summaryrefslogtreecommitdiffstats
path: root/dom/browser-element/BrowserElementParent.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'dom/browser-element/BrowserElementParent.jsm')
-rw-r--r--dom/browser-element/BrowserElementParent.jsm276
1 files changed, 0 insertions, 276 deletions
diff --git a/dom/browser-element/BrowserElementParent.jsm b/dom/browser-element/BrowserElementParent.jsm
deleted file mode 100644
index ec342dace2..0000000000
--- a/dom/browser-element/BrowserElementParent.jsm
+++ /dev/null
@@ -1,276 +0,0 @@
-/* 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/. */
-
-"use strict";
-
-/* BrowserElementParent injects script to listen for certain events in the
- * child. We then listen to messages from the child script and take
- * appropriate action here in the parent.
- */
-
-const { BrowserElementPromptService } = ChromeUtils.import(
- "resource://gre/modules/BrowserElementPromptService.jsm"
-);
-
-function debug(msg) {
- // dump("BrowserElementParent - " + msg + "\n");
-}
-
-function handleWindowEvent(e) {
- if (this._browserElementParents) {
- let beps = ChromeUtils.nondeterministicGetWeakMapKeys(
- this._browserElementParents
- );
- beps.forEach(bep => bep._handleOwnerEvent(e));
- }
-}
-
-function BrowserElementParent() {
- debug("Creating new BrowserElementParent object");
-}
-
-BrowserElementParent.prototype = {
- classDescription: "BrowserElementAPI implementation",
- classID: Components.ID("{9f171ac4-0939-4ef8-b360-3408aedc3060}"),
- contractID: "@mozilla.org/dom/browser-element-api;1",
- QueryInterface: ChromeUtils.generateQI([
- "nsIBrowserElementAPI",
- "nsISupportsWeakReference",
- ]),
-
- setFrameLoader(frameLoader) {
- debug("Setting frameLoader");
- this._frameLoader = frameLoader;
- this._frameElement = frameLoader.ownerElement;
- if (!this._frameElement) {
- debug("No frame element?");
- return;
- }
- // Listen to visibilitychange on the iframe's owner window, and forward
- // changes down to the child. We want to do this while registering as few
- // visibilitychange listeners on _window as possible, because such a listener
- // may live longer than this BrowserElementParent object.
- //
- // To accomplish this, we register just one listener on the window, and have
- // it reference a WeakMap whose keys are all the BrowserElementParent objects
- // on the window. Then when the listener fires, we iterate over the
- // WeakMap's keys (which we can do, because we're chrome) to notify the
- // BrowserElementParents.
- if (!this._window._browserElementParents) {
- this._window._browserElementParents = new WeakMap();
- let handler = handleWindowEvent.bind(this._window);
- let windowEvents = ["visibilitychange"];
- for (let event of windowEvents) {
- Services.els.addSystemEventListener(
- this._window,
- event,
- handler,
- /* useCapture = */ true
- );
- }
- }
-
- this._window._browserElementParents.set(this, null);
-
- // Insert ourself into the prompt service.
- BrowserElementPromptService.mapFrameToBrowserElementParent(
- this._frameElement,
- this
- );
- this._setupMessageListener();
- },
-
- destroyFrameScripts() {
- debug("Destroying frame scripts");
- this._mm.sendAsyncMessage("browser-element-api:destroy");
- },
-
- _setupMessageListener() {
- this._mm = this._frameLoader.messageManager;
- this._mm.addMessageListener("browser-element-api:call", this);
- },
-
- receiveMessage(aMsg) {
- if (!this._isAlive()) {
- return undefined;
- }
-
- // Messages we receive are handed to functions which take a (data) argument,
- // where |data| is the message manager's data object.
- // We use a single message and dispatch to various function based
- // on data.msg_name
- let mmCalls = {
- hello: this._recvHello,
- };
-
- let mmSecuritySensitiveCalls = {
- showmodalprompt: this._handleShowModalPrompt,
- };
-
- if (aMsg.data.msg_name in mmCalls) {
- return mmCalls[aMsg.data.msg_name].apply(this, arguments);
- } else if (aMsg.data.msg_name in mmSecuritySensitiveCalls) {
- return mmSecuritySensitiveCalls[aMsg.data.msg_name].apply(
- this,
- arguments
- );
- }
- return undefined;
- },
-
- _removeMessageListener() {
- this._mm.removeMessageListener("browser-element-api:call", this);
- },
-
- /**
- * You shouldn't touch this._frameElement or this._window if _isAlive is
- * false. (You'll likely get an exception if you do.)
- */
- _isAlive() {
- return (
- !Cu.isDeadWrapper(this._frameElement) &&
- !Cu.isDeadWrapper(this._frameElement.ownerDocument) &&
- !Cu.isDeadWrapper(this._frameElement.ownerGlobal)
- );
- },
-
- get _window() {
- return this._frameElement.ownerGlobal;
- },
-
- _sendAsyncMsg(msg, data) {
- try {
- if (!data) {
- data = {};
- }
-
- data.msg_name = msg;
- this._mm.sendAsyncMessage("browser-element-api:call", data);
- } catch (e) {
- return false;
- }
- return true;
- },
-
- _recvHello() {
- debug("recvHello");
-
- // Inform our child if our owner element's document is invisible. Note
- // that we must do so here, rather than in the BrowserElementParent
- // constructor, because the BrowserElementChild may not be initialized when
- // we run our constructor.
- if (this._window.document.hidden) {
- this._ownerVisibilityChange();
- }
- },
-
- /**
- * Fire either a vanilla or a custom event, depending on the contents of
- * |data|.
- */
- _fireEventFromMsg(data) {
- let detail = data.json;
- let name = detail.msg_name;
-
- // For events that send a "_payload_" property, we just want to transmit
- // this in the event.
- if ("_payload_" in detail) {
- detail = detail._payload_;
- }
-
- debug("fireEventFromMsg: " + name + ", " + JSON.stringify(detail));
- let evt = this._createEvent(name, detail, /* cancelable = */ false);
- this._frameElement.dispatchEvent(evt);
- },
-
- _handleShowModalPrompt(data) {
- // Fire a showmodalprmopt event on the iframe. When this method is called,
- // the child is spinning in a nested event loop waiting for an
- // unblock-modal-prompt message.
- //
- // If the embedder calls preventDefault() on the showmodalprompt event,
- // we'll block the child until event.detail.unblock() is called.
- //
- // Otherwise, if preventDefault() is not called, we'll send the
- // unblock-modal-prompt message to the child as soon as the event is done
- // dispatching.
-
- let detail = data.json;
- debug("handleShowPrompt " + JSON.stringify(detail));
-
- // Strip off the windowID property from the object we send along in the
- // event.
- let windowID = detail.windowID;
- delete detail.windowID;
- debug("Event will have detail: " + JSON.stringify(detail));
- let evt = this._createEvent(
- "showmodalprompt",
- detail,
- /* cancelable = */ true
- );
-
- let self = this;
- let unblockMsgSent = false;
- function sendUnblockMsg() {
- if (unblockMsgSent) {
- return;
- }
- unblockMsgSent = true;
-
- // We don't need to sanitize evt.detail.returnValue (e.g. converting the
- // return value of confirm() to a boolean); Gecko does that for us.
-
- let data = { windowID, returnValue: evt.detail.returnValue };
- self._sendAsyncMsg("unblock-modal-prompt", data);
- }
-
- Cu.exportFunction(sendUnblockMsg, evt.detail, { defineAs: "unblock" });
-
- this._frameElement.dispatchEvent(evt);
-
- if (!evt.defaultPrevented) {
- // Unblock the inner frame immediately. Otherwise we'll unblock upon
- // evt.detail.unblock().
- sendUnblockMsg();
- }
- },
-
- _createEvent(evtName, detail, cancelable) {
- // This will have to change if we ever want to send a CustomEvent with null
- // detail. For now, it's OK.
- if (detail !== undefined && detail !== null) {
- detail = Cu.cloneInto(detail, this._window);
- return new this._window.CustomEvent("mozbrowser" + evtName, {
- bubbles: true,
- cancelable,
- detail,
- });
- }
-
- return new this._window.Event("mozbrowser" + evtName, {
- bubbles: true,
- cancelable,
- });
- },
-
- _handleOwnerEvent(evt) {
- switch (evt.type) {
- case "visibilitychange":
- this._ownerVisibilityChange();
- break;
- }
- },
-
- /**
- * Called when the visibility of the window which owns this iframe changes.
- */
- _ownerVisibilityChange() {
- let bc = this._frameLoader?.browsingContext;
- if (bc) {
- bc.isActive = !this._window.document.hidden;
- }
- },
-};
-
-var EXPORTED_SYMBOLS = ["BrowserElementParent"];