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 28 using autofill::PasswordForm; 29 using base::ASCIIToUTF16; 30 using base::UTF16ToUTF8; 31 using blink::WebDocument; 32 using blink::WebElement; 33 using blink::WebFrame; 34 using blink::WebInputElement; 35 using blink::WebString; 36 using blink::WebView; 37 38 namespace { 39 40 // The name of the username/password element in the form. 41 const char kUsernameName[] = "username"; 42 const char kPasswordName[] = "password"; 43 44 const char kAliceUsername[] = "alice"; 45 const char kAlicePassword[] = "password"; 46 const char kBobUsername[] = "bob"; 47 const char kBobPassword[] = "secret"; 48 const char kCarolUsername[] = "Carol"; 49 const char kCarolPassword[] = "test"; 50 const char kCarolAlternateUsername[] = "RealCarolUsername"; 51 52 const 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 59 const 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 69 const char kEmptyFormHTML[] = 70 "<head> <style> form {display: inline;} </style> </head>" 71 "<body> <form> </form> </body>"; 72 73 const 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 83 const char kEmptyWebpage[] = 84 "<html>" 85 " <head>" 86 " </head>" 87 " <body>" 88 " </body>" 89 "</html>"; 90 91 const 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 105 const 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 120 const 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 137 const 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 147 const 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|. 160 void SetElementReadOnly(WebInputElement& element, bool read_only) { 161 element.setAttribute(WebString::fromUTF8("readonly"), 162 read_only ? WebString::fromUTF8("true") : WebString()); 163 } 164 165 } // namespace 166 167 namespace autofill { 168 169 class 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 password_autofill_->OnMessageReceived(msg); 181 } 182 183 void SendVisiblePasswordForms() { 184 password_autofill_->SendPasswordForms(GetMainFrame(), 185 true /* only_visible */); 186 } 187 188 virtual void SetUp() { 189 ChromeRenderViewTest::SetUp(); 190 191 // Add a preferred login and an additional login to the FillData. 192 username1_ = ASCIIToUTF16(kAliceUsername); 193 password1_ = ASCIIToUTF16(kAlicePassword); 194 username2_ = ASCIIToUTF16(kBobUsername); 195 password2_ = ASCIIToUTF16(kBobPassword); 196 username3_ = ASCIIToUTF16(kCarolUsername); 197 password3_ = ASCIIToUTF16(kCarolPassword); 198 alternate_username3_ = ASCIIToUTF16(kCarolAlternateUsername); 199 200 FormFieldData username_field; 201 username_field.name = ASCIIToUTF16(kUsernameName); 202 username_field.value = username1_; 203 fill_data_.basic_data.fields.push_back(username_field); 204 205 FormFieldData password_field; 206 password_field.name = ASCIIToUTF16(kPasswordName); 207 password_field.value = password1_; 208 password_field.form_control_type = "password"; 209 fill_data_.basic_data.fields.push_back(password_field); 210 211 PasswordAndRealm password2; 212 password2.password = password2_; 213 fill_data_.additional_logins[username2_] = password2; 214 PasswordAndRealm password3; 215 password3.password = password3_; 216 fill_data_.additional_logins[username3_] = password3; 217 218 UsernamesCollectionKey key; 219 key.username = username3_; 220 key.password = password3_; 221 key.realm = "google.com"; 222 fill_data_.other_possible_usernames[key].push_back(alternate_username3_); 223 224 // We need to set the origin so it matches the frame URL and the action so 225 // it matches the form action, otherwise we won't autocomplete. 226 UpdateOriginForHTML(kFormHTML); 227 fill_data_.basic_data.action = GURL("http://www.bidule.com"); 228 229 LoadHTML(kFormHTML); 230 231 // Now retrieve the input elements so the test can access them. 232 UpdateUsernameAndPasswordElements(); 233 } 234 235 virtual void TearDown() { 236 username_element_.reset(); 237 password_element_.reset(); 238 ChromeRenderViewTest::TearDown(); 239 } 240 241 void UpdateOriginForHTML(const std::string& html) { 242 std::string origin = "data:text/html;charset=utf-8," + html; 243 fill_data_.basic_data.origin = GURL(origin); 244 } 245 246 void UpdateUsernameAndPasswordElements() { 247 WebDocument document = GetMainFrame()->document(); 248 WebElement element = 249 document.getElementById(WebString::fromUTF8(kUsernameName)); 250 ASSERT_FALSE(element.isNull()); 251 username_element_ = element.to<blink::WebInputElement>(); 252 element = document.getElementById(WebString::fromUTF8(kPasswordName)); 253 ASSERT_FALSE(element.isNull()); 254 password_element_ = element.to<blink::WebInputElement>(); 255 } 256 257 void ClearUsernameAndPasswordFields() { 258 username_element_.setValue(""); 259 username_element_.setAutofilled(false); 260 password_element_.setValue(""); 261 password_element_.setAutofilled(false); 262 } 263 264 void SimulateUsernameChangeForElement(const std::string& username, 265 bool move_caret_to_end, 266 WebFrame* input_frame, 267 WebInputElement& username_input) { 268 username_input.setValue(WebString::fromUTF8(username)); 269 // The field must have focus or AutofillAgent will think the 270 // change should be ignored. 271 while (!username_input.focused()) 272 input_frame->document().frame()->view()->advanceFocus(false); 273 if (move_caret_to_end) 274 username_input.setSelectionRange(username.length(), username.length()); 275 autofill_agent_->textFieldDidChange(username_input); 276 // Processing is delayed because of a Blink bug: 277 // https://bugs.webkit.org/show_bug.cgi?id=16976 278 // See PasswordAutofillAgent::TextDidChangeInTextField() for details. 279 280 // Autocomplete will trigger a style recalculation when we put up the next 281 // frame, but we don't want to wait that long. Instead, trigger a style 282 // recalcuation manually after TextFieldDidChangeImpl runs. 283 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( 284 &PasswordAutofillAgentTest::LayoutMainFrame, base::Unretained(this))); 285 286 base::MessageLoop::current()->RunUntilIdle(); 287 } 288 289 void LayoutMainFrame() { 290 GetMainFrame()->view()->layout(); 291 } 292 293 void SimulateUsernameChange(const std::string& username, 294 bool move_caret_to_end) { 295 SimulateUsernameChangeForElement(username, move_caret_to_end, 296 GetMainFrame(), username_element_); 297 } 298 299 // Tests that no suggestion popup is generated when the username_element_ is 300 // edited. 301 void ExpectNoSuggestionsPopup() { 302 // The first test below ensures that the suggestions have been handled by 303 // the password_autofill_agent, even though autocomplete='off' is set. The 304 // second check ensures that, although handled, no "show suggestions" IPC to 305 // the browser was generated. 306 // 307 // This is interesting in the specific case of an autocomplete='off' form 308 // that also has a remembered username and password 309 // (http://crbug.com/326679). To fix the DCHECK that this case used to hit, 310 // |true| is returned from ShowSuggestions for all forms with valid 311 // usersnames that are autocomplete='off', prentending that a selection box 312 // has been shown to the user. Of course, it hasn't, so a message is never 313 // sent to the browser on acceptance, and the DCHECK isn't hit (and nothing 314 // is filled). 315 // 316 // These tests only make sense in the context of not ignoring 317 // autocomplete='off', so only test them if the disable autocomplete='off' 318 // flag is not enabled. 319 // TODO(jww): Remove this function and callers once autocomplete='off' is 320 // permanently ignored. 321 if (!ShouldIgnoreAutocompleteOffForPasswordFields()) { 322 EXPECT_TRUE(autofill_agent_->password_autofill_agent_->ShowSuggestions( 323 username_element_)); 324 325 EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching( 326 AutofillHostMsg_ShowPasswordSuggestions::ID)); 327 } 328 } 329 330 void SimulateKeyDownEvent(const WebInputElement& element, 331 ui::KeyboardCode key_code) { 332 blink::WebKeyboardEvent key_event; 333 key_event.windowsKeyCode = key_code; 334 autofill_agent_->textFieldDidReceiveKeyDown(element, key_event); 335 } 336 337 void CheckTextFieldsStateForElements(const WebInputElement& username_element, 338 const std::string& username, 339 bool username_autofilled, 340 const WebInputElement& password_element, 341 const std::string& password, 342 bool password_autofilled, 343 bool checkSuggestedValue = true) { 344 EXPECT_EQ(username, 345 static_cast<std::string>(username_element.value().utf8())); 346 EXPECT_EQ(username_autofilled, username_element.isAutofilled()); 347 EXPECT_EQ(password, 348 static_cast<std::string>( 349 checkSuggestedValue ? password_element.suggestedValue().utf8() 350 : password_element.value().utf8())); 351 EXPECT_EQ(password_autofilled, password_element.isAutofilled()); 352 } 353 354 // Checks the DOM-accessible value of the username element and the 355 // *suggested* value of the password element. 356 void CheckTextFieldsState(const std::string& username, 357 bool username_autofilled, 358 const std::string& password, 359 bool password_autofilled) { 360 CheckTextFieldsStateForElements(username_element_, username, 361 username_autofilled, password_element_, 362 password, password_autofilled); 363 } 364 365 // Checks the DOM-accessible value of the username element and the 366 // DOM-accessible value of the password element. 367 void CheckTextFieldsDOMState(const std::string& username, 368 bool username_autofilled, 369 const std::string& password, 370 bool password_autofilled) { 371 CheckTextFieldsStateForElements(username_element_, 372 username, 373 username_autofilled, 374 password_element_, 375 password, 376 password_autofilled, 377 false); 378 } 379 380 void CheckUsernameSelection(int start, int end) { 381 EXPECT_EQ(start, username_element_.selectionStart()); 382 EXPECT_EQ(end, username_element_.selectionEnd()); 383 } 384 385 base::string16 username1_; 386 base::string16 username2_; 387 base::string16 username3_; 388 base::string16 password1_; 389 base::string16 password2_; 390 base::string16 password3_; 391 base::string16 alternate_username3_; 392 PasswordFormFillData fill_data_; 393 394 WebInputElement username_element_; 395 WebInputElement password_element_; 396 397 private: 398 DISALLOW_COPY_AND_ASSIGN(PasswordAutofillAgentTest); 399 }; 400 401 // Tests that the password login is autocompleted as expected when the browser 402 // sends back the password info. 403 TEST_F(PasswordAutofillAgentTest, InitialAutocomplete) { 404 /* 405 * Right now we are not sending the message to the browser because we are 406 * loading a data URL and the security origin canAccessPasswordManager() 407 * returns false. May be we should mock URL loading to cirmcuvent this? 408 TODO(jcivelli): find a way to make the security origin not deny access to the 409 password manager and then reenable this code. 410 411 // The form has been loaded, we should have sent the browser a message about 412 // the form. 413 const IPC::Message* msg = render_thread_.sink().GetFirstMessageMatching( 414 AutofillHostMsg_PasswordFormsParsed::ID); 415 ASSERT_TRUE(msg != NULL); 416 417 Tuple1<std::vector<PasswordForm> > forms; 418 AutofillHostMsg_PasswordFormsParsed::Read(msg, &forms); 419 ASSERT_EQ(1U, forms.a.size()); 420 PasswordForm password_form = forms.a[0]; 421 EXPECT_EQ(PasswordForm::SCHEME_HTML, password_form.scheme); 422 EXPECT_EQ(ASCIIToUTF16(kUsernameName), password_form.username_element); 423 EXPECT_EQ(ASCIIToUTF16(kPasswordName), password_form.password_element); 424 */ 425 426 // Simulate the browser sending back the login info, it triggers the 427 // autocomplete. 428 SimulateOnFillPasswordForm(fill_data_); 429 430 // The username and password should have been autocompleted. 431 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); 432 } 433 434 // Tests that we correctly fill forms having an empty 'action' attribute. 435 TEST_F(PasswordAutofillAgentTest, InitialAutocompleteForEmptyAction) { 436 const char kEmptyActionFormHTML[] = 437 "<FORM name='LoginTestForm'>" 438 " <INPUT type='text' id='username'/>" 439 " <INPUT type='password' id='password'/>" 440 " <INPUT type='submit' value='Login'/>" 441 "</FORM>"; 442 LoadHTML(kEmptyActionFormHTML); 443 444 // Retrieve the input elements so the test can access them. 445 WebDocument document = GetMainFrame()->document(); 446 WebElement element = 447 document.getElementById(WebString::fromUTF8(kUsernameName)); 448 ASSERT_FALSE(element.isNull()); 449 username_element_ = element.to<blink::WebInputElement>(); 450 element = document.getElementById(WebString::fromUTF8(kPasswordName)); 451 ASSERT_FALSE(element.isNull()); 452 password_element_ = element.to<blink::WebInputElement>(); 453 454 // Set the expected form origin and action URLs. 455 UpdateOriginForHTML(kEmptyActionFormHTML); 456 fill_data_.basic_data.action = fill_data_.basic_data.origin; 457 458 // Simulate the browser sending back the login info, it triggers the 459 // autocomplete. 460 SimulateOnFillPasswordForm(fill_data_); 461 462 // The username and password should have been autocompleted. 463 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); 464 } 465 466 // Tests that if a password is marked as readonly, neither field is autofilled 467 // on page load. 468 TEST_F(PasswordAutofillAgentTest, NoInitialAutocompleteForReadOnlyPassword) { 469 SetElementReadOnly(password_element_, true); 470 471 // Simulate the browser sending back the login info, it triggers the 472 // autocomplete. 473 SimulateOnFillPasswordForm(fill_data_); 474 475 CheckTextFieldsState(std::string(), false, std::string(), false); 476 } 477 478 // Can still fill a password field if the username is set to a value that 479 // matches. 480 TEST_F(PasswordAutofillAgentTest, 481 AutocompletePasswordForReadonlyUsernameMatched) { 482 username_element_.setValue(username3_); 483 SetElementReadOnly(username_element_, true); 484 485 // Filled even though username is not the preferred match. 486 SimulateOnFillPasswordForm(fill_data_); 487 CheckTextFieldsState(UTF16ToUTF8(username3_), false, 488 UTF16ToUTF8(password3_), true); 489 } 490 491 // If a username field is empty and readonly, don't autofill. 492 TEST_F(PasswordAutofillAgentTest, 493 NoAutocompletePasswordForReadonlyUsernameUnmatched) { 494 username_element_.setValue(WebString::fromUTF8("")); 495 SetElementReadOnly(username_element_, true); 496 497 SimulateOnFillPasswordForm(fill_data_); 498 CheckTextFieldsState(std::string(), false, std::string(), false); 499 } 500 501 // Tests that having a non-matching username precludes the autocomplete. 502 TEST_F(PasswordAutofillAgentTest, NoAutocompleteForFilledFieldUnmatched) { 503 username_element_.setValue(WebString::fromUTF8("bogus")); 504 505 // Simulate the browser sending back the login info, it triggers the 506 // autocomplete. 507 SimulateOnFillPasswordForm(fill_data_); 508 509 // Neither field should be autocompleted. 510 CheckTextFieldsState("bogus", false, std::string(), false); 511 } 512 513 // Don't try to complete a prefilled value even if it's a partial match 514 // to a username. 515 TEST_F(PasswordAutofillAgentTest, NoPartialMatchForPrefilledUsername) { 516 username_element_.setValue(WebString::fromUTF8("ali")); 517 518 SimulateOnFillPasswordForm(fill_data_); 519 520 CheckTextFieldsState("ali", false, std::string(), false); 521 } 522 523 TEST_F(PasswordAutofillAgentTest, InputWithNoForms) { 524 const char kNoFormInputs[] = 525 "<input type='text' id='username'/>" 526 "<input type='password' id='password'/>"; 527 LoadHTML(kNoFormInputs); 528 529 SimulateOnFillPasswordForm(fill_data_); 530 531 // Input elements that aren't in a <form> won't autofill. 532 CheckTextFieldsState(std::string(), false, std::string(), false); 533 } 534 535 TEST_F(PasswordAutofillAgentTest, NoAutocompleteForTextFieldPasswords) { 536 const char kTextFieldPasswordFormHTML[] = 537 "<FORM name='LoginTestForm' action='http://www.bidule.com'>" 538 " <INPUT type='text' id='username'/>" 539 " <INPUT type='text' id='password'/>" 540 " <INPUT type='submit' value='Login'/>" 541 "</FORM>"; 542 LoadHTML(kTextFieldPasswordFormHTML); 543 544 // Retrieve the input elements so the test can access them. 545 WebDocument document = GetMainFrame()->document(); 546 WebElement element = 547 document.getElementById(WebString::fromUTF8(kUsernameName)); 548 ASSERT_FALSE(element.isNull()); 549 username_element_ = element.to<blink::WebInputElement>(); 550 element = document.getElementById(WebString::fromUTF8(kPasswordName)); 551 ASSERT_FALSE(element.isNull()); 552 password_element_ = element.to<blink::WebInputElement>(); 553 554 // Set the expected form origin URL. 555 UpdateOriginForHTML(kTextFieldPasswordFormHTML); 556 557 SimulateOnFillPasswordForm(fill_data_); 558 559 // Fields should still be empty. 560 CheckTextFieldsState(std::string(), false, std::string(), false); 561 } 562 563 TEST_F(PasswordAutofillAgentTest, NoAutocompleteForPasswordFieldUsernames) { 564 const char kPasswordFieldUsernameFormHTML[] = 565 "<FORM name='LoginTestForm' action='http://www.bidule.com'>" 566 " <INPUT type='password' id='username'/>" 567 " <INPUT type='password' id='password'/>" 568 " <INPUT type='submit' value='Login'/>" 569 "</FORM>"; 570 LoadHTML(kPasswordFieldUsernameFormHTML); 571 572 // Retrieve the input elements so the test can access them. 573 WebDocument document = GetMainFrame()->document(); 574 WebElement element = 575 document.getElementById(WebString::fromUTF8(kUsernameName)); 576 ASSERT_FALSE(element.isNull()); 577 username_element_ = element.to<blink::WebInputElement>(); 578 element = document.getElementById(WebString::fromUTF8(kPasswordName)); 579 ASSERT_FALSE(element.isNull()); 580 password_element_ = element.to<blink::WebInputElement>(); 581 582 // Set the expected form origin URL. 583 UpdateOriginForHTML(kPasswordFieldUsernameFormHTML); 584 585 SimulateOnFillPasswordForm(fill_data_); 586 587 // Fields should still be empty. 588 CheckTextFieldsState(std::string(), false, std::string(), false); 589 } 590 591 // Tests that having a matching username does not preclude the autocomplete. 592 TEST_F(PasswordAutofillAgentTest, InitialAutocompleteForMatchingFilledField) { 593 username_element_.setValue(WebString::fromUTF8(kAliceUsername)); 594 595 // Simulate the browser sending back the login info, it triggers the 596 // autocomplete. 597 SimulateOnFillPasswordForm(fill_data_); 598 599 // The username and password should have been autocompleted. 600 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); 601 } 602 603 // Tests that editing the password clears the autocompleted password field. 604 TEST_F(PasswordAutofillAgentTest, PasswordClearOnEdit) { 605 // Simulate the browser sending back the login info, it triggers the 606 // autocomplete. 607 SimulateOnFillPasswordForm(fill_data_); 608 609 // Simulate the user changing the username to some unknown username. 610 SimulateUsernameChange("alicia", true); 611 612 // The password should have been cleared. 613 CheckTextFieldsState("alicia", false, std::string(), false); 614 } 615 616 // Tests that we only autocomplete on focus lost and with a full username match 617 // when |wait_for_username| is true. 618 TEST_F(PasswordAutofillAgentTest, WaitUsername) { 619 // Simulate the browser sending back the login info. 620 fill_data_.wait_for_username = true; 621 SimulateOnFillPasswordForm(fill_data_); 622 623 // No auto-fill should have taken place. 624 CheckTextFieldsState(std::string(), false, std::string(), false); 625 626 // No autocomplete should happen when text is entered in the username. 627 SimulateUsernameChange("a", true); 628 CheckTextFieldsState("a", false, std::string(), false); 629 SimulateUsernameChange("al", true); 630 CheckTextFieldsState("al", false, std::string(), false); 631 SimulateUsernameChange(kAliceUsername, true); 632 CheckTextFieldsState(kAliceUsername, false, std::string(), false); 633 634 // Autocomplete should happen only when the username textfield is blurred with 635 // a full match. 636 username_element_.setValue("a"); 637 autofill_agent_->textFieldDidEndEditing(username_element_); 638 CheckTextFieldsState("a", false, std::string(), false); 639 username_element_.setValue("al"); 640 autofill_agent_->textFieldDidEndEditing(username_element_); 641 CheckTextFieldsState("al", false, std::string(), false); 642 username_element_.setValue("alices"); 643 autofill_agent_->textFieldDidEndEditing(username_element_); 644 CheckTextFieldsState("alices", false, std::string(), false); 645 username_element_.setValue(ASCIIToUTF16(kAliceUsername)); 646 autofill_agent_->textFieldDidEndEditing(username_element_); 647 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); 648 } 649 650 // Tests that inline autocompletion works properly. 651 TEST_F(PasswordAutofillAgentTest, InlineAutocomplete) { 652 // Simulate the browser sending back the login info. 653 SimulateOnFillPasswordForm(fill_data_); 654 655 // Clear the text fields to start fresh. 656 ClearUsernameAndPasswordFields(); 657 658 // Simulate the user typing in the first letter of 'alice', a stored username. 659 SimulateUsernameChange("a", true); 660 // Both the username and password text fields should reflect selection of the 661 // stored login. 662 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); 663 // And the selection should have been set to 'lice', the last 4 letters. 664 CheckUsernameSelection(1, 5); 665 666 // Now the user types the next letter of the same username, 'l'. 667 SimulateUsernameChange("al", true); 668 // Now the fields should have the same value, but the selection should have a 669 // different start value. 670 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); 671 CheckUsernameSelection(2, 5); 672 673 // Test that deleting does not trigger autocomplete. 674 SimulateKeyDownEvent(username_element_, ui::VKEY_BACK); 675 SimulateUsernameChange("alic", true); 676 CheckTextFieldsState("alic", false, std::string(), false); 677 CheckUsernameSelection(4, 4); // No selection. 678 // Reset the last pressed key to something other than backspace. 679 SimulateKeyDownEvent(username_element_, ui::VKEY_A); 680 681 // Now lets say the user goes astray from the stored username and types the 682 // letter 'f', spelling 'alf'. We don't know alf (that's just sad), so in 683 // practice the username should no longer be 'alice' and the selected range 684 // should be empty. 685 SimulateUsernameChange("alf", true); 686 CheckTextFieldsState("alf", false, std::string(), false); 687 CheckUsernameSelection(3, 3); // No selection. 688 689 // Ok, so now the user removes all the text and enters the letter 'b'. 690 SimulateUsernameChange("b", true); 691 // The username and password fields should match the 'bob' entry. 692 CheckTextFieldsState(kBobUsername, true, kBobPassword, true); 693 CheckUsernameSelection(1, 3); 694 695 // Then, the user again removes all the text and types an uppercase 'C'. 696 SimulateUsernameChange("C", true); 697 // The username and password fields should match the 'Carol' entry. 698 CheckTextFieldsState(kCarolUsername, true, kCarolPassword, true); 699 CheckUsernameSelection(1, 5); 700 // The user removes all the text and types a lowercase 'c'. We only 701 // want case-sensitive autocompletion, so the username and the selected range 702 // should be empty. 703 SimulateUsernameChange("c", true); 704 CheckTextFieldsState("c", false, std::string(), false); 705 CheckUsernameSelection(1, 1); 706 707 // Check that we complete other_possible_usernames as well. 708 SimulateUsernameChange("R", true); 709 CheckTextFieldsState(kCarolAlternateUsername, true, kCarolPassword, true); 710 CheckUsernameSelection(1, 17); 711 } 712 713 TEST_F(PasswordAutofillAgentTest, IsWebNodeVisibleTest) { 714 blink::WebVector<blink::WebFormElement> forms1, forms2, forms3; 715 blink::WebFrame* frame; 716 717 LoadHTML(kVisibleFormHTML); 718 frame = GetMainFrame(); 719 frame->document().forms(forms1); 720 ASSERT_EQ(1u, forms1.size()); 721 EXPECT_TRUE(IsWebNodeVisible(forms1[0])); 722 723 LoadHTML(kEmptyFormHTML); 724 frame = GetMainFrame(); 725 frame->document().forms(forms2); 726 ASSERT_EQ(1u, forms2.size()); 727 EXPECT_FALSE(IsWebNodeVisible(forms2[0])); 728 729 LoadHTML(kNonVisibleFormHTML); 730 frame = GetMainFrame(); 731 frame->document().forms(forms3); 732 ASSERT_EQ(1u, forms3.size()); 733 EXPECT_FALSE(IsWebNodeVisible(forms3[0])); 734 } 735 736 TEST_F(PasswordAutofillAgentTest, SendPasswordFormsTest) { 737 render_thread_->sink().ClearMessages(); 738 LoadHTML(kVisibleFormHTML); 739 const IPC::Message* message = render_thread_->sink() 740 .GetFirstMessageMatching(AutofillHostMsg_PasswordFormsRendered::ID); 741 EXPECT_TRUE(message); 742 Tuple1<std::vector<autofill::PasswordForm> > param; 743 AutofillHostMsg_PasswordFormsRendered::Read(message, ¶m); 744 EXPECT_TRUE(param.a.size()); 745 746 render_thread_->sink().ClearMessages(); 747 LoadHTML(kEmptyFormHTML); 748 message = render_thread_->sink().GetFirstMessageMatching( 749 AutofillHostMsg_PasswordFormsRendered::ID); 750 EXPECT_TRUE(message); 751 AutofillHostMsg_PasswordFormsRendered::Read(message, ¶m); 752 EXPECT_FALSE(param.a.size()); 753 754 render_thread_->sink().ClearMessages(); 755 LoadHTML(kNonVisibleFormHTML); 756 message = render_thread_->sink().GetFirstMessageMatching( 757 AutofillHostMsg_PasswordFormsRendered::ID); 758 EXPECT_TRUE(message); 759 AutofillHostMsg_PasswordFormsRendered::Read(message, ¶m); 760 EXPECT_FALSE(param.a.size()); 761 } 762 763 TEST_F(PasswordAutofillAgentTest, SendPasswordFormsTest_Redirection) { 764 render_thread_->sink().ClearMessages(); 765 LoadHTML(kEmptyWebpage); 766 EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching( 767 AutofillHostMsg_PasswordFormsRendered::ID)); 768 769 render_thread_->sink().ClearMessages(); 770 LoadHTML(kRedirectionWebpage); 771 EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching( 772 AutofillHostMsg_PasswordFormsRendered::ID)); 773 774 render_thread_->sink().ClearMessages(); 775 LoadHTML(kSimpleWebpage); 776 EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching( 777 AutofillHostMsg_PasswordFormsRendered::ID)); 778 779 render_thread_->sink().ClearMessages(); 780 LoadHTML(kWebpageWithDynamicContent); 781 EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching( 782 AutofillHostMsg_PasswordFormsRendered::ID)); 783 } 784 785 // Tests that a password form in an iframe will not be filled in until a user 786 // interaction with the form. 787 TEST_F(PasswordAutofillAgentTest, IframeNoFillTest) { 788 const char kIframeName[] = "iframe"; 789 const char kWebpageWithIframeStart[] = 790 "<html>" 791 " <head>" 792 " <meta charset='utf-8' />" 793 " <title>Title</title>" 794 " </head>" 795 " <body>" 796 " <iframe name='iframe' src=\""; 797 const char kWebpageWithIframeEnd[] = 798 "\"></iframe>" 799 " </body>" 800 "</html>"; 801 802 std::string origin("data:text/html;charset=utf-8,"); 803 origin += kSimpleWebpage; 804 805 std::string page_html(kWebpageWithIframeStart); 806 page_html += origin; 807 page_html += kWebpageWithIframeEnd; 808 809 LoadHTML(page_html.c_str()); 810 811 // Set the expected form origin and action URLs. 812 fill_data_.basic_data.origin = GURL(origin); 813 fill_data_.basic_data.action = GURL(origin); 814 815 SimulateOnFillPasswordForm(fill_data_); 816 817 // Retrieve the input elements from the iframe since that is where we want to 818 // test the autofill. 819 WebFrame* iframe = GetMainFrame()->findChildByName(kIframeName); 820 ASSERT_TRUE(iframe); 821 WebDocument document = iframe->document(); 822 823 WebElement username_element = document.getElementById(kUsernameName); 824 WebElement password_element = document.getElementById(kPasswordName); 825 ASSERT_FALSE(username_element.isNull()); 826 ASSERT_FALSE(password_element.isNull()); 827 828 WebInputElement username_input = username_element.to<WebInputElement>(); 829 WebInputElement password_input = password_element.to<WebInputElement>(); 830 ASSERT_FALSE(username_element.isNull()); 831 832 CheckTextFieldsStateForElements(username_input, "", false, 833 password_input, "", false); 834 835 // Simulate the user typing in the username in the iframe, which should cause 836 // an autofill. 837 SimulateUsernameChangeForElement(kAliceUsername, true, 838 iframe, username_input); 839 840 CheckTextFieldsStateForElements(username_input, kAliceUsername, true, 841 password_input, kAlicePassword, true); 842 } 843 844 // Tests that a password will only be filled as a suggested and will not be 845 // accessible by the DOM until a user gesture has occurred. 846 TEST_F(PasswordAutofillAgentTest, GestureRequiredTest) { 847 // Trigger the initial autocomplete. 848 SimulateOnFillPasswordForm(fill_data_); 849 850 // The username and password should have been autocompleted. 851 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); 852 853 // However, it should only have completed with the suggested value, as tested 854 // above, and it should not have completed into the DOM accessible value for 855 // the password field. 856 CheckTextFieldsDOMState(kAliceUsername, true, std::string(), true); 857 858 // Simulate a user click so that the password field's real value is filled. 859 SimulateElementClick(kUsernameName); 860 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); 861 } 862 863 // Verfies that a DOM-activated UI event will not cause an autofill. 864 TEST_F(PasswordAutofillAgentTest, NoDOMActivationTest) { 865 // Trigger the initial autocomplete. 866 SimulateOnFillPasswordForm(fill_data_); 867 868 ExecuteJavaScript(kJavaScriptClick); 869 CheckTextFieldsDOMState(kAliceUsername, true, "", true); 870 } 871 872 // Regression test for http://crbug.com/326679 873 TEST_F(PasswordAutofillAgentTest, SelectUsernameWithUsernameAutofillOff) { 874 // Simulate the browser sending back the login info. 875 SimulateOnFillPasswordForm(fill_data_); 876 877 // Set the username element to autocomplete='off' 878 username_element_.setAttribute(WebString::fromUTF8("autocomplete"), 879 WebString::fromUTF8("off")); 880 881 // Simulate the user changing the username to some known username. 882 SimulateUsernameChange(kAliceUsername, true); 883 884 ExpectNoSuggestionsPopup(); 885 } 886 887 // Regression test for http://crbug.com/326679 888 TEST_F(PasswordAutofillAgentTest, 889 SelectUnknownUsernameWithUsernameAutofillOff) { 890 // Simulate the browser sending back the login info. 891 SimulateOnFillPasswordForm(fill_data_); 892 893 // Set the username element to autocomplete='off' 894 username_element_.setAttribute(WebString::fromUTF8("autocomplete"), 895 WebString::fromUTF8("off")); 896 897 // Simulate the user changing the username to some unknown username. 898 SimulateUsernameChange("foo", true); 899 900 ExpectNoSuggestionsPopup(); 901 } 902 903 // Regression test for http://crbug.com/326679 904 TEST_F(PasswordAutofillAgentTest, SelectUsernameWithPasswordAutofillOff) { 905 // Simulate the browser sending back the login info. 906 SimulateOnFillPasswordForm(fill_data_); 907 908 // Set the main password element to autocomplete='off' 909 password_element_.setAttribute(WebString::fromUTF8("autocomplete"), 910 WebString::fromUTF8("off")); 911 912 // Simulate the user changing the username to some known username. 913 SimulateUsernameChange(kAliceUsername, true); 914 915 ExpectNoSuggestionsPopup(); 916 } 917 918 // Regression test for http://crbug.com/326679 919 TEST_F(PasswordAutofillAgentTest, 920 SelectUnknownUsernameWithPasswordAutofillOff) { 921 // Simulate the browser sending back the login info. 922 SimulateOnFillPasswordForm(fill_data_); 923 924 // Set the main password element to autocomplete='off' 925 password_element_.setAttribute(WebString::fromUTF8("autocomplete"), 926 WebString::fromUTF8("off")); 927 928 // Simulate the user changing the username to some unknown username. 929 SimulateUsernameChange("foo", true); 930 931 ExpectNoSuggestionsPopup(); 932 } 933 934 // Verifies that password autofill triggers onChange events in JavaScript for 935 // forms that are filled on page load. 936 TEST_F(PasswordAutofillAgentTest, 937 PasswordAutofillTriggersOnChangeEventsOnLoad) { 938 std::string html = std::string(kFormHTML) + kOnChangeDetectionScript; 939 LoadHTML(html.c_str()); 940 UpdateOriginForHTML(html); 941 UpdateUsernameAndPasswordElements(); 942 943 // Simulate the browser sending back the login info, it triggers the 944 // autocomplete. 945 SimulateOnFillPasswordForm(fill_data_); 946 947 // The username and password should have been autocompleted... 948 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); 949 // ... but since there hasn't been a user gesture yet, the autocompleted 950 // password should only be visible to the user. 951 CheckTextFieldsDOMState(kAliceUsername, true, std::string(), true); 952 953 // A JavaScript onChange event should have been triggered for the username, 954 // but not yet for the password. 955 int username_onchange_called = -1; 956 int password_onchange_called = -1; 957 ASSERT_TRUE( 958 ExecuteJavaScriptAndReturnIntValue( 959 ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"), 960 &username_onchange_called)); 961 EXPECT_EQ(1, username_onchange_called); 962 ASSERT_TRUE( 963 ExecuteJavaScriptAndReturnIntValue( 964 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"), 965 &password_onchange_called)); 966 // TODO(isherman): Re-enable this check once http://crbug.com/333144 is fixed. 967 // EXPECT_EQ(0, password_onchange_called); 968 969 // Simulate a user click so that the password field's real value is filled. 970 SimulateElementClick(kUsernameName); 971 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); 972 973 // Now, a JavaScript onChange event should have been triggered for the 974 // password as well. 975 ASSERT_TRUE( 976 ExecuteJavaScriptAndReturnIntValue( 977 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"), 978 &password_onchange_called)); 979 EXPECT_EQ(1, password_onchange_called); 980 } 981 982 // Verifies that password autofill triggers onChange events in JavaScript for 983 // forms that are filled after page load. 984 TEST_F(PasswordAutofillAgentTest, 985 PasswordAutofillTriggersOnChangeEventsWaitForUsername) { 986 std::string html = std::string(kFormHTML) + kOnChangeDetectionScript; 987 LoadHTML(html.c_str()); 988 UpdateOriginForHTML(html); 989 UpdateUsernameAndPasswordElements(); 990 991 // Simulate the browser sending back the login info, it triggers the 992 // autocomplete. 993 fill_data_.wait_for_username = true; 994 SimulateOnFillPasswordForm(fill_data_); 995 996 // The username and password should not yet have been autocompleted. 997 CheckTextFieldsState(std::string(), false, std::string(), false); 998 999 // Simulate a click just to force a user gesture, since the username value is 1000 // set directly. 1001 SimulateElementClick(kUsernameName); 1002 1003 // Simulate the user entering her username. 1004 username_element_.setValue(ASCIIToUTF16(kAliceUsername), true); 1005 autofill_agent_->textFieldDidEndEditing(username_element_); 1006 1007 // The username and password should now have been autocompleted. 1008 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); 1009 1010 // JavaScript onChange events should have been triggered both for the username 1011 // and for the password. 1012 int username_onchange_called = -1; 1013 int password_onchange_called = -1; 1014 ASSERT_TRUE( 1015 ExecuteJavaScriptAndReturnIntValue( 1016 ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"), 1017 &username_onchange_called)); 1018 EXPECT_EQ(1, username_onchange_called); 1019 ASSERT_TRUE( 1020 ExecuteJavaScriptAndReturnIntValue( 1021 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"), 1022 &password_onchange_called)); 1023 EXPECT_EQ(1, password_onchange_called); 1024 } 1025 1026 // Tests that |FillSuggestion| properly fills the username and password. 1027 TEST_F(PasswordAutofillAgentTest, FillSuggestion) { 1028 // Simulate the browser sending the login info, but set |wait_for_username| 1029 // to prevent the form from being immediately filled. 1030 fill_data_.wait_for_username = true; 1031 SimulateOnFillPasswordForm(fill_data_); 1032 1033 // Neither field should have been autocompleted. 1034 CheckTextFieldsDOMState(std::string(), false, std::string(), false); 1035 1036 // If the password field is not autocompletable, it should not be affected. 1037 SetElementReadOnly(password_element_, true); 1038 EXPECT_FALSE(password_autofill_->FillSuggestion( 1039 username_element_, kAliceUsername, kAlicePassword)); 1040 CheckTextFieldsDOMState(std::string(), false, std::string(), false); 1041 SetElementReadOnly(password_element_, false); 1042 1043 // After filling with the suggestion, both fields should be autocompleted. 1044 EXPECT_TRUE(password_autofill_->FillSuggestion( 1045 username_element_, kAliceUsername, kAlicePassword)); 1046 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); 1047 int username_length = strlen(kAliceUsername); 1048 CheckUsernameSelection(username_length, username_length); 1049 1050 // Try Filling with a suggestion with password different from the one that was 1051 // initially sent to the renderer. 1052 EXPECT_TRUE(password_autofill_->FillSuggestion( 1053 username_element_, kBobUsername, kCarolPassword)); 1054 CheckTextFieldsDOMState(kBobUsername, true, kCarolPassword, true); 1055 username_length = strlen(kBobUsername); 1056 CheckUsernameSelection(username_length, username_length); 1057 } 1058 1059 // Tests that |PreviewSuggestion| properly previews the username and password. 1060 TEST_F(PasswordAutofillAgentTest, PreviewSuggestion) { 1061 // Simulate the browser sending the login info, but set |wait_for_username| 1062 // to prevent the form from being immediately filled. 1063 fill_data_.wait_for_username = true; 1064 SimulateOnFillPasswordForm(fill_data_); 1065 1066 // Neither field should have been autocompleted. 1067 CheckTextFieldsDOMState(std::string(), false, std::string(), false); 1068 1069 // If the password field is not autocompletable, it should not be affected. 1070 SetElementReadOnly(password_element_, true); 1071 EXPECT_FALSE(password_autofill_->PreviewSuggestion( 1072 username_element_, kAliceUsername, kAlicePassword)); 1073 EXPECT_EQ(std::string(), username_element_.suggestedValue().utf8()); 1074 EXPECT_FALSE(username_element_.isAutofilled()); 1075 EXPECT_EQ(std::string(), password_element_.suggestedValue().utf8()); 1076 EXPECT_FALSE(password_element_.isAutofilled()); 1077 SetElementReadOnly(password_element_, false); 1078 1079 // After selecting the suggestion, both fields should be previewed 1080 // with suggested values. 1081 EXPECT_TRUE(password_autofill_->PreviewSuggestion( 1082 username_element_, kAliceUsername, kAlicePassword)); 1083 EXPECT_EQ( 1084 kAliceUsername, 1085 static_cast<std::string>(username_element_.suggestedValue().utf8())); 1086 EXPECT_TRUE(username_element_.isAutofilled()); 1087 EXPECT_EQ( 1088 kAlicePassword, 1089 static_cast<std::string>(password_element_.suggestedValue().utf8())); 1090 EXPECT_TRUE(password_element_.isAutofilled()); 1091 int username_length = strlen(kAliceUsername); 1092 CheckUsernameSelection(0, username_length); 1093 1094 // Try previewing with a password different from the one that was initially 1095 // sent to the renderer. 1096 EXPECT_TRUE(password_autofill_->PreviewSuggestion( 1097 username_element_, kBobUsername, kCarolPassword)); 1098 EXPECT_EQ( 1099 kBobUsername, 1100 static_cast<std::string>(username_element_.suggestedValue().utf8())); 1101 EXPECT_TRUE(username_element_.isAutofilled()); 1102 EXPECT_EQ( 1103 kCarolPassword, 1104 static_cast<std::string>(password_element_.suggestedValue().utf8())); 1105 EXPECT_TRUE(password_element_.isAutofilled()); 1106 username_length = strlen(kBobUsername); 1107 CheckUsernameSelection(0, username_length); 1108 } 1109 1110 // Tests that |PreviewSuggestion| properly sets the username selection range. 1111 TEST_F(PasswordAutofillAgentTest, PreviewSuggestionSelectionRange) { 1112 username_element_.setValue(WebString::fromUTF8("ali")); 1113 username_element_.setAutofilled(true); 1114 1115 CheckTextFieldsDOMState("ali", true, std::string(), false); 1116 1117 // Simulate the browser sending the login info, but set |wait_for_username| 1118 // to prevent the form from being immediately filled. 1119 fill_data_.wait_for_username = true; 1120 SimulateOnFillPasswordForm(fill_data_); 1121 1122 EXPECT_TRUE(password_autofill_->PreviewSuggestion( 1123 username_element_, kAliceUsername, kAlicePassword)); 1124 EXPECT_EQ( 1125 kAliceUsername, 1126 static_cast<std::string>(username_element_.suggestedValue().utf8())); 1127 EXPECT_TRUE(username_element_.isAutofilled()); 1128 EXPECT_EQ( 1129 kAlicePassword, 1130 static_cast<std::string>(password_element_.suggestedValue().utf8())); 1131 EXPECT_TRUE(password_element_.isAutofilled()); 1132 int username_length = strlen(kAliceUsername); 1133 CheckUsernameSelection(3, username_length); 1134 } 1135 1136 // Tests that |ClearPreview| properly clears previewed username and password 1137 // with password being previously autofilled. 1138 TEST_F(PasswordAutofillAgentTest, ClearPreviewWithPasswordAutofilled) { 1139 password_element_.setValue(WebString::fromUTF8("sec")); 1140 password_element_.setAutofilled(true); 1141 1142 // Simulate the browser sending the login info, but set |wait_for_username| 1143 // to prevent the form from being immediately filled. 1144 fill_data_.wait_for_username = true; 1145 SimulateOnFillPasswordForm(fill_data_); 1146 1147 CheckTextFieldsDOMState(std::string(), false, "sec", true); 1148 1149 EXPECT_TRUE(password_autofill_->PreviewSuggestion( 1150 username_element_, kAliceUsername, kAlicePassword)); 1151 1152 EXPECT_TRUE(password_autofill_->DidClearAutofillSelection( 1153 username_element_)); 1154 1155 EXPECT_TRUE(username_element_.value().isEmpty()); 1156 EXPECT_TRUE(username_element_.suggestedValue().isEmpty()); 1157 EXPECT_FALSE(username_element_.isAutofilled()); 1158 EXPECT_EQ(ASCIIToUTF16("sec"), password_element_.value()); 1159 EXPECT_TRUE(password_element_.suggestedValue().isEmpty()); 1160 EXPECT_TRUE(password_element_.isAutofilled()); 1161 CheckUsernameSelection(0, 0); 1162 } 1163 1164 // Tests that |ClearPreview| properly clears previewed username and password 1165 // with username being previously autofilled. 1166 TEST_F(PasswordAutofillAgentTest, ClearPreviewWithUsernameAutofilled) { 1167 username_element_.setValue(WebString::fromUTF8("ali")); 1168 username_element_.setAutofilled(true); 1169 1170 // Simulate the browser sending the login info, but set |wait_for_username| 1171 // to prevent the form from being immediately filled. 1172 fill_data_.wait_for_username = true; 1173 SimulateOnFillPasswordForm(fill_data_); 1174 1175 CheckTextFieldsDOMState("ali", true, std::string(), false); 1176 1177 EXPECT_TRUE(password_autofill_->PreviewSuggestion( 1178 username_element_, kAliceUsername, kAlicePassword)); 1179 1180 EXPECT_TRUE(password_autofill_->DidClearAutofillSelection( 1181 username_element_)); 1182 1183 EXPECT_EQ(ASCIIToUTF16("ali"), username_element_.value()); 1184 EXPECT_TRUE(username_element_.suggestedValue().isEmpty()); 1185 EXPECT_TRUE(username_element_.isAutofilled()); 1186 EXPECT_TRUE(password_element_.value().isEmpty()); 1187 EXPECT_TRUE(password_element_.suggestedValue().isEmpty()); 1188 EXPECT_FALSE(password_element_.isAutofilled()); 1189 CheckUsernameSelection(3, 3); 1190 } 1191 1192 // Tests that |ClearPreview| properly clears previewed username and password 1193 // with username and password being previously autofilled. 1194 TEST_F(PasswordAutofillAgentTest, 1195 ClearPreviewWithAutofilledUsernameAndPassword) { 1196 username_element_.setValue(WebString::fromUTF8("ali")); 1197 username_element_.setAutofilled(true); 1198 password_element_.setValue(WebString::fromUTF8("sec")); 1199 password_element_.setAutofilled(true); 1200 1201 // Simulate the browser sending the login info, but set |wait_for_username| 1202 // to prevent the form from being immediately filled. 1203 fill_data_.wait_for_username = true; 1204 SimulateOnFillPasswordForm(fill_data_); 1205 1206 CheckTextFieldsDOMState("ali", true, "sec", true); 1207 1208 EXPECT_TRUE(password_autofill_->PreviewSuggestion( 1209 username_element_, kAliceUsername, kAlicePassword)); 1210 1211 EXPECT_TRUE(password_autofill_->DidClearAutofillSelection( 1212 username_element_)); 1213 1214 EXPECT_EQ(ASCIIToUTF16("ali"), username_element_.value()); 1215 EXPECT_TRUE(username_element_.suggestedValue().isEmpty()); 1216 EXPECT_TRUE(username_element_.isAutofilled()); 1217 EXPECT_EQ(ASCIIToUTF16("sec"), password_element_.value()); 1218 EXPECT_TRUE(password_element_.suggestedValue().isEmpty()); 1219 EXPECT_TRUE(password_element_.isAutofilled()); 1220 CheckUsernameSelection(3, 3); 1221 } 1222 1223 // Tests that |ClearPreview| properly clears previewed username and password 1224 // with neither username nor password being previously autofilled. 1225 TEST_F(PasswordAutofillAgentTest, 1226 ClearPreviewWithNotAutofilledUsernameAndPassword) { 1227 // Simulate the browser sending the login info, but set |wait_for_username| 1228 // to prevent the form from being immediately filled. 1229 fill_data_.wait_for_username = true; 1230 SimulateOnFillPasswordForm(fill_data_); 1231 1232 CheckTextFieldsDOMState(std::string(), false, std::string(), false); 1233 1234 EXPECT_TRUE(password_autofill_->PreviewSuggestion( 1235 username_element_, kAliceUsername, kAlicePassword)); 1236 1237 EXPECT_TRUE(password_autofill_->DidClearAutofillSelection( 1238 username_element_)); 1239 1240 EXPECT_TRUE(username_element_.value().isEmpty()); 1241 EXPECT_TRUE(username_element_.suggestedValue().isEmpty()); 1242 EXPECT_FALSE(username_element_.isAutofilled()); 1243 EXPECT_TRUE(password_element_.value().isEmpty()); 1244 EXPECT_TRUE(password_element_.suggestedValue().isEmpty()); 1245 EXPECT_FALSE(password_element_.isAutofilled()); 1246 CheckUsernameSelection(0, 0); 1247 } 1248 1249 // Tests that |ClearPreview| properly restores the original selection range of 1250 // username field that has initially been filled by inline autocomplete. 1251 TEST_F(PasswordAutofillAgentTest, ClearPreviewWithInlineAutocompletedUsername) { 1252 // Simulate the browser sending back the login info. 1253 SimulateOnFillPasswordForm(fill_data_); 1254 1255 // Clear the text fields to start fresh. 1256 ClearUsernameAndPasswordFields(); 1257 1258 // Simulate the user typing in the first letter of 'alice', a stored username. 1259 SimulateUsernameChange("a", true); 1260 // Both the username and password text fields should reflect selection of the 1261 // stored login. 1262 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); 1263 // The selection should have been set to 'lice', the last 4 letters. 1264 CheckUsernameSelection(1, 5); 1265 1266 EXPECT_TRUE(password_autofill_->PreviewSuggestion( 1267 username_element_, "alicia", "secret")); 1268 EXPECT_EQ( 1269 "alicia", 1270 static_cast<std::string>(username_element_.suggestedValue().utf8())); 1271 EXPECT_TRUE(username_element_.isAutofilled()); 1272 EXPECT_EQ( 1273 "secret", 1274 static_cast<std::string>(password_element_.suggestedValue().utf8())); 1275 EXPECT_TRUE(password_element_.isAutofilled()); 1276 CheckUsernameSelection(1, 6); 1277 1278 EXPECT_TRUE(password_autofill_->DidClearAutofillSelection( 1279 username_element_)); 1280 1281 EXPECT_EQ(kAliceUsername, username_element_.value().utf8()); 1282 EXPECT_TRUE(username_element_.suggestedValue().isEmpty()); 1283 EXPECT_TRUE(username_element_.isAutofilled()); 1284 EXPECT_TRUE(password_element_.value().isEmpty()); 1285 EXPECT_TRUE(password_element_.suggestedValue().isEmpty()); 1286 EXPECT_TRUE(password_element_.isAutofilled()); 1287 CheckUsernameSelection(1, 5); 1288 } 1289 1290 // Tests that logging is off by default. 1291 TEST_F(PasswordAutofillAgentTest, OnChangeLoggingState_NoMessage) { 1292 render_thread_->sink().ClearMessages(); 1293 SendVisiblePasswordForms(); 1294 const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching( 1295 AutofillHostMsg_RecordSavePasswordProgress::ID); 1296 EXPECT_FALSE(message); 1297 } 1298 1299 // Test that logging can be turned on by a message. 1300 TEST_F(PasswordAutofillAgentTest, OnChangeLoggingState_Activated) { 1301 // Turn the logging on. 1302 AutofillMsg_SetLoggingState msg_activate(0, true); 1303 // Up-cast to access OnMessageReceived, which is private in the agent. 1304 EXPECT_TRUE(static_cast<IPC::Listener*>(password_autofill_) 1305 ->OnMessageReceived(msg_activate)); 1306 1307 render_thread_->sink().ClearMessages(); 1308 SendVisiblePasswordForms(); 1309 const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching( 1310 AutofillHostMsg_RecordSavePasswordProgress::ID); 1311 EXPECT_TRUE(message); 1312 } 1313 1314 // Test that logging can be turned off by a message. 1315 TEST_F(PasswordAutofillAgentTest, OnChangeLoggingState_Deactivated) { 1316 // Turn the logging on and then off. 1317 AutofillMsg_SetLoggingState msg_activate(0, /*active=*/true); 1318 // Up-cast to access OnMessageReceived, which is private in the agent. 1319 EXPECT_TRUE(static_cast<IPC::Listener*>(password_autofill_) 1320 ->OnMessageReceived(msg_activate)); 1321 AutofillMsg_SetLoggingState msg_deactivate(0, /*active=*/false); 1322 EXPECT_TRUE(static_cast<IPC::Listener*>(password_autofill_) 1323 ->OnMessageReceived(msg_deactivate)); 1324 1325 render_thread_->sink().ClearMessages(); 1326 SendVisiblePasswordForms(); 1327 const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching( 1328 AutofillHostMsg_RecordSavePasswordProgress::ID); 1329 EXPECT_FALSE(message); 1330 } 1331 1332 // Test that the agent sends an IPC call to get the current activity state of 1333 // password saving logging soon after construction. 1334 TEST_F(PasswordAutofillAgentTest, SendsLoggingStateUpdatePingOnConstruction) { 1335 const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching( 1336 AutofillHostMsg_PasswordAutofillAgentConstructed::ID); 1337 EXPECT_TRUE(message); 1338 } 1339 1340 } // namespace autofill 1341