blob: 560f0322d60b806e8f04e835f195114f6c9ffe80 [file] [log] [blame]
// Copyright (C) 2022 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import m from 'mithril';
import {
RecordingPageController,
} from '../../common/recordingV2/recording_page_controller';
import {EXTENSION_URL} from '../../common/recordingV2/recording_utils';
import {
CHROME_TARGET_FACTORY,
ChromeTargetFactory,
} from '../../common/recordingV2/target_factories/chrome_target_factory';
import {
targetFactoryRegistry,
} from '../../common/recordingV2/target_factory_registry';
import {
WebsocketMenuController,
} from '../../common/recordingV2/websocket_menu_controller';
import {fullscreenModalContainer, ModalDefinition} from '../modal';
import {CodeSnippet} from '../record_widgets';
import {RecordingMultipleChoice} from './recording_multiple_choice';
const RUN_WEBSOCKET_CMD = '# Get tracebox\n' +
'curl -LO https://get.perfetto.dev/tracebox\n' +
'chmod +x ./tracebox\n' +
'# Option A - trace android devices\n' +
'adb start-server\n' +
'# Option B - trace the host OS\n' +
'./tracebox traced --background\n' +
'./tracebox traced_probes --background\n' +
'# Start the websocket server\n' +
'./tracebox websocket_bridge\n';
export function addNewTarget(recordingPageController: RecordingPageController):
ModalDefinition {
const components = [];
components.push(m('text', 'Select platform:'));
components.push(assembleWebusbSection(recordingPageController));
components.push(m('.line'));
components.push(assembleWebsocketSection(recordingPageController));
components.push(m('.line'));
components.push(assembleChromeSection(recordingPageController));
return {
title: 'Add new recording target',
content: m('.record-modal', components),
};
}
function assembleWebusbSection(
recordingPageController: RecordingPageController): m.Vnode {
return m(
'.record-modal-section',
m('.logo-wrapping', m('i.material-icons', 'usb')),
m('.record-modal-description',
m('h3', 'Android device over WebUSB'),
m('text',
'Android developers: this option cannot co-operate ' +
'with the adb host on your machine. Only one entity between ' +
'the browser and adb can control the USB endpoint. If adb is ' +
'running, you will be prompted to re-assign the device to the ' +
'browser. Use the websocket option below to use both ' +
'simultaneously.'),
m('.record-modal-button',
{
onclick: () => {
fullscreenModalContainer.close();
recordingPageController.addAndroidDevice();
},
},
'Connect new WebUSB driver')));
}
function assembleWebsocketSection(
recordingPageController: RecordingPageController): m.Vnode {
const websocketComponents = [];
websocketComponents.push(
m('h3', 'Android / Linux / MacOS device via Websocket'));
websocketComponents.push(
m('text',
'This option assumes that the adb server is already ' +
'running on your machine.'),
m('.record-modal-command', m(CodeSnippet, {
text: RUN_WEBSOCKET_CMD,
})));
websocketComponents.push(m(
'.record-modal-command',
m('text', 'Websocket bridge address: '),
m('input[type=text]', {
value: websocketMenuController.getPath(),
oninput() {
websocketMenuController.setPath(this.value);
},
}),
m('.record-modal-logo-button',
{
onclick: () => websocketMenuController.onPathChange(),
},
m('i.material-icons', 'refresh')),
));
websocketComponents.push(m(RecordingMultipleChoice, {
controller: recordingPageController,
targetFactories: websocketMenuController.getTargetFactories(),
}));
return m(
'.record-modal-section',
m('.logo-wrapping', m('i.material-icons', 'settings_ethernet')),
m('.record-modal-description', ...websocketComponents));
}
function assembleChromeSection(
recordingPageController: RecordingPageController): m.Vnode|undefined {
if (!targetFactoryRegistry.has(CHROME_TARGET_FACTORY)) {
return undefined;
}
const chromeComponents = [];
chromeComponents.push(m('h3', 'Chrome Browser instance or ChromeOS device'));
const chromeFactory: ChromeTargetFactory =
targetFactoryRegistry.get(CHROME_TARGET_FACTORY) as ChromeTargetFactory;
if (!chromeFactory.isExtensionInstalled) {
chromeComponents.push(
m('text',
'Install the extension ',
m('a', {href: EXTENSION_URL, target: '_blank'}, 'from this link '),
'and refresh the page.'));
} else {
chromeComponents.push(m(RecordingMultipleChoice, {
controller: recordingPageController,
targetFactories: [chromeFactory],
}));
}
return m(
'.record-modal-section',
m('.logo-wrapping', m('i.material-icons', 'web')),
m('.record-modal-description', ...chromeComponents));
}
const websocketMenuController = new WebsocketMenuController();