chrome-devtools-frontend 1.0.1661063 → 1.0.1662965

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 (131) hide show
  1. package/.agents/skills/devtools-unicode-escaping/SKILL.md +64 -0
  2. package/.agents/skills/evaluate-ai-css-completion/SKILL.md +19 -9
  3. package/.agents/skills/evaluate-ai-css-completion/scripts/evaluate.js +44 -16
  4. package/.agents/skills/migrate-chromium-test/SKILL.md +32 -2
  5. package/.agents/skills/ui-eng-vision-local-lit-renderer/SKILL.md +7 -1
  6. package/docs/ui_engineering.md +75 -42
  7. package/front_end/core/common/SettingRegistration.ts +0 -10
  8. package/front_end/core/common/Settings.ts +69 -3
  9. package/front_end/core/platform/ArrayUtilities.ts +10 -0
  10. package/front_end/core/platform/StringUtilities.ts +38 -6
  11. package/front_end/core/sdk/ServiceWorkerCacheModel.ts +0 -10
  12. package/front_end/core/sdk/StorageBucketsModel.ts +0 -10
  13. package/front_end/core/sdk/sdk-meta.ts +0 -1
  14. package/front_end/entrypoints/inspector_main/OutermostTargetSelector.ts +0 -13
  15. package/front_end/entrypoints/inspector_main/RenderingOptions.ts +8 -3
  16. package/front_end/entrypoints/inspector_main/inspector_main-meta.ts +3 -3
  17. package/front_end/entrypoints/main/MainImpl.ts +7 -2
  18. package/front_end/foundation/README.md +86 -0
  19. package/front_end/foundation/Universe.ts +16 -0
  20. package/front_end/generated/InspectorBackendCommands.ts +6 -19
  21. package/front_end/generated/protocol-mapping.d.ts +0 -53
  22. package/front_end/generated/protocol-proxy-api.d.ts +0 -46
  23. package/front_end/generated/protocol.ts +20 -186
  24. package/front_end/models/ai_assistance/AiAgent2.ts +3 -3
  25. package/front_end/models/ai_assistance/AiConversation.ts +21 -10
  26. package/front_end/models/ai_assistance/AiHistoryStorage.ts +21 -10
  27. package/front_end/models/ai_assistance/ChangeManager.ts +2 -2
  28. package/front_end/models/ai_assistance/ExtensionScope.ts +6 -2
  29. package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +1 -1
  30. package/front_end/models/ai_assistance/agents/AiAgent.ts +8 -1
  31. package/front_end/models/ai_assistance/agents/StylingAgent.ts +1 -1
  32. package/front_end/models/badges/UserBadges.ts +31 -17
  33. package/front_end/models/bindings/CompilerScriptMapping.ts +5 -4
  34. package/front_end/models/bindings/ContentProviderBasedProject.ts +2 -3
  35. package/front_end/models/bindings/DebuggerLanguagePlugins.ts +4 -3
  36. package/front_end/models/bindings/DefaultScriptMapping.ts +3 -3
  37. package/front_end/models/bindings/NetworkProject.ts +22 -1
  38. package/front_end/models/bindings/ResourceMapping.ts +4 -3
  39. package/front_end/models/bindings/ResourceScriptMapping.ts +2 -1
  40. package/front_end/models/bindings/SASSSourceMapping.ts +4 -3
  41. package/front_end/models/bindings/StylesSourceMapping.ts +3 -3
  42. package/front_end/models/emulation/DeviceModeModel.ts +67 -5
  43. package/front_end/models/extensions/RecorderExtensionEndpoint.ts +7 -5
  44. package/front_end/models/extensions/RecorderPluginManager.ts +10 -6
  45. package/front_end/models/har/Log.snapshot.txt +193 -0
  46. package/front_end/models/har/Log.ts +3 -2
  47. package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +14 -5
  48. package/front_end/models/issues_manager/CheckFormsIssuesTrigger.ts +8 -9
  49. package/front_end/models/issues_manager/RelatedIssue.ts +10 -8
  50. package/front_end/models/javascript_metadata/NativeFunctions.js +1 -1
  51. package/front_end/models/logs/RequestResolver.ts +2 -2
  52. package/front_end/models/persistence/AutomaticFileSystemWorkspaceBinding.ts +0 -5
  53. package/front_end/models/source_map_scopes/FunctionCodeResolver.ts +8 -6
  54. package/front_end/models/source_map_scopes/NamesResolver.ts +36 -30
  55. package/front_end/models/stack_trace/StackTrace.ts +17 -0
  56. package/front_end/models/trace/handlers/FramesHandler.ts +4 -7
  57. package/front_end/models/trace/handlers/ModelHandlers.ts +0 -1
  58. package/front_end/models/trace/handlers/RendererHandler.ts +2 -15
  59. package/front_end/models/trace/handlers/Threads.ts +4 -11
  60. package/front_end/models/trace/insights/DOMSize.ts +1 -1
  61. package/front_end/models/workspace/WorkspaceImpl.ts +1 -10
  62. package/front_end/panels/application/ApplicationPanelSidebar.ts +0 -44
  63. package/front_end/panels/application/CookieItemsView.ts +1 -1
  64. package/front_end/panels/application/FrameDetailsView.ts +1 -1
  65. package/front_end/panels/application/IndexedDBModel.ts +0 -10
  66. package/front_end/panels/application/IndexedDBViews.ts +240 -164
  67. package/front_end/panels/application/ServiceWorkersView.ts +494 -411
  68. package/front_end/panels/application/SharedStorageModel.ts +0 -10
  69. package/front_end/panels/application/application.ts +0 -6
  70. package/front_end/panels/application/components/AdsView.ts +23 -0
  71. package/front_end/panels/application/components/SharedStorageAccessGrid.ts +1 -1
  72. package/front_end/panels/application/components/adsView.css +21 -1
  73. package/front_end/panels/application/components/components.ts +0 -2
  74. package/front_end/panels/application/indexedDBViews.css +1 -1
  75. package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +1 -1
  76. package/front_end/panels/application/serviceWorkersView.css +40 -4
  77. package/front_end/panels/browser_debugger/XHRBreakpointsSidebarPane.ts +147 -123
  78. package/front_end/panels/common/ExtensionServer.ts +3 -3
  79. package/front_end/panels/console/ConsoleView.ts +1 -1
  80. package/front_end/panels/emulation/DeviceModeView.ts +139 -70
  81. package/front_end/panels/issues/AffectedResourcesView.ts +1 -1
  82. package/front_end/panels/lighthouse/LighthouseProtocolService.ts +53 -12
  83. package/front_end/panels/network/NetworkDataGridNode.ts +43 -1
  84. package/front_end/panels/network/RequestInitiatorView.ts +24 -2
  85. package/front_end/panels/network/RequestPayloadView.ts +77 -39
  86. package/front_end/panels/network/components/ResponseHeaderSection.ts +5 -3
  87. package/front_end/panels/network/networkLogView.css +5 -0
  88. package/front_end/panels/network/requestInitiatorViewTree.css +5 -0
  89. package/front_end/panels/profiler/HeapProfileView.ts +198 -79
  90. package/front_end/panels/profiler/HeapSnapshotView.ts +2 -2
  91. package/front_end/panels/recorder/README.md +1 -2
  92. package/front_end/panels/recorder/RecorderPanel.ts +1749 -17
  93. package/front_end/panels/recorder/recorder.ts +0 -2
  94. package/front_end/panels/settings/AISettingsTab.ts +13 -0
  95. package/front_end/panels/sources/SourcesNavigator.ts +3 -2
  96. package/front_end/panels/sources/SourcesView.ts +0 -17
  97. package/front_end/panels/sources/UISourceCodeFrame.ts +42 -0
  98. package/front_end/panels/sources/sources.ts +0 -2
  99. package/front_end/panels/timeline/CompatibilityTracksAppender.ts +0 -17
  100. package/front_end/panels/timeline/ThreadAppender.ts +0 -106
  101. package/front_end/third_party/chromium/README.chromium +1 -1
  102. package/front_end/ui/components/report_view/ReportView.ts +11 -5
  103. package/front_end/ui/components/report_view/report.css +4 -1
  104. package/front_end/ui/components/spinners/Spinner.ts +29 -32
  105. package/front_end/ui/components/spinners/spinner.css +32 -84
  106. package/front_end/ui/legacy/TextPrompt.ts +49 -1
  107. package/front_end/ui/legacy/Treeoutline.ts +14 -6
  108. package/front_end/ui/legacy/UIUtils.ts +36 -11
  109. package/front_end/ui/legacy/Widget.ts +17 -10
  110. package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +2 -2
  111. package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +36 -7
  112. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +63 -68
  113. package/front_end/ui/legacy/components/object_ui/RemoteObjectPreviewFormatter.ts +1 -1
  114. package/front_end/ui/legacy/components/object_ui/objectValue.css +2 -1
  115. package/front_end/ui/legacy/inspectorCommon.css +4 -4
  116. package/front_end/ui/legacy/textPrompt.css +10 -0
  117. package/front_end/ui/lit/lit.ts +1 -0
  118. package/front_end/ui/lit/render.ts +44 -10
  119. package/front_end/ui/lit/strip-whitespace.ts +23 -2
  120. package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
  121. package/package.json +1 -1
  122. package/front_end/models/trace/handlers/AuctionWorkletsHandler.ts +0 -183
  123. package/front_end/panels/application/InterestGroupStorageModel.ts +0 -81
  124. package/front_end/panels/application/InterestGroupStorageView.ts +0 -151
  125. package/front_end/panels/application/InterestGroupTreeElement.ts +0 -65
  126. package/front_end/panels/application/components/InterestGroupAccessGrid.ts +0 -135
  127. package/front_end/panels/application/components/interestGroupAccessGrid.css +0 -27
  128. package/front_end/panels/application/interestGroupStorageView.css +0 -9
  129. package/front_end/panels/recorder/RecorderController.ts +0 -1595
  130. package/front_end/panels/sources/InplaceFormatterEditorAction.ts +0 -149
  131. /package/front_end/panels/recorder/{recorderController.css → recorderPanel.css} +0 -0
