OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |