mirror of
https://github.com/microsoft/vscode.git
synced 2026-09-01 21:54:52 +01:00
Add explicit wait on protocol registration
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
This commit is contained in:
@@ -113,23 +113,29 @@ 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._register(handle.onFirstLoad(contents => {
|
||||
this.registerProtocols(contents);
|
||||
}));
|
||||
}
|
||||
this.ready = new Promise((resolve, reject) => {
|
||||
this._resolve = resolve;
|
||||
this._reject = reject;
|
||||
});
|
||||
|
||||
private registerProtocols(contents: WebContents) {
|
||||
registerFileProtocol(contents, WebviewResourceScheme, this._fileService, this._getExtensionLocation(), () =>
|
||||
this._getLocalResourceRoots()
|
||||
);
|
||||
this._register(handle.onFirstLoad(contents => {
|
||||
registerFileProtocol(contents, WebviewResourceScheme, fileService, getExtensionLocation(), getLocalResourceRoots)
|
||||
.then(this._resolve, this._reject);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
@@ -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,
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user