toolbox-init.js (4513B)
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 "use strict"; 6 7 const { require } = ChromeUtils.importESModule( 8 "resource://devtools/shared/loader/Loader.sys.mjs" 9 ); 10 11 // URL constructor doesn't support about: scheme 12 const href = window.location.href.replace("about:", "http://"); 13 const url = new window.URL(href); 14 15 // `host` is the frame element loading the toolbox. 16 let host = window.browsingContext.embedderElement; 17 18 // If there's no containerElement (which happens when loading about:devtools-toolbox as 19 // a top level document), use the current window. 20 if (!host) { 21 host = { 22 contentWindow: window, 23 contentDocument: document, 24 // toolbox-host-manager.js wants to set attributes on the frame that contains it, 25 // but that is fine to skip and doesn't make sense when using the current window. 26 setAttribute() {}, 27 ownerDocument: document, 28 // toolbox-host-manager.js wants to listen for unload events from outside the frame, 29 // but this is fine to skip since the toolbox code listens inside the frame as well, 30 // and there is no outer document in this case. 31 addEventListener() {}, 32 }; 33 } 34 35 const onLoad = new Promise(r => { 36 host.contentWindow.addEventListener("DOMContentLoaded", r, { once: true }); 37 }); 38 39 async function showErrorPage(doc, errorMessage) { 40 const win = doc.defaultView; 41 const { BrowserLoader } = ChromeUtils.importESModule( 42 "resource://devtools/shared/loader/browser-loader.sys.mjs" 43 ); 44 const browserRequire = BrowserLoader({ 45 window: win, 46 useOnlyShared: true, 47 }).require; 48 49 const React = browserRequire("devtools/client/shared/vendor/react"); 50 const ReactDOM = browserRequire("devtools/client/shared/vendor/react-dom"); 51 const DebugTargetErrorPage = React.createFactory( 52 require("resource://devtools/client/framework/components/DebugTargetErrorPage.js") 53 ); 54 const { LocalizationHelper } = browserRequire("devtools/shared/l10n"); 55 const L10N = new LocalizationHelper( 56 "devtools/client/locales/toolbox.properties" 57 ); 58 59 // mount the React component into our XUL container once the DOM is ready 60 await onLoad; 61 62 // Update the tab title. 63 document.title = L10N.getStr("toolbox.debugTargetInfo.tabTitleError"); 64 65 const mountEl = doc.querySelector("#toolbox-error-mount"); 66 const element = DebugTargetErrorPage({ 67 errorMessage, 68 L10N, 69 }); 70 ReactDOM.render(element, mountEl); 71 72 // make sure we unmount the component when the page is destroyed 73 win.addEventListener( 74 "unload", 75 () => { 76 ReactDOM.unmountComponentAtNode(mountEl); 77 }, 78 { once: true } 79 ); 80 } 81 82 async function initToolbox(url, host) { 83 const { 84 gDevTools, 85 } = require("resource://devtools/client/framework/devtools.js"); 86 87 const { 88 commandsFromURL, 89 } = require("resource://devtools/client/framework/commands-from-url.js"); 90 const { 91 Toolbox, 92 } = require("resource://devtools/client/framework/toolbox.js"); 93 94 // Specify the default tool to open 95 const tool = url.searchParams.get("tool"); 96 97 try { 98 const commands = await commandsFromURL(url); 99 const toolbox = gDevTools.getToolboxForCommands(commands); 100 if (toolbox && toolbox.isDestroying()) { 101 // If a toolbox already exists for the commands, wait for current 102 // toolbox destroy to be finished. 103 await toolbox.destroy(); 104 } 105 106 // Display an error page if we are connected to a remote target and we lose it 107 commands.descriptorFront.once("descriptor-destroyed", function () { 108 // Prevent trying to display the error page if the toolbox tab is being destroyed 109 if (host.contentDocument) { 110 const error = new Error("Debug target was disconnected"); 111 showErrorPage(host.contentDocument, `${error}`); 112 } 113 }); 114 115 const options = { customIframe: host }; 116 await gDevTools.showToolbox(commands, { 117 toolId: tool, 118 hostType: Toolbox.HostType.PAGE, 119 hostOptions: options, 120 }); 121 } catch (error) { 122 // When an error occurs, show error page with message. 123 console.error("Exception while loading the toolbox", error); 124 showErrorPage(host.contentDocument, `${error}`); 125 } 126 } 127 128 // Only use this method to attach the toolbox if some query parameters are given 129 if (url.search.length > 1) { 130 initToolbox(url, host); 131 } 132 // TODO: handle no params in about:devtool-toolbox 133 // https://bugzilla.mozilla.org/show_bug.cgi?id=1526996