blob: 72b5517065f74a4e5f3cdc90eefbb58a5a0605b0 [file] [log] [blame]
[email protected]7b37fbb2011-03-07 16:16:031// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]3db3ff62010-01-07 00:35:392// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/autofill/phone_number.h"
6
7#include "base/basictypes.h"
[email protected]11c2bdd12011-05-23 18:24:328#include "base/string_number_conversions.h"
[email protected]3db3ff62010-01-07 00:35:399#include "base/string_util.h"
[email protected]11c2bdd12011-05-23 18:24:3210#include "base/utf_string_conversions.h"
[email protected]9b435be92010-03-04 21:20:1511#include "chrome/browser/autofill/autofill_profile.h"
[email protected]3db3ff62010-01-07 00:35:3912#include "chrome/browser/autofill/autofill_type.h"
13#include "chrome/browser/autofill/field_types.h"
[email protected]11c2bdd12011-05-23 18:24:3214#include "chrome/browser/autofill/phone_number_i18n.h"
[email protected]3db3ff62010-01-07 00:35:3915
[email protected]9b435be92010-03-04 21:20:1516namespace {
[email protected]3db3ff62010-01-07 00:35:3917
[email protected]9b435be92010-03-04 21:20:1518const char16 kPhoneNumberSeparators[] = { ' ', '.', '(', ')', '-', 0 };
19
20// The number of digits in a phone number.
21const size_t kPhoneNumberLength = 7;
22
23// The number of digits in an area code.
24const size_t kPhoneCityCodeLength = 3;
25
[email protected]663bd9e2011-03-21 01:07:0126const AutofillType::FieldTypeSubGroup kAutofillPhoneTypes[] = {
[email protected]7b37fbb2011-03-07 16:16:0327 AutofillType::PHONE_NUMBER,
28 AutofillType::PHONE_CITY_CODE,
29 AutofillType::PHONE_COUNTRY_CODE,
30 AutofillType::PHONE_CITY_AND_NUMBER,
31 AutofillType::PHONE_WHOLE_NUMBER,
[email protected]3db3ff62010-01-07 00:35:3932};
33
[email protected]663bd9e2011-03-21 01:07:0134const int kAutofillPhoneLength = arraysize(kAutofillPhoneTypes);
[email protected]9b435be92010-03-04 21:20:1535
[email protected]fcfece42011-07-22 08:29:3236void StripPunctuation(string16* number) {
37 RemoveChars(*number, kPhoneNumberSeparators, number);
[email protected]11c2bdd12011-05-23 18:24:3238}
39
[email protected]fcfece42011-07-22 08:29:3240} // namespace
41
42PhoneNumber::PhoneNumber(AutofillProfile* profile)
43 : phone_group_(AutofillType::NO_GROUP),
44 profile_(profile) {
45}
46
47PhoneNumber::PhoneNumber(AutofillType::FieldTypeGroup phone_group,
48 AutofillProfile* profile)
49 : phone_group_(phone_group),
50 profile_(profile) {
[email protected]11c2bdd12011-05-23 18:24:3251}
[email protected]8e383412010-10-19 16:57:0352
[email protected]43897242011-03-09 03:52:1153PhoneNumber::PhoneNumber(const PhoneNumber& number) : FormGroup() {
54 *this = number;
55}
56
[email protected]8e383412010-10-19 16:57:0357PhoneNumber::~PhoneNumber() {}
58
[email protected]43897242011-03-09 03:52:1159PhoneNumber& PhoneNumber::operator=(const PhoneNumber& number) {
60 if (this == &number)
61 return *this;
[email protected]11c2bdd12011-05-23 18:24:3262 phone_group_ = number.phone_group_;
[email protected]fcfece42011-07-22 08:29:3263 number_ = number.number_;
64 profile_ = number.profile_;
[email protected]35734e92011-06-24 21:06:2565 cached_parsed_phone_ = number.cached_parsed_phone_;
[email protected]43897242011-03-09 03:52:1166 return *this;
67}
68
[email protected]fcfece42011-07-22 08:29:3269void PhoneNumber::GetSupportedTypes(FieldTypeSet* supported_types) const {
70 supported_types->insert(GetWholeNumberType());
71 supported_types->insert(GetNumberType());
72 supported_types->insert(GetCityCodeType());
73 supported_types->insert(GetCityAndNumberType());
74 supported_types->insert(GetCountryCodeType());
[email protected]cea1d112010-07-01 00:57:3375}
76
[email protected]3b3a0ca72011-03-17 23:04:5577string16 PhoneNumber::GetInfo(AutofillFieldType type) const {
[email protected]11c2bdd12011-05-23 18:24:3278 if (type == GetWholeNumberType())
79 return number_;
[email protected]35734e92011-06-24 21:06:2580
[email protected]fcfece42011-07-22 08:29:3281 UpdateCacheIfNeeded();
[email protected]35734e92011-06-24 21:06:2582 if (!cached_parsed_phone_.IsValidNumber())
[email protected]11c2bdd12011-05-23 18:24:3283 return string16();
84
[email protected]1ffe8e992011-03-17 06:26:2985 if (type == GetNumberType())
[email protected]35734e92011-06-24 21:06:2586 return cached_parsed_phone_.GetNumber();
[email protected]3db3ff62010-01-07 00:35:3987
[email protected]1ffe8e992011-03-17 06:26:2988 if (type == GetCityCodeType())
[email protected]35734e92011-06-24 21:06:2589 return cached_parsed_phone_.GetCityCode();
[email protected]3db3ff62010-01-07 00:35:3990
[email protected]1ffe8e992011-03-17 06:26:2991 if (type == GetCountryCodeType())
[email protected]35734e92011-06-24 21:06:2592 return cached_parsed_phone_.GetCountryCode();
[email protected]3db3ff62010-01-07 00:35:3993
[email protected]fcfece42011-07-22 08:29:3294 if (type == GetCityAndNumberType()) {
95 string16 city_and_local(cached_parsed_phone_.GetCityCode());
96 city_and_local.append(cached_parsed_phone_.GetNumber());
[email protected]6f113af2011-06-03 05:10:4397 return city_and_local;
[email protected]fcfece42011-07-22 08:29:3298 }
[email protected]3db3ff62010-01-07 00:35:3999
[email protected]cea1d112010-07-01 00:57:33100 return string16();
[email protected]3db3ff62010-01-07 00:35:39101}
102
[email protected]1ffe8e992011-03-17 06:26:29103void PhoneNumber::SetInfo(AutofillFieldType type, const string16& value) {
[email protected]fcfece42011-07-22 08:29:32104 // Store the group the first time we set some info.
[email protected]11c2bdd12011-05-23 18:24:32105 if (phone_group_ == AutofillType::NO_GROUP)
[email protected]fcfece42011-07-22 08:29:32106 phone_group_ = AutofillType(type).group();
107
108 FieldTypeSubGroup subgroup = AutofillType(type).subgroup();
109 if (subgroup != AutofillType::PHONE_CITY_AND_NUMBER &&
110 subgroup != AutofillType::PHONE_WHOLE_NUMBER) {
111 // Only full phone numbers should be set directly.
[email protected]11c2bdd12011-05-23 18:24:32112 NOTREACHED();
[email protected]fcfece42011-07-22 08:29:32113 return;
114 }
115
116 number_ = value;
117 cached_parsed_phone_ = autofill_i18n::PhoneObject(number_, locale());
118}
119
120// Normalize phones if |type| is a whole number:
121// (650)2345678 -> 6502345678
122// 1-800-FLOWERS -> 18003569377
123// If the phone cannot be normalized, returns the stored value verbatim.
124string16 PhoneNumber::GetCanonicalizedInfo(AutofillFieldType type) const {
125 string16 phone = GetInfo(type);
126 if (type != GetWholeNumberType())
127 return phone;
128
129 string16 normalized_phone = autofill_i18n::NormalizePhoneNumber(phone,
130 locale());
131 if (!normalized_phone.empty())
132 return normalized_phone;
133
134 return phone;
135}
136
137bool PhoneNumber::SetCanonicalizedInfo(AutofillFieldType type,
138 const string16& value) {
139 string16 number = value;
140 StripPunctuation(&number);
141 SetInfo(type, number);
142
143 return NormalizePhone();
144}
145
146void PhoneNumber::GetMatchingTypes(const string16& text,
147 FieldTypeSet* matching_types) const {
148 string16 stripped_text = text;
149 StripPunctuation(&stripped_text);
150 FormGroup::GetMatchingTypes(stripped_text, matching_types);
151
152 // 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.
154 string16 number = GetCanonicalizedInfo(GetNumberType());
155 if (locale() == "US" && number.size() == (kPrefixLength + kSuffixLength)) {
156 string16 prefix = number.substr(kPrefixOffset, kPrefixLength);
157 string16 suffix = number.substr(kSuffixOffset, kSuffixLength);
158 if (text == prefix || text == suffix)
159 matching_types->insert(GetNumberType());
160 }
161
162 string16 whole_number = GetCanonicalizedInfo(GetWholeNumberType());
163 if (!whole_number.empty() &&
164 autofill_i18n::NormalizePhoneNumber(text, locale()) == whole_number) {
165 matching_types->insert(GetWholeNumberType());
[email protected]11c2bdd12011-05-23 18:24:32166 }
167}
168
169bool PhoneNumber::NormalizePhone() {
[email protected]11c2bdd12011-05-23 18:24:32170 // Empty number does not need normalization.
171 if (number_.empty())
172 return true;
173
[email protected]fcfece42011-07-22 08:29:32174 UpdateCacheIfNeeded();
[email protected]35734e92011-06-24 21:06:25175 number_ = cached_parsed_phone_.GetWholeNumber();
[email protected]f4672472011-05-27 07:21:01176 return !number_.empty();
[email protected]11c2bdd12011-05-23 18:24:32177}
178
[email protected]fcfece42011-07-22 08:29:32179std::string PhoneNumber::locale() const {
180 if (!profile_) {
181 NOTREACHED();
182 return "US";
183 }
184
185 return profile_->CountryCode();
186}
187
188void PhoneNumber::UpdateCacheIfNeeded() const {
189 if (!number_.empty() && cached_parsed_phone_.GetLocale() != locale())
190 cached_parsed_phone_ = autofill_i18n::PhoneObject(number_, locale());
[email protected]11c2bdd12011-05-23 18:24:32191}
192
193AutofillFieldType PhoneNumber::GetNumberType() const {
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;
[email protected]3db3ff62010-01-07 00:35:39198 else
199 NOTREACHED();
[email protected]11c2bdd12011-05-23 18:24:32200 return UNKNOWN_TYPE;
[email protected]3db3ff62010-01-07 00:35:39201}
202
[email protected]11c2bdd12011-05-23 18:24:32203AutofillFieldType 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}
[email protected]9b435be92010-03-04 21:20:15212
[email protected]11c2bdd12011-05-23 18:24:32213AutofillFieldType 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}
[email protected]9b435be92010-03-04 21:20:15222
[email protected]11c2bdd12011-05-23 18:24:32223AutofillFieldType 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}
[email protected]9b435be92010-03-04 21:20:15232
[email protected]11c2bdd12011-05-23 18:24:32233AutofillFieldType 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}
[email protected]9b435be92010-03-04 21:20:15242
[email protected]fcfece42011-07-22 08:29:32243PhoneNumber::PhoneCombineHelper::PhoneCombineHelper(
244 AutofillType::FieldTypeGroup phone_group)
245 : phone_group_(phone_group) {
246}
247
248PhoneNumber::PhoneCombineHelper::~PhoneCombineHelper() {
249}
250
[email protected]11c2bdd12011-05-23 18:24:32251bool PhoneNumber::PhoneCombineHelper::SetInfo(AutofillFieldType field_type,
252 const string16& value) {
[email protected]fcfece42011-07-22 08:29:32253 PhoneNumber temp(phone_group_, NULL);
[email protected]11c2bdd12011-05-23 18:24:32254
255 if (field_type == temp.GetCountryCodeType()) {
256 country_ = value;
257 return true;
[email protected]fcfece42011-07-22 08:29:32258 }
259
260 if (field_type == temp.GetCityCodeType()) {
[email protected]11c2bdd12011-05-23 18:24:32261 city_ = value;
262 return true;
[email protected]fcfece42011-07-22 08:29:32263 }
264
265 if (field_type == temp.GetCityAndNumberType()) {
[email protected]11c2bdd12011-05-23 18:24:32266 phone_ = value;
267 return true;
[email protected]fcfece42011-07-22 08:29:32268 }
269
270 if (field_type == temp.GetWholeNumberType()) {
271 whole_number_ = value;
272 return true;
273 }
274
275 if (field_type == temp.GetNumberType()) {
[email protected]11c2bdd12011-05-23 18:24:32276 phone_.append(value);
277 return true;
[email protected]11c2bdd12011-05-23 18:24:32278 }
[email protected]fcfece42011-07-22 08:29:32279
280 return false;
[email protected]9b435be92010-03-04 21:20:15281}
282
[email protected]11c2bdd12011-05-23 18:24:32283bool PhoneNumber::PhoneCombineHelper::ParseNumber(const std::string& locale,
284 string16* value) {
[email protected]fcfece42011-07-22 08:29:32285 if (!whole_number_.empty()) {
286 *value = whole_number_;
287 return true;
288 }
289
[email protected]11c2bdd12011-05-23 18:24:32290 return autofill_i18n::ConstructPhoneNumber(
291 country_, city_, phone_,
292 locale,
293 (country_.empty() ?
294 autofill_i18n::NATIONAL : autofill_i18n::INTERNATIONAL),
295 value);
[email protected]3db3ff62010-01-07 00:35:39296}
297
[email protected]fcfece42011-07-22 08:29:32298bool PhoneNumber::PhoneCombineHelper::IsEmpty() const {
299 return phone_.empty() && whole_number_.empty();
[email protected]3db3ff62010-01-07 00:35:39300}