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
35using base::ASCIIToUTF16;
36using base::UTF16ToUTF8;
37using i18n::addressinput::AddressData;
38using i18n::addressinput::AddressField;
39
40namespace autofill {
41namespace {
42
43// Like |AutofillType::GetStorableType()|, but also returns |NAME_FULL| for
44// first, middle, and last name field types.
45ServerFieldType 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.
60void 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.
126const 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
139base::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
147template <class T>
148void 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
160template <class T>
161void 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
174template <class T>
175void 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.
187void 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
216class FindByPhone {
217 public:
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
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.
236struct CaseInsensitiveStringEquals {
237 public:
238  CaseInsensitiveStringEquals(const base::string16& other)
239      : other_(other) {}
240
241  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
252AutofillProfile::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
260AutofillProfile::AutofillProfile()
261    : AutofillDataModel(base::GenerateGUID(), std::string()),
262      name_(1),
263      email_(1),
264      phone_number_(1, PhoneNumber(this)) {
265}
266
267AutofillProfile::AutofillProfile(const AutofillProfile& profile)
268    : AutofillDataModel(std::string(), std::string()) {
269  operator=(profile);
270}
271
272AutofillProfile::~AutofillProfile() {
273}
274
275AutofillProfile& 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
296void 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
305base::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
313void 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
320base::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
340bool 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
352base::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
368void 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
399void AutofillProfile::GetRawMultiInfo(
400    ServerFieldType type,
401    std::vector<base::string16>* values) const {
402  GetMultiInfoImpl(AutofillType(type), std::string(), values);
403}
404
405void 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
437void 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
443bool AutofillProfile::IsEmpty(const std::string& app_locale) const {
444  ServerFieldTypeSet types;
445  GetNonEmptyTypes(app_locale, &types);
446  return types.empty();
447}
448
449bool 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
474int 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
519bool AutofillProfile::EqualsSansOrigin(const AutofillProfile& profile) const {
520  return guid() == profile.guid() &&
521         language_code() == profile.language_code() &&
522         Compare(profile) == 0;
523}
524
525bool AutofillProfile::EqualsSansGuid(const AutofillProfile& profile) const {
526  return origin() == profile.origin() &&
527         language_code() == profile.language_code() &&
528         Compare(profile) == 0;
529}
530
531bool AutofillProfile::operator==(const AutofillProfile& profile) const {
532  return guid() == profile.guid() && EqualsSansGuid(profile);
533}
534
535bool AutofillProfile::operator!=(const AutofillProfile& profile) const {
536  return !operator==(profile);
537}
538
539const base::string16 AutofillProfile::PrimaryValue() const {
540  return GetRawInfo(ADDRESS_HOME_LINE1) + GetRawInfo(ADDRESS_HOME_CITY);
541}
542
543bool 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
577void 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
634void 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
713bool 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
723void 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
734void 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
775void 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
782void 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
804base::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
876void 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
954AutofillProfile::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
964const FormGroup* AutofillProfile::FormGroupForType(
965    const AutofillType& type) const {
966  return const_cast<AutofillProfile*>(this)->MutableFormGroupForType(type);
967}
968
969FormGroup* 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().
1001std::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