From c2a11cef63ea15a9be32c632d3c87883ee8a7a9d Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Thu, 19 May 2022 15:13:48 -0700 Subject: [PATCH] fix: crash when creating interface for speculative frame (#34294) Co-authored-by: samuelmaddock --- .../browser/api/electron_api_web_contents.cc | 2 +- .../api/electron_api_web_frame_main.cc | 33 +++++++++++-------- .../browser/api/electron_api_web_frame_main.h | 5 +-- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/shell/browser/api/electron_api_web_contents.cc b/shell/browser/api/electron_api_web_contents.cc index caf9cdb41b3ea..5db6744bd7ce1 100644 --- a/shell/browser/api/electron_api_web_contents.cc +++ b/shell/browser/api/electron_api_web_contents.cc @@ -1510,7 +1510,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 e7ba32a33f782..70ae9210aaa85 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 { @@ -182,20 +184,30 @@ void WebFrameMain::Send(v8::Isolate* isolate, } const mojo::Remote& WebFrameMain::GetRendererApi() { + MaybeSetupMojoConnection(); + return renderer_api_; +} + +void WebFrameMain::MaybeSetupMojoConnection() { 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())); } - return renderer_api_; + // 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::OnRendererConnectionError() { +void WebFrameMain::TeardownMojoConnection() { renderer_api_.reset(); + pending_receiver_.reset(); +} + +void WebFrameMain::OnRendererConnectionError() { + TeardownMojoConnection(); } void WebFrameMain::PostMessage(v8::Isolate* isolate, @@ -315,13 +327,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 23a3b657fd45c..b45264db59627 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_;