chrome-devtools-frontend 1.0.1701636 → 1.0.1703574
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/front_end/core/common/ParsedURL.ts +5 -1
- package/front_end/core/host/UserMetricsEnums.ts +2 -1
- package/front_end/core/root/ExperimentNames.ts +1 -0
- package/front_end/core/sdk/CSSPropertyParserMatchers.ts +2 -7
- package/front_end/core/text_utils/Markdown.ts +73 -0
- package/front_end/core/text_utils/text_utils.ts +2 -0
- package/front_end/devtools_compatibility.js +2 -1
- package/front_end/entrypoints/main/MainImpl.ts +8 -0
- package/front_end/generated/InspectorBackendCommands.ts +6 -4
- package/front_end/generated/protocol-mapping.d.ts +8 -0
- package/front_end/generated/protocol-proxy-api.d.ts +6 -0
- package/front_end/generated/protocol.ts +22 -3
- package/front_end/models/ai_assistance/AiAgent2.ts +13 -1
- package/front_end/models/ai_assistance/AiConversation.ts +1 -1
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +13 -19
- package/front_end/models/change_tracker/ChangeTracker.ts +5 -64
- package/front_end/models/comment_manager/CD4ABridge.ts +5 -0
- package/front_end/models/comment_manager/CommentManager.ts +3 -5
- package/front_end/models/comment_manager/CommentThread.ts +30 -13
- package/front_end/models/issues_manager/CookieDeprecationMetadataIssue.ts +6 -7
- package/front_end/models/issues_manager/DeprecationIssue.ts +1 -1
- package/front_end/models/issues_manager/MarkdownIssueDescription.ts +18 -52
- package/front_end/models/issues_manager/SRIMessageSignatureIssue.ts +2 -4
- package/front_end/models/issues_manager/descriptions/cookieWarnMetadataGrantRead.md +0 -1
- package/front_end/models/issues_manager/descriptions/cookieWarnMetadataGrantReadOptOut.md +5 -0
- package/front_end/models/issues_manager/descriptions/cookieWarnMetadataGrantSet.md +0 -1
- package/front_end/models/issues_manager/descriptions/cookieWarnMetadataGrantSetOptOut.md +5 -0
- package/front_end/models/issues_manager/descriptions/deprecation.md +1 -1
- package/front_end/models/issues_manager/descriptions/sriValidationFailedIntegrityMismatch.md +2 -0
- package/front_end/models/persistence/AutomaticFileSystemWorkspaceBinding.ts +1 -1
- package/front_end/models/persistence/NetworkPersistenceManager.ts +14 -2
- package/front_end/panels/common/CommentThreadWidget.ts +29 -10
- package/front_end/panels/common/CommentsOverlayWidget.ts +50 -14
- package/front_end/panels/common/CommentsStatusBarPill.ts +40 -7
- package/front_end/panels/common/commentThreadWidget.css +11 -0
- package/front_end/panels/common/commentsStatusBarPill.css +13 -0
- package/front_end/panels/elements/StylePropertiesSection.ts +10 -0
- package/front_end/panels/elements/StylePropertyTreeElement.ts +1 -1
- package/front_end/panels/elements/StylesSidebarPane.ts +101 -49
- package/front_end/panels/elements/components/CSSQuery.ts +1 -1
- package/front_end/panels/elements/components/cssQuery.css +4 -0
- package/front_end/panels/elements/elements.ts +0 -1
- package/front_end/panels/elements/stylesSidebarPane.css +6 -0
- package/front_end/panels/issues/IssueView.ts +5 -1
- package/front_end/panels/sources/ResourceOriginPlugin.ts +8 -3
- package/front_end/panels/sources/ScopeChainSidebarPane.ts +3 -4
- package/front_end/panels/sources/SourcesView.ts +127 -147
- package/front_end/panels/sources/TabbedEditorContainer.ts +518 -246
- package/front_end/panels/sources/UISourceCodeFrame.ts +9 -0
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/chromium/client-variations/ClientVariations.js +25 -96
- package/front_end/third_party/codemirror.next/chunk/angular.js +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/legacy.js +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/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/package.json +4 -1
- package/front_end/third_party/codemirror.next/rebuild.sh +1 -1
- package/front_end/ui/comments/CommentOverlayManager.ts +11 -10
- package/front_end/ui/components/markdown_view/MarkdownPlaceholderLitRenderer.ts +59 -0
- package/front_end/ui/components/markdown_view/markdown_view.ts +2 -0
- package/front_end/ui/legacy/TabbedPane.ts +51 -40
- package/front_end/ui/legacy/Treeoutline.ts +28 -19
- package/front_end/ui/legacy/UIUtils.ts +1 -1
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +424 -570
- package/front_end/ui/legacy/components/object_ui/objectPropertiesSection.css +2 -27
- package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
- package/mcp/mcp.ts +1 -0
- package/package.json +2 -1
package/eslint.config.mjs
CHANGED
|
@@ -59,6 +59,7 @@ export default defineConfig([
|
|
|
59
59
|
'scripts/migration/**/*.js',
|
|
60
60
|
'scripts/protocol_typescript/*.js',
|
|
61
61
|
'scripts/deps/tests/fixtures',
|
|
62
|
+
'scripts/gn_deps_verifier/tests/fixtures',
|
|
62
63
|
'test/**/fixtures/',
|
|
63
64
|
'test/e2e/**/*.js',
|
|
64
65
|
'test/shared/**/*.js',
|
|
@@ -740,7 +741,8 @@ export default defineConfig([
|
|
|
740
741
|
'front_end/**/*.docs.ts',
|
|
741
742
|
'test/**/*.ts',
|
|
742
743
|
'**/testing/*.ts',
|
|
743
|
-
'scripts/eslint_rules/
|
|
744
|
+
'scripts/eslint_rules/tests/**/*',
|
|
745
|
+
'scripts/gn_deps_verifier/tests/**/*',
|
|
744
746
|
'extensions/cxx_debugging/e2e/**/*.ts',
|
|
745
747
|
'extensions/cxx_debugging/tests/**/*.ts',
|
|
746
748
|
],
|
|
@@ -179,7 +179,11 @@ export class ParsedURL {
|
|
|
179
179
|
preEncodedPath = 'file:///' + preEncodedPath;
|
|
180
180
|
}
|
|
181
181
|
}
|
|
182
|
-
|
|
182
|
+
let url = new URL(preEncodedPath).toString();
|
|
183
|
+
while (url.endsWith('/') && url.length > 'file:///'.length) {
|
|
184
|
+
url = url.substring(0, url.length - 1);
|
|
185
|
+
}
|
|
186
|
+
return url as Platform.DevToolsPath.UrlString;
|
|
183
187
|
}
|
|
184
188
|
|
|
185
189
|
static relativePathToUrlString(
|
|
@@ -498,10 +498,11 @@ export enum DevtoolsExperiments {
|
|
|
498
498
|
'durable-messages' = 110,
|
|
499
499
|
'jpeg-xl' = 111,
|
|
500
500
|
'plus-button' = 112,
|
|
501
|
+
'source-map-scopes-in-sources-panel' = 113,
|
|
501
502
|
/* eslint-enable @typescript-eslint/naming-convention */
|
|
502
503
|
|
|
503
504
|
// Increment this when new experiments are added.
|
|
504
|
-
MAX_VALUE =
|
|
505
|
+
MAX_VALUE = 114,
|
|
505
506
|
}
|
|
506
507
|
|
|
507
508
|
/** Update DevToolsIssuesPanelIssueExpanded from tools/metrics/histograms/enums.xml if new enum is added. **/
|
|
@@ -9,6 +9,7 @@ export enum ExperimentName {
|
|
|
9
9
|
DURABLE_MESSAGES = 'durable-messages',
|
|
10
10
|
JPEG_XL = 'jpeg-xl',
|
|
11
11
|
PLUS_BUTTON = 'plus-button',
|
|
12
|
+
SOURCE_MAP_SCOPES_IN_SOURCES_PANEL = 'source-map-scopes-in-sources-panel',
|
|
12
13
|
// Adding or removing an entry from this enum?
|
|
13
14
|
// You will need to update:
|
|
14
15
|
// 1. DevToolsExperiments enum in host/UserMetrics.ts
|
|
@@ -56,13 +56,8 @@ export class BaseVariableMatch implements Match {
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
// TODO(b/533783988): Remove ValueName handling once https://code.haverbeke.berlin/lezer/css/issues/36 is fixed and rolled.
|
|
60
59
|
function isVariableNameNode(node: CodeMirror.SyntaxNode|null|undefined, ast: SyntaxTree): boolean {
|
|
61
|
-
|
|
62
|
-
return false;
|
|
63
|
-
}
|
|
64
|
-
const text = ast.text(node);
|
|
65
|
-
return text.length > 2 && text.startsWith('--');
|
|
60
|
+
return node?.name === 'VariableName' && ast.text(node).length > 2;
|
|
66
61
|
}
|
|
67
62
|
|
|
68
63
|
const BaseVariableMatcherBase: MatcherClass<BaseVariableMatch> = matcherBase(BaseVariableMatch);
|
|
@@ -1122,7 +1117,7 @@ export class CustomFunctionMatcher extends CustomFunctionMatcherBase {
|
|
|
1122
1117
|
if (node.name !== 'CallExpression') {
|
|
1123
1118
|
return null;
|
|
1124
1119
|
}
|
|
1125
|
-
const callee = matching.ast.text(node.getChild('VariableName')
|
|
1120
|
+
const callee = matching.ast.text(node.getChild('VariableName'));
|
|
1126
1121
|
if (!callee || callee.length <= 2 || !callee.startsWith('--')) {
|
|
1127
1122
|
return null;
|
|
1128
1123
|
}
|
|
@@ -0,0 +1,73 @@
|
|
|
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 Marked from '../../third_party/marked/marked.js';
|
|
6
|
+
|
|
7
|
+
export interface PlaceholderToken extends Marked.Marked.Tokens.Generic {
|
|
8
|
+
type: 'placeholder';
|
|
9
|
+
raw: string;
|
|
10
|
+
key: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const VALID_PLACEHOLDER_MATCH_PATTERN: RegExp = /\{(PLACEHOLDER_[a-zA-Z][a-zA-Z0-9_]*)\}/g;
|
|
14
|
+
const VALID_PLACEHOLDER_NAME_PATTERN = /^PLACEHOLDER_[a-zA-Z][a-zA-Z0-9_]*$/;
|
|
15
|
+
|
|
16
|
+
const placeholderExtension: Marked.Marked.TokenizerExtension = {
|
|
17
|
+
name: 'placeholder',
|
|
18
|
+
level: 'inline',
|
|
19
|
+
start(src: string): number |
|
|
20
|
+
undefined {
|
|
21
|
+
return src.match(/\{PLACEHOLDER_[a-zA-Z][a-zA-Z0-9_]*\}/)?.index;
|
|
22
|
+
},
|
|
23
|
+
tokenizer(src: string): PlaceholderToken |
|
|
24
|
+
undefined {
|
|
25
|
+
const match = /^\{(PLACEHOLDER_[a-zA-Z][a-zA-Z0-9_]*)\}/.exec(src);
|
|
26
|
+
if (match) {
|
|
27
|
+
return {
|
|
28
|
+
type: 'placeholder',
|
|
29
|
+
raw: match[0],
|
|
30
|
+
key: match[1],
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
return undefined;
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export function validateSubstitutions(rawMarkdown: string, substitutions?: Map<string, string>): void {
|
|
38
|
+
if (!substitutions) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const unusedPlaceholders = new Set(substitutions.keys());
|
|
42
|
+
for (const key of unusedPlaceholders) {
|
|
43
|
+
if (!VALID_PLACEHOLDER_NAME_PATTERN.test(key)) {
|
|
44
|
+
throw new Error(`Invalid placeholder '${key}' provided in the substitutions map.`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
for (const [, placeholder] of rawMarkdown.matchAll(VALID_PLACEHOLDER_MATCH_PATTERN)) {
|
|
48
|
+
if (!substitutions.has(placeholder)) {
|
|
49
|
+
throw new Error(`No replacement provided for placeholder '${placeholder}'.`);
|
|
50
|
+
}
|
|
51
|
+
unusedPlaceholders.delete(placeholder);
|
|
52
|
+
}
|
|
53
|
+
if (unusedPlaceholders.size > 0) {
|
|
54
|
+
throw new Error(`Unused replacements provided: ${[...unusedPlaceholders]}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Tokenizes markdown into a Marked AST while preserving `{PLACEHOLDER_*}` tokens
|
|
60
|
+
* as `PlaceholderToken` AST nodes instead of substituting strings before lexing.
|
|
61
|
+
*/
|
|
62
|
+
export function tokenizeWithPlaceholders(markdown: string|Marked.Marked.Token[],
|
|
63
|
+
substitutions?: Map<string, string>): Marked.Marked.Token[] {
|
|
64
|
+
const rawMarkdown = typeof markdown === 'string' ? markdown : markdown.map(token => token.raw).join('');
|
|
65
|
+
validateSubstitutions(rawMarkdown, substitutions);
|
|
66
|
+
if (typeof markdown !== 'string' && !rawMarkdown.includes('{PLACEHOLDER_')) {
|
|
67
|
+
return markdown;
|
|
68
|
+
}
|
|
69
|
+
const markedInstance = new Marked.Marked.Marked({
|
|
70
|
+
extensions: [placeholderExtension],
|
|
71
|
+
});
|
|
72
|
+
return markedInstance.lexer(rawMarkdown);
|
|
73
|
+
}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import * as CodeMirrorUtils from './CodeMirrorUtils.js';
|
|
6
6
|
import * as ContentData from './ContentData.js';
|
|
7
7
|
import * as ContentProvider from './ContentProvider.js';
|
|
8
|
+
import * as Markdown from './Markdown.js';
|
|
8
9
|
import * as StaticContentProvider from './StaticContentProvider.js';
|
|
9
10
|
import * as StreamingContentData from './StreamingContentData.js';
|
|
10
11
|
import * as Text from './Text.js';
|
|
@@ -17,6 +18,7 @@ export {
|
|
|
17
18
|
CodeMirrorUtils,
|
|
18
19
|
ContentData,
|
|
19
20
|
ContentProvider,
|
|
21
|
+
Markdown,
|
|
20
22
|
StaticContentProvider,
|
|
21
23
|
StreamingContentData,
|
|
22
24
|
Text,
|
|
@@ -415,6 +415,14 @@ export class MainImpl {
|
|
|
415
415
|
requiresChromeRestart: false,
|
|
416
416
|
});
|
|
417
417
|
|
|
418
|
+
Root.Runtime.experiments.register({
|
|
419
|
+
name: Root.ExperimentNames.ExperimentName.SOURCE_MAP_SCOPES_IN_SOURCES_PANEL,
|
|
420
|
+
title: 'Source map scopes in the Sources panel',
|
|
421
|
+
aboutFlag: 'devtools-source-map-scopes-in-sources-panel',
|
|
422
|
+
isEnabled: Root.Runtime.hostConfig.devToolsSourceMapScopesInSourcesPanel?.enabled ?? false,
|
|
423
|
+
requiresChromeRestart: false,
|
|
424
|
+
});
|
|
425
|
+
|
|
418
426
|
for (const experiment of Root.Runtime.experiments.allConfigurableExperiments()) {
|
|
419
427
|
if (experiment.isEnabled()) {
|
|
420
428
|
Host.userMetrics.experimentEnabledAtLaunch(experiment.name);
|
|
@@ -73,7 +73,7 @@ inspectorBackend.registerType("Animation.KeyframesRule", [{"name": "name", "type
|
|
|
73
73
|
inspectorBackend.registerType("Animation.KeyframeStyle", [{"name": "offset", "type": "string", "optional": false, "description": "Keyframe's time offset.", "typeRef": null}, {"name": "easing", "type": "string", "optional": false, "description": "`AnimationEffect`'s timing function.", "typeRef": null}]);
|
|
74
74
|
|
|
75
75
|
// Audits.
|
|
76
|
-
inspectorBackend.registerEnum("Audits.CookieExclusionReason", {ExcludeSameSiteUnspecifiedTreatedAsLax: "ExcludeSameSiteUnspecifiedTreatedAsLax", ExcludeSameSiteNoneInsecure: "ExcludeSameSiteNoneInsecure", ExcludeSameSiteLax: "ExcludeSameSiteLax", ExcludeSameSiteStrict: "ExcludeSameSiteStrict", ExcludeDomainNonASCII: "ExcludeDomainNonASCII",
|
|
76
|
+
inspectorBackend.registerEnum("Audits.CookieExclusionReason", {ExcludeSameSiteUnspecifiedTreatedAsLax: "ExcludeSameSiteUnspecifiedTreatedAsLax", ExcludeSameSiteNoneInsecure: "ExcludeSameSiteNoneInsecure", ExcludeSameSiteLax: "ExcludeSameSiteLax", ExcludeSameSiteStrict: "ExcludeSameSiteStrict", ExcludeDomainNonASCII: "ExcludeDomainNonASCII", ExcludeThirdPartyPhaseout: "ExcludeThirdPartyPhaseout", ExcludePortMismatch: "ExcludePortMismatch", ExcludeSchemeMismatch: "ExcludeSchemeMismatch"});
|
|
77
77
|
inspectorBackend.registerEnum("Audits.CookieWarningReason", {WarnSameSiteUnspecifiedCrossSiteContext: "WarnSameSiteUnspecifiedCrossSiteContext", WarnSameSiteNoneInsecure: "WarnSameSiteNoneInsecure", WarnSameSiteUnspecifiedLaxAllowUnsafe: "WarnSameSiteUnspecifiedLaxAllowUnsafe", WarnSameSiteStrictLaxDowngradeStrict: "WarnSameSiteStrictLaxDowngradeStrict", WarnSameSiteStrictCrossDowngradeStrict: "WarnSameSiteStrictCrossDowngradeStrict", WarnSameSiteStrictCrossDowngradeLax: "WarnSameSiteStrictCrossDowngradeLax", WarnSameSiteLaxCrossDowngradeStrict: "WarnSameSiteLaxCrossDowngradeStrict", WarnSameSiteLaxCrossDowngradeLax: "WarnSameSiteLaxCrossDowngradeLax", WarnAttributeValueExceedsMaxSize: "WarnAttributeValueExceedsMaxSize", WarnDomainNonASCII: "WarnDomainNonASCII", WarnThirdPartyPhaseout: "WarnThirdPartyPhaseout", WarnCrossSiteRedirectDowngradeChangesInclusion: "WarnCrossSiteRedirectDowngradeChangesInclusion", WarnDeprecationTrialMetadata: "WarnDeprecationTrialMetadata", WarnThirdPartyCookieHeuristic: "WarnThirdPartyCookieHeuristic"});
|
|
78
78
|
inspectorBackend.registerEnum("Audits.CookieOperation", {SetCookie: "SetCookie", ReadCookie: "ReadCookie"});
|
|
79
79
|
inspectorBackend.registerEnum("Audits.InsightType", {GitHubResource: "GitHubResource", GracePeriod: "GracePeriod", Heuristics: "Heuristics"});
|
|
@@ -815,8 +815,8 @@ inspectorBackend.registerEnum("Network.TrustTokenOperationType", {Issuance: "Iss
|
|
|
815
815
|
inspectorBackend.registerEnum("Network.AlternateProtocolUsage", {AlternativeJobWonWithoutRace: "alternativeJobWonWithoutRace", AlternativeJobWonRace: "alternativeJobWonRace", MainJobWonRace: "mainJobWonRace", MappingMissing: "mappingMissing", Broken: "broken", DnsAlpnH3JobWonWithoutRace: "dnsAlpnH3JobWonWithoutRace", DnsAlpnH3JobWonRace: "dnsAlpnH3JobWonRace", UnspecifiedReason: "unspecifiedReason"});
|
|
816
816
|
inspectorBackend.registerEnum("Network.ServiceWorkerRouterSource", {Network: "network", Cache: "cache", FetchEvent: "fetch-event", RaceNetworkAndFetchHandler: "race-network-and-fetch-handler", RaceNetworkAndCache: "race-network-and-cache"});
|
|
817
817
|
inspectorBackend.registerEnum("Network.InitiatorType", {Parser: "parser", Script: "script", Preload: "preload", SignedExchange: "SignedExchange", Preflight: "preflight", FedCM: "FedCM", Other: "other"});
|
|
818
|
-
inspectorBackend.registerEnum("Network.SetCookieBlockedReason", {SecureOnly: "SecureOnly", SameSiteStrict: "SameSiteStrict", SameSiteLax: "SameSiteLax", SameSiteUnspecifiedTreatedAsLax: "SameSiteUnspecifiedTreatedAsLax", SameSiteNoneInsecure: "SameSiteNoneInsecure", UserPreferences: "UserPreferences", ThirdPartyPhaseout: "ThirdPartyPhaseout",
|
|
819
|
-
inspectorBackend.registerEnum("Network.CookieBlockedReason", {SecureOnly: "SecureOnly", NotOnPath: "NotOnPath", DomainMismatch: "DomainMismatch", SameSiteStrict: "SameSiteStrict", SameSiteLax: "SameSiteLax", SameSiteUnspecifiedTreatedAsLax: "SameSiteUnspecifiedTreatedAsLax", SameSiteNoneInsecure: "SameSiteNoneInsecure", UserPreferences: "UserPreferences", ThirdPartyPhaseout: "ThirdPartyPhaseout",
|
|
818
|
+
inspectorBackend.registerEnum("Network.SetCookieBlockedReason", {SecureOnly: "SecureOnly", SameSiteStrict: "SameSiteStrict", SameSiteLax: "SameSiteLax", SameSiteUnspecifiedTreatedAsLax: "SameSiteUnspecifiedTreatedAsLax", SameSiteNoneInsecure: "SameSiteNoneInsecure", UserPreferences: "UserPreferences", ThirdPartyPhaseout: "ThirdPartyPhaseout", SyntaxError: "SyntaxError", SchemeNotSupported: "SchemeNotSupported", OverwriteSecure: "OverwriteSecure", InvalidDomain: "InvalidDomain", InvalidPrefix: "InvalidPrefix", UnknownError: "UnknownError", SchemefulSameSiteStrict: "SchemefulSameSiteStrict", SchemefulSameSiteLax: "SchemefulSameSiteLax", SchemefulSameSiteUnspecifiedTreatedAsLax: "SchemefulSameSiteUnspecifiedTreatedAsLax", NameValuePairExceedsMaxSize: "NameValuePairExceedsMaxSize", DisallowedCharacter: "DisallowedCharacter", NoCookieContent: "NoCookieContent"});
|
|
819
|
+
inspectorBackend.registerEnum("Network.CookieBlockedReason", {SecureOnly: "SecureOnly", NotOnPath: "NotOnPath", DomainMismatch: "DomainMismatch", SameSiteStrict: "SameSiteStrict", SameSiteLax: "SameSiteLax", SameSiteUnspecifiedTreatedAsLax: "SameSiteUnspecifiedTreatedAsLax", SameSiteNoneInsecure: "SameSiteNoneInsecure", UserPreferences: "UserPreferences", ThirdPartyPhaseout: "ThirdPartyPhaseout", UnknownError: "UnknownError", SchemefulSameSiteStrict: "SchemefulSameSiteStrict", SchemefulSameSiteLax: "SchemefulSameSiteLax", SchemefulSameSiteUnspecifiedTreatedAsLax: "SchemefulSameSiteUnspecifiedTreatedAsLax", NameValuePairExceedsMaxSize: "NameValuePairExceedsMaxSize", PortMismatch: "PortMismatch", SchemeMismatch: "SchemeMismatch", AnonymousContext: "AnonymousContext"});
|
|
820
820
|
inspectorBackend.registerEnum("Network.CookieExemptionReason", {None: "None", UserSetting: "UserSetting", EnterprisePolicy: "EnterprisePolicy", StorageAccess: "StorageAccess", TopLevelStorageAccess: "TopLevelStorageAccess", Scheme: "Scheme", SameSiteNoneCookiesInSandbox: "SameSiteNoneCookiesInSandbox"});
|
|
821
821
|
inspectorBackend.registerEnum("Network.AuthChallengeSource", {Server: "Server", Proxy: "Proxy"});
|
|
822
822
|
inspectorBackend.registerEnum("Network.AuthChallengeResponseResponse", {Default: "Default", CancelAuth: "CancelAuth", ProvideCredentials: "ProvideCredentials"});
|
|
@@ -1183,7 +1183,7 @@ inspectorBackend.registerType("Page.FrameResource", [{"name": "url", "type": "st
|
|
|
1183
1183
|
inspectorBackend.registerType("Page.FrameResourceTree", [{"name": "frame", "type": "object", "optional": false, "description": "Frame information for this tree item.", "typeRef": "Page.Frame"}, {"name": "childFrames", "type": "array", "optional": true, "description": "Child frames.", "typeRef": "Page.FrameResourceTree"}, {"name": "resources", "type": "array", "optional": false, "description": "Information about frame resources.", "typeRef": "Page.FrameResource"}]);
|
|
1184
1184
|
inspectorBackend.registerType("Page.FrameTree", [{"name": "frame", "type": "object", "optional": false, "description": "Frame information for this tree item.", "typeRef": "Page.Frame"}, {"name": "childFrames", "type": "array", "optional": true, "description": "Child frames.", "typeRef": "Page.FrameTree"}]);
|
|
1185
1185
|
inspectorBackend.registerType("Page.NavigationEntry", [{"name": "id", "type": "number", "optional": false, "description": "Unique id of the navigation history entry.", "typeRef": null}, {"name": "url", "type": "string", "optional": false, "description": "URL of the navigation history entry.", "typeRef": null}, {"name": "userTypedURL", "type": "string", "optional": false, "description": "URL that the user typed in the url bar.", "typeRef": null}, {"name": "title", "type": "string", "optional": false, "description": "Title of the navigation history entry.", "typeRef": null}, {"name": "transitionType", "type": "string", "optional": false, "description": "Transition type.", "typeRef": "Page.TransitionType"}]);
|
|
1186
|
-
inspectorBackend.registerType("Page.ScreencastFrameMetadata", [{"name": "offsetTop", "type": "number", "optional": false, "description": "Top offset in DIP.", "typeRef": null}, {"name": "pageScaleFactor", "type": "number", "optional": false, "description": "Page scale factor.", "typeRef": null}, {"name": "deviceWidth", "type": "number", "optional": false, "description": "Device screen width in DIP.", "typeRef": null}, {"name": "deviceHeight", "type": "number", "optional": false, "description": "Device screen height in DIP.", "typeRef": null}, {"name": "scrollOffsetX", "type": "number", "optional": false, "description": "Position of horizontal scroll in CSS pixels.", "typeRef": null}, {"name": "scrollOffsetY", "type": "number", "optional": false, "description": "Position of vertical scroll in CSS pixels.", "typeRef": null}, {"name": "timestamp", "type": "number", "optional": true, "description": "Frame swap timestamp.", "typeRef": "Network.TimeSinceEpoch"}]);
|
|
1186
|
+
inspectorBackend.registerType("Page.ScreencastFrameMetadata", [{"name": "offsetTop", "type": "number", "optional": false, "description": "Top offset in DIP.", "typeRef": null}, {"name": "pageScaleFactor", "type": "number", "optional": false, "description": "Page scale factor.", "typeRef": null}, {"name": "deviceWidth", "type": "number", "optional": false, "description": "Device screen width in DIP.", "typeRef": null}, {"name": "deviceHeight", "type": "number", "optional": false, "description": "Device screen height in DIP.", "typeRef": null}, {"name": "scrollOffsetX", "type": "number", "optional": false, "description": "Position of horizontal scroll in CSS pixels.", "typeRef": null}, {"name": "scrollOffsetY", "type": "number", "optional": false, "description": "Position of vertical scroll in CSS pixels.", "typeRef": null}, {"name": "timestamp", "type": "number", "optional": true, "description": "Frame swap timestamp.", "typeRef": "Network.TimeSinceEpoch"}, {"name": "monotonicTimestamp", "type": "number", "optional": true, "description": "Frame swap timestamp as monotonic time.", "typeRef": "Network.MonotonicTime"}]);
|
|
1187
1187
|
inspectorBackend.registerType("Page.AppManifestError", [{"name": "message", "type": "string", "optional": false, "description": "Error message.", "typeRef": null}, {"name": "critical", "type": "number", "optional": false, "description": "If critical, this is a non-recoverable parse error.", "typeRef": null}, {"name": "line", "type": "number", "optional": false, "description": "Error line.", "typeRef": null}, {"name": "column", "type": "number", "optional": false, "description": "Error column.", "typeRef": null}]);
|
|
1188
1188
|
inspectorBackend.registerType("Page.AppManifestParsedProperties", [{"name": "scope", "type": "string", "optional": false, "description": "Computed scope value", "typeRef": null}]);
|
|
1189
1189
|
inspectorBackend.registerType("Page.LayoutViewport", [{"name": "pageX", "type": "number", "optional": false, "description": "Horizontal offset relative to the document (CSS pixels).", "typeRef": null}, {"name": "pageY", "type": "number", "optional": false, "description": "Vertical offset relative to the document (CSS pixels).", "typeRef": null}, {"name": "clientWidth", "type": "number", "optional": false, "description": "Width (CSS pixels), excludes scrollbar if present.", "typeRef": null}, {"name": "clientHeight", "type": "number", "optional": false, "description": "Height (CSS pixels), excludes scrollbar if present.", "typeRef": null}]);
|
|
@@ -1362,6 +1362,7 @@ inspectorBackend.registerCommand("Storage.untrackIndexedDBForStorageKey", [{"nam
|
|
|
1362
1362
|
inspectorBackend.registerCommand("Storage.getTrustTokens", [], ["tokens"], "Returns the number of stored Trust Tokens per issuer for the current browsing context.");
|
|
1363
1363
|
inspectorBackend.registerCommand("Storage.clearTrustTokens", [{"name": "issuerOrigin", "type": "string", "optional": false, "description": "", "typeRef": null}], ["didDeleteTokens"], "Removes all Trust Tokens issued by the provided issuerOrigin. Leaves other stored data, including the issuer's Redemption Records, intact.");
|
|
1364
1364
|
inspectorBackend.registerCommand("Storage.getPrivateVerificationTokens", [], ["tokens"], "Returns all stored Private Verification Tokens for the current browsing context.");
|
|
1365
|
+
inspectorBackend.registerCommand("Storage.getPrivateVerificationTokensIssuerConfigs", [], ["configs"], "Returns the configured Private Verification Tokens issuers and their redeemer origins.");
|
|
1365
1366
|
inspectorBackend.registerCommand("Storage.clearPrivateVerificationTokens", [{"name": "issuerOrigin", "type": "string", "optional": false, "description": "", "typeRef": null}], [], "Removes all Private Verification Tokens issued by the provided issuerOrigin.");
|
|
1366
1367
|
inspectorBackend.registerCommand("Storage.deletePrivateVerificationToken", [{"name": "tokenId", "type": "string", "optional": false, "description": "", "typeRef": null}], [], "Removes a specific Private Verification Token by its ID.");
|
|
1367
1368
|
inspectorBackend.registerCommand("Storage.setPrivateVerificationTokensTracking", [{"name": "enable", "type": "boolean", "optional": false, "description": "", "typeRef": null}], [], "Set tracking for Private Verification Tokens.");
|
|
@@ -1371,6 +1372,7 @@ inspectorBackend.registerCommand("Storage.runBounceTrackingMitigations", [], ["d
|
|
|
1371
1372
|
inspectorBackend.registerType("Storage.UsageForType", [{"name": "storageType", "type": "string", "optional": false, "description": "Name of storage type.", "typeRef": "Storage.StorageType"}, {"name": "usage", "type": "number", "optional": false, "description": "Storage usage (bytes).", "typeRef": null}]);
|
|
1372
1373
|
inspectorBackend.registerType("Storage.TrustTokens", [{"name": "issuerOrigin", "type": "string", "optional": false, "description": "", "typeRef": null}, {"name": "count", "type": "number", "optional": false, "description": "", "typeRef": null}]);
|
|
1373
1374
|
inspectorBackend.registerType("Storage.PrivateVerificationToken", [{"name": "id", "type": "string", "optional": false, "description": "Unique identifier of the token in the database.", "typeRef": null}, {"name": "issuerOrigin", "type": "string", "optional": false, "description": "Origin of the token issuer.", "typeRef": null}, {"name": "keyId", "type": "number", "optional": false, "description": "Public key ID used to issue the token.", "typeRef": null}, {"name": "expiration", "type": "number", "optional": false, "description": "Expiration timestamp in seconds since the epoch.", "typeRef": "Network.TimeSinceEpoch"}, {"name": "creationTime", "type": "number", "optional": false, "description": "Token creation timestamp in seconds since the epoch.", "typeRef": "Network.TimeSinceEpoch"}, {"name": "version", "type": "number", "optional": false, "description": "Token protocol version.", "typeRef": null}, {"name": "token", "type": "string", "optional": false, "description": "Base64-encoded serialized token.", "typeRef": null}]);
|
|
1375
|
+
inspectorBackend.registerType("Storage.PrivateVerificationTokensIssuerConfig", [{"name": "issuerOrigin", "type": "string", "optional": false, "description": "Origin of the token issuer.", "typeRef": null}, {"name": "redeemerOrigins", "type": "array", "optional": false, "description": "Origins authorized to redeem tokens from this issuer.", "typeRef": "string"}]);
|
|
1374
1376
|
inspectorBackend.registerType("Storage.StorageBucket", [{"name": "storageKey", "type": "string", "optional": false, "description": "", "typeRef": "Storage.SerializedStorageKey"}, {"name": "name", "type": "string", "optional": true, "description": "If not specified, it is the default bucket of the storageKey.", "typeRef": null}]);
|
|
1375
1377
|
inspectorBackend.registerType("Storage.StorageBucketInfo", [{"name": "bucket", "type": "object", "optional": false, "description": "", "typeRef": "Storage.StorageBucket"}, {"name": "id", "type": "string", "optional": false, "description": "", "typeRef": null}, {"name": "expiration", "type": "number", "optional": false, "description": "", "typeRef": "Network.TimeSinceEpoch"}, {"name": "quota", "type": "number", "optional": false, "description": "Storage quota (bytes).", "typeRef": null}, {"name": "persistent", "type": "boolean", "optional": false, "description": "", "typeRef": null}, {"name": "durability", "type": "string", "optional": false, "description": "", "typeRef": "Storage.StorageBucketsDurability"}]);
|
|
1376
1378
|
|
|
@@ -4954,6 +4954,14 @@ export namespace ProtocolMapping {
|
|
|
4954
4954
|
paramsType: [];
|
|
4955
4955
|
returnType: Protocol.Storage.GetPrivateVerificationTokensResponse;
|
|
4956
4956
|
};
|
|
4957
|
+
/**
|
|
4958
|
+
* Returns the configured Private Verification Tokens issuers and their redeemer
|
|
4959
|
+
* origins.
|
|
4960
|
+
*/
|
|
4961
|
+
'Storage.getPrivateVerificationTokensIssuerConfigs': {
|
|
4962
|
+
paramsType: [];
|
|
4963
|
+
returnType: Protocol.Storage.GetPrivateVerificationTokensIssuerConfigsResponse;
|
|
4964
|
+
};
|
|
4957
4965
|
/**
|
|
4958
4966
|
* Removes all Private Verification Tokens issued by the provided issuerOrigin.
|
|
4959
4967
|
*/
|
|
@@ -4331,6 +4331,12 @@ declare namespace ProtocolProxyApi {
|
|
|
4331
4331
|
*/
|
|
4332
4332
|
invoke_getPrivateVerificationTokens(): Promise<Protocol.Storage.GetPrivateVerificationTokensResponse>;
|
|
4333
4333
|
|
|
4334
|
+
/**
|
|
4335
|
+
* Returns the configured Private Verification Tokens issuers and their redeemer
|
|
4336
|
+
* origins.
|
|
4337
|
+
*/
|
|
4338
|
+
invoke_getPrivateVerificationTokensIssuerConfigs(): Promise<Protocol.Storage.GetPrivateVerificationTokensIssuerConfigsResponse>;
|
|
4339
|
+
|
|
4334
4340
|
/**
|
|
4335
4341
|
* Removes all Private Verification Tokens issued by the provided issuerOrigin.
|
|
4336
4342
|
*/
|
|
@@ -875,7 +875,6 @@ export namespace Audits {
|
|
|
875
875
|
ExcludeSameSiteLax = 'ExcludeSameSiteLax',
|
|
876
876
|
ExcludeSameSiteStrict = 'ExcludeSameSiteStrict',
|
|
877
877
|
ExcludeDomainNonASCII = 'ExcludeDomainNonASCII',
|
|
878
|
-
ExcludeThirdPartyCookieBlockedInFirstPartySet = 'ExcludeThirdPartyCookieBlockedInFirstPartySet',
|
|
879
878
|
ExcludeThirdPartyPhaseout = 'ExcludeThirdPartyPhaseout',
|
|
880
879
|
ExcludePortMismatch = 'ExcludePortMismatch',
|
|
881
880
|
ExcludeSchemeMismatch = 'ExcludeSchemeMismatch',
|
|
@@ -11318,7 +11317,6 @@ export namespace Network {
|
|
|
11318
11317
|
SameSiteNoneInsecure = 'SameSiteNoneInsecure',
|
|
11319
11318
|
UserPreferences = 'UserPreferences',
|
|
11320
11319
|
ThirdPartyPhaseout = 'ThirdPartyPhaseout',
|
|
11321
|
-
ThirdPartyBlockedInFirstPartySet = 'ThirdPartyBlockedInFirstPartySet',
|
|
11322
11320
|
SyntaxError = 'SyntaxError',
|
|
11323
11321
|
SchemeNotSupported = 'SchemeNotSupported',
|
|
11324
11322
|
OverwriteSecure = 'OverwriteSecure',
|
|
@@ -11346,7 +11344,6 @@ export namespace Network {
|
|
|
11346
11344
|
SameSiteNoneInsecure = 'SameSiteNoneInsecure',
|
|
11347
11345
|
UserPreferences = 'UserPreferences',
|
|
11348
11346
|
ThirdPartyPhaseout = 'ThirdPartyPhaseout',
|
|
11349
|
-
ThirdPartyBlockedInFirstPartySet = 'ThirdPartyBlockedInFirstPartySet',
|
|
11350
11347
|
UnknownError = 'UnknownError',
|
|
11351
11348
|
SchemefulSameSiteStrict = 'SchemefulSameSiteStrict',
|
|
11352
11349
|
SchemefulSameSiteLax = 'SchemefulSameSiteLax',
|
|
@@ -15136,6 +15133,10 @@ export namespace Page {
|
|
|
15136
15133
|
* Frame swap timestamp.
|
|
15137
15134
|
*/
|
|
15138
15135
|
timestamp?: Network.TimeSinceEpoch;
|
|
15136
|
+
/**
|
|
15137
|
+
* Frame swap timestamp as monotonic time.
|
|
15138
|
+
*/
|
|
15139
|
+
monotonicTimestamp?: Network.MonotonicTime;
|
|
15139
15140
|
}
|
|
15140
15141
|
|
|
15141
15142
|
/**
|
|
@@ -18507,6 +18508,20 @@ export namespace Storage {
|
|
|
18507
18508
|
token: string;
|
|
18508
18509
|
}
|
|
18509
18510
|
|
|
18511
|
+
/**
|
|
18512
|
+
* Configuration for a Private Verification Tokens issuer.
|
|
18513
|
+
*/
|
|
18514
|
+
export interface PrivateVerificationTokensIssuerConfig {
|
|
18515
|
+
/**
|
|
18516
|
+
* Origin of the token issuer.
|
|
18517
|
+
*/
|
|
18518
|
+
issuerOrigin: string;
|
|
18519
|
+
/**
|
|
18520
|
+
* Origins authorized to redeem tokens from this issuer.
|
|
18521
|
+
*/
|
|
18522
|
+
redeemerOrigins: string[];
|
|
18523
|
+
}
|
|
18524
|
+
|
|
18510
18525
|
export const enum StorageBucketsDurability {
|
|
18511
18526
|
Relaxed = 'relaxed',
|
|
18512
18527
|
Strict = 'strict',
|
|
@@ -18720,6 +18735,10 @@ export namespace Storage {
|
|
|
18720
18735
|
tokens: PrivateVerificationToken[];
|
|
18721
18736
|
}
|
|
18722
18737
|
|
|
18738
|
+
export interface GetPrivateVerificationTokensIssuerConfigsResponse extends ProtocolResponseWithError {
|
|
18739
|
+
configs: PrivateVerificationTokensIssuerConfig[];
|
|
18740
|
+
}
|
|
18741
|
+
|
|
18723
18742
|
export interface ClearPrivateVerificationTokensRequest {
|
|
18724
18743
|
issuerOrigin: string;
|
|
18725
18744
|
}
|
|
@@ -141,7 +141,19 @@ export class AiAgent2 extends AiAgent<unknown> {
|
|
|
141
141
|
readonly #declaredTools = new Set<string>();
|
|
142
142
|
|
|
143
143
|
constructor(opts: AiAgent2Options) {
|
|
144
|
-
super(
|
|
144
|
+
super({
|
|
145
|
+
...opts,
|
|
146
|
+
allowedOrigin: opts.allowedOrigin ?? (() => {
|
|
147
|
+
const lock = opts.originLock();
|
|
148
|
+
if (lock.status === 'BLOCKED_BY_NAVIGATION') {
|
|
149
|
+
return {blocked: true};
|
|
150
|
+
}
|
|
151
|
+
if (lock.status === 'ESTABLISHED_ORIGIN') {
|
|
152
|
+
return {origin: lock.origin};
|
|
153
|
+
}
|
|
154
|
+
return {origin: undefined};
|
|
155
|
+
}),
|
|
156
|
+
});
|
|
145
157
|
this.#changes = opts.changeManager ?? new ChangeManager(opts.targetManager);
|
|
146
158
|
this.#lighthouseRecording = opts.lighthouseRecording;
|
|
147
159
|
this.#performanceRecordAndReload = opts.performanceRecordAndReload;
|
|
@@ -434,7 +434,7 @@ export class AiConversation {
|
|
|
434
434
|
} = {},
|
|
435
435
|
): AsyncGenerator<ResponseData, void, void> {
|
|
436
436
|
this.#navigationOccurredDuringRun = false;
|
|
437
|
-
const originAtRunStart = getPrimaryPageSecurityOrigin(this.#targetManager);
|
|
437
|
+
const originAtRunStart = this.#origin ?? getPrimaryPageSecurityOrigin(this.#targetManager);
|
|
438
438
|
const listener = (): void => {
|
|
439
439
|
// Prevent the agent from executing tools or reading data from an untrusted origin
|
|
440
440
|
// if the page navigates unexpectedly during execution.
|
|
@@ -148,13 +148,12 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
148
148
|
};
|
|
149
149
|
}
|
|
150
150
|
const origin = allowedOriginResult.origin;
|
|
151
|
-
if (origin
|
|
151
|
+
if (!origin || origin.isOpaque()) {
|
|
152
152
|
return {
|
|
153
153
|
error: 'No requests recorded by DevTools',
|
|
154
154
|
};
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
const allowedSecurityOrigin = origin ?? null;
|
|
158
157
|
let hasCrossOriginRequest = false;
|
|
159
158
|
const requestsToShow: NetworkRequest[] = [];
|
|
160
159
|
for (const request of this.#networkLog.requests()) {
|
|
@@ -166,7 +165,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
166
165
|
* during the loading of the target page, and do not leak URLs from
|
|
167
166
|
* other pages.
|
|
168
167
|
*/
|
|
169
|
-
if (
|
|
168
|
+
if (!isOriginAllowedByLock({status: 'ESTABLISHED_ORIGIN', origin}, request.initiatorSecurityOrigin())) {
|
|
170
169
|
hasCrossOriginRequest = true;
|
|
171
170
|
continue;
|
|
172
171
|
}
|
|
@@ -184,7 +183,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
184
183
|
if (requests.length === 0) {
|
|
185
184
|
return {
|
|
186
185
|
error: hasCrossOriginRequest ?
|
|
187
|
-
`No requests showing with origin ${origin
|
|
186
|
+
`No requests showing with origin ${origin.siteId()}. Tell the user to start a new chat` :
|
|
188
187
|
'No requests recorded by DevTools',
|
|
189
188
|
};
|
|
190
189
|
}
|
|
@@ -231,18 +230,17 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
231
230
|
};
|
|
232
231
|
}
|
|
233
232
|
const origin = allowedOriginResult.origin;
|
|
234
|
-
if (origin
|
|
233
|
+
if (!origin || origin.isOpaque()) {
|
|
235
234
|
return {
|
|
236
235
|
error: 'No request found',
|
|
237
236
|
};
|
|
238
237
|
}
|
|
239
|
-
const allowedSecurityOrigin = origin ?? null;
|
|
240
238
|
const request = this.#networkLog.requests().find(req => {
|
|
241
239
|
if (req.requestId() !== id) {
|
|
242
240
|
return false;
|
|
243
241
|
}
|
|
244
242
|
|
|
245
|
-
return
|
|
243
|
+
return isOriginAllowedByLock({status: 'ESTABLISHED_ORIGIN', origin}, req.initiatorSecurityOrigin());
|
|
246
244
|
});
|
|
247
245
|
|
|
248
246
|
if (request) {
|
|
@@ -288,13 +286,16 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
288
286
|
};
|
|
289
287
|
}
|
|
290
288
|
const origin = allowedOriginResult.origin;
|
|
289
|
+
if (!origin || origin.isOpaque()) {
|
|
290
|
+
return {
|
|
291
|
+
result: [],
|
|
292
|
+
};
|
|
293
|
+
}
|
|
291
294
|
|
|
292
295
|
const files: Array<{file: string, id: number | undefined}> = [];
|
|
293
296
|
const uiSourceCodes: Workspace.UISourceCode.UISourceCode[] = [];
|
|
294
297
|
for (const file of ContextSelectionAgent.getUISourceCodes(this.#workspace)) {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
if (origin && !fileSecurityOrigin.isSameOriginWith(origin)) {
|
|
298
|
+
if (!isOriginAllowedByLock({status: 'ESTABLISHED_ORIGIN', origin}, file.securityOrigin())) {
|
|
298
299
|
continue;
|
|
299
300
|
}
|
|
300
301
|
|
|
@@ -347,14 +348,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
347
348
|
};
|
|
348
349
|
}
|
|
349
350
|
const origin = allowedOriginResult.origin;
|
|
350
|
-
|
|
351
|
-
const file = ContextSelectionAgent.getUISourceCodes(this.#workspace).find(file => {
|
|
352
|
-
if (ContextSelectionAgent.uiSourceCodeId.get(file) !== params.id) {
|
|
353
|
-
return false;
|
|
354
|
-
}
|
|
355
|
-
const fileSecurityOrigin = file.securityOrigin();
|
|
356
|
-
return !origin || fileSecurityOrigin.isSameOriginWith(origin);
|
|
357
|
-
});
|
|
351
|
+
const file = ContextSelectionAgent.getSourceById(params.id, origin, this.#workspace);
|
|
358
352
|
|
|
359
353
|
if (!file) {
|
|
360
354
|
return {
|
|
@@ -524,7 +518,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
524
518
|
};
|
|
525
519
|
}
|
|
526
520
|
const origin = allowedOriginResult.origin;
|
|
527
|
-
if (!origin) {
|
|
521
|
+
if (!origin || origin.isOpaque()) {
|
|
528
522
|
return {
|
|
529
523
|
error: 'Unable to find page storage.',
|
|
530
524
|
};
|
|
@@ -5,23 +5,11 @@
|
|
|
5
5
|
import * as Root from '../../core/root/root.js';
|
|
6
6
|
import type * as CommentManager from '../comment_manager/comment_manager.js';
|
|
7
7
|
|
|
8
|
-
export type ChangeRecord = CommentManager.CommentManager.ChangeRecord;
|
|
9
|
-
|
|
10
|
-
export const MAX_RECORDS = 1000;
|
|
11
|
-
|
|
12
8
|
export class ChangeTracker {
|
|
13
|
-
readonly #records = new Map<string, ChangeRecord>();
|
|
14
9
|
readonly #commentManager: CommentManager.CommentManager.CommentManager;
|
|
15
|
-
readonly #maxRecords: number;
|
|
16
|
-
#lastRecord?: ChangeRecord;
|
|
17
10
|
|
|
18
|
-
constructor(commentManager: CommentManager.CommentManager.CommentManager
|
|
11
|
+
constructor(commentManager: CommentManager.CommentManager.CommentManager) {
|
|
19
12
|
this.#commentManager = commentManager;
|
|
20
|
-
this.#maxRecords = Math.max(1, maxRecords);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
get maxRecords(): number {
|
|
24
|
-
return this.#maxRecords;
|
|
25
13
|
}
|
|
26
14
|
|
|
27
15
|
get isTracking(): boolean {
|
|
@@ -31,59 +19,12 @@ export class ChangeTracker {
|
|
|
31
19
|
trackChange(
|
|
32
20
|
description: string,
|
|
33
21
|
anchor: CommentManager.CommentManager.CommentAnchorSignature,
|
|
34
|
-
):
|
|
22
|
+
): void {
|
|
35
23
|
if (!this.isTracking) {
|
|
36
|
-
return
|
|
37
|
-
}
|
|
38
|
-
const record: ChangeRecord = {
|
|
39
|
-
id: crypto.randomUUID(),
|
|
40
|
-
description,
|
|
41
|
-
timestamp: Date.now(),
|
|
42
|
-
};
|
|
43
|
-
while (this.#records.size >= this.#maxRecords) {
|
|
44
|
-
this.#evictOldestRecord();
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const thread = this.#commentManager.createCommentThread(anchor, undefined, undefined, [record]);
|
|
48
|
-
this.#records.set(thread.id, record);
|
|
49
|
-
this.#lastRecord = record;
|
|
50
|
-
return record;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
#evictOldestRecord(): void {
|
|
54
|
-
// Delete the oldest record for which the comment thread has no user comments.
|
|
55
|
-
// If all comment threads have user comments, delete the oldest record.
|
|
56
|
-
for (const threadId of this.#records.keys()) {
|
|
57
|
-
const thread = this.#commentManager.getCommentThread(threadId);
|
|
58
|
-
if (!thread || thread.comments.length === 0) {
|
|
59
|
-
this.#commentManager.removeCommentThread(threadId);
|
|
60
|
-
this.#records.delete(threadId);
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
24
|
+
return;
|
|
63
25
|
}
|
|
64
26
|
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
this.#records.delete(oldestThreadId);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
getChanges(): ChangeRecord[] {
|
|
72
|
-
return Array.from(this.#records.values());
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
getLastChange(): ChangeRecord|undefined {
|
|
76
|
-
return this.#lastRecord;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
clear(): void {
|
|
80
|
-
for (const threadId of this.#records.keys()) {
|
|
81
|
-
const thread = this.#commentManager.getCommentThread(threadId);
|
|
82
|
-
if (!thread || thread.comments.length === 0) {
|
|
83
|
-
this.#commentManager.removeCommentThread(threadId);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
this.#records.clear();
|
|
87
|
-
this.#lastRecord = undefined;
|
|
27
|
+
const thread = this.#commentManager.createCommentThread(anchor, description, 'DEVELOPER', true);
|
|
28
|
+
thread.save();
|
|
88
29
|
}
|
|
89
30
|
}
|
|
@@ -87,8 +87,13 @@ export class CD4ABridge extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
|
|
|
87
87
|
|
|
88
88
|
#formatCommentText(thread: CommentManager.CommentThread): string {
|
|
89
89
|
const rawText = thread.comments[0]?.text ?? '';
|
|
90
|
+
|
|
90
91
|
const details: string[] = [];
|
|
91
92
|
|
|
93
|
+
if (thread.anchor.vePath) {
|
|
94
|
+
details.push(`- DevTools VEPath: ${thread.anchor.vePath}`);
|
|
95
|
+
}
|
|
96
|
+
|
|
92
97
|
if (thread.anchor.textSignature) {
|
|
93
98
|
details.push(`- DevTools element: ${thread.anchor.textSignature}`);
|
|
94
99
|
}
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
import * as Common from '../../core/common/common.js';
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
|
-
type ChangeRecord,
|
|
9
8
|
type Comment,
|
|
10
9
|
type CommentAnchorSignature,
|
|
11
10
|
CommentThread,
|
|
@@ -18,7 +17,6 @@ import {
|
|
|
18
17
|
} from './CommentThread.js';
|
|
19
18
|
|
|
20
19
|
export {
|
|
21
|
-
type ChangeRecord,
|
|
22
20
|
type Comment,
|
|
23
21
|
type CommentAnchorSignature,
|
|
24
22
|
CommentThread,
|
|
@@ -92,7 +90,7 @@ export class CommentManager extends Common.ObjectWrapper.ObjectWrapper<EventType
|
|
|
92
90
|
anchor: CommentAnchorSignature,
|
|
93
91
|
text?: string,
|
|
94
92
|
author: 'DEVELOPER'|'AGENT' = 'DEVELOPER',
|
|
95
|
-
|
|
93
|
+
isGeneratedComment?: boolean,
|
|
96
94
|
): CommentThread {
|
|
97
95
|
const comments: Comment[] = text ? [{
|
|
98
96
|
author,
|
|
@@ -103,7 +101,7 @@ export class CommentManager extends Common.ObjectWrapper.ObjectWrapper<EventType
|
|
|
103
101
|
const thread = new CommentThread({
|
|
104
102
|
anchor,
|
|
105
103
|
comments,
|
|
106
|
-
|
|
104
|
+
isGeneratedComment,
|
|
107
105
|
});
|
|
108
106
|
thread.addEventListener(CommentThreadEvents.CHANGED, this.#onThreadChanged, this);
|
|
109
107
|
|
|
@@ -123,7 +121,7 @@ export class CommentManager extends Common.ObjectWrapper.ObjectWrapper<EventType
|
|
|
123
121
|
takeComments(): CommentThread[] {
|
|
124
122
|
const threads: CommentThread[] = [];
|
|
125
123
|
for (const thread of this.#commentThreads.values()) {
|
|
126
|
-
if (thread.status === '
|
|
124
|
+
if (thread.status === 'SENT_TO_AGENT' && !thread.transmitted) {
|
|
127
125
|
thread.transmitted = true;
|
|
128
126
|
threads.push(thread);
|
|
129
127
|
}
|