chrome-devtools-frontend 1.0.1558690 → 1.0.1561080

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 (167) hide show
  1. package/front_end/Images/src/container.svg +4 -0
  2. package/front_end/core/common/Gzip.ts +15 -0
  3. package/front_end/core/host/InspectorFrontendHostStub.ts +0 -3
  4. package/front_end/core/platform/ArrayUtilities.ts +13 -0
  5. package/front_end/core/root/Runtime.ts +0 -5
  6. package/front_end/core/sdk/CSSMetadata.ts +6 -6
  7. package/front_end/core/sdk/CSSModel.ts +2 -2
  8. package/front_end/core/sdk/DOMModel.ts +15 -3
  9. package/front_end/core/sdk/NetworkManager.ts +4 -0
  10. package/front_end/core/sdk/NetworkRequest.ts +9 -0
  11. package/front_end/core/sdk/OverlayModel.ts +20 -9
  12. package/front_end/entrypoints/main/MainImpl.ts +2 -1
  13. package/front_end/generated/InspectorBackendCommands.ts +6 -3
  14. package/front_end/generated/SupportedCSSProperties.js +64 -32
  15. package/front_end/generated/protocol-mapping.d.ts +16 -0
  16. package/front_end/generated/protocol-proxy-api.d.ts +12 -0
  17. package/front_end/generated/protocol.ts +38 -1
  18. package/front_end/models/ai_assistance/agents/StylingAgent.ts +1 -1
  19. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +11 -7
  20. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +23 -22
  21. package/front_end/models/badges/UserBadges.ts +48 -16
  22. package/front_end/models/greendev/Prototypes.ts +6 -1
  23. package/front_end/models/trace/LanternComputationData.ts +4 -3
  24. package/front_end/models/trace/Processor.ts +6 -5
  25. package/front_end/models/trace/Styles.ts +10 -1
  26. package/front_end/models/trace/extras/TraceTree.ts +1 -1
  27. package/front_end/models/trace/handlers/LargestImagePaintHandler.ts +2 -2
  28. package/front_end/models/trace/handlers/MetaHandler.ts +14 -0
  29. package/front_end/models/trace/handlers/PageLoadMetricsHandler.ts +59 -34
  30. package/front_end/models/trace/helpers/Timing.ts +8 -1
  31. package/front_end/models/trace/insights/Common.ts +1 -1
  32. package/front_end/models/trace/insights/LCPBreakdown.ts +4 -4
  33. package/front_end/models/trace/insights/LCPDiscovery.ts +3 -3
  34. package/front_end/models/trace/insights/RenderBlocking.ts +1 -1
  35. package/front_end/models/trace/insights/types.ts +1 -1
  36. package/front_end/models/trace/types/TraceEvents.ts +62 -10
  37. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +11 -142
  38. package/front_end/panels/ai_assistance/PatchWidget.ts +90 -72
  39. package/front_end/panels/ai_assistance/ai_assistance.ts +1 -0
  40. package/front_end/panels/ai_assistance/components/ChatInput.ts +701 -0
  41. package/front_end/panels/ai_assistance/components/ChatView.ts +71 -1268
  42. package/front_end/panels/ai_assistance/components/UserActionRow.ts +514 -31
  43. package/front_end/panels/ai_assistance/components/chatInput.css +387 -0
  44. package/front_end/panels/ai_assistance/components/chatView.css +38 -599
  45. package/front_end/panels/ai_assistance/components/userActionRow.css +230 -0
  46. package/front_end/panels/autofill/AutofillView.ts +2 -2
  47. package/front_end/panels/changes/ChangesView.ts +15 -1
  48. package/front_end/panels/changes/changesView.css +6 -0
  49. package/front_end/panels/common/AiCodeGenerationTeaser.ts +48 -12
  50. package/front_end/panels/common/BadgeNotification.ts +44 -58
  51. package/front_end/panels/common/CopyChangesToPrompt.ts +233 -0
  52. package/front_end/panels/common/aiCodeGenerationTeaser.css +14 -0
  53. package/front_end/panels/common/common.ts +2 -1
  54. package/front_end/panels/console/consoleView.css +1 -1
  55. package/front_end/panels/elements/CSSRuleValidator.ts +38 -0
  56. package/front_end/panels/elements/ElementsTreeElement.ts +222 -377
  57. package/front_end/panels/elements/ElementsTreeOutline.ts +0 -23
  58. package/front_end/panels/elements/ShortcutTreeElement.ts +57 -50
  59. package/front_end/panels/elements/StylePropertiesSection.ts +1 -3
  60. package/front_end/panels/elements/StylesSidebarPane.ts +15 -4
  61. package/front_end/panels/elements/components/AdornerManager.ts +5 -149
  62. package/front_end/panels/issues/HiddenIssuesRow.ts +1 -2
  63. package/front_end/panels/issues/IssueKindView.ts +2 -4
  64. package/front_end/panels/issues/IssueView.ts +2 -4
  65. package/front_end/panels/network/NetworkDataGridNode.ts +65 -1
  66. package/front_end/panels/network/NetworkLogView.ts +2 -4
  67. package/front_end/panels/network/NetworkLogViewColumns.ts +9 -0
  68. package/front_end/panels/screencast/ScreencastApp.ts +1 -0
  69. package/front_end/panels/settings/SettingsScreen.ts +3 -2
  70. package/front_end/panels/timeline/CompatibilityTracksAppender.ts +14 -1
  71. package/front_end/panels/timeline/StatusDialog.ts +4 -3
  72. package/front_end/panels/timeline/ThirdPartyTreeView.ts +1 -4
  73. package/front_end/panels/timeline/TimelineController.ts +185 -3
  74. package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +52 -25
  75. package/front_end/panels/timeline/TimelineFlameChartNetworkDataProvider.ts +3 -16
  76. package/front_end/panels/timeline/TimelineFlameChartView.ts +65 -21
  77. package/front_end/panels/timeline/TimelinePanel.ts +86 -126
  78. package/front_end/panels/timeline/TimelineTreeView.ts +1 -0
  79. package/front_end/panels/timeline/TimelineUIUtils.ts +28 -2
  80. package/front_end/panels/timeline/TimingsTrackAppender.ts +3 -1
  81. package/front_end/panels/timeline/components/SidebarSingleInsightSet.ts +1 -1
  82. package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +2 -2
  83. package/front_end/panels/timeline/components/insights/RenderBlocking.ts +6 -4
  84. package/front_end/panels/timeline/components/insights/Table.ts +3 -3
  85. package/front_end/panels/timeline/overlays/OverlaysImpl.ts +4 -0
  86. package/front_end/panels/timeline/timelinePanel.css +8 -1
  87. package/front_end/panels/timeline/utils/EntryNodes.ts +2 -1
  88. package/front_end/panels/whats_new/ReleaseNoteText.ts +15 -9
  89. package/front_end/panels/whats_new/resources/WNDT.md +6 -6
  90. package/front_end/third_party/chromium/README.chromium +1 -1
  91. package/front_end/third_party/codemirror.next/rebuild.sh +1 -1
  92. package/front_end/third_party/lit/rebuild.sh +1 -1
  93. package/front_end/third_party/puppeteer/README.chromium +2 -2
  94. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts +2 -3
  95. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts.map +1 -1
  96. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.js.map +1 -1
  97. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPRequest.d.ts.map +1 -1
  98. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPRequest.js +9 -0
  99. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPRequest.js.map +1 -1
  100. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPResponse.d.ts +3 -0
  101. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPResponse.d.ts.map +1 -1
  102. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPResponse.js +9 -0
  103. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPResponse.js.map +1 -1
  104. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Request.d.ts +3 -0
  105. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Request.d.ts.map +1 -1
  106. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Request.js +10 -0
  107. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Request.js.map +1 -1
  108. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.d.ts.map +1 -1
  109. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.js +8 -4
  110. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.js.map +1 -1
  111. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/injected.d.ts +1 -1
  112. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/injected.d.ts.map +1 -1
  113. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/injected.js +1 -1
  114. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/injected.js.map +1 -1
  115. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
  116. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +3 -3
  117. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +3 -3
  118. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js.map +1 -1
  119. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
  120. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.d.ts +1 -1
  121. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.js +1 -1
  122. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +10 -1
  123. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +13 -7
  124. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts +2 -3
  125. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts.map +1 -1
  126. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.js.map +1 -1
  127. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPRequest.d.ts.map +1 -1
  128. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPRequest.js +9 -0
  129. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPRequest.js.map +1 -1
  130. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPResponse.d.ts +3 -0
  131. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPResponse.d.ts.map +1 -1
  132. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPResponse.js +9 -0
  133. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPResponse.js.map +1 -1
  134. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/Request.d.ts +3 -0
  135. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/Request.d.ts.map +1 -1
  136. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/Request.js +10 -0
  137. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/Request.js.map +1 -1
  138. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.d.ts.map +1 -1
  139. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.js +8 -4
  140. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.js.map +1 -1
  141. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/injected.d.ts +1 -1
  142. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/injected.d.ts.map +1 -1
  143. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/injected.js +1 -1
  144. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/injected.js.map +1 -1
  145. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +3 -3
  146. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +3 -3
  147. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js.map +1 -1
  148. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.d.ts +1 -1
  149. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.js +1 -1
  150. package/front_end/third_party/puppeteer/package/lib/types.d.ts +10 -1
  151. package/front_end/third_party/puppeteer/package/package.json +3 -3
  152. package/front_end/third_party/puppeteer/package/src/api/Page.ts +2 -3
  153. package/front_end/third_party/puppeteer/package/src/bidi/HTTPRequest.ts +13 -0
  154. package/front_end/third_party/puppeteer/package/src/bidi/HTTPResponse.ts +10 -0
  155. package/front_end/third_party/puppeteer/package/src/bidi/core/Request.ts +15 -0
  156. package/front_end/third_party/puppeteer/package/src/cdp/Browser.ts +9 -4
  157. package/front_end/third_party/puppeteer/package/src/generated/injected.ts +1 -1
  158. package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
  159. package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
  160. package/front_end/ui/components/adorners/Adorner.ts +8 -68
  161. package/front_end/ui/components/text_editor/AiCodeGenerationProvider.ts +70 -28
  162. package/front_end/ui/legacy/SearchableView.ts +11 -5
  163. package/front_end/ui/legacy/SplitWidget.ts +1 -1
  164. package/front_end/ui/legacy/TabbedPane.ts +1 -1
  165. package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +43 -9
  166. package/front_end/ui/visual_logging/KnownContextValues.ts +16 -0
  167. package/package.json +2 -1
