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 #include "chrome/browser/password_manager/password_store_mac_internal.h" | 6 #include "chrome/browser/password_manager/password_store_mac_internal.h" |
7 | 7 |
8 #include <CoreServices/CoreServices.h> | 8 #include <CoreServices/CoreServices.h> |
9 #include <set> | 9 #include <set> |
10 #include <string> | 10 #include <string> |
11 #include <utility> | 11 #include <utility> |
12 #include <vector> | 12 #include <vector> |
13 | 13 |
14 #include "base/callback.h" | 14 #include "base/callback.h" |
15 #include "base/logging.h" | 15 #include "base/logging.h" |
16 #include "base/mac/foundation_util.h" | 16 #include "base/mac/foundation_util.h" |
17 #include "base/mac/mac_logging.h" | 17 #include "base/mac/mac_logging.h" |
18 #include "base/memory/scoped_vector.h" | |
19 #include "base/message_loop/message_loop.h" | 18 #include "base/message_loop/message_loop.h" |
20 #include "base/stl_util.h" | 19 #include "base/stl_util.h" |
21 #include "base/strings/string_util.h" | 20 #include "base/strings/string_util.h" |
22 #include "base/strings/utf_string_conversions.h" | 21 #include "base/strings/utf_string_conversions.h" |
23 #include "chrome/browser/mac/security_wrappers.h" | 22 #include "chrome/browser/mac/security_wrappers.h" |
24 #include "components/password_manager/core/browser/login_database.h" | 23 #include "components/password_manager/core/browser/login_database.h" |
25 #include "components/password_manager/core/browser/password_store_change.h" | 24 #include "components/password_manager/core/browser/password_store_change.h" |
26 #include "content/public/browser/browser_thread.h" | 25 #include "content/public/browser/browser_thread.h" |
27 #include "crypto/apple_keychain.h" | 26 #include "crypto/apple_keychain.h" |
28 | 27 |
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
411 if (base_form.origin == (*i)->origin) { | 410 if (base_form.origin == (*i)->origin) { |
412 return *i; | 411 return *i; |
413 } else if (!partial_match) { | 412 } else if (!partial_match) { |
414 partial_match = *i; | 413 partial_match = *i; |
415 } | 414 } |
416 } | 415 } |
417 } | 416 } |
418 return partial_match; | 417 return partial_match; |
419 } | 418 } |
420 | 419 |
421 // Returns entries from |forms| that are blacklist entries, after removing | 420 // Moves entries from |forms| that are blacklist entries into |blacklist|. |
422 // them from |forms|. | 421 void ExtractBlacklistForms(ScopedVector<autofill::PasswordForm>* forms, |
423 std::vector<PasswordForm*> ExtractBlacklistForms( | 422 ScopedVector<autofill::PasswordForm>* blacklist) { |
424 std::vector<PasswordForm*>* forms) { | 423 blacklist->reserve(blacklist->size() + forms->size()); |
425 std::vector<PasswordForm*> blacklist_forms; | 424 ScopedVector<autofill::PasswordForm> non_blacklist; |
426 for (std::vector<PasswordForm*>::iterator i = forms->begin(); | 425 for (auto& form : *forms) { |
427 i != forms->end();) { | 426 if (form->blacklisted_by_user) |
428 PasswordForm* form = *i; | 427 blacklist->push_back(form); |
429 if (form->blacklisted_by_user) { | 428 else |
430 blacklist_forms.push_back(form); | 429 non_blacklist.push_back(form); |
431 i = forms->erase(i); | 430 form = nullptr; |
vasilii
2015/01/27 20:45:51
you could weak_clear |forms| instead.
vabr (Chromium)
2015/01/28 13:27:36
I could, but that extends the period of time when
vasilii
2015/01/28 15:09:03
It's performance related. You know that |forms| co
vabr (Chromium)
2015/01/28 16:36:27
To record our offline discussion: a benchmark run
| |
432 } else { | |
433 ++i; | |
434 } | |
435 } | 431 } |
436 return blacklist_forms; | 432 forms->swap(non_blacklist); |
437 } | 433 } |
438 | 434 |
439 // Deletes and removes from v any element that exists in s. | 435 // Takes |keychain_forms| and |database_forms| and moves the following 2 types |
440 template <class T> | 436 // of forms to |merged_forms|: (1) blacklisted |database_forms|, (2) |
441 void DeleteVectorElementsInSet(std::vector<T*>* v, const std::set<T*>& s) { | 437 // |database_forms| which have a corresponding entry in |keychain_forms|. The |
442 for (typename std::vector<T*>::iterator i = v->begin(); i != v->end();) { | 438 // database forms of type (2) have their password value updated from the |
443 T* element = *i; | 439 // corresponding keychain form, and all the keychain forms corresponding to some |
444 if (s.find(element) != s.end()) { | 440 // database form are removed from |keychain_forms| and deleted. |
445 delete element; | 441 void MergePasswordForms(ScopedVector<autofill::PasswordForm>* keychain_forms, |
446 i = v->erase(i); | 442 ScopedVector<autofill::PasswordForm>* database_forms, |
447 } else { | 443 ScopedVector<autofill::PasswordForm>* merged_forms) { |
448 ++i; | |
449 } | |
450 } | |
451 } | |
452 | |
453 void MergePasswordForms(std::vector<PasswordForm*>* keychain_forms, | |
454 std::vector<PasswordForm*>* database_forms, | |
455 std::vector<PasswordForm*>* merged_forms) { | |
456 // Pull out the database blacklist items, since they are used as-is rather | 444 // Pull out the database blacklist items, since they are used as-is rather |
457 // than being merged with keychain forms. | 445 // than being merged with keychain forms. |
458 std::vector<PasswordForm*> database_blacklist_forms = | 446 ExtractBlacklistForms(database_forms, merged_forms); |
459 ExtractBlacklistForms(database_forms); | |
460 | 447 |
461 // Merge the normal entries. | 448 // Merge the normal entries. |
462 std::set<PasswordForm*> used_keychain_forms; | 449 ScopedVector<autofill::PasswordForm> unused_database_forms; |
463 for (std::vector<PasswordForm*>::iterator i = database_forms->begin(); | 450 unused_database_forms.reserve(database_forms->size()); |
464 i != database_forms->end();) { | 451 std::set<autofill::PasswordForm*> used_keychain_forms; |
465 PasswordForm* db_form = *i; | 452 for (auto& db_form : *database_forms) { |
466 PasswordForm* best_match = BestKeychainFormForForm(*db_form, | 453 PasswordForm* best_match = |
467 keychain_forms); | 454 BestKeychainFormForForm(*db_form, &keychain_forms->get()); |
468 if (best_match) { | 455 if (best_match) { |
469 used_keychain_forms.insert(best_match); | 456 used_keychain_forms.insert(best_match); |
470 db_form->password_value = best_match->password_value; | 457 db_form->password_value = best_match->password_value; |
471 merged_forms->push_back(db_form); | 458 merged_forms->push_back(db_form); |
472 i = database_forms->erase(i); | |
473 } else { | 459 } else { |
474 ++i; | 460 unused_database_forms.push_back(db_form); |
461 } | |
462 db_form = nullptr; | |
vasilii
2015/01/27 20:45:51
again I'd prefer weak_clear.
vabr (Chromium)
2015/01/28 13:27:35
Please see my response above.
| |
463 } | |
464 database_forms->swap(unused_database_forms); | |
465 | |
466 // Clear out all the Keychain entries we used. | |
467 ScopedVector<autofill::PasswordForm> unused_keychain_forms; | |
468 unused_keychain_forms.reserve(keychain_forms->size()); | |
469 for (auto& keychain_form : *keychain_forms) { | |
470 if (!ContainsKey(used_keychain_forms, keychain_form)) { | |
471 using std::swap; | |
vasilii
2015/01/27 20:45:51
excessive here.
vabr (Chromium)
2015/01/28 13:27:35
Done.
| |
472 unused_keychain_forms.push_back(nullptr); | |
473 swap(keychain_form, unused_keychain_forms.back()); | |
vasilii
2015/01/27 20:45:51
It's easier to understand
unused_keychain_forms.p
vabr (Chromium)
2015/01/28 13:27:36
Agreed. This was an overlooked relic from a past p
| |
475 } | 474 } |
476 } | 475 } |
477 | 476 keychain_forms->swap(unused_keychain_forms); |
478 // Add in the blacklist entries from the database. | |
479 merged_forms->insert(merged_forms->end(), | |
480 database_blacklist_forms.begin(), | |
481 database_blacklist_forms.end()); | |
482 | |
483 // Clear out all the Keychain entries we used. | |
484 DeleteVectorElementsInSet(keychain_forms, used_keychain_forms); | |
485 } | 477 } |
486 | 478 |
487 std::vector<ItemFormPair> ExtractAllKeychainItemAttributesIntoPasswordForms( | 479 std::vector<ItemFormPair> ExtractAllKeychainItemAttributesIntoPasswordForms( |
488 std::vector<SecKeychainItemRef>* keychain_items, | 480 std::vector<SecKeychainItemRef>* keychain_items, |
489 const AppleKeychain& keychain) { | 481 const AppleKeychain& keychain) { |
490 DCHECK(keychain_items); | 482 DCHECK(keychain_items); |
491 MacKeychainPasswordFormAdapter keychain_adapter(&keychain); | 483 MacKeychainPasswordFormAdapter keychain_adapter(&keychain); |
492 *keychain_items = keychain_adapter.GetAllPasswordFormKeychainItems(); | 484 *keychain_items = keychain_adapter.GetAllPasswordFormKeychainItems(); |
493 std::vector<ItemFormPair> item_form_pairs; | 485 std::vector<ItemFormPair> item_form_pairs; |
494 for (std::vector<SecKeychainItemRef>::iterator i = keychain_items->begin(); | 486 for (std::vector<SecKeychainItemRef>::iterator i = keychain_items->begin(); |
495 i != keychain_items->end(); ++i) { | 487 i != keychain_items->end(); ++i) { |
496 PasswordForm* form_without_password = new PasswordForm(); | 488 PasswordForm* form_without_password = new PasswordForm(); |
497 internal_keychain_helpers::FillPasswordFormFromKeychainItem( | 489 internal_keychain_helpers::FillPasswordFormFromKeychainItem( |
498 keychain, | 490 keychain, |
499 *i, | 491 *i, |
500 form_without_password, | 492 form_without_password, |
501 false); // Load password attributes, but not password data. | 493 false); // Load password attributes, but not password data. |
502 item_form_pairs.push_back(std::make_pair(&(*i), form_without_password)); | 494 item_form_pairs.push_back(std::make_pair(&(*i), form_without_password)); |
503 } | 495 } |
504 return item_form_pairs; | 496 return item_form_pairs; |
505 } | 497 } |
506 | 498 |
507 std::vector<PasswordForm*> GetPasswordsForForms( | 499 void GetPasswordsForForms(const AppleKeychain& keychain, |
508 const AppleKeychain& keychain, | 500 ScopedVector<autofill::PasswordForm>* database_forms, |
509 std::vector<PasswordForm*>* database_forms) { | 501 ScopedVector<autofill::PasswordForm>* passwords) { |
510 // First load the attributes of all items in the keychain without loading | 502 // First load the attributes of all items in the keychain without loading |
511 // their password data, and then match items in |database_forms| against them. | 503 // their password data, and then match items in |database_forms| against them. |
512 // This avoids individually searching through the keychain for passwords | 504 // This avoids individually searching through the keychain for passwords |
513 // matching each form in |database_forms|, and results in a significant | 505 // matching each form in |database_forms|, and results in a significant |
514 // performance gain, replacing O(N) keychain search operations with a single | 506 // performance gain, replacing O(N) keychain search operations with a single |
515 // operation that loads all keychain items, and then selective reads of only | 507 // operation that loads all keychain items, and then selective reads of only |
516 // the relevant passwords. See crbug.com/263685. | 508 // the relevant passwords. See crbug.com/263685. |
517 std::vector<SecKeychainItemRef> keychain_items; | 509 std::vector<SecKeychainItemRef> keychain_items; |
518 std::vector<ItemFormPair> item_form_pairs = | 510 std::vector<ItemFormPair> item_form_pairs = |
519 ExtractAllKeychainItemAttributesIntoPasswordForms(&keychain_items, | 511 ExtractAllKeychainItemAttributesIntoPasswordForms(&keychain_items, |
520 keychain); | 512 keychain); |
521 | 513 |
522 // Next, compare the attributes of the PasswordForms in |database_forms| | 514 // Next, compare the attributes of the PasswordForms in |database_forms| |
523 // against those in |item_form_pairs|, and extract password data for each | 515 // against those in |item_form_pairs|, and extract password data for each |
524 // matching PasswordForm using its corresponding SecKeychainItemRef. | 516 // matching PasswordForm using its corresponding SecKeychainItemRef. |
525 std::vector<PasswordForm*> merged_forms; | 517 ScopedVector<autofill::PasswordForm> unused_db_forms; |
526 for (std::vector<PasswordForm*>::iterator i = database_forms->begin(); | 518 unused_db_forms.reserve(database_forms->size()); |
527 i != database_forms->end();) { | 519 for (auto& db_form : *database_forms) { |
528 std::vector<PasswordForm*> db_form_container(1, *i); | 520 ScopedVector<autofill::PasswordForm> keychain_matches; |
529 std::vector<PasswordForm*> keychain_matches = | 521 ExtractPasswordsMergeableWithForm(keychain, item_form_pairs, *db_form, |
530 ExtractPasswordsMergeableWithForm(keychain, item_form_pairs, **i); | 522 &keychain_matches); |
531 MergePasswordForms(&keychain_matches, &db_form_container, &merged_forms); | 523 |
532 if (db_form_container.empty()) { | 524 ScopedVector<autofill::PasswordForm> db_form_container; |
533 i = database_forms->erase(i); | 525 db_form_container.push_back(db_form); |
534 } else { | 526 db_form = nullptr; |
vasilii
2015/01/27 20:45:51
I think weak_clear is better here.
vabr (Chromium)
2015/01/28 13:27:35
Please see my answer above.
| |
535 ++i; | 527 MergePasswordForms(&keychain_matches, &db_form_container, passwords); |
536 } | 528 unused_db_forms.insert(unused_db_forms.end(), db_form_container.begin(), |
537 STLDeleteElements(&keychain_matches); | 529 db_form_container.end()); |
530 db_form_container.weak_clear(); | |
538 } | 531 } |
532 database_forms->swap(unused_db_forms); | |
539 | 533 |
540 // Clean up temporary PasswordForms and SecKeychainItemRefs. | |
541 STLDeleteContainerPairSecondPointers(item_form_pairs.begin(), | 534 STLDeleteContainerPairSecondPointers(item_form_pairs.begin(), |
542 item_form_pairs.end()); | 535 item_form_pairs.end()); |
543 for (std::vector<SecKeychainItemRef>::iterator i = keychain_items.begin(); | 536 for (auto& item : keychain_items) { |
vasilii
2015/01/27 20:45:51
Here I'd prefer "SecKeychainItemRef item" but not
vabr (Chromium)
2015/01/28 13:27:35
Done.
| |
544 i != keychain_items.end(); ++i) { | 537 keychain.Free(item); |
545 keychain.Free(*i); | |
546 } | 538 } |
547 return merged_forms; | |
548 } | 539 } |
549 | 540 |
550 // TODO(stuartmorgan): signon_realm for proxies is not yet supported. | 541 // TODO(stuartmorgan): signon_realm for proxies is not yet supported. |
551 bool ExtractSignonRealmComponents(const std::string& signon_realm, | 542 bool ExtractSignonRealmComponents(const std::string& signon_realm, |
552 std::string* server, | 543 std::string* server, |
553 UInt32* port, | 544 UInt32* port, |
554 bool* is_secure, | 545 bool* is_secure, |
555 std::string* security_domain) { | 546 std::string* security_domain) { |
556 // The signon_realm will be the Origin portion of a URL for an HTML form, | 547 // The signon_realm will be the Origin portion of a URL for an HTML form, |
557 // and the same but with the security domain as a path for HTTP auth. | 548 // and the same but with the security domain as a path for HTTP auth. |
(...skipping 25 matching lines...) Expand all Loading... | |
583 UInt32 port; | 574 UInt32 port; |
584 bool is_secure; | 575 bool is_secure; |
585 if (!ExtractSignonRealmComponents(query_form.signon_realm, &server, &port, | 576 if (!ExtractSignonRealmComponents(query_form.signon_realm, &server, &port, |
586 &is_secure, &security_domain)) { | 577 &is_secure, &security_domain)) { |
587 return false; | 578 return false; |
588 } | 579 } |
589 return internal_keychain_helpers::FormsMatchForMerge( | 580 return internal_keychain_helpers::FormsMatchForMerge( |
590 query_form, other_form, STRICT_FORM_MATCH); | 581 query_form, other_form, STRICT_FORM_MATCH); |
591 } | 582 } |
592 | 583 |
593 std::vector<PasswordForm*> ExtractPasswordsMergeableWithForm( | 584 void ExtractPasswordsMergeableWithForm( |
594 const AppleKeychain& keychain, | 585 const AppleKeychain& keychain, |
595 const std::vector<ItemFormPair>& item_form_pairs, | 586 const std::vector<ItemFormPair>& item_form_pairs, |
596 const PasswordForm& query_form) { | 587 const PasswordForm& query_form, |
597 std::vector<PasswordForm*> matches; | 588 ScopedVector<autofill::PasswordForm>* matches) { |
vasilii
2015/01/27 20:45:51
returning this object would simplify the caller.
vabr (Chromium)
2015/01/28 13:27:35
Done.
(I misread the definition of ScopedVector a
| |
598 for (std::vector<ItemFormPair>::const_iterator i = item_form_pairs.begin(); | 589 for (std::vector<ItemFormPair>::const_iterator i = item_form_pairs.begin(); |
599 i != item_form_pairs.end(); ++i) { | 590 i != item_form_pairs.end(); ++i) { |
600 if (FormIsValidAndMatchesOtherForm(query_form, *(i->second))) { | 591 if (FormIsValidAndMatchesOtherForm(query_form, *(i->second))) { |
601 // Create a new object, since the caller is responsible for deleting the | 592 // Create a new object, since the caller is responsible for deleting the |
602 // returned forms. | 593 // returned forms. |
603 scoped_ptr<PasswordForm> form_with_password(new PasswordForm()); | 594 scoped_ptr<PasswordForm> form_with_password(new PasswordForm()); |
604 internal_keychain_helpers::FillPasswordFormFromKeychainItem( | 595 internal_keychain_helpers::FillPasswordFormFromKeychainItem( |
605 keychain, | 596 keychain, |
606 *(i->first), | 597 *(i->first), |
607 form_with_password.get(), | 598 form_with_password.get(), |
608 true); // Load password attributes and data. | 599 true); // Load password attributes and data. |
609 // Do not include blacklisted items found in the keychain. | 600 // Do not include blacklisted items found in the keychain. |
610 if (!form_with_password->blacklisted_by_user) | 601 if (!form_with_password->blacklisted_by_user) |
611 matches.push_back(form_with_password.release()); | 602 matches->push_back(form_with_password.release()); |
612 } | 603 } |
613 } | 604 } |
614 return matches; | |
615 } | 605 } |
616 | 606 |
617 } // namespace internal_keychain_helpers | 607 } // namespace internal_keychain_helpers |
618 | 608 |
619 #pragma mark - | 609 #pragma mark - |
620 | 610 |
621 MacKeychainPasswordFormAdapter::MacKeychainPasswordFormAdapter( | 611 MacKeychainPasswordFormAdapter::MacKeychainPasswordFormAdapter( |
622 const AppleKeychain* keychain) | 612 const AppleKeychain* keychain) |
623 : keychain_(keychain), finds_only_owned_(false) { | 613 : keychain_(keychain), finds_only_owned_(false) { |
624 } | 614 } |
625 | 615 |
626 std::vector<PasswordForm*> MacKeychainPasswordFormAdapter::PasswordsFillingForm( | 616 // Gets keychain items corresponding to |signon_realm| and |scheme|, converts |
617 // them into PasswordForms and appends them to |forms|. | |
618 void MacKeychainPasswordFormAdapter::PasswordsFillingForm( | |
627 const std::string& signon_realm, | 619 const std::string& signon_realm, |
628 PasswordForm::Scheme scheme) { | 620 PasswordForm::Scheme scheme, |
621 ScopedVector<autofill::PasswordForm>* forms) { | |
629 std::vector<SecKeychainItemRef> keychain_items = | 622 std::vector<SecKeychainItemRef> keychain_items = |
630 MatchingKeychainItems(signon_realm, scheme, NULL, NULL); | 623 MatchingKeychainItems(signon_realm, scheme, NULL, NULL); |
631 | 624 ConvertKeychainItemsToForms(&keychain_items, forms); |
632 return ConvertKeychainItemsToForms(&keychain_items); | |
633 } | 625 } |
634 | 626 |
635 bool MacKeychainPasswordFormAdapter::HasPasswordExactlyMatchingForm( | 627 bool MacKeychainPasswordFormAdapter::HasPasswordExactlyMatchingForm( |
636 const PasswordForm& query_form) { | 628 const PasswordForm& query_form) { |
637 SecKeychainItemRef keychain_item = KeychainItemForForm(query_form); | 629 SecKeychainItemRef keychain_item = KeychainItemForForm(query_form); |
638 if (keychain_item) { | 630 if (keychain_item) { |
639 keychain_->Free(keychain_item); | 631 keychain_->Free(keychain_item); |
640 return true; | 632 return true; |
641 } | 633 } |
642 return false; | 634 return false; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
674 &supported_auth_types[i], | 666 &supported_auth_types[i], |
675 NULL, | 667 NULL, |
676 NULL, | 668 NULL, |
677 NULL, | 669 NULL, |
678 creator ? &creator : NULL); | 670 creator ? &creator : NULL); |
679 keychain_search.FindMatchingItems(&matches); | 671 keychain_search.FindMatchingItems(&matches); |
680 } | 672 } |
681 return matches; | 673 return matches; |
682 } | 674 } |
683 | 675 |
684 std::vector<PasswordForm*> | 676 void MacKeychainPasswordFormAdapter::GetAllPasswordFormPasswords( |
685 MacKeychainPasswordFormAdapter::GetAllPasswordFormPasswords() { | 677 ScopedVector<autofill::PasswordForm>* forms) { |
686 std::vector<SecKeychainItemRef> items = GetAllPasswordFormKeychainItems(); | 678 std::vector<SecKeychainItemRef> items = GetAllPasswordFormKeychainItems(); |
687 return ConvertKeychainItemsToForms(&items); | 679 return ConvertKeychainItemsToForms(&items, forms); |
688 } | 680 } |
689 | 681 |
690 bool MacKeychainPasswordFormAdapter::AddPassword(const PasswordForm& form) { | 682 bool MacKeychainPasswordFormAdapter::AddPassword(const PasswordForm& form) { |
691 // We should never be trying to store a blacklist in the keychain. | 683 // We should never be trying to store a blacklist in the keychain. |
692 DCHECK(!form.blacklisted_by_user); | 684 DCHECK(!form.blacklisted_by_user); |
693 | 685 |
694 std::string server; | 686 std::string server; |
695 std::string security_domain; | 687 std::string security_domain; |
696 UInt32 port; | 688 UInt32 port; |
697 bool is_secure; | 689 bool is_secure; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
738 OSStatus result = keychain_->ItemDelete(keychain_item); | 730 OSStatus result = keychain_->ItemDelete(keychain_item); |
739 keychain_->Free(keychain_item); | 731 keychain_->Free(keychain_item); |
740 return result == noErr; | 732 return result == noErr; |
741 } | 733 } |
742 | 734 |
743 void MacKeychainPasswordFormAdapter::SetFindsOnlyOwnedItems( | 735 void MacKeychainPasswordFormAdapter::SetFindsOnlyOwnedItems( |
744 bool finds_only_owned) { | 736 bool finds_only_owned) { |
745 finds_only_owned_ = finds_only_owned; | 737 finds_only_owned_ = finds_only_owned; |
746 } | 738 } |
747 | 739 |
748 std::vector<PasswordForm*> | 740 void MacKeychainPasswordFormAdapter::ConvertKeychainItemsToForms( |
749 MacKeychainPasswordFormAdapter::ConvertKeychainItemsToForms( | 741 std::vector<SecKeychainItemRef>* items, |
750 std::vector<SecKeychainItemRef>* items) { | 742 ScopedVector<autofill::PasswordForm>* forms) { |
vasilii
2015/01/27 20:45:51
returning this would simplify the code.
vabr (Chromium)
2015/01/28 13:27:35
Done.
| |
751 std::vector<PasswordForm*> keychain_forms; | 743 for (const auto& item : *items) { |
vasilii
2015/01/27 20:45:51
You are iterating over pointers. I'd prefer "SecKe
vabr (Chromium)
2015/01/28 13:27:35
Done.
| |
752 for (std::vector<SecKeychainItemRef>::const_iterator i = items->begin(); | 744 scoped_ptr<PasswordForm> form(new PasswordForm()); |
753 i != items->end(); ++i) { | |
754 PasswordForm* form = new PasswordForm(); | |
755 if (internal_keychain_helpers::FillPasswordFormFromKeychainItem( | 745 if (internal_keychain_helpers::FillPasswordFormFromKeychainItem( |
756 *keychain_, *i, form, true)) { | 746 *keychain_, item, form.get(), true)) { |
757 keychain_forms.push_back(form); | 747 forms->push_back(form.release()); |
758 } | 748 } |
759 keychain_->Free(*i); | 749 keychain_->Free(item); |
760 } | 750 } |
761 items->clear(); | 751 items->clear(); |
762 return keychain_forms; | |
763 } | 752 } |
764 | 753 |
765 SecKeychainItemRef MacKeychainPasswordFormAdapter::KeychainItemForForm( | 754 SecKeychainItemRef MacKeychainPasswordFormAdapter::KeychainItemForForm( |
766 const PasswordForm& form) { | 755 const PasswordForm& form) { |
767 // We don't store blacklist entries in the keychain, so the answer to "what | 756 // We don't store blacklist entries in the keychain, so the answer to "what |
768 // Keychain item goes with this form" is always "nothing" for blacklists. | 757 // Keychain item goes with this form" is always "nothing" for blacklists. |
769 if (form.blacklisted_by_user) { | 758 if (form.blacklisted_by_user) { |
770 return NULL; | 759 return NULL; |
771 } | 760 } |
772 | 761 |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
976 | 965 |
977 changes.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE, form)); | 966 changes.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE, form)); |
978 } | 967 } |
979 return changes; | 968 return changes; |
980 } | 969 } |
981 | 970 |
982 PasswordStoreChangeList PasswordStoreMac::RemoveLoginsCreatedBetweenImpl( | 971 PasswordStoreChangeList PasswordStoreMac::RemoveLoginsCreatedBetweenImpl( |
983 base::Time delete_begin, | 972 base::Time delete_begin, |
984 base::Time delete_end) { | 973 base::Time delete_end) { |
985 PasswordStoreChangeList changes; | 974 PasswordStoreChangeList changes; |
986 ScopedVector<PasswordForm> forms; | 975 ScopedVector<PasswordForm> forms_to_remove; |
987 if (login_metadata_db_ && | 976 if (login_metadata_db_ && |
988 login_metadata_db_->GetLoginsCreatedBetween(delete_begin, delete_end, | 977 login_metadata_db_->GetLoginsCreatedBetween(delete_begin, delete_end, |
989 &forms.get()) && | 978 &forms_to_remove) && |
990 login_metadata_db_->RemoveLoginsCreatedBetween(delete_begin, | 979 login_metadata_db_->RemoveLoginsCreatedBetween(delete_begin, |
991 delete_end)) { | 980 delete_end)) { |
992 RemoveKeychainForms(forms.get()); | 981 RemoveKeychainForms(forms_to_remove.get()); |
993 CleanOrphanedForms(&forms.get()); | 982 CleanOrphanedForms(&forms_to_remove); // Add the orphaned forms. |
994 changes = FormsToRemoveChangeList(forms.get()); | 983 changes = FormsToRemoveChangeList(forms_to_remove.get()); |
995 LogStatsForBulkDeletion(changes.size()); | 984 LogStatsForBulkDeletion(changes.size()); |
996 } | 985 } |
997 return changes; | 986 return changes; |
998 } | 987 } |
999 | 988 |
1000 PasswordStoreChangeList PasswordStoreMac::RemoveLoginsSyncedBetweenImpl( | 989 PasswordStoreChangeList PasswordStoreMac::RemoveLoginsSyncedBetweenImpl( |
1001 base::Time delete_begin, | 990 base::Time delete_begin, |
1002 base::Time delete_end) { | 991 base::Time delete_end) { |
1003 PasswordStoreChangeList changes; | 992 PasswordStoreChangeList changes; |
1004 ScopedVector<PasswordForm> forms; | 993 ScopedVector<PasswordForm> forms_to_remove; |
1005 if (login_metadata_db_ && | 994 if (login_metadata_db_ && |
1006 login_metadata_db_->GetLoginsSyncedBetween(delete_begin, delete_end, | 995 login_metadata_db_->GetLoginsSyncedBetween(delete_begin, delete_end, |
1007 &forms.get()) && | 996 &forms_to_remove) && |
1008 login_metadata_db_->RemoveLoginsSyncedBetween(delete_begin, delete_end)) { | 997 login_metadata_db_->RemoveLoginsSyncedBetween(delete_begin, delete_end)) { |
1009 RemoveKeychainForms(forms.get()); | 998 RemoveKeychainForms(forms_to_remove.get()); |
1010 CleanOrphanedForms(&forms.get()); | 999 CleanOrphanedForms(&forms_to_remove); // Add the orphaned forms_to_remove. |
1011 changes = FormsToRemoveChangeList(forms.get()); | 1000 changes = FormsToRemoveChangeList(forms_to_remove.get()); |
1012 LogStatsForBulkDeletionDuringRollback(changes.size()); | 1001 LogStatsForBulkDeletionDuringRollback(changes.size()); |
1013 } | 1002 } |
1014 return changes; | 1003 return changes; |
1015 } | 1004 } |
1016 | 1005 |
1017 void PasswordStoreMac::GetLoginsImpl( | 1006 void PasswordStoreMac::GetLoginsImpl( |
1018 const autofill::PasswordForm& form, | 1007 const autofill::PasswordForm& form, |
1019 AuthorizationPromptPolicy prompt_policy, | 1008 AuthorizationPromptPolicy prompt_policy, |
1020 const ConsumerCallbackRunner& callback_runner) { | 1009 const ConsumerCallbackRunner& callback_runner) { |
1021 chrome::ScopedSecKeychainSetUserInteractionAllowed user_interaction_allowed( | 1010 chrome::ScopedSecKeychainSetUserInteractionAllowed user_interaction_allowed( |
1022 prompt_policy == ALLOW_PROMPT); | 1011 prompt_policy == ALLOW_PROMPT); |
1023 | 1012 |
1024 if (!login_metadata_db_) { | 1013 if (!login_metadata_db_) { |
1025 callback_runner.Run(std::vector<PasswordForm*>()); | 1014 ScopedVector<autofill::PasswordForm> dummy_matched_forms; |
1015 callback_runner.Run(&dummy_matched_forms); | |
1026 return; | 1016 return; |
1027 } | 1017 } |
1028 | 1018 |
1029 ScopedVector<PasswordForm> database_forms; | 1019 ScopedVector<PasswordForm> database_forms; |
1030 login_metadata_db_->GetLogins(form, &database_forms.get()); | 1020 login_metadata_db_->GetLogins(form, &database_forms); |
1031 | 1021 |
1032 // Let's gather all signon realms we want to match with keychain entries. | 1022 // Let's gather all signon realms we want to match with keychain entries. |
1033 std::set<std::string> realm_set; | 1023 std::set<std::string> realm_set; |
1034 realm_set.insert(form.signon_realm); | 1024 realm_set.insert(form.signon_realm); |
1035 for (std::vector<PasswordForm*>::const_iterator db_form = | 1025 for (const auto& db_form : database_forms) { |
vasilii
2015/01/27 20:45:51
const reference to pointer seems to be an overhead
vabr (Chromium)
2015/01/28 13:27:36
Done.
| |
1036 database_forms.begin(); | |
1037 db_form != database_forms.end(); | |
1038 ++db_form) { | |
1039 // TODO(vabr): We should not be getting different schemes here. | 1026 // TODO(vabr): We should not be getting different schemes here. |
1040 // http://crbug.com/340112 | 1027 // http://crbug.com/340112 |
1041 if (form.scheme != (*db_form)->scheme) | 1028 if (form.scheme != db_form->scheme) |
1042 continue; // Forms with different schemes never match. | 1029 continue; // Forms with different schemes never match. |
1043 const std::string& original_singon_realm((*db_form)->original_signon_realm); | 1030 const std::string& original_singon_realm(db_form->original_signon_realm); |
1044 if (!original_singon_realm.empty()) | 1031 if (!original_singon_realm.empty()) |
1045 realm_set.insert(original_singon_realm); | 1032 realm_set.insert(original_singon_realm); |
1046 } | 1033 } |
1047 std::vector<PasswordForm*> keychain_forms; | 1034 ScopedVector<autofill::PasswordForm> keychain_forms; |
1048 for (std::set<std::string>::const_iterator realm = realm_set.begin(); | 1035 for (std::set<std::string>::const_iterator realm = realm_set.begin(); |
1049 realm != realm_set.end(); | 1036 realm != realm_set.end(); |
1050 ++realm) { | 1037 ++realm) { |
1051 MacKeychainPasswordFormAdapter keychain_adapter(keychain_.get()); | 1038 MacKeychainPasswordFormAdapter keychain_adapter(keychain_.get()); |
1052 std::vector<PasswordForm*> temp_keychain_forms = | 1039 keychain_adapter.PasswordsFillingForm(*realm, form.scheme, &keychain_forms); |
1053 keychain_adapter.PasswordsFillingForm(*realm, form.scheme); | |
1054 keychain_forms.insert(keychain_forms.end(), | |
1055 temp_keychain_forms.begin(), | |
1056 temp_keychain_forms.end()); | |
1057 } | 1040 } |
1058 | 1041 |
1059 std::vector<PasswordForm*> matched_forms; | 1042 ScopedVector<autofill::PasswordForm> matched_forms; |
1060 internal_keychain_helpers::MergePasswordForms(&keychain_forms, | 1043 internal_keychain_helpers::MergePasswordForms( |
1061 &database_forms.get(), | 1044 &keychain_forms, &database_forms, &matched_forms); |
1062 &matched_forms); | |
1063 | 1045 |
1064 // Strip any blacklist entries out of the unused Keychain array, then take | 1046 // Strip any blacklist entries out of the unused Keychain array, then take |
1065 // all the entries that are left (which we can use as imported passwords). | 1047 // all the entries that are left (which we can use as imported passwords). |
1066 ScopedVector<PasswordForm> keychain_blacklist_forms; | 1048 ScopedVector<PasswordForm> keychain_blacklist_forms; |
1067 internal_keychain_helpers::ExtractBlacklistForms(&keychain_forms).swap( | 1049 internal_keychain_helpers::ExtractBlacklistForms(&keychain_forms, |
1068 keychain_blacklist_forms.get()); | 1050 &keychain_blacklist_forms); |
1069 matched_forms.insert(matched_forms.end(), | 1051 matched_forms.insert(matched_forms.end(), |
1070 keychain_forms.begin(), | 1052 keychain_forms.begin(), |
1071 keychain_forms.end()); | 1053 keychain_forms.end()); |
1072 keychain_forms.clear(); | 1054 keychain_forms.weak_clear(); |
1073 | 1055 |
1074 if (!database_forms.empty()) { | 1056 if (!database_forms.empty()) { |
1075 RemoveDatabaseForms(database_forms.get()); | 1057 RemoveDatabaseForms(database_forms.get()); |
1076 NotifyLoginsChanged(FormsToRemoveChangeList(database_forms.get())); | 1058 NotifyLoginsChanged(FormsToRemoveChangeList(database_forms.get())); |
1077 } | 1059 } |
1078 | 1060 |
1079 callback_runner.Run(matched_forms); | 1061 callback_runner.Run(&matched_forms); |
1080 } | 1062 } |
1081 | 1063 |
1082 void PasswordStoreMac::GetBlacklistLoginsImpl(GetLoginsRequest* request) { | 1064 void PasswordStoreMac::GetBlacklistLoginsImpl(GetLoginsRequest* request) { |
1083 FillBlacklistLogins(request->result()); | 1065 ScopedVector<autofill::PasswordForm> obtained_forms; |
1066 FillBlacklistLogins(&obtained_forms); | |
1067 request->result()->swap(obtained_forms.get()); | |
1068 obtained_forms.weak_clear(); // TODO(vabr): Change request to have a | |
vasilii
2015/01/27 20:45:51
Seems to be a leak.
vabr (Chromium)
2015/01/28 13:27:35
You are right. I honestly don't know what I was th
| |
1069 // ScopedVector instead. | |
1084 ForwardLoginsResult(request); | 1070 ForwardLoginsResult(request); |
1085 } | 1071 } |
1086 | 1072 |
1087 void PasswordStoreMac::GetAutofillableLoginsImpl(GetLoginsRequest* request) { | 1073 void PasswordStoreMac::GetAutofillableLoginsImpl(GetLoginsRequest* request) { |
1088 FillAutofillableLogins(request->result()); | 1074 ScopedVector<autofill::PasswordForm> obtained_forms; |
1075 FillAutofillableLogins(&obtained_forms); | |
1076 request->result()->swap(obtained_forms.get()); | |
1077 obtained_forms.weak_clear(); // TODO(vabr): Change request to have a | |
vasilii
2015/01/27 20:45:51
Same here.
vabr (Chromium)
2015/01/28 13:27:35
Done.
| |
1078 // ScopedVector instead. | |
1089 ForwardLoginsResult(request); | 1079 ForwardLoginsResult(request); |
1090 } | 1080 } |
1091 | 1081 |
1092 bool PasswordStoreMac::FillAutofillableLogins( | 1082 bool PasswordStoreMac::FillAutofillableLogins( |
1093 std::vector<PasswordForm*>* forms) { | 1083 ScopedVector<autofill::PasswordForm>* forms) { |
1094 DCHECK(thread_->message_loop() == base::MessageLoop::current()); | 1084 DCHECK(thread_->message_loop() == base::MessageLoop::current()); |
1095 | 1085 |
1096 ScopedVector<PasswordForm> database_forms; | 1086 ScopedVector<PasswordForm> database_forms; |
1097 if (!login_metadata_db_ || | 1087 if (!login_metadata_db_ || |
1098 !login_metadata_db_->GetAutofillableLogins(&database_forms.get())) | 1088 !login_metadata_db_->GetAutofillableLogins(&database_forms)) |
1099 return false; | 1089 return false; |
1100 | 1090 |
1101 std::vector<PasswordForm*> merged_forms = | 1091 internal_keychain_helpers::GetPasswordsForForms(*keychain_, &database_forms, |
1102 internal_keychain_helpers::GetPasswordsForForms(*keychain_, | 1092 forms); |
1103 &database_forms.get()); | |
1104 | 1093 |
1105 if (!database_forms.empty()) { | 1094 if (!database_forms.empty()) { |
1106 RemoveDatabaseForms(database_forms.get()); | 1095 RemoveDatabaseForms(database_forms.get()); |
1107 NotifyLoginsChanged(FormsToRemoveChangeList(database_forms.get())); | 1096 NotifyLoginsChanged(FormsToRemoveChangeList(database_forms.get())); |
1108 } | 1097 } |
1109 | 1098 |
1110 forms->insert(forms->end(), merged_forms.begin(), merged_forms.end()); | |
1111 return true; | 1099 return true; |
1112 } | 1100 } |
1113 | 1101 |
1114 bool PasswordStoreMac::FillBlacklistLogins( | 1102 bool PasswordStoreMac::FillBlacklistLogins( |
1115 std::vector<PasswordForm*>* forms) { | 1103 ScopedVector<autofill::PasswordForm>* forms) { |
1116 DCHECK(thread_->message_loop() == base::MessageLoop::current()); | 1104 DCHECK(thread_->message_loop() == base::MessageLoop::current()); |
1117 return login_metadata_db_ && login_metadata_db_->GetBlacklistLogins(forms); | 1105 return login_metadata_db_ && login_metadata_db_->GetBlacklistLogins(forms); |
1118 } | 1106 } |
1119 | 1107 |
1120 bool PasswordStoreMac::AddToKeychainIfNecessary(const PasswordForm& form) { | 1108 bool PasswordStoreMac::AddToKeychainIfNecessary(const PasswordForm& form) { |
1121 if (form.blacklisted_by_user) { | 1109 if (form.blacklisted_by_user) { |
1122 return true; | 1110 return true; |
1123 } | 1111 } |
1124 MacKeychainPasswordFormAdapter keychainAdapter(keychain_.get()); | 1112 MacKeychainPasswordFormAdapter keychainAdapter(keychain_.get()); |
1125 return keychainAdapter.AddPassword(form); | 1113 return keychainAdapter.AddPassword(form); |
1126 } | 1114 } |
1127 | 1115 |
1128 bool PasswordStoreMac::DatabaseHasFormMatchingKeychainForm( | 1116 bool PasswordStoreMac::DatabaseHasFormMatchingKeychainForm( |
1129 const autofill::PasswordForm& form) { | 1117 const autofill::PasswordForm& form) { |
1130 DCHECK(login_metadata_db_); | 1118 DCHECK(login_metadata_db_); |
1131 bool has_match = false; | 1119 bool has_match = false; |
1132 std::vector<PasswordForm*> database_forms; | 1120 ScopedVector<autofill::PasswordForm> database_forms; |
1133 login_metadata_db_->GetLogins(form, &database_forms); | 1121 login_metadata_db_->GetLogins(form, &database_forms); |
1134 for (std::vector<PasswordForm*>::iterator i = database_forms.begin(); | 1122 for (const auto& db_form : database_forms) { |
vasilii
2015/01/27 20:45:51
a reference to the pointer
vabr (Chromium)
2015/01/28 13:27:35
Done.
| |
1135 i != database_forms.end(); ++i) { | |
1136 // Below we filter out forms with non-empty original_signon_realm, because | 1123 // Below we filter out forms with non-empty original_signon_realm, because |
1137 // those signal fuzzy matches, and we are only interested in exact ones. | 1124 // those signal fuzzy matches, and we are only interested in exact ones. |
1138 if ((*i)->original_signon_realm.empty() && | 1125 if (db_form->original_signon_realm.empty() && |
1139 internal_keychain_helpers::FormsMatchForMerge( | 1126 internal_keychain_helpers::FormsMatchForMerge( |
1140 form, **i, internal_keychain_helpers::STRICT_FORM_MATCH) && | 1127 form, *db_form, internal_keychain_helpers::STRICT_FORM_MATCH) && |
1141 (*i)->origin == form.origin) { | 1128 db_form->origin == form.origin) { |
1142 has_match = true; | 1129 has_match = true; |
1143 break; | 1130 break; |
1144 } | 1131 } |
1145 } | 1132 } |
1146 STLDeleteElements(&database_forms); | |
1147 return has_match; | 1133 return has_match; |
1148 } | 1134 } |
1149 | 1135 |
1150 void PasswordStoreMac::RemoveDatabaseForms( | 1136 void PasswordStoreMac::RemoveDatabaseForms( |
1151 const std::vector<PasswordForm*>& forms) { | 1137 const std::vector<PasswordForm*>& forms) { |
1152 DCHECK(login_metadata_db_); | 1138 DCHECK(login_metadata_db_); |
1153 for (std::vector<PasswordForm*>::const_iterator i = forms.begin(); | 1139 for (std::vector<PasswordForm*>::const_iterator i = forms.begin(); |
1154 i != forms.end(); ++i) { | 1140 i != forms.end(); ++i) { |
1155 login_metadata_db_->RemoveLogin(**i); | 1141 login_metadata_db_->RemoveLogin(**i); |
1156 } | 1142 } |
1157 } | 1143 } |
1158 | 1144 |
1159 void PasswordStoreMac::RemoveKeychainForms( | 1145 void PasswordStoreMac::RemoveKeychainForms( |
1160 const std::vector<PasswordForm*>& forms) { | 1146 const std::vector<PasswordForm*>& forms) { |
1161 MacKeychainPasswordFormAdapter owned_keychain_adapter(keychain_.get()); | 1147 MacKeychainPasswordFormAdapter owned_keychain_adapter(keychain_.get()); |
1162 owned_keychain_adapter.SetFindsOnlyOwnedItems(true); | 1148 owned_keychain_adapter.SetFindsOnlyOwnedItems(true); |
1163 for (std::vector<PasswordForm*>::const_iterator i = forms.begin(); | 1149 for (std::vector<PasswordForm*>::const_iterator i = forms.begin(); |
1164 i != forms.end(); ++i) { | 1150 i != forms.end(); ++i) { |
1165 owned_keychain_adapter.RemovePassword(**i); | 1151 owned_keychain_adapter.RemovePassword(**i); |
1166 } | 1152 } |
1167 } | 1153 } |
1168 | 1154 |
1169 void PasswordStoreMac::CleanOrphanedForms(std::vector<PasswordForm*>* forms) { | 1155 void PasswordStoreMac::CleanOrphanedForms( |
1170 DCHECK(forms); | 1156 ScopedVector<autofill::PasswordForm>* orphaned_forms) { |
1157 DCHECK(orphaned_forms); | |
1171 DCHECK(login_metadata_db_); | 1158 DCHECK(login_metadata_db_); |
1172 | 1159 |
1173 std::vector<PasswordForm*> database_forms; | 1160 ScopedVector<autofill::PasswordForm> database_forms; |
1174 login_metadata_db_->GetAutofillableLogins(&database_forms); | 1161 login_metadata_db_->GetAutofillableLogins(&database_forms); |
1175 | 1162 |
1176 ScopedVector<PasswordForm> merged_forms; | 1163 // Filter forms with corresponding Keychain entry out of |database_forms|. |
1177 merged_forms.get() = internal_keychain_helpers::GetPasswordsForForms( | 1164 ScopedVector<PasswordForm> forms_with_keychain_entry; |
1178 *keychain_, &database_forms); | 1165 internal_keychain_helpers::GetPasswordsForForms(*keychain_, &database_forms, |
1166 &forms_with_keychain_entry); | |
1179 | 1167 |
1180 // Clean up any orphaned database entries. | 1168 // Clean up any orphaned database entries. |
1181 RemoveDatabaseForms(database_forms); | 1169 RemoveDatabaseForms(database_forms.get()); |
1182 | 1170 |
1183 forms->insert(forms->end(), database_forms.begin(), database_forms.end()); | 1171 // Move the orphaned DB forms to the output parameter. |
1172 orphaned_forms->insert(orphaned_forms->end(), database_forms.begin(), | |
1173 database_forms.end()); | |
1174 database_forms.weak_clear(); | |
1184 } | 1175 } |
OLD | NEW |