diff options
-rw-r--r-- | chrome/browser/autofill/autofill_manager.cc | 52 | ||||
-rw-r--r-- | chrome/browser/autofill/autofill_manager.h | 6 | ||||
-rw-r--r-- | chrome/browser/browser.cc | 11 | ||||
-rw-r--r-- | chrome/browser/browser.h | 1 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_view_host.cc | 5 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_view_host.h | 3 | ||||
-rwxr-xr-x | chrome/common/render_messages_internal.h | 3 | ||||
-rw-r--r-- | chrome/renderer/form_manager.cc | 19 | ||||
-rw-r--r-- | chrome/renderer/form_manager.h | 14 | ||||
-rw-r--r-- | chrome/renderer/form_manager_unittest.cc | 112 | ||||
-rwxr-xr-x | chrome/renderer/render_view.cc | 10 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 5 |
12 files changed, 123 insertions, 118 deletions
diff --git a/chrome/browser/autofill/autofill_manager.cc b/chrome/browser/autofill/autofill_manager.cc index 33d6e6e..8733f39 100644 --- a/chrome/browser/autofill/autofill_manager.cc +++ b/chrome/browser/autofill/autofill_manager.cc @@ -379,58 +379,6 @@ void AutoFillManager::UploadFormData() { // form_is_autofilled); } -void AutoFillManager::FillDefaultProfile() { - if (!IsAutoFillEnabled()) - return; - - RenderViewHost* host = tab_contents_->render_view_host(); - if (!host) - return; - - // TODO(jhawkins): Do we need to wait for the profiles to be loaded? - const std::vector<AutoFillProfile*>& profiles = personal_data_->profiles(); - if (profiles.empty()) - return; - - AutoFillProfile* profile = NULL; - int default_profile = personal_data_->DefaultProfile(); - if (default_profile != -1) - profile = profiles[default_profile]; - - // If we have any profiles, at least one of them must be the default. - DCHECK(profile); - - std::vector<FormData> forms; - for (std::vector<FormStructure*>::const_iterator iter = - form_structures_.begin(); - iter != form_structures_.end(); ++iter) { - const FormStructure* form_structure = *iter; - - // Don't fill the form if it's not auto-fillable. - if (!form_structure->IsAutoFillable()) - continue; - - FormData form = form_structure->ConvertToFormData(); - DCHECK_EQ(form_structure->field_count(), form.fields.size()); - - for (size_t i = 0; i < form_structure->field_count(); ++i) { - const AutoFillField* field = form_structure->field(i); - AutoFillType type(field->type()); - - // Don't AutoFill credit card information. - if (type.group() == AutoFillType::CREDIT_CARD) - continue; - - form.fields[i].set_value(profile->GetFieldText(type)); - } - - forms.push_back(form); - } - - if (!forms.empty()) - host->AutoFillForms(forms); -} - AutoFillManager::AutoFillManager() : tab_contents_(NULL), personal_data_(NULL), diff --git a/chrome/browser/autofill/autofill_manager.h b/chrome/browser/autofill/autofill_manager.h index 546f02c..9c7579e 100644 --- a/chrome/browser/autofill/autofill_manager.h +++ b/chrome/browser/autofill/autofill_manager.h @@ -88,12 +88,6 @@ class AutoFillManager : public RenderViewHostDelegate::AutoFill, // Uploads the form data to the AutoFill server. void UploadFormData(); - // Fills all the forms in the page with the default profile. Credit card - // fields are not filled out. - // TODO(jhawkins): Do we really want to fill all of the forms on the page? - // Check how toolbar handles this case. - void FillDefaultProfile(); - protected: // For tests. AutoFillManager(); diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc index 49f5394..9a2e9ad 100644 --- a/chrome/browser/browser.cc +++ b/chrome/browser/browser.cc @@ -1761,14 +1761,6 @@ void Browser::OpenInternetOptionsDialog() { } #endif -void Browser::AutoFillDefaultProfile() { - TabContents* current_tab = GetSelectedTabContents(); - if (!current_tab) // May be NULL during tab restore. - return; - - current_tab->GetAutoFillManager()->FillDefaultProfile(); -} - /////////////////////////////////////////////////////////////////////////////// // static @@ -2020,9 +2012,6 @@ void Browser::ExecuteCommandWithDisposition( case IDC_INTERNET_OPTIONS: OpenInternetOptionsDialog(); break; #endif - // AutoFill - case IDC_AUTOFILL_DEFAULT: AutoFillDefaultProfile(); break; - default: LOG(WARNING) << "Received Unimplemented Command: " << id; break; diff --git a/chrome/browser/browser.h b/chrome/browser/browser.h index cfd9959..49329de 100644 --- a/chrome/browser/browser.h +++ b/chrome/browser/browser.h @@ -536,7 +536,6 @@ class Browser : public TabStripModelDelegate, void OpenSystemOptionsDialog(); void OpenInternetOptionsDialog(); #endif - void AutoFillDefaultProfile(); virtual void UpdateDownloadShelfVisibility(bool visible); diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc index 5202e17..223a2e4 100644 --- a/chrome/browser/renderer_host/render_view_host.cc +++ b/chrome/browser/renderer_host/render_view_host.cc @@ -1632,11 +1632,6 @@ void RenderViewHost::AutoFillSuggestionsReturned( routing_id(), query_id, names, labels, default_suggestion_index)); } -void RenderViewHost::AutoFillForms( - const std::vector<webkit_glue::FormData>& forms) { - Send(new ViewMsg_AutoFillForms(routing_id(), forms)); -} - void RenderViewHost::AutocompleteSuggestionsReturned( int query_id, const std::vector<string16>& suggestions, int default_suggestion_index) { diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h index d789047..75898af 100644 --- a/chrome/browser/renderer_host/render_view_host.h +++ b/chrome/browser/renderer_host/render_view_host.h @@ -388,9 +388,6 @@ class RenderViewHost : public RenderWidgetHost { const std::vector<string16>& labels, int default_suggestion_index); - // Called by the AutoFillManager to fill out all the forms in the renderer. - void AutoFillForms(const std::vector<webkit_glue::FormData>& forms); - // Called by the AutocompleteHistoryManager when the list of suggestions is // ready. void AutocompleteSuggestionsReturned( diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index 88725ad..7946508 100755 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -641,9 +641,6 @@ IPC_BEGIN_MESSAGES(View) std::vector<string16> /* labels */, int /* index of default suggestion */) - IPC_MESSAGE_ROUTED1(ViewMsg_AutoFillForms, - std::vector<webkit_glue::FormData> /* forms */) - // Reply to the ViewHostMsg_QueryFormFieldAutofill message with the // autocomplete suggestions. IPC_MESSAGE_ROUTED3(ViewMsg_AutocompleteSuggestionsReturned, diff --git a/chrome/renderer/form_manager.cc b/chrome/renderer/form_manager.cc index 6cc4e17..3868582 100644 --- a/chrome/renderer/form_manager.cc +++ b/chrome/renderer/form_manager.cc @@ -514,7 +514,7 @@ bool FormManager::FindFormWithFormControlElement( return false; } -bool FormManager::FillForm(const FormData& form) { +bool FormManager::FillForm(const FormData& form, const WebKit::WebNode& node) { FormElement* form_element = NULL; if (!FindCachedFormElement(form, &form_element)) return false; @@ -522,6 +522,7 @@ bool FormManager::FillForm(const FormData& form) { RequirementsMask requirements = static_cast<RequirementsMask>( REQUIRE_AUTOCOMPLETE | REQUIRE_ENABLED | REQUIRE_EMPTY); ForEachMatchingFormField(form_element, + node, requirements, form, NewCallback(this, &FormManager::FillFormField)); @@ -537,6 +538,7 @@ bool FormManager::PreviewForm(const FormData& form) { RequirementsMask requirements = static_cast<RequirementsMask>( REQUIRE_AUTOCOMPLETE | REQUIRE_ENABLED | REQUIRE_EMPTY); ForEachMatchingFormField(form_element, + WebNode(), requirements, form, NewCallback(this, &FormManager::PreviewFormField)); @@ -567,13 +569,6 @@ void FormManager::ClearPreviewedForm(const FormData& form) { } } -void FormManager::FillForms(const std::vector<FormData>& forms) { - for (std::vector<FormData>::const_iterator iter = forms.begin(); - iter != forms.end(); ++iter) { - FillForm(*iter); - } -} - void FormManager::Reset() { for (WebFrameFormElementMap::iterator iter = form_elements_map_.begin(); iter != form_elements_map_.end(); ++iter) { @@ -682,6 +677,7 @@ bool FormManager::FindCachedFormElement(const FormData& form, } void FormManager::ForEachMatchingFormField(FormElement* form, + const WebKit::WebNode& node, RequirementsMask requirements, const FormData& data, Callback* callback) { @@ -723,7 +719,12 @@ void FormManager::ForEachMatchingFormField(FormElement* form, if (requirements & REQUIRE_AUTOCOMPLETE && !input_element.autoComplete()) continue; - if (requirements & REQUIRE_EMPTY && !input_element.value().isEmpty()) + // Don't require the node that initiated the auto-fill process to be + // empty. The user is typing in this field and we should complete the + // value when the user selects a value to fill out. + if (requirements & REQUIRE_EMPTY && + input_element != node && + !input_element.value().isEmpty()) continue; } diff --git a/chrome/renderer/form_manager.h b/chrome/renderer/form_manager.h index ad4dee7..4d6aa5c 100644 --- a/chrome/renderer/form_manager.h +++ b/chrome/renderer/form_manager.h @@ -87,10 +87,11 @@ class FormManager { // 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. + // must match the number of stored elements in the form. |node| is the form + // control element that initiated the auto-fill process. // 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 webkit_glue::FormData& form); + bool FillForm(const webkit_glue::FormData& form, const WebKit::WebNode& node); // Previews the form represented by |form|. Same conditions as FillForm. bool PreviewForm(const webkit_glue::FormData& form); @@ -99,9 +100,6 @@ class FormManager { // in |form| that have been previewed. void ClearPreviewedForm(const webkit_glue::FormData& form); - // Fills all of the forms in the cache with form data from |forms|. - void FillForms(const std::vector<webkit_glue::FormData>& forms); - // Resets the stored set of forms. void Reset(); @@ -144,9 +142,11 @@ class FormManager { // For each field in |data| that matches the corresponding field in |form| // and meets the |requirements|, |callback| is called with the actual - // WebFormControlElement and the FormField data from |form|. This method owns - // |callback|. + // WebFormControlElement and the FormField data from |form|. The field that + // matches |node| is not required to be empty if |requirements| includes + // REQUIRE_EMPTY. This method owns |callback|. void ForEachMatchingFormField(FormElement* form, + const WebKit::WebNode& node, RequirementsMask requirements, const webkit_glue::FormData& data, Callback* callback); diff --git a/chrome/renderer/form_manager_unittest.cc b/chrome/renderer/form_manager_unittest.cc index 4344499..1731f47 100644 --- a/chrome/renderer/form_manager_unittest.cc +++ b/chrome/renderer/form_manager_unittest.cc @@ -9,6 +9,7 @@ #include "third_party/WebKit/WebKit/chromium/public/WebElement.h" #include "third_party/WebKit/WebKit/chromium/public/WebFormElement.h" #include "third_party/WebKit/WebKit/chromium/public/WebInputElement.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" #include "webkit/glue/form_data.h" @@ -18,6 +19,7 @@ using WebKit::WebElement; using WebKit::WebFormElement; using WebKit::WebFrame; using WebKit::WebInputElement; +using WebKit::WebNode; using WebKit::WebString; using WebKit::WebVector; @@ -420,7 +422,7 @@ TEST_F(FormManagerTest, FillForm) { form.fields[3].set_value(ASCIIToUTF16("Beta")); form.fields[4].set_value(ASCIIToUTF16("Gamma")); form.fields[5].set_value(ASCIIToUTF16("Delta")); - EXPECT_TRUE(form_manager.FillForm(form)); + EXPECT_TRUE(form_manager.FillForm(form, WebNode())); // Verify the filled elements. WebDocument document = web_frame->document(); @@ -1271,7 +1273,7 @@ TEST_F(FormManagerTest, FillFormMaxLength) { // Fill the form. form.fields[0].set_value(ASCIIToUTF16("Brother")); form.fields[1].set_value(ASCIIToUTF16("Jonathan")); - EXPECT_TRUE(form_manager.FillForm(form)); + EXPECT_TRUE(form_manager.FillForm(form, WebNode())); // Find the newly-filled form that contains the input element. FormData form2; @@ -1359,7 +1361,7 @@ TEST_F(FormManagerTest, FillFormNegativeMaxLength) { // Fill the form. form.fields[0].set_value(ASCIIToUTF16("Brother")); form.fields[1].set_value(ASCIIToUTF16("Jonathan")); - EXPECT_TRUE(form_manager.FillForm(form)); + EXPECT_TRUE(form_manager.FillForm(form, WebNode())); // Find the newly-filled form that contains the input element. FormData form2; @@ -1459,7 +1461,7 @@ TEST_F(FormManagerTest, FillFormMoreFormDataFields) { form->fields[4].set_value(ASCIIToUTF16("Beta")); form->fields[5].set_value(ASCIIToUTF16("Jonathan")); form->fields[6].set_value(ASCIIToUTF16("Omega")); - EXPECT_TRUE(form_manager.FillForm(*form)); + EXPECT_TRUE(form_manager.FillForm(*form, WebNode())); // Get the input element we want to find. WebElement element = web_frame->document().getElementById("firstname"); @@ -1537,7 +1539,7 @@ TEST_F(FormManagerTest, FillFormFewerFormDataFields) { form->fields[0].set_value(ASCIIToUTF16("Brother")); form->fields[1].set_value(ASCIIToUTF16("Joseph")); form->fields[2].set_value(ASCIIToUTF16("Jonathan")); - EXPECT_TRUE(form_manager.FillForm(*form)); + EXPECT_TRUE(form_manager.FillForm(*form, WebNode())); // Get the input element we want to find. WebElement element = web_frame->document().getElementById("firstname"); @@ -1632,7 +1634,7 @@ TEST_F(FormManagerTest, FillFormChangedFormDataFields) { form->fields[1].set_label(ASCIIToUTF16("bogus")); form->fields[1].set_name(ASCIIToUTF16("bogus")); - EXPECT_TRUE(form_manager.FillForm(*form)); + EXPECT_TRUE(form_manager.FillForm(*form, WebNode())); // Get the input element we want to find. WebElement element = web_frame->document().getElementById("firstname"); @@ -1704,7 +1706,7 @@ TEST_F(FormManagerTest, FillFormExtraFieldInCache) { form->fields[0].set_value(ASCIIToUTF16("Brother")); form->fields[1].set_value(ASCIIToUTF16("Joseph")); form->fields[2].set_value(ASCIIToUTF16("Jonathan")); - EXPECT_TRUE(form_manager.FillForm(*form)); + EXPECT_TRUE(form_manager.FillForm(*form, WebNode())); // Get the input element we want to find. WebElement element = web_frame->document().getElementById("firstname"); @@ -1801,7 +1803,7 @@ TEST_F(FormManagerTest, FillFormEmptyName) { // Fill the form. form.fields[0].set_value(ASCIIToUTF16("Wyatt")); form.fields[1].set_value(ASCIIToUTF16("Earp")); - EXPECT_TRUE(form_manager.FillForm(form)); + EXPECT_TRUE(form_manager.FillForm(form, WebNode())); // Find the newly-filled form that contains the input element. FormData form2; @@ -1893,7 +1895,7 @@ TEST_F(FormManagerTest, FillFormEmptyFormNames) { // Fill the form. form.fields[0].set_value(ASCIIToUTF16("Red")); form.fields[1].set_value(ASCIIToUTF16("Yellow")); - EXPECT_TRUE(form_manager.FillForm(form)); + EXPECT_TRUE(form_manager.FillForm(form, WebNode())); // Find the newly-filled form that contains the input element. FormData form2; @@ -2070,4 +2072,96 @@ TEST_F(FormManagerTest, SizeFields) { fields[6]); } +// This test re-creates the experience of typing in a field then selecting a +// profile from the AutoFill suggestions popup. The field that is being typed +// into should be filled even though it's not technically empty. +TEST_F(FormManagerTest, FillFormNonEmptyField) { + LoadHTML("<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">" + " <INPUT type=\"text\" id=\"firstname\"/>" + " <INPUT type=\"text\" id=\"lastname\"/>" + " <INPUT type=\"submit\" value=\"Send\"/>" + "</FORM>"); + + WebFrame* web_frame = GetMainFrame(); + ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame); + + FormManager form_manager; + form_manager.ExtractForms(web_frame); + + // Verify that we have the form. + std::vector<FormData> forms; + form_manager.GetForms(FormManager::REQUIRE_NONE, &forms); + ASSERT_EQ(1U, forms.size()); + + // Get the input element we want to find. + WebElement element = web_frame->document().getElementById("firstname"); + WebInputElement input_element = element.to<WebInputElement>(); + + // Simulate typing by modifying the field value. + input_element.setValue(ASCIIToUTF16("Wy")); + + // Find the form that contains the input element. + FormData form; + EXPECT_TRUE(form_manager.FindFormWithFormControlElement( + input_element, FormManager::REQUIRE_NONE, &form)); + EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); + EXPECT_EQ(GURL(web_frame->url()), form.origin); + EXPECT_EQ(GURL("http://buh.com"), form.action); + + const std::vector<FormField>& fields = form.fields; + ASSERT_EQ(3U, fields.size()); + EXPECT_EQ(FormField(string16(), + ASCIIToUTF16("firstname"), + string16(), + ASCIIToUTF16("text"), + 20), + fields[0]); + EXPECT_EQ(FormField(string16(), + ASCIIToUTF16("lastname"), + string16(), + ASCIIToUTF16("text"), + 20), + fields[1]); + EXPECT_EQ(FormField(string16(), + string16(), + ASCIIToUTF16("Send"), + ASCIIToUTF16("submit"), + 0), + fields[2]); + + // Fill the form. + form.fields[0].set_value(ASCIIToUTF16("Wyatt")); + form.fields[1].set_value(ASCIIToUTF16("Earp")); + EXPECT_TRUE(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, FormManager::REQUIRE_NONE, &form2)); + EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name); + EXPECT_EQ(GURL(web_frame->url()), form2.origin); + EXPECT_EQ(GURL("http://buh.com"), form2.action); + + const std::vector<FormField>& fields2 = form2.fields; + ASSERT_EQ(3U, fields2.size()); + EXPECT_EQ(FormField(string16(), + ASCIIToUTF16("firstname"), + ASCIIToUTF16("Wyatt"), + ASCIIToUTF16("text"), + 20), + fields2[0]); + EXPECT_EQ(FormField(string16(), + ASCIIToUTF16("lastname"), + ASCIIToUTF16("Earp"), + ASCIIToUTF16("text"), + 20), + fields2[1]); + EXPECT_EQ(FormField(string16(), + string16(), + ASCIIToUTF16("Send"), + ASCIIToUTF16("submit"), + 0), + fields2[2]); +} + } // namespace diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index c9e89c52..74dd7ac 100755 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -682,7 +682,6 @@ void RenderView::OnMessageReceived(const IPC::Message& message) { OnDisassociateFromPopupCount) IPC_MESSAGE_HANDLER(ViewMsg_AutoFillSuggestionsReturned, OnAutoFillSuggestionsReturned) - IPC_MESSAGE_HANDLER(ViewMsg_AutoFillForms, OnAutoFillForms) IPC_MESSAGE_HANDLER(ViewMsg_AutocompleteSuggestionsReturned, OnAutocompleteSuggestionsReturned) IPC_MESSAGE_HANDLER(ViewMsg_AutoFillFormDataFilled, @@ -1515,12 +1514,6 @@ void RenderView::OnAutoFillSuggestionsReturned( webview()->applyAutoFillSuggestions( autofill_query_node_, values, labels, default_suggestion_index); } - autofill_query_node_.reset(); -} - -void RenderView::OnAutoFillForms( - const std::vector<webkit_glue::FormData>& forms) { - form_manager_.FillForms(forms); } void RenderView::OnAutocompleteSuggestionsReturned( @@ -1531,7 +1524,6 @@ void RenderView::OnAutocompleteSuggestionsReturned( webview()->applyAutocompleteSuggestions( autofill_query_node_, suggestions, default_suggestion_index); } - autofill_query_node_.reset(); } void RenderView::OnAutoFillFormDataFilled(int query_id, @@ -1542,7 +1534,7 @@ void RenderView::OnAutoFillFormDataFilled(int query_id, DCHECK_NE(AUTOFILL_NONE, autofill_action_); if (autofill_action_ == AUTOFILL_FILL) - form_manager_.FillForm(form); + form_manager_.FillForm(form, autofill_query_node_); else if (autofill_action_ == AUTOFILL_PREVIEW) form_manager_.PreviewForm(form); diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index 4a06534..6b6016c 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -683,7 +683,6 @@ class RenderView : public RenderWidget, int default_suggestions_index); void OnAutoFillFormDataFilled(int query_id, const webkit_glue::FormData& form); - void OnAutoFillForms(const std::vector<webkit_glue::FormData>& forms); void OnAutoFillSuggestionsReturned( int query_id, const std::vector<string16>& values, @@ -1136,12 +1135,12 @@ class RenderView : public RenderWidget, // Autofill ------------------------------------------------------------------ - // The id of the last request sent for form field autofill. Used to ignore + // The id of the last request sent for form field AutoFill. Used to ignore // out of date responses. int autofill_query_id_; // The id of the node corresponding to the last request sent for form field - // autofill. + // AutoFill. WebKit::WebNode autofill_query_node_; // The action to take when receiving AutoFill data from the AutoFillManager. |