• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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