chrome-devtools-frontend 1.0.1682249 → 1.0.1684555

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 (103) hide show
  1. package/AUTHORS +1 -0
  2. package/front_end/core/sdk/ServiceWorkerCacheModel.ts +0 -7
  3. package/front_end/core/sdk/StorageBucketsModel.ts +0 -6
  4. package/front_end/entrypoints/inspector_main/InspectorMain.ts +2 -1
  5. package/front_end/entrypoints/inspector_main/inspector_main-meta.ts +1 -5
  6. package/front_end/entrypoints/main/MainImpl.ts +6 -4
  7. package/front_end/entrypoints/main/main-meta.ts +9 -51
  8. package/front_end/foundation/Universe.ts +7 -0
  9. package/front_end/generated/InspectorBackendCommands.ts +12 -22
  10. package/front_end/generated/protocol-mapping.d.ts +9 -59
  11. package/front_end/generated/protocol-proxy-api.d.ts +7 -47
  12. package/front_end/generated/protocol.ts +105 -330
  13. package/front_end/models/ai_assistance/AiAgent2.ts +12 -4
  14. package/front_end/models/ai_assistance/AiConversation.ts +25 -7
  15. package/front_end/models/ai_assistance/agents/AiAgent.ts +11 -19
  16. package/front_end/models/ai_assistance/agents/StorageAgent.ts +6 -6
  17. package/front_end/models/ai_assistance/ai_assistance.ts +4 -0
  18. package/front_end/models/ai_assistance/tools/GetLighthouseAudits.ts +12 -6
  19. package/front_end/models/ai_assistance/tools/GetStorageValues.ts +1 -1
  20. package/front_end/models/ai_assistance/tools/ListStorageKeys.ts +1 -1
  21. package/front_end/models/ai_assistance/tools/RunLighthouse.ts +5 -8
  22. package/front_end/models/ai_assistance/tools/Tool.ts +19 -6
  23. package/front_end/models/issues_manager/DOMIssuesManager.ts +144 -0
  24. package/front_end/models/issues_manager/ElementAccessibilityIssue.ts +13 -1
  25. package/front_end/models/issues_manager/GenericIssue.ts +14 -2
  26. package/front_end/models/issues_manager/IssuesManager.ts +0 -1
  27. package/front_end/models/issues_manager/issues_manager.ts +2 -0
  28. package/front_end/models/javascript_metadata/NativeFunctions.js +8 -0
  29. package/front_end/models/trace/Processor.ts +1 -0
  30. package/front_end/panels/ai_assistance/ExternalHandler.ts +89 -0
  31. package/front_end/panels/ai_assistance/ai_assistance.ts +1 -0
  32. package/front_end/panels/application/BackgroundServiceModel.ts +4 -3
  33. package/front_end/panels/application/IndexedDBModel.ts +0 -7
  34. package/front_end/panels/console/ConsoleView.ts +17 -16
  35. package/front_end/panels/console/ConsoleViewMessage.ts +4 -1
  36. package/front_end/panels/console/console-meta.ts +4 -19
  37. package/front_end/panels/elements/ElementIssueUtils.ts +10 -2
  38. package/front_end/panels/elements/ElementsPanel.ts +8 -3
  39. package/front_end/panels/elements/ElementsTreeElement.ts +82 -161
  40. package/front_end/panels/elements/ElementsTreeOutline.ts +26 -105
  41. package/front_end/panels/elements/StandaloneStylesContainer.ts +5 -11
  42. package/front_end/panels/elements/StylePropertyTreeElement.ts +2 -0
  43. package/front_end/panels/elements/StylesContainer.ts +1 -0
  44. package/front_end/panels/elements/StylesSidebarPane.ts +174 -151
  45. package/front_end/panels/network/RequestPayloadView.ts +5 -2
  46. package/front_end/panels/security/SecurityPanelSidebar.ts +0 -32
  47. package/front_end/panels/settings/KeybindsSettingsTab.ts +5 -2
  48. package/front_end/panels/sources/SourcesPanel.ts +6 -3
  49. package/front_end/panels/timeline/components/BreadcrumbsUI.ts +2 -6
  50. package/front_end/panels/timeline/components/CWVMetrics.ts +9 -10
  51. package/front_end/panels/timeline/components/DetailsView.ts +12 -16
  52. package/front_end/panels/timeline/components/ExportTraceOptions.ts +13 -13
  53. package/front_end/panels/timeline/components/FieldSettingsDialog.ts +19 -19
  54. package/front_end/panels/timeline/components/IgnoreListSetting.ts +7 -9
  55. package/front_end/panels/timeline/components/InteractionBreakdown.ts +3 -3
  56. package/front_end/panels/timeline/components/LayoutShiftDetails.ts +13 -13
  57. package/front_end/panels/timeline/components/LiveMetricsView.ts +64 -64
  58. package/front_end/panels/timeline/components/MetricCard.ts +25 -25
  59. package/front_end/panels/timeline/components/NetworkRequestDetails.ts +22 -22
  60. package/front_end/panels/timeline/components/NetworkRequestTooltip.ts +9 -9
  61. package/front_end/panels/timeline/components/OriginMap.ts +7 -7
  62. package/front_end/panels/timeline/components/RelatedInsightChips.ts +2 -2
  63. package/front_end/panels/timeline/components/SidebarAnnotationsTab.ts +19 -20
  64. package/front_end/panels/timeline/components/SidebarSingleInsightSet.ts +1 -1
  65. package/front_end/panels/timeline/components/TimelineSummary.ts +2 -2
  66. package/front_end/panels/timeline/components/Utils.ts +2 -6
  67. package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +6 -9
  68. package/front_end/panels/timeline/components/insights/Checklist.ts +2 -2
  69. package/front_end/panels/timeline/components/insights/Table.ts +1 -1
  70. package/front_end/third_party/chromium/README.chromium +1 -1
  71. package/front_end/ui/comments/CommentAnchorResolver.ts +94 -0
  72. package/front_end/ui/comments/CommentOverlayManager.ts +16 -32
  73. package/front_end/ui/components/text_editor/config.ts +2 -1
  74. package/front_end/ui/legacy/DockController.ts +4 -1
  75. package/front_end/ui/legacy/InspectorView.ts +3 -1
  76. package/front_end/ui/legacy/KeyboardShortcut.ts +4 -7
  77. package/front_end/ui/legacy/SearchableView.ts +2 -1
  78. package/front_end/ui/legacy/ShortcutRegistry.ts +6 -3
  79. package/front_end/ui/legacy/UIUtils.ts +10 -6
  80. package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +23 -24
  81. package/front_end/ui/legacy/components/perf_ui/BrickBreaker.ts +2 -2
  82. package/front_end/ui/legacy/components/perf_ui/FilmStripView.ts +6 -6
  83. package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +14 -15
  84. package/front_end/ui/legacy/components/perf_ui/GCActionDelegate.ts +1 -1
  85. package/front_end/ui/legacy/components/perf_ui/NetworkPriorities.ts +5 -5
  86. package/front_end/ui/legacy/components/perf_ui/OverviewGrid.ts +5 -5
  87. package/front_end/ui/legacy/components/perf_ui/PieChart.ts +1 -1
  88. package/front_end/ui/legacy/components/perf_ui/perf_ui-meta.ts +4 -6
  89. package/front_end/ui/legacy/components/source_frame/FontView.ts +2 -2
  90. package/front_end/ui/legacy/components/source_frame/ImageView.ts +13 -13
  91. package/front_end/ui/legacy/components/source_frame/JSONView.ts +1 -1
  92. package/front_end/ui/legacy/components/source_frame/PreviewFactory.ts +2 -2
  93. package/front_end/ui/legacy/components/source_frame/ResourceSourceFrame.ts +1 -1
  94. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +15 -18
  95. package/front_end/ui/legacy/components/source_frame/XMLView.ts +1 -1
  96. package/front_end/ui/legacy/components/source_frame/source_frame-meta.ts +10 -10
  97. package/front_end/ui/legacy/theme_support/ThemeSupport.ts +5 -2
  98. package/front_end/ui/settings/ConsoleSettings.ts +32 -0
  99. package/front_end/ui/settings/InspectorMainSettings.ts +7 -0
  100. package/front_end/ui/settings/MainSettings.ts +80 -0
  101. package/front_end/ui/settings/settings.ts +4 -0
  102. package/front_end/ui/visual_logging/KnownContextValues.ts +8 -0
  103. package/package.json +1 -1
