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.
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"
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;
40 // The name of the username/password element in the form.
41 const char kUsernameName[] = "username";
42 const char kPasswordName[] = "password";
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";
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'/>"
59 const char kVisibleFormHTML[] =
60 "<head> <style> form {display: inline;} </style> </head>"
64 " <input type='password' id='password'/>"
69 const char kEmptyFormHTML[] =
70 "<head> <style> form {display: inline;} </style> </head>"
71 "<body> <form> </form> </body>";
73 const char kNonVisibleFormHTML[] =
74 "<head> <style> form {display: none;} </style> </head>"
78 " <input type='password' id='password'/>"
83 const char kEmptyWebpage[] =
91 const char kRedirectionWebpage[] =
94 " <meta http-equiv='Content-Type' content='text/html'>"
95 " <title>Redirection page</title>"
99 " <script type='text/javascript'>"
105 const char kSimpleWebpage[] =
108 " <meta charset='utf-8' />"
109 " <title>Title</title>"
112 " <form name='LoginTestForm'>"
113 " <input type='text' id='username'/>"
114 " <input type='password' id='password'/>"
115 " <input type='submit' value='Login'/>"
120 const char kWebpageWithDynamicContent[] =
123 " <meta charset='utf-8' />"
124 " <title>Title</title>"
127 " <script type='text/javascript'>"
128 " function addParagraph() {"
129 " var p = document.createElement('p');"
130 " document.body.appendChild(p);"
132 " window.onload = addParagraph;"
137 const char kJavaScriptClick[] =
138 "var event = new MouseEvent('click', {"
141 " 'cancelable': true"
143 "var form = document.getElementById('myform1');"
144 "form.dispatchEvent(event);"
145 "console.log('clicked!');";
147 const char kOnChangeDetectionScript[] =
149 " usernameOnchangeCalled = false;"
150 " passwordOnchangeCalled = false;"
151 " document.getElementById('username').onchange = function() {"
152 " usernameOnchangeCalled = true;"
154 " document.getElementById('password').onchange = function() {"
155 " passwordOnchangeCalled = true;"
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());
169 class PasswordAutofillAgentTest : public ChromeRenderViewTest {
171 PasswordAutofillAgentTest() {
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()
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);
184 void SendVisiblePasswordForms() {
185 static_cast<content::RenderViewObserver*>(password_autofill_agent_)
186 ->DidFinishLoad(GetMainFrame());
189 virtual void SetUp() {
190 ChromeRenderViewTest::SetUp();
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);
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);
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);
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;
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_);
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");
232 // Now retrieve the input elements so the test can access them.
233 UpdateUsernameAndPasswordElements();
236 virtual void TearDown() {
237 username_element_.reset();
238 password_element_.reset();
239 ChromeRenderViewTest::TearDown();
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);
247 void UpdateUsernameAndPasswordElements() {
248 WebDocument document = GetMainFrame()->document();
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>();
258 void ClearUsernameAndPasswordFields() {
259 username_element_.setValue("");
260 username_element_.setAutofilled(false);
261 password_element_.setValue("");
262 password_element_.setAutofilled(false);
265 void SimulateDidEndEditing(WebFrame* input_frame, WebInputElement& input) {
266 static_cast<blink::WebAutofillClient*>(autofill_agent_)
267 ->textFieldDidEndEditing(input);
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());
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.
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)));
296 base::MessageLoop::current()->RunUntilIdle();
299 void SimulateSuggestionChoice(WebInputElement& username_input) {
300 base::string16 username(base::ASCIIToUTF16(kAliceUsername));
301 base::string16 password(base::ASCIIToUTF16(kAlicePassword));
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);
309 AutofillMsg_FillPasswordSuggestion msg(0, username, password);
310 static_cast<content::RenderViewObserver*>(autofill_agent_)
311 ->OnMessageReceived(msg);
314 void LayoutMainFrame() {
315 GetMainFrame()->view()->layout();
318 void SimulateUsernameChange(const std::string& username,
319 bool move_caret_to_end,
320 bool is_user_input = false) {
321 SimulateInputChangeForElement(username,
328 // Tests that no suggestion popup is generated when the username_element_ is
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.
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
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()) {
352 password_autofill_agent_->ShowSuggestions(username_element_, false));
354 EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching(
355 AutofillHostMsg_ShowPasswordSuggestions::ID));
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);
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) {
375 static_cast<std::string>(username_element.value().utf8()));
376 EXPECT_EQ(username_autofilled, username_element.isAutofilled());
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());
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_,
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_,
415 void CheckUsernameSelection(int start, int end) {
416 EXPECT_EQ(start, username_element_.selectionStart());
417 EXPECT_EQ(end, username_element_.selectionEnd());
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,
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);
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_);
441 const IPC::Message* message =
442 render_thread_->sink().GetFirstMessageMatching(
443 AutofillHostMsg_ShowPasswordSuggestions::ID);
444 ASSERT_TRUE(message);
445 Tuple4<autofill::FormFieldData,
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;
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())
460 EXPECT_TRUE(usernames.empty());
462 render_thread_->sink().ClearMessages();
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);
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_;
486 WebInputElement username_element_;
487 WebInputElement password_element_;
490 DISALLOW_COPY_AND_ASSIGN(PasswordAutofillAgentTest);
493 // Tests that the password login is autocompleted as expected when the browser
494 // sends back the password info.
495 TEST_F(PasswordAutofillAgentTest, InitialAutocomplete) {
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.
503 // The form has been loaded, we should have sent the browser a message about
505 const IPC::Message* msg = render_thread_.sink().GetFirstMessageMatching(
506 AutofillHostMsg_PasswordFormsParsed::ID);
507 ASSERT_TRUE(msg != NULL);
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);
518 // Simulate the browser sending back the login info, it triggers the
520 SimulateOnFillPasswordForm(fill_data_);
522 // The username and password should have been autocompleted.
523 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
526 // Tests that we correctly fill forms having an empty 'action' attribute.
527 TEST_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'/>"
534 LoadHTML(kEmptyActionFormHTML);
536 // Retrieve the input elements so the test can access them.
537 WebDocument document = GetMainFrame()->document();
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>();
546 // Set the expected form origin and action URLs.
547 UpdateOriginForHTML(kEmptyActionFormHTML);
548 fill_data_.basic_data.action = fill_data_.basic_data.origin;
550 // Simulate the browser sending back the login info, it triggers the
552 SimulateOnFillPasswordForm(fill_data_);
554 // The username and password should have been autocompleted.
555 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
558 // Tests that if a password is marked as readonly, neither field is autofilled
560 TEST_F(PasswordAutofillAgentTest, NoInitialAutocompleteForReadOnlyPassword) {
561 SetElementReadOnly(password_element_, true);
563 // Simulate the browser sending back the login info, it triggers the
565 SimulateOnFillPasswordForm(fill_data_);
567 CheckTextFieldsState(std::string(), false, std::string(), false);
570 // Can still fill a password field if the username is set to a value that
572 TEST_F(PasswordAutofillAgentTest,
573 AutocompletePasswordForReadonlyUsernameMatched) {
574 username_element_.setValue(username3_);
575 SetElementReadOnly(username_element_, true);
577 // Filled even though username is not the preferred match.
578 SimulateOnFillPasswordForm(fill_data_);
579 CheckTextFieldsState(UTF16ToUTF8(username3_), false,
580 UTF16ToUTF8(password3_), true);
583 // If a username field is empty and readonly, don't autofill.
584 TEST_F(PasswordAutofillAgentTest,
585 NoAutocompletePasswordForReadonlyUsernameUnmatched) {
586 username_element_.setValue(WebString::fromUTF8(""));
587 SetElementReadOnly(username_element_, true);
589 SimulateOnFillPasswordForm(fill_data_);
590 CheckTextFieldsState(std::string(), false, std::string(), false);
593 // Tests that having a non-matching username precludes the autocomplete.
594 TEST_F(PasswordAutofillAgentTest, NoAutocompleteForFilledFieldUnmatched) {
595 username_element_.setValue(WebString::fromUTF8("bogus"));
597 // Simulate the browser sending back the login info, it triggers the
599 SimulateOnFillPasswordForm(fill_data_);
601 // Neither field should be autocompleted.
602 CheckTextFieldsState("bogus", false, std::string(), false);
605 // Don't try to complete a prefilled value even if it's a partial match
607 TEST_F(PasswordAutofillAgentTest, NoPartialMatchForPrefilledUsername) {
608 username_element_.setValue(WebString::fromUTF8("ali"));
610 SimulateOnFillPasswordForm(fill_data_);
612 CheckTextFieldsState("ali", false, std::string(), false);
615 TEST_F(PasswordAutofillAgentTest, InputWithNoForms) {
616 const char kNoFormInputs[] =
617 "<input type='text' id='username'/>"
618 "<input type='password' id='password'/>";
619 LoadHTML(kNoFormInputs);
621 SimulateOnFillPasswordForm(fill_data_);
623 // Input elements that aren't in a <form> won't autofill.
624 CheckTextFieldsState(std::string(), false, std::string(), false);
627 TEST_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'/>"
634 LoadHTML(kTextFieldPasswordFormHTML);
636 // Retrieve the input elements so the test can access them.
637 WebDocument document = GetMainFrame()->document();
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>();
646 // Set the expected form origin URL.
647 UpdateOriginForHTML(kTextFieldPasswordFormHTML);
649 SimulateOnFillPasswordForm(fill_data_);
651 // Fields should still be empty.
652 CheckTextFieldsState(std::string(), false, std::string(), false);
655 TEST_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'/>"
662 LoadHTML(kPasswordFieldUsernameFormHTML);
664 // Retrieve the input elements so the test can access them.
665 WebDocument document = GetMainFrame()->document();
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>();
674 // Set the expected form origin URL.
675 UpdateOriginForHTML(kPasswordFieldUsernameFormHTML);
677 SimulateOnFillPasswordForm(fill_data_);
679 // Fields should still be empty.
680 CheckTextFieldsState(std::string(), false, std::string(), false);
683 // Tests that having a matching username does not preclude the autocomplete.
684 TEST_F(PasswordAutofillAgentTest, InitialAutocompleteForMatchingFilledField) {
685 username_element_.setValue(WebString::fromUTF8(kAliceUsername));
687 // Simulate the browser sending back the login info, it triggers the
689 SimulateOnFillPasswordForm(fill_data_);
691 // The username and password should have been autocompleted.
692 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
695 // Tests that editing the password clears the autocompleted password field.
696 TEST_F(PasswordAutofillAgentTest, PasswordClearOnEdit) {
697 // Simulate the browser sending back the login info, it triggers the
699 SimulateOnFillPasswordForm(fill_data_);
701 // Simulate the user changing the username to some unknown username.
702 SimulateUsernameChange("alicia", true);
704 // The password should have been cleared.
705 CheckTextFieldsState("alicia", false, std::string(), false);
708 // Tests that we only autocomplete on focus lost and with a full username match
709 // when |wait_for_username| is true.
710 TEST_F(PasswordAutofillAgentTest, WaitUsername) {
711 // Simulate the browser sending back the login info.
712 fill_data_.wait_for_username = true;
713 SimulateOnFillPasswordForm(fill_data_);
715 // No auto-fill should have taken place.
716 CheckTextFieldsState(std::string(), false, std::string(), false);
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);
726 // Autocomplete should happen only when the username textfield is blurred with
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);
746 // Tests that inline autocompletion works properly.
747 TEST_F(PasswordAutofillAgentTest, InlineAutocomplete) {
748 // Simulate the browser sending back the login info.
749 SimulateOnFillPasswordForm(fill_data_);
751 ClearUsernameAndPasswordFields();
753 // Simulate the user typing in the first letter of 'alice', a stored
755 SimulateUsernameChange("a", true);
756 // Both the username and password text fields should reflect selection of the
758 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
759 // And the selection should have been set to 'lice', the last 4 letters.
760 CheckUsernameSelection(1, 5);
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);
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);
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
781 SimulateUsernameChange("alf", true);
782 CheckTextFieldsState("alf", false, std::string(), false);
783 CheckUsernameSelection(3, 3); // No selection.
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);
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
799 SimulateUsernameChange("c", true);
800 CheckTextFieldsState("c", false, std::string(), false);
801 CheckUsernameSelection(1, 1);
803 // Check that we complete other_possible_usernames as well.
804 SimulateUsernameChange("R", true);
805 CheckTextFieldsState(kCarolAlternateUsername, true, kCarolPassword, true);
806 CheckUsernameSelection(1, 17);
809 TEST_F(PasswordAutofillAgentTest, IsWebNodeVisibleTest) {
810 blink::WebVector<blink::WebFormElement> forms1, forms2, forms3;
811 blink::WebFrame* frame;
813 LoadHTML(kVisibleFormHTML);
814 frame = GetMainFrame();
815 frame->document().forms(forms1);
816 ASSERT_EQ(1u, forms1.size());
817 EXPECT_TRUE(IsWebNodeVisible(forms1[0]));
819 LoadHTML(kEmptyFormHTML);
820 frame = GetMainFrame();
821 frame->document().forms(forms2);
822 ASSERT_EQ(1u, forms2.size());
823 EXPECT_FALSE(IsWebNodeVisible(forms2[0]));
825 LoadHTML(kNonVisibleFormHTML);
826 frame = GetMainFrame();
827 frame->document().forms(forms3);
828 ASSERT_EQ(1u, forms3.size());
829 EXPECT_FALSE(IsWebNodeVisible(forms3[0]));
832 TEST_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());
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());
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());
859 TEST_F(PasswordAutofillAgentTest, SendPasswordFormsTest_Redirection) {
860 render_thread_->sink().ClearMessages();
861 LoadHTML(kEmptyWebpage);
862 EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching(
863 AutofillHostMsg_PasswordFormsRendered::ID));
865 render_thread_->sink().ClearMessages();
866 LoadHTML(kRedirectionWebpage);
867 EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching(
868 AutofillHostMsg_PasswordFormsRendered::ID));
870 render_thread_->sink().ClearMessages();
871 LoadHTML(kSimpleWebpage);
872 EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching(
873 AutofillHostMsg_PasswordFormsRendered::ID));
875 render_thread_->sink().ClearMessages();
876 LoadHTML(kWebpageWithDynamicContent);
877 EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching(
878 AutofillHostMsg_PasswordFormsRendered::ID));
881 // Tests that a password form in an iframe will not be filled in until a user
882 // interaction with the form.
883 TEST_F(PasswordAutofillAgentTest, IframeNoFillTest) {
884 const char kIframeName[] = "iframe";
885 const char kWebpageWithIframeStart[] =
888 " <meta charset='utf-8' />"
889 " <title>Title</title>"
892 " <iframe name='iframe' src=\"";
893 const char kWebpageWithIframeEnd[] =
898 std::string origin("data:text/html;charset=utf-8,");
899 origin += kSimpleWebpage;
901 std::string page_html(kWebpageWithIframeStart);
903 page_html += kWebpageWithIframeEnd;
905 LoadHTML(page_html.c_str());
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);
911 SimulateOnFillPasswordForm(fill_data_);
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);
917 WebDocument document = iframe->document();
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());
924 WebInputElement username_input = username_element.to<WebInputElement>();
925 WebInputElement password_input = password_element.to<WebInputElement>();
926 ASSERT_FALSE(username_element.isNull());
928 CheckTextFieldsStateForElements(
929 username_input, "", false, password_input, "", false, false);
931 // Simulate the user typing in the username in the iframe which should cause
933 SimulateInputChangeForElement(
934 kAliceUsername, true, iframe, username_input, true);
936 CheckTextFieldsStateForElements(username_input,
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.
947 TEST_F(PasswordAutofillAgentTest, GestureRequiredTest) {
948 // Trigger the initial autocomplete.
949 SimulateOnFillPasswordForm(fill_data_);
951 // The username and password should have been autocompleted.
952 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
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);
959 // Simulate a user click so that the password field's real value is filled.
960 SimulateElementClick(kUsernameName);
961 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true);
964 // Verfies that a DOM-activated UI event will not cause an autofill.
965 TEST_F(PasswordAutofillAgentTest, NoDOMActivationTest) {
966 // Trigger the initial autocomplete.
967 SimulateOnFillPasswordForm(fill_data_);
969 ExecuteJavaScript(kJavaScriptClick);
970 CheckTextFieldsDOMState(kAliceUsername, true, "", true);
973 // Regression test for http://crbug.com/326679
974 TEST_F(PasswordAutofillAgentTest, SelectUsernameWithUsernameAutofillOff) {
975 // Simulate the browser sending back the login info.
976 SimulateOnFillPasswordForm(fill_data_);
978 // Set the username element to autocomplete='off'
979 username_element_.setAttribute(WebString::fromUTF8("autocomplete"),
980 WebString::fromUTF8("off"));
982 // Simulate the user changing the username to some known username.
983 SimulateUsernameChange(kAliceUsername, true);
985 ExpectNoSuggestionsPopup();
988 // Regression test for http://crbug.com/326679
989 TEST_F(PasswordAutofillAgentTest,
990 SelectUnknownUsernameWithUsernameAutofillOff) {
991 // Simulate the browser sending back the login info.
992 SimulateOnFillPasswordForm(fill_data_);
994 // Set the username element to autocomplete='off'
995 username_element_.setAttribute(WebString::fromUTF8("autocomplete"),
996 WebString::fromUTF8("off"));
998 // Simulate the user changing the username to some unknown username.
999 SimulateUsernameChange("foo", true);
1001 ExpectNoSuggestionsPopup();
1004 // Regression test for http://crbug.com/326679
1005 TEST_F(PasswordAutofillAgentTest, SelectUsernameWithPasswordAutofillOff) {
1006 // Simulate the browser sending back the login info.
1007 SimulateOnFillPasswordForm(fill_data_);
1009 // Set the main password element to autocomplete='off'
1010 password_element_.setAttribute(WebString::fromUTF8("autocomplete"),
1011 WebString::fromUTF8("off"));
1013 // Simulate the user changing the username to some known username.
1014 SimulateUsernameChange(kAliceUsername, true);
1016 ExpectNoSuggestionsPopup();
1019 // Regression test for http://crbug.com/326679
1020 TEST_F(PasswordAutofillAgentTest,
1021 SelectUnknownUsernameWithPasswordAutofillOff) {
1022 // Simulate the browser sending back the login info.
1023 SimulateOnFillPasswordForm(fill_data_);
1025 // Set the main password element to autocomplete='off'
1026 password_element_.setAttribute(WebString::fromUTF8("autocomplete"),
1027 WebString::fromUTF8("off"));
1029 // Simulate the user changing the username to some unknown username.
1030 SimulateUsernameChange("foo", true);
1032 ExpectNoSuggestionsPopup();
1035 // Verifies that password autofill triggers onChange events in JavaScript for
1036 // forms that are filled on page load.
1037 TEST_F(PasswordAutofillAgentTest,
1038 PasswordAutofillTriggersOnChangeEventsOnLoad) {
1039 std::string html = std::string(kFormHTML) + kOnChangeDetectionScript;
1040 LoadHTML(html.c_str());
1041 UpdateOriginForHTML(html);
1042 UpdateUsernameAndPasswordElements();
1044 // Simulate the browser sending back the login info, it triggers the
1046 SimulateOnFillPasswordForm(fill_data_);
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);
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;
1059 ExecuteJavaScriptAndReturnIntValue(
1060 ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"),
1061 &username_onchange_called));
1062 EXPECT_EQ(1, username_onchange_called);
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);
1070 // Simulate a user click so that the password field's real value is filled.
1071 SimulateElementClick(kUsernameName);
1072 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true);
1074 // Now, a JavaScript onChange event should have been triggered for the
1075 // password as well.
1077 ExecuteJavaScriptAndReturnIntValue(
1078 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"),
1079 &password_onchange_called));
1080 EXPECT_EQ(1, password_onchange_called);
1083 // Verifies that password autofill triggers onChange events in JavaScript for
1084 // forms that are filled after page load.
1085 TEST_F(PasswordAutofillAgentTest,
1086 PasswordAutofillTriggersOnChangeEventsWaitForUsername) {
1087 std::string html = std::string(kFormHTML) + kOnChangeDetectionScript;
1088 LoadHTML(html.c_str());
1089 UpdateOriginForHTML(html);
1090 UpdateUsernameAndPasswordElements();
1092 // Simulate the browser sending back the login info, it triggers the
1094 fill_data_.wait_for_username = true;
1095 SimulateOnFillPasswordForm(fill_data_);
1097 // The username and password should not yet have been autocompleted.
1098 CheckTextFieldsState(std::string(), false, std::string(), false);
1100 // Simulate a click just to force a user gesture, since the username value is
1102 SimulateElementClick(kUsernameName);
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_);
1109 // The username and password should now have been autocompleted.
1110 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true);
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;
1117 ExecuteJavaScriptAndReturnIntValue(
1118 ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"),
1119 &username_onchange_called));
1120 EXPECT_EQ(1, username_onchange_called);
1122 ExecuteJavaScriptAndReturnIntValue(
1123 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"),
1124 &password_onchange_called));
1125 EXPECT_EQ(1, password_onchange_called);
1128 // Tests that |FillSuggestion| properly fills the username and password.
1129 TEST_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_);
1135 // Neither field should have been autocompleted.
1136 CheckTextFieldsDOMState(std::string(), false, std::string(), false);
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);
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);
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);
1161 // Tests that |PreviewSuggestion| properly previews the username and password.
1162 TEST_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_);
1168 // Neither field should have been autocompleted.
1169 CheckTextFieldsDOMState(std::string(), false, std::string(), false);
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);
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));
1187 static_cast<std::string>(username_element_.suggestedValue().utf8()));
1188 EXPECT_TRUE(username_element_.isAutofilled());
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);
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));
1202 static_cast<std::string>(username_element_.suggestedValue().utf8()));
1203 EXPECT_TRUE(username_element_.isAutofilled());
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);
1212 // Tests that |PreviewSuggestion| properly sets the username selection range.
1213 TEST_F(PasswordAutofillAgentTest, PreviewSuggestionSelectionRange) {
1214 username_element_.setValue(WebString::fromUTF8("ali"));
1215 username_element_.setSelectionRange(3, 3);
1216 username_element_.setAutofilled(true);
1218 CheckTextFieldsDOMState("ali", true, std::string(), false);
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_);
1225 EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion(
1226 username_element_, kAliceUsername, kAlicePassword));
1229 static_cast<std::string>(username_element_.suggestedValue().utf8()));
1230 EXPECT_TRUE(username_element_.isAutofilled());
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);
1239 // Tests that |ClearPreview| properly clears previewed username and password
1240 // with password being previously autofilled.
1241 TEST_F(PasswordAutofillAgentTest, ClearPreviewWithPasswordAutofilled) {
1242 password_element_.setValue(WebString::fromUTF8("sec"));
1243 password_element_.setAutofilled(true);
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_);
1250 CheckTextFieldsDOMState(std::string(), false, "sec", true);
1252 EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion(
1253 username_element_, kAliceUsername, kAlicePassword));
1256 password_autofill_agent_->DidClearAutofillSelection(username_element_));
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);
1267 // Tests that |ClearPreview| properly clears previewed username and password
1268 // with username being previously autofilled.
1269 TEST_F(PasswordAutofillAgentTest, ClearPreviewWithUsernameAutofilled) {
1270 username_element_.setValue(WebString::fromUTF8("ali"));
1271 username_element_.setSelectionRange(3, 3);
1272 username_element_.setAutofilled(true);
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_);
1279 CheckTextFieldsDOMState("ali", true, std::string(), false);
1281 EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion(
1282 username_element_, kAliceUsername, kAlicePassword));
1285 password_autofill_agent_->DidClearAutofillSelection(username_element_));
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);
1296 // Tests that |ClearPreview| properly clears previewed username and password
1297 // with username and password being previously autofilled.
1298 TEST_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);
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_);
1311 CheckTextFieldsDOMState("ali", true, "sec", true);
1313 EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion(
1314 username_element_, kAliceUsername, kAlicePassword));
1317 password_autofill_agent_->DidClearAutofillSelection(username_element_));
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);
1328 // Tests that |ClearPreview| properly clears previewed username and password
1329 // with neither username nor password being previously autofilled.
1330 TEST_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_);
1337 CheckTextFieldsDOMState(std::string(), false, std::string(), false);
1339 EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion(
1340 username_element_, kAliceUsername, kAlicePassword));
1343 password_autofill_agent_->DidClearAutofillSelection(username_element_));
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);
1354 // Tests that |ClearPreview| properly restores the original selection range of
1355 // username field that has initially been filled by inline autocomplete.
1356 TEST_F(PasswordAutofillAgentTest, ClearPreviewWithInlineAutocompletedUsername) {
1357 // Simulate the browser sending back the login info.
1358 SimulateOnFillPasswordForm(fill_data_);
1360 // Clear the text fields to start fresh.
1361 ClearUsernameAndPasswordFields();
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
1367 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
1368 // The selection should have been set to 'lice', the last 4 letters.
1369 CheckUsernameSelection(1, 5);
1371 EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion(
1372 username_element_, "alicia", "secret"));
1375 static_cast<std::string>(username_element_.suggestedValue().utf8()));
1376 EXPECT_TRUE(username_element_.isAutofilled());
1379 static_cast<std::string>(password_element_.suggestedValue().utf8()));
1380 EXPECT_TRUE(password_element_.isAutofilled());
1381 CheckUsernameSelection(1, 6);
1384 password_autofill_agent_->DidClearAutofillSelection(username_element_));
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);
1395 // Tests that logging is off by default.
1396 TEST_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);
1404 // Test that logging can be turned on by a message.
1405 TEST_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));
1412 render_thread_->sink().ClearMessages();
1413 SendVisiblePasswordForms();
1414 const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching(
1415 AutofillHostMsg_RecordSavePasswordProgress::ID);
1416 EXPECT_TRUE(message);
1419 // Test that logging can be turned off by a message.
1420 TEST_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));
1430 render_thread_->sink().ClearMessages();
1431 SendVisiblePasswordForms();
1432 const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching(
1433 AutofillHostMsg_RecordSavePasswordProgress::ID);
1434 EXPECT_FALSE(message);
1437 // Test that the agent sends an IPC call to get the current activity state of
1438 // password saving logging soon after construction.
1439 TEST_F(PasswordAutofillAgentTest, SendsLoggingStateUpdatePingOnConstruction) {
1440 const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching(
1441 AutofillHostMsg_PasswordAutofillAgentConstructed::ID);
1442 EXPECT_TRUE(message);
1445 // TODO(gcasto): Re-enabled these tests after crbug.com/423464 has been fixed.
1446 #if !defined(OS_ANDROID)
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.
1451 TEST_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();
1463 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true);
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.
1471 TEST_F(PasswordAutofillAgentTest, CredentialsOnClick) {
1472 // Simulate the browser sending back the login info.
1473 SimulateOnFillPasswordForm(fill_data_);
1475 // Clear the text fields to start fresh.
1476 ClearUsernameAndPasswordFields();
1478 // Call SimulateElementClick() to produce a user gesture on the page so
1479 // autofill will actually fill.
1480 SimulateElementClick(kUsernameName);
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();
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();
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
1502 SimulateUsernameChange("a", true);
1503 render_thread_->sink().ClearMessages();
1504 static_cast<PageClickListener*>(autofill_agent_)
1505 ->FormControlElementClicked(username_element_, true);
1506 ExpectAllCredentials();
1509 #endif // !defined(OS_ANDROID)
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.
1514 TEST_F(PasswordAutofillAgentTest,
1515 RememberLastNonEmptyPasswordOnSubmit_ScriptCleared) {
1516 SimulateInputChangeForElement(
1517 "temp", true, GetMainFrame(), username_element_, true);
1518 SimulateInputChangeForElement(
1519 "random", true, GetMainFrame(), password_element_, true);
1521 // Simulate that the password value was cleared by the site's JavaScript
1523 password_element_.setValue(WebString());
1524 static_cast<content::RenderViewObserver*>(password_autofill_agent_)
1525 ->WillSubmitForm(GetMainFrame(), username_element_.form());
1527 // Observe that the PasswordAutofillAgent still remembered the last non-empty
1528 // password and sent that to the browser.
1529 ExpectFormSubmittedWithPasswords("random", "");
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.
1535 TEST_F(PasswordAutofillAgentTest,
1536 RememberLastNonEmptyPasswordOnSubmit_UserCleared) {
1537 SimulateInputChangeForElement(
1538 "temp", true, GetMainFrame(), username_element_, true);
1539 SimulateInputChangeForElement(
1540 "random", true, GetMainFrame(), password_element_, true);
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());
1548 // Observe that the PasswordAutofillAgent respects the user having cleared the
1550 ExpectFormSubmittedWithPasswords("", "");
1553 // Similar to RememberLastNonEmptyPasswordOnSubmit_ScriptCleared, but uses the
1554 // new password instead of the current password.
1555 TEST_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'/>"
1563 LoadHTML(kNewPasswordFormHTML);
1564 UpdateUsernameAndPasswordElements();
1566 SimulateInputChangeForElement(
1567 "temp", true, GetMainFrame(), username_element_, true);
1568 SimulateInputChangeForElement(
1569 "random", true, GetMainFrame(), password_element_, true);
1571 // Simulate that the password value was cleared by the site's JavaScript
1573 password_element_.setValue(WebString());
1574 static_cast<content::RenderViewObserver*>(password_autofill_agent_)
1575 ->WillSubmitForm(GetMainFrame(), username_element_.form());
1577 // Observe that the PasswordAutofillAgent still remembered the last non-empty
1578 // password and sent that to the browser.
1579 ExpectFormSubmittedWithPasswords("", "random");
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.
1585 TEST_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,
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");
1603 // The user changes the password.
1604 SimulateInputChangeForElement(new_password,
1605 /*move_caret_to_end=*/true,
1608 /*is_user_input=*/true);
1610 // The user switches back into the username field, but leaves that without
1612 SimulateDidEndEditing(GetMainFrame(), username_element_);
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);
1620 TEST_F(PasswordAutofillAgentTest,
1621 InlineAutocompleteOverwritesManuallyEditedPassword) {
1622 // Simulate the browser sending back the login info.
1623 SimulateOnFillPasswordForm(fill_data_);
1625 ClearUsernameAndPasswordFields();
1627 // The user enters a password
1628 SimulateInputChangeForElement("someOtherPassword",
1629 /*move_caret_to_end=*/true,
1632 /*is_user_input=*/true);
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);
1640 } // namespace autofill