Skip to content
This repository was archived by the owner on Sep 17, 2021. It is now read-only.

Commit f5c6cbd

Browse files
authored
Merge pull request #7 from CodeMooseUS/persist_settings
Persist devtools settings
2 parents ce08c49 + 31ce66e commit f5c6cbd

File tree

5 files changed

+65
-28
lines changed

5 files changed

+65
-28
lines changed

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ A VSCode extension to host the chrome devtools inside of a webview.
88
</a>
99
</p>
1010

11-
## Attach to a running chrome instance:
11+
## Attaching to a running chrome instance:
1212
![Demo1](demo.gif)
1313

14-
## Launch a chrome debugger project and use screencasting:
14+
## Launching a 'debugger for chrome' project and using screencast:
1515
![Demo2](demo2.gif)
1616

1717
# Using the extension
@@ -32,7 +32,9 @@ A VSCode extension to host the chrome devtools inside of a webview.
3232

3333
# Known Issues
3434
- Prototyping stage
35-
- Settings in the devtools are not persisted
35+
- Having the DevTools in a non-foreground tab can cause issues while debugging
36+
- This is due to VS Code suspending script execution of non-foreground webviews
37+
- The workaround is to put the DevTools in a split view tab so that they are always visible while open
3638
- Chrome browser extensions can sometimes cause the webview to terminate
3739

3840
# Developing the extension itself

demo2.gif

-17.9 KB
Loading

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "vscode-devtools-for-chrome",
33
"displayName": "DevTools for Chrome",
44
"description": "Open the chrome devtools as a dockable webview",
5-
"version": "0.0.1",
5+
"version": "0.0.2",
66
"preview": true,
77
"license": "SEE LICENSE IN LICENSE",
88
"publisher": "codemooseus",

src/extension.ts

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ async function launch(context: vscode.ExtensionContext, launchUrl?: string, chro
9494
telemetryReporter.sendTelemetryEvent('launch/error/tab_not_found', telemetryProps);
9595
attach(context, viaConfig);
9696
} else {
97-
DevToolsPanel.createOrShow(context.extensionPath, target.webSocketDebuggerUrl);
97+
DevToolsPanel.createOrShow(context, target.webSocketDebuggerUrl);
9898
}
9999
}
100100

