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

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

Issue 2533303007: [Autofill] Transfer cards' billing address id when deduping profiles. (Closed)
Patch Set: Addressed Roger's comment Created 4 years 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 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <list> 10 #include <list>
(...skipping 993 matching lines...) Expand 10 before | Expand all | Expand 10 after
1004 if (a->IsVerified() != b->IsVerified()) 1004 if (a->IsVerified() != b->IsVerified())
1005 return !a->IsVerified(); 1005 return !a->IsVerified();
1006 return a->CompareFrecency(b.get(), comparison_time); 1006 return a->CompareFrecency(b.get(), comparison_time);
1007 }); 1007 });
1008 1008
1009 // Set to true if |existing_profiles| already contains an equivalent profile. 1009 // Set to true if |existing_profiles| already contains an equivalent profile.
1010 bool matching_profile_found = false; 1010 bool matching_profile_found = false;
1011 std::string guid = new_profile.guid(); 1011 std::string guid = new_profile.guid();
1012 1012
1013 // If we have already saved this address, merge in any missing values. 1013 // If we have already saved this address, merge in any missing values.
1014 // Only merge with the first match. 1014 // Only merge with the first match. Merging the new profile into the existing
1015 // one preserves the validity of credit card's billing address reference.
1015 AutofillProfileComparator comparator(app_locale); 1016 AutofillProfileComparator comparator(app_locale);
1016 for (const auto& existing_profile : *existing_profiles) { 1017 for (const auto& existing_profile : *existing_profiles) {
1017 if (!matching_profile_found && 1018 if (!matching_profile_found &&
1018 comparator.AreMergeable(new_profile, *existing_profile) && 1019 comparator.AreMergeable(new_profile, *existing_profile) &&
1019 existing_profile->SaveAdditionalInfo(new_profile, app_locale)) { 1020 existing_profile->SaveAdditionalInfo(new_profile, app_locale)) {
1020 // Unverified profiles should always be updated with the newer data, 1021 // Unverified profiles should always be updated with the newer data,
1021 // whereas verified profiles should only ever be overwritten by verified 1022 // whereas verified profiles should only ever be overwritten by verified
1022 // data. If an automatically aggregated profile would overwrite a 1023 // data. If an automatically aggregated profile would overwrite a
1023 // verified profile, just drop it. 1024 // verified profile, just drop it.
1024 matching_profile_found = true; 1025 matching_profile_found = true;
(...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after
1696 current_major_version) { 1697 current_major_version) {
1697 DVLOG(1) 1698 DVLOG(1)
1698 << "Autofill profile de-duplication already performed for this version"; 1699 << "Autofill profile de-duplication already performed for this version";
1699 return false; 1700 return false;
1700 } 1701 }
1701 1702
1702 DVLOG(1) << "Starting autofill profile de-duplication."; 1703 DVLOG(1) << "Starting autofill profile de-duplication.";
1703 std::unordered_set<AutofillProfile*> profiles_to_delete; 1704 std::unordered_set<AutofillProfile*> profiles_to_delete;
1704 profiles_to_delete.reserve(web_profiles_.size()); 1705 profiles_to_delete.reserve(web_profiles_.size());
1705 1706
1706 DedupeProfiles(&web_profiles_, &profiles_to_delete); 1707 // Create the map used to update credit card's billing addresses after the
1708 // dedupe.
1709 std::unordered_map<std::string, std::string> guids_merge_map;
1707 1710
1708 // Apply the changes to the database. 1711 DedupeProfiles(&web_profiles_, &profiles_to_delete, &guids_merge_map);
1712
1713 // Apply the profile changes to the database.
1709 for (const auto& profile : web_profiles_) { 1714 for (const auto& profile : web_profiles_) {
1710 // If the profile was set to be deleted, remove it from the database. 1715 // If the profile was set to be deleted, remove it from the database.
1711 if (profiles_to_delete.count(profile.get())) { 1716 if (profiles_to_delete.count(profile.get())) {
1712 database_->RemoveAutofillProfile(profile->guid()); 1717 database_->RemoveAutofillProfile(profile->guid());
1713 } else { 1718 } else {
1714 // Otherwise, update the profile in the database. 1719 // Otherwise, update the profile in the database.
1715 database_->UpdateAutofillProfile(*profile); 1720 database_->UpdateAutofillProfile(*profile);
1716 } 1721 }
1717 } 1722 }
1718 1723
1724 UpdateCardsBillingAddressReference(guids_merge_map);
1725
1719 // Set the pref to the current major version. 1726 // Set the pref to the current major version.
1720 pref_service_->SetInteger(prefs::kAutofillLastVersionDeduped, 1727 pref_service_->SetInteger(prefs::kAutofillLastVersionDeduped,
1721 current_major_version); 1728 current_major_version);
1722 1729
1723 // Refresh the local cache and send notifications to observers. 1730 // Refresh the local cache and send notifications to observers.
1724 Refresh(); 1731 Refresh();
1725 1732
1726 return true; 1733 return true;
1727 } 1734 }
1728 1735
1729 void PersonalDataManager::DedupeProfiles( 1736 void PersonalDataManager::DedupeProfiles(
1730 std::vector<std::unique_ptr<AutofillProfile>>* existing_profiles, 1737 std::vector<std::unique_ptr<AutofillProfile>>* existing_profiles,
1731 std::unordered_set<AutofillProfile*>* profiles_to_delete) { 1738 std::unordered_set<AutofillProfile*>* profiles_to_delete,
1739 std::unordered_map<std::string, std::string>* guids_merge_map) {
1732 AutofillMetrics::LogNumberOfProfilesConsideredForDedupe( 1740 AutofillMetrics::LogNumberOfProfilesConsideredForDedupe(
1733 existing_profiles->size()); 1741 existing_profiles->size());
1734 1742
1735 // Sort the profiles by frecency with all the verified profiles at the end. 1743 // Sort the profiles by frecency with all the verified profiles at the end.
1736 // That way the most relevant profiles will get merged into the less relevant 1744 // That way the most relevant profiles will get merged into the less relevant
1737 // profiles, which keeps the syntax of the most relevant profiles data. 1745 // profiles, which keeps the syntax of the most relevant profiles data.
1738 // Verified profiles are put at the end because they do not merge into other 1746 // Verified profiles are put at the end because they do not merge into other
1739 // profiles, so the loop can be stopped when we reach those. However they need 1747 // profiles, so the loop can be stopped when we reach those. However they need
1740 // to be in the vector because an unverified profile trying to merge into a 1748 // to be in the vector because an unverified profile trying to merge into a
1741 // similar verified profile will be discarded. 1749 // similar verified profile will be discarded.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1775 // Move on if the profiles are not mergeable. 1783 // Move on if the profiles are not mergeable.
1776 if (!comparator.AreMergeable(*existing_profile, *profile_to_merge)) 1784 if (!comparator.AreMergeable(*existing_profile, *profile_to_merge))
1777 continue; 1785 continue;
1778 1786
1779 // The profiles are found to be mergeable. Attempt to update the existing 1787 // The profiles are found to be mergeable. Attempt to update the existing
1780 // profile. This returns true if the merge was successful, or if the 1788 // profile. This returns true if the merge was successful, or if the
1781 // merge would have been successful but the existing profile IsVerified() 1789 // merge would have been successful but the existing profile IsVerified()
1782 // and will not accept updates from profile_to_merge. 1790 // and will not accept updates from profile_to_merge.
1783 if (existing_profile->SaveAdditionalInfo(*profile_to_merge, 1791 if (existing_profile->SaveAdditionalInfo(*profile_to_merge,
1784 app_locale_)) { 1792 app_locale_)) {
1793 // Keep track that a credit card using |profile_to_merge|'s GUID as its
1794 // billing address id should replace it by |existing_profile|'s GUID.
1795 guids_merge_map->insert(std::pair<std::string, std::string>(
1796 profile_to_merge->guid(), existing_profile->guid()));
1797
1785 // Since |profile_to_merge| was a duplicate of |existing_profile| 1798 // Since |profile_to_merge| was a duplicate of |existing_profile|
1786 // and was merged successfully, it can now be deleted. 1799 // and was merged successfully, it can now be deleted.
1787 profiles_to_delete->insert(profile_to_merge); 1800 profiles_to_delete->insert(profile_to_merge);
1788 1801
1789 // Now try to merge the new resulting profile with the rest of the 1802 // Now try to merge the new resulting profile with the rest of the
1790 // existing profiles. 1803 // existing profiles.
1791 profile_to_merge = existing_profile; 1804 profile_to_merge = existing_profile;
1792 1805
1793 // Verified profiles do not get merged. Save some time by not 1806 // Verified profiles do not get merged. Save some time by not
1794 // trying. 1807 // trying.
1795 if (profile_to_merge->IsVerified()) 1808 if (profile_to_merge->IsVerified())
1796 break; 1809 break;
1797 } 1810 }
1798 } 1811 }
1799 } 1812 }
1800 AutofillMetrics::LogNumberOfProfilesRemovedDuringDedupe( 1813 AutofillMetrics::LogNumberOfProfilesRemovedDuringDedupe(
1801 profiles_to_delete->size()); 1814 profiles_to_delete->size());
1802 } 1815 }
1803 1816
1817 void PersonalDataManager::UpdateCardsBillingAddressReference(
1818 const std::unordered_map<std::string, std::string>& guids_merge_map) {
1819 /* Here is an example of what the graph might look like.
1820
1821 A -> B
1822 \
1823 -> E
1824 /
1825 C -> D
1826 */
1827
1828 for (auto& credit_card : local_credit_cards_) {
1829 // If the credit card is not associated with a billing address, skip it.
1830 if (credit_card->billing_address_id().empty())
1831 break;
1832
1833 // If the billing address profile associated with the card has been merged,
1834 // replace it by the id of the profile in which it was merged. Repeat the
1835 // process until the billing address has not been merged into another one.
1836 std::unordered_map<std::string, std::string>::size_type nb_guid_changes = 0;
1837 bool was_modified = false;
1838 auto it = guids_merge_map.find(credit_card->billing_address_id());
1839 while (it != guids_merge_map.end()) {
1840 was_modified = true;
1841 credit_card->set_billing_address_id(it->second);
1842 it = guids_merge_map.find(credit_card->billing_address_id());
1843
1844 // Out of abundance of caution.
1845 if (nb_guid_changes > guids_merge_map.size()) {
1846 NOTREACHED();
1847 // Cancel the changes for that card.
1848 was_modified = false;
1849 break;
1850 }
1851 }
1852
1853 // If the card was modified, apply the changes to the database.
1854 if (was_modified) {
1855 database_->UpdateCreditCard(*credit_card);
1856 }
1857 }
1858 }
1859
1804 } // namespace autofill 1860 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698