summaryrefslogtreecommitdiffstats
path: root/chrome/renderer
diff options
context:
space:
mode:
authorisherman@chromium.org <isherman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-07 21:18:32 +0000
committerisherman@chromium.org <isherman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-07 21:18:32 +0000
commit829245b1c00a35df64fd0acd6f90518b2880731c (patch)
tree65d7c7ed1787649cd07d99737a013dc5c50ed574 /chrome/renderer
parent658600ecbdb63bf8997d0c87812243cc1aae670e (diff)
downloadchromium_src-829245b1c00a35df64fd0acd6f90518b2880731c.zip
chromium_src-829245b1c00a35df64fd0acd6f90518b2880731c.tar.gz
chromium_src-829245b1c00a35df64fd0acd6f90518b2880731c.tar.bz2
Add Autofill support for dynamically updated forms (updated via JavaScript).
o Rip out most of the cache in the renderer (FormManager). + We still cache the set of loaded frames, so that we can show field type predictions (when the corresponding flag is enabled). + We also still cache the original values for <select> elements, so that we can restore these values upon clearing a form. + That's all that we cache! + This vastly simplifies the form previewing/filling loop logic. o Update the browser process cache on the fly. + Whenever we look for a form in our cache, update the cache if we don't find an exact match. + We also preserve the original versions of cached forms, so that we do not destroy our ability to parse the crowdsourcing server's response to a query. + This vastly simplifies the form filling and section finding loop logic. o Related code cleanup + Consolidated previously duplicated label extraction code. + Several member functions on the renderer side became static. + Const-correctness for several functions on the browser side. + Decomposed some functions into more manageable chunks. + Unique field names are guaranteed to actually be unique! BUG=57182, 64112, 44323, 92229, 88252, 62593, 93595, 51527 TEST=interactive_ui_tests --gtest_filter=AutofillTest.DynamicFormFill Review URL: http://codereview.chromium.org/7831032 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@100021 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer')
-rw-r--r--chrome/renderer/autofill/autofill_agent.cc39
-rw-r--r--chrome/renderer/autofill/form_manager.cc579
-rw-r--r--chrome/renderer/autofill/form_manager.h118
-rw-r--r--chrome/renderer/autofill/form_manager_browsertest.cc553
4 files changed, 481 insertions, 808 deletions
diff --git a/chrome/renderer/autofill/autofill_agent.cc b/chrome/renderer/autofill/autofill_agent.cc
index 98334d7..d18d9b4 100644
--- a/chrome/renderer/autofill/autofill_agent.cc
+++ b/chrome/renderer/autofill/autofill_agent.cc
@@ -78,7 +78,7 @@ void AutofillAgent::DidFinishDocumentLoad(WebFrame* frame) {
// The document has now been fully loaded. Scan for forms to be sent up to
// the browser.
std::vector<webkit_glue::FormData> forms;
- form_manager_.ExtractForms(frame, &forms);
+ form_manager_.ExtractForms(*frame, &forms);
if (!forms.empty()) {
Send(new AutofillHostMsg_FormsSeen(routing_id(), forms,
@@ -87,11 +87,11 @@ void AutofillAgent::DidFinishDocumentLoad(WebFrame* frame) {
}
void AutofillAgent::FrameDetached(WebFrame* frame) {
- form_manager_.ResetFrame(frame);
+ form_manager_.ResetFrame(*frame);
}
void AutofillAgent::FrameWillClose(WebFrame* frame) {
- form_manager_.ResetFrame(frame);
+ form_manager_.ResetFrame(*frame);
}
void AutofillAgent::WillSubmitForm(WebFrame* frame,
@@ -99,10 +99,12 @@ void AutofillAgent::WillSubmitForm(WebFrame* frame,
FormData form_data;
if (FormManager::WebFormElementToFormData(
form,
+ WebFormControlElement(),
FormManager::REQUIRE_AUTOCOMPLETE,
static_cast<FormManager::ExtractMask>(
FormManager::EXTRACT_VALUE | FormManager::EXTRACT_OPTION_TEXT),
- &form_data)) {
+ &form_data,
+ NULL)) {
Send(new AutofillHostMsg_FormSubmitted(routing_id(), form_data,
base::TimeTicks::Now()));
}
@@ -137,7 +139,8 @@ void AutofillAgent::didAcceptAutofillSuggestion(const WebNode& node,
} else if (suggestions_clear_index_ != -1 &&
index == static_cast<unsigned>(suggestions_clear_index_)) {
// User selected 'Clear form'.
- form_manager_.ClearFormWithNode(node);
+ DCHECK(node == autofill_query_element_);
+ form_manager_.ClearFormWithElement(autofill_query_element_);
} else if (!unique_id) {
// User selected an Autocomplete entry, so we fill directly.
WebInputElement element = node.toConst<WebInputElement>();
@@ -167,7 +170,9 @@ void AutofillAgent::didSelectAutofillSuggestion(const WebNode& node,
}
void AutofillAgent::didClearAutofillSelection(const WebNode& node) {
- form_manager_.ClearPreviewedFormWithNode(node, was_query_node_autofilled_);
+ DCHECK(node == autofill_query_element_);
+ FormManager::ClearPreviewedFormWithElement(autofill_query_element_,
+ was_query_node_autofilled_);
}
void AutofillAgent::removeAutocompleteSuggestion(const WebString& name,
@@ -276,7 +281,7 @@ void AutofillAgent::OnSuggestionsReturned(int query_id,
// The form has been auto-filled, so give the user the chance to clear the
// form. Append the 'Clear form' menu item.
if (has_autofill_item &&
- form_manager_.FormWithNodeIsAutofilled(autofill_query_element_)) {
+ FormManager::FormWithElementIsAutofilled(autofill_query_element_)) {
v.push_back(l10n_util::GetStringUTF16(IDS_AUTOFILL_CLEAR_FORM_MENU_ITEM));
l.push_back(string16());
i.push_back(string16());
@@ -316,12 +321,12 @@ void AutofillAgent::OnFormDataFilled(int query_id,
switch (autofill_action_) {
case AUTOFILL_FILL:
- form_manager_.FillForm(form, autofill_query_element_);
+ FormManager::FillForm(form, autofill_query_element_);
Send(new AutofillHostMsg_DidFillAutofillFormData(routing_id(),
base::TimeTicks::Now()));
break;
case AUTOFILL_PREVIEW:
- form_manager_.PreviewForm(form, autofill_query_element_);
+ FormManager::PreviewForm(form, autofill_query_element_);
Send(new AutofillHostMsg_DidPreviewAutofillFormData(routing_id()));
break;
default:
@@ -415,20 +420,8 @@ bool AutofillAgent::FindFormAndFieldForNode(const WebNode& node,
webkit_glue::FormData* form,
webkit_glue::FormField* field) {
const WebInputElement& element = node.toConst<WebInputElement>();
- if (!form_manager_.FindFormWithFormControlElement(element, form))
- return false;
-
- FormManager::WebFormControlElementToFormField(element,
- FormManager::EXTRACT_VALUE,
- field);
-
- // WebFormControlElementToFormField does not scrape the DOM for the field
- // label, so find the label here.
- // TODO(isherman): Add form and field identities so we can use the cached form
- // data in FormManager.
- field->label = FormManager::LabelForElement(element);
-
- return true;
+ return
+ FormManager::FindFormAndFieldForFormControlElement(element, form, field);
}
} // namespace autofill
diff --git a/chrome/renderer/autofill/form_manager.cc b/chrome/renderer/autofill/form_manager.cc
index 3465f93..99e2f8e 100644
--- a/chrome/renderer/autofill/form_manager.cc
+++ b/chrome/renderer/autofill/form_manager.cc
@@ -457,35 +457,62 @@ typedef void (*Callback)(WebKit::WebFormControlElement*,
const webkit_glue::FormField*,
bool);
+// Fills |autofillable_elements| with all the auto-fillable form control
+// elements in |form_element|.
+void ExtractAutofillableElements(
+ const WebFormElement& form_element,
+ std::vector<WebFormControlElement>* autofillable_elements) {
+ WebVector<WebFormControlElement> control_elements;
+ form_element.getFormControlElements(control_elements);
+
+ autofillable_elements->clear();
+ for (size_t i = 0; i < control_elements.size(); ++i) {
+ WebFormControlElement element = control_elements[i];
+ if (!IsAutofillableElement(element))
+ continue;
+
+ autofillable_elements->push_back(element);
+ }
+}
+
// For each autofillable field in |data| that matches a field in the |form|,
// the |callback| is invoked with the corresponding |form| field data.
-void ForEachMatchingFormField(
- std::vector<WebKit::WebFormControlElement>* control_elements,
- const WebNode& node,
- const FormData& data,
- Callback callback) {
+void ForEachMatchingFormField(const WebFormElement& form_element,
+ const WebElement& initiating_element,
+ const FormData& data,
+ Callback callback) {
+ std::vector<WebFormControlElement> control_elements;
+ ExtractAutofillableElements(form_element, &control_elements);
+
+ if (control_elements.size() != data.fields.size()) {
+ // This case should be reachable only for pathological websites, which add
+ // or remove form fields while the user is interacting with the Autofill
+ // popup. I (isherman) am not aware of any such websites, and so am
+ // optimistically including a NOTREACHED(). If you ever trip this check,
+ // please file a bug against me.
+ NOTREACHED();
+ return;
+ }
+
// It's possible that the site has injected fields into the form after the
// page has loaded, so we can't assert that the size of the cached control
// elements is equal to the size of the fields in |form|. Fortunately, the
// one case in the wild where this happens, paypal.com signup form, the fields
// are appended to the end of the form and are not visible.
- for (size_t i = 0, j = 0;
- i < control_elements->size() && j < data.fields.size();
- ++i) {
- WebFormControlElement* element = &(*control_elements)[i];
- string16 element_name(element->nameForAutofill());
-
- // Search forward in the |form| for a corresponding field.
- size_t k = j;
- while (k < data.fields.size() && element_name != data.fields[k].name)
- k++;
-
- if (k >= data.fields.size())
+ for (size_t i = 0; i < control_elements.size(); ++i) {
+ WebFormControlElement* element = &control_elements[i];
+
+ if (string16(element->nameForAutofill()) != data.fields[i].name) {
+ // This case should be reachable only for pathological websites, which
+ // rename form fields while the user is interacting with the Autofill
+ // popup. I (isherman) am not aware of any such websites, and so am
+ // optimistically including a NOTREACHED(). If you ever trip this check,
+ // please file a bug against me.
+ NOTREACHED();
continue;
+ }
- DCHECK_EQ(data.fields[k].name, element_name);
-
- bool is_initiating_node = false;
+ bool is_initiating_element = (*element == initiating_element);
const WebInputElement* input_element = toWebInputElement(element);
if (IsTextInput(input_element)) {
@@ -494,11 +521,9 @@ void ForEachMatchingFormField(
if (!input_element->autoComplete())
continue;
- is_initiating_node = (*input_element == node);
-
// Only autofill empty fields and the field that initiated the filling,
// i.e. the field the user is currently editing and interacting with.
- if (!is_initiating_node && !input_element->value().isEmpty())
+ if (!is_initiating_element && !input_element->value().isEmpty())
continue;
}
@@ -506,10 +531,7 @@ void ForEachMatchingFormField(
!element->isFocusable())
continue;
- callback(element, &data.fields[k], is_initiating_node);
-
- // We found a matching form field so move on to the next.
- ++j;
+ callback(element, &data.fields[i], is_initiating_element);
}
}
@@ -573,12 +595,6 @@ void PreviewFormField(WebKit::WebFormControlElement* field,
namespace autofill {
-struct FormManager::FormElement {
- WebKit::WebFormElement form_element;
- std::vector<WebKit::WebFormControlElement> control_elements;
- std::vector<string16> control_values;
-};
-
FormManager::FormManager() {
}
@@ -659,50 +675,30 @@ void FormManager::WebFormControlElementToFormField(
}
// static
-string16 FormManager::LabelForElement(const WebFormControlElement& element) {
- // Don't scrape labels for elements we can't possibly autofill anyway.
- if (!IsAutofillableElement(element))
- return string16();
-
- WebNodeList labels = element.document().getElementsByTagName("label");
- for (unsigned i = 0; i < labels.length(); ++i) {
- WebLabelElement label = labels.item(i).to<WebLabelElement>();
- WebElement corresponding_control = label.correspondingControl();
- if (corresponding_control == element ||
- (corresponding_control.isNull() &&
- label.getAttribute("for") == element.nameForAutofill())) {
- return FindChildText(label);
- }
- }
-
- // Infer the label from context if not found in label element.
- return InferLabelForElement(element);
-}
-
-// static
-bool FormManager::WebFormElementToFormData(const WebFormElement& element,
- RequirementsMask requirements,
- ExtractMask extract_mask,
- FormData* form) {
- DCHECK(form);
-
- const WebFrame* frame = element.document().frame();
+bool FormManager::WebFormElementToFormData(
+ const WebKit::WebFormElement& form_element,
+ const WebKit::WebFormControlElement& form_control_element,
+ RequirementsMask requirements,
+ ExtractMask extract_mask,
+ webkit_glue::FormData* form,
+ webkit_glue::FormField* field) {
+ const WebFrame* frame = form_element.document().frame();
if (!frame)
return false;
- if (requirements & REQUIRE_AUTOCOMPLETE && !element.autoComplete())
+ if (requirements & REQUIRE_AUTOCOMPLETE && !form_element.autoComplete())
return false;
- form->name = GetFormIdentifier(element);
- form->method = element.method();
+ form->name = GetFormIdentifier(form_element);
+ form->method = form_element.method();
form->origin = frame->document().url();
- form->action = frame->document().completeURL(element.action());
- form->user_submitted = element.wasUserSubmitted();
+ form->action = frame->document().completeURL(form_element.action());
+ form->user_submitted = form_element.wasUserSubmitted();
// If the completed URL is not valid, just use the action we get from
// WebKit.
if (!form->action.is_valid())
- form->action = GURL(element.action());
+ form->action = GURL(form_element.action());
// A map from a FormField's name to the FormField itself.
std::map<string16, FormField*> name_map;
@@ -712,7 +708,7 @@ bool FormManager::WebFormElementToFormData(const WebFormElement& element,
ScopedVector<FormField> form_fields;
WebVector<WebFormControlElement> control_elements;
- element.getFormControlElements(control_elements);
+ form_element.getFormControlElements(control_elements);
// A vector of bools that indicate whether each field in the form meets the
// requirements and thus will be in the resulting |form|.
@@ -733,13 +729,13 @@ bool FormManager::WebFormElementToFormData(const WebFormElement& element,
continue;
// Create a new FormField, fill it out and map it to the field's name.
- FormField* field = new FormField;
- WebFormControlElementToFormField(control_element, extract_mask, field);
- form_fields.push_back(field);
+ FormField* form_field = new FormField;
+ WebFormControlElementToFormField(control_element, extract_mask, form_field);
+ form_fields.push_back(form_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;
+ name_map[form_field->name] = form_field;
fields_extracted[i] = true;
}
@@ -752,7 +748,7 @@ bool FormManager::WebFormElementToFormData(const WebFormElement& element,
// 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
// label.firstChild().nodeValue() of the label element.
- WebNodeList labels = element.getElementsByTagName("label");
+ WebNodeList labels = form_element.getElementsByTagName("label");
for (unsigned i = 0; i < labels.length(); ++i) {
WebLabelElement label = labels.item(i).to<WebLabelElement>();
WebFormControlElement field_element =
@@ -798,6 +794,9 @@ bool FormManager::WebFormElementToFormData(const WebFormElement& element,
if (form_fields[field_idx]->label.empty())
form_fields[field_idx]->label = InferLabelForElement(control_element);
+ if (field && form_control_element == control_element)
+ *field = *form_fields[field_idx];
+
++field_idx;
}
@@ -810,50 +809,156 @@ bool FormManager::WebFormElementToFormData(const WebFormElement& element,
return true;
}
-void FormManager::ExtractForms(const WebFrame* frame,
+// static
+bool FormManager::FindFormAndFieldForFormControlElement(
+ const WebFormControlElement& element,
+ FormData* form,
+ webkit_glue::FormField* field) {
+ const WebFormElement form_element = element.form();
+ if (form_element.isNull())
+ return false;
+
+ ExtractMask extract_mask =
+ static_cast<ExtractMask>(EXTRACT_VALUE | EXTRACT_OPTIONS);
+ return WebFormElementToFormData(form_element,
+ element,
+ REQUIRE_NONE,
+ extract_mask,
+ form,
+ field);
+}
+
+// static
+void FormManager::FillForm(const FormData& form,
+ const WebInputElement& element) {
+ WebFormElement form_element = element.form();
+ if (form_element.isNull())
+ return;
+
+ ForEachMatchingFormField(form_element,
+ element,
+ form,
+ &FillFormField);
+}
+
+// static
+void FormManager::PreviewForm(const FormData& form,
+ const WebInputElement& element) {
+ WebFormElement form_element = element.form();
+ if (form_element.isNull())
+ return;
+
+ ForEachMatchingFormField(form_element,
+ element,
+ form,
+ &PreviewFormField);
+}
+
+// static
+bool FormManager::ClearPreviewedFormWithElement(const WebInputElement& element,
+ bool was_autofilled) {
+ WebFormElement form_element = element.form();
+ if (form_element.isNull())
+ return false;
+
+ std::vector<WebFormControlElement> control_elements;
+ ExtractAutofillableElements(form_element, &control_elements);
+ for (size_t i = 0; i < control_elements.size(); ++i) {
+ // Only text input elements can be previewed.
+ WebInputElement* input_element = toWebInputElement(&control_elements[i]);
+ if (!IsTextInput(input_element))
+ continue;
+
+ // If the input element is not auto-filled, we did not preview it, so there
+ // is nothing to reset.
+ if (!input_element->isAutofilled())
+ continue;
+
+ // There might be unrelated elements in this form which have already been
+ // auto-filled. For example, the user might have already filled the address
+ // part of a form and now be dealing with the credit card section. We only
+ // want to reset the auto-filled status for fields that were previewed.
+ if (input_element->suggestedValue().isEmpty())
+ continue;
+
+ // Clear the suggested value. For the initiating node, also restore the
+ // original value.
+ input_element->setSuggestedValue(WebString());
+ bool is_initiating_node = (element == *input_element);
+ if (is_initiating_node)
+ input_element->setAutofilled(was_autofilled);
+ else
+ input_element->setAutofilled(false);
+
+ // Clearing the suggested value in the focused node (above) can cause
+ // selection to be lost. We force selection range to restore the text
+ // cursor.
+ if (is_initiating_node) {
+ int length = input_element->value().length();
+ input_element->setSelectionRange(length, length);
+ }
+ }
+
+ return true;
+}
+
+// static
+bool FormManager::FormWithElementIsAutofilled(const WebInputElement& element) {
+ WebFormElement form_element = element.form();
+ if (form_element.isNull())
+ return false;
+
+ std::vector<WebFormControlElement> control_elements;
+ ExtractAutofillableElements(form_element, &control_elements);
+ for (size_t i = 0; i < control_elements.size(); ++i) {
+ WebInputElement* input_element = toWebInputElement(&control_elements[i]);
+ if (!IsTextInput(input_element))
+ continue;
+
+ if (input_element->isAutofilled())
+ return true;
+ }
+
+ return false;
+}
+
+void FormManager::ExtractForms(const WebFrame& frame,
std::vector<FormData>* forms) {
// Reset the vector of FormElements for this frame.
ResetFrame(frame);
+ web_frames_.insert(&frame);
WebVector<WebFormElement> web_forms;
- frame->document().forms(web_forms);
+ frame.document().forms(web_forms);
size_t num_fields_seen = 0;
for (size_t i = 0; i < web_forms.size(); ++i) {
- // Owned by |form_elements_|.
- FormElement* form_element = new FormElement;
- form_element->form_element = web_forms[i];
+ WebFormElement form_element = web_forms[i];
- WebVector<WebFormControlElement> control_elements;
- form_element->form_element.getFormControlElements(control_elements);
+ std::vector<WebFormControlElement> control_elements;
+ ExtractAutofillableElements(form_element, &control_elements);
for (size_t j = 0; j < control_elements.size(); ++j) {
WebFormControlElement element = control_elements[j];
- if (!IsAutofillableElement(element))
- continue;
-
- form_element->control_elements.push_back(element);
// Save original values of <select> elements so we can restore them
// when |ClearFormWithNode()| is invoked.
if (IsSelectElement(element)) {
- form_element->control_values.push_back(
- element.toConst<WebSelectElement>().value());
- } else {
- form_element->control_values.push_back(string16());
+ const WebSelectElement select_element =
+ element.toConst<WebSelectElement>();
+ initial_select_values_.insert(std::make_pair(select_element,
+ select_element.value()));
}
}
- form_elements_.push_back(form_element);
-
// To avoid overly expensive computation, we impose both a minimum and a
// maximum number of allowable fields.
- if (form_element->control_elements.size() < kRequiredAutofillFields ||
- form_element->control_elements.size() > kMaxParseableFields)
+ if (control_elements.size() < kRequiredAutofillFields ||
+ control_elements.size() > kMaxParseableFields)
continue;
FormData form;
- WebFormElementToFormData(
- form_element->form_element, REQUIRE_NONE, EXTRACT_VALUE, &form);
+ WebFormElementToFormData(form_element, WebFormControlElement(),
+ REQUIRE_NONE, EXTRACT_VALUE, &form, NULL);
num_fields_seen += form.fields.size();
if (num_fields_seen > kMaxParseableFields)
@@ -864,112 +969,36 @@ void FormManager::ExtractForms(const WebFrame* frame,
}
}
-bool FormManager::FindFormWithFormControlElement(
- const WebFormControlElement& element,
- FormData* form) {
- DCHECK(form);
-
- const WebFrame* frame = element.document().frame();
- if (!frame)
- return false;
-
- for (FormElementList::const_iterator iter = form_elements_.begin();
- iter != form_elements_.end(); ++iter) {
- const FormElement* form_element = *iter;
+void FormManager::ResetFrame(const WebFrame& frame) {
+ web_frames_.erase(&frame);
- if (form_element->form_element.document().frame() != frame)
- continue;
-
- for (std::vector<WebFormControlElement>::const_iterator iter =
- form_element->control_elements.begin();
- iter != form_element->control_elements.end(); ++iter) {
- if (iter->nameForAutofill() == element.nameForAutofill()) {
- ExtractMask extract_mask =
- static_cast<ExtractMask>(EXTRACT_VALUE | EXTRACT_OPTIONS);
- return WebFormElementToFormData(form_element->form_element,
- REQUIRE_NONE,
- extract_mask,
- form);
- }
- }
+ std::vector<WebSelectElement> to_delete;
+ for (std::map<const WebSelectElement, string16>::const_iterator it =
+ initial_select_values_.begin();
+ it != initial_select_values_.end(); ++it) {
+ WebFormElement form_element = it->first.form();
+ if (form_element.isNull() || form_element.document().frame() == &frame)
+ to_delete.push_back(it->first);
}
- return false;
-}
-
-void FormManager::FillForm(const FormData& form, const WebNode& node) {
- FormElement* form_element = NULL;
- if (!FindCachedFormElement(form, &form_element))
- return;
-
- ForEachMatchingFormField(&form_element->control_elements,
- node,
- form,
- &FillFormField);
-}
-
-void FormManager::PreviewForm(const FormData& form, const WebNode& node) {
- FormElement* form_element = NULL;
- if (!FindCachedFormElement(form, &form_element))
- return;
-
- ForEachMatchingFormField(&form_element->control_elements,
- node,
- form,
- &PreviewFormField);
-}
-
-bool FormManager::ShowPredictions(const FormDataPredictions& form) {
- FormElement* form_element = NULL;
- if (!FindCachedFormElement(form.data, &form_element))
- return false;
-
- DCHECK_EQ(form.data.fields.size(), form.fields.size());
- for (size_t i = 0, j = 0;
- i < form_element->control_elements.size() && j < form.fields.size();
- ++i) {
- WebFormControlElement* element = &form_element->control_elements[i];
- string16 element_name(element->nameForAutofill());
-
- // Search forward in the |form| for a corresponding field.
- size_t k = j;
- while (k < form.fields.size() && element_name != form.data.fields[k].name)
- k++;
-
- if (k >= form.fields.size())
- continue;
-
- DCHECK_EQ(form.data.fields[k].name, element_name);
-
- std::string placeholder = form.fields[k].overall_type;
- string16 title = l10n_util::GetStringFUTF16(
- IDS_AUTOFILL_SHOW_PREDICTIONS_TITLE,
- UTF8ToUTF16(form.fields[k].heuristic_type),
- UTF8ToUTF16(form.fields[k].server_type),
- UTF8ToUTF16(form.fields[k].signature),
- UTF8ToUTF16(form.signature),
- UTF8ToUTF16(form.experiment_id));
- if (!element->hasAttribute("placeholder"))
- element->setAttribute("placeholder", WebString(UTF8ToUTF16(placeholder)));
- element->setAttribute("title", WebString(title));
-
- // We found a matching form field so move on to the next.
- ++j;
+ for (std::vector<WebSelectElement>::const_iterator it =
+ to_delete.begin();
+ it != to_delete.end(); ++it) {
+ initial_select_values_.erase(*it);
}
-
- return true;
}
-bool FormManager::ClearFormWithNode(const WebNode& node) {
- FormElement* form_element = NULL;
- if (!FindCachedFormElementWithNode(node, &form_element))
+bool FormManager::ClearFormWithElement(const WebInputElement& element) {
+ WebFormElement form_element = element.form();
+ if (form_element.isNull())
return false;
- for (size_t i = 0; i < form_element->control_elements.size(); ++i) {
- WebFormControlElement element = form_element->control_elements[i];
- WebInputElement* input_element = toWebInputElement(&element);
+ std::vector<WebFormControlElement> control_elements;
+ ExtractAutofillableElements(form_element, &control_elements);
+ for (size_t i = 0; i < control_elements.size(); ++i) {
+ WebFormControlElement control_element = control_elements[i];
+ WebInputElement* input_element = toWebInputElement(&control_element);
if (IsTextInput(input_element)) {
-
// We don't modify the value of disabled fields.
if (!input_element->isEnabled())
continue;
@@ -979,15 +1008,19 @@ bool FormManager::ClearFormWithNode(const WebNode& node) {
// Clearing the value in the focused node (above) can cause selection
// to be lost. We force selection range to restore the text cursor.
- if (node == *input_element) {
+ if (element == *input_element) {
int length = input_element->value().length();
input_element->setSelectionRange(length, length);
}
} else {
- DCHECK(IsSelectElement(element));
- WebSelectElement select_element = element.to<WebSelectElement>();
- if (select_element.value() != form_element->control_values[i]) {
- select_element.setValue(form_element->control_values[i]);
+ DCHECK(IsSelectElement(control_element));
+ WebSelectElement select_element = control_element.to<WebSelectElement>();
+
+ std::map<const WebSelectElement, string16>::const_iterator
+ initial_value_iter = initial_select_values_.find(select_element);
+ if (initial_value_iter != initial_select_values_.end() &&
+ select_element.value() != initial_value_iter->second) {
+ select_element.setValue(initial_value_iter->second);
select_element.dispatchFormControlChangeEvent();
}
}
@@ -996,121 +1029,71 @@ bool FormManager::ClearFormWithNode(const WebNode& node) {
return true;
}
-bool FormManager::ClearPreviewedFormWithNode(const WebNode& node,
- bool was_autofilled) {
- FormElement* form_element = NULL;
- if (!FindCachedFormElementWithNode(node, &form_element))
- return false;
-
- for (size_t i = 0; i < form_element->control_elements.size(); ++i) {
- WebInputElement* input_element =
- toWebInputElement(&form_element->control_elements[i]);
- // Only text input elements can be previewed.
- if (!IsTextInput(input_element))
- continue;
-
- // If the input element has not been auto-filled, FormManager has not
- // previewed this field, so we have nothing to reset.
- if (!input_element->isAutofilled())
- continue;
-
- // There might be unrelated elements in this form which have already been
- // auto-filled. For example, the user might have already filled the address
- // part of a form and now be dealing with the credit card section. We only
- // want to reset the auto-filled status for fields that were previewed.
- if (input_element->suggestedValue().isEmpty())
- continue;
-
- // Clear the suggested value. For the initiating node, also restore the
- // original value.
- input_element->setSuggestedValue(WebString());
- bool is_initiating_node = (node == *input_element);
- if (is_initiating_node)
- input_element->setAutofilled(was_autofilled);
- else
- input_element->setAutofilled(false);
+bool FormManager::ShowPredictions(const FormDataPredictions& form) {
+ DCHECK_EQ(form.data.fields.size(), form.fields.size());
- // Clearing the suggested value in the focused node (above) can cause
- // selection to be lost. We force selection range to restore the text
- // cursor.
- if (is_initiating_node) {
- int length = input_element->value().length();
- input_element->setSelectionRange(length, length);
+ // Find the form.
+ bool found_form = false;
+ WebFormElement form_element;
+ for (std::set<const WebFrame*>::const_iterator it = web_frames_.begin();
+ it != web_frames_.end() && !found_form; ++it) {
+ WebVector<WebFormElement> web_forms;
+ (*it)->document().forms(web_forms);
+
+ for (size_t i = 0; i < web_forms.size(); ++i) {
+ form_element = web_forms[i];
+
+ // Note: matching on the form name here which is not guaranteed to be
+ // unique for the page, nor is it guaranteed to be non-empty. Ideally, we
+ // would have a way to uniquely identify the form cross-process. For now,
+ // we'll check form name and form action for identity.
+ // Also note that WebString() == WebString(string16()) does not evaluate
+ // to |true| -- WebKit distinguishes between a "null" string (lhs) and an
+ // "empty" string (rhs). We don't want that distinction, so forcing to
+ // string16.
+ string16 element_name = GetFormIdentifier(form_element);
+ GURL action(form_element.document().completeURL(form_element.action()));
+ if (element_name == form.data.name && action == form.data.action) {
+ found_form = true;
+ break;
+ }
}
}
- return true;
-}
-
-void FormManager::ResetFrame(const WebFrame* frame) {
- FormElementList::iterator iter = form_elements_.begin();
- while (iter != form_elements_.end()) {
- if ((*iter)->form_element.document().frame() == frame)
- iter = form_elements_.erase(iter);
- else
- ++iter;
- }
-}
-
-bool FormManager::FormWithNodeIsAutofilled(const WebNode& node) {
- FormElement* form_element = NULL;
- if (!FindCachedFormElementWithNode(node, &form_element))
+ if (!found_form)
return false;
- for (size_t i = 0; i < form_element->control_elements.size(); ++i) {
- WebInputElement* input_element =
- toWebInputElement(&form_element->control_elements[i]);
- if (!IsTextInput(input_element))
- continue;
-
- if (input_element->isAutofilled())
- return true;
+ std::vector<WebFormControlElement> control_elements;
+ ExtractAutofillableElements(form_element, &control_elements);
+ if (control_elements.size() != form.fields.size()) {
+ // Keep things simple. Don't show predictions for forms that were modified
+ // between page load and the server's response to our query.
+ return false;
}
- return false;
-}
+ for (size_t i = 0; i < control_elements.size(); ++i) {
+ WebFormControlElement* element = &control_elements[i];
-bool FormManager::FindCachedFormElementWithNode(const WebNode& node,
- FormElement** form_element) {
- for (FormElementList::const_iterator form_iter = form_elements_.begin();
- form_iter != form_elements_.end(); ++form_iter) {
- for (std::vector<WebFormControlElement>::const_iterator iter =
- (*form_iter)->control_elements.begin();
- iter != (*form_iter)->control_elements.end(); ++iter) {
- if (*iter == node) {
- *form_element = *form_iter;
- return true;
- }
+ if (string16(element->nameForAutofill()) != form.data.fields[i].name) {
+ // Keep things simple. Don't show predictions for elements whose names
+ // were modified between page load and the server's response to our query.
+ continue;
}
- }
-
- return false;
-}
-bool FormManager::FindCachedFormElement(const FormData& form,
- FormElement** form_element) {
- for (FormElementList::iterator form_iter = form_elements_.begin();
- form_iter != form_elements_.end(); ++form_iter) {
- // TODO(dhollowa): matching on form name here which is not guaranteed to
- // be unique for the page, nor is it guaranteed to be non-empty. Need to
- // find a way to uniquely identify the form cross-process. For now we'll
- // check form name and form action for identity.
- // http://crbug.com/37990 test file sample8.html.
- // Also note that WebString() == WebString(string16()) does not evaluate to
- // |true| -- WebKit distinguishes between a "null" string (lhs) and an
- // "empty" string (rhs). We don't want that distinction, so forcing to
- // string16.
- string16 element_name = GetFormIdentifier((*form_iter)->form_element);
- GURL action(
- (*form_iter)->form_element.document().completeURL(
- (*form_iter)->form_element.action()));
- if (element_name == form.name && action == form.action) {
- *form_element = *form_iter;
- return true;
- }
+ std::string placeholder = form.fields[i].overall_type;
+ string16 title = l10n_util::GetStringFUTF16(
+ IDS_AUTOFILL_SHOW_PREDICTIONS_TITLE,
+ UTF8ToUTF16(form.fields[i].heuristic_type),
+ UTF8ToUTF16(form.fields[i].server_type),
+ UTF8ToUTF16(form.fields[i].signature),
+ UTF8ToUTF16(form.signature),
+ UTF8ToUTF16(form.experiment_id));
+ if (!element->hasAttribute("placeholder"))
+ element->setAttribute("placeholder", WebString(UTF8ToUTF16(placeholder)));
+ element->setAttribute("title", WebString(title));
}
- return false;
+ return true;
}
} // namespace autofill
diff --git a/chrome/renderer/autofill/form_manager.h b/chrome/renderer/autofill/form_manager.h
index b32dcb5..cc8f570 100644
--- a/chrome/renderer/autofill/form_manager.h
+++ b/chrome/renderer/autofill/form_manager.h
@@ -7,6 +7,7 @@
#pragma once
#include <map>
+#include <set>
#include <vector>
#include "base/callback_old.h"
@@ -23,6 +24,8 @@ struct FormField;
namespace WebKit {
class WebFormControlElement;
class WebFrame;
+class WebInputElement;
+class WebSelectElement;
} // namespace WebKit
namespace autofill {
@@ -61,86 +64,75 @@ class FormManager {
ExtractMask extract_mask,
webkit_glue::FormField* field);
- // Returns the corresponding label for |element|. WARNING: This method can
- // potentially be very slow. Do not use during any code paths where the page
- // is loading.
- // TODO(isherman): Refactor autofill_agent.cc not to require this method to be
- // exposed.
- static string16 LabelForElement(const WebKit::WebFormControlElement& element);
-
- // Fills out a FormData object from a given WebFormElement. If |get_values|
- // is true, the fields in |form| will have the values filled out. If
- // |get_options| is true, the fields in |form will have select options filled
- // out. Returns true if |form| is filled out; it's possible that |element|
- // won't meet the requirements in |requirements|. This also returns false if
- // there are no fields in |form|.
- static bool WebFormElementToFormData(const WebKit::WebFormElement& element,
- RequirementsMask requirements,
- ExtractMask extract_mask,
- webkit_glue::FormData* form);
-
- // Scans the DOM in |frame| extracting and storing forms.
- // Returns a vector of the extracted forms.
- void ExtractForms(const WebKit::WebFrame* frame,
- std::vector<webkit_glue::FormData>* forms);
+ // Fills |form| with the FormData object corresponding to the |form_element|.
+ // If |field| is non-NULL, also fills |field| with the FormField object
+ // corresponding to the |form_control_element|.
+ // |extract_mask| controls what data is extracted.
+ // Returns true if |form| is filled out; it's possible that the |form_element|
+ // won't meet the |requirements|. Also returns false if there are no fields
+ // in the |form|.
+ static bool WebFormElementToFormData(
+ const WebKit::WebFormElement& form_element,
+ const WebKit::WebFormControlElement& form_control_element,
+ RequirementsMask requirements,
+ ExtractMask extract_mask,
+ webkit_glue::FormData* form,
+ webkit_glue::FormField* field);
- // Finds the form that contains |element| and returns it in |form|. Returns
- // false if the form is not found.
- bool FindFormWithFormControlElement(
+ // Finds the form that contains |element| and returns it in |form|. Fills
+ // |field| with the |FormField| representation for element.
+ // Returns false if the form is not found.
+ static bool FindFormAndFieldForFormControlElement(
const WebKit::WebFormControlElement& element,
- webkit_glue::FormData* form);
+ webkit_glue::FormData* form,
+ webkit_glue::FormField* field);
- // Fills the form represented by |form|. |node| is the input element that
+ // Fills the form represented by |form|. |element| is the input element that
// initiated the auto-fill process.
- void FillForm(const webkit_glue::FormData& form, const WebKit::WebNode& node);
-
- // Previews the form represented by |form|. |node| is the input element that
- // initiated the preview process.
- void PreviewForm(const webkit_glue::FormData& form,
- const WebKit::WebNode &node);
-
- // For each field in the |form|, sets the field's placeholder text to the
- // field's overall predicted type. Also sets the title to include the field's
- // heuristic type, server type, and signature; as well as the form's signature
- // and the experiment id for the server predictions.
- bool ShowPredictions(const webkit_glue::FormDataPredictions& form);
+ static void FillForm(const webkit_glue::FormData& form,
+ const WebKit::WebInputElement& element);
- // Clears the values of all input elements in the form that contains |node|.
- // Returns false if the form is not found.
- bool ClearFormWithNode(const WebKit::WebNode& node);
+ // Previews the form represented by |form|. |element| is the input element
+ // that initiated the preview process.
+ static void PreviewForm(const webkit_glue::FormData& form,
+ const WebKit::WebInputElement& element);
// Clears the placeholder values and the auto-filled background for any fields
// in the form containing |node| that have been previewed. Resets the
// autofilled state of |node| to |was_autofilled|. Returns false if the form
// is not found.
- bool ClearPreviewedFormWithNode(const WebKit::WebNode& node,
- bool was_autofilled);
-
- // Resets the forms for the specified |frame|.
- void ResetFrame(const WebKit::WebFrame* frame);
+ static bool ClearPreviewedFormWithElement(
+ const WebKit::WebInputElement& element,
+ bool was_autofilled);
// Returns true if |form| has any auto-filled fields.
- bool FormWithNodeIsAutofilled(const WebKit::WebNode& node);
+ static bool FormWithElementIsAutofilled(
+ const WebKit::WebInputElement& element);
- private:
- // Stores the WebFormElement and the form control elements for a form.
- // Original form values are stored so when we clear a form we can reset
- // <select> elements to their original value.
- struct FormElement;
+ // Scans the DOM in |frame| extracting and storing forms.
+ // Returns a vector of the extracted forms.
+ void ExtractForms(const WebKit::WebFrame& frame,
+ std::vector<webkit_glue::FormData>* forms);
- // Type for cache of FormElement objects.
- typedef ScopedVector<FormElement> FormElementList;
+ // Resets the forms for the specified |frame|.
+ void ResetFrame(const WebKit::WebFrame& frame);
- // Finds the cached FormElement that contains |node|.
- bool FindCachedFormElementWithNode(const WebKit::WebNode& node,
- FormElement** form_element);
+ // Clears the values of all input elements in the form that contains
+ // |element|. Returns false if the form is not found.
+ bool ClearFormWithElement(const WebKit::WebInputElement& element);
- // Uses the data in |form| to find the cached FormElement.
- bool FindCachedFormElement(const webkit_glue::FormData& form,
- FormElement** form_element);
+ // For each field in the |form|, sets the field's placeholder text to the
+ // field's overall predicted type. Also sets the title to include the field's
+ // heuristic type, server type, and signature; as well as the form's signature
+ // and the experiment id for the server predictions.
+ bool ShowPredictions(const webkit_glue::FormDataPredictions& form);
+
+ private:
+ // The cached web frames.
+ std::set<const WebKit::WebFrame*> web_frames_;
- // The cached FormElement objects.
- FormElementList form_elements_;
+ // The cached initial values for <select> elements.
+ std::map<const WebKit::WebSelectElement, string16> initial_select_values_;
DISALLOW_COPY_AND_ASSIGN(FormManager);
};
diff --git a/chrome/renderer/autofill/form_manager_browsertest.cc b/chrome/renderer/autofill/form_manager_browsertest.cc
index c28d548..fefcef0 100644
--- a/chrome/renderer/autofill/form_manager_browsertest.cc
+++ b/chrome/renderer/autofill/form_manager_browsertest.cc
@@ -69,7 +69,7 @@ class FormManagerTest : public RenderViewTest {
FormManager form_manager;
std::vector<FormData> forms;
- form_manager.ExtractForms(web_frame, &forms);
+ form_manager.ExtractForms(*web_frame, &forms);
ASSERT_EQ(1U, forms.size());
const FormData& form = forms[0];
@@ -463,14 +463,19 @@ TEST_F(FormManagerTest, WebFormControlElementToFormFieldAutocompletetype) {
TEST_F(FormManagerTest, WebFormElementToFormData) {
LoadHTML("<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ " <LABEL for=\"firstname\">First name:</LABEL>"
" <INPUT type=\"text\" id=\"firstname\" value=\"John\"/>"
+ " <LABEL for=\"lastname\">Last name:</LABEL>"
" <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " <LABEL for=\"state\">State:</LABEL>"
" <SELECT id=\"state\"/>"
" <OPTION value=\"CA\">California</OPTION>"
" <OPTION value=\"TX\">Texas</OPTION>"
" </SELECT>"
// The below inputs should be ignored
+ " <LABEL for=\"notvisible\">Hidden:</LABEL>"
" <INPUT type=\"hidden\" id=\"notvisible\" value=\"apple\"/>"
+ " <LABEL for=\"password\">Password:</LABEL>"
" <INPUT type=\"password\" id=\"password\" value=\"secret\"/>"
" <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
"</FORM>");
@@ -482,11 +487,17 @@ TEST_F(FormManagerTest, WebFormElementToFormData) {
frame->document().forms(forms);
ASSERT_EQ(1U, forms.size());
+ WebElement element = frame->document().getElementById("firstname");
+ WebInputElement input_element = element.to<WebInputElement>();
+
FormData form;
+ FormField field;
EXPECT_TRUE(FormManager::WebFormElementToFormData(forms[0],
+ input_element,
FormManager::REQUIRE_NONE,
FormManager::EXTRACT_VALUE,
- &form));
+ &form,
+ &field));
EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
EXPECT_EQ(GURL(frame->document().url()), form.origin);
EXPECT_EQ(GURL("http://cnn.com"), form.action);
@@ -497,18 +508,21 @@ TEST_F(FormManagerTest, WebFormElementToFormData) {
FormField expected;
expected.name = ASCIIToUTF16("firstname");
expected.value = ASCIIToUTF16("John");
+ expected.label = ASCIIToUTF16("First name:");
expected.form_control_type = ASCIIToUTF16("text");
expected.max_length = WebInputElement::defaultMaxLength();
EXPECT_FORM_FIELD_EQUALS(expected, fields[0]);
expected.name = ASCIIToUTF16("lastname");
expected.value = ASCIIToUTF16("Smith");
+ expected.label = ASCIIToUTF16("Last name:");
expected.form_control_type = ASCIIToUTF16("text");
expected.max_length = WebInputElement::defaultMaxLength();
EXPECT_FORM_FIELD_EQUALS(expected, fields[1]);
expected.name = ASCIIToUTF16("state");
expected.value = ASCIIToUTF16("CA");
+ expected.label = ASCIIToUTF16("State:");
expected.form_control_type = ASCIIToUTF16("select-one");
expected.max_length = 0;
EXPECT_FORM_FIELD_EQUALS(expected, fields[2]);
@@ -543,7 +557,7 @@ TEST_F(FormManagerTest, ExtractMultipleForms) {
FormManager form_manager;
std::vector<FormData> forms;
- form_manager.ExtractForms(web_frame, &forms);
+ form_manager.ExtractForms(*web_frame, &forms);
ASSERT_EQ(2U, forms.size());
// First form.
@@ -606,7 +620,7 @@ TEST_F(FormManagerTest, ExtractFormsTooFewFields) {
FormManager form_manager;
std::vector<FormData> forms;
- form_manager.ExtractForms(web_frame, &forms);
+ form_manager.ExtractForms(*web_frame, &forms);
EXPECT_EQ(0U, forms.size());
}
@@ -631,10 +645,11 @@ TEST_F(FormManagerTest, WebFormElementToFormDataAutocomplete) {
FormData form;
EXPECT_TRUE(FormManager::WebFormElementToFormData(
- web_form, FormManager::REQUIRE_NONE, FormManager::EXTRACT_NONE, &form));
+ web_form, WebFormControlElement(), FormManager::REQUIRE_NONE,
+ FormManager::EXTRACT_NONE, &form, NULL));
EXPECT_FALSE(FormManager::WebFormElementToFormData(
- web_form, FormManager::REQUIRE_AUTOCOMPLETE, FormManager::EXTRACT_NONE,
- &form));
+ web_form, WebFormControlElement(), FormManager::REQUIRE_AUTOCOMPLETE,
+ FormManager::EXTRACT_NONE, &form, NULL));
}
{
@@ -659,8 +674,8 @@ TEST_F(FormManagerTest, WebFormElementToFormDataAutocomplete) {
FormData form;
EXPECT_TRUE(FormManager::WebFormElementToFormData(
- web_form, FormManager::REQUIRE_AUTOCOMPLETE, FormManager::EXTRACT_VALUE,
- &form));
+ web_form, WebFormControlElement(), FormManager::REQUIRE_AUTOCOMPLETE,
+ FormManager::EXTRACT_VALUE, &form, NULL));
EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
@@ -707,8 +722,8 @@ TEST_F(FormManagerTest, WebFormElementToFormDataEnabled) {
FormData form;
EXPECT_TRUE(FormManager::WebFormElementToFormData(
- web_form, FormManager::REQUIRE_ENABLED, FormManager::EXTRACT_VALUE,
- &form));
+ web_form, WebFormControlElement(), FormManager::REQUIRE_ENABLED,
+ FormManager::EXTRACT_VALUE, &form, NULL));
EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
@@ -747,7 +762,7 @@ TEST_F(FormManagerTest, FindForm) {
FormManager form_manager;
std::vector<FormData> forms;
- form_manager.ExtractForms(web_frame, &forms);
+ form_manager.ExtractForms(*web_frame, &forms);
ASSERT_EQ(1U, forms.size());
// Get the input element we want to find.
@@ -756,8 +771,10 @@ TEST_F(FormManagerTest, FindForm) {
// Find the form and verify it's the correct form.
FormData form;
- EXPECT_TRUE(form_manager.FindFormWithFormControlElement(input_element,
- &form));
+ FormField field;
+ EXPECT_TRUE(FormManager::FindFormAndFieldForFormControlElement(input_element,
+ &form,
+ &field));
EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
EXPECT_EQ(GURL("http://buh.com"), form.action);
@@ -772,6 +789,7 @@ TEST_F(FormManagerTest, FindForm) {
expected.name = ASCIIToUTF16("firstname");
expected.value = ASCIIToUTF16("John");
EXPECT_FORM_FIELD_EQUALS(expected, fields[0]);
+ EXPECT_FORM_FIELD_EQUALS(expected, field);
expected.name = ASCIIToUTF16("lastname");
expected.value = ASCIIToUTF16("Smith");
@@ -802,7 +820,7 @@ TEST_F(FormManagerTest, FillForm) {
FormManager form_manager;
std::vector<FormData> forms;
- form_manager.ExtractForms(web_frame, &forms);
+ form_manager.ExtractForms(*web_frame, &forms);
ASSERT_EQ(1U, forms.size());
// Get the input element we want to find.
@@ -811,8 +829,10 @@ TEST_F(FormManagerTest, FillForm) {
// Find the form that contains the input element.
FormData form;
- EXPECT_TRUE(form_manager.FindFormWithFormControlElement(input_element,
- &form));
+ FormField field;
+ EXPECT_TRUE(FormManager::FindFormAndFieldForFormControlElement(input_element,
+ &form,
+ &field));
EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
EXPECT_EQ(GURL("http://buh.com"), form.action);
@@ -933,7 +953,7 @@ TEST_F(FormManagerTest, FAILS_PreviewForm) {
FormManager form_manager;
std::vector<FormData> forms;
- form_manager.ExtractForms(web_frame, &forms);
+ form_manager.ExtractForms(*web_frame, &forms);
ASSERT_EQ(1U, forms.size());
// Get the input element we want to find.
@@ -942,8 +962,10 @@ TEST_F(FormManagerTest, FAILS_PreviewForm) {
// Find the form that contains the input element.
FormData form;
- EXPECT_TRUE(form_manager.FindFormWithFormControlElement(input_element,
- &form));
+ FormField field;
+ EXPECT_TRUE(FormManager::FindFormAndFieldForFormControlElement(input_element,
+ &form,
+ &field));
EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
EXPECT_EQ(GURL("http://buh.com"), form.action);
@@ -1888,7 +1910,7 @@ TEST_F(FormManagerTest, FillFormMaxLength) {
FormManager form_manager;
std::vector<FormData> forms;
- form_manager.ExtractForms(web_frame, &forms);
+ form_manager.ExtractForms(*web_frame, &forms);
ASSERT_EQ(1U, forms.size());
// Get the input element we want to find.
@@ -1897,8 +1919,10 @@ TEST_F(FormManagerTest, FillFormMaxLength) {
// Find the form that contains the input element.
FormData form;
- EXPECT_TRUE(form_manager.FindFormWithFormControlElement(input_element,
- &form));
+ FormField field;
+ EXPECT_TRUE(FormManager::FindFormAndFieldForFormControlElement(input_element,
+ &form,
+ &field));
EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
EXPECT_EQ(GURL("http://buh.com"), form.action);
@@ -1928,12 +1952,15 @@ TEST_F(FormManagerTest, FillFormMaxLength) {
form.fields[0].value = ASCIIToUTF16("Brother");
form.fields[1].value = ASCIIToUTF16("Jonathan");
form.fields[2].value = ASCIIToUTF16("brotherj@example.com");
- form_manager.FillForm(form, WebNode());
+ form_manager.FillForm(form, input_element);
// Find the newly-filled form that contains the input element.
FormData form2;
- EXPECT_TRUE(form_manager.FindFormWithFormControlElement(input_element,
- &form2));
+ FormField field2;
+ EXPECT_TRUE(FormManager::FindFormAndFieldForFormControlElement(input_element,
+ &form2,
+ &field2));
+
EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name);
EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
EXPECT_EQ(GURL("http://buh.com"), form2.action);
@@ -1978,7 +2005,7 @@ TEST_F(FormManagerTest, FillFormNegativeMaxLength) {
FormManager form_manager;
std::vector<FormData> forms;
- form_manager.ExtractForms(web_frame, &forms);
+ form_manager.ExtractForms(*web_frame, &forms);
ASSERT_EQ(1U, forms.size());
// Get the input element we want to find.
@@ -1987,8 +2014,10 @@ TEST_F(FormManagerTest, FillFormNegativeMaxLength) {
// Find the form that contains the input element.
FormData form;
- EXPECT_TRUE(form_manager.FindFormWithFormControlElement(input_element,
- &form));
+ FormField field;
+ EXPECT_TRUE(FormManager::FindFormAndFieldForFormControlElement(input_element,
+ &form,
+ &field));
EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
EXPECT_EQ(GURL("http://buh.com"), form.action);
@@ -2013,12 +2042,15 @@ TEST_F(FormManagerTest, FillFormNegativeMaxLength) {
form.fields[0].value = ASCIIToUTF16("Brother");
form.fields[1].value = ASCIIToUTF16("Jonathan");
form.fields[2].value = ASCIIToUTF16("brotherj@example.com");
- form_manager.FillForm(form, WebNode());
+ form_manager.FillForm(form, input_element);
// Find the newly-filled form that contains the input element.
FormData form2;
- EXPECT_TRUE(form_manager.FindFormWithFormControlElement(input_element,
- &form2));
+ FormField field2;
+ EXPECT_TRUE(FormManager::FindFormAndFieldForFormControlElement(input_element,
+ &form2,
+ &field2));
+
EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name);
EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
EXPECT_EQ(GURL("http://buh.com"), form2.action);
@@ -2039,340 +2071,6 @@ TEST_F(FormManagerTest, FillFormNegativeMaxLength) {
EXPECT_FORM_FIELD_EQUALS(expected, fields[2]);
}
-// This test sends a FormData object to FillForm with more fields than are in
-// the cached WebFormElement. In this case, we only fill out the fields that
-// match between the FormData object and the WebFormElement.
-TEST_F(FormManagerTest, FillFormMoreFormDataFields) {
- LoadHTML("<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">"
- " <INPUT type=\"text\" id=\"firstname\"/>"
- " <INPUT type=\"text\" id=\"middlename\"/>"
- " <INPUT type=\"text\" id=\"lastname\"/>"
- " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
- "</FORM>");
-
- WebFrame* web_frame = GetMainFrame();
- ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
-
- FormManager form_manager;
- std::vector<FormData> forms;
- form_manager.ExtractForms(web_frame, &forms);
- ASSERT_EQ(1U, forms.size());
-
- // After the field modification, the fields in |form| will look like:
- // prefix
- // firstname
- // hidden
- // middlename
- // second
- // lastname
- // postfix
- FormData* form = &forms[0];
-
- FormField field1;
- field1.name = ASCIIToUTF16("prefix");
- field1.form_control_type = ASCIIToUTF16("text");
- field1.max_length = WebInputElement::defaultMaxLength();
- form->fields.insert(form->fields.begin(), field1);
-
- FormField field2;
- field2.name = ASCIIToUTF16("hidden");
- field2.form_control_type = ASCIIToUTF16("text");
- field2.max_length = WebInputElement::defaultMaxLength();
- form->fields.insert(form->fields.begin() + 2, field2);
-
- FormField field3;
- field3.name = ASCIIToUTF16("second");
- field3.form_control_type = ASCIIToUTF16("text");
- field3.max_length = WebInputElement::defaultMaxLength();
- form->fields.insert(form->fields.begin() + 4, field3);
-
- FormField field4;
- field4.name = ASCIIToUTF16("postfix");
- field4.form_control_type = ASCIIToUTF16("text");
- field4.max_length = WebInputElement::defaultMaxLength();
- form->fields.insert(form->fields.begin() + 6, field4);
-
- // Fill the form.
- form->fields[0].value = ASCIIToUTF16("Alpha");
- form->fields[1].value = ASCIIToUTF16("Brother");
- form->fields[2].value = ASCIIToUTF16("Abracadabra");
- form->fields[3].value = ASCIIToUTF16("Joseph");
- form->fields[4].value = ASCIIToUTF16("Beta");
- form->fields[5].value = ASCIIToUTF16("Jonathan");
- form->fields[6].value = ASCIIToUTF16("Omega");
- form_manager.FillForm(*form, WebNode());
-
- // Get the input element we want to find.
- WebElement element = web_frame->document().getElementById("firstname");
- WebInputElement input_element = element.to<WebInputElement>();
-
- // Find the newly-filled form that contains the input element.
- FormData form2;
- EXPECT_TRUE(form_manager.FindFormWithFormControlElement(input_element,
- &form2));
- EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name);
- EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
- EXPECT_EQ(GURL("http://buh.com"), form2.action);
-
- const std::vector<FormField>& fields = form2.fields;
- ASSERT_EQ(3U, fields.size());
-
- FormField expected;
- expected.form_control_type = ASCIIToUTF16("text");
- expected.max_length = WebInputElement::defaultMaxLength();
- expected.is_autofilled = true;
-
- expected.name = ASCIIToUTF16("firstname");
- expected.value = ASCIIToUTF16("Brother");
- EXPECT_FORM_FIELD_EQUALS(expected, fields[0]);
-
- expected.name = ASCIIToUTF16("middlename");
- expected.value = ASCIIToUTF16("Joseph");
- EXPECT_FORM_FIELD_EQUALS(expected, fields[1]);
-
- expected.name = ASCIIToUTF16("lastname");
- expected.value = ASCIIToUTF16("Jonathan");
- EXPECT_FORM_FIELD_EQUALS(expected, fields[2]);
-}
-
-// This test sends a FormData object to FillForm with fewer fields than are in
-// the cached WebFormElement. In this case, we only fill out the fields that
-// match between the FormData object and the WebFormElement.
-TEST_F(FormManagerTest, FillFormFewerFormDataFields) {
- LoadHTML("<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">"
- " <INPUT type=\"text\" id=\"prefix\"/>"
- " <INPUT type=\"text\" id=\"firstname\"/>"
- " <INPUT type=\"text\" id=\"hidden\"/>"
- " <INPUT type=\"text\" id=\"middlename\"/>"
- " <INPUT type=\"text\" id=\"second\"/>"
- " <INPUT type=\"text\" id=\"lastname\"/>"
- " <INPUT type=\"text\" id=\"postfix\"/>"
- " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
- "</FORM>");
-
- WebFrame* web_frame = GetMainFrame();
- ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
-
- FormManager form_manager;
- std::vector<FormData> forms;
- form_manager.ExtractForms(web_frame, &forms);
- ASSERT_EQ(1U, forms.size());
-
- // After the field modification, the fields in |form| will look like:
- // firstname
- // middlename
- // lastname
- FormData* form = &forms[0];
- form->fields.erase(form->fields.begin());
- form->fields.erase(form->fields.begin() + 1);
- form->fields.erase(form->fields.begin() + 2);
- form->fields.erase(form->fields.begin() + 3);
-
- // Fill the form.
- form->fields[0].value = ASCIIToUTF16("Brother");
- form->fields[1].value = ASCIIToUTF16("Joseph");
- form->fields[2].value = ASCIIToUTF16("Jonathan");
- form_manager.FillForm(*form, WebNode());
-
- // Get the input element we want to find.
- WebElement element = web_frame->document().getElementById("firstname");
- WebInputElement input_element = element.to<WebInputElement>();
-
- // Find the newly-filled form that contains the input element.
- FormData form2;
- EXPECT_TRUE(form_manager.FindFormWithFormControlElement(input_element,
- &form2));
- EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name);
- EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
- EXPECT_EQ(GURL("http://buh.com"), form2.action);
-
- const std::vector<FormField>& fields = form2.fields;
- ASSERT_EQ(7U, fields.size());
-
- FormField expected;
- expected.form_control_type = ASCIIToUTF16("text");
- expected.max_length = WebInputElement::defaultMaxLength();
-
- expected.name = ASCIIToUTF16("prefix");
- expected.value = string16();
- expected.is_autofilled = false;
- EXPECT_FORM_FIELD_EQUALS(expected, fields[0]);
-
- expected.name = ASCIIToUTF16("firstname");
- expected.value = ASCIIToUTF16("Brother");
- expected.is_autofilled = true;
- EXPECT_FORM_FIELD_EQUALS(expected, fields[1]);
-
- expected.name = ASCIIToUTF16("hidden");
- expected.value = string16();
- expected.is_autofilled = false;
- EXPECT_FORM_FIELD_EQUALS(expected, fields[2]);
-
- expected.name = ASCIIToUTF16("middlename");
- expected.value = ASCIIToUTF16("Joseph");
- expected.is_autofilled = true;
- EXPECT_FORM_FIELD_EQUALS(expected, fields[3]);
-
- expected.name = ASCIIToUTF16("second");
- expected.value = string16();
- expected.is_autofilled = false;
- EXPECT_FORM_FIELD_EQUALS(expected, fields[4]);
-
- expected.name = ASCIIToUTF16("lastname");
- expected.value = ASCIIToUTF16("Jonathan");
- expected.is_autofilled = true;
- EXPECT_FORM_FIELD_EQUALS(expected, fields[5]);
-
- expected.name = ASCIIToUTF16("postfix");
- expected.value = string16();
- expected.is_autofilled = false;
- EXPECT_FORM_FIELD_EQUALS(expected, fields[6]);
-}
-
-// This test sends a FormData object to FillForm with a field changed from
-// those in the cached WebFormElement. In this case, we only fill out the
-// fields that match between the FormData object and the WebFormElement.
-TEST_F(FormManagerTest, FillFormChangedFormDataFields) {
- LoadHTML("<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">"
- " <INPUT type=\"text\" id=\"firstname\"/>"
- " <INPUT type=\"text\" id=\"middlename\"/>"
- " <INPUT type=\"text\" id=\"lastname\"/>"
- " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
- "</FORM>");
-
- WebFrame* web_frame = GetMainFrame();
- ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
-
- FormManager form_manager;
- std::vector<FormData> forms;
- form_manager.ExtractForms(web_frame, &forms);
- ASSERT_EQ(1U, forms.size());
-
- // After the field modification, the fields in |form| will look like:
- // firstname
- // middlename
- // lastname
- FormData* form = &forms[0];
-
- // Fill the form.
- form->fields[0].value = ASCIIToUTF16("Brother");
- form->fields[1].value = ASCIIToUTF16("Joseph");
- form->fields[2].value = ASCIIToUTF16("Jonathan");
-
- // Alter the label and name used for matching.
- form->fields[1].label = ASCIIToUTF16("bogus");
- form->fields[1].name = ASCIIToUTF16("bogus");
-
- form_manager.FillForm(*form, WebNode());
-
- // Get the input element we want to find.
- WebElement element = web_frame->document().getElementById("firstname");
- WebInputElement input_element = element.to<WebInputElement>();
-
- // Find the newly-filled form that contains the input element.
- FormData form2;
- EXPECT_TRUE(form_manager.FindFormWithFormControlElement(input_element,
- &form2));
- EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name);
- EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
- EXPECT_EQ(GURL("http://buh.com"), form2.action);
-
- const std::vector<FormField>& fields = form2.fields;
- ASSERT_EQ(3U, fields.size());
-
- FormField expected;
- expected.form_control_type = ASCIIToUTF16("text");
- expected.max_length = WebInputElement::defaultMaxLength();
-
- expected.name = ASCIIToUTF16("firstname");
- expected.value = ASCIIToUTF16("Brother");
- expected.is_autofilled = true;
- EXPECT_FORM_FIELD_EQUALS(expected, fields[0]);
-
- expected.name = ASCIIToUTF16("middlename");
- expected.value = ASCIIToUTF16("");
- expected.is_autofilled = false;
- EXPECT_FORM_FIELD_EQUALS(expected, fields[1]);
-
- expected.name = ASCIIToUTF16("lastname");
- expected.value = ASCIIToUTF16("Jonathan");
- expected.is_autofilled = true;
- EXPECT_FORM_FIELD_EQUALS(expected, fields[2]);
-}
-
-// This test sends a FormData object to FillForm with fewer fields than are in
-// the cached WebFormElement. In this case, we only fill out the fields that
-// match between the FormData object and the WebFormElement.
-TEST_F(FormManagerTest, FillFormExtraFieldInCache) {
- LoadHTML("<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">"
- " <INPUT type=\"text\" id=\"firstname\"/>"
- " <INPUT type=\"text\" id=\"middlename\"/>"
- " <INPUT type=\"text\" id=\"lastname\"/>"
- " <INPUT type=\"text\" id=\"postfix\"/>"
- " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
- "</FORM>");
-
- WebFrame* web_frame = GetMainFrame();
- ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
-
- FormManager form_manager;
- std::vector<FormData> forms;
- form_manager.ExtractForms(web_frame, &forms);
- ASSERT_EQ(1U, forms.size());
-
- // After the field modification, the fields in |form| will look like:
- // firstname
- // middlename
- // lastname
- FormData* form = &forms[0];
- form->fields.pop_back();
-
- // Fill the form.
- form->fields[0].value = ASCIIToUTF16("Brother");
- form->fields[1].value = ASCIIToUTF16("Joseph");
- form->fields[2].value = ASCIIToUTF16("Jonathan");
- form_manager.FillForm(*form, WebNode());
-
- // Get the input element we want to find.
- WebElement element = web_frame->document().getElementById("firstname");
- WebInputElement input_element = element.to<WebInputElement>();
-
- // Find the newly-filled form that contains the input element.
- FormData form2;
- EXPECT_TRUE(form_manager.FindFormWithFormControlElement(input_element,
- &form2));
- EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name);
- EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
- EXPECT_EQ(GURL("http://buh.com"), form2.action);
-
- const std::vector<FormField>& fields = form2.fields;
- ASSERT_EQ(4U, fields.size());
-
- FormField expected;
- expected.form_control_type = ASCIIToUTF16("text");
- expected.max_length = WebInputElement::defaultMaxLength();
-
- expected.name = ASCIIToUTF16("firstname");
- expected.value = ASCIIToUTF16("Brother");
- expected.is_autofilled = true;
- EXPECT_FORM_FIELD_EQUALS(expected, fields[0]);
-
- expected.name = ASCIIToUTF16("middlename");
- expected.value = ASCIIToUTF16("Joseph");
- expected.is_autofilled = true;
- EXPECT_FORM_FIELD_EQUALS(expected, fields[1]);
-
- expected.name = ASCIIToUTF16("lastname");
- expected.value = ASCIIToUTF16("Jonathan");
- expected.is_autofilled = true;
- EXPECT_FORM_FIELD_EQUALS(expected, fields[2]);
-
- expected.name = ASCIIToUTF16("postfix");
- expected.value = string16();
- expected.is_autofilled = false;
- EXPECT_FORM_FIELD_EQUALS(expected, fields[3]);
-}
-
TEST_F(FormManagerTest, FillFormEmptyName) {
LoadHTML("<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">"
" <INPUT type=\"text\" id=\"firstname\"/>"
@@ -2386,7 +2084,7 @@ TEST_F(FormManagerTest, FillFormEmptyName) {
FormManager form_manager;
std::vector<FormData> forms;
- form_manager.ExtractForms(web_frame, &forms);
+ form_manager.ExtractForms(*web_frame, &forms);
ASSERT_EQ(1U, forms.size());
// Get the input element we want to find.
@@ -2395,8 +2093,10 @@ TEST_F(FormManagerTest, FillFormEmptyName) {
// Find the form that contains the input element.
FormData form;
- EXPECT_TRUE(form_manager.FindFormWithFormControlElement(input_element,
- &form));
+ FormField field;
+ EXPECT_TRUE(FormManager::FindFormAndFieldForFormControlElement(input_element,
+ &form,
+ &field));
EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
EXPECT_EQ(GURL("http://buh.com"), form.action);
@@ -2421,12 +2121,15 @@ TEST_F(FormManagerTest, FillFormEmptyName) {
form.fields[0].value = ASCIIToUTF16("Wyatt");
form.fields[1].value = ASCIIToUTF16("Earp");
form.fields[2].value = ASCIIToUTF16("wyatt@example.com");
- form_manager.FillForm(form, WebNode());
+ form_manager.FillForm(form, input_element);
// Find the newly-filled form that contains the input element.
FormData form2;
- EXPECT_TRUE(form_manager.FindFormWithFormControlElement(input_element,
- &form2));
+ FormField field2;
+ EXPECT_TRUE(FormManager::FindFormAndFieldForFormControlElement(input_element,
+ &form2,
+ &field2));
+
EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name);
EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
EXPECT_EQ(GURL("http://buh.com"), form2.action);
@@ -2469,7 +2172,7 @@ TEST_F(FormManagerTest, FillFormEmptyFormNames) {
FormManager form_manager;
std::vector<FormData> forms;
- form_manager.ExtractForms(web_frame, &forms);
+ form_manager.ExtractForms(*web_frame, &forms);
ASSERT_EQ(2U, forms.size());
// Get the input element we want to find.
@@ -2478,8 +2181,10 @@ TEST_F(FormManagerTest, FillFormEmptyFormNames) {
// Find the form that contains the input element.
FormData form;
- EXPECT_TRUE(form_manager.FindFormWithFormControlElement(input_element,
- &form));
+ FormField field;
+ EXPECT_TRUE(FormManager::FindFormAndFieldForFormControlElement(input_element,
+ &form,
+ &field));
EXPECT_EQ(string16(), form.name);
EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
EXPECT_EQ(GURL("http://abc.com"), form.action);
@@ -2507,12 +2212,15 @@ TEST_F(FormManagerTest, FillFormEmptyFormNames) {
form.fields[0].value = ASCIIToUTF16("Red");
form.fields[1].value = ASCIIToUTF16("Yellow");
form.fields[2].value = ASCIIToUTF16("Also Yellow");
- form_manager.FillForm(form, WebNode());
+ form_manager.FillForm(form, input_element);
// Find the newly-filled form that contains the input element.
FormData form2;
- EXPECT_TRUE(form_manager.FindFormWithFormControlElement(input_element,
- &form2));
+ FormField field2;
+ EXPECT_TRUE(FormManager::FindFormAndFieldForFormControlElement(input_element,
+ &form2,
+ &field2));
+
EXPECT_EQ(string16(), form2.name);
EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
EXPECT_EQ(GURL("http://abc.com"), form2.action);
@@ -2559,9 +2267,11 @@ TEST_F(FormManagerTest, ThreePartPhone) {
FormData form;
EXPECT_TRUE(FormManager::WebFormElementToFormData(forms[0],
+ WebFormControlElement(),
FormManager::REQUIRE_NONE,
FormManager::EXTRACT_VALUE,
- &form));
+ &form,
+ NULL));
EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
EXPECT_EQ(GURL(frame->document().url()), form.origin);
EXPECT_EQ(GURL("http://cnn.com"), form.action);
@@ -2616,9 +2326,11 @@ TEST_F(FormManagerTest, MaxLengthFields) {
FormData form;
EXPECT_TRUE(FormManager::WebFormElementToFormData(forms[0],
+ WebFormControlElement(),
FormManager::REQUIRE_NONE,
FormManager::EXTRACT_VALUE,
- &form));
+ &form,
+ NULL));
EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
EXPECT_EQ(GURL(frame->document().url()), form.origin);
EXPECT_EQ(GURL("http://cnn.com"), form.action);
@@ -2678,7 +2390,7 @@ TEST_F(FormManagerTest, FAILS_FillFormNonEmptyField) {
FormManager form_manager;
std::vector<FormData> forms;
- form_manager.ExtractForms(web_frame, &forms);
+ form_manager.ExtractForms(*web_frame, &forms);
ASSERT_EQ(1U, forms.size());
// Get the input element we want to find.
@@ -2690,8 +2402,10 @@ TEST_F(FormManagerTest, FAILS_FillFormNonEmptyField) {
// Find the form that contains the input element.
FormData form;
- EXPECT_TRUE(form_manager.FindFormWithFormControlElement(input_element,
- &form));
+ FormField field;
+ EXPECT_TRUE(FormManager::FindFormAndFieldForFormControlElement(input_element,
+ &form,
+ &field));
EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
EXPECT_EQ(GURL("http://buh.com"), form.action);
@@ -2731,8 +2445,11 @@ TEST_F(FormManagerTest, FAILS_FillFormNonEmptyField) {
// Find the newly-filled form that contains the input element.
FormData form2;
- EXPECT_TRUE(form_manager.FindFormWithFormControlElement(input_element,
- &form2));
+ FormField field2;
+ EXPECT_TRUE(FormManager::FindFormAndFieldForFormControlElement(input_element,
+ &form2,
+ &field2));
+
EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name);
EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
EXPECT_EQ(GURL("http://buh.com"), form2.action);
@@ -2775,7 +2492,7 @@ TEST_F(FormManagerTest, ClearFormWithNode) {
FormManager form_manager;
std::vector<FormData> forms;
- form_manager.ExtractForms(web_frame, &forms);
+ form_manager.ExtractForms(*web_frame, &forms);
ASSERT_EQ(1U, forms.size());
// Set the auto-filled attribute on the firstname element.
@@ -2789,14 +2506,17 @@ TEST_F(FormManagerTest, ClearFormWithNode) {
notenabled.setValue(WebString::fromUTF8("no clear"));
// Clear the form.
- EXPECT_TRUE(form_manager.ClearFormWithNode(firstname));
+ EXPECT_TRUE(form_manager.ClearFormWithElement(firstname));
// Verify that the auto-filled attribute has been turned off.
EXPECT_FALSE(firstname.isAutofilled());
// Verify the form is cleared.
FormData form2;
- EXPECT_TRUE(form_manager.FindFormWithFormControlElement(firstname, &form2));
+ FormField field2;
+ EXPECT_TRUE(FormManager::FindFormAndFieldForFormControlElement(firstname,
+ &form2,
+ &field2));
EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name);
EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
EXPECT_EQ(GURL("http://buh.com"), form2.action);
@@ -2848,7 +2568,7 @@ TEST_F(FormManagerTest, ClearFormWithNodeContainingSelectOne) {
FormManager form_manager;
std::vector<FormData> forms;
- form_manager.ExtractForms(web_frame, &forms);
+ form_manager.ExtractForms(*web_frame, &forms);
ASSERT_EQ(1U, forms.size());
// Set the auto-filled attribute on the firstname element.
@@ -2862,14 +2582,17 @@ TEST_F(FormManagerTest, ClearFormWithNodeContainingSelectOne) {
select_element.setValue(WebString::fromUTF8("AK"));
// Clear the form.
- EXPECT_TRUE(form_manager.ClearFormWithNode(firstname));
+ EXPECT_TRUE(form_manager.ClearFormWithElement(firstname));
// Verify that the auto-filled attribute has been turned off.
EXPECT_FALSE(firstname.isAutofilled());
// Verify the form is cleared.
FormData form2;
- EXPECT_TRUE(form_manager.FindFormWithFormControlElement(firstname, &form2));
+ FormField field2;
+ EXPECT_TRUE(FormManager::FindFormAndFieldForFormControlElement(firstname,
+ &form2,
+ &field2));
EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name);
EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
EXPECT_EQ(GURL("http://buh.com"), form2.action);
@@ -2902,7 +2625,7 @@ TEST_F(FormManagerTest, ClearFormWithNodeContainingSelectOne) {
EXPECT_EQ(0, firstname.selectionEnd());
}
-TEST_F(FormManagerTest, ClearPreviewedFormWithNode) {
+TEST_F(FormManagerTest, ClearPreviewedFormWithElement) {
LoadHTML("<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">"
" <INPUT type=\"text\" id=\"firstname\" value=\"Wyatt\"/>"
" <INPUT type=\"text\" id=\"lastname\"/>"
@@ -2917,7 +2640,7 @@ TEST_F(FormManagerTest, ClearPreviewedFormWithNode) {
FormManager form_manager;
std::vector<FormData> forms;
- form_manager.ExtractForms(web_frame, &forms);
+ form_manager.ExtractForms(*web_frame, &forms);
ASSERT_EQ(1U, forms.size());
// Set the auto-filled attribute.
@@ -2944,7 +2667,7 @@ TEST_F(FormManagerTest, ClearPreviewedFormWithNode) {
phone.setSuggestedValue(ASCIIToUTF16("650-777-9999"));
// Clear the previewed fields.
- EXPECT_TRUE(form_manager.ClearPreviewedFormWithNode(lastname, false));
+ EXPECT_TRUE(FormManager::ClearPreviewedFormWithElement(lastname, false));
// Fields with empty suggestions suggestions are not modified.
EXPECT_EQ(ASCIIToUTF16("Wyatt"), firstname.value());
@@ -2985,7 +2708,7 @@ TEST_F(FormManagerTest, ClearPreviewedFormWithNonEmptyInitiatingNode) {
FormManager form_manager;
std::vector<FormData> forms;
- form_manager.ExtractForms(web_frame, &forms);
+ form_manager.ExtractForms(*web_frame, &forms);
ASSERT_EQ(1U, forms.size());
// Set the auto-filled attribute.
@@ -3014,7 +2737,7 @@ TEST_F(FormManagerTest, ClearPreviewedFormWithNonEmptyInitiatingNode) {
phone.setSuggestedValue(ASCIIToUTF16("650-777-9999"));
// Clear the previewed fields.
- EXPECT_TRUE(form_manager.ClearPreviewedFormWithNode(firstname, false));
+ EXPECT_TRUE(FormManager::ClearPreviewedFormWithElement(firstname, false));
// Fields with non-empty values are restored.
EXPECT_EQ(ASCIIToUTF16("W"), firstname.value());
@@ -3053,7 +2776,7 @@ TEST_F(FormManagerTest, ClearPreviewedFormWithAutofilledInitiatingNode) {
FormManager form_manager;
std::vector<FormData> forms;
- form_manager.ExtractForms(web_frame, &forms);
+ form_manager.ExtractForms(*web_frame, &forms);
ASSERT_EQ(1U, forms.size());
// Set the auto-filled attribute.
@@ -3081,7 +2804,7 @@ TEST_F(FormManagerTest, ClearPreviewedFormWithAutofilledInitiatingNode) {
phone.setSuggestedValue(ASCIIToUTF16("650-777-9999"));
// Clear the previewed fields.
- EXPECT_TRUE(form_manager.ClearPreviewedFormWithNode(firstname, true));
+ EXPECT_TRUE(FormManager::ClearPreviewedFormWithElement(firstname, true));
// Fields with non-empty values are restored.
EXPECT_EQ(ASCIIToUTF16("W"), firstname.value());
@@ -3120,39 +2843,19 @@ TEST_F(FormManagerTest, FormWithNodeIsAutofilled) {
FormManager form_manager;
std::vector<FormData> forms;
- form_manager.ExtractForms(web_frame, &forms);
+ form_manager.ExtractForms(*web_frame, &forms);
ASSERT_EQ(1U, forms.size());
WebInputElement firstname =
web_frame->document().getElementById("firstname").to<WebInputElement>();
// Auto-filled attribute not set yet.
- EXPECT_FALSE(form_manager.FormWithNodeIsAutofilled(firstname));
+ EXPECT_FALSE(FormManager::FormWithElementIsAutofilled(firstname));
// Set the auto-filled attribute.
firstname.setAutofilled(true);
- EXPECT_TRUE(form_manager.FormWithNodeIsAutofilled(firstname));
-}
-
-TEST_F(FormManagerTest, LabelForElementHidden) {
- LoadHTML("<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
- " <LABEL for=\"firstname\"> First name: </LABEL>"
- " <INPUT type=\"hidden\" id=\"firstname\" value=\"John\"/>"
- " <LABEL for=\"lastname\"> Last name: </LABEL>"
- " <INPUT type=\"hidden\" id=\"lastname\" value=\"Smith\"/>"
- " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
- "</FORM>");
-
- WebFrame* web_frame = GetMainFrame();
- ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
-
- WebElement e = web_frame->document().getElementById("firstname");
- WebFormControlElement firstname = e.to<WebFormControlElement>();
-
- // Hidden form control element should not have a label set.
- FormManager form_manager;
- EXPECT_EQ(string16(), form_manager.LabelForElement(firstname));
+ EXPECT_TRUE(FormManager::FormWithElementIsAutofilled(firstname));
}
// If we have multiple labels per id, the labels concatenated into label string.
@@ -3215,10 +2918,10 @@ TEST_F(FormManagerTest, SelectOneAsText) {
// Extract the country select-one value as text.
EXPECT_TRUE(FormManager::WebFormElementToFormData(
- forms[0], FormManager::REQUIRE_NONE,
+ forms[0], WebFormControlElement(), FormManager::REQUIRE_NONE,
static_cast<FormManager::ExtractMask>(FormManager::EXTRACT_VALUE |
FormManager::EXTRACT_OPTION_TEXT),
- &form));
+ &form, NULL));
EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
EXPECT_EQ(GURL(frame->document().url()), form.origin);
EXPECT_EQ(GURL("http://cnn.com"), form.action);
@@ -3249,9 +2952,11 @@ TEST_F(FormManagerTest, SelectOneAsText) {
form.fields.clear();
// Extract the country select-one value as value.
EXPECT_TRUE(FormManager::WebFormElementToFormData(forms[0],
+ WebFormControlElement(),
FormManager::REQUIRE_NONE,
FormManager::EXTRACT_VALUE,
- &form));
+ &form,
+ NULL));
EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
EXPECT_EQ(GURL(frame->document().url()), form.origin);
EXPECT_EQ(GURL("http://cnn.com"), form.action);