From c2b02df9ab208b025b214599660ee86027ca7df9 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 22 May 2019 15:23:22 -0700 Subject: [PATCH] Allow hidden (but persisted) webviews to recieve messages Fixes #47534 --- .../src/singlefolder-tests/webview.test.ts | 87 +++++++++++-------- .../api/electron-browser/mainThreadWebview.ts | 17 ++-- 2 files changed, 61 insertions(+), 43 deletions(-) diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/webview.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/webview.test.ts index 5e28b247b07..3cc1cb3863b 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/webview.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/webview.test.ts @@ -132,24 +132,7 @@ suite('Webview tests', () => { // Open webview in same column const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true })); const ready = getMesssage(webview); - webview.webview.html = createHtmlDocumentWithBody(/*html*/` - `); + webview.webview.html = statefulWebviewHtml; await ready; const firstResponse = await sendRecieveMessage(webview, { type: 'add' }); @@ -167,25 +150,7 @@ suite('Webview tests', () => { const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true, retainContextWhenHidden: true })); const ready = getMesssage(webview); - webview.webview.html = createHtmlDocumentWithBody(/*html*/` - `); + webview.webview.html = statefulWebviewHtml; await ready; const firstResponse = await sendRecieveMessage(webview, { type: 'add' }); @@ -244,6 +209,33 @@ suite('Webview tests', () => { assert.strictEqual(secondResponse.value, 100); }); + conditionalTest('webviews with retainContextWhenHidden should be able to recive messages while hidden', async () => { + const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true, retainContextWhenHidden: true })); + const ready = getMesssage(webview); + + webview.webview.html = statefulWebviewHtml; + await ready; + + const firstResponse = await sendRecieveMessage(webview, { type: 'add' }); + assert.strictEqual((await firstResponse).value, 1); + + // Swap away from the webview + const doc = await vscode.workspace.openTextDocument(testDocument); + await vscode.window.showTextDocument(doc); + + // Try posting a message to our hidden webview + const secondResponse = await sendRecieveMessage(webview, { type: 'add' }); + assert.strictEqual((await secondResponse).value, 2); + + // Now show webview again + webview.reveal(vscode.ViewColumn.One); + + // We should still have old state + const thirdResponse = await sendRecieveMessage(webview, { type: 'get' }); + assert.strictEqual(thirdResponse.value, 2); + }); + + conditionalTest('webviews should only be able to load resources from workspace by default', async () => { const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true })); @@ -356,6 +348,27 @@ function createHtmlDocumentWithBody(body: string): string { `; } +const statefulWebviewHtml = createHtmlDocumentWithBody(/*html*/ ` + `); + + function getMesssage(webview: vscode.WebviewPanel): Promise { return new Promise(resolve => { const sub = webview.webview.onDidReceiveMessage(message => { diff --git a/src/vs/workbench/api/electron-browser/mainThreadWebview.ts b/src/vs/workbench/api/electron-browser/mainThreadWebview.ts index 09e372750d1..e0abea919a8 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadWebview.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadWebview.ts @@ -210,11 +210,10 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews } } - public $postMessage(handle: WebviewPanelHandle | WebviewInsetHandle, message: any): Promise { + public async $postMessage(handle: WebviewPanelHandle | WebviewInsetHandle, message: any): Promise { if (typeof handle === 'number') { this.getWebviewElement(handle).sendMessage(message); - return Promise.resolve(true); - + return true; } else { const webview = this.getWebview(handle); const editors = this._editorService.visibleControls @@ -222,11 +221,17 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews .map(e => e as WebviewEditor) .filter(e => e.input!.matches(webview)); - for (const editor of editors) { - editor.sendMessage(message); + if (editors.length > 0) { + editors[0].sendMessage(message); + return true; } - return Promise.resolve(editors.length > 0); + if (webview.webview) { + webview.webview.sendMessage(message); + return true; + } + + return false; } }