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 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
182 PasswordStoreChangeList FormsToRemoveChangeList( | 181 PasswordStoreChangeList FormsToRemoveChangeList( |
183 const std::vector<PasswordForm*>& forms) { | 182 const std::vector<PasswordForm*>& forms) { |
184 PasswordStoreChangeList changes; | 183 PasswordStoreChangeList changes; |
185 for (std::vector<PasswordForm*>::const_iterator i = forms.begin(); | 184 for (std::vector<PasswordForm*>::const_iterator i = forms.begin(); |
186 i != forms.end(); ++i) { | 185 i != forms.end(); ++i) { |
187 changes.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE, **i)); | 186 changes.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE, **i)); |
188 } | 187 } |
189 return changes; | 188 return changes; |
190 } | 189 } |
191 | 190 |
191 // Moves the content of |second| to the end of |first|. | |
192 void AppendSecondToFirst(ScopedVector<autofill::PasswordForm>* first, | |
193 ScopedVector<autofill::PasswordForm>* second) { | |
194 first->insert(first->end(), second->begin(), second->end()); | |
195 second->weak_clear(); | |
196 } | |
197 | |
192 } // namespace | 198 } // namespace |
193 | 199 |
194 #pragma mark - | 200 #pragma mark - |
195 | 201 |
196 // TODO(stuartmorgan): Convert most of this to private helpers in | 202 // TODO(stuartmorgan): Convert most of this to private helpers in |
197 // MacKeychainPasswordFormAdapter once it has sufficient higher-level public | 203 // MacKeychainPasswordFormAdapter once it has sufficient higher-level public |
198 // methods to provide test coverage. | 204 // methods to provide test coverage. |
199 namespace internal_keychain_helpers { | 205 namespace internal_keychain_helpers { |
200 | 206 |
201 // Returns a URL built from the given components. To create a URL without a | 207 // Returns a URL built from the given components. To create a URL without a |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
411 if (base_form.origin == (*i)->origin) { | 417 if (base_form.origin == (*i)->origin) { |
412 return *i; | 418 return *i; |
413 } else if (!partial_match) { | 419 } else if (!partial_match) { |
414 partial_match = *i; | 420 partial_match = *i; |
415 } | 421 } |
416 } | 422 } |
417 } | 423 } |
418 return partial_match; | 424 return partial_match; |
419 } | 425 } |
420 | 426 |
421 // Returns entries from |forms| that are blacklist entries, after removing | 427 // Moves entries from |forms| that are blacklist entries into |blacklist|. |
422 // them from |forms|. | 428 void ExtractBlacklistForms(ScopedVector<autofill::PasswordForm>* forms, |
423 std::vector<PasswordForm*> ExtractBlacklistForms( | 429 ScopedVector<autofill::PasswordForm>* blacklist) { |
424 std::vector<PasswordForm*>* forms) { | 430 blacklist->reserve(blacklist->size() + forms->size()); |
425 std::vector<PasswordForm*> blacklist_forms; | 431 ScopedVector<autofill::PasswordForm> non_blacklist; |
426 for (std::vector<PasswordForm*>::iterator i = forms->begin(); | 432 for (auto& form : *forms) { |
427 i != forms->end();) { | 433 if (form->blacklisted_by_user) |
428 PasswordForm* form = *i; | 434 blacklist->push_back(form); |
429 if (form->blacklisted_by_user) { | 435 else |
430 blacklist_forms.push_back(form); | 436 non_blacklist.push_back(form); |
431 i = forms->erase(i); | 437 form = nullptr; |
432 } else { | |
433 ++i; | |
434 } | |
435 } | 438 } |
436 return blacklist_forms; | 439 forms->swap(non_blacklist); |
437 } | 440 } |
438 | 441 |
439 // Deletes and removes from v any element that exists in s. | 442 // Takes |keychain_forms| and |database_forms| and moves the following 2 types |
440 template <class T> | 443 // of forms to |merged_forms|: (1) blacklisted |database_forms|, (2) |
441 void DeleteVectorElementsInSet(std::vector<T*>* v, const std::set<T*>& s) { | 444 // |database_forms| which have a corresponding entry in |keychain_forms|. The |
442 for (typename std::vector<T*>::iterator i = v->begin(); i != v->end();) { | 445 // database forms of type (2) have their password value updated from the |
443 T* element = *i; | 446 // corresponding keychain form, and all the keychain forms corresponding to some |
444 if (s.find(element) != s.end()) { | 447 // database form are removed from |keychain_forms| and deleted. |
445 delete element; | 448 void MergePasswordForms(ScopedVector<autofill::PasswordForm>* keychain_forms, |
446 i = v->erase(i); | 449 ScopedVector<autofill::PasswordForm>* database_forms, |
447 } else { | 450 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 | 451 // Pull out the database blacklist items, since they are used as-is rather |
457 // than being merged with keychain forms. | 452 // than being merged with keychain forms. |
458 std::vector<PasswordForm*> database_blacklist_forms = | 453 ExtractBlacklistForms(database_forms, merged_forms); |
459 ExtractBlacklistForms(database_forms); | |
460 | 454 |
461 // Merge the normal entries. | 455 // Merge the normal entries. |
462 std::set<PasswordForm*> used_keychain_forms; | 456 ScopedVector<autofill::PasswordForm> unused_database_forms; |
463 for (std::vector<PasswordForm*>::iterator i = database_forms->begin(); | 457 unused_database_forms.reserve(database_forms->size()); |
464 i != database_forms->end();) { | 458 std::set<autofill::PasswordForm*> used_keychain_forms; |
465 PasswordForm* db_form = *i; | 459 for (auto& db_form : *database_forms) { |
466 PasswordForm* best_match = BestKeychainFormForForm(*db_form, | 460 PasswordForm* best_match = |
467 keychain_forms); | 461 BestKeychainFormForForm(*db_form, &keychain_forms->get()); |
468 if (best_match) { | 462 if (best_match) { |
469 used_keychain_forms.insert(best_match); | 463 used_keychain_forms.insert(best_match); |
470 db_form->password_value = best_match->password_value; | 464 db_form->password_value = best_match->password_value; |
471 merged_forms->push_back(db_form); | 465 merged_forms->push_back(db_form); |
472 i = database_forms->erase(i); | |
473 } else { | 466 } else { |
474 ++i; | 467 unused_database_forms.push_back(db_form); |
468 } | |
469 db_form = nullptr; | |
470 } | |
471 database_forms->swap(unused_database_forms); | |
472 | |
473 // Clear out all the Keychain entries we used. | |
474 ScopedVector<autofill::PasswordForm> unused_keychain_forms; | |
475 unused_keychain_forms.reserve(keychain_forms->size()); | |
476 for (auto& keychain_form : *keychain_forms) { | |
477 if (!ContainsKey(used_keychain_forms, keychain_form)) { | |
478 unused_keychain_forms.push_back(keychain_form); | |
479 keychain_form = nullptr; | |
475 } | 480 } |
476 } | 481 } |
477 | 482 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 } | 483 } |
486 | 484 |
487 std::vector<ItemFormPair> ExtractAllKeychainItemAttributesIntoPasswordForms( | 485 std::vector<ItemFormPair> ExtractAllKeychainItemAttributesIntoPasswordForms( |
488 std::vector<SecKeychainItemRef>* keychain_items, | 486 std::vector<SecKeychainItemRef>* keychain_items, |
489 const AppleKeychain& keychain) { | 487 const AppleKeychain& keychain) { |
490 DCHECK(keychain_items); | 488 DCHECK(keychain_items); |
491 MacKeychainPasswordFormAdapter keychain_adapter(&keychain); | 489 MacKeychainPasswordFormAdapter keychain_adapter(&keychain); |
492 *keychain_items = keychain_adapter.GetAllPasswordFormKeychainItems(); | 490 *keychain_items = keychain_adapter.GetAllPasswordFormKeychainItems(); |
493 std::vector<ItemFormPair> item_form_pairs; | 491 std::vector<ItemFormPair> item_form_pairs; |
494 for (std::vector<SecKeychainItemRef>::iterator i = keychain_items->begin(); | 492 for (std::vector<SecKeychainItemRef>::iterator i = keychain_items->begin(); |
495 i != keychain_items->end(); ++i) { | 493 i != keychain_items->end(); ++i) { |
496 PasswordForm* form_without_password = new PasswordForm(); | 494 PasswordForm* form_without_password = new PasswordForm(); |
497 internal_keychain_helpers::FillPasswordFormFromKeychainItem( | 495 internal_keychain_helpers::FillPasswordFormFromKeychainItem( |
498 keychain, | 496 keychain, |
499 *i, | 497 *i, |
500 form_without_password, | 498 form_without_password, |
501 false); // Load password attributes, but not password data. | 499 false); // Load password attributes, but not password data. |
502 item_form_pairs.push_back(std::make_pair(&(*i), form_without_password)); | 500 item_form_pairs.push_back(std::make_pair(&(*i), form_without_password)); |
503 } | 501 } |
504 return item_form_pairs; | 502 return item_form_pairs; |
505 } | 503 } |
506 | 504 |
507 std::vector<PasswordForm*> GetPasswordsForForms( | 505 void GetPasswordsForForms(const AppleKeychain& keychain, |
508 const AppleKeychain& keychain, | 506 ScopedVector<autofill::PasswordForm>* database_forms, |
509 std::vector<PasswordForm*>* database_forms) { | 507 ScopedVector<autofill::PasswordForm>* passwords) { |
510 // First load the attributes of all items in the keychain without loading | 508 // 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. | 509 // their password data, and then match items in |database_forms| against them. |
512 // This avoids individually searching through the keychain for passwords | 510 // This avoids individually searching through the keychain for passwords |
513 // matching each form in |database_forms|, and results in a significant | 511 // matching each form in |database_forms|, and results in a significant |
514 // performance gain, replacing O(N) keychain search operations with a single | 512 // performance gain, replacing O(N) keychain search operations with a single |
515 // operation that loads all keychain items, and then selective reads of only | 513 // operation that loads all keychain items, and then selective reads of only |
516 // the relevant passwords. See crbug.com/263685. | 514 // the relevant passwords. See crbug.com/263685. |
517 std::vector<SecKeychainItemRef> keychain_items; | 515 std::vector<SecKeychainItemRef> keychain_items; |
518 std::vector<ItemFormPair> item_form_pairs = | 516 std::vector<ItemFormPair> item_form_pairs = |
519 ExtractAllKeychainItemAttributesIntoPasswordForms(&keychain_items, | 517 ExtractAllKeychainItemAttributesIntoPasswordForms(&keychain_items, |
520 keychain); | 518 keychain); |
521 | 519 |
522 // Next, compare the attributes of the PasswordForms in |database_forms| | 520 // Next, compare the attributes of the PasswordForms in |database_forms| |
523 // against those in |item_form_pairs|, and extract password data for each | 521 // against those in |item_form_pairs|, and extract password data for each |
524 // matching PasswordForm using its corresponding SecKeychainItemRef. | 522 // matching PasswordForm using its corresponding SecKeychainItemRef. |
525 std::vector<PasswordForm*> merged_forms; | 523 ScopedVector<autofill::PasswordForm> unused_db_forms; |
526 for (std::vector<PasswordForm*>::iterator i = database_forms->begin(); | 524 unused_db_forms.reserve(database_forms->size()); |
527 i != database_forms->end();) { | 525 for (auto& db_form : *database_forms) { |
528 std::vector<PasswordForm*> db_form_container(1, *i); | 526 ScopedVector<autofill::PasswordForm> keychain_matches( |
vasilii
2015/01/28 15:09:03
nit: ScopedVector<autofill::PasswordForm> keychain
vabr (Chromium)
2015/01/28 16:36:27
Done.
You are right: Both the r-value constructor
vasilii
2015/01/28 17:27:22
There is no operator= here. "MyObject o = somethin
| |
529 std::vector<PasswordForm*> keychain_matches = | 527 ExtractPasswordsMergeableWithForm(keychain, item_form_pairs, *db_form)); |
530 ExtractPasswordsMergeableWithForm(keychain, item_form_pairs, **i); | 528 |
531 MergePasswordForms(&keychain_matches, &db_form_container, &merged_forms); | 529 ScopedVector<autofill::PasswordForm> db_form_container; |
532 if (db_form_container.empty()) { | 530 db_form_container.push_back(db_form); |
533 i = database_forms->erase(i); | 531 db_form = nullptr; |
534 } else { | 532 MergePasswordForms(&keychain_matches, &db_form_container, passwords); |
535 ++i; | 533 unused_db_forms.insert(unused_db_forms.end(), db_form_container.begin(), |
536 } | 534 db_form_container.end()); |
537 STLDeleteElements(&keychain_matches); | 535 db_form_container.weak_clear(); |
538 } | 536 } |
537 database_forms->swap(unused_db_forms); | |
539 | 538 |
540 // Clean up temporary PasswordForms and SecKeychainItemRefs. | |
541 STLDeleteContainerPairSecondPointers(item_form_pairs.begin(), | 539 STLDeleteContainerPairSecondPointers(item_form_pairs.begin(), |
542 item_form_pairs.end()); | 540 item_form_pairs.end()); |
543 for (std::vector<SecKeychainItemRef>::iterator i = keychain_items.begin(); | 541 for (SecKeychainItemRef item : keychain_items) { |
544 i != keychain_items.end(); ++i) { | 542 keychain.Free(item); |
545 keychain.Free(*i); | |
546 } | 543 } |
547 return merged_forms; | |
548 } | 544 } |
549 | 545 |
550 // TODO(stuartmorgan): signon_realm for proxies is not yet supported. | 546 // TODO(stuartmorgan): signon_realm for proxies is not yet supported. |
551 bool ExtractSignonRealmComponents(const std::string& signon_realm, | 547 bool ExtractSignonRealmComponents(const std::string& signon_realm, |
552 std::string* server, | 548 std::string* server, |
553 UInt32* port, | 549 UInt32* port, |
554 bool* is_secure, | 550 bool* is_secure, |
555 std::string* security_domain) { | 551 std::string* security_domain) { |
556 // The signon_realm will be the Origin portion of a URL for an HTML form, | 552 // 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. | 553 // and the same but with the security domain as a path for HTTP auth. |
(...skipping 25 matching lines...) Expand all Loading... | |
583 UInt32 port; | 579 UInt32 port; |
584 bool is_secure; | 580 bool is_secure; |
585 if (!ExtractSignonRealmComponents(query_form.signon_realm, &server, &port, | 581 if (!ExtractSignonRealmComponents(query_form.signon_realm, &server, &port, |
586 &is_secure, &security_domain)) { | 582 &is_secure, &security_domain)) { |
587 return false; | 583 return false; |
588 } | 584 } |
589 return internal_keychain_helpers::FormsMatchForMerge( | 585 return internal_keychain_helpers::FormsMatchForMerge( |
590 query_form, other_form, STRICT_FORM_MATCH); | 586 query_form, other_form, STRICT_FORM_MATCH); |
591 } | 587 } |
592 | 588 |
593 std::vector<PasswordForm*> ExtractPasswordsMergeableWithForm( | 589 ScopedVector<autofill::PasswordForm> ExtractPasswordsMergeableWithForm( |
594 const AppleKeychain& keychain, | 590 const AppleKeychain& keychain, |
595 const std::vector<ItemFormPair>& item_form_pairs, | 591 const std::vector<ItemFormPair>& item_form_pairs, |
596 const PasswordForm& query_form) { | 592 const PasswordForm& query_form) { |
597 std::vector<PasswordForm*> matches; | 593 ScopedVector<autofill::PasswordForm> matches; |
598 for (std::vector<ItemFormPair>::const_iterator i = item_form_pairs.begin(); | 594 for (std::vector<ItemFormPair>::const_iterator i = item_form_pairs.begin(); |
599 i != item_form_pairs.end(); ++i) { | 595 i != item_form_pairs.end(); ++i) { |
600 if (FormIsValidAndMatchesOtherForm(query_form, *(i->second))) { | 596 if (FormIsValidAndMatchesOtherForm(query_form, *(i->second))) { |
601 // Create a new object, since the caller is responsible for deleting the | 597 // Create a new object, since the caller is responsible for deleting the |
602 // returned forms. | 598 // returned forms. |
603 scoped_ptr<PasswordForm> form_with_password(new PasswordForm()); | 599 scoped_ptr<PasswordForm> form_with_password(new PasswordForm()); |
604 internal_keychain_helpers::FillPasswordFormFromKeychainItem( | 600 internal_keychain_helpers::FillPasswordFormFromKeychainItem( |
605 keychain, | 601 keychain, *(i->first), form_with_password.get(), |
606 *(i->first), | |
607 form_with_password.get(), | |
608 true); // Load password attributes and data. | 602 true); // Load password attributes and data. |
609 // Do not include blacklisted items found in the keychain. | 603 // Do not include blacklisted items found in the keychain. |
610 if (!form_with_password->blacklisted_by_user) | 604 if (!form_with_password->blacklisted_by_user) |
611 matches.push_back(form_with_password.release()); | 605 matches.push_back(form_with_password.release()); |
612 } | 606 } |
613 } | 607 } |
614 return matches; | 608 return matches.Pass(); |
615 } | 609 } |
616 | 610 |
617 } // namespace internal_keychain_helpers | 611 } // namespace internal_keychain_helpers |
618 | 612 |
619 #pragma mark - | 613 #pragma mark - |
620 | 614 |
621 MacKeychainPasswordFormAdapter::MacKeychainPasswordFormAdapter( | 615 MacKeychainPasswordFormAdapter::MacKeychainPasswordFormAdapter( |
622 const AppleKeychain* keychain) | 616 const AppleKeychain* keychain) |
623 : keychain_(keychain), finds_only_owned_(false) { | 617 : keychain_(keychain), finds_only_owned_(false) { |
624 } | 618 } |
625 | 619 |
626 std::vector<PasswordForm*> MacKeychainPasswordFormAdapter::PasswordsFillingForm( | 620 ScopedVector<autofill::PasswordForm> |
621 MacKeychainPasswordFormAdapter::PasswordsFillingForm( | |
627 const std::string& signon_realm, | 622 const std::string& signon_realm, |
628 PasswordForm::Scheme scheme) { | 623 PasswordForm::Scheme scheme) { |
629 std::vector<SecKeychainItemRef> keychain_items = | 624 std::vector<SecKeychainItemRef> keychain_items = |
630 MatchingKeychainItems(signon_realm, scheme, NULL, NULL); | 625 MatchingKeychainItems(signon_realm, scheme, NULL, NULL); |
631 | |
632 return ConvertKeychainItemsToForms(&keychain_items); | 626 return ConvertKeychainItemsToForms(&keychain_items); |
633 } | 627 } |
634 | 628 |
635 bool MacKeychainPasswordFormAdapter::HasPasswordExactlyMatchingForm( | 629 bool MacKeychainPasswordFormAdapter::HasPasswordExactlyMatchingForm( |
636 const PasswordForm& query_form) { | 630 const PasswordForm& query_form) { |
637 SecKeychainItemRef keychain_item = KeychainItemForForm(query_form); | 631 SecKeychainItemRef keychain_item = KeychainItemForForm(query_form); |
638 if (keychain_item) { | 632 if (keychain_item) { |
639 keychain_->Free(keychain_item); | 633 keychain_->Free(keychain_item); |
640 return true; | 634 return true; |
641 } | 635 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
674 &supported_auth_types[i], | 668 &supported_auth_types[i], |
675 NULL, | 669 NULL, |
676 NULL, | 670 NULL, |
677 NULL, | 671 NULL, |
678 creator ? &creator : NULL); | 672 creator ? &creator : NULL); |
679 keychain_search.FindMatchingItems(&matches); | 673 keychain_search.FindMatchingItems(&matches); |
680 } | 674 } |
681 return matches; | 675 return matches; |
682 } | 676 } |
683 | 677 |
684 std::vector<PasswordForm*> | 678 ScopedVector<autofill::PasswordForm> |
685 MacKeychainPasswordFormAdapter::GetAllPasswordFormPasswords() { | 679 MacKeychainPasswordFormAdapter::GetAllPasswordFormPasswords() { |
686 std::vector<SecKeychainItemRef> items = GetAllPasswordFormKeychainItems(); | 680 std::vector<SecKeychainItemRef> items = GetAllPasswordFormKeychainItems(); |
687 return ConvertKeychainItemsToForms(&items); | 681 return ConvertKeychainItemsToForms(&items); |
688 } | 682 } |
689 | 683 |
690 bool MacKeychainPasswordFormAdapter::AddPassword(const PasswordForm& form) { | 684 bool MacKeychainPasswordFormAdapter::AddPassword(const PasswordForm& form) { |
691 // We should never be trying to store a blacklist in the keychain. | 685 // We should never be trying to store a blacklist in the keychain. |
692 DCHECK(!form.blacklisted_by_user); | 686 DCHECK(!form.blacklisted_by_user); |
693 | 687 |
694 std::string server; | 688 std::string server; |
695 std::string security_domain; | 689 std::string security_domain; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
738 OSStatus result = keychain_->ItemDelete(keychain_item); | 732 OSStatus result = keychain_->ItemDelete(keychain_item); |
739 keychain_->Free(keychain_item); | 733 keychain_->Free(keychain_item); |
740 return result == noErr; | 734 return result == noErr; |
741 } | 735 } |
742 | 736 |
743 void MacKeychainPasswordFormAdapter::SetFindsOnlyOwnedItems( | 737 void MacKeychainPasswordFormAdapter::SetFindsOnlyOwnedItems( |
744 bool finds_only_owned) { | 738 bool finds_only_owned) { |
745 finds_only_owned_ = finds_only_owned; | 739 finds_only_owned_ = finds_only_owned; |
746 } | 740 } |
747 | 741 |
748 std::vector<PasswordForm*> | 742 ScopedVector<autofill::PasswordForm> |
749 MacKeychainPasswordFormAdapter::ConvertKeychainItemsToForms( | 743 MacKeychainPasswordFormAdapter::ConvertKeychainItemsToForms( |
750 std::vector<SecKeychainItemRef>* items) { | 744 std::vector<SecKeychainItemRef>* items) { |
751 std::vector<PasswordForm*> keychain_forms; | 745 ScopedVector<autofill::PasswordForm> forms; |
752 for (std::vector<SecKeychainItemRef>::const_iterator i = items->begin(); | 746 for (SecKeychainItemRef item : *items) { |
753 i != items->end(); ++i) { | 747 scoped_ptr<PasswordForm> form(new PasswordForm()); |
754 PasswordForm* form = new PasswordForm(); | |
755 if (internal_keychain_helpers::FillPasswordFormFromKeychainItem( | 748 if (internal_keychain_helpers::FillPasswordFormFromKeychainItem( |
756 *keychain_, *i, form, true)) { | 749 *keychain_, item, form.get(), true)) { |
757 keychain_forms.push_back(form); | 750 forms.push_back(form.release()); |
758 } | 751 } |
759 keychain_->Free(*i); | 752 keychain_->Free(item); |
760 } | 753 } |
761 items->clear(); | 754 items->clear(); |
762 return keychain_forms; | 755 return forms.Pass(); |
763 } | 756 } |
764 | 757 |
765 SecKeychainItemRef MacKeychainPasswordFormAdapter::KeychainItemForForm( | 758 SecKeychainItemRef MacKeychainPasswordFormAdapter::KeychainItemForForm( |
766 const PasswordForm& form) { | 759 const PasswordForm& form) { |
767 // We don't store blacklist entries in the keychain, so the answer to "what | 760 // 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. | 761 // Keychain item goes with this form" is always "nothing" for blacklists. |
769 if (form.blacklisted_by_user) { | 762 if (form.blacklisted_by_user) { |
770 return NULL; | 763 return NULL; |
771 } | 764 } |
772 | 765 |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
976 | 969 |
977 changes.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE, form)); | 970 changes.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE, form)); |
978 } | 971 } |
979 return changes; | 972 return changes; |
980 } | 973 } |
981 | 974 |
982 PasswordStoreChangeList PasswordStoreMac::RemoveLoginsCreatedBetweenImpl( | 975 PasswordStoreChangeList PasswordStoreMac::RemoveLoginsCreatedBetweenImpl( |
983 base::Time delete_begin, | 976 base::Time delete_begin, |
984 base::Time delete_end) { | 977 base::Time delete_end) { |
985 PasswordStoreChangeList changes; | 978 PasswordStoreChangeList changes; |
986 ScopedVector<PasswordForm> forms; | 979 ScopedVector<PasswordForm> forms_to_remove; |
987 if (login_metadata_db_ && | 980 if (login_metadata_db_ && |
988 login_metadata_db_->GetLoginsCreatedBetween(delete_begin, delete_end, | 981 login_metadata_db_->GetLoginsCreatedBetween(delete_begin, delete_end, |
989 &forms.get()) && | 982 &forms_to_remove) && |
990 login_metadata_db_->RemoveLoginsCreatedBetween(delete_begin, | 983 login_metadata_db_->RemoveLoginsCreatedBetween(delete_begin, |
991 delete_end)) { | 984 delete_end)) { |
992 RemoveKeychainForms(forms.get()); | 985 RemoveKeychainForms(forms_to_remove.get()); |
993 CleanOrphanedForms(&forms.get()); | 986 CleanOrphanedForms(&forms_to_remove); // Add the orphaned forms. |
994 changes = FormsToRemoveChangeList(forms.get()); | 987 changes = FormsToRemoveChangeList(forms_to_remove.get()); |
995 LogStatsForBulkDeletion(changes.size()); | 988 LogStatsForBulkDeletion(changes.size()); |
996 } | 989 } |
997 return changes; | 990 return changes; |
998 } | 991 } |
999 | 992 |
1000 PasswordStoreChangeList PasswordStoreMac::RemoveLoginsSyncedBetweenImpl( | 993 PasswordStoreChangeList PasswordStoreMac::RemoveLoginsSyncedBetweenImpl( |
1001 base::Time delete_begin, | 994 base::Time delete_begin, |
1002 base::Time delete_end) { | 995 base::Time delete_end) { |
1003 PasswordStoreChangeList changes; | 996 PasswordStoreChangeList changes; |
1004 ScopedVector<PasswordForm> forms; | 997 ScopedVector<PasswordForm> forms_to_remove; |
1005 if (login_metadata_db_ && | 998 if (login_metadata_db_ && |
1006 login_metadata_db_->GetLoginsSyncedBetween(delete_begin, delete_end, | 999 login_metadata_db_->GetLoginsSyncedBetween(delete_begin, delete_end, |
1007 &forms.get()) && | 1000 &forms_to_remove) && |
1008 login_metadata_db_->RemoveLoginsSyncedBetween(delete_begin, delete_end)) { | 1001 login_metadata_db_->RemoveLoginsSyncedBetween(delete_begin, delete_end)) { |
1009 RemoveKeychainForms(forms.get()); | 1002 RemoveKeychainForms(forms_to_remove.get()); |
1010 CleanOrphanedForms(&forms.get()); | 1003 CleanOrphanedForms(&forms_to_remove); // Add the orphaned forms_to_remove. |
1011 changes = FormsToRemoveChangeList(forms.get()); | 1004 changes = FormsToRemoveChangeList(forms_to_remove.get()); |
1012 LogStatsForBulkDeletionDuringRollback(changes.size()); | 1005 LogStatsForBulkDeletionDuringRollback(changes.size()); |
1013 } | 1006 } |
1014 return changes; | 1007 return changes; |
1015 } | 1008 } |
1016 | 1009 |
1017 void PasswordStoreMac::GetLoginsImpl( | 1010 void PasswordStoreMac::GetLoginsImpl( |
1018 const autofill::PasswordForm& form, | 1011 const autofill::PasswordForm& form, |
1019 AuthorizationPromptPolicy prompt_policy, | 1012 AuthorizationPromptPolicy prompt_policy, |
1020 const ConsumerCallbackRunner& callback_runner) { | 1013 const ConsumerCallbackRunner& callback_runner) { |
1021 chrome::ScopedSecKeychainSetUserInteractionAllowed user_interaction_allowed( | 1014 chrome::ScopedSecKeychainSetUserInteractionAllowed user_interaction_allowed( |
1022 prompt_policy == ALLOW_PROMPT); | 1015 prompt_policy == ALLOW_PROMPT); |
1023 | 1016 |
1024 if (!login_metadata_db_) { | 1017 if (!login_metadata_db_) { |
1025 callback_runner.Run(std::vector<PasswordForm*>()); | 1018 callback_runner.Run(ScopedVector<autofill::PasswordForm>()); |
1026 return; | 1019 return; |
1027 } | 1020 } |
1028 | 1021 |
1029 ScopedVector<PasswordForm> database_forms; | 1022 ScopedVector<PasswordForm> database_forms; |
1030 login_metadata_db_->GetLogins(form, &database_forms.get()); | 1023 login_metadata_db_->GetLogins(form, &database_forms); |
1031 | 1024 |
1032 // Let's gather all signon realms we want to match with keychain entries. | 1025 // Let's gather all signon realms we want to match with keychain entries. |
1033 std::set<std::string> realm_set; | 1026 std::set<std::string> realm_set; |
1034 realm_set.insert(form.signon_realm); | 1027 realm_set.insert(form.signon_realm); |
1035 for (std::vector<PasswordForm*>::const_iterator db_form = | 1028 for (const autofill::PasswordForm* db_form : database_forms) { |
1036 database_forms.begin(); | |
1037 db_form != database_forms.end(); | |
1038 ++db_form) { | |
1039 // TODO(vabr): We should not be getting different schemes here. | 1029 // TODO(vabr): We should not be getting different schemes here. |
1040 // http://crbug.com/340112 | 1030 // http://crbug.com/340112 |
1041 if (form.scheme != (*db_form)->scheme) | 1031 if (form.scheme != db_form->scheme) |
1042 continue; // Forms with different schemes never match. | 1032 continue; // Forms with different schemes never match. |
1043 const std::string& original_singon_realm((*db_form)->original_signon_realm); | 1033 const std::string& original_singon_realm(db_form->original_signon_realm); |
1044 if (!original_singon_realm.empty()) | 1034 if (!original_singon_realm.empty()) |
1045 realm_set.insert(original_singon_realm); | 1035 realm_set.insert(original_singon_realm); |
1046 } | 1036 } |
1047 std::vector<PasswordForm*> keychain_forms; | 1037 ScopedVector<autofill::PasswordForm> keychain_forms; |
1048 for (std::set<std::string>::const_iterator realm = realm_set.begin(); | 1038 for (std::set<std::string>::const_iterator realm = realm_set.begin(); |
1049 realm != realm_set.end(); | 1039 realm != realm_set.end(); ++realm) { |
1050 ++realm) { | |
1051 MacKeychainPasswordFormAdapter keychain_adapter(keychain_.get()); | 1040 MacKeychainPasswordFormAdapter keychain_adapter(keychain_.get()); |
1052 std::vector<PasswordForm*> temp_keychain_forms = | 1041 ScopedVector<autofill::PasswordForm> temp_keychain_forms( |
1053 keychain_adapter.PasswordsFillingForm(*realm, form.scheme); | 1042 keychain_adapter.PasswordsFillingForm(*realm, form.scheme)); |
1054 keychain_forms.insert(keychain_forms.end(), | 1043 AppendSecondToFirst(&keychain_forms, &temp_keychain_forms); |
1055 temp_keychain_forms.begin(), | |
1056 temp_keychain_forms.end()); | |
1057 } | 1044 } |
1058 | 1045 |
1059 std::vector<PasswordForm*> matched_forms; | 1046 ScopedVector<autofill::PasswordForm> matched_forms; |
1060 internal_keychain_helpers::MergePasswordForms(&keychain_forms, | 1047 internal_keychain_helpers::MergePasswordForms( |
1061 &database_forms.get(), | 1048 &keychain_forms, &database_forms, &matched_forms); |
1062 &matched_forms); | |
1063 | 1049 |
1064 // Strip any blacklist entries out of the unused Keychain array, then take | 1050 // 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). | 1051 // all the entries that are left (which we can use as imported passwords). |
1066 ScopedVector<PasswordForm> keychain_blacklist_forms; | 1052 ScopedVector<PasswordForm> keychain_blacklist_forms; |
1067 internal_keychain_helpers::ExtractBlacklistForms(&keychain_forms).swap( | 1053 internal_keychain_helpers::ExtractBlacklistForms(&keychain_forms, |
1068 keychain_blacklist_forms.get()); | 1054 &keychain_blacklist_forms); |
1069 matched_forms.insert(matched_forms.end(), | 1055 matched_forms.insert(matched_forms.end(), |
1070 keychain_forms.begin(), | 1056 keychain_forms.begin(), |
1071 keychain_forms.end()); | 1057 keychain_forms.end()); |
1072 keychain_forms.clear(); | 1058 keychain_forms.weak_clear(); |
1073 | 1059 |
1074 if (!database_forms.empty()) { | 1060 if (!database_forms.empty()) { |
1075 RemoveDatabaseForms(database_forms.get()); | 1061 RemoveDatabaseForms(database_forms.get()); |
1076 NotifyLoginsChanged(FormsToRemoveChangeList(database_forms.get())); | 1062 NotifyLoginsChanged(FormsToRemoveChangeList(database_forms.get())); |
1077 } | 1063 } |
1078 | 1064 |
1079 callback_runner.Run(matched_forms); | 1065 callback_runner.Run(matched_forms.Pass()); |
1080 } | 1066 } |
1081 | 1067 |
1082 void PasswordStoreMac::GetBlacklistLoginsImpl(GetLoginsRequest* request) { | 1068 void PasswordStoreMac::GetBlacklistLoginsImpl(GetLoginsRequest* request) { |
1083 FillBlacklistLogins(request->result()); | 1069 ScopedVector<autofill::PasswordForm> obtained_forms; |
1070 FillBlacklistLogins(&obtained_forms); | |
1071 request->result()->swap(obtained_forms.get()); | |
1084 ForwardLoginsResult(request); | 1072 ForwardLoginsResult(request); |
1085 } | 1073 } |
1086 | 1074 |
1087 void PasswordStoreMac::GetAutofillableLoginsImpl(GetLoginsRequest* request) { | 1075 void PasswordStoreMac::GetAutofillableLoginsImpl(GetLoginsRequest* request) { |
1088 FillAutofillableLogins(request->result()); | 1076 ScopedVector<autofill::PasswordForm> obtained_forms; |
1077 FillAutofillableLogins(&obtained_forms); | |
1078 request->result()->swap(obtained_forms.get()); | |
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 autofill::PasswordForm* db_form : database_forms) { |
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 |