chrome-devtools-frontend 1.0.1717709 → 1.0.1721762

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 (291) hide show
  1. package/.agents/rules/models-and-core/core-ai-agent-context-and-prompt-discipline.md +29 -0
  2. package/.agents/rules/models-and-core/core-cdp-and-extension-error-handling.md +34 -0
  3. package/.agents/rules/models-and-core/core-gn-build-and-module-layering.md +23 -0
  4. package/.agents/rules/models-and-core/core-runtime-neutrality-and-platform-utils.md +28 -0
  5. package/.agents/rules/models-and-core/core-sdk-model-and-target-lifecycle.md +35 -0
  6. package/.agents/rules/models-and-core/core-security-origin-and-capability-guards.md +33 -0
  7. package/.agents/rules/models-and-core/core-settings-and-storage-migration.md +31 -0
  8. package/.agents/rules/models-and-core/core-sourcemap-and-workspace-mapping.md +28 -0
  9. package/.agents/rules/models-and-core/core-trace-engine-handler-invariants.md +32 -0
  10. package/.agents/rules/models-and-core/core-trace-insight-models-and-timing-types.md +28 -0
  11. package/.agents/rules/tests/test-cleanup-mutated-globals-and-widgets.md +40 -0
  12. package/.agents/rules/tests/test-deterministic-async-synchronization.md +30 -0
  13. package/.agents/rules/tests/test-modular-hooks-and-test-universe.md +38 -0
  14. package/.agents/rules/tests/test-public-api-and-encapsulation.md +30 -0
  15. package/.agents/rules/tests/test-shared-fixture-and-helper-reuse.md +29 -0
  16. package/.agents/rules/tests/test-single-responsibility-and-conciseness.md +37 -0
  17. package/.agents/rules/tests/test-strict-assertions-and-literal-expectations.md +31 -0
  18. package/.agents/rules/tests/test-type-safe-mocks-and-events.md +30 -0
  19. package/.agents/rules/tests/test-view-and-presenter-isolation.md +32 -0
  20. package/.agents/rules/ui-and-widgets/ui-accessibility-and-semantic-html.md +32 -0
  21. package/.agents/rules/ui-and-widgets/ui-await-update-complete-post-render.md +30 -0
  22. package/.agents/rules/ui-and-widgets/ui-css-scoping-and-flex-layout.md +27 -0
  23. package/.agents/rules/ui-and-widgets/ui-declarative-child-widget-composition.md +29 -0
  24. package/.agents/rules/ui-and-widgets/ui-lit-declarative-templates-and-directives.md +33 -0
  25. package/.agents/rules/ui-and-widgets/ui-localization-and-uistrings-hygiene.md +36 -0
  26. package/.agents/rules/ui-and-widgets/ui-modern-component-and-encapsulation-standards.md +32 -0
  27. package/.agents/rules/ui-and-widgets/ui-panel-and-meta-registration.md +35 -0
  28. package/.agents/rules/ui-and-widgets/ui-performance-and-flamechart-rendering.md +34 -0
  29. package/.agents/rules/ui-and-widgets/ui-pure-view-and-presenter-separation.md +31 -0
  30. package/.agents/rules/ui-and-widgets/ui-reactive-widget-update-lifecycle.md +34 -0
  31. package/.agents/rules/ui-and-widgets/ui-security-and-output-sanitization.md +28 -0
  32. package/.agents/rules/ui-and-widgets/ui-type-safety-and-exhaustiveness.md +37 -0
  33. package/.agents/rules/ui-and-widgets/ui-view-output-and-callback-contracts.md +35 -0
  34. package/.agents/rules/ui-and-widgets/ui-visual-logging-instrumentation.md +29 -0
  35. package/.agents/rules/ui-and-widgets/ui-weak-dom-references-and-observer-cleanup.md +29 -0
  36. package/.agents/rules/ui-and-widgets/ui-widget-dom-and-listener-lifecycle.md +38 -0
  37. package/.agents/skills/code-review/SKILL.md +3 -0
  38. package/.agents/skills/devtools-testing-guidance/SKILL.md +1 -0
  39. package/.agents/skills/review-models-core/SKILL.md +73 -0
  40. package/.agents/skills/review-tests/SKILL.md +67 -0
  41. package/.agents/skills/review-ui-widgets/SKILL.md +115 -0
  42. package/.agents/skills/ui-eng-vision-local-lit-renderer/SKILL.md +19 -3
  43. package/.agents/skills/ui-eng-vision-widget-promoter/SKILL.md +2 -1
  44. package/.agents/skills/ui-widgets/SKILL.md +3 -1
  45. package/AUTHORS +3 -0
  46. package/DIR_METADATA +51 -1
  47. package/eslint.config.mjs +63 -21
  48. package/front_end/core/platform/api/HostRuntime.ts +1 -0
  49. package/front_end/core/platform/browser/HostRuntime.ts +10 -0
  50. package/front_end/core/platform/node/HostRuntime.ts +1 -0
  51. package/front_end/core/sdk/CSSMatchedStyles.ts +60 -20
  52. package/front_end/core/sdk/CSSProperty.ts +2 -2
  53. package/front_end/core/sdk/CSSPropertyParserMatchers.ts +28 -9
  54. package/front_end/core/sdk/NetworkManager.ts +9 -3
  55. package/front_end/core/sdk/OverlayModel.ts +2 -8
  56. package/front_end/core/sdk/PrivateVerificationTokensModel.ts +79 -0
  57. package/front_end/core/sdk/SecurityOrigin.ts +1 -1
  58. package/front_end/core/sdk/SourceMapCache.ts +20 -15
  59. package/front_end/core/sdk/SourceMapManager.ts +28 -9
  60. package/front_end/core/sdk/TargetManager.ts +7 -4
  61. package/front_end/core/sdk/WebAuthnModel.ts +11 -2
  62. package/front_end/core/sdk/sdk.ts +2 -0
  63. package/front_end/entrypoints/inspector_main/InspectorMain.ts +0 -2
  64. package/front_end/entrypoints/inspector_main/inspector_main-meta.ts +10 -0
  65. package/front_end/entrypoints/main/GlobalAiButton.ts +1 -1
  66. package/front_end/entrypoints/main/MainImpl.ts +5 -2
  67. package/front_end/foundation/Universe.ts +1 -1
  68. package/front_end/generated/Deprecation.ts +4 -0
  69. package/front_end/generated/InspectorBackendCommands.ts +3 -3
  70. package/front_end/generated/SupportedCSSProperties.ts +89 -17
  71. package/front_end/generated/protocol-mapping.d.ts +1 -0
  72. package/front_end/generated/protocol-proxy-api.d.ts +1 -0
  73. package/front_end/generated/protocol.ts +5 -3
  74. package/front_end/models/{ai_assistance → ai-utils}/AiHistoryStorage.ts +6 -5
  75. package/front_end/models/{ai_assistance → ai-utils}/AiUtils.ts +9 -0
  76. package/front_end/models/{ai_assistance → ai-utils}/BuiltInAi.ts +1 -1
  77. package/front_end/models/ai-utils/ai-utils.ts +17 -0
  78. package/front_end/models/ai_assistance/AiAgent2.ts +3 -1
  79. package/front_end/models/ai_assistance/AiConversation.ts +34 -22
  80. package/front_end/models/ai_assistance/AlwaysAllowedTools.ts +107 -0
  81. package/front_end/models/ai_assistance/ConversationSummary.ts +2 -1
  82. package/front_end/models/ai_assistance/PerformanceAnnotations.ts +3 -1
  83. package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +3 -1
  84. package/front_end/models/ai_assistance/agents/AiAgent.ts +15 -7
  85. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +3 -1
  86. package/front_end/models/ai_assistance/agents/ExecuteJavascript.ts +3 -1
  87. package/front_end/models/ai_assistance/agents/PerformanceAgent.snapshot.txt +1 -1
  88. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +3 -1
  89. package/front_end/models/ai_assistance/ai_assistance.ts +9 -10
  90. package/front_end/models/ai_assistance/data_formatters/FileFormatter.ts +27 -6
  91. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +3 -3
  92. package/front_end/models/ai_assistance/skills/sources.md +3 -1
  93. package/front_end/models/ai_assistance/tools/ExecuteJavaScript.ts +1 -0
  94. package/front_end/models/ai_assistance/tools/GetCookieValues.ts +1 -0
  95. package/front_end/models/ai_assistance/tools/GetInsightDetails.ts +3 -1
  96. package/front_end/models/ai_assistance/tools/GetSourceContent.ts +46 -4
  97. package/front_end/models/ai_assistance/tools/GetStorageValues.ts +1 -0
  98. package/front_end/models/ai_assistance/tools/Tool.ts +6 -0
  99. package/front_end/models/breakpoints/BreakpointManager.ts +0 -4
  100. package/front_end/models/change_tracker/ChangeTracker.ts +2 -0
  101. package/front_end/models/comment_manager/CommentManager.ts +12 -0
  102. package/front_end/models/comment_manager/CommentThread.ts +21 -1
  103. package/front_end/models/elements/ChangeTrackingUtils.ts +37 -0
  104. package/front_end/models/elements/DOMChanges.ts +24 -36
  105. package/front_end/models/elements/StyleChanges.ts +97 -0
  106. package/front_end/models/elements/elements.ts +4 -0
  107. package/front_end/models/emulation/DeviceModeModel.ts +19 -0
  108. package/front_end/models/javascript_metadata/NativeFunctions.ts +11 -1
  109. package/front_end/models/trace/EventsSerializer.ts +35 -2
  110. package/front_end/models/trace/handlers/LayoutShiftsHandler.ts +17 -21
  111. package/front_end/models/trace/helpers/SyntheticEvents.ts +4 -2
  112. package/front_end/models/trace/lantern/core/NetworkAnalyzer.ts +12 -8
  113. package/front_end/models/trace/types/File.ts +20 -3
  114. package/front_end/models/trace/types/TraceEvents.ts +8 -3
  115. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +14 -0
  116. package/front_end/panels/ai_assistance/README.md +1 -1
  117. package/front_end/panels/ai_assistance/ai_assistance-meta.ts +1 -1
  118. package/front_end/panels/ai_assistance/ai_assistance.ts +2 -0
  119. package/front_end/panels/ai_assistance/components/ChatInput.ts +5 -43
  120. package/front_end/panels/ai_assistance/components/ChatMessage.ts +52 -147
  121. package/front_end/panels/ai_assistance/components/ChatView.ts +28 -3
  122. package/front_end/panels/ai_assistance/components/PermissionPrompt.ts +151 -0
  123. package/front_end/panels/ai_assistance/components/RelevantDataDisclaimer.ts +73 -0
  124. package/front_end/panels/ai_assistance/components/chatInput.css +0 -59
  125. package/front_end/panels/ai_assistance/components/chatMessage.css +0 -47
  126. package/front_end/panels/ai_assistance/components/chatView.css +5 -30
  127. package/front_end/panels/ai_assistance/components/permissionPrompt.css +55 -0
  128. package/front_end/panels/ai_assistance/components/relevantDataDisclaimer.css +35 -0
  129. package/front_end/panels/application/ApplicationPanelSidebar.ts +3 -7
  130. package/front_end/panels/application/BackgroundServiceView.ts +8 -8
  131. package/front_end/panels/application/IndexedDBViews.ts +102 -73
  132. package/front_end/panels/application/OpenedWindowDetailsView.ts +167 -130
  133. package/front_end/panels/application/ServiceWorkerCacheViews.ts +288 -346
  134. package/front_end/panels/application/StorageBucketsTreeElement.ts +22 -27
  135. package/front_end/panels/application/StorageItemsToolbar.ts +2 -2
  136. package/front_end/panels/application/components/StorageMetadataView.ts +207 -160
  137. package/front_end/panels/application/openedWindowDetailsView.css +7 -30
  138. package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +1 -1
  139. package/front_end/panels/changes/changesView.css +0 -6
  140. package/front_end/panels/console/ConsoleInsightTeaser.ts +5 -1
  141. package/front_end/panels/console/ConsolePinPane.ts +1 -1
  142. package/front_end/panels/console/ConsoleView.ts +1 -0
  143. package/front_end/panels/elements/CSSValueTraceView.ts +5 -5
  144. package/front_end/panels/elements/ColorSwatchPopoverIcon.ts +14 -6
  145. package/front_end/panels/elements/ComputedStyleWidget.ts +14 -5
  146. package/front_end/panels/elements/DOMTreeElementWidget.ts +2 -2
  147. package/front_end/panels/elements/DOMTreeWidget.ts +7 -3
  148. package/front_end/panels/elements/EventListenersWidget.ts +1 -1
  149. package/front_end/panels/elements/LayersWidget.ts +1 -1
  150. package/front_end/panels/elements/PropertyRenderer.ts +91 -16
  151. package/front_end/panels/elements/StandaloneStylesContainer.ts +33 -6
  152. package/front_end/panels/elements/StylePropertiesSection.ts +1 -0
  153. package/front_end/panels/elements/StylePropertyTreeElement.ts +211 -121
  154. package/front_end/panels/elements/StylesContainer.ts +2 -0
  155. package/front_end/panels/elements/StylesSidebarPane.ts +34 -16
  156. package/front_end/panels/elements/components/QueryContainer.ts +1 -1
  157. package/front_end/panels/elements/elementStatePaneWidget.css +1 -1
  158. package/front_end/panels/elements/stylePropertiesTreeOutline.css +1 -1
  159. package/front_end/panels/elements/stylesSidebarPane.css +4 -0
  160. package/front_end/panels/emulation/DeviceModeToolbar.ts +57 -25
  161. package/front_end/panels/emulation/DeviceModeView.ts +27 -1
  162. package/front_end/panels/emulation/InspectedPagePlaceholder.ts +6 -0
  163. package/front_end/panels/emulation/MediaQueryInspector.ts +14 -4
  164. package/front_end/panels/explain/components/ConsoleInsight.ts +2 -3
  165. package/front_end/panels/explain/explain-meta.ts +1 -1
  166. package/front_end/panels/issues/AffectedMetadataAllowedSitesView.ts +67 -34
  167. package/front_end/panels/issues/issues.ts +2 -0
  168. package/front_end/panels/layer_viewer/LayerTreeOutline.ts +7 -3
  169. package/front_end/panels/lighthouse/LighthouseController.ts +1 -1
  170. package/front_end/panels/media/PlayerMessagesView.ts +1 -1
  171. package/front_end/panels/mobile_throttling/CPUThrottlingSelector.ts +1 -1
  172. package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +45 -15
  173. package/front_end/panels/mobile_throttling/ThrottlingManager.ts +3 -3
  174. package/front_end/panels/network/BinaryResourceView.ts +54 -50
  175. package/front_end/panels/network/RequestHeadersView.ts +6 -2
  176. package/front_end/panels/network/RequestPreviewView.ts +28 -5
  177. package/front_end/panels/network/ResourceWebSocketFrameView.ts +1 -0
  178. package/front_end/panels/network/components/EditableSpan.ts +11 -30
  179. package/front_end/panels/network/components/HeaderSectionRow.ts +2 -2
  180. package/front_end/panels/performance_monitor/PerformanceMonitor.ts +10 -6
  181. package/front_end/panels/profiler/HeapDetachedElementsView.ts +112 -22
  182. package/front_end/panels/profiler/HeapProfileView.ts +3 -3
  183. package/front_end/panels/profiler/HeapSnapshotView.ts +12 -2
  184. package/front_end/panels/profiler/HeapTimelineOverview.ts +16 -2
  185. package/front_end/panels/profiler/profiler.ts +0 -2
  186. package/front_end/panels/protocol_monitor/JSONEditor.ts +1 -1
  187. package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +1 -1
  188. package/front_end/panels/recorder/CreateRecordingView.ts +1 -1
  189. package/front_end/panels/recorder/RecordingView.ts +3 -3
  190. package/front_end/panels/recorder/ReplaySection.ts +1 -1
  191. package/front_end/panels/screencast/ScreencastApp.ts +83 -57
  192. package/front_end/panels/screencast/screencastView.css +1 -1
  193. package/front_end/panels/settings/AISettingsTab.ts +107 -4
  194. package/front_end/panels/settings/aiSettingsTab.css +53 -0
  195. package/front_end/panels/settings/settings-meta.ts +1 -1
  196. package/front_end/panels/settings/settingsScreen.css +0 -4
  197. package/front_end/panels/sources/BreakpointsView.ts +2 -2
  198. package/front_end/panels/sources/DebuggerPlugin.ts +7 -0
  199. package/front_end/panels/sources/NavigatorView.ts +61 -18
  200. package/front_end/panels/sources/SourcesNavigator.ts +22 -7
  201. package/front_end/panels/sources/SourcesPanel.ts +1 -0
  202. package/front_end/panels/timeline/README.md +12 -0
  203. package/front_end/panels/timeline/StatusDialog.ts +1 -1
  204. package/front_end/panels/timeline/ThirdPartyTreeView.ts +1 -3
  205. package/front_end/panels/timeline/TimelineCommentController.ts +346 -0
  206. package/front_end/panels/timeline/TimelineDetailsView.ts +24 -1
  207. package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +34 -30
  208. package/front_end/panels/timeline/TimelineFlameChartView.ts +22 -1
  209. package/front_end/panels/timeline/TimelinePanel.ts +12 -5
  210. package/front_end/panels/timeline/TimelineTreeView.ts +28 -6
  211. package/front_end/panels/timeline/components/LiveMetricsView.ts +1 -1
  212. package/front_end/panels/timeline/components/fieldSettingsDialog.css +2 -2
  213. package/front_end/panels/timeline/components/insights/baseInsightComponent.css +1 -1
  214. package/front_end/panels/timeline/overlays/components/entriesLinkOverlay.css +2 -2
  215. package/front_end/panels/timeline/overlays/components/entryLabelOverlay.css +9 -9
  216. package/front_end/panels/timeline/timeline-meta.ts +2 -2
  217. package/front_end/panels/timeline/timeline.ts +4 -0
  218. package/front_end/panels/timeline/timelineFlamechartPopover.css +2 -2
  219. package/front_end/panels/timeline/timelinePanel.css +2 -2
  220. package/front_end/panels/web_audio/WebAudioView.ts +7 -4
  221. package/front_end/third_party/chromium/README.chromium +1 -1
  222. package/front_end/third_party/codemirror.next/chunk/angular.js +1 -1
  223. package/front_end/third_party/codemirror.next/chunk/angular.js.map +1 -1
  224. package/front_end/third_party/codemirror.next/chunk/codemirror.js +1 -1
  225. package/front_end/third_party/codemirror.next/chunk/codemirror.js.map +1 -1
  226. package/front_end/third_party/codemirror.next/chunk/cpp.js +1 -1
  227. package/front_end/third_party/codemirror.next/chunk/cpp.js.map +1 -1
  228. package/front_end/third_party/codemirror.next/chunk/java.js +1 -1
  229. package/front_end/third_party/codemirror.next/chunk/java.js.map +1 -1
  230. package/front_end/third_party/codemirror.next/chunk/less.js +1 -1
  231. package/front_end/third_party/codemirror.next/chunk/less.js.map +1 -1
  232. package/front_end/third_party/codemirror.next/chunk/markdown.js +1 -1
  233. package/front_end/third_party/codemirror.next/chunk/markdown.js.map +1 -1
  234. package/front_end/third_party/codemirror.next/chunk/php.js +1 -1
  235. package/front_end/third_party/codemirror.next/chunk/php.js.map +1 -1
  236. package/front_end/third_party/codemirror.next/chunk/python.js +1 -1
  237. package/front_end/third_party/codemirror.next/chunk/python.js.map +1 -1
  238. package/front_end/third_party/codemirror.next/chunk/sass.js +1 -1
  239. package/front_end/third_party/codemirror.next/chunk/sass.js.map +1 -1
  240. package/front_end/third_party/codemirror.next/chunk/svelte.js +1 -1
  241. package/front_end/third_party/codemirror.next/chunk/svelte.js.map +1 -1
  242. package/front_end/third_party/codemirror.next/chunk/vue.js +1 -1
  243. package/front_end/third_party/codemirror.next/chunk/vue.js.map +1 -1
  244. package/front_end/third_party/codemirror.next/chunk/wast.js +1 -1
  245. package/front_end/third_party/codemirror.next/chunk/wast.js.map +1 -1
  246. package/front_end/third_party/codemirror.next/chunk/xml.js +1 -1
  247. package/front_end/third_party/codemirror.next/chunk/xml.js.map +1 -1
  248. package/front_end/third_party/codemirror.next/codemirror.next.js +1 -1
  249. package/front_end/third_party/codemirror.next/rollup.config.mjs +1 -1
  250. package/front_end/tsconfig.json +1 -1
  251. package/front_end/ui/comments/CommentAnchorResolver.ts +1 -1
  252. package/front_end/ui/components/buttons/Button.ts +29 -18
  253. package/front_end/ui/components/code_highlighter/CodeHighlighter.ts +1 -1
  254. package/front_end/ui/components/dialogs/TypeToAllowDialog.ts +94 -39
  255. package/front_end/ui/components/dialogs/dialog.css +1 -1
  256. package/front_end/ui/components/menus/menuItem.css +11 -0
  257. package/front_end/ui/components/text_editor/AccessiblePlaceholder.ts +1 -1
  258. package/front_end/ui/components/text_editor/AiCodeCompletionTeaser.ts +1 -1
  259. package/front_end/ui/components/text_editor/config.ts +2 -1
  260. package/front_end/ui/components/text_editor/javascript.ts +2 -1
  261. package/front_end/ui/legacy/InspectorView.ts +4 -2
  262. package/front_end/ui/legacy/SplitWidget.ts +14 -16
  263. package/front_end/ui/legacy/TabbedPane.ts +9 -1
  264. package/front_end/ui/legacy/UIUtils.ts +60 -40
  265. package/front_end/ui/legacy/components/color_picker/spectrum.css +2 -2
  266. package/front_end/ui/legacy/components/data_grid/dataGrid.css +9 -0
  267. package/front_end/ui/legacy/components/inline_editor/CSSAngle.ts +0 -1
  268. package/front_end/ui/legacy/components/inline_editor/cssShadowEditor.css +5 -7
  269. package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +1 -1
  270. package/front_end/ui/legacy/components/perf_ui/PieChart.ts +11 -0
  271. package/front_end/ui/legacy/components/perf_ui/chartViewport.css +4 -4
  272. package/front_end/ui/legacy/components/quick_open/filteredListWidget.css +6 -0
  273. package/front_end/ui/legacy/components/settings_ui/SettingsUI.ts +1 -1
  274. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +38 -13
  275. package/front_end/ui/legacy/dropTarget.css +1 -1
  276. package/front_end/ui/legacy/statusBar.css +7 -0
  277. package/front_end/ui/legacy/tabbedPane.css +0 -7
  278. package/front_end/ui/visual_logging/KnownContextValues.ts +13 -0
  279. package/inspector_overlay/main.ts +2 -15
  280. package/inspector_overlay/tool_persistent.ts +0 -14
  281. package/mcp/mcp.ts +3 -0
  282. package/package.json +1 -1
  283. package/front_end/panels/ai_assistance/components/StylingAgentMarkdownRenderer.ts +0 -178
  284. package/front_end/panels/profiler/HeapDetachedElementsDataGrid.ts +0 -147
  285. package/front_end/panels/profiler/heapDetachedElementsDataGrid.css +0 -14
  286. package/front_end/ui/components/legacy_wrapper/LegacyWrapper.ts +0 -62
  287. package/front_end/ui/components/legacy_wrapper/legacy_wrapper.ts +0 -8
  288. package/inspector_overlay/tool_green_dev_anchors.css +0 -54
  289. package/inspector_overlay/tool_green_dev_anchors.ts +0 -164
  290. /package/front_end/models/{ai_assistance → ai-utils}/AiSetting.ts +0 -0
  291. /package/front_end/models/{ai_assistance → ai-utils}/debug.ts +0 -0
