[MPArch] Add GetVirtualAuthenticatorManager in RFHO

This CL is a part of the effort to split RFH and FTN.
This CL adds GetVirtualAuthenticatorManager method in
RenderFrameHostOwner not to reference FrameTreeNode directly
in RenderFrameHostImpl.

Cq-Include-Trybots: luci.chromium.try:linux-wpt-identity-fyi-rel

Bug: 1350570
Change-Id: Ib018d60525f8de5d6c668ea40cbc26086a1b945f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4160123
Reviewed-by: Nina Satragno <nsatragno@chromium.org>
Reviewed-by: Kevin McNee <mcnee@chromium.org>
Reviewed-by: Arthur Sonzogni <arthursonzogni@chromium.org>
Commit-Queue: Miyoung Shin <myid.shin@igalia.com>
Cr-Commit-Position: refs/heads/main@{#1097228}
diff --git a/content/browser/renderer_host/frame_tree_node.cc b/content/browser/renderer_host/frame_tree_node.cc
index 852f86ac..436c82d6 100644
--- a/content/browser/renderer_host/frame_tree_node.cc
+++ b/content/browser/renderer_host/frame_tree_node.cc
@@ -30,6 +30,7 @@
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/browser/web_package/subresource_web_bundle_navigation_info.h"
 #include "content/browser/web_package/web_bundle_navigation_info.h"
+#include "content/browser/webauth/authenticator_environment_impl.h"
 #include "content/common/navigation_params_utils.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/site_isolation_policy.h"
@@ -1076,4 +1077,16 @@
   return attributes_->credentialless;
 }
 
+#if !BUILDFLAG(IS_ANDROID)
+void FrameTreeNode::GetVirtualAuthenticatorManager(
+    mojo::PendingReceiver<blink::test::mojom::VirtualAuthenticatorManager>
+        receiver) {
+  auto* environment_singleton = AuthenticatorEnvironmentImpl::GetInstance();
+  environment_singleton->EnableVirtualAuthenticatorFor(this,
+                                                       /*enable_ui=*/false);
+  environment_singleton->AddVirtualAuthenticatorReceiver(this,
+                                                         std::move(receiver));
+}
+#endif  // !BUILDFLAG(IS_ANDROID)
+
 }  // namespace content
diff --git a/content/browser/renderer_host/frame_tree_node.h b/content/browser/renderer_host/frame_tree_node.h
index 6940679..acd986f2 100644
--- a/content/browser/renderer_host/frame_tree_node.h
+++ b/content/browser/renderer_host/frame_tree_node.h
@@ -31,6 +31,7 @@
 #include "third_party/blink/public/mojom/frame/frame_replication_state.mojom-forward.h"
 #include "third_party/blink/public/mojom/frame/tree_scope_type.mojom.h"
 #include "third_party/blink/public/mojom/frame/user_activation_update_types.mojom-forward.h"
+#include "third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom-forward.h"
 
 #include "base/time/time.h"
 #include "url/gurl.h"
@@ -636,6 +637,11 @@
       int http_response_code) override;
   void CancelNavigation() override;
   bool Credentialless() const override;
+#if !BUILDFLAG(IS_ANDROID)
+  void GetVirtualAuthenticatorManager(
+      mojo::PendingReceiver<blink::test::mojom::VirtualAuthenticatorManager>
+          receiver) override;
+#endif
 
  private:
   friend class CSPEmbeddedEnforcementUnitTest;
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 8f6481b..43b6e4d 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -143,7 +143,6 @@
 #include "content/browser/web_package/web_bundle_handle_tracker.h"
 #include "content/browser/web_package/web_bundle_navigation_info.h"
 #include "content/browser/web_package/web_bundle_source.h"
-#include "content/browser/webauth/authenticator_environment_impl.h"
 #include "content/browser/webauth/authenticator_impl.h"
 #include "content/browser/webauth/webauth_request_security_checker.h"
 #include "content/browser/webid/federated_auth_request_impl.h"
@@ -11056,13 +11055,17 @@
     mojo::PendingReceiver<blink::test::mojom::VirtualAuthenticatorManager>
         receiver) {
 #if !BUILDFLAG(IS_ANDROID)
+  // VirtualAuthenticatorManagerImpl is enabled at the frame level. Inactive
+  // document are detached. They don't have a frame anymore, so they can't be
+  // used to enable this test-only feature.
+  if (!IsActive()) {
+    return;
+  }
+
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kEnableWebAuthDeprecatedMojoTestingApi)) {
-    auto* environment_singleton = AuthenticatorEnvironmentImpl::GetInstance();
-    environment_singleton->EnableVirtualAuthenticatorFor(frame_tree_node_,
-                                                         /*enable_ui=*/false);
-    environment_singleton->AddVirtualAuthenticatorReceiver(frame_tree_node_,
-                                                           std::move(receiver));
+    CHECK(owner_);
+    owner_->GetVirtualAuthenticatorManager(std::move(receiver));
   }
 #endif  // !BUILDFLAG(IS_ANDROID)
 }
