UNPKG

appium-remote-debugger

Version:
191 lines 8.37 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const logger_1 = __importDefault(require("../logger")); const lodash_1 = __importDefault(require("lodash")); const support_1 = require("@appium/support"); const events_1 = __importDefault(require("events")); class RpcMessageHandler extends events_1.default { constructor(isTargetBased = false) { super(); this.isTargetBased = isTargetBased; } get isTargetBased() { return this._isTargetBased; } set isTargetBased(isTargetBased) { this._isTargetBased = !!isTargetBased; } async handleMessage(plist) { const selector = plist.__selector; if (!selector) { logger_1.default.debug('Got an invalid plist'); return; } const argument = plist.__argument; switch (selector) { case '_rpc_reportSetup:': this.emit('_rpc_reportSetup:', null, argument.WIRSimulatorNameKey, argument.WIRSimulatorBuildKey, argument.WIRSimulatorProductVersionKey); break; case '_rpc_reportConnectedApplicationList:': this.emit('_rpc_reportConnectedApplicationList:', null, argument.WIRApplicationDictionaryKey); break; case '_rpc_applicationSentListing:': this.emit('_rpc_forwardGetListing:', null, argument.WIRApplicationIdentifierKey, argument.WIRListingKey); break; case '_rpc_applicationConnected:': this.emit('_rpc_applicationConnected:', null, argument); break; case '_rpc_applicationDisconnected:': this.emit('_rpc_applicationDisconnected:', null, argument); break; case '_rpc_applicationUpdated:': this.emit('_rpc_applicationUpdated:', null, argument); break; case '_rpc_reportConnectedDriverList:': this.emit('_rpc_reportConnectedDriverList:', null, argument); break; case '_rpc_reportCurrentState:': this.emit('_rpc_reportCurrentState:', null, argument); break; case '_rpc_applicationSentData:': await this.handleDataMessage(plist); break; default: logger_1.default.debug(`Debugger got a message for '${selector}' and have no ` + `handler, doing nothing.`); } } parseDataKey(plist) { try { return JSON.parse(plist.__argument.WIRMessageDataKey.toString('utf8')); } catch (err) { logger_1.default.error(`Unparseable message data: ${lodash_1.default.truncate(JSON.stringify(plist), { length: 100 })}`); throw new Error(`Unable to parse message data: ${err.message}`); } } async dispatchDataMessage(msgId, method, params, result, error) { if (!lodash_1.default.isEmpty(msgId)) { logger_1.default.debug(`Handling message (id: '${msgId}')`); } if (msgId) { if (this.listenerCount(msgId)) { if (lodash_1.default.has(result?.result, 'value')) { result = result.result.value; } this.emit(msgId, error, result); } else { logger_1.default.error(`Web Inspector returned data for message '${msgId}' ` + `but we were not waiting for that message! ` + `result: '${JSON.stringify(result)}'; ` + `error: '${JSON.stringify(error)}'`); } return; } let eventNames = [method]; let args = [params]; // some events have different names, or the arguments are mapped from the // parameters received switch (method) { case 'Page.frameStoppedLoading': eventNames.push('Page.frameNavigated'); case 'Page.frameNavigated': // eslint-disable-line no-fallthrough args = [`'${method}' event`]; break; case 'Timeline.eventRecorded': args = [params || params.record]; break; case 'Console.messageAdded': args = [params.message]; break; case 'Runtime.executionContextCreated': args = [params.context]; break; default: // pass break; } if (lodash_1.default.startsWith(method, 'Network.')) { // aggregate Network events, and add original method name to the arguments eventNames.push('NetworkEvent'); args.push(method); } if (lodash_1.default.startsWith(method, 'Console.')) { // aggregate Network events, and add original method name to the arguments eventNames.push('ConsoleEvent'); args.push(method); } for (const name of eventNames) { this.emit(name, error, ...args); } } async handleDataMessage(plist) { const dataKey = this.parseDataKey(plist); let msgId = (dataKey.id || '').toString(); let result = dataKey.result; let method = dataKey.method; let params; if (method === 'Target.targetCreated') { // this is in response to a `_rpc_forwardSocketSetup:` call // targetInfo: { targetId: 'page-1', type: 'page' } const app = plist.__argument.WIRApplicationIdentifierKey; const targetInfo = dataKey.params.targetInfo; this.emit('Target.targetCreated', null, app, targetInfo); return; } else if (method === 'Target.didCommitProvisionalTarget') { const app = plist.__argument.WIRApplicationIdentifierKey; const oldTargetId = dataKey.params.oldTargetId; const newTargetId = dataKey.params.newTargetId; this.emit('Target.didCommitProvisionalTarget', null, app, oldTargetId, newTargetId); return; } else if (method === 'Target.targetDestroyed') { const app = plist.__argument.WIRApplicationIdentifierKey; const targetInfo = dataKey.params.targetInfo || { targetId: dataKey.params.targetId }; this.emit('Target.targetDestroyed', null, app, targetInfo); return; } if (!dataKey.error && this.isTargetBased) { if (dataKey.method !== 'Target.dispatchMessageFromTarget') { // this sort of message, at this point, is just an acknowledgement // that the original message was received return; } // at this point, we have a Target-based message wrapping a protocol message let message; try { message = JSON.parse(dataKey.params.message); msgId = message.id; method = message.method; result = message.result || message; params = result.params; } catch (err) { // if this happens then some aspect of the protocol is missing to us // so print the entire message to get visibiity into what is going on logger_1.default.error(`Unexpected message format from Web Inspector:`); logger_1.default.warn(support_1.util.jsonStringify(plist, null)); throw err; } } else { params = dataKey.params; } // we can get an error, or we can get a response that is an error let error = dataKey.error || null; if (result?.wasThrown) { const message = (result?.result?.value || result?.result?.description) ? (result?.result?.value || result?.result?.description) : 'Error occurred in handling data message'; error = new Error(message); } await this.dispatchDataMessage(msgId, method, params, result, error); } } exports.default = RpcMessageHandler; //# sourceMappingURL=rpc-message-handler.js.map