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.
5 #include "components/autofill/core/browser/phone_number.h"
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"
20 const char16 kPhoneNumberSeparators[] = { ' ', '.', '(', ')', '-', 0 };
22 void StripPunctuation(base::string16* number) {
23 RemoveChars(*number, kPhoneNumberSeparators, number);
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);
36 return AutofillCountry::CountryCodeForLocale(app_locale);
41 PhoneNumber::PhoneNumber(AutofillProfile* profile)
45 PhoneNumber::PhoneNumber(const PhoneNumber& number)
50 PhoneNumber::~PhoneNumber() {}
52 PhoneNumber& PhoneNumber::operator=(const PhoneNumber& number) {
56 number_ = number.number_;
57 profile_ = number.profile_;
58 cached_parsed_phone_ = number.cached_parsed_phone_;
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);
70 base::string16 PhoneNumber::GetRawInfo(ServerFieldType type) const {
71 DCHECK_EQ(PHONE_HOME, AutofillType(type).group());
72 if (type == PHONE_HOME_WHOLE_NUMBER)
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();
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.
92 // Invalidate the cached number.
93 cached_parsed_phone_ = i18n::PhoneObject();
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);
105 // Queries for whole numbers will return the non-normalized number if
106 // normalization for the number fails. All other field types require
108 if (storable_type != PHONE_HOME_WHOLE_NUMBER &&
109 !cached_parsed_phone_.IsValidNumber())
110 return base::string16();
112 switch (storable_type) {
113 case PHONE_HOME_WHOLE_NUMBER:
114 return cached_parsed_phone_.GetWholeNumber();
116 case PHONE_HOME_NUMBER:
117 return cached_parsed_phone_.number();
119 case PHONE_HOME_CITY_CODE:
120 return cached_parsed_phone_.city_code();
122 case PHONE_HOME_COUNTRY_CODE:
123 return cached_parsed_phone_.country_code();
125 case PHONE_HOME_CITY_AND_NUMBER:
127 cached_parsed_phone_.city_code() + cached_parsed_phone_.number();
131 return base::string16();
135 bool PhoneNumber::SetInfo(const AutofillType& type,
136 const base::string16& value,
137 const std::string& app_locale) {
138 SetRawInfo(type.GetStorableType(), value);
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();
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);
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);
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);
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);
183 PhoneNumber::PhoneCombineHelper::PhoneCombineHelper() {
186 PhoneNumber::PhoneCombineHelper::~PhoneCombineHelper() {
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) {
197 if (storable_type == PHONE_HOME_CITY_CODE) {
202 if (storable_type == PHONE_HOME_CITY_AND_NUMBER) {
207 if (storable_type == PHONE_HOME_WHOLE_NUMBER) {
208 whole_number_ = value;
212 if (storable_type == PHONE_HOME_NUMBER) {
213 phone_.append(value);
220 bool PhoneNumber::PhoneCombineHelper::ParseNumber(
221 const AutofillProfile& profile,
222 const std::string& app_locale,
223 base::string16* value) {
227 if (!whole_number_.empty()) {
228 *value = whole_number_;
232 return i18n::ConstructPhoneNumber(
233 country_, city_, phone_, GetRegion(profile, app_locale), value);
236 bool PhoneNumber::PhoneCombineHelper::IsEmpty() const {
237 return phone_.empty() && whole_number_.empty();
240 } // namespace autofill