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<std::string> checkers, | |
|
vabr (Chromium)
2017/03/17 12:01:06
Please pass the vector by (const) reference, not b
kolos1
2017/03/17 12:47:36
Done.
| |
| 543 bool expected) { | |
| 544 for (const std::string& variable : checkers) { | |
| 545 int value; | |
| 546 EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue( | |
| 547 base::UTF8ToUTF16(variable), &value)) | |
| 548 << variable; | |
| 549 EXPECT_EQ(expected, value == 1) << variable; | |
| 550 } | |
| 551 } | |
| 552 | |
| 554 bool GetCalledShowPasswordGenerationPopup() { | 553 bool GetCalledShowPasswordGenerationPopup() { |
| 555 fake_pw_client_.Flush(); | 554 fake_pw_client_.Flush(); |
| 556 return fake_pw_client_.called_show_pw_generation_popup(); | 555 return fake_pw_client_.called_show_pw_generation_popup(); |
| 557 } | 556 } |
| 558 | 557 |
| 559 void BindPasswordManagerDriver(mojo::ScopedMessagePipeHandle handle) { | 558 void BindPasswordManagerDriver(mojo::ScopedMessagePipeHandle handle) { |
| 560 fake_driver_.BindRequest( | 559 fake_driver_.BindRequest( |
| 561 mojo::MakeRequest<mojom::PasswordManagerDriver>(std::move(handle))); | 560 mojo::MakeRequest<mojom::PasswordManagerDriver>(std::move(handle))); |
| 562 } | 561 } |
| 563 | 562 |
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 912 SimulateOnFillPasswordForm(fill_data_); | 911 SimulateOnFillPasswordForm(fill_data_); |
| 913 | 912 |
| 914 ExecuteJavaScriptForTests(kJavaScriptClick); | 913 ExecuteJavaScriptForTests(kJavaScriptClick); |
| 915 CheckTextFieldsDOMState(kAliceUsername, true, "", true); | 914 CheckTextFieldsDOMState(kAliceUsername, true, "", true); |
| 916 } | 915 } |
| 917 | 916 |
| 918 // Verifies that password autofill triggers onChange events in JavaScript for | 917 // Verifies that password autofill triggers onChange events in JavaScript for |
| 919 // forms that are filled on page load. | 918 // forms that are filled on page load. |
| 920 TEST_F(PasswordAutofillAgentTest, | 919 TEST_F(PasswordAutofillAgentTest, |
| 921 PasswordAutofillTriggersOnChangeEventsOnLoad) { | 920 PasswordAutofillTriggersOnChangeEventsOnLoad) { |
| 922 std::string html = std::string(kFormHTML) + kOnChangeDetectionScript; | 921 std::string html = std::string(kFormHTML); |
| 923 LoadHTML(html.c_str()); | 922 LoadHTML(html.c_str()); |
| 924 UpdateOriginForHTML(html); | 923 UpdateOriginForHTML(html); |
| 925 UpdateUsernameAndPasswordElements(); | 924 UpdateUsernameAndPasswordElements(); |
| 926 | 925 |
| 926 std::vector<std::string> username_event_checkers; | |
| 927 std::vector<std::string> password_event_checkers; | |
| 928 std::string events_registration_script = | |
| 929 CreateScriptToRegisterListeners(kUsernameName, &username_event_checkers) + | |
| 930 CreateScriptToRegisterListeners(kPasswordName, &password_event_checkers); | |
| 931 ExecuteJavaScriptForTests(events_registration_script.c_str()); | |
| 932 | |
| 927 // Simulate the browser sending back the login info, it triggers the | 933 // Simulate the browser sending back the login info, it triggers the |
| 928 // autocomplete. | 934 // autocomplete. |
| 929 SimulateOnFillPasswordForm(fill_data_); | 935 SimulateOnFillPasswordForm(fill_data_); |
| 930 | 936 |
| 931 // The username and password should have been autocompleted... | 937 // The username and password should have been autocompleted... |
| 932 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); | 938 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); |
| 933 // ... but since there hasn't been a user gesture yet, the autocompleted | 939 // ... but since there hasn't been a user gesture yet, the autocompleted |
| 934 // password should only be visible to the user. | 940 // password should only be visible to the user. |
| 935 CheckTextFieldsDOMState(kAliceUsername, true, std::string(), true); | 941 CheckTextFieldsDOMState(kAliceUsername, true, std::string(), true); |
| 936 | 942 |
| 937 // A JavaScript onChange event should have been triggered for the username, | 943 // A JavaScript onChange event should have been triggered for the username, |
| 938 // but not yet for the password. | 944 // but not yet for the password. |
| 939 int username_onchange_called = -1; | 945 |
| 940 int password_onchange_called = -1; | 946 CheckIfEventsAreCalled(username_event_checkers, true); |
| 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. | 947 // TODO(isherman): Re-enable this check once http://crbug.com/333144 is fixed. |
|
vabr (Chromium)
2017/03/17 12:01:07
This comment looks obsoleted by your changes.
kolos1
2017/03/17 12:47:36
Done.
| |
| 951 // EXPECT_EQ(0, password_onchange_called); | 948 CheckIfEventsAreCalled(password_event_checkers, false); |
| 952 | 949 |
| 953 // Simulate a user click so that the password field's real value is filled. | 950 // Simulate a user click so that the password field's real value is filled. |
| 954 SimulateElementClick(kUsernameName); | 951 SimulateElementClick(kUsernameName); |
| 955 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); | 952 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); |
| 956 | 953 |
| 957 // Now, a JavaScript onChange event should have been triggered for the | 954 // Now, a JavaScript onChange event should have been triggered for the |
| 958 // password as well. | 955 // password as well. |
| 959 ASSERT_TRUE( | 956 CheckIfEventsAreCalled(password_event_checkers, true); |
| 960 ExecuteJavaScriptAndReturnIntValue( | |
| 961 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"), | |
| 962 &password_onchange_called)); | |
| 963 EXPECT_EQ(1, password_onchange_called); | |
| 964 } | 957 } |
| 965 | 958 |
| 966 // Verifies that password autofill triggers onChange events in JavaScript for | 959 // Verifies that password autofill triggers onChange events in JavaScript for |
| 967 // forms that are filled after page load. | 960 // forms that are filled after page load. |
| 968 TEST_F(PasswordAutofillAgentTest, | 961 TEST_F(PasswordAutofillAgentTest, |
| 969 PasswordAutofillTriggersOnChangeEventsWaitForUsername) { | 962 PasswordAutofillTriggersOnChangeEventsWaitForUsername) { |
| 970 std::string html = std::string(kFormHTML) + kOnChangeDetectionScript; | 963 std::string html = std::string(kFormHTML); |
| 971 LoadHTML(html.c_str()); | 964 LoadHTML(html.c_str()); |
| 972 UpdateOriginForHTML(html); | 965 UpdateOriginForHTML(html); |
| 973 UpdateUsernameAndPasswordElements(); | 966 UpdateUsernameAndPasswordElements(); |
| 974 | 967 |
| 968 std::vector<std::string> event_checkers; | |
| 969 std::string events_registration_script = | |
| 970 CreateScriptToRegisterListeners(kUsernameName, &event_checkers) + | |
| 971 CreateScriptToRegisterListeners(kPasswordName, &event_checkers); | |
| 972 ExecuteJavaScriptForTests(events_registration_script.c_str()); | |
| 973 | |
| 975 // Simulate the browser sending back the login info, it triggers the | 974 // Simulate the browser sending back the login info, it triggers the |
| 976 // autocomplete. | 975 // autocomplete. |
| 977 fill_data_.wait_for_username = true; | 976 fill_data_.wait_for_username = true; |
| 978 SimulateOnFillPasswordForm(fill_data_); | 977 SimulateOnFillPasswordForm(fill_data_); |
| 979 | 978 |
| 980 // The username and password should not yet have been autocompleted. | 979 // The username and password should not yet have been autocompleted. |
| 981 CheckTextFieldsState(std::string(), false, std::string(), false); | 980 CheckTextFieldsState(std::string(), false, std::string(), false); |
| 982 | 981 |
| 983 // Simulate a click just to force a user gesture, since the username value is | 982 // Simulate a click just to force a user gesture, since the username value is |
| 984 // set directly. | 983 // set directly. |
| 985 SimulateElementClick(kUsernameName); | 984 SimulateElementClick(kUsernameName); |
| 986 | 985 |
| 987 // Simulate the user entering the first letter of their username and selecting | 986 // Simulate the user entering the first letter of their username and selecting |
| 988 // the matching autofill from the dropdown. | 987 // the matching autofill from the dropdown. |
| 989 SimulateUsernameChange("a"); | 988 SimulateUsernameChange("a"); |
| 989 // Since the username element has focus, blur event will ne be triggered. | |
| 990 event_checkers.erase(std::remove(event_checkers.begin(), event_checkers.end(), | |
|
vabr (Chromium)
2017/03/17 12:01:06
Please use base::Erase instead (this is a recent c
kolos1
2017/03/17 12:47:36
Done.
| |
| 991 "username_blur_event"), | |
| 992 event_checkers.end()); | |
| 990 SimulateSuggestionChoice(username_element_); | 993 SimulateSuggestionChoice(username_element_); |
| 991 | 994 |
| 992 // The username and password should now have been autocompleted. | 995 // The username and password should now have been autocompleted. |
| 993 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); | 996 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); |
| 994 | 997 |
| 995 // JavaScript onChange events should have been triggered both for the username | 998 // JavaScript onChange events should have been triggered both for the username |
| 996 // and for the password. | 999 // and for the password. |
| 997 int username_onchange_called = -1; | 1000 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 } | 1001 } |
| 1010 | 1002 |
| 1011 // Tests that |FillSuggestion| properly fills the username and password. | 1003 // Tests that |FillSuggestion| properly fills the username and password. |
| 1012 TEST_F(PasswordAutofillAgentTest, FillSuggestion) { | 1004 TEST_F(PasswordAutofillAgentTest, FillSuggestion) { |
| 1013 // Simulate the browser sending the login info, but set |wait_for_username| | 1005 // Simulate the browser sending the login info, but set |wait_for_username| |
| 1014 // to prevent the form from being immediately filled. | 1006 // to prevent the form from being immediately filled. |
| 1015 fill_data_.wait_for_username = true; | 1007 fill_data_.wait_for_username = true; |
| 1016 SimulateOnFillPasswordForm(fill_data_); | 1008 SimulateOnFillPasswordForm(fill_data_); |
| 1017 | 1009 |
| 1018 // Neither field should have been autocompleted. | 1010 // Neither field should have been autocompleted. |
| (...skipping 1512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2531 SimulateElementClick(kUsernameName); | 2523 SimulateElementClick(kUsernameName); |
| 2532 | 2524 |
| 2533 // Simulate a user clicking on the password element. This should produce a | 2525 // Simulate a user clicking on the password element. This should produce a |
| 2534 // dropdown with suggestion of all available usernames. | 2526 // dropdown with suggestion of all available usernames. |
| 2535 static_cast<PageClickListener*>(autofill_agent_) | 2527 static_cast<PageClickListener*>(autofill_agent_) |
| 2536 ->FormControlElementClicked(password_element_, false); | 2528 ->FormControlElementClicked(password_element_, false); |
| 2537 CheckSuggestions("", false); | 2529 CheckSuggestions("", false); |
| 2538 } | 2530 } |
| 2539 | 2531 |
| 2540 } // namespace autofill | 2532 } // namespace autofill |
| OLD | NEW |