chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc

// Copyright 2016 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/extensions/api/passwords_private/passwords_private_delegate_impl.h"

#include <stddef.h>

#include <memory>
#include <optional>
#include <utility>
#include <vector>

#include "base/functional/bind.h"
#include "base/functional/callback_forward.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/rand_util.h"
#include "base/ranges/algorithm.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/gmock_move_support.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/metrics/user_action_tester.h"
#include "base/test/mock_callback.h"
#include "base/types/cxx23_to_underlying.h"
#include "base/values.h"
#include "chrome/browser/affiliations/affiliation_service_factory.h"
#include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h"
#include "chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h"
#include "chrome/browser/extensions/api/passwords_private/passwords_private_event_router_factory.h"
#include "chrome/browser/password_manager/account_password_store_factory.h"
#include "chrome/browser/password_manager/chrome_password_manager_client.h"
#include "chrome/browser/password_manager/password_manager_test_util.h"
#include "chrome/browser/password_manager/password_sender_service_factory.h"
#include "chrome/browser/sync/sync_service_factory.h"
#include "chrome/browser/ui/autofill/chrome_autofill_client.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/browser/ui/browser_navigator_params.h"
#include "chrome/browser/ui/passwords/settings/password_manager_porter_interface.h"
#include "chrome/browser/web_applications/test/fake_web_app_provider.h"
#include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
#include "chrome/browser/web_applications/test/web_app_test.h"
#include "chrome/browser/web_applications/web_app_command_manager.h"
#include "chrome/browser/web_applications/web_app_id_constants.h"
#include "chrome/browser/web_applications/web_contents/web_contents_manager.h"
#include "chrome/browser/webapps/webapps_client_desktop.h"
#include "chrome/browser/webauthn/change_pin_controller.h"
#include "chrome/browser/webauthn/enclave_manager.h"
#include "chrome/browser/webauthn/enclave_manager_factory.h"
#include "chrome/browser/webauthn/enclave_manager_interface.h"
#include "chrome/browser/webauthn/passkey_model_factory.h"
#include "chrome/common/extensions/api/passwords_private.h"
#include "chrome/test/base/test_browser_window.h"
#include "chrome/test/base/testing_profile.h"
#include "components/affiliations/core/browser/fake_affiliation_service.h"
#include "components/device_reauth/device_reauth_metrics_util.h"
#include "components/device_reauth/mock_device_authenticator.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/password_manager/content/browser/password_manager_log_router_factory.h"
#include "components/password_manager/core/browser/features/password_features.h"
#include "components/password_manager/core/browser/import/import_results.h"
#include "components/password_manager/core/browser/mock_password_feature_manager.h"
#include "components/password_manager/core/browser/password_form.h"
#include "components/password_manager/core/browser/password_manager_metrics_util.h"
#include "components/password_manager/core/browser/password_manager_test_utils.h"
#include "components/password_manager/core/browser/password_store/test_password_store.h"
#include "components/password_manager/core/browser/sharing/mock_password_sender_service.h"
#include "components/password_manager/core/browser/sharing/password_sharing_recipients_downloader.h"
#include "components/password_manager/core/browser/sharing/recipients_fetcher_impl.h"
#include "components/password_manager/core/common/password_manager_features.h"
#include "components/password_manager/core/common/password_manager_pref_names.h"
#include "components/signin/public/base/signin_metrics.h"
#include "components/signin/public/base/signin_pref_names.h"
#include "components/signin/public/base/signin_switches.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "components/sync/base/features.h"
#include "components/sync/protocol/password_sharing_recipients.pb.h"
#include "components/sync/test/test_sync_service.h"
#include "components/webauthn/core/browser/test_passkey_model.h"
#include "content/public/browser/browser_context.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/test_web_contents_factory.h"
#include "content/public/test/web_contents_tester.h"
#include "extensions/browser/test_event_router.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/clipboard/test/test_clipboard.h"

#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
#include "base/test/scoped_feature_list.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#endif

ReauthResult;
PasswordForm;
PasswordRecipient;
TestPasswordStore;
_;
AllOf;
ElementsAre;
Eq;
Field;
IsEmpty;
IsNull;
Ne;
Optional;
Return;
SizeIs;
StrictMock;

