| 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> |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 #include "components/autofill/core/browser/phone_number_i18n.h" | 32 #include "components/autofill/core/browser/phone_number_i18n.h" |
| 33 #include "components/autofill/core/browser/validation.h" | 33 #include "components/autofill/core/browser/validation.h" |
| 34 #include "components/autofill/core/common/autofill_pref_names.h" | 34 #include "components/autofill/core/common/autofill_pref_names.h" |
| 35 #include "components/autofill/core/common/autofill_switches.h" | 35 #include "components/autofill/core/common/autofill_switches.h" |
| 36 #include "components/autofill/core/common/autofill_util.h" | 36 #include "components/autofill/core/common/autofill_util.h" |
| 37 #include "components/prefs/pref_service.h" | 37 #include "components/prefs/pref_service.h" |
| 38 #include "components/signin/core/browser/account_tracker_service.h" | 38 #include "components/signin/core/browser/account_tracker_service.h" |
| 39 #include "components/signin/core/browser/signin_manager.h" | 39 #include "components/signin/core/browser/signin_manager.h" |
| 40 #include "components/signin/core/common/signin_pref_names.h" | 40 #include "components/signin/core/common/signin_pref_names.h" |
| 41 #include "components/variations/variations_associated_data.h" | 41 #include "components/variations/variations_associated_data.h" |
| 42 #include "components/version_info/version_info.h" |
| 42 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_da
ta.h" | 43 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_da
ta.h" |
| 43 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_fo
rmatter.h" | 44 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_fo
rmatter.h" |
| 44 | 45 |
| 45 namespace autofill { | 46 namespace autofill { |
| 46 namespace { | 47 namespace { |
| 47 | 48 |
| 48 using ::i18n::addressinput::AddressField; | 49 using ::i18n::addressinput::AddressField; |
| 49 using ::i18n::addressinput::GetStreetAddressLinesAsSingleLine; | 50 using ::i18n::addressinput::GetStreetAddressLinesAsSingleLine; |
| 50 using ::i18n::addressinput::STREET_ADDRESS; | 51 using ::i18n::addressinput::STREET_ADDRESS; |
| 51 | 52 |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 pending_profiles_query_ = 0; | 318 pending_profiles_query_ = 0; |
| 318 return; | 319 return; |
| 319 } | 320 } |
| 320 | 321 |
| 321 switch (result->GetType()) { | 322 switch (result->GetType()) { |
| 322 case AUTOFILL_PROFILES_RESULT: | 323 case AUTOFILL_PROFILES_RESULT: |
| 323 if (h == pending_profiles_query_) { | 324 if (h == pending_profiles_query_) { |
| 324 ReceiveLoadedDbValues(h, result, &pending_profiles_query_, | 325 ReceiveLoadedDbValues(h, result, &pending_profiles_query_, |
| 325 &web_profiles_); | 326 &web_profiles_); |
| 326 LogProfileCount(); // This only logs local profiles. | 327 LogProfileCount(); // This only logs local profiles. |
| 327 ApplyProfileUseDatesFix(); | 328 // Since these two routines both re-launch the database queries, don't |
| 329 // run them on the same query response. |
| 330 if (!ApplyDedupingRoutine()) |
| 331 ApplyProfileUseDatesFix(); |
| 328 } else { | 332 } else { |
| 329 ReceiveLoadedDbValues(h, result, &pending_server_profiles_query_, | 333 ReceiveLoadedDbValues(h, result, &pending_server_profiles_query_, |
| 330 &server_profiles_); | 334 &server_profiles_); |
| 331 | 335 |
| 332 if (!server_profiles_.empty()) { | 336 if (!server_profiles_.empty()) { |
| 333 std::string account_id = signin_manager_->GetAuthenticatedAccountId(); | 337 std::string account_id = signin_manager_->GetAuthenticatedAccountId(); |
| 334 base::string16 email = | 338 base::string16 email = |
| 335 base::UTF8ToUTF16( | 339 base::UTF8ToUTF16( |
| 336 account_tracker_->GetAccountInfo(account_id).email); | 340 account_tracker_->GetAccountInfo(account_id).email); |
| 337 | 341 |
| (...skipping 590 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 928 if (!matching_profile_found && | 932 if (!matching_profile_found && |
| 929 !new_profile.PrimaryValue(app_locale_).empty() && | 933 !new_profile.PrimaryValue(app_locale_).empty() && |
| 930 existing_profile->SaveAdditionalInfo(new_profile, app_locale)) { | 934 existing_profile->SaveAdditionalInfo(new_profile, app_locale)) { |
| 931 // Unverified profiles should always be updated with the newer data, | 935 // Unverified profiles should always be updated with the newer data, |
| 932 // whereas verified profiles should only ever be overwritten by verified | 936 // whereas verified profiles should only ever be overwritten by verified |
| 933 // data. If an automatically aggregated profile would overwrite a | 937 // data. If an automatically aggregated profile would overwrite a |
| 934 // verified profile, just drop it. | 938 // verified profile, just drop it. |
| 935 matching_profile_found = true; | 939 matching_profile_found = true; |
| 936 guid = existing_profile->guid(); | 940 guid = existing_profile->guid(); |
| 937 | 941 |
| 938 if (IsAutofillProfileCleanupEnabled()) { | |
| 939 // Look for duplicates of |existing_profile| to merge into. | |
| 940 FindMergeAndDeleteDuplicateProfiles(existing_profiles, | |
| 941 existing_profile); | |
| 942 } | |
| 943 | |
| 944 // We set the modification date so that immediate requests for profiles | 942 // We set the modification date so that immediate requests for profiles |
| 945 // will properly reflect the fact that this profile has been modified | 943 // will properly reflect the fact that this profile has been modified |
| 946 // recently. After writing to the database and refreshing the local copies | 944 // recently. After writing to the database and refreshing the local copies |
| 947 // the profile will have a very slightly newer time reflecting what's | 945 // the profile will have a very slightly newer time reflecting what's |
| 948 // actually stored in the database. | 946 // actually stored in the database. |
| 949 existing_profile->set_modification_date(base::Time::Now()); | 947 existing_profile->set_modification_date(base::Time::Now()); |
| 950 } | 948 } |
| 951 merged_profiles->push_back(*existing_profile); | 949 merged_profiles->push_back(*existing_profile); |
| 952 } | 950 } |
| 953 | 951 |
| (...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1549 if (IsFeatureSubstringMatchEnabled()) { | 1547 if (IsFeatureSubstringMatchEnabled()) { |
| 1550 std::stable_sort(suggestions.begin(), suggestions.end(), | 1548 std::stable_sort(suggestions.begin(), suggestions.end(), |
| 1551 [](const Suggestion& a, const Suggestion& b) { | 1549 [](const Suggestion& a, const Suggestion& b) { |
| 1552 return a.match < b.match; | 1550 return a.match < b.match; |
| 1553 }); | 1551 }); |
| 1554 } | 1552 } |
| 1555 | 1553 |
| 1556 return suggestions; | 1554 return suggestions; |
| 1557 } | 1555 } |
| 1558 | 1556 |
| 1559 void PersonalDataManager::FindMergeAndDeleteDuplicateProfiles( | |
| 1560 const std::vector<AutofillProfile*>& existing_profiles, | |
| 1561 AutofillProfile* profile_to_merge) { | |
| 1562 std::vector<std::string> profile_guids_to_delete; | |
| 1563 | |
| 1564 FindAndMergeDuplicateProfiles(existing_profiles, profile_to_merge, | |
| 1565 &profile_guids_to_delete); | |
| 1566 | |
| 1567 // Delete the duplicate profiles. | |
| 1568 for (const std::string& profile_guid_to_delete : profile_guids_to_delete) { | |
| 1569 RemoveByGUID(profile_guid_to_delete); | |
| 1570 } | |
| 1571 } | |
| 1572 | |
| 1573 void PersonalDataManager::FindAndMergeDuplicateProfiles( | |
| 1574 const std::vector<AutofillProfile*>& existing_profiles, | |
| 1575 AutofillProfile* profile_to_merge, | |
| 1576 std::vector<std::string>* profile_guids_to_delete) { | |
| 1577 AutofillMetrics::LogNumberOfProfilesConsideredForDedupe( | |
| 1578 existing_profiles.size()); | |
| 1579 for (AutofillProfile* existing_profile : existing_profiles) { | |
| 1580 // Don't try to merge a profile with itself or with any profile with a | |
| 1581 // different PrimaryValue. | |
| 1582 if (existing_profile->guid() != profile_to_merge->guid() && | |
| 1583 AutofillProfile::CanonicalizeProfileString( | |
| 1584 existing_profile->PrimaryValue(app_locale_)) == | |
| 1585 AutofillProfile::CanonicalizeProfileString( | |
| 1586 profile_to_merge->PrimaryValue(app_locale_))) { | |
| 1587 if (existing_profile->SaveAdditionalInfo(*profile_to_merge, | |
| 1588 app_locale_)) { | |
| 1589 // Since |profile_to_merge| was a duplicate of |existing_profile| and | |
| 1590 // was merged sucessfully, it can now be deleted. The only exception is | |
| 1591 // if |profile_to_merge| is verified and |existing_profile| is not. | |
| 1592 // Verified profiles only merge with other verified profiles. | |
| 1593 if (!profile_to_merge->IsVerified() || existing_profile->IsVerified()) | |
| 1594 profile_guids_to_delete->push_back(profile_to_merge->guid()); | |
| 1595 | |
| 1596 // Now try to merge the new resulting profile with the rest of the | |
| 1597 // existing profiles. | |
| 1598 profile_to_merge = existing_profile; | |
| 1599 } | |
| 1600 } | |
| 1601 } | |
| 1602 | |
| 1603 AutofillMetrics::LogNumberOfProfilesRemovedDuringDedupe( | |
| 1604 profile_guids_to_delete->size()); | |
| 1605 } | |
| 1606 | |
| 1607 void PersonalDataManager::ApplyProfileUseDatesFix() { | 1557 void PersonalDataManager::ApplyProfileUseDatesFix() { |
| 1608 // Don't run if the fix has already been applied. | 1558 // Don't run if the fix has already been applied. |
| 1609 if (pref_service_->GetBoolean(prefs::kAutofillProfileUseDatesFixed)) | 1559 if (pref_service_->GetBoolean(prefs::kAutofillProfileUseDatesFixed)) |
| 1610 return; | 1560 return; |
| 1611 | 1561 |
| 1612 std::vector<AutofillProfile> profiles; | 1562 std::vector<AutofillProfile> profiles; |
| 1613 bool has_changed_data = false; | 1563 bool has_changed_data = false; |
| 1614 for (AutofillProfile* profile : web_profiles()) { | 1564 for (AutofillProfile* profile : web_profiles()) { |
| 1615 if (profile->use_date() == base::Time()) { | 1565 if (profile->use_date() == base::Time()) { |
| 1616 profile->set_use_date(base::Time::Now() - base::TimeDelta::FromDays(14)); | 1566 profile->set_use_date(base::Time::Now() - base::TimeDelta::FromDays(14)); |
| 1617 has_changed_data = true; | 1567 has_changed_data = true; |
| 1618 } | 1568 } |
| 1619 profiles.push_back(*profile); | 1569 profiles.push_back(*profile); |
| 1620 } | 1570 } |
| 1621 | 1571 |
| 1622 // Set the pref so that this fix is never run again. | 1572 // Set the pref so that this fix is never run again. |
| 1623 pref_service_->SetBoolean(prefs::kAutofillProfileUseDatesFixed, true); | 1573 pref_service_->SetBoolean(prefs::kAutofillProfileUseDatesFixed, true); |
| 1624 | 1574 |
| 1625 if (has_changed_data) | 1575 if (has_changed_data) |
| 1626 SetProfiles(&profiles); | 1576 SetProfiles(&profiles); |
| 1627 } | 1577 } |
| 1628 | 1578 |
| 1579 bool PersonalDataManager::ApplyDedupingRoutine() { |
| 1580 if (!IsAutofillProfileCleanupEnabled()) |
| 1581 return false; |
| 1582 |
| 1583 int current_major_version = atoi(version_info::GetVersionNumber().c_str()); |
| 1584 |
| 1585 // Check if the deduping routine has already been run on this major version. |
| 1586 if (pref_service_->GetInteger(prefs::kAutofillLastVersionDeduped) >= |
| 1587 current_major_version) |
| 1588 return false; |
| 1589 |
| 1590 std::vector<AutofillProfile*> existing_profiles = web_profiles_.get(); |
| 1591 std::unordered_set<AutofillProfile*> profiles_to_delete; |
| 1592 profiles_to_delete.reserve(existing_profiles.size()); |
| 1593 |
| 1594 DedupeProfiles(&existing_profiles, &profiles_to_delete); |
| 1595 |
| 1596 // Apply the changes to the database. |
| 1597 for (AutofillProfile* profile : existing_profiles) { |
| 1598 // If the profile was set to be deleted, remove it from the database. |
| 1599 if (profiles_to_delete.count(profile)) { |
| 1600 database_->RemoveAutofillProfile(profile->guid()); |
| 1601 } else { |
| 1602 // Otherwise, update the profile in the database. |
| 1603 database_->UpdateAutofillProfile(*profile); |
| 1604 } |
| 1605 } |
| 1606 |
| 1607 // Set the pref to the current major version. |
| 1608 pref_service_->SetInteger(prefs::kAutofillLastVersionDeduped, |
| 1609 current_major_version); |
| 1610 |
| 1611 // Refresh the local cache and send notifications to observers. |
| 1612 Refresh(); |
| 1613 |
| 1614 return true; |
| 1615 } |
| 1616 |
| 1617 void PersonalDataManager::DedupeProfiles( |
| 1618 std::vector<AutofillProfile*>* existing_profiles, |
| 1619 std::unordered_set<AutofillProfile*>* profiles_to_delete) { |
| 1620 AutofillMetrics::LogNumberOfProfilesConsideredForDedupe( |
| 1621 existing_profiles->size()); |
| 1622 |
| 1623 // Sort the profiles by frecency with all the verified profiles at the end. |
| 1624 // That way the most relevant profiles will get merged into the less relevant |
| 1625 // profiles, which keeps the syntax of the most relevant profiles data. |
| 1626 // Verified profiles are put at the end because they do not merge into other |
| 1627 // profiles, so the loop can be stopped when we reach those. However they need |
| 1628 // to be in the vector because an unverified profile trying to merge into a |
| 1629 // similar verified profile will be discarded. |
| 1630 base::Time comparison_time = base::Time::Now(); |
| 1631 std::sort(existing_profiles->begin(), existing_profiles->end(), |
| 1632 [comparison_time](const AutofillDataModel* a, |
| 1633 const AutofillDataModel* b) { |
| 1634 if (a->IsVerified() != b->IsVerified()) |
| 1635 return !a->IsVerified(); |
| 1636 return a->CompareFrecency(b, comparison_time); |
| 1637 }); |
| 1638 |
| 1639 for (size_t i = 0; i < existing_profiles->size(); ++i) { |
| 1640 AutofillProfile* profile_to_merge = (*existing_profiles)[i]; |
| 1641 |
| 1642 // If the profile was set to be deleted, skip it. It has already been |
| 1643 // merged into another profile. |
| 1644 if (profiles_to_delete->count(profile_to_merge)) |
| 1645 continue; |
| 1646 |
| 1647 // If we have reached the verified profiles, stop trying to merge. Verified |
| 1648 // profiles do not get merged. |
| 1649 if (profile_to_merge->IsVerified()) |
| 1650 break; |
| 1651 |
| 1652 // If we have not reached the last profile, try to merge |profile_to_merge| |
| 1653 // with all the less relevant |existing_profiles|. |
| 1654 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 |
| 1656 // don't try to merge with profiles with a different PrimaryValue |
| 1657 // because they are not similar. |
| 1658 AutofillProfile* existing_profile = (*existing_profiles)[j]; |
| 1659 if (!profiles_to_delete->count(existing_profile) && |
| 1660 existing_profile->PrimaryValue(app_locale_) == |
| 1661 profile_to_merge->PrimaryValue(app_locale_)) { |
| 1662 // If the profiles are found to be similar, |profile_to_merge|'s non |
| 1663 // empty data will overwrite the |existing_profile|'s data. |
| 1664 // |existing_profile| will have added the complementary data from |
| 1665 // |profile_to_merge| and will keep the most relevant syntax for data |
| 1666 // present in both profiles. |
| 1667 if (existing_profile->SaveAdditionalInfo(*profile_to_merge, |
| 1668 app_locale_)) { |
| 1669 // Since |profile_to_merge| was a duplicate of |existing_profile| |
| 1670 // and was merged sucessfully, it can now be deleted. |
| 1671 profiles_to_delete->insert(profile_to_merge); |
| 1672 |
| 1673 // Now try to merge the new resulting profile with the rest of the |
| 1674 // existing profiles. |
| 1675 profile_to_merge = existing_profile; |
| 1676 |
| 1677 // Verified profiles do not get merged. Save some time by not |
| 1678 // trying. |
| 1679 if (profile_to_merge->IsVerified()) |
| 1680 break; |
| 1681 } |
| 1682 } |
| 1683 } |
| 1684 } |
| 1685 AutofillMetrics::LogNumberOfProfilesRemovedDuringDedupe( |
| 1686 profiles_to_delete->size()); |
| 1687 } |
| 1688 |
| 1629 } // namespace autofill | 1689 } // namespace autofill |
| OLD | NEW |