form_field.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1// Copyright 2013 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 "components/autofill/core/browser/form_field.h"
6
7#include <stddef.h>
8#include <string>
9#include <utility>
10
11#include "base/logging.h"
12#include "base/memory/scoped_ptr.h"
13#include "base/strings/string_util.h"
14#include "base/strings/stringprintf.h"
15#include "base/strings/utf_string_conversions.h"
16#include "components/autofill/core/browser/address_field.h"
17#include "components/autofill/core/browser/autofill_field.h"
18#include "components/autofill/core/browser/autofill_regexes.h"
19#include "components/autofill/core/browser/autofill_scanner.h"
20#include "components/autofill/core/browser/credit_card_field.h"
21#include "components/autofill/core/browser/email_field.h"
22#include "components/autofill/core/browser/form_structure.h"
23#include "components/autofill/core/browser/name_field.h"
24#include "components/autofill/core/browser/phone_field.h"
25#include "ui/base/l10n/l10n_util.h"
26
27namespace autofill {
28namespace {
29
30bool IsCheckable(const AutofillField* field) {
31  return field->is_checkable;
32}
33
34}  // namespace
35
36// static
37void FormField::ParseFormFields(const std::vector<AutofillField*>& fields,
38                                ServerFieldTypeMap* map) {
39  // Set up a working copy of the fields to be processed.
40  std::vector<const AutofillField*> remaining_fields(fields.size());
41  std::copy(fields.begin(), fields.end(), remaining_fields.begin());
42
43  // Ignore checkable fields as they interfere with parsers assuming context.
44  // Eg., while parsing address, "Is PO box" checkbox after ADDRESS_LINE1
45  // interferes with correctly understanding ADDRESS_LINE2.
46  remaining_fields.erase(
47      std::remove_if(remaining_fields.begin(), remaining_fields.end(),
48                     IsCheckable),
49      remaining_fields.end());
50
51  // Email pass.
52  ParseFormFieldsPass(EmailField::Parse, &remaining_fields, map);
53
54  // Phone pass.
55  ParseFormFieldsPass(PhoneField::Parse, &remaining_fields, map);
56
57  // Address pass.
58  ParseFormFieldsPass(AddressField::Parse, &remaining_fields, map);
59
60  // Credit card pass.
61  ParseFormFieldsPass(CreditCardField::Parse, &remaining_fields, map);
62
63  // Name pass.
64  ParseFormFieldsPass(NameField::Parse, &remaining_fields, map);
65}
66
67// static
68bool FormField::ParseField(AutofillScanner* scanner,
69                           const base::string16& pattern,
70                           const AutofillField** match) {
71  return ParseFieldSpecifics(scanner, pattern, MATCH_DEFAULT, match);
72}
73
74// static
75bool FormField::ParseFieldSpecifics(AutofillScanner* scanner,
76                                    const base::string16& pattern,
77                                    int match_type,
78                                    const AutofillField** match) {
79  if (scanner->IsEnd())
80    return false;
81
82  const AutofillField* field = scanner->Cursor();
83
84  if (!MatchesFormControlType(field->form_control_type, match_type))
85    return false;
86
87  return MatchAndAdvance(scanner, pattern, match_type, match);
88}
89
90// static
91bool FormField::ParseEmptyLabel(AutofillScanner* scanner,
92                                const AutofillField** match) {
93  return ParseFieldSpecifics(scanner,
94                             base::ASCIIToUTF16("^$"),
95                             MATCH_LABEL | MATCH_ALL_INPUTS,
96                             match);
97}
98
99// static
100bool FormField::AddClassification(const AutofillField* field,
101                                  ServerFieldType type,
102                                  ServerFieldTypeMap* map) {
103  // Several fields are optional.
104  if (!field)
105    return true;
106
107  return map->insert(make_pair(field->unique_name(), type)).second;
108}
109
110// static.
111bool FormField::MatchAndAdvance(AutofillScanner* scanner,
112                                const base::string16& pattern,
113                                int match_type,
114                                const AutofillField** match) {
115  const AutofillField* field = scanner->Cursor();
116  if (FormField::Match(field, pattern, match_type)) {
117    if (match)
118      *match = field;
119    scanner->Advance();
120    return true;
121  }
122
123  return false;
124}
125
126// static
127bool FormField::Match(const AutofillField* field,
128                      const base::string16& pattern,
129                      int match_type) {
130  if ((match_type & FormField::MATCH_LABEL) &&
131      autofill::MatchesPattern(field->label, pattern)) {
132    return true;
133  }
134
135  if ((match_type & FormField::MATCH_NAME) &&
136      autofill::MatchesPattern(field->name, pattern)) {
137    return true;
138  }
139
140  if ((match_type & FormField::MATCH_VALUE) &&
141      autofill::MatchesPattern(field->value, pattern)) {
142    return true;
143  }
144
145  return false;
146}
147
148// static
149void FormField::ParseFormFieldsPass(ParseFunction parse,
150                                    std::vector<const AutofillField*>* fields,
151                                    ServerFieldTypeMap* map) {
152  // Store unmatched fields for further processing by the caller.
153  std::vector<const AutofillField*> remaining_fields;
154
155  AutofillScanner scanner(*fields);
156  while (!scanner.IsEnd()) {
157    scoped_ptr<FormField> form_field(parse(&scanner));
158    if (!form_field.get()) {
159      remaining_fields.push_back(scanner.Cursor());
160      scanner.Advance();
161      continue;
162    }
163
164    // Add entries into the map for each field type found in |form_field|.
165    bool ok = form_field->ClassifyField(map);
166    DCHECK(ok);
167  }
168
169  std::swap(*fields, remaining_fields);
170}
171
172bool FormField::MatchesFormControlType(const std::string& type,
173                                       int match_type) {
174  if ((match_type & MATCH_TEXT) && type == "text")
175    return true;
176
177  if ((match_type & MATCH_EMAIL) && type == "email")
178    return true;
179
180  if ((match_type & MATCH_TELEPHONE) && type == "tel")
181    return true;
182
183  if ((match_type & MATCH_SELECT) && type == "select-one")
184    return true;
185
186  if ((match_type & MATCH_TEXT_AREA) && type == "textarea")
187    return true;
188
189  return false;
190}
191
192}  // namespace autofill
193