chrome-devtools-frontend 1.0.1636056 → 1.0.1640418
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/front_end/core/common/Color.ts +0 -4
- package/front_end/core/host/AidaClientTypes.ts +8 -6
- package/front_end/core/root/Runtime.ts +2 -2
- package/front_end/core/sdk/DOMStorageModel.ts +1 -1
- package/front_end/core/sdk/SourceMap.ts +8 -3
- package/front_end/core/sdk/TargetManager.ts +14 -1
- package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +147 -0
- package/front_end/generated/ARIAProperties.js +17 -4
- package/front_end/generated/InspectorBackendCommands.ts +13 -7
- package/front_end/generated/SupportedCSSProperties.js +1 -0
- package/front_end/generated/protocol-mapping.d.ts +7 -0
- package/front_end/generated/protocol-proxy-api.d.ts +14 -0
- package/front_end/generated/protocol.ts +120 -2
- package/front_end/global_typings/global_defs.d.ts +13 -0
- package/front_end/models/ai_assistance/AiAgent2.ts +116 -0
- package/front_end/models/ai_assistance/AiConversation.ts +22 -36
- package/front_end/models/ai_assistance/AiHistoryStorage.ts +0 -1
- package/front_end/models/ai_assistance/AiOrigins.ts +46 -0
- package/front_end/models/ai_assistance/AiUtils.ts +9 -0
- package/front_end/models/ai_assistance/README.md +16 -0
- package/front_end/models/ai_assistance/StorageItem.ts +30 -26
- package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +12 -5
- package/front_end/models/ai_assistance/agents/AiAgent.ts +86 -32
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.snapshot.txt +2 -2
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +31 -10
- package/front_end/models/ai_assistance/agents/ConversationSummaryAgent.ts +1 -1
- package/front_end/models/ai_assistance/agents/FileAgent.ts +2 -2
- package/front_end/models/ai_assistance/agents/GreenDevAgent.ts +1 -3
- package/front_end/models/ai_assistance/agents/NetworkAgent.snapshot.txt +19 -0
- package/front_end/models/ai_assistance/agents/NetworkAgent.ts +9 -4
- package/front_end/models/ai_assistance/agents/PerformanceAgent.snapshot.txt +2 -2
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +41 -12
- package/front_end/models/ai_assistance/agents/StorageAgent.ts +442 -122
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +2 -2
- package/front_end/models/ai_assistance/ai_assistance.ts +4 -2
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +2 -2
- package/front_end/models/ai_assistance/performance/AIContext.ts +7 -8
- package/front_end/models/ai_assistance/skills/README.md +40 -0
- package/front_end/models/ai_assistance/skills/Skill.ts +13 -0
- package/front_end/models/ai_assistance/skills/SkillRegistry.ts +10 -0
- package/front_end/models/ai_assistance/skills/styling.md +6 -0
- package/front_end/models/bindings/CompilerScriptMapping.ts +12 -4
- package/front_end/models/breakpoints/BreakpointManager.ts +54 -2
- package/front_end/models/greendev/Prototypes.ts +0 -7
- package/front_end/models/heap_snapshot/HeapSnapshotModel.ts +20 -0
- package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +5 -0
- package/front_end/models/issues_manager/EmailVerificationRequestIssue.ts +293 -0
- package/front_end/models/issues_manager/IssuesManager.ts +5 -0
- package/front_end/models/issues_manager/descriptions/emailVerificationRequestDnsFetchFailed.md +1 -0
- package/front_end/models/issues_manager/descriptions/emailVerificationRequestDnsInvalidRecord.md +1 -0
- package/front_end/models/issues_manager/descriptions/emailVerificationRequestInvalidEmail.md +1 -0
- package/front_end/models/issues_manager/descriptions/emailVerificationRequestKeyBindingSigningFailed.md +1 -0
- package/front_end/models/issues_manager/descriptions/emailVerificationRequestRpOriginIsOpaque.md +1 -0
- package/front_end/models/issues_manager/descriptions/emailVerificationRequestTokenHttpNotFound.md +1 -0
- package/front_end/models/issues_manager/descriptions/emailVerificationRequestTokenInvalidContentType.md +1 -0
- package/front_end/models/issues_manager/descriptions/emailVerificationRequestTokenInvalidResponse.md +1 -0
- package/front_end/models/issues_manager/descriptions/emailVerificationRequestTokenInvalidSdJwt.md +1 -0
- package/front_end/models/issues_manager/descriptions/emailVerificationRequestTokenMalformedSdJwt.md +1 -0
- package/front_end/models/issues_manager/descriptions/emailVerificationRequestTokenNoResponse.md +1 -0
- package/front_end/models/issues_manager/descriptions/emailVerificationRequestUserLoggedOut.md +1 -0
- package/front_end/models/issues_manager/descriptions/emailVerificationRequestWellKnownAccountsEndpointCrossOrigin.md +1 -0
- package/front_end/models/issues_manager/descriptions/emailVerificationRequestWellKnownHttpNotFound.md +1 -0
- package/front_end/models/issues_manager/descriptions/emailVerificationRequestWellKnownInvalidContentType.md +1 -0
- package/front_end/models/issues_manager/descriptions/emailVerificationRequestWellKnownInvalidResponse.md +1 -0
- package/front_end/models/issues_manager/descriptions/emailVerificationRequestWellKnownIssuanceEndpointCrossOrigin.md +1 -0
- package/front_end/models/issues_manager/descriptions/emailVerificationRequestWellKnownListEmpty.md +1 -0
- package/front_end/models/issues_manager/descriptions/emailVerificationRequestWellKnownMissingAccountsEndpoint.md +1 -0
- package/front_end/models/issues_manager/descriptions/emailVerificationRequestWellKnownMissingIssuanceEndpoint.md +1 -0
- package/front_end/models/issues_manager/descriptions/emailVerificationRequestWellKnownNoResponse.md +1 -0
- package/front_end/models/issues_manager/descriptions/emailVerificationRequestWellKnownUnsupportedSigningAlgorithm.md +1 -0
- package/front_end/models/issues_manager/issues_manager.ts +2 -0
- package/front_end/models/javascript_metadata/NativeFunctions.js +1748 -1739
- package/front_end/models/live-metrics/web-vitals-injected/web-vitals-injected.ts +1 -1
- package/front_end/models/stack_trace/DetailedErrorStackParser.ts +9 -1
- package/front_end/models/stack_trace/StackTraceImpl.ts +29 -9
- package/front_end/models/stack_trace/StackTraceModel.ts +23 -11
- package/front_end/models/stack_trace/Trie.ts +11 -1
- package/front_end/models/trace/extras/TraceTree.ts +20 -1
- package/front_end/models/trace/insights/Common.ts +9 -0
- package/front_end/models/trace/lantern/core/NetworkAnalyzer.ts +21 -25
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +19 -75
- package/front_end/panels/ai_assistance/components/AccessibilityAgentMarkdownRenderer.ts +10 -3
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +148 -2
- package/front_end/panels/ai_assistance/components/PerformanceAgentMarkdownRenderer.ts +2 -3
- package/front_end/panels/ai_assistance/components/chatMessage.css +27 -0
- package/front_end/panels/application/CookieItemsView.ts +24 -0
- package/front_end/panels/application/DOMStorageItemsView.ts +9 -4
- package/front_end/panels/application/preloading/components/PreloadingString.ts +6 -0
- package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +4 -4
- package/front_end/panels/console/ConsoleViewMessage.ts +13 -102
- package/front_end/panels/elements/StandaloneStylesContainer.ts +10 -0
- package/front_end/panels/elements/StylePropertiesSection.ts +6 -2
- package/front_end/panels/elements/StylePropertyTreeElement.ts +30 -1
- package/front_end/panels/elements/StylesContainer.ts +3 -0
- package/front_end/panels/elements/StylesSidebarPane.ts +54 -4
- package/front_end/panels/elements/elements-meta.ts +14 -0
- package/front_end/panels/layer_viewer/layerDetailsView.css +1 -1
- package/front_end/panels/lighthouse/LighthouseController.ts +1 -1
- package/front_end/panels/lighthouse/LighthouseProtocolService.ts +4 -4
- package/front_end/panels/network/NetworkDataGridNode.ts +14 -0
- package/front_end/panels/network/NetworkLogViewColumns.ts +2 -2
- package/front_end/panels/network/RequestHeadersView.ts +55 -19
- package/front_end/panels/network/networkTimingTable.css +2 -4
- package/front_end/panels/recorder/components/ReplaySection.ts +28 -16
- package/front_end/panels/recorder/converters/LighthouseConverter.snapshot.txt +47 -0
- package/front_end/panels/recorder/converters/PuppeteerConverter.snapshot.txt +49 -0
- package/front_end/panels/recorder/converters/PuppeteerReplayConverter.snapshot.txt +33 -0
- package/front_end/panels/settings/SettingsScreen.ts +1 -2
- package/front_end/panels/sources/BreakpointsView.ts +23 -42
- package/front_end/panels/sources/DebuggerPlugin.ts +12 -5
- package/front_end/panels/sources/ScopeChainSidebarPane.ts +169 -106
- package/front_end/panels/timeline/components/IgnoreListSetting.ts +1 -0
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/lighthouse/lighthouse-dt-bundle.js +2 -2
- package/front_end/third_party/marked/README.chromium +3 -6
- package/front_end/third_party/marked/package/README.md +5 -5
- package/front_end/third_party/marked/package/bin/main.js +27 -22
- package/front_end/third_party/marked/package/bin/marked.js +2 -1
- package/front_end/third_party/marked/package/lib/marked.esm.d.ts +346 -256
- package/front_end/third_party/marked/package/lib/marked.esm.js +67 -2698
- package/front_end/third_party/marked/package/lib/marked.esm.js.map +7 -1
- package/front_end/third_party/marked/package/lib/marked.umd.js +69 -2722
- package/front_end/third_party/marked/package/lib/marked.umd.js.map +7 -1
- package/front_end/third_party/marked/package/man/marked.1 +4 -2
- package/front_end/third_party/marked/package/man/marked.1.md +2 -1
- package/front_end/third_party/marked/package/package.json +49 -57
- package/front_end/third_party/puppeteer-replay/README.chromium +2 -2
- package/front_end/third_party/puppeteer-replay/package/lib/cli.js +84 -80
- package/front_end/third_party/puppeteer-replay/package/lib/cli.js.map +1 -1
- package/front_end/third_party/puppeteer-replay/package/lib/extension-test.js +79 -83
- package/front_end/third_party/puppeteer-replay/package/lib/extension-test.js.map +1 -1
- package/front_end/third_party/puppeteer-replay/package/lib/main.d.ts +43 -171
- package/front_end/third_party/puppeteer-replay/package/lib/main.js +51 -206
- package/front_end/third_party/puppeteer-replay/package/lib/main.js.map +1 -1
- package/front_end/third_party/puppeteer-replay/package/package.json +37 -67
- package/front_end/tsconfig.json +1 -1
- package/front_end/ui/components/markdown_view/CodeBlock.ts +17 -6
- package/front_end/ui/components/markdown_view/MarkdownView.ts +39 -3
- package/front_end/ui/components/markdown_view/codeBlock.css +11 -0
- package/front_end/ui/components/markdown_view/markdownView.css +17 -0
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +0 -79
- package/front_end/ui/legacy/components/object_ui/RemoteObjectPreviewFormatter.ts +16 -4
- package/front_end/ui/visual_logging/KnownContextValues.ts +4 -0
- package/inspector_overlay/testing/InspectorOverlayHelpers.ts +2 -0
- package/mcp/mcp.ts +1 -6
- package/package.json +14 -16
- package/front_end/models/ai_assistance/agents/BreakpointDebuggerAgent.ts +0 -1015
- package/front_end/models/ai_assistance/agents/BreakpointDebuggerAgentOverlay.ts +0 -87
- package/front_end/third_party/marked/package/bin/marked +0 -215
- package/front_end/third_party/marked/package/lib/marked.cjs +0 -2726
- package/front_end/third_party/marked/package/lib/marked.cjs.map +0 -1
- package/front_end/third_party/marked/package/lib/marked.d.cts +0 -670
- package/front_end/third_party/marked/package/lib/marked.js +0 -2780
- package/front_end/third_party/marked/package/man/marked.1.txt +0 -86
- package/front_end/third_party/marked/package/marked.min.js +0 -6
- package/front_end/third_party/marked/package/src/Lexer.js +0 -492
- package/front_end/third_party/marked/package/src/Parser.js +0 -286
- package/front_end/third_party/marked/package/src/Renderer.js +0 -166
- package/front_end/third_party/marked/package/src/Slugger.js +0 -49
- package/front_end/third_party/marked/package/src/TextRenderer.js +0 -42
- package/front_end/third_party/marked/package/src/Tokenizer.js +0 -755
- package/front_end/third_party/marked/package/src/defaults.js +0 -29
- package/front_end/third_party/marked/package/src/helpers.js +0 -249
- package/front_end/third_party/marked/package/src/marked.js +0 -350
- package/front_end/third_party/marked/package/src/rules.js +0 -285
- package/front_end/third_party/puppeteer-replay/package/lib/cjs/main.cjs +0 -2099
- package/front_end/third_party/puppeteer-replay/package/lib/cjs/main.cjs.map +0 -1
- package/front_end/third_party/puppeteer-replay/package/lib/cjs/main.d.cts +0 -686
- package/front_end/third_party/puppeteer-replay/package/lib/cjs/main.d.ts +0 -35
- package/mcp/HostBindings.ts +0 -319
- /package/front_end/third_party/marked/package/{LICENSE.md → LICENSE} +0 -0
|
@@ -2,11 +2,12 @@
|
|
|
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';
|
|
7
8
|
import * as Root from '../../../core/root/root.js';
|
|
8
9
|
import * as SDK from '../../../core/sdk/sdk.js';
|
|
9
|
-
import type
|
|
10
|
+
import {CookieItem, DOMStorageItem, type StorageItem} from '../StorageItem.js';
|
|
10
11
|
|
|
11
12
|
import {
|
|
12
13
|
type AgentOptions,
|
|
@@ -19,37 +20,56 @@ import {
|
|
|
19
20
|
|
|
20
21
|
const lockedString = i18n.i18n.lockedString;
|
|
21
22
|
|
|
22
|
-
// TODO(kimanh): Replace temporary preamble as soon as functions are implemented
|
|
23
23
|
const preamble =
|
|
24
|
-
`You are a Senior Software Engineer specializing in state audit and storage analysis within Chrome DevTools. Your mission is to help developers debug storage-related issues faster by analyzing the evidence in LocalStorage and
|
|
25
|
-
|
|
26
|
-
You have access to the site's storage using tools like \`listStorageKeys
|
|
27
|
-
|
|
28
|
-
# Goals
|
|
29
|
-
|
|
30
|
-
1. **Explain Purpose**: Identify what specific storage entries are for.
|
|
31
|
-
2. **Understand Application State**: Help users inspect, understand, and audit the state stored in
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
-
|
|
37
|
-
- **
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
-
|
|
42
|
-
|
|
43
|
-
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
24
|
+
`You are a Senior Software Engineer specializing in state audit and storage analysis within Chrome DevTools. Your mission is to help developers debug storage-related issues faster by analyzing the evidence in LocalStorage, SessionStorage, and Cookies.
|
|
25
|
+
|
|
26
|
+
You have access to the site's storage using tools like \`listPageOrigins\`, \`listStorageKeys\`, \`getStorageValues\`, \`listCookies\`, and \`getCookieValues\`.
|
|
27
|
+
|
|
28
|
+
# Goals
|
|
29
|
+
|
|
30
|
+
1. **Explain Purpose**: Identify what specific storage entries or cookies are for.
|
|
31
|
+
2. **Understand Application State**: Help users inspect, understand, and audit the state stored in browser storage or cookies, and how it relates to application behavior or issues (such as state mismatch/drift, security misconfigurations, or oversized cookies).
|
|
32
|
+
3. **Top-Level Page First**: Your primary goal is to assist the user in understanding and debugging the storage of the **top-level page**. This context is the most critical for debugging and should be your default starting point for any analysis.
|
|
33
|
+
|
|
34
|
+
# Tools & Workflow
|
|
35
|
+
|
|
36
|
+
- **Prioritize Top-Level Context**: Always initiate your investigation from the top-level page's storage. Explicitly state if you are analyzing storage from a different context (e.g., an iframe).
|
|
37
|
+
- **Address Specific Selections**: The user can select individual storage items in the DevTools UI (provided in the '# Active Context' section of the prompt). If the query is about a selected item (e.g., "Why is this cookie set?"), focus your response on that specific item.
|
|
38
|
+
- **Expand Scope When Necessary**: For general questions or those implying a wider scope (e.g., "Check all storages," "Are there related cookies on subdomains?"), proactively use your tools to explore other relevant storage contexts, including iframes and different origins.
|
|
39
|
+
- **Discovery**: Start by calling \`listPageOrigins\` to discover all active, non-empty frame origins loaded by the page.
|
|
40
|
+
- **Storage Partitioning (LocalStorage / SessionStorage)**:
|
|
41
|
+
- Use \`listStorageKeys\` to survey keys. The results are grouped into **partitions** characterized by unique \`storageKey\` strings.
|
|
42
|
+
- Be aware that the same origin can have multiple storage partitions depending on frame ancestry.
|
|
43
|
+
- Use \`getStorageValues\` to inspect specific keys. The results are grouped into an array of partition \`items\` matching the requested keys under their unique \`storageKey\`.
|
|
44
|
+
- **Cookies**:
|
|
45
|
+
- Use \`listCookies\` to discover active cookies for an origin. Note that cookies are visible by domain scopes, paths, and partition status.
|
|
46
|
+
- Use \`getCookieValues\` to retrieve the values and detailed metadata of specific cookies by name.
|
|
47
|
+
- **HttpOnly Protection**: You don't have access to \`HttpOnly\` cookies. They are filtered out from both discovery and retrieval tools for security reasons.
|
|
48
|
+
- **Active Context**: Start by inspecting the active context's origin (provided in the '# Active Context' section of the prompt).
|
|
49
|
+
- **Value Minimization**: Only request values using \`getStorageValues\` or \`getCookieValues\` when key names/cookie names alone are insufficient.
|
|
50
|
+
|
|
51
|
+
# Considerations
|
|
52
|
+
|
|
53
|
+
- **Strictly Read-Only**: You cannot write, clear, delete, or edit storage or cookies.
|
|
54
|
+
- **DevTools UI Fallback**: If the user asks you to modify state, politely decline and provide exact step-by-step visual navigation directions on how they can perform the edit manually in the DevTools Application panel. Do NOT supply Console scripts.
|
|
55
|
+
- **Raw Evidence**: Treat storage data as raw evidence. Do not make assumptions about values without reading them first.
|
|
56
|
+
- **Dynamic State**: Always re-request values if you suspect they might have changed, rather than relying on past tool outputs.
|
|
57
|
+
- **CRITICAL**: Use the precision of Strunk & White, the brevity of Hemingway, and the simple clarity of Vonnegut. Don't add repeated information, and keep the whole answer short.
|
|
58
|
+
- **CRITICAL**: You are a storage debugging assistant. NEVER answer unrelated topics (legal, financial, race, sexuality, medical, religion, politics). If asked, respond: "Sorry, I can't answer that. I'm best at questions about debugging web pages."
|
|
59
|
+
`;
|
|
60
|
+
|
|
61
|
+
function isSamePrimaryPageOrigin(context?: ConversationContext<StorageItem>): boolean {
|
|
62
|
+
const primaryPageTarget = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
|
|
63
|
+
return isSamePageOrigin(primaryPageTarget, context);
|
|
64
|
+
}
|
|
47
65
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
66
|
+
function isSamePageOrigin(target: SDK.Target.Target|null, context?: ConversationContext<StorageItem>): boolean {
|
|
67
|
+
if (!target || !context) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
const pageOrigin = Common.ParsedURL.ParsedURL.extractOrigin(target.inspectedURL());
|
|
71
|
+
return pageOrigin !== '' && context.isOriginAllowed(pageOrigin);
|
|
72
|
+
}
|
|
53
73
|
|
|
54
74
|
export class StorageContext extends ConversationContext<StorageItem> {
|
|
55
75
|
#item: StorageItem;
|
|
@@ -59,8 +79,8 @@ export class StorageContext extends ConversationContext<StorageItem> {
|
|
|
59
79
|
this.#item = item;
|
|
60
80
|
}
|
|
61
81
|
|
|
62
|
-
override
|
|
63
|
-
return this.#item.
|
|
82
|
+
override getURL(): string {
|
|
83
|
+
return this.#item.primaryTargetOrigin;
|
|
64
84
|
}
|
|
65
85
|
|
|
66
86
|
override getItem(): StorageItem {
|
|
@@ -68,13 +88,33 @@ export class StorageContext extends ConversationContext<StorageItem> {
|
|
|
68
88
|
}
|
|
69
89
|
|
|
70
90
|
override getTitle(): string {
|
|
71
|
-
if (this.#item
|
|
72
|
-
return `${this.#item.
|
|
91
|
+
if (this.#item instanceof CookieItem) {
|
|
92
|
+
return `${this.#item.name ? `cookie: ${this.#item.name}` : 'cookies:'} ${this.#item.origin}`;
|
|
93
|
+
}
|
|
94
|
+
if (this.#item instanceof DOMStorageItem) {
|
|
95
|
+
return `${this.#item.key ? `entry: ${this.#item.key}` : 'storage:'} ${this.#item.origin}`;
|
|
73
96
|
}
|
|
74
|
-
return `Storage
|
|
97
|
+
return `Storage: ${this.getOrigin()}`;
|
|
75
98
|
}
|
|
76
99
|
}
|
|
77
100
|
|
|
101
|
+
// Maximum character length of values allowed.
|
|
102
|
+
const MAX_NUM_CHAR_LENGTH = 10000;
|
|
103
|
+
|
|
104
|
+
interface CookieDetails {
|
|
105
|
+
value: string;
|
|
106
|
+
domain: string;
|
|
107
|
+
path: string;
|
|
108
|
+
expires: number;
|
|
109
|
+
size: number;
|
|
110
|
+
secure: boolean;
|
|
111
|
+
sameSite: string;
|
|
112
|
+
partitioned: boolean;
|
|
113
|
+
priority: string;
|
|
114
|
+
sourcePort: number;
|
|
115
|
+
sourceScheme: string;
|
|
116
|
+
}
|
|
117
|
+
|
|
78
118
|
export class StorageAgent extends AiAgent<StorageItem> {
|
|
79
119
|
readonly preamble = preamble;
|
|
80
120
|
readonly clientFeature = Host.AidaClient.ClientFeature.CHROME_STORAGE_AGENT;
|
|
@@ -96,10 +136,57 @@ export class StorageAgent extends AiAgent<StorageItem> {
|
|
|
96
136
|
constructor(opts: AgentOptions) {
|
|
97
137
|
super(opts);
|
|
98
138
|
|
|
99
|
-
this.declareFunction<{
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
139
|
+
this.declareFunction<Record<string, never>, {origins: string[]}>('listPageOrigins', {
|
|
140
|
+
description:
|
|
141
|
+
'Lists all active, non-empty frame origins loaded by the page. Use this first to discover what other targets/iframes exist on the page for querying their storage.',
|
|
142
|
+
parameters: {
|
|
143
|
+
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
144
|
+
description: '',
|
|
145
|
+
nullable: false,
|
|
146
|
+
properties: {},
|
|
147
|
+
required: [],
|
|
148
|
+
},
|
|
149
|
+
displayInfoFromArgs: () => {
|
|
150
|
+
return {
|
|
151
|
+
title: lockedString('Listing page origins'),
|
|
152
|
+
action: 'listPageOrigins()',
|
|
153
|
+
};
|
|
154
|
+
},
|
|
155
|
+
handler: async () => {
|
|
156
|
+
if (!isSamePrimaryPageOrigin(this.context)) {
|
|
157
|
+
return {error: 'No origin available or not allowed.'};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const origins = new Set<string>();
|
|
161
|
+
for (const frame of SDK.ResourceTreeModel.ResourceTreeModel.frames()) {
|
|
162
|
+
if (!isSamePageOrigin(frame.resourceTreeModel().target().outermostTarget(), this.context)) {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
const origin = frame.securityOrigin;
|
|
166
|
+
if (!origin || origins.has(origin)) {
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
origins.add(origin);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return {result: {origins: Array.from(origins)}};
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
this.declareFunction<
|
|
177
|
+
{
|
|
178
|
+
type: 'localStorage' | 'sessionStorage',
|
|
179
|
+
origin: string,
|
|
180
|
+
storageKey?: string,
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
partitions: Array<{
|
|
184
|
+
storageKey: string,
|
|
185
|
+
keys: string[],
|
|
186
|
+
}>,
|
|
187
|
+
}>('listStorageKeys', {
|
|
188
|
+
description:
|
|
189
|
+
'Lists all keys for a given storage type for the requested origin. Returns keys grouped by storage partition.',
|
|
103
190
|
parameters: {
|
|
104
191
|
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
105
192
|
description: '',
|
|
@@ -110,36 +197,67 @@ export class StorageAgent extends AiAgent<StorageItem> {
|
|
|
110
197
|
description: 'Storage type: localStorage or sessionStorage',
|
|
111
198
|
nullable: false,
|
|
112
199
|
},
|
|
200
|
+
origin: {
|
|
201
|
+
type: Host.AidaClient.ParametersTypes.STRING,
|
|
202
|
+
description: 'Specific origin to list keys for.',
|
|
203
|
+
nullable: false,
|
|
204
|
+
},
|
|
205
|
+
storageKey: {
|
|
206
|
+
type: Host.AidaClient.ParametersTypes.STRING,
|
|
207
|
+
description: 'Optional. Specific storageKey to to list keys for.',
|
|
208
|
+
nullable: true,
|
|
209
|
+
}
|
|
113
210
|
},
|
|
114
|
-
required: ['type'],
|
|
211
|
+
required: ['type', 'origin'],
|
|
115
212
|
},
|
|
116
213
|
displayInfoFromArgs: args => {
|
|
117
214
|
return {
|
|
118
215
|
title: lockedString('Reading storage keys'),
|
|
119
|
-
action: `listStorageKeys('${args.type}')`,
|
|
216
|
+
action: `listStorageKeys('${args.type}', '${args.origin}')`,
|
|
120
217
|
};
|
|
121
218
|
},
|
|
122
219
|
|
|
123
220
|
handler: async args => {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
return storageOrError;
|
|
221
|
+
if (!isSamePrimaryPageOrigin(this.context)) {
|
|
222
|
+
return {error: 'No origin available or not allowed.'};
|
|
127
223
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
224
|
+
|
|
225
|
+
const storages = resolveDOMStorages(this.context, args.type, args.origin, args.storageKey);
|
|
226
|
+
|
|
227
|
+
const keyAndItems = await Promise.all(storages.map(async storage => {
|
|
228
|
+
const items = await storage.getItems();
|
|
229
|
+
return {storageKey: storage.storageKey, items};
|
|
230
|
+
}));
|
|
231
|
+
|
|
232
|
+
const partitionsResult = [];
|
|
233
|
+
for (const {storageKey, items} of keyAndItems) {
|
|
234
|
+
if (!items) {
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
const keys = items.map(([key]) => key);
|
|
238
|
+
if (keys.length > 0) {
|
|
239
|
+
partitionsResult.push({storageKey, keys});
|
|
240
|
+
}
|
|
131
241
|
}
|
|
132
242
|
|
|
133
|
-
|
|
134
|
-
return {result: JSON.stringify({keys})};
|
|
243
|
+
return {result: {partitions: partitionsResult}};
|
|
135
244
|
},
|
|
136
245
|
});
|
|
137
246
|
|
|
138
|
-
this.declareFunction<
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
247
|
+
this.declareFunction<
|
|
248
|
+
{
|
|
249
|
+
type: 'localStorage' | 'sessionStorage',
|
|
250
|
+
keys: string[],
|
|
251
|
+
origin: string,
|
|
252
|
+
storageKey?: string,
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
items: Array<{
|
|
256
|
+
storageKey: string,
|
|
257
|
+
values: Record<string, string>,
|
|
258
|
+
}>,
|
|
259
|
+
}>('getStorageValues', {
|
|
260
|
+
description: 'Retrieve specific string values from storage partitions for requested keys.',
|
|
143
261
|
parameters: {
|
|
144
262
|
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
145
263
|
description: '',
|
|
@@ -156,105 +274,228 @@ export class StorageAgent extends AiAgent<StorageItem> {
|
|
|
156
274
|
items: {type: Host.AidaClient.ParametersTypes.STRING, description: 'A storage key.'},
|
|
157
275
|
nullable: false,
|
|
158
276
|
},
|
|
277
|
+
origin: {
|
|
278
|
+
type: Host.AidaClient.ParametersTypes.STRING,
|
|
279
|
+
description: 'Specific origin to get values for.',
|
|
280
|
+
nullable: false,
|
|
281
|
+
},
|
|
282
|
+
storageKey: {
|
|
283
|
+
type: Host.AidaClient.ParametersTypes.STRING,
|
|
284
|
+
description: 'Optional. Specific storageKey partition to get values for.',
|
|
285
|
+
nullable: true,
|
|
286
|
+
}
|
|
159
287
|
},
|
|
160
|
-
required: ['type', 'keys'],
|
|
288
|
+
required: ['type', 'keys', 'origin'],
|
|
161
289
|
},
|
|
162
290
|
displayInfoFromArgs: args => {
|
|
163
291
|
return {
|
|
164
292
|
title: lockedString('Reading storage values'),
|
|
165
|
-
action: `getStorageValues('${args.type}', ${JSON.stringify(args.keys)}
|
|
293
|
+
action: `getStorageValues('${args.type}', ${JSON.stringify(args.keys)}, '${args.origin}'${
|
|
294
|
+
args.storageKey ? `, '${args.storageKey}'` : ''})`,
|
|
166
295
|
};
|
|
167
296
|
},
|
|
168
297
|
|
|
169
298
|
handler: async (args, options) => {
|
|
299
|
+
if (!isSamePrimaryPageOrigin(this.context)) {
|
|
300
|
+
return {error: 'No origin available or not allowed.'};
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const storages = resolveDOMStorages(this.context, args.type, args.origin, args.storageKey);
|
|
304
|
+
if (storages.length === 0) {
|
|
305
|
+
return {error: 'No matching storage partitions found.'};
|
|
306
|
+
}
|
|
307
|
+
|
|
170
308
|
if (options?.approved !== true) {
|
|
171
309
|
const keyString = args.keys.map(k => `\`${k}\``).join(', ');
|
|
310
|
+
|
|
311
|
+
const uniqueTargetOrigins = Array.from(new Set(storages.map(storage => {
|
|
312
|
+
const parsed = SDK.StorageKeyManager.parseStorageKey(storage.storageKey || '');
|
|
313
|
+
return parsed.origin;
|
|
314
|
+
})));
|
|
315
|
+
const targetsDesc = uniqueTargetOrigins.join(', ');
|
|
316
|
+
|
|
172
317
|
return {
|
|
173
318
|
requiresApproval: true,
|
|
174
|
-
description: lockedString(
|
|
319
|
+
description: lockedString(
|
|
320
|
+
`The AI wants to access the value(s) of ${args.type} keys ${keyString} on ${targetsDesc}.`),
|
|
175
321
|
};
|
|
176
322
|
}
|
|
177
323
|
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
324
|
+
const itemsResult = [];
|
|
325
|
+
|
|
326
|
+
const keyAndItems = await Promise.all(storages.map(async storage => {
|
|
327
|
+
const items = await storage.getItems();
|
|
328
|
+
return {storageKey: storage.storageKey, items};
|
|
329
|
+
}));
|
|
330
|
+
|
|
331
|
+
for (const {storageKey, items} of keyAndItems) {
|
|
332
|
+
if (!items) {
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
const itemMap = new Map<string, string>(items as Array<[string, string]>);
|
|
336
|
+
const storageValues: Record<string, string> = {};
|
|
337
|
+
|
|
338
|
+
for (const key of args.keys) {
|
|
339
|
+
const value = itemMap.get(key);
|
|
340
|
+
if (value === undefined) {
|
|
341
|
+
continue;
|
|
342
|
+
}
|
|
343
|
+
const truncatedValue = value.length > MAX_NUM_CHAR_LENGTH ?
|
|
344
|
+
value.substring(0, MAX_NUM_CHAR_LENGTH) + '... <truncated>' :
|
|
345
|
+
value;
|
|
346
|
+
storageValues[key] = truncatedValue;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
itemsResult.push({storageKey, values: storageValues});
|
|
185
350
|
}
|
|
186
351
|
|
|
187
|
-
|
|
352
|
+
return {result: {items: itemsResult}};
|
|
353
|
+
},
|
|
354
|
+
});
|
|
188
355
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
356
|
+
this.declareFunction<
|
|
357
|
+
{
|
|
358
|
+
origin: string,
|
|
359
|
+
},
|
|
360
|
+
{cookies: string[]}>('listCookies', {
|
|
361
|
+
description: 'Lists all cookies for the requested origin, strictly excluding their values.',
|
|
362
|
+
parameters: {
|
|
363
|
+
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
364
|
+
description: '',
|
|
365
|
+
nullable: false,
|
|
366
|
+
properties: {
|
|
367
|
+
origin: {
|
|
368
|
+
type: Host.AidaClient.ParametersTypes.STRING,
|
|
369
|
+
description: 'Origin to list cookies for.',
|
|
370
|
+
nullable: false,
|
|
371
|
+
}
|
|
372
|
+
},
|
|
373
|
+
required: ['origin'],
|
|
374
|
+
},
|
|
375
|
+
displayInfoFromArgs: args => {
|
|
376
|
+
return {
|
|
377
|
+
title: lockedString('Reading cookies'),
|
|
378
|
+
action: `listCookies('${args.origin}')`,
|
|
379
|
+
};
|
|
380
|
+
},
|
|
381
|
+
handler: async args => {
|
|
382
|
+
if (!isSamePrimaryPageOrigin(this.context)) {
|
|
383
|
+
return {error: 'No origin available or not allowed.'};
|
|
192
384
|
}
|
|
193
385
|
|
|
194
|
-
|
|
195
|
-
|
|
386
|
+
const frame = findFrameForOrigin(this.context, args.origin);
|
|
387
|
+
if (!frame) {
|
|
388
|
+
return {result: {cookies: []}};
|
|
389
|
+
}
|
|
196
390
|
|
|
391
|
+
const target = frame.resourceTreeModel().target();
|
|
392
|
+
const cookies = await getCookiesForDomain(target, args.origin);
|
|
393
|
+
const uniqueNames = Array.from(new Set(cookies?.map(c => c.name())));
|
|
394
|
+
|
|
395
|
+
return {result: {cookies: uniqueNames}};
|
|
396
|
+
},
|
|
197
397
|
});
|
|
198
|
-
}
|
|
199
398
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
399
|
+
this.declareFunction<
|
|
400
|
+
{
|
|
401
|
+
cookieNames: string[],
|
|
402
|
+
origin: string,
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
cookies: CookieDetails[],
|
|
406
|
+
}>('getCookieValues', {
|
|
407
|
+
description: 'Retrieve the values and detailed metadata of specific cookies by their names.',
|
|
408
|
+
parameters: {
|
|
409
|
+
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
410
|
+
description: '',
|
|
411
|
+
nullable: false,
|
|
412
|
+
properties: {
|
|
413
|
+
cookieNames: {
|
|
414
|
+
type: Host.AidaClient.ParametersTypes.ARRAY,
|
|
415
|
+
description: 'A list of cookie names to retrieve values and metadata for.',
|
|
416
|
+
items: {type: Host.AidaClient.ParametersTypes.STRING, description: 'A cookie name.'},
|
|
417
|
+
nullable: false,
|
|
418
|
+
},
|
|
419
|
+
origin: {
|
|
420
|
+
type: Host.AidaClient.ParametersTypes.STRING,
|
|
421
|
+
description: 'The specific origin the cookies belong to.',
|
|
422
|
+
nullable: false,
|
|
423
|
+
}
|
|
424
|
+
},
|
|
425
|
+
required: ['cookieNames', 'origin'],
|
|
426
|
+
},
|
|
427
|
+
displayInfoFromArgs: args => {
|
|
428
|
+
return {
|
|
429
|
+
title: lockedString('Reading cookie values and metadata'),
|
|
430
|
+
action: `getCookieValues(${JSON.stringify(args.cookieNames)}, '${args.origin}')`,
|
|
431
|
+
};
|
|
432
|
+
},
|
|
433
|
+
handler: async (args, options) => {
|
|
434
|
+
if (!isSamePrimaryPageOrigin(this.context)) {
|
|
435
|
+
return {error: 'No origin available or not allowed.'};
|
|
219
436
|
}
|
|
220
|
-
}
|
|
221
|
-
return {error: `Storage not found for key ${storageKey} and type ${type}`};
|
|
222
|
-
}
|
|
223
437
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
}
|
|
229
|
-
const domStorageModel = target.model(SDK.DOMStorageModel.DOMStorageModel);
|
|
230
|
-
if (!domStorageModel) {
|
|
231
|
-
return {error: 'DOMStorageModel not found.'};
|
|
232
|
-
}
|
|
438
|
+
const frame = findFrameForOrigin(this.context, args.origin);
|
|
439
|
+
if (!frame) {
|
|
440
|
+
return {result: {cookies: []}};
|
|
441
|
+
}
|
|
233
442
|
|
|
234
|
-
|
|
443
|
+
const target = frame.resourceTreeModel().target();
|
|
235
444
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
return parsedKey.origin === origin && s.isLocalStorage === isLocalStorage;
|
|
244
|
-
});
|
|
445
|
+
if (options?.approved !== true) {
|
|
446
|
+
return {
|
|
447
|
+
requiresApproval: true,
|
|
448
|
+
description: lockedString(`The AI wants to access the value(s) and metadata of cookie(s) ${
|
|
449
|
+
args.cookieNames.map(name => `\`${name}\``).join(', ')} on ${args.origin}.`),
|
|
450
|
+
};
|
|
451
|
+
}
|
|
245
452
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
453
|
+
const cookies = await getCookiesForDomain(target, args.origin);
|
|
454
|
+
if (!cookies) {
|
|
455
|
+
return {result: {cookies: []}};
|
|
456
|
+
}
|
|
249
457
|
|
|
250
|
-
|
|
458
|
+
const matchingCookies = cookies.filter(c => args.cookieNames.includes(c.name()));
|
|
459
|
+
const cookieData = matchingCookies.map(cookie => {
|
|
460
|
+
const value = cookie.value();
|
|
461
|
+
const truncatedValue =
|
|
462
|
+
value.length > MAX_NUM_CHAR_LENGTH ? value.substring(0, MAX_NUM_CHAR_LENGTH) + '... <truncated>' : value;
|
|
463
|
+
|
|
464
|
+
return {
|
|
465
|
+
value: truncatedValue,
|
|
466
|
+
domain: cookie.domain(),
|
|
467
|
+
path: cookie.path(),
|
|
468
|
+
expires: cookie.expires(),
|
|
469
|
+
size: cookie.size(),
|
|
470
|
+
secure: cookie.secure(),
|
|
471
|
+
sameSite: cookie.sameSite(),
|
|
472
|
+
partitioned: cookie.partitioned(),
|
|
473
|
+
priority: cookie.priority(),
|
|
474
|
+
sourcePort: cookie.sourcePort(),
|
|
475
|
+
sourceScheme: cookie.sourceScheme(),
|
|
476
|
+
};
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
return {result: {cookies: cookieData}};
|
|
480
|
+
},
|
|
481
|
+
});
|
|
251
482
|
}
|
|
252
483
|
|
|
253
|
-
static #formatContext(
|
|
254
|
-
|
|
255
|
-
|
|
484
|
+
static #formatContext(item: StorageItem): string {
|
|
485
|
+
const primaryTargetOrigin = `Primary target: ${item.primaryTargetOrigin}`;
|
|
486
|
+
if (item instanceof CookieItem) {
|
|
487
|
+
const parsedURL = Common.ParsedURL.ParsedURL.fromString(item.origin);
|
|
488
|
+
const domain = parsedURL ? parsedURL.host : item.origin;
|
|
489
|
+
return `${primaryTargetOrigin}\nUser-selected Context: Cookies\nDomain: ${domain}${
|
|
490
|
+
item.name ? `\nCookie Name: ${item.name}` : ''}`;
|
|
256
491
|
}
|
|
257
|
-
|
|
492
|
+
|
|
493
|
+
if (item instanceof DOMStorageItem) {
|
|
494
|
+
return `${primaryTargetOrigin}\nUser-selected Context: DOM Storage\n Type: ${item.type}\nStorageKey: ${
|
|
495
|
+
item.storageKey}\nOrigin: ${item.origin}${item.key ? `\nKey: ${item.key}` : ''}`;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
return primaryTargetOrigin;
|
|
258
499
|
}
|
|
259
500
|
|
|
260
501
|
async *
|
|
@@ -269,7 +510,7 @@ export class StorageAgent extends AiAgent<StorageItem> {
|
|
|
269
510
|
details: [
|
|
270
511
|
{
|
|
271
512
|
title: 'Selected Storage Context',
|
|
272
|
-
text: StorageAgent.#formatContext(context.
|
|
513
|
+
text: StorageAgent.#formatContext(context.getItem()),
|
|
273
514
|
},
|
|
274
515
|
],
|
|
275
516
|
};
|
|
@@ -279,6 +520,85 @@ export class StorageAgent extends AiAgent<StorageItem> {
|
|
|
279
520
|
if (!context) {
|
|
280
521
|
return query;
|
|
281
522
|
}
|
|
282
|
-
return `# Active Context\n${StorageAgent.#formatContext(context.
|
|
523
|
+
return `# Active Context\n${StorageAgent.#formatContext(context.getItem())}\n\n${query}`;
|
|
283
524
|
}
|
|
284
525
|
}
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Resolves and filters active DOM storage partitions from the Target Manager matching the given context constraints.
|
|
529
|
+
*
|
|
530
|
+
* @param context The conversation context containing origin permissions. Only storage partitions under targets allowed
|
|
531
|
+
* by this context will be returned.
|
|
532
|
+
* @param type The DOM storage type ('localStorage' or 'sessionStorage') to filter for.
|
|
533
|
+
* @param origin The partition origin to match.
|
|
534
|
+
* @param storageKey Optional. If specified, resolves only the partition exactly matching this unique key, bypassing origin comparison.
|
|
535
|
+
*/
|
|
536
|
+
|
|
537
|
+
export async function getCookiesForDomain(
|
|
538
|
+
target: SDK.Target.Target, origin: string): Promise<SDK.Cookie.Cookie[]|null> {
|
|
539
|
+
const cookieModel = target.model(SDK.CookieModel.CookieModel);
|
|
540
|
+
if (!cookieModel) {
|
|
541
|
+
return null;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
const allCookies = await cookieModel.getCookiesForDomain(origin);
|
|
545
|
+
if (!allCookies) {
|
|
546
|
+
return null;
|
|
547
|
+
}
|
|
548
|
+
return allCookies.filter(cookie => !cookie.httpOnly());
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
export function findFrameForOrigin(
|
|
552
|
+
context: ConversationContext<StorageItem>|undefined, origin: string): SDK.ResourceTreeModel.ResourceTreeFrame|null {
|
|
553
|
+
for (const frame of SDK.ResourceTreeModel.ResourceTreeModel.frames()) {
|
|
554
|
+
if (frame.securityOrigin === origin) {
|
|
555
|
+
const target = frame.resourceTreeModel().target();
|
|
556
|
+
if (isSamePageOrigin(target.outermostTarget(), context)) {
|
|
557
|
+
return frame;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
return null;
|
|
562
|
+
}
|
|
563
|
+
export function resolveDOMStorages(
|
|
564
|
+
context: ConversationContext<StorageItem>|undefined, type: 'localStorage'|'sessionStorage', origin: string,
|
|
565
|
+
storageKey?: string): SDK.DOMStorageModel.DOMStorage[] {
|
|
566
|
+
const resolvedStorages: SDK.DOMStorageModel.DOMStorage[] = [];
|
|
567
|
+
const isLocalStorage = type === 'localStorage';
|
|
568
|
+
|
|
569
|
+
const domStorageModels = SDK.TargetManager.TargetManager.instance().models(SDK.DOMStorageModel.DOMStorageModel);
|
|
570
|
+
for (const domStorageModel of domStorageModels) {
|
|
571
|
+
if (!isSamePageOrigin(domStorageModel.target().outermostTarget(), context)) {
|
|
572
|
+
// Skip DOMStorageModels that don't point to the same outermost target.
|
|
573
|
+
continue;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
for (const storage of domStorageModel.storages()) {
|
|
577
|
+
if (storage.isLocalStorage !== isLocalStorage) {
|
|
578
|
+
continue;
|
|
579
|
+
}
|
|
580
|
+
const currentStorageKey = storage.storageKey;
|
|
581
|
+
if (!currentStorageKey) {
|
|
582
|
+
continue;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
// If we search by storageKey, verify the storage key matches AND the underlying origin matches the request origin.
|
|
586
|
+
if (storageKey) {
|
|
587
|
+
if (storageKey === currentStorageKey) {
|
|
588
|
+
const parsedKey = SDK.StorageKeyManager.parseStorageKey(currentStorageKey);
|
|
589
|
+
if (parsedKey.origin === origin) {
|
|
590
|
+
resolvedStorages.push(storage);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
continue;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
const parsedKey = SDK.StorageKeyManager.parseStorageKey(currentStorageKey);
|
|
597
|
+
if (parsedKey.origin === origin) {
|
|
598
|
+
resolvedStorages.push(storage);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
return resolvedStorages;
|
|
604
|
+
}
|