namespace extensions {

FamilyFetchResults;
ImportResults;
PasswordUiEntry;
PublicKey;
RecipientInfo;
UrlCollection;

namespace {

constexpr char kHistogramName[] =;
constexpr char kSharingRecipientId1[] =;
constexpr char kSharingRecipientKeyValue1[] =;
constexpr char kSharingRecipientKeyValue2[] =;
constexpr char kSharingRecipientId2[] =;
constexpr char kSharingRecipientDisplayName1[] =;
constexpr char kSharingRecipientDisplayName2[] =;
constexpr char kSharingRecipientEmail1[] =;
constexpr char kSharingRecipientEmail2[] =;
constexpr char kSharingRecipientProfileImageUrl1[] =;
constexpr char kSharingRecipientProfileImageUrl2[] =;

MockPlaintextPasswordCallback;
MockRequestCredentialsDetailsCallback;

class MockPasswordManagerPorter : public PasswordManagerPorterInterface {};

class MockChangePinController : public ChangePinController {};

class FakePasswordManagerPorter : public PasswordManagerPorterInterface {};

class MockPasswordManagerClient : public ChromePasswordManagerClient {};

class MockEnclaveManager : public EnclaveManagerInterface {};

// static
MockPasswordManagerClient*
MockPasswordManagerClient::CreateForWebContentsAndGet(
    content::WebContents* web_contents) {}

void SetUpSyncInTransportMode(Profile* profile) {}

class PasswordEventObserver
    : public extensions::TestEventRouter::EventObserver {};

PasswordEventObserver::PasswordEventObserver(const std::string& event_name)
    :{}

PasswordEventObserver::~PasswordEventObserver() = default;

base::Value PasswordEventObserver::PassEventArgs() {}

void PasswordEventObserver::OnBroadcastEvent(const extensions::Event& event) {}

std::unique_ptr<KeyedService> BuildPasswordsPrivateEventRouter(
    content::BrowserContext* context) {}

PasswordForm CreateSampleForm(
    PasswordForm::Store store = PasswordForm::Store::kProfileStore,
    const std::u16string& username = u"[email protected]") {}

sync_pb::WebauthnCredentialSpecifics CreatePasskey() {}

MATCHER_P(PasswordUiEntryDataEquals, expected, "") {}

void ExpectAuthentication(scoped_refptr<PasswordsPrivateDelegateImpl> delegate,
                          bool successful) {}

}  // namespace

class PasswordsPrivateDelegateImplTest : public WebAppTest {};

PasswordsPrivateDelegateImplTest::~PasswordsPrivateDelegateImplTest() {}

void PasswordsPrivateDelegateImplTest::SetUp() {}

void PasswordsPrivateDelegateImplTest::SetUpPasswordStores(
    std::vector<PasswordForm> forms) {}

void PasswordsPrivateDelegateImplTest::SetUpRouters() {}

PasswordsPrivateDelegate::UiEntries
PasswordsPrivateDelegateImplTest::GetCredentials(
    PasswordsPrivateDelegate& delegate) {}

syncer::TestSyncService* PasswordsPrivateDelegateImplTest::sync_service() {}

TEST_F(PasswordsPrivateDelegateImplTest, GetSavedPasswordsList) {}

TEST_F(PasswordsPrivateDelegateImplTest,
       PasswordsDuplicatedInStoresAreRepresentedAsSingleEntity) {}

TEST_F(PasswordsPrivateDelegateImplTest, GetPasswordExceptionsList) {}

TEST_F(PasswordsPrivateDelegateImplTest,
       ExceptionsDuplicatedInStoresAreRepresentedAsSingleEntity) {}

TEST_F(PasswordsPrivateDelegateImplTest, AddPassword) {}

TEST_F(PasswordsPrivateDelegateImplTest, AddPasswordUpdatesDefaultStore) {}

TEST_F(PasswordsPrivateDelegateImplTest, AddPasswordDoesNotUpdateDefaultStore) {}

TEST_F(PasswordsPrivateDelegateImplTest,
       ImportPasswordsDoesNotUpdateDefaultStore) {}

TEST_F(PasswordsPrivateDelegateImplTest,
       ImportPasswordsDoesntUpdateDefaultStore) {}

TEST_F(PasswordsPrivateDelegateImplTest,
       ImportPasswordsLogsImportResultsStatus) {}

TEST_F(PasswordsPrivateDelegateImplTest, TestReauthFailedOnImport) {}

TEST_F(PasswordsPrivateDelegateImplTest,
       ContinueImportLogsImportResultsStatus) {}

TEST_F(PasswordsPrivateDelegateImplTest, ResetImporter) {}

TEST_F(PasswordsPrivateDelegateImplTest, ChangeCredential_Password) {}

TEST_F(PasswordsPrivateDelegateImplTest,
       ChangeCredential_PasswordInBothStores) {}

TEST_F(PasswordsPrivateDelegateImplTest,
       ChangeCredential_PasswordInAccountStore) {}

TEST_F(PasswordsPrivateDelegateImplTest, ChangeCredential_Passkey) {}

TEST_F(PasswordsPrivateDelegateImplTest, ChangeCredential_NotFound) {}

TEST_F(PasswordsPrivateDelegateImplTest, ChangeCredential_EmptyPassword) {}

// Checking callback result of RequestPlaintextPassword with reason Copy.
// By implementation for Copy, callback will receive empty string.
TEST_F(PasswordsPrivateDelegateImplTest, TestCopyPasswordCallbackResult) {}

TEST_F(PasswordsPrivateDelegateImplTest,
       TestShouldNotReauthForOptInIfExplicitSigninUIEnabled) {}

TEST_F(PasswordsPrivateDelegateImplTest,
       TestShouldNotReauthForOptOutAndShouldSetPref) {}

#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS)
TEST_F(PasswordsPrivateDelegateImplTest, TestCopyPasswordCallbackResultFail) {
  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();

  SetUpPasswordStores({CreateSampleForm()});

  auto delegate = CreateDelegate();
  base::RunLoop().RunUntilIdle();

  ExpectAuthentication(delegate, /*successful=*/false);

  base::Time before_call = test_clipboard_->GetLastModifiedTime();

  MockPlaintextPasswordCallback password_callback;
  EXPECT_CALL(password_callback, Run(Eq(std::nullopt)));
  delegate->RequestPlaintextPassword(
      0, api::passwords_private::PlaintextReason::kCopy,
      password_callback.Get(), web_contents.get());
  // Clipboard should not be modified in case Reauth failed
  std::u16string result;
  test_clipboard_->ReadText(ui::ClipboardBuffer::kCopyPaste,
                            /* data_dst = */ nullptr, &result);
  EXPECT_EQ(std::u16string(), result);
  EXPECT_EQ(before_call, test_clipboard_->GetLastModifiedTime());

  // Since Reauth had failed password was not copied and metric wasn't recorded
  histogram_tester().ExpectTotalCount(kHistogramName, 0);
}
#endif

TEST_F(PasswordsPrivateDelegateImplTest, TestPassedReauthOnView) {}

TEST_F(PasswordsPrivateDelegateImplTest,
       TestPassedReauthOnRequestCredentialsDetails) {}

#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS)
TEST_F(PasswordsPrivateDelegateImplTest, TestFailedReauthOnView) {
  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();

  SetUpPasswordStores({CreateSampleForm()});

  auto delegate = CreateDelegate();
  // Spin the loop to allow PasswordStore tasks posted on the creation of
  // |delegate| to be completed.
  base::RunLoop().RunUntilIdle();

  ExpectAuthentication(delegate, /*successful=*/false);

  MockPlaintextPasswordCallback password_callback;
  EXPECT_CALL(password_callback, Run(Eq(std::nullopt)));
  delegate->RequestPlaintextPassword(
      0, api::passwords_private::PlaintextReason::kView,
      password_callback.Get(), web_contents.get());

  // Since Reauth had failed password was not viewed and metric wasn't recorded
  histogram_tester().ExpectTotalCount(kHistogramName, 0);
}

TEST_F(PasswordsPrivateDelegateImplTest,
       TestFailedReauthOnRequestCredentialsDetails) {
  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();

  SetUpPasswordStores({CreateSampleForm()});

  auto delegate = CreateDelegate();
  // Spin the loop to allow PasswordStore tasks posted on the creation of
  // |delegate| to be completed.
  base::RunLoop().RunUntilIdle();

  ExpectAuthentication(delegate, /*successful=*/false);

  MockRequestCredentialsDetailsCallback password_callback;
  EXPECT_CALL(password_callback, Run(testing::IsEmpty()));
  delegate->RequestCredentialsDetails({0}, password_callback.Get(),
                                      web_contents.get());

  // Since Reauth had failed password was not viewed and metric wasn't recorded
  histogram_tester().ExpectTotalCount(kHistogramName, 0);
}

TEST_F(PasswordsPrivateDelegateImplTest, TestReauthFailedOnExport) {
  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();

  SetUpPasswordStores({CreateSampleForm()});
  StrictMock<base::MockCallback<base::OnceCallback<void(const std::string&)>>>
      mock_accepted;

  auto delegate = CreateDelegate();
  // Spin the loop to allow PasswordStore tasks posted on the creation of
  // |delegate| to be completed.
  base::RunLoop().RunUntilIdle();

  ExpectAuthentication(delegate, /*successful=*/false);

  EXPECT_CALL(mock_accepted, Run(std::string("reauth-failed")));
  delegate->ExportPasswords(mock_accepted.Get(), web_contents.get());
}
#endif

TEST_F(PasswordsPrivateDelegateImplTest,
       GetUrlCollectionValueWithSchemeWhenIpAddress) {}

TEST_F(PasswordsPrivateDelegateImplTest,
       GetUrlCollectionValueWithSchemeWhenWebAddress) {}

TEST_F(PasswordsPrivateDelegateImplTest,
       GetUrlCollectionStrippedValueWhenFullUrl) {}

TEST_F(PasswordsPrivateDelegateImplTest,
       GetUrlCollectionNoValueWhenUnsupportedScheme) {}

TEST_F(PasswordsPrivateDelegateImplTest,
       GetUrlCollectionNoValueWhenInvalidUrl) {}

TEST_F(PasswordsPrivateDelegateImplTest, IsAccountStoreDefault) {}

TEST_F(PasswordsPrivateDelegateImplTest, TestMovePasswordsToAccountStore) {}

TEST_F(PasswordsPrivateDelegateImplTest, VerifyCastingOfImportEntryStatus) {}

TEST_F(PasswordsPrivateDelegateImplTest, VerifyCastingOfImportResultsStatus) {}

#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
// Checks if authentication is triggered.
TEST_F(PasswordsPrivateDelegateImplTest,
       SwitchBiometricAuthBeforeFillingState) {
  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();
  base::MockCallback<
      extensions::PasswordsPrivateDelegate::AuthenticationCallback>
      result_callback;

  profile()->GetPrefs()->SetBoolean(
      password_manager::prefs::kBiometricAuthenticationBeforeFilling, false);

  auto delegate = CreateDelegate();
  ExpectAuthentication(delegate, /*successful=*/true);

  EXPECT_CALL(result_callback, Run(/*auth_succeeded=*/true));
  delegate->SwitchBiometricAuthBeforeFillingState(web_contents.get(),
                                                  result_callback.Get());
  // Expects that the switch value will change.
  EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(
      password_manager::prefs::kBiometricAuthenticationBeforeFilling));
}

