blob: 2dcd7a2cd87c9bdf4b862daa9d381981dbfc0ddc [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]e217c5632013-04-12 19:11:4817namespace autofill {
[email protected]9b435be92010-03-04 21:20:1518namespace {
[email protected]3db3ff62010-01-07 00:35:3919
[email protected]9b435be92010-03-04 21:20:1520const char16 kPhoneNumberSeparators[] = { ' ', '.', '(', ')', '-', 0 };
21
22// The number of digits in a phone number.
23const size_t kPhoneNumberLength = 7;
24
25// The number of digits in an area code.
26const size_t kPhoneCityCodeLength = 3;
27
[email protected]d5ca8fb2013-04-11 17:54:3128void StripPunctuation(base::string16* number) {
[email protected]fcfece42011-07-22 08:29:3229 RemoveChars(*number, kPhoneNumberSeparators, number);
[email protected]11c2bdd12011-05-23 18:24:3230}
31
[email protected]3de6a5982013-01-10 01:45:4432// Returns the region code for this phone number, which is an ISO 3166 2-letter
33// country code. The returned value is based on the |profile|; if the |profile|
34// does not have a country code associated with it, falls back to the country
35// code corresponding to the |app_locale|.
36std::string GetRegion(const AutofillProfile& profile,
37 const std::string& app_locale) {
[email protected]d5ca8fb2013-04-11 17:54:3138 base::string16 country_code = profile.GetRawInfo(ADDRESS_HOME_COUNTRY);
[email protected]3de6a5982013-01-10 01:45:4439 if (!country_code.empty())
[email protected]ed005f6f2013-04-05 17:03:5640 return UTF16ToASCII(country_code);
[email protected]3de6a5982013-01-10 01:45:4441
42 return AutofillCountry::CountryCodeForLocale(app_locale);
43}
44
[email protected]fcfece42011-07-22 08:29:3245} // namespace
46
47PhoneNumber::PhoneNumber(AutofillProfile* profile)
[email protected]4ef55f8c12011-09-17 00:06:5448 : profile_(profile) {
[email protected]11c2bdd12011-05-23 18:24:3249}
[email protected]8e383412010-10-19 16:57:0350
[email protected]651dd5c32011-09-27 17:04:3851PhoneNumber::PhoneNumber(const PhoneNumber& number)
[email protected]7df904d2013-01-15 22:33:2252 : profile_(NULL) {
[email protected]43897242011-03-09 03:52:1153 *this = number;
54}
55
[email protected]8e383412010-10-19 16:57:0356PhoneNumber::~PhoneNumber() {}
57
[email protected]43897242011-03-09 03:52:1158PhoneNumber& PhoneNumber::operator=(const PhoneNumber& number) {
59 if (this == &number)
60 return *this;
[email protected]4ef55f8c12011-09-17 00:06:5461
[email protected]fcfece42011-07-22 08:29:3262 number_ = number.number_;
63 profile_ = number.profile_;
[email protected]35734e92011-06-24 21:06:2564 cached_parsed_phone_ = number.cached_parsed_phone_;
[email protected]43897242011-03-09 03:52:1165 return *this;
66}
67
[email protected]fcfece42011-07-22 08:29:3268void PhoneNumber::GetSupportedTypes(FieldTypeSet* supported_types) const {
[email protected]4ef55f8c12011-09-17 00:06:5469 supported_types->insert(PHONE_HOME_WHOLE_NUMBER);
70 supported_types->insert(PHONE_HOME_NUMBER);
71 supported_types->insert(PHONE_HOME_CITY_CODE);
72 supported_types->insert(PHONE_HOME_CITY_AND_NUMBER);
73 supported_types->insert(PHONE_HOME_COUNTRY_CODE);
[email protected]cea1d112010-07-01 00:57:3374}
75
[email protected]d5ca8fb2013-04-11 17:54:3176base::string16 PhoneNumber::GetRawInfo(AutofillFieldType type) const {
[email protected]4ef55f8c12011-09-17 00:06:5477 if (type == PHONE_HOME_WHOLE_NUMBER)
[email protected]11c2bdd12011-05-23 18:24:3278 return number_;
[email protected]35734e92011-06-24 21:06:2579
[email protected]4d11fcd2012-12-05 05:34:4880 // Only the whole number is available as raw data. All of the other types are
81 // parsed from this raw info, and parsing requires knowledge of the phone
82 // number's region, which is only available via GetInfo().
[email protected]d5ca8fb2013-04-11 17:54:3183 return base::string16();
[email protected]3db3ff62010-01-07 00:35:3984}
85
[email protected]d5ca8fb2013-04-11 17:54:3186void PhoneNumber::SetRawInfo(AutofillFieldType type,
87 const base::string16& value) {
[email protected]13405292011-10-07 22:37:0988 if (type != PHONE_HOME_CITY_AND_NUMBER &&
89 type != PHONE_HOME_WHOLE_NUMBER) {
[email protected]08f691b2011-07-26 23:22:0390 // Only full phone numbers should be set directly. The remaining field
91 // field types are read-only.
[email protected]fcfece42011-07-22 08:29:3292 return;
93 }
94
95 number_ = value;
[email protected]4d11fcd2012-12-05 05:34:4896
97 // Invalidate the cached number.
[email protected]e217c5632013-04-12 19:11:4898 cached_parsed_phone_ = i18n::PhoneObject();
[email protected]fcfece42011-07-22 08:29:3299}
100
101// Normalize phones if |type| is a whole number:
102// (650)2345678 -> 6502345678
103// 1-800-FLOWERS -> 18003569377
104// If the phone cannot be normalized, returns the stored value verbatim.
[email protected]d5ca8fb2013-04-11 17:54:31105base::string16 PhoneNumber::GetInfo(AutofillFieldType type,
[email protected]4d11fcd2012-12-05 05:34:48106 const std::string& app_locale) const {
[email protected]4d11fcd2012-12-05 05:34:48107 UpdateCacheIfNeeded(app_locale);
[email protected]7df904d2013-01-15 22:33:22108
109 // Queries for whole numbers will return the non-normalized number if
110 // normalization for the number fails. All other field types require
111 // normalization.
112 if (type != PHONE_HOME_WHOLE_NUMBER && !cached_parsed_phone_.IsValidNumber())
[email protected]d5ca8fb2013-04-11 17:54:31113 return base::string16();
[email protected]4d11fcd2012-12-05 05:34:48114
115 switch (type) {
[email protected]7df904d2013-01-15 22:33:22116 case PHONE_HOME_WHOLE_NUMBER:
117 return cached_parsed_phone_.GetWholeNumber();
118
[email protected]4d11fcd2012-12-05 05:34:48119 case PHONE_HOME_NUMBER:
[email protected]7df904d2013-01-15 22:33:22120 return cached_parsed_phone_.number();
[email protected]4d11fcd2012-12-05 05:34:48121
122 case PHONE_HOME_CITY_CODE:
[email protected]7df904d2013-01-15 22:33:22123 return cached_parsed_phone_.city_code();
[email protected]4d11fcd2012-12-05 05:34:48124
125 case PHONE_HOME_COUNTRY_CODE:
[email protected]7df904d2013-01-15 22:33:22126 return cached_parsed_phone_.country_code();
[email protected]4d11fcd2012-12-05 05:34:48127
128 case PHONE_HOME_CITY_AND_NUMBER:
129 return
[email protected]7df904d2013-01-15 22:33:22130 cached_parsed_phone_.city_code() + cached_parsed_phone_.number();
[email protected]4d11fcd2012-12-05 05:34:48131
132 default:
133 NOTREACHED();
[email protected]d5ca8fb2013-04-11 17:54:31134 return base::string16();
[email protected]4d11fcd2012-12-05 05:34:48135 }
[email protected]fcfece42011-07-22 08:29:32136}
137
[email protected]4d11fcd2012-12-05 05:34:48138bool PhoneNumber::SetInfo(AutofillFieldType type,
[email protected]d5ca8fb2013-04-11 17:54:31139 const base::string16& value,
[email protected]4d11fcd2012-12-05 05:34:48140 const std::string& app_locale) {
[email protected]7df904d2013-01-15 22:33:22141 SetRawInfo(type, value);
[email protected]fcfece42011-07-22 08:29:32142
[email protected]4d11fcd2012-12-05 05:34:48143 if (number_.empty())
144 return true;
145
[email protected]7df904d2013-01-15 22:33:22146 // Store a formatted (i.e., pretty printed) version of the number.
[email protected]4d11fcd2012-12-05 05:34:48147 UpdateCacheIfNeeded(app_locale);
[email protected]7df904d2013-01-15 22:33:22148 number_ = cached_parsed_phone_.GetFormattedNumber();
[email protected]4d11fcd2012-12-05 05:34:48149 return !number_.empty();
[email protected]fcfece42011-07-22 08:29:32150}
151
[email protected]d5ca8fb2013-04-11 17:54:31152void PhoneNumber::GetMatchingTypes(const base::string16& text,
[email protected]4d11fcd2012-12-05 05:34:48153 const std::string& app_locale,
[email protected]fcfece42011-07-22 08:29:32154 FieldTypeSet* matching_types) const {
[email protected]d5ca8fb2013-04-11 17:54:31155 base::string16 stripped_text = text;
[email protected]fcfece42011-07-22 08:29:32156 StripPunctuation(&stripped_text);
[email protected]4d11fcd2012-12-05 05:34:48157 FormGroup::GetMatchingTypes(stripped_text, app_locale, matching_types);
[email protected]fcfece42011-07-22 08:29:32158
159 // For US numbers, also compare to the three-digit prefix and the four-digit
[email protected]4ef55f8c12011-09-17 00:06:54160 // suffix, since web sites often split numbers into these two fields.
[email protected]d5ca8fb2013-04-11 17:54:31161 base::string16 number = GetInfo(PHONE_HOME_NUMBER, app_locale);
[email protected]3de6a5982013-01-10 01:45:44162 if (GetRegion(*profile_, app_locale) == "US" &&
[email protected]4d11fcd2012-12-05 05:34:48163 number.size() == (kPrefixLength + kSuffixLength)) {
[email protected]d5ca8fb2013-04-11 17:54:31164 base::string16 prefix = number.substr(kPrefixOffset, kPrefixLength);
165 base::string16 suffix = number.substr(kSuffixOffset, kSuffixLength);
[email protected]fcfece42011-07-22 08:29:32166 if (text == prefix || text == suffix)
[email protected]4ef55f8c12011-09-17 00:06:54167 matching_types->insert(PHONE_HOME_NUMBER);
[email protected]fcfece42011-07-22 08:29:32168 }
169
[email protected]d5ca8fb2013-04-11 17:54:31170 base::string16 whole_number = GetInfo(PHONE_HOME_WHOLE_NUMBER, app_locale);
[email protected]4d11fcd2012-12-05 05:34:48171 if (!whole_number.empty()) {
[email protected]d5ca8fb2013-04-11 17:54:31172 base::string16 normalized_number =
[email protected]e217c5632013-04-12 19:11:48173 i18n::NormalizePhoneNumber(text, 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]e217c5632013-04-12 19:11:48182 cached_parsed_phone_ = 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]e217c5632013-04-12 19:11:48233 return 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}
[email protected]e217c5632013-04-12 19:11:48240
241} // namespace autofill