/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"; const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { error: "chrome://remote/content/shared/messagehandler/Errors.sys.mjs", RootMessageHandlerRegistry: "chrome://remote/content/shared/messagehandler/RootMessageHandlerRegistry.sys.mjs", WindowGlobalMessageHandler: "chrome://remote/content/shared/messagehandler/WindowGlobalMessageHandler.sys.mjs", }); XPCOMUtils.defineLazyGetter(lazy, "WebDriverError", () => { return ChromeUtils.importESModule( "chrome://remote/content/shared/webdriver/Errors.sys.mjs" ).error.WebDriverError; }); /** * Parent actor for the MessageHandlerFrame JSWindowActor. The * MessageHandlerFrame actor is used by RootTransport to communicate between * ROOT MessageHandlers and WINDOW_GLOBAL MessageHandlers. */ export class MessageHandlerFrameParent extends JSWindowActorParent { async receiveMessage(message) { switch (message.name) { case "MessageHandlerFrameChild:sendCommand": { return this.#handleSendCommandMessage(message.data); } case "MessageHandlerFrameChild:messageHandlerEvent": { return this.#handleMessageHandlerEventMessage(message.data); } default: throw new Error("Unsupported message:" + message.name); } } /** * Send a command to the corresponding MessageHandlerFrameChild actor via a * JSWindowActor query. * * @param {Command} command * The command to forward. See type definition in MessageHandler.js * @param {string} sessionId * ID of the session that sent the command. * @returns {Promise} * Promise that will resolve with the result of query sent to the * MessageHandlerFrameChild actor. */ async sendCommand(command, sessionId) { const result = await this.sendQuery( "MessageHandlerFrameParent:sendCommand", { command, sessionId, } ); if (result?.error) { if (result.isMessageHandlerError) { throw lazy.error.MessageHandlerError.fromJSON(result.error); } // TODO: Do not assume WebDriver is the session protocol, see Bug 1779026. throw lazy.WebDriverError.fromJSON(result.error); } return result; } async #handleMessageHandlerEventMessage(messageData) { const { name, contextInfo, data, sessionId } = messageData; const [moduleName] = name.split("."); // Re-emit the event on the RootMessageHandler. const messageHandler = lazy.RootMessageHandlerRegistry.getExistingMessageHandler(sessionId); // TODO: getModuleInstance expects a CommandDestination in theory, // but only uses the MessageHandler type in practice, see Bug 1776389. const module = messageHandler.moduleCache.getModuleInstance(moduleName, { type: lazy.WindowGlobalMessageHandler.type, }); let eventPayload = data; // Modify an event payload if there is a special method in the targeted module. // If present it can be found in windowglobal-in-root module. if (module?.interceptEvent) { eventPayload = await module.interceptEvent(name, data); // Make sure that an event payload is returned. if (!eventPayload) { throw new Error( `${moduleName}.interceptEvent doesn't return the event payload` ); } } messageHandler.emitEvent(name, eventPayload, contextInfo); } async #handleSendCommandMessage(messageData) { const { sessionId, command } = messageData; const messageHandler = lazy.RootMessageHandlerRegistry.getExistingMessageHandler(sessionId); try { return await messageHandler.handleCommand(command); } catch (e) { if (e?.isRemoteError) { return { error: e.toJSON(), isMessageHandlerError: e.isMessageHandlerError, }; } throw e; } } }