chrome-devtools-frontend 1.0.956812 → 1.0.957983

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 (59) hide show
  1. package/extension-api/ExtensionAPI.d.ts +7 -0
  2. package/front_end/Tests.js +14 -0
  3. package/front_end/core/common/Debouncer.ts +1 -1
  4. package/front_end/core/common/Settings.ts +33 -0
  5. package/front_end/core/host/InspectorFrontendHost.ts +7 -3
  6. package/front_end/core/host/InspectorFrontendHostAPI.ts +2 -0
  7. package/front_end/core/host/UserMetrics.ts +2 -2
  8. package/front_end/core/i18n/i18nImpl.ts +1 -1
  9. package/front_end/core/i18n/locales/en-US.json +6 -0
  10. package/front_end/core/i18n/locales/en-XL.json +6 -0
  11. package/front_end/core/protocol_client/InspectorBackend.ts +3 -3
  12. package/front_end/core/sdk/Connections.ts +1 -1
  13. package/front_end/core/sdk/IsolateManager.ts +1 -1
  14. package/front_end/core/sdk/PageResourceLoader.ts +4 -2
  15. package/front_end/devtools_compatibility.js +9 -0
  16. package/front_end/entrypoints/main/MainImpl.ts +7 -2
  17. package/front_end/models/extensions/ExtensionAPI.ts +33 -5
  18. package/front_end/models/extensions/ExtensionServer.ts +28 -0
  19. package/front_end/models/logs/LogManager.ts +1 -1
  20. package/front_end/models/persistence/FileSystemWorkspaceBinding.ts +1 -1
  21. package/front_end/models/workspace/UISourceCode.ts +1 -1
  22. package/front_end/panels/application/AppManifestView.ts +41 -0
  23. package/front_end/panels/application/StorageView.ts +1 -1
  24. package/front_end/panels/console/ConsoleView.ts +1 -1
  25. package/front_end/panels/elements/ComputedStyleModel.ts +1 -1
  26. package/front_end/panels/elements/StylesSidebarPane.ts +2 -2
  27. package/front_end/panels/network/NetworkItemView.ts +1 -1
  28. package/front_end/panels/network/NetworkLogViewColumns.ts +5 -0
  29. package/front_end/panels/profiler/HeapTimelineOverview.ts +2 -2
  30. package/front_end/panels/profiler/LiveHeapProfileView.ts +1 -1
  31. package/front_end/panels/screencast/ScreencastView.ts +2 -2
  32. package/front_end/panels/settings/SettingsScreen.ts +1 -1
  33. package/front_end/panels/settings/settingsScreen.css +8 -3
  34. package/front_end/panels/sources/DebuggerPlugin.ts +1 -1
  35. package/front_end/panels/sources/NavigatorView.ts +1 -1
  36. package/front_end/panels/sources/SourcesSearchScope.ts +1 -1
  37. package/front_end/panels/timeline/TimelineController.ts +2 -2
  38. package/front_end/panels/timeline/TimelineLoader.ts +3 -3
  39. package/front_end/panels/timeline/TimelinePanel.ts +1 -1
  40. package/front_end/panels/webauthn/WebauthnPane.ts +1 -1
  41. package/front_end/third_party/codemirror.next/chunk/codemirror.js +1 -1
  42. package/front_end/third_party/codemirror.next/chunk/markdown.js +1 -1
  43. package/front_end/third_party/codemirror.next/codemirror.next.d.ts +76 -12
  44. package/front_end/third_party/codemirror.next/codemirror.next.js +1 -1
  45. package/front_end/third_party/codemirror.next/package.json +13 -13
  46. package/front_end/ui/components/render_coordinator/RenderCoordinator.ts +2 -2
  47. package/front_end/ui/components/text_editor/TextEditor.ts +1 -1
  48. package/front_end/ui/components/text_editor/cursor_tooltip.ts +1 -1
  49. package/front_end/ui/components/text_editor/javascript.ts +1 -1
  50. package/front_end/ui/components/text_editor/theme.ts +1 -0
  51. package/front_end/ui/legacy/SearchableView.ts +1 -1
  52. package/front_end/ui/legacy/SoftDropDown.ts +2 -2
  53. package/front_end/ui/legacy/TextPrompt.ts +2 -1
  54. package/front_end/ui/legacy/components/perf_ui/LiveHeapProfile.ts +1 -1
  55. package/front_end/ui/legacy/theme_support/theme_support_impl.ts +1 -1
  56. package/package.json +1 -1
  57. package/front_end/third_party/codemirror/README.md +0 -3
  58. package/front_end/third_party/codemirror/codemirror.css +0 -283
  59. package/front_end/third_party/codemirror/codemirror.ts +0 -19
