Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(266)

Side by Side Diff: chrome/browser/password_manager/password_store_mac_unittest.cc

Issue 1207373002: Implement Mac Keychain migration algorithm. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/files/scoped_temp_dir.h" 8 #include "base/files/scoped_temp_dir.h"
9 #include "base/scoped_observer.h" 9 #include "base/scoped_observer.h"
10 #include "base/stl_util.h" 10 #include "base/stl_util.h"
(...skipping 1155 matching lines...) Expand 10 before | Expand all | Expand 10 after
1166 } 1166 }
1167 1167
1168 #pragma mark - 1168 #pragma mark -
1169 1169
1170 class PasswordStoreMacTest : public testing::Test { 1170 class PasswordStoreMacTest : public testing::Test {
1171 public: 1171 public:
1172 PasswordStoreMacTest() : ui_thread_(BrowserThread::UI, &message_loop_) {} 1172 PasswordStoreMacTest() : ui_thread_(BrowserThread::UI, &message_loop_) {}
1173 1173
1174 void SetUp() override { 1174 void SetUp() override {
1175 ASSERT_TRUE(db_dir_.CreateUniqueTempDir()); 1175 ASSERT_TRUE(db_dir_.CreateUniqueTempDir());
1176 histogram_tester_.reset(new base::HistogramTester);
1176 1177
1177 // Ensure that LoginDatabase will use the mock keychain if it needs to 1178 // Ensure that LoginDatabase will use the mock keychain if it needs to
1178 // encrypt/decrypt a password. 1179 // encrypt/decrypt a password.
1179 OSCrypt::UseMockKeychain(true); 1180 OSCrypt::UseMockKeychain(true);
1180 login_db_.reset( 1181 login_db_.reset(
1181 new password_manager::LoginDatabase(test_login_db_file_path())); 1182 new password_manager::LoginDatabase(test_login_db_file_path()));
1182 thread_.reset(new base::Thread("Chrome_PasswordStore_Thread")); 1183 thread_.reset(new base::Thread("Chrome_PasswordStore_Thread"));
1183 ASSERT_TRUE(thread_->Start()); 1184 ASSERT_TRUE(thread_->Start());
1184 ASSERT_TRUE(thread_->task_runner()->PostTask( 1185 ASSERT_TRUE(thread_->task_runner()->PostTask(
1185 FROM_HERE, base::Bind(&PasswordStoreMacTest::InitLoginDatabase, 1186 FROM_HERE, base::Bind(&PasswordStoreMacTest::InitLoginDatabase,
1186 base::Unretained(login_db_.get())))); 1187 base::Unretained(login_db_.get()))));
1187 CreateAndInitPasswordStore(login_db_.get()); 1188 CreateAndInitPasswordStore(login_db_.get());
1188 // Make sure deferred initialization is performed before some tests start 1189 // Make sure deferred initialization is performed before some tests start
1189 // accessing the |login_db| directly. 1190 // accessing the |login_db| directly.
1190 FinishAsyncProcessing(); 1191 FinishAsyncProcessing();
1191 } 1192 }
1192 1193
1193 void TearDown() override { 1194 void TearDown() override {
1194 ClosePasswordStore(); 1195 ClosePasswordStore();
1195 thread_.reset(); 1196 thread_.reset();
1196 login_db_.reset(); 1197 login_db_.reset();
1198 crypto::MockAppleKeychain::set_locked(false);
1197 // Whatever a test did, PasswordStoreMac stores only empty password values 1199 // Whatever a test did, PasswordStoreMac stores only empty password values
1198 // in LoginDatabase. The empty valus do not require encryption and therefore 1200 // in LoginDatabase. The empty valus do not require encryption and therefore
1199 // OSCrypt shouldn't call the Keychain. The histogram doesn't cover the 1201 // OSCrypt shouldn't call the Keychain. The histogram doesn't cover the
1200 // internet passwords. 1202 // internet passwords.
1201 EXPECT_FALSE(histogram_tester_.GetHistogramSamplesSinceCreation( 1203 if (histogram_tester_) {
1202 "OSX.Keychain.Access")); 1204 scoped_ptr<base::HistogramSamples> samples =
1205 histogram_tester_->GetHistogramSamplesSinceCreation(
1206 "OSX.Keychain.Access");
1207 EXPECT_TRUE(!samples || samples->TotalCount() == 0);
1208 }
1203 } 1209 }
1204 1210
1205 static void InitLoginDatabase(password_manager::LoginDatabase* login_db) { 1211 static void InitLoginDatabase(password_manager::LoginDatabase* login_db) {
1206 ASSERT_TRUE(login_db->Init()); 1212 ASSERT_TRUE(login_db->Init());
1207 } 1213 }
1208 1214
1209 void CreateAndInitPasswordStore(password_manager::LoginDatabase* login_db) { 1215 void CreateAndInitPasswordStore(password_manager::LoginDatabase* login_db) {
1210 store_ = new PasswordStoreMac( 1216 store_ = new PasswordStoreMac(
1211 base::ThreadTaskRunnerHandle::Get(), nullptr, 1217 base::ThreadTaskRunnerHandle::Get(), nullptr,
1212 make_scoped_ptr<AppleKeychain>(new MockAppleKeychain), login_db); 1218 make_scoped_ptr<AppleKeychain>(new MockAppleKeychain), login_db);
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1297 1303
1298 protected: 1304 protected:
1299 base::MessageLoopForUI message_loop_; 1305 base::MessageLoopForUI message_loop_;
1300 content::TestBrowserThread ui_thread_; 1306 content::TestBrowserThread ui_thread_;
1301 // Thread that the synchronous methods are run on. 1307 // Thread that the synchronous methods are run on.
1302 scoped_ptr<base::Thread> thread_; 1308 scoped_ptr<base::Thread> thread_;
1303 1309
1304 base::ScopedTempDir db_dir_; 1310 base::ScopedTempDir db_dir_;
1305 scoped_ptr<password_manager::LoginDatabase> login_db_; 1311 scoped_ptr<password_manager::LoginDatabase> login_db_;
1306 scoped_refptr<PasswordStoreMac> store_; 1312 scoped_refptr<PasswordStoreMac> store_;
1307 base::HistogramTester histogram_tester_; 1313 scoped_ptr<base::HistogramTester> histogram_tester_;
1308 }; 1314 };
1309 1315
1310 TEST_F(PasswordStoreMacTest, TestStoreUpdate) { 1316 TEST_F(PasswordStoreMacTest, TestStoreUpdate) {
1311 // Insert a password into both the database and the keychain. 1317 // Insert a password into both the database and the keychain.
1312 // This is done manually, rather than through store_->AddLogin, because the 1318 // This is done manually, rather than through store_->AddLogin, because the
1313 // Mock Keychain isn't smart enough to be able to support update generically, 1319 // Mock Keychain isn't smart enough to be able to support update generically,
1314 // so some.domain.com triggers special handling to test it that make inserting 1320 // so some.domain.com triggers special handling to test it that make inserting
1315 // fail. 1321 // fail.
1316 PasswordFormData joint_data = { 1322 PasswordFormData joint_data = {
1317 PasswordForm::SCHEME_HTML, "http://some.domain.com/", 1323 PasswordForm::SCHEME_HTML, "http://some.domain.com/",
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after
1751 // Verify that federated credentials can be stored, retrieved and deleted. 1757 // Verify that federated credentials can be stored, retrieved and deleted.
1752 TEST_F(PasswordStoreMacTest, StoringAndRetrievingFederatedCredentials) { 1758 TEST_F(PasswordStoreMacTest, StoringAndRetrievingFederatedCredentials) {
1753 PasswordForm form; 1759 PasswordForm form;
1754 form.signon_realm = "android://7x7IDboo8u9YKraUsbmVkuf1@net.rateflix.app/"; 1760 form.signon_realm = "android://7x7IDboo8u9YKraUsbmVkuf1@net.rateflix.app/";
1755 form.federation_url = GURL(password_manager::kTestingFederationUrlSpec); 1761 form.federation_url = GURL(password_manager::kTestingFederationUrlSpec);
1756 form.username_value = base::UTF8ToUTF16("randomusername"); 1762 form.username_value = base::UTF8ToUTF16("randomusername");
1757 form.password_value = base::UTF8ToUTF16(""); // No password. 1763 form.password_value = base::UTF8ToUTF16(""); // No password.
1758 1764
1759 VerifyCredentialLifecycle(form); 1765 VerifyCredentialLifecycle(form);
1760 } 1766 }
1767
1768 void CheckMigrationResult(PasswordStoreMac::MigrationResult expected_result,
1769 PasswordStoreMac::MigrationResult result) {
1770 EXPECT_EQ(expected_result, result);
1771 QuitUIMessageLoop();
1772 }
1773
1774 // Import the passwords from the Keychain to LoginDatabase.
1775 TEST_F(PasswordStoreMacTest, ImportFromKeychain) {
1776 PasswordForm form1;
1777 form1.origin = GURL("http://accounts.google.com/LoginAuth");
1778 form1.signon_realm = "http://accounts.google.com/";
1779 form1.username_value = ASCIIToUTF16("my_username");
1780 form1.password_value = ASCIIToUTF16("my_password");
1781
1782 PasswordForm form2;
1783 form2.origin = GURL("http://facebook.com/Login");
1784 form2.signon_realm = "http://facebook.com/";
1785 form2.username_value = ASCIIToUTF16("my_username");
1786 form2.password_value = ASCIIToUTF16("my_password");
1787
1788 PasswordForm blacklisted_form;
1789 blacklisted_form.origin = GURL("http://badsite.com/Login");
1790 blacklisted_form.signon_realm = "http://badsite.com/";
1791 blacklisted_form.blacklisted_by_user = true;
1792
1793 store()->AddLogin(form1);
1794 store()->AddLogin(form2);
1795 store()->AddLogin(blacklisted_form);
1796 FinishAsyncProcessing();
1797
1798 ASSERT_TRUE(base::PostTaskAndReplyWithResult(
1799 thread_->task_runner().get(), FROM_HERE,
1800 base::Bind(&PasswordStoreMac::ImportFromKeychain, store()),
1801 base::Bind(&CheckMigrationResult, PasswordStoreMac::MIGRATION_OK)));
1802 FinishAsyncProcessing();
1803
1804 // The password should be stored in the database by now.
1805 ScopedVector<PasswordForm> matching_items;
1806 EXPECT_TRUE(login_db()->GetLogins(form1, &matching_items));
1807 ASSERT_EQ(1u, matching_items.size());
1808 EXPECT_EQ(form1, *matching_items[0]);
1809
1810 EXPECT_TRUE(login_db()->GetLogins(form2, &matching_items));
1811 ASSERT_EQ(1u, matching_items.size());
1812 EXPECT_EQ(form2, *matching_items[0]);
1813
1814 EXPECT_TRUE(login_db()->GetLogins(blacklisted_form, &matching_items));
1815 ASSERT_EQ(1u, matching_items.size());
1816 EXPECT_EQ(blacklisted_form, *matching_items[0]);
1817
1818 // The passwords are encrypted using a key from the Keychain.
1819 EXPECT_TRUE(histogram_tester_->GetHistogramSamplesSinceCreation(
1820 "OSX.Keychain.Access")->TotalCount());
1821 histogram_tester_.reset();
1822 }
1823
1824 // Import a federated credential while the Keychain is locked.
1825 TEST_F(PasswordStoreMacTest, ImportFederatedFromLockedKeychain) {
1826 crypto::MockAppleKeychain::set_locked(true);
1827 PasswordForm form1;
1828 form1.origin = GURL("http://example.com/Login");
1829 form1.signon_realm = "http://example.com/";
1830 form1.username_value = ASCIIToUTF16("my_username");
1831 form1.federation_url = GURL("https://accounts.google.com/");
1832
1833 store()->AddLogin(form1);
1834 FinishAsyncProcessing();
1835 ASSERT_TRUE(base::PostTaskAndReplyWithResult(
1836 thread_->task_runner().get(), FROM_HERE,
1837 base::Bind(&PasswordStoreMac::ImportFromKeychain, store()),
1838 base::Bind(&CheckMigrationResult, PasswordStoreMac::MIGRATION_OK)));
1839 FinishAsyncProcessing();
1840
1841 ScopedVector<PasswordForm> matching_items;
1842 EXPECT_TRUE(login_db()->GetLogins(form1, &matching_items));
1843 ASSERT_EQ(1u, matching_items.size());
1844 EXPECT_EQ(form1, *matching_items[0]);
1845 }
1846
1847 // Try to import while the Keychain is locked but the encryption key had been
1848 // read earlier.
1849 TEST_F(PasswordStoreMacTest, ImportFromLockedKeychainError) {
1850 PasswordForm form1;
1851 form1.origin = GURL("http://accounts.google.com/LoginAuth");
1852 form1.signon_realm = "http://accounts.google.com/";
1853 form1.username_value = ASCIIToUTF16("my_username");
1854 form1.password_value = ASCIIToUTF16("my_password");
1855
1856 store()->AddLogin(form1);
1857 FinishAsyncProcessing();
1858 crypto::MockAppleKeychain::set_locked(true);
1859 ASSERT_TRUE(base::PostTaskAndReplyWithResult(
1860 thread_->task_runner().get(), FROM_HERE,
1861 base::Bind(&PasswordStoreMac::ImportFromKeychain, store()),
1862 base::Bind(&CheckMigrationResult, PasswordStoreMac::KEYCHAIN_BLOCKED)));
1863 FinishAsyncProcessing();
1864
1865 ScopedVector<PasswordForm> matching_items;
1866 EXPECT_TRUE(login_db()->GetLogins(form1, &matching_items));
1867 ASSERT_EQ(1u, matching_items.size());
1868 EXPECT_EQ(base::string16(), matching_items[0]->password_value);
1869
1870 histogram_tester_->ExpectUniqueSample(
1871 "PasswordManager.KeychainMigration.NumPasswords", 1, 1);
1872 histogram_tester_->ExpectUniqueSample(
1873 "PasswordManager.KeychainMigration.NumLockedPasswords", 1, 1);
1874 histogram_tester_->ExpectUniqueSample(
1875 "PasswordManager.KeychainMigration.NumChromeOwnedLockedPasswords", 1, 1);
1876 // Don't test the encryption key access.
1877 histogram_tester_.reset();
1878 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698