initializer.js (5136B)
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 // @ts-check 5 /** 6 * @typedef {import("../@types/perf").RecordingSettings} RecordingSettings 7 * @typedef {import("../@types/perf").PerfFront} PerfFront 8 * @typedef {import("../@types/perf").PageContext} PageContext 9 */ 10 "use strict"; 11 12 /** 13 * This file initializes the about:profiling page, which can be used to tweak the 14 * profiler's settings. 15 */ 16 17 { 18 // Create the browser loader, but take care not to conflict with 19 // TypeScript. See devtools/client/performance-new/typescript.md and 20 // the section on "Do not overload require" for more information. 21 22 const { BrowserLoader } = ChromeUtils.importESModule( 23 "resource://devtools/shared/loader/browser-loader.sys.mjs" 24 ); 25 const browserLoader = BrowserLoader({ 26 baseURI: "resource://devtools/client/performance-new/aboutprofiling", 27 window, 28 }); 29 30 /** 31 * @type {any} - Coerce the current scope into an `any`, and assign the 32 * loaders to the scope. They can then be used freely below. 33 */ 34 const scope = this; 35 scope.require = browserLoader.require; 36 scope.loader = browserLoader.loader; 37 } 38 39 /** 40 * The background.sys.mjs manages the profiler state, and can be loaded multiple time 41 * for various components. This page needs a copy, and it is also used by the 42 * profiler shortcuts. In order to do this, the background code needs to live in a 43 * JSM module, that can be shared with the DevTools keyboard shortcut manager. 44 */ 45 const { presets } = ChromeUtils.importESModule( 46 "resource://devtools/shared/performance-new/prefs-presets.sys.mjs" 47 ); 48 49 const ReactDOM = require("resource://devtools/client/shared/vendor/react-dom.mjs"); 50 const React = require("resource://devtools/client/shared/vendor/react.mjs"); 51 const FluentReact = require("resource://devtools/client/shared/vendor/fluent-react.js"); 52 const { 53 FluentL10n, 54 } = require("resource://devtools/client/shared/fluent-l10n/fluent-l10n.js"); 55 const Provider = React.createFactory( 56 require("resource://devtools/client/shared/vendor/react-redux.js").Provider 57 ); 58 const ProfilerPreferenceObserver = React.createFactory( 59 require("resource://devtools/client/performance-new/components/shared/ProfilerPreferenceObserver.js") 60 ); 61 const LocalizationProvider = React.createFactory( 62 FluentReact.LocalizationProvider 63 ); 64 const AboutProfiling = React.createFactory( 65 require("resource://devtools/client/performance-new/components/aboutprofiling/AboutProfiling.js") 66 ); 67 const createStore = require("resource://devtools/client/shared/redux/create-store.js"); 68 const reducers = require("resource://devtools/client/performance-new/store/reducers.js"); 69 const actions = require("resource://devtools/client/performance-new/store/actions.js"); 70 71 /** 72 * Initialize the panel by creating a redux store, and render the root component. 73 * 74 * @param {PageContext} pageContext - The context that the UI is being loaded in under. 75 * @param {boolean} isSupportedPlatform 76 * @param {string[]} supportedFeatures 77 * @param {(() => void)} [openRemoteDevTools] Optionally provide a way to go back to 78 * the remote devtools page. 79 */ 80 async function gInit( 81 pageContext, 82 isSupportedPlatform, 83 supportedFeatures, 84 openRemoteDevTools 85 ) { 86 const store = createStore(reducers); 87 88 const l10n = new FluentL10n(); 89 await l10n.init( 90 [ 91 "devtools/client/perftools.ftl", 92 // For -brand-shorter-name used in some profiler preset descriptions. 93 "branding/brand.ftl", 94 // Needed for the onboarding UI 95 "toolkit/branding/brandings.ftl", 96 ], 97 { 98 setAttributesOnDocument: true, 99 } 100 ); 101 102 // Do some initialization, especially with privileged things that are part of the 103 // the browser. 104 store.dispatch( 105 actions.initializeStore({ 106 isSupportedPlatform, 107 supportedFeatures, 108 presets, 109 pageContext, 110 openRemoteDevTools, 111 }) 112 ); 113 114 ReactDOM.render( 115 Provider( 116 { store }, 117 LocalizationProvider( 118 { bundles: l10n.getBundles() }, 119 React.createElement( 120 React.Fragment, 121 null, 122 ProfilerPreferenceObserver(), 123 AboutProfiling() 124 ) 125 ) 126 ), 127 document.querySelector("#root") 128 ); 129 130 window.addEventListener("unload", () => gDestroy(), { once: true }); 131 } 132 133 async function gDestroy() { 134 // This allows all unregister commands to run. 135 const root = document.querySelector("#root"); 136 if (root) { 137 ReactDOM.unmountComponentAtNode(root); 138 } 139 } 140 141 // Automatically initialize the page if it's not a remote connection, otherwise 142 // the page will be initialized by about:debugging. 143 if (window.location.hash !== "#remote") { 144 document.addEventListener( 145 "DOMContentLoaded", 146 () => { 147 const isSupportedPlatform = "nsIProfiler" in Ci; 148 const supportedFeatures = isSupportedPlatform 149 ? Services.profiler.GetFeatures() 150 : []; 151 gInit("aboutprofiling", isSupportedPlatform, supportedFeatures); 152 }, 153 { once: true } 154 ); 155 }