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 password_autofill_
->OnMessageReceived(msg
);
183 void SendVisiblePasswordForms() {
184 password_autofill_
->SendPasswordForms(GetMainFrame(),
185 true /* only_visible */);
188 virtual void SetUp() {
189 ChromeRenderViewTest::SetUp();
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
);
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
);
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
);
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
;
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_
);
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");
231 // Now retrieve the input elements so the test can access them.
232 UpdateUsernameAndPasswordElements();
235 virtual void TearDown() {
236 username_element_
.reset();
237 password_element_
.reset();
238 ChromeRenderViewTest::TearDown();
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
);
246 void UpdateUsernameAndPasswordElements() {
247 WebDocument document
= GetMainFrame()->document();
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
>();
257 void ClearUsernameAndPasswordFields() {
258 username_element_
.setValue("");
259 username_element_
.setAutofilled(false);
260 password_element_
.setValue("");
261 password_element_
.setAutofilled(false);
264 void SimulateDidEndEditing(WebFrame
* input_frame
, WebInputElement
& input
) {
265 autofill_agent_
->textFieldDidEndEditing(input
);
268 void SimulateInputChangeForElement(const std::string
& new_value
,
269 bool move_caret_to_end
,
270 WebFrame
* input_frame
,
271 WebInputElement
& input
,
272 bool is_user_input
) {
273 input
.setValue(WebString::fromUTF8(new_value
), is_user_input
);
274 // The field must have focus or AutofillAgent will think the
275 // change should be ignored.
276 while (!input
.focused())
277 input_frame
->document().frame()->view()->advanceFocus(false);
278 if (move_caret_to_end
)
279 input
.setSelectionRange(new_value
.length(), new_value
.length());
281 password_autofill_agent()->FirstUserGestureObserved();
282 autofill_agent_
->textFieldDidChange(input
);
283 // Processing is delayed because of a Blink bug:
284 // https://bugs.webkit.org/show_bug.cgi?id=16976
285 // See PasswordAutofillAgent::TextDidChangeInTextField() for details.
287 // Autocomplete will trigger a style recalculation when we put up the next
288 // frame, but we don't want to wait that long. Instead, trigger a style
289 // recalcuation manually after TextFieldDidChangeImpl runs.
290 base::MessageLoop::current()->PostTask(FROM_HERE
, base::Bind(
291 &PasswordAutofillAgentTest::LayoutMainFrame
, base::Unretained(this)));
293 base::MessageLoop::current()->RunUntilIdle();
296 void SimulateSuggestionChoice(WebInputElement
& username_input
) {
297 blink::WebString blink_username
=
298 blink::WebString::fromUTF8(kAliceUsername
);
299 blink::WebString blink_password
=
300 blink::WebString::fromUTF8(kAlicePassword
);
302 // This call is necessary to setup the autofill agent appropriate for the
303 // user selection; simulates the menu actually popping up.
304 render_thread_
->sink().ClearMessages();
305 autofill_agent_
->FormControlElementClicked(username_input
, false);
307 autofill_agent_
->OnFillPasswordSuggestion(blink_username
, blink_password
);
310 void LayoutMainFrame() {
311 GetMainFrame()->view()->layout();
314 void SimulateUsernameChange(const std::string
& username
,
315 bool move_caret_to_end
,
316 bool is_user_input
= false) {
317 SimulateInputChangeForElement(username
,
324 // Tests that no suggestion popup is generated when the username_element_ is
326 void ExpectNoSuggestionsPopup() {
327 // The first test below ensures that the suggestions have been handled by
328 // the password_autofill_agent, even though autocomplete='off' is set. The
329 // second check ensures that, although handled, no "show suggestions" IPC to
330 // the browser was generated.
332 // This is interesting in the specific case of an autocomplete='off' form
333 // that also has a remembered username and password
334 // (http://crbug.com/326679). To fix the DCHECK that this case used to hit,
335 // |true| is returned from ShowSuggestions for all forms with valid
336 // usersnames that are autocomplete='off', prentending that a selection box
337 // has been shown to the user. Of course, it hasn't, so a message is never
338 // sent to the browser on acceptance, and the DCHECK isn't hit (and nothing
341 // These tests only make sense in the context of not ignoring
342 // autocomplete='off', so only test them if the disable autocomplete='off'
343 // flag is not enabled.
344 // TODO(jww): Remove this function and callers once autocomplete='off' is
345 // permanently ignored.
346 if (!ShouldIgnoreAutocompleteOffForPasswordFields()) {
348 password_autofill_agent()->ShowSuggestions(username_element_
, false));
350 EXPECT_FALSE(render_thread_
->sink().GetFirstMessageMatching(
351 AutofillHostMsg_ShowPasswordSuggestions::ID
));
355 void SimulateKeyDownEvent(const WebInputElement
& element
,
356 ui::KeyboardCode key_code
) {
357 blink::WebKeyboardEvent key_event
;
358 key_event
.windowsKeyCode
= key_code
;
359 autofill_agent_
->textFieldDidReceiveKeyDown(element
, key_event
);
362 void CheckTextFieldsStateForElements(const WebInputElement
& username_element
,
363 const std::string
& username
,
364 bool username_autofilled
,
365 const WebInputElement
& password_element
,
366 const std::string
& password
,
367 bool password_autofilled
,
368 bool checkSuggestedValue
) {
370 static_cast<std::string
>(username_element
.value().utf8()));
371 EXPECT_EQ(username_autofilled
, username_element
.isAutofilled());
373 static_cast<std::string
>(
374 checkSuggestedValue
? password_element
.suggestedValue().utf8()
375 : password_element
.value().utf8()))
376 << "checkSuggestedValue == " << checkSuggestedValue
;
377 EXPECT_EQ(password_autofilled
, password_element
.isAutofilled());
380 // Checks the DOM-accessible value of the username element and the
381 // *suggested* value of the password element.
382 void CheckTextFieldsState(const std::string
& username
,
383 bool username_autofilled
,
384 const std::string
& password
,
385 bool password_autofilled
) {
386 CheckTextFieldsStateForElements(username_element_
,
395 // Checks the DOM-accessible value of the username element and the
396 // DOM-accessible value of the password element.
397 void CheckTextFieldsDOMState(const std::string
& username
,
398 bool username_autofilled
,
399 const std::string
& password
,
400 bool password_autofilled
) {
401 CheckTextFieldsStateForElements(username_element_
,
410 void CheckUsernameSelection(int start
, int end
) {
411 EXPECT_EQ(start
, username_element_
.selectionStart());
412 EXPECT_EQ(end
, username_element_
.selectionEnd());
415 void ExpectOneCredential(const base::string16
& username
) {
416 const IPC::Message
* message
=
417 render_thread_
->sink().GetFirstMessageMatching(
418 AutofillHostMsg_ShowPasswordSuggestions::ID
);
419 ASSERT_TRUE(message
);
420 Tuple4
<autofill::FormFieldData
,
422 std::vector
<base::string16
>,
423 std::vector
<base::string16
> > args
;
424 AutofillHostMsg_ShowPasswordSuggestions::Read(message
, &args
);
425 ASSERT_EQ(1u, args
.c
.size());
426 EXPECT_TRUE(args
.c
[0] == username
);
429 void ExpectAllCredentials() {
430 std::set
<base::string16
> usernames
;
431 usernames
.insert(username1_
);
432 usernames
.insert(username2_
);
433 usernames
.insert(username3_
);
434 usernames
.insert(alternate_username3_
);
436 const IPC::Message
* message
=
437 render_thread_
->sink().GetFirstMessageMatching(
438 AutofillHostMsg_ShowPasswordSuggestions::ID
);
439 ASSERT_TRUE(message
);
440 Tuple4
<autofill::FormFieldData
,
442 std::vector
<base::string16
>,
443 std::vector
<base::string16
> > args
;
444 AutofillHostMsg_ShowPasswordSuggestions::Read(message
, &args
);
445 ASSERT_EQ(4u, args
.c
.size());
446 std::set
<base::string16
>::iterator it
;
448 for (int i
= 0; i
< 4; i
++) {
449 it
= usernames
.find(args
.c
[i
]);
450 EXPECT_TRUE(it
!= usernames
.end());
451 if (it
!= usernames
.end())
455 EXPECT_TRUE(usernames
.empty());
457 render_thread_
->sink().ClearMessages();
460 PasswordAutofillAgent
* password_autofill_agent() {
461 return autofill_agent_
->password_autofill_agent_
;
464 void ExpectFormSubmittedWithPasswords(const std::string
& password_value
,
465 const std::string
& new_password_value
) {
466 const IPC::Message
* message
=
467 render_thread_
->sink().GetFirstMessageMatching(
468 AutofillHostMsg_PasswordFormSubmitted::ID
);
469 ASSERT_TRUE(message
);
470 Tuple1
<autofill::PasswordForm
> args
;
471 AutofillHostMsg_PasswordFormSubmitted::Read(message
, &args
);
472 EXPECT_EQ(ASCIIToUTF16(password_value
), args
.a
.password_value
);
473 EXPECT_EQ(ASCIIToUTF16(new_password_value
), args
.a
.new_password_value
);
476 base::string16 username1_
;
477 base::string16 username2_
;
478 base::string16 username3_
;
479 base::string16 password1_
;
480 base::string16 password2_
;
481 base::string16 password3_
;
482 base::string16 alternate_username3_
;
483 PasswordFormFillData fill_data_
;
485 WebInputElement username_element_
;
486 WebInputElement password_element_
;
489 DISALLOW_COPY_AND_ASSIGN(PasswordAutofillAgentTest
);
492 // Tests that the password login is autocompleted as expected when the browser
493 // sends back the password info.
494 TEST_F(PasswordAutofillAgentTest
, InitialAutocomplete
) {
496 * Right now we are not sending the message to the browser because we are
497 * loading a data URL and the security origin canAccessPasswordManager()
498 * returns false. May be we should mock URL loading to cirmcuvent this?
499 TODO(jcivelli): find a way to make the security origin not deny access to the
500 password manager and then reenable this code.
502 // The form has been loaded, we should have sent the browser a message about
504 const IPC::Message* msg = render_thread_.sink().GetFirstMessageMatching(
505 AutofillHostMsg_PasswordFormsParsed::ID);
506 ASSERT_TRUE(msg != NULL);
508 Tuple1<std::vector<PasswordForm> > forms;
509 AutofillHostMsg_PasswordFormsParsed::Read(msg, &forms);
510 ASSERT_EQ(1U, forms.a.size());
511 PasswordForm password_form = forms.a[0];
512 EXPECT_EQ(PasswordForm::SCHEME_HTML, password_form.scheme);
513 EXPECT_EQ(ASCIIToUTF16(kUsernameName), password_form.username_element);
514 EXPECT_EQ(ASCIIToUTF16(kPasswordName), password_form.password_element);
517 // Simulate the browser sending back the login info, it triggers the
519 SimulateOnFillPasswordForm(fill_data_
);
521 // The username and password should have been autocompleted.
522 CheckTextFieldsState(kAliceUsername
, true, kAlicePassword
, true);
525 // Tests that we correctly fill forms having an empty 'action' attribute.
526 TEST_F(PasswordAutofillAgentTest
, InitialAutocompleteForEmptyAction
) {
527 const char kEmptyActionFormHTML
[] =
528 "<FORM name='LoginTestForm'>"
529 " <INPUT type='text' id='username'/>"
530 " <INPUT type='password' id='password'/>"
531 " <INPUT type='submit' value='Login'/>"
533 LoadHTML(kEmptyActionFormHTML
);
535 // Retrieve the input elements so the test can access them.
536 WebDocument document
= GetMainFrame()->document();
538 document
.getElementById(WebString::fromUTF8(kUsernameName
));
539 ASSERT_FALSE(element
.isNull());
540 username_element_
= element
.to
<blink::WebInputElement
>();
541 element
= document
.getElementById(WebString::fromUTF8(kPasswordName
));
542 ASSERT_FALSE(element
.isNull());
543 password_element_
= element
.to
<blink::WebInputElement
>();
545 // Set the expected form origin and action URLs.
546 UpdateOriginForHTML(kEmptyActionFormHTML
);
547 fill_data_
.basic_data
.action
= fill_data_
.basic_data
.origin
;
549 // Simulate the browser sending back the login info, it triggers the
551 SimulateOnFillPasswordForm(fill_data_
);
553 // The username and password should have been autocompleted.
554 CheckTextFieldsState(kAliceUsername
, true, kAlicePassword
, true);
557 // Tests that if a password is marked as readonly, neither field is autofilled
559 TEST_F(PasswordAutofillAgentTest
, NoInitialAutocompleteForReadOnlyPassword
) {
560 SetElementReadOnly(password_element_
, true);
562 // Simulate the browser sending back the login info, it triggers the
564 SimulateOnFillPasswordForm(fill_data_
);
566 CheckTextFieldsState(std::string(), false, std::string(), false);
569 // Can still fill a password field if the username is set to a value that
571 TEST_F(PasswordAutofillAgentTest
,
572 AutocompletePasswordForReadonlyUsernameMatched
) {
573 username_element_
.setValue(username3_
);
574 SetElementReadOnly(username_element_
, true);
576 // Filled even though username is not the preferred match.
577 SimulateOnFillPasswordForm(fill_data_
);
578 CheckTextFieldsState(UTF16ToUTF8(username3_
), false,
579 UTF16ToUTF8(password3_
), true);
582 // If a username field is empty and readonly, don't autofill.
583 TEST_F(PasswordAutofillAgentTest
,
584 NoAutocompletePasswordForReadonlyUsernameUnmatched
) {
585 username_element_
.setValue(WebString::fromUTF8(""));
586 SetElementReadOnly(username_element_
, true);
588 SimulateOnFillPasswordForm(fill_data_
);
589 CheckTextFieldsState(std::string(), false, std::string(), false);
592 // Tests that having a non-matching username precludes the autocomplete.
593 TEST_F(PasswordAutofillAgentTest
, NoAutocompleteForFilledFieldUnmatched
) {
594 username_element_
.setValue(WebString::fromUTF8("bogus"));
596 // Simulate the browser sending back the login info, it triggers the
598 SimulateOnFillPasswordForm(fill_data_
);
600 // Neither field should be autocompleted.
601 CheckTextFieldsState("bogus", false, std::string(), false);
604 // Don't try to complete a prefilled value even if it's a partial match
606 TEST_F(PasswordAutofillAgentTest
, NoPartialMatchForPrefilledUsername
) {
607 username_element_
.setValue(WebString::fromUTF8("ali"));
609 SimulateOnFillPasswordForm(fill_data_
);
611 CheckTextFieldsState("ali", false, std::string(), false);
614 TEST_F(PasswordAutofillAgentTest
, InputWithNoForms
) {
615 const char kNoFormInputs
[] =
616 "<input type='text' id='username'/>"
617 "<input type='password' id='password'/>";
618 LoadHTML(kNoFormInputs
);
620 SimulateOnFillPasswordForm(fill_data_
);
622 // Input elements that aren't in a <form> won't autofill.
623 CheckTextFieldsState(std::string(), false, std::string(), false);
626 TEST_F(PasswordAutofillAgentTest
, NoAutocompleteForTextFieldPasswords
) {
627 const char kTextFieldPasswordFormHTML
[] =
628 "<FORM name='LoginTestForm' action='http://www.bidule.com'>"
629 " <INPUT type='text' id='username'/>"
630 " <INPUT type='text' id='password'/>"
631 " <INPUT type='submit' value='Login'/>"
633 LoadHTML(kTextFieldPasswordFormHTML
);
635 // Retrieve the input elements so the test can access them.
636 WebDocument document
= GetMainFrame()->document();
638 document
.getElementById(WebString::fromUTF8(kUsernameName
));
639 ASSERT_FALSE(element
.isNull());
640 username_element_
= element
.to
<blink::WebInputElement
>();
641 element
= document
.getElementById(WebString::fromUTF8(kPasswordName
));
642 ASSERT_FALSE(element
.isNull());
643 password_element_
= element
.to
<blink::WebInputElement
>();
645 // Set the expected form origin URL.
646 UpdateOriginForHTML(kTextFieldPasswordFormHTML
);
648 SimulateOnFillPasswordForm(fill_data_
);
650 // Fields should still be empty.
651 CheckTextFieldsState(std::string(), false, std::string(), false);
654 TEST_F(PasswordAutofillAgentTest
, NoAutocompleteForPasswordFieldUsernames
) {
655 const char kPasswordFieldUsernameFormHTML
[] =
656 "<FORM name='LoginTestForm' action='http://www.bidule.com'>"
657 " <INPUT type='password' id='username'/>"
658 " <INPUT type='password' id='password'/>"
659 " <INPUT type='submit' value='Login'/>"
661 LoadHTML(kPasswordFieldUsernameFormHTML
);
663 // Retrieve the input elements so the test can access them.
664 WebDocument document
= GetMainFrame()->document();
666 document
.getElementById(WebString::fromUTF8(kUsernameName
));
667 ASSERT_FALSE(element
.isNull());
668 username_element_
= element
.to
<blink::WebInputElement
>();
669 element
= document
.getElementById(WebString::fromUTF8(kPasswordName
));
670 ASSERT_FALSE(element
.isNull());
671 password_element_
= element
.to
<blink::WebInputElement
>();
673 // Set the expected form origin URL.
674 UpdateOriginForHTML(kPasswordFieldUsernameFormHTML
);
676 SimulateOnFillPasswordForm(fill_data_
);
678 // Fields should still be empty.
679 CheckTextFieldsState(std::string(), false, std::string(), false);
682 // Tests that having a matching username does not preclude the autocomplete.
683 TEST_F(PasswordAutofillAgentTest
, InitialAutocompleteForMatchingFilledField
) {
684 username_element_
.setValue(WebString::fromUTF8(kAliceUsername
));
686 // Simulate the browser sending back the login info, it triggers the
688 SimulateOnFillPasswordForm(fill_data_
);
690 // The username and password should have been autocompleted.
691 CheckTextFieldsState(kAliceUsername
, true, kAlicePassword
, true);
694 // Tests that editing the password clears the autocompleted password field.
695 TEST_F(PasswordAutofillAgentTest
, PasswordClearOnEdit
) {
696 // Simulate the browser sending back the login info, it triggers the
698 SimulateOnFillPasswordForm(fill_data_
);
700 // Simulate the user changing the username to some unknown username.
701 SimulateUsernameChange("alicia", true);
703 // The password should have been cleared.
704 CheckTextFieldsState("alicia", false, std::string(), false);
707 // Tests that we only autocomplete on focus lost and with a full username match
708 // when |wait_for_username| is true.
709 TEST_F(PasswordAutofillAgentTest
, WaitUsername
) {
710 // Simulate the browser sending back the login info.
711 fill_data_
.wait_for_username
= true;
712 SimulateOnFillPasswordForm(fill_data_
);
714 // No auto-fill should have taken place.
715 CheckTextFieldsState(std::string(), false, std::string(), false);
717 // No autocomplete should happen when text is entered in the username.
718 SimulateUsernameChange("a", true);
719 CheckTextFieldsState("a", false, std::string(), false);
720 SimulateUsernameChange("al", true);
721 CheckTextFieldsState("al", false, std::string(), false);
722 SimulateUsernameChange(kAliceUsername
, true);
723 CheckTextFieldsState(kAliceUsername
, false, std::string(), false);
725 // Autocomplete should happen only when the username textfield is blurred with
727 username_element_
.setValue("a");
728 autofill_agent_
->textFieldDidEndEditing(username_element_
);
729 CheckTextFieldsState("a", false, std::string(), false);
730 username_element_
.setValue("al");
731 autofill_agent_
->textFieldDidEndEditing(username_element_
);
732 CheckTextFieldsState("al", false, std::string(), false);
733 username_element_
.setValue("alices");
734 autofill_agent_
->textFieldDidEndEditing(username_element_
);
735 CheckTextFieldsState("alices", false, std::string(), false);
736 username_element_
.setValue(ASCIIToUTF16(kAliceUsername
));
737 autofill_agent_
->textFieldDidEndEditing(username_element_
);
738 CheckTextFieldsState(kAliceUsername
, true, kAlicePassword
, true);
741 // Tests that inline autocompletion works properly.
742 TEST_F(PasswordAutofillAgentTest
, InlineAutocomplete
) {
743 // Simulate the browser sending back the login info.
744 SimulateOnFillPasswordForm(fill_data_
);
746 ClearUsernameAndPasswordFields();
748 // Simulate the user typing in the first letter of 'alice', a stored
750 SimulateUsernameChange("a", true);
751 // Both the username and password text fields should reflect selection of the
753 CheckTextFieldsState(kAliceUsername
, true, kAlicePassword
, true);
754 // And the selection should have been set to 'lice', the last 4 letters.
755 CheckUsernameSelection(1, 5);
757 // Now the user types the next letter of the same username, 'l'.
758 SimulateUsernameChange("al", true);
759 // Now the fields should have the same value, but the selection should have a
760 // different start value.
761 CheckTextFieldsState(kAliceUsername
, true, kAlicePassword
, true);
762 CheckUsernameSelection(2, 5);
764 // Test that deleting does not trigger autocomplete.
765 SimulateKeyDownEvent(username_element_
, ui::VKEY_BACK
);
766 SimulateUsernameChange("alic", true);
767 CheckTextFieldsState("alic", false, std::string(), false);
768 CheckUsernameSelection(4, 4); // No selection.
769 // Reset the last pressed key to something other than backspace.
770 SimulateKeyDownEvent(username_element_
, ui::VKEY_A
);
772 // Now lets say the user goes astray from the stored username and types the
773 // letter 'f', spelling 'alf'. We don't know alf (that's just sad), so in
774 // practice the username should no longer be 'alice' and the selected range
776 SimulateUsernameChange("alf", true);
777 CheckTextFieldsState("alf", false, std::string(), false);
778 CheckUsernameSelection(3, 3); // No selection.
780 // Ok, so now the user removes all the text and enters the letter 'b'.
781 SimulateUsernameChange("b", true);
782 // The username and password fields should match the 'bob' entry.
783 CheckTextFieldsState(kBobUsername
, true, kBobPassword
, true);
784 CheckUsernameSelection(1, 3);
786 // Then, the user again removes all the text and types an uppercase 'C'.
787 SimulateUsernameChange("C", true);
788 // The username and password fields should match the 'Carol' entry.
789 CheckTextFieldsState(kCarolUsername
, true, kCarolPassword
, true);
790 CheckUsernameSelection(1, 5);
791 // The user removes all the text and types a lowercase 'c'. We only
792 // want case-sensitive autocompletion, so the username and the selected range
794 SimulateUsernameChange("c", true);
795 CheckTextFieldsState("c", false, std::string(), false);
796 CheckUsernameSelection(1, 1);
798 // Check that we complete other_possible_usernames as well.
799 SimulateUsernameChange("R", true);
800 CheckTextFieldsState(kCarolAlternateUsername
, true, kCarolPassword
, true);
801 CheckUsernameSelection(1, 17);
804 TEST_F(PasswordAutofillAgentTest
, IsWebNodeVisibleTest
) {
805 blink::WebVector
<blink::WebFormElement
> forms1
, forms2
, forms3
;
806 blink::WebFrame
* frame
;
808 LoadHTML(kVisibleFormHTML
);
809 frame
= GetMainFrame();
810 frame
->document().forms(forms1
);
811 ASSERT_EQ(1u, forms1
.size());
812 EXPECT_TRUE(IsWebNodeVisible(forms1
[0]));
814 LoadHTML(kEmptyFormHTML
);
815 frame
= GetMainFrame();
816 frame
->document().forms(forms2
);
817 ASSERT_EQ(1u, forms2
.size());
818 EXPECT_FALSE(IsWebNodeVisible(forms2
[0]));
820 LoadHTML(kNonVisibleFormHTML
);
821 frame
= GetMainFrame();
822 frame
->document().forms(forms3
);
823 ASSERT_EQ(1u, forms3
.size());
824 EXPECT_FALSE(IsWebNodeVisible(forms3
[0]));
827 TEST_F(PasswordAutofillAgentTest
, SendPasswordFormsTest
) {
828 render_thread_
->sink().ClearMessages();
829 LoadHTML(kVisibleFormHTML
);
830 const IPC::Message
* message
= render_thread_
->sink()
831 .GetFirstMessageMatching(AutofillHostMsg_PasswordFormsRendered::ID
);
832 EXPECT_TRUE(message
);
833 Tuple2
<std::vector
<autofill::PasswordForm
>, bool > param
;
834 AutofillHostMsg_PasswordFormsRendered::Read(message
, ¶m
);
835 EXPECT_TRUE(param
.a
.size());
837 render_thread_
->sink().ClearMessages();
838 LoadHTML(kEmptyFormHTML
);
839 message
= render_thread_
->sink().GetFirstMessageMatching(
840 AutofillHostMsg_PasswordFormsRendered::ID
);
841 EXPECT_TRUE(message
);
842 AutofillHostMsg_PasswordFormsRendered::Read(message
, ¶m
);
843 EXPECT_FALSE(param
.a
.size());
845 render_thread_
->sink().ClearMessages();
846 LoadHTML(kNonVisibleFormHTML
);
847 message
= render_thread_
->sink().GetFirstMessageMatching(
848 AutofillHostMsg_PasswordFormsRendered::ID
);
849 EXPECT_TRUE(message
);
850 AutofillHostMsg_PasswordFormsRendered::Read(message
, ¶m
);
851 EXPECT_FALSE(param
.a
.size());
854 TEST_F(PasswordAutofillAgentTest
, SendPasswordFormsTest_Redirection
) {
855 render_thread_
->sink().ClearMessages();
856 LoadHTML(kEmptyWebpage
);
857 EXPECT_FALSE(render_thread_
->sink().GetFirstMessageMatching(
858 AutofillHostMsg_PasswordFormsRendered::ID
));
860 render_thread_
->sink().ClearMessages();
861 LoadHTML(kRedirectionWebpage
);
862 EXPECT_FALSE(render_thread_
->sink().GetFirstMessageMatching(
863 AutofillHostMsg_PasswordFormsRendered::ID
));
865 render_thread_
->sink().ClearMessages();
866 LoadHTML(kSimpleWebpage
);
867 EXPECT_TRUE(render_thread_
->sink().GetFirstMessageMatching(
868 AutofillHostMsg_PasswordFormsRendered::ID
));
870 render_thread_
->sink().ClearMessages();
871 LoadHTML(kWebpageWithDynamicContent
);
872 EXPECT_TRUE(render_thread_
->sink().GetFirstMessageMatching(
873 AutofillHostMsg_PasswordFormsRendered::ID
));
876 // Tests that a password form in an iframe will not be filled in until a user
877 // interaction with the form.
878 TEST_F(PasswordAutofillAgentTest
, IframeNoFillTest
) {
879 const char kIframeName
[] = "iframe";
880 const char kWebpageWithIframeStart
[] =
883 " <meta charset='utf-8' />"
884 " <title>Title</title>"
887 " <iframe name='iframe' src=\"";
888 const char kWebpageWithIframeEnd
[] =
893 std::string
origin("data:text/html;charset=utf-8,");
894 origin
+= kSimpleWebpage
;
896 std::string
page_html(kWebpageWithIframeStart
);
898 page_html
+= kWebpageWithIframeEnd
;
900 LoadHTML(page_html
.c_str());
902 // Set the expected form origin and action URLs.
903 fill_data_
.basic_data
.origin
= GURL(origin
);
904 fill_data_
.basic_data
.action
= GURL(origin
);
906 SimulateOnFillPasswordForm(fill_data_
);
908 // Retrieve the input elements from the iframe since that is where we want to
909 // test the autofill.
910 WebFrame
* iframe
= GetMainFrame()->findChildByName(kIframeName
);
912 WebDocument document
= iframe
->document();
914 WebElement username_element
= document
.getElementById(kUsernameName
);
915 WebElement password_element
= document
.getElementById(kPasswordName
);
916 ASSERT_FALSE(username_element
.isNull());
917 ASSERT_FALSE(password_element
.isNull());
919 WebInputElement username_input
= username_element
.to
<WebInputElement
>();
920 WebInputElement password_input
= password_element
.to
<WebInputElement
>();
921 ASSERT_FALSE(username_element
.isNull());
923 CheckTextFieldsStateForElements(
924 username_input
, "", false, password_input
, "", false, false);
926 // Simulate the user typing in the username in the iframe which should cause
928 SimulateInputChangeForElement(
929 kAliceUsername
, true, iframe
, username_input
, true);
931 CheckTextFieldsStateForElements(username_input
,
940 // Tests that a password will only be filled as a suggested and will not be
941 // accessible by the DOM until a user gesture has occurred.
942 TEST_F(PasswordAutofillAgentTest
, GestureRequiredTest
) {
943 // Trigger the initial autocomplete.
944 SimulateOnFillPasswordForm(fill_data_
);
946 // The username and password should have been autocompleted.
947 CheckTextFieldsState(kAliceUsername
, true, kAlicePassword
, true);
949 // However, it should only have completed with the suggested value, as tested
950 // above, and it should not have completed into the DOM accessible value for
951 // the password field.
952 CheckTextFieldsDOMState(kAliceUsername
, true, std::string(), true);
954 // Simulate a user click so that the password field's real value is filled.
955 SimulateElementClick(kUsernameName
);
956 CheckTextFieldsDOMState(kAliceUsername
, true, kAlicePassword
, true);
959 // Verfies that a DOM-activated UI event will not cause an autofill.
960 TEST_F(PasswordAutofillAgentTest
, NoDOMActivationTest
) {
961 // Trigger the initial autocomplete.
962 SimulateOnFillPasswordForm(fill_data_
);
964 ExecuteJavaScript(kJavaScriptClick
);
965 CheckTextFieldsDOMState(kAliceUsername
, true, "", true);
968 // Regression test for http://crbug.com/326679
969 TEST_F(PasswordAutofillAgentTest
, SelectUsernameWithUsernameAutofillOff
) {
970 // Simulate the browser sending back the login info.
971 SimulateOnFillPasswordForm(fill_data_
);
973 // Set the username element to autocomplete='off'
974 username_element_
.setAttribute(WebString::fromUTF8("autocomplete"),
975 WebString::fromUTF8("off"));
977 // Simulate the user changing the username to some known username.
978 SimulateUsernameChange(kAliceUsername
, true);
980 ExpectNoSuggestionsPopup();
983 // Regression test for http://crbug.com/326679
984 TEST_F(PasswordAutofillAgentTest
,
985 SelectUnknownUsernameWithUsernameAutofillOff
) {
986 // Simulate the browser sending back the login info.
987 SimulateOnFillPasswordForm(fill_data_
);
989 // Set the username element to autocomplete='off'
990 username_element_
.setAttribute(WebString::fromUTF8("autocomplete"),
991 WebString::fromUTF8("off"));
993 // Simulate the user changing the username to some unknown username.
994 SimulateUsernameChange("foo", true);
996 ExpectNoSuggestionsPopup();
999 // Regression test for http://crbug.com/326679
1000 TEST_F(PasswordAutofillAgentTest
, SelectUsernameWithPasswordAutofillOff
) {
1001 // Simulate the browser sending back the login info.
1002 SimulateOnFillPasswordForm(fill_data_
);
1004 // Set the main password element to autocomplete='off'
1005 password_element_
.setAttribute(WebString::fromUTF8("autocomplete"),
1006 WebString::fromUTF8("off"));
1008 // Simulate the user changing the username to some known username.
1009 SimulateUsernameChange(kAliceUsername
, true);
1011 ExpectNoSuggestionsPopup();
1014 // Regression test for http://crbug.com/326679
1015 TEST_F(PasswordAutofillAgentTest
,
1016 SelectUnknownUsernameWithPasswordAutofillOff
) {
1017 // Simulate the browser sending back the login info.
1018 SimulateOnFillPasswordForm(fill_data_
);
1020 // Set the main password element to autocomplete='off'
1021 password_element_
.setAttribute(WebString::fromUTF8("autocomplete"),
1022 WebString::fromUTF8("off"));
1024 // Simulate the user changing the username to some unknown username.
1025 SimulateUsernameChange("foo", true);
1027 ExpectNoSuggestionsPopup();
1030 // Verifies that password autofill triggers onChange events in JavaScript for
1031 // forms that are filled on page load.
1032 TEST_F(PasswordAutofillAgentTest
,
1033 PasswordAutofillTriggersOnChangeEventsOnLoad
) {
1034 std::string html
= std::string(kFormHTML
) + kOnChangeDetectionScript
;
1035 LoadHTML(html
.c_str());
1036 UpdateOriginForHTML(html
);
1037 UpdateUsernameAndPasswordElements();
1039 // Simulate the browser sending back the login info, it triggers the
1041 SimulateOnFillPasswordForm(fill_data_
);
1043 // The username and password should have been autocompleted...
1044 CheckTextFieldsState(kAliceUsername
, true, kAlicePassword
, true);
1045 // ... but since there hasn't been a user gesture yet, the autocompleted
1046 // password should only be visible to the user.
1047 CheckTextFieldsDOMState(kAliceUsername
, true, std::string(), true);
1049 // A JavaScript onChange event should have been triggered for the username,
1050 // but not yet for the password.
1051 int username_onchange_called
= -1;
1052 int password_onchange_called
= -1;
1054 ExecuteJavaScriptAndReturnIntValue(
1055 ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"),
1056 &username_onchange_called
));
1057 EXPECT_EQ(1, username_onchange_called
);
1059 ExecuteJavaScriptAndReturnIntValue(
1060 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"),
1061 &password_onchange_called
));
1062 // TODO(isherman): Re-enable this check once http://crbug.com/333144 is fixed.
1063 // EXPECT_EQ(0, password_onchange_called);
1065 // Simulate a user click so that the password field's real value is filled.
1066 SimulateElementClick(kUsernameName
);
1067 CheckTextFieldsDOMState(kAliceUsername
, true, kAlicePassword
, true);
1069 // Now, a JavaScript onChange event should have been triggered for the
1070 // password as well.
1072 ExecuteJavaScriptAndReturnIntValue(
1073 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"),
1074 &password_onchange_called
));
1075 EXPECT_EQ(1, password_onchange_called
);
1078 // Verifies that password autofill triggers onChange events in JavaScript for
1079 // forms that are filled after page load.
1080 TEST_F(PasswordAutofillAgentTest
,
1081 PasswordAutofillTriggersOnChangeEventsWaitForUsername
) {
1082 std::string html
= std::string(kFormHTML
) + kOnChangeDetectionScript
;
1083 LoadHTML(html
.c_str());
1084 UpdateOriginForHTML(html
);
1085 UpdateUsernameAndPasswordElements();
1087 // Simulate the browser sending back the login info, it triggers the
1089 fill_data_
.wait_for_username
= true;
1090 SimulateOnFillPasswordForm(fill_data_
);
1092 // The username and password should not yet have been autocompleted.
1093 CheckTextFieldsState(std::string(), false, std::string(), false);
1095 // Simulate a click just to force a user gesture, since the username value is
1097 SimulateElementClick(kUsernameName
);
1099 // Simulate the user entering her username and selecting the matching autofill
1100 // from the dropdown.
1101 SimulateUsernameChange(kAliceUsername
, true, true);
1102 SimulateSuggestionChoice(username_element_
);
1104 // The username and password should now have been autocompleted.
1105 CheckTextFieldsDOMState(kAliceUsername
, true, kAlicePassword
, true);
1107 // JavaScript onChange events should have been triggered both for the username
1108 // and for the password.
1109 int username_onchange_called
= -1;
1110 int password_onchange_called
= -1;
1112 ExecuteJavaScriptAndReturnIntValue(
1113 ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"),
1114 &username_onchange_called
));
1115 EXPECT_EQ(1, username_onchange_called
);
1117 ExecuteJavaScriptAndReturnIntValue(
1118 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"),
1119 &password_onchange_called
));
1120 EXPECT_EQ(1, password_onchange_called
);
1123 // Tests that |FillSuggestion| properly fills the username and password.
1124 TEST_F(PasswordAutofillAgentTest
, FillSuggestion
) {
1125 // Simulate the browser sending the login info, but set |wait_for_username|
1126 // to prevent the form from being immediately filled.
1127 fill_data_
.wait_for_username
= true;
1128 SimulateOnFillPasswordForm(fill_data_
);
1130 // Neither field should have been autocompleted.
1131 CheckTextFieldsDOMState(std::string(), false, std::string(), false);
1133 // If the password field is not autocompletable, it should not be affected.
1134 SetElementReadOnly(password_element_
, true);
1135 EXPECT_FALSE(password_autofill_
->FillSuggestion(
1136 username_element_
, kAliceUsername
, kAlicePassword
));
1137 CheckTextFieldsDOMState(std::string(), false, std::string(), false);
1138 SetElementReadOnly(password_element_
, false);
1140 // After filling with the suggestion, both fields should be autocompleted.
1141 EXPECT_TRUE(password_autofill_
->FillSuggestion(
1142 username_element_
, kAliceUsername
, kAlicePassword
));
1143 CheckTextFieldsDOMState(kAliceUsername
, true, kAlicePassword
, true);
1144 int username_length
= strlen(kAliceUsername
);
1145 CheckUsernameSelection(username_length
, username_length
);
1147 // Try Filling with a suggestion with password different from the one that was
1148 // initially sent to the renderer.
1149 EXPECT_TRUE(password_autofill_
->FillSuggestion(
1150 username_element_
, kBobUsername
, kCarolPassword
));
1151 CheckTextFieldsDOMState(kBobUsername
, true, kCarolPassword
, true);
1152 username_length
= strlen(kBobUsername
);
1153 CheckUsernameSelection(username_length
, username_length
);
1156 // Tests that |PreviewSuggestion| properly previews the username and password.
1157 TEST_F(PasswordAutofillAgentTest
, PreviewSuggestion
) {
1158 // Simulate the browser sending the login info, but set |wait_for_username|
1159 // to prevent the form from being immediately filled.
1160 fill_data_
.wait_for_username
= true;
1161 SimulateOnFillPasswordForm(fill_data_
);
1163 // Neither field should have been autocompleted.
1164 CheckTextFieldsDOMState(std::string(), false, std::string(), false);
1166 // If the password field is not autocompletable, it should not be affected.
1167 SetElementReadOnly(password_element_
, true);
1168 EXPECT_FALSE(password_autofill_
->PreviewSuggestion(
1169 username_element_
, kAliceUsername
, kAlicePassword
));
1170 EXPECT_EQ(std::string(), username_element_
.suggestedValue().utf8());
1171 EXPECT_FALSE(username_element_
.isAutofilled());
1172 EXPECT_EQ(std::string(), password_element_
.suggestedValue().utf8());
1173 EXPECT_FALSE(password_element_
.isAutofilled());
1174 SetElementReadOnly(password_element_
, false);
1176 // After selecting the suggestion, both fields should be previewed
1177 // with suggested values.
1178 EXPECT_TRUE(password_autofill_
->PreviewSuggestion(
1179 username_element_
, kAliceUsername
, kAlicePassword
));
1182 static_cast<std::string
>(username_element_
.suggestedValue().utf8()));
1183 EXPECT_TRUE(username_element_
.isAutofilled());
1186 static_cast<std::string
>(password_element_
.suggestedValue().utf8()));
1187 EXPECT_TRUE(password_element_
.isAutofilled());
1188 int username_length
= strlen(kAliceUsername
);
1189 CheckUsernameSelection(0, username_length
);
1191 // Try previewing with a password different from the one that was initially
1192 // sent to the renderer.
1193 EXPECT_TRUE(password_autofill_
->PreviewSuggestion(
1194 username_element_
, kBobUsername
, kCarolPassword
));
1197 static_cast<std::string
>(username_element_
.suggestedValue().utf8()));
1198 EXPECT_TRUE(username_element_
.isAutofilled());
1201 static_cast<std::string
>(password_element_
.suggestedValue().utf8()));
1202 EXPECT_TRUE(password_element_
.isAutofilled());
1203 username_length
= strlen(kBobUsername
);
1204 CheckUsernameSelection(0, username_length
);
1207 // Tests that |PreviewSuggestion| properly sets the username selection range.
1208 TEST_F(PasswordAutofillAgentTest
, PreviewSuggestionSelectionRange
) {
1209 username_element_
.setValue(WebString::fromUTF8("ali"));
1210 username_element_
.setSelectionRange(3, 3);
1211 username_element_
.setAutofilled(true);
1213 CheckTextFieldsDOMState("ali", true, std::string(), false);
1215 // Simulate the browser sending the login info, but set |wait_for_username|
1216 // to prevent the form from being immediately filled.
1217 fill_data_
.wait_for_username
= true;
1218 SimulateOnFillPasswordForm(fill_data_
);
1220 EXPECT_TRUE(password_autofill_
->PreviewSuggestion(
1221 username_element_
, kAliceUsername
, kAlicePassword
));
1224 static_cast<std::string
>(username_element_
.suggestedValue().utf8()));
1225 EXPECT_TRUE(username_element_
.isAutofilled());
1228 static_cast<std::string
>(password_element_
.suggestedValue().utf8()));
1229 EXPECT_TRUE(password_element_
.isAutofilled());
1230 int username_length
= strlen(kAliceUsername
);
1231 CheckUsernameSelection(3, username_length
);
1234 // Tests that |ClearPreview| properly clears previewed username and password
1235 // with password being previously autofilled.
1236 TEST_F(PasswordAutofillAgentTest
, ClearPreviewWithPasswordAutofilled
) {
1237 password_element_
.setValue(WebString::fromUTF8("sec"));
1238 password_element_
.setAutofilled(true);
1240 // Simulate the browser sending the login info, but set |wait_for_username|
1241 // to prevent the form from being immediately filled.
1242 fill_data_
.wait_for_username
= true;
1243 SimulateOnFillPasswordForm(fill_data_
);
1245 CheckTextFieldsDOMState(std::string(), false, "sec", true);
1247 EXPECT_TRUE(password_autofill_
->PreviewSuggestion(
1248 username_element_
, kAliceUsername
, kAlicePassword
));
1250 EXPECT_TRUE(password_autofill_
->DidClearAutofillSelection(
1251 username_element_
));
1253 EXPECT_TRUE(username_element_
.value().isEmpty());
1254 EXPECT_TRUE(username_element_
.suggestedValue().isEmpty());
1255 EXPECT_FALSE(username_element_
.isAutofilled());
1256 EXPECT_EQ(ASCIIToUTF16("sec"), password_element_
.value());
1257 EXPECT_TRUE(password_element_
.suggestedValue().isEmpty());
1258 EXPECT_TRUE(password_element_
.isAutofilled());
1259 CheckUsernameSelection(0, 0);
1262 // Tests that |ClearPreview| properly clears previewed username and password
1263 // with username being previously autofilled.
1264 TEST_F(PasswordAutofillAgentTest
, ClearPreviewWithUsernameAutofilled
) {
1265 username_element_
.setValue(WebString::fromUTF8("ali"));
1266 username_element_
.setSelectionRange(3, 3);
1267 username_element_
.setAutofilled(true);
1269 // Simulate the browser sending the login info, but set |wait_for_username|
1270 // to prevent the form from being immediately filled.
1271 fill_data_
.wait_for_username
= true;
1272 SimulateOnFillPasswordForm(fill_data_
);
1274 CheckTextFieldsDOMState("ali", true, std::string(), false);
1276 EXPECT_TRUE(password_autofill_
->PreviewSuggestion(
1277 username_element_
, kAliceUsername
, kAlicePassword
));
1279 EXPECT_TRUE(password_autofill_
->DidClearAutofillSelection(
1280 username_element_
));
1282 EXPECT_EQ(ASCIIToUTF16("ali"), username_element_
.value());
1283 EXPECT_TRUE(username_element_
.suggestedValue().isEmpty());
1284 EXPECT_TRUE(username_element_
.isAutofilled());
1285 EXPECT_TRUE(password_element_
.value().isEmpty());
1286 EXPECT_TRUE(password_element_
.suggestedValue().isEmpty());
1287 EXPECT_FALSE(password_element_
.isAutofilled());
1288 CheckUsernameSelection(3, 3);
1291 // Tests that |ClearPreview| properly clears previewed username and password
1292 // with username and password being previously autofilled.
1293 TEST_F(PasswordAutofillAgentTest
,
1294 ClearPreviewWithAutofilledUsernameAndPassword
) {
1295 username_element_
.setValue(WebString::fromUTF8("ali"));
1296 username_element_
.setSelectionRange(3, 3);
1297 username_element_
.setAutofilled(true);
1298 password_element_
.setValue(WebString::fromUTF8("sec"));
1299 password_element_
.setAutofilled(true);
1301 // Simulate the browser sending the login info, but set |wait_for_username|
1302 // to prevent the form from being immediately filled.
1303 fill_data_
.wait_for_username
= true;
1304 SimulateOnFillPasswordForm(fill_data_
);
1306 CheckTextFieldsDOMState("ali", true, "sec", true);
1308 EXPECT_TRUE(password_autofill_
->PreviewSuggestion(
1309 username_element_
, kAliceUsername
, kAlicePassword
));
1311 EXPECT_TRUE(password_autofill_
->DidClearAutofillSelection(
1312 username_element_
));
1314 EXPECT_EQ(ASCIIToUTF16("ali"), username_element_
.value());
1315 EXPECT_TRUE(username_element_
.suggestedValue().isEmpty());
1316 EXPECT_TRUE(username_element_
.isAutofilled());
1317 EXPECT_EQ(ASCIIToUTF16("sec"), password_element_
.value());
1318 EXPECT_TRUE(password_element_
.suggestedValue().isEmpty());
1319 EXPECT_TRUE(password_element_
.isAutofilled());
1320 CheckUsernameSelection(3, 3);
1323 // Tests that |ClearPreview| properly clears previewed username and password
1324 // with neither username nor password being previously autofilled.
1325 TEST_F(PasswordAutofillAgentTest
,
1326 ClearPreviewWithNotAutofilledUsernameAndPassword
) {
1327 // Simulate the browser sending the login info, but set |wait_for_username|
1328 // to prevent the form from being immediately filled.
1329 fill_data_
.wait_for_username
= true;
1330 SimulateOnFillPasswordForm(fill_data_
);
1332 CheckTextFieldsDOMState(std::string(), false, std::string(), false);
1334 EXPECT_TRUE(password_autofill_
->PreviewSuggestion(
1335 username_element_
, kAliceUsername
, kAlicePassword
));
1337 EXPECT_TRUE(password_autofill_
->DidClearAutofillSelection(
1338 username_element_
));
1340 EXPECT_TRUE(username_element_
.value().isEmpty());
1341 EXPECT_TRUE(username_element_
.suggestedValue().isEmpty());
1342 EXPECT_FALSE(username_element_
.isAutofilled());
1343 EXPECT_TRUE(password_element_
.value().isEmpty());
1344 EXPECT_TRUE(password_element_
.suggestedValue().isEmpty());
1345 EXPECT_FALSE(password_element_
.isAutofilled());
1346 CheckUsernameSelection(0, 0);
1349 // Tests that |ClearPreview| properly restores the original selection range of
1350 // username field that has initially been filled by inline autocomplete.
1351 TEST_F(PasswordAutofillAgentTest
, ClearPreviewWithInlineAutocompletedUsername
) {
1352 // Simulate the browser sending back the login info.
1353 SimulateOnFillPasswordForm(fill_data_
);
1355 // Clear the text fields to start fresh.
1356 ClearUsernameAndPasswordFields();
1358 // Simulate the user typing in the first letter of 'alice', a stored username.
1359 SimulateUsernameChange("a", true);
1360 // Both the username and password text fields should reflect selection of the
1362 CheckTextFieldsState(kAliceUsername
, true, kAlicePassword
, true);
1363 // The selection should have been set to 'lice', the last 4 letters.
1364 CheckUsernameSelection(1, 5);
1366 EXPECT_TRUE(password_autofill_
->PreviewSuggestion(
1367 username_element_
, "alicia", "secret"));
1370 static_cast<std::string
>(username_element_
.suggestedValue().utf8()));
1371 EXPECT_TRUE(username_element_
.isAutofilled());
1374 static_cast<std::string
>(password_element_
.suggestedValue().utf8()));
1375 EXPECT_TRUE(password_element_
.isAutofilled());
1376 CheckUsernameSelection(1, 6);
1378 EXPECT_TRUE(password_autofill_
->DidClearAutofillSelection(
1379 username_element_
));
1381 EXPECT_EQ(kAliceUsername
, username_element_
.value().utf8());
1382 EXPECT_TRUE(username_element_
.suggestedValue().isEmpty());
1383 EXPECT_TRUE(username_element_
.isAutofilled());
1384 EXPECT_TRUE(password_element_
.value().isEmpty());
1385 EXPECT_TRUE(password_element_
.suggestedValue().isEmpty());
1386 EXPECT_TRUE(password_element_
.isAutofilled());
1387 CheckUsernameSelection(1, 5);
1390 // Tests that logging is off by default.
1391 TEST_F(PasswordAutofillAgentTest
, OnChangeLoggingState_NoMessage
) {
1392 render_thread_
->sink().ClearMessages();
1393 SendVisiblePasswordForms();
1394 const IPC::Message
* message
= render_thread_
->sink().GetFirstMessageMatching(
1395 AutofillHostMsg_RecordSavePasswordProgress::ID
);
1396 EXPECT_FALSE(message
);
1399 // Test that logging can be turned on by a message.
1400 TEST_F(PasswordAutofillAgentTest
, OnChangeLoggingState_Activated
) {
1401 // Turn the logging on.
1402 AutofillMsg_SetLoggingState
msg_activate(0, true);
1403 // Up-cast to access OnMessageReceived, which is private in the agent.
1404 EXPECT_TRUE(static_cast<IPC::Listener
*>(password_autofill_
)
1405 ->OnMessageReceived(msg_activate
));
1407 render_thread_
->sink().ClearMessages();
1408 SendVisiblePasswordForms();
1409 const IPC::Message
* message
= render_thread_
->sink().GetFirstMessageMatching(
1410 AutofillHostMsg_RecordSavePasswordProgress::ID
);
1411 EXPECT_TRUE(message
);
1414 // Test that logging can be turned off by a message.
1415 TEST_F(PasswordAutofillAgentTest
, OnChangeLoggingState_Deactivated
) {
1416 // Turn the logging on and then off.
1417 AutofillMsg_SetLoggingState
msg_activate(0, /*active=*/true);
1418 // Up-cast to access OnMessageReceived, which is private in the agent.
1419 EXPECT_TRUE(static_cast<IPC::Listener
*>(password_autofill_
)
1420 ->OnMessageReceived(msg_activate
));
1421 AutofillMsg_SetLoggingState
msg_deactivate(0, /*active=*/false);
1422 EXPECT_TRUE(static_cast<IPC::Listener
*>(password_autofill_
)
1423 ->OnMessageReceived(msg_deactivate
));
1425 render_thread_
->sink().ClearMessages();
1426 SendVisiblePasswordForms();
1427 const IPC::Message
* message
= render_thread_
->sink().GetFirstMessageMatching(
1428 AutofillHostMsg_RecordSavePasswordProgress::ID
);
1429 EXPECT_FALSE(message
);
1432 // Test that the agent sends an IPC call to get the current activity state of
1433 // password saving logging soon after construction.
1434 TEST_F(PasswordAutofillAgentTest
, SendsLoggingStateUpdatePingOnConstruction
) {
1435 const IPC::Message
* message
= render_thread_
->sink().GetFirstMessageMatching(
1436 AutofillHostMsg_PasswordAutofillAgentConstructed::ID
);
1437 EXPECT_TRUE(message
);
1440 // Tests that one user click on a username field is sufficient to bring up a
1441 // credential suggestion popup, and the user can autocomplete the password by
1442 // selecting the credential from the popup.
1443 TEST_F(PasswordAutofillAgentTest
, ClickAndSelect
) {
1444 // SimulateElementClick() is called so that a user gesture is actually made
1445 // and the password can be filled. However, SimulateElementClick() does not
1446 // actually lead to the AutofillAgent's InputElementClicked() method being
1447 // called, so SimulateSuggestionChoice has to manually call
1448 // InputElementClicked().
1449 ClearUsernameAndPasswordFields();
1450 SimulateOnFillPasswordForm(fill_data_
);
1451 SimulateElementClick(kUsernameName
);
1452 SimulateSuggestionChoice(username_element_
);
1453 ExpectAllCredentials();
1455 CheckTextFieldsDOMState(kAliceUsername
, true, kAlicePassword
, true);
1458 // Tests the autosuggestions that are given when the element is clicked.
1459 // Specifically, tests when the user clicks on the username element after page
1460 // load and the element is autofilled, when the user clicks on an element that
1461 // has a non-matching username, and when the user clicks on an element that's
1462 // already been autofilled and they've already modified.
1463 TEST_F(PasswordAutofillAgentTest
, CredentialsOnClick
) {
1464 // Simulate the browser sending back the login info.
1465 SimulateOnFillPasswordForm(fill_data_
);
1467 // Clear the text fields to start fresh.
1468 ClearUsernameAndPasswordFields();
1470 // Call SimulateElementClick() to produce a user gesture on the page so
1471 // autofill will actually fill.
1472 SimulateElementClick(kUsernameName
);
1474 // Simulate a user clicking on the username element. This should produce a
1475 // message with all the usernames.
1476 render_thread_
->sink().ClearMessages();
1477 autofill_agent_
->FormControlElementClicked(username_element_
, false);
1478 ExpectAllCredentials();
1480 // Now simulate a user typing in an unrecognized username and then
1481 // clicking on the username element. This should also produce a message with
1482 // all the usernames.
1483 SimulateUsernameChange("baz", true);
1484 render_thread_
->sink().ClearMessages();
1485 autofill_agent_
->FormControlElementClicked(username_element_
, true);
1486 ExpectAllCredentials();
1488 // Now simulate a user typing in the first letter of the username and then
1489 // clicking on the username element. While the typing of the first letter will
1490 // inline autocomplete, clicking on the element should still produce a full
1492 SimulateUsernameChange("a", true);
1493 render_thread_
->sink().ClearMessages();
1494 autofill_agent_
->FormControlElementClicked(username_element_
, true);
1495 ExpectAllCredentials();
1498 // The user types in a password, but then just before sending the form off, a
1499 // script clears that password. This test checks that PasswordAutofillAgent can
1500 // still remember the password typed by the user.
1501 TEST_F(PasswordAutofillAgentTest
,
1502 RememberLastNonEmptyPasswordOnSubmit_ScriptCleared
) {
1503 SimulateInputChangeForElement(
1504 "temp", true, GetMainFrame(), username_element_
, true);
1505 SimulateInputChangeForElement(
1506 "random", true, GetMainFrame(), password_element_
, true);
1508 // Simulate that the password value was cleared by the site's JavaScript
1510 password_element_
.setValue(WebString());
1511 static_cast<content::RenderViewObserver
*>(password_autofill_agent())
1512 ->WillSubmitForm(GetMainFrame(), username_element_
.form());
1514 // Observe that the PasswordAutofillAgent still remembered the last non-empty
1515 // password and sent that to the browser.
1516 ExpectFormSubmittedWithPasswords("random", "");
1519 // Similar to RememberLastNonEmptyPasswordOnSubmit_ScriptCleared, but this time
1520 // it's the user who clears the password. This test checks that in that case,
1521 // the last non-empty password is not remembered.
1522 TEST_F(PasswordAutofillAgentTest
,
1523 RememberLastNonEmptyPasswordOnSubmit_UserCleared
) {
1524 SimulateInputChangeForElement(
1525 "temp", true, GetMainFrame(), username_element_
, true);
1526 SimulateInputChangeForElement(
1527 "random", true, GetMainFrame(), password_element_
, true);
1529 // Simulate that the user actually cleared the password again.
1530 SimulateInputChangeForElement(
1531 "", true, GetMainFrame(), password_element_
, true);
1532 static_cast<content::RenderViewObserver
*>(password_autofill_agent())
1533 ->WillSubmitForm(GetMainFrame(), username_element_
.form());
1535 // Observe that the PasswordAutofillAgent respects the user having cleared the
1537 ExpectFormSubmittedWithPasswords("", "");
1540 // Similar to RememberLastNonEmptyPasswordOnSubmit_ScriptCleared, but uses the
1541 // new password instead of the current password.
1542 TEST_F(PasswordAutofillAgentTest
,
1543 RememberLastNonEmptyPasswordOnSubmit_NewPassword
) {
1544 const char kNewPasswordFormHTML
[] =
1545 "<FORM name='LoginTestForm'>"
1546 " <INPUT type='text' id='username' autocomplete='username'/>"
1547 " <INPUT type='password' id='password' autocomplete='new-password'/>"
1548 " <INPUT type='submit' value='Login'/>"
1550 LoadHTML(kNewPasswordFormHTML
);
1551 UpdateUsernameAndPasswordElements();
1553 SimulateInputChangeForElement(
1554 "temp", true, GetMainFrame(), username_element_
, true);
1555 SimulateInputChangeForElement(
1556 "random", true, GetMainFrame(), password_element_
, true);
1558 // Simulate that the password value was cleared by the site's JavaScript
1560 password_element_
.setValue(WebString());
1561 static_cast<content::RenderViewObserver
*>(password_autofill_agent())
1562 ->WillSubmitForm(GetMainFrame(), username_element_
.form());
1564 // Observe that the PasswordAutofillAgent still remembered the last non-empty
1565 // password and sent that to the browser.
1566 ExpectFormSubmittedWithPasswords("", "random");
1569 // The user first accepts a suggestion, but then overwrites the password. This
1570 // test checks that the overwritten password is not reverted back if the user
1571 // triggers autofill through focusing (but not changing) the username again.
1572 TEST_F(PasswordAutofillAgentTest
,
1573 NoopEditingDoesNotOverwriteManuallyEditedPassword
) {
1574 // Simulate having credentials which needed to wait until the user starts
1575 // typing the username to be filled (e.g., PSL-matched credentials). Those are
1576 // the ones which can be filled as a result of TextFieldDidEndEditing.
1577 fill_data_
.wait_for_username
= true;
1578 SimulateOnFillPasswordForm(fill_data_
);
1579 // Simulate that the user typed her name to make the autofill work.
1580 SimulateInputChangeForElement(kAliceUsername
,
1581 /*move_caret_to_end=*/true,
1584 /*is_user_input=*/true);
1585 SimulateDidEndEditing(GetMainFrame(), username_element_
);
1586 const std::string
old_username(username_element_
.value().utf8());
1587 const std::string
old_password(password_element_
.value().utf8());
1588 const std::string
new_password(old_password
+ "modify");
1590 // The user changes the password.
1591 SimulateInputChangeForElement(new_password
,
1592 /*move_caret_to_end=*/true,
1595 /*is_user_input=*/true);
1597 // The user switches back into the username field, but leaves that without
1599 SimulateDidEndEditing(GetMainFrame(), username_element_
);
1601 // The password should have stayed as the user changed it.
1602 CheckTextFieldsDOMState(old_username
, true, new_password
, false);
1603 // The password should not have a suggested value.
1604 CheckTextFieldsState(old_username
, true, std::string(), false);
1607 TEST_F(PasswordAutofillAgentTest
,
1608 InlineAutocompleteOverwritesManuallyEditedPassword
) {
1609 // Simulate the browser sending back the login info.
1610 SimulateOnFillPasswordForm(fill_data_
);
1612 ClearUsernameAndPasswordFields();
1614 // The user enters a password
1615 SimulateInputChangeForElement("someOtherPassword",
1616 /*move_caret_to_end=*/true,
1619 /*is_user_input=*/true);
1621 // Simulate the user typing a stored username.
1622 SimulateUsernameChange(kAliceUsername
, true);
1623 // The autofileld password should replace the typed one.
1624 CheckTextFieldsDOMState(kAliceUsername
, true, kAlicePassword
, true);
1627 } // namespace autofill