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