chrome-devtools-frontend 1.0.1598808 → 1.0.1601661

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 (161) hide show
  1. package/.agents/README.md +13 -0
  2. package/{agents/prompts/creating-a-model.md → .agents/skills/creating-a-model/SKILL.md} +7 -1
  3. package/{agents/prompts/devtools-imports.md → .agents/skills/devtools-imports/SKILL.md} +10 -5
  4. package/{agents/prompts/merging-devtools-module.md → .agents/skills/merging-devtools-module/SKILL.md} +5 -0
  5. package/{agents/prompts/ui-widgets.md → .agents/skills/ui-widgets/SKILL.md} +5 -0
  6. package/{agents/prompts/verification.md → .agents/skills/verification/SKILL.md} +5 -0
  7. package/front_end/core/common/Settings.ts +24 -1
  8. package/front_end/core/dom_extension/DOMExtension.ts +1 -0
  9. package/front_end/core/host/AidaClient.ts +5 -2
  10. package/front_end/core/host/AidaGcaTranslation.ts +377 -0
  11. package/front_end/core/host/GcaTypes.ts +520 -0
  12. package/front_end/core/host/UserMetrics.ts +0 -3
  13. package/front_end/core/host/host.ts +4 -0
  14. package/front_end/core/root/ExperimentNames.ts +0 -3
  15. package/front_end/core/sdk/CPUThrottlingManager.ts +12 -9
  16. package/front_end/core/sdk/ResourceTreeModel.ts +1 -1
  17. package/front_end/core/sdk/SourceMap.ts +4 -2
  18. package/front_end/entrypoints/main/MainImpl.ts +1 -12
  19. package/front_end/generated/Deprecation.ts +16 -0
  20. package/front_end/generated/InspectorBackendCommands.ts +4 -6
  21. package/front_end/generated/protocol.ts +46 -77
  22. package/front_end/models/ai_assistance/AiConversation.ts +49 -22
  23. package/front_end/models/ai_assistance/AiHistoryStorage.snapshot.txt +1 -1
  24. package/front_end/models/ai_assistance/AiHistoryStorage.ts +1 -0
  25. package/front_end/models/ai_assistance/ConversationHandler.ts +16 -11
  26. package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +76 -36
  27. package/front_end/models/ai_assistance/agents/AiAgent.ts +26 -2
  28. package/front_end/models/ai_assistance/agents/BreakpointDebuggerAgent.ts +0 -1
  29. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.snapshot.txt +11 -0
  30. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +39 -0
  31. package/front_end/models/ai_assistance/agents/ConversationSummaryAgent.ts +53 -12
  32. package/front_end/models/ai_assistance/agents/FileAgent.ts +0 -15
  33. package/front_end/models/ai_assistance/agents/NetworkAgent.ts +0 -5
  34. package/front_end/models/ai_assistance/agents/PerformanceAgent.snapshot.txt +57 -0
  35. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +87 -15
  36. package/front_end/models/ai_assistance/agents/PerformanceAnnotationsAgent.ts +0 -10
  37. package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +0 -6
  38. package/front_end/models/ai_assistance/agents/StylingAgent.ts +1 -5
  39. package/front_end/models/ai_assistance/ai_assistance.ts +2 -0
  40. package/front_end/models/ai_assistance/data_formatters/LighthouseFormatter.snapshot.txt +84 -0
  41. package/front_end/models/ai_assistance/data_formatters/LighthouseFormatter.ts +172 -0
  42. package/front_end/models/breakpoints/BreakpointManager.ts +20 -12
  43. package/front_end/models/emulation/DeviceModeModel.ts +5 -1
  44. package/front_end/models/emulation/EmulatedDevices.ts +3 -2
  45. package/front_end/models/javascript_metadata/NativeFunctions.js +60 -0
  46. package/front_end/models/lighthouse/LighthouseReporterTypes.ts +104 -10
  47. package/front_end/models/lighthouse/RunTypes.ts +42 -0
  48. package/front_end/models/lighthouse/lighthouse.ts +2 -0
  49. package/front_end/models/live-metrics/web-vitals-injected/web-vitals-injected.ts +59 -35
  50. package/front_end/models/stack_trace/StackTrace.ts +5 -0
  51. package/front_end/models/stack_trace/StackTraceImpl.ts +7 -1
  52. package/front_end/models/stack_trace/StackTraceModel.ts +2 -1
  53. package/front_end/models/stack_trace/stack_trace.ts +4 -0
  54. package/front_end/models/trace/ModelImpl.ts +4 -0
  55. package/front_end/models/trace/helpers/SamplesIntegrator.ts +1 -8
  56. package/front_end/models/trace/types/Configuration.ts +0 -5
  57. package/front_end/panels/accessibility/AccessibilityNodeView.ts +7 -3
  58. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +163 -74
  59. package/front_end/panels/ai_assistance/ExportConversation.ts +25 -0
  60. package/front_end/panels/ai_assistance/ai_assistance.ts +2 -0
  61. package/front_end/panels/ai_assistance/components/ChatInput.ts +2 -0
  62. package/front_end/panels/ai_assistance/components/ChatMessage.ts +120 -32
  63. package/front_end/panels/ai_assistance/components/ChatView.ts +44 -0
  64. package/front_end/panels/ai_assistance/components/ExportForAgentsDialog.ts +240 -0
  65. package/front_end/panels/ai_assistance/components/PerformanceAgentMarkdownRenderer.ts +4 -12
  66. package/front_end/panels/ai_assistance/components/StylingAgentMarkdownRenderer.ts +5 -27
  67. package/front_end/panels/ai_assistance/components/WalkthroughView.ts +115 -17
  68. package/front_end/panels/ai_assistance/components/chatMessage.css +65 -1
  69. package/front_end/panels/ai_assistance/components/chatView.css +8 -0
  70. package/front_end/panels/ai_assistance/components/exportForAgentsDialog.css +82 -0
  71. package/front_end/panels/ai_assistance/components/walkthroughView.css +9 -1
  72. package/front_end/panels/animation/AnimationTimeline.ts +5 -5
  73. package/front_end/panels/application/AppManifestView.ts +13 -7
  74. package/front_end/panels/application/FrameDetailsView.ts +4 -4
  75. package/front_end/panels/application/preloading/PreloadingView.ts +2 -4
  76. package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +6 -3
  77. package/front_end/panels/application/preloading/components/PreloadingString.ts +15 -2
  78. package/front_end/panels/application/preloading/helper/PreloadingForward.ts +31 -2
  79. package/front_end/panels/browser_debugger/DOMBreakpointsSidebarPane.ts +3 -2
  80. package/front_end/panels/common/DOMLinkifier.ts +10 -8
  81. package/front_end/panels/console/ConsoleView.ts +24 -2
  82. package/front_end/panels/console/ConsoleViewMessage.ts +22 -23
  83. package/front_end/panels/console/console.ts +0 -2
  84. package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +5 -5
  85. package/front_end/panels/elements/ElementsTreeElement.ts +2 -3
  86. package/front_end/panels/elements/PropertiesWidget.ts +5 -3
  87. package/front_end/panels/elements/StandaloneStylesContainer.ts +21 -9
  88. package/front_end/panels/elements/StylePropertiesSection.ts +98 -50
  89. package/front_end/panels/elements/StylePropertyTreeElement.ts +38 -4
  90. package/front_end/panels/elements/StylesAiCodeCompletionProvider.ts +43 -35
  91. package/front_end/panels/elements/StylesSidebarPane.ts +154 -24
  92. package/front_end/panels/elements/components/ComputedStyleTrace.ts +3 -2
  93. package/front_end/panels/event_listeners/EventListenersView.ts +16 -4
  94. package/front_end/panels/explain/components/ConsoleInsight.ts +6 -9
  95. package/front_end/panels/explain/explain-meta.ts +5 -0
  96. package/front_end/panels/issues/AffectedResourcesView.ts +5 -9
  97. package/front_end/panels/issues/AffectedSelectivePermissionsInterventionView.ts +1 -1
  98. package/front_end/panels/lighthouse/LighthouseController.ts +154 -164
  99. package/front_end/panels/lighthouse/LighthousePanel.ts +5 -9
  100. package/front_end/panels/lighthouse/LighthouseProtocolService.ts +1 -0
  101. package/front_end/panels/lighthouse/LighthouseReportRenderer.ts +9 -6
  102. package/front_end/panels/lighthouse/LighthouseStartView.ts +7 -6
  103. package/front_end/panels/lighthouse/LighthouseStatusView.ts +32 -8
  104. package/front_end/panels/linear_memory_inspector/components/LinearMemoryInspector.ts +7 -3
  105. package/front_end/panels/network/NetworkDataGridNode.ts +34 -0
  106. package/front_end/panels/network/NetworkLogViewColumns.ts +10 -0
  107. package/front_end/panels/network/RequestPayloadView.ts +4 -1
  108. package/front_end/panels/network/RequestTimingView.ts +8 -2
  109. package/front_end/panels/performance_monitor/performanceMonitor.css +6 -4
  110. package/front_end/panels/recorder/RecorderController.ts +52 -14
  111. package/front_end/panels/recorder/components/RecordingView.ts +2 -1
  112. package/front_end/panels/recorder/models/RecordingStorage.ts +15 -20
  113. package/front_end/panels/sensors/SensorsView.ts +333 -157
  114. package/front_end/panels/settings/emulation/DevicesSettingsTab.ts +18 -4
  115. package/front_end/panels/sources/DebuggerPausedMessage.ts +6 -6
  116. package/front_end/panels/sources/FilteredUISourceCodeListProvider.ts +2 -3
  117. package/front_end/panels/sources/NavigatorView.ts +11 -7
  118. package/front_end/panels/sources/ScopeChainSidebarPane.ts +1 -1
  119. package/front_end/panels/sources/SourcesPanel.ts +12 -34
  120. package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +5 -1
  121. package/front_end/panels/sources/sources-meta.ts +6 -0
  122. package/front_end/panels/timeline/StatusDialog.ts +159 -83
  123. package/front_end/panels/timeline/ThirdPartyTreeView.ts +6 -2
  124. package/front_end/panels/timeline/TimelineController.ts +0 -4
  125. package/front_end/panels/timeline/TimelineDetailsView.ts +35 -3
  126. package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +6 -1
  127. package/front_end/panels/timeline/TimelineFlameChartNetworkDataProvider.ts +9 -4
  128. package/front_end/panels/timeline/TimelinePanel.ts +36 -11
  129. package/front_end/panels/timeline/TimelineTreeView.ts +14 -3
  130. package/front_end/panels/timeline/TimelineUIUtils.ts +5 -57
  131. package/front_end/panels/timeline/components/InteractionBreakdown.ts +2 -1
  132. package/front_end/panels/timeline/components/LiveMetricsView.ts +2 -2
  133. package/front_end/panels/timeline/components/NetworkRequestTooltip.ts +3 -7
  134. package/front_end/panels/timeline/components/Sidebar.ts +11 -19
  135. package/front_end/panels/timeline/components/SidebarInsightsTab.ts +2 -1
  136. package/front_end/panels/timeline/components/SidebarSingleInsightSet.ts +60 -27
  137. package/front_end/panels/timeline/components/TimelineRangeSummaryView.ts +66 -0
  138. package/front_end/panels/timeline/components/TimelineSummary.ts +7 -19
  139. package/front_end/panels/timeline/components/components.ts +2 -0
  140. package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +55 -28
  141. package/front_end/panels/timeline/components/insights/NodeLink.ts +3 -3
  142. package/front_end/panels/timeline/components/insights/baseInsightComponent.css +7 -0
  143. package/front_end/panels/timeline/components/insights/insights.ts +0 -2
  144. package/front_end/panels/timeline/components/timelineRangeSummaryView.css +20 -0
  145. package/front_end/panels/timeline/overlays/OverlaysImpl.ts +7 -7
  146. package/front_end/panels/timeline/timeline-meta.ts +11 -0
  147. package/front_end/panels/timeline/timelineDetailsView.css +0 -9
  148. package/front_end/third_party/chromium/README.chromium +1 -1
  149. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onINP.js +11 -2
  150. package/front_end/third_party/web-vitals/package/src/attribution/onINP.ts +11 -2
  151. package/front_end/third_party/web-vitals/patches/0001-Add-onEachInteraction-to-onINP-options.patch +65 -4
  152. package/front_end/ui/kit/link/link.css +2 -2
  153. package/front_end/ui/legacy/Widget.ts +5 -3
  154. package/front_end/ui/legacy/components/object_ui/CustomPreviewComponent.ts +7 -2
  155. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +57 -35
  156. package/front_end/ui/legacy/components/source_frame/PreviewFactory.ts +1 -0
  157. package/front_end/ui/visual_logging/KnownContextValues.ts +6 -1
  158. package/package.json +1 -1
  159. package/agents/prompts/README.md +0 -18
  160. package/front_end/panels/timeline/components/insights/InsightRenderer.ts +0 -93
  161. /package/front_end/{panels/console → models/stack_trace}/ErrorStackParser.ts +0 -0
