Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(455)

Side by Side Diff: components/autofill/browser/name_field.cc

Issue 17392006: In components/autofill, move browser/ to core/browser/ (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase to fix conflicts Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 "components/autofill/browser/name_field.h"
6
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "components/autofill/browser/autofill_regex_constants.h"
12 #include "components/autofill/browser/autofill_scanner.h"
13 #include "components/autofill/browser/autofill_type.h"
14 #include "ui/base/l10n/l10n_util.h"
15
16 namespace autofill {
17 namespace {
18
19 // A form field that can parse a full name field.
20 class FullNameField : public NameField {
21 public:
22 static FullNameField* Parse(AutofillScanner* scanner);
23
24 protected:
25 // FormField:
26 virtual bool ClassifyField(FieldTypeMap* map) const OVERRIDE;
27
28 private:
29 explicit FullNameField(const AutofillField* field);
30
31 const AutofillField* field_;
32
33 DISALLOW_COPY_AND_ASSIGN(FullNameField);
34 };
35
36 // A form field that can parse a first and last name field.
37 class FirstLastNameField : public NameField {
38 public:
39 static FirstLastNameField* ParseSpecificName(AutofillScanner* scanner);
40 static FirstLastNameField* ParseComponentNames(AutofillScanner* scanner);
41 static FirstLastNameField* Parse(AutofillScanner* scanner);
42
43 protected:
44 // FormField:
45 virtual bool ClassifyField(FieldTypeMap* map) const OVERRIDE;
46
47 private:
48 FirstLastNameField();
49
50 const AutofillField* first_name_;
51 const AutofillField* middle_name_; // Optional.
52 const AutofillField* last_name_;
53 bool middle_initial_; // True if middle_name_ is a middle initial.
54
55 DISALLOW_COPY_AND_ASSIGN(FirstLastNameField);
56 };
57
58 } // namespace
59
60 FormField* NameField::Parse(AutofillScanner* scanner) {
61 if (scanner->IsEnd())
62 return NULL;
63
64 // Try FirstLastNameField first since it's more specific.
65 NameField* field = FirstLastNameField::Parse(scanner);
66 if (!field)
67 field = FullNameField::Parse(scanner);
68 return field;
69 }
70
71 // This is overriden in concrete subclasses.
72 bool NameField::ClassifyField(FieldTypeMap* map) const {
73 return false;
74 }
75
76 FullNameField* FullNameField::Parse(AutofillScanner* scanner) {
77 // Exclude e.g. "username" or "nickname" fields.
78 scanner->SaveCursor();
79 bool should_ignore = ParseField(scanner,
80 UTF8ToUTF16(autofill::kNameIgnoredRe), NULL);
81 scanner->Rewind();
82 if (should_ignore)
83 return NULL;
84
85 // Searching for any label containing the word "name" is too general;
86 // for example, Travelocity_Edit travel profile.html contains a field
87 // "Travel Profile Name".
88 const AutofillField* field = NULL;
89 if (ParseField(scanner, UTF8ToUTF16(autofill::kNameRe), &field))
90 return new FullNameField(field);
91
92 return NULL;
93 }
94
95 bool FullNameField::ClassifyField(FieldTypeMap* map) const {
96 return AddClassification(field_, NAME_FULL, map);
97 }
98
99 FullNameField::FullNameField(const AutofillField* field)
100 : field_(field) {
101 }
102
103 FirstLastNameField* FirstLastNameField::ParseSpecificName(
104 AutofillScanner* scanner) {
105 // Some pages (e.g. Overstock_comBilling.html, SmithsonianCheckout.html)
106 // have the label "Name" followed by two or three text fields.
107 scoped_ptr<FirstLastNameField> v(new FirstLastNameField);
108 scanner->SaveCursor();
109
110 const AutofillField* next = NULL;
111 if (ParseField(scanner,
112 UTF8ToUTF16(autofill::kNameSpecificRe), &v->first_name_) &&
113 ParseEmptyLabel(scanner, &next)) {
114 if (ParseEmptyLabel(scanner, &v->last_name_)) {
115 // There are three name fields; assume that the middle one is a
116 // middle initial (it is, at least, on SmithsonianCheckout.html).
117 v->middle_name_ = next;
118 v->middle_initial_ = true;
119 } else { // only two name fields
120 v->last_name_ = next;
121 }
122
123 return v.release();
124 }
125
126 scanner->Rewind();
127 return NULL;
128 }
129
130 FirstLastNameField* FirstLastNameField::ParseComponentNames(
131 AutofillScanner* scanner) {
132 scoped_ptr<FirstLastNameField> v(new FirstLastNameField);
133 scanner->SaveCursor();
134
135 // A fair number of pages use the names "fname" and "lname" for naming
136 // first and last name fields (examples from the test suite:
137 // BESTBUY_COM - Sign In2.html; Crate and Barrel Check Out.html;
138 // dell_checkout1.html). At least one UK page (The China Shop2.html)
139 // asks, in stuffy English style, for just initials and a surname,
140 // so we match "initials" here (and just fill in a first name there,
141 // American-style).
142 // The ".*first$" matches fields ending in "first" (example in sample8.html).
143 // The ".*last$" matches fields ending in "last" (example in sample8.html).
144
145 // Allow name fields to appear in any order.
146 while (!scanner->IsEnd()) {
147 // Skip over any unrelated fields, e.g. "username" or "nickname".
148 if (ParseFieldSpecifics(scanner, UTF8ToUTF16(autofill::kNameIgnoredRe),
149 MATCH_DEFAULT | MATCH_SELECT, NULL)) {
150 continue;
151 }
152
153 if (!v->first_name_ &&
154 ParseField(scanner, UTF8ToUTF16(autofill::kFirstNameRe),
155 &v->first_name_)) {
156 continue;
157 }
158
159 // We check for a middle initial before checking for a middle name
160 // because at least one page (PC Connection.html) has a field marked
161 // as both (the label text is "MI" and the element name is
162 // "txtmiddlename"); such a field probably actually represents a
163 // middle initial.
164 if (!v->middle_name_ &&
165 ParseField(scanner, UTF8ToUTF16(autofill::kMiddleInitialRe),
166 &v->middle_name_)) {
167 v->middle_initial_ = true;
168 continue;
169 }
170
171 if (!v->middle_name_ &&
172 ParseField(scanner, UTF8ToUTF16(autofill::kMiddleNameRe),
173 &v->middle_name_)) {
174 continue;
175 }
176
177 if (!v->last_name_ &&
178 ParseField(scanner, UTF8ToUTF16(autofill::kLastNameRe),
179 &v->last_name_)) {
180 continue;
181 }
182
183 break;
184 }
185
186 // Consider the match to be successful if we detected both first and last name
187 // fields.
188 if (v->first_name_ && v->last_name_)
189 return v.release();
190
191 scanner->Rewind();
192 return NULL;
193 }
194
195 FirstLastNameField* FirstLastNameField::Parse(AutofillScanner* scanner) {
196 FirstLastNameField* field = ParseSpecificName(scanner);
197 if (!field)
198 field = ParseComponentNames(scanner);
199 return field;
200 }
201
202 FirstLastNameField::FirstLastNameField()
203 : first_name_(NULL),
204 middle_name_(NULL),
205 last_name_(NULL),
206 middle_initial_(false) {
207 }
208
209 bool FirstLastNameField::ClassifyField(FieldTypeMap* map) const {
210 bool ok = AddClassification(first_name_, NAME_FIRST, map);
211 ok = ok && AddClassification(last_name_, NAME_LAST, map);
212 AutofillFieldType type = middle_initial_ ? NAME_MIDDLE_INITIAL : NAME_MIDDLE;
213 ok = ok && AddClassification(middle_name_, type, map);
214 return ok;
215 }
216
217 } // namespace autofill
OLDNEW
« no previous file with comments | « components/autofill/browser/name_field.h ('k') | components/autofill/browser/name_field_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698