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

Side by Side Diff: chrome/browser/password_manager/password_store_mac.cc

Issue 825773003: PasswordStore: Use ScopedVector to express ownership of forms (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Leaks fixed + VABR->vabr Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698