phone_field.cc revision ddb351dbec246cf1fab5ec20d2d5520909041de1
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.
29PhoneField::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
97PhoneField::~PhoneField() {}
98
99// static
100PhoneField* 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
124PhoneField* 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
138bool 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
182PhoneField::PhoneField() {
183  memset(parsed_phone_fields_, 0, sizeof(parsed_phone_fields_));
184  SetPhoneType(HOME_PHONE);
185}
186
187string16  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
192string16 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
200string16 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
205string16 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
215string16 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
220string16 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
225string16 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
230string16 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
235string16 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
240string16 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
259bool 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
326void 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