1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/strings/utf_string_conversions.h" 6 #include "chrome/test/base/chrome_render_view_test.h" 7 #include "components/autofill/content/common/autofill_messages.h" 8 #include "components/autofill/content/renderer/autofill_agent.h" 9 #include "components/autofill/core/common/form_data.h" 10 #include "components/autofill/core/common/form_field_data.h" 11 #include "testing/gtest/include/gtest/gtest.h" 12 #include "third_party/WebKit/public/platform/WebString.h" 13 #include "third_party/WebKit/public/web/WebDocument.h" 14 #include "third_party/WebKit/public/web/WebInputElement.h" 15 16 using blink::WebDocument; 17 using blink::WebFrame; 18 using blink::WebInputElement; 19 using blink::WebString; 20 21 namespace autofill { 22 23 typedef Tuple5<int, 24 autofill::FormData, 25 autofill::FormFieldData, 26 gfx::RectF, 27 bool> AutofillQueryParam; 28 29 TEST_F(ChromeRenderViewTest, SendForms) { 30 // Don't want any delay for form state sync changes. This will still post a 31 // message so updates will get coalesced, but as soon as we spin the message 32 // loop, it will generate an update. 33 SendContentStateImmediately(); 34 35 LoadHTML("<form method=\"POST\">" 36 " <input type=\"text\" id=\"firstname\"/>" 37 " <input type=\"text\" id=\"middlename\"/>" 38 " <input type=\"text\" id=\"lastname\" autoComplete=\"off\"/>" 39 " <input type=\"hidden\" id=\"email\"/>" 40 " <select id=\"state\"/>" 41 " <option>?</option>" 42 " <option>California</option>" 43 " <option>Texas</option>" 44 " </select>" 45 "</form>"); 46 47 // Verify that "FormsSeen" sends the expected number of fields. 48 const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching( 49 AutofillHostMsg_FormsSeen::ID); 50 ASSERT_NE(static_cast<IPC::Message*>(NULL), message); 51 AutofillHostMsg_FormsSeen::Param params; 52 AutofillHostMsg_FormsSeen::Read(message, ¶ms); 53 const std::vector<FormData>& forms = params.a; 54 ASSERT_EQ(1UL, forms.size()); 55 ASSERT_EQ(4UL, forms[0].fields.size()); 56 57 FormFieldData expected; 58 59 expected.name = ASCIIToUTF16("firstname"); 60 expected.value = base::string16(); 61 expected.form_control_type = "text"; 62 expected.max_length = WebInputElement::defaultMaxLength(); 63 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[0]); 64 65 expected.name = ASCIIToUTF16("middlename"); 66 expected.value = base::string16(); 67 expected.form_control_type = "text"; 68 expected.max_length = WebInputElement::defaultMaxLength(); 69 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[1]); 70 71 expected.name = ASCIIToUTF16("lastname"); 72 expected.value = base::string16(); 73 expected.form_control_type = "text"; 74 expected.autocomplete_attribute = "off"; 75 expected.max_length = WebInputElement::defaultMaxLength(); 76 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[2]); 77 expected.autocomplete_attribute = std::string(); // reset 78 79 expected.name = ASCIIToUTF16("state"); 80 expected.value = ASCIIToUTF16("?"); 81 expected.form_control_type = "select-one"; 82 expected.max_length = 0; 83 EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[3]); 84 85 // Verify that |didAcceptAutofillSuggestion()| sends the expected number of 86 // fields. 87 WebFrame* web_frame = GetMainFrame(); 88 WebDocument document = web_frame->document(); 89 WebInputElement firstname = 90 document.getElementById("firstname").to<WebInputElement>(); 91 92 // Make sure to query for Autofill suggestions before selecting one. 93 autofill_agent_->element_ = firstname; 94 autofill_agent_->QueryAutofillSuggestions(firstname, false, false); 95 96 // Fill the form with a suggestion that contained a label. Labeled items 97 // indicate Autofill as opposed to Autocomplete. We're testing this 98 // distinction below with the |AutofillHostMsg_FillAutofillFormData::ID| 99 // message. 100 autofill_agent_->FillAutofillFormData( 101 firstname, 102 1, 103 AutofillAgent::AUTOFILL_PREVIEW); 104 105 ProcessPendingMessages(); 106 const IPC::Message* message2 = 107 render_thread_->sink().GetUniqueMessageMatching( 108 AutofillHostMsg_FillAutofillFormData::ID); 109 ASSERT_NE(static_cast<IPC::Message*>(NULL), message2); 110 AutofillHostMsg_FillAutofillFormData::Param params2; 111 AutofillHostMsg_FillAutofillFormData::Read(message2, ¶ms2); 112 const FormData& form2 = params2.b; 113 ASSERT_EQ(3UL, form2.fields.size()); 114 115 expected.name = ASCIIToUTF16("firstname"); 116 expected.value = base::string16(); 117 expected.form_control_type = "text"; 118 expected.max_length = WebInputElement::defaultMaxLength(); 119 EXPECT_FORM_FIELD_DATA_EQUALS(expected, form2.fields[0]); 120 121 expected.name = ASCIIToUTF16("middlename"); 122 expected.value = base::string16(); 123 expected.form_control_type = "text"; 124 expected.max_length = WebInputElement::defaultMaxLength(); 125 EXPECT_FORM_FIELD_DATA_EQUALS(expected, form2.fields[1]); 126 127 expected.name = ASCIIToUTF16("state"); 128 expected.value = ASCIIToUTF16("?"); 129 expected.form_control_type = "select-one"; 130 expected.max_length = 0; 131 EXPECT_FORM_FIELD_DATA_EQUALS(expected, form2.fields[2]); 132 } 133 134 TEST_F(ChromeRenderViewTest, EnsureNoFormSeenIfTooFewFields) { 135 // Don't want any delay for form state sync changes. This will still post a 136 // message so updates will get coalesced, but as soon as we spin the message 137 // loop, it will generate an update. 138 SendContentStateImmediately(); 139 140 LoadHTML("<form method=\"POST\">" 141 " <input type=\"text\" id=\"firstname\"/>" 142 " <input type=\"text\" id=\"middlename\"/>" 143 "</form>"); 144 145 // Verify that "FormsSeen" isn't sent, as there are too few fields. 146 const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching( 147 AutofillHostMsg_FormsSeen::ID); 148 ASSERT_NE(static_cast<IPC::Message*>(NULL), message); 149 AutofillHostMsg_FormsSeen::Param params; 150 AutofillHostMsg_FormsSeen::Read(message, ¶ms); 151 const std::vector<FormData>& forms = params.a; 152 ASSERT_EQ(0UL, forms.size()); 153 } 154 155 TEST_F(ChromeRenderViewTest, ShowAutofillWarning) { 156 // Don't want any delay for form state sync changes. This will still post a 157 // message so updates will get coalesced, but as soon as we spin the message 158 // loop, it will generate an update. 159 SendContentStateImmediately(); 160 161 LoadHTML("<form method=\"POST\" autocomplete=\"Off\">" 162 " <input id=\"firstname\" autocomplete=\"OFF\"/>" 163 " <input id=\"middlename\"/>" 164 " <input id=\"lastname\"/>" 165 "</form>"); 166 167 // Verify that "QueryFormFieldAutofill" isn't sent prior to a user 168 // interaction. 169 const IPC::Message* message0 = render_thread_->sink().GetFirstMessageMatching( 170 AutofillHostMsg_QueryFormFieldAutofill::ID); 171 EXPECT_EQ(static_cast<IPC::Message*>(NULL), message0); 172 173 WebFrame* web_frame = GetMainFrame(); 174 WebDocument document = web_frame->document(); 175 WebInputElement firstname = 176 document.getElementById("firstname").to<WebInputElement>(); 177 WebInputElement middlename = 178 document.getElementById("middlename").to<WebInputElement>(); 179 180 // Simulate attempting to Autofill the form from the first element, which 181 // specifies autocomplete="off". This should still trigger an IPC which 182 // shouldn't display warnings. 183 autofill_agent_->InputElementClicked(firstname, true, true); 184 const IPC::Message* message1 = render_thread_->sink().GetFirstMessageMatching( 185 AutofillHostMsg_QueryFormFieldAutofill::ID); 186 EXPECT_NE(static_cast<IPC::Message*>(NULL), message1); 187 188 AutofillQueryParam query_param; 189 AutofillHostMsg_QueryFormFieldAutofill::Read(message1, &query_param); 190 EXPECT_FALSE(query_param.e); 191 render_thread_->sink().ClearMessages(); 192 193 // Simulate attempting to Autofill the form from the second element, which 194 // does not specify autocomplete="off". This should trigger an IPC that will 195 // show warnings, as we *do* show warnings for elements that don't themselves 196 // set autocomplete="off", but for which the form does. 197 autofill_agent_->InputElementClicked(middlename, true, true); 198 const IPC::Message* message2 = render_thread_->sink().GetFirstMessageMatching( 199 AutofillHostMsg_QueryFormFieldAutofill::ID); 200 ASSERT_NE(static_cast<IPC::Message*>(NULL), message2); 201 202 AutofillHostMsg_QueryFormFieldAutofill::Read(message2, &query_param); 203 EXPECT_TRUE(query_param.e); 204 } 205 206 } // namespace autofill 207