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

#include <memory>
#include <string>
#include <vector>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/files/scoped_temp_dir.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/task_scheduler/post_task.h"
#include "base/test/histogram_tester.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "chrome/test/base/testing_profile.h"
#include "components/os_crypt/ie7_password_win.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.h"
#include "components/password_manager/core/browser/password_store_consumer.h"
#include "components/password_manager/core/browser/webdata/logins_table.h"
#include "components/password_manager/core/browser/webdata/password_web_data_service_win.h"
#include "components/webdata/common/web_database_service.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "crypto/wincrypt_shim.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using autofill::PasswordForm;
using password_manager::LoginDatabase;
using password_manager::PasswordFormData;
using password_manager::PasswordStore;
using password_manager::PasswordStoreConsumer;
using password_manager::UnorderedPasswordFormElementsAre;
using testing::_;
using testing::DoAll;
using testing::IsEmpty;
using testing::WithArg;

namespace {

class MockPasswordStoreConsumer : public 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 MockWebDataServiceConsumer : public WebDataServiceConsumer {
 public:
  MOCK_METHOD0(OnWebDataServiceRequestDoneStub, void());

  // GMock cannot mock methods with move-only args.
  void OnWebDataServiceRequestDone(WebDataServiceBase::Handle h,
                                   std::unique_ptr<WDTypedResult> result) {
    OnWebDataServiceRequestDoneStub();
  }
};

}  // anonymous namespace

class PasswordStoreWinTest : public testing::Test {
 protected:
  PasswordStoreWinTest() {}

  bool CreateIE7PasswordInfo(const std::wstring& url,
                             const base::Time& created,
                             IE7PasswordInfo* info) {
    // Copied from chrome/browser/importer/importer_unittest.cc
    // The username is "abcdefgh" and the password "abcdefghijkl".
    unsigned char data[] =
        "\x0c\x00\x00\x00\x38\x00\x00\x00\x2c\x00\x00\x00"
        "\x57\x49\x43\x4b\x18\x00\x00\x00\x02\x00\x00\x00"
        "\x67\x00\x72\x00\x01\x00\x00\x00\x00\x00\x00\x00"
        "\x00\x00\x00\x00\x4e\xfa\x67\x76\x22\x94\xc8\x01"
        "\x08\x00\x00\x00\x12\x00\x00\x00\x4e\xfa\x67\x76"
        "\x22\x94\xc8\x01\x0c\x00\x00\x00\x61\x00\x62\x00"
        "\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00"
        "\x00\x00\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00"
        "\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00"
        "\x6c\x00\x00\x00";
    DATA_BLOB input = {0};
    DATA_BLOB url_key = {0};
    DATA_BLOB output = {0};

    input.pbData = data;
    input.cbData = sizeof(data);

    url_key.pbData =
        reinterpret_cast<unsigned char*>(const_cast<wchar_t*>(url.data()));
    url_key.cbData =
        static_cast<DWORD>((url.size() + 1) * sizeof(std::wstring::value_type));

    if (!CryptProtectData(&input, nullptr, &url_key, nullptr, nullptr,
                          CRYPTPROTECT_UI_FORBIDDEN, &output))
      return false;

    std::vector<unsigned char> encrypted_data;
    encrypted_data.resize(output.cbData);
    memcpy(&encrypted_data.front(), output.pbData, output.cbData);

    LocalFree(output.pbData);

    info->url_hash = ie7_password::GetUrlHash(url);
    info->encrypted_data = encrypted_data;
    info->date_created = created;

    return true;
  }

  void SetUp() override {
    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());

    profile_.reset(new TestingProfile());

    base::FilePath path = temp_dir_.GetPath().AppendASCII("web_data_test");
    // TODO(pkasting): http://crbug.com/740773 This should likely be sequenced,
    // not single-threaded.
    auto db_thread =
        base::CreateSingleThreadTaskRunnerWithTraits({base::MayBlock()});
    wdbs_ = new WebDatabaseService(path, base::ThreadTaskRunnerHandle::Get(),
                                   db_thread);
    // Need to add at least one table so the database gets created.
    wdbs_->AddTable(std::unique_ptr<WebDatabaseTable>(new LoginsTable()));
    wdbs_->LoadDatabase();
    wds_ =
        new PasswordWebDataService(wdbs_, base::ThreadTaskRunnerHandle::Get(),
                                   WebDataServiceBase::ProfileErrorCallback());
    wds_->Init();
  }

  void TearDown() override {
    if (store_.get())
      store_->ShutdownOnUIThread();
    if (wds_) {
      wds_->ShutdownOnUIThread();
      wds_ = nullptr;
    }
    if (wdbs_) {
      wdbs_->ShutdownDatabase();
      wdbs_ = nullptr;
    }
    content::RunAllBlockingPoolTasksUntilIdle();
  }

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

  PasswordStoreWin* CreatePasswordStore() {
    return new PasswordStoreWin(
        base::SequencedTaskRunnerHandle::Get(),
        base::SequencedTaskRunnerHandle::Get(),
        base::MakeUnique<LoginDatabase>(test_login_db_file_path()), wds_.get());
  }

  content::TestBrowserThreadBundle test_browser_thread_bundle_;

  base::ScopedTempDir temp_dir_;
  std::unique_ptr<TestingProfile> profile_;
  scoped_refptr<PasswordWebDataService> wds_;
  scoped_refptr<WebDatabaseService> wdbs_;
  scoped_refptr<PasswordStore> store_;
};

