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> |
| (...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 was run on this major version. | |
|
Roger McFarlane (Chromium)
2016/06/20 18:40:04
nit:
...was already run...
or, better yet,
...h
sebsg
2016/06/20 19:12:19
Done.
| |
| 1586 if (!(pref_service_->GetInteger(prefs::kAutofillLastVersionDeduped) < | |
|
Mathieu
2016/06/20 15:48:54
I think I would prefer >=, it's cleaner.
sebsg
2016/06/20 19:12:19
Done.
| |
| 1587 current_major_version)) | |
| 1588 return false; | |
| 1589 | |
| 1590 std::vector<AutofillProfile*> existing_profiles = web_profiles_.get(); | |
| 1591 std::set<std::string> profile_guids_to_delete; | |
|
Roger McFarlane (Chromium)
2016/06/20 18:40:04
micro-optimizations:
* Why reference the profiles
sebsg
2016/06/20 19:12:19
Done.
| |
| 1592 | |
| 1593 DedupeProfiles(&existing_profiles, &profile_guids_to_delete); | |
| 1594 | |
| 1595 // Set the pref to the current major version. | |
| 1596 pref_service_->SetInteger(prefs::kAutofillLastVersionDeduped, | |
|
Roger McFarlane (Chromium)
2016/06/20 18:40:04
unless there is no possibility of failure beyond t
sebsg
2016/06/20 19:12:19
Done.
| |
| 1597 current_major_version); | |
| 1598 | |
| 1599 // Apply the changes to the database. | |
| 1600 for (AutofillProfile* profile : existing_profiles) { | |
| 1601 // If the profile was set to be deleted, remove it from the database. | |
| 1602 if (profile_guids_to_delete.count(profile->guid())) { | |
| 1603 database_->RemoveAutofillProfile(profile->guid()); | |
| 1604 } else { | |
| 1605 // Otherwise, update the profile in the database. | |
| 1606 database_->UpdateAutofillProfile(*profile); | |
| 1607 } | |
| 1608 } | |
| 1609 | |
| 1610 // Refresh the local cache and send notifications to observers. | |
| 1611 Refresh(); | |
| 1612 | |
| 1613 return true; | |
| 1614 } | |
| 1615 | |
| 1616 void PersonalDataManager::DedupeProfiles( | |
| 1617 std::vector<AutofillProfile*>* existing_profiles, | |
| 1618 std::set<std::string>* profile_guids_to_delete) { | |
|
Roger McFarlane (Chromium)
2016/06/20 18:40:04
unordered_set, reserved existing_profiles.size()
sebsg
2016/06/20 19:12:19
Done.
| |
| 1619 // Sort the profiles by frecency with all the verified profiles at the end. | |
| 1620 // That way the most relevant profiles will get merged into the less relevant | |
| 1621 // profiles, which keeps the syntax of the most relevant profiles data. | |
| 1622 // Verified profiles are put at the end because they do not merge into other | |
| 1623 // profiles, so the loop can be stopped when we reach those. However they need | |
| 1624 // to be in the vector because an unverified profile trying to merge into a | |
| 1625 // similar verified profile will be discarded. | |
| 1626 base::Time comparison_time = base::Time::Now(); | |
| 1627 std::sort(existing_profiles->begin(), existing_profiles->end(), | |
| 1628 [comparison_time](const AutofillDataModel* a, | |
| 1629 const AutofillDataModel* b) { | |
| 1630 if (a->IsVerified() != b->IsVerified()) | |
| 1631 return !a->IsVerified(); | |
| 1632 return a->CompareFrecency(b, comparison_time); | |
| 1633 }); | |
| 1634 | |
| 1635 AutofillMetrics::LogNumberOfProfilesConsideredForDedupe( | |
|
Roger McFarlane (Chromium)
2016/06/20 18:40:04
move the log to the beginning... since it's not a
sebsg
2016/06/20 19:12:19
Done.
| |
| 1636 existing_profiles->size()); | |
| 1637 | |
| 1638 for (size_t i = 0; i < existing_profiles->size(); ++i) { | |
| 1639 AutofillProfile* profile_to_merge = (*existing_profiles)[i]; | |
| 1640 | |
| 1641 // If the profile was set to be deleted, skip it. It has already been | |
| 1642 // merged into another profile. | |
| 1643 if (profile_guids_to_delete->count(profile_to_merge->guid())) | |
| 1644 continue; | |
| 1645 | |
| 1646 // If we have reached the verified profiles, stop trying to merge. Verified | |
| 1647 // profiles do not get merged. | |
| 1648 if (profile_to_merge->IsVerified()) | |
| 1649 break; | |
| 1650 | |
| 1651 // If we have not reached the last profile. | |
| 1652 if (i + 1 < existing_profiles->size()) { | |
|
Roger McFarlane (Chromium)
2016/06/20 18:40:04
this is redundant with the bounds in the enclosed
sebsg
2016/06/20 19:12:19
Done.
| |
| 1653 // Try to merge |profile_to_merge| with all the less relevant | |
| 1654 // |existing_profiles|. | |
| 1655 for (size_t j = i + 1; j < existing_profiles->size(); ++j) { | |
| 1656 // Don't try to merge a profile that was already set for deletion. Also | |
| 1657 // don't try to merge with profiles with a different PrimaryValue | |
| 1658 // because they are not similar. | |
| 1659 AutofillProfile* existing_profile = (*existing_profiles)[j]; | |
| 1660 if (!profile_guids_to_delete->count(existing_profile->guid()) && | |
| 1661 existing_profile->PrimaryValue(app_locale_) == | |
| 1662 profile_to_merge->PrimaryValue(app_locale_)) { | |
| 1663 // If the profiles are found to be similar, |profile_to_merge|'s non | |
| 1664 // empty data will overwrite the |existing_profile|'s data. | |
| 1665 // |existing_profile| will have added the complementary data from | |
| 1666 // |profile_to_merge| and will keep the most relevant syntax for data | |
| 1667 // present in both profiles. | |
| 1668 if (existing_profile->SaveAdditionalInfo(*profile_to_merge, | |
| 1669 app_locale_)) { | |
| 1670 // Since |profile_to_merge| was a duplicate of |existing_profile| | |
| 1671 // and was merged sucessfully, it can now be deleted. | |
| 1672 profile_guids_to_delete->insert(profile_to_merge->guid()); | |
| 1673 | |
| 1674 // Now try to merge the new resulting profile with the rest of the | |
| 1675 // existing profiles. | |
| 1676 profile_to_merge = existing_profile; | |
| 1677 | |
| 1678 // Verified profiles do not get merged. Save some time by not | |
| 1679 // trying. | |
| 1680 if (profile_to_merge->IsVerified()) | |
|
Roger McFarlane (Chromium)
2016/06/20 18:40:04
this check seems too late.
I think you need to ch
sebsg
2016/06/20 19:12:19
The |existing_profile| can (and should sometimes)
Roger McFarlane (Chromium)
2016/06/20 19:18:36
Acknowledged.
| |
| 1681 break; | |
| 1682 } | |
| 1683 } | |
| 1684 } | |
| 1685 } | |
| 1686 } | |
| 1687 AutofillMetrics::LogNumberOfProfilesRemovedDuringDedupe( | |
| 1688 profile_guids_to_delete->size()); | |
| 1689 } | |
| 1690 | |
| 1629 } // namespace autofill | 1691 } // namespace autofill |
| OLD | NEW |