Skip to content

Commit

Permalink
Add explicit wait on protocol registration
Browse files Browse the repository at this point in the history
Possible fix for #89038/#91506. In both cases, it looks like we try to use the protocol before it is properly registered. If this fix doesn't work, there's probably something weird going on on the electron side of things
  • Loading branch information
mjbvz committed Mar 3, 2020
1 parent 2158b1a commit ed8c0e4
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 33 deletions.
41 changes: 25 additions & 16 deletions src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,24 +113,30 @@ class WebviewSession extends Disposable {
}

class WebviewProtocolProvider extends Disposable {

private _resolve!: () => void;
private _reject!: () => void;

public readonly ready: Promise<void>;

constructor(
handle: WebviewTagHandle,
private readonly _getExtensionLocation: () => URI | undefined,
private readonly _getLocalResourceRoots: () => ReadonlyArray<URI>,
private readonly _fileService: IFileService,
getExtensionLocation: () => URI | undefined,
getLocalResourceRoots: () => ReadonlyArray<URI>,
fileService: IFileService,
) {
super();

this.ready = new Promise((resolve, reject) => {
this._resolve = resolve;
this._reject = reject;
});

this._register(handle.onFirstLoad(contents => {
this.registerProtocols(contents);
registerFileProtocol(contents, WebviewResourceScheme, fileService, getExtensionLocation(), getLocalResourceRoots)
.then(this._resolve, this._reject);
}));
}

private registerProtocols(contents: WebContents) {
registerFileProtocol(contents, WebviewResourceScheme, this._fileService, this._getExtensionLocation(), () =>
this._getLocalResourceRoots()
);
}
}

class WebviewPortMappingProvider extends Disposable {
Expand Down Expand Up @@ -204,6 +210,7 @@ export class ElectronWebviewBasedWebview extends BaseWebview<WebviewTag> impleme
private _findStarted: boolean = false;

public extension: WebviewExtensionDescription | undefined;
private readonly _protocolProvider: WebviewProtocolProvider;

constructor(
id: string,
Expand All @@ -222,11 +229,12 @@ export class ElectronWebviewBasedWebview extends BaseWebview<WebviewTag> impleme
const webviewAndContents = this._register(new WebviewTagHandle(this.element!));
const session = this._register(new WebviewSession(webviewAndContents));

this._register(new WebviewProtocolProvider(
webviewAndContents,
() => this.extension ? this.extension.location : undefined,
() => (this.content.options.localResourceRoots || []),
fileService));
this._protocolProvider = new WebviewProtocolProvider
(webviewAndContents,
() => this.extension ? this.extension.location : undefined,
() => (this.content.options.localResourceRoots || []),
fileService);
this._register(this._protocolProvider);

this._register(new WebviewPortMappingProvider(
session,
Expand Down Expand Up @@ -322,7 +330,8 @@ export class ElectronWebviewBasedWebview extends BaseWebview<WebviewTag> impleme
parent.appendChild(this.element);
}

protected postMessage(channel: string, data?: any): void {
protected async postMessage(channel: string, data?: any): Promise<void> {
await this._protocolProvider.ready;
this.element?.send(channel, data);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,27 @@ export function registerFileProtocol(
extensionLocation: URI | undefined,
getRoots: () => ReadonlyArray<URI>
) {
contents.session.protocol.registerBufferProtocol(protocol, async (request, callback: any) => {
try {
const result = await loadLocalResource(URI.parse(request.url), fileService, extensionLocation, getRoots);
if (result.type === WebviewResourceResponse.Type.Success) {
return callback({
data: Buffer.from(result.data.buffer),
mimeType: result.mimeType
});
return new Promise((resolve, reject) =>
contents.session.protocol.registerBufferProtocol(protocol, async (request, callback: any) => {
try {
const result = await loadLocalResource(URI.parse(request.url), fileService, extensionLocation, getRoots);
if (result.type === WebviewResourceResponse.Type.Success) {
return callback({
data: Buffer.from(result.data.buffer),
mimeType: result.mimeType
});
}
if (result.type === WebviewResourceResponse.Type.AccessDenied) {
console.error('Webview: Cannot load resource outside of protocol root');
return callback({ error: -10 /* ACCESS_DENIED: https://cs.chromium.org/chromium/src/net/base/net_error_list.h */ });
}
} catch {
// noop
}
if (result.type === WebviewResourceResponse.Type.AccessDenied) {
console.error('Webview: Cannot load resource outside of protocol root');
return callback({ error: -10 /* ACCESS_DENIED: https://cs.chromium.org/chromium/src/net/base/net_error_list.h */ });
}
} catch {
// noop
}

return callback({ error: -2 /* FAILED: https://cs.chromium.org/chromium/src/net/base/net_error_list.h */ });
});
return callback({ error: -2 /* FAILED: https://cs.chromium.org/chromium/src/net/base/net_error_list.h */ });
}, (err) => {
err ? reject(err) : resolve();
}));
}

0 comments on commit ed8c0e4

Please sign in to comment.