Allow intent picker for external schemes
[chromium-blink-merge.git] / components / proximity_auth / cryptauth / cryptauth_enrollment_manager_unittest.cc
blob33336ace759460c3248dded826d68ded2afca686
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.
5 #include "components/proximity_auth/cryptauth/cryptauth_enrollment_manager.h"
7 #include "base/memory/weak_ptr.h"
8 #include "base/prefs/testing_pref_service.h"
9 #include "base/test/simple_test_clock.h"
10 #include "base/time/clock.h"
11 #include "base/time/time.h"
12 #include "components/proximity_auth/cryptauth/cryptauth_enroller.h"
13 #include "components/proximity_auth/cryptauth/fake_cryptauth_gcm_manager.h"
14 #include "components/proximity_auth/cryptauth/mock_sync_scheduler.h"
15 #include "components/proximity_auth/cryptauth/pref_names.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 using ::testing::_;
20 using ::testing::NiceMock;
21 using ::testing::Return;
22 using ::testing::SaveArg;
24 namespace proximity_auth {
26 namespace {
28 // The GCM registration id from a successful registration.
29 const char kGCMRegistrationId[] = "new gcm registration id";
31 // The user's persistent key pair identifying the local device.
32 const char kUserPublicKey[] = "user public key";
33 const char kUserPrivateKey[] = "user private key";
35 // The initial "Now" time for testing.
36 const double kInitialTimeNowSeconds = 20000000;
38 // A later "Now" time for testing.
39 const double kLaterTimeNow = kInitialTimeNowSeconds + 30;
41 // The timestamp of a last successful enrollment that is still valid.
42 const double kLastEnrollmentTimeSeconds =
43 kInitialTimeNowSeconds - (60 * 60 * 24 * 15);
45 // The timestamp of a last successful enrollment that is expired.
46 const double kLastExpiredEnrollmentTimeSeconds =
47 kInitialTimeNowSeconds - (60 * 60 * 24 * 100);
49 // Mocks out the actual enrollment flow.
50 class MockCryptAuthEnroller : public CryptAuthEnroller {
51 public:
52 MockCryptAuthEnroller() {}
53 ~MockCryptAuthEnroller() override {}
55 MOCK_METHOD5(Enroll,
56 void(const std::string& user_public_key,
57 const std::string& user_private_key,
58 const cryptauth::GcmDeviceInfo& device_info,
59 cryptauth::InvocationReason invocation_reason,
60 const EnrollmentFinishedCallback& callback));
62 private:
63 DISALLOW_COPY_AND_ASSIGN(MockCryptAuthEnroller);
66 // Creates MockCryptAuthEnroller instances, and allows expecations to be set
67 // before they are returned.
68 class MockCryptAuthEnrollerFactory : public CryptAuthEnrollerFactory {
69 public:
70 MockCryptAuthEnrollerFactory()
71 : next_cryptauth_enroller_(new NiceMock<MockCryptAuthEnroller>()) {}
72 ~MockCryptAuthEnrollerFactory() override {}
74 // CryptAuthEnrollerFactory:
75 scoped_ptr<CryptAuthEnroller> CreateInstance() override {
76 auto passed_cryptauth_enroller = next_cryptauth_enroller_.Pass();
77 next_cryptauth_enroller_.reset(new NiceMock<MockCryptAuthEnroller>());
78 return passed_cryptauth_enroller.Pass();
81 MockCryptAuthEnroller* next_cryptauth_enroller() {
82 return next_cryptauth_enroller_.get();
85 private:
86 // Stores the next CryptAuthEnroller to be created.
87 // Ownership is passed to the caller of |CreateInstance()|.
88 scoped_ptr<MockCryptAuthEnroller> next_cryptauth_enroller_;
90 DISALLOW_COPY_AND_ASSIGN(MockCryptAuthEnrollerFactory);
93 // Harness for testing CryptAuthEnrollmentManager.
94 class TestCryptAuthEnrollmentManager : public CryptAuthEnrollmentManager {
95 public:
96 TestCryptAuthEnrollmentManager(
97 scoped_ptr<base::Clock> clock,
98 scoped_ptr<CryptAuthEnrollerFactory> enroller_factory,
99 const cryptauth::GcmDeviceInfo& device_info,
100 CryptAuthGCMManager* gcm_manager,
101 PrefService* pref_service)
102 : CryptAuthEnrollmentManager(clock.Pass(),
103 enroller_factory.Pass(),
104 kUserPublicKey,
105 kUserPrivateKey,
106 device_info,
107 gcm_manager,
108 pref_service),
109 scoped_sync_scheduler_(new NiceMock<MockSyncScheduler>()),
110 weak_sync_scheduler_factory_(scoped_sync_scheduler_.get()) {}
112 ~TestCryptAuthEnrollmentManager() override {}
114 scoped_ptr<SyncScheduler> CreateSyncScheduler() override {
115 EXPECT_TRUE(scoped_sync_scheduler_);
116 return scoped_sync_scheduler_.Pass();
119 base::WeakPtr<MockSyncScheduler> GetSyncScheduler() {
120 return weak_sync_scheduler_factory_.GetWeakPtr();
123 private:
124 // Ownership is passed to |CryptAuthEnrollmentManager| super class when
125 // |CreateSyncScheduler()| is called.
126 scoped_ptr<MockSyncScheduler> scoped_sync_scheduler_;
128 // Stores the pointer of |scoped_sync_scheduler_| after ownership is passed to
129 // the super class.
130 // This should be safe because the life-time this SyncScheduler will always be
131 // within the life of the TestCryptAuthEnrollmentManager object.
132 base::WeakPtrFactory<MockSyncScheduler> weak_sync_scheduler_factory_;
134 DISALLOW_COPY_AND_ASSIGN(TestCryptAuthEnrollmentManager);
137 } // namespace
139 class ProximityAuthCryptAuthEnrollmentManagerTest
140 : public testing::Test,
141 public CryptAuthEnrollmentManager::Observer {
142 protected:
143 ProximityAuthCryptAuthEnrollmentManagerTest()
144 : clock_(new base::SimpleTestClock()),
145 enroller_factory_(new MockCryptAuthEnrollerFactory()),
146 gcm_manager_(kGCMRegistrationId),
147 enrollment_manager_(make_scoped_ptr(clock_),
148 make_scoped_ptr(enroller_factory_),
149 device_info_,
150 &gcm_manager_,
151 &pref_service_) {}
153 // testing::Test:
154 void SetUp() override {
155 clock_->SetNow(base::Time::FromDoubleT(kInitialTimeNowSeconds));
156 enrollment_manager_.AddObserver(this);
158 CryptAuthEnrollmentManager::RegisterPrefs(pref_service_.registry());
159 pref_service_.SetUserPref(
160 prefs::kCryptAuthEnrollmentIsRecoveringFromFailure,
161 new base::FundamentalValue(false));
162 pref_service_.SetUserPref(
163 prefs::kCryptAuthEnrollmentLastEnrollmentTimeSeconds,
164 new base::FundamentalValue(kLastEnrollmentTimeSeconds));
165 pref_service_.SetUserPref(
166 prefs::kCryptAuthEnrollmentReason,
167 new base::FundamentalValue(cryptauth::INVOCATION_REASON_UNKNOWN));
169 ON_CALL(*sync_scheduler(), GetStrategy())
170 .WillByDefault(Return(SyncScheduler::Strategy::PERIODIC_REFRESH));
173 void TearDown() override { enrollment_manager_.RemoveObserver(this); }
175 // CryptAuthEnrollmentManager::Observer:
176 void OnEnrollmentStarted() override { OnEnrollmentStartedProxy(); }
178 void OnEnrollmentFinished(bool success) override {
179 // Simulate the scheduler changing strategies based on success or failure.
180 SyncScheduler::Strategy new_strategy =
181 SyncScheduler::Strategy::AGGRESSIVE_RECOVERY;
182 ON_CALL(*sync_scheduler(), GetStrategy())
183 .WillByDefault(Return(new_strategy));
185 OnEnrollmentFinishedProxy(success);
188 MOCK_METHOD0(OnEnrollmentStartedProxy, void());
189 MOCK_METHOD1(OnEnrollmentFinishedProxy, void(bool success));
191 // Simulates firing the SyncScheduler to trigger an enrollment attempt.
192 CryptAuthEnroller::EnrollmentFinishedCallback FireSchedulerForEnrollment(
193 cryptauth::InvocationReason expected_invocation_reason) {
194 CryptAuthEnroller::EnrollmentFinishedCallback completion_callback;
195 EXPECT_CALL(*next_cryptauth_enroller(),
196 Enroll(kUserPublicKey, kUserPrivateKey, _,
197 expected_invocation_reason, _))
198 .WillOnce(SaveArg<4>(&completion_callback));
200 auto sync_request = make_scoped_ptr(
201 new SyncScheduler::SyncRequest(enrollment_manager_.GetSyncScheduler()));
202 EXPECT_CALL(*this, OnEnrollmentStartedProxy());
204 SyncScheduler::Delegate* delegate =
205 static_cast<SyncScheduler::Delegate*>(&enrollment_manager_);
206 delegate->OnSyncRequested(sync_request.Pass());
208 return completion_callback;
211 MockSyncScheduler* sync_scheduler() {
212 return enrollment_manager_.GetSyncScheduler().get();
215 MockCryptAuthEnroller* next_cryptauth_enroller() {
216 return enroller_factory_->next_cryptauth_enroller();
219 // Owned by |enrollment_manager_|.
220 base::SimpleTestClock* clock_;
222 // Owned by |enrollment_manager_|.
223 MockCryptAuthEnrollerFactory* enroller_factory_;
225 cryptauth::GcmDeviceInfo device_info_;
227 TestingPrefServiceSimple pref_service_;
229 FakeCryptAuthGCMManager gcm_manager_;
231 TestCryptAuthEnrollmentManager enrollment_manager_;
233 DISALLOW_COPY_AND_ASSIGN(ProximityAuthCryptAuthEnrollmentManagerTest);
236 TEST_F(ProximityAuthCryptAuthEnrollmentManagerTest, RegisterPrefs) {
237 TestingPrefServiceSimple pref_service;
238 CryptAuthEnrollmentManager::RegisterPrefs(pref_service.registry());
239 EXPECT_TRUE(pref_service.FindPreference(
240 prefs::kCryptAuthEnrollmentLastEnrollmentTimeSeconds));
241 EXPECT_TRUE(pref_service.FindPreference(
242 prefs::kCryptAuthEnrollmentIsRecoveringFromFailure));
243 EXPECT_TRUE(pref_service.FindPreference(prefs::kCryptAuthEnrollmentReason));
246 TEST_F(ProximityAuthCryptAuthEnrollmentManagerTest, GetEnrollmentState) {
247 enrollment_manager_.Start();
249 ON_CALL(*sync_scheduler(), GetStrategy())
250 .WillByDefault(Return(SyncScheduler::Strategy::PERIODIC_REFRESH));
251 EXPECT_FALSE(enrollment_manager_.IsRecoveringFromFailure());
253 ON_CALL(*sync_scheduler(), GetStrategy())
254 .WillByDefault(Return(SyncScheduler::Strategy::AGGRESSIVE_RECOVERY));
255 EXPECT_TRUE(enrollment_manager_.IsRecoveringFromFailure());
257 base::TimeDelta time_to_next_sync = base::TimeDelta::FromMinutes(60);
258 ON_CALL(*sync_scheduler(), GetTimeToNextSync())
259 .WillByDefault(Return(time_to_next_sync));
260 EXPECT_EQ(time_to_next_sync, enrollment_manager_.GetTimeToNextAttempt());
262 ON_CALL(*sync_scheduler(), GetSyncState())
263 .WillByDefault(Return(SyncScheduler::SyncState::SYNC_IN_PROGRESS));
264 EXPECT_TRUE(enrollment_manager_.IsEnrollmentInProgress());
266 ON_CALL(*sync_scheduler(), GetSyncState())
267 .WillByDefault(Return(SyncScheduler::SyncState::WAITING_FOR_REFRESH));
268 EXPECT_FALSE(enrollment_manager_.IsEnrollmentInProgress());
271 TEST_F(ProximityAuthCryptAuthEnrollmentManagerTest, InitWithDefaultPrefs) {
272 scoped_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock());
273 clock->SetNow(base::Time::FromDoubleT(kInitialTimeNowSeconds));
274 base::TimeDelta elapsed_time = clock->Now() - base::Time::FromDoubleT(0);
276 TestingPrefServiceSimple pref_service;
277 CryptAuthEnrollmentManager::RegisterPrefs(pref_service.registry());
279 TestCryptAuthEnrollmentManager enrollment_manager(
280 clock.Pass(), make_scoped_ptr(new MockCryptAuthEnrollerFactory()),
281 device_info_, &gcm_manager_, &pref_service);
283 EXPECT_CALL(
284 *enrollment_manager.GetSyncScheduler(),
285 Start(elapsed_time, SyncScheduler::Strategy::AGGRESSIVE_RECOVERY));
286 enrollment_manager.Start();
288 EXPECT_FALSE(enrollment_manager.IsEnrollmentValid());
289 EXPECT_TRUE(enrollment_manager.GetLastEnrollmentTime().is_null());
292 TEST_F(ProximityAuthCryptAuthEnrollmentManagerTest, InitWithExistingPrefs) {
293 EXPECT_CALL(
294 *sync_scheduler(),
295 Start(clock_->Now() - base::Time::FromDoubleT(kLastEnrollmentTimeSeconds),
296 SyncScheduler::Strategy::PERIODIC_REFRESH));
298 enrollment_manager_.Start();
299 EXPECT_TRUE(enrollment_manager_.IsEnrollmentValid());
300 EXPECT_EQ(base::Time::FromDoubleT(kLastEnrollmentTimeSeconds),
301 enrollment_manager_.GetLastEnrollmentTime());
304 TEST_F(ProximityAuthCryptAuthEnrollmentManagerTest, InitWithExpiredEnrollment) {
305 pref_service_.SetUserPref(
306 prefs::kCryptAuthEnrollmentLastEnrollmentTimeSeconds,
307 new base::FundamentalValue(kLastExpiredEnrollmentTimeSeconds));
309 EXPECT_CALL(*sync_scheduler(),
310 Start(clock_->Now() - base::Time::FromDoubleT(
311 kLastExpiredEnrollmentTimeSeconds),
312 SyncScheduler::Strategy::AGGRESSIVE_RECOVERY));
314 enrollment_manager_.Start();
315 EXPECT_FALSE(enrollment_manager_.IsEnrollmentValid());
316 EXPECT_EQ(base::Time::FromDoubleT(kLastExpiredEnrollmentTimeSeconds),
317 enrollment_manager_.GetLastEnrollmentTime());
320 TEST_F(ProximityAuthCryptAuthEnrollmentManagerTest,
321 EnrollmentSucceedsForFirstTime) {
322 pref_service_.ClearPref(prefs::kCryptAuthEnrollmentLastEnrollmentTimeSeconds);
323 enrollment_manager_.Start();
324 EXPECT_FALSE(enrollment_manager_.IsEnrollmentValid());
326 auto completion_callback =
327 FireSchedulerForEnrollment(cryptauth::INVOCATION_REASON_INITIALIZATION);
328 ASSERT_FALSE(completion_callback.is_null());
330 clock_->SetNow(base::Time::FromDoubleT(kLaterTimeNow));
331 EXPECT_CALL(*this, OnEnrollmentFinishedProxy(true));
332 completion_callback.Run(true);
334 EXPECT_EQ(clock_->Now(), enrollment_manager_.GetLastEnrollmentTime());
335 EXPECT_TRUE(enrollment_manager_.IsEnrollmentValid());
338 TEST_F(ProximityAuthCryptAuthEnrollmentManagerTest, ForceEnrollment) {
339 enrollment_manager_.Start();
341 EXPECT_CALL(*sync_scheduler(), ForceSync());
342 enrollment_manager_.ForceEnrollmentNow(
343 cryptauth::INVOCATION_REASON_SERVER_INITIATED);
345 auto completion_callback =
346 FireSchedulerForEnrollment(cryptauth::INVOCATION_REASON_SERVER_INITIATED);
348 clock_->SetNow(base::Time::FromDoubleT(kLaterTimeNow));
349 EXPECT_CALL(*this, OnEnrollmentFinishedProxy(true));
350 completion_callback.Run(true);
351 EXPECT_EQ(clock_->Now(), enrollment_manager_.GetLastEnrollmentTime());
354 TEST_F(ProximityAuthCryptAuthEnrollmentManagerTest,
355 EnrollmentFailsThenSucceeds) {
356 enrollment_manager_.Start();
357 base::Time old_enrollment_time = enrollment_manager_.GetLastEnrollmentTime();
359 // The first periodic enrollment fails.
360 ON_CALL(*sync_scheduler(), GetStrategy())
361 .WillByDefault(Return(SyncScheduler::Strategy::PERIODIC_REFRESH));
362 auto completion_callback =
363 FireSchedulerForEnrollment(cryptauth::INVOCATION_REASON_PERIODIC);
364 clock_->SetNow(base::Time::FromDoubleT(kLaterTimeNow));
365 EXPECT_CALL(*this, OnEnrollmentFinishedProxy(false));
366 completion_callback.Run(false);
367 EXPECT_EQ(old_enrollment_time, enrollment_manager_.GetLastEnrollmentTime());
368 EXPECT_TRUE(pref_service_.GetBoolean(
369 prefs::kCryptAuthEnrollmentIsRecoveringFromFailure));
371 // The second recovery enrollment succeeds.
372 ON_CALL(*sync_scheduler(), GetStrategy())
373 .WillByDefault(Return(SyncScheduler::Strategy::AGGRESSIVE_RECOVERY));
374 completion_callback =
375 FireSchedulerForEnrollment(cryptauth::INVOCATION_REASON_FAILURE_RECOVERY);
376 clock_->SetNow(base::Time::FromDoubleT(kLaterTimeNow + 30));
377 EXPECT_CALL(*this, OnEnrollmentFinishedProxy(true));
378 completion_callback.Run(true);
379 EXPECT_EQ(clock_->Now(), enrollment_manager_.GetLastEnrollmentTime());
380 EXPECT_FALSE(pref_service_.GetBoolean(
381 prefs::kCryptAuthEnrollmentIsRecoveringFromFailure));
384 TEST_F(ProximityAuthCryptAuthEnrollmentManagerTest,
385 EnrollWithoutGCMRegistrationId) {
386 // Initialize |enrollment_manager_|.
387 ON_CALL(*sync_scheduler(), GetStrategy())
388 .WillByDefault(Return(SyncScheduler::Strategy::PERIODIC_REFRESH));
389 gcm_manager_.set_registration_id(std::string());
390 enrollment_manager_.Start();
392 // Trigger a sync request.
393 EXPECT_CALL(*this, OnEnrollmentStartedProxy());
394 auto sync_request = make_scoped_ptr(
395 new SyncScheduler::SyncRequest(enrollment_manager_.GetSyncScheduler()));
396 static_cast<SyncScheduler::Delegate*>(&enrollment_manager_)
397 ->OnSyncRequested(sync_request.Pass());
399 // Complete GCM registration successfully.
400 CryptAuthEnroller::EnrollmentFinishedCallback enrollment_callback;
401 EXPECT_CALL(*next_cryptauth_enroller(),
402 Enroll(kUserPublicKey, kUserPrivateKey, _,
403 cryptauth::INVOCATION_REASON_PERIODIC, _))
404 .WillOnce(SaveArg<4>(&enrollment_callback));
405 ASSERT_TRUE(gcm_manager_.registration_in_progress());
406 gcm_manager_.CompleteRegistration(kGCMRegistrationId);
408 // Complete CryptAuth enrollment.
409 ASSERT_FALSE(enrollment_callback.is_null());
410 EXPECT_CALL(*this, OnEnrollmentFinishedProxy(true));
411 enrollment_callback.Run(true);
414 TEST_F(ProximityAuthCryptAuthEnrollmentManagerTest, GCMRegistrationFails) {
415 // Initialize |enrollment_manager_|.
416 ON_CALL(*sync_scheduler(), GetStrategy())
417 .WillByDefault(Return(SyncScheduler::Strategy::PERIODIC_REFRESH));
418 gcm_manager_.set_registration_id(std::string());
419 enrollment_manager_.Start();
421 // Trigger a sync request.
422 EXPECT_CALL(*this, OnEnrollmentStartedProxy());
423 auto sync_request = make_scoped_ptr(
424 new SyncScheduler::SyncRequest(enrollment_manager_.GetSyncScheduler()));
425 static_cast<SyncScheduler::Delegate*>(&enrollment_manager_)
426 ->OnSyncRequested(sync_request.Pass());
428 // Complete GCM registration with failure.
429 EXPECT_CALL(*this, OnEnrollmentFinishedProxy(false));
430 gcm_manager_.CompleteRegistration(std::string());
433 TEST_F(ProximityAuthCryptAuthEnrollmentManagerTest, ReenrollOnGCMPushMessage) {
434 enrollment_manager_.Start();
436 // Simulate receiving a GCM push message, forcing the device to re-enroll.
437 gcm_manager_.PushReenrollMessage();
438 auto completion_callback =
439 FireSchedulerForEnrollment(cryptauth::INVOCATION_REASON_SERVER_INITIATED);
441 EXPECT_CALL(*this, OnEnrollmentFinishedProxy(true));
442 completion_callback.Run(true);
445 } // namespace proximity_auth