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 3// found in the LICENSE file. 4 5#include "base/strings/string_util.h" 6#include "base/strings/utf_string_conversions.h" 7#include "chrome/test/base/chrome_render_view_test.h" 8#include "components/autofill/content/common/autofill_messages.h" 9#include "components/autofill/content/renderer/autofill_agent.h" 10#include "components/autofill/content/renderer/form_autofill_util.h" 11#include "components/autofill/content/renderer/password_autofill_agent.h" 12#include "components/autofill/content/renderer/test_password_autofill_agent.h" 13#include "components/autofill/core/common/form_data.h" 14#include "components/autofill/core/common/form_field_data.h" 15#include "components/autofill/core/common/password_autofill_util.h" 16#include "testing/gtest/include/gtest/gtest.h" 17#include "third_party/WebKit/public/platform/WebString.h" 18#include "third_party/WebKit/public/platform/WebVector.h" 19#include "third_party/WebKit/public/web/WebDocument.h" 20#include "third_party/WebKit/public/web/WebElement.h" 21#include "third_party/WebKit/public/web/WebFormElement.h" 22#include "third_party/WebKit/public/web/WebInputElement.h" 23#include "third_party/WebKit/public/web/WebLocalFrame.h" 24#include "third_party/WebKit/public/web/WebNode.h" 25#include "third_party/WebKit/public/web/WebView.h" 26#include "ui/events/keycodes/keyboard_codes.h" 27 28using autofill::PasswordForm; 29using base::ASCIIToUTF16; 30using base::UTF16ToUTF8; 31using blink::WebDocument; 32using blink::WebElement; 33using blink::WebFrame; 34using blink::WebInputElement; 35using blink::WebString; 36using blink::WebView; 37 38namespace { 39 40// The name of the username/password element in the form. 41const char kUsernameName[] = "username"; 42const char kPasswordName[] = "password"; 43 44const char kAliceUsername[] = "alice"; 45const char kAlicePassword[] = "password"; 46const char kBobUsername[] = "bob"; 47const char kBobPassword[] = "secret"; 48const char kCarolUsername[] = "Carol"; 49const char kCarolPassword[] = "test"; 50const char kCarolAlternateUsername[] = "RealCarolUsername"; 51 52const char kFormHTML[] = 53 "<FORM name='LoginTestForm' action='http://www.bidule.com'>" 54 " <INPUT type='text' id='username'/>" 55 " <INPUT type='password' id='password'/>" 56 " <INPUT type='submit' value='Login'/>" 57 "</FORM>"; 58 59const char kVisibleFormHTML[] = 60 "<head> <style> form {display: inline;} </style> </head>" 61 "<body>" 62 " <form>" 63 " <div>" 64 " <input type='password' id='password'/>" 65 " </div>" 66 " </form>" 67 "</body>"; 68 69const char kEmptyFormHTML[] = 70 "<head> <style> form {display: inline;} </style> </head>" 71 "<body> <form> </form> </body>"; 72 73const char kNonVisibleFormHTML[] = 74 "<head> <style> form {display: none;} </style> </head>" 75 "<body>" 76 " <form>" 77 " <div>" 78 " <input type='password' id='password'/>" 79 " </div>" 80 " </form>" 81 "</body>"; 82 83const char kEmptyWebpage[] = 84 "<html>" 85 " <head>" 86 " </head>" 87 " <body>" 88 " </body>" 89 "</html>"; 90 91const char kRedirectionWebpage[] = 92 "<html>" 93 " <head>" 94 " <meta http-equiv='Content-Type' content='text/html'>" 95 " <title>Redirection page</title>" 96 " <script></script>" 97 " </head>" 98 " <body>" 99 " <script type='text/javascript'>" 100 " function test(){}" 101 " </script>" 102 " </body>" 103 "</html>"; 104 105const char kSimpleWebpage[] = 106 "<html>" 107 " <head>" 108 " <meta charset='utf-8' />" 109 " <title>Title</title>" 110 " </head>" 111 " <body>" 112 " <form name='LoginTestForm'>" 113 " <input type='text' id='username'/>" 114 " <input type='password' id='password'/>" 115 " <input type='submit' value='Login'/>" 116 " </form>" 117 " </body>" 118 "</html>"; 119 120const char kWebpageWithDynamicContent[] = 121 "<html>" 122 " <head>" 123 " <meta charset='utf-8' />" 124 " <title>Title</title>" 125 " </head>" 126 " <body>" 127 " <script type='text/javascript'>" 128 " function addParagraph() {" 129 " var p = document.createElement('p');" 130 " document.body.appendChild(p);" 131 " }" 132 " window.onload = addParagraph;" 133 " </script>" 134 " </body>" 135 "</html>"; 136 137const char kJavaScriptClick[] = 138 "var event = new MouseEvent('click', {" 139 " 'view': window," 140 " 'bubbles': true," 141 " 'cancelable': true" 142 "});" 143 "var form = document.getElementById('myform1');" 144 "form.dispatchEvent(event);" 145 "console.log('clicked!');"; 146 147const char kOnChangeDetectionScript[] = 148 "<script>" 149 " usernameOnchangeCalled = false;" 150 " passwordOnchangeCalled = false;" 151 " document.getElementById('username').onchange = function() {" 152 " usernameOnchangeCalled = true;" 153 " };" 154 " document.getElementById('password').onchange = function() {" 155 " passwordOnchangeCalled = true;" 156 " };" 157 "</script>"; 158 159// Sets the "readonly" attribute of |element| to the value given by |read_only|. 160void SetElementReadOnly(WebInputElement& element, bool read_only) { 161 element.setAttribute(WebString::fromUTF8("readonly"), 162 read_only ? WebString::fromUTF8("true") : WebString()); 163} 164 165} // namespace 166 167namespace autofill { 168 169class PasswordAutofillAgentTest : public ChromeRenderViewTest { 170 public: 171 PasswordAutofillAgentTest() { 172 } 173 174 // Simulates the fill password form message being sent to the renderer. 175 // We use that so we don't have to make RenderView::OnFillPasswordForm() 176 // protected. 177 void SimulateOnFillPasswordForm( 178 const PasswordFormFillData& fill_data) { 179 AutofillMsg_FillPasswordForm msg(0, fill_data); 180 static_cast<content::RenderViewObserver*>(password_autofill_agent_) 181 ->OnMessageReceived(msg); 182 } 183 184 void SendVisiblePasswordForms() { 185 static_cast<content::RenderViewObserver*>(password_autofill_agent_) 186 ->DidFinishLoad(GetMainFrame()); 187 } 188 189 virtual void SetUp() { 190 ChromeRenderViewTest::SetUp(); 191 192 // Add a preferred login and an additional login to the FillData. 193 username1_ = ASCIIToUTF16(kAliceUsername); 194 password1_ = ASCIIToUTF16(kAlicePassword); 195 username2_ = ASCIIToUTF16(kBobUsername); 196 password2_ = ASCIIToUTF16(kBobPassword); 197 username3_ = ASCIIToUTF16(kCarolUsername); 198 password3_ = ASCIIToUTF16(kCarolPassword); 199 alternate_username3_ = ASCIIToUTF16(kCarolAlternateUsername); 200 201 FormFieldData username_field; 202 username_field.name = ASCIIToUTF16(kUsernameName); 203 username_field.value = username1_; 204 fill_data_.basic_data.fields.push_back(username_field); 205 206 FormFieldData password_field; 207 password_field.name = ASCIIToUTF16(kPasswordName); 208 password_field.value = password1_; 209 password_field.form_control_type = "password"; 210 fill_data_.basic_data.fields.push_back(password_field); 211 212 PasswordAndRealm password2; 213 password2.password = password2_; 214 fill_data_.additional_logins[username2_] = password2; 215 PasswordAndRealm password3; 216 password3.password = password3_; 217 fill_data_.additional_logins[username3_] = password3; 218 219 UsernamesCollectionKey key; 220 key.username = username3_; 221 key.password = password3_; 222 key.realm = "google.com"; 223 fill_data_.other_possible_usernames[key].push_back(alternate_username3_); 224 225 // We need to set the origin so it matches the frame URL and the action so 226 // it matches the form action, otherwise we won't autocomplete. 227 UpdateOriginForHTML(kFormHTML); 228 fill_data_.basic_data.action = GURL("http://www.bidule.com"); 229 230 LoadHTML(kFormHTML); 231 232 // Now retrieve the input elements so the test can access them. 233 UpdateUsernameAndPasswordElements(); 234 } 235 236 virtual void TearDown() { 237 username_element_.reset(); 238 password_element_.reset(); 239 ChromeRenderViewTest::TearDown(); 240 } 241 242 void UpdateOriginForHTML(const std::string& html) { 243 std::string origin = "data:text/html;charset=utf-8," + html; 244 fill_data_.basic_data.origin = GURL(origin); 245 } 246 247 void UpdateUsernameAndPasswordElements() { 248 WebDocument document = GetMainFrame()->document(); 249 WebElement element = 250 document.getElementById(WebString::fromUTF8(kUsernameName)); 251 ASSERT_FALSE(element.isNull()); 252 username_element_ = element.to<blink::WebInputElement>(); 253 element = document.getElementById(WebString::fromUTF8(kPasswordName)); 254 ASSERT_FALSE(element.isNull()); 255 password_element_ = element.to<blink::WebInputElement>(); 256 } 257 258 void ClearUsernameAndPasswordFields() { 259 username_element_.setValue(""); 260 username_element_.setAutofilled(false); 261 password_element_.setValue(""); 262 password_element_.setAutofilled(false); 263 } 264 265 void SimulateDidEndEditing(WebFrame* input_frame, WebInputElement& input) { 266 static_cast<blink::WebAutofillClient*>(autofill_agent_) 267 ->textFieldDidEndEditing(input); 268 } 269 270 void SimulateInputChangeForElement(const std::string& new_value, 271 bool move_caret_to_end, 272 WebFrame* input_frame, 273 WebInputElement& input, 274 bool is_user_input) { 275 input.setValue(WebString::fromUTF8(new_value), is_user_input); 276 // The field must have focus or AutofillAgent will think the 277 // change should be ignored. 278 while (!input.focused()) 279 input_frame->document().frame()->view()->advanceFocus(false); 280 if (move_caret_to_end) 281 input.setSelectionRange(new_value.length(), new_value.length()); 282 if (is_user_input) 283 password_autofill_agent_->FirstUserGestureObserved(); 284 static_cast<blink::WebAutofillClient*>(autofill_agent_) 285 ->textFieldDidChange(input); 286 // Processing is delayed because of a Blink bug: 287 // https://bugs.webkit.org/show_bug.cgi?id=16976 288 // See PasswordAutofillAgent::TextDidChangeInTextField() for details. 289 290 // Autocomplete will trigger a style recalculation when we put up the next 291 // frame, but we don't want to wait that long. Instead, trigger a style 292 // recalcuation manually after TextFieldDidChangeImpl runs. 293 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( 294 &PasswordAutofillAgentTest::LayoutMainFrame, base::Unretained(this))); 295 296 base::MessageLoop::current()->RunUntilIdle(); 297 } 298 299 void SimulateSuggestionChoice(WebInputElement& username_input) { 300 base::string16 username(base::ASCIIToUTF16(kAliceUsername)); 301 base::string16 password(base::ASCIIToUTF16(kAlicePassword)); 302 303 // This call is necessary to setup the autofill agent appropriate for the 304 // user selection; simulates the menu actually popping up. 305 render_thread_->sink().ClearMessages(); 306 static_cast<autofill::PageClickListener*>(autofill_agent_) 307 ->FormControlElementClicked(username_input, false); 308 309 AutofillMsg_FillPasswordSuggestion msg(0, username, password); 310 static_cast<content::RenderViewObserver*>(autofill_agent_) 311 ->OnMessageReceived(msg); 312 } 313 314 void LayoutMainFrame() { 315 GetMainFrame()->view()->layout(); 316 } 317 318 void SimulateUsernameChange(const std::string& username, 319 bool move_caret_to_end, 320 bool is_user_input = false) { 321 SimulateInputChangeForElement(username, 322 move_caret_to_end, 323 GetMainFrame(), 324 username_element_, 325 is_user_input); 326 } 327 328 // Tests that no suggestion popup is generated when the username_element_ is 329 // edited. 330 void ExpectNoSuggestionsPopup() { 331 // The first test below ensures that the suggestions have been handled by 332 // the password_autofill_agent, even though autocomplete='off' is set. The 333 // second check ensures that, although handled, no "show suggestions" IPC to 334 // the browser was generated. 335 // 336 // This is interesting in the specific case of an autocomplete='off' form 337 // that also has a remembered username and password 338 // (http://crbug.com/326679). To fix the DCHECK that this case used to hit, 339 // |true| is returned from ShowSuggestions for all forms with valid 340 // usersnames that are autocomplete='off', prentending that a selection box 341 // has been shown to the user. Of course, it hasn't, so a message is never 342 // sent to the browser on acceptance, and the DCHECK isn't hit (and nothing 343 // is filled). 344 // 345 // These tests only make sense in the context of not ignoring 346 // autocomplete='off', so only test them if the disable autocomplete='off' 347 // flag is not enabled. 348 // TODO(jww): Remove this function and callers once autocomplete='off' is 349 // permanently ignored. 350 if (!ShouldIgnoreAutocompleteOffForPasswordFields()) { 351 EXPECT_TRUE( 352 password_autofill_agent_->ShowSuggestions(username_element_, false)); 353 354 EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching( 355 AutofillHostMsg_ShowPasswordSuggestions::ID)); 356 } 357 } 358 359 void SimulateKeyDownEvent(const WebInputElement& element, 360 ui::KeyboardCode key_code) { 361 blink::WebKeyboardEvent key_event; 362 key_event.windowsKeyCode = key_code; 363 static_cast<blink::WebAutofillClient*>(autofill_agent_) 364 ->textFieldDidReceiveKeyDown(element, key_event); 365 } 366 367 void CheckTextFieldsStateForElements(const WebInputElement& username_element, 368 const std::string& username, 369 bool username_autofilled, 370 const WebInputElement& password_element, 371 const std::string& password, 372 bool password_autofilled, 373 bool checkSuggestedValue) { 374 EXPECT_EQ(username, 375 static_cast<std::string>(username_element.value().utf8())); 376 EXPECT_EQ(username_autofilled, username_element.isAutofilled()); 377 EXPECT_EQ(password, 378 static_cast<std::string>( 379 checkSuggestedValue ? password_element.suggestedValue().utf8() 380 : password_element.value().utf8())) 381 << "checkSuggestedValue == " << checkSuggestedValue; 382 EXPECT_EQ(password_autofilled, password_element.isAutofilled()); 383 } 384 385 // Checks the DOM-accessible value of the username element and the 386 // *suggested* value of the password element. 387 void CheckTextFieldsState(const std::string& username, 388 bool username_autofilled, 389 const std::string& password, 390 bool password_autofilled) { 391 CheckTextFieldsStateForElements(username_element_, 392 username, 393 username_autofilled, 394 password_element_, 395 password, 396 password_autofilled, 397 true); 398 } 399 400 // Checks the DOM-accessible value of the username element and the 401 // DOM-accessible value of the password element. 402 void CheckTextFieldsDOMState(const std::string& username, 403 bool username_autofilled, 404 const std::string& password, 405 bool password_autofilled) { 406 CheckTextFieldsStateForElements(username_element_, 407 username, 408 username_autofilled, 409 password_element_, 410 password, 411 password_autofilled, 412 false); 413 } 414 415 void CheckUsernameSelection(int start, int end) { 416 EXPECT_EQ(start, username_element_.selectionStart()); 417 EXPECT_EQ(end, username_element_.selectionEnd()); 418 } 419 420 void ExpectOneCredential(const base::string16& username) { 421 const IPC::Message* message = 422 render_thread_->sink().GetFirstMessageMatching( 423 AutofillHostMsg_ShowPasswordSuggestions::ID); 424 ASSERT_TRUE(message); 425 Tuple4<autofill::FormFieldData, 426 gfx::RectF, 427 std::vector<base::string16>, 428 std::vector<base::string16> > args; 429 AutofillHostMsg_ShowPasswordSuggestions::Read(message, &args); 430 ASSERT_EQ(1u, args.c.size()); 431 EXPECT_TRUE(args.c[0] == username); 432 } 433 434 void ExpectAllCredentials() { 435 std::set<base::string16> usernames; 436 usernames.insert(username1_); 437 usernames.insert(username2_); 438 usernames.insert(username3_); 439 usernames.insert(alternate_username3_); 440 441 const IPC::Message* message = 442 render_thread_->sink().GetFirstMessageMatching( 443 AutofillHostMsg_ShowPasswordSuggestions::ID); 444 ASSERT_TRUE(message); 445 Tuple4<autofill::FormFieldData, 446 gfx::RectF, 447 std::vector<base::string16>, 448 std::vector<base::string16> > args; 449 AutofillHostMsg_ShowPasswordSuggestions::Read(message, &args); 450 ASSERT_EQ(4u, args.c.size()); 451 std::set<base::string16>::iterator it; 452 453 for (int i = 0; i < 4; i++) { 454 it = usernames.find(args.c[i]); 455 EXPECT_TRUE(it != usernames.end()); 456 if (it != usernames.end()) 457 usernames.erase(it); 458 } 459 460 EXPECT_TRUE(usernames.empty()); 461 462 render_thread_->sink().ClearMessages(); 463 } 464 465 void ExpectFormSubmittedWithPasswords(const std::string& password_value, 466 const std::string& new_password_value) { 467 const IPC::Message* message = 468 render_thread_->sink().GetFirstMessageMatching( 469 AutofillHostMsg_PasswordFormSubmitted::ID); 470 ASSERT_TRUE(message); 471 Tuple1<autofill::PasswordForm> args; 472 AutofillHostMsg_PasswordFormSubmitted::Read(message, &args); 473 EXPECT_EQ(ASCIIToUTF16(password_value), args.a.password_value); 474 EXPECT_EQ(ASCIIToUTF16(new_password_value), args.a.new_password_value); 475 } 476 477 base::string16 username1_; 478 base::string16 username2_; 479 base::string16 username3_; 480 base::string16 password1_; 481 base::string16 password2_; 482 base::string16 password3_; 483 base::string16 alternate_username3_; 484 PasswordFormFillData fill_data_; 485 486 WebInputElement username_element_; 487 WebInputElement password_element_; 488 489 private: 490 DISALLOW_COPY_AND_ASSIGN(PasswordAutofillAgentTest); 491}; 492 493// Tests that the password login is autocompleted as expected when the browser 494// sends back the password info. 495TEST_F(PasswordAutofillAgentTest, InitialAutocomplete) { 496 /* 497 * Right now we are not sending the message to the browser because we are 498 * loading a data URL and the security origin canAccessPasswordManager() 499 * returns false. May be we should mock URL loading to cirmcuvent this? 500 TODO(jcivelli): find a way to make the security origin not deny access to the 501 password manager and then reenable this code. 502 503 // The form has been loaded, we should have sent the browser a message about 504 // the form. 505 const IPC::Message* msg = render_thread_.sink().GetFirstMessageMatching( 506 AutofillHostMsg_PasswordFormsParsed::ID); 507 ASSERT_TRUE(msg != NULL); 508 509 Tuple1<std::vector<PasswordForm> > forms; 510 AutofillHostMsg_PasswordFormsParsed::Read(msg, &forms); 511 ASSERT_EQ(1U, forms.a.size()); 512 PasswordForm password_form = forms.a[0]; 513 EXPECT_EQ(PasswordForm::SCHEME_HTML, password_form.scheme); 514 EXPECT_EQ(ASCIIToUTF16(kUsernameName), password_form.username_element); 515 EXPECT_EQ(ASCIIToUTF16(kPasswordName), password_form.password_element); 516 */ 517 518 // Simulate the browser sending back the login info, it triggers the 519 // autocomplete. 520 SimulateOnFillPasswordForm(fill_data_); 521 522 // The username and password should have been autocompleted. 523 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); 524} 525 526// Tests that we correctly fill forms having an empty 'action' attribute. 527TEST_F(PasswordAutofillAgentTest, InitialAutocompleteForEmptyAction) { 528 const char kEmptyActionFormHTML[] = 529 "<FORM name='LoginTestForm'>" 530 " <INPUT type='text' id='username'/>" 531 " <INPUT type='password' id='password'/>" 532 " <INPUT type='submit' value='Login'/>" 533 "</FORM>"; 534 LoadHTML(kEmptyActionFormHTML); 535 536 // Retrieve the input elements so the test can access them. 537 WebDocument document = GetMainFrame()->document(); 538 WebElement element = 539 document.getElementById(WebString::fromUTF8(kUsernameName)); 540 ASSERT_FALSE(element.isNull()); 541 username_element_ = element.to<blink::WebInputElement>(); 542 element = document.getElementById(WebString::fromUTF8(kPasswordName)); 543 ASSERT_FALSE(element.isNull()); 544 password_element_ = element.to<blink::WebInputElement>(); 545 546 // Set the expected form origin and action URLs. 547 UpdateOriginForHTML(kEmptyActionFormHTML); 548 fill_data_.basic_data.action = fill_data_.basic_data.origin; 549 550 // Simulate the browser sending back the login info, it triggers the 551 // autocomplete. 552 SimulateOnFillPasswordForm(fill_data_); 553 554 // The username and password should have been autocompleted. 555 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); 556} 557 558// Tests that if a password is marked as readonly, neither field is autofilled 559// on page load. 560TEST_F(PasswordAutofillAgentTest, NoInitialAutocompleteForReadOnlyPassword) { 561 SetElementReadOnly(password_element_, true); 562 563 // Simulate the browser sending back the login info, it triggers the 564 // autocomplete. 565 SimulateOnFillPasswordForm(fill_data_); 566 567 CheckTextFieldsState(std::string(), false, std::string(), false); 568} 569 570// Can still fill a password field if the username is set to a value that 571// matches. 572TEST_F(PasswordAutofillAgentTest, 573 AutocompletePasswordForReadonlyUsernameMatched) { 574 username_element_.setValue(username3_); 575 SetElementReadOnly(username_element_, true); 576 577 // Filled even though username is not the preferred match. 578 SimulateOnFillPasswordForm(fill_data_); 579 CheckTextFieldsState(UTF16ToUTF8(username3_), false, 580 UTF16ToUTF8(password3_), true); 581} 582 583// If a username field is empty and readonly, don't autofill. 584TEST_F(PasswordAutofillAgentTest, 585 NoAutocompletePasswordForReadonlyUsernameUnmatched) { 586 username_element_.setValue(WebString::fromUTF8("")); 587 SetElementReadOnly(username_element_, true); 588 589 SimulateOnFillPasswordForm(fill_data_); 590 CheckTextFieldsState(std::string(), false, std::string(), false); 591} 592 593// Tests that having a non-matching username precludes the autocomplete. 594TEST_F(PasswordAutofillAgentTest, NoAutocompleteForFilledFieldUnmatched) { 595 username_element_.setValue(WebString::fromUTF8("bogus")); 596 597 // Simulate the browser sending back the login info, it triggers the 598 // autocomplete. 599 SimulateOnFillPasswordForm(fill_data_); 600 601 // Neither field should be autocompleted. 602 CheckTextFieldsState("bogus", false, std::string(), false); 603} 604 605// Don't try to complete a prefilled value even if it's a partial match 606// to a username. 607TEST_F(PasswordAutofillAgentTest, NoPartialMatchForPrefilledUsername) { 608 username_element_.setValue(WebString::fromUTF8("ali")); 609 610 SimulateOnFillPasswordForm(fill_data_); 611 612 CheckTextFieldsState("ali", false, std::string(), false); 613} 614 615TEST_F(PasswordAutofillAgentTest, InputWithNoForms) { 616 const char kNoFormInputs[] = 617 "<input type='text' id='username'/>" 618 "<input type='password' id='password'/>"; 619 LoadHTML(kNoFormInputs); 620 621 SimulateOnFillPasswordForm(fill_data_); 622 623 // Input elements that aren't in a <form> won't autofill. 624 CheckTextFieldsState(std::string(), false, std::string(), false); 625} 626 627TEST_F(PasswordAutofillAgentTest, NoAutocompleteForTextFieldPasswords) { 628 const char kTextFieldPasswordFormHTML[] = 629 "<FORM name='LoginTestForm' action='http://www.bidule.com'>" 630 " <INPUT type='text' id='username'/>" 631 " <INPUT type='text' id='password'/>" 632 " <INPUT type='submit' value='Login'/>" 633 "</FORM>"; 634 LoadHTML(kTextFieldPasswordFormHTML); 635 636 // Retrieve the input elements so the test can access them. 637 WebDocument document = GetMainFrame()->document(); 638 WebElement element = 639 document.getElementById(WebString::fromUTF8(kUsernameName)); 640 ASSERT_FALSE(element.isNull()); 641 username_element_ = element.to<blink::WebInputElement>(); 642 element = document.getElementById(WebString::fromUTF8(kPasswordName)); 643 ASSERT_FALSE(element.isNull()); 644 password_element_ = element.to<blink::WebInputElement>(); 645 646 // Set the expected form origin URL. 647 UpdateOriginForHTML(kTextFieldPasswordFormHTML); 648 649 SimulateOnFillPasswordForm(fill_data_); 650 651 // Fields should still be empty. 652 CheckTextFieldsState(std::string(), false, std::string(), false); 653} 654 655TEST_F(PasswordAutofillAgentTest, NoAutocompleteForPasswordFieldUsernames) { 656 const char kPasswordFieldUsernameFormHTML[] = 657 "<FORM name='LoginTestForm' action='http://www.bidule.com'>" 658 " <INPUT type='password' id='username'/>" 659 " <INPUT type='password' id='password'/>" 660 " <INPUT type='submit' value='Login'/>" 661 "</FORM>"; 662 LoadHTML(kPasswordFieldUsernameFormHTML); 663 664 // Retrieve the input elements so the test can access them. 665 WebDocument document = GetMainFrame()->document(); 666 WebElement element = 667 document.getElementById(WebString::fromUTF8(kUsernameName)); 668 ASSERT_FALSE(element.isNull()); 669 username_element_ = element.to<blink::WebInputElement>(); 670 element = document.getElementById(WebString::fromUTF8(kPasswordName)); 671 ASSERT_FALSE(element.isNull()); 672 password_element_ = element.to<blink::WebInputElement>(); 673 674 // Set the expected form origin URL. 675 UpdateOriginForHTML(kPasswordFieldUsernameFormHTML); 676 677 SimulateOnFillPasswordForm(fill_data_); 678 679 // Fields should still be empty. 680 CheckTextFieldsState(std::string(), false, std::string(), false); 681} 682 683// Tests that having a matching username does not preclude the autocomplete. 684TEST_F(PasswordAutofillAgentTest, InitialAutocompleteForMatchingFilledField) { 685 username_element_.setValue(WebString::fromUTF8(kAliceUsername)); 686 687 // Simulate the browser sending back the login info, it triggers the 688 // autocomplete. 689 SimulateOnFillPasswordForm(fill_data_); 690 691 // The username and password should have been autocompleted. 692 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); 693} 694 695// Tests that editing the password clears the autocompleted password field. 696TEST_F(PasswordAutofillAgentTest, PasswordClearOnEdit) { 697 // Simulate the browser sending back the login info, it triggers the 698 // autocomplete. 699 SimulateOnFillPasswordForm(fill_data_); 700 701 // Simulate the user changing the username to some unknown username. 702 SimulateUsernameChange("alicia", true); 703 704 // The password should have been cleared. 705 CheckTextFieldsState("alicia", false, std::string(), false); 706} 707 708// Tests that we only autocomplete on focus lost and with a full username match 709// when |wait_for_username| is true. 710TEST_F(PasswordAutofillAgentTest, WaitUsername) { 711 // Simulate the browser sending back the login info. 712 fill_data_.wait_for_username = true; 713 SimulateOnFillPasswordForm(fill_data_); 714 715 // No auto-fill should have taken place. 716 CheckTextFieldsState(std::string(), false, std::string(), false); 717 718 // No autocomplete should happen when text is entered in the username. 719 SimulateUsernameChange("a", true); 720 CheckTextFieldsState("a", false, std::string(), false); 721 SimulateUsernameChange("al", true); 722 CheckTextFieldsState("al", false, std::string(), false); 723 SimulateUsernameChange(kAliceUsername, true); 724 CheckTextFieldsState(kAliceUsername, false, std::string(), false); 725 726 // Autocomplete should happen only when the username textfield is blurred with 727 // a full match. 728 username_element_.setValue("a"); 729 static_cast<blink::WebAutofillClient*>(autofill_agent_) 730 ->textFieldDidEndEditing(username_element_); 731 CheckTextFieldsState("a", false, std::string(), false); 732 username_element_.setValue("al"); 733 static_cast<blink::WebAutofillClient*>(autofill_agent_) 734 ->textFieldDidEndEditing(username_element_); 735 CheckTextFieldsState("al", false, std::string(), false); 736 username_element_.setValue("alices"); 737 static_cast<blink::WebAutofillClient*>(autofill_agent_) 738 ->textFieldDidEndEditing(username_element_); 739 CheckTextFieldsState("alices", false, std::string(), false); 740 username_element_.setValue(ASCIIToUTF16(kAliceUsername)); 741 static_cast<blink::WebAutofillClient*>(autofill_agent_) 742 ->textFieldDidEndEditing(username_element_); 743 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); 744} 745 746// Tests that inline autocompletion works properly. 747TEST_F(PasswordAutofillAgentTest, InlineAutocomplete) { 748 // Simulate the browser sending back the login info. 749 SimulateOnFillPasswordForm(fill_data_); 750 751 ClearUsernameAndPasswordFields(); 752 753 // Simulate the user typing in the first letter of 'alice', a stored 754 // username. 755 SimulateUsernameChange("a", true); 756 // Both the username and password text fields should reflect selection of the 757 // stored login. 758 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); 759 // And the selection should have been set to 'lice', the last 4 letters. 760 CheckUsernameSelection(1, 5); 761 762 // Now the user types the next letter of the same username, 'l'. 763 SimulateUsernameChange("al", true); 764 // Now the fields should have the same value, but the selection should have a 765 // different start value. 766 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); 767 CheckUsernameSelection(2, 5); 768 769 // Test that deleting does not trigger autocomplete. 770 SimulateKeyDownEvent(username_element_, ui::VKEY_BACK); 771 SimulateUsernameChange("alic", true); 772 CheckTextFieldsState("alic", false, std::string(), false); 773 CheckUsernameSelection(4, 4); // No selection. 774 // Reset the last pressed key to something other than backspace. 775 SimulateKeyDownEvent(username_element_, ui::VKEY_A); 776 777 // Now lets say the user goes astray from the stored username and types the 778 // letter 'f', spelling 'alf'. We don't know alf (that's just sad), so in 779 // practice the username should no longer be 'alice' and the selected range 780 // should be empty. 781 SimulateUsernameChange("alf", true); 782 CheckTextFieldsState("alf", false, std::string(), false); 783 CheckUsernameSelection(3, 3); // No selection. 784 785 // Ok, so now the user removes all the text and enters the letter 'b'. 786 SimulateUsernameChange("b", true); 787 // The username and password fields should match the 'bob' entry. 788 CheckTextFieldsState(kBobUsername, true, kBobPassword, true); 789 CheckUsernameSelection(1, 3); 790 791 // Then, the user again removes all the text and types an uppercase 'C'. 792 SimulateUsernameChange("C", true); 793 // The username and password fields should match the 'Carol' entry. 794 CheckTextFieldsState(kCarolUsername, true, kCarolPassword, true); 795 CheckUsernameSelection(1, 5); 796 // The user removes all the text and types a lowercase 'c'. We only 797 // want case-sensitive autocompletion, so the username and the selected range 798 // should be empty. 799 SimulateUsernameChange("c", true); 800 CheckTextFieldsState("c", false, std::string(), false); 801 CheckUsernameSelection(1, 1); 802 803 // Check that we complete other_possible_usernames as well. 804 SimulateUsernameChange("R", true); 805 CheckTextFieldsState(kCarolAlternateUsername, true, kCarolPassword, true); 806 CheckUsernameSelection(1, 17); 807} 808 809TEST_F(PasswordAutofillAgentTest, IsWebNodeVisibleTest) { 810 blink::WebVector<blink::WebFormElement> forms1, forms2, forms3; 811 blink::WebFrame* frame; 812 813 LoadHTML(kVisibleFormHTML); 814 frame = GetMainFrame(); 815 frame->document().forms(forms1); 816 ASSERT_EQ(1u, forms1.size()); 817 EXPECT_TRUE(IsWebNodeVisible(forms1[0])); 818 819 LoadHTML(kEmptyFormHTML); 820 frame = GetMainFrame(); 821 frame->document().forms(forms2); 822 ASSERT_EQ(1u, forms2.size()); 823 EXPECT_FALSE(IsWebNodeVisible(forms2[0])); 824 825 LoadHTML(kNonVisibleFormHTML); 826 frame = GetMainFrame(); 827 frame->document().forms(forms3); 828 ASSERT_EQ(1u, forms3.size()); 829 EXPECT_FALSE(IsWebNodeVisible(forms3[0])); 830} 831 832TEST_F(PasswordAutofillAgentTest, SendPasswordFormsTest) { 833 render_thread_->sink().ClearMessages(); 834 LoadHTML(kVisibleFormHTML); 835 const IPC::Message* message = render_thread_->sink() 836 .GetFirstMessageMatching(AutofillHostMsg_PasswordFormsRendered::ID); 837 EXPECT_TRUE(message); 838 Tuple2<std::vector<autofill::PasswordForm>, bool > param; 839 AutofillHostMsg_PasswordFormsRendered::Read(message, ¶m); 840 EXPECT_TRUE(param.a.size()); 841 842 render_thread_->sink().ClearMessages(); 843 LoadHTML(kEmptyFormHTML); 844 message = render_thread_->sink().GetFirstMessageMatching( 845 AutofillHostMsg_PasswordFormsRendered::ID); 846 EXPECT_TRUE(message); 847 AutofillHostMsg_PasswordFormsRendered::Read(message, ¶m); 848 EXPECT_FALSE(param.a.size()); 849 850 render_thread_->sink().ClearMessages(); 851 LoadHTML(kNonVisibleFormHTML); 852 message = render_thread_->sink().GetFirstMessageMatching( 853 AutofillHostMsg_PasswordFormsRendered::ID); 854 EXPECT_TRUE(message); 855 AutofillHostMsg_PasswordFormsRendered::Read(message, ¶m); 856 EXPECT_FALSE(param.a.size()); 857} 858 859TEST_F(PasswordAutofillAgentTest, SendPasswordFormsTest_Redirection) { 860 render_thread_->sink().ClearMessages(); 861 LoadHTML(kEmptyWebpage); 862 EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching( 863 AutofillHostMsg_PasswordFormsRendered::ID)); 864 865 render_thread_->sink().ClearMessages(); 866 LoadHTML(kRedirectionWebpage); 867 EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching( 868 AutofillHostMsg_PasswordFormsRendered::ID)); 869 870 render_thread_->sink().ClearMessages(); 871 LoadHTML(kSimpleWebpage); 872 EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching( 873 AutofillHostMsg_PasswordFormsRendered::ID)); 874 875 render_thread_->sink().ClearMessages(); 876 LoadHTML(kWebpageWithDynamicContent); 877 EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching( 878 AutofillHostMsg_PasswordFormsRendered::ID)); 879} 880 881// Tests that a password form in an iframe will not be filled in until a user 882// interaction with the form. 883TEST_F(PasswordAutofillAgentTest, IframeNoFillTest) { 884 const char kIframeName[] = "iframe"; 885 const char kWebpageWithIframeStart[] = 886 "<html>" 887 " <head>" 888 " <meta charset='utf-8' />" 889 " <title>Title</title>" 890 " </head>" 891 " <body>" 892 " <iframe name='iframe' src=\""; 893 const char kWebpageWithIframeEnd[] = 894 "\"></iframe>" 895 " </body>" 896 "</html>"; 897 898 std::string origin("data:text/html;charset=utf-8,"); 899 origin += kSimpleWebpage; 900 901 std::string page_html(kWebpageWithIframeStart); 902 page_html += origin; 903 page_html += kWebpageWithIframeEnd; 904 905 LoadHTML(page_html.c_str()); 906 907 // Set the expected form origin and action URLs. 908 fill_data_.basic_data.origin = GURL(origin); 909 fill_data_.basic_data.action = GURL(origin); 910 911 SimulateOnFillPasswordForm(fill_data_); 912 913 // Retrieve the input elements from the iframe since that is where we want to 914 // test the autofill. 915 WebFrame* iframe = GetMainFrame()->findChildByName(kIframeName); 916 ASSERT_TRUE(iframe); 917 WebDocument document = iframe->document(); 918 919 WebElement username_element = document.getElementById(kUsernameName); 920 WebElement password_element = document.getElementById(kPasswordName); 921 ASSERT_FALSE(username_element.isNull()); 922 ASSERT_FALSE(password_element.isNull()); 923 924 WebInputElement username_input = username_element.to<WebInputElement>(); 925 WebInputElement password_input = password_element.to<WebInputElement>(); 926 ASSERT_FALSE(username_element.isNull()); 927 928 CheckTextFieldsStateForElements( 929 username_input, "", false, password_input, "", false, false); 930 931 // Simulate the user typing in the username in the iframe which should cause 932 // an autofill. 933 SimulateInputChangeForElement( 934 kAliceUsername, true, iframe, username_input, true); 935 936 CheckTextFieldsStateForElements(username_input, 937 kAliceUsername, 938 true, 939 password_input, 940 kAlicePassword, 941 true, 942 false); 943} 944 945// Tests that a password will only be filled as a suggested and will not be 946// accessible by the DOM until a user gesture has occurred. 947TEST_F(PasswordAutofillAgentTest, GestureRequiredTest) { 948 // Trigger the initial autocomplete. 949 SimulateOnFillPasswordForm(fill_data_); 950 951 // The username and password should have been autocompleted. 952 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); 953 954 // However, it should only have completed with the suggested value, as tested 955 // above, and it should not have completed into the DOM accessible value for 956 // the password field. 957 CheckTextFieldsDOMState(kAliceUsername, true, std::string(), true); 958 959 // Simulate a user click so that the password field's real value is filled. 960 SimulateElementClick(kUsernameName); 961 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); 962} 963 964// Verfies that a DOM-activated UI event will not cause an autofill. 965TEST_F(PasswordAutofillAgentTest, NoDOMActivationTest) { 966 // Trigger the initial autocomplete. 967 SimulateOnFillPasswordForm(fill_data_); 968 969 ExecuteJavaScript(kJavaScriptClick); 970 CheckTextFieldsDOMState(kAliceUsername, true, "", true); 971} 972 973// Regression test for http://crbug.com/326679 974TEST_F(PasswordAutofillAgentTest, SelectUsernameWithUsernameAutofillOff) { 975 // Simulate the browser sending back the login info. 976 SimulateOnFillPasswordForm(fill_data_); 977 978 // Set the username element to autocomplete='off' 979 username_element_.setAttribute(WebString::fromUTF8("autocomplete"), 980 WebString::fromUTF8("off")); 981 982 // Simulate the user changing the username to some known username. 983 SimulateUsernameChange(kAliceUsername, true); 984 985 ExpectNoSuggestionsPopup(); 986} 987 988// Regression test for http://crbug.com/326679 989TEST_F(PasswordAutofillAgentTest, 990 SelectUnknownUsernameWithUsernameAutofillOff) { 991 // Simulate the browser sending back the login info. 992 SimulateOnFillPasswordForm(fill_data_); 993 994 // Set the username element to autocomplete='off' 995 username_element_.setAttribute(WebString::fromUTF8("autocomplete"), 996 WebString::fromUTF8("off")); 997 998 // Simulate the user changing the username to some unknown username. 999 SimulateUsernameChange("foo", true); 1000 1001 ExpectNoSuggestionsPopup(); 1002} 1003 1004// Regression test for http://crbug.com/326679 1005TEST_F(PasswordAutofillAgentTest, SelectUsernameWithPasswordAutofillOff) { 1006 // Simulate the browser sending back the login info. 1007 SimulateOnFillPasswordForm(fill_data_); 1008 1009 // Set the main password element to autocomplete='off' 1010 password_element_.setAttribute(WebString::fromUTF8("autocomplete"), 1011 WebString::fromUTF8("off")); 1012 1013 // Simulate the user changing the username to some known username. 1014 SimulateUsernameChange(kAliceUsername, true); 1015 1016 ExpectNoSuggestionsPopup(); 1017} 1018 1019// Regression test for http://crbug.com/326679 1020TEST_F(PasswordAutofillAgentTest, 1021 SelectUnknownUsernameWithPasswordAutofillOff) { 1022 // Simulate the browser sending back the login info. 1023 SimulateOnFillPasswordForm(fill_data_); 1024 1025 // Set the main password element to autocomplete='off' 1026 password_element_.setAttribute(WebString::fromUTF8("autocomplete"), 1027 WebString::fromUTF8("off")); 1028 1029 // Simulate the user changing the username to some unknown username. 1030 SimulateUsernameChange("foo", true); 1031 1032 ExpectNoSuggestionsPopup(); 1033} 1034 1035// Verifies that password autofill triggers onChange events in JavaScript for 1036// forms that are filled on page load. 1037TEST_F(PasswordAutofillAgentTest, 1038 PasswordAutofillTriggersOnChangeEventsOnLoad) { 1039 std::string html = std::string(kFormHTML) + kOnChangeDetectionScript; 1040 LoadHTML(html.c_str()); 1041 UpdateOriginForHTML(html); 1042 UpdateUsernameAndPasswordElements(); 1043 1044 // Simulate the browser sending back the login info, it triggers the 1045 // autocomplete. 1046 SimulateOnFillPasswordForm(fill_data_); 1047 1048 // The username and password should have been autocompleted... 1049 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); 1050 // ... but since there hasn't been a user gesture yet, the autocompleted 1051 // password should only be visible to the user. 1052 CheckTextFieldsDOMState(kAliceUsername, true, std::string(), true); 1053 1054 // A JavaScript onChange event should have been triggered for the username, 1055 // but not yet for the password. 1056 int username_onchange_called = -1; 1057 int password_onchange_called = -1; 1058 ASSERT_TRUE( 1059 ExecuteJavaScriptAndReturnIntValue( 1060 ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"), 1061 &username_onchange_called)); 1062 EXPECT_EQ(1, username_onchange_called); 1063 ASSERT_TRUE( 1064 ExecuteJavaScriptAndReturnIntValue( 1065 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"), 1066 &password_onchange_called)); 1067 // TODO(isherman): Re-enable this check once http://crbug.com/333144 is fixed. 1068 // EXPECT_EQ(0, password_onchange_called); 1069 1070 // Simulate a user click so that the password field's real value is filled. 1071 SimulateElementClick(kUsernameName); 1072 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); 1073 1074 // Now, a JavaScript onChange event should have been triggered for the 1075 // password as well. 1076 ASSERT_TRUE( 1077 ExecuteJavaScriptAndReturnIntValue( 1078 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"), 1079 &password_onchange_called)); 1080 EXPECT_EQ(1, password_onchange_called); 1081} 1082 1083// Verifies that password autofill triggers onChange events in JavaScript for 1084// forms that are filled after page load. 1085TEST_F(PasswordAutofillAgentTest, 1086 PasswordAutofillTriggersOnChangeEventsWaitForUsername) { 1087 std::string html = std::string(kFormHTML) + kOnChangeDetectionScript; 1088 LoadHTML(html.c_str()); 1089 UpdateOriginForHTML(html); 1090 UpdateUsernameAndPasswordElements(); 1091 1092 // Simulate the browser sending back the login info, it triggers the 1093 // autocomplete. 1094 fill_data_.wait_for_username = true; 1095 SimulateOnFillPasswordForm(fill_data_); 1096 1097 // The username and password should not yet have been autocompleted. 1098 CheckTextFieldsState(std::string(), false, std::string(), false); 1099 1100 // Simulate a click just to force a user gesture, since the username value is 1101 // set directly. 1102 SimulateElementClick(kUsernameName); 1103 1104 // Simulate the user entering her username and selecting the matching autofill 1105 // from the dropdown. 1106 SimulateUsernameChange(kAliceUsername, true, true); 1107 SimulateSuggestionChoice(username_element_); 1108 1109 // The username and password should now have been autocompleted. 1110 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); 1111 1112 // JavaScript onChange events should have been triggered both for the username 1113 // and for the password. 1114 int username_onchange_called = -1; 1115 int password_onchange_called = -1; 1116 ASSERT_TRUE( 1117 ExecuteJavaScriptAndReturnIntValue( 1118 ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"), 1119 &username_onchange_called)); 1120 EXPECT_EQ(1, username_onchange_called); 1121 ASSERT_TRUE( 1122 ExecuteJavaScriptAndReturnIntValue( 1123 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"), 1124 &password_onchange_called)); 1125 EXPECT_EQ(1, password_onchange_called); 1126} 1127 1128// Tests that |FillSuggestion| properly fills the username and password. 1129TEST_F(PasswordAutofillAgentTest, FillSuggestion) { 1130 // Simulate the browser sending the login info, but set |wait_for_username| 1131 // to prevent the form from being immediately filled. 1132 fill_data_.wait_for_username = true; 1133 SimulateOnFillPasswordForm(fill_data_); 1134 1135 // Neither field should have been autocompleted. 1136 CheckTextFieldsDOMState(std::string(), false, std::string(), false); 1137 1138 // If the password field is not autocompletable, it should not be affected. 1139 SetElementReadOnly(password_element_, true); 1140 EXPECT_FALSE(password_autofill_agent_->FillSuggestion( 1141 username_element_, kAliceUsername, kAlicePassword)); 1142 CheckTextFieldsDOMState(std::string(), false, std::string(), false); 1143 SetElementReadOnly(password_element_, false); 1144 1145 // After filling with the suggestion, both fields should be autocompleted. 1146 EXPECT_TRUE(password_autofill_agent_->FillSuggestion( 1147 username_element_, kAliceUsername, kAlicePassword)); 1148 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); 1149 int username_length = strlen(kAliceUsername); 1150 CheckUsernameSelection(username_length, username_length); 1151 1152 // Try Filling with a suggestion with password different from the one that was 1153 // initially sent to the renderer. 1154 EXPECT_TRUE(password_autofill_agent_->FillSuggestion( 1155 username_element_, kBobUsername, kCarolPassword)); 1156 CheckTextFieldsDOMState(kBobUsername, true, kCarolPassword, true); 1157 username_length = strlen(kBobUsername); 1158 CheckUsernameSelection(username_length, username_length); 1159} 1160 1161// Tests that |PreviewSuggestion| properly previews the username and password. 1162TEST_F(PasswordAutofillAgentTest, PreviewSuggestion) { 1163 // Simulate the browser sending the login info, but set |wait_for_username| 1164 // to prevent the form from being immediately filled. 1165 fill_data_.wait_for_username = true; 1166 SimulateOnFillPasswordForm(fill_data_); 1167 1168 // Neither field should have been autocompleted. 1169 CheckTextFieldsDOMState(std::string(), false, std::string(), false); 1170 1171 // If the password field is not autocompletable, it should not be affected. 1172 SetElementReadOnly(password_element_, true); 1173 EXPECT_FALSE(password_autofill_agent_->PreviewSuggestion( 1174 username_element_, kAliceUsername, kAlicePassword)); 1175 EXPECT_EQ(std::string(), username_element_.suggestedValue().utf8()); 1176 EXPECT_FALSE(username_element_.isAutofilled()); 1177 EXPECT_EQ(std::string(), password_element_.suggestedValue().utf8()); 1178 EXPECT_FALSE(password_element_.isAutofilled()); 1179 SetElementReadOnly(password_element_, false); 1180 1181 // After selecting the suggestion, both fields should be previewed 1182 // with suggested values. 1183 EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion( 1184 username_element_, kAliceUsername, kAlicePassword)); 1185 EXPECT_EQ( 1186 kAliceUsername, 1187 static_cast<std::string>(username_element_.suggestedValue().utf8())); 1188 EXPECT_TRUE(username_element_.isAutofilled()); 1189 EXPECT_EQ( 1190 kAlicePassword, 1191 static_cast<std::string>(password_element_.suggestedValue().utf8())); 1192 EXPECT_TRUE(password_element_.isAutofilled()); 1193 int username_length = strlen(kAliceUsername); 1194 CheckUsernameSelection(0, username_length); 1195 1196 // Try previewing with a password different from the one that was initially 1197 // sent to the renderer. 1198 EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion( 1199 username_element_, kBobUsername, kCarolPassword)); 1200 EXPECT_EQ( 1201 kBobUsername, 1202 static_cast<std::string>(username_element_.suggestedValue().utf8())); 1203 EXPECT_TRUE(username_element_.isAutofilled()); 1204 EXPECT_EQ( 1205 kCarolPassword, 1206 static_cast<std::string>(password_element_.suggestedValue().utf8())); 1207 EXPECT_TRUE(password_element_.isAutofilled()); 1208 username_length = strlen(kBobUsername); 1209 CheckUsernameSelection(0, username_length); 1210} 1211 1212// Tests that |PreviewSuggestion| properly sets the username selection range. 1213TEST_F(PasswordAutofillAgentTest, PreviewSuggestionSelectionRange) { 1214 username_element_.setValue(WebString::fromUTF8("ali")); 1215 username_element_.setSelectionRange(3, 3); 1216 username_element_.setAutofilled(true); 1217 1218 CheckTextFieldsDOMState("ali", true, std::string(), false); 1219 1220 // Simulate the browser sending the login info, but set |wait_for_username| 1221 // to prevent the form from being immediately filled. 1222 fill_data_.wait_for_username = true; 1223 SimulateOnFillPasswordForm(fill_data_); 1224 1225 EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion( 1226 username_element_, kAliceUsername, kAlicePassword)); 1227 EXPECT_EQ( 1228 kAliceUsername, 1229 static_cast<std::string>(username_element_.suggestedValue().utf8())); 1230 EXPECT_TRUE(username_element_.isAutofilled()); 1231 EXPECT_EQ( 1232 kAlicePassword, 1233 static_cast<std::string>(password_element_.suggestedValue().utf8())); 1234 EXPECT_TRUE(password_element_.isAutofilled()); 1235 int username_length = strlen(kAliceUsername); 1236 CheckUsernameSelection(3, username_length); 1237} 1238 1239// Tests that |ClearPreview| properly clears previewed username and password 1240// with password being previously autofilled. 1241TEST_F(PasswordAutofillAgentTest, ClearPreviewWithPasswordAutofilled) { 1242 password_element_.setValue(WebString::fromUTF8("sec")); 1243 password_element_.setAutofilled(true); 1244 1245 // Simulate the browser sending the login info, but set |wait_for_username| 1246 // to prevent the form from being immediately filled. 1247 fill_data_.wait_for_username = true; 1248 SimulateOnFillPasswordForm(fill_data_); 1249 1250 CheckTextFieldsDOMState(std::string(), false, "sec", true); 1251 1252 EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion( 1253 username_element_, kAliceUsername, kAlicePassword)); 1254 1255 EXPECT_TRUE( 1256 password_autofill_agent_->DidClearAutofillSelection(username_element_)); 1257 1258 EXPECT_TRUE(username_element_.value().isEmpty()); 1259 EXPECT_TRUE(username_element_.suggestedValue().isEmpty()); 1260 EXPECT_FALSE(username_element_.isAutofilled()); 1261 EXPECT_EQ(ASCIIToUTF16("sec"), password_element_.value()); 1262 EXPECT_TRUE(password_element_.suggestedValue().isEmpty()); 1263 EXPECT_TRUE(password_element_.isAutofilled()); 1264 CheckUsernameSelection(0, 0); 1265} 1266 1267// Tests that |ClearPreview| properly clears previewed username and password 1268// with username being previously autofilled. 1269TEST_F(PasswordAutofillAgentTest, ClearPreviewWithUsernameAutofilled) { 1270 username_element_.setValue(WebString::fromUTF8("ali")); 1271 username_element_.setSelectionRange(3, 3); 1272 username_element_.setAutofilled(true); 1273 1274 // Simulate the browser sending the login info, but set |wait_for_username| 1275 // to prevent the form from being immediately filled. 1276 fill_data_.wait_for_username = true; 1277 SimulateOnFillPasswordForm(fill_data_); 1278 1279 CheckTextFieldsDOMState("ali", true, std::string(), false); 1280 1281 EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion( 1282 username_element_, kAliceUsername, kAlicePassword)); 1283 1284 EXPECT_TRUE( 1285 password_autofill_agent_->DidClearAutofillSelection(username_element_)); 1286 1287 EXPECT_EQ(ASCIIToUTF16("ali"), username_element_.value()); 1288 EXPECT_TRUE(username_element_.suggestedValue().isEmpty()); 1289 EXPECT_TRUE(username_element_.isAutofilled()); 1290 EXPECT_TRUE(password_element_.value().isEmpty()); 1291 EXPECT_TRUE(password_element_.suggestedValue().isEmpty()); 1292 EXPECT_FALSE(password_element_.isAutofilled()); 1293 CheckUsernameSelection(3, 3); 1294} 1295 1296// Tests that |ClearPreview| properly clears previewed username and password 1297// with username and password being previously autofilled. 1298TEST_F(PasswordAutofillAgentTest, 1299 ClearPreviewWithAutofilledUsernameAndPassword) { 1300 username_element_.setValue(WebString::fromUTF8("ali")); 1301 username_element_.setSelectionRange(3, 3); 1302 username_element_.setAutofilled(true); 1303 password_element_.setValue(WebString::fromUTF8("sec")); 1304 password_element_.setAutofilled(true); 1305 1306 // Simulate the browser sending the login info, but set |wait_for_username| 1307 // to prevent the form from being immediately filled. 1308 fill_data_.wait_for_username = true; 1309 SimulateOnFillPasswordForm(fill_data_); 1310 1311 CheckTextFieldsDOMState("ali", true, "sec", true); 1312 1313 EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion( 1314 username_element_, kAliceUsername, kAlicePassword)); 1315 1316 EXPECT_TRUE( 1317 password_autofill_agent_->DidClearAutofillSelection(username_element_)); 1318 1319 EXPECT_EQ(ASCIIToUTF16("ali"), username_element_.value()); 1320 EXPECT_TRUE(username_element_.suggestedValue().isEmpty()); 1321 EXPECT_TRUE(username_element_.isAutofilled()); 1322 EXPECT_EQ(ASCIIToUTF16("sec"), password_element_.value()); 1323 EXPECT_TRUE(password_element_.suggestedValue().isEmpty()); 1324 EXPECT_TRUE(password_element_.isAutofilled()); 1325 CheckUsernameSelection(3, 3); 1326} 1327 1328// Tests that |ClearPreview| properly clears previewed username and password 1329// with neither username nor password being previously autofilled. 1330TEST_F(PasswordAutofillAgentTest, 1331 ClearPreviewWithNotAutofilledUsernameAndPassword) { 1332 // Simulate the browser sending the login info, but set |wait_for_username| 1333 // to prevent the form from being immediately filled. 1334 fill_data_.wait_for_username = true; 1335 SimulateOnFillPasswordForm(fill_data_); 1336 1337 CheckTextFieldsDOMState(std::string(), false, std::string(), false); 1338 1339 EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion( 1340 username_element_, kAliceUsername, kAlicePassword)); 1341 1342 EXPECT_TRUE( 1343 password_autofill_agent_->DidClearAutofillSelection(username_element_)); 1344 1345 EXPECT_TRUE(username_element_.value().isEmpty()); 1346 EXPECT_TRUE(username_element_.suggestedValue().isEmpty()); 1347 EXPECT_FALSE(username_element_.isAutofilled()); 1348 EXPECT_TRUE(password_element_.value().isEmpty()); 1349 EXPECT_TRUE(password_element_.suggestedValue().isEmpty()); 1350 EXPECT_FALSE(password_element_.isAutofilled()); 1351 CheckUsernameSelection(0, 0); 1352} 1353 1354// Tests that |ClearPreview| properly restores the original selection range of 1355// username field that has initially been filled by inline autocomplete. 1356TEST_F(PasswordAutofillAgentTest, ClearPreviewWithInlineAutocompletedUsername) { 1357 // Simulate the browser sending back the login info. 1358 SimulateOnFillPasswordForm(fill_data_); 1359 1360 // Clear the text fields to start fresh. 1361 ClearUsernameAndPasswordFields(); 1362 1363 // Simulate the user typing in the first letter of 'alice', a stored username. 1364 SimulateUsernameChange("a", true); 1365 // Both the username and password text fields should reflect selection of the 1366 // stored login. 1367 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); 1368 // The selection should have been set to 'lice', the last 4 letters. 1369 CheckUsernameSelection(1, 5); 1370 1371 EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion( 1372 username_element_, "alicia", "secret")); 1373 EXPECT_EQ( 1374 "alicia", 1375 static_cast<std::string>(username_element_.suggestedValue().utf8())); 1376 EXPECT_TRUE(username_element_.isAutofilled()); 1377 EXPECT_EQ( 1378 "secret", 1379 static_cast<std::string>(password_element_.suggestedValue().utf8())); 1380 EXPECT_TRUE(password_element_.isAutofilled()); 1381 CheckUsernameSelection(1, 6); 1382 1383 EXPECT_TRUE( 1384 password_autofill_agent_->DidClearAutofillSelection(username_element_)); 1385 1386 EXPECT_EQ(kAliceUsername, username_element_.value().utf8()); 1387 EXPECT_TRUE(username_element_.suggestedValue().isEmpty()); 1388 EXPECT_TRUE(username_element_.isAutofilled()); 1389 EXPECT_TRUE(password_element_.value().isEmpty()); 1390 EXPECT_TRUE(password_element_.suggestedValue().isEmpty()); 1391 EXPECT_TRUE(password_element_.isAutofilled()); 1392 CheckUsernameSelection(1, 5); 1393} 1394 1395// Tests that logging is off by default. 1396TEST_F(PasswordAutofillAgentTest, OnChangeLoggingState_NoMessage) { 1397 render_thread_->sink().ClearMessages(); 1398 SendVisiblePasswordForms(); 1399 const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching( 1400 AutofillHostMsg_RecordSavePasswordProgress::ID); 1401 EXPECT_FALSE(message); 1402} 1403 1404// Test that logging can be turned on by a message. 1405TEST_F(PasswordAutofillAgentTest, OnChangeLoggingState_Activated) { 1406 // Turn the logging on. 1407 AutofillMsg_SetLoggingState msg_activate(0, true); 1408 // Up-cast to access OnMessageReceived, which is private in the agent. 1409 EXPECT_TRUE(static_cast<IPC::Listener*>(password_autofill_agent_) 1410 ->OnMessageReceived(msg_activate)); 1411 1412 render_thread_->sink().ClearMessages(); 1413 SendVisiblePasswordForms(); 1414 const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching( 1415 AutofillHostMsg_RecordSavePasswordProgress::ID); 1416 EXPECT_TRUE(message); 1417} 1418 1419// Test that logging can be turned off by a message. 1420TEST_F(PasswordAutofillAgentTest, OnChangeLoggingState_Deactivated) { 1421 // Turn the logging on and then off. 1422 AutofillMsg_SetLoggingState msg_activate(0, /*active=*/true); 1423 // Up-cast to access OnMessageReceived, which is private in the agent. 1424 EXPECT_TRUE(static_cast<IPC::Listener*>(password_autofill_agent_) 1425 ->OnMessageReceived(msg_activate)); 1426 AutofillMsg_SetLoggingState msg_deactivate(0, /*active=*/false); 1427 EXPECT_TRUE(static_cast<IPC::Listener*>(password_autofill_agent_) 1428 ->OnMessageReceived(msg_deactivate)); 1429 1430 render_thread_->sink().ClearMessages(); 1431 SendVisiblePasswordForms(); 1432 const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching( 1433 AutofillHostMsg_RecordSavePasswordProgress::ID); 1434 EXPECT_FALSE(message); 1435} 1436 1437// Test that the agent sends an IPC call to get the current activity state of 1438// password saving logging soon after construction. 1439TEST_F(PasswordAutofillAgentTest, SendsLoggingStateUpdatePingOnConstruction) { 1440 const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching( 1441 AutofillHostMsg_PasswordAutofillAgentConstructed::ID); 1442 EXPECT_TRUE(message); 1443} 1444 1445// TODO(gcasto): Re-enabled these tests after crbug.com/423464 has been fixed. 1446#if !defined(OS_ANDROID) 1447 1448// Tests that one user click on a username field is sufficient to bring up a 1449// credential suggestion popup, and the user can autocomplete the password by 1450// selecting the credential from the popup. 1451TEST_F(PasswordAutofillAgentTest, ClickAndSelect) { 1452 // SimulateElementClick() is called so that a user gesture is actually made 1453 // and the password can be filled. However, SimulateElementClick() does not 1454 // actually lead to the AutofillAgent's InputElementClicked() method being 1455 // called, so SimulateSuggestionChoice has to manually call 1456 // InputElementClicked(). 1457 ClearUsernameAndPasswordFields(); 1458 SimulateOnFillPasswordForm(fill_data_); 1459 SimulateElementClick(kUsernameName); 1460 SimulateSuggestionChoice(username_element_); 1461 ExpectAllCredentials(); 1462 1463 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); 1464} 1465 1466// Tests the autosuggestions that are given when the element is clicked. 1467// Specifically, tests when the user clicks on the username element after page 1468// load and the element is autofilled, when the user clicks on an element that 1469// has a non-matching username, and when the user clicks on an element that's 1470// already been autofilled and they've already modified. 1471TEST_F(PasswordAutofillAgentTest, CredentialsOnClick) { 1472 // Simulate the browser sending back the login info. 1473 SimulateOnFillPasswordForm(fill_data_); 1474 1475 // Clear the text fields to start fresh. 1476 ClearUsernameAndPasswordFields(); 1477 1478 // Call SimulateElementClick() to produce a user gesture on the page so 1479 // autofill will actually fill. 1480 SimulateElementClick(kUsernameName); 1481 1482 // Simulate a user clicking on the username element. This should produce a 1483 // message with all the usernames. 1484 render_thread_->sink().ClearMessages(); 1485 static_cast<PageClickListener*>(autofill_agent_) 1486 ->FormControlElementClicked(username_element_, false); 1487 ExpectAllCredentials(); 1488 1489 // Now simulate a user typing in an unrecognized username and then 1490 // clicking on the username element. This should also produce a message with 1491 // all the usernames. 1492 SimulateUsernameChange("baz", true); 1493 render_thread_->sink().ClearMessages(); 1494 static_cast<PageClickListener*>(autofill_agent_) 1495 ->FormControlElementClicked(username_element_, true); 1496 ExpectAllCredentials(); 1497 1498 // Now simulate a user typing in the first letter of the username and then 1499 // clicking on the username element. While the typing of the first letter will 1500 // inline autocomplete, clicking on the element should still produce a full 1501 // suggestion list. 1502 SimulateUsernameChange("a", true); 1503 render_thread_->sink().ClearMessages(); 1504 static_cast<PageClickListener*>(autofill_agent_) 1505 ->FormControlElementClicked(username_element_, true); 1506 ExpectAllCredentials(); 1507} 1508 1509#endif // !defined(OS_ANDROID) 1510 1511// The user types in a password, but then just before sending the form off, a 1512// script clears that password. This test checks that PasswordAutofillAgent can 1513// still remember the password typed by the user. 1514TEST_F(PasswordAutofillAgentTest, 1515 RememberLastNonEmptyPasswordOnSubmit_ScriptCleared) { 1516 SimulateInputChangeForElement( 1517 "temp", true, GetMainFrame(), username_element_, true); 1518 SimulateInputChangeForElement( 1519 "random", true, GetMainFrame(), password_element_, true); 1520 1521 // Simulate that the password value was cleared by the site's JavaScript 1522 // before submit. 1523 password_element_.setValue(WebString()); 1524 static_cast<content::RenderViewObserver*>(password_autofill_agent_) 1525 ->WillSubmitForm(GetMainFrame(), username_element_.form()); 1526 1527 // Observe that the PasswordAutofillAgent still remembered the last non-empty 1528 // password and sent that to the browser. 1529 ExpectFormSubmittedWithPasswords("random", ""); 1530} 1531 1532// Similar to RememberLastNonEmptyPasswordOnSubmit_ScriptCleared, but this time 1533// it's the user who clears the password. This test checks that in that case, 1534// the last non-empty password is not remembered. 1535TEST_F(PasswordAutofillAgentTest, 1536 RememberLastNonEmptyPasswordOnSubmit_UserCleared) { 1537 SimulateInputChangeForElement( 1538 "temp", true, GetMainFrame(), username_element_, true); 1539 SimulateInputChangeForElement( 1540 "random", true, GetMainFrame(), password_element_, true); 1541 1542 // Simulate that the user actually cleared the password again. 1543 SimulateInputChangeForElement( 1544 "", true, GetMainFrame(), password_element_, true); 1545 static_cast<content::RenderViewObserver*>(password_autofill_agent_) 1546 ->WillSubmitForm(GetMainFrame(), username_element_.form()); 1547 1548 // Observe that the PasswordAutofillAgent respects the user having cleared the 1549 // password. 1550 ExpectFormSubmittedWithPasswords("", ""); 1551} 1552 1553// Similar to RememberLastNonEmptyPasswordOnSubmit_ScriptCleared, but uses the 1554// new password instead of the current password. 1555TEST_F(PasswordAutofillAgentTest, 1556 RememberLastNonEmptyPasswordOnSubmit_NewPassword) { 1557 const char kNewPasswordFormHTML[] = 1558 "<FORM name='LoginTestForm'>" 1559 " <INPUT type='text' id='username' autocomplete='username'/>" 1560 " <INPUT type='password' id='password' autocomplete='new-password'/>" 1561 " <INPUT type='submit' value='Login'/>" 1562 "</FORM>"; 1563 LoadHTML(kNewPasswordFormHTML); 1564 UpdateUsernameAndPasswordElements(); 1565 1566 SimulateInputChangeForElement( 1567 "temp", true, GetMainFrame(), username_element_, true); 1568 SimulateInputChangeForElement( 1569 "random", true, GetMainFrame(), password_element_, true); 1570 1571 // Simulate that the password value was cleared by the site's JavaScript 1572 // before submit. 1573 password_element_.setValue(WebString()); 1574 static_cast<content::RenderViewObserver*>(password_autofill_agent_) 1575 ->WillSubmitForm(GetMainFrame(), username_element_.form()); 1576 1577 // Observe that the PasswordAutofillAgent still remembered the last non-empty 1578 // password and sent that to the browser. 1579 ExpectFormSubmittedWithPasswords("", "random"); 1580} 1581 1582// The user first accepts a suggestion, but then overwrites the password. This 1583// test checks that the overwritten password is not reverted back if the user 1584// triggers autofill through focusing (but not changing) the username again. 1585TEST_F(PasswordAutofillAgentTest, 1586 NoopEditingDoesNotOverwriteManuallyEditedPassword) { 1587 // Simulate having credentials which needed to wait until the user starts 1588 // typing the username to be filled (e.g., PSL-matched credentials). Those are 1589 // the ones which can be filled as a result of TextFieldDidEndEditing. 1590 fill_data_.wait_for_username = true; 1591 SimulateOnFillPasswordForm(fill_data_); 1592 // Simulate that the user typed her name to make the autofill work. 1593 SimulateInputChangeForElement(kAliceUsername, 1594 /*move_caret_to_end=*/true, 1595 GetMainFrame(), 1596 username_element_, 1597 /*is_user_input=*/true); 1598 SimulateDidEndEditing(GetMainFrame(), username_element_); 1599 const std::string old_username(username_element_.value().utf8()); 1600 const std::string old_password(password_element_.value().utf8()); 1601 const std::string new_password(old_password + "modify"); 1602 1603 // The user changes the password. 1604 SimulateInputChangeForElement(new_password, 1605 /*move_caret_to_end=*/true, 1606 GetMainFrame(), 1607 password_element_, 1608 /*is_user_input=*/true); 1609 1610 // The user switches back into the username field, but leaves that without 1611 // changes. 1612 SimulateDidEndEditing(GetMainFrame(), username_element_); 1613 1614 // The password should have stayed as the user changed it. 1615 CheckTextFieldsDOMState(old_username, true, new_password, false); 1616 // The password should not have a suggested value. 1617 CheckTextFieldsState(old_username, true, std::string(), false); 1618} 1619 1620TEST_F(PasswordAutofillAgentTest, 1621 InlineAutocompleteOverwritesManuallyEditedPassword) { 1622 // Simulate the browser sending back the login info. 1623 SimulateOnFillPasswordForm(fill_data_); 1624 1625 ClearUsernameAndPasswordFields(); 1626 1627 // The user enters a password 1628 SimulateInputChangeForElement("someOtherPassword", 1629 /*move_caret_to_end=*/true, 1630 GetMainFrame(), 1631 password_element_, 1632 /*is_user_input=*/true); 1633 1634 // Simulate the user typing a stored username. 1635 SimulateUsernameChange(kAliceUsername, true); 1636 // The autofileld password should replace the typed one. 1637 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); 1638} 1639 1640} // namespace autofill 1641