@@ -12,7 +12,7 @@ import * as PanelsCommon from '../../common/common.js';
12
12
  import {MarkdownRendererWithCodeBlock} from './MarkdownRendererWithCodeBlock.js';
13
13
 
14
14
  const {html} = Lit.StaticHtml;
15
- const {ref, createRef} = Lit.Directives;
15
+ const {until} = Lit.Directives;
16
16
 
17
17
  export class StylingAgentMarkdownRenderer extends MarkdownRendererWithCodeBlock {
18
18
  constructor(
@@ -99,16 +99,8 @@ export class StylingAgentMarkdownRenderer extends MarkdownRendererWithCodeBlock
99
99
  }
100
100
 
101
101
  if (nodeId) {
102
- const templateRef = createRef();
103
- void this.#linkifyNode(nodeId, token.text).then(node => {
104
- if (!templateRef.value || !node) {
105
- return;
106
- }
107
-
108
- templateRef.value.textContent = '';
109
- templateRef.value.append(node);
110
- });
111
- return html`<span ${ref(templateRef)}>${token.text}</span>`;
102
+ return html`<span>${
103
+ until(this.#linkifyNode(nodeId, token.text).then(node => node || token.text), token.text)}</span>`;
112
104
  }
113
105
  }
114
106
 
@@ -157,24 +149,10 @@ export class StylingAgentMarkdownRenderer extends MarkdownRendererWithCodeBlock
157
149
 
