// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// 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/password_store_x.h"

#include <stddef.h>

#include <string>
#include <utility>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
#include "base/time/time.h"
#include "chrome/test/base/testing_browser_process.h"
#include "components/os_crypt/os_crypt_mocker.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_change.h"
#include "components/password_manager/core/browser/password_store_consumer.h"
#include "components/password_manager/core/browser/password_store_origin_unittest.h"
#include "components/password_manager/core/common/password_manager_features.h"
#include "components/password_manager/core/common/password_manager_pref_names.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/testing_pref_service.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using autofill::PasswordForm;
using password_manager::metrics_util::LinuxBackendMigrationStatus;
using password_manager::PasswordStoreChange;
using password_manager::PasswordStoreChangeList;
using password_manager::UnorderedPasswordFormElementsAre;
using testing::ElementsAreArray;
using testing::IsEmpty;
using testing::Pointee;
using testing::UnorderedElementsAre;

namespace {

class MockPasswordStoreConsumer
    : public password_manager::PasswordStoreConsumer {
 public:
  MOCK_METHOD1(OnGetPasswordStoreResultsConstRef,
               void(const std::vector<std::unique_ptr<PasswordForm>>&));

  // GMock cannot mock methods with move-only args.
  void OnGetPasswordStoreResults(
      std::vector<std::unique_ptr<PasswordForm>> results) override {
    OnGetPasswordStoreResultsConstRef(results);
  }
};

class FailingBackend : public PasswordStoreX::NativeBackend {
 public:
  bool Init() override { return true; }

  PasswordStoreChangeList AddLogin(const PasswordForm& form) override {
    return PasswordStoreChangeList();
  }
  bool UpdateLogin(const PasswordForm& form,
                   PasswordStoreChangeList* changes) override {
    return false;
  }
  bool RemoveLogin(const PasswordForm& form,
                   PasswordStoreChangeList* changes) override {
    return false;
  }

  bool RemoveLoginsCreatedBetween(
      base::Time delete_begin,
      base::Time delete_end,
      password_manager::PasswordStoreChangeList* changes) override {
    return false;
  }

  bool RemoveLoginsSyncedBetween(
      base::Time delete_begin,
      base::Time delete_end,
      password_manager::PasswordStoreChangeList* changes) override {
    return false;
  }

  bool DisableAutoSignInForOrigins(
      const base::Callback<bool(const GURL&)>& origin_filter,
      password_manager::PasswordStoreChangeList* changes) override {
    return false;
  }

  // Use this as a landmine to check whether results of failed Get*Logins calls
  // get ignored.
  static std::vector<std::unique_ptr<PasswordForm>> CreateTrashForms() {
    std::vector<std::unique_ptr<PasswordForm>> forms;
    PasswordForm trash;
    trash.username_element = base::ASCIIToUTF16("trash u. element");
    trash.username_value = base::ASCIIToUTF16("trash u. value");
    trash.password_element = base::ASCIIToUTF16("trash p. element");
    trash.password_value = base::ASCIIToUTF16("trash p. value");
    for (size_t i = 0; i < 3; ++i) {
      trash.origin = GURL(base::StringPrintf("http://trash%zu.com", i));
      forms.push_back(std::make_unique<PasswordForm>(trash));
    }
    return forms;
  }

  bool GetLogins(const PasswordStore::FormDigest& form,
                 std::vector<std::unique_ptr<PasswordForm>>* forms) override {
    *forms = CreateTrashForms();
    return false;
  }

  bool GetAutofillableLogins(
      std::vector<std::unique_ptr<PasswordForm>>* forms) override {
    *forms = CreateTrashForms();
    return false;
  }

  bool GetBlacklistLogins(
      std::vector<std::unique_ptr<PasswordForm>>* forms) override {
    *forms = CreateTrashForms();
    return false;
  }

  bool GetAllLogins(
      std::vector<std::unique_ptr<PasswordForm>>* forms) override {
    *forms = CreateTrashForms();
    return false;
  }

