Determine cross-origin password reuse based on PasswordForm::url

This change adds url property to MatchingReusedCredential structure which corresponds to PasswordForm::url.

Before: PasswordForm::signon_realm was cast to GURL and passed to
GetRegistryControlledDomain().

Now: PasswordForm::url is used and passed to
GetRegistryControlledDomain().

Bug: 368517711
Fixed: 40895227
Change-Id: I1a18739135350117603dbe4c9d17bb13e9b16ea3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5891506
Reviewed-by: Sylvain Defresne <sdefresne@chromium.org>
Commit-Queue: Viktor Semeniuk <vsemeniuk@google.com>
Reviewed-by: Vasilii Sukhanov <vasilii@chromium.org>
Reviewed-by: Daniel Rubery <drubery@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1367331}
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service_browsertest.cc b/chrome/browser/safe_browsing/chrome_password_protection_service_browsertest.cc
index 6de68c7..672ca7b 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service_browsertest.cc
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service_browsertest.cc
@@ -414,7 +414,7 @@
   AddFormToStore(password_store.get(), form);
 
   std::vector<password_manager::MatchingReusedCredential> credentials = {
-      {kSignonRealm, kUsername}};
+      {kSignonRealm, GURL(kSignonRealm), kUsername}};
 
   service->set_saved_passwords_matching_reused_credentials({credentials});
 
