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 "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" |
11 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
12 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
13 #include "base/synchronization/waitable_event.h" | 13 #include "base/synchronization/waitable_event.h" |
14 #include "base/test/histogram_tester.h" | 14 #include "base/test/histogram_tester.h" |
15 #include "base/thread_task_runner_handle.h" | 15 #include "base/thread_task_runner_handle.h" |
16 #include "chrome/browser/password_manager/password_store_mac_internal.h" | 16 #include "chrome/browser/password_manager/password_store_mac_internal.h" |
17 #include "chrome/common/chrome_paths.h" | 17 #include "chrome/common/chrome_paths.h" |
18 #include "components/os_crypt/os_crypt.h" | 18 #include "components/os_crypt/os_crypt.h" |
19 #include "components/password_manager/core/browser/login_database.h" | 19 #include "components/password_manager/core/browser/login_database.h" |
20 #include "components/password_manager/core/browser/password_manager_test_utils.h " | 20 #include "components/password_manager/core/browser/password_manager_test_utils.h " |
21 #include "components/password_manager/core/browser/password_store_consumer.h" | 21 #include "components/password_manager/core/browser/password_store_consumer.h" |
22 #include "components/password_manager/core/browser/password_store_origin_unittes t.h" | |
22 #include "content/public/test/test_browser_thread.h" | 23 #include "content/public/test/test_browser_thread.h" |
23 #include "content/public/test/test_utils.h" | 24 #include "content/public/test/test_utils.h" |
24 #include "crypto/mock_apple_keychain.h" | 25 #include "crypto/mock_apple_keychain.h" |
25 #include "testing/gmock/include/gmock/gmock.h" | 26 #include "testing/gmock/include/gmock/gmock.h" |
26 #include "testing/gtest/include/gtest/gtest.h" | 27 #include "testing/gtest/include/gtest/gtest.h" |
27 | 28 |
28 using autofill::PasswordForm; | 29 using autofill::PasswordForm; |
29 using base::ASCIIToUTF16; | 30 using base::ASCIIToUTF16; |
30 using base::WideToUTF16; | 31 using base::WideToUTF16; |
31 using content::BrowserThread; | 32 using content::BrowserThread; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
67 public: | 68 public: |
68 MOCK_METHOD1(OnGetPasswordStoreResultsConstRef, | 69 MOCK_METHOD1(OnGetPasswordStoreResultsConstRef, |
69 void(const std::vector<PasswordForm*>&)); | 70 void(const std::vector<PasswordForm*>&)); |
70 | 71 |
71 // GMock cannot mock methods with move-only args. | 72 // GMock cannot mock methods with move-only args. |
72 void OnGetPasswordStoreResults(ScopedVector<PasswordForm> results) override { | 73 void OnGetPasswordStoreResults(ScopedVector<PasswordForm> results) override { |
73 OnGetPasswordStoreResultsConstRef(results.get()); | 74 OnGetPasswordStoreResultsConstRef(results.get()); |
74 } | 75 } |
75 }; | 76 }; |
76 | 77 |
77 class MockPasswordStoreObserver : public PasswordStore::Observer { | |
78 public: | |
79 MOCK_METHOD1(OnLoginsChanged, | |
80 void(const password_manager::PasswordStoreChangeList& changes)); | |
81 }; | |
82 | |
83 // A LoginDatabase that simulates an Init() method that takes a long time. | 78 // A LoginDatabase that simulates an Init() method that takes a long time. |
84 class SlowToInitLoginDatabase : public password_manager::LoginDatabase { | 79 class SlowToInitLoginDatabase : public password_manager::LoginDatabase { |
85 public: | 80 public: |
86 // Creates an instance whose Init() method will block until |event| is | 81 // Creates an instance whose Init() method will block until |event| is |
87 // signaled. |event| must outlive |this|. | 82 // signaled. |event| must outlive |this|. |
88 SlowToInitLoginDatabase(const base::FilePath& db_path, | 83 SlowToInitLoginDatabase(const base::FilePath& db_path, |
89 base::WaitableEvent* event) | 84 base::WaitableEvent* event) |
90 : password_manager::LoginDatabase(db_path), event_(event) {} | 85 : password_manager::LoginDatabase(db_path), event_(event) {} |
91 ~SlowToInitLoginDatabase() override {} | 86 ~SlowToInitLoginDatabase() override {} |
92 | 87 |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
165 form->date_synced); | 160 form->date_synced); |
166 EXPECT_EQ(GURL(password_manager::kTestingIconUrlSpec), form->icon_url); | 161 EXPECT_EQ(GURL(password_manager::kTestingIconUrlSpec), form->icon_url); |
167 } | 162 } |
168 } | 163 } |
169 | 164 |
170 PasswordStoreChangeList AddChangeForForm(const PasswordForm& form) { | 165 PasswordStoreChangeList AddChangeForForm(const PasswordForm& form) { |
171 return PasswordStoreChangeList( | 166 return PasswordStoreChangeList( |
172 1, PasswordStoreChange(PasswordStoreChange::ADD, form)); | 167 1, PasswordStoreChange(PasswordStoreChange::ADD, form)); |
173 } | 168 } |
174 | 169 |
170 class PasswordStoreMacTestDelegate { | |
171 public: | |
172 PasswordStoreMacTestDelegate(); | |
173 ~PasswordStoreMacTestDelegate(); | |
174 | |
175 PasswordStoreMac* store() { return store_.get(); } | |
176 | |
177 base::Thread* thread() { return thread_.get(); } | |
178 | |
179 void FinishAsyncProcessing(); | |
180 | |
181 private: | |
182 static void InitLoginDatabase(LoginDatabase* login_db); | |
183 void Initialize(); | |
184 base::FilePath test_login_db_file_path() const; | |
185 | |
186 void ClosePasswordStore(); | |
187 | |
188 base::MessageLoopForUI message_loop_; | |
189 content::TestBrowserThread ui_thread_; | |
vasilii
2015/11/18 16:27:42
It's deprecated. Use TestBrowserThreadBundle. It c
Timo Reimann
2015/11/18 23:42:15
Okay, done. Apart from adding TestBrowserThreadBun
vasilii
2015/11/23 15:04:56
In the implementation you made the test single-thr
Timo Reimann
2015/11/24 02:36:09
This part was and still is somewhat unclear to me:
vasilii
2015/11/24 18:14:54
You don't have to refactor PasswordStoreMacTest. Y
Timo Reimann
2015/11/24 23:06:02
Without any refactoring permitted, wouldn't that p
vasilii
2015/11/25 18:18:39
I don't understand your concern. You have Password
Timo Reimann
2015/11/25 18:47:32
I believe I'm starting to understand where you're
Timo Reimann
2015/11/26 01:12:51
I followed your advice and build a simplified Pass
| |
190 // Thread that the synchronous methods are run on. | |
191 scoped_ptr<base::Thread> thread_; | |
192 | |
193 base::ScopedTempDir db_dir_; | |
194 scoped_ptr<LoginDatabase> login_db_; | |
195 scoped_refptr<PasswordStoreMac> store_; | |
196 | |
197 DISALLOW_COPY_AND_ASSIGN(PasswordStoreMacTestDelegate); | |
198 }; | |
199 | |
200 PasswordStoreMacTestDelegate::PasswordStoreMacTestDelegate() | |
201 : ui_thread_(BrowserThread::UI, &message_loop_) { | |
202 Initialize(); | |
203 } | |
204 | |
205 PasswordStoreMacTestDelegate::~PasswordStoreMacTestDelegate() { | |
206 ClosePasswordStore(); | |
207 thread_.reset(); | |
208 login_db_.reset(); | |
209 } | |
210 | |
211 void PasswordStoreMacTestDelegate::Initialize() { | |
212 ASSERT_TRUE(db_dir_.CreateUniqueTempDir()); | |
213 | |
214 // Ensure that LoginDatabase will use the mock keychain if it needs to | |
215 // encrypt/decrypt a password. | |
216 OSCrypt::UseMockKeychain(true); | |
217 login_db_.reset(new LoginDatabase(test_login_db_file_path())); | |
218 thread_.reset(new base::Thread("Chrome_PasswordStore_Thread")); | |
219 ASSERT_TRUE(thread_->Start()); | |
220 ASSERT_TRUE(thread_->task_runner()->PostTask( | |
221 FROM_HERE, base::Bind(&PasswordStoreMacTestDelegate::InitLoginDatabase, | |
222 base::Unretained(login_db_.get())))); | |
223 | |
224 // Creat and initialize the password store. | |
225 store_ = new PasswordStoreMac( | |
226 base::ThreadTaskRunnerHandle::Get(), nullptr, | |
227 make_scoped_ptr<AppleKeychain>(new MockAppleKeychain)); | |
vasilii
2015/11/18 16:27:42
I think it should work without the type specifier.
Timo Reimann
2015/11/18 23:42:15
It does. Removed.
| |
228 ASSERT_TRUE(thread_->task_runner()->PostTask( | |
229 FROM_HERE, base::Bind(&PasswordStoreMac::InitWithTaskRunner, store_, | |
230 thread_->task_runner()))); | |
231 | |
232 ASSERT_TRUE(thread_->task_runner()->PostTask( | |
233 FROM_HERE, base::Bind(&PasswordStoreMac::set_login_metadata_db, store_, | |
234 base::Unretained(login_db_.get())))); | |
235 | |
236 // Make sure deferred initialization is performed before some tests start | |
237 // accessing the |login_db| directly. | |
238 FinishAsyncProcessing(); | |
239 } | |
240 | |
241 void PasswordStoreMacTestDelegate::FinishAsyncProcessing() { | |
242 scoped_refptr<content::MessageLoopRunner> runner = | |
243 new content::MessageLoopRunner; | |
244 ASSERT_TRUE(thread_->task_runner()->PostTaskAndReply( | |
245 FROM_HERE, base::Bind(&Noop), runner->QuitClosure())); | |
246 runner->Run(); | |
247 } | |
248 | |
vasilii
2015/11/18 16:27:42
// static
Timo Reimann
2015/11/18 23:42:15
Done.
| |
249 void PasswordStoreMacTestDelegate::InitLoginDatabase(LoginDatabase* login_db) { | |
250 ASSERT_TRUE(login_db->Init()); | |
251 } | |
252 | |
253 base::FilePath PasswordStoreMacTestDelegate::test_login_db_file_path() const { | |
254 return db_dir_.path().Append(FILE_PATH_LITERAL("login.db")); | |
255 } | |
256 | |
257 void PasswordStoreMacTestDelegate::ClosePasswordStore() { | |
258 if (!store_) | |
259 return; | |
260 | |
261 store_->Shutdown(); | |
262 FinishAsyncProcessing(); | |
263 store_ = nullptr; | |
264 } | |
265 | |
175 } // namespace | 266 } // namespace |
176 | 267 |
268 namespace password_manager { | |
269 | |
270 INSTANTIATE_TYPED_TEST_CASE_P(Mac, | |
271 PasswordStoreOriginTest, | |
272 PasswordStoreMacTestDelegate); | |
273 | |
274 } // namespace password_manager | |
275 | |
177 #pragma mark - | 276 #pragma mark - |
178 | 277 |
179 class PasswordStoreMacInternalsTest : public testing::Test { | 278 class PasswordStoreMacInternalsTest : public testing::Test { |
180 public: | 279 public: |
181 void SetUp() override { | 280 void SetUp() override { |
182 MockAppleKeychain::KeychainTestData test_data[] = { | 281 MockAppleKeychain::KeychainTestData test_data[] = { |
183 // Basic HTML form. | 282 // Basic HTML form. |
184 {kSecAuthenticationTypeHTMLForm, | 283 {kSecAuthenticationTypeHTMLForm, |
185 "some.domain.com", | 284 "some.domain.com", |
186 kSecProtocolTypeHTTP, | 285 kSecProtocolTypeHTTP, |
(...skipping 979 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1166 | 1265 |
1167 ScopedVector<autofill::PasswordForm> owned_passwords = | 1266 ScopedVector<autofill::PasswordForm> owned_passwords = |
1168 owned_keychain_adapter.GetAllPasswordFormPasswords(); | 1267 owned_keychain_adapter.GetAllPasswordFormPasswords(); |
1169 EXPECT_EQ(arraysize(owned_password_data), owned_passwords.size()); | 1268 EXPECT_EQ(arraysize(owned_password_data), owned_passwords.size()); |
1170 } | 1269 } |
1171 | 1270 |
1172 #pragma mark - | 1271 #pragma mark - |
1173 | 1272 |
1174 class PasswordStoreMacTest : public testing::Test { | 1273 class PasswordStoreMacTest : public testing::Test { |
1175 public: | 1274 public: |
1176 PasswordStoreMacTest() : ui_thread_(BrowserThread::UI, &message_loop_) {} | 1275 PasswordStoreMacTest() |
1276 : histogram_tester_(new base::HistogramTester), | |
1277 store_(delegate_.store()) {} | |
1177 | 1278 |
1178 void SetUp() override { | 1279 ~PasswordStoreMacTest() override { |
1179 ASSERT_TRUE(db_dir_.CreateUniqueTempDir()); | |
1180 histogram_tester_.reset(new base::HistogramTester); | |
1181 | |
1182 // Ensure that LoginDatabase will use the mock keychain if it needs to | |
1183 // encrypt/decrypt a password. | |
1184 OSCrypt::UseMockKeychain(true); | |
1185 login_db_.reset( | |
1186 new password_manager::LoginDatabase(test_login_db_file_path())); | |
1187 thread_.reset(new base::Thread("Chrome_PasswordStore_Thread")); | |
1188 ASSERT_TRUE(thread_->Start()); | |
1189 ASSERT_TRUE(thread_->task_runner()->PostTask( | |
1190 FROM_HERE, base::Bind(&PasswordStoreMacTest::InitLoginDatabase, | |
1191 base::Unretained(login_db_.get())))); | |
1192 CreateAndInitPasswordStore(login_db_.get()); | |
1193 // Make sure deferred initialization is performed before some tests start | |
1194 // accessing the |login_db| directly. | |
1195 FinishAsyncProcessing(); | |
1196 } | |
1197 | |
1198 void TearDown() override { | |
1199 ClosePasswordStore(); | |
1200 thread_.reset(); | |
1201 login_db_.reset(); | |
1202 // Whatever a test did, PasswordStoreMac stores only empty password values | 1280 // Whatever a test did, PasswordStoreMac stores only empty password values |
1203 // in LoginDatabase. The empty valus do not require encryption and therefore | 1281 // in LoginDatabase. The empty valus do not require encryption and therefore |
1204 // OSCrypt shouldn't call the Keychain. The histogram doesn't cover the | 1282 // OSCrypt shouldn't call the Keychain. The histogram doesn't cover the |
1205 // internet passwords. | 1283 // internet passwords. |
1206 if (histogram_tester_) { | 1284 if (histogram_tester_) { |
1207 histogram_tester_->ExpectTotalCount("OSX.Keychain.Access", 0); | 1285 histogram_tester_->ExpectTotalCount("OSX.Keychain.Access", 0); |
1208 } | 1286 } |
1209 } | 1287 } |
1210 | 1288 |
1211 static void InitLoginDatabase(password_manager::LoginDatabase* login_db) { | |
1212 ASSERT_TRUE(login_db->Init()); | |
1213 } | |
1214 | |
1215 void CreateAndInitPasswordStore(password_manager::LoginDatabase* login_db) { | |
1216 store_ = new PasswordStoreMac( | |
1217 base::ThreadTaskRunnerHandle::Get(), nullptr, | |
1218 make_scoped_ptr<AppleKeychain>(new MockAppleKeychain)); | |
1219 ASSERT_TRUE(thread_->task_runner()->PostTask( | |
1220 FROM_HERE, base::Bind(&PasswordStoreMac::InitWithTaskRunner, store_, | |
1221 thread_->task_runner()))); | |
1222 | |
1223 ASSERT_TRUE(thread_->task_runner()->PostTask( | |
1224 FROM_HERE, base::Bind(&PasswordStoreMac::set_login_metadata_db, store_, | |
1225 base::Unretained(login_db)))); | |
1226 } | |
1227 | |
1228 void ClosePasswordStore() { | |
1229 if (!store_) | |
1230 return; | |
1231 | |
1232 store_->Shutdown(); | |
1233 store_ = nullptr; | |
1234 } | |
1235 | |
1236 // Verifies that the given |form| can be properly stored so that it can be | 1289 // Verifies that the given |form| can be properly stored so that it can be |
1237 // retrieved by FillMatchingLogins() and GetAutofillableLogins(), and then it | 1290 // retrieved by FillMatchingLogins() and GetAutofillableLogins(), and then it |
1238 // can be properly removed. | 1291 // can be properly removed. |
1239 void VerifyCredentialLifecycle(const PasswordForm& form) { | 1292 void VerifyCredentialLifecycle(const PasswordForm& form) { |
1240 // Run everything twice to make sure no garbage is left behind that would | 1293 // Run everything twice to make sure no garbage is left behind that would |
1241 // prevent storing the form a second time. | 1294 // prevent storing the form a second time. |
1242 for (size_t iteration = 0; iteration < 2; ++iteration) { | 1295 for (size_t iteration = 0; iteration < 2; ++iteration) { |
1243 SCOPED_TRACE(testing::Message("Iteration: ") << iteration); | 1296 SCOPED_TRACE(testing::Message("Iteration: ") << iteration); |
1244 | 1297 |
1245 MockPasswordStoreConsumer mock_consumer; | 1298 MockPasswordStoreConsumer mock_consumer; |
1246 EXPECT_CALL(mock_consumer, OnGetPasswordStoreResultsConstRef(IsEmpty())) | 1299 EXPECT_CALL(mock_consumer, OnGetPasswordStoreResultsConstRef(IsEmpty())) |
1247 .WillOnce(QuitUIMessageLoop()); | 1300 .WillOnce(QuitUIMessageLoop()); |
1248 store()->GetAutofillableLogins(&mock_consumer); | 1301 store()->GetAutofillableLogins(&mock_consumer); |
1249 base::MessageLoop::current()->Run(); | 1302 base::MessageLoop::current()->Run(); |
1250 ::testing::Mock::VerifyAndClearExpectations(&mock_consumer); | 1303 ::testing::Mock::VerifyAndClearExpectations(&mock_consumer); |
1251 | 1304 |
1252 store()->AddLogin(form); | 1305 store()->AddLogin(form); |
1253 FinishAsyncProcessing(); | 1306 delegate_.FinishAsyncProcessing(); |
1254 | 1307 |
1255 PasswordForm returned_form; | 1308 PasswordForm returned_form; |
1256 EXPECT_CALL(mock_consumer, OnGetPasswordStoreResultsConstRef(SizeIs(1u))) | 1309 EXPECT_CALL(mock_consumer, OnGetPasswordStoreResultsConstRef(SizeIs(1u))) |
1257 .WillOnce( | 1310 .WillOnce( |
1258 DoAll(SaveACopyOfFirstForm(&returned_form), QuitUIMessageLoop())); | 1311 DoAll(SaveACopyOfFirstForm(&returned_form), QuitUIMessageLoop())); |
1259 | 1312 |
1260 // The query operations will also do some housekeeping: they will remove | 1313 // The query operations will also do some housekeeping: they will remove |
1261 // dangling credentials in the LoginDatabase without a matching Keychain | 1314 // dangling credentials in the LoginDatabase without a matching Keychain |
1262 // item when one is expected. If the logic that stores the Keychain item | 1315 // item when one is expected. If the logic that stores the Keychain item |
1263 // is incorrect, this will wipe the newly added form before the second | 1316 // is incorrect, this will wipe the newly added form before the second |
(...skipping 12 matching lines...) Expand all Loading... | |
1276 store()->GetLogins(query_form, PasswordStore::ALLOW_PROMPT, | 1329 store()->GetLogins(query_form, PasswordStore::ALLOW_PROMPT, |
1277 &mock_consumer); | 1330 &mock_consumer); |
1278 base::MessageLoop::current()->Run(); | 1331 base::MessageLoop::current()->Run(); |
1279 ::testing::Mock::VerifyAndClearExpectations(&mock_consumer); | 1332 ::testing::Mock::VerifyAndClearExpectations(&mock_consumer); |
1280 EXPECT_EQ(form, returned_form); | 1333 EXPECT_EQ(form, returned_form); |
1281 | 1334 |
1282 store()->RemoveLogin(form); | 1335 store()->RemoveLogin(form); |
1283 } | 1336 } |
1284 } | 1337 } |
1285 | 1338 |
1286 base::FilePath test_login_db_file_path() const { | |
1287 return db_dir_.path().Append(FILE_PATH_LITERAL("login.db")); | |
1288 } | |
1289 | |
1290 password_manager::LoginDatabase* login_db() const { | 1339 password_manager::LoginDatabase* login_db() const { |
1291 return store_->login_metadata_db(); | 1340 return store_->login_metadata_db(); |
1292 } | 1341 } |
1293 | 1342 |
1294 MockAppleKeychain* keychain() { | 1343 MockAppleKeychain* keychain() { |
1295 return static_cast<MockAppleKeychain*>(store_->keychain()); | 1344 return static_cast<MockAppleKeychain*>(store_->keychain()); |
1296 } | 1345 } |
1297 | 1346 |
1298 void FinishAsyncProcessing() { | 1347 PasswordStoreMac* store() { return store_; } |
1299 scoped_refptr<content::MessageLoopRunner> runner = | |
1300 new content::MessageLoopRunner; | |
1301 ASSERT_TRUE(thread_->task_runner()->PostTaskAndReply( | |
1302 FROM_HERE, base::Bind(&Noop), runner->QuitClosure())); | |
1303 runner->Run(); | |
1304 } | |
1305 | 1348 |
1306 PasswordStoreMac* store() { return store_.get(); } | 1349 PasswordStoreMacTestDelegate& delegate() { return delegate_; } |
1307 | 1350 |
1308 protected: | 1351 protected: |
1309 base::MessageLoopForUI message_loop_; | |
1310 content::TestBrowserThread ui_thread_; | |
1311 // Thread that the synchronous methods are run on. | |
1312 scoped_ptr<base::Thread> thread_; | |
1313 | |
1314 base::ScopedTempDir db_dir_; | |
1315 scoped_ptr<password_manager::LoginDatabase> login_db_; | |
1316 scoped_refptr<PasswordStoreMac> store_; | |
1317 scoped_ptr<base::HistogramTester> histogram_tester_; | 1352 scoped_ptr<base::HistogramTester> histogram_tester_; |
1353 PasswordStoreMacTestDelegate delegate_; | |
1354 PasswordStoreMac* store_; | |
vasilii
2015/11/18 16:27:42
Remove
Timo Reimann
2015/11/18 23:42:15
Done (and replaced all references to store_ by del
| |
1318 }; | 1355 }; |
1319 | 1356 |
1320 TEST_F(PasswordStoreMacTest, TestStoreUpdate) { | 1357 TEST_F(PasswordStoreMacTest, TestStoreUpdate) { |
1321 // Insert a password into both the database and the keychain. | 1358 // Insert a password into both the database and the keychain. |
1322 // This is done manually, rather than through store_->AddLogin, because the | 1359 // This is done manually, rather than through store_->AddLogin, because the |
1323 // Mock Keychain isn't smart enough to be able to support update generically, | 1360 // Mock Keychain isn't smart enough to be able to support update generically, |
1324 // so some.domain.com triggers special handling to test it that make inserting | 1361 // so some.domain.com triggers special handling to test it that make inserting |
1325 // fail. | 1362 // fail. |
1326 PasswordFormData joint_data = { | 1363 PasswordFormData joint_data = { |
1327 PasswordForm::SCHEME_HTML, "http://some.domain.com/", | 1364 PasswordForm::SCHEME_HTML, "http://some.domain.com/", |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1376 true, false, 2 }, | 1413 true, false, 2 }, |
1377 NULL, | 1414 NULL, |
1378 }, | 1415 }, |
1379 }; | 1416 }; |
1380 for (unsigned int i = 0; i < arraysize(updates); ++i) { | 1417 for (unsigned int i = 0; i < arraysize(updates); ++i) { |
1381 scoped_ptr<PasswordForm> form = | 1418 scoped_ptr<PasswordForm> form = |
1382 CreatePasswordFormFromDataForTesting(updates[i].form_data); | 1419 CreatePasswordFormFromDataForTesting(updates[i].form_data); |
1383 store_->UpdateLogin(*form); | 1420 store_->UpdateLogin(*form); |
1384 } | 1421 } |
1385 | 1422 |
1386 FinishAsyncProcessing(); | 1423 delegate_.FinishAsyncProcessing(); |
1387 | 1424 |
1388 MacKeychainPasswordFormAdapter keychain_adapter(keychain()); | 1425 MacKeychainPasswordFormAdapter keychain_adapter(keychain()); |
1389 for (unsigned int i = 0; i < arraysize(updates); ++i) { | 1426 for (unsigned int i = 0; i < arraysize(updates); ++i) { |
1390 scoped_ptr<PasswordForm> query_form = | 1427 scoped_ptr<PasswordForm> query_form = |
1391 CreatePasswordFormFromDataForTesting(updates[i].form_data); | 1428 CreatePasswordFormFromDataForTesting(updates[i].form_data); |
1392 | 1429 |
1393 ScopedVector<autofill::PasswordForm> matching_items = | 1430 ScopedVector<autofill::PasswordForm> matching_items = |
1394 keychain_adapter.PasswordsFillingForm(query_form->signon_realm, | 1431 keychain_adapter.PasswordsFillingForm(query_form->signon_realm, |
1395 query_form->scheme); | 1432 query_form->scheme); |
1396 if (updates[i].password) { | 1433 if (updates[i].password) { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1453 // 3. Add the returned password for m.facebook.com. | 1490 // 3. Add the returned password for m.facebook.com. |
1454 returned_form.signon_realm = "http://m.facebook.com"; | 1491 returned_form.signon_realm = "http://m.facebook.com"; |
1455 returned_form.origin = GURL("http://m.facebook.com/index.html"); | 1492 returned_form.origin = GURL("http://m.facebook.com/index.html"); |
1456 EXPECT_EQ(AddChangeForForm(returned_form), | 1493 EXPECT_EQ(AddChangeForForm(returned_form), |
1457 login_db()->AddLogin(returned_form)); | 1494 login_db()->AddLogin(returned_form)); |
1458 owned_keychain_adapter.AddPassword(m_form); | 1495 owned_keychain_adapter.AddPassword(m_form); |
1459 | 1496 |
1460 // 4. Remove both passwords. | 1497 // 4. Remove both passwords. |
1461 store_->RemoveLogin(*www_form); | 1498 store_->RemoveLogin(*www_form); |
1462 store_->RemoveLogin(m_form); | 1499 store_->RemoveLogin(m_form); |
1463 FinishAsyncProcessing(); | 1500 delegate_.FinishAsyncProcessing(); |
1464 | 1501 |
1465 // No trace of www.facebook.com. | 1502 // No trace of www.facebook.com. |
1466 ScopedVector<autofill::PasswordForm> matching_items = | 1503 ScopedVector<autofill::PasswordForm> matching_items = |
1467 owned_keychain_adapter.PasswordsFillingForm(www_form->signon_realm, | 1504 owned_keychain_adapter.PasswordsFillingForm(www_form->signon_realm, |
1468 www_form->scheme); | 1505 www_form->scheme); |
1469 EXPECT_EQ(0u, matching_items.size()); | 1506 EXPECT_EQ(0u, matching_items.size()); |
1470 EXPECT_TRUE(login_db()->GetLogins(*www_form, &matching_items)); | 1507 EXPECT_TRUE(login_db()->GetLogins(*www_form, &matching_items)); |
1471 EXPECT_EQ(0u, matching_items.size()); | 1508 EXPECT_EQ(0u, matching_items.size()); |
1472 // No trace of m.facebook.com. | 1509 // No trace of m.facebook.com. |
1473 matching_items = owned_keychain_adapter.PasswordsFillingForm( | 1510 matching_items = owned_keychain_adapter.PasswordsFillingForm( |
1474 m_form.signon_realm, m_form.scheme); | 1511 m_form.signon_realm, m_form.scheme); |
1475 EXPECT_EQ(0u, matching_items.size()); | 1512 EXPECT_EQ(0u, matching_items.size()); |
1476 EXPECT_TRUE(login_db()->GetLogins(m_form, &matching_items)); | 1513 EXPECT_TRUE(login_db()->GetLogins(m_form, &matching_items)); |
1477 EXPECT_EQ(0u, matching_items.size()); | 1514 EXPECT_EQ(0u, matching_items.size()); |
1478 } | 1515 } |
1479 | 1516 |
1480 namespace { | 1517 namespace { |
1481 | 1518 |
1482 class PasswordsChangeObserver : | 1519 class PasswordsChangeObserver : |
1483 public password_manager::PasswordStore::Observer { | 1520 public password_manager::PasswordStore::Observer { |
1484 public: | 1521 public: |
1485 PasswordsChangeObserver(PasswordStoreMac* store) : observer_(this) { | 1522 explicit PasswordsChangeObserver(PasswordStoreMac* store) : observer_(this) { |
1486 observer_.Add(store); | 1523 observer_.Add(store); |
1487 } | 1524 } |
1488 | 1525 |
1489 void WaitAndVerify(PasswordStoreMacTest* test) { | 1526 void WaitAndVerify(PasswordStoreMacTest* test) { |
1490 test->FinishAsyncProcessing(); | 1527 test->delegate().FinishAsyncProcessing(); |
1491 ::testing::Mock::VerifyAndClearExpectations(this); | 1528 ::testing::Mock::VerifyAndClearExpectations(this); |
1492 } | 1529 } |
1493 | 1530 |
1494 // password_manager::PasswordStore::Observer: | 1531 // password_manager::PasswordStore::Observer: |
1495 MOCK_METHOD1(OnLoginsChanged, | 1532 MOCK_METHOD1(OnLoginsChanged, |
1496 void(const password_manager::PasswordStoreChangeList& changes)); | 1533 void(const password_manager::PasswordStoreChangeList& changes)); |
1497 | 1534 |
1498 private: | 1535 private: |
1499 ScopedObserver<password_manager::PasswordStore, | 1536 ScopedObserver<password_manager::PasswordStore, |
1500 PasswordsChangeObserver> observer_; | 1537 PasswordsChangeObserver> observer_; |
1501 }; | 1538 }; |
1502 | 1539 |
1503 password_manager::PasswordStoreChangeList GetAddChangeList( | 1540 password_manager::PasswordStoreChangeList GetAddChangeList( |
1504 const PasswordForm& form) { | 1541 const PasswordForm& form) { |
1505 password_manager::PasswordStoreChange change( | 1542 password_manager::PasswordStoreChange change( |
1506 password_manager::PasswordStoreChange::ADD, form); | 1543 password_manager::PasswordStoreChange::ADD, form); |
1507 return password_manager::PasswordStoreChangeList(1, change); | 1544 return password_manager::PasswordStoreChangeList(1, change); |
1508 } | 1545 } |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1636 CreatePasswordFormFromDataForTesting(www_form_data1); | 1673 CreatePasswordFormFromDataForTesting(www_form_data1); |
1637 EXPECT_TRUE(owned_keychain_adapter.AddPassword(*www_form)); | 1674 EXPECT_TRUE(owned_keychain_adapter.AddPassword(*www_form)); |
1638 | 1675 |
1639 // Add a password from the current profile. | 1676 // Add a password from the current profile. |
1640 PasswordFormData www_form_data2 = { | 1677 PasswordFormData www_form_data2 = { |
1641 PasswordForm::SCHEME_HTML, "http://www.facebook.com/", | 1678 PasswordForm::SCHEME_HTML, "http://www.facebook.com/", |
1642 "http://www.facebook.com/index.html", "login", L"username", L"password", | 1679 "http://www.facebook.com/index.html", "login", L"username", L"password", |
1643 L"submit", L"not_joe_user", L"12345", true, false, 1 }; | 1680 L"submit", L"not_joe_user", L"12345", true, false, 1 }; |
1644 www_form = CreatePasswordFormFromDataForTesting(www_form_data2); | 1681 www_form = CreatePasswordFormFromDataForTesting(www_form_data2); |
1645 store_->AddLogin(*www_form); | 1682 store_->AddLogin(*www_form); |
1646 FinishAsyncProcessing(); | 1683 delegate_.FinishAsyncProcessing(); |
1647 | 1684 |
1648 ScopedVector<PasswordForm> matching_items; | 1685 ScopedVector<PasswordForm> matching_items; |
1649 EXPECT_TRUE(login_db()->GetLogins(*www_form, &matching_items)); | 1686 EXPECT_TRUE(login_db()->GetLogins(*www_form, &matching_items)); |
1650 EXPECT_EQ(1u, matching_items.size()); | 1687 EXPECT_EQ(1u, matching_items.size()); |
1651 | 1688 |
1652 store_->RemoveLoginsCreatedBetween(base::Time(), base::Time(), | 1689 store_->RemoveLoginsCreatedBetween(base::Time(), base::Time(), |
1653 base::Closure()); | 1690 base::Closure()); |
1654 FinishAsyncProcessing(); | 1691 delegate_.FinishAsyncProcessing(); |
1655 | 1692 |
1656 // Check the second facebook form is gone. | 1693 // Check the second facebook form is gone. |
1657 EXPECT_TRUE(login_db()->GetLogins(*www_form, &matching_items)); | 1694 EXPECT_TRUE(login_db()->GetLogins(*www_form, &matching_items)); |
1658 EXPECT_EQ(0u, matching_items.size()); | 1695 EXPECT_EQ(0u, matching_items.size()); |
1659 | 1696 |
1660 // Check the first facebook form is still there. | 1697 // Check the first facebook form is still there. |
1661 matching_items = owned_keychain_adapter.PasswordsFillingForm( | 1698 matching_items = owned_keychain_adapter.PasswordsFillingForm( |
1662 www_form->signon_realm, www_form->scheme); | 1699 www_form->signon_realm, www_form->scheme); |
1663 ASSERT_EQ(1u, matching_items.size()); | 1700 ASSERT_EQ(1u, matching_items.size()); |
1664 EXPECT_EQ(ASCIIToUTF16("joe_user"), matching_items[0]->username_value); | 1701 EXPECT_EQ(ASCIIToUTF16("joe_user"), matching_items[0]->username_value); |
1665 | 1702 |
1666 // Check the third-party password is still there. | 1703 // Check the third-party password is still there. |
1667 owned_keychain_adapter.SetFindsOnlyOwnedItems(false); | 1704 owned_keychain_adapter.SetFindsOnlyOwnedItems(false); |
1668 matching_items = owned_keychain_adapter.PasswordsFillingForm( | 1705 matching_items = owned_keychain_adapter.PasswordsFillingForm( |
1669 "http://some.domain.com/insecure.html", PasswordForm::SCHEME_HTML); | 1706 "http://some.domain.com/insecure.html", PasswordForm::SCHEME_HTML); |
1670 ASSERT_EQ(1u, matching_items.size()); | 1707 ASSERT_EQ(1u, matching_items.size()); |
1671 } | 1708 } |
1672 | 1709 |
1673 // Add a facebook form to the store but not to the keychain. The form is to be | 1710 // Add a facebook form to the store but not to the keychain. The form is to be |
1674 // implicitly deleted. However, the observers shouldn't get notified about | 1711 // implicitly deleted. However, the observers shouldn't get notified about |
1675 // deletion of non-existent forms like m.facebook.com. | 1712 // deletion of non-existent forms like m.facebook.com. |
1676 TEST_F(PasswordStoreMacTest, SilentlyRemoveOrphanedForm) { | 1713 TEST_F(PasswordStoreMacTest, SilentlyRemoveOrphanedForm) { |
1677 testing::StrictMock<MockPasswordStoreObserver> mock_observer; | 1714 testing::StrictMock<password_manager::MockPasswordStoreObserver> |
1715 mock_observer; | |
1678 store()->AddObserver(&mock_observer); | 1716 store()->AddObserver(&mock_observer); |
1679 | 1717 |
1680 // 1. Add a password for www.facebook.com to the LoginDatabase. | 1718 // 1. Add a password for www.facebook.com to the LoginDatabase. |
1681 PasswordFormData www_form_data = { | 1719 PasswordFormData www_form_data = { |
1682 PasswordForm::SCHEME_HTML, "http://www.facebook.com/", | 1720 PasswordForm::SCHEME_HTML, "http://www.facebook.com/", |
1683 "http://www.facebook.com/index.html", "login", | 1721 "http://www.facebook.com/index.html", "login", |
1684 L"username", L"password", L"submit", L"joe_user", L"", true, false, 1 | 1722 L"username", L"password", L"submit", L"joe_user", L"", true, false, 1 |
1685 }; | 1723 }; |
1686 scoped_ptr<PasswordForm> www_form( | 1724 scoped_ptr<PasswordForm> www_form( |
1687 CreatePasswordFormFromDataForTesting(www_form_data)); | 1725 CreatePasswordFormFromDataForTesting(www_form_data)); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1763 form2.password_value = ASCIIToUTF16("my_password"); | 1801 form2.password_value = ASCIIToUTF16("my_password"); |
1764 | 1802 |
1765 PasswordForm blacklisted_form; | 1803 PasswordForm blacklisted_form; |
1766 blacklisted_form.origin = GURL("http://badsite.com/Login"); | 1804 blacklisted_form.origin = GURL("http://badsite.com/Login"); |
1767 blacklisted_form.signon_realm = "http://badsite.com/"; | 1805 blacklisted_form.signon_realm = "http://badsite.com/"; |
1768 blacklisted_form.blacklisted_by_user = true; | 1806 blacklisted_form.blacklisted_by_user = true; |
1769 | 1807 |
1770 store()->AddLogin(form1); | 1808 store()->AddLogin(form1); |
1771 store()->AddLogin(form2); | 1809 store()->AddLogin(form2); |
1772 store()->AddLogin(blacklisted_form); | 1810 store()->AddLogin(blacklisted_form); |
1773 FinishAsyncProcessing(); | 1811 delegate_.FinishAsyncProcessing(); |
1774 | 1812 |
1775 ASSERT_TRUE(base::PostTaskAndReplyWithResult( | 1813 ASSERT_TRUE(base::PostTaskAndReplyWithResult( |
1776 thread_->task_runner().get(), FROM_HERE, | 1814 delegate_.thread()->task_runner().get(), FROM_HERE, |
1777 base::Bind(&PasswordStoreMac::ImportFromKeychain, store()), | 1815 base::Bind(&PasswordStoreMac::ImportFromKeychain, store()), |
1778 base::Bind(&CheckMigrationResult, PasswordStoreMac::MIGRATION_OK))); | 1816 base::Bind(&CheckMigrationResult, PasswordStoreMac::MIGRATION_OK))); |
1779 FinishAsyncProcessing(); | 1817 delegate_.FinishAsyncProcessing(); |
1780 | 1818 |
1781 // The password should be stored in the database by now. | 1819 // The password should be stored in the database by now. |
1782 ScopedVector<PasswordForm> matching_items; | 1820 ScopedVector<PasswordForm> matching_items; |
1783 EXPECT_TRUE(login_db()->GetLogins(form1, &matching_items)); | 1821 EXPECT_TRUE(login_db()->GetLogins(form1, &matching_items)); |
1784 ASSERT_EQ(1u, matching_items.size()); | 1822 ASSERT_EQ(1u, matching_items.size()); |
1785 EXPECT_EQ(form1, *matching_items[0]); | 1823 EXPECT_EQ(form1, *matching_items[0]); |
1786 | 1824 |
1787 EXPECT_TRUE(login_db()->GetLogins(form2, &matching_items)); | 1825 EXPECT_TRUE(login_db()->GetLogins(form2, &matching_items)); |
1788 ASSERT_EQ(1u, matching_items.size()); | 1826 ASSERT_EQ(1u, matching_items.size()); |
1789 EXPECT_EQ(form2, *matching_items[0]); | 1827 EXPECT_EQ(form2, *matching_items[0]); |
(...skipping 11 matching lines...) Expand all Loading... | |
1801 // Import a federated credential while the Keychain is locked. | 1839 // Import a federated credential while the Keychain is locked. |
1802 TEST_F(PasswordStoreMacTest, ImportFederatedFromLockedKeychain) { | 1840 TEST_F(PasswordStoreMacTest, ImportFederatedFromLockedKeychain) { |
1803 keychain()->set_locked(true); | 1841 keychain()->set_locked(true); |
1804 PasswordForm form1; | 1842 PasswordForm form1; |
1805 form1.origin = GURL("http://example.com/Login"); | 1843 form1.origin = GURL("http://example.com/Login"); |
1806 form1.signon_realm = "http://example.com/"; | 1844 form1.signon_realm = "http://example.com/"; |
1807 form1.username_value = ASCIIToUTF16("my_username"); | 1845 form1.username_value = ASCIIToUTF16("my_username"); |
1808 form1.federation_url = GURL("https://accounts.google.com/"); | 1846 form1.federation_url = GURL("https://accounts.google.com/"); |
1809 | 1847 |
1810 store()->AddLogin(form1); | 1848 store()->AddLogin(form1); |
1811 FinishAsyncProcessing(); | 1849 delegate_.FinishAsyncProcessing(); |
1812 ASSERT_TRUE(base::PostTaskAndReplyWithResult( | 1850 ASSERT_TRUE(base::PostTaskAndReplyWithResult( |
1813 thread_->task_runner().get(), FROM_HERE, | 1851 delegate_.thread()->task_runner().get(), FROM_HERE, |
1814 base::Bind(&PasswordStoreMac::ImportFromKeychain, store()), | 1852 base::Bind(&PasswordStoreMac::ImportFromKeychain, store()), |
1815 base::Bind(&CheckMigrationResult, PasswordStoreMac::MIGRATION_OK))); | 1853 base::Bind(&CheckMigrationResult, PasswordStoreMac::MIGRATION_OK))); |
1816 FinishAsyncProcessing(); | 1854 delegate_.FinishAsyncProcessing(); |
1817 | 1855 |
1818 ScopedVector<PasswordForm> matching_items; | 1856 ScopedVector<PasswordForm> matching_items; |
1819 EXPECT_TRUE(login_db()->GetLogins(form1, &matching_items)); | 1857 EXPECT_TRUE(login_db()->GetLogins(form1, &matching_items)); |
1820 ASSERT_EQ(1u, matching_items.size()); | 1858 ASSERT_EQ(1u, matching_items.size()); |
1821 EXPECT_EQ(form1, *matching_items[0]); | 1859 EXPECT_EQ(form1, *matching_items[0]); |
1822 } | 1860 } |
1823 | 1861 |
1824 // Try to import while the Keychain is locked but the encryption key had been | 1862 // Try to import while the Keychain is locked but the encryption key had been |
1825 // read earlier. | 1863 // read earlier. |
1826 TEST_F(PasswordStoreMacTest, ImportFromLockedKeychainError) { | 1864 TEST_F(PasswordStoreMacTest, ImportFromLockedKeychainError) { |
1827 PasswordForm form1; | 1865 PasswordForm form1; |
1828 form1.origin = GURL("http://accounts.google.com/LoginAuth"); | 1866 form1.origin = GURL("http://accounts.google.com/LoginAuth"); |
1829 form1.signon_realm = "http://accounts.google.com/"; | 1867 form1.signon_realm = "http://accounts.google.com/"; |
1830 form1.username_value = ASCIIToUTF16("my_username"); | 1868 form1.username_value = ASCIIToUTF16("my_username"); |
1831 form1.password_value = ASCIIToUTF16("my_password"); | 1869 form1.password_value = ASCIIToUTF16("my_password"); |
1832 store()->AddLogin(form1); | 1870 store()->AddLogin(form1); |
1833 FinishAsyncProcessing(); | 1871 delegate_.FinishAsyncProcessing(); |
1834 | 1872 |
1835 // Add a second keychain item matching the Database entry. | 1873 // Add a second keychain item matching the Database entry. |
1836 PasswordForm form2 = form1; | 1874 PasswordForm form2 = form1; |
1837 form2.origin = GURL("http://accounts.google.com/Login"); | 1875 form2.origin = GURL("http://accounts.google.com/Login"); |
1838 form2.password_value = ASCIIToUTF16("1234"); | 1876 form2.password_value = ASCIIToUTF16("1234"); |
1839 MacKeychainPasswordFormAdapter adapter(keychain()); | 1877 MacKeychainPasswordFormAdapter adapter(keychain()); |
1840 EXPECT_TRUE(adapter.AddPassword(form2)); | 1878 EXPECT_TRUE(adapter.AddPassword(form2)); |
1841 | 1879 |
1842 keychain()->set_locked(true); | 1880 keychain()->set_locked(true); |
1843 ASSERT_TRUE(base::PostTaskAndReplyWithResult( | 1881 ASSERT_TRUE(base::PostTaskAndReplyWithResult( |
1844 thread_->task_runner().get(), FROM_HERE, | 1882 delegate_.thread()->task_runner().get(), FROM_HERE, |
1845 base::Bind(&PasswordStoreMac::ImportFromKeychain, store()), | 1883 base::Bind(&PasswordStoreMac::ImportFromKeychain, store()), |
1846 base::Bind(&CheckMigrationResult, PasswordStoreMac::KEYCHAIN_BLOCKED))); | 1884 base::Bind(&CheckMigrationResult, PasswordStoreMac::KEYCHAIN_BLOCKED))); |
1847 FinishAsyncProcessing(); | 1885 delegate_.FinishAsyncProcessing(); |
1848 | 1886 |
1849 ScopedVector<PasswordForm> matching_items; | 1887 ScopedVector<PasswordForm> matching_items; |
1850 EXPECT_TRUE(login_db()->GetLogins(form1, &matching_items)); | 1888 EXPECT_TRUE(login_db()->GetLogins(form1, &matching_items)); |
1851 ASSERT_EQ(1u, matching_items.size()); | 1889 ASSERT_EQ(1u, matching_items.size()); |
1852 EXPECT_EQ(base::string16(), matching_items[0]->password_value); | 1890 EXPECT_EQ(base::string16(), matching_items[0]->password_value); |
1853 | 1891 |
1854 histogram_tester_->ExpectUniqueSample( | 1892 histogram_tester_->ExpectUniqueSample( |
1855 "PasswordManager.KeychainMigration.NumPasswordsOnFailure", 1, 1); | 1893 "PasswordManager.KeychainMigration.NumPasswordsOnFailure", 1, 1); |
1856 histogram_tester_->ExpectUniqueSample( | 1894 histogram_tester_->ExpectUniqueSample( |
1857 "PasswordManager.KeychainMigration.NumFailedPasswords", 1, 1); | 1895 "PasswordManager.KeychainMigration.NumFailedPasswords", 1, 1); |
1858 histogram_tester_->ExpectUniqueSample( | 1896 histogram_tester_->ExpectUniqueSample( |
1859 "PasswordManager.KeychainMigration.NumChromeOwnedInaccessiblePasswords", | 1897 "PasswordManager.KeychainMigration.NumChromeOwnedInaccessiblePasswords", |
1860 2, 1); | 1898 2, 1); |
1861 // Don't test the encryption key access. | 1899 // Don't test the encryption key access. |
1862 histogram_tester_.reset(); | 1900 histogram_tester_.reset(); |
1863 } | 1901 } |
OLD | NEW |