blob: 073e2e39bc062ceb277fb62037ad7f751dc67fd1 [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 './mojo_timestamp.js';
import './expandable_json_viewer.js';
import {CustomElement} from 'chrome://resources/js/custom_element.js';
import type {Value} from 'chrome://resources/mojo/mojo/public/mojom/base/values.mojom-webui.js';
import {getTemplate} from './value_display.html.js';
export type LogicalFn = (v: Value) => HTMLElement|undefined;
export function defaultLogicalFn(_v: Value) {
return undefined;
}
export function timestampLogicalFn(v: Value) {
if (!v.stringValue) {
return undefined;
}
const tsElement = document.createElement('mojo-timestamp');
tsElement.setAttribute('ts', v.stringValue);
return tsElement;
}
// TODO(crbug.com/427549893): Don't use expandable-json-viewer if JSON content
// is {} or [].
export class ValueDisplayElement extends CustomElement {
static override get template() {
return getTemplate();
}
flattenValue(value: Value): any {
if (value.listValue != null) {
return value.listValue.storage.map(v => this.flattenValue(v));
} else if (value.dictionaryValue != null) {
const flattenedDictionary: {[key: string]: any} = {};
for (const [k, v] of Object.entries(value.dictionaryValue.storage)) {
flattenedDictionary[k] = this.flattenValue(v);
}
return flattenedDictionary;
} else {
return value;
}
}
configure(
value: Value, logicalFn: LogicalFn = defaultLogicalFn,
title: string = '') {
const tElem = this.shadowRoot!.querySelector<HTMLElement>(`#type`)!;
const vElem = this.shadowRoot!.querySelector<HTMLElement>(`#value`)!;
const lElem =
this.shadowRoot!.querySelector<HTMLElement>(`#logical-value`)!;
const logicalElem = logicalFn(value);
if (logicalElem !== undefined) {
lElem.classList.add('defined');
lElem.appendChild(logicalElem);
}
if (value.boolValue != null) {
if (value.boolValue) {
vElem.textContent = 'true';
vElem.classList.add('bool-true');
} else {
vElem.textContent = 'false';
vElem.classList.add('bool-false');
}
} else if (value.intValue != null) {
tElem.textContent = '(int)';
vElem.textContent = '' + value.intValue;
} else if (value.stringValue != null) {
tElem.textContent = '(string)';
vElem.textContent = value.stringValue;
} else if (value.nullValue != null) {
vElem.textContent = 'null';
vElem.classList.add('none');
} else if (value.listValue != null || value.dictionaryValue != null) {
// The pre element is used to preserve line breaks and spaces
const jsonValueElement = document.createElement('pre');
jsonValueElement.id = 'json-value';
jsonValueElement.textContent =
JSON.stringify(this.flattenValue(value), null, 2);
const jsonViewerElement =
document.createElement('expandable-json-viewer');
vElem.appendChild(jsonViewerElement);
jsonViewerElement.configure(jsonValueElement, title);
} else if (value.binaryValue != null) {
tElem.textContent = '(binary)';
vElem.textContent = JSON.stringify(value.binaryValue);
} else {
tElem.textContent = '(???)';
vElem.textContent = JSON.stringify(value);
}
}
}
declare global {
interface HTMLElementTagNameMap {
'value-display': ValueDisplayElement;
}
}
customElements.define('value-display', ValueDisplayElement);