Browse Source

fix: crash when creating interface for speculative frame (#34294)

Co-authored-by: samuelmaddock <[email protected]>
trop[bot] 2 years ago
parent
commit
c2a11cef63

+ 1 - 1
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() {

+ 19 - 14
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<mojom::ElectronRenderer>& 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<content::RenderFrameHost*> 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");
 }

+ 3 - 2
shell/browser/api/electron_api_web_frame_main.h

@@ -82,6 +82,9 @@ class WebFrameMain : public gin::Wrappable<WebFrameMain>,
   void UpdateRenderFrameHost(content::RenderFrameHost* rfh);
 
   const mojo::Remote<mojom::ElectronRenderer>& 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<WebFrameMain>,
   std::vector<content::RenderFrameHost*> Frames() const;
   std::vector<content::RenderFrameHost*> FramesInSubtree() const;
 
-  void OnRendererConnectionError();
-  void Connect();
   void DOMContentLoaded();
 
   mojo::Remote<mojom::ElectronRenderer> renderer_api_;