• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2024 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15import {bindMithrilAttrs} from '../../base/mithril_utils';
16import {App} from '../../public/app';
17import {PerfettoPlugin} from '../../public/plugin';
18import {AdbWebsocketTargetProvider} from './adb/websocket/adb_websocket_target_provider';
19import {AdbWebusbTargetProvider} from './adb/webusb/adb_webusb_target_provider';
20import {ChromeExtensionTargetProvider} from './chrome/chrome_extension_target_provider';
21import {advancedRecordSection} from './pages/advanced';
22import {androidRecordSection} from './pages/android';
23import {bufferConfigPage} from './pages/buffer_config_page';
24import {chromeRecordSection} from './pages/chrome';
25import {instructionsPage} from './pages/instructions_page';
26import {cpuRecordSection} from './pages/cpu';
27import {gpuRecordSection} from './pages/gpu';
28import {memoryRecordSection} from './pages/memory';
29import {powerRecordSection} from './pages/power';
30import {RecordPageV2} from './pages/record_page';
31import {stackSamplingRecordSection} from './pages/stack_sampling';
32import {targetSelectionPage} from './pages/target_selection_page';
33import {RecordingManager} from './recording_manager';
34import {TracedWebsocketTargetProvider} from './traced_over_websocket/traced_websocket_provider';
35import {savedConfigsPage} from './pages/saved_configs';
36import {WebDeviceProxyTargetProvider} from './adb/web_device_proxy/wdp_target_provider';
37
38export default class implements PerfettoPlugin {
39  static readonly id = 'dev.perfetto.RecordTraceV2';
40  private static recordingMgr?: RecordingManager;
41
42  static onActivate(app: App) {
43    app.sidebar.addMenuItem({
44      section: 'navigation',
45      text: 'Record new trace',
46      href: '#!/record',
47      icon: 'fiber_smart_record',
48      sortOrder: 2,
49    });
50    app.pages.registerPage({
51      route: '/record',
52      traceless: true,
53      page: bindMithrilAttrs(RecordPageV2, {
54        getRecordingManager: this.getRecordingManager.bind(this, app),
55      }),
56    });
57  }
58
59  // Lazily initialize the RecordingManager at first call. This is to prevent
60  // providers to connect to sockets / devtools (which in turn can trigger
61  // security UX in the browser) before the user has even done anything.
62  private static getRecordingManager(app: App): RecordingManager {
63    if (this.recordingMgr === undefined) {
64      const recMgr = new RecordingManager(app);
65      this.recordingMgr = recMgr;
66      recMgr.registerProvider(new AdbWebusbTargetProvider());
67      recMgr.registerProvider(new AdbWebsocketTargetProvider());
68      recMgr.registerProvider(new WebDeviceProxyTargetProvider());
69
70      const chromeProvider = new ChromeExtensionTargetProvider();
71      recMgr.registerProvider(chromeProvider);
72      recMgr.registerProvider(new TracedWebsocketTargetProvider());
73      recMgr.registerPage(
74        targetSelectionPage(recMgr),
75        bufferConfigPage(recMgr),
76        instructionsPage(recMgr),
77        savedConfigsPage(recMgr),
78
79        chromeRecordSection(() => chromeProvider.getChromeCategories()),
80        cpuRecordSection(),
81        gpuRecordSection(),
82        powerRecordSection(),
83        memoryRecordSection(),
84        androidRecordSection(),
85        stackSamplingRecordSection(),
86        advancedRecordSection(),
87      );
88      recMgr.restorePluginStateFromLocalstorage();
89    }
90
91    // For devtools debugging purposes.
92    (window as {} as {recordingMgr: unknown}).recordingMgr = this.recordingMgr;
93    return this.recordingMgr;
94  }
95}
96