chrome-devtools-frontend 1.0.1701636 → 1.0.1702515
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/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/devtools_compatibility.js +2 -1
- package/front_end/entrypoints/main/MainImpl.ts +8 -0
- package/front_end/generated/InspectorBackendCommands.ts +3 -3
- package/front_end/generated/protocol.ts +0 -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/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 +14 -5
- 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/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/commentThreadWidget.css +11 -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/sources/ResourceOriginPlugin.ts +8 -3
- package/front_end/panels/sources/ScopeChainSidebarPane.ts +3 -4
- package/front_end/panels/sources/TabbedEditorContainer.ts +339 -126
- 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 +117 -0
- package/front_end/ui/components/markdown_view/markdown_view.ts +2 -0
- 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 +228 -343
- package/front_end/ui/legacy/components/object_ui/objectPropertiesSection.css +2 -27
- package/mcp/mcp.ts +1 -0
- package/package.json +1 -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
|
],
|
|
@@ -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
|
}
|
|
@@ -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"});
|
|
@@ -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',
|
|
@@ -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
|
}
|
|
@@ -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
|
}
|
|
@@ -58,13 +58,7 @@ export interface Comment {
|
|
|
58
58
|
timestamp: number;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
export
|
|
62
|
-
id: string;
|
|
63
|
-
description: string;
|
|
64
|
-
timestamp: number;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export type CommentThreadStatus = 'DRAFT'|'ACTIVE'|'RESOLVED';
|
|
61
|
+
export type CommentThreadStatus = 'DRAFT'|'ACTIVE'|'SENT_TO_AGENT'|'RESOLVED';
|
|
68
62
|
|
|
69
63
|
export const enum Events {
|
|
70
64
|
CHANGED = 'Changed',
|
|
@@ -77,7 +71,8 @@ export interface EventTypes {
|
|
|
77
71
|
export interface CommentThreadOptions {
|
|
78
72
|
anchor: CommentAnchorSignature;
|
|
79
73
|
comments?: Comment[];
|
|
80
|
-
|
|
74
|
+
/** True for comments generated from the change tracker. */
|
|
75
|
+
isGeneratedComment?: boolean;
|
|
81
76
|
}
|
|
82
77
|
|
|
83
78
|
export class CommentThread extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
|
|
@@ -89,33 +84,41 @@ export class CommentThread extends Common.ObjectWrapper.ObjectWrapper<EventTypes
|
|
|
89
84
|
|
|
90
85
|
readonly id: string = crypto.randomUUID();
|
|
91
86
|
readonly anchor: CommentAnchorSignature;
|
|
87
|
+
/** True for comments generated from the change tracker. */
|
|
88
|
+
readonly isGeneratedComment: boolean;
|
|
92
89
|
#savedIndex?: number;
|
|
93
90
|
comments: Comment[];
|
|
94
91
|
status: CommentThreadStatus = 'DRAFT';
|
|
95
92
|
transmitted: boolean = false;
|
|
96
|
-
changes?: ChangeRecord[];
|
|
97
93
|
|
|
98
94
|
constructor(options: CommentThreadOptions) {
|
|
99
95
|
super();
|
|
100
96
|
this.anchor = options.anchor;
|
|
101
97
|
this.comments = options.comments ?? [];
|
|
102
|
-
this.
|
|
98
|
+
this.isGeneratedComment = Boolean(options.isGeneratedComment);
|
|
103
99
|
}
|
|
104
100
|
|
|
105
101
|
get index(): number {
|
|
106
102
|
return this.#savedIndex ?? CommentThread.#nextIndex;
|
|
107
103
|
}
|
|
108
104
|
|
|
109
|
-
|
|
110
|
-
|
|
105
|
+
/**
|
|
106
|
+
* Returns whether it was changed.
|
|
107
|
+
*/
|
|
108
|
+
#saveText(text?: string, author: 'DEVELOPER'|'AGENT' = 'DEVELOPER'): boolean {
|
|
111
109
|
if (text && text.trim().length > 0) {
|
|
112
110
|
this.comments.push({
|
|
113
111
|
author,
|
|
114
112
|
text: text.trim(),
|
|
115
113
|
timestamp: Date.now(),
|
|
116
114
|
});
|
|
117
|
-
|
|
115
|
+
return true;
|
|
118
116
|
}
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
save(text?: string, author: 'DEVELOPER'|'AGENT' = 'DEVELOPER'): void {
|
|
121
|
+
let changed = this.#saveText(text, author);
|
|
119
122
|
if (this.status === 'DRAFT') {
|
|
120
123
|
if (this.#savedIndex === undefined) {
|
|
121
124
|
this.#savedIndex = CommentThread.#nextIndex++;
|
|
@@ -128,6 +131,20 @@ export class CommentThread extends Common.ObjectWrapper.ObjectWrapper<EventTypes
|
|
|
128
131
|
}
|
|
129
132
|
}
|
|
130
133
|
|
|
134
|
+
sendToAgent(text?: string, author: 'DEVELOPER'|'AGENT' = 'DEVELOPER'): void {
|
|
135
|
+
let changed = this.#saveText(text, author);
|
|
136
|
+
if (this.status === 'DRAFT' || this.status === 'ACTIVE') {
|
|
137
|
+
if (this.#savedIndex === undefined) {
|
|
138
|
+
this.#savedIndex = CommentThread.#nextIndex++;
|
|
139
|
+
}
|
|
140
|
+
this.status = 'SENT_TO_AGENT';
|
|
141
|
+
changed = true;
|
|
142
|
+
}
|
|
143
|
+
if (changed) {
|
|
144
|
+
this.dispatchEventToListeners(Events.CHANGED);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
131
148
|
resolve(replyText?: string): void {
|
|
132
149
|
if (replyText && replyText.trim().length > 0) {
|
|
133
150
|
this.comments.push({
|
|
@@ -33,20 +33,19 @@ export class CookieDeprecationMetadataIssue extends Issue<Protocol.Audits.Cookie
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
getDescription(): MarkdownIssueDescription {
|
|
36
|
-
|
|
36
|
+
let fileName =
|
|
37
37
|
this.details().operation === 'SetCookie' ? 'cookieWarnMetadataGrantSet.md' : 'cookieWarnMetadataGrantRead.md';
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
const substitutions = new Map<string, string>();
|
|
40
40
|
if (this.details().isOptOutTopLevel) {
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
fileName = this.details().operation === 'SetCookie' ? 'cookieWarnMetadataGrantSetOptOut.md' :
|
|
42
|
+
'cookieWarnMetadataGrantReadOptOut.md';
|
|
43
|
+
substitutions.set('PLACEHOLDER_optOutPercentage', String(this.details().optOutPercentage));
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
return {
|
|
46
47
|
file: fileName,
|
|
47
|
-
substitutions
|
|
48
|
-
['PLACEHOLDER_topleveloptout', optOutText],
|
|
49
|
-
]),
|
|
48
|
+
substitutions,
|
|
50
49
|
links: [
|
|
51
50
|
{
|
|
52
51
|
link: 'https://goo.gle/changes-to-chrome-browsing',
|
|
@@ -71,8 +71,8 @@ export class DeprecationIssue extends Issue<Protocol.Audits.DeprecationIssueDeta
|
|
|
71
71
|
}
|
|
72
72
|
return resolveLazyDescription({
|
|
73
73
|
file: 'deprecation.md',
|
|
74
|
+
title: i18nLazyString(UIStrings.title),
|
|
74
75
|
substitutions: new Map([
|
|
75
|
-
['PLACEHOLDER_title', i18nLazyString(UIStrings.title)],
|
|
76
76
|
['PLACEHOLDER_message', messageFunction],
|
|
77
77
|
]),
|
|
78
78
|
links,
|
|
@@ -13,12 +13,14 @@ import * as Marked from '../../third_party/marked/marked.js';
|
|
|
13
13
|
*/
|
|
14
14
|
export interface MarkdownIssueDescription {
|
|
15
15
|
file: string;
|
|
16
|
+
title?: string;
|
|
16
17
|
substitutions?: Map<string, string>;
|
|
17
18
|
links: Array<{link: string, linkTitle: string}>;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
export interface LazyMarkdownIssueDescription {
|
|
21
22
|
file: string;
|
|
23
|
+
title?: () => string;
|
|
22
24
|
substitutions?: Map<string, () => string>;
|
|
23
25
|
links: Array<{link: string, linkTitle: () => string}>;
|
|
24
26
|
}
|
|
@@ -38,8 +40,9 @@ export function resolveLazyDescription(lazyDescription: LazyMarkdownIssueDescrip
|
|
|
38
40
|
substitutionMap.set(key, value());
|
|
39
41
|
});
|
|
40
42
|
|
|
41
|
-
const description = {
|
|
43
|
+
const description: MarkdownIssueDescription = {
|
|
42
44
|
file: lazyDescription.file,
|
|
45
|
+
title: lazyDescription.title?.(),
|
|
43
46
|
links: lazyDescription.links.map(linksMap),
|
|
44
47
|
substitutions: substitutionMap,
|
|
45
48
|
};
|
|
@@ -54,6 +57,7 @@ export interface IssueDescription {
|
|
|
54
57
|
title: string;
|
|
55
58
|
markdown: Marked.Marked.Token[];
|
|
56
59
|
links: Array<{link: string, linkTitle: string}>;
|
|
60
|
+
substitutions?: Map<string, string>;
|
|
57
61
|
}
|
|
58
62
|
|
|
59
63
|
export async function getFileContent(url: URL): Promise<string> {
|
|
@@ -82,15 +86,16 @@ export async function createIssueDescriptionFromMarkdown(description: MarkdownIs
|
|
|
82
86
|
export function createIssueDescriptionFromRawMarkdown(
|
|
83
87
|
markdown: string, description: MarkdownIssueDescription): IssueDescription {
|
|
84
88
|
const markdownAst = Marked.Marked.lexer(markdown);
|
|
85
|
-
const
|
|
86
|
-
if (!
|
|
89
|
+
const markdownTitle = findTitleFromMarkdownAst(markdownAst);
|
|
90
|
+
if (!markdownTitle) {
|
|
87
91
|
throw new Error('Markdown issue descriptions must start with a heading');
|
|
88
92
|
}
|
|
89
93
|
|
|
90
94
|
return {
|
|
91
|
-
title,
|
|
95
|
+
title: description.title ?? markdownTitle,
|
|
92
96
|
markdown: markdownAst.slice(1),
|
|
93
97
|
links: description.links,
|
|
98
|
+
substitutions: description.substitutions,
|
|
94
99
|
};
|
|
95
100
|
}
|
|
96
101
|
|
|
@@ -148,5 +153,9 @@ export async function getIssueTitleFromMarkdownDescription(description: Markdown
|
|
|
148
153
|
Promise<string|null> {
|
|
149
154
|
const rawMarkdown = await getMarkdownFileContent(description.file);
|
|
150
155
|
const markdownAst = Marked.Marked.lexer(rawMarkdown);
|
|
151
|
-
|
|
156
|
+
const markdownTitle = findTitleFromMarkdownAst(markdownAst);
|
|
157
|
+
if (!markdownTitle) {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
return description.title ?? markdownTitle;
|
|
152
161
|
}
|
|
@@ -77,10 +77,8 @@ export class SRIMessageSignatureIssue extends Issue<Protocol.Audits.SRIMessageSi
|
|
|
77
77
|
description.substitutions?.set('PLACEHOLDER_signatureBase', () => details.signatureBase);
|
|
78
78
|
}
|
|
79
79
|
if (details.error === Protocol.Audits.SRIMessageSignatureError.ValidationFailedIntegrityMismatch) {
|
|
80
|
-
description.substitutions?.set('PLACEHOLDER_integrityAssertions',
|
|
81
|
-
|
|
82
|
-
return prefix + this.details().integrityAssertions.join(prefix);
|
|
83
|
-
});
|
|
80
|
+
description.substitutions?.set('PLACEHOLDER_integrityAssertions',
|
|
81
|
+
() => this.details().integrityAssertions.join('\n'));
|
|
84
82
|
}
|
|
85
83
|
return resolveLazyDescription(description);
|
|
86
84
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
# Third-party websites are allowed to read cookies on this page
|
|
2
2
|
|
|
3
3
|
One or more websites are allowed to bypass user settings to read third-party cookies on this page. Web developers should take steps to remove these reads without disrupting user experience. To forcefully block these third-party cookies, update [user settings](manageCookiesHelpPage).
|
|
4
|
-
{PLACEHOLDER_topleveloptout}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Third-party websites are allowed to read cookies on this page
|
|
2
|
+
|
|
3
|
+
One or more websites are allowed to bypass user settings to read third-party cookies on this page. Web developers should take steps to remove these reads without disrupting user experience. To forcefully block these third-party cookies, update [user settings](manageCookiesHelpPage).
|
|
4
|
+
|
|
5
|
+
(Top level site opt-out: {PLACEHOLDER_optOutPercentage}% - [learn more](gracePeriodStagedControlExplainer))
|
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
# Third-party websites are allowed to set cookies on this page
|
|
2
2
|
|
|
3
3
|
One or more websites are allowed to bypass user settings to set third-party cookies on this page. Web developers should take steps to remove these sets without disrupting user experience. To forcefully block these third-party cookies, update [user settings](manageCookiesHelpPage).
|
|
4
|
-
{PLACEHOLDER_topleveloptout}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Third-party websites are allowed to set cookies on this page
|
|
2
|
+
|
|
3
|
+
One or more websites are allowed to bypass user settings to set third-party cookies on this page. Web developers should take steps to remove these sets without disrupting user experience. To forcefully block these third-party cookies, update [user settings](manageCookiesHelpPage).
|
|
4
|
+
|
|
5
|
+
(Top level site opt-out: {PLACEHOLDER_optOutPercentage}% - [learn more](gracePeriodStagedControlExplainer))
|