UNPKG

appium-remote-debugger

Version:
267 lines 11.8 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.RPC_RESPONSE_TIMEOUT_MS = exports.REMOTE_DEBUGGER_PORT = exports.RemoteDebugger = void 0; const events_1 = require("events"); const logger_1 = __importDefault(require("./logger")); const rpc_1 = require("./rpc"); const utils_1 = require("./utils"); const mixins_1 = require("./mixins"); const lodash_1 = __importDefault(require("lodash")); const bluebird_1 = __importDefault(require("bluebird")); const path_1 = __importDefault(require("path")); const async_lock_1 = __importDefault(require("async-lock")); const REMOTE_DEBUGGER_PORT = 27753; exports.REMOTE_DEBUGGER_PORT = REMOTE_DEBUGGER_PORT; const SAFARI_BUNDLE_ID = 'com.apple.mobilesafari'; /* How many milliseconds to wait for webkit to return a response before timing out */ const RPC_RESPONSE_TIMEOUT_MS = 5000; exports.RPC_RESPONSE_TIMEOUT_MS = RPC_RESPONSE_TIMEOUT_MS; const PAGE_READY_TIMEOUT = 5000; const GARBAGE_COLLECT_TIMEOUT = 5000; class RemoteDebugger extends events_1.EventEmitter { /* * The constructor takes an opts hash with the following properties: * - bundleId - id of the app being connected to * - additionalBundleIds - array of possible bundle ids that the inspector * could return * - platformVersion - version of iOS * - useNewSafari - for web inspector, whether this is a new Safari instance * - pageLoadMs - the time, in ms, that should be waited for page loading * - host - the remote debugger's host address * - port - the remote debugger port through which to communicate * - logAllCommunication - log plists sent and received from Web Inspector * - logAllCommunicationHexDump - log communication from Web Inspector as hex dump * - socketChunkSize - size, in bytes, of chunks of data sent to Web Inspector (real device only) * - webInspectorMaxFrameLength - The maximum size in bytes of a single data frame * in the device communication protocol */ constructor(opts = {}) { super(); // eslint-disable-next-line @typescript-eslint/no-var-requires logger_1.default.info(`Remote Debugger version ${require(path_1.default.resolve((0, utils_1.getModuleRoot)(), 'package.json')).version}`); const { bundleId, additionalBundleIds = [], platformVersion, isSafari = true, includeSafari = false, useNewSafari = false, pageLoadMs, host, port = REMOTE_DEBUGGER_PORT, socketPath, pageReadyTimeout = PAGE_READY_TIMEOUT, remoteDebugProxy, garbageCollectOnExecute = false, logFullResponse = false, logAllCommunication = false, logAllCommunicationHexDump = false, webInspectorMaxFrameLength, socketChunkSize, fullPageInitialization, } = opts; this.bundleId = bundleId; this.additionalBundleIds = additionalBundleIds; this.platformVersion = platformVersion; this.isSafari = isSafari; this.includeSafari = includeSafari; this.useNewSafari = useNewSafari; this.pageLoadMs = pageLoadMs; logger_1.default.debug(`useNewSafari --> ${this.useNewSafari}`); this.garbageCollectOnExecute = garbageCollectOnExecute; this.host = host; this.port = port; this.socketPath = socketPath; this.remoteDebugProxy = remoteDebugProxy; this.pageReadyTimeout = pageReadyTimeout; this.logAllCommunication = lodash_1.default.isNil(logAllCommunication) ? !!logFullResponse : !!logAllCommunication; this.logAllCommunicationHexDump = logAllCommunicationHexDump; this.socketChunkSize = socketChunkSize; if (lodash_1.default.isInteger(webInspectorMaxFrameLength)) { this.webInspectorMaxFrameLength = webInspectorMaxFrameLength; } this.fullPageInitialization = fullPageInitialization; this._lock = new async_lock_1.default(); } setup() { // app handling configuration this.appDict = {}; this.appIdKey = null; this.pageIdKey = null; this.pageLoading = false; this._navigatingToPage = false; this.allowNavigationWithoutReload = false; this.rpcClient = null; this._clientEventListeners = {}; } teardown() { logger_1.default.debug('Cleaning up listeners'); this.appDict = {}; this.appIdKey = null; this.pageIdKey = null; this.pageLoading = false; this.rpcClient = null; this.removeAllListeners(RemoteDebugger.EVENT_PAGE_CHANGE); this.removeAllListeners(RemoteDebugger.EVENT_DISCONNECT); } initRpcClient() { this.rpcClient = new rpc_1.RpcClientSimulator({ bundleId: this.bundleId, platformVersion: this.platformVersion, isSafari: this.isSafari, host: this.host, port: this.port, socketPath: this.socketPath, messageProxy: this.remoteDebugProxy, logAllCommunication: this.logAllCommunication, logAllCommunicationHexDump: this.logAllCommunicationHexDump, fullPageInitialization: this.fullPageInitialization, webInspectorMaxFrameLength: this.webInspectorMaxFrameLength, }); } get isConnected() { return !!this.rpcClient?.isConnected; } async launchSafari() { if (!this.rpcClient) { throw new Error(`rpcClient is undefined. Has 'initRpcClient' been called before?`); } await this.rpcClient.send('launchApplication', { bundleId: SAFARI_BUNDLE_ID }); } async startTimeline(fn) { if (!this.rpcClient) { throw new Error(`rpcClient is undefined. Has 'initRpcClient' been called before?`); } logger_1.default.debug('Starting to record the timeline'); this.rpcClient.on('Timeline.eventRecorded', fn); return await this.rpcClient.send('Timeline.start', { appIdKey: this.appIdKey, pageIdKey: this.pageIdKey, }); } async stopTimeline() { if (!this.rpcClient) { throw new Error(`rpcClient is undefined. Has 'initRpcClient' been called before?`); } logger_1.default.debug('Stopping to record the timeline'); await this.rpcClient.send('Timeline.stop', { appIdKey: this.appIdKey, pageIdKey: this.pageIdKey, }); } /* * Keep track of the client event listeners so they can be removed */ addClientEventListener(eventName, listener) { if (!this.rpcClient) { throw new Error(`rpcClient is undefined. Has 'initRpcClient' been called before?`); } this._clientEventListeners[eventName] = this._clientEventListeners[eventName] || []; this._clientEventListeners[eventName].push(listener); this.rpcClient.on(eventName, listener); } removeClientEventListener(eventName) { if (!this.rpcClient) { throw new Error(`rpcClient is undefined. Has 'initRpcClient' been called before?`); } for (const listener of (this._clientEventListeners[eventName] || [])) { this.rpcClient.off(eventName, listener); } } startConsole(listener) { logger_1.default.debug('Starting to listen for JavaScript console'); this.addClientEventListener('Console.messageAdded', listener); this.addClientEventListener('Console.messageRepeatCountUpdated', listener); } stopConsole() { logger_1.default.debug('Stopping to listen for JavaScript console'); this.removeClientEventListener('Console.messageAdded'); this.removeClientEventListener('Console.messageRepeatCountUpdated'); } startNetwork(listener) { logger_1.default.debug('Starting to listen for network events'); this.addClientEventListener('NetworkEvent', listener); } stopNetwork() { logger_1.default.debug('Stopping to listen for network events'); this.removeClientEventListener('NetworkEvent'); } set allowNavigationWithoutReload(allow) { this._allowNavigationWithoutReload = allow; } get allowNavigationWithoutReload() { return this._allowNavigationWithoutReload; } // Potentially this does not work for mobile safari async overrideUserAgent(value) { logger_1.default.debug('Setting overrideUserAgent'); if (!this.rpcClient) { throw new Error(`rpcClient is undefined. Has 'initRpcClient' been called before?`); } return await this.rpcClient.send('Page.overrideUserAgent', { appIdKey: this.appIdKey, pageIdKey: this.pageIdKey, value }); } async getCookies() { logger_1.default.debug('Getting cookies'); if (!this.rpcClient) { throw new Error(`rpcClient is undefined. Has 'initRpcClient' been called before?`); } return await this.rpcClient.send('Page.getCookies', { appIdKey: this.appIdKey, pageIdKey: this.pageIdKey }); } async setCookie(cookie) { logger_1.default.debug('Setting cookie'); if (!this.rpcClient) { throw new Error(`rpcClient is undefined. Has 'initRpcClient' been called before?`); } return await this.rpcClient.send('Page.setCookie', { appIdKey: this.appIdKey, pageIdKey: this.pageIdKey, cookie }); } async deleteCookie(cookieName, url) { logger_1.default.debug(`Deleting cookie '${cookieName}' on '${url}'`); if (!this.rpcClient) { throw new Error(`rpcClient is undefined. Has 'initRpcClient' been called before?`); } return await this.rpcClient.send('Page.deleteCookie', { appIdKey: this.appIdKey, pageIdKey: this.pageIdKey, cookieName, url, }); } async garbageCollect(timeoutMs = GARBAGE_COLLECT_TIMEOUT) { logger_1.default.debug(`Garbage collecting with ${timeoutMs}ms timeout`); if (!this.rpcClient) { throw new Error(`rpcClient is undefined. Has 'initRpcClient' been called before?`); } try { (0, utils_1.checkParams)({ appIdKey: this.appIdKey, pageIdKey: this.pageIdKey }); } catch (err) { logger_1.default.debug(`Unable to collect garbage at this time`); return; } await bluebird_1.default.resolve(this.rpcClient.send('Heap.gc', { appIdKey: this.appIdKey, pageIdKey: this.pageIdKey, })).timeout(timeoutMs) .then(function gcSuccess() { logger_1.default.debug(`Garbage collection successful`); }).catch(function gcError(err) { if (err instanceof bluebird_1.default.TimeoutError) { logger_1.default.debug(`Garbage collection timed out after ${timeoutMs}ms`); } else { logger_1.default.debug(`Unable to collect garbage: ${err.message}`); } }); } async useAppDictLock(fn) { return await this._lock.acquire('appDict', fn); } get skippedApps() { return this._skippedApps || []; } } exports.RemoteDebugger = RemoteDebugger; for (const [name, fn] of lodash_1.default.toPairs(mixins_1.mixins)) { RemoteDebugger.prototype[name] = fn; } for (const [name, event] of lodash_1.default.toPairs(mixins_1.events)) { RemoteDebugger[name] = event; } exports.default = RemoteDebugger; //# sourceMappingURL=remote-debugger.js.map