Skip to content

Commit dba2e1c

Browse files
islandryuDevtools-frontend LUCI CQ
authored andcommitted
enable dom_storage for node
This is a change request to enable DOM storage inspection in Node.js. The Node.js changes are implemented in the following PR. nodejs/node#61139 Bug: none Change-Id: Iaf0fe135f1cc3f6cc746856d6a3fdd506f08390e Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/7274801 Reviewed-by: Philip Pfaffe <pfaffe@chromium.org> Reviewed-by: Simon Zünd <szuend@chromium.org> Commit-Queue: Simon Zünd <szuend@chromium.org>
1 parent 7f17613 commit dba2e1c

File tree

8 files changed

+88
-21
lines changed

8 files changed

+88
-21
lines changed

front_end/core/sdk/StorageKeyManager.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,12 @@ export function parseStorageKey(storageKeyString: string): StorageKey {
5656
// third_party/blink/common/storage_key/storage_key.cc
5757
const components = storageKeyString.split('^');
5858
const origin = Common.ParsedURL.ParsedURL.extractOrigin(components[0] as Platform.DevToolsPath.UrlString);
59-
const storageKey = {origin, components: new Map<StorageKeyComponent, string>()};
59+
const storageKey = {
60+
// For file:// URLs, extracting the origin collapses it to "file://".
61+
// Node.js uses the full file URL as the StorageKey, so keep the original URL here.
62+
origin: origin === 'file://' ? components[0] as Platform.DevToolsPath.UrlString : origin,
63+
components: new Map<StorageKeyComponent, string>()
64+
};
6065
for (let i = 1; i < components.length; ++i) {
6166
storageKey.components.set(components[i].charAt(0) as StorageKeyComponent, components[i].substring(1));
6267
}

front_end/core/sdk/Target.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export class Target extends ProtocolClient.InspectorBackend.TargetBase {
4949
this.#capabilitiesMask = Capability.BROWSER | Capability.STORAGE | Capability.DOM | Capability.JS |
5050
Capability.LOG | Capability.NETWORK | Capability.TARGET | Capability.TRACING | Capability.EMULATION |
5151
Capability.INPUT | Capability.INSPECTOR | Capability.AUDITS | Capability.WEB_AUTHN | Capability.IO |
52-
Capability.MEDIA | Capability.EVENT_BREAKPOINTS;
52+
Capability.MEDIA | Capability.EVENT_BREAKPOINTS | Capability.DOM_STORAGE;
5353
if (parentTarget?.type() !== Type.FRAME) {
5454
// This matches backend exposing certain capabilities only for the main frame.
5555
this.#capabilitiesMask |=
@@ -92,7 +92,8 @@ export class Target extends ProtocolClient.InspectorBackend.TargetBase {
9292
this.#capabilitiesMask = Capability.JS | Capability.LOG | Capability.EVENT_BREAKPOINTS | Capability.NETWORK;
9393
break;
9494
case Type.NODE:
95-
this.#capabilitiesMask = Capability.JS | Capability.NETWORK | Capability.TARGET | Capability.IO;
95+
this.#capabilitiesMask =
96+
Capability.JS | Capability.NETWORK | Capability.TARGET | Capability.IO | Capability.DOM_STORAGE;
9697
break;
9798
case Type.AUCTION_WORKLET:
9899
this.#capabilitiesMask = Capability.JS | Capability.EVENT_BREAKPOINTS;
@@ -318,5 +319,6 @@ export const enum Capability {
318319
IO = 1 << 17,
319320
MEDIA = 1 << 18,
320321
EVENT_BREAKPOINTS = 1 << 19,
322+
DOM_STORAGE = 1 << 20,
321323
NONE = 0,
322324
}

front_end/entrypoints/node_app/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ devtools_entrypoint("entrypoint") {
1212
"../../core/common:bundle",
1313
"../../core/i18n:bundle",
1414
"../../core/root:bundle",
15+
"../../panels/application:bundle",
1516
"../../panels/js_timeline:meta",
1617
"../../panels/mobile_throttling:meta",
1718
"../../panels/network:meta",

front_end/entrypoints/node_app/app/NodeMain.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ export class NodeChildTargetManager extends SDK.SDKModel.SDKModel<void> implemen
107107
targetDestroyed(_event: Protocol.Target.TargetDestroyedEvent): void {
108108
}
109109

110-
attachedToTarget({sessionId, targetInfo}: Protocol.Target.AttachedToTargetEvent): void {
110+
async attachedToTarget({sessionId, targetInfo}: Protocol.Target.AttachedToTargetEvent): Promise<void> {
111111
let target: SDK.Target.Target;
112112
if (targetInfo.type === 'node_worker') {
113113
target = this.#targetManager.createTarget(
@@ -124,6 +124,24 @@ export class NodeChildTargetManager extends SDK.SDKModel.SDKModel<void> implemen
124124
}
125125
this.#childTargets.set(sessionId, target);
126126
void target.runtimeAgent().invoke_runIfWaitingForDebugger();
127+
await this.#initializeStorage(target);
128+
}
129+
130+
async #initializeStorage(target: SDK.Target.Target): Promise<void> {
131+
const storageAgent = target.storageAgent();
132+
const response = await storageAgent.invoke_getStorageKey({});
133+
134+
const storageKey = response.storageKey;
135+
if (response.getError() || !storageKey) {
136+
console.error(`Failed to get storage key for target ${target.id()}: ${response.getError()}`);
137+
return;
138+
}
139+
140+
const storageKeyManager = target.model(SDK.StorageKeyManager.StorageKeyManager);
141+
if (storageKeyManager) {
142+
storageKeyManager.setMainStorageKey(storageKey);
143+
storageKeyManager.updateStorageKeys(new Set([storageKey]));
144+
}
127145
}
128146

129147
detachedFromTarget({sessionId}: Protocol.Target.DetachedFromTargetEvent): void {

front_end/entrypoints/node_app/node_app.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import '../../panels/network/network-meta.js';
99
import * as Common from '../../core/common/common.js';
1010
import * as i18n from '../../core/i18n/i18n.js';
1111
import * as Root from '../../core/root/root.js';
12+
import type * as Resources from '../../panels/application/application.js';
1213
import type * as Sources from '../../panels/sources/sources.js';
1314
import * as UI from '../../ui/legacy/legacy.js';
1415
import * as Main from '../main/main.js';
@@ -39,6 +40,14 @@ const UIStrings = {
3940
* @description Command for showing the 'Node' tool in the Network Navigator View, which is part of the Sources tool
4041
*/
4142
showNode: 'Show Node',
43+
/**
44+
* @description Text in Application Panel Sidebar of the Application panel
45+
*/
46+
application: 'Application',
47+
/**
48+
* @description Command for showing the 'Application' tool
49+
*/
50+
showApplication: 'Show Application',
4251
} as const;
4352

4453
const str_ = i18n.i18n.registerUIStrings('entrypoints/node_app/node_app.ts', UIStrings);
@@ -78,6 +87,31 @@ UI.ViewManager.registerViewExtension({
7887
},
7988
});
8089

90+
let loadedResourcesModule: (typeof Resources|undefined);
91+
92+
async function loadResourcesModule(): Promise<typeof Resources> {
93+
if (!loadedResourcesModule) {
94+
loadedResourcesModule = await import('../../panels/application/application.js');
95+
}
96+
return loadedResourcesModule;
97+
}
98+
99+
UI.ViewManager.registerViewExtension({
100+
location: UI.ViewManager.ViewLocationValues.PANEL,
101+
id: 'resources',
102+
title: i18nLazyString(UIStrings.application),
103+
commandPrompt: i18nLazyString(UIStrings.showApplication),
104+
order: 70,
105+
async loadView() {
106+
const Resources = await loadResourcesModule();
107+
return Resources.ResourcesPanel.ResourcesPanel.instance({
108+
forceNew: true,
109+
mode: 'node',
110+
});
111+
},
112+
tags: [],
113+
});
114+
81115
// @ts-expect-error Exposed for legacy layout tests
82116
self.runtime = Root.Runtime.Runtime.instance({forceNew: true});
83117
Common.Runnable.registerEarlyInitializationRunnable(NodeMainImpl.instance);

front_end/panels/application/ApplicationPanelSidebar.ts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1916,17 +1916,19 @@ export class ResourcesSection implements SDK.TargetManager.Observer {
19161916
frameManager.addEventListener(
19171917
SDK.FrameManager.Events.RESOURCE_ADDED, event => this.resourceAdded(event.data.resource), this);
19181918

1919-
SDK.TargetManager.TargetManager.instance().addModelListener(
1920-
SDK.ChildTargetManager.ChildTargetManager, SDK.ChildTargetManager.Events.TARGET_CREATED, this.windowOpened,
1921-
this, {scoped: true});
1922-
SDK.TargetManager.TargetManager.instance().addModelListener(
1923-
SDK.ChildTargetManager.ChildTargetManager, SDK.ChildTargetManager.Events.TARGET_INFO_CHANGED,
1924-
this.windowChanged, this, {scoped: true});
1925-
SDK.TargetManager.TargetManager.instance().addModelListener(
1926-
SDK.ChildTargetManager.ChildTargetManager, SDK.ChildTargetManager.Events.TARGET_DESTROYED, this.windowDestroyed,
1927-
this, {scoped: true});
1928-
1929-
SDK.TargetManager.TargetManager.instance().observeTargets(this, {scoped: true});
1919+
if (this.panel.mode !== 'node') {
1920+
SDK.TargetManager.TargetManager.instance().addModelListener(
1921+
SDK.ChildTargetManager.ChildTargetManager, SDK.ChildTargetManager.Events.TARGET_CREATED, this.windowOpened,
1922+
this, {scoped: true});
1923+
SDK.TargetManager.TargetManager.instance().addModelListener(
1924+
SDK.ChildTargetManager.ChildTargetManager, SDK.ChildTargetManager.Events.TARGET_INFO_CHANGED,
1925+
this.windowChanged, this, {scoped: true});
1926+
SDK.TargetManager.TargetManager.instance().addModelListener(
1927+
SDK.ChildTargetManager.ChildTargetManager, SDK.ChildTargetManager.Events.TARGET_DESTROYED,
1928+
this.windowDestroyed, this, {scoped: true});
1929+
1930+
SDK.TargetManager.TargetManager.instance().observeTargets(this, {scoped: true});
1931+
}
19301932
}
19311933

19321934
private initialize(): void {

front_end/panels/application/DOMStorageModel.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ export class DOMStorageModel extends SDK.SDKModel.SDKModel<EventTypes> {
250250
}
251251
}
252252

253-
SDK.SDKModel.SDKModel.register(DOMStorageModel, {capabilities: SDK.Target.Capability.DOM, autostart: false});
253+
SDK.SDKModel.SDKModel.register(DOMStorageModel, {capabilities: SDK.Target.Capability.DOM_STORAGE, autostart: false});
254254

255255
export const enum Events {
256256
DOM_STORAGE_ADDED = 'DOMStorageAdded',

front_end/panels/application/ResourcesPanel.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,13 @@ export class ResourcesPanel extends UI.Panel.PanelWithSidebar {
3737
private cookieView: CookieItemsView|null;
3838
private deviceBoundSessionsView: DeviceBoundSessionsView|null;
3939
private readonly sidebar: ApplicationPanelSidebar;
40+
mode: 'default'|'node' = 'default';
4041

41-
private constructor() {
42+
private constructor(
43+
mode: 'default'|'node' = 'default',
44+
) {
4245
super('resources');
46+
this.mode = mode;
4347
this.registerRequiredCSS(resourcesPanelStyles);
4448

4549
this.resourcesLastSelectedItemSetting =
@@ -68,11 +72,12 @@ export class ResourcesPanel extends UI.Panel.PanelWithSidebar {
6872
}
6973

7074
static instance(opts: {
71-
forceNew: boolean|null,
72-
} = {forceNew: null}): ResourcesPanel {
73-
const {forceNew} = opts;
75+
forceNew?: boolean|null,
76+
mode?: 'default'|'node',
77+
} = {forceNew: null, mode: 'default'}): ResourcesPanel {
78+
const {forceNew, mode} = opts;
7479
if (!resourcesPanelInstance || forceNew) {
75-
resourcesPanelInstance = new ResourcesPanel();
80+
resourcesPanelInstance = new ResourcesPanel(mode);
7681
}
7782

7883
return resourcesPanelInstance;

0 commit comments

Comments
 (0)