| 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 "testing/gmock/include/gmock/gmock.h" | 5 #include "testing/gmock/include/gmock/gmock.h" |
| 6 #include "testing/gtest/include/gtest/gtest.h" | 6 #include "testing/gtest/include/gtest/gtest.h" |
| 7 | 7 |
| 8 #include "base/basictypes.h" | 8 #include "base/basictypes.h" |
| 9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
| 10 #include "base/path_service.h" | 10 #include "base/path_service.h" |
| 11 #include "base/scoped_temp_dir.h" | 11 #include "base/scoped_temp_dir.h" |
| 12 #include "base/stl_util.h" | 12 #include "base/stl_util.h" |
| 13 #include "base/string_util.h" | 13 #include "base/string_util.h" |
| 14 #include "base/utf_string_conversions.h" | 14 #include "base/utf_string_conversions.h" |
| 15 #include "chrome/browser/password_manager/password_store_consumer.h" | 15 #include "chrome/browser/password_manager/password_store_consumer.h" |
| 16 #include "chrome/browser/password_manager/password_store_mac.h" | 16 #include "chrome/browser/password_manager/password_store_mac.h" |
| 17 #include "chrome/browser/password_manager/password_store_mac_internal.h" | 17 #include "chrome/browser/password_manager/password_store_mac_internal.h" |
| 18 #include "chrome/common/chrome_paths.h" | 18 #include "chrome/common/chrome_paths.h" |
| 19 #include "content/public/test/test_browser_thread.h" | 19 #include "content/public/test/test_browser_thread.h" |
| 20 #include "crypto/mock_keychain_mac.h" | 20 #include "crypto/mock_apple_keychain.h" |
| 21 | 21 |
| 22 using content::BrowserThread; | 22 using content::BrowserThread; |
| 23 using crypto::MockKeychain; | 23 using crypto::MockAppleKeychain; |
| 24 using webkit::forms::PasswordForm; | 24 using webkit::forms::PasswordForm; |
| 25 using testing::_; | 25 using testing::_; |
| 26 using testing::DoAll; | 26 using testing::DoAll; |
| 27 using testing::WithArg; | 27 using testing::WithArg; |
| 28 | 28 |
| 29 namespace { | 29 namespace { |
| 30 | 30 |
| 31 class MockPasswordStoreConsumer : public PasswordStoreConsumer { | 31 class MockPasswordStoreConsumer : public PasswordStoreConsumer { |
| 32 public: | 32 public: |
| 33 MOCK_METHOD2(OnPasswordStoreRequestDone, | 33 MOCK_METHOD2(OnPasswordStoreRequestDone, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 44 MessageLoop::current()->Quit(); | 44 MessageLoop::current()->Quit(); |
| 45 } | 45 } |
| 46 | 46 |
| 47 } // namespace | 47 } // namespace |
| 48 | 48 |
| 49 #pragma mark - | 49 #pragma mark - |
| 50 | 50 |
| 51 class PasswordStoreMacInternalsTest : public testing::Test { | 51 class PasswordStoreMacInternalsTest : public testing::Test { |
| 52 public: | 52 public: |
| 53 virtual void SetUp() { | 53 virtual void SetUp() { |
| 54 MockKeychain::KeychainTestData test_data[] = { | 54 MockAppleKeychain::KeychainTestData test_data[] = { |
| 55 // Basic HTML form. | 55 // Basic HTML form. |
| 56 { kSecAuthenticationTypeHTMLForm, "some.domain.com", | 56 { kSecAuthenticationTypeHTMLForm, "some.domain.com", |
| 57 kSecProtocolTypeHTTP, NULL, 0, NULL, "20020601171500Z", | 57 kSecProtocolTypeHTTP, NULL, 0, NULL, "20020601171500Z", |
| 58 "joe_user", "sekrit", false }, | 58 "joe_user", "sekrit", false }, |
| 59 // HTML form with path. | 59 // HTML form with path. |
| 60 { kSecAuthenticationTypeHTMLForm, "some.domain.com", | 60 { kSecAuthenticationTypeHTMLForm, "some.domain.com", |
| 61 kSecProtocolTypeHTTP, "/insecure.html", 0, NULL, "19991231235959Z", | 61 kSecProtocolTypeHTTP, "/insecure.html", 0, NULL, "19991231235959Z", |
| 62 "joe_user", "sekrit", false }, | 62 "joe_user", "sekrit", false }, |
| 63 // Secure HTML form with path. | 63 // Secure HTML form with path. |
| 64 { kSecAuthenticationTypeHTMLForm, "some.domain.com", | 64 { kSecAuthenticationTypeHTMLForm, "some.domain.com", |
| (...skipping 19 matching lines...) Expand all Loading... |
| 84 // HTTP auth digest, secure. | 84 // HTTP auth digest, secure. |
| 85 { kSecAuthenticationTypeHTTPDigest, "some.domain.com", | 85 { kSecAuthenticationTypeHTTPDigest, "some.domain.com", |
| 86 kSecProtocolTypeHTTPS, NULL, 0, "high_security", "19980330100000Z", | 86 kSecProtocolTypeHTTPS, NULL, 0, "high_security", "19980330100000Z", |
| 87 "digest_auth_user", "digest", false }, | 87 "digest_auth_user", "digest", false }, |
| 88 // An FTP password with an invalid date, for edge-case testing. | 88 // An FTP password with an invalid date, for edge-case testing. |
| 89 { kSecAuthenticationTypeDefault, "a.server.com", | 89 { kSecAuthenticationTypeDefault, "a.server.com", |
| 90 kSecProtocolTypeFTP, NULL, 0, NULL, "20010203040", | 90 kSecProtocolTypeFTP, NULL, 0, NULL, "20010203040", |
| 91 "abc", "123", false }, | 91 "abc", "123", false }, |
| 92 }; | 92 }; |
| 93 | 93 |
| 94 keychain_ = new MockKeychain(); | 94 keychain_ = new MockAppleKeychain(); |
| 95 | 95 |
| 96 for (unsigned int i = 0; i < arraysize(test_data); ++i) { | 96 for (unsigned int i = 0; i < arraysize(test_data); ++i) { |
| 97 keychain_->AddTestItem(test_data[i]); | 97 keychain_->AddTestItem(test_data[i]); |
| 98 } | 98 } |
| 99 } | 99 } |
| 100 | 100 |
| 101 virtual void TearDown() { | 101 virtual void TearDown() { |
| 102 ExpectCreatesAndFreesBalanced(); | 102 ExpectCreatesAndFreesBalanced(); |
| 103 ExpectCreatorCodesSet(); | 103 ExpectCreatorCodesSet(); |
| 104 delete keychain_; | 104 delete keychain_; |
| 105 } | 105 } |
| 106 | 106 |
| 107 protected: | 107 protected: |
| 108 // Causes a test failure unless everything returned from keychain_'s | 108 // Causes a test failure unless everything returned from keychain_'s |
| 109 // ItemCopyAttributesAndData, SearchCreateFromAttributes, and SearchCopyNext | 109 // ItemCopyAttributesAndData, SearchCreateFromAttributes, and SearchCopyNext |
| 110 // was correctly freed. | 110 // was correctly freed. |
| 111 void ExpectCreatesAndFreesBalanced() { | 111 void ExpectCreatesAndFreesBalanced() { |
| 112 EXPECT_EQ(0, keychain_->UnfreedSearchCount()); | 112 EXPECT_EQ(0, keychain_->UnfreedSearchCount()); |
| 113 EXPECT_EQ(0, keychain_->UnfreedKeychainItemCount()); | 113 EXPECT_EQ(0, keychain_->UnfreedKeychainItemCount()); |
| 114 EXPECT_EQ(0, keychain_->UnfreedAttributeDataCount()); | 114 EXPECT_EQ(0, keychain_->UnfreedAttributeDataCount()); |
| 115 } | 115 } |
| 116 | 116 |
| 117 // Causes a test failure unless any Keychain items added during the test have | 117 // Causes a test failure unless any Keychain items added during the test have |
| 118 // their creator code set. | 118 // their creator code set. |
| 119 void ExpectCreatorCodesSet() { | 119 void ExpectCreatorCodesSet() { |
| 120 EXPECT_TRUE(keychain_->CreatorCodesSetForAddedItems()); | 120 EXPECT_TRUE(keychain_->CreatorCodesSetForAddedItems()); |
| 121 } | 121 } |
| 122 | 122 |
| 123 MockKeychain* keychain_; | 123 MockAppleKeychain* keychain_; |
| 124 }; | 124 }; |
| 125 | 125 |
| 126 #pragma mark - | 126 #pragma mark - |
| 127 | 127 |
| 128 // Struct used for creation of PasswordForms from static arrays of data. | 128 // Struct used for creation of PasswordForms from static arrays of data. |
| 129 struct PasswordFormData { | 129 struct PasswordFormData { |
| 130 const PasswordForm::Scheme scheme; | 130 const PasswordForm::Scheme scheme; |
| 131 const char* signon_realm; | 131 const char* signon_realm; |
| 132 const char* origin; | 132 const char* origin; |
| 133 const char* action; | 133 const char* action; |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 267 "https://some.domain.com/", L"digest_auth_user", L"digest", true, | 267 "https://some.domain.com/", L"digest_auth_user", L"digest", true, |
| 268 1998, 3, 30, 10, 0, 0 }, | 268 1998, 3, 30, 10, 0, 0 }, |
| 269 // This one gives us an invalid date, which we will treat as a "NULL" date | 269 // This one gives us an invalid date, which we will treat as a "NULL" date |
| 270 // which is 1601. | 270 // which is 1601. |
| 271 { PasswordForm::SCHEME_OTHER, "http://a.server.com/", | 271 { PasswordForm::SCHEME_OTHER, "http://a.server.com/", |
| 272 "http://a.server.com/", L"abc", L"123", false, | 272 "http://a.server.com/", L"abc", L"123", false, |
| 273 1601, 1, 1, 0, 0, 0 }, | 273 1601, 1, 1, 0, 0, 0 }, |
| 274 }; | 274 }; |
| 275 | 275 |
| 276 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(expected); ++i) { | 276 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(expected); ++i) { |
| 277 // Create our fake KeychainItemRef; see MockKeychain docs. | 277 // Create our fake KeychainItemRef; see MockAppleKeychain docs. |
| 278 SecKeychainItemRef keychain_item = | 278 SecKeychainItemRef keychain_item = |
| 279 reinterpret_cast<SecKeychainItemRef>(i + 1); | 279 reinterpret_cast<SecKeychainItemRef>(i + 1); |
| 280 PasswordForm form; | 280 PasswordForm form; |
| 281 bool parsed = internal_keychain_helpers::FillPasswordFormFromKeychainItem( | 281 bool parsed = internal_keychain_helpers::FillPasswordFormFromKeychainItem( |
| 282 *keychain_, keychain_item, &form); | 282 *keychain_, keychain_item, &form); |
| 283 | 283 |
| 284 EXPECT_TRUE(parsed) << "In iteration " << i; | 284 EXPECT_TRUE(parsed) << "In iteration " << i; |
| 285 | 285 |
| 286 EXPECT_EQ(expected[i].scheme, form.scheme) << "In iteration " << i; | 286 EXPECT_EQ(expected[i].scheme, form.scheme) << "In iteration " << i; |
| 287 EXPECT_EQ(GURL(expected[i].origin), form.origin) << "In iteration " << i; | 287 EXPECT_EQ(GURL(expected[i].origin), form.origin) << "In iteration " << i; |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 507 "http://a.site.com:2222/", NULL, NULL, NULL, NULL, | 507 "http://a.site.com:2222/", NULL, NULL, NULL, NULL, |
| 508 L"username", L"password", false, false, 0 }, true }, | 508 L"username", L"password", false, false, 0 }, true }, |
| 509 { { PasswordForm::SCHEME_DIGEST, "https://digest.site.com/differentrealm", | 509 { { PasswordForm::SCHEME_DIGEST, "https://digest.site.com/differentrealm", |
| 510 "https://digest.site.com/secure.html", NULL, NULL, NULL, NULL, | 510 "https://digest.site.com/secure.html", NULL, NULL, NULL, NULL, |
| 511 L"testname", L"testpass", false, false, 0 }, true }, | 511 L"testname", L"testpass", false, false, 0 }, true }, |
| 512 // Make sure that garbage forms are rejected. | 512 // Make sure that garbage forms are rejected. |
| 513 { { PasswordForm::SCHEME_HTML, "gobbledygook", | 513 { { PasswordForm::SCHEME_HTML, "gobbledygook", |
| 514 "gobbledygook", NULL, NULL, NULL, NULL, | 514 "gobbledygook", NULL, NULL, NULL, NULL, |
| 515 L"anonymous", L"knock-knock", false, false, 0 }, false }, | 515 L"anonymous", L"knock-knock", false, false, 0 }, false }, |
| 516 // Test that failing to update a duplicate (forced using the magic failure | 516 // Test that failing to update a duplicate (forced using the magic failure |
| 517 // password; see MockKeychain::ItemModifyAttributesAndData) is reported. | 517 // password; see MockAppleKeychain::ItemModifyAttributesAndData) is |
| 518 // reported. |
| 518 { { PasswordForm::SCHEME_HTML, "http://some.domain.com", | 519 { { PasswordForm::SCHEME_HTML, "http://some.domain.com", |
| 519 "http://some.domain.com/insecure.html", NULL, NULL, NULL, NULL, | 520 "http://some.domain.com/insecure.html", NULL, NULL, NULL, NULL, |
| 520 L"joe_user", L"fail_me", false, false, 0 }, false }, | 521 L"joe_user", L"fail_me", false, false, 0 }, false }, |
| 521 }; | 522 }; |
| 522 | 523 |
| 523 MacKeychainPasswordFormAdapter owned_keychain_adapter(keychain_); | 524 MacKeychainPasswordFormAdapter owned_keychain_adapter(keychain_); |
| 524 owned_keychain_adapter.SetFindsOnlyOwnedItems(true); | 525 owned_keychain_adapter.SetFindsOnlyOwnedItems(true); |
| 525 | 526 |
| 526 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { | 527 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { |
| 527 scoped_ptr<PasswordForm> in_form( | 528 scoped_ptr<PasswordForm> in_form( |
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 899 class PasswordStoreMacTest : public testing::Test { | 900 class PasswordStoreMacTest : public testing::Test { |
| 900 public: | 901 public: |
| 901 PasswordStoreMacTest() : ui_thread_(BrowserThread::UI, &message_loop_) {} | 902 PasswordStoreMacTest() : ui_thread_(BrowserThread::UI, &message_loop_) {} |
| 902 | 903 |
| 903 virtual void SetUp() { | 904 virtual void SetUp() { |
| 904 login_db_ = new LoginDatabase(); | 905 login_db_ = new LoginDatabase(); |
| 905 ASSERT_TRUE(db_dir_.CreateUniqueTempDir()); | 906 ASSERT_TRUE(db_dir_.CreateUniqueTempDir()); |
| 906 FilePath db_file = db_dir_.path().AppendASCII("login.db"); | 907 FilePath db_file = db_dir_.path().AppendASCII("login.db"); |
| 907 ASSERT_TRUE(login_db_->Init(db_file)); | 908 ASSERT_TRUE(login_db_->Init(db_file)); |
| 908 | 909 |
| 909 keychain_ = new MockKeychain(); | 910 keychain_ = new MockAppleKeychain(); |
| 910 | 911 |
| 911 store_ = new PasswordStoreMac(keychain_, login_db_); | 912 store_ = new PasswordStoreMac(keychain_, login_db_); |
| 912 ASSERT_TRUE(store_->Init()); | 913 ASSERT_TRUE(store_->Init()); |
| 913 } | 914 } |
| 914 | 915 |
| 915 virtual void TearDown() { | 916 virtual void TearDown() { |
| 916 store_->ShutdownOnUIThread(); | 917 store_->ShutdownOnUIThread(); |
| 917 MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure()); | 918 MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure()); |
| 918 MessageLoop::current()->Run(); | 919 MessageLoop::current()->Run(); |
| 919 } | 920 } |
| 920 | 921 |
| 921 protected: | 922 protected: |
| 922 MessageLoopForUI message_loop_; | 923 MessageLoopForUI message_loop_; |
| 923 content::TestBrowserThread ui_thread_; | 924 content::TestBrowserThread ui_thread_; |
| 924 | 925 |
| 925 MockKeychain* keychain_; // Owned by store_. | 926 MockAppleKeychain* keychain_; // Owned by store_. |
| 926 LoginDatabase* login_db_; // Owned by store_. | 927 LoginDatabase* login_db_; // Owned by store_. |
| 927 scoped_refptr<PasswordStoreMac> store_; | 928 scoped_refptr<PasswordStoreMac> store_; |
| 928 ScopedTempDir db_dir_; | 929 ScopedTempDir db_dir_; |
| 929 }; | 930 }; |
| 930 | 931 |
| 931 TEST_F(PasswordStoreMacTest, TestStoreUpdate) { | 932 TEST_F(PasswordStoreMacTest, TestStoreUpdate) { |
| 932 // Insert a password into both the database and the keychain. | 933 // Insert a password into both the database and the keychain. |
| 933 // This is done manually, rather than through store_->AddLogin, because the | 934 // This is done manually, rather than through store_->AddLogin, because the |
| 934 // Mock Keychain isn't smart enough to be able to support update generically, | 935 // Mock Keychain isn't smart enough to be able to support update generically, |
| 935 // so some.domain.com triggers special handling to test it that make inserting | 936 // so some.domain.com triggers special handling to test it that make inserting |
| 936 // fail. | 937 // fail. |
| 937 PasswordFormData joint_data = { | 938 PasswordFormData joint_data = { |
| 938 PasswordForm::SCHEME_HTML, "http://some.domain.com/", | 939 PasswordForm::SCHEME_HTML, "http://some.domain.com/", |
| 939 "http://some.domain.com/insecure.html", "login.cgi", | 940 "http://some.domain.com/insecure.html", "login.cgi", |
| 940 L"username", L"password", L"submit", L"joe_user", L"sekrit", true, false, 1 | 941 L"username", L"password", L"submit", L"joe_user", L"sekrit", true, false, 1 |
| 941 }; | 942 }; |
| 942 scoped_ptr<PasswordForm> joint_form(CreatePasswordFormFromData(joint_data)); | 943 scoped_ptr<PasswordForm> joint_form(CreatePasswordFormFromData(joint_data)); |
| 943 login_db_->AddLogin(*joint_form); | 944 login_db_->AddLogin(*joint_form); |
| 944 MockKeychain::KeychainTestData joint_keychain_data = { | 945 MockAppleKeychain::KeychainTestData joint_keychain_data = { |
| 945 kSecAuthenticationTypeHTMLForm, "some.domain.com", | 946 kSecAuthenticationTypeHTMLForm, "some.domain.com", |
| 946 kSecProtocolTypeHTTP, "/insecure.html", 0, NULL, "20020601171500Z", | 947 kSecProtocolTypeHTTP, "/insecure.html", 0, NULL, "20020601171500Z", |
| 947 "joe_user", "sekrit", false }; | 948 "joe_user", "sekrit", false }; |
| 948 keychain_->AddTestItem(joint_keychain_data); | 949 keychain_->AddTestItem(joint_keychain_data); |
| 949 | 950 |
| 950 // Insert a password into the keychain only. | 951 // Insert a password into the keychain only. |
| 951 MockKeychain::KeychainTestData keychain_only_data = { | 952 MockAppleKeychain::KeychainTestData keychain_only_data = { |
| 952 kSecAuthenticationTypeHTMLForm, "keychain.only.com", | 953 kSecAuthenticationTypeHTMLForm, "keychain.only.com", |
| 953 kSecProtocolTypeHTTP, NULL, 0, NULL, "20020601171500Z", | 954 kSecProtocolTypeHTTP, NULL, 0, NULL, "20020601171500Z", |
| 954 "keychain", "only", false | 955 "keychain", "only", false |
| 955 }; | 956 }; |
| 956 keychain_->AddTestItem(keychain_only_data); | 957 keychain_->AddTestItem(keychain_only_data); |
| 957 | 958 |
| 958 struct UpdateData { | 959 struct UpdateData { |
| 959 PasswordFormData form_data; | 960 PasswordFormData form_data; |
| 960 const char* password; // NULL indicates no entry should be present. | 961 const char* password; // NULL indicates no entry should be present. |
| 961 }; | 962 }; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1018 EXPECT_EQ(0U, matching_items.size()) << "iteration " << i; | 1019 EXPECT_EQ(0U, matching_items.size()) << "iteration " << i; |
| 1019 } | 1020 } |
| 1020 STLDeleteElements(&matching_items); | 1021 STLDeleteElements(&matching_items); |
| 1021 | 1022 |
| 1022 login_db_->GetLogins(*query_form, &matching_items); | 1023 login_db_->GetLogins(*query_form, &matching_items); |
| 1023 EXPECT_EQ(updates[i].password ? 1U : 0U, matching_items.size()) | 1024 EXPECT_EQ(updates[i].password ? 1U : 0U, matching_items.size()) |
| 1024 << "iteration " << i; | 1025 << "iteration " << i; |
| 1025 STLDeleteElements(&matching_items); | 1026 STLDeleteElements(&matching_items); |
| 1026 } | 1027 } |
| 1027 } | 1028 } |
| OLD | NEW |