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.
    138   UpdateCacheIfNeeded(app_locale);
    139   number_ = cached_parsed_phone_.GetFormattedNumber();
    140   return !number_.empty();
    141 }
    142 
    143 void PhoneNumber::GetMatchingTypes(const base::string16& text,
    144                                    const std::string& app_locale,
    145                                    ServerFieldTypeSet* matching_types) const {
    146   base::string16 stripped_text = text;
    147   base::RemoveChars(stripped_text, base::ASCIIToUTF16(" .()-"), &stripped_text);
    148   FormGroup::GetMatchingTypes(stripped_text, app_locale, matching_types);
    149 
    150   // For US numbers, also compare to the three-digit prefix and the four-digit
    151   // suffix, since web sites often split numbers into these two fields.
    152   base::string16 number = GetInfo(AutofillType(PHONE_HOME_NUMBER), app_locale);
    153   if (GetRegion(*profile_, app_locale) == "US" &&
    154       number.size() == (kPrefixLength + kSuffixLength)) {
    155     base::string16 prefix = number.substr(kPrefixOffset, kPrefixLength);
    156     base::string16 suffix = number.substr(kSuffixOffset, kSuffixLength);
    157     if (text == prefix || text == suffix)
    158       matching_types->insert(PHONE_HOME_NUMBER);
    159   }
    160 
    161   base::string16 whole_number =
    162       GetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER), app_locale);
    163   if (!whole_number.empty()) {
    164     base::string16 normalized_number =
    165         i18n::NormalizePhoneNumber(text, GetRegion(*profile_, app_locale));
    166     if (normalized_number == whole_number)
    167       matching_types->insert(PHONE_HOME_WHOLE_NUMBER);
    168   }
    169 }
    170 
    171 void PhoneNumber::UpdateCacheIfNeeded(const std::string& app_locale) const {
    172   std::string region = GetRegion(*profile_, app_locale);
    173   if (!number_.empty() && cached_parsed_phone_.region() != region)
    174     cached_parsed_phone_ = i18n::PhoneObject(number_, region);
    175 }
    176 
    177 PhoneNumber::PhoneCombineHelper::PhoneCombineHelper() {
    178 }
    179 
    180 PhoneNumber::PhoneCombineHelper::~PhoneCombineHelper() {
    181 }
    182 
    183 bool PhoneNumber::PhoneCombineHelper::SetInfo(const AutofillType& type,
    184                                               const base::string16& value) {
    185   ServerFieldType storable_type = type.GetStorableType();
    186   if (storable_type == PHONE_HOME_COUNTRY_CODE) {
    187     country_ = value;
    188     return true;
    189   }
    190 
    191   if (storable_type == PHONE_HOME_CITY_CODE) {
    192     city_ = value;
    193     return true;
    194   }
    195 
    196   if (storable_type == PHONE_HOME_CITY_AND_NUMBER) {
    197     phone_ = value;
    198     return true;
    199   }
    200 
    201   if (storable_type == PHONE_HOME_WHOLE_NUMBER) {
    202     whole_number_ = value;
    203     return true;
    204   }
    205 
    206   if (storable_type == PHONE_HOME_NUMBER) {
    207     phone_.append(value);
    208     return true;
    209   }
    210 
    211   return false;
    212 }
    213 
    214 bool PhoneNumber::PhoneCombineHelper::ParseNumber(
    215     const AutofillProfile& profile,
    216     const std::string& app_locale,
    217     base::string16* value) {
    218   if (IsEmpty())
    219     return false;
    220 
    221   if (!whole_number_.empty()) {
    222     *value = whole_number_;
    223     return true;
    224   }
    225 
    226   return i18n::ConstructPhoneNumber(
    227       country_, city_, phone_, GetRegion(profile, app_locale), value);
    228 }
    229 
    230 bool PhoneNumber::PhoneCombineHelper::IsEmpty() const {
    231   return phone_.empty() && whole_number_.empty();
    232 }
    233 
    234 }  // namespace autofill
    235