Index: chrome/renderer/autofill/password_autofill_agent_browsertest.cc |
diff --git a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc |
index 2ff6a4e467bc6332f5fe098202bd085e4a772787..5897e9d7594026fb750912b7f0277105d0e42140 100644 |
--- a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc |
+++ b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc |
@@ -142,6 +142,18 @@ const char kJavaScriptClick[] = |
"form.dispatchEvent(event);" |
"console.log('clicked!');"; |
+const char kOnChangeDetectionScript[] = |
+ "<script>" |
+ " usernameOnchangeCalled = false;" |
+ " passwordOnchangeCalled = false;" |
+ " document.getElementById('username').onchange = function() {" |
+ " usernameOnchangeCalled = true;" |
+ " };" |
+ " document.getElementById('password').onchange = function() {" |
+ " passwordOnchangeCalled = true;" |
+ " };" |
+ "</script>"; |
+ |
} // namespace |
namespace autofill { |
@@ -198,14 +210,27 @@ class PasswordAutofillAgentTest : public ChromeRenderViewTest { |
// We need to set the origin so it matches the frame URL and the action so |
// it matches the form action, otherwise we won't autocomplete. |
- std::string origin("data:text/html;charset=utf-8,"); |
- origin += kFormHTML; |
- fill_data_.basic_data.origin = GURL(origin); |
+ UpdateOriginForHTML(kFormHTML); |
fill_data_.basic_data.action = GURL("http://www.bidule.com"); |
LoadHTML(kFormHTML); |
- // Now retrieves the input elements so the test can access them. |
+ // Now retrieve the input elements so the test can access them. |
+ UpdateUsernameAndPasswordElements(); |
+ } |
+ |
+ virtual void TearDown() { |
+ username_element_.reset(); |
+ password_element_.reset(); |
+ ChromeRenderViewTest::TearDown(); |
+ } |
+ |
+ void UpdateOriginForHTML(const std::string& html) { |
+ std::string origin = "data:text/html;charset=utf-8," + html; |
+ fill_data_.basic_data.origin = GURL(origin); |
+ } |
+ |
+ void UpdateUsernameAndPasswordElements() { |
WebDocument document = GetMainFrame()->document(); |
WebElement element = |
document.getElementById(WebString::fromUTF8(kUsernameName)); |
@@ -216,12 +241,6 @@ class PasswordAutofillAgentTest : public ChromeRenderViewTest { |
password_element_ = element.to<blink::WebInputElement>(); |
} |
- virtual void TearDown() { |
- username_element_.reset(); |
- password_element_.reset(); |
- ChromeRenderViewTest::TearDown(); |
- } |
- |
void ClearUsernameAndPasswordFields() { |
username_element_.setValue(""); |
username_element_.setAutofilled(false); |
@@ -378,10 +397,8 @@ TEST_F(PasswordAutofillAgentTest, InitialAutocompleteForEmptyAction) { |
password_element_ = element.to<blink::WebInputElement>(); |
// Set the expected form origin and action URLs. |
- std::string origin("data:text/html;charset=utf-8,"); |
- origin += kEmptyActionFormHTML; |
- fill_data_.basic_data.origin = GURL(origin); |
- fill_data_.basic_data.action = GURL(origin); |
+ UpdateOriginForHTML(kEmptyActionFormHTML); |
+ fill_data_.basic_data.action = fill_data_.basic_data.origin; |
// Simulate the browser sending back the login info, it triggers the |
// autocomplete. |
@@ -483,9 +500,7 @@ TEST_F(PasswordAutofillAgentTest, NoAutocompleteForTextFieldPasswords) { |
password_element_ = element.to<blink::WebInputElement>(); |
// Set the expected form origin URL. |
- std::string origin("data:text/html;charset=utf-8,"); |
- origin += kTextFieldPasswordFormHTML; |
- fill_data_.basic_data.origin = GURL(origin); |
+ UpdateOriginForHTML(kTextFieldPasswordFormHTML); |
SimulateOnFillPasswordForm(fill_data_); |
@@ -513,9 +528,7 @@ TEST_F(PasswordAutofillAgentTest, NoAutocompleteForPasswordFieldUsernames) { |
password_element_ = element.to<blink::WebInputElement>(); |
// Set the expected form origin URL. |
- std::string origin("data:text/html;charset=utf-8,"); |
- origin += kPasswordFieldUsernameFormHTML; |
- fill_data_.basic_data.origin = GURL(origin); |
+ UpdateOriginForHTML(kPasswordFieldUsernameFormHTML); |
SimulateOnFillPasswordForm(fill_data_); |
@@ -807,7 +820,7 @@ TEST_F(PasswordAutofillAgentTest, GestureRequiredTest) { |
// However, it should only have completed with the suggested value, as tested |
// above, and it should not have completed into the DOM accessible value for |
// the password field. |
- CheckTextFieldsDOMState(kAliceUsername, true, "", true); |
+ CheckTextFieldsDOMState(kAliceUsername, true, std::string(), true); |
// Simulate a user click so that the password field's real value is filled. |
SimulateElementClick(kUsernameName); |
@@ -823,4 +836,96 @@ TEST_F(PasswordAutofillAgentTest, NoDOMActivationTest) { |
CheckTextFieldsDOMState(kAliceUsername, true, "", true); |
} |
+// Verifies that password autofill triggers onChange events in JavaScript for |
+// forms that are filled on page load. |
+TEST_F(PasswordAutofillAgentTest, |
+ PasswordAutofillTriggersOnChangeEventsOnLoad) { |
+ std::string html = std::string(kFormHTML) + kOnChangeDetectionScript; |
+ LoadHTML(html.c_str()); |
+ UpdateOriginForHTML(html); |
+ UpdateUsernameAndPasswordElements(); |
+ |
+ // Simulate the browser sending back the login info, it triggers the |
+ // autocomplete. |
+ SimulateOnFillPasswordForm(fill_data_); |
+ |
+ // The username and password should have been autocompleted... |
+ CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); |
+ // ... but since there hasn't been a user gesture yet, the autocompleted |
+ // password should only be visible to the user. |
+ CheckTextFieldsDOMState(kAliceUsername, true, std::string(), true); |
+ |
+ |
Garrett Casto
2014/01/09 19:14:32
Extra space.
Ilya Sherman
2014/01/10 06:32:49
Done.
|
+ // A JavaScript onChange event should have been triggered for the username, |
+ // but not yet for the password. |
+ int username_onchange_called = -1; |
+ int password_onchange_called = -1; |
+ ASSERT_TRUE( |
+ ExecuteJavaScriptAndReturnIntValue( |
+ ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"), |
+ &username_onchange_called)); |
+ EXPECT_EQ(1, username_onchange_called); |
+ ASSERT_TRUE( |
+ ExecuteJavaScriptAndReturnIntValue( |
+ ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"), |
+ &password_onchange_called)); |
+ EXPECT_EQ(0, password_onchange_called); |
+ |
+ // Simulate a user click so that the password field's real value is filled. |
+ SimulateElementClick(kUsernameName); |
+ CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); |
+ |
+ // Now, a JavaScript onChange event should have been triggered for the |
+ // password as well. |
+ ASSERT_TRUE( |
+ ExecuteJavaScriptAndReturnIntValue( |
+ ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"), |
+ &password_onchange_called)); |
+ EXPECT_EQ(1, password_onchange_called); |
+} |
+ |
+// Verifies that password autofill triggers onChange events in JavaScript for |
+// forms that are filled after page load. |
+TEST_F(PasswordAutofillAgentTest, |
+ PasswordAutofillTriggersOnChangeEventsWaitForUsername) { |
+ std::string html = std::string(kFormHTML) + kOnChangeDetectionScript; |
+ LoadHTML(html.c_str()); |
+ UpdateOriginForHTML(html); |
+ UpdateUsernameAndPasswordElements(); |
+ |
+ // Simulate the browser sending back the login info, it triggers the |
+ // autocomplete. |
+ fill_data_.wait_for_username = true; |
+ SimulateOnFillPasswordForm(fill_data_); |
+ |
+ // The username and password should not yet have been autocompleted. |
+ CheckTextFieldsState(std::string(), false, std::string(), false); |
+ |
+ // Simulate a click just to force a user gesture, since the username value is |
+ // set directly. |
+ SimulateElementClick(kUsernameName); |
+ |
+ // Simulate the user entering her username. |
+ username_element_.setValue(ASCIIToUTF16(kAliceUsername), true); |
+ autofill_agent_->textFieldDidEndEditing(username_element_); |
+ |
+ // The username and password should now have been autocompleted. |
+ CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); |
+ |
+ // JavaScript onChange events should have been triggered both for the username |
+ // and for the password. |
+ int username_onchange_called = -1; |
+ int password_onchange_called = -1; |
+ ASSERT_TRUE( |
+ ExecuteJavaScriptAndReturnIntValue( |
+ ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"), |
+ &username_onchange_called)); |
+ EXPECT_EQ(1, username_onchange_called); |
+ ASSERT_TRUE( |
+ ExecuteJavaScriptAndReturnIntValue( |
+ ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"), |
+ &password_onchange_called)); |
+ EXPECT_EQ(1, password_onchange_called); |
+} |
+ |
} // namespace autofill |