MATCHER(EmptyWDResult, "") {
  return static_cast<
             const WDResult<std::vector<std::unique_ptr<PasswordForm>>>*>(arg)
      ->GetValue()
      .empty();
}

TEST_F(PasswordStoreWinTest, ReportIE7NoImport) {
  base::HistogramTester histogram_tester;

  store_ = CreatePasswordStore();
  EXPECT_TRUE(store_->Init(syncer::SyncableService::StartSyncFlare(), nullptr));

  MockPasswordStoreConsumer consumer;

  PasswordStore::FormDigest observed_form(PasswordForm::SCHEME_HTML,
                                          "http://example.com/origin",
                                          GURL("http://example.com/origin"));

  EXPECT_CALL(consumer, OnGetPasswordStoreResultsConstRef(_));
  store_->GetLogins(observed_form, &consumer);
  content::RunAllBlockingPoolTasksUntilIdle();
  histogram_tester.ExpectUniqueSample(
      "PasswordManager.IE7LookupResult",
      password_manager::metrics_util::IE7_RESULTS_ABSENT, 1);
}

TEST_F(PasswordStoreWinTest, ReportIE7Import) {
  base::HistogramTester histogram_tester;

  IE7PasswordInfo password_info;
  ASSERT_TRUE(CreateIE7PasswordInfo(L"http://example.com/origin",
                                    base::Time::FromDoubleT(1),
                                    &password_info));
  // This IE7 password will be retrieved by the GetLogins call.
  wds_->AddIE7Login(password_info);

  store_ = CreatePasswordStore();
  EXPECT_TRUE(store_->Init(syncer::SyncableService::StartSyncFlare(), nullptr));

  MockPasswordStoreConsumer consumer;

  PasswordStore::FormDigest observed_form(PasswordForm::SCHEME_HTML,
                                          "http://example.com/origin",
                                          GURL("http://example.com/origin"));

  EXPECT_CALL(consumer, OnGetPasswordStoreResultsConstRef(_));
  store_->GetLogins(observed_form, &consumer);
  content::RunAllBlockingPoolTasksUntilIdle();
  histogram_tester.ExpectUniqueSample(
      "PasswordManager.IE7LookupResult",
      password_manager::metrics_util::IE7_RESULTS_PRESENT, 1);
}

// Hangs flakily, http://crbug.com/71385.
TEST_F(PasswordStoreWinTest, DISABLED_ConvertIE7Login) {
  IE7PasswordInfo password_info;
  ASSERT_TRUE(CreateIE7PasswordInfo(L"http://example.com/origin",
                                    base::Time::FromDoubleT(1),
                                    &password_info));
  // Verify the URL hash
  ASSERT_EQ(L"39471418FF5453FEEB3731E382DEB5D53E14FAF9B5",
            password_info.url_hash);

  // This IE7 password will be retrieved by the GetLogins call.
  wds_->AddIE7Login(password_info);

  store_ = CreatePasswordStore();
  EXPECT_TRUE(store_->Init(syncer::SyncableService::StartSyncFlare(), nullptr));

  MockPasswordStoreConsumer consumer;

  PasswordFormData form_data = {
      PasswordForm::SCHEME_HTML,
      "http://example.com/",
      "http://example.com/origin",
      "http://example.com/action",
      L"submit_element",
      L"username_element",
      L"password_element",
      L"",
      L"",
      true,
      1,
  };
  PasswordStore::FormDigest form(
      *CreatePasswordFormFromDataForTesting(form_data));

  // The returned form will not have 'action' or '*_element' fields set. This
  // is because credentials imported from IE don't have this information.
  PasswordFormData expected_form_data = {
      PasswordForm::SCHEME_HTML,
      "http://example.com/",
      "http://example.com/origin",
      "",
      L"",
      L"",
      L"",
      L"abcdefgh",
      L"abcdefghijkl",
      true,
      1,
  };
  std::vector<std::unique_ptr<PasswordForm>> expected_forms;
  expected_forms.push_back(
      CreatePasswordFormFromDataForTesting(expected_form_data));

  // The IE7 password should be returned.
  EXPECT_CALL(consumer, OnGetPasswordStoreResultsConstRef(
                            UnorderedPasswordFormElementsAre(&expected_forms)));

  store_->GetLogins(form, &consumer);
  content::RunAllBlockingPoolTasksUntilIdle();
}

