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