diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 8c8afe56014..a98b67a079f 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -483,16 +483,20 @@ WebContents::~WebContents() { RenderViewDeleted(web_contents()->GetRenderViewHost()); - if (type_ == BROWSER_WINDOW && owner_window()) { - for (ExtendedWebContentsObserver& observer : observers_) - observer.OnCloseContents(); + if (type_ == WEB_VIEW) { + DestroyWebContents(false /* async */); } else { - DestroyWebContents(!IsGuest() /* async */); + if (type_ == BROWSER_WINDOW && owner_window()) { + for (ExtendedWebContentsObserver& observer : observers_) + observer.OnCloseContents(); + } else { + DestroyWebContents(true /* async */); + } + // The WebContentsDestroyed will not be called automatically because we + // destroy the webContents in the next tick. So we have to manually + // call it here to make sure "destroyed" event is emitted. + WebContentsDestroyed(); } - // The WebContentsDestroyed will not be called automatically because we - // destroy the webContents in the next tick. So we have to manually - // call it here to make sure "destroyed" event is emitted. - WebContentsDestroyed(); } } @@ -1048,7 +1052,7 @@ bool WebContents::OnMessageReceived(const IPC::Message& message, // 2. garbage collection; // 3. user closes the window of webContents; // 4. the embedder detaches the frame. -// For webview only #4 will happen, for BrowserWindow both #1 and #3 may +// For webview both #1 and #4 may happen, for BrowserWindow both #1 and #3 may // happen. The #2 should never happen for webContents, because webview is // managed by GuestViewManager, and BrowserWindow's webContents is managed // by api::BrowserWindow. diff --git a/lib/browser/guest-view-manager.js b/lib/browser/guest-view-manager.js index 06ce7d21c7e..b9ff71035bc 100644 --- a/lib/browser/guest-view-manager.js +++ b/lib/browser/guest-view-manager.js @@ -70,6 +70,19 @@ const createGuest = function (embedder, params) { } // Clear the guest from map when it is destroyed. + // + // The guest WebContents is usually destroyed in 2 cases: + // 1. The embedder frame is closed (reloaded or destroyed), and it + // automatically closes the guest frame. + // 2. The guest frame is detached dynamically via JS, and it is manually + // destroyed when the renderer sends the GUEST_VIEW_MANAGER_DESTROY_GUEST + // message. + // The second case relies on the libcc patch: + // https://github.com/electron/libchromiumcontent/pull/676 + // The patch was introduced to work around a bug in Chromium: + // https://github.com/electron/electron/issues/14211 + // We should revisit the bug to see if we can remove our libcc patch, the + // patch was introduced in Chrome 66. guest.once('destroyed', () => { if (guestInstanceId in guestInstances) { detachGuest(embedder, guestInstanceId) @@ -319,6 +332,13 @@ ipcMain.on('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST_SYNC', function (event, par event.returnValue = createGuest(event.sender, params) }) +ipcMain.on('ELECTRON_GUEST_VIEW_MANAGER_DESTROY_GUEST', function (event, guestInstanceId) { + const guest = getGuest(guestInstanceId) + if (guest) { + guest.destroy() + } +}) + ipcMain.on('ELECTRON_GUEST_VIEW_MANAGER_ATTACH_GUEST', function (event, embedderFrameId, elementInstanceId, guestInstanceId, params) { attachGuest(event, embedderFrameId, elementInstanceId, guestInstanceId, params) }) diff --git a/lib/renderer/web-view/guest-view-internal.js b/lib/renderer/web-view/guest-view-internal.js index 183c85af850..3abef43dffd 100644 --- a/lib/renderer/web-view/guest-view-internal.js +++ b/lib/renderer/web-view/guest-view-internal.js @@ -94,6 +94,9 @@ module.exports = { createGuestSync: function (params) { return ipcRenderer.sendSync('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST_SYNC', params) }, + destroyGuest: function (guestInstanceId) { + ipcRenderer.send('ELECTRON_GUEST_VIEW_MANAGER_DESTROY_GUEST', guestInstanceId) + }, attachGuest: function (elementInstanceId, guestInstanceId, params, contentWindow) { const embedderFrameId = webFrame.getWebFrameId(contentWindow) if (embedderFrameId < 0) { // this error should not happen. diff --git a/lib/renderer/web-view/web-view.js b/lib/renderer/web-view/web-view.js index 063d6ab5622..29bcbd5e577 100644 --- a/lib/renderer/web-view/web-view.js +++ b/lib/renderer/web-view/web-view.js @@ -76,6 +76,7 @@ class WebViewImpl { // heard back from createGuest yet. We will not reset the flag in this case so // that we don't end up allocating a second guest. if (this.guestInstanceId) { + guestViewInternal.destroyGuest(this.guestInstanceId) this.guestInstanceId = void 0 } diff --git a/vendor/libchromiumcontent b/vendor/libchromiumcontent index d2ffd8ab4b2..6fdee949b2b 160000 --- a/vendor/libchromiumcontent +++ b/vendor/libchromiumcontent @@ -1 +1 @@ -Subproject commit d2ffd8ab4b238cb9fa16026ea95bd24b5c79915f +Subproject commit 6fdee949b2b153cb6e64217ee984e010b5e9028c