[PassGroup] Bridge to call the java UI

The CL introduces the bridge to call the java UI to display the grouped
credential acknowledgement sheet.

Bug: 372635361
Change-Id: I338d989e3a21dd4f45f2d6024d0aba7a40207a42
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5940567
Commit-Queue: Anna Tsvirchkova <atsvirchkova@google.com>
Reviewed-by: Ioana Pandele <ioanap@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1371364}
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 9753aa5..91c8069 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -422,6 +422,7 @@
       "//chrome/browser/password_manager/android/access_loss:helper_java",
       "//chrome/browser/password_manager/android/account_storage_toggle:java",
       "//chrome/browser/password_manager/android/bottom_sheet:java",
+      "//chrome/browser/password_manager/android/grouped_affiliations:java",
       "//chrome/browser/password_manager/android/pwd_migration:java",
       "//chrome/browser/password_manager/android/pwd_migration:java_resources",
       "//chrome/browser/policy/android:java",
diff --git a/chrome/browser/password_manager/android/grouped_affiliations/BUILD.gn b/chrome/browser/password_manager/android/grouped_affiliations/BUILD.gn
index f16d96a..b1c6914 100644
--- a/chrome/browser/password_manager/android/grouped_affiliations/BUILD.gn
+++ b/chrome/browser/password_manager/android/grouped_affiliations/BUILD.gn
@@ -3,14 +3,39 @@
 # found in the LICENSE file.
 
 import("//build/config/android/rules.gni")
