Chromium Code Reviews| 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 <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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |