summaryrefslogtreecommitdiffstats
path: root/devtools/client/performance-new/aboutprofiling/initializer.js
blob: 8dd854007ca813af34238fddd144442a14a32ae7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/* 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/. */
// @ts-check
/**
 * @typedef {import("../@types/perf").RecordingSettings} RecordingSettings
 * @typedef {import("../@types/perf").PerfFront} PerfFront
 * @typedef {import("../@types/perf").PageContext} PageContext
 */
"use strict";

/**
 * This file initializes the about:profiling page, which can be used to tweak the
 * profiler's settings.
 */

{
  // Create the browser loader, but take care not to conflict with
  // TypeScript. See devtools/client/performance-new/typescript.md and
  // the section on "Do not overload require" for more information.

  const { BrowserLoader } = ChromeUtils.import(
    "resource://devtools/shared/loader/browser-loader.js"
  );
  const browserLoader = BrowserLoader({
    baseURI: "resource://devtools/client/performance-new/aboutprofiling",
    window,
  });

  /**
   * @type {any} - Coerce the current scope into an `any`, and assign the
   *     loaders to the scope. They can then be used freely below.
   */
  const scope = this;
  scope.require = browserLoader.require;
  scope.loader = browserLoader.loader;
}

/**
 * The background.sys.mjs manages the profiler state, and can be loaded multiple time
 * for various components. This page needs a copy, and it is also used by the
 * profiler shortcuts. In order to do this, the background code needs to live in a
 * JSM module, that can be shared with the DevTools keyboard shortcut manager.
 */
const { presets } = ChromeUtils.importESModule(
  "resource://devtools/client/performance-new/shared/background.sys.mjs"
);

const ReactDOM = require("resource://devtools/client/shared/vendor/react-dom.js");
const React = require("resource://devtools/client/shared/vendor/react.js");
const FluentReact = require("resource://devtools/client/shared/vendor/fluent-react.js");
const {
  FluentL10n,
} = require("resource://devtools/client/shared/fluent-l10n/fluent-l10n.js");
const Provider = React.createFactory(
  require("resource://devtools/client/shared/vendor/react-redux.js").Provider
);
const ProfilerPreferenceObserver = React.createFactory(
  require("resource://devtools/client/performance-new/components/shared/ProfilerPreferenceObserver.js")
);
const LocalizationProvider = React.createFactory(
  FluentReact.LocalizationProvider
);
const AboutProfiling = React.createFactory(
  require("resource://devtools/client/performance-new/components/aboutprofiling/AboutProfiling.js")
);
const createStore = require("resource://devtools/client/shared/redux/create-store.js");
const reducers = require("resource://devtools/client/performance-new/store/reducers.js");
const actions = require("resource://devtools/client/performance-new/store/actions.js");

/**
 * Initialize the panel by creating a redux store, and render the root component.
 *
 * @param {PageContext} pageContext - The context that the UI is being loaded in under.
 * @param {boolean} isSupportedPlatform
 * @param {string[]} supportedFeatures
 * @param {(() => void)} [openRemoteDevTools] Optionally provide a way to go back to
 *                                            the remote devtools page.
 */
async function gInit(
  pageContext,
  isSupportedPlatform,
  supportedFeatures,
  openRemoteDevTools
) {
  const store = createStore(reducers);

  const l10n = new FluentL10n();
  await l10n.init(
    [
      "devtools/client/perftools.ftl",
      // For -brand-shorter-name used in some profiler preset descriptions.
      "branding/brand.ftl",
      // Needed for the onboarding UI
      "toolkit/branding/brandings.ftl",
    ],
    {
      setAttributesOnDocument: true,
    }
  );

  // Do some initialization, especially with privileged things that are part of the
  // the browser.
  store.dispatch(
    actions.initializeStore({
      isSupportedPlatform,
      supportedFeatures,
      presets,
      pageContext,
      openRemoteDevTools,
    })
  );

  ReactDOM.render(
    Provider(
      { store },
      LocalizationProvider(
        { bundles: l10n.getBundles() },
        React.createElement(
          React.Fragment,
          null,
          ProfilerPreferenceObserver(),
          AboutProfiling()
        )
      )
    ),
    document.querySelector("#root")
  );

  window.addEventListener("unload", () => gDestroy(), { once: true });
}

async function gDestroy() {
  // This allows all unregister commands to run.
  ReactDOM.unmountComponentAtNode(document.querySelector("#root"));
}

// Automatically initialize the page if it's not a remote connection, otherwise
// the page will be initialized by about:debugging.
if (window.location.hash !== "#remote") {
  document.addEventListener(
    "DOMContentLoaded",
    () => {
      const isSupportedPlatform = "nsIProfiler" in Ci;
      const supportedFeatures = isSupportedPlatform
        ? Services.profiler.GetFeatures()
        : [];
      gInit("aboutprofiling", isSupportedPlatform, supportedFeatures);
    },
    { once: true }
  );
}