+import("//third_party/jni_zero/jni_zero.gni")
 
 # Public API.
 static_library("public") {
   sources = [
+    "acknowledge_grouped_credential_sheet_bridge.cc",
+    "acknowledge_grouped_credential_sheet_bridge.h",
     "acknowledge_grouped_credential_sheet_controller.cc",
     "acknowledge_grouped_credential_sheet_controller.h",
   ]
-  deps = [ "//base" ]
+  deps = [
+    ":jni_headers",
+    "//base",
+    "//content/public/browser",
+    "//ui/android:android",
+  ]
+}
+
+generate_jni("jni_headers") {
+  sources = [ "java/src/org/chromium/chrome/browser/grouped_affiliations/AcknowledgeGroupedCredentialSheetBridge.java" ]
+}
+
+android_library("java") {
+  srcjar_deps = [ ":jni_headers" ]
+  sources = [ "java/src/org/chromium/chrome/browser/grouped_affiliations/AcknowledgeGroupedCredentialSheetBridge.java" ]
+
+  deps = [
+    "//base:base_java",
+    "//build/android:build_java",
+    "//third_party/androidx:androidx_annotation_annotation_java",
+    "//third_party/jni_zero:jni_zero_java",
+    "//ui/android:ui_no_recycler_view_java",
+  ]
 }
 
 source_set("unit_tests") {
diff --git a/chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_bridge.cc b/chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_bridge.cc
new file mode 100644
index 0000000..317fa5e
--- /dev/null
+++ b/chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_bridge.cc
@@ -0,0 +1,85 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_bridge.h"
+
+#include <memory>
+
+#include "base/android/jni_android.h"
+#include "base/functional/callback_forward.h"
+#include "ui/android/window_android.h"
+
+// Must come after all headers that specialize FromJniType() / ToJniType().
+#include "chrome/browser/password_manager/android/grouped_affiliations/jni_headers/AcknowledgeGroupedCredentialSheetBridge_jni.h"
+
+namespace {
+
+using JniDelegate = AcknowledgeGroupedCredentialSheetBridge::JniDelegate;
+
+class JniDelegateImpl : public JniDelegate {
+ public:
+  JniDelegateImpl() = default;
+  JniDelegateImpl(const JniDelegateImpl&) = delete;
+  JniDelegateImpl& operator=(const JniDelegateImpl&) = delete;
+  ~JniDelegateImpl() override = default;
+
+  void Create(const gfx::NativeWindow window_android,
+              AcknowledgeGroupedCredentialSheetBridge* bridge) override {
+    if (!window_android) {
+      return;
+    }
+
+    java_bridge_.Reset(Java_AcknowledgeGroupedCredentialSheetBridge_Constructor(
+        base::android::AttachCurrentThread(),
+        reinterpret_cast<intptr_t>(bridge), window_android->GetJavaObject()));
+  }
+
+  void Show() override {
+    Java_AcknowledgeGroupedCredentialSheetBridge_show(
+        base::android::AttachCurrentThread(), java_bridge_);
+  }
+
+  void Dismiss() override {
+    Java_AcknowledgeGroupedCredentialSheetBridge_dismiss(
+        base::android::AttachCurrentThread(), java_bridge_);
+  }
+
+ private:
+  // The corresponding Java GroupedCredentialAcknowledgeSheetBridge.
+  base::android::ScopedJavaGlobalRef<jobject> java_bridge_;
+};
+}  // namespace
+
+AcknowledgeGroupedCredentialSheetBridge::JniDelegate::JniDelegate() = default;
+AcknowledgeGroupedCredentialSheetBridge::JniDelegate::~JniDelegate() = default;
+
+AcknowledgeGroupedCredentialSheetBridge::
+    AcknowledgeGroupedCredentialSheetBridge(const gfx::NativeWindow window)
+    : jni_delegate_(std::make_unique<JniDelegateImpl>()) {
+  jni_delegate_->Create(window, this);
+}
+
+AcknowledgeGroupedCredentialSheetBridge::
+    AcknowledgeGroupedCredentialSheetBridge(
+        base::PassKey<class TouchToFillControllerAutofillTest>,
+        std::unique_ptr<JniDelegate> jni_delegate)
+    : jni_delegate_(std::move(jni_delegate)) {}
+
+AcknowledgeGroupedCredentialSheetBridge::
+    AcknowledgeGroupedCredentialSheetBridge(
+        base::PassKey<class AcknowledgeGroupedCredentialSheetControllerTest>,
+        std::unique_ptr<JniDelegate> jni_delegate)
+    : jni_delegate_(std::move(jni_delegate)) {}
+
+AcknowledgeGroupedCredentialSheetBridge::
+    ~AcknowledgeGroupedCredentialSheetBridge() {
+  jni_delegate_->Dismiss();
+}
+
+void AcknowledgeGroupedCredentialSheetBridge::Show(
+    base::OnceCallback<void(bool)> closure_callback) {
+  closure_callback_ = std::move(closure_callback);
+
+  jni_delegate_->Show();
+}
diff --git a/chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_bridge.h b/chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_bridge.h
new file mode 100644
index 0000000..eb17f80
--- /dev/null
+++ b/chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_bridge.h
@@ -0,0 +1,52 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PASSWORD_MANAGER_ANDROID_GROUPED_AFFILIATIONS_ACKNOWLEDGE_GROUPED_CREDENTIAL_SHEET_BRIDGE_H_
+#define CHROME_BROWSER_PASSWORD_MANAGER_ANDROID_GROUPED_AFFILIATIONS_ACKNOWLEDGE_GROUPED_CREDENTIAL_SHEET_BRIDGE_H_
+
+#include "base/functional/callback_helpers.h"
+#include "base/types/pass_key.h"
+#include "ui/gfx/native_widget_types.h"
+
+// JNI bridge to display the acknowledgement sheet when filling grouped
+// credentials on Android.
+class AcknowledgeGroupedCredentialSheetBridge {
+ public:
+  class JniDelegate {
+   public:
+    JniDelegate();
+    JniDelegate(const JniDelegate&) = delete;
+    JniDelegate& operator=(const JniDelegate&) = delete;
+    virtual ~JniDelegate() = 0;
+
+    virtual void Create(const gfx::NativeWindow window_android,
+                        AcknowledgeGroupedCredentialSheetBridge* bridge) = 0;
+    virtual void Show() = 0;
+    virtual void Dismiss() = 0;
+  };
+  explicit AcknowledgeGroupedCredentialSheetBridge(
+      const gfx::NativeWindow window);
+  // Test constructors
+  AcknowledgeGroupedCredentialSheetBridge(
+      base::PassKey<class TouchToFillControllerAutofillTest>,
+      std::unique_ptr<JniDelegate> jni_delegate);
+  AcknowledgeGroupedCredentialSheetBridge(
+      base::PassKey<class AcknowledgeGroupedCredentialSheetControllerTest>,
+      std::unique_ptr<JniDelegate> jni_delegate);
+
+  AcknowledgeGroupedCredentialSheetBridge(
+      const AcknowledgeGroupedCredentialSheetBridge&) = delete;
+  AcknowledgeGroupedCredentialSheetBridge& operator=(
+      const AcknowledgeGroupedCredentialSheetBridge&) = delete;
+
+  ~AcknowledgeGroupedCredentialSheetBridge();
+
+  void Show(base::OnceCallback<void(bool)> closure_callback);
+
+ private:
+  base::OnceCallback<void(bool)> closure_callback_;
+  std::unique_ptr<JniDelegate> jni_delegate_;
+};
+
+#endif  // CHROME_BROWSER_PASSWORD_MANAGER_ANDROID_GROUPED_AFFILIATIONS_ACKNOWLEDGE_GROUPED_CREDENTIAL_SHEET_BRIDGE_H_
diff --git a/chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_controller.cc b/chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_controller.cc
index a043dab0f..5d1da91 100644
--- a/chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_controller.cc
+++ b/chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_controller.cc
@@ -5,15 +5,14 @@
 #include "chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_controller.h"
 
 AcknowledgeGroupedCredentialSheetController::
-    AcknowledgeGroupedCredentialSheetController() = default;
+    AcknowledgeGroupedCredentialSheetController(
+        std::unique_ptr<AcknowledgeGroupedCredentialSheetBridge> bridge)
+    : bridge_(std::move(bridge)) {}
 
 AcknowledgeGroupedCredentialSheetController::
     ~AcknowledgeGroupedCredentialSheetController() = default;
 
 void AcknowledgeGroupedCredentialSheetController::ShowAcknowledgeSheet(
     base::OnceCallback<void(bool)> on_close_callback) {
-  // TODO (crbug.com/372635361): Implement actually showing the sheet. For now
-  // just run the callback as if the sheet was shown and canceled by the user.
-  on_close_callback_ = std::move(on_close_callback);
-  std::move(on_close_callback_).Run(false);
+  bridge_->Show(std::move(on_close_callback));
 }
diff --git a/chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_controller.h b/chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_controller.h
index 9e0c46d..a8b279b 100644
--- a/chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_controller.h
+++ b/chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_controller.h
@@ -7,6 +7,7 @@
 
 #include "base/functional/callback_forward.h"
 #include "base/functional/callback_helpers.h"
+#include "chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_bridge.h"
 
 // Displays the UI to ask for user verification before filling credential, that
 // was originally saved for a web site or app grouped with current web site. If
@@ -14,7 +15,8 @@
 // the current web site.
 class AcknowledgeGroupedCredentialSheetController {
  public:
-  AcknowledgeGroupedCredentialSheetController();
+  explicit AcknowledgeGroupedCredentialSheetController(
+      std::unique_ptr<AcknowledgeGroupedCredentialSheetBridge> bridge);
   AcknowledgeGroupedCredentialSheetController(
       const AcknowledgeGroupedCredentialSheetController&) = delete;
   AcknowledgeGroupedCredentialSheetController& operator=(
@@ -26,6 +28,8 @@
 
  private:
   base::OnceCallback<void(bool)> on_close_callback_ = base::NullCallback();
+
+  std::unique_ptr<AcknowledgeGroupedCredentialSheetBridge> bridge_;
 };
 
 #endif  // CHROME_BROWSER_PASSWORD_MANAGER_ANDROID_GROUPED_AFFILIATIONS_ACKNOWLEDGE_GROUPED_CREDENTIAL_SHEET_CONTROLLER_H_
diff --git a/chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_controller_unittest.cc b/chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_controller_unittest.cc
index 225078f..d18f86d2 100644
--- a/chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_controller_unittest.cc
+++ b/chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_controller_unittest.cc
@@ -7,26 +7,55 @@
 #include <memory>
 
 #include "base/functional/callback_helpers.h"
+#include "base/memory/raw_ptr.h"
 #include "base/test/mock_callback.h"
+#include "chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_bridge.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-class GroupedCredentialAcknowledgeSheetControllerTest : public testing::Test {
+namespace {
+class MockJniDelegate
+    : public AcknowledgeGroupedCredentialSheetBridge::JniDelegate {
  public:
+  MockJniDelegate() = default;
+  ~MockJniDelegate() override = default;
+
+  MOCK_METHOD((void),
+              Create,
+              (const gfx::NativeWindow,
+               AcknowledgeGroupedCredentialSheetBridge*),
+              (override));
+  MOCK_METHOD((void), Show, (), (override));
+  MOCK_METHOD((void), Dismiss, (), (override));
+};
+}  // namespace
+
+class AcknowledgeGroupedCredentialSheetControllerTest : public testing::Test {
+ public:
+  AcknowledgeGroupedCredentialSheetControllerTest() {
+    auto mock_jni_bridge = std::make_unique<MockJniDelegate>();
+    mock_jni_bridge_ = mock_jni_bridge.get();
+    controller_ = std::make_unique<AcknowledgeGroupedCredentialSheetController>(
+        std::make_unique<AcknowledgeGroupedCredentialSheetBridge>(
+            base::PassKey<
+                class AcknowledgeGroupedCredentialSheetControllerTest>(),
+            std::move(mock_jni_bridge)));
+  }
   AcknowledgeGroupedCredentialSheetController* GetController() {
     return controller_.get();
   }
 
+  MockJniDelegate* mock_jni_bridge() { return mock_jni_bridge_; }
+
  private:
-  std::unique_ptr<AcknowledgeGroupedCredentialSheetController> controller_ =
-      std::make_unique<AcknowledgeGroupedCredentialSheetController>();
+  std::unique_ptr<AcknowledgeGroupedCredentialSheetController> controller_;
+  raw_ptr<MockJniDelegate> mock_jni_bridge_;
 };
 
-TEST_F(GroupedCredentialAcknowledgeSheetControllerTest,
-       ShowAcknowledgeSheetDeclined) {
+TEST_F(AcknowledgeGroupedCredentialSheetControllerTest, ShowAcknowledgeSheet) {
   // TODO(crbug.com/372635361): After implementing the bridge, expect the call
   // to show the actual sheet. Now only checks that the callback is called.
   base::MockCallback<base::OnceCallback<void(bool)>> mock_reply;
-  EXPECT_CALL(mock_reply, Run(false));
+  EXPECT_CALL(*mock_jni_bridge(), Show);
   GetController()->ShowAcknowledgeSheet(mock_reply.Get());
 }
diff --git a/chrome/browser/password_manager/android/grouped_affiliations/java/src/org/chromium/chrome/browser/grouped_affiliations/AcknowledgeGroupedCredentialSheetBridge.java b/chrome/browser/password_manager/android/grouped_affiliations/java/src/org/chromium/chrome/browser/grouped_affiliations/AcknowledgeGroupedCredentialSheetBridge.java
new file mode 100644
index 0000000..788795adb
--- /dev/null
+++ b/chrome/browser/password_manager/android/grouped_affiliations/java/src/org/chromium/chrome/browser/grouped_affiliations/AcknowledgeGroupedCredentialSheetBridge.java
@@ -0,0 +1,29 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.grouped_affiliations;
+
+import androidx.annotation.NonNull;
+
+import org.jni_zero.CalledByNative;
+
+import org.chromium.ui.base.WindowAndroid;
+
+// JNI bridge to display the acknowledgement sheet when filling grouped
+// credentials on Android.
+public class AcknowledgeGroupedCredentialSheetBridge {
+    @CalledByNative
+    public AcknowledgeGroupedCredentialSheetBridge(
+            long nativeAddUsernameDialogBridge, @NonNull WindowAndroid windowAndroid) {}
+
+    @CalledByNative
+    public void show() {
+        // TODO(crbug.com/372635361): Implement.
+    }
+
+    @CalledByNative
+    public void dismiss() {
+        // TODO(crbug.com/372635361): Implement.
+    }
+}
diff --git a/chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_autofill_delegate.cc b/chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_autofill_delegate.cc
index 537c93ac..a541ad6 100644
--- a/chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_autofill_delegate.cc
+++ b/chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_autofill_delegate.cc
@@ -14,6 +14,7 @@
 #include "base/ranges/algorithm.h"
 #include "base/types/pass_key.h"
 #include "chrome/browser/password_manager/android/access_loss/password_access_loss_warning_bridge_impl.h"
+#include "chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_bridge.h"
 #include "chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_controller.h"
 #include "chrome/browser/password_manager/android/local_passwords_migration_warning_util.h"
 #include "chrome/browser/password_manager/chrome_password_manager_client.h"
@@ -47,8 +48,12 @@
 }
 
 std::unique_ptr<AcknowledgeGroupedCredentialSheetController>
-CreateAcknowledgeGroupedCredentialSheetController() {
-  return std::make_unique<AcknowledgeGroupedCredentialSheetController>();
+CreateAcknowledgeGroupedCredentialSheetController(
+    content::WebContents* web_contents) {
+  auto bridge = std::make_unique<AcknowledgeGroupedCredentialSheetBridge>(
+      web_contents->GetTopLevelNativeWindow());
+  return std::make_unique<AcknowledgeGroupedCredentialSheetController>(
+      std::move(bridge));
 }
 
 }  // namespace
@@ -109,7 +114,7 @@
       access_loss_warning_bridge_(
           std::make_unique<PasswordAccessLossWarningBridgeImpl>()),
       grouped_credential_sheet_controller_(
-          CreateAcknowledgeGroupedCredentialSheetController()),
+          CreateAcknowledgeGroupedCredentialSheetController(web_contents_)),
       source_id_(password_client->web_contents()
                      ->GetPrimaryMainFrame()
                      ->GetPageUkmSourceId()) {}
@@ -329,6 +334,12 @@
         [](TouchToFillControllerAutofillDelegate* delegate,
            const UiCredential& credential, bool accepted) {
           if (!accepted) {
+            // TODO(crbug.com/372635361): Introduce new bucket to report grouped
+            // credential filling metric.
+            delegate->CleanUpFillerAndReportOutcome(
+                TouchToFillOutcome::kSheetDismissed,
+                /*show_virtual_keyboard=*/false);
+            std::move(delegate->action_complete_).Run();
             return;
           }
           delegate->FillCredential(credential);
diff --git a/chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_autofill_delegate.h b/chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_autofill_delegate.h
index 86380719..96d1070b 100644
--- a/chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_autofill_delegate.h
+++ b/chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_autofill_delegate.h
@@ -14,6 +14,7 @@
 #include "base/types/pass_key.h"
 #include "base/types/strong_alias.h"
 #include "chrome/browser/password_manager/android/access_loss/password_access_loss_warning_bridge.h"
+#include "chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_bridge.h"
 #include "chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_controller.h"
 #include "chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_delegate.h"
 #include "components/autofill/core/common/unique_ids.h"
diff --git a/chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_autofill_delegate_unittest.cc b/chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_autofill_delegate_unittest.cc
index 38b983f4a..bbf0c4a 100644
--- a/chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_autofill_delegate_unittest.cc
+++ b/chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_autofill_delegate_unittest.cc
@@ -19,6 +19,7 @@
 #include "base/time/time.h"
 #include "base/types/pass_key.h"
 #include "chrome/browser/password_manager/android/access_loss/mock_password_access_loss_warning_bridge.h"
+#include "chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_bridge.h"
 #include "chrome/browser/password_manager/android/grouped_affiliations/acknowledge_grouped_credential_sheet_controller.h"
 #include "chrome/browser/password_manager/android/password_manager_launcher_android.h"
 #include "chrome/browser/password_manager/chrome_password_manager_client.h"
@@ -105,6 +106,21 @@
   MOCK_METHOD(void, OnDismiss, ());
 };
 
+class MockAckGroupedCredentialJniDelegate
+    : public AcknowledgeGroupedCredentialSheetBridge::JniDelegate {
+ public:
+  MockAckGroupedCredentialJniDelegate() = default;
+  ~MockAckGroupedCredentialJniDelegate() override = default;
+
+  MOCK_METHOD((void),
+              Create,
+              (const gfx::NativeWindow,
+               AcknowledgeGroupedCredentialSheetBridge*),
+              (override));
+  MOCK_METHOD((void), Show, (), (override));
+  MOCK_METHOD((void), Dismiss, (), (override));
+};
+
 struct MakeUiCredentialParams {
   std::string_view username;
   std::string_view password;
@@ -194,10 +210,15 @@
     std::unique_ptr<MockPasswordAccessLossWarningBridge> mock_bridge =
         std::make_unique<MockPasswordAccessLossWarningBridge>();
     mock_access_loss_warning_bridge_ = mock_bridge.get();
+
+    auto mock_jni_bridge =
+        std::make_unique<MockAckGroupedCredentialJniDelegate>();
+    grouped_credential_sheet_bridge_ = mock_jni_bridge.get();
     auto grouped_credential_sheet_controller =
-        std::make_unique<AcknowledgeGroupedCredentialSheetController>();
-    grouped_credential_sheet_controller_ =
-        grouped_credential_sheet_controller.get();
+        std::make_unique<AcknowledgeGroupedCredentialSheetController>(
+            std::make_unique<AcknowledgeGroupedCredentialSheetBridge>(
+                base::PassKey<class TouchToFillControllerAutofillTest>(),
+                std::move(mock_jni_bridge)));
     return std::make_unique<TouchToFillControllerAutofillDelegate>(
         base::PassKey<TouchToFillControllerAutofillTest>(), &client_,
         web_contents(), std::move(authenticator_),
@@ -229,9 +250,8 @@
     return mock_access_loss_warning_bridge_;
   }
 
-  AcknowledgeGroupedCredentialSheetController*
-  grouped_credential_sheet_controller() {
-    return grouped_credential_sheet_controller_;
+  MockAckGroupedCredentialJniDelegate* grouped_credential_sheet_bridge() {
+    return grouped_credential_sheet_bridge_;
   }
 
   void SetUp() override {
@@ -269,8 +289,7 @@
   raw_ptr<MockPasswordAccessLossWarningBridge> mock_access_loss_warning_bridge_;
   raw_ptr<MockPasswordCredentialFiller> weak_filler_;
   password_manager::PasswordForm form_to_fill_;
-  raw_ptr<AcknowledgeGroupedCredentialSheetController>
-      grouped_credential_sheet_controller_;
+  raw_ptr<MockAckGroupedCredentialJniDelegate> grouped_credential_sheet_bridge_;
 };
 
 TEST_F(TouchToFillControllerAutofillTest, Show_Fill_And_Submit) {
@@ -970,11 +989,8 @@
           TouchToFillControllerAutofillDelegate::ShowHybridOption(false)),
       /*cred_man_delegate=*/nullptr, /*frame_driver=*/nullptr);
 
-  // TODO(crbug.com/372635361): After implementing the bridge, expect the call
-  // to show the actual sheet. Now only check, that FillUsernameAndPassword will
-  // not be called because there is a stub, which simulates that sheet was
-  // declined.
   EXPECT_CALL(*last_mock_filler(), FillUsernameAndPassword).Times(0);
+  EXPECT_CALL(*grouped_credential_sheet_bridge(), Show);
   ON_CALL(client(), IsReauthBeforeFillingRequired).WillByDefault(Return(false));
   touch_to_fill_controller().OnCredentialSelected(credentials[0]);
 }