| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/autofill_profile_comparator.h" | 5 #include "components/autofill/core/browser/autofill_profile_comparator.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/i18n/case_conversion.h" | 10 #include "base/i18n/case_conversion.h" |
| 11 #include "base/i18n/char_iterator.h" | 11 #include "base/i18n/char_iterator.h" |
| 12 #include "base/i18n/unicodestring.h" | 12 #include "base/i18n/unicodestring.h" |
| 13 #include "base/strings/string_piece.h" | |
| 14 #include "base/strings/string_split.h" | 13 #include "base/strings/string_split.h" |
| 15 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
| 16 #include "base/strings/utf_string_conversion_utils.h" | 15 #include "base/strings/utf_string_conversion_utils.h" |
| 17 #include "base/strings/utf_string_conversions.h" | 16 #include "base/strings/utf_string_conversions.h" |
| 18 #include "components/autofill/core/browser/address_rewriter.h" | 17 #include "components/autofill/core/browser/address_rewriter.h" |
| 19 #include "components/autofill/core/browser/autofill_country.h" | 18 #include "components/autofill/core/browser/autofill_country.h" |
| 20 #include "components/autofill/core/browser/autofill_data_util.h" | 19 #include "components/autofill/core/browser/autofill_data_util.h" |
| 21 #include "components/autofill/core/browser/state_names.h" | 20 #include "components/autofill/core/browser/state_names.h" |
| 22 #include "third_party/libphonenumber/phonenumber_api.h" | 21 #include "third_party/libphonenumber/phonenumber_api.h" |
| 23 | 22 |
| (...skipping 637 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 661 if (!s1.empty()) | 660 if (!s1.empty()) |
| 662 return s1; | 661 return s1; |
| 663 return p2.GetInfo(t, app_locale_); | 662 return p2.GetInfo(t, app_locale_); |
| 664 } | 663 } |
| 665 | 664 |
| 666 // static | 665 // static |
| 667 std::set<base::string16> AutofillProfileComparator::GetNamePartVariants( | 666 std::set<base::string16> AutofillProfileComparator::GetNamePartVariants( |
| 668 const base::string16& name_part) { | 667 const base::string16& name_part) { |
| 669 const size_t kMaxSupportedSubNames = 8; | 668 const size_t kMaxSupportedSubNames = 8; |
| 670 | 669 |
| 671 std::vector<base::string16> sub_names = base::SplitString( | 670 std::vector<base::StringPiece16> sub_names = base::SplitStringPiece( |
| 672 name_part, kSpace, base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); | 671 name_part, kSpace, base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); |
| 673 | 672 |
| 674 // Limit the number of sub-names we support (to constrain memory usage); | 673 // Limit the number of sub-names we support (to constrain memory usage); |
| 675 if (sub_names.size() > kMaxSupportedSubNames) | 674 if (sub_names.size() > kMaxSupportedSubNames) |
| 676 return {name_part}; | 675 return {name_part}; |
| 677 | 676 |
| 678 // Start with the empty string as a variant. | 677 // Start with the empty string as a variant. |
| 679 std::set<base::string16> variants = {base::EmptyString16()}; | 678 std::set<base::string16> variants = {base::EmptyString16()}; |
| 680 | 679 |
| 681 // For each sub-name, add a variant of all the already existing variants that | 680 // For each sub-name, add a variant of all the already existing variants that |
| 682 // appends this sub-name and one that appends the initial of this sub-name. | 681 // appends this sub-name and one that appends the initial of this sub-name. |
| 683 // Duplicates will be discarded when they're added to the variants set. | 682 // Duplicates will be discarded when they're added to the variants set. |
| 684 for (const base::string16& sub_name : sub_names) { | 683 for (const auto& sub_name : sub_names) { |
| 685 if (sub_name.empty()) | 684 if (sub_name.empty()) |
| 686 continue; | 685 continue; |
| 687 std::vector<base::string16> new_variants; | 686 std::vector<base::string16> new_variants; |
| 688 for (const base::string16& variant : variants) { | 687 for (const base::string16& variant : variants) { |
| 689 new_variants.push_back(base::CollapseWhitespace( | 688 new_variants.push_back(base::CollapseWhitespace( |
| 690 base::JoinString({variant, sub_name}, kSpace), true)); | 689 base::JoinString({variant, sub_name}, kSpace), true)); |
| 691 new_variants.push_back(base::CollapseWhitespace( | 690 new_variants.push_back(base::CollapseWhitespace( |
| 692 base::JoinString({variant, sub_name.substr(0, 1)}, kSpace), true)); | 691 base::JoinString({variant, sub_name.substr(0, 1)}, kSpace), true)); |
| 693 } | 692 } |
| 694 variants.insert(new_variants.begin(), new_variants.end()); | 693 variants.insert(new_variants.begin(), new_variants.end()); |
| 695 } | 694 } |
| 696 | 695 |
| 697 // As a common case, also add the variant that just concatenates all of the | 696 // As a common case, also add the variant that just concatenates all of the |
| 698 // initials. | 697 // initials. |
| 699 base::string16 initials; | 698 base::string16 initials; |
| 700 for (const base::string16& sub_name : sub_names) { | 699 for (const auto& sub_name : sub_names) { |
| 701 if (sub_name.empty()) | 700 if (sub_name.empty()) |
| 702 continue; | 701 continue; |
| 703 initials.push_back(sub_name[0]); | 702 initials.push_back(sub_name[0]); |
| 704 } | 703 } |
| 705 variants.insert(initials); | 704 variants.insert(initials); |
| 706 | 705 |
| 707 // And, we're done. | 706 // And, we're done. |
| 708 return variants; | 707 return variants; |
| 709 } | 708 } |
| 710 | 709 |
| 711 bool AutofillProfileComparator::IsNameVariantOf( | 710 bool AutofillProfileComparator::IsNameVariantOf( |
| 712 const base::string16& full_name_1, | 711 const base::string16& full_name_1, |
| 713 const base::string16& full_name_2) const { | 712 const base::string16& full_name_2) const { |
| 714 data_util::NameParts name_1_parts = data_util::SplitName(full_name_1); | 713 data_util::NameParts name_1_parts = data_util::SplitName(full_name_1); |
| 715 | 714 |
| 716 // Build the variants of full_name_1`s given, middle and family names. | 715 // Build the variants of full_name_1`s given, middle and family names. |
| 717 // | 716 // |
| 718 // TODO(rogerm): Figure out whether or not we should break apart a compound | 717 // TODO(rogerm): Figure out whether or not we should break apart a compound |
| 719 // family name into variants (crbug/619051) | 718 // family name into variants (crbug/619051) |
| 720 const std::set<base::string16> given_name_variants = | 719 const std::set<base::string16> given_name_variants = |
| 721 GetNamePartVariants(name_1_parts.given); | 720 GetNamePartVariants(name_1_parts.given); |
| 722 const std::set<base::string16> middle_name_variants = | 721 const std::set<base::string16> middle_name_variants = |
| 723 GetNamePartVariants(name_1_parts.middle); | 722 GetNamePartVariants(name_1_parts.middle); |
| 724 const base::string16& family_name = name_1_parts.family; | 723 base::StringPiece16 family_name = name_1_parts.family; |
| 725 | 724 |
| 726 // Iterate over all full name variants of profile 2 and see if any of them | 725 // Iterate over all full name variants of profile 2 and see if any of them |
| 727 // match the full name from profile 1. | 726 // match the full name from profile 1. |
| 728 for (const base::string16& given_name : given_name_variants) { | 727 for (const auto& given_name : given_name_variants) { |
| 729 for (const base::string16& middle_name : middle_name_variants) { | 728 for (const auto& middle_name : middle_name_variants) { |
| 730 base::string16 candidate = base::CollapseWhitespace( | 729 base::string16 candidate = base::CollapseWhitespace( |
| 731 base::JoinString({given_name, middle_name, family_name}, kSpace), | 730 base::JoinString({given_name, middle_name, family_name}, kSpace), |
| 732 true); | 731 true); |
| 733 if (candidate == full_name_2) | 732 if (candidate == full_name_2) |
| 734 return true; | 733 return true; |
| 735 } | 734 } |
| 736 } | 735 } |
| 737 | 736 |
| 738 // Also check if the name is just composed of the user's initials. For | 737 // Also check if the name is just composed of the user's initials. For |
| 739 // example, "thomas jefferson miller" could be composed as "tj miller". | 738 // example, "thomas jefferson miller" could be composed as "tj miller". |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 951 const base::string16& address2 = rewriter.Rewrite(NormalizeForComparison( | 950 const base::string16& address2 = rewriter.Rewrite(NormalizeForComparison( |
| 952 p2.GetInfo(AutofillType(ADDRESS_HOME_STREET_ADDRESS), app_locale_))); | 951 p2.GetInfo(AutofillType(ADDRESS_HOME_STREET_ADDRESS), app_locale_))); |
| 953 if (CompareTokens(address1, address2) == DIFFERENT_TOKENS) { | 952 if (CompareTokens(address1, address2) == DIFFERENT_TOKENS) { |
| 954 return false; | 953 return false; |
| 955 } | 954 } |
| 956 | 955 |
| 957 return true; | 956 return true; |
| 958 } | 957 } |
| 959 | 958 |
| 960 } // namespace autofill | 959 } // namespace autofill |
| OLD | NEW |