chrome-devtools-frontend 1.0.1660788 → 1.0.1662289

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 (177) hide show
  1. package/.agents/skills/evaluate-ai-css-completion/SKILL.md +143 -0
  2. package/.agents/skills/evaluate-ai-css-completion/scripts/evaluate.js +104 -0
  3. package/.agents/skills/migrate-chromium-test/SKILL.md +7 -2
  4. package/.agents/skills/ui-eng-vision-local-lit-renderer/SKILL.md +7 -1
  5. package/docs/ui_engineering.md +75 -42
  6. package/eslint.config.mjs +7 -0
  7. package/extension-api/ExtensionAPI.d.ts +88 -0
  8. package/front_end/core/common/SettingRegistration.ts +0 -5
  9. package/front_end/core/host/InspectorFrontendHost.ts +1 -0
  10. package/front_end/core/host/InspectorFrontendHostStub.ts +2 -0
  11. package/front_end/core/platform/ArrayUtilities.ts +10 -0
  12. package/front_end/core/platform/StringUtilities.ts +20 -4
  13. package/front_end/core/sdk/CPUThrottlingManager.ts +2 -0
  14. package/front_end/core/sdk/DOMDebuggerModel.ts +2 -0
  15. package/front_end/core/sdk/DOMModel.ts +1 -0
  16. package/front_end/core/sdk/DebuggerModel.ts +4 -4
  17. package/front_end/core/sdk/EventBreakpointsModel.ts +2 -0
  18. package/front_end/core/sdk/FrameManager.ts +1 -0
  19. package/front_end/core/sdk/IsolateManager.ts +1 -0
  20. package/front_end/core/sdk/NetworkManager.ts +2 -0
  21. package/front_end/core/sdk/NetworkRequest.ts +1 -0
  22. package/front_end/core/sdk/PageResourceLoader.ts +2 -0
  23. package/front_end/core/sdk/SourceMap.ts +5 -5
  24. package/front_end/core/sdk/SourceMapManager.ts +3 -2
  25. package/front_end/core/sdk/TargetManager.ts +4 -0
  26. package/front_end/entrypoints/main/MainImpl.ts +2 -1
  27. package/front_end/foundation/README.md +86 -0
  28. package/front_end/generated/InspectorBackendCommands.ts +4 -5
  29. package/front_end/generated/protocol.ts +20 -38
  30. package/front_end/models/bindings/CompilerScriptMapping.ts +5 -5
  31. package/front_end/models/bindings/ContentProviderBasedProject.ts +2 -3
  32. package/front_end/models/bindings/DebuggerLanguagePlugins.ts +3 -3
  33. package/front_end/models/bindings/DefaultScriptMapping.ts +3 -3
  34. package/front_end/models/bindings/ResourceMapping.ts +3 -3
  35. package/front_end/models/bindings/ResourceScriptMapping.ts +2 -2
  36. package/front_end/models/bindings/SASSSourceMapping.ts +3 -3
  37. package/front_end/models/bindings/TempFile.ts +8 -3
  38. package/front_end/models/extensions/ExtensionAPI.ts +110 -46
  39. package/front_end/models/extensions/RecorderExtensionEndpoint.ts +7 -5
  40. package/front_end/models/formatter/ScriptFormatter.ts +8 -11
  41. package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +14 -5
  42. package/front_end/models/issues_manager/CheckFormsIssuesTrigger.ts +8 -9
  43. package/front_end/models/issues_manager/CookieIssue.ts +21 -9
  44. package/front_end/models/issues_manager/Issue.ts +3 -4
  45. package/front_end/models/issues_manager/IssueAggregator.ts +0 -9
  46. package/front_end/models/issues_manager/IssueResolver.ts +2 -2
  47. package/front_end/models/issues_manager/IssuesManager.ts +136 -137
  48. package/front_end/models/issues_manager/RelatedIssue.ts +10 -8
  49. package/front_end/models/issues_manager/issues_manager.ts +0 -2
  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/source_map_scopes/FunctionCodeResolver.ts +12 -9
  53. package/front_end/models/trace/handlers/FramesHandler.ts +4 -7
  54. package/front_end/models/trace/handlers/ModelHandlers.ts +0 -1
  55. package/front_end/models/trace/handlers/RendererHandler.ts +2 -15
  56. package/front_end/models/trace/handlers/Threads.ts +4 -11
  57. package/front_end/models/trace/insights/DOMSize.ts +1 -1
  58. package/front_end/models/workspace_diff/WorkspaceDiff.ts +10 -4
  59. package/front_end/panels/ai_assistance/components/ChatMessage.ts +2 -1
  60. package/front_end/panels/application/ApplicationPanelSidebar.ts +0 -44
  61. package/front_end/panels/application/CookieItemsView.ts +1 -1
  62. package/front_end/panels/application/ServiceWorkersView.ts +494 -411
  63. package/front_end/panels/application/WebMCPView.ts +38 -43
  64. package/front_end/panels/application/application.ts +0 -6
  65. package/front_end/panels/application/components/AdsView.ts +201 -30
  66. package/front_end/panels/application/components/adsView.css +25 -0
  67. package/front_end/panels/application/components/components.ts +0 -2
  68. package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +1 -1
  69. package/front_end/panels/application/preloading/components/RuleSetDetailsView.ts +2 -2
  70. package/front_end/panels/application/serviceWorkersView.css +40 -4
  71. package/front_end/panels/browser_debugger/XHRBreakpointsSidebarPane.ts +147 -123
  72. package/front_end/panels/common/ExtensionServer.ts +3 -3
  73. package/front_end/panels/console/ConsoleView.ts +3 -2
  74. package/front_end/panels/console/PromptBuilder.ts +2 -1
  75. package/front_end/panels/emulation/DeviceModeView.ts +164 -113
  76. package/front_end/panels/issues/AffectedResourcesView.ts +1 -1
  77. package/front_end/panels/issues/IssueView.ts +0 -2
  78. package/front_end/panels/issues/IssuesPane.ts +1 -8
  79. package/front_end/panels/js_timeline/js_timeline-meta.ts +3 -2
  80. package/front_end/panels/lighthouse/LighthouseProtocolService.ts +53 -12
  81. package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorController.ts +3 -3
  82. package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorPane.ts +5 -5
  83. package/front_end/panels/linear_memory_inspector/components/LinearMemoryHighlightChipList.ts +4 -4
  84. package/front_end/panels/linear_memory_inspector/components/LinearMemoryInspector.ts +2 -2
  85. package/front_end/panels/linear_memory_inspector/components/LinearMemoryNavigator.ts +6 -6
  86. package/front_end/panels/linear_memory_inspector/components/LinearMemoryValueInterpreter.ts +3 -3
  87. package/front_end/panels/linear_memory_inspector/components/ValueInterpreterDisplay.ts +8 -9
  88. package/front_end/panels/linear_memory_inspector/components/ValueInterpreterDisplayUtils.ts +2 -2
  89. package/front_end/panels/linear_memory_inspector/components/ValueInterpreterSettings.ts +1 -1
  90. package/front_end/panels/linear_memory_inspector/linear_memory_inspector-meta.ts +2 -2
  91. package/front_end/panels/network/RequestPayloadView.ts +92 -52
  92. package/front_end/panels/network/RequestTimingView.ts +95 -127
  93. package/front_end/panels/network/components/ResponseHeaderSection.ts +5 -3
  94. package/front_end/panels/profiler/HeapSnapshotView.ts +3 -3
  95. package/front_end/panels/profiler/WritableProfileHeader.ts +2 -2
  96. package/front_end/panels/recorder/{components/ControlButton.ts → ControlButton.ts} +9 -10
  97. package/front_end/panels/recorder/{components/CreateRecordingView.ts → CreateRecordingView.ts} +48 -47
  98. package/front_end/panels/recorder/{components/ExtensionView.ts → ExtensionView.ts} +8 -8
  99. package/front_end/panels/recorder/RecorderController.ts +302 -127
  100. package/front_end/panels/recorder/RecorderPanel.ts +1 -1
  101. package/front_end/panels/recorder/{components/RecordingListView.ts → RecordingListView.ts} +19 -20
  102. package/front_end/panels/recorder/{components/RecordingView.ts → RecordingView.ts} +88 -88
  103. package/front_end/panels/recorder/{components/ReplaySection.ts → ReplaySection.ts} +11 -11
  104. package/front_end/panels/recorder/{components/SelectorPicker.ts → SelectorPicker.ts} +13 -13
  105. package/front_end/panels/recorder/{components/StepEditor.ts → StepEditor.ts} +15 -15
  106. package/front_end/panels/recorder/{components/StepView.ts → StepView.ts} +10 -10
  107. package/front_end/panels/recorder/{components/TimelineSection.ts → TimelineSection.ts} +2 -2
  108. package/front_end/panels/recorder/recorder.ts +23 -1
  109. package/front_end/panels/recorder/util/util.ts +113 -0
  110. package/front_end/panels/sources/SourcesView.ts +0 -17
  111. package/front_end/panels/sources/TabbedEditorContainer.ts +1 -1
  112. package/front_end/panels/sources/UISourceCodeFrame.ts +42 -0
  113. package/front_end/panels/sources/sources.ts +0 -2
  114. package/front_end/panels/timeline/CompatibilityTracksAppender.ts +0 -17
  115. package/front_end/panels/timeline/IsolateSelector.ts +10 -8
  116. package/front_end/panels/timeline/ThreadAppender.ts +0 -106
  117. package/front_end/panels/timeline/TimelinePanel.ts +18 -7
  118. package/front_end/panels/timeline/TimelineUIUtils.ts +144 -129
  119. package/front_end/panels/timeline/timeline-meta.ts +3 -2
  120. package/front_end/third_party/chromium/README.chromium +1 -1
  121. package/front_end/ui/components/report_view/ReportView.ts +11 -5
  122. package/front_end/ui/components/report_view/report.css +4 -1
  123. package/front_end/ui/legacy/TextPrompt.ts +49 -1
  124. package/front_end/ui/legacy/Treeoutline.ts +3 -0
  125. package/front_end/ui/legacy/UIUtils.ts +11 -1
  126. package/front_end/ui/legacy/Widget.ts +14 -15
  127. package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +2 -2
  128. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +11 -7
  129. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +2 -1
  130. package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +10 -1
  131. package/front_end/ui/legacy/textPrompt.css +10 -0
  132. package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
  133. package/package.json +1 -1
  134. package/front_end/models/issues_manager/AttributionReportingIssue.ts +0 -247
  135. package/front_end/models/issues_manager/descriptions/arInsecureContext.md +0 -7
  136. package/front_end/models/issues_manager/descriptions/arInvalidInfoHeader.md +0 -5
  137. package/front_end/models/issues_manager/descriptions/arInvalidRegisterOsSourceHeader.md +0 -5
  138. package/front_end/models/issues_manager/descriptions/arInvalidRegisterOsTriggerHeader.md +0 -5
  139. package/front_end/models/issues_manager/descriptions/arInvalidRegisterSourceHeader.md +0 -5
  140. package/front_end/models/issues_manager/descriptions/arInvalidRegisterTriggerHeader.md +0 -5
  141. package/front_end/models/issues_manager/descriptions/arNavigationRegistrationUniqueScopeAlreadySet.md +0 -5
  142. package/front_end/models/issues_manager/descriptions/arNavigationRegistrationWithoutTransientUserActivation.md +0 -6
  143. package/front_end/models/issues_manager/descriptions/arNoRegisterOsSourceHeader.md +0 -5
  144. package/front_end/models/issues_manager/descriptions/arNoRegisterOsTriggerHeader.md +0 -5
  145. package/front_end/models/issues_manager/descriptions/arNoRegisterSourceHeader.md +0 -5
  146. package/front_end/models/issues_manager/descriptions/arNoRegisterTriggerHeader.md +0 -5
  147. package/front_end/models/issues_manager/descriptions/arNoWebOrOsSupport.md +0 -4
  148. package/front_end/models/issues_manager/descriptions/arOsSourceIgnored.md +0 -18
  149. package/front_end/models/issues_manager/descriptions/arOsTriggerIgnored.md +0 -19
  150. package/front_end/models/issues_manager/descriptions/arPermissionPolicyDisabled.md +0 -8
  151. package/front_end/models/issues_manager/descriptions/arSourceAndTriggerHeaders.md +0 -9
  152. package/front_end/models/issues_manager/descriptions/arSourceIgnored.md +0 -13
  153. package/front_end/models/issues_manager/descriptions/arTriggerIgnored.md +0 -12
  154. package/front_end/models/issues_manager/descriptions/arUntrustworthyReportingOrigin.md +0 -10
  155. package/front_end/models/issues_manager/descriptions/arWebAndOsHeaders.md +0 -11
  156. package/front_end/models/trace/handlers/AuctionWorkletsHandler.ts +0 -183
  157. package/front_end/panels/application/InterestGroupStorageModel.ts +0 -81
  158. package/front_end/panels/application/InterestGroupStorageView.ts +0 -151
  159. package/front_end/panels/application/InterestGroupTreeElement.ts +0 -65
  160. package/front_end/panels/application/components/InterestGroupAccessGrid.ts +0 -135
  161. package/front_end/panels/application/components/interestGroupAccessGrid.css +0 -27
  162. package/front_end/panels/application/interestGroupStorageView.css +0 -9
  163. package/front_end/panels/issues/AttributionReportingIssueDetailsView.ts +0 -182
  164. package/front_end/panels/recorder/components/components.ts +0 -25
  165. package/front_end/panels/recorder/components/util.ts +0 -116
  166. package/front_end/panels/sources/InplaceFormatterEditorAction.ts +0 -149
  167. /package/front_end/panels/recorder/{components/controlButton.css → controlButton.css} +0 -0
  168. /package/front_end/panels/recorder/{components/createRecordingView.css → createRecordingView.css} +0 -0
  169. /package/front_end/panels/recorder/{components/extensionView.css → extensionView.css} +0 -0
  170. /package/front_end/panels/recorder/{components/recordingListView.css → recordingListView.css} +0 -0
  171. /package/front_end/panels/recorder/{components/recordingView.css → recordingView.css} +0 -0
  172. /package/front_end/panels/recorder/{components/replaySection.css → replaySection.css} +0 -0
  173. /package/front_end/panels/recorder/{components/selectorPicker.css → selectorPicker.css} +0 -0
  174. /package/front_end/panels/recorder/{components/startView.css → startView.css} +0 -0
  175. /package/front_end/panels/recorder/{components/stepEditor.css → stepEditor.css} +0 -0
  176. /package/front_end/panels/recorder/{components/stepView.css → stepView.css} +0 -0
  177. /package/front_end/panels/recorder/{components/timelineSection.css → timelineSection.css} +0 -0
