| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/password_manager/password_store_proxy_mac.h" | 5 #include "chrome/browser/password_manager/password_store_proxy_mac.h" |
| 6 | 6 |
| 7 #include "base/files/scoped_temp_dir.h" | 7 #include "base/files/scoped_temp_dir.h" |
| 8 #include "base/scoped_observer.h" | 8 #include "base/scoped_observer.h" |
| 9 #include "base/strings/utf_string_conversions.h" | 9 #include "base/strings/utf_string_conversions.h" |
| 10 #include "base/test/histogram_tester.h" |
| 11 #include "chrome/browser/password_manager/password_store_mac.h" |
| 12 #include "chrome/browser/password_manager/password_store_mac_internal.h" |
| 13 #include "chrome/browser/prefs/browser_prefs.h" |
| 14 #include "chrome/test/base/testing_pref_service_syncable.h" |
| 10 #include "components/os_crypt/os_crypt.h" | 15 #include "components/os_crypt/os_crypt.h" |
| 11 #include "components/password_manager/core/browser/login_database.h" | 16 #include "components/password_manager/core/browser/login_database.h" |
| 12 #include "components/password_manager/core/browser/password_manager_test_utils.h
" | 17 #include "components/password_manager/core/browser/password_manager_test_utils.h
" |
| 13 #include "components/password_manager/core/browser/password_store_consumer.h" | 18 #include "components/password_manager/core/browser/password_store_consumer.h" |
| 19 #include "components/password_manager/core/common/password_manager_pref_names.h" |
| 14 #include "content/public/browser/browser_thread.h" | 20 #include "content/public/browser/browser_thread.h" |
| 15 #include "content/public/test/test_browser_thread_bundle.h" | 21 #include "content/public/test/test_browser_thread_bundle.h" |
| 16 #include "crypto/mock_apple_keychain.h" | 22 #include "crypto/mock_apple_keychain.h" |
| 17 #include "testing/gmock/include/gmock/gmock.h" | 23 #include "testing/gmock/include/gmock/gmock.h" |
| 18 #include "testing/gtest/include/gtest/gtest.h" | 24 #include "testing/gtest/include/gtest/gtest.h" |
| 19 | 25 |
| 20 namespace { | 26 namespace { |
| 21 | 27 |
| 22 using autofill::PasswordForm; | 28 using autofill::PasswordForm; |
| 23 using content::BrowserThread; | 29 using content::BrowserThread; |
| 30 using password_manager::MigrationStatus; |
| 31 using password_manager::PasswordStoreChange; |
| 32 using password_manager::PasswordStoreChangeList; |
| 24 using testing::_; | 33 using testing::_; |
| 25 using testing::ElementsAre; | 34 using testing::ElementsAre; |
| 26 using testing::IsEmpty; | 35 using testing::IsEmpty; |
| 27 using testing::Pointee; | 36 using testing::Pointee; |
| 28 | 37 |
| 29 ACTION(QuitUIMessageLoop) { | 38 ACTION(QuitUIMessageLoop) { |
| 30 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 39 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 31 base::MessageLoop::current()->Quit(); | 40 base::MessageLoop::current()->Quit(); |
| 32 } | 41 } |
| 33 | 42 |
| 43 // Returns a change list corresponding to |form| being added. |
| 44 PasswordStoreChangeList AddChangeForForm(const PasswordForm& form) { |
| 45 return PasswordStoreChangeList( |
| 46 1, PasswordStoreChange(PasswordStoreChange::ADD, form)); |
| 47 } |
| 48 |
| 34 class MockPasswordStoreConsumer | 49 class MockPasswordStoreConsumer |
| 35 : public password_manager::PasswordStoreConsumer { | 50 : public password_manager::PasswordStoreConsumer { |
| 36 public: | 51 public: |
| 37 MOCK_METHOD1(OnGetPasswordStoreResultsConstRef, | 52 MOCK_METHOD1(OnGetPasswordStoreResultsConstRef, |
| 38 void(const std::vector<PasswordForm*>&)); | 53 void(const std::vector<PasswordForm*>&)); |
| 39 | 54 |
| 40 // GMock cannot mock methods with move-only args. | 55 // GMock cannot mock methods with move-only args. |
| 41 void OnGetPasswordStoreResults(ScopedVector<PasswordForm> results) override { | 56 void OnGetPasswordStoreResults(ScopedVector<PasswordForm> results) override { |
| 42 OnGetPasswordStoreResultsConstRef(results.get()); | 57 OnGetPasswordStoreResultsConstRef(results.get()); |
| 43 } | 58 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 63 BadLoginDatabase() : password_manager::LoginDatabase(base::FilePath()) {} | 78 BadLoginDatabase() : password_manager::LoginDatabase(base::FilePath()) {} |
| 64 ~BadLoginDatabase() override {} | 79 ~BadLoginDatabase() override {} |
| 65 | 80 |
| 66 // LoginDatabase: | 81 // LoginDatabase: |
| 67 bool Init() override { return false; } | 82 bool Init() override { return false; } |
| 68 | 83 |
| 69 private: | 84 private: |
| 70 DISALLOW_COPY_AND_ASSIGN(BadLoginDatabase); | 85 DISALLOW_COPY_AND_ASSIGN(BadLoginDatabase); |
| 71 }; | 86 }; |
| 72 | 87 |
| 73 class PasswordStoreProxyMacTest : public testing::Test { | 88 class PasswordStoreProxyMacTest |
| 89 : public testing::TestWithParam<MigrationStatus> { |
| 74 public: | 90 public: |
| 91 PasswordStoreProxyMacTest(); |
| 92 ~PasswordStoreProxyMacTest() override; |
| 93 |
| 75 void SetUp() override; | 94 void SetUp() override; |
| 76 void TearDown() override; | 95 void TearDown() override; |
| 77 | 96 |
| 78 void CreateAndInitPasswordStore( | 97 void CreateAndInitPasswordStore( |
| 79 scoped_ptr<password_manager::LoginDatabase> login_db); | 98 scoped_ptr<password_manager::LoginDatabase> login_db); |
| 80 | 99 |
| 81 void ClosePasswordStore(); | 100 void ClosePasswordStore(); |
| 82 | 101 |
| 83 // Do a store-level query to wait for all the previously enqueued operations | 102 // Do a store-level query to wait for all the previously enqueued operations |
| 84 // to finish. | 103 // to finish. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 99 return store_->login_metadata_db(); | 118 return store_->login_metadata_db(); |
| 100 } | 119 } |
| 101 | 120 |
| 102 PasswordStoreProxyMac* store() { return store_.get(); } | 121 PasswordStoreProxyMac* store() { return store_.get(); } |
| 103 | 122 |
| 104 protected: | 123 protected: |
| 105 content::TestBrowserThreadBundle ui_thread_; | 124 content::TestBrowserThreadBundle ui_thread_; |
| 106 | 125 |
| 107 base::ScopedTempDir db_dir_; | 126 base::ScopedTempDir db_dir_; |
| 108 scoped_refptr<PasswordStoreProxyMac> store_; | 127 scoped_refptr<PasswordStoreProxyMac> store_; |
| 128 TestingPrefServiceSyncable testing_prefs_; |
| 109 }; | 129 }; |
| 110 | 130 |
| 111 void PasswordStoreProxyMacTest::SetUp() { | 131 PasswordStoreProxyMacTest::PasswordStoreProxyMacTest() { |
| 112 ASSERT_TRUE(db_dir_.CreateUniqueTempDir()); | 132 EXPECT_TRUE(db_dir_.CreateUniqueTempDir()); |
| 113 | 133 chrome::RegisterUserProfilePrefs(testing_prefs_.registry()); |
| 134 testing_prefs_.SetInteger(password_manager::prefs::kKeychainMigrationStatus, |
| 135 static_cast<int>(GetParam())); |
| 114 // Ensure that LoginDatabase will use the mock keychain if it needs to | 136 // Ensure that LoginDatabase will use the mock keychain if it needs to |
| 115 // encrypt/decrypt a password. | 137 // encrypt/decrypt a password. |
| 116 OSCrypt::UseMockKeychain(true); | 138 OSCrypt::UseMockKeychain(true); |
| 139 } |
| 140 |
| 141 PasswordStoreProxyMacTest::~PasswordStoreProxyMacTest() { |
| 142 } |
| 143 |
| 144 void PasswordStoreProxyMacTest::SetUp() { |
| 117 scoped_ptr<password_manager::LoginDatabase> login_db( | 145 scoped_ptr<password_manager::LoginDatabase> login_db( |
| 118 new password_manager::LoginDatabase(test_login_db_file_path())); | 146 new password_manager::LoginDatabase(test_login_db_file_path())); |
| 119 CreateAndInitPasswordStore(login_db.Pass()); | 147 CreateAndInitPasswordStore(login_db.Pass()); |
| 120 // Make sure deferred initialization is performed before some tests start | |
| 121 // accessing the |login_db| directly. | |
| 122 FinishAsyncProcessing(); | |
| 123 } | 148 } |
| 124 | 149 |
| 125 void PasswordStoreProxyMacTest::TearDown() { | 150 void PasswordStoreProxyMacTest::TearDown() { |
| 126 ClosePasswordStore(); | 151 ClosePasswordStore(); |
| 127 } | 152 } |
| 128 | 153 |
| 129 void PasswordStoreProxyMacTest::CreateAndInitPasswordStore( | 154 void PasswordStoreProxyMacTest::CreateAndInitPasswordStore( |
| 130 scoped_ptr<password_manager::LoginDatabase> login_db) { | 155 scoped_ptr<password_manager::LoginDatabase> login_db) { |
| 131 store_ = new PasswordStoreProxyMac( | 156 store_ = new PasswordStoreProxyMac( |
| 132 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), | 157 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), |
| 133 make_scoped_ptr(new crypto::MockAppleKeychain), login_db.Pass()); | 158 make_scoped_ptr(new crypto::MockAppleKeychain), login_db.Pass(), |
| 159 &testing_prefs_); |
| 134 ASSERT_TRUE(store_->Init(syncer::SyncableService::StartSyncFlare())); | 160 ASSERT_TRUE(store_->Init(syncer::SyncableService::StartSyncFlare())); |
| 135 } | 161 } |
| 136 | 162 |
| 137 void PasswordStoreProxyMacTest::ClosePasswordStore() { | 163 void PasswordStoreProxyMacTest::ClosePasswordStore() { |
| 138 if (!store_) | 164 if (!store_) |
| 139 return; | 165 return; |
| 140 store_->Shutdown(); | 166 store_->Shutdown(); |
| 141 EXPECT_FALSE(store_->GetBackgroundTaskRunner()); | 167 EXPECT_FALSE(store_->GetBackgroundTaskRunner()); |
| 142 base::MessageLoop::current()->RunUntilIdle(); | |
| 143 store_ = nullptr; | 168 store_ = nullptr; |
| 144 } | 169 } |
| 145 | 170 |
| 146 void PasswordStoreProxyMacTest::FinishAsyncProcessing() { | 171 void PasswordStoreProxyMacTest::FinishAsyncProcessing() { |
| 147 // Do a store-level query to wait for all the previously enqueued operations | 172 // Do a store-level query to wait for all the previously enqueued operations |
| 148 // to finish. | 173 // to finish. |
| 149 MockPasswordStoreConsumer consumer; | 174 MockPasswordStoreConsumer consumer; |
| 150 store_->GetLogins(PasswordForm(), | 175 store_->GetLogins(PasswordForm(), |
| 151 password_manager::PasswordStore::ALLOW_PROMPT, &consumer); | 176 password_manager::PasswordStore::ALLOW_PROMPT, &consumer); |
| 152 EXPECT_CALL(consumer, OnGetPasswordStoreResultsConstRef(_)) | 177 EXPECT_CALL(consumer, OnGetPasswordStoreResultsConstRef(_)) |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 EXPECT_CALL(mock_observer, OnLoginsChanged(list)); | 247 EXPECT_CALL(mock_observer, OnLoginsChanged(list)); |
| 223 if (check_created) { | 248 if (check_created) { |
| 224 store()->RemoveLoginsCreatedBetween(base::Time(), next_day, | 249 store()->RemoveLoginsCreatedBetween(base::Time(), next_day, |
| 225 base::Closure()); | 250 base::Closure()); |
| 226 } else { | 251 } else { |
| 227 store()->RemoveLoginsSyncedBetween(base::Time(), next_day); | 252 store()->RemoveLoginsSyncedBetween(base::Time(), next_day); |
| 228 } | 253 } |
| 229 FinishAsyncProcessing(); | 254 FinishAsyncProcessing(); |
| 230 } | 255 } |
| 231 | 256 |
| 232 TEST_F(PasswordStoreProxyMacTest, FormLifeCycle) { | 257 // ----------- Tests ------------- |
| 258 |
| 259 TEST_P(PasswordStoreProxyMacTest, StartAndStop) { |
| 260 // PasswordStore::Shutdown() immediately follows PasswordStore::Init(). The |
| 261 // message loop isn't running in between. Anyway, PasswordStore should end up |
| 262 // in the right state. |
| 263 ClosePasswordStore(); |
| 264 |
| 265 int status = testing_prefs_.GetInteger( |
| 266 password_manager::prefs::kKeychainMigrationStatus); |
| 267 if (GetParam() == MigrationStatus::NOT_STARTED || |
| 268 GetParam() == MigrationStatus::FAILED_ONCE) { |
| 269 EXPECT_EQ(static_cast<int>(MigrationStatus::MIGRATED), status); |
| 270 } else { |
| 271 EXPECT_EQ(static_cast<int>(GetParam()), status); |
| 272 } |
| 273 } |
| 274 |
| 275 TEST_P(PasswordStoreProxyMacTest, FormLifeCycle) { |
| 233 PasswordForm password_form; | 276 PasswordForm password_form; |
| 234 password_form.origin = GURL("http://example.com"); | 277 password_form.origin = GURL("http://example.com"); |
| 235 password_form.username_value = base::ASCIIToUTF16("test1@gmail.com"); | 278 password_form.username_value = base::ASCIIToUTF16("test1@gmail.com"); |
| 236 password_form.password_value = base::ASCIIToUTF16("12345"); | 279 password_form.password_value = base::ASCIIToUTF16("12345"); |
| 237 password_form.signon_realm = "http://example.com/"; | 280 password_form.signon_realm = "http://example.com/"; |
| 238 | 281 |
| 239 AddForm(password_form); | 282 AddForm(password_form); |
| 240 password_form.password_value = base::ASCIIToUTF16("password"); | 283 password_form.password_value = base::ASCIIToUTF16("password"); |
| 241 UpdateForm(password_form); | 284 UpdateForm(password_form); |
| 242 RemoveForm(password_form); | 285 RemoveForm(password_form); |
| 243 } | 286 } |
| 244 | 287 |
| 245 TEST_F(PasswordStoreProxyMacTest, TestRemoveLoginsCreatedBetween) { | 288 TEST_P(PasswordStoreProxyMacTest, TestRemoveLoginsCreatedBetween) { |
| 246 CheckRemoveLoginsBetween(true); | 289 CheckRemoveLoginsBetween(true); |
| 247 } | 290 } |
| 248 | 291 |
| 249 TEST_F(PasswordStoreProxyMacTest, TestRemoveLoginsSyncedBetween) { | 292 TEST_P(PasswordStoreProxyMacTest, TestRemoveLoginsSyncedBetween) { |
| 250 CheckRemoveLoginsBetween(false); | 293 CheckRemoveLoginsBetween(false); |
| 251 } | 294 } |
| 252 | 295 |
| 253 TEST_F(PasswordStoreProxyMacTest, FillLogins) { | 296 TEST_P(PasswordStoreProxyMacTest, FillLogins) { |
| 254 PasswordForm password_form; | 297 PasswordForm password_form; |
| 255 password_form.origin = GURL("http://example.com"); | 298 password_form.origin = GURL("http://example.com"); |
| 256 password_form.signon_realm = "http://example.com/"; | 299 password_form.signon_realm = "http://example.com/"; |
| 257 password_form.username_value = base::ASCIIToUTF16("test1@gmail.com"); | 300 password_form.username_value = base::ASCIIToUTF16("test1@gmail.com"); |
| 258 password_form.password_value = base::ASCIIToUTF16("12345"); | 301 password_form.password_value = base::ASCIIToUTF16("12345"); |
| 259 AddForm(password_form); | 302 AddForm(password_form); |
| 260 | 303 |
| 261 PasswordForm blacklisted_form; | 304 PasswordForm blacklisted_form; |
| 262 blacklisted_form.origin = GURL("http://example2.com"); | 305 blacklisted_form.origin = GURL("http://example2.com"); |
| 263 blacklisted_form.signon_realm = "http://example2.com/"; | 306 blacklisted_form.signon_realm = "http://example2.com/"; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 278 .WillOnce(QuitUIMessageLoop()); | 321 .WillOnce(QuitUIMessageLoop()); |
| 279 base::MessageLoop::current()->Run(); | 322 base::MessageLoop::current()->Run(); |
| 280 | 323 |
| 281 store()->GetAutofillableLogins(&mock_consumer); | 324 store()->GetAutofillableLogins(&mock_consumer); |
| 282 EXPECT_CALL(mock_consumer, OnGetPasswordStoreResultsConstRef( | 325 EXPECT_CALL(mock_consumer, OnGetPasswordStoreResultsConstRef( |
| 283 ElementsAre(Pointee(password_form)))) | 326 ElementsAre(Pointee(password_form)))) |
| 284 .WillOnce(QuitUIMessageLoop()); | 327 .WillOnce(QuitUIMessageLoop()); |
| 285 base::MessageLoop::current()->Run(); | 328 base::MessageLoop::current()->Run(); |
| 286 } | 329 } |
| 287 | 330 |
| 288 TEST_F(PasswordStoreProxyMacTest, OperationsOnABadDatabaseSilentlyFail) { | 331 TEST_P(PasswordStoreProxyMacTest, OperationsOnABadDatabaseSilentlyFail) { |
| 289 // Verify that operations on a PasswordStore with a bad database cause no | 332 // Verify that operations on a PasswordStore with a bad database cause no |
| 290 // explosions, but fail without side effect, return no data and trigger no | 333 // explosions, but fail without side effect, return no data and trigger no |
| 291 // notifications. | 334 // notifications. |
| 292 ClosePasswordStore(); | 335 ClosePasswordStore(); |
| 293 CreateAndInitPasswordStore(make_scoped_ptr(new BadLoginDatabase)); | 336 CreateAndInitPasswordStore(make_scoped_ptr(new BadLoginDatabase)); |
| 294 FinishAsyncProcessing(); | 337 FinishAsyncProcessing(); |
| 295 EXPECT_FALSE(login_db()); | 338 EXPECT_FALSE(login_db()); |
| 296 | 339 |
| 297 // The store should outlive the observer. | 340 // The store should outlive the observer. |
| 298 scoped_refptr<PasswordStoreProxyMac> store_refptr = store(); | 341 scoped_refptr<PasswordStoreProxyMac> store_refptr = store(); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 344 // Delete one login; a range of logins. | 387 // Delete one login; a range of logins. |
| 345 store()->RemoveLogin(*form); | 388 store()->RemoveLogin(*form); |
| 346 store()->RemoveLoginsCreatedBetween(base::Time(), base::Time::Max(), | 389 store()->RemoveLoginsCreatedBetween(base::Time(), base::Time::Max(), |
| 347 base::Closure()); | 390 base::Closure()); |
| 348 store()->RemoveLoginsSyncedBetween(base::Time(), base::Time::Max()); | 391 store()->RemoveLoginsSyncedBetween(base::Time(), base::Time::Max()); |
| 349 FinishAsyncProcessing(); | 392 FinishAsyncProcessing(); |
| 350 | 393 |
| 351 // Verify no notifications are fired during shutdown either. | 394 // Verify no notifications are fired during shutdown either. |
| 352 ClosePasswordStore(); | 395 ClosePasswordStore(); |
| 353 } | 396 } |
| 397 |
| 398 INSTANTIATE_TEST_CASE_P(, |
| 399 PasswordStoreProxyMacTest, |
| 400 testing::Values(MigrationStatus::NOT_STARTED, |
| 401 MigrationStatus::MIGRATED, |
| 402 MigrationStatus::FAILED_ONCE, |
| 403 MigrationStatus::FAILED_TWICE)); |
| 404 |
| 405 // Test the migration process. |
| 406 class PasswordStoreProxyMacMigrationTest : public PasswordStoreProxyMacTest { |
| 407 public: |
| 408 void SetUp() override; |
| 409 |
| 410 void TestMigration(bool lock_keychain); |
| 411 |
| 412 protected: |
| 413 scoped_ptr<password_manager::LoginDatabase> login_db_; |
| 414 scoped_ptr<crypto::MockAppleKeychain> keychain_; |
| 415 base::HistogramTester histogram_tester_; |
| 416 }; |
| 417 |
| 418 void PasswordStoreProxyMacMigrationTest::SetUp() { |
| 419 login_db_.reset( |
| 420 new password_manager::LoginDatabase(test_login_db_file_path())); |
| 421 keychain_.reset(new crypto::MockAppleKeychain); |
| 422 } |
| 423 |
| 424 void PasswordStoreProxyMacMigrationTest::TestMigration(bool lock_keychain) { |
| 425 PasswordForm form; |
| 426 form.origin = GURL("http://accounts.google.com/LoginAuth"); |
| 427 form.signon_realm = "http://accounts.google.com/"; |
| 428 form.username_value = base::ASCIIToUTF16("my_username"); |
| 429 form.password_value = base::ASCIIToUTF16("12345"); |
| 430 |
| 431 if (GetParam() != MigrationStatus::MIGRATED) |
| 432 login_db_->set_clear_password_values(true); |
| 433 EXPECT_TRUE(login_db_->Init()); |
| 434 EXPECT_EQ(AddChangeForForm(form), login_db_->AddLogin(form)); |
| 435 // Prepare another database instance with the same content which is to be |
| 436 // initialized by PasswordStoreProxyMac. |
| 437 login_db_.reset( |
| 438 new password_manager::LoginDatabase(test_login_db_file_path())); |
| 439 MacKeychainPasswordFormAdapter adapter(keychain_.get()); |
| 440 EXPECT_TRUE(adapter.AddPassword(form)); |
| 441 |
| 442 // Init the store. It may trigger the migration. |
| 443 if (lock_keychain) |
| 444 keychain_->set_locked(true); |
| 445 store_ = new PasswordStoreProxyMac( |
| 446 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), |
| 447 keychain_.Pass(), login_db_.Pass(), &testing_prefs_); |
| 448 ASSERT_TRUE(store_->Init(syncer::SyncableService::StartSyncFlare())); |
| 449 FinishAsyncProcessing(); |
| 450 |
| 451 // Check the password is still there. |
| 452 if (lock_keychain && store_->password_store_mac()) { |
| 453 static_cast<crypto::MockAppleKeychain*>( |
| 454 store_->password_store_mac()->keychain())->set_locked(false); |
| 455 } |
| 456 MockPasswordStoreConsumer mock_consumer; |
| 457 store()->GetLogins(form, PasswordStoreProxyMac::ALLOW_PROMPT, &mock_consumer); |
| 458 EXPECT_CALL(mock_consumer, |
| 459 OnGetPasswordStoreResultsConstRef(ElementsAre(Pointee(form)))) |
| 460 .WillOnce(QuitUIMessageLoop()); |
| 461 base::MessageLoop::current()->Run(); |
| 462 |
| 463 int status = testing_prefs_.GetInteger( |
| 464 password_manager::prefs::kKeychainMigrationStatus); |
| 465 if (GetParam() == MigrationStatus::MIGRATED || |
| 466 GetParam() == MigrationStatus::FAILED_TWICE) { |
| 467 EXPECT_EQ(static_cast<int>(GetParam()), status); |
| 468 } else if (lock_keychain) { |
| 469 EXPECT_EQ(static_cast<int>(GetParam() == MigrationStatus::NOT_STARTED |
| 470 ? MigrationStatus::FAILED_ONCE |
| 471 : MigrationStatus::FAILED_TWICE), |
| 472 status); |
| 473 } else { |
| 474 EXPECT_EQ(static_cast<int>(MigrationStatus::MIGRATED), status); |
| 475 } |
| 476 histogram_tester_.ExpectUniqueSample( |
| 477 "PasswordManager.KeychainMigration.Status", |
| 478 status, 1); |
| 479 } |
| 480 |
| 481 TEST_P(PasswordStoreProxyMacMigrationTest, TestSuccessfullMigration) { |
| 482 TestMigration(false); |
| 483 } |
| 484 |
| 485 TEST_P(PasswordStoreProxyMacMigrationTest, TestFailedMigration) { |
| 486 TestMigration(true); |
| 487 } |
| 488 |
| 489 INSTANTIATE_TEST_CASE_P(, |
| 490 PasswordStoreProxyMacMigrationTest, |
| 491 testing::Values(MigrationStatus::NOT_STARTED, |
| 492 MigrationStatus::MIGRATED, |
| 493 MigrationStatus::FAILED_ONCE, |
| 494 MigrationStatus::FAILED_TWICE)); |
| 495 |
| 354 } // namespace | 496 } // namespace |
| OLD | NEW |