158
150
  #renderSingleLink(nodeId: Protocol.DOM.BackendNodeId): Lit.LitTemplate {
159
151
  const label = `link`;
160
- const templateRef = createRef();
161
- void this.#linkifyNode(nodeId, label).then(node => {
162
- if (!templateRef.value) {
163
- return;
164
- }
165
- templateRef.value.textContent = '';
166
- if (node) {
167
- templateRef.value.append(node);
168
- } else {
169
- // Fallback to plain text if linkification fails
170
- templateRef.value.append(document.createTextNode(label));
171
- }
172
- });
173
- // Placeholder for async link
174
- return html`<span ${ref(templateRef)}>${label}</span>`;
152
+ return html`<span>${until(this.#linkifyNode(nodeId, label).then(node => node || label), label)}</span>`;
175
153
  }
176
154
 
177
- async #linkifyNode(backendNodeId: Protocol.DOM.BackendNodeId, label: string): Promise<Node|undefined> {
155
+ async #linkifyNode(backendNodeId: Protocol.DOM.BackendNodeId, label: string): Promise<Lit.LitTemplate|undefined> {
178
156
  if (backendNodeId === undefined) {
179
157
  return;
180
158
  }
@@ -15,7 +15,9 @@ import walkthroughViewStyles from './walkthroughView.css.js';
15
15
 
16
16
  const lockedString = i18n.i18n.lockedString;
17
17
 
