blob: e9c7779a8c9bd6955f08bcdee030a1547c9aacd0 [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import './tracing_scenario.js';
import '//resources/cr_elements/cr_button/cr_button.js';
import '//resources/cr_elements/cr_toast/cr_toast.js';
import '//resources/cr_elements/cr_toggle/cr_toggle.js';
import type {CrToastElement} from '//resources/cr_elements/cr_toast/cr_toast.js';
// <if expr="is_win">
import type {CrToggleElement} from '//resources/cr_elements/cr_toggle/cr_toggle.js';
// </if>
import {CrLitElement} from '//resources/lit/v3_0/lit.rollup.js';
import type {BigBuffer} from '//resources/mojo/mojo/public/mojom/base/big_buffer.mojom-webui.js';
import {TracesBrowserProxy} from './traces_browser_proxy.js';
import type {Scenario} from './traces_internals.mojom-webui.js';
import {getCss} from './tracing_scenarios_config.css.js';
import {getHtml} from './tracing_scenarios_config.html.js';
export interface TracingScenariosConfigElement {
$: {
toast: CrToastElement,
};
}
export class TracingScenariosConfigElement extends CrLitElement {
static get is() {
return 'tracing-scenarios-config';
}
static override get styles() {
return getCss();
}
override render() {
return getHtml.bind(this)();
}
static override get properties() {
return {
enabledScenarios_: {type: Object},
localConfig_: {type: Array},
fieldConfig_: {type: Array},
isLoading_: {type: Boolean},
privacyFilterEnabled_: {type: Boolean},
toastMessage_: {type: String},
// <if expr="is_win">
tracingServiceSupported_: {type: Boolean},
tracingServiceRegistered_: {type: Boolean},
// </if>
};
}
private traceReportProxy_: TracesBrowserProxy =
TracesBrowserProxy.getInstance();
private refreshIntervalId_: number = 0;
protected accessor enabledScenarios_: {[id: string]: boolean} = {};
protected accessor localConfig_: Scenario[] = [];
protected accessor fieldConfig_: Scenario[] = [];
protected accessor isLoading_: boolean = false;
protected accessor privacyFilterEnabled_: boolean = false;
protected accessor toastMessage_: string = '';
// <if expr="is_win">
protected accessor tracingServiceSupported_: boolean = false;
protected accessor tracingServiceRegistered_: boolean = false;
protected securityShieldIconUrl_: string = '';
// </if>
override connectedCallback(): void {
super.connectedCallback();
this.initializeConfig_();
}
override disconnectedCallback(): void {
super.disconnectedCallback();
clearInterval(this.refreshIntervalId_);
}
protected async initializeConfig_(): Promise<void> {
this.isLoading_ = true;
await this.loadScenariosConfig_();
this.privacyFilterEnabled_ =
(await this.traceReportProxy_.handler.getPrivacyFilterEnabled())
.enabled;
// <if expr="is_win">
const {
serviceSupported: serviceSupported,
serviceRegistered: serviceRegistered,
} = await this.traceReportProxy_.handler.getSystemTracingState();
this.tracingServiceSupported_ = serviceSupported;
this.tracingServiceRegistered_ = serviceRegistered;
if (this.tracingServiceSupported_) {
this.securityShieldIconUrl_ =
(await this.traceReportProxy_.handler.getSecurityShieldIconUrl())
.shieldIconUrl.url;
}
// </if>
this.isLoading_ = false;
this.refreshIntervalId_ =
setInterval(this.loadScenariosConfig_.bind(this), 1000);
}
protected async loadScenariosConfig_(): Promise<void> {
const {config: scenarios} =
await this.traceReportProxy_.handler.getAllScenarios();
this.localConfig_ = [];
this.fieldConfig_ = [];
for (const scenario of scenarios) {
if (scenario.isLocalScenario) {
this.localConfig_.push(scenario);
} else {
this.fieldConfig_.push(scenario);
}
}
}
protected isScenarioEnabled_(scenario: Scenario) {
return this.enabledScenarios_[scenario.scenarioName] ?? scenario.isEnabled;
}
protected async privacyFilterDidChange_(event: CustomEvent<boolean>):
Promise<void> {
if (this.privacyFilterEnabled_ === event.detail) {
return;
}
this.privacyFilterEnabled_ = event.detail;
await this.traceReportProxy_.handler.setPrivacyFilterEnabled(
this.privacyFilterEnabled_);
}
protected valueDidChange_(event: CustomEvent<{value: boolean}>): void {
const key = (event.currentTarget as HTMLElement).dataset['key'];
if (key === undefined) {
return;
}
this.enabledScenarios_[key] = event.detail.value;
}
protected onCancelClick_() {
this.enabledScenarios_ = {};
}
protected async onConfirmClick_(): Promise<void> {
const enabledScenarios: string[] = [];
for (const scenario of this.localConfig_) {
if (this.enabledScenarios_[scenario.scenarioName] ?? scenario.isEnabled) {
enabledScenarios.push(scenario.scenarioName);
}
}
const {success} = await this.traceReportProxy_.handler.setEnabledScenarios(
enabledScenarios);
if (!success) {
this.toastMessage_ = 'Failed to update scenarios config';
this.$.toast.show();
return;
}
await this.loadScenariosConfig_();
this.enabledScenarios_ = {};
}
protected async onAddConfig_(e: Event&
{target: HTMLInputElement}): Promise<void> {
const files = e.target.files;
if (!files) {
this.toastMessage_ = `Failed to open config file.`;
this.$.toast.show();
return;
}
for (const file of files) {
const result = await this.processConfigFile_(file);
if (!result.success) {
this.toastMessage_ = `Failed to read config file ${file.name}.`;
this.$.toast.show();
}
}
await this.loadScenariosConfig_();
}
private async processConfigFile_(file: File): Promise<{success: boolean}> {
const isTextFile = (file.type === 'text/plain');
const handler = this.traceReportProxy_.handler;
if (isTextFile) {
const text = await file.text();
return handler.setScenariosConfigFromString(text);
} else {
const bytes = await file.arrayBuffer();
const buffer: BigBuffer = {bytes: Array.from(new Uint8Array(bytes))} as
any;
return handler.setScenariosConfigFromBuffer(buffer);
}
}
protected async resetAllClick_(): Promise<void> {
const {success} =
await this.traceReportProxy_.handler.setEnabledScenarios([]);
if (!success) {
this.toastMessage_ = 'Failed to reset scenarios';
this.$.toast.show();
return;
}
await this.loadScenariosConfig_();
this.enabledScenarios_ = {};
}
// <if expr="is_win">
protected async onSystemTracingChange_(e: CustomEvent<boolean>) {
const enable = e.detail;
if (enable === this.tracingServiceRegistered_) {
return;
}
const target = (e.target as CrToggleElement);
const {success} = enable ?
await this.traceReportProxy_.handler.enableSystemTracing() :
await this.traceReportProxy_.handler.disableSystemTracing();
if (success) {
// On success, update the instance's registration state.
this.tracingServiceRegistered_ = enable;
} else if (target) {
// On failure, put the toggle back to its previous state.
target.checked = !enable;
}
}
// </if>
}
declare global {
interface HTMLElementTagNameMap {
'tracing-scenarios-config': TracingScenariosConfigElement;
}
}
customElements.define(
TracingScenariosConfigElement.is, TracingScenariosConfigElement);