ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / components / autofill / core / browser / autofill_profile.cc
blob9b6504e51ecaec5699474e90de6b52e4b4ea0d90
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"
7 #include <algorithm>
8 #include <functional>
9 #include <map>
10 #include <ostream>
11 #include <set>
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;
44 namespace autofill {
45 namespace {
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)
52 return NAME_FULL;
54 return storable_type;
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[] = {
69 NAME_FULL,
70 ADDRESS_HOME_LINE1,
71 ADDRESS_HOME_LINE2,
72 ADDRESS_HOME_DEPENDENT_LOCALITY,
73 ADDRESS_HOME_CITY,
74 ADDRESS_HOME_STATE,
75 ADDRESS_HOME_ZIP,
76 ADDRESS_HOME_SORTING_CODE,
77 ADDRESS_HOME_COUNTRY,
78 EMAIL_ADDRESS,
79 PHONE_HOME_WHOLE_NUMBER,
80 COMPANY_NAME,
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);
90 return;
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);
122 break;
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) {
136 if (i > 0)
137 accumulate += ASCIIToUTF16(" ");
138 accumulate += values[i];
140 return accumulate;
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);
151 template <class T>
152 void CopyRawValuesToItems(ServerFieldType type,
153 const std::vector<base::string16>& values,
154 const T& prototype,
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);
164 template <class T>
165 void CopyValuesToItems(AutofillType type,
166 const std::vector<base::string16>& values,
167 const T& prototype,
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);
178 template <class T>
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) {
195 switch (*it) {
196 case NAME_FIRST:
197 case NAME_MIDDLE:
198 case NAME_LAST:
199 case NAME_MIDDLE_INITIAL:
200 case NAME_FULL:
201 case NAME_SUFFIX:
202 collapsed_set.insert(NAME_FULL);
203 break;
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);
211 break;
213 default:
214 collapsed_set.insert(*it);
217 std::swap(*type_set, collapsed_set);
220 class FindByPhone {
221 public:
222 FindByPhone(const base::string16& phone,
223 const std::string& country_code,
224 const std::string& app_locale)
225 : phone_(phone),
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_);
233 private:
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 {
241 public:
242 CaseInsensitiveStringEquals(const base::string16& other)
243 : other_(other) {}
245 bool operator()(const base::string16& x) const {
246 return x.size() == other_.size() &&
247 base::StringToLowerASCII(x) == base::StringToLowerASCII(other_);
250 private:
251 const base::string16& other_;
254 } // namespace
256 AutofillProfile::AutofillProfile(const std::string& guid,
257 const std::string& origin)
258 : AutofillDataModel(guid, origin),
259 record_type_(LOCAL_PROFILE),
260 name_(1),
261 email_(1),
262 phone_number_(1, PhoneNumber(this)) {
265 AutofillProfile::AutofillProfile(RecordType type, const std::string& server_id)
266 : AutofillDataModel(base::GenerateGUID(), std::string()),
267 record_type_(type),
268 name_(1),
269 email_(1),
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),
277 name_(1),
278 email_(1),
279 phone_number_(1, PhoneNumber(this)) {
282 AutofillProfile::AutofillProfile(const AutofillProfile& profile)
283 : AutofillDataModel(std::string(), std::string()) {
284 operator=(profile);
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)
296 return *this;
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());
314 return *this;
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));
328 if (!form_group)
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));
337 if (form_group)
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);
355 if (!form_group)
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);
365 if (!form_group)
366 return false;
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,
375 size_t variant,
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()) {
393 case NAME:
394 case NAME_BILLING:
395 CopyRawValuesToItems(type, values, NameInfo(), &name_);
396 break;
398 case EMAIL:
399 CopyRawValuesToItems(type, values, EmailInfo(), &email_);
400 break;
402 case PHONE_HOME:
403 case PHONE_BILLING:
404 CopyRawValuesToItems(type, values, PhoneNumber(this), &phone_number_);
405 break;
407 default:
408 if (values.size() == 1U) {
409 SetRawInfo(type, values[0]);
410 } else if (values.empty()) {
411 SetRawInfo(type, base::string16());
412 } else {
413 // Shouldn't attempt to set multiple values on single-valued field.
414 NOTREACHED();
416 break;
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()) {
430 case NAME:
431 case NAME_BILLING:
432 CopyValuesToItems(type, values, NameInfo(), app_locale, &name_);
433 break;
435 case EMAIL:
436 CopyValuesToItems(type, values, EmailInfo(), app_locale, &email_);
437 break;
439 case PHONE_HOME:
440 case PHONE_BILLING:
441 CopyValuesToItems(
442 type, values, PhoneNumber(this), app_locale, &phone_number_);
443 break;
445 default:
446 if (values.size() == 1U) {
447 SetInfo(type, values[0], app_locale);
448 } else if (values.empty()) {
449 SetInfo(type, base::string16(), app_locale);
450 } else {
451 // Shouldn't attempt to set multiple values on single-valued field.
452 NOTREACHED();
454 break;
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);
473 if (data.empty())
474 return false;
476 switch (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();
486 case EMAIL_ADDRESS:
487 return !autofill::IsValidEmailAddress(data);
489 default:
490 NOTREACHED();
491 return false;
495 int AutofillProfile::Compare(const AutofillProfile& profile) const {
496 const ServerFieldType single_value_types[] = {
497 COMPANY_NAME,
498 ADDRESS_HOME_STREET_ADDRESS,
499 ADDRESS_HOME_DEPENDENT_LOCALITY,
500 ADDRESS_HOME_CITY,
501 ADDRESS_HOME_STATE,
502 ADDRESS_HOME_ZIP,
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]));
510 if (comparison != 0)
511 return comparison;
514 const ServerFieldType multi_value_types[] = { NAME_FULL,
515 NAME_FIRST,
516 NAME_MIDDLE,
517 NAME_LAST,
518 EMAIL_ADDRESS,
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())
527 return -1;
528 if (values_a.size() > values_b.size())
529 return 1;
530 for (size_t j = 0; j < values_a.size(); ++j) {
531 int comparison = values_a[j].compare(values_b[j]);
532 if (comparison != 0)
533 return comparison;
537 return 0;
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)
547 const {
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();
571 ++it) {
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.
578 continue;
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) {
582 continue;
583 } else if (!i18n::PhoneNumbersMatch(
584 GetRawInfo(*it),
585 profile.GetRawInfo(*it),
586 base::UTF16ToASCII(GetRawInfo(ADDRESS_HOME_COUNTRY)),
587 app_locale)) {
588 return false;
590 } else if (base::StringToLowerASCII(GetRawInfo(*it)) !=
591 base::StringToLowerASCII(profile.GetRawInfo(*it))) {
592 return false;
596 return true;
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);
604 if (!from)
605 return;
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)) {
611 name_[i] = old_name;
612 break;
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();
623 it != names.end();
624 ++it) {
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;
637 break;
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
651 // of the name.
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;
656 break;
659 if (current_name.ParsedNamesAreEqual(heuristically_parsed_name)) {
660 results[index] = imported_name;
661 should_append_imported_name = false;
662 break;
667 // Append unique names to the list.
668 if (should_append_imported_name)
669 results.push_back(imported_name);
672 name_.swap(results);
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.
702 if (group == NAME) {
703 OverwriteOrAppendNames(profile.name_, app_locale);
704 continue;
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);
714 continue;
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 =
729 new_values.begin();
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));
739 existing_iter =
740 std::find_if(existing_values.begin(), existing_values.end(),
741 FindByPhone(*value_iter, country_code, app_locale));
742 } else {
743 existing_iter =
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);
756 // static
757 bool AutofillProfile::SupportsMultiValue(ServerFieldType type) {
758 FieldTypeGroup group = AutofillType(type).group();
759 return group == NAME ||
760 group == NAME_BILLING ||
761 group == EMAIL ||
762 group == PHONE_HOME ||
763 group == PHONE_BILLING;
766 // static
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,
773 app_locale, labels);
774 DCHECK_EQ(profiles.size(), labels->size());
777 // static
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,
787 &fields_to_use);
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,
797 app_locale);
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;
810 } else {
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);
819 // static
820 base::string16 AutofillProfile::CanonicalizeProfileString(
821 const base::string16& str) {
822 base::string16 ret;
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
841 // end of the loop).
842 if (!previous_was_whitespace) {
843 ret.push_back(' ');
844 previous_was_whitespace = true;
846 break;
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) {
853 ret.push_back(' ');
854 previous_was_whitespace = true;
856 break;
858 case U_UPPERCASE_LETTER:
859 case U_TITLECASE_LETTER:
860 previous_was_whitespace = false;
861 base::WriteUnicodeCharacter(u_tolower(iter.get()), &ret);
862 break;
864 default:
865 previous_was_whitespace = false;
866 base::WriteUnicodeCharacter(iter.get(), &ret);
867 break;
869 iter.Advance();
872 // Trim off trailing whitespace if we left one.
873 if (previous_was_whitespace)
874 ret.resize(ret.size() - 1);
876 return ret;
879 // static
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()) {
897 case NAME:
898 case NAME_BILLING:
899 CopyItemsToValues(type, name_, app_locale, values);
900 break;
901 case EMAIL:
902 CopyItemsToValues(type, email_, app_locale, values);
903 break;
904 case PHONE_HOME:
905 case PHONE_BILLING:
906 CopyItemsToValues(type, phone_number_, app_locale, values);
907 break;
908 default:
909 values->resize(1);
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;
936 ++it) {
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);
943 continue;
946 AutofillType autofill_type(*it);
947 const base::string16& field_value = GetInfo(autofill_type, app_locale);
948 if (field_value.empty())
949 continue;
951 trimmed_profile.SetInfo(autofill_type, field_value, app_locale);
952 --num_fields_to_use;
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;
965 ++it) {
966 const base::string16& field_value = GetInfo(AutofillType(*it), app_locale);
967 if (field_value.empty())
968 continue;
970 if (!label.empty())
971 label.append(separator);
973 label.append(field_value);
974 --num_fields_to_use;
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);
982 return label;
985 // static
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())
1036 continue;
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))
1048 continue;
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)
1056 break;
1059 (*labels)[*it] = profile->ConstructInferredLabel(
1060 label_fields, label_fields.size(), app_locale);
1064 AutofillProfile::FormGroupList AutofillProfile::FormGroups() const {
1065 FormGroupList v(5);
1066 v[0] = &name_[0];
1067 v[1] = &email_[0];
1068 v[2] = &company_;
1069 v[3] = &phone_number_[0];
1070 v[4] = &address_;
1071 return v;
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()) {
1081 case NAME:
1082 case NAME_BILLING:
1083 return &name_[0];
1085 case EMAIL:
1086 return &email_[0];
1088 case COMPANY:
1089 return &company_;
1091 case PHONE_HOME:
1092 case PHONE_BILLING:
1093 return &phone_number_[0];
1095 case ADDRESS_HOME:
1096 case ADDRESS_BILLING:
1097 return &address_;
1099 case NO_GROUP:
1100 case CREDIT_CARD:
1101 case PASSWORD_FIELD:
1102 case TRANSACTION:
1103 return NULL;
1106 NOTREACHED();
1107 return NULL;
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) {
1118 return os
1119 << profile.guid()
1120 << " "
1121 << profile.origin()
1122 << " "
1123 << UTF16ToUTF8(MultiString(profile, NAME_FIRST))
1124 << " "
1125 << UTF16ToUTF8(MultiString(profile, NAME_MIDDLE))
1126 << " "
1127 << UTF16ToUTF8(MultiString(profile, NAME_LAST))
1128 << " "
1129 << UTF16ToUTF8(MultiString(profile, EMAIL_ADDRESS))
1130 << " "
1131 << UTF16ToUTF8(profile.GetRawInfo(COMPANY_NAME))
1132 << " "
1133 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_LINE1))
1134 << " "
1135 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_LINE2))
1136 << " "
1137 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY))
1138 << " "
1139 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_CITY))
1140 << " "
1141 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_STATE))
1142 << " "
1143 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_ZIP))
1144 << " "
1145 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_SORTING_CODE))
1146 << " "
1147 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_COUNTRY))
1148 << " "
1149 << profile.language_code()
1150 << " "
1151 << UTF16ToUTF8(MultiString(profile, PHONE_HOME_WHOLE_NUMBER));
1154 } // namespace autofill