blob: 7b01c1583fd769b30d6b0903330e87f269801c4c [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)
[email protected]4ef55f8c12011-09-17 00:06:5443 : profile_(profile) {
[email protected]11c2bdd12011-05-23 18:24:3244}
[email protected]8e383412010-10-19 16:57:0345
[email protected]43897242011-03-09 03:52:1146PhoneNumber::PhoneNumber(const PhoneNumber& number) : FormGroup() {
47 *this = number;
48}
49
[email protected]8e383412010-10-19 16:57:0350PhoneNumber::~PhoneNumber() {}
51
[email protected]43897242011-03-09 03:52:1152PhoneNumber& PhoneNumber::operator=(const PhoneNumber& number) {
53 if (this == &number)
54 return *this;
[email protected]4ef55f8c12011-09-17 00:06:5455
[email protected]fcfece42011-07-22 08:29:3256 number_ = number.number_;
57 profile_ = number.profile_;
[email protected]35734e92011-06-24 21:06:2558 cached_parsed_phone_ = number.cached_parsed_phone_;
[email protected]43897242011-03-09 03:52:1159 return *this;
60}
61
[email protected]fcfece42011-07-22 08:29:3262void PhoneNumber::GetSupportedTypes(FieldTypeSet* supported_types) const {
[email protected]4ef55f8c12011-09-17 00:06:5463 supported_types->insert(PHONE_HOME_WHOLE_NUMBER);
64 supported_types->insert(PHONE_HOME_NUMBER);
65 supported_types->insert(PHONE_HOME_CITY_CODE);
66 supported_types->insert(PHONE_HOME_CITY_AND_NUMBER);
67 supported_types->insert(PHONE_HOME_COUNTRY_CODE);
[email protected]cea1d112010-07-01 00:57:3368}
69
[email protected]3b3a0ca72011-03-17 23:04:5570string16 PhoneNumber::GetInfo(AutofillFieldType type) const {
[email protected]4ef55f8c12011-09-17 00:06:5471 if (type == PHONE_HOME_WHOLE_NUMBER)
[email protected]11c2bdd12011-05-23 18:24:3272 return number_;
[email protected]35734e92011-06-24 21:06:2573
[email protected]fcfece42011-07-22 08:29:3274 UpdateCacheIfNeeded();
[email protected]35734e92011-06-24 21:06:2575 if (!cached_parsed_phone_.IsValidNumber())
[email protected]11c2bdd12011-05-23 18:24:3276 return string16();
77
[email protected]4ef55f8c12011-09-17 00:06:5478 if (type == PHONE_HOME_NUMBER)
[email protected]35734e92011-06-24 21:06:2579 return cached_parsed_phone_.GetNumber();
[email protected]3db3ff62010-01-07 00:35:3980
[email protected]4ef55f8c12011-09-17 00:06:5481 if (type == PHONE_HOME_CITY_CODE)
[email protected]35734e92011-06-24 21:06:2582 return cached_parsed_phone_.GetCityCode();
[email protected]3db3ff62010-01-07 00:35:3983
[email protected]4ef55f8c12011-09-17 00:06:5484 if (type == PHONE_HOME_COUNTRY_CODE)
[email protected]35734e92011-06-24 21:06:2585 return cached_parsed_phone_.GetCountryCode();
[email protected]3db3ff62010-01-07 00:35:3986
[email protected]4ef55f8c12011-09-17 00:06:5487 if (type == PHONE_HOME_CITY_AND_NUMBER) {
[email protected]fcfece42011-07-22 08:29:3288 string16 city_and_local(cached_parsed_phone_.GetCityCode());
89 city_and_local.append(cached_parsed_phone_.GetNumber());
[email protected]6f113af2011-06-03 05:10:4390 return city_and_local;
[email protected]fcfece42011-07-22 08:29:3291 }
[email protected]3db3ff62010-01-07 00:35:3992
[email protected]cea1d112010-07-01 00:57:3393 return string16();
[email protected]3db3ff62010-01-07 00:35:3994}
95
[email protected]1ffe8e992011-03-17 06:26:2996void PhoneNumber::SetInfo(AutofillFieldType type, const string16& value) {
[email protected]fcfece42011-07-22 08:29:3297 FieldTypeSubGroup subgroup = AutofillType(type).subgroup();
98 if (subgroup != AutofillType::PHONE_CITY_AND_NUMBER &&
99 subgroup != AutofillType::PHONE_WHOLE_NUMBER) {
[email protected]08f691b2011-07-26 23:22:03100 // Only full phone numbers should be set directly. The remaining field
101 // field types are read-only.
[email protected]fcfece42011-07-22 08:29:32102 return;
103 }
104
105 number_ = value;
106 cached_parsed_phone_ = autofill_i18n::PhoneObject(number_, locale());
107}
108
109// Normalize phones if |type| is a whole number:
110// (650)2345678 -> 6502345678
111// 1-800-FLOWERS -> 18003569377
112// If the phone cannot be normalized, returns the stored value verbatim.
113string16 PhoneNumber::GetCanonicalizedInfo(AutofillFieldType type) const {
114 string16 phone = GetInfo(type);
[email protected]4ef55f8c12011-09-17 00:06:54115 if (type != PHONE_HOME_WHOLE_NUMBER)
[email protected]fcfece42011-07-22 08:29:32116 return phone;
117
118 string16 normalized_phone = autofill_i18n::NormalizePhoneNumber(phone,
119 locale());
120 if (!normalized_phone.empty())
121 return normalized_phone;
122
123 return phone;
124}
125
126bool PhoneNumber::SetCanonicalizedInfo(AutofillFieldType type,
127 const string16& value) {
128 string16 number = value;
129 StripPunctuation(&number);
130 SetInfo(type, number);
131
132 return NormalizePhone();
133}
134
135void PhoneNumber::GetMatchingTypes(const string16& text,
136 FieldTypeSet* matching_types) const {
137 string16 stripped_text = text;
138 StripPunctuation(&stripped_text);
139 FormGroup::GetMatchingTypes(stripped_text, matching_types);
140
141 // For US numbers, also compare to the three-digit prefix and the four-digit
[email protected]4ef55f8c12011-09-17 00:06:54142 // suffix, since web sites often split numbers into these two fields.
143 string16 number = GetCanonicalizedInfo(PHONE_HOME_NUMBER);
[email protected]fcfece42011-07-22 08:29:32144 if (locale() == "US" && number.size() == (kPrefixLength + kSuffixLength)) {
145 string16 prefix = number.substr(kPrefixOffset, kPrefixLength);
146 string16 suffix = number.substr(kSuffixOffset, kSuffixLength);
147 if (text == prefix || text == suffix)
[email protected]4ef55f8c12011-09-17 00:06:54148 matching_types->insert(PHONE_HOME_NUMBER);
[email protected]fcfece42011-07-22 08:29:32149 }
150
[email protected]4ef55f8c12011-09-17 00:06:54151 string16 whole_number = GetCanonicalizedInfo(PHONE_HOME_WHOLE_NUMBER);
[email protected]fcfece42011-07-22 08:29:32152 if (!whole_number.empty() &&
153 autofill_i18n::NormalizePhoneNumber(text, locale()) == whole_number) {
[email protected]4ef55f8c12011-09-17 00:06:54154 matching_types->insert(PHONE_HOME_WHOLE_NUMBER);
[email protected]11c2bdd12011-05-23 18:24:32155 }
156}
157
158bool PhoneNumber::NormalizePhone() {
[email protected]11c2bdd12011-05-23 18:24:32159 // Empty number does not need normalization.
160 if (number_.empty())
161 return true;
162
[email protected]fcfece42011-07-22 08:29:32163 UpdateCacheIfNeeded();
[email protected]35734e92011-06-24 21:06:25164 number_ = cached_parsed_phone_.GetWholeNumber();
[email protected]f4672472011-05-27 07:21:01165 return !number_.empty();
[email protected]11c2bdd12011-05-23 18:24:32166}
167
[email protected]fcfece42011-07-22 08:29:32168std::string PhoneNumber::locale() const {
169 if (!profile_) {
170 NOTREACHED();
171 return "US";
172 }
173
174 return profile_->CountryCode();
175}
176
177void PhoneNumber::UpdateCacheIfNeeded() const {
178 if (!number_.empty() && cached_parsed_phone_.GetLocale() != locale())
179 cached_parsed_phone_ = autofill_i18n::PhoneObject(number_, locale());
[email protected]11c2bdd12011-05-23 18:24:32180}
181
[email protected]4ef55f8c12011-09-17 00:06:54182PhoneNumber::PhoneCombineHelper::PhoneCombineHelper() {
[email protected]fcfece42011-07-22 08:29:32183}
184
185PhoneNumber::PhoneCombineHelper::~PhoneCombineHelper() {
186}
187
[email protected]11c2bdd12011-05-23 18:24:32188bool PhoneNumber::PhoneCombineHelper::SetInfo(AutofillFieldType field_type,
189 const string16& value) {
[email protected]4ef55f8c12011-09-17 00:06:54190 if (field_type == PHONE_HOME_COUNTRY_CODE) {
[email protected]11c2bdd12011-05-23 18:24:32191 country_ = value;
192 return true;
[email protected]fcfece42011-07-22 08:29:32193 }
194
[email protected]4ef55f8c12011-09-17 00:06:54195 if (field_type == PHONE_HOME_CITY_CODE) {
[email protected]11c2bdd12011-05-23 18:24:32196 city_ = value;
197 return true;
[email protected]fcfece42011-07-22 08:29:32198 }
199
[email protected]4ef55f8c12011-09-17 00:06:54200 if (field_type == PHONE_HOME_CITY_AND_NUMBER) {
[email protected]11c2bdd12011-05-23 18:24:32201 phone_ = value;
202 return true;
[email protected]fcfece42011-07-22 08:29:32203 }
204
[email protected]4ef55f8c12011-09-17 00:06:54205 if (field_type == PHONE_HOME_WHOLE_NUMBER) {
[email protected]fcfece42011-07-22 08:29:32206 whole_number_ = value;
207 return true;
208 }
209
[email protected]4ef55f8c12011-09-17 00:06:54210 if (field_type == PHONE_HOME_NUMBER) {
[email protected]11c2bdd12011-05-23 18:24:32211 phone_.append(value);
212 return true;
[email protected]11c2bdd12011-05-23 18:24:32213 }
[email protected]fcfece42011-07-22 08:29:32214
215 return false;
[email protected]9b435be92010-03-04 21:20:15216}
217
[email protected]11c2bdd12011-05-23 18:24:32218bool PhoneNumber::PhoneCombineHelper::ParseNumber(const std::string& locale,
219 string16* value) {
[email protected]fcfece42011-07-22 08:29:32220 if (!whole_number_.empty()) {
221 *value = whole_number_;
222 return true;
223 }
224
[email protected]11c2bdd12011-05-23 18:24:32225 return autofill_i18n::ConstructPhoneNumber(
226 country_, city_, phone_,
227 locale,
228 (country_.empty() ?
229 autofill_i18n::NATIONAL : autofill_i18n::INTERNATIONAL),
230 value);
[email protected]3db3ff62010-01-07 00:35:39231}
232
[email protected]fcfece42011-07-22 08:29:32233bool PhoneNumber::PhoneCombineHelper::IsEmpty() const {
234 return phone_.empty() && whole_number_.empty();
[email protected]3db3ff62010-01-07 00:35:39235}