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 13 matching lines...) Expand all Loading... |
24 #include "components/autofill/core/browser/autofill_experiments.h" | 24 #include "components/autofill/core/browser/autofill_experiments.h" |
25 #include "components/autofill/core/browser/autofill_field.h" | 25 #include "components/autofill/core/browser/autofill_field.h" |
26 #include "components/autofill/core/browser/autofill_metrics.h" | 26 #include "components/autofill/core/browser/autofill_metrics.h" |
27 #include "components/autofill/core/browser/form_structure.h" | 27 #include "components/autofill/core/browser/form_structure.h" |
28 #include "components/autofill/core/browser/personal_data_manager_observer.h" | 28 #include "components/autofill/core/browser/personal_data_manager_observer.h" |
29 #include "components/autofill/core/browser/phone_number.h" | 29 #include "components/autofill/core/browser/phone_number.h" |
30 #include "components/autofill/core/browser/phone_number_i18n.h" | 30 #include "components/autofill/core/browser/phone_number_i18n.h" |
31 #include "components/autofill/core/browser/validation.h" | 31 #include "components/autofill/core/browser/validation.h" |
32 #include "components/autofill/core/common/autofill_pref_names.h" | 32 #include "components/autofill/core/common/autofill_pref_names.h" |
33 #include "components/autofill/core/common/autofill_switches.h" | 33 #include "components/autofill/core/common/autofill_switches.h" |
| 34 #include "components/autofill/core/common/autofill_util.h" |
34 #include "components/signin/core/browser/account_tracker_service.h" | 35 #include "components/signin/core/browser/account_tracker_service.h" |
35 #include "components/signin/core/common/signin_pref_names.h" | 36 #include "components/signin/core/common/signin_pref_names.h" |
36 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_da
ta.h" | 37 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_da
ta.h" |
37 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_fo
rmatter.h" | 38 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_fo
rmatter.h" |
38 | 39 |
39 namespace autofill { | 40 namespace autofill { |
40 namespace { | 41 namespace { |
41 | 42 |
42 using ::i18n::addressinput::AddressField; | 43 using ::i18n::addressinput::AddressField; |
43 using ::i18n::addressinput::GetStreetAddressLinesAsSingleLine; | 44 using ::i18n::addressinput::GetStreetAddressLinesAsSingleLine; |
(...skipping 745 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
789 | 790 |
790 std::vector<Suggestion> suggestions; | 791 std::vector<Suggestion> suggestions; |
791 // Match based on a prefix search. | 792 // Match based on a prefix search. |
792 std::vector<AutofillProfile*> matched_profiles; | 793 std::vector<AutofillProfile*> matched_profiles; |
793 for (AutofillProfile* profile : profiles) { | 794 for (AutofillProfile* profile : profiles) { |
794 base::string16 value = GetInfoInOneLine(profile, type, app_locale_); | 795 base::string16 value = GetInfoInOneLine(profile, type, app_locale_); |
795 if (value.empty()) | 796 if (value.empty()) |
796 continue; | 797 continue; |
797 base::string16 value_canon = | 798 base::string16 value_canon = |
798 AutofillProfile::CanonicalizeProfileString(value); | 799 AutofillProfile::CanonicalizeProfileString(value); |
799 if (base::StartsWith(value_canon, field_contents_canon, | 800 bool prefix_matched_suggestion = base::StartsWith( |
800 base::CompareCase::SENSITIVE)) { | 801 value_canon, field_contents_canon, base::CompareCase::SENSITIVE); |
801 // Prefix match, add suggestion. | 802 if (prefix_matched_suggestion || |
| 803 FieldIsSuggestionSubstringStartingOnTokenBoundary(value, field_contents, |
| 804 false)) { |
802 matched_profiles.push_back(profile); | 805 matched_profiles.push_back(profile); |
803 suggestions.push_back(Suggestion(value)); | 806 suggestions.push_back(Suggestion(value)); |
804 suggestions.back().backend_id = profile->guid(); | 807 suggestions.back().backend_id = profile->guid(); |
| 808 suggestions.back().match = prefix_matched_suggestion |
| 809 ? Suggestion::PREFIX_MATCH |
| 810 : Suggestion::SUBSTRING_MATCH; |
805 } | 811 } |
806 } | 812 } |
807 | 813 |
| 814 // Prefix matches should precede other token matches. |
| 815 if (IsFeatureSubstringMatchEnabled()) { |
| 816 std::stable_sort(suggestions.begin(), suggestions.end(), |
| 817 [](const Suggestion& a, const Suggestion& b) { |
| 818 return a.match < b.match; |
| 819 }); |
| 820 } |
| 821 |
808 // Don't show two suggestions if one is a subset of the other. | 822 // Don't show two suggestions if one is a subset of the other. |
809 std::vector<AutofillProfile*> unique_matched_profiles; | 823 std::vector<AutofillProfile*> unique_matched_profiles; |
810 std::vector<Suggestion> unique_suggestions; | 824 std::vector<Suggestion> unique_suggestions; |
811 ServerFieldTypeSet types(other_field_types.begin(), other_field_types.end()); | 825 ServerFieldTypeSet types(other_field_types.begin(), other_field_types.end()); |
812 for (size_t i = 0; i < matched_profiles.size(); ++i) { | 826 for (size_t i = 0; i < matched_profiles.size(); ++i) { |
813 bool include = true; | 827 bool include = true; |
814 AutofillProfile* profile_a = matched_profiles[i]; | 828 AutofillProfile* profile_a = matched_profiles[i]; |
815 for (size_t j = 0; j < matched_profiles.size(); ++j) { | 829 for (size_t j = 0; j < matched_profiles.size(); ++j) { |
816 AutofillProfile* profile_b = matched_profiles[j]; | 830 AutofillProfile* profile_b = matched_profiles[j]; |
817 // Check if profile A is a subset of profile B. If not, continue. | 831 // Check if profile A is a subset of profile B. If not, continue. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
849 return unique_suggestions; | 863 return unique_suggestions; |
850 } | 864 } |
851 | 865 |
852 std::vector<Suggestion> PersonalDataManager::GetCreditCardSuggestions( | 866 std::vector<Suggestion> PersonalDataManager::GetCreditCardSuggestions( |
853 const AutofillType& type, | 867 const AutofillType& type, |
854 const base::string16& field_contents) { | 868 const base::string16& field_contents) { |
855 if (IsInAutofillSuggestionsDisabledExperiment()) | 869 if (IsInAutofillSuggestionsDisabledExperiment()) |
856 return std::vector<Suggestion>(); | 870 return std::vector<Suggestion>(); |
857 | 871 |
858 std::list<const CreditCard*> cards_to_suggest; | 872 std::list<const CreditCard*> cards_to_suggest; |
| 873 std::list<const CreditCard*> substring_matched_cards; |
859 base::string16 field_contents_lower = base::i18n::ToLower(field_contents); | 874 base::string16 field_contents_lower = base::i18n::ToLower(field_contents); |
860 for (const CreditCard* credit_card : GetCreditCards()) { | 875 for (const CreditCard* credit_card : GetCreditCards()) { |
861 // The value of the stored data for this field type in the |credit_card|. | 876 // The value of the stored data for this field type in the |credit_card|. |
862 base::string16 creditcard_field_value = | 877 base::string16 creditcard_field_value = |
863 credit_card->GetInfo(type, app_locale_); | 878 credit_card->GetInfo(type, app_locale_); |
864 if (creditcard_field_value.empty()) | 879 if (creditcard_field_value.empty()) |
865 continue; | 880 continue; |
866 base::string16 creditcard_field_lower = | 881 base::string16 creditcard_field_lower = |
867 base::i18n::ToLower(creditcard_field_value); | 882 base::i18n::ToLower(creditcard_field_value); |
868 | 883 |
869 // For card number fields, suggest the card if: | 884 // For card number fields, suggest the card if: |
870 // - the number matches any part of the card, or | 885 // - the number matches any part of the card, or |
871 // - it's a masked card and there are 6 or fewers typed so far. | 886 // - it's a masked card and there are 6 or fewers typed so far. |
872 // For other fields, require that the field contents match the beginning of | 887 // For other fields, require that the field contents match the beginning of |
873 // the stored data. | 888 // the stored data. |
874 if (type.GetStorableType() == CREDIT_CARD_NUMBER) { | 889 if (type.GetStorableType() == CREDIT_CARD_NUMBER) { |
875 if (creditcard_field_lower.find(field_contents_lower) == | 890 if (creditcard_field_lower.find(field_contents_lower) == |
876 base::string16::npos && | 891 base::string16::npos && |
877 (credit_card->record_type() != CreditCard::MASKED_SERVER_CARD || | 892 (credit_card->record_type() != CreditCard::MASKED_SERVER_CARD || |
878 field_contents.size() >= 6)) { | 893 field_contents.size() >= 6)) { |
879 continue; | 894 continue; |
880 } | 895 } |
881 } else if (!base::StartsWith(creditcard_field_lower, field_contents_lower, | 896 cards_to_suggest.push_back(credit_card); |
882 base::CompareCase::SENSITIVE)) { | 897 } else if (base::StartsWith(creditcard_field_lower, field_contents_lower, |
883 continue; | 898 base::CompareCase::SENSITIVE)) { |
| 899 cards_to_suggest.push_back(credit_card); |
| 900 } else if (FieldIsSuggestionSubstringStartingOnTokenBoundary( |
| 901 creditcard_field_lower, field_contents_lower, true)) { |
| 902 substring_matched_cards.push_back(credit_card); |
884 } | 903 } |
| 904 } |
885 | 905 |
886 cards_to_suggest.push_back(credit_card); | 906 cards_to_suggest.sort(RankByMfu); |
| 907 |
| 908 // Prefix matches should precede other token matches. |
| 909 if (IsFeatureSubstringMatchEnabled()) { |
| 910 substring_matched_cards.sort(RankByMfu); |
| 911 cards_to_suggest.insert(cards_to_suggest.end(), |
| 912 substring_matched_cards.begin(), |
| 913 substring_matched_cards.end()); |
887 } | 914 } |
888 | 915 |
889 // De-dupe card suggestions. Full server cards shadow local cards, and | 916 // De-dupe card suggestions. Full server cards shadow local cards, and |
890 // local cards shadow masked server cards. | 917 // local cards shadow masked server cards. |
891 for (auto outer_it = cards_to_suggest.begin(); | 918 for (auto outer_it = cards_to_suggest.begin(); |
892 outer_it != cards_to_suggest.end(); | 919 outer_it != cards_to_suggest.end(); |
893 ++outer_it) { | 920 ++outer_it) { |
894 | 921 |
895 if ((*outer_it)->record_type() == CreditCard::FULL_SERVER_CARD) { | 922 if ((*outer_it)->record_type() == CreditCard::FULL_SERVER_CARD) { |
896 for (auto inner_it = cards_to_suggest.begin(); | 923 for (auto inner_it = cards_to_suggest.begin(); |
897 inner_it != cards_to_suggest.end();) { | 924 inner_it != cards_to_suggest.end();) { |
898 auto inner_it_copy = inner_it++; | 925 auto inner_it_copy = inner_it++; |
899 if ((*inner_it_copy)->IsLocalDuplicateOfServerCard(**outer_it)) | 926 if ((*inner_it_copy)->IsLocalDuplicateOfServerCard(**outer_it)) |
900 cards_to_suggest.erase(inner_it_copy); | 927 cards_to_suggest.erase(inner_it_copy); |
901 } | 928 } |
902 } else if ((*outer_it)->record_type() == CreditCard::LOCAL_CARD) { | 929 } else if ((*outer_it)->record_type() == CreditCard::LOCAL_CARD) { |
903 for (auto inner_it = cards_to_suggest.begin(); | 930 for (auto inner_it = cards_to_suggest.begin(); |
904 inner_it != cards_to_suggest.end();) { | 931 inner_it != cards_to_suggest.end();) { |
905 auto inner_it_copy = inner_it++; | 932 auto inner_it_copy = inner_it++; |
906 if ((*inner_it_copy)->record_type() == CreditCard::MASKED_SERVER_CARD && | 933 if ((*inner_it_copy)->record_type() == CreditCard::MASKED_SERVER_CARD && |
907 (*outer_it)->IsLocalDuplicateOfServerCard(**inner_it_copy)) { | 934 (*outer_it)->IsLocalDuplicateOfServerCard(**inner_it_copy)) { |
908 cards_to_suggest.erase(inner_it_copy); | 935 cards_to_suggest.erase(inner_it_copy); |
909 } | 936 } |
910 } | 937 } |
911 } | 938 } |
912 } | 939 } |
913 | 940 |
914 cards_to_suggest.sort(RankByMfu); | |
915 | |
916 std::vector<Suggestion> suggestions; | 941 std::vector<Suggestion> suggestions; |
917 for (const CreditCard* credit_card : cards_to_suggest) { | 942 for (const CreditCard* credit_card : cards_to_suggest) { |
918 // Make a new suggestion. | 943 // Make a new suggestion. |
919 suggestions.push_back(Suggestion()); | 944 suggestions.push_back(Suggestion()); |
920 Suggestion* suggestion = &suggestions.back(); | 945 Suggestion* suggestion = &suggestions.back(); |
921 | 946 |
922 suggestion->value = credit_card->GetInfo(type, app_locale_); | 947 suggestion->value = credit_card->GetInfo(type, app_locale_); |
923 suggestion->icon = base::UTF8ToUTF16(credit_card->type()); | 948 suggestion->icon = base::UTF8ToUTF16(credit_card->type()); |
924 suggestion->backend_id = credit_card->guid(); | 949 suggestion->backend_id = credit_card->guid(); |
925 | 950 |
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1339 } | 1364 } |
1340 if (IsExperimentalWalletIntegrationEnabled() && | 1365 if (IsExperimentalWalletIntegrationEnabled() && |
1341 pref_service_->GetBoolean(prefs::kAutofillWalletImportEnabled)) { | 1366 pref_service_->GetBoolean(prefs::kAutofillWalletImportEnabled)) { |
1342 profiles_.insert( | 1367 profiles_.insert( |
1343 profiles_.end(), server_profiles_.begin(), server_profiles_.end()); | 1368 profiles_.end(), server_profiles_.begin(), server_profiles_.end()); |
1344 } | 1369 } |
1345 return profiles_; | 1370 return profiles_; |
1346 } | 1371 } |
1347 | 1372 |
1348 } // namespace autofill | 1373 } // namespace autofill |
OLD | NEW |