diff options
Diffstat (limited to 'devtools/client/framework/toolbox-init.js')
-rw-r--r-- | devtools/client/framework/toolbox-init.js | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/devtools/client/framework/toolbox-init.js b/devtools/client/framework/toolbox-init.js new file mode 100644 index 0000000000..de2bce080a --- /dev/null +++ b/devtools/client/framework/toolbox-init.js @@ -0,0 +1,135 @@ +/* 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/. */ + +/* eslint-env browser */ + +"use strict"; + +const { require } = ChromeUtils.importESModule( + "resource://devtools/shared/loader/Loader.sys.mjs" +); + +// URL constructor doesn't support about: scheme +const href = window.location.href.replace("about:", "http://"); +const url = new window.URL(href); + +// `host` is the frame element loading the toolbox. +let host = window.browsingContext.embedderElement; + +// If there's no containerElement (which happens when loading about:devtools-toolbox as +// a top level document), use the current window. +if (!host) { + host = { + contentWindow: window, + contentDocument: document, + // toolbox-host-manager.js wants to set attributes on the frame that contains it, + // but that is fine to skip and doesn't make sense when using the current window. + setAttribute() {}, + ownerDocument: document, + // toolbox-host-manager.js wants to listen for unload events from outside the frame, + // but this is fine to skip since the toolbox code listens inside the frame as well, + // and there is no outer document in this case. + addEventListener() {}, + }; +} + +const onLoad = new Promise(r => { + host.contentWindow.addEventListener("DOMContentLoaded", r, { once: true }); +}); + +async function showErrorPage(doc, errorMessage) { + const win = doc.defaultView; + const { BrowserLoader } = ChromeUtils.import( + "resource://devtools/shared/loader/browser-loader.js" + ); + const browserRequire = BrowserLoader({ + window: win, + useOnlyShared: true, + }).require; + + const React = browserRequire("devtools/client/shared/vendor/react"); + const ReactDOM = browserRequire("devtools/client/shared/vendor/react-dom"); + const DebugTargetErrorPage = React.createFactory( + require("resource://devtools/client/framework/components/DebugTargetErrorPage.js") + ); + const { LocalizationHelper } = browserRequire("devtools/shared/l10n"); + const L10N = new LocalizationHelper( + "devtools/client/locales/toolbox.properties" + ); + + // mount the React component into our XUL container once the DOM is ready + await onLoad; + + // Update the tab title. + document.title = L10N.getStr("toolbox.debugTargetInfo.tabTitleError"); + + const mountEl = doc.querySelector("#toolbox-error-mount"); + const element = DebugTargetErrorPage({ + errorMessage, + L10N, + }); + ReactDOM.render(element, mountEl); + + // make sure we unmount the component when the page is destroyed + win.addEventListener( + "unload", + () => { + ReactDOM.unmountComponentAtNode(mountEl); + }, + { once: true } + ); +} + +async function initToolbox(url, host) { + const { + gDevTools, + } = require("resource://devtools/client/framework/devtools.js"); + + const { + commandsFromURL, + } = require("resource://devtools/client/framework/commands-from-url.js"); + const { + Toolbox, + } = require("resource://devtools/client/framework/toolbox.js"); + + // Specify the default tool to open + const tool = url.searchParams.get("tool"); + + try { + const commands = await commandsFromURL(url); + const toolbox = gDevTools.getToolboxForCommands(commands); + if (toolbox && toolbox.isDestroying()) { + // If a toolbox already exists for the commands, wait for current + // toolbox destroy to be finished. + await toolbox.destroy(); + } + + // Display an error page if we are connected to a remote target and we lose it + commands.descriptorFront.once("descriptor-destroyed", function () { + // Prevent trying to display the error page if the toolbox tab is being destroyed + if (host.contentDocument) { + const error = new Error("Debug target was disconnected"); + showErrorPage(host.contentDocument, `${error}`); + } + }); + + const options = { customIframe: host }; + await gDevTools.showToolbox(commands, { + toolId: tool, + hostType: Toolbox.HostType.PAGE, + hostOptions: options, + }); + } catch (error) { + // When an error occurs, show error page with message. + console.error("Exception while loading the toolbox", error); + showErrorPage(host.contentDocument, `${error}`); + } +} + +// Only use this method to attach the toolbox if some query parameters are given +if (url.search.length > 1) { + initToolbox(url, host); +} +// TODO: handle no params in about:devtool-toolbox +// https://bugzilla.mozilla.org/show_bug.cgi?id=1526996 |