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.
- package/.agents/rules/models-and-core/core-ai-agent-context-and-prompt-discipline.md +29 -0
- package/.agents/rules/models-and-core/core-cdp-and-extension-error-handling.md +34 -0
- package/.agents/rules/models-and-core/core-gn-build-and-module-layering.md +23 -0
- package/.agents/rules/models-and-core/core-runtime-neutrality-and-platform-utils.md +28 -0
- package/.agents/rules/models-and-core/core-sdk-model-and-target-lifecycle.md +35 -0
- package/.agents/rules/models-and-core/core-security-origin-and-capability-guards.md +33 -0
- package/.agents/rules/models-and-core/core-settings-and-storage-migration.md +31 -0
- package/.agents/rules/models-and-core/core-sourcemap-and-workspace-mapping.md +28 -0
- package/.agents/rules/models-and-core/core-trace-engine-handler-invariants.md +32 -0
- package/.agents/rules/models-and-core/core-trace-insight-models-and-timing-types.md +28 -0
- package/.agents/rules/tests/test-cleanup-mutated-globals-and-widgets.md +40 -0
- package/.agents/rules/tests/test-deterministic-async-synchronization.md +30 -0
- package/.agents/rules/tests/test-modular-hooks-and-test-universe.md +38 -0
- package/.agents/rules/tests/test-public-api-and-encapsulation.md +30 -0
- package/.agents/rules/tests/test-shared-fixture-and-helper-reuse.md +29 -0
- package/.agents/rules/tests/test-single-responsibility-and-conciseness.md +37 -0
- package/.agents/rules/tests/test-strict-assertions-and-literal-expectations.md +31 -0
- package/.agents/rules/tests/test-type-safe-mocks-and-events.md +30 -0
- package/.agents/rules/tests/test-view-and-presenter-isolation.md +32 -0
- package/.agents/rules/ui-and-widgets/ui-accessibility-and-semantic-html.md +32 -0
- package/.agents/rules/ui-and-widgets/ui-await-update-complete-post-render.md +30 -0
- package/.agents/rules/ui-and-widgets/ui-css-scoping-and-flex-layout.md +27 -0
- package/.agents/rules/ui-and-widgets/ui-declarative-child-widget-composition.md +29 -0
- package/.agents/rules/ui-and-widgets/ui-lit-declarative-templates-and-directives.md +33 -0
- package/.agents/rules/ui-and-widgets/ui-localization-and-uistrings-hygiene.md +36 -0
- package/.agents/rules/ui-and-widgets/ui-modern-component-and-encapsulation-standards.md +32 -0
- package/.agents/rules/ui-and-widgets/ui-panel-and-meta-registration.md +35 -0
- package/.agents/rules/ui-and-widgets/ui-performance-and-flamechart-rendering.md +34 -0
- package/.agents/rules/ui-and-widgets/ui-pure-view-and-presenter-separation.md +31 -0
- package/.agents/rules/ui-and-widgets/ui-reactive-widget-update-lifecycle.md +34 -0
- package/.agents/rules/ui-and-widgets/ui-security-and-output-sanitization.md +28 -0
- package/.agents/rules/ui-and-widgets/ui-type-safety-and-exhaustiveness.md +37 -0
- package/.agents/rules/ui-and-widgets/ui-view-output-and-callback-contracts.md +35 -0
- package/.agents/rules/ui-and-widgets/ui-visual-logging-instrumentation.md +29 -0
- package/.agents/rules/ui-and-widgets/ui-weak-dom-references-and-observer-cleanup.md +29 -0
- package/.agents/rules/ui-and-widgets/ui-widget-dom-and-listener-lifecycle.md +38 -0
- package/.agents/skills/code-review/SKILL.md +3 -0
- package/.agents/skills/devtools-testing-guidance/SKILL.md +1 -0
- package/.agents/skills/review-models-core/SKILL.md +73 -0
- package/.agents/skills/review-tests/SKILL.md +67 -0
- package/.agents/skills/review-ui-widgets/SKILL.md +115 -0
- package/.agents/skills/ui-eng-vision-local-lit-renderer/SKILL.md +19 -3
- package/.agents/skills/ui-eng-vision-widget-promoter/SKILL.md +2 -1
- package/.agents/skills/ui-widgets/SKILL.md +3 -1
- package/AUTHORS +3 -0
- package/DIR_METADATA +51 -1
- package/eslint.config.mjs +63 -21
- package/front_end/core/platform/api/HostRuntime.ts +1 -0
- package/front_end/core/platform/browser/HostRuntime.ts +10 -0
- package/front_end/core/platform/node/HostRuntime.ts +1 -0
- package/front_end/core/sdk/CSSMatchedStyles.ts +60 -20
- package/front_end/core/sdk/CSSProperty.ts +2 -2
- package/front_end/core/sdk/CSSPropertyParserMatchers.ts +28 -9
- package/front_end/core/sdk/NetworkManager.ts +9 -3
- package/front_end/core/sdk/OverlayModel.ts +2 -8
- package/front_end/core/sdk/PrivateVerificationTokensModel.ts +79 -0
- package/front_end/core/sdk/SecurityOrigin.ts +1 -1
- package/front_end/core/sdk/SourceMapCache.ts +20 -15
- package/front_end/core/sdk/SourceMapManager.ts +28 -9
- package/front_end/core/sdk/TargetManager.ts +7 -4
- package/front_end/core/sdk/WebAuthnModel.ts +11 -2
- package/front_end/core/sdk/sdk.ts +2 -0
- package/front_end/entrypoints/inspector_main/InspectorMain.ts +0 -2
- package/front_end/entrypoints/inspector_main/inspector_main-meta.ts +10 -0
- package/front_end/entrypoints/main/GlobalAiButton.ts +1 -1
- package/front_end/entrypoints/main/MainImpl.ts +5 -2
- package/front_end/foundation/Universe.ts +1 -1
- package/front_end/generated/Deprecation.ts +4 -0
- package/front_end/generated/InspectorBackendCommands.ts +3 -3
- package/front_end/generated/SupportedCSSProperties.ts +89 -17
- package/front_end/generated/protocol-mapping.d.ts +1 -0
- package/front_end/generated/protocol-proxy-api.d.ts +1 -0
- package/front_end/generated/protocol.ts +5 -3
- package/front_end/models/{ai_assistance → ai-utils}/AiHistoryStorage.ts +6 -5
- package/front_end/models/{ai_assistance → ai-utils}/AiUtils.ts +9 -0
- package/front_end/models/{ai_assistance → ai-utils}/BuiltInAi.ts +1 -1
- package/front_end/models/ai-utils/ai-utils.ts +17 -0
- package/front_end/models/ai_assistance/AiAgent2.ts +3 -1
- package/front_end/models/ai_assistance/AiConversation.ts +34 -22
- package/front_end/models/ai_assistance/AlwaysAllowedTools.ts +107 -0
- package/front_end/models/ai_assistance/ConversationSummary.ts +2 -1
- package/front_end/models/ai_assistance/PerformanceAnnotations.ts +3 -1
- package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +3 -1
- package/front_end/models/ai_assistance/agents/AiAgent.ts +15 -7
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +3 -1
- package/front_end/models/ai_assistance/agents/ExecuteJavascript.ts +3 -1
- package/front_end/models/ai_assistance/agents/PerformanceAgent.snapshot.txt +1 -1
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +3 -1
- package/front_end/models/ai_assistance/ai_assistance.ts +9 -10
- package/front_end/models/ai_assistance/data_formatters/FileFormatter.ts +27 -6
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +3 -3
- package/front_end/models/ai_assistance/skills/sources.md +3 -1
- package/front_end/models/ai_assistance/tools/ExecuteJavaScript.ts +1 -0
- package/front_end/models/ai_assistance/tools/GetCookieValues.ts +1 -0
- package/front_end/models/ai_assistance/tools/GetInsightDetails.ts +3 -1
- package/front_end/models/ai_assistance/tools/GetSourceContent.ts +46 -4
- package/front_end/models/ai_assistance/tools/GetStorageValues.ts +1 -0
- package/front_end/models/ai_assistance/tools/Tool.ts +6 -0
- package/front_end/models/breakpoints/BreakpointManager.ts +0 -4
- package/front_end/models/change_tracker/ChangeTracker.ts +2 -0
- package/front_end/models/comment_manager/CommentManager.ts +12 -0
- package/front_end/models/comment_manager/CommentThread.ts +21 -1
- package/front_end/models/elements/ChangeTrackingUtils.ts +37 -0
- package/front_end/models/elements/DOMChanges.ts +24 -36
- package/front_end/models/elements/StyleChanges.ts +97 -0
- package/front_end/models/elements/elements.ts +4 -0
- package/front_end/models/emulation/DeviceModeModel.ts +19 -0
- package/front_end/models/javascript_metadata/NativeFunctions.ts +11 -1
- package/front_end/models/trace/EventsSerializer.ts +35 -2
- package/front_end/models/trace/handlers/LayoutShiftsHandler.ts +17 -21
- package/front_end/models/trace/helpers/SyntheticEvents.ts +4 -2
- package/front_end/models/trace/lantern/core/NetworkAnalyzer.ts +12 -8
- package/front_end/models/trace/types/File.ts +20 -3
- package/front_end/models/trace/types/TraceEvents.ts +8 -3
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +14 -0
- package/front_end/panels/ai_assistance/README.md +1 -1
- package/front_end/panels/ai_assistance/ai_assistance-meta.ts +1 -1
- package/front_end/panels/ai_assistance/ai_assistance.ts +2 -0
- package/front_end/panels/ai_assistance/components/ChatInput.ts +5 -43
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +52 -147
- package/front_end/panels/ai_assistance/components/ChatView.ts +28 -3
- package/front_end/panels/ai_assistance/components/PermissionPrompt.ts +151 -0
- package/front_end/panels/ai_assistance/components/RelevantDataDisclaimer.ts +73 -0
- package/front_end/panels/ai_assistance/components/chatInput.css +0 -59
- package/front_end/panels/ai_assistance/components/chatMessage.css +0 -47
- package/front_end/panels/ai_assistance/components/chatView.css +5 -30
- package/front_end/panels/ai_assistance/components/permissionPrompt.css +55 -0
- package/front_end/panels/ai_assistance/components/relevantDataDisclaimer.css +35 -0
- package/front_end/panels/application/ApplicationPanelSidebar.ts +3 -7
- package/front_end/panels/application/BackgroundServiceView.ts +8 -8
- package/front_end/panels/application/IndexedDBViews.ts +102 -73
- package/front_end/panels/application/OpenedWindowDetailsView.ts +167 -130
- package/front_end/panels/application/ServiceWorkerCacheViews.ts +288 -346
- package/front_end/panels/application/StorageBucketsTreeElement.ts +22 -27
- package/front_end/panels/application/StorageItemsToolbar.ts +2 -2
- package/front_end/panels/application/components/StorageMetadataView.ts +207 -160
- package/front_end/panels/application/openedWindowDetailsView.css +7 -30
- package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +1 -1
- package/front_end/panels/changes/changesView.css +0 -6
- package/front_end/panels/console/ConsoleInsightTeaser.ts +5 -1
- package/front_end/panels/console/ConsolePinPane.ts +1 -1
- package/front_end/panels/console/ConsoleView.ts +1 -0
- package/front_end/panels/elements/CSSValueTraceView.ts +5 -5
- package/front_end/panels/elements/ColorSwatchPopoverIcon.ts +14 -6
- package/front_end/panels/elements/ComputedStyleWidget.ts +14 -5
- package/front_end/panels/elements/DOMTreeElementWidget.ts +2 -2
- package/front_end/panels/elements/DOMTreeWidget.ts +7 -3
- package/front_end/panels/elements/EventListenersWidget.ts +1 -1
- package/front_end/panels/elements/LayersWidget.ts +1 -1
- package/front_end/panels/elements/PropertyRenderer.ts +91 -16
- package/front_end/panels/elements/StandaloneStylesContainer.ts +33 -6
- package/front_end/panels/elements/StylePropertiesSection.ts +1 -0
- package/front_end/panels/elements/StylePropertyTreeElement.ts +211 -121
- package/front_end/panels/elements/StylesContainer.ts +2 -0
- package/front_end/panels/elements/StylesSidebarPane.ts +34 -16
- package/front_end/panels/elements/components/QueryContainer.ts +1 -1
- package/front_end/panels/elements/elementStatePaneWidget.css +1 -1
- package/front_end/panels/elements/stylePropertiesTreeOutline.css +1 -1
- package/front_end/panels/elements/stylesSidebarPane.css +4 -0
- package/front_end/panels/emulation/DeviceModeToolbar.ts +57 -25
- package/front_end/panels/emulation/DeviceModeView.ts +27 -1
- package/front_end/panels/emulation/InspectedPagePlaceholder.ts +6 -0
- package/front_end/panels/emulation/MediaQueryInspector.ts +14 -4
- package/front_end/panels/explain/components/ConsoleInsight.ts +2 -3
- package/front_end/panels/explain/explain-meta.ts +1 -1
- package/front_end/panels/issues/AffectedMetadataAllowedSitesView.ts +67 -34
- package/front_end/panels/issues/issues.ts +2 -0
- package/front_end/panels/layer_viewer/LayerTreeOutline.ts +7 -3
- package/front_end/panels/lighthouse/LighthouseController.ts +1 -1
- package/front_end/panels/media/PlayerMessagesView.ts +1 -1
- package/front_end/panels/mobile_throttling/CPUThrottlingSelector.ts +1 -1
- package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +45 -15
- package/front_end/panels/mobile_throttling/ThrottlingManager.ts +3 -3
- package/front_end/panels/network/BinaryResourceView.ts +54 -50
- package/front_end/panels/network/RequestHeadersView.ts +6 -2
- package/front_end/panels/network/RequestPreviewView.ts +28 -5
- package/front_end/panels/network/ResourceWebSocketFrameView.ts +1 -0
- package/front_end/panels/network/components/EditableSpan.ts +11 -30
- package/front_end/panels/network/components/HeaderSectionRow.ts +2 -2
- package/front_end/panels/performance_monitor/PerformanceMonitor.ts +10 -6
- package/front_end/panels/profiler/HeapDetachedElementsView.ts +112 -22
- package/front_end/panels/profiler/HeapProfileView.ts +3 -3
- package/front_end/panels/profiler/HeapSnapshotView.ts +12 -2
- package/front_end/panels/profiler/HeapTimelineOverview.ts +16 -2
- package/front_end/panels/profiler/profiler.ts +0 -2
- package/front_end/panels/protocol_monitor/JSONEditor.ts +1 -1
- package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +1 -1
- package/front_end/panels/recorder/CreateRecordingView.ts +1 -1
- package/front_end/panels/recorder/RecordingView.ts +3 -3
- package/front_end/panels/recorder/ReplaySection.ts +1 -1
- package/front_end/panels/screencast/ScreencastApp.ts +83 -57
- package/front_end/panels/screencast/screencastView.css +1 -1
- package/front_end/panels/settings/AISettingsTab.ts +107 -4
- package/front_end/panels/settings/aiSettingsTab.css +53 -0
- package/front_end/panels/settings/settings-meta.ts +1 -1
- package/front_end/panels/settings/settingsScreen.css +0 -4
- package/front_end/panels/sources/BreakpointsView.ts +2 -2
- package/front_end/panels/sources/DebuggerPlugin.ts +7 -0
- package/front_end/panels/sources/NavigatorView.ts +61 -18
- package/front_end/panels/sources/SourcesNavigator.ts +22 -7
- package/front_end/panels/sources/SourcesPanel.ts +1 -0
- package/front_end/panels/timeline/README.md +12 -0
- package/front_end/panels/timeline/StatusDialog.ts +1 -1
- package/front_end/panels/timeline/ThirdPartyTreeView.ts +1 -3
- package/front_end/panels/timeline/TimelineCommentController.ts +346 -0
- package/front_end/panels/timeline/TimelineDetailsView.ts +24 -1
- package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +34 -30
- package/front_end/panels/timeline/TimelineFlameChartView.ts +22 -1
- package/front_end/panels/timeline/TimelinePanel.ts +12 -5
- package/front_end/panels/timeline/TimelineTreeView.ts +28 -6
- package/front_end/panels/timeline/components/LiveMetricsView.ts +1 -1
- package/front_end/panels/timeline/components/fieldSettingsDialog.css +2 -2
- package/front_end/panels/timeline/components/insights/baseInsightComponent.css +1 -1
- package/front_end/panels/timeline/overlays/components/entriesLinkOverlay.css +2 -2
- package/front_end/panels/timeline/overlays/components/entryLabelOverlay.css +9 -9
- package/front_end/panels/timeline/timeline-meta.ts +2 -2
- package/front_end/panels/timeline/timeline.ts +4 -0
- package/front_end/panels/timeline/timelineFlamechartPopover.css +2 -2
- package/front_end/panels/timeline/timelinePanel.css +2 -2
- package/front_end/panels/web_audio/WebAudioView.ts +7 -4
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/codemirror.next/chunk/angular.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/angular.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/codemirror.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/codemirror.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/cpp.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/cpp.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/java.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/java.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/less.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/less.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/markdown.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/markdown.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/php.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/php.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/python.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/python.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/sass.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/sass.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/svelte.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/svelte.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/vue.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/vue.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/wast.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/wast.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/xml.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/xml.js.map +1 -1
- package/front_end/third_party/codemirror.next/codemirror.next.js +1 -1
- package/front_end/third_party/codemirror.next/rollup.config.mjs +1 -1
- package/front_end/tsconfig.json +1 -1
- package/front_end/ui/comments/CommentAnchorResolver.ts +1 -1
- package/front_end/ui/components/buttons/Button.ts +29 -18
- package/front_end/ui/components/code_highlighter/CodeHighlighter.ts +1 -1
- package/front_end/ui/components/dialogs/TypeToAllowDialog.ts +94 -39
- package/front_end/ui/components/dialogs/dialog.css +1 -1
- package/front_end/ui/components/menus/menuItem.css +11 -0
- package/front_end/ui/components/text_editor/AccessiblePlaceholder.ts +1 -1
- package/front_end/ui/components/text_editor/AiCodeCompletionTeaser.ts +1 -1
- package/front_end/ui/components/text_editor/config.ts +2 -1
- package/front_end/ui/components/text_editor/javascript.ts +2 -1
- package/front_end/ui/legacy/InspectorView.ts +4 -2
- package/front_end/ui/legacy/SplitWidget.ts +14 -16
- package/front_end/ui/legacy/TabbedPane.ts +9 -1
- package/front_end/ui/legacy/UIUtils.ts +60 -40
- package/front_end/ui/legacy/components/color_picker/spectrum.css +2 -2
- package/front_end/ui/legacy/components/data_grid/dataGrid.css +9 -0
- package/front_end/ui/legacy/components/inline_editor/CSSAngle.ts +0 -1
- package/front_end/ui/legacy/components/inline_editor/cssShadowEditor.css +5 -7
- package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +1 -1
- package/front_end/ui/legacy/components/perf_ui/PieChart.ts +11 -0
- package/front_end/ui/legacy/components/perf_ui/chartViewport.css +4 -4
- package/front_end/ui/legacy/components/quick_open/filteredListWidget.css +6 -0
- package/front_end/ui/legacy/components/settings_ui/SettingsUI.ts +1 -1
- package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +38 -13
- package/front_end/ui/legacy/dropTarget.css +1 -1
- package/front_end/ui/legacy/statusBar.css +7 -0
- package/front_end/ui/legacy/tabbedPane.css +0 -7
- package/front_end/ui/visual_logging/KnownContextValues.ts +13 -0
- package/inspector_overlay/main.ts +2 -15
- package/inspector_overlay/tool_persistent.ts +0 -14
- package/mcp/mcp.ts +3 -0
- package/package.json +1 -1
- package/front_end/panels/ai_assistance/components/StylingAgentMarkdownRenderer.ts +0 -178
- package/front_end/panels/profiler/HeapDetachedElementsDataGrid.ts +0 -147
- package/front_end/panels/profiler/heapDetachedElementsDataGrid.css +0 -14
- package/front_end/ui/components/legacy_wrapper/LegacyWrapper.ts +0 -62
- package/front_end/ui/components/legacy_wrapper/legacy_wrapper.ts +0 -8
- package/inspector_overlay/tool_green_dev_anchors.css +0 -54
- package/inspector_overlay/tool_green_dev_anchors.ts +0 -164
- /package/front_end/models/{ai_assistance → ai-utils}/AiSetting.ts +0 -0
- /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:
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
26
|
-
|
|
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),
|
|
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),
|
|
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),
|
|
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()),
|
|
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),
|
|
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),
|
|
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()),
|
|
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),
|
|
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()),
|
|
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),
|
|
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,
|
|
90
|
-
|
|
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;
|