@@ -6,11 +6,11 @@ import * as Host from '../../../core/host/host.js';
6
6
  import * as i18n from '../../../core/i18n/i18n.js';
7
7
  import * as SDK from '../../../core/sdk/sdk.js';
8
8
  import * as TextUtils from '../../../core/text_utils/text_utils.js';
9
+ import * as AiUtils from '../../ai-utils/ai-utils.js';
9
10
  import * as Logs from '../../logs/logs.js';
10
11
  import * as Trace from '../../trace/trace.js';
11
12
  import type {AiWidget} from '../agents/AiAgent.js';
12
13
  import {PerformanceInsightFormatter} from '../data_formatters/PerformanceInsightFormatter.js';
13
- import {debugLog} from '../debug.js';
14
14
 
15
15
  import {
16
16
  type BaseToolCapability,
@@ -24,6 +24,8 @@ import {
24
24
  ToolName,
25
25
  } from './Tool.js';
26
26
 
27
+ const {debugLog} = AiUtils.Debug;
28
+
27
29
  const lockedString = i18n.i18n.lockedString;
28
30
 
29
31
  async function getNetworkRequestImageData(
@@ -25,20 +25,44 @@ const UIStringsNotTranslate = {
25
25
 
26
26
  const lockedString = i18n.i18n.lockedString;
27
27
 
28
+ /**
29
+ * Formats offsets in step titles, e.g. 30000 as "30,000". The titles are
30
+ * locked English strings, so the number uses en-US formatting to match.
31
+ */
32
+ const offsetFormatter = new Intl.NumberFormat('en-US');
33
+
28
34
  export interface GetSourceContentArgs extends ToolArgs {
29
35
  id: number;
36
+ offset?: number;
37
+ }
38
+
39
+ /**
40
+ * Names the file in the step title so that reads of different files, or of
41
+ * different parts of one file, are distinguishable in the walkthrough. The
42
+ * lookup does not check the origin lock: an id from an earlier listing can
43
+ * name a file from another origin. The title is only shown in the local UI and
44
+ * is not sent to the model, and the handler still rejects reading that file.
45
+ */
46
+ function titleFromArgs(args: GetSourceContentArgs): string {
47
+ const fileName = ListSourcesTool.idToUiSourceCode.get(args.id)?.displayName();
48
+ if (!fileName) {
49
+ return lockedString(UIStringsNotTranslate.readingSource);
50
+ }
51
+ return args.offset ? lockedString(`Reading ${fileName} (offset ${offsetFormatter.format(args.offset)})`) :
52
+ lockedString(`Reading ${fileName}`);
30
53
  }
31
54
 
32
55
  /**
33
56
  * A tool that retrieves the contents of a source file by its unique ID.
34
57
  * Filters access by origin lock to prevent cross-origin leakage.
58
+ * Long files are returned in parts; `offset` selects which part.
35
59
  */
36
60
  export class GetSourceContentTool implements
37
61
  DataTool<GetSourceContentArgs, {content: string}, BaseToolCapability&OriginLockCapability> {
38
62
  readonly name: ToolName = ToolName.GET_SOURCE_CONTENT;
39
63
  readonly permissionPrompt: PermissionPrompt = PermissionPrompt.NEVER;
40
64
  readonly description: string =
41
- 'Retrieves the formatted content and metadata of a source file by its numeric ID obtained from listSources.';
65
+ 'Retrieves the formatted content and metadata of a source file by its numeric ID obtained from listSources. Long files are returned in parts. If the result ends with a "Content truncated" notice, call this function again with the same id and the offset given in the notice to read the next part.';
42
66
 
43
67
  readonly parameters: Host.AidaClient.FunctionObjectParam<keyof GetSourceContentArgs> = {
44
68
  type: Host.AidaClient.ParametersTypes.OBJECT,
@@ -49,6 +73,12 @@ export class GetSourceContentTool implements
49
73
  description: 'The unique numeric ID of the source file to retrieve.',
50
74
  nullable: false,
51
75
  },
76
+ offset: {
77
+ type: Host.AidaClient.ParametersTypes.INTEGER,
78
+ description:
79
+ 'Character offset to start reading from. Omit to read from the start of the file. Use the offset given in a "Content truncated" notice to read the next part.',
80
+ nullable: true,
81
+ },
52
82
  },
53
83
  required: ['id'],
54
84
  };
@@ -58,8 +88,8 @@ export class GetSourceContentTool implements
58
88
  action: string,
59
89
  } {
60
90
  return {
61
- title: lockedString(UIStringsNotTranslate.readingSource),
62
- action: `getSourceContent(${args.id})`,
91
+ title: titleFromArgs(args),
92
+ action: args.offset ? `getSourceContent(${args.id}, ${args.offset})` : `getSourceContent(${args.id})`,
63
93
  };
64
94
  }
65
95
 
@@ -88,11 +118,23 @@ export class GetSourceContentTool implements
88
118
  };
