chromium/chrome/browser/password_manager/android/android_backend_with_double_deletion_unittest.cc

// 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/android_backend_with_double_deletion.h"

#include "base/task/sequenced_task_runner.h"
#include "base/test/mock_callback.h"
#include "base/test/task_environment.h"
#include "base/test/test_mock_time_task_runner.h"
#include "components/password_manager/core/browser/password_store/mock_password_store_backend.h"
#include "components/sync/test/test_sync_service.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace password_manager {
namespace {

using ::testing::_;
using ::testing::ElementsAreArray;
using ::testing::NiceMock;
using ::testing::Return;

PasswordForm CreateTestForm() {
  PasswordForm form;
  form.username_value = u"admin";
  form.password_value = u"admin";
  form.signon_realm = "https://admin.google.com/";
  form.url = GURL(form.signon_realm);
  return form;
}

}  // namespace

class AndroidBackendWithDoubleDeletionTest : public testing::Test {
 protected:
  AndroidBackendWithDoubleDeletionTest() {
    auto built_in_backend =
        std::make_unique<NiceMock<MockPasswordStoreBackend>>();
    auto android_backend =
        std::make_unique<NiceMock<MockPasswordStoreBackend>>();
    built_in_backend_ = built_in_backend.get();
    android_backend_ = android_backend.get();
    proxy_backend_ = std::make_unique<AndroidBackendWithDoubleDeletion>(
        std::move(built_in_backend), std::move(android_backend));

    EXPECT_CALL(*built_in_backend_, InitBackend);
    EXPECT_CALL(*android_backend_, InitBackend);
    proxy_backend()->InitBackend(nullptr, base::DoNothing(), base::DoNothing(),
                                 base::DoNothing());
  }

  ~AndroidBackendWithDoubleDeletionTest() override {
    EXPECT_CALL(android_backend(), Shutdown);
    EXPECT_CALL(built_in_backend(), Shutdown);
    built_in_backend_ = nullptr;
    android_backend_ = nullptr;
    proxy_backend()->Shutdown(base::DoNothing());
  }

  PasswordStoreBackend* proxy_backend() { return proxy_backend_.get(); }
  MockPasswordStoreBackend& built_in_backend() { return *built_in_backend_; }
  MockPasswordStoreBackend& android_backend() { return *android_backend_; }

 private:
  base::test::SingleThreadTaskEnvironment task_env_;
  raw_ptr<NiceMock<MockPasswordStoreBackend>> built_in_backend_;
  raw_ptr<NiceMock<MockPasswordStoreBackend>> android_backend_;
  std::unique_ptr<AndroidBackendWithDoubleDeletion> proxy_backend_;
};

TEST_F(AndroidBackendWithDoubleDeletionTest, GetAllLoginsAsync) {
  EXPECT_CALL(built_in_backend(), GetAllLoginsAsync).Times(0);
  EXPECT_CALL(android_backend(), GetAllLoginsAsync);

  proxy_backend()->GetAllLoginsAsync(base::DoNothing());
}

TEST_F(AndroidBackendWithDoubleDeletionTest, IsAbleToSavePasswords) {
  EXPECT_CALL(built_in_backend(), IsAbleToSavePasswords).Times(0);
  EXPECT_CALL(android_backend(), IsAbleToSavePasswords).WillOnce(Return(false));

  EXPECT_FALSE(proxy_backend()->IsAbleToSavePasswords());
}

TEST_F(AndroidBackendWithDoubleDeletionTest,
       GetAllLoginsWithAffiliationAndBrandingAsync) {
  EXPECT_CALL(built_in_backend(), GetAllLoginsWithAffiliationAndBrandingAsync)
      .Times(0);
  EXPECT_CALL(android_backend(), GetAllLoginsWithAffiliationAndBrandingAsync);

  proxy_backend()->GetAllLoginsWithAffiliationAndBrandingAsync(
      base::DoNothing());
}

TEST_F(AndroidBackendWithDoubleDeletionTest, GetAutofillableLoginsAsync) {
  EXPECT_CALL(built_in_backend(), GetAutofillableLoginsAsync).Times(0);
  EXPECT_CALL(android_backend(), GetAutofillableLoginsAsync);

  proxy_backend()->GetAutofillableLoginsAsync(base::DoNothing());
}

