| 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 "components/autofill/browser/phone_number_i18n.h" | 5 #include "components/autofill/browser/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/string_util.h" | 9 #include "base/string_util.h" |
| 10 #include "base/stringprintf.h" | 10 #include "base/stringprintf.h" |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 | 44 |
| 45 // Formats the given |number| as a human-readable string, and writes the result | 45 // Formats the given |number| as a human-readable string, and writes the result |
| 46 // into |formatted_number|. Also, normalizes the formatted number, and writes | 46 // into |formatted_number|. Also, normalizes the formatted number, and writes |
| 47 // that result into |normalized_number|. This function should only be called | 47 // that result into |normalized_number|. This function should only be called |
| 48 // with numbers already known to be valid, i.e. validation should be done prior | 48 // with numbers already known to be valid, i.e. validation should be done prior |
| 49 // to calling this function. Note that the |country_code|, which determines | 49 // to calling this function. Note that the |country_code|, which determines |
| 50 // whether to format in the national or in the international format, is passed | 50 // whether to format in the national or in the international format, is passed |
| 51 // in explicitly, as |number| might have an implicit country code set, even | 51 // in explicitly, as |number| might have an implicit country code set, even |
| 52 // though the original input lacked a country code. | 52 // though the original input lacked a country code. |
| 53 void FormatValidatedNumber(const PhoneNumber& number, | 53 void FormatValidatedNumber(const PhoneNumber& number, |
| 54 const string16& country_code, | 54 const base::string16& country_code, |
| 55 string16* formatted_number, | 55 base::string16* formatted_number, |
| 56 string16* normalized_number) { | 56 base::string16* normalized_number) { |
| 57 PhoneNumberUtil::PhoneNumberFormat format = | 57 PhoneNumberUtil::PhoneNumberFormat format = |
| 58 country_code.empty() ? | 58 country_code.empty() ? |
| 59 PhoneNumberUtil::NATIONAL : | 59 PhoneNumberUtil::NATIONAL : |
| 60 PhoneNumberUtil::INTERNATIONAL; | 60 PhoneNumberUtil::INTERNATIONAL; |
| 61 | 61 |
| 62 PhoneNumberUtil* phone_util = PhoneNumberUtil::GetInstance(); | 62 PhoneNumberUtil* phone_util = PhoneNumberUtil::GetInstance(); |
| 63 std::string processed_number; | 63 std::string processed_number; |
| 64 phone_util->Format(number, format, &processed_number); | 64 phone_util->Format(number, format, &processed_number); |
| 65 | 65 |
| 66 if (formatted_number) | 66 if (formatted_number) |
| 67 *formatted_number = UTF8ToUTF16(processed_number); | 67 *formatted_number = UTF8ToUTF16(processed_number); |
| 68 | 68 |
| 69 if (normalized_number) { | 69 if (normalized_number) { |
| 70 phone_util->NormalizeDigitsOnly(&processed_number); | 70 phone_util->NormalizeDigitsOnly(&processed_number); |
| 71 *normalized_number = UTF8ToUTF16(processed_number); | 71 *normalized_number = UTF8ToUTF16(processed_number); |
| 72 } | 72 } |
| 73 } | 73 } |
| 74 | 74 |
| 75 } // namespace | 75 } // namespace |
| 76 | 76 |
| 77 namespace autofill_i18n { | 77 namespace autofill_i18n { |
| 78 | 78 |
| 79 // Parses the number stored in |value| as it should be interpreted in the given | 79 // Parses the number stored in |value| as it should be interpreted in the given |
| 80 // |region|, and stores the results into the remaining arguments. The |region| | 80 // |region|, and stores the results into the remaining arguments. The |region| |
| 81 // should be sanitized prior to calling this function. | 81 // should be sanitized prior to calling this function. |
| 82 bool ParsePhoneNumber(const string16& value, | 82 bool ParsePhoneNumber(const base::string16& value, |
| 83 const std::string& region, | 83 const std::string& region, |
| 84 string16* country_code, | 84 base::string16* country_code, |
| 85 string16* city_code, | 85 base::string16* city_code, |
| 86 string16* number, | 86 base::string16* number, |
| 87 PhoneNumber* i18n_number) { | 87 PhoneNumber* i18n_number) { |
| 88 country_code->clear(); | 88 country_code->clear(); |
| 89 city_code->clear(); | 89 city_code->clear(); |
| 90 number->clear(); | 90 number->clear(); |
| 91 *i18n_number = PhoneNumber(); | 91 *i18n_number = PhoneNumber(); |
| 92 | 92 |
| 93 std::string number_text(UTF16ToUTF8(value)); | 93 std::string number_text(UTF16ToUTF8(value)); |
| 94 | 94 |
| 95 // Parse phone number based on the region. | 95 // Parse phone number based on the region. |
| 96 PhoneNumberUtil* phone_util = PhoneNumberUtil::GetInstance(); | 96 PhoneNumberUtil* phone_util = PhoneNumberUtil::GetInstance(); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 121 std::string area_code; | 121 std::string area_code; |
| 122 std::string subscriber_number; | 122 std::string subscriber_number; |
| 123 if (area_length > 0) { | 123 if (area_length > 0) { |
| 124 area_code = national_significant_number.substr(0, area_length); | 124 area_code = national_significant_number.substr(0, area_length); |
| 125 subscriber_number = national_significant_number.substr(area_length); | 125 subscriber_number = national_significant_number.substr(area_length); |
| 126 } else { | 126 } else { |
| 127 subscriber_number = national_significant_number; | 127 subscriber_number = national_significant_number; |
| 128 } | 128 } |
| 129 *number = UTF8ToUTF16(subscriber_number); | 129 *number = UTF8ToUTF16(subscriber_number); |
| 130 *city_code = UTF8ToUTF16(area_code); | 130 *city_code = UTF8ToUTF16(area_code); |
| 131 *country_code = string16(); | 131 *country_code = base::string16(); |
| 132 | 132 |
| 133 phone_util->NormalizeDigitsOnly(&number_text); | 133 phone_util->NormalizeDigitsOnly(&number_text); |
| 134 string16 normalized_number(UTF8ToUTF16(number_text)); | 134 base::string16 normalized_number(UTF8ToUTF16(number_text)); |
| 135 | 135 |
| 136 // Check if parsed number has a country code that was not inferred from the | 136 // Check if parsed number has a country code that was not inferred from the |
| 137 // region. | 137 // region. |
| 138 if (i18n_number->has_country_code()) { | 138 if (i18n_number->has_country_code()) { |
| 139 *country_code = UTF8ToUTF16( | 139 *country_code = UTF8ToUTF16( |
| 140 base::StringPrintf("%d", i18n_number->country_code())); | 140 base::StringPrintf("%d", i18n_number->country_code())); |
| 141 if (normalized_number.length() <= national_significant_number.length() && | 141 if (normalized_number.length() <= national_significant_number.length() && |
| 142 !StartsWith(normalized_number, *country_code, | 142 !StartsWith(normalized_number, *country_code, |
| 143 true /* case_sensitive */)) { | 143 true /* case_sensitive */)) { |
| 144 country_code->clear(); | 144 country_code->clear(); |
| 145 } | 145 } |
| 146 } | 146 } |
| 147 | 147 |
| 148 return true; | 148 return true; |
| 149 } | 149 } |
| 150 | 150 |
| 151 string16 NormalizePhoneNumber(const string16& value, | 151 base::string16 NormalizePhoneNumber(const base::string16& value, |
| 152 const std::string& region) { | 152 const std::string& region) { |
| 153 DCHECK_EQ(2u, region.size()); | 153 DCHECK_EQ(2u, region.size()); |
| 154 string16 country_code; | 154 base::string16 country_code; |
| 155 string16 unused_city_code; | 155 base::string16 unused_city_code; |
| 156 string16 unused_number; | 156 base::string16 unused_number; |
| 157 PhoneNumber phone_number; | 157 PhoneNumber phone_number; |
| 158 if (!ParsePhoneNumber(value, region, &country_code, &unused_city_code, | 158 if (!ParsePhoneNumber(value, region, &country_code, &unused_city_code, |
| 159 &unused_number, &phone_number)) { | 159 &unused_number, &phone_number)) { |
| 160 return string16(); // Parsing failed - do not store phone. | 160 return base::string16(); // Parsing failed - do not store phone. |
| 161 } | 161 } |
| 162 | 162 |
| 163 string16 normalized_number; | 163 base::string16 normalized_number; |
| 164 FormatValidatedNumber(phone_number, country_code, NULL, &normalized_number); | 164 FormatValidatedNumber(phone_number, country_code, NULL, &normalized_number); |
| 165 return normalized_number; | 165 return normalized_number; |
| 166 } | 166 } |
| 167 | 167 |
| 168 bool ConstructPhoneNumber(const string16& country_code, | 168 bool ConstructPhoneNumber(const base::string16& country_code, |
| 169 const string16& city_code, | 169 const base::string16& city_code, |
| 170 const string16& number, | 170 const base::string16& number, |
| 171 const std::string& region, | 171 const std::string& region, |
| 172 string16* whole_number) { | 172 base::string16* whole_number) { |
| 173 DCHECK_EQ(2u, region.size()); | 173 DCHECK_EQ(2u, region.size()); |
| 174 whole_number->clear(); | 174 whole_number->clear(); |
| 175 | 175 |
| 176 string16 unused_country_code; | 176 base::string16 unused_country_code; |
| 177 string16 unused_city_code; | 177 base::string16 unused_city_code; |
| 178 string16 unused_number; | 178 base::string16 unused_number; |
| 179 PhoneNumber phone_number; | 179 PhoneNumber phone_number; |
| 180 if (!ParsePhoneNumber(country_code + city_code + number, region, | 180 if (!ParsePhoneNumber(country_code + city_code + number, region, |
| 181 &unused_country_code, &unused_city_code, &unused_number, | 181 &unused_country_code, &unused_city_code, &unused_number, |
| 182 &phone_number)) { | 182 &phone_number)) { |
| 183 return false; | 183 return false; |
| 184 } | 184 } |
| 185 | 185 |
| 186 FormatValidatedNumber(phone_number, country_code, whole_number, NULL); | 186 FormatValidatedNumber(phone_number, country_code, whole_number, NULL); |
| 187 return true; | 187 return true; |
| 188 } | 188 } |
| 189 | 189 |
| 190 bool PhoneNumbersMatch(const string16& number_a, | 190 bool PhoneNumbersMatch(const base::string16& number_a, |
| 191 const string16& number_b, | 191 const base::string16& number_b, |
| 192 const std::string& raw_region, | 192 const std::string& raw_region, |
| 193 const std::string& app_locale) { | 193 const std::string& app_locale) { |
| 194 // Sanitize the provided |raw_region| before trying to use it for parsing. | 194 // Sanitize the provided |raw_region| before trying to use it for parsing. |
| 195 const std::string region = SanitizeRegion(raw_region, app_locale); | 195 const std::string region = SanitizeRegion(raw_region, app_locale); |
| 196 | 196 |
| 197 PhoneNumberUtil* phone_util = PhoneNumberUtil::GetInstance(); | 197 PhoneNumberUtil* phone_util = PhoneNumberUtil::GetInstance(); |
| 198 | 198 |
| 199 // Parse phone numbers based on the region | 199 // Parse phone numbers based on the region |
| 200 PhoneNumber i18n_number1; | 200 PhoneNumber i18n_number1; |
| 201 if (phone_util->Parse(UTF16ToUTF8(number_a), region.c_str(), &i18n_number1) != | 201 if (phone_util->Parse(UTF16ToUTF8(number_a), region.c_str(), &i18n_number1) != |
| (...skipping 15 matching lines...) Expand all Loading... |
| 217 return false; | 217 return false; |
| 218 case PhoneNumberUtil::NSN_MATCH: | 218 case PhoneNumberUtil::NSN_MATCH: |
| 219 case PhoneNumberUtil::EXACT_MATCH: | 219 case PhoneNumberUtil::EXACT_MATCH: |
| 220 return true; | 220 return true; |
| 221 } | 221 } |
| 222 | 222 |
| 223 NOTREACHED(); | 223 NOTREACHED(); |
| 224 return false; | 224 return false; |
| 225 } | 225 } |
| 226 | 226 |
| 227 PhoneObject::PhoneObject(const string16& number, | 227 PhoneObject::PhoneObject(const base::string16& number, |
| 228 const std::string& region) | 228 const std::string& region) |
| 229 : region_(region), | 229 : region_(region), |
| 230 i18n_number_(NULL) { | 230 i18n_number_(NULL) { |
| 231 DCHECK_EQ(2u, region.size()); | 231 DCHECK_EQ(2u, region.size()); |
| 232 // TODO(isherman): Autofill profiles should always have a |region| set, but in | 232 // TODO(isherman): Autofill profiles should always have a |region| set, but in |
| 233 // some cases it should be marked as implicit. Otherwise, phone numbers | 233 // some cases it should be marked as implicit. Otherwise, phone numbers |
| 234 // might behave differently when they are synced across computers: | 234 // might behave differently when they are synced across computers: |
| 235 // [ http://crbug.com/100845 ]. Once the bug is fixed, add a DCHECK here to | 235 // [ http://crbug.com/100845 ]. Once the bug is fixed, add a DCHECK here to |
| 236 // verify. | 236 // verify. |
| 237 | 237 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 251 PhoneObject::PhoneObject(const PhoneObject& other) : i18n_number_(NULL) { | 251 PhoneObject::PhoneObject(const PhoneObject& other) : i18n_number_(NULL) { |
| 252 *this = other; | 252 *this = other; |
| 253 } | 253 } |
| 254 | 254 |
| 255 PhoneObject::PhoneObject() : i18n_number_(NULL) { | 255 PhoneObject::PhoneObject() : i18n_number_(NULL) { |
| 256 } | 256 } |
| 257 | 257 |
| 258 PhoneObject::~PhoneObject() { | 258 PhoneObject::~PhoneObject() { |
| 259 } | 259 } |
| 260 | 260 |
| 261 string16 PhoneObject::GetFormattedNumber() const { | 261 base::string16 PhoneObject::GetFormattedNumber() const { |
| 262 if (i18n_number_ && formatted_number_.empty()) { | 262 if (i18n_number_ && formatted_number_.empty()) { |
| 263 FormatValidatedNumber(*i18n_number_, country_code_, &formatted_number_, | 263 FormatValidatedNumber(*i18n_number_, country_code_, &formatted_number_, |
| 264 &whole_number_); | 264 &whole_number_); |
| 265 } | 265 } |
| 266 | 266 |
| 267 return formatted_number_; | 267 return formatted_number_; |
| 268 } | 268 } |
| 269 | 269 |
| 270 string16 PhoneObject::GetWholeNumber() const { | 270 base::string16 PhoneObject::GetWholeNumber() const { |
| 271 if (i18n_number_ && whole_number_.empty()) { | 271 if (i18n_number_ && whole_number_.empty()) { |
| 272 FormatValidatedNumber(*i18n_number_, country_code_, &formatted_number_, | 272 FormatValidatedNumber(*i18n_number_, country_code_, &formatted_number_, |
| 273 &whole_number_); | 273 &whole_number_); |
| 274 } | 274 } |
| 275 | 275 |
| 276 return whole_number_; | 276 return whole_number_; |
| 277 } | 277 } |
| 278 | 278 |
| 279 PhoneObject& PhoneObject::operator=(const PhoneObject& other) { | 279 PhoneObject& PhoneObject::operator=(const PhoneObject& other) { |
| 280 if (this == &other) | 280 if (this == &other) |
| (...skipping 10 matching lines...) Expand all Loading... |
| 291 city_code_ = other.city_code_; | 291 city_code_ = other.city_code_; |
| 292 number_ = other.number_; | 292 number_ = other.number_; |
| 293 | 293 |
| 294 formatted_number_ = other.formatted_number_; | 294 formatted_number_ = other.formatted_number_; |
| 295 whole_number_ = other.whole_number_; | 295 whole_number_ = other.whole_number_; |
| 296 | 296 |
| 297 return *this; | 297 return *this; |
| 298 } | 298 } |
| 299 | 299 |
| 300 } // namespace autofill_i18n | 300 } // namespace autofill_i18n |
| OLD | NEW |