chrome-devtools-frontend 1.0.1643099 → 1.0.1645245

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 (99) hide show
  1. package/eslint.config.mjs +3 -1
  2. package/extension-api/ExtensionAPI.d.ts +83 -12
  3. package/front_end/core/host/UserMetrics.ts +3 -3
  4. package/front_end/core/root/ExperimentNames.ts +0 -1
  5. package/front_end/core/sdk/CSSPropertyParserMatchers.ts +2 -3
  6. package/front_end/core/sdk/ConsoleModel.ts +4 -0
  7. package/front_end/core/sdk/NetworkRequest.ts +12 -1
  8. package/front_end/core/sdk/SourceMap.ts +15 -18
  9. package/front_end/entrypoints/greendev_floaty/FloatyEntrypoint.ts +0 -2
  10. package/front_end/entrypoints/greendev_floaty/greendev_floaty.ts +0 -2
  11. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +37 -0
  12. package/front_end/entrypoints/main/MainImpl.ts +0 -6
  13. package/front_end/generated/SupportedCSSProperties.js +4 -2
  14. package/front_end/models/ai_assistance/AiAgent2.ts +23 -12
  15. package/front_end/models/ai_assistance/README.md +5 -4
  16. package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +22 -16
  17. package/front_end/models/ai_assistance/agents/AiAgent.ts +19 -6
  18. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +5 -5
  19. package/front_end/models/ai_assistance/agents/ExecuteJavascript.ts +1 -94
  20. package/front_end/models/ai_assistance/agents/NetworkAgent.ts +25 -0
  21. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +37 -0
  22. package/front_end/models/ai_assistance/agents/README.md +57 -0
  23. package/front_end/models/ai_assistance/agents/StorageAgent.ts +54 -1
  24. package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +1 -2
  25. package/front_end/models/ai_assistance/agents/StylingAgent.ts +31 -3
  26. package/front_end/models/ai_assistance/tools/ExecuteJavaScript.ts +12 -21
  27. package/front_end/models/ai_assistance/tools/GetStyles.ts +19 -12
  28. package/front_end/models/ai_assistance/tools/README.md +45 -0
  29. package/front_end/models/ai_assistance/tools/Tool.ts +78 -9
  30. package/front_end/models/ai_assistance/tools/ToolRegistry.ts +21 -5
  31. package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +6 -9
  32. package/front_end/models/bindings/DefaultScriptMapping.ts +2 -1
  33. package/front_end/models/bindings/SymbolizedError.ts +45 -35
  34. package/front_end/models/extensions/ExtensionAPI.ts +138 -47
  35. package/front_end/models/har/Importer.ts +1 -0
  36. package/front_end/models/heap_snapshot/HeapSnapshotModel.ts +18 -2
  37. package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +4 -0
  38. package/front_end/models/source_map_scopes/FunctionCodeResolver.ts +12 -2
  39. package/front_end/models/stack_trace/DetailedErrorStackParser.ts +58 -52
  40. package/front_end/models/stack_trace/StackTrace.ts +7 -0
  41. package/front_end/models/stack_trace/StackTraceImpl.ts +13 -4
  42. package/front_end/models/stack_trace/StackTraceModel.ts +43 -9
  43. package/front_end/models/trace/Styles.ts +29 -7
  44. package/front_end/models/trace/handlers/PageLoadMetricsHandler.ts +33 -4
  45. package/front_end/models/trace/helpers/Timing.ts +10 -0
  46. package/front_end/models/trace/types/TraceEvents.ts +22 -2
  47. package/front_end/panels/accessibility/AccessibilitySidebarView.ts +2 -1
  48. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +9 -2
  49. package/front_end/panels/ai_assistance/ai_assistance-meta.ts +16 -0
  50. package/front_end/panels/application/ApplicationPanelSidebar.ts +83 -0
  51. package/front_end/panels/application/ApplicationPanelTreeElement.ts +39 -0
  52. package/front_end/panels/application/CookieItemsView.ts +2 -2
  53. package/front_end/panels/application/ServiceWorkersView.ts +2 -2
  54. package/front_end/panels/application/WebMCPView.ts +0 -1
  55. package/front_end/panels/application/components/BackForwardCacheView.ts +1 -2
  56. package/front_end/panels/application/resourcesSidebar.css +11 -0
  57. package/front_end/panels/console/ConsoleView.ts +6 -1
  58. package/front_end/panels/console/ConsoleViewMessage.ts +46 -213
  59. package/front_end/panels/console/SymbolizedErrorWidget.ts +14 -8
  60. package/front_end/panels/elements/AdoptedStyleSheetTreeElement.ts +0 -1
  61. package/front_end/panels/elements/ElementsTreeElement.ts +0 -2
  62. package/front_end/panels/elements/PropertyRenderer.ts +0 -1
  63. package/front_end/panels/elements/StylesSidebarPane.ts +9 -2
  64. package/front_end/panels/issues/AffectedResourcesView.ts +1 -1
  65. package/front_end/panels/issues/AffectedSourcesView.ts +1 -1
  66. package/front_end/panels/lighthouse/LighthouseReportRenderer.ts +0 -1
  67. package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +10 -0
  68. package/front_end/panels/network/NetworkDataGridNode.ts +1 -2
  69. package/front_end/panels/network/NetworkLogView.ts +34 -7
  70. package/front_end/panels/profiler/HeapProfileView.ts +0 -1
  71. package/front_end/panels/profiler/HeapSnapshotGridNodes.ts +0 -1
  72. package/front_end/panels/profiler/HeapSnapshotView.ts +1 -1
  73. package/front_end/panels/settings/components/SyncSection.ts +1 -1
  74. package/front_end/panels/settings/emulation/DevicesSettingsTab.ts +1 -0
  75. package/front_end/panels/sources/SourcesPanel.ts +2 -1
  76. package/front_end/panels/timeline/TimelineFlameChartView.ts +5 -4
  77. package/front_end/panels/timeline/TimelinePanel.ts +7 -0
  78. package/front_end/panels/timeline/TimelineUIUtils.ts +13 -14
  79. package/front_end/panels/timeline/TimingsTrackAppender.ts +7 -5
  80. package/front_end/panels/timeline/components/LayoutShiftDetails.ts +0 -1
  81. package/front_end/panels/timeline/components/NetworkRequestDetails.ts +0 -2
  82. package/front_end/panels/timeline/components/insights/ForcedReflow.ts +0 -1
  83. package/front_end/panels/timeline/components/insights/NodeLink.ts +0 -1
  84. package/front_end/panels/timeline/overlays/OverlaysImpl.ts +2 -0
  85. package/front_end/third_party/chromium/README.chromium +1 -1
  86. package/front_end/ui/helpers/OpenInNewTab.ts +3 -3
  87. package/front_end/ui/kit/link/Link.ts +16 -2
  88. package/front_end/ui/legacy/InspectorDrawerView.ts +14 -5
  89. package/front_end/ui/legacy/InspectorView.ts +4 -1
  90. package/front_end/ui/legacy/PlusButton.ts +6 -1
  91. package/front_end/ui/legacy/StackedPane.ts +229 -0
  92. package/front_end/ui/legacy/ViewManager.ts +59 -169
  93. package/front_end/ui/legacy/Widget.ts +19 -1
  94. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +95 -31
  95. package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +0 -1
  96. package/front_end/ui/legacy/components/utils/Linkifier.ts +2 -16
  97. package/front_end/ui/legacy/legacy.ts +3 -1
  98. package/front_end/ui/visual_logging/KnownContextValues.ts +5 -0
  99. package/package.json +1 -1
