| 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.h" | 5 #include "chrome/browser/autofill/phone_number.h" |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/string_number_conversions.h" | 8 #include "base/string_number_conversions.h" |
| 9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 10 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 | 33 |
| 34 const int kAutofillPhoneLength = arraysize(kAutofillPhoneTypes); | 34 const int kAutofillPhoneLength = arraysize(kAutofillPhoneTypes); |
| 35 | 35 |
| 36 void StripPunctuation(string16* number) { | 36 void StripPunctuation(string16* number) { |
| 37 RemoveChars(*number, kPhoneNumberSeparators, number); | 37 RemoveChars(*number, kPhoneNumberSeparators, number); |
| 38 } | 38 } |
| 39 | 39 |
| 40 } // namespace | 40 } // namespace |
| 41 | 41 |
| 42 PhoneNumber::PhoneNumber(AutofillProfile* profile) | 42 PhoneNumber::PhoneNumber(AutofillProfile* profile) |
| 43 : phone_group_(AutofillType::NO_GROUP), | 43 : profile_(profile) { |
| 44 profile_(profile) { | |
| 45 } | |
| 46 | |
| 47 PhoneNumber::PhoneNumber(AutofillType::FieldTypeGroup phone_group, | |
| 48 AutofillProfile* profile) | |
| 49 : phone_group_(phone_group), | |
| 50 profile_(profile) { | |
| 51 } | 44 } |
| 52 | 45 |
| 53 PhoneNumber::PhoneNumber(const PhoneNumber& number) : FormGroup() { | 46 PhoneNumber::PhoneNumber(const PhoneNumber& number) : FormGroup() { |
| 54 *this = number; | 47 *this = number; |
| 55 } | 48 } |
| 56 | 49 |
| 57 PhoneNumber::~PhoneNumber() {} | 50 PhoneNumber::~PhoneNumber() {} |
| 58 | 51 |
| 59 PhoneNumber& PhoneNumber::operator=(const PhoneNumber& number) { | 52 PhoneNumber& PhoneNumber::operator=(const PhoneNumber& number) { |
| 60 if (this == &number) | 53 if (this == &number) |
| 61 return *this; | 54 return *this; |
| 62 phone_group_ = number.phone_group_; | 55 |
| 63 number_ = number.number_; | 56 number_ = number.number_; |
| 64 profile_ = number.profile_; | 57 profile_ = number.profile_; |
| 65 cached_parsed_phone_ = number.cached_parsed_phone_; | 58 cached_parsed_phone_ = number.cached_parsed_phone_; |
| 66 return *this; | 59 return *this; |
| 67 } | 60 } |
| 68 | 61 |
| 69 void PhoneNumber::GetSupportedTypes(FieldTypeSet* supported_types) const { | 62 void PhoneNumber::GetSupportedTypes(FieldTypeSet* supported_types) const { |
| 70 supported_types->insert(GetWholeNumberType()); | 63 supported_types->insert(PHONE_HOME_WHOLE_NUMBER); |
| 71 supported_types->insert(GetNumberType()); | 64 supported_types->insert(PHONE_HOME_NUMBER); |
| 72 supported_types->insert(GetCityCodeType()); | 65 supported_types->insert(PHONE_HOME_CITY_CODE); |
| 73 supported_types->insert(GetCityAndNumberType()); | 66 supported_types->insert(PHONE_HOME_CITY_AND_NUMBER); |
| 74 supported_types->insert(GetCountryCodeType()); | 67 supported_types->insert(PHONE_HOME_COUNTRY_CODE); |
| 75 } | 68 } |
| 76 | 69 |
| 77 string16 PhoneNumber::GetInfo(AutofillFieldType type) const { | 70 string16 PhoneNumber::GetInfo(AutofillFieldType type) const { |
| 78 if (type == GetWholeNumberType()) | 71 if (type == PHONE_HOME_WHOLE_NUMBER) |
| 79 return number_; | 72 return number_; |
| 80 | 73 |
| 81 UpdateCacheIfNeeded(); | 74 UpdateCacheIfNeeded(); |
| 82 if (!cached_parsed_phone_.IsValidNumber()) | 75 if (!cached_parsed_phone_.IsValidNumber()) |
| 83 return string16(); | 76 return string16(); |
| 84 | 77 |
| 85 if (type == GetNumberType()) | 78 if (type == PHONE_HOME_NUMBER) |
| 86 return cached_parsed_phone_.GetNumber(); | 79 return cached_parsed_phone_.GetNumber(); |
| 87 | 80 |
| 88 if (type == GetCityCodeType()) | 81 if (type == PHONE_HOME_CITY_CODE) |
| 89 return cached_parsed_phone_.GetCityCode(); | 82 return cached_parsed_phone_.GetCityCode(); |
| 90 | 83 |
| 91 if (type == GetCountryCodeType()) | 84 if (type == PHONE_HOME_COUNTRY_CODE) |
| 92 return cached_parsed_phone_.GetCountryCode(); | 85 return cached_parsed_phone_.GetCountryCode(); |
| 93 | 86 |
| 94 if (type == GetCityAndNumberType()) { | 87 if (type == PHONE_HOME_CITY_AND_NUMBER) { |
| 95 string16 city_and_local(cached_parsed_phone_.GetCityCode()); | 88 string16 city_and_local(cached_parsed_phone_.GetCityCode()); |
| 96 city_and_local.append(cached_parsed_phone_.GetNumber()); | 89 city_and_local.append(cached_parsed_phone_.GetNumber()); |
| 97 return city_and_local; | 90 return city_and_local; |
| 98 } | 91 } |
| 99 | 92 |
| 100 return string16(); | 93 return string16(); |
| 101 } | 94 } |
| 102 | 95 |
| 103 void PhoneNumber::SetInfo(AutofillFieldType type, const string16& value) { | 96 void PhoneNumber::SetInfo(AutofillFieldType type, const string16& value) { |
| 104 // Store the group the first time we set some info. | |
| 105 if (phone_group_ == AutofillType::NO_GROUP) | |
| 106 phone_group_ = AutofillType(type).group(); | |
| 107 | |
| 108 FieldTypeSubGroup subgroup = AutofillType(type).subgroup(); | 97 FieldTypeSubGroup subgroup = AutofillType(type).subgroup(); |
| 109 if (subgroup != AutofillType::PHONE_CITY_AND_NUMBER && | 98 if (subgroup != AutofillType::PHONE_CITY_AND_NUMBER && |
| 110 subgroup != AutofillType::PHONE_WHOLE_NUMBER) { | 99 subgroup != AutofillType::PHONE_WHOLE_NUMBER) { |
| 111 // Only full phone numbers should be set directly. The remaining field | 100 // Only full phone numbers should be set directly. The remaining field |
| 112 // field types are read-only. | 101 // field types are read-only. |
| 113 return; | 102 return; |
| 114 } | 103 } |
| 115 | 104 |
| 116 number_ = value; | 105 number_ = value; |
| 117 cached_parsed_phone_ = autofill_i18n::PhoneObject(number_, locale()); | 106 cached_parsed_phone_ = autofill_i18n::PhoneObject(number_, locale()); |
| 118 } | 107 } |
| 119 | 108 |
| 120 // Normalize phones if |type| is a whole number: | 109 // Normalize phones if |type| is a whole number: |
| 121 // (650)2345678 -> 6502345678 | 110 // (650)2345678 -> 6502345678 |
| 122 // 1-800-FLOWERS -> 18003569377 | 111 // 1-800-FLOWERS -> 18003569377 |
| 123 // If the phone cannot be normalized, returns the stored value verbatim. | 112 // If the phone cannot be normalized, returns the stored value verbatim. |
| 124 string16 PhoneNumber::GetCanonicalizedInfo(AutofillFieldType type) const { | 113 string16 PhoneNumber::GetCanonicalizedInfo(AutofillFieldType type) const { |
| 125 string16 phone = GetInfo(type); | 114 string16 phone = GetInfo(type); |
| 126 if (type != GetWholeNumberType()) | 115 if (type != PHONE_HOME_WHOLE_NUMBER) |
| 127 return phone; | 116 return phone; |
| 128 | 117 |
| 129 string16 normalized_phone = autofill_i18n::NormalizePhoneNumber(phone, | 118 string16 normalized_phone = autofill_i18n::NormalizePhoneNumber(phone, |
| 130 locale()); | 119 locale()); |
| 131 if (!normalized_phone.empty()) | 120 if (!normalized_phone.empty()) |
| 132 return normalized_phone; | 121 return normalized_phone; |
| 133 | 122 |
| 134 return phone; | 123 return phone; |
| 135 } | 124 } |
| 136 | 125 |
| 137 bool PhoneNumber::SetCanonicalizedInfo(AutofillFieldType type, | 126 bool PhoneNumber::SetCanonicalizedInfo(AutofillFieldType type, |
| 138 const string16& value) { | 127 const string16& value) { |
| 139 string16 number = value; | 128 string16 number = value; |
| 140 StripPunctuation(&number); | 129 StripPunctuation(&number); |
| 141 SetInfo(type, number); | 130 SetInfo(type, number); |
| 142 | 131 |
| 143 return NormalizePhone(); | 132 return NormalizePhone(); |
| 144 } | 133 } |
| 145 | 134 |
| 146 void PhoneNumber::GetMatchingTypes(const string16& text, | 135 void PhoneNumber::GetMatchingTypes(const string16& text, |
| 147 FieldTypeSet* matching_types) const { | 136 FieldTypeSet* matching_types) const { |
| 148 string16 stripped_text = text; | 137 string16 stripped_text = text; |
| 149 StripPunctuation(&stripped_text); | 138 StripPunctuation(&stripped_text); |
| 150 FormGroup::GetMatchingTypes(stripped_text, matching_types); | 139 FormGroup::GetMatchingTypes(stripped_text, matching_types); |
| 151 | 140 |
| 152 // For US numbers, also compare to the three-digit prefix and the four-digit | 141 // For US numbers, also compare to the three-digit prefix and the four-digit |
| 153 // suffix, since websites often split numbers into these two fields. | 142 // suffix, since web sites often split numbers into these two fields. |
| 154 string16 number = GetCanonicalizedInfo(GetNumberType()); | 143 string16 number = GetCanonicalizedInfo(PHONE_HOME_NUMBER); |
| 155 if (locale() == "US" && number.size() == (kPrefixLength + kSuffixLength)) { | 144 if (locale() == "US" && number.size() == (kPrefixLength + kSuffixLength)) { |
| 156 string16 prefix = number.substr(kPrefixOffset, kPrefixLength); | 145 string16 prefix = number.substr(kPrefixOffset, kPrefixLength); |
| 157 string16 suffix = number.substr(kSuffixOffset, kSuffixLength); | 146 string16 suffix = number.substr(kSuffixOffset, kSuffixLength); |
| 158 if (text == prefix || text == suffix) | 147 if (text == prefix || text == suffix) |
| 159 matching_types->insert(GetNumberType()); | 148 matching_types->insert(PHONE_HOME_NUMBER); |
| 160 } | 149 } |
| 161 | 150 |
| 162 string16 whole_number = GetCanonicalizedInfo(GetWholeNumberType()); | 151 string16 whole_number = GetCanonicalizedInfo(PHONE_HOME_WHOLE_NUMBER); |
| 163 if (!whole_number.empty() && | 152 if (!whole_number.empty() && |
| 164 autofill_i18n::NormalizePhoneNumber(text, locale()) == whole_number) { | 153 autofill_i18n::NormalizePhoneNumber(text, locale()) == whole_number) { |
| 165 matching_types->insert(GetWholeNumberType()); | 154 matching_types->insert(PHONE_HOME_WHOLE_NUMBER); |
| 166 } | 155 } |
| 167 } | 156 } |
| 168 | 157 |
| 169 bool PhoneNumber::NormalizePhone() { | 158 bool PhoneNumber::NormalizePhone() { |
| 170 // Empty number does not need normalization. | 159 // Empty number does not need normalization. |
| 171 if (number_.empty()) | 160 if (number_.empty()) |
| 172 return true; | 161 return true; |
| 173 | 162 |
| 174 UpdateCacheIfNeeded(); | 163 UpdateCacheIfNeeded(); |
| 175 number_ = cached_parsed_phone_.GetWholeNumber(); | 164 number_ = cached_parsed_phone_.GetWholeNumber(); |
| 176 return !number_.empty(); | 165 return !number_.empty(); |
| 177 } | 166 } |
| 178 | 167 |
| 179 std::string PhoneNumber::locale() const { | 168 std::string PhoneNumber::locale() const { |
| 180 if (!profile_) { | 169 if (!profile_) { |
| 181 NOTREACHED(); | 170 NOTREACHED(); |
| 182 return "US"; | 171 return "US"; |
| 183 } | 172 } |
| 184 | 173 |
| 185 return profile_->CountryCode(); | 174 return profile_->CountryCode(); |
| 186 } | 175 } |
| 187 | 176 |
| 188 void PhoneNumber::UpdateCacheIfNeeded() const { | 177 void PhoneNumber::UpdateCacheIfNeeded() const { |
| 189 if (!number_.empty() && cached_parsed_phone_.GetLocale() != locale()) | 178 if (!number_.empty() && cached_parsed_phone_.GetLocale() != locale()) |
| 190 cached_parsed_phone_ = autofill_i18n::PhoneObject(number_, locale()); | 179 cached_parsed_phone_ = autofill_i18n::PhoneObject(number_, locale()); |
| 191 } | 180 } |
| 192 | 181 |
| 193 AutofillFieldType PhoneNumber::GetNumberType() const { | 182 PhoneNumber::PhoneCombineHelper::PhoneCombineHelper() { |
| 194 if (phone_group_ == AutofillType::PHONE_HOME) | |
| 195 return PHONE_HOME_NUMBER; | |
| 196 else if (phone_group_ == AutofillType::PHONE_FAX) | |
| 197 return PHONE_FAX_NUMBER; | |
| 198 else | |
| 199 NOTREACHED(); | |
| 200 return UNKNOWN_TYPE; | |
| 201 } | |
| 202 | |
| 203 AutofillFieldType PhoneNumber::GetCityCodeType() const { | |
| 204 if (phone_group_ == AutofillType::PHONE_HOME) | |
| 205 return PHONE_HOME_CITY_CODE; | |
| 206 else if (phone_group_ == AutofillType::PHONE_FAX) | |
| 207 return PHONE_FAX_CITY_CODE; | |
| 208 else | |
| 209 NOTREACHED(); | |
| 210 return UNKNOWN_TYPE; | |
| 211 } | |
| 212 | |
| 213 AutofillFieldType PhoneNumber::GetCountryCodeType() const { | |
| 214 if (phone_group_ == AutofillType::PHONE_HOME) | |
| 215 return PHONE_HOME_COUNTRY_CODE; | |
| 216 else if (phone_group_ == AutofillType::PHONE_FAX) | |
| 217 return PHONE_FAX_COUNTRY_CODE; | |
| 218 else | |
| 219 NOTREACHED(); | |
| 220 return UNKNOWN_TYPE; | |
| 221 } | |
| 222 | |
| 223 AutofillFieldType PhoneNumber::GetCityAndNumberType() const { | |
| 224 if (phone_group_ == AutofillType::PHONE_HOME) | |
| 225 return PHONE_HOME_CITY_AND_NUMBER; | |
| 226 else if (phone_group_ == AutofillType::PHONE_FAX) | |
| 227 return PHONE_FAX_CITY_AND_NUMBER; | |
| 228 else | |
| 229 NOTREACHED(); | |
| 230 return UNKNOWN_TYPE; | |
| 231 } | |
| 232 | |
| 233 AutofillFieldType PhoneNumber::GetWholeNumberType() const { | |
| 234 if (phone_group_ == AutofillType::PHONE_HOME) | |
| 235 return PHONE_HOME_WHOLE_NUMBER; | |
| 236 else if (phone_group_ == AutofillType::PHONE_FAX) | |
| 237 return PHONE_FAX_WHOLE_NUMBER; | |
| 238 else | |
| 239 NOTREACHED(); | |
| 240 return UNKNOWN_TYPE; | |
| 241 } | |
| 242 | |
| 243 PhoneNumber::PhoneCombineHelper::PhoneCombineHelper( | |
| 244 AutofillType::FieldTypeGroup phone_group) | |
| 245 : phone_group_(phone_group) { | |
| 246 } | 183 } |
| 247 | 184 |
| 248 PhoneNumber::PhoneCombineHelper::~PhoneCombineHelper() { | 185 PhoneNumber::PhoneCombineHelper::~PhoneCombineHelper() { |
| 249 } | 186 } |
| 250 | 187 |
| 251 bool PhoneNumber::PhoneCombineHelper::SetInfo(AutofillFieldType field_type, | 188 bool PhoneNumber::PhoneCombineHelper::SetInfo(AutofillFieldType field_type, |
| 252 const string16& value) { | 189 const string16& value) { |
| 253 PhoneNumber temp(phone_group_, NULL); | 190 if (field_type == PHONE_HOME_COUNTRY_CODE) { |
| 254 | |
| 255 if (field_type == temp.GetCountryCodeType()) { | |
| 256 country_ = value; | 191 country_ = value; |
| 257 return true; | 192 return true; |
| 258 } | 193 } |
| 259 | 194 |
| 260 if (field_type == temp.GetCityCodeType()) { | 195 if (field_type == PHONE_HOME_CITY_CODE) { |
| 261 city_ = value; | 196 city_ = value; |
| 262 return true; | 197 return true; |
| 263 } | 198 } |
| 264 | 199 |
| 265 if (field_type == temp.GetCityAndNumberType()) { | 200 if (field_type == PHONE_HOME_CITY_AND_NUMBER) { |
| 266 phone_ = value; | 201 phone_ = value; |
| 267 return true; | 202 return true; |
| 268 } | 203 } |
| 269 | 204 |
| 270 if (field_type == temp.GetWholeNumberType()) { | 205 if (field_type == PHONE_HOME_WHOLE_NUMBER) { |
| 271 whole_number_ = value; | 206 whole_number_ = value; |
| 272 return true; | 207 return true; |
| 273 } | 208 } |
| 274 | 209 |
| 275 if (field_type == temp.GetNumberType()) { | 210 if (field_type == PHONE_HOME_NUMBER) { |
| 276 phone_.append(value); | 211 phone_.append(value); |
| 277 return true; | 212 return true; |
| 278 } | 213 } |
| 279 | 214 |
| 280 return false; | 215 return false; |
| 281 } | 216 } |
| 282 | 217 |
| 283 bool PhoneNumber::PhoneCombineHelper::ParseNumber(const std::string& locale, | 218 bool PhoneNumber::PhoneCombineHelper::ParseNumber(const std::string& locale, |
| 284 string16* value) { | 219 string16* value) { |
| 285 if (!whole_number_.empty()) { | 220 if (!whole_number_.empty()) { |
| 286 *value = whole_number_; | 221 *value = whole_number_; |
| 287 return true; | 222 return true; |
| 288 } | 223 } |
| 289 | 224 |
| 290 return autofill_i18n::ConstructPhoneNumber( | 225 return autofill_i18n::ConstructPhoneNumber( |
| 291 country_, city_, phone_, | 226 country_, city_, phone_, |
| 292 locale, | 227 locale, |
| 293 (country_.empty() ? | 228 (country_.empty() ? |
| 294 autofill_i18n::NATIONAL : autofill_i18n::INTERNATIONAL), | 229 autofill_i18n::NATIONAL : autofill_i18n::INTERNATIONAL), |
| 295 value); | 230 value); |
| 296 } | 231 } |
| 297 | 232 |
| 298 bool PhoneNumber::PhoneCombineHelper::IsEmpty() const { | 233 bool PhoneNumber::PhoneCombineHelper::IsEmpty() const { |
| 299 return phone_.empty() && whole_number_.empty(); | 234 return phone_.empty() && whole_number_.empty(); |
| 300 } | 235 } |
| OLD | NEW |