TEST_F(AndroidBackendWithDoubleDeletionTest, FillMatchingLoginsAsync) {
  std::vector<PasswordFormDigest> forms = {
      PasswordFormDigest(PasswordForm::Scheme::kHtml, "https://google.com/",
                         GURL("https://google.com/"))};
  EXPECT_CALL(built_in_backend(), FillMatchingLoginsAsync).Times(0);
  EXPECT_CALL(android_backend(),
              FillMatchingLoginsAsync(_, false, ElementsAreArray(forms)));

  proxy_backend()->FillMatchingLoginsAsync(base::DoNothing(),
                                           /*include_psl=*/false, forms);
}

TEST_F(AndroidBackendWithDoubleDeletionTest, GetGroupedMatchingLoginsAsync) {
  PasswordFormDigest form_digest(PasswordForm::Scheme::kHtml,
                                 "https://google.com/",
                                 GURL("https://google.com/"));
  EXPECT_CALL(built_in_backend(), GetGroupedMatchingLoginsAsync).Times(0);
  EXPECT_CALL(android_backend(), GetGroupedMatchingLoginsAsync(form_digest, _));

  proxy_backend()->GetGroupedMatchingLoginsAsync(form_digest,
                                                 base::DoNothing());
}

TEST_F(AndroidBackendWithDoubleDeletionTest, AddLoginAsync) {
  EXPECT_CALL(built_in_backend(), AddLoginAsync).Times(0);
  EXPECT_CALL(android_backend(), AddLoginAsync(CreateTestForm(), _));

  proxy_backend()->AddLoginAsync(CreateTestForm(), base::DoNothing());
}

TEST_F(AndroidBackendWithDoubleDeletionTest, UpdateLoginAsync) {
  EXPECT_CALL(built_in_backend(), UpdateLoginAsync).Times(0);
  EXPECT_CALL(android_backend(), UpdateLoginAsync(CreateTestForm(), _));

  proxy_backend()->UpdateLoginAsync(CreateTestForm(), base::DoNothing());
}

TEST_F(AndroidBackendWithDoubleDeletionTest, RemoveLoginAsync) {
  EXPECT_CALL(built_in_backend(), RemoveLoginAsync(_, CreateTestForm(), _));
  EXPECT_CALL(android_backend(), RemoveLoginAsync(_, CreateTestForm(), _));

  proxy_backend()->RemoveLoginAsync(FROM_HERE, CreateTestForm(),
                                    base::DoNothing());
}

TEST_F(AndroidBackendWithDoubleDeletionTest, RemoveLoginsByURLAndTimeAsync) {
  base::RepeatingCallback<bool(const GURL&)> url_filter =
      base::BindRepeating([](const GURL& url) { return true; });
  base::Time delete_begin = base::Time::FromTimeT(1000);
  base::Time delete_end = base::Time::FromTimeT(2000);
  EXPECT_CALL(built_in_backend(),
              RemoveLoginsByURLAndTimeAsync(_, url_filter, delete_begin,
                                            delete_end, _, _));
  EXPECT_CALL(android_backend(),
              RemoveLoginsByURLAndTimeAsync(_, url_filter, delete_begin,
                                            delete_end, _, _));

  proxy_backend()->RemoveLoginsByURLAndTimeAsync(
      FROM_HERE, url_filter, delete_begin, delete_end,
      base::OnceCallback<void(bool)>(), base::DoNothing());
}

TEST_F(AndroidBackendWithDoubleDeletionTest, RemoveLoginsCreatedBetweenAsync) {
  base::Time delete_begin = base::Time::FromTimeT(1000);
  base::Time delete_end = base::Time::FromTimeT(2000);
  EXPECT_CALL(built_in_backend(),
              RemoveLoginsCreatedBetweenAsync(_, delete_begin, delete_end, _));
  EXPECT_CALL(android_backend(),
              RemoveLoginsCreatedBetweenAsync(_, delete_begin, delete_end, _));

  proxy_backend()->RemoveLoginsCreatedBetweenAsync(
      FROM_HERE, delete_begin, delete_end, base::DoNothing());
}

TEST_F(AndroidBackendWithDoubleDeletionTest, DisableAutoSignInForOriginsAsync) {
  base::RepeatingCallback<bool(const GURL&)> url_filter =
      base::BindRepeating([](const GURL& url) { return true; });

  EXPECT_CALL(built_in_backend(), DisableAutoSignInForOriginsAsync).Times(0);
  EXPECT_CALL(android_backend(),
              DisableAutoSignInForOriginsAsync(url_filter, _));

  proxy_backend()->DisableAutoSignInForOriginsAsync(url_filter,
                                                    base::DoNothing());
}

}  // namespace password_manager