diff options
author | jhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-05 01:30:49 +0000 |
---|---|---|
committer | jhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-05 01:30:49 +0000 |
commit | 3a60d2349854d9594b33aa119a390e39eee96f68 (patch) | |
tree | 117e6ae2250a0c222f8067573c418730163b9b97 | |
parent | 696bdc8641a331f9260aed274387888d512a882e (diff) | |
download | chromium_src-3a60d2349854d9594b33aa119a390e39eee96f68.zip chromium_src-3a60d2349854d9594b33aa119a390e39eee96f68.tar.gz chromium_src-3a60d2349854d9594b33aa119a390e39eee96f68.tar.bz2 |
Implement FormManager, a class that manages forms in a RenderView.
BUG=18201
TEST=FormManagerTest
Review URL: http://codereview.chromium.org/577009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@38157 0039d316-1c4b-4281-b951-d872f2087c98
-rwxr-xr-x | chrome/chrome_renderer.gypi | 2 | ||||
-rwxr-xr-x | chrome/chrome_tests.gypi | 1 | ||||
-rw-r--r-- | chrome/renderer/form_manager.cc | 184 | ||||
-rw-r--r-- | chrome/renderer/form_manager.h | 84 | ||||
-rw-r--r-- | chrome/renderer/form_manager_unittest.cc | 346 | ||||
-rw-r--r-- | webkit/glue/form_data.h | 11 |
6 files changed, 628 insertions, 0 deletions
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi index 1a41678..77252ba 100755 --- a/chrome/chrome_renderer.gypi +++ b/chrome/chrome_renderer.gypi @@ -81,6 +81,8 @@ 'renderer/external_host_bindings.h', 'renderer/external_extension.cc', 'renderer/external_extension.h', + 'renderer/form_manager.cc', + 'renderer/form_manager.h', 'renderer/localized_error.cc', 'renderer/localized_error.h', 'renderer/navigation_state.h', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 10d4e45..246e8f0 100755 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -847,6 +847,7 @@ 'common/worker_thread_ticker_unittest.cc', 'common/zip_unittest.cc', 'renderer/audio_message_filter_unittest.cc', + 'renderer/form_manager_unittest.cc', 'renderer/media/audio_renderer_impl_unittest.cc', 'renderer/extensions/extension_api_client_unittest.cc', 'renderer/extensions/json_schema_unittest.cc', diff --git a/chrome/renderer/form_manager.cc b/chrome/renderer/form_manager.cc new file mode 100644 index 0000000..afea244 --- /dev/null +++ b/chrome/renderer/form_manager.cc @@ -0,0 +1,184 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/renderer/form_manager.h" + +#include "base/logging.h" +#include "base/stl_util-inl.h" +#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h" +#include "third_party/WebKit/WebKit/chromium/public/WebNode.h" +#include "third_party/WebKit/WebKit/chromium/public/WebString.h" +#include "third_party/WebKit/WebKit/chromium/public/WebVector.h" + +using WebKit::WebFormElement; +using WebKit::WebFrame; +using WebKit::WebInputElement; +using WebKit::WebNode; +using WebKit::WebString; +using WebKit::WebVector; + +FormManager::FormManager() { +} + +FormManager::~FormManager() { + Reset(); +} + +void FormManager::ExtractForms(WebFrame* frame) { + // Reset the vector of FormElements for this frame. + ResetFrame(frame); + + WebVector<WebFormElement> web_forms; + frame->forms(web_forms); + + // Form loop. + for (size_t i = 0; i < web_forms.size(); ++i) { + FormElement* form_elements = new FormElement; + form_elements->form_element = web_forms[i]; + + // Form elements loop. + WebVector<WebInputElement> input_elements; + form_elements->form_element.getInputElements(input_elements); + for (size_t j = 0; j < input_elements.size(); ++j) { + WebInputElement element = input_elements[j]; + form_elements->input_elements[element.nameForAutofill()] = element; + } + + form_elements_map_[frame].push_back(form_elements); + } +} + +void FormManager::GetForms(std::vector<FormData>* forms, + RequirementsMask requirements) { + // Frame loop. + for (WebFrameFormElementMap::iterator iter = form_elements_map_.begin(); + iter != form_elements_map_.end(); ++iter) { + WebFrame* frame = iter->first; + + // Form loop. + 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); + } + } +} + +bool FormManager::FindForm(const WebInputElement& element, FormData* form) { + // Frame loop. + for (WebFrameFormElementMap::iterator iter = form_elements_map_.begin(); + iter != form_elements_map_.end(); ++iter) { + WebFrame* frame = iter->first; + + // Form loop. + for (std::vector<FormElement*>::iterator form_iter = iter->second.begin(); + form_iter != iter->second.end(); ++form_iter) { + FormElement* form_element = *form_iter; + + if (form_element->input_elements.find(element.nameForAutofill()) != + form_element->input_elements.end()) { + FormElementToFormData(frame, form_element, REQUIRE_NONE, form); + return true; + } + } + } + + return false; +} + +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) { + if ((*form_iter)->form_element.name() == form.name) { + form_element = *form_iter; + break; + } + } + } + + if (!form_element) + return false; + + DCHECK(form_element->input_elements.size() == form.elements.size()); + DCHECK(form.elements.size() == form.values.size()); + + size_t i = 0; + for (FormInputElementMap::iterator iter = + form_element->input_elements.begin(); + iter != form_element->input_elements.end(); ++iter, ++i) { + DCHECK(iter->second.nameForAutofill() == form.elements[i]); + + iter->second.setValue(form.values[i]); + iter->second.setAutofilled(true); + } + + return true; +} + +void FormManager::Reset() { + for (WebFrameFormElementMap::iterator iter = form_elements_map_.begin(); + iter != form_elements_map_.end(); ++iter) { + STLDeleteElements(&iter->second); + } + form_elements_map_.clear(); +} + +void FormManager::ResetFrame(WebFrame* frame) { + WebFrameFormElementMap::iterator iter = form_elements_map_.find(frame); + if (iter != form_elements_map_.end()) { + STLDeleteElements(&iter->second); + form_elements_map_.erase(iter); + } +} + +void FormManager::FormElementToFormData(WebFrame* frame, + const FormElement* form_element, + RequirementsMask requirements, + FormData* form) { + form->name = form_element->form_element.name(); + form->origin = frame->url(); + form->action = frame->completeURL(form_element->form_element.action()); + + // If the completed ULR is not valid, just use the action we get from + // WebKit. + if (!form->action.is_valid()) + form->action = GURL(form_element->form_element.action()); + + // Form elements loop. + for (FormInputElementMap::const_iterator element_iter = + form_element->input_elements.begin(); + element_iter != form_element->input_elements.end(); ++element_iter) { + const WebInputElement& input_element = element_iter->second; + + if (requirements & REQUIRE_AUTOCOMPLETE && + !input_element.autoComplete()) + continue; + + if (requirements & REQUIRE_ELEMENTS_ENABLED && + !input_element.isEnabledFormControl()) + continue; + + form->elements.push_back(input_element.nameForAutofill()); + form->values.push_back(input_element.value()); + + // TODO(jhawkins): It's possible for a form to have more than one submit + // input element. The FormData structure probably doesn't need to keep + // track of the name of any submit button. + if (input_element.inputType() == WebInputElement::Submit) + form->submit = input_element.nameForAutofill(); + } +} diff --git a/chrome/renderer/form_manager.h b/chrome/renderer/form_manager.h new file mode 100644 index 0000000..209c93c --- /dev/null +++ b/chrome/renderer/form_manager.h @@ -0,0 +1,84 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_RENDERER_FORM_MANAGER_H_ +#define CHROME_RENDERER_FORM_MANAGER_H_ + +#include <map> +#include <vector> + +#include "base/string16.h" +#include "third_party/WebKit/WebKit/chromium/public/WebFormElement.h" +#include "third_party/WebKit/WebKit/chromium/public/WebInputElement.h" +#include "webkit/glue/form_data.h" + +namespace WebKit { +class WebFrame; +} + +// Manages the forms in a RenderView. +class FormManager { + public: + // A bitfield mask for form requirements. + typedef enum { + REQUIRE_NONE = 0x0, // No requirements. + REQUIRE_AUTOCOMPLETE = 0x1, // Require that autocomplete != off. + REQUIRE_ELEMENTS_ENABLED = 0x2 // Require that disabled attribute is off. + } RequirementsMask; + + FormManager(); + virtual ~FormManager(); + + // Scans the DOM in |frame| extracting and storing forms. + void ExtractForms(WebKit::WebFrame* frame); + + // Returns a vector of forms that match |requirements|. + void GetForms(std::vector<FormData>* forms, RequirementsMask requirements); + + // Finds the form that contains |input_element| and returns it in |form|. + // Returns false if the form is not found. + bool FindForm(const WebKit::WebInputElement& input_element, FormData* form); + + // Fills the form represented by |form|. |form| should have the name set to + // the name of the form to fill out, and the number of elements and values + // must match the number of stored elements in the form. + // TODO(jhawkins): Is matching on name alone good enough? It's possible to + // store multiple forms with the same names from different frames. + bool FillForm(const FormData& form); + + // Resets the stored set of forms. + void Reset(); + + private: + // A map of WebInputElements keyed by each element's name. + typedef std::map<string16, WebKit::WebInputElement> FormInputElementMap; + + // Stores the WebFormElement and the map of input elements for each form. + struct FormElement { + WebKit::WebFormElement form_element; + FormInputElementMap input_elements; + }; + + // A map of vectors of FormElements keyed by the WebFrame containing each + // form. + typedef std::map<WebKit::WebFrame*, std::vector<FormElement*> > + WebFrameFormElementMap; + + // Resets the forms for the specified |frame|. + void ResetFrame(WebKit::WebFrame* frame); + + // Converts a FormElement to FormData storage. + // TODO(jhawkins): Modify FormElement so we don't need |frame|. + void FormElementToFormData(WebKit::WebFrame* frame, + const FormElement* form_element, + RequirementsMask requirements, + FormData* form); + + // The map of form elements. + WebFrameFormElementMap form_elements_map_; + + DISALLOW_COPY_AND_ASSIGN(FormManager); +}; + +#endif // CHROME_RENDERER_FORM_MANAGER_H_ diff --git a/chrome/renderer/form_manager_unittest.cc b/chrome/renderer/form_manager_unittest.cc new file mode 100644 index 0000000..4a5e52a --- /dev/null +++ b/chrome/renderer/form_manager_unittest.cc @@ -0,0 +1,346 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/renderer/form_manager.h" +#include "chrome/test/render_view_test.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h" +#include "third_party/WebKit/WebKit/chromium/public/WebElement.h" +#include "third_party/WebKit/WebKit/chromium/public/WebInputElement.h" +#include "third_party/WebKit/WebKit/chromium/public/WebString.h" + +using WebKit::WebElement; +using WebKit::WebFrame; +using WebKit::WebInputElement; +using WebKit::WebString; + +class FormManagerTest : public RenderViewTest { + public: + FormManagerTest() {} +}; + +TEST_F(FormManagerTest, ExtractForms) { + LoadHTML("<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">" + " <INPUT type=\"text\" id=\"firstname\" value=\"John\">" + " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\">" + " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\">" + "</FORM>"); + + WebFrame* web_frame = GetMainFrame(); + ASSERT_TRUE(web_frame); + + FormManager form_manager; + form_manager.ExtractForms(web_frame); + + std::vector<FormData> forms; + form_manager.GetForms(&forms, FormManager::REQUIRE_NONE); + ASSERT_EQ(1U, forms.size()); + + const FormData& form = forms[0]; + EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); + EXPECT_EQ(GURL(web_frame->url()), form.origin); + EXPECT_EQ(GURL("http://cnn.com"), form.action); + EXPECT_EQ(ASCIIToUTF16("reply-send"), form.submit); + + const std::vector<string16>& elements = form.elements; + ASSERT_EQ(3U, elements.size()); + EXPECT_EQ(ASCIIToUTF16("firstname"), elements[0]); + EXPECT_EQ(ASCIIToUTF16("lastname"), elements[1]); + EXPECT_EQ(ASCIIToUTF16("reply-send"), elements[2]); + + const std::vector<string16>& values = form.values; + ASSERT_EQ(3U, values.size()); + EXPECT_EQ(ASCIIToUTF16("John"), values[0]); + EXPECT_EQ(ASCIIToUTF16("Smith"), values[1]); + EXPECT_EQ(ASCIIToUTF16("Send"), values[2]); +} + +TEST_F(FormManagerTest, ExtractMultipleForms) { + LoadHTML("<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">" + " <INPUT type=\"text\" id=\"firstname\" value=\"John\">" + " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\">" + "</FORM>" + "<FORM name=\"TestForm2\" action=\"http://zoo.com\" method=\"post\">" + " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\">" + " <INPUT type=\"submit\" name=\"second\" value=\"Submit\">" + "</FORM>"); + + WebFrame* web_frame = GetMainFrame(); + ASSERT_TRUE(web_frame); + + FormManager form_manager; + form_manager.ExtractForms(web_frame); + + std::vector<FormData> forms; + form_manager.GetForms(&forms, FormManager::REQUIRE_NONE); + ASSERT_EQ(2U, forms.size()); + + // First form. + const FormData& form = forms[0]; + EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); + EXPECT_EQ(GURL(web_frame->url()), form.origin); + EXPECT_EQ(GURL("http://cnn.com"), form.action); + EXPECT_EQ(ASCIIToUTF16("reply-send"), form.submit); + + const std::vector<string16>& elements = form.elements; + ASSERT_EQ(2U, elements.size()); + EXPECT_EQ(ASCIIToUTF16("firstname"), elements[0]); + EXPECT_EQ(ASCIIToUTF16("reply-send"), elements[1]); + + const std::vector<string16>& values = form.values; + ASSERT_EQ(2U, values.size()); + EXPECT_EQ(ASCIIToUTF16("John"), values[0]); + EXPECT_EQ(ASCIIToUTF16("Send"), values[1]); + + // Second form. + const FormData& form2 = forms[1]; + EXPECT_EQ(ASCIIToUTF16("TestForm2"), form2.name); + EXPECT_EQ(GURL(web_frame->url()), form2.origin); + EXPECT_EQ(GURL("http://zoo.com"), form2.action); + EXPECT_EQ(ASCIIToUTF16("second"), form2.submit); + + const std::vector<string16>& elements2 = form2.elements; + ASSERT_EQ(2U, elements2.size()); + EXPECT_EQ(ASCIIToUTF16("lastname"), elements2[0]); + EXPECT_EQ(ASCIIToUTF16("second"), elements2[1]); + + const std::vector<string16>& values2 = form2.values; + ASSERT_EQ(2U, values2.size()); + EXPECT_EQ(ASCIIToUTF16("Smith"), values2[0]); + EXPECT_EQ(ASCIIToUTF16("Submit"), values2[1]); +} + +TEST_F(FormManagerTest, GetFormsAutocomplete) { + // Form is not auto-completable due to autocomplete=off. + LoadHTML("<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\"" + " autocomplete=off>" + " <INPUT type=\"text\" id=\"firstname\" value=\"John\">" + " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\">" + "</FORM>"); + + WebFrame* web_frame = GetMainFrame(); + ASSERT_TRUE(web_frame); + + FormManager form_manager; + form_manager.ExtractForms(web_frame); + + // Verify that we did load the forms. + std::vector<FormData> forms; + form_manager.GetForms(&forms, FormManager::REQUIRE_NONE); + ASSERT_EQ(1U, forms.size()); + + // autocomplete=off and we're requiring autocomplete, so no forms returned. + forms.clear(); + form_manager.GetForms(&forms, FormManager::REQUIRE_AUTOCOMPLETE); + ASSERT_EQ(0U, forms.size()); + + // The firstname element is not auto-completable due to autocomplete=off. + LoadHTML("<FORM name=\"TestForm\" action=\"http://abc.com\" method=\"post\">" + " <INPUT type=\"text\" id=\"firstname\" value=\"John\"" + " autocomplete=off>" + " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\">" + " <INPUT type=\"submit\" name=\"reply\" value=\"Send\">" + "</FORM>"); + + web_frame = GetMainFrame(); + ASSERT_TRUE(web_frame); + + form_manager.Reset(); + form_manager.ExtractForms(web_frame); + + forms.clear(); + form_manager.GetForms(&forms, FormManager::REQUIRE_AUTOCOMPLETE); + ASSERT_EQ(1U, forms.size()); + + const FormData& form = forms[0]; + EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); + EXPECT_EQ(GURL(web_frame->url()), form.origin); + EXPECT_EQ(GURL("http://abc.com"), form.action); + EXPECT_EQ(ASCIIToUTF16("reply"), form.submit); + + const std::vector<string16>& elements = form.elements; + ASSERT_EQ(2U, elements.size()); + EXPECT_EQ(ASCIIToUTF16("lastname"), elements[0]); + EXPECT_EQ(ASCIIToUTF16("reply"), elements[1]); + + const std::vector<string16>& values = form.values; + ASSERT_EQ(2U, values.size()); + EXPECT_EQ(ASCIIToUTF16("Smith"), values[0]); + EXPECT_EQ(ASCIIToUTF16("Send"), values[1]); +} + +TEST_F(FormManagerTest, GetFormsElementsEnabled) { + // The firstname element is not enabled due to disabled being set. + LoadHTML("<FORM name=\"TestForm\" action=\"http://xyz.com\" method=\"post\">" + " <INPUT disabled type=\"text\" id=\"firstname\" value=\"John\">" + " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\">" + " <INPUT type=\"submit\" name=\"submit\" value=\"Send\">" + "</FORM>"); + + WebFrame* web_frame = GetMainFrame(); + ASSERT_TRUE(web_frame); + + FormManager form_manager; + form_manager.ExtractForms(web_frame); + + std::vector<FormData> forms; + form_manager.GetForms(&forms, FormManager::REQUIRE_ELEMENTS_ENABLED); + ASSERT_EQ(1U, forms.size()); + + const FormData& form = forms[0]; + EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); + EXPECT_EQ(GURL(web_frame->url()), form.origin); + EXPECT_EQ(GURL("http://xyz.com"), form.action); + EXPECT_EQ(ASCIIToUTF16("submit"), form.submit); + + const std::vector<string16>& elements = form.elements; + ASSERT_EQ(2U, elements.size()); + EXPECT_EQ(ASCIIToUTF16("lastname"), elements[0]); + EXPECT_EQ(ASCIIToUTF16("submit"), elements[1]); + + const std::vector<string16>& values = form.values; + ASSERT_EQ(2U, values.size()); + EXPECT_EQ(ASCIIToUTF16("Smith"), values[0]); + EXPECT_EQ(ASCIIToUTF16("Send"), values[1]); +} + +TEST_F(FormManagerTest, FindForm) { + LoadHTML("<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">" + " <INPUT type=\"text\" id=\"firstname\" value=\"John\">" + " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\">" + " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\">" + "</FORM>"); + + WebFrame* web_frame = GetMainFrame(); + ASSERT_TRUE(web_frame); + + FormManager form_manager; + form_manager.ExtractForms(web_frame); + + // Verify that we have the form. + std::vector<FormData> forms; + form_manager.GetForms(&forms, FormManager::REQUIRE_NONE); + ASSERT_EQ(1U, forms.size()); + + // Get the input element we want to find. + WebElement element = + web_frame->document().getElementById(WebString::fromUTF8("firstname")); + WebInputElement input_element = element.toElement<WebInputElement>(); + + // Find the form and verify it's the correct form. + FormData form; + EXPECT_TRUE(form_manager.FindForm(input_element, &form)); + EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); + EXPECT_EQ(GURL(web_frame->url()), form.origin); + EXPECT_EQ(GURL("http://buh.com"), form.action); + EXPECT_EQ(ASCIIToUTF16("reply-send"), form.submit); + + const std::vector<string16>& elements = form.elements; + ASSERT_EQ(3U, elements.size()); + EXPECT_EQ(ASCIIToUTF16("firstname"), elements[0]); + EXPECT_EQ(ASCIIToUTF16("lastname"), elements[1]); + EXPECT_EQ(ASCIIToUTF16("reply-send"), elements[2]); + + const std::vector<string16>& values = form.values; + ASSERT_EQ(3U, values.size()); + EXPECT_EQ(ASCIIToUTF16("John"), values[0]); + EXPECT_EQ(ASCIIToUTF16("Smith"), values[1]); + EXPECT_EQ(ASCIIToUTF16("Send"), values[2]); +} + +TEST_F(FormManagerTest, FillForm) { + LoadHTML("<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">" + " <INPUT type=\"text\" id=\"firstname\">" + " <INPUT type=\"text\" id=\"lastname\">" + " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\">" + "</FORM>"); + + WebFrame* web_frame = GetMainFrame(); + ASSERT_TRUE(web_frame); + + FormManager form_manager; + form_manager.ExtractForms(web_frame); + + // Verify that we have the form. + std::vector<FormData> forms; + form_manager.GetForms(&forms, FormManager::REQUIRE_NONE); + ASSERT_EQ(1U, forms.size()); + + // Get the input element we want to find. + WebElement element = + web_frame->document().getElementById(WebString::fromUTF8("firstname")); + WebInputElement input_element = element.toElement<WebInputElement>(); + + // Find the form that contains the input element. + FormData form; + EXPECT_TRUE(form_manager.FindForm(input_element, &form)); + EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); + EXPECT_EQ(GURL(web_frame->url()), form.origin); + EXPECT_EQ(GURL("http://buh.com"), form.action); + EXPECT_EQ(ASCIIToUTF16("reply-send"), form.submit); + + const std::vector<string16>& elements = form.elements; + ASSERT_EQ(3U, elements.size()); + EXPECT_EQ(ASCIIToUTF16("firstname"), elements[0]); + EXPECT_EQ(ASCIIToUTF16("lastname"), elements[1]); + EXPECT_EQ(ASCIIToUTF16("reply-send"), elements[2]); + + // Verify that the text fields have no values. + const std::vector<string16>& values = form.values; + ASSERT_EQ(3U, values.size()); + EXPECT_EQ(string16(), values[0]); + EXPECT_EQ(string16(), values[1]); + EXPECT_EQ(ASCIIToUTF16("Send"), values[2]); + + // Fill the form. + form.values[0] = ASCIIToUTF16("Wyatt"); + form.values[1] = ASCIIToUTF16("Earp"); + EXPECT_TRUE(form_manager.FillForm(form)); + + // Find the newly-filled form that contains the input element. + FormData form2; + EXPECT_TRUE(form_manager.FindForm(input_element, &form2)); + EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name); + EXPECT_EQ(GURL(web_frame->url()), form2.origin); + EXPECT_EQ(GURL("http://buh.com"), form2.action); + EXPECT_EQ(ASCIIToUTF16("reply-send"), form2.submit); + + const std::vector<string16>& elements2 = form2.elements; + ASSERT_EQ(3U, elements2.size()); + EXPECT_EQ(ASCIIToUTF16("firstname"), elements2[0]); + EXPECT_EQ(ASCIIToUTF16("lastname"), elements2[1]); + EXPECT_EQ(ASCIIToUTF16("reply-send"), elements2[2]); + + // Verify that the text fields have no values. + const std::vector<string16>& values2 = form2.values; + ASSERT_EQ(3U, values2.size()); + EXPECT_EQ(ASCIIToUTF16("Wyatt"), values2[0]); + EXPECT_EQ(ASCIIToUTF16("Earp"), values2[1]); + EXPECT_EQ(ASCIIToUTF16("Send"), values2[2]); +} + +TEST_F(FormManagerTest, Reset) { + LoadHTML("<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">" + " <INPUT type=\"text\" id=\"firstname\" value=\"John\">" + " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\">" + " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\">" + "</FORM>"); + + WebFrame* web_frame = GetMainFrame(); + ASSERT_TRUE(web_frame); + + FormManager form_manager; + form_manager.ExtractForms(web_frame); + + std::vector<FormData> forms; + form_manager.GetForms(&forms, FormManager::REQUIRE_NONE); + ASSERT_EQ(1U, forms.size()); + + // There should be no forms after the call to Reset. + form_manager.Reset(); + + forms.clear(); + form_manager.GetForms(&forms, FormManager::REQUIRE_NONE); + ASSERT_EQ(0U, forms.size()); +} diff --git a/webkit/glue/form_data.h b/webkit/glue/form_data.h index 8c5876c..02e0096 100644 --- a/webkit/glue/form_data.h +++ b/webkit/glue/form_data.h @@ -11,6 +11,17 @@ // Holds information about a form to be filled and/or submitted. struct FormData { + FormData() {} + FormData(const FormData& data) + : name(data.name), + origin(data.origin), + action(data.action), + elements(data.elements), + values(data.values), + submit(data.submit) {} + + // The name of the form. + string16 name; // The URL (minus query parameters) containing the form GURL origin; // The action target of the form |