OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/strings/string_util.h" | 5 #include "base/strings/string_util.h" |
6 #include "base/strings/utf_string_conversions.h" | 6 #include "base/strings/utf_string_conversions.h" |
7 #include "chrome/test/base/chrome_render_view_test.h" | 7 #include "chrome/test/base/chrome_render_view_test.h" |
8 #include "components/autofill/content/common/autofill_messages.h" | 8 #include "components/autofill/content/common/autofill_messages.h" |
9 #include "components/autofill/content/renderer/autofill_agent.h" | 9 #include "components/autofill/content/renderer/autofill_agent.h" |
10 #include "components/autofill/content/renderer/form_autofill_util.h" | 10 #include "components/autofill/content/renderer/form_autofill_util.h" |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
135 const char kJavaScriptClick[] = | 135 const char kJavaScriptClick[] = |
136 "var event = new MouseEvent('click', {" | 136 "var event = new MouseEvent('click', {" |
137 " 'view': window," | 137 " 'view': window," |
138 " 'bubbles': true," | 138 " 'bubbles': true," |
139 " 'cancelable': true" | 139 " 'cancelable': true" |
140 "});" | 140 "});" |
141 "var form = document.getElementById('myform1');" | 141 "var form = document.getElementById('myform1');" |
142 "form.dispatchEvent(event);" | 142 "form.dispatchEvent(event);" |
143 "console.log('clicked!');"; | 143 "console.log('clicked!');"; |
144 | 144 |
145 const char kOnChangeDetectionScript[] = | |
146 "<script>" | |
147 " usernameOnchangeCalled = false;" | |
148 " passwordOnchangeCalled = false;" | |
149 " document.getElementById('username').onchange = function() {" | |
150 " usernameOnchangeCalled = true;" | |
151 " };" | |
152 " document.getElementById('password').onchange = function() {" | |
153 " passwordOnchangeCalled = true;" | |
154 " };" | |
155 "</script>"; | |
156 | |
145 } // namespace | 157 } // namespace |
146 | 158 |
147 namespace autofill { | 159 namespace autofill { |
148 | 160 |
149 class PasswordAutofillAgentTest : public ChromeRenderViewTest { | 161 class PasswordAutofillAgentTest : public ChromeRenderViewTest { |
150 public: | 162 public: |
151 PasswordAutofillAgentTest() { | 163 PasswordAutofillAgentTest() { |
152 } | 164 } |
153 | 165 |
154 // Simulates the fill password form message being sent to the renderer. | 166 // Simulates the fill password form message being sent to the renderer. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
191 fill_data_.additional_logins[username3_] = password3; | 203 fill_data_.additional_logins[username3_] = password3; |
192 | 204 |
193 UsernamesCollectionKey key; | 205 UsernamesCollectionKey key; |
194 key.username = username3_; | 206 key.username = username3_; |
195 key.password = password3_; | 207 key.password = password3_; |
196 key.realm = "google.com"; | 208 key.realm = "google.com"; |
197 fill_data_.other_possible_usernames[key].push_back(alternate_username3_); | 209 fill_data_.other_possible_usernames[key].push_back(alternate_username3_); |
198 | 210 |
199 // We need to set the origin so it matches the frame URL and the action so | 211 // We need to set the origin so it matches the frame URL and the action so |
200 // it matches the form action, otherwise we won't autocomplete. | 212 // it matches the form action, otherwise we won't autocomplete. |
201 std::string origin("data:text/html;charset=utf-8,"); | 213 UpdateOriginForHTML(kFormHTML); |
202 origin += kFormHTML; | |
203 fill_data_.basic_data.origin = GURL(origin); | |
204 fill_data_.basic_data.action = GURL("http://www.bidule.com"); | 214 fill_data_.basic_data.action = GURL("http://www.bidule.com"); |
205 | 215 |
206 LoadHTML(kFormHTML); | 216 LoadHTML(kFormHTML); |
207 | 217 |
208 // Now retrieves the input elements so the test can access them. | 218 // Now retrieve the input elements so the test can access them. |
219 UpdateUsernameAndPasswordElements(); | |
220 } | |
221 | |
222 virtual void TearDown() { | |
223 username_element_.reset(); | |
224 password_element_.reset(); | |
225 ChromeRenderViewTest::TearDown(); | |
226 } | |
227 | |
228 void UpdateOriginForHTML(const std::string& html) { | |
229 std::string origin = "data:text/html;charset=utf-8," + html; | |
230 fill_data_.basic_data.origin = GURL(origin); | |
231 } | |
232 | |
233 void UpdateUsernameAndPasswordElements() { | |
209 WebDocument document = GetMainFrame()->document(); | 234 WebDocument document = GetMainFrame()->document(); |
210 WebElement element = | 235 WebElement element = |
211 document.getElementById(WebString::fromUTF8(kUsernameName)); | 236 document.getElementById(WebString::fromUTF8(kUsernameName)); |
212 ASSERT_FALSE(element.isNull()); | 237 ASSERT_FALSE(element.isNull()); |
213 username_element_ = element.to<blink::WebInputElement>(); | 238 username_element_ = element.to<blink::WebInputElement>(); |
214 element = document.getElementById(WebString::fromUTF8(kPasswordName)); | 239 element = document.getElementById(WebString::fromUTF8(kPasswordName)); |
215 ASSERT_FALSE(element.isNull()); | 240 ASSERT_FALSE(element.isNull()); |
216 password_element_ = element.to<blink::WebInputElement>(); | 241 password_element_ = element.to<blink::WebInputElement>(); |
217 } | 242 } |
218 | 243 |
219 virtual void TearDown() { | |
220 username_element_.reset(); | |
221 password_element_.reset(); | |
222 ChromeRenderViewTest::TearDown(); | |
223 } | |
224 | |
225 void ClearUsernameAndPasswordFields() { | 244 void ClearUsernameAndPasswordFields() { |
226 username_element_.setValue(""); | 245 username_element_.setValue(""); |
227 username_element_.setAutofilled(false); | 246 username_element_.setAutofilled(false); |
228 password_element_.setValue(""); | 247 password_element_.setValue(""); |
229 password_element_.setAutofilled(false); | 248 password_element_.setAutofilled(false); |
230 } | 249 } |
231 | 250 |
232 void SimulateUsernameChangeForElement(const std::string& username, | 251 void SimulateUsernameChangeForElement(const std::string& username, |
233 bool move_caret_to_end, | 252 bool move_caret_to_end, |
234 WebFrame* input_frame, | 253 WebFrame* input_frame, |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
371 WebDocument document = GetMainFrame()->document(); | 390 WebDocument document = GetMainFrame()->document(); |
372 WebElement element = | 391 WebElement element = |
373 document.getElementById(WebString::fromUTF8(kUsernameName)); | 392 document.getElementById(WebString::fromUTF8(kUsernameName)); |
374 ASSERT_FALSE(element.isNull()); | 393 ASSERT_FALSE(element.isNull()); |
375 username_element_ = element.to<blink::WebInputElement>(); | 394 username_element_ = element.to<blink::WebInputElement>(); |
376 element = document.getElementById(WebString::fromUTF8(kPasswordName)); | 395 element = document.getElementById(WebString::fromUTF8(kPasswordName)); |
377 ASSERT_FALSE(element.isNull()); | 396 ASSERT_FALSE(element.isNull()); |
378 password_element_ = element.to<blink::WebInputElement>(); | 397 password_element_ = element.to<blink::WebInputElement>(); |
379 | 398 |
380 // Set the expected form origin and action URLs. | 399 // Set the expected form origin and action URLs. |
381 std::string origin("data:text/html;charset=utf-8,"); | 400 UpdateOriginForHTML(kEmptyActionFormHTML); |
382 origin += kEmptyActionFormHTML; | 401 fill_data_.basic_data.action = fill_data_.basic_data.origin; |
383 fill_data_.basic_data.origin = GURL(origin); | |
384 fill_data_.basic_data.action = GURL(origin); | |
385 | 402 |
386 // Simulate the browser sending back the login info, it triggers the | 403 // Simulate the browser sending back the login info, it triggers the |
387 // autocomplete. | 404 // autocomplete. |
388 SimulateOnFillPasswordForm(fill_data_); | 405 SimulateOnFillPasswordForm(fill_data_); |
389 | 406 |
390 // The username and password should have been autocompleted. | 407 // The username and password should have been autocompleted. |
391 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); | 408 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); |
392 } | 409 } |
393 | 410 |
394 // Tests that if a password is marked as readonly, neither field is autofilled | 411 // Tests that if a password is marked as readonly, neither field is autofilled |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
476 WebDocument document = GetMainFrame()->document(); | 493 WebDocument document = GetMainFrame()->document(); |
477 WebElement element = | 494 WebElement element = |
478 document.getElementById(WebString::fromUTF8(kUsernameName)); | 495 document.getElementById(WebString::fromUTF8(kUsernameName)); |
479 ASSERT_FALSE(element.isNull()); | 496 ASSERT_FALSE(element.isNull()); |
480 username_element_ = element.to<blink::WebInputElement>(); | 497 username_element_ = element.to<blink::WebInputElement>(); |
481 element = document.getElementById(WebString::fromUTF8(kPasswordName)); | 498 element = document.getElementById(WebString::fromUTF8(kPasswordName)); |
482 ASSERT_FALSE(element.isNull()); | 499 ASSERT_FALSE(element.isNull()); |
483 password_element_ = element.to<blink::WebInputElement>(); | 500 password_element_ = element.to<blink::WebInputElement>(); |
484 | 501 |
485 // Set the expected form origin URL. | 502 // Set the expected form origin URL. |
486 std::string origin("data:text/html;charset=utf-8,"); | 503 UpdateOriginForHTML(kTextFieldPasswordFormHTML); |
487 origin += kTextFieldPasswordFormHTML; | |
488 fill_data_.basic_data.origin = GURL(origin); | |
489 | 504 |
490 SimulateOnFillPasswordForm(fill_data_); | 505 SimulateOnFillPasswordForm(fill_data_); |
491 | 506 |
492 // Fields should still be empty. | 507 // Fields should still be empty. |
493 CheckTextFieldsState(std::string(), false, std::string(), false); | 508 CheckTextFieldsState(std::string(), false, std::string(), false); |
494 } | 509 } |
495 | 510 |
496 TEST_F(PasswordAutofillAgentTest, NoAutocompleteForPasswordFieldUsernames) { | 511 TEST_F(PasswordAutofillAgentTest, NoAutocompleteForPasswordFieldUsernames) { |
497 const char kPasswordFieldUsernameFormHTML[] = | 512 const char kPasswordFieldUsernameFormHTML[] = |
498 "<FORM name='LoginTestForm' action='http://www.bidule.com'>" | 513 "<FORM name='LoginTestForm' action='http://www.bidule.com'>" |
499 " <INPUT type='password' id='username'/>" | 514 " <INPUT type='password' id='username'/>" |
500 " <INPUT type='password' id='password'/>" | 515 " <INPUT type='password' id='password'/>" |
501 " <INPUT type='submit' value='Login'/>" | 516 " <INPUT type='submit' value='Login'/>" |
502 "</FORM>"; | 517 "</FORM>"; |
503 LoadHTML(kPasswordFieldUsernameFormHTML); | 518 LoadHTML(kPasswordFieldUsernameFormHTML); |
504 | 519 |
505 // Retrieve the input elements so the test can access them. | 520 // Retrieve the input elements so the test can access them. |
506 WebDocument document = GetMainFrame()->document(); | 521 WebDocument document = GetMainFrame()->document(); |
507 WebElement element = | 522 WebElement element = |
508 document.getElementById(WebString::fromUTF8(kUsernameName)); | 523 document.getElementById(WebString::fromUTF8(kUsernameName)); |
509 ASSERT_FALSE(element.isNull()); | 524 ASSERT_FALSE(element.isNull()); |
510 username_element_ = element.to<blink::WebInputElement>(); | 525 username_element_ = element.to<blink::WebInputElement>(); |
511 element = document.getElementById(WebString::fromUTF8(kPasswordName)); | 526 element = document.getElementById(WebString::fromUTF8(kPasswordName)); |
512 ASSERT_FALSE(element.isNull()); | 527 ASSERT_FALSE(element.isNull()); |
513 password_element_ = element.to<blink::WebInputElement>(); | 528 password_element_ = element.to<blink::WebInputElement>(); |
514 | 529 |
515 // Set the expected form origin URL. | 530 // Set the expected form origin URL. |
516 std::string origin("data:text/html;charset=utf-8,"); | 531 UpdateOriginForHTML(kPasswordFieldUsernameFormHTML); |
517 origin += kPasswordFieldUsernameFormHTML; | |
518 fill_data_.basic_data.origin = GURL(origin); | |
519 | 532 |
520 SimulateOnFillPasswordForm(fill_data_); | 533 SimulateOnFillPasswordForm(fill_data_); |
521 | 534 |
522 // Fields should still be empty. | 535 // Fields should still be empty. |
523 CheckTextFieldsState(std::string(), false, std::string(), false); | 536 CheckTextFieldsState(std::string(), false, std::string(), false); |
524 } | 537 } |
525 | 538 |
526 // Tests that having a matching username does not preclude the autocomplete. | 539 // Tests that having a matching username does not preclude the autocomplete. |
527 TEST_F(PasswordAutofillAgentTest, InitialAutocompleteForMatchingFilledField) { | 540 TEST_F(PasswordAutofillAgentTest, InitialAutocompleteForMatchingFilledField) { |
528 username_element_.setValue(WebString::fromUTF8(kAliceUsername)); | 541 username_element_.setValue(WebString::fromUTF8(kAliceUsername)); |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
800 TEST_F(PasswordAutofillAgentTest, GestureRequiredTest) { | 813 TEST_F(PasswordAutofillAgentTest, GestureRequiredTest) { |
801 // Trigger the initial autocomplete. | 814 // Trigger the initial autocomplete. |
802 SimulateOnFillPasswordForm(fill_data_); | 815 SimulateOnFillPasswordForm(fill_data_); |
803 | 816 |
804 // The username and password should have been autocompleted. | 817 // The username and password should have been autocompleted. |
805 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); | 818 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); |
806 | 819 |
807 // However, it should only have completed with the suggested value, as tested | 820 // However, it should only have completed with the suggested value, as tested |
808 // above, and it should not have completed into the DOM accessible value for | 821 // above, and it should not have completed into the DOM accessible value for |
809 // the password field. | 822 // the password field. |
810 CheckTextFieldsDOMState(kAliceUsername, true, "", true); | 823 CheckTextFieldsDOMState(kAliceUsername, true, std::string(), true); |
811 | 824 |
812 // Simulate a user click so that the password field's real value is filled. | 825 // Simulate a user click so that the password field's real value is filled. |
813 SimulateElementClick(kUsernameName); | 826 SimulateElementClick(kUsernameName); |
814 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); | 827 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); |
815 } | 828 } |
816 | 829 |
817 // Verfies that a DOM-activated UI event will not cause an autofill. | 830 // Verfies that a DOM-activated UI event will not cause an autofill. |
818 TEST_F(PasswordAutofillAgentTest, NoDOMActivationTest) { | 831 TEST_F(PasswordAutofillAgentTest, NoDOMActivationTest) { |
819 // Trigger the initial autocomplete. | 832 // Trigger the initial autocomplete. |
820 SimulateOnFillPasswordForm(fill_data_); | 833 SimulateOnFillPasswordForm(fill_data_); |
821 | 834 |
822 ExecuteJavaScript(kJavaScriptClick); | 835 ExecuteJavaScript(kJavaScriptClick); |
823 CheckTextFieldsDOMState(kAliceUsername, true, "", true); | 836 CheckTextFieldsDOMState(kAliceUsername, true, "", true); |
824 } | 837 } |
825 | 838 |
839 // Verifies that password autofill triggers onChange events in JavaScript for | |
840 // forms that are filled on page load. | |
841 TEST_F(PasswordAutofillAgentTest, | |
842 PasswordAutofillTriggersOnChangeEventsOnLoad) { | |
843 std::string html = std::string(kFormHTML) + kOnChangeDetectionScript; | |
844 LoadHTML(html.c_str()); | |
845 UpdateOriginForHTML(html); | |
846 UpdateUsernameAndPasswordElements(); | |
847 | |
848 // Simulate the browser sending back the login info, it triggers the | |
849 // autocomplete. | |
850 SimulateOnFillPasswordForm(fill_data_); | |
851 | |
852 // The username and password should have been autocompleted... | |
853 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); | |
854 // ... but since there hasn't been a user gesture yet, the autocompleted | |
855 // password should only be visible to the user. | |
856 CheckTextFieldsDOMState(kAliceUsername, true, std::string(), true); | |
857 | |
858 | |
Garrett Casto
2014/01/09 19:14:32
Extra space.
Ilya Sherman
2014/01/10 06:32:49
Done.
| |
859 // A JavaScript onChange event should have been triggered for the username, | |
860 // but not yet for the password. | |
861 int username_onchange_called = -1; | |
862 int password_onchange_called = -1; | |
863 ASSERT_TRUE( | |
864 ExecuteJavaScriptAndReturnIntValue( | |
865 ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"), | |
866 &username_onchange_called)); | |
867 EXPECT_EQ(1, username_onchange_called); | |
868 ASSERT_TRUE( | |
869 ExecuteJavaScriptAndReturnIntValue( | |
870 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"), | |
871 &password_onchange_called)); | |
872 EXPECT_EQ(0, password_onchange_called); | |
873 | |
874 // Simulate a user click so that the password field's real value is filled. | |
875 SimulateElementClick(kUsernameName); | |
876 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); | |
877 | |
878 // Now, a JavaScript onChange event should have been triggered for the | |
879 // password as well. | |
880 ASSERT_TRUE( | |
881 ExecuteJavaScriptAndReturnIntValue( | |
882 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"), | |
883 &password_onchange_called)); | |
884 EXPECT_EQ(1, password_onchange_called); | |
885 } | |
886 | |
887 // Verifies that password autofill triggers onChange events in JavaScript for | |
888 // forms that are filled after page load. | |
889 TEST_F(PasswordAutofillAgentTest, | |
890 PasswordAutofillTriggersOnChangeEventsWaitForUsername) { | |
891 std::string html = std::string(kFormHTML) + kOnChangeDetectionScript; | |
892 LoadHTML(html.c_str()); | |
893 UpdateOriginForHTML(html); | |
894 UpdateUsernameAndPasswordElements(); | |
895 | |
896 // Simulate the browser sending back the login info, it triggers the | |
897 // autocomplete. | |
898 fill_data_.wait_for_username = true; | |
899 SimulateOnFillPasswordForm(fill_data_); | |
900 | |
901 // The username and password should not yet have been autocompleted. | |
902 CheckTextFieldsState(std::string(), false, std::string(), false); | |
903 | |
904 // Simulate a click just to force a user gesture, since the username value is | |
905 // set directly. | |
906 SimulateElementClick(kUsernameName); | |
907 | |
908 // Simulate the user entering her username. | |
909 username_element_.setValue(ASCIIToUTF16(kAliceUsername), true); | |
910 autofill_agent_->textFieldDidEndEditing(username_element_); | |
911 | |
912 // The username and password should now have been autocompleted. | |
913 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); | |
914 | |
915 // JavaScript onChange events should have been triggered both for the username | |
916 // and for the password. | |
917 int username_onchange_called = -1; | |
918 int password_onchange_called = -1; | |
919 ASSERT_TRUE( | |
920 ExecuteJavaScriptAndReturnIntValue( | |
921 ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"), | |
922 &username_onchange_called)); | |
923 EXPECT_EQ(1, username_onchange_called); | |
924 ASSERT_TRUE( | |
925 ExecuteJavaScriptAndReturnIntValue( | |
926 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"), | |
927 &password_onchange_called)); | |
928 EXPECT_EQ(1, password_onchange_called); | |
929 } | |
930 | |
826 } // namespace autofill | 931 } // namespace autofill |
OLD | NEW |