TEST_F(PasswordsPrivateDelegateImplTest,
       SwitchBiometricAuthBeforeFillingStateAuthenticationFailed) {
  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();
  base::MockCallback<
      extensions::PasswordsPrivateDelegate::AuthenticationCallback>
      result_callback;

  profile()->GetPrefs()->SetBoolean(
      password_manager::prefs::kBiometricAuthenticationBeforeFilling, false);

  auto delegate = CreateDelegate();
  ExpectAuthentication(delegate, /*successful=*/false);

  EXPECT_CALL(result_callback, Run(/*auth_succeeded=*/false));
  delegate->SwitchBiometricAuthBeforeFillingState(web_contents.get(),
                                                  result_callback.Get());

  // Expects that the switch value will change.
  EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
      password_manager::prefs::kBiometricAuthenticationBeforeFilling));
}
#endif

#if BUILDFLAG(IS_MAC)
// Checks if authentication is triggered.
TEST_F(PasswordsPrivateDelegateImplTest,
       SwitchBiometricAuthBeforeFillingCancelsLastTry) {
  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();

  auto biometric_authenticator =
      std::make_unique<device_reauth::MockDeviceAuthenticator>();
  auto* biometric_authenticator_ptr = biometric_authenticator.get();

  auto delegate = CreateDelegate();
  EXPECT_CALL(*biometric_authenticator_ptr, AuthenticateWithMessage);
  delegate->SetDeviceAuthenticatorForTesting(
      std::move(biometric_authenticator));

  delegate->SwitchBiometricAuthBeforeFillingState(web_contents.get(),
                                                  base::DoNothing());

  // Invoking authentication again will cancel previous request.
  EXPECT_CALL(*biometric_authenticator_ptr, Cancel);
  ExpectAuthentication(delegate, /*successful=*/true);
  delegate->SwitchBiometricAuthBeforeFillingState(web_contents.get(),
                                                  base::DoNothing());
}
#endif

