From 4333020157f3041f812881cf4775d041c3ca7bfe Mon Sep 17 00:00:00 2001 From: "trop[bot]" Date: Sat, 21 Jul 2018 16:51:31 +0900 Subject: [PATCH] fix: create WebContents for webview on request (#13761) --- lib/browser/guest-view-manager.js | 4 ++++ lib/renderer/web-view/guest-view-internal.js | 3 +++ lib/renderer/web-view/web-view-attributes.js | 5 +---- lib/renderer/web-view/web-view.js | 10 +++++++++- spec/webview-spec.js | 17 ++++++++++++++--- 5 files changed, 31 insertions(+), 8 deletions(-) diff --git a/lib/browser/guest-view-manager.js b/lib/browser/guest-view-manager.js index da2663e606..1e44876268 100644 --- a/lib/browser/guest-view-manager.js +++ b/lib/browser/guest-view-manager.js @@ -348,6 +348,10 @@ ipcMain.on('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST', function (event, params, event.sender.send(`ELECTRON_RESPONSE_${requestId}`, createGuest(event.sender, params)) }) +ipcMain.on('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST_SYNC', function (event, params) { + event.returnValue = createGuest(event.sender, params) +}) + ipcMain.on('ELECTRON_GUEST_VIEW_MANAGER_ATTACH_GUEST', function (event, elementInstanceId, guestInstanceId, params) { attachGuest(event, elementInstanceId, guestInstanceId, params) }) diff --git a/lib/renderer/web-view/guest-view-internal.js b/lib/renderer/web-view/guest-view-internal.js index a868b513eb..b9b7a8ea39 100644 --- a/lib/renderer/web-view/guest-view-internal.js +++ b/lib/renderer/web-view/guest-view-internal.js @@ -100,6 +100,9 @@ module.exports = { ipcRenderer.send('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST', params, requestId) ipcRenderer.once(`ELECTRON_RESPONSE_${requestId}`, callback) }, + createGuestSync: function (params) { + return ipcRenderer.sendSync('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST_SYNC', params) + }, attachGuest: function (elementInstanceId, guestInstanceId, params) { ipcRenderer.send('ELECTRON_GUEST_VIEW_MANAGER_ATTACH_GUEST', elementInstanceId, guestInstanceId, params) webFrame.attachGuest(elementInstanceId) diff --git a/lib/renderer/web-view/web-view-attributes.js b/lib/renderer/web-view/web-view-attributes.js index 16bfe7e61a..204046bd60 100644 --- a/lib/renderer/web-view/web-view-attributes.js +++ b/lib/renderer/web-view/web-view-attributes.js @@ -230,7 +230,7 @@ class SrcAttribute extends WebViewAttribute { } parse () { - if (!this.webViewImpl.elementAttached || !this.webViewImpl.attributes[webViewConstants.ATTRIBUTE_PARTITION].validPartitionId) { + if (!this.webViewImpl.elementAttached || !this.webViewImpl.attributes[webViewConstants.ATTRIBUTE_PARTITION].validPartitionId || !this.getValue()) { return } if (this.webViewImpl.guestInstanceId == null) { @@ -240,9 +240,6 @@ class SrcAttribute extends WebViewAttribute { } return } - if (!this.getValue()) { - return - } // Navigate to |this.src|. const opts = {} diff --git a/lib/renderer/web-view/web-view.js b/lib/renderer/web-view/web-view.js index bea1a5d420..0f2962e298 100644 --- a/lib/renderer/web-view/web-view.js +++ b/lib/renderer/web-view/web-view.js @@ -174,6 +174,10 @@ class WebViewImpl { }) } + createGuestSync () { + this.attachGuestInstance(guestViewInternal.createGuestSync(this.buildParams())) + } + dispatchEvent (webViewEvent) { this.webviewNode.dispatchEvent(webViewEvent) } @@ -421,7 +425,11 @@ const registerWebViewElement = function () { // WebContents associated with this webview. proto.getWebContents = function () { - return v8Util.getHiddenValue(this, 'internal').webContents + const internal = v8Util.getHiddenValue(this, 'internal') + if (!internal.webContents) { + internal.createGuestSync() + } + return internal.webContents } window.WebView = webFrame.registerEmbedderCustomElement('webview', { diff --git a/spec/webview-spec.js b/spec/webview-spec.js index 7f52cad128..1464991a4a 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -679,7 +679,6 @@ describe(' tag', function () { it('sets webContents of webview as devtools', async () => { const webview2 = new WebView() loadWebView(webview2) - await waitForEvent(webview2, 'did-attach') // Setup an event handler for further usage. const waitForDomReady = waitForEvent(webview2, 'dom-ready') @@ -1161,6 +1160,18 @@ describe(' tag', function () { }) describe('will-attach-webview event', () => { + it('does not emit when src is not changed', (done) => { + loadWebView(webview) + setTimeout(() => { + const expectedErrorMessage = + 'Cannot call stop because the webContents is unavailable. ' + + 'The WebView must be attached to the DOM ' + + 'and the dom-ready event emitted before this method can be called.' + expect(() => { webview.stop() }).to.throw(expectedErrorMessage) + done() + }) + }) + it('supports changing the web preferences', async () => { ipcRenderer.send('disable-node-on-next-will-attach-webview') const message = await startLoadingWebViewAndWaitForMessage(webview, { @@ -1349,11 +1360,11 @@ describe(' tag', function () { const destroy1Listener = () => { assert.equal(webContents, webview2.getWebContents()) - assert.equal(null, webview.getWebContents()) + assert.notStrictEqual(webContents, webview.getWebContents()) const destroy2Listener = () => { assert.equal(webContents, webview.getWebContents()) - assert.equal(null, webview2.getWebContents()) + assert.notStrictEqual(webContents, webview2.getWebContents()) // Make sure that events are hooked up to the right webview now webview.addEventListener('console-message', (e) => {