  scoped_refptr<base::SequencedTaskRunner> GetBackgroundTaskRunner() override {
    return nullptr;
  }
};

class MockBackend : public PasswordStoreX::NativeBackend {
 public:
  ~MockBackend() override {
    if (save_on_destruct_) {
      *save_on_destruct_ = std::move(all_forms_);
    }
  }

  bool Init() override { return true; }

  PasswordStoreChangeList AddLogin(const PasswordForm& form) override {
    all_forms_.push_back(form);
    PasswordStoreChange change(PasswordStoreChange::ADD, form);
    return PasswordStoreChangeList(1, change);
  }

  bool UpdateLogin(const PasswordForm& form,
                   PasswordStoreChangeList* changes) override {
    for (size_t i = 0; i < all_forms_.size(); ++i) {
      if (ArePasswordFormUniqueKeyEqual(all_forms_[i], form)) {
        all_forms_[i] = form;
        changes->push_back(PasswordStoreChange(PasswordStoreChange::UPDATE,
                                               form));
      }
    }
    return true;
  }

  bool RemoveLogin(const PasswordForm& form,
                   PasswordStoreChangeList* changes) override {
    for (size_t i = 0; i < all_forms_.size(); ++i) {
      if (ArePasswordFormUniqueKeyEqual(all_forms_[i], form)) {
        changes->push_back(PasswordStoreChange(PasswordStoreChange::REMOVE,
                                               form));
        erase(i--);
      }
    }
    return true;
  }

  bool RemoveLoginsCreatedBetween(
      base::Time delete_begin,
      base::Time delete_end,
      password_manager::PasswordStoreChangeList* changes) override {
    for (size_t i = 0; i < all_forms_.size(); ++i) {
      if (delete_begin <= all_forms_[i].date_created &&
          (delete_end.is_null() || all_forms_[i].date_created < delete_end))
        erase(i--);
    }
    return true;
  }

  bool RemoveLoginsSyncedBetween(
      base::Time delete_begin,
      base::Time delete_end,
      password_manager::PasswordStoreChangeList* changes) override {
    DCHECK(changes);
    for (size_t i = 0; i < all_forms_.size(); ++i) {
      if (delete_begin <= all_forms_[i].date_synced &&
          (delete_end.is_null() || all_forms_[i].date_synced < delete_end)) {
        changes->push_back(password_manager::PasswordStoreChange(
            password_manager::PasswordStoreChange::REMOVE, all_forms_[i]));
        erase(i--);
      }
    }
    return true;
  }

  bool DisableAutoSignInForOrigins(
      const base::Callback<bool(const GURL&)>& origin_filter,
      password_manager::PasswordStoreChangeList* changes) override {
    return true;
  }

  bool GetLogins(const PasswordStore::FormDigest& form,
                 std::vector<std::unique_ptr<PasswordForm>>* forms) override {
    for (size_t i = 0; i < all_forms_.size(); ++i)
      if (all_forms_[i].signon_realm == form.signon_realm)
        forms->push_back(std::make_unique<PasswordForm>(all_forms_[i]));
    return true;
  }

  bool GetAutofillableLogins(
      std::vector<std::unique_ptr<PasswordForm>>* forms) override {
    for (size_t i = 0; i < all_forms_.size(); ++i)
      if (!all_forms_[i].blacklisted_by_user)
        forms->push_back(std::make_unique<PasswordForm>(all_forms_[i]));
    return true;
  }

  bool GetBlacklistLogins(
      std::vector<std::unique_ptr<PasswordForm>>* forms) override {
    for (size_t i = 0; i < all_forms_.size(); ++i)
      if (all_forms_[i].blacklisted_by_user)
        forms->push_back(std::make_unique<PasswordForm>(all_forms_[i]));
    return true;
  }

  bool GetAllLogins(
      std::vector<std::unique_ptr<PasswordForm>>* forms) override {
    for (size_t i = 0; i < all_forms_.size(); ++i)
      forms->push_back(std::make_unique<PasswordForm>(all_forms_[i]));
    return true;
  }

