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

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

Issue 347183005: autofill names - dont parse when calling SetRawInfo(FULL_NAME) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix android test expectation Created 6 years, 5 months 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 | Annotate | Revision Log
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/autofill_profile.h" 5 #include "components/autofill/core/browser/autofill_profile.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <functional> 8 #include <functional>
9 #include <map> 9 #include <map>
10 #include <ostream> 10 #include <ostream>
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 std::swap(*type_set, collapsed_set); 189 std::swap(*type_set, collapsed_set);
190 } 190 }
191 191
192 class FindByPhone { 192 class FindByPhone {
193 public: 193 public:
194 FindByPhone(const base::string16& phone, 194 FindByPhone(const base::string16& phone,
195 const std::string& country_code, 195 const std::string& country_code,
196 const std::string& app_locale) 196 const std::string& app_locale)
197 : phone_(phone), 197 : phone_(phone),
198 country_code_(country_code), 198 country_code_(country_code),
199 app_locale_(app_locale) { 199 app_locale_(app_locale) {}
200 }
201 200
202 bool operator()(const base::string16& phone) { 201 bool operator()(const base::string16& phone) {
203 return i18n::PhoneNumbersMatch(phone, phone_, country_code_, app_locale_); 202 return i18n::PhoneNumbersMatch(phone, phone_, country_code_, app_locale_);
204 } 203 }
205 204
206 bool operator()(const base::string16* phone) {
207 return i18n::PhoneNumbersMatch(*phone, phone_, country_code_, app_locale_);
208 }
209
210 private: 205 private:
211 base::string16 phone_; 206 base::string16 phone_;
212 std::string country_code_; 207 std::string country_code_;
213 std::string app_locale_; 208 std::string app_locale_;
214 }; 209 };
215 210
216 // Functor used to check for case-insensitive equality of two strings. 211 // Functor used to check for case-insensitive equality of two strings.
217 struct CaseInsensitiveStringEquals 212 struct CaseInsensitiveStringEquals {
218 : public std::binary_function<base::string16, base::string16, bool> 213 public:
219 { 214 CaseInsensitiveStringEquals(const base::string16& other)
220 bool operator()(const base::string16& x, const base::string16& y) const { 215 : other_(other) {}
221 return 216
222 x.size() == y.size() && StringToLowerASCII(x) == StringToLowerASCII(y); 217 bool operator()(const base::string16& x) const {
218 return x.size() == other_.size() &&
219 StringToLowerASCII(x) == StringToLowerASCII(other_);
223 } 220 }
221
222 private:
223 const base::string16& other_;
224 }; 224 };
225 225
226 } // namespace 226 } // namespace
227 227
228 AutofillProfile::AutofillProfile(const std::string& guid, 228 AutofillProfile::AutofillProfile(const std::string& guid,
229 const std::string& origin) 229 const std::string& origin)
230 : AutofillDataModel(guid, origin), 230 : AutofillDataModel(guid, origin),
231 name_(1), 231 name_(1),
232 email_(1), 232 email_(1),
233 phone_number_(1, PhoneNumber(this)) { 233 phone_number_(1, PhoneNumber(this)) {
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
427 ADDRESS_HOME_COUNTRY, 427 ADDRESS_HOME_COUNTRY,
428 }; 428 };
429 429
430 for (size_t i = 0; i < arraysize(single_value_types); ++i) { 430 for (size_t i = 0; i < arraysize(single_value_types); ++i) {
431 int comparison = GetRawInfo(single_value_types[i]).compare( 431 int comparison = GetRawInfo(single_value_types[i]).compare(
432 profile.GetRawInfo(single_value_types[i])); 432 profile.GetRawInfo(single_value_types[i]));
433 if (comparison != 0) 433 if (comparison != 0)
434 return comparison; 434 return comparison;
435 } 435 }
436 436
437 const ServerFieldType multi_value_types[] = { NAME_FIRST, 437 const ServerFieldType multi_value_types[] = { NAME_FULL,
438 NAME_FIRST,
438 NAME_MIDDLE, 439 NAME_MIDDLE,
439 NAME_LAST, 440 NAME_LAST,
440 EMAIL_ADDRESS, 441 EMAIL_ADDRESS,
441 PHONE_HOME_WHOLE_NUMBER }; 442 PHONE_HOME_WHOLE_NUMBER };
442 443
443 for (size_t i = 0; i < arraysize(multi_value_types); ++i) { 444 for (size_t i = 0; i < arraysize(multi_value_types); ++i) {
444 std::vector<base::string16> values_a; 445 std::vector<base::string16> values_a;
445 std::vector<base::string16> values_b; 446 std::vector<base::string16> values_b;
446 GetRawMultiInfo(multi_value_types[i], &values_a); 447 GetRawMultiInfo(multi_value_types[i], &values_a);
447 profile.GetRawMultiInfo(multi_value_types[i], &values_b); 448 profile.GetRawMultiInfo(multi_value_types[i], &values_b);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 } else if (StringToLowerASCII(GetRawInfo(*it)) != 512 } else if (StringToLowerASCII(GetRawInfo(*it)) !=
512 StringToLowerASCII(profile.GetRawInfo(*it))) { 513 StringToLowerASCII(profile.GetRawInfo(*it))) {
513 return false; 514 return false;
514 } 515 }
515 } 516 }
516 517
517 return true; 518 return true;
518 } 519 }
519 520
520 void AutofillProfile::OverwriteOrAppendNames( 521 void AutofillProfile::OverwriteOrAppendNames(
521 const std::vector<NameInfo>& names) { 522 const std::vector<NameInfo>& names,
523 const std::string& app_locale) {
522 std::vector<NameInfo> results(name_); 524 std::vector<NameInfo> results(name_);
523 for (std::vector<NameInfo>::const_iterator it = names.begin(); 525 for (std::vector<NameInfo>::const_iterator it = names.begin();
524 it != names.end(); 526 it != names.end();
525 ++it) { 527 ++it) {
526 NameInfo imported_name = *it; 528 NameInfo imported_name = *it;
527 bool should_append_imported_name = true; 529 bool should_append_imported_name = true;
528 530
529 for (size_t index = 0; index < name_.size(); ++index) { 531 for (size_t index = 0; index < name_.size(); ++index) {
530 NameInfo current_name = name_[index]; 532 NameInfo current_name = name_[index];
531 if (current_name.EqualsIgnoreCase(imported_name)) { 533 if (current_name.ParsedNamesAreEqual(imported_name)) {
534 if (current_name.GetRawInfo(NAME_FULL).empty()) {
535 current_name.SetRawInfo(NAME_FULL,
536 imported_name.GetRawInfo(NAME_FULL));
537 }
538
532 should_append_imported_name = false; 539 should_append_imported_name = false;
533 break; 540 break;
534 } 541 }
535 542
536 base::string16 full_name = current_name.GetRawInfo(NAME_FULL); 543 AutofillType type = AutofillType(NAME_FULL);
544 base::string16 full_name = current_name.GetInfo(type, app_locale);
537 if (StringToLowerASCII(full_name) == 545 if (StringToLowerASCII(full_name) ==
538 StringToLowerASCII(imported_name.GetRawInfo(NAME_FULL))) { 546 StringToLowerASCII(imported_name.GetInfo(type, app_locale))) {
539 // The imported name has the same full name string as one of the 547 // The imported name has the same full name string as one of the
540 // existing names for this profile. Because full names are 548 // existing names for this profile. Because full names are
541 // _heuristically_ parsed into {first, middle, last} name components, 549 // _heuristically_ parsed into {first, middle, last} name components,
542 // it's possible that either the existing name or the imported name 550 // it's possible that either the existing name or the imported name
543 // was misparsed. Prefer to keep the name whose {first, middle, 551 // was misparsed. Prefer to keep the name whose {first, middle,
544 // last} components do not match those computed by the heuristic 552 // last} components do not match those computed by the heuristic
545 // parse, as this more likely represents the correct, user-input parse 553 // parse, as this more likely represents the correct, user-input parse
546 // of the name. 554 // of the name.
547 NameInfo heuristically_parsed_name; 555 NameInfo heuristically_parsed_name;
548 heuristically_parsed_name.SetRawInfo(NAME_FULL, full_name); 556 heuristically_parsed_name.SetInfo(type, full_name, app_locale);
549 if (imported_name.EqualsIgnoreCase(heuristically_parsed_name)) { 557 if (imported_name.ParsedNamesAreEqual(heuristically_parsed_name)) {
550 should_append_imported_name = false; 558 should_append_imported_name = false;
551 break; 559 break;
552 } 560 }
553 561
554 if (current_name.EqualsIgnoreCase(heuristically_parsed_name)) { 562 if (current_name.ParsedNamesAreEqual(heuristically_parsed_name)) {
555 results[index] = imported_name; 563 results[index] = imported_name;
556 should_append_imported_name = false; 564 should_append_imported_name = false;
557 break; 565 break;
558 } 566 }
559 } 567 }
560 } 568 }
561 569
562 // Append unique names to the list. 570 // Append unique names to the list.
563 if (should_append_imported_name) 571 if (should_append_imported_name)
564 results.push_back(imported_name); 572 results.push_back(imported_name);
(...skipping 17 matching lines...) Expand all
582 CollapseCompoundFieldTypes(&field_types); 590 CollapseCompoundFieldTypes(&field_types);
583 591
584 // TODO(isherman): Revisit this decision in the context of i18n and storing 592 // TODO(isherman): Revisit this decision in the context of i18n and storing
585 // full addresses rather than storing 1-to-2 lines of an address. 593 // full addresses rather than storing 1-to-2 lines of an address.
586 // For addresses, do the opposite: transfer individual address lines, rather 594 // For addresses, do the opposite: transfer individual address lines, rather
587 // than full addresses. 595 // than full addresses.
588 field_types.erase(ADDRESS_HOME_STREET_ADDRESS); 596 field_types.erase(ADDRESS_HOME_STREET_ADDRESS);
589 597
590 for (ServerFieldTypeSet::const_iterator iter = field_types.begin(); 598 for (ServerFieldTypeSet::const_iterator iter = field_types.begin();
591 iter != field_types.end(); ++iter) { 599 iter != field_types.end(); ++iter) {
592 if (AutofillProfile::SupportsMultiValue(*iter)) { 600 FieldTypeGroup group = AutofillType(*iter).group();
593 std::vector<base::string16> new_values; 601 // Special case names.
594 profile.GetRawMultiInfo(*iter, &new_values); 602 if (group == NAME) {
595 std::vector<base::string16> existing_values; 603 OverwriteOrAppendNames(profile.name_, app_locale);
596 GetRawMultiInfo(*iter, &existing_values); 604 continue;
605 }
597 606
598 // GetMultiInfo always returns at least one element, even if the profile 607 // Single value field --- overwrite.
599 // has no data stored for this field type. 608 if (!AutofillProfile::SupportsMultiValue(*iter)) {
600 if (existing_values.size() == 1 && existing_values.front().empty())
601 existing_values.clear();
602
603 FieldTypeGroup group = AutofillType(*iter).group();
604 for (std::vector<base::string16>::iterator value_iter =
605 new_values.begin();
606 value_iter != new_values.end(); ++value_iter) {
607 // Don't add duplicates.
608 if (group == PHONE_HOME) {
609 AddPhoneIfUnique(*value_iter, app_locale, &existing_values);
610 } else {
611 std::vector<base::string16>::const_iterator existing_iter =
612 std::find_if(
613 existing_values.begin(), existing_values.end(),
614 std::bind1st(CaseInsensitiveStringEquals(), *value_iter));
615 if (existing_iter == existing_values.end())
616 existing_values.insert(existing_values.end(), *value_iter);
617 }
618 }
619 if (group == NAME)
620 OverwriteOrAppendNames(profile.name_);
621 else
622 SetRawMultiInfo(*iter, existing_values);
623 } else {
624 base::string16 new_value = profile.GetRawInfo(*iter); 609 base::string16 new_value = profile.GetRawInfo(*iter);
625 if (StringToLowerASCII(GetRawInfo(*iter)) != 610 if (StringToLowerASCII(GetRawInfo(*iter)) !=
626 StringToLowerASCII(new_value)) { 611 StringToLowerASCII(new_value)) {
627 SetRawInfo(*iter, new_value); 612 SetRawInfo(*iter, new_value);
628 } 613 }
614 continue;
629 } 615 }
616
617 // Multi value field --- overwrite/append.
618 std::vector<base::string16> new_values;
619 profile.GetRawMultiInfo(*iter, &new_values);
620 std::vector<base::string16> existing_values;
621 GetRawMultiInfo(*iter, &existing_values);
622
623 // GetMultiInfo always returns at least one element, even if the profile
624 // has no data stored for this field type.
625 if (existing_values.size() == 1 && existing_values.front().empty())
626 existing_values.clear();
627
628 for (std::vector<base::string16>::iterator value_iter =
629 new_values.begin();
630 value_iter != new_values.end(); ++value_iter) {
631 // Don't add duplicates. Most types get case insensitive matching.
632 std::vector<base::string16>::const_iterator existing_iter;
633
634 if (group == PHONE_HOME) {
635 // Phones allow "fuzzy" matching, so "1-800-FLOWERS", "18003569377",
636 // "(800)356-9377" and "356-9377" are considered the same.
637 std::string country_code =
638 base::UTF16ToASCII(GetRawInfo(ADDRESS_HOME_COUNTRY));
639 existing_iter =
640 std::find_if(existing_values.begin(), existing_values.end(),
641 FindByPhone(*value_iter, country_code, app_locale));
642 } else {
643 existing_iter =
644 std::find_if(existing_values.begin(), existing_values.end(),
645 CaseInsensitiveStringEquals(*value_iter));
646 }
647
648 if (existing_iter == existing_values.end())
649 existing_values.insert(existing_values.end(), *value_iter);
650 }
651
652 SetRawMultiInfo(*iter, existing_values);
630 } 653 }
631 } 654 }
632 655
633 // static 656 // static
634 bool AutofillProfile::SupportsMultiValue(ServerFieldType type) { 657 bool AutofillProfile::SupportsMultiValue(ServerFieldType type) {
635 FieldTypeGroup group = AutofillType(type).group(); 658 FieldTypeGroup group = AutofillType(type).group();
636 return group == NAME || 659 return group == NAME ||
637 group == NAME_BILLING || 660 group == NAME_BILLING ||
638 group == EMAIL || 661 group == EMAIL ||
639 group == PHONE_HOME || 662 group == PHONE_HOME ||
640 group == PHONE_BILLING; 663 group == PHONE_BILLING;
641 } 664 }
642 665
643 // static 666 // static
644 void AutofillProfile::CreateDifferentiatingLabels( 667 void AutofillProfile::CreateDifferentiatingLabels(
645 const std::vector<AutofillProfile*>& profiles, 668 const std::vector<AutofillProfile*>& profiles,
669 const std::string& app_locale,
646 std::vector<base::string16>* labels) { 670 std::vector<base::string16>* labels) {
647 const size_t kMinimalFieldsShown = 2; 671 const size_t kMinimalFieldsShown = 2;
648 CreateInferredLabels(profiles, NULL, UNKNOWN_TYPE, kMinimalFieldsShown, 672 CreateInferredLabels(profiles, NULL, UNKNOWN_TYPE, kMinimalFieldsShown,
649 labels); 673 app_locale, labels);
650 DCHECK_EQ(profiles.size(), labels->size()); 674 DCHECK_EQ(profiles.size(), labels->size());
651 } 675 }
652 676
653 // static 677 // static
654 void AutofillProfile::CreateInferredLabels( 678 void AutofillProfile::CreateInferredLabels(
655 const std::vector<AutofillProfile*>& profiles, 679 const std::vector<AutofillProfile*>& profiles,
656 const std::vector<ServerFieldType>* suggested_fields, 680 const std::vector<ServerFieldType>* suggested_fields,
657 ServerFieldType excluded_field, 681 ServerFieldType excluded_field,
658 size_t minimal_fields_shown, 682 size_t minimal_fields_shown,
683 const std::string& app_locale,
659 std::vector<base::string16>* labels) { 684 std::vector<base::string16>* labels) {
660 std::vector<ServerFieldType> fields_to_use; 685 std::vector<ServerFieldType> fields_to_use;
661 GetFieldsForDistinguishingProfiles(suggested_fields, excluded_field, 686 GetFieldsForDistinguishingProfiles(suggested_fields, excluded_field,
662 &fields_to_use); 687 &fields_to_use);
663 688
664 // Construct the default label for each profile. Also construct a map that 689 // Construct the default label for each profile. Also construct a map that
665 // associates each label with the profiles that have this label. This map is 690 // associates each label with the profiles that have this label. This map is
666 // then used to detect which labels need further differentiating fields. 691 // then used to detect which labels need further differentiating fields.
667 std::map<base::string16, std::list<size_t> > labels_to_profiles; 692 std::map<base::string16, std::list<size_t> > labels_to_profiles;
668 for (size_t i = 0; i < profiles.size(); ++i) { 693 for (size_t i = 0; i < profiles.size(); ++i) {
669 base::string16 label = 694 base::string16 label =
670 profiles[i]->ConstructInferredLabel(fields_to_use, 695 profiles[i]->ConstructInferredLabel(fields_to_use,
671 minimal_fields_shown); 696 minimal_fields_shown,
697 app_locale);
672 labels_to_profiles[label].push_back(i); 698 labels_to_profiles[label].push_back(i);
673 } 699 }
674 700
675 labels->resize(profiles.size()); 701 labels->resize(profiles.size());
676 for (std::map<base::string16, std::list<size_t> >::const_iterator it = 702 for (std::map<base::string16, std::list<size_t> >::const_iterator it =
677 labels_to_profiles.begin(); 703 labels_to_profiles.begin();
678 it != labels_to_profiles.end(); ++it) { 704 it != labels_to_profiles.end(); ++it) {
679 if (it->second.size() == 1) { 705 if (it->second.size() == 1) {
680 // This label is unique, so use it without any further ado. 706 // This label is unique, so use it without any further ado.
681 base::string16 label = it->first; 707 base::string16 label = it->first;
682 size_t profile_index = it->second.front(); 708 size_t profile_index = it->second.front();
683 (*labels)[profile_index] = label; 709 (*labels)[profile_index] = label;
684 } else { 710 } else {
685 // We have more than one profile with the same label, so add 711 // We have more than one profile with the same label, so add
686 // differentiating fields. 712 // differentiating fields.
687 CreateInferredLabelsHelper(profiles, it->second, fields_to_use, 713 CreateInferredLabelsHelper(profiles, it->second, fields_to_use,
688 minimal_fields_shown, labels); 714 minimal_fields_shown, app_locale, labels);
689 } 715 }
690 } 716 }
691 } 717 }
692 718
693 void AutofillProfile::GetSupportedTypes( 719 void AutofillProfile::GetSupportedTypes(
694 ServerFieldTypeSet* supported_types) const { 720 ServerFieldTypeSet* supported_types) const {
695 FormGroupList info = FormGroups(); 721 FormGroupList info = FormGroups();
696 for (FormGroupList::const_iterator it = info.begin(); it != info.end(); ++it) 722 for (FormGroupList::const_iterator it = info.begin(); it != info.end(); ++it)
697 (*it)->GetSupportedTypes(supported_types); 723 (*it)->GetSupportedTypes(supported_types);
698 } 724 }
(...skipping 13 matching lines...) Expand all
712 case PHONE_HOME: 738 case PHONE_HOME:
713 case PHONE_BILLING: 739 case PHONE_BILLING:
714 CopyItemsToValues(type, phone_number_, app_locale, values); 740 CopyItemsToValues(type, phone_number_, app_locale, values);
715 break; 741 break;
716 default: 742 default:
717 values->resize(1); 743 values->resize(1);
718 (*values)[0] = GetFormGroupInfo(*this, type, app_locale); 744 (*values)[0] = GetFormGroupInfo(*this, type, app_locale);
719 } 745 }
720 } 746 }
721 747
722 void AutofillProfile::AddPhoneIfUnique(
723 const base::string16& phone,
724 const std::string& app_locale,
725 std::vector<base::string16>* existing_phones) {
726 DCHECK(existing_phones);
727 // Phones allow "fuzzy" matching, so "1-800-FLOWERS", "18003569377",
728 // "(800)356-9377" and "356-9377" are considered the same.
729 std::string country_code =
730 base::UTF16ToASCII(GetRawInfo(ADDRESS_HOME_COUNTRY));
731 if (std::find_if(existing_phones->begin(), existing_phones->end(),
732 FindByPhone(phone, country_code, app_locale)) ==
733 existing_phones->end()) {
734 existing_phones->push_back(phone);
735 }
736 }
737
738 base::string16 AutofillProfile::ConstructInferredLabel( 748 base::string16 AutofillProfile::ConstructInferredLabel(
739 const std::vector<ServerFieldType>& included_fields, 749 const std::vector<ServerFieldType>& included_fields,
740 size_t num_fields_to_use) const { 750 size_t num_fields_to_use,
751 const std::string& app_locale) const {
741 const base::string16 separator = 752 const base::string16 separator =
742 l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_SUMMARY_SEPARATOR); 753 l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_SUMMARY_SEPARATOR);
743 754
744 base::string16 label; 755 base::string16 label;
745 size_t num_fields_used = 0; 756 size_t num_fields_used = 0;
746 for (std::vector<ServerFieldType>::const_iterator it = 757 for (std::vector<ServerFieldType>::const_iterator it =
747 included_fields.begin(); 758 included_fields.begin();
748 it != included_fields.end() && num_fields_used < num_fields_to_use; 759 it != included_fields.end() && num_fields_used < num_fields_to_use;
749 ++it) { 760 ++it) {
750 base::string16 field = GetRawInfo(*it); 761 base::string16 field = GetInfo(AutofillType(*it), app_locale);
751 if (field.empty()) 762 if (field.empty())
752 continue; 763 continue;
753 764
754 if (!label.empty()) 765 if (!label.empty())
755 label.append(separator); 766 label.append(separator);
756 767
757 label.append(field); 768 label.append(field);
758 ++num_fields_used; 769 ++num_fields_used;
759 } 770 }
760 771
761 // Flatten the label if need be. 772 // Flatten the label if need be.
762 const base::string16& line_separator = 773 const base::string16& line_separator =
763 l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_LINE_SEPARATOR); 774 l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_LINE_SEPARATOR);
764 base::ReplaceChars(label, base::ASCIIToUTF16("\n"), line_separator, &label); 775 base::ReplaceChars(label, base::ASCIIToUTF16("\n"), line_separator, &label);
765 776
766 return label; 777 return label;
767 } 778 }
768 779
769 // static 780 // static
770 void AutofillProfile::CreateInferredLabelsHelper( 781 void AutofillProfile::CreateInferredLabelsHelper(
771 const std::vector<AutofillProfile*>& profiles, 782 const std::vector<AutofillProfile*>& profiles,
772 const std::list<size_t>& indices, 783 const std::list<size_t>& indices,
773 const std::vector<ServerFieldType>& fields, 784 const std::vector<ServerFieldType>& fields,
774 size_t num_fields_to_include, 785 size_t num_fields_to_include,
786 const std::string& app_locale,
775 std::vector<base::string16>* labels) { 787 std::vector<base::string16>* labels) {
776 // For efficiency, we first construct a map of fields to their text values and 788 // For efficiency, we first construct a map of fields to their text values and
777 // each value's frequency. 789 // each value's frequency.
778 std::map<ServerFieldType, 790 std::map<ServerFieldType,
779 std::map<base::string16, size_t> > field_text_frequencies_by_field; 791 std::map<base::string16, size_t> > field_text_frequencies_by_field;
780 for (std::vector<ServerFieldType>::const_iterator field = fields.begin(); 792 for (std::vector<ServerFieldType>::const_iterator field = fields.begin();
781 field != fields.end(); ++field) { 793 field != fields.end(); ++field) {
782 std::map<base::string16, size_t>& field_text_frequencies = 794 std::map<base::string16, size_t>& field_text_frequencies =
783 field_text_frequencies_by_field[*field]; 795 field_text_frequencies_by_field[*field];
784 796
785 for (std::list<size_t>::const_iterator it = indices.begin(); 797 for (std::list<size_t>::const_iterator it = indices.begin();
786 it != indices.end(); ++it) { 798 it != indices.end(); ++it) {
787 const AutofillProfile* profile = profiles[*it]; 799 const AutofillProfile* profile = profiles[*it];
788 base::string16 field_text = profile->GetRawInfo(*field); 800 base::string16 field_text =
801 profile->GetInfo(AutofillType(*field), app_locale);
789 802
790 // If this label is not already in the map, add it with frequency 0. 803 // If this label is not already in the map, add it with frequency 0.
791 if (!field_text_frequencies.count(field_text)) 804 if (!field_text_frequencies.count(field_text))
792 field_text_frequencies[field_text] = 0; 805 field_text_frequencies[field_text] = 0;
793 806
794 // Now, increment the frequency for this label. 807 // Now, increment the frequency for this label.
795 ++field_text_frequencies[field_text]; 808 ++field_text_frequencies[field_text];
796 } 809 }
797 } 810 }
798 811
799 // Now comes the meat of the algorithm. For each profile, we scan the list of 812 // Now comes the meat of the algorithm. For each profile, we scan the list of
800 // fields to use, looking for two things: 813 // fields to use, looking for two things:
801 // 1. A (non-empty) field that differentiates the profile from all others 814 // 1. A (non-empty) field that differentiates the profile from all others
802 // 2. At least |num_fields_to_include| non-empty fields 815 // 2. At least |num_fields_to_include| non-empty fields
803 // Before we've satisfied condition (2), we include all fields, even ones that 816 // Before we've satisfied condition (2), we include all fields, even ones that
804 // are identical across all the profiles. Once we've satisfied condition (2), 817 // are identical across all the profiles. Once we've satisfied condition (2),
805 // we only include fields that that have at last two distinct values. 818 // we only include fields that that have at last two distinct values.
806 for (std::list<size_t>::const_iterator it = indices.begin(); 819 for (std::list<size_t>::const_iterator it = indices.begin();
807 it != indices.end(); ++it) { 820 it != indices.end(); ++it) {
808 const AutofillProfile* profile = profiles[*it]; 821 const AutofillProfile* profile = profiles[*it];
809 822
810 std::vector<ServerFieldType> label_fields; 823 std::vector<ServerFieldType> label_fields;
811 bool found_differentiating_field = false; 824 bool found_differentiating_field = false;
812 for (std::vector<ServerFieldType>::const_iterator field = fields.begin(); 825 for (std::vector<ServerFieldType>::const_iterator field = fields.begin();
813 field != fields.end(); ++field) { 826 field != fields.end(); ++field) {
814 // Skip over empty fields. 827 // Skip over empty fields.
815 base::string16 field_text = profile->GetRawInfo(*field); 828 base::string16 field_text =
829 profile->GetInfo(AutofillType(*field), app_locale);
816 if (field_text.empty()) 830 if (field_text.empty())
817 continue; 831 continue;
818 832
819 std::map<base::string16, size_t>& field_text_frequencies = 833 std::map<base::string16, size_t>& field_text_frequencies =
820 field_text_frequencies_by_field[*field]; 834 field_text_frequencies_by_field[*field];
821 found_differentiating_field |= 835 found_differentiating_field |=
822 !field_text_frequencies.count(base::string16()) && 836 !field_text_frequencies.count(base::string16()) &&
823 (field_text_frequencies[field_text] == 1); 837 (field_text_frequencies[field_text] == 1);
824 838
825 // Once we've found enough non-empty fields, skip over any remaining 839 // Once we've found enough non-empty fields, skip over any remaining
826 // fields that are identical across all the profiles. 840 // fields that are identical across all the profiles.
827 if (label_fields.size() >= num_fields_to_include && 841 if (label_fields.size() >= num_fields_to_include &&
828 (field_text_frequencies.size() == 1)) 842 (field_text_frequencies.size() == 1))
829 continue; 843 continue;
830 844
831 label_fields.push_back(*field); 845 label_fields.push_back(*field);
832 846
833 // If we've (1) found a differentiating field and (2) found at least 847 // If we've (1) found a differentiating field and (2) found at least
834 // |num_fields_to_include| non-empty fields, we're done! 848 // |num_fields_to_include| non-empty fields, we're done!
835 if (found_differentiating_field && 849 if (found_differentiating_field &&
836 label_fields.size() >= num_fields_to_include) 850 label_fields.size() >= num_fields_to_include)
837 break; 851 break;
838 } 852 }
839 853
840 (*labels)[*it] = 854 (*labels)[*it] = profile->ConstructInferredLabel(
841 profile->ConstructInferredLabel(label_fields, label_fields.size()); 855 label_fields, label_fields.size(), app_locale);
842 } 856 }
843 } 857 }
844 858
845 AutofillProfile::FormGroupList AutofillProfile::FormGroups() const { 859 AutofillProfile::FormGroupList AutofillProfile::FormGroups() const {
846 FormGroupList v(5); 860 FormGroupList v(5);
847 v[0] = &name_[0]; 861 v[0] = &name_[0];
848 v[1] = &email_[0]; 862 v[1] = &email_[0];
849 v[2] = &company_; 863 v[2] = &company_;
850 v[3] = &phone_number_[0]; 864 v[3] = &phone_number_[0];
851 v[4] = &address_; 865 v[4] = &address_;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
920 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_SORTING_CODE)) 934 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_SORTING_CODE))
921 << " " 935 << " "
922 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_COUNTRY)) 936 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_COUNTRY))
923 << " " 937 << " "
924 << profile.language_code() 938 << profile.language_code()
925 << " " 939 << " "
926 << UTF16ToUTF8(MultiString(profile, PHONE_HOME_WHOLE_NUMBER)); 940 << UTF16ToUTF8(MultiString(profile, PHONE_HOME_WHOLE_NUMBER));
927 } 941 }
928 942
929 } // namespace autofill 943 } // namespace autofill
OLDNEW
« no previous file with comments | « components/autofill/core/browser/autofill_profile.h ('k') | components/autofill/core/browser/autofill_profile_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698