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

Side by Side Diff: components/password_manager/core/browser/login_database_ios_unittest.cc

Issue 1237403003: [Password manager IOS upsteaming] Upstreaming login database (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 1 month 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
« no previous file with comments | « components/password_manager/core/browser/login_database_ios.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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/password_manager/core/browser/login_database.h"
6
7 #include <Security/Security.h>
8
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/ios/ios_util.h"
11 #include "base/mac/scoped_cftyperef.h"
12 #include "base/macros.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "components/autofill/core/common/password_form.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "testing/platform_test.h"
17
18 using base::ScopedCFTypeRef;
19 using autofill::PasswordForm;
20
21 namespace password_manager {
22
23 class LoginDatabaseIOSTest : public PlatformTest {
24 public:
25 void SetUp() override {
26 ClearKeychain();
27 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
28 base::FilePath login_db_path =
29 temp_dir_.path().AppendASCII("temp_login.db");
30 login_db_.reset(new password_manager::LoginDatabase(login_db_path));
31 login_db_->Init();
32 }
33
34 void TearDown() override { ClearKeychain(); }
35
36 // Removes all passwords from the keychain. Since the unit test
37 // executable does not share the keychain with anything else on iOS, clearing
38 // the keychain will not affect any other applications.
39 void ClearKeychain();
40
41 // Returns the number of items in the keychain.
42 size_t GetKeychainSize();
43
44 protected:
45 base::ScopedTempDir temp_dir_;
46 scoped_ptr<LoginDatabase> login_db_;
47 };
48
49 void LoginDatabaseIOSTest::ClearKeychain() {
50 const void* queryKeys[] = {kSecClass};
51 const void* queryValues[] = {kSecClassGenericPassword};
52 ScopedCFTypeRef<CFDictionaryRef> query(CFDictionaryCreate(
53 NULL, queryKeys, queryValues, arraysize(queryKeys),
54 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
55 OSStatus status = SecItemDelete(query);
56 // iOS7 returns an error of |errSecItemNotFound| if you try to clear an empty
57 // keychain.
58 ASSERT_TRUE(status == errSecSuccess || status == errSecItemNotFound);
59 }
60
61 size_t LoginDatabaseIOSTest::GetKeychainSize() {
62 // Verify that the keychain now contains exactly one item.
63 ScopedCFTypeRef<CFMutableDictionaryRef> query(
64 CFDictionaryCreateMutable(NULL, 4, &kCFTypeDictionaryKeyCallBacks,
65 &kCFTypeDictionaryValueCallBacks));
66 CFDictionarySetValue(query, kSecClass, kSecClassGenericPassword);
67 CFDictionarySetValue(query, kSecReturnAttributes, kCFBooleanTrue);
68 CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll);
69 CFDictionarySetValue(query, kSecAttrAccessible,
70 kSecAttrAccessibleWhenUnlocked);
71
72 CFTypeRef result;
73 OSStatus status = SecItemCopyMatching(query, &result);
74 if (status == errSecItemNotFound)
75 return 0;
76
77 EXPECT_EQ(errSecSuccess, status);
78 size_t size = CFArrayGetCount((CFArrayRef)result);
79 CFRelease(result);
80 return size;
81 }
82
83 TEST_F(LoginDatabaseIOSTest, KeychainStorage) {
84 base::string16 test_passwords[] = {
85 base::ASCIIToUTF16("foo"), base::ASCIIToUTF16("bar"),
86 base::WideToUTF16(L"\u043F\u0430\u0440\u043E\u043B\u044C"),
87 base::string16(),
88 };
89
90 for (unsigned int i = 0; i < arraysize(test_passwords); i++) {
91 std::string encrypted;
92 EXPECT_EQ(LoginDatabase::ENCRYPTION_RESULT_SUCCESS,
93 login_db_->EncryptedString(test_passwords[i], &encrypted));
94 base::string16 decrypted;
95 EXPECT_EQ(LoginDatabase::ENCRYPTION_RESULT_SUCCESS,
96 login_db_->DecryptedString(encrypted, &decrypted));
97 EXPECT_STREQ(UTF16ToUTF8(test_passwords[i]).c_str(),
98 UTF16ToUTF8(decrypted).c_str());
99 }
100 }
101
102 TEST_F(LoginDatabaseIOSTest, UpdateLogin) {
103 PasswordForm form;
104 form.origin = GURL("http://0.com");
105 form.signon_realm = "http://www.example.com";
106 form.action = GURL("http://www.example.com/action");
107 form.password_element = base::ASCIIToUTF16("pwd");
108 form.password_value = base::ASCIIToUTF16("example");
109
110 ignore_result(login_db_->AddLogin(form));
111
112 form.password_value = base::ASCIIToUTF16("secret");
113
114 password_manager::PasswordStoreChangeList changes =
115 login_db_->UpdateLogin(form);
116 ASSERT_EQ(1u, changes.size());
117
118 form.password_value = base::string16();
119
120 ScopedVector<PasswordForm> forms;
121 EXPECT_TRUE(login_db_->GetLogins(form, &forms));
122
123 ASSERT_EQ(1U, forms.size());
124 EXPECT_STREQ("secret", UTF16ToUTF8(forms[0]->password_value).c_str());
125 ASSERT_EQ(1U, GetKeychainSize());
126 }
127
128 TEST_F(LoginDatabaseIOSTest, RemoveLogin) {
129 PasswordForm form;
130 form.signon_realm = "www.example.com";
131 form.action = GURL("www.example.com/action");
132 form.password_element = base::ASCIIToUTF16("pwd");
133 form.password_value = base::ASCIIToUTF16("example");
134
135 ignore_result(login_db_->AddLogin(form));
136
137 ignore_result(login_db_->RemoveLogin(form));
138
139 ScopedVector<PasswordForm> forms;
140 EXPECT_TRUE(login_db_->GetLogins(form, &forms));
141
142 ASSERT_EQ(0U, forms.size());
143 ASSERT_EQ(0U, GetKeychainSize());
144 }
145
146 TEST_F(LoginDatabaseIOSTest, RemoveLoginsCreatedBetween) {
147 PasswordForm forms[3];
148 forms[0].origin = GURL("http://0.com");
149 forms[0].signon_realm = "http://www.example.com";
150 forms[0].username_element = base::ASCIIToUTF16("login0");
151 forms[0].date_created = base::Time::FromDoubleT(100);
152 forms[0].password_value = base::ASCIIToUTF16("pass0");
153
154 forms[1].origin = GURL("http://1.com");
155 forms[1].signon_realm = "http://www.example.com";
156 forms[1].username_element = base::ASCIIToUTF16("login1");
157 forms[1].date_created = base::Time::FromDoubleT(200);
158 forms[1].password_value = base::ASCIIToUTF16("pass1");
159
160 forms[2].origin = GURL("http://2.com");
161 forms[2].signon_realm = "http://www.example.com";
162 forms[2].username_element = base::ASCIIToUTF16("login2");
163 forms[2].date_created = base::Time::FromDoubleT(300);
164 forms[2].password_value = base::ASCIIToUTF16("pass2");
165
166 for (size_t i = 0; i < arraysize(forms); i++) {
167 ignore_result(login_db_->AddLogin(forms[i]));
168 }
169
170 login_db_->RemoveLoginsCreatedBetween(base::Time::FromDoubleT(150),
171 base::Time::FromDoubleT(250));
172
173 PasswordForm form;
174 form.signon_realm = "http://www.example.com";
175 ScopedVector<PasswordForm> logins;
176 EXPECT_TRUE(login_db_->GetLogins(form, &logins));
177
178 ASSERT_EQ(2U, logins.size());
179 ASSERT_EQ(2U, GetKeychainSize());
180
181 EXPECT_STREQ("login0", UTF16ToUTF8(logins[0]->username_element).c_str());
182 EXPECT_STREQ("pass0", UTF16ToUTF8(logins[0]->password_value).c_str());
183 EXPECT_STREQ("login2", UTF16ToUTF8(logins[1]->username_element).c_str());
184 EXPECT_STREQ("pass2", UTF16ToUTF8(logins[1]->password_value).c_str());
185 }
186
187 } // namespace password_manager
OLDNEW
« no previous file with comments | « components/password_manager/core/browser/login_database_ios.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698