form_field.cc revision 3f50c38dc070f4bb515c1b64450dae14f316474e
1// Copyright (c) 2009 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/form_field.h"
6
7<<<<<<< HEAD
8#ifdef ANDROID
9#include "app/l10n_util.h"
10#endif
11=======
12#include "app/l10n_util.h"
13>>>>>>> chromium.org at r10.0.634.0
14#include "base/string_util.h"
15#include "base/utf_string_conversions.h"
16#include "chrome/browser/autofill/address_field.h"
17#include "chrome/browser/autofill/autofill_field.h"
18#include "chrome/browser/autofill/credit_card_field.h"
19#include "chrome/browser/autofill/fax_field.h"
20#include "chrome/browser/autofill/name_field.h"
21#include "chrome/browser/autofill/phone_field.h"
22#include "third_party/WebKit/WebKit/chromium/public/WebRegularExpression.h"
23#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
24#include "grit/autofill_resources.h"
25
26// Field names from the ECML specification; see RFC 3106.  We've
27// made these names lowercase since we convert labels and field names to
28// lowercase before searching.
29
30// shipping name/address fields
31const char kEcmlShipToTitle[] = "ecom_shipto_postal_name_prefix";
32const char kEcmlShipToFirstName[] = "ecom_shipto_postal_name_first";
33const char kEcmlShipToMiddleName[] = "ecom_shipto_postal_name_middle";
34const char kEcmlShipToLastName[] = "ecom_shipto_postal_name_last";
35const char kEcmlShipToNameSuffix[] = "ecom_shipto_postal_name_suffix";
36const char kEcmlShipToCompanyName[] = "ecom_shipto_postal_company";
37const char kEcmlShipToAddress1[] = "ecom_shipto_postal_street_line1";
38const char kEcmlShipToAddress2[] = "ecom_shipto_postal_street_line2";
39const char kEcmlShipToAddress3[] = "ecom_shipto_postal_street_line3";
40const char kEcmlShipToCity[] = "ecom_shipto_postal_city";
41const char kEcmlShipToStateProv[] = "ecom_shipto_postal_stateprov";
42const char kEcmlShipToPostalCode[] = "ecom_shipto_postal_postalcode";
43const char kEcmlShipToCountry[] = "ecom_shipto_postal_countrycode";
44const char kEcmlShipToPhone[] = "ecom_shipto_telecom_phone_number";
45const char kEcmlShipToEmail[] = "ecom_shipto_online_email";
46
47// billing name/address fields
48const char kEcmlBillToTitle[] = "ecom_billto_postal_name_prefix";
49const char kEcmlBillToFirstName[] = "ecom_billto_postal_name_first";
50const char kEcmlBillToMiddleName[] = "ecom_billto_postal_name_middle";
51const char kEcmlBillToLastName[] = "ecom_billto_postal_name_last";
52const char kEcmlBillToNameSuffix[] = "ecom_billto_postal_name_suffix";
53const char kEcmlBillToCompanyName[] = "ecom_billto_postal_company";
54const char kEcmlBillToAddress1[] = "ecom_billto_postal_street_line1";
55const char kEcmlBillToAddress2[] = "ecom_billto_postal_street_line2";
56const char kEcmlBillToAddress3[] = "ecom_billto_postal_street_line3";
57const char kEcmlBillToCity[] = "ecom_billto_postal_city";
58const char kEcmlBillToStateProv[] = "ecom_billto_postal_stateprov";
59const char kEcmlBillToPostalCode[] = "ecom_billto_postal_postalcode";
60const char kEcmlBillToCountry[] = "ecom_billto_postal_countrycode";
61const char kEcmlBillToPhone[] = "ecom_billto_telecom_phone_number";
62const char kEcmlBillToEmail[] = "ecom_billto_online_email";
63
64// credit card fields
65const char kEcmlCardHolder[] = "ecom_payment_card_name";
66const char kEcmlCardType[] = "ecom_payment_card_type";
67const char kEcmlCardNumber[] = "ecom_payment_card_number";
68const char kEcmlCardVerification[] = "ecom_payment_card_verification";
69const char kEcmlCardExpireDay[] = "ecom_payment_card_expdate_day";
70const char kEcmlCardExpireMonth[] = "ecom_payment_card_expdate_month";
71const char kEcmlCardExpireYear[] = "ecom_payment_card_expdate_year";
72
73namespace {
74
75// The name of the hidden form control element.
76const char* const kControlTypeHidden = "hidden";
77
78// The name of the radio form control element.
79const char* const kControlTypeRadio = "radio";
80
81// The name of the checkbox form control element.
82const char* const kControlTypeCheckBox = "checkbox";
83
84}  // namespace
85
86class EmailField : public FormField {
87 public:
88  virtual bool GetFieldInfo(FieldTypeMap* field_type_map) const {
89    bool ok = Add(field_type_map, field_, AutoFillType(EMAIL_ADDRESS));
90    DCHECK(ok);
91    return true;
92  }
93
94  static EmailField* Parse(std::vector<AutoFillField*>::const_iterator* iter,
95                          bool is_ecml) {
96    string16 pattern;
97    if (is_ecml) {
98      pattern = GetEcmlPattern(kEcmlShipToEmail, kEcmlBillToEmail, '|');
99    } else {
100      pattern = l10n_util::GetStringUTF16(IDS_AUTOFILL_EMAIL_RE);
101    }
102
103    AutoFillField* field;
104    if (ParseText(iter, pattern, &field))
105      return new EmailField(field);
106
107    return NULL;
108  }
109
110 private:
111  explicit EmailField(AutoFillField *field) : field_(field) {}
112
113  AutoFillField* field_;
114};
115
116FormFieldType FormField::GetFormFieldType() const {
117  return kOtherFieldType;
118}
119
120// static
121bool FormField::Match(AutoFillField* field,
122                      const string16& pattern,
123                      bool match_label_only) {
124  if (match_label_only) {
125    if (MatchLabel(field, pattern)) {
126      return true;
127    }
128  } else {
129    // For now, we apply the same pattern to the field's label and the field's
130    // name.  Matching the name is a bit of a long shot for many patterns, but
131    // it generally doesn't hurt to try.
132    if (MatchLabel(field, pattern) || MatchName(field, pattern)) {
133      return true;
134    }
135  }
136
137  return false;
138}
139
140// static
141bool FormField::MatchName(AutoFillField* field, const string16& pattern) {
142  // TODO(jhawkins): Remove StringToLowerASCII.  WebRegularExpression needs to
143  // be fixed to take WebTextCaseInsensitive into account.
144  WebKit::WebRegularExpression re(WebKit::WebString(pattern),
145                                  WebKit::WebTextCaseInsensitive);
146  bool match = re.match(
147      WebKit::WebString(StringToLowerASCII(field->name()))) != -1;
148  return match;
149}
150
151// static
152bool FormField::MatchLabel(AutoFillField* field, const string16& pattern) {
153  // TODO(jhawkins): Remove StringToLowerASCII.  WebRegularExpression needs to
154  // be fixed to take WebTextCaseInsensitive into account.
155  WebKit::WebRegularExpression re(WebKit::WebString(pattern),
156                                  WebKit::WebTextCaseInsensitive);
157  bool match = re.match(
158      WebKit::WebString(StringToLowerASCII(field->label()))) != -1;
159  return match;
160}
161
162// static
163FormField* FormField::ParseFormField(
164    std::vector<AutoFillField*>::const_iterator* iter,
165    bool is_ecml) {
166  FormField *field;
167  field = EmailField::Parse(iter, is_ecml);
168  if (field != NULL)
169    return field;
170  field = PhoneField::Parse(iter, is_ecml);
171  if (field != NULL)
172    return field;
173  field = FaxField::Parse(iter);
174  if (field != NULL)
175    return field;
176  field = AddressField::Parse(iter, is_ecml);
177  if (field != NULL)
178    return field;
179  field = CreditCardField::Parse(iter, is_ecml);
180  if (field != NULL)
181    return field;
182
183  // We search for a NameField last since it matches the word "name", which is
184  // relatively general.
185  return NameField::Parse(iter, is_ecml);
186}
187
188// static
189bool FormField::ParseText(std::vector<AutoFillField*>::const_iterator* iter,
190                          const string16& pattern) {
191  AutoFillField* field;
192  return ParseText(iter, pattern, &field);
193}
194
195// static
196bool FormField::ParseText(std::vector<AutoFillField*>::const_iterator* iter,
197                          const string16& pattern,
198                          AutoFillField** dest) {
199  return ParseText(iter, pattern, dest, false);
200}
201
202// static
203bool FormField::ParseEmptyText(
204    std::vector<AutoFillField*>::const_iterator* iter,
205    AutoFillField** dest) {
206  return ParseLabelText(iter, ASCIIToUTF16("^$"), dest);
207}
208
209// static
210bool FormField::ParseLabelText(
211    std::vector<AutoFillField*>::const_iterator* iter,
212    const string16& pattern,
213    AutoFillField** dest) {
214  return ParseText(iter, pattern, dest, true);
215}
216
217// static
218bool FormField::ParseText(std::vector<AutoFillField*>::const_iterator* iter,
219                          const string16& pattern,
220                          AutoFillField** dest,
221                          bool match_label_only) {
222  // Some forms have one or more hidden fields before each visible input; skip
223  // past these.
224  while (**iter && LowerCaseEqualsASCII((**iter)->form_control_type(),
225                                        kControlTypeHidden))
226    (*iter)++;
227
228  AutoFillField* field = **iter;
229  if (!field)
230    return false;
231
232  if (Match(field, pattern, match_label_only)) {
233    if (dest)
234      *dest = field;
235    (*iter)++;
236    return true;
237  }
238
239  return false;
240}
241
242// static
243bool FormField::ParseLabelAndName(
244    std::vector<AutoFillField*>::const_iterator* iter,
245    const string16& pattern,
246    AutoFillField** dest) {
247  AutoFillField* field = **iter;
248  if (!field)
249    return false;
250
251  if (MatchLabel(field, pattern) && MatchName(field, pattern)) {
252    if (dest)
253      *dest = field;
254    (*iter)++;
255    return true;
256  }
257
258  return false;
259}
260
261// static
262bool FormField::ParseEmpty(std::vector<AutoFillField*>::const_iterator* iter) {
263  // TODO(jhawkins): Handle select fields.
264  return ParseLabelAndName(iter, ASCIIToUTF16("^$"), NULL);
265}
266
267// static
268bool FormField::Add(FieldTypeMap* field_type_map, AutoFillField* field,
269               const AutoFillType& type) {
270  // Several fields are optional.
271  if (field)
272    field_type_map->insert(make_pair(field->unique_name(), type.field_type()));
273
274  return true;
275}
276
277string16 FormField::GetEcmlPattern(const char* ecml_name) {
278  return ASCIIToUTF16(std::string("^") + ecml_name);
279}
280
281string16 FormField::GetEcmlPattern(const char* ecml_name1,
282                                   const char* ecml_name2,
283                                   char pattern_operator) {
284  return ASCIIToUTF16(StringPrintf("^%s%c^%s",
285      ecml_name1, pattern_operator, ecml_name2));
286}
287
288FormFieldSet::FormFieldSet(FormStructure* fields) {
289  std::vector<AddressField*> addresses;
290
291  // First, find if there is one form field with an ECML name.  If there is,
292  // then we will match an element only if it is in the standard.
293  bool is_ecml = CheckECML(fields);
294
295  // Parse fields.
296  std::vector<AutoFillField*>::const_iterator field = fields->begin();
297  while (field != fields->end() && *field != NULL) {
298    // Don't parse hidden fields or radio or checkbox controls.
299    if (LowerCaseEqualsASCII((*field)->form_control_type(),
300                             kControlTypeHidden) ||
301        LowerCaseEqualsASCII((*field)->form_control_type(),
302                             kControlTypeRadio) ||
303        LowerCaseEqualsASCII((*field)->form_control_type(),
304                             kControlTypeCheckBox)) {
305      field++;
306      continue;
307    }
308
309    FormField* form_field = FormField::ParseFormField(&field, is_ecml);
310    if (!form_field) {
311      field++;
312      continue;
313    }
314
315    push_back(form_field);
316
317    if (form_field->GetFormFieldType() == kAddressType) {
318      AddressField* address = static_cast<AddressField*>(form_field);
319      if (address->IsFullAddress())
320        addresses.push_back(address);
321    }
322  }
323
324  // Now determine an address type for each address. Note, if this is an ECML
325  // form, then we already got this info from the field names.
326  if (!is_ecml && !addresses.empty()) {
327    if (addresses.size() == 1) {
328      addresses[0]->SetType(addresses[0]->FindType());
329    } else {
330      AddressType type0 = addresses[0]->FindType();
331      AddressType type1 = addresses[1]->FindType();
332
333      // When there are two addresses on a page, they almost always appear in
334      // the order (billing, shipping).
335      bool reversed = (type0 == kShippingAddress && type1 == kBillingAddress);
336      addresses[0]->SetType(reversed ? kShippingAddress : kBillingAddress);
337      addresses[1]->SetType(reversed ? kBillingAddress : kShippingAddress);
338    }
339  }
340}
341
342bool FormFieldSet::CheckECML(FormStructure* fields) {
343  size_t num_fields = fields->field_count();
344  struct EcmlField {
345    const char* name_;
346    const int length_;
347  } form_fields[] = {
348#define ECML_STRING_ENTRY(x) { x, arraysize(x) - 1 },
349    ECML_STRING_ENTRY(kEcmlShipToTitle)
350    ECML_STRING_ENTRY(kEcmlShipToFirstName)
351    ECML_STRING_ENTRY(kEcmlShipToMiddleName)
352    ECML_STRING_ENTRY(kEcmlShipToLastName)
353    ECML_STRING_ENTRY(kEcmlShipToNameSuffix)
354    ECML_STRING_ENTRY(kEcmlShipToCompanyName)
355    ECML_STRING_ENTRY(kEcmlShipToAddress1)
356    ECML_STRING_ENTRY(kEcmlShipToAddress2)
357    ECML_STRING_ENTRY(kEcmlShipToAddress3)
358    ECML_STRING_ENTRY(kEcmlShipToCity)
359    ECML_STRING_ENTRY(kEcmlShipToStateProv)
360    ECML_STRING_ENTRY(kEcmlShipToPostalCode)
361    ECML_STRING_ENTRY(kEcmlShipToCountry)
362    ECML_STRING_ENTRY(kEcmlShipToPhone)
363    ECML_STRING_ENTRY(kEcmlShipToPhone)
364    ECML_STRING_ENTRY(kEcmlShipToEmail)
365    ECML_STRING_ENTRY(kEcmlBillToTitle)
366    ECML_STRING_ENTRY(kEcmlBillToFirstName)
367    ECML_STRING_ENTRY(kEcmlBillToMiddleName)
368    ECML_STRING_ENTRY(kEcmlBillToLastName)
369    ECML_STRING_ENTRY(kEcmlBillToNameSuffix)
370    ECML_STRING_ENTRY(kEcmlBillToCompanyName)
371    ECML_STRING_ENTRY(kEcmlBillToAddress1)
372    ECML_STRING_ENTRY(kEcmlBillToAddress2)
373    ECML_STRING_ENTRY(kEcmlBillToAddress3)
374    ECML_STRING_ENTRY(kEcmlBillToCity)
375    ECML_STRING_ENTRY(kEcmlBillToStateProv)
376    ECML_STRING_ENTRY(kEcmlBillToPostalCode)
377    ECML_STRING_ENTRY(kEcmlBillToCountry)
378    ECML_STRING_ENTRY(kEcmlBillToPhone)
379    ECML_STRING_ENTRY(kEcmlBillToPhone)
380    ECML_STRING_ENTRY(kEcmlBillToEmail)
381    ECML_STRING_ENTRY(kEcmlCardHolder)
382    ECML_STRING_ENTRY(kEcmlCardType)
383    ECML_STRING_ENTRY(kEcmlCardNumber)
384    ECML_STRING_ENTRY(kEcmlCardVerification)
385    ECML_STRING_ENTRY(kEcmlCardExpireMonth)
386    ECML_STRING_ENTRY(kEcmlCardExpireYear)
387#undef ECML_STRING_ENTRY
388  };
389
390  const string16 ecom(ASCIIToUTF16("ecom"));
391  for (size_t index = 0; index < num_fields; ++index) {
392    const string16& utf16_name = fields->field(index)->name();
393    if (StartsWith(utf16_name, ecom, true)) {
394      std::string name(UTF16ToASCII(utf16_name));
395      for (size_t i = 0; i < ARRAYSIZE_UNSAFE(form_fields); ++i) {
396        if (base::strncasecmp(name.c_str(), form_fields[i].name_,
397                              form_fields[i].length_) == 0) {
398          return true;
399        }
400      }
401    }
402  }
403
404  return false;
405}
406