chrome-devtools-frontend 1.0.953776 → 1.0.954427

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/config/gni/devtools_grd_files.gni +1 -0
  2. package/front_end/core/common/Settings.ts +10 -0
  3. package/front_end/core/i18n/locales/en-US.json +4 -16
  4. package/front_end/core/i18n/locales/en-XL.json +4 -16
  5. package/front_end/core/platform/number-utilities.ts +5 -7
  6. package/front_end/core/platform/string-utilities.ts +45 -205
  7. package/front_end/core/sdk/EmulationModel.ts +18 -19
  8. package/front_end/core/sdk/ResourceTreeModel.ts +12 -2
  9. package/front_end/core/sdk/sdk-meta.ts +2 -39
  10. package/front_end/entrypoints/inspector_main/RenderingOptions.ts +13 -9
  11. package/front_end/generated/InspectorBackendCommands.js +3 -1
  12. package/front_end/generated/protocol.d.ts +19 -0
  13. package/front_end/models/extensions/ExtensionServer.ts +2 -3
  14. package/front_end/panels/application/components/BackForwardCacheView.ts +6 -4
  15. package/front_end/panels/application/storageView.css +1 -1
  16. package/front_end/panels/console/ConsoleFormat.ts +197 -0
  17. package/front_end/panels/console/ConsoleViewMessage.ts +54 -155
  18. package/front_end/panels/console/console.ts +3 -0
  19. package/front_end/panels/elements/components/AdornerSettingsPane.ts +2 -1
  20. package/front_end/panels/elements/components/LayoutPane.ts +2 -0
  21. package/front_end/panels/elements/elementStatePaneWidget.css +1 -1
  22. package/front_end/panels/elements/layoutPane.css +0 -4
  23. package/front_end/panels/emulation/components/DeviceSizeInputElement.ts +5 -1
  24. package/front_end/panels/settings/emulation/components/UserAgentClientHintsForm.ts +2 -1
  25. package/front_end/panels/sources/SourcesPanel.ts +1 -1
  26. package/front_end/panels/web_audio/webAudio.css +1 -1
  27. package/front_end/ui/components/linear_memory_inspector/ValueInterpreterSettings.ts +2 -1
  28. package/front_end/ui/components/settings/SettingCheckbox.ts +3 -2
  29. package/front_end/ui/legacy/SettingsUI.ts +1 -0
  30. package/front_end/ui/legacy/themeColors.css +2 -2
  31. package/front_end/ui/legacy/treeoutline.css +1 -1
  32. package/package.json +1 -1
@@ -845,6 +845,7 @@ grd_files_debug_sources = [
845
845
  "front_end/panels/changes/changesView.css.js",
846
846
  "front_end/panels/console/ConsoleContextSelector.js",
847
847
  "front_end/panels/console/ConsoleFilter.js",
848
+ "front_end/panels/console/ConsoleFormat.js",
848
849
  "front_end/panels/console/ConsolePanel.js",
849
850
  "front_end/panels/console/ConsolePinPane.js",
850
851
  "front_end/panels/console/ConsolePrompt.js",
@@ -290,6 +290,7 @@ export class Setting<V> {
290
290
  // TODO(crbug.com/1172300) Type cannot be inferred without changes to consumers. See above.
291
291
  #serializer: Serializer<unknown, V> = JSON;
292
292
  #hadUserAction?: boolean;
293
+ #disabled?: boolean;
293
294
 
294
295
  constructor(
295
296
  readonly name: string, readonly defaultValue: V, private readonly eventSupport: ObjectWrapper<GenericEvents>,
@@ -333,6 +334,15 @@ export class Setting<V> {
333
334
  this.#requiresUserAction = requiresUserAction;
334
335
  }
335
336
 
337
+ disabled(): boolean {
338
+ return this.#disabled || false;
339
+ }
340
+
341
+ setDisabled(disabled: boolean): void {
342
+ this.#disabled = disabled;
343
+ this.eventSupport.dispatchEventToListeners(this.name);
344
+ }
345
+
336
346
  get(): V {
337
347
  if (this.#requiresUserAction && !this.#hadUserAction) {
338
348
  return this.defaultValue;
@@ -581,12 +581,6 @@
581
581
  "core/sdk/sdk-meta.ts | disableCache": {
582
582
  "message": "Disable cache (while DevTools is open)"
583
583
  },
584
- "core/sdk/sdk-meta.ts | disabledDarkMode": {
585
- "message": "Disable"
586
- },
587
- "core/sdk/sdk-meta.ts | disableEmulateAutoDarkMode": {
588
- "message": "Disable auto dark mode"
589
- },
590
584
  "core/sdk/sdk-meta.ts | disableJavascript": {
591
585
  "message": "Disable JavaScript"
592
586
  },
@@ -617,9 +611,6 @@
617
611
  "core/sdk/sdk-meta.ts | doNotEmulateCssMediaType": {
618
612
  "message": "Do not emulate CSS media type"
619
613
  },
620
- "core/sdk/sdk-meta.ts | doNotEmulateDarkMode": {
621
- "message": "Do not emulate auto dark mode"
622
- },
623
614
  "core/sdk/sdk-meta.ts | doNotExtendGridLines": {
624
615
  "message": "Do not extend grid lines"
625
616
  },
@@ -689,12 +680,6 @@
689
680
  "core/sdk/sdk-meta.ts | enableCustomFormatters": {
690
681
  "message": "Enable custom formatters"
691
682
  },
692
- "core/sdk/sdk-meta.ts | enabledDarkMode": {
693
- "message": "Enable"
694
- },
695
- "core/sdk/sdk-meta.ts | enableEmulateAutoDarkMode": {
696
- "message": "Enable auto dark mode"
697
- },
698
683
  "core/sdk/sdk-meta.ts | enableJavascript": {
699
684
  "message": "Enable JavaScript"
700
685
  },
@@ -947,11 +932,14 @@
947
932
  "entrypoints/inspector_main/RenderingOptions.ts | emulateAFocusedPage": {
948
933
  "message": "Emulate a focused page"
949
934
  },
935
+ "entrypoints/inspector_main/RenderingOptions.ts | emulateAutoDarkMode": {
936
+ "message": "Enable automatic dark mode"
937
+ },
950
938
  "entrypoints/inspector_main/RenderingOptions.ts | emulatesAFocusedPage": {
951
939
  "message": "Emulates a focused page."
952
940
  },
953
941
  "entrypoints/inspector_main/RenderingOptions.ts | emulatesAutoDarkMode": {
954
- "message": "Enables automatic dark mode for the inspected page."
942
+ "message": "Enables automatic dark mode and sets prefers-color-scheme to dark."
955
943
  },
956
944
  "entrypoints/inspector_main/RenderingOptions.ts | forcesCssColorgamutMediaFeature": {
957
945
  "message": "Forces CSS color-gamut media feature"
@@ -581,12 +581,6 @@
581
581
  "core/sdk/sdk-meta.ts | disableCache": {
582
582
  "message": "D̂íŝáb̂ĺê ćâćĥé (ŵh́îĺê D́êv́T̂óôĺŝ íŝ óp̂én̂)"
583
583
  },
584
- "core/sdk/sdk-meta.ts | disabledDarkMode": {
585
- "message": "D̂íŝáb̂ĺê"
586
- },
587
- "core/sdk/sdk-meta.ts | disableEmulateAutoDarkMode": {
588
- "message": "D̂íŝáb̂ĺê áût́ô d́âŕk̂ ḿôd́ê"
589
- },
590
584
  "core/sdk/sdk-meta.ts | disableJavascript": {
591
585
  "message": "D̂íŝáb̂ĺê J́âv́âŚĉŕîṕt̂"
592
586
  },
@@ -617,9 +611,6 @@
617
611
  "core/sdk/sdk-meta.ts | doNotEmulateCssMediaType": {
618
612
  "message": "D̂ó n̂ót̂ ém̂úl̂át̂é ĈŚŜ ḿêd́îá t̂ýp̂é"
619
613
  },
620
- "core/sdk/sdk-meta.ts | doNotEmulateDarkMode": {
621
- "message": "D̂ó n̂ót̂ ém̂úl̂át̂é âút̂ó d̂ár̂ḱ m̂ód̂é"
622
- },
623
614
  "core/sdk/sdk-meta.ts | doNotExtendGridLines": {
624
615
  "message": "D̂ó n̂ót̂ éx̂t́êńd̂ ǵr̂íd̂ ĺîńêś"
625
616
  },
@@ -689,12 +680,6 @@
689
680
  "core/sdk/sdk-meta.ts | enableCustomFormatters": {
690
681
  "message": "Êńâb́l̂é ĉúŝt́ôḿ f̂ór̂ḿât́t̂ér̂ś"
691
682
  },
692
- "core/sdk/sdk-meta.ts | enabledDarkMode": {
693
- "message": "Êńâb́l̂é"
694
- },
695
- "core/sdk/sdk-meta.ts | enableEmulateAutoDarkMode": {
696
- "message": "Êńâb́l̂é âút̂ó d̂ár̂ḱ m̂ód̂é"
697
- },
698
683
  "core/sdk/sdk-meta.ts | enableJavascript": {
699
684
  "message": "Êńâb́l̂é Ĵáv̂áŜćr̂íp̂t́"
700
685
  },
@@ -947,11 +932,14 @@
947
932
  "entrypoints/inspector_main/RenderingOptions.ts | emulateAFocusedPage": {
948
933
  "message": "Êḿûĺât́ê á f̂óĉúŝéd̂ ṕâǵê"
949
934
  },
935
+ "entrypoints/inspector_main/RenderingOptions.ts | emulateAutoDarkMode": {
936
+ "message": "Êńâb́l̂é âút̂óm̂át̂íĉ d́âŕk̂ ḿôd́ê"
937
+ },
950
938
  "entrypoints/inspector_main/RenderingOptions.ts | emulatesAFocusedPage": {
951
939
  "message": "Êḿûĺât́êś â f́ôćûśêd́ p̂áĝé."
952
940
  },
953
941
  "entrypoints/inspector_main/RenderingOptions.ts | emulatesAutoDarkMode": {
954
- "message": "Êńâb́l̂éŝ áût́ôḿât́îć d̂ár̂ḱ m̂ód̂é f̂ór̂ t́é îńŝṕêćt̂éd̂ ṕâǵê."
942
+ "message": "Êńâb́l̂éŝ áût́ôḿât́îć d̂ár̂ḱ m̂ód̂é âńd̂ śêt́ŝ prefers-color-scheme ô dark."
955
943
  },
956
944
  "entrypoints/inspector_main/RenderingOptions.ts | forcesCssColorgamutMediaFeature": {
957
945
  "message": "F̂ór̂ćêś ĈŚŜ color-gamut ḿêd́îá f̂éât́ûŕê"
@@ -2,8 +2,6 @@
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
4
 
5
- import * as StringUtilities from './string-utilities.js';
6
-
7
5
  export const clamp = (num: number, min: number, max: number): number => {
8
6
  let clampedNumber = num;
9
7
  if (num < min) {
@@ -20,22 +18,22 @@ export const mod = (m: number, n: number): number => {
20
18
 
21
19
  export const bytesToString = (bytes: number): string => {
22
20
  if (bytes < 1000) {
23
- return StringUtilities.vsprintf('%.0f\xA0B', [bytes]);
21
+ return `${bytes.toFixed(0)}\xA0B`;
24
22
  }
25
23
 
26
24
  const kilobytes = bytes / 1000;
27
25
  if (kilobytes < 100) {
28
- return StringUtilities.vsprintf('%.1f\xA0kB', [kilobytes]);
26
+ return `${kilobytes.toFixed(1)}\xA0kB`;
29
27
  }
30
28
  if (kilobytes < 1000) {
31
- return StringUtilities.vsprintf('%.0f\xA0kB', [kilobytes]);
29
+ return `${kilobytes.toFixed(0)}\xA0kB`;
32
30
  }
33
31
 
34
32
  const megabytes = kilobytes / 1000;
35
33
  if (megabytes < 100) {
36
- return StringUtilities.vsprintf('%.1f\xA0MB', [megabytes]);
34
+ return `${megabytes.toFixed(1)}\xA0MB`;
37
35
  }
38
- return StringUtilities.vsprintf('%.0f\xA0MB', [megabytes]);
36
+ return `${megabytes.toFixed(0)}\xA0MB`;
39
37
  };
40
38
 
41
39
  export const toFixedIfFloating = (value: string): string => {
@@ -26,205 +26,6 @@ export const escapeCharacters = (inputString: string, charsToEscape: string): st
26
26
  return result;
27
27
  };
28
28
 
29
- export const enum FormatterType {
30
- STRING = 'string',
31
- SPECIFIER = 'specifier',
32
- }
33
-
34
- export interface FormatterToken {
35
- type: FormatterType;
36
- value?: string|{description: string};
37
- specifier?: string;
38
- precision?: number;
39
- substitutionIndex?: number;
40
- }
41
-
42
- export const tokenizeFormatString = function(
43
- formatString: string, formatters: Record<string, Function>): FormatterToken[] {
44
- const tokens: FormatterToken[] = [];
45
-
46
- function addStringToken(str: string): void {
47
- if (!str) {
48
- return;
49
- }
50
- if (tokens.length && tokens[tokens.length - 1].type === FormatterType.STRING) {
51
- tokens[tokens.length - 1].value += str;
52
- } else {
53
- tokens.push({
54
- type: FormatterType.STRING,
55
- value: str,
56
- });
57
- }
58
- }
59
-
60
- function addSpecifierToken(specifier: string, precision: number, substitutionIndex: number): void {
61
- tokens.push({type: FormatterType.SPECIFIER, specifier, precision, substitutionIndex, value: undefined});
62
- }
63
-
64
- function addAnsiColor(code: number): void {
65
- type ColorType = 'color'|'colorLight'|'bgColor'|'bgColorLight';
66
-
67
- const types: Record<number, ColorType> = {3: 'color', 9: 'colorLight', 4: 'bgColor', 10: 'bgColorLight'};
68
- const colorCodes = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'lightGray', '', 'default'];
69
- const colorCodesLight =
70
- ['darkGray', 'lightRed', 'lightGreen', 'lightYellow', 'lightBlue', 'lightMagenta', 'lightCyan', 'white', ''];
71
- const colors: Record<ColorType, string[]> =
72
- {color: colorCodes, colorLight: colorCodesLight, bgColor: colorCodes, bgColorLight: colorCodesLight};
73
- const type = types[Math.floor(code / 10)] as ColorType;
74
- if (!type) {
75
- return;
76
- }
77
- const color = colors[type][code % 10];
78
- if (!color) {
79
- return;
80
- }
81
- tokens.push({
82
- type: FormatterType.SPECIFIER,
83
- specifier: 'c',
84
- value: {description: (type.startsWith('bg') ? 'background : ' : 'color: ') + color},
85
- precision: undefined,
86
- substitutionIndex: undefined,
87
- });
88
- }
89
-
90
- let textStart = 0;
91
- let substitutionIndex = 0;
92
- const re =
93
- new RegExp(`%%|%(?:(\\d+)\\$)?(?:\\.(\\d*))?([${Object.keys(formatters).join('')}])|\\u001b\\[(\\d+)m`, 'g');
94
- for (let match = re.exec(formatString); match !== null; match = re.exec(formatString)) {
95
- const matchStart = match.index;
96
- if (matchStart > textStart) {
97
- addStringToken(formatString.substring(textStart, matchStart));
98
- }
99
-
100
- if (match[0] === '%%') {
101
- addStringToken('%');
102
- } else if (match[0].startsWith('%')) {
103
- const [, substitionString, precisionString, specifierString] = match;
104
- if (substitionString && Number(substitionString) > 0) {
105
- substitutionIndex = Number(substitionString) - 1;
106
- }
107
- const precision = precisionString ? Number(precisionString) : -1;
108
- addSpecifierToken(specifierString, precision, substitutionIndex);
109
- ++substitutionIndex;
110
- } else {
111
- const code = Number(match[4]);
112
- addAnsiColor(code);
113
- }
114
- textStart = matchStart + match[0].length;
115
- }
116
- addStringToken(formatString.substring(textStart));
117
- return tokens;
118
- };
119
-
120
- export type FormatterFunction<T> = (input: string|{description: string}|undefined|T, token: FormatterToken) => unknown;
121
-
122
- export const format = function<T, U>(
123
- formatString: string, substitutions: ArrayLike<U>|null, formatters: Record<string, FormatterFunction<U>>,
124
- initialValue: T, append: (initialValue: T, newString: string) => T, tokenizedFormat?: FormatterToken[]): {
125
- formattedResult: T,
126
- unusedSubstitutions: ArrayLike<U>|null,
127
- } {
128
- if (!formatString || ((!substitutions || !substitutions.length) && formatString.search(/\u001b\[(\d+)m/) === -1)) {
129
- return {formattedResult: append(initialValue, formatString), unusedSubstitutions: substitutions};
130
- }
131
-
132
- function prettyFunctionName(): string {
133
- return 'String.format("' + formatString + '", "' + Array.prototype.join.call(substitutions, '", "') + '")';
134
- }
135
-
136
- function warn(msg: string): void {
137
- console.warn(prettyFunctionName() + ': ' + msg);
138
- }
139
-
140
- function error(msg: string): void {
141
- console.error(prettyFunctionName() + ': ' + msg);
142
- }
143
-
144
- let result = initialValue;
145
- const tokens = tokenizedFormat || tokenizeFormatString(formatString, formatters);
146
- const usedSubstitutionIndexes: Record<number, boolean> = {};
147
- const actualSubstitutions: ArrayLike<U> = substitutions || [];
148
-
149
- for (const token of tokens) {
150
- if (token.type === FormatterType.STRING) {
151
- result = append(result, token.value as string);
152
- continue;
153
- }
154
-
155
- if (token.type !== FormatterType.SPECIFIER) {
156
- error('Unknown token type "' + token.type + '" found.');
157
- continue;
158
- }
159
-
160
- if (!token.value && token.substitutionIndex !== undefined &&
161
- token.substitutionIndex >= actualSubstitutions.length) {
162
- // If there are not enough substitutions for the current substitutionIndex
163
- // just output the format specifier literally and move on.
164
- error(
165
- 'not enough substitution arguments. Had ' + actualSubstitutions.length + ' but needed ' +
166
- (token.substitutionIndex + 1) + ', so substitution was skipped.');
167
- result = append(
168
- result,
169
- '%' + ((token.precision !== undefined && token.precision > -1) ? token.precision : '') + token.specifier);
170
- continue;
171
- }
172
-
173
- if (!token.value && token.substitutionIndex !== undefined) {
174
- usedSubstitutionIndexes[token.substitutionIndex] = true;
175
- }
176
-
177
- if (token.specifier === undefined || !(token.specifier in formatters)) {
178
- // Encountered an unsupported format character, treat as a string.
179
- warn('unsupported format character \u201C' + token.specifier + '\u201D. Treating as a string.');
180
- const stringToAppend = (token.value || token.substitutionIndex === undefined) ?
181
- '' :
182
- String(actualSubstitutions[token.substitutionIndex]);
183
- result = append(result, stringToAppend);
184
- continue;
185
- }
186
-
187
- const formatter = formatters[token.specifier];
188
- const valueToFormat = token.value ||
189
- (token.substitutionIndex !== undefined ? actualSubstitutions[token.substitutionIndex] : undefined);
190
- const stringToAppend = formatter(valueToFormat, token);
191
-
192
- result = append(
193
- result,
194
- stringToAppend as string,
195
- );
196
- }
197
-
198
- const unusedSubstitutions = [];
199
- for (let i = 0; i < actualSubstitutions.length; ++i) {
200
- if (i in usedSubstitutionIndexes) {
201
- continue;
202
- }
203
- unusedSubstitutions.push(actualSubstitutions[i]);
204
- }
205
-
206
- return {formattedResult: result, unusedSubstitutions: unusedSubstitutions};
207
- };
208
-
209
- export const standardFormatters = {
210
- d: function(substitution: unknown): number {
211
- return (!isNaN(substitution as number) ? substitution as number : 0);
212
- },
213
-
214
- f: function(substitution: unknown, token: FormatterToken): string {
215
- if (substitution && typeof substitution === 'number' && token.precision !== undefined && token.precision > -1) {
216
- substitution = substitution.toFixed(token.precision);
217
- }
218
- const precision =
219
- (token.precision !== undefined && token.precision > -1) ? Number(0).toFixed(token.precision) : '0';
220
- return !isNaN(substitution as number) ? substitution as string : precision;
221
- },
222
-
223
- s: function(substitution: unknown): string {
224
- return substitution as string;
225
- },
226
- };
227
-
228
29
  const toHexadecimal = (charCode: number, padToLength: number): string => {
229
30
  return charCode.toString(16).toUpperCase().padStart(padToLength, '0');
230
31
  };
@@ -285,12 +86,51 @@ export const formatAsJSLiteral = (content: string): string => {
285
86
  return `${quote}${escapedContent}${quote}`;
286
87
  };
287
88
 
288
- export const vsprintf = function(formatString: string, substitutions: unknown[]): string {
289
- return format(formatString, substitutions, standardFormatters, '', (a, b) => a + b).formattedResult;
290
- };
291
-
292
- export const sprintf = function(format: string, ...varArg: unknown[]): string {
293
- return vsprintf(format, varArg);
89
+ /**
90
+ * This implements a subset of the sprintf() function described in the Single UNIX
91
+ * Specification. It supports the %s, %f, %d, and %% formatting specifiers, and
92
+ * understands the %m$d notation to select the m-th parameter for this substitution,
93
+ * as well as the optional precision for %s, %f, and %d.
94
+ *
95
+ * @param fmt format string.
96
+ * @param args parameters to the format string.
97
+ * @returns the formatted output string.
98
+ */
99
+ export const sprintf = (fmt: string, ...args: unknown[]): string => {
100
+ let argIndex = 0;
101
+ const RE = /%(?:(\d+)\$)?(?:\.(\d*))?([%dfs])/g;
102
+ return fmt.replaceAll(RE, (_: string, index?: string, precision?: string, specifier?: string): string => {
103
+ if (specifier === '%') {
104
+ return '%';
105
+ }
106
+ if (index !== undefined) {
107
+ argIndex = parseInt(index, 10) - 1;
108
+ if (argIndex < 0) {
109
+ throw new RangeError(`Invalid parameter index ${argIndex + 1}`);
110
+ }
111
+ }
112
+ if (argIndex >= args.length) {
113
+ throw new RangeError(`Expected at least ${argIndex + 1} format parameters, but only ${args.length} where given.`);
114
+ }
115
+ if (specifier === 's') {
116
+ const argValue = String(args[argIndex++]);
117
+ if (precision !== undefined) {
118
+ return argValue.substring(0, Number(precision));
119
+ }
120
+ return argValue;
121
+ }
122
+ let argValue = Number(args[argIndex++]);
123
+ if (isNaN(argValue)) {
124
+ argValue = 0;
125
+ }
126
+ if (specifier === 'd') {
127
+ return String(Math.floor(argValue)).padStart(Number(precision), '0');
128
+ }
129
+ if (precision !== undefined) {
130
+ return argValue.toFixed(Number(precision));
131
+ }
132
+ return String(argValue);
133
+ });
294
134
  };
295
135
 
296
136
  export const toBase64 = (inputString: string): string => {
@@ -126,9 +126,16 @@ export class EmulationModel extends SDKModel<void> {
126
126
  this.updateCssMedia();
127
127
 
128
128
  const autoDarkModeSetting = Common.Settings.Settings.instance().moduleSetting('emulateAutoDarkMode');
129
- autoDarkModeSetting.addChangeListener(() => this.emulateAutoDarkMode(autoDarkModeSetting.get()));
129
+ autoDarkModeSetting.addChangeListener(() => {
130
+ const enabled = autoDarkModeSetting.get();
131
+ mediaFeaturePrefersColorSchemeSetting.setDisabled(enabled);
132
+ mediaFeaturePrefersColorSchemeSetting.set(enabled ? 'dark' : '');
133
+ this.emulateAutoDarkMode(enabled);
134
+ });
130
135
  if (autoDarkModeSetting.get()) {
131
- this.emulateAutoDarkMode(autoDarkModeSetting.get());
136
+ mediaFeaturePrefersColorSchemeSetting.setDisabled(true);
137
+ mediaFeaturePrefersColorSchemeSetting.set('dark');
138
+ this.emulateAutoDarkMode(true);
132
139
  }
133
140
 
134
141
  const visionDeficiencySetting = Common.Settings.Settings.instance().moduleSetting('emulatedVisionDeficiency');
@@ -277,22 +284,14 @@ export class EmulationModel extends SDKModel<void> {
277
284
  }
278
285
  }
279
286
 
280
- private static parseAutoDarkModeSetting(setting: string): boolean|undefined {
281
- switch (setting) {
282
- case 'default':
283
- return undefined;
284
- case 'enabled':
285
- return true;
286
- case 'disabled':
287
- return false;
288
- default:
289
- throw Error('unrecognized auto dark mode setting');
287
+ private async emulateAutoDarkMode(enabled: boolean): Promise<void> {
288
+ if (enabled) {
289
+ this.#mediaConfiguration.set('prefers-color-scheme', 'dark');
290
+ await this.updateCssMedia();
290
291
  }
291
- }
292
-
293
- private async emulateAutoDarkMode(setting: string): Promise<void> {
294
- const enabled = EmulationModel.parseAutoDarkModeSetting(setting);
295
- await this.#emulationAgent.invoke_setAutoDarkModeOverride({enabled});
292
+ // We never send `enabled: false` since that would explicitly disable
293
+ // autodark mode. We either enable it or clear any existing override.
294
+ await this.#emulationAgent.invoke_setAutoDarkModeOverride({enabled: enabled || undefined});
296
295
  }
297
296
 
298
297
  private async emulateVisionDeficiency(type: Protocol.Emulation.SetEmulatedVisionDeficiencyRequestType):
@@ -360,7 +359,7 @@ export class EmulationModel extends SDKModel<void> {
360
359
  {enabled: configuration.enabled, configuration: configuration.configuration});
361
360
  }
362
361
 
363
- private updateCssMedia(): void {
362
+ private async updateCssMedia(): Promise<void> {
364
363
  // See the note above, where this.#mediaConfiguration is defined.
365
364
  const type = this.#mediaConfiguration.get('type') ?? '';
366
365
  const features = [
@@ -389,7 +388,7 @@ export class EmulationModel extends SDKModel<void> {
389
388
  value: this.#mediaConfiguration.get('prefers-reduced-motion') ?? '',
390
389
  },
391
390
  ];
392
- this.emulateCSSMedia(type, features);
391
+ return this.emulateCSSMedia(type, features);
393
392
  }
394
393
  }
395
394
 
@@ -616,7 +616,12 @@ export class ResourceTreeFrame {
616
616
  backForwardCacheDetails: {
617
617
  restoredFromCache: boolean|undefined,
618
618
  explanations: Protocol.Page.BackForwardCacheNotRestoredExplanation[],
619
- } = {restoredFromCache: undefined, explanations: []};
619
+ explanationsTree: Protocol.Page.BackForwardCacheNotRestoredExplanationTree|undefined,
620
+ } = {
621
+ restoredFromCache: undefined,
622
+ explanations: [],
623
+ explanationsTree: undefined,
624
+ };
620
625
 
621
626
  constructor(
622
627
  model: ResourceTreeModel, parentFrame: ResourceTreeFrame|null, frameId: Protocol.Page.FrameId,
@@ -688,7 +693,11 @@ export class ResourceTreeFrame {
688
693
  this.#secureContextType = framePayload.secureContextType;
689
694
  this.#crossOriginIsolatedContextType = framePayload.crossOriginIsolatedContextType;
690
695
  this.#gatedAPIFeatures = framePayload.gatedAPIFeatures;
691
- this.backForwardCacheDetails = {restoredFromCache: undefined, explanations: []};
696
+ this.backForwardCacheDetails = {
697
+ restoredFromCache: undefined,
698
+ explanations: [],
699
+ explanationsTree: undefined,
700
+ };
692
701
 
693
702
  const mainResource = this.resourcesMap.get(this.#urlInternal);
694
703
  this.resourcesMap.clear();
@@ -963,6 +972,7 @@ export class ResourceTreeFrame {
963
972
  setBackForwardCacheDetails(event: Protocol.Page.BackForwardCacheNotUsedEvent): void {
964
973
  this.backForwardCacheDetails.restoredFromCache = false;
965
974
  this.backForwardCacheDetails.explanations = event.notRestoredExplanations;
975
+ this.backForwardCacheDetails.explanationsTree = event.notRestoredExplanationsTree;
966
976
  }
967
977
 
968
978
  getResourcesMap(): Map<string, Resource> {
@@ -314,26 +314,6 @@ const UIStrings = {
314
314
  * emulates that the webpage is in auto dark mode.
315
315
  */
316
316
  emulateAutoDarkMode: 'Emulate auto dark mode',
317
- /**
318
- * @description Title of a setting for enabling auto dark mode.
319
- */
320
- enableEmulateAutoDarkMode: 'Enable auto dark mode',
321
- /**
322
- * @description Text to emulate enabled auto dark mode.
323
- */
324
- enabledDarkMode: 'Enable',
325
- /**
326
- * @description Title of a setting for disabling auto dark mode.
327
- */
328
- disableEmulateAutoDarkMode: 'Disable auto dark mode',
329
- /**
330
- * @description Text to emulate disabled auto dark mode.
331
- */
332
- disabledDarkMode: 'Disable',
333
- /**
334
- * @description Title of a setting for disabling dark mode emulation.
335
- */
336
- doNotEmulateDarkMode: 'Do not emulate auto dark mode',
337
317
  };
338
318
  const str_ = i18n.i18n.registerUIStrings('core/sdk/sdk-meta.ts', UIStrings);
339
319
  const i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_);
@@ -1049,24 +1029,7 @@ Common.Settings.registerSettingExtension({
1049
1029
  category: Common.Settings.SettingCategory.RENDERING,
1050
1030
  title: i18nLazyString(UIStrings.emulateAutoDarkMode),
1051
1031
  settingName: 'emulateAutoDarkMode',
1052
- settingType: Common.Settings.SettingType.ENUM,
1032
+ settingType: Common.Settings.SettingType.BOOLEAN,
1053
1033
  storageType: Common.Settings.SettingStorageType.Session,
1054
- defaultValue: 'default',
1055
- options: [
1056
- {
1057
- title: i18nLazyString(UIStrings.doNotEmulateDarkMode),
1058
- text: i18nLazyString(UIStrings.noEmulation),
1059
- value: 'default',
1060
- },
1061
- {
1062
- title: i18nLazyString(UIStrings.enableEmulateAutoDarkMode),
1063
- text: i18nLazyString(UIStrings.enabledDarkMode),
1064
- value: 'enabled',
1065
- },
1066
- {
1067
- title: i18nLazyString(UIStrings.disableEmulateAutoDarkMode),
1068
- text: i18nLazyString(UIStrings.disabledDarkMode),
1069
- value: 'disabled',
1070
- },
1071
- ],
1034
+ defaultValue: false,
1072
1035
  });
@@ -124,9 +124,13 @@ const UIStrings = {
124
124
  */
125
125
  emulatesAFocusedPage: 'Emulates a focused page.',
126
126
  /**
127
- * @description Explanation text for the 'Emulate a focused page' setting in the Rendering tool.
127
+ * @description The name of a checkbox setting in the Rendering tool. This setting enables auto dark mode emulation.
128
+ */
129
+ emulateAutoDarkMode: 'Enable automatic dark mode',
130
+ /**
131
+ * @description Explanation text for the 'Emulate automatic dark mode' setting in the Rendering tool.
128
132
  */
129
- emulatesAutoDarkMode: 'Enables automatic dark mode for the inspected page.',
133
+ emulatesAutoDarkMode: 'Enables automatic dark mode and sets `prefers-color-scheme` to `dark`.',
130
134
  /**
131
135
  * @description Explanation text for the 'Emulate CSS media type' setting in the Rendering tool.
132
136
  * This setting overrides the CSS media type on the page:
@@ -245,14 +249,18 @@ export class RenderingOptionsView extends UI.Widget.VBox {
245
249
  this.#appendCheckbox(
246
250
  i18nString(UIStrings.emulateAFocusedPage), i18nString(UIStrings.emulatesAFocusedPage),
247
251
  Common.Settings.Settings.instance().moduleSetting('emulatePageFocus'));
252
+ this.#appendCheckbox(
253
+ i18nString(UIStrings.emulateAutoDarkMode), i18nString(UIStrings.emulatesAutoDarkMode),
254
+ Common.Settings.Settings.instance().moduleSetting('emulateAutoDarkMode'));
255
+
248
256
  this.contentElement.createChild('div').classList.add('panel-section-separator');
249
257
 
250
- this.#appendSelect(
251
- i18nString(UIStrings.forcesMediaTypeForTestingPrint),
252
- Common.Settings.Settings.instance().moduleSetting('emulatedCSSMedia'));
253
258
  this.#appendSelect(
254
259
  i18nString(UIStrings.forcesCssPreferscolorschemeMedia),
255
260
  Common.Settings.Settings.instance().moduleSetting('emulatedCSSMediaFeaturePrefersColorScheme'));
261
+ this.#appendSelect(
262
+ i18nString(UIStrings.forcesMediaTypeForTestingPrint),
263
+ Common.Settings.Settings.instance().moduleSetting('emulatedCSSMedia'));
256
264
  this.#appendSelect(
257
265
  i18nString(UIStrings.forcesCssForcedColors),
258
266
  Common.Settings.Settings.instance().moduleSetting('emulatedCSSMediaFeatureForcedColors'));
@@ -279,10 +287,6 @@ export class RenderingOptionsView extends UI.Widget.VBox {
279
287
  Common.Settings.Settings.instance().moduleSetting('emulatedVisionDeficiency'));
280
288
 
281
289
  this.contentElement.createChild('div').classList.add('panel-section-separator');
282
- this.#appendSelect(
283
- i18nString(UIStrings.emulatesAutoDarkMode),
284
- Common.Settings.Settings.instance().moduleSetting('emulateAutoDarkMode'));
285
- this.contentElement.createChild('div').classList.add('panel-section-separator');
286
290
 
287
291
  this.#appendCheckbox(
288
292
  i18nString(UIStrings.disableAvifImageFormat), i18nString(UIStrings.requiresAPageReloadToApplyAnd),
@@ -2262,7 +2262,9 @@ export function registerCommands(inspectorBackend) {
2262
2262
  inspectorBackend.registerEvent(
2263
2263
  'Page.javascriptDialogOpening', ['url', 'message', 'type', 'hasBrowserHandler', 'defaultPrompt']);
2264
2264
  inspectorBackend.registerEvent('Page.lifecycleEvent', ['frameId', 'loaderId', 'name', 'timestamp']);
2265
- inspectorBackend.registerEvent('Page.backForwardCacheNotUsed', ['loaderId', 'frameId', 'notRestoredExplanations']);
2265
+ inspectorBackend.registerEvent(
2266
+ 'Page.backForwardCacheNotUsed',
2267
+ ['loaderId', 'frameId', 'notRestoredExplanations', 'notRestoredExplanationsTree']);
2266
2268
  inspectorBackend.registerEvent('Page.loadEventFired', ['timestamp']);
2267
2269
  inspectorBackend.registerEvent('Page.navigatedWithinDocument', ['frameId', 'url']);
2268
2270
  inspectorBackend.registerEvent('Page.screencastFrame', ['data', 'metadata', 'sessionId']);