chrome-devtools-frontend 1.0.956881 → 1.0.958475

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 (69) hide show
  1. package/.eslintignore +0 -1
  2. package/extension-api/ExtensionAPI.d.ts +7 -0
  3. package/front_end/Tests.js +14 -0
  4. package/front_end/core/common/Debouncer.ts +1 -1
  5. package/front_end/core/common/Settings.ts +33 -0
  6. package/front_end/core/host/InspectorFrontendHost.ts +7 -3
  7. package/front_end/core/host/InspectorFrontendHostAPI.ts +2 -0
  8. package/front_end/core/host/UserMetrics.ts +2 -2
  9. package/front_end/core/i18n/i18nImpl.ts +1 -1
  10. package/front_end/core/i18n/locales/en-US.json +6 -0
  11. package/front_end/core/i18n/locales/en-XL.json +6 -0
  12. package/front_end/core/protocol_client/InspectorBackend.ts +3 -3
  13. package/front_end/core/sdk/Connections.ts +1 -1
  14. package/front_end/core/sdk/IsolateManager.ts +1 -1
  15. package/front_end/core/sdk/PageResourceLoader.ts +4 -2
  16. package/front_end/devtools_compatibility.js +9 -0
  17. package/front_end/entrypoints/main/MainImpl.ts +7 -2
  18. package/front_end/models/extensions/ExtensionAPI.ts +33 -5
  19. package/front_end/models/extensions/ExtensionServer.ts +28 -0
  20. package/front_end/models/logs/LogManager.ts +1 -1
  21. package/front_end/models/persistence/Automapping.ts +32 -4
  22. package/front_end/models/persistence/FileSystemWorkspaceBinding.ts +1 -1
  23. package/front_end/models/persistence/PersistenceImpl.ts +33 -13
  24. package/front_end/models/workspace/UISourceCode.ts +1 -1
  25. package/front_end/panels/application/AppManifestView.ts +41 -0
  26. package/front_end/panels/application/StorageView.ts +1 -1
  27. package/front_end/panels/console/ConsoleView.ts +1 -1
  28. package/front_end/panels/elements/AccessibilityTreeView.ts +2 -2
  29. package/front_end/panels/elements/ComputedStyleModel.ts +1 -1
  30. package/front_end/panels/elements/ElementsPanel.ts +16 -15
  31. package/front_end/panels/elements/StylesSidebarPane.ts +2 -2
  32. package/front_end/panels/elements/elementsPanel.css +4 -2
  33. package/front_end/panels/network/NetworkItemView.ts +1 -1
  34. package/front_end/panels/network/NetworkLogViewColumns.ts +5 -0
  35. package/front_end/panels/profiler/HeapTimelineOverview.ts +2 -2
  36. package/front_end/panels/profiler/LiveHeapProfileView.ts +1 -1
  37. package/front_end/panels/screencast/ScreencastView.ts +2 -2
  38. package/front_end/panels/settings/SettingsScreen.ts +1 -1
  39. package/front_end/panels/settings/settingsScreen.css +8 -3
  40. package/front_end/panels/sources/DebuggerPlugin.ts +1 -1
  41. package/front_end/panels/sources/NavigatorView.ts +1 -1
  42. package/front_end/panels/sources/SourcesSearchScope.ts +1 -1
  43. package/front_end/panels/sources/sources-meta.ts +14 -11
  44. package/front_end/panels/timeline/TimelineController.ts +2 -2
  45. package/front_end/panels/timeline/TimelineLoader.ts +3 -3
  46. package/front_end/panels/timeline/TimelinePanel.ts +1 -1
  47. package/front_end/panels/webauthn/WebauthnPane.ts +1 -1
  48. package/front_end/third_party/codemirror.next/chunk/codemirror.js +1 -1
  49. package/front_end/third_party/codemirror.next/chunk/markdown.js +1 -1
  50. package/front_end/third_party/codemirror.next/codemirror.next.d.ts +76 -12
  51. package/front_end/third_party/codemirror.next/codemirror.next.js +1 -1
  52. package/front_end/third_party/codemirror.next/package.json +13 -13
  53. package/front_end/ui/components/buttons/Button.ts +5 -1
  54. package/front_end/ui/components/buttons/button.css +10 -1
  55. package/front_end/ui/components/render_coordinator/RenderCoordinator.ts +2 -2
  56. package/front_end/ui/components/text_editor/TextEditor.ts +1 -1
  57. package/front_end/ui/components/text_editor/cursor_tooltip.ts +1 -1
  58. package/front_end/ui/components/text_editor/javascript.ts +1 -1
  59. package/front_end/ui/components/text_editor/theme.ts +1 -0
  60. package/front_end/ui/legacy/SearchableView.ts +1 -1
  61. package/front_end/ui/legacy/SoftDropDown.ts +2 -2
  62. package/front_end/ui/legacy/TextPrompt.ts +2 -1
  63. package/front_end/ui/legacy/components/perf_ui/LiveHeapProfile.ts +1 -1
  64. package/front_end/ui/legacy/theme_support/theme_support_impl.ts +1 -1
  65. package/front_end/ui/legacy/toolbar.css +2 -0
  66. package/package.json +1 -1
  67. package/front_end/third_party/codemirror/README.md +0 -3
  68. package/front_end/third_party/codemirror/codemirror.css +0 -283
  69. package/front_end/third_party/codemirror/codemirror.ts +0 -19
