diff --git a/shell/browser/api/electron_api_web_contents.cc b/shell/browser/api/electron_api_web_contents.cc index cf2eb42d9cc41..56e10ef9f3317 100644 --- a/shell/browser/api/electron_api_web_contents.cc +++ b/shell/browser/api/electron_api_web_contents.cc @@ -943,18 +943,31 @@ WebContents::~WebContents() { // InspectableWebContents will be automatically destroyed. } +void WebContents::DeleteThisIfAlive() { + // It is possible that the FirstWeakCallback has been called but the + // SecondWeakCallback has not, in this case the garbage collection of + // WebContents has already started and we should not |delete this|. + // Calling |GetWrapper| can detect this corner case. + auto* isolate = JavascriptEnvironment::GetIsolate(); + v8::HandleScope scope(isolate); + v8::Local wrapper; + if (!GetWrapper(isolate).ToLocal(&wrapper)) + return; + delete this; +} + void WebContents::Destroy() { // The content::WebContents should be destroyed asyncronously when possible // as user may choose to destroy WebContents during an event of it. if (Browser::Get()->is_shutting_down() || IsGuest() || type_ == Type::kBrowserView) { - delete this; + DeleteThisIfAlive(); } else { base::PostTask(FROM_HERE, {content::BrowserThread::UI}, base::BindOnce( [](base::WeakPtr contents) { if (contents) - delete contents.get(); + contents->DeleteThisIfAlive(); }, GetWeakPtr())); } diff --git a/shell/browser/api/electron_api_web_contents.h b/shell/browser/api/electron_api_web_contents.h index 9e6e92d4bfb33..8fbb27d3fd8ea 100644 --- a/shell/browser/api/electron_api_web_contents.h +++ b/shell/browser/api/electron_api_web_contents.h @@ -432,6 +432,9 @@ class WebContents : public gin::Wrappable, WebContents(v8::Isolate* isolate, const gin_helper::Dictionary& options); ~WebContents() override; + // Delete this if garbage collection has not started. + void DeleteThisIfAlive(); + // Creates a InspectableWebContents object and takes ownership of // |web_contents|. void InitWithWebContents(content::WebContents* web_contents,