blob: e2425217a0b65600f095de6985b443ac65f20d52 [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]fcfece42011-07-22 08:29:3226void StripPunctuation(string16* number) {
27 RemoveChars(*number, kPhoneNumberSeparators, number);
[email protected]11c2bdd12011-05-23 18:24:3228}
29
[email protected]fcfece42011-07-22 08:29:3230} // namespace
31
32PhoneNumber::PhoneNumber(AutofillProfile* profile)
[email protected]4ef55f8c12011-09-17 00:06:5433 : profile_(profile) {
[email protected]11c2bdd12011-05-23 18:24:3234}
[email protected]8e383412010-10-19 16:57:0335
[email protected]651dd5c32011-09-27 17:04:3836PhoneNumber::PhoneNumber(const PhoneNumber& number)
37 : FormGroup(),
38 profile_(NULL) {
[email protected]43897242011-03-09 03:52:1139 *this = number;
40}
41
[email protected]8e383412010-10-19 16:57:0342PhoneNumber::~PhoneNumber() {}
43
[email protected]43897242011-03-09 03:52:1144PhoneNumber& PhoneNumber::operator=(const PhoneNumber& number) {
45 if (this == &number)
46 return *this;
[email protected]4ef55f8c12011-09-17 00:06:5447
[email protected]fcfece42011-07-22 08:29:3248 number_ = number.number_;
49 profile_ = number.profile_;
[email protected]35734e92011-06-24 21:06:2550 cached_parsed_phone_ = number.cached_parsed_phone_;
[email protected]43897242011-03-09 03:52:1151 return *this;
52}
53
[email protected]fcfece42011-07-22 08:29:3254void PhoneNumber::GetSupportedTypes(FieldTypeSet* supported_types) const {
[email protected]4ef55f8c12011-09-17 00:06:5455 supported_types->insert(PHONE_HOME_WHOLE_NUMBER);
56 supported_types->insert(PHONE_HOME_NUMBER);
57 supported_types->insert(PHONE_HOME_CITY_CODE);
58 supported_types->insert(PHONE_HOME_CITY_AND_NUMBER);
59 supported_types->insert(PHONE_HOME_COUNTRY_CODE);
[email protected]cea1d112010-07-01 00:57:3360}
61
[email protected]6b44b582012-11-10 06:31:1862string16 PhoneNumber::GetRawInfo(AutofillFieldType type) const {
[email protected]4ef55f8c12011-09-17 00:06:5463 if (type == PHONE_HOME_WHOLE_NUMBER)
[email protected]11c2bdd12011-05-23 18:24:3264 return number_;
[email protected]35734e92011-06-24 21:06:2565
[email protected]fcfece42011-07-22 08:29:3266 UpdateCacheIfNeeded();
[email protected]35734e92011-06-24 21:06:2567 if (!cached_parsed_phone_.IsValidNumber())
[email protected]11c2bdd12011-05-23 18:24:3268 return string16();
69
[email protected]4ef55f8c12011-09-17 00:06:5470 if (type == PHONE_HOME_NUMBER)
[email protected]35734e92011-06-24 21:06:2571 return cached_parsed_phone_.GetNumber();
[email protected]3db3ff62010-01-07 00:35:3972
[email protected]4ef55f8c12011-09-17 00:06:5473 if (type == PHONE_HOME_CITY_CODE)
[email protected]35734e92011-06-24 21:06:2574 return cached_parsed_phone_.GetCityCode();
[email protected]3db3ff62010-01-07 00:35:3975
[email protected]4ef55f8c12011-09-17 00:06:5476 if (type == PHONE_HOME_COUNTRY_CODE)
[email protected]35734e92011-06-24 21:06:2577 return cached_parsed_phone_.GetCountryCode();
[email protected]3db3ff62010-01-07 00:35:3978
[email protected]4ef55f8c12011-09-17 00:06:5479 if (type == PHONE_HOME_CITY_AND_NUMBER) {
[email protected]fcfece42011-07-22 08:29:3280 string16 city_and_local(cached_parsed_phone_.GetCityCode());
81 city_and_local.append(cached_parsed_phone_.GetNumber());
[email protected]6f113af2011-06-03 05:10:4382 return city_and_local;
[email protected]fcfece42011-07-22 08:29:3283 }
[email protected]3db3ff62010-01-07 00:35:3984
[email protected]cea1d112010-07-01 00:57:3385 return string16();
[email protected]3db3ff62010-01-07 00:35:3986}
87
[email protected]6b44b582012-11-10 06:31:1888void PhoneNumber::SetRawInfo(AutofillFieldType type, const string16& value) {
[email protected]13405292011-10-07 22:37:0989 if (type != PHONE_HOME_CITY_AND_NUMBER &&
90 type != PHONE_HOME_WHOLE_NUMBER) {
[email protected]08f691b2011-07-26 23:22:0391 // Only full phone numbers should be set directly. The remaining field
92 // field types are read-only.
[email protected]fcfece42011-07-22 08:29:3293 return;
94 }
95
96 number_ = value;
[email protected]442405062012-11-28 05:36:1897 cached_parsed_phone_ = autofill_i18n::PhoneObject(number_, GetRegion());
[email protected]fcfece42011-07-22 08:29:3298}
99
100// Normalize phones if |type| is a whole number:
101// (650)2345678 -> 6502345678
102// 1-800-FLOWERS -> 18003569377
103// If the phone cannot be normalized, returns the stored value verbatim.
104string16 PhoneNumber::GetCanonicalizedInfo(AutofillFieldType type) const {
[email protected]6b44b582012-11-10 06:31:18105 string16 phone = GetRawInfo(type);
[email protected]4ef55f8c12011-09-17 00:06:54106 if (type != PHONE_HOME_WHOLE_NUMBER)
[email protected]fcfece42011-07-22 08:29:32107 return phone;
108
109 string16 normalized_phone = autofill_i18n::NormalizePhoneNumber(phone,
[email protected]442405062012-11-28 05:36:18110 GetRegion());
[email protected]fcfece42011-07-22 08:29:32111 if (!normalized_phone.empty())
112 return normalized_phone;
113
114 return phone;
115}
116
117bool PhoneNumber::SetCanonicalizedInfo(AutofillFieldType type,
118 const string16& value) {
119 string16 number = value;
120 StripPunctuation(&number);
[email protected]6b44b582012-11-10 06:31:18121 SetRawInfo(type, number);
[email protected]fcfece42011-07-22 08:29:32122
123 return NormalizePhone();
124}
125
126void PhoneNumber::GetMatchingTypes(const string16& text,
127 FieldTypeSet* matching_types) const {
128 string16 stripped_text = text;
129 StripPunctuation(&stripped_text);
130 FormGroup::GetMatchingTypes(stripped_text, matching_types);
131
132 // For US numbers, also compare to the three-digit prefix and the four-digit
[email protected]4ef55f8c12011-09-17 00:06:54133 // suffix, since web sites often split numbers into these two fields.
134 string16 number = GetCanonicalizedInfo(PHONE_HOME_NUMBER);
[email protected]442405062012-11-28 05:36:18135 if (GetRegion() == "US" && number.size() == (kPrefixLength + kSuffixLength)) {
[email protected]fcfece42011-07-22 08:29:32136 string16 prefix = number.substr(kPrefixOffset, kPrefixLength);
137 string16 suffix = number.substr(kSuffixOffset, kSuffixLength);
138 if (text == prefix || text == suffix)
[email protected]4ef55f8c12011-09-17 00:06:54139 matching_types->insert(PHONE_HOME_NUMBER);
[email protected]fcfece42011-07-22 08:29:32140 }
141
[email protected]4ef55f8c12011-09-17 00:06:54142 string16 whole_number = GetCanonicalizedInfo(PHONE_HOME_WHOLE_NUMBER);
[email protected]fcfece42011-07-22 08:29:32143 if (!whole_number.empty() &&
[email protected]442405062012-11-28 05:36:18144 autofill_i18n::NormalizePhoneNumber(text, GetRegion()) == whole_number) {
[email protected]4ef55f8c12011-09-17 00:06:54145 matching_types->insert(PHONE_HOME_WHOLE_NUMBER);
[email protected]11c2bdd12011-05-23 18:24:32146 }
147}
148
149bool PhoneNumber::NormalizePhone() {
[email protected]11c2bdd12011-05-23 18:24:32150 // Empty number does not need normalization.
151 if (number_.empty())
152 return true;
153
[email protected]fcfece42011-07-22 08:29:32154 UpdateCacheIfNeeded();
[email protected]35734e92011-06-24 21:06:25155 number_ = cached_parsed_phone_.GetWholeNumber();
[email protected]f4672472011-05-27 07:21:01156 return !number_.empty();
[email protected]11c2bdd12011-05-23 18:24:32157}
158
[email protected]442405062012-11-28 05:36:18159std::string PhoneNumber::GetRegion() const {
[email protected]fcfece42011-07-22 08:29:32160 if (!profile_) {
161 NOTREACHED();
162 return "US";
163 }
164
165 return profile_->CountryCode();
166}
167
168void PhoneNumber::UpdateCacheIfNeeded() const {
[email protected]442405062012-11-28 05:36:18169 std::string region = GetRegion();
170 if (!number_.empty() && cached_parsed_phone_.GetRegion() != region)
171 cached_parsed_phone_ = autofill_i18n::PhoneObject(number_, region);
[email protected]11c2bdd12011-05-23 18:24:32172}
173
[email protected]4ef55f8c12011-09-17 00:06:54174PhoneNumber::PhoneCombineHelper::PhoneCombineHelper() {
[email protected]fcfece42011-07-22 08:29:32175}
176
177PhoneNumber::PhoneCombineHelper::~PhoneCombineHelper() {
178}
179
[email protected]11c2bdd12011-05-23 18:24:32180bool PhoneNumber::PhoneCombineHelper::SetInfo(AutofillFieldType field_type,
181 const string16& value) {
[email protected]4ef55f8c12011-09-17 00:06:54182 if (field_type == PHONE_HOME_COUNTRY_CODE) {
[email protected]11c2bdd12011-05-23 18:24:32183 country_ = value;
184 return true;
[email protected]fcfece42011-07-22 08:29:32185 }
186
[email protected]4ef55f8c12011-09-17 00:06:54187 if (field_type == PHONE_HOME_CITY_CODE) {
[email protected]11c2bdd12011-05-23 18:24:32188 city_ = value;
189 return true;
[email protected]fcfece42011-07-22 08:29:32190 }
191
[email protected]4ef55f8c12011-09-17 00:06:54192 if (field_type == PHONE_HOME_CITY_AND_NUMBER) {
[email protected]11c2bdd12011-05-23 18:24:32193 phone_ = 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_WHOLE_NUMBER) {
[email protected]fcfece42011-07-22 08:29:32198 whole_number_ = value;
199 return true;
200 }
201
[email protected]4ef55f8c12011-09-17 00:06:54202 if (field_type == PHONE_HOME_NUMBER) {
[email protected]11c2bdd12011-05-23 18:24:32203 phone_.append(value);
204 return true;
[email protected]11c2bdd12011-05-23 18:24:32205 }
[email protected]fcfece42011-07-22 08:29:32206
207 return false;
[email protected]9b435be92010-03-04 21:20:15208}
209
[email protected]442405062012-11-28 05:36:18210bool PhoneNumber::PhoneCombineHelper::ParseNumber(const std::string& region,
[email protected]11c2bdd12011-05-23 18:24:32211 string16* value) {
[email protected]fcfece42011-07-22 08:29:32212 if (!whole_number_.empty()) {
213 *value = whole_number_;
214 return true;
215 }
216
[email protected]11c2bdd12011-05-23 18:24:32217 return autofill_i18n::ConstructPhoneNumber(
218 country_, city_, phone_,
[email protected]442405062012-11-28 05:36:18219 region,
[email protected]11c2bdd12011-05-23 18:24:32220 (country_.empty() ?
221 autofill_i18n::NATIONAL : autofill_i18n::INTERNATIONAL),
222 value);
[email protected]3db3ff62010-01-07 00:35:39223}
224
[email protected]fcfece42011-07-22 08:29:32225bool PhoneNumber::PhoneCombineHelper::IsEmpty() const {
226 return phone_.empty() && whole_number_.empty();
[email protected]3db3ff62010-01-07 00:35:39227}