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