  scoped_refptr<base::SequencedTaskRunner> GetBackgroundTaskRunner() override {
    return nullptr;
  }

  void SaveFormsOnDestruct(std::vector<PasswordForm>* forms) {
    save_on_destruct_ = forms;
  }

 private:
  void erase(size_t index) {
    if (index < all_forms_.size() - 1)
      all_forms_[index] = all_forms_.back();
    all_forms_.pop_back();
  }

  std::vector<PasswordForm>* save_on_destruct_ = nullptr;
  std::vector<PasswordForm> all_forms_;
};

class MockLoginDatabaseReturn {
 public:
  MOCK_METHOD1(OnLoginDatabaseQueryDone,
               void(const std::vector<std::unique_ptr<PasswordForm>>&));
};

void LoginDatabaseQueryCallback(password_manager::LoginDatabase* login_db,
                                bool autofillable,
                                MockLoginDatabaseReturn* mock_return) {
  std::vector<std::unique_ptr<PasswordForm>> forms;
  if (autofillable)
    EXPECT_TRUE(login_db->GetAutofillableLogins(&forms));
  else
    EXPECT_TRUE(login_db->GetBlacklistLogins(&forms));
  mock_return->OnLoginDatabaseQueryDone(forms);
}

// Generate |count| expected logins, either auto-fillable or blacklisted.
void InitExpectedForms(bool autofillable,
                       size_t count,
                       std::vector<std::unique_ptr<PasswordForm>>* forms) {
  const char* domain = autofillable ? "example" : "blacklisted";
  for (size_t i = 0; i < count; ++i) {
    std::string realm = base::StringPrintf("http://%zu.%s.com", i, domain);
    std::string origin = base::StringPrintf("http://%zu.%s.com/origin",
                                            i, domain);
    std::string action = base::StringPrintf("http://%zu.%s.com/action",
                                            i, domain);
    password_manager::PasswordFormData data = {
        PasswordForm::SCHEME_HTML,
        realm.c_str(),
        origin.c_str(),
        action.c_str(),
        L"submit_element",
        L"username_element",
        L"password_element",
        autofillable ? L"username_value" : nullptr,
        autofillable ? L"password_value" : nullptr,
        autofillable,
        static_cast<double>(i + 1)};
    forms->push_back(FillPasswordFormWithData(data));
  }
}

PasswordStoreChangeList AddChangeForForm(const PasswordForm& form) {
  return PasswordStoreChangeList(
      1, PasswordStoreChange(PasswordStoreChange::ADD, form));
}

enum BackendType {
  NO_BACKEND,
  FAILING_BACKEND,
  WORKING_BACKEND
};

std::unique_ptr<PasswordStoreX::NativeBackend> GetBackend(
    BackendType backend_type) {
  switch (backend_type) {
    case FAILING_BACKEND:
      return std::make_unique<FailingBackend>();
    case WORKING_BACKEND:
      return std::make_unique<MockBackend>();
    default:
      return std::unique_ptr<PasswordStoreX::NativeBackend>();
  }
}

class PasswordStoreXTestDelegate {
 public:
  PasswordStoreX* store() { return store_.get(); }

  void FinishAsyncProcessing();

 protected:
  explicit PasswordStoreXTestDelegate(BackendType backend_type);
  ~PasswordStoreXTestDelegate();

 private:
  void SetupTempDir();

  base::FilePath test_login_db_file_path() const;
  base::FilePath test_encrypted_login_db_file_path() const;

  base::test::ScopedTaskEnvironment task_environment_;
  base::ScopedTempDir temp_dir_;
  BackendType backend_type_;
  scoped_refptr<PasswordStoreX> store_;
  TestingPrefServiceSimple fake_pref_service;

