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