Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(634)

Side by Side Diff: chrome/renderer/autofill/password_autofill_agent_browsertest.cc

Issue 119493004: [Password Autofill] Trigger onChange events in JavaScript when autofilling passwords. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Temporarily disable part of the test while waiting on http://crbug.com/333144 to be fixed. Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | components/autofill/content/renderer/autofill_agent.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 const char kJavaScriptClick[] = 137 const char kJavaScriptClick[] =
138 "var event = new MouseEvent('click', {" 138 "var event = new MouseEvent('click', {"
139 " 'view': window," 139 " 'view': window,"
140 " 'bubbles': true," 140 " 'bubbles': true,"
141 " 'cancelable': true" 141 " 'cancelable': true"
142 "});" 142 "});"
143 "var form = document.getElementById('myform1');" 143 "var form = document.getElementById('myform1');"
144 "form.dispatchEvent(event);" 144 "form.dispatchEvent(event);"
145 "console.log('clicked!');"; 145 "console.log('clicked!');";
146 146
147 const char kOnChangeDetectionScript[] =
148 "<script>"
149 " usernameOnchangeCalled = false;"
150 " passwordOnchangeCalled = false;"
151 " document.getElementById('username').onchange = function() {"
152 " usernameOnchangeCalled = true;"
153 " };"
154 " document.getElementById('password').onchange = function() {"
155 " passwordOnchangeCalled = true;"
156 " };"
157 "</script>";
158
147 } // namespace 159 } // namespace
148 160
149 namespace autofill { 161 namespace autofill {
150 162
151 class PasswordAutofillAgentTest : public ChromeRenderViewTest { 163 class PasswordAutofillAgentTest : public ChromeRenderViewTest {
152 public: 164 public:
153 PasswordAutofillAgentTest() { 165 PasswordAutofillAgentTest() {
154 } 166 }
155 167
156 // Simulates the fill password form message being sent to the renderer. 168 // Simulates the fill password form message being sent to the renderer.
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 fill_data_.additional_logins[username3_] = password3; 205 fill_data_.additional_logins[username3_] = password3;
194 206
195 UsernamesCollectionKey key; 207 UsernamesCollectionKey key;
196 key.username = username3_; 208 key.username = username3_;
197 key.password = password3_; 209 key.password = password3_;
198 key.realm = "google.com"; 210 key.realm = "google.com";
199 fill_data_.other_possible_usernames[key].push_back(alternate_username3_); 211 fill_data_.other_possible_usernames[key].push_back(alternate_username3_);
200 212
201 // We need to set the origin so it matches the frame URL and the action so 213 // We need to set the origin so it matches the frame URL and the action so
202 // it matches the form action, otherwise we won't autocomplete. 214 // it matches the form action, otherwise we won't autocomplete.
203 std::string origin("data:text/html;charset=utf-8,"); 215 UpdateOriginForHTML(kFormHTML);
204 origin += kFormHTML;
205 fill_data_.basic_data.origin = GURL(origin);
206 fill_data_.basic_data.action = GURL("http://www.bidule.com"); 216 fill_data_.basic_data.action = GURL("http://www.bidule.com");
207 217
208 LoadHTML(kFormHTML); 218 LoadHTML(kFormHTML);
209 219
210 // Now retrieves the input elements so the test can access them. 220 // Now retrieve the input elements so the test can access them.
221 UpdateUsernameAndPasswordElements();
222 }
223
224 virtual void TearDown() {
225 username_element_.reset();
226 password_element_.reset();
227 ChromeRenderViewTest::TearDown();
228 }
229
230 void UpdateOriginForHTML(const std::string& html) {
231 std::string origin = "data:text/html;charset=utf-8," + html;
232 fill_data_.basic_data.origin = GURL(origin);
233 }
234
235 void UpdateUsernameAndPasswordElements() {
211 WebDocument document = GetMainFrame()->document(); 236 WebDocument document = GetMainFrame()->document();
212 WebElement element = 237 WebElement element =
213 document.getElementById(WebString::fromUTF8(kUsernameName)); 238 document.getElementById(WebString::fromUTF8(kUsernameName));
214 ASSERT_FALSE(element.isNull()); 239 ASSERT_FALSE(element.isNull());
215 username_element_ = element.to<blink::WebInputElement>(); 240 username_element_ = element.to<blink::WebInputElement>();
216 element = document.getElementById(WebString::fromUTF8(kPasswordName)); 241 element = document.getElementById(WebString::fromUTF8(kPasswordName));
217 ASSERT_FALSE(element.isNull()); 242 ASSERT_FALSE(element.isNull());
218 password_element_ = element.to<blink::WebInputElement>(); 243 password_element_ = element.to<blink::WebInputElement>();
219 } 244 }
220 245
221 virtual void TearDown() {
222 username_element_.reset();
223 password_element_.reset();
224 ChromeRenderViewTest::TearDown();
225 }
226
227 void ClearUsernameAndPasswordFields() { 246 void ClearUsernameAndPasswordFields() {
228 username_element_.setValue(""); 247 username_element_.setValue("");
229 username_element_.setAutofilled(false); 248 username_element_.setAutofilled(false);
230 password_element_.setValue(""); 249 password_element_.setValue("");
231 password_element_.setAutofilled(false); 250 password_element_.setAutofilled(false);
232 } 251 }
233 252
234 void SimulateUsernameChangeForElement(const std::string& username, 253 void SimulateUsernameChangeForElement(const std::string& username,
235 bool move_caret_to_end, 254 bool move_caret_to_end,
236 WebFrame* input_frame, 255 WebFrame* input_frame,
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 WebDocument document = GetMainFrame()->document(); 414 WebDocument document = GetMainFrame()->document();
396 WebElement element = 415 WebElement element =
397 document.getElementById(WebString::fromUTF8(kUsernameName)); 416 document.getElementById(WebString::fromUTF8(kUsernameName));
398 ASSERT_FALSE(element.isNull()); 417 ASSERT_FALSE(element.isNull());
399 username_element_ = element.to<blink::WebInputElement>(); 418 username_element_ = element.to<blink::WebInputElement>();
400 element = document.getElementById(WebString::fromUTF8(kPasswordName)); 419 element = document.getElementById(WebString::fromUTF8(kPasswordName));
401 ASSERT_FALSE(element.isNull()); 420 ASSERT_FALSE(element.isNull());
402 password_element_ = element.to<blink::WebInputElement>(); 421 password_element_ = element.to<blink::WebInputElement>();
403 422
404 // Set the expected form origin and action URLs. 423 // Set the expected form origin and action URLs.
405 std::string origin("data:text/html;charset=utf-8,"); 424 UpdateOriginForHTML(kEmptyActionFormHTML);
406 origin += kEmptyActionFormHTML; 425 fill_data_.basic_data.action = fill_data_.basic_data.origin;
407 fill_data_.basic_data.origin = GURL(origin);
408 fill_data_.basic_data.action = GURL(origin);
409 426
410 // Simulate the browser sending back the login info, it triggers the 427 // Simulate the browser sending back the login info, it triggers the
411 // autocomplete. 428 // autocomplete.
412 SimulateOnFillPasswordForm(fill_data_); 429 SimulateOnFillPasswordForm(fill_data_);
413 430
414 // The username and password should have been autocompleted. 431 // The username and password should have been autocompleted.
415 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); 432 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
416 } 433 }
417 434
418 // Tests that if a password is marked as readonly, neither field is autofilled 435 // 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
500 WebDocument document = GetMainFrame()->document(); 517 WebDocument document = GetMainFrame()->document();
501 WebElement element = 518 WebElement element =
502 document.getElementById(WebString::fromUTF8(kUsernameName)); 519 document.getElementById(WebString::fromUTF8(kUsernameName));
503 ASSERT_FALSE(element.isNull()); 520 ASSERT_FALSE(element.isNull());
504 username_element_ = element.to<blink::WebInputElement>(); 521 username_element_ = element.to<blink::WebInputElement>();
505 element = document.getElementById(WebString::fromUTF8(kPasswordName)); 522 element = document.getElementById(WebString::fromUTF8(kPasswordName));
506 ASSERT_FALSE(element.isNull()); 523 ASSERT_FALSE(element.isNull());
507 password_element_ = element.to<blink::WebInputElement>(); 524 password_element_ = element.to<blink::WebInputElement>();
508 525
509 // Set the expected form origin URL. 526 // Set the expected form origin URL.
510 std::string origin("data:text/html;charset=utf-8,"); 527 UpdateOriginForHTML(kTextFieldPasswordFormHTML);
511 origin += kTextFieldPasswordFormHTML;
512 fill_data_.basic_data.origin = GURL(origin);
513 528
514 SimulateOnFillPasswordForm(fill_data_); 529 SimulateOnFillPasswordForm(fill_data_);
515 530
516 // Fields should still be empty. 531 // Fields should still be empty.
517 CheckTextFieldsState(std::string(), false, std::string(), false); 532 CheckTextFieldsState(std::string(), false, std::string(), false);
518 } 533 }
519 534
520 TEST_F(PasswordAutofillAgentTest, NoAutocompleteForPasswordFieldUsernames) { 535 TEST_F(PasswordAutofillAgentTest, NoAutocompleteForPasswordFieldUsernames) {
521 const char kPasswordFieldUsernameFormHTML[] = 536 const char kPasswordFieldUsernameFormHTML[] =
522 "<FORM name='LoginTestForm' action='http://www.bidule.com'>" 537 "<FORM name='LoginTestForm' action='http://www.bidule.com'>"
523 " <INPUT type='password' id='username'/>" 538 " <INPUT type='password' id='username'/>"
524 " <INPUT type='password' id='password'/>" 539 " <INPUT type='password' id='password'/>"
525 " <INPUT type='submit' value='Login'/>" 540 " <INPUT type='submit' value='Login'/>"
526 "</FORM>"; 541 "</FORM>";
527 LoadHTML(kPasswordFieldUsernameFormHTML); 542 LoadHTML(kPasswordFieldUsernameFormHTML);
528 543
529 // Retrieve the input elements so the test can access them. 544 // Retrieve the input elements so the test can access them.
530 WebDocument document = GetMainFrame()->document(); 545 WebDocument document = GetMainFrame()->document();
531 WebElement element = 546 WebElement element =
532 document.getElementById(WebString::fromUTF8(kUsernameName)); 547 document.getElementById(WebString::fromUTF8(kUsernameName));
533 ASSERT_FALSE(element.isNull()); 548 ASSERT_FALSE(element.isNull());
534 username_element_ = element.to<blink::WebInputElement>(); 549 username_element_ = element.to<blink::WebInputElement>();
535 element = document.getElementById(WebString::fromUTF8(kPasswordName)); 550 element = document.getElementById(WebString::fromUTF8(kPasswordName));
536 ASSERT_FALSE(element.isNull()); 551 ASSERT_FALSE(element.isNull());
537 password_element_ = element.to<blink::WebInputElement>(); 552 password_element_ = element.to<blink::WebInputElement>();
538 553
539 // Set the expected form origin URL. 554 // Set the expected form origin URL.
540 std::string origin("data:text/html;charset=utf-8,"); 555 UpdateOriginForHTML(kPasswordFieldUsernameFormHTML);
541 origin += kPasswordFieldUsernameFormHTML;
542 fill_data_.basic_data.origin = GURL(origin);
543 556
544 SimulateOnFillPasswordForm(fill_data_); 557 SimulateOnFillPasswordForm(fill_data_);
545 558
546 // Fields should still be empty. 559 // Fields should still be empty.
547 CheckTextFieldsState(std::string(), false, std::string(), false); 560 CheckTextFieldsState(std::string(), false, std::string(), false);
548 } 561 }
549 562
550 // Tests that having a matching username does not preclude the autocomplete. 563 // Tests that having a matching username does not preclude the autocomplete.
551 TEST_F(PasswordAutofillAgentTest, InitialAutocompleteForMatchingFilledField) { 564 TEST_F(PasswordAutofillAgentTest, InitialAutocompleteForMatchingFilledField) {
552 username_element_.setValue(WebString::fromUTF8(kAliceUsername)); 565 username_element_.setValue(WebString::fromUTF8(kAliceUsername));
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
805 TEST_F(PasswordAutofillAgentTest, GestureRequiredTest) { 818 TEST_F(PasswordAutofillAgentTest, GestureRequiredTest) {
806 // Trigger the initial autocomplete. 819 // Trigger the initial autocomplete.
807 SimulateOnFillPasswordForm(fill_data_); 820 SimulateOnFillPasswordForm(fill_data_);
808 821
809 // The username and password should have been autocompleted. 822 // The username and password should have been autocompleted.
810 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); 823 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
811 824
812 // However, it should only have completed with the suggested value, as tested 825 // However, it should only have completed with the suggested value, as tested
813 // above, and it should not have completed into the DOM accessible value for 826 // above, and it should not have completed into the DOM accessible value for
814 // the password field. 827 // the password field.
815 CheckTextFieldsDOMState(kAliceUsername, true, "", true); 828 CheckTextFieldsDOMState(kAliceUsername, true, std::string(), true);
816 829
817 // Simulate a user click so that the password field's real value is filled. 830 // Simulate a user click so that the password field's real value is filled.
818 SimulateElementClick(kUsernameName); 831 SimulateElementClick(kUsernameName);
819 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); 832 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true);
820 } 833 }
821 834
822 // Verfies that a DOM-activated UI event will not cause an autofill. 835 // Verfies that a DOM-activated UI event will not cause an autofill.
823 TEST_F(PasswordAutofillAgentTest, NoDOMActivationTest) { 836 TEST_F(PasswordAutofillAgentTest, NoDOMActivationTest) {
824 // Trigger the initial autocomplete. 837 // Trigger the initial autocomplete.
825 SimulateOnFillPasswordForm(fill_data_); 838 SimulateOnFillPasswordForm(fill_data_);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
861 874
862 // Regression test for http://crbug.com/326679 875 // Regression test for http://crbug.com/326679
863 TEST_F(PasswordAutofillAgentTest, SelectUsernameWithPasswordAutofillOff) { 876 TEST_F(PasswordAutofillAgentTest, SelectUsernameWithPasswordAutofillOff) {
864 // Simulate the browser sending back the login info. 877 // Simulate the browser sending back the login info.
865 SimulateOnFillPasswordForm(fill_data_); 878 SimulateOnFillPasswordForm(fill_data_);
866 879
867 // Set the main password element to autocomplete='off' 880 // Set the main password element to autocomplete='off'
868 password_element_.setAttribute(WebString::fromUTF8("autocomplete"), 881 password_element_.setAttribute(WebString::fromUTF8("autocomplete"),
869 WebString::fromUTF8("off")); 882 WebString::fromUTF8("off"));
870 883
871 // Simulate the user changing the username to some known username. 884 // Simulate the user changing the username to some known username.
872 SimulateUsernameChange(kAliceUsername, true); 885 SimulateUsernameChange(kAliceUsername, true);
873 886
874 ExpectNoSuggestionsPopup(); 887 ExpectNoSuggestionsPopup();
875 } 888 }
876 889
877 // Regression test for http://crbug.com/326679 890 // Regression test for http://crbug.com/326679
878 TEST_F(PasswordAutofillAgentTest, 891 TEST_F(PasswordAutofillAgentTest,
879 SelectUnknownUsernameWithPasswordAutofillOff) { 892 SelectUnknownUsernameWithPasswordAutofillOff) {
880 // Simulate the browser sending back the login info. 893 // Simulate the browser sending back the login info.
881 SimulateOnFillPasswordForm(fill_data_); 894 SimulateOnFillPasswordForm(fill_data_);
882 895
883 // Set the main password element to autocomplete='off' 896 // Set the main password element to autocomplete='off'
884 password_element_.setAttribute(WebString::fromUTF8("autocomplete"), 897 password_element_.setAttribute(WebString::fromUTF8("autocomplete"),
885 WebString::fromUTF8("off")); 898 WebString::fromUTF8("off"));
886 899
887 // Simulate the user changing the username to some unknown username. 900 // Simulate the user changing the username to some unknown username.
888 SimulateUsernameChange("foo", true); 901 SimulateUsernameChange("foo", true);
889 902
890 ExpectNoSuggestionsPopup(); 903 ExpectNoSuggestionsPopup();
891 } 904 }
892 905
906 // Verifies that password autofill triggers onChange events in JavaScript for
907 // forms that are filled on page load.
908 TEST_F(PasswordAutofillAgentTest,
909 PasswordAutofillTriggersOnChangeEventsOnLoad) {
910 std::string html = std::string(kFormHTML) + kOnChangeDetectionScript;
911 LoadHTML(html.c_str());
912 UpdateOriginForHTML(html);
913 UpdateUsernameAndPasswordElements();
914
915 // Simulate the browser sending back the login info, it triggers the
916 // autocomplete.
917 SimulateOnFillPasswordForm(fill_data_);
918
919 // The username and password should have been autocompleted...
920 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
921 // ... but since there hasn't been a user gesture yet, the autocompleted
922 // password should only be visible to the user.
923 CheckTextFieldsDOMState(kAliceUsername, true, std::string(), true);
924
925 // A JavaScript onChange event should have been triggered for the username,
926 // but not yet for the password.
927 int username_onchange_called = -1;
928 int password_onchange_called = -1;
929 ASSERT_TRUE(
930 ExecuteJavaScriptAndReturnIntValue(
931 ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"),
932 &username_onchange_called));
933 EXPECT_EQ(1, username_onchange_called);
934 ASSERT_TRUE(
935 ExecuteJavaScriptAndReturnIntValue(
936 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"),
937 &password_onchange_called));
938 // TODO(isherman): Re-enable this check once http://crbug.com/333144 is fixed.
939 // EXPECT_EQ(0, password_onchange_called);
940
941 // Simulate a user click so that the password field's real value is filled.
942 SimulateElementClick(kUsernameName);
943 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true);
944
945 // Now, a JavaScript onChange event should have been triggered for the
946 // password as well.
947 ASSERT_TRUE(
948 ExecuteJavaScriptAndReturnIntValue(
949 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"),
950 &password_onchange_called));
951 EXPECT_EQ(1, password_onchange_called);
952 }
953
954 // Verifies that password autofill triggers onChange events in JavaScript for
955 // forms that are filled after page load.
956 TEST_F(PasswordAutofillAgentTest,
957 PasswordAutofillTriggersOnChangeEventsWaitForUsername) {
958 std::string html = std::string(kFormHTML) + kOnChangeDetectionScript;
959 LoadHTML(html.c_str());
960 UpdateOriginForHTML(html);
961 UpdateUsernameAndPasswordElements();
962
963 // Simulate the browser sending back the login info, it triggers the
964 // autocomplete.
965 fill_data_.wait_for_username = true;
966 SimulateOnFillPasswordForm(fill_data_);
967
968 // The username and password should not yet have been autocompleted.
969 CheckTextFieldsState(std::string(), false, std::string(), false);
970
971 // Simulate a click just to force a user gesture, since the username value is
972 // set directly.
973 SimulateElementClick(kUsernameName);
974
975 // Simulate the user entering her username.
976 username_element_.setValue(ASCIIToUTF16(kAliceUsername), true);
977 autofill_agent_->textFieldDidEndEditing(username_element_);
978
979 // The username and password should now have been autocompleted.
980 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true);
981
982 // JavaScript onChange events should have been triggered both for the username
983 // and for the password.
984 int username_onchange_called = -1;
985 int password_onchange_called = -1;
986 ASSERT_TRUE(
987 ExecuteJavaScriptAndReturnIntValue(
988 ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"),
989 &username_onchange_called));
990 EXPECT_EQ(1, username_onchange_called);
991 ASSERT_TRUE(
992 ExecuteJavaScriptAndReturnIntValue(
993 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"),
994 &password_onchange_called));
995 EXPECT_EQ(1, password_onchange_called);
996 }
997
893 } // namespace autofill 998 } // namespace autofill
OLDNEW
« no previous file with comments | « no previous file | components/autofill/content/renderer/autofill_agent.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698