chrome-devtools-frontend 1.0.1656897 → 1.0.1657855

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 (113) hide show
  1. package/.agents/skills/devtools-ux-writing-refactor/SKILL.md +125 -0
  2. package/.agents/skills/repro-flaky-tests/SKILL.md +53 -0
  3. package/AUTHORS +2 -0
  4. package/docs/get_the_code.md +6 -6
  5. package/front_end/Images/src/ads.svg +1 -0
  6. package/front_end/Tests.js +1 -1
  7. package/front_end/core/common/ResourceType.ts +19 -19
  8. package/front_end/core/common/Revealer.ts +15 -15
  9. package/front_end/core/common/SettingRegistration.ts +19 -19
  10. package/front_end/core/common/Settings.ts +0 -8
  11. package/front_end/core/host/Platform.ts +4 -0
  12. package/front_end/core/sdk/CSSMetadata.ts +121 -16
  13. package/front_end/core/sdk/CSSModel.ts +3 -0
  14. package/front_end/core/sdk/DOMModel.ts +37 -8
  15. package/front_end/core/sdk/DebuggerModel.ts +5 -4
  16. package/front_end/core/sdk/EmulationModel.ts +6 -4
  17. package/front_end/core/sdk/NetworkManager.ts +22 -17
  18. package/front_end/core/sdk/RuntimeModel.ts +1 -1
  19. package/front_end/core/sdk/TargetManager.ts +10 -0
  20. package/front_end/design_system_tokens.css +6 -0
  21. package/front_end/entrypoints/devtools_app/devtools_app.ts +1 -1
  22. package/front_end/entrypoints/formatter_worker/CSSFormatter.ts +13 -4
  23. package/front_end/entrypoints/formatter_worker/FormatterWorker.ts +23 -4
  24. package/front_end/entrypoints/formatter_worker/HTMLFormatter.ts +7 -6
  25. package/front_end/entrypoints/inspector_main/InspectorMain.ts +1 -11
  26. package/front_end/entrypoints/inspector_main/inspector_main-meta.ts +1 -1
  27. package/front_end/entrypoints/main/GlobalAiButton.ts +29 -35
  28. package/front_end/entrypoints/main/MainImpl.ts +7 -34
  29. package/front_end/entrypoints/main/main-meta.ts +9 -9
  30. package/front_end/entrypoints/node_app/app/NodeConnectionsPanel.ts +7 -8
  31. package/front_end/entrypoints/node_app/app/NodeMain.ts +3 -3
  32. package/front_end/entrypoints/node_app/node_app.ts +7 -7
  33. package/front_end/foundation/Universe.ts +60 -1
  34. package/front_end/generated/InspectorBackendCommands.ts +1 -1
  35. package/front_end/generated/protocol.ts +4 -0
  36. package/front_end/models/ai_assistance/AiUtils.ts +6 -6
  37. package/front_end/models/bindings/CSSWorkspaceBinding.ts +8 -5
  38. package/front_end/models/bindings/DebuggerLanguagePlugins.ts +13 -15
  39. package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +6 -3
  40. package/front_end/models/bindings/FileUtils.ts +11 -12
  41. package/front_end/models/emulation/DeviceModeModel.ts +56 -37
  42. package/front_end/models/emulation/EmulatedDevices.ts +3 -3
  43. package/front_end/models/live-metrics/LiveMetrics.ts +47 -23
  44. package/front_end/models/project_settings/ProjectSettingsModel.ts +2 -37
  45. package/front_end/models/workspace/FileManager.ts +9 -6
  46. package/front_end/models/workspace_diff/WorkspaceDiff.ts +23 -12
  47. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +2 -1
  48. package/front_end/panels/application/ApplicationPanelSidebar.ts +9 -1
  49. package/front_end/panels/application/BackgroundServiceView.ts +2 -1
  50. package/front_end/panels/application/IndexedDBViews.ts +52 -23
  51. package/front_end/panels/application/ServiceWorkersView.ts +9 -20
  52. package/front_end/panels/application/components/AdsView.ts +1 -1
  53. package/front_end/panels/application/components/StorageMetadataView.ts +7 -2
  54. package/front_end/panels/application/resourcesSidebar.css +5 -0
  55. package/front_end/panels/common/BadgeNotification.ts +1 -1
  56. package/front_end/panels/console/ConsoleContextSelector.ts +3 -3
  57. package/front_end/panels/console/ConsoleInsightTeaser.ts +2 -1
  58. package/front_end/panels/console/ConsolePinPane.ts +10 -10
  59. package/front_end/panels/console/ConsolePrompt.ts +4 -4
  60. package/front_end/panels/console/ConsoleSidebar.ts +7 -7
  61. package/front_end/panels/console/ConsoleView.ts +44 -43
  62. package/front_end/panels/console/ConsoleViewMessage.ts +40 -40
  63. package/front_end/panels/console/console-meta.ts +34 -34
  64. package/front_end/panels/coverage/CoverageView.ts +1 -1
  65. package/front_end/panels/developer_resources/DeveloperResourcesListView.ts +19 -20
  66. package/front_end/panels/developer_resources/DeveloperResourcesView.ts +6 -8
  67. package/front_end/panels/developer_resources/developer_resources-meta.ts +2 -2
  68. package/front_end/panels/elements/ElementsTreeElement.ts +253 -144
  69. package/front_end/panels/elements/ElementsTreeOutline.ts +3 -2
  70. package/front_end/panels/elements/components/AdornerManager.ts +1 -0
  71. package/front_end/panels/emulation/DeviceModeToolbar.ts +19 -19
  72. package/front_end/panels/explain/components/ConsoleInsight.ts +2 -1
  73. package/front_end/panels/media/EventDisplayTable.ts +2 -2
  74. package/front_end/panels/media/EventTimelineView.ts +4 -4
  75. package/front_end/panels/media/MainView.ts +4 -4
  76. package/front_end/panels/media/PlayerDetailView.ts +5 -5
  77. package/front_end/panels/media/PlayerListView.ts +1 -1
  78. package/front_end/panels/media/PlayerMessagesView.ts +12 -12
  79. package/front_end/panels/media/PlayerPropertiesView.ts +17 -17
  80. package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +13 -12
  81. package/front_end/panels/mobile_throttling/ThrottlingManager.ts +8 -7
  82. package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +6 -7
  83. package/front_end/panels/mobile_throttling/mobile_throttling-meta.ts +3 -2
  84. package/front_end/panels/network/NetworkLogView.ts +2 -1
  85. package/front_end/panels/network/NetworkWaterfallColumn.ts +1 -3
  86. package/front_end/panels/network/RequestConditionsDrawer.ts +2 -2
  87. package/front_end/panels/network/networkPanel.css +1 -0
  88. package/front_end/panels/network/networkTimingTable.css +1 -1
  89. package/front_end/panels/profiler/HeapSnapshotView.ts +2 -1
  90. package/front_end/panels/profiler/ProfileView.ts +2 -1
  91. package/front_end/panels/protocol_monitor/JSONEditor.ts +10 -10
  92. package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +28 -32
  93. package/front_end/panels/protocol_monitor/protocol_monitor-meta.ts +1 -1
  94. package/front_end/panels/recorder/RecorderController.ts +1 -0
  95. package/front_end/panels/recorder/RecorderEvents.ts +8 -0
  96. package/front_end/panels/settings/components/SyncSection.ts +2 -1
  97. package/front_end/panels/timeline/AppenderUtils.ts +12 -4
  98. package/front_end/panels/timeline/ThreadAppender.ts +3 -3
  99. package/front_end/panels/timeline/TimelinePanel.ts +5 -5
  100. package/front_end/panels/timeline/timelineFlameChartView.css +2 -1
  101. package/front_end/panels/webauthn/WebauthnPane.ts +10 -10
  102. package/front_end/third_party/chromium/README.chromium +1 -1
  103. package/front_end/third_party/chromium/ahem/ahem.js +792 -0
  104. package/front_end/tsconfig.json +7 -1
  105. package/front_end/ui/components/dialogs/shortcutDialog.css +15 -12
  106. package/front_end/ui/legacy/ActionRegistration.ts +1 -1
  107. package/front_end/ui/legacy/InspectorView.ts +1 -1
  108. package/front_end/ui/legacy/Treeoutline.ts +15 -0
  109. package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +109 -23
  110. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +5 -0
  111. package/front_end/ui/legacy/theme_support/ThemeSupport.ts +2 -2
  112. package/front_end/ui/visual_logging/KnownContextValues.ts +4 -0
  113. package/package.json +1 -1