@@ -4,6 +4,7 @@
4
4
 
5
5
  import * as Common from '../../core/common/common.js';
6
6
  import * as Host from '../../core/host/host.js';
7
+ import * as Root from '../../core/root/root.js';
7
8
 
8
9
  import {AiExplorerBadge} from './AiExplorerBadge.js';
9
10
  import type {Badge, BadgeAction, BadgeActionEvents, BadgeContext, TriggerOptions} from './Badge.js';
@@ -32,7 +33,6 @@ const SNOOZE_TIME_MS = 24 * 60 * 60 * 1000; // 24 hours
32
33
  const MAX_SNOOZE_COUNT = 3;
33
34
  const DELAY_BEFORE_TRIGGER = 1500;
34
35
 
35
- let userBadgesInstance: UserBadges|undefined = undefined;
36
36
  export class UserBadges extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
37
37
  readonly #badgeActionEventTarget = new Common.ObjectWrapper.ObjectWrapper<BadgeActionEvents>();
38
38
 
@@ -43,6 +43,9 @@ export class UserBadges extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
43
43
  #starterBadgeLastSnoozedTimestamp: Common.Settings.Setting<number>;
44
44
  #starterBadgeDismissed: Common.Settings.Setting<boolean>;
45
45
 
46
+ readonly #settings: Common.Settings.Settings;
47
+ readonly #gdpClient: Host.GdpClient.GdpClient;
48
+
46
49
  static readonly BADGE_REGISTRY: BadgeClass[] = [
47
50
  StarterBadge,
48
51
  SpeedsterBadge,
@@ -51,21 +54,27 @@ export class UserBadges extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
51
54
  AiExplorerBadge,
52
55
  ];
