MarionetteEventsParent.sys.mjs (3279B)
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 EventEmitter: "resource://gre/modules/EventEmitter.sys.mjs", 9 10 Log: "chrome://remote/content/shared/Log.sys.mjs", 11 }); 12 13 ChromeUtils.defineLazyGetter(lazy, "logger", () => 14 lazy.Log.get(lazy.Log.TYPES.MARIONETTE) 15 ); 16 17 // Singleton to allow forwarding events to registered listeners. 18 export const EventDispatcher = { 19 init() { 20 lazy.EventEmitter.decorate(this); 21 }, 22 }; 23 24 EventDispatcher.init(); 25 26 export class MarionetteEventsParent extends JSWindowActorParent { 27 async receiveMessage(msg) { 28 const { name, data } = msg; 29 30 let rv; 31 switch (name) { 32 case "MarionetteEventsChild:PageLoadEvent": 33 EventDispatcher.emit("page-load", data); 34 break; 35 } 36 37 return rv; 38 } 39 } 40 41 // Flag to check if the MarionetteEvents actors have already been registered. 42 let eventsActorRegistered = false; 43 44 /** 45 * Register Events actors to listen for page load events via EventDispatcher. 46 */ 47 function registerEventsActor() { 48 if (eventsActorRegistered) { 49 return; 50 } 51 52 try { 53 // Register the JSWindowActor pair for events as used by Marionette 54 ChromeUtils.registerWindowActor("MarionetteEvents", { 55 kind: "JSWindowActor", 56 parent: { 57 esModuleURI: 58 "chrome://remote/content/marionette/actors/MarionetteEventsParent.sys.mjs", 59 }, 60 child: { 61 esModuleURI: 62 "chrome://remote/content/marionette/actors/MarionetteEventsChild.sys.mjs", 63 events: { 64 beforeunload: { capture: true }, 65 DOMContentLoaded: { mozSystemGroup: true }, 66 hashchange: { mozSystemGroup: true }, 67 pagehide: { mozSystemGroup: true }, 68 pageshow: { mozSystemGroup: true }, 69 // popstate doesn't bubble, as such use capturing phase 70 popstate: { capture: true, mozSystemGroup: true }, 71 72 click: {}, 73 dblclick: {}, 74 unload: { capture: true, createActor: false }, 75 }, 76 }, 77 78 allFrames: true, 79 includeChrome: true, 80 }); 81 82 eventsActorRegistered = true; 83 } catch (e) { 84 if (e.name === "NotSupportedError") { 85 lazy.logger.warn(`MarionetteEvents actor is already registered!`); 86 } else { 87 throw e; 88 } 89 } 90 } 91 92 /** 93 * Enable MarionetteEvents actors to start forwarding page load events from the 94 * child actor to the parent actor. Register the MarionetteEvents actor if necessary. 95 */ 96 export function enableEventsActor() { 97 // sharedData is replicated across processes and will be checked by 98 // MarionetteEventsChild before forward events to the parent actor. 99 Services.ppmm.sharedData.set("MARIONETTE_EVENTS_ENABLED", true); 100 // Request to immediately flush the data to the content processes to avoid races. 101 Services.ppmm.sharedData.flush(); 102 103 registerEventsActor(); 104 } 105 106 /** 107 * Disable MarionetteEvents actors to stop forwarding page load events from the 108 * child actor to the parent actor. 109 */ 110 export function disableEventsActor() { 111 Services.ppmm.sharedData.set("MARIONETTE_EVENTS_ENABLED", false); 112 Services.ppmm.sharedData.flush(); 113 }