OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/autofill/phone_number_i18n.h" | 5 #include "chrome/browser/autofill/phone_number_i18n.h" |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/stringprintf.h" | 9 #include "base/stringprintf.h" |
10 #include "base/string_number_conversions.h" | 10 #include "base/string_number_conversions.h" |
11 #include "base/utf_string_conversions.h" | 11 #include "base/utf_string_conversions.h" |
12 #include "chrome/browser/autofill/autofill_country.h" | 12 #include "chrome/browser/autofill/autofill_country.h" |
13 #include "third_party/libphonenumber/src/phonenumber_api.h" | 13 #include "third_party/libphonenumber/src/phonenumber_api.h" |
14 | 14 |
15 using i18n::phonenumbers::PhoneNumber; | 15 using i18n::phonenumbers::PhoneNumber; |
16 using i18n::phonenumbers::PhoneNumberUtil; | 16 using i18n::phonenumbers::PhoneNumberUtil; |
17 | 17 |
18 namespace { | 18 namespace { |
19 | 19 |
20 std::string SanitizeRegion(const std::string& region) { | 20 std::string SanitizeRegion(const std::string& region) { |
21 if (region.length() == 2) | 21 if (region.length() == 2) |
22 return region; | 22 return region; |
23 | 23 |
24 return AutofillCountry::CountryCodeForLocale( | 24 return AutofillCountry::CountryCodeForLocale( |
25 AutofillCountry::ApplicationLocale()); | 25 AutofillCountry::ApplicationLocale()); |
26 } | 26 } |
27 | 27 |
28 i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat UtilsTypeToPhoneLibType( | 28 PhoneNumberUtil::PhoneNumberFormat UtilsTypeToPhoneLibType( |
29 autofill_i18n::FullPhoneFormat phone_format) { | 29 autofill_i18n::FullPhoneFormat phone_format) { |
30 switch (phone_format) { | 30 switch (phone_format) { |
31 case autofill_i18n::E164: | 31 case autofill_i18n::E164: |
32 return i18n::phonenumbers::PhoneNumberUtil::E164; | 32 return PhoneNumberUtil::E164; |
33 case autofill_i18n::INTERNATIONAL: | 33 case autofill_i18n::INTERNATIONAL: |
34 return i18n::phonenumbers::PhoneNumberUtil::INTERNATIONAL; | 34 return PhoneNumberUtil::INTERNATIONAL; |
35 case autofill_i18n::NATIONAL: | 35 case autofill_i18n::NATIONAL: |
36 return i18n::phonenumbers::PhoneNumberUtil::NATIONAL; | 36 return PhoneNumberUtil::NATIONAL; |
37 case autofill_i18n::RFC3966: | 37 case autofill_i18n::RFC3966: |
38 return i18n::phonenumbers::PhoneNumberUtil::RFC3966; | 38 return PhoneNumberUtil::RFC3966; |
39 default: | 39 default: |
40 NOTREACHED(); | 40 NOTREACHED(); |
| 41 return PhoneNumberUtil::NATIONAL; |
41 } | 42 } |
42 return i18n::phonenumbers::PhoneNumberUtil::NATIONAL; | |
43 } | 43 } |
44 | 44 |
45 // Parses the number stored in |value| as it should be interpreted in the given | 45 // Parses the number stored in |value| as it should be interpreted in the given |
46 // |region|, and stores the results into the remaining arguments. The |region| | 46 // |region|, and stores the results into the remaining arguments. The |region| |
47 // should be sanitized prior to calling this function. | 47 // should be sanitized prior to calling this function. |
48 bool ParsePhoneNumberInternal(const string16& value, | 48 bool ParsePhoneNumberInternal(const string16& value, |
49 const std::string& region, | 49 const std::string& region, |
50 string16* country_code, | 50 string16* country_code, |
51 string16* city_code, | 51 string16* city_code, |
52 string16* number, | 52 string16* number, |
53 PhoneNumber* i18n_number) { | 53 PhoneNumber* i18n_number) { |
| 54 DCHECK(country_code); |
| 55 DCHECK(city_code); |
54 DCHECK(number); | 56 DCHECK(number); |
55 DCHECK(city_code); | |
56 DCHECK(country_code); | |
57 DCHECK(i18n_number); | 57 DCHECK(i18n_number); |
58 | 58 |
| 59 country_code->clear(); |
| 60 city_code->clear(); |
59 number->clear(); | 61 number->clear(); |
60 city_code->clear(); | |
61 country_code->clear(); | |
62 | 62 |
63 std::string number_text(UTF16ToUTF8(value)); | 63 std::string number_text(UTF16ToUTF8(value)); |
64 | 64 |
65 // Parse phone number based on the region. | 65 // Parse phone number based on the region. |
66 PhoneNumberUtil* phone_util = PhoneNumberUtil::GetInstance(); | 66 PhoneNumberUtil* phone_util = PhoneNumberUtil::GetInstance(); |
67 | 67 |
68 // The |region| should already be sanitized. | 68 // The |region| should already be sanitized. |
69 DCHECK_EQ(2U, region.size()); | 69 DCHECK_EQ(2U, region.size()); |
70 if (phone_util->Parse(number_text, region.c_str(), i18n_number) != | 70 if (phone_util->Parse(number_text, region.c_str(), i18n_number) != |
71 i18n::phonenumbers::PhoneNumberUtil::NO_PARSING_ERROR) { | 71 PhoneNumberUtil::NO_PARSING_ERROR) { |
72 return false; | 72 return false; |
73 } | 73 } |
74 | 74 |
75 i18n::phonenumbers::PhoneNumberUtil::ValidationResult validation = | 75 PhoneNumberUtil::ValidationResult validation = |
76 phone_util->IsPossibleNumberWithReason(*i18n_number); | 76 phone_util->IsPossibleNumberWithReason(*i18n_number); |
77 if (validation != i18n::phonenumbers::PhoneNumberUtil::IS_POSSIBLE) | 77 if (validation != PhoneNumberUtil::IS_POSSIBLE) |
78 return false; | 78 return false; |
79 | 79 |
80 // This verifies that number has a valid area code (that in some cases could | 80 // This verifies that number has a valid area code (that in some cases could |
81 // be empty) for parsed country code. Also verifies that this is a valid | 81 // be empty) for parsed country code. Also verifies that this is a valid |
82 // number (in US 1234567 is not valid, because numbers do not start with 1). | 82 // number (in US 1234567 is not valid, because numbers do not start with 1). |
83 if (!phone_util->IsValidNumber(*i18n_number)) | 83 if (!phone_util->IsValidNumber(*i18n_number)) |
84 return false; | 84 return false; |
85 | 85 |
86 std::string national_significant_number; | 86 std::string national_significant_number; |
87 phone_util->GetNationalSignificantNumber(*i18n_number, | 87 phone_util->GetNationalSignificantNumber(*i18n_number, |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 std::string result_utf8(UTF16ToUTF8(result)); | 150 std::string result_utf8(UTF16ToUTF8(result)); |
151 PhoneNumberUtil::GetInstance()->NormalizeDigitsOnly(&result_utf8); | 151 PhoneNumberUtil::GetInstance()->NormalizeDigitsOnly(&result_utf8); |
152 return UTF8ToUTF16(result_utf8); | 152 return UTF8ToUTF16(result_utf8); |
153 } | 153 } |
154 | 154 |
155 bool ParsePhoneNumber(const string16& value, | 155 bool ParsePhoneNumber(const string16& value, |
156 const std::string& region, | 156 const std::string& region, |
157 string16* country_code, | 157 string16* country_code, |
158 string16* city_code, | 158 string16* city_code, |
159 string16* number) { | 159 string16* number) { |
160 PhoneNumber i18n_number; | 160 PhoneNumber unused_i18n_number; |
161 return ParsePhoneNumberInternal(value, SanitizeRegion(region), | 161 return ParsePhoneNumberInternal(value, SanitizeRegion(region), |
162 country_code, city_code, number, | 162 country_code, city_code, number, |
163 &i18n_number); | 163 &unused_i18n_number); |
164 } | 164 } |
165 | 165 |
166 bool ConstructPhoneNumber(const string16& country_code, | 166 bool ConstructPhoneNumber(const string16& country_code, |
167 const string16& city_code, | 167 const string16& city_code, |
168 const string16& number, | 168 const string16& number, |
169 const std::string& region, | 169 const std::string& region, |
170 FullPhoneFormat phone_format, | 170 FullPhoneFormat phone_format, |
171 string16* whole_number) { | 171 string16* whole_number) { |
172 DCHECK(whole_number); | 172 DCHECK(whole_number); |
173 | 173 |
(...skipping 13 matching lines...) Expand all Loading... |
187 PhoneNumber i18n_number; | 187 PhoneNumber i18n_number; |
188 i18n_number.set_national_number(static_cast<uint64>(number_int)); | 188 i18n_number.set_national_number(static_cast<uint64>(number_int)); |
189 | 189 |
190 int country_int = phone_util->GetCountryCodeForRegion( | 190 int country_int = phone_util->GetCountryCodeForRegion( |
191 SanitizeRegion(region)); | 191 SanitizeRegion(region)); |
192 if (!country_code.empty() && !base::StringToInt(country_code, &country_int)) | 192 if (!country_code.empty() && !base::StringToInt(country_code, &country_int)) |
193 return false; | 193 return false; |
194 if (country_int) | 194 if (country_int) |
195 i18n_number.set_country_code(country_int); | 195 i18n_number.set_country_code(country_int); |
196 | 196 |
197 i18n::phonenumbers::PhoneNumberUtil::ValidationResult validation = | 197 PhoneNumberUtil::ValidationResult validation = |
198 phone_util->IsPossibleNumberWithReason(i18n_number); | 198 phone_util->IsPossibleNumberWithReason(i18n_number); |
199 if (validation != i18n::phonenumbers::PhoneNumberUtil::IS_POSSIBLE) | 199 if (validation != PhoneNumberUtil::IS_POSSIBLE) |
200 return false; | 200 return false; |
201 | 201 |
202 // This verifies that number has a valid area code (that in some cases could | 202 // This verifies that number has a valid area code (that in some cases could |
203 // be empty) for parsed country code. Also verifies that this is a valid | 203 // be empty) for parsed country code. Also verifies that this is a valid |
204 // number (in US 1234567 is not valid, because numbers do not start with 1). | 204 // number (in US 1234567 is not valid, because numbers do not start with 1). |
205 if (!phone_util->IsValidNumber(i18n_number)) | 205 if (!phone_util->IsValidNumber(i18n_number)) |
206 return false; | 206 return false; |
207 | 207 |
208 std::string formatted_number; | 208 std::string formatted_number; |
209 | 209 |
210 phone_util->Format(i18n_number, UtilsTypeToPhoneLibType(phone_format), | 210 phone_util->Format(i18n_number, UtilsTypeToPhoneLibType(phone_format), |
211 &formatted_number); | 211 &formatted_number); |
212 *whole_number = UTF8ToUTF16(formatted_number); | 212 *whole_number = UTF8ToUTF16(formatted_number); |
213 return true; | 213 return true; |
214 } | 214 } |
215 | 215 |
216 bool PhoneNumbersMatch(const string16& number_a, | 216 bool PhoneNumbersMatch(const string16& number_a, |
217 const string16& number_b, | 217 const string16& number_b, |
218 const std::string& raw_region) { | 218 const std::string& raw_region) { |
219 // Sanitize the provided |country_code| before trying to use it for parsing. | 219 // Sanitize the provided |country_code| before trying to use it for parsing. |
220 const std::string region = SanitizeRegion(raw_region); | 220 const std::string region = SanitizeRegion(raw_region); |
221 | 221 |
222 PhoneNumberUtil* phone_util = PhoneNumberUtil::GetInstance(); | 222 PhoneNumberUtil* phone_util = PhoneNumberUtil::GetInstance(); |
223 | 223 |
224 // Parse phone numbers based on the region | 224 // Parse phone numbers based on the region |
225 PhoneNumber i18n_number1; | 225 PhoneNumber i18n_number1; |
226 if (phone_util->Parse(UTF16ToUTF8(number_a), region.c_str(), &i18n_number1) != | 226 if (phone_util->Parse(UTF16ToUTF8(number_a), region.c_str(), &i18n_number1) != |
227 i18n::phonenumbers::PhoneNumberUtil::NO_PARSING_ERROR) { | 227 PhoneNumberUtil::NO_PARSING_ERROR) { |
228 return false; | 228 return false; |
229 } | 229 } |
230 | 230 |
231 PhoneNumber i18n_number2; | 231 PhoneNumber i18n_number2; |
232 if (phone_util->Parse(UTF16ToUTF8(number_b), region.c_str(), &i18n_number2) != | 232 if (phone_util->Parse(UTF16ToUTF8(number_b), region.c_str(), &i18n_number2) != |
233 i18n::phonenumbers::PhoneNumberUtil::NO_PARSING_ERROR) { | 233 PhoneNumberUtil::NO_PARSING_ERROR) { |
234 return false; | 234 return false; |
235 } | 235 } |
236 | 236 |
237 switch (phone_util->IsNumberMatch(i18n_number1, i18n_number2)) { | 237 switch (phone_util->IsNumberMatch(i18n_number1, i18n_number2)) { |
238 case i18n::phonenumbers::PhoneNumberUtil::INVALID_NUMBER: | 238 case PhoneNumberUtil::INVALID_NUMBER: |
239 case i18n::phonenumbers::PhoneNumberUtil::NO_MATCH: | 239 case PhoneNumberUtil::NO_MATCH: |
240 return false; | 240 return false; |
241 case i18n::phonenumbers::PhoneNumberUtil::SHORT_NSN_MATCH: | 241 case PhoneNumberUtil::SHORT_NSN_MATCH: |
242 return false; | 242 return false; |
243 case i18n::phonenumbers::PhoneNumberUtil::NSN_MATCH: | 243 case PhoneNumberUtil::NSN_MATCH: |
244 case i18n::phonenumbers::PhoneNumberUtil::EXACT_MATCH: | 244 case PhoneNumberUtil::EXACT_MATCH: |
245 return true; | 245 return true; |
246 default: | 246 default: |
247 NOTREACHED(); | 247 NOTREACHED(); |
| 248 return false; |
248 } | 249 } |
249 | |
250 return false; | |
251 } | 250 } |
252 | 251 |
253 PhoneObject::PhoneObject(const string16& number, const std::string& region) | 252 PhoneObject::PhoneObject(const string16& number, const std::string& region) |
254 : region_(SanitizeRegion(region)), | 253 : region_(SanitizeRegion(region)), |
255 i18n_number_(NULL) { | 254 i18n_number_(NULL) { |
256 // TODO(isherman): Autofill profiles should always have a |region| set, but in | 255 // TODO(isherman): Autofill profiles should always have a |region| set, but in |
257 // some cases it should be marked as implicit. Otherwise, phone numbers | 256 // some cases it should be marked as implicit. Otherwise, phone numbers |
258 // might behave differently when they are synced across computers: | 257 // might behave differently when they are synced across computers: |
259 // [ http://crbug.com/100845 ]. Once the bug is fixed, add a DCHECK here to | 258 // [ http://crbug.com/100845 ]. Once the bug is fixed, add a DCHECK here to |
260 // verify. | 259 // verify. |
(...skipping 15 matching lines...) Expand all Loading... |
276 } | 275 } |
277 | 276 |
278 PhoneObject::PhoneObject() : i18n_number_(NULL) { | 277 PhoneObject::PhoneObject() : i18n_number_(NULL) { |
279 } | 278 } |
280 | 279 |
281 PhoneObject::~PhoneObject() { | 280 PhoneObject::~PhoneObject() { |
282 } | 281 } |
283 | 282 |
284 string16 PhoneObject::GetWholeNumber() const { | 283 string16 PhoneObject::GetWholeNumber() const { |
285 if (i18n_number_.get() && whole_number_.empty()) { | 284 if (i18n_number_.get() && whole_number_.empty()) { |
286 i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat format = | 285 PhoneNumberUtil::PhoneNumberFormat format = PhoneNumberUtil::INTERNATIONAL; |
287 i18n::phonenumbers::PhoneNumberUtil::INTERNATIONAL; | |
288 if (country_code_.empty()) | 286 if (country_code_.empty()) |
289 format = i18n::phonenumbers::PhoneNumberUtil::NATIONAL; | 287 format = PhoneNumberUtil::NATIONAL; |
290 | 288 |
291 std::string formatted_number; | 289 std::string formatted_number; |
292 PhoneNumberUtil* phone_util = PhoneNumberUtil::GetInstance(); | 290 PhoneNumberUtil* phone_util = PhoneNumberUtil::GetInstance(); |
293 phone_util->Format(*i18n_number_, format, &formatted_number); | 291 phone_util->Format(*i18n_number_, format, &formatted_number); |
294 whole_number_ = UTF8ToUTF16(formatted_number); | 292 whole_number_ = UTF8ToUTF16(formatted_number); |
295 } | 293 } |
296 return whole_number_; | 294 return whole_number_; |
297 } | 295 } |
298 | 296 |
299 PhoneObject& PhoneObject::operator=(const PhoneObject& other) { | 297 PhoneObject& PhoneObject::operator=(const PhoneObject& other) { |
300 if (this == &other) | 298 if (this == &other) |
301 return *this; | 299 return *this; |
302 | 300 |
303 country_code_ = other.country_code_; | 301 country_code_ = other.country_code_; |
304 city_code_ = other.city_code_; | 302 city_code_ = other.city_code_; |
305 number_ = other.number_; | 303 number_ = other.number_; |
306 region_ = other.region_; | 304 region_ = other.region_; |
307 if (other.i18n_number_.get()) | 305 if (other.i18n_number_.get()) |
308 i18n_number_.reset(new PhoneNumber(*other.i18n_number_)); | 306 i18n_number_.reset(new PhoneNumber(*other.i18n_number_)); |
309 | 307 |
310 return *this; | 308 return *this; |
311 } | 309 } |
312 | 310 |
313 } // namespace autofill_i18n | 311 } // namespace autofill_i18n |
OLD | NEW |