package/.eslintignore CHANGED
@@ -5,7 +5,6 @@
5
5
  // clang-format check also ignores that file
6
6
  front_end/.eslintrc.js
7
7
  front_end/diff/diff_match_patch.js
8
- front_end/protocol_externs.js
9
8
  front_end/javascript_metadata/NativeFunctions.js
10
9
  front_end/third_party/
11
10
  test/e2e/**/*.js
@@ -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
  }
@@ -3,6 +3,7 @@
3
3
  // found in the LICENSE file.
4
4
 
5
5
  import * as Common from '../../core/common/common.js';
6
+ import * as Host from '../../core/host/host.js';
6
7
  import * as i18n from '../../core/i18n/i18n.js';
7
8
  import * as Platform from '../../core/platform/platform.js';
8
9
  import * as SDK from '../../core/sdk/sdk.js';
@@ -28,7 +29,7 @@ export class Automapping {
28
29
  private readonly onStatusAdded: (arg0: AutomappingStatus) => Promise<void>;
29
30
  private readonly onStatusRemoved: (arg0: AutomappingStatus) => Promise<void>;
30
31
  private readonly statuses: Set<AutomappingStatus>;
31
- private readonly fileSystemUISourceCodes: Map<string, Workspace.UISourceCode.UISourceCode>;
32
+ private readonly fileSystemUISourceCodes: FileSystemUISourceCodes;
32
33
  private readonly sweepThrottler: Common.Throttler.Throttler;
33
34
  private readonly sourceCodeToProcessingPromiseMap: WeakMap<Workspace.UISourceCode.UISourceCode, Promise<void>>;
34
35
  private readonly sourceCodeToAutoMappingStatusMap: WeakMap<Workspace.UISourceCode.UISourceCode, AutomappingStatus>;
@@ -47,7 +48,7 @@ export class Automapping {
47
48
  this.onStatusRemoved = onStatusRemoved;
48
49
  this.statuses = new Set();
49
50
 
50
- this.fileSystemUISourceCodes = new Map();
51
+ this.fileSystemUISourceCodes = new FileSystemUISourceCodes();
51
52
  this.sweepThrottler = new Common.Throttler.Throttler(100);
52
53
 
53
54
  this.sourceCodeToProcessingPromiseMap = new WeakMap();
@@ -144,7 +145,7 @@ export class Automapping {
144
145
  return;
145
146
  }
146
147
  this.filesIndex.addPath(uiSourceCode.url());
147
- this.fileSystemUISourceCodes.set(uiSourceCode.url(), uiSourceCode);
148
+ this.fileSystemUISourceCodes.add(uiSourceCode);
148
149
  this.scheduleSweep();
149
150
  } else if (project.type() === Workspace.Workspace.projectTypes.Network) {
150
151
  this.computeNetworkStatus(uiSourceCode);
@@ -179,7 +180,7 @@ export class Automapping {
179
180
  }
180
181
 
181
182
  this.filesIndex.addPath(uiSourceCode.url());
182
- this.fileSystemUISourceCodes.set(uiSourceCode.url(), uiSourceCode);
183
+ this.fileSystemUISourceCodes.add(uiSourceCode);
183
184
  this.scheduleSweep();
184
185
  }
185
186
 
@@ -489,6 +490,33 @@ class FolderIndex {
489
490
  }
490
491
  }
491
492
 
493
+ class FileSystemUISourceCodes {
494
+ private readonly sourceCodes: Map<string, Workspace.UISourceCode.UISourceCode>;
495
+
496
+ constructor() {
497
+ this.sourceCodes = new Map();
498
+ }
499
+
500
+ private getPlatformCanonicalFileUrl(path: string): string {
501
+ return Host.Platform.isWin() ? path.toLowerCase() : path;
502
+ }
503
+
504
+ add(sourceCode: Workspace.UISourceCode.UISourceCode): void {
505
+ const fileUrl = this.getPlatformCanonicalFileUrl(sourceCode.url());
506
+ this.sourceCodes.set(fileUrl, sourceCode);
507
+ }
508
+
509
+ get(fileUrl: string): Workspace.UISourceCode.UISourceCode|undefined {
510
+ fileUrl = this.getPlatformCanonicalFileUrl(fileUrl);
511
+ return this.sourceCodes.get(fileUrl);
512
+ }
513
+
514
+ delete(fileUrl: string): void {
515
+ fileUrl = this.getPlatformCanonicalFileUrl(fileUrl);
516
+ this.sourceCodes.delete(fileUrl);
517
+ }
518
+ }
519
+
492
520
  export class AutomappingStatus {
493
521
  network: Workspace.UISourceCode.UISourceCode;
494
522
  fileSystem: Workspace.UISourceCode.UISourceCode;
@@ -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
  }