xref: /aosp_15_r20/external/perfetto/ui/src/frontend/index.ts (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker// Copyright (C) 2018 The Android Open Source Project
2*6dbdd20aSAndroid Build Coastguard Worker//
3*6dbdd20aSAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*6dbdd20aSAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*6dbdd20aSAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*6dbdd20aSAndroid Build Coastguard Worker//
7*6dbdd20aSAndroid Build Coastguard Worker//      http://www.apache.org/licenses/LICENSE-2.0
8*6dbdd20aSAndroid Build Coastguard Worker//
9*6dbdd20aSAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*6dbdd20aSAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*6dbdd20aSAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*6dbdd20aSAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*6dbdd20aSAndroid Build Coastguard Worker// limitations under the License.
14*6dbdd20aSAndroid Build Coastguard Worker
15*6dbdd20aSAndroid Build Coastguard Worker// Keep this import first.
16*6dbdd20aSAndroid Build Coastguard Workerimport '../base/disposable_polyfill';
17*6dbdd20aSAndroid Build Coastguard Workerimport '../base/static_initializers';
18*6dbdd20aSAndroid Build Coastguard Workerimport NON_CORE_PLUGINS from '../gen/all_plugins';
19*6dbdd20aSAndroid Build Coastguard Workerimport CORE_PLUGINS from '../gen/all_core_plugins';
20*6dbdd20aSAndroid Build Coastguard Workerimport m from 'mithril';
21*6dbdd20aSAndroid Build Coastguard Workerimport {defer} from '../base/deferred';
22*6dbdd20aSAndroid Build Coastguard Workerimport {addErrorHandler, reportError} from '../base/logging';
23*6dbdd20aSAndroid Build Coastguard Workerimport {featureFlags} from '../core/feature_flags';
24*6dbdd20aSAndroid Build Coastguard Workerimport {initLiveReload} from '../core/live_reload';
25*6dbdd20aSAndroid Build Coastguard Workerimport {raf} from '../core/raf_scheduler';
26*6dbdd20aSAndroid Build Coastguard Workerimport {initWasm} from '../trace_processor/wasm_engine_proxy';
27*6dbdd20aSAndroid Build Coastguard Workerimport {setScheduleFullRedraw} from '../widgets/raf';
28*6dbdd20aSAndroid Build Coastguard Workerimport {UiMain} from './ui_main';
29*6dbdd20aSAndroid Build Coastguard Workerimport {initCssConstants} from './css_constants';
30*6dbdd20aSAndroid Build Coastguard Workerimport {registerDebugGlobals} from './debug';
31*6dbdd20aSAndroid Build Coastguard Workerimport {maybeShowErrorDialog} from './error_dialog';
32*6dbdd20aSAndroid Build Coastguard Workerimport {installFileDropHandler} from './file_drop_handler';
33*6dbdd20aSAndroid Build Coastguard Workerimport {globals} from './globals';
34*6dbdd20aSAndroid Build Coastguard Workerimport {HomePage} from './home_page';
35*6dbdd20aSAndroid Build Coastguard Workerimport {postMessageHandler} from './post_message_handler';
36*6dbdd20aSAndroid Build Coastguard Workerimport {Route, Router} from '../core/router';
37*6dbdd20aSAndroid Build Coastguard Workerimport {CheckHttpRpcConnection} from './rpc_http_dialog';
38*6dbdd20aSAndroid Build Coastguard Workerimport {maybeOpenTraceFromRoute} from './trace_url_handler';
39*6dbdd20aSAndroid Build Coastguard Workerimport {ViewerPage} from './viewer_page';
40*6dbdd20aSAndroid Build Coastguard Workerimport {HttpRpcEngine} from '../trace_processor/http_rpc_engine';
41*6dbdd20aSAndroid Build Coastguard Workerimport {showModal} from '../widgets/modal';
42*6dbdd20aSAndroid Build Coastguard Workerimport {IdleDetector} from './idle_detector';
43*6dbdd20aSAndroid Build Coastguard Workerimport {IdleDetectorWindow} from './idle_detector_interface';
44*6dbdd20aSAndroid Build Coastguard Workerimport {AppImpl} from '../core/app_impl';
45*6dbdd20aSAndroid Build Coastguard Workerimport {addSqlTableTab} from '../components/details/sql_table_tab';
46*6dbdd20aSAndroid Build Coastguard Workerimport {configureExtensions} from '../components/extensions';
47*6dbdd20aSAndroid Build Coastguard Workerimport {
48*6dbdd20aSAndroid Build Coastguard Worker  addDebugCounterTrack,
49*6dbdd20aSAndroid Build Coastguard Worker  addDebugSliceTrack,
50*6dbdd20aSAndroid Build Coastguard Worker} from '../components/tracks/debug_tracks';
51*6dbdd20aSAndroid Build Coastguard Workerimport {addVisualizedArgTracks} from '../components/tracks/visualized_args_tracks';
52*6dbdd20aSAndroid Build Coastguard Workerimport {addQueryResultsTab} from '../components/query_table/query_result_tab';
53*6dbdd20aSAndroid Build Coastguard Workerimport {assetSrc, initAssets} from '../base/assets';
54*6dbdd20aSAndroid Build Coastguard Worker
55*6dbdd20aSAndroid Build Coastguard Workerconst CSP_WS_PERMISSIVE_PORT = featureFlags.register({
56*6dbdd20aSAndroid Build Coastguard Worker  id: 'cspAllowAnyWebsocketPort',
57*6dbdd20aSAndroid Build Coastguard Worker  name: 'Relax Content Security Policy for 127.0.0.1:*',
58*6dbdd20aSAndroid Build Coastguard Worker  description:
59*6dbdd20aSAndroid Build Coastguard Worker    'Allows simultaneous usage of several trace_processor_shell ' +
60*6dbdd20aSAndroid Build Coastguard Worker    '-D --http-port 1234 by opening ' +
61*6dbdd20aSAndroid Build Coastguard Worker    'https://ui.perfetto.dev/#!/?rpc_port=1234',
62*6dbdd20aSAndroid Build Coastguard Worker  defaultValue: false,
63*6dbdd20aSAndroid Build Coastguard Worker});
64*6dbdd20aSAndroid Build Coastguard Worker
65*6dbdd20aSAndroid Build Coastguard Workerfunction routeChange(route: Route) {
66*6dbdd20aSAndroid Build Coastguard Worker  raf.scheduleFullRedraw('force', () => {
67*6dbdd20aSAndroid Build Coastguard Worker    if (route.fragment) {
68*6dbdd20aSAndroid Build Coastguard Worker      // This needs to happen after the next redraw call. It's not enough
69*6dbdd20aSAndroid Build Coastguard Worker      // to use setTimeout(..., 0); since that may occur before the
70*6dbdd20aSAndroid Build Coastguard Worker      // redraw scheduled above.
71*6dbdd20aSAndroid Build Coastguard Worker      const e = document.getElementById(route.fragment);
72*6dbdd20aSAndroid Build Coastguard Worker      if (e) {
73*6dbdd20aSAndroid Build Coastguard Worker        e.scrollIntoView();
74*6dbdd20aSAndroid Build Coastguard Worker      }
75*6dbdd20aSAndroid Build Coastguard Worker    }
76*6dbdd20aSAndroid Build Coastguard Worker  });
77*6dbdd20aSAndroid Build Coastguard Worker  maybeOpenTraceFromRoute(route);
78*6dbdd20aSAndroid Build Coastguard Worker}
79*6dbdd20aSAndroid Build Coastguard Worker
80*6dbdd20aSAndroid Build Coastguard Workerfunction setupContentSecurityPolicy() {
81*6dbdd20aSAndroid Build Coastguard Worker  // Note: self and sha-xxx must be quoted, urls data: and blob: must not.
82*6dbdd20aSAndroid Build Coastguard Worker
83*6dbdd20aSAndroid Build Coastguard Worker  let rpcPolicy = [
84*6dbdd20aSAndroid Build Coastguard Worker    'http://127.0.0.1:9001', // For trace_processor_shell --httpd.
85*6dbdd20aSAndroid Build Coastguard Worker    'ws://127.0.0.1:9001', // Ditto, for the websocket RPC.
86*6dbdd20aSAndroid Build Coastguard Worker  ];
87*6dbdd20aSAndroid Build Coastguard Worker  if (CSP_WS_PERMISSIVE_PORT.get()) {
88*6dbdd20aSAndroid Build Coastguard Worker    const route = Router.parseUrl(window.location.href);
89*6dbdd20aSAndroid Build Coastguard Worker    if (/^\d+$/.exec(route.args.rpc_port ?? '')) {
90*6dbdd20aSAndroid Build Coastguard Worker      rpcPolicy = [
91*6dbdd20aSAndroid Build Coastguard Worker        `http://127.0.0.1:${route.args.rpc_port}`,
92*6dbdd20aSAndroid Build Coastguard Worker        `ws://127.0.0.1:${route.args.rpc_port}`,
93*6dbdd20aSAndroid Build Coastguard Worker      ];
94*6dbdd20aSAndroid Build Coastguard Worker    }
95*6dbdd20aSAndroid Build Coastguard Worker  }
96*6dbdd20aSAndroid Build Coastguard Worker  const policy = {
97*6dbdd20aSAndroid Build Coastguard Worker    'default-src': [
98*6dbdd20aSAndroid Build Coastguard Worker      `'self'`,
99*6dbdd20aSAndroid Build Coastguard Worker      // Google Tag Manager bootstrap.
100*6dbdd20aSAndroid Build Coastguard Worker      `'sha256-LirUKeorCU4uRNtNzr8tlB11uy8rzrdmqHCX38JSwHY='`,
101*6dbdd20aSAndroid Build Coastguard Worker    ],
102*6dbdd20aSAndroid Build Coastguard Worker    'script-src': [
103*6dbdd20aSAndroid Build Coastguard Worker      `'self'`,
104*6dbdd20aSAndroid Build Coastguard Worker      // TODO(b/201596551): this is required for Wasm after crrev.com/c/3179051
105*6dbdd20aSAndroid Build Coastguard Worker      // and should be replaced with 'wasm-unsafe-eval'.
106*6dbdd20aSAndroid Build Coastguard Worker      `'unsafe-eval'`,
107*6dbdd20aSAndroid Build Coastguard Worker      'https://*.google.com',
108*6dbdd20aSAndroid Build Coastguard Worker      'https://*.googleusercontent.com',
109*6dbdd20aSAndroid Build Coastguard Worker      'https://www.googletagmanager.com',
110*6dbdd20aSAndroid Build Coastguard Worker      'https://*.google-analytics.com',
111*6dbdd20aSAndroid Build Coastguard Worker    ],
112*6dbdd20aSAndroid Build Coastguard Worker    'object-src': ['none'],
113*6dbdd20aSAndroid Build Coastguard Worker    'connect-src': [
114*6dbdd20aSAndroid Build Coastguard Worker      `'self'`,
115*6dbdd20aSAndroid Build Coastguard Worker      'ws://127.0.0.1:8037', // For the adb websocket server.
116*6dbdd20aSAndroid Build Coastguard Worker      'https://*.google-analytics.com',
117*6dbdd20aSAndroid Build Coastguard Worker      'https://*.googleapis.com', // For Google Cloud Storage fetches.
118*6dbdd20aSAndroid Build Coastguard Worker      'blob:',
119*6dbdd20aSAndroid Build Coastguard Worker      'data:',
120*6dbdd20aSAndroid Build Coastguard Worker    ].concat(rpcPolicy),
121*6dbdd20aSAndroid Build Coastguard Worker    'img-src': [
122*6dbdd20aSAndroid Build Coastguard Worker      `'self'`,
123*6dbdd20aSAndroid Build Coastguard Worker      'data:',
124*6dbdd20aSAndroid Build Coastguard Worker      'blob:',
125*6dbdd20aSAndroid Build Coastguard Worker      'https://*.google-analytics.com',
126*6dbdd20aSAndroid Build Coastguard Worker      'https://www.googletagmanager.com',
127*6dbdd20aSAndroid Build Coastguard Worker      'https://*.googleapis.com',
128*6dbdd20aSAndroid Build Coastguard Worker    ],
129*6dbdd20aSAndroid Build Coastguard Worker    'style-src': [`'self'`, `'unsafe-inline'`],
130*6dbdd20aSAndroid Build Coastguard Worker    'navigate-to': ['https://*.perfetto.dev', 'self'],
131*6dbdd20aSAndroid Build Coastguard Worker  };
132*6dbdd20aSAndroid Build Coastguard Worker  const meta = document.createElement('meta');
133*6dbdd20aSAndroid Build Coastguard Worker  meta.httpEquiv = 'Content-Security-Policy';
134*6dbdd20aSAndroid Build Coastguard Worker  let policyStr = '';
135*6dbdd20aSAndroid Build Coastguard Worker  for (const [key, list] of Object.entries(policy)) {
136*6dbdd20aSAndroid Build Coastguard Worker    policyStr += `${key} ${list.join(' ')}; `;
137*6dbdd20aSAndroid Build Coastguard Worker  }
138*6dbdd20aSAndroid Build Coastguard Worker  meta.content = policyStr;
139*6dbdd20aSAndroid Build Coastguard Worker  document.head.appendChild(meta);
140*6dbdd20aSAndroid Build Coastguard Worker}
141*6dbdd20aSAndroid Build Coastguard Worker
142*6dbdd20aSAndroid Build Coastguard Workerfunction main() {
143*6dbdd20aSAndroid Build Coastguard Worker  // Setup content security policy before anything else.
144*6dbdd20aSAndroid Build Coastguard Worker  setupContentSecurityPolicy();
145*6dbdd20aSAndroid Build Coastguard Worker  initAssets();
146*6dbdd20aSAndroid Build Coastguard Worker  AppImpl.initialize({
147*6dbdd20aSAndroid Build Coastguard Worker    initialRouteArgs: Router.parseUrl(window.location.href).args,
148*6dbdd20aSAndroid Build Coastguard Worker  });
149*6dbdd20aSAndroid Build Coastguard Worker
150*6dbdd20aSAndroid Build Coastguard Worker  // Wire up raf for widgets.
151*6dbdd20aSAndroid Build Coastguard Worker  setScheduleFullRedraw((force?: 'force') => raf.scheduleFullRedraw(force));
152*6dbdd20aSAndroid Build Coastguard Worker
153*6dbdd20aSAndroid Build Coastguard Worker  // Load the css. The load is asynchronous and the CSS is not ready by the time
154*6dbdd20aSAndroid Build Coastguard Worker  // appendChild returns.
155*6dbdd20aSAndroid Build Coastguard Worker  const cssLoadPromise = defer<void>();
156*6dbdd20aSAndroid Build Coastguard Worker  const css = document.createElement('link');
157*6dbdd20aSAndroid Build Coastguard Worker  css.rel = 'stylesheet';
158*6dbdd20aSAndroid Build Coastguard Worker  css.href = assetSrc('perfetto.css');
159*6dbdd20aSAndroid Build Coastguard Worker  css.onload = () => cssLoadPromise.resolve();
160*6dbdd20aSAndroid Build Coastguard Worker  css.onerror = (err) => cssLoadPromise.reject(err);
161*6dbdd20aSAndroid Build Coastguard Worker  const favicon = document.head.querySelector('#favicon');
162*6dbdd20aSAndroid Build Coastguard Worker  if (favicon instanceof HTMLLinkElement) {
163*6dbdd20aSAndroid Build Coastguard Worker    favicon.href = assetSrc('assets/favicon.png');
164*6dbdd20aSAndroid Build Coastguard Worker  }
165*6dbdd20aSAndroid Build Coastguard Worker
166*6dbdd20aSAndroid Build Coastguard Worker  // Load the script to detect if this is a Googler (see comments on globals.ts)
167*6dbdd20aSAndroid Build Coastguard Worker  // and initialize GA after that (or after a timeout if something goes wrong).
168*6dbdd20aSAndroid Build Coastguard Worker  function initAnalyticsOnScriptLoad() {
169*6dbdd20aSAndroid Build Coastguard Worker    AppImpl.instance.analytics.initialize(globals.isInternalUser);
170*6dbdd20aSAndroid Build Coastguard Worker  }
171*6dbdd20aSAndroid Build Coastguard Worker  const script = document.createElement('script');
172*6dbdd20aSAndroid Build Coastguard Worker  script.src =
173*6dbdd20aSAndroid Build Coastguard Worker    'https://storage.cloud.google.com/perfetto-ui-internal/is_internal_user.js';
174*6dbdd20aSAndroid Build Coastguard Worker  script.async = true;
175*6dbdd20aSAndroid Build Coastguard Worker  script.onerror = () => initAnalyticsOnScriptLoad();
176*6dbdd20aSAndroid Build Coastguard Worker  script.onload = () => initAnalyticsOnScriptLoad();
177*6dbdd20aSAndroid Build Coastguard Worker  setTimeout(() => initAnalyticsOnScriptLoad(), 5000);
178*6dbdd20aSAndroid Build Coastguard Worker
179*6dbdd20aSAndroid Build Coastguard Worker  document.head.append(script, css);
180*6dbdd20aSAndroid Build Coastguard Worker
181*6dbdd20aSAndroid Build Coastguard Worker  // Route errors to both the UI bugreport dialog and Analytics (if enabled).
182*6dbdd20aSAndroid Build Coastguard Worker  addErrorHandler(maybeShowErrorDialog);
183*6dbdd20aSAndroid Build Coastguard Worker  addErrorHandler((e) => AppImpl.instance.analytics.logError(e));
184*6dbdd20aSAndroid Build Coastguard Worker
185*6dbdd20aSAndroid Build Coastguard Worker  // Add Error handlers for JS error and for uncaught exceptions in promises.
186*6dbdd20aSAndroid Build Coastguard Worker  window.addEventListener('error', (e) => reportError(e));
187*6dbdd20aSAndroid Build Coastguard Worker  window.addEventListener('unhandledrejection', (e) => reportError(e));
188*6dbdd20aSAndroid Build Coastguard Worker
189*6dbdd20aSAndroid Build Coastguard Worker  initWasm();
190*6dbdd20aSAndroid Build Coastguard Worker  AppImpl.instance.serviceWorkerController.install();
191*6dbdd20aSAndroid Build Coastguard Worker
192*6dbdd20aSAndroid Build Coastguard Worker  // Put debug variables in the global scope for better debugging.
193*6dbdd20aSAndroid Build Coastguard Worker  registerDebugGlobals();
194*6dbdd20aSAndroid Build Coastguard Worker
195*6dbdd20aSAndroid Build Coastguard Worker  // Prevent pinch zoom.
196*6dbdd20aSAndroid Build Coastguard Worker  document.body.addEventListener(
197*6dbdd20aSAndroid Build Coastguard Worker    'wheel',
198*6dbdd20aSAndroid Build Coastguard Worker    (e: MouseEvent) => {
199*6dbdd20aSAndroid Build Coastguard Worker      if (e.ctrlKey) e.preventDefault();
200*6dbdd20aSAndroid Build Coastguard Worker    },
201*6dbdd20aSAndroid Build Coastguard Worker    {passive: false},
202*6dbdd20aSAndroid Build Coastguard Worker  );
203*6dbdd20aSAndroid Build Coastguard Worker
204*6dbdd20aSAndroid Build Coastguard Worker  cssLoadPromise.then(() => onCssLoaded());
205*6dbdd20aSAndroid Build Coastguard Worker
206*6dbdd20aSAndroid Build Coastguard Worker  if (AppImpl.instance.testingMode) {
207*6dbdd20aSAndroid Build Coastguard Worker    document.body.classList.add('testing');
208*6dbdd20aSAndroid Build Coastguard Worker  }
209*6dbdd20aSAndroid Build Coastguard Worker
210*6dbdd20aSAndroid Build Coastguard Worker  (window as {} as IdleDetectorWindow).waitForPerfettoIdle = (ms?: number) => {
211*6dbdd20aSAndroid Build Coastguard Worker    return new IdleDetector().waitForPerfettoIdle(ms);
212*6dbdd20aSAndroid Build Coastguard Worker  };
213*6dbdd20aSAndroid Build Coastguard Worker}
214*6dbdd20aSAndroid Build Coastguard Worker
215*6dbdd20aSAndroid Build Coastguard Workerfunction onCssLoaded() {
216*6dbdd20aSAndroid Build Coastguard Worker  initCssConstants();
217*6dbdd20aSAndroid Build Coastguard Worker  // Clear all the contents of the initial page (e.g. the <pre> error message)
218*6dbdd20aSAndroid Build Coastguard Worker  // And replace it with the root <main> element which will be used by mithril.
219*6dbdd20aSAndroid Build Coastguard Worker  document.body.innerHTML = '';
220*6dbdd20aSAndroid Build Coastguard Worker
221*6dbdd20aSAndroid Build Coastguard Worker  const pages = AppImpl.instance.pages;
222*6dbdd20aSAndroid Build Coastguard Worker  const traceless = true;
223*6dbdd20aSAndroid Build Coastguard Worker  pages.registerPage({route: '/', traceless, page: HomePage});
224*6dbdd20aSAndroid Build Coastguard Worker  pages.registerPage({route: '/viewer', page: ViewerPage});
225*6dbdd20aSAndroid Build Coastguard Worker  const router = new Router();
226*6dbdd20aSAndroid Build Coastguard Worker  router.onRouteChanged = routeChange;
227*6dbdd20aSAndroid Build Coastguard Worker
228*6dbdd20aSAndroid Build Coastguard Worker  // Mount the main mithril component. This also forces a sync render pass.
229*6dbdd20aSAndroid Build Coastguard Worker  raf.mount(document.body, UiMain);
230*6dbdd20aSAndroid Build Coastguard Worker
231*6dbdd20aSAndroid Build Coastguard Worker  if (
232*6dbdd20aSAndroid Build Coastguard Worker    (location.origin.startsWith('http://localhost:') ||
233*6dbdd20aSAndroid Build Coastguard Worker      location.origin.startsWith('http://127.0.0.1:')) &&
234*6dbdd20aSAndroid Build Coastguard Worker    !AppImpl.instance.embeddedMode &&
235*6dbdd20aSAndroid Build Coastguard Worker    !AppImpl.instance.testingMode
236*6dbdd20aSAndroid Build Coastguard Worker  ) {
237*6dbdd20aSAndroid Build Coastguard Worker    initLiveReload();
238*6dbdd20aSAndroid Build Coastguard Worker  }
239*6dbdd20aSAndroid Build Coastguard Worker
240*6dbdd20aSAndroid Build Coastguard Worker  // Will update the chip on the sidebar footer that notifies that the RPC is
241*6dbdd20aSAndroid Build Coastguard Worker  // connected. Has no effect on the controller (which will repeat this check
242*6dbdd20aSAndroid Build Coastguard Worker  // before creating a new engine).
243*6dbdd20aSAndroid Build Coastguard Worker  // Don't auto-open any trace URLs until we get a response here because we may
244*6dbdd20aSAndroid Build Coastguard Worker  // accidentially clober the state of an open trace processor instance
245*6dbdd20aSAndroid Build Coastguard Worker  // otherwise.
246*6dbdd20aSAndroid Build Coastguard Worker  maybeChangeRpcPortFromFragment();
247*6dbdd20aSAndroid Build Coastguard Worker  CheckHttpRpcConnection().then(() => {
248*6dbdd20aSAndroid Build Coastguard Worker    const route = Router.parseUrl(window.location.href);
249*6dbdd20aSAndroid Build Coastguard Worker    if (!AppImpl.instance.embeddedMode) {
250*6dbdd20aSAndroid Build Coastguard Worker      installFileDropHandler();
251*6dbdd20aSAndroid Build Coastguard Worker    }
252*6dbdd20aSAndroid Build Coastguard Worker
253*6dbdd20aSAndroid Build Coastguard Worker    // Don't allow postMessage or opening trace from route when the user says
254*6dbdd20aSAndroid Build Coastguard Worker    // that they want to reuse the already loaded trace in trace processor.
255*6dbdd20aSAndroid Build Coastguard Worker    const traceSource = AppImpl.instance.trace?.traceInfo.source;
256*6dbdd20aSAndroid Build Coastguard Worker    if (traceSource && traceSource.type === 'HTTP_RPC') {
257*6dbdd20aSAndroid Build Coastguard Worker      return;
258*6dbdd20aSAndroid Build Coastguard Worker    }
259*6dbdd20aSAndroid Build Coastguard Worker
260*6dbdd20aSAndroid Build Coastguard Worker    // Add support for opening traces from postMessage().
261*6dbdd20aSAndroid Build Coastguard Worker    window.addEventListener('message', postMessageHandler, {passive: true});
262*6dbdd20aSAndroid Build Coastguard Worker
263*6dbdd20aSAndroid Build Coastguard Worker    // Handles the initial ?local_cache_key=123 or ?s=permalink or ?url=...
264*6dbdd20aSAndroid Build Coastguard Worker    // cases.
265*6dbdd20aSAndroid Build Coastguard Worker    routeChange(route);
266*6dbdd20aSAndroid Build Coastguard Worker  });
267*6dbdd20aSAndroid Build Coastguard Worker
268*6dbdd20aSAndroid Build Coastguard Worker  // Initialize plugins, now that we are ready to go.
269*6dbdd20aSAndroid Build Coastguard Worker  const pluginManager = AppImpl.instance.plugins;
270*6dbdd20aSAndroid Build Coastguard Worker  CORE_PLUGINS.forEach((p) => pluginManager.registerPlugin(p));
271*6dbdd20aSAndroid Build Coastguard Worker  NON_CORE_PLUGINS.forEach((p) => pluginManager.registerPlugin(p));
272*6dbdd20aSAndroid Build Coastguard Worker  const route = Router.parseUrl(window.location.href);
273*6dbdd20aSAndroid Build Coastguard Worker  const overrides = (route.args.enablePlugins ?? '').split(',');
274*6dbdd20aSAndroid Build Coastguard Worker  pluginManager.activatePlugins(overrides);
275*6dbdd20aSAndroid Build Coastguard Worker}
276*6dbdd20aSAndroid Build Coastguard Worker
277*6dbdd20aSAndroid Build Coastguard Worker// If the URL is /#!?rpc_port=1234, change the default RPC port.
278*6dbdd20aSAndroid Build Coastguard Worker// For security reasons, this requires toggling a flag. Detect this and tell the
279*6dbdd20aSAndroid Build Coastguard Worker// user what to do in this case.
280*6dbdd20aSAndroid Build Coastguard Workerfunction maybeChangeRpcPortFromFragment() {
281*6dbdd20aSAndroid Build Coastguard Worker  const route = Router.parseUrl(window.location.href);
282*6dbdd20aSAndroid Build Coastguard Worker  if (route.args.rpc_port !== undefined) {
283*6dbdd20aSAndroid Build Coastguard Worker    if (!CSP_WS_PERMISSIVE_PORT.get()) {
284*6dbdd20aSAndroid Build Coastguard Worker      showModal({
285*6dbdd20aSAndroid Build Coastguard Worker        title: 'Using a different port requires a flag change',
286*6dbdd20aSAndroid Build Coastguard Worker        content: m(
287*6dbdd20aSAndroid Build Coastguard Worker          'div',
288*6dbdd20aSAndroid Build Coastguard Worker          m(
289*6dbdd20aSAndroid Build Coastguard Worker            'span',
290*6dbdd20aSAndroid Build Coastguard Worker            'For security reasons before connecting to a non-standard ' +
291*6dbdd20aSAndroid Build Coastguard Worker              'TraceProcessor port you need to manually enable the flag to ' +
292*6dbdd20aSAndroid Build Coastguard Worker              'relax the Content Security Policy and restart the UI.',
293*6dbdd20aSAndroid Build Coastguard Worker          ),
294*6dbdd20aSAndroid Build Coastguard Worker        ),
295*6dbdd20aSAndroid Build Coastguard Worker        buttons: [
296*6dbdd20aSAndroid Build Coastguard Worker          {
297*6dbdd20aSAndroid Build Coastguard Worker            text: 'Take me to the flags page',
298*6dbdd20aSAndroid Build Coastguard Worker            primary: true,
299*6dbdd20aSAndroid Build Coastguard Worker            action: () => Router.navigate('#!/flags/cspAllowAnyWebsocketPort'),
300*6dbdd20aSAndroid Build Coastguard Worker          },
301*6dbdd20aSAndroid Build Coastguard Worker        ],
302*6dbdd20aSAndroid Build Coastguard Worker      });
303*6dbdd20aSAndroid Build Coastguard Worker    } else {
304*6dbdd20aSAndroid Build Coastguard Worker      HttpRpcEngine.rpcPort = route.args.rpc_port;
305*6dbdd20aSAndroid Build Coastguard Worker    }
306*6dbdd20aSAndroid Build Coastguard Worker  }
307*6dbdd20aSAndroid Build Coastguard Worker}
308*6dbdd20aSAndroid Build Coastguard Worker
309*6dbdd20aSAndroid Build Coastguard Worker// TODO(primiano): this injection is to break a cirular dependency. See
310*6dbdd20aSAndroid Build Coastguard Worker// comment in sql_table_tab_interface.ts. Remove once we add an extension
311*6dbdd20aSAndroid Build Coastguard Worker// point for context menus.
312*6dbdd20aSAndroid Build Coastguard WorkerconfigureExtensions({
313*6dbdd20aSAndroid Build Coastguard Worker  addDebugCounterTrack,
314*6dbdd20aSAndroid Build Coastguard Worker  addDebugSliceTrack,
315*6dbdd20aSAndroid Build Coastguard Worker  addVisualizedArgTracks,
316*6dbdd20aSAndroid Build Coastguard Worker  addSqlTableTab,
317*6dbdd20aSAndroid Build Coastguard Worker  addQueryResultsTab,
318*6dbdd20aSAndroid Build Coastguard Worker});
319*6dbdd20aSAndroid Build Coastguard Worker
320*6dbdd20aSAndroid Build Coastguard Workermain();
321