chrome-devtools-frontend 1.0.1643099 → 1.0.1643855
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/eslint.config.mjs +3 -1
- package/extension-api/ExtensionAPI.d.ts +83 -12
- package/front_end/core/host/UserMetrics.ts +0 -1
- package/front_end/core/root/ExperimentNames.ts +0 -1
- package/front_end/core/sdk/ConsoleModel.ts +4 -0
- package/front_end/core/sdk/NetworkRequest.ts +12 -0
- package/front_end/core/sdk/SourceMap.ts +15 -18
- package/front_end/entrypoints/greendev_floaty/FloatyEntrypoint.ts +0 -2
- package/front_end/entrypoints/greendev_floaty/greendev_floaty.ts +0 -2
- package/front_end/entrypoints/main/MainImpl.ts +0 -6
- package/front_end/models/ai_assistance/AiAgent2.ts +1 -0
- package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +22 -16
- package/front_end/models/ai_assistance/agents/AiAgent.ts +19 -6
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +5 -5
- package/front_end/models/ai_assistance/agents/ExecuteJavascript.ts +1 -94
- package/front_end/models/ai_assistance/agents/NetworkAgent.ts +25 -0
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +22 -0
- package/front_end/models/ai_assistance/agents/StorageAgent.ts +54 -1
- package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +1 -2
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +5 -0
- package/front_end/models/ai_assistance/tools/ExecuteJavaScript.ts +4 -10
- package/front_end/models/ai_assistance/tools/Tool.ts +6 -0
- package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +6 -9
- package/front_end/models/bindings/DefaultScriptMapping.ts +2 -1
- package/front_end/models/bindings/SymbolizedError.ts +45 -35
- package/front_end/models/extensions/ExtensionAPI.ts +138 -47
- package/front_end/models/har/Importer.ts +1 -0
- package/front_end/models/source_map_scopes/FunctionCodeResolver.ts +12 -2
- package/front_end/models/stack_trace/DetailedErrorStackParser.ts +44 -51
- package/front_end/models/stack_trace/StackTrace.ts +7 -0
- package/front_end/models/stack_trace/StackTraceImpl.ts +13 -4
- package/front_end/models/stack_trace/StackTraceModel.ts +9 -8
- package/front_end/panels/accessibility/AccessibilitySidebarView.ts +2 -1
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +2 -1
- package/front_end/panels/application/ApplicationPanelSidebar.ts +39 -0
- package/front_end/panels/application/ApplicationPanelTreeElement.ts +39 -0
- package/front_end/panels/application/CookieItemsView.ts +2 -2
- package/front_end/panels/application/resourcesSidebar.css +11 -0
- package/front_end/panels/console/SymbolizedErrorWidget.ts +10 -7
- package/front_end/panels/settings/emulation/DevicesSettingsTab.ts +1 -0
- package/front_end/panels/sources/SourcesPanel.ts +2 -1
- package/front_end/ui/legacy/StackedPane.ts +229 -0
- package/front_end/ui/legacy/ViewManager.ts +59 -169
- package/front_end/ui/legacy/legacy.ts +3 -1
- package/package.json +1 -1
package/eslint.config.mjs
CHANGED
|
@@ -721,7 +721,8 @@ export default defineConfig([
|
|
|
721
721
|
'test/**/*.ts',
|
|
722
722
|
'**/testing/*.ts',
|
|
723
723
|
'scripts/eslint_rules/test/**/*',
|
|
724
|
-
'extensions/cxx_debugging/e2e
|
|
724
|
+
'extensions/cxx_debugging/e2e/**/*.ts',
|
|
725
|
+
'extensions/cxx_debugging/tests/**/*.ts',
|
|
725
726
|
],
|
|
726
727
|
|
|
727
728
|
rules: {
|
|
@@ -750,6 +751,7 @@ export default defineConfig([
|
|
|
750
751
|
],
|
|
751
752
|
|
|
752
753
|
'@devtools/check-test-definitions': 'error',
|
|
754
|
+
'@devtools/prefer-chai-assert': 'error',
|
|
753
755
|
'@devtools/no-assert-strict-equal-for-arrays-and-objects': 'error',
|
|
754
756
|
'@devtools/no-assert-deep-strict-equal': 'error',
|
|
755
757
|
'@devtools/no-assert-equal': 'error',
|
|
@@ -19,8 +19,35 @@ export namespace Chrome {
|
|
|
19
19
|
*/
|
|
20
20
|
readonly buildId?: string;
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Returns the `content` and `encoding` of the resource. If a `callback`
|
|
24
|
+
* is provided, it is invoked with the `content` and `encoding` and the
|
|
25
|
+
* method returns `void`. If no `callback` is provided, the method returns
|
|
26
|
+
* a `Promise`.
|
|
27
|
+
*
|
|
28
|
+
* @param callback Optional callback to be invoked with the content and
|
|
29
|
+
* encoding.
|
|
30
|
+
* @returns A Promise that resolves to an object containing the content
|
|
31
|
+
* and encoding if no callback is provided, otherwise void. Rejects with
|
|
32
|
+
* an error object on failure.
|
|
33
|
+
*/
|
|
34
|
+
getContent(): Promise<{content: string, encoding: string}>;
|
|
22
35
|
getContent(callback: (content: string, encoding: string) => unknown): void;
|
|
23
|
-
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Sets the content of the resource. If a `callback` is provided, it is
|
|
39
|
+
* invoked when the content is set and the method returns `void`. If no
|
|
40
|
+
* `callback` is provided, the method returns a `Promise`.
|
|
41
|
+
*
|
|
42
|
+
* @param content The new content of the resource.
|
|
43
|
+
* @param commit Whether to commit the changes.
|
|
44
|
+
* @param callback Optional callback to be invoked when the content is
|
|
45
|
+
* set.
|
|
46
|
+
* @returns A Promise that resolves when the content is set if no callback
|
|
47
|
+
* is provided, otherwise void. Rejects with an error object on failure.
|
|
48
|
+
*/
|
|
49
|
+
setContent(content: string, commit: boolean): Promise<void>;
|
|
50
|
+
setContent(content: string, commit: boolean, callback: (error?: object) => unknown): void;
|
|
24
51
|
/**
|
|
25
52
|
* Augments this resource's scopes information based on the list of {@link NamedFunctionRange}s
|
|
26
53
|
* for improved debuggability and function naming.
|
|
@@ -40,18 +67,62 @@ export namespace Chrome {
|
|
|
40
67
|
onResourceAdded: EventSink<(resource: Resource) => unknown>;
|
|
41
68
|
onResourceContentCommitted: EventSink<(resource: Resource, content: string) => unknown>;
|
|
42
69
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
70
|
+
/**
|
|
71
|
+
* Evaluates a JavaScript expression in the context of the inspected page.
|
|
72
|
+
*
|
|
73
|
+
* If a `callback` is provided, it is invoked with the result and
|
|
74
|
+
* exception information and the method returns `void`. If no `callback`
|
|
75
|
+
* is provided, the method returns a `Promise`.
|
|
76
|
+
*
|
|
77
|
+
* @template E The type of the value that the Promise resolves to.
|
|
78
|
+
* @param expression The JavaScript expression to evaluate.
|
|
79
|
+
* @param optionsOrCallback Optional options for evaluation, or a callback
|
|
80
|
+
* function.
|
|
81
|
+
* @param callback Optional callback to be invoked with the evaluation
|
|
82
|
+
* result and exception information.
|
|
83
|
+
* @returns A Promise that resolves to the result if no callback is
|
|
84
|
+
* provided, otherwise void. Rejects with an error object on failure.
|
|
85
|
+
*/
|
|
86
|
+
eval<E = unknown>(expression: string, options?: {
|
|
87
|
+
scriptExecutionContext?: string,
|
|
88
|
+
frameURL?: string,
|
|
89
|
+
useContentScriptContext?: boolean,
|
|
90
|
+
}): Promise<E>;
|
|
91
|
+
eval(expression: string,
|
|
92
|
+
optionsOrCallback: {scriptExecutionContext?: string, frameURL?: string, useContentScriptContext?: boolean}|
|
|
93
|
+
undefined|((result: unknown, exceptioninfo: {
|
|
94
|
+
code: string,
|
|
95
|
+
description: string,
|
|
96
|
+
details: unknown[],
|
|
97
|
+
isError: boolean,
|
|
98
|
+
isException: boolean,
|
|
99
|
+
value: string,
|
|
100
|
+
}) => unknown),
|
|
101
|
+
callback?: (result: unknown, exceptioninfo: {
|
|
102
|
+
code: string,
|
|
103
|
+
description: string,
|
|
104
|
+
details: unknown[],
|
|
105
|
+
isError: boolean,
|
|
106
|
+
isException: boolean,
|
|
107
|
+
value: string,
|
|
108
|
+
}) => unknown): void;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Retrieves all resources within the inspected window.
|
|
112
|
+
*
|
|
113
|
+
* If a `callback` is provided, it is invoked with the array of resources
|
|
114
|
+
* and the method returns `void`. If no `callback` is provided, the method
|
|
115
|
+
* returns a `Promise`.
|
|
116
|
+
*
|
|
117
|
+
* @param callback Optional callback to be invoked with the array of
|
|
118
|
+
* resources.
|
|
119
|
+
* @returns A Promise that resolves to an array of resources if no
|
|
120
|
+
* callback is provided, otherwise void. Rejects with an error object on
|
|
121
|
+
* failure.
|
|
122
|
+
*/
|
|
123
|
+
getResources(): Promise<Resource[]>;
|
|
54
124
|
getResources(callback: (resources: Resource[]) => unknown): void;
|
|
125
|
+
|
|
55
126
|
reload(reloadOptions?: {ignoreCache?: boolean, injectedScript?: string, userAgent?: string}): void;
|
|
56
127
|
}
|
|
57
128
|
|
|
@@ -767,7 +767,6 @@ export enum DevtoolsExperiments {
|
|
|
767
767
|
/* eslint-disable @typescript-eslint/naming-convention */
|
|
768
768
|
'protocol-monitor' = 13,
|
|
769
769
|
'instrumentation-breakpoints' = 61,
|
|
770
|
-
'use-source-map-scopes' = 76,
|
|
771
770
|
'durable-messages' = 110,
|
|
772
771
|
'jpeg-xl' = 111,
|
|
773
772
|
'plus-button' = 112,
|
|
@@ -6,7 +6,6 @@ export enum ExperimentName {
|
|
|
6
6
|
ALL = '*',
|
|
7
7
|
PROTOCOL_MONITOR = 'protocol-monitor',
|
|
8
8
|
INSTRUMENTATION_BREAKPOINTS = 'instrumentation-breakpoints',
|
|
9
|
-
USE_SOURCE_MAP_SCOPES = 'use-source-map-scopes',
|
|
10
9
|
DURABLE_MESSAGES = 'durable-messages',
|
|
11
10
|
JPEG_XL = 'jpeg-xl',
|
|
12
11
|
PLUS_BUTTON = 'plus-button',
|
|
@@ -547,6 +547,7 @@ export interface ConsoleMessageDetails {
|
|
|
547
547
|
context?: string;
|
|
548
548
|
affectedResources?: AffectedResources;
|
|
549
549
|
category?: Protocol.Log.LogEntryCategory;
|
|
550
|
+
exceptionDetails?: Protocol.Runtime.ExceptionDetails;
|
|
550
551
|
}
|
|
551
552
|
|
|
552
553
|
export class ConsoleMessage {
|
|
@@ -570,6 +571,7 @@ export class ConsoleMessage {
|
|
|
570
571
|
#exceptionId?: number = undefined;
|
|
571
572
|
#affectedResources?: AffectedResources;
|
|
572
573
|
category?: Protocol.Log.LogEntryCategory;
|
|
574
|
+
readonly exceptionDetails?: Protocol.Runtime.ExceptionDetails;
|
|
573
575
|
|
|
574
576
|
/**
|
|
575
577
|
* The parent frame of the `console.log` call of logpoints or conditional breakpoints
|
|
@@ -600,6 +602,7 @@ export class ConsoleMessage {
|
|
|
600
602
|
this.workerId = details?.workerId;
|
|
601
603
|
this.#affectedResources = details?.affectedResources;
|
|
602
604
|
this.category = details?.category;
|
|
605
|
+
this.exceptionDetails = details?.exceptionDetails;
|
|
603
606
|
|
|
604
607
|
if (!this.#executionContextId && this.#runtimeModel) {
|
|
605
608
|
if (this.scriptId) {
|
|
@@ -646,6 +649,7 @@ export class ConsoleMessage {
|
|
|
646
649
|
executionContextId: exceptionDetails.executionContextId,
|
|
647
650
|
scriptId: exceptionDetails.scriptId,
|
|
648
651
|
affectedResources,
|
|
652
|
+
exceptionDetails,
|
|
649
653
|
};
|
|
650
654
|
return new ConsoleMessage(
|
|
651
655
|
runtimeModel, Protocol.Log.LogEntrySource.Javascript, Protocol.Log.LogEntryLevel.Error,
|
|
@@ -299,6 +299,10 @@ export class NetworkRequest extends Common.ObjectWrapper.ObjectWrapper<EventType
|
|
|
299
299
|
#contentDataProvider?: () => Promise<TextUtils.ContentData.ContentDataOrError>;
|
|
300
300
|
#isSameSite: boolean|null = null;
|
|
301
301
|
#wasIntercepted = false;
|
|
302
|
+
/**
|
|
303
|
+
* Whether this request was imported from a HAR file.
|
|
304
|
+
*/
|
|
305
|
+
#isImportedHar = false;
|
|
302
306
|
#associatedData = new Map<string, object>();
|
|
303
307
|
#hasOverriddenContent = false;
|
|
304
308
|
#hasThirdPartyCookiePhaseoutIssue = false;
|
|
@@ -1148,6 +1152,14 @@ export class NetworkRequest extends Common.ObjectWrapper.ObjectWrapper<EventType
|
|
|
1148
1152
|
this.#wasIntercepted = wasIntercepted;
|
|
1149
1153
|
}
|
|
1150
1154
|
|
|
1155
|
+
isImportedHar(): boolean {
|
|
1156
|
+
return this.#isImportedHar;
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
setIsImportedHar(isImportedHar: boolean): void {
|
|
1160
|
+
this.#isImportedHar = isImportedHar;
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1151
1163
|
setEarlyHintsHeaders(headers: NameValue[]): void {
|
|
1152
1164
|
this.earlyHintsHeaders = headers;
|
|
1153
1165
|
}
|
|
@@ -6,7 +6,6 @@ import * as TextUtils from '../../models/text_utils/text_utils.js';
|
|
|
6
6
|
import * as ScopesCodec from '../../third_party/source-map-scopes-codec/source-map-scopes-codec.js';
|
|
7
7
|
import * as Common from '../common/common.js';
|
|
8
8
|
import * as Platform from '../platform/platform.js';
|
|
9
|
-
import * as Root from '../root/root.js';
|
|
10
9
|
|
|
11
10
|
import type {CallFrame, ScopeChainEntry} from './DebuggerModel.js';
|
|
12
11
|
import {scopeTreeForScript} from './ScopeTreeCache.js';
|
|
@@ -584,23 +583,21 @@ export class SourceMap {
|
|
|
584
583
|
lineNumber, columnNumber, sourceIndex, sourceURL, sourceLineNumber, sourceColumnNumber, names[nameIndex]));
|
|
585
584
|
}
|
|
586
585
|
|
|
587
|
-
if (
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
this.#scopesInfo.addOriginalScopes(new Array(map.sources.length).fill(null));
|
|
603
|
-
}
|
|
586
|
+
if (!this.#scopesInfo) {
|
|
587
|
+
this.#scopesInfo = new SourceMapScopesInfo(this, {scopes: [], ranges: []});
|
|
588
|
+
}
|
|
589
|
+
if (map.scopes) {
|
|
590
|
+
const {scopes, ranges} = ScopesCodec.decode(
|
|
591
|
+
map as ScopesCodec.SourceMapJson,
|
|
592
|
+
{mode: ScopesCodec.DecodeMode.LAX, generatedOffset: {line: baseLineNumber, column: baseColumnNumber}});
|
|
593
|
+
this.#scopesInfo.addOriginalScopes(scopes);
|
|
594
|
+
this.#scopesInfo.addGeneratedRanges(ranges);
|
|
595
|
+
} else if (map.x_com_bloomberg_sourcesFunctionMappings) {
|
|
596
|
+
const originalScopes = this.parseBloombergScopes(map);
|
|
597
|
+
this.#scopesInfo.addOriginalScopes(originalScopes);
|
|
598
|
+
} else {
|
|
599
|
+
// Keep the OriginalScope[] tree array consistent with sources.
|
|
600
|
+
this.#scopesInfo.addOriginalScopes(new Array(map.sources.length).fill(null));
|
|
604
601
|
}
|
|
605
602
|
}
|
|
606
603
|
|
|
@@ -593,8 +593,6 @@ async function init(): Promise<void> {
|
|
|
593
593
|
|
|
594
594
|
safeRegisterExperiment(
|
|
595
595
|
Root.ExperimentNames.ExperimentName.INSTRUMENTATION_BREAKPOINTS, 'Enable instrumentation breakpoints');
|
|
596
|
-
safeRegisterExperiment(
|
|
597
|
-
Root.ExperimentNames.ExperimentName.USE_SOURCE_MAP_SCOPES, 'Use scope information from source maps');
|
|
598
596
|
safeRegisterExperiment(Root.ExperimentNames.ExperimentName.PROTOCOL_MONITOR, 'Protocol Monitor');
|
|
599
597
|
|
|
600
598
|
const hostUnsyncedStorage: Common.Settings.SettingsBackingStore = {
|
|
@@ -247,8 +247,6 @@ async function init(): Promise<void> {
|
|
|
247
247
|
// Register necessary experiments to avoid "Unknown experiment" errors.
|
|
248
248
|
Root.Runtime.experiments.register(
|
|
249
249
|
Root.ExperimentNames.ExperimentName.INSTRUMENTATION_BREAKPOINTS, 'Enable instrumentation breakpoints');
|
|
250
|
-
Root.Runtime.experiments.register(
|
|
251
|
-
Root.ExperimentNames.ExperimentName.USE_SOURCE_MAP_SCOPES, 'Use scope information from source maps');
|
|
252
250
|
Root.Runtime.experiments.register(Root.ExperimentNames.ExperimentName.PROTOCOL_MONITOR, 'Protocol Monitor');
|
|
253
251
|
|
|
254
252
|
const WINDOW_LOCAL_STORAGE: Common.Settings.SettingsBackingStore = {
|
|
@@ -365,8 +365,6 @@ export class MainImpl {
|
|
|
365
365
|
// Debugging
|
|
366
366
|
Root.Runtime.experiments.register(
|
|
367
367
|
Root.ExperimentNames.ExperimentName.INSTRUMENTATION_BREAKPOINTS, 'Instrumentation breakpoints');
|
|
368
|
-
Root.Runtime.experiments.register(
|
|
369
|
-
Root.ExperimentNames.ExperimentName.USE_SOURCE_MAP_SCOPES, 'Use scope information from source maps');
|
|
370
368
|
|
|
371
369
|
Root.Runtime.experiments.registerHostExperiment({
|
|
372
370
|
name: Root.ExperimentNames.ExperimentName.DURABLE_MESSAGES,
|
|
@@ -392,10 +390,6 @@ export class MainImpl {
|
|
|
392
390
|
requiresChromeRestart: false,
|
|
393
391
|
});
|
|
394
392
|
|
|
395
|
-
Root.Runtime.experiments.enableExperimentsByDefault([
|
|
396
|
-
Root.ExperimentNames.ExperimentName.USE_SOURCE_MAP_SCOPES,
|
|
397
|
-
]);
|
|
398
|
-
|
|
399
393
|
const enabledExperiments = Root.Runtime.Runtime.queryParam('enabledExperiments');
|
|
400
394
|
if (enabledExperiments) {
|
|
401
395
|
Root.Runtime.experiments.setServerEnabledExperiments(enabledExperiments.split(';'));
|
|
@@ -186,6 +186,7 @@ User query: ${enhancedQuery}`;
|
|
|
186
186
|
changeManager: this.#changes,
|
|
187
187
|
createExtensionScope: this.#createExtensionScope.bind(this),
|
|
188
188
|
execJs: this.#execJs,
|
|
189
|
+
getExecutionContextNode: () => this.context instanceof DOMNodeContext ? this.context.getItem() : null,
|
|
189
190
|
},
|
|
190
191
|
options,
|
|
191
192
|
),
|
|
@@ -13,6 +13,8 @@ import {ChangeManager} from '../ChangeManager.js';
|
|
|
13
13
|
import {LighthouseFormatter} from '../data_formatters/LighthouseFormatter.js';
|
|
14
14
|
import {debugLog} from '../debug.js';
|
|
15
15
|
import {ExtensionScope} from '../ExtensionScope.js';
|
|
16
|
+
import {ToolName} from '../tools/Tool.js';
|
|
17
|
+
import {ToolRegistry} from '../tools/ToolRegistry.js';
|
|
16
18
|
|
|
17
19
|
import {
|
|
18
20
|
AiAgent,
|
|
@@ -25,10 +27,8 @@ import {
|
|
|
25
27
|
} from './AiAgent.js';
|
|
26
28
|
import {
|
|
27
29
|
type CreateExtensionScopeFunction,
|
|
28
|
-
executeJavaScriptFunction,
|
|
29
30
|
type ExecuteJsAgentOptions,
|
|
30
31
|
executeJsCode,
|
|
31
|
-
JavascriptExecutor
|
|
32
32
|
} from './ExecuteJavascript.js';
|
|
33
33
|
|
|
34
34
|
/**
|
|
@@ -117,7 +117,6 @@ export class AccessibilityAgent extends AiAgent<LHModel.ReporterTypes.ReportJSON
|
|
|
117
117
|
(overrides?: LHModel.RunTypes.RunOverrides) => Promise<LHModel.ReporterTypes.ReportJSON|null>;
|
|
118
118
|
|
|
119
119
|
#execJs: typeof executeJsCode;
|
|
120
|
-
#javascriptExecutor: JavascriptExecutor;
|
|
121
120
|
#changes: ChangeManager;
|
|
122
121
|
#createExtensionScope: CreateExtensionScopeFunction;
|
|
123
122
|
|
|
@@ -129,14 +128,6 @@ export class AccessibilityAgent extends AiAgent<LHModel.ReporterTypes.ReportJSON
|
|
|
129
128
|
this.#createExtensionScope = opts.createExtensionScope ?? ((changes: ChangeManager) => {
|
|
130
129
|
return new ExtensionScope(changes, this.sessionId, this.#getDocumentBodyNode());
|
|
131
130
|
});
|
|
132
|
-
this.#javascriptExecutor = new JavascriptExecutor(
|
|
133
|
-
{
|
|
134
|
-
executionMode: this.executionMode,
|
|
135
|
-
getContextNode: () => this.#getDocumentBodyNode(),
|
|
136
|
-
createExtensionScope: this.#createExtensionScope.bind(this),
|
|
137
|
-
changes: this.#changes,
|
|
138
|
-
},
|
|
139
|
-
this.#execJs);
|
|
140
131
|
}
|
|
141
132
|
|
|
142
133
|
get userTier(): string|undefined {
|
|
@@ -271,16 +262,31 @@ export class AccessibilityAgent extends AiAgent<LHModel.ReporterTypes.ReportJSON
|
|
|
271
262
|
}
|
|
272
263
|
});
|
|
273
264
|
|
|
274
|
-
const
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
265
|
+
const executeJsTool = ToolRegistry.get(ToolName.EXECUTE_JAVASCRIPT);
|
|
266
|
+
if (!executeJsTool) {
|
|
267
|
+
throw new Error('Required tool "executeJavaScript" not found');
|
|
268
|
+
}
|
|
269
|
+
this.declareFunction(executeJsTool.name, {
|
|
270
|
+
description: executeJsTool.description,
|
|
271
|
+
parameters: executeJsTool.parameters,
|
|
272
|
+
displayInfoFromArgs: executeJsTool.displayInfoFromArgs,
|
|
273
|
+
handler: async (args, options) => {
|
|
278
274
|
if (isImported) {
|
|
279
275
|
return {
|
|
280
276
|
error: 'Cannot use this tool on an imported file.',
|
|
281
277
|
};
|
|
282
278
|
}
|
|
283
|
-
return await
|
|
279
|
+
return await executeJsTool.handler(
|
|
280
|
+
args,
|
|
281
|
+
{
|
|
282
|
+
conversationContext: this.context ?? null,
|
|
283
|
+
changeManager: this.#changes,
|
|
284
|
+
createExtensionScope: this.#createExtensionScope.bind(this),
|
|
285
|
+
execJs: this.#execJs,
|
|
286
|
+
getExecutionContextNode: () => this.#getDocumentBodyNode(),
|
|
287
|
+
},
|
|
288
|
+
options,
|
|
289
|
+
);
|
|
284
290
|
},
|
|
285
291
|
});
|
|
286
292
|
|
|
@@ -509,8 +509,8 @@ export abstract class AiAgent<T> {
|
|
|
509
509
|
this.#allowedOrigin = opts.allowedOrigin;
|
|
510
510
|
}
|
|
511
511
|
|
|
512
|
-
async enhanceQuery(query: string, selected: ConversationContext<T>|null,
|
|
513
|
-
|
|
512
|
+
async enhanceQuery(query: string, selected: ConversationContext<T>|null,
|
|
513
|
+
multimodalInputType?: MultimodalInputType): Promise<string>;
|
|
514
514
|
async enhanceQuery(query: string): Promise<string> {
|
|
515
515
|
return query;
|
|
516
516
|
}
|
|
@@ -557,9 +557,21 @@ export abstract class AiAgent<T> {
|
|
|
557
557
|
return undefined;
|
|
558
558
|
}
|
|
559
559
|
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
560
|
+
/**
|
|
561
|
+
* Preamble features appended to the `client_version` in metadata.
|
|
562
|
+
* This is required ONLY for the Styling Agent for legacy reasons to serve
|
|
563
|
+
* different server-side preambles based on the Chrome version.
|
|
564
|
+
* Other agents should NOT set or override this.
|
|
565
|
+
* If you are curious about this, look for `do_conversation_handler.cc` in
|
|
566
|
+
* Google3 or chat to @jacktfranklin.
|
|
567
|
+
*/
|
|
568
|
+
preambleFeatures(): string[] {
|
|
569
|
+
return [];
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
buildRequest(part: Host.AidaClient.Part|Host.AidaClient.Part[],
|
|
573
|
+
role: Host.AidaClient.Role.USER|
|
|
574
|
+
Host.AidaClient.Role.ROLE_UNSPECIFIED): Host.AidaClient.DoConversationRequest {
|
|
563
575
|
const parts = Array.isArray(part) ? part : [part];
|
|
564
576
|
const currentMessage: Host.AidaClient.Content = {
|
|
565
577
|
parts,
|
|
@@ -600,7 +612,8 @@ export abstract class AiAgent<T> {
|
|
|
600
612
|
disable_user_content_logging: !(this.#serverSideLoggingEnabled ?? false),
|
|
601
613
|
string_session_id: this.#sessionId,
|
|
602
614
|
user_tier: userTier,
|
|
603
|
-
client_version:
|
|
615
|
+
client_version:
|
|
616
|
+
Root.Runtime.getChromeVersion() + this.preambleFeatures().map(feature => `+${feature}`).join(''),
|
|
604
617
|
},
|
|
605
618
|
|
|
606
619
|
functionality_type: enableAidaFunctionCalling ? Host.AidaClient.FunctionalityType.AGENTIC_CHAT :
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
type RequestOptions,
|
|
28
28
|
} from './AiAgent.js';
|
|
29
29
|
import {FileContext} from './FileAgent.js';
|
|
30
|
-
import {RequestContext} from './NetworkAgent.js';
|
|
30
|
+
import {getRequestContextOrigin, RequestContext} from './NetworkAgent.js';
|
|
31
31
|
import {PerformanceTraceContext} from './PerformanceAgent.js';
|
|
32
32
|
import {StorageContext} from './StorageAgent.js';
|
|
33
33
|
|
|
@@ -146,7 +146,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
146
146
|
let hasCrossOriginRequest = false;
|
|
147
147
|
const requestsToShow: NetworkRequest[] = [];
|
|
148
148
|
for (const request of Logs.NetworkLog.NetworkLog.instance().requests()) {
|
|
149
|
-
const
|
|
149
|
+
const requestOrigin = getRequestContextOrigin(request);
|
|
150
150
|
/**
|
|
151
151
|
* NOTE: this origin check does not ensure that all the requests are
|
|
152
152
|
* from the same origin as the target page. Instead, it ensures that
|
|
@@ -155,7 +155,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
155
155
|
* during the loading of the target page, and do not leak URLs from
|
|
156
156
|
* other pages.
|
|
157
157
|
*/
|
|
158
|
-
if (origin &&
|
|
158
|
+
if (origin && requestOrigin !== origin) {
|
|
159
159
|
hasCrossOriginRequest = true;
|
|
160
160
|
continue;
|
|
161
161
|
}
|
|
@@ -230,8 +230,8 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
230
230
|
return false;
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
-
const
|
|
234
|
-
return !origin ||
|
|
233
|
+
const requestOrigin = getRequestContextOrigin(req);
|
|
234
|
+
return !origin || requestOrigin === origin;
|
|
235
235
|
});
|
|
236
236
|
|
|
237
237
|
if (request) {
|
|
@@ -12,9 +12,7 @@ import {debugLog} from '../debug.js';
|
|
|
12
12
|
import {EvaluateAction, formatError, SideEffectError} from '../EvaluateAction.js';
|
|
13
13
|
import {FREESTYLER_WORLD_NAME} from '../injected.js';
|
|
14
14
|
|
|
15
|
-
import type {
|
|
16
|
-
AgentOptions as BaseAgentOptions, FunctionCallHandlerResult, FunctionDeclaration, FunctionHandlerOptions,} from
|
|
17
|
-
'./AiAgent.js';
|
|
15
|
+
import type {AgentOptions as BaseAgentOptions, FunctionCallHandlerResult, FunctionHandlerOptions,} from './AiAgent.js';
|
|
18
16
|
|
|
19
17
|
const lockedString = i18n.i18n.lockedString;
|
|
20
18
|
|
|
@@ -28,97 +26,6 @@ export interface ExecuteJsAgentOptions extends BaseAgentOptions {
|
|
|
28
26
|
execJs?: typeof executeJsCode;
|
|
29
27
|
}
|
|
30
28
|
|
|
31
|
-
// TODO(crbug.com/510206549): De-duplicate this function by migrating AccessibilityAgent to use
|
|
32
|
-
// the registry-based ExecuteJavaScriptTool in tools/ExecuteJavaScript.ts.
|
|
33
|
-
export function executeJavaScriptFunction(executor: JavascriptExecutor): FunctionDeclaration<
|
|
34
|
-
{
|
|
35
|
-
title: string,
|
|
36
|
-
explanation: string,
|
|
37
|
-
code: string,
|
|
38
|
-
},
|
|
39
|
-
unknown> {
|
|
40
|
-
return {
|
|
41
|
-
description:
|
|
42
|
-
'This function allows you to run JavaScript code on the inspected page to access the element styles and page content.\nCall this function to gather additional information or modify the page state. Call this function enough times to investigate the user request.',
|
|
43
|
-
parameters: {
|
|
44
|
-
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
45
|
-
description: '',
|
|
46
|
-
nullable: false,
|
|
47
|
-
properties: {
|
|
48
|
-
code: {
|
|
49
|
-
type: Host.AidaClient.ParametersTypes.STRING,
|
|
50
|
-
description:
|
|
51
|
-
`JavaScript code snippet to run on the inspected page. Make sure the code is formatted for readability.
|
|
52
|
-
|
|
53
|
-
# Instructions
|
|
54
|
-
|
|
55
|
-
* To return data, define a top-level \`data\` variable and populate it with data you want to get. Only JSON-serializable objects can be assigned to \`data\`.
|
|
56
|
-
* If you modify styles on an element, ALWAYS call the pre-defined global \`async setElementStyles(el: Element, styles: object)\` function. This function is an internal mechanism for you and should never be presented as a command/advice to the user.
|
|
57
|
-
* **CRITICAL** Only get styles that might be relevant to the user request.
|
|
58
|
-
* **CRITICAL** Never assume a selector for the elements unless you verified your knowledge.
|
|
59
|
-
* **CRITICAL** Consider that \`data\` variable from the previous function calls are not available in a new function call.
|
|
60
|
-
|
|
61
|
-
For example, the code to change element styles:
|
|
62
|
-
|
|
63
|
-
\`\`\`
|
|
64
|
-
await setElementStyles($0, {
|
|
65
|
-
color: 'blue',
|
|
66
|
-
});
|
|
67
|
-
\`\`\`
|
|
68
|
-
|
|
69
|
-
For example, the code to get overlapping elements:
|
|
70
|
-
|
|
71
|
-
\`\`\`
|
|
72
|
-
const data = {
|
|
73
|
-
overlappingElements: Array.from(document.querySelectorAll('*'))
|
|
74
|
-
.filter(el => {
|
|
75
|
-
const rect = el.getBoundingClientRect();
|
|
76
|
-
const popupRect = $0.getBoundingClientRect();
|
|
77
|
-
return (
|
|
78
|
-
el !== $0 &&
|
|
79
|
-
rect.left < popupRect.right &&
|
|
80
|
-
rect.right > popupRect.left &&
|
|
81
|
-
rect.top < popupRect.bottom &&
|
|
82
|
-
rect.bottom > popupRect.top
|
|
83
|
-
);
|
|
84
|
-
})
|
|
85
|
-
.map(el => ({
|
|
86
|
-
tagName: el.tagName,
|
|
87
|
-
id: el.id,
|
|
88
|
-
className: el.className,
|
|
89
|
-
zIndex: window.getComputedStyle(el)['z-index']
|
|
90
|
-
}))
|
|
91
|
-
};
|
|
92
|
-
\`\`\`
|
|
93
|
-
`,
|
|
94
|
-
},
|
|
95
|
-
explanation: {
|
|
96
|
-
type: Host.AidaClient.ParametersTypes.STRING,
|
|
97
|
-
description: 'Explain why you want to run this code',
|
|
98
|
-
},
|
|
99
|
-
title: {
|
|
100
|
-
type: Host.AidaClient.ParametersTypes.STRING,
|
|
101
|
-
description: 'Provide a summary of what the code does. For example, "Checking related element styles".',
|
|
102
|
-
},
|
|
103
|
-
},
|
|
104
|
-
required: ['code', 'explanation', 'title']
|
|
105
|
-
},
|
|
106
|
-
displayInfoFromArgs: params => {
|
|
107
|
-
return {
|
|
108
|
-
title: params.title,
|
|
109
|
-
thought: params.explanation,
|
|
110
|
-
action: params.code,
|
|
111
|
-
};
|
|
112
|
-
},
|
|
113
|
-
handler: async (
|
|
114
|
-
params,
|
|
115
|
-
options,
|
|
116
|
-
) => {
|
|
117
|
-
return await executor.executeAction(params.code, options);
|
|
118
|
-
},
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
|
|
122
29
|
export async function executeJsCode(
|
|
123
30
|
functionDeclaration: string,
|
|
124
31
|
{throwOnSideEffect, contextNode}: {throwOnSideEffect: boolean, contextNode: SDK.DOMModel.DOMNode|null}):
|
|
@@ -2,11 +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 Common from '../../../core/common/common.js';
|
|
5
6
|
import * as Host from '../../../core/host/host.js';
|
|
6
7
|
import * as i18n from '../../../core/i18n/i18n.js';
|
|
8
|
+
import type * as Platform from '../../../core/platform/platform.js';
|
|
7
9
|
import * as Root from '../../../core/root/root.js';
|
|
8
10
|
import type * as SDK from '../../../core/sdk/sdk.js';
|
|
9
11
|
import type * as NetworkTimeCalculator from '../../network_time_calculator/network_time_calculator.js';
|
|
12
|
+
import {extractContextOrigin} from '../AiOrigins.js';
|
|
10
13
|
import {NetworkRequestFormatter} from '../data_formatters/NetworkRequestFormatter.js';
|
|
11
14
|
|
|
12
15
|
import {
|
|
@@ -98,6 +101,24 @@ const UIStringsNotTranslate = {
|
|
|
98
101
|
|
|
99
102
|
const lockedString = i18n.i18n.lockedString;
|
|
100
103
|
|
|
104
|
+
/**
|
|
105
|
+
* Returns the origin for a network request in the AI context.
|
|
106
|
+
*
|
|
107
|
+
* To prevent cross-origin prompt injection attacks, HAR-imported requests
|
|
108
|
+
* are isolated from live pages. We assign them a virtual origin
|
|
109
|
+
* (`imported-har://${domain}`) so they do not share the origin of live pages
|
|
110
|
+
* (e.g., `https://${domain}`). This forces a conversation reset when transitioning
|
|
111
|
+
* between imported HAR data and live pages.
|
|
112
|
+
*/
|
|
113
|
+
export function getRequestContextOrigin(request: SDK.NetworkRequest.NetworkRequest): string {
|
|
114
|
+
const origin = extractContextOrigin(request.documentURL);
|
|
115
|
+
if (request.isImportedHar()) {
|
|
116
|
+
const parsed = Common.ParsedURL.ParsedURL.fromString(origin as Platform.DevToolsPath.UrlString);
|
|
117
|
+
return `imported-har://${parsed ? parsed.domain() : origin}`;
|
|
118
|
+
}
|
|
119
|
+
return origin;
|
|
120
|
+
}
|
|
121
|
+
|
|
101
122
|
export class RequestContext extends ConversationContext<SDK.NetworkRequest.NetworkRequest> {
|
|
102
123
|
#request: SDK.NetworkRequest.NetworkRequest;
|
|
103
124
|
#calculator: NetworkTimeCalculator.NetworkTransferTimeCalculator;
|
|
@@ -119,6 +140,10 @@ export class RequestContext extends ConversationContext<SDK.NetworkRequest.Netwo
|
|
|
119
140
|
return this.#request.documentURL;
|
|
120
141
|
}
|
|
121
142
|
|
|
143
|
+
override getOrigin(): string {
|
|
144
|
+
return getRequestContextOrigin(this.#request);
|
|
145
|
+
}
|
|
146
|
+
|
|
122
147
|
override getItem(): SDK.NetworkRequest.NetworkRequest {
|
|
123
148
|
return this.#request;
|
|
124
149
|
}
|
|
@@ -15,6 +15,7 @@ import * as Logs from '../../logs/logs.js';
|
|
|
15
15
|
import * as SourceMapScopes from '../../source_map_scopes/source_map_scopes.js';
|
|
16
16
|
import * as TextUtils from '../../text_utils/text_utils.js';
|
|
17
17
|
import * as Trace from '../../trace/trace.js';
|
|
18
|
+
import {extractContextOrigin} from '../AiOrigins.js';
|
|
18
19
|
import {sanitizeHeaders} from '../data_formatters/NetworkRequestFormatter.js';
|
|
19
20
|
import {
|
|
20
21
|
PerformanceInsightFormatter,
|
|
@@ -256,6 +257,27 @@ export class PerformanceTraceContext extends ConversationContext<AgentFocus> {
|
|
|
256
257
|
}
|
|
257
258
|
}
|
|
258
259
|
|
|
260
|
+
/**
|
|
261
|
+
* Returns the origin for a performance trace in the AI context.
|
|
262
|
+
*
|
|
263
|
+
* To prevent cross-origin prompt injection attacks, imported traces
|
|
264
|
+
* are isolated from live pages. We assign them a virtual origin
|
|
265
|
+
* (`imported-trace://${domain}`) so they do not share the origin of live pages
|
|
266
|
+
* (e.g., `https://${domain}`). This forces a conversation reset when transitioning
|
|
267
|
+
* between imported trace data and live pages.
|
|
268
|
+
*/
|
|
269
|
+
override getOrigin(): string {
|
|
270
|
+
const parsedTrace = this.#focus.parsedTrace;
|
|
271
|
+
const url = this.getURL();
|
|
272
|
+
const origin = extractContextOrigin(url);
|
|
273
|
+
const isFresh = Tracing.FreshRecording.Tracker.instance().recordingIsFresh(parsedTrace);
|
|
274
|
+
if (!isFresh) {
|
|
275
|
+
const parsed = Common.ParsedURL.ParsedURL.fromString(origin as Platform.DevToolsPath.UrlString);
|
|
276
|
+
return `imported-trace://${parsed ? parsed.domain() : origin}`;
|
|
277
|
+
}
|
|
278
|
+
return origin;
|
|
279
|
+
}
|
|
280
|
+
|
|
259
281
|
override getItem(): AgentFocus {
|
|
260
282
|
return this.#focus;
|
|
261
283
|
}
|