OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "components/autofill/core/browser/personal_data_manager.h" | 5 #include "components/autofill/core/browser/personal_data_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <functional> | 8 #include <functional> |
9 #include <iterator> | 9 #include <iterator> |
10 | 10 |
(...skipping 725 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
736 void PersonalDataManager::Refresh() { | 736 void PersonalDataManager::Refresh() { |
737 LoadProfiles(); | 737 LoadProfiles(); |
738 LoadCreditCards(); | 738 LoadCreditCards(); |
739 } | 739 } |
740 | 740 |
741 std::vector<Suggestion> PersonalDataManager::GetProfileSuggestions( | 741 std::vector<Suggestion> PersonalDataManager::GetProfileSuggestions( |
742 const AutofillType& type, | 742 const AutofillType& type, |
743 const base::string16& field_contents, | 743 const base::string16& field_contents, |
744 bool field_is_autofilled, | 744 bool field_is_autofilled, |
745 const std::vector<ServerFieldType>& other_field_types) { | 745 const std::vector<ServerFieldType>& other_field_types) { |
746 std::vector<Suggestion> suggestions; | |
747 base::string16 field_contents_canon = | 746 base::string16 field_contents_canon = |
748 AutofillProfile::CanonicalizeProfileString(field_contents); | 747 AutofillProfile::CanonicalizeProfileString(field_contents); |
749 | 748 |
750 std::vector<AutofillProfile*> profiles = GetProfiles(true); | 749 std::vector<AutofillProfile*> profiles = GetProfiles(true); |
751 std::sort(profiles.begin(), profiles.end(), RankByMfu); | 750 std::sort(profiles.begin(), profiles.end(), RankByMfu); |
752 | 751 |
753 if (field_is_autofilled) { | 752 if (field_is_autofilled) { |
| 753 std::vector<Suggestion> suggestions; |
754 // This field was previously autofilled. In this case, suggesting results | 754 // This field was previously autofilled. In this case, suggesting results |
755 // based on prefix is useless since it will be the same thing. Instead, | 755 // based on prefix is useless since it will be the same thing. Instead, |
756 // check for a field that may have multiple possible values (for example, | 756 // check for a field that may have multiple possible values (for example, |
757 // multiple names for the same address) and suggest the alternates. This | 757 // multiple names for the same address) and suggest the alternates. This |
758 // allows for easy correction of the data. | 758 // allows for easy correction of the data. |
759 for (AutofillProfile* profile : profiles) { | 759 for (AutofillProfile* profile : profiles) { |
760 std::vector<base::string16> values = | 760 std::vector<base::string16> values = |
761 GetMultiInfoInOneLine(profile, type, app_locale_); | 761 GetMultiInfoInOneLine(profile, type, app_locale_); |
762 | 762 |
763 // Check if the contents of this field match any of the inputs. | 763 // Check if the contents of this field match any of the inputs. |
764 bool matches_field = false; | 764 bool matches_field = false; |
765 for (const base::string16& value : values) { | 765 for (const base::string16& value : values) { |
766 if (MatchesInput(value, field_contents_canon, type)) { | 766 if (MatchesInput(value, field_contents_canon, type)) { |
767 matches_field = true; | 767 matches_field = true; |
768 break; | 768 break; |
769 } | 769 } |
770 } | 770 } |
771 | 771 |
772 if (matches_field) { | 772 if (matches_field) { |
773 // Field unmodified, make alternate suggestions. | 773 // Field unmodified, make alternate suggestions. |
774 for (size_t i = 0; i < values.size(); i++) { | 774 for (size_t i = 0; i < values.size(); i++) { |
775 if (values[i].empty()) | 775 if (values[i].empty()) |
776 continue; | 776 continue; |
777 suggestions.push_back(Suggestion(values[i])); | |
778 suggestions.back().backend_id.guid = profile->guid(); | |
779 suggestions.back().backend_id.variant = i; | |
780 } | |
781 } | |
782 } | |
783 } else { | |
784 // Match based on a prefix search. | |
785 std::vector<AutofillProfile*> matched_profiles; | |
786 for (AutofillProfile* profile : profiles) { | |
787 std::vector<base::string16> values = | |
788 GetMultiInfoInOneLine(profile, type, app_locale_); | |
789 for (size_t i = 0; i < values.size(); i++) { | |
790 if (values[i].empty()) | |
791 continue; | |
792 | 777 |
793 base::string16 value_canon = | 778 bool is_unique = true; |
794 AutofillProfile::CanonicalizeProfileString(values[i]); | 779 for (size_t j = 0; j < suggestions.size(); ++j) { |
795 if (StartsWith(value_canon, field_contents_canon, true)) { | 780 if (values[i] == suggestions[j].value) { |
796 // Prefix match, add suggestion. | 781 is_unique = false; |
797 matched_profiles.push_back(profile); | 782 break; |
798 suggestions.push_back(Suggestion(values[i])); | 783 } |
799 suggestions.back().backend_id.guid = profile->guid(); | 784 } |
800 suggestions.back().backend_id.variant = i; | 785 if (is_unique) { |
| 786 suggestions.push_back(Suggestion(values[i])); |
| 787 suggestions.back().backend_id.guid = profile->guid(); |
| 788 suggestions.back().backend_id.variant = i; |
| 789 } |
801 } | 790 } |
802 } | 791 } |
803 } | 792 } |
804 | 793 |
805 // Generate disambiguating labels based on the list of matches. | 794 return suggestions; |
806 std::vector<base::string16> labels; | |
807 AutofillProfile::CreateInferredLabels( | |
808 matched_profiles, &other_field_types, | |
809 type.GetStorableType(), 1, app_locale_, &labels); | |
810 DCHECK_EQ(suggestions.size(), labels.size()); | |
811 for (size_t i = 0; i < labels.size(); i++) | |
812 suggestions[i].label = labels[i]; | |
813 } | 795 } |
814 | 796 |
815 return suggestions; | 797 std::vector<Suggestion> suggestions; |
| 798 // Match based on a prefix search. |
| 799 std::vector<AutofillProfile*> matched_profiles; |
| 800 for (AutofillProfile* profile : profiles) { |
| 801 std::vector<base::string16> values = |
| 802 GetMultiInfoInOneLine(profile, type, app_locale_); |
| 803 for (size_t i = 0; i < values.size(); i++) { |
| 804 if (values[i].empty()) |
| 805 continue; |
| 806 |
| 807 base::string16 value_canon = |
| 808 AutofillProfile::CanonicalizeProfileString(values[i]); |
| 809 if (StartsWith(value_canon, field_contents_canon, true)) { |
| 810 // Prefix match, add suggestion. |
| 811 matched_profiles.push_back(profile); |
| 812 suggestions.push_back(Suggestion(values[i])); |
| 813 suggestions.back().backend_id.guid = profile->guid(); |
| 814 suggestions.back().backend_id.variant = i; |
| 815 } |
| 816 } |
| 817 } |
| 818 |
| 819 // Don't show two suggestions if one is a subset of the other. |
| 820 std::vector<AutofillProfile*> unique_matched_profiles; |
| 821 std::vector<Suggestion> unique_suggestions; |
| 822 ServerFieldTypeSet types(other_field_types.begin(), other_field_types.end()); |
| 823 for (size_t i = 0; i < matched_profiles.size(); ++i) { |
| 824 bool include = true; |
| 825 AutofillProfile* profile_a = matched_profiles[i]; |
| 826 for (size_t j = 0; j < matched_profiles.size(); ++j) { |
| 827 AutofillProfile* profile_b = matched_profiles[j]; |
| 828 // Check if profile A is a subset of profile B. If not, continue. |
| 829 if (i == j || suggestions[i].value != suggestions[j].value || |
| 830 !profile_a->IsSubsetOfForFieldSet(*profile_b, app_locale_, types)) { |
| 831 continue; |
| 832 } |
| 833 |
| 834 // Check if profile B is also a subset of profile A. If so, the |
| 835 // profiles are identical. Include the first one but not the second. |
| 836 if (i < j && |
| 837 profile_b->IsSubsetOfForFieldSet(*profile_a, app_locale_, types)) { |
| 838 continue; |
| 839 } |
| 840 |
| 841 // One-way subset. Don't include profile A. |
| 842 include = false; |
| 843 break; |
| 844 } |
| 845 if (include) { |
| 846 unique_matched_profiles.push_back(matched_profiles[i]); |
| 847 unique_suggestions.push_back(suggestions[i]); |
| 848 } |
| 849 } |
| 850 |
| 851 // Generate disambiguating labels based on the list of matches. |
| 852 std::vector<base::string16> labels; |
| 853 AutofillProfile::CreateInferredLabels( |
| 854 unique_matched_profiles, &other_field_types, type.GetStorableType(), 1, |
| 855 app_locale_, &labels); |
| 856 DCHECK_EQ(unique_suggestions.size(), labels.size()); |
| 857 for (size_t i = 0; i < labels.size(); i++) |
| 858 unique_suggestions[i].label = labels[i]; |
| 859 |
| 860 return unique_suggestions; |
816 } | 861 } |
817 | 862 |
818 std::vector<Suggestion> PersonalDataManager::GetCreditCardSuggestions( | 863 std::vector<Suggestion> PersonalDataManager::GetCreditCardSuggestions( |
819 const AutofillType& type, | 864 const AutofillType& type, |
820 const base::string16& field_contents) { | 865 const base::string16& field_contents) { |
821 std::list<const CreditCard*> cards_to_suggest; | 866 std::list<const CreditCard*> cards_to_suggest; |
822 for (const CreditCard* credit_card : GetCreditCards()) { | 867 for (const CreditCard* credit_card : GetCreditCards()) { |
823 // The value of the stored data for this field type in the |credit_card|. | 868 // The value of the stored data for this field type in the |credit_card|. |
824 base::string16 creditcard_field_value = | 869 base::string16 creditcard_field_value = |
825 credit_card->GetInfo(type, app_locale_); | 870 credit_card->GetInfo(type, app_locale_); |
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1283 } | 1328 } |
1284 if (IsExperimentalWalletIntegrationEnabled() && | 1329 if (IsExperimentalWalletIntegrationEnabled() && |
1285 pref_service_->GetBoolean(prefs::kAutofillWalletImportEnabled)) { | 1330 pref_service_->GetBoolean(prefs::kAutofillWalletImportEnabled)) { |
1286 profiles_.insert( | 1331 profiles_.insert( |
1287 profiles_.end(), server_profiles_.begin(), server_profiles_.end()); | 1332 profiles_.end(), server_profiles_.begin(), server_profiles_.end()); |
1288 } | 1333 } |
1289 return profiles_; | 1334 return profiles_; |
1290 } | 1335 } |
1291 | 1336 |
1292 } // namespace autofill | 1337 } // namespace autofill |
OLD | NEW |