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

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

Issue 414013003: Password autofill should not override explicitly typed password (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Further corrections Created 6 years, 4 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
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 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 password_element_ = element.to<blink::WebInputElement>(); 254 password_element_ = element.to<blink::WebInputElement>();
255 } 255 }
256 256
257 void ClearUsernameAndPasswordFields() { 257 void ClearUsernameAndPasswordFields() {
258 username_element_.setValue(""); 258 username_element_.setValue("");
259 username_element_.setAutofilled(false); 259 username_element_.setAutofilled(false);
260 password_element_.setValue(""); 260 password_element_.setValue("");
261 password_element_.setAutofilled(false); 261 password_element_.setAutofilled(false);
262 } 262 }
263 263
264 void SimulateUsernameChangeForElement(const std::string& username, 264 void SimulateDidEndEditingWithNoChangeForElement(WebFrame* input_frame,
265 bool move_caret_to_end, 265 WebInputElement& input) {
266 WebFrame* input_frame, 266 autofill_agent_->textFieldDidEndEditing(input);
267 WebInputElement& username_input, 267 }
268 bool is_user_input) { 268
269 username_input.setValue(WebString::fromUTF8(username), is_user_input); 269 void SimulateInputChangeForElement(const std::string& new_value,
270 bool move_caret_to_end,
271 WebFrame* input_frame,
272 WebInputElement& input,
273 bool is_user_input) {
274 input.setValue(WebString::fromUTF8(new_value), is_user_input);
270 // The field must have focus or AutofillAgent will think the 275 // The field must have focus or AutofillAgent will think the
271 // change should be ignored. 276 // change should be ignored.
272 while (!username_input.focused()) 277 while (!input.focused())
273 input_frame->document().frame()->view()->advanceFocus(false); 278 input_frame->document().frame()->view()->advanceFocus(false);
274 if (move_caret_to_end) 279 if (move_caret_to_end)
275 username_input.setSelectionRange(username.length(), username.length()); 280 input.setSelectionRange(new_value.length(), new_value.length());
276 if (is_user_input) 281 if (is_user_input)
277 password_autofill_agent()->FirstUserGestureObserved(); 282 password_autofill_agent()->FirstUserGestureObserved();
278 autofill_agent_->textFieldDidChange(username_input); 283 autofill_agent_->textFieldDidChange(input);
279 // Processing is delayed because of a Blink bug: 284 // Processing is delayed because of a Blink bug:
280 // https://bugs.webkit.org/show_bug.cgi?id=16976 285 // https://bugs.webkit.org/show_bug.cgi?id=16976
281 // See PasswordAutofillAgent::TextDidChangeInTextField() for details. 286 // See PasswordAutofillAgent::TextDidChangeInTextField() for details.
282 287
283 // Autocomplete will trigger a style recalculation when we put up the next 288 // Autocomplete will trigger a style recalculation when we put up the next
284 // frame, but we don't want to wait that long. Instead, trigger a style 289 // frame, but we don't want to wait that long. Instead, trigger a style
285 // recalcuation manually after TextFieldDidChangeImpl runs. 290 // recalcuation manually after TextFieldDidChangeImpl runs.
286 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( 291 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
287 &PasswordAutofillAgentTest::LayoutMainFrame, base::Unretained(this))); 292 &PasswordAutofillAgentTest::LayoutMainFrame, base::Unretained(this)));
288 293
(...skipping 14 matching lines...) Expand all
303 autofill_agent_->OnFillPasswordSuggestion(blink_username, blink_password); 308 autofill_agent_->OnFillPasswordSuggestion(blink_username, blink_password);
304 } 309 }
305 310
306 void LayoutMainFrame() { 311 void LayoutMainFrame() {
307 GetMainFrame()->view()->layout(); 312 GetMainFrame()->view()->layout();
308 } 313 }
309 314
310 void SimulateUsernameChange(const std::string& username, 315 void SimulateUsernameChange(const std::string& username,
311 bool move_caret_to_end, 316 bool move_caret_to_end,
312 bool is_user_input = false) { 317 bool is_user_input = false) {
313 SimulateUsernameChangeForElement(username, 318 SimulateInputChangeForElement(username,
314 move_caret_to_end, 319 move_caret_to_end,
315 GetMainFrame(), 320 GetMainFrame(),
316 username_element_, 321 username_element_,
317 is_user_input); 322 is_user_input);
318 } 323 }
319 324
320 // Tests that no suggestion popup is generated when the username_element_ is 325 // Tests that no suggestion popup is generated when the username_element_ is
321 // edited. 326 // edited.
322 void ExpectNoSuggestionsPopup() { 327 void ExpectNoSuggestionsPopup() {
323 // The first test below ensures that the suggestions have been handled by 328 // The first test below ensures that the suggestions have been handled by
324 // the password_autofill_agent, even though autocomplete='off' is set. The 329 // the password_autofill_agent, even though autocomplete='off' is set. The
325 // second check ensures that, although handled, no "show suggestions" IPC to 330 // second check ensures that, although handled, no "show suggestions" IPC to
326 // the browser was generated. 331 // the browser was generated.
327 // 332 //
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 const WebInputElement& password_element, 366 const WebInputElement& password_element,
362 const std::string& password, 367 const std::string& password,
363 bool password_autofilled, 368 bool password_autofilled,
364 bool checkSuggestedValue) { 369 bool checkSuggestedValue) {
365 EXPECT_EQ(username, 370 EXPECT_EQ(username,
366 static_cast<std::string>(username_element.value().utf8())); 371 static_cast<std::string>(username_element.value().utf8()));
367 EXPECT_EQ(username_autofilled, username_element.isAutofilled()); 372 EXPECT_EQ(username_autofilled, username_element.isAutofilled());
368 EXPECT_EQ(password, 373 EXPECT_EQ(password,
369 static_cast<std::string>( 374 static_cast<std::string>(
370 checkSuggestedValue ? password_element.suggestedValue().utf8() 375 checkSuggestedValue ? password_element.suggestedValue().utf8()
371 : password_element.value().utf8())); 376 : password_element.value().utf8()))
377 << "checkSuggestedValue == " << checkSuggestedValue;
372 EXPECT_EQ(password_autofilled, password_element.isAutofilled()); 378 EXPECT_EQ(password_autofilled, password_element.isAutofilled());
373 } 379 }
374 380
375 // Checks the DOM-accessible value of the username element and the 381 // Checks the DOM-accessible value of the username element and the
376 // *suggested* value of the password element. 382 // *suggested* value of the password element.
377 void CheckTextFieldsState(const std::string& username, 383 void CheckTextFieldsState(const std::string& username,
378 bool username_autofilled, 384 bool username_autofilled,
379 const std::string& password, 385 const std::string& password,
380 bool password_autofilled) { 386 bool password_autofilled) {
381 CheckTextFieldsStateForElements(username_element_, 387 CheckTextFieldsStateForElements(username_element_,
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after
913 919
914 WebInputElement username_input = username_element.to<WebInputElement>(); 920 WebInputElement username_input = username_element.to<WebInputElement>();
915 WebInputElement password_input = password_element.to<WebInputElement>(); 921 WebInputElement password_input = password_element.to<WebInputElement>();
916 ASSERT_FALSE(username_element.isNull()); 922 ASSERT_FALSE(username_element.isNull());
917 923
918 CheckTextFieldsStateForElements( 924 CheckTextFieldsStateForElements(
919 username_input, "", false, password_input, "", false, false); 925 username_input, "", false, password_input, "", false, false);
920 926
921 // Simulate the user typing in the username in the iframe which should cause 927 // Simulate the user typing in the username in the iframe which should cause
922 // an autofill. 928 // an autofill.
923 SimulateUsernameChangeForElement( 929 SimulateInputChangeForElement(
924 kAliceUsername, true, iframe, username_input, true); 930 kAliceUsername, true, iframe, username_input, true);
925 931
926 CheckTextFieldsStateForElements(username_input, 932 CheckTextFieldsStateForElements(username_input,
927 kAliceUsername, 933 kAliceUsername,
928 true, 934 true,
929 password_input, 935 password_input,
930 kAlicePassword, 936 kAlicePassword,
931 true, 937 true,
932 false); 938 false);
933 } 939 }
(...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after
1488 render_thread_->sink().ClearMessages(); 1494 render_thread_->sink().ClearMessages();
1489 autofill_agent_->FormControlElementClicked(username_element_, true); 1495 autofill_agent_->FormControlElementClicked(username_element_, true);
1490 ExpectAllCredentials(); 1496 ExpectAllCredentials();
1491 } 1497 }
1492 1498
1493 // The user types in a password, but then just before sending the form off, a 1499 // The user types in a password, but then just before sending the form off, a
1494 // script clears that password. This test checks that PasswordAutofillAgent can 1500 // script clears that password. This test checks that PasswordAutofillAgent can
1495 // still remember the password typed by the user. 1501 // still remember the password typed by the user.
1496 TEST_F(PasswordAutofillAgentTest, 1502 TEST_F(PasswordAutofillAgentTest,
1497 RememberLastNonEmptyPasswordOnSubmit_ScriptCleared) { 1503 RememberLastNonEmptyPasswordOnSubmit_ScriptCleared) {
1498 SimulateUsernameChangeForElement( 1504 SimulateInputChangeForElement(
1499 "temp", true, GetMainFrame(), username_element_, true); 1505 "temp", true, GetMainFrame(), username_element_, true);
1500 SimulateUsernameChangeForElement( 1506 SimulateInputChangeForElement(
1501 "random", true, GetMainFrame(), password_element_, true); 1507 "random", true, GetMainFrame(), password_element_, true);
1502 1508
1503 // Simulate that the password value was cleared by the site's JavaScript 1509 // Simulate that the password value was cleared by the site's JavaScript
1504 // before submit. 1510 // before submit.
1505 password_element_.setValue(WebString()); 1511 password_element_.setValue(WebString());
1506 static_cast<content::RenderViewObserver*>(password_autofill_agent()) 1512 static_cast<content::RenderViewObserver*>(password_autofill_agent())
1507 ->WillSubmitForm(GetMainFrame(), username_element_.form()); 1513 ->WillSubmitForm(GetMainFrame(), username_element_.form());
1508 1514
1509 // Observe that the PasswordAutofillAgent still remembered the last non-empty 1515 // Observe that the PasswordAutofillAgent still remembered the last non-empty
1510 // password and sent that to the browser. 1516 // password and sent that to the browser.
1511 ExpectFormSubmittedWithPasswords("random", ""); 1517 ExpectFormSubmittedWithPasswords("random", "");
1512 } 1518 }
1513 1519
1514 // Similar to RememberLastNonEmptyPasswordOnSubmit_ScriptCleared, but this time 1520 // Similar to RememberLastNonEmptyPasswordOnSubmit_ScriptCleared, but this time
1515 // it's the user who clears the password. This test checks that in that case, 1521 // it's the user who clears the password. This test checks that in that case,
1516 // the last non-empty password is not remembered. 1522 // the last non-empty password is not remembered.
1517 TEST_F(PasswordAutofillAgentTest, 1523 TEST_F(PasswordAutofillAgentTest,
1518 RememberLastNonEmptyPasswordOnSubmit_UserCleared) { 1524 RememberLastNonEmptyPasswordOnSubmit_UserCleared) {
1519 SimulateUsernameChangeForElement( 1525 SimulateInputChangeForElement(
1520 "temp", true, GetMainFrame(), username_element_, true); 1526 "temp", true, GetMainFrame(), username_element_, true);
1521 SimulateUsernameChangeForElement( 1527 SimulateInputChangeForElement(
1522 "random", true, GetMainFrame(), password_element_, true); 1528 "random", true, GetMainFrame(), password_element_, true);
1523 1529
1524 // Simulate that the user actually cleared the password again. 1530 // Simulate that the user actually cleared the password again.
1525 SimulateUsernameChangeForElement( 1531 SimulateInputChangeForElement(
1526 "", true, GetMainFrame(), password_element_, true); 1532 "", true, GetMainFrame(), password_element_, true);
1527 static_cast<content::RenderViewObserver*>(password_autofill_agent()) 1533 static_cast<content::RenderViewObserver*>(password_autofill_agent())
1528 ->WillSubmitForm(GetMainFrame(), username_element_.form()); 1534 ->WillSubmitForm(GetMainFrame(), username_element_.form());
1529 1535
1530 // Observe that the PasswordAutofillAgent respects the user having cleared the 1536 // Observe that the PasswordAutofillAgent respects the user having cleared the
1531 // password. 1537 // password.
1532 ExpectFormSubmittedWithPasswords("", ""); 1538 ExpectFormSubmittedWithPasswords("", "");
1533 } 1539 }
1534 1540
1535 // Similar to RememberLastNonEmptyPasswordOnSubmit_ScriptCleared, but uses the 1541 // Similar to RememberLastNonEmptyPasswordOnSubmit_ScriptCleared, but uses the
1536 // new password instead of the current password. 1542 // new password instead of the current password.
1537 TEST_F(PasswordAutofillAgentTest, 1543 TEST_F(PasswordAutofillAgentTest,
1538 RememberLastNonEmptyPasswordOnSubmit_NewPassword) { 1544 RememberLastNonEmptyPasswordOnSubmit_NewPassword) {
1539 const char kNewPasswordFormHTML[] = 1545 const char kNewPasswordFormHTML[] =
1540 "<FORM name='LoginTestForm'>" 1546 "<FORM name='LoginTestForm'>"
1541 " <INPUT type='text' id='username' autocomplete='username'/>" 1547 " <INPUT type='text' id='username' autocomplete='username'/>"
1542 " <INPUT type='password' id='password' autocomplete='new-password'/>" 1548 " <INPUT type='password' id='password' autocomplete='new-password'/>"
1543 " <INPUT type='submit' value='Login'/>" 1549 " <INPUT type='submit' value='Login'/>"
1544 "</FORM>"; 1550 "</FORM>";
1545 LoadHTML(kNewPasswordFormHTML); 1551 LoadHTML(kNewPasswordFormHTML);
1546 UpdateUsernameAndPasswordElements(); 1552 UpdateUsernameAndPasswordElements();
1547 1553
1548 SimulateUsernameChangeForElement( 1554 SimulateInputChangeForElement(
1549 "temp", true, GetMainFrame(), username_element_, true); 1555 "temp", true, GetMainFrame(), username_element_, true);
1550 SimulateUsernameChangeForElement( 1556 SimulateInputChangeForElement(
1551 "random", true, GetMainFrame(), password_element_, true); 1557 "random", true, GetMainFrame(), password_element_, true);
1552 1558
1553 // Simulate that the password value was cleared by the site's JavaScript 1559 // Simulate that the password value was cleared by the site's JavaScript
1554 // before submit. 1560 // before submit.
1555 password_element_.setValue(WebString()); 1561 password_element_.setValue(WebString());
1556 static_cast<content::RenderViewObserver*>(password_autofill_agent()) 1562 static_cast<content::RenderViewObserver*>(password_autofill_agent())
1557 ->WillSubmitForm(GetMainFrame(), username_element_.form()); 1563 ->WillSubmitForm(GetMainFrame(), username_element_.form());
1558 1564
1559 // Observe that the PasswordAutofillAgent still remembered the last non-empty 1565 // Observe that the PasswordAutofillAgent still remembered the last non-empty
1560 // password and sent that to the browser. 1566 // password and sent that to the browser.
1561 ExpectFormSubmittedWithPasswords("", "random"); 1567 ExpectFormSubmittedWithPasswords("", "random");
1562 } 1568 }
1563 1569
1570 // The user first accepts a suggestion, but then overwrites the password. This
1571 // test checks that the overwritten password is not reverted back by the user
1572 // triggering autofill through focusing (but not changing) the username again.
1573 TEST_F(PasswordAutofillAgentTest, PasswordNotOverwritten) {
1574 // Simulate having credentials which needed to wait until the user starts
1575 // typing the username to be filled (e.g., PSL-matched credentials). Those are
1576 // the ones which can be filled as a result of TextFieldDidEndEditing.
1577 fill_data_.wait_for_username = true;
1578 // Simulate that the user typed her name to make the autofill work.
1579 SimulateInputChangeForElement(kAliceUsername,
1580 /*move_caret_to_end=*/true,
1581 GetMainFrame(),
1582 username_element_,
1583 /*is_user_input=*/true);
1584 SimulateOnFillPasswordForm(fill_data_);
1585
1586 const std::string old_username(username_element_.value().utf8());
1587 const std::string old_password(password_element_.value().utf8());
1588 const std::string new_password(old_password + "modify");
1589
1590 // The user changes the password.
1591 SimulateInputChangeForElement(new_password,
1592 /*move_caret_to_end=*/true,
1593 GetMainFrame(),
1594 password_element_,
1595 /*is_user_input=*/true);
1596
1597 // The user switches back into the username field, but leaves that without
1598 // changes.
1599 SimulateDidEndEditingWithNoChangeForElement(GetMainFrame(),
1600 username_element_);
1601
1602 // The password should have stayed as the user changed it.
1603 CheckTextFieldsDOMState(old_username, false, new_password, false);
1604 // The password should not have a suggested value.
1605 CheckTextFieldsState(old_username, false, std::string(), false);
1606 }
1607
1608 // Tests that inline autocompletion overwrites the previous password value when
1609 // it should.
1610 TEST_F(PasswordAutofillAgentTest, InlineAutocompleteOverwritesValue) {
1611 // Simulate the browser sending back the login info.
1612 SimulateOnFillPasswordForm(fill_data_);
1613
1614 ClearUsernameAndPasswordFields();
1615
1616 // The user enters a password
1617 SimulateInputChangeForElement("someOtherPassword",
1618 /*move_caret_to_end=*/true,
1619 GetMainFrame(),
1620 password_element_,
1621 /*is_user_input=*/true);
1622
1623 // Simulate the user typing a stored username.
1624 SimulateUsernameChange(kAliceUsername, true);
1625 // The autofileld password should replace the typed one.
1626 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true);
1627 }
1628
1564 } // namespace autofill 1629 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698