| // 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 "chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.h" |
| |
| #include <stddef.h> |
| |
| #include <map> |
| #include <memory> |
| #include <string> |
| #include <utility> |
| |
| #include "base/bind.h" |
| #include "base/macros.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/no_destructor.h" |
| #include "base/run_loop.h" |
| #include "base/values.h" |
| #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_notification_controller.h" |
| #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_factory.h" |
| #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.h" |
| #include "chrome/browser/chromeos/login/users/mock_user_manager.h" |
| #include "chrome/browser/chromeos/profiles/profile_helper.h" |
| #include "chrome/browser/prefs/browser_prefs.h" |
| #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/test/base/testing_browser_process.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "chromeos/dbus/dbus_thread_manager.h" |
| #include "chromeos/dbus/fake_power_manager_client.h" |
| #include "chromeos/dbus/power_manager/suspend.pb.h" |
| #include "chromeos/services/device_sync/public/cpp/fake_device_sync_client.h" |
| #include "chromeos/services/multidevice_setup/public/cpp/fake_multidevice_setup_client.h" |
| #include "components/account_id/account_id.h" |
| #include "components/signin/core/browser/account_info.h" |
| #include "components/sync_preferences/testing_pref_service_syncable.h" |
| #include "components/user_manager/scoped_user_manager.h" |
| #include "content/public/test/test_browser_thread_bundle.h" |
| #include "device/bluetooth/bluetooth_adapter_factory.h" |
| #include "device/bluetooth/test/mock_bluetooth_adapter.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| |
| using device::MockBluetoothAdapter; |
| using testing::_; |
| using testing::AnyNumber; |
| using testing::Return; |
| |
| namespace chromeos { |
| |
| namespace { |
| |
| // Emails for fake users used in tests. |
| const char kTestUserPrimary[] = "primary_user@nowhere.com"; |
| const char kTestUserSecondary[] = "secondary_user@nowhere.com"; |
| |
| class MockEasyUnlockNotificationController |
| : public EasyUnlockNotificationController { |
| public: |
| MockEasyUnlockNotificationController() |
| : EasyUnlockNotificationController(nullptr) {} |
| ~MockEasyUnlockNotificationController() override {} |
| |
| // EasyUnlockNotificationController: |
| MOCK_METHOD0(ShowChromebookAddedNotification, void()); |
| MOCK_METHOD0(ShowPairingChangeNotification, void()); |
| MOCK_METHOD1(ShowPairingChangeAppliedNotification, void(const std::string&)); |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(MockEasyUnlockNotificationController); |
| }; |
| |
| device_sync::FakeDeviceSyncClient* GetDefaultDeviceSyncClient() { |
| static base::NoDestructor<device_sync::FakeDeviceSyncClient> fake_client; |
| return fake_client.get(); |
| } |
| |
| multidevice_setup::FakeMultiDeviceSetupClient* |
| GetDefaultMultiDeviceSetupClient() { |
| static base::NoDestructor<multidevice_setup::FakeMultiDeviceSetupClient> |
| fake_client; |
| return fake_client.get(); |
| } |
| |
| // EasyUnlockService factory function injected into testing profiles. |
| std::unique_ptr<KeyedService> CreateEasyUnlockServiceForTest( |
| content::BrowserContext* context) { |
| std::unique_ptr<EasyUnlockServiceRegular> service( |
| new EasyUnlockServiceRegular( |
| Profile::FromBrowserContext(context), |
| nullptr /* secure_channel_client */, |
| std::make_unique<MockEasyUnlockNotificationController>(), |
| GetDefaultDeviceSyncClient(), GetDefaultMultiDeviceSetupClient())); |
| service->Initialize(); |
| return std::move(service); |
| } |
| |
| } // namespace |
| |
| class EasyUnlockServiceTest : public testing::Test { |
| protected: |
| EasyUnlockServiceTest() |
| : mock_user_manager_(new testing::NiceMock<MockUserManager>()), |
| scoped_user_manager_(base::WrapUnique(mock_user_manager_)), |
| is_bluetooth_adapter_present_(true) {} |
| |
| ~EasyUnlockServiceTest() override {} |
| |
| void SetUp() override { |
| mock_adapter_ = new testing::NiceMock<MockBluetoothAdapter>(); |
| device::BluetoothAdapterFactory::SetAdapterForTesting(mock_adapter_); |
| EXPECT_CALL(*mock_adapter_, IsPresent()) |
| .WillRepeatedly(testing::Invoke( |
| this, &EasyUnlockServiceTest::is_bluetooth_adapter_present)); |
| |
| std::unique_ptr<DBusThreadManagerSetter> dbus_setter = |
| DBusThreadManager::GetSetterForTesting(); |
| power_manager_client_ = new FakePowerManagerClient; |
| dbus_setter->SetPowerManagerClient( |
| std::unique_ptr<PowerManagerClient>(power_manager_client_)); |
| |
| ON_CALL(*mock_user_manager_, Shutdown()).WillByDefault(Return()); |
| ON_CALL(*mock_user_manager_, IsLoggedInAsUserWithGaiaAccount()) |
| .WillByDefault(Return(true)); |
| ON_CALL(*mock_user_manager_, IsCurrentUserNonCryptohomeDataEphemeral()) |
| .WillByDefault(Return(false)); |
| |
| TestingBrowserProcess::GetGlobal()->SetLocalState(&local_pref_service_); |
| RegisterLocalState(local_pref_service_.registry()); |
| |
| profile_ = SetUpProfile(kTestUserPrimary, &profile_gaia_id_); |
| } |
| |
| void TearDown() override { |
| TestingBrowserProcess::GetGlobal()->SetLocalState(nullptr); |
| } |
| |
| void SetEasyUnlockAllowedPolicy(bool allowed) { |
| profile_->GetTestingPrefService()->SetManagedPref( |
| prefs::kEasyUnlockAllowed, std::make_unique<base::Value>(allowed)); |
| } |
| |
| void set_is_bluetooth_adapter_present(bool is_present) { |
| is_bluetooth_adapter_present_ = is_present; |
| } |
| |
| bool is_bluetooth_adapter_present() const { |
| return is_bluetooth_adapter_present_; |
| } |
| |
| FakePowerManagerClient* power_manager_client() { |
| return power_manager_client_; |
| } |
| |
| // Sets up a test profile using the provided |email|. Will generate a unique |
| // gaia id and output to |gaia_id|. Returns the created TestingProfile. |
| std::unique_ptr<TestingProfile> SetUpProfile(const std::string& email, |
| std::string* gaia_id) { |
| std::unique_ptr<TestingProfile> profile = |
| IdentityTestEnvironmentProfileAdaptor:: |
| CreateProfileForIdentityTestEnvironment( |
| {{EasyUnlockServiceFactory::GetInstance(), |
| base::BindRepeating(&CreateEasyUnlockServiceForTest)}}); |
| |
| // Note: This can simply be a local variable as the test does not need to |
| // interact with IdentityTestEnvironment outside of this method. If that |
| // ever changes, there will need to be distinct instance variables for the |
| // environments associated with |profile_| and |secondary_profile_|. |
| IdentityTestEnvironmentProfileAdaptor identity_test_env_adaptor( |
| profile.get()); |
| AccountInfo account_info = |
| identity_test_env_adaptor.identity_test_env()->SetPrimaryAccount(email); |
| |
| *gaia_id = account_info.gaia; |
| |
| mock_user_manager_->AddUser( |
| AccountId::FromUserEmailGaiaId(email, *gaia_id)); |
| profile.get()->set_profile_name(email); |
| |
| return profile; |
| } |
| |
| void SetUpSecondaryProfile() { |
| secondary_profile_ = |
| SetUpProfile(kTestUserSecondary, &secondary_profile_gaia_id_); |
| } |
| |
| // Must outlive TestingProfiles. |
| content::TestBrowserThreadBundle thread_bundle_; |
| |
| std::unique_ptr<TestingProfile> profile_; |
| std::string profile_gaia_id_; |
| std::unique_ptr<TestingProfile> secondary_profile_; |
| std::string secondary_profile_gaia_id_; |
| MockUserManager* mock_user_manager_; |
| |
| private: |
| user_manager::ScopedUserManager scoped_user_manager_; |
| |
| FakePowerManagerClient* power_manager_client_; |
| |
| bool is_bluetooth_adapter_present_; |
| scoped_refptr<testing::NiceMock<MockBluetoothAdapter>> mock_adapter_; |
| |
| // PrefService which contains the browser process' local storage. |
| TestingPrefServiceSimple local_pref_service_; |
| |
| DISALLOW_COPY_AND_ASSIGN(EasyUnlockServiceTest); |
| }; |
| |
| TEST_F(EasyUnlockServiceTest, NoBluetoothNoService) { |
| set_is_bluetooth_adapter_present(false); |
| |
| EasyUnlockService* service = EasyUnlockService::Get(profile_.get()); |
| ASSERT_TRUE(service); |
| |
| EXPECT_FALSE(service->IsAllowed()); |
| } |
| |
| TEST_F(EasyUnlockServiceTest, NotAllowedForEphemeralAccounts) { |
| ON_CALL(*mock_user_manager_, IsCurrentUserNonCryptohomeDataEphemeral()) |
| .WillByDefault(Return(true)); |
| |
| EXPECT_FALSE(EasyUnlockService::Get(profile_.get())->IsAllowed()); |
| } |
| |
| TEST_F(EasyUnlockServiceTest, GetAccountId) { |
| EXPECT_EQ(AccountId::FromUserEmailGaiaId(kTestUserPrimary, profile_gaia_id_), |
| EasyUnlockService::Get(profile_.get())->GetAccountId()); |
| |
| SetUpSecondaryProfile(); |
| EXPECT_EQ(AccountId::FromUserEmailGaiaId(kTestUserSecondary, |
| secondary_profile_gaia_id_), |
| EasyUnlockService::Get(secondary_profile_.get())->GetAccountId()); |
| } |
| |
| } // namespace chromeos |