89
119
  }
90
120
 
121
+ // Validate against the same working copy that FileFormatter slices. Binary
122
+ // files count as 0 characters so any offset above 0 is rejected, rather than
123
+ // slicing FileFormatter's '<binary data>' placeholder.
124
+ const offset = args.offset ?? 0;
125
+ const workingCopy = file.workingCopyContentData();
126
+ const contentLength = workingCopy.isTextContent ? workingCopy.text.length : 0;
127
+ if (!Number.isInteger(offset) || offset < 0 || (offset > 0 && offset >= contentLength)) {
128
+ return {
129
+ error: `Invalid offset ${offset}. The file content has ${contentLength} characters.`,
130
+ };
131
+ }
132
+
91
133
  const formatter = new FileFormatter(file);
92
134
 
93
135
  return {
94
136
  result: {
95
- content: formatter.formatFile(),
137
+ content: formatter.formatFile({offset}),
96
138
  },
97
139
  };
98
140
  }
@@ -49,6 +49,7 @@ export class GetStorageValuesTool implements DataTool<GetStorageValuesArgs, GetS
49
49
  readonly name: ToolName = ToolName.GET_STORAGE_VALUES;
50
50
  readonly permissionPrompt: PermissionPrompt = PermissionPrompt.ALLOW_ONCE;
