Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't show infinite notebook progress if webview fails to init #176680

Merged
merged 1 commit into from Mar 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -497,10 +497,10 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Themable {
return !!this.webview;
}

createWebview(): void {
createWebview(): Promise<void> {
const baseUrl = this.asWebviewUri(this.getNotebookBaseUri(), undefined);
const htmlContent = this.generateContent(baseUrl.toString());
this._initialize(htmlContent);
return this._initialize(htmlContent);
}

private getNotebookBaseUri() {
Expand Down Expand Up @@ -535,7 +535,7 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Themable {
];
}

private _initialize(content: string) {
private _initialize(content: string): Promise<void> {
if (!document.body.contains(this.element)) {
throw new Error('Element is already detached from the DOM tree');
}
Expand All @@ -546,6 +546,12 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Themable {

this._register(new WebviewWindowDragMonitor(() => this.webview));

const initializePromise = new DeferredPromise<void>();

this._register(this.webview.onFatalError(e => {
initializePromise.error(new Error(`Could not initialize webview: ${e.message}}`));
}));

this._register(this.webview.onMessage(async (message) => {
const data: FromWebviewMessage | { readonly __vscode_notebook_message: undefined } = message.message;
if (this._disposed) {
Expand All @@ -558,6 +564,7 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Themable {

switch (data.type) {
case 'initialized': {
initializePromise.complete();
this.initializeWebViewState();
break;
}
Expand Down Expand Up @@ -828,6 +835,8 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Themable {
}
}
}));

return initializePromise.p;
}

private _handleNotebookCellResource(uri: URI) {
Expand Down
4 changes: 4 additions & 0 deletions src/vs/workbench/contrib/webview/browser/overlayWebview.ts
Expand Up @@ -222,6 +222,7 @@ export class OverlayWebview extends Disposable implements IOverlayWebview {
this._webviewEvents.add(webview.onMissingCsp(x => { this._onMissingCsp.fire(x); }));
this._webviewEvents.add(webview.onDidWheel(x => { this._onDidWheel.fire(x); }));
this._webviewEvents.add(webview.onDidReload(() => { this._onDidReload.fire(); }));
this._webviewEvents.add(webview.onFatalError(x => { this._onFatalError.fire(x); }));

this._webviewEvents.add(webview.onDidScroll(x => {
this._initialScrollProgress = x.scrollYPercentage;
Expand Down Expand Up @@ -320,6 +321,9 @@ export class OverlayWebview extends Disposable implements IOverlayWebview {
private readonly _onDidWheel = this._register(new Emitter<IMouseWheelEvent>());
public readonly onDidWheel = this._onDidWheel.event;

private readonly _onFatalError = this._register(new Emitter<{ readonly message: string }>());
public onFatalError = this._onFatalError.event;

public async postMessage(message: any, transfer?: readonly ArrayBuffer[]): Promise<boolean> {
if (this._webview.value) {
return this._webview.value.postMessage(message, transfer);
Expand Down
13 changes: 12 additions & 1 deletion src/vs/workbench/contrib/webview/browser/webview.ts
Expand Up @@ -215,16 +215,27 @@ export interface IWebview extends IDisposable {

readonly onDidFocus: Event<void>;
readonly onDidBlur: Event<void>;

/**
* Fired when the webview is disposed of.
*/
readonly onDidDispose: Event<void>;

readonly onDidClickLink: Event<string>;
readonly onDidScroll: Event<{ readonly scrollYPercentage: number }>;
readonly onDidWheel: Event<IMouseWheelEvent>;

readonly onDidUpdateState: Event<string | undefined>;
readonly onDidReload: Event<void>;
readonly onMessage: Event<WebviewMessageReceivedEvent>;

/**
* Fired when the webview cannot be loaded or is now in a non-functional state.
*/
readonly onFatalError: Event<{ readonly message: string }>;
readonly onMissingCsp: Event<ExtensionIdentifier>;

readonly onMessage: Event<WebviewMessageReceivedEvent>;

postMessage(message: any, transfer?: readonly ArrayBuffer[]): Promise<boolean>;

focus(): void;
Expand Down
4 changes: 4 additions & 0 deletions src/vs/workbench/contrib/webview/browser/webviewElement.ts
Expand Up @@ -261,6 +261,7 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD

this._register(this.on('fatal-error', (e) => {
notificationService.error(localize('fatalErrorMessage', "Error loading webview: {0}", e.message));
this._onFatalError.fire({ message: e.message });
}));

this._register(this.on('did-keydown', (data) => {
Expand Down Expand Up @@ -403,6 +404,9 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD
private readonly _onDidBlur = this._register(new Emitter<void>());
public readonly onDidBlur = this._onDidBlur.event;

private readonly _onFatalError = this._register(new Emitter<{ readonly message: string }>());
public readonly onFatalError = this._onFatalError.event;

private readonly _onDidDispose = this._register(new Emitter<void>());
public readonly onDidDispose = this._onDidDispose.event;

Expand Down