| 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 |