Skip to content

Commit 75fb631

Browse files
committed
Move webview protocol to live in webview manager service
This reduces the use of the ipc module
1 parent 6088508 commit 75fb631

6 files changed

Lines changed: 79 additions & 61 deletions

File tree

src/vs/code/electron-main/app.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ import { StorageKeysSyncRegistryChannel } from 'vs/platform/userDataSync/common/
7979
import { INativeEnvironmentService } from 'vs/platform/environment/node/environmentService';
8080
import { mnemonicButtonLabel, getPathLabel } from 'vs/base/common/labels';
8181
import { IFileService } from 'vs/platform/files/common/files';
82-
import { WebviewProtocolProvider } from 'vs/platform/webview/electron-main/webviewProtocolProvider';
8382
import { WebviewChannel } from 'vs/platform/webview/electron-main/webviewIpcs';
8483
import { WebviewMainService } from 'vs/platform/webview/electron-main/webviewMainService';
8584
import { IWebviewManagerService } from 'vs/platform/webview/common/webviewManagerService';
@@ -102,8 +101,6 @@ export class CodeApplication extends Disposable {
102101
super();
103102

104103
this.registerListeners();
105-
106-
this._register(new WebviewProtocolProvider(fileService));
107104
}
108105

109106
private registerListeners(): void {

src/vs/platform/webview/common/webviewManagerService.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,22 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6+
import { UriComponents } from 'vs/base/common/uri';
67
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
78

89
export const IWebviewManagerService = createDecorator<IWebviewManagerService>('webviewManagerService');
910

1011
export interface IWebviewManagerService {
1112
_serviceBrand: unknown;
1213

14+
registerWebview(id: string, metadata: RegisterWebviewMetadata): Promise<void>;
15+
unregisterWebview(id: string): Promise<void>;
16+
updateLocalResourceRoots(id: string, roots: UriComponents[]): Promise<void>;
17+
1318
setIgnoreMenuShortcuts(webContentsId: number, enabled: boolean): void;
1419
}
20+
21+
export interface RegisterWebviewMetadata {
22+
readonly extensionLocation: UriComponents | undefined;
23+
readonly localResourceRoots: readonly UriComponents[];
24+
}

src/vs/platform/webview/electron-main/webviewIpcs.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ import { Event } from 'vs/base/common/event';
77
import { IServerChannel } from 'vs/base/parts/ipc/common/ipc';
88
import { IWebviewManagerService } from 'vs/platform/webview/common/webviewManagerService';
99

10+
type KeyWithParams<T> = {
11+
[K in keyof T]: T[K] extends (...args: infer P) => any ? [K, P] : never
12+
}[keyof T];
13+
1014
export class WebviewChannel implements IServerChannel {
1115

1216
constructor(
@@ -17,11 +21,14 @@ export class WebviewChannel implements IServerChannel {
1721
throw new Error(`Event not found: ${event}`);
1822
}
1923

20-
async call(_: unknown, command: string, arg?: any): Promise<any> {
21-
switch (command) {
22-
case 'setIgnoreMenuShortcuts': this.webviewMainService.setIgnoreMenuShortcuts(arg[0], arg[1]); return;
24+
async call(_: unknown, ...commandAndArgs: KeyWithParams<IWebviewManagerService>): Promise<any> {
25+
switch (commandAndArgs[0]) {
26+
case 'setIgnoreMenuShortcuts': this.webviewMainService.setIgnoreMenuShortcuts(...commandAndArgs[1]); return;
27+
case 'registerWebview': this.webviewMainService.registerWebview(...commandAndArgs[1]); return;
28+
case 'unregisterWebview': this.webviewMainService.unregisterWebview(...commandAndArgs[1]); return;
29+
case 'updateLocalResourceRoots': this.webviewMainService.updateLocalResourceRoots(...commandAndArgs[1]); return;
2330
}
2431

25-
throw new Error(`Call not found: ${command}`);
32+
throw new Error(`Call not found: ${commandAndArgs[0]}`);
2633
}
2734
}

src/vs/platform/webview/electron-main/webviewMainService.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,38 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { webContents } from 'electron';
7-
import { IWebviewManagerService } from 'vs/platform/webview/common/webviewManagerService';
7+
import { IWebviewManagerService, RegisterWebviewMetadata } from 'vs/platform/webview/common/webviewManagerService';
8+
import { WebviewProtocolProvider } from 'vs/platform/webview/electron-main/webviewProtocolProvider';
9+
import { IFileService } from 'vs/platform/files/common/files';
10+
import { UriComponents, URI } from 'vs/base/common/uri';
811

912
export class WebviewMainService implements IWebviewManagerService {
1013

1114
_serviceBrand: undefined;
1215

16+
private protocolProvider: WebviewProtocolProvider;
17+
18+
constructor(
19+
@IFileService fileService: IFileService,
20+
) {
21+
this.protocolProvider = new WebviewProtocolProvider(fileService);
22+
}
23+
24+
public async registerWebview(id: string, metadata: RegisterWebviewMetadata): Promise<void> {
25+
this.protocolProvider.registerWebview(id,
26+
metadata.extensionLocation ? URI.from(metadata.extensionLocation) : undefined,
27+
metadata.localResourceRoots.map((x: UriComponents) => URI.from(x))
28+
);
29+
}
30+
31+
public async unregisterWebview(id: string): Promise<void> {
32+
this.protocolProvider.unreigsterWebview(id);
33+
}
34+
35+
public async updateLocalResourceRoots(id: string, roots: UriComponents[]): Promise<void> {
36+
this.protocolProvider.updateLocalResourceRoots(id, roots.map((x: UriComponents) => URI.from(x)));
37+
}
38+
1339
public setIgnoreMenuShortcuts(webContentsId: number, enabled: boolean): void {
1440
const contents = webContents.fromId(webContentsId);
1541
if (!contents) {

src/vs/platform/webview/electron-main/webviewProtocolProvider.ts

Lines changed: 21 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,56 +3,26 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { ipcMain as ipc, IpcMainEvent, protocol } from 'electron';
6+
import { protocol } from 'electron';
77
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
88
import { Schemas } from 'vs/base/common/network';
9-
import { URI, UriComponents } from 'vs/base/common/uri';
9+
import { URI } from 'vs/base/common/uri';
1010
import { streamToNodeReadable } from 'vs/base/node/stream';
1111
import { IFileService } from 'vs/platform/files/common/files';
1212
import { loadLocalResourceStream, WebviewResourceResponse } from 'vs/platform/webview/common/resourceLoader';
1313

14-
export interface RegisterWebviewMetadata {
15-
readonly extensionLocation: URI | undefined;
16-
readonly localResourceRoots: readonly URI[];
17-
}
18-
19-
2014
export class WebviewProtocolProvider extends Disposable {
2115

2216
private readonly webviewMetadata = new Map<string, {
2317
readonly extensionLocation: URI | undefined;
24-
readonly localResourceRoots: URI[];
18+
readonly localResourceRoots: readonly URI[];
2519
}>();
2620

2721
constructor(
2822
@IFileService private readonly fileService: IFileService,
2923
) {
3024
super();
3125

32-
ipc.on('vscode:registerWebview', (event: IpcMainEvent, id: string, data: RegisterWebviewMetadata) => {
33-
this.webviewMetadata.set(id, {
34-
extensionLocation: data.extensionLocation ? URI.from(data.extensionLocation) : undefined,
35-
localResourceRoots: data.localResourceRoots.map((x: UriComponents) => URI.from(x)),
36-
});
37-
38-
event.sender.send(`vscode:didRegisterWebview-${id}`);
39-
});
40-
41-
ipc.on('vscode:updateWebviewLocalResourceRoots', (event: IpcMainEvent, id: string, localResourceRoots: readonly URI[]) => {
42-
const entry = this.webviewMetadata.get(id);
43-
if (entry) {
44-
this.webviewMetadata.set(id, {
45-
extensionLocation: entry.extensionLocation,
46-
localResourceRoots: localResourceRoots.map((x: UriComponents) => URI.from(x)),
47-
});
48-
}
49-
event.sender.send(`vscode:didUpdateWebviewLocalResourceRoots-${id}`);
50-
});
51-
52-
ipc.on('vscode:unregisterWebview', (_event: IpcMainEvent, id: string) => {
53-
this.webviewMetadata.delete(id);
54-
});
55-
5626
protocol.registerStreamProtocol(Schemas.vscodeWebviewResource, async (request, callback): Promise<void> => {
5727
try {
5828
const uri = URI.parse(request.url);
@@ -86,4 +56,22 @@ export class WebviewProtocolProvider extends Disposable {
8656

8757
this._register(toDisposable(() => protocol.unregisterProtocol(Schemas.vscodeWebviewResource)));
8858
}
59+
60+
public registerWebview(id: string, extensionLocation: URI | undefined, localResourceRoots: readonly URI[]): void {
61+
this.webviewMetadata.set(id, { extensionLocation, localResourceRoots });
62+
}
63+
64+
public unreigsterWebview(id: string): void {
65+
this.webviewMetadata.delete(id);
66+
}
67+
68+
public updateLocalResourceRoots(id: string, localResourceRoots: readonly URI[]) {
69+
const entry = this.webviewMetadata.get(id);
70+
if (entry) {
71+
this.webviewMetadata.set(id, {
72+
extensionLocation: entry.extensionLocation,
73+
localResourceRoots: localResourceRoots,
74+
});
75+
}
76+
}
8977
}

src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { FindInPageOptions, OnBeforeRequestListenerDetails, OnHeadersReceivedListenerDetails, Response, WebContents, WebviewTag } from 'electron';
7-
import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals';
87
import { addDisposableListener } from 'vs/base/browser/dom';
98
import { equals } from 'vs/base/common/arrays';
109
import { ThrottledDelayer } from 'vs/base/common/async';
@@ -14,22 +13,22 @@ import { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/
1413
import { Schemas } from 'vs/base/common/network';
1514
import { isMacintosh } from 'vs/base/common/platform';
1615
import { URI } from 'vs/base/common/uri';
16+
import { createChannelSender } from 'vs/base/parts/ipc/common/ipc';
1717
import * as modes from 'vs/editor/common/modes';
1818
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
1919
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
2020
import { IFileService } from 'vs/platform/files/common/files';
2121
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
22+
import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService';
2223
import { ITunnelService } from 'vs/platform/remote/common/tunnel';
2324
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
25+
import { IWebviewManagerService } from 'vs/platform/webview/common/webviewManagerService';
2426
import { BaseWebview, WebviewMessageChannels } from 'vs/workbench/contrib/webview/browser/baseWebviewElement';
2527
import { Webview, WebviewContentOptions, WebviewExtensionDescription, WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview';
2628
import { WebviewPortMappingManager } from 'vs/workbench/contrib/webview/common/portMapping';
2729
import { WebviewThemeDataProvider } from 'vs/workbench/contrib/webview/common/themeing';
2830
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
2931
import { WebviewFindDelegate, WebviewFindWidget } from '../browser/webviewFindWidget';
30-
import { IWebviewManagerService } from 'vs/platform/webview/common/webviewManagerService';
31-
import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService';
32-
import { createChannelSender } from 'vs/base/parts/ipc/common/ipc';
3332

3433
class WebviewTagHandle extends Disposable {
3534

@@ -127,19 +126,18 @@ class WebviewProtocolProvider extends Disposable {
127126
private readonly id: string,
128127
private readonly extension: WebviewExtensionDescription | undefined,
129128
initialLocalResourceRoots: ReadonlyArray<URI>,
129+
private readonly _webviewManagerService: IWebviewManagerService,
130130
) {
131131
super();
132132

133133
this._localResourceRoots = initialLocalResourceRoots;
134134

135-
ipcRenderer.send('vscode:registerWebview', this.id, {
135+
this._ready = _webviewManagerService.registerWebview(this.id, {
136136
extensionLocation: this.extension?.location.toJSON(),
137137
localResourceRoots: initialLocalResourceRoots.map(x => x.toJSON()),
138138
});
139139

140-
this._ready = new Promise((resolve) => {
141-
ipcRenderer.once(`vscode:didRegisterWebview-${this.id}`, () => resolve());
142-
});
140+
this._register(toDisposable(() => this._webviewManagerService.unregisterWebview(this.id)));
143141
}
144142

145143
public update(localResourceRoots: ReadonlyArray<URI>) {
@@ -149,22 +147,12 @@ class WebviewProtocolProvider extends Disposable {
149147

150148
this._localResourceRoots = localResourceRoots;
151149

152-
ipcRenderer.send('vscode:updateWebviewLocalResourceRoots', this.id, localResourceRoots.map(x => x.toJSON()));
153-
154-
this._ready = new Promise((resolve) => {
155-
ipcRenderer.once(`vscode:didUpdateWebviewLocalResourceRoots-${this.id}`, () => resolve());
156-
});
150+
this._ready = this._webviewManagerService.updateLocalResourceRoots(this.id, localResourceRoots.map(x => x.toJSON()));
157151
}
158152

159153
async synchronize(): Promise<void> {
160154
return this._ready;
161155
}
162-
163-
dispose() {
164-
super.dispose();
165-
166-
ipcRenderer.send('vscode:unregisterWebview', this.id);
167-
}
168156
}
169157

170158
class WebviewPortMappingProvider extends Disposable {
@@ -286,10 +274,12 @@ export class ElectronWebviewBasedWebview extends BaseWebview<WebviewTag> impleme
286274
) {
287275
super(id, options, contentOptions, extension, _webviewThemeDataProvider, telemetryService, environementService, workbenchEnvironmentService);
288276

277+
const webviewManagerService = createChannelSender<IWebviewManagerService>(mainProcessService.getChannel('webview'));
278+
289279
const webviewAndContents = this._register(new WebviewTagHandle(this.element!));
290280
const session = this._register(new WebviewSession(webviewAndContents));
291281

292-
this._protocolProvider = this._register(new WebviewProtocolProvider(id, extension, this.content.options.localResourceRoots || []));
282+
this._protocolProvider = this._register(new WebviewProtocolProvider(id, extension, this.content.options.localResourceRoots || [], webviewManagerService));
293283

294284
this._register(new WebviewPortMappingProvider(
295285
session,

0 commit comments

Comments
 (0)