#if BUILDFLAG(IS_WIN)
// Checks if authentication is triggered.
TEST_F(PasswordsPrivateDelegateImplTest,
       SwitchBiometricAuthBeforeFillingDoesntCancelLastTry) {
  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();
  base::MockCallback<
      extensions::PasswordsPrivateDelegate::AuthenticationCallback>
      result_callback;

  auto biometric_authenticator =
      std::make_unique<device_reauth::MockDeviceAuthenticator>();
  auto* biometric_authenticator_ptr = biometric_authenticator.get();

  auto delegate = CreateDelegate();
  EXPECT_CALL(*biometric_authenticator_ptr, AuthenticateWithMessage);
  delegate->SetDeviceAuthenticatorForTesting(
      std::move(biometric_authenticator));

  delegate->SwitchBiometricAuthBeforeFillingState(web_contents.get(),
                                                  result_callback.Get());

  // Invoking authentication again should not cancel previous request.
  EXPECT_CALL(*biometric_authenticator_ptr, Cancel).Times(0);
  EXPECT_CALL(result_callback, Run(false));
  delegate->SwitchBiometricAuthBeforeFillingState(web_contents.get(),
                                                  result_callback.Get());
}
#endif

// TODO(http://crbug.com/1455574) Re-enable.
TEST_F(PasswordsPrivateDelegateImplTest, DISABLED_ShowAddShortcutDialog) {}

