blob: e5027fa170a63a34fc6b9dbe2971d892de13f307 [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]4d11fcd2012-12-05 05:34:4811#include "chrome/browser/autofill/autofill_country.h"
[email protected]9b435be92010-03-04 21:20:1512#include "chrome/browser/autofill/autofill_profile.h"
[email protected]3db3ff62010-01-07 00:35:3913#include "chrome/browser/autofill/autofill_type.h"
14#include "chrome/browser/autofill/field_types.h"
[email protected]11c2bdd12011-05-23 18:24:3215#include "chrome/browser/autofill/phone_number_i18n.h"
[email protected]3db3ff62010-01-07 00:35:3916
[email protected]9b435be92010-03-04 21:20:1517namespace {
[email protected]3db3ff62010-01-07 00:35:3918
[email protected]9b435be92010-03-04 21:20:1519const char16 kPhoneNumberSeparators[] = { ' ', '.', '(', ')', '-', 0 };
20
21// The number of digits in a phone number.
22const size_t kPhoneNumberLength = 7;
23
24// The number of digits in an area code.
25const size_t kPhoneCityCodeLength = 3;
26
[email protected]fcfece42011-07-22 08:29:3227void StripPunctuation(string16* number) {
28 RemoveChars(*number, kPhoneNumberSeparators, number);
[email protected]11c2bdd12011-05-23 18:24:3229}
30
[email protected]fcfece42011-07-22 08:29:3231} // namespace
32
33PhoneNumber::PhoneNumber(AutofillProfile* profile)
[email protected]4ef55f8c12011-09-17 00:06:5434 : profile_(profile) {
[email protected]11c2bdd12011-05-23 18:24:3235}
[email protected]8e383412010-10-19 16:57:0336
[email protected]651dd5c32011-09-27 17:04:3837PhoneNumber::PhoneNumber(const PhoneNumber& number)
38 : FormGroup(),
39 profile_(NULL) {
[email protected]43897242011-03-09 03:52:1140 *this = number;
41}
42
[email protected]8e383412010-10-19 16:57:0343PhoneNumber::~PhoneNumber() {}
44
[email protected]43897242011-03-09 03:52:1145PhoneNumber& PhoneNumber::operator=(const PhoneNumber& number) {
46 if (this == &number)
47 return *this;
[email protected]4ef55f8c12011-09-17 00:06:5448
[email protected]fcfece42011-07-22 08:29:3249 number_ = number.number_;
50 profile_ = number.profile_;
[email protected]35734e92011-06-24 21:06:2551 cached_parsed_phone_ = number.cached_parsed_phone_;
[email protected]43897242011-03-09 03:52:1152 return *this;
53}
54
[email protected]fcfece42011-07-22 08:29:3255void PhoneNumber::GetSupportedTypes(FieldTypeSet* supported_types) const {
[email protected]4ef55f8c12011-09-17 00:06:5456 supported_types->insert(PHONE_HOME_WHOLE_NUMBER);
57 supported_types->insert(PHONE_HOME_NUMBER);
58 supported_types->insert(PHONE_HOME_CITY_CODE);
59 supported_types->insert(PHONE_HOME_CITY_AND_NUMBER);
60 supported_types->insert(PHONE_HOME_COUNTRY_CODE);
[email protected]cea1d112010-07-01 00:57:3361}
62
[email protected]6b44b582012-11-10 06:31:1863string16 PhoneNumber::GetRawInfo(AutofillFieldType type) const {
[email protected]4ef55f8c12011-09-17 00:06:5464 if (type == PHONE_HOME_WHOLE_NUMBER)
[email protected]11c2bdd12011-05-23 18:24:3265 return number_;
[email protected]35734e92011-06-24 21:06:2566
[email protected]4d11fcd2012-12-05 05:34:4867 // Only the whole number is available as raw data. All of the other types are
68 // parsed from this raw info, and parsing requires knowledge of the phone
69 // number's region, which is only available via GetInfo().
[email protected]cea1d112010-07-01 00:57:3370 return string16();
[email protected]3db3ff62010-01-07 00:35:3971}
72
[email protected]6b44b582012-11-10 06:31:1873void PhoneNumber::SetRawInfo(AutofillFieldType type, const string16& value) {
[email protected]13405292011-10-07 22:37:0974 if (type != PHONE_HOME_CITY_AND_NUMBER &&
75 type != PHONE_HOME_WHOLE_NUMBER) {
[email protected]08f691b2011-07-26 23:22:0376 // Only full phone numbers should be set directly. The remaining field
77 // field types are read-only.
[email protected]fcfece42011-07-22 08:29:3278 return;
79 }
80
81 number_ = value;
[email protected]4d11fcd2012-12-05 05:34:4882
83 // Invalidate the cached number.
84 cached_parsed_phone_ = autofill_i18n::PhoneObject();
[email protected]fcfece42011-07-22 08:29:3285}
86
87// Normalize phones if |type| is a whole number:
88// (650)2345678 -> 6502345678
89// 1-800-FLOWERS -> 18003569377
90// If the phone cannot be normalized, returns the stored value verbatim.
[email protected]4d11fcd2012-12-05 05:34:4891string16 PhoneNumber::GetInfo(AutofillFieldType type,
92 const std::string& app_locale) const {
93 if (type == PHONE_HOME_WHOLE_NUMBER) {
94 // Whole numbers require special handling: If normalization for the number
95 // fails, return the non-normalized number instead.
96 string16 phone = GetRawInfo(type);
[email protected]fcfece42011-07-22 08:29:3297
[email protected]4d11fcd2012-12-05 05:34:4898 // TODO(isherman): Can/should this use the cached_parsed_phone_?
99 string16 normalized_phone =
100 autofill_i18n::NormalizePhoneNumber(phone, GetRegion(app_locale));
101 return !normalized_phone.empty() ? normalized_phone : phone;
102 }
[email protected]fcfece42011-07-22 08:29:32103
[email protected]4d11fcd2012-12-05 05:34:48104 UpdateCacheIfNeeded(app_locale);
105 if (!cached_parsed_phone_.IsValidNumber())
106 return string16();
107
108 switch (type) {
109 case PHONE_HOME_NUMBER:
110 return cached_parsed_phone_.GetNumber();
111
112 case PHONE_HOME_CITY_CODE:
113 return cached_parsed_phone_.GetCityCode();
114
115 case PHONE_HOME_COUNTRY_CODE:
116 return cached_parsed_phone_.GetCountryCode();
117
118 case PHONE_HOME_CITY_AND_NUMBER:
119 return
120 cached_parsed_phone_.GetCityCode() + cached_parsed_phone_.GetNumber();
121
122 case PHONE_HOME_WHOLE_NUMBER:
123 NOTREACHED(); // Should have been handled above.
124 return string16();
125
126 default:
127 NOTREACHED();
128 return string16();
129 }
[email protected]fcfece42011-07-22 08:29:32130}
131
[email protected]4d11fcd2012-12-05 05:34:48132bool PhoneNumber::SetInfo(AutofillFieldType type,
133 const string16& value,
134 const std::string& app_locale) {
[email protected]fcfece42011-07-22 08:29:32135 string16 number = value;
136 StripPunctuation(&number);
[email protected]6b44b582012-11-10 06:31:18137 SetRawInfo(type, number);
[email protected]fcfece42011-07-22 08:29:32138
[email protected]4d11fcd2012-12-05 05:34:48139 if (number_.empty())
140 return true;
141
142 // Normalize the phone number by validating and translating it into a
143 // digits-only format.
144 UpdateCacheIfNeeded(app_locale);
145 number_ = cached_parsed_phone_.GetWholeNumber();
146 return !number_.empty();
[email protected]fcfece42011-07-22 08:29:32147}
148
149void PhoneNumber::GetMatchingTypes(const string16& text,
[email protected]4d11fcd2012-12-05 05:34:48150 const std::string& app_locale,
[email protected]fcfece42011-07-22 08:29:32151 FieldTypeSet* matching_types) const {
152 string16 stripped_text = text;
153 StripPunctuation(&stripped_text);
[email protected]4d11fcd2012-12-05 05:34:48154 FormGroup::GetMatchingTypes(stripped_text, app_locale, matching_types);
[email protected]fcfece42011-07-22 08:29:32155
156 // For US numbers, also compare to the three-digit prefix and the four-digit
[email protected]4ef55f8c12011-09-17 00:06:54157 // suffix, since web sites often split numbers into these two fields.
[email protected]4d11fcd2012-12-05 05:34:48158 string16 number = GetInfo(PHONE_HOME_NUMBER, app_locale);
159 if (GetRegion(app_locale) == "US" &&
160 number.size() == (kPrefixLength + kSuffixLength)) {
[email protected]fcfece42011-07-22 08:29:32161 string16 prefix = number.substr(kPrefixOffset, kPrefixLength);
162 string16 suffix = number.substr(kSuffixOffset, kSuffixLength);
163 if (text == prefix || text == suffix)
[email protected]4ef55f8c12011-09-17 00:06:54164 matching_types->insert(PHONE_HOME_NUMBER);
[email protected]fcfece42011-07-22 08:29:32165 }
166
[email protected]4d11fcd2012-12-05 05:34:48167 string16 whole_number = GetInfo(PHONE_HOME_WHOLE_NUMBER, app_locale);
168 if (!whole_number.empty()) {
169 string16 normalized_number =
170 autofill_i18n::NormalizePhoneNumber(text, GetRegion(app_locale));
171 if (normalized_number == whole_number)
172 matching_types->insert(PHONE_HOME_WHOLE_NUMBER);
[email protected]11c2bdd12011-05-23 18:24:32173 }
174}
175
[email protected]4d11fcd2012-12-05 05:34:48176std::string PhoneNumber::GetRegion(const std::string& app_locale) const {
177 const std::string country_code = profile_->CountryCode();
178 if (country_code.empty())
179 return AutofillCountry::CountryCodeForLocale(app_locale);
[email protected]11c2bdd12011-05-23 18:24:32180
[email protected]4d11fcd2012-12-05 05:34:48181 return country_code;
[email protected]11c2bdd12011-05-23 18:24:32182}
183
[email protected]4d11fcd2012-12-05 05:34:48184void PhoneNumber::UpdateCacheIfNeeded(const std::string& app_locale) const {
185 std::string region = GetRegion(app_locale);
[email protected]442405062012-11-28 05:36:18186 if (!number_.empty() && cached_parsed_phone_.GetRegion() != region)
187 cached_parsed_phone_ = autofill_i18n::PhoneObject(number_, region);
[email protected]11c2bdd12011-05-23 18:24:32188}
189
[email protected]4ef55f8c12011-09-17 00:06:54190PhoneNumber::PhoneCombineHelper::PhoneCombineHelper() {
[email protected]fcfece42011-07-22 08:29:32191}
192
193PhoneNumber::PhoneCombineHelper::~PhoneCombineHelper() {
194}
195
[email protected]11c2bdd12011-05-23 18:24:32196bool PhoneNumber::PhoneCombineHelper::SetInfo(AutofillFieldType field_type,
197 const string16& value) {
[email protected]4ef55f8c12011-09-17 00:06:54198 if (field_type == PHONE_HOME_COUNTRY_CODE) {
[email protected]11c2bdd12011-05-23 18:24:32199 country_ = value;
200 return true;
[email protected]fcfece42011-07-22 08:29:32201 }
202
[email protected]4ef55f8c12011-09-17 00:06:54203 if (field_type == PHONE_HOME_CITY_CODE) {
[email protected]11c2bdd12011-05-23 18:24:32204 city_ = value;
205 return true;
[email protected]fcfece42011-07-22 08:29:32206 }
207
[email protected]4ef55f8c12011-09-17 00:06:54208 if (field_type == PHONE_HOME_CITY_AND_NUMBER) {
[email protected]11c2bdd12011-05-23 18:24:32209 phone_ = value;
210 return true;
[email protected]fcfece42011-07-22 08:29:32211 }
212
[email protected]4ef55f8c12011-09-17 00:06:54213 if (field_type == PHONE_HOME_WHOLE_NUMBER) {
[email protected]fcfece42011-07-22 08:29:32214 whole_number_ = value;
215 return true;
216 }
217
[email protected]4ef55f8c12011-09-17 00:06:54218 if (field_type == PHONE_HOME_NUMBER) {
[email protected]11c2bdd12011-05-23 18:24:32219 phone_.append(value);
220 return true;
[email protected]11c2bdd12011-05-23 18:24:32221 }
[email protected]fcfece42011-07-22 08:29:32222
223 return false;
[email protected]9b435be92010-03-04 21:20:15224}
225
[email protected]442405062012-11-28 05:36:18226bool PhoneNumber::PhoneCombineHelper::ParseNumber(const std::string& region,
[email protected]11c2bdd12011-05-23 18:24:32227 string16* value) {
[email protected]fcfece42011-07-22 08:29:32228 if (!whole_number_.empty()) {
229 *value = whole_number_;
230 return true;
231 }
232
[email protected]11c2bdd12011-05-23 18:24:32233 return autofill_i18n::ConstructPhoneNumber(
[email protected]4d11fcd2012-12-05 05:34:48234 country_, city_, phone_, region,
[email protected]11c2bdd12011-05-23 18:24:32235 (country_.empty() ?
236 autofill_i18n::NATIONAL : autofill_i18n::INTERNATIONAL),
237 value);
[email protected]3db3ff62010-01-07 00:35:39238}
239
[email protected]fcfece42011-07-22 08:29:32240bool PhoneNumber::PhoneCombineHelper::IsEmpty() const {
241 return phone_.empty() && whole_number_.empty();
[email protected]3db3ff62010-01-07 00:35:39242}