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

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

Issue 7043027: Autofill refactor form_field.h/cc. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: OVERRIDE glitch. 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
« 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
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/name_field.h" 5 #include "chrome/browser/autofill/name_field.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h" 8 #include "base/memory/scoped_ptr.h"
9 #include "base/string_util.h" 9 #include "base/string_util.h"
10 #include "base/utf_string_conversions.h" 10 #include "base/utf_string_conversions.h"
11 #include "chrome/browser/autofill/autofill_ecml.h"
11 #include "chrome/browser/autofill/autofill_scanner.h" 12 #include "chrome/browser/autofill/autofill_scanner.h"
12 #include "chrome/browser/autofill/autofill_type.h" 13 #include "chrome/browser/autofill/autofill_type.h"
13 #include "grit/autofill_resources.h" 14 #include "grit/autofill_resources.h"
14 #include "ui/base/l10n/l10n_util.h" 15 #include "ui/base/l10n/l10n_util.h"
15 16
17 using autofill::GetEcmlPattern;
18
19 namespace {
20
21 // A form field that can parse a full name field.
22 class FullNameField : public NameField {
23 public:
24 static FullNameField* Parse(AutofillScanner* scanner);
25
26 protected:
27 // FormField:
28 virtual bool ClassifyField(FieldTypeMap* map) const OVERRIDE;
29
30 private:
31 explicit FullNameField(const AutofillField* field);
32
33 const AutofillField* field_;
34
35 DISALLOW_COPY_AND_ASSIGN(FullNameField);
36 };
37
38 // A form field that can parse a first and last name field.
39 class FirstLastNameField : public NameField {
40 public:
41 static FirstLastNameField* ParseSpecificName(AutofillScanner* scanner);
42 static FirstLastNameField* ParseComponentNames(AutofillScanner* scanner);
43 static FirstLastNameField* ParseEcmlName(AutofillScanner* scanner);
44 static FirstLastNameField* Parse(AutofillScanner* scanner, bool is_ecml);
45
46 protected:
47 // FormField:
48 virtual bool ClassifyField(FieldTypeMap* map) const OVERRIDE;
49
50 private:
51 FirstLastNameField();
52
53 const AutofillField* first_name_;
54 const AutofillField* middle_name_; // Optional.
55 const AutofillField* last_name_;
56 bool middle_initial_; // True if middle_name_ is a middle initial.
57
58 DISALLOW_COPY_AND_ASSIGN(FirstLastNameField);
59 };
60
61 } // namespace
62
16 NameField* NameField::Parse(AutofillScanner* scanner, bool is_ecml) { 63 NameField* NameField::Parse(AutofillScanner* scanner, bool is_ecml) {
17 if (scanner->IsEnd()) 64 if (scanner->IsEnd())
18 return NULL; 65 return NULL;
19 66
20 // Try FirstLastNameField first since it's more specific. 67 // Try FirstLastNameField first since it's more specific.
21 NameField* field = FirstLastNameField::Parse(scanner, is_ecml); 68 NameField* field = FirstLastNameField::Parse(scanner, is_ecml);
22 if (!field && !is_ecml) 69 if (!field && !is_ecml)
23 field = FullNameField::Parse(scanner); 70 field = FullNameField::Parse(scanner);
24 return field; 71 return field;
25 } 72 }
26 73
27 bool FullNameField::GetFieldInfo(FieldTypeMap* field_type_map) const { 74 // This is overriden in concrete subclasses.
28 return Add(field_type_map, field_, NAME_FULL); 75 bool NameField::ClassifyField(FieldTypeMap* map) const {
76 return false;
29 } 77 }
30 78
31 FullNameField* FullNameField::Parse(AutofillScanner* scanner) { 79 FullNameField* FullNameField::Parse(AutofillScanner* scanner) {
32 // Exclude labels containing the string "username", which typically 80 // Exclude labels containing the string "username", which typically
33 // denotes a login ID rather than the user's actual name. 81 // denotes a login ID rather than the user's actual name.
34 const AutofillField* field = scanner->Cursor(); 82 scanner->SaveCursor();
35 if (Match(field, l10n_util::GetStringUTF16(IDS_AUTOFILL_USERNAME_RE), false)) 83 bool is_username = ParseField(
84 scanner, l10n_util::GetStringUTF16(IDS_AUTOFILL_USERNAME_RE), NULL);
85 scanner->Rewind();
86 if (is_username)
36 return NULL; 87 return NULL;
37 88
38 // Searching for any label containing the word "name" is too general; 89 // Searching for any label containing the word "name" is too general;
39 // for example, Travelocity_Edit travel profile.html contains a field 90 // for example, Travelocity_Edit travel profile.html contains a field
40 // "Travel Profile Name". 91 // "Travel Profile Name".
41 if (ParseText(scanner, l10n_util::GetStringUTF16(IDS_AUTOFILL_NAME_RE), 92 const AutofillField* field = NULL;
42 &field)) 93 if (ParseField(scanner, l10n_util::GetStringUTF16(IDS_AUTOFILL_NAME_RE),
94 &field))
43 return new FullNameField(field); 95 return new FullNameField(field);
44 96
45 return NULL; 97 return NULL;
46 } 98 }
47 99
100 bool FullNameField::ClassifyField(FieldTypeMap* map) const {
101 return AddClassification(field_, NAME_FULL, map);
102 }
103
48 FullNameField::FullNameField(const AutofillField* field) 104 FullNameField::FullNameField(const AutofillField* field)
49 : field_(field) { 105 : field_(field) {
50 } 106 }
51 107
52 bool FirstLastNameField::GetFieldInfo(FieldTypeMap* field_type_map) const {
53 bool ok = Add(field_type_map, first_name_, NAME_FIRST);
54 ok = ok && Add(field_type_map, last_name_, NAME_LAST);
55 AutofillFieldType type = middle_initial_ ? NAME_MIDDLE_INITIAL : NAME_MIDDLE;
56 ok = ok && Add(field_type_map, middle_name_, type);
57 return ok;
58 }
59
60 FirstLastNameField* FirstLastNameField::ParseSpecificName( 108 FirstLastNameField* FirstLastNameField::ParseSpecificName(
61 AutofillScanner* scanner) { 109 AutofillScanner* scanner) {
62 // Some pages (e.g. Overstock_comBilling.html, SmithsonianCheckout.html) 110 // Some pages (e.g. Overstock_comBilling.html, SmithsonianCheckout.html)
63 // have the label "Name" followed by two or three text fields. 111 // have the label "Name" followed by two or three text fields.
64 scoped_ptr<FirstLastNameField> v(new FirstLastNameField); 112 scoped_ptr<FirstLastNameField> v(new FirstLastNameField);
65 scanner->SaveCursor(); 113 scanner->SaveCursor();
66 114
67 const AutofillField* next; 115 const AutofillField* next;
68 if (ParseText(scanner, 116 if (ParseField(scanner,
69 l10n_util::GetStringUTF16(IDS_AUTOFILL_NAME_SPECIFIC_RE), 117 l10n_util::GetStringUTF16(IDS_AUTOFILL_NAME_SPECIFIC_RE),
70 &v->first_name_) && 118 &v->first_name_) &&
71 ParseEmptyText(scanner, &next)) { 119 ParseEmptyLabel(scanner, &next)) {
72 if (ParseEmptyText(scanner, &v->last_name_)) { 120 if (ParseEmptyLabel(scanner, &v->last_name_)) {
73 // There are three name fields; assume that the middle one is a 121 // There are three name fields; assume that the middle one is a
74 // middle initial (it is, at least, on SmithsonianCheckout.html). 122 // middle initial (it is, at least, on SmithsonianCheckout.html).
75 v->middle_name_ = next; 123 v->middle_name_ = next;
76 v->middle_initial_ = true; 124 v->middle_initial_ = true;
77 } else { // only two name fields 125 } else { // only two name fields
78 v->last_name_ = next; 126 v->last_name_ = next;
79 } 127 }
80 128
81 return v.release(); 129 return v.release();
82 } 130 }
83 131
84 scanner->Rewind(); 132 scanner->Rewind();
85 return NULL; 133 return NULL;
86 } 134 }
87 135
88 FirstLastNameField* FirstLastNameField::ParseComponentNames( 136 FirstLastNameField* FirstLastNameField::ParseComponentNames(
89 AutofillScanner* scanner) { 137 AutofillScanner* scanner) {
90 scoped_ptr<FirstLastNameField> v(new FirstLastNameField); 138 scoped_ptr<FirstLastNameField> v(new FirstLastNameField);
91 scanner->SaveCursor(); 139 scanner->SaveCursor();
92 140
93 // A fair number of pages use the names "fname" and "lname" for naming 141 // A fair number of pages use the names "fname" and "lname" for naming
94 // first and last name fields (examples from the test suite: 142 // first and last name fields (examples from the test suite:
95 // BESTBUY_COM - Sign In2.html; Crate and Barrel Check Out.html; 143 // BESTBUY_COM - Sign In2.html; Crate and Barrel Check Out.html;
96 // dell_checkout1.html). At least one UK page (The China Shop2.html) 144 // dell_checkout1.html). At least one UK page (The China Shop2.html)
97 // asks, in stuffy English style, for just initials and a surname, 145 // asks, in stuffy English style, for just initials and a surname,
98 // so we match "initials" here (and just fill in a first name there, 146 // so we match "initials" here (and just fill in a first name there,
99 // American-style). 147 // American-style).
100 // The ".*first$" matches fields ending in "first" (example in sample8.html). 148 // The ".*first$" matches fields ending in "first" (example in sample8.html).
101 if (!ParseText(scanner, l10n_util::GetStringUTF16(IDS_AUTOFILL_FIRST_NAME_RE), 149 if (!ParseField(scanner,
102 &v->first_name_)) 150 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIRST_NAME_RE),
151 &v->first_name_)) {
103 return NULL; 152 return NULL;
153 }
104 154
105 // We check for a middle initial before checking for a middle name 155 // We check for a middle initial before checking for a middle name
106 // because at least one page (PC Connection.html) has a field marked 156 // because at least one page (PC Connection.html) has a field marked
107 // as both (the label text is "MI" and the element name is 157 // as both (the label text is "MI" and the element name is
108 // "txtmiddlename"); such a field probably actually represents a 158 // "txtmiddlename"); such a field probably actually represents a
109 // middle initial. 159 // middle initial.
110 if (ParseText(scanner, 160 if (ParseField(scanner,
111 l10n_util::GetStringUTF16(IDS_AUTOFILL_MIDDLE_INITIAL_RE), 161 l10n_util::GetStringUTF16(IDS_AUTOFILL_MIDDLE_INITIAL_RE),
112 &v->middle_name_)) { 162 &v->middle_name_)) {
113 v->middle_initial_ = true; 163 v->middle_initial_ = true;
114 } else { 164 } else {
115 ParseText(scanner, l10n_util::GetStringUTF16(IDS_AUTOFILL_MIDDLE_NAME_RE), 165 ParseField(scanner, l10n_util::GetStringUTF16(IDS_AUTOFILL_MIDDLE_NAME_RE),
116 &v->middle_name_); 166 &v->middle_name_);
117 } 167 }
118 168
119 // The ".*last$" matches fields ending in "last" (example in sample8.html). 169 // The ".*last$" matches fields ending in "last" (example in sample8.html).
120 if (ParseText(scanner, l10n_util::GetStringUTF16(IDS_AUTOFILL_LAST_NAME_RE), 170 if (ParseField(scanner, l10n_util::GetStringUTF16(IDS_AUTOFILL_LAST_NAME_RE),
121 &v->last_name_)) { 171 &v->last_name_)) {
122 return v.release(); 172 return v.release();
123 } 173 }
124 174
125 scanner->Rewind(); 175 scanner->Rewind();
126 return NULL; 176 return NULL;
127 } 177 }
128 178
129 FirstLastNameField* FirstLastNameField::ParseEcmlName( 179 FirstLastNameField* FirstLastNameField::ParseEcmlName(
130 AutofillScanner* scanner) { 180 AutofillScanner* scanner) {
131 scoped_ptr<FirstLastNameField> field(new FirstLastNameField); 181 scoped_ptr<FirstLastNameField> field(new FirstLastNameField);
132 scanner->SaveCursor(); 182 scanner->SaveCursor();
133 183
134 string16 pattern = GetEcmlPattern(kEcmlShipToFirstName, 184 string16 pattern = GetEcmlPattern(kEcmlShipToFirstName,
135 kEcmlBillToFirstName, '|'); 185 kEcmlBillToFirstName, '|');
136 if (!ParseText(scanner, pattern, &field->first_name_)) 186 if (!ParseField(scanner, pattern, &field->first_name_))
137 return NULL; 187 return NULL;
138 188
139 pattern = GetEcmlPattern(kEcmlShipToMiddleName, kEcmlBillToMiddleName, '|'); 189 pattern = GetEcmlPattern(kEcmlShipToMiddleName, kEcmlBillToMiddleName, '|');
140 ParseText(scanner, pattern, &field->middle_name_); 190 ParseField(scanner, pattern, &field->middle_name_);
141 191
142 pattern = GetEcmlPattern(kEcmlShipToLastName, kEcmlBillToLastName, '|'); 192 pattern = GetEcmlPattern(kEcmlShipToLastName, kEcmlBillToLastName, '|');
143 if (ParseText(scanner, pattern, &field->last_name_)) 193 if (ParseField(scanner, pattern, &field->last_name_))
144 return field.release(); 194 return field.release();
145 195
146 scanner->Rewind(); 196 scanner->Rewind();
147 return NULL; 197 return NULL;
148 } 198 }
149 199
150 FirstLastNameField* FirstLastNameField::Parse(AutofillScanner* scanner, 200 FirstLastNameField* FirstLastNameField::Parse(AutofillScanner* scanner,
151 bool is_ecml) { 201 bool is_ecml) {
152 if (is_ecml) 202 if (is_ecml)
153 return ParseEcmlName(scanner); 203 return ParseEcmlName(scanner);
154 204
155 FirstLastNameField* field = ParseSpecificName(scanner); 205 FirstLastNameField* field = ParseSpecificName(scanner);
156 if (!field) 206 if (!field)
157 field = ParseComponentNames(scanner); 207 field = ParseComponentNames(scanner);
158 return field; 208 return field;
159 } 209 }
160 210
161 FirstLastNameField::FirstLastNameField() 211 FirstLastNameField::FirstLastNameField()
162 : first_name_(NULL), 212 : first_name_(NULL),
163 middle_name_(NULL), 213 middle_name_(NULL),
164 last_name_(NULL), 214 last_name_(NULL),
165 middle_initial_(false) { 215 middle_initial_(false) {
166 } 216 }
217
218 bool FirstLastNameField::ClassifyField(FieldTypeMap* map) const {
219 bool ok = AddClassification(first_name_, NAME_FIRST, map);
220 ok = ok && AddClassification(last_name_, NAME_LAST, map);
221 AutofillFieldType type = middle_initial_ ? NAME_MIDDLE_INITIAL : NAME_MIDDLE;
222 ok = ok && AddClassification(middle_name_, type, map);
223 return ok;
224 }
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