  DISALLOW_COPY_AND_ASSIGN(PasswordStoreXTestDelegate);
};

PasswordStoreXTestDelegate::PasswordStoreXTestDelegate(BackendType backend_type)
    : backend_type_(backend_type) {
  SetupTempDir();
  auto login_db = std::make_unique<password_manager::LoginDatabase>(
      test_login_db_file_path());
  fake_pref_service.registry()->RegisterIntegerPref(
      password_manager::prefs::kMigrationToLoginDBStep,
      PasswordStoreX::NOT_ATTEMPTED);
  store_ = new PasswordStoreX(std::move(login_db), test_login_db_file_path(),
                              test_encrypted_login_db_file_path(),
                              GetBackend(backend_type_), &fake_pref_service);
  store_->Init(syncer::SyncableService::StartSyncFlare(), nullptr);
}

PasswordStoreXTestDelegate::~PasswordStoreXTestDelegate() {
  store_->ShutdownOnUIThread();
}

void PasswordStoreXTestDelegate::FinishAsyncProcessing() {
  task_environment_.RunUntilIdle();
}

void PasswordStoreXTestDelegate::SetupTempDir() {
  ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
}

base::FilePath PasswordStoreXTestDelegate::test_login_db_file_path() const {
  return temp_dir_.GetPath().Append(FILE_PATH_LITERAL("login_test"));
}

base::FilePath PasswordStoreXTestDelegate::test_encrypted_login_db_file_path()
    const {
  return temp_dir_.GetPath().Append(FILE_PATH_LITERAL("encrypted_login_test"));
}

class PasswordStoreXNoBackendTestDelegate : public PasswordStoreXTestDelegate {
 public:
  PasswordStoreXNoBackendTestDelegate()
      : PasswordStoreXTestDelegate(NO_BACKEND) {}
};

class PasswordStoreXWorkingBackendTestDelegate
    : public PasswordStoreXTestDelegate {
 public:
  PasswordStoreXWorkingBackendTestDelegate()
      : PasswordStoreXTestDelegate(WORKING_BACKEND) {}
};

std::vector<std::unique_ptr<PasswordForm>> ReadLoginDB(
    const base::FilePath& path,
    bool encrypted) {
  password_manager::LoginDatabase login_db(path);
  if (!encrypted)
    login_db.disable_encryption();
  EXPECT_TRUE(login_db.Init());
  std::vector<std::unique_ptr<PasswordForm>> stored_forms;
  EXPECT_TRUE(login_db.GetAutofillableLogins(&stored_forms));
  return stored_forms;
}

}  // namespace

namespace password_manager {

INSTANTIATE_TYPED_TEST_CASE_P(XNoBackend,
                              PasswordStoreOriginTest,
                              PasswordStoreXNoBackendTestDelegate);

INSTANTIATE_TYPED_TEST_CASE_P(XWorkingBackend,
                              PasswordStoreOriginTest,
                              PasswordStoreXWorkingBackendTestDelegate);
}

class PasswordStoreXTest : public testing::TestWithParam<BackendType> {
 protected:
  PasswordStoreXTest() = default;

  void SetUp() override {
    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
    fake_pref_service_.registry()->RegisterIntegerPref(
        password_manager::prefs::kMigrationToLoginDBStep,
        PasswordStoreX::NOT_ATTEMPTED);
    OSCryptMocker::SetUp();
  }

  void TearDown() override { OSCryptMocker::TearDown(); }

  base::FilePath test_login_db_file_path() const {
    return temp_dir_.GetPath().Append(FILE_PATH_LITERAL("login_test"));
  }

  base::FilePath test_encrypted_login_db_file_path() const {
    return temp_dir_.GetPath().Append(
        FILE_PATH_LITERAL("encrypted_login_test"));
  }

  void WaitForPasswordStore() { task_environment_.RunUntilIdle(); }

 protected:
  TestingPrefServiceSimple fake_pref_service_;
  base::HistogramTester histogram_tester_;

 private:
  base::test::ScopedTaskEnvironment task_environment_;
  base::ScopedTempDir temp_dir_;

  DISALLOW_COPY_AND_ASSIGN(PasswordStoreXTest);
};

