Index: chrome/renderer/form_manager.cc |
diff --git a/chrome/renderer/form_manager.cc b/chrome/renderer/form_manager.cc |
index 3d313b60ee78ada5c6c5d3e4278ac0a4c8945a1e..5bd22e52fcf394fcebd9be665c28af4f802096f2 100644 |
--- a/chrome/renderer/form_manager.cc |
+++ b/chrome/renderer/form_manager.cc |
@@ -5,6 +5,7 @@ |
#include "chrome/renderer/form_manager.h" |
#include "base/logging.h" |
+#include "base/scoped_vector.h" |
#include "base/string_util.h" |
#include "base/stl_util-inl.h" |
#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h" |
@@ -58,9 +59,9 @@ void FormManager::WebFormControlElementToFormField( |
const WebFormControlElement& element, FormField* field) { |
DCHECK(field); |
- // TODO(jhawkins): LabelForElement. Returning an empty label temporarily to |
- // diagnose a perf issue. |
- field->set_label(string16()); |
+ // The label is not officially part of a WebFormControlElement; however, the |
+ // labels for all form control elements are scraped from the DOM and set in |
+ // WebFormElementToFormData. |
field->set_name(element.nameForAutofill()); |
field->set_form_control_type(element.formControlType()); |
@@ -104,6 +105,13 @@ bool FormManager::WebFormElementToFormData(const WebFormElement& element, |
if (!form->action.is_valid()) |
form->action = GURL(element.action()); |
+ // A map from a FormField's name to the FormField itself. |
+ std::map<string16, FormField*> name_map; |
+ |
+ // The extracted FormFields. We use pointers so we can store them in |
+ // |name_map|. |
+ ScopedVector<FormField> form_fields; |
+ |
WebVector<WebFormControlElement> control_elements; |
element.getFormControlElements(control_elements); |
for (size_t i = 0; i < control_elements.size(); ++i) { |
@@ -120,12 +128,46 @@ bool FormManager::WebFormElementToFormData(const WebFormElement& element, |
if (requirements & REQUIRE_ELEMENTS_ENABLED && !control_element.isEnabled()) |
continue; |
- FormField field; |
- WebFormControlElementToFormField(control_element, &field); |
- form->fields.push_back(field); |
+ // Create a new FormField, fill it out and map it to the field's name. |
+ FormField* field = new FormField; |
+ WebFormControlElementToFormField(control_element, field); |
+ form_fields.push_back(field); |
+ // TODO(jhawkins): A label element is mapped to a form control element's id. |
+ // field->name() will contain the id only if the name does not exist. Add |
+ // an id() method to WebFormControlElement and use that here. |
+ name_map[field->name()] = field; |
+ } |
+ |
+ // Don't extract field labels if we have no fields. |
+ if (form_fields.empty()) |
+ return false; |
+ |
+ // Loop through the label elements inside the form element. For each label |
+ // element, get the corresponding form control element, use the form control |
+ // element's name as a key into the <name, FormField> map to find the |
+ // previously created FormField and set the FormField's label to the |
+ // innerText() of the label element. |
+ WebNodeList labels = element.getElementsByTagName("label"); |
+ for (unsigned i = 0; i < labels.length(); ++i) { |
+ WebLabelElement label = labels.item(i).toElement<WebLabelElement>(); |
+ WebFormControlElement field_element = |
+ label.correspondingControl().toElement<WebFormControlElement>(); |
+ if (field_element.isNull() || !field_element.isFormControlElement()) |
+ continue; |
+ |
+ std::map<string16, FormField*>::iterator iter = |
+ name_map.find(field_element.nameForAutofill()); |
+ if (iter != name_map.end()) |
+ iter->second->set_label(label.innerText()); |
} |
- return !form->fields.empty(); |
+ // Copy the created FormFields into the resulting FormData object. |
+ for (ScopedVector<FormField>::const_iterator iter = form_fields.begin(); |
+ iter != form_fields.end(); ++iter) { |
+ form->fields.push_back(**iter); |
+ } |
+ |
+ return true; |
} |
void FormManager::ExtractForms(const WebFrame* frame) { |
@@ -145,9 +187,7 @@ void FormManager::ExtractForms(const WebFrame* frame) { |
form_elements->form_element.getFormControlElements(control_elements); |
for (size_t j = 0; j < control_elements.size(); ++j) { |
WebFormControlElement element = control_elements[j]; |
- // TODO(jhawkins): Remove this check when we have labels. |
- if (!element.nameForAutofill().isEmpty()) |
- form_elements->control_elements[element.nameForAutofill()] = element; |
+ form_elements->control_elements.push_back(element); |
} |
form_elements_map_[frame].push_back(form_elements); |
@@ -160,19 +200,13 @@ void FormManager::GetForms(RequirementsMask requirements, |
for (WebFrameFormElementMap::iterator iter = form_elements_map_.begin(); |
iter != form_elements_map_.end(); ++iter) { |
- const WebFrame* frame = iter->first; |
- |
for (std::vector<FormElement*>::iterator form_iter = iter->second.begin(); |
form_iter != iter->second.end(); ++form_iter) { |
- FormElement* form_element = *form_iter; |
- |
- if (requirements & REQUIRE_AUTOCOMPLETE && |
- !form_element->form_element.autoComplete()) |
- continue; |
- |
FormData form; |
- FormElementToFormData(frame, form_element, requirements, &form); |
- forms->push_back(form); |
+ if (WebFormElementToFormData((*form_iter)->form_element, |
+ requirements, |
+ &form)) |
+ forms->push_back(form); |
} |
} |
} |
@@ -254,10 +288,13 @@ bool FormManager::FindFormWithFormControlElement( |
iter != forms.end(); ++iter) { |
const FormElement* form_element = *iter; |
- if (form_element->control_elements.find(element.nameForAutofill()) != |
- form_element->control_elements.end()) { |
- FormElementToFormData(frame, form_element, requirements, form); |
- return true; |
+ for (std::vector<WebFormControlElement>::const_iterator iter = |
+ form_element->control_elements.begin(); |
+ iter != form_element->control_elements.end(); ++iter) { |
+ if (iter->nameForAutofill() == element.nameForAutofill()) { |
+ WebFormElementToFormData(form_element->form_element, requirements, form); |
+ return true; |
+ } |
} |
} |
@@ -267,10 +304,8 @@ bool FormManager::FindFormWithFormControlElement( |
bool FormManager::FillForm(const FormData& form) { |
FormElement* form_element = NULL; |
- // Frame loop. |
for (WebFrameFormElementMap::iterator iter = form_elements_map_.begin(); |
iter != form_elements_map_.end(); ++iter) { |
- // Form loop. |
for (std::vector<FormElement*>::iterator form_iter = iter->second.begin(); |
form_iter != iter->second.end(); ++form_iter) { |
// TODO(dhollowa): matching on form name here which is not guaranteed to |
@@ -293,23 +328,27 @@ bool FormManager::FillForm(const FormData& form) { |
DCHECK(form_element->control_elements.size() == form.fields.size()); |
- size_t i = 0; |
- for (FormControlElementMap::iterator iter = |
- form_element->control_elements.begin(); |
- iter != form_element->control_elements.end(); ++iter, ++i) { |
- DCHECK_EQ(form.fields[i].name(), iter->second.nameForAutofill()); |
+ for (size_t i = 0; i < form.fields.size(); ++i) { |
+ WebFormControlElement* element = &form_element->control_elements[i]; |
+ |
+ // It's possible that nameForAutofill() is empty if the form control element |
+ // has no name or ID. In that case, iter->nameForAutofill() must also be |
+ // empty. |
+ if (form.fields[i].name().empty()) |
+ DCHECK(element->nameForAutofill().isEmpty()); |
+ else |
+ DCHECK_EQ(form.fields[i].name(), element->nameForAutofill()); |
if (!form.fields[i].value().empty() && |
- iter->second.formControlType() != WebString::fromUTF8("submit")) { |
- if (iter->second.formControlType() == WebString::fromUTF8("text")) { |
- WebInputElement input_element = |
- iter->second.toElement<WebInputElement>(); |
+ element->formControlType() != WebString::fromUTF8("submit")) { |
+ if (element->formControlType() == WebString::fromUTF8("text")) { |
+ WebInputElement input_element = element->toElement<WebInputElement>(); |
input_element.setValue(form.fields[i].value()); |
input_element.setAutofilled(true); |
- } else if (iter->second.formControlType() == |
+ } else if (element->formControlType() == |
WebString::fromUTF8("select-one")) { |
WebSelectElement select_element = |
- iter->second.toElement<WebSelectElement>(); |
+ element->toElement<WebSelectElement>(); |
select_element.setValue(form.fields[i].value()); |
} |
} |
@@ -346,10 +385,10 @@ bool FormManager::FormElementToFormData(const WebFrame* frame, |
form->action = GURL(form_element->form_element.action()); |
// Form elements loop. |
- for (FormControlElementMap::const_iterator element_iter = |
+ for (std::vector<WebFormControlElement>::const_iterator element_iter = |
form_element->control_elements.begin(); |
element_iter != form_element->control_elements.end(); ++element_iter) { |
- WebFormControlElement control_element = element_iter->second; |
+ const WebFormControlElement& control_element = *element_iter; |
if (requirements & REQUIRE_AUTOCOMPLETE && |
control_element.formControlType() == WebString::fromUTF8("text")) { |