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