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/sha1.h"
19 #include "base/strings/string_util.h"
20 #include "base/strings/utf_string_conversion_utils.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "components/autofill/core/browser/address.h"
23 #include "components/autofill/core/browser/address_i18n.h"
24 #include "components/autofill/core/browser/autofill_country.h"
25 #include "components/autofill/core/browser/autofill_field.h"
26 #include "components/autofill/core/browser/autofill_type.h"
27 #include "components/autofill/core/browser/contact_info.h"
28 #include "components/autofill/core/browser/phone_number.h"
29 #include "components/autofill/core/browser/phone_number_i18n.h"
30 #include "components/autofill/core/browser/validation.h"
31 #include "components/autofill/core/common/autofill_l10n_util.h"
32 #include "components/autofill/core/common/form_field_data.h"
33 #include "grit/components_strings.h"
34 #include "third_party/icu/source/common/unicode/uchar.h"
35 #include "third_party/libaddressinput/chromium/addressinput_util.h"
36 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
37 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_formatter.h"
38 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_metadata.h"
39 #include "ui/base/l10n/l10n_util.h"
41 using base::ASCIIToUTF16
;
42 using base::UTF16ToUTF8
;
43 using i18n::addressinput::AddressData
;
44 using i18n::addressinput::AddressField
;
49 // Like |AutofillType::GetStorableType()|, but also returns |NAME_FULL| for
50 // first, middle, and last name field types, and groups phone number types
52 ServerFieldType
GetStorableTypeCollapsingGroups(ServerFieldType type
) {
53 ServerFieldType storable_type
= AutofillType(type
).GetStorableType();
54 if (AutofillType(storable_type
).group() == NAME
)
57 if (AutofillType(storable_type
).group() == PHONE_HOME
)
58 return PHONE_HOME_WHOLE_NUMBER
;
63 // Returns a value that represents specificity/privacy of the given type. This
64 // is used for prioritizing which data types are shown in inferred labels. For
65 // example, if the profile is going to fill ADDRESS_HOME_ZIP, it should
66 // prioritize showing that over ADDRESS_HOME_STATE in the suggestion sublabel.
67 int SpecificityForType(ServerFieldType type
) {
69 case ADDRESS_HOME_LINE1
:
72 case ADDRESS_HOME_LINE2
:
78 case PHONE_HOME_WHOLE_NUMBER
:
84 case ADDRESS_HOME_ZIP
:
87 case ADDRESS_HOME_SORTING_CODE
:
93 case ADDRESS_HOME_CITY
:
96 case ADDRESS_HOME_STATE
:
99 case ADDRESS_HOME_COUNTRY
:
106 // The priority of other types is arbitrary, but deterministic.
110 bool CompareSpecificity(ServerFieldType type1
, ServerFieldType type2
) {
111 return SpecificityForType(type1
) < SpecificityForType(type2
);
114 // Fills |distinguishing_fields| with a list of fields to use when creating
115 // labels that can help to distinguish between two profiles. Draws fields from
116 // |suggested_fields| if it is non-NULL; otherwise returns a default list.
117 // If |suggested_fields| is non-NULL, does not include |excluded_field| in the
118 // list. Otherwise, |excluded_field| is ignored, and should be set to
119 // |UNKNOWN_TYPE| by convention. The resulting list of fields is sorted in
120 // decreasing order of importance.
121 void GetFieldsForDistinguishingProfiles(
122 const std::vector
<ServerFieldType
>* suggested_fields
,
123 ServerFieldType excluded_field
,
124 std::vector
<ServerFieldType
>* distinguishing_fields
) {
125 static const ServerFieldType kDefaultDistinguishingFields
[] = {
129 ADDRESS_HOME_DEPENDENT_LOCALITY
,
133 ADDRESS_HOME_SORTING_CODE
,
134 ADDRESS_HOME_COUNTRY
,
136 PHONE_HOME_WHOLE_NUMBER
,
140 std::vector
<ServerFieldType
> default_fields
;
141 if (!suggested_fields
) {
142 default_fields
.assign(
143 kDefaultDistinguishingFields
,
144 kDefaultDistinguishingFields
+ arraysize(kDefaultDistinguishingFields
));
145 if (excluded_field
== UNKNOWN_TYPE
) {
146 distinguishing_fields
->swap(default_fields
);
149 suggested_fields
= &default_fields
;
152 // Keep track of which fields we've seen so that we avoid duplicate entries.
153 // Always ignore fields of unknown type and the excluded field.
154 std::set
<ServerFieldType
> seen_fields
;
155 seen_fields
.insert(UNKNOWN_TYPE
);
156 seen_fields
.insert(GetStorableTypeCollapsingGroups(excluded_field
));
158 distinguishing_fields
->clear();
159 for (std::vector
<ServerFieldType
>::const_iterator it
=
160 suggested_fields
->begin();
161 it
!= suggested_fields
->end(); ++it
) {
162 ServerFieldType suggested_type
= GetStorableTypeCollapsingGroups(*it
);
163 if (seen_fields
.insert(suggested_type
).second
)
164 distinguishing_fields
->push_back(suggested_type
);
167 std::sort(distinguishing_fields
->begin(), distinguishing_fields
->end(),
170 // Special case: If the excluded field is a partial name (e.g. first name) and
171 // the suggested fields include other name fields, include |NAME_FULL| in the
172 // list of distinguishing fields as a last-ditch fallback. This allows us to
173 // distinguish between profiles that are identical except for the name.
174 ServerFieldType effective_excluded_type
=
175 GetStorableTypeCollapsingGroups(excluded_field
);
176 if (excluded_field
!= effective_excluded_type
) {
177 for (std::vector
<ServerFieldType
>::const_iterator it
=
178 suggested_fields
->begin();
179 it
!= suggested_fields
->end(); ++it
) {
180 if (*it
!= excluded_field
&&
181 GetStorableTypeCollapsingGroups(*it
) == effective_excluded_type
) {
182 distinguishing_fields
->push_back(effective_excluded_type
);
189 // A helper function for string streaming. Concatenates multi-valued entries
190 // stored for a given |type| into a single string. This string is returned.
191 const base::string16
MultiString(const AutofillProfile
& p
,
192 ServerFieldType type
) {
193 std::vector
<base::string16
> values
;
194 p
.GetRawMultiInfo(type
, &values
);
195 base::string16 accumulate
;
196 for (size_t i
= 0; i
< values
.size(); ++i
) {
198 accumulate
+= ASCIIToUTF16(" ");
199 accumulate
+= values
[i
];
204 base::string16
GetFormGroupInfo(const FormGroup
& form_group
,
205 const AutofillType
& type
,
206 const std::string
& app_locale
) {
207 return app_locale
.empty() ?
208 form_group
.GetRawInfo(type
.GetStorableType()) :
209 form_group
.GetInfo(type
, app_locale
);
213 void CopyRawValuesToItems(ServerFieldType type
,
214 const std::vector
<base::string16
>& values
,
216 std::vector
<T
>* form_group_items
) {
217 form_group_items
->resize(values
.size(), prototype
);
218 for (size_t i
= 0; i
< form_group_items
->size(); ++i
) {
219 (*form_group_items
)[i
].SetRawInfo(type
, values
[i
]);
221 // Must have at least one (possibly empty) element.
222 form_group_items
->resize(std::max
<size_t>(1UL, values
.size()), prototype
);
226 void CopyValuesToItems(AutofillType type
,
227 const std::vector
<base::string16
>& values
,
229 const std::string
& app_locale
,
230 std::vector
<T
>* form_group_items
) {
231 form_group_items
->resize(values
.size(), prototype
);
232 for (size_t i
= 0; i
< form_group_items
->size(); ++i
) {
233 (*form_group_items
)[i
].SetInfo(type
, values
[i
], app_locale
);
235 // Must have at least one (possibly empty) element.
236 form_group_items
->resize(std::max
<size_t>(1UL, values
.size()), prototype
);
240 void CopyItemsToValues(const AutofillType
& type
,
241 const std::vector
<T
>& form_group_items
,
242 const std::string
& app_locale
,
243 std::vector
<base::string16
>* values
) {
244 values
->resize(form_group_items
.size());
245 for (size_t i
= 0; i
< values
->size(); ++i
) {
246 (*values
)[i
] = GetFormGroupInfo(form_group_items
[i
], type
, app_locale
);
250 // Collapse compound field types to their "full" type. I.e. First name
251 // collapses to full name, area code collapses to full phone, etc.
252 void CollapseCompoundFieldTypes(ServerFieldTypeSet
* type_set
) {
253 ServerFieldTypeSet collapsed_set
;
254 for (ServerFieldTypeSet::iterator it
= type_set
->begin();
255 it
!= type_set
->end(); ++it
) {
260 case NAME_MIDDLE_INITIAL
:
263 collapsed_set
.insert(NAME_FULL
);
266 case PHONE_HOME_NUMBER
:
267 case PHONE_HOME_CITY_CODE
:
268 case PHONE_HOME_COUNTRY_CODE
:
269 case PHONE_HOME_CITY_AND_NUMBER
:
270 case PHONE_HOME_WHOLE_NUMBER
:
271 collapsed_set
.insert(PHONE_HOME_WHOLE_NUMBER
);
275 collapsed_set
.insert(*it
);
278 std::swap(*type_set
, collapsed_set
);
283 FindByPhone(const base::string16
& phone
,
284 const std::string
& country_code
,
285 const std::string
& app_locale
)
287 country_code_(country_code
),
288 app_locale_(app_locale
) {}
290 bool operator()(const base::string16
& phone
) {
291 return i18n::PhoneNumbersMatch(phone
, phone_
, country_code_
, app_locale_
);
295 base::string16 phone_
;
296 std::string country_code_
;
297 std::string app_locale_
;
302 AutofillProfile::AutofillProfile(const std::string
& guid
,
303 const std::string
& origin
)
304 : AutofillDataModel(guid
, origin
),
305 record_type_(LOCAL_PROFILE
),
308 phone_number_(1, PhoneNumber(this)) {
311 AutofillProfile::AutofillProfile(RecordType type
, const std::string
& server_id
)
312 : AutofillDataModel(base::GenerateGUID(), std::string()),
316 phone_number_(1, PhoneNumber(this)),
317 server_id_(server_id
) {
318 DCHECK(type
== SERVER_PROFILE
);
321 AutofillProfile::AutofillProfile()
322 : AutofillDataModel(base::GenerateGUID(), std::string()),
323 record_type_(LOCAL_PROFILE
),
326 phone_number_(1, PhoneNumber(this)) {
329 AutofillProfile::AutofillProfile(const AutofillProfile
& profile
)
330 : AutofillDataModel(std::string(), std::string()) {
334 AutofillProfile::~AutofillProfile() {
337 AutofillProfile
& AutofillProfile::operator=(const AutofillProfile
& profile
) {
338 set_use_count(profile
.use_count());
339 set_use_date(profile
.use_date());
340 set_modification_date(profile
.modification_date());
342 if (this == &profile
)
345 set_guid(profile
.guid());
346 set_origin(profile
.origin());
348 record_type_
= profile
.record_type_
;
350 name_
= profile
.name_
;
351 email_
= profile
.email_
;
352 company_
= profile
.company_
;
353 phone_number_
= profile
.phone_number_
;
355 for (size_t i
= 0; i
< phone_number_
.size(); ++i
)
356 phone_number_
[i
].set_profile(this);
358 address_
= profile
.address_
;
359 set_language_code(profile
.language_code());
361 server_id_
= profile
.server_id();
366 void AutofillProfile::GetMatchingTypes(
367 const base::string16
& text
,
368 const std::string
& app_locale
,
369 ServerFieldTypeSet
* matching_types
) const {
370 FormGroupList info
= FormGroups();
371 for (FormGroupList::const_iterator it
= info
.begin(); it
!= info
.end(); ++it
)
372 (*it
)->GetMatchingTypes(text
, app_locale
, matching_types
);
375 base::string16
AutofillProfile::GetRawInfo(ServerFieldType type
) const {
376 const FormGroup
* form_group
= FormGroupForType(AutofillType(type
));
378 return base::string16();
380 return form_group
->GetRawInfo(type
);
383 void AutofillProfile::SetRawInfo(ServerFieldType type
,
384 const base::string16
& value
) {
385 FormGroup
* form_group
= MutableFormGroupForType(AutofillType(type
));
387 form_group
->SetRawInfo(type
, value
);
390 base::string16
AutofillProfile::GetInfo(const AutofillType
& type
,
391 const std::string
& app_locale
) const {
392 if (type
.html_type() == HTML_TYPE_FULL_ADDRESS
) {
393 scoped_ptr
<AddressData
> address_data
=
394 i18n::CreateAddressDataFromAutofillProfile(*this, app_locale
);
395 if (!addressinput::HasAllRequiredFields(*address_data
))
396 return base::string16();
398 std::vector
<std::string
> lines
;
399 ::i18n::addressinput::GetFormattedNationalAddress(*address_data
, &lines
);
400 return base::UTF8ToUTF16(JoinString(lines
, '\n'));
403 const FormGroup
* form_group
= FormGroupForType(type
);
405 return base::string16();
407 return form_group
->GetInfo(type
, app_locale
);
410 bool AutofillProfile::SetInfo(const AutofillType
& type
,
411 const base::string16
& value
,
412 const std::string
& app_locale
) {
413 FormGroup
* form_group
= MutableFormGroupForType(type
);
417 base::string16 trimmed_value
;
418 base::TrimWhitespace(value
, base::TRIM_ALL
, &trimmed_value
);
419 return form_group
->SetInfo(type
, trimmed_value
, app_locale
);
422 void AutofillProfile::SetRawMultiInfo(
423 ServerFieldType type
,
424 const std::vector
<base::string16
>& values
) {
425 switch (AutofillType(type
).group()) {
428 CopyRawValuesToItems(type
, values
, NameInfo(), &name_
);
432 CopyRawValuesToItems(type
, values
, EmailInfo(), &email_
);
437 CopyRawValuesToItems(type
, values
, PhoneNumber(this), &phone_number_
);
441 if (values
.size() == 1U) {
442 SetRawInfo(type
, values
[0]);
443 } else if (values
.empty()) {
444 SetRawInfo(type
, base::string16());
446 // Shouldn't attempt to set multiple values on single-valued field.
453 void AutofillProfile::GetRawMultiInfo(
454 ServerFieldType type
,
455 std::vector
<base::string16
>* values
) const {
456 GetMultiInfoImpl(AutofillType(type
), std::string(), values
);
459 void AutofillProfile::GetMultiInfo(const AutofillType
& type
,
460 const std::string
& app_locale
,
461 std::vector
<base::string16
>* values
) const {
462 GetMultiInfoImpl(type
, app_locale
, values
);
465 bool AutofillProfile::IsEmpty(const std::string
& app_locale
) const {
466 ServerFieldTypeSet types
;
467 GetNonEmptyTypes(app_locale
, &types
);
468 return types
.empty();
471 bool AutofillProfile::IsPresentButInvalid(ServerFieldType type
) const {
472 std::string country
= UTF16ToUTF8(GetRawInfo(ADDRESS_HOME_COUNTRY
));
473 base::string16 data
= GetRawInfo(type
);
478 case ADDRESS_HOME_STATE
:
479 return country
== "US" && !autofill::IsValidState(data
);
481 case ADDRESS_HOME_ZIP
:
482 return country
== "US" && !autofill::IsValidZip(data
);
484 case PHONE_HOME_WHOLE_NUMBER
:
485 return !i18n::PhoneObject(data
, country
).IsValidNumber();
488 return !autofill::IsValidEmailAddress(data
);
496 int AutofillProfile::Compare(const AutofillProfile
& profile
) const {
497 const ServerFieldType single_value_types
[] = {
499 ADDRESS_HOME_STREET_ADDRESS
,
500 ADDRESS_HOME_DEPENDENT_LOCALITY
,
504 ADDRESS_HOME_SORTING_CODE
,
505 ADDRESS_HOME_COUNTRY
,
508 for (size_t i
= 0; i
< arraysize(single_value_types
); ++i
) {
509 int comparison
= GetRawInfo(single_value_types
[i
]).compare(
510 profile
.GetRawInfo(single_value_types
[i
]));
515 const ServerFieldType multi_value_types
[] = { NAME_FULL
,
520 PHONE_HOME_WHOLE_NUMBER
};
522 for (size_t i
= 0; i
< arraysize(multi_value_types
); ++i
) {
523 std::vector
<base::string16
> values_a
;
524 std::vector
<base::string16
> values_b
;
525 GetRawMultiInfo(multi_value_types
[i
], &values_a
);
526 profile
.GetRawMultiInfo(multi_value_types
[i
], &values_b
);
527 if (values_a
.size() < values_b
.size())
529 if (values_a
.size() > values_b
.size())
531 for (size_t j
= 0; j
< values_a
.size(); ++j
) {
532 int comparison
= values_a
[j
].compare(values_b
[j
]);
541 bool AutofillProfile::EqualsSansOrigin(const AutofillProfile
& profile
) const {
542 return guid() == profile
.guid() &&
543 language_code() == profile
.language_code() &&
544 Compare(profile
) == 0;
547 bool AutofillProfile::EqualsForSyncPurposes(const AutofillProfile
& profile
)
549 return use_count() == profile
.use_count() &&
550 use_date() == profile
.use_date() &&
551 EqualsSansGuid(profile
);
554 bool AutofillProfile::operator==(const AutofillProfile
& profile
) const {
555 return guid() == profile
.guid() && EqualsSansGuid(profile
);
558 bool AutofillProfile::operator!=(const AutofillProfile
& profile
) const {
559 return !operator==(profile
);
562 const base::string16
AutofillProfile::PrimaryValue() const {
563 return GetRawInfo(ADDRESS_HOME_LINE1
) + GetRawInfo(ADDRESS_HOME_CITY
);
566 bool AutofillProfile::IsSubsetOf(const AutofillProfile
& profile
,
567 const std::string
& app_locale
) const {
568 ServerFieldTypeSet types
;
569 GetSupportedTypes(&types
);
570 return IsSubsetOfForFieldSet(profile
, app_locale
, types
);
573 bool AutofillProfile::IsSubsetOfForFieldSet(
574 const AutofillProfile
& profile
,
575 const std::string
& app_locale
,
576 const ServerFieldTypeSet
& types
) const {
577 scoped_ptr
<l10n::CaseInsensitiveCompare
> compare
;
579 for (ServerFieldType type
: types
) {
580 base::string16 value
= GetRawInfo(type
);
584 if (type
== NAME_FULL
|| type
== ADDRESS_HOME_STREET_ADDRESS
) {
585 // Ignore the compound "full name" field type. We are only interested in
586 // comparing the constituent parts. For example, if |this| has a middle
587 // name saved, but |profile| lacks one, |profile| could still be a subset
588 // of |this|. Likewise, ignore the compound "street address" type, as we
589 // are only interested in matching line-by-line.
591 } else if (AutofillType(type
).group() == PHONE_HOME
) {
592 // Phone numbers should be canonicalized prior to being compared.
593 if (type
!= PHONE_HOME_WHOLE_NUMBER
) {
595 } else if (!i18n::PhoneNumbersMatch(
596 value
, profile
.GetRawInfo(type
),
597 base::UTF16ToASCII(GetRawInfo(ADDRESS_HOME_COUNTRY
)),
603 compare
.reset(new l10n::CaseInsensitiveCompare());
604 if (!compare
->StringsEqual(value
, profile
.GetRawInfo(type
)))
612 void AutofillProfile::OverwriteOrAppendNames(
613 const std::vector
<NameInfo
>& names
,
614 const std::string
& app_locale
) {
615 std::vector
<NameInfo
> results(name_
);
616 l10n::CaseInsensitiveCompare compare
;
617 for (std::vector
<NameInfo
>::const_iterator it
= names
.begin();
620 NameInfo imported_name
= *it
;
621 bool should_append_imported_name
= true;
623 for (size_t index
= 0; index
< name_
.size(); ++index
) {
624 NameInfo current_name
= name_
[index
];
625 if (current_name
.ParsedNamesAreEqual(imported_name
)) {
626 if (current_name
.GetRawInfo(NAME_FULL
).empty()) {
627 current_name
.SetRawInfo(NAME_FULL
,
628 imported_name
.GetRawInfo(NAME_FULL
));
631 should_append_imported_name
= false;
635 AutofillType type
= AutofillType(NAME_FULL
);
636 base::string16 full_name
= current_name
.GetInfo(type
, app_locale
);
637 if (compare
.StringsEqual(full_name
,
638 imported_name
.GetInfo(type
, app_locale
))) {
639 // The imported name has the same full name string as one of the
640 // existing names for this profile. Because full names are
641 // _heuristically_ parsed into {first, middle, last} name components,
642 // it's possible that either the existing name or the imported name
643 // was misparsed. Prefer to keep the name whose {first, middle,
644 // last} components do not match those computed by the heuristic
645 // parse, as this more likely represents the correct, user-input parse
647 NameInfo heuristically_parsed_name
;
648 heuristically_parsed_name
.SetInfo(type
, full_name
, app_locale
);
649 if (imported_name
.ParsedNamesAreEqual(heuristically_parsed_name
)) {
650 should_append_imported_name
= false;
654 if (current_name
.ParsedNamesAreEqual(heuristically_parsed_name
)) {
655 results
[index
] = imported_name
;
656 should_append_imported_name
= false;
662 // Append unique names to the list.
663 if (should_append_imported_name
)
664 results
.push_back(imported_name
);
670 void AutofillProfile::OverwriteWithOrAddTo(const AutofillProfile
& profile
,
671 const std::string
& app_locale
) {
672 // Verified profiles should never be overwritten with unverified data.
673 DCHECK(!IsVerified() || profile
.IsVerified());
674 set_origin(profile
.origin());
675 set_language_code(profile
.language_code());
676 set_use_count(profile
.use_count() + use_count());
677 if (profile
.use_date() > use_date())
678 set_use_date(profile
.use_date());
680 ServerFieldTypeSet field_types
;
681 profile
.GetNonEmptyTypes(app_locale
, &field_types
);
683 // Only transfer "full" types (e.g. full name) and not fragments (e.g.
684 // first name, last name).
685 CollapseCompoundFieldTypes(&field_types
);
687 // TODO(isherman): Revisit this decision in the context of i18n and storing
688 // full addresses rather than storing 1-to-2 lines of an address.
689 // For addresses, do the opposite: transfer individual address lines, rather
690 // than full addresses.
691 field_types
.erase(ADDRESS_HOME_STREET_ADDRESS
);
693 l10n::CaseInsensitiveCompare compare
;
695 for (ServerFieldTypeSet::const_iterator iter
= field_types
.begin();
696 iter
!= field_types
.end(); ++iter
) {
697 FieldTypeGroup group
= AutofillType(*iter
).group();
698 // Special case names.
700 OverwriteOrAppendNames(profile
.name_
, app_locale
);
704 // Single value field --- overwrite.
705 if (!AutofillProfile::SupportsMultiValue(*iter
)) {
706 base::string16 new_value
= profile
.GetRawInfo(*iter
);
707 if (!compare
.StringsEqual(GetRawInfo(*iter
), new_value
))
708 SetRawInfo(*iter
, new_value
);
712 // Multi value field --- overwrite/append.
713 std::vector
<base::string16
> new_values
;
714 profile
.GetRawMultiInfo(*iter
, &new_values
);
715 std::vector
<base::string16
> existing_values
;
716 GetRawMultiInfo(*iter
, &existing_values
);
718 // GetMultiInfo always returns at least one element, even if the profile
719 // has no data stored for this field type.
720 if (existing_values
.size() == 1 && existing_values
.front().empty())
721 existing_values
.clear();
723 for (std::vector
<base::string16
>::iterator value_iter
=
725 value_iter
!= new_values
.end(); ++value_iter
) {
726 // Don't add duplicates. Most types get case insensitive matching.
727 std::vector
<base::string16
>::const_iterator existing_iter
;
729 if (group
== PHONE_HOME
) {
730 // Phones allow "fuzzy" matching, so "1-800-FLOWERS", "18003569377",
731 // "(800)356-9377" and "356-9377" are considered the same.
732 std::string country_code
=
733 base::UTF16ToASCII(GetRawInfo(ADDRESS_HOME_COUNTRY
));
735 std::find_if(existing_values
.begin(), existing_values
.end(),
736 FindByPhone(*value_iter
, country_code
, app_locale
));
739 std::find_if(existing_values
.begin(), existing_values
.end(),
740 [&compare
, value_iter
](base::string16
& rhs
) {
741 return compare
.StringsEqual(*value_iter
, rhs
);
745 if (existing_iter
== existing_values
.end())
746 existing_values
.insert(existing_values
.end(), *value_iter
);
749 SetRawMultiInfo(*iter
, existing_values
);
754 bool AutofillProfile::SupportsMultiValue(ServerFieldType type
) {
755 FieldTypeGroup group
= AutofillType(type
).group();
756 return group
== NAME
||
757 group
== NAME_BILLING
||
759 group
== PHONE_HOME
||
760 group
== PHONE_BILLING
;
764 void AutofillProfile::CreateDifferentiatingLabels(
765 const std::vector
<AutofillProfile
*>& profiles
,
766 const std::string
& app_locale
,
767 std::vector
<base::string16
>* labels
) {
768 const size_t kMinimalFieldsShown
= 2;
769 CreateInferredLabels(profiles
, NULL
, UNKNOWN_TYPE
, kMinimalFieldsShown
,
771 DCHECK_EQ(profiles
.size(), labels
->size());
775 void AutofillProfile::CreateInferredLabels(
776 const std::vector
<AutofillProfile
*>& profiles
,
777 const std::vector
<ServerFieldType
>* suggested_fields
,
778 ServerFieldType excluded_field
,
779 size_t minimal_fields_shown
,
780 const std::string
& app_locale
,
781 std::vector
<base::string16
>* labels
) {
782 std::vector
<ServerFieldType
> fields_to_use
;
783 GetFieldsForDistinguishingProfiles(suggested_fields
, excluded_field
,
786 // Construct the default label for each profile. Also construct a map that
787 // associates each label with the profiles that have this label. This map is
788 // then used to detect which labels need further differentiating fields.
789 std::map
<base::string16
, std::list
<size_t> > labels_to_profiles
;
790 for (size_t i
= 0; i
< profiles
.size(); ++i
) {
791 base::string16 label
=
792 profiles
[i
]->ConstructInferredLabel(fields_to_use
,
793 minimal_fields_shown
,
795 labels_to_profiles
[label
].push_back(i
);
798 labels
->resize(profiles
.size());
799 for (std::map
<base::string16
, std::list
<size_t> >::const_iterator it
=
800 labels_to_profiles
.begin();
801 it
!= labels_to_profiles
.end(); ++it
) {
802 if (it
->second
.size() == 1) {
803 // This label is unique, so use it without any further ado.
804 base::string16 label
= it
->first
;
805 size_t profile_index
= it
->second
.front();
806 (*labels
)[profile_index
] = label
;
808 // We have more than one profile with the same label, so add
809 // differentiating fields.
810 CreateInferredLabelsHelper(profiles
, it
->second
, fields_to_use
,
811 minimal_fields_shown
, app_locale
, labels
);
816 void AutofillProfile::GenerateServerProfileIdentifier() {
817 DCHECK_EQ(SERVER_PROFILE
, record_type());
818 base::string16 contents
= MultiString(*this, NAME_FIRST
);
819 contents
.append(MultiString(*this, NAME_MIDDLE
));
820 contents
.append(MultiString(*this, NAME_LAST
));
821 contents
.append(MultiString(*this, EMAIL_ADDRESS
));
822 contents
.append(GetRawInfo(COMPANY_NAME
));
823 contents
.append(GetRawInfo(ADDRESS_HOME_STREET_ADDRESS
));
824 contents
.append(GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY
));
825 contents
.append(GetRawInfo(ADDRESS_HOME_CITY
));
826 contents
.append(GetRawInfo(ADDRESS_HOME_STATE
));
827 contents
.append(GetRawInfo(ADDRESS_HOME_ZIP
));
828 contents
.append(GetRawInfo(ADDRESS_HOME_SORTING_CODE
));
829 contents
.append(GetRawInfo(ADDRESS_HOME_COUNTRY
));
830 contents
.append(MultiString(*this, PHONE_HOME_WHOLE_NUMBER
));
831 std::string contents_utf8
= UTF16ToUTF8(contents
);
832 contents_utf8
.append(language_code());
833 server_id_
= base::SHA1HashString(contents_utf8
);
837 base::string16
AutofillProfile::CanonicalizeProfileString(
838 const base::string16
& str
) {
840 ret
.reserve(str
.size());
842 bool previous_was_whitespace
= false;
844 // This algorithm isn't designed to be perfect, we could get arbitrarily
845 // fancy here trying to canonicalize address lines. Instead, this is designed
846 // to handle common cases for all types of data (addresses and names)
847 // without the need of domain-specific logic.
848 base::i18n::UTF16CharIterator
iter(&str
);
849 while (!iter
.end()) {
850 switch (u_charType(iter
.get())) {
851 case U_DASH_PUNCTUATION
:
852 case U_START_PUNCTUATION
:
853 case U_END_PUNCTUATION
:
854 case U_CONNECTOR_PUNCTUATION
:
855 case U_OTHER_PUNCTUATION
:
856 // Convert punctuation to spaces. This will convert "Mid-Island Plz."
857 // -> "Mid Island Plz" (the trailing space will be trimmed off at the
859 if (!previous_was_whitespace
) {
861 previous_was_whitespace
= true;
865 case U_SPACE_SEPARATOR
:
866 case U_LINE_SEPARATOR
:
867 case U_PARAGRAPH_SEPARATOR
:
868 // Convert sequences of spaces to single spaces.
869 if (!previous_was_whitespace
) {
871 previous_was_whitespace
= true;
875 case U_UPPERCASE_LETTER
:
876 case U_TITLECASE_LETTER
:
877 previous_was_whitespace
= false;
878 base::WriteUnicodeCharacter(u_tolower(iter
.get()), &ret
);
882 previous_was_whitespace
= false;
883 base::WriteUnicodeCharacter(iter
.get(), &ret
);
889 // Trim off trailing whitespace if we left one.
890 if (previous_was_whitespace
)
891 ret
.resize(ret
.size() - 1);
897 bool AutofillProfile::AreProfileStringsSimilar(const base::string16
& a
,
898 const base::string16
& b
) {
899 return CanonicalizeProfileString(a
) == CanonicalizeProfileString(b
);
902 void AutofillProfile::GetSupportedTypes(
903 ServerFieldTypeSet
* supported_types
) const {
904 FormGroupList info
= FormGroups();
905 for (FormGroupList::const_iterator it
= info
.begin(); it
!= info
.end(); ++it
)
906 (*it
)->GetSupportedTypes(supported_types
);
909 void AutofillProfile::GetMultiInfoImpl(
910 const AutofillType
& type
,
911 const std::string
& app_locale
,
912 std::vector
<base::string16
>* values
) const {
913 switch (type
.group()) {
916 CopyItemsToValues(type
, name_
, app_locale
, values
);
919 CopyItemsToValues(type
, email_
, app_locale
, values
);
923 CopyItemsToValues(type
, phone_number_
, app_locale
, values
);
927 (*values
)[0] = GetFormGroupInfo(*this, type
, app_locale
);
931 base::string16
AutofillProfile::ConstructInferredLabel(
932 const std::vector
<ServerFieldType
>& included_fields
,
933 size_t num_fields_to_use
,
934 const std::string
& app_locale
) const {
935 // TODO(estade): use libaddressinput?
936 base::string16 separator
=
937 l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_SUMMARY_SEPARATOR
);
939 AutofillType
region_code_type(HTML_TYPE_COUNTRY_CODE
, HTML_MODE_NONE
);
940 const base::string16
& profile_region_code
=
941 GetInfo(region_code_type
, app_locale
);
942 std::string address_region_code
= UTF16ToUTF8(profile_region_code
);
944 // A copy of |this| pruned down to contain only data for the address fields in
945 // |included_fields|.
946 AutofillProfile
trimmed_profile(guid(), origin());
947 trimmed_profile
.SetInfo(region_code_type
, profile_region_code
, app_locale
);
948 trimmed_profile
.set_language_code(language_code());
950 std::vector
<ServerFieldType
> remaining_fields
;
951 for (std::vector
<ServerFieldType
>::const_iterator it
=
952 included_fields
.begin();
953 it
!= included_fields
.end() && num_fields_to_use
> 0;
955 AddressField address_field
;
956 if (!i18n::FieldForType(*it
, &address_field
) ||
957 !::i18n::addressinput::IsFieldUsed(
958 address_field
, address_region_code
) ||
959 address_field
== ::i18n::addressinput::COUNTRY
) {
960 remaining_fields
.push_back(*it
);
964 AutofillType
autofill_type(*it
);
965 const base::string16
& field_value
= GetInfo(autofill_type
, app_locale
);
966 if (field_value
.empty())
969 trimmed_profile
.SetInfo(autofill_type
, field_value
, app_locale
);
973 scoped_ptr
<AddressData
> address_data
=
974 i18n::CreateAddressDataFromAutofillProfile(trimmed_profile
, app_locale
);
975 std::string address_line
;
976 ::i18n::addressinput::GetFormattedNationalAddressLine(
977 *address_data
, &address_line
);
978 base::string16 label
= base::UTF8ToUTF16(address_line
);
980 for (std::vector
<ServerFieldType
>::const_iterator it
=
981 remaining_fields
.begin();
982 it
!= remaining_fields
.end() && num_fields_to_use
> 0;
984 const base::string16
& field_value
= GetInfo(AutofillType(*it
), app_locale
);
985 if (field_value
.empty())
989 label
.append(separator
);
991 label
.append(field_value
);
995 // If country code is missing, libaddressinput won't be used to format the
996 // address. In this case the suggestion might include a multi-line street
997 // address which needs to be flattened.
998 base::ReplaceChars(label
, base::ASCIIToUTF16("\n"), separator
, &label
);
1004 void AutofillProfile::CreateInferredLabelsHelper(
1005 const std::vector
<AutofillProfile
*>& profiles
,
1006 const std::list
<size_t>& indices
,
1007 const std::vector
<ServerFieldType
>& fields
,
1008 size_t num_fields_to_include
,
1009 const std::string
& app_locale
,
1010 std::vector
<base::string16
>* labels
) {
1011 // For efficiency, we first construct a map of fields to their text values and
1012 // each value's frequency.
1013 std::map
<ServerFieldType
,
1014 std::map
<base::string16
, size_t> > field_text_frequencies_by_field
;
1015 for (std::vector
<ServerFieldType
>::const_iterator field
= fields
.begin();
1016 field
!= fields
.end(); ++field
) {
1017 std::map
<base::string16
, size_t>& field_text_frequencies
=
1018 field_text_frequencies_by_field
[*field
];
1020 for (std::list
<size_t>::const_iterator it
= indices
.begin();
1021 it
!= indices
.end(); ++it
) {
1022 const AutofillProfile
* profile
= profiles
[*it
];
1023 base::string16 field_text
=
1024 profile
->GetInfo(AutofillType(*field
), app_locale
);
1026 // If this label is not already in the map, add it with frequency 0.
1027 if (!field_text_frequencies
.count(field_text
))
1028 field_text_frequencies
[field_text
] = 0;
1030 // Now, increment the frequency for this label.
1031 ++field_text_frequencies
[field_text
];
1035 // Now comes the meat of the algorithm. For each profile, we scan the list of
1036 // fields to use, looking for two things:
1037 // 1. A (non-empty) field that differentiates the profile from all others
1038 // 2. At least |num_fields_to_include| non-empty fields
1039 // Before we've satisfied condition (2), we include all fields, even ones that
1040 // are identical across all the profiles. Once we've satisfied condition (2),
1041 // we only include fields that that have at last two distinct values.
1042 for (std::list
<size_t>::const_iterator it
= indices
.begin();
1043 it
!= indices
.end(); ++it
) {
1044 const AutofillProfile
* profile
= profiles
[*it
];
1046 std::vector
<ServerFieldType
> label_fields
;
1047 bool found_differentiating_field
= false;
1048 for (std::vector
<ServerFieldType
>::const_iterator field
= fields
.begin();
1049 field
!= fields
.end(); ++field
) {
1050 // Skip over empty fields.
1051 base::string16 field_text
=
1052 profile
->GetInfo(AutofillType(*field
), app_locale
);
1053 if (field_text
.empty())
1056 std::map
<base::string16
, size_t>& field_text_frequencies
=
1057 field_text_frequencies_by_field
[*field
];
1058 found_differentiating_field
|=
1059 !field_text_frequencies
.count(base::string16()) &&
1060 (field_text_frequencies
[field_text
] == 1);
1062 // Once we've found enough non-empty fields, skip over any remaining
1063 // fields that are identical across all the profiles.
1064 if (label_fields
.size() >= num_fields_to_include
&&
1065 (field_text_frequencies
.size() == 1))
1068 label_fields
.push_back(*field
);
1070 // If we've (1) found a differentiating field and (2) found at least
1071 // |num_fields_to_include| non-empty fields, we're done!
1072 if (found_differentiating_field
&&
1073 label_fields
.size() >= num_fields_to_include
)
1077 (*labels
)[*it
] = profile
->ConstructInferredLabel(
1078 label_fields
, label_fields
.size(), app_locale
);
1082 AutofillProfile::FormGroupList
AutofillProfile::FormGroups() const {
1087 v
[3] = &phone_number_
[0];
1092 const FormGroup
* AutofillProfile::FormGroupForType(
1093 const AutofillType
& type
) const {
1094 return const_cast<AutofillProfile
*>(this)->MutableFormGroupForType(type
);
1097 FormGroup
* AutofillProfile::MutableFormGroupForType(const AutofillType
& type
) {
1098 switch (type
.group()) {
1111 return &phone_number_
[0];
1114 case ADDRESS_BILLING
:
1119 case PASSWORD_FIELD
:
1120 case USERNAME_FIELD
:
1129 bool AutofillProfile::EqualsSansGuid(const AutofillProfile
& profile
) const {
1130 return origin() == profile
.origin() &&
1131 language_code() == profile
.language_code() &&
1132 Compare(profile
) == 0;
1135 // So we can compare AutofillProfiles with EXPECT_EQ().
1136 std::ostream
& operator<<(std::ostream
& os
, const AutofillProfile
& profile
) {
1142 << UTF16ToUTF8(MultiString(profile
, NAME_FIRST
))
1144 << UTF16ToUTF8(MultiString(profile
, NAME_MIDDLE
))
1146 << UTF16ToUTF8(MultiString(profile
, NAME_LAST
))
1148 << UTF16ToUTF8(MultiString(profile
, EMAIL_ADDRESS
))
1150 << UTF16ToUTF8(profile
.GetRawInfo(COMPANY_NAME
))
1152 << UTF16ToUTF8(profile
.GetRawInfo(ADDRESS_HOME_LINE1
))
1154 << UTF16ToUTF8(profile
.GetRawInfo(ADDRESS_HOME_LINE2
))
1156 << UTF16ToUTF8(profile
.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY
))
1158 << UTF16ToUTF8(profile
.GetRawInfo(ADDRESS_HOME_CITY
))
1160 << UTF16ToUTF8(profile
.GetRawInfo(ADDRESS_HOME_STATE
))
1162 << UTF16ToUTF8(profile
.GetRawInfo(ADDRESS_HOME_ZIP
))
1164 << UTF16ToUTF8(profile
.GetRawInfo(ADDRESS_HOME_SORTING_CODE
))
1166 << UTF16ToUTF8(profile
.GetRawInfo(ADDRESS_HOME_COUNTRY
))
1168 << profile
.language_code()
1170 << UTF16ToUTF8(MultiString(profile
, PHONE_HOME_WHOLE_NUMBER
));
1173 } // namespace autofill