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 |