51
51
  readonly permissionTitle: string = lockedString('Allow reading storage values?');
52
+ readonly displayName: string = lockedString('Read storage values');
52
53
  readonly description: string =
53
54
  'Retrieve specific string values from storage partitions for requested keys across origins.';
54
55
 
@@ -330,6 +330,12 @@ export interface BaseTool<ArgsType extends ToolArgs = ToolArgs> {
330
330
  * Required for tools that require user permission to run.
331
331
  */
332
332
  readonly permissionTitle?: string;
333
+ /**
334
+ * Short user-facing name of the tool, e.g. "Read cookie values".
335
+ * Shown in the "Allowed tools" list in Settings.
336
+ * Required for tools that require user permission to run.
337
+ */
338
+ readonly displayName?: string;
333
339
  /**
334
340
  * JSON schema representing the parameters this tool accepts.
335
341
  */
@@ -330,10 +330,6 @@ export class BreakpointManager extends Common.ObjectWrapper.ObjectWrapper<EventT
330
330
  enabled, isLogpoint, origin);
331
331
 
332
332
  if (uiSourceCode === compatibleUiSourceCode) {
333
- if (normalizedLocation.id() !== uiLocation.id()) {
334
- // Only call this on the uiSourceCode that was initially selected for breakpoint setting.
335
- void Common.Revealer.reveal(normalizedLocation);
336
- }
337
333
  primaryBreakpoint = breakpoint;
338
334
  }