diff --git a/content/browser/renderer_host/render_frame_host_impl_unittest.cc b/content/browser/renderer_host/render_frame_host_impl_unittest.cc
index d24d362..edf6121 100644
--- a/content/browser/renderer_host/render_frame_host_impl_unittest.cc
+++ b/content/browser/renderer_host/render_frame_host_impl_unittest.cc
@@ -38,6 +38,12 @@
 #include "content/public/browser/authenticator_request_client_delegate.h"
 #endif  // BUIDLFLAG(IS_ANDROID)
 
+#if !BUILDFLAG(IS_ANDROID)
+#include "content/browser/webauth/authenticator_environment_impl.h"
+#include "content/public/common/content_switches.h"
+#include "third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom.h"
+#endif
+
 namespace content {
 
 class RenderFrameHostImplTest : public RenderViewHostImplTestHarness {
@@ -930,4 +936,51 @@
   }
 }
 
+#if !BUILDFLAG(IS_ANDROID)
+TEST_F(RenderFrameHostImplTest, GetVirtualAuthenticatorManagerWhenInactiveRFH) {
+  base::CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kEnableWebAuthDeprecatedMojoTestingApi);
+
+  // Create a page with an iframe:
+  contents()->NavigateAndCommit(GURL("https://initial.example.test/"));
+
+  RenderFrameHostImpl* parent_rfh = main_test_rfh();
+  RenderFrameHostImpl* child_rfh = static_cast<RenderFrameHostImpl*>(
+      NavigationSimulator::NavigateAndCommitFromDocument(
+          GURL("https://childframe.com"),
+          RenderFrameHostTester::For(parent_rfh)->AppendChild("child")));
+  EXPECT_TRUE(child_rfh->IsActive());
+
+  // The active child document should enable VirtualAuthenticator.
+  {
+    mojo::Remote<blink::test::mojom::VirtualAuthenticatorManager> remote;
+    child_rfh->GetVirtualAuthenticatorManager(
+        remote.BindNewPipeAndPassReceiver());
+    EXPECT_TRUE(AuthenticatorEnvironmentImpl::GetInstance()
+                    ->IsVirtualAuthenticatorEnabledFor(
+                        contents()->GetPrimaryFrameTree().root()->child_at(0)));
+  }
+
+  // Navigate to another page, causing the two RenderFrameHost to become
+  // inactive.
+  RenderFrameDeletedObserver parent_rfh_deleted(parent_rfh);
+  auto navigation = NavigationSimulatorImpl::CreateBrowserInitiated(
+      GURL("https://final.example.test/"), contents());
+  navigation->set_drop_unload_ack(true);
+  navigation->Commit();
+  ASSERT_FALSE(parent_rfh_deleted.deleted());
+  EXPECT_FALSE(parent_rfh->IsActive());
+
+  // The inactive document should not enable VirtualAuthenticator.
+  {
+    mojo::Remote<blink::test::mojom::VirtualAuthenticatorManager> remote;
+    child_rfh->GetVirtualAuthenticatorManager(
+        remote.BindNewPipeAndPassReceiver());
+    EXPECT_FALSE(AuthenticatorEnvironmentImpl::GetInstance()
+                     ->IsVirtualAuthenticatorEnabledFor(
+                         contents()->GetPrimaryFrameTree().root()));
+  }
+}
+#endif
+
 }  // namespace content
diff --git a/content/browser/renderer_host/render_frame_host_owner.h b/content/browser/renderer_host/render_frame_host_owner.h
index 8dea3744..b32494e 100644
--- a/content/browser/renderer_host/render_frame_host_owner.h
+++ b/content/browser/renderer_host/render_frame_host_owner.h
@@ -8,11 +8,17 @@
 #include <memory>
 #include <vector>
 
+#include "build/build_config.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "services/network/public/mojom/referrer_policy.mojom-forward.h"
 #include "third_party/blink/public/mojom/frame/user_activation_update_types.mojom-forward.h"
 #include "third_party/blink/public/mojom/loader/referrer.mojom-forward.h"
 #include "ui/base/page_transition_types.h"
 
+#if !BUILDFLAG(IS_ANDROID)
+#include "third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom-forward.h"
+#endif
+
 class GURL;
 
 namespace net {
@@ -124,6 +130,12 @@
 
   // Return the iframe.credentialless attribute value.
   virtual bool Credentialless() const = 0;
+
+#if !BUILDFLAG(IS_ANDROID)
+  virtual void GetVirtualAuthenticatorManager(
+      mojo::PendingReceiver<blink::test::mojom::VirtualAuthenticatorManager>
+          receiver) = 0;
+#endif
 };
 
 }  // namespace content