TEST_P(PasswordStoreXTest, Notifications) {
  std::unique_ptr<password_manager::LoginDatabase> login_db(
      new password_manager::LoginDatabase(test_login_db_file_path()));
  scoped_refptr<PasswordStoreX> store(
      new PasswordStoreX(std::move(login_db), test_login_db_file_path(),
                         test_encrypted_login_db_file_path(),
                         GetBackend(GetParam()), &fake_pref_service_));
  store->Init(syncer::SyncableService::StartSyncFlare(), nullptr);

  password_manager::PasswordFormData form_data = {
      PasswordForm::SCHEME_HTML,
      "http://bar.example.com",
      "http://bar.example.com/origin",
      "http://bar.example.com/action",
      L"submit_element",
      L"username_element",
      L"password_element",
      L"username_value",
      L"password_value",
      true,
      1};
  std::unique_ptr<PasswordForm> form = FillPasswordFormWithData(form_data);

  password_manager::MockPasswordStoreObserver observer;
  store->AddObserver(&observer);

  const PasswordStoreChange expected_add_changes[] = {
    PasswordStoreChange(PasswordStoreChange::ADD, *form),
  };

  EXPECT_CALL(
      observer,
      OnLoginsChanged(ElementsAreArray(expected_add_changes)));

  // Adding a login should trigger a notification.
  store->AddLogin(*form);

  WaitForPasswordStore();

  // Change the password.
  form->password_value = base::ASCIIToUTF16("a different password");

  const PasswordStoreChange expected_update_changes[] = {
    PasswordStoreChange(PasswordStoreChange::UPDATE, *form),
  };

  EXPECT_CALL(
      observer,
      OnLoginsChanged(ElementsAreArray(expected_update_changes)));

  // Updating the login with the new password should trigger a notification.
  store->UpdateLogin(*form);

  WaitForPasswordStore();

  const PasswordStoreChange expected_delete_changes[] = {
    PasswordStoreChange(PasswordStoreChange::REMOVE, *form),
  };

  EXPECT_CALL(
      observer,
      OnLoginsChanged(ElementsAreArray(expected_delete_changes)));

  // Deleting the login should trigger a notification.
  store->RemoveLogin(*form);

  WaitForPasswordStore();

  store->RemoveObserver(&observer);

  store->ShutdownOnUIThread();
}

