1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
8 #include "base/macros.h"
9 #include "base/run_loop.h"
10 #include "base/values.h"
11 #include "chrome/browser/chromeos/login/users/mock_user_manager.h"
12 #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
13 #include "chrome/browser/chromeos/profiles/profile_helper.h"
14 #include "chrome/browser/signin/easy_unlock_app_manager.h"
15 #include "chrome/browser/signin/easy_unlock_service.h"
16 #include "chrome/browser/signin/easy_unlock_service_factory.h"
17 #include "chrome/browser/signin/easy_unlock_service_regular.h"
18 #include "chrome/browser/signin/signin_manager_factory.h"
19 #include "chrome/common/pref_names.h"
20 #include "chrome/test/base/testing_pref_service_syncable.h"
21 #include "chrome/test/base/testing_profile.h"
22 #include "chromeos/dbus/dbus_thread_manager.h"
23 #include "chromeos/dbus/fake_power_manager_client.h"
24 #include "components/signin/core/browser/signin_manager_base.h"
25 #include "content/public/test/test_browser_thread_bundle.h"
26 #include "device/bluetooth/bluetooth_adapter_factory.h"
27 #include "device/bluetooth/test/mock_bluetooth_adapter.h"
28 #include "testing/gmock/include/gmock/gmock.h"
30 using chromeos::DBusThreadManagerSetter
;
31 using chromeos::FakePowerManagerClient
;
32 using chromeos::PowerManagerClient
;
33 using chromeos::ProfileHelper
;
34 using device::MockBluetoothAdapter
;
36 using testing::AnyNumber
;
37 using testing::Return
;
41 // IDs for fake users used in tests.
42 const char kTestUserPrimary
[] = "primary_user@nowhere.com";
43 const char kTestUserSecondary
[] = "secondary_user@nowhere.com";
45 // App manager to be used in EasyUnlockService tests.
46 // This effectivelly abstracts the extension system from the tests.
47 class TestAppManager
: public EasyUnlockAppManager
{
50 : state_(STATE_NOT_LOADED
),
51 app_launch_count_(0u),
54 ~TestAppManager() override
{}
56 // The easy unlock app state.
57 enum State
{ STATE_NOT_LOADED
, STATE_LOADED
, STATE_DISABLED
};
59 State
state() const { return state_
; }
60 size_t app_launch_count() const { return app_launch_count_
; }
61 size_t reload_count() const { return reload_count_
; }
63 // Marks the manager as ready and runs |ready_callback_| if there is one set.
66 if (!ready_callback_
.is_null()) {
67 ready_callback_
.Run();
68 ready_callback_
= base::Closure();
72 void EnsureReady(const base::Closure
& ready_callback
) override
{
73 ASSERT_TRUE(ready_callback_
.is_null());
78 ready_callback_
= ready_callback
;
81 void LaunchSetup() override
{
82 ASSERT_EQ(STATE_LOADED
, state_
);
86 void LoadApp() override
{ state_
= STATE_LOADED
; }
88 void DisableAppIfLoaded() override
{
89 if (state_
== STATE_LOADED
)
90 state_
= STATE_DISABLED
;
93 void ReloadApp() override
{
94 if (state_
== STATE_LOADED
)
98 bool SendUserUpdatedEvent(const std::string
& user_id
,
100 bool data_ready
) override
{
101 // TODO(tbarzic): Make this a bit smarter and add some test to utilize it.
105 bool SendAuthAttemptEvent() override
{
106 ADD_FAILURE() << "Not reached.";
111 // The current app state.
114 // Number of times LaunchSetup was called.
115 size_t app_launch_count_
;
117 // Number of times ReloadApp was called.
118 size_t reload_count_
;
120 // Whether the manager is ready. Set using |SetReady|.
122 // If |EnsureReady| was called before |SetReady|, cached callback that will be
123 // called when manager becomes ready.
124 base::Closure ready_callback_
;
126 DISALLOW_COPY_AND_ASSIGN(TestAppManager
);
129 // Helper factory that tracks AppManagers passed to EasyUnlockServices per
130 // browser context owning a EasyUnlockService. Used to allow tests access to the
131 // TestAppManagers passed to the created services.
132 class TestAppManagerFactory
{
134 TestAppManagerFactory() {}
135 ~TestAppManagerFactory() {}
137 // Creates a TestAppManager for the provided browser context. If a
138 // TestAppManager was already created for the context, returns NULL.
139 scoped_ptr
<TestAppManager
> Create(content::BrowserContext
* context
) {
141 return scoped_ptr
<TestAppManager
>();
142 scoped_ptr
<TestAppManager
> app_manager(new TestAppManager());
143 mapping_
[context
] = app_manager
.get();
144 return app_manager
.Pass();
147 // Finds a TestAppManager created for |context|. Returns NULL if no
148 // TestAppManagers have been created for the context.
149 TestAppManager
* Find(content::BrowserContext
* context
) {
150 std::map
<content::BrowserContext
*, TestAppManager
*>::iterator it
=
151 mapping_
.find(context
);
152 if (it
== mapping_
.end())
158 // Mapping from browser contexts to test AppManagers. The AppManagers are not
160 std::map
<content::BrowserContext
*, TestAppManager
*> mapping_
;
162 DISALLOW_COPY_AND_ASSIGN(TestAppManagerFactory
);
165 // Global TestAppManager factory. It should be created and desctructed in
166 // EasyUnlockServiceTest::SetUp and EasyUnlockServiceTest::TearDown
168 TestAppManagerFactory
* app_manager_factory
= NULL
;
170 // EasyUnlockService factory function injected into testing profiles.
171 // It creates an EasyUnlockService with test AppManager.
172 KeyedService
* CreateEasyUnlockServiceForTest(content::BrowserContext
* context
) {
173 EXPECT_TRUE(app_manager_factory
);
174 if (!app_manager_factory
)
177 scoped_ptr
<EasyUnlockAppManager
> app_manager
=
178 app_manager_factory
->Create(context
);
179 EXPECT_TRUE(app_manager
.get());
180 if (!app_manager
.get())
183 EasyUnlockService
* service
=
184 new EasyUnlockServiceRegular(Profile::FromBrowserContext(context
));
185 service
->Initialize(app_manager
.Pass());
189 class EasyUnlockServiceTest
: public testing::Test
{
191 EasyUnlockServiceTest()
192 : mock_user_manager_(new testing::NiceMock
<chromeos::MockUserManager
>()),
193 scoped_user_manager_(mock_user_manager_
),
194 is_bluetooth_adapter_present_(true) {}
196 ~EasyUnlockServiceTest() override
{}
198 void SetUp() override
{
199 app_manager_factory
= new TestAppManagerFactory();
201 mock_adapter_
= new testing::NiceMock
<MockBluetoothAdapter
>();
202 device::BluetoothAdapterFactory::SetAdapterForTesting(mock_adapter_
);
203 EXPECT_CALL(*mock_adapter_
, IsPresent())
204 .WillRepeatedly(testing::Invoke(
205 this, &EasyUnlockServiceTest::is_bluetooth_adapter_present
));
207 scoped_ptr
<DBusThreadManagerSetter
> dbus_setter
=
208 chromeos::DBusThreadManager::GetSetterForTesting();
209 power_manager_client_
= new FakePowerManagerClient
;
210 dbus_setter
->SetPowerManagerClient(
211 scoped_ptr
<PowerManagerClient
>(power_manager_client_
));
213 ON_CALL(*mock_user_manager_
, Shutdown()).WillByDefault(Return());
214 ON_CALL(*mock_user_manager_
, IsLoggedInAsUserWithGaiaAccount())
215 .WillByDefault(Return(true));
216 ON_CALL(*mock_user_manager_
, IsCurrentUserNonCryptohomeDataEphemeral())
217 .WillByDefault(Return(false));
219 SetUpProfile(&profile_
, kTestUserPrimary
);
222 void TearDown() override
{
223 delete app_manager_factory
;
224 app_manager_factory
= NULL
;
227 void SetEasyUnlockAllowedPolicy(bool allowed
) {
228 profile_
->GetTestingPrefService()->SetManagedPref(
229 prefs::kEasyUnlockAllowed
, new base::FundamentalValue(allowed
));
232 void set_is_bluetooth_adapter_present(bool is_present
) {
233 is_bluetooth_adapter_present_
= is_present
;
236 bool is_bluetooth_adapter_present() const {
237 return is_bluetooth_adapter_present_
;
240 FakePowerManagerClient
* power_manager_client() {
241 return power_manager_client_
;
244 // Checks whether AppManager passed to EasyUnlockservice for |profile| has
245 // Easy Unlock app loaded.
246 bool EasyUnlockAppInState(Profile
* profile
, TestAppManager::State state
) {
247 EXPECT_TRUE(app_manager_factory
);
248 if (!app_manager_factory
)
250 TestAppManager
* app_manager
= app_manager_factory
->Find(profile
);
251 EXPECT_TRUE(app_manager
);
252 return app_manager
&& app_manager
->state() == state
;
255 void SetAppManagerReady(content::BrowserContext
* context
) {
256 ASSERT_TRUE(app_manager_factory
);
257 TestAppManager
* app_manager
= app_manager_factory
->Find(context
);
258 ASSERT_TRUE(app_manager
);
259 app_manager
->SetReady();
262 void SetUpSecondaryProfile() {
263 SetUpProfile(&secondary_profile_
, kTestUserSecondary
);
267 // Sets up a test profile with a user id.
268 void SetUpProfile(scoped_ptr
<TestingProfile
>* profile
,
269 const std::string
& user_id
) {
270 ASSERT_TRUE(profile
);
271 ASSERT_FALSE(profile
->get());
273 TestingProfile::Builder builder
;
274 builder
.AddTestingFactory(EasyUnlockServiceFactory::GetInstance(),
275 &CreateEasyUnlockServiceForTest
);
276 *profile
= builder
.Build();
278 mock_user_manager_
->AddUser(user_id
);
279 profile
->get()->set_profile_name(user_id
);
281 SigninManagerBase
* signin_manager
=
282 SigninManagerFactory::GetForProfile(profile
->get());
283 signin_manager
->SetAuthenticatedUsername(user_id
);
287 scoped_ptr
<TestingProfile
> profile_
;
288 scoped_ptr
<TestingProfile
> secondary_profile_
;
289 chromeos::MockUserManager
* mock_user_manager_
;
292 content::TestBrowserThreadBundle thread_bundle_
;
294 chromeos::ScopedUserManagerEnabler scoped_user_manager_
;
296 FakePowerManagerClient
* power_manager_client_
;
298 bool is_bluetooth_adapter_present_
;
299 scoped_refptr
<testing::NiceMock
<MockBluetoothAdapter
>> mock_adapter_
;
301 DISALLOW_COPY_AND_ASSIGN(EasyUnlockServiceTest
);
304 TEST_F(EasyUnlockServiceTest
, NoBluetoothNoService
) {
305 set_is_bluetooth_adapter_present(false);
307 // This should start easy unlock service initialization.
308 SetAppManagerReady(profile_
.get());
310 EasyUnlockService
* service
= EasyUnlockService::Get(profile_
.get());
311 ASSERT_TRUE(service
);
313 EXPECT_FALSE(service
->IsAllowed());
315 EasyUnlockAppInState(profile_
.get(), TestAppManager::STATE_NOT_LOADED
));
318 TEST_F(EasyUnlockServiceTest
, DisabledOnSuspend
) {
319 // This should start easy unlock service initialization.
320 SetAppManagerReady(profile_
.get());
322 EasyUnlockService
* service
= EasyUnlockService::Get(profile_
.get());
323 ASSERT_TRUE(service
);
325 EXPECT_TRUE(service
->IsAllowed());
327 EasyUnlockAppInState(profile_
.get(), TestAppManager::STATE_LOADED
));
329 power_manager_client()->SendSuspendImminent();
331 EasyUnlockAppInState(profile_
.get(), TestAppManager::STATE_DISABLED
));
333 power_manager_client()->SendSuspendDone();
335 EasyUnlockAppInState(profile_
.get(), TestAppManager::STATE_LOADED
));
338 TEST_F(EasyUnlockServiceTest
, NotAllowedForSecondaryProfile
) {
339 SetAppManagerReady(profile_
.get());
341 EasyUnlockService
* primary_service
= EasyUnlockService::Get(profile_
.get());
342 ASSERT_TRUE(primary_service
);
344 // A sanity check for the test to confirm that the primary profile service
345 // is allowed under these conditions..
346 ASSERT_TRUE(primary_service
->IsAllowed());
348 SetUpSecondaryProfile();
349 SetAppManagerReady(secondary_profile_
.get());
351 EasyUnlockService
* secondary_service
=
352 EasyUnlockService::Get(secondary_profile_
.get());
353 ASSERT_TRUE(secondary_service
);
355 EXPECT_FALSE(secondary_service
->IsAllowed());
356 EXPECT_TRUE(EasyUnlockAppInState(secondary_profile_
.get(),
357 TestAppManager::STATE_NOT_LOADED
));
360 TEST_F(EasyUnlockServiceTest
, NotAllowedForEphemeralAccounts
) {
361 ON_CALL(*mock_user_manager_
, IsCurrentUserNonCryptohomeDataEphemeral())
362 .WillByDefault(Return(true));
364 SetAppManagerReady(profile_
.get());
365 EXPECT_FALSE(EasyUnlockService::Get(profile_
.get())->IsAllowed());
367 EasyUnlockAppInState(profile_
.get(), TestAppManager::STATE_NOT_LOADED
));