@@ -7040,6 +7040,10 @@ export namespace DigitalCredentials {
7040
7040
  * Required when |action| is "respond", forbidden otherwise.
7041
7041
  */
7042
7042
  response?: any;
7043
+ /**
7044
+ * The frame to scope the virtual wallet behavior to.
7045
+ */
7046
+ frameId?: Page.FrameId;
7043
7047
  }
7044
7048
  }
7045
7049
 
@@ -12,21 +12,21 @@ import {debugLog} from './debug.js';
12
12
 
13
13
  const UIStrings = {
14
14
  /**
15
- * @description Message shown to the user if the age check is not successful.
15
+ * @description Message shown to the user if the age check isn’t successful.
16
16
  */
17
- ageRestricted: 'This feature is only available to users who are 18 years of age or older.',
17
+ ageRestricted: 'This feature is only available to users 18 years or older.',
18
18
  /**
19
- * @description The error message when the user is not logged in into Chrome.
19
+ * @description The error message when the user isn’t logged in to Chrome.
20
20
  */
21
- notLoggedIn: 'This feature is only available when you sign into Chrome with your Google account.',
21
+ notLoggedIn: 'This feature is only available when you sign in to Chrome with your Google account.',
22
22
  /**
23
23
  * @description Message shown when the user is offline.
24
24
  */
25
25
  offline: 'This feature is only available with an active internet connection.',
26
26
  /**
27
- * @description Text informing the user that AI assistance is not available in Incognito mode or Guest mode.
27
+ * @description Text informing the user that AI assistance isn’t available in Incognito mode or Guest mode.
28
28
  */
29
- notAvailableInIncognitoMode: 'AI assistance is not available in Incognito mode or Guest mode.',
29
+ notAvailableInIncognitoMode: 'AI assistance isn’t available in Incognito mode or Guest mode.',
30
30
  } as const;
31
31
  const str_ = i18n.i18n.registerUIStrings('models/ai_assistance/AiUtils.ts', UIStrings);
