1 // Copyright (c) 2011 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 "chrome/browser/autofill/phone_field.h"
6
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/string16.h"
10 #include "base/string_util.h"
11 #include "base/utf_string_conversions.h"
12 #include "chrome/browser/autofill/autofill_field.h"
13 #include "chrome/browser/autofill/fax_number.h"
14 #include "chrome/browser/autofill/home_phone_number.h"
15 #include "grit/autofill_resources.h"
16 #include "ui/base/l10n/l10n_util.h"
17
18 // Phone field grammars - first matched grammar will be parsed. Grammars are
19 // separated by { REGEX_SEPARATOR, FIELD_NONE, 0 }. Suffix and extension are
20 // parsed separately unless they are necessary parts of the match.
21 // The following notation is used to describe the patterns:
22 // <cc> - country code field.
23 // <ac> - area code field.
24 // <phone> - phone or prefix.
25 // <suffix> - suffix.
26 // <ext> - extension.
27 // :N means field is limited to N characters, otherwise it is unlimited.
28 // (pattern <field>)? means pattern is optional and matched separately.
29 PhoneField::Parser PhoneField::phone_field_grammars_[] = {
30 // Country code: <cc> Area Code: <ac> Phone: <phone> (- <suffix>
31 // (Ext: <ext>)?)?
32 { PhoneField::REGEX_COUNTRY, PhoneField::FIELD_COUNTRY_CODE, 0 },
33 { PhoneField::REGEX_AREA, PhoneField::FIELD_AREA_CODE, 0 },
34 { PhoneField::REGEX_PHONE, PhoneField::FIELD_PHONE, 0 },
35 { PhoneField::REGEX_SEPARATOR, FIELD_NONE, 0 },
36 // Phone: <cc> <ac>:3 - <phone>:3 - <suffix>:4 (Ext: <ext>)?
37 { PhoneField::REGEX_PHONE, PhoneField::FIELD_COUNTRY_CODE, 0 },
38 { PhoneField::REGEX_PHONE, PhoneField::FIELD_AREA_CODE, 3 },
39 { PhoneField::REGEX_PREFIX_SEPARATOR, PhoneField::FIELD_PHONE, 3 },
40 { PhoneField::REGEX_SUFFIX_SEPARATOR, PhoneField::FIELD_SUFFIX, 4 },
41 { PhoneField::REGEX_SEPARATOR, FIELD_NONE, 0 },
42 // Phone: <cc>:3 <ac>:3 <phone>:3 <suffix>:4 (Ext: <ext>)?
43 { PhoneField::REGEX_PHONE, PhoneField::FIELD_COUNTRY_CODE, 3 },
44 { PhoneField::REGEX_PHONE, PhoneField::FIELD_AREA_CODE, 3 },
45 { PhoneField::REGEX_PHONE, PhoneField::FIELD_PHONE, 3 },
46 { PhoneField::REGEX_PHONE, PhoneField::FIELD_SUFFIX, 4 },
47 { PhoneField::REGEX_SEPARATOR, FIELD_NONE, 0 },
48 // Area Code: <ac> Phone: <phone> (- <suffix> (Ext: <ext>)?)?
49 { PhoneField::REGEX_AREA, PhoneField::FIELD_AREA_CODE, 0 },
50 { PhoneField::REGEX_PHONE, PhoneField::FIELD_PHONE, 0 },
51 { PhoneField::REGEX_SEPARATOR, FIELD_NONE, 0 },
52 // Phone: <ac> <phone>:3 <suffix>:4 (Ext: <ext>)?
53 { PhoneField::REGEX_PHONE, PhoneField::FIELD_AREA_CODE, 0 },
54 { PhoneField::REGEX_PHONE, PhoneField::FIELD_PHONE, 3 },
55 { PhoneField::REGEX_PHONE, PhoneField::FIELD_SUFFIX, 4 },
56 { PhoneField::REGEX_SEPARATOR, FIELD_NONE, 0 },
57 // Phone: <cc> \( <ac> \) <phone> (- <suffix> (Ext: <ext>)?)?
58 { PhoneField::REGEX_PHONE, PhoneField::FIELD_COUNTRY_CODE, 0 },
59 { PhoneField::REGEX_AREA_NOTEXT, PhoneField::FIELD_AREA_CODE, 0 },
60 { PhoneField::REGEX_PREFIX_SEPARATOR, PhoneField::FIELD_PHONE, 0 },
61 { PhoneField::REGEX_SEPARATOR, FIELD_NONE, 0 },
62 // Phone: \( <ac> \) <phone> (- <suffix> (Ext: <ext>)?)?
63 { PhoneField::REGEX_PHONE, PhoneField::FIELD_COUNTRY_CODE, 0 },
64 { PhoneField::REGEX_AREA_NOTEXT, PhoneField::FIELD_AREA_CODE, 0 },
65 { PhoneField::REGEX_PREFIX_SEPARATOR, PhoneField::FIELD_PHONE, 0 },
66 { PhoneField::REGEX_SEPARATOR, FIELD_NONE, 0 },
67 // Phone: <cc> - <ac> - <phone> - <suffix> (Ext: <ext>)?
68 { PhoneField::REGEX_PHONE, PhoneField::FIELD_COUNTRY_CODE, 0 },
69 { PhoneField::REGEX_PREFIX_SEPARATOR, PhoneField::FIELD_AREA_CODE, 0 },
70 { PhoneField::REGEX_PREFIX_SEPARATOR, PhoneField::FIELD_PHONE, 0 },
71 { PhoneField::REGEX_SUFFIX_SEPARATOR, PhoneField::FIELD_SUFFIX, 0 },
72 { PhoneField::REGEX_SEPARATOR, FIELD_NONE, 0 },
73 // Phone: <ac> Prefix: <phone> Suffix: <suffix> (Ext: <ext>)?
74 { PhoneField::REGEX_PHONE, PhoneField::FIELD_AREA_CODE, 0 },
75 { PhoneField::REGEX_PREFIX, PhoneField::FIELD_PHONE, 0 },
76 { PhoneField::REGEX_SUFFIX, PhoneField::FIELD_SUFFIX, 0 },
77 { PhoneField::REGEX_SEPARATOR, FIELD_NONE, 0 },
78 // Phone: <ac> - <phone>:3 - <suffix>:4 (Ext: <ext>)?
79 { PhoneField::REGEX_PHONE, PhoneField::FIELD_AREA_CODE, 0 },
80 { PhoneField::REGEX_PREFIX_SEPARATOR, PhoneField::FIELD_PHONE, 3 },
81 { PhoneField::REGEX_SUFFIX_SEPARATOR, PhoneField::FIELD_SUFFIX, 4 },
82 { PhoneField::REGEX_SEPARATOR, FIELD_NONE, 0 },
83 // Phone: <cc> - <ac> - <phone> (Ext: <ext>)?
84 { PhoneField::REGEX_PHONE, PhoneField::FIELD_COUNTRY_CODE, 0 },
85 { PhoneField::REGEX_PREFIX_SEPARATOR, PhoneField::FIELD_AREA_CODE, 0 },
86 { PhoneField::REGEX_SUFFIX_SEPARATOR, PhoneField::FIELD_PHONE, 0 },
87 { PhoneField::REGEX_SEPARATOR, FIELD_NONE, 0 },
88 // Phone: <ac> - <phone> (Ext: <ext>)?
89 { PhoneField::REGEX_AREA, PhoneField::FIELD_AREA_CODE, 0 },
90 { PhoneField::REGEX_PHONE, PhoneField::FIELD_PHONE, 0 },
91 { PhoneField::REGEX_SEPARATOR, FIELD_NONE, 0 },
92 // Phone: <phone> (Ext: <ext>)?
93 { PhoneField::REGEX_PHONE, PhoneField::FIELD_PHONE, 0 },
94 { PhoneField::REGEX_SEPARATOR, FIELD_NONE, 0 },
95 };
96
~PhoneField()97 PhoneField::~PhoneField() {}
98
99 // static
Parse(std::vector<AutofillField * >::const_iterator * iter,bool is_ecml)100 PhoneField* PhoneField::Parse(std::vector<AutofillField*>::const_iterator* iter,
101 bool is_ecml) {
102 DCHECK(iter);
103 if (!iter)
104 return NULL;
105
106 if (is_ecml)
107 return ParseECML(iter);
108
109 scoped_ptr<PhoneField> phone_field(new PhoneField);
110
111 // Go through the phones in order HOME, FAX, attempting to match. HOME should
112 // be the last as it is a catch all case ("fax" and "faxarea" parsed as FAX,
113 // but "area" and "someotherarea" parsed as HOME, for example).
114 for (int i = PHONE_TYPE_MAX - 1; i >= PHONE_TYPE_FIRST; --i) {
115 phone_field->SetPhoneType(static_cast<PhoneField::PhoneType>(i));
116 if (ParseInternal(phone_field.get(), iter, i == HOME_PHONE))
117 return phone_field.release();
118 }
119
120 return NULL;
121 }
122
123 // static
ParseECML(std::vector<AutofillField * >::const_iterator * iter)124 PhoneField* PhoneField::ParseECML(
125 std::vector<AutofillField*>::const_iterator* iter) {
126 string16 pattern(GetEcmlPattern(kEcmlShipToPhone, kEcmlBillToPhone, '|'));
127
128 AutofillField* field;
129 if (ParseText(iter, pattern, &field)) {
130 PhoneField* phone_field = new PhoneField();
131 phone_field->parsed_phone_fields_[FIELD_PHONE] = field;
132 return phone_field;
133 }
134
135 return NULL;
136 }
137
GetFieldInfo(FieldTypeMap * field_type_map) const138 bool PhoneField::GetFieldInfo(FieldTypeMap* field_type_map) const {
139 bool ok = false;
140
141 DCHECK(parsed_phone_fields_[FIELD_PHONE]); // Phone was correctly parsed.
142
143 if ((parsed_phone_fields_[FIELD_COUNTRY_CODE] != NULL) ||
144 (parsed_phone_fields_[FIELD_AREA_CODE] != NULL) ||
145 (parsed_phone_fields_[FIELD_SUFFIX] != NULL)) {
146 if (parsed_phone_fields_[FIELD_COUNTRY_CODE] != NULL) {
147 ok = Add(field_type_map,
148 parsed_phone_fields_[FIELD_COUNTRY_CODE],
149 AutofillType(number_->GetCountryCodeType()));
150 DCHECK(ok);
151 }
152 if (parsed_phone_fields_[FIELD_AREA_CODE] != NULL) {
153 ok = Add(field_type_map,
154 parsed_phone_fields_[FIELD_AREA_CODE],
155 AutofillType(number_->GetCityCodeType()));
156 DCHECK(ok);
157 }
158 // We tag the prefix as PHONE_HOME_NUMBER, then when filling the form
159 // we fill only the prefix depending on the size of the input field.
160 ok = Add(field_type_map,
161 parsed_phone_fields_[FIELD_PHONE],
162 AutofillType(number_->GetNumberType()));
163 DCHECK(ok);
164 // We tag the suffix as PHONE_HOME_NUMBER, then when filling the form
165 // we fill only the suffix depending on the size of the input field.
166 if (parsed_phone_fields_[FIELD_SUFFIX] != NULL) {
167 ok = Add(field_type_map,
168 parsed_phone_fields_[FIELD_SUFFIX],
169 AutofillType(number_->GetNumberType()));
170 DCHECK(ok);
171 }
172 } else {
173 ok = Add(field_type_map,
174 parsed_phone_fields_[FIELD_PHONE],
175 AutofillType(number_->GetWholeNumberType()));
176 DCHECK(ok);
177 }
178
179 return ok;
180 }
181
PhoneField()182 PhoneField::PhoneField() {
183 memset(parsed_phone_fields_, 0, sizeof(parsed_phone_fields_));
184 SetPhoneType(HOME_PHONE);
185 }
186
GetCountryRegex() const187 string16 PhoneField::GetCountryRegex() const {
188 // This one is the same for Home and Fax numbers.
189 return l10n_util::GetStringUTF16(IDS_AUTOFILL_COUNTRY_CODE_RE);
190 }
191
GetAreaRegex() const192 string16 PhoneField::GetAreaRegex() const {
193 // This one is the same for Home and Fax numbers.
194 string16 area_code = l10n_util::GetStringUTF16(IDS_AUTOFILL_AREA_CODE_RE);
195 area_code.append(ASCIIToUTF16("|")); // Regexp separator.
196 area_code.append(GetAreaNoTextRegex());
197 return area_code;
198 }
199
GetAreaNoTextRegex() const200 string16 PhoneField::GetAreaNoTextRegex() const {
201 // This one is the same for Home and Fax numbers.
202 return l10n_util::GetStringUTF16(IDS_AUTOFILL_AREA_CODE_NOTEXT_RE);
203 }
204
GetPhoneRegex() const205 string16 PhoneField::GetPhoneRegex() const {
206 if (phone_type_ == HOME_PHONE)
207 return l10n_util::GetStringUTF16(IDS_AUTOFILL_PHONE_RE);
208 else if (phone_type_ == FAX_PHONE)
209 return l10n_util::GetStringUTF16(IDS_AUTOFILL_FAX_RE);
210 else
211 NOTREACHED();
212 return string16();
213 }
214
GetPrefixSeparatorRegex() const215 string16 PhoneField::GetPrefixSeparatorRegex() const {
216 // This one is the same for Home and Fax numbers.
217 return l10n_util::GetStringUTF16(IDS_AUTOFILL_PHONE_PREFIX_SEPARATOR_RE);
218 }
219
GetPrefixRegex() const220 string16 PhoneField::GetPrefixRegex() const {
221 // This one is the same for Home and Fax numbers.
222 return l10n_util::GetStringUTF16(IDS_AUTOFILL_PHONE_PREFIX_RE);
223 }
224
GetSuffixSeparatorRegex() const225 string16 PhoneField::GetSuffixSeparatorRegex() const {
226 // This one is the same for Home and Fax numbers.
227 return l10n_util::GetStringUTF16(IDS_AUTOFILL_PHONE_SUFFIX_SEPARATOR_RE);
228 }
229
GetSuffixRegex() const230 string16 PhoneField::GetSuffixRegex() const {
231 // This one is the same for Home and Fax numbers.
232 return l10n_util::GetStringUTF16(IDS_AUTOFILL_PHONE_SUFFIX_RE);
233 }
234
GetExtensionRegex() const235 string16 PhoneField::GetExtensionRegex() const {
236 // This one is the same for Home and Fax numbers.
237 return l10n_util::GetStringUTF16(IDS_AUTOFILL_PHONE_EXTENSION_RE);
238 }
239
GetRegExp(RegexType regex_id) const240 string16 PhoneField::GetRegExp(RegexType regex_id) const {
241 switch (regex_id) {
242 case REGEX_COUNTRY: return GetCountryRegex();
243 case REGEX_AREA: return GetAreaRegex();
244 case REGEX_AREA_NOTEXT: return GetAreaNoTextRegex();
245 case REGEX_PHONE: return GetPhoneRegex();
246 case REGEX_PREFIX_SEPARATOR: return GetPrefixSeparatorRegex();
247 case REGEX_PREFIX: return GetPrefixRegex();
248 case REGEX_SUFFIX_SEPARATOR: return GetSuffixSeparatorRegex();
249 case REGEX_SUFFIX: return GetSuffixRegex();
250 case REGEX_EXTENSION: return GetExtensionRegex();
251 default:
252 NOTREACHED();
253 break;
254 }
255 return string16();
256 }
257
258 // static
ParseInternal(PhoneField * phone_field,std::vector<AutofillField * >::const_iterator * iter,bool regular_phone)259 bool PhoneField::ParseInternal(
260 PhoneField *phone_field,
261 std::vector<AutofillField*>::const_iterator* iter,
262 bool regular_phone) {
263 DCHECK(iter);
264
265 DCHECK(phone_field);
266 if (!phone_field)
267 return false;
268
269 std::vector<AutofillField*>::const_iterator q = *iter;
270
271 // The form owns the following variables, so they should not be deleted.
272 AutofillField* parsed_fields[FIELD_MAX];
273
274 for (size_t i = 0; i < arraysize(phone_field_grammars_); ++i) {
275 memset(parsed_fields, 0, sizeof(parsed_fields));
276 q = *iter;
277 // Attempt to parse next possible match.
278 for (; i < arraysize(phone_field_grammars_) &&
279 phone_field_grammars_[i].regex != REGEX_SEPARATOR; ++i) {
280 if (!ParseText(&q, phone_field->GetRegExp(phone_field_grammars_[i].regex),
281 &parsed_fields[phone_field_grammars_[i].phone_part]))
282 break;
283 if (phone_field_grammars_[i].max_size &&
284 (!parsed_fields[phone_field_grammars_[i].phone_part]->max_length ||
285 phone_field_grammars_[i].max_size <
286 parsed_fields[phone_field_grammars_[i].phone_part]->max_length)) {
287 break;
288 }
289 }
290 if (i >= arraysize(phone_field_grammars_))
291 return false; // Parsing failed.
292 if (phone_field_grammars_[i].regex == REGEX_SEPARATOR)
293 break; // Parsing succeeded.
294 do {
295 ++i;
296 } while (i < arraysize(phone_field_grammars_) &&
297 phone_field_grammars_[i].regex != REGEX_SEPARATOR);
298 if (i + 1 == arraysize(phone_field_grammars_))
299 return false; // Tried through all the possibilities - did not match.
300 }
301 if (!parsed_fields[FIELD_PHONE])
302 return false;
303
304 for (int i = 0; i < FIELD_MAX; ++i)
305 phone_field->parsed_phone_fields_[i] = parsed_fields[i];
306
307 // Look for optional fields.
308
309 // Look for a third text box.
310 if (!phone_field->parsed_phone_fields_[FIELD_SUFFIX]) {
311 if (!ParseText(&q, phone_field->GetSuffixRegex(),
312 &phone_field->parsed_phone_fields_[FIELD_SUFFIX])) {
313 ParseText(&q, phone_field->GetSuffixSeparatorRegex(),
314 &phone_field->parsed_phone_fields_[FIELD_SUFFIX]);
315 }
316 }
317
318 // Now look for an extension.
319 ParseText(&q, phone_field->GetExtensionRegex(),
320 &phone_field->parsed_phone_fields_[FIELD_EXTENSION]);
321
322 *iter = q;
323 return true;
324 }
325
SetPhoneType(PhoneType phone_type)326 void PhoneField::SetPhoneType(PhoneType phone_type) {
327 // Field types are different as well, so we create a temporary phone number,
328 // to get relevant field types.
329 if (phone_type == HOME_PHONE)
330 number_.reset(new HomePhoneNumber);
331 else
332 number_.reset(new FaxNumber);
333 phone_type_ = phone_type;
334 }
335
336