@@ -69,6 +69,13 @@ export namespace Chrome {
69
69
 
70
70
  create(title: string, iconPath: string, pagePath: string, callback?: (panel: ExtensionPanel) => unknown): void;
71
71
  openResource(url: string, lineNumber: number, columnNumber?: number, callback?: () => unknown): void;
72
+
73
+ /**
74
+ * Fired when the theme changes in DevTools.
75
+ *
76
+ * @param callback The handler callback to register and be invoked on theme changes.
77
+ */
78
+ setThemeChangeHandler(callback?: (themeName: string) => unknown): void;
72
79
  }
73
80
 
74
81
  export interface Request {
@@ -1572,6 +1572,20 @@
1572
1572
  `console.log(1) //# sourceMappingURL=chrome-extension://${extensionId}/source.map`, () => {});
1573
1573
  };
1574
1574
 
1575
+ TestSuite.prototype.testSourceMapsFromDevtools = function() {
1576
+ this.takeControl();
1577
+ const debuggerModel = self.SDK.targetManager.mainTarget().model(SDK.DebuggerModel);
1578
+ debuggerModel.sourceMapManager().addEventListener(
1579
+ SDK.SourceMapManager.Events.SourceMapWillAttach, this.releaseControl.bind(this));
1580
+
1581
+ this.evaluateInConsole_(
1582
+ 'console.log(1) //# sourceMappingURL=devtools://devtools/bundled/devtools_compatibility.js', () => {});
1583
+ };
1584
+
1585
+ TestSuite.prototype.testDoesNotCrashOnSourceMapsFromUnknownScheme = function() {
1586
+ this.evaluateInConsole_('console.log(1) //# sourceMappingURL=invalid-scheme://source.map', () => {});
1587
+ };
1588
+
1575
1589
  /**
1576
1590
  * Returns all loaded non anonymous uiSourceCodes.
1577
1591
  * @return {!Array.<!Workspace.UISourceCode>}
@@ -9,7 +9,7 @@ export const debounce = function(func: Function, delay: number): Function {
9
9
  let timer = 0;
10
10
  const debounced = (): void => {
11
11
  clearTimeout(timer);
12
- timer = setTimeout(() => func(), delay);
12
+ timer = window.setTimeout(() => func(), delay);
13
13
  };
14
14
  return debounced;
15
15
  };
@@ -197,6 +197,7 @@ export class Settings {
197
197
 
198
198
  export interface SettingsBackingStore {
199
199
  register(setting: string): void;
200
+ get(setting: string): Promise<string>;
200
201
  set(setting: string, value: string): void;
201
202
  remove(setting: string): void;
202
203
  clear(): void;
@@ -205,6 +206,7 @@ export interface SettingsBackingStore {
205
206
  export const NOOP_STORAGE: SettingsBackingStore = {
206
207
  register: () => {},
207
208
  set: () => {},
209
+ get: () => Promise.resolve(''),
208
210
  remove: () => {},
209
211
  clear: () => {},
210
212
  };
@@ -236,6 +238,17 @@ export class SettingsStorage {
236
238
  return this.object[name];
237
239
  }
238
240
 
241
+ async forceGet(originalName: string): Promise<string> {
242
+ const name = this.storagePrefix + originalName;
243
+ const value = await this.backingStore.get(name);
244
+ if (value && value !== this.object[name]) {
245
+ this.set(originalName, value);
246
+ } else if (!value) {
247
+ this.remove(originalName);
248
+ }
249
+ return value;
250
+ }
251
+
239
252
  remove(name: string): void {
240
253
  name = this.storagePrefix + name;
241
254
  delete this.object[name];
@@ -363,6 +376,26 @@ export class Setting<V> {
363
376
  return this.#value;
364
377
  }
365
378
 
379
+ async forceGet(): Promise<V> {
380
+ const name = this.name;
381
+ const oldValue = this.storage.get(name);
382
+ const value = await this.storage.forceGet(name);
383
+ this.#value = this.defaultValue;
384
+ if (value) {
385
+ try {
386
+ this.#value = this.#serializer.parse(value);
387
+ } catch (e) {
388
+ this.storage.remove(this.name);
389
+ }
390
+ }
391
+
392
+ if (oldValue !== value) {
393
+ this.eventSupport.dispatchEventToListeners(this.name, this.#value);
394
+ }
395
+
396
+ return this.#value;
397
+ }
398
+
366
399
  set(value: V): void {
367
400
  this.#hadUserAction = true;
368
401
  this.#value = value;
@@ -94,15 +94,15 @@ export class InspectorFrontendHostStub implements InspectorFrontendHostAPI {
94
94
  }
95
95
 
96
96
  setIsDocked(isDocked: boolean, callback: () => void): void {
97
- setTimeout(callback, 0);
97
+ window.setTimeout(callback, 0);
98
98
  }
99
99
 
100
100
  showSurvey(trigger: string, callback: (arg0: ShowSurveyResult) => void): void {
101
- setTimeout(() => callback({surveyShown: false}), 0);
101
+ window.setTimeout(() => callback({surveyShown: false}), 0);
102
102
  }
103
103
 
104
104
  canShowSurvey(trigger: string, callback: (arg0: CanShowSurveyResult) => void): void {
105
- setTimeout(() => callback({canShowSurvey: false}), 0);
105
+ window.setTimeout(() => callback({canShowSurvey: false}), 0);
106
106
  }
107
107
 
108
108
  /**
@@ -260,6 +260,10 @@ export class InspectorFrontendHostStub implements InspectorFrontendHostAPI {
260
260
  callback(prefs);
261
261
  }
262
262
 
263
+ getPreference(name: string, callback: (arg0: string) => void): void {
264
+ callback(window.localStorage[name]);
265
+ }
266
+
263
267
  setPreference(name: string, value: string): void {
264
268
  window.localStorage[name] = value;
265
269
  }
@@ -234,6 +234,8 @@ export interface InspectorFrontendHostAPI {
234
234
  [x: string]: string,
235
235
  }) => void): void;
236
236
 
237
+ getPreference(name: string, callback: (arg0: string) => void): void;
238
+
237
239
  setPreference(name: string, value: string): void;
238
240
 
239
241
  removePreference(name: string): void;
@@ -78,10 +78,10 @@ export class UserMetrics {
78
78
  }
79
79
 
80
80
  this.#firedLaunchHistogram = true;
81
- // Use rAF and setTimeout to ensure the marker is fired after layout and rendering.
81
+ // Use rAF and window.setTimeout to ensure the marker is fired after layout and rendering.
82
82
  // This will give the most accurate representation of the tool being ready for a user.
83
83
  requestAnimationFrame(() => {
84
- setTimeout(() => {
84
+ window.setTimeout(() => {
85
85
  // Mark the load time so that we can pinpoint it more easily in a trace.
86
86
  performance.mark(histogramName);
87
87
  // If the user has switched panel before we finished loading, ignore the histogram,
@@ -58,7 +58,7 @@ function getLocaleFetchUrl(locale: Intl.UnicodeBCP47LocaleIdentifier): string {
58
58
  export async function fetchAndRegisterLocaleData(locale: Intl.UnicodeBCP47LocaleIdentifier): Promise<void> {
59
59
  const localeDataTextPromise = fetch(getLocaleFetchUrl(locale)).then(result => result.json());
60
60
  const timeoutPromise =
61
- new Promise((resolve, reject) => setTimeout(() => reject(new Error('timed out fetching locale')), 5000));
61
+ new Promise((resolve, reject) => window.setTimeout(() => reject(new Error('timed out fetching locale')), 5000));
62
62
  const localeData = await Promise.race([timeoutPromise, localeDataTextPromise]);
63
63
  i18nInstance.registerLocaleData(locale, localeData);
64
64
  }
@@ -2171,6 +2171,12 @@
2171
2171
  "panels/application/AppManifestView.ts | couldNotDownloadARequiredIcon": {
2172
2172
  "message": "Could not download a required icon from the manifest"
2173
2173
  },
2174
+ "panels/application/AppManifestView.ts | darkBackgroundColor": {
2175
+ "message": "Dark background color"
2176
+ },
2177
+ "panels/application/AppManifestView.ts | darkThemeColor": {
2178
+ "message": "Dark theme color"
2179
+ },
2174
2180
  "panels/application/AppManifestView.ts | description": {
2175
2181
  "message": "Description"
2176
2182
  },
@@ -2171,6 +2171,12 @@
2171
2171
  "panels/application/AppManifestView.ts | couldNotDownloadARequiredIcon": {
2172
2172
  "message": "Ĉóûĺd̂ ńôt́ d̂óŵńl̂óâd́ â ŕêq́ûír̂éd̂ íĉón̂ f́r̂óm̂ t́ĥé m̂án̂íf̂éŝt́"
2173
2173
  },
2174
+ "panels/application/AppManifestView.ts | darkBackgroundColor": {
2175
+ "message": "D̂ár̂ḱ b̂áĉḱĝŕôún̂d́ ĉól̂ór̂"
2176
+ },
2177
+ "panels/application/AppManifestView.ts | darkThemeColor": {
2178
+ "message": "D̂ár̂ḱ t̂h́êḿê ćôĺôŕ"
2179
+ },
2174
2180
  "panels/application/AppManifestView.ts | description": {
2175
2181
  "message": "D̂éŝćr̂íp̂t́îón̂"
2176
2182
  },
@@ -442,7 +442,7 @@ export class SessionRouter {
442
442
  }
443
443
 
444
444
  // Execute all promises.
445
- setTimeout(() => {
445
+ window.setTimeout(() => {
446
446
  if (!this.hasOutstandingNonLongPollingRequests()) {
447
447
  this.executeAfterPendingDispatches();
448
448
  } else {
@@ -467,7 +467,7 @@ export class SessionRouter {
467
467
  code: ConnectionClosedErrorCode,
468
468
  data: null,
469
469
  };
470
- setTimeout(() => callback(error, null), 0);
470
+ window.setTimeout(() => callback(error, null), 0);
471
471
  }
472
472
 
473
473
  static dispatchUnregisterSessionError({callback, method}: CallbackWithDebugInfo): void {
@@ -476,7 +476,7 @@ export class SessionRouter {
476
476
  code: ConnectionClosedErrorCode,
477
477
  data: null,
478
478
  };
479
- setTimeout(() => callback(error, null), 0);
479
+ window.setTimeout(() => callback(error, null), 0);
480
480
  }
481
481
  }
482
482
 
@@ -189,7 +189,7 @@ export class StubConnection implements ProtocolClient.InspectorBackend.Connectio
189
189
  }
190
190
 
191
191
  sendRawMessage(message: string): void {
192
- setTimeout(this.respondWithError.bind(this, message), 0);
192
+ window.setTimeout(this.respondWithError.bind(this, message), 0);
193
193
  }
194
194
 
195
195
  private respondWithError(message: string): void {
@@ -126,7 +126,7 @@ export class IsolateManager extends Common.ObjectWrapper.ObjectWrapper<EventType
126
126
  const pollId = this.#pollId;
127
127
  while (pollId === this.#pollId) {
128
128
  await Promise.all(Array.from(this.isolates(), isolate => isolate.update()));
129
- await new Promise(r => setTimeout(r, PollIntervalMs));
129
+ await new Promise(r => window.setTimeout(r, PollIntervalMs));
130
130
  }
131
131
  }
132
132
  }
@@ -163,7 +163,8 @@ export class PageResourceLoader extends Common.ObjectWrapper.ObjectWrapper<Event
163
163
 
164
164
  static async withTimeout<T>(promise: Promise<T>, timeout: number): Promise<T> {
165
165
  const timeoutPromise = new Promise<T>(
166
- (_, reject) => setTimeout(reject, timeout, new Error(i18nString(UIStrings.loadCanceledDueToLoadTimeout))));
166
+ (_, reject) =>
167
+ window.setTimeout(reject, timeout, new Error(i18nString(UIStrings.loadCanceledDueToLoadTimeout))));
167
168
  return Promise.race([promise, timeoutPromise]);
168
169
  }
169
170
 
@@ -219,7 +220,8 @@ export class PageResourceLoader extends Common.ObjectWrapper.ObjectWrapper<Event
219
220
  return this.#loadOverride(url);
220
221
  }
221
222
  const parsedURL = new Common.ParsedURL.ParsedURL(url);
222
- const eligibleForLoadFromTarget = getLoadThroughTargetSetting().get() && parsedURL && parsedURL.isHttpOrHttps();
223
+ const eligibleForLoadFromTarget = getLoadThroughTargetSetting().get() && parsedURL && parsedURL.scheme !== 'file' &&
224
+ parsedURL.scheme !== 'data' && parsedURL.scheme !== 'devtools';
223
225
  Host.userMetrics.developerResourceScheme(this.getDeveloperResourceScheme(parsedURL));
224
226
  if (eligibleForLoadFromTarget) {
225
227
  try {
@@ -542,6 +542,15 @@
542
542
  DevToolsAPI.sendMessageToEmbedder('getPreferences', [], /** @type {function(?Object)} */ (callback));
