OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/password_manager/password_store_mac.h" | 5 #include "chrome/browser/password_manager/password_store_mac.h" |
6 | 6 |
7 #include <CoreServices/CoreServices.h> | 7 #include <CoreServices/CoreServices.h> |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <set> | 10 #include <set> |
11 #include <string> | 11 #include <string> |
12 #include <utility> | 12 #include <utility> |
13 #include <vector> | 13 #include <vector> |
14 | 14 |
15 #include "base/callback.h" | 15 #include "base/callback.h" |
16 #include "base/logging.h" | 16 #include "base/logging.h" |
17 #include "base/mac/foundation_util.h" | 17 #include "base/mac/foundation_util.h" |
18 #include "base/mac/mac_logging.h" | 18 #include "base/mac/mac_logging.h" |
19 #include "base/macros.h" | 19 #include "base/macros.h" |
| 20 #include "base/memory/ptr_util.h" |
20 #include "base/message_loop/message_loop.h" | 21 #include "base/message_loop/message_loop.h" |
21 #include "base/metrics/histogram_macros.h" | 22 #include "base/metrics/histogram_macros.h" |
22 #include "base/stl_util.h" | |
23 #include "base/strings/string_util.h" | 23 #include "base/strings/string_util.h" |
24 #include "base/strings/utf_string_conversions.h" | 24 #include "base/strings/utf_string_conversions.h" |
25 #include "chrome/browser/mac/security_wrappers.h" | 25 #include "chrome/browser/mac/security_wrappers.h" |
26 #include "chrome/browser/password_manager/password_store_mac_internal.h" | 26 #include "chrome/browser/password_manager/password_store_mac_internal.h" |
27 #include "components/os_crypt/os_crypt.h" | 27 #include "components/os_crypt/os_crypt.h" |
28 #include "components/password_manager/core/browser/affiliation_utils.h" | 28 #include "components/password_manager/core/browser/affiliation_utils.h" |
29 #include "components/password_manager/core/browser/login_database.h" | 29 #include "components/password_manager/core/browser/login_database.h" |
30 #include "components/password_manager/core/browser/password_manager_util.h" | 30 #include "components/password_manager/core/browser/password_manager_util.h" |
31 #include "components/password_manager/core/browser/password_store_change.h" | 31 #include "components/password_manager/core/browser/password_store_change.h" |
32 #include "content/public/browser/browser_thread.h" | 32 #include "content/public/browser/browser_thread.h" |
33 #include "crypto/apple_keychain.h" | 33 #include "crypto/apple_keychain.h" |
34 #include "url/origin.h" | 34 #include "url/origin.h" |
35 | 35 |
36 using autofill::PasswordForm; | 36 using autofill::PasswordForm; |
37 using crypto::AppleKeychain; | 37 using crypto::AppleKeychain; |
38 using password_manager::PasswordStoreChange; | 38 using password_manager::PasswordStoreChange; |
39 using password_manager::PasswordStoreChangeList; | 39 using password_manager::PasswordStoreChangeList; |
40 | 40 |
41 namespace { | 41 namespace { |
42 | 42 |
43 // Utility class to handle the details of constructing and running a keychain | 43 // Utility class to handle the details of constructing and running a keychain |
44 // search from a set of attributes. | 44 // search from a set of attributes. |
45 class KeychainSearch { | 45 class KeychainSearch { |
46 public: | 46 public: |
47 explicit KeychainSearch(const AppleKeychain& keychain); | 47 explicit KeychainSearch(const AppleKeychain& keychain); |
48 ~KeychainSearch(); | 48 ~KeychainSearch(); |
49 | 49 |
50 // Sets up a keycahin search based on an non "null" (NULL for char*, | 50 // Sets up a keychain search based on an non "null" (NULL for char*, |
51 // The appropriate "Any" entry for other types) arguments. | 51 // The appropriate "Any" entry for other types) arguments. |
52 // | 52 // |
53 // IMPORTANT: Any paramaters passed in *must* remain valid for as long as the | 53 // IMPORTANT: Any parameters passed in *must* remain valid for as long as the |
54 // KeychainSearch object, since the search uses them by reference. | 54 // KeychainSearch object, since the search uses them by reference. |
55 void Init(const char* server, | 55 void Init(const char* server, |
56 const UInt32* port, | 56 const UInt32* port, |
57 const SecProtocolType* protocol, | 57 const SecProtocolType* protocol, |
58 const SecAuthenticationType* auth_type, | 58 const SecAuthenticationType* auth_type, |
59 const char* security_domain, | 59 const char* security_domain, |
60 const char* path, | 60 const char* path, |
61 const char* username, | 61 const char* username, |
62 const OSType* creator); | 62 const OSType* creator); |
63 | 63 |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 PasswordForm::Scheme SchemeForAuthType(SecAuthenticationType auth_type) { | 318 PasswordForm::Scheme SchemeForAuthType(SecAuthenticationType auth_type) { |
319 switch (auth_type) { | 319 switch (auth_type) { |
320 case kSecAuthenticationTypeHTMLForm: return PasswordForm::SCHEME_HTML; | 320 case kSecAuthenticationTypeHTMLForm: return PasswordForm::SCHEME_HTML; |
321 case kSecAuthenticationTypeHTTPBasic: return PasswordForm::SCHEME_BASIC; | 321 case kSecAuthenticationTypeHTTPBasic: return PasswordForm::SCHEME_BASIC; |
322 case kSecAuthenticationTypeHTTPDigest: return PasswordForm::SCHEME_DIGEST; | 322 case kSecAuthenticationTypeHTTPDigest: return PasswordForm::SCHEME_DIGEST; |
323 default: return PasswordForm::SCHEME_OTHER; | 323 default: return PasswordForm::SCHEME_OTHER; |
324 } | 324 } |
325 } | 325 } |
326 | 326 |
327 bool FillPasswordFormFromKeychainItem(const AppleKeychain& keychain, | 327 bool FillPasswordFormFromKeychainItem(const AppleKeychain& keychain, |
328 const SecKeychainItemRef& keychain_item, | 328 SecKeychainItemRef keychain_item, |
329 PasswordForm* form, | 329 PasswordForm* form, |
330 bool extract_password_data) { | 330 bool extract_password_data) { |
331 DCHECK(form); | 331 DCHECK(form); |
332 | 332 |
333 SecKeychainAttributeInfo attrInfo; | 333 SecKeychainAttributeInfo attrInfo; |
334 UInt32 tags[] = { kSecAccountItemAttr, | 334 UInt32 tags[] = { kSecAccountItemAttr, |
335 kSecServerItemAttr, | 335 kSecServerItemAttr, |
336 kSecPortItemAttr, | 336 kSecPortItemAttr, |
337 kSecPathItemAttr, | 337 kSecPathItemAttr, |
338 kSecProtocolItemAttr, | 338 kSecProtocolItemAttr, |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
450 // format. | 450 // format. |
451 form->signon_realm = form->origin.GetOrigin().spec(); | 451 form->signon_realm = form->origin.GetOrigin().spec(); |
452 if (form->scheme != PasswordForm::SCHEME_HTML) { | 452 if (form->scheme != PasswordForm::SCHEME_HTML) { |
453 form->signon_realm.append(security_domain); | 453 form->signon_realm.append(security_domain); |
454 } | 454 } |
455 } | 455 } |
456 return true; | 456 return true; |
457 } | 457 } |
458 | 458 |
459 bool HasChromeCreatorCode(const AppleKeychain& keychain, | 459 bool HasChromeCreatorCode(const AppleKeychain& keychain, |
460 const SecKeychainItemRef& keychain_item) { | 460 SecKeychainItemRef keychain_item) { |
461 SecKeychainAttributeInfo attr_info; | 461 SecKeychainAttributeInfo attr_info; |
462 UInt32 tags[] = {kSecCreatorItemAttr}; | 462 UInt32 tags[] = {kSecCreatorItemAttr}; |
463 attr_info.count = arraysize(tags); | 463 attr_info.count = arraysize(tags); |
464 attr_info.tag = tags; | 464 attr_info.tag = tags; |
465 attr_info.format = nullptr; | 465 attr_info.format = nullptr; |
466 | 466 |
467 SecKeychainAttributeList* attr_list; | 467 SecKeychainAttributeList* attr_list; |
468 UInt32 password_length; | 468 UInt32 password_length; |
469 OSStatus result = keychain.ItemCopyAttributesAndData( | 469 OSStatus result = keychain.ItemCopyAttributesAndData( |
470 keychain_item, &attr_info, nullptr, &attr_list, | 470 keychain_item, &attr_info, nullptr, &attr_list, |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
569 keychain_forms->swap(unused_keychain_forms); | 569 keychain_forms->swap(unused_keychain_forms); |
570 } | 570 } |
571 | 571 |
572 std::vector<ItemFormPair> ExtractAllKeychainItemAttributesIntoPasswordForms( | 572 std::vector<ItemFormPair> ExtractAllKeychainItemAttributesIntoPasswordForms( |
573 std::vector<SecKeychainItemRef>* keychain_items, | 573 std::vector<SecKeychainItemRef>* keychain_items, |
574 const AppleKeychain& keychain) { | 574 const AppleKeychain& keychain) { |
575 DCHECK(keychain_items); | 575 DCHECK(keychain_items); |
576 MacKeychainPasswordFormAdapter keychain_adapter(&keychain); | 576 MacKeychainPasswordFormAdapter keychain_adapter(&keychain); |
577 *keychain_items = keychain_adapter.GetAllPasswordFormKeychainItems(); | 577 *keychain_items = keychain_adapter.GetAllPasswordFormKeychainItems(); |
578 std::vector<ItemFormPair> item_form_pairs; | 578 std::vector<ItemFormPair> item_form_pairs; |
579 for (std::vector<SecKeychainItemRef>::iterator i = keychain_items->begin(); | 579 for (const auto& keychain_item : *keychain_items) { |
580 i != keychain_items->end(); ++i) { | 580 std::unique_ptr<PasswordForm> form_without_password = |
581 PasswordForm* form_without_password = new PasswordForm(); | 581 base::MakeUnique<PasswordForm>(); |
582 internal_keychain_helpers::FillPasswordFormFromKeychainItem( | 582 internal_keychain_helpers::FillPasswordFormFromKeychainItem( |
583 keychain, | 583 keychain, keychain_item, form_without_password.get(), |
584 *i, | |
585 form_without_password, | |
586 false); // Load password attributes, but not password data. | 584 false); // Load password attributes, but not password data. |
587 item_form_pairs.push_back(std::make_pair(&(*i), form_without_password)); | 585 item_form_pairs.push_back( |
| 586 std::make_pair(keychain_item, std::move(form_without_password))); |
588 } | 587 } |
589 return item_form_pairs; | 588 return item_form_pairs; |
590 } | 589 } |
591 | 590 |
592 void GetPasswordsForForms(const AppleKeychain& keychain, | 591 void GetPasswordsForForms(const AppleKeychain& keychain, |
593 ScopedVector<autofill::PasswordForm>* database_forms, | 592 ScopedVector<autofill::PasswordForm>* database_forms, |
594 ScopedVector<autofill::PasswordForm>* passwords) { | 593 ScopedVector<autofill::PasswordForm>* passwords) { |
595 // First load the attributes of all items in the keychain without loading | 594 // First load the attributes of all items in the keychain without loading |
596 // their password data, and then match items in |database_forms| against them. | 595 // their password data, and then match items in |database_forms| against them. |
597 // This avoids individually searching through the keychain for passwords | 596 // This avoids individually searching through the keychain for passwords |
(...skipping 20 matching lines...) Expand all Loading... |
618 ScopedVector<autofill::PasswordForm> keychain_matches = | 617 ScopedVector<autofill::PasswordForm> keychain_matches = |
619 ExtractPasswordsMergeableWithForm(keychain, item_form_pairs, *form); | 618 ExtractPasswordsMergeableWithForm(keychain, item_form_pairs, *form); |
620 | 619 |
621 ScopedVector<autofill::PasswordForm> db_form_container; | 620 ScopedVector<autofill::PasswordForm> db_form_container; |
622 db_form_container.push_back(std::move(form)); | 621 db_form_container.push_back(std::move(form)); |
623 MergePasswordForms(&keychain_matches, &db_form_container, passwords); | 622 MergePasswordForms(&keychain_matches, &db_form_container, passwords); |
624 AppendSecondToFirst(&unused_db_forms, &db_form_container); | 623 AppendSecondToFirst(&unused_db_forms, &db_form_container); |
625 }); | 624 }); |
626 database_forms->swap(unused_db_forms); | 625 database_forms->swap(unused_db_forms); |
627 | 626 |
628 base::STLDeleteContainerPairSecondPointers(item_form_pairs.begin(), | |
629 item_form_pairs.end()); | |
630 for (SecKeychainItemRef item : keychain_items) { | 627 for (SecKeychainItemRef item : keychain_items) { |
631 keychain.Free(item); | 628 keychain.Free(item); |
632 } | 629 } |
633 } | 630 } |
634 | 631 |
635 // TODO(stuartmorgan): signon_realm for proxies is not yet supported. | 632 // TODO(stuartmorgan): signon_realm for proxies is not yet supported. |
636 bool ExtractSignonRealmComponents(const std::string& signon_realm, | 633 bool ExtractSignonRealmComponents(const std::string& signon_realm, |
637 std::string* server, | 634 std::string* server, |
638 UInt32* port, | 635 UInt32* port, |
639 bool* is_secure, | 636 bool* is_secure, |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
692 const std::vector<ItemFormPair>& item_form_pairs, | 689 const std::vector<ItemFormPair>& item_form_pairs, |
693 const PasswordForm& query_form) { | 690 const PasswordForm& query_form) { |
694 ScopedVector<autofill::PasswordForm> matches; | 691 ScopedVector<autofill::PasswordForm> matches; |
695 for (std::vector<ItemFormPair>::const_iterator i = item_form_pairs.begin(); | 692 for (std::vector<ItemFormPair>::const_iterator i = item_form_pairs.begin(); |
696 i != item_form_pairs.end(); ++i) { | 693 i != item_form_pairs.end(); ++i) { |
697 if (FormIsValidAndMatchesOtherForm(query_form, *(i->second))) { | 694 if (FormIsValidAndMatchesOtherForm(query_form, *(i->second))) { |
698 // Create a new object, since the caller is responsible for deleting the | 695 // Create a new object, since the caller is responsible for deleting the |
699 // returned forms. | 696 // returned forms. |
700 std::unique_ptr<PasswordForm> form_with_password(new PasswordForm()); | 697 std::unique_ptr<PasswordForm> form_with_password(new PasswordForm()); |
701 FillPasswordFormFromKeychainItem( | 698 FillPasswordFormFromKeychainItem( |
702 keychain, *(i->first), form_with_password.get(), | 699 keychain, i->first, form_with_password.get(), |
703 true); // Load password attributes and data. | 700 true); // Load password attributes and data. |
704 // Do not include blacklisted items found in the keychain. | 701 // Do not include blacklisted items found in the keychain. |
705 if (!form_with_password->blacklisted_by_user) | 702 if (!form_with_password->blacklisted_by_user) |
706 matches.push_back(std::move(form_with_password)); | 703 matches.push_back(std::move(form_with_password)); |
707 } | 704 } |
708 } | 705 } |
709 return matches; | 706 return matches; |
710 } | 707 } |
711 | 708 |
712 } // namespace internal_keychain_helpers | 709 } // namespace internal_keychain_helpers |
(...skipping 25 matching lines...) Expand all Loading... |
738 } | 735 } |
739 | 736 |
740 bool MacKeychainPasswordFormAdapter::HasPasswordsMergeableWithForm( | 737 bool MacKeychainPasswordFormAdapter::HasPasswordsMergeableWithForm( |
741 const PasswordForm& query_form) { | 738 const PasswordForm& query_form) { |
742 if (IsLoginDatabaseOnlyForm(query_form)) | 739 if (IsLoginDatabaseOnlyForm(query_form)) |
743 return false; | 740 return false; |
744 std::string username = base::UTF16ToUTF8(query_form.username_value); | 741 std::string username = base::UTF16ToUTF8(query_form.username_value); |
745 std::vector<SecKeychainItemRef> matches = | 742 std::vector<SecKeychainItemRef> matches = |
746 MatchingKeychainItems(query_form.signon_realm, query_form.scheme, | 743 MatchingKeychainItems(query_form.signon_realm, query_form.scheme, |
747 NULL, username.c_str()); | 744 NULL, username.c_str()); |
748 for (std::vector<SecKeychainItemRef>::iterator i = matches.begin(); | 745 for (SecKeychainItemRef item : matches) |
749 i != matches.end(); ++i) { | 746 keychain_->Free(item); |
750 keychain_->Free(*i); | |
751 } | |
752 | 747 |
753 return !matches.empty(); | 748 return !matches.empty(); |
754 } | 749 } |
755 | 750 |
756 std::vector<SecKeychainItemRef> | 751 std::vector<SecKeychainItemRef> |
757 MacKeychainPasswordFormAdapter::GetAllPasswordFormKeychainItems() { | 752 MacKeychainPasswordFormAdapter::GetAllPasswordFormKeychainItems() { |
758 SecAuthenticationType supported_auth_types[] = { | 753 SecAuthenticationType supported_auth_types[] = { |
759 kSecAuthenticationTypeHTMLForm, | 754 kSecAuthenticationTypeHTMLForm, |
760 kSecAuthenticationTypeHTTPBasic, | 755 kSecAuthenticationTypeHTTPBasic, |
761 kSecAuthenticationTypeHTTPDigest, | 756 kSecAuthenticationTypeHTTPDigest, |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
873 // Path doesn't make sense for Android app credentials. | 868 // Path doesn't make sense for Android app credentials. |
874 if (!password_manager::IsValidAndroidFacetURI(form.signon_realm)) | 869 if (!password_manager::IsValidAndroidFacetURI(form.signon_realm)) |
875 path = form.origin.path(); | 870 path = form.origin.path(); |
876 std::string username = base::UTF16ToUTF8(form.username_value); | 871 std::string username = base::UTF16ToUTF8(form.username_value); |
877 std::vector<SecKeychainItemRef> matches = MatchingKeychainItems( | 872 std::vector<SecKeychainItemRef> matches = MatchingKeychainItems( |
878 form.signon_realm, form.scheme, path.c_str(), username.c_str()); | 873 form.signon_realm, form.scheme, path.c_str(), username.c_str()); |
879 | 874 |
880 if (matches.empty()) { | 875 if (matches.empty()) { |
881 return NULL; | 876 return NULL; |
882 } | 877 } |
| 878 |
883 // Free all items after the first, since we won't be returning them. | 879 // Free all items after the first, since we won't be returning them. |
884 for (std::vector<SecKeychainItemRef>::iterator i = matches.begin() + 1; | 880 for (auto i = matches.begin() + 1; i != matches.end(); ++i) |
885 i != matches.end(); ++i) { | |
886 keychain_->Free(*i); | 881 keychain_->Free(*i); |
887 } | 882 |
888 return matches[0]; | 883 return matches[0]; |
889 } | 884 } |
890 | 885 |
891 std::vector<SecKeychainItemRef> | 886 std::vector<SecKeychainItemRef> |
892 MacKeychainPasswordFormAdapter::MatchingKeychainItems( | 887 MacKeychainPasswordFormAdapter::MatchingKeychainItems( |
893 const std::string& signon_realm, | 888 const std::string& signon_realm, |
894 autofill::PasswordForm::Scheme scheme, | 889 autofill::PasswordForm::Scheme scheme, |
895 const char* path, const char* username) { | 890 const char* path, const char* username) { |
896 std::vector<SecKeychainItemRef> matches; | 891 std::vector<SecKeychainItemRef> matches; |
897 | 892 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
935 case PasswordForm::SCHEME_OTHER: return kSecAuthenticationTypeDefault; | 930 case PasswordForm::SCHEME_OTHER: return kSecAuthenticationTypeDefault; |
936 case PasswordForm::SCHEME_USERNAME_ONLY: | 931 case PasswordForm::SCHEME_USERNAME_ONLY: |
937 NOTREACHED(); | 932 NOTREACHED(); |
938 break; | 933 break; |
939 } | 934 } |
940 NOTREACHED(); | 935 NOTREACHED(); |
941 return kSecAuthenticationTypeDefault; | 936 return kSecAuthenticationTypeDefault; |
942 } | 937 } |
943 | 938 |
944 bool MacKeychainPasswordFormAdapter::SetKeychainItemPassword( | 939 bool MacKeychainPasswordFormAdapter::SetKeychainItemPassword( |
945 const SecKeychainItemRef& keychain_item, const std::string& password) { | 940 SecKeychainItemRef keychain_item, |
| 941 const std::string& password) { |
946 OSStatus result = keychain_->ItemModifyAttributesAndData(keychain_item, NULL, | 942 OSStatus result = keychain_->ItemModifyAttributesAndData(keychain_item, NULL, |
947 password.size(), | 943 password.size(), |
948 password.c_str()); | 944 password.c_str()); |
949 return result == noErr; | 945 return result == noErr; |
950 } | 946 } |
951 | 947 |
952 bool MacKeychainPasswordFormAdapter::SetKeychainItemCreatorCode( | 948 bool MacKeychainPasswordFormAdapter::SetKeychainItemCreatorCode( |
953 const SecKeychainItemRef& keychain_item, OSType creator_code) { | 949 SecKeychainItemRef keychain_item, |
| 950 OSType creator_code) { |
954 SecKeychainAttribute attr = { kSecCreatorItemAttr, sizeof(creator_code), | 951 SecKeychainAttribute attr = { kSecCreatorItemAttr, sizeof(creator_code), |
955 &creator_code }; | 952 &creator_code }; |
956 SecKeychainAttributeList attrList = { 1, &attr }; | 953 SecKeychainAttributeList attrList = { 1, &attr }; |
957 OSStatus result = keychain_->ItemModifyAttributesAndData(keychain_item, | 954 OSStatus result = keychain_->ItemModifyAttributesAndData(keychain_item, |
958 &attrList, 0, NULL); | 955 &attrList, 0, NULL); |
959 return result == noErr; | 956 return result == noErr; |
960 } | 957 } |
961 | 958 |
962 OSType MacKeychainPasswordFormAdapter::CreatorCodeForSearch() { | 959 OSType MacKeychainPasswordFormAdapter::CreatorCodeForSearch() { |
963 return finds_only_owned_ ? base::mac::CreatorCodeForApplication() : 0; | 960 return finds_only_owned_ ? base::mac::CreatorCodeForApplication() : 0; |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1033 if (best_match) { | 1030 if (best_match) { |
1034 form->password_value = best_match->password_value; | 1031 form->password_value = best_match->password_value; |
1035 PasswordStoreChangeList change = login_db->UpdateLogin(*form); | 1032 PasswordStoreChangeList change = login_db->UpdateLogin(*form); |
1036 DCHECK_EQ(1u, change.size()); | 1033 DCHECK_EQ(1u, change.size()); |
1037 } else { | 1034 } else { |
1038 unmerged_forms_count++; | 1035 unmerged_forms_count++; |
1039 bool removed = login_db->RemoveLogin(*form); | 1036 bool removed = login_db->RemoveLogin(*form); |
1040 DCHECK(removed); | 1037 DCHECK(removed); |
1041 } | 1038 } |
1042 } | 1039 } |
1043 base::STLDeleteContainerPairSecondPointers(item_form_pairs.begin(), | |
1044 item_form_pairs.end()); | |
1045 for (SecKeychainItemRef item : keychain_items) | 1040 for (SecKeychainItemRef item : keychain_items) |
1046 keychain->Free(item); | 1041 keychain->Free(item); |
1047 | 1042 |
1048 if (unmerged_forms_count) { | 1043 if (unmerged_forms_count) { |
1049 UMA_HISTOGRAM_COUNTS( | 1044 UMA_HISTOGRAM_COUNTS( |
1050 "PasswordManager.KeychainMigration.NumPasswordsOnFailure", | 1045 "PasswordManager.KeychainMigration.NumPasswordsOnFailure", |
1051 database_forms.size()); | 1046 database_forms.size()); |
1052 UMA_HISTOGRAM_COUNTS("PasswordManager.KeychainMigration.NumFailedPasswords", | 1047 UMA_HISTOGRAM_COUNTS("PasswordManager.KeychainMigration.NumFailedPasswords", |
1053 unmerged_forms_count); | 1048 unmerged_forms_count); |
1054 return MIGRATION_PARTIAL; | 1049 return MIGRATION_PARTIAL; |
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1425 ScopedVector<PasswordForm> forms_with_keychain_entry; | 1420 ScopedVector<PasswordForm> forms_with_keychain_entry; |
1426 internal_keychain_helpers::GetPasswordsForForms(*keychain_, &database_forms, | 1421 internal_keychain_helpers::GetPasswordsForForms(*keychain_, &database_forms, |
1427 &forms_with_keychain_entry); | 1422 &forms_with_keychain_entry); |
1428 | 1423 |
1429 // Clean up any orphaned database entries. | 1424 // Clean up any orphaned database entries. |
1430 RemoveDatabaseForms(&database_forms); | 1425 RemoveDatabaseForms(&database_forms); |
1431 | 1426 |
1432 // Move the orphaned DB forms to the output parameter. | 1427 // Move the orphaned DB forms to the output parameter. |
1433 AppendSecondToFirst(orphaned_forms, &database_forms); | 1428 AppendSecondToFirst(orphaned_forms, &database_forms); |
1434 } | 1429 } |
OLD | NEW |