chrome-devtools-frontend
Version:
Chrome DevTools UI
156 lines (134 loc) • 4.99 kB
text/typescript
// Copyright 2026 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import * as Common from '../../core/common/common.js';
import type * as Platform from '../../core/platform/platform.js';
export interface SettingUIDescriptor {
/**
* The category with which the setting is displayed in the UI.
*/
category?: Common.SettingRegistration.SettingCategory;
/**
* Used to sort on screen the settings that belong to the same category.
*/
order?: number;
/**
* The title with which the setting is shown on screen.
*/
title?: () => Platform.UIString.LocalizedString;
/**
* Words used to find a setting in the Command Menu.
*/
tags?: Array<() => Platform.UIString.LocalizedString>;
/**
* The possible values the setting can have, each with a description composed of a title and an optional text.
*/
options?: Common.SettingRegistration.SettingExtensionOption[];
/**
* Whether DevTools must be reloaded for a change in the setting to take effect.
*/
reloadRequired?: boolean;
/**
* See {@link LearnMore} for more info.
*/
learnMore?: Common.SettingRegistration.LearnMore;
}
export interface RegisteredSettingUI {
descriptor: Common.Settings.SettingDescriptor<unknown>;
uiDescriptor: SettingUIDescriptor;
}
const registeredSettings = new Map<string, RegisteredSettingUI>();
export function register(
settingDescriptor: Common.Settings.SettingDescriptor<unknown>,
settingUIDescriptor: SettingUIDescriptor,
): void {
const settingName = settingDescriptor.name;
if (registeredSettings.has(settingName)) {
throw new Error(`Duplicate setting name '${settingName}'`);
}
Common.SettingRegistration.registerCategoryOrder(settingUIDescriptor.category, settingUIDescriptor.order);
registeredSettings.set(settingName, {descriptor: settingDescriptor, uiDescriptor: settingUIDescriptor});
}
export function getRegisteredSettings(): readonly RegisteredSettingUI[] {
const combined = new Map<string, RegisteredSettingUI>();
for (const legacy of Common.SettingRegistration.getRegisteredSettings()) {
combined.set(legacy.settingName, {
descriptor: {
name: legacy.settingName,
type: legacy.settingType,
defaultValue: legacy.defaultValue,
storageType: legacy.storageType,
},
uiDescriptor: {
category: legacy.category,
order: legacy.order,
title: legacy.title,
tags: legacy.tags,
options: legacy.options,
reloadRequired: legacy.reloadRequired,
learnMore: legacy.learnMore,
},
});
}
for (const [name, registeredUI] of registeredSettings) {
combined.set(name, registeredUI);
}
return Array.from(combined.values());
}
export interface SimpleSettingOption {
value: string|boolean;
title: Platform.UIString.LocalizedString;
text?: Platform.UIString.LocalizedString|string;
raw?: boolean;
}
export class SettingUI {
readonly #raw: SettingUIDescriptor;
constructor(raw: SettingUIDescriptor) {
this.#raw = raw;
}
get title(): Platform.UIString.LocalizedString {
return this.#raw.title?.() ?? ('' as Platform.UIString.LocalizedString);
}
get category(): Common.SettingRegistration.SettingCategory|null {
return this.#raw.category ?? null;
}
get order(): number|null {
return this.#raw.order ?? null;
}
get tags(): string {
return this.#raw.tags ? this.#raw.tags.map(tag => tag()).join('\0') : '';
}
get options(): SimpleSettingOption[] {
return this.#raw.options?.map(opt => ({
value: opt.value,
title: opt.title(),
text: typeof opt.text === 'function' ? opt.text() : opt.text,
raw: opt.raw,
})) ??
[];
}
get reloadRequired(): boolean {
return Boolean(this.#raw.reloadRequired);
}
get learnMore(): Common.SettingRegistration.LearnMore|null {
return this.#raw.learnMore ?? null;
}
}
export function maybeResolve(settingDescriptor: Common.Settings.SettingDescriptor<unknown>): SettingUI|null {
const settingUI = registeredSettings.get(settingDescriptor.name) ??
getRegisteredSettings().find(registered => registered.descriptor.name === settingDescriptor.name);
return settingUI ? new SettingUI(settingUI.uiDescriptor) : null;
}
export function resolve(settingDescriptor: Common.Settings.SettingDescriptor<unknown>): SettingUI {
const ui = maybeResolve(settingDescriptor);
if (!ui) {
throw new Error(`No UI descriptor registered for setting '${settingDescriptor.name}'`);
}
return ui;
}
export function resetSettings(): void {
for (const {uiDescriptor} of registeredSettings.values()) {
Common.SettingRegistration.removeCategoryOrder(uiDescriptor.category, uiDescriptor.order);
}
registeredSettings.clear();
}