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
3 // found in the LICENSE file.
5 #include "components/autofill/core/browser/autofill_profile.h"
13 #include "base/basictypes.h"
14 #include "base/guid.h"
15 #include "base/i18n/case_conversion.h"
16 #include "base/i18n/char_iterator.h"
17 #include "base/logging.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/utf_string_conversion_utils.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "components/autofill/core/browser/address.h"
22 #include "components/autofill/core/browser/address_i18n.h"
23 #include "components/autofill/core/browser/autofill_country.h"
24 #include "components/autofill/core/browser/autofill_field.h"
25 #include "components/autofill/core/browser/autofill_type.h"
26 #include "components/autofill/core/browser/contact_info.h"
27 #include "components/autofill/core/browser/phone_number.h"
28 #include "components/autofill/core/browser/phone_number_i18n.h"
29 #include "components/autofill/core/browser/validation.h"
30 #include "components/autofill/core/common/form_field_data.h"
31 #include "grit/components_strings.h"
32 #include "third_party/icu/source/common/unicode/uchar.h"
33 #include "third_party/libaddressinput/chromium/addressinput_util.h"
34 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
35 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_formatter.h"
36 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_metadata.h"
37 #include "ui/base/l10n/l10n_util.h"
39 using base::ASCIIToUTF16
;
40 using base::UTF16ToUTF8
;
41 using i18n::addressinput::AddressData
;
42 using i18n::addressinput::AddressField
;
47 // Like |AutofillType::GetStorableType()|, but also returns |NAME_FULL| for
48 // first, middle, and last name field types.
49 ServerFieldType
GetStorableTypeCollapsingNames(ServerFieldType type
) {
50 ServerFieldType storable_type
= AutofillType(type
).GetStorableType();
51 if (AutofillType(storable_type
).group() == NAME
)
57 // Fills |distinguishing_fields| with a list of fields to use when creating
58 // labels that can help to distinguish between two profiles. Draws fields from
59 // |suggested_fields| if it is non-NULL; otherwise returns a default list.
60 // If |suggested_fields| is non-NULL, does not include |excluded_field| in the
61 // list. Otherwise, |excluded_field| is ignored, and should be set to
62 // |UNKNOWN_TYPE| by convention. The resulting list of fields is sorted in
63 // decreasing order of importance.
64 void GetFieldsForDistinguishingProfiles(
65 const std::vector
<ServerFieldType
>* suggested_fields
,
66 ServerFieldType excluded_field
,
67 std::vector
<ServerFieldType
>* distinguishing_fields
) {
68 static const ServerFieldType kDefaultDistinguishingFields
[] = {
72 ADDRESS_HOME_DEPENDENT_LOCALITY
,
76 ADDRESS_HOME_SORTING_CODE
,
79 PHONE_HOME_WHOLE_NUMBER
,
83 std::vector
<ServerFieldType
> default_fields
;
84 if (!suggested_fields
) {
85 default_fields
.assign(
86 kDefaultDistinguishingFields
,
87 kDefaultDistinguishingFields
+ arraysize(kDefaultDistinguishingFields
));
88 if (excluded_field
== UNKNOWN_TYPE
) {
89 distinguishing_fields
->swap(default_fields
);
92 suggested_fields
= &default_fields
;
95 // Keep track of which fields we've seen so that we avoid duplicate entries.
96 // Always ignore fields of unknown type and the excluded field.
97 std::set
<ServerFieldType
> seen_fields
;
98 seen_fields
.insert(UNKNOWN_TYPE
);
99 seen_fields
.insert(GetStorableTypeCollapsingNames(excluded_field
));
101 distinguishing_fields
->clear();
102 for (std::vector
<ServerFieldType
>::const_iterator it
=
103 suggested_fields
->begin();
104 it
!= suggested_fields
->end(); ++it
) {
105 ServerFieldType suggested_type
= GetStorableTypeCollapsingNames(*it
);
106 if (seen_fields
.insert(suggested_type
).second
)
107 distinguishing_fields
->push_back(suggested_type
);
110 // Special case: If the excluded field is a partial name (e.g. first name) and
111 // the suggested fields include other name fields, include |NAME_FULL| in the
112 // list of distinguishing fields as a last-ditch fallback. This allows us to
113 // distinguish between profiles that are identical except for the name.
114 if (excluded_field
!= NAME_FULL
&&
115 GetStorableTypeCollapsingNames(excluded_field
) == NAME_FULL
) {
116 for (std::vector
<ServerFieldType
>::const_iterator it
=
117 suggested_fields
->begin();
118 it
!= suggested_fields
->end(); ++it
) {
119 if (*it
!= excluded_field
&&
120 GetStorableTypeCollapsingNames(*it
) == NAME_FULL
) {
121 distinguishing_fields
->push_back(NAME_FULL
);
128 // A helper function for string streaming. Concatenates multi-valued entries
129 // stored for a given |type| into a single string. This string is returned.
130 const base::string16
MultiString(const AutofillProfile
& p
,
131 ServerFieldType type
) {
132 std::vector
<base::string16
> values
;
133 p
.GetRawMultiInfo(type
, &values
);
134 base::string16 accumulate
;
135 for (size_t i
= 0; i
< values
.size(); ++i
) {
137 accumulate
+= ASCIIToUTF16(" ");
138 accumulate
+= values
[i
];
143 base::string16
GetFormGroupInfo(const FormGroup
& form_group
,
144 const AutofillType
& type
,
145 const std::string
& app_locale
) {
146 return app_locale
.empty() ?
147 form_group
.GetRawInfo(type
.GetStorableType()) :
148 form_group
.GetInfo(type
, app_locale
);
152 void CopyRawValuesToItems(ServerFieldType type
,
153 const std::vector
<base::string16
>& values
,
155 std::vector
<T
>* form_group_items
) {
156 form_group_items
->resize(values
.size(), prototype
);
157 for (size_t i
= 0; i
< form_group_items
->size(); ++i
) {
158 (*form_group_items
)[i
].SetRawInfo(type
, values
[i
]);
160 // Must have at least one (possibly empty) element.
161 form_group_items
->resize(std::max
<size_t>(1UL, values
.size()), prototype
);
165 void CopyValuesToItems(AutofillType type
,
166 const std::vector
<base::string16
>& values
,
168 const std::string
& app_locale
,
169 std::vector
<T
>* form_group_items
) {
170 form_group_items
->resize(values
.size(), prototype
);
171 for (size_t i
= 0; i
< form_group_items
->size(); ++i
) {
172 (*form_group_items
)[i
].SetInfo(type
, values
[i
], app_locale
);
174 // Must have at least one (possibly empty) element.
175 form_group_items
->resize(std::max
<size_t>(1UL, values
.size()), prototype
);
179 void CopyItemsToValues(const AutofillType
& type
,
180 const std::vector
<T
>& form_group_items
,
181 const std::string
& app_locale
,
182 std::vector
<base::string16
>* values
) {
183 values
->resize(form_group_items
.size());
184 for (size_t i
= 0; i
< values
->size(); ++i
) {
185 (*values
)[i
] = GetFormGroupInfo(form_group_items
[i
], type
, app_locale
);
189 // Collapse compound field types to their "full" type. I.e. First name
190 // collapses to full name, area code collapses to full phone, etc.
191 void CollapseCompoundFieldTypes(ServerFieldTypeSet
* type_set
) {
192 ServerFieldTypeSet collapsed_set
;
193 for (ServerFieldTypeSet::iterator it
= type_set
->begin();
194 it
!= type_set
->end(); ++it
) {
199 case NAME_MIDDLE_INITIAL
:
202 collapsed_set
.insert(NAME_FULL
);
205 case PHONE_HOME_NUMBER
:
206 case PHONE_HOME_CITY_CODE
:
207 case PHONE_HOME_COUNTRY_CODE
:
208 case PHONE_HOME_CITY_AND_NUMBER
:
209 case PHONE_HOME_WHOLE_NUMBER
:
210 collapsed_set
.insert(PHONE_HOME_WHOLE_NUMBER
);
214 collapsed_set
.insert(*it
);
217 std::swap(*type_set
, collapsed_set
);
222 FindByPhone(const base::string16
& phone
,
223 const std::string
& country_code
,
224 const std::string
& app_locale
)
226 country_code_(country_code
),
227 app_locale_(app_locale
) {}
229 bool operator()(const base::string16
& phone
) {
230 return i18n::PhoneNumbersMatch(phone
, phone_
, country_code_
, app_locale_
);
234 base::string16 phone_
;
235 std::string country_code_
;
236 std::string app_locale_
;
239 // Functor used to check for case-insensitive equality of two strings.
240 struct CaseInsensitiveStringEquals
{
242 CaseInsensitiveStringEquals(const base::string16
& other
)
245 bool operator()(const base::string16
& x
) const {
246 return x
.size() == other_
.size() &&
247 base::StringToLowerASCII(x
) == base::StringToLowerASCII(other_
);
251 const base::string16
& other_
;
256 AutofillProfile::AutofillProfile(const std::string
& guid
,
257 const std::string
& origin
)
258 : AutofillDataModel(guid
, origin
),
259 record_type_(LOCAL_PROFILE
),
262 phone_number_(1, PhoneNumber(this)) {
265 AutofillProfile::AutofillProfile(RecordType type
, const std::string
& server_id
)
266 : AutofillDataModel(base::GenerateGUID(), std::string()),
270 phone_number_(1, PhoneNumber(this)) {
271 DCHECK(type
== SERVER_PROFILE
);
274 AutofillProfile::AutofillProfile()
275 : AutofillDataModel(base::GenerateGUID(), std::string()),
276 record_type_(LOCAL_PROFILE
),
279 phone_number_(1, PhoneNumber(this)) {
282 AutofillProfile::AutofillProfile(const AutofillProfile
& profile
)
283 : AutofillDataModel(std::string(), std::string()) {
287 AutofillProfile::~AutofillProfile() {
290 AutofillProfile
& AutofillProfile::operator=(const AutofillProfile
& profile
) {
291 set_use_count(profile
.use_count());
292 set_use_date(profile
.use_date());
293 set_modification_date(profile
.modification_date());
295 if (this == &profile
)
298 set_guid(profile
.guid());
299 set_origin(profile
.origin());
301 record_type_
= profile
.record_type_
;
303 name_
= profile
.name_
;
304 email_
= profile
.email_
;
305 company_
= profile
.company_
;
306 phone_number_
= profile
.phone_number_
;
308 for (size_t i
= 0; i
< phone_number_
.size(); ++i
)
309 phone_number_
[i
].set_profile(this);
311 address_
= profile
.address_
;
312 set_language_code(profile
.language_code());
317 void AutofillProfile::GetMatchingTypes(
318 const base::string16
& text
,
319 const std::string
& app_locale
,
320 ServerFieldTypeSet
* matching_types
) const {
321 FormGroupList info
= FormGroups();
322 for (FormGroupList::const_iterator it
= info
.begin(); it
!= info
.end(); ++it
)
323 (*it
)->GetMatchingTypes(text
, app_locale
, matching_types
);
326 base::string16
AutofillProfile::GetRawInfo(ServerFieldType type
) const {
327 const FormGroup
* form_group
= FormGroupForType(AutofillType(type
));
329 return base::string16();
331 return form_group
->GetRawInfo(type
);
334 void AutofillProfile::SetRawInfo(ServerFieldType type
,
335 const base::string16
& value
) {
336 FormGroup
* form_group
= MutableFormGroupForType(AutofillType(type
));
338 form_group
->SetRawInfo(type
, value
);
341 base::string16
AutofillProfile::GetInfo(const AutofillType
& type
,
342 const std::string
& app_locale
) const {
343 if (type
.html_type() == HTML_TYPE_FULL_ADDRESS
) {
344 scoped_ptr
<AddressData
> address_data
=
345 i18n::CreateAddressDataFromAutofillProfile(*this, app_locale
);
346 if (!addressinput::HasAllRequiredFields(*address_data
))
347 return base::string16();
349 std::vector
<std::string
> lines
;
350 ::i18n::addressinput::GetFormattedNationalAddress(*address_data
, &lines
);
351 return base::UTF8ToUTF16(JoinString(lines
, '\n'));
354 const FormGroup
* form_group
= FormGroupForType(type
);
356 return base::string16();
358 return form_group
->GetInfo(type
, app_locale
);
361 bool AutofillProfile::SetInfo(const AutofillType
& type
,
362 const base::string16
& value
,
363 const std::string
& app_locale
) {
364 FormGroup
* form_group
= MutableFormGroupForType(type
);
368 base::string16 trimmed_value
;
369 base::TrimWhitespace(value
, base::TRIM_ALL
, &trimmed_value
);
370 return form_group
->SetInfo(type
, trimmed_value
, app_locale
);
373 base::string16
AutofillProfile::GetInfoForVariant(
374 const AutofillType
& type
,
376 const std::string
& app_locale
) const {
377 std::vector
<base::string16
> values
;
378 GetMultiInfo(type
, app_locale
, &values
);
380 if (variant
>= values
.size()) {
381 // If the variant is unavailable, bail. This case is reachable, for
382 // example if Sync updates a profile during the filling process.
383 return base::string16();
386 return values
[variant
];
389 void AutofillProfile::SetRawMultiInfo(
390 ServerFieldType type
,
391 const std::vector
<base::string16
>& values
) {
392 switch (AutofillType(type
).group()) {
395 CopyRawValuesToItems(type
, values
, NameInfo(), &name_
);
399 CopyRawValuesToItems(type
, values
, EmailInfo(), &email_
);
404 CopyRawValuesToItems(type
, values
, PhoneNumber(this), &phone_number_
);
408 if (values
.size() == 1U) {
409 SetRawInfo(type
, values
[0]);
410 } else if (values
.empty()) {
411 SetRawInfo(type
, base::string16());
413 // Shouldn't attempt to set multiple values on single-valued field.
420 void AutofillProfile::GetRawMultiInfo(
421 ServerFieldType type
,
422 std::vector
<base::string16
>* values
) const {
423 GetMultiInfoImpl(AutofillType(type
), std::string(), values
);
426 void AutofillProfile::SetMultiInfo(const AutofillType
& type
,
427 const std::vector
<base::string16
>& values
,
428 const std::string
& app_locale
) {
429 switch (AutofillType(type
).group()) {
432 CopyValuesToItems(type
, values
, NameInfo(), app_locale
, &name_
);
436 CopyValuesToItems(type
, values
, EmailInfo(), app_locale
, &email_
);
442 type
, values
, PhoneNumber(this), app_locale
, &phone_number_
);
446 if (values
.size() == 1U) {
447 SetInfo(type
, values
[0], app_locale
);
448 } else if (values
.empty()) {
449 SetInfo(type
, base::string16(), app_locale
);
451 // Shouldn't attempt to set multiple values on single-valued field.
458 void AutofillProfile::GetMultiInfo(const AutofillType
& type
,
459 const std::string
& app_locale
,
460 std::vector
<base::string16
>* values
) const {
461 GetMultiInfoImpl(type
, app_locale
, values
);
464 bool AutofillProfile::IsEmpty(const std::string
& app_locale
) const {
465 ServerFieldTypeSet types
;
466 GetNonEmptyTypes(app_locale
, &types
);
467 return types
.empty();
470 bool AutofillProfile::IsPresentButInvalid(ServerFieldType type
) const {
471 std::string country
= UTF16ToUTF8(GetRawInfo(ADDRESS_HOME_COUNTRY
));
472 base::string16 data
= GetRawInfo(type
);
477 case ADDRESS_HOME_STATE
:
478 return country
== "US" && !autofill::IsValidState(data
);
480 case ADDRESS_HOME_ZIP
:
481 return country
== "US" && !autofill::IsValidZip(data
);
483 case PHONE_HOME_WHOLE_NUMBER
:
484 return !i18n::PhoneObject(data
, country
).IsValidNumber();
487 return !autofill::IsValidEmailAddress(data
);
495 int AutofillProfile::Compare(const AutofillProfile
& profile
) const {
496 const ServerFieldType single_value_types
[] = {
498 ADDRESS_HOME_STREET_ADDRESS
,
499 ADDRESS_HOME_DEPENDENT_LOCALITY
,
503 ADDRESS_HOME_SORTING_CODE
,
504 ADDRESS_HOME_COUNTRY
,
507 for (size_t i
= 0; i
< arraysize(single_value_types
); ++i
) {
508 int comparison
= GetRawInfo(single_value_types
[i
]).compare(
509 profile
.GetRawInfo(single_value_types
[i
]));
514 const ServerFieldType multi_value_types
[] = { NAME_FULL
,
519 PHONE_HOME_WHOLE_NUMBER
};
521 for (size_t i
= 0; i
< arraysize(multi_value_types
); ++i
) {
522 std::vector
<base::string16
> values_a
;
523 std::vector
<base::string16
> values_b
;
524 GetRawMultiInfo(multi_value_types
[i
], &values_a
);
525 profile
.GetRawMultiInfo(multi_value_types
[i
], &values_b
);
526 if (values_a
.size() < values_b
.size())
528 if (values_a
.size() > values_b
.size())
530 for (size_t j
= 0; j
< values_a
.size(); ++j
) {
531 int comparison
= values_a
[j
].compare(values_b
[j
]);
540 bool AutofillProfile::EqualsSansOrigin(const AutofillProfile
& profile
) const {
541 return guid() == profile
.guid() &&
542 language_code() == profile
.language_code() &&
543 Compare(profile
) == 0;
546 bool AutofillProfile::EqualsForSyncPurposes(const AutofillProfile
& profile
)
548 return use_count() == profile
.use_count() &&
549 use_date() == profile
.use_date() &&
550 EqualsSansGuid(profile
);
553 bool AutofillProfile::operator==(const AutofillProfile
& profile
) const {
554 return guid() == profile
.guid() && EqualsSansGuid(profile
);
557 bool AutofillProfile::operator!=(const AutofillProfile
& profile
) const {
558 return !operator==(profile
);
561 const base::string16
AutofillProfile::PrimaryValue() const {
562 return GetRawInfo(ADDRESS_HOME_LINE1
) + GetRawInfo(ADDRESS_HOME_CITY
);
565 bool AutofillProfile::IsSubsetOf(const AutofillProfile
& profile
,
566 const std::string
& app_locale
) const {
567 ServerFieldTypeSet types
;
568 GetNonEmptyTypes(app_locale
, &types
);
570 for (ServerFieldTypeSet::const_iterator it
= types
.begin(); it
!= types
.end();
572 if (*it
== NAME_FULL
|| *it
== ADDRESS_HOME_STREET_ADDRESS
) {
573 // Ignore the compound "full name" field type. We are only interested in
574 // comparing the constituent parts. For example, if |this| has a middle
575 // name saved, but |profile| lacks one, |profile| could still be a subset
576 // of |this|. Likewise, ignore the compound "street address" type, as we
577 // are only interested in matching line-by-line.
579 } else if (AutofillType(*it
).group() == PHONE_HOME
) {
580 // Phone numbers should be canonicalized prior to being compared.
581 if (*it
!= PHONE_HOME_WHOLE_NUMBER
) {
583 } else if (!i18n::PhoneNumbersMatch(
585 profile
.GetRawInfo(*it
),
586 base::UTF16ToASCII(GetRawInfo(ADDRESS_HOME_COUNTRY
)),
590 } else if (base::StringToLowerASCII(GetRawInfo(*it
)) !=
591 base::StringToLowerASCII(profile
.GetRawInfo(*it
))) {
599 void AutofillProfile::CopyAndUpdateNameList(
600 const std::vector
<base::string16
> names
,
601 const AutofillProfile
* from
,
602 const std::string
& locale
) {
603 SetMultiInfo(AutofillType(NAME_FULL
), names
, locale
);
607 for (const auto& old_name
: from
->name_
) {
608 for (size_t i
= 0; i
< name_
.size(); ++i
) {
609 if (old_name
.GetInfo(AutofillType(NAME_FULL
), locale
) ==
610 name_
[i
].GetInfo(AutofillType(NAME_FULL
), locale
)) {
618 void AutofillProfile::OverwriteOrAppendNames(
619 const std::vector
<NameInfo
>& names
,
620 const std::string
& app_locale
) {
621 std::vector
<NameInfo
> results(name_
);
622 for (std::vector
<NameInfo
>::const_iterator it
= names
.begin();
625 NameInfo imported_name
= *it
;
626 bool should_append_imported_name
= true;
628 for (size_t index
= 0; index
< name_
.size(); ++index
) {
629 NameInfo current_name
= name_
[index
];
630 if (current_name
.ParsedNamesAreEqual(imported_name
)) {
631 if (current_name
.GetRawInfo(NAME_FULL
).empty()) {
632 current_name
.SetRawInfo(NAME_FULL
,
633 imported_name
.GetRawInfo(NAME_FULL
));
636 should_append_imported_name
= false;
640 AutofillType type
= AutofillType(NAME_FULL
);
641 base::string16 full_name
= current_name
.GetInfo(type
, app_locale
);
642 if (base::StringToLowerASCII(full_name
) ==
643 base::StringToLowerASCII(imported_name
.GetInfo(type
, app_locale
))) {
644 // The imported name has the same full name string as one of the
645 // existing names for this profile. Because full names are
646 // _heuristically_ parsed into {first, middle, last} name components,
647 // it's possible that either the existing name or the imported name
648 // was misparsed. Prefer to keep the name whose {first, middle,
649 // last} components do not match those computed by the heuristic
650 // parse, as this more likely represents the correct, user-input parse
652 NameInfo heuristically_parsed_name
;
653 heuristically_parsed_name
.SetInfo(type
, full_name
, app_locale
);
654 if (imported_name
.ParsedNamesAreEqual(heuristically_parsed_name
)) {
655 should_append_imported_name
= false;
659 if (current_name
.ParsedNamesAreEqual(heuristically_parsed_name
)) {
660 results
[index
] = imported_name
;
661 should_append_imported_name
= false;
667 // Append unique names to the list.
668 if (should_append_imported_name
)
669 results
.push_back(imported_name
);
675 void AutofillProfile::OverwriteWithOrAddTo(const AutofillProfile
& profile
,
676 const std::string
& app_locale
) {
677 // Verified profiles should never be overwritten with unverified data.
678 DCHECK(!IsVerified() || profile
.IsVerified());
679 set_origin(profile
.origin());
680 set_language_code(profile
.language_code());
681 set_use_count(profile
.use_count() + use_count());
682 if (profile
.use_date() > use_date())
683 set_use_date(profile
.use_date());
685 ServerFieldTypeSet field_types
;
686 profile
.GetNonEmptyTypes(app_locale
, &field_types
);
688 // Only transfer "full" types (e.g. full name) and not fragments (e.g.
689 // first name, last name).
690 CollapseCompoundFieldTypes(&field_types
);
692 // TODO(isherman): Revisit this decision in the context of i18n and storing
693 // full addresses rather than storing 1-to-2 lines of an address.
694 // For addresses, do the opposite: transfer individual address lines, rather
695 // than full addresses.
696 field_types
.erase(ADDRESS_HOME_STREET_ADDRESS
);
698 for (ServerFieldTypeSet::const_iterator iter
= field_types
.begin();
699 iter
!= field_types
.end(); ++iter
) {
700 FieldTypeGroup group
= AutofillType(*iter
).group();
701 // Special case names.
703 OverwriteOrAppendNames(profile
.name_
, app_locale
);
707 // Single value field --- overwrite.
708 if (!AutofillProfile::SupportsMultiValue(*iter
)) {
709 base::string16 new_value
= profile
.GetRawInfo(*iter
);
710 if (base::StringToLowerASCII(GetRawInfo(*iter
)) !=
711 base::StringToLowerASCII(new_value
)) {
712 SetRawInfo(*iter
, new_value
);
717 // Multi value field --- overwrite/append.
718 std::vector
<base::string16
> new_values
;
719 profile
.GetRawMultiInfo(*iter
, &new_values
);
720 std::vector
<base::string16
> existing_values
;
721 GetRawMultiInfo(*iter
, &existing_values
);
723 // GetMultiInfo always returns at least one element, even if the profile
724 // has no data stored for this field type.
725 if (existing_values
.size() == 1 && existing_values
.front().empty())
726 existing_values
.clear();
728 for (std::vector
<base::string16
>::iterator value_iter
=
730 value_iter
!= new_values
.end(); ++value_iter
) {
731 // Don't add duplicates. Most types get case insensitive matching.
732 std::vector
<base::string16
>::const_iterator existing_iter
;
734 if (group
== PHONE_HOME
) {
735 // Phones allow "fuzzy" matching, so "1-800-FLOWERS", "18003569377",
736 // "(800)356-9377" and "356-9377" are considered the same.
737 std::string country_code
=
738 base::UTF16ToASCII(GetRawInfo(ADDRESS_HOME_COUNTRY
));
740 std::find_if(existing_values
.begin(), existing_values
.end(),
741 FindByPhone(*value_iter
, country_code
, app_locale
));
744 std::find_if(existing_values
.begin(), existing_values
.end(),
745 CaseInsensitiveStringEquals(*value_iter
));
748 if (existing_iter
== existing_values
.end())
749 existing_values
.insert(existing_values
.end(), *value_iter
);
752 SetRawMultiInfo(*iter
, existing_values
);
757 bool AutofillProfile::SupportsMultiValue(ServerFieldType type
) {
758 FieldTypeGroup group
= AutofillType(type
).group();
759 return group
== NAME
||
760 group
== NAME_BILLING
||
762 group
== PHONE_HOME
||
763 group
== PHONE_BILLING
;
767 void AutofillProfile::CreateDifferentiatingLabels(
768 const std::vector
<AutofillProfile
*>& profiles
,
769 const std::string
& app_locale
,
770 std::vector
<base::string16
>* labels
) {
771 const size_t kMinimalFieldsShown
= 2;
772 CreateInferredLabels(profiles
, NULL
, UNKNOWN_TYPE
, kMinimalFieldsShown
,
774 DCHECK_EQ(profiles
.size(), labels
->size());
778 void AutofillProfile::CreateInferredLabels(
779 const std::vector
<AutofillProfile
*>& profiles
,
780 const std::vector
<ServerFieldType
>* suggested_fields
,
781 ServerFieldType excluded_field
,
782 size_t minimal_fields_shown
,
783 const std::string
& app_locale
,
784 std::vector
<base::string16
>* labels
) {
785 std::vector
<ServerFieldType
> fields_to_use
;
786 GetFieldsForDistinguishingProfiles(suggested_fields
, excluded_field
,
789 // Construct the default label for each profile. Also construct a map that
790 // associates each label with the profiles that have this label. This map is
791 // then used to detect which labels need further differentiating fields.
792 std::map
<base::string16
, std::list
<size_t> > labels_to_profiles
;
793 for (size_t i
= 0; i
< profiles
.size(); ++i
) {
794 base::string16 label
=
795 profiles
[i
]->ConstructInferredLabel(fields_to_use
,
796 minimal_fields_shown
,
798 labels_to_profiles
[label
].push_back(i
);
801 labels
->resize(profiles
.size());
802 for (std::map
<base::string16
, std::list
<size_t> >::const_iterator it
=
803 labels_to_profiles
.begin();
804 it
!= labels_to_profiles
.end(); ++it
) {
805 if (it
->second
.size() == 1) {
806 // This label is unique, so use it without any further ado.
807 base::string16 label
= it
->first
;
808 size_t profile_index
= it
->second
.front();
809 (*labels
)[profile_index
] = label
;
811 // We have more than one profile with the same label, so add
812 // differentiating fields.
813 CreateInferredLabelsHelper(profiles
, it
->second
, fields_to_use
,
814 minimal_fields_shown
, app_locale
, labels
);
820 base::string16
AutofillProfile::CanonicalizeProfileString(
821 const base::string16
& str
) {
823 ret
.reserve(str
.size());
825 bool previous_was_whitespace
= false;
827 // This algorithm isn't designed to be perfect, we could get arbitrarily
828 // fancy here trying to canonicalize address lines. Instead, this is designed
829 // to handle common cases for all types of data (addresses and names)
830 // without the need of domain-specific logic.
831 base::i18n::UTF16CharIterator
iter(&str
);
832 while (!iter
.end()) {
833 switch (u_charType(iter
.get())) {
834 case U_DASH_PUNCTUATION
:
835 case U_START_PUNCTUATION
:
836 case U_END_PUNCTUATION
:
837 case U_CONNECTOR_PUNCTUATION
:
838 case U_OTHER_PUNCTUATION
:
839 // Convert punctuation to spaces. This will convert "Mid-Island Plz."
840 // -> "Mid Island Plz" (the trailing space will be trimmed off at the
842 if (!previous_was_whitespace
) {
844 previous_was_whitespace
= true;
848 case U_SPACE_SEPARATOR
:
849 case U_LINE_SEPARATOR
:
850 case U_PARAGRAPH_SEPARATOR
:
851 // Convert sequences of spaces to single spaces.
852 if (!previous_was_whitespace
) {
854 previous_was_whitespace
= true;
858 case U_UPPERCASE_LETTER
:
859 case U_TITLECASE_LETTER
:
860 previous_was_whitespace
= false;
861 base::WriteUnicodeCharacter(u_tolower(iter
.get()), &ret
);
865 previous_was_whitespace
= false;
866 base::WriteUnicodeCharacter(iter
.get(), &ret
);
872 // Trim off trailing whitespace if we left one.
873 if (previous_was_whitespace
)
874 ret
.resize(ret
.size() - 1);
880 bool AutofillProfile::AreProfileStringsSimilar(const base::string16
& a
,
881 const base::string16
& b
) {
882 return CanonicalizeProfileString(a
) == CanonicalizeProfileString(b
);
885 void AutofillProfile::GetSupportedTypes(
886 ServerFieldTypeSet
* supported_types
) const {
887 FormGroupList info
= FormGroups();
888 for (FormGroupList::const_iterator it
= info
.begin(); it
!= info
.end(); ++it
)
889 (*it
)->GetSupportedTypes(supported_types
);
892 void AutofillProfile::GetMultiInfoImpl(
893 const AutofillType
& type
,
894 const std::string
& app_locale
,
895 std::vector
<base::string16
>* values
) const {
896 switch (type
.group()) {
899 CopyItemsToValues(type
, name_
, app_locale
, values
);
902 CopyItemsToValues(type
, email_
, app_locale
, values
);
906 CopyItemsToValues(type
, phone_number_
, app_locale
, values
);
910 (*values
)[0] = GetFormGroupInfo(*this, type
, app_locale
);
914 base::string16
AutofillProfile::ConstructInferredLabel(
915 const std::vector
<ServerFieldType
>& included_fields
,
916 size_t num_fields_to_use
,
917 const std::string
& app_locale
) const {
918 base::string16 separator
=
919 l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_SUMMARY_SEPARATOR
);
921 AutofillType
region_code_type(HTML_TYPE_COUNTRY_CODE
, HTML_MODE_NONE
);
922 const base::string16
& profile_region_code
=
923 GetInfo(region_code_type
, app_locale
);
924 std::string address_region_code
= UTF16ToUTF8(profile_region_code
);
926 // A copy of |this| pruned down to contain only data for the address fields in
927 // |included_fields|.
928 AutofillProfile
trimmed_profile(guid(), origin());
929 trimmed_profile
.SetInfo(region_code_type
, profile_region_code
, app_locale
);
930 trimmed_profile
.set_language_code(language_code());
932 std::vector
<ServerFieldType
> remaining_fields
;
933 for (std::vector
<ServerFieldType
>::const_iterator it
=
934 included_fields
.begin();
935 it
!= included_fields
.end() && num_fields_to_use
> 0;
937 AddressField address_field
;
938 if (!i18n::FieldForType(*it
, &address_field
) ||
939 !::i18n::addressinput::IsFieldUsed(
940 address_field
, address_region_code
) ||
941 address_field
== ::i18n::addressinput::COUNTRY
) {
942 remaining_fields
.push_back(*it
);
946 AutofillType
autofill_type(*it
);
947 const base::string16
& field_value
= GetInfo(autofill_type
, app_locale
);
948 if (field_value
.empty())
951 trimmed_profile
.SetInfo(autofill_type
, field_value
, app_locale
);
955 scoped_ptr
<AddressData
> address_data
=
956 i18n::CreateAddressDataFromAutofillProfile(trimmed_profile
, app_locale
);
957 std::string address_line
;
958 ::i18n::addressinput::GetFormattedNationalAddressLine(
959 *address_data
, &address_line
);
960 base::string16 label
= base::UTF8ToUTF16(address_line
);
962 for (std::vector
<ServerFieldType
>::const_iterator it
=
963 remaining_fields
.begin();
964 it
!= remaining_fields
.end() && num_fields_to_use
> 0;
966 const base::string16
& field_value
= GetInfo(AutofillType(*it
), app_locale
);
967 if (field_value
.empty())
971 label
.append(separator
);
973 label
.append(field_value
);
977 // If country code is missing, libaddressinput won't be used to format the
978 // address. In this case the suggestion might include a multi-line street
979 // address which needs to be flattened.
980 base::ReplaceChars(label
, base::ASCIIToUTF16("\n"), separator
, &label
);
986 void AutofillProfile::CreateInferredLabelsHelper(
987 const std::vector
<AutofillProfile
*>& profiles
,
988 const std::list
<size_t>& indices
,
989 const std::vector
<ServerFieldType
>& fields
,
990 size_t num_fields_to_include
,
991 const std::string
& app_locale
,
992 std::vector
<base::string16
>* labels
) {
993 // For efficiency, we first construct a map of fields to their text values and
994 // each value's frequency.
995 std::map
<ServerFieldType
,
996 std::map
<base::string16
, size_t> > field_text_frequencies_by_field
;
997 for (std::vector
<ServerFieldType
>::const_iterator field
= fields
.begin();
998 field
!= fields
.end(); ++field
) {
999 std::map
<base::string16
, size_t>& field_text_frequencies
=
1000 field_text_frequencies_by_field
[*field
];
1002 for (std::list
<size_t>::const_iterator it
= indices
.begin();
1003 it
!= indices
.end(); ++it
) {
1004 const AutofillProfile
* profile
= profiles
[*it
];
1005 base::string16 field_text
=
1006 profile
->GetInfo(AutofillType(*field
), app_locale
);
1008 // If this label is not already in the map, add it with frequency 0.
1009 if (!field_text_frequencies
.count(field_text
))
1010 field_text_frequencies
[field_text
] = 0;
1012 // Now, increment the frequency for this label.
1013 ++field_text_frequencies
[field_text
];
1017 // Now comes the meat of the algorithm. For each profile, we scan the list of
1018 // fields to use, looking for two things:
1019 // 1. A (non-empty) field that differentiates the profile from all others
1020 // 2. At least |num_fields_to_include| non-empty fields
1021 // Before we've satisfied condition (2), we include all fields, even ones that
1022 // are identical across all the profiles. Once we've satisfied condition (2),
1023 // we only include fields that that have at last two distinct values.
1024 for (std::list
<size_t>::const_iterator it
= indices
.begin();
1025 it
!= indices
.end(); ++it
) {
1026 const AutofillProfile
* profile
= profiles
[*it
];
1028 std::vector
<ServerFieldType
> label_fields
;
1029 bool found_differentiating_field
= false;
1030 for (std::vector
<ServerFieldType
>::const_iterator field
= fields
.begin();
1031 field
!= fields
.end(); ++field
) {
1032 // Skip over empty fields.
1033 base::string16 field_text
=
1034 profile
->GetInfo(AutofillType(*field
), app_locale
);
1035 if (field_text
.empty())
1038 std::map
<base::string16
, size_t>& field_text_frequencies
=
1039 field_text_frequencies_by_field
[*field
];
1040 found_differentiating_field
|=
1041 !field_text_frequencies
.count(base::string16()) &&
1042 (field_text_frequencies
[field_text
] == 1);
1044 // Once we've found enough non-empty fields, skip over any remaining
1045 // fields that are identical across all the profiles.
1046 if (label_fields
.size() >= num_fields_to_include
&&
1047 (field_text_frequencies
.size() == 1))
1050 label_fields
.push_back(*field
);
1052 // If we've (1) found a differentiating field and (2) found at least
1053 // |num_fields_to_include| non-empty fields, we're done!
1054 if (found_differentiating_field
&&
1055 label_fields
.size() >= num_fields_to_include
)
1059 (*labels
)[*it
] = profile
->ConstructInferredLabel(
1060 label_fields
, label_fields
.size(), app_locale
);
1064 AutofillProfile::FormGroupList
AutofillProfile::FormGroups() const {
1069 v
[3] = &phone_number_
[0];
1074 const FormGroup
* AutofillProfile::FormGroupForType(
1075 const AutofillType
& type
) const {
1076 return const_cast<AutofillProfile
*>(this)->MutableFormGroupForType(type
);
1079 FormGroup
* AutofillProfile::MutableFormGroupForType(const AutofillType
& type
) {
1080 switch (type
.group()) {
1093 return &phone_number_
[0];
1096 case ADDRESS_BILLING
:
1101 case PASSWORD_FIELD
:
1110 bool AutofillProfile::EqualsSansGuid(const AutofillProfile
& profile
) const {
1111 return origin() == profile
.origin() &&
1112 language_code() == profile
.language_code() &&
1113 Compare(profile
) == 0;
1116 // So we can compare AutofillProfiles with EXPECT_EQ().
1117 std::ostream
& operator<<(std::ostream
& os
, const AutofillProfile
& profile
) {
1123 << UTF16ToUTF8(MultiString(profile
, NAME_FIRST
))
1125 << UTF16ToUTF8(MultiString(profile
, NAME_MIDDLE
))
1127 << UTF16ToUTF8(MultiString(profile
, NAME_LAST
))
1129 << UTF16ToUTF8(MultiString(profile
, EMAIL_ADDRESS
))
1131 << UTF16ToUTF8(profile
.GetRawInfo(COMPANY_NAME
))
1133 << UTF16ToUTF8(profile
.GetRawInfo(ADDRESS_HOME_LINE1
))
1135 << UTF16ToUTF8(profile
.GetRawInfo(ADDRESS_HOME_LINE2
))
1137 << UTF16ToUTF8(profile
.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY
))
1139 << UTF16ToUTF8(profile
.GetRawInfo(ADDRESS_HOME_CITY
))
1141 << UTF16ToUTF8(profile
.GetRawInfo(ADDRESS_HOME_STATE
))
1143 << UTF16ToUTF8(profile
.GetRawInfo(ADDRESS_HOME_ZIP
))
1145 << UTF16ToUTF8(profile
.GetRawInfo(ADDRESS_HOME_SORTING_CODE
))
1147 << UTF16ToUTF8(profile
.GetRawInfo(ADDRESS_HOME_COUNTRY
))
1149 << profile
.language_code()
1151 << UTF16ToUTF8(MultiString(profile
, PHONE_HOME_WHOLE_NUMBER
));
1154 } // namespace autofill