543
543
  }
544
544
 
545
+ /**
546
+ * @override
547
+ * @param {string} name
548
+ * @param {function(string)} callback
549
+ */
550
+ getPreference(name, callback) {
551
+ DevToolsAPI.sendMessageToEmbedder('getPreference', [name], /** @type {function(string)} */ (callback));
552
+ }
553
+
545
554
  /**
546
555
  * @override
547
556
  * @param {string} name
@@ -233,6 +233,11 @@ export class MainImpl {
233
233
  register: (name: string) =>
234
234
  Host.InspectorFrontendHost.InspectorFrontendHostInstance.registerPreference(name, {synced: false}),
235
235
  set: Host.InspectorFrontendHost.InspectorFrontendHostInstance.setPreference,
236
+ get: (name: string) => {
237
+ return new Promise(resolve => {
238
+ Host.InspectorFrontendHost.InspectorFrontendHostInstance.getPreference(name, resolve);
239
+ });
240
+ },
236
241
  remove: Host.InspectorFrontendHost.InspectorFrontendHostInstance.removePreference,
237
242
  clear: Host.InspectorFrontendHost.InspectorFrontendHostInstance.clearPreferences,
238
243
  };
@@ -571,7 +576,7 @@ export class MainImpl {
571
576
  UI.ARIAUtils.alertElementInstance();
572
577
 
573
578
  // Allow UI cycles to repaint prior to creating connection.
574
- setTimeout(this.#initializeTarget.bind(this), 0);
579
+ window.setTimeout(this.#initializeTarget.bind(this), 0);
575
580
  MainImpl.timeEnd('Main._showAppUI');
576
581
  }
577
582
 
@@ -587,7 +592,7 @@ export class MainImpl {
587
592
  // Used for browser tests.
588
593
  Host.InspectorFrontendHost.InspectorFrontendHostInstance.readyForTest();
589
594
  // Asynchronously run the extensions.
590
- setTimeout(this.#lateInitialization.bind(this), 100);
595
+ window.setTimeout(this.#lateInitialization.bind(this), 100);
591
596
  MainImpl.timeEnd('Main._initializeTarget');
592
597
  }
593
598
 
@@ -55,6 +55,7 @@ export namespace PrivateAPI {
55
55
  ResourceContentCommitted = 'resource-content-committed',
56
56
  ViewShown = 'view-shown-',
57
57
  ViewHidden = 'view-hidden,',
58
+ ThemeChange = 'host-theme-change',
58
59
  }
59
60
 
60
61
  export const enum Commands {
@@ -75,6 +76,7 @@ export namespace PrivateAPI {
75
76
  Reload = 'Reload',
76
77
  Subscribe = 'subscribe',
77
78
  SetOpenResourceHandler = 'setOpenResourceHandler',
79
+ SetThemeChangeHandler = 'setThemeChangeHandler',
78
80
  SetResourceContent = 'setResourceContent',
79
81
  SetSidebarContent = 'setSidebarContent',
80
82
  SetSidebarHeight = 'setSidebarHeight',
@@ -151,6 +153,7 @@ export namespace PrivateAPI {
151
153
  type SetSidebarPageRequest = {command: Commands.SetSidebarPage, id: string, page: string};
152
154
  type OpenResourceRequest = {command: Commands.OpenResource, url: string, lineNumber: number, columnNumber: number};
153
155
  type SetOpenResourceHandlerRequest = {command: Commands.SetOpenResourceHandler, handlerPresent: boolean};
156
+ type SetThemeChangeHandlerRequest = {command: Commands.SetThemeChangeHandler, handlerPresent: boolean};
154
157
  type ReloadRequest = {
155
158
  command: Commands.Reload,
156
159
  options: null|{
@@ -180,9 +183,10 @@ export namespace PrivateAPI {
180
183
  export type ServerRequests = RegisterLanguageExtensionPluginRequest|SubscribeRequest|UnsubscribeRequest|
181
184
  AddRequestHeadersRequest|ApplyStyleSheetRequest|CreatePanelRequest|ShowPanelRequest|CreateToolbarButtonRequest|
182
185
  UpdateButtonRequest|CompleteTraceSessionRequest|CreateSidebarPaneRequest|SetSidebarHeightRequest|
183
- SetSidebarContentRequest|SetSidebarPageRequest|OpenResourceRequest|SetOpenResourceHandlerRequest|ReloadRequest|
184
- EvaluateOnInspectedPageRequest|GetRequestContentRequest|GetResourceContentRequest|SetResourceContentRequest|
185
- AddTraceProviderRequest|ForwardKeyboardEventRequest|GetHARRequest|GetPageResourcesRequest;
186
+ SetSidebarContentRequest|SetSidebarPageRequest|OpenResourceRequest|SetOpenResourceHandlerRequest|
187
+ SetThemeChangeHandlerRequest|ReloadRequest|EvaluateOnInspectedPageRequest|GetRequestContentRequest|
188
+ GetResourceContentRequest|SetResourceContentRequest|AddTraceProviderRequest|ForwardKeyboardEventRequest|
189
+ GetHARRequest|GetPageResourcesRequest;
186
190
  export type ExtensionServerRequestMessage = PrivateAPI.ServerRequests&{requestId?: number};
187
191
 
188
192
  type AddRawModuleRequest = {
@@ -330,6 +334,7 @@ namespace APIImpl {
330
334
  applyStyleSheet(styleSheet: string): void;
331
335
  setOpenResourceHandler(callback?: (resource: PublicAPI.Chrome.DevTools.Resource, lineNumber: number) => unknown):
332
336
  void;
337
+ setThemeChangeHandler(callback?: (themeName: string) => unknown): void;
333
338
  }
334
339
 
335
340
  export interface ExtensionView extends PublicAPI.Chrome.DevTools.ExtensionView {
@@ -539,7 +544,8 @@ self.injectedExtensionAPI = function(
539
544
  };
540
545
  }
541
546
 
542
- (Panels.prototype as Pick<APIImpl.Panels, 'create'|'setOpenResourceHandler'|'openResource'|'SearchAction'>) = {
547
+ (Panels.prototype as
548
+ Pick<APIImpl.Panels, 'create'|'setOpenResourceHandler'|'openResource'|'SearchAction'|'setThemeChangeHandler'>) = {
543
549
  create: function(
544
550
  title: string, icon: string, page: string,
545
551
  callback: (panel: PublicAPI.Chrome.DevTools.ExtensionPanel) => unknown): void {
@@ -577,6 +583,28 @@ self.injectedExtensionAPI = function(
577
583
  }
578
584
  },
579
585
 
586
+ setThemeChangeHandler: function(callback: (themeName: string) => unknown): void {
587
+ const hadHandler = extensionServer.hasHandler(PrivateAPI.Events.ThemeChange);
588
+
589
+ function callbackWrapper(message: unknown): void {
590
+ const {themeName} = message as {themeName: string};
591
+ chrome.devtools.panels.themeName = themeName;
592
+ callback.call(null, themeName);
593
+ }
594
+
595
+ if (!callback) {
596
+ extensionServer.unregisterHandler(PrivateAPI.Events.ThemeChange);
597
+ } else {
598
+ extensionServer.registerHandler(PrivateAPI.Events.ThemeChange, callbackWrapper);
599
+ }
600
+
601
+ // Only send command if we either removed an existing handler or added handler and had none before.
602
+ if (hadHandler === !callback) {
603
+ extensionServer.sendRequest(
604
+ {command: PrivateAPI.Commands.SetThemeChangeHandler, 'handlerPresent': Boolean(callback)});
605
+ }
606
+ },
607
+
580
608
  openResource: function(
581
609
  url: string, lineNumber: number, columnNumber?: number, _callback?: (response: unknown) => unknown): void {
582
610
  const callbackArg = extractCallbackArgument(arguments);
@@ -1084,7 +1112,7 @@ self.injectedExtensionAPI = function(
1084
1112
  };
1085
1113
  keyboardEventRequestQueue.push(requestPayload);
1086
1114
  if (!forwardTimer) {
1087
- forwardTimer = setTimeout(forwardEventQueue, 0);
1115
+ forwardTimer = window.setTimeout(forwardEventQueue, 0);
1088
1116
  }
1089
1117
  }
1090
1118
 
@@ -89,6 +89,7 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
89
89
  private extensionsEnabled: boolean;
90
90
  private inspectedTabId?: string;
91
91
  private readonly extensionAPITestHook?: (server: unknown, api: unknown) => unknown;
92
+ private themeChangeHandlers: Map<string, MessagePort> = new Map();
92
93
 
93
94
  private constructor() {
94
95
  super();
@@ -124,6 +125,7 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
124
125
  this.registerHandler(PrivateAPI.Commands.GetResourceContent, this.onGetResourceContent.bind(this));
125
126
  this.registerHandler(PrivateAPI.Commands.Reload, this.onReload.bind(this));
126
127
  this.registerHandler(PrivateAPI.Commands.SetOpenResourceHandler, this.onSetOpenResourceHandler.bind(this));
128
+ this.registerHandler(PrivateAPI.Commands.SetThemeChangeHandler, this.onSetThemeChangeHandler.bind(this));
127
129
  this.registerHandler(PrivateAPI.Commands.SetResourceContent, this.onSetResourceContent.bind(this));
128
130
  this.registerHandler(PrivateAPI.Commands.SetSidebarHeight, this.onSetSidebarHeight.bind(this));
129
131
  this.registerHandler(PrivateAPI.Commands.SetSidebarContent, this.onSetSidebarContent.bind(this));
@@ -147,6 +149,13 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
147
149
  Host.InspectorFrontendHostAPI.Events.SetInspectedTabId, this.setInspectedTabId, this);
148
150
 
149
151
  this.initExtensions();
152
+
153
+ ThemeSupport.ThemeSupport.instance().addEventListener(ThemeSupport.ThemeChangeEvent.eventName, () => {
154
+ const themeName = ThemeSupport.ThemeSupport.instance().themeName();
155
+ for (const port of this.themeChangeHandlers.values()) {
156
+ port.postMessage({command: PrivateAPI.Events.ThemeChange, themeName});
157
+ }
158
+ });
150
159
  }
151
160
 
152
161
  static instance(opts: {
@@ -530,6 +539,25 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
530
539
  return undefined;
531
540
  }
532
541
 
542
+ private onSetThemeChangeHandler(message: PrivateAPI.ExtensionServerRequestMessage, port: MessagePort): Record
543
+ |undefined {
544
+ if (message.command !== PrivateAPI.Commands.SetThemeChangeHandler) {
545
+ return this.status.E_BADARG('command', `expected ${PrivateAPI.Commands.SetThemeChangeHandler}`);
546
+ }
547
+ const extensionOrigin = this.getExtensionOrigin(port);
548
+ const extension = this.registeredExtensions.get(extensionOrigin);
549
+ if (!extension) {
550
+ throw new Error('Received a message from an unregistered extension');
551
+ }
552
+
553
+ if (message.handlerPresent) {
554
+ this.themeChangeHandlers.set(extensionOrigin, port);
555
+ } else {
556
+ this.themeChangeHandlers.delete(extensionOrigin);
557
+ }
558
+ return undefined;
559
+ }
560
+
533
561
  private handleOpenURL(
534
562
  port: MessagePort, contentProvider: TextUtils.ContentProvider.ContentProvider, lineNumber: number): void {
535
563
  port.postMessage(
@@ -67,7 +67,7 @@ export class LogManager implements SDK.TargetManager.SDKModelObserver<SDK.LogMod
67
67
  if (SDK.TargetManager.TargetManager.instance().targetById(workerId)) {
68
68
  return;
69
69
  }
70
- setTimeout(() => {
70
+ window.setTimeout(() => {
71
71
  if (!SDK.TargetManager.TargetManager.instance().targetById(workerId)) {
72
72
  SDK.ConsoleModel.ConsoleModel.instance().addMessage(consoleMessage);
73
73
  }
@@ -331,7 +331,7 @@ export class FileSystem extends Workspace.Workspace.ProjectStore implements Work
331
331
  this.addFile(filePaths[i]);
332
332
  }
333
333
  if (to < filePaths.length) {
334
- setTimeout(reportFileChunk.bind(this, to), 100);
334
+ window.setTimeout(reportFileChunk.bind(this, to), 100);
335
335
  }
336
336
  }
337
337
  }
@@ -277,7 +277,7 @@ export class UISourceCode extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
277
277
  await Common.Revealer.reveal(this);
278
278
 
279
279
  // Make sure we are in the next frame before stopping the world with confirm
280
- await new Promise(resolve => setTimeout(resolve, 0));
280
+ await new Promise(resolve => window.setTimeout(resolve, 0));
281
281
 
282
282
  const shouldUpdate = window.confirm(i18nString(UIStrings.thisFileWasChangedExternally));
283
283
  if (shouldUpdate) {
@@ -102,6 +102,14 @@ const UIStrings = {
102
102
  */