TEST_P(PasswordStoreXTest, NativeMigration) {
  std::vector<std::unique_ptr<PasswordForm>> expected_autofillable;
  InitExpectedForms(true, 5, &expected_autofillable);

  std::vector<std::unique_ptr<PasswordForm>> expected_blacklisted;
  InitExpectedForms(false, 5, &expected_blacklisted);

  const base::FilePath login_db_file = test_login_db_file_path();
  std::unique_ptr<password_manager::LoginDatabase> login_db(
      new password_manager::LoginDatabase(login_db_file));
  login_db->disable_encryption();
  ASSERT_TRUE(login_db->Init());

  // Get the initial size of the login DB file, before we populate it.
  // This will be used later to make sure it gets back to this size.
  base::File::Info db_file_start_info;
  ASSERT_TRUE(base::GetFileInfo(login_db_file, &db_file_start_info));

  // Populate the login DB with logins that should be migrated.
  for (const auto& form : expected_autofillable) {
    EXPECT_EQ(AddChangeForForm(*form), login_db->AddLogin(*form));
  }
  for (const auto& form : expected_blacklisted) {
    EXPECT_EQ(AddChangeForForm(*form), login_db->AddLogin(*form));
  }

  // Get the new size of the login DB file. We expect it to be larger.
  base::File::Info db_file_full_info;
  ASSERT_TRUE(base::GetFileInfo(login_db_file, &db_file_full_info));
  EXPECT_GT(db_file_full_info.size, db_file_start_info.size);

  // Initializing the PasswordStore shouldn't trigger a native migration (yet).
  login_db.reset(new password_manager::LoginDatabase(login_db_file));
  scoped_refptr<PasswordStoreX> store(
      new PasswordStoreX(std::move(login_db), test_login_db_file_path(),
                         test_encrypted_login_db_file_path(),
                         GetBackend(GetParam()), &fake_pref_service_));
  store->Init(syncer::SyncableService::StartSyncFlare(), nullptr);

  MockPasswordStoreConsumer consumer;

  // The autofillable forms should have been migrated to the native backend.
  EXPECT_CALL(consumer,
              OnGetPasswordStoreResultsConstRef(
                  UnorderedPasswordFormElementsAre(&expected_autofillable)));

  store->GetAutofillableLogins(&consumer);
  WaitForPasswordStore();

  // The blacklisted forms should have been migrated to the native backend.
  EXPECT_CALL(consumer,
              OnGetPasswordStoreResultsConstRef(
                  UnorderedPasswordFormElementsAre(&expected_blacklisted)));

  store->GetBlacklistLogins(&consumer);
  WaitForPasswordStore();

  MockLoginDatabaseReturn ld_return;

  if (GetParam() == WORKING_BACKEND) {
    // No autofillable logins should be left in the login DB.
    EXPECT_CALL(ld_return, OnLoginDatabaseQueryDone(IsEmpty()));
  } else {
    // The autofillable logins should still be in the login DB.
    EXPECT_CALL(ld_return,
                OnLoginDatabaseQueryDone(
                    UnorderedPasswordFormElementsAre(&expected_autofillable)));
  }

  LoginDatabaseQueryCallback(store->login_db(), true, &ld_return);

  WaitForPasswordStore();

  if (GetParam() == WORKING_BACKEND) {
    // Likewise, no blacklisted logins should be left in the login DB.
    EXPECT_CALL(ld_return, OnLoginDatabaseQueryDone(IsEmpty()));
  } else {
    // The blacklisted logins should still be in the login DB.
    EXPECT_CALL(ld_return,
                OnLoginDatabaseQueryDone(
                    UnorderedPasswordFormElementsAre(&expected_blacklisted)));
  }

  LoginDatabaseQueryCallback(store->login_db(), false, &ld_return);

  WaitForPasswordStore();

  if (GetParam() == WORKING_BACKEND) {
    // If the migration succeeded, then not only should there be no logins left
    // in the login DB, but also the file should have been deleted and then
    // recreated. We approximate checking for this by checking that the file
    // size is equal to the size before we populated it, even though it was
    // larger after populating it.
    base::File::Info db_file_end_info;
    ASSERT_TRUE(base::GetFileInfo(login_db_file, &db_file_end_info));
    EXPECT_EQ(db_file_start_info.size, db_file_end_info.size);
  }

  store->ShutdownOnUIThread();
}