@@ -916,7 +916,7 @@
     const std::string kSignonRealm = "https://example.test";
     const std::u16string kUsername = u"username1";
     std::vector<password_manager::MatchingReusedCredential> credentials = {
-        {kSignonRealm, kUsername}};
+        {kSignonRealm, GURL(kSignonRealm), kUsername}};
 
     service->StartRequestForTesting(
         GetWebContents(), GURL(), GURL(), GURL(), "",
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc b/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
index be6452b1..c301944 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
@@ -399,8 +399,9 @@
 
   void InitializeRequest(LoginReputationClientRequest::TriggerType trigger_type,
                          PasswordType reused_password_type) {
-    std::vector<password_manager::MatchingReusedCredential> credentials = {
-        {"somedomain.com"}};
+    std::vector<MatchingReusedCredential> credentials;
+    credentials.emplace_back("somedomain.com", GURL("https://somedomain.com/"),
+                             u"user");
     if (trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE) {
       request_ = new PasswordProtectionRequestContent(
           web_contents(), GURL(kPhishingURL), GURL(), GURL(),
@@ -680,8 +681,11 @@
        VerifyPersistPhishedSavedPasswordCredential) {
   service_->ConfigService(/*is_incognito=*/false,
                           /*is_extended_reporting=*/true);
-  std::vector<password_manager::MatchingReusedCredential> credentials = {
-      {"http://example.test"}, {"http://2.example.com"}};
+  std::vector<password_manager::MatchingReusedCredential> credentials;
+  credentials.emplace_back("http://example.test", GURL("http://example.test/"),
+                           u"user");
+  credentials.emplace_back("http://2.example.com",
+                           GURL("http://example2.test/"), u"user");
 
   EXPECT_CALL(mock_add_callback_, Run(password_store_.get(), credentials[0]));
   EXPECT_CALL(mock_add_callback_, Run(password_store_.get(), credentials[1]));
@@ -692,9 +696,11 @@
        VerifyRemovePhishedSavedPasswordCredential) {
   service_->ConfigService(/*is_incognito=*/false,
                           /*is_extended_reporting=*/true);
-  std::vector<password_manager::MatchingReusedCredential> credentials = {
-      {"http://example.test", u"username1"},
-      {"http://2.example.test", u"username2"}};
+  std::vector<password_manager::MatchingReusedCredential> credentials;
+  credentials.emplace_back("http://example.test", GURL("http://example.test/"),
+                           u"user");
+  credentials.emplace_back("http://2.example.com",
+                           GURL("http://example2.test/"), u"user");
 
   EXPECT_CALL(mock_remove_callback_,
               Run(password_store_.get(), credentials[0]));
@@ -1672,11 +1678,13 @@
        VerifyPersistPhishedSavedPasswordCredential) {
   service_->ConfigService(/*is_incognito=*/false,
                           /*is_extended_reporting=*/true);
-  std::vector<password_manager::MatchingReusedCredential> credentials = {
-      {.signon_realm = "http://example.test",
-       .in_store = password_manager::PasswordForm::Store::kAccountStore},
-      {.signon_realm = "http://2.example.test",
-       .in_store = password_manager::PasswordForm::Store::kAccountStore}};
+  std::vector<password_manager::MatchingReusedCredential> credentials;
+  credentials.emplace_back(
+      "http://example.test", GURL("http://example.test/"), u"user",
+      password_manager::PasswordForm::Store::kAccountStore);
+  credentials.emplace_back(
+      "http://2.example.com", GURL("http://example2.test/"), u"user",
+      password_manager::PasswordForm::Store::kAccountStore);
 
   EXPECT_CALL(mock_add_callback_,
               Run(account_password_store_.get(), credentials[0]));
@@ -1689,11 +1697,13 @@
        VerifyRemovePhishedSavedPasswordCredential) {
   service_->ConfigService(/*is_incognito=*/false,
                           /*is_extended_reporting=*/true);
-  std::vector<password_manager::MatchingReusedCredential> credentials = {
-      {"http://example.test", u"username1",
-       password_manager::PasswordForm::Store::kAccountStore},
-      {"http://2.example.test", u"username2",
-       password_manager::PasswordForm::Store::kAccountStore}};
+  std::vector<password_manager::MatchingReusedCredential> credentials;
+  credentials.emplace_back(
+      "http://example.test", GURL("http://example.test/"), u"user",
+      password_manager::PasswordForm::Store::kAccountStore);
+  credentials.emplace_back(
+      "http://2.example.com", GURL("http://example2.test/"), u"user",
+      password_manager::PasswordForm::Store::kAccountStore);
 
   EXPECT_CALL(mock_remove_callback_,
               Run(account_password_store_.get(), credentials[0]));
@@ -1752,9 +1762,10 @@
        VerifyPhishGuardDialogOpensPasswordCheckupForAccountStoreSyncing) {
   service_->ConfigService(/*is_incognito=*/false,
                           /*is_extended_reporting=*/true);
-  std::vector<password_manager::MatchingReusedCredential> credentials = {
-      {"http://example.test", u"username",
-       password_manager::PasswordForm::Store::kAccountStore}};
+  std::vector<password_manager::MatchingReusedCredential> credentials;
+  credentials.emplace_back(
+      "http://example.test", GURL("http://example.test/"), u"user",
+      password_manager::PasswordForm::Store::kAccountStore);
   service_->set_saved_passwords_matching_reused_credentials(credentials);
 
   SetUpSyncService(/*is_syncing_passwords=*/true);
@@ -1773,9 +1784,11 @@
        VerifyPhishGuardDialogOpensPasswordCheckupForProfileStoreSyncing) {
   service_->ConfigService(/*is_incognito=*/false,
                           /*is_extended_reporting=*/true);
-  std::vector<password_manager::MatchingReusedCredential> credentials = {
-      {"http://example.test", u"username",
-       password_manager::PasswordForm::Store::kProfileStore}};
+  std::vector<password_manager::MatchingReusedCredential> credentials;
+  credentials.emplace_back(
+      "http://example.test", GURL("http://example.test/"), u"user",
+      password_manager::PasswordForm::Store::kProfileStore);
+
   service_->set_saved_passwords_matching_reused_credentials(credentials);
 
   SetUpSyncService(/*is_syncing_passwords=*/true);
@@ -1794,9 +1807,11 @@
        VerifyPhishGuardDialogOpensPasswordCheckupForProfileStoreNotSyncing) {
   service_->ConfigService(/*is_incognito=*/false,
                           /*is_extended_reporting=*/true);
-  std::vector<password_manager::MatchingReusedCredential> credentials = {
-      {"http://example.test", u"username",
-       password_manager::PasswordForm::Store::kProfileStore}};
+  std::vector<password_manager::MatchingReusedCredential> credentials;
+  credentials.emplace_back(
+      "http://example.test", GURL("http://example.test/"), u"user",
+      password_manager::PasswordForm::Store::kProfileStore);
+
   service_->set_saved_passwords_matching_reused_credentials(credentials);
 
   SetUpSyncService(/*is_syncing_passwords=*/false);
@@ -1815,11 +1830,14 @@
        VerifyPhishGuardDialogOpensSafetyCheckMenuForBothStoresSyncing) {
   service_->ConfigService(/*is_incognito=*/false,
                           /*is_extended_reporting=*/true);
-  std::vector<password_manager::MatchingReusedCredential> credentials = {
-      {"http://example.test", u"username",
-       password_manager::PasswordForm::Store::kProfileStore},
-      {"http://2.example.test", u"username",
-       password_manager::PasswordForm::Store::kAccountStore}};
+  std::vector<password_manager::MatchingReusedCredential> credentials;
+  credentials.emplace_back(
+      "http://example.test", GURL("http://example.test/"), u"user",
+      password_manager::PasswordForm::Store::kAccountStore);
+  credentials.emplace_back(
+      "http://2.example.test", GURL("http://example.test/"), u"user",
+      password_manager::PasswordForm::Store::kProfileStore);
+
   service_->set_saved_passwords_matching_reused_credentials(credentials);
 
   SetUpSyncService(/*is_syncing_passwords=*/true);
@@ -1845,9 +1863,10 @@
     VerifyPhishGuardDialogOpensPasswordCheckupEmptyAccountForNonSyncingUser) {
   service_->ConfigService(/*is_incognito=*/false,
                           /*is_extended_reporting=*/true);
-  std::vector<password_manager::MatchingReusedCredential> credentials = {
-      {"http://example.test", u"username",
-       password_manager::PasswordForm::Store::kProfileStore}};
+  std::vector<password_manager::MatchingReusedCredential> credentials;
+  credentials.emplace_back(
+      "http://example.test", GURL("http://example.test/"), u"user",
+      password_manager::PasswordForm::Store::kProfileStore);
   service_->set_saved_passwords_matching_reused_credentials(credentials);
 
   SetUpSyncService(/*is_syncing_passwords=*/false);
@@ -1866,9 +1885,11 @@
        VerifyPhishGuardDialogOpensPasswordCheckupWithAnAccountForSyncingUser) {
   service_->ConfigService(/*is_incognito=*/false,
                           /*is_extended_reporting=*/true);
-  std::vector<password_manager::MatchingReusedCredential> credentials = {
-      {"http://example.test", u"username",
-       password_manager::PasswordForm::Store::kProfileStore}};
+  std::vector<password_manager::MatchingReusedCredential> credentials;
+  credentials.emplace_back(
+      "http://example.test", GURL("http://example.test/"), u"user",
+      password_manager::PasswordForm::Store::kProfileStore);
+
   service_->set_saved_passwords_matching_reused_credentials(credentials);
 
   SetUpSyncService(/*is_syncing_passwords=*/true);
diff --git a/chrome/browser/safe_browsing/chrome_password_reuse_detection_manager_client.cc b/chrome/browser/safe_browsing/chrome_password_reuse_detection_manager_client.cc
index e0b94504..c720bf9 100644
--- a/chrome/browser/safe_browsing/chrome_password_reuse_detection_manager_client.cc
+++ b/chrome/browser/safe_browsing/chrome_password_reuse_detection_manager_client.cc
@@ -71,10 +71,8 @@
         matching_reused_credentials) {
   base::flat_set<std::string> matching_domains;
   for (const auto& credential : matching_reused_credentials) {
-    // TODO(crbug.com/40895227): Avoid converting signon_realm to URL,
-    // ideally use PasswordForm::url.
     std::string domain = base::UTF16ToUTF8(url_formatter::FormatUrl(
-        GURL(credential.signon_realm),
+        credential.url,
         url_formatter::kFormatUrlOmitDefaults |
             url_formatter::kFormatUrlOmitHTTPS |
             url_formatter::kFormatUrlOmitTrivialSubdomains |
diff --git a/chrome/browser/safe_browsing/chrome_password_reuse_detection_manager_client_unittest.cc b/chrome/browser/safe_browsing/chrome_password_reuse_detection_manager_client_unittest.cc
index 01e68c9f..7c686881 100644
--- a/chrome/browser/safe_browsing/chrome_password_reuse_detection_manager_client_unittest.cc
+++ b/chrome/browser/safe_browsing/chrome_password_reuse_detection_manager_client_unittest.cc
@@ -163,7 +163,7 @@
       MaybeStartProtectedPasswordEntryRequest(_, _, "username", _, _, true))
       .Times(4);
   std::vector<password_manager::MatchingReusedCredential> credentials = {
-      {"saved_domain.com", u"username"}};
+      {"saved_domain.com", GURL("https://saved_domain.com/"), u"username"}};
 
   client->CheckProtectedPasswordEntry(
       password_manager::metrics_util::PasswordType::SAVED_PASSWORD, "username",
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn
index 434cf83..ac36d55 100644
--- a/components/password_manager/core/browser/BUILD.gn
+++ b/components/password_manager/core/browser/BUILD.gn
@@ -127,6 +127,7 @@
     "password_manual_fallback_metrics_recorder.h",
     "password_requirements_service.cc",
     "password_requirements_service.h",
+    "password_reuse_detector.cc",
     "password_reuse_detector.h",
     "password_reuse_detector_consumer.cc",
     "password_reuse_detector_consumer.h",
diff --git a/components/password_manager/core/browser/insecure_credentials_helper.cc b/components/password_manager/core/browser/insecure_credentials_helper.cc
index 87a0b55..69b1a4a 100644
--- a/components/password_manager/core/browser/insecure_credentials_helper.cc
+++ b/components/password_manager/core/browser/insecure_credentials_helper.cc
@@ -59,8 +59,7 @@
 void InsecureCredentialsHelper::AddPhishedCredentials(
     const MatchingReusedCredential& credential) {
   PasswordFormDigest digest = {PasswordForm::Scheme::kHtml,
-                               credential.signon_realm,
-                               GURL(credential.signon_realm)};
+                               credential.signon_realm, credential.url};
   operation_ =
       base::BindOnce(&InsecureCredentialsHelper::AddPhishedCredentialsInternal,
                      base::Owned(this), credential);
@@ -70,8 +69,7 @@
 void InsecureCredentialsHelper::RemovePhishedCredentials(
     const MatchingReusedCredential& credential) {
   PasswordFormDigest digest = {PasswordForm::Scheme::kHtml,
-                               credential.signon_realm,
-                               GURL(credential.signon_realm)};
+                               credential.signon_realm, credential.url};
   operation_ = base::BindOnce(
       &InsecureCredentialsHelper::RemovePhishedCredentialsInternal,
       base::Owned(this), credential);
diff --git a/components/password_manager/core/browser/insecure_credentials_helper_unittest.cc b/components/password_manager/core/browser/insecure_credentials_helper_unittest.cc
index a5d85913..6bb3f8b7 100644
--- a/components/password_manager/core/browser/insecure_credentials_helper_unittest.cc
+++ b/components/password_manager/core/browser/insecure_credentials_helper_unittest.cc
@@ -27,16 +27,16 @@
                         std::u16string_view password = std::u16string_view()) {
   PasswordForm form;
   form.signon_realm = std::string(signon_realm);
+  form.url = GURL(signon_realm);
   form.username_value = std::u16string(username);
   form.password_value = std::u16string(password);
   return form;
 }
 
-MatchingReusedCredential MakeCredential(std::string_view signon_realm,
+MatchingReusedCredential MakeCredential(const std::string& signon_realm,
                                         std::u16string_view username) {
-  MatchingReusedCredential credential;
-  credential.signon_realm = std::string(signon_realm);
-  credential.username = std::u16string(username);
+  MatchingReusedCredential credential(signon_realm, GURL(signon_realm),
+                                      std::u16string(username));
   return credential;
 }
 
diff --git a/components/password_manager/core/browser/password_reuse_detector.cc b/components/password_manager/core/browser/password_reuse_detector.cc
new file mode 100644
index 0000000..fbb8bce4
--- /dev/null
+++ b/components/password_manager/core/browser/password_reuse_detector.cc
@@ -0,0 +1,34 @@
+// 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 "components/password_manager/core/browser/password_reuse_detector.h"
+
+namespace password_manager {
+
+MatchingReusedCredential::MatchingReusedCredential(std::string signon_realm,
+                                                   GURL url,
+                                                   std::u16string username,
+                                                   PasswordForm::Store in_store)
+    : signon_realm(std::move(signon_realm)),
+      url(std::move(url)),
+      username(std::move(username)),
+      in_store(in_store) {}
+
+MatchingReusedCredential::MatchingReusedCredential(const PasswordForm& form)
+    : MatchingReusedCredential(form.signon_realm,
+                               form.url,
+                               form.username_value,
+                               form.in_store) {}
+MatchingReusedCredential::MatchingReusedCredential(
+    const MatchingReusedCredential& other) = default;
+MatchingReusedCredential::MatchingReusedCredential(
+    MatchingReusedCredential&& other) = default;
+MatchingReusedCredential::~MatchingReusedCredential() = default;
+
+MatchingReusedCredential& MatchingReusedCredential::operator=(
+    MatchingReusedCredential& other) = default;
+MatchingReusedCredential& MatchingReusedCredential::operator=(
+    MatchingReusedCredential&&) = default;
+
+}  // namespace password_manager
diff --git a/components/password_manager/core/browser/password_reuse_detector.h b/components/password_manager/core/browser/password_reuse_detector.h
index 0a5be41..89b7c64 100644
--- a/components/password_manager/core/browser/password_reuse_detector.h
+++ b/components/password_manager/core/browser/password_reuse_detector.h
@@ -36,15 +36,28 @@
 // Container for the signon_realm and username that a compromised saved password
 // is saved on/with.
 struct MatchingReusedCredential {
+  MatchingReusedCredential(
+      std::string signon_realm,
+      GURL url,
+      std::u16string username,
+      PasswordForm::Store in_store = PasswordForm::Store::kNotSet);
+  explicit MatchingReusedCredential(const PasswordForm& form);
+  MatchingReusedCredential(const MatchingReusedCredential& other);
+  MatchingReusedCredential(MatchingReusedCredential&& other);
+  ~MatchingReusedCredential();
+
   friend auto operator<=>(const MatchingReusedCredential&,
                           const MatchingReusedCredential&) = default;
   friend bool operator==(const MatchingReusedCredential&,
                          const MatchingReusedCredential&) = default;
+  MatchingReusedCredential& operator=(MatchingReusedCredential& other);
+  MatchingReusedCredential& operator=(MatchingReusedCredential&&);
 
   std::string signon_realm;
+  GURL url;
   std::u16string username;
   // The store in which those credentials are stored.
-  PasswordForm::Store in_store = PasswordForm::Store::kNotSet;
+  PasswordForm::Store in_store;
 };
 
 // Per-profile class responsible for detection of password reuse, i.e. that the
diff --git a/components/password_manager/core/browser/password_reuse_detector_impl.cc b/components/password_manager/core/browser/password_reuse_detector_impl.cc
index bd20ea7..b81f01d 100644
--- a/components/password_manager/core/browser/password_reuse_detector_impl.cc
+++ b/components/password_manager/core/browser/password_reuse_detector_impl.cc
@@ -248,14 +248,13 @@
         passwords_iterator->second;
     DCHECK(!credentials.empty());
 
-    std::set<std::string> signon_realms;
+    std::set<std::string> domains;
     for (const auto& credential : credentials) {
-      signon_realms.insert(
-          GetRegistryControlledDomain(GURL(credential.signon_realm)));
+      domains.insert(GetRegistryControlledDomain(credential.url));
     }
     // If the page's URL matches a saved domain for this password,
     // this isn't password-reuse.
-    if (base::Contains(signon_realms, registry_controlled_domain)) {
+    if (base::Contains(domains, registry_controlled_domain)) {
       continue;
     }
 
@@ -268,9 +267,13 @@
     }
   }
 
-  matching_reused_credentials_out->assign(
-      matching_reused_credentials_set.begin(),
-      matching_reused_credentials_set.end());
+  matching_reused_credentials_out->reserve(
+      matching_reused_credentials_set.size());
+  for (auto it = matching_reused_credentials_set.begin();
+       it != matching_reused_credentials_set.end();) {
+    matching_reused_credentials_out->push_back(
+        std::move(matching_reused_credentials_set.extract(it++).value()));
+  }
 
   return reused_saved_password;
 }
@@ -348,7 +351,7 @@
   }
 
   passwords_with_matching_reused_credentials_[form.password_value].insert(
-      {form.signon_realm, form.username_value, form.in_store});
+      MatchingReusedCredential(form));
 }
 
 void PasswordReuseDetectorImpl::RemovePassword(const PasswordForm& form) {
@@ -357,8 +360,7 @@
     return;
   }
 
-  MatchingReusedCredential credential_criteria = {
-      form.signon_realm, form.username_value, form.in_store};
+  MatchingReusedCredential credential_criteria(form);
   auto password_value_iter =
       passwords_with_matching_reused_credentials_.begin();
   while (password_value_iter !=
diff --git a/components/password_manager/core/browser/password_reuse_detector_impl_unittest.cc b/components/password_manager/core/browser/password_reuse_detector_impl_unittest.cc
index fefa20b..c84567b 100644
--- a/components/password_manager/core/browser/password_reuse_detector_impl_unittest.cc
+++ b/components/password_manager/core/browser/password_reuse_detector_impl_unittest.cc
@@ -24,6 +24,7 @@
 using base::ASCIIToUTF16;
 using testing::_;
 using testing::IsEmpty;
+using testing::UnorderedElementsAre;
 using testing::UnorderedElementsAreArray;
 
 namespace password_manager {
@@ -81,6 +82,7 @@
                                       PasswordForm::Store store) {
   auto form = std::make_unique<PasswordForm>();
   form->signon_realm = domain;
+  form->url = GURL(domain);
   form->password_value = ASCIIToUTF16(password);
   form->username_value = ASCIIToUTF16(username);
   form->in_store = store;
@@ -161,8 +163,8 @@
   testing::Mock::VerifyAndClearExpectations(&mockConsumer);
 
   std::vector<MatchingReusedCredential> credentials = {
-      {"https://accounts.google.com", u"gUsername",
-       PasswordForm::Store::kProfileStore}};
+      {"https://accounts.google.com", GURL("https://accounts.google.com"),
+       u"gUsername", PasswordForm::Store::kProfileStore}};
   EXPECT_CALL(
       mockConsumer,
       OnReuseCheckDone(true, strlen("saved_password"),
@@ -182,10 +184,13 @@
 
   testing::Mock::VerifyAndClearExpectations(&mockConsumer);
 
-  credentials = {{"https://example1.com", u"example1Username",
-                  PasswordForm::Store::kProfileStore},
-                 {"https://example2.com", u"example2Username",
-                  PasswordForm::Store::kProfileStore}};
+  credentials.clear();
+  credentials.emplace_back("https://example1.com", GURL("https://example1.com"),
+                           u"example1Username",
+                           PasswordForm::Store::kProfileStore);
+  credentials.emplace_back("https://example2.com", GURL("https://example2.com"),
+                           u"example2Username",
+                           PasswordForm::Store::kProfileStore);
   EXPECT_CALL(
       mockConsumer,
       OnReuseCheckDone(true, strlen("secretword"),
@@ -213,8 +218,8 @@
   MockPasswordReuseDetectorConsumer mockConsumer;
 
   const std::vector<MatchingReusedCredential> credentials = {
-      {"https://a.appspot.com", u"appspotUsername",
-       PasswordForm::Store::kProfileStore}};
+      {"https://a.appspot.com", GURL("https://a.appspot.com"),
+       u"appspotUsername", PasswordForm::Store::kProfileStore}};
   // a.appspot.com and b.appspot.com are not PSL matches. So reuse event should
   // be raised.
   EXPECT_CALL(
@@ -263,8 +268,8 @@
       EXPECT_CALL(mockConsumer, OnReuseCheckDone(false, _, _, _, _, _, _));
     } else {
       const std::vector<MatchingReusedCredential> credentials = {
-          {"https://accounts.google.com", u"gUsername",
-           PasswordForm::Store::kProfileStore}};
+          {"https://accounts.google.com", GURL("https://accounts.google.com"),
+           u"gUsername", PasswordForm::Store::kProfileStore}};
       EXPECT_CALL(
           mockConsumer,
           OnReuseCheckDone(true, strlen("saved_password"),
@@ -287,8 +292,8 @@
 
   const std::vector<MatchingReusedCredential>
       expected_matching_reused_credentials = {
-          {"https://accounts.google.com", u"gUsername",
-           PasswordForm::Store::kProfileStore}};
+          {"https://accounts.google.com", GURL("https://accounts.google.com"),
+           u"gUsername", PasswordForm::Store::kProfileStore}};
   MockPasswordReuseDetectorConsumer mockConsumer;
   // One of the passwords in |login_credentials| has less than the minimum
   // requirement of characters in a password so it will not be stored.
@@ -333,11 +338,10 @@
       GetChangeList(PasswordStoreChange::ADD, login_credentials);
   reuse_detector.OnLoginsChanged(add_changes);
 
-  std::vector<MatchingReusedCredential> expected_matching_reused_credentials = {
-      {"https://example1.com", u"example1Username",
-       PasswordForm::Store::kProfileStore},
-      {"https://example2.com", u"example2Username",
-       PasswordForm::Store::kProfileStore}};
+  std::vector<MatchingReusedCredential> expected_matching_reused_credentials;
+  expected_matching_reused_credentials.emplace_back(*login_credentials[0]);
+  expected_matching_reused_credentials.emplace_back(*login_credentials[2]);
+
   MockPasswordReuseDetectorConsumer mockConsumer;
   int valid_passwords = login_credentials.size();
   EXPECT_CALL(
@@ -359,9 +363,9 @@
       PasswordStoreChange::REMOVE,
       GetForms({{"https://example1.com", "example1Username", "secretword"}}));
   reuse_detector.OnLoginsChanged(remove_changes);
-  expected_matching_reused_credentials = {{"https://example2.com",
-                                           u"example2Username",
-                                           PasswordForm::Store::kProfileStore}};
+  expected_matching_reused_credentials.clear();
+  expected_matching_reused_credentials.emplace_back(*login_credentials[2]);
+
   EXPECT_CALL(
       mockConsumer,
       OnReuseCheckDone(
@@ -387,7 +391,7 @@
 }
 
 TEST(PasswordReuseDetectorTest, MatchMultiplePasswords) {
-  // These all have different length passwods so we can check the
+  // These all have different length passwords so we can check the
   // returned length.
   const std::vector<TestData> domain_passwords = {
       {"https://a.com, https://all.com", "aUsername", "34567890"},
@@ -403,13 +407,20 @@
   MockPasswordReuseDetectorConsumer mockConsumer;
 
   std::vector<MatchingReusedCredential> credentials = {
-      {"https://a.com", u"aUsername", PasswordForm::Store::kProfileStore},
-      {"https://all.com", u"aUsername", PasswordForm::Store::kProfileStore},
-      {"https://all.com", u"bUsername", PasswordForm::Store::kProfileStore},
-      {"https://all.com", u"cUsername", PasswordForm::Store::kProfileStore},
-      {"https://b.com", u"bUsername", PasswordForm::Store::kProfileStore},
-      {"https://b2.com", u"bUsername", PasswordForm::Store::kProfileStore},
-      {"https://c.com", u"cUsername", PasswordForm::Store::kProfileStore}};
+      {"https://a.com", GURL("https://a.com"), u"aUsername",
+       PasswordForm::Store::kProfileStore},
+      {"https://all.com", GURL("https://all.com"), u"aUsername",
+       PasswordForm::Store::kProfileStore},
+      {"https://all.com", GURL("https://all.com"), u"bUsername",
+       PasswordForm::Store::kProfileStore},
+      {"https://all.com", GURL("https://all.com"), u"cUsername",
+       PasswordForm::Store::kProfileStore},
+      {"https://b.com", GURL("https://b.com"), u"bUsername",
+       PasswordForm::Store::kProfileStore},
+      {"https://b2.com", GURL("https://b2.com"), u"bUsername",
+       PasswordForm::Store::kProfileStore},
+      {"https://c.com", GURL("https://c.com"), u"cUsername",
+       PasswordForm::Store::kProfileStore}};
   EXPECT_CALL(
       mockConsumer,
       OnReuseCheckDone(true, strlen("01234567890"),
@@ -419,11 +430,15 @@
                             &mockConsumer);
   testing::Mock::VerifyAndClearExpectations(&mockConsumer);
 
-  credentials = {
-      {"https://a.com", u"aUsername", PasswordForm::Store::kProfileStore},
-      {"https://all.com", u"aUsername", PasswordForm::Store::kProfileStore},
-      {"https://all.com", u"cUsername", PasswordForm::Store::kProfileStore},
-      {"https://c.com", u"cUsername", PasswordForm::Store::kProfileStore}};
+  credentials.clear();
+  credentials.emplace_back("https://a.com", GURL("https://a.com"), u"aUsername",
+                           PasswordForm::Store::kProfileStore);
+  credentials.emplace_back("https://all.com", GURL("https://all.com"),
+                           u"aUsername", PasswordForm::Store::kProfileStore);
+  credentials.emplace_back("https://all.com", GURL("https://all.com"),
+                           u"cUsername", PasswordForm::Store::kProfileStore);
+  credentials.emplace_back("https://c.com", GURL("https://c.com"), u"cUsername",
+                           PasswordForm::Store::kProfileStore);
   EXPECT_CALL(
       mockConsumer,
       OnReuseCheckDone(true, strlen("1234567890"),
@@ -551,8 +566,10 @@
   MockPasswordReuseDetectorConsumer mockConsumer;
 
   const std::vector<MatchingReusedCredential> credentials = {
-      {"https://a.com", u"aUsername", PasswordForm::Store::kProfileStore},
-      {"https://b.com", u"bUsername", PasswordForm::Store::kProfileStore}};
+      {"https://a.com", GURL("https://a.com"), u"aUsername",
+       PasswordForm::Store::kProfileStore},
+      {"https://b.com", GURL("https://b.com"), u"bUsername",
+       PasswordForm::Store::kProfileStore}};
   EXPECT_CALL(
       mockConsumer,
       OnReuseCheckDone(true, strlen("01234567890"),
@@ -584,8 +601,8 @@
   reuse_detector.UseGaiaPasswordHash(PrepareGaiaPasswordData({gaia_password}));
 
   const std::vector<MatchingReusedCredential> credentials = {
-      {"https://accounts.google.com", u"gUsername",
-       PasswordForm::Store::kProfileStore}};
+      {"https://accounts.google.com", GURL("https://accounts.google.com"),
+       u"gUsername", PasswordForm::Store::kProfileStore}};
   EXPECT_CALL(
       mockConsumer,
       OnReuseCheckDone(true, strlen("saved_password"),
@@ -601,6 +618,7 @@
 
   auto account_store_form = std::make_unique<PasswordForm>();
   account_store_form->signon_realm = "https://twitter.com";
+  account_store_form->url = GURL(account_store_form->signon_realm);
   account_store_form->username_value = u"twitterUsername";
   account_store_form->password_value = u"saved_password";
   account_store_form->in_store = PasswordForm::Store::kAccountStore;
@@ -612,7 +630,7 @@
   reuse_detector.UseGaiaPasswordHash(PrepareGaiaPasswordData({gaia_password}));
 
   const std::vector<MatchingReusedCredential> credentials = {
-      {"https://twitter.com", u"twitterUsername",
+      {"https://twitter.com", GURL("https://twitter.com"), u"twitterUsername",
        PasswordForm::Store::kAccountStore}};
 
   MockPasswordReuseDetectorConsumer mockConsumer;
@@ -645,8 +663,10 @@
   MockPasswordReuseDetectorConsumer mockConsumer;
 
   const std::vector<MatchingReusedCredential> credentials = {
-      {"https://a.com", u"aUsername", PasswordForm::Store::kProfileStore},
-      {"https://b.com", u"bUsername", PasswordForm::Store::kProfileStore}};
+      {"https://a.com", GURL("https://a.com"), u"aUsername",
+       PasswordForm::Store::kProfileStore},
+      {"https://b.com", GURL("https://b.com"), u"bUsername",
+       PasswordForm::Store::kProfileStore}};
   EXPECT_CALL(
       mockConsumer,
       OnReuseCheckDone(true, strlen("01234567890"),
@@ -680,8 +700,8 @@
       PrepareEnterprisePasswordData({enterprise_password}));
 
   const std::vector<MatchingReusedCredential> credentials = {
-      {"https://accounts.google.com", u"gUsername",
-       PasswordForm::Store::kProfileStore}};
+      {"https://accounts.google.com", GURL("https://accounts.google.com"),
+       u"gUsername", PasswordForm::Store::kProfileStore}};
   EXPECT_CALL(
       mockConsumer,
       OnReuseCheckDone(true, strlen("saved_password"),
@@ -714,8 +734,10 @@
   MockPasswordReuseDetectorConsumer mockConsumer;
 
   const std::vector<MatchingReusedCredential> credentials = {
-      {"https://a.com", u"aUsername", PasswordForm::Store::kProfileStore},
-      {"https://b.com", u"bUsername", PasswordForm::Store::kProfileStore}};
+      {"https://a.com", GURL("https://a.com"), u"aUsername",
+       PasswordForm::Store::kProfileStore},
+      {"https://b.com", GURL("https://b.com"), u"bUsername",
+       PasswordForm::Store::kProfileStore}};
   EXPECT_CALL(
       mockConsumer,
       OnReuseCheckDone(true, strlen("01234567890"),
@@ -775,24 +797,21 @@
   // The credential duplicated in both stores
   PasswordForm account_store_form = *account_credentials[2];
 
+  std::vector<MatchingReusedCredential> expected_credentials;
+  expected_credentials.emplace_back(*profile_credentials[4]);
+  expected_credentials.emplace_back(*profile_credentials[5]);
+  expected_credentials.emplace_back(account_store_form);
+
   reuse_detector.OnGetPasswordStoreResults(std::move(profile_credentials));
   reuse_detector.OnGetPasswordStoreResults(std::move(account_credentials));
 
   MockPasswordReuseDetectorConsumer mockConsumer;
 
-  EXPECT_CALL(
-      mockConsumer,
-      OnReuseCheckDone(
-          /*is_reuse_found=*/true, strlen("secretword"),
-          Matches(NO_GAIA_OR_ENTERPRISE_REUSE),
-          UnorderedElementsAreArray(std::vector<MatchingReusedCredential>{
-              {"https://example1.com", u"example1Username",
-               PasswordForm::Store::kProfileStore},
-              {"https://example2.com", u"example2Username",
-               PasswordForm::Store::kProfileStore},
-              {"https://example2.com", u"example2Username",
-               PasswordForm::Store::kAccountStore}}),
-          /*saved_passwords=*/9, _, _));
+  EXPECT_CALL(mockConsumer, OnReuseCheckDone(
+                                /*is_reuse_found=*/true, strlen("secretword"),
+                                Matches(NO_GAIA_OR_ENTERPRISE_REUSE),
+                                UnorderedElementsAreArray(expected_credentials),
+                                /*saved_passwords=*/9, _, _));
 
   reuse_detector.CheckReuse(u"secretword", "https://evil.com", &mockConsumer);
   testing::Mock::VerifyAndClearExpectations(&mockConsumer);
@@ -802,18 +821,13 @@
   remove_changes.push_back(
       PasswordStoreChange(PasswordStoreChange::REMOVE, account_store_form));
   reuse_detector.OnLoginsChanged(remove_changes);
+  expected_credentials.pop_back();
 
-  EXPECT_CALL(
-      mockConsumer,
-      OnReuseCheckDone(
-          /*is_reuse_found=*/true, strlen("secretword"),
-          Matches(NO_GAIA_OR_ENTERPRISE_REUSE),
-          UnorderedElementsAreArray(std::vector<MatchingReusedCredential>{
-              {"https://example1.com", u"example1Username",
-               PasswordForm::Store::kProfileStore},
-              {"https://example2.com", u"example2Username",
-               PasswordForm::Store::kProfileStore}}),
-          /*saved_passwords=*/8, _, _));
+  EXPECT_CALL(mockConsumer, OnReuseCheckDone(
+                                /*is_reuse_found=*/true, strlen("secretword"),
+                                Matches(NO_GAIA_OR_ENTERPRISE_REUSE),
+                                UnorderedElementsAreArray(expected_credentials),
+                                /*saved_passwords=*/8, _, _));
   reuse_detector.CheckReuse(u"secretword", "https://evil.com", &mockConsumer);
 }
 
@@ -825,41 +839,33 @@
   std::vector<std::unique_ptr<PasswordForm>> account_credentials =
       GetForms(GetTestDomainsPasswordsForAccountStore());
 
+  std::vector<MatchingReusedCredential> expected_credentials;
+  expected_credentials.emplace_back(*profile_credentials[4]);
+  expected_credentials.emplace_back(*profile_credentials[5]);
+  expected_credentials.emplace_back(*account_credentials[2]);
+
   reuse_detector.OnGetPasswordStoreResults(std::move(profile_credentials));
   reuse_detector.OnGetPasswordStoreResults(std::move(account_credentials));
 
   MockPasswordReuseDetectorConsumer mockConsumer;
 
-  EXPECT_CALL(
-      mockConsumer,
-      OnReuseCheckDone(
-          /*is_reuse_found=*/true, strlen("secretword"),
-          Matches(NO_GAIA_OR_ENTERPRISE_REUSE),
-          UnorderedElementsAreArray(std::vector<MatchingReusedCredential>{
-              {"https://example1.com", u"example1Username",
-               PasswordForm::Store::kProfileStore},
-              {"https://example2.com", u"example2Username",
-               PasswordForm::Store::kAccountStore},
-              {"https://example2.com", u"example2Username",
-               PasswordForm::Store::kProfileStore}}),
-          /*saved_passwords=*/9, _, _));
+  EXPECT_CALL(mockConsumer, OnReuseCheckDone(
+                                /*is_reuse_found=*/true, strlen("secretword"),
+                                Matches(NO_GAIA_OR_ENTERPRISE_REUSE),
+                                UnorderedElementsAreArray(expected_credentials),
+                                /*saved_passwords=*/9, _, _));
 
   reuse_detector.CheckReuse(u"secretword", "https://evil.com", &mockConsumer);
   testing::Mock::VerifyAndClearExpectations(&mockConsumer);
 
   reuse_detector.ClearCachedAccountStorePasswords();
+  expected_credentials.pop_back();
 
-  EXPECT_CALL(
-      mockConsumer,
-      OnReuseCheckDone(
-          /*is_reuse_found=*/true, strlen("secretword"),
-          Matches(NO_GAIA_OR_ENTERPRISE_REUSE),
-          UnorderedElementsAreArray(std::vector<MatchingReusedCredential>{
-              {"https://example1.com", u"example1Username",
-               PasswordForm::Store::kProfileStore},
-              {"https://example2.com", u"example2Username",
-               PasswordForm::Store::kProfileStore}}),
-          /*saved_passwords=*/6, _, _));
+  EXPECT_CALL(mockConsumer, OnReuseCheckDone(
+                                /*is_reuse_found=*/true, strlen("secretword"),
+                                Matches(NO_GAIA_OR_ENTERPRISE_REUSE),
+                                UnorderedElementsAreArray(expected_credentials),
+                                /*saved_passwords=*/6, _, _));
   reuse_detector.CheckReuse(u"secretword", "https://evil.com", &mockConsumer);
 }
 
diff --git a/components/password_manager/core/browser/password_reuse_manager_impl.cc b/components/password_manager/core/browser/password_reuse_manager_impl.cc
index d5fda15..a4b969b6 100644
--- a/components/password_manager/core/browser/password_reuse_manager_impl.cc
+++ b/components/password_manager/core/browser/password_reuse_manager_impl.cc
@@ -20,6 +20,7 @@
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_client.h"
 #include "components/password_manager/core/browser/password_manager_util.h"
+#include "components/password_manager/core/browser/password_reuse_detector.h"
 #include "components/password_manager/core/browser/password_reuse_manager_signin_notifier.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "components/prefs/pref_service.h"
diff --git a/components/password_manager/core/browser/password_reuse_manager_impl_unittest.cc b/components/password_manager/core/browser/password_reuse_manager_impl_unittest.cc
index 2796b3b5..df88b1f 100644
--- a/components/password_manager/core/browser/password_reuse_manager_impl_unittest.cc
+++ b/components/password_manager/core/browser/password_reuse_manager_impl_unittest.cc
@@ -31,9 +31,11 @@
 namespace {
 
 using ::testing::_;
+using ::testing::ElementsAre;
 using ::testing::ElementsAreArray;
 using ::testing::IsEmpty;
 using ::testing::Return;
+using ::testing::UnorderedElementsAre;
 using ::testing::UnorderedElementsAreArray;
 
 PasswordForm CreateForm(
@@ -44,6 +46,7 @@
   PasswordForm form;
   form.scheme = PasswordForm::Scheme::kHtml;
   form.signon_realm = std::string(signon_realm);
+  form.url = GURL(signon_realm);
   form.username_value = std::u16string(username);
   form.password_value = std::u16string(password);
   form.url = GURL(signon_realm);
@@ -267,13 +270,11 @@
   for (const auto& test_data : kReuseTestData) {
     MockPasswordReuseDetectorConsumer mock_consumer;
     if (test_data.reused_password_len != 0) {
-      const std::vector<MatchingReusedCredential> credentials = {
-          {"https://www.google.com", u"username1",
-           PasswordForm::Store::kProfileStore}};
-      EXPECT_CALL(mock_consumer,
-                  OnReuseCheckDone(true, test_data.reused_password_len,
-                                   Matches(std::nullopt),
-                                   ElementsAreArray(credentials), 2, _, _));
+      EXPECT_CALL(
+          mock_consumer,
+          OnReuseCheckDone(
+              true, test_data.reused_password_len, Matches(std::nullopt),
+              ElementsAre(MatchingReusedCredential(forms[0])), 2, _, _));
     } else {
       EXPECT_CALL(mock_consumer, OnReuseCheckDone(false, _, _, _, _, _, _));
     }
@@ -536,17 +537,13 @@
   RunUntilIdle();
 
   MockPasswordReuseDetectorConsumer mock_consumer;
-  EXPECT_CALL(
-      mock_consumer,
-      OnReuseCheckDone(
-          /* is_reuse_found=*/true, /*password_length=*/8,
-          Matches(std::nullopt),
-          UnorderedElementsAreArray(std::vector<MatchingReusedCredential>{
-              {"https://www.google.com", u"username1",
-               PasswordForm::Store::kProfileStore},
-              {"https://www.facebook.com", u"username3",
-               PasswordForm::Store::kAccountStore}}),
-          /*saved_passwords=*/3, _, _));
+  EXPECT_CALL(mock_consumer, OnReuseCheckDone(
+                                 /* is_reuse_found=*/true,
+                                 /*password_length=*/8, Matches(std::nullopt),
+                                 UnorderedElementsAre(
+                                     MatchingReusedCredential(profile_forms[0]),
+                                     MatchingReusedCredential(account_form)),
+                                 /*saved_passwords=*/3, _, _));
   reuse_manager()->CheckReuse(u"12345password", "https://evil.com",
                               &mock_consumer);
   RunUntilIdle();
diff --git a/components/safe_browsing/content/browser/password_protection/password_protection_commit_deferring_condition_unittest.cc b/components/safe_browsing/content/browser/password_protection/password_protection_commit_deferring_condition_unittest.cc
index d9abedf..855cd95 100644
--- a/components/safe_browsing/content/browser/password_protection/password_protection_commit_deferring_condition_unittest.cc
+++ b/components/safe_browsing/content/browser/password_protection/password_protection_commit_deferring_condition_unittest.cc
@@ -43,8 +43,11 @@
   void SetUp() override {
     RenderViewHostTestHarness::SetUp();
 
-    std::vector<password_manager::MatchingReusedCredential> credentials = {
-        {"http://example.test"}, {"http://2.example.com"}};
+    std::vector<password_manager::MatchingReusedCredential> credentials;
+    credentials.emplace_back("http://example.test", GURL("http://example.test"),
+                             u"username");
+    credentials.emplace_back("http://2.example.com",
+                             GURL("http://example.test"), u"username2");
 
     request_ = new PasswordProtectionRequestContent(
         RenderViewHostTestHarness::web_contents(), GURL(), GURL(), GURL(),
diff --git a/components/safe_browsing/content/browser/password_protection/password_protection_service_unittest.cc b/components/safe_browsing/content/browser/password_protection/password_protection_service_unittest.cc
index 48ea6b77..837fb46 100644
--- a/components/safe_browsing/content/browser/password_protection/password_protection_service_unittest.cc
+++ b/components/safe_browsing/content/browser/password_protection/password_protection_service_unittest.cc
@@ -556,7 +556,8 @@
     std::unique_ptr<content::WebContents> web_contents = GetWebContents();
     password_protection_service_->StartRequest(
         web_contents.get(), GURL("about:blank"), GURL(), GURL(), kUserName,
-        PasswordType::SAVED_PASSWORD, {{"example.com", u"username"}},
+        PasswordType::SAVED_PASSWORD,
+        {{"example.com", GURL("https://example.com/"), u"username"}},
         LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE, true);
     base::RunLoop().RunUntilIdle();
 
@@ -1160,7 +1161,8 @@
       .WillRepeatedly(Return(account_info));
 
   InitializeAndStartPasswordEntryRequest(
-      PasswordType::OTHER_GAIA_PASSWORD, {{"gmail.com", u"username"}},
+      PasswordType::OTHER_GAIA_PASSWORD,
+      {{"gmail.com", GURL("https://gmail.com/"), u"username"}},
       /*match_allowlist=*/false,
       /*timeout_in_ms=*/10000, web_contents.get());
   password_protection_service_->WaitForResponse();
@@ -1345,9 +1347,9 @@
   // Initialize request triggered by saved password reuse.
   InitializeAndStartPasswordEntryRequest(
       PasswordType::SAVED_PASSWORD,
-      {{kSavedDomain, u"username"},
-       {kSavedDomain2, u"username"},
-       {"http://localhost:8080", u"username"}},
+      {{kSavedDomain, GURL(kSavedDomain), u"username"},
+       {kSavedDomain2, GURL(kSavedDomain2), u"username"},
+       {"http://localhost:8080", GURL("http://localhost:8080"), u"username"}},
       false /* match allowlist */, 100000 /* timeout in ms*/,
       web_contents.get());
   password_protection_service_->WaitForResponse();
@@ -1551,7 +1553,8 @@
       web_contents->GetPrimaryMainFrame());
   password_protection_service_->StartRequest(
       web_contents.get(), GURL("about:blank"), GURL(), GURL(), "username",
-      PasswordType::SAVED_PASSWORD, {{"example1.com", u"username"}},
+      PasswordType::SAVED_PASSWORD,
+      {{"example1.com", GURL("https://example.com/"), u"username"}},
       LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE, true);
   base::RunLoop().RunUntilIdle();
   histograms_.ExpectTotalCount(kPasswordOnFocusRequestOutcomeHistogram, 1);
@@ -1572,7 +1575,8 @@
   std::unique_ptr<content::WebContents> web_contents = GetWebContents();
   password_protection_service_->StartRequest(
       web_contents.get(), GURL("about:blank"), GURL(), GURL(), kUserName,
-      PasswordType::SAVED_PASSWORD, {{"example.com", u"username"}},
+      PasswordType::SAVED_PASSWORD,
+      {{"example.com", GURL("https://example.com/"), u"username"}},
       LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE, true);
   base::RunLoop().RunUntilIdle();
 
@@ -1599,7 +1603,8 @@
       web_contents->GetPrimaryMainFrame());
   password_protection_service_->StartRequest(
       web_contents.get(), GURL("about:blank"), GURL(), GURL(), kUserName,
-      PasswordType::SAVED_PASSWORD, {{"example.com", u"username"}},
+      PasswordType::SAVED_PASSWORD,
+      {{"example.com", GURL("https://example.com/"), u"username"}},
       LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE, true);
   base::RunLoop().RunUntilIdle();
 
@@ -1622,7 +1627,8 @@
   std::unique_ptr<content::WebContents> web_contents = GetWebContents();
   password_protection_service_->StartRequest(
       web_contents.get(), GURL("about:blank"), GURL(), GURL(), kUserName,
-      PasswordType::SAVED_PASSWORD, {{"example.com", u"username"}},
+      PasswordType::SAVED_PASSWORD,
+      {{"example.com", GURL("https://example.com/"), u"username"}},
       LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE, true);
   task_environment_.RunUntilIdle();
 
diff --git a/components/safe_browsing/core/browser/password_protection/password_protection_request.cc b/components/safe_browsing/core/browser/password_protection/password_protection_request.cc
index da31ba5b..a7e6624 100644
--- a/components/safe_browsing/core/browser/password_protection/password_protection_request.cc
+++ b/components/safe_browsing/core/browser/password_protection/password_protection_request.cc
@@ -52,7 +52,7 @@
     // to be special handing and should use affiliation information instead of
     // the signon_realm.
     std::string domain = base::UTF16ToUTF8(url_formatter::FormatUrl(
-        GURL(credential.signon_realm),
+        credential.url,
         url_formatter::kFormatUrlOmitDefaults |
             url_formatter::kFormatUrlOmitHTTPS |
             url_formatter::kFormatUrlOmitTrivialSubdomains |
diff --git a/components/safe_browsing/core/browser/password_protection/password_reuse_detection_manager_unittest.cc b/components/safe_browsing/core/browser/password_protection/password_reuse_detection_manager_unittest.cc
index 16b5a93..97ffca6c 100644
--- a/components/safe_browsing/core/browser/password_protection/password_reuse_detection_manager_unittest.cc
+++ b/components/safe_browsing/core/browser/password_protection/password_reuse_detection_manager_unittest.cc
@@ -156,8 +156,11 @@
   PasswordReuseDetectionManager manager(&client_);
 
   // Simulate that reuse found.
-  manager.OnReuseCheckDone(true, 0ul, std::nullopt, {{"https://example.com"}},
-                           0, std::string(), 0);
+  manager.OnReuseCheckDone(
+      true, 0ul, std::nullopt,
+      {password_manager::MatchingReusedCredential(
+          "https://example.com", GURL("https://example.com"), u"username")},
+      0, std::string(), 0);
 
   // Expect no checking of reuse.
   EXPECT_CALL(reuse_manager_, CheckReuse).Times(0);
@@ -237,10 +240,10 @@
   manager.OnPaste(kInput);
   testing::Mock::VerifyAndClearExpectations(&reuse_manager_);
 
-  std::vector<password_manager::MatchingReusedCredential> reused_credentials = {
-      {.signon_realm = "www.example2.com",
-       .username = u"username1",
-       .in_store = password_manager::PasswordForm::Store::kProfileStore}};
+  std::vector<password_manager::MatchingReusedCredential> reused_credentials;
+  reused_credentials.emplace_back(
+      "www.example2.com", GURL("www.example2.com"), u"username1",
+      password_manager::PasswordForm::Store::kProfileStore);
 
   // CheckProtectedPasswordEntry should get called once, and the reused
   // credentials get used reported once in this call.
diff --git a/ios/chrome/browser/safe_browsing/model/chrome_password_protection_service_unittest.mm b/ios/chrome/browser/safe_browsing/model/chrome_password_protection_service_unittest.mm
index 27732d80..fc5ef241 100644
--- a/ios/chrome/browser/safe_browsing/model/chrome_password_protection_service_unittest.mm
+++ b/ios/chrome/browser/safe_browsing/model/chrome_password_protection_service_unittest.mm
@@ -409,7 +409,8 @@
        VerifyPersistPhishedSavedPasswordCredential) {
   service_->SetIsIncognito(false);
   std::vector<password_manager::MatchingReusedCredential> credentials = {
-      {"http://example.test"}, {"http://2.example.com"}};
+      {"http://example.test", GURL("http://example.test/"), u"user"},
+      {"http://2.example.com", GURL("http://2.example.test/"), u"user2"}};
 
   EXPECT_CALL(mock_add_callback_, Run(_, credentials[0]));
   EXPECT_CALL(mock_add_callback_, Run(_, credentials[1]));
@@ -420,8 +421,8 @@
        VerifyRemovePhishedSavedPasswordCredential) {
   service_->SetIsIncognito(false);
   std::vector<password_manager::MatchingReusedCredential> credentials = {
-      {"http://example.test", u"username1"},
-      {"http://2.example.test", u"username2"}};
+      {"http://example.test", GURL("http://example.test/"), u"username1"},
+      {"http://2.example.test", GURL("http://2.example.test/"), u"username2"}};
 
   EXPECT_CALL(mock_remove_callback_, Run(_, credentials[0]));
   EXPECT_CALL(mock_remove_callback_, Run(_, credentials[1]));