// Copyright 2014 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. #include "chrome/browser/signin/easy_unlock_screenlock_state_handler.h" #include #include #include #include "base/macros.h" #include "base/strings/string16.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/test/histogram_tester.h" #include "chrome/browser/signin/easy_unlock_metrics.h" #include "chrome/browser/signin/easy_unlock_service.h" #include "chrome/grit/generated_resources.h" #include "components/proximity_auth/screenlock_bridge.h" #include "components/proximity_auth/screenlock_state.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/l10n/l10n_util.h" using proximity_auth::ScreenlockState; namespace { // Icons used by EasyUnlockScreenlockStateHandler. The icon id values are the // same as the ones set by proximity_auth::ScreenlockBridge. const char kLockedIconId[] = "locked"; const char kLockedToBeActivatedIconId[] = "locked-to-be-activated"; const char kUnlockedIconId[] = "unlocked"; const char kSpinnerIconId[] = "spinner"; const char kHardlockedIconId[] = "hardlocked"; // Checks if |input| string has any unreplaced placeholders. bool StringHasPlaceholders(const base::string16& input) { std::vector offsets; std::vector subst; subst.push_back(base::string16()); base::string16 replaced = base::ReplaceStringPlaceholders(input, subst, &offsets); return !offsets.empty(); } // Fake lock handler to be used in these tests. class TestLockHandler : public proximity_auth::ScreenlockBridge::LockHandler { public: explicit TestLockHandler(const AccountId& account_id) : account_id_(account_id), show_icon_count_(0u), auth_type_(OFFLINE_PASSWORD) {} ~TestLockHandler() override {} // proximity_auth::ScreenlockBridge::LockHandler implementation: void ShowBannerMessage(const base::string16& message) override { ASSERT_FALSE(true) << "Should not be reached."; } void ShowUserPodCustomIcon( const AccountId& account_id, const proximity_auth::ScreenlockBridge::UserPodCustomIconOptions& icon) override { ASSERT_TRUE(account_id_ == account_id) << "account_id_=" << account_id_.Serialize() << " != account_id=" << account_id.Serialize(); ++show_icon_count_; last_custom_icon_ = icon.ToDictionaryValue(); ValidateCustomIcon(); } void HideUserPodCustomIcon(const AccountId& account_id) override { ASSERT_TRUE(account_id_ == account_id) << "account_id_=" << account_id_.Serialize() << " != account_id=" << account_id.Serialize(); last_custom_icon_.reset(); } void EnableInput() override { ASSERT_FALSE(true) << "Should not be reached."; } void SetAuthType(const AccountId& account_id, AuthType auth_type, const base::string16& auth_value) override { ASSERT_TRUE(account_id_ == account_id) << "account_id_=" << account_id_.Serialize() << " != account_id=" << account_id.Serialize(); // Generally, this is allowed, but EasyUnlockScreenlockStateHandler should // avoid resetting the same auth type. EXPECT_NE(auth_type_, auth_type); auth_type_ = auth_type; auth_value_ = auth_value; } AuthType GetAuthType(const AccountId& account_id) const override { EXPECT_TRUE(account_id_ == account_id) << "account_id_=" << account_id_.Serialize() << " != account_id=" << account_id.Serialize(); return auth_type_; } ScreenType GetScreenType() const override { return LOCK_SCREEN; } void Unlock(const AccountId& account_id) override { ASSERT_FALSE(true) << "Should not be reached."; } void AttemptEasySignin(const AccountId& account_id, const std::string& secret, const std::string& key_label) override { ASSERT_FALSE(true) << "Should not be reached."; } // Utility methods used by tests: // Gets last set auth value. base::string16 GetAuthValue() const { return auth_value_; } // Sets the auth value. void SetAuthValue(const base::string16& value) { auth_value_ = value; } // Returns the number of times an icon was shown since the last call to this // method. size_t GetAndResetShowIconCount() { size_t result = show_icon_count_; show_icon_count_ = 0u; return result; } // Whether the custom icon is set. bool HasCustomIcon() const { return !!last_custom_icon_; } // If custom icon is set, returns the icon's id. // If there is no icon, or if it doesn't have an id set, returns an empty // string. std::string GetCustomIconId() const { std::string result; if (last_custom_icon_) last_custom_icon_->GetString("id", &result); return result; } // Whether the custom icon is set and it has a tooltip. bool CustomIconHasTooltip() const { return last_custom_icon_ && last_custom_icon_->HasKey("tooltip"); } // Gets the custom icon's tooltip text, if one is set. base::string16 GetCustomIconTooltip() const { base::string16 result; if (last_custom_icon_) last_custom_icon_->GetString("tooltip.text", &result); return result; } // Whether the custom icon's tooltip should be autoshown. If the icon is not // set, or it doesn't have a tooltip, returns false. bool IsCustomIconTooltipAutoshown() const { bool result = false; if (last_custom_icon_) last_custom_icon_->GetBoolean("tooltip.autoshow", &result); return result; } // Whether the custom icon is set and if has hardlock capability enabed. bool CustomIconHardlocksOnClick() const { bool result = false; if (last_custom_icon_) last_custom_icon_->GetBoolean("hardlockOnClick", &result); return result; } private: // Does some sanity checks on the last icon set by |ShowUserPodCustomIcon|. // It will cause a test failure if the icon is not valid. void ValidateCustomIcon() { ASSERT_TRUE(last_custom_icon_.get()); EXPECT_TRUE(last_custom_icon_->HasKey("id")); if (last_custom_icon_->HasKey("tooltip")) { base::string16 tooltip; EXPECT_TRUE(last_custom_icon_->GetString("tooltip.text", &tooltip)); EXPECT_FALSE(tooltip.empty()); EXPECT_FALSE(StringHasPlaceholders(tooltip)); } } // The fake account id used in test. All methods called on |this| should be // associated with this user. const AccountId account_id_; // The last icon set using |SetUserPodCustomIcon|. Call to // |HideUserPodcustomIcon| resets it. scoped_ptr last_custom_icon_; size_t show_icon_count_; // Auth type and value set using |SetAuthType|. AuthType auth_type_; base::string16 auth_value_; DISALLOW_COPY_AND_ASSIGN(TestLockHandler); }; class EasyUnlockScreenlockStateHandlerTest : public testing::Test { public: EasyUnlockScreenlockStateHandlerTest() {} ~EasyUnlockScreenlockStateHandlerTest() override {} void SetUp() override { // Create and inject fake lock handler to the screenlock bridge. lock_handler_.reset(new TestLockHandler(account_id_)); proximity_auth::ScreenlockBridge* screenlock_bridge = proximity_auth::ScreenlockBridge::Get(); screenlock_bridge->SetLockHandler(lock_handler_.get()); // Create the screenlock state handler object that will be tested. state_handler_.reset(new EasyUnlockScreenlockStateHandler( account_id_, EasyUnlockScreenlockStateHandler::NO_HARDLOCK, screenlock_bridge)); } void TearDown() override { proximity_auth::ScreenlockBridge::Get()->SetLockHandler(NULL); lock_handler_.reset(); state_handler_.reset(); } protected: // The state handler that is being tested. scoped_ptr state_handler_; // The user associated with |state_handler_|. const AccountId account_id_ = AccountId::FromUserEmail("test_user@gmail.com"); // Faked lock handler given to proximity_auth::ScreenlockBridge during the // test. Abstracts the screen lock UI. scoped_ptr lock_handler_; }; TEST_F(EasyUnlockScreenlockStateHandlerTest, AuthenticatedTrialRun) { state_handler_->SetTrialRun(); state_handler_->ChangeState(ScreenlockState::AUTHENTICATED); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK, lock_handler_->GetAuthType(account_id_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); EXPECT_EQ(kUnlockedIconId, lock_handler_->GetCustomIconId()); EXPECT_TRUE(lock_handler_->CustomIconHasTooltip()); EXPECT_TRUE(lock_handler_->IsCustomIconTooltipAutoshown()); EXPECT_FALSE(lock_handler_->CustomIconHardlocksOnClick()); state_handler_->ChangeState(ScreenlockState::AUTHENTICATED); // Duplicated state change should be ignored. EXPECT_EQ(0u, lock_handler_->GetAndResetShowIconCount()); } TEST_F(EasyUnlockScreenlockStateHandlerTest, AuthenticatedNotInitialRun) { state_handler_->ChangeState(ScreenlockState::AUTHENTICATED); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK, lock_handler_->GetAuthType(account_id_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); EXPECT_EQ(kUnlockedIconId, lock_handler_->GetCustomIconId()); EXPECT_TRUE(lock_handler_->CustomIconHasTooltip()); EXPECT_FALSE(lock_handler_->IsCustomIconTooltipAutoshown()); EXPECT_TRUE(lock_handler_->CustomIconHardlocksOnClick()); } TEST_F(EasyUnlockScreenlockStateHandlerTest, IsActive) { EXPECT_FALSE(state_handler_->IsActive()); state_handler_->ChangeState(ScreenlockState::AUTHENTICATED); EXPECT_TRUE(state_handler_->IsActive()); state_handler_->ChangeState(ScreenlockState::INACTIVE); EXPECT_FALSE(state_handler_->IsActive()); } TEST_F(EasyUnlockScreenlockStateHandlerTest, BluetoothConnecting) { state_handler_->ChangeState(ScreenlockState::BLUETOOTH_CONNECTING); EXPECT_TRUE(state_handler_->IsActive()); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, lock_handler_->GetAuthType(account_id_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); EXPECT_EQ(kSpinnerIconId, lock_handler_->GetCustomIconId()); EXPECT_FALSE(lock_handler_->CustomIconHasTooltip()); EXPECT_TRUE(lock_handler_->CustomIconHardlocksOnClick()); state_handler_->ChangeState(ScreenlockState::BLUETOOTH_CONNECTING); // Duplicated state change should be ignored. EXPECT_EQ(0u, lock_handler_->GetAndResetShowIconCount()); } TEST_F(EasyUnlockScreenlockStateHandlerTest, HardlockedState) { state_handler_->ChangeState(ScreenlockState::AUTHENTICATED); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK, lock_handler_->GetAuthType(account_id_)); state_handler_->SetHardlockState( EasyUnlockScreenlockStateHandler::USER_HARDLOCK); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, lock_handler_->GetAuthType(account_id_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); EXPECT_EQ(kHardlockedIconId, lock_handler_->GetCustomIconId()); EXPECT_TRUE(lock_handler_->CustomIconHasTooltip()); EXPECT_TRUE(lock_handler_->IsCustomIconTooltipAutoshown()); EXPECT_FALSE(lock_handler_->CustomIconHardlocksOnClick()); state_handler_->SetHardlockState( EasyUnlockScreenlockStateHandler::USER_HARDLOCK); EXPECT_EQ(0u, lock_handler_->GetAndResetShowIconCount()); ASSERT_TRUE(lock_handler_->HasCustomIcon()); } TEST_F(EasyUnlockScreenlockStateHandlerTest, HardlockedStateNoPairing) { state_handler_->ChangeState(ScreenlockState::AUTHENTICATED); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK, lock_handler_->GetAuthType(account_id_)); state_handler_->SetHardlockState( EasyUnlockScreenlockStateHandler::NO_PAIRING); EXPECT_FALSE(lock_handler_->HasCustomIcon()); EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, lock_handler_->GetAuthType(account_id_)); } TEST_F(EasyUnlockScreenlockStateHandlerTest, StatesWithLockedIcon) { std::vector states; states.push_back(ScreenlockState::NO_BLUETOOTH); states.push_back(ScreenlockState::NO_PHONE); states.push_back(ScreenlockState::PHONE_UNSUPPORTED); states.push_back(ScreenlockState::PHONE_NOT_LOCKABLE); states.push_back(ScreenlockState::PHONE_NOT_AUTHENTICATED); states.push_back(ScreenlockState::PHONE_LOCKED); for (size_t i = 0; i < states.size(); ++i) { SCOPED_TRACE(base::SizeTToString(i)); state_handler_->ChangeState(states[i]); EXPECT_TRUE(state_handler_->IsActive()); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, lock_handler_->GetAuthType(account_id_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); EXPECT_EQ(kLockedIconId, lock_handler_->GetCustomIconId()); EXPECT_TRUE(lock_handler_->CustomIconHasTooltip()); EXPECT_TRUE(lock_handler_->IsCustomIconTooltipAutoshown()); EXPECT_TRUE(lock_handler_->CustomIconHardlocksOnClick()); state_handler_->ChangeState(states[i]); EXPECT_EQ(0u, lock_handler_->GetAndResetShowIconCount()); } } TEST_F(EasyUnlockScreenlockStateHandlerTest, SettingTrialRunUpdatesUI) { state_handler_->ChangeState(ScreenlockState::AUTHENTICATED); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK, lock_handler_->GetAuthType(account_id_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); ASSERT_FALSE(lock_handler_->IsCustomIconTooltipAutoshown()); state_handler_->SetTrialRun(); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK, lock_handler_->GetAuthType(account_id_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); ASSERT_TRUE(lock_handler_->IsCustomIconTooltipAutoshown()); } TEST_F(EasyUnlockScreenlockStateHandlerTest, LockScreenClearedOnStateHandlerDestruction) { state_handler_->ChangeState(ScreenlockState::AUTHENTICATED); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK, lock_handler_->GetAuthType(account_id_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); state_handler_.reset(); EXPECT_EQ(0u, lock_handler_->GetAndResetShowIconCount()); EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, lock_handler_->GetAuthType(account_id_)); ASSERT_FALSE(lock_handler_->HasCustomIcon()); } TEST_F(EasyUnlockScreenlockStateHandlerTest, StatePreservedWhenScreenUnlocks) { state_handler_->ChangeState(ScreenlockState::AUTHENTICATED); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK, lock_handler_->GetAuthType(account_id_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); proximity_auth::ScreenlockBridge::Get()->SetLockHandler(NULL); lock_handler_.reset(new TestLockHandler(account_id_)); EXPECT_EQ(0u, lock_handler_->GetAndResetShowIconCount()); proximity_auth::ScreenlockBridge::Get()->SetLockHandler(lock_handler_.get()); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK, lock_handler_->GetAuthType(account_id_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); } TEST_F(EasyUnlockScreenlockStateHandlerTest, StateChangeWhileScreenUnlocked) { state_handler_->ChangeState(ScreenlockState::AUTHENTICATED); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK, lock_handler_->GetAuthType(account_id_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); proximity_auth::ScreenlockBridge::Get()->SetLockHandler(NULL); lock_handler_.reset(new TestLockHandler(account_id_)); EXPECT_EQ(0u, lock_handler_->GetAndResetShowIconCount()); state_handler_->ChangeState(ScreenlockState::BLUETOOTH_CONNECTING); proximity_auth::ScreenlockBridge::Get()->SetLockHandler(lock_handler_.get()); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, lock_handler_->GetAuthType(account_id_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); EXPECT_EQ(kSpinnerIconId, lock_handler_->GetCustomIconId()); } TEST_F(EasyUnlockScreenlockStateHandlerTest, HardlockEnabledAfterInitialUnlock) { state_handler_->SetTrialRun(); std::vector states; states.push_back(ScreenlockState::BLUETOOTH_CONNECTING); states.push_back(ScreenlockState::PHONE_NOT_AUTHENTICATED); states.push_back(ScreenlockState::NO_BLUETOOTH); states.push_back(ScreenlockState::NO_PHONE); states.push_back(ScreenlockState::PHONE_UNSUPPORTED); states.push_back(ScreenlockState::PHONE_NOT_LOCKABLE); // This one should go last as changing state to AUTHENTICATED enables hard // locking. states.push_back(ScreenlockState::AUTHENTICATED); for (size_t i = 0; i < states.size(); ++i) { SCOPED_TRACE(base::SizeTToString(i)); state_handler_->ChangeState(states[i]); ASSERT_TRUE(lock_handler_->HasCustomIcon()); EXPECT_FALSE(lock_handler_->CustomIconHardlocksOnClick()); } proximity_auth::ScreenlockBridge::Get()->SetLockHandler(NULL); lock_handler_.reset(new TestLockHandler(account_id_)); proximity_auth::ScreenlockBridge::Get()->SetLockHandler(lock_handler_.get()); for (size_t i = 0; i < states.size(); ++i) { SCOPED_TRACE(base::SizeTToString(i)); state_handler_->ChangeState(states[i]); ASSERT_TRUE(lock_handler_->HasCustomIcon()); EXPECT_TRUE(lock_handler_->CustomIconHardlocksOnClick()); } } TEST_F(EasyUnlockScreenlockStateHandlerTest, NoPairingHardlockClearsIcon) { state_handler_->ChangeState(ScreenlockState::PHONE_LOCKED); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); ASSERT_TRUE(lock_handler_->HasCustomIcon()); EXPECT_EQ(kLockedIconId, lock_handler_->GetCustomIconId()); state_handler_->SetHardlockState( EasyUnlockScreenlockStateHandler::NO_PAIRING); EXPECT_EQ(0u, lock_handler_->GetAndResetShowIconCount()); ASSERT_FALSE(lock_handler_->HasCustomIcon()); } TEST_F(EasyUnlockScreenlockStateHandlerTest, PairingChangedHardlock) { state_handler_->ChangeState(ScreenlockState::PHONE_LOCKED); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); ASSERT_TRUE(lock_handler_->HasCustomIcon()); EXPECT_EQ(kLockedIconId, lock_handler_->GetCustomIconId()); state_handler_->SetHardlockState( EasyUnlockScreenlockStateHandler::PAIRING_CHANGED); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); ASSERT_TRUE(lock_handler_->HasCustomIcon()); EXPECT_EQ(kLockedToBeActivatedIconId, lock_handler_->GetCustomIconId()); state_handler_->ChangeState(ScreenlockState::AUTHENTICATED); EXPECT_EQ(0u, lock_handler_->GetAndResetShowIconCount()); ASSERT_TRUE(lock_handler_->HasCustomIcon()); EXPECT_EQ(kLockedToBeActivatedIconId, lock_handler_->GetCustomIconId()); } TEST_F(EasyUnlockScreenlockStateHandlerTest, PairingChangedHardlockIneffectiveOnInitialRun) { state_handler_->SetTrialRun(); state_handler_->ChangeState(ScreenlockState::PHONE_LOCKED); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); ASSERT_TRUE(lock_handler_->HasCustomIcon()); EXPECT_EQ(kLockedIconId, lock_handler_->GetCustomIconId()); state_handler_->SetHardlockState( EasyUnlockScreenlockStateHandler::PAIRING_CHANGED); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); ASSERT_TRUE(lock_handler_->HasCustomIcon()); EXPECT_EQ(kLockedIconId, lock_handler_->GetCustomIconId()); } TEST_F(EasyUnlockScreenlockStateHandlerTest, InactiveStateHidesIcon) { state_handler_->ChangeState(ScreenlockState::AUTHENTICATED); ASSERT_TRUE(lock_handler_->HasCustomIcon()); state_handler_->ChangeState(ScreenlockState::INACTIVE); ASSERT_FALSE(lock_handler_->HasCustomIcon()); } TEST_F(EasyUnlockScreenlockStateHandlerTest, AuthenticatedStateClearsPreviousAuthValue) { state_handler_->ChangeState(ScreenlockState::INACTIVE); lock_handler_->SetAuthValue(base::ASCIIToUTF16("xxx")); state_handler_->ChangeState(ScreenlockState::AUTHENTICATED); EXPECT_EQ(l10n_util::GetStringUTF16( IDS_EASY_UNLOCK_SCREENLOCK_USER_POD_AUTH_VALUE), lock_handler_->GetAuthValue()); state_handler_->ChangeState(ScreenlockState::NO_PHONE); EXPECT_EQ(base::string16(), lock_handler_->GetAuthValue()); } TEST_F(EasyUnlockScreenlockStateHandlerTest, ChangingStateDoesNotAffectAuthValueIfAuthTypeDoesNotChange) { lock_handler_->SetAuthValue(base::ASCIIToUTF16("xxx")); state_handler_->ChangeState(ScreenlockState::NO_PHONE); EXPECT_EQ(base::ASCIIToUTF16("xxx"), lock_handler_->GetAuthValue()); state_handler_->ChangeState(ScreenlockState::PHONE_NOT_AUTHENTICATED); EXPECT_EQ(base::ASCIIToUTF16("xxx"), lock_handler_->GetAuthValue()); state_handler_->ChangeState(ScreenlockState::BLUETOOTH_CONNECTING); EXPECT_EQ(base::ASCIIToUTF16("xxx"), lock_handler_->GetAuthValue()); ASSERT_TRUE(lock_handler_->HasCustomIcon()); EXPECT_EQ(kSpinnerIconId, lock_handler_->GetCustomIconId()); } TEST_F(EasyUnlockScreenlockStateHandlerTest, StateChangesIgnoredIfHardlocked) { state_handler_->ChangeState(ScreenlockState::AUTHENTICATED); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK, lock_handler_->GetAuthType(account_id_)); state_handler_->SetHardlockState( EasyUnlockScreenlockStateHandler::USER_HARDLOCK); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, lock_handler_->GetAuthType(account_id_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); EXPECT_EQ(kHardlockedIconId, lock_handler_->GetCustomIconId()); state_handler_->ChangeState(ScreenlockState::NO_PHONE); ASSERT_TRUE(lock_handler_->HasCustomIcon()); EXPECT_EQ(0u, lock_handler_->GetAndResetShowIconCount()); state_handler_->ChangeState(ScreenlockState::AUTHENTICATED); ASSERT_TRUE(lock_handler_->HasCustomIcon()); EXPECT_EQ(0u, lock_handler_->GetAndResetShowIconCount()); EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, lock_handler_->GetAuthType(account_id_)); } TEST_F(EasyUnlockScreenlockStateHandlerTest, LockScreenChangeableOnLockAfterHardlockReset) { state_handler_->ChangeState(ScreenlockState::AUTHENTICATED); state_handler_->SetHardlockState( EasyUnlockScreenlockStateHandler::USER_HARDLOCK); EXPECT_EQ(2u, lock_handler_->GetAndResetShowIconCount()); state_handler_->SetHardlockState( EasyUnlockScreenlockStateHandler::NO_HARDLOCK); proximity_auth::ScreenlockBridge::Get()->SetLockHandler(NULL); lock_handler_.reset(new TestLockHandler(account_id_)); EXPECT_EQ(0u, lock_handler_->GetAndResetShowIconCount()); proximity_auth::ScreenlockBridge::Get()->SetLockHandler(lock_handler_.get()); state_handler_->ChangeState(ScreenlockState::NO_PHONE); EXPECT_EQ(2u, lock_handler_->GetAndResetShowIconCount()); EXPECT_TRUE(lock_handler_->HasCustomIcon()); proximity_auth::ScreenlockBridge::Get()->SetLockHandler(NULL); lock_handler_.reset(new TestLockHandler(account_id_)); EXPECT_EQ(0u, lock_handler_->GetAndResetShowIconCount()); proximity_auth::ScreenlockBridge::Get()->SetLockHandler(lock_handler_.get()); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); EXPECT_TRUE(lock_handler_->HasCustomIcon()); EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, lock_handler_->GetAuthType(account_id_)); EXPECT_EQ(kLockedIconId, lock_handler_->GetCustomIconId()); state_handler_->ChangeState(ScreenlockState::AUTHENTICATED); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); EXPECT_TRUE(lock_handler_->HasCustomIcon()); EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK, lock_handler_->GetAuthType(account_id_)); EXPECT_TRUE(lock_handler_->CustomIconHardlocksOnClick()); } TEST_F(EasyUnlockScreenlockStateHandlerTest, HardlockStatePersistsOverUnlocks) { state_handler_->ChangeState(ScreenlockState::AUTHENTICATED); state_handler_->SetHardlockState( EasyUnlockScreenlockStateHandler::USER_HARDLOCK); EXPECT_EQ(2u, lock_handler_->GetAndResetShowIconCount()); proximity_auth::ScreenlockBridge::Get()->SetLockHandler(NULL); lock_handler_.reset(new TestLockHandler(account_id_)); EXPECT_EQ(0u, lock_handler_->GetAndResetShowIconCount()); proximity_auth::ScreenlockBridge::Get()->SetLockHandler(lock_handler_.get()); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, lock_handler_->GetAuthType(account_id_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); EXPECT_EQ(kHardlockedIconId, lock_handler_->GetCustomIconId()); state_handler_->ChangeState(ScreenlockState::AUTHENTICATED); EXPECT_EQ(0u, lock_handler_->GetAndResetShowIconCount()); EXPECT_TRUE(lock_handler_->HasCustomIcon()); EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, lock_handler_->GetAuthType(account_id_)); } TEST_F(EasyUnlockScreenlockStateHandlerTest, NoOverrideOnlineSignin) { lock_handler_->SetAuthType( account_id_, proximity_auth::ScreenlockBridge::LockHandler::ONLINE_SIGN_IN, base::string16()); std::vector states; states.push_back(ScreenlockState::NO_BLUETOOTH); states.push_back(ScreenlockState::NO_PHONE); states.push_back(ScreenlockState::PHONE_UNSUPPORTED); states.push_back(ScreenlockState::PHONE_NOT_LOCKABLE); states.push_back(ScreenlockState::PHONE_NOT_AUTHENTICATED); states.push_back(ScreenlockState::PHONE_LOCKED); states.push_back(ScreenlockState::PHONE_NOT_LOCKABLE); states.push_back(ScreenlockState::PHONE_UNSUPPORTED); states.push_back(ScreenlockState::RSSI_TOO_LOW); states.push_back(ScreenlockState::TX_POWER_TOO_HIGH); states.push_back(ScreenlockState::AUTHENTICATED); for (size_t i = 0; i < states.size(); ++i) { state_handler_->ChangeState(states[i]); EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::ONLINE_SIGN_IN, lock_handler_->GetAuthType(account_id_)); EXPECT_FALSE(lock_handler_->HasCustomIcon()); } std::vector hardlock_states; hardlock_states.push_back(EasyUnlockScreenlockStateHandler::NO_HARDLOCK); hardlock_states.push_back(EasyUnlockScreenlockStateHandler::USER_HARDLOCK); hardlock_states.push_back(EasyUnlockScreenlockStateHandler::PAIRING_CHANGED); hardlock_states.push_back(EasyUnlockScreenlockStateHandler::PAIRING_ADDED); hardlock_states.push_back(EasyUnlockScreenlockStateHandler::NO_PAIRING); hardlock_states.push_back(EasyUnlockScreenlockStateHandler::LOGIN_FAILED); for (size_t i = 0; i < hardlock_states.size(); ++i) { state_handler_->SetHardlockState(hardlock_states[i]); EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::ONLINE_SIGN_IN, lock_handler_->GetAuthType(account_id_)); EXPECT_FALSE(lock_handler_->HasCustomIcon()); } } TEST_F(EasyUnlockScreenlockStateHandlerTest, TrialRunMetrics) { base::HistogramTester histogram_tester; // Simulate the user clicking on the lock icon twice outside of a trial run. // No trial run metrics should be recorded. state_handler_->RecordClickOnLockIcon(); state_handler_->RecordClickOnLockIcon(); histogram_tester.ExpectTotalCount("EasyUnlock.TrialRun.Events", 0); // Simulate the user clicking on the lock icon three times during a trial run. state_handler_->SetTrialRun(); state_handler_->RecordClickOnLockIcon(); state_handler_->RecordClickOnLockIcon(); state_handler_->RecordClickOnLockIcon(); histogram_tester.ExpectTotalCount("EasyUnlock.TrialRun.Events", 4); histogram_tester.ExpectBucketCount("EasyUnlock.TrialRun.Events", EASY_UNLOCK_TRIAL_RUN_EVENT_LAUNCHED, 1); histogram_tester.ExpectBucketCount( "EasyUnlock.TrialRun.Events", EASY_UNLOCK_TRIAL_RUN_EVENT_CLICKED_LOCK_ICON, 3); } } // namespace