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