103
103
  backgroundColor: 'Background color',
104
104
  /**
105
+ *@description Text in App Manifest View of the Application panel
106
+ */
107
+ darkThemeColor: 'Dark theme color',
108
+ /**
109
+ *@description Text in App Manifest View of the Application panel
110
+ */
111
+ darkBackgroundColor: 'Dark background color',
112
+ /**
105
113
  *@description Text for the orientation of something
106
114
  */
107
115
  orientation: 'Orientation',
@@ -403,6 +411,10 @@ export class AppManifestView extends UI.Widget.VBox implements SDK.TargetManager
403
411
  private readonly startURLField: HTMLElement;
404
412
  private readonly themeColorSwatch: InlineEditor.ColorSwatch.ColorSwatch;
405
413
  private readonly backgroundColorSwatch: InlineEditor.ColorSwatch.ColorSwatch;
414
+ private readonly darkThemeColorField: HTMLElement;
415
+ private readonly darkThemeColorSwatch: InlineEditor.ColorSwatch.ColorSwatch;
416
+ private readonly darkBackgroundColorField: HTMLElement;
417
+ private readonly darkBackgroundColorSwatch: InlineEditor.ColorSwatch.ColorSwatch;
406
418
  private orientationField: HTMLElement;
407
419
  private displayField: HTMLElement;