@@ -116,7 +116,7 @@ async function attach(context: vscode.ExtensionContext, viaConfig: boolean) {
116116

117117
vscode.window.showQuickPick(items).then((selection) => {
118118
if (selection) {
119-
DevToolsPanel.createOrShow(context.extensionPath, selection.detail as string);
119+
DevToolsPanel.createOrShow(context, selection.detail as string);
120120
}
121121
});
122122
} else {
@@ -164,36 +164,38 @@ async function getListOfTargets(hostname: string, port: number): Promise<Array<a
164164
class DevToolsPanel {
165165
private static currentPanel: DevToolsPanel;
166166
private readonly _panel: vscode.WebviewPanel;
167+
private readonly _context: vscode.ExtensionContext;
167168
private readonly _extensionPath: string;
168169
private readonly _targetUrl: string;
169170
private _socket: WebSocket = undefined;
170171
private _isConnected: boolean = false;
171172
private _messages: any[] = [];
172173
private _disposables: vscode.Disposable[] = [];
173174

174-
public static createOrShow(extensionPath: string, targetUrl: string) {
175-
const column = vscode.window.activeTextEditor ? vscode.window.activeTextEditor.viewColumn : undefined;
175+
public static createOrShow(context: vscode.ExtensionContext, targetUrl: string) {
176+
const column = vscode.ViewColumn.Beside;
176177

177178
if (DevToolsPanel.currentPanel) {
178179
DevToolsPanel.currentPanel._panel.reveal(column);
179180
} else {
180-
const panel = vscode.window.createWebviewPanel('devtools-for-chrome', 'DevTools', column || vscode.ViewColumn.Two, {
181+
const panel = vscode.window.createWebviewPanel('devtools-for-chrome', 'DevTools', column, {
181182
enableScripts: true,
182183
enableCommandUris: true,
183184
retainContextWhenHidden: true
184185
});
185186

186-
DevToolsPanel.currentPanel = new DevToolsPanel(panel, extensionPath, targetUrl);
187+
DevToolsPanel.currentPanel = new DevToolsPanel(panel, context, targetUrl);
187188
}
188189
}
189190

190-
public static revive(panel: vscode.WebviewPanel, extensionPath: string, targetUrl: string) {
191-
DevToolsPanel.currentPanel = new DevToolsPanel(panel, extensionPath, targetUrl);
191+
public static revive(panel: vscode.WebviewPanel, context: vscode.ExtensionContext, targetUrl: string) {
192+
DevToolsPanel.currentPanel = new DevToolsPanel(panel, context, targetUrl);
192193
}
193194

194-
private constructor(panel: vscode.WebviewPanel, extensionPath: string, targetUrl: string) {
195+
private constructor(panel: vscode.WebviewPanel, context: vscode.ExtensionContext, targetUrl: string) {
195196
this._panel = panel;
196-
this._extensionPath = extensionPath;
197+
this._context = context;
198+
this._extensionPath = context.extensionPath;
197199
this._targetUrl = targetUrl;
198200

199201
this._update();
@@ -251,6 +253,10 @@ class DevToolsPanel {
251253
this._disposeSocket();
252254
} else if (message.substr(0, 10) === 'telemetry:') {
253255
return this._sendTelemetryMessage(message.substr(10));
256+
} else if (message.substr(0, 9) === 'getState:') {
257+
return this._getDevtoolsState();
258+
} else if (message.substr(0, 9) === 'setState:') {
259+
return this._setDevtoolsState(message.substr(9));
254260
}
255261

256262
if (!this._socket) {
@@ -320,6 +326,26 @@ class DevToolsPanel {
320326
telemetryReporter.sendTelemetryEvent(telemetry.name, telemetry.properties, telemetry.metrics);
321327
}
322328

329+
private _getDevtoolsState() {
330+
const allPrefsKey = 'devtools-preferences';
331+
const allPrefs: any = this._context.workspaceState.get(allPrefsKey) ||
332+
{
333+
uiTheme: '"dark"',
334+
screencastEnabled: false
335+
};
336+
this._panel.webview.postMessage(`preferences:${JSON.stringify(allPrefs)}`);
337+
}
338+
339+
private _setDevtoolsState(state: string) {
340+
// Parse the preference from the message and store it
341+
const pref = JSON.parse(state) as { name: string, value: string };
342+
343+
const allPrefsKey = 'devtools-preferences';
344+
const allPrefs: any = this._context.workspaceState.get(allPrefsKey) || {};
345+
allPrefs[pref.name] = pref.value;
346+
this._context.workspaceState.update(allPrefsKey, allPrefs);
347+
}
348+
323349
private _update() {
324350
this._panel.webview.html = this._getHtmlForWebview();
325351
}

src/host/storage.ts

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
11
class ToolsHost {
2-
getPreferences(callback: (prefs: any) => void) {
3-
// Set some default preferences
4-
const prefs: any = {
5-
uiTheme: '"dark"',
6-
screencastEnabled: false
7-
};
2+
private _getStateCallback: (prefs: any) => void;
83

9-
// TODO: load the preference via the extension and global/workspaceState
10-
callback(prefs);
4+
public getPreferences(callback: (prefs: any) => void) {
5+
// Load the preference via the extension workspaceState
6+
this._getStateCallback = callback;
7+
window.parent.postMessage('getState:', '*');
118
}
129

13-
setPreference(name: string, value: string) {
14-
// TODO: save the preference via the extension and global/workspaceState
10+
public setPreference(name: string, value: string) {
11+
// Save the preference via the extension workspaceState
12+
window.parent.postMessage(`setState:${JSON.stringify({ name, value })}`, '*');
1513
}
1614

17-
recordEnumeratedHistogram(actionName: string, actionCode: number, bucketSize: number) {
15+
public recordEnumeratedHistogram(actionName: string, actionCode: number, bucketSize: number) {
1816
// Inform the extension of the chrome telemetry event
1917
const telemetry = {
2018
name: `devtools/${actionName}`,
@@ -28,6 +26,11 @@ class ToolsHost {
2826
}
2927
window.parent.postMessage(`telemetry:${JSON.stringify(telemetry)}`, '*');
3028
}
29+
30+
public fireGetStateCallback(state: string) {
31+
const prefs = JSON.parse(state);
32+
this._getStateCallback(prefs);
33+
}
3134
}
3235

3336
class ToolsWebSocket {
@@ -58,7 +61,7 @@ class ToolsWebSocket {
5861
window.parent.postMessage('ready', '*');
5962
}
6063

61-
send(message: string) {
64+
public send(message: string) {
6265
// Forward the message to the extension
6366
window.parent.postMessage(message, '*');
6467
}
@@ -89,6 +92,7 @@ devToolsFrame.onload = () => {
8992
}
9093
};
9194

95+
// Add unhandled exception listeners for telemetry
9296
const reportError = function (name: string, stack: string) {
9397
const telemetry = {
9498
name: `devtools/${name}`,
@@ -97,8 +101,6 @@ devToolsFrame.onload = () => {
97101
};
98102
dtWindow.parent.postMessage(`telemetry:${JSON.stringify(telemetry)}`, '*');
99103
};
100-
101-
// Add unhandled exception listeners for telemetry
102104
(dtWindow as any).addEventListener('error', (event: ErrorEvent) => {
103105
const stack = (event && event.error && event.error.stack ? event.error.stack : event.message);
104106
reportError('error', stack);
@@ -108,3 +110,10 @@ devToolsFrame.onload = () => {
108110
reportError('unhandledrejection', stack);
109111
});
110112
};
113+
114+
// Listen for preferences from the extension
115+
window.addEventListener('message', (e) => {
116+
if (e.data.substr(0, 12) === 'preferences:') {
117+
(devToolsFrame.contentWindow as any).InspectorFrontendHost.fireGetStateCallback(e.data.substr(12));
118+
}
119+
});

0 commit comments

Comments
 (0)