From 5ff94e7f2becc435e4e7c66e112686461b74e95b Mon Sep 17 00:00:00 2001 From: Samuel Maddock Date: Thu, 19 May 2022 14:34:58 -0400 Subject: [PATCH] fix: crash when creating interface for speculative frame (#33919) --- .../browser/api/electron_api_web_contents.cc | 2 +- .../api/electron_api_web_frame_main.cc | 41 +++++++++++-------- .../browser/api/electron_api_web_frame_main.h | 5 ++- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/shell/browser/api/electron_api_web_contents.cc b/shell/browser/api/electron_api_web_contents.cc index 60a8a5846d..639f20eda2 100644 --- a/shell/browser/api/electron_api_web_contents.cc +++ b/shell/browser/api/electron_api_web_contents.cc @@ -1505,7 +1505,7 @@ void WebContents::HandleNewRenderFrame( auto* web_frame = WebFrameMain::FromRenderFrameHost(render_frame_host); if (web_frame) - web_frame->Connect(); + web_frame->MaybeSetupMojoConnection(); } void WebContents::OnBackgroundColorChanged() { diff --git a/shell/browser/api/electron_api_web_frame_main.cc b/shell/browser/api/electron_api_web_frame_main.cc index d39943e4d6..f8bc7c9efc 100644 --- a/shell/browser/api/electron_api_web_frame_main.cc +++ b/shell/browser/api/electron_api_web_frame_main.cc @@ -96,13 +96,15 @@ void WebFrameMain::Destroyed() { void WebFrameMain::MarkRenderFrameDisposed() { render_frame_ = nullptr; render_frame_disposed_ = true; + TeardownMojoConnection(); } void WebFrameMain::UpdateRenderFrameHost(content::RenderFrameHost* rfh) { // Should only be called when swapping frames. render_frame_disposed_ = false; render_frame_ = rfh; - renderer_api_.reset(); + TeardownMojoConnection(); + MaybeSetupMojoConnection(); } bool WebFrameMain::CheckRenderFrame() const { @@ -181,20 +183,30 @@ void WebFrameMain::Send(v8::Isolate* isolate, } const mojo::Remote& WebFrameMain::GetRendererApi() { - if (!renderer_api_) { - pending_receiver_ = renderer_api_.BindNewPipeAndPassReceiver(); - if (render_frame_->IsRenderFrameCreated()) { - render_frame_->GetRemoteInterfaces()->GetInterface( - std::move(pending_receiver_)); - } - renderer_api_.set_disconnect_handler(base::BindOnce( - &WebFrameMain::OnRendererConnectionError, weak_factory_.GetWeakPtr())); - } + MaybeSetupMojoConnection(); return renderer_api_; } -void WebFrameMain::OnRendererConnectionError() { +void WebFrameMain::MaybeSetupMojoConnection() { + if (!renderer_api_) { + pending_receiver_ = renderer_api_.BindNewPipeAndPassReceiver(); + renderer_api_.set_disconnect_handler(base::BindOnce( + &WebFrameMain::OnRendererConnectionError, weak_factory_.GetWeakPtr())); + } + // Wait for RenderFrame to be created in renderer before accessing remote. + if (pending_receiver_ && render_frame_->IsRenderFrameCreated()) { + render_frame_->GetRemoteInterfaces()->GetInterface( + std::move(pending_receiver_)); + } +} + +void WebFrameMain::TeardownMojoConnection() { renderer_api_.reset(); + pending_receiver_.reset(); +} + +void WebFrameMain::OnRendererConnectionError() { + TeardownMojoConnection(); } void WebFrameMain::PostMessage(v8::Isolate* isolate, @@ -314,13 +326,6 @@ std::vector WebFrameMain::FramesInSubtree() const { return frame_hosts; } -void WebFrameMain::Connect() { - if (pending_receiver_) { - render_frame_->GetRemoteInterfaces()->GetInterface( - std::move(pending_receiver_)); - } -} - void WebFrameMain::DOMContentLoaded() { Emit("dom-ready"); } diff --git a/shell/browser/api/electron_api_web_frame_main.h b/shell/browser/api/electron_api_web_frame_main.h index 23a3b657fd..b45264db59 100644 --- a/shell/browser/api/electron_api_web_frame_main.h +++ b/shell/browser/api/electron_api_web_frame_main.h @@ -82,6 +82,9 @@ class WebFrameMain : public gin::Wrappable, void UpdateRenderFrameHost(content::RenderFrameHost* rfh); const mojo::Remote& GetRendererApi(); + void MaybeSetupMojoConnection(); + void TeardownMojoConnection(); + void OnRendererConnectionError(); // WebFrameMain can outlive its RenderFrameHost pointer so we need to check // whether its been disposed of prior to accessing it. @@ -112,8 +115,6 @@ class WebFrameMain : public gin::Wrappable, std::vector Frames() const; std::vector FramesInSubtree() const; - void OnRendererConnectionError(); - void Connect(); void DOMContentLoaded(); mojo::Remote renderer_api_;