339
335
  }
@@ -2,6 +2,7 @@
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
4
 
5
+ import * as Host from '../../core/host/host.js';
5
6
  import * as Root from '../../core/root/root.js';
6
7
  import type * as CommentManager from '../comment_manager/comment_manager.js';
7
8
 
@@ -26,5 +27,6 @@ export class ChangeTracker {
26
27
 
27
28
  const thread = this.#commentManager.createCommentThread(anchor, description, 'DEVELOPER', true);
28
29
  thread.save();
30
+ Host.userMetrics.changeRecorded(1);
29
31
  }
30
32
  }
@@ -3,6 +3,7 @@
3
3
  // found in the LICENSE file.
4
4
 
5
5
  import * as Common from '../../core/common/common.js';
6
+ import * as Host from '../../core/host/host.js';
6
7
 
7
8
  import {
8
9
  type Comment,
@@ -126,6 +127,14 @@ export class CommentManager extends Common.ObjectWrapper.ObjectWrapper<EventType
126
127
  threads.push(thread);
127
128
  }
128
129
  }
130
+ const changeCount = threads.filter(thread => thread.isGeneratedComment).length;
131
+ const commentCount = threads.length - changeCount;
132
+ if (commentCount > 0) {
133
+ Host.userMetrics.commentSharedWithAgent(commentCount);
134
+ }
135
+ if (changeCount > 0) {
136
+ Host.userMetrics.changeSharedWithAgent(changeCount);
137
+ }
129
138
  return threads;
130
139
  }
131
140
 
@@ -142,6 +151,9 @@ export class CommentManager extends Common.ObjectWrapper.ObjectWrapper<EventType
142
151
  if (!thread) {
143
152
  return false;
144
153
  }
154
+ if (thread.status !== 'RESOLVED') {
155
+ Host.userMetrics.commentResolved('Agent', 1);
156
+ }
145
157
  thread.resolve(replyText);
146
158
  return true;
147
159
  }
@@ -3,6 +3,7 @@
3
3
  // found in the LICENSE file.
4
4
 
5
5
  import * as Common from '../../core/common/common.js';
6
+ import * as Host from '../../core/host/host.js';
6
7
 