32
32
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
@@ -152,6 +152,7 @@ export interface SourceMapping {
152
152
 
153
153
  export class ModelInfo {
154
154
  readonly #eventListeners: Common.EventTarget.EventDescriptor[];
155
+ readonly #cssWorkspaceBinding: CSSWorkspaceBinding;
155
156
  readonly #resourceMapping: ResourceMapping;
156
157
  #stylesSourceMapping: StylesSourceMapping;
157
158
  #sassSourceMapping: SASSSourceMapping;
@@ -159,6 +160,7 @@ export class ModelInfo {
159
160
  readonly #unboundLocations: Platform.MapUtilities.Multimap<Platform.DevToolsPath.UrlString, LiveLocation>;
160
161
  constructor(
161
162
  cssModel: SDK.CSSModel.CSSModel, resourceMapping: ResourceMapping, cssWorkspaceBinding: CSSWorkspaceBinding) {
163
+ this.#cssWorkspaceBinding = cssWorkspaceBinding;
162
164
  this.#eventListeners = [
163
165
  cssModel.addEventListener(
164
166
  SDK.CSSModel.Events.StyleSheetAdded,
@@ -191,7 +193,7 @@ export class ModelInfo {
191
193
  async createLiveLocation(
192
194
  rawLocation: SDK.CSSModel.CSSLocation, updateDelegate: (arg0: LiveLocationInterface) => Promise<void>,
193
195
  locationPool: LiveLocationPool): Promise<LiveLocation> {
194
- const location = new LiveLocation(rawLocation, this, updateDelegate, locationPool);
196
+ const location = new LiveLocation(rawLocation, this, this.#cssWorkspaceBinding, updateDelegate, locationPool);
195
197
  const header = rawLocation.header();
196
198
  if (header) {
197
199
  location.setHeader(header);
@@ -286,15 +288,16 @@ export class LiveLocation extends LiveLocationWithPool {
286
288
  readonly #lineNumber: number;
287
289
  readonly #columnNumber: number;
288
290
  readonly #info: ModelInfo;
291
+ readonly #cssWorkspaceBinding: CSSWorkspaceBinding;
289
292
  #header: SDK.CSSStyleSheetHeader.CSSStyleSheetHeader|null;
290
- constructor(
291
- rawLocation: SDK.CSSModel.CSSLocation, info: ModelInfo,
292
- updateDelegate: (arg0: LiveLocationInterface) => Promise<void>, locationPool: LiveLocationPool) {
293
+ constructor(rawLocation: SDK.CSSModel.CSSLocation, info: ModelInfo, cssWorkspaceBinding: CSSWorkspaceBinding,
294
+ updateDelegate: (arg0: LiveLocationInterface) => Promise<void>, locationPool: LiveLocationPool) {
293
295
  super(updateDelegate, locationPool);
294
296
  this.url = rawLocation.url;
295
297
  this.#lineNumber = rawLocation.lineNumber;
296
298
  this.#columnNumber = rawLocation.columnNumber;
297
299
  this.#info = info;
300
+ this.#cssWorkspaceBinding = cssWorkspaceBinding;
298
301
  this.#header = null;
299
302
  }
300
303
 
@@ -311,7 +314,7 @@ export class LiveLocation extends LiveLocationWithPool {
311
314
  return null;
312
315
  }
313
316
  const rawLocation = new SDK.CSSModel.CSSLocation(this.#header, this.#lineNumber, this.#columnNumber);
314
- return CSSWorkspaceBinding.instance().rawLocationToUILocation(rawLocation);
317
+ return this.#cssWorkspaceBinding.rawLocationToUILocation(rawLocation);
315
318
  }
316
319
 
317
320
  override dispose(): void {
@@ -404,6 +404,7 @@ export class DebuggerLanguagePluginManager implements
404
404
  SDK.TargetManager.SDKModelObserver<SDK.DebuggerModel.DebuggerModel> {
405
405
  readonly #workspace: Workspace.Workspace.WorkspaceImpl;
406
406
  readonly #debuggerWorkspaceBinding: DebuggerWorkspaceBinding;
407
+ readonly #console: Common.Console.Console;
407
408
  #plugins: DebuggerLanguagePlugin[];
408
409
  readonly #debuggerModelToData: Map<SDK.DebuggerModel.DebuggerModel, ModelData>;
409
410
  readonly #rawModuleHandles: Map<string, {
@@ -417,11 +418,11 @@ export class DebuggerLanguagePluginManager implements
417
418
  private readonly stopIdByCallFrame = new Map<SDK.DebuggerModel.CallFrame, StopId>();
418
419
  private nextStopId: StopId = 0n;
419
420
 
420
- constructor(
421
- targetManager: SDK.TargetManager.TargetManager, workspace: Workspace.Workspace.WorkspaceImpl,
422
- debuggerWorkspaceBinding: DebuggerWorkspaceBinding) {
421
+ constructor(targetManager: SDK.TargetManager.TargetManager, workspace: Workspace.Workspace.WorkspaceImpl,
422
+ debuggerWorkspaceBinding: DebuggerWorkspaceBinding, console: Common.Console.Console) {
423
423
  this.#workspace = workspace;
424
424
  this.#debuggerWorkspaceBinding = debuggerWorkspaceBinding;
425
+ this.#console = console;
425
426
 
426
427
  this.#plugins = [];
427
428
 
@@ -511,8 +512,8 @@ export class DebuggerLanguagePluginManager implements
511
512
  const scripts = rawModuleHandle.scripts.filter(script => script.debuggerModel !== debuggerModel);
512
513
  if (scripts.length === 0) {
513
514
  rawModuleHandle.plugin.removeRawModule(rawModuleId).catch(error => {
514
- Common.Console.Console.instance().error(
515
- i18nString(UIStrings.errorInDebuggerLanguagePlugin, {PH1: error.message}), /* show=*/ false);
515
+ this.#console.error(i18nString(UIStrings.errorInDebuggerLanguagePlugin, {PH1: error.message}),
516
+ /* show=*/ false);
516
517
  });
517
518
  this.#rawModuleHandles.delete(rawModuleId);
518
519
  } else {
@@ -633,8 +634,7 @@ export class DebuggerLanguagePluginManager implements
633
634
  sourceLocation.lineNumber, sourceLocation.columnNumber >= 0 ? sourceLocation.columnNumber : undefined);
634
635
  }
635
636
  } catch (error) {
636
- Common.Console.Console.instance().error(
637
- i18nString(UIStrings.errorInDebuggerLanguagePlugin, {PH1: error.message}), /* show=*/ false);
637
+ this.#console.error(i18nString(UIStrings.errorInDebuggerLanguagePlugin, {PH1: error.message}), /* show=*/ false);
638
638
  }
639
639
  return null;
640
640
  }
@@ -663,8 +663,7 @@ export class DebuggerLanguagePluginManager implements
663
663
  }
664
664
 
665
665
  return Promise.all(locationPromises).then(locations => locations.flat()).catch(error => {
666
- Common.Console.Console.instance().error(
667
- i18nString(UIStrings.errorInDebuggerLanguagePlugin, {PH1: error.message}), /* show=*/ false);
666
+ this.#console.error(i18nString(UIStrings.errorInDebuggerLanguagePlugin, {PH1: error.message}), /* show=*/ false);
668
667
  return null;
669
668
  });
670
669
 
@@ -841,7 +840,7 @@ export class DebuggerLanguagePluginManager implements
841
840
  let rawModuleHandle = this.#rawModuleHandles.get(rawModuleId);
842
841
  if (!rawModuleHandle) {
843
842
  const sourceFileURLsPromise = (async () => {
844
- const console = Common.Console.Console.instance();
843
+ const console = this.#console;
845
844
  const url = script.sourceURL;
846
845
  const symbolsUrl = (script.debugSymbols?.externalURL) || '';
847
846
  if (symbolsUrl) {
@@ -962,8 +961,7 @@ export class DebuggerLanguagePluginManager implements
962
961
  }
963
962
  return Array.from(scopes.values());
964
963
  } catch (error) {
965
- Common.Console.Console.instance().error(
966
- i18nString(UIStrings.errorInDebuggerLanguagePlugin, {PH1: error.message}), /* show=*/ false);
964
+ this.#console.error(i18nString(UIStrings.errorInDebuggerLanguagePlugin, {PH1: error.message}), /* show=*/ false);
967
965
  return null;
968
966
  }
969
967
  }
@@ -995,7 +993,7 @@ export class DebuggerLanguagePluginManager implements
995
993
  }
996
994
  return functionInfo;
997
995
  } catch (error) {
998
- Common.Console.Console.instance().warn(i18nString(UIStrings.errorInDebuggerLanguagePlugin, {PH1: error.message}));
996
+ this.#console.warn(i18nString(UIStrings.errorInDebuggerLanguagePlugin, {PH1: error.message}));
999
997
  return {frames: []};
1000
998
  }
1001
999
  }
@@ -1032,7 +1030,7 @@ export class DebuggerLanguagePluginManager implements
1032
1030
  script.debuggerModel, script.scriptId, 0, Number(m.endOffset) + (script.codeOffset() || 0)),
1033
1031
  }));
1034
1032
  } catch (error) {
1035
- Common.Console.Console.instance().warn(i18nString(UIStrings.errorInDebuggerLanguagePlugin, {PH1: error.message}));
1033
+ this.#console.warn(i18nString(UIStrings.errorInDebuggerLanguagePlugin, {PH1: error.message}));
1036
1034
  return [];
1037
1035
  }
1038
1036
  }
@@ -1069,7 +1067,7 @@ export class DebuggerLanguagePluginManager implements
1069
1067
  script.debuggerModel, script.scriptId, 0, Number(m.endOffset) + (script.codeOffset() || 0)),
1070
1068
  }));
