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

Side by Side Diff: components/autofill/core/browser/personal_data_manager.cc

Issue 962673004: [Autofill/Autocomplete Feature] Substring matching instead of prefix matching. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Changes in BUILD.gn Created 5 years, 6 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 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 12 matching lines...) Expand all
23 #include "components/autofill/core/browser/autofill_experiments.h" 23 #include "components/autofill/core/browser/autofill_experiments.h"
24 #include "components/autofill/core/browser/autofill_field.h" 24 #include "components/autofill/core/browser/autofill_field.h"
25 #include "components/autofill/core/browser/autofill_metrics.h" 25 #include "components/autofill/core/browser/autofill_metrics.h"
26 #include "components/autofill/core/browser/form_structure.h" 26 #include "components/autofill/core/browser/form_structure.h"
27 #include "components/autofill/core/browser/personal_data_manager_observer.h" 27 #include "components/autofill/core/browser/personal_data_manager_observer.h"
28 #include "components/autofill/core/browser/phone_number.h" 28 #include "components/autofill/core/browser/phone_number.h"
29 #include "components/autofill/core/browser/phone_number_i18n.h" 29 #include "components/autofill/core/browser/phone_number_i18n.h"
30 #include "components/autofill/core/browser/validation.h" 30 #include "components/autofill/core/browser/validation.h"
31 #include "components/autofill/core/common/autofill_pref_names.h" 31 #include "components/autofill/core/common/autofill_pref_names.h"
32 #include "components/autofill/core/common/autofill_switches.h" 32 #include "components/autofill/core/common/autofill_switches.h"
33 #include "components/autofill/core/common/autofill_util.h"
33 #include "components/signin/core/browser/account_tracker_service.h" 34 #include "components/signin/core/browser/account_tracker_service.h"
34 #include "components/signin/core/common/signin_pref_names.h" 35 #include "components/signin/core/common/signin_pref_names.h"
35 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_da ta.h" 36 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_da ta.h"
36 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_fo rmatter.h" 37 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_fo rmatter.h"
37 38
38 namespace autofill { 39 namespace autofill {
39 namespace { 40 namespace {
40 41
41 using ::i18n::addressinput::AddressField; 42 using ::i18n::addressinput::AddressField;
42 using ::i18n::addressinput::GetStreetAddressLinesAsSingleLine; 43 using ::i18n::addressinput::GetStreetAddressLinesAsSingleLine;
(...skipping 710 matching lines...) Expand 10 before | Expand all | Expand 10 after
753 754
754 const std::vector<CreditCard*>& PersonalDataManager::GetCreditCards() const { 755 const std::vector<CreditCard*>& PersonalDataManager::GetCreditCards() const {
755 credit_cards_.clear(); 756 credit_cards_.clear();
756 credit_cards_.insert(credit_cards_.end(), local_credit_cards_.begin(), 757 credit_cards_.insert(credit_cards_.end(), local_credit_cards_.begin(),
757 local_credit_cards_.end()); 758 local_credit_cards_.end());
758 if (IsExperimentalWalletIntegrationEnabled() && 759 if (IsExperimentalWalletIntegrationEnabled() &&
759 pref_service_->GetBoolean(prefs::kAutofillWalletImportEnabled)) { 760 pref_service_->GetBoolean(prefs::kAutofillWalletImportEnabled)) {
760 credit_cards_.insert(credit_cards_.end(), server_credit_cards_.begin(), 761 credit_cards_.insert(credit_cards_.end(), server_credit_cards_.begin(),
761 server_credit_cards_.end()); 762 server_credit_cards_.end());
762 } 763 }
764
763 return credit_cards_; 765 return credit_cards_;
764 } 766 }
765 767
766 bool PersonalDataManager::HasServerData() const { 768 bool PersonalDataManager::HasServerData() const {
767 return !server_credit_cards_.empty() || !server_profiles_.empty(); 769 return !server_credit_cards_.empty() || !server_profiles_.empty();
768 } 770 }
769 771
770 void PersonalDataManager::Refresh() { 772 void PersonalDataManager::Refresh() {
771 LoadProfiles(); 773 LoadProfiles();
772 LoadCreditCards(); 774 LoadCreditCards();
(...skipping 12 matching lines...) Expand all
785 787
786 std::vector<Suggestion> suggestions; 788 std::vector<Suggestion> suggestions;
787 // Match based on a prefix search. 789 // Match based on a prefix search.
788 std::vector<AutofillProfile*> matched_profiles; 790 std::vector<AutofillProfile*> matched_profiles;
789 for (AutofillProfile* profile : profiles) { 791 for (AutofillProfile* profile : profiles) {
790 base::string16 value = GetInfoInOneLine(profile, type, app_locale_); 792 base::string16 value = GetInfoInOneLine(profile, type, app_locale_);
791 if (value.empty()) 793 if (value.empty())
792 continue; 794 continue;
793 base::string16 value_canon = 795 base::string16 value_canon =
794 AutofillProfile::CanonicalizeProfileString(value); 796 AutofillProfile::CanonicalizeProfileString(value);
795 if (StartsWith(value_canon, field_contents_canon, true)) { 797 // CanonicalizeProfileString() returns lower-case string with all
796 // Prefix match, add suggestion. 798 // separator substituted by whitespaces and trims off trailing whitespace
799 // if any. Passing |value_canon| and |field_contents_canon| to
800 // ContainsTokenThatStartsWith() may lead to unexpected result, hence
801 // preferred passing |values[i]| and |field_contents| instead.
802 bool substring_matched_suggestion = false;
803 if (StartsWith(value_canon, field_contents_canon, true) ||
804 (substring_matched_suggestion =
805 ContainsTokenThatStartsWith(value, field_contents, false))) {
797 matched_profiles.push_back(profile); 806 matched_profiles.push_back(profile);
798 suggestions.push_back(Suggestion(value)); 807 suggestions.push_back(Suggestion(value));
799 suggestions.back().backend_id = profile->guid(); 808 suggestions.back().backend_id = profile->guid();
809 suggestions.back().match = substring_matched_suggestion
810 ? Suggestion::SUBSTRING_MATCH
811 : Suggestion::PREFIX_MATCH;
800 } 812 }
801 } 813 }
802 814
815 // Prefix matches should precede other token matches.
816 if (IsFeatureSubstringMatchEnabled())
817 OrderPrefixBeforeSubstring(&suggestions);
818
803 // Don't show two suggestions if one is a subset of the other. 819 // Don't show two suggestions if one is a subset of the other.
804 std::vector<AutofillProfile*> unique_matched_profiles; 820 std::vector<AutofillProfile*> unique_matched_profiles;
805 std::vector<Suggestion> unique_suggestions; 821 std::vector<Suggestion> unique_suggestions;
806 ServerFieldTypeSet types(other_field_types.begin(), other_field_types.end()); 822 ServerFieldTypeSet types(other_field_types.begin(), other_field_types.end());
807 for (size_t i = 0; i < matched_profiles.size(); ++i) { 823 for (size_t i = 0; i < matched_profiles.size(); ++i) {
808 bool include = true; 824 bool include = true;
809 AutofillProfile* profile_a = matched_profiles[i]; 825 AutofillProfile* profile_a = matched_profiles[i];
810 for (size_t j = 0; j < matched_profiles.size(); ++j) { 826 for (size_t j = 0; j < matched_profiles.size(); ++j) {
811 AutofillProfile* profile_b = matched_profiles[j]; 827 AutofillProfile* profile_b = matched_profiles[j];
812 // Check if profile A is a subset of profile B. If not, continue. 828 // Check if profile A is a subset of profile B. If not, continue.
(...skipping 28 matching lines...) Expand all
841 for (size_t i = 0; i < labels.size(); i++) 857 for (size_t i = 0; i < labels.size(); i++)
842 unique_suggestions[i].label = labels[i]; 858 unique_suggestions[i].label = labels[i];
843 859
844 return unique_suggestions; 860 return unique_suggestions;
845 } 861 }
846 862
847 std::vector<Suggestion> PersonalDataManager::GetCreditCardSuggestions( 863 std::vector<Suggestion> PersonalDataManager::GetCreditCardSuggestions(
848 const AutofillType& type, 864 const AutofillType& type,
849 const base::string16& field_contents) { 865 const base::string16& field_contents) {
850 std::list<const CreditCard*> cards_to_suggest; 866 std::list<const CreditCard*> cards_to_suggest;
867 std::list<const CreditCard*> substring_matched_suggestions;
851 for (const CreditCard* credit_card : GetCreditCards()) { 868 for (const CreditCard* credit_card : GetCreditCards()) {
852 // The value of the stored data for this field type in the |credit_card|. 869 // The value of the stored data for this field type in the |credit_card|.
853 base::string16 creditcard_field_value = 870 base::string16 creditcard_field_value =
854 credit_card->GetInfo(type, app_locale_); 871 credit_card->GetInfo(type, app_locale_);
855 if (creditcard_field_value.empty()) 872 if (creditcard_field_value.empty())
856 continue; 873 continue;
857 874
858 // For card number fields, suggest the card if: 875 // For card number fields, suggest the card if:
859 // - the number matches any part of the card, or 876 // - the number matches any part of the card, or
860 // - it's a masked card and there are 6 or fewers typed so far. 877 // - it's a masked card and there are 6 or fewers typed so far.
861 // For other fields, require that the field contents match the beginning of 878 // For other fields, require that the field contents match the beginning of
862 // the stored data. 879 // the stored data.
863 if (type.GetStorableType() == CREDIT_CARD_NUMBER) { 880 if (type.GetStorableType() == CREDIT_CARD_NUMBER) {
864 if (creditcard_field_value.find(field_contents) == base::string16::npos && 881 if (creditcard_field_value.find(field_contents) == base::string16::npos &&
865 (credit_card->record_type() != CreditCard::MASKED_SERVER_CARD || 882 (credit_card->record_type() != CreditCard::MASKED_SERVER_CARD ||
866 field_contents.size() >= 6)) { 883 field_contents.size() >= 6)) {
867 continue; 884 continue;
868 } 885 }
869 } else if (!StartsWith(creditcard_field_value, field_contents, false)) { 886 cards_to_suggest.push_back(credit_card);
870 continue; 887 } else if (StartsWith(creditcard_field_value, field_contents, false)) {
888 cards_to_suggest.push_back(credit_card);
889 } else if (ContainsTokenThatStartsWith(creditcard_field_value,
890 field_contents, false)) {
891 substring_matched_suggestions.push_back(credit_card);
871 } 892 }
893 }
872 894
873 cards_to_suggest.push_back(credit_card); 895 cards_to_suggest.sort(RankByMfu);
896
897 // Prefix matches should precede other token matches.
898 if (IsFeatureSubstringMatchEnabled()) {
899 cards_to_suggest.insert(cards_to_suggest.end(),
Evan Stade 2015/06/08 23:23:38 so it seems the substring matches are not ranked i
Pritam Nikam 2015/06/09 11:39:06 Done.
900 substring_matched_suggestions.begin(),
901 substring_matched_suggestions.end());
874 } 902 }
875 903
876 // De-dupe card suggestions. Full server cards shadow local cards, and 904 // De-dupe card suggestions. Full server cards shadow local cards, and
877 // local cards shadow masked server cards. 905 // local cards shadow masked server cards.
878 for (auto outer_it = cards_to_suggest.begin(); 906 for (auto outer_it = cards_to_suggest.begin();
879 outer_it != cards_to_suggest.end(); 907 outer_it != cards_to_suggest.end();
880 ++outer_it) { 908 ++outer_it) {
881 909
882 if ((*outer_it)->record_type() == CreditCard::FULL_SERVER_CARD) { 910 if ((*outer_it)->record_type() == CreditCard::FULL_SERVER_CARD) {
883 for (auto inner_it = cards_to_suggest.begin(); 911 for (auto inner_it = cards_to_suggest.begin();
884 inner_it != cards_to_suggest.end();) { 912 inner_it != cards_to_suggest.end();) {
885 auto inner_it_copy = inner_it++; 913 auto inner_it_copy = inner_it++;
886 if ((*inner_it_copy)->IsLocalDuplicateOfServerCard(**outer_it)) 914 if ((*inner_it_copy)->IsLocalDuplicateOfServerCard(**outer_it))
887 cards_to_suggest.erase(inner_it_copy); 915 cards_to_suggest.erase(inner_it_copy);
888 } 916 }
889 } else if ((*outer_it)->record_type() == CreditCard::LOCAL_CARD) { 917 } else if ((*outer_it)->record_type() == CreditCard::LOCAL_CARD) {
890 for (auto inner_it = cards_to_suggest.begin(); 918 for (auto inner_it = cards_to_suggest.begin();
891 inner_it != cards_to_suggest.end();) { 919 inner_it != cards_to_suggest.end();) {
892 auto inner_it_copy = inner_it++; 920 auto inner_it_copy = inner_it++;
893 if ((*inner_it_copy)->record_type() == CreditCard::MASKED_SERVER_CARD && 921 if ((*inner_it_copy)->record_type() == CreditCard::MASKED_SERVER_CARD &&
894 (*outer_it)->IsLocalDuplicateOfServerCard(**inner_it_copy)) { 922 (*outer_it)->IsLocalDuplicateOfServerCard(**inner_it_copy)) {
895 cards_to_suggest.erase(inner_it_copy); 923 cards_to_suggest.erase(inner_it_copy);
896 } 924 }
897 } 925 }
898 } 926 }
899 } 927 }
900 928
901 cards_to_suggest.sort(RankByMfu);
902
903 std::vector<Suggestion> suggestions; 929 std::vector<Suggestion> suggestions;
904 for (const CreditCard* credit_card : cards_to_suggest) { 930 for (const CreditCard* credit_card : cards_to_suggest) {
905 // Make a new suggestion. 931 // Make a new suggestion.
906 suggestions.push_back(Suggestion()); 932 suggestions.push_back(Suggestion());
907 Suggestion* suggestion = &suggestions.back(); 933 Suggestion* suggestion = &suggestions.back();
908 934
909 suggestion->value = credit_card->GetInfo(type, app_locale_); 935 suggestion->value = credit_card->GetInfo(type, app_locale_);
910 suggestion->icon = base::UTF8ToUTF16(credit_card->type()); 936 suggestion->icon = base::UTF8ToUTF16(credit_card->type());
911 suggestion->backend_id = credit_card->guid(); 937 suggestion->backend_id = credit_card->guid();
912 938
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after
1331 } 1357 }
1332 if (IsExperimentalWalletIntegrationEnabled() && 1358 if (IsExperimentalWalletIntegrationEnabled() &&
1333 pref_service_->GetBoolean(prefs::kAutofillWalletImportEnabled)) { 1359 pref_service_->GetBoolean(prefs::kAutofillWalletImportEnabled)) {
1334 profiles_.insert( 1360 profiles_.insert(
1335 profiles_.end(), server_profiles_.begin(), server_profiles_.end()); 1361 profiles_.end(), server_profiles_.begin(), server_profiles_.end());
1336 } 1362 }
1337 return profiles_; 1363 return profiles_;
1338 } 1364 }
1339 1365
1340 } // namespace autofill 1366 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698