Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(944)

Unified Diff: chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc

Issue 1968083004: Implement the private API for quick unlock. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@lkgr
Patch Set: Fix compile Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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
new file mode 100644
index 0000000000000000000000000000000000000000..f527ea2e06f4543dc5a835989ea54cd4b4dce08d
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc
@@ -0,0 +1,317 @@
+// Copyright 2016 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.
+
+// This file tests the chromeos.quickUnlockPrivate extension API.
+
+#include "chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.h"
+
+#include "base/bind.h"
+
+#include "base/memory/ptr_util.h"
+#include "chrome/browser/chromeos/login/quick_unlock/pin_storage.h"
+#include "chrome/browser/chromeos/login/quick_unlock/pin_storage_factory.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/extensions/extension_api_unittest.h"
+#include "chromeos/login/auth/fake_extended_authenticator.h"
+#include "extensions/browser/api_test_utils.h"
+#include "extensions/browser/extension_function_dispatcher.h"
+
+using namespace extensions;
+namespace quick_unlock_private = extensions::api::quick_unlock_private;
+using QuickUnlockMode = quick_unlock_private::QuickUnlockMode;
+using QuickUnlockModeList = std::vector<QuickUnlockMode>;
+using CredentialList = std::vector<std::string>;
+
+namespace chromeos {
+namespace {
+
+const char* kTestUserEmail = "testuser@gmail.com";
+const char* kTestUserEmailHash = "testuser@gmail.com-hash";
+const char* kValidPassword = "valid";
+const char* kInvalidPassword = "invalid";
+
+chromeos::ExtendedAuthenticator* CreateFakeAuthenticator(
+ chromeos::AuthStatusConsumer* auth_status_consumer) {
+ AccountId account_id = AccountId::FromUserEmail(kTestUserEmail);
+ chromeos::UserContext expected_context(account_id);
+ expected_context.SetKey(Key(kValidPassword));
+
+ chromeos::ExtendedAuthenticator* authenticator =
+ new chromeos::FakeExtendedAuthenticator(auth_status_consumer,
+ expected_context);
+ return authenticator;
+}
+
+void DoNothing(const QuickUnlockModeList& modes) {}
+
+void FailIfCalled(const QuickUnlockModeList& modes) {
+ FAIL();
+}
+
+} // namespace
+
+class QuickUnlockPrivateUnitTest : public ExtensionApiUnittest {
+ public:
+ QuickUnlockPrivateUnitTest()
+ : fake_user_manager_(new FakeChromeUserManager()),
+ scoped_user_manager_(fake_user_manager_) {}
+
+ protected:
+ void SetUp() override {
+ ExtensionApiUnittest::SetUp();
+
+ // Setup a primary user.
+ auto test_account = AccountId::FromUserEmail(kTestUserEmail);
+ fake_user_manager_->AddUser(test_account);
+ fake_user_manager_->UserLoggedIn(test_account, kTestUserEmailHash, false);
+
+ // Ensure that quick unlock is turned off.
+ SetModes(QuickUnlockModeList{}, CredentialList{});
+
+ modes_changed_handler_ = base::Bind(&DoNothing);
+ }
+
+ // If a mode change event is raised, fail the test.
+ void FailIfModesChanged() {
+ modes_changed_handler_ = base::Bind(&FailIfCalled);
+ }
+
+ // If a mode change event is raised, expect the given |modes|.
+ void ExpectModesChanged(const QuickUnlockModeList& modes) {
+ modes_changed_handler_ =
+ base::Bind(&QuickUnlockPrivateUnitTest::ExpectModeList,
+ base::Unretained(this), modes);
+ expect_modes_changed_ = true;
+ }
+
+ // Wrapper for chrome.quickUnlockPrivate.getAvailableModes.
+ QuickUnlockModeList GetAvailableModes() {
+ // Run the function.
+ std::unique_ptr<base::Value> result =
+ RunFunction(new QuickUnlockPrivateGetAvailableModesFunction(),
+ base::WrapUnique(new base::ListValue()));
+
+ // Extract the results.
+ QuickUnlockModeList modes;
+
+ base::ListValue* list = nullptr;
+ EXPECT_TRUE(result->GetAsList(&list));
+ // Consume the unique_ptr by reference so we don't take ownership.
+ for (const std::unique_ptr<base::Value>& value : (*list)) {
+ std::string mode;
+ EXPECT_TRUE(value->GetAsString(&mode));
+ modes.push_back(quick_unlock_private::ParseQuickUnlockMode(mode));
+ }
+
+ return modes;
+ }
+
+ // Wrapper for chrome.quickUnlockPrivate.getActiveModes.
+ QuickUnlockModeList GetActiveModes() {
+ std::unique_ptr<base::Value> result =
+ RunFunction(new QuickUnlockPrivateGetActiveModesFunction(),
+ base::WrapUnique(new base::ListValue()));
+
+ QuickUnlockModeList modes;
+
+ base::ListValue* list = nullptr;
+ EXPECT_TRUE(result->GetAsList(&list));
+ for (const std::unique_ptr<base::Value>& value : *list) {
+ std::string mode;
+ EXPECT_TRUE(value->GetAsString(&mode));
+ modes.push_back(quick_unlock_private::ParseQuickUnlockMode(mode));
+ }
+
+ return modes;
+ }
+
+ // Wrapper for chrome.quickUnlockPrivate.setModes that automatically uses a
+ // valid password.
+ bool SetModes(const QuickUnlockModeList& modes,
+ const CredentialList& passwords) {
+ return SetModesUsingPassword(kValidPassword, modes, passwords);
+ }
+
+ // Wrapper for chrome.quickUnlockPrivate.setModes.
+ bool SetModesUsingPassword(const std::string& password,
+ const QuickUnlockModeList& modes,
+ const CredentialList& passwords) {
+ // Serialize parameters.
+ auto params = base::WrapUnique(new base::ListValue());
+ params->AppendString(password);
+
+ auto serialized_modes = base::WrapUnique(new base::ListValue());
+ for (QuickUnlockMode mode : modes)
+ serialized_modes->AppendString(quick_unlock_private::ToString(mode));
+ params->Append(std::move(serialized_modes));
+
+ auto serialized_passwords = base::WrapUnique(new base::ListValue());
+ for (const std::string& password : passwords)
+ serialized_passwords->AppendString(password);
+ params->Append(std::move(serialized_passwords));
+
+ // Setup a fake authenticator so quickUnlockPrivate.checkPassword doesn't
+ // call cryptohome methods.
+ auto* func = new QuickUnlockPrivateSetModesFunction();
+ func->SetAuthenticatorAllocatorForTesting(
+ base::Bind(&CreateFakeAuthenticator));
+
+ // Stub out event handling since we are not setting up an event router.
+ func->SetModesChangedEventHandlerForTesting(modes_changed_handler_);
+
+ // Run function and extract the result.
+ std::unique_ptr<base::Value> func_result =
+ RunFunction(func, std::move(params));
+ bool result;
+ EXPECT_TRUE(func_result->GetAsBoolean(&result));
+
+ // Verify that the mode change event handler was run if it was registered.
+ // ExpectModesChanged will set expect_modes_changed_ to true and the event
+ // handler will set it to false; so if the handler never runs,
+ // expect_modes_changed_ will still be true.
+ EXPECT_FALSE(expect_modes_changed_) << "Mode change event was not raised";
+
+ return result;
+ }
+
+ std::string SetModesWithError(const std::string& args) {
+ auto func = new QuickUnlockPrivateSetModesFunction();
+ func->SetAuthenticatorAllocatorForTesting(
+ base::Bind(&CreateFakeAuthenticator));
+ func->SetModesChangedEventHandlerForTesting(base::Bind(&DoNothing));
+
+ return api_test_utils::RunFunctionAndReturnError(func, args, profile());
+ }
+
+ // Returns true if |password| is correct. This calls into SetModes to do so.
+ // This will turn off any active quick unlock modes.
+ bool CheckPassword(const std::string& password) {
+ return SetModesUsingPassword(password, QuickUnlockModeList{},
+ CredentialList{});
+ }
+
+ 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>(
+ api_test_utils::RunFunctionWithDelegateAndReturnSingleResult(
+ func, std::move(params), profile(),
+ base::WrapUnique(new ExtensionFunctionDispatcher(profile())),
+ api_test_utils::NONE));
+ }
+
+ // Verifies a mode change event is raised and that |expected| is now the
+ // active set of quick unlock modes.
+ void ExpectModeList(const QuickUnlockModeList& expected,
+ const QuickUnlockModeList& actual) {
+ EXPECT_EQ(expected, actual);
+ expect_modes_changed_ = false;
+ }
+
+ FakeChromeUserManager* fake_user_manager_;
+ ScopedUserManagerEnabler scoped_user_manager_;
+ QuickUnlockPrivateSetModesFunction::ModesChangedEventHandler
+ modes_changed_handler_;
+ bool expect_modes_changed_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(QuickUnlockPrivateUnitTest);
+};
+
+// Verify that password checking works.
+TEST_F(QuickUnlockPrivateUnitTest, CheckPassword) {
+ EXPECT_TRUE(CheckPassword(kValidPassword));
+ EXPECT_FALSE(CheckPassword(kInvalidPassword));
+}
+
+// Verifies that this returns PIN for GetAvailableModes.
+TEST_F(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) {
+ // Verify there is no active mode.
+ EXPECT_EQ(GetActiveModes(), QuickUnlockModeList{});
+
+ // Try to enable PIN, but use an invalid password. Verify that no event is
+ // raised and GetActiveModes still returns an empty set.
+ FailIfModesChanged();
+ EXPECT_FALSE(SetModesUsingPassword(
+ kInvalidPassword,
+ QuickUnlockModeList{QuickUnlockMode::QUICK_UNLOCK_MODE_PIN}, {"11"}));
+ EXPECT_EQ(GetActiveModes(), QuickUnlockModeList{});
+}
+
+// Verifies that the quickUnlockPrivate.onActiveModesChanged is only raised when
+// the active set of modes changes.
+TEST_F(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{}));
+ FailIfModesChanged();
+ EXPECT_TRUE(SetModes(QuickUnlockModeList{}, CredentialList{}));
+
+ // Turn on PIN unlock, and then verify turning it on again and also changing
+ // the password does not trigger an event.
+ ExpectModesChanged(
+ QuickUnlockModeList{QuickUnlockMode::QUICK_UNLOCK_MODE_PIN});
+ EXPECT_TRUE(SetModes(
+ QuickUnlockModeList{QuickUnlockMode::QUICK_UNLOCK_MODE_PIN}, {"11"}));
+ FailIfModesChanged();
+ EXPECT_TRUE(SetModes(
+ QuickUnlockModeList{QuickUnlockMode::QUICK_UNLOCK_MODE_PIN}, {"22"}));
+ EXPECT_TRUE(SetModes(
+ QuickUnlockModeList{QuickUnlockMode::QUICK_UNLOCK_MODE_PIN}, {""}));
+}
+
+// Ensures that quick unlock can be enabled and disabled by checking the result
+// of quickUnlockPrivate.GetActiveModes and PinStorage::IsPinSet.
+TEST_F(QuickUnlockPrivateUnitTest, SetModesAndGetActiveModes) {
+ PinStorage* pin_storage = PinStorageFactory::GetForProfile(profile());
+
+ // Update mode to PIN raises an event and updates GetActiveModes.
+ ExpectModesChanged(
+ QuickUnlockModeList{QuickUnlockMode::QUICK_UNLOCK_MODE_PIN});
+ EXPECT_TRUE(SetModes(
+ QuickUnlockModeList{QuickUnlockMode::QUICK_UNLOCK_MODE_PIN}, {"11"}));
+ EXPECT_EQ(GetActiveModes(),
+ QuickUnlockModeList{QuickUnlockMode::QUICK_UNLOCK_MODE_PIN});
+ EXPECT_TRUE(pin_storage->IsPinSet());
+
+ // SetModes can be used to turn off a quick unlock mode.
+ ExpectModesChanged(QuickUnlockModeList{});
+ EXPECT_TRUE(SetModes(QuickUnlockModeList{}, CredentialList{}));
+ EXPECT_EQ(GetActiveModes(), QuickUnlockModeList{});
+ EXPECT_FALSE(pin_storage->IsPinSet());
+}
+
+// Verifies that enabling PIN quick unlock actually talks to the PIN subsystem.
+TEST_F(QuickUnlockPrivateUnitTest, VerifyAuthenticationAgainstPIN) {
+ PinStorage* pin_storage = PinStorageFactory::GetForProfile(profile());
+
+ EXPECT_TRUE(SetModes(QuickUnlockModeList{}, CredentialList{}));
+ EXPECT_FALSE(pin_storage->IsPinSet());
+
+ EXPECT_TRUE(SetModes(
+ QuickUnlockModeList{QuickUnlockMode::QUICK_UNLOCK_MODE_PIN}, {"11"}));
+ EXPECT_TRUE(pin_storage->IsPinSet());
+
+ pin_storage->MarkStrongAuth();
+ pin_storage->ResetUnlockAttemptCount();
+ EXPECT_TRUE(pin_storage->TryAuthenticatePin("11"));
+ EXPECT_FALSE(pin_storage->TryAuthenticatePin("00"));
+}
+
+// Verifies that the number of modes and the number of passwords given must be
+// the same.
+TEST_F(QuickUnlockPrivateUnitTest, ThrowErrorOnMismatchedParameterCount) {
+ EXPECT_FALSE(SetModesWithError("[\"valid\", [\"PIN\"], []]").empty());
+ EXPECT_FALSE(SetModesWithError("[\"valid\", [], [\"11\"]]").empty());
+}
+
+} // namespace chromeos

Powered by Google App Engine
This is Rietveld 408576698