TEST_F(PasswordsPrivateDelegateImplTest, GetCredentialGroups) {}

TEST_F(PasswordsPrivateDelegateImplTest, PasswordManagerAppInstalled) {}

TEST_F(PasswordsPrivateDelegateImplTest, GetPasskeyInGroups) {}

TEST_F(PasswordsPrivateDelegateImplTest, RemovePasskey) {}

// Ensures that if a password is deleted from the account store via the settings
// UI, password removal reason is recorded in the pref.
TEST_F(PasswordsPrivateDelegateImplTest,
       RemovePasswordFromAccountStoreTracksRemovalReason) {}

// Ensures that if a password is deleted from the profile store via the settings
// UI, password removal reason is recorded in the pref.
TEST_F(PasswordsPrivateDelegateImplTest,
       RemovePasswordFromProfileStoreTracksRemovalReason) {}

TEST_F(PasswordsPrivateDelegateImplTest, SharePasswordWithTwoRecipients) {}

TEST_F(PasswordsPrivateDelegateImplTest,
       ShareAllPasswordsRepresentedByUiEntry) {}

TEST_F(PasswordsPrivateDelegateImplTest, ShareNonExistentPassword) {}

TEST_F(PasswordsPrivateDelegateImplTest, IsChangePinFlowAvailable) {}

TEST_F(PasswordsPrivateDelegateImplTest, DisconnectCloudAuthenticator) {}

TEST_F(PasswordsPrivateDelegateImplTest, IsConnecetdToCloudAuthenticator) {}

