Merge pull request #14488 from electron/manage-webview-webcontents-3-0-x
fix: manually manage WebContents of webview when it is detached (3-0-x)
This commit is contained in:
commit
03dac078d7
5 changed files with 38 additions and 10 deletions
|
@ -483,17 +483,21 @@ WebContents::~WebContents() {
|
||||||
|
|
||||||
RenderViewDeleted(web_contents()->GetRenderViewHost());
|
RenderViewDeleted(web_contents()->GetRenderViewHost());
|
||||||
|
|
||||||
|
if (type_ == WEB_VIEW) {
|
||||||
|
DestroyWebContents(false /* async */);
|
||||||
|
} else {
|
||||||
if (type_ == BROWSER_WINDOW && owner_window()) {
|
if (type_ == BROWSER_WINDOW && owner_window()) {
|
||||||
for (ExtendedWebContentsObserver& observer : observers_)
|
for (ExtendedWebContentsObserver& observer : observers_)
|
||||||
observer.OnCloseContents();
|
observer.OnCloseContents();
|
||||||
} else {
|
} else {
|
||||||
DestroyWebContents(!IsGuest() /* async */);
|
DestroyWebContents(true /* async */);
|
||||||
}
|
}
|
||||||
// The WebContentsDestroyed will not be called automatically because we
|
// The WebContentsDestroyed will not be called automatically because we
|
||||||
// destroy the webContents in the next tick. So we have to manually
|
// destroy the webContents in the next tick. So we have to manually
|
||||||
// call it here to make sure "destroyed" event is emitted.
|
// call it here to make sure "destroyed" event is emitted.
|
||||||
WebContentsDestroyed();
|
WebContentsDestroyed();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebContents::DestroyWebContents(bool async) {
|
void WebContents::DestroyWebContents(bool async) {
|
||||||
|
@ -1040,7 +1044,7 @@ bool WebContents::OnMessageReceived(const IPC::Message& message,
|
||||||
// 2. garbage collection;
|
// 2. garbage collection;
|
||||||
// 3. user closes the window of webContents;
|
// 3. user closes the window of webContents;
|
||||||
// 4. the embedder detaches the frame.
|
// 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
|
// happen. The #2 should never happen for webContents, because webview is
|
||||||
// managed by GuestViewManager, and BrowserWindow's webContents is managed
|
// managed by GuestViewManager, and BrowserWindow's webContents is managed
|
||||||
// by api::BrowserWindow.
|
// by api::BrowserWindow.
|
||||||
|
|
|
@ -70,6 +70,19 @@ const createGuest = function (embedder, params) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear the guest from map when it is destroyed.
|
// 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', () => {
|
guest.once('destroyed', () => {
|
||||||
if (guestInstanceId in guestInstances) {
|
if (guestInstanceId in guestInstances) {
|
||||||
detachGuest(embedder, guestInstanceId)
|
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)
|
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) {
|
ipcMain.on('ELECTRON_GUEST_VIEW_MANAGER_ATTACH_GUEST', function (event, embedderFrameId, elementInstanceId, guestInstanceId, params) {
|
||||||
attachGuest(event, embedderFrameId, elementInstanceId, guestInstanceId, params)
|
attachGuest(event, embedderFrameId, elementInstanceId, guestInstanceId, params)
|
||||||
})
|
})
|
||||||
|
|
|
@ -94,6 +94,9 @@ module.exports = {
|
||||||
createGuestSync: function (params) {
|
createGuestSync: function (params) {
|
||||||
return ipcRenderer.sendSync('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST_SYNC', 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) {
|
attachGuest: function (elementInstanceId, guestInstanceId, params, contentWindow) {
|
||||||
const embedderFrameId = webFrame.getWebFrameId(contentWindow)
|
const embedderFrameId = webFrame.getWebFrameId(contentWindow)
|
||||||
if (embedderFrameId < 0) { // this error should not happen.
|
if (embedderFrameId < 0) { // this error should not happen.
|
||||||
|
|
|
@ -76,6 +76,7 @@ class WebViewImpl {
|
||||||
// heard back from createGuest yet. We will not reset the flag in this case so
|
// 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.
|
// that we don't end up allocating a second guest.
|
||||||
if (this.guestInstanceId) {
|
if (this.guestInstanceId) {
|
||||||
|
guestViewInternal.destroyGuest(this.guestInstanceId)
|
||||||
this.guestInstanceId = void 0
|
this.guestInstanceId = void 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
vendor/libchromiumcontent
vendored
2
vendor/libchromiumcontent
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 61d71f3f150c3ff5025560dee254a53313bfbaf6
|
Subproject commit 0309588604aedd159793b611ae14a9015e4f65d0
|
Loading…
Reference in a new issue