[Payments][Desktop] Fix potential use-after-free of render_frame_host.

PaymentRequest gets a RenderFrameHost* in its constructor that is later
used when PaymentRequest::Init() is triggered asynchronously by mojo.
This can lead to a use-after-free.

This CL converts the RenderFrameHost* to its GlobalFrameRoutingID
in the PaymentRequest constructor, when it is guaranteed to be live.
If the RenderFrameHost is freed when PaymentRequest::Init() is called,
the RenderFrameHost::FromID() will return nullptr, and the rest of the
code can handle it appropriately.

The real fix is to change all RenderFrameHost* to WeakPtr. This is tracked
in crbug.com/1058840.

Bug: 1072772
Change-Id: I2c7b54aeea67aa39fd11248d35faecbf8c771594
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2186396
Commit-Queue: Danyao Wang <[email protected]>
Reviewed-by: Rouslan Solomakhin <[email protected]>
Cr-Commit-Position: refs/heads/master@{#766641}
diff --git a/components/payments/content/payment_request.cc b/components/payments/content/payment_request.cc
index a55904d1..dd5ee3b 100644
--- a/components/payments/content/payment_request.cc
+++ b/components/payments/content/payment_request.cc
@@ -35,6 +35,7 @@
 #include "components/url_formatter/elide_url.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/origin_util.h"
@@ -78,7 +79,11 @@
     mojo::PendingReceiver<mojom::PaymentRequest> receiver,
     ObserverForTest* observer_for_testing)
     : web_contents_(web_contents),
-      initiator_render_frame_host_(render_frame_host),
+      // TODO(crbug.com/1058840): change to WeakPtr<RenderFrameHost> once
+      // RenderFrameHost provides a WeakPtr API.
+      initiator_frame_routing_id_(content::GlobalFrameRoutingId(
+          render_frame_host->GetProcess()->GetID(),
+          render_frame_host->GetRoutingID())),
       log_(web_contents_),
       delegate_(std::move(delegate)),
       manager_(manager),
@@ -164,12 +169,22 @@
     return;
   }
 
+  // TODO(crbug.com/1058840): change to WeakPtr<RenderFrameHost> once
+  // RenderFrameHost provides a WeakPtr API.
+  content::RenderFrameHost* initiator_frame =
+      content::RenderFrameHost::FromID(initiator_frame_routing_id_);
+  if (!initiator_frame) {
+    log_.Error(errors::kInvalidInitiatorFrame);
+    OnConnectionTerminated();
+    return;
+  }
+
   spec_ = std::make_unique<PaymentRequestSpec>(
       std::move(options), std::move(details), std::move(method_data),
       /*observer=*/this, delegate_->GetApplicationLocale());
   state_ = std::make_unique<PaymentRequestState>(
-      web_contents_, initiator_render_frame_host_, top_level_origin_,
-      frame_origin_, frame_security_origin_, spec_.get(),
+      web_contents_, initiator_frame, top_level_origin_, frame_origin_,
+      frame_security_origin_, spec_.get(),
       /*delegate=*/this, delegate_->GetApplicationLocale(),
       delegate_->GetPersonalDataManager(), delegate_.get(),
       base::BindRepeating(&PaymentRequest::SetInvokedServiceWorkerIdentity,