Vectorize website settings icons in omnibox
[chromium-blink-merge.git] / components / proximity_auth / cryptauth / cryptauth_enrollment_manager_unittest.cc
blobaf954b1765e904fe3f9662255fb88a8d18fde774
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/base64url.h"
13 #include "components/proximity_auth/cryptauth/cryptauth_enroller.h"
14 #include "components/proximity_auth/cryptauth/fake_cryptauth_gcm_manager.h"
15 #include "components/proximity_auth/cryptauth/fake_secure_message_delegate.h"
16 #include "components/proximity_auth/cryptauth/mock_sync_scheduler.h"
17 #include "components/proximity_auth/cryptauth/pref_names.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
21 using ::testing::_;
22 using ::testing::NiceMock;
23 using ::testing::Return;
24 using ::testing::SaveArg;
26 namespace proximity_auth {
28 namespace {
30 // The GCM registration id from a successful registration.
31 const char kGCMRegistrationId[] = "new gcm registration id";
33 // The user's persistent public key identifying the local device.
34 const char kUserPublicKey[] = "user public key";
36 // The initial "Now" time for testing.
37 const double kInitialTimeNowSeconds = 20000000;
39 // A later "Now" time for testing.
40 const double kLaterTimeNow = kInitialTimeNowSeconds + 30;
42 // The timestamp of a last successful enrollment that is still valid.
43 const double kLastEnrollmentTimeSeconds =
44 kInitialTimeNowSeconds - (60 * 60 * 24 * 15);
46 // The timestamp of a last successful enrollment that is expired.
47 const double kLastExpiredEnrollmentTimeSeconds =
48 kInitialTimeNowSeconds - (60 * 60 * 24 * 100);
50 // Mocks out the actual enrollment flow.
51 class MockCryptAuthEnroller : public CryptAuthEnroller {
52 public:
53 MockCryptAuthEnroller() {}
54 ~MockCryptAuthEnroller() override {}
56 MOCK_METHOD5(Enroll,
57 void(const std::string& user_public_key,
58 const std::string& user_private_key,
59 const cryptauth::GcmDeviceInfo& device_info,
60 cryptauth::InvocationReason invocation_reason,
61 const EnrollmentFinishedCallback& callback));
63 private:
64 DISALLOW_COPY_AND_ASSIGN(MockCryptAuthEnroller);
67 // Creates MockCryptAuthEnroller instances, and allows expecations to be set
68 // before they are returned.
69 class MockCryptAuthEnrollerFactory : public CryptAuthEnrollerFactory {
70 public:
71 MockCryptAuthEnrollerFactory()
72 : next_cryptauth_enroller_(new NiceMock<MockCryptAuthEnroller>()) {}
73 ~MockCryptAuthEnrollerFactory() override {}
75 // CryptAuthEnrollerFactory:
76 scoped_ptr<CryptAuthEnroller> CreateInstance() override {
77 auto passed_cryptauth_enroller = next_cryptauth_enroller_.Pass();
78 next_cryptauth_enroller_.reset(new NiceMock<MockCryptAuthEnroller>());
79 return passed_cryptauth_enroller.Pass();
82 MockCryptAuthEnroller* next_cryptauth_enroller() {
83 return next_cryptauth_enroller_.get();
86 private:
87 // Stores the next CryptAuthEnroller to be created.
88 // Ownership is passed to the caller of |CreateInstance()|.
89 scoped_ptr<MockCryptAuthEnroller> next_cryptauth_enroller_;
91 DISALLOW_COPY_AND_ASSIGN(MockCryptAuthEnrollerFactory);
94 // Harness for testing CryptAuthEnrollmentManager.
95 class TestCryptAuthEnrollmentManager : public CryptAuthEnrollmentManager {
96 public:
97 TestCryptAuthEnrollmentManager(
98 scoped_ptr<base::Clock> clock,
99 scoped_ptr<CryptAuthEnrollerFactory> enroller_factory,
100 scoped_ptr<SecureMessageDelegate> secure_message_delegate,
101 const cryptauth::GcmDeviceInfo& device_info,
102 CryptAuthGCMManager* gcm_manager,
103 PrefService* pref_service)
104 : CryptAuthEnrollmentManager(clock.Pass(),
105 enroller_factory.Pass(),
106 secure_message_delegate.Pass(),
107 device_info,
108 gcm_manager,
109 pref_service),
110 scoped_sync_scheduler_(new NiceMock<MockSyncScheduler>()),
111 weak_sync_scheduler_factory_(scoped_sync_scheduler_.get()) {}
113 ~TestCryptAuthEnrollmentManager() override {}
115 scoped_ptr<SyncScheduler> CreateSyncScheduler() override {
116 EXPECT_TRUE(scoped_sync_scheduler_);
117 return scoped_sync_scheduler_.Pass();
120 base::WeakPtr<MockSyncScheduler> GetSyncScheduler() {
121 return weak_sync_scheduler_factory_.GetWeakPtr();
124 private:
125 // Ownership is passed to |CryptAuthEnrollmentManager| super class when
126 // |CreateSyncScheduler()| is called.
127 scoped_ptr<MockSyncScheduler> scoped_sync_scheduler_;
129 // Stores the pointer of |scoped_sync_scheduler_| after ownership is passed to
130 // the super class.
131 // This should be safe because the life-time this SyncScheduler will always be
132 // within the life of the TestCryptAuthEnrollmentManager object.
133 base::WeakPtrFactory<MockSyncScheduler> weak_sync_scheduler_factory_;
135 DISALLOW_COPY_AND_ASSIGN(TestCryptAuthEnrollmentManager);
138 } // namespace
140 class ProximityAuthCryptAuthEnrollmentManagerTest
141 : public testing::Test,
142 public CryptAuthEnrollmentManager::Observer {
143 protected:
144 ProximityAuthCryptAuthEnrollmentManagerTest()
145 : public_key_(kUserPublicKey),
146 clock_(new base::SimpleTestClock()),
147 enroller_factory_(new MockCryptAuthEnrollerFactory()),
148 secure_message_delegate_(new FakeSecureMessageDelegate()),
149 gcm_manager_(kGCMRegistrationId),
150 enrollment_manager_(make_scoped_ptr(clock_),
151 make_scoped_ptr(enroller_factory_),
152 make_scoped_ptr(secure_message_delegate_),
153 device_info_,
154 &gcm_manager_,
155 &pref_service_) {}
157 // testing::Test:
158 void SetUp() override {
159 clock_->SetNow(base::Time::FromDoubleT(kInitialTimeNowSeconds));
160 enrollment_manager_.AddObserver(this);
162 private_key_ =
163 secure_message_delegate_->GetPrivateKeyForPublicKey(public_key_);
164 secure_message_delegate_->set_next_public_key(public_key_);
166 CryptAuthEnrollmentManager::RegisterPrefs(pref_service_.registry());
167 pref_service_.SetUserPref(
168 prefs::kCryptAuthEnrollmentIsRecoveringFromFailure,
169 new base::FundamentalValue(false));
170 pref_service_.SetUserPref(
171 prefs::kCryptAuthEnrollmentLastEnrollmentTimeSeconds,
172 new base::FundamentalValue(kLastEnrollmentTimeSeconds));
173 pref_service_.SetUserPref(
174 prefs::kCryptAuthEnrollmentReason,
175 new base::FundamentalValue(cryptauth::INVOCATION_REASON_UNKNOWN));
177 std::string public_key_b64, private_key_b64;
178 Base64UrlEncode(public_key_, &public_key_b64);
179 Base64UrlEncode(private_key_, &private_key_b64);
180 pref_service_.SetString(prefs::kCryptAuthEnrollmentUserPublicKey,
181 public_key_b64);
182 pref_service_.SetString(prefs::kCryptAuthEnrollmentUserPrivateKey,
183 private_key_b64);
185 ON_CALL(*sync_scheduler(), GetStrategy())
186 .WillByDefault(Return(SyncScheduler::Strategy::PERIODIC_REFRESH));
189 void TearDown() override { enrollment_manager_.RemoveObserver(this); }
191 // CryptAuthEnrollmentManager::Observer:
192 void OnEnrollmentStarted() override { OnEnrollmentStartedProxy(); }
194 void OnEnrollmentFinished(bool success) override {
195 // Simulate the scheduler changing strategies based on success or failure.
196 SyncScheduler::Strategy new_strategy =
197 SyncScheduler::Strategy::AGGRESSIVE_RECOVERY;
198 ON_CALL(*sync_scheduler(), GetStrategy())
199 .WillByDefault(Return(new_strategy));
201 OnEnrollmentFinishedProxy(success);
204 MOCK_METHOD0(OnEnrollmentStartedProxy, void());
205 MOCK_METHOD1(OnEnrollmentFinishedProxy, void(bool success));
207 // Simulates firing the SyncScheduler to trigger an enrollment attempt.
208 CryptAuthEnroller::EnrollmentFinishedCallback FireSchedulerForEnrollment(
209 cryptauth::InvocationReason expected_invocation_reason) {
210 CryptAuthEnroller::EnrollmentFinishedCallback completion_callback;
211 EXPECT_CALL(
212 *next_cryptauth_enroller(),
213 Enroll(public_key_, private_key_, _, expected_invocation_reason, _))
214 .WillOnce(SaveArg<4>(&completion_callback));
216 auto sync_request = make_scoped_ptr(
217 new SyncScheduler::SyncRequest(enrollment_manager_.GetSyncScheduler()));
218 EXPECT_CALL(*this, OnEnrollmentStartedProxy());
220 SyncScheduler::Delegate* delegate =
221 static_cast<SyncScheduler::Delegate*>(&enrollment_manager_);
222 delegate->OnSyncRequested(sync_request.Pass());
224 return completion_callback;
227 MockSyncScheduler* sync_scheduler() {
228 return enrollment_manager_.GetSyncScheduler().get();
231 MockCryptAuthEnroller* next_cryptauth_enroller() {
232 return enroller_factory_->next_cryptauth_enroller();
235 // The expected persistent keypair.
236 std::string public_key_;
237 std::string private_key_;
239 // Owned by |enrollment_manager_|.
240 base::SimpleTestClock* clock_;
242 // Owned by |enrollment_manager_|.
243 MockCryptAuthEnrollerFactory* enroller_factory_;
245 // Ownered by |enrollment_manager_|.
246 FakeSecureMessageDelegate* secure_message_delegate_;
248 cryptauth::GcmDeviceInfo device_info_;
250 TestingPrefServiceSimple pref_service_;
252 FakeCryptAuthGCMManager gcm_manager_;
254 TestCryptAuthEnrollmentManager enrollment_manager_;
256 DISALLOW_COPY_AND_ASSIGN(ProximityAuthCryptAuthEnrollmentManagerTest);
259 TEST_F(ProximityAuthCryptAuthEnrollmentManagerTest, RegisterPrefs) {
260 TestingPrefServiceSimple pref_service;
261 CryptAuthEnrollmentManager::RegisterPrefs(pref_service.registry());
262 EXPECT_TRUE(pref_service.FindPreference(
263 prefs::kCryptAuthEnrollmentLastEnrollmentTimeSeconds));
264 EXPECT_TRUE(pref_service.FindPreference(
265 prefs::kCryptAuthEnrollmentIsRecoveringFromFailure));
266 EXPECT_TRUE(pref_service.FindPreference(prefs::kCryptAuthEnrollmentReason));
269 TEST_F(ProximityAuthCryptAuthEnrollmentManagerTest, GetEnrollmentState) {
270 enrollment_manager_.Start();
272 ON_CALL(*sync_scheduler(), GetStrategy())
273 .WillByDefault(Return(SyncScheduler::Strategy::PERIODIC_REFRESH));
274 EXPECT_FALSE(enrollment_manager_.IsRecoveringFromFailure());
276 ON_CALL(*sync_scheduler(), GetStrategy())
277 .WillByDefault(Return(SyncScheduler::Strategy::AGGRESSIVE_RECOVERY));
278 EXPECT_TRUE(enrollment_manager_.IsRecoveringFromFailure());
280 base::TimeDelta time_to_next_sync = base::TimeDelta::FromMinutes(60);
281 ON_CALL(*sync_scheduler(), GetTimeToNextSync())
282 .WillByDefault(Return(time_to_next_sync));
283 EXPECT_EQ(time_to_next_sync, enrollment_manager_.GetTimeToNextAttempt());
285 ON_CALL(*sync_scheduler(), GetSyncState())
286 .WillByDefault(Return(SyncScheduler::SyncState::SYNC_IN_PROGRESS));
287 EXPECT_TRUE(enrollment_manager_.IsEnrollmentInProgress());
289 ON_CALL(*sync_scheduler(), GetSyncState())
290 .WillByDefault(Return(SyncScheduler::SyncState::WAITING_FOR_REFRESH));
291 EXPECT_FALSE(enrollment_manager_.IsEnrollmentInProgress());
294 TEST_F(ProximityAuthCryptAuthEnrollmentManagerTest, InitWithDefaultPrefs) {
295 scoped_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock());
296 clock->SetNow(base::Time::FromDoubleT(kInitialTimeNowSeconds));
297 base::TimeDelta elapsed_time = clock->Now() - base::Time::FromDoubleT(0);
299 TestingPrefServiceSimple pref_service;
300 CryptAuthEnrollmentManager::RegisterPrefs(pref_service.registry());
302 TestCryptAuthEnrollmentManager enrollment_manager(
303 clock.Pass(), make_scoped_ptr(new MockCryptAuthEnrollerFactory()),
304 make_scoped_ptr(new FakeSecureMessageDelegate()), device_info_,
305 &gcm_manager_, &pref_service);
307 EXPECT_CALL(
308 *enrollment_manager.GetSyncScheduler(),
309 Start(elapsed_time, SyncScheduler::Strategy::AGGRESSIVE_RECOVERY));
310 enrollment_manager.Start();
312 EXPECT_FALSE(enrollment_manager.IsEnrollmentValid());
313 EXPECT_TRUE(enrollment_manager.GetLastEnrollmentTime().is_null());
316 TEST_F(ProximityAuthCryptAuthEnrollmentManagerTest, InitWithExistingPrefs) {
317 EXPECT_CALL(
318 *sync_scheduler(),
319 Start(clock_->Now() - base::Time::FromDoubleT(kLastEnrollmentTimeSeconds),
320 SyncScheduler::Strategy::PERIODIC_REFRESH));
322 enrollment_manager_.Start();
323 EXPECT_TRUE(enrollment_manager_.IsEnrollmentValid());
324 EXPECT_EQ(base::Time::FromDoubleT(kLastEnrollmentTimeSeconds),
325 enrollment_manager_.GetLastEnrollmentTime());
328 TEST_F(ProximityAuthCryptAuthEnrollmentManagerTest, InitWithExpiredEnrollment) {
329 pref_service_.SetUserPref(
330 prefs::kCryptAuthEnrollmentLastEnrollmentTimeSeconds,
331 new base::FundamentalValue(kLastExpiredEnrollmentTimeSeconds));
333 EXPECT_CALL(*sync_scheduler(),
334 Start(clock_->Now() - base::Time::FromDoubleT(
335 kLastExpiredEnrollmentTimeSeconds),
336 SyncScheduler::Strategy::AGGRESSIVE_RECOVERY));
338 enrollment_manager_.Start();
339 EXPECT_FALSE(enrollment_manager_.IsEnrollmentValid());
340 EXPECT_EQ(base::Time::FromDoubleT(kLastExpiredEnrollmentTimeSeconds),
341 enrollment_manager_.GetLastEnrollmentTime());
344 TEST_F(ProximityAuthCryptAuthEnrollmentManagerTest, ForceEnrollment) {
345 enrollment_manager_.Start();
347 EXPECT_CALL(*sync_scheduler(), ForceSync());
348 enrollment_manager_.ForceEnrollmentNow(
349 cryptauth::INVOCATION_REASON_SERVER_INITIATED);
351 auto completion_callback =
352 FireSchedulerForEnrollment(cryptauth::INVOCATION_REASON_SERVER_INITIATED);
354 clock_->SetNow(base::Time::FromDoubleT(kLaterTimeNow));
355 EXPECT_CALL(*this, OnEnrollmentFinishedProxy(true));
356 completion_callback.Run(true);
357 EXPECT_EQ(clock_->Now(), enrollment_manager_.GetLastEnrollmentTime());
360 TEST_F(ProximityAuthCryptAuthEnrollmentManagerTest,
361 EnrollmentFailsThenSucceeds) {
362 enrollment_manager_.Start();
363 base::Time old_enrollment_time = enrollment_manager_.GetLastEnrollmentTime();
365 // The first periodic enrollment fails.
366 ON_CALL(*sync_scheduler(), GetStrategy())
367 .WillByDefault(Return(SyncScheduler::Strategy::PERIODIC_REFRESH));
368 auto completion_callback =
369 FireSchedulerForEnrollment(cryptauth::INVOCATION_REASON_PERIODIC);
370 clock_->SetNow(base::Time::FromDoubleT(kLaterTimeNow));
371 EXPECT_CALL(*this, OnEnrollmentFinishedProxy(false));
372 completion_callback.Run(false);
373 EXPECT_EQ(old_enrollment_time, enrollment_manager_.GetLastEnrollmentTime());
374 EXPECT_TRUE(pref_service_.GetBoolean(
375 prefs::kCryptAuthEnrollmentIsRecoveringFromFailure));
377 // The second recovery enrollment succeeds.
378 ON_CALL(*sync_scheduler(), GetStrategy())
379 .WillByDefault(Return(SyncScheduler::Strategy::AGGRESSIVE_RECOVERY));
380 completion_callback =
381 FireSchedulerForEnrollment(cryptauth::INVOCATION_REASON_FAILURE_RECOVERY);
382 clock_->SetNow(base::Time::FromDoubleT(kLaterTimeNow + 30));
383 EXPECT_CALL(*this, OnEnrollmentFinishedProxy(true));
384 completion_callback.Run(true);
385 EXPECT_EQ(clock_->Now(), enrollment_manager_.GetLastEnrollmentTime());
386 EXPECT_FALSE(pref_service_.GetBoolean(
387 prefs::kCryptAuthEnrollmentIsRecoveringFromFailure));
390 TEST_F(ProximityAuthCryptAuthEnrollmentManagerTest,
391 EnrollmentSucceedsForFirstTime) {
392 // Initialize |enrollment_manager_|.
393 ON_CALL(*sync_scheduler(), GetStrategy())
394 .WillByDefault(Return(SyncScheduler::Strategy::PERIODIC_REFRESH));
395 gcm_manager_.set_registration_id(std::string());
396 pref_service_.ClearPref(prefs::kCryptAuthEnrollmentUserPublicKey);
397 pref_service_.ClearPref(prefs::kCryptAuthEnrollmentUserPrivateKey);
398 pref_service_.ClearPref(prefs::kCryptAuthEnrollmentLastEnrollmentTimeSeconds);
399 enrollment_manager_.Start();
400 EXPECT_FALSE(enrollment_manager_.IsEnrollmentValid());
402 // Trigger a sync request.
403 EXPECT_CALL(*this, OnEnrollmentStartedProxy());
404 auto sync_request = make_scoped_ptr(
405 new SyncScheduler::SyncRequest(enrollment_manager_.GetSyncScheduler()));
406 static_cast<SyncScheduler::Delegate*>(&enrollment_manager_)
407 ->OnSyncRequested(sync_request.Pass());
409 // Complete GCM registration successfully, and expect an enrollment.
410 CryptAuthEnroller::EnrollmentFinishedCallback enrollment_callback;
411 EXPECT_CALL(*next_cryptauth_enroller(),
412 Enroll(public_key_, private_key_, _,
413 cryptauth::INVOCATION_REASON_INITIALIZATION, _))
414 .WillOnce(SaveArg<4>(&enrollment_callback));
415 ASSERT_TRUE(gcm_manager_.registration_in_progress());
416 gcm_manager_.CompleteRegistration(kGCMRegistrationId);
418 // Complete CryptAuth enrollment.
419 ASSERT_FALSE(enrollment_callback.is_null());
420 clock_->SetNow(base::Time::FromDoubleT(kLaterTimeNow));
421 EXPECT_CALL(*this, OnEnrollmentFinishedProxy(true));
422 enrollment_callback.Run(true);
423 EXPECT_EQ(clock_->Now(), enrollment_manager_.GetLastEnrollmentTime());
424 EXPECT_TRUE(enrollment_manager_.IsEnrollmentValid());
426 // Check that CryptAuthEnrollmentManager returns the expected key-pair.
427 EXPECT_EQ(public_key_, enrollment_manager_.GetUserPublicKey());
428 EXPECT_EQ(private_key_, enrollment_manager_.GetUserPrivateKey());
431 TEST_F(ProximityAuthCryptAuthEnrollmentManagerTest, GCMRegistrationFails) {
432 // Initialize |enrollment_manager_|.
433 ON_CALL(*sync_scheduler(), GetStrategy())
434 .WillByDefault(Return(SyncScheduler::Strategy::PERIODIC_REFRESH));
435 gcm_manager_.set_registration_id(std::string());
436 enrollment_manager_.Start();
438 // Trigger a sync request.
439 EXPECT_CALL(*this, OnEnrollmentStartedProxy());
440 auto sync_request = make_scoped_ptr(
441 new SyncScheduler::SyncRequest(enrollment_manager_.GetSyncScheduler()));
442 static_cast<SyncScheduler::Delegate*>(&enrollment_manager_)
443 ->OnSyncRequested(sync_request.Pass());
445 // Complete GCM registration with failure.
446 EXPECT_CALL(*this, OnEnrollmentFinishedProxy(false));
447 gcm_manager_.CompleteRegistration(std::string());
450 TEST_F(ProximityAuthCryptAuthEnrollmentManagerTest, ReenrollOnGCMPushMessage) {
451 enrollment_manager_.Start();
453 // Simulate receiving a GCM push message, forcing the device to re-enroll.
454 gcm_manager_.PushReenrollMessage();
455 auto completion_callback =
456 FireSchedulerForEnrollment(cryptauth::INVOCATION_REASON_SERVER_INITIATED);
458 EXPECT_CALL(*this, OnEnrollmentFinishedProxy(true));
459 completion_callback.Run(true);
462 } // namespace proximity_auth