@@ -202,7 +202,7 @@ export class StorageAgent extends AiAgent<StorageItem> {
202
202
  },
203
203
 
204
204
  handler: async args => {
205
- this.setServerSideLoggingActive(false);
205
+ this.disableServerSideLogging();
206
206
  if (!isSamePrimaryPageOrigin(this.targetManager, this.context)) {
207
207
  return {error: 'No origin available or not allowed.'};
208
208
  }
@@ -288,7 +288,7 @@ export class StorageAgent extends AiAgent<StorageItem> {
288
288
  },
289
289
 
290
290
  handler: async (args, options) => {
291
- this.setServerSideLoggingActive(false);
291
+ this.disableServerSideLogging();
292
292
  if (!isSamePrimaryPageOrigin(this.targetManager, this.context)) {
293
293
  return {error: 'No origin available or not allowed.'};
294
294
  }
@@ -388,7 +388,7 @@ export class StorageAgent extends AiAgent<StorageItem> {
388
388
  };
389
389
  },
390
390
  handler: async args => {
391
- this.setServerSideLoggingActive(false);
391
+ this.disableServerSideLogging();
392
392
  if (!isSamePrimaryPageOrigin(this.targetManager, this.context)) {
393
393
  return {error: 'No origin available or not allowed.'};
394
394
  }
@@ -448,7 +448,7 @@ export class StorageAgent extends AiAgent<StorageItem> {
448
448
  };
449
449
  },
450
450
  handler: async (args, options) => {
451
- this.setServerSideLoggingActive(false);
451
+ this.disableServerSideLogging();
452
452
  if (!isSamePrimaryPageOrigin(this.targetManager, this.context)) {
453
453
  return {error: 'No origin available or not allowed.'};
454
454
  }
@@ -618,9 +618,9 @@ export class StorageAgent extends AiAgent<StorageItem> {
618
618
  protected override async preRun(): Promise<void> {
619
619
  const item = this.context?.getItem();
620
620
  if (item instanceof CookieItem && Boolean(item.name)) {
621
- this.setServerSideLoggingActive(false);
621
+ this.disableServerSideLogging();
622
622
  } else if (item instanceof DOMStorageItem && Boolean(item.key)) {
623
- this.setServerSideLoggingActive(false);
623
+ this.disableServerSideLogging();
624
624
  }
625
625
  }
626
626
 
@@ -38,6 +38,8 @@ import * as AICallTree from './performance/AICallTree.js';
38
38
  import * as AIContext from './performance/AIContext.js';
39
39
  import * as AIQueries from './performance/AIQueries.js';
40
40
  import * as PerformanceAnnotations from './PerformanceAnnotations.js';
41
+ import * as Skill from './skills/Skill.js';
42
+ import * as SkillRegistry from './skills/SkillRegistry.js';
41
43
  import * as StorageItem from './StorageItem.js';
42
44
  import * as DOMStorageUtils from './tools/DOMStorageUtils.js';
43
45
  import * as ExecuteJavaScript from './tools/ExecuteJavaScript.js';
@@ -122,6 +124,8 @@ export {
122
124
  ResolveDevtoolsNodePath,
123
125
  RunLighthouse,
124
126
  SelectTraceEventByKey,
127
+ Skill,
128
+ SkillRegistry,
125
129
  StorageAgent,
126
130
  StorageContext,
127
131
  StorageItem,
@@ -4,17 +4,23 @@
4
4
 
5
5
  import * as Host from '../../../core/host/host.js';
6
6
  import type * as LHModel from '../../lighthouse/lighthouse.js';
7
- import {AccessibilityContext} from '../contexts/AccessibilityContext.js';
8
7
  import {LighthouseFormatter} from '../data_formatters/LighthouseFormatter.js';
9
8
 
10
- import {type BaseToolCapability, type DataHandlerResult, type DataTool, type ToolArgs, ToolName} from './Tool.js';
9
+ import {
10
+ type BaseToolCapability,
11
+ type DataHandlerResult,
12
+ type DataTool,
13
+ type LighthouseReportCapability,
14
+ type ToolArgs,
15
+ ToolName,
16
+ } from './Tool.js';
11
17
 
12
18
  export interface GetLighthouseAuditsArgs extends ToolArgs {
13
19
  categoryId: LHModel.RunTypes.CategoryId;
14
20
  }
15
21
 
16
22
  export class GetLighthouseAuditsTool implements
17
- DataTool<GetLighthouseAuditsArgs, {audits: string}, BaseToolCapability> {
23
+ DataTool<GetLighthouseAuditsArgs, {audits: string}, BaseToolCapability&LighthouseReportCapability> {
18
24
  readonly name = ToolName.GET_LIGHTHOUSE_AUDITS;
19
25
  readonly description = 'Returns the audits for a specific Lighthouse category.';
20
26
 
@@ -40,11 +46,11 @@ export class GetLighthouseAuditsTool implements
40
46
  }
41
47
 
42
48
  async handler(params: GetLighthouseAuditsArgs,
43
- context: BaseToolCapability): Promise<DataHandlerResult<{audits: string}>> {
44
- if (!(context.conversationContext instanceof AccessibilityContext)) {
49
+ context: BaseToolCapability&LighthouseReportCapability): Promise<DataHandlerResult<{audits: string}>> {
50
+ const report = context.getLighthouseReport();
51
+ if (!report) {
45
52
  return {error: 'Error: Active context is not a Lighthouse report.'};
46
53
  }
47
- const report = context.conversationContext.getItem();
48
54
  const audits = new LighthouseFormatter().audits(report, params.categoryId);
49
55
  return {
50
56
  result: {audits},
@@ -97,7 +97,7 @@ export class GetStorageValuesTool implements DataTool<GetStorageValuesArgs, GetS
97
97
  context: BaseToolCapability&OriginLockCapability&ServerLoggingCapability,
98
98
  options?: FunctionHandlerOptions,
99
99
  ): Promise<DataHandlerResult<GetStorageValuesResult>> {
100
- context.setLoggingEnabled(false);
100
+ context.disableLogging();
101
101
 
102
102
  // eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
103
103
  const targetManager = SDK.TargetManager.TargetManager.instance();
@@ -84,7 +84,7 @@ export class ListStorageKeysTool implements DataTool<ListStorageKeysArgs, ListSt
84
84
  args: ListStorageKeysArgs,
85
85
  context: BaseToolCapability&OriginLockCapability&ServerLoggingCapability,
86
86
  ): Promise<DataHandlerResult<ListStorageKeysResult>> {
87
- context.setLoggingEnabled(false);
87
+ context.disableLogging();
88
88
 
89
89
  // eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
90
90
  const targetManager = SDK.TargetManager.TargetManager.instance();
@@ -10,7 +10,7 @@ import {
10
10
  type BaseToolCapability,
11
11
  type DataHandlerResult,
12
12
  type DataTool,
13
- type LighthouseCapability,
13
+ type LighthouseRecordingCapability,
14
14
  type ToolArgs,
15
15
  ToolName,
16
16
  } from './Tool.js';
@@ -22,7 +22,7 @@ export interface RunLighthouseArgs extends ToolArgs {
22
22
  }
23
23
 
24
24
  export class RunLighthouseTool implements
25
- DataTool<RunLighthouseArgs, {audits: string}, BaseToolCapability&LighthouseCapability> {
25
+ DataTool<RunLighthouseArgs, {audits: string}, BaseToolCapability&LighthouseRecordingCapability> {
26
26
  readonly name = ToolName.RUN_LIGHTHOUSE;
27
27
  readonly description =
28
28
  'Runs Lighthouse audits on the active page. Supports "navigation" (for full initial page load audits), "snapshot" (for inspecting live in-page modifications without reload), and "timespan" (for interactions).';
@@ -60,14 +60,11 @@ export class RunLighthouseTool implements
60
60
  };
61
61
  }
62
62
 
63
- async handler(params: RunLighthouseArgs,
64
- context: BaseToolCapability&LighthouseCapability): Promise<DataHandlerResult<{audits: string}>> {
65
- if (!context.lighthouseRecording) {
66
- return {error: 'Error: Lighthouse recording capability is not available.'};
67
- }
63
+ async handler(params: RunLighthouseArgs, context: BaseToolCapability&LighthouseRecordingCapability):
64
+ Promise<DataHandlerResult<{audits: string}>> {
68
65
  const mode = params.mode ?? 'snapshot';
69
66
  try {
70
- const report = await context.lighthouseRecording({
67
+ const report = await context.runLighthouse({
71
68
  mode,
72
69
  categoryIds: [params.category],
73
70
  isAIControlled: true,
@@ -122,10 +122,17 @@ export interface OriginLockCapability {
122
122
  }
123
123
 
124
124
  /**
125
- * Capability for tools that need to run or query Lighthouse audits.
125
+ * Capability for tools that need to inspect an active Lighthouse report from context.
126
126
  */
127
- export interface LighthouseCapability {
128
- lighthouseRecording?: (overrides?: LHModel.RunTypes.RunOverrides) => Promise<LHModel.ReporterTypes.ReportJSON|null>;
127
+ export interface LighthouseReportCapability {
128
+ getLighthouseReport(): LHModel.ReporterTypes.ReportJSON|null;
129
+ }
130
+
131
+ /**
132
+ * Capability for tools that trigger new Lighthouse audit runs.
133
+ */
134
+ export interface LighthouseRecordingCapability {
135
+ runLighthouse(overrides?: LHModel.RunTypes.RunOverrides): Promise<LHModel.ReporterTypes.ReportJSON|null>;
129
136
  }
130
137
 
131
138
  /**
@@ -139,8 +146,9 @@ export interface PerformanceRecordingCapability {
139
146
  * Unified context interface providing all capabilities available in the project.
140
147
  * Used by the agent to pass a complete context to any tool type-safely.
141
148
  */
142
- export type AllToolsCapabilities = BaseToolCapability&PageExecutionCapability&StyleMutationCapability&TargetCapability&
143
- OriginLockCapability&LighthouseCapability&PerformanceRecordingCapability&ServerLoggingCapability;
149
+ export type AllToolsCapabilities =
150
+ BaseToolCapability&PageExecutionCapability&StyleMutationCapability&TargetCapability&OriginLockCapability&
151
+ LighthouseReportCapability&LighthouseRecordingCapability&PerformanceRecordingCapability&ServerLoggingCapability;
144
152
 
145
153
  /**
146
154
  * Base argument type for AI Tools.
@@ -263,8 +271,13 @@ export type Tool<
263
271
  CapabilitiesType extends BaseToolCapability = BaseToolCapability,
264
272
  > = DataTool<ArgsType, ReturnType, CapabilitiesType>|ContextTool<ArgsType, ReturnType, CapabilitiesType>;
265
273
 
274
+ /**
275
+ * Capability provided to tools that handle sensitive user data (e.g. cookies or storage values).
276
+ * Calling `disableLogging()` irreversibly disables server-side logging for the remainder of
277
+ * the conversation session to prevent sensitive data from being logged on future turns.
278
+ */
266
279
  export interface ServerLoggingCapability {
267
- setLoggingEnabled(enabled: boolean): void;
280
+ disableLogging(): void;
268
281
  }
269
282
 
270
283
  export const enum ToolAnnotation {
@@ -0,0 +1,144 @@
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 Common from '../../core/common/common.js';
6
+ import * as Platform from '../../core/platform/platform.js';
7
+ import * as SDK from '../../core/sdk/sdk.js';
8
+ import type * as Protocol from '../../generated/protocol.js';
9
+
10
+ import type {Issue} from './Issue.js';
11
+ import type {IssueAddedEvent, IssueHiddenStatusUpdatedEvent, IssuesManager} from './IssuesManager.js';
12
+ import {Events as IssuesManagerEvents} from './IssuesManagerEvents.js';
13
+
14
+ export const enum Events {
15
+ DOM_ISSUE_ADDED = 'DOMIssueAdded',
16
+ DOM_ISSUE_REMOVED = 'DOMIssueRemoved',
17
+ }
18
+
19
+ export interface EventTypes {
20
+ [Events.DOM_ISSUE_ADDED]: {node: SDK.DOMModel.DOMNode, issue: Issue};
21
+ [Events.DOM_ISSUE_REMOVED]: {node: SDK.DOMModel.DOMNode, issue: Issue};
22
+ }
23
+
24
+ export class DOMIssuesManager extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
25
+ readonly #issuesManager: IssuesManager;
26
+ readonly #targetManager: SDK.TargetManager.TargetManager;
27
+ #currentIssues = new Set<Issue>();
28
+ #nodeToIssues = new Platform.MapUtilities.Multimap<SDK.DOMModel.DOMNode, Issue>();
29
+ readonly #nodeIdSubscribers = new Platform.MapUtilities.Multimap<Protocol.DOM.NodeId, () => void>();
30
+
31
+ constructor(issuesManager: IssuesManager, targetManager: SDK.TargetManager.TargetManager) {
32
+ super();
33
+ this.#issuesManager = issuesManager;
34
+ this.#targetManager = targetManager;
35
+ this.#issuesManager.addEventListener(IssuesManagerEvents.ISSUE_ADDED, this.#onIssueAdded, this);
36
+ this.#issuesManager.addEventListener(IssuesManagerEvents.ISSUE_HIDDEN_STATUS_UPDATED,
37
+ this.#onIssueHiddenStatusUpdated, this);
38
+ this.#issuesManager.addEventListener(IssuesManagerEvents.FULL_UPDATE_REQUIRED, this.#onFullUpdateRequired, this);
39
+ this.#targetManager.addModelListener(SDK.DOMModel.DOMModel, SDK.DOMModel.Events.DocumentUpdated,
40
+ this.#onDocumentUpdated, this, {scoped: true});
41
+ }
42
+
43
+ subscribeByNodeId(nodeId: Protocol.DOM.NodeId, callback: () => void): void {
44
+ this.#nodeIdSubscribers.set(nodeId, callback);
45
+ }
46
+
47
+ unsubscribeByNodeId(nodeId: Protocol.DOM.NodeId, callback: () => void): void {
48
+ this.#nodeIdSubscribers.delete(nodeId, callback);
49
+ }
50
+
51
+ issuesForNode(node: SDK.DOMModel.DOMNode): Issue[] {
52
+ return Array.from(this.#nodeToIssues.get(node));
53
+ }
54
+
55
+ #onIssueAdded(event: Common.EventTarget.EventTargetEvent<IssueAddedEvent>): void {
56
+ void this.#addIssue(event.data.issue);
57
+ }
58
+
59
+ #onIssueHiddenStatusUpdated(event: Common.EventTarget.EventTargetEvent<IssueHiddenStatusUpdatedEvent>): void {
60
+ const {issue} = event.data;
61
+ if (issue.isHidden()) {
62
+ void this.#removeIssue(issue);
63
+ } else {
64
+ void this.#addIssue(issue);
65
+ }
66
+ }
67
+
68
+ #onFullUpdateRequired(): void {
69
+ const newIssues = new Set(this.#issuesManager.issues());
70
+ for (const issue of this.#currentIssues) {
71
+ if (!newIssues.has(issue) || issue.isHidden()) {
72
+ void this.#removeIssue(issue);
73
+ }
74
+ }
75
+ for (const issue of newIssues) {
76
+ if (!issue.isHidden()) {
77
+ void this.#addIssue(issue);
78
+ }
79
+ }
80
+ }
81
+
82
+ #onDocumentUpdated(_event: Common.EventTarget.EventTargetEvent<SDK.DOMModel.DOMModel>): void {
83
+ this.#nodeToIssues.clear();
84
+ for (const issue of this.#issuesManager.issues()) {
85
+ if (!issue.isHidden()) {
86
+ void this.#addIssue(issue);
87
+ }
88
+ }
89
+ }
90
+
91
+ async #resolveNodesForIssue(issue: Issue): Promise<SDK.DOMModel.DOMNode[]> {
92
+ const primaryTarget = this.#targetManager.primaryPageTarget() ?? this.#targetManager.targets()[0];
93
+ const nodes: SDK.DOMModel.DOMNode[] = [];
94
+ for (const element of issue.elements()) {
95
+ const elementTarget = (element.target && typeof (element.target as SDK.Target.Target).model === 'function') ?
96
+ (element.target as SDK.Target.Target) :
97
+ primaryTarget;
98
+ if (!elementTarget) {
99
+ continue;
100
+ }
101
+ const domModel = elementTarget.model(SDK.DOMModel.DOMModel);
102
+ if (!domModel) {
103
+ continue;
104
+ }
105
+ const deferredDOMNode = new SDK.DOMModel.DeferredDOMNode(elementTarget, element.backendNodeId);
106
+ const node = await deferredDOMNode.resolvePromise();
107
+ if (node) {
108
+ nodes.push(node);
109
+ }
110
+ }
111
+ return nodes;
112
+ }
113
+
114
+ async #addIssue(issue: Issue): Promise<void> {
115
+ if (issue.isHidden()) {
116
+ return;
117
+ }
118
+ this.#currentIssues.add(issue);
119
+ const nodes = await this.#resolveNodesForIssue(issue);
120
+ for (const node of nodes) {
121
+ if (!this.#nodeToIssues.hasValue(node, issue)) {
122
+ this.#nodeToIssues.set(node, issue);
123
+ this.dispatchEventToListeners(Events.DOM_ISSUE_ADDED, {node, issue});
124
+ for (const callback of this.#nodeIdSubscribers.get(node.id)) {
125
+ callback();
126
+ }
127
+ }
128
+ }
129
+ }
130
+
131
+ async #removeIssue(issue: Issue): Promise<void> {
132
+ this.#currentIssues.delete(issue);
133
+ const nodes = await this.#resolveNodesForIssue(issue);
134
+ for (const node of nodes) {
135
+ if (this.#nodeToIssues.hasValue(node, issue)) {
136
+ this.#nodeToIssues.delete(node, issue);
137
+ this.dispatchEventToListeners(Events.DOM_ISSUE_REMOVED, {node, issue});
138
+ for (const callback of this.#nodeIdSubscribers.get(node.id)) {
139
+ callback();
140
+ }
141
+ }
142
+ }
143
+ }
144
+ }
@@ -5,7 +5,7 @@
5
5
  import type * as SDK from '../../core/sdk/sdk.js';
6
6
  import * as Protocol from '../../generated/protocol.js';
7
7
 
8
- import {Issue, IssueCategory, IssueKind} from './Issue.js';
8
+ import {type AffectedElement, Issue, IssueCategory, IssueKind} from './Issue.js';
9
9
  import {
10
10
  type LazyMarkdownIssueDescription,
11
11
  type MarkdownIssueDescription,
@@ -23,6 +23,18 @@ export class ElementAccessibilityIssue extends Issue<Protocol.Audits.ElementAcce
23
23
  super(issueCode, issueDetails, issuesModel, issueId);
24
24
  }
25
25
 
26
+ override elements(): Iterable<AffectedElement> {
27
+ const details = this.details();
28
+ if (details.nodeId) {
29
+ return [{
30
+ backendNodeId: details.nodeId,
31
+ nodeName: '',
32
+ target: this.model()?.target() ?? null,
33
+ }];
34
+ }
35
+ return [];
36
+ }
37
+
26
38
  primaryKey(): string {
27
39
  return JSON.stringify(this.details());
28
40
  }
@@ -6,11 +6,11 @@ import * as i18n from '../../core/i18n/i18n.js';
6
6
  import type * as SDK from '../../core/sdk/sdk.js';
7
7
  import * as Protocol from '../../generated/protocol.js';
8
8
 
9
- import {Issue, IssueCategory, IssueKind} from './Issue.js';
9
+ import {type AffectedElement, Issue, IssueCategory, IssueKind} from './Issue.js';
10
10
  import {
11
- resolveLazyDescription,
12
11
  type LazyMarkdownIssueDescription,
13
12
  type MarkdownIssueDescription,
13
+ resolveLazyDescription,
14
14
  } from './MarkdownIssueDescription.js';
15
15
 
16
16
  const UIStrings = {
@@ -72,6 +72,18 @@ export class GenericIssue extends Issue<Protocol.Audits.GenericIssueDetails> {
72
72
  return [];
73
73
  }
74
74
 
75
+ override elements(): Iterable<AffectedElement> {
76
+ const details = this.details();
77
+ if (details.violatingNodeId) {
78
+ return [{
79
+ backendNodeId: details.violatingNodeId,
80
+ nodeName: '',
81
+ target: this.model()?.target() ?? null,
82
+ }];
83
+ }
84
+ return [];
85
+ }
86
+
75
87
  getCategory(): IssueCategory {
76
88
  return IssueCategory.GENERIC;
77
89
  }
@@ -233,7 +233,6 @@ export class IssuesManager extends Common.ObjectWrapper.ObjectWrapper<EventTypes
233
233
  #issuesByOutermostTarget: WeakMap<SDK.Target.Target, Set<Issue>> = new Map();
234
234
  #frameManager: SDK.FrameManager.FrameManager;
235
235
  #targetManager: SDK.TargetManager.TargetManager;
236
-
237
236
  constructor(
238
237
  private readonly showThirdPartyIssuesSetting?: Common.Settings.Setting<boolean>,
239
238
  private readonly hideIssueSetting?: Common.Settings.Setting<HideIssueMenuSetting>,
@@ -10,6 +10,7 @@ import * as CookieIssue from './CookieIssue.js';
10
10
  import * as CorsIssue from './CorsIssue.js';
11
11
  import * as CrossOriginEmbedderPolicyIssue from './CrossOriginEmbedderPolicyIssue.js';
12
12
  import * as DeprecationIssue from './DeprecationIssue.js';
13
+ import * as DOMIssuesManager from './DOMIssuesManager.js';
13
14
  import * as ElementAccessibilityIssue from './ElementAccessibilityIssue.js';
14
15
  import * as EmailVerificationRequestIssue from './EmailVerificationRequestIssue.js';
15
16
  import * as FederatedAuthRequestIssue from './FederatedAuthRequestIssue.js';
@@ -45,6 +46,7 @@ export {
45
46
  CorsIssue,
46
47
  CrossOriginEmbedderPolicyIssue,
47
48
  DeprecationIssue,
49
+ DOMIssuesManager,
48
50
  ElementAccessibilityIssue,
49
51
  EmailVerificationRequestIssue,
50
52
  FederatedAuthRequestIssue,
@@ -6718,6 +6718,10 @@ export const NativeFunctions = [
6718
6718
  name: "copyElementImageToTexture",
6719
6719
  signatures: [["source","destination"]]
6720
6720
  },
6721
+ {
6722
+ name: "drawElementImageToTexture",
6723
+ signatures: [["source","destination"]]
6724
+ },
6721
6725
  {
6722
6726
  name: "multiDrawIndirect",
6723
6727
  signatures: [["indirectBuffer","indirectOffset","maxDrawCount","?drawCountBuffer","?drawCountBufferOffset"]]
@@ -7898,6 +7902,10 @@ export const NativeFunctions = [
7898
7902
  name: "receiveFeatureReport",
7899
7903
  signatures: [["reportId"]]
7900
7904
  },
7905
+ {
7906
+ name: "playHaptics",
7907
+ signatures: [["effect","?intensity"]]
7908
+ },
7901
7909
  {
7902
7910
  name: "addStroke",
7903
7911
  signatures: [["stroke"]]
@@ -606,6 +606,7 @@ export class TraceProcessor extends EventTarget {
606
606
  'missing metric scores for main frame',
607
607
  'missing metric: FCP',
608
608
  'missing metric: LCP',
609
+ 'NO_LCP',
609
610
  'No network requests found in trace',
610
611
  'Trace is too old',
611
612
  ];
@@ -0,0 +1,89 @@
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 Host from '../../core/host/host.js';
6
+ import * as SDK from '../../core/sdk/sdk.js';
7
+ import * as AiAssistanceModel from '../../models/ai_assistance/ai_assistance.js';
8
+ import * as NetworkTimeCalculator from '../../models/network_time_calculator/network_time_calculator.js';
9
+ import * as UI from '../../ui/legacy/legacy.js';
10
+
11
+ export type ContextType = 'NETWORK_REQUEST';
12
+
13
+ export interface ExternalAIRequestOptions {
14
+ context?: {
15
+ type: ContextType,
16
+ contextIdentifier: string,
17
+ };
18
+ prompts: string[];
19
+ }
20
+
21
+ export interface IndividualPromptRequestResponse {
22
+ prompt: string;
23
+ response: string;
24
+ error?: string;
25
+ }
26
+
27
+ function resolveConversationType(contextType?: ContextType): AiAssistanceModel.AiHistoryStorage.ConversationType {
28
+ switch (contextType) {
29
+ case 'NETWORK_REQUEST':
30
+ return AiAssistanceModel.AiHistoryStorage.ConversationType.NETWORK;
31
+ default:
32
+ return AiAssistanceModel.AiHistoryStorage.ConversationType.NONE;
33
+ }
34
+ }
35
+
36
+ function getMatchingFlavorContext(
37
+ contextOptions?: ExternalAIRequestOptions['context'],
38
+ ): AiAssistanceModel.AiAgent.ConversationContext<unknown>|null {
39
+ if (!contextOptions?.contextIdentifier) {
40
+ return null;
41
+ }
42
+ if (contextOptions.type === 'NETWORK_REQUEST') {
43
+ const raw = UI.Context.Context.instance().flavor(SDK.NetworkRequest.NetworkRequest);
44
+ if (raw) {
45
+ if (raw.name() !== contextOptions.contextIdentifier && raw.url() !== contextOptions.contextIdentifier) {
46
+ return null;
47
+ }
48
+ return new AiAssistanceModel.RequestContext.RequestContext(
49
+ raw, new NetworkTimeCalculator.NetworkTransferTimeCalculator());
50
+ }
51
+ }
52
+ return null;
53
+ }
54
+
55
+ export async function handleExternalAIRequest(options: ExternalAIRequestOptions): Promise<unknown[]> {
56
+ localStorage.setItem('aiAssistanceStructuredLogEnabled', 'true');
57
+ localStorage.removeItem('aiAssistanceStructuredLog');
58
+
59
+ const conversationType = resolveConversationType(options.context?.type);
60
+
61
+ const aidaClient = new Host.AidaClient.AidaClient();
62
+ const conversation = new AiAssistanceModel.AiConversation.AiConversation({
63
+ type: conversationType,
64
+ data: [],
65
+ isReadOnly: false,
66
+ aidaClient,
67
+ });
68
+
69
+ const resolvedContext = getMatchingFlavorContext(options.context);
70
+ if (resolvedContext) {
71
+ conversation.setContext(resolvedContext);
72
+ }
73
+
74
+ for (const prompt of options.prompts) {
75
+ await Array.fromAsync(conversation.run(prompt));
76
+ }
77
+
78
+ const logsRaw = localStorage.getItem('aiAssistanceStructuredLog');
79
+ return logsRaw ? JSON.parse(logsRaw) : [];
80
+ }
81
+
82
+ declare global {
83
+ interface Window {
84
+ handleExternalAIRequest?: typeof handleExternalAIRequest;
85
+ }
86
+ }
87
+
88
+ // @ts-expect-error
89
+ globalThis.handleExternalAIRequest = handleExternalAIRequest;
@@ -16,4 +16,5 @@ export * as DisabledWidget from './components/DisabledWidget.js';
16
16
  export * as WalkthroughUtils from './components/WalkthroughUtils.js';
17
17
  export * as WalkthroughView from './components/WalkthroughView.js';
18
18
  export * as ExportConversation from './ExportConversation.js';
19
+ export * as ExternalHandler from './ExternalHandler.js';
19
20
  export * as ImageResize from './components/ImageResize.js';
@@ -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 Platform from '../../core/platform/platform.js';
5
6
  import * as SDK from '../../core/sdk/sdk.js';
6
7
  import type * as ProtocolProxyApi from '../../generated/protocol-proxy-api.js';
7
8
  import type * as Protocol from '../../generated/protocol.js';
@@ -44,9 +45,9 @@ export class BackgroundServiceModel extends SDK.SDKModel.SDKModel<EventTypes> im
44
45
 
45
46
  backgroundServiceEventReceived({backgroundServiceEvent}:
46
47
  Protocol.BackgroundService.BackgroundServiceEventReceivedEvent): void {
47
- // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration)
48
- // @ts-expect-error
49
- this.events.get(backgroundServiceEvent.service).push(backgroundServiceEvent);
48
+ const events = this.events.get(backgroundServiceEvent.service);
49
+ Platform.assertNotNullOrUndefined(events);
50
+ events.push(backgroundServiceEvent);
50
51
  this.dispatchEventToListeners(Events.BackgroundServiceEventReceived, backgroundServiceEvent);
51
52
  }
52
53
  }
@@ -423,13 +423,6 @@ export class IndexedDBModel extends SDK.SDKModel.SDKModel<EventTypes> implements
423
423
  cacheStorageContentUpdated(_event: Protocol.Storage.CacheStorageContentUpdatedEvent): void {
424
424
  }
425
425
 
426
- sharedStorageAccessed(_event: Protocol.Storage.SharedStorageAccessedEvent): void {
427
- }
428
-
429
- sharedStorageWorkletOperationExecutionFinished(
430
- _event: Protocol.Storage.SharedStorageWorkletOperationExecutionFinishedEvent): void {
431
- }
432
-
433
426
  storageBucketCreatedOrUpdated(_event: Protocol.Storage.StorageBucketCreatedOrUpdatedEvent): void {
434
427
  }
435
428