Index: components/autofill/core/browser/personal_data_manager.cc |
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc |
index aa1658bc9ca4a56fa1e79e7a7af7d3b13bf84c94..201a4b77af5f977802ff62c32fd3a9ff8035f518 100644 |
--- a/components/autofill/core/browser/personal_data_manager.cc |
+++ b/components/autofill/core/browser/personal_data_manager.cc |
@@ -743,7 +743,6 @@ std::vector<Suggestion> PersonalDataManager::GetProfileSuggestions( |
const base::string16& field_contents, |
bool field_is_autofilled, |
const std::vector<ServerFieldType>& other_field_types) { |
- std::vector<Suggestion> suggestions; |
base::string16 field_contents_canon = |
AutofillProfile::CanonicalizeProfileString(field_contents); |
@@ -751,6 +750,7 @@ std::vector<Suggestion> PersonalDataManager::GetProfileSuggestions( |
std::sort(profiles.begin(), profiles.end(), RankByMfu); |
if (field_is_autofilled) { |
+ std::vector<Suggestion> suggestions; |
// This field was previously autofilled. In this case, suggesting results |
// based on prefix is useless since it will be the same thing. Instead, |
// check for a field that may have multiple possible values (for example, |
@@ -774,45 +774,90 @@ std::vector<Suggestion> PersonalDataManager::GetProfileSuggestions( |
for (size_t i = 0; i < values.size(); i++) { |
if (values[i].empty()) |
continue; |
- suggestions.push_back(Suggestion(values[i])); |
- suggestions.back().backend_id.guid = profile->guid(); |
- suggestions.back().backend_id.variant = i; |
+ |
+ bool is_unique = true; |
+ for (size_t j = 0; j < suggestions.size(); ++j) { |
+ if (values[i] == suggestions[j].value) { |
+ is_unique = false; |
+ break; |
+ } |
+ } |
+ if (is_unique) { |
+ suggestions.push_back(Suggestion(values[i])); |
+ suggestions.back().backend_id.guid = profile->guid(); |
+ suggestions.back().backend_id.variant = i; |
+ } |
} |
} |
} |
- } else { |
- // Match based on a prefix search. |
- std::vector<AutofillProfile*> matched_profiles; |
- for (AutofillProfile* profile : profiles) { |
- std::vector<base::string16> values = |
- GetMultiInfoInOneLine(profile, type, app_locale_); |
- for (size_t i = 0; i < values.size(); i++) { |
- if (values[i].empty()) |
- continue; |
- |
- base::string16 value_canon = |
- AutofillProfile::CanonicalizeProfileString(values[i]); |
- if (StartsWith(value_canon, field_contents_canon, true)) { |
- // Prefix match, add suggestion. |
- matched_profiles.push_back(profile); |
- suggestions.push_back(Suggestion(values[i])); |
- suggestions.back().backend_id.guid = profile->guid(); |
- suggestions.back().backend_id.variant = i; |
- } |
+ |
+ return suggestions; |
+ } |
+ |
+ std::vector<Suggestion> suggestions; |
+ // Match based on a prefix search. |
+ std::vector<AutofillProfile*> matched_profiles; |
+ for (AutofillProfile* profile : profiles) { |
+ std::vector<base::string16> values = |
+ GetMultiInfoInOneLine(profile, type, app_locale_); |
+ for (size_t i = 0; i < values.size(); i++) { |
+ if (values[i].empty()) |
+ continue; |
+ |
+ base::string16 value_canon = |
+ AutofillProfile::CanonicalizeProfileString(values[i]); |
+ if (StartsWith(value_canon, field_contents_canon, true)) { |
+ // Prefix match, add suggestion. |
+ matched_profiles.push_back(profile); |
+ suggestions.push_back(Suggestion(values[i])); |
+ suggestions.back().backend_id.guid = profile->guid(); |
+ suggestions.back().backend_id.variant = i; |
} |
} |
+ } |
+ |
+ // Don't show two suggestions if one is a subset of the other. |
+ std::vector<AutofillProfile*> unique_matched_profiles; |
+ std::vector<Suggestion> unique_suggestions; |
+ ServerFieldTypeSet types(other_field_types.begin(), other_field_types.end()); |
+ for (size_t i = 0; i < matched_profiles.size(); ++i) { |
+ bool include = true; |
+ AutofillProfile* profile_a = matched_profiles[i]; |
+ for (size_t j = 0; j < matched_profiles.size(); ++j) { |
+ AutofillProfile* profile_b = matched_profiles[j]; |
+ // Check if profile A is a subset of profile B. If not, continue. |
+ if (i == j || suggestions[i].value != suggestions[j].value || |
+ !profile_a->IsSubsetOfForFieldSet(*profile_b, app_locale_, types)) { |
+ continue; |
+ } |
+ |
+ // Check if profile B is also a subset of profile A. If so, the |
+ // profiles are identical. Include the first one but not the second. |
+ if (i < j && |
+ profile_b->IsSubsetOfForFieldSet(*profile_a, app_locale_, types)) { |
+ continue; |
+ } |
- // Generate disambiguating labels based on the list of matches. |
- std::vector<base::string16> labels; |
- AutofillProfile::CreateInferredLabels( |
- matched_profiles, &other_field_types, |
- type.GetStorableType(), 1, app_locale_, &labels); |
- DCHECK_EQ(suggestions.size(), labels.size()); |
- for (size_t i = 0; i < labels.size(); i++) |
- suggestions[i].label = labels[i]; |
+ // One-way subset. Don't include profile A. |
+ include = false; |
+ break; |
+ } |
+ if (include) { |
+ unique_matched_profiles.push_back(matched_profiles[i]); |
+ unique_suggestions.push_back(suggestions[i]); |
+ } |
} |
- return suggestions; |
+ // Generate disambiguating labels based on the list of matches. |
+ std::vector<base::string16> labels; |
+ AutofillProfile::CreateInferredLabels( |
+ unique_matched_profiles, &other_field_types, type.GetStorableType(), 1, |
+ app_locale_, &labels); |
+ DCHECK_EQ(unique_suggestions.size(), labels.size()); |
+ for (size_t i = 0; i < labels.size(); i++) |
+ unique_suggestions[i].label = labels[i]; |
+ |
+ return unique_suggestions; |
} |
std::vector<Suggestion> PersonalDataManager::GetCreditCardSuggestions( |