MessageHandlerFrameChild.sys.mjs (3961B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 const lazy = {}; 6 7 ChromeUtils.defineESModuleGetters(lazy, { 8 isBrowsingContextCompatible: 9 "chrome://remote/content/shared/messagehandler/transports/BrowsingContextUtils.sys.mjs", 10 MessageHandlerRegistry: 11 "chrome://remote/content/shared/messagehandler/MessageHandlerRegistry.sys.mjs", 12 WindowGlobalMessageHandler: 13 "chrome://remote/content/shared/messagehandler/WindowGlobalMessageHandler.sys.mjs", 14 }); 15 16 /** 17 * Map from MessageHandlerRegistry to MessageHandlerFrameChild actor. This will 18 * allow a WindowGlobalMessageHandler to find the JSWindowActorChild instance to 19 * use to send commands. 20 */ 21 const registryToActor = new WeakMap(); 22 23 /** 24 * Retrieve the MessageHandlerFrameChild which is linked to the provided 25 * WindowGlobalMessageHandler instance. 26 * 27 * @param {WindowGlobalMessageHandler} messageHandler 28 * The WindowGlobalMessageHandler for which to get the JSWindowActor. 29 * @returns {MessageHandlerFrameChild} 30 * The corresponding MessageHandlerFrameChild instance. 31 */ 32 export function getMessageHandlerFrameChildActor(messageHandler) { 33 return registryToActor.get(messageHandler.registry); 34 } 35 36 /** 37 * Child actor for the MessageHandlerFrame JSWindowActor. The 38 * MessageHandlerFrame actor is used by RootTransport to communicate between 39 * ROOT MessageHandlers and WINDOW_GLOBAL MessageHandlers. 40 */ 41 export class MessageHandlerFrameChild extends JSWindowActorChild { 42 actorCreated() { 43 this.type = lazy.WindowGlobalMessageHandler.type; 44 this.context = this.manager.browsingContext; 45 46 this._registry = new lazy.MessageHandlerRegistry(this.type, this.context); 47 registryToActor.set(this._registry, this); 48 49 this._onRegistryEvent = this._onRegistryEvent.bind(this); 50 51 // MessageHandlerFrameChild is responsible for forwarding events from 52 // WindowGlobalMessageHandler to the parent process. 53 // Such events are re-emitted on the MessageHandlerRegistry to avoid 54 // setting up listeners on individual MessageHandler instances. 55 this._registry.on("message-handler-registry-event", this._onRegistryEvent); 56 } 57 58 handleEvent({ persisted, type }) { 59 if (type == "DOMWindowCreated" || (type == "pageshow" && persisted)) { 60 // When the window is created or is retrieved from BFCache, instantiate 61 // a MessageHandler for all sessions which might need it. 62 if (lazy.isBrowsingContextCompatible(this.manager.browsingContext)) { 63 this._registry.createAllMessageHandlers(); 64 } 65 } else if (type == "pagehide" && persisted) { 66 // When the page is moved to BFCache, all the currently created message 67 // handlers should be destroyed. 68 this._registry.destroy(); 69 } 70 } 71 72 async receiveMessage(message) { 73 if (message.name === "MessageHandlerFrameParent:sendCommand") { 74 const { sessionId, command } = message.data; 75 const messageHandler = 76 this._registry.getOrCreateMessageHandler(sessionId); 77 try { 78 return await messageHandler.handleCommand(command); 79 } catch (e) { 80 if (e?.isRemoteError) { 81 return { 82 error: e.toJSON(), 83 isMessageHandlerError: e.isMessageHandlerError, 84 }; 85 } 86 throw e; 87 } 88 } else if (message.name === "MessageHandlerFrameParent:sendPing") { 89 return true; 90 } 91 92 return null; 93 } 94 95 sendCommand(command, sessionId) { 96 return this.sendQuery("MessageHandlerFrameChild:sendCommand", { 97 command, 98 sessionId, 99 }); 100 } 101 102 _onRegistryEvent(eventName, wrappedEvent) { 103 this.sendAsyncMessage( 104 "MessageHandlerFrameChild:messageHandlerEvent", 105 wrappedEvent 106 ); 107 } 108 109 didDestroy() { 110 this._registry.off("message-handler-registry-event", this._onRegistryEvent); 111 this._registry.destroy(); 112 } 113 }