18
- const {html, render} = Lit;
18
+ const {html, render, Directives} = Lit;
19
+ const {ref} = Directives;
20
+ const SCROLL_ROUND_OFFSET = 2;
19
21
 
20
22
  const UIStrings = {
21
23
  /**
@@ -46,6 +48,12 @@ export interface ViewInput {
46
48
  isExpanded: boolean;
47
49
  onToggle: (isOpen: boolean) => void;
48
50
  onOpen: (message: ModelChatMessage) => void;
51
+ handleScroll: (ev: Event) => void;
52
+ }
53
+
54
+ export interface ViewOutput {
55
+ scrollContainer?: HTMLElement;
56
+ stepsContainer?: HTMLElement;
49
57
  }
50
58
 
51
59
  export function walkthroughTitle(input: {
@@ -69,7 +77,12 @@ function renderInlineWalkthrough(input: ViewInput, stepsOutput: Lit.LitTemplate,
69
77
  }
70
78
 
71
79
  function onToggle(event: Event): void {
72
- input.onToggle((event.target as HTMLDetailsElement).open);
80
+ const isOpen = (event.target as HTMLDetailsElement).open;
81
+ if (isOpen && input.message) {
82
+ input.onOpen(input.message);
83
+ } else {
84
+ input.onToggle(isOpen);
85
+ }
73
86
  }
74
87
 
75
88
  const hasWidgets = steps.some(s => s.widgets?.length);
@@ -121,27 +134,33 @@ function renderSidebarWalkthrough(input: ViewInput, stepsOutput: Lit.LitTemplate
121
134
 
122
135
  export const DEFAULT_VIEW = (
123
136
  input: ViewInput,
124
- _output: null,
137
+ output: ViewOutput,
125
138
  target: HTMLElement|DocumentFragment,
126
139
  ): void => {
127
140
  const steps = input.message?.parts.filter(t => t.type === 'step')?.map(p => p.step) ?? [];
128
141
 
129
142
  // clang-format off
130
143
  const stepsOutput = steps.length > 0 ? html`
131
- <div class="steps-container">
132
- ${steps.map((step, index) => html`
133
- <div class="walkthrough-step">
134
- <span class="step-number">${index+1}</span>
135
- <div class="step-wrapper">
136
- ${renderStep({
137
- step,
138
- isLoading: input.isLoading,
139
- markdownRenderer: input.markdownRenderer,
140
- isLast: index === steps.length - 1
141
- })}
144
+ <div class="steps-container" @scroll=${input.handleScroll} ${ref(el => {
145
+ output.scrollContainer = el as HTMLElement;
146
+ })}>
147
+ <div class="steps-scroll-content" ${ref(el => {
148
+ output.stepsContainer = el as HTMLElement;
149
+ })}>
150
+ ${steps.map((step, index) => html`
151
+ <div class="walkthrough-step">
152
+ <span class="step-number">${index + 1}</span>
153
+ <div class="step-wrapper">
154
+ ${renderStep({
155
+ step,
156
+ isLoading: input.isLoading,
157
+ markdownRenderer: input.markdownRenderer,
158
+ isLast: index === steps.length - 1
159
+ })}
160
+ </div>
142
161
  </div>
143
- </div>
144
- `)}
162
+ `)}
163
+ </div>
145
164
  </div>
146
165
  ` : Lit.nothing;
147
166
 
@@ -172,11 +191,83 @@ export class WalkthroughView extends UI.Widget.Widget {
172
191
  #isInlined = false;
173
192
  #isExpanded = false;
174
193
 
194
+ #pinScrollToBottom = true;
195
+ #isProgrammaticScroll = false;
196
+
197
+ #output: ViewOutput = {};
198
+ #stepsContainerResizeObserver = new ResizeObserver(() => this.#handleStepsContainerResize());
199
+
175
200
  constructor(element?: HTMLElement, view: View = DEFAULT_VIEW) {
176
201
  super(element);
177
202
  this.#view = view;
178
203
  }
179
204
 
205
+ override wasShown(): void {
206
+ super.wasShown();
207
+ this.#registerResizeObservers();
208
+ }
209
+
210
+ override willHide(): void {
211
+ super.willHide();
212
+ this.#stepsContainerResizeObserver.disconnect();
213
+ }
214
+
215
+ #registerResizeObservers(): void {
216
+ if (this.#output.stepsContainer) {
217
+ this.#stepsContainerResizeObserver.observe(this.#output.stepsContainer);
218
+ }
219
+ }
220
+
221
+ override onResize(): void {
222
+ this.#handleStepsContainerResize();
223
+ }
224
+
225
+ #handleStepsContainerResize(): void {
226
+ if (!this.#pinScrollToBottom) {
227
+ return;
228
+ }
229
+
230
+ this.scrollToBottom();
231
+ }
232
+
233
+ scrollToBottom(): void {
234
+ if (!this.#output.stepsContainer) {
235
+ return;
236
+ }
237
+
238
+ this.#isProgrammaticScroll = true;
239
+ window.requestAnimationFrame(() => {
240
+ const lastElement = this.#output.stepsContainer?.lastElementChild;
241
+ if (lastElement) {
242
+ lastElement.scrollIntoView({
243
+ behavior: 'smooth',
244
+ block: 'end',
245
+ });
246
+ }
247
+ });
248
+ }
249
+
250
+ #handleScroll = (ev: Event): void => {
251
+ if (!ev.target || !(ev.target instanceof HTMLElement)) {
252
+ return;
253
+ }
254
+
255
+ if (this.#isProgrammaticScroll) {
256
+ // For smooth scrolling, multiple scroll events will be fired.
257
+ // We only reset the flag once we've reached the bottom,
258
+ // or we can just rely on the fact that if it's programmatic,
259
+ // we don't want to change the pinning state based on mid-scroll positions.
260
+ const isAtBottom = ev.target.scrollTop + ev.target.clientHeight + SCROLL_ROUND_OFFSET >= ev.target.scrollHeight;
261
+ if (isAtBottom) {
262
+ this.#isProgrammaticScroll = false;
263
+ }
264
+ return;
265
+ }
266
+
267
+ this.#pinScrollToBottom =
268
+ ev.target.scrollTop + ev.target.clientHeight + SCROLL_ROUND_OFFSET >= ev.target.scrollHeight;
269
+ };
270
+
180
271
  set isLoading(isLoading: boolean) {
181
272
  this.#isLoading = isLoading;
182
273
  this.requestUpdate();
@@ -241,7 +332,14 @@ export class WalkthroughView extends UI.Widget.Widget {
241
332
  isInlined: this.#isInlined,
242
333
  isExpanded: this.#isExpanded,
243
334
  message: this.#message,
335
+ handleScroll: this.#handleScroll,
244
336
  },
245
- null, this.contentElement);
337
+ this.#output, this.contentElement);
338
+
339
+ this.#registerResizeObservers();
340
+
341
+ if (this.#pinScrollToBottom) {
342
+ this.scrollToBottom();
343
+ }
246
344
  }
247
345
  }
@@ -366,13 +366,16 @@
366
366
  }
367
367
 
368
368
  .step-widgets-wrapper {
369
- width: fit-content;
370
369
  display: flex;
371
370
  flex-direction: column;
372
371
  align-items: flex-start;
373
372
  gap: var(--sys-size-5);
374
373
  }
375
374
 
375
+ .widget-and-revealer-container {
376
+ width: 100%;
377
+ }
378
+
376
379
  .widget-reveal-container {
377
380
  background: var(--sys-color-surface5);
378
381
  border-bottom-right-radius: var(--sys-shape-corner-medium);
@@ -380,6 +383,11 @@
380
383
  padding: 0 var(--sys-size-4) var(--sys-size-4) 0;
381
384
  }
382
385
 
386
+ .revealer-only .widget-reveal-container {
387
+ background: none;
388
+ border-radius: unset;
389
+ }
390
+
383
391
  .widget-content-container {
384
392
  padding: var(--sys-size-4);
385
393
  border-top-left-radius: var(--sys-shape-corner-medium);
@@ -389,4 +397,60 @@
389
397
 
390
398
  --override-computed-style-property-white-space: normal;
391
399
  }
400
+
401
+ .network-request-preview {
402
+ display: flex;
403
+ flex-direction: column;
404
+ gap: var(--sys-size-4);
405
+ margin-bottom: var(--sys-size-5);
406
+ padding-bottom: var(--sys-size-5);
407
+ border-bottom: 1px solid var(--sys-color-divider);
408
+
409
+ .network-request-header {
410
+ display: flex;
411
+ align-items: center;
412
+ gap: var(--sys-size-5);
413
+
414
+ .network-request-icon {
415
+ width: 32px;
416
+ height: 32px;
417
+ display: flex;
418
+ align-items: center;
419
+ justify-content: center;
420
+ background-color: var(--sys-color-surface1);
421
+ border-radius: var(--sys-shape-corner-small);
422
+ border: 1px solid var(--sys-color-divider);
423
+ overflow: hidden;
424
+
425
+ img {
426
+ max-width: 100%;
427
+ max-height: 100%;
428
+ object-fit: contain;
429
+ }
430
+
431
+ devtools-icon {
432
+ width: 20px;
433
+ height: 20px;
434
+ }
435
+ }
436
+
437
+ .network-request-details {
438
+ display: flex;
439
+ flex-direction: column;
440
+ overflow: hidden;
441
+
442
+ .network-request-name {
443
+ font: var(--sys-typescale-body4-bold);
444
+ overflow: hidden;
445
+ text-overflow: ellipsis;
446
+ white-space: nowrap;
447
+ }
448
+
449
+ .network-request-size {
450
+ font: var(--sys-typescale-body4-regular);
451
+ color: var(--sys-color-on-surface-subtle);
452
+ }
453
+ }
454
+ }
455
+ }
392
456
  }
@@ -411,3 +411,11 @@ main {
411
411
  padding-bottom: var(--sys-size-1);
412
412
  }
413
413
  }
414
+
415
+ .export-for-agents-button {
416
+ /* Bottom margin to ensure it's not right up against the chat box when
417
+ * the conversation requires a scrollbar */
418
+ margin: 0 auto var(--sys-size-8) auto;
419
+ display: block;
420
+
421
+ }
@@ -0,0 +1,82 @@
1
+ /*
2
+ * Copyright 2026 The Chromium Authors
3
+ * Use of this source code is governed by a BSD-style license that can be
4
+ * found in the LICENSE file.
5
+ */
6
+
7
+ @scope to (devtools-widget > *) {
8
+ :scope {
9
+ width: 100%;
10
+ box-shadow: none;
11
+ padding: var(--sys-size-8);
12
+ background-color: var(--sys-color-surface);
13
+ border-radius: var(--sys-shape-corner-medium);
14
+ }
15
+
16
+ .export-for-agents-dialog {
17
+ width: var(--sys-size-33); /* 512px */
18
+ max-width: 100%; /* deal with the dialog being squashed on smaller devices */
19
+ }
20
+
21
+ .export-for-agents-dialog header {
22
+ margin-bottom: var(--sys-size-6);
23
+
24
+ h2 {
25
+ font: var(--sys-typescale-headline5);
26
+ margin: 0;
27
+ color: var(--sys-color-on-surface);
28
+ }
29
+ }
30
+
31
+ .export-for-agents-dialog .state-selection {
32
+ display: flex;
33
+ gap: var(--sys-size-5);
34
+ margin: var(--sys-size-7) 0;
35
+ }
36
+
37
+ .export-for-agents-dialog .state-selection label {
38
+ display: flex;
39
+ align-items: center;
40
+ gap: var(--sys-size-2);
41
+ cursor: pointer;
42
+ font: var(--sys-typescale-body3-regular);
43
+
44
+ input {
45
+ /* Remove the margin on radio buttons so that the text and the
46
+ * radio button are properly aligned vertically. */
47
+ margin-bottom: 0;
48
+ }
49
+ }
50
+
51
+ .export-for-agents-dialog textarea {
52
+ width: 100%;
53
+ min-height: var(--sys-size-30); /* 288px */
54
+ max-height: var(--sys-size-34); /* 512px */
55
+ resize: none;
56
+ padding: var(--sys-size-5);
57
+ box-sizing: border-box;
58
+ font-family: var(--monospace-font-family);
59
+ font-size: var(--monospace-font-size);
60
+ background-color: var(--sys-color-surface5);
61
+ color: var(--sys-color-on-surface);
62
+ border-radius: var(--sys-shape-corner-small);
63
+ border: none;
64
+ }
65
+
66
+ .export-for-agents-dialog .disclaimer {
67
+ margin-top: var(--sys-size-5);
68
+ font: var(--sys-typescale-body4-regular);
69
+ color: var(--sys-color-on-surface-subtle);
70
+ }
71
+
72
+ .export-for-agents-dialog footer {
73
+ display: flex;
74
+ justify-content: flex-end;
75
+ margin-top: var(--sys-size-6);
76
+ }
77
+
78
+ .export-for-agents-dialog .right-buttons {
79
+ display: flex;
80
+ gap: var(--sys-size-5);
81
+ }
82
+ }
@@ -8,7 +8,9 @@
8
8
  .walkthrough-view {
9
9
  height: 100%;
10
10
  background-color: var(--sys-color-cdt-base-container);
11
- overflow: auto;
11
+ overflow: hidden;
12
+ display: flex;
13
+ flex-direction: column;
12
14
  }
