Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / components / autofill / core / browser / phone_number.cc
blob6783677e3e77644882418e3098d1b94727ed3b56
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/autofill/core/browser/phone_number.h"
7 #include "base/basictypes.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "components/autofill/core/browser/autofill_country.h"
12 #include "components/autofill/core/browser/autofill_profile.h"
13 #include "components/autofill/core/browser/autofill_type.h"
14 #include "components/autofill/core/browser/field_types.h"
15 #include "components/autofill/core/browser/phone_number_i18n.h"
17 namespace autofill {
18 namespace {
20 // Returns the region code for this phone number, which is an ISO 3166 2-letter
21 // country code. The returned value is based on the |profile|; if the |profile|
22 // does not have a country code associated with it, falls back to the country
23 // code corresponding to the |app_locale|.
24 std::string GetRegion(const AutofillProfile& profile,
25 const std::string& app_locale) {
26 base::string16 country_code = profile.GetRawInfo(ADDRESS_HOME_COUNTRY);
27 if (!country_code.empty())
28 return base::UTF16ToASCII(country_code);
30 return AutofillCountry::CountryCodeForLocale(app_locale);
33 } // namespace
35 PhoneNumber::PhoneNumber(AutofillProfile* profile)
36 : profile_(profile) {
39 PhoneNumber::PhoneNumber(const PhoneNumber& number)
40 : profile_(NULL) {
41 *this = number;
44 PhoneNumber::~PhoneNumber() {}
46 PhoneNumber& PhoneNumber::operator=(const PhoneNumber& number) {
47 if (this == &number)
48 return *this;
50 number_ = number.number_;
51 profile_ = number.profile_;
52 cached_parsed_phone_ = number.cached_parsed_phone_;
53 return *this;
56 void PhoneNumber::GetSupportedTypes(ServerFieldTypeSet* supported_types) const {
57 supported_types->insert(PHONE_HOME_WHOLE_NUMBER);
58 supported_types->insert(PHONE_HOME_NUMBER);
59 supported_types->insert(PHONE_HOME_CITY_CODE);
60 supported_types->insert(PHONE_HOME_CITY_AND_NUMBER);
61 supported_types->insert(PHONE_HOME_COUNTRY_CODE);
64 base::string16 PhoneNumber::GetRawInfo(ServerFieldType type) const {
65 DCHECK_EQ(PHONE_HOME, AutofillType(type).group());
66 if (type == PHONE_HOME_WHOLE_NUMBER)
67 return number_;
69 // Only the whole number is available as raw data. All of the other types are
70 // parsed from this raw info, and parsing requires knowledge of the phone
71 // number's region, which is only available via GetInfo().
72 return base::string16();
75 void PhoneNumber::SetRawInfo(ServerFieldType type,
76 const base::string16& value) {
77 DCHECK_EQ(PHONE_HOME, AutofillType(type).group());
78 if (type != PHONE_HOME_CITY_AND_NUMBER && type != PHONE_HOME_WHOLE_NUMBER) {
79 // Only full phone numbers should be set directly. The remaining field
80 // field types are read-only.
81 return;
84 number_ = value;
86 // Invalidate the cached number.
87 cached_parsed_phone_ = i18n::PhoneObject();
90 // Normalize phones if |type| is a whole number:
91 // (650)2345678 -> 6502345678
92 // 1-800-FLOWERS -> 18003569377
93 // If the phone cannot be normalized, returns the stored value verbatim.
94 base::string16 PhoneNumber::GetInfo(const AutofillType& type,
95 const std::string& app_locale) const {
96 ServerFieldType storable_type = type.GetStorableType();
97 UpdateCacheIfNeeded(app_locale);
99 // Queries for whole numbers will return the non-normalized number if
100 // normalization for the number fails. All other field types require
101 // normalization.
102 if (storable_type != PHONE_HOME_WHOLE_NUMBER &&
103 !cached_parsed_phone_.IsValidNumber())
104 return base::string16();
106 switch (storable_type) {
107 case PHONE_HOME_WHOLE_NUMBER:
108 return cached_parsed_phone_.GetWholeNumber();
110 case PHONE_HOME_NUMBER:
111 return cached_parsed_phone_.number();
113 case PHONE_HOME_CITY_CODE:
114 return cached_parsed_phone_.city_code();
116 case PHONE_HOME_COUNTRY_CODE:
117 return cached_parsed_phone_.country_code();
119 case PHONE_HOME_CITY_AND_NUMBER:
120 return
121 cached_parsed_phone_.city_code() + cached_parsed_phone_.number();
123 default:
124 NOTREACHED();
125 return base::string16();
129 bool PhoneNumber::SetInfo(const AutofillType& type,
130 const base::string16& value,
131 const std::string& app_locale) {
132 SetRawInfo(type.GetStorableType(), value);
134 if (number_.empty())
135 return true;
137 // Store a formatted (i.e., pretty printed) version of the number if either
138 // the number doesn't contain formatting marks.
139 UpdateCacheIfNeeded(app_locale);
140 if (base::ContainsOnlyChars(number_, base::ASCIIToUTF16("+0123456789"))) {
141 number_ = cached_parsed_phone_.GetFormattedNumber();
142 } else if (i18n::NormalizePhoneNumber(
143 number_, GetRegion(*profile_, app_locale)).empty()) {
144 // The number doesn't make sense for this region; clear it.
145 number_.clear();
147 return !number_.empty();
150 void PhoneNumber::GetMatchingTypes(const base::string16& text,
151 const std::string& app_locale,
152 ServerFieldTypeSet* matching_types) const {
153 base::string16 stripped_text = text;
154 base::RemoveChars(stripped_text, base::ASCIIToUTF16(" .()-"), &stripped_text);
155 FormGroup::GetMatchingTypes(stripped_text, app_locale, matching_types);
157 // For US numbers, also compare to the three-digit prefix and the four-digit
158 // suffix, since web sites often split numbers into these two fields.
159 base::string16 number = GetInfo(AutofillType(PHONE_HOME_NUMBER), app_locale);
160 if (GetRegion(*profile_, app_locale) == "US" &&
161 number.size() == (kPrefixLength + kSuffixLength)) {
162 base::string16 prefix = number.substr(kPrefixOffset, kPrefixLength);
163 base::string16 suffix = number.substr(kSuffixOffset, kSuffixLength);
164 if (text == prefix || text == suffix)
165 matching_types->insert(PHONE_HOME_NUMBER);
168 base::string16 whole_number =
169 GetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER), app_locale);
170 if (!whole_number.empty()) {
171 base::string16 normalized_number =
172 i18n::NormalizePhoneNumber(text, GetRegion(*profile_, app_locale));
173 if (normalized_number == whole_number)
174 matching_types->insert(PHONE_HOME_WHOLE_NUMBER);
178 void PhoneNumber::UpdateCacheIfNeeded(const std::string& app_locale) const {
179 std::string region = GetRegion(*profile_, app_locale);
180 if (!number_.empty() && cached_parsed_phone_.region() != region)
181 cached_parsed_phone_ = i18n::PhoneObject(number_, region);
184 PhoneNumber::PhoneCombineHelper::PhoneCombineHelper() {
187 PhoneNumber::PhoneCombineHelper::~PhoneCombineHelper() {
190 bool PhoneNumber::PhoneCombineHelper::SetInfo(const AutofillType& type,
191 const base::string16& value) {
192 ServerFieldType storable_type = type.GetStorableType();
193 if (storable_type == PHONE_HOME_COUNTRY_CODE) {
194 country_ = value;
195 return true;
198 if (storable_type == PHONE_HOME_CITY_CODE) {
199 city_ = value;
200 return true;
203 if (storable_type == PHONE_HOME_CITY_AND_NUMBER) {
204 phone_ = value;
205 return true;
208 if (storable_type == PHONE_HOME_WHOLE_NUMBER) {
209 whole_number_ = value;
210 return true;
213 if (storable_type == PHONE_HOME_NUMBER) {
214 phone_.append(value);
215 return true;
218 return false;
221 bool PhoneNumber::PhoneCombineHelper::ParseNumber(
222 const AutofillProfile& profile,
223 const std::string& app_locale,
224 base::string16* value) {
225 if (IsEmpty())
226 return false;
228 if (!whole_number_.empty()) {
229 *value = whole_number_;
230 return true;
233 return i18n::ConstructPhoneNumber(
234 country_, city_, phone_, GetRegion(profile, app_locale), value);
237 bool PhoneNumber::PhoneCombineHelper::IsEmpty() const {
238 return phone_.empty() && whole_number_.empty();
241 } // namespace autofill