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

Side by Side Diff: chrome/renderer/form_manager.cc

Issue 1622004: AutoFill: Parse HTMLLabel elements for form control element labels. (Closed)
Patch Set: Update constness. Created 10 years, 8 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
« no previous file with comments | « chrome/renderer/form_manager.h ('k') | chrome/renderer/form_manager_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) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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/renderer/form_manager.h" 5 #include "chrome/renderer/form_manager.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/scoped_vector.h"
8 #include "base/string_util.h" 9 #include "base/string_util.h"
9 #include "base/stl_util-inl.h" 10 #include "base/stl_util-inl.h"
10 #include "third_party/WebKit/WebKit/chromium/public/WebDocument.h" 11 #include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
11 #include "third_party/WebKit/WebKit/chromium/public/WebElement.h" 12 #include "third_party/WebKit/WebKit/chromium/public/WebElement.h"
12 #include "third_party/WebKit/WebKit/chromium/public/WebFormControlElement.h" 13 #include "third_party/WebKit/WebKit/chromium/public/WebFormControlElement.h"
13 #include "third_party/WebKit/WebKit/chromium/public/WebFrame.h" 14 #include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
14 #include "third_party/WebKit/WebKit/chromium/public/WebInputElement.h" 15 #include "third_party/WebKit/WebKit/chromium/public/WebInputElement.h"
15 #include "third_party/WebKit/WebKit/chromium/public/WebLabelElement.h" 16 #include "third_party/WebKit/WebKit/chromium/public/WebLabelElement.h"
16 #include "third_party/WebKit/WebKit/chromium/public/WebNode.h" 17 #include "third_party/WebKit/WebKit/chromium/public/WebNode.h"
17 #include "third_party/WebKit/WebKit/chromium/public/WebNodeList.h" 18 #include "third_party/WebKit/WebKit/chromium/public/WebNodeList.h"
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 52
52 FormManager::~FormManager() { 53 FormManager::~FormManager() {
53 Reset(); 54 Reset();
54 } 55 }
55 56
56 // static 57 // static
57 void FormManager::WebFormControlElementToFormField( 58 void FormManager::WebFormControlElementToFormField(
58 const WebFormControlElement& element, FormField* field) { 59 const WebFormControlElement& element, FormField* field) {
59 DCHECK(field); 60 DCHECK(field);
60 61
61 // TODO(jhawkins): LabelForElement. Returning an empty label temporarily to 62 // The label is not officially part of a WebFormControlElement; however, the
62 // diagnose a perf issue. 63 // labels for all form control elements are scraped from the DOM and set in
63 field->set_label(string16()); 64 // WebFormElementToFormData.
64 field->set_name(element.nameForAutofill()); 65 field->set_name(element.nameForAutofill());
65 field->set_form_control_type(element.formControlType()); 66 field->set_form_control_type(element.formControlType());
66 67
67 // TODO(jhawkins): In WebKit, move value() and setValue() to 68 // TODO(jhawkins): In WebKit, move value() and setValue() to
68 // WebFormControlElement. 69 // WebFormControlElement.
69 string16 value; 70 string16 value;
70 if (element.formControlType() == WebString::fromUTF8("text")) { 71 if (element.formControlType() == WebString::fromUTF8("text")) {
71 const WebInputElement& input_element = 72 const WebInputElement& input_element =
72 element.toConstElement<WebInputElement>(); 73 element.toConstElement<WebInputElement>();
73 value = input_element.value(); 74 value = input_element.value();
(...skipping 23 matching lines...) Expand all
97 form->name = element.name(); 98 form->name = element.name();
98 form->method = element.method(); 99 form->method = element.method();
99 form->origin = frame->url(); 100 form->origin = frame->url();
100 form->action = frame->completeURL(element.action()); 101 form->action = frame->completeURL(element.action());
101 102
102 // If the completed URL is not valid, just use the action we get from 103 // If the completed URL is not valid, just use the action we get from
103 // WebKit. 104 // WebKit.
104 if (!form->action.is_valid()) 105 if (!form->action.is_valid())
105 form->action = GURL(element.action()); 106 form->action = GURL(element.action());
106 107
108 // A map from a FormField's name to the FormField itself.
109 std::map<string16, FormField*> name_map;
110
111 // The extracted FormFields. We use pointers so we can store them in
112 // |name_map|.
113 ScopedVector<FormField> form_fields;
114
107 WebVector<WebFormControlElement> control_elements; 115 WebVector<WebFormControlElement> control_elements;
108 element.getFormControlElements(control_elements); 116 element.getFormControlElements(control_elements);
109 for (size_t i = 0; i < control_elements.size(); ++i) { 117 for (size_t i = 0; i < control_elements.size(); ++i) {
110 const WebFormControlElement& control_element = control_elements[i]; 118 const WebFormControlElement& control_element = control_elements[i];
111 119
112 if (requirements & REQUIRE_AUTOCOMPLETE && 120 if (requirements & REQUIRE_AUTOCOMPLETE &&
113 control_element.formControlType() == WebString::fromUTF8("text")) { 121 control_element.formControlType() == WebString::fromUTF8("text")) {
114 const WebInputElement& input_element = 122 const WebInputElement& input_element =
115 control_element.toConstElement<WebInputElement>(); 123 control_element.toConstElement<WebInputElement>();
116 if (!input_element.autoComplete()) 124 if (!input_element.autoComplete())
117 continue; 125 continue;
118 } 126 }
119 127
120 if (requirements & REQUIRE_ELEMENTS_ENABLED && !control_element.isEnabled()) 128 if (requirements & REQUIRE_ELEMENTS_ENABLED && !control_element.isEnabled())
121 continue; 129 continue;
122 130
123 FormField field; 131 // Create a new FormField, fill it out and map it to the field's name.
124 WebFormControlElementToFormField(control_element, &field); 132 FormField* field = new FormField;
125 form->fields.push_back(field); 133 WebFormControlElementToFormField(control_element, field);
134 form_fields.push_back(field);
135 // TODO(jhawkins): A label element is mapped to a form control element's id.
136 // field->name() will contain the id only if the name does not exist. Add
137 // an id() method to WebFormControlElement and use that here.
138 name_map[field->name()] = field;
126 } 139 }
127 140
128 return !form->fields.empty(); 141 // Don't extract field labels if we have no fields.
142 if (form_fields.empty())
143 return false;
144
145 // Loop through the label elements inside the form element. For each label
146 // element, get the corresponding form control element, use the form control
147 // element's name as a key into the <name, FormField> map to find the
148 // previously created FormField and set the FormField's label to the
149 // innerText() of the label element.
150 WebNodeList labels = element.getElementsByTagName("label");
151 for (unsigned i = 0; i < labels.length(); ++i) {
152 WebLabelElement label = labels.item(i).toElement<WebLabelElement>();
153 WebFormControlElement field_element =
154 label.correspondingControl().toElement<WebFormControlElement>();
155 if (field_element.isNull() || !field_element.isFormControlElement())
156 continue;
157
158 std::map<string16, FormField*>::iterator iter =
159 name_map.find(field_element.nameForAutofill());
160 if (iter != name_map.end())
161 iter->second->set_label(label.innerText());
162 }
163
164 // Copy the created FormFields into the resulting FormData object.
165 for (ScopedVector<FormField>::const_iterator iter = form_fields.begin();
166 iter != form_fields.end(); ++iter) {
167 form->fields.push_back(**iter);
168 }
169
170 return true;
129 } 171 }
130 172
131 void FormManager::ExtractForms(const WebFrame* frame) { 173 void FormManager::ExtractForms(const WebFrame* frame) {
132 DCHECK(frame); 174 DCHECK(frame);
133 175
134 // Reset the vector of FormElements for this frame. 176 // Reset the vector of FormElements for this frame.
135 ResetFrame(frame); 177 ResetFrame(frame);
136 178
137 WebVector<WebFormElement> web_forms; 179 WebVector<WebFormElement> web_forms;
138 frame->forms(web_forms); 180 frame->forms(web_forms);
139 181
140 for (size_t i = 0; i < web_forms.size(); ++i) { 182 for (size_t i = 0; i < web_forms.size(); ++i) {
141 FormElement* form_elements = new FormElement; 183 FormElement* form_elements = new FormElement;
142 form_elements->form_element = web_forms[i]; 184 form_elements->form_element = web_forms[i];
143 185
144 WebVector<WebFormControlElement> control_elements; 186 WebVector<WebFormControlElement> control_elements;
145 form_elements->form_element.getFormControlElements(control_elements); 187 form_elements->form_element.getFormControlElements(control_elements);
146 for (size_t j = 0; j < control_elements.size(); ++j) { 188 for (size_t j = 0; j < control_elements.size(); ++j) {
147 WebFormControlElement element = control_elements[j]; 189 WebFormControlElement element = control_elements[j];
148 // TODO(jhawkins): Remove this check when we have labels. 190 form_elements->control_elements.push_back(element);
149 if (!element.nameForAutofill().isEmpty())
150 form_elements->control_elements[element.nameForAutofill()] = element;
151 } 191 }
152 192
153 form_elements_map_[frame].push_back(form_elements); 193 form_elements_map_[frame].push_back(form_elements);
154 } 194 }
155 } 195 }
156 196
157 void FormManager::GetForms(RequirementsMask requirements, 197 void FormManager::GetForms(RequirementsMask requirements,
158 std::vector<FormData>* forms) { 198 std::vector<FormData>* forms) {
159 DCHECK(forms); 199 DCHECK(forms);
160 200
161 for (WebFrameFormElementMap::iterator iter = form_elements_map_.begin(); 201 for (WebFrameFormElementMap::iterator iter = form_elements_map_.begin();
162 iter != form_elements_map_.end(); ++iter) { 202 iter != form_elements_map_.end(); ++iter) {
163 const WebFrame* frame = iter->first;
164
165 for (std::vector<FormElement*>::iterator form_iter = iter->second.begin(); 203 for (std::vector<FormElement*>::iterator form_iter = iter->second.begin();
166 form_iter != iter->second.end(); ++form_iter) { 204 form_iter != iter->second.end(); ++form_iter) {
167 FormElement* form_element = *form_iter;
168
169 if (requirements & REQUIRE_AUTOCOMPLETE &&
170 !form_element->form_element.autoComplete())
171 continue;
172
173 FormData form; 205 FormData form;
174 FormElementToFormData(frame, form_element, requirements, &form); 206 if (WebFormElementToFormData((*form_iter)->form_element,
175 forms->push_back(form); 207 requirements,
208 &form))
209 forms->push_back(form);
176 } 210 }
177 } 211 }
178 } 212 }
179 213
180 void FormManager::GetFormsInFrame(const WebFrame* frame, 214 void FormManager::GetFormsInFrame(const WebFrame* frame,
181 RequirementsMask requirements, 215 RequirementsMask requirements,
182 std::vector<FormData>* forms) { 216 std::vector<FormData>* forms) {
183 DCHECK(frame); 217 DCHECK(frame);
184 DCHECK(forms); 218 DCHECK(forms);
185 219
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 return false; 281 return false;
248 282
249 if (form_elements_map_.find(frame) == form_elements_map_.end()) 283 if (form_elements_map_.find(frame) == form_elements_map_.end())
250 return false; 284 return false;
251 285
252 const std::vector<FormElement*> forms = form_elements_map_[frame]; 286 const std::vector<FormElement*> forms = form_elements_map_[frame];
253 for (std::vector<FormElement*>::const_iterator iter = forms.begin(); 287 for (std::vector<FormElement*>::const_iterator iter = forms.begin();
254 iter != forms.end(); ++iter) { 288 iter != forms.end(); ++iter) {
255 const FormElement* form_element = *iter; 289 const FormElement* form_element = *iter;
256 290
257 if (form_element->control_elements.find(element.nameForAutofill()) != 291 for (std::vector<WebFormControlElement>::const_iterator iter =
258 form_element->control_elements.end()) { 292 form_element->control_elements.begin();
259 FormElementToFormData(frame, form_element, requirements, form); 293 iter != form_element->control_elements.end(); ++iter) {
260 return true; 294 if (iter->nameForAutofill() == element.nameForAutofill()) {
295 WebFormElementToFormData(form_element->form_element, requirements, form) ;
296 return true;
297 }
261 } 298 }
262 } 299 }
263 300
264 return false; 301 return false;
265 } 302 }
266 303
267 bool FormManager::FillForm(const FormData& form) { 304 bool FormManager::FillForm(const FormData& form) {
268 FormElement* form_element = NULL; 305 FormElement* form_element = NULL;
269 306
270 // Frame loop.
271 for (WebFrameFormElementMap::iterator iter = form_elements_map_.begin(); 307 for (WebFrameFormElementMap::iterator iter = form_elements_map_.begin();
272 iter != form_elements_map_.end(); ++iter) { 308 iter != form_elements_map_.end(); ++iter) {
273 // Form loop.
274 for (std::vector<FormElement*>::iterator form_iter = iter->second.begin(); 309 for (std::vector<FormElement*>::iterator form_iter = iter->second.begin();
275 form_iter != iter->second.end(); ++form_iter) { 310 form_iter != iter->second.end(); ++form_iter) {
276 // TODO(dhollowa): matching on form name here which is not guaranteed to 311 // TODO(dhollowa): matching on form name here which is not guaranteed to
277 // be unique for the page, nor is it guaranteed to be non-empty. Need to 312 // be unique for the page, nor is it guaranteed to be non-empty. Need to
278 // find a way to uniquely identify the form cross-process. 313 // find a way to uniquely identify the form cross-process.
279 // http://crbug.com/37990 test file sample8.html. 314 // http://crbug.com/37990 test file sample8.html.
280 // Also note that WebString() == WebString(string16()) does not seem to 315 // Also note that WebString() == WebString(string16()) does not seem to
281 // evaluate to |true| for some reason TBD, so forcing to string16. 316 // evaluate to |true| for some reason TBD, so forcing to string16.
282 string16 element_name((*form_iter)->form_element.name()); 317 string16 element_name((*form_iter)->form_element.name());
283 if (element_name == form.name && 318 if (element_name == form.name &&
284 (*form_iter)->control_elements.size() == form.fields.size()) { 319 (*form_iter)->control_elements.size() == form.fields.size()) {
285 form_element = *form_iter; 320 form_element = *form_iter;
286 break; 321 break;
287 } 322 }
288 } 323 }
289 } 324 }
290 325
291 if (!form_element) 326 if (!form_element)
292 return false; 327 return false;
293 328
294 DCHECK(form_element->control_elements.size() == form.fields.size()); 329 DCHECK(form_element->control_elements.size() == form.fields.size());
295 330
296 size_t i = 0; 331 for (size_t i = 0; i < form.fields.size(); ++i) {
297 for (FormControlElementMap::iterator iter = 332 WebFormControlElement* element = &form_element->control_elements[i];
298 form_element->control_elements.begin(); 333
299 iter != form_element->control_elements.end(); ++iter, ++i) { 334 // It's possible that nameForAutofill() is empty if the form control element
300 DCHECK_EQ(form.fields[i].name(), iter->second.nameForAutofill()); 335 // has no name or ID. In that case, iter->nameForAutofill() must also be
336 // empty.
337 if (form.fields[i].name().empty())
338 DCHECK(element->nameForAutofill().isEmpty());
339 else
340 DCHECK_EQ(form.fields[i].name(), element->nameForAutofill());
301 341
302 if (!form.fields[i].value().empty() && 342 if (!form.fields[i].value().empty() &&
303 iter->second.formControlType() != WebString::fromUTF8("submit")) { 343 element->formControlType() != WebString::fromUTF8("submit")) {
304 if (iter->second.formControlType() == WebString::fromUTF8("text")) { 344 if (element->formControlType() == WebString::fromUTF8("text")) {
305 WebInputElement input_element = 345 WebInputElement input_element = element->toElement<WebInputElement>();
306 iter->second.toElement<WebInputElement>();
307 input_element.setValue(form.fields[i].value()); 346 input_element.setValue(form.fields[i].value());
308 input_element.setAutofilled(true); 347 input_element.setAutofilled(true);
309 } else if (iter->second.formControlType() == 348 } else if (element->formControlType() ==
310 WebString::fromUTF8("select-one")) { 349 WebString::fromUTF8("select-one")) {
311 WebSelectElement select_element = 350 WebSelectElement select_element =
312 iter->second.toElement<WebSelectElement>(); 351 element->toElement<WebSelectElement>();
313 select_element.setValue(form.fields[i].value()); 352 select_element.setValue(form.fields[i].value());
314 } 353 }
315 } 354 }
316 } 355 }
317 356
318 return true; 357 return true;
319 } 358 }
320 359
321 void FormManager::Reset() { 360 void FormManager::Reset() {
322 for (WebFrameFormElementMap::iterator iter = form_elements_map_.begin(); 361 for (WebFrameFormElementMap::iterator iter = form_elements_map_.begin();
(...skipping 16 matching lines...) Expand all
339 form->method = form_element->form_element.method(); 378 form->method = form_element->form_element.method();
340 form->origin = frame->url(); 379 form->origin = frame->url();
341 form->action = frame->completeURL(form_element->form_element.action()); 380 form->action = frame->completeURL(form_element->form_element.action());
342 381
343 // If the completed URL is not valid, just use the action we get from 382 // If the completed URL is not valid, just use the action we get from
344 // WebKit. 383 // WebKit.
345 if (!form->action.is_valid()) 384 if (!form->action.is_valid())
346 form->action = GURL(form_element->form_element.action()); 385 form->action = GURL(form_element->form_element.action());
347 386
348 // Form elements loop. 387 // Form elements loop.
349 for (FormControlElementMap::const_iterator element_iter = 388 for (std::vector<WebFormControlElement>::const_iterator element_iter =
350 form_element->control_elements.begin(); 389 form_element->control_elements.begin();
351 element_iter != form_element->control_elements.end(); ++element_iter) { 390 element_iter != form_element->control_elements.end(); ++element_iter) {
352 WebFormControlElement control_element = element_iter->second; 391 const WebFormControlElement& control_element = *element_iter;
353 392
354 if (requirements & REQUIRE_AUTOCOMPLETE && 393 if (requirements & REQUIRE_AUTOCOMPLETE &&
355 control_element.formControlType() == WebString::fromUTF8("text")) { 394 control_element.formControlType() == WebString::fromUTF8("text")) {
356 const WebInputElement& input_element = 395 const WebInputElement& input_element =
357 control_element.toConstElement<WebInputElement>(); 396 control_element.toConstElement<WebInputElement>();
358 if (!input_element.autoComplete()) 397 if (!input_element.autoComplete())
359 continue; 398 continue;
360 } 399 }
361 400
362 if (requirements & REQUIRE_ELEMENTS_ENABLED && !control_element.isEnabled()) 401 if (requirements & REQUIRE_ELEMENTS_ENABLED && !control_element.isEnabled())
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 inferred_label = element.innerText(); 491 inferred_label = element.innerText();
453 TrimWhitespace(inferred_label, TRIM_ALL, &inferred_label); 492 TrimWhitespace(inferred_label, TRIM_ALL, &inferred_label);
454 } 493 }
455 } 494 }
456 } 495 }
457 } 496 }
458 } 497 }
459 498
460 return inferred_label; 499 return inferred_label;
461 } 500 }
OLDNEW
« no previous file with comments | « chrome/renderer/form_manager.h ('k') | chrome/renderer/form_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698