13
15
  }
14
16
 
@@ -32,6 +34,9 @@
32
34
  .steps-container {
33
35
  flex: 1;
34
36
  overflow-y: auto;
37
+ }
38
+
39
+ .steps-scroll-content {
35
40
  padding: var(--sys-size-6);
36
41
  display: flex;
37
42
  flex-direction: column;
@@ -43,6 +48,7 @@
43
48
  gap: var(--sys-size-6);
44
49
  align-items: flex-start;
45
50
  justify-content: flex-start;
51
+ flex-shrink: 0;
46
52
 
47
53
  .step-number {
48
54
  font: var(--sys-typescale-body4-regular);
@@ -57,6 +63,8 @@
57
63
  display: flex;
58
64
  flex-direction: column;
59
65
  gap: var(--sys-size-5);
66
+ min-width: 0;
67
+ width: 100%;
60
68
  }
61
69
 
62
70
  .step-container {
@@ -1215,12 +1215,12 @@ export class NodeUI {
1215
1215
  }
1216
1216
  this.#node = node;
1217
1217
  this.nodeChanged();
1218
- const link = PanelsCommon.DOMLinkifier.Linkifier.instance().linkify(node);
1219
- link.addEventListener('click', () => {
1220
- Host.userMetrics.actionTaken(Host.UserMetrics.Action.AnimatedNodeDescriptionClicked);
1218
+ const link = PanelsCommon.DOMLinkifier.Linkifier.instance().linkify(node, {
1219
+ onClick: () => {
1220
+ Host.userMetrics.actionTaken(Host.UserMetrics.Action.AnimatedNodeDescriptionClicked);
1221
+ }
1221
1222
  });
1222
-
1223
- this.#description.appendChild(link);
1223
+ render(link, this.#description, {host: this});
1224
1224
  if (!node.ownerDocument) {
1225
1225
  this.nodeRemoved();
1226
1226
  }
@@ -1354,13 +1354,19 @@ export class AppManifestView extends Common.ObjectWrapper.eventMixin<EventTypes,
1354
1354
  if (!frameId) {
1355
1355
  throw new Error('no main frame found');
1356
1356
  }
1357
- const {content} = await SDK.PageResourceLoader.PageResourceLoader.instance().loadResource(
1358
- url, {
1359
- target: this.target,
1360
- frameId,
1361
- initiatorUrl: this.target.inspectedURL(),
1362
- },
1363
- /* isBinary=*/ true);
1357
+ let content;
1358
+ try {
1359
+ const response = await SDK.PageResourceLoader.PageResourceLoader.instance().loadResource(
1360
+ url, {
1361
+ target: this.target,
1362
+ frameId,
1363
+ initiatorUrl: this.target.inspectedURL(),
1364
+ },
1365
+ /* isBinary=*/ true);
1366
+ content = response.content;
1367
+ } catch {
1368
+ return null;
1369
+ }
1364
1370
  // Just loading the image, not building UI.
1365
1371
  /* eslint-disable @devtools/no-imperative-dom-api */
1366
1372
  const image = document.createElement('img');
@@ -265,14 +265,14 @@ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
265
265
  export interface FrameDetailsReportViewData {
266
266
  frame: SDK.ResourceTreeModel.ResourceTreeFrame;
267
267
  target?: SDK.Target.Target;
268
- adScriptAncestry: Protocol.Page.AdScriptAncestry|null;
268
+ adScriptAncestry: Protocol.Network.AdAncestry|null;
269
269
  }
270
270
 
271
271
  interface FrameDetailsViewInput {
272
272
  frame: SDK.ResourceTreeModel.ResourceTreeFrame;
273
273
  target: SDK.Target.Target|null;
274
274
  creationStackTrace: StackTrace.StackTrace.StackTrace|null;
275
- adScriptAncestry: Protocol.Page.AdScriptAncestry|null;
275
+ adScriptAncestry: Protocol.Network.AdAncestry|null;
276
276
  linkTargetDOMNode: SDK.DOMModel.DOMNode|null;
277
277
  permissionsPolicies: Protocol.Page.PermissionsPolicyFeatureState[]|null;
278
278
  protocolMonitorExperimentEnabled: boolean;
@@ -506,7 +506,7 @@ function maybeRenderAdStatus(
506
506
 
507
507
  function maybeRenderCreatorAdScriptAncestry(
508
508
  adFrameType: Protocol.Page.AdFrameType|null, target: SDK.Target.Target|null,
509
- adScriptAncestry: Protocol.Page.AdScriptAncestry|null): LitTemplate {
509
+ adScriptAncestry: Protocol.Network.AdAncestry|null): LitTemplate {
510
510
  if (adFrameType === Protocol.Page.AdFrameType.None) {
511
511
  return nothing;
512
512
  }
@@ -842,7 +842,7 @@ export class FrameDetailsReportView extends UI.Widget.Widget {
842
842
  #protocolMonitorExperimentEnabled = false;
843
843
  #permissionsPolicies: Protocol.Page.PermissionsPolicyFeatureState[]|null = null;
844
844
  #linkifier = new Components.Linkifier.Linkifier();
845
- #adScriptAncestry: Protocol.Page.AdScriptAncestry|null = null;
845
+ #adScriptAncestry: Protocol.Network.AdAncestry|null = null;
846
846
  #view: View;
847
847
 
848
848
  constructor(element?: HTMLElement, view = DEFAULT_VIEW) {
@@ -620,10 +620,8 @@ export class PreloadingAttemptView extends UI.Widget.VBox {
620
620
  return ruleSet === null ? [] : [ruleSet];
621
621
  });
622
622
 
623
- // Lookup status code for prefetch attempts
624
- const statusCode = attempt.action === Protocol.Preload.SpeculationAction.Prefetch ?
625
- PreloadingHelper.PreloadingForward.prefetchStatusCode(attempt.requestId) :
626
- undefined;
623
+ // Lookup status code from the network log for display in the grid.
624
+ const statusCode = PreloadingHelper.PreloadingForward.preloadStatusCode(attempt);
627
625
 
628
626
  return {
629
627
  id,
@@ -349,8 +349,8 @@ export class PreloadingDetailsReportView extends LegacyWrapper.LegacyWrapper.Wra
349
349
  return Lit.nothing;
350
350
  }
351
351
 
352
- // Lookup status code for Non2XX failures
353
- const statusCode = PreloadingHelper.PreloadingForward.prefetchStatusCode(attempt.requestId);
352
+ // Lookup status code for Non2XX failures.
353
+ const statusCode = PreloadingHelper.PreloadingForward.preloadStatusCode(attempt);
354
354
 
355
355
  const failureDescription = prefetchFailureReason(attempt, statusCode);
356
356
  if (failureDescription === null) {
@@ -389,8 +389,11 @@ export class PreloadingDetailsReportView extends LegacyWrapper.LegacyWrapper.Wra
389
389
  return Lit.nothing;
390
390
  }
391
391
 
392
+ // Lookup status code from the network log for NavigationBadHttpStatus.
393
+ const statusCode = PreloadingHelper.PreloadingForward.preloadStatusCode(attempt);
394
+
392
395
  const failureReason = prerenderFailureReason(
393
- attempt as SDK.PreloadingModel.PrerenderAttempt | SDK.PreloadingModel.PrerenderUntilScriptAttempt);
396
+ attempt as SDK.PreloadingModel.PrerenderAttempt | SDK.PreloadingModel.PrerenderUntilScriptAttempt, statusCode);
394
397
  if (failureReason === null) {
395
398
  return Lit.nothing;
396
399
  }
@@ -176,6 +176,12 @@ const UIStrings = {
176
176
  */
177
177
  prerenderFinalStatusNavigationBadHttpStatus:
178
178
  'The prerendering navigation failed because of a non-2xx HTTP response status code.',
179
+ /**
180
+ * @description Description text for PrerenderFinalStatus::kNavigationBadHttpStatus when the HTTP status code is known.
181
+ * @example {404} PH1
182
+ */
183
+ prerenderFinalStatusNavigationBadHttpStatusWithStatusCode:
184
+ 'The prerendering navigation failed because of a non-2xx HTTP response status code ({PH1}).',
179
185
  /**
180
186
  * Description text for PrerenderFinalStatus::kClientCertRequested.
181
187
  */
@@ -545,7 +551,8 @@ export function prefetchFailureReason(
545
551
 
546
552
  /** Detailed failure reason for PrerenderFinalStatus. **/
547
553
  export function prerenderFailureReason(
548
- attempt: SDK.PreloadingModel.PrerenderAttempt|SDK.PreloadingModel.PrerenderUntilScriptAttempt): string|null {
554
+ attempt: SDK.PreloadingModel.PrerenderAttempt|SDK.PreloadingModel.PrerenderUntilScriptAttempt,
555
+ statusCode?: number): string|null {
549
556
  // If you face an error on rolling CDP changes, see
550
557
  // https://docs.google.com/document/d/1PnrfowsZMt62PX1EvvTp2Nqs3ji1zrklrAEe1JYbkTk
551
558
  switch (attempt.prerenderStatus) {
@@ -581,7 +588,12 @@ export function prerenderFailureReason(
581
588
  // TODO(https://crbug.com/1410709): Fill it.
582
589
  return i18n.i18n.lockedString('Internal error');
583
590
  case Protocol.Preload.PrerenderFinalStatus.NavigationBadHttpStatus:
591
+ if (statusCode !== undefined) {
592
+ return i18nString(
593
+ UIStrings.prerenderFinalStatusNavigationBadHttpStatusWithStatusCode, {PH1: String(statusCode)});
594
+ }
584
595
  return i18nString(UIStrings.prerenderFinalStatusNavigationBadHttpStatus);
596
+
585
597
  case Protocol.Preload.PrerenderFinalStatus.ClientCertRequested:
586
598
  return i18nString(UIStrings.prerenderFinalStatusClientCertRequested);
587
599
  case Protocol.Preload.PrerenderFinalStatus.NavigationRequestNetworkError:
@@ -819,7 +831,8 @@ export function composedStatus(attempt: SDK.PreloadingModel.PreloadingAttempt, s
819
831
  case Protocol.Preload.SpeculationAction.Prerender:
820
832
  case Protocol.Preload.SpeculationAction.PrerenderUntilScript: {
821
833
  const detail = prerenderFailureReason(
822
- attempt as SDK.PreloadingModel.PrerenderAttempt | SDK.PreloadingModel.PrerenderUntilScriptAttempt);
834
+ attempt as SDK.PreloadingModel.PrerenderAttempt | SDK.PreloadingModel.PrerenderUntilScriptAttempt,
835
+ statusCode);
823
836
  assertNotNullOrUndefined(detail);
824
837
  return short + ' - ' + detail;
825
838
  }
@@ -2,7 +2,8 @@
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 type * as Protocol from '../../../../generated/protocol.js';
5
+ import * as SDK from '../../../../core/sdk/sdk.js';
6
+ import * as Protocol from '../../../../generated/protocol.js';
6
7
  import * as Logs from '../../../../models/logs/logs.js';
7
8
 
8
9
  export class RuleSetView {
@@ -21,11 +22,26 @@ export class AttemptViewWithFilter {
21
22
  }
22
23
  }
23
24
 
25
+ /**
26
+ * Retrieves the HTTP status code for a preloading attempt.
27
+ */
28
+ export function preloadStatusCode(attempt: SDK.PreloadingModel.PreloadingAttempt): number|undefined {
29
+ switch (attempt.action) {
30
+ case Protocol.Preload.SpeculationAction.Prefetch:
31
+ return prefetchStatusCode(attempt.requestId);
32
+ case Protocol.Preload.SpeculationAction.Prerender:
33
+ case Protocol.Preload.SpeculationAction.PrerenderUntilScript:
34
+ return prerenderStatusCode(attempt.key.loaderId);
35
+ }
36
+
37
+ return undefined;
38
+ }
39
+
24
40
  /**
25
41
  * Retrieves the HTTP status code for a prefetch attempt by looking up its
26
42
  * network request in the network log.
27
43
  */
28
- export function prefetchStatusCode(requestId: Protocol.Network.RequestId): number|undefined {
44
+ function prefetchStatusCode(requestId: Protocol.Network.RequestId): number|undefined {
29
45
  const networkLog = Logs.NetworkLog.NetworkLog.instance();
30
46
  const requests = networkLog.requestsForId(requestId);
31
47
  if (requests.length > 0) {
@@ -33,3 +49,16 @@ export function prefetchStatusCode(requestId: Protocol.Network.RequestId): numbe
33
49
  }
34
50
  return undefined;
35
51
  }
52
+
53
+ /**
54
+ * Retrieves the HTTP status code for a prerender attempt.
55
+ */
56
+ function prerenderStatusCode(loaderId: Protocol.Network.LoaderId): number|undefined {
57
+ const frame = SDK.ResourceTreeModel.ResourceTreeModel.frames().find(f => f.loaderId === loaderId);
58
+ if (!frame) {
59
+ return undefined;
60
+ }
61
+ const networkManager = frame.resourceTreeModel().target().model(SDK.NetworkManager.NetworkManager);
62
+ const request = networkManager?.requestForLoaderId(loaderId);
63
+ return request?.statusCode === 0 ? undefined : request?.statusCode;
64
+ }