diff options
Diffstat (limited to 'application/basilisk/components/extensions/ext-devtools.js')
-rw-r--r-- | application/basilisk/components/extensions/ext-devtools.js | 312 |
1 files changed, 0 insertions, 312 deletions
diff --git a/application/basilisk/components/extensions/ext-devtools.js b/application/basilisk/components/extensions/ext-devtools.js deleted file mode 100644 index 6ba9e507a..000000000 --- a/application/basilisk/components/extensions/ext-devtools.js +++ /dev/null @@ -1,312 +0,0 @@ -/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* vim: set sts=2 sw=2 et tw=80: */ -"use strict"; - -/* global getTargetTabIdForToolbox */ - -/** - * This module provides helpers used by the other specialized `ext-devtools-*.js` modules - * and the implementation of the `devtools_page`. - */ - -XPCOMUtils.defineLazyModuleGetter(this, "gDevTools", - "resource://devtools/client/framework/gDevTools.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Task", - "resource://gre/modules/Task.jsm"); - -Cu.import("resource://gre/modules/ExtensionParent.jsm"); - -const { - HiddenExtensionPage, - watchExtensionProxyContextLoad, -} = ExtensionParent; - -// Map[extension -> DevToolsPageDefinition] -let devtoolsPageDefinitionMap = new Map(); - -let initDevTools; - -/** - * Retrieve the devtools target for the devtools extension proxy context - * (lazily cloned from the target of the toolbox associated to the context - * the first time that it is accessed). - * - * @param {DevToolsExtensionPageContextParent} context - * A devtools extension proxy context. - * - * @returns {Promise<TabTarget>} - * The cloned devtools target associated to the context. - */ -global.getDevToolsTargetForContext = (context) => { - return Task.spawn(function* asyncGetTabTarget() { - if (context.devToolsTarget) { - return context.devToolsTarget; - } - - if (!context.devToolsToolbox || !context.devToolsToolbox.target) { - throw new Error("Unable to get a TabTarget for a context not associated to any toolbox"); - } - - if (!context.devToolsToolbox.target.isLocalTab) { - throw new Error("Unexpected target type: only local tabs are currently supported."); - } - - const {TabTarget} = require("devtools/client/framework/target"); - - context.devToolsTarget = new TabTarget(context.devToolsToolbox.target.tab); - yield context.devToolsTarget.makeRemote(); - - return context.devToolsTarget; - }); -}; - -/** - * Retrieve the devtools target for the devtools extension proxy context - * (lazily cloned from the target of the toolbox associated to the context - * the first time that it is accessed). - * - * @param {Toolbox} toolbox - * A devtools toolbox instance. - * - * @returns {number} - * The corresponding WebExtensions tabId. - */ -global.getTargetTabIdForToolbox = (toolbox) => { - let {target} = toolbox; - - if (!target.isLocalTab) { - throw new Error("Unexpected target type: only local tabs are currently supported."); - } - - let parentWindow = target.tab.linkedBrowser.ownerDocument.defaultView; - let tab = parentWindow.gBrowser.getTabForBrowser(target.tab.linkedBrowser); - - return TabManager.getId(tab); -}; - -/** - * The DevToolsPage represents the "devtools_page" related to a particular - * Toolbox and WebExtension. - * - * The devtools_page contexts are invisible WebExtensions contexts, similar to the - * background page, associated to a single developer toolbox (e.g. If an add-on - * registers a devtools_page and the user opens 3 developer toolbox in 3 webpages, - * 3 devtools_page contexts will be created for that add-on). - * - * @param {Extension} extension - * The extension that owns the devtools_page. - * @param {Object} options - * @param {Toolbox} options.toolbox - * The developer toolbox instance related to this devtools_page. - * @param {string} options.url - * The path to the devtools page html page relative to the extension base URL. - * @param {DevToolsPageDefinition} options.devToolsPageDefinition - * The instance of the devToolsPageDefinition class related to this DevToolsPage. - */ -class DevToolsPage extends HiddenExtensionPage { - constructor(extension, options) { - super(extension, "devtools_page"); - - this.url = extension.baseURI.resolve(options.url); - this.toolbox = options.toolbox; - this.devToolsPageDefinition = options.devToolsPageDefinition; - - this.unwatchExtensionProxyContextLoad = null; - - this.waitForTopLevelContext = new Promise(resolve => { - this.resolveTopLevelContext = resolve; - }); - } - - build() { - return Task.spawn(function* () { - yield this.createBrowserElement(); - - // Listening to new proxy contexts. - this.unwatchExtensionProxyContextLoad = watchExtensionProxyContextLoad(this, context => { - // Keep track of the toolbox and target associated to the context, which is - // needed by the API methods implementation. - context.devToolsToolbox = this.toolbox; - - if (!this.topLevelContext) { - this.topLevelContext = context; - - // Ensure this devtools page is destroyed, when the top level context proxy is - // closed. - this.topLevelContext.callOnClose(this); - - this.resolveTopLevelContext(context); - } - }); - - extensions.emit("extension-browser-inserted", this.browser, { - devtoolsToolboxInfo: { - inspectedWindowTabId: getTargetTabIdForToolbox(this.toolbox), - }, - }); - - this.browser.loadURI(this.url); - - yield this.waitForTopLevelContext; - }.bind(this)); - } - - close() { - if (this.closed) { - throw new Error("Unable to shutdown a closed DevToolsPage instance"); - } - - this.closed = true; - - // Unregister the devtools page instance from the devtools page definition. - this.devToolsPageDefinition.forgetForTarget(this.toolbox.target); - - // Unregister it from the resources to cleanup when the context has been closed. - if (this.topLevelContext) { - this.topLevelContext.forgetOnClose(this); - } - - // Stop watching for any new proxy contexts from the devtools page. - if (this.unwatchExtensionProxyContextLoad) { - this.unwatchExtensionProxyContextLoad(); - this.unwatchExtensionProxyContextLoad = null; - } - - super.shutdown(); - } -} - -/** - * The DevToolsPageDefinitions class represents the "devtools_page" manifest property - * of a WebExtension. - * - * A DevToolsPageDefinition instance is created automatically when a WebExtension - * which contains the "devtools_page" manifest property has been loaded, and it is - * automatically destroyed when the related WebExtension has been unloaded, - * and so there will be at most one DevtoolsPageDefinition per add-on. - * - * Every time a developer tools toolbox is opened, the DevToolsPageDefinition creates - * and keep track of a DevToolsPage instance (which represents the actual devtools_page - * instance related to that particular toolbox). - * - * @param {Extension} extension - * The extension that owns the devtools_page. - * @param {string} url - * The path to the devtools page html page relative to the extension base URL. - */ -class DevToolsPageDefinition { - constructor(extension, url) { - initDevTools(); - - this.url = url; - this.extension = extension; - - // Map[TabTarget -> DevToolsPage] - this.devtoolsPageForTarget = new Map(); - } - - buildForToolbox(toolbox) { - if (this.devtoolsPageForTarget.has(toolbox.target)) { - return Promise.reject(new Error("DevtoolsPage has been already created for this toolbox")); - } - - const devtoolsPage = new DevToolsPage(this.extension, { - toolbox, url: this.url, devToolsPageDefinition: this, - }); - this.devtoolsPageForTarget.set(toolbox.target, devtoolsPage); - - return devtoolsPage.build(); - } - - shutdownForTarget(target) { - if (this.devtoolsPageForTarget.has(target)) { - const devtoolsPage = this.devtoolsPageForTarget.get(target); - devtoolsPage.close(); - - // `devtoolsPage.close()` should remove the instance from the map, - // raise an exception if it is still there. - if (this.devtoolsPageForTarget.has(target)) { - throw new Error(`Leaked DevToolsPage instance for target "${target.toString()}"`); - } - } - } - - forgetForTarget(target) { - this.devtoolsPageForTarget.delete(target); - } - - shutdown() { - for (let target of this.devtoolsPageForTarget.keys()) { - this.shutdownForTarget(target); - } - - if (this.devtoolsPageForTarget.size > 0) { - throw new Error( - `Leaked ${this.devtoolsPageForTarget.size} DevToolsPage instances in devtoolsPageForTarget Map` - ); - } - } -} - -/* eslint-disable mozilla/balanced-listeners */ - -let devToolsInitialized = false; -initDevTools = function() { - if (devToolsInitialized) { - return; - } - - // Create a devtools page context for a new opened toolbox, - // based on the registered devtools_page definitions. - gDevTools.on("toolbox-created", (evt, toolbox) => { - if (!toolbox.target.isLocalTab) { - // Only local tabs are currently supported (See Bug 1304378 for additional details - // related to remote targets support). - let msg = `Ignoring DevTools Toolbox for target "${toolbox.target.toString()}": ` + - `"${toolbox.target.name}" ("${toolbox.target.url}"). ` + - "Only local tab are currently supported by the WebExtensions DevTools API."; - let scriptError = Cc["@mozilla.org/scripterror;1"].createInstance(Ci.nsIScriptError); - scriptError.init(msg, null, null, null, null, Ci.nsIScriptError.warningFlag, "content javascript"); - let consoleService = Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService); - consoleService.logMessage(scriptError); - - return; - } - - for (let devtoolsPage of devtoolsPageDefinitionMap.values()) { - devtoolsPage.buildForToolbox(toolbox); - } - }); - - // Destroy a devtools page context for a destroyed toolbox, - // based on the registered devtools_page definitions. - gDevTools.on("toolbox-destroy", (evt, target) => { - if (!target.isLocalTab) { - // Only local tabs are currently supported (See Bug 1304378 for additional details - // related to remote targets support). - return; - } - - for (let devtoolsPageDefinition of devtoolsPageDefinitionMap.values()) { - devtoolsPageDefinition.shutdownForTarget(target); - } - }); - - devToolsInitialized = true; -}; - -// Create and register a new devtools_page definition as specified in the -// "devtools_page" property in the extension manifest. -extensions.on("manifest_devtools_page", (type, directive, extension, manifest) => { - let devtoolsPageDefinition = new DevToolsPageDefinition(extension, manifest[directive]); - devtoolsPageDefinitionMap.set(extension, devtoolsPageDefinition); -}); - -// Destroy the registered devtools_page definition on extension shutdown. -extensions.on("shutdown", (type, extension) => { - if (devtoolsPageDefinitionMap.has(extension)) { - devtoolsPageDefinitionMap.get(extension).shutdown(); - devtoolsPageDefinitionMap.delete(extension); - } -}); -/* eslint-enable mozilla/balanced-listeners */ |