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

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

Issue 970403002: Don't suggest autofill profiles that are subsets of other profiles. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 9 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 725 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698