blob: 703e63efcc19e338c205a455b28b04ebf2794ad7 [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
[email protected]e4b2fa32013-03-09 22:56:565#include "components/autofill/browser/phone_number.h"
[email protected]3db3ff62010-01-07 00:35:396
7#include "base/basictypes.h"
8#include "base/string_util.h"
[email protected]3ea1b182013-02-08 22:38:419#include "base/strings/string_number_conversions.h"
[email protected]11c2bdd12011-05-23 18:24:3210#include "base/utf_string_conversions.h"
[email protected]e4b2fa32013-03-09 22:56:5611#include "components/autofill/browser/autofill_country.h"
12#include "components/autofill/browser/autofill_profile.h"
13#include "components/autofill/browser/autofill_type.h"
14#include "components/autofill/browser/field_types.h"
15#include "components/autofill/browser/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]3de6a5982013-01-10 01:45:4431// Returns the region code for this phone number, which is an ISO 3166 2-letter
32// country code. The returned value is based on the |profile|; if the |profile|
33// does not have a country code associated with it, falls back to the country
34// code corresponding to the |app_locale|.
35std::string GetRegion(const AutofillProfile& profile,
36 const std::string& app_locale) {
[email protected]ed005f6f2013-04-05 17:03:5637 string16 country_code = profile.GetRawInfo(ADDRESS_HOME_COUNTRY);
[email protected]3de6a5982013-01-10 01:45:4438 if (!country_code.empty())
[email protected]ed005f6f2013-04-05 17:03:5639 return UTF16ToASCII(country_code);
[email protected]3de6a5982013-01-10 01:45:4440
41 return AutofillCountry::CountryCodeForLocale(app_locale);
42}
43
[email protected]fcfece42011-07-22 08:29:3244} // namespace
45
46PhoneNumber::PhoneNumber(AutofillProfile* profile)
[email protected]4ef55f8c12011-09-17 00:06:5447 : profile_(profile) {
[email protected]11c2bdd12011-05-23 18:24:3248}
[email protected]8e383412010-10-19 16:57:0349
[email protected]651dd5c32011-09-27 17:04:3850PhoneNumber::PhoneNumber(const PhoneNumber& number)
[email protected]7df904d2013-01-15 22:33:2251 : profile_(NULL) {
[email protected]43897242011-03-09 03:52:1152 *this = number;
53}
54
[email protected]8e383412010-10-19 16:57:0355PhoneNumber::~PhoneNumber() {}
56
[email protected]43897242011-03-09 03:52:1157PhoneNumber& PhoneNumber::operator=(const PhoneNumber& number) {
58 if (this == &number)
59 return *this;
[email protected]4ef55f8c12011-09-17 00:06:5460
[email protected]fcfece42011-07-22 08:29:3261 number_ = number.number_;
62 profile_ = number.profile_;
[email protected]35734e92011-06-24 21:06:2563 cached_parsed_phone_ = number.cached_parsed_phone_;
[email protected]43897242011-03-09 03:52:1164 return *this;
65}
66
[email protected]fcfece42011-07-22 08:29:3267void PhoneNumber::GetSupportedTypes(FieldTypeSet* supported_types) const {
[email protected]4ef55f8c12011-09-17 00:06:5468 supported_types->insert(PHONE_HOME_WHOLE_NUMBER);
69 supported_types->insert(PHONE_HOME_NUMBER);
70 supported_types->insert(PHONE_HOME_CITY_CODE);
71 supported_types->insert(PHONE_HOME_CITY_AND_NUMBER);
72 supported_types->insert(PHONE_HOME_COUNTRY_CODE);
[email protected]cea1d112010-07-01 00:57:3373}
74
[email protected]6b44b582012-11-10 06:31:1875string16 PhoneNumber::GetRawInfo(AutofillFieldType type) const {
[email protected]4ef55f8c12011-09-17 00:06:5476 if (type == PHONE_HOME_WHOLE_NUMBER)
[email protected]11c2bdd12011-05-23 18:24:3277 return number_;
[email protected]35734e92011-06-24 21:06:2578
[email protected]4d11fcd2012-12-05 05:34:4879 // Only the whole number is available as raw data. All of the other types are
80 // parsed from this raw info, and parsing requires knowledge of the phone
81 // number's region, which is only available via GetInfo().
[email protected]cea1d112010-07-01 00:57:3382 return string16();
[email protected]3db3ff62010-01-07 00:35:3983}
84
[email protected]6b44b582012-11-10 06:31:1885void PhoneNumber::SetRawInfo(AutofillFieldType type, const string16& value) {
[email protected]13405292011-10-07 22:37:0986 if (type != PHONE_HOME_CITY_AND_NUMBER &&
87 type != PHONE_HOME_WHOLE_NUMBER) {
[email protected]08f691b2011-07-26 23:22:0388 // Only full phone numbers should be set directly. The remaining field
89 // field types are read-only.
[email protected]fcfece42011-07-22 08:29:3290 return;
91 }
92
93 number_ = value;
[email protected]4d11fcd2012-12-05 05:34:4894
95 // Invalidate the cached number.
96 cached_parsed_phone_ = autofill_i18n::PhoneObject();
[email protected]fcfece42011-07-22 08:29:3297}
98
99// Normalize phones if |type| is a whole number:
100// (650)2345678 -> 6502345678
101// 1-800-FLOWERS -> 18003569377
102// If the phone cannot be normalized, returns the stored value verbatim.
[email protected]4d11fcd2012-12-05 05:34:48103string16 PhoneNumber::GetInfo(AutofillFieldType type,
104 const std::string& app_locale) const {
[email protected]4d11fcd2012-12-05 05:34:48105 UpdateCacheIfNeeded(app_locale);
[email protected]7df904d2013-01-15 22:33:22106
107 // Queries for whole numbers will return the non-normalized number if
108 // normalization for the number fails. All other field types require
109 // normalization.
110 if (type != PHONE_HOME_WHOLE_NUMBER && !cached_parsed_phone_.IsValidNumber())
[email protected]4d11fcd2012-12-05 05:34:48111 return string16();
112
113 switch (type) {
[email protected]7df904d2013-01-15 22:33:22114 case PHONE_HOME_WHOLE_NUMBER:
115 return cached_parsed_phone_.GetWholeNumber();
116
[email protected]4d11fcd2012-12-05 05:34:48117 case PHONE_HOME_NUMBER:
[email protected]7df904d2013-01-15 22:33:22118 return cached_parsed_phone_.number();
[email protected]4d11fcd2012-12-05 05:34:48119
120 case PHONE_HOME_CITY_CODE:
[email protected]7df904d2013-01-15 22:33:22121 return cached_parsed_phone_.city_code();
[email protected]4d11fcd2012-12-05 05:34:48122
123 case PHONE_HOME_COUNTRY_CODE:
[email protected]7df904d2013-01-15 22:33:22124 return cached_parsed_phone_.country_code();
[email protected]4d11fcd2012-12-05 05:34:48125
126 case PHONE_HOME_CITY_AND_NUMBER:
127 return
[email protected]7df904d2013-01-15 22:33:22128 cached_parsed_phone_.city_code() + cached_parsed_phone_.number();
[email protected]4d11fcd2012-12-05 05:34:48129
130 default:
131 NOTREACHED();
132 return string16();
133 }
[email protected]fcfece42011-07-22 08:29:32134}
135
[email protected]4d11fcd2012-12-05 05:34:48136bool PhoneNumber::SetInfo(AutofillFieldType type,
137 const string16& value,
138 const std::string& app_locale) {
[email protected]7df904d2013-01-15 22:33:22139 SetRawInfo(type, value);
[email protected]fcfece42011-07-22 08:29:32140
[email protected]4d11fcd2012-12-05 05:34:48141 if (number_.empty())
142 return true;
143
[email protected]7df904d2013-01-15 22:33:22144 // Store a formatted (i.e., pretty printed) version of the number.
[email protected]4d11fcd2012-12-05 05:34:48145 UpdateCacheIfNeeded(app_locale);
[email protected]7df904d2013-01-15 22:33:22146 number_ = cached_parsed_phone_.GetFormattedNumber();
[email protected]4d11fcd2012-12-05 05:34:48147 return !number_.empty();
[email protected]fcfece42011-07-22 08:29:32148}
149
150void PhoneNumber::GetMatchingTypes(const string16& text,
[email protected]4d11fcd2012-12-05 05:34:48151 const std::string& app_locale,
[email protected]fcfece42011-07-22 08:29:32152 FieldTypeSet* matching_types) const {
153 string16 stripped_text = text;
154 StripPunctuation(&stripped_text);
[email protected]4d11fcd2012-12-05 05:34:48155 FormGroup::GetMatchingTypes(stripped_text, app_locale, matching_types);
[email protected]fcfece42011-07-22 08:29:32156
157 // For US numbers, also compare to the three-digit prefix and the four-digit
[email protected]4ef55f8c12011-09-17 00:06:54158 // suffix, since web sites often split numbers into these two fields.
[email protected]4d11fcd2012-12-05 05:34:48159 string16 number = GetInfo(PHONE_HOME_NUMBER, app_locale);
[email protected]3de6a5982013-01-10 01:45:44160 if (GetRegion(*profile_, app_locale) == "US" &&
[email protected]4d11fcd2012-12-05 05:34:48161 number.size() == (kPrefixLength + kSuffixLength)) {
[email protected]fcfece42011-07-22 08:29:32162 string16 prefix = number.substr(kPrefixOffset, kPrefixLength);
163 string16 suffix = number.substr(kSuffixOffset, kSuffixLength);
164 if (text == prefix || text == suffix)
[email protected]4ef55f8c12011-09-17 00:06:54165 matching_types->insert(PHONE_HOME_NUMBER);
[email protected]fcfece42011-07-22 08:29:32166 }
167
[email protected]4d11fcd2012-12-05 05:34:48168 string16 whole_number = GetInfo(PHONE_HOME_WHOLE_NUMBER, app_locale);
169 if (!whole_number.empty()) {
170 string16 normalized_number =
[email protected]3de6a5982013-01-10 01:45:44171 autofill_i18n::NormalizePhoneNumber(text,
172 GetRegion(*profile_, app_locale));
[email protected]4d11fcd2012-12-05 05:34:48173 if (normalized_number == whole_number)
174 matching_types->insert(PHONE_HOME_WHOLE_NUMBER);
[email protected]11c2bdd12011-05-23 18:24:32175 }
176}
177
[email protected]4d11fcd2012-12-05 05:34:48178void PhoneNumber::UpdateCacheIfNeeded(const std::string& app_locale) const {
[email protected]3de6a5982013-01-10 01:45:44179 std::string region = GetRegion(*profile_, app_locale);
[email protected]7df904d2013-01-15 22:33:22180 if (!number_.empty() && cached_parsed_phone_.region() != region)
[email protected]442405062012-11-28 05:36:18181 cached_parsed_phone_ = autofill_i18n::PhoneObject(number_, region);
[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]3de6a5982013-01-10 01:45:44220bool PhoneNumber::PhoneCombineHelper::ParseNumber(
221 const AutofillProfile& profile,
222 const std::string& app_locale,
223 string16* value) {
224 if (IsEmpty())
225 return false;
226
[email protected]fcfece42011-07-22 08:29:32227 if (!whole_number_.empty()) {
228 *value = whole_number_;
229 return true;
230 }
231
[email protected]11c2bdd12011-05-23 18:24:32232 return autofill_i18n::ConstructPhoneNumber(
[email protected]7df904d2013-01-15 22:33:22233 country_, city_, phone_, GetRegion(profile, app_locale), value);
[email protected]3db3ff62010-01-07 00:35:39234}
235
[email protected]fcfece42011-07-22 08:29:32236bool PhoneNumber::PhoneCombineHelper::IsEmpty() const {
237 return phone_.empty() && whole_number_.empty();
[email protected]3db3ff62010-01-07 00:35:39238}