chrome-devtools-frontend 1.0.1518653 → 1.0.1520139

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 (143) hide show
  1. package/config/owner/COMMON_OWNERS +1 -2
  2. package/config/typescript/tsconfig.eslint.json +12 -1
  3. package/docs/ui_engineering.md +1011 -0
  4. package/eslint.config.mjs +1 -0
  5. package/front_end/core/host/GdpClient.ts +12 -3
  6. package/front_end/core/sdk/EnhancedTracesParser.ts +5 -5
  7. package/front_end/core/sdk/NetworkManager.ts +1 -0
  8. package/front_end/core/sdk/NetworkRequest.ts +10 -0
  9. package/front_end/core/sdk/RehydratingConnection.snapshot.txt +211 -0
  10. package/front_end/core/sdk/TargetManager.ts +4 -0
  11. package/front_end/entrypoints/main/MainImpl.ts +6 -1
  12. package/front_end/entrypoints/main/main-meta.ts +3 -3
  13. package/front_end/generated/SupportedCSSProperties.js +19 -4
  14. package/front_end/models/ai_assistance/agents/AiAgent.ts +57 -10
  15. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +64 -87
  16. package/front_end/models/ai_assistance/agents/PerformanceAnnotationsAgent.ts +4 -4
  17. package/front_end/models/ai_assistance/agents/StylingAgent.ts +0 -31
  18. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +127 -29
  19. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +106 -55
  20. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +317 -640
  21. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +23 -19
  22. package/front_end/models/ai_assistance/performance/AICallTree.snapshot.txt +75 -0
  23. package/front_end/models/ai_assistance/performance/AICallTree.ts +14 -6
  24. package/front_end/models/ai_assistance/performance/AIContext.ts +63 -8
  25. package/front_end/models/ai_code_completion/AiCodeCompletion.ts +5 -0
  26. package/front_end/models/badges/AiExplorerBadge.ts +19 -3
  27. package/front_end/models/badges/Badge.ts +8 -1
  28. package/front_end/models/badges/CodeWhispererBadge.ts +1 -0
  29. package/front_end/models/badges/DOMDetectiveBadge.ts +1 -0
  30. package/front_end/models/badges/SpeedsterBadge.ts +1 -0
  31. package/front_end/models/badges/StarterBadge.ts +6 -0
  32. package/front_end/models/badges/badges.ts +1 -0
  33. package/front_end/models/javascript_metadata/NativeFunctions.js +4 -0
  34. package/front_end/models/trace/EventsSerializer.ts +4 -3
  35. package/front_end/models/trace/handlers/UserInteractionsHandler.ts +101 -73
  36. package/front_end/models/trace/helpers/Timing.ts +1 -1
  37. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +18 -8
  38. package/front_end/panels/ai_assistance/PatchWidget.ts +17 -55
  39. package/front_end/panels/ai_assistance/components/ChatView.ts +44 -68
  40. package/front_end/panels/ai_assistance/components/PerformanceAgentMarkdownRenderer.ts +63 -15
  41. package/front_end/panels/ai_assistance/components/chatView.css +12 -0
  42. package/front_end/panels/animation/AnimationTimeline.ts +1 -1
  43. package/front_end/panels/animation/animationTimeline.css +4 -0
  44. package/front_end/panels/application/components/BounceTrackingMitigationsView.ts +2 -2
  45. package/front_end/panels/application/preloading/components/PreloadingString.ts +2 -5
  46. package/front_end/panels/common/AiCodeCompletionTeaser.ts +5 -0
  47. package/front_end/panels/common/BadgeNotification.ts +3 -3
  48. package/front_end/panels/common/GdpSignUpDialog.ts +3 -4
  49. package/front_end/panels/common/aiCodeCompletionTeaser.css +6 -1
  50. package/front_end/panels/console/ConsolePrompt.ts +6 -0
  51. package/front_end/panels/console/ConsoleView.ts +4 -2
  52. package/front_end/panels/coverage/CoverageListView.ts +133 -158
  53. package/front_end/panels/coverage/CoverageView.ts +39 -16
  54. package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +5 -5
  55. package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +2 -0
  56. package/front_end/panels/network/NetworkDataGridNode.ts +22 -0
  57. package/front_end/panels/network/NetworkLogViewColumns.ts +9 -0
  58. package/front_end/panels/recorder/components/CreateRecordingView.ts +2 -0
  59. package/front_end/panels/recorder/components/RecordingView.ts +2 -2
  60. package/front_end/panels/search/SearchResultsPane.ts +186 -134
  61. package/front_end/panels/search/SearchView.ts +42 -36
  62. package/front_end/panels/search/searchResultsPane.css +9 -0
  63. package/front_end/panels/search/searchView.css +0 -2
  64. package/front_end/panels/security/CookieControlsView.ts +2 -1
  65. package/front_end/panels/settings/AISettingsTab.ts +6 -3
  66. package/front_end/panels/settings/components/SyncSection.ts +26 -12
  67. package/front_end/panels/settings/emulation/components/UserAgentClientHintsForm.ts +1 -1
  68. package/front_end/panels/sources/AiCodeCompletionPlugin.ts +4 -4
  69. package/front_end/panels/sources/DebuggerPlugin.ts +4 -0
  70. package/front_end/panels/sources/SourcesPanel.ts +1 -1
  71. package/front_end/panels/sources/sourcesView.css +6 -1
  72. package/front_end/panels/timeline/ThirdPartyTreeView.ts +1 -1
  73. package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +0 -8
  74. package/front_end/panels/timeline/TimelineFlameChartView.ts +5 -5
  75. package/front_end/panels/timeline/TimelinePanel.ts +2 -0
  76. package/front_end/panels/timeline/TimelineTreeView.ts +1 -1
  77. package/front_end/panels/timeline/components/LayoutShiftDetails.ts +1 -1
  78. package/front_end/panels/timeline/components/NetworkRequestDetails.ts +1 -1
  79. package/front_end/panels/timeline/components/RelatedInsightChips.ts +1 -1
  80. package/front_end/panels/timeline/components/SidebarSingleInsightSet.ts +1 -1
  81. package/front_end/third_party/chromium/README.chromium +1 -1
  82. package/front_end/third_party/puppeteer/README.chromium +2 -2
  83. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Realm.d.ts +2 -2
  84. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/injected.d.ts +1 -1
  85. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/injected.js +1 -1
  86. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.d.ts +1 -1
  87. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.js +1 -1
  88. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
  89. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js +1 -1
  90. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js.map +1 -1
  91. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
  92. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.js +1 -0
  93. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.js.map +1 -1
  94. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/PipeTransport.d.ts.map +1 -1
  95. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/PipeTransport.js +15 -16
  96. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/PipeTransport.js.map +1 -1
  97. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +3 -3
  98. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +3 -3
  99. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js.map +1 -1
  100. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Function.d.ts.map +1 -1
  101. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Function.js +16 -25
  102. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Function.js.map +1 -1
  103. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
  104. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +19 -28
  105. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/injected.d.ts +1 -1
  106. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/injected.js +1 -1
  107. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.d.ts +1 -1
  108. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.js +1 -1
  109. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js +1 -1
  110. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js.map +1 -1
  111. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
  112. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.js +1 -0
  113. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.js.map +1 -1
  114. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/PipeTransport.d.ts.map +1 -1
  115. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/PipeTransport.js +15 -16
  116. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/PipeTransport.js.map +1 -1
  117. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +3 -3
  118. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +3 -3
  119. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js.map +1 -1
  120. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/Function.d.ts.map +1 -1
  121. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/Function.js +16 -25
  122. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/Function.js.map +1 -1
  123. package/front_end/third_party/puppeteer/package/package.json +12 -4
  124. package/front_end/third_party/puppeteer/package/src/generated/injected.ts +1 -1
  125. package/front_end/third_party/puppeteer/package/src/generated/version.ts +1 -1
  126. package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +1 -1
  127. package/front_end/third_party/puppeteer/package/src/node/ChromeLauncher.ts +1 -0
  128. package/front_end/third_party/puppeteer/package/src/node/PipeTransport.ts +15 -17
  129. package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
  130. package/front_end/third_party/puppeteer/package/src/util/Function.ts +22 -30
  131. package/front_end/tsconfig.json +12 -1
  132. package/front_end/ui/components/dialogs/Dialog.ts +1 -1
  133. package/front_end/ui/components/markdown_view/MarkdownImage.ts +4 -5
  134. package/front_end/ui/components/switch/SwitchImpl.ts +12 -1
  135. package/front_end/ui/components/text_editor/config.ts +16 -2
  136. package/front_end/ui/legacy/InspectorView.ts +86 -13
  137. package/front_end/ui/legacy/TabbedPane.ts +2 -1
  138. package/front_end/ui/legacy/Treeoutline.ts +3 -1
  139. package/front_end/ui/legacy/components/source_frame/XMLView.ts +12 -11
  140. package/front_end/ui/lit/i18n-template.ts +5 -2
  141. package/front_end/ui/visual_logging/KnownContextValues.ts +15 -5
  142. package/front_end/ui/visual_logging/LoggingEvents.ts +1 -1
  143. package/package.json +1 -1
