OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/gtest/include/gtest/gtest.h" | 6 #include "testing/gtest/include/gtest/gtest.h" |
6 | 7 |
7 #include "base/basictypes.h" | 8 #include "base/basictypes.h" |
| 9 #include "base/file_util.h" |
| 10 #include "base/path_service.h" |
| 11 #include "base/scoped_temp_dir.h" |
8 #include "base/stl_util-inl.h" | 12 #include "base/stl_util-inl.h" |
9 #include "base/string_util.h" | 13 #include "base/string_util.h" |
10 #include "base/utf_string_conversions.h" | 14 #include "base/utf_string_conversions.h" |
| 15 #include "chrome/browser/chrome_thread.h" |
11 #include "chrome/browser/keychain_mock_mac.h" | 16 #include "chrome/browser/keychain_mock_mac.h" |
12 #include "chrome/browser/password_manager/password_store_mac.h" | 17 #include "chrome/browser/password_manager/password_store_mac.h" |
13 #include "chrome/browser/password_manager/password_store_mac_internal.h" | 18 #include "chrome/browser/password_manager/password_store_mac_internal.h" |
| 19 #include "chrome/common/chrome_paths.h" |
14 | 20 |
15 using webkit_glue::PasswordForm; | 21 using webkit_glue::PasswordForm; |
| 22 using testing::_; |
| 23 using testing::DoAll; |
| 24 using testing::WithArg; |
16 | 25 |
17 class PasswordStoreMacTest : public testing::Test { | 26 namespace { |
| 27 |
| 28 class MockPasswordStoreConsumer : public PasswordStoreConsumer { |
| 29 public: |
| 30 MOCK_METHOD2(OnPasswordStoreRequestDone, |
| 31 void(int, const std::vector<webkit_glue::PasswordForm*>&)); |
| 32 }; |
| 33 |
| 34 ACTION(STLDeleteElements0) { |
| 35 STLDeleteContainerPointers(arg0.begin(), arg0.end()); |
| 36 } |
| 37 |
| 38 ACTION(QuitUIMessageLoop) { |
| 39 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
| 40 MessageLoop::current()->Quit(); |
| 41 } |
| 42 |
| 43 } // namespace |
| 44 |
| 45 #pragma mark - |
| 46 |
| 47 class PasswordStoreMacInternalsTest : public testing::Test { |
18 public: | 48 public: |
19 virtual void SetUp() { | 49 virtual void SetUp() { |
20 MockKeychain::KeychainTestData test_data[] = { | 50 MockKeychain::KeychainTestData test_data[] = { |
21 // Basic HTML form. | 51 // Basic HTML form. |
22 { kSecAuthenticationTypeHTMLForm, "some.domain.com", | 52 { kSecAuthenticationTypeHTMLForm, "some.domain.com", |
23 kSecProtocolTypeHTTP, NULL, 0, NULL, "20020601171500Z", | 53 kSecProtocolTypeHTTP, NULL, 0, NULL, "20020601171500Z", |
24 "joe_user", "sekrit", false }, | 54 "joe_user", "sekrit", false }, |
25 // HTML form with path. | 55 // HTML form with path. |
26 { kSecAuthenticationTypeHTMLForm, "some.domain.com", | 56 { kSecAuthenticationTypeHTMLForm, "some.domain.com", |
27 kSecProtocolTypeHTTP, "/insecure.html", 0, NULL, "19991231235959Z", | 57 kSecProtocolTypeHTTP, "/insecure.html", 0, NULL, "19991231235959Z", |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 } | 216 } |
187 EXPECT_EQ(expectation->preferred, form->preferred) << test_label; | 217 EXPECT_EQ(expectation->preferred, form->preferred) << test_label; |
188 EXPECT_EQ(expectation->ssl_valid, form->ssl_valid) << test_label; | 218 EXPECT_EQ(expectation->ssl_valid, form->ssl_valid) << test_label; |
189 EXPECT_DOUBLE_EQ(expectation->creation_time, | 219 EXPECT_DOUBLE_EQ(expectation->creation_time, |
190 form->date_created.ToDoubleT()) << test_label; | 220 form->date_created.ToDoubleT()) << test_label; |
191 } | 221 } |
192 } | 222 } |
193 | 223 |
194 #pragma mark - | 224 #pragma mark - |
195 | 225 |
196 TEST_F(PasswordStoreMacTest, TestKeychainToFormTranslation) { | 226 TEST_F(PasswordStoreMacInternalsTest, TestKeychainToFormTranslation) { |
197 typedef struct { | 227 typedef struct { |
198 const PasswordForm::Scheme scheme; | 228 const PasswordForm::Scheme scheme; |
199 const char* signon_realm; | 229 const char* signon_realm; |
200 const char* origin; | 230 const char* origin; |
201 const wchar_t* username; // Set to NULL to check for a blacklist entry. | 231 const wchar_t* username; // Set to NULL to check for a blacklist entry. |
202 const wchar_t* password; | 232 const wchar_t* password; |
203 const bool ssl_valid; | 233 const bool ssl_valid; |
204 const int creation_year; | 234 const int creation_year; |
205 const int creation_month; | 235 const int creation_month; |
206 const int creation_day; | 236 const int creation_day; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 { | 314 { |
285 // Use an invalid ref, to make sure errors are reported. | 315 // Use an invalid ref, to make sure errors are reported. |
286 SecKeychainItemRef keychain_item = reinterpret_cast<SecKeychainItemRef>(99); | 316 SecKeychainItemRef keychain_item = reinterpret_cast<SecKeychainItemRef>(99); |
287 PasswordForm form; | 317 PasswordForm form; |
288 bool parsed = internal_keychain_helpers::FillPasswordFormFromKeychainItem( | 318 bool parsed = internal_keychain_helpers::FillPasswordFormFromKeychainItem( |
289 *keychain_, keychain_item, &form); | 319 *keychain_, keychain_item, &form); |
290 EXPECT_FALSE(parsed); | 320 EXPECT_FALSE(parsed); |
291 } | 321 } |
292 } | 322 } |
293 | 323 |
294 TEST_F(PasswordStoreMacTest, TestKeychainSearch) { | 324 TEST_F(PasswordStoreMacInternalsTest, TestKeychainSearch) { |
295 struct TestDataAndExpectation { | 325 struct TestDataAndExpectation { |
296 const PasswordFormData data; | 326 const PasswordFormData data; |
297 const size_t expected_fill_matches; | 327 const size_t expected_fill_matches; |
298 const size_t expected_merge_matches; | 328 const size_t expected_merge_matches; |
299 }; | 329 }; |
300 // Most fields are left blank because we don't care about them for searching. | 330 // Most fields are left blank because we don't care about them for searching. |
301 TestDataAndExpectation test_data[] = { | 331 TestDataAndExpectation test_data[] = { |
302 // An HTML form we've seen. | 332 // An HTML form we've seen. |
303 { { PasswordForm::SCHEME_HTML, "http://some.domain.com/", | 333 { { PasswordForm::SCHEME_HTML, "http://some.domain.com/", |
304 NULL, NULL, NULL, NULL, NULL, L"joe_user", NULL, false, false, 0 }, | 334 NULL, NULL, NULL, NULL, NULL, L"joe_user", NULL, false, false, 0 }, |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
345 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { | 375 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { |
346 scoped_ptr<PasswordForm> query_form( | 376 scoped_ptr<PasswordForm> query_form( |
347 CreatePasswordFormFromData(test_data[i].data)); | 377 CreatePasswordFormFromData(test_data[i].data)); |
348 | 378 |
349 // Check matches treating the form as a fill target. | 379 // Check matches treating the form as a fill target. |
350 std::vector<PasswordForm*> matching_items = | 380 std::vector<PasswordForm*> matching_items = |
351 keychain_adapter.PasswordsFillingForm(*query_form); | 381 keychain_adapter.PasswordsFillingForm(*query_form); |
352 EXPECT_EQ(test_data[i].expected_fill_matches, matching_items.size()); | 382 EXPECT_EQ(test_data[i].expected_fill_matches, matching_items.size()); |
353 STLDeleteElements(&matching_items); | 383 STLDeleteElements(&matching_items); |
354 | 384 |
355 // Check matches teating the form as a merging target. | 385 // Check matches treating the form as a merging target. |
| 386 EXPECT_EQ(test_data[i].expected_merge_matches > 0, |
| 387 keychain_adapter.HasPasswordsMergeableWithForm(*query_form)); |
356 matching_items = keychain_adapter.PasswordsMergeableWithForm(*query_form); | 388 matching_items = keychain_adapter.PasswordsMergeableWithForm(*query_form); |
357 EXPECT_EQ(test_data[i].expected_merge_matches, matching_items.size()); | 389 EXPECT_EQ(test_data[i].expected_merge_matches, matching_items.size()); |
358 STLDeleteElements(&matching_items); | 390 STLDeleteElements(&matching_items); |
359 | 391 |
360 // None of the pre-seeded items are owned by us, so none should match an | 392 // None of the pre-seeded items are owned by us, so none should match an |
361 // owned-passwords-only search. | 393 // owned-passwords-only search. |
362 matching_items = owned_keychain_adapter.PasswordsFillingForm(*query_form); | 394 matching_items = owned_keychain_adapter.PasswordsFillingForm(*query_form); |
363 EXPECT_EQ(0U, matching_items.size()); | 395 EXPECT_EQ(0U, matching_items.size()); |
364 STLDeleteElements(&matching_items); | 396 STLDeleteElements(&matching_items); |
365 } | 397 } |
(...skipping 18 matching lines...) Expand all Loading... |
384 | 416 |
385 // Changes just the signon_ream auth realm of |form|. | 417 // Changes just the signon_ream auth realm of |form|. |
386 static void SetPasswordFormRealm(PasswordForm* form, const char* realm) { | 418 static void SetPasswordFormRealm(PasswordForm* form, const char* realm) { |
387 GURL::Replacements replacement; | 419 GURL::Replacements replacement; |
388 std::string new_value(realm); | 420 std::string new_value(realm); |
389 replacement.SetPathStr(new_value); | 421 replacement.SetPathStr(new_value); |
390 GURL signon_gurl = GURL(form->signon_realm); | 422 GURL signon_gurl = GURL(form->signon_realm); |
391 form->signon_realm = signon_gurl.ReplaceComponents(replacement).spec(); | 423 form->signon_realm = signon_gurl.ReplaceComponents(replacement).spec(); |
392 } | 424 } |
393 | 425 |
394 TEST_F(PasswordStoreMacTest, TestKeychainExactSearch) { | 426 TEST_F(PasswordStoreMacInternalsTest, TestKeychainExactSearch) { |
395 MacKeychainPasswordFormAdapter keychain_adapter(keychain_); | 427 MacKeychainPasswordFormAdapter keychain_adapter(keychain_); |
396 | 428 |
397 PasswordFormData base_form_data[] = { | 429 PasswordFormData base_form_data[] = { |
398 { PasswordForm::SCHEME_HTML, "http://some.domain.com/", | 430 { PasswordForm::SCHEME_HTML, "http://some.domain.com/", |
399 "http://some.domain.com/insecure.html", | 431 "http://some.domain.com/insecure.html", |
400 NULL, NULL, NULL, NULL, L"joe_user", NULL, true, false, 0 }, | 432 NULL, NULL, NULL, NULL, L"joe_user", NULL, true, false, 0 }, |
401 { PasswordForm::SCHEME_BASIC, "http://some.domain.com:4567/low_security", | 433 { PasswordForm::SCHEME_BASIC, "http://some.domain.com:4567/low_security", |
402 "http://some.domain.com:4567/insecure.html", | 434 "http://some.domain.com:4567/insecure.html", |
403 NULL, NULL, NULL, NULL, L"basic_auth_user", NULL, true, false, 0 }, | 435 NULL, NULL, NULL, NULL, L"basic_auth_user", NULL, true, false, 0 }, |
404 { PasswordForm::SCHEME_DIGEST, "https://some.domain.com/high_security", | 436 { PasswordForm::SCHEME_DIGEST, "https://some.domain.com/high_security", |
405 "https://some.domain.com", | 437 "https://some.domain.com", |
406 NULL, NULL, NULL, NULL, L"digest_auth_user", NULL, true, true, 0 }, | 438 NULL, NULL, NULL, NULL, L"digest_auth_user", NULL, true, true, 0 }, |
407 }; | 439 }; |
408 | 440 |
409 for (unsigned int i = 0; i < arraysize(base_form_data); ++i) { | 441 for (unsigned int i = 0; i < arraysize(base_form_data); ++i) { |
410 // Create a base form and make sure we find a match. | 442 // Create a base form and make sure we find a match. |
411 scoped_ptr<PasswordForm> base_form(CreatePasswordFormFromData( | 443 scoped_ptr<PasswordForm> base_form(CreatePasswordFormFromData( |
412 base_form_data[i])); | 444 base_form_data[i])); |
| 445 EXPECT_TRUE(keychain_adapter.HasPasswordsMergeableWithForm(*base_form)); |
413 PasswordForm* match = | 446 PasswordForm* match = |
414 keychain_adapter.PasswordExactlyMatchingForm(*base_form); | 447 keychain_adapter.PasswordExactlyMatchingForm(*base_form); |
415 EXPECT_TRUE(match != NULL); | 448 EXPECT_TRUE(match != NULL); |
416 if (match) { | 449 if (match) { |
417 EXPECT_EQ(base_form->scheme, match->scheme); | 450 EXPECT_EQ(base_form->scheme, match->scheme); |
418 EXPECT_EQ(base_form->origin, match->origin); | 451 EXPECT_EQ(base_form->origin, match->origin); |
419 EXPECT_EQ(base_form->username_value, match->username_value); | 452 EXPECT_EQ(base_form->username_value, match->username_value); |
420 delete match; | 453 delete match; |
421 } | 454 } |
422 | 455 |
(...skipping 25 matching lines...) Expand all Loading... |
448 for (unsigned int j = 0; j < modified_forms.size(); ++j) { | 481 for (unsigned int j = 0; j < modified_forms.size(); ++j) { |
449 PasswordForm* match = | 482 PasswordForm* match = |
450 keychain_adapter.PasswordExactlyMatchingForm(*modified_forms[j]); | 483 keychain_adapter.PasswordExactlyMatchingForm(*modified_forms[j]); |
451 EXPECT_EQ(NULL, match) << "In modified version " << j << " of base form " | 484 EXPECT_EQ(NULL, match) << "In modified version " << j << " of base form " |
452 << i; | 485 << i; |
453 } | 486 } |
454 STLDeleteElements(&modified_forms); | 487 STLDeleteElements(&modified_forms); |
455 } | 488 } |
456 } | 489 } |
457 | 490 |
458 TEST_F(PasswordStoreMacTest, TestKeychainAdd) { | 491 TEST_F(PasswordStoreMacInternalsTest, TestKeychainAdd) { |
459 struct TestDataAndExpectation { | 492 struct TestDataAndExpectation { |
460 PasswordFormData data; | 493 PasswordFormData data; |
461 bool should_succeed; | 494 bool should_succeed; |
462 }; | 495 }; |
463 TestDataAndExpectation test_data[] = { | 496 TestDataAndExpectation test_data[] = { |
464 // Test a variety of scheme/port/protocol/path variations. | 497 // Test a variety of scheme/port/protocol/path variations. |
465 { { PasswordForm::SCHEME_HTML, "http://web.site.com/", | 498 { { PasswordForm::SCHEME_HTML, "http://web.site.com/", |
466 "http://web.site.com/path/to/page.html", NULL, NULL, NULL, NULL, | 499 "http://web.site.com/path/to/page.html", NULL, NULL, NULL, NULL, |
467 L"anonymous", L"knock-knock", false, false, 0 }, true }, | 500 L"anonymous", L"knock-knock", false, false, 0 }, true }, |
468 { { PasswordForm::SCHEME_HTML, "https://web.site.com/", | 501 { { PasswordForm::SCHEME_HTML, "https://web.site.com/", |
(...skipping 18 matching lines...) Expand all Loading... |
487 | 520 |
488 MacKeychainPasswordFormAdapter owned_keychain_adapter(keychain_); | 521 MacKeychainPasswordFormAdapter owned_keychain_adapter(keychain_); |
489 owned_keychain_adapter.SetFindsOnlyOwnedItems(true); | 522 owned_keychain_adapter.SetFindsOnlyOwnedItems(true); |
490 | 523 |
491 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { | 524 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { |
492 scoped_ptr<PasswordForm> in_form( | 525 scoped_ptr<PasswordForm> in_form( |
493 CreatePasswordFormFromData(test_data[i].data)); | 526 CreatePasswordFormFromData(test_data[i].data)); |
494 bool add_succeeded = owned_keychain_adapter.AddPassword(*in_form); | 527 bool add_succeeded = owned_keychain_adapter.AddPassword(*in_form); |
495 EXPECT_EQ(test_data[i].should_succeed, add_succeeded); | 528 EXPECT_EQ(test_data[i].should_succeed, add_succeeded); |
496 if (add_succeeded) { | 529 if (add_succeeded) { |
| 530 EXPECT_TRUE(owned_keychain_adapter.HasPasswordsMergeableWithForm( |
| 531 *in_form)); |
497 scoped_ptr<PasswordForm> out_form( | 532 scoped_ptr<PasswordForm> out_form( |
498 owned_keychain_adapter.PasswordExactlyMatchingForm(*in_form)); | 533 owned_keychain_adapter.PasswordExactlyMatchingForm(*in_form)); |
499 EXPECT_TRUE(out_form.get() != NULL); | 534 EXPECT_TRUE(out_form.get() != NULL); |
500 EXPECT_EQ(out_form->scheme, in_form->scheme); | 535 EXPECT_EQ(out_form->scheme, in_form->scheme); |
501 EXPECT_EQ(out_form->signon_realm, in_form->signon_realm); | 536 EXPECT_EQ(out_form->signon_realm, in_form->signon_realm); |
502 EXPECT_EQ(out_form->origin, in_form->origin); | 537 EXPECT_EQ(out_form->origin, in_form->origin); |
503 EXPECT_EQ(out_form->username_value, in_form->username_value); | 538 EXPECT_EQ(out_form->username_value, in_form->username_value); |
504 EXPECT_EQ(out_form->password_value, in_form->password_value); | 539 EXPECT_EQ(out_form->password_value, in_form->password_value); |
505 } | 540 } |
506 } | 541 } |
(...skipping 10 matching lines...) Expand all Loading... |
517 EXPECT_TRUE(keychain_adapter.AddPassword(*update_form)); | 552 EXPECT_TRUE(keychain_adapter.AddPassword(*update_form)); |
518 SecKeychainItemRef keychain_item = reinterpret_cast<SecKeychainItemRef>(2); | 553 SecKeychainItemRef keychain_item = reinterpret_cast<SecKeychainItemRef>(2); |
519 PasswordForm stored_form; | 554 PasswordForm stored_form; |
520 internal_keychain_helpers::FillPasswordFormFromKeychainItem(*keychain_, | 555 internal_keychain_helpers::FillPasswordFormFromKeychainItem(*keychain_, |
521 keychain_item, | 556 keychain_item, |
522 &stored_form); | 557 &stored_form); |
523 EXPECT_EQ(update_form->password_value, stored_form.password_value); | 558 EXPECT_EQ(update_form->password_value, stored_form.password_value); |
524 } | 559 } |
525 } | 560 } |
526 | 561 |
527 TEST_F(PasswordStoreMacTest, TestKeychainRemove) { | 562 TEST_F(PasswordStoreMacInternalsTest, TestKeychainRemove) { |
528 struct TestDataAndExpectation { | 563 struct TestDataAndExpectation { |
529 PasswordFormData data; | 564 PasswordFormData data; |
530 bool should_succeed; | 565 bool should_succeed; |
531 }; | 566 }; |
532 TestDataAndExpectation test_data[] = { | 567 TestDataAndExpectation test_data[] = { |
533 // Test deletion of an item that we add. | 568 // Test deletion of an item that we add. |
534 { { PasswordForm::SCHEME_HTML, "http://web.site.com/", | 569 { { PasswordForm::SCHEME_HTML, "http://web.site.com/", |
535 "http://web.site.com/path/to/page.html", NULL, NULL, NULL, NULL, | 570 "http://web.site.com/path/to/page.html", NULL, NULL, NULL, NULL, |
536 L"anonymous", L"knock-knock", false, false, 0 }, true }, | 571 L"anonymous", L"knock-knock", false, false, 0 }, true }, |
537 // Make sure we don't delete items we don't own. | 572 // Make sure we don't delete items we don't own. |
(...skipping 18 matching lines...) Expand all Loading... |
556 | 591 |
557 MacKeychainPasswordFormAdapter keychain_adapter(keychain_); | 592 MacKeychainPasswordFormAdapter keychain_adapter(keychain_); |
558 PasswordForm* match = keychain_adapter.PasswordExactlyMatchingForm(*form); | 593 PasswordForm* match = keychain_adapter.PasswordExactlyMatchingForm(*form); |
559 EXPECT_EQ(test_data[i].should_succeed, match == NULL); | 594 EXPECT_EQ(test_data[i].should_succeed, match == NULL); |
560 if (match) { | 595 if (match) { |
561 delete match; | 596 delete match; |
562 } | 597 } |
563 } | 598 } |
564 } | 599 } |
565 | 600 |
566 TEST_F(PasswordStoreMacTest, TestFormMatch) { | 601 TEST_F(PasswordStoreMacInternalsTest, TestFormMatch) { |
567 PasswordForm base_form; | 602 PasswordForm base_form; |
568 base_form.signon_realm = std::string("http://some.domain.com/"); | 603 base_form.signon_realm = std::string("http://some.domain.com/"); |
569 base_form.origin = GURL("http://some.domain.com/page.html"); | 604 base_form.origin = GURL("http://some.domain.com/page.html"); |
570 base_form.username_value = ASCIIToUTF16("joe_user"); | 605 base_form.username_value = ASCIIToUTF16("joe_user"); |
571 | 606 |
572 { | 607 { |
573 // Check that everything unimportant can be changed. | 608 // Check that everything unimportant can be changed. |
574 PasswordForm different_form(base_form); | 609 PasswordForm different_form(base_form); |
575 different_form.username_element = ASCIIToUTF16("username"); | 610 different_form.username_element = ASCIIToUTF16("username"); |
576 different_form.submit_element = ASCIIToUTF16("submit"); | 611 different_form.submit_element = ASCIIToUTF16("submit"); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
618 // Blacklist forms should *never* match for merging, even when identical | 653 // Blacklist forms should *never* match for merging, even when identical |
619 // (and certainly not when only one is a blacklist entry). | 654 // (and certainly not when only one is a blacklist entry). |
620 { | 655 { |
621 PasswordForm form_a(base_form); | 656 PasswordForm form_a(base_form); |
622 form_a.blacklisted_by_user = true; | 657 form_a.blacklisted_by_user = true; |
623 PasswordForm form_b(form_a); | 658 PasswordForm form_b(form_a); |
624 EXPECT_FALSE(internal_keychain_helpers::FormsMatchForMerge(form_a, form_b)); | 659 EXPECT_FALSE(internal_keychain_helpers::FormsMatchForMerge(form_a, form_b)); |
625 } | 660 } |
626 } | 661 } |
627 | 662 |
628 TEST_F(PasswordStoreMacTest, TestFormMerge) { | 663 TEST_F(PasswordStoreMacInternalsTest, TestFormMerge) { |
629 // Set up a bunch of test data to use in varying combinations. | 664 // Set up a bunch of test data to use in varying combinations. |
630 PasswordFormData keychain_user_1 = | 665 PasswordFormData keychain_user_1 = |
631 { PasswordForm::SCHEME_HTML, "http://some.domain.com/", | 666 { PasswordForm::SCHEME_HTML, "http://some.domain.com/", |
632 "http://some.domain.com/", "", L"", L"", L"", L"joe_user", L"sekrit", | 667 "http://some.domain.com/", "", L"", L"", L"", L"joe_user", L"sekrit", |
633 false, false, 1010101010 }; | 668 false, false, 1010101010 }; |
634 PasswordFormData keychain_user_1_with_path = | 669 PasswordFormData keychain_user_1_with_path = |
635 { PasswordForm::SCHEME_HTML, "http://some.domain.com/", | 670 { PasswordForm::SCHEME_HTML, "http://some.domain.com/", |
636 "http://some.domain.com/page.html", | 671 "http://some.domain.com/page.html", |
637 "", L"", L"", L"", L"joe_user", L"otherpassword", | 672 "", L"", L"", L"", L"joe_user", L"otherpassword", |
638 false, false, 1010101010 }; | 673 false, false, 1010101010 }; |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
773 CHECK_FORMS(database_forms, test_data[DATABASE_OUTPUT][test_case], | 808 CHECK_FORMS(database_forms, test_data[DATABASE_OUTPUT][test_case], |
774 test_case); | 809 test_case); |
775 CHECK_FORMS(merged_forms, test_data[MERGE_OUTPUT][test_case], test_case); | 810 CHECK_FORMS(merged_forms, test_data[MERGE_OUTPUT][test_case], test_case); |
776 | 811 |
777 STLDeleteElements(&keychain_forms); | 812 STLDeleteElements(&keychain_forms); |
778 STLDeleteElements(&database_forms); | 813 STLDeleteElements(&database_forms); |
779 STLDeleteElements(&merged_forms); | 814 STLDeleteElements(&merged_forms); |
780 } | 815 } |
781 } | 816 } |
782 | 817 |
783 TEST_F(PasswordStoreMacTest, TestPasswordBulkLookup) { | 818 TEST_F(PasswordStoreMacInternalsTest, TestPasswordBulkLookup) { |
784 PasswordFormData db_data[] = { | 819 PasswordFormData db_data[] = { |
785 { PasswordForm::SCHEME_HTML, "http://some.domain.com/", | 820 { PasswordForm::SCHEME_HTML, "http://some.domain.com/", |
786 "http://some.domain.com/", "http://some.domain.com/action.cgi", | 821 "http://some.domain.com/", "http://some.domain.com/action.cgi", |
787 L"submit", L"username", L"password", L"joe_user", L"", | 822 L"submit", L"username", L"password", L"joe_user", L"", |
788 true, false, 1212121212 }, | 823 true, false, 1212121212 }, |
789 { PasswordForm::SCHEME_HTML, "http://some.domain.com/", | 824 { PasswordForm::SCHEME_HTML, "http://some.domain.com/", |
790 "http://some.domain.com/page.html", | 825 "http://some.domain.com/page.html", |
791 "http://some.domain.com/handlepage.cgi", | 826 "http://some.domain.com/handlepage.cgi", |
792 L"submit", L"username", L"password", L"joe_user", L"", | 827 L"submit", L"username", L"password", L"joe_user", L"", |
793 true, false, 1234567890 }, | 828 true, false, 1234567890 }, |
(...skipping 22 matching lines...) Expand all Loading... |
816 EXPECT_EQ(2U, database_forms.size()); | 851 EXPECT_EQ(2U, database_forms.size()); |
817 ASSERT_EQ(3U, merged_forms.size()); | 852 ASSERT_EQ(3U, merged_forms.size()); |
818 EXPECT_EQ(ASCIIToUTF16("sekrit"), merged_forms[0]->password_value); | 853 EXPECT_EQ(ASCIIToUTF16("sekrit"), merged_forms[0]->password_value); |
819 EXPECT_EQ(ASCIIToUTF16("sekrit"), merged_forms[1]->password_value); | 854 EXPECT_EQ(ASCIIToUTF16("sekrit"), merged_forms[1]->password_value); |
820 EXPECT_EQ(true, merged_forms[2]->blacklisted_by_user); | 855 EXPECT_EQ(true, merged_forms[2]->blacklisted_by_user); |
821 | 856 |
822 STLDeleteElements(&database_forms); | 857 STLDeleteElements(&database_forms); |
823 STLDeleteElements(&merged_forms); | 858 STLDeleteElements(&merged_forms); |
824 } | 859 } |
825 | 860 |
826 TEST_F(PasswordStoreMacTest, TestPasswordGetAll) { | 861 TEST_F(PasswordStoreMacInternalsTest, TestPasswordGetAll) { |
827 MacKeychainPasswordFormAdapter keychain_adapter(keychain_); | 862 MacKeychainPasswordFormAdapter keychain_adapter(keychain_); |
828 MacKeychainPasswordFormAdapter owned_keychain_adapter(keychain_); | 863 MacKeychainPasswordFormAdapter owned_keychain_adapter(keychain_); |
829 owned_keychain_adapter.SetFindsOnlyOwnedItems(true); | 864 owned_keychain_adapter.SetFindsOnlyOwnedItems(true); |
830 | 865 |
831 // Add a few passwords of various types so that we own some. | 866 // Add a few passwords of various types so that we own some. |
832 PasswordFormData owned_password_data[] = { | 867 PasswordFormData owned_password_data[] = { |
833 { PasswordForm::SCHEME_HTML, "http://web.site.com/", | 868 { PasswordForm::SCHEME_HTML, "http://web.site.com/", |
834 "http://web.site.com/path/to/page.html", NULL, NULL, NULL, NULL, | 869 "http://web.site.com/path/to/page.html", NULL, NULL, NULL, NULL, |
835 L"anonymous", L"knock-knock", false, false, 0 }, | 870 L"anonymous", L"knock-knock", false, false, 0 }, |
836 { PasswordForm::SCHEME_BASIC, "http://a.site.com:2222/therealm", | 871 { PasswordForm::SCHEME_BASIC, "http://a.site.com:2222/therealm", |
(...skipping 12 matching lines...) Expand all Loading... |
849 std::vector<PasswordForm*> all_passwords = | 884 std::vector<PasswordForm*> all_passwords = |
850 keychain_adapter.GetAllPasswordFormPasswords(); | 885 keychain_adapter.GetAllPasswordFormPasswords(); |
851 EXPECT_EQ(8 + arraysize(owned_password_data), all_passwords.size()); | 886 EXPECT_EQ(8 + arraysize(owned_password_data), all_passwords.size()); |
852 STLDeleteElements(&all_passwords); | 887 STLDeleteElements(&all_passwords); |
853 | 888 |
854 std::vector<PasswordForm*> owned_passwords = | 889 std::vector<PasswordForm*> owned_passwords = |
855 owned_keychain_adapter.GetAllPasswordFormPasswords(); | 890 owned_keychain_adapter.GetAllPasswordFormPasswords(); |
856 EXPECT_EQ(arraysize(owned_password_data), owned_passwords.size()); | 891 EXPECT_EQ(arraysize(owned_password_data), owned_passwords.size()); |
857 STLDeleteElements(&owned_passwords); | 892 STLDeleteElements(&owned_passwords); |
858 } | 893 } |
| 894 |
| 895 #pragma mark - |
| 896 |
| 897 class PasswordStoreMacTest : public testing::Test { |
| 898 public: |
| 899 PasswordStoreMacTest() : ui_thread_(ChromeThread::UI, &message_loop_) {} |
| 900 |
| 901 virtual void SetUp() { |
| 902 login_db_ = new LoginDatabase(); |
| 903 ASSERT_TRUE(db_dir_.CreateUniqueTempDir()); |
| 904 FilePath db_file = db_dir_.path().AppendASCII("login.db"); |
| 905 ASSERT_TRUE(login_db_->Init(db_file)); |
| 906 |
| 907 keychain_ = new MockKeychain(3); |
| 908 |
| 909 store_ = new PasswordStoreMac(keychain_, login_db_); |
| 910 ASSERT_TRUE(store_->Init()); |
| 911 } |
| 912 |
| 913 virtual void TearDown() { |
| 914 MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask); |
| 915 MessageLoop::current()->Run(); |
| 916 } |
| 917 |
| 918 protected: |
| 919 MessageLoopForUI message_loop_; |
| 920 ChromeThread ui_thread_; |
| 921 |
| 922 MockKeychain* keychain_; // Owned by store_. |
| 923 LoginDatabase* login_db_; // Owned by store_. |
| 924 scoped_refptr<PasswordStoreMac> store_; |
| 925 ScopedTempDir db_dir_; |
| 926 }; |
| 927 |
| 928 TEST_F(PasswordStoreMacTest, TestStoreUpdate) { |
| 929 // Insert a password into both the database and the keychain. |
| 930 // This is done manually, rather than through store_->AddLogin, because the |
| 931 // Mock Keychain isn't smart enough to be able to support update generically, |
| 932 // so some.domain.com triggers special handling to test it that make inserting |
| 933 // fail. |
| 934 PasswordFormData joint_data = { |
| 935 PasswordForm::SCHEME_HTML, "http://some.domain.com/", |
| 936 "http://some.domain.com/insecure.html", "login.cgi", |
| 937 L"username", L"password", L"submit", L"joe_user", L"sekrit", true, false, 1 |
| 938 }; |
| 939 scoped_ptr<PasswordForm> joint_form(CreatePasswordFormFromData(joint_data)); |
| 940 login_db_->AddLogin(*joint_form); |
| 941 MockKeychain::KeychainTestData joint_keychain_data = { |
| 942 kSecAuthenticationTypeHTMLForm, "some.domain.com", |
| 943 kSecProtocolTypeHTTP, "/insecure.html", 0, NULL, "20020601171500Z", |
| 944 "joe_user", "sekrit", false }; |
| 945 keychain_->AddTestItem(joint_keychain_data); |
| 946 |
| 947 // Insert a password into the keychain only. |
| 948 MockKeychain::KeychainTestData keychain_only_data = { |
| 949 kSecAuthenticationTypeHTMLForm, "keychain.only.com", |
| 950 kSecProtocolTypeHTTP, NULL, 0, NULL, "20020601171500Z", |
| 951 "keychain", "only", false |
| 952 }; |
| 953 keychain_->AddTestItem(keychain_only_data); |
| 954 |
| 955 struct UpdateData { |
| 956 PasswordFormData form_data; |
| 957 const char* password; // NULL indicates no entry should be present. |
| 958 }; |
| 959 |
| 960 // Make a series of update calls. |
| 961 UpdateData updates[] = { |
| 962 // Update the keychain+db passwords (the normal password update case). |
| 963 { { PasswordForm::SCHEME_HTML, "http://some.domain.com/", |
| 964 "http://some.domain.com/insecure.html", "login.cgi", |
| 965 L"username", L"password", L"submit", L"joe_user", L"53krit", |
| 966 true, false, 2 }, |
| 967 "53krit", |
| 968 }, |
| 969 // Update the keychain-only password; this simulates the initial use of a |
| 970 // password stored by another browsers. |
| 971 { { PasswordForm::SCHEME_HTML, "http://keychain.only.com/", |
| 972 "http://keychain.only.com/login.html", "login.cgi", |
| 973 L"username", L"password", L"submit", L"keychain", L"only", |
| 974 true, false, 2 }, |
| 975 "only", |
| 976 }, |
| 977 // Update a password that doesn't exist in either location. This tests the |
| 978 // case where a form is filled, then the stored login is removed, then the |
| 979 // form is submitted. |
| 980 { { PasswordForm::SCHEME_HTML, "http://different.com/", |
| 981 "http://different.com/index.html", "login.cgi", |
| 982 L"username", L"password", L"submit", L"abc", L"123", |
| 983 true, false, 2 }, |
| 984 NULL, |
| 985 }, |
| 986 }; |
| 987 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(updates); ++i) { |
| 988 scoped_ptr<PasswordForm> form(CreatePasswordFormFromData( |
| 989 updates[i].form_data)); |
| 990 store_->UpdateLogin(*form); |
| 991 } |
| 992 |
| 993 // Do a store-level query to wait for all the operations above to be done. |
| 994 MockPasswordStoreConsumer consumer; |
| 995 ON_CALL(consumer, OnPasswordStoreRequestDone(_, _)).WillByDefault( |
| 996 QuitUIMessageLoop()); |
| 997 EXPECT_CALL(consumer, OnPasswordStoreRequestDone(_, _)).WillOnce( |
| 998 DoAll(WithArg<1>(STLDeleteElements0()), QuitUIMessageLoop())); |
| 999 store_->GetLogins(*joint_form, &consumer); |
| 1000 MessageLoop::current()->Run(); |
| 1001 |
| 1002 MacKeychainPasswordFormAdapter keychain_adapter(keychain_); |
| 1003 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(updates); ++i) { |
| 1004 scoped_ptr<PasswordForm> query_form( |
| 1005 CreatePasswordFormFromData(updates[i].form_data)); |
| 1006 |
| 1007 std::vector<PasswordForm*> matching_items = |
| 1008 keychain_adapter.PasswordsFillingForm(*query_form); |
| 1009 if (updates[i].password) { |
| 1010 EXPECT_GT(matching_items.size(), 0U) << "iteration " << i; |
| 1011 if (matching_items.size() >= 1) |
| 1012 EXPECT_EQ(ASCIIToUTF16(updates[i].password), |
| 1013 matching_items[0]->password_value) << "iteration " << i; |
| 1014 } else { |
| 1015 EXPECT_EQ(0U, matching_items.size()) << "iteration " << i; |
| 1016 } |
| 1017 STLDeleteElements(&matching_items); |
| 1018 |
| 1019 login_db_->GetLogins(*query_form, &matching_items); |
| 1020 EXPECT_EQ(updates[i].password ? 1U : 0U, matching_items.size()) |
| 1021 << "iteration " << i; |
| 1022 STLDeleteElements(&matching_items); |
| 1023 } |
| 1024 } |
OLD | NEW |