@@ -3351,6 +3351,15 @@ export namespace ProtocolMapping {
3351
3351
  paramsType: [Protocol.Network.EnableRequest?];
3352
3352
  returnType: void;
3353
3353
  };
3354
+ /**
3355
+ * Configures storing response bodies outside of renderer, so that these survive
3356
+ * a cross-process navigation.
3357
+ * If maxTotalBufferSize is not set, durable messages are disabled.
3358
+ */
3359
+ 'Network.configureDurableMessages': {
3360
+ paramsType: [Protocol.Network.ConfigureDurableMessagesRequest?];
3361
+ returnType: void;
3362
+ };
3354
3363
  /**
3355
3364
  * Returns all browser cookies. Depending on the backend support, will return detailed cookie
3356
3365
  * information in the `cookies` field.
@@ -4880,6 +4889,13 @@ export namespace ProtocolMapping {
4880
4889
  paramsType: [];
4881
4890
  returnType: Protocol.Tracing.GetCategoriesResponse;
4882
4891
  };
4892
+ /**
4893
+ * Return a descriptor for all available tracing categories.
4894
+ */
4895
+ 'Tracing.getTrackEventDescriptor': {
4896
+ paramsType: [];
4897
+ returnType: Protocol.Tracing.GetTrackEventDescriptorResponse;
4898
+ };
4883
4899
  /**
4884
4900
  * Record a clock sync marker in the trace.
4885
4901
  */