@@ -11,12 +11,15 @@ import type * as Protocol from '../../generated/protocol.js';
11
11
  import * as EmulationModel from '../../models/emulation/emulation.js';
12
12
  import * as Geometry from '../../models/geometry/geometry.js';
13
13
  import * as UI from '../../ui/legacy/legacy.js';
14
+ import {Directives, html, nothing, render} from '../../ui/lit/lit.js';
14
15
  import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
15
16
 
16
17
  import {DeviceModeToolbar} from './DeviceModeToolbar.js';
17
18
  import deviceModeViewStyles from './deviceModeView.css.js';
18
19
  import {MediaQueryInspector} from './MediaQueryInspector.js';
19
20
 
21
+ const {classMap, styleMap} = Directives;
22
+
20
23
  const UIStrings = {
21
24
  /**
22
25
  * @description Bottom resizer element title in Device Mode View of the Device Toolbar
@@ -58,14 +61,12 @@ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
58
61
 
59
62
  export class DeviceModeView extends UI.Widget.VBox {
60
63
  wrapperInstance!: UI.Widget.VBox|null;
61
- blockElementToWidth: WeakMap<HTMLElement, number>;
62
64
  private model: EmulationModel.DeviceModeModel.DeviceModeModel;
63
65
  private readonly mediaInspector: MediaQueryInspector;
64
66
  private showMediaInspectorSetting: Common.Settings.Setting<boolean>;
65
67
  private showRulersSetting: Common.Settings.Setting<boolean>;
66
68
  private readonly topRuler: Ruler;
67
69
  private readonly leftRuler: Ruler;
68
- private presetBlocks!: HTMLElement[];
69
70
  private responsivePresetsContainer!: HTMLElement;
70
71
  private screenArea!: HTMLElement;
71
72
  private pageArea!: HTMLElement;
@@ -98,8 +99,6 @@ export class DeviceModeView extends UI.Widget.VBox {
98
99
  constructor() {
99
100
  super({useShadowDom: true});
100
101
 
101
- this.blockElementToWidth = new WeakMap();
102
-
103
102
  this.setMinimumSize(150, 150);
104
103
  this.element.classList.add('device-mode-view');
105
104
  this.registerRequiredCSS(deviceModeViewStyles);
@@ -114,9 +113,17 @@ export class DeviceModeView extends UI.Widget.VBox {
114
113
  this.showRulersSetting = Common.Settings.Settings.instance().moduleSetting('emulation.show-rulers');
115
114
  this.showRulersSetting.addChangeListener(this.updateUI, this);
116
115
 
117
- this.topRuler = new Ruler(true, this.model.setWidthAndScaleToFit.bind(this.model));
116
+ this.topRuler = new Ruler();
117
+ this.topRuler.horizontal = true;
118
+ this.topRuler.addEventListener(RulerEvents.MARKER_SELECTED, event => {
119
+ this.model.setWidthAndScaleToFit(event.data);
120
+ });
118
121
  this.topRuler.element.classList.add('device-mode-ruler-top');
119
- this.leftRuler = new Ruler(false, this.model.setHeightAndScaleToFit.bind(this.model));
122
+ this.leftRuler = new Ruler();
123
+ this.leftRuler.horizontal = false;
124
+ this.leftRuler.addEventListener(RulerEvents.MARKER_SELECTED, event => {
125
+ this.model.setHeightAndScaleToFit(event.data);
126
+ });
120
127
  this.leftRuler.element.classList.add('device-mode-ruler-left');
121
128
  this.createUI();
122
129
  UI.ZoomManager.ZoomManager.instance().addEventListener(UI.ZoomManager.Events.ZOOM_CHANGED, this.zoomChanged, this);
@@ -128,7 +135,7 @@ export class DeviceModeView extends UI.Widget.VBox {
128
135
  this.contentClip = this.contentElement.createChild('div', 'device-mode-content-clip vbox');
129
136
  this.responsivePresetsContainer = this.contentClip.createChild('div', 'device-mode-presets-container');
130
137
  this.responsivePresetsContainer.setAttribute('jslog', `${VisualLogging.responsivePresets()}`);
131
- this.populatePresetsContainer();
138
+ this.renderPresets();
132
139
  this.mediaInspectorContainer = this.contentClip.createChild('div', 'device-mode-media-container');
133
140
  this.contentArea = this.contentClip.createChild('div', 'device-mode-content-area');
134
141
  this.outlineImage = this.contentArea.createChild('img', 'device-mode-outline-image hidden fill');
@@ -161,7 +168,8 @@ export class DeviceModeView extends UI.Widget.VBox {
161
168
  this.pageArea.createChild('slot');
162
169
  }
163
170
 
164
- private populatePresetsContainer(): void {
171
+ private renderPresets(): void {
172
+ const scale = this.model.scale();
165
173
  const sizes = [320, 375, 425, 768, 1024, 1440, 2560];
166
174
  const titles = [
167
175
  i18nString(UIStrings.mobileS),
@@ -172,24 +180,29 @@ export class DeviceModeView extends UI.Widget.VBox {
172
180
  i18nString(UIStrings.laptopL),
173
181
  '4K',
174
182
  ];
175
- this.presetBlocks = [];
176
- const inner = this.responsivePresetsContainer.createChild('div', 'device-mode-presets-container-inner');
177
- for (let i = sizes.length - 1; i >= 0; --i) {
178
- const outer = inner.createChild('div', 'fill device-mode-preset-bar-outer');
179
- const block = outer.createChild('div', 'device-mode-preset-bar');
180
- block.createChild('span').textContent = titles[i] + ' \u2013 ' + sizes[i] + 'px';
181
- block.setAttribute(
182
- 'jslog', `${VisualLogging.action().track({click: true}).context(`device-mode-preset-${sizes[i]}px`)}`);
183
- block.addEventListener('click', applySize.bind(this, sizes[i]), false);
184
- this.blockElementToWidth.set(block, sizes[i]);
185
- this.presetBlocks.push(block);
186
- }
187
-
188
- function applySize(this: DeviceModeView, width: number, e: Event): void {
183
+
184
+ const applySize = (width: number, e: Event): void => {
189
185
  this.model.emulate(EmulationModel.DeviceModeModel.Type.Responsive, null, null);
190
186
  this.model.setWidthAndScaleToFit(width);
191
187
  e.consume();
192
- }
188
+ };
189
+
190
+ // eslint-disable-next-line @devtools/no-lit-render-outside-of-view
191
+ render(html`
192
+ <div class="device-mode-presets-container-inner">
193
+ ${sizes.map((size, idx) => html`
194
+ <div class="fill device-mode-preset-bar-outer">
195
+ <div class="device-mode-preset-bar"
196
+ style="width: ${size * scale}px;"
197
+ jslog=${VisualLogging.action().track({click: true}).context(`device-mode-preset-${size}px`)}
198
+ @click=${(e: Event) => applySize(size, e)}>
199
+ <span>${titles[idx]} – ${size}px</span>
200
+ </div>
201
+ </div>
202
+ `).reverse()}
203
+ </div>
204
+ `,
205
+ this.responsivePresetsContainer);
193
206
  }
194
207
 
195
208
  private createResizer(element: HTMLElement, widthFactor: number, heightFactor: number):
@@ -348,13 +361,7 @@ export class DeviceModeView extends UI.Widget.VBox {
348
361
  if (this.model.scale() !== this.cachedScale) {
349
362
  updateRulers = true;
350
363
  callDoResize = true;
351
- for (const block of this.presetBlocks) {
352
- const blockWidth = this.blockElementToWidth.get(block);
353
- if (!blockWidth) {
354
- throw new Error('Could not get width for block.');
355
- }
356
- block.style.width = blockWidth * this.model.scale() + 'px';
357
- }
364
+ this.renderPresets();
358
365
  this.cachedScale = this.model.scale();
359
366
  }
360
367
 
@@ -567,103 +574,147 @@ export class DeviceModeView extends UI.Widget.VBox {
567
574
  }
568
575
  }
569
576
 
570
- export class Ruler extends UI.Widget.VBox {
571
- #contentElement: HTMLElement;
572
- private readonly horizontal: boolean;
573
- private scale: number;
574
- private count: number;
575
- private readonly throttler: Common.Throttler.Throttler;
576
- private readonly applyCallback: (arg0: number) => void;
577
- private renderedScale!: number|undefined;
578
- private renderedZoomFactor!: number|undefined;
579
- constructor(horizontal: boolean, applyCallback: (arg0: number) => void) {
580
- super({jslog: `${VisualLogging.deviceModeRuler().track({click: true})}`});
581
- this.element.classList.add('device-mode-ruler');
582
- this.#contentElement =
583
- this.element.createChild('div', 'device-mode-ruler-content').createChild('div', 'device-mode-ruler-inner');
584
- this.horizontal = horizontal;
585
- this.scale = 1;
586
- this.count = 0;
587
- this.throttler = new Common.Throttler.Throttler(0);
588
- this.applyCallback = applyCallback;
577
+ export interface RulerViewInput {
578
+ horizontal: boolean;
579
+ scale: number;
580
+ onMarkerClick: (size: number) => void;
581
+ }
582
+
583
+ export type RulerView = (input: RulerViewInput, output: undefined, target: HTMLElement) => void;
584
+
585
+ export const DEFAULT_RULER_VIEW: RulerView = (input: RulerViewInput, output: undefined, target: HTMLElement): void => {
586
+ const zoomFactor = UI.ZoomManager.ZoomManager.instance().zoomFactor();
587
+ const size = input.horizontal ? target.offsetWidth : target.offsetHeight;
588
+
589
+ const dipSize = size * zoomFactor / input.scale;
590
+ const count = Math.ceil(dipSize / 5);
591
+ let step = 1;
592
+ if (input.scale < 0.8) {
593
+ step = 2;
594
+ }
595
+ if (input.scale < 0.6) {
596
+ step = 4;
597
+ }
598
+ if (input.scale < 0.4) {
599
+ step = 8;
600
+ }
601
+ if (input.scale < 0.2) {
602
+ step = 16;
603
+ }
604
+ if (input.scale < 0.1) {
605
+ step = 32;
589
606
  }
590
607
 
591
- render(scale: number): void {
592
- this.scale = scale;
593
- void this.throttler.schedule(this.update.bind(this));
608
+ const markers = [];
609
+ for (let i = 0; i < count; i++) {
610
+ if (i % step) {
611
+ continue;
612
+ }
613
+ const isLarge = !(i % 10);
614
+ const isMedium = !(i % 5);
615
+ const offset = i ? `${(5 * i) * input.scale / zoomFactor}px` : undefined;
616
+
617
+ // clang-format off
618
+ markers.push(html`
619
+ <div
620
+ class=${classMap({
621
+ 'device-mode-ruler-marker': true,
622
+ 'device-mode-ruler-marker-large': isLarge,
623
+ 'device-mode-ruler-marker-medium': isMedium && !isLarge,
624
+ })}
625
+ style=${styleMap(input.horizontal ? {left: offset} : {top: offset})}>
626
+ ${i && !(i % 20) ?
627
+ html`<div class="device-mode-ruler-text" @click=${() => input.onMarkerClick(i * 5)}>${i * 5}</div>` :
628
+ nothing}
629
+ </div>
630
+ `);
631
+ // clang-format on
594
632
  }
595
633
 
596
- override onResize(): void {
597
- void this.throttler.schedule(this.update.bind(this));
634
+ render(html`
635
+ <div class="device-mode-ruler-content">
636
+ <div class="device-mode-ruler-inner">
637
+ ${markers}
638
+ </div>
639
+ </div>
640
+ `,
641
+ target, {
642
+ container: {
643
+ classes: ['device-mode-ruler'],
644
+ attributes: {jslog: VisualLogging.deviceModeRuler().track({click: true})},
645
+ },
646
+ });
647
+ };
648
+
649
+ export const enum RulerEvents {
650
+ MARKER_SELECTED = 'MarkerSelected',
651
+ }
652
+
653
+ export interface RulerEventTypes {
654
+ [RulerEvents.MARKER_SELECTED]: number;
655
+ }
656
+
657
+ export class Ruler extends Common.ObjectWrapper.eventMixin<RulerEventTypes, typeof UI.Widget.Widget>(UI.Widget.Widget) {
658
+ #view: RulerView;
659
+ #horizontal = true;
660
+ #scale = 1;
661
+
662
+ constructor(element?: HTMLElement, view: RulerView = DEFAULT_RULER_VIEW) {
663
+ super(element);
664
+ this.#view = view;
598
665
  }
599
666
 
600
- update(): void {
601
- const zoomFactor = UI.ZoomManager.ZoomManager.instance().zoomFactor();
602
- const size = this.horizontal ? this.#contentElement.offsetWidth : this.#contentElement.offsetHeight;
667
+ get horizontal(): boolean {
668
+ return this.#horizontal;
669
+ }
603
670
 
604
- if (this.scale !== this.renderedScale || zoomFactor !== this.renderedZoomFactor) {
605
- this.#contentElement.removeChildren();
606
- this.count = 0;
607
- this.renderedScale = this.scale;
608
- this.renderedZoomFactor = zoomFactor;
671
+ set horizontal(horizontal: boolean) {
672
+ if (this.#horizontal === horizontal) {
673
+ return;
609
674
  }
675
+ this.#horizontal = horizontal;
676
+ this.requestUpdate();
677
+ }
610
678
 
611
- const dipSize = size * zoomFactor / this.scale;
612
- const count = Math.ceil(dipSize / 5);
613
- let step = 1;
614
- if (this.scale < 0.8) {
615
- step = 2;
616
- }
617
- if (this.scale < 0.6) {
618
- step = 4;
619
- }
620
- if (this.scale < 0.4) {
621
- step = 8;
622
- }
623
- if (this.scale < 0.2) {
624
- step = 16;
625
- }
626
- if (this.scale < 0.1) {
627
- step = 32;
628
- }
679
+ get scale(): number {
680
+ return this.#scale;
681
+ }
629
682
 
630
- for (let i = count; i < this.count; i++) {
631
- if (!(i % step)) {
632
- const lastChild = this.#contentElement.lastChild;
633
- if (lastChild) {
634
- lastChild.remove();
635
- }
636
- }
683
+ set scale(scale: number) {
684
+ if (this.#scale === scale) {
685
+ return;
637
686
  }
687
+ this.#scale = scale;
688
+ this.requestUpdate();
689
+ }
638
690
 
639
- for (let i = this.count; i < count; i++) {
640
- if (i % step) {
641
- continue;
642
- }
643
- const marker = this.#contentElement.createChild('div', 'device-mode-ruler-marker');
644
- if (i) {
645
- if (this.horizontal) {
646
- marker.style.left = (5 * i) * this.scale / zoomFactor + 'px';
647
- } else {
648
- marker.style.top = (5 * i) * this.scale / zoomFactor + 'px';
649
- }
650
- if (!(i % 20)) {
651
- const text = marker.createChild('div', 'device-mode-ruler-text');
652
- text.textContent = String(i * 5);
653
- text.addEventListener('click', this.onMarkerClick.bind(this, i * 5), false);
654
- }
655
- }
656
- if (!(i % 10)) {
657
- marker.classList.add('device-mode-ruler-marker-large');
658
- } else if (!(i % 5)) {
659
- marker.classList.add('device-mode-ruler-marker-medium');
660
- }
661
- }
691
+ render(scale: number): void {
692
+ this.scale = scale;
693
+ }
662
694
 
663
- this.count = count;
695
+ override wasShown(): void {
696
+ super.wasShown();
697
+ this.requestUpdate();
664
698
  }
665
699
 
666
- private onMarkerClick(size: number): void {
667
- this.applyCallback.call(null, size);
700
+ override onResize(): void {
701
+ super.onResize();
702
+ this.requestUpdate();
703
+ }
704
+
705
+ #onMarkerClick = (size: number): void => {
706
+ this.dispatchEventToListeners(RulerEvents.MARKER_SELECTED, size);
707
+ };
708
+
709
+ override performUpdate(): void {
710
+ if (!this.isShowing()) {
711
+ return;
712
+ }
713
+ const viewInput: RulerViewInput = {
714
+ horizontal: this.#horizontal,
715
+ scale: this.#scale,
716
+ onMarkerClick: this.#onMarkerClick,
717
+ };
718
+ this.#view(viewInput, undefined, this.contentElement);
668
719
  }
669
720
  }
@@ -84,7 +84,7 @@ export abstract class AffectedResourcesView extends UI.TreeOutline.TreeElement {
84
84
 
85
85
  this.affectedResources = this.createAffectedResources();
86
86
  this.#affectedResourcesCount = 0;
87
- this.requestResolver = new Logs.RequestResolver.RequestResolver();
87
+ this.requestResolver = new Logs.RequestResolver.RequestResolver(Logs.NetworkLog.NetworkLog.instance());
88
88
  this.#frameListeners = [];
89
89
  this.#unresolvedFrameIds = new Set();
90
90
  }
@@ -33,7 +33,6 @@ import {AffectedSelectivePermissionsInterventionView} from './AffectedSelectiveP
33
33
  import {AffectedSharedArrayBufferIssueDetailsView} from './AffectedSharedArrayBufferIssueDetailsView.js';
34
34
  import {AffectedSourcesView} from './AffectedSourcesView.js';
35
35
  import {AffectedTrackingSitesView} from './AffectedTrackingSitesView.js';
36
- import {AttributionReportingIssueDetailsView} from './AttributionReportingIssueDetailsView.js';
37
36
  import * as Components from './components/components.js';
38
37
  import type {HiddenIssuesMenuData} from './components/HideIssuesMenu.js';
39
38
  import {CorsIssueDetailsView} from './CorsIssueDetailsView.js';
@@ -254,7 +253,6 @@ export class IssueView extends UI.TreeOutline.TreeElement {
254
253
  new CorsIssueDetailsView(this, this.#issue, 'cors-details'),
255
254
  new GenericIssueDetailsView(this, this.#issue, 'generic-details'),
256
255
  new AffectedDocumentsInQuirksModeView(this, this.#issue, 'affected-documents'),
257
- new AttributionReportingIssueDetailsView(this, this.#issue, 'attribution-reporting-details'),
258
256
  new AffectedRawCookieLinesView(this, this.#issue, 'affected-raw-cookies'),
259
257
  new AffectedTrackingSitesView(this, this.#issue, 'tracking-sites-details'),
260
258
  new AffectedMetadataAllowedSitesView(this, this.#issue, 'metadata-allowed-sites-details'),
@@ -91,11 +91,6 @@ const UIStrings = {
91
91
  * @description Text that explains the issues panel that is shown if no issues are shown.
92
92
  */
93
93
  issuesPanelDescription: 'On this page you can find warnings from the browser.',
94
- /**
95
- * @description Category title for the different 'Attribution Reporting API' issues. The
96
- * Attribution Reporting API is a newly proposed web API (see https://github.com/WICG/conversion-measurement-api).
97
- */
98
- attributionReporting: 'Attribution Reporting `API`',
99
94
  /**
100
95
  * @description Category title for the different 'Quirks Mode' issues. Quirks Mode refers
101
96
  * to the legacy browser modes that displays web content according to outdated
@@ -149,8 +144,6 @@ class IssueCategoryView extends UI.TreeOutline.TreeElement {
149
144
  return i18nString(UIStrings.lowTextContrast);
150
145
  case IssuesManager.Issue.IssueCategory.CORS:
151
146
  return i18nString(UIStrings.cors);
152
- case IssuesManager.Issue.IssueCategory.ATTRIBUTION_REPORTING:
153
- return i18nString(UIStrings.attributionReporting);
154
147
  case IssuesManager.Issue.IssueCategory.QUIRKS_MODE:
155
148
  return i18nString(UIStrings.quirksMode);
156
149
  case IssuesManager.Issue.IssueCategory.GENERIC:
@@ -271,7 +264,7 @@ export class IssuesPane extends UI.Widget.VBox {
271
264
  });
272
265
  groupByKindSettingCheckbox.setVisible(true);
273
266
 
274
- const thirdPartySetting = IssuesManager.Issue.getShowThirdPartyIssuesSetting();
267
+ const thirdPartySetting = IssuesManager.Issue.getShowThirdPartyIssuesSetting(Common.Settings.Settings.instance());
275
268
  this.#showThirdPartyCheckbox = new UI.Toolbar.ToolbarSettingCheckbox(
276
269
  thirdPartySetting, i18nString(UIStrings.includeCookieIssuesCausedBy),
277
270
  i18nString(UIStrings.includeThirdpartyCookieIssues));
@@ -71,8 +71,9 @@ UI.ViewManager.registerViewExtension({
71
71
  isPreviewFeature: true,
72
72
  async loadView(universe) {
73
73
  const Timeline = await loadTimelineModule();
74
- const {pageResourceLoader: resourceLoader} = universe;
75
- return Timeline.TimelinePanel.TimelinePanel.instance({forceNew: true, resourceLoader});
74
+ const {pageResourceLoader: resourceLoader, targetManager, isolateManager} = universe;
75
+ return Timeline.TimelinePanel.TimelinePanel.instance(
76
+ {forceNew: true, resourceLoader, targetManager, isolateManager});
76
77
  },
77
78
  });
78
79
 
@@ -5,7 +5,7 @@
5
5
  import * as Common from '../../core/common/common.js';
6
6
  import * as i18n from '../../core/i18n/i18n.js';
7
7
  import type * as Platform from '../../core/platform/platform.js';
8
- import type * as ProtocolClient from '../../core/protocol_client/protocol_client.js';
8
+ import * as ProtocolClient from '../../core/protocol_client/protocol_client.js';
9
9
  import * as SDK from '../../core/sdk/sdk.js';
10
10
  import type * as Protocol from '../../generated/protocol.js';
11
11
  import type * as LighthouseModel from '../../models/lighthouse/lighthouse.js';
@@ -78,6 +78,14 @@ export class ProtocolService implements ProtocolClient.CDPConnection.CDPConnecti
78
78
  private configForTesting?: object;
79
79
  private connection?: ProtocolClient.CDPConnection.CDPConnection;
80
80
 
81
+ /**
82
+ * Session ids that belong to this Lighthouse run. The proxy only relays
83
+ * worker commands and connection events that target one of these sessions
84
+ * so that traffic stays scoped to the parallel session created in
85
+ * `attach()` and its descendants.
86
+ */
87
+ readonly #knownSessionIds = new Set<string>();
88
+
81
89
  /**
82
90
  * Tracks pending requests to the Lighthouse worker.
83
91
  * Key: The message ID sent to the worker.
@@ -119,6 +127,8 @@ export class ProtocolService implements ProtocolClient.CDPConnection.CDPConnecti
119
127
 
120
128
  const rootTargetId = await rootChildTargetManager.getParentTargetId();
121
129
  const {sessionId} = await rootTarget.targetAgent().invoke_attachToTarget({targetId: rootTargetId, flatten: true});
130
+ this.#knownSessionIds.clear();
131
+ this.#knownSessionIds.add(sessionId);
122
132
  this.connection = connection;
123
133
  this.connection.observe(this);
124
134
 
@@ -217,6 +227,7 @@ export class ProtocolService implements ProtocolClient.CDPConnection.CDPConnecti
217
227
  this.rootTarget = undefined;
218
228
  this.connection?.unobserve(this);
219
229
  this.connection = undefined;
230
+ this.#knownSessionIds.clear();
220
231
 
221
232
  if (oldLighthouseWorker) {
222
233
  (await oldLighthouseWorker).terminate();
@@ -237,18 +248,29 @@ export class ProtocolService implements ProtocolClient.CDPConnection.CDPConnecti
237
248
  }
238
249
 
239
250
  private dispatchProtocolMessage(message: ProtocolClient.CDPConnection.CDPReceivableMessage): void {
240
- // A message without a sessionId is the main session of the main target (call it "Main session").
241
- // A parallel connection and session was made that connects to the same main target (call it "Lighthouse session").
242
- // Messages from the "Lighthouse session" have a sessionId.
243
- // Without some care, there is a risk of sending the same events for the same main frame to Lighthouse–the backend
244
- // will create events for the "Main session" and the "Lighthouse session".
245
- // The workaround–only send message to Lighthouse if:
246
- // * the message has a sessionId (is not for the "Main session")
247
- // * the message does not have a sessionId (is for the "Main session"), but only for the Target domain
248
- // (to kickstart autoAttach in LH).
249
- if (message.sessionId || ('method' in message && message.method?.startsWith('Target'))) {
250
- void this.send('dispatchProtocolMessage', {message});
251
+ // The shared CDPConnection carries traffic for every DevTools session. A
252
+ // parallel session is created for the Lighthouse run in `attach()`, and the
253
+ // worker only ever needs traffic that belongs to that session or one of the
254
+ // child sessions it subsequently attaches. Filtering on `#knownSessionIds`
255
+ // keeps the proxy scoped to the run instead of broadcasting unrelated
256
+ // session traffic into the worker.
257
+ if (!message.sessionId || !this.#knownSessionIds.has(message.sessionId)) {
258
+ return;
259
+ }
260
+ if ('method' in message) {
261
+ if (message.method === 'Target.attachedToTarget') {
262
+ const childSessionId = (message.params as Protocol.Target.AttachedToTargetEvent | undefined)?.sessionId;
263
+ if (childSessionId) {
264
+ this.#knownSessionIds.add(childSessionId);
265
+ }
266
+ } else if (message.method === 'Target.detachedFromTarget') {
267
+ const childSessionId = (message.params as Protocol.Target.DetachedFromTargetEvent | undefined)?.sessionId;
268
+ if (childSessionId) {
269
+ this.#knownSessionIds.delete(childSessionId);
270
+ }
271
+ }
251
272
  }
273
+ void this.send('dispatchProtocolMessage', {message});
252
274
  }
253
275
 
254
276
  onDisconnect(): void {
@@ -303,11 +325,30 @@ export class ProtocolService implements ProtocolClient.CDPConnection.CDPConnecti
303
325
 
304
326
  private sendProtocolMessage(message: string): void {
305
327
  const {id, method, params, sessionId} = JSON.parse(message);
328
+ // The worker is expected to only address the parallel session created in
329
+ // `attach()` or sessions discovered beneath it. Anything else, including
330
+ // the root session, is outside the scope of the run.
331
+ if (!sessionId || !this.#knownSessionIds.has(sessionId)) {
332
+ void this.send('dispatchProtocolMessage', {
333
+ message: {
334
+ id,
335
+ sessionId,
336
+ error: {
337
+ code: ProtocolClient.CDPConnection.CDPErrorStatus.SESSION_NOT_FOUND,
338
+ message: `Unknown session id: ${sessionId}`,
339
+ },
340
+ },
341
+ });
342
+ return;
343
+ }
306
344
  // CDPConnection manages it's own message IDs and it's important, otherwise we'd clash
307
345
  // with the rest of the DevTools traffic.
308
346
  // Instead, we ignore the ID coming from the worker when sending the command, but
309
347
  // patch it back in when sending the response back to the worker.
310
348
  void this.connection?.send(method, params, sessionId).then(response => {
349
+ if ('result' in response && method === 'Target.attachToTarget' && response.result?.sessionId) {
350
+ this.#knownSessionIds.add(response.result.sessionId);
351
+ }
311
352
  const message =
312
353
  'result' in response ? {id, sessionId, result: response.result} : {id, sessionId, error: response.error};
313
354
  this.dispatchProtocolMessage(message);
@@ -14,11 +14,11 @@ import {Events as LmiEvents, LinearMemoryInspectorPane} from './LinearMemoryInsp
14
14
 
15
15
  const UIStrings = {
16
16
  /**
17
- * @description Error message that shows up in the console if a buffer to be opened in the linear memory inspector cannot be found.
17
+ * @description Error message that shows up in the console if a buffer to be opened in the Memory inspector panel cannot be found.
18
18
  */
19
- couldNotOpenLinearMemory: 'Could not open linear memory inspector: failed locating buffer.',
19
+ couldNotOpenLinearMemory: 'Could not open Memory inspector: buffer not found.',
20
20
  /**
21
- * @description A context menu item in the Scope View of the Sources Panel
21
+ * @description A context menu item in the Scope view of the Sources panel.
22
22
  */
23
23
  openInMemoryInspectorPanel: 'Open in Memory inspector panel',
24
24
  } as const;
