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

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

Issue 7043027: Autofill refactor form_field.h/cc. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 7 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
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/autofill/form_field.h" 5 #include "chrome/browser/autofill/form_field.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <string> 8 #include <string>
9 #include <utility> 9 #include <utility>
10 10
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h" 12 #include "base/memory/scoped_ptr.h"
13 #include "base/string_util.h" 13 #include "base/string_util.h"
14 #include "base/stringprintf.h" 14 #include "base/stringprintf.h"
15 #include "base/utf_string_conversions.h" 15 #include "base/utf_string_conversions.h"
16 #include "chrome/browser/autofill/autofill_ecml.h"
16 #include "chrome/browser/autofill/address_field.h" 17 #include "chrome/browser/autofill/address_field.h"
17 #include "chrome/browser/autofill/autofill_field.h" 18 #include "chrome/browser/autofill/autofill_field.h"
18 #include "chrome/browser/autofill/autofill_scanner.h" 19 #include "chrome/browser/autofill/autofill_scanner.h"
19 #include "chrome/browser/autofill/credit_card_field.h" 20 #include "chrome/browser/autofill/credit_card_field.h"
20 #include "chrome/browser/autofill/email_field.h" 21 #include "chrome/browser/autofill/email_field.h"
21 #include "chrome/browser/autofill/field_types.h" 22 #include "chrome/browser/autofill/field_types.h"
22 #include "chrome/browser/autofill/form_structure.h" 23 #include "chrome/browser/autofill/form_structure.h"
23 #include "chrome/browser/autofill/name_field.h" 24 #include "chrome/browser/autofill/name_field.h"
24 #include "chrome/browser/autofill/phone_field.h" 25 #include "chrome/browser/autofill/phone_field.h"
25 #include "grit/autofill_resources.h" 26 #include "grit/autofill_resources.h"
26 #include "third_party/WebKit/Source/WebKit/chromium/public/WebRegularExpression. h" 27 #include "third_party/WebKit/Source/WebKit/chromium/public/WebRegularExpression. h"
27 #include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" 28 #include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
28 #include "third_party/WebKit/Source/WebKit/chromium/public/WebTextCaseSensitivit y.h" 29 #include "third_party/WebKit/Source/WebKit/chromium/public/WebTextCaseSensitivit y.h"
29 #include "ui/base/l10n/l10n_util.h" 30 #include "ui/base/l10n/l10n_util.h"
30 31
31 // Field names from the ECML specification; see RFC 3106. We've
32 // made these names lowercase since we convert labels and field names to
33 // lowercase before searching.
34
35 // shipping name/address fields
36 const char kEcmlShipToTitle[] = "ecom_shipto_postal_name_prefix";
37 const char kEcmlShipToFirstName[] = "ecom_shipto_postal_name_first";
38 const char kEcmlShipToMiddleName[] = "ecom_shipto_postal_name_middle";
39 const char kEcmlShipToLastName[] = "ecom_shipto_postal_name_last";
40 const char kEcmlShipToNameSuffix[] = "ecom_shipto_postal_name_suffix";
41 const char kEcmlShipToCompanyName[] = "ecom_shipto_postal_company";
42 const char kEcmlShipToAddress1[] = "ecom_shipto_postal_street_line1";
43 const char kEcmlShipToAddress2[] = "ecom_shipto_postal_street_line2";
44 const char kEcmlShipToAddress3[] = "ecom_shipto_postal_street_line3";
45 const char kEcmlShipToCity[] = "ecom_shipto_postal_city";
46 const char kEcmlShipToStateProv[] = "ecom_shipto_postal_stateprov";
47 const char kEcmlShipToPostalCode[] = "ecom_shipto_postal_postalcode";
48 const char kEcmlShipToCountry[] = "ecom_shipto_postal_countrycode";
49 const char kEcmlShipToPhone[] = "ecom_shipto_telecom_phone_number";
50 const char kEcmlShipToEmail[] = "ecom_shipto_online_email";
51
52 // billing name/address fields
53 const char kEcmlBillToTitle[] = "ecom_billto_postal_name_prefix";
54 const char kEcmlBillToFirstName[] = "ecom_billto_postal_name_first";
55 const char kEcmlBillToMiddleName[] = "ecom_billto_postal_name_middle";
56 const char kEcmlBillToLastName[] = "ecom_billto_postal_name_last";
57 const char kEcmlBillToNameSuffix[] = "ecom_billto_postal_name_suffix";
58 const char kEcmlBillToCompanyName[] = "ecom_billto_postal_company";
59 const char kEcmlBillToAddress1[] = "ecom_billto_postal_street_line1";
60 const char kEcmlBillToAddress2[] = "ecom_billto_postal_street_line2";
61 const char kEcmlBillToAddress3[] = "ecom_billto_postal_street_line3";
62 const char kEcmlBillToCity[] = "ecom_billto_postal_city";
63 const char kEcmlBillToStateProv[] = "ecom_billto_postal_stateprov";
64 const char kEcmlBillToPostalCode[] = "ecom_billto_postal_postalcode";
65 const char kEcmlBillToCountry[] = "ecom_billto_postal_countrycode";
66 const char kEcmlBillToPhone[] = "ecom_billto_telecom_phone_number";
67 const char kEcmlBillToEmail[] = "ecom_billto_online_email";
68
69 // credit card fields
70 const char kEcmlCardHolder[] = "ecom_payment_card_name";
71 const char kEcmlCardType[] = "ecom_payment_card_type";
72 const char kEcmlCardNumber[] = "ecom_payment_card_number";
73 const char kEcmlCardVerification[] = "ecom_payment_card_verification";
74 const char kEcmlCardExpireDay[] = "ecom_payment_card_expdate_day";
75 const char kEcmlCardExpireMonth[] = "ecom_payment_card_expdate_month";
76 const char kEcmlCardExpireYear[] = "ecom_payment_card_expdate_year";
77
78 namespace { 32 namespace {
79 33
80 // Checks if any of the |form|'s labels are named according to the ECML 34 using autofill::GetEcmlPattern;
81 // standard. Returns true if at least one ECML named element is found. 35 using autofill::HasECMLField;
82 bool HasECMLField(const std::vector<AutofillField*>& fields) {
83 struct EcmlField {
84 const char* name_;
85 const int length_;
86 } ecml_fields[] = {
87 #define ECML_STRING_ENTRY(x) { x, arraysize(x) - 1 },
88 ECML_STRING_ENTRY(kEcmlShipToTitle)
89 ECML_STRING_ENTRY(kEcmlShipToFirstName)
90 ECML_STRING_ENTRY(kEcmlShipToMiddleName)
91 ECML_STRING_ENTRY(kEcmlShipToLastName)
92 ECML_STRING_ENTRY(kEcmlShipToNameSuffix)
93 ECML_STRING_ENTRY(kEcmlShipToCompanyName)
94 ECML_STRING_ENTRY(kEcmlShipToAddress1)
95 ECML_STRING_ENTRY(kEcmlShipToAddress2)
96 ECML_STRING_ENTRY(kEcmlShipToAddress3)
97 ECML_STRING_ENTRY(kEcmlShipToCity)
98 ECML_STRING_ENTRY(kEcmlShipToStateProv)
99 ECML_STRING_ENTRY(kEcmlShipToPostalCode)
100 ECML_STRING_ENTRY(kEcmlShipToCountry)
101 ECML_STRING_ENTRY(kEcmlShipToPhone)
102 ECML_STRING_ENTRY(kEcmlShipToPhone)
103 ECML_STRING_ENTRY(kEcmlShipToEmail)
104 ECML_STRING_ENTRY(kEcmlBillToTitle)
105 ECML_STRING_ENTRY(kEcmlBillToFirstName)
106 ECML_STRING_ENTRY(kEcmlBillToMiddleName)
107 ECML_STRING_ENTRY(kEcmlBillToLastName)
108 ECML_STRING_ENTRY(kEcmlBillToNameSuffix)
109 ECML_STRING_ENTRY(kEcmlBillToCompanyName)
110 ECML_STRING_ENTRY(kEcmlBillToAddress1)
111 ECML_STRING_ENTRY(kEcmlBillToAddress2)
112 ECML_STRING_ENTRY(kEcmlBillToAddress3)
113 ECML_STRING_ENTRY(kEcmlBillToCity)
114 ECML_STRING_ENTRY(kEcmlBillToStateProv)
115 ECML_STRING_ENTRY(kEcmlBillToPostalCode)
116 ECML_STRING_ENTRY(kEcmlBillToCountry)
117 ECML_STRING_ENTRY(kEcmlBillToPhone)
118 ECML_STRING_ENTRY(kEcmlBillToPhone)
119 ECML_STRING_ENTRY(kEcmlBillToEmail)
120 ECML_STRING_ENTRY(kEcmlCardHolder)
121 ECML_STRING_ENTRY(kEcmlCardType)
122 ECML_STRING_ENTRY(kEcmlCardNumber)
123 ECML_STRING_ENTRY(kEcmlCardVerification)
124 ECML_STRING_ENTRY(kEcmlCardExpireMonth)
125 ECML_STRING_ENTRY(kEcmlCardExpireYear)
126 #undef ECML_STRING_ENTRY
127 };
128 36
129 const string16 ecom(ASCIIToUTF16("ecom")); 37 bool MatchName(const AutofillField* field, const string16& pattern) {
130 for (std::vector<AutofillField*>::const_iterator field = fields.begin();
131 field != fields.end();
132 ++field) {
133 const string16& utf16_name = (*field)->name;
134 if (StartsWith(utf16_name, ecom, true)) {
135 std::string name(UTF16ToUTF8(utf16_name));
136 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(ecml_fields); ++i) {
137 if (base::strncasecmp(name.c_str(), ecml_fields[i].name_,
138 ecml_fields[i].length_) == 0) {
139 return true;
140 }
141 }
142 }
143 }
144
145 return false;
146 }
147
148 } // namespace
149
150 // static
151 void FormField::ParseFormFields(const std::vector<AutofillField*>& fields,
152 FieldTypeMap* field_type_map) {
153 // First, check if there is at least one form field with an ECML name.
154 // If there is, then we will match an element only if it is in the standard.
155 bool is_ecml = HasECMLField(fields);
156
157 // Parse fields.
158 AutofillScanner scanner(fields);
159 while (!scanner.IsEnd()) {
160 scoped_ptr<FormField> form_field(
161 FormField::ParseFormField(&scanner, is_ecml));
162 if (!form_field.get()) {
163 scanner.Advance();
164 continue;
165 }
166
167 bool ok = form_field->GetFieldInfo(field_type_map);
168 DCHECK(ok);
169 }
170 }
171
172 // static
173 bool FormField::Match(const AutofillField* field,
174 const string16& pattern,
175 bool match_label_only) {
176 if (MatchLabel(field, pattern))
177 return true;
178
179 // For now, we apply the same pattern to the field's label and the field's
180 // name. Matching the name is a bit of a long shot for many patterns, but
181 // it generally doesn't hurt to try.
182 if (!match_label_only && MatchName(field, pattern))
183 return true;
184
185 return false;
186 }
187
188 // static
189 bool FormField::MatchName(const AutofillField* field, const string16& pattern) {
190 // TODO(jhawkins): Remove StringToLowerASCII. WebRegularExpression needs to 38 // TODO(jhawkins): Remove StringToLowerASCII. WebRegularExpression needs to
191 // be fixed to take WebTextCaseInsensitive into account. 39 // be fixed to take WebTextCaseInsensitive into account.
192 WebKit::WebRegularExpression re(WebKit::WebString(pattern), 40 WebKit::WebRegularExpression re(WebKit::WebString(pattern),
193 WebKit::WebTextCaseInsensitive); 41 WebKit::WebTextCaseInsensitive);
194 bool match = re.match( 42 bool match = re.match(
195 WebKit::WebString(StringToLowerASCII(field->name))) != -1; 43 WebKit::WebString(StringToLowerASCII(field->name))) != -1;
196 return match; 44 return match;
197 } 45 }
198 46
199 // static 47 bool MatchLabel(const AutofillField* field, const string16& pattern) {
200 bool FormField::MatchLabel(const AutofillField* field,
201 const string16& pattern) {
202 // TODO(jhawkins): Remove StringToLowerASCII. WebRegularExpression needs to 48 // TODO(jhawkins): Remove StringToLowerASCII. WebRegularExpression needs to
203 // be fixed to take WebTextCaseInsensitive into account. 49 // be fixed to take WebTextCaseInsensitive into account.
204 WebKit::WebRegularExpression re(WebKit::WebString(pattern), 50 WebKit::WebRegularExpression re(WebKit::WebString(pattern),
205 WebKit::WebTextCaseInsensitive); 51 WebKit::WebTextCaseInsensitive);
206 bool match = re.match( 52 bool match = re.match(
207 WebKit::WebString(StringToLowerASCII(field->label))) != -1; 53 WebKit::WebString(StringToLowerASCII(field->label))) != -1;
208 return match; 54 return match;
209 } 55 }
210 56
211 // static 57 // Parses a field using the different field views we know about. |is_ecml|
212 FormField* FormField::ParseFormField(AutofillScanner* scanner, bool is_ecml) { 58 // should be true when the field conforms to the ECML specification.
213 FormField *field; 59 FormField* ParseFormField(AutofillScanner* scanner, bool is_ecml) {
60 FormField* field;
214 61
215 field = EmailField::Parse(scanner, is_ecml); 62 field = EmailField::Parse(scanner, is_ecml);
216 if (field) 63 if (field)
217 return field; 64 return field;
218 65
219 // Parses both phone and fax. 66 // Parses both phone and fax.
220 field = PhoneField::Parse(scanner, is_ecml); 67 field = PhoneField::Parse(scanner, is_ecml);
221 if (field) 68 if (field)
222 return field; 69 return field;
223 70
224 field = AddressField::Parse(scanner, is_ecml); 71 field = AddressField::Parse(scanner, is_ecml);
225 if (field) 72 if (field)
226 return field; 73 return field;
227 74
228 field = CreditCardField::Parse(scanner, is_ecml); 75 field = CreditCardField::Parse(scanner, is_ecml);
229 if (field) 76 if (field)
230 return field; 77 return field;
231 78
232 // We search for a |NameField| last since it matches the word "name", which is 79 // We search for a |NameField| last since it matches the word "name", which is
233 // relatively general. 80 // relatively general.
234 return NameField::Parse(scanner, is_ecml); 81 return NameField::Parse(scanner, is_ecml);
235 } 82 }
236 83
84 } // namespace
85
237 // static 86 // static
238 bool FormField::ParseText(AutofillScanner* scanner, const string16& pattern) { 87 void FormField::ParseFormFields(const std::vector<AutofillField*>& fields,
239 const AutofillField* field; 88 FieldTypeMap* map) {
240 return ParseText(scanner, pattern, &field); 89 // First, check if there is at least one form field with an ECML name.
90 // If there is, then we will match an element only if it is in the standard.
91 bool is_ecml = HasECMLField(fields);
92
93 // Parse fields.
94 AutofillScanner scanner(fields);
95 while (!scanner.IsEnd()) {
96 scoped_ptr<FormField> form_field(ParseFormField(&scanner, is_ecml));
97 if (!form_field.get()) {
98 scanner.Advance();
99 continue;
100 }
101
102 bool ok = form_field->ClassifyField(map);
Ilya Sherman 2011/05/19 05:44:16 This line parses really oddly, since form_field ca
dhollowa 2011/05/19 17:53:08 Yes, it requires the reader to understand that a "
103 DCHECK(ok);
104 }
241 } 105 }
242 106
243 // static 107 // static
244 bool FormField::ParseText(AutofillScanner* scanner, 108 bool FormField::ParseField(AutofillScanner* scanner,
245 const string16& pattern, 109 const string16& pattern,
246 const AutofillField** dest) { 110 const AutofillField** match) {
247 return ParseText(scanner, pattern, dest, false); 111 return ParseFieldSpecifics(scanner, pattern, MATCH_ALL, match);
248 } 112 }
249 113
250 // static 114 // static
251 bool FormField::ParseEmptyText(AutofillScanner* scanner, 115 bool FormField::ParseFieldSpecifics(AutofillScanner* scanner,
252 const AutofillField** dest) { 116 const string16& pattern,
253 return ParseLabelText(scanner, ASCIIToUTF16("^$"), dest); 117 int match_type,
254 } 118 const AutofillField** match) {
255
256 // static
257 bool FormField::ParseLabelText(AutofillScanner* scanner,
258 const string16& pattern,
259 const AutofillField** dest) {
260 return ParseText(scanner, pattern, dest, true);
261 }
262
263 // static
264 bool FormField::ParseText(AutofillScanner* scanner,
265 const string16& pattern,
266 const AutofillField** dest,
267 bool match_label_only) {
268 if (scanner->IsEnd()) 119 if (scanner->IsEnd())
269 return false; 120 return false;
270 121
271 const AutofillField* field = scanner->Cursor(); 122 const AutofillField* field = scanner->Cursor();
272 if (Match(field, pattern, match_label_only)) { 123 if (Match(field, pattern, match_type)) {
273 if (dest) 124 if (match)
274 *dest = field; 125 *match = field;
275 scanner->Advance(); 126 scanner->Advance();
276 return true; 127 return true;
277 } 128 }
278 129
279 return false; 130 return false;
280 } 131 }
281 132
282 // static 133 // static
283 bool FormField::ParseLabelAndName(AutofillScanner* scanner, 134 bool FormField::ParseEmptyLabel(AutofillScanner* scanner,
284 const string16& pattern, 135 const AutofillField** match) {
285 const AutofillField** dest) { 136 return ParseFieldSpecifics(scanner, ASCIIToUTF16("^$"), MATCH_LABEL, match);
286 const AutofillField* field = scanner->Cursor();
287 if (MatchLabel(field, pattern) && MatchName(field, pattern)) {
288 if (dest)
289 *dest = field;
290 scanner->Advance();
291 return true;
292 }
293
294 return false;
295 } 137 }
296 138
297 // static 139 // static
298 bool FormField::ParseEmpty(AutofillScanner* scanner) { 140 bool FormField::AddClassification(const AutofillField* field,
299 // TODO(jhawkins): Handle select fields. 141 AutofillFieldType type,
300 return ParseLabelAndName(scanner, ASCIIToUTF16("^$"), NULL); 142 FieldTypeMap* map) {
301 }
302
303 // static
304 bool FormField::Add(FieldTypeMap* field_type_map,
305 const AutofillField* field,
306 AutofillFieldType type) {
307 // Several fields are optional. 143 // Several fields are optional.
308 if (!field) 144 if (!field)
309 return true; 145 return true;
310 146
311 // TODO(isherman): Is this the intent? 147 return map->insert(make_pair(field->unique_name(), type)).second;
312 return field_type_map->insert(make_pair(field->unique_name(), type)).second;
313 } 148 }
314 149
315 string16 FormField::GetEcmlPattern(const char* ecml_name) { 150 // static
316 return ASCIIToUTF16(std::string("^") + ecml_name); 151 bool FormField::Match(const AutofillField* field,
152 const string16& pattern,
153 int match_type) {
154 if ((match_type & FormField::MATCH_LABEL) && MatchLabel(field, pattern))
155 return true;
156
157 if ((match_type & FormField::MATCH_NAME) && MatchName(field, pattern))
158 return true;
159
160 return false;
317 } 161 }
318
319 string16 FormField::GetEcmlPattern(const char* ecml_name1,
320 const char* ecml_name2,
321 char pattern_operator) {
322 return ASCIIToUTF16(StringPrintf("^%s%c^%s",
323 ecml_name1, pattern_operator, ecml_name2));
324 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698