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

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

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

Powered by Google App Engine
This is Rietveld 408576698