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

Unified 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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")) {
« 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