package/eslint.config.mjs CHANGED
@@ -720,6 +720,7 @@ export default defineConfig([
720
720
  'rulesdir/no-assert-deep-strict-equal': 'error',
721
721
  'rulesdir/no-assert-equal': 'error',
722
722
  'rulesdir/no-assert-equal-boolean-null-undefined': 'error',
723
+ 'rulesdir/no-capture-screenshot': 'error',
723
724
  'rulesdir/no-imperative-dom-api': 'off',
724
725
  'rulesdir/no-lit-render-outside-of-view': 'off',
725
726
  'rulesdir/prefer-assert-instance-of': 'error',
@@ -68,6 +68,11 @@ export interface Profile {
68
68
  };
69
69
  }
70
70
 
71
+ interface InitializeResult {
72
+ hasProfile: boolean;
73
+ isEligible: boolean;
74
+ }
75
+
71
76
  // The `batchGet` awards endpoint returns badge names with an
72
77
  // obfuscated user ID (e.g., `profiles/12345/awards/badge-name`).
73
78
  // This function normalizes them to use `me` instead of the ID
@@ -114,9 +119,13 @@ export class GdpClient {
114
119
  return gdpClientInstance;
115
120
  }
116
121
 
117
- async initialize(): Promise<void> {
118
- void this.getProfile();
119
- void this.checkEligibility();
122
+ async initialize(): Promise<InitializeResult> {
123
+ return await Promise.all([this.getProfile(), this.checkEligibility()]).then(([profile, eligibilityResponse]) => {
124
+ return {
125
+ hasProfile: Boolean(profile),
126
+ isEligible: eligibilityResponse?.createProfile === EligibilityStatus.ELIGIBLE
127
+ };
128
+ });
120
129
  }
121
130
 
122
131
  async getProfile(): Promise<Profile|null> {
@@ -459,11 +459,11 @@ export class EnhancedTracesParser {
459
459
  for (const orphanScript of orphanScripts) {
460
460
  const orphanScriptExecutionContextIsolateId =
461
461
  this.getExecutionContextIsolateId(orphanScript.isolate, orphanScript.executionContextId);
462
- if (orphanScriptExecutionContextIsolateId in executionContextIsolateToTarget) {
463
- const frameId = executionContextIsolateToTarget.get(orphanScriptExecutionContextIsolateId);
464
- if (frameId) {
465
- targetToScripts.get(frameId)?.push(orphanScript);
466
- }
462
+ const frameId = executionContextIsolateToTarget.get(orphanScriptExecutionContextIsolateId);
463
+
464
+ if (frameId) {
465
+ // Found a link via execution context, use it.
466
+ targetToScripts.get(frameId)?.push(orphanScript);
467
467
  } else if (orphanScript.pid) {
468
468
  const target = targets.find(target => target.pid === orphanScript.pid);
469
469
  if (target) {
@@ -597,6 +597,7 @@ export class NetworkDispatcher implements ProtocolProxyApi.NetworkDispatcher {
597
597
  networkRequest.mixedContentType = request.mixedContentType || Protocol.Security.MixedContentType.None;
598
598
  networkRequest.setReferrerPolicy(request.referrerPolicy);
599
599
  networkRequest.setIsSameSite(request.isSameSite || false);
600
+ networkRequest.setIsAdRelated(request.isAdRelated || false);
600
601
  }
601
602
 
602
603
  private updateNetworkRequestWithResponse(networkRequest: NetworkRequest, response: Protocol.Network.Response): void {
@@ -320,6 +320,7 @@ export class NetworkRequest extends Common.ObjectWrapper.ObjectWrapper<EventType
320
320
  directSocketInfo?: DirectSocketInfo;
321
321
  readonly #directSocketChunks: DirectSocketChunk[] = [];
322
322
  #isIpProtectionUsed: boolean;
323
+ #isAdRelated: boolean;
323
324
 
324
325
  constructor(
325
326
  requestId: string,
@@ -342,6 +343,7 @@ export class NetworkRequest extends Common.ObjectWrapper.ObjectWrapper<EventType
342
343
  this.#initiator = initiator;
343
344
  this.#hasUserGesture = hasUserGesture;
344
345
  this.#isIpProtectionUsed = false;
346
+ this.#isAdRelated = false;
345
347
  }
346
348
 
347
349
  static create(
@@ -1850,6 +1852,14 @@ export class NetworkRequest extends Common.ObjectWrapper.ObjectWrapper<EventType
1850
1852
  return this.#isIpProtectionUsed;
1851
1853
  }
1852
1854
 
1855
+ setIsAdRelated(isAdRelated: boolean): void {
1856
+ this.#isAdRelated = isAdRelated;
1857
+ }
1858
+
1859
+ isAdRelated(): boolean {
1860
+ return this.#isAdRelated;
1861
+ }
1862
+
1853
1863
  getAssociatedData(key: string): object|null {
1854
1864
  return this.#associatedData.get(key) || null;
1855
1865
  }
@@ -992,6 +992,217 @@ Content:
992
992
  "sessionId": 1
993
993
  }
994
994
 
995
+ /* RehydratingConnection says: */
996
+ {
997
+ "method": "Debugger.scriptParsed",
998
+ "params": {
999
+ "scriptId": "6",
1000
+ "isolate": "7348673817420155000",
1001
+ "buildId": "",
1002
+ "executionContextId": 1,
1003
+ "startLine": 0,
1004
+ "startColumn": 0,
1005
+ "endLine": 0,
1006
+ "endColumn": 0,
1007
+ "hash": "",
1008
+ "isModule": false,
1009
+ "url": "",
1010
+ "hasSourceURL": false,
1011
+ "sourceURL": "",
1012
+ "pid": 97964,
1013
+ "sourceText": "(async function(){ a…",
1014
+ "length": 32
1015
+ },
1016
+ "sessionId": 1
1017
+ }
1018
+
1019
+ /* fakeDevToolsFrontend says: */
1020
+ {
1021
+ "id": 21,
1022
+ "sessionId": 1,
1023
+ "method": "Debugger.getScriptSource",
1024
+ "params": {
1025
+ "scriptId": "6"
1026
+ }
1027
+ }
1028
+
1029
+ /* RehydratingConnection says: */
1030
+ {
1031
+ "id": 21,
1032
+ "result": {
1033
+ "scriptSource": "(async function(){ a…"
1034
+ },
1035
+ "sessionId": 1
1036
+ }
1037
+
1038
+ /* RehydratingConnection says: */
1039
+ {
1040
+ "method": "Debugger.scriptParsed",
1041
+ "params": {
1042
+ "scriptId": "1",
1043
+ "isolate": "7348673817420155000",
1044
+ "buildId": "",
1045
+ "executionContextId": 1,
1046
+ "startLine": 0,
1047
+ "startColumn": 0,
1048
+ "endLine": 0,
1049
+ "endColumn": 0,
1050
+ "hash": "",
1051
+ "isModule": false,
1052
+ "url": "",
1053
+ "hasSourceURL": false,
1054
+ "sourceURL": "",
1055
+ "pid": 97964
1056
+ },
1057
+ "sessionId": 1
1058
+ }
1059
+
1060
+ /* fakeDevToolsFrontend says: */
1061
+ {
1062
+ "id": 22,
1063
+ "sessionId": 1,
1064
+ "method": "Debugger.getScriptSource",
1065
+ "params": {
1066
+ "scriptId": "1"
1067
+ }
1068
+ }
1069
+
1070
+ /* RehydratingConnection says: */
1071
+ {
1072
+ "id": 22,
1073
+ "result": {
1074
+ "scriptSource": "No source text avail…"
1075
+ },
1076
+ "sessionId": 1
1077
+ }
1078
+
1079
+ /* RehydratingConnection says: */
1080
+ {
1081
+ "method": "Debugger.scriptParsed",
1082
+ "params": {
1083
+ "scriptId": "2",
1084
+ "isolate": "7348673817420155000",
1085
+ "buildId": "",
1086
+ "executionContextId": 1,
1087
+ "startLine": 0,
1088
+ "startColumn": 0,
1089
+ "endLine": 0,
1090
+ "endColumn": 0,
1091
+ "hash": "",
1092
+ "isModule": false,
1093
+ "url": "",
1094
+ "hasSourceURL": false,
1095
+ "sourceURL": "",
1096
+ "pid": 97964,
1097
+ "sourceText": "() {}…",
1098
+ "length": 5
1099
+ },
1100
+ "sessionId": 1
1101
+ }
1102
+
1103
+ /* fakeDevToolsFrontend says: */
1104
+ {
1105
+ "id": 23,
1106
+ "sessionId": 1,
1107
+ "method": "Debugger.getScriptSource",
1108
+ "params": {
1109
+ "scriptId": "2"
1110
+ }
1111
+ }
1112
+
1113
+ /* RehydratingConnection says: */
1114
+ {
1115
+ "id": 23,
1116
+ "result": {
1117
+ "scriptSource": "() {}…"
1118
+ },
1119
+ "sessionId": 1
1120
+ }
1121
+
1122
+ /* RehydratingConnection says: */
1123
+ {
1124
+ "method": "Debugger.scriptParsed",
1125
+ "params": {
1126
+ "scriptId": "3",
1127
+ "isolate": "7348673817420155000",
1128
+ "buildId": "",
1129
+ "executionContextId": 1,
1130
+ "startLine": 0,
1131
+ "startColumn": 0,
1132
+ "endLine": 0,
1133
+ "endColumn": 0,
1134
+ "hash": "",
1135
+ "isModule": false,
1136
+ "url": "extensions::SafeBuiltins",
1137
+ "hasSourceURL": false,
1138
+ "sourceURL": "",
1139
+ "pid": 97964
1140
+ },
1141
+ "sessionId": 1
1142
+ }
1143
+
1144
+ /* fakeDevToolsFrontend says: */
1145
+ {
1146
+ "id": 24,
1147
+ "sessionId": 1,
1148
+ "method": "Debugger.getScriptSource",
1149
+ "params": {
1150
+ "scriptId": "3"
1151
+ }
1152
+ }
1153
+
1154
+ /* RehydratingConnection says: */
1155
+ {
1156
+ "id": 24,
1157
+ "result": {
1158
+ "scriptSource": "No source text avail…"
1159
+ },
1160
+ "sessionId": 1
1161
+ }
1162
+
1163
+ /* RehydratingConnection says: */
1164
+ {
1165
+ "method": "Debugger.scriptParsed",
1166
+ "params": {
1167
+ "scriptId": "4",
1168
+ "isolate": "7348673817420155000",
1169
+ "buildId": "",
1170
+ "executionContextId": 1,
1171
+ "startLine": 0,
1172
+ "startColumn": 0,
1173
+ "endLine": 0,
1174
+ "endColumn": 0,
1175
+ "hash": "",
1176
+ "isModule": false,
1177
+ "url": "v8/LoadTimes",
1178
+ "hasSourceURL": false,
1179
+ "sourceURL": "",
1180
+ "pid": 97964,
1181
+ "sourceText": "var chrome;if (!chro…",
1182
+ "length": 198
1183
+ },
1184
+ "sessionId": 1
1185
+ }
1186
+
1187
+ /* fakeDevToolsFrontend says: */
1188
+ {
1189
+ "id": 25,
1190
+ "sessionId": 1,
1191
+ "method": "Debugger.getScriptSource",
1192
+ "params": {
1193
+ "scriptId": "4"
1194
+ }
1195
+ }
1196
+
1197
+ /* RehydratingConnection says: */
1198
+ {
1199
+ "id": 25,
1200
+ "result": {
1201
+ "scriptSource": "var chrome;if (!chro…"
1202
+ },
1203
+ "sessionId": 1
1204
+ }
1205
+
995
1206
  /* RehydratingConnection says: */
996
1207
  {
997
1208
  "id": 2,
@@ -318,6 +318,10 @@ export class TargetManager extends Common.ObjectWrapper.ObjectWrapper<EventTypes
318
318
  * (eg., tab URL of `devtools://devtools/bundled/devtools_app.html` uses a MainConnection but has no CDP server behind it).
319
319
  */
320
320
  hasFakeConnection(): boolean {
321
+ // Rehydrated DevTools always has a fake connection, so we shortcut and avoid the race.
322
+ if (Root.Runtime.getPathName().includes('rehydrated_devtools_app')) {
323
+ return true;
324
+ }
321
325
  // There _may_ be a race condition hiding here on the router/connection creation.
322
326
  // So we play it safe and consider "no connection yet" as "not fake".
323
327
  const connection = this.primaryPageTarget()?.router()?.connection();
@@ -519,7 +519,12 @@ export class MainImpl {
519
519
 
520
520
  // Initialize `GDPClient` and `UserBadges` for Google Developer Program integration
521
521
  if (Host.GdpClient.isGdpProfilesAvailable()) {
522
- void Host.GdpClient.GdpClient.instance().initialize();
522
+ void Host.GdpClient.GdpClient.instance().initialize().then(({hasProfile, isEligible}) => {
523
+ const contextString = hasProfile ? 'has-profile' :
524
+ isEligible ? 'no-profile-and-eligible' :
525
+ 'no-profile-and-not-eligible';
526
+ void VisualLogging.logFunctionCall('gdp-client-initialize', contextString);
527
+ });
523
528
  void Badges.UserBadges.instance().initialize();
524
529
  Badges.UserBadges.instance().addEventListener(Badges.Events.BADGE_TRIGGERED, async ev => {
525
530
  loadedPanelCommonModule ??= await import('../../panels/common/common.js') as typeof PanelCommon;
@@ -188,9 +188,9 @@ const UIStrings = {
188
188
  browserLanguage: 'Browser UI language',
189
189
  /**
190
190
  * @description Label for a checkbox in the settings UI. Allows developers to opt-in/opt-out
191
- * of syncing DevTools settings via Chrome Sync.
191
+ * of saving settings to their Google account.
192
192
  */
193
- enableSync: 'Enable settings sync',
193
+ saveSettings: 'Save `DevTools` settings to your `Google` account',
194
194
  /**
195
195
  * @description Label for a checkbox in the settings UI. Allows developers to opt-in/opt-out
196
196
  * of receiving Google Developer Program (GDP) badges based on their activity in Chrome DevTools.
@@ -789,7 +789,7 @@ Common.Settings.registerSettingExtension({
789
789
  // This name must be kept in sync with DevToolsSettings::kSyncDevToolsPreferencesFrontendName.
790
790
  settingName: 'sync-preferences',
791
791
  settingType: Common.Settings.SettingType.BOOLEAN,
792
- title: i18nLazyString(UIStrings.enableSync),
792
+ title: i18nLazyString(UIStrings.saveSettings),
793
793
  defaultValue: false,
794
794
  reloadRequired: true,
795
795
  });
@@ -641,6 +641,7 @@ export const generatedProperties = [
641
641
  "row-rule-style",
642
642
  "row-rule-width",
643
643
  "ruby-align",
644
+ "ruby-overhang",
644
645
  "ruby-position",
645
646
  "rx",
646
647
  "ry",
@@ -738,7 +739,7 @@ export const generatedProperties = [
738
739
  "timeline-trigger-name",
739
740
  "timeline-trigger-range-end",
740
741
  "timeline-trigger-range-start",
741
- "timeline-trigger-timeline",
742
+ "timeline-trigger-source",
742
743
  "top",
743
744
  "touch-action",
744
745
  "transform",
@@ -3732,6 +3733,14 @@ export const generatedProperties = [
3732
3733
  ],
3733
3734
  "name": "ruby-align"
3734
3735
  },
3736
+ {
3737
+ "inherited": true,
3738
+ "keywords": [
3739
+ "auto",
3740
+ "none"
3741
+ ],
3742
+ "name": "ruby-overhang"
3743
+ },
3735
3744
  {
3736
3745
  "inherited": true,
3737
3746
  "keywords": [
@@ -4422,7 +4431,7 @@ export const generatedProperties = [
4422
4431
  {
4423
4432
  "longhands": [
4424
4433
  "timeline-trigger-name",
4425
- "timeline-trigger-timeline",
4434
+ "timeline-trigger-source",
4426
4435
  "timeline-trigger-behavior",
4427
4436
  "timeline-trigger-range-start",
4428
4437
  "timeline-trigger-range-end",
@@ -4460,7 +4469,7 @@ export const generatedProperties = [
4460
4469
  "none",
4461
4470
  "auto"
4462
4471
  ],
4463
- "name": "timeline-trigger-timeline"
4472
+ "name": "timeline-trigger-source"
4464
4473
  },
4465
4474
  {
4466
4475
  "keywords": [
@@ -6482,6 +6491,12 @@ export const generatedPropertyValues = {
6482
6491
  "space-between"
6483
6492
  ]
6484
6493
  },
6494
+ "ruby-overhang": {
6495
+ "values": [
6496
+ "auto",
6497
+ "none"
6498
+ ]
6499
+ },
6485
6500
  "ruby-position": {
6486
6501
  "values": [
6487
6502
  "over",
@@ -6839,7 +6854,7 @@ export const generatedPropertyValues = {
6839
6854
  "state"
6840
6855
  ]
6841
6856
  },
6842
- "timeline-trigger-timeline": {
6857
+ "timeline-trigger-source": {
6843
6858
  "values": [
6844
6859
  "none",
6845
6860
  "auto"
@@ -133,13 +133,7 @@ export interface ParsedAnswer {
133
133
  suggestions?: [string, ...string[]];
134
134
  }
135
135
 
136
- export interface ParsedStep {
137
- thought?: string;
138
- title?: string;
139
- action?: string;
140
- }
141
-
142
- export type ParsedResponse = ParsedAnswer|ParsedStep;
136
+ export type ParsedResponse = ParsedAnswer;
143
137
 
144
138
  export const MAX_STEPS = 10;
145
139
 
@@ -404,13 +398,66 @@ export abstract class AiAgent<T> {
404
398
  return this.#origin;
405
399
  }
406
400
 
401
+ /**
402
+ * The AI has instructions to emit structured suggestions in their response. This
403
+ * function parses for that.
404
+ *
405
+ * Note: currently only StylingAgent and PerformanceAgent utilize this, but
406
+ * eventually all agents should support this.
407
+ */
408
+ parseTextResponseForSuggestions(text: string): ParsedResponse {
409
+ if (!text) {
410
+ return {answer: ''};
411
+ }
412
+
413
+ const lines = text.split('\n');
414
+ const answerLines: string[] = [];
415
+ let suggestions: [string, ...string[]]|undefined;
416
+
417
+ for (const line of lines) {
418
+ const trimmed = line.trim();
419
+ if (trimmed.startsWith('SUGGESTIONS:')) {
420
+ try {
421
+ // TODO: Do basic validation this is an array with strings
422
+ suggestions = JSON.parse(trimmed.substring('SUGGESTIONS:'.length).trim());
423
+ } catch {
424
+ }
425
+ } else {
426
+ answerLines.push(line);
427
+ }
428
+ }
429
+
430
+ // Sometimes the model fails to put the SUGGESTIONS text on its own line. Handle
431
+ // the case where the suggestions are part of the last line of the answer.
432
+ if (!suggestions && answerLines.at(-1)?.includes('SUGGESTIONS:')) {
433
+ const [answer, suggestionsText] = answerLines[answerLines.length - 1].split('SUGGESTIONS:', 2);
434
+ try {
435
+ // TODO: Do basic validation this is an array with strings
436
+ suggestions = JSON.parse(suggestionsText.trim().substring('SUGGESTIONS:'.length).trim());
437
+ } catch {
438
+ }
439
+ answerLines[answerLines.length - 1] = answer;
440
+ }
441
+
442
+ const response: ParsedResponse = {
443
+ // If we could not parse the parts, consider the response to be an
444
+ // answer.
445
+ answer: answerLines.join('\n'),
446
+ };
447
+
448
+ if (suggestions) {
449
+ response.suggestions = suggestions;
450
+ }
451
+
452
+ return response;
453
+ }
454
+
407
455
  /**
408
456
  * Parses a streaming text response into a
409
- * though/action/title/answer/suggestions component. This is only used
410
- * by StylingAgent.
457
+ * though/action/title/answer/suggestions component.
411
458
  */
412
459
  parseTextResponse(response: string): ParsedResponse {
413
- return {answer: response};
460
+ return this.parseTextResponseForSuggestions(response.trim());
414
461
  }
415
462
 
416
463
  /**