| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #include "components/proximity_auth/cryptauth/cryptauth_device_manager.h" | |
| 6 | |
| 7 #include <stddef.h> | |
| 8 | |
| 9 #include <utility> | |
| 10 | |
| 11 #include "base/base64url.h" | |
| 12 #include "base/macros.h" | |
| 13 #include "base/memory/ptr_util.h" | |
| 14 #include "base/memory/weak_ptr.h" | |
| 15 #include "base/strings/stringprintf.h" | |
| 16 #include "base/test/simple_test_clock.h" | |
| 17 #include "components/prefs/scoped_user_pref_update.h" | |
| 18 #include "components/prefs/testing_pref_service.h" | |
| 19 #include "components/proximity_auth/cryptauth/fake_cryptauth_gcm_manager.h" | |
| 20 #include "components/proximity_auth/cryptauth/mock_cryptauth_client.h" | |
| 21 #include "components/proximity_auth/cryptauth/mock_sync_scheduler.h" | |
| 22 #include "components/proximity_auth/cryptauth/pref_names.h" | |
| 23 #include "testing/gmock/include/gmock/gmock.h" | |
| 24 #include "testing/gtest/include/gtest/gtest.h" | |
| 25 | |
| 26 using ::testing::_; | |
| 27 using ::testing::DoAll; | |
| 28 using ::testing::NiceMock; | |
| 29 using ::testing::Return; | |
| 30 using ::testing::SaveArg; | |
| 31 | |
| 32 namespace proximity_auth { | |
| 33 namespace { | |
| 34 | |
| 35 // The initial "Now" time for testing. | |
| 36 const double kInitialTimeNowSeconds = 20000000; | |
| 37 | |
| 38 // A later "Now" time for testing. | |
| 39 const double kLaterTimeNowSeconds = kInitialTimeNowSeconds + 30; | |
| 40 | |
| 41 // The timestamp of a last successful sync in seconds. | |
| 42 const double kLastSyncTimeSeconds = kInitialTimeNowSeconds - (60 * 60 * 5); | |
| 43 | |
| 44 // Unlock key fields originally stored in the user prefs. | |
| 45 const char kStoredPublicKey[] = "AAPL"; | |
| 46 const char kStoredDeviceName[] = "iPhone 6"; | |
| 47 const char kStoredBluetoothAddress[] = "12:34:56:78:90:AB"; | |
| 48 | |
| 49 // ExternalDeviceInfo fields for the synced unlock key. | |
| 50 const char kPublicKey1[] = "GOOG"; | |
| 51 const char kDeviceName1[] = "Nexus 5"; | |
| 52 const char kBluetoothAddress1[] = "aa:bb:cc:ee:dd:ff"; | |
| 53 | |
| 54 // ExternalDeviceInfo fields for a non-synced unlockable device. | |
| 55 const char kPublicKey2[] = "MSFT"; | |
| 56 const char kDeviceName2[] = "Surface Pro 3"; | |
| 57 | |
| 58 // Validates that |unlock_keys| and the corresponding preferences stored by | |
| 59 // |pref_service| are equal to |expected_unlock_keys|. | |
| 60 void ExpectUnlockKeysAndPrefAreEqual( | |
| 61 const std::vector<cryptauth::ExternalDeviceInfo>& expected_unlock_keys, | |
| 62 const std::vector<cryptauth::ExternalDeviceInfo>& unlock_keys, | |
| 63 const PrefService& pref_service) { | |
| 64 ASSERT_EQ(expected_unlock_keys.size(), unlock_keys.size()); | |
| 65 for (size_t i = 0; i < unlock_keys.size(); ++i) { | |
| 66 SCOPED_TRACE( | |
| 67 base::StringPrintf("Compare protos at index=%d", static_cast<int>(i))); | |
| 68 const auto& expected_unlock_key = expected_unlock_keys[i]; | |
| 69 const auto& unlock_key = unlock_keys.at(i); | |
| 70 EXPECT_EQ(expected_unlock_key.public_key(), unlock_key.public_key()); | |
| 71 EXPECT_EQ(expected_unlock_key.friendly_device_name(), | |
| 72 unlock_key.friendly_device_name()); | |
| 73 EXPECT_EQ(expected_unlock_key.bluetooth_address(), | |
| 74 unlock_key.bluetooth_address()); | |
| 75 EXPECT_TRUE(expected_unlock_key.unlock_key()); | |
| 76 EXPECT_FALSE(expected_unlock_key.unlockable()); | |
| 77 } | |
| 78 | |
| 79 const base::ListValue* unlock_keys_pref = | |
| 80 pref_service.GetList(prefs::kCryptAuthDeviceSyncUnlockKeys); | |
| 81 ASSERT_EQ(expected_unlock_keys.size(), unlock_keys_pref->GetSize()); | |
| 82 for (size_t i = 0; i < unlock_keys_pref->GetSize(); ++i) { | |
| 83 SCOPED_TRACE(base::StringPrintf("Compare pref dictionary at index=%d", | |
| 84 static_cast<int>(i))); | |
| 85 const base::DictionaryValue* unlock_key_dictionary; | |
| 86 EXPECT_TRUE(unlock_keys_pref->GetDictionary(i, &unlock_key_dictionary)); | |
| 87 std::string public_key_b64, device_name_b64, bluetooth_address_b64; | |
| 88 ASSERT_TRUE( | |
| 89 unlock_key_dictionary->GetString("public_key", &public_key_b64)); | |
| 90 ASSERT_TRUE( | |
| 91 unlock_key_dictionary->GetString("device_name", &device_name_b64)); | |
| 92 ASSERT_TRUE(unlock_key_dictionary->GetString("bluetooth_address", | |
| 93 &bluetooth_address_b64)); | |
| 94 | |
| 95 std::string public_key, device_name, bluetooth_address; | |
| 96 ASSERT_TRUE(base::Base64UrlDecode( | |
| 97 public_key_b64, base::Base64UrlDecodePolicy::REQUIRE_PADDING, | |
| 98 &public_key)); | |
| 99 ASSERT_TRUE(base::Base64UrlDecode( | |
| 100 device_name_b64, base::Base64UrlDecodePolicy::REQUIRE_PADDING, | |
| 101 &device_name)); | |
| 102 ASSERT_TRUE(base::Base64UrlDecode( | |
| 103 bluetooth_address_b64, base::Base64UrlDecodePolicy::REQUIRE_PADDING, | |
| 104 &bluetooth_address)); | |
| 105 | |
| 106 const auto& expected_unlock_key = expected_unlock_keys[i]; | |
| 107 EXPECT_EQ(expected_unlock_key.public_key(), public_key); | |
| 108 EXPECT_EQ(expected_unlock_key.friendly_device_name(), device_name); | |
| 109 EXPECT_EQ(expected_unlock_key.bluetooth_address(), bluetooth_address); | |
| 110 EXPECT_TRUE(expected_unlock_key.unlock_key()); | |
| 111 EXPECT_FALSE(expected_unlock_key.unlockable()); | |
| 112 } | |
| 113 } | |
| 114 | |
| 115 // Harness for testing CryptAuthDeviceManager. | |
| 116 class TestCryptAuthDeviceManager : public CryptAuthDeviceManager { | |
| 117 public: | |
| 118 TestCryptAuthDeviceManager( | |
| 119 std::unique_ptr<base::Clock> clock, | |
| 120 std::unique_ptr<CryptAuthClientFactory> client_factory, | |
| 121 CryptAuthGCMManager* gcm_manager, | |
| 122 PrefService* pref_service) | |
| 123 : CryptAuthDeviceManager(std::move(clock), | |
| 124 std::move(client_factory), | |
| 125 gcm_manager, | |
| 126 pref_service), | |
| 127 scoped_sync_scheduler_(new NiceMock<MockSyncScheduler>()), | |
| 128 weak_sync_scheduler_factory_(scoped_sync_scheduler_.get()) {} | |
| 129 | |
| 130 ~TestCryptAuthDeviceManager() override {} | |
| 131 | |
| 132 std::unique_ptr<SyncScheduler> CreateSyncScheduler() override { | |
| 133 EXPECT_TRUE(scoped_sync_scheduler_); | |
| 134 return std::move(scoped_sync_scheduler_); | |
| 135 } | |
| 136 | |
| 137 base::WeakPtr<MockSyncScheduler> GetSyncScheduler() { | |
| 138 return weak_sync_scheduler_factory_.GetWeakPtr(); | |
| 139 } | |
| 140 | |
| 141 private: | |
| 142 // Ownership is passed to |CryptAuthDeviceManager| super class when | |
| 143 // |CreateSyncScheduler()| is called. | |
| 144 std::unique_ptr<MockSyncScheduler> scoped_sync_scheduler_; | |
| 145 | |
| 146 // Stores the pointer of |scoped_sync_scheduler_| after ownership is passed to | |
| 147 // the super class. | |
| 148 // This should be safe because the life-time this SyncScheduler will always be | |
| 149 // within the life of the TestCryptAuthDeviceManager object. | |
| 150 base::WeakPtrFactory<MockSyncScheduler> weak_sync_scheduler_factory_; | |
| 151 | |
| 152 DISALLOW_COPY_AND_ASSIGN(TestCryptAuthDeviceManager); | |
| 153 }; | |
| 154 | |
| 155 } // namespace | |
| 156 | |
| 157 class ProximityAuthCryptAuthDeviceManagerTest | |
| 158 : public testing::Test, | |
| 159 public CryptAuthDeviceManager::Observer, | |
| 160 public MockCryptAuthClientFactory::Observer { | |
| 161 protected: | |
| 162 ProximityAuthCryptAuthDeviceManagerTest() | |
| 163 : clock_(new base::SimpleTestClock()), | |
| 164 client_factory_(new MockCryptAuthClientFactory( | |
| 165 MockCryptAuthClientFactory::MockType::MAKE_STRICT_MOCKS)), | |
| 166 gcm_manager_("existing gcm registration id") { | |
| 167 client_factory_->AddObserver(this); | |
| 168 } | |
| 169 | |
| 170 ~ProximityAuthCryptAuthDeviceManagerTest() { | |
| 171 client_factory_->RemoveObserver(this); | |
| 172 } | |
| 173 | |
| 174 // testing::Test: | |
| 175 void SetUp() override { | |
| 176 clock_->SetNow(base::Time::FromDoubleT(kInitialTimeNowSeconds)); | |
| 177 | |
| 178 CryptAuthDeviceManager::RegisterPrefs(pref_service_.registry()); | |
| 179 pref_service_.SetUserPref( | |
| 180 prefs::kCryptAuthDeviceSyncIsRecoveringFromFailure, | |
| 181 new base::FundamentalValue(false)); | |
| 182 pref_service_.SetUserPref(prefs::kCryptAuthDeviceSyncLastSyncTimeSeconds, | |
| 183 new base::FundamentalValue(kLastSyncTimeSeconds)); | |
| 184 pref_service_.SetUserPref( | |
| 185 prefs::kCryptAuthDeviceSyncReason, | |
| 186 new base::FundamentalValue(cryptauth::INVOCATION_REASON_UNKNOWN)); | |
| 187 | |
| 188 std::unique_ptr<base::DictionaryValue> unlock_key_dictionary( | |
| 189 new base::DictionaryValue()); | |
| 190 | |
| 191 std::string public_key_b64, device_name_b64, bluetooth_address_b64; | |
| 192 base::Base64UrlEncode(kStoredPublicKey, | |
| 193 base::Base64UrlEncodePolicy::INCLUDE_PADDING, | |
| 194 &public_key_b64); | |
| 195 base::Base64UrlEncode(kStoredDeviceName, | |
| 196 base::Base64UrlEncodePolicy::INCLUDE_PADDING, | |
| 197 &device_name_b64); | |
| 198 base::Base64UrlEncode(kStoredBluetoothAddress, | |
| 199 base::Base64UrlEncodePolicy::INCLUDE_PADDING, | |
| 200 &bluetooth_address_b64); | |
| 201 | |
| 202 unlock_key_dictionary->SetString("public_key", public_key_b64); | |
| 203 unlock_key_dictionary->SetString("device_name", device_name_b64); | |
| 204 unlock_key_dictionary->SetString("bluetooth_address", | |
| 205 bluetooth_address_b64); | |
| 206 { | |
| 207 ListPrefUpdate update(&pref_service_, | |
| 208 prefs::kCryptAuthDeviceSyncUnlockKeys); | |
| 209 update.Get()->Append(std::move(unlock_key_dictionary)); | |
| 210 } | |
| 211 | |
| 212 device_manager_.reset(new TestCryptAuthDeviceManager( | |
| 213 base::WrapUnique(clock_), base::WrapUnique(client_factory_), | |
| 214 &gcm_manager_, &pref_service_)); | |
| 215 device_manager_->AddObserver(this); | |
| 216 | |
| 217 cryptauth::ExternalDeviceInfo unlock_key; | |
| 218 unlock_key.set_public_key(kPublicKey1); | |
| 219 unlock_key.set_friendly_device_name(kDeviceName1); | |
| 220 unlock_key.set_bluetooth_address(kBluetoothAddress1); | |
| 221 unlock_key.set_unlock_key(true); | |
| 222 unlock_key.set_unlockable(false); | |
| 223 | |
| 224 cryptauth::ExternalDeviceInfo unlockable_device; | |
| 225 unlockable_device.set_public_key(kPublicKey2); | |
| 226 unlockable_device.set_friendly_device_name(kDeviceName2); | |
| 227 unlockable_device.set_unlock_key(false); | |
| 228 unlockable_device.set_unlockable(true); | |
| 229 | |
| 230 get_my_devices_response_.add_devices()->CopyFrom(unlock_key); | |
| 231 get_my_devices_response_.add_devices()->CopyFrom(unlockable_device); | |
| 232 | |
| 233 ON_CALL(*sync_scheduler(), GetStrategy()) | |
| 234 .WillByDefault(Return(SyncScheduler::Strategy::PERIODIC_REFRESH)); | |
| 235 } | |
| 236 | |
| 237 void TearDown() override { device_manager_->RemoveObserver(this); } | |
| 238 | |
| 239 // CryptAuthDeviceManager::Observer: | |
| 240 void OnSyncStarted() override { OnSyncStartedProxy(); } | |
| 241 | |
| 242 void OnSyncFinished(CryptAuthDeviceManager::SyncResult sync_result, | |
| 243 CryptAuthDeviceManager::DeviceChangeResult | |
| 244 device_change_result) override { | |
| 245 OnSyncFinishedProxy(sync_result, device_change_result); | |
| 246 } | |
| 247 | |
| 248 MOCK_METHOD0(OnSyncStartedProxy, void()); | |
| 249 MOCK_METHOD2(OnSyncFinishedProxy, | |
| 250 void(CryptAuthDeviceManager::SyncResult, | |
| 251 CryptAuthDeviceManager::DeviceChangeResult)); | |
| 252 | |
| 253 // Simulates firing the SyncScheduler to trigger a device sync attempt. | |
| 254 void FireSchedulerForSync( | |
| 255 cryptauth::InvocationReason expected_invocation_reason) { | |
| 256 SyncScheduler::Delegate* delegate = | |
| 257 static_cast<SyncScheduler::Delegate*>(device_manager_.get()); | |
| 258 | |
| 259 std::unique_ptr<SyncScheduler::SyncRequest> sync_request = | |
| 260 base::MakeUnique<SyncScheduler::SyncRequest>( | |
| 261 device_manager_->GetSyncScheduler()); | |
| 262 EXPECT_CALL(*this, OnSyncStartedProxy()); | |
| 263 delegate->OnSyncRequested(std::move(sync_request)); | |
| 264 | |
| 265 EXPECT_EQ(expected_invocation_reason, | |
| 266 get_my_devices_request_.invocation_reason()); | |
| 267 | |
| 268 // The allow_stale_read flag is set if the sync was not forced. | |
| 269 bool allow_stale_read = | |
| 270 pref_service_.GetInteger(prefs::kCryptAuthDeviceSyncReason) != | |
| 271 cryptauth::INVOCATION_REASON_UNKNOWN; | |
| 272 EXPECT_EQ(allow_stale_read, get_my_devices_request_.allow_stale_read()); | |
| 273 } | |
| 274 | |
| 275 // MockCryptAuthClientFactory::Observer: | |
| 276 void OnCryptAuthClientCreated(MockCryptAuthClient* client) override { | |
| 277 EXPECT_CALL(*client, GetMyDevices(_, _, _)) | |
| 278 .WillOnce(DoAll(SaveArg<0>(&get_my_devices_request_), | |
| 279 SaveArg<1>(&success_callback_), | |
| 280 SaveArg<2>(&error_callback_))); | |
| 281 } | |
| 282 | |
| 283 MockSyncScheduler* sync_scheduler() { | |
| 284 return device_manager_->GetSyncScheduler().get(); | |
| 285 } | |
| 286 | |
| 287 // Owned by |device_manager_|. | |
| 288 base::SimpleTestClock* clock_; | |
| 289 | |
| 290 // Owned by |device_manager_|. | |
| 291 MockCryptAuthClientFactory* client_factory_; | |
| 292 | |
| 293 TestingPrefServiceSimple pref_service_; | |
| 294 | |
| 295 FakeCryptAuthGCMManager gcm_manager_; | |
| 296 | |
| 297 std::unique_ptr<TestCryptAuthDeviceManager> device_manager_; | |
| 298 | |
| 299 cryptauth::GetMyDevicesResponse get_my_devices_response_; | |
| 300 | |
| 301 cryptauth::GetMyDevicesRequest get_my_devices_request_; | |
| 302 | |
| 303 CryptAuthClient::GetMyDevicesCallback success_callback_; | |
| 304 | |
| 305 CryptAuthClient::ErrorCallback error_callback_; | |
| 306 | |
| 307 DISALLOW_COPY_AND_ASSIGN(ProximityAuthCryptAuthDeviceManagerTest); | |
| 308 }; | |
| 309 | |
| 310 TEST_F(ProximityAuthCryptAuthDeviceManagerTest, RegisterPrefs) { | |
| 311 TestingPrefServiceSimple pref_service; | |
| 312 CryptAuthDeviceManager::RegisterPrefs(pref_service.registry()); | |
| 313 EXPECT_TRUE(pref_service.FindPreference( | |
| 314 prefs::kCryptAuthDeviceSyncLastSyncTimeSeconds)); | |
| 315 EXPECT_TRUE(pref_service.FindPreference( | |
| 316 prefs::kCryptAuthDeviceSyncIsRecoveringFromFailure)); | |
| 317 EXPECT_TRUE(pref_service.FindPreference(prefs::kCryptAuthDeviceSyncReason)); | |
| 318 EXPECT_TRUE( | |
| 319 pref_service.FindPreference(prefs::kCryptAuthDeviceSyncUnlockKeys)); | |
| 320 } | |
| 321 | |
| 322 TEST_F(ProximityAuthCryptAuthDeviceManagerTest, GetSyncState) { | |
| 323 device_manager_->Start(); | |
| 324 | |
| 325 ON_CALL(*sync_scheduler(), GetStrategy()) | |
| 326 .WillByDefault(Return(SyncScheduler::Strategy::PERIODIC_REFRESH)); | |
| 327 EXPECT_FALSE(device_manager_->IsRecoveringFromFailure()); | |
| 328 | |
| 329 ON_CALL(*sync_scheduler(), GetStrategy()) | |
| 330 .WillByDefault(Return(SyncScheduler::Strategy::AGGRESSIVE_RECOVERY)); | |
| 331 EXPECT_TRUE(device_manager_->IsRecoveringFromFailure()); | |
| 332 | |
| 333 base::TimeDelta time_to_next_sync = base::TimeDelta::FromMinutes(60); | |
| 334 ON_CALL(*sync_scheduler(), GetTimeToNextSync()) | |
| 335 .WillByDefault(Return(time_to_next_sync)); | |
| 336 EXPECT_EQ(time_to_next_sync, device_manager_->GetTimeToNextAttempt()); | |
| 337 | |
| 338 ON_CALL(*sync_scheduler(), GetSyncState()) | |
| 339 .WillByDefault(Return(SyncScheduler::SyncState::SYNC_IN_PROGRESS)); | |
| 340 EXPECT_TRUE(device_manager_->IsSyncInProgress()); | |
| 341 | |
| 342 ON_CALL(*sync_scheduler(), GetSyncState()) | |
| 343 .WillByDefault(Return(SyncScheduler::SyncState::WAITING_FOR_REFRESH)); | |
| 344 EXPECT_FALSE(device_manager_->IsSyncInProgress()); | |
| 345 } | |
| 346 | |
| 347 TEST_F(ProximityAuthCryptAuthDeviceManagerTest, InitWithDefaultPrefs) { | |
| 348 std::unique_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock); | |
| 349 clock->SetNow(base::Time::FromDoubleT(kInitialTimeNowSeconds)); | |
| 350 base::TimeDelta elapsed_time = clock->Now() - base::Time::FromDoubleT(0); | |
| 351 | |
| 352 TestingPrefServiceSimple pref_service; | |
| 353 CryptAuthDeviceManager::RegisterPrefs(pref_service.registry()); | |
| 354 | |
| 355 TestCryptAuthDeviceManager device_manager( | |
| 356 std::move(clock), | |
| 357 base::MakeUnique<MockCryptAuthClientFactory>( | |
| 358 MockCryptAuthClientFactory::MockType::MAKE_STRICT_MOCKS), | |
| 359 &gcm_manager_, &pref_service); | |
| 360 | |
| 361 EXPECT_CALL( | |
| 362 *(device_manager.GetSyncScheduler()), | |
| 363 Start(elapsed_time, SyncScheduler::Strategy::AGGRESSIVE_RECOVERY)); | |
| 364 device_manager.Start(); | |
| 365 EXPECT_TRUE(device_manager.GetLastSyncTime().is_null()); | |
| 366 EXPECT_EQ(0u, device_manager.unlock_keys().size()); | |
| 367 } | |
| 368 | |
| 369 TEST_F(ProximityAuthCryptAuthDeviceManagerTest, InitWithExistingPrefs) { | |
| 370 EXPECT_CALL( | |
| 371 *sync_scheduler(), | |
| 372 Start(clock_->Now() - base::Time::FromDoubleT(kLastSyncTimeSeconds), | |
| 373 SyncScheduler::Strategy::PERIODIC_REFRESH)); | |
| 374 | |
| 375 device_manager_->Start(); | |
| 376 EXPECT_EQ(base::Time::FromDoubleT(kLastSyncTimeSeconds), | |
| 377 device_manager_->GetLastSyncTime()); | |
| 378 | |
| 379 auto unlock_keys = device_manager_->unlock_keys(); | |
| 380 ASSERT_EQ(1u, unlock_keys.size()); | |
| 381 EXPECT_EQ(kStoredPublicKey, unlock_keys[0].public_key()); | |
| 382 EXPECT_EQ(kStoredDeviceName, unlock_keys[0].friendly_device_name()); | |
| 383 EXPECT_EQ(kStoredBluetoothAddress, unlock_keys[0].bluetooth_address()); | |
| 384 EXPECT_TRUE(unlock_keys[0].unlock_key()); | |
| 385 } | |
| 386 | |
| 387 TEST_F(ProximityAuthCryptAuthDeviceManagerTest, SyncSucceedsForFirstTime) { | |
| 388 pref_service_.ClearPref(prefs::kCryptAuthDeviceSyncLastSyncTimeSeconds); | |
| 389 device_manager_->Start(); | |
| 390 | |
| 391 FireSchedulerForSync(cryptauth::INVOCATION_REASON_INITIALIZATION); | |
| 392 ASSERT_FALSE(success_callback_.is_null()); | |
| 393 | |
| 394 clock_->SetNow(base::Time::FromDoubleT(kLaterTimeNowSeconds)); | |
| 395 EXPECT_CALL(*this, OnSyncFinishedProxy( | |
| 396 CryptAuthDeviceManager::SyncResult::SUCCESS, | |
| 397 CryptAuthDeviceManager::DeviceChangeResult::CHANGED)); | |
| 398 | |
| 399 success_callback_.Run(get_my_devices_response_); | |
| 400 EXPECT_EQ(clock_->Now(), device_manager_->GetLastSyncTime()); | |
| 401 | |
| 402 ExpectUnlockKeysAndPrefAreEqual(std::vector<cryptauth::ExternalDeviceInfo>( | |
| 403 1, get_my_devices_response_.devices(0)), | |
| 404 device_manager_->unlock_keys(), | |
| 405 pref_service_); | |
| 406 } | |
| 407 | |
| 408 TEST_F(ProximityAuthCryptAuthDeviceManagerTest, ForceSync) { | |
| 409 device_manager_->Start(); | |
| 410 | |
| 411 EXPECT_CALL(*sync_scheduler(), ForceSync()); | |
| 412 device_manager_->ForceSyncNow(cryptauth::INVOCATION_REASON_MANUAL); | |
| 413 | |
| 414 FireSchedulerForSync(cryptauth::INVOCATION_REASON_MANUAL); | |
| 415 | |
| 416 clock_->SetNow(base::Time::FromDoubleT(kLaterTimeNowSeconds)); | |
| 417 EXPECT_CALL(*this, OnSyncFinishedProxy( | |
| 418 CryptAuthDeviceManager::SyncResult::SUCCESS, | |
| 419 CryptAuthDeviceManager::DeviceChangeResult::CHANGED)); | |
| 420 success_callback_.Run(get_my_devices_response_); | |
| 421 EXPECT_EQ(clock_->Now(), device_manager_->GetLastSyncTime()); | |
| 422 | |
| 423 ExpectUnlockKeysAndPrefAreEqual(std::vector<cryptauth::ExternalDeviceInfo>( | |
| 424 1, get_my_devices_response_.devices(0)), | |
| 425 device_manager_->unlock_keys(), | |
| 426 pref_service_); | |
| 427 } | |
| 428 | |
| 429 TEST_F(ProximityAuthCryptAuthDeviceManagerTest, ForceSyncFailsThenSucceeds) { | |
| 430 device_manager_->Start(); | |
| 431 EXPECT_FALSE(pref_service_.GetBoolean( | |
| 432 prefs::kCryptAuthDeviceSyncIsRecoveringFromFailure)); | |
| 433 base::Time old_sync_time = device_manager_->GetLastSyncTime(); | |
| 434 | |
| 435 // The first force sync fails. | |
| 436 EXPECT_CALL(*sync_scheduler(), ForceSync()); | |
| 437 device_manager_->ForceSyncNow(cryptauth::INVOCATION_REASON_MANUAL); | |
| 438 FireSchedulerForSync(cryptauth::INVOCATION_REASON_MANUAL); | |
| 439 clock_->SetNow(base::Time::FromDoubleT(kLaterTimeNowSeconds)); | |
| 440 EXPECT_CALL(*this, | |
| 441 OnSyncFinishedProxy( | |
| 442 CryptAuthDeviceManager::SyncResult::FAILURE, | |
| 443 CryptAuthDeviceManager::DeviceChangeResult::UNCHANGED)); | |
| 444 error_callback_.Run("404"); | |
| 445 EXPECT_EQ(old_sync_time, device_manager_->GetLastSyncTime()); | |
| 446 EXPECT_TRUE(pref_service_.GetBoolean( | |
| 447 prefs::kCryptAuthDeviceSyncIsRecoveringFromFailure)); | |
| 448 EXPECT_EQ(static_cast<int>(cryptauth::INVOCATION_REASON_MANUAL), | |
| 449 pref_service_.GetInteger(prefs::kCryptAuthDeviceSyncReason)); | |
| 450 | |
| 451 // The second recovery sync succeeds. | |
| 452 ON_CALL(*sync_scheduler(), GetStrategy()) | |
| 453 .WillByDefault(Return(SyncScheduler::Strategy::AGGRESSIVE_RECOVERY)); | |
| 454 FireSchedulerForSync(cryptauth::INVOCATION_REASON_MANUAL); | |
| 455 clock_->SetNow(base::Time::FromDoubleT(kLaterTimeNowSeconds + 30)); | |
| 456 EXPECT_CALL(*this, OnSyncFinishedProxy( | |
| 457 CryptAuthDeviceManager::SyncResult::SUCCESS, | |
| 458 CryptAuthDeviceManager::DeviceChangeResult::CHANGED)); | |
| 459 success_callback_.Run(get_my_devices_response_); | |
| 460 EXPECT_EQ(clock_->Now(), device_manager_->GetLastSyncTime()); | |
| 461 | |
| 462 ExpectUnlockKeysAndPrefAreEqual(std::vector<cryptauth::ExternalDeviceInfo>( | |
| 463 1, get_my_devices_response_.devices(0)), | |
| 464 device_manager_->unlock_keys(), | |
| 465 pref_service_); | |
| 466 | |
| 467 EXPECT_FLOAT_EQ( | |
| 468 clock_->Now().ToDoubleT(), | |
| 469 pref_service_.GetDouble(prefs::kCryptAuthDeviceSyncLastSyncTimeSeconds)); | |
| 470 EXPECT_EQ(static_cast<int>(cryptauth::INVOCATION_REASON_UNKNOWN), | |
| 471 pref_service_.GetInteger(prefs::kCryptAuthDeviceSyncReason)); | |
| 472 EXPECT_FALSE(pref_service_.GetBoolean( | |
| 473 prefs::kCryptAuthDeviceSyncIsRecoveringFromFailure)); | |
| 474 } | |
| 475 | |
| 476 TEST_F(ProximityAuthCryptAuthDeviceManagerTest, PeriodicSyncFailsThenSucceeds) { | |
| 477 device_manager_->Start(); | |
| 478 base::Time old_sync_time = device_manager_->GetLastSyncTime(); | |
| 479 | |
| 480 // The first periodic sync fails. | |
| 481 FireSchedulerForSync(cryptauth::INVOCATION_REASON_PERIODIC); | |
| 482 clock_->SetNow(base::Time::FromDoubleT(kLaterTimeNowSeconds)); | |
| 483 EXPECT_CALL(*this, | |
| 484 OnSyncFinishedProxy( | |
| 485 CryptAuthDeviceManager::SyncResult::FAILURE, | |
| 486 CryptAuthDeviceManager::DeviceChangeResult::UNCHANGED)); | |
| 487 error_callback_.Run("401"); | |
| 488 EXPECT_EQ(old_sync_time, device_manager_->GetLastSyncTime()); | |
| 489 EXPECT_TRUE(pref_service_.GetBoolean( | |
| 490 prefs::kCryptAuthDeviceSyncIsRecoveringFromFailure)); | |
| 491 | |
| 492 // The second recovery sync succeeds. | |
| 493 ON_CALL(*sync_scheduler(), GetStrategy()) | |
| 494 .WillByDefault(Return(SyncScheduler::Strategy::AGGRESSIVE_RECOVERY)); | |
| 495 FireSchedulerForSync(cryptauth::INVOCATION_REASON_FAILURE_RECOVERY); | |
| 496 clock_->SetNow(base::Time::FromDoubleT(kLaterTimeNowSeconds + 30)); | |
| 497 EXPECT_CALL(*this, OnSyncFinishedProxy( | |
| 498 CryptAuthDeviceManager::SyncResult::SUCCESS, | |
| 499 CryptAuthDeviceManager::DeviceChangeResult::CHANGED)); | |
| 500 success_callback_.Run(get_my_devices_response_); | |
| 501 EXPECT_EQ(clock_->Now(), device_manager_->GetLastSyncTime()); | |
| 502 | |
| 503 ExpectUnlockKeysAndPrefAreEqual(std::vector<cryptauth::ExternalDeviceInfo>( | |
| 504 1, get_my_devices_response_.devices(0)), | |
| 505 device_manager_->unlock_keys(), | |
| 506 pref_service_); | |
| 507 | |
| 508 EXPECT_FLOAT_EQ( | |
| 509 clock_->Now().ToDoubleT(), | |
| 510 pref_service_.GetDouble(prefs::kCryptAuthDeviceSyncLastSyncTimeSeconds)); | |
| 511 EXPECT_FALSE(pref_service_.GetBoolean( | |
| 512 prefs::kCryptAuthDeviceSyncIsRecoveringFromFailure)); | |
| 513 } | |
| 514 | |
| 515 TEST_F(ProximityAuthCryptAuthDeviceManagerTest, SyncSameDevice) { | |
| 516 device_manager_->Start(); | |
| 517 auto original_unlock_keys = device_manager_->unlock_keys(); | |
| 518 | |
| 519 // Sync new devices. | |
| 520 FireSchedulerForSync(cryptauth::INVOCATION_REASON_PERIODIC); | |
| 521 ASSERT_FALSE(success_callback_.is_null()); | |
| 522 EXPECT_CALL(*this, | |
| 523 OnSyncFinishedProxy( | |
| 524 CryptAuthDeviceManager::SyncResult::SUCCESS, | |
| 525 CryptAuthDeviceManager::DeviceChangeResult::UNCHANGED)); | |
| 526 | |
| 527 // Sync the same device. | |
| 528 cryptauth::ExternalDeviceInfo synced_unlock_key; | |
| 529 synced_unlock_key.set_public_key(kStoredPublicKey); | |
| 530 synced_unlock_key.set_friendly_device_name(kStoredDeviceName); | |
| 531 synced_unlock_key.set_bluetooth_address(kStoredBluetoothAddress); | |
| 532 synced_unlock_key.set_unlock_key(true); | |
| 533 synced_unlock_key.set_unlockable(false); | |
| 534 cryptauth::GetMyDevicesResponse get_my_devices_response; | |
| 535 get_my_devices_response.add_devices()->CopyFrom(synced_unlock_key); | |
| 536 success_callback_.Run(get_my_devices_response); | |
| 537 | |
| 538 // Check that unlock keys are still the same after sync. | |
| 539 ExpectUnlockKeysAndPrefAreEqual( | |
| 540 original_unlock_keys, device_manager_->unlock_keys(), pref_service_); | |
| 541 } | |
| 542 | |
| 543 TEST_F(ProximityAuthCryptAuthDeviceManagerTest, SyncEmptyDeviceList) { | |
| 544 cryptauth::GetMyDevicesResponse empty_response; | |
| 545 | |
| 546 device_manager_->Start(); | |
| 547 EXPECT_EQ(1u, device_manager_->unlock_keys().size()); | |
| 548 | |
| 549 FireSchedulerForSync(cryptauth::INVOCATION_REASON_PERIODIC); | |
| 550 ASSERT_FALSE(success_callback_.is_null()); | |
| 551 EXPECT_CALL(*this, OnSyncFinishedProxy( | |
| 552 CryptAuthDeviceManager::SyncResult::SUCCESS, | |
| 553 CryptAuthDeviceManager::DeviceChangeResult::CHANGED)); | |
| 554 success_callback_.Run(empty_response); | |
| 555 | |
| 556 ExpectUnlockKeysAndPrefAreEqual(std::vector<cryptauth::ExternalDeviceInfo>(), | |
| 557 device_manager_->unlock_keys(), | |
| 558 pref_service_); | |
| 559 } | |
| 560 | |
| 561 TEST_F(ProximityAuthCryptAuthDeviceManagerTest, SyncTwoUnlockKeys) { | |
| 562 cryptauth::GetMyDevicesResponse response(get_my_devices_response_); | |
| 563 cryptauth::ExternalDeviceInfo unlock_key2; | |
| 564 unlock_key2.set_public_key("new public key"); | |
| 565 unlock_key2.set_friendly_device_name("new device name"); | |
| 566 unlock_key2.set_bluetooth_address("aa:bb:cc:dd:ee:ff"); | |
| 567 unlock_key2.set_unlock_key(true); | |
| 568 response.add_devices()->CopyFrom(unlock_key2); | |
| 569 | |
| 570 std::vector<cryptauth::ExternalDeviceInfo> expected_unlock_keys; | |
| 571 expected_unlock_keys.push_back(get_my_devices_response_.devices(0)); | |
| 572 expected_unlock_keys.push_back(unlock_key2); | |
| 573 | |
| 574 device_manager_->Start(); | |
| 575 EXPECT_EQ(1u, device_manager_->unlock_keys().size()); | |
| 576 EXPECT_EQ(1u, pref_service_.GetList(prefs::kCryptAuthDeviceSyncUnlockKeys) | |
| 577 ->GetSize()); | |
| 578 | |
| 579 FireSchedulerForSync(cryptauth::INVOCATION_REASON_PERIODIC); | |
| 580 ASSERT_FALSE(success_callback_.is_null()); | |
| 581 EXPECT_CALL(*this, OnSyncFinishedProxy( | |
| 582 CryptAuthDeviceManager::SyncResult::SUCCESS, | |
| 583 CryptAuthDeviceManager::DeviceChangeResult::CHANGED)); | |
| 584 success_callback_.Run(response); | |
| 585 | |
| 586 ExpectUnlockKeysAndPrefAreEqual( | |
| 587 expected_unlock_keys, device_manager_->unlock_keys(), pref_service_); | |
| 588 } | |
| 589 | |
| 590 TEST_F(ProximityAuthCryptAuthDeviceManagerTest, SyncOnGCMPushMessage) { | |
| 591 device_manager_->Start(); | |
| 592 | |
| 593 EXPECT_CALL(*sync_scheduler(), ForceSync()); | |
| 594 gcm_manager_.PushResyncMessage(); | |
| 595 | |
| 596 FireSchedulerForSync(cryptauth::INVOCATION_REASON_SERVER_INITIATED); | |
| 597 | |
| 598 EXPECT_CALL(*this, OnSyncFinishedProxy( | |
| 599 CryptAuthDeviceManager::SyncResult::SUCCESS, | |
| 600 CryptAuthDeviceManager::DeviceChangeResult::CHANGED)); | |
| 601 success_callback_.Run(get_my_devices_response_); | |
| 602 | |
| 603 ExpectUnlockKeysAndPrefAreEqual(std::vector<cryptauth::ExternalDeviceInfo>( | |
| 604 1, get_my_devices_response_.devices(0)), | |
| 605 device_manager_->unlock_keys(), | |
| 606 pref_service_); | |
| 607 } | |
| 608 | |
| 609 } // namespace proximity_auth | |
| OLD | NEW |