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