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

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

Issue 2110563002: Use AutofillProfileComparator in place of ad-hoc merge logic. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@merge
Patch Set: Initial CL for review Created 4 years, 5 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 <stddef.h> 7 #include <stddef.h>
8 #include <algorithm> 8 #include <algorithm>
9 #include <list> 9 #include <list>
10 #include <map> 10 #include <map>
11 #include <string> 11 #include <string>
12 #include <utility> 12 #include <utility>
13 13
14 #include "base/i18n/case_conversion.h" 14 #include "base/i18n/case_conversion.h"
15 #include "base/i18n/timezone.h" 15 #include "base/i18n/timezone.h"
16 #include "base/profiler/scoped_tracker.h" 16 #include "base/profiler/scoped_tracker.h"
17 #include "base/strings/string_number_conversions.h" 17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/string_util.h" 18 #include "base/strings/string_util.h"
19 #include "base/strings/utf_string_conversions.h" 19 #include "base/strings/utf_string_conversions.h"
20 #include "build/build_config.h" 20 #include "build/build_config.h"
21 #include "components/autofill/core/browser/address_i18n.h" 21 #include "components/autofill/core/browser/address_i18n.h"
22 #include "components/autofill/core/browser/autofill-inl.h" 22 #include "components/autofill/core/browser/autofill-inl.h"
23 #include "components/autofill/core/browser/autofill_country.h" 23 #include "components/autofill/core/browser/autofill_country.h"
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/autofill_profile_comparator.h"
27 #include "components/autofill/core/browser/country_data.h" 28 #include "components/autofill/core/browser/country_data.h"
28 #include "components/autofill/core/browser/country_names.h" 29 #include "components/autofill/core/browser/country_names.h"
29 #include "components/autofill/core/browser/form_structure.h" 30 #include "components/autofill/core/browser/form_structure.h"
30 #include "components/autofill/core/browser/personal_data_manager_observer.h" 31 #include "components/autofill/core/browser/personal_data_manager_observer.h"
31 #include "components/autofill/core/browser/phone_number.h" 32 #include "components/autofill/core/browser/phone_number.h"
32 #include "components/autofill/core/browser/phone_number_i18n.h" 33 #include "components/autofill/core/browser/phone_number_i18n.h"
33 #include "components/autofill/core/browser/validation.h" 34 #include "components/autofill/core/browser/validation.h"
34 #include "components/autofill/core/common/autofill_pref_names.h" 35 #include "components/autofill/core/common/autofill_pref_names.h"
35 #include "components/autofill/core/common/autofill_switches.h" 36 #include "components/autofill/core/common/autofill_switches.h"
36 #include "components/autofill/core/common/autofill_util.h" 37 #include "components/autofill/core/common/autofill_util.h"
(...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after
717 } 718 }
718 719
719 std::vector<Suggestion> PersonalDataManager::GetProfileSuggestions( 720 std::vector<Suggestion> PersonalDataManager::GetProfileSuggestions(
720 const AutofillType& type, 721 const AutofillType& type,
721 const base::string16& field_contents, 722 const base::string16& field_contents,
722 bool field_is_autofilled, 723 bool field_is_autofilled,
723 const std::vector<ServerFieldType>& other_field_types) { 724 const std::vector<ServerFieldType>& other_field_types) {
724 if (IsInAutofillSuggestionsDisabledExperiment()) 725 if (IsInAutofillSuggestionsDisabledExperiment())
725 return std::vector<Suggestion>(); 726 return std::vector<Suggestion>();
726 727
728 AutofillProfileComparator comparator(app_locale_);
727 base::string16 field_contents_canon = 729 base::string16 field_contents_canon =
728 AutofillProfile::CanonicalizeProfileString(field_contents); 730 comparator.NormalizeForComparison(field_contents);
729 731
730 // Get the profiles to suggest, which are already sorted. 732 // Get the profiles to suggest, which are already sorted.
731 std::vector<AutofillProfile*> profiles = GetProfilesToSuggest(); 733 std::vector<AutofillProfile*> profiles = GetProfilesToSuggest();
732 734
733 std::vector<Suggestion> suggestions; 735 std::vector<Suggestion> suggestions;
734 // Match based on a prefix search. 736 // Match based on a prefix search.
735 std::vector<AutofillProfile*> matched_profiles; 737 std::vector<AutofillProfile*> matched_profiles;
736 for (AutofillProfile* profile : profiles) { 738 for (AutofillProfile* profile : profiles) {
737 base::string16 value = GetInfoInOneLine(profile, type, app_locale_); 739 base::string16 value = GetInfoInOneLine(profile, type, app_locale_);
738 if (value.empty()) 740 if (value.empty())
739 continue; 741 continue;
740 742
741 bool prefix_matched_suggestion; 743 bool prefix_matched_suggestion;
742 base::string16 suggestion_canon = 744 base::string16 suggestion_canon = comparator.NormalizeForComparison(value);
743 AutofillProfile::CanonicalizeProfileString(value);
744 if (IsValidSuggestionForFieldContents( 745 if (IsValidSuggestionForFieldContents(
745 suggestion_canon, field_contents_canon, type, 746 suggestion_canon, field_contents_canon, type,
746 /* is_masked_server_card= */ false, &prefix_matched_suggestion)) { 747 /* is_masked_server_card= */ false, &prefix_matched_suggestion)) {
747 matched_profiles.push_back(profile); 748 matched_profiles.push_back(profile);
748 suggestions.push_back(Suggestion(value)); 749 suggestions.push_back(Suggestion(value));
749 suggestions.back().backend_id = profile->guid(); 750 suggestions.back().backend_id = profile->guid();
750 suggestions.back().match = prefix_matched_suggestion 751 suggestions.back().match = prefix_matched_suggestion
751 ? Suggestion::PREFIX_MATCH 752 ? Suggestion::PREFIX_MATCH
752 : Suggestion::SUBSTRING_MATCH; 753 : Suggestion::SUBSTRING_MATCH;
753 } 754 }
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
921 return !a->IsVerified(); 922 return !a->IsVerified();
922 return a->CompareFrecency(b, comparison_time); 923 return a->CompareFrecency(b, comparison_time);
923 }); 924 });
924 925
925 // Set to true if |existing_profiles| already contains an equivalent profile. 926 // Set to true if |existing_profiles| already contains an equivalent profile.
926 bool matching_profile_found = false; 927 bool matching_profile_found = false;
927 std::string guid = new_profile.guid(); 928 std::string guid = new_profile.guid();
928 929
929 // If we have already saved this address, merge in any missing values. 930 // If we have already saved this address, merge in any missing values.
930 // Only merge with the first match. 931 // Only merge with the first match.
932 AutofillProfileComparator comparator(app_locale);
931 for (AutofillProfile* existing_profile : existing_profiles) { 933 for (AutofillProfile* existing_profile : existing_profiles) {
932 if (!matching_profile_found && 934 if (!matching_profile_found &&
933 !new_profile.PrimaryValue(app_locale_).empty() && 935 comparator.AreMergeable(new_profile, *existing_profile) &&
934 existing_profile->SaveAdditionalInfo(new_profile, app_locale)) { 936 existing_profile->SaveAdditionalInfo(new_profile, app_locale)) {
935 // Unverified profiles should always be updated with the newer data, 937 // Unverified profiles should always be updated with the newer data,
936 // whereas verified profiles should only ever be overwritten by verified 938 // whereas verified profiles should only ever be overwritten by verified
937 // data. If an automatically aggregated profile would overwrite a 939 // data. If an automatically aggregated profile would overwrite a
938 // verified profile, just drop it. 940 // verified profile, just drop it.
939 matching_profile_found = true; 941 matching_profile_found = true;
940 guid = existing_profile->guid(); 942 guid = existing_profile->guid();
941 943
942 // We set the modification date so that immediate requests for profiles 944 // We set the modification date so that immediate requests for profiles
943 // will properly reflect the fact that this profile has been modified 945 // will properly reflect the fact that this profile has been modified
(...skipping 685 matching lines...) Expand 10 before | Expand all | Expand 10 after
1629 // similar verified profile will be discarded. 1631 // similar verified profile will be discarded.
1630 base::Time comparison_time = base::Time::Now(); 1632 base::Time comparison_time = base::Time::Now();
1631 std::sort(existing_profiles->begin(), existing_profiles->end(), 1633 std::sort(existing_profiles->begin(), existing_profiles->end(),
1632 [comparison_time](const AutofillDataModel* a, 1634 [comparison_time](const AutofillDataModel* a,
1633 const AutofillDataModel* b) { 1635 const AutofillDataModel* b) {
1634 if (a->IsVerified() != b->IsVerified()) 1636 if (a->IsVerified() != b->IsVerified())
1635 return !a->IsVerified(); 1637 return !a->IsVerified();
1636 return a->CompareFrecency(b, comparison_time); 1638 return a->CompareFrecency(b, comparison_time);
1637 }); 1639 });
1638 1640
1641 AutofillProfileComparator comparator(app_locale_);
1642
1639 for (size_t i = 0; i < existing_profiles->size(); ++i) { 1643 for (size_t i = 0; i < existing_profiles->size(); ++i) {
1640 AutofillProfile* profile_to_merge = (*existing_profiles)[i]; 1644 AutofillProfile* profile_to_merge = (*existing_profiles)[i];
1641 1645
1642 // If the profile was set to be deleted, skip it. It has already been 1646 // If the profile was set to be deleted, skip it. It has already been
1643 // merged into another profile. 1647 // merged into another profile.
1644 if (profiles_to_delete->count(profile_to_merge)) 1648 if (profiles_to_delete->count(profile_to_merge))
1645 continue; 1649 continue;
1646 1650
1647 // If we have reached the verified profiles, stop trying to merge. Verified 1651 // If we have reached the verified profiles, stop trying to merge. Verified
1648 // profiles do not get merged. 1652 // profiles do not get merged.
1649 if (profile_to_merge->IsVerified()) 1653 if (profile_to_merge->IsVerified())
1650 break; 1654 break;
1651 1655
1652 // If we have not reached the last profile, try to merge |profile_to_merge| 1656 // If we have not reached the last profile, try to merge |profile_to_merge|
1653 // with all the less relevant |existing_profiles|. 1657 // with all the less relevant |existing_profiles|.
1654 for (size_t j = i + 1; j < existing_profiles->size(); ++j) { 1658 for (size_t j = i + 1; j < existing_profiles->size(); ++j) {
1655 // Don't try to merge a profile that was already set for deletion. Also 1659 // Don't try to merge a profile that was already set for deletion. Also
1656 // don't try to merge with profiles with a different PrimaryValue 1660 // don't try to merge with profiles with a different PrimaryValue
1657 // because they are not similar. 1661 // because they are not similar.
1658 AutofillProfile* existing_profile = (*existing_profiles)[j]; 1662 AutofillProfile* existing_profile = (*existing_profiles)[j];
1659 if (!profiles_to_delete->count(existing_profile) && 1663 if (!profiles_to_delete->count(existing_profile) &&
1660 existing_profile->PrimaryValue(app_locale_) == 1664 comparator.AreMergeable(*existing_profile, *profile_to_merge)) {
sebsg 2016/06/29 08:57:04 If you made the change to SaveAdditionnalInfo (dch
Roger McFarlane (Chromium) 2016/06/29 18:21:37 That's true, but I think that would make this code
sebsg 2016/06/29 19:04:50 Yes, AttemptMerge would be a better name for sure.
1661 profile_to_merge->PrimaryValue(app_locale_)) {
1662 // If the profiles are found to be similar, |profile_to_merge|'s non 1665 // If the profiles are found to be similar, |profile_to_merge|'s non
1663 // empty data will overwrite the |existing_profile|'s data. 1666 // empty data will overwrite the |existing_profile|'s data.
1664 // |existing_profile| will have added the complementary data from 1667 // |existing_profile| will have added the complementary data from
1665 // |profile_to_merge| and will keep the most relevant syntax for data 1668 // |profile_to_merge| and will keep the most relevant syntax for data
1666 // present in both profiles. 1669 // present in both profiles.
1667 if (existing_profile->SaveAdditionalInfo(*profile_to_merge, 1670 if (existing_profile->SaveAdditionalInfo(*profile_to_merge,
1668 app_locale_)) { 1671 app_locale_)) {
1669 // Since |profile_to_merge| was a duplicate of |existing_profile| 1672 // Since |profile_to_merge| was a duplicate of |existing_profile|
1670 // and was merged sucessfully, it can now be deleted. 1673 // and was merged sucessfully, it can now be deleted.
1671 profiles_to_delete->insert(profile_to_merge); 1674 profiles_to_delete->insert(profile_to_merge);
1672 1675
1673 // Now try to merge the new resulting profile with the rest of the 1676 // Now try to merge the new resulting profile with the rest of the
1674 // existing profiles. 1677 // existing profiles.
1675 profile_to_merge = existing_profile; 1678 profile_to_merge = existing_profile;
1676 1679
1677 // Verified profiles do not get merged. Save some time by not 1680 // Verified profiles do not get merged. Save some time by not
1678 // trying. 1681 // trying.
1679 if (profile_to_merge->IsVerified()) 1682 if (profile_to_merge->IsVerified())
1680 break; 1683 break;
1681 } 1684 }
1682 } 1685 }
1683 } 1686 }
1684 } 1687 }
1685 AutofillMetrics::LogNumberOfProfilesRemovedDuringDedupe( 1688 AutofillMetrics::LogNumberOfProfilesRemovedDuringDedupe(
1686 profiles_to_delete->size()); 1689 profiles_to_delete->size());
1687 } 1690 }
1688 1691
1689 } // namespace autofill 1692 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698