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

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: Created 7 years 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 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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