@@ -15,17 +15,17 @@ import {type LazyUint8Array, LinearMemoryInspectorController} from './LinearMemo
15
15
 
16
16
  const UIStrings = {
17
17
  /**
18
- * @description Label in the Linear Memory inspector tool that serves as a placeholder if no inspections are open (i.e. nothing to see here).
19
- * Inspection hereby refers to viewing, navigating and understanding the memory through this tool.
18
+ * @description Label in the Memory inspector panel that serves as a placeholder if no inspections are open (i.e., nothing to see here).
19
+ * Inspection here refers to viewing, navigating, and understanding the memory through this panel.
20
20
  */
21
21
  noOpenInspections: 'No open inspections',
22
22
  /**
23
- * @description Label in the Linear Memory inspector tool that serves as a placeholder if no inspections are open (i.e. nothing to see here).
24
- * Inspection hereby refers to viewing, navigating and understanding the memory through this tool.
23
+ * @description Label in the Memory inspector panel that serves as a placeholder if no inspections are open (i.e., nothing to see here).
24
+ * Inspection here refers to viewing, navigating, and understanding the memory through this panel.
25
25
  */
26
26
  memoryInspectorExplanation: 'On this page you can inspect binary data.',
27
27
  /**
28
- * @description Label in the Linear Memory inspector tool for a link.
28
+ * @description Label in the Memory inspector panel for a link.
29
29
  */
30
30
  learnMore: 'Learn more',
31
31
  } as const;
