blob: 4b551de4e7a7d9a543bba41c842f04bae07ba8be [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]d5ca8fb2013-04-11 17:54:3127void StripPunctuation(base::string16* number) {
[email protected]fcfece42011-07-22 08:29:3228 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]d5ca8fb2013-04-11 17:54:3137 base::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]d5ca8fb2013-04-11 17:54:3175base::string16 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]d5ca8fb2013-04-11 17:54:3182 return base::string16();
[email protected]3db3ff62010-01-07 00:35:3983}
84
[email protected]d5ca8fb2013-04-11 17:54:3185void PhoneNumber::SetRawInfo(AutofillFieldType type,
86 const base::string16& value) {
[email protected]13405292011-10-07 22:37:0987 if (type != PHONE_HOME_CITY_AND_NUMBER &&
88 type != PHONE_HOME_WHOLE_NUMBER) {
[email protected]08f691b2011-07-26 23:22:0389 // Only full phone numbers should be set directly. The remaining field
90 // field types are read-only.
[email protected]fcfece42011-07-22 08:29:3291 return;
92 }
93
94 number_ = value;
[email protected]4d11fcd2012-12-05 05:34:4895
96 // Invalidate the cached number.
97 cached_parsed_phone_ = autofill_i18n::PhoneObject();
[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.
[email protected]d5ca8fb2013-04-11 17:54:31104base::string16 PhoneNumber::GetInfo(AutofillFieldType type,
[email protected]4d11fcd2012-12-05 05:34:48105 const std::string& app_locale) const {
[email protected]4d11fcd2012-12-05 05:34:48106 UpdateCacheIfNeeded(app_locale);
[email protected]7df904d2013-01-15 22:33:22107
108 // Queries for whole numbers will return the non-normalized number if
109 // normalization for the number fails. All other field types require
110 // normalization.
111 if (type != PHONE_HOME_WHOLE_NUMBER && !cached_parsed_phone_.IsValidNumber())
[email protected]d5ca8fb2013-04-11 17:54:31112 return base::string16();
[email protected]4d11fcd2012-12-05 05:34:48113
114 switch (type) {
[email protected]7df904d2013-01-15 22:33:22115 case PHONE_HOME_WHOLE_NUMBER:
116 return cached_parsed_phone_.GetWholeNumber();
117
[email protected]4d11fcd2012-12-05 05:34:48118 case PHONE_HOME_NUMBER:
[email protected]7df904d2013-01-15 22:33:22119 return cached_parsed_phone_.number();
[email protected]4d11fcd2012-12-05 05:34:48120
121 case PHONE_HOME_CITY_CODE:
[email protected]7df904d2013-01-15 22:33:22122 return cached_parsed_phone_.city_code();
[email protected]4d11fcd2012-12-05 05:34:48123
124 case PHONE_HOME_COUNTRY_CODE:
[email protected]7df904d2013-01-15 22:33:22125 return cached_parsed_phone_.country_code();
[email protected]4d11fcd2012-12-05 05:34:48126
127 case PHONE_HOME_CITY_AND_NUMBER:
128 return
[email protected]7df904d2013-01-15 22:33:22129 cached_parsed_phone_.city_code() + cached_parsed_phone_.number();
[email protected]4d11fcd2012-12-05 05:34:48130
131 default:
132 NOTREACHED();
[email protected]d5ca8fb2013-04-11 17:54:31133 return base::string16();
[email protected]4d11fcd2012-12-05 05:34:48134 }
[email protected]fcfece42011-07-22 08:29:32135}
136
[email protected]4d11fcd2012-12-05 05:34:48137bool PhoneNumber::SetInfo(AutofillFieldType type,
[email protected]d5ca8fb2013-04-11 17:54:31138 const base::string16& value,
[email protected]4d11fcd2012-12-05 05:34:48139 const std::string& app_locale) {
[email protected]7df904d2013-01-15 22:33:22140 SetRawInfo(type, value);
[email protected]fcfece42011-07-22 08:29:32141
[email protected]4d11fcd2012-12-05 05:34:48142 if (number_.empty())
143 return true;
144
[email protected]7df904d2013-01-15 22:33:22145 // Store a formatted (i.e., pretty printed) version of the number.
[email protected]4d11fcd2012-12-05 05:34:48146 UpdateCacheIfNeeded(app_locale);
[email protected]7df904d2013-01-15 22:33:22147 number_ = cached_parsed_phone_.GetFormattedNumber();
[email protected]4d11fcd2012-12-05 05:34:48148 return !number_.empty();
[email protected]fcfece42011-07-22 08:29:32149}
150
[email protected]d5ca8fb2013-04-11 17:54:31151void PhoneNumber::GetMatchingTypes(const base::string16& text,
[email protected]4d11fcd2012-12-05 05:34:48152 const std::string& app_locale,
[email protected]fcfece42011-07-22 08:29:32153 FieldTypeSet* matching_types) const {
[email protected]d5ca8fb2013-04-11 17:54:31154 base::string16 stripped_text = text;
[email protected]fcfece42011-07-22 08:29:32155 StripPunctuation(&stripped_text);
[email protected]4d11fcd2012-12-05 05:34:48156 FormGroup::GetMatchingTypes(stripped_text, app_locale, matching_types);
[email protected]fcfece42011-07-22 08:29:32157
158 // For US numbers, also compare to the three-digit prefix and the four-digit
[email protected]4ef55f8c12011-09-17 00:06:54159 // suffix, since web sites often split numbers into these two fields.
[email protected]d5ca8fb2013-04-11 17:54:31160 base::string16 number = GetInfo(PHONE_HOME_NUMBER, app_locale);
[email protected]3de6a5982013-01-10 01:45:44161 if (GetRegion(*profile_, app_locale) == "US" &&
[email protected]4d11fcd2012-12-05 05:34:48162 number.size() == (kPrefixLength + kSuffixLength)) {
[email protected]d5ca8fb2013-04-11 17:54:31163 base::string16 prefix = number.substr(kPrefixOffset, kPrefixLength);
164 base::string16 suffix = number.substr(kSuffixOffset, kSuffixLength);
[email protected]fcfece42011-07-22 08:29:32165 if (text == prefix || text == suffix)
[email protected]4ef55f8c12011-09-17 00:06:54166 matching_types->insert(PHONE_HOME_NUMBER);
[email protected]fcfece42011-07-22 08:29:32167 }
168
[email protected]d5ca8fb2013-04-11 17:54:31169 base::string16 whole_number = GetInfo(PHONE_HOME_WHOLE_NUMBER, app_locale);
[email protected]4d11fcd2012-12-05 05:34:48170 if (!whole_number.empty()) {
[email protected]d5ca8fb2013-04-11 17:54:31171 base::string16 normalized_number =
[email protected]3de6a5982013-01-10 01:45:44172 autofill_i18n::NormalizePhoneNumber(text,
173 GetRegion(*profile_, app_locale));
[email protected]4d11fcd2012-12-05 05:34:48174 if (normalized_number == whole_number)
175 matching_types->insert(PHONE_HOME_WHOLE_NUMBER);
[email protected]11c2bdd12011-05-23 18:24:32176 }
177}
178
[email protected]4d11fcd2012-12-05 05:34:48179void PhoneNumber::UpdateCacheIfNeeded(const std::string& app_locale) const {
[email protected]3de6a5982013-01-10 01:45:44180 std::string region = GetRegion(*profile_, app_locale);
[email protected]7df904d2013-01-15 22:33:22181 if (!number_.empty() && cached_parsed_phone_.region() != region)
[email protected]442405062012-11-28 05:36:18182 cached_parsed_phone_ = autofill_i18n::PhoneObject(number_, region);
[email protected]11c2bdd12011-05-23 18:24:32183}
184
[email protected]4ef55f8c12011-09-17 00:06:54185PhoneNumber::PhoneCombineHelper::PhoneCombineHelper() {
[email protected]fcfece42011-07-22 08:29:32186}
187
188PhoneNumber::PhoneCombineHelper::~PhoneCombineHelper() {
189}
190
[email protected]11c2bdd12011-05-23 18:24:32191bool PhoneNumber::PhoneCombineHelper::SetInfo(AutofillFieldType field_type,
[email protected]d5ca8fb2013-04-11 17:54:31192 const base::string16& value) {
[email protected]4ef55f8c12011-09-17 00:06:54193 if (field_type == PHONE_HOME_COUNTRY_CODE) {
[email protected]11c2bdd12011-05-23 18:24:32194 country_ = value;
195 return true;
[email protected]fcfece42011-07-22 08:29:32196 }
197
[email protected]4ef55f8c12011-09-17 00:06:54198 if (field_type == PHONE_HOME_CITY_CODE) {
[email protected]11c2bdd12011-05-23 18:24:32199 city_ = 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_AND_NUMBER) {
[email protected]11c2bdd12011-05-23 18:24:32204 phone_ = 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_WHOLE_NUMBER) {
[email protected]fcfece42011-07-22 08:29:32209 whole_number_ = value;
210 return true;
211 }
212
[email protected]4ef55f8c12011-09-17 00:06:54213 if (field_type == PHONE_HOME_NUMBER) {
[email protected]11c2bdd12011-05-23 18:24:32214 phone_.append(value);
215 return true;
[email protected]11c2bdd12011-05-23 18:24:32216 }
[email protected]fcfece42011-07-22 08:29:32217
218 return false;
[email protected]9b435be92010-03-04 21:20:15219}
220
[email protected]3de6a5982013-01-10 01:45:44221bool PhoneNumber::PhoneCombineHelper::ParseNumber(
222 const AutofillProfile& profile,
223 const std::string& app_locale,
[email protected]d5ca8fb2013-04-11 17:54:31224 base::string16* value) {
[email protected]3de6a5982013-01-10 01:45:44225 if (IsEmpty())
226 return false;
227
[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]7df904d2013-01-15 22:33:22234 country_, city_, phone_, GetRegion(profile, app_locale), value);
[email protected]3db3ff62010-01-07 00:35:39235}
236
[email protected]fcfece42011-07-22 08:29:32237bool PhoneNumber::PhoneCombineHelper::IsEmpty() const {
238 return phone_.empty() && whole_number_.empty();
[email protected]3db3ff62010-01-07 00:35:39239}