- add sources.
[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 const char16 kPhoneNumberSeparators[] = { ' ', '.', '(', ')', '-', 0 };
21
22 void StripPunctuation(base::string16* number) {
23   RemoveChars(*number, kPhoneNumberSeparators, number);
24 }
25
26 // Returns the region code for this phone number, which is an ISO 3166 2-letter
27 // country code.  The returned value is based on the |profile|; if the |profile|
28 // does not have a country code associated with it, falls back to the country
29 // code corresponding to the |app_locale|.
30 std::string GetRegion(const AutofillProfile& profile,
31                       const std::string& app_locale) {
32   base::string16 country_code = profile.GetRawInfo(ADDRESS_HOME_COUNTRY);
33   if (!country_code.empty())
34     return UTF16ToASCII(country_code);
35
36   return AutofillCountry::CountryCodeForLocale(app_locale);
37 }
38
39 }  // namespace
40
41 PhoneNumber::PhoneNumber(AutofillProfile* profile)
42     : profile_(profile) {
43 }
44
45 PhoneNumber::PhoneNumber(const PhoneNumber& number)
46     : profile_(NULL) {
47   *this = number;
48 }
49
50 PhoneNumber::~PhoneNumber() {}
51
52 PhoneNumber& PhoneNumber::operator=(const PhoneNumber& number) {
53   if (this == &number)
54     return *this;
55
56   number_ = number.number_;
57   profile_ = number.profile_;
58   cached_parsed_phone_ = number.cached_parsed_phone_;
59   return *this;
60 }
61
62 void PhoneNumber::GetSupportedTypes(ServerFieldTypeSet* supported_types) const {
63   supported_types->insert(PHONE_HOME_WHOLE_NUMBER);
64   supported_types->insert(PHONE_HOME_NUMBER);
65   supported_types->insert(PHONE_HOME_CITY_CODE);
66   supported_types->insert(PHONE_HOME_CITY_AND_NUMBER);
67   supported_types->insert(PHONE_HOME_COUNTRY_CODE);
68 }
69
70 base::string16 PhoneNumber::GetRawInfo(ServerFieldType type) const {
71   DCHECK_EQ(PHONE_HOME, AutofillType(type).group());
72   if (type == PHONE_HOME_WHOLE_NUMBER)
73     return number_;
74
75   // Only the whole number is available as raw data.  All of the other types are
76   // parsed from this raw info, and parsing requires knowledge of the phone
77   // number's region, which is only available via GetInfo().
78   return base::string16();
79 }
80
81 void PhoneNumber::SetRawInfo(ServerFieldType type,
82                              const base::string16& value) {
83   DCHECK_EQ(PHONE_HOME, AutofillType(type).group());
84   if (type != PHONE_HOME_CITY_AND_NUMBER && type != PHONE_HOME_WHOLE_NUMBER) {
85     // Only full phone numbers should be set directly.  The remaining field
86     // field types are read-only.
87     return;
88   }
89
90   number_ = value;
91
92   // Invalidate the cached number.
93   cached_parsed_phone_ = i18n::PhoneObject();
94 }
95
96 // Normalize phones if |type| is a whole number:
97 //   (650)2345678 -> 6502345678
98 //   1-800-FLOWERS -> 18003569377
99 // If the phone cannot be normalized, returns the stored value verbatim.
100 base::string16 PhoneNumber::GetInfo(const AutofillType& type,
101                                     const std::string& app_locale) const {
102   ServerFieldType storable_type = type.GetStorableType();
103   UpdateCacheIfNeeded(app_locale);
104
105   // Queries for whole numbers will return the non-normalized number if
106   // normalization for the number fails.  All other field types require
107   // normalization.
108   if (storable_type != PHONE_HOME_WHOLE_NUMBER &&
109       !cached_parsed_phone_.IsValidNumber())
110     return base::string16();
111
112   switch (storable_type) {
113     case PHONE_HOME_WHOLE_NUMBER:
114       return cached_parsed_phone_.GetWholeNumber();
115
116     case PHONE_HOME_NUMBER:
117       return cached_parsed_phone_.number();
118
119     case PHONE_HOME_CITY_CODE:
120       return cached_parsed_phone_.city_code();
121
122     case PHONE_HOME_COUNTRY_CODE:
123       return cached_parsed_phone_.country_code();
124
125     case PHONE_HOME_CITY_AND_NUMBER:
126       return
127           cached_parsed_phone_.city_code() + cached_parsed_phone_.number();
128
129     default:
130       NOTREACHED();
131       return base::string16();
132   }
133 }
134
135 bool PhoneNumber::SetInfo(const AutofillType& type,
136                           const base::string16& value,
137                           const std::string& app_locale) {
138   SetRawInfo(type.GetStorableType(), value);
139
140   if (number_.empty())
141     return true;
142
143   // Store a formatted (i.e., pretty printed) version of the number.
144   UpdateCacheIfNeeded(app_locale);
145   number_ = cached_parsed_phone_.GetFormattedNumber();
146   return !number_.empty();
147 }
148
149 void PhoneNumber::GetMatchingTypes(const base::string16& text,
150                                    const std::string& app_locale,
151                                    ServerFieldTypeSet* matching_types) const {
152   base::string16 stripped_text = text;
153   StripPunctuation(&stripped_text);
154   FormGroup::GetMatchingTypes(stripped_text, app_locale, matching_types);
155
156   // For US numbers, also compare to the three-digit prefix and the four-digit
157   // suffix, since web sites often split numbers into these two fields.
158   base::string16 number = GetInfo(AutofillType(PHONE_HOME_NUMBER), app_locale);
159   if (GetRegion(*profile_, app_locale) == "US" &&
160       number.size() == (kPrefixLength + kSuffixLength)) {
161     base::string16 prefix = number.substr(kPrefixOffset, kPrefixLength);
162     base::string16 suffix = number.substr(kSuffixOffset, kSuffixLength);
163     if (text == prefix || text == suffix)
164       matching_types->insert(PHONE_HOME_NUMBER);
165   }
166
167   base::string16 whole_number =
168       GetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER), app_locale);
169   if (!whole_number.empty()) {
170     base::string16 normalized_number =
171         i18n::NormalizePhoneNumber(text, GetRegion(*profile_, app_locale));
172     if (normalized_number == whole_number)
173       matching_types->insert(PHONE_HOME_WHOLE_NUMBER);
174   }
175 }
176
177 void PhoneNumber::UpdateCacheIfNeeded(const std::string& app_locale) const {
178   std::string region = GetRegion(*profile_, app_locale);
179   if (!number_.empty() && cached_parsed_phone_.region() != region)
180     cached_parsed_phone_ = i18n::PhoneObject(number_, region);
181 }
182
183 PhoneNumber::PhoneCombineHelper::PhoneCombineHelper() {
184 }
185
186 PhoneNumber::PhoneCombineHelper::~PhoneCombineHelper() {
187 }
188
189 bool PhoneNumber::PhoneCombineHelper::SetInfo(const AutofillType& type,
190                                               const base::string16& value) {
191   ServerFieldType storable_type = type.GetStorableType();
192   if (storable_type == PHONE_HOME_COUNTRY_CODE) {
193     country_ = value;
194     return true;
195   }
196
197   if (storable_type == PHONE_HOME_CITY_CODE) {
198     city_ = value;
199     return true;
200   }
201
202   if (storable_type == PHONE_HOME_CITY_AND_NUMBER) {
203     phone_ = value;
204     return true;
205   }
206
207   if (storable_type == PHONE_HOME_WHOLE_NUMBER) {
208     whole_number_ = value;
209     return true;
210   }
211
212   if (storable_type == PHONE_HOME_NUMBER) {
213     phone_.append(value);
214     return true;
215   }
216
217   return false;
218 }
219
220 bool PhoneNumber::PhoneCombineHelper::ParseNumber(
221     const AutofillProfile& profile,
222     const std::string& app_locale,
223     base::string16* value) {
224   if (IsEmpty())
225     return false;
226
227   if (!whole_number_.empty()) {
228     *value = whole_number_;
229     return true;
230   }
231
232   return i18n::ConstructPhoneNumber(
233       country_, city_, phone_, GetRegion(profile, app_locale), value);
234 }
235
236 bool PhoneNumber::PhoneCombineHelper::IsEmpty() const {
237   return phone_.empty() && whole_number_.empty();
238 }
239
240 }  // namespace autofill