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

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: Address comments 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..c5f7e4d29f2465c44343bdc8e16dfff170052f62
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc
@@ -0,0 +1,265 @@
+// 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/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 ModeList = std::vector<QuickUnlockMode>;
+
+namespace chromeos {
+namespace {
+const char* kTestUserEmail = "testuser@gmail.com";
+const char* kTestUserEmailHash = "testuser@gmail.com-hash";
+const char* kValidPassword = "valid";
+const char* kInvalidPassword = "invalid";
+}
+
+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 fake authenticator so quickUnlockPrivate.checkPassword doesn't
+ // call cryptohome methods.
+ QuickUnlockPrivateSetModesFunction::SetCreateAuthenticatorForTesting(
+ [](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;
+ });
+
+ // Stub out event handling since we are not setting up an event router.
+ // Some tests can and do override this by installing their own event
+ // handler.
+ SetModesChangedEventHandler([](const ModeList& modes) {});
+
+ // 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({}, {});
+ }
+
+ void TearDown() override {
+ QuickUnlockPrivateSetModesFunction::SetCreateAuthenticatorForTesting(
+ nullptr);
+ SetModesChangedEventHandler(nullptr);
+
+ ExtensionApiUnittest::TearDown();
+ }
+
+ void SetModesChangedEventHandler(
+ QuickUnlockPrivateSetModesFunction::ModesChangedEventHandler handler) {
+ QuickUnlockPrivateSetModesFunction::SetModesChangedEventHandlerForTesting(
+ handler);
+ }
+
+ // Wrapper for chrome.quickUnlockPrivate.getAvailableModes.
+ ModeList GetAvailableModes() {
+ // Run the function.
+ std::unique_ptr<base::Value> result =
+ RunFunction(new QuickUnlockPrivateGetAvailableModesFunction(),
+ new base::ListValue());
+
+ // Extract the results.
+ ModeList 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.
+ ModeList GetActiveModes() {
+ std::unique_ptr<base::Value> result = RunFunction(
+ new QuickUnlockPrivateGetActiveModesFunction(), new base::ListValue());
+
+ ModeList 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 ModeList& modes,
+ const std::vector<std::string>& passwords) {
+ return SetModesUsingPassword(kValidPassword, modes, passwords);
+ }
+
+ // Wrapper for chrome.quickUnlockPrivate.setModes.
+ bool SetModesUsingPassword(const std::string& password,
+ const ModeList& modes,
+ const std::vector<std::string>& passwords) {
+ // Serialize the parameters.
+ auto params = 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));
+
+ // Run function and extract the result.
+ std::unique_ptr<base::Value> func_result =
+ RunFunction(new QuickUnlockPrivateSetModesFunction(), params);
+ bool result;
+ EXPECT_TRUE(func_result->GetAsBoolean(&result));
+ return result;
+ }
+
+ std::string SetModesWithError(const std::string& args) {
+ return api_test_utils::RunFunctionAndReturnError(
+ new QuickUnlockPrivateSetModesFunction(), 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, {}, {});
+ }
+
+ private:
+ // Runs the given |func| with the given |params|. This function takes
+ // ownership over |func| and |params|; they are passed as raw pointers for
+ // caller convenience.
+ std::unique_ptr<base::Value> RunFunction(UIThreadExtensionFunction* func,
+ base::ListValue* params) {
+ return std::unique_ptr<base::Value>(
+ api_test_utils::RunFunctionWithDelegateAndReturnSingleResult(
+ func, base::WrapUnique(params), profile(),
+ base::WrapUnique(new ExtensionFunctionDispatcher(profile())),
+ api_test_utils::NONE));
+ }
+
+ FakeChromeUserManager* fake_user_manager_;
+ ScopedUserManagerEnabler scoped_user_manager_;
+
+ 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(),
+ ModeList{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(), ModeList{});
+
+ // Try to enable PIN, but use an invalid password. Verify that no event is
+ // raised and GetActiveModes still returns an empty set.
+ SetModesChangedEventHandler([](const ModeList& modes) { FAIL(); });
+ EXPECT_FALSE(SetModesUsingPassword(
+ kInvalidPassword, {QuickUnlockMode::QUICK_UNLOCK_MODE_PIN}, {"11"}));
+ EXPECT_EQ(GetActiveModes(), ModeList{});
+}
+
+// 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({}, {}));
+ SetModesChangedEventHandler([](const ModeList& modes) { FAIL(); });
+ EXPECT_TRUE(SetModes({}, {}));
+
+ // Turn on PIN unlock, and then verify turning it on again and also changing
+ // the password does not trigger an event.
+ SetModesChangedEventHandler([](const ModeList& modes) {});
+ EXPECT_TRUE(SetModes({QuickUnlockMode::QUICK_UNLOCK_MODE_PIN}, {"11"}));
+ SetModesChangedEventHandler([](const ModeList& modes) { FAIL(); });
+ EXPECT_TRUE(SetModes({QuickUnlockMode::QUICK_UNLOCK_MODE_PIN}, {"22"}));
+ EXPECT_TRUE(SetModes({QuickUnlockMode::QUICK_UNLOCK_MODE_PIN}, {""}));
+}
+
+TEST_F(QuickUnlockPrivateUnitTest, SetModesAndGetActiveModes) {
+ // Update mode to PIN raises an event and updates GetActiveModes.
+ SetModesChangedEventHandler([](const ModeList& modes) {
+ EXPECT_EQ(modes, ModeList{QuickUnlockMode::QUICK_UNLOCK_MODE_PIN});
+ });
+ EXPECT_TRUE(SetModes({QuickUnlockMode::QUICK_UNLOCK_MODE_PIN}, {"11"}));
+ EXPECT_EQ(GetActiveModes(), ModeList{QuickUnlockMode::QUICK_UNLOCK_MODE_PIN});
+
+ // SetModes can be used to turn off a quick unlock mode.
+ SetModesChangedEventHandler(
+ [](const ModeList& modes) { EXPECT_EQ(modes, ModeList{}); });
+ EXPECT_TRUE(SetModes({}, {}));
+ EXPECT_EQ(GetActiveModes(), ModeList{});
+}
+
+// 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({}, {}));
+ EXPECT_FALSE(pin_storage->IsPinSet());
+
+ EXPECT_TRUE(SetModes({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"));
+}
+
+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