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