TEST_P(PasswordStoreXTest, MigrationToEncryption) {
  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndEnableFeature(
      password_manager::features::kMigrateLinuxToLoginDB);
  IntegerPrefMember migration_step_pref_;
  migration_step_pref_.Init(password_manager::prefs::kMigrationToLoginDBStep,
                            &fake_pref_service_);

  EXPECT_EQ(PasswordStoreX::NOT_ATTEMPTED, migration_step_pref_.GetValue());

  // Add existing credentials into the backend.
  std::vector<std::unique_ptr<PasswordForm>> old_credentials;
  InitExpectedForms(true, 6, &old_credentials);
  std::unique_ptr<PasswordStoreX::NativeBackend> backend =
      GetBackend(GetParam());
  std::vector<PasswordForm> native_backend_last_state;
  if (GetParam() == WORKING_BACKEND) {
    static_cast<MockBackend*>(backend.get())
        ->SaveFormsOnDestruct(&native_backend_last_state);
  }
  if (GetParam() != NO_BACKEND) {
    for (int i = 0; i < 3; i++)
      backend->AddLogin(*old_credentials[i]);
  }

  // Add existing credentials into the unencrypted loginDB.
  auto login_db = std::make_unique<password_manager::LoginDatabase>(
      test_login_db_file_path());
  login_db->disable_encryption();
  ASSERT_TRUE(login_db->Init());
  for (int i = 3; i < 6; i++)
    ignore_result(login_db->AddLogin(*old_credentials[i]));

  login_db = std::make_unique<password_manager::LoginDatabase>(
      test_login_db_file_path());
  scoped_refptr<PasswordStoreX> store(
      new PasswordStoreX(std::move(login_db), test_login_db_file_path(),
                         test_encrypted_login_db_file_path(),
                         std::move(backend), &fake_pref_service_));
  store->Init(syncer::SyncableService::StartSyncFlare(), nullptr);

  // Make modifications, so that we trigger the migration and so that we can
  // verify where the store serves from. The migration is triggered
  // opportunistically during access to the store.
  const auto new_form = password_manager::FillPasswordFormWithData(
      {PasswordForm::SCHEME_HTML, "https://www.fakebook.com",
       "https://www.fakebook.com/li", "https://www.fakebook.com/a",
       L"submit_element", L"username_element", L"password_element",
       L"username_value", L"password_value", true, 1.0});
  store->RemoveLogin(*old_credentials[0]);
  store->AddLogin(*new_form);

  MockPasswordStoreConsumer consumer;
  if (GetParam() == WORKING_BACKEND) {
    // The store has the native backend data, the initial unencrypted loginDB
    // data and modifications.
    EXPECT_CALL(
        consumer,
        OnGetPasswordStoreResultsConstRef(UnorderedElementsAre(
            Pointee(*new_form), Pointee(*old_credentials[1]),
            Pointee(*old_credentials[2]), Pointee(*old_credentials[3]),
            Pointee(*old_credentials[4]), Pointee(*old_credentials[5]))));
  } else {
    // The has the initial unencrypted loginDB data and modifications.
    EXPECT_CALL(
        consumer,
        OnGetPasswordStoreResultsConstRef(UnorderedElementsAre(
            Pointee(*new_form), Pointee(*old_credentials[3]),
            Pointee(*old_credentials[4]), Pointee(*old_credentials[5]))));
  }
  store->GetAutofillableLogins(&consumer);

  WaitForPasswordStore();
  store->ShutdownOnUIThread();
  store.reset();
  WaitForPasswordStore();

  // This will report that it was migrated on the next run.
  histogram_tester_.ExpectBucketCount(
      "PasswordManager.LinuxBackendMigration.Adoption",
      LinuxBackendMigrationStatus::kNotAttempted, 1);

  if (GetParam() == WORKING_BACKEND) {
    // Verify that the login database contains all the values, now encrypted.
    std::vector<std::unique_ptr<PasswordForm>> stored_forms =
        ReadLoginDB(test_login_db_file_path(), true);
    EXPECT_EQ(6u, stored_forms.size());
    EXPECT_THAT(
        stored_forms,
        UnorderedElementsAre(
            Pointee(*new_form), Pointee(*old_credentials[1]),
            Pointee(*old_credentials[2]), Pointee(*old_credentials[3]),
            Pointee(*old_credentials[4]), Pointee(*old_credentials[5])));
    EXPECT_TRUE(native_backend_last_state.empty());

    stored_forms = ReadLoginDB(test_encrypted_login_db_file_path(), false);
    EXPECT_TRUE(stored_forms.empty());
    EXPECT_EQ(PasswordStoreX::LOGIN_DB_REPLACED,
              migration_step_pref_.GetValue());

    histogram_tester_.ExpectBucketCount(
        "PasswordManager.LinuxBackendMigration.AttemptResult",
        LinuxBackendMigrationStatus::kLoginDBReplaced, 1);
  } else if (GetParam() == FAILING_BACKEND) {
    // No values should be written if we can't read the backend.
    auto stored_forms = ReadLoginDB(test_encrypted_login_db_file_path(), true);
    EXPECT_TRUE(stored_forms.empty());
    EXPECT_THAT(migration_step_pref_.GetValue(), PasswordStoreX::POSTPONED);

    histogram_tester_.ExpectBucketCount(
        "PasswordManager.LinuxBackendMigration.AttemptResult",
        LinuxBackendMigrationStatus::kPostponed, 1);
  } else {  // NO_BACKEND
    // No values should be moved without a working backend.
    auto stored_forms = ReadLoginDB(test_encrypted_login_db_file_path(), true);
    EXPECT_TRUE(stored_forms.empty());
    EXPECT_THAT(migration_step_pref_.GetValue(), PasswordStoreX::NOT_ATTEMPTED);
  }
}