TEST_F(PasswordStoreWinTest, OutstandingWDSQueries) {
  store_ = CreatePasswordStore();
  EXPECT_TRUE(store_->Init(syncer::SyncableService::StartSyncFlare(), nullptr));

  PasswordFormData form_data = {
      PasswordForm::SCHEME_HTML,
      "http://example.com/",
      "http://example.com/origin",
      "http://example.com/action",
      L"submit_element",
      L"username_element",
      L"password_element",
      L"",
      L"",
      true,
      1,
  };
  PasswordStore::FormDigest form(
      *CreatePasswordFormFromDataForTesting(form_data));

  MockPasswordStoreConsumer consumer;
  store_->GetLogins(form, &consumer);

  // Release the PSW and the WDS before the query can return.
  store_->ShutdownOnUIThread();
  store_ = nullptr;
  wds_->ShutdownOnUIThread();
  wds_ = nullptr;
  wdbs_->ShutdownDatabase();
  wdbs_ = nullptr;

  content::RunAllBlockingPoolTasksUntilIdle();
}

// Hangs flakily, see http://crbug.com/43836.
TEST_F(PasswordStoreWinTest, DISABLED_MultipleWDSQueriesOnDifferentThreads) {
  IE7PasswordInfo password_info;
  ASSERT_TRUE(CreateIE7PasswordInfo(L"http://example.com/origin",
                                    base::Time::FromDoubleT(1),
                                    &password_info));
  wds_->AddIE7Login(password_info);

  store_ = CreatePasswordStore();
  EXPECT_TRUE(store_->Init(syncer::SyncableService::StartSyncFlare(), nullptr));

  MockPasswordStoreConsumer password_consumer;

  PasswordFormData form_data = {
      PasswordForm::SCHEME_HTML,
      "http://example.com/",
      "http://example.com/origin",
      "http://example.com/action",
      L"submit_element",
      L"username_element",
      L"password_element",
      L"",
      L"",
      true,
      1,
  };
  PasswordStore::FormDigest form(
      *CreatePasswordFormFromDataForTesting(form_data));

  PasswordFormData expected_form_data = {
      PasswordForm::SCHEME_HTML,
      "http://example.com/",
      "http://example.com/origin",
      "http://example.com/action",
      L"submit_element",
      L"username_element",
      L"password_element",
      L"abcdefgh",
      L"abcdefghijkl",
      true,
      1,
  };
  std::vector<std::unique_ptr<PasswordForm>> expected_forms;
  expected_forms.push_back(
      CreatePasswordFormFromDataForTesting(expected_form_data));

  // The IE7 password should be returned.
  EXPECT_CALL(password_consumer,
              OnGetPasswordStoreResultsConstRef(
                  UnorderedPasswordFormElementsAre(&expected_forms)));

  store_->GetLogins(form, &password_consumer);

  MockWebDataServiceConsumer wds_consumer;
  EXPECT_CALL(wds_consumer, OnWebDataServiceRequestDoneStub());
  wds_->GetIE7Login(password_info, &wds_consumer);

  content::RunAllBlockingPoolTasksUntilIdle();
}

TEST_F(PasswordStoreWinTest, EmptyLogins) {
  store_ = CreatePasswordStore();
  store_->Init(syncer::SyncableService::StartSyncFlare(), nullptr);

  PasswordFormData form_data = {
      PasswordForm::SCHEME_HTML,
      "http://example.com/",
      "http://example.com/origin",
      "http://example.com/action",
      L"submit_element",
      L"username_element",
      L"password_element",
      L"",
      L"",
      true,
      1,
  };
  PasswordStore::FormDigest form(
      *CreatePasswordFormFromDataForTesting(form_data));

  MockPasswordStoreConsumer consumer;
  EXPECT_CALL(consumer, OnGetPasswordStoreResultsConstRef(IsEmpty()));
  store_->GetLogins(form, &consumer);

  content::RunAllBlockingPoolTasksUntilIdle();
}

TEST_F(PasswordStoreWinTest, EmptyBlacklistLogins) {
  store_ = CreatePasswordStore();
  store_->Init(syncer::SyncableService::StartSyncFlare(), nullptr);

  MockPasswordStoreConsumer consumer;
  EXPECT_CALL(consumer, OnGetPasswordStoreResultsConstRef(IsEmpty()));
  store_->GetBlacklistLogins(&consumer);

  content::RunAllBlockingPoolTasksUntilIdle();
}

TEST_F(PasswordStoreWinTest, EmptyAutofillableLogins) {
  store_ = CreatePasswordStore();
  store_->Init(syncer::SyncableService::StartSyncFlare(), nullptr);

  MockPasswordStoreConsumer consumer;
  EXPECT_CALL(consumer, OnGetPasswordStoreResultsConstRef(IsEmpty()));
  store_->GetAutofillableLogins(&consumer);

  content::RunAllBlockingPoolTasksUntilIdle();
}
