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.
4
5 #include "components/autofill/core/browser/autofill_profile.h"
6
7 #include <algorithm>
8 #include <functional>
9 #include <map>
10 #include <ostream>
11 #include <set>
12
13 #include "base/basictypes.h"
14 #include "base/guid.h"
15 #include "base/logging.h"
16 #include "base/strings/string_util.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "components/autofill/core/browser/address.h"
19 #include "components/autofill/core/browser/address_i18n.h"
20 #include "components/autofill/core/browser/autofill_country.h"
21 #include "components/autofill/core/browser/autofill_field.h"
22 #include "components/autofill/core/browser/autofill_type.h"
23 #include "components/autofill/core/browser/contact_info.h"
24 #include "components/autofill/core/browser/phone_number.h"
25 #include "components/autofill/core/browser/phone_number_i18n.h"
26 #include "components/autofill/core/browser/validation.h"
27 #include "components/autofill/core/common/form_field_data.h"
28 #include "grit/components_strings.h"
29 #include "third_party/libaddressinput/chromium/addressinput_util.h"
30 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
31 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_formatter.h"
32 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_metadata.h"
33 #include "ui/base/l10n/l10n_util.h"
34
35 using base::ASCIIToUTF16;
36 using base::UTF16ToUTF8;
37 using i18n::addressinput::AddressData;
38 using i18n::addressinput::AddressField;
39
40 namespace autofill {
41 namespace {
42
43 // Like |AutofillType::GetStorableType()|, but also returns |NAME_FULL| for
44 // first, middle, and last name field types.
GetStorableTypeCollapsingNames(ServerFieldType type)45 ServerFieldType GetStorableTypeCollapsingNames(ServerFieldType type) {
46 ServerFieldType storable_type = AutofillType(type).GetStorableType();
47 if (AutofillType(storable_type).group() == NAME)
48 return NAME_FULL;
49
50 return storable_type;
51 }
52
53 // Fills |distinguishing_fields| with a list of fields to use when creating
54 // labels that can help to distinguish between two profiles. Draws fields from
55 // |suggested_fields| if it is non-NULL; otherwise returns a default list.
56 // If |suggested_fields| is non-NULL, does not include |excluded_field| in the
57 // list. Otherwise, |excluded_field| is ignored, and should be set to
58 // |UNKNOWN_TYPE| by convention. The resulting list of fields is sorted in
59 // decreasing order of importance.
GetFieldsForDistinguishingProfiles(const std::vector<ServerFieldType> * suggested_fields,ServerFieldType excluded_field,std::vector<ServerFieldType> * distinguishing_fields)60 void GetFieldsForDistinguishingProfiles(
61 const std::vector<ServerFieldType>* suggested_fields,
62 ServerFieldType excluded_field,
63 std::vector<ServerFieldType>* distinguishing_fields) {
64 static const ServerFieldType kDefaultDistinguishingFields[] = {
65 NAME_FULL,
66 ADDRESS_HOME_LINE1,
67 ADDRESS_HOME_LINE2,
68 ADDRESS_HOME_DEPENDENT_LOCALITY,
69 ADDRESS_HOME_CITY,
70 ADDRESS_HOME_STATE,
71 ADDRESS_HOME_ZIP,
72 ADDRESS_HOME_SORTING_CODE,
73 ADDRESS_HOME_COUNTRY,
74 EMAIL_ADDRESS,
75 PHONE_HOME_WHOLE_NUMBER,
76 COMPANY_NAME,
77 };
78
79 std::vector<ServerFieldType> default_fields;
80 if (!suggested_fields) {
81 default_fields.assign(
82 kDefaultDistinguishingFields,
83 kDefaultDistinguishingFields + arraysize(kDefaultDistinguishingFields));
84 if (excluded_field == UNKNOWN_TYPE) {
85 distinguishing_fields->swap(default_fields);
86 return;
87 }
88 suggested_fields = &default_fields;
89 }
90
91 // Keep track of which fields we've seen so that we avoid duplicate entries.
92 // Always ignore fields of unknown type and the excluded field.
93 std::set<ServerFieldType> seen_fields;
94 seen_fields.insert(UNKNOWN_TYPE);
95 seen_fields.insert(GetStorableTypeCollapsingNames(excluded_field));
96
97 distinguishing_fields->clear();
98 for (std::vector<ServerFieldType>::const_iterator it =
99 suggested_fields->begin();
100 it != suggested_fields->end(); ++it) {
101 ServerFieldType suggested_type = GetStorableTypeCollapsingNames(*it);
102 if (seen_fields.insert(suggested_type).second)
103 distinguishing_fields->push_back(suggested_type);
104 }
105
106 // Special case: If the excluded field is a partial name (e.g. first name) and
107 // the suggested fields include other name fields, include |NAME_FULL| in the
108 // list of distinguishing fields as a last-ditch fallback. This allows us to
109 // distinguish between profiles that are identical except for the name.
110 if (excluded_field != NAME_FULL &&
111 GetStorableTypeCollapsingNames(excluded_field) == NAME_FULL) {
112 for (std::vector<ServerFieldType>::const_iterator it =
113 suggested_fields->begin();
114 it != suggested_fields->end(); ++it) {
115 if (*it != excluded_field &&
116 GetStorableTypeCollapsingNames(*it) == NAME_FULL) {
117 distinguishing_fields->push_back(NAME_FULL);
118 break;
119 }
120 }
121 }
122 }
123
124 // A helper function for string streaming. Concatenates multi-valued entries
125 // stored for a given |type| into a single string. This string is returned.
MultiString(const AutofillProfile & p,ServerFieldType type)126 const base::string16 MultiString(const AutofillProfile& p,
127 ServerFieldType type) {
128 std::vector<base::string16> values;
129 p.GetRawMultiInfo(type, &values);
130 base::string16 accumulate;
131 for (size_t i = 0; i < values.size(); ++i) {
132 if (i > 0)
133 accumulate += ASCIIToUTF16(" ");
134 accumulate += values[i];
135 }
136 return accumulate;
137 }
138
GetFormGroupInfo(const FormGroup & form_group,const AutofillType & type,const std::string & app_locale)139 base::string16 GetFormGroupInfo(const FormGroup& form_group,
140 const AutofillType& type,
141 const std::string& app_locale) {
142 return app_locale.empty() ?
143 form_group.GetRawInfo(type.GetStorableType()) :
144 form_group.GetInfo(type, app_locale);
145 }
146
147 template <class T>
CopyRawValuesToItems(ServerFieldType type,const std::vector<base::string16> & values,const T & prototype,std::vector<T> * form_group_items)148 void CopyRawValuesToItems(ServerFieldType type,
149 const std::vector<base::string16>& values,
150 const T& prototype,
151 std::vector<T>* form_group_items) {
152 form_group_items->resize(values.size(), prototype);
153 for (size_t i = 0; i < form_group_items->size(); ++i) {
154 (*form_group_items)[i].SetRawInfo(type, values[i]);
155 }
156 // Must have at least one (possibly empty) element.
157 form_group_items->resize(std::max<size_t>(1UL, values.size()), prototype);
158 }
159
160 template <class T>
CopyValuesToItems(AutofillType type,const std::vector<base::string16> & values,const T & prototype,const std::string & app_locale,std::vector<T> * form_group_items)161 void CopyValuesToItems(AutofillType type,
162 const std::vector<base::string16>& values,
163 const T& prototype,
164 const std::string& app_locale,
165 std::vector<T>* form_group_items) {
166 form_group_items->resize(values.size(), prototype);
167 for (size_t i = 0; i < form_group_items->size(); ++i) {
168 (*form_group_items)[i].SetInfo(type, values[i], app_locale);
169 }
170 // Must have at least one (possibly empty) element.
171 form_group_items->resize(std::max<size_t>(1UL, values.size()), prototype);
172 }
173
174 template <class T>
CopyItemsToValues(const AutofillType & type,const std::vector<T> & form_group_items,const std::string & app_locale,std::vector<base::string16> * values)175 void CopyItemsToValues(const AutofillType& type,
176 const std::vector<T>& form_group_items,
177 const std::string& app_locale,
178 std::vector<base::string16>* values) {
179 values->resize(form_group_items.size());
180 for (size_t i = 0; i < values->size(); ++i) {
181 (*values)[i] = GetFormGroupInfo(form_group_items[i], type, app_locale);
182 }
183 }
184
185 // Collapse compound field types to their "full" type. I.e. First name
186 // collapses to full name, area code collapses to full phone, etc.
CollapseCompoundFieldTypes(ServerFieldTypeSet * type_set)187 void CollapseCompoundFieldTypes(ServerFieldTypeSet* type_set) {
188 ServerFieldTypeSet collapsed_set;
189 for (ServerFieldTypeSet::iterator it = type_set->begin();
190 it != type_set->end(); ++it) {
191 switch (*it) {
192 case NAME_FIRST:
193 case NAME_MIDDLE:
194 case NAME_LAST:
195 case NAME_MIDDLE_INITIAL:
196 case NAME_FULL:
197 case NAME_SUFFIX:
198 collapsed_set.insert(NAME_FULL);
199 break;
200
201 case PHONE_HOME_NUMBER:
202 case PHONE_HOME_CITY_CODE:
203 case PHONE_HOME_COUNTRY_CODE:
204 case PHONE_HOME_CITY_AND_NUMBER:
205 case PHONE_HOME_WHOLE_NUMBER:
206 collapsed_set.insert(PHONE_HOME_WHOLE_NUMBER);
207 break;
208
209 default:
210 collapsed_set.insert(*it);
211 }
212 }
213 std::swap(*type_set, collapsed_set);
214 }
215
216 class FindByPhone {
217 public:
FindByPhone(const base::string16 & phone,const std::string & country_code,const std::string & app_locale)218 FindByPhone(const base::string16& phone,
219 const std::string& country_code,
220 const std::string& app_locale)
221 : phone_(phone),
222 country_code_(country_code),
223 app_locale_(app_locale) {}
224
operator ()(const base::string16 & phone)225 bool operator()(const base::string16& phone) {
226 return i18n::PhoneNumbersMatch(phone, phone_, country_code_, app_locale_);
227 }
228
229 private:
230 base::string16 phone_;
231 std::string country_code_;
232 std::string app_locale_;
233 };
234
235 // Functor used to check for case-insensitive equality of two strings.
236 struct CaseInsensitiveStringEquals {
237 public:
CaseInsensitiveStringEqualsautofill::__anon7519bb150111::CaseInsensitiveStringEquals238 CaseInsensitiveStringEquals(const base::string16& other)
239 : other_(other) {}
240
operator ()autofill::__anon7519bb150111::CaseInsensitiveStringEquals241 bool operator()(const base::string16& x) const {
242 return x.size() == other_.size() &&
243 base::StringToLowerASCII(x) == base::StringToLowerASCII(other_);
244 }
245
246 private:
247 const base::string16& other_;
248 };
249
250 } // namespace
251
AutofillProfile(const std::string & guid,const std::string & origin)252 AutofillProfile::AutofillProfile(const std::string& guid,
253 const std::string& origin)
254 : AutofillDataModel(guid, origin),
255 name_(1),
256 email_(1),
257 phone_number_(1, PhoneNumber(this)) {
258 }
259
AutofillProfile()260 AutofillProfile::AutofillProfile()
261 : AutofillDataModel(base::GenerateGUID(), std::string()),
262 name_(1),
263 email_(1),
264 phone_number_(1, PhoneNumber(this)) {
265 }
266
AutofillProfile(const AutofillProfile & profile)267 AutofillProfile::AutofillProfile(const AutofillProfile& profile)
268 : AutofillDataModel(std::string(), std::string()) {
269 operator=(profile);
270 }
271
~AutofillProfile()272 AutofillProfile::~AutofillProfile() {
273 }
274
operator =(const AutofillProfile & profile)275 AutofillProfile& AutofillProfile::operator=(const AutofillProfile& profile) {
276 if (this == &profile)
277 return *this;
278
279 set_guid(profile.guid());
280 set_origin(profile.origin());
281
282 name_ = profile.name_;
283 email_ = profile.email_;
284 company_ = profile.company_;
285 phone_number_ = profile.phone_number_;
286
287 for (size_t i = 0; i < phone_number_.size(); ++i)
288 phone_number_[i].set_profile(this);
289
290 address_ = profile.address_;
291 set_language_code(profile.language_code());
292
293 return *this;
294 }
295
GetMatchingTypes(const base::string16 & text,const std::string & app_locale,ServerFieldTypeSet * matching_types) const296 void AutofillProfile::GetMatchingTypes(
297 const base::string16& text,
298 const std::string& app_locale,
299 ServerFieldTypeSet* matching_types) const {
300 FormGroupList info = FormGroups();
301 for (FormGroupList::const_iterator it = info.begin(); it != info.end(); ++it)
302 (*it)->GetMatchingTypes(text, app_locale, matching_types);
303 }
304
GetRawInfo(ServerFieldType type) const305 base::string16 AutofillProfile::GetRawInfo(ServerFieldType type) const {
306 const FormGroup* form_group = FormGroupForType(AutofillType(type));
307 if (!form_group)
308 return base::string16();
309
310 return form_group->GetRawInfo(type);
311 }
312
SetRawInfo(ServerFieldType type,const base::string16 & value)313 void AutofillProfile::SetRawInfo(ServerFieldType type,
314 const base::string16& value) {
315 FormGroup* form_group = MutableFormGroupForType(AutofillType(type));
316 if (form_group)
317 form_group->SetRawInfo(type, value);
318 }
319
GetInfo(const AutofillType & type,const std::string & app_locale) const320 base::string16 AutofillProfile::GetInfo(const AutofillType& type,
321 const std::string& app_locale) const {
322 if (type.html_type() == HTML_TYPE_FULL_ADDRESS) {
323 scoped_ptr<AddressData> address_data =
324 i18n::CreateAddressDataFromAutofillProfile(*this, app_locale);
325 if (!addressinput::HasAllRequiredFields(*address_data))
326 return base::string16();
327
328 std::vector<std::string> lines;
329 ::i18n::addressinput::GetFormattedNationalAddress(*address_data, &lines);
330 return base::UTF8ToUTF16(JoinString(lines, '\n'));
331 }
332
333 const FormGroup* form_group = FormGroupForType(type);
334 if (!form_group)
335 return base::string16();
336
337 return form_group->GetInfo(type, app_locale);
338 }
339
SetInfo(const AutofillType & type,const base::string16 & value,const std::string & app_locale)340 bool AutofillProfile::SetInfo(const AutofillType& type,
341 const base::string16& value,
342 const std::string& app_locale) {
343 FormGroup* form_group = MutableFormGroupForType(type);
344 if (!form_group)
345 return false;
346
347 base::string16 trimmed_value;
348 base::TrimWhitespace(value, base::TRIM_ALL, &trimmed_value);
349 return form_group->SetInfo(type, trimmed_value, app_locale);
350 }
351
GetInfoForVariant(const AutofillType & type,size_t variant,const std::string & app_locale) const352 base::string16 AutofillProfile::GetInfoForVariant(
353 const AutofillType& type,
354 size_t variant,
355 const std::string& app_locale) const {
356 std::vector<base::string16> values;
357 GetMultiInfo(type, app_locale, &values);
358
359 if (variant >= values.size()) {
360 // If the variant is unavailable, bail. This case is reachable, for
361 // example if Sync updates a profile during the filling process.
362 return base::string16();
363 }
364
365 return values[variant];
366 }
367
SetRawMultiInfo(ServerFieldType type,const std::vector<base::string16> & values)368 void AutofillProfile::SetRawMultiInfo(
369 ServerFieldType type,
370 const std::vector<base::string16>& values) {
371 switch (AutofillType(type).group()) {
372 case NAME:
373 case NAME_BILLING:
374 CopyRawValuesToItems(type, values, NameInfo(), &name_);
375 break;
376
377 case EMAIL:
378 CopyRawValuesToItems(type, values, EmailInfo(), &email_);
379 break;
380
381 case PHONE_HOME:
382 case PHONE_BILLING:
383 CopyRawValuesToItems(type, values, PhoneNumber(this), &phone_number_);
384 break;
385
386 default:
387 if (values.size() == 1U) {
388 SetRawInfo(type, values[0]);
389 } else if (values.empty()) {
390 SetRawInfo(type, base::string16());
391 } else {
392 // Shouldn't attempt to set multiple values on single-valued field.
393 NOTREACHED();
394 }
395 break;
396 }
397 }
398
GetRawMultiInfo(ServerFieldType type,std::vector<base::string16> * values) const399 void AutofillProfile::GetRawMultiInfo(
400 ServerFieldType type,
401 std::vector<base::string16>* values) const {
402 GetMultiInfoImpl(AutofillType(type), std::string(), values);
403 }
404
SetMultiInfo(const AutofillType & type,const std::vector<base::string16> & values,const std::string & app_locale)405 void AutofillProfile::SetMultiInfo(const AutofillType& type,
406 const std::vector<base::string16>& values,
407 const std::string& app_locale) {
408 switch (AutofillType(type).group()) {
409 case NAME:
410 case NAME_BILLING:
411 CopyValuesToItems(type, values, NameInfo(), app_locale, &name_);
412 break;
413
414 case EMAIL:
415 CopyValuesToItems(type, values, EmailInfo(), app_locale, &email_);
416 break;
417
418 case PHONE_HOME:
419 case PHONE_BILLING:
420 CopyValuesToItems(
421 type, values, PhoneNumber(this), app_locale, &phone_number_);
422 break;
423
424 default:
425 if (values.size() == 1U) {
426 SetInfo(type, values[0], app_locale);
427 } else if (values.empty()) {
428 SetInfo(type, base::string16(), app_locale);
429 } else {
430 // Shouldn't attempt to set multiple values on single-valued field.
431 NOTREACHED();
432 }
433 break;
434 }
435 }
436
GetMultiInfo(const AutofillType & type,const std::string & app_locale,std::vector<base::string16> * values) const437 void AutofillProfile::GetMultiInfo(const AutofillType& type,
438 const std::string& app_locale,
439 std::vector<base::string16>* values) const {
440 GetMultiInfoImpl(type, app_locale, values);
441 }
442
IsEmpty(const std::string & app_locale) const443 bool AutofillProfile::IsEmpty(const std::string& app_locale) const {
444 ServerFieldTypeSet types;
445 GetNonEmptyTypes(app_locale, &types);
446 return types.empty();
447 }
448
IsPresentButInvalid(ServerFieldType type) const449 bool AutofillProfile::IsPresentButInvalid(ServerFieldType type) const {
450 std::string country = UTF16ToUTF8(GetRawInfo(ADDRESS_HOME_COUNTRY));
451 base::string16 data = GetRawInfo(type);
452 if (data.empty())
453 return false;
454
455 switch (type) {
456 case ADDRESS_HOME_STATE:
457 return country == "US" && !autofill::IsValidState(data);
458
459 case ADDRESS_HOME_ZIP:
460 return country == "US" && !autofill::IsValidZip(data);
461
462 case PHONE_HOME_WHOLE_NUMBER:
463 return !i18n::PhoneObject(data, country).IsValidNumber();
464
465 case EMAIL_ADDRESS:
466 return !autofill::IsValidEmailAddress(data);
467
468 default:
469 NOTREACHED();
470 return false;
471 }
472 }
473
Compare(const AutofillProfile & profile) const474 int AutofillProfile::Compare(const AutofillProfile& profile) const {
475 const ServerFieldType single_value_types[] = {
476 COMPANY_NAME,
477 ADDRESS_HOME_STREET_ADDRESS,
478 ADDRESS_HOME_DEPENDENT_LOCALITY,
479 ADDRESS_HOME_CITY,
480 ADDRESS_HOME_STATE,
481 ADDRESS_HOME_ZIP,
482 ADDRESS_HOME_SORTING_CODE,
483 ADDRESS_HOME_COUNTRY,
484 };
485
486 for (size_t i = 0; i < arraysize(single_value_types); ++i) {
487 int comparison = GetRawInfo(single_value_types[i]).compare(
488 profile.GetRawInfo(single_value_types[i]));
489 if (comparison != 0)
490 return comparison;
491 }
492
493 const ServerFieldType multi_value_types[] = { NAME_FULL,
494 NAME_FIRST,
495 NAME_MIDDLE,
496 NAME_LAST,
497 EMAIL_ADDRESS,
498 PHONE_HOME_WHOLE_NUMBER };
499
500 for (size_t i = 0; i < arraysize(multi_value_types); ++i) {
501 std::vector<base::string16> values_a;
502 std::vector<base::string16> values_b;
503 GetRawMultiInfo(multi_value_types[i], &values_a);
504 profile.GetRawMultiInfo(multi_value_types[i], &values_b);
505 if (values_a.size() < values_b.size())
506 return -1;
507 if (values_a.size() > values_b.size())
508 return 1;
509 for (size_t j = 0; j < values_a.size(); ++j) {
510 int comparison = values_a[j].compare(values_b[j]);
511 if (comparison != 0)
512 return comparison;
513 }
514 }
515
516 return 0;
517 }
518
EqualsSansOrigin(const AutofillProfile & profile) const519 bool AutofillProfile::EqualsSansOrigin(const AutofillProfile& profile) const {
520 return guid() == profile.guid() &&
521 language_code() == profile.language_code() &&
522 Compare(profile) == 0;
523 }
524
EqualsSansGuid(const AutofillProfile & profile) const525 bool AutofillProfile::EqualsSansGuid(const AutofillProfile& profile) const {
526 return origin() == profile.origin() &&
527 language_code() == profile.language_code() &&
528 Compare(profile) == 0;
529 }
530
operator ==(const AutofillProfile & profile) const531 bool AutofillProfile::operator==(const AutofillProfile& profile) const {
532 return guid() == profile.guid() && EqualsSansGuid(profile);
533 }
534
operator !=(const AutofillProfile & profile) const535 bool AutofillProfile::operator!=(const AutofillProfile& profile) const {
536 return !operator==(profile);
537 }
538
PrimaryValue() const539 const base::string16 AutofillProfile::PrimaryValue() const {
540 return GetRawInfo(ADDRESS_HOME_LINE1) + GetRawInfo(ADDRESS_HOME_CITY);
541 }
542
IsSubsetOf(const AutofillProfile & profile,const std::string & app_locale) const543 bool AutofillProfile::IsSubsetOf(const AutofillProfile& profile,
544 const std::string& app_locale) const {
545 ServerFieldTypeSet types;
546 GetNonEmptyTypes(app_locale, &types);
547
548 for (ServerFieldTypeSet::const_iterator it = types.begin(); it != types.end();
549 ++it) {
550 if (*it == NAME_FULL || *it == ADDRESS_HOME_STREET_ADDRESS) {
551 // Ignore the compound "full name" field type. We are only interested in
552 // comparing the constituent parts. For example, if |this| has a middle
553 // name saved, but |profile| lacks one, |profile| could still be a subset
554 // of |this|. Likewise, ignore the compound "street address" type, as we
555 // are only interested in matching line-by-line.
556 continue;
557 } else if (AutofillType(*it).group() == PHONE_HOME) {
558 // Phone numbers should be canonicalized prior to being compared.
559 if (*it != PHONE_HOME_WHOLE_NUMBER) {
560 continue;
561 } else if (!i18n::PhoneNumbersMatch(
562 GetRawInfo(*it),
563 profile.GetRawInfo(*it),
564 base::UTF16ToASCII(GetRawInfo(ADDRESS_HOME_COUNTRY)),
565 app_locale)) {
566 return false;
567 }
568 } else if (base::StringToLowerASCII(GetRawInfo(*it)) !=
569 base::StringToLowerASCII(profile.GetRawInfo(*it))) {
570 return false;
571 }
572 }
573
574 return true;
575 }
576
OverwriteOrAppendNames(const std::vector<NameInfo> & names,const std::string & app_locale)577 void AutofillProfile::OverwriteOrAppendNames(
578 const std::vector<NameInfo>& names,
579 const std::string& app_locale) {
580 std::vector<NameInfo> results(name_);
581 for (std::vector<NameInfo>::const_iterator it = names.begin();
582 it != names.end();
583 ++it) {
584 NameInfo imported_name = *it;
585 bool should_append_imported_name = true;
586
587 for (size_t index = 0; index < name_.size(); ++index) {
588 NameInfo current_name = name_[index];
589 if (current_name.ParsedNamesAreEqual(imported_name)) {
590 if (current_name.GetRawInfo(NAME_FULL).empty()) {
591 current_name.SetRawInfo(NAME_FULL,
592 imported_name.GetRawInfo(NAME_FULL));
593 }
594
595 should_append_imported_name = false;
596 break;
597 }
598
599 AutofillType type = AutofillType(NAME_FULL);
600 base::string16 full_name = current_name.GetInfo(type, app_locale);
601 if (base::StringToLowerASCII(full_name) ==
602 base::StringToLowerASCII(imported_name.GetInfo(type, app_locale))) {
603 // The imported name has the same full name string as one of the
604 // existing names for this profile. Because full names are
605 // _heuristically_ parsed into {first, middle, last} name components,
606 // it's possible that either the existing name or the imported name
607 // was misparsed. Prefer to keep the name whose {first, middle,
608 // last} components do not match those computed by the heuristic
609 // parse, as this more likely represents the correct, user-input parse
610 // of the name.
611 NameInfo heuristically_parsed_name;
612 heuristically_parsed_name.SetInfo(type, full_name, app_locale);
613 if (imported_name.ParsedNamesAreEqual(heuristically_parsed_name)) {
614 should_append_imported_name = false;
615 break;
616 }
617
618 if (current_name.ParsedNamesAreEqual(heuristically_parsed_name)) {
619 results[index] = imported_name;
620 should_append_imported_name = false;
621 break;
622 }
623 }
624 }
625
626 // Append unique names to the list.
627 if (should_append_imported_name)
628 results.push_back(imported_name);
629 }
630
631 name_.swap(results);
632 }
633
OverwriteWithOrAddTo(const AutofillProfile & profile,const std::string & app_locale)634 void AutofillProfile::OverwriteWithOrAddTo(const AutofillProfile& profile,
635 const std::string& app_locale) {
636 // Verified profiles should never be overwritten with unverified data.
637 DCHECK(!IsVerified() || profile.IsVerified());
638 set_origin(profile.origin());
639 set_language_code(profile.language_code());
640
641 ServerFieldTypeSet field_types;
642 profile.GetNonEmptyTypes(app_locale, &field_types);
643
644 // Only transfer "full" types (e.g. full name) and not fragments (e.g.
645 // first name, last name).
646 CollapseCompoundFieldTypes(&field_types);
647
648 // TODO(isherman): Revisit this decision in the context of i18n and storing
649 // full addresses rather than storing 1-to-2 lines of an address.
650 // For addresses, do the opposite: transfer individual address lines, rather
651 // than full addresses.
652 field_types.erase(ADDRESS_HOME_STREET_ADDRESS);
653
654 for (ServerFieldTypeSet::const_iterator iter = field_types.begin();
655 iter != field_types.end(); ++iter) {
656 FieldTypeGroup group = AutofillType(*iter).group();
657 // Special case names.
658 if (group == NAME) {
659 OverwriteOrAppendNames(profile.name_, app_locale);
660 continue;
661 }
662
663 // Single value field --- overwrite.
664 if (!AutofillProfile::SupportsMultiValue(*iter)) {
665 base::string16 new_value = profile.GetRawInfo(*iter);
666 if (base::StringToLowerASCII(GetRawInfo(*iter)) !=
667 base::StringToLowerASCII(new_value)) {
668 SetRawInfo(*iter, new_value);
669 }
670 continue;
671 }
672
673 // Multi value field --- overwrite/append.
674 std::vector<base::string16> new_values;
675 profile.GetRawMultiInfo(*iter, &new_values);
676 std::vector<base::string16> existing_values;
677 GetRawMultiInfo(*iter, &existing_values);
678
679 // GetMultiInfo always returns at least one element, even if the profile
680 // has no data stored for this field type.
681 if (existing_values.size() == 1 && existing_values.front().empty())
682 existing_values.clear();
683
684 for (std::vector<base::string16>::iterator value_iter =
685 new_values.begin();
686 value_iter != new_values.end(); ++value_iter) {
687 // Don't add duplicates. Most types get case insensitive matching.
688 std::vector<base::string16>::const_iterator existing_iter;
689
690 if (group == PHONE_HOME) {
691 // Phones allow "fuzzy" matching, so "1-800-FLOWERS", "18003569377",
692 // "(800)356-9377" and "356-9377" are considered the same.
693 std::string country_code =
694 base::UTF16ToASCII(GetRawInfo(ADDRESS_HOME_COUNTRY));
695 existing_iter =
696 std::find_if(existing_values.begin(), existing_values.end(),
697 FindByPhone(*value_iter, country_code, app_locale));
698 } else {
699 existing_iter =
700 std::find_if(existing_values.begin(), existing_values.end(),
701 CaseInsensitiveStringEquals(*value_iter));
702 }
703
704 if (existing_iter == existing_values.end())
705 existing_values.insert(existing_values.end(), *value_iter);
706 }
707
708 SetRawMultiInfo(*iter, existing_values);
709 }
710 }
711
712 // static
SupportsMultiValue(ServerFieldType type)713 bool AutofillProfile::SupportsMultiValue(ServerFieldType type) {
714 FieldTypeGroup group = AutofillType(type).group();
715 return group == NAME ||
716 group == NAME_BILLING ||
717 group == EMAIL ||
718 group == PHONE_HOME ||
719 group == PHONE_BILLING;
720 }
721
722 // static
CreateDifferentiatingLabels(const std::vector<AutofillProfile * > & profiles,const std::string & app_locale,std::vector<base::string16> * labels)723 void AutofillProfile::CreateDifferentiatingLabels(
724 const std::vector<AutofillProfile*>& profiles,
725 const std::string& app_locale,
726 std::vector<base::string16>* labels) {
727 const size_t kMinimalFieldsShown = 2;
728 CreateInferredLabels(profiles, NULL, UNKNOWN_TYPE, kMinimalFieldsShown,
729 app_locale, labels);
730 DCHECK_EQ(profiles.size(), labels->size());
731 }
732
733 // static
CreateInferredLabels(const std::vector<AutofillProfile * > & profiles,const std::vector<ServerFieldType> * suggested_fields,ServerFieldType excluded_field,size_t minimal_fields_shown,const std::string & app_locale,std::vector<base::string16> * labels)734 void AutofillProfile::CreateInferredLabels(
735 const std::vector<AutofillProfile*>& profiles,
736 const std::vector<ServerFieldType>* suggested_fields,
737 ServerFieldType excluded_field,
738 size_t minimal_fields_shown,
739 const std::string& app_locale,
740 std::vector<base::string16>* labels) {
741 std::vector<ServerFieldType> fields_to_use;
742 GetFieldsForDistinguishingProfiles(suggested_fields, excluded_field,
743 &fields_to_use);
744
745 // Construct the default label for each profile. Also construct a map that
746 // associates each label with the profiles that have this label. This map is
747 // then used to detect which labels need further differentiating fields.
748 std::map<base::string16, std::list<size_t> > labels_to_profiles;
749 for (size_t i = 0; i < profiles.size(); ++i) {
750 base::string16 label =
751 profiles[i]->ConstructInferredLabel(fields_to_use,
752 minimal_fields_shown,
753 app_locale);
754 labels_to_profiles[label].push_back(i);
755 }
756
757 labels->resize(profiles.size());
758 for (std::map<base::string16, std::list<size_t> >::const_iterator it =
759 labels_to_profiles.begin();
760 it != labels_to_profiles.end(); ++it) {
761 if (it->second.size() == 1) {
762 // This label is unique, so use it without any further ado.
763 base::string16 label = it->first;
764 size_t profile_index = it->second.front();
765 (*labels)[profile_index] = label;
766 } else {
767 // We have more than one profile with the same label, so add
768 // differentiating fields.
769 CreateInferredLabelsHelper(profiles, it->second, fields_to_use,
770 minimal_fields_shown, app_locale, labels);
771 }
772 }
773 }
774
GetSupportedTypes(ServerFieldTypeSet * supported_types) const775 void AutofillProfile::GetSupportedTypes(
776 ServerFieldTypeSet* supported_types) const {
777 FormGroupList info = FormGroups();
778 for (FormGroupList::const_iterator it = info.begin(); it != info.end(); ++it)
779 (*it)->GetSupportedTypes(supported_types);
780 }
781
GetMultiInfoImpl(const AutofillType & type,const std::string & app_locale,std::vector<base::string16> * values) const782 void AutofillProfile::GetMultiInfoImpl(
783 const AutofillType& type,
784 const std::string& app_locale,
785 std::vector<base::string16>* values) const {
786 switch (type.group()) {
787 case NAME:
788 case NAME_BILLING:
789 CopyItemsToValues(type, name_, app_locale, values);
790 break;
791 case EMAIL:
792 CopyItemsToValues(type, email_, app_locale, values);
793 break;
794 case PHONE_HOME:
795 case PHONE_BILLING:
796 CopyItemsToValues(type, phone_number_, app_locale, values);
797 break;
798 default:
799 values->resize(1);
800 (*values)[0] = GetFormGroupInfo(*this, type, app_locale);
801 }
802 }
803
ConstructInferredLabel(const std::vector<ServerFieldType> & included_fields,size_t num_fields_to_use,const std::string & app_locale) const804 base::string16 AutofillProfile::ConstructInferredLabel(
805 const std::vector<ServerFieldType>& included_fields,
806 size_t num_fields_to_use,
807 const std::string& app_locale) const {
808 base::string16 separator =
809 l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_SUMMARY_SEPARATOR);
810
811 AutofillType region_code_type(HTML_TYPE_COUNTRY_CODE, HTML_MODE_NONE);
812 const base::string16& profile_region_code =
813 GetInfo(region_code_type, app_locale);
814 std::string address_region_code = UTF16ToUTF8(profile_region_code);
815
816 // A copy of |this| pruned down to contain only data for the address fields in
817 // |included_fields|.
818 AutofillProfile trimmed_profile(guid(), origin());
819 trimmed_profile.SetInfo(region_code_type, profile_region_code, app_locale);
820 trimmed_profile.set_language_code(language_code());
821
822 std::vector<ServerFieldType> remaining_fields;
823 for (std::vector<ServerFieldType>::const_iterator it =
824 included_fields.begin();
825 it != included_fields.end() && num_fields_to_use > 0;
826 ++it) {
827 AddressField address_field;
828 if (!i18n::FieldForType(*it, &address_field) ||
829 !::i18n::addressinput::IsFieldUsed(
830 address_field, address_region_code) ||
831 address_field == ::i18n::addressinput::COUNTRY) {
832 remaining_fields.push_back(*it);
833 continue;
834 }
835
836 AutofillType autofill_type(*it);
837 const base::string16& field_value = GetInfo(autofill_type, app_locale);
838 if (field_value.empty())
839 continue;
840
841 trimmed_profile.SetInfo(autofill_type, field_value, app_locale);
842 --num_fields_to_use;
843 }
844
845 scoped_ptr<AddressData> address_data =
846 i18n::CreateAddressDataFromAutofillProfile(trimmed_profile, app_locale);
847 std::string address_line;
848 ::i18n::addressinput::GetFormattedNationalAddressLine(
849 *address_data, &address_line);
850 base::string16 label = base::UTF8ToUTF16(address_line);
851
852 for (std::vector<ServerFieldType>::const_iterator it =
853 remaining_fields.begin();
854 it != remaining_fields.end() && num_fields_to_use > 0;
855 ++it) {
856 const base::string16& field_value = GetInfo(AutofillType(*it), app_locale);
857 if (field_value.empty())
858 continue;
859
860 if (!label.empty())
861 label.append(separator);
862
863 label.append(field_value);
864 --num_fields_to_use;
865 }
866
867 // If country code is missing, libaddressinput won't be used to format the
868 // address. In this case the suggestion might include a multi-line street
869 // address which needs to be flattened.
870 base::ReplaceChars(label, base::ASCIIToUTF16("\n"), separator, &label);
871
872 return label;
873 }
874
875 // static
CreateInferredLabelsHelper(const std::vector<AutofillProfile * > & profiles,const std::list<size_t> & indices,const std::vector<ServerFieldType> & fields,size_t num_fields_to_include,const std::string & app_locale,std::vector<base::string16> * labels)876 void AutofillProfile::CreateInferredLabelsHelper(
877 const std::vector<AutofillProfile*>& profiles,
878 const std::list<size_t>& indices,
879 const std::vector<ServerFieldType>& fields,
880 size_t num_fields_to_include,
881 const std::string& app_locale,
882 std::vector<base::string16>* labels) {
883 // For efficiency, we first construct a map of fields to their text values and
884 // each value's frequency.
885 std::map<ServerFieldType,
886 std::map<base::string16, size_t> > field_text_frequencies_by_field;
887 for (std::vector<ServerFieldType>::const_iterator field = fields.begin();
888 field != fields.end(); ++field) {
889 std::map<base::string16, size_t>& field_text_frequencies =
890 field_text_frequencies_by_field[*field];
891
892 for (std::list<size_t>::const_iterator it = indices.begin();
893 it != indices.end(); ++it) {
894 const AutofillProfile* profile = profiles[*it];
895 base::string16 field_text =
896 profile->GetInfo(AutofillType(*field), app_locale);
897
898 // If this label is not already in the map, add it with frequency 0.
899 if (!field_text_frequencies.count(field_text))
900 field_text_frequencies[field_text] = 0;
901
902 // Now, increment the frequency for this label.
903 ++field_text_frequencies[field_text];
904 }
905 }
906
907 // Now comes the meat of the algorithm. For each profile, we scan the list of
908 // fields to use, looking for two things:
909 // 1. A (non-empty) field that differentiates the profile from all others
910 // 2. At least |num_fields_to_include| non-empty fields
911 // Before we've satisfied condition (2), we include all fields, even ones that
912 // are identical across all the profiles. Once we've satisfied condition (2),
913 // we only include fields that that have at last two distinct values.
914 for (std::list<size_t>::const_iterator it = indices.begin();
915 it != indices.end(); ++it) {
916 const AutofillProfile* profile = profiles[*it];
917
918 std::vector<ServerFieldType> label_fields;
919 bool found_differentiating_field = false;
920 for (std::vector<ServerFieldType>::const_iterator field = fields.begin();
921 field != fields.end(); ++field) {
922 // Skip over empty fields.
923 base::string16 field_text =
924 profile->GetInfo(AutofillType(*field), app_locale);
925 if (field_text.empty())
926 continue;
927
928 std::map<base::string16, size_t>& field_text_frequencies =
929 field_text_frequencies_by_field[*field];
930 found_differentiating_field |=
931 !field_text_frequencies.count(base::string16()) &&
932 (field_text_frequencies[field_text] == 1);
933
934 // Once we've found enough non-empty fields, skip over any remaining
935 // fields that are identical across all the profiles.
936 if (label_fields.size() >= num_fields_to_include &&
937 (field_text_frequencies.size() == 1))
938 continue;
939
940 label_fields.push_back(*field);
941
942 // If we've (1) found a differentiating field and (2) found at least
943 // |num_fields_to_include| non-empty fields, we're done!
944 if (found_differentiating_field &&
945 label_fields.size() >= num_fields_to_include)
946 break;
947 }
948
949 (*labels)[*it] = profile->ConstructInferredLabel(
950 label_fields, label_fields.size(), app_locale);
951 }
952 }
953
FormGroups() const954 AutofillProfile::FormGroupList AutofillProfile::FormGroups() const {
955 FormGroupList v(5);
956 v[0] = &name_[0];
957 v[1] = &email_[0];
958 v[2] = &company_;
959 v[3] = &phone_number_[0];
960 v[4] = &address_;
961 return v;
962 }
963
FormGroupForType(const AutofillType & type) const964 const FormGroup* AutofillProfile::FormGroupForType(
965 const AutofillType& type) const {
966 return const_cast<AutofillProfile*>(this)->MutableFormGroupForType(type);
967 }
968
MutableFormGroupForType(const AutofillType & type)969 FormGroup* AutofillProfile::MutableFormGroupForType(const AutofillType& type) {
970 switch (type.group()) {
971 case NAME:
972 case NAME_BILLING:
973 return &name_[0];
974
975 case EMAIL:
976 return &email_[0];
977
978 case COMPANY:
979 return &company_;
980
981 case PHONE_HOME:
982 case PHONE_BILLING:
983 return &phone_number_[0];
984
985 case ADDRESS_HOME:
986 case ADDRESS_BILLING:
987 return &address_;
988
989 case NO_GROUP:
990 case CREDIT_CARD:
991 case PASSWORD_FIELD:
992 case TRANSACTION:
993 return NULL;
994 }
995
996 NOTREACHED();
997 return NULL;
998 }
999
1000 // So we can compare AutofillProfiles with EXPECT_EQ().
operator <<(std::ostream & os,const AutofillProfile & profile)1001 std::ostream& operator<<(std::ostream& os, const AutofillProfile& profile) {
1002 return os
1003 << profile.guid()
1004 << " "
1005 << profile.origin()
1006 << " "
1007 << UTF16ToUTF8(MultiString(profile, NAME_FIRST))
1008 << " "
1009 << UTF16ToUTF8(MultiString(profile, NAME_MIDDLE))
1010 << " "
1011 << UTF16ToUTF8(MultiString(profile, NAME_LAST))
1012 << " "
1013 << UTF16ToUTF8(MultiString(profile, EMAIL_ADDRESS))
1014 << " "
1015 << UTF16ToUTF8(profile.GetRawInfo(COMPANY_NAME))
1016 << " "
1017 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_LINE1))
1018 << " "
1019 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_LINE2))
1020 << " "
1021 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY))
1022 << " "
1023 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_CITY))
1024 << " "
1025 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_STATE))
1026 << " "
1027 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_ZIP))
1028 << " "
1029 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_SORTING_CODE))
1030 << " "
1031 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_COUNTRY))
1032 << " "
1033 << profile.language_code()
1034 << " "
1035 << UTF16ToUTF8(MultiString(profile, PHONE_HOME_WHOLE_NUMBER));
1036 }
1037
1038 } // namespace autofill
1039