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/phone_number.h"
      6 
      7 #include "base/basictypes.h"
      8 #include "base/strings/string_number_conversions.h"
      9 #include "base/strings/string_util.h"
     10 #include "base/strings/utf_string_conversions.h"
     11 #include "components/autofill/core/browser/autofill_country.h"
     12 #include "components/autofill/core/browser/autofill_profile.h"
     13 #include "components/autofill/core/browser/autofill_type.h"
     14 #include "components/autofill/core/browser/field_types.h"
     15 #include "components/autofill/core/browser/phone_number_i18n.h"
     16 
     17 namespace autofill {
     18 namespace {
     19 
     20 const char16 kPhoneNumberSeparators[] = { ' ', '.', '(', ')', '-', 0 };
     21 
     22 void StripPunctuation(base::string16* number) {
     23   base::RemoveChars(*number, kPhoneNumberSeparators, number);
     24 }
     25 
     26 // Returns the region code for this phone number, which is an ISO 3166 2-letter
     27 // country code.  The returned value is based on the |profile|; if the |profile|
     28 // does not have a country code associated with it, falls back to the country
     29 // code corresponding to the |app_locale|.
     30 std::string GetRegion(const AutofillProfile& profile,
     31                       const std::string& app_locale) {
     32   base::string16 country_code = profile.GetRawInfo(ADDRESS_HOME_COUNTRY);
     33   if (!country_code.empty())
     34     return UTF16ToASCII(country_code);
     35 
     36   return AutofillCountry::CountryCodeForLocale(app_locale);
     37 }
     38 
     39 }  // namespace
     40 
     41 PhoneNumber::PhoneNumber(AutofillProfile* profile)
     42     : profile_(profile) {
     43 }
     44 
     45 PhoneNumber::PhoneNumber(const PhoneNumber& number)
     46     : profile_(NULL) {
     47   *this = number;
     48 }
     49 
     50 PhoneNumber::~PhoneNumber() {}
     51 
     52 PhoneNumber& PhoneNumber::operator=(const PhoneNumber& number) {
     53   if (this == &number)
     54     return *this;
     55 
     56   number_ = number.number_;
     57   profile_ = number.profile_;
     58   cached_parsed_phone_ = number.cached_parsed_phone_;
     59   return *this;
     60 }
     61 
     62 void PhoneNumber::GetSupportedTypes(ServerFieldTypeSet* supported_types) const {
     63   supported_types->insert(PHONE_HOME_WHOLE_NUMBER);
     64   supported_types->insert(PHONE_HOME_NUMBER);
     65   supported_types->insert(PHONE_HOME_CITY_CODE);
     66   supported_types->insert(PHONE_HOME_CITY_AND_NUMBER);
     67   supported_types->insert(PHONE_HOME_COUNTRY_CODE);
     68 }
     69 
     70 base::string16 PhoneNumber::GetRawInfo(ServerFieldType type) const {
     71   DCHECK_EQ(PHONE_HOME, AutofillType(type).group());
     72   if (type == PHONE_HOME_WHOLE_NUMBER)
     73     return number_;
     74 
     75   // Only the whole number is available as raw data.  All of the other types are
     76   // parsed from this raw info, and parsing requires knowledge of the phone
     77   // number's region, which is only available via GetInfo().
     78   return base::string16();
     79 }
     80 
     81 void PhoneNumber::SetRawInfo(ServerFieldType type,
     82                              const base::string16& value) {
     83   DCHECK_EQ(PHONE_HOME, AutofillType(type).group());
     84   if (type != PHONE_HOME_CITY_AND_NUMBER && type != PHONE_HOME_WHOLE_NUMBER) {
     85     // Only full phone numbers should be set directly.  The remaining field
     86     // field types are read-only.
     87     return;
     88   }
     89 
     90   number_ = value;
     91 
     92   // Invalidate the cached number.
     93   cached_parsed_phone_ = i18n::PhoneObject();
     94 }
     95 
     96 // Normalize phones if |type| is a whole number:
     97 //   (650)2345678 -> 6502345678
     98 //   1-800-FLOWERS -> 18003569377
     99 // If the phone cannot be normalized, returns the stored value verbatim.
    100 base::string16 PhoneNumber::GetInfo(const AutofillType& type,
    101                                     const std::string& app_locale) const {
    102   ServerFieldType storable_type = type.GetStorableType();
    103   UpdateCacheIfNeeded(app_locale);
    104 
    105   // Queries for whole numbers will return the non-normalized number if
    106   // normalization for the number fails.  All other field types require
    107   // normalization.
    108   if (storable_type != PHONE_HOME_WHOLE_NUMBER &&
    109       !cached_parsed_phone_.IsValidNumber())
    110     return base::string16();
    111 
    112   switch (storable_type) {
    113     case PHONE_HOME_WHOLE_NUMBER:
    114       return cached_parsed_phone_.GetWholeNumber();
    115 
    116     case PHONE_HOME_NUMBER:
    117       return cached_parsed_phone_.number();
    118 
    119     case PHONE_HOME_CITY_CODE:
    120       return cached_parsed_phone_.city_code();
    121 
    122     case PHONE_HOME_COUNTRY_CODE:
    123       return cached_parsed_phone_.country_code();
    124 
    125     case PHONE_HOME_CITY_AND_NUMBER:
    126       return
    127           cached_parsed_phone_.city_code() + cached_parsed_phone_.number();
    128 
    129     default:
    130       NOTREACHED();
    131       return base::string16();
    132   }
    133 }
    134 
    135 bool PhoneNumber::SetInfo(const AutofillType& type,
    136                           const base::string16& value,
    137                           const std::string& app_locale) {
    138   SetRawInfo(type.GetStorableType(), value);
    139 
    140   if (number_.empty())
    141     return true;
    142 
    143   // Store a formatted (i.e., pretty printed) version of the number.
    144   UpdateCacheIfNeeded(app_locale);
    145   number_ = cached_parsed_phone_.GetFormattedNumber();
    146   return !number_.empty();
    147 }
    148 
    149 void PhoneNumber::GetMatchingTypes(const base::string16& text,
    150                                    const std::string& app_locale,
    151                                    ServerFieldTypeSet* matching_types) const {
    152   base::string16 stripped_text = text;
    153   StripPunctuation(&stripped_text);
    154   FormGroup::GetMatchingTypes(stripped_text, app_locale, matching_types);
    155 
    156   // For US numbers, also compare to the three-digit prefix and the four-digit
    157   // suffix, since web sites often split numbers into these two fields.
    158   base::string16 number = GetInfo(AutofillType(PHONE_HOME_NUMBER), app_locale);
    159   if (GetRegion(*profile_, app_locale) == "US" &&
    160       number.size() == (kPrefixLength + kSuffixLength)) {
    161     base::string16 prefix = number.substr(kPrefixOffset, kPrefixLength);
    162     base::string16 suffix = number.substr(kSuffixOffset, kSuffixLength);
    163     if (text == prefix || text == suffix)
    164       matching_types->insert(PHONE_HOME_NUMBER);
    165   }
    166 
    167   base::string16 whole_number =
    168       GetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER), app_locale);
    169   if (!whole_number.empty()) {
    170     base::string16 normalized_number =
    171         i18n::NormalizePhoneNumber(text, GetRegion(*profile_, app_locale));
    172     if (normalized_number == whole_number)
    173       matching_types->insert(PHONE_HOME_WHOLE_NUMBER);
    174   }
    175 }
    176 
    177 void PhoneNumber::UpdateCacheIfNeeded(const std::string& app_locale) const {
    178   std::string region = GetRegion(*profile_, app_locale);
    179   if (!number_.empty() && cached_parsed_phone_.region() != region)
    180     cached_parsed_phone_ = i18n::PhoneObject(number_, region);
    181 }
    182 
    183 PhoneNumber::PhoneCombineHelper::PhoneCombineHelper() {
    184 }
    185 
    186 PhoneNumber::PhoneCombineHelper::~PhoneCombineHelper() {
    187 }
    188 
    189 bool PhoneNumber::PhoneCombineHelper::SetInfo(const AutofillType& type,
    190                                               const base::string16& value) {
    191   ServerFieldType storable_type = type.GetStorableType();
    192   if (storable_type == PHONE_HOME_COUNTRY_CODE) {
    193     country_ = value;
    194     return true;
    195   }
    196 
    197   if (storable_type == PHONE_HOME_CITY_CODE) {
    198     city_ = value;
    199     return true;
    200   }
    201 
    202   if (storable_type == PHONE_HOME_CITY_AND_NUMBER) {
    203     phone_ = value;
    204     return true;
    205   }
    206 
    207   if (storable_type == PHONE_HOME_WHOLE_NUMBER) {
    208     whole_number_ = value;
    209     return true;
    210   }
    211 
    212   if (storable_type == PHONE_HOME_NUMBER) {
    213     phone_.append(value);
    214     return true;
    215   }
    216 
    217   return false;
    218 }
    219 
    220 bool PhoneNumber::PhoneCombineHelper::ParseNumber(
    221     const AutofillProfile& profile,
    222     const std::string& app_locale,
    223     base::string16* value) {
    224   if (IsEmpty())
    225     return false;
    226 
    227   if (!whole_number_.empty()) {
    228     *value = whole_number_;
    229     return true;
    230   }
    231 
    232   return i18n::ConstructPhoneNumber(
    233       country_, city_, phone_, GetRegion(profile, app_locale), value);
    234 }
    235 
    236 bool PhoneNumber::PhoneCombineHelper::IsEmpty() const {
    237   return phone_.empty() && whole_number_.empty();
    238 }
    239 
    240 }  // namespace autofill
    241