Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / components / autofill / core / browser / phone_number.cc
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.
4
5 #include "components/autofill/core/browser/phone_number.h"
6
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"
16
17 namespace autofill {
18 namespace {
19
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);
29
30   return AutofillCountry::CountryCodeForLocale(app_locale);
31 }
32
33 }  // namespace
34
35 PhoneNumber::PhoneNumber(AutofillProfile* profile)
36     : profile_(profile) {
37 }
38
39 PhoneNumber::PhoneNumber(const PhoneNumber& number)
40     : profile_(NULL) {
41   *this = number;
42 }
43
44 PhoneNumber::~PhoneNumber() {}
45
46 PhoneNumber& PhoneNumber::operator=(const PhoneNumber& number) {
47   if (this == &number)
48     return *this;
49
50   number_ = number.number_;
51   profile_ = number.profile_;
52   cached_parsed_phone_ = number.cached_parsed_phone_;
53   return *this;
54 }
55
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);
62 }
63
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_;
68
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();
73 }
74
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;
82   }
83
84   number_ = value;
85
86   // Invalidate the cached number.
87   cached_parsed_phone_ = i18n::PhoneObject();
88 }
89
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);
98
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();
105
106   switch (storable_type) {
107     case PHONE_HOME_WHOLE_NUMBER:
108       return cached_parsed_phone_.GetWholeNumber();
109
110     case PHONE_HOME_NUMBER:
111       return cached_parsed_phone_.number();
112
113     case PHONE_HOME_CITY_CODE:
114       return cached_parsed_phone_.city_code();
115
116     case PHONE_HOME_COUNTRY_CODE:
117       return cached_parsed_phone_.country_code();
118
119     case PHONE_HOME_CITY_AND_NUMBER:
120       return
121           cached_parsed_phone_.city_code() + cached_parsed_phone_.number();
122
123     default:
124       NOTREACHED();
125       return base::string16();
126   }
127 }
128
129 bool PhoneNumber::SetInfo(const AutofillType& type,
130                           const base::string16& value,
131                           const std::string& app_locale) {
132   SetRawInfo(type.GetStorableType(), value);
133
134   if (number_.empty())
135     return true;
136
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();
146   }
147   return !number_.empty();
148 }
149
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);
156
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);
166   }
167
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);
175   }
176 }
177
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);
182 }
183
184 PhoneNumber::PhoneCombineHelper::PhoneCombineHelper() {
185 }
186
187 PhoneNumber::PhoneCombineHelper::~PhoneCombineHelper() {
188 }
189
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;
196   }
197
198   if (storable_type == PHONE_HOME_CITY_CODE) {
199     city_ = value;
200     return true;
201   }
202
203   if (storable_type == PHONE_HOME_CITY_AND_NUMBER) {
204     phone_ = value;
205     return true;
206   }
207
208   if (storable_type == PHONE_HOME_WHOLE_NUMBER) {
209     whole_number_ = value;
210     return true;
211   }
212
213   if (storable_type == PHONE_HOME_NUMBER) {
214     phone_.append(value);
215     return true;
216   }
217
218   return false;
219 }
220
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;
227
228   if (!whole_number_.empty()) {
229     *value = whole_number_;
230     return true;
231   }
232
233   return i18n::ConstructPhoneNumber(
234       country_, city_, phone_, GetRegion(profile, app_locale), value);
235 }
236
237 bool PhoneNumber::PhoneCombineHelper::IsEmpty() const {
238   return phone_.empty() && whole_number_.empty();
239 }
240
241 }  // namespace autofill