1071
1069
  } catch (error) {
1072
- Common.Console.Console.instance().warn(i18nString(UIStrings.errorInDebuggerLanguagePlugin, {PH1: error.message}));
1070
+ this.#console.warn(i18nString(UIStrings.errorInDebuggerLanguagePlugin, {PH1: error.message}));
1073
1071
  return [];
1074
1072
  }
1075
1073
  }
@@ -2,7 +2,7 @@
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 Common from '../../core/common/common.js';
5
+ import type * as Common from '../../core/common/common.js';
6
6
  import * as Platform from '../../core/platform/platform.js';
7
7
  import * as Root from '../../core/root/root.js';
8
8
  import * as SDK from '../../core/sdk/sdk.js';
@@ -34,6 +34,7 @@ export class DebuggerWorkspaceBinding implements SDK.TargetManager.SDKModelObser
34
34
  readonly pluginManager: DebuggerLanguagePluginManager;
35
35
  readonly ignoreListManager: Workspace.IgnoreListManager.IgnoreListManager;
36
36
  readonly workspace: Workspace.Workspace.WorkspaceImpl;
37
+ readonly #settings: Common.Settings.Settings;
37
38
 
38
39
  constructor(
39
40
  resourceMapping: ResourceMapping, targetManager: SDK.TargetManager.TargetManager,
@@ -42,6 +43,7 @@ export class DebuggerWorkspaceBinding implements SDK.TargetManager.SDKModelObser
42
43
  this.resourceMapping.debuggerWorkspaceBinding = this;
43
44
  this.ignoreListManager = ignoreListManager;
44
45
  this.workspace = workspace;
46
+ this.#settings = targetManager.settings;
45
47
 
46
48
  this.#debuggerModelToData = new Map();
47
49
  targetManager.observeModels(SDK.DebuggerModel.DebuggerModel, this);
@@ -50,7 +52,8 @@ export class DebuggerWorkspaceBinding implements SDK.TargetManager.SDKModelObser
50
52
 
51
53
  this.#liveLocationPromises = new Set();
52
54
 
53
- this.pluginManager = new DebuggerLanguagePluginManager(targetManager, resourceMapping.workspace, this);
55
+ this.pluginManager =
56
+ new DebuggerLanguagePluginManager(targetManager, resourceMapping.workspace, this, targetManager.getConsole());
54
57
  }