53
56
 
54
- private constructor() {
57
+ constructor(
58
+ settings: Common.Settings.Settings,
59
+ gdpClient: Host.GdpClient.GdpClient,
60
+ ) {
55
61
  super();
56
62
 
57
- this.#receiveBadgesSetting = Common.Settings.Settings.instance().moduleSetting('receive-gdp-badges');
63
+ this.#settings = settings;
64
+ this.#gdpClient = gdpClient;
65
+
66
+ this.#receiveBadgesSetting = this.#settings.moduleSetting('receive-gdp-badges');
58
67
  if (!Host.GdpClient.isBadgesEnabled()) {
59
68
  this.#receiveBadgesSetting.set(false);
60
69
  }
61
70
  this.#receiveBadgesSetting.addChangeListener(this.#reconcileBadges, this);
62
71
 
63
- this.#starterBadgeSnoozeCount = Common.Settings.Settings.instance().createSetting(
64
- 'starter-badge-snooze-count', 0, Common.Settings.SettingStorageType.SYNCED);
65
- this.#starterBadgeLastSnoozedTimestamp = Common.Settings.Settings.instance().createSetting(
66
- 'starter-badge-last-snoozed-timestamp', 0, Common.Settings.SettingStorageType.SYNCED);
67
- this.#starterBadgeDismissed = Common.Settings.Settings.instance().createSetting(
68
- 'starter-badge-dismissed', false, Common.Settings.SettingStorageType.SYNCED);
72
+ this.#starterBadgeSnoozeCount =
73
+ this.#settings.createSetting('starter-badge-snooze-count', 0, Common.Settings.SettingStorageType.SYNCED);
74
+ this.#starterBadgeLastSnoozedTimestamp = this.#settings.createSetting('starter-badge-last-snoozed-timestamp', 0,
75
+ Common.Settings.SettingStorageType.SYNCED);
76
+ this.#starterBadgeDismissed =
77
+ this.#settings.createSetting('starter-badge-dismissed', false, Common.Settings.SettingStorageType.SYNCED);
69
78
 
70
79
  this.#allBadges = UserBadges.BADGE_REGISTRY.map(badgeCtor => new badgeCtor({
71
80
  onTriggerBadge: this.#onTriggerBadge.bind(this),
@@ -74,10 +83,16 @@ export class UserBadges extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
74
83
  }
75
84
 