7
8
  export interface EditorAnchorSignature {
8
9
  /** 1-based line number for CodeMirror text editor anchors */
@@ -37,7 +38,7 @@ export interface CommentAnchorSignature {
37
38
  /** Visual logging tree path, e.g. "Panel: elements > Pane: styles > TreeOutline > TreeItem: color" */
38
39
  vePath: string;
39
40
  /** Normalized text content of the target node */
40
- textSignature: string;
41
+ textSignature?: string;
41
42
  /** Text content of the parent container VE node for sibling disambiguation */
42
43
  parentTextSignature?: string;
43
44
  /** 0-indexed position among siblings sharing the same visual logging path */
@@ -117,9 +118,25 @@ export class CommentThread extends Common.ObjectWrapper.ObjectWrapper<EventTypes
117
118
  return false;
118
119
  }
119
120
 
121
+ /**
122
+ * Records UMA for a developer-authored comment when it leaves the DRAFT state.
123
+ */
124
+ #recordCommentCreated(): void {
125
+ if (this.isGeneratedComment) {
126
+ return;
127
+ }
128
+ const text = this.comments.find(c => c.author === 'DEVELOPER')?.text.trim();
129
+ if (!text) {
130
+ return;
131
+ }
132
+ Host.userMetrics.commentCreated(1);
133
+ Host.userMetrics.commentSize(text.length);
134
+ }
135
+
120
136
  save(text?: string, author: 'DEVELOPER'|'AGENT' = 'DEVELOPER'): void {
121
137
  let changed = this.#saveText(text, author);
122
138
  if (this.status === 'DRAFT') {
139
+ this.#recordCommentCreated();
123
140
  if (this.#savedIndex === undefined) {
124
141
  this.#savedIndex = CommentThread.#nextIndex++;
125
142
  }
@@ -146,6 +163,9 @@ export class CommentThread extends Common.ObjectWrapper.ObjectWrapper<EventTypes
146
163
 
147
164
  sendToAgent(text?: string, author: 'DEVELOPER'|'AGENT' = 'DEVELOPER'): void {
148
165
  let changed = this.#saveText(text, author);
166
+ if (this.status === 'DRAFT') {
167
+ this.#recordCommentCreated();
168
+ }
149
169
  if (this.status === 'DRAFT' || this.status === 'ACTIVE') {
150
170
  if (this.#savedIndex === undefined) {
151
171
  this.#savedIndex = CommentThread.#nextIndex++;
@@ -0,0 +1,37 @@
1
+ // Copyright 2026 The Chromium Authors
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import * as Platform from '../../core/platform/platform.js';
6
+ import type * as SDK from '../../core/sdk/sdk.js';
7
+ import type * as CommentManager from '../comment_manager/comment_manager.js';
8
+
9
+ /**
10
+ * Maximum number of characters of page or author controlled data (tag names, attribute names
11
+ * and values, text node values, HTML, CSS property names/values, and selectors) that a change
12
+ * description embeds.
13
+ */
14
+ export const MAX_VALUE_LENGTH = 100;
15
+
16
+ /** Shortens page or author controlled data so that both its start and end stay recognizable. */
17
+ export function trimValue(value: string): string {
18
+ return Platform.StringUtilities.trimMiddle(value.trim(), MAX_VALUE_LENGTH);
19
+ }
20
+
21
+ export function buildAnchor(
22
+ vePath: string,
23
+ node: SDK.DOMModel.DOMNode|null,
24
+ textSignature?: string,
25
+ ): CommentManager.CommentManager.CommentAnchorSignature {
26
+ return {
27
+ vePath,
28
+ ...(textSignature ? {textSignature} : {}),
29
+ ...(node ? {
30
+ node: {
31
+ backendNodeId: node.backendNodeId(),
32
+ targetId: node.domModel().target().id(),
33
+ },
34
+ } :
35
+ {}),
36
+ };
37
+ }
@@ -2,37 +2,15 @@
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
4
 
5
- import * as Platform from '../../core/platform/platform.js';
6
5
  import type * as SDK from '../../core/sdk/sdk.js';
7
6
  import type * as ChangeTracker from '../change_tracker/change_tracker.js';
8
- import type * as CommentManager from '../comment_manager/comment_manager.js';
9
7
 
10
- type Tracker = ChangeTracker.ChangeTracker.ChangeTracker|undefined;
11
-
12
- /**
13
- * Maximum number of characters of page controlled data (tag names, attribute names and values,
14
- * text node values and HTML) that a change description embeds. The inspected page fully controls
15
- * these strings and `Changed HTML from ... to ...` in particular can otherwise hold on to the
16
- * entire subtree of an element.
17
- */
18
- export const MAX_VALUE_LENGTH = 100;
8
+ import {buildAnchor, trimValue} from './ChangeTrackingUtils.js';
19
9
 
20
- /** Shortens page controlled data so that both its start and its end stay recognizable. */
21
- function trimValue(value: string): string {
22
- return Platform.StringUtilities.trimMiddle(value, MAX_VALUE_LENGTH);
23
- }
10
+ type Tracker = ChangeTracker.ChangeTracker.ChangeTracker|undefined;
24
11
 
25
- function buildAnchor(node: SDK.DOMModel.DOMNode,
26
- selector = 'element'): CommentManager.CommentManager.CommentAnchorSignature {
27
- return {
28
- vePath: 'Panel: elements > Tree: elements > TreeItem',
29
- textSignature: selector,
30
- node: {
31
- backendNodeId: node.backendNodeId(),
32
- targetId: node.domModel().target().id(),
33
- },
34
- };
35
- }
12
+ const DOM_TREE_VE_PATH = 'Panel: elements > Tree: elements > TreeItem';
13
+ const ELEMENT_PLACEHOLDER_TEXT_SIGNATURE = 'element';
36
14
 
37
15
  /**
38
16
  * Parses a raw attribute string (e.g. 'class="btn"', 'data-id=123', or 'disabled')
@@ -165,7 +143,8 @@ export function trackAttributeEdit(tracker: Tracker, node: SDK.DOMModel.DOMNode,
165
143
  if (!tracker?.isTracking) {
166
144
  return;
167
145
  }
168
- tracker.trackChange(describeAttributeEdit(edit), buildAnchor(node, selector));
146
+ tracker.trackChange(describeAttributeEdit(edit),
147
+ buildAnchor(DOM_TREE_VE_PATH, node, selector ?? ELEMENT_PLACEHOLDER_TEXT_SIGNATURE));
169
148
  }
170
149
 
171
150
  export function trackTagNameEdit(tracker: Tracker, node: SDK.DOMModel.DOMNode, selector: string|undefined,
@@ -173,7 +152,8 @@ export function trackTagNameEdit(tracker: Tracker, node: SDK.DOMModel.DOMNode, s
173
152
  if (!tracker?.isTracking) {
174
153
  return;
175
154
  }
176
- tracker.trackChange(describeTagNameEdit(oldTagName, newTagName), buildAnchor(node, selector));
155
+ tracker.trackChange(describeTagNameEdit(oldTagName, newTagName),
156
+ buildAnchor(DOM_TREE_VE_PATH, node, selector ?? ELEMENT_PLACEHOLDER_TEXT_SIGNATURE));
177
157
  }
178
158
 
179
159
  export function trackTextNodeEdit(tracker: Tracker, node: SDK.DOMModel.DOMNode, selector: string|undefined,
@@ -181,14 +161,16 @@ export function trackTextNodeEdit(tracker: Tracker, node: SDK.DOMModel.DOMNode,
181
161
  if (!tracker?.isTracking) {
182
162
  return;
183
163
  }
184
- tracker.trackChange(describeTextNodeEdit(oldText, newText), buildAnchor(node, selector));
164
+ tracker.trackChange(describeTextNodeEdit(oldText, newText),
165
+ buildAnchor(DOM_TREE_VE_PATH, node, selector ?? ELEMENT_PLACEHOLDER_TEXT_SIGNATURE));
185
166
  }
186
167
 
187
168
  export function trackNodeRemoval(tracker: Tracker, node: SDK.DOMModel.DOMNode, selector: string|undefined): void {
188
169
  if (!tracker?.isTracking) {
189
170
  return;
190
171
  }
191
- tracker.trackChange(describeNodeRemoval(node.nodeName().toLowerCase()), buildAnchor(node, selector));
172
+ tracker.trackChange(describeNodeRemoval(node.nodeName().toLowerCase()),
173
+ buildAnchor(DOM_TREE_VE_PATH, node, selector ?? ELEMENT_PLACEHOLDER_TEXT_SIGNATURE));
192
174
  }
193
175
 
194
176
  export function trackHTMLEdit(tracker: Tracker, node: SDK.DOMModel.DOMNode, selector: string|undefined,
@@ -196,7 +178,8 @@ export function trackHTMLEdit(tracker: Tracker, node: SDK.DOMModel.DOMNode, sele
196
178
  if (!tracker?.isTracking) {
197
179
  return;
198
180
  }
199
- tracker.trackChange(describeHTMLEdit(oldValue, newValue), buildAnchor(node, selector));
181
+ tracker.trackChange(describeHTMLEdit(oldValue, newValue),
182
+ buildAnchor(DOM_TREE_VE_PATH, node, selector ?? ELEMENT_PLACEHOLDER_TEXT_SIGNATURE));
200
183
  }
201
184
 
202
185
  export function trackVisibilityToggle(tracker: Tracker, node: SDK.DOMModel.DOMNode, selector: string|undefined,
@@ -204,14 +187,16 @@ export function trackVisibilityToggle(tracker: Tracker, node: SDK.DOMModel.DOMNo
204
187
  if (!tracker?.isTracking) {
205
188
  return;
206
189
  }
207
- tracker.trackChange(describeVisibilityToggle(node.nodeName().toLowerCase(), hidden), buildAnchor(node, selector));
190
+ tracker.trackChange(describeVisibilityToggle(node.nodeName().toLowerCase(), hidden),
191
+ buildAnchor(DOM_TREE_VE_PATH, node, selector ?? ELEMENT_PLACEHOLDER_TEXT_SIGNATURE));
208
192
  }
209
193
 
210
194
  export function trackNodeDuplication(tracker: Tracker, node: SDK.DOMModel.DOMNode, selector: string|undefined): void {
211
195
  if (!tracker?.isTracking) {
212
196
  return;
213
197
  }
214
- tracker.trackChange(describeNodeDuplication(node.nodeName().toLowerCase()), buildAnchor(node, selector));
198
+ tracker.trackChange(describeNodeDuplication(node.nodeName().toLowerCase()),
199
+ buildAnchor(DOM_TREE_VE_PATH, node, selector ?? ELEMENT_PLACEHOLDER_TEXT_SIGNATURE));
215
200
  }
216
201
 
217
202
  export function trackNodeMove(tracker: Tracker, node: SDK.DOMModel.DOMNode, selector: string|undefined,
@@ -219,14 +204,16 @@ export function trackNodeMove(tracker: Tracker, node: SDK.DOMModel.DOMNode, sele
219
204
  if (!tracker?.isTracking) {
220
205
  return;
221
206
  }
222
- tracker.trackChange(describeNodeMove(node.nodeName().toLowerCase(), directionUp), buildAnchor(node, selector));
207
+ tracker.trackChange(describeNodeMove(node.nodeName().toLowerCase(), directionUp),
208
+ buildAnchor(DOM_TREE_VE_PATH, node, selector ?? ELEMENT_PLACEHOLDER_TEXT_SIGNATURE));
223
209
  }
224
210
 
225
211
  export function trackNodeDrop(tracker: Tracker, node: SDK.DOMModel.DOMNode, selector: string|undefined): void {
226
212
  if (!tracker?.isTracking) {
227
213
  return;
228
214
  }
229
- tracker.trackChange(describeNodeDrop(node.nodeName().toLowerCase()), buildAnchor(node, selector));
215
+ tracker.trackChange(describeNodeDrop(node.nodeName().toLowerCase()),
216
+ buildAnchor(DOM_TREE_VE_PATH, node, selector ?? ELEMENT_PLACEHOLDER_TEXT_SIGNATURE));
230
217
  }
231
218
 
232
219
  export function trackNodePaste(tracker: Tracker, node: SDK.DOMModel.DOMNode, selector: string|undefined,
@@ -234,5 +221,6 @@ export function trackNodePaste(tracker: Tracker, node: SDK.DOMModel.DOMNode, sel
234
221
  if (!tracker?.isTracking) {
235
222
  return;
236
223
  }
237
- tracker.trackChange(describeNodePaste(node.nodeName().toLowerCase(), isCut), buildAnchor(node, selector));
224
+ tracker.trackChange(describeNodePaste(node.nodeName().toLowerCase(), isCut),
225
+ buildAnchor(DOM_TREE_VE_PATH, node, selector ?? ELEMENT_PLACEHOLDER_TEXT_SIGNATURE));
238
226
  }
@@ -0,0 +1,97 @@
1
+ // Copyright 2026 The Chromium Authors
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import * as Platform from '../../core/platform/platform.js';
6
+ import type * as SDK from '../../core/sdk/sdk.js';
7
+ import type * as ChangeTracker from '../change_tracker/change_tracker.js';
8
+
9
+ import {buildAnchor, trimValue} from './ChangeTrackingUtils.js';
10
+
11
+ const STYLES_PANE_VE_PATH = 'Panel: elements > Pane: styles';
12
+
13
+ function formatRuleSuffix(preposition: 'in'|'to'|'from', ruleHeader?: string): string {
14
+ const trimmedRule = ruleHeader ? Platform.StringUtilities.collapseWhitespace(ruleHeader.trim()) : '';
15
+ return trimmedRule ? ` ${preposition} rule "${trimValue(trimmedRule)}"` : '';
16
+ }
17
+
18
+ export interface StylePropertyEdit {
19
+ /** Rule header or selector containing the property (e.g. 'element.style' or '.btn:hover'). */
20
+ ruleHeader?: string;
21
+ /** Property name before the edit, or an empty string when a new property is added. */
22
+ oldName: string;
23
+ /** Property value before the edit (including '!important' if present). */
24
+ oldValue: string;
25
+ /** Committed property name, or an empty string when the property is removed. */
26
+ newName: string;
27
+ /** Committed property value (including '!important' if present). */
28
+ newValue: string;
29
+ }
30
+
31
+ export interface StylePropertyToggle {
32
+ /** Rule header or selector containing the property (e.g. 'element.style' or '.btn:hover'). */
33
+ ruleHeader?: string;
34
+ name: string;
35
+ value: string;
36
+ /** Whether the property is now disabled. */
37
+ disabled: boolean;
38
+ }
39
+
40
+ /**
41
+ * These strings are for consumption by AI agents and do not need to be translated.
42
+ */
43
+ function describeStylePropertyEdit({ruleHeader, oldName, oldValue, newName, newValue}: StylePropertyEdit): string {
44
+ if (!newName) {
45
+ return `Removed style property "${trimValue(oldName)}: ${trimValue(oldValue)}"${
46
+ formatRuleSuffix('from', ruleHeader)}`;
47
+ }
48
+
49
+ if (!oldName) {
50
+ return `Added style property "${trimValue(newName)}: ${trimValue(newValue)}"${formatRuleSuffix('to', ruleHeader)}`;
51
+ }
52
+
53
+ if (oldName !== newName) {
54
+ return `Changed style property from "${trimValue(oldName)}: ${trimValue(oldValue)}" to "${trimValue(newName)}: ${
55
+ trimValue(newValue)}"${formatRuleSuffix('in', ruleHeader)}`;
56
+ }
57
+
58
+ return `Changed style property "${trimValue(newName)}" from "${trimValue(oldValue)}" to "${trimValue(newValue)}"${
59
+ formatRuleSuffix('in', ruleHeader)}`;
60
+ }
61
+
62
+ function describeStylePropertyToggle({ruleHeader, name, value, disabled}: StylePropertyToggle): string {
63
+ const action = disabled ? 'Disabled' : 'Enabled';
64
+ return `${action} style property "${trimValue(name)}: ${trimValue(value)}"${formatRuleSuffix('in', ruleHeader)}`;
65
+ }
66
+
67
+ export function trackStylePropertyEdit(
68
+ tracker: ChangeTracker.ChangeTracker.ChangeTracker|undefined,
69
+ node: SDK.DOMModel.DOMNode,
70
+ edit: StylePropertyEdit,
71
+ ): void {
72
+ if (!tracker?.isTracking) {
73
+ return;
74
+ }
75
+ const oldName = edit.oldName.trim();
76
+ const oldValue = edit.oldValue.trim();
77
+ const newName = edit.newName.trim();
78
+ const newValue = edit.newValue.trim();
79
+ if (oldName === newName && oldValue === newValue) {
80
+ return;
81
+ }
82
+ tracker.trackChange(
83
+ describeStylePropertyEdit({ruleHeader: edit.ruleHeader, oldName, oldValue, newName, newValue}),
84
+ buildAnchor(STYLES_PANE_VE_PATH, node),
85
+ );
86
+ }
87
+
88
+ export function trackStylePropertyToggle(
89
+ tracker: ChangeTracker.ChangeTracker.ChangeTracker|undefined,
90
+ node: SDK.DOMModel.DOMNode,
91
+ toggle: StylePropertyToggle,
92
+ ): void {
93
+ if (!tracker?.isTracking) {
94
+ return;
95
+ }
96
+ tracker.trackChange(describeStylePropertyToggle(toggle), buildAnchor(STYLES_PANE_VE_PATH, node));
97
+ }
@@ -2,10 +2,14 @@
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
4
 
5
+ import * as ChangeTrackingUtils from './ChangeTrackingUtils.js';
5
6
  import * as DOMChanges from './DOMChanges.js';
6
7
  import * as ElementUpdateRecord from './ElementUpdateRecord.js';
8
+ import * as StyleChanges from './StyleChanges.js';
7
9
 
8
10
  export {
11
+ ChangeTrackingUtils,
9
12
  DOMChanges,
10
13
  ElementUpdateRecord,
14
+ StyleChanges,
11
15
  };
@@ -918,6 +918,21 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
918
918
  try {
919
919
  const screenshot = await screenCaptureModel.captureScreenshot(
920
920
  Protocol.Page.CaptureScreenshotRequestFormat.Png, 100, screenshotMode, clip);
921
+
922
+ if (screenshot !== null) {
923
+ void Platform.HostRuntime.HOST_RUNTIME
924
+ .copyScreenshot({
925
+ base64Png: screenshot,
926
+ fileName: this.getScreenshotFileName(),
927
+ })
928
+ .then(() => {
929
+ this.dispatchEventToListeners(Events.SCREENSHOT_COPIED);
930
+ })
931
+ .catch(() => {
932
+ this.dispatchEventToListeners(Events.SCREENSHOT_COPY_FAILED);
933
+ });
934
+ }
935
+
921
936
  return screenshot;
922
937
  } finally {
923
938
  await this.#emulationModel?.emulateDevice(null);
@@ -1173,10 +1188,14 @@ export class Rect {
1173
1188
 
1174
1189
  export const enum Events {
1175
1190
  UPDATED = 'Updated',
1191
+ SCREENSHOT_COPIED = 'ScreenshotCopied',
1192
+ SCREENSHOT_COPY_FAILED = 'ScreenshotCopyFailed',
1176
1193
  }
1177
1194
 
1178
1195
  export interface EventTypes {
1179
1196
  [Events.UPDATED]: void;
1197
+ [Events.SCREENSHOT_COPIED]: void;
1198
+ [Events.SCREENSHOT_COPY_FAILED]: void;
1180
1199
  }
1181
1200
 
1182
1201
  export enum Type {
@@ -6409,7 +6409,13 @@ export const NativeFunctions: readonly NativeFunctionValue[] = [
6409
6409
  },
6410
6410
  {
6411
6411
  name: "openWindow",
6412
- signatures: [["url"]]
6412
+ signatures: [["url"]],
6413
+ receivers: ["Clients"]
6414
+ },
6415
+ {
6416
+ name: "openWindow",
6417
+ signatures: [["url","?options"]],
6418
+ receivers: ["PaymentRequestEvent"]
6413
6419
  },
6414
6420
  {
6415
6421
  name: "waitUntil",
@@ -8471,6 +8477,10 @@ export const NativeFunctions: readonly NativeFunctionValue[] = [
8471
8477
  name: "executeTool",
8472
8478
  signatures: [["tool","?inputObject","?options"]]
8473
8479
  },
8480
+ {
8481
+ name: "resumeTool",
8482
+ signatures: [["token","callback"]]
8483
+ },
8474
8484
  {
8475
8485
  name: "TaskController",
8476
8486
  signatures: [["?init"]]
@@ -24,6 +24,21 @@ export class EventsSerializer {
24
24
  }
25
25
 
26
26
  const rawEvents = Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager().getRawTraceEvents();
27
+
28
+ if (Types.Events.isSyntheticLayoutShiftCluster(event)) {
29
+ // A cluster has no raw event of its own, so it is keyed by the raw event
30
+ // of its first layout shift.
31
+ const firstShift = event.events.at(0);
32
+ if (!firstShift) {
33
+ return null;
34
+ }
35
+ const firstShiftIndex = rawEvents.indexOf(firstShift.rawSourceEvent);
36
+ if (firstShiftIndex === -1) {
37
+ return null;
38
+ }
39
+ return `${Types.File.EventKeyType.LAYOUT_SHIFT_CLUSTER}-${firstShiftIndex}`;
40
+ }
41
+
27
42
  const isSynthetic = Types.Events.isSyntheticBased(event);
28
43
  const index = rawEvents.indexOf(isSynthetic ? event.rawSourceEvent : event);
29
44
  if (index === -1) {
@@ -54,6 +69,20 @@ export class EventsSerializer {
54
69
  return event;
55
70
  }
56
71
 
72
+ if (EventsSerializer.isLayoutShiftClusterKey(eventValues)) {
73
+ const rawEvents = Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager().getRawTraceEvents();
74
+ const firstShiftRawEvent = rawEvents.at(eventValues.rawIndex);
75
+ const cluster = parsedTrace.data.LayoutShifts.clusters.find(cluster => {
76
+ const firstShift = cluster.events.at(0);
77
+ return firstShift !== undefined && firstShift.rawSourceEvent === firstShiftRawEvent;
78
+ });
79
+ if (!cluster) {
80
+ throw new Error(
81
+ `Unknown trace event. Could not find layout shift cluster with first shift index ${eventValues.rawIndex}`);
82
+ }
83
+ return cluster;
84
+ }
85
+
57
86
  if (EventsSerializer.isSyntheticEventKey(eventValues)) {
58
87
  const syntheticEvents = Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager().getSyntheticTraces();
59
88
  const syntheticEvent = syntheticEvents.at(eventValues.rawIndex);
@@ -79,6 +108,10 @@ export class EventsSerializer {
79
108
  return key.type === Types.File.EventKeyType.LEGACY_TIMELINE_FRAME;
80
109
  }
81
110
 
111
+ static isLayoutShiftClusterKey(key: Types.File.SerializableKeyValues): key is Types.File.LayoutShiftClusterKeyValues {
112
+ return key.type === Types.File.EventKeyType.LAYOUT_SHIFT_CLUSTER;
113
+ }
114
+
82
115
  static isRawEventKey(key: Types.File.SerializableKeyValues): key is Types.File.RawEventKeyValues {
83
116
  return key.type === Types.File.EventKeyType.RAW_EVENT;
84
117
  }
@@ -86,8 +119,8 @@ export class EventsSerializer {
86
119
  return key.type === Types.File.EventKeyType.SYNTHETIC_EVENT;
87
120
  }
88
121
 
89
- #getModifiedProfileCallByKeyValues(key: Types.File.ProfileCallKeyValues, parsedTrace: ParsedTrace):
90
- Types.Events.SyntheticProfileCall {
122
+ #getModifiedProfileCallByKeyValues(key: Types.File.ProfileCallKeyValues,
123
+ parsedTrace: ParsedTrace): Types.Events.SyntheticProfileCall {
91
124
  const cacheResult = this.#modifiedProfileCallByKey.get(key);
92
125
  if (cacheResult) {
93
126
  return cacheResult;