55
58
 
56
59
  setFunctionRanges(
@@ -489,7 +492,7 @@ export class DebuggerWorkspaceBinding implements SDK.TargetManager.SDKModelObser
489
492
  }
490
493
  const functionLocation = frame.functionLocation();
491
494
  if (!autoSteppingContext || debuggerPausedDetails.reason !== Protocol.Debugger.PausedEventReason.Step ||
492
- !functionLocation || !frame.script.isWasm() || !Common.Settings.moduleSetting('wasm-auto-stepping').get() ||
495
+ !functionLocation || !frame.script.isWasm() || !this.#settings.moduleSetting('wasm-auto-stepping').get() ||
493
496
  !this.pluginManager.hasPluginForScript(frame.script)) {
494
497
  return true;
495
498
  }
@@ -170,10 +170,12 @@ export class ChunkedFileReader implements ChunkedReader {
170
170
  }
171
171
 
172
172
  export class FileOutputStream implements Common.StringOutputStream.OutputStream {
173
+ readonly #fileManager: Workspace.FileManager.FileManager;
173
174
  #writeCallbacks: Array<() => void>;
174
175
  #fileName!: Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString;
175
176
  #closed?: boolean;
176
- constructor() {
177
+ constructor(fileManager: Workspace.FileManager.FileManager) {
178
+ this.#fileManager = fileManager;
177
179
  this.#writeCallbacks = [];
178
180
  }
179
181
 
@@ -181,11 +183,10 @@ export class FileOutputStream implements Common.StringOutputStream.OutputStream
181
183
  this.#closed = false;
182
184
  this.#writeCallbacks = [];
183
185
  this.#fileName = fileName;
184
- const saveResponse = await Workspace.FileManager.FileManager.instance().save(
185
- this.#fileName, TextUtils.ContentData.EMPTY_TEXT_CONTENT_DATA, /* forceSaveAs=*/ true);
186
+ const saveResponse = await this.#fileManager.save(this.#fileName, TextUtils.ContentData.EMPTY_TEXT_CONTENT_DATA,
187
+ /* forceSaveAs=*/ true);
186
188
  if (saveResponse) {
187
- Workspace.FileManager.FileManager.instance().addEventListener(
188
- Workspace.FileManager.Events.APPENDED_TO_URL, this.onAppendDone, this);
189
+ this.#fileManager.addEventListener(Workspace.FileManager.Events.APPENDED_TO_URL, this.onAppendDone, this);
189
190
  }
190
191
  return Boolean(saveResponse);
191
192
  }
@@ -193,7 +194,7 @@ export class FileOutputStream implements Common.StringOutputStream.OutputStream
193
194
  write(data: string): Promise<void> {
194
195
  return new Promise(resolve => {
195
196
  this.#writeCallbacks.push(resolve);
196
- Workspace.FileManager.FileManager.instance().append(this.#fileName, data);
197
+ this.#fileManager.append(this.#fileName, data);
197
198
  });
198
199
  }
199
200
 
@@ -202,9 +203,8 @@ export class FileOutputStream implements Common.StringOutputStream.OutputStream
202
203
  if (this.#writeCallbacks.length) {
203
204
  return;
204
205
  }
205
- Workspace.FileManager.FileManager.instance().removeEventListener(
206
- Workspace.FileManager.Events.APPENDED_TO_URL, this.onAppendDone, this);
207
- Workspace.FileManager.FileManager.instance().close(this.#fileName);
206
+ this.#fileManager.removeEventListener(Workspace.FileManager.Events.APPENDED_TO_URL, this.onAppendDone, this);
207
+ this.#fileManager.close(this.#fileName);
208
208
  }
209
209
 
210
210
  private onAppendDone(event: Common.EventTarget.EventTargetEvent<string>): void {
@@ -221,8 +221,7 @@ export class FileOutputStream implements Common.StringOutputStream.OutputStream
221
221
  if (!this.#closed) {
222
222
  return;
223
223
  }
224
- Workspace.FileManager.FileManager.instance().removeEventListener(
225
- Workspace.FileManager.Events.APPENDED_TO_URL, this.onAppendDone, this);
226
- Workspace.FileManager.FileManager.instance().close(this.#fileName);
224
+ this.#fileManager.removeEventListener(Workspace.FileManager.Events.APPENDED_TO_URL, this.onAppendDone, this);
225
+ this.#fileManager.close(this.#fileName);
227
226
  }
228
227
  }
@@ -5,6 +5,7 @@
5
5
  import * as Common from '../../core/common/common.js';
6
6
  import * as Host from '../../core/host/host.js';
7
7
  import * as i18n from '../../core/i18n/i18n.js';
8
+ import * as Root from '../../core/root/root.js';
8
9
  import * as SDK from '../../core/sdk/sdk.js';
9
10
  import * as Protocol from '../../generated/protocol.js';
10
11
  import * as Geometry from '../geometry/geometry.js';
@@ -20,62 +21,62 @@ import {
20
21
 
21
22
  const UIStrings = {
22
23
  /**
23
- * @description Error message shown in the Devices settings pane when the user enters an empty
24
+ * @description Error message shown on the Devices settings tab when the user enters an empty
24
25
  * width for a custom device.
25
26
  */
26
- widthCannotBeEmpty: 'Width cannot be empty.',
27
+ widthCannotBeEmpty: 'Width can’t be empty.',
27
28
  /**
28
- * @description Error message shown in the Devices settings pane when the user enters an invalid
29
+ * @description Error message shown on the Devices settings tab when the user enters an invalid
29
30
  * width for a custom device.
30
31
  */
31
32
  widthMustBeANumber: 'Width must be a number.',
32
33
  /**
33
- * @description Error message shown in the Devices settings pane when the user has entered a width
34
+ * @description Error message shown on the Devices settings tab when the user has entered a width
34
35
  * for a custom device that is too large.
35
36
  * @example {9999} PH1
36
37
  */
37
38
  widthMustBeLessThanOrEqualToS: 'Width must be less than or equal to {PH1}.',
38
39
  /**
39
- * @description Error message shown in the Devices settings pane when the user has entered a width
40
+ * @description Error message shown on the Devices settings tab when the user has entered a width
40
41
  * for a custom device that is too small.
41
42
  * @example {50} PH1
42
43
  */
43
44
  widthMustBeGreaterThanOrEqualToS: 'Width must be greater than or equal to {PH1}.',
44
45
  /**
45
- * @description Error message shown in the Devices settings pane when the user enters an empty
46
+ * @description Error message shown on the Devices settings tab when the user enters an empty
46
47
  * height for a custom device.
47
48
  */
48
- heightCannotBeEmpty: 'Height cannot be empty.',
49
+ heightCannotBeEmpty: 'Height can’t be empty.',
49
50
  /**
50
- * @description Error message shown in the Devices settings pane when the user enters an invalid
51
+ * @description Error message shown on the Devices settings tab when the user enters an invalid
51
52
  * height for a custom device.
52
53
  */
53
54
  heightMustBeANumber: 'Height must be a number.',
54
55
  /**
55
- * @description Error message shown in the Devices settings pane when the user has entered a height
56
+ * @description Error message shown on the Devices settings tab when the user has entered a height
56
57
  * for a custom device that is too large.
57
58
  * @example {9999} PH1
58
59
  */
59
60
  heightMustBeLessThanOrEqualToS: 'Height must be less than or equal to {PH1}.',
60
61
  /**
61
- * @description Error message shown in the Devices settings pane when the user has entered a height
62
+ * @description Error message shown on the Devices settings tab when the user has entered a height
62
63
  * for a custom device that is too small.
63
64
  * @example {50} PH1
64
65
  */
65
66
  heightMustBeGreaterThanOrEqualTo: 'Height must be greater than or equal to {PH1}.',
66
67
  /**
67
- * @description Error message shown in the Devices settings pane when the user enters an invalid
68
+ * @description Error message shown on the Devices settings tab when the user enters an invalid
68
69
  * device pixel ratio for a custom device.
69
70
  */
70
71
  devicePixelRatioMustBeANumberOr: 'Device pixel ratio must be a number or blank.',
71
72
  /**
72
- * @description Error message shown in the Devices settings pane when the user enters a device
73
+ * @description Error message shown on the Devices settings tab when the user enters a device
73
74
  * pixel ratio for a custom device that is too large.
74
75
  * @example {10} PH1
75
76
  */
76
77
  devicePixelRatioMustBeLessThanOr: 'Device pixel ratio must be less than or equal to {PH1}.',
77
78
  /**
78
- * @description Error message shown in the Devices settings pane when the user enters a device
79
+ * @description Error message shown on the Devices settings tab when the user enters a device
79
80
  * pixel ratio for a custom device that is too small.
80
81
  * @example {0} PH1
81
82
  */
@@ -84,8 +85,6 @@ const UIStrings = {
84
85
  const str_ = i18n.i18n.registerUIStrings('models/emulation/DeviceModeModel.ts', UIStrings);
85
86
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
86
87
 
87
- let deviceModeModelInstance: DeviceModeModel|null;
88
-
89
88
  export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTypes> implements
90
89
  SDK.TargetManager.SDKModelObserver<SDK.EmulationModel.EmulationModel> {
91
90
  #screenRect: Rect;
@@ -114,9 +113,19 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
114
113
  #onModelAvailable: (() => void)|null;
115
114
  #outlineRect?: Rect;
116
115
  #screenOrientationLocked: boolean;
117
-
118
- private constructor() {
116
+ readonly #targetManager: SDK.TargetManager.TargetManager;
117
+ readonly #settings: Common.Settings.Settings;
118
+ readonly #multitargetNetworkManager: SDK.NetworkManager.MultitargetNetworkManager;
119
+
120
+ constructor(
121
+ targetManager: SDK.TargetManager.TargetManager,
122
+ settings: Common.Settings.Settings,
123
+ multitargetNetworkManager: SDK.NetworkManager.MultitargetNetworkManager,
124
+ ) {
119
125
  super();
126
+ this.#targetManager = targetManager;
127
+ this.#settings = settings;
128
+ this.#multitargetNetworkManager = multitargetNetworkManager;
120
129
  this.#screenRect = new Rect(0, 0, 1, 1);
121
130
  this.#visiblePageRect = new Rect(0, 0, 1, 1);
122
131
  this.#availableSize = new Geometry.Size(1, 1);
@@ -126,7 +135,7 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
126
135
  this.#appliedDeviceScaleFactor = globalThis.devicePixelRatio;
127
136
  this.#appliedUserAgentType = UA.DESKTOP;
128
137
 
129
- this.#scaleSetting = Common.Settings.Settings.instance().createSetting('emulation.device-scale', 1);
138
+ this.#scaleSetting = this.#settings.createSetting('emulation.device-scale', 1);
130
139
  // We've used to allow zero before.
131
140
  if (!this.#scaleSetting.get()) {
132
141
  this.#scaleSetting.set(1);
@@ -134,7 +143,7 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
134
143
  this.#scaleSetting.addChangeListener(this.scaleSettingChanged, this);
135
144
  this.#scale = 1;
136
145
 
137
- this.#widthSetting = Common.Settings.Settings.instance().createSetting('emulation.device-width', 400);
146
+ this.#widthSetting = this.#settings.createSetting('emulation.device-width', 400);
138
147
  if (this.#widthSetting.get() < MinDeviceSize) {
139
148
  this.#widthSetting.set(MinDeviceSize);
140
149
  }
@@ -143,7 +152,7 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
143
152
  }
144
153
  this.#widthSetting.addChangeListener(this.widthSettingChanged, this);
145
154
 
146
- this.#heightSetting = Common.Settings.Settings.instance().createSetting('emulation.device-height', 0);
155
+ this.#heightSetting = this.#settings.createSetting('emulation.device-height', 0);
147
156
  if (this.#heightSetting.get() && this.#heightSetting.get() < MinDeviceSize) {
148
157
  this.#heightSetting.set(MinDeviceSize);
149
158
  }
@@ -152,17 +161,16 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
152
161
  }
153
162
  this.#heightSetting.addChangeListener(this.heightSettingChanged, this);
154
163
 
155
- this.#uaSetting = Common.Settings.Settings.instance().createSetting('emulation.device-ua', UA.MOBILE);
164
+ this.#uaSetting = this.#settings.createSetting('emulation.device-ua', UA.MOBILE);
156
165
  this.#uaSetting.addChangeListener(this.uaSettingChanged, this);
157
- this.#deviceScaleFactorSetting =
158
- Common.Settings.Settings.instance().createSetting('emulation.device-scale-factor', 0);
166
+ this.#deviceScaleFactorSetting = this.#settings.createSetting('emulation.device-scale-factor', 0);
159
167
  this.#deviceScaleFactorSetting.addChangeListener(this.deviceScaleFactorSettingChanged, this);
160
168
 
161
- this.#deviceOutlineSetting = Common.Settings.Settings.instance().moduleSetting('emulation.show-device-outline');
169
+ this.#deviceOutlineSetting = this.#settings.moduleSetting('emulation.show-device-outline');
162
170
  this.#deviceOutlineSetting.addChangeListener(this.deviceOutlineSettingChanged, this);
163
171
 
164
- this.#toolbarControlsEnabledSetting = Common.Settings.Settings.instance().createSetting(
165
- 'emulation.toolbar-controls-enabled', true, Common.Settings.SettingStorageType.SESSION);
172
+ this.#toolbarControlsEnabledSetting = this.#settings.createSetting('emulation.toolbar-controls-enabled', true,
173
+ Common.Settings.SettingStorageType.SESSION);
166
174
 
167
175
  this.#type = Type.None;
168
176
  this.#device = null;
@@ -174,15 +182,20 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
174
182
  this.#emulationModel = null;
175
183
  this.#onModelAvailable = null;
176
184
  this.#screenOrientationLocked = false;
177
- SDK.TargetManager.TargetManager.instance().observeModels(SDK.EmulationModel.EmulationModel, this);
185
+ this.#targetManager.observeModels(SDK.EmulationModel.EmulationModel, this);
178
186
  }
179
187
 
180
188
  static instance(opts?: {forceNew: boolean}): DeviceModeModel {
181
- if (!deviceModeModelInstance || opts?.forceNew) {
182
- deviceModeModelInstance = new DeviceModeModel();
189
+ if (!Root.DevToolsContext.globalInstance().has(DeviceModeModel) || opts?.forceNew) {
190
+ Root.DevToolsContext.globalInstance().set(DeviceModeModel,
191
+ new DeviceModeModel(
192
+ SDK.TargetManager.TargetManager.instance(),
193
+ Common.Settings.Settings.instance(),
194
+ SDK.NetworkManager.MultitargetNetworkManager.instance(),
195
+ ));
183
196
  }
184
197
 
185
- return deviceModeModelInstance;
198
+ return Root.DevToolsContext.globalInstance().get(DeviceModeModel);
186
199
  }
187
200
 
188
201
  /**
@@ -201,11 +214,14 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
201
214
  }
202
215
 
203
216
  static removeInstance(): void {
204
- deviceModeModelInstance = null;
217
+ if (Root.DevToolsContext.globalInstance().has(DeviceModeModel)) {
218
+ Root.DevToolsContext.globalInstance().get(DeviceModeModel).dispose();
219
+ }
220
+ Root.DevToolsContext.globalInstance().delete(DeviceModeModel);
205
221
  }
206
222
 
207
223
  dispose(): void {
208
- SDK.TargetManager.TargetManager.instance().unobserveModels(SDK.EmulationModel.EmulationModel, this);
224
+ this.#targetManager.unobserveModels(SDK.EmulationModel.EmulationModel, this);
209
225
  }
210
226
 
211
227
  static widthValidator(value: string): {
@@ -363,6 +379,10 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
363
379
  '';
364
380
  }
365
381
 
382
+ canShowDeviceFrame(): boolean {
383
+ return Boolean(this.#device && this.#mode && this.#device.outlineImage(this.#mode));
384
+ }
385
+
366
386
  outlineRect(): Rect|null {
367
387
  return this.#outlineRect || null;
368
388
  }
@@ -412,7 +432,7 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
412
432
  }
413
433
 
414
434
  enabledSetting(): Common.Settings.Setting<boolean> {
415
- return Common.Settings.Settings.instance().createSetting('emulation.show-device-mode', false);
435
+ return this.#settings.createSetting('emulation.show-device-mode', false);
416
436
  }
417
437
 
418
438
  scaleSetting(): Common.Settings.Setting<number> {
@@ -444,7 +464,7 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
444
464
  }
445
465
 
446
466
  modelAdded(emulationModel: SDK.EmulationModel.EmulationModel): void {
447
- if (emulationModel.target() === SDK.TargetManager.TargetManager.instance().primaryPageTarget() &&
467
+ if (emulationModel.target() === this.#targetManager.primaryPageTarget() &&
448
468
  emulationModel.supportsDeviceEmulation()) {
449
469
  this.#emulationModel = emulationModel;
450
470
  if (this.#onModelAvailable) {
@@ -713,8 +733,7 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
713
733
  // When the user agent string is empty (e.g. custom desktop device without
714
734
  // a UA override), metadata must also be cleared. The backend rejects
715
735
  // setUserAgentOverride calls that provide metadata without a UA string.
716
- SDK.NetworkManager.MultitargetNetworkManager.instance().setUserAgentOverride(
717
- userAgent, userAgent ? userAgentMetadata : null);
736
+ this.#multitargetNetworkManager.setUserAgentOverride(userAgent, userAgent ? userAgentMetadata : null);
718
737
  }
719
738
 
720
739
  private applyDeviceMetrics(
@@ -854,7 +873,7 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
854
873
  private applyTouch(touchEnabled: boolean, mobile: boolean): void {
855
874
  this.#touchEnabled = touchEnabled;
856
875
  this.#touchMobile = mobile;
857
- for (const emulationModel of SDK.TargetManager.TargetManager.instance().models(SDK.EmulationModel.EmulationModel)) {
876
+ for (const emulationModel of this.#targetManager.models(SDK.EmulationModel.EmulationModel)) {
858
877
  void emulationModel.emulateTouch(touchEnabled, mobile);
859
878
  }
860
879
  }
@@ -14,15 +14,15 @@ import {Insets, MaxDeviceSize, MinDeviceSize} from './DeviceModeModel.js';
14
14
 
15
15
  const UIStrings = {
16
16
  /**
17
- * @description Title of the Laptop with touch device
17
+ * @description Title of the Laptop with touch device.
18
18
  */
19
19
  laptopWithTouch: 'Laptop with touch',
20
20
  /**
21
- * @description Title of the Laptop with HiDPI screen device
21
+ * @description Title of the Laptop with HiDPI screen device.
22
22
  */
23
23
  laptopWithHiDPIScreen: 'Laptop with HiDPI screen',
24
24
  /**
25
- * @description Title of the Laptop with MDPI screen device
25
+ * @description Title of the Laptop with MDPI screen device.
26
26
  */
27
27
  laptopWithMDPIScreen: 'Laptop with MDPI screen',
28
28
  } as const;