Home | History | Annotate | Download | only in autofill
      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 
     97 PhoneField::~PhoneField() {}
     98 
     99 // static
    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
    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 
    138 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 
    182 PhoneField::PhoneField() {
    183   memset(parsed_phone_fields_, 0, sizeof(parsed_phone_fields_));
    184   SetPhoneType(HOME_PHONE);
    185 }
    186 
    187 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 
    192 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 
    200 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 
    205 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 
    215 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 
    220 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 
    225 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 
    230 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 
    235 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 
    240 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
    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 
    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