summaryrefslogtreecommitdiffstats
path: root/toolkit/components/webextensions/LegacyExtensionsUtils.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/webextensions/LegacyExtensionsUtils.jsm')
-rw-r--r--toolkit/components/webextensions/LegacyExtensionsUtils.jsm250
1 files changed, 0 insertions, 250 deletions
diff --git a/toolkit/components/webextensions/LegacyExtensionsUtils.jsm b/toolkit/components/webextensions/LegacyExtensionsUtils.jsm
deleted file mode 100644
index e8d276fe9..000000000
--- a/toolkit/components/webextensions/LegacyExtensionsUtils.jsm
+++ /dev/null
@@ -1,250 +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";
-
-this.EXPORTED_SYMBOLS = ["LegacyExtensionsUtils"];
-
-/* exported LegacyExtensionsUtils, LegacyExtensionContext */
-
-/**
- * This file exports helpers for Legacy Extensions that want to embed a webextensions
- * and exchange messages with the embedded WebExtension.
- */
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "Extension",
- "resource://gre/modules/Extension.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Services",
- "resource://gre/modules/Services.jsm");
-
-Cu.import("resource://gre/modules/ExtensionChild.jsm");
-Cu.import("resource://gre/modules/ExtensionCommon.jsm");
-
-var {
- BaseContext,
-} = ExtensionCommon;
-
-var {
- Messenger,
-} = ExtensionChild;
-
-/**
- * Instances created from this class provide to a legacy extension
- * a simple API to exchange messages with a webextension.
- */
-var LegacyExtensionContext = class extends BaseContext {
- /**
- * Create a new LegacyExtensionContext given a target Extension instance.
- *
- * @param {Extension} targetExtension
- * The webextension instance associated with this context. This will be the
- * instance of the newly created embedded webextension when this class is
- * used through the EmbeddedWebExtensionsUtils.
- */
- constructor(targetExtension) {
- super("legacy_extension", targetExtension);
-
- // Legacy Extensions (xul overlays, bootstrap restartless and Addon SDK)
- // runs with a systemPrincipal.
- let addonPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
- Object.defineProperty(
- this, "principal",
- {value: addonPrincipal, enumerable: true, configurable: true}
- );
-
- let cloneScope = Cu.Sandbox(this.principal, {});
- Cu.setSandboxMetadata(cloneScope, {addonId: targetExtension.id});
- Object.defineProperty(
- this, "cloneScope",
- {value: cloneScope, enumerable: true, configurable: true, writable: true}
- );
-
- let sender = {id: targetExtension.id};
- let filter = {extensionId: targetExtension.id};
- // Legacy addons live in the main process. Messages from other addons are
- // Messages from WebExtensions are sent to the main process and forwarded via
- // the parent process manager to the legacy extension.
- this.messenger = new Messenger(this, [Services.cpmm], sender, filter);
-
- this.api = {
- browser: {
- runtime: {
- onConnect: this.messenger.onConnect("runtime.onConnect"),
- onMessage: this.messenger.onMessage("runtime.onMessage"),
- },
- },
- };
- }
-
- /**
- * This method is called when the extension shuts down or is unloaded,
- * and it nukes the cloneScope sandbox, if any.
- */
- unload() {
- if (this.unloaded) {
- throw new Error("Error trying to unload LegacyExtensionContext twice.");
- }
- super.unload();
- Cu.nukeSandbox(this.cloneScope);
- this.cloneScope = null;
- }
-};
-
-var EmbeddedExtensionManager;
-
-/**
- * Instances of this class are used internally by the exported EmbeddedWebExtensionsUtils
- * to manage the embedded webextension instance and the related LegacyExtensionContext
- * instance used to exchange messages with it.
- */
-class EmbeddedExtension {
- /**
- * Create a new EmbeddedExtension given the add-on id and the base resource URI of the
- * container add-on (the webextension resources will be loaded from the "webextension/"
- * subdir of the base resource URI for the legacy extension add-on).
- *
- * @param {Object} containerAddonParams
- * An object with the following properties:
- * @param {string} containerAddonParams.id
- * The Add-on id of the Legacy Extension which will contain the embedded webextension.
- * @param {nsIURI} containerAddonParams.resourceURI
- * The nsIURI of the Legacy Extension container add-on.
- */
- constructor({id, resourceURI}) {
- this.addonId = id;
- this.resourceURI = resourceURI;
-
- // Setup status flag.
- this.started = false;
- }
-
- /**
- * Start the embedded webextension.
- *
- * @returns {Promise<LegacyContextAPI>} A promise which resolve to the API exposed to the
- * legacy context.
- */
- startup() {
- if (this.started) {
- return Promise.reject(new Error("This embedded extension has already been started"));
- }
-
- // Setup the startup promise.
- this.startupPromise = new Promise((resolve, reject) => {
- let embeddedExtensionURI = Services.io.newURI("webextension/", null, this.resourceURI);
-
- // This is the instance of the WebExtension embedded in the hybrid add-on.
- this.extension = new Extension({
- id: this.addonId,
- resourceURI: embeddedExtensionURI,
- });
-
- // This callback is register to the "startup" event, emitted by the Extension instance
- // after the extension manifest.json has been loaded without any errors, but before
- // starting any of the defined contexts (which give the legacy part a chance to subscribe
- // runtime.onMessage/onConnect listener before the background page has been loaded).
- const onBeforeStarted = () => {
- this.extension.off("startup", onBeforeStarted);
-
- // Resolve the startup promise and reset the startupError.
- this.started = true;
- this.startupPromise = null;
-
- // Create the legacy extension context, the legacy container addon
- // needs to use it before the embedded webextension startup,
- // because it is supposed to be used during the legacy container startup
- // to subscribe its message listeners (which are supposed to be able to
- // receive any message that the embedded part can try to send to it
- // during its startup).
- this.context = new LegacyExtensionContext(this.extension);
-
- // Destroy the LegacyExtensionContext cloneScope when
- // the embedded webextensions is unloaded.
- this.extension.callOnClose({
- close: () => {
- this.context.unload();
- },
- });
-
- // resolve startupPromise to execute any pending shutdown that has been
- // chained to it.
- resolve(this.context.api);
- };
-
- this.extension.on("startup", onBeforeStarted);
-
- // Run ambedded extension startup and catch any error during embedded extension
- // startup.
- this.extension.startup().catch((err) => {
- this.started = false;
- this.startupPromise = null;
- this.extension.off("startup", onBeforeStarted);
-
- reject(err);
- });
- });
-
- return this.startupPromise;
- }
-
- /**
- * Shuts down the embedded webextension.
- *
- * @returns {Promise<void>} a promise that is resolved when the shutdown has been done
- */
- shutdown() {
- EmbeddedExtensionManager.untrackEmbeddedExtension(this);
-
- // If there is a pending startup, wait to be completed and then shutdown.
- if (this.startupPromise) {
- return this.startupPromise.then(() => {
- this.extension.shutdown();
- });
- }
-
- // Run shutdown now if the embedded webextension has been correctly started
- if (this.extension && this.started && !this.extension.hasShutdown) {
- this.extension.shutdown();
- }
-
- return Promise.resolve();
- }
-}
-
-// Keep track on the created EmbeddedExtension instances and destroy
-// them when their container addon is going to be disabled or uninstalled.
-EmbeddedExtensionManager = {
- // Map of the existent EmbeddedExtensions instances by addon id.
- embeddedExtensionsByAddonId: new Map(),
-
- untrackEmbeddedExtension(embeddedExtensionInstance) {
- // Remove this instance from the tracked embedded extensions
- let id = embeddedExtensionInstance.addonId;
- if (this.embeddedExtensionsByAddonId.get(id) == embeddedExtensionInstance) {
- this.embeddedExtensionsByAddonId.delete(id);
- }
- },
-
- getEmbeddedExtensionFor({id, resourceURI}) {
- let embeddedExtension = this.embeddedExtensionsByAddonId.get(id);
-
- if (!embeddedExtension) {
- embeddedExtension = new EmbeddedExtension({id, resourceURI});
- // Keep track of the embedded extension instance.
- this.embeddedExtensionsByAddonId.set(id, embeddedExtension);
- }
-
- return embeddedExtension;
- },
-};
-
-this.LegacyExtensionsUtils = {
- getEmbeddedExtensionFor: (addon) => {
- return EmbeddedExtensionManager.getEmbeddedExtensionFor(addon);
- },
-};