#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS)
class PasswordsPrivateDelegateImplMockTaskEnvironmentTest
    : public testing::Test {
 public:
  PasswordsPrivateDelegateImplMockTaskEnvironmentTest()
      : profile_manager_(TestingBrowserProcess::GetGlobal()) {}

  void SetUp() override {
    ASSERT_TRUE(profile_manager_.SetUp());

    profile_ = profile_manager_.CreateTestingProfile("test_profile");
    web_contents_ = web_contents_factory_.CreateWebContents(profile_);

    profile_store_ = CreateAndUseTestPasswordStore(profile_);
    account_store_ = CreateAndUseTestAccountPasswordStore(profile_);
  }

  void TearDown() override { profile_manager_.DeleteAllTestingProfiles(); }

  base::HistogramTester& histogram_tester() { return histogram_tester_; }

  content::WebContents* web_contents() { return web_contents_; }

  content::TestWebContentsFactory& web_contents_factory() {
    return web_contents_factory_;
  }

  TestingProfile* profile() { return profile_; }

  scoped_refptr<PasswordsPrivateDelegateImpl> CreateDelegate() {
    return new PasswordsPrivateDelegateImpl(profile_);
  }

  content::BrowserTaskEnvironment& GetTaskEnvironment() {
    return task_environment_;
  }

 private:
  TestingProfileManager profile_manager_;
  content::BrowserTaskEnvironment task_environment_{
      base::test::TaskEnvironment::TimeSource::MOCK_TIME};
  base::HistogramTester histogram_tester_;
  content::TestWebContentsFactory web_contents_factory_;
  scoped_refptr<TestPasswordStore> profile_store_;
  scoped_refptr<TestPasswordStore> account_store_;
  // Owned by |web_contents_factory_|
  raw_ptr<content::WebContents> web_contents_;
  raw_ptr<TestingProfile> profile_;
};

TEST_F(PasswordsPrivateDelegateImplMockTaskEnvironmentTest,
       AuthenticationTimeMetric) {
  content::WebContents* web_contents_ptr = web_contents();
  auto delegate = CreateDelegate();

  auto biometric_authenticator =
      std::make_unique<device_reauth::MockDeviceAuthenticator>();

  EXPECT_CALL(*biometric_authenticator, AuthenticateWithMessage)
      .WillOnce(testing::WithArg<1>(
          [this](PasswordsPrivateDelegateImpl::AuthResultCallback callback) {
            // Waiting for 10 seconds to simulate a long authentication process.
            GetTaskEnvironment().FastForwardBy(base::Seconds(10));
            std::move(callback).Run(/*successful=*/true);
          }));

  delegate->SetDeviceAuthenticatorForTesting(
      std::move(biometric_authenticator));

  MockRequestCredentialsDetailsCallback callback;
  EXPECT_CALL(callback, Run(testing::IsEmpty()));
  delegate->RequestCredentialsDetails({0}, callback.Get(), web_contents_ptr);

  histogram_tester().ExpectUniqueTimeSample(
      "PasswordManager.Settings.AuthenticationTime2", base::Seconds(10), 1);
}

TEST_F(PasswordsPrivateDelegateImplMockTaskEnvironmentTest,
       ClosingTabDuringExportDoesNotCrashChrome) {
  content::WebContents* web_contents_ptr =
      web_contents_factory().CreateWebContents(profile());
  auto delegate = CreateDelegate();

  auto biometric_authenticator =
      std::make_unique<device_reauth::MockDeviceAuthenticator>();

  device_reauth::DeviceAuthenticator::AuthenticateCallback auth_result_callback;
  EXPECT_CALL(*biometric_authenticator, AuthenticateWithMessage)
      .WillOnce(MoveArg<1>(&auth_result_callback));

  delegate->SetDeviceAuthenticatorForTesting(
      std::move(biometric_authenticator));

  base::MockCallback<base::OnceCallback<void(const std::string&)>> callback;
  delegate->ExportPasswords(callback.Get(), web_contents_ptr);

  // Simulate closing tab while authentication is still ongoing.
  web_contents_factory().DestroyWebContents(web_contents_ptr);

  // Now simulate auth is finished with success. Expect export to fail because
  // the tab is closed.
  EXPECT_CALL(callback, Run("reauth-failed"));
  std::move(auth_result_callback).Run(true);
}