76
85
  static instance({forceNew}: {forceNew: boolean} = {forceNew: false}): UserBadges {
77
- if (!userBadgesInstance || forceNew) {
78
- userBadgesInstance = new UserBadges();
86
+ if (!Root.DevToolsContext.globalInstance().has(UserBadges) || forceNew) {
87
+ Root.DevToolsContext.globalInstance().set(
88
+ UserBadges,
89
+ new UserBadges(
90
+ Common.Settings.Settings.instance(),
91
+ Host.GdpClient.GdpClient.instance(),
92
+ ),
93
+ );
79
94
  }
80
- return userBadgesInstance;
95
+ return Root.DevToolsContext.globalInstance().get(UserBadges);
81
96
  }
82
97
 
83
98
  async initialize(): Promise<void> {
@@ -108,7 +123,7 @@ export class UserBadges extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
108
123
  return BadgeTriggerReason.AWARD;
109
124
  }
110
125
 
111
- const getProfileResponse = await Host.GdpClient.GdpClient.instance().getProfile();
126
+ const getProfileResponse = await this.#gdpClient.getProfile();
112
127
  // The `getProfile` call failed and returned a `null`.
113
128
  // For that case, we don't show anything.
114
129
  if (!getProfileResponse) {
@@ -147,7 +162,7 @@ export class UserBadges extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
147
162
  }
148
163
 
149
164
  if (reason === BadgeTriggerReason.AWARD) {
150
- const result = await Host.GdpClient.GdpClient.instance().createAward({name: badge.name});
165
+ const result = await this.#gdpClient.createAward({name: badge.name});
151
166
  if (!result) {
152
167
  return;
153
168
  }
@@ -192,7 +207,7 @@ export class UserBadges extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
192
207
  return;
193
208
  }
194
209
 
195
- const getProfileResponse = await Host.GdpClient.GdpClient.instance().getProfile();
210
+ const getProfileResponse = await this.#gdpClient.getProfile();
196
211
  if (!getProfileResponse) {
197
212
  this.#deactivateAllBadges();
198
213
  return;
@@ -209,8 +224,7 @@ export class UserBadges extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
209
224
 
210
225
  let awardedBadgeNames: Set<string>|null = null;
211
226
  if (hasGdpProfile) {
212
- awardedBadgeNames = await Host.GdpClient.GdpClient.instance().getAwardedBadgeNames(
213
- {names: this.#allBadges.map(badge => badge.name)});
227
+ awardedBadgeNames = await this.#gdpClient.getAwardedBadgeNames({names: this.#allBadges.map(badge => badge.name)});
214
228
  // This is a conservative approach. We bail out if `awardedBadgeNames` is null
215
229
  // when there is a profile to prevent a negative user experience.
216
230
  //
@@ -55,9 +55,9 @@ export class CompilerScriptMapping implements DebuggerSourceMapping {
55
55
  this.#debuggerModel = debuggerModel;
56
56
  this.#ignoreListManager = debuggerWorkspaceBinding.ignoreListManager;
57
57
 
58
- this.#stubProject = new ContentProviderBasedProject(workspace, 'jsSourceMaps:stub:' + debuggerModel.target().id(),
59
- Workspace.Workspace.projectTypes.Service, '',
60
- true /* isServiceProject */, debuggerModel.target());
58
+ this.#stubProject =
59
+ new ContentProviderBasedProject(workspace, 'jsSourceMaps:stub:' + debuggerModel.target().id(),
60
+ Workspace.Workspace.projectTypes.Service, '', true /* isServiceProject */);
61
61
  this.#eventListeners = [
62
62
  this.#sourceMapManager.addEventListener(
63
63
  SDK.SourceMapManager.Events.SourceMapWillAttach, this.sourceMapWillAttach, this),
@@ -464,7 +464,8 @@ export class CompilerScriptMapping implements DebuggerSourceMapping {
464
464
  const projectType = script.isContentScript() ? Workspace.Workspace.projectTypes.ContentScripts :
465
465
  Workspace.Workspace.projectTypes.Network;
466
466
  project = new ContentProviderBasedProject(this.#stubProject.workspace(), projectId, projectType,
467
- /* displayName */ '', /* isServiceProject */ false, target);
467
+ /* displayName */ '', /* isServiceProject */ false);
468
+ NetworkProject.setTargetForProject(project, target);
468
469
  this.#projects.set(projectId, project);
469
470
  }
470
471
  this.#sourceMapToProject.set(sourceMap, project);
@@ -5,7 +5,6 @@
5
5
  import type * as Common from '../../core/common/common.js';
6
6
  import * as i18n from '../../core/i18n/i18n.js';
7
7
  import * as Platform from '../../core/platform/platform.js';
8
- import type * as SDK from '../../core/sdk/sdk.js';
9
8
  import * as TextUtils from '../text_utils/text_utils.js';
10
9
  import * as Workspace from '../workspace/workspace.js';
11
10
 
@@ -28,8 +27,8 @@ export class ContentProviderBasedProject extends Workspace.Workspace.ProjectStor
28
27
  readonly #isServiceProject: boolean;
29
28
  readonly #uiSourceCodeToData = new WeakMap<Workspace.UISourceCode.UISourceCode, UISourceCodeData>();
30
29
  constructor(workspace: Workspace.Workspace.WorkspaceImpl, id: string, type: Workspace.Workspace.projectTypes,
31
- displayName: string, isServiceProject: boolean, target: SDK.Target.Target|null = null) {
32
- super(workspace, id, type, displayName, target);
30
+ displayName: string, isServiceProject: boolean) {
31
+ super(workspace, id, type, displayName);
33
32
  this.#isServiceProject = isServiceProject;
34
33
  workspace.addProject(this);
35
34
  }
@@ -1100,9 +1100,10 @@ class ModelData {
1100
1100
  project: ContentProviderBasedProject;
1101
1101
  readonly uiSourceCodeToScripts: Map<Workspace.UISourceCode.UISourceCode, SDK.Script.Script[]>;
1102
1102
  constructor(debuggerModel: SDK.DebuggerModel.DebuggerModel, workspace: Workspace.Workspace.WorkspaceImpl) {
1103
- this.project = new ContentProviderBasedProject(workspace, 'language_plugins::' + debuggerModel.target().id(),
1104
- Workspace.Workspace.projectTypes.Network, '',
1105
- false /* isServiceProject */, debuggerModel.target());
1103
+ this.project =
1104
+ new ContentProviderBasedProject(workspace, 'language_plugins::' + debuggerModel.target().id(),
1105
+ Workspace.Workspace.projectTypes.Network, '', false /* isServiceProject */);
1106
+ NetworkProject.setTargetForProject(this.project, debuggerModel.target());
1106
1107
 
1107
1108
  this.uiSourceCodeToScripts = new Map();
1108
1109
  }
@@ -23,9 +23,9 @@ export class DefaultScriptMapping implements DebuggerSourceMapping {
23
23
  debuggerWorkspaceBinding: DebuggerWorkspaceBinding) {
24
24
  defaultScriptMappings.add(this);
25
25
  this.#debuggerWorkspaceBinding = debuggerWorkspaceBinding;
26
- this.#project = new ContentProviderBasedProject(workspace, 'debugger:' + debuggerModel.target().id(),
27
- Workspace.Workspace.projectTypes.Debugger, '',
28
- true /* isServiceProject */, debuggerModel.target());
26
+ this.#project =
27
+ new ContentProviderBasedProject(workspace, 'debugger:' + debuggerModel.target().id(),
28
+ Workspace.Workspace.projectTypes.Debugger, '', true /* isServiceProject */);
29
29
  this.#eventListeners = [
30
30
  debuggerModel.addEventListener(SDK.DebuggerModel.Events.GlobalObjectCleared, this.globalObjectCleared, this),
31
31
  debuggerModel.addEventListener(SDK.DebuggerModel.Events.ParsedScriptSource, this.parsedScriptSource, this),
@@ -14,6 +14,7 @@ const uiSourceCodeToAttributionMap = new WeakMap<Workspace.UISourceCode.UISource
14
14
  }>>();
15
15
 
16
16
  export class NetworkProjectManager extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
17
+ readonly #projectToTargetMap = new WeakMap<Workspace.Workspace.Project, SDK.Target.Target>();
17
18
 
18
19
  static instance({forceNew}: {
19
20
  forceNew: boolean,
@@ -28,6 +29,18 @@ export class NetworkProjectManager extends Common.ObjectWrapper.ObjectWrapper<Ev
28
29
  static removeInstance(): void {
29
30
  Root.DevToolsContext.globalInstance().delete(NetworkProjectManager);
30
31
  }
32
+
33
+ setTargetForProject(project: Workspace.Workspace.Project, target: SDK.Target.Target): void {
34
+ this.#projectToTargetMap.set(project, target);
35
+ }
36
+
37
+ getTargetForProject(project: Workspace.Workspace.Project): SDK.Target.Target|null {
38
+ return this.#projectToTargetMap.get(project) ?? null;
39
+ }
40
+
41
+ getTargetForUISourceCode(uiSourceCode: Workspace.UISourceCode.UISourceCode): SDK.Target.Target|null {
42
+ return this.#projectToTargetMap.get(uiSourceCode.project()) ?? null;
43
+ }
31
44
  }
32
45
 
33
46
  export const enum Events {
@@ -131,7 +144,15 @@ export class NetworkProject {
131
144
  }
132
145
 
133
146
  static targetForUISourceCode(uiSourceCode: Workspace.UISourceCode.UISourceCode): SDK.Target.Target|null {
134
- return uiSourceCode.project().target();
147
+ return NetworkProjectManager.instance().getTargetForUISourceCode(uiSourceCode);
148
+ }
149
+
150
+ static setTargetForProject(project: Workspace.Workspace.Project, target: SDK.Target.Target): void {
151
+ NetworkProjectManager.instance().setTargetForProject(project, target);
152
+ }
153
+
154
+ static getTargetForProject(project: Workspace.Workspace.Project): SDK.Target.Target|null {
155
+ return NetworkProjectManager.instance().getTargetForProject(project);
135
156
  }
136
157
 
137
158
  static framesForUISourceCode(uiSourceCode: Workspace.UISourceCode.UISourceCode):
@@ -361,9 +361,10 @@ class ModelInfo {
361
361
  constructor(resourceMapping: ResourceMapping, resourceTreeModel: SDK.ResourceTreeModel.ResourceTreeModel) {
362
362
  const target = resourceTreeModel.target();
363
363
  this.resourceMapping = resourceMapping;
364
- this.project = new ContentProviderBasedProject(resourceMapping.workspace, 'resources:' + target.id(),
365
- Workspace.Workspace.projectTypes.Network, '',
366
- false /* isServiceProject */, target);
364
+ this.project =
365
+ new ContentProviderBasedProject(resourceMapping.workspace, 'resources:' + target.id(),
366
+ Workspace.Workspace.projectTypes.Network, '', false /* isServiceProject */);
367
+ NetworkProject.setTargetForProject(this.project, target);
367
368
 
368
369
  const cssModel = target.model(SDK.CSSModel.CSSModel);
369
370
  console.assert(Boolean(cssModel));
@@ -74,7 +74,8 @@ export class ResourceScriptMapping implements DebuggerSourceMapping {
74
74
  const projectType = script.isContentScript() ? Workspace.Workspace.projectTypes.ContentScripts :
75
75
  Workspace.Workspace.projectTypes.Network;
76
76
  project = new ContentProviderBasedProject(this.#workspace, projectId, projectType, '' /* displayName */,
77
- false /* isServiceProject */, this.debuggerModel.target());
77
+ false /* isServiceProject */);
78
+ NetworkProject.setTargetForProject(project, this.debuggerModel.target());
78
79
  this.#projects.set(projectId, project);
79
80
  }
80
81
  return project;
@@ -26,9 +26,10 @@ export class SASSSourceMapping implements SourceMapping {
26
26
  workspace: Workspace.Workspace.WorkspaceImpl, cssWorkspaceBinding: CSSWorkspaceBinding) {
27
27
  this.#sourceMapManager = sourceMapManager;
28
28
  this.#cssWorkspaceBinding = cssWorkspaceBinding;
29
- this.#project = new ContentProviderBasedProject(workspace, 'cssSourceMaps:' + target.id(),
30
- Workspace.Workspace.projectTypes.Network, '',
31
- false /* isServiceProject */, target);
29
+ this.#project =
30
+ new ContentProviderBasedProject(workspace, 'cssSourceMaps:' + target.id(),
31
+ Workspace.Workspace.projectTypes.Network, '', false /* isServiceProject */);
32
+ NetworkProject.setTargetForProject(this.#project, target);
32
33
 
33
34
  this.#bindings = new Map();
34
35
 
@@ -24,9 +24,9 @@ export class StylesSourceMapping implements SourceMapping {
24
24
  constructor(cssModel: SDK.CSSModel.CSSModel, workspace: Workspace.Workspace.WorkspaceImpl) {
25
25
  this.#cssModel = cssModel;
26
26
  const target = this.#cssModel.target();
27
- this.#project =
28
- new ContentProviderBasedProject(workspace, 'css:' + target.id(), Workspace.Workspace.projectTypes.Network, '',
29
- false /* isServiceProject */, target);
27
+ this.#project = new ContentProviderBasedProject(
28
+ workspace, 'css:' + target.id(), Workspace.Workspace.projectTypes.Network, '', false /* isServiceProject */);
29
+ NetworkProject.setTargetForProject(this.#project, target);
30
30
 
31
31
  this.#eventListeners = [
32
32
  this.#cssModel.addEventListener(SDK.CSSModel.Events.StyleSheetAdded, this.styleSheetAdded, this),
@@ -11,6 +11,8 @@ import * as Protocol from '../../generated/protocol.js';
11
11
  import * as Geometry from '../geometry/geometry.js';
12
12
 
13
13
  import {
14
+ type Cutout,
15
+ CutoutShape,
14
16
  type EmulatedDevice,
15
17
  Horizontal,
16
18
  HorizontalSpanned,
@@ -85,6 +87,13 @@ const UIStrings = {
85
87
  const str_ = i18n.i18n.registerUIStrings('models/emulation/DeviceModeModel.ts', UIStrings);
86
88
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
87
89
 
90
+ const CUTOUT_SHAPE_TO_PROTOCOL: Record<CutoutShape, Protocol.Overlay.DisplayCutoutShape> = {
91
+ [CutoutShape.PILL]: Protocol.Overlay.DisplayCutoutShape.Pill,
92
+ [CutoutShape.NOTCH]: Protocol.Overlay.DisplayCutoutShape.Notch,
93
+ [CutoutShape.CIRCLE]: Protocol.Overlay.DisplayCutoutShape.Circle,
94
+ [CutoutShape.RECTANGLE]: Protocol.Overlay.DisplayCutoutShape.Rectangle,
95
+ };
96
+
88
97
  export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTypes> implements
89
98
  SDK.TargetManager.SDKModelObserver<SDK.EmulationModel.EmulationModel> {
90
99
  #screenRect: Rect;
@@ -506,7 +515,7 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
506
515
  return;
507
516
  }
508
517
 
509
- this.showHingeIfApplicable(overlayModel);
518
+ this.showDeviceOverlaysIfApplicable(overlayModel);
510
519
  }
511
520
 
512
521
  private onScreenOrientationLockChanged(
@@ -638,7 +647,7 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
638
647
  const mobile = this.isMobile();
639
648
  const overlayModel = this.#emulationModel ? this.#emulationModel.overlayModel() : null;
640
649
  if (overlayModel) {
641
- this.showHingeIfApplicable(overlayModel);
650
+ this.showDeviceOverlaysIfApplicable(overlayModel);
642
651
  }
643
652
  if (this.#type === Type.Device && this.#device && this.#mode) {
644
653
  const orientation = this.#device.orientationByName(this.#mode.orientation);
@@ -878,14 +887,67 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
878
887
  }
879
888
  }
880
889
 
881
- private showHingeIfApplicable(overlayModel: SDK.OverlayModel.OverlayModel): void {
890
+ private showDeviceOverlaysIfApplicable(overlayModel: SDK.OverlayModel.OverlayModel): void {
882
891
  const orientation = (this.#device && this.#mode) ? this.#device.orientationByName(this.#mode.orientation) : null;
883
892
  if (orientation?.hinge) {
884
893
  overlayModel.showHingeForDualScreen(orientation.hinge);
885
- return;
894
+ } else {
895
+ overlayModel.showHingeForDualScreen(null);
896
+ }
897
+
898
+ overlayModel.showDisplayCutout(this.currentDisplayCutout());
899
+ }
900
+
901
+ private currentDisplayCutout(): SDK.OverlayModel.DisplayCutout|null {
902
+ const device = this.#device;
903
+ const mode = this.#mode;
904
+ if (!device || !mode || !device.modes.includes(mode)) {
905
+ return null;
906
+ }
907
+
908
+ const cutout = mode.cutout;
909
+ if (cutout) {
910
+ return this.toDisplayCutout(cutout);
886
911
  }
887
912
 
888
- overlayModel.showHingeForDualScreen(null);
913
+ if (mode.orientation !== Horizontal) {
914
+ return null;
915
+ }
916
+
917
+ const rotationPartner = device.getRotationPartner(mode);
918
+ const rotatedCutout = rotationPartner?.cutout;
919
+ if (rotationPartner?.orientation !== Vertical || !rotatedCutout) {
920
+ return null;
921
+ }
922
+
923
+ const orientation = device.orientationByName(mode.orientation);
924
+ if (rotatedCutout.shape === CutoutShape.CIRCLE) {
925
+ return this.toDisplayCutout({
926
+ ...rotatedCutout,
927
+ x: orientation.width - rotatedCutout.y - rotatedCutout.height,
928
+ y: rotatedCutout.x,
929
+ width: rotatedCutout.height,
930
+ height: rotatedCutout.width,
931
+ cx: orientation.width - rotatedCutout.cy,
932
+ cy: rotatedCutout.cx,
933
+ });
934
+ }
935
+ return this.toDisplayCutout({
936
+ ...rotatedCutout,
937
+ x: orientation.width - rotatedCutout.y - rotatedCutout.height,
938
+ y: rotatedCutout.x,
939
+ width: rotatedCutout.height,
940
+ height: rotatedCutout.width,
941
+ });
942
+ }
943
+
944
+ private toDisplayCutout(cutout: Cutout): SDK.OverlayModel.DisplayCutout {
945
+ const {shape, ...rest} = cutout;
946
+ return {
947
+ ...rest,
948
+ shape: CUTOUT_SHAPE_TO_PROTOCOL[shape],
949
+ contentColor: {r: 0, g: 0, b: 0, a: 1},
950
+ } as SDK.OverlayModel.DisplayCutout;
889
951
  }
890
952
 
891
953
  private getDisplayFeatureOrientation(): Protocol.Emulation.DisplayFeatureOrientation {
@@ -6,22 +6,24 @@ import type * as Platform from '../../core/platform/platform.js';
6
6
 
7
7
  import {PrivateAPI} from './ExtensionAPI.js';
8
8
  import {ExtensionEndpoint} from './ExtensionEndpoint.js';
9
- import {RecorderPluginManager} from './RecorderPluginManager.js';
9
+ import type {RecorderPluginManager} from './RecorderPluginManager.js';
10
10
 
11
11
  export class RecorderExtensionEndpoint extends ExtensionEndpoint {
12
12
  private readonly name: string;
13
13
  private readonly mediaType?: string;
14
14
  private readonly capabilities: PrivateAPI.RecordingExtensionPluginCapability[];
15
15
  readonly #extensionOrigin: Platform.DevToolsPath.UrlString;
16
+ readonly #recorderPluginManager: RecorderPluginManager;
16
17
 
17
- constructor(
18
- name: string, port: MessagePort, capabilities: PrivateAPI.RecordingExtensionPluginCapability[],
19
- extensionOrigin: Platform.DevToolsPath.UrlString, mediaType?: string) {
18
+ constructor(name: string, port: MessagePort, capabilities: PrivateAPI.RecordingExtensionPluginCapability[],
19
+ extensionOrigin: Platform.DevToolsPath.UrlString, recorderPluginManager: RecorderPluginManager,
20
+ mediaType?: string) {
20
21
  super(port);
21
22
  this.name = name;
22
23
  this.mediaType = mediaType;
23
24
  this.capabilities = capabilities;
24
25
  this.#extensionOrigin = extensionOrigin;
26
+ this.#recorderPluginManager = recorderPluginManager;
25
27
  }
26
28
 
27
29
  getName(): string {
@@ -44,7 +46,7 @@ export class RecorderExtensionEndpoint extends ExtensionEndpoint {
44
46
  switch (event) {
45
47
  case PrivateAPI.RecorderExtensionPluginEvents.UnregisteredRecorderExtensionPlugin: {
46
48
  this.disconnect();
47
- RecorderPluginManager.instance().removePlugin(this);
49
+ this.#recorderPluginManager.removePlugin(this);
48
50
  break;
49
51
  }
50
52
  default:
@@ -3,11 +3,10 @@
3
3
  // found in the LICENSE file.
4
4
 
5
5
  import * as Common from '../../core/common/common.js';
6
+ import * as Root from '../../core/root/root.js';
6
7
 
7
8
  import type {RecorderExtensionEndpoint} from './RecorderExtensionEndpoint.js';
8
9
 
9
- let instance: RecorderPluginManager|null = null;
10
-
11
10
  export interface ViewDescriptor {
12
11
  id: string;
13
12
  title: string;
@@ -21,11 +20,16 @@ export class RecorderPluginManager extends Common.ObjectWrapper.ObjectWrapper<Ev
21
20
  #plugins = new Set<RecorderExtensionEndpoint>();
22
21
  #views = new Map<string, ViewDescriptor>();
23
22
 
24
- static instance(): RecorderPluginManager {
25
- if (!instance) {
26
- instance = new RecorderPluginManager();
23
+ static instance(opts?: {forceNew: boolean}): RecorderPluginManager {
24
+ if (!Root.DevToolsContext.globalInstance().has(RecorderPluginManager) || opts?.forceNew) {
25
+ Root.DevToolsContext.globalInstance().set(RecorderPluginManager, new RecorderPluginManager());
27
26
  }
28
- return instance;
27
+
28
+ return Root.DevToolsContext.globalInstance().get(RecorderPluginManager);
29
+ }
30
+
31
+ static removeInstance(): void {
32
+ Root.DevToolsContext.globalInstance().delete(RecorderPluginManager);
29
33
  }
30
34
 
31
35
  addPlugin(plugin: RecorderExtensionEndpoint): void {
@@ -0,0 +1,193 @@
1
+ Title: HAR Log build converts network requests into a complete HAR log with pages and entries
2
+ Content:
3
+ {
4
+ "version": "1.2",
5
+ "creator": {
6
+ "name": "WebInspector",
7
+ "version": "VERSION"
8
+ },
9
+ "pages": [
10
+ {
11
+ "startedDateTime": "1970-01-01T00:00:01.000Z",
12
+ "id": "page_1",
13
+ "title": "http://127.0.0.1:8000/devtools/resources/inspected-page.html",
14
+ "pageTimings": {
15
+ "onContentLoad": 9000,
16
+ "onLoad": 14000
17
+ }
18
+ }
19
+ ],
20
+ "entries": [
21
+ {
22
+ "_initiator": null,
23
+ "_priority": null,
24
+ "_resourceType": "document",
25
+ "cache": {},
26
+ "request": {
27
+ "method": "GET",
28
+ "url": "http://127.0.0.1:8000/devtools/resources/inspected-page.html",
29
+ "httpVersion": "HTTP/1.1",
30
+ "headers": [
31
+ {
32
+ "name": "version",
33
+ "value": "HTTP/1.1"
34
+ }
35
+ ],
36
+ "queryString": [],
37
+ "cookies": [
38
+ {
39
+ "name": "a",
40
+ "value": "b",
41
+ "path": "/path",
42
+ "domain": "example.com",
43
+ "expires": null,
44
+ "httpOnly": false,
45
+ "secure": false
46
+ },
47
+ {
48
+ "name": "a1",
49
+ "value": "b1",
50
+ "expires": null,
51
+ "httpOnly": false,
52
+ "secure": false
53
+ },
54
+ {
55
+ "name": "c1",
56
+ "value": "d1",
57
+ "expires": null,
58
+ "httpOnly": false,
59
+ "secure": false
60
+ }
61
+ ],
62
+ "headersSize": -1,
63
+ "bodySize": 0
64
+ },
65
+ "response": {
66
+ "status": 0,
67
+ "statusText": "",
68
+ "httpVersion": "",
69
+ "headers": [
70
+ {
71
+ "name": "Set-Cookie",
72
+ "value": "x=y; Path=/path; Domain=example.com; httpOnly; Secure\nx1=y1; SameSite=Strict\nz2=y2; SameSite=Lax"
73
+ }
74
+ ],
75
+ "cookies": [
76
+ {
77
+ "name": "x",
78
+ "value": "y",
79
+ "path": "/path",
80
+ "domain": "example.com",
81
+ "expires": null,
82
+ "httpOnly": true,
83
+ "secure": true
84
+ },
85
+ {
86
+ "name": "x1",
87
+ "value": "y1",
88
+ "domain": "127.0.0.1",
89
+ "expires": null,
90
+ "httpOnly": false,
91
+ "secure": false,
92
+ "sameSite": "Strict"
93
+ },
94
+ {
95
+ "name": "z2",
96
+ "value": "y2",
97
+ "domain": "127.0.0.1",
98
+ "expires": null,
99
+ "httpOnly": false,
100
+ "secure": false,
101
+ "sameSite": "Lax"
102
+ }
103
+ ],
104
+ "content": {
105
+ "size": 0,
106
+ "mimeType": "x-unknown"
107
+ },
108
+ "redirectURL": "",
109
+ "headersSize": -1,
110
+ "bodySize": -1,
111
+ "_transferSize": 0,
112
+ "_error": null,
113
+ "_fetchedViaServiceWorker": true,
114
+ "_responseCacheStorageCacheName": "v1",
115
+ "_serviceWorkerResponseSource": "cache-storage",
116
+ "_serviceWorkerRouterRuleIdMatched": 3,
117
+ "_serviceWorkerRouterMatchedSourceType": "cache",
118
+ "_serviceWorkerRouterActualSourceType": "cache"
119
+ },
120
+ "serverIPAddress": "",
121
+ "startedDateTime": "1969-12-31T23:59:59.000Z",
122
+ "time": 0,
123
+ "timings": {
124
+ "blocked": 0,
125
+ "dns": -1,
126
+ "ssl": -1,
127
+ "connect": -1,
128
+ "send": 0,
129
+ "wait": 0,
130
+ "receive": 0,
131
+ "_blocked_queueing": 2000
132
+ },
133
+ "pageref": "page_1"
134
+ },
135
+ {
136
+ "_initiator": null,
137
+ "_priority": null,
138
+ "_resourceType": "xhr",
139
+ "cache": {},
140
+ "request": {
141
+ "method": "POST",
142
+ "url": "http://127.0.0.1:8000/devtools/resources/post-target.cgi",
143
+ "httpVersion": "",
144
+ "headers": [
145
+ {
146
+ "name": "Content-Type",
147
+ "value": "text/xml"
148
+ }
149
+ ],
150
+ "queryString": [],
151
+ "cookies": [],
152
+ "headersSize": -1,
153
+ "bodySize": 11,
154
+ "postData": {
155
+ "mimeType": "text/xml",
156
+ "text": "<xml></xml>"
157
+ }
158
+ },
159
+ "response": {
160
+ "status": 0,
161
+ "statusText": "",
162
+ "httpVersion": "",
163
+ "headers": [],
164
+ "cookies": [],
165
+ "content": {
166
+ "size": 0,
167
+ "mimeType": "application/xml"
168
+ },
169
+ "redirectURL": "",
170
+ "headersSize": -1,
171
+ "bodySize": -1,
172
+ "_transferSize": 0,
173
+ "_error": null,
174
+ "_fetchedViaServiceWorker": false
175
+ },
176
+ "serverIPAddress": "",
177
+ "startedDateTime": "1969-12-31T23:59:59.000Z",
178
+ "time": 0,
179
+ "timings": {
180
+ "blocked": 0,
181
+ "dns": -1,
182
+ "ssl": -1,
183
+ "connect": -1,
184
+ "send": 0,
185
+ "wait": 0,
186
+ "receive": 0,
187
+ "_blocked_queueing": -1
188
+ },
189
+ "pageref": "page_1"
190
+ }
191
+ ]
192
+ }
193
+ === end content