| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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_mac.h" | 5 #include "chrome/browser/password_manager/password_store_mac.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <string> | 9 #include <string> |
| 10 | 10 |
| 11 #include "base/files/scoped_temp_dir.h" | 11 #include "base/files/scoped_temp_dir.h" |
| 12 #include "base/macros.h" | 12 #include "base/macros.h" |
| 13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 14 #include "base/run_loop.h" |
| 14 #include "base/scoped_observer.h" | 15 #include "base/scoped_observer.h" |
| 15 #include "base/stl_util.h" | 16 #include "base/stl_util.h" |
| 16 #include "base/strings/string_util.h" | 17 #include "base/strings/string_util.h" |
| 17 #include "base/strings/utf_string_conversions.h" | 18 #include "base/strings/utf_string_conversions.h" |
| 18 #include "base/synchronization/waitable_event.h" | 19 #include "base/synchronization/waitable_event.h" |
| 19 #include "base/test/histogram_tester.h" | 20 #include "base/test/histogram_tester.h" |
| 20 #include "base/threading/thread_task_runner_handle.h" | 21 #include "base/threading/thread_task_runner_handle.h" |
| 21 #include "chrome/browser/password_manager/password_store_mac_internal.h" | 22 #include "chrome/browser/password_manager/password_store_mac_internal.h" |
| 22 #include "chrome/common/chrome_paths.h" | 23 #include "chrome/common/chrome_paths.h" |
| 23 #include "components/os_crypt/os_crypt_mocker.h" | 24 #include "components/os_crypt/os_crypt_mocker.h" |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 | 201 |
| 201 PasswordStoreMacTestDelegate::PasswordStoreMacTestDelegate() { | 202 PasswordStoreMacTestDelegate::PasswordStoreMacTestDelegate() { |
| 202 Initialize(); | 203 Initialize(); |
| 203 } | 204 } |
| 204 | 205 |
| 205 PasswordStoreMacTestDelegate::~PasswordStoreMacTestDelegate() { | 206 PasswordStoreMacTestDelegate::~PasswordStoreMacTestDelegate() { |
| 206 ClosePasswordStore(); | 207 ClosePasswordStore(); |
| 207 } | 208 } |
| 208 | 209 |
| 209 void PasswordStoreMacTestDelegate::FinishAsyncProcessing() { | 210 void PasswordStoreMacTestDelegate::FinishAsyncProcessing() { |
| 210 base::MessageLoop::current()->RunUntilIdle(); | 211 base::RunLoop().RunUntilIdle(); |
| 211 } | 212 } |
| 212 | 213 |
| 213 void PasswordStoreMacTestDelegate::Initialize() { | 214 void PasswordStoreMacTestDelegate::Initialize() { |
| 214 ASSERT_TRUE(db_dir_.CreateUniqueTempDir()); | 215 ASSERT_TRUE(db_dir_.CreateUniqueTempDir()); |
| 215 | 216 |
| 216 // Ensure that LoginDatabase will use the mock keychain if it needs to | 217 // Ensure that LoginDatabase will use the mock keychain if it needs to |
| 217 // encrypt/decrypt a password. | 218 // encrypt/decrypt a password. |
| 218 OSCryptMocker::SetUpWithSingleton(); | 219 OSCryptMocker::SetUpWithSingleton(); |
| 219 login_db_.reset(new LoginDatabase(test_login_db_file_path())); | 220 login_db_.reset(new LoginDatabase(test_login_db_file_path())); |
| 220 ASSERT_TRUE(login_db_->Init()); | 221 ASSERT_TRUE(login_db_->Init()); |
| (...skipping 1093 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1314 void VerifyCredentialLifecycle(const PasswordForm& form) { | 1315 void VerifyCredentialLifecycle(const PasswordForm& form) { |
| 1315 // Run everything twice to make sure no garbage is left behind that would | 1316 // Run everything twice to make sure no garbage is left behind that would |
| 1316 // prevent storing the form a second time. | 1317 // prevent storing the form a second time. |
| 1317 for (size_t iteration = 0; iteration < 2; ++iteration) { | 1318 for (size_t iteration = 0; iteration < 2; ++iteration) { |
| 1318 SCOPED_TRACE(testing::Message("Iteration: ") << iteration); | 1319 SCOPED_TRACE(testing::Message("Iteration: ") << iteration); |
| 1319 | 1320 |
| 1320 MockPasswordStoreConsumer mock_consumer; | 1321 MockPasswordStoreConsumer mock_consumer; |
| 1321 EXPECT_CALL(mock_consumer, OnGetPasswordStoreResultsConstRef(IsEmpty())) | 1322 EXPECT_CALL(mock_consumer, OnGetPasswordStoreResultsConstRef(IsEmpty())) |
| 1322 .WillOnce(QuitUIMessageLoop()); | 1323 .WillOnce(QuitUIMessageLoop()); |
| 1323 store()->GetAutofillableLogins(&mock_consumer); | 1324 store()->GetAutofillableLogins(&mock_consumer); |
| 1324 base::MessageLoop::current()->Run(); | 1325 base::RunLoop().Run(); |
| 1325 ::testing::Mock::VerifyAndClearExpectations(&mock_consumer); | 1326 ::testing::Mock::VerifyAndClearExpectations(&mock_consumer); |
| 1326 | 1327 |
| 1327 store()->AddLogin(form); | 1328 store()->AddLogin(form); |
| 1328 FinishAsyncProcessing(); | 1329 FinishAsyncProcessing(); |
| 1329 | 1330 |
| 1330 PasswordForm returned_form; | 1331 PasswordForm returned_form; |
| 1331 EXPECT_CALL(mock_consumer, OnGetPasswordStoreResultsConstRef(SizeIs(1u))) | 1332 EXPECT_CALL(mock_consumer, OnGetPasswordStoreResultsConstRef(SizeIs(1u))) |
| 1332 .WillOnce( | 1333 .WillOnce( |
| 1333 DoAll(SaveACopyOfFirstForm(&returned_form), QuitUIMessageLoop())); | 1334 DoAll(SaveACopyOfFirstForm(&returned_form), QuitUIMessageLoop())); |
| 1334 | 1335 |
| 1335 // The query operations will also do some housekeeping: they will remove | 1336 // The query operations will also do some housekeeping: they will remove |
| 1336 // dangling credentials in the LoginDatabase without a matching Keychain | 1337 // dangling credentials in the LoginDatabase without a matching Keychain |
| 1337 // item when one is expected. If the logic that stores the Keychain item | 1338 // item when one is expected. If the logic that stores the Keychain item |
| 1338 // is incorrect, this will wipe the newly added form before the second | 1339 // is incorrect, this will wipe the newly added form before the second |
| 1339 // query. | 1340 // query. |
| 1340 store()->GetAutofillableLogins(&mock_consumer); | 1341 store()->GetAutofillableLogins(&mock_consumer); |
| 1341 base::MessageLoop::current()->Run(); | 1342 base::RunLoop().Run(); |
| 1342 ::testing::Mock::VerifyAndClearExpectations(&mock_consumer); | 1343 ::testing::Mock::VerifyAndClearExpectations(&mock_consumer); |
| 1343 EXPECT_EQ(form, returned_form); | 1344 EXPECT_EQ(form, returned_form); |
| 1344 | 1345 |
| 1345 PasswordForm query_form = form; | 1346 PasswordForm query_form = form; |
| 1346 query_form.password_value.clear(); | 1347 query_form.password_value.clear(); |
| 1347 query_form.username_value.clear(); | 1348 query_form.username_value.clear(); |
| 1348 EXPECT_CALL(mock_consumer, OnGetPasswordStoreResultsConstRef(SizeIs(1u))) | 1349 EXPECT_CALL(mock_consumer, OnGetPasswordStoreResultsConstRef(SizeIs(1u))) |
| 1349 .WillOnce( | 1350 .WillOnce( |
| 1350 DoAll(SaveACopyOfFirstForm(&returned_form), QuitUIMessageLoop())); | 1351 DoAll(SaveACopyOfFirstForm(&returned_form), QuitUIMessageLoop())); |
| 1351 store()->GetLogins(query_form, &mock_consumer); | 1352 store()->GetLogins(query_form, &mock_consumer); |
| 1352 base::MessageLoop::current()->Run(); | 1353 base::RunLoop().Run(); |
| 1353 ::testing::Mock::VerifyAndClearExpectations(&mock_consumer); | 1354 ::testing::Mock::VerifyAndClearExpectations(&mock_consumer); |
| 1354 EXPECT_EQ(form, returned_form); | 1355 EXPECT_EQ(form, returned_form); |
| 1355 | 1356 |
| 1356 store()->RemoveLogin(form); | 1357 store()->RemoveLogin(form); |
| 1357 } | 1358 } |
| 1358 } | 1359 } |
| 1359 | 1360 |
| 1360 base::FilePath test_login_db_file_path() const { | 1361 base::FilePath test_login_db_file_path() const { |
| 1361 return db_dir_.path().Append(FILE_PATH_LITERAL("login.db")); | 1362 return db_dir_.path().Append(FILE_PATH_LITERAL("login.db")); |
| 1362 } | 1363 } |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1515 PasswordForm m_form(*www_form); | 1516 PasswordForm m_form(*www_form); |
| 1516 m_form.signon_realm = "http://m.facebook.com"; | 1517 m_form.signon_realm = "http://m.facebook.com"; |
| 1517 m_form.origin = GURL("http://m.facebook.com/index.html"); | 1518 m_form.origin = GURL("http://m.facebook.com/index.html"); |
| 1518 | 1519 |
| 1519 MockPasswordStoreConsumer consumer; | 1520 MockPasswordStoreConsumer consumer; |
| 1520 store_->GetLogins(m_form, &consumer); | 1521 store_->GetLogins(m_form, &consumer); |
| 1521 PasswordForm returned_form; | 1522 PasswordForm returned_form; |
| 1522 EXPECT_CALL(consumer, OnGetPasswordStoreResultsConstRef(SizeIs(1u))) | 1523 EXPECT_CALL(consumer, OnGetPasswordStoreResultsConstRef(SizeIs(1u))) |
| 1523 .WillOnce( | 1524 .WillOnce( |
| 1524 DoAll(SaveACopyOfFirstForm(&returned_form), QuitUIMessageLoop())); | 1525 DoAll(SaveACopyOfFirstForm(&returned_form), QuitUIMessageLoop())); |
| 1525 base::MessageLoop::current()->Run(); | 1526 base::RunLoop().Run(); |
| 1526 | 1527 |
| 1527 // 3. Add the returned password for m.facebook.com. | 1528 // 3. Add the returned password for m.facebook.com. |
| 1528 returned_form.signon_realm = "http://m.facebook.com"; | 1529 returned_form.signon_realm = "http://m.facebook.com"; |
| 1529 returned_form.origin = GURL("http://m.facebook.com/index.html"); | 1530 returned_form.origin = GURL("http://m.facebook.com/index.html"); |
| 1530 EXPECT_EQ(AddChangeForForm(returned_form), | 1531 EXPECT_EQ(AddChangeForForm(returned_form), |
| 1531 login_db()->AddLogin(returned_form)); | 1532 login_db()->AddLogin(returned_form)); |
| 1532 owned_keychain_adapter.AddPassword(m_form); | 1533 owned_keychain_adapter.AddPassword(m_form); |
| 1533 | 1534 |
| 1534 // 4. Remove both passwords. | 1535 // 4. Remove both passwords. |
| 1535 store_->RemoveLogin(*www_form); | 1536 store_->RemoveLogin(*www_form); |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1805 m_form.origin = GURL("http://m.facebook.com/index.html"); | 1806 m_form.origin = GURL("http://m.facebook.com/index.html"); |
| 1806 | 1807 |
| 1807 MockPasswordStoreConsumer consumer; | 1808 MockPasswordStoreConsumer consumer; |
| 1808 ON_CALL(consumer, OnGetPasswordStoreResultsConstRef(_)) | 1809 ON_CALL(consumer, OnGetPasswordStoreResultsConstRef(_)) |
| 1809 .WillByDefault(QuitUIMessageLoop()); | 1810 .WillByDefault(QuitUIMessageLoop()); |
| 1810 EXPECT_CALL(mock_observer, OnLoginsChanged(_)).Times(0); | 1811 EXPECT_CALL(mock_observer, OnLoginsChanged(_)).Times(0); |
| 1811 // The PSL-matched form isn't returned because there is no actual password in | 1812 // The PSL-matched form isn't returned because there is no actual password in |
| 1812 // the keychain. | 1813 // the keychain. |
| 1813 EXPECT_CALL(consumer, OnGetPasswordStoreResultsConstRef(IsEmpty())); | 1814 EXPECT_CALL(consumer, OnGetPasswordStoreResultsConstRef(IsEmpty())); |
| 1814 store_->GetLogins(m_form, &consumer); | 1815 store_->GetLogins(m_form, &consumer); |
| 1815 base::MessageLoop::current()->Run(); | 1816 base::RunLoop().Run(); |
| 1816 ScopedVector<autofill::PasswordForm> all_forms; | 1817 ScopedVector<autofill::PasswordForm> all_forms; |
| 1817 EXPECT_TRUE(login_db()->GetAutofillableLogins(&all_forms)); | 1818 EXPECT_TRUE(login_db()->GetAutofillableLogins(&all_forms)); |
| 1818 EXPECT_EQ(1u, all_forms.size()); | 1819 EXPECT_EQ(1u, all_forms.size()); |
| 1819 ::testing::Mock::VerifyAndClearExpectations(&mock_observer); | 1820 ::testing::Mock::VerifyAndClearExpectations(&mock_observer); |
| 1820 | 1821 |
| 1821 // 3. Get a password for www.facebook.com. The form is implicitly removed and | 1822 // 3. Get a password for www.facebook.com. The form is implicitly removed and |
| 1822 // the observer is notified. | 1823 // the observer is notified. |
| 1823 password_manager::PasswordStoreChangeList list; | 1824 password_manager::PasswordStoreChangeList list; |
| 1824 list.push_back(password_manager::PasswordStoreChange( | 1825 list.push_back(password_manager::PasswordStoreChange( |
| 1825 password_manager::PasswordStoreChange::REMOVE, *www_form)); | 1826 password_manager::PasswordStoreChange::REMOVE, *www_form)); |
| 1826 EXPECT_CALL(mock_observer, OnLoginsChanged(list)); | 1827 EXPECT_CALL(mock_observer, OnLoginsChanged(list)); |
| 1827 EXPECT_CALL(consumer, OnGetPasswordStoreResultsConstRef(IsEmpty())); | 1828 EXPECT_CALL(consumer, OnGetPasswordStoreResultsConstRef(IsEmpty())); |
| 1828 store_->GetLogins(*www_form, &consumer); | 1829 store_->GetLogins(*www_form, &consumer); |
| 1829 base::MessageLoop::current()->Run(); | 1830 base::RunLoop().Run(); |
| 1830 EXPECT_TRUE(login_db()->GetAutofillableLogins(&all_forms)); | 1831 EXPECT_TRUE(login_db()->GetAutofillableLogins(&all_forms)); |
| 1831 EXPECT_EQ(0u, all_forms.size()); | 1832 EXPECT_EQ(0u, all_forms.size()); |
| 1832 } | 1833 } |
| 1833 | 1834 |
| 1834 // Verify that Android app passwords can be stored, retrieved, and deleted. | 1835 // Verify that Android app passwords can be stored, retrieved, and deleted. |
| 1835 // Regression test for http://crbug.com/455551 | 1836 // Regression test for http://crbug.com/455551 |
| 1836 TEST_F(PasswordStoreMacTest, StoringAndRetrievingAndroidCredentials) { | 1837 TEST_F(PasswordStoreMacTest, StoringAndRetrievingAndroidCredentials) { |
| 1837 PasswordForm form; | 1838 PasswordForm form; |
| 1838 form.signon_realm = "android://7x7IDboo8u9YKraUsbmVkuf1@net.rateflix.app/"; | 1839 form.signon_realm = "android://7x7IDboo8u9YKraUsbmVkuf1@net.rateflix.app/"; |
| 1839 form.username_value = base::UTF8ToUTF16("randomusername"); | 1840 form.username_value = base::UTF8ToUTF16("randomusername"); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1966 histogram_tester_->ExpectUniqueSample( | 1967 histogram_tester_->ExpectUniqueSample( |
| 1967 "PasswordManager.KeychainMigration.NumPasswordsOnFailure", 1, 1); | 1968 "PasswordManager.KeychainMigration.NumPasswordsOnFailure", 1, 1); |
| 1968 histogram_tester_->ExpectUniqueSample( | 1969 histogram_tester_->ExpectUniqueSample( |
| 1969 "PasswordManager.KeychainMigration.NumFailedPasswords", 1, 1); | 1970 "PasswordManager.KeychainMigration.NumFailedPasswords", 1, 1); |
| 1970 histogram_tester_->ExpectUniqueSample( | 1971 histogram_tester_->ExpectUniqueSample( |
| 1971 "PasswordManager.KeychainMigration.NumChromeOwnedInaccessiblePasswords", | 1972 "PasswordManager.KeychainMigration.NumChromeOwnedInaccessiblePasswords", |
| 1972 2, 1); | 1973 2, 1); |
| 1973 // Don't test the encryption key access. | 1974 // Don't test the encryption key access. |
| 1974 histogram_tester_.reset(); | 1975 histogram_tester_.reset(); |
| 1975 } | 1976 } |
| OLD | NEW |