fix: detach webview instead of destroying it

Chromium no longer cleans up everything when a guest webcontents is
destroyed, we have to force detaching it and let Chromium destroy everything.
This commit is contained in:
Cheng Zhao 2019-01-12 15:50:33 +09:00 committed by Jeremy Apthorp
parent 5e043812ef
commit 03d499bf34
7 changed files with 21 additions and 6 deletions

View file

@ -421,7 +421,6 @@ static_library("electron_lib") {
if (enable_osr) { if (enable_osr) {
sources += [ sources += [
"atom/browser/api/atom_api_web_contents_osr.cc",
"atom/browser/osr/osr_output_device.cc", "atom/browser/osr/osr_output_device.cc",
"atom/browser/osr/osr_output_device.h", "atom/browser/osr/osr_output_device.h",
"atom/browser/osr/osr_render_widget_host_view.cc", "atom/browser/osr/osr_render_widget_host_view.cc",

View file

@ -470,9 +470,9 @@ WebContents::~WebContents() {
RenderViewDeleted(web_contents()->GetRenderViewHost()); RenderViewDeleted(web_contents()->GetRenderViewHost());
if (type_ == WEB_VIEW) { if (type_ == WEB_VIEW) {
DCHECK(!web_contents()->GetOuterWebContents())
<< "Should never manually destroy an attached webview";
// For webview simply destroy the WebContents immediately. // For webview simply destroy the WebContents immediately.
// TODO(zcbenz): Add an internal API for webview instead of using
// destroy(), so we don't have to add a special branch here.
DestroyWebContents(false /* async */); DestroyWebContents(false /* async */);
} else if (type_ == BROWSER_WINDOW && owner_window()) { } else if (type_ == BROWSER_WINDOW && owner_window()) {
// For BrowserWindow we should close the window and clean up everything // For BrowserWindow we should close the window and clean up everything
@ -2150,6 +2150,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
.SetMethod("startDrag", &WebContents::StartDrag) .SetMethod("startDrag", &WebContents::StartDrag)
.SetMethod("isGuest", &WebContents::IsGuest) .SetMethod("isGuest", &WebContents::IsGuest)
.SetMethod("attachToIframe", &WebContents::AttachToIframe) .SetMethod("attachToIframe", &WebContents::AttachToIframe)
.SetMethod("detachFromOuterFrame", &WebContents::DetachFromOuterFrame)
.SetMethod("isOffscreen", &WebContents::IsOffScreen) .SetMethod("isOffscreen", &WebContents::IsOffScreen)
#if BUILDFLAG(ENABLE_OSR) #if BUILDFLAG(ENABLE_OSR)
.SetMethod("startPainting", &WebContents::StartPainting) .SetMethod("startPainting", &WebContents::StartPainting)

View file

@ -242,6 +242,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
bool IsGuest() const; bool IsGuest() const;
void AttachToIframe(content::WebContents* embedder_web_contents, void AttachToIframe(content::WebContents* embedder_web_contents,
int embedder_frame_id); int embedder_frame_id);
void DetachFromOuterFrame();
// Methods for offscreen rendering // Methods for offscreen rendering
bool IsOffScreen() const; bool IsOffScreen() const;

View file

@ -4,9 +4,12 @@
#include "atom/browser/api/atom_api_web_contents.h" #include "atom/browser/api/atom_api_web_contents.h"
#include "content/browser/web_contents/web_contents_impl.h"
#if BUILDFLAG(ENABLE_OSR)
#include "atom/browser/osr/osr_render_widget_host_view.h" #include "atom/browser/osr/osr_render_widget_host_view.h"
#include "atom/browser/osr/osr_web_contents_view.h" #include "atom/browser/osr/osr_web_contents_view.h"
#include "content/browser/web_contents/web_contents_impl.h" #endif
// Including both web_contents_impl.h and node.h would introduce a error, we // Including both web_contents_impl.h and node.h would introduce a error, we
// have to isolate the usage of WebContentsImpl into a clean file to fix it: // have to isolate the usage of WebContentsImpl into a clean file to fix it:
@ -16,6 +19,13 @@ namespace atom {
namespace api { namespace api {
void WebContents::DetachFromOuterFrame() {
// See detach_webview_frame.patch on how to detach.
auto* impl = static_cast<content::WebContentsImpl*>(web_contents());
impl->GetRenderManagerForTesting()->RemoveOuterDelegateFrame();
}
#if BUILDFLAG(ENABLE_OSR)
OffScreenWebContentsView* WebContents::GetOffScreenWebContentsView() const { OffScreenWebContentsView* WebContents::GetOffScreenWebContentsView() const {
if (IsOffScreen()) { if (IsOffScreen()) {
const auto* impl = const auto* impl =
@ -35,6 +45,7 @@ OffScreenRenderWidgetHostView* WebContents::GetOffScreenRenderWidgetHostView()
return nullptr; return nullptr;
} }
} }
#endif
} // namespace api } // namespace api

View file

@ -177,6 +177,7 @@ filenames = {
"atom/browser/api/atom_api_view.h", "atom/browser/api/atom_api_view.h",
"atom/browser/api/atom_api_web_contents.cc", "atom/browser/api/atom_api_web_contents.cc",
"atom/browser/api/atom_api_web_contents.h", "atom/browser/api/atom_api_web_contents.h",
"atom/browser/api/atom_api_web_contents_impl.cc",
"atom/browser/api/atom_api_web_contents_mac.mm", "atom/browser/api/atom_api_web_contents_mac.mm",
"atom/browser/api/atom_api_web_contents_view.cc", "atom/browser/api/atom_api_web_contents_view.cc",
"atom/browser/api/atom_api_web_contents_view.h", "atom/browser/api/atom_api_web_contents_view.h",

View file

@ -181,7 +181,7 @@ const attachGuest = function (event, embedderFrameId, elementInstanceId, guestIn
const oldGuestInstance = guestInstances[oldGuestInstanceId] const oldGuestInstance = guestInstances[oldGuestInstanceId]
if (oldGuestInstance) { if (oldGuestInstance) {
oldGuestInstance.guest.destroy() oldGuestInstance.guest.detachFromOuterFrame()
} }
} }
@ -360,7 +360,7 @@ handleMessage('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST_SYNC', function (event,
handleMessage('ELECTRON_GUEST_VIEW_MANAGER_DESTROY_GUEST', function (event, guestInstanceId) { handleMessage('ELECTRON_GUEST_VIEW_MANAGER_DESTROY_GUEST', function (event, guestInstanceId) {
try { try {
const guest = getGuestForWebContents(guestInstanceId, event.sender) const guest = getGuestForWebContents(guestInstanceId, event.sender)
guest.destroy() guest.detachFromOuterFrame()
} catch (error) { } catch (error) {
console.error(`Guest destroy failed: ${error}`) console.error(`Guest destroy failed: ${error}`)
} }

View file

@ -9,6 +9,8 @@ This is part of the fixes for https://github.com/electron/electron/issues/14211.
We should revisit this bug after upgrading to newer versions of Chrome, We should revisit this bug after upgrading to newer versions of Chrome,
this patch was introduced in Chrome 66. this patch was introduced in Chrome 66.
Update(zcbenz): The bug is still in Chrome 72.
diff --git a/content/browser/frame_host/render_frame_proxy_host.cc b/content/browser/frame_host/render_frame_proxy_host.cc diff --git a/content/browser/frame_host/render_frame_proxy_host.cc b/content/browser/frame_host/render_frame_proxy_host.cc
index cfa3fd15714c3743cb9d2900b35570c94545fa87..80785902890c57ffae2fa841831d3bd60a8fa11a 100644 index cfa3fd15714c3743cb9d2900b35570c94545fa87..80785902890c57ffae2fa841831d3bd60a8fa11a 100644
--- a/content/browser/frame_host/render_frame_proxy_host.cc --- a/content/browser/frame_host/render_frame_proxy_host.cc