@@ -28,8 +28,8 @@ function renderHeader(content: Lit.LitTemplate|Node|UI.Widget.Widget, isCause: b
28
28
  }
29
29
 
30
30
  function formatName(frame: StackTrace.StackTrace.ParsedErrorStackFrame): string {
31
- let name = frame.name || '';
32
- const isInline = Boolean(frame.rawName) && frame.name !== frame.rawName;
31
+ const isInline = frame.isInline;
32
+ let name = isInline ? (frame.name || '') : (frame.rawName || frame.name || '');
33
33
  const shouldAppendMethodAlias = !isInline && frame.methodName && name && name !== frame.methodName &&
34
34
  !name.endsWith('.' + frame.methodName) && !name.endsWith(' ' + frame.methodName);
35
35
  if (shouldAppendMethodAlias) {
@@ -105,10 +105,6 @@ function renderFrameSuffix(frame: StackTrace.StackTrace.ParsedErrorStackFrame):
105
105
 
106
106
  const DEFAULT_VIEW = (input: ViewInput, _output: object, target: HTMLElement): void => {
107
107
  const renderError = (error: Bindings.SymbolizedError.SymbolizedError, isCause: boolean): Lit.LitTemplate => {
108
- if (error instanceof Bindings.SymbolizedError.SymbolizedSyntaxError) {
109
- console.error('SymbolizedErrorWidget received an unsupported error type:', error);
110
- return Lit.nothing;
111
- }
112
108
  if (error instanceof Bindings.SymbolizedError.UnparsableError) {
113
109
  const fragment = ConsoleViewMessage.linkifyWithCustomLinkifier(
114
110
  error.errorStack,
@@ -126,11 +122,17 @@ const DEFAULT_VIEW = (input: ViewInput, _output: object, target: HTMLElement): v
126
122
 
127
123
  const linkOptions: Components.Linkifier.LinkifyOptions = {
128
124
  showColumnNumber: true,
129
- inlineFrameIndex: 0,
130
125
  maxLength: UI.UIUtils.MaxLengthForDisplayedURLsInConsole,
131
126
  ignoreListManager: input.ignoreListManager,
132
127
  };
133
- const headerContent = html`${error.message}`;
128
+
129
+ let headerContent = html`${error.message}`;
130
+ if (error.syntaxErrorLocation) {
131
+ const linkElement = Components.Linkifier.Linkifier.linkifyUILocation(error.syntaxErrorLocation, linkOptions);
132
+ linkElement.tabIndex = -1;
133
+ headerContent = html`${error.message} (at ${linkElement})`;
134
+ }
135
+
134
136
  const header = renderHeader(headerContent, isCause);
135
137
  const syncFrames = error.stackTrace.syncFragment.frames;
136
138
  // clang-format off
@@ -168,6 +170,10 @@ export class SymbolizedErrorWidget extends UI.Widget.Widget {
168
170
  this.#view = view;
169
171
  }
170
172
 
173
+ get linkElements(): readonly HTMLElement[] {
174
+ return [...this.contentElement.querySelectorAll<HTMLElement>('.devtools-link')];
175
+ }
176
+
171
177
  set ignoreListManager(ignoreListManager: Workspace.IgnoreListManager.IgnoreListManager) {
172
178
  this.#ignoreListManager = ignoreListManager;
173
179
  this.requestUpdate();
@@ -58,7 +58,6 @@ export class AdoptedStyleSheetTreeElement extends UI.TreeOutline.TreeElement {
58
58
  text: linkText,
59
59
  preventClick: true,
60
60
  showColumnNumber: false,
61
- inlineFrameIndex: 0,
62
61
  }));
63
62
  UI.UIUtils.createTextChild(documentElement, ')');
64
63
  }
@@ -644,7 +644,6 @@ function renderTitle(
644
644
  text,
645
645
  preventClick: true,
646
646
  showColumnNumber: false,
647
- inlineFrameIndex: 0,
648
647
  })}</span>)</span>`;
649
648
  }
650
649
 
@@ -733,7 +732,6 @@ function renderLinkifiedValue(value: string, node: SDK.DOMModel.DOMNode): Lit.Te
733
732
  text: value,
734
733
  preventClick: true,
735
734
  showColumnNumber: false,
736
- inlineFrameIndex: 0,
737
735
  onRef: link => {
738
736
  ImagePreviewPopover.setImageUrl(link, rewrittenHref);
739
737
  }
@@ -556,7 +556,6 @@ export class URLRenderer extends rendererBase(SDK.CSSPropertyParserMatchers.URLM
556
556
  // at the same time, which complicates both StylesSidebarPane and StylePropertyTreeElement.
557
557
  bypassURLTrimming: true,
558
558
  showColumnNumber: false,
559
- inlineFrameIndex: 0,
560
559
  }),
561
560
  hrefUrl || url);
562
561
  container.appendChild(link);
@@ -235,6 +235,7 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
235
235
  #shouldRenderLazily = false;
236
236
  #lazyRenderObserver?: IntersectionObserver;
237
237
  #lazyRenderCallbacks = new WeakMap<Element, () => void>();
238
+ #updateId = 0;
238
239
 
239
240
  constructor(computedStyleModel: ComputedStyle.ComputedStyleModel.ComputedStyleModel) {
240
241
  super(computedStyleModel, {delegatesFocus: true, useShadowDom: true, classes: ['flex-none']});
@@ -616,9 +617,15 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
616
617
  this.dispatchEventToListeners(Events.INITIAL_UPDATE_COMPLETED);
617
618
  }
618
619
 
619
- this.nodeStylesUpdatedForTest((this.node() as SDK.DOMModel.DOMNode), true);
620
+ this.#updateId += 1;
621
+ const currentUpdateId = this.#updateId;
620
622
 
621
- this.dispatchEventToListeners(Events.STYLES_UPDATE_COMPLETED, {hasMatchedStyles: this.hasMatchedStyles});
623
+ void UI.Widget.Widget.allUpdatesComplete.then(() => {
624
+ if (this.#updateId === currentUpdateId) {
625
+ this.nodeStylesUpdatedForTest((this.node() as SDK.DOMModel.DOMNode), true);
626
+ this.dispatchEventToListeners(Events.STYLES_UPDATE_COMPLETED, {hasMatchedStyles: this.hasMatchedStyles});
627
+ }
628
+ });
622
629
  }
623
630
 
624
631
  #getRegisteredPropertyDetails(matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles, variableName: string):
@@ -252,7 +252,7 @@ export abstract class AffectedResourcesView extends UI.TreeOutline.TreeElement {
252
252
  const linkifier = new Components.Linkifier.Linkifier(UI.UIUtils.MaxLengthForDisplayedURLsInConsole);
253
253
  const sourceAnchor = linkifier.linkifyScriptLocation(
254
254
  target || null, sourceLocation.scriptId || null, sourceLocation.url as Platform.DevToolsPath.UrlString,
255
- sourceLocation.lineNumber, {columnNumber: sourceLocation.columnNumber, inlineFrameIndex: 0});
255
+ sourceLocation.lineNumber, {columnNumber: sourceLocation.columnNumber});
256
256
  sourceAnchor.setAttribute('jslog', `${VisualLogging.link('source-location').track({click: true})}`);
257
257
  sourceCodeLocation.appendChild(sourceAnchor);
258
258
  }
@@ -39,7 +39,7 @@ export class AffectedSourcesView extends AffectedResourcesView {
39
39
  const cellElement = document.createElement('td');
40
40
  // TODO(chromium:1072331): Check feasibility of plumping through scriptId for `linkifyScriptLocation`
41
41
  // to support source maps and formatted scripts.
42
- const linkifierURLOptions = {columnNumber, lineNumber, tabStop: true, showColumnNumber: false, inlineFrameIndex: 0};
42
+ const linkifierURLOptions = {columnNumber, lineNumber, tabStop: true, showColumnNumber: false};
43
43
  // An element created with linkifyURL can subscribe to the events
44
44
  // 'click' neither 'keydown' if that key is the 'Enter' key.
45
45
  // Also, this element has a context menu, so we should be able to
@@ -198,7 +198,6 @@ export class LighthouseReportRenderer {
198
198
  lineNumber: line,
199
199
  columnNumber: column,
200
200
  showColumnNumber: false,
201
- inlineFrameIndex: 0,
202
201
  maxLength: MaxLengthForLinks,
203
202
  });
204
203
  UI.Tooltip.Tooltip.install(origHTMLElement, '');
@@ -180,10 +180,20 @@ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
180
180
  /**
181
181
  * This promise resolves after the first compute pressure record is observed.
182
182
  * The object it returns is always up-to-date with the most recent record observed.
183
+ *
184
+ * Note: The returned value measures the host machine's compute pressure. When
185
+ * debugging a remote device, this may trigger irrelevant high-pressure warnings.
183
186
  */
184
187
  function createComputePressurePromise(): Promise<{state: string}> {
185
188
  const result = {state: ''};
186
189
 
190
+ // @ts-expect-error typescript/lib version needs to be updated.
191
+ if (typeof PressureObserver === 'undefined') {
192
+ // The Compute Pressure API is used only for showing warnings to the user.
193
+ // If it's unavailable, resolve immediately to proceed without warnings.
194
+ return Promise.resolve(result);
195
+ }
196
+
187
197
  return new Promise(resolve => {
188
198
  // @ts-expect-error typescript/lib version needs to be updated.
189
199
  const observer = new PressureObserver(records => {
@@ -1515,8 +1515,7 @@ export class NetworkRequestNode extends NetworkNode {
1515
1515
  this.linkifiedInitiatorAnchor = linkifier.linkifyStackTraceTopFrame(target, initiator.stack);
1516
1516
  } else {
1517
1517
  this.linkifiedInitiatorAnchor = linkifier.linkifyScriptLocation(
1518
- target, initiator.scriptId, initiator.url, initiator.lineNumber,
1519
- {columnNumber: initiator.columnNumber, inlineFrameIndex: 0});
1518
+ target, initiator.scriptId, initiator.url, initiator.lineNumber, {columnNumber: initiator.columnNumber});
1520
1519
  }
1521
1520
  UI.Tooltip.Tooltip.install((this.linkifiedInitiatorAnchor), '');
1522
1521
  cell.appendChild(this.linkifiedInitiatorAnchor);
@@ -505,6 +505,11 @@ const UIStrings = {
505
505
  * @description Context menu item in Network panel to assess security headers of a request via AI.
506
506
  */
507
507
  assessSecurityHeaders: 'Assess security headers',
508
+ /**
509
+ * @description A comment in a generated command indicating that the URL scheme is unsupported. The placeholder is the comment prefix (e.g. '//' or '#').
510
+ * @example {//} PH1
511
+ */
512
+ unsupportedUrlScheme: '{PH1} Unsupported URL scheme',
508
513
  } as const;
509
514
  const str_ = i18n.i18n.registerUIStrings('panels/network/NetworkLogView.ts', UIStrings);
510
515
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
@@ -557,6 +562,8 @@ export class NetworkLogView extends Common.ObjectWrapper.eventMixin<EventTypes,
557
562
  private readonly textFilterSetting: Common.Settings.Setting<string>;
558
563
  private networkRequestToNode: WeakMap<SDK.NetworkRequest.NetworkRequest, NetworkRequestNode>;
559
564
 
565
+ static #allowedSchemes = new Set(['http:', 'https:', 'ws:', 'wss:', 'data:']);
566
+
560
567
  constructor(
561
568
  filterBar: UI.FilterBar.FilterBar, progressBarContainer: Element,
562
569
  networkLogLargeRowsSetting: Common.Settings.Setting<boolean>) {
@@ -2319,6 +2326,18 @@ export class NetworkLogView extends Common.ObjectWrapper.eventMixin<EventTypes,
2319
2326
  return requests.filter(request => !request.isBlobRequest());
2320
2327
  }
2321
2328
 
2329
+ static #getValidClipboardUrl(url: string): Platform.DevToolsPath.UrlString|null {
2330
+ try {
2331
+ const parsedUrl = new URL(url);
2332
+ if (!NetworkLogView.#allowedSchemes.has(parsedUrl.protocol)) {
2333
+ return null;
2334
+ }
2335
+ return url as Platform.DevToolsPath.UrlString;
2336
+ } catch {
2337
+ return null;
2338
+ }
2339
+ }
2340
+
2322
2341
  private async generateFetchCall(request: SDK.NetworkRequest.NetworkRequest, style: FetchStyle): Promise<string> {
2323
2342
  const ignoredHeaders = new Set<string>([
2324
2343
  // Internal headers
@@ -2355,7 +2374,11 @@ export class NetworkLogView extends Common.ObjectWrapper.eventMixin<EventTypes,
2355
2374
 
2356
2375
  const credentialHeaders = new Set<string>(['cookie', 'authorization']);
2357
2376
 
2358
- const url = JSON.stringify(request.url());
2377
+ const validUrl = NetworkLogView.#getValidClipboardUrl(request.url());
2378
+ if (!validUrl) {
2379
+ return i18nString(UIStrings.unsupportedUrlScheme, {PH1: '//'});
2380
+ }
2381
+ const url = JSON.stringify(validUrl);
2359
2382
 
2360
2383
  const requestHeaders = request.requestHeaders();
2361
2384
  const headerData: Headers = requestHeaders.reduce((result, header) => {
@@ -2507,11 +2530,11 @@ export class NetworkLogView extends Common.ObjectWrapper.eventMixin<EventTypes,
2507
2530
  // (it may be different from the inspected page platform).
2508
2531
  const escapeString = platform === 'win' ? escapeStringWin : escapeStringPosix;
2509
2532
 
2510
- // The shell escaping above protects the *shell* parser, but not curl's own
2511
- // argv parser: if the (HAR-imported) URL begins with '-', curl will parse
2512
- // it as an option (e.g. "-K//host/share/file" -> --config UNC path).
2513
- // Passing the URL via --url forces curl to treat it as a URL operand.
2514
- command.push('--url ' + escapeString(request.url()).replace(/[[{}\]]/g, '\\$&'));
2533
+ const validUrl = NetworkLogView.#getValidClipboardUrl(request.url());
2534
+ if (!validUrl) {
2535
+ return i18nString(UIStrings.unsupportedUrlScheme, {PH1: '#'});
2536
+ }
2537
+ command.push('--url ' + escapeString(validUrl).replace(/[[{}\]]/g, '\\$&'));
2515
2538
 
2516
2539
  let inferredMethod = 'GET';
2517
2540
  const data = [];
@@ -2617,7 +2640,11 @@ export class NetworkLogView extends Common.ObjectWrapper.eventMixin<EventTypes,
2617
2640
  return null;
2618
2641
  }
2619
2642
 
2620
- command.push('-Uri ' + escapeString(request.url()));
2643
+ const validUrl = NetworkLogView.#getValidClipboardUrl(request.url());
2644
+ if (!validUrl) {
2645
+ return i18nString(UIStrings.unsupportedUrlScheme, {PH1: '#'});
2646
+ }
2647
+ command.push('-Uri ' + escapeString(validUrl));
2621
2648
 
2622
2649
  if (request.requestMethod !== 'GET') {
2623
2650
  command.push('-Method ' + escapeString(request.requestMethod));
@@ -628,7 +628,6 @@ export class NodeFormatter implements Formatter {
628
628
  const target = heapProfilerModel ? heapProfilerModel.target() : null;
629
629
  const options = {
630
630
  className: 'profile-node-file',
631
- inlineFrameIndex: 0,
632
631
  };
633
632
  return this.profileView.linkifier().maybeLinkifyConsoleCallFrame(target, node.profileNode.callFrame, options);
634
633
  }
@@ -1467,7 +1467,6 @@ export class AllocationGridNode extends HeapSnapshotGridNode {
1467
1467
  String(allocationNode.scriptId) as Protocol.Runtime.ScriptId,
1468
1468
  allocationNode.scriptName as Platform.DevToolsPath.UrlString, allocationNode.line - 1, {
1469
1469
  columnNumber: allocationNode.column - 1,
1470
- inlineFrameIndex: 0,
1471
1470
  className: 'profile-node-file',
1472
1471
  });
1473
1472
  urlElement.style.maxWidth = '75%';
@@ -1949,7 +1949,7 @@ export class HeapAllocationStackView extends UI.Widget.Widget {
1949
1949
  continue;
1950
1950
  }
1951
1951
  const target = this.heapProfilerModel ? this.heapProfilerModel.target() : null;
1952
- const options = {columnNumber: frame.column - 1, inlineFrameIndex: 0};
1952
+ const options = {columnNumber: frame.column - 1};
1953
1953
  const urlElement = this.linkifier.linkifyScriptLocation(
1954
1954
  target, String(frame.scriptId) as Protocol.Runtime.ScriptId,
1955
1955
  frame.scriptName as Platform.DevToolsPath.UrlString, frame.line - 1, options);
@@ -346,7 +346,7 @@ export class SyncSection extends UI.Widget.Widget {
346
346
  // TODO: investigate if /advance link is alive
347
347
  const warningLink =
348
348
  this.#syncInfo.isSyncActive ? 'chrome://settings/syncSetup/advanced' : 'chrome://settings/syncSetup';
349
- UIHelpers.openInNewTab(warningLink);
349
+ UIHelpers.openInNewTab(warningLink, /* allowPrivileged=*/ true);
350
350
  event.consume();
351
351
  }
352
352
 
@@ -177,6 +177,7 @@ export class DevicesSettingsTab extends UI.Widget.VBox implements
177
177
  device.horizontal.height = 400;
178
178
  device.vertical.width = 400;
179
179
  device.vertical.height = 700;
180
+ device.userAgent = navigator.userAgent;
180
181
  this.#customDeviceList.addNewItem(this.emulatedDevicesList.custom().length, device);
181
182
  }
182
183
 
@@ -221,7 +221,7 @@ export class SourcesPanel extends UI.Panel.Panel implements
221
221
  #paused?: boolean;
222
222
  private switchToPausedTargetTimeout?: number;
223
223
  private executionLineLocation?: Bindings.DebuggerWorkspaceBinding.Location|null;
224
- private sidebarPaneStack?: UI.View.ViewLocation;
224
+ private sidebarPaneStack?: UI.ViewManager.StackLocation;
225
225
  private tabbedLocationHeader?: Element|null;
226
226
  private extensionSidebarPanesContainer?: UI.View.ViewLocation;
227
227
  sidebarPaneView?: UI.Widget.VBox|UI.SplitWidget.SplitWidget;
@@ -477,6 +477,7 @@ export class SourcesPanel extends UI.Panel.Panel implements
477
477
 
478
478
  toggleDebuggerSidebar(): void {
479
479
  this.splitWidget.toggleSidebar();
480
+ this.sidebarPaneStack?.notifyVisibilityChanged(this.splitWidget.sidebarIsShowing());
480
481
  }
481
482
 
482
483
  private debuggerPaused(event: Common.EventTarget.EventTargetEvent<SDK.DebuggerModel.DebuggerModel>): void {
@@ -69,9 +69,10 @@ export const SORT_ORDER_PAGE_LOAD_MARKERS: Readonly<Record<string, number>> = {
69
69
  [Trace.Types.Events.Name.SOFT_NAVIGATION_START]: 1,
70
70
  [Trace.Types.Events.Name.MARK_LOAD]: 2,
71
71
  [Trace.Types.Events.Name.MARK_FCP]: 3,
72
- [Trace.Types.Events.Name.MARK_DOM_CONTENT]: 4,
73
- [Trace.Types.Events.Name.MARK_LCP_CANDIDATE]: 5,
74
- [Trace.Types.Events.Name.MARK_LCP_CANDIDATE_FOR_SOFT_NAVIGATION]: 6,
72
+ [Trace.Types.Events.Name.MARK_SOFT_FCP]: 4,
73
+ [Trace.Types.Events.Name.MARK_DOM_CONTENT]: 5,
74
+ [Trace.Types.Events.Name.MARK_LCP_CANDIDATE]: 6,
75
+ [Trace.Types.Events.Name.MARK_LCP_CANDIDATE_FOR_SOFT_NAVIGATION]: 7,
75
76
  };
76
77
 
77
78
  // Threshold to match up overlay markers that are off by a tiny amount so they aren't rendered
@@ -676,7 +677,7 @@ export class TimelineFlameChartView extends Common.ObjectWrapper.eventMixin<Even
676
677
  event.name === Trace.Types.Events.Name.SOFT_NAVIGATION_START ||
677
678
  event.name === Trace.Types.Events.Name.MARK_LCP_CANDIDATE ||
678
679
  event.name === Trace.Types.Events.Name.MARK_LCP_CANDIDATE_FOR_SOFT_NAVIGATION ||
679
- event.name === Trace.Types.Events.Name.MARK_FCP ||
680
+ event.name === Trace.Types.Events.Name.MARK_FCP || event.name === Trace.Types.Events.Name.MARK_SOFT_FCP ||
680
681
  event.name === Trace.Types.Events.Name.MARK_DOM_CONTENT ||
681
682
  event.name === Trace.Types.Events.Name.MARK_LOAD);
682
683
 
@@ -2435,6 +2435,13 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
2435
2435
  async loadingStarted(): Promise<void> {
2436
2436
  this.#changeView({mode: 'STATUS_PANE_OVERLAY'});
2437
2437
 
2438
+ // If recording was stopped automatically (e.g. page reload or AI-triggered trace),
2439
+ // we must transition to STOP_PENDING so that loadingComplete() knows the resulting
2440
+ // trace is a fresh recording.
2441
+ if (this.state === State.RECORDING) {
2442
+ this.setState(State.STOP_PENDING);
2443
+ }
2444
+
2438
2445
  if (this.statusDialog) {
2439
2446
  this.statusDialog.remove();
2440
2447
  }
@@ -668,7 +668,6 @@ export class TimelineUIUtils {
668
668
  const options = {
669
669
  tabStop: true,
670
670
  showColumnNumber: false,
671
- inlineFrameIndex: 0,
672
671
  };
673
672
  details = LegacyComponents.Linkifier.Linkifier.linkifyURL(url, options);
674
673
  }
@@ -763,7 +762,6 @@ export class TimelineUIUtils {
763
762
  lineNumber,
764
763
  columnNumber,
765
764
  showColumnNumber: true,
766
- inlineFrameIndex: 0,
767
765
  className: 'timeline-details',
768
766
  tabStop: true,
769
767
  omitOrigin,
@@ -788,14 +786,13 @@ export class TimelineUIUtils {
788
786
  const options = {
789
787
  className: 'timeline-details',
790
788
  tabStop: true,
791
- inlineFrameIndex: 0,
792
789
  showColumnNumber: true,
793
790
  columnNumber: frame.columnNumber,
794
791
  lineNumber: frame.lineNumber,
795
792
  maxLength,
796
793
  };
797
794
  if (isFreshOrEnhanced) {
798
- return linkifier.maybeLinkifyConsoleCallFrame(target, frame, {showColumnNumber: true, inlineFrameIndex: 0});
795
+ return linkifier.maybeLinkifyConsoleCallFrame(target, frame, {showColumnNumber: true});
799
796
  }
800
797
  return LegacyComponents.Linkifier.Linkifier.linkifyURL(frame.url as Platform.DevToolsPath.UrlString, options);
801
798
  }
@@ -809,17 +806,21 @@ export class TimelineUIUtils {
809
806
  name = 'Largest Contentful Paint';
810
807
  break;
811
808
  case Trace.Types.Events.Name.MARK_LCP_CANDIDATE_FOR_SOFT_NAVIGATION:
812
- link = 'https://developer.chrome.com/docs/web-platform/soft-navigations-experiment';
809
+ link = 'https://developer.chrome.com/docs/web-platform/soft-navigations';
813
810
  name = 'Soft Largest Contentful Paint';
814
811
  break;
815
812
  case Trace.Types.Events.Name.SOFT_NAVIGATION_START:
816
- link = 'https://developer.chrome.com/docs/web-platform/soft-navigations-experiment';
813
+ link = 'https://developer.chrome.com/docs/web-platform/soft-navigations';
817
814
  name = 'Soft Navigations';
818
815
  break;
819
816
  case Trace.Types.Events.Name.MARK_FCP:
820
817
  link = 'https://web.dev/first-contentful-paint/';
821
818
  name = 'First Contentful Paint';
822
819
  break;
820
+ case Trace.Types.Events.Name.MARK_SOFT_FCP:
821
+ link = 'https://developer.chrome.com/docs/web-platform/soft-navigations';
822
+ name = 'Soft First Contentful Paint';
823
+ break;
823
824
  default:
824
825
  break;
825
826
  }
@@ -963,7 +964,7 @@ export class TimelineUIUtils {
963
964
 
964
965
  // Add timestamp to user timings, including custom extensibility markers
965
966
  if (Trace.Helpers.Trace.eventHasCategory(event, Trace.Types.Events.Categories.UserTiming) ||
966
- Trace.Types.Extensions.isSyntheticExtensionEntry(event)) {
967
+ Trace.Types.Extensions.isSyntheticExtensionEntry(event) || Trace.Types.Events.isSoftNavigationStart(event)) {
967
968
  const adjustedEventTimeStamp = timeStampForEventAdjustedForClosestNavigationIfPossible(
968
969
  event,
969
970
  parsedTrace,
@@ -1228,7 +1229,6 @@ export class TimelineUIUtils {
1228
1229
  const options = {
1229
1230
  tabStop: true,
1230
1231
  showColumnNumber: false,
1231
- inlineFrameIndex: 0,
1232
1232
  };
1233
1233
  contentHelper.appendElementRow(
1234
1234
  i18nString(UIStrings.imageUrl), LegacyComponents.Linkifier.Linkifier.linkifyURL(url, options));
@@ -1242,7 +1242,6 @@ export class TimelineUIUtils {
1242
1242
  const options = {
1243
1243
  tabStop: true,
1244
1244
  showColumnNumber: false,
1245
- inlineFrameIndex: 0,
1246
1245
  };
1247
1246
  contentHelper.appendElementRow(
1248
1247
  i18nString(UIStrings.stylesheetUrl), LegacyComponents.Linkifier.Linkifier.linkifyURL(url, options));
@@ -1444,6 +1443,7 @@ export class TimelineUIUtils {
1444
1443
 
1445
1444
  case Trace.Types.Events.Name.MARK_FIRST_PAINT:
1446
1445
  case Trace.Types.Events.Name.MARK_FCP:
1446
+ case Trace.Types.Events.Name.MARK_SOFT_FCP:
1447
1447
  case Trace.Types.Events.Name.MARK_LOAD:
1448
1448
  case Trace.Types.Events.Name.MARK_DOM_CONTENT: {
1449
1449
  const adjustedEventTimeStamp = timeStampForEventAdjustedForClosestNavigationIfPossible(
@@ -2074,7 +2074,7 @@ export class TimelineUIUtils {
2074
2074
  tall = true;
2075
2075
  break;
2076
2076
  case Trace.Types.Events.Name.SOFT_NAVIGATION_START:
2077
- color = 'var(--sys-color-blue)';
2077
+ color = 'var(--color-text-primary)';
2078
2078
  tall = true;
2079
2079
  break;
2080
2080
  case Trace.Types.Events.Name.FRAME_STARTED_LOADING:
@@ -2094,6 +2094,7 @@ export class TimelineUIUtils {
2094
2094
  tall = true;
2095
2095
  break;
2096
2096
  case Trace.Types.Events.Name.MARK_FCP:
2097
+ case Trace.Types.Events.Name.MARK_SOFT_FCP:
2097
2098
  color = 'var(--sys-color-green-bright)';
2098
2099
  tall = true;
2099
2100
  break;
@@ -2299,7 +2300,6 @@ export class TimelineDetailsContentHelper {
2299
2300
  tabStop: true,
2300
2301
  columnNumber: startColumn,
2301
2302
  showColumnNumber: true,
2302
- inlineFrameIndex: 0,
2303
2303
  text,
2304
2304
  omitOrigin,
2305
2305
  };
@@ -2316,8 +2316,7 @@ export class TimelineDetailsContentHelper {
2316
2316
  return;
2317
2317
  }
2318
2318
  const locationContent = document.createElement('span');
2319
- const link = this.#linkifier.maybeLinkifyScriptLocation(
2320
- this.target, null, url, startLine, {tabStop: true, inlineFrameIndex: 0});
2319
+ const link = this.#linkifier.maybeLinkifyScriptLocation(this.target, null, url, startLine, {tabStop: true});
2321
2320
  if (!link) {
2322
2321
  return;
2323
2322
  }
@@ -2407,7 +2406,7 @@ export function isMarkerEvent(parsedTrace: Trace.TraceModel.ParsedTrace, event:
2407
2406
  return true;
2408
2407
  }
2409
2408
 
2410
- if (Trace.Types.Events.isFirstContentfulPaint(event) || Trace.Types.Events.isFirstPaint(event)) {
2409
+ if (Trace.Types.Events.isAnyFirstContentfulPaint(event) || Trace.Types.Events.isFirstPaint(event)) {
2411
2410
  return event.args.frame === parsedTrace.data.Meta.mainFrameId;
2412
2411
  }
2413
2412
 
@@ -37,12 +37,14 @@ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
37
37
  */
38
38
  export const SORT_ORDER_PAGE_LOAD_MARKERS: Readonly<Record<string, number>> = {
39
39
  [Trace.Types.Events.Name.NAVIGATION_START]: 0,
40
- [Trace.Types.Events.Name.MARK_LOAD]: 1,
41
- [Trace.Types.Events.Name.MARK_FCP]: 2,
40
+ [Trace.Types.Events.Name.SOFT_NAVIGATION_START]: 1,
42
41
  [Trace.Types.Events.Name.MARK_FIRST_PAINT]: 2,
43
- [Trace.Types.Events.Name.MARK_DOM_CONTENT]: 3,
44
- [Trace.Types.Events.Name.MARK_LCP_CANDIDATE]: 4,
45
- [Trace.Types.Events.Name.MARK_LCP_CANDIDATE_FOR_SOFT_NAVIGATION]: 5,
42
+ [Trace.Types.Events.Name.MARK_FCP]: 3,
43
+ [Trace.Types.Events.Name.MARK_SOFT_FCP]: 4,
44
+ [Trace.Types.Events.Name.MARK_DOM_CONTENT]: 5,
45
+ [Trace.Types.Events.Name.MARK_LOAD]: 6,
46
+ [Trace.Types.Events.Name.MARK_LCP_CANDIDATE]: 7,
47
+ [Trace.Types.Events.Name.MARK_LCP_CANDIDATE_FOR_SOFT_NAVIGATION]: 8,
46
48
  };
47
49
 
48
50
  export class TimingsTrackAppender implements TrackAppender {
@@ -436,7 +436,6 @@ function linkifyURL(url: Platform.DevToolsPath.UrlString): HTMLElement {
436
436
  return LegacyComponents.Linkifier.Linkifier.linkifyURL(url, {
437
437
  tabStop: true,
438
438
  showColumnNumber: false,
439
- inlineFrameIndex: 0,
440
439
  maxLength: MAX_URL_LENGTH,
441
440
  });
442
441
  }
@@ -267,7 +267,6 @@ function renderURL(request: Trace.Types.Events.SyntheticNetworkRequest): Lit.Tem
267
267
  const options: LegacyComponents.Linkifier.LinkifyURLOptions = {
268
268
  tabStop: true,
269
269
  showColumnNumber: false,
270
- inlineFrameIndex: 0,
271
270
  maxLength: MAX_URL_LENGTH,
272
271
  };
273
272
  const linkifiedURL = LegacyComponents.Linkifier.Linkifier.linkifyURL(
@@ -439,7 +438,6 @@ function renderInitiatedBy(
439
438
  const options: LegacyComponents.Linkifier.LinkifyOptions = {
440
439
  tabStop: true,
441
440
  showColumnNumber: true,
442
- inlineFrameIndex: 0,
443
441
  };
444
442
  // If we have a stack trace, that is the most reliable way to get the initiator data and display a link to the source.
445
443
  if (hasStackTrace) {
@@ -53,7 +53,6 @@ export class ForcedReflow extends BaseInsightComponent<ForcedReflowInsightModel>
53
53
  callFrame.lineNumber, {
54
54
  columnNumber: callFrame.columnNumber,
55
55
  showColumnNumber: true,
56
- inlineFrameIndex: 0,
57
56
  tabStop: true,
58
57
  });
59
58
 
@@ -39,7 +39,6 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
39
39
  const options = {
40
40
  tabStop: true,
41
41
  showColumnNumber: false,
42
- inlineFrameIndex: 0,
43
42
  maxLength: MAX_URL_LENGTH,
44
43
  };
45
44
  const linkEl = LegacyComponents.Linkifier.Linkifier.linkifyURL(fallbackUrl, options);
@@ -1627,6 +1627,8 @@ export class Overlays extends EventTarget {
1627
1627
  markers: HTMLElement, marker: HTMLElement): void {
1628
1628
  if (Trace.Types.Events.isSoftNavigationStart(event)) {
1629
1629
  name = 'Soft Nav';
1630
+ } else if (Trace.Types.Events.isSoftFirstContentfulPaint(event)) {
1631
+ name = 'Soft FCP';
1630
1632
  } else if (Trace.Types.Events.isSoftLargestContentfulPaintCandidate(event)) {
1631
1633
  name = 'Soft LCP';
1632
1634
  }
@@ -1,7 +1,7 @@
1
1
  Name: Dependencies sourced from the upstream `chromium` repository
2
2
  URL: Internal
3
3
  Version: N/A
4
- Revision: e1605f15bac37245745e5fb8327995ededbe2337
4
+ Revision: db882e11eb73564831cdf0a63b661a81332df665
5
5
  Update Mechanism: Manual (https://crbug.com/428069060)
6
6
  License: BSD-3-Clause
7
7
  License File: LICENSE
@@ -57,15 +57,15 @@ import * as SDK from '../../core/sdk/sdk.js';
57
57
  * @throws TypeError if `url` is not a valid URL.
58
58
  * @see https://en.wikipedia.org/wiki/UTM_parameters
59
59
  */
60
- export function openInNewTab(url: URL|string): void {
60
+ export function openInNewTab(url: URL|string, allowPrivileged?: boolean): void {
61
61
  url = new URL(url);
62
62
  if (Common.ParsedURL.schemeIs(url, 'javascript:')) {
63
63
  return;
64
64
  }
65
65
 
66
66
  // Navigating to a chrome:// link via a normal anchor doesn't work, so we "navigate"
67
- // there using CDP.
68
- if (Common.ParsedURL.schemeIs(url, 'chrome:')) {
67
+ // there using CDP if explicitly requested.
68
+ if (allowPrivileged && Common.ParsedURL.schemeIs(url, 'chrome:')) {
69
69
  const rootTarget = SDK.TargetManager.TargetManager.instance().rootTarget();
70
70
  if (rootTarget === null) {
71
71
  return;
@@ -60,7 +60,7 @@ export class Link extends HTMLElement {
60
60
  return;
61
61
  }
62
62
 
63
- UIHelpers.openInNewTab(href);
63
+ UIHelpers.openInNewTab(href, this.allowPrivileged);
64
64
 
65
65
  event.consume();
66
66
  }
@@ -73,6 +73,18 @@ export class Link extends HTMLElement {
73
73
  this.setAttribute('href', href);
74
74
  }
75
75
 
76
+ get allowPrivileged(): boolean {
77
+ return this.hasAttribute('allow-privileged');
78
+ }
79
+
80
+ set allowPrivileged(allowPrivileged: boolean) {
81
+ if (allowPrivileged) {
82
+ this.setAttribute('allow-privileged', '');
83
+ } else {
84
+ this.removeAttribute('allow-privileged');
85
+ }
86
+ }
87
+
76
88
  get jslogContext(): string|null {
77
89
  return this.getAttribute('jslogcontext');
78
90
  }
@@ -98,7 +110,7 @@ export class Link extends HTMLElement {
98
110
  oldValue: string|null,
99
111
  newValue: string|null,
100
112
  ): void {
101
- if (oldValue !== newValue) {
113
+ if (oldValue === newValue) {
102
114
  return;
103
115
  }
104
116
  if (name === 'jslogcontext') {
@@ -145,9 +157,11 @@ export class Link extends HTMLElement {
145
157
  className?: string,
146
158
  jsLogContext?: string,
147
159
  tabindex = 0,
160
+ allowPrivileged = false,
148
161
  ): Link {
149
162
  const link = new Link();
150
163
  link.href = url as Platform.DevToolsPath.UrlString;
164
+ link.allowPrivileged = allowPrivileged;
151
165
  linkText = linkText ?? url;
152
166
  link.textContent = Platform.StringUtilities.trimMiddle(linkText, 150);
153
167