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/memory/scoped_ptr.h"
10 #include "base/run_loop.h"
11 #include "base/values.h"
12 #include "chrome/browser/chromeos/login/users/mock_user_manager.h"
13 #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
14 #include "chrome/browser/chromeos/profiles/profile_helper.h"
15 #include "chrome/browser/signin/easy_unlock_app_manager.h"
16 #include "chrome/browser/signin/easy_unlock_service.h"
17 #include "chrome/browser/signin/easy_unlock_service_factory.h"
18 #include "chrome/browser/signin/easy_unlock_service_regular.h"
19 #include "chrome/browser/signin/signin_manager_factory.h"
20 #include "chrome/common/pref_names.h"
21 #include "chrome/test/base/testing_pref_service_syncable.h"
22 #include "chrome/test/base/testing_profile.h"
23 #include "chromeos/dbus/dbus_thread_manager.h"
24 #include "chromeos/dbus/fake_power_manager_client.h"
25 #include "components/signin/core/browser/signin_manager_base.h"
26 #include "content/public/test/test_browser_thread_bundle.h"
27 #include "device/bluetooth/bluetooth_adapter_factory.h"
28 #include "device/bluetooth/test/mock_bluetooth_adapter.h"
29 #include "testing/gmock/include/gmock/gmock.h"
31 using chromeos::DBusThreadManagerSetter
;
32 using chromeos::FakePowerManagerClient
;
33 using chromeos::PowerManagerClient
;
34 using chromeos::ProfileHelper
;
35 using device::MockBluetoothAdapter
;
37 using testing::AnyNumber
;
38 using testing::Return
;
42 // IDs for fake users used in tests.
43 const char kTestUserPrimary
[] = "primary_user@nowhere.com";
44 const char kTestUserSecondary
[] = "secondary_user@nowhere.com";
46 // App manager to be used in EasyUnlockService tests.
47 // This effectivelly abstracts the extension system from the tests.
48 class TestAppManager
: public EasyUnlockAppManager
{
51 : state_(STATE_NOT_LOADED
),
52 app_launch_count_(0u),
55 ~TestAppManager() override
{}
57 // The easy unlock app state.
58 enum State
{ STATE_NOT_LOADED
, STATE_LOADED
, STATE_DISABLED
};
60 State
state() const { return state_
; }
61 size_t app_launch_count() const { return app_launch_count_
; }
62 size_t reload_count() const { return reload_count_
; }
64 // Marks the manager as ready and runs |ready_callback_| if there is one set.
67 if (!ready_callback_
.is_null()) {
68 ready_callback_
.Run();
69 ready_callback_
= base::Closure();
73 void EnsureReady(const base::Closure
& ready_callback
) override
{
74 ASSERT_TRUE(ready_callback_
.is_null());
79 ready_callback_
= ready_callback
;
82 void LaunchSetup() override
{
83 ASSERT_EQ(STATE_LOADED
, state_
);
87 void LoadApp() override
{ state_
= STATE_LOADED
; }
89 void DisableAppIfLoaded() override
{
90 if (state_
== STATE_LOADED
)
91 state_
= STATE_DISABLED
;
94 void ReloadApp() override
{
95 if (state_
== STATE_LOADED
)
99 bool SendUserUpdatedEvent(const std::string
& user_id
,
101 bool data_ready
) override
{
102 // TODO(tbarzic): Make this a bit smarter and add some test to utilize it.
106 bool SendAuthAttemptEvent() override
{
107 ADD_FAILURE() << "Not reached.";
112 // The current app state.
115 // Number of times LaunchSetup was called.
116 size_t app_launch_count_
;
118 // Number of times ReloadApp was called.
119 size_t reload_count_
;
121 // Whether the manager is ready. Set using |SetReady|.
123 // If |EnsureReady| was called before |SetReady|, cached callback that will be
124 // called when manager becomes ready.
125 base::Closure ready_callback_
;
127 DISALLOW_COPY_AND_ASSIGN(TestAppManager
);
130 // Helper factory that tracks AppManagers passed to EasyUnlockServices per
131 // browser context owning a EasyUnlockService. Used to allow tests access to the
132 // TestAppManagers passed to the created services.
133 class TestAppManagerFactory
{
135 TestAppManagerFactory() {}
136 ~TestAppManagerFactory() {}
138 // Creates a TestAppManager for the provided browser context. If a
139 // TestAppManager was already created for the context, returns NULL.
140 scoped_ptr
<TestAppManager
> Create(content::BrowserContext
* context
) {
142 return scoped_ptr
<TestAppManager
>();
143 scoped_ptr
<TestAppManager
> app_manager(new TestAppManager());
144 mapping_
[context
] = app_manager
.get();
145 return app_manager
.Pass();
148 // Finds a TestAppManager created for |context|. Returns NULL if no
149 // TestAppManagers have been created for the context.
150 TestAppManager
* Find(content::BrowserContext
* context
) {
151 std::map
<content::BrowserContext
*, TestAppManager
*>::iterator it
=
152 mapping_
.find(context
);
153 if (it
== mapping_
.end())
159 // Mapping from browser contexts to test AppManagers. The AppManagers are not
161 std::map
<content::BrowserContext
*, TestAppManager
*> mapping_
;
163 DISALLOW_COPY_AND_ASSIGN(TestAppManagerFactory
);
166 // Global TestAppManager factory. It should be created and desctructed in
167 // EasyUnlockServiceTest::SetUp and EasyUnlockServiceTest::TearDown
169 TestAppManagerFactory
* app_manager_factory
= NULL
;
171 // EasyUnlockService factory function injected into testing profiles.
172 // It creates an EasyUnlockService with test AppManager.
173 scoped_ptr
<KeyedService
> CreateEasyUnlockServiceForTest(
174 content::BrowserContext
* context
) {
175 EXPECT_TRUE(app_manager_factory
);
176 if (!app_manager_factory
)
179 scoped_ptr
<EasyUnlockAppManager
> app_manager
=
180 app_manager_factory
->Create(context
);
181 EXPECT_TRUE(app_manager
.get());
182 if (!app_manager
.get())
185 scoped_ptr
<EasyUnlockServiceRegular
> service(
186 new EasyUnlockServiceRegular(Profile::FromBrowserContext(context
)));
187 service
->Initialize(app_manager
.Pass());
188 return service
.Pass();
191 class EasyUnlockServiceTest
: public testing::Test
{
193 EasyUnlockServiceTest()
194 : mock_user_manager_(new testing::NiceMock
<chromeos::MockUserManager
>()),
195 scoped_user_manager_(mock_user_manager_
),
196 is_bluetooth_adapter_present_(true) {}
198 ~EasyUnlockServiceTest() override
{}
200 void SetUp() override
{
201 app_manager_factory
= new TestAppManagerFactory();
203 mock_adapter_
= new testing::NiceMock
<MockBluetoothAdapter
>();
204 device::BluetoothAdapterFactory::SetAdapterForTesting(mock_adapter_
);
205 EXPECT_CALL(*mock_adapter_
, IsPresent())
206 .WillRepeatedly(testing::Invoke(
207 this, &EasyUnlockServiceTest::is_bluetooth_adapter_present
));
209 scoped_ptr
<DBusThreadManagerSetter
> dbus_setter
=
210 chromeos::DBusThreadManager::GetSetterForTesting();
211 power_manager_client_
= new FakePowerManagerClient
;
212 dbus_setter
->SetPowerManagerClient(
213 scoped_ptr
<PowerManagerClient
>(power_manager_client_
));
215 ON_CALL(*mock_user_manager_
, Shutdown()).WillByDefault(Return());
216 ON_CALL(*mock_user_manager_
, IsLoggedInAsUserWithGaiaAccount())
217 .WillByDefault(Return(true));
218 ON_CALL(*mock_user_manager_
, IsCurrentUserNonCryptohomeDataEphemeral())
219 .WillByDefault(Return(false));
221 SetUpProfile(&profile_
, kTestUserPrimary
);
224 void TearDown() override
{
225 delete app_manager_factory
;
226 app_manager_factory
= NULL
;
229 void SetEasyUnlockAllowedPolicy(bool allowed
) {
230 profile_
->GetTestingPrefService()->SetManagedPref(
231 prefs::kEasyUnlockAllowed
, new base::FundamentalValue(allowed
));
234 void set_is_bluetooth_adapter_present(bool is_present
) {
235 is_bluetooth_adapter_present_
= is_present
;
238 bool is_bluetooth_adapter_present() const {
239 return is_bluetooth_adapter_present_
;
242 FakePowerManagerClient
* power_manager_client() {
243 return power_manager_client_
;
246 // Checks whether AppManager passed to EasyUnlockservice for |profile| has
247 // Easy Unlock app loaded.
248 bool EasyUnlockAppInState(Profile
* profile
, TestAppManager::State state
) {
249 EXPECT_TRUE(app_manager_factory
);
250 if (!app_manager_factory
)
252 TestAppManager
* app_manager
= app_manager_factory
->Find(profile
);
253 EXPECT_TRUE(app_manager
);
254 return app_manager
&& app_manager
->state() == state
;
257 void SetAppManagerReady(content::BrowserContext
* context
) {
258 ASSERT_TRUE(app_manager_factory
);
259 TestAppManager
* app_manager
= app_manager_factory
->Find(context
);
260 ASSERT_TRUE(app_manager
);
261 app_manager
->SetReady();
264 void SetUpSecondaryProfile() {
265 SetUpProfile(&secondary_profile_
, kTestUserSecondary
);
269 // Sets up a test profile with a user id.
270 void SetUpProfile(scoped_ptr
<TestingProfile
>* profile
,
271 const std::string
& user_id
) {
272 ASSERT_TRUE(profile
);
273 ASSERT_FALSE(profile
->get());
275 TestingProfile::Builder builder
;
276 builder
.AddTestingFactory(EasyUnlockServiceFactory::GetInstance(),
277 &CreateEasyUnlockServiceForTest
);
278 *profile
= builder
.Build();
280 mock_user_manager_
->AddUser(user_id
);
281 profile
->get()->set_profile_name(user_id
);
283 SigninManagerBase
* signin_manager
=
284 SigninManagerFactory::GetForProfile(profile
->get());
285 signin_manager
->SetAuthenticatedAccountInfo(user_id
, user_id
);
289 scoped_ptr
<TestingProfile
> profile_
;
290 scoped_ptr
<TestingProfile
> secondary_profile_
;
291 chromeos::MockUserManager
* mock_user_manager_
;
294 content::TestBrowserThreadBundle thread_bundle_
;
296 chromeos::ScopedUserManagerEnabler scoped_user_manager_
;
298 FakePowerManagerClient
* power_manager_client_
;
300 bool is_bluetooth_adapter_present_
;
301 scoped_refptr
<testing::NiceMock
<MockBluetoothAdapter
>> mock_adapter_
;
303 DISALLOW_COPY_AND_ASSIGN(EasyUnlockServiceTest
);
306 TEST_F(EasyUnlockServiceTest
, NoBluetoothNoService
) {
307 set_is_bluetooth_adapter_present(false);
309 // This should start easy unlock service initialization.
310 SetAppManagerReady(profile_
.get());
312 EasyUnlockService
* service
= EasyUnlockService::Get(profile_
.get());
313 ASSERT_TRUE(service
);
315 EXPECT_FALSE(service
->IsAllowed());
317 EasyUnlockAppInState(profile_
.get(), TestAppManager::STATE_NOT_LOADED
));
320 TEST_F(EasyUnlockServiceTest
, DisabledOnSuspend
) {
321 // This should start easy unlock service initialization.
322 SetAppManagerReady(profile_
.get());
324 EasyUnlockService
* service
= EasyUnlockService::Get(profile_
.get());
325 ASSERT_TRUE(service
);
327 EXPECT_TRUE(service
->IsAllowed());
329 EasyUnlockAppInState(profile_
.get(), TestAppManager::STATE_LOADED
));
331 power_manager_client()->SendSuspendImminent();
333 EasyUnlockAppInState(profile_
.get(), TestAppManager::STATE_DISABLED
));
335 power_manager_client()->SendSuspendDone();
337 EasyUnlockAppInState(profile_
.get(), TestAppManager::STATE_LOADED
));
340 TEST_F(EasyUnlockServiceTest
, NotAllowedForSecondaryProfile
) {
341 SetAppManagerReady(profile_
.get());
343 EasyUnlockService
* primary_service
= EasyUnlockService::Get(profile_
.get());
344 ASSERT_TRUE(primary_service
);
346 // A sanity check for the test to confirm that the primary profile service
347 // is allowed under these conditions..
348 ASSERT_TRUE(primary_service
->IsAllowed());
350 SetUpSecondaryProfile();
351 SetAppManagerReady(secondary_profile_
.get());
353 EasyUnlockService
* secondary_service
=
354 EasyUnlockService::Get(secondary_profile_
.get());
355 ASSERT_TRUE(secondary_service
);
357 EXPECT_FALSE(secondary_service
->IsAllowed());
358 EXPECT_TRUE(EasyUnlockAppInState(secondary_profile_
.get(),
359 TestAppManager::STATE_NOT_LOADED
));
362 TEST_F(EasyUnlockServiceTest
, NotAllowedForEphemeralAccounts
) {
363 ON_CALL(*mock_user_manager_
, IsCurrentUserNonCryptohomeDataEphemeral())
364 .WillByDefault(Return(true));
366 SetAppManagerReady(profile_
.get());
367 EXPECT_FALSE(EasyUnlockService::Get(profile_
.get())->IsAllowed());
369 EasyUnlockAppInState(profile_
.get(), TestAppManager::STATE_NOT_LOADED
));