Chromium Code Reviews| 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 "components/autofill/content/renderer/password_autofill_agent.h" | 5 #include "components/autofill/content/renderer/password_autofill_agent.h" |
| 6 | 6 |
| 7 #include "base/macros.h" | 7 #include "base/macros.h" |
| 8 #include "base/run_loop.h" | 8 #include "base/run_loop.h" |
| 9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
| 10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 170 const char kJavaScriptClick[] = | 170 const char kJavaScriptClick[] = |
| 171 "var event = new MouseEvent('click', {" | 171 "var event = new MouseEvent('click', {" |
| 172 " 'view': window," | 172 " 'view': window," |
| 173 " 'bubbles': true," | 173 " 'bubbles': true," |
| 174 " 'cancelable': true" | 174 " 'cancelable': true" |
| 175 "});" | 175 "});" |
| 176 "var form = document.getElementById('myform1');" | 176 "var form = document.getElementById('myform1');" |
| 177 "form.dispatchEvent(event);" | 177 "form.dispatchEvent(event);" |
| 178 "console.log('clicked!');"; | 178 "console.log('clicked!');"; |
| 179 | 179 |
| 180 const char kOnChangeDetectionScript[] = | |
| 181 "<script>" | |
| 182 " usernameOnchangeCalled = false;" | |
| 183 " passwordOnchangeCalled = false;" | |
| 184 " document.getElementById('username').onchange = function() {" | |
| 185 " usernameOnchangeCalled = true;" | |
| 186 " };" | |
| 187 " document.getElementById('password').onchange = function() {" | |
| 188 " passwordOnchangeCalled = true;" | |
| 189 " };" | |
| 190 "</script>"; | |
| 191 | |
| 192 const char kFormHTMLWithTwoTextFields[] = | 180 const char kFormHTMLWithTwoTextFields[] = |
| 193 "<FORM name='LoginTestForm' id='LoginTestForm' " | 181 "<FORM name='LoginTestForm' id='LoginTestForm' " |
| 194 "action='http://www.bidule.com'>" | 182 "action='http://www.bidule.com'>" |
| 195 " <INPUT type='text' id='username'/>" | 183 " <INPUT type='text' id='username'/>" |
| 196 " <INPUT type='text' id='email'/>" | 184 " <INPUT type='text' id='email'/>" |
| 197 " <INPUT type='password' id='password'/>" | 185 " <INPUT type='password' id='password'/>" |
| 198 " <INPUT type='submit' value='Login'/>" | 186 " <INPUT type='submit' value='Login'/>" |
| 199 "</FORM>"; | 187 "</FORM>"; |
| 200 | 188 |
| 201 const char kPasswordChangeFormHTML[] = | 189 const char kPasswordChangeFormHTML[] = |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 544 ASSERT_TRUE(fake_driver_.called_inpage_navigation()); | 532 ASSERT_TRUE(fake_driver_.called_inpage_navigation()); |
| 545 ASSERT_TRUE( | 533 ASSERT_TRUE( |
| 546 static_cast<bool>(fake_driver_.password_form_inpage_navigation())); | 534 static_cast<bool>(fake_driver_.password_form_inpage_navigation())); |
| 547 const autofill::PasswordForm& form = | 535 const autofill::PasswordForm& form = |
| 548 *(fake_driver_.password_form_inpage_navigation()); | 536 *(fake_driver_.password_form_inpage_navigation()); |
| 549 EXPECT_EQ(ASCIIToUTF16(username_value), form.username_value); | 537 EXPECT_EQ(ASCIIToUTF16(username_value), form.username_value); |
| 550 EXPECT_EQ(ASCIIToUTF16(password_value), form.password_value); | 538 EXPECT_EQ(ASCIIToUTF16(password_value), form.password_value); |
| 551 EXPECT_EQ(ASCIIToUTF16(new_password_value), form.new_password_value); | 539 EXPECT_EQ(ASCIIToUTF16(new_password_value), form.new_password_value); |
| 552 } | 540 } |
| 553 | 541 |
| 542 void CheckIfEventsAreCalled(const std::vector<base::string16>& checkers, | |
| 543 bool expected) { | |
| 544 for (const base::string16& variable : checkers) { | |
| 545 int value; | |
| 546 EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(variable, &value)) | |
| 547 << variable; | |
| 548 EXPECT_EQ(expected, value == 1) << variable; | |
| 549 } | |
| 550 } | |
| 551 | |
| 554 bool GetCalledShowPasswordGenerationPopup() { | 552 bool GetCalledShowPasswordGenerationPopup() { |
| 555 fake_pw_client_.Flush(); | 553 fake_pw_client_.Flush(); |
| 556 return fake_pw_client_.called_show_pw_generation_popup(); | 554 return fake_pw_client_.called_show_pw_generation_popup(); |
| 557 } | 555 } |
| 558 | 556 |
| 559 void BindPasswordManagerDriver(mojo::ScopedMessagePipeHandle handle) { | 557 void BindPasswordManagerDriver(mojo::ScopedMessagePipeHandle handle) { |
| 560 fake_driver_.BindRequest( | 558 fake_driver_.BindRequest( |
| 561 mojo::MakeRequest<mojom::PasswordManagerDriver>(std::move(handle))); | 559 mojo::MakeRequest<mojom::PasswordManagerDriver>(std::move(handle))); |
| 562 } | 560 } |
| 563 | 561 |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 908 | 906 |
| 909 // Verfies that a DOM-activated UI event will not cause an autofill. | 907 // Verfies that a DOM-activated UI event will not cause an autofill. |
| 910 TEST_F(PasswordAutofillAgentTest, NoDOMActivationTest) { | 908 TEST_F(PasswordAutofillAgentTest, NoDOMActivationTest) { |
| 911 // Trigger the initial autocomplete. | 909 // Trigger the initial autocomplete. |
| 912 SimulateOnFillPasswordForm(fill_data_); | 910 SimulateOnFillPasswordForm(fill_data_); |
| 913 | 911 |
| 914 ExecuteJavaScriptForTests(kJavaScriptClick); | 912 ExecuteJavaScriptForTests(kJavaScriptClick); |
| 915 CheckTextFieldsDOMState(kAliceUsername, true, "", true); | 913 CheckTextFieldsDOMState(kAliceUsername, true, "", true); |
| 916 } | 914 } |
| 917 | 915 |
| 918 // Verifies that password autofill triggers onChange events in JavaScript for | 916 // Verifies that password autofill triggers events in JavaScript for forms that |
| 919 // forms that are filled on page load. | 917 // are filled on page load. |
| 920 TEST_F(PasswordAutofillAgentTest, | 918 TEST_F(PasswordAutofillAgentTest, |
| 921 PasswordAutofillTriggersOnChangeEventsOnLoad) { | 919 PasswordAutofillTriggersOnChangeEventsOnLoad) { |
| 922 std::string html = std::string(kFormHTML) + kOnChangeDetectionScript; | 920 std::vector<base::string16> username_event_checkers; |
| 921 std::vector<base::string16> password_event_checkers; | |
| 922 std::string events_registration_script = | |
| 923 CreateScriptToRegisterListeners(kUsernameName, &username_event_checkers) + | |
| 924 CreateScriptToRegisterListeners(kPasswordName, &password_event_checkers); | |
| 925 std::string html = std::string(kFormHTML) + events_registration_script; | |
| 923 LoadHTML(html.c_str()); | 926 LoadHTML(html.c_str()); |
| 924 UpdateOriginForHTML(html); | 927 UpdateOriginForHTML(html); |
| 925 UpdateUsernameAndPasswordElements(); | 928 UpdateUsernameAndPasswordElements(); |
| 926 | 929 |
| 927 // Simulate the browser sending back the login info, it triggers the | 930 // Simulate the browser sending back the login info, it triggers the |
| 928 // autocomplete. | 931 // autocomplete. |
| 929 SimulateOnFillPasswordForm(fill_data_); | 932 SimulateOnFillPasswordForm(fill_data_); |
| 930 | 933 |
| 931 // The username and password should have been autocompleted... | 934 // The username and password should have been autocompleted... |
| 932 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); | 935 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); |
| 933 // ... but since there hasn't been a user gesture yet, the autocompleted | 936 // ... but since there hasn't been a user gesture yet, the autocompleted |
| 934 // password should only be visible to the user. | 937 // password should only be visible to the user. |
| 935 CheckTextFieldsDOMState(kAliceUsername, true, std::string(), true); | 938 CheckTextFieldsDOMState(kAliceUsername, true, std::string(), true); |
| 936 | 939 |
| 937 // A JavaScript onChange event should have been triggered for the username, | 940 // A JavaScript events should have been triggered for the username, but not |
|
vabr (Chromium)
2017/03/21 07:57:30
nit: Remove "A": A JavaScript events -> JavaScript
kolos1
2017/03/21 08:29:21
Done.
| |
| 938 // but not yet for the password. | 941 // yet for the password. |
| 939 int username_onchange_called = -1; | 942 CheckIfEventsAreCalled(username_event_checkers, true); |
| 940 int password_onchange_called = -1; | 943 CheckIfEventsAreCalled(password_event_checkers, false); |
| 941 ASSERT_TRUE( | |
| 942 ExecuteJavaScriptAndReturnIntValue( | |
| 943 ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"), | |
| 944 &username_onchange_called)); | |
| 945 EXPECT_EQ(1, username_onchange_called); | |
| 946 ASSERT_TRUE( | |
| 947 ExecuteJavaScriptAndReturnIntValue( | |
| 948 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"), | |
| 949 &password_onchange_called)); | |
| 950 // TODO(isherman): Re-enable this check once http://crbug.com/333144 is fixed. | |
| 951 // EXPECT_EQ(0, password_onchange_called); | |
| 952 | 944 |
| 953 // Simulate a user click so that the password field's real value is filled. | 945 // Simulate a user click so that the password field's real value is filled. |
| 954 SimulateElementClick(kUsernameName); | 946 SimulateElementClick(kUsernameName); |
| 955 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); | 947 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); |
| 956 | 948 |
| 957 // Now, a JavaScript onChange event should have been triggered for the | 949 // Now, JavaScript events should have been triggered for the password as well. |
| 958 // password as well. | 950 CheckIfEventsAreCalled(password_event_checkers, true); |
| 959 ASSERT_TRUE( | |
| 960 ExecuteJavaScriptAndReturnIntValue( | |
| 961 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"), | |
| 962 &password_onchange_called)); | |
| 963 EXPECT_EQ(1, password_onchange_called); | |
| 964 } | 951 } |
| 965 | 952 |
| 966 // Verifies that password autofill triggers onChange events in JavaScript for | 953 // Verifies that password autofill triggers events in JavaScript for forms that |
| 967 // forms that are filled after page load. | 954 // are filled after page load. |
| 968 TEST_F(PasswordAutofillAgentTest, | 955 TEST_F(PasswordAutofillAgentTest, |
| 969 PasswordAutofillTriggersOnChangeEventsWaitForUsername) { | 956 PasswordAutofillTriggersOnChangeEventsWaitForUsername) { |
| 970 std::string html = std::string(kFormHTML) + kOnChangeDetectionScript; | 957 std::vector<base::string16> event_checkers; |
| 958 std::string events_registration_script = | |
| 959 CreateScriptToRegisterListeners(kUsernameName, &event_checkers) + | |
| 960 CreateScriptToRegisterListeners(kPasswordName, &event_checkers); | |
| 961 std::string html = std::string(kFormHTML) + events_registration_script; | |
| 971 LoadHTML(html.c_str()); | 962 LoadHTML(html.c_str()); |
| 972 UpdateOriginForHTML(html); | 963 UpdateOriginForHTML(html); |
| 973 UpdateUsernameAndPasswordElements(); | 964 UpdateUsernameAndPasswordElements(); |
| 974 | 965 |
| 975 // Simulate the browser sending back the login info, it triggers the | 966 // Simulate the browser sending back the login info, it triggers the |
| 976 // autocomplete. | 967 // autocomplete. |
| 977 fill_data_.wait_for_username = true; | 968 fill_data_.wait_for_username = true; |
| 978 SimulateOnFillPasswordForm(fill_data_); | 969 SimulateOnFillPasswordForm(fill_data_); |
| 979 | 970 |
| 980 // The username and password should not yet have been autocompleted. | 971 // The username and password should not yet have been autocompleted. |
| 981 CheckTextFieldsState(std::string(), false, std::string(), false); | 972 CheckTextFieldsState(std::string(), false, std::string(), false); |
| 982 | 973 |
| 983 // Simulate a click just to force a user gesture, since the username value is | 974 // Simulate a click just to force a user gesture, since the username value is |
| 984 // set directly. | 975 // set directly. |
| 985 SimulateElementClick(kUsernameName); | 976 SimulateElementClick(kUsernameName); |
| 986 | 977 |
| 987 // Simulate the user entering the first letter of their username and selecting | 978 // Simulate the user entering the first letter of their username and selecting |
| 988 // the matching autofill from the dropdown. | 979 // the matching autofill from the dropdown. |
| 989 SimulateUsernameChange("a"); | 980 SimulateUsernameChange("a"); |
| 981 // Since the username element has focus, blur event will be not triggered. | |
| 982 base::Erase(event_checkers, base::ASCIIToUTF16("username_blur_event")); | |
| 990 SimulateSuggestionChoice(username_element_); | 983 SimulateSuggestionChoice(username_element_); |
| 991 | 984 |
| 992 // The username and password should now have been autocompleted. | 985 // The username and password should now have been autocompleted. |
| 993 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); | 986 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); |
| 994 | 987 |
| 995 // JavaScript onChange events should have been triggered both for the username | 988 // JavaScript events should have been triggered both for the username and for |
| 996 // and for the password. | 989 // the password. |
| 997 int username_onchange_called = -1; | 990 CheckIfEventsAreCalled(event_checkers, true); |
| 998 int password_onchange_called = -1; | |
| 999 ASSERT_TRUE( | |
| 1000 ExecuteJavaScriptAndReturnIntValue( | |
| 1001 ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"), | |
| 1002 &username_onchange_called)); | |
| 1003 EXPECT_EQ(1, username_onchange_called); | |
| 1004 ASSERT_TRUE( | |
| 1005 ExecuteJavaScriptAndReturnIntValue( | |
| 1006 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"), | |
| 1007 &password_onchange_called)); | |
| 1008 EXPECT_EQ(1, password_onchange_called); | |
| 1009 } | 991 } |
| 1010 | 992 |
| 1011 // Tests that |FillSuggestion| properly fills the username and password. | 993 // Tests that |FillSuggestion| properly fills the username and password. |
| 1012 TEST_F(PasswordAutofillAgentTest, FillSuggestion) { | 994 TEST_F(PasswordAutofillAgentTest, FillSuggestion) { |
| 1013 // Simulate the browser sending the login info, but set |wait_for_username| | 995 // Simulate the browser sending the login info, but set |wait_for_username| |
| 1014 // to prevent the form from being immediately filled. | 996 // to prevent the form from being immediately filled. |
| 1015 fill_data_.wait_for_username = true; | 997 fill_data_.wait_for_username = true; |
| 1016 SimulateOnFillPasswordForm(fill_data_); | 998 SimulateOnFillPasswordForm(fill_data_); |
| 1017 | 999 |
| 1018 // Neither field should have been autocompleted. | 1000 // Neither field should have been autocompleted. |
| (...skipping 1571 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2590 SimulateElementClick(kUsernameName); | 2572 SimulateElementClick(kUsernameName); |
| 2591 | 2573 |
| 2592 // Simulate a user clicking on the password element. This should produce a | 2574 // Simulate a user clicking on the password element. This should produce a |
| 2593 // dropdown with suggestion of all available usernames. | 2575 // dropdown with suggestion of all available usernames. |
| 2594 static_cast<PageClickListener*>(autofill_agent_) | 2576 static_cast<PageClickListener*>(autofill_agent_) |
| 2595 ->FormControlElementClicked(password_element_, false); | 2577 ->FormControlElementClicked(password_element_, false); |
| 2596 CheckSuggestions("", false); | 2578 CheckSuggestions("", false); |
| 2597 } | 2579 } |
| 2598 | 2580 |
| 2599 } // namespace autofill | 2581 } // namespace autofill |
| OLD | NEW |