#if !BUILDFLAG(IS_WIN)
TEST_F(PasswordsPrivateDelegateImplMockTaskEnvironmentTest,
       DestroyingDelegateWhileExportOngoing) {
  content::WebContents* web_contents_ptr =
      web_contents_factory().CreateWebContents(profile());
  auto delegate = CreateDelegate();

  auto biometric_authenticator =
      std::make_unique<device_reauth::MockDeviceAuthenticator>();
  auto* biometric_authenticator_ptr = biometric_authenticator.get();

  device_reauth::DeviceAuthenticator::AuthenticateCallback auth_result_callback;

  delegate->SetDeviceAuthenticatorForTesting(
      std::move(biometric_authenticator));

  EXPECT_CALL(*biometric_authenticator_ptr, AuthenticateWithMessage);
  base::MockCallback<base::OnceCallback<void(const std::string&)>> callback;
  delegate->ExportPasswords(callback.Get(), web_contents_ptr);

  // Simulate destroying delegate while authentication is still ongoing. It
  // should trigger cancelation of ongoing authentication.
  EXPECT_CALL(*biometric_authenticator_ptr, Cancel);
  delegate.reset();
}
#endif  // !BUILDFLAG(IS_WIN)
#endif  // BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS)

class PasswordsPrivateDelegateImplFetchFamilyMembersTest
    : public PasswordsPrivateDelegateImplTest {};

TEST_F(PasswordsPrivateDelegateImplFetchFamilyMembersTest,
       FetchFamilyMembersSucceedsWithoutPublicKey) {}

TEST_F(PasswordsPrivateDelegateImplFetchFamilyMembersTest,
       FetchFamilyMembersSucceedsWithPublicKey) {}

TEST_F(PasswordsPrivateDelegateImplFetchFamilyMembersTest,
       FetchFamilyMembersFailsWithUnknownError) {}

TEST_F(PasswordsPrivateDelegateImplFetchFamilyMembersTest,
       FetchFamilyMembersFailsWithNoFamilyMembersError) {}

TEST_F(PasswordsPrivateDelegateImplFetchFamilyMembersTest,
       FetchFamilyMembersFailsWithAnotherRequestInFlight) {}

TEST_F(PasswordsPrivateDelegateImplFetchFamilyMembersTest,
       FetchFamilyMembersFailsWithNetworkError) {}

TEST_F(PasswordsPrivateDelegateImplTest, GetCredentialGroups_SyncOn) {}

TEST_F(PasswordsPrivateDelegateImplTest, GetCredentialGroups_SyncOff) {}

TEST_F(PasswordsPrivateDelegateImplTest, GetCredentialGroups_Butter) {}

TEST_F(PasswordsPrivateDelegateImplTest, DeleteAllData) {}

#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS)
TEST_F(PasswordsPrivateDelegateImplTest, DeleteAllDataWithReauthFailed) {
  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();
  auto delegate = CreateDelegate();
  PasswordForm form_profile =
      CreateSampleForm(PasswordForm::Store::kProfileStore);
  PasswordForm form_account =
      CreateSampleForm(PasswordForm::Store::kAccountStore);
  SetUpPasswordStores({form_profile, form_account});
  task_environment()->RunUntilIdle();

  base::test::ScopedFeatureList scoped_feature_list;
  scoped_feature_list.InitAndEnableFeature(syncer::kSyncWebauthnCredentials);
  webauthn::PasskeyModel* passkey_model =
      PasskeyModelFactory::GetForProfile(profile());
  ASSERT_EQ(passkey_model, PasskeyModelFactory::GetForProfile(profile()));
  ASSERT_TRUE(passkey_model);
  sync_pb::WebauthnCredentialSpecifics passkey = CreatePasskey();
  passkey_model->AddNewPasskeyForTesting(passkey);
  task_environment()->RunUntilIdle();

  ExpectAuthentication(delegate, /*successful=*/false);
  base::MockCallback<base::OnceCallback<void(bool)>> callback;
  EXPECT_CALL(callback, Run(false));
  delegate->DeleteAllPasswordManagerData(web_contents.get(), callback.Get());
  task_environment()->RunUntilIdle();
  EXPECT_THAT(profile_store_->stored_passwords(), testing::SizeIs(1));
  EXPECT_THAT(account_store_->stored_passwords(), testing::SizeIs(1));
  EXPECT_THAT(passkey_model->GetAllPasskeys(), SizeIs(1));
}
#endif

}  // namespace extensions