UNPKG

appium-xcuitest-driver

Version:

Appium driver for iOS using XCUITest for backend

116 lines 5.05 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AppTerminationClient = void 0; const lodash_1 = __importDefault(require("lodash")); const appium_ios_device_1 = require("appium-ios-device"); const utils_1 = require("../utils"); const installation_proxy_client_1 = require("./installation-proxy-client"); const remotexpc_utils_1 = require("./remotexpc-utils"); class AppTerminationClient { udid; platformVersion; devicectl; log; constructor(udid, platformVersion, devicectl, log) { this.udid = udid; this.platformVersion = platformVersion; this.devicectl = devicectl; this.log = log; } async terminate(bundleId) { let result; if ((0, utils_1.isIos18OrNewerPlatform)(this.platformVersion)) { try { result = await this.terminateRemoteXPC(bundleId); } catch (err) { this.log.warn(`Failed to terminate '${bundleId}' via RemoteXPC: ${err.message}`); result = await this.terminateLegacy(bundleId); } } else { result = await this.terminateLegacy(bundleId); } if (result.terminated) { this.log.debug(`Killed process for '${bundleId}' app with PID ${result.pid}`); return true; } switch (result.reason) { case 'not_running': this.log.info(`The process of '${bundleId}' app was not running`); break; case 'error': this.log.warn(`Failed to kill '${bundleId}'. Original error: ${result.detail ?? 'unknown'}`); break; } return false; } async terminateRemoteXPC(bundleId) { const Services = await (0, remotexpc_utils_1.getRemoteXPCServices)(); const dvt = await Services.startDVTService(this.udid); const remoteXPCConnection = dvt.remoteXPC; try { const pid = await dvt.processControl.getPidForBundleIdentifier(bundleId); if (!pid) { return { terminated: false, reason: 'not_running' }; } await dvt.processControl.kill(pid); return { terminated: true, pid }; } finally { await remoteXPCConnection.close(); } } async terminateLegacy(bundleId) { let instrumentService; let installProxyClient; try { installProxyClient = await installation_proxy_client_1.InstallationProxyClient.create(this.udid, false); const apps = await installProxyClient.listApplications({ returnAttributes: ['CFBundleIdentifier', 'CFBundleExecutable'], }); if (!apps[bundleId]) { return { terminated: false, reason: 'not_running' }; } const executableName = apps[bundleId].CFBundleExecutable; this.log.debug(`The executable name for the bundle id '${bundleId}' was '${executableName}'`); if ((0, utils_1.isIos17OrNewerPlatform)(this.platformVersion)) { this.log.debug(`Calling devicectl to kill the process`); const pids = (await this.devicectl.listProcesses()) .filter(({ executable }) => executable.endsWith(`/${executableName}`)) .map(({ processIdentifier }) => processIdentifier); if (lodash_1.default.isEmpty(pids)) { return { terminated: false, reason: 'not_running' }; } await this.devicectl.sendSignalToProcess(pids[0], 2); return { terminated: true, pid: pids[0] }; } // iOS < 17: use instrument service instrumentService = await appium_ios_device_1.services.startInstrumentService(this.udid); const processes = await instrumentService.callChannel(appium_ios_device_1.INSTRUMENT_CHANNEL.DEVICE_INFO, 'runningProcesses'); const process = processes.selector.find((proc) => proc.name === executableName); if (!process) { return { terminated: false, reason: 'not_running' }; } await instrumentService.callChannel(appium_ios_device_1.INSTRUMENT_CHANNEL.PROCESS_CONTROL, 'killPid:', `${process.pid}`); return { terminated: true, pid: process.pid }; } catch (err) { const detail = err.stderr ?? err.message; return { terminated: false, reason: 'error', detail: String(detail) }; } finally { if (installProxyClient) { await installProxyClient.close(); } if (instrumentService) { instrumentService.close(); } } } } exports.AppTerminationClient = AppTerminationClient; //# sourceMappingURL=app-termination-client.js.map