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

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: Migrate browser tests to unit tests 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..e36eab8927097c076c82a2e8b3c76527ede3267f
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc
@@ -0,0 +1,271 @@
+// 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";
+
+// Verifies that two mode lists are equal.
+void EXPECT_MODES(const ModeList& x, const ModeList& y) {
+ ASSERT_EQ(x.size(), y.size()) << "Vectors x and y are of unequal length";
+ for (size_t i = 0; i < x.size(); ++i)
+ EXPECT_EQ(x[i], y[i]) << "Vectors x and y differ at index " << i;
+}
+
+} // 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 fake authenticator so quickUnlockPrivate.checkPassword doesn't
+ // call cryptohome methods.
+ QuickUnlockPrivateSetModesFunction::SetCreateAuthenticatorForTesting(
Devlin 2016/06/06 16:35:01 The create_authenticator_ variable is global, whic
jdufault 2016/06/08 18:39:10 I've done this is TearDown().
+ [](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.
+ QuickUnlockPrivateSetModesFunction::SetModesChangedEventHandlerForTesting(
+ [](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 {
+ ExtensionApiUnittest::TearDown();
+
+ QuickUnlockPrivateSetModesFunction::SetModesChangedEventHandlerForTesting(
+ nullptr);
+ }
+
+ // 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;
+ EXPECT_TRUE(result->GetAsList(&list));
+ for (base::ListValue::iterator i = list->begin(); i != list->end(); ++i) {
+ std::string mode;
+ EXPECT_TRUE((*i)->GetAsString(&mode));
+ modes.push_back(quick_unlock_private::ParseQuickUnlockMode(mode));
+ }
+
+ return modes;
+ }
+
+ // Wrapper for chrome.quickUnlockPrivate.getActiveModes.
+ ModeList GetActiveModes() {
+ auto result = RunFunction(new QuickUnlockPrivateGetActiveModesFunction(),
+ new base::ListValue());
+
+ ModeList modes;
+
+ base::ListValue* list;
+ EXPECT_TRUE(result->GetAsList(&list));
+ for (base::ListValue::iterator i = list->begin(); i != list->end(); ++i) {
+ std::string mode;
+ EXPECT_TRUE((*i)->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 = new base::ListValue();
Devlin 2016/06/06 16:35:01 nit: typically preferred style to enforce ownershi
jdufault 2016/06/08 18:39:09 Done.
+ for (QuickUnlockMode mode : modes)
+ serialized_modes->AppendString(quick_unlock_private::ToString(mode));
+ params->Append(base::WrapUnique(serialized_modes));
+
+ auto serialized_passwords = new base::ListValue();
+ for (const std::string& password : passwords)
+ serialized_passwords->AppendString(password);
+ params->Append(base::WrapUnique(serialized_passwords));
+
+ // Run function and extract the result.
+ auto 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_MODES(GetAvailableModes(), {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_MODES(GetActiveModes(), {});
+
+ // Try to enable PIN, but use an invalid password. Verify that no event is
+ // raised and GetActiveModes still returns an empty set.
+ QuickUnlockPrivateSetModesFunction::SetModesChangedEventHandlerForTesting(
+ [](const ModeList& modes) { FAIL(); });
+ EXPECT_FALSE(SetModesUsingPassword(
+ kInvalidPassword, {QuickUnlockMode::QUICK_UNLOCK_MODE_PIN}, {"11"}));
+ EXPECT_MODES(GetActiveModes(), {});
+}
+
+// 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({}, {}));
+ QuickUnlockPrivateSetModesFunction::SetModesChangedEventHandlerForTesting(
+ [](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.
+ QuickUnlockPrivateSetModesFunction::SetModesChangedEventHandlerForTesting(
Devlin 2016/06/06 16:35:01 Why do we need to do this everywhere?
jdufault 2016/06/08 18:39:09 You mean calling SetModesChangedEventHandlerForTes
+ [](const ModeList& modes) {});
+ EXPECT_TRUE(SetModes({QuickUnlockMode::QUICK_UNLOCK_MODE_PIN}, {"11"}));
+ QuickUnlockPrivateSetModesFunction::SetModesChangedEventHandlerForTesting(
+ [](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.
+ QuickUnlockPrivateSetModesFunction::SetModesChangedEventHandlerForTesting(
+ [](const ModeList& modes) {
+ EXPECT_MODES(modes, {QuickUnlockMode::QUICK_UNLOCK_MODE_PIN});
+ });
+ EXPECT_TRUE(SetModes({QuickUnlockMode::QUICK_UNLOCK_MODE_PIN}, {"11"}));
+ EXPECT_MODES(GetActiveModes(), {QuickUnlockMode::QUICK_UNLOCK_MODE_PIN});
+
+ // SetModes can be used to turn off a quick unlock mode.
+ QuickUnlockPrivateSetModesFunction::SetModesChangedEventHandlerForTesting(
+ [](const ModeList& modes) { EXPECT_MODES(modes, {}); });
+ EXPECT_TRUE(SetModes({}, {}));
+ EXPECT_MODES(GetActiveModes(), {});
+}
+
+// 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