408
420
  private readonly newNoteUrlField: HTMLElement;
@@ -456,6 +468,14 @@ export class AppManifestView extends UI.Widget.VBox implements SDK.TargetManager
456
468
  this.backgroundColorSwatch = new InlineEditor.ColorSwatch.ColorSwatch();
457
469
  backgroundColorField.appendChild(this.backgroundColorSwatch);
458
470
 
471
+ this.darkThemeColorField = this.presentationSection.appendField(i18nString(UIStrings.darkThemeColor));
472
+ this.darkThemeColorSwatch = new InlineEditor.ColorSwatch.ColorSwatch();
473
+ this.darkThemeColorField.appendChild(this.darkThemeColorSwatch);
474
+
475
+ this.darkBackgroundColorField = this.presentationSection.appendField(i18nString(UIStrings.darkBackgroundColor));
476
+ this.darkBackgroundColorSwatch = new InlineEditor.ColorSwatch.ColorSwatch();
477
+ this.darkBackgroundColorField.appendChild(this.darkBackgroundColorSwatch);
478
+
459
479
  this.orientationField = this.presentationSection.appendField(i18nString(UIStrings.orientation));
460
480
  this.displayField = this.presentationSection.appendField(i18nString(UIStrings.display));
461
481
 
@@ -634,6 +654,27 @@ export class AppManifestView extends UI.Widget.VBox implements SDK.TargetManager
634
654
  this.backgroundColorSwatch.renderColor(backgroundColor, true);
