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