blob: 5303067acec2d8236a01fa0923fbc2ccac1cdd5d [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]651dd5c32011-09-27 17:04:3846PhoneNumber::PhoneNumber(const PhoneNumber& number)
47 : FormGroup(),
48 profile_(NULL) {
[email protected]43897242011-03-09 03:52:1149 *this = number;
50}
51
[email protected]8e383412010-10-19 16:57:0352PhoneNumber::~PhoneNumber() {}
53
[email protected]43897242011-03-09 03:52:1154PhoneNumber& PhoneNumber::operator=(const PhoneNumber& number) {
55 if (this == &number)
56 return *this;
[email protected]4ef55f8c12011-09-17 00:06:5457
[email protected]fcfece42011-07-22 08:29:3258 number_ = number.number_;
59 profile_ = number.profile_;
[email protected]35734e92011-06-24 21:06:2560 cached_parsed_phone_ = number.cached_parsed_phone_;
[email protected]43897242011-03-09 03:52:1161 return *this;
62}
63
[email protected]fcfece42011-07-22 08:29:3264void PhoneNumber::GetSupportedTypes(FieldTypeSet* supported_types) const {
[email protected]4ef55f8c12011-09-17 00:06:5465 supported_types->insert(PHONE_HOME_WHOLE_NUMBER);
66 supported_types->insert(PHONE_HOME_NUMBER);
67 supported_types->insert(PHONE_HOME_CITY_CODE);
68 supported_types->insert(PHONE_HOME_CITY_AND_NUMBER);
69 supported_types->insert(PHONE_HOME_COUNTRY_CODE);
[email protected]cea1d112010-07-01 00:57:3370}
71
[email protected]3b3a0ca72011-03-17 23:04:5572string16 PhoneNumber::GetInfo(AutofillFieldType type) const {
[email protected]4ef55f8c12011-09-17 00:06:5473 if (type == PHONE_HOME_WHOLE_NUMBER)
[email protected]11c2bdd12011-05-23 18:24:3274 return number_;
[email protected]35734e92011-06-24 21:06:2575
[email protected]fcfece42011-07-22 08:29:3276 UpdateCacheIfNeeded();
[email protected]35734e92011-06-24 21:06:2577 if (!cached_parsed_phone_.IsValidNumber())
[email protected]11c2bdd12011-05-23 18:24:3278 return string16();
79
[email protected]4ef55f8c12011-09-17 00:06:5480 if (type == PHONE_HOME_NUMBER)
[email protected]35734e92011-06-24 21:06:2581 return cached_parsed_phone_.GetNumber();
[email protected]3db3ff62010-01-07 00:35:3982
[email protected]4ef55f8c12011-09-17 00:06:5483 if (type == PHONE_HOME_CITY_CODE)
[email protected]35734e92011-06-24 21:06:2584 return cached_parsed_phone_.GetCityCode();
[email protected]3db3ff62010-01-07 00:35:3985
[email protected]4ef55f8c12011-09-17 00:06:5486 if (type == PHONE_HOME_COUNTRY_CODE)
[email protected]35734e92011-06-24 21:06:2587 return cached_parsed_phone_.GetCountryCode();
[email protected]3db3ff62010-01-07 00:35:3988
[email protected]4ef55f8c12011-09-17 00:06:5489 if (type == PHONE_HOME_CITY_AND_NUMBER) {
[email protected]fcfece42011-07-22 08:29:3290 string16 city_and_local(cached_parsed_phone_.GetCityCode());
91 city_and_local.append(cached_parsed_phone_.GetNumber());
[email protected]6f113af2011-06-03 05:10:4392 return city_and_local;
[email protected]fcfece42011-07-22 08:29:3293 }
[email protected]3db3ff62010-01-07 00:35:3994
[email protected]cea1d112010-07-01 00:57:3395 return string16();
[email protected]3db3ff62010-01-07 00:35:3996}
97
[email protected]1ffe8e992011-03-17 06:26:2998void PhoneNumber::SetInfo(AutofillFieldType type, const string16& value) {
[email protected]fcfece42011-07-22 08:29:3299 FieldTypeSubGroup subgroup = AutofillType(type).subgroup();
100 if (subgroup != AutofillType::PHONE_CITY_AND_NUMBER &&
101 subgroup != AutofillType::PHONE_WHOLE_NUMBER) {
[email protected]08f691b2011-07-26 23:22:03102 // Only full phone numbers should be set directly. The remaining field
103 // field types are read-only.
[email protected]fcfece42011-07-22 08:29:32104 return;
105 }
106
107 number_ = value;
108 cached_parsed_phone_ = autofill_i18n::PhoneObject(number_, locale());
109}
110
111// Normalize phones if |type| is a whole number:
112// (650)2345678 -> 6502345678
113// 1-800-FLOWERS -> 18003569377
114// If the phone cannot be normalized, returns the stored value verbatim.
115string16 PhoneNumber::GetCanonicalizedInfo(AutofillFieldType type) const {
116 string16 phone = GetInfo(type);
[email protected]4ef55f8c12011-09-17 00:06:54117 if (type != PHONE_HOME_WHOLE_NUMBER)
[email protected]fcfece42011-07-22 08:29:32118 return phone;
119
120 string16 normalized_phone = autofill_i18n::NormalizePhoneNumber(phone,
121 locale());
122 if (!normalized_phone.empty())
123 return normalized_phone;
124
125 return phone;
126}
127
128bool PhoneNumber::SetCanonicalizedInfo(AutofillFieldType type,
129 const string16& value) {
130 string16 number = value;
131 StripPunctuation(&number);
132 SetInfo(type, number);
133
134 return NormalizePhone();
135}
136
137void PhoneNumber::GetMatchingTypes(const string16& text,
138 FieldTypeSet* matching_types) const {
139 string16 stripped_text = text;
140 StripPunctuation(&stripped_text);
141 FormGroup::GetMatchingTypes(stripped_text, matching_types);
142
143 // For US numbers, also compare to the three-digit prefix and the four-digit
[email protected]4ef55f8c12011-09-17 00:06:54144 // suffix, since web sites often split numbers into these two fields.
145 string16 number = GetCanonicalizedInfo(PHONE_HOME_NUMBER);
[email protected]fcfece42011-07-22 08:29:32146 if (locale() == "US" && number.size() == (kPrefixLength + kSuffixLength)) {
147 string16 prefix = number.substr(kPrefixOffset, kPrefixLength);
148 string16 suffix = number.substr(kSuffixOffset, kSuffixLength);
149 if (text == prefix || text == suffix)
[email protected]4ef55f8c12011-09-17 00:06:54150 matching_types->insert(PHONE_HOME_NUMBER);
[email protected]fcfece42011-07-22 08:29:32151 }
152
[email protected]4ef55f8c12011-09-17 00:06:54153 string16 whole_number = GetCanonicalizedInfo(PHONE_HOME_WHOLE_NUMBER);
[email protected]fcfece42011-07-22 08:29:32154 if (!whole_number.empty() &&
155 autofill_i18n::NormalizePhoneNumber(text, locale()) == whole_number) {
[email protected]4ef55f8c12011-09-17 00:06:54156 matching_types->insert(PHONE_HOME_WHOLE_NUMBER);
[email protected]11c2bdd12011-05-23 18:24:32157 }
158}
159
160bool PhoneNumber::NormalizePhone() {
[email protected]11c2bdd12011-05-23 18:24:32161 // Empty number does not need normalization.
162 if (number_.empty())
163 return true;
164
[email protected]fcfece42011-07-22 08:29:32165 UpdateCacheIfNeeded();
[email protected]35734e92011-06-24 21:06:25166 number_ = cached_parsed_phone_.GetWholeNumber();
[email protected]f4672472011-05-27 07:21:01167 return !number_.empty();
[email protected]11c2bdd12011-05-23 18:24:32168}
169
[email protected]fcfece42011-07-22 08:29:32170std::string PhoneNumber::locale() const {
171 if (!profile_) {
172 NOTREACHED();
173 return "US";
174 }
175
176 return profile_->CountryCode();
177}
178
179void PhoneNumber::UpdateCacheIfNeeded() const {
180 if (!number_.empty() && cached_parsed_phone_.GetLocale() != locale())
181 cached_parsed_phone_ = autofill_i18n::PhoneObject(number_, locale());
[email protected]11c2bdd12011-05-23 18:24:32182}
183
[email protected]4ef55f8c12011-09-17 00:06:54184PhoneNumber::PhoneCombineHelper::PhoneCombineHelper() {
[email protected]fcfece42011-07-22 08:29:32185}
186
187PhoneNumber::PhoneCombineHelper::~PhoneCombineHelper() {
188}
189
[email protected]11c2bdd12011-05-23 18:24:32190bool PhoneNumber::PhoneCombineHelper::SetInfo(AutofillFieldType field_type,
191 const string16& value) {
[email protected]4ef55f8c12011-09-17 00:06:54192 if (field_type == PHONE_HOME_COUNTRY_CODE) {
[email protected]11c2bdd12011-05-23 18:24:32193 country_ = value;
194 return true;
[email protected]fcfece42011-07-22 08:29:32195 }
196
[email protected]4ef55f8c12011-09-17 00:06:54197 if (field_type == PHONE_HOME_CITY_CODE) {
[email protected]11c2bdd12011-05-23 18:24:32198 city_ = value;
199 return true;
[email protected]fcfece42011-07-22 08:29:32200 }
201
[email protected]4ef55f8c12011-09-17 00:06:54202 if (field_type == PHONE_HOME_CITY_AND_NUMBER) {
[email protected]11c2bdd12011-05-23 18:24:32203 phone_ = value;
204 return true;
[email protected]fcfece42011-07-22 08:29:32205 }
206
[email protected]4ef55f8c12011-09-17 00:06:54207 if (field_type == PHONE_HOME_WHOLE_NUMBER) {
[email protected]fcfece42011-07-22 08:29:32208 whole_number_ = value;
209 return true;
210 }
211
[email protected]4ef55f8c12011-09-17 00:06:54212 if (field_type == PHONE_HOME_NUMBER) {
[email protected]11c2bdd12011-05-23 18:24:32213 phone_.append(value);
214 return true;
[email protected]11c2bdd12011-05-23 18:24:32215 }
[email protected]fcfece42011-07-22 08:29:32216
217 return false;
[email protected]9b435be92010-03-04 21:20:15218}
219
[email protected]11c2bdd12011-05-23 18:24:32220bool PhoneNumber::PhoneCombineHelper::ParseNumber(const std::string& locale,
221 string16* value) {
[email protected]fcfece42011-07-22 08:29:32222 if (!whole_number_.empty()) {
223 *value = whole_number_;
224 return true;
225 }
226
[email protected]11c2bdd12011-05-23 18:24:32227 return autofill_i18n::ConstructPhoneNumber(
228 country_, city_, phone_,
229 locale,
230 (country_.empty() ?
231 autofill_i18n::NATIONAL : autofill_i18n::INTERNATIONAL),
232 value);
[email protected]3db3ff62010-01-07 00:35:39233}
234
[email protected]fcfece42011-07-22 08:29:32235bool PhoneNumber::PhoneCombineHelper::IsEmpty() const {
236 return phone_.empty() && whole_number_.empty();
[email protected]3db3ff62010-01-07 00:35:39237}