// Once the migration is performed, don't port anything else into the new
// location.
TEST_P(PasswordStoreXTest, MigrationToEncryption_OnlyOnce) {
  if (GetParam() != WORKING_BACKEND)
    return;

  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndEnableFeature(
      password_manager::features::kMigrateLinuxToLoginDB);
  IntegerPrefMember migration_step_pref_;
  migration_step_pref_.Init(password_manager::prefs::kMigrationToLoginDBStep,
                            &fake_pref_service_);
  // Signal that the migration has been completed.
  migration_step_pref_.SetValue(PasswordStoreX::LOGIN_DB_REPLACED);

  // We add new credentials into a backend. They should be completely ignored by
  // the store.
  std::vector<std::unique_ptr<PasswordForm>> old_credentials;
  InitExpectedForms(true, 6, &old_credentials);
  auto backend = GetBackend(GetParam());
  for (int i = 0; i < 3; i++)
    backend->AddLogin(*old_credentials[i]);

  // Add existing credentials into loginDB. They should be the only thing that's
  // available in the store.
  auto login_db = std::make_unique<password_manager::LoginDatabase>(
      test_login_db_file_path());
  ASSERT_TRUE(login_db->Init());
  for (int i = 3; i < 6; i++)
    ignore_result(login_db->AddLogin(*old_credentials[i]));
  login_db.reset();

  // Create the store.
  login_db = std::make_unique<password_manager::LoginDatabase>(
      test_login_db_file_path());
  scoped_refptr<PasswordStoreX> store =
      new PasswordStoreX(std::move(login_db), test_login_db_file_path(),
                         test_encrypted_login_db_file_path(),
                         std::move(backend), &fake_pref_service_);
  store->Init(syncer::SyncableService::StartSyncFlare(), nullptr);

  // Make modifications and check the contents.
  MockPasswordStoreConsumer consumer;
  EXPECT_CALL(consumer,
              OnGetPasswordStoreResultsConstRef(UnorderedElementsAre(
                  Pointee(*old_credentials[3]), Pointee(*old_credentials[4]),
                  Pointee(*old_credentials[5]))));
  store->GetAutofillableLogins(&consumer);
  store->RemoveLogin(*old_credentials[3]);
  EXPECT_CALL(consumer,
              OnGetPasswordStoreResultsConstRef(UnorderedElementsAre(
                  Pointee(*old_credentials[4]), Pointee(*old_credentials[5]))));
  store->GetAutofillableLogins(&consumer);

  WaitForPasswordStore();
  store->ShutdownOnUIThread();
  store.reset();
  WaitForPasswordStore();

  // The previous results were served from an encrypted login database.
  std::vector<std::unique_ptr<PasswordForm>> stored_forms =
      ReadLoginDB(test_login_db_file_path(), true);
  EXPECT_EQ(2u, stored_forms.size());
  EXPECT_EQ(PasswordStoreX::LOGIN_DB_REPLACED, migration_step_pref_.GetValue());
  EXPECT_THAT(stored_forms, UnorderedElementsAre(Pointee(*old_credentials[4]),
                                                 Pointee(*old_credentials[5])));

  histogram_tester_.ExpectBucketCount(
      "PasswordManager.LinuxBackendMigration.Adoption",
      LinuxBackendMigrationStatus::kLoginDBReplaced, 1);
  histogram_tester_.ExpectTotalCount(
      "PasswordManager.LinuxBackendMigration.AttemptResult", 0);
}

INSTANTIATE_TEST_CASE_P(NoBackend,
                        PasswordStoreXTest,
                        testing::Values(NO_BACKEND));
INSTANTIATE_TEST_CASE_P(FailingBackend,
                        PasswordStoreXTest,
                        testing::Values(FAILING_BACKEND));
INSTANTIATE_TEST_CASE_P(WorkingBackend,
                        PasswordStoreXTest,
                        testing::Values(WORKING_BACKEND));
