| 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 |