123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905 |
- // Copyright 2015 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 "ash/components/proximity_auth/unlock_manager_impl.h"
- #include <memory>
- #include <utility>
- #include "ash/components/multidevice/logging/logging.h"
- #include "ash/components/multidevice/remote_device_test_util.h"
- #include "ash/components/proximity_auth/fake_lock_handler.h"
- #include "ash/components/proximity_auth/fake_remote_device_life_cycle.h"
- #include "ash/components/proximity_auth/messenger.h"
- #include "ash/components/proximity_auth/mock_proximity_auth_client.h"
- #include "ash/components/proximity_auth/proximity_monitor.h"
- #include "ash/components/proximity_auth/remote_device_life_cycle.h"
- #include "ash/components/proximity_auth/remote_status_update.h"
- #include "ash/services/secure_channel/connection.h"
- #include "ash/services/secure_channel/public/cpp/client/fake_client_channel.h"
- #include "base/memory/ref_counted.h"
- #include "base/test/gmock_callback_support.h"
- #include "base/test/test_simple_task_runner.h"
- #include "base/threading/thread_task_runner_handle.h"
- #include "base/timer/mock_timer.h"
- #include "build/build_config.h"
- #include "chromeos/dbus/power/fake_power_manager_client.h"
- #include "chromeos/dbus/power/power_manager_client.h"
- #include "chromeos/dbus/power_manager/suspend.pb.h"
- #include "device/bluetooth/bluetooth_adapter_factory.h"
- #include "device/bluetooth/test/mock_bluetooth_adapter.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- using testing::_;
- using testing::AtLeast;
- using testing::Invoke;
- using testing::NiceMock;
- using testing::Return;
- namespace proximity_auth {
- namespace {
- using SmartLockState = ash::SmartLockState;
- // The sign-in challenge to send to the remote device.
- const char kChallenge[] = "sign-in challenge";
- const char kSignInSecret[] = "decrypted challenge";
- // Note that the trust agent state is currently ignored by the UnlockManager
- // implementation.
- RemoteStatusUpdate kRemoteScreenUnlocked = {
- USER_PRESENT, SECURE_SCREEN_LOCK_ENABLED, TRUST_AGENT_UNSUPPORTED};
- RemoteStatusUpdate kRemoteScreenLocked = {
- USER_ABSENT, SECURE_SCREEN_LOCK_ENABLED, TRUST_AGENT_UNSUPPORTED};
- RemoteStatusUpdate kRemoteScreenlockDisabled = {
- USER_PRESENT, SECURE_SCREEN_LOCK_DISABLED, TRUST_AGENT_UNSUPPORTED};
- RemoteStatusUpdate kRemoteScreenlockStateUnknown = {
- USER_PRESENCE_UNKNOWN, SECURE_SCREEN_LOCK_STATE_UNKNOWN,
- TRUST_AGENT_UNSUPPORTED};
- class MockMessenger : public Messenger {
- public:
- MockMessenger() {}
- MockMessenger(const MockMessenger&) = delete;
- MockMessenger& operator=(const MockMessenger&) = delete;
- ~MockMessenger() override {}
- MOCK_METHOD1(AddObserver, void(MessengerObserver* observer));
- MOCK_METHOD1(RemoveObserver, void(MessengerObserver* observer));
- MOCK_METHOD0(DispatchUnlockEvent, void());
- MOCK_METHOD1(RequestDecryption, void(const std::string& challenge));
- MOCK_METHOD0(RequestUnlock, void());
- MOCK_CONST_METHOD0(GetConnection, ash::secure_channel::Connection*());
- MOCK_CONST_METHOD0(GetChannel, ash::secure_channel::ClientChannel*());
- };
- class MockProximityMonitor : public ProximityMonitor {
- public:
- explicit MockProximityMonitor(base::OnceClosure destroy_callback)
- : destroy_callback_(std::move(destroy_callback)), started_(false) {
- ON_CALL(*this, IsUnlockAllowed()).WillByDefault(Return(true));
- }
- MockProximityMonitor(const MockProximityMonitor&) = delete;
- MockProximityMonitor& operator=(const MockProximityMonitor&) = delete;
- ~MockProximityMonitor() override { std::move(destroy_callback_).Run(); }
- void Start() override { started_ = true; }
- void Stop() override {}
- MOCK_CONST_METHOD0(IsUnlockAllowed, bool());
- MOCK_METHOD0(RecordProximityMetricsOnAuthSuccess, void());
- bool started() { return started_; }
- private:
- base::OnceClosure destroy_callback_;
- bool started_;
- };
- class TestUnlockManager : public UnlockManagerImpl {
- public:
- TestUnlockManager(ProximityAuthSystem::ScreenlockType screenlock_type,
- ProximityAuthClient* proximity_auth_client)
- : UnlockManagerImpl(screenlock_type, proximity_auth_client) {}
- TestUnlockManager(const TestUnlockManager&) = delete;
- TestUnlockManager& operator=(const TestUnlockManager&) = delete;
- ~TestUnlockManager() override {}
- using MessengerObserver::OnDecryptResponse;
- using MessengerObserver::OnDisconnected;
- using MessengerObserver::OnRemoteStatusUpdate;
- using MessengerObserver::OnUnlockEventSent;
- using MessengerObserver::OnUnlockResponse;
- using UnlockManager::OnAuthAttempted;
- MockProximityMonitor* proximity_monitor() { return proximity_monitor_; }
- bool proximity_monitor_destroyed() { return proximity_monitor_destroyed_; }
- private:
- std::unique_ptr<ProximityMonitor> CreateProximityMonitor(
- RemoteDeviceLifeCycle* life_cycle) override {
- std::unique_ptr<MockProximityMonitor> proximity_monitor(
- new NiceMock<MockProximityMonitor>(
- base::BindOnce(&TestUnlockManager::OnProximityMonitorDestroyed,
- base::Unretained(this))));
- proximity_monitor_destroyed_ = false;
- proximity_monitor_ = proximity_monitor.get();
- return proximity_monitor;
- }
- void OnProximityMonitorDestroyed() { proximity_monitor_destroyed_ = true; }
- // Owned by the super class.
- MockProximityMonitor* proximity_monitor_ = nullptr;
- bool proximity_monitor_destroyed_ = false;
- };
- // Creates a mock Bluetooth adapter and sets it as the global adapter for
- // testing.
- scoped_refptr<device::MockBluetoothAdapter>
- CreateAndRegisterMockBluetoothAdapter() {
- scoped_refptr<device::MockBluetoothAdapter> adapter =
- new NiceMock<device::MockBluetoothAdapter>();
- device::BluetoothAdapterFactory::SetAdapterForTesting(adapter);
- return adapter;
- }
- } // namespace
- class ProximityAuthUnlockManagerImplTest : public testing::Test {
- public:
- ProximityAuthUnlockManagerImplTest()
- : remote_device_(ash::multidevice::CreateRemoteDeviceRefForTest()),
- local_device_(ash::multidevice::CreateRemoteDeviceRefForTest()),
- life_cycle_(remote_device_, local_device_),
- fake_client_channel_(
- std::make_unique<ash::secure_channel::FakeClientChannel>()),
- bluetooth_adapter_(CreateAndRegisterMockBluetoothAdapter()),
- task_runner_(new base::TestSimpleTaskRunner()),
- thread_task_runner_handle_(task_runner_) {}
- ~ProximityAuthUnlockManagerImplTest() override = default;
- void SetUp() override {
- chromeos::PowerManagerClient::InitializeFake();
- ON_CALL(*bluetooth_adapter_, IsPresent()).WillByDefault(Return(true));
- ON_CALL(*bluetooth_adapter_, IsPowered()).WillByDefault(Return(true));
- ON_CALL(messenger_, GetChannel())
- .WillByDefault(Return(fake_client_channel_.get()));
- life_cycle_.set_messenger(&messenger_);
- life_cycle_.set_channel(fake_client_channel_.get());
- }
- void TearDown() override {
- // Make sure to verify the mock prior to the destruction of the unlock
- // manager, as otherwise it's impossible to tell whether calls to Stop()
- // occur as a side-effect of the destruction or from the code intended to be
- // under test.
- if (proximity_monitor())
- testing::Mock::VerifyAndClearExpectations(proximity_monitor());
- unlock_manager_.reset();
- chromeos::PowerManagerClient::Shutdown();
- }
- void CreateUnlockManager(
- ProximityAuthSystem::ScreenlockType screenlock_type) {
- unlock_manager_ = std::make_unique<TestUnlockManager>(
- screenlock_type, &proximity_auth_client_);
- auto mock_timer = std::make_unique<base::MockOneShotTimer>();
- mock_bluetooth_suspension_recovery_timer_ = mock_timer.get();
- unlock_manager_->SetBluetoothSuspensionRecoveryTimerForTesting(
- std::move(mock_timer));
- }
- void SimulateUserPresentState() {
- unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_);
- life_cycle_.ChangeState(
- RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED);
- unlock_manager_->OnRemoteStatusUpdate(kRemoteScreenUnlocked);
- }
- void RunPendingTasks() { task_runner_->RunPendingTasks(); }
- MockProximityMonitor* proximity_monitor() {
- return unlock_manager_ ? unlock_manager_->proximity_monitor() : nullptr;
- }
- bool proximity_monitor_destroyed() {
- return unlock_manager_ ? unlock_manager_->proximity_monitor_destroyed()
- : false;
- }
- protected:
- ash::multidevice::RemoteDeviceRef remote_device_;
- ash::multidevice::RemoteDeviceRef local_device_;
- FakeRemoteDeviceLifeCycle life_cycle_;
- std::unique_ptr<ash::secure_channel::FakeClientChannel> fake_client_channel_;
- // Mock used for verifying interactions with the Bluetooth subsystem.
- scoped_refptr<device::MockBluetoothAdapter> bluetooth_adapter_;
- NiceMock<MockProximityAuthClient> proximity_auth_client_;
- NiceMock<MockMessenger> messenger_;
- std::unique_ptr<TestUnlockManager> unlock_manager_;
- base::MockOneShotTimer* mock_bluetooth_suspension_recovery_timer_ = nullptr;
- private:
- scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
- base::ThreadTaskRunnerHandle thread_task_runner_handle_;
- FakeLockHandler lock_handler_;
- ash::multidevice::ScopedDisableLoggingForTesting disable_logging_;
- };
- TEST_F(ProximityAuthUnlockManagerImplTest, IsUnlockAllowed_InitialState) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- EXPECT_FALSE(unlock_manager_->IsUnlockAllowed());
- }
- TEST_F(ProximityAuthUnlockManagerImplTest,
- IsUnlockAllowed_SessionLock_AllGood) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_);
- life_cycle_.ChangeState(
- RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED);
- unlock_manager_->OnRemoteStatusUpdate(kRemoteScreenUnlocked);
- EXPECT_TRUE(unlock_manager_->IsUnlockAllowed());
- }
- TEST_F(ProximityAuthUnlockManagerImplTest, IsUnlockAllowed_SignIn_AllGood) {
- CreateUnlockManager(ProximityAuthSystem::SIGN_IN);
- unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_);
- life_cycle_.ChangeState(
- RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED);
- unlock_manager_->OnRemoteStatusUpdate(kRemoteScreenUnlocked);
- EXPECT_TRUE(unlock_manager_->IsUnlockAllowed());
- }
- TEST_F(ProximityAuthUnlockManagerImplTest,
- IsUnlockAllowed_DisallowedByProximityMonitor) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_);
- life_cycle_.ChangeState(
- RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED);
- ON_CALL(*proximity_monitor(), IsUnlockAllowed()).WillByDefault(Return(false));
- unlock_manager_->OnRemoteStatusUpdate(kRemoteScreenUnlocked);
- EXPECT_FALSE(unlock_manager_->IsUnlockAllowed());
- }
- TEST_F(ProximityAuthUnlockManagerImplTest,
- IsUnlockAllowed_RemoteDeviceLifeCycleIsNull) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- unlock_manager_->SetRemoteDeviceLifeCycle(nullptr);
- unlock_manager_->OnRemoteStatusUpdate(kRemoteScreenUnlocked);
- EXPECT_FALSE(unlock_manager_->IsUnlockAllowed());
- }
- TEST_F(ProximityAuthUnlockManagerImplTest,
- IsUnlockAllowed_RemoteScreenlockStateLocked) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_);
- life_cycle_.ChangeState(
- RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED);
- unlock_manager_->OnRemoteStatusUpdate(kRemoteScreenLocked);
- EXPECT_FALSE(unlock_manager_->IsUnlockAllowed());
- }
- TEST_F(ProximityAuthUnlockManagerImplTest, IsUnlockAllowed_UserIsSecondary) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_);
- life_cycle_.ChangeState(
- RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED);
- unlock_manager_->OnRemoteStatusUpdate({USER_PRESENCE_SECONDARY,
- SECURE_SCREEN_LOCK_ENABLED,
- TRUST_AGENT_UNSUPPORTED});
- EXPECT_FALSE(unlock_manager_->IsUnlockAllowed());
- }
- TEST_F(ProximityAuthUnlockManagerImplTest,
- IsUnlockAllowed_PrimaryUserInBackground) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_);
- life_cycle_.ChangeState(
- RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED);
- unlock_manager_->OnRemoteStatusUpdate({USER_PRESENCE_BACKGROUND,
- SECURE_SCREEN_LOCK_ENABLED,
- TRUST_AGENT_UNSUPPORTED});
- EXPECT_FALSE(unlock_manager_->IsUnlockAllowed());
- }
- TEST_F(ProximityAuthUnlockManagerImplTest,
- IsUnlockAllowed_RemoteScreenlockStateUnknown) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_);
- life_cycle_.ChangeState(
- RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED);
- unlock_manager_->OnRemoteStatusUpdate(kRemoteScreenlockStateUnknown);
- EXPECT_FALSE(unlock_manager_->IsUnlockAllowed());
- }
- TEST_F(ProximityAuthUnlockManagerImplTest,
- IsUnlockAllowed_RemoteScreenlockStateDisabled) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_);
- life_cycle_.ChangeState(
- RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED);
- unlock_manager_->OnRemoteStatusUpdate(kRemoteScreenlockDisabled);
- EXPECT_FALSE(unlock_manager_->IsUnlockAllowed());
- }
- TEST_F(ProximityAuthUnlockManagerImplTest,
- IsUnlockAllowed_RemoteScreenlockStateNotYetReceived) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_);
- life_cycle_.ChangeState(
- RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED);
- EXPECT_FALSE(unlock_manager_->IsUnlockAllowed());
- }
- TEST_F(ProximityAuthUnlockManagerImplTest, SetRemoteDeviceLifeCycle_SetToNull) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- SimulateUserPresentState();
- EXPECT_CALL(proximity_auth_client_,
- UpdateSmartLockState(SmartLockState::kInactive));
- unlock_manager_->SetRemoteDeviceLifeCycle(nullptr);
- }
- TEST_F(ProximityAuthUnlockManagerImplTest,
- SetRemoteDeviceLifeCycle_ExistingRemoteDeviceLifeCycle) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- SimulateUserPresentState();
- EXPECT_CALL(proximity_auth_client_,
- UpdateSmartLockState(SmartLockState::kConnectingToPhone));
- unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_);
- }
- TEST_F(ProximityAuthUnlockManagerImplTest,
- SetRemoteDeviceLifeCycle_AuthenticationFailed) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- SimulateUserPresentState();
- unlock_manager_->SetRemoteDeviceLifeCycle(nullptr);
- life_cycle_.ChangeState(RemoteDeviceLifeCycle::State::AUTHENTICATION_FAILED);
- EXPECT_CALL(proximity_auth_client_,
- UpdateSmartLockState(SmartLockState::kPhoneNotAuthenticated));
- unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_);
- }
- TEST_F(ProximityAuthUnlockManagerImplTest, SetRemoteDeviceLifeCycle_WakingUp) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- SimulateUserPresentState();
- unlock_manager_->SetRemoteDeviceLifeCycle(nullptr);
- life_cycle_.ChangeState(RemoteDeviceLifeCycle::State::FINDING_CONNECTION);
- EXPECT_CALL(proximity_auth_client_,
- UpdateSmartLockState(SmartLockState::kConnectingToPhone));
- unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_);
- }
- TEST_F(ProximityAuthUnlockManagerImplTest,
- SetRemoteDeviceLifeCycle_TimesOutBeforeConnection) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- life_cycle_.set_messenger(nullptr);
- life_cycle_.ChangeState(RemoteDeviceLifeCycle::State::FINDING_CONNECTION);
- EXPECT_CALL(proximity_auth_client_,
- UpdateSmartLockState(SmartLockState::kConnectingToPhone));
- unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_);
- EXPECT_CALL(proximity_auth_client_,
- UpdateSmartLockState(SmartLockState::kPhoneNotFound));
- // Simulate timing out before a connection is established.
- RunPendingTasks();
- }
- TEST_F(ProximityAuthUnlockManagerImplTest,
- SetRemoteDeviceLifeCycle_NullRemoteDeviceLifeCycle_NoProximityMonitor) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- SimulateUserPresentState();
- unlock_manager_->SetRemoteDeviceLifeCycle(nullptr);
- }
- TEST_F(
- ProximityAuthUnlockManagerImplTest,
- SetRemoteDeviceLifeCycle_ConnectingRemoteDeviceLifeCycle_StopsProximityMonitor) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- SimulateUserPresentState();
- life_cycle_.ChangeState(RemoteDeviceLifeCycle::State::FINDING_CONNECTION);
- EXPECT_TRUE(proximity_monitor_destroyed());
- }
- TEST_F(
- ProximityAuthUnlockManagerImplTest,
- SetRemoteDeviceLifeCycle_ConnectedRemoteDeviceLifeCycle_StartsProximityMonitor) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_);
- life_cycle_.ChangeState(
- RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED);
- EXPECT_TRUE(proximity_monitor()->started());
- }
- // Regression test for crbug.com/931929. Capture the case where the phone is
- // connected to, connection is lost, and then a new connection is made shortly
- // after.
- TEST_F(ProximityAuthUnlockManagerImplTest,
- SetRemoteDeviceLifeCycle_TwiceConnectedRemoteDeviceLifeCycle) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_);
- life_cycle_.ChangeState(
- RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED);
- EXPECT_TRUE(proximity_monitor()->started());
- // Simulate the phone connection being lost. The ProximityMonitor is stale
- // and should have been destroyed.
- life_cycle_.ChangeState(RemoteDeviceLifeCycle::State::FINDING_CONNECTION);
- EXPECT_TRUE(proximity_monitor_destroyed());
- life_cycle_.ChangeState(
- RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED);
- EXPECT_FALSE(proximity_monitor_destroyed());
- EXPECT_TRUE(proximity_monitor()->started());
- }
- TEST_F(ProximityAuthUnlockManagerImplTest, BluetoothAdapterNotPresent) {
- ON_CALL(*bluetooth_adapter_, IsPresent()).WillByDefault(Return(false));
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- EXPECT_CALL(proximity_auth_client_,
- UpdateSmartLockState(SmartLockState::kBluetoothDisabled));
- unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_);
- EXPECT_FALSE(life_cycle_.started());
- }
- TEST_F(ProximityAuthUnlockManagerImplTest, BluetoothAdapterPowerChanges) {
- ON_CALL(*bluetooth_adapter_, IsPowered()).WillByDefault(Return(false));
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- EXPECT_CALL(proximity_auth_client_,
- UpdateSmartLockState(SmartLockState::kBluetoothDisabled));
- unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_);
- EXPECT_FALSE(life_cycle_.started());
- EXPECT_CALL(proximity_auth_client_,
- UpdateSmartLockState(SmartLockState::kConnectingToPhone));
- ON_CALL(*bluetooth_adapter_, IsPowered()).WillByDefault(Return(true));
- bluetooth_adapter_->NotifyAdapterPoweredChanged(true);
- EXPECT_TRUE(life_cycle_.started());
- }
- TEST_F(
- ProximityAuthUnlockManagerImplTest,
- CacheBluetoothAdapterStateAfterSuspendAndResume_AttemptConnectionWhileBluetoothAdapterIsStillRecovering) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- ASSERT_FALSE(mock_bluetooth_suspension_recovery_timer_->IsRunning());
- chromeos::FakePowerManagerClient::Get()->SendSuspendImminent(
- power_manager::SuspendImminent_Reason_LID_CLOSED);
- // Simulate https://crbug.com/986896 by returning false for presence and power
- // directly after resuming, but do not fire
- // |mock_bluetooth_suspension_recovery_timer_|, simulating that not enough
- // time has passed for the BluetoothAdapter to recover. It's expected under
- // these conditions that:
- // * ProximityAuthClient::UpdateSmartLockState() never be called with
- // SmartLockState::kBluetoothDisabled.
- // * ProximityAuthClient::UpdateSmartLockState() only be called once with
- // SmartLockState::BLUETOOTH_CONNECTING, because it should only be called
- // on when the SmartLockState value changes.
- EXPECT_CALL(proximity_auth_client_,
- UpdateSmartLockState(SmartLockState::kBluetoothDisabled))
- .Times(0);
- EXPECT_CALL(proximity_auth_client_,
- UpdateSmartLockState(SmartLockState::kConnectingToPhone));
- ON_CALL(*bluetooth_adapter_, IsPresent()).WillByDefault(Return(false));
- ON_CALL(*bluetooth_adapter_, IsPowered()).WillByDefault(Return(false));
- chromeos::FakePowerManagerClient::Get()->SendSuspendDone();
- EXPECT_TRUE(mock_bluetooth_suspension_recovery_timer_->IsRunning());
- // Simulate how ProximityAuthSystem, the owner of UnlockManager, reacts to
- // resume: providing a new RemoteDeviceLifeCycle. This shouldn't trigger a new
- // call to ProximityAuthClient::UpdateSmartLockState().
- unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_);
- EXPECT_TRUE(life_cycle_.started());
- EXPECT_TRUE(mock_bluetooth_suspension_recovery_timer_->IsRunning());
- }
- TEST_F(
- ProximityAuthUnlockManagerImplTest,
- CacheBluetoothAdapterStateAfterSuspendAndResume_AttemptConnectionOnceBluetoothAdapterHasHadTimeToRecover) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- ASSERT_FALSE(mock_bluetooth_suspension_recovery_timer_->IsRunning());
- chromeos::FakePowerManagerClient::Get()->SendSuspendImminent(
- power_manager::SuspendImminent_Reason_LID_CLOSED);
- // Simulate https://crbug.com/986896 by returning false for presence and power
- // directly after resuming, and then fire
- // |mock_bluetooth_suspension_recovery_timer_|, simulating that enough time
- // has passed for the BluetoothAdapter to recover - this means that Bluetooth
- // is truly off after resume and the user should be visually informed as such.
- // It's expected under these conditions that:
- // * ProximityAuthClient::UpdateSmartLockState() only be called once with
- // SmartLockState::kBluetoothDisabled, but after the timer fires (this is
- // impossible to explicitly do in code with mocks, unfortunately).
- // * ProximityAuthClient::UpdateSmartLockState() only be called once with
- // SmartLockState::BLUETOOTH_CONNECTING, directly after SuspendDone.
- EXPECT_CALL(proximity_auth_client_,
- UpdateSmartLockState(SmartLockState::kBluetoothDisabled));
- EXPECT_CALL(proximity_auth_client_,
- UpdateSmartLockState(SmartLockState::kConnectingToPhone));
- ON_CALL(*bluetooth_adapter_, IsPresent()).WillByDefault(Return(false));
- ON_CALL(*bluetooth_adapter_, IsPowered()).WillByDefault(Return(false));
- chromeos::FakePowerManagerClient::Get()->SendSuspendDone();
- EXPECT_TRUE(mock_bluetooth_suspension_recovery_timer_->IsRunning());
- // Simulate how ProximityAuthSystem, the owner of UnlockManager, reacts to
- // resume: providing a new RemoteDeviceLifeCycle. This shouldn't trigger a new
- // call to ProximityAuthClient::UpdateSmartLockState().
- unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_);
- EXPECT_TRUE(life_cycle_.started());
- ON_CALL(*bluetooth_adapter_, IsPresent()).WillByDefault(Return(false));
- ON_CALL(*bluetooth_adapter_, IsPowered()).WillByDefault(Return(false));
- EXPECT_TRUE(mock_bluetooth_suspension_recovery_timer_->IsRunning());
- // This leads to ProximityAuthClient::UpdateSmartLockState() being called
- // with SmartLockState::NO_BLUETOOTH.
- mock_bluetooth_suspension_recovery_timer_->Fire();
- }
- TEST_F(
- ProximityAuthUnlockManagerImplTest,
- InitialScanAfterSuspendResume_DontPerformInitialScanIfConnectionEstablished) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- ASSERT_FALSE(mock_bluetooth_suspension_recovery_timer_->IsRunning());
- // Simulates the lid of chromebook closing resulting in suspension.
- chromeos::FakePowerManagerClient::Get()->SendSuspendImminent(
- power_manager::SuspendImminent_Reason_LID_CLOSED);
- EXPECT_CALL(
- proximity_auth_client_,
- UpdateSmartLockState(SmartLockState::kPhoneFoundLockedAndProximate))
- .Times(1);
- EXPECT_CALL(proximity_auth_client_,
- UpdateSmartLockState(SmartLockState::kConnectingToPhone))
- .Times(1);
- // We want to emulate a bluetooth adapter that is present and powered
- // upon lid reopen and resume, because we are testing the code path
- // within OnBluetoothAdapterPresentAndPowerChanged() after the
- // suspension timer concludes.
- ON_CALL(*bluetooth_adapter_, IsPresent()).WillByDefault(Return(true));
- ON_CALL(*bluetooth_adapter_, IsPowered()).WillByDefault(Return(true));
- // This event simulates reopen of lid resulting in resume.
- chromeos::FakePowerManagerClient::Get()->SendSuspendDone();
- EXPECT_TRUE(mock_bluetooth_suspension_recovery_timer_->IsRunning());
- // Start the life cycle for unlock manager.
- unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_);
- EXPECT_TRUE(life_cycle_.started());
- // Simulate a secure channel connection established with phone.
- life_cycle_.ChangeState(
- RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED);
- // Simulate the phone responding with locked and proximate.
- unlock_manager_->OnRemoteStatusUpdate(kRemoteScreenLocked);
- EXPECT_TRUE(mock_bluetooth_suspension_recovery_timer_->IsRunning());
- // Time out the suspension recovery timer so we run
- // OnBluetoothAdapterPresentAndPowerChanged().
- mock_bluetooth_suspension_recovery_timer_->Fire();
- }
- TEST_F(ProximityAuthUnlockManagerImplTest,
- BluetoothOffMessageShownImmediatelyIfBluetoothWasOffBeforeSuspend) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- ON_CALL(*bluetooth_adapter_, IsPresent()).WillByDefault(Return(false));
- ON_CALL(*bluetooth_adapter_, IsPowered()).WillByDefault(Return(false));
- chromeos::FakePowerManagerClient::Get()->SendSuspendImminent(
- power_manager::SuspendImminent_Reason_LID_CLOSED);
- EXPECT_CALL(proximity_auth_client_,
- UpdateSmartLockState(SmartLockState::kBluetoothDisabled));
- EXPECT_CALL(proximity_auth_client_,
- UpdateSmartLockState(SmartLockState::kConnectingToPhone))
- .Times(0);
- chromeos::FakePowerManagerClient::Get()->SendSuspendDone();
- // Simulate how ProximityAuthSystem, the owner of UnlockManager, reacts to
- // resume: providing a new RemoteDeviceLifeCycle.
- unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_);
- EXPECT_FALSE(life_cycle_.started());
- }
- TEST_F(ProximityAuthUnlockManagerImplTest, StartsProximityMonitor) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- SimulateUserPresentState();
- EXPECT_TRUE(proximity_monitor()->started());
- }
- TEST_F(ProximityAuthUnlockManagerImplTest,
- OnAuthenticationFailed_StopsProximityMonitor) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- SimulateUserPresentState();
- life_cycle_.ChangeState(RemoteDeviceLifeCycle::State::AUTHENTICATION_FAILED);
- EXPECT_TRUE(proximity_monitor_destroyed());
- }
- TEST_F(ProximityAuthUnlockManagerImplTest,
- AuthenticationFailed_UpdatesSmartLockState) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- SimulateUserPresentState();
- EXPECT_CALL(proximity_auth_client_,
- UpdateSmartLockState(SmartLockState::kPhoneNotAuthenticated));
- life_cycle_.ChangeState(RemoteDeviceLifeCycle::State::AUTHENTICATION_FAILED);
- }
- TEST_F(ProximityAuthUnlockManagerImplTest,
- FindingConnection_UpdatesSmartLockState) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- // Regression test for https://crbug.com/890047, ensuring that the NO_PHONE
- // status doesn't incorrectly appear for a brief moment before the
- // BLUETOOTH_CONNECTING spinner.
- EXPECT_CALL(proximity_auth_client_,
- UpdateSmartLockState(SmartLockState::kPhoneNotFound))
- .Times(0);
- EXPECT_CALL(proximity_auth_client_,
- UpdateSmartLockState(SmartLockState::kConnectingToPhone));
- unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_);
- EXPECT_TRUE(life_cycle_.started());
- }
- TEST_F(ProximityAuthUnlockManagerImplTest,
- Authenticating_UpdatesSmartLockState) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- // Regression test for https://crbug.com/890047, ensuring that the NO_PHONE
- // status doesn't incorrectly appear for a brief moment before the
- // BLUETOOTH_CONNECTING spinner.
- EXPECT_CALL(proximity_auth_client_,
- UpdateSmartLockState(SmartLockState::kPhoneNotFound))
- .Times(0);
- EXPECT_CALL(proximity_auth_client_,
- UpdateSmartLockState(SmartLockState::kConnectingToPhone));
- unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_);
- EXPECT_TRUE(life_cycle_.started());
- life_cycle_.ChangeState(RemoteDeviceLifeCycle::State::AUTHENTICATING);
- }
- TEST_F(ProximityAuthUnlockManagerImplTest,
- OnDecryptResponse_NoAuthAttemptInProgress) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- SimulateUserPresentState();
- EXPECT_CALL(proximity_auth_client_, FinalizeUnlock(_)).Times(0);
- unlock_manager_.get()->OnDecryptResponse(kSignInSecret);
- }
- TEST_F(ProximityAuthUnlockManagerImplTest,
- OnUnlockEventSent_NoAuthAttemptInProgress) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- SimulateUserPresentState();
- EXPECT_CALL(proximity_auth_client_, FinalizeUnlock(_)).Times(0);
- unlock_manager_.get()->OnUnlockEventSent(true);
- }
- TEST_F(ProximityAuthUnlockManagerImplTest,
- OnUnlockResponse_NoAuthAttemptInProgress) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- SimulateUserPresentState();
- EXPECT_CALL(proximity_auth_client_, FinalizeUnlock(_)).Times(0);
- unlock_manager_.get()->OnUnlockResponse(true);
- }
- TEST_F(ProximityAuthUnlockManagerImplTest,
- OnAuthAttempted_NoRemoteDeviceLifeCycle) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- SimulateUserPresentState();
- unlock_manager_->SetRemoteDeviceLifeCycle(nullptr);
- EXPECT_CALL(proximity_auth_client_, FinalizeUnlock(false));
- unlock_manager_->OnAuthAttempted(mojom::AuthType::USER_CLICK);
- }
- TEST_F(ProximityAuthUnlockManagerImplTest, OnAuthAttempted_UnlockNotAllowed) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- SimulateUserPresentState();
- ON_CALL(*proximity_monitor(), IsUnlockAllowed()).WillByDefault(Return(false));
- EXPECT_CALL(proximity_auth_client_, FinalizeUnlock(false));
- unlock_manager_->OnAuthAttempted(mojom::AuthType::USER_CLICK);
- }
- TEST_F(ProximityAuthUnlockManagerImplTest, OnAuthAttempted_NotUserClick) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- SimulateUserPresentState();
- EXPECT_CALL(proximity_auth_client_, FinalizeUnlock(_)).Times(0);
- unlock_manager_->OnAuthAttempted(mojom::AuthType::EXPAND_THEN_USER_CLICK);
- }
- TEST_F(ProximityAuthUnlockManagerImplTest, OnAuthAttempted_DuplicateCall) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- SimulateUserPresentState();
- EXPECT_CALL(messenger_, RequestUnlock());
- unlock_manager_->OnAuthAttempted(mojom::AuthType::USER_CLICK);
- EXPECT_CALL(messenger_, RequestUnlock()).Times(0);
- unlock_manager_->OnAuthAttempted(mojom::AuthType::USER_CLICK);
- }
- TEST_F(ProximityAuthUnlockManagerImplTest, OnAuthAttempted_TimesOut) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- SimulateUserPresentState();
- unlock_manager_->OnAuthAttempted(mojom::AuthType::USER_CLICK);
- // Simulate the timeout period elapsing.
- EXPECT_CALL(proximity_auth_client_, FinalizeUnlock(false));
- RunPendingTasks();
- }
- TEST_F(ProximityAuthUnlockManagerImplTest,
- OnAuthAttempted_DoesntTimeOutFollowingResponse) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- SimulateUserPresentState();
- unlock_manager_->OnAuthAttempted(mojom::AuthType::USER_CLICK);
- EXPECT_CALL(proximity_auth_client_, FinalizeUnlock(_));
- unlock_manager_->OnUnlockResponse(false);
- // Simulate the timeout period elapsing.
- EXPECT_CALL(proximity_auth_client_, FinalizeUnlock(_)).Times(0);
- RunPendingTasks();
- }
- TEST_F(ProximityAuthUnlockManagerImplTest,
- OnAuthAttempted_Unlock_UnlockRequestFails) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- SimulateUserPresentState();
- EXPECT_CALL(messenger_, RequestUnlock());
- unlock_manager_->OnAuthAttempted(mojom::AuthType::USER_CLICK);
- EXPECT_CALL(proximity_auth_client_, FinalizeUnlock(false));
- unlock_manager_->OnUnlockResponse(false);
- }
- TEST_F(ProximityAuthUnlockManagerImplTest,
- OnAuthAttempted_Unlock_WithSignIn_RequestSucceeds_EventSendFails) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- SimulateUserPresentState();
- EXPECT_CALL(messenger_, RequestUnlock());
- unlock_manager_->OnAuthAttempted(mojom::AuthType::USER_CLICK);
- EXPECT_CALL(messenger_, DispatchUnlockEvent());
- unlock_manager_->OnUnlockResponse(true);
- EXPECT_CALL(proximity_auth_client_, FinalizeUnlock(false));
- unlock_manager_->OnUnlockEventSent(false);
- }
- TEST_F(ProximityAuthUnlockManagerImplTest,
- OnAuthAttempted_Unlock_RequestSucceeds_EventSendSucceeds) {
- CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
- SimulateUserPresentState();
- EXPECT_CALL(messenger_, RequestUnlock());
- unlock_manager_->OnAuthAttempted(mojom::AuthType::USER_CLICK);
- EXPECT_CALL(messenger_, DispatchUnlockEvent());
- unlock_manager_->OnUnlockResponse(true);
- EXPECT_CALL(proximity_auth_client_, FinalizeUnlock(true));
- unlock_manager_->OnUnlockEventSent(true);
- }
- TEST_F(ProximityAuthUnlockManagerImplTest, OnAuthAttempted_SignIn_Success) {
- CreateUnlockManager(ProximityAuthSystem::SIGN_IN);
- SimulateUserPresentState();
- std::string channel_binding_data = "channel binding data";
- EXPECT_CALL(proximity_auth_client_,
- GetChallengeForUserAndDevice(remote_device_.user_email(),
- remote_device_.public_key(),
- channel_binding_data, _))
- .WillOnce(base::test::RunOnceCallback<3>(kChallenge));
- EXPECT_CALL(messenger_, RequestDecryption(kChallenge));
- unlock_manager_->OnAuthAttempted(mojom::AuthType::USER_CLICK);
- std::vector<ash::secure_channel::mojom::ConnectionCreationDetail>
- creation_details{ash::secure_channel::mojom::ConnectionCreationDetail::
- REMOTE_DEVICE_USED_BACKGROUND_BLE_ADVERTISING};
- ash::secure_channel::mojom::ConnectionMetadataPtr connection_metadata_ptr =
- ash::secure_channel::mojom::ConnectionMetadata::New(
- creation_details, nullptr /* bluetooth_connection_metadata */,
- channel_binding_data);
- fake_client_channel_->InvokePendingGetConnectionMetadataCallback(
- std::move(connection_metadata_ptr));
- EXPECT_CALL(messenger_, DispatchUnlockEvent());
- unlock_manager_->OnDecryptResponse(kSignInSecret);
- EXPECT_CALL(proximity_auth_client_, FinalizeSignin(kSignInSecret));
- unlock_manager_->OnUnlockEventSent(true);
- }
- } // namespace proximity_auth
|