@@ -14,13 +14,13 @@ import type {HighlightInfo} from './LinearMemoryViewerUtils.js';
14
14
 
15
15
  const UIStrings = {
16
16
  /**
17
- * @description Tooltip text that appears when hovering over an inspected variable's button in the Linear Memory Highlight Chip List.
18
- * Clicking the button changes the displayed slice of computer memory in the Linear Memory inspector to contain the inspected variable's bytes.
17
+ * @description Tooltip text that appears when hovering over an inspected variable's button in the highlight chip list in the Memory inspector panel.
18
+ * Clicking the button changes the displayed slice of computer memory in the Memory inspector panel to contain the inspected variable's bytes.
19
19
  */
20
20
  jumpToAddress: 'Jump to this memory',
21
21
  /**
22
- * @description Tooltip text that appears when hovering over an inspected variable's delete button in the Linear Memory Highlight Chip List.
23
- * Clicking the delete button stops highlighting the variable's memory in the Linear Memory inspector.
22
+ * @description Tooltip text that appears when hovering over an inspected variable's delete button in the highlight chip list in the Memory inspector panel.
23
+ * Clicking the delete button stops highlighting the variable's memory in the Memory inspector panel.
24
24
  * 'Memory' is a slice of bytes in the computer memory.
25
25
  */
26
26
  deleteHighlight: 'Stop highlighting this memory',
@@ -32,11 +32,11 @@ import {
32
32
 
33
33
  const UIStrings = {
34
34
  /**
35
- * @description Tooltip text that appears when hovering over an invalid address in the address line in the Linear memory inspector
35
+ * @description Tooltip text that appears when hovering over an invalid address in the address line in the Memory inspector panel.
36
36
  * @example {0x00000000} PH1
37
37
  * @example {0x00400000} PH2
38
38
  */
39
- addressHasToBeANumberBetweenSAnd: 'Address has to be a number between {PH1} and {PH2}',
39
+ addressHasToBeANumberBetweenSAnd: 'Address must be a number between {PH1} and {PH2}',
40
40
  } as const;
41
41
  const str_ =
42
42
  i18n.i18n.registerUIStrings('panels/linear_memory_inspector/components/LinearMemoryInspector.ts', UIStrings);