| Index: chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc
|
| diff --git a/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc
|
| index 13cbf2d989828ed76abc232bf2888e19a5e651d5..51c6ff26ad1d3df2221851fd57efc85ea759fe61 100644
|
| --- a/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc
|
| +++ b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc
|
| @@ -10,14 +10,22 @@
|
|
|
| #include "base/bind.h"
|
| #include "base/memory/ptr_util.h"
|
| +#include "base/stl_util.h"
|
| +#include "base/threading/thread_task_runner_handle.h"
|
| +#include "chrome/browser/chromeos/login/quick_unlock/pin_backend.h"
|
| +#include "chrome/browser/chromeos/login/quick_unlock/pin_storage_prefs.h"
|
| #include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_factory.h"
|
| #include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_storage.h"
|
| #include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.h"
|
| #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
|
| #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
|
| +#include "chrome/browser/chromeos/profiles/profile_helper.h"
|
| #include "chrome/browser/extensions/extension_api_unittest.h"
|
| #include "chrome/common/pref_names.h"
|
| +#include "chromeos/cryptohome/mock_homedir_methods.h"
|
| +#include "chromeos/cryptohome/system_salt_getter.h"
|
| #include "chromeos/login/auth/fake_extended_authenticator.h"
|
| +#include "content/public/test/test_utils.h"
|
| #include "extensions/browser/api_test_utils.h"
|
| #include "extensions/browser/extension_function_dispatcher.h"
|
|
|
| @@ -30,6 +38,10 @@ using QuickUnlockMode = quick_unlock_private::QuickUnlockMode;
|
| using QuickUnlockModeList = std::vector<QuickUnlockMode>;
|
| using CredentialList = std::vector<std::string>;
|
|
|
| +using ::testing::Invoke;
|
| +using ::testing::WithArgs;
|
| +using ::testing::_;
|
| +
|
| namespace chromeos {
|
| namespace {
|
|
|
| @@ -66,7 +78,9 @@ enum ExpectedPinState {
|
|
|
| } // namespace
|
|
|
| -class QuickUnlockPrivateUnitTest : public ExtensionApiUnittest {
|
| +class QuickUnlockPrivateUnitTest
|
| + : public ExtensionApiUnittest,
|
| + public ::testing::WithParamInterface<quick_unlock::PinStorageType> {
|
| public:
|
| QuickUnlockPrivateUnitTest()
|
| : fake_user_manager_(new FakeChromeUserManager()),
|
| @@ -76,17 +90,58 @@ class QuickUnlockPrivateUnitTest : public ExtensionApiUnittest {
|
| void SetUp() override {
|
| ExtensionApiUnittest::SetUp();
|
|
|
| - quick_unlock::EnableForTesting(quick_unlock::PinStorageType::kPrefs);
|
| + quick_unlock::EnableForTesting(GetParam());
|
| +
|
| + quick_unlock::PinBackend::ResetForTesting();
|
| + run_loop_ = base::MakeUnique<base::RunLoop>();
|
| +
|
| + // PinBackend will run cryptohome routines even if we're just using the pref
|
| + // backend. Make sure it has the globals needed.
|
| + SystemSaltGetter::Get()->SetRawSaltForTesting({1, 2, 3, 4, 5, 6, 7, 8});
|
| +
|
| + homedir_methods_ = new cryptohome::MockHomedirMethods();
|
| + ON_CALL(*homedir_methods_, GetKeyDataEx(_, _, _))
|
| + .WillByDefault(WithArgs<2>(
|
| + Invoke(this, &QuickUnlockPrivateUnitTest::DoGetKeyDataCallback)));
|
| + ON_CALL(*homedir_methods_, AddKeyEx(_, _, _, _, _))
|
| + .WillByDefault(WithArgs<2, 4>(
|
| + Invoke(this, &QuickUnlockPrivateUnitTest::DoAddKeyCallback)));
|
| + ON_CALL(*homedir_methods_, RemoveKeyEx(_, _, _, _))
|
| + .WillByDefault(WithArgs<2, 3>(
|
| + Invoke(this, &QuickUnlockPrivateUnitTest::DoRemoveKeyCallback)));
|
| +
|
| + // InitializeForTesting takes ownership over |homedir_methods_|.
|
| + cryptohome::HomedirMethods::InitializeForTesting(homedir_methods_);
|
|
|
| // Setup a primary user.
|
| auto test_account = AccountId::FromUserEmail(kTestUserEmail);
|
| fake_user_manager_->AddUser(test_account);
|
| fake_user_manager_->UserLoggedIn(test_account, kTestUserEmailHash, false);
|
| + chromeos::ProfileHelper::Get()->SetUserToProfileMappingForTesting(
|
| + fake_user_manager_->GetPrimaryUser(), GetProfile());
|
|
|
| + modes_changed_handler_ = base::Bind(&DoNothing);
|
| // Ensure that quick unlock is turned off.
|
| SetModes(QuickUnlockModeList{}, CredentialList{});
|
| + }
|
|
|
| - modes_changed_handler_ = base::Bind(&DoNothing);
|
| + void TearDown() override {
|
| + PumpRunLoop();
|
| + run_loop_.reset();
|
| +
|
| + homedir_methods_ = nullptr;
|
| + fake_user_manager_ = nullptr;
|
| +
|
| + ExtensionApiUnittest::TearDown();
|
| + cryptohome::HomedirMethods::Shutdown();
|
| + }
|
| +
|
| + // Executes all pending tasks.
|
| + void PumpRunLoop() {
|
| + base::ThreadTaskRunnerHandle::Get()->PostTask(
|
| + FROM_HERE, run_loop_->QuitWhenIdleClosure());
|
| + run_loop_->Run();
|
| + run_loop_ = base::MakeUnique<base::RunLoop>();
|
| }
|
|
|
| // If a mode change event is raised, fail the test.
|
| @@ -273,16 +328,34 @@ class QuickUnlockPrivateUnitTest : public ExtensionApiUnittest {
|
| CredentialList{});
|
| }
|
|
|
| + // Returns if the pin is set in the backend.
|
| + bool IsPinSetInBackend() {
|
| + const AccountId account_id = AccountId::FromUserEmail(kTestUserEmail);
|
| +
|
| + bool is_set = false;
|
| + quick_unlock::PinBackend::IsSet(
|
| + account_id,
|
| + base::Bind([](bool* result, bool is_set) { *result = is_set; },
|
| + &is_set));
|
| +
|
| + PumpRunLoop();
|
| +
|
| + return is_set;
|
| + }
|
| +
|
| private:
|
| // Runs the given |func| with the given |params|.
|
| std::unique_ptr<base::Value> RunFunction(
|
| scoped_refptr<UIThreadExtensionFunction> func,
|
| std::unique_ptr<base::ListValue> params) {
|
| - return std::unique_ptr<base::Value>(
|
| + PumpRunLoop();
|
| + auto result = std::unique_ptr<base::Value>(
|
| api_test_utils::RunFunctionWithDelegateAndReturnSingleResult(
|
| func, std::move(params), profile(),
|
| base::MakeUnique<ExtensionFunctionDispatcher>(profile()),
|
| api_test_utils::NONE));
|
| + PumpRunLoop();
|
| + return result;
|
| }
|
|
|
| // Verifies a mode change event is raised and that |expected| is now the
|
| @@ -293,7 +366,35 @@ class QuickUnlockPrivateUnitTest : public ExtensionApiUnittest {
|
| expect_modes_changed_ = false;
|
| }
|
|
|
| - FakeChromeUserManager* fake_user_manager_;
|
| + // Methods used to setup the mock homedir methods instance.
|
| + void DoGetKeyDataCallback(
|
| + const cryptohome::HomedirMethods::GetKeyDataCallback& callback) {
|
| + callback.Run(true, cryptohome::MountError::MOUNT_ERROR_NONE, keys_);
|
| + }
|
| +
|
| + void DoAddKeyCallback(const cryptohome::KeyDefinition& key,
|
| + const cryptohome::HomedirMethods::Callback& callback) {
|
| + keys_.push_back(key);
|
| + callback.Run(true, cryptohome::MountError::MOUNT_ERROR_NONE);
|
| + }
|
| +
|
| + void DoRemoveKeyCallback(
|
| + const std::string& label,
|
| + const cryptohome::HomedirMethods::Callback& callback) {
|
| + base::EraseIf(keys_, [&label](const cryptohome::KeyDefinition& key) {
|
| + return key.label == label;
|
| + });
|
| + callback.Run(true, cryptohome::MountError::MOUNT_ERROR_NONE);
|
| + }
|
| +
|
| + // Run loop that collects all pending tasks. Use |PumpRunLoop| to run them.
|
| + std::unique_ptr<base::RunLoop> run_loop_;
|
| +
|
| + // Keys registered on cryptohome.
|
| + std::vector<cryptohome::KeyDefinition> keys_;
|
| +
|
| + cryptohome::MockHomedirMethods* homedir_methods_ = nullptr; // Unowned
|
| + FakeChromeUserManager* fake_user_manager_ = nullptr;
|
| ScopedUserManagerEnabler scoped_user_manager_;
|
| QuickUnlockPrivateSetModesFunction::ModesChangedEventHandler
|
| modes_changed_handler_;
|
| @@ -303,19 +404,19 @@ class QuickUnlockPrivateUnitTest : public ExtensionApiUnittest {
|
| };
|
|
|
| // Verify that password checking works.
|
| -TEST_F(QuickUnlockPrivateUnitTest, CheckPassword) {
|
| +TEST_P(QuickUnlockPrivateUnitTest, CheckPassword) {
|
| EXPECT_TRUE(CheckPassword(kValidPassword));
|
| EXPECT_FALSE(CheckPassword(kInvalidPassword));
|
| }
|
|
|
| // Verifies that this returns PIN for GetAvailableModes.
|
| -TEST_F(QuickUnlockPrivateUnitTest, GetAvailableModes) {
|
| +TEST_P(QuickUnlockPrivateUnitTest, GetAvailableModes) {
|
| EXPECT_EQ(GetAvailableModes(),
|
| QuickUnlockModeList{QuickUnlockMode::QUICK_UNLOCK_MODE_PIN});
|
| }
|
|
|
| // Verifies that an invalid password cannot be used to update the mode list.
|
| -TEST_F(QuickUnlockPrivateUnitTest, SetModesFailsWithInvalidPassword) {
|
| +TEST_P(QuickUnlockPrivateUnitTest, SetModesFailsWithInvalidPassword) {
|
| // Verify there is no active mode.
|
| EXPECT_EQ(GetActiveModes(), QuickUnlockModeList{});
|
|
|
| @@ -330,7 +431,7 @@ TEST_F(QuickUnlockPrivateUnitTest, SetModesFailsWithInvalidPassword) {
|
|
|
| // Verifies that the quickUnlockPrivate.onActiveModesChanged is only raised when
|
| // the active set of modes changes.
|
| -TEST_F(QuickUnlockPrivateUnitTest, ModeChangeEventOnlyRaisedWhenModesChange) {
|
| +TEST_P(QuickUnlockPrivateUnitTest, ModeChangeEventOnlyRaisedWhenModesChange) {
|
| // Make sure quick unlock is turned off, and then verify that turning it off
|
| // again does not trigger an event.
|
| EXPECT_TRUE(SetModes(QuickUnlockModeList{}, CredentialList{}));
|
| @@ -352,10 +453,7 @@ TEST_F(QuickUnlockPrivateUnitTest, ModeChangeEventOnlyRaisedWhenModesChange) {
|
|
|
| // Ensures that quick unlock can be enabled and disabled by checking the result
|
| // of quickUnlockPrivate.GetActiveModes and PinStorage::IsPinSet.
|
| -TEST_F(QuickUnlockPrivateUnitTest, SetModesAndGetActiveModes) {
|
| - quick_unlock::QuickUnlockStorage* quick_unlock_storage =
|
| - quick_unlock::QuickUnlockFactory::GetForProfile(profile());
|
| -
|
| +TEST_P(QuickUnlockPrivateUnitTest, SetModesAndGetActiveModes) {
|
| // Update mode to PIN raises an event and updates GetActiveModes.
|
| ExpectModesChanged(
|
| QuickUnlockModeList{QuickUnlockMode::QUICK_UNLOCK_MODE_PIN});
|
| @@ -363,42 +461,49 @@ TEST_F(QuickUnlockPrivateUnitTest, SetModesAndGetActiveModes) {
|
| QuickUnlockModeList{QuickUnlockMode::QUICK_UNLOCK_MODE_PIN}, {"111111"}));
|
| EXPECT_EQ(GetActiveModes(),
|
| QuickUnlockModeList{QuickUnlockMode::QUICK_UNLOCK_MODE_PIN});
|
| - EXPECT_TRUE(quick_unlock_storage->pin_storage()->IsPinSet());
|
| + EXPECT_TRUE(IsPinSetInBackend());
|
|
|
| // SetModes can be used to turn off a quick unlock mode.
|
| ExpectModesChanged(QuickUnlockModeList{});
|
| EXPECT_TRUE(SetModes(QuickUnlockModeList{}, CredentialList{}));
|
| EXPECT_EQ(GetActiveModes(), QuickUnlockModeList{});
|
| - EXPECT_FALSE(quick_unlock_storage->pin_storage()->IsPinSet());
|
| + EXPECT_FALSE(IsPinSetInBackend());
|
| }
|
|
|
| // Verifies that enabling PIN quick unlock actually talks to the PIN subsystem.
|
| -TEST_F(QuickUnlockPrivateUnitTest, VerifyAuthenticationAgainstPIN) {
|
| +TEST_P(QuickUnlockPrivateUnitTest, VerifyAuthenticationAgainstPIN) {
|
| + // Cryptohome authentication does not go through PinBackend at the moment and
|
| + // cannot be easily tested.
|
| + if (GetParam() == quick_unlock::PinStorageType::kCryptohome)
|
| + return;
|
| +
|
| quick_unlock::QuickUnlockStorage* quick_unlock_storage =
|
| quick_unlock::QuickUnlockFactory::GetForProfile(profile());
|
| + quick_unlock::PinStoragePrefs* pin_storage =
|
| + quick_unlock_storage->pin_storage_prefs();
|
|
|
| EXPECT_TRUE(SetModes(QuickUnlockModeList{}, CredentialList{}));
|
| - EXPECT_FALSE(quick_unlock_storage->pin_storage()->IsPinSet());
|
| + EXPECT_FALSE(IsPinSetInBackend());
|
|
|
| EXPECT_TRUE(SetModes(
|
| QuickUnlockModeList{QuickUnlockMode::QUICK_UNLOCK_MODE_PIN}, {"111111"}));
|
| - EXPECT_TRUE(quick_unlock_storage->pin_storage()->IsPinSet());
|
| + EXPECT_TRUE(IsPinSetInBackend());
|
|
|
| quick_unlock_storage->MarkStrongAuth();
|
| - quick_unlock_storage->pin_storage()->ResetUnlockAttemptCount();
|
| - EXPECT_TRUE(quick_unlock_storage->TryAuthenticatePin("111111"));
|
| - EXPECT_FALSE(quick_unlock_storage->TryAuthenticatePin("000000"));
|
| + pin_storage->ResetUnlockAttemptCount();
|
| + EXPECT_TRUE(pin_storage->TryAuthenticatePin("111111"));
|
| + EXPECT_FALSE(pin_storage->TryAuthenticatePin("000000"));
|
| }
|
|
|
| // Verifies that the number of modes and the number of passwords given must be
|
| // the same.
|
| -TEST_F(QuickUnlockPrivateUnitTest, ThrowErrorOnMismatchedParameterCount) {
|
| +TEST_P(QuickUnlockPrivateUnitTest, ThrowErrorOnMismatchedParameterCount) {
|
| EXPECT_FALSE(SetModesWithError("[\"valid\", [\"PIN\"], []]").empty());
|
| EXPECT_FALSE(SetModesWithError("[\"valid\", [], [\"11\"]]").empty());
|
| }
|
|
|
| // Validates PIN error checking in conjuction with policy-related prefs.
|
| -TEST_F(QuickUnlockPrivateUnitTest, CheckCredentialProblemReporting) {
|
| +TEST_P(QuickUnlockPrivateUnitTest, CheckCredentialProblemReporting) {
|
| PrefService* pref_service = profile()->GetPrefs();
|
|
|
| // Verify the pin checks work with the default preferences which are minimum
|
| @@ -470,7 +575,7 @@ TEST_F(QuickUnlockPrivateUnitTest, CheckCredentialProblemReporting) {
|
| CheckPin(PIN_TOO_SHORT | PIN_WEAK_ERROR, "234");
|
| }
|
|
|
| -TEST_F(QuickUnlockPrivateUnitTest, GetCredentialRequirements) {
|
| +TEST_P(QuickUnlockPrivateUnitTest, GetCredentialRequirements) {
|
| PrefService* pref_service = profile()->GetPrefs();
|
|
|
| // Verify that trying out PINs under the minimum/maximum lengths will send the
|
| @@ -490,4 +595,11 @@ TEST_F(QuickUnlockPrivateUnitTest, GetCredentialRequirements) {
|
| pref_service->SetInteger(prefs::kPinUnlockMaximumLength, -3);
|
| CheckGetCredentialRequirements(1, 0);
|
| }
|
| +
|
| +INSTANTIATE_TEST_CASE_P(
|
| + StorageProviders,
|
| + QuickUnlockPrivateUnitTest,
|
| + ::testing::Values(quick_unlock::PinStorageType::kPrefs,
|
| + quick_unlock::PinStorageType::kCryptohome));
|
| +
|
| } // namespace chromeos
|
|
|