@@ -2538,6 +2538,13 @@ declare namespace ProtocolProxyApi {
2538
2538
  */
2539
2539
  invoke_enable(params: Protocol.Network.EnableRequest): Promise<Protocol.ProtocolResponseWithError>;
2540
2540
 
2541
+ /**
2542
+ * Configures storing response bodies outside of renderer, so that these survive
2543
+ * a cross-process navigation.
2544
+ * If maxTotalBufferSize is not set, durable messages are disabled.
2545
+ */
2546
+ invoke_configureDurableMessages(params: Protocol.Network.ConfigureDurableMessagesRequest): Promise<Protocol.ProtocolResponseWithError>;
2547
+
2541
2548
  /**
2542
2549
  * Returns all browser cookies. Depending on the backend support, will return detailed cookie
2543
2550
  * information in the `cookies` field.
@@ -4293,6 +4300,11 @@ declare namespace ProtocolProxyApi {
4293
4300
  */
4294
4301
  invoke_getCategories(): Promise<Protocol.Tracing.GetCategoriesResponse>;
4295
4302
 
4303
+ /**
4304
+ * Return a descriptor for all available tracing categories.
4305
+ */
4306
+ invoke_getTrackEventDescriptor(): Promise<Protocol.Tracing.GetTrackEventDescriptorResponse>;
4307
+
4296
4308
  /**
4297
4309
  * Record a clock sync marker in the trace.
4298
4310
  */
@@ -10001,6 +10001,17 @@ export namespace Network {
10001
10001
  VeryHigh = 'VeryHigh',
10002
10002
  }
10003
10003
 
10004
+ /**
10005
+ * The render blocking behavior of a resource request.
10006
+ */
10007
+ export const enum RenderBlockingBehavior {
10008
+ Blocking = 'Blocking',
10009
+ InBodyParserBlocking = 'InBodyParserBlocking',
10010
+ NonBlocking = 'NonBlocking',
10011
+ NonBlockingDynamic = 'NonBlockingDynamic',
10012
+ PotentiallyBlocking = 'PotentiallyBlocking',
10013
+ }
10014
+
10004
10015
  /**
10005
10016
  * Post data entry for HTTP request
10006
10017
  */
@@ -11571,11 +11582,24 @@ export namespace Network {
11571
11582
  /**
11572
11583
  * Enable storing response bodies outside of renderer, so that these survive
11573
11584
  * a cross-process navigation. Requires maxTotalBufferSize to be set.
11574
- * Currently defaults to false.
11585
+ * Currently defaults to false. This field is being deprecated in favor of the dedicated
11586
+ * configureDurableMessages command, due to the possibility of deadlocks when awaiting
11587
+ * Network.enable before issuing Runtime.runIfWaitingForDebugger.
11575
11588
  */
11576
11589
  enableDurableMessages?: boolean;
11577
11590
  }
11578
11591
 
11592
+ export interface ConfigureDurableMessagesRequest {
11593
+ /**
11594
+ * Buffer size in bytes to use when preserving network payloads (XHRs, etc).
11595
+ */
11596
+ maxTotalBufferSize?: integer;
11597
+ /**
11598
+ * Per-resource buffer size in bytes to use when preserving network payloads (XHRs, etc).
11599
+ */
11600
+ maxResourceBufferSize?: integer;
11601
+ }
11602
+
11579
11603
  export interface GetAllCookiesResponse extends ProtocolResponseWithError {
11580
11604
  /**
11581
11605
  * Array of cookie objects.
@@ -12143,6 +12167,10 @@ export namespace Network {
12143
12167
  * Whether the request is initiated by a user gesture. Defaults to false.
12144
12168
  */
12145
12169
  hasUserGesture?: boolean;
12170
+ /**
12171
+ * The render blocking behavior of the request.
12172
+ */
12173
+ renderBlockingBehavior?: RenderBlockingBehavior;
12146
12174
  }
12147
12175
 
12148
12176
  /**
@@ -13738,7 +13766,9 @@ export namespace Page {
13738
13766
  LanguageDetector = 'language-detector',
13739
13767
  LanguageModel = 'language-model',
13740
13768
  LocalFonts = 'local-fonts',
13769
+ LocalNetwork = 'local-network',
13741
13770
  LocalNetworkAccess = 'local-network-access',
13771
+ LoopbackNetwork = 'loopback-network',
13742
13772
  Magnetometer = 'magnetometer',
13743
13773
  ManualText = 'manual-text',
13744
13774
  MediaPlaybackWhileNotVisible = 'media-playback-while-not-visible',
@@ -18826,6 +18856,13 @@ export namespace Tracing {
18826
18856
  categories: string[];
18827
18857
  }
18828
18858
 
18859
+ export interface GetTrackEventDescriptorResponse extends ProtocolResponseWithError {
18860
+ /**
18861
+ * Base64-encoded serialized perfetto.protos.TrackEventDescriptor protobuf message.
18862
+ */
18863
+ descriptor: binary;
18864
+ }
18865
+
18829
18866
  export interface RecordClockSyncMarkerRequest {
18830
18867
  /**
18831
18868
  * The ID of this clock sync marker
@@ -219,7 +219,7 @@ export class NodeContext extends ConversationContext<SDK.DOMModel.DOMNode> {
219
219
  {title: 'Why does this element scroll?', jslogContext: 'scroll-why'},
220
220
  ];
221
221
  }
222
- if (layoutProps.isContainer) {
222
+ if (layoutProps.containerType) {
223
223
  return [
224
224
  {title: 'What are container queries?', jslogContext: 'container-what'},
225
225
  {title: 'How do I use container-type?', jslogContext: 'container-how'},
@@ -13,12 +13,13 @@ import {bytes, millis} from './UnitFormatters.js';
13
13
  /**
14
14
  * For a given frame ID and navigation ID, returns the LCP Event and the LCP Request, if the resource was an image.
15
15
  */
16
- function getLCPData(parsedTrace: Trace.TraceModel.ParsedTrace, frameId: string, navigationId: string): {
16
+ function getLCPData(
17
+ parsedTrace: Trace.TraceModel.ParsedTrace, frameId: string, navigation: Trace.Types.Events.NavigationStart): {
17
18
  lcpEvent: Trace.Types.Events.LargestContentfulPaintCandidate,
18
19
  metricScore: Trace.Handlers.ModelHandlers.PageLoadMetrics.LCPMetricScore,
19
20
  lcpRequest?: Trace.Types.Events.SyntheticNetworkRequest,
20
21
  }|null {
21
- const navMetrics = parsedTrace.data.PageLoadMetrics.metricScoresByFrameId.get(frameId)?.get(navigationId);
22
+ const navMetrics = parsedTrace.data.PageLoadMetrics.metricScoresByFrameId.get(frameId)?.get(navigation);
22
23
  if (!navMetrics) {
23
24
  return null;
24
25
  }
@@ -28,13 +29,16 @@ function getLCPData(parsedTrace: Trace.TraceModel.ParsedTrace, frameId: string,
28
29
  return null;
29
30
  }
30
31
  const lcpEvent = metric?.event;
31
- if (!lcpEvent || !Trace.Types.Events.isLargestContentfulPaintCandidate(lcpEvent)) {
32
+ if (!lcpEvent || !Trace.Types.Events.isAnyLargestContentfulPaintCandidate(lcpEvent)) {
32
33
  return null;
33
34
  }
34
35
 
36
+ const navigationId = navigation.args.data?.navigationId;
37
+
35
38
  return {
36
39
  lcpEvent,
37
- lcpRequest: parsedTrace.data.LargestImagePaint.lcpRequestByNavigationId.get(navigationId),
40
+ lcpRequest: navigationId ? parsedTrace.data.LargestImagePaint.lcpRequestByNavigationId.get(navigationId) :
41
+ undefined,
38
42
  metricScore: metric,
39
43
  };
40
44
  }
@@ -89,15 +93,15 @@ export class PerformanceInsightFormatter {
89
93
  * Information about LCP which we pass to the LLM for all insights that relate to LCP.
90
94
  */
91
95
  #lcpMetricSharedContext(): string {
92
- if (!this.#insight.navigationId) {
96
+ if (!this.#insight.navigation) {
93
97
  // No navigation ID = no LCP.
94
98
  return '';
95
99
  }
96
- if (!this.#insight.frameId || !this.#insight.navigationId) {
100
+ if (!this.#insight.frameId || !this.#insight.navigation) {
97
101
  return '';
98
102
  }
99
103
 
100
- const data = getLCPData(this.#parsedTrace, this.#insight.frameId, this.#insight.navigationId);
104
+ const data = getLCPData(this.#parsedTrace, this.#insight.frameId, this.#insight.navigation);
101
105
  if (!data) {
102
106
  return '';
103
107
  }
@@ -374,17 +374,17 @@ This is the bottom-up summary for the entire trace. Only the top 20 activities (
374
374
  - self: 29 ms, total: 32 ms, source: clearTimeout
375
375
  - self: 27 ms, total: 50 ms, source: Parse HTML
376
376
  - self: 18 ms, total: 19 ms, source: aC (url: https://s.yimg.com/aaq/f10d509c/d1irmdsmbztlvx.js, line: 0, column: 19068)
377
- - self: 18 ms, total: 186 ms, source: (anonymous) (url: https://s.yimg.com/aaq/prebid/prebid-2.0.js, line: 5, column: 1)
378
377
  - self: 16 ms, total: 226 ms, source: Function call
379
- - self: 12 ms, total: 163 ms, source: (anonymous) (url: https://s.yimg.com/aaq/f10d509c/d1irmdsmbztlvx.js, line: 0, column: 0)
380
- - self: 12 ms, total: 83 ms, source: (anonymous) (url: https://cdn.taboola.com/libtrc/yahooweb-network/loader.js, line: 0, column: 9)
381
378
  - self: 11 ms, total: 12 ms, source: fetch
382
379
  - self: 11 ms, total: 12 ms, source: evaluate
383
380
  - self: 10 ms, total: 212 ms, source: Run microtasks
384
- - self: 9 ms, total: 19 ms, source: (anonymous) (url: https://s.yimg.com/du/ay/wnsrvbjmeprtfrnfx.js, line: 0, column: 0)
385
381
  - self: 9 ms, total: 10 ms, source: Minor GC
386
382
  - self: 8 ms, total: 226 ms, source: Evaluate script
387
- - self: 7 ms, total: 109 ms, source: n (url: https://s.yimg.com/aaq/prebid/prebid-2.0.js, line: 11, column: 4263)
383
+ - self: 7 ms, total: 7 ms, source: (anonymous) (url: https://s.yimg.com/du/ay/wnsrvbjmeprtfrnfx.js, line: 111, column: 4705)
384
+ - self: 7 ms, total: 9 ms, source: appendChild
385
+ - self: 6 ms, total: 8 ms, source: Ei (url: https://s.yimg.com/aaq/benji/benji-2.2.99.js, line: 0, column: 24493)
386
+ - self: 6 ms, total: 6 ms, source: Il (url: https://securepubads.g.doubleclick.net/pagead/managed/js/gpt/m202503250101/pubads_impl.js, line: 32, column: 58003)
387
+ - self: 5 ms, total: 7 ms, source: n (url: https://s.yimg.com/aaq/prebid/prebid-2.0.js, line: 11, column: 3881)
388
388
 
389
389
  # Third parties
390
390
 
@@ -970,28 +970,29 @@ Content:
970
970
  4;p-73704-775-2074-419;(anonymous);7.2;0.1;0;5;0;9
971
971
  5;p-73704-775-2075-420;(anonymous);7.1;;0;6;0;200
972
972
  6;p-73704-775-2075-421;(anonymous);7.1;2.6;0;7;0;231
973
- 7;p-73704-775-2095-422;(anonymous);4.5;1.3;0;8-19;0;292
974
- 8;p-73704-775-2095-423;(anonymous);0.5;0.1;0;19-21;0;756
973
+ 7;p-73704-775-2095-422;(anonymous);4.5;1.3;0;8-20;0;292
974
+ 8;p-73704-775-2095-423;(anonymous);0.1;0.1;0;;0;756
975
975
  9;p-73704-775-2097-424;Et;0.1;0.1;0;;0;10766
976
- 10;p-73704-775-2098-425;St;0.4;0.2;0;21;0;10904
976
+ 10;p-73704-775-2098-425;St;0.4;0.2;0;20;0;10904
977
977
  11;p-73704-775-2105-427;k;0.4;0.4;0;;0;5125
978
- 12;p-73704-775-2108-428;Go;0.1;;0;22;0;68523
979
- 13;p-73704-775-2109-430;Oi;0.4;0.2;0;23;0;38264
978
+ 12;p-73704-775-2108-428;Go;0.1;;0;21;0;68523
979
+ 13;p-73704-775-2109-430;Oi;0.4;0.2;0;22;0;38264
980
980
  14;p-73704-775-2115-432;tl;0.3;0.3;0;;0;154217
981
- 15;p-73704-775-2118-433;ul;0.6;0.5;0;24;0;155034
981
+ 15;p-73704-775-2118-433;ul;0.6;0.5;0;23;0;155034
982
982
  16;p-73704-775-2121-435;cl;0.1;0.1;0;;0;155107
983
- 17;p-73704-775-2123-436;hl;0.1;;0;25;0;155309
983
+ 17;p-73704-775-2123-436;hl;0.1;;0;24;0;155309
984
984
  18;p-73704-775-2124-439;sl;0.1;0.1;0;;0;154927
985
- 19;p-73704-775-2127-441;hl;0.1;0.1;0;;0;155309
986
- 20;p-73704-775-2128-442;registerService;0.2;;1;26-28;0;9441
987
- 21;p-73704-775-2099-426;vt;0.2;0.2;0;;0;10155
988
- 22;p-73704-775-2108-429;Mo;0.1;0.1;0;;0;66493
989
- 23;p-73704-775-2111-431;vi;0.1;0.1;0;;0;37138
990
- 24;p-73704-775-2118-434;ll;0.1;0.1;0;;0;155345
991
- 25;p-73704-775-2123-437;ll;0.1;;0;28;0;155345
992
- 26;p-73704-775-2128-443;u;0.1;0.1;1;;0;10091
993
- 27;p-73704-775-2129-444;d;0.1;0.1;1;;0;595
994
- 28;p-73704-775-2123-438;get prototype;0.1;0.1;;;;
985
+ 19;p-73704-775-2127-440;(anonymous);0.3;;0;25-27;0;161805
986
+ 20;p-73704-775-2099-426;vt;0.2;0.2;0;;0;10155
987
+ 21;p-73704-775-2108-429;Mo;0.1;0.1;0;;0;66493
988
+ 22;p-73704-775-2111-431;vi;0.1;0.1;0;;0;37138
989
+ 23;p-73704-775-2118-434;ll;0.1;0.1;0;;0;155345
990
+ 24;p-73704-775-2123-437;ll;0.1;;0;27;0;155345
991
+ 25;p-73704-775-2127-441;hl;0.1;0.1;0;;0;155309
992
+ 26;p-73704-775-2128-442;registerService;0.2;;1;28-30;0;9441
993
+ 27;p-73704-775-2123-438;get prototype;0.1;0.1;;;;
994
+ 28;p-73704-775-2128-443;u;0.1;0.1;1;;0;10091
995
+ 29;p-73704-775-2129-444;d;0.1;0.1;1;;0;595
995
996
 
996
997
  IMPORTANT: Never show eventKey to the user.
997
998
 
@@ -14,12 +14,18 @@ import {StarterBadge} from './StarterBadge.js';
14
14
 
15
15
  type BadgeClass = new (badgeContext: BadgeContext) => Badge;
16
16
 
17
+ export const enum BadgeTriggerReason {
18
+ AWARD = 'Award',
19
+ STARTER_BADGE_SETTINGS_NUDGE = 'StarterBadgeSettingsNudge',
20
+ STARTER_BADGE_PROFILE_NUDGE = 'StarterBadgeProfileNudge',
21
+ }
22
+
17
23
  export const enum Events {
18
24
  BADGE_TRIGGERED = 'BadgeTriggered',
19
25
  }
20
26
 
21
27
  export interface EventTypes {
22
- [Events.BADGE_TRIGGERED]: Badge;
28
+ [Events.BADGE_TRIGGERED]: {badge: Badge, reason: BadgeTriggerReason};
23
29
  }
24
30
 
25
31
  const SNOOZE_TIME_MS = 24 * 60 * 60 * 1000; // 24 hours
@@ -97,24 +103,50 @@ export class UserBadges extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
97
103
  this.#badgeActionEventTarget.dispatchEventToListeners(action);
98
104
  }
99
105
 
106
+ async #resolveBadgeTriggerReason(badge: Badge): Promise<BadgeTriggerReason|undefined> {
107
+ if (!badge.isStarterBadge) {
108
+ return BadgeTriggerReason.AWARD;
109
+ }
110
+
111
+ const getProfileResponse = await Host.GdpClient.GdpClient.instance().getProfile();
112
+ // The `getProfile` call failed and returned a `null`.
113
+ // For that case, we don't show anything.
114
+ if (!getProfileResponse) {
115
+ return;
116
+ }
117
+
118
+ const hasGdpProfile = Boolean(getProfileResponse.profile);
119
+ const receiveBadgesSettingEnabled = Boolean(this.#receiveBadgesSetting.get());
120
+
121
+ // If the user already has a GDP profile and the receive badges setting enabled,
122
+ // starter badge behaves as if it's an activity based badge.
123
+ if (hasGdpProfile && receiveBadgesSettingEnabled) {
124
+ return BadgeTriggerReason.AWARD;
125
+ }
126
+
127
+ if (this.#isStarterBadgeDismissed() || this.#isStarterBadgeSnoozed()) {
128
+ return;
129
+ }
130
+
131
+ // If the user already has a GDP profile and the receive badges setting disabled,
132
+ // starter badge behaves as a nudge for opting into receiving badges.
133
+ if (hasGdpProfile && !receiveBadgesSettingEnabled) {
134
+ return BadgeTriggerReason.STARTER_BADGE_SETTINGS_NUDGE;
135
+ }
136
+
137
+ // The user does not have a GDP profile, starter badge acts as a nudge for creating a GDP profile.
138
+ return BadgeTriggerReason.STARTER_BADGE_PROFILE_NUDGE;
139
+ }
140
+
100
141
  async #onTriggerBadge(badge: Badge, opts?: TriggerOptions): Promise<void> {
101
142
  const triggerTime = Date.now();
102
- let shouldAwardBadge = false;
103
- // By default, we award non-starter badges directly when they are triggered.
104
- if (!badge.isStarterBadge) {
105
- shouldAwardBadge = true;
106
- } else {
107
- const getProfileResponse = await Host.GdpClient.GdpClient.instance().getProfile();
108
- const receiveBadgesSettingEnabled = Boolean(this.#receiveBadgesSetting.get());
109
- // If there is a GDP profile and the user has enabled receiving badges, we award the starter badge as well.
110
- if (getProfileResponse?.profile && receiveBadgesSettingEnabled && !this.#isStarterBadgeDismissed() &&
111
- !this.#isStarterBadgeSnoozed()) {
112
- shouldAwardBadge = true;
113
- }
143
+ const reason = await this.#resolveBadgeTriggerReason(badge);
144
+
145
+ if (!reason) {
146
+ return;
114
147
  }
115
148
 
116
- // Awarding was needed and not successful, we don't show the notification
117
- if (shouldAwardBadge) {
149
+ if (reason === BadgeTriggerReason.AWARD) {
118
150
  const result = await Host.GdpClient.GdpClient.instance().createAward({name: badge.name});
119
151
  if (!result) {
120
152
  return;
@@ -125,7 +157,7 @@ export class UserBadges extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
125
157
  // We want to add exactly 1.5 second delay between the trigger action & the notification.
126
158
  const delay = opts?.immediate ? 0 : Math.max(DELAY_BEFORE_TRIGGER - timeElapsedAfterTriggerCall, 0);
127
159
  setTimeout(() => {
128
- this.dispatchEventToListeners(Events.BADGE_TRIGGERED, badge);
160
+ this.dispatchEventToListeners(Events.BADGE_TRIGGERED, {badge, reason});
129
161
  }, delay);
130
162
  }
131
163
 
@@ -12,6 +12,7 @@ export interface GreenDevSettings {
12
12
  inlineWidgets: Common.Settings.Setting<boolean>;
13
13
  artifactViewer: Common.Settings.Setting<boolean>;
14
14
  aiAnnotations: Common.Settings.Setting<boolean>;
15
+ copyToGemini: Common.Settings.Setting<boolean>;
15
16
  }
16
17
 
17
18
  export class Prototypes {
@@ -51,6 +52,10 @@ export class Prototypes {
51
52
 
52
53
  const artifactViewer =
53
54
  settings.createSetting('greendev-artifact-viewer-enabled', false, Common.Settings.SettingStorageType.LOCAL);
54
- return {inDevToolsFloaty, inlineWidgets, aiAnnotations, artifactViewer};
55
+
56
+ const copyToGemini =
57
+ settings.createSetting('greendev-copy-to-gemini-enabled', false, Common.Settings.SettingStorageType.LOCAL);
58
+
59
+ return {inDevToolsFloaty, inlineWidgets, aiAnnotations, artifactViewer, copyToGemini};
55
60
  }
56
61
  }
@@ -10,14 +10,15 @@ import type * as Types from './types/types.js';
10
10
 
11
11
  type NetworkRequest = Lantern.Types.NetworkRequest<Types.Events.SyntheticNetworkRequest>;
12
12
 
13
- function createProcessedNavigation(data: Handlers.Types.HandlerData, frameId: string, navigationId: string):
14
- Lantern.Types.Simulation.ProcessedNavigation {
13
+ function createProcessedNavigation(
14
+ data: Handlers.Types.HandlerData, frameId: string,
15
+ navigation: Types.Events.NavigationStart): Lantern.Types.Simulation.ProcessedNavigation {
15
16
  const scoresByNav = data.PageLoadMetrics.metricScoresByFrameId.get(frameId);
16
17
  if (!scoresByNav) {
17
18
  throw new Lantern.Core.LanternError('missing metric scores for frame');
18
19
  }
19
20
 
20
- const scores = scoresByNav.get(navigationId);
21
+ const scores = scoresByNav.get(navigation);
21
22
  if (!scores) {
22
23
  throw new Lantern.Core.LanternError('missing metric scores for specified navigation');
23
24
  }
@@ -268,7 +268,8 @@ export class TraceProcessor extends EventTarget {
268
268
 
269
269
  #createLanternContext(
270
270
  data: Handlers.Types.HandlerData, traceEvents: readonly Types.Events.Event[], frameId: string,
271
- navigationId: string, options: Types.Configuration.ParseOptions): Insights.Types.LanternContext|undefined {
271
+ navigation: Types.Events.NavigationStart,
272
+ options: Types.Configuration.ParseOptions): Insights.Types.LanternContext|undefined {
272
273
  // Check for required handlers.
273
274
  if (!data.NetworkRequests || !data.Workers || !data.PageLoadMetrics) {
274
275
  return;
@@ -278,7 +279,7 @@ export class TraceProcessor extends EventTarget {
278
279
  }
279
280
 
280
281
  const navStarts = data.Meta.navigationsByFrameId.get(frameId);
281
- const navStartIndex = navStarts?.findIndex(n => n.args.data?.navigationId === navigationId);
282
+ const navStartIndex = navStarts?.findIndex(n => n === navigation);
282
283
  if (!navStarts || navStartIndex === undefined || navStartIndex === -1) {
283
284
  throw new Lantern.Core.LanternError('Could not find navigation start');
284
285
  }
@@ -295,7 +296,7 @@ export class TraceProcessor extends EventTarget {
295
296
 
296
297
  const requests = LanternComputationData.createNetworkRequests(trace, data, startTime, endTime);
297
298
  const graph = LanternComputationData.createGraph(requests, trace, data);
298
- const processedNavigation = LanternComputationData.createProcessedNavigation(data, frameId, navigationId);
299
+ const processedNavigation = LanternComputationData.createProcessedNavigation(data, frameId, navigation);
299
300
 
300
301
  const networkAnalysis = Lantern.Core.NetworkAnalyzer.analyze(requests);
301
302
  if (!networkAnalysis) {
@@ -455,7 +456,7 @@ export class TraceProcessor extends EventTarget {
455
456
  model.frameId = context.frameId;
456
457
  const navId = context.navigation?.args.data?.navigationId;
457
458
  if (navId) {
458
- model.navigationId = navId;
459
+ model.navigation = context.navigation;
459
460
  }
460
461
  model.createOverlays = () => {
461
462
  // @ts-expect-error: model is a union of all possible insight model types.
@@ -571,7 +572,7 @@ export class TraceProcessor extends EventTarget {
571
572
  let lantern: Insights.Types.LanternContext|undefined;
572
573
  try {
573
574
  options.logger?.start('insights:createLanternContext');
574
- lantern = this.#createLanternContext(data, traceEvents, frameId, navigationId, options);
575
+ lantern = this.#createLanternContext(data, traceEvents, frameId, navigation, options);
575
576
  } catch (e) {
576
577
  // Handle Lantern errors gracefully
577
578
  // Don't allow an error in constructing the Lantern graphs to break the rest of the trace processor.
@@ -879,6 +879,11 @@ export function maybeInitSylesMap(): EventStylesMap {
879
879
  defaultCategoryStyles.rendering,
880
880
  true,
881
881
  ),
882
+ [Types.Events.Name.MARK_LCP_CANDIDATE_FOR_SOFT_NAVIGATION]: new TimelineRecordStyle(
883
+ i18nString(UIStrings.largestContentfulPaint),
884
+ defaultCategoryStyles.rendering,
885
+ true,
886
+ ),
882
887
 
883
888
  [Types.Events.Name.TIME_STAMP]:
884
889
  new TimelineRecordStyle(i18nString(UIStrings.timestamp), defaultCategoryStyles.scripting),
@@ -1118,7 +1123,7 @@ export function markerDetailsForEvent(event: Types.Events.Event): {
1118
1123
  color = 'var(--sys-color-green-bright)';
1119
1124
  title = Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP;
1120
1125
  }
1121
- if (Types.Events.isLargestContentfulPaintCandidate(event)) {
1126
+ if (Types.Events.isAnyLargestContentfulPaintCandidate(event)) {
1122
1127
  color = 'var(--sys-color-green)';
1123
1128
  title = Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP;
1124
1129
  }
@@ -1126,6 +1131,10 @@ export function markerDetailsForEvent(event: Types.Events.Event): {
1126
1131
  color = 'var(--color-text-primary)';
1127
1132
  title = Handlers.ModelHandlers.PageLoadMetrics.MetricName.NAV;
1128
1133
  }
1134
+ if (Types.Events.isSoftNavigationStart(event)) {
1135
+ color = 'var(--sys-color-blue)';
1136
+ title = Handlers.ModelHandlers.PageLoadMetrics.MetricName.SOFT_NAV;
1137
+ }
1129
1138
  if (Types.Events.isMarkDOMContent(event)) {
1130
1139
  color = 'var(--color-text-disabled)';
1131
1140
  title = Handlers.ModelHandlers.PageLoadMetrics.MetricName.DCL;
@@ -687,7 +687,7 @@ export function generateEventID(event: Types.Events.Event): string {
687
687
  SamplesIntegrator.nativeGroup(event.callFrame.functionName) :
688
688
  event.callFrame.functionName;
689
689
  const location = event.callFrame.scriptId || event.callFrame.url || '';
690
- return `f:${name}@${location}`;
690
+ return `f:${name}@${location}:${event.callFrame.lineNumber}:${event.callFrame.columnNumber}`;
691
691
  }
692
692
 
693
693
  if (Types.Events.isConsoleTimeStamp(event) && event.args.data) {
@@ -55,9 +55,9 @@ export async function finalize(): Promise<void> {
55
55
  const metricScoresByFrameId = pageLoadMetricsData().metricScoresByFrameId;
56
56
 
57
57
  for (const [navigationId, navigation] of navigationsByNavigationId) {
58
- const lcpMetric = metricScoresByFrameId.get(navigation.args.frame)?.get(navigationId)?.get(MetricName.LCP);
58
+ const lcpMetric = metricScoresByFrameId.get(navigation.args.frame)?.get(navigation)?.get(MetricName.LCP);
59
59
  const lcpEvent = lcpMetric?.event;
60
- if (!lcpEvent || !Types.Events.isLargestContentfulPaintCandidate(lcpEvent)) {
60
+ if (!lcpEvent || !Types.Events.isAnyLargestContentfulPaintCandidate(lcpEvent)) {
61
61
  continue;
62
62
  }
63
63
 
@@ -59,6 +59,7 @@ let traceBounds: Types.Timing.TraceWindowMicro = makeNewTraceBounds();
59
59
  */
60
60
  let navigationsByFrameId = new Map<string, Types.Events.NavigationStart[]>();
61
61
  let navigationsByNavigationId = new Map<string, Types.Events.NavigationStart>();
62
+ let softNavigationsById = new Map<number, Types.Events.SoftNavigationStart>();
62
63
  let finalDisplayUrlByNavigationId = new Map<string, string>();
63
64
  let mainFrameNavigations: Types.Events.NavigationStart[] = [];
64
65
 
@@ -92,6 +93,7 @@ const CHROME_WEB_TRACE_EVENTS = new Set([
92
93
  export function reset(): void {
93
94
  navigationsByFrameId = new Map();
94
95
  navigationsByNavigationId = new Map();
96
+ softNavigationsById = new Map();
95
97
  finalDisplayUrlByNavigationId = new Map();
96
98
  processNames = new Map();
97
99
  mainFrameNavigations = [];
@@ -324,6 +326,10 @@ export function handleEvent(event: Types.Events.Event): void {
324
326
  return;
325
327
  }
326
328
 
329
+ if (Types.Events.isSoftNavigationStart(event)) {
330
+ softNavigationsById.set(event.args.context.performanceTimelineNavigationId, event);
331
+ }
332
+
327
333
  // Update `finalDisplayUrlByNavigationId` to reflect the latest redirect for each navigation.
328
334
  if (Types.Events.isResourceSendRequest(event)) {
329
335
  if (event.args.data.resourceType !== 'Document') {
@@ -445,7 +451,14 @@ export interface MetaHandlerData {
445
451
  browserThreadId: Types.Events.ThreadID;
446
452
  gpuProcessId: Types.Events.ProcessID;
447
453
  navigationsByFrameId: Map<string, Types.Events.NavigationStart[]>;
454
+ /**
455
+ * This does not include soft navigations.
456
+ *
457
+ * TODO(crbug.com/414468047): include soft navs here, so that
458
+ * PageLoadMetricsHandler and insights can use this map for all navigation types.
459
+ */
448
460
  navigationsByNavigationId: Map<string, Types.Events.NavigationStart>;
461
+ softNavigationsById: Map<number, Types.Events.SoftNavigationStart>;
449
462
  /**
450
463
  * The user-visible URL displayed to users in the address bar.
451
464
  * This captures:
@@ -514,6 +527,7 @@ export function data(): MetaHandlerData {
514
527
  mainFrameURL,
515
528
  navigationsByFrameId,
516
529
  navigationsByNavigationId,
530
+ softNavigationsById,
517
531
  finalDisplayUrlByNavigationId,
518
532
  threadsInProcess,
519
533
  rendererProcessesByFrame: rendererProcessesByFrameId,