635
655
  }
636
656
 
657
+ const userPreferences = parsedManifest['user_preferences'] || {};
658
+ const colorSchemeDark = userPreferences['color_scheme_dark'] || {};
659
+ const darkThemeColorString = colorSchemeDark['theme_color'];
660
+ const hasDarkThemeColor = typeof darkThemeColorString === 'string';
661
+ this.darkThemeColorField.parentElement?.classList.toggle('hidden', !hasDarkThemeColor);
662
+ if (hasDarkThemeColor) {
663
+ const darkThemeColor = Common.Color.Color.parse(darkThemeColorString);
664
+ if (darkThemeColor) {
665
+ this.darkThemeColorSwatch.renderColor(darkThemeColor, true);
666
+ }
667
+ }
668
+ const darkBackgroundColorString = colorSchemeDark['background_color'];
669
+ const hasDarkBackgroundColor = typeof darkBackgroundColorString === 'string';
670
+ this.darkBackgroundColorField.parentElement?.classList.toggle('hidden', !hasDarkBackgroundColor);
671
+ if (hasDarkBackgroundColor) {
672
+ const darkBackgroundColor = Common.Color.Color.parse(darkBackgroundColorString);
673
+ if (darkBackgroundColor) {
674
+ this.darkBackgroundColorSwatch.renderColor(darkBackgroundColor, true);
675
+ }
676
+ }
677
+
637
678
  this.orientationField.textContent = stringProperty('orientation');
638
679
  const displayType = stringProperty('display');
639
680
  this.displayField.textContent = displayType;
@@ -381,7 +381,7 @@ export class StorageView extends UI.ThrottledWidget.ThrottledWidget {
381
381
  this.clearButton.disabled = true;
382
382
  const label = this.clearButton.textContent;
383
383
  this.clearButton.textContent = i18nString(UIStrings.clearing);
384
- setTimeout(() => {
384
+ window.setTimeout(() => {
385
385
  this.clearButton.disabled = false;
386
386
  this.clearButton.textContent = label;
387
387
  this.clearButton.focus();
@@ -1390,7 +1390,7 @@ export class ConsoleView extends UI.Widget.VBox implements UI.SearchableView.Sea
1390
1390
 
1391
1391
  if (index === this.visibleViewMessages.length) {
1392
1392
  this.cleanupAfterSearch();
1393
- setTimeout(this.searchFinishedForTests.bind(this), 0);
1393
+ window.setTimeout(this.searchFinishedForTests.bind(this), 0);
1394
1394
  return;
1395
1395
  }
1396
1396
 
@@ -83,7 +83,7 @@ export class ComputedStyleModel extends Common.ObjectWrapper.ObjectWrapper<Event
83
83
  clearTimeout(this.frameResizedTimer);
84
84
  }
85
85
 
86
- this.frameResizedTimer = setTimeout(refreshContents.bind(this), 100);
86
+ this.frameResizedTimer = window.setTimeout(refreshContents.bind(this), 100);
87
87
  }
88
88
 
89
89
  private elementNode(): SDK.DOMModel.DOMNode|null {
@@ -590,7 +590,7 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
590
590
 
591
591
  async doUpdate(): Promise<void> {
592
592
  if (!this.initialUpdateCompleted) {
593
- setTimeout(() => {
593
+ window.setTimeout(() => {
594
594
  if (!this.initialUpdateCompleted) {
595
595
  // the spinner will get automatically removed when innerRebuildUpdate is called
596
596
  this.sectionsContainer.createChild('span', 'spinner');
@@ -1650,7 +1650,7 @@ export class StylePropertiesSection {
1650
1650
  if (this.hoverTimer) {
1651
1651
  clearTimeout(this.hoverTimer);
1652
1652
  }
1653
- this.hoverTimer = setTimeout(this.highlight.bind(this), 300);
1653
+ this.hoverTimer = window.setTimeout(this.highlight.bind(this), 300);
1654
1654
  }
1655
1655
 
1656
1656
  highlight(mode: string|undefined = 'all'): void {
@@ -275,7 +275,7 @@ export class NetworkItemView extends UI.TabbedPane.TabbedPane {
275
275
  if (!this.selectTab(tabId)) {
276
276
  // maybeAppendPayloadPanel might cause payload tab to appear asynchronously, so
277
277
  // it makes sense to retry on the next tick
278
- setTimeout(() => {
278
+ window.setTimeout(() => {
279
279
  if (!this.selectTab(tabId)) {
280
280
  this.selectTab('headers');
281
281
  }
@@ -8,6 +8,7 @@ import type * as SDK from '../../core/sdk/sdk.js';
8
8
  import * as DataGrid from '../../ui/legacy/components/data_grid/data_grid.js';
9
9
  import * as Components from '../../ui/legacy/components/utils/utils.js';
10
10
  import * as UI from '../../ui/legacy/legacy.js';
11
+ import * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';
11
12
 
12
13
  import type {NetworkNode} from './NetworkDataGridNode.js';
13
14
  import {NetworkRequestNode} from './NetworkDataGridNode.js';
@@ -205,6 +206,10 @@ export class NetworkLogViewColumns {
205
206
 
206
207
  this.setupDataGrid();
207
208
  this.setupWaterfall();
209
+
210
+ ThemeSupport.ThemeSupport.instance().addEventListener(ThemeSupport.ThemeChangeEvent.eventName, () => {
211
+ this.scheduleRefresh();
212
+ });
208
213
  }
209
214
 
210
215
  private static convertToDataGridDescriptor(columnConfig: Descriptor): DataGrid.DataGrid.ColumnDescriptor {