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"
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
);
35 PhoneNumber::PhoneNumber(AutofillProfile
* profile
)
39 PhoneNumber::PhoneNumber(const PhoneNumber
& number
)
44 PhoneNumber::~PhoneNumber() {}
46 PhoneNumber
& PhoneNumber::operator=(const PhoneNumber
& number
) {
50 number_
= number
.number_
;
51 profile_
= number
.profile_
;
52 cached_parsed_phone_
= number
.cached_parsed_phone_
;
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
)
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.
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
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
:
121 cached_parsed_phone_
.city_code() + cached_parsed_phone_
.number();
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
);
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.
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
) {
198 if (storable_type
== PHONE_HOME_CITY_CODE
) {
203 if (storable_type
== PHONE_HOME_CITY_AND_NUMBER
) {
208 if (storable_type
== PHONE_HOME_WHOLE_NUMBER
) {
209 whole_number_
= value
;
213 if (storable_type
== PHONE_HOME_NUMBER
) {
214 phone_
.append(value
);
221 bool PhoneNumber::PhoneCombineHelper::ParseNumber(
222 const AutofillProfile
& profile
,
223 const std::string
& app_locale
,
224 base::string16
* value
) {
228 if (!whole_number_
.empty()) {
229 *value
= whole_number_
;
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