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 void SetUp() override
{
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 void TearDown() override
{
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 // Checks the message sent to PasswordAutofillManager to build the suggestion
421 // list. |username| is the expected username field value, and |show_all| is
422 // the expected flag for the PasswordAutofillManager, whether to show all
423 // suggestions, or only those starting with |username|.
424 void CheckSuggestions(const std::string
& username
, bool show_all
) {
425 const IPC::Message
* message
=
426 render_thread_
->sink().GetFirstMessageMatching(
427 AutofillHostMsg_ShowPasswordSuggestions::ID
);
428 EXPECT_TRUE(message
);
429 Tuple4
<autofill::FormFieldData
, base::string16
, bool, gfx::RectF
> args
;
430 AutofillHostMsg_ShowPasswordSuggestions::Read(message
, &args
);
431 EXPECT_EQ(2u, fill_data_
.basic_data
.fields
.size());
432 EXPECT_EQ(fill_data_
.basic_data
.fields
[0].name
, args
.a
.name
);
433 EXPECT_EQ(ASCIIToUTF16(username
), args
.a
.value
);
434 EXPECT_EQ(ASCIIToUTF16(username
), args
.b
);
435 EXPECT_EQ(show_all
, args
.c
);
437 render_thread_
->sink().ClearMessages();
440 void ExpectFormSubmittedWithPasswords(const std::string
& password_value
,
441 const std::string
& new_password_value
) {
442 const IPC::Message
* message
=
443 render_thread_
->sink().GetFirstMessageMatching(
444 AutofillHostMsg_PasswordFormSubmitted::ID
);
445 ASSERT_TRUE(message
);
446 Tuple1
<autofill::PasswordForm
> args
;
447 AutofillHostMsg_PasswordFormSubmitted::Read(message
, &args
);
448 EXPECT_EQ(ASCIIToUTF16(password_value
), args
.a
.password_value
);
449 EXPECT_EQ(ASCIIToUTF16(new_password_value
), args
.a
.new_password_value
);
452 base::string16 username1_
;
453 base::string16 username2_
;
454 base::string16 username3_
;
455 base::string16 password1_
;
456 base::string16 password2_
;
457 base::string16 password3_
;
458 base::string16 alternate_username3_
;
459 PasswordFormFillData fill_data_
;
461 WebInputElement username_element_
;
462 WebInputElement password_element_
;
465 DISALLOW_COPY_AND_ASSIGN(PasswordAutofillAgentTest
);
468 // Tests that the password login is autocompleted as expected when the browser
469 // sends back the password info.
470 TEST_F(PasswordAutofillAgentTest
, InitialAutocomplete
) {
472 * Right now we are not sending the message to the browser because we are
473 * loading a data URL and the security origin canAccessPasswordManager()
474 * returns false. May be we should mock URL loading to cirmcuvent this?
475 TODO(jcivelli): find a way to make the security origin not deny access to the
476 password manager and then reenable this code.
478 // The form has been loaded, we should have sent the browser a message about
480 const IPC::Message* msg = render_thread_.sink().GetFirstMessageMatching(
481 AutofillHostMsg_PasswordFormsParsed::ID);
482 ASSERT_TRUE(msg != NULL);
484 Tuple1<std::vector<PasswordForm> > forms;
485 AutofillHostMsg_PasswordFormsParsed::Read(msg, &forms);
486 ASSERT_EQ(1U, forms.a.size());
487 PasswordForm password_form = forms.a[0];
488 EXPECT_EQ(PasswordForm::SCHEME_HTML, password_form.scheme);
489 EXPECT_EQ(ASCIIToUTF16(kUsernameName), password_form.username_element);
490 EXPECT_EQ(ASCIIToUTF16(kPasswordName), password_form.password_element);
493 // Simulate the browser sending back the login info, it triggers the
495 SimulateOnFillPasswordForm(fill_data_
);
497 // The username and password should have been autocompleted.
498 CheckTextFieldsState(kAliceUsername
, true, kAlicePassword
, true);
501 // Tests that we correctly fill forms having an empty 'action' attribute.
502 TEST_F(PasswordAutofillAgentTest
, InitialAutocompleteForEmptyAction
) {
503 const char kEmptyActionFormHTML
[] =
504 "<FORM name='LoginTestForm'>"
505 " <INPUT type='text' id='username'/>"
506 " <INPUT type='password' id='password'/>"
507 " <INPUT type='submit' value='Login'/>"
509 LoadHTML(kEmptyActionFormHTML
);
511 // Retrieve the input elements so the test can access them.
512 WebDocument document
= GetMainFrame()->document();
514 document
.getElementById(WebString::fromUTF8(kUsernameName
));
515 ASSERT_FALSE(element
.isNull());
516 username_element_
= element
.to
<blink::WebInputElement
>();
517 element
= document
.getElementById(WebString::fromUTF8(kPasswordName
));
518 ASSERT_FALSE(element
.isNull());
519 password_element_
= element
.to
<blink::WebInputElement
>();
521 // Set the expected form origin and action URLs.
522 UpdateOriginForHTML(kEmptyActionFormHTML
);
523 fill_data_
.basic_data
.action
= fill_data_
.basic_data
.origin
;
525 // Simulate the browser sending back the login info, it triggers the
527 SimulateOnFillPasswordForm(fill_data_
);
529 // The username and password should have been autocompleted.
530 CheckTextFieldsState(kAliceUsername
, true, kAlicePassword
, true);
533 // Tests that if a password is marked as readonly, neither field is autofilled
535 TEST_F(PasswordAutofillAgentTest
, NoInitialAutocompleteForReadOnlyPassword
) {
536 SetElementReadOnly(password_element_
, true);
538 // Simulate the browser sending back the login info, it triggers the
540 SimulateOnFillPasswordForm(fill_data_
);
542 CheckTextFieldsState(std::string(), false, std::string(), false);
545 // Can still fill a password field if the username is set to a value that
547 TEST_F(PasswordAutofillAgentTest
,
548 AutocompletePasswordForReadonlyUsernameMatched
) {
549 username_element_
.setValue(username3_
);
550 SetElementReadOnly(username_element_
, true);
552 // Filled even though username is not the preferred match.
553 SimulateOnFillPasswordForm(fill_data_
);
554 CheckTextFieldsState(UTF16ToUTF8(username3_
), false,
555 UTF16ToUTF8(password3_
), true);
558 // If a username field is empty and readonly, don't autofill.
559 TEST_F(PasswordAutofillAgentTest
,
560 NoAutocompletePasswordForReadonlyUsernameUnmatched
) {
561 username_element_
.setValue(WebString::fromUTF8(""));
562 SetElementReadOnly(username_element_
, true);
564 SimulateOnFillPasswordForm(fill_data_
);
565 CheckTextFieldsState(std::string(), false, std::string(), false);
568 // Tests that having a non-matching username precludes the autocomplete.
569 TEST_F(PasswordAutofillAgentTest
, NoAutocompleteForFilledFieldUnmatched
) {
570 username_element_
.setValue(WebString::fromUTF8("bogus"));
572 // Simulate the browser sending back the login info, it triggers the
574 SimulateOnFillPasswordForm(fill_data_
);
576 // Neither field should be autocompleted.
577 CheckTextFieldsState("bogus", false, std::string(), false);
580 // Don't try to complete a prefilled value even if it's a partial match
582 TEST_F(PasswordAutofillAgentTest
, NoPartialMatchForPrefilledUsername
) {
583 username_element_
.setValue(WebString::fromUTF8("ali"));
585 SimulateOnFillPasswordForm(fill_data_
);
587 CheckTextFieldsState("ali", false, std::string(), false);
590 TEST_F(PasswordAutofillAgentTest
, InputWithNoForms
) {
591 const char kNoFormInputs
[] =
592 "<input type='text' id='username'/>"
593 "<input type='password' id='password'/>";
594 LoadHTML(kNoFormInputs
);
596 SimulateOnFillPasswordForm(fill_data_
);
598 // Input elements that aren't in a <form> won't autofill.
599 CheckTextFieldsState(std::string(), false, std::string(), false);
602 TEST_F(PasswordAutofillAgentTest
, NoAutocompleteForTextFieldPasswords
) {
603 const char kTextFieldPasswordFormHTML
[] =
604 "<FORM name='LoginTestForm' action='http://www.bidule.com'>"
605 " <INPUT type='text' id='username'/>"
606 " <INPUT type='text' id='password'/>"
607 " <INPUT type='submit' value='Login'/>"
609 LoadHTML(kTextFieldPasswordFormHTML
);
611 // Retrieve the input elements so the test can access them.
612 WebDocument document
= GetMainFrame()->document();
614 document
.getElementById(WebString::fromUTF8(kUsernameName
));
615 ASSERT_FALSE(element
.isNull());
616 username_element_
= element
.to
<blink::WebInputElement
>();
617 element
= document
.getElementById(WebString::fromUTF8(kPasswordName
));
618 ASSERT_FALSE(element
.isNull());
619 password_element_
= element
.to
<blink::WebInputElement
>();
621 // Set the expected form origin URL.
622 UpdateOriginForHTML(kTextFieldPasswordFormHTML
);
624 SimulateOnFillPasswordForm(fill_data_
);
626 // Fields should still be empty.
627 CheckTextFieldsState(std::string(), false, std::string(), false);
630 TEST_F(PasswordAutofillAgentTest
, NoAutocompleteForPasswordFieldUsernames
) {
631 const char kPasswordFieldUsernameFormHTML
[] =
632 "<FORM name='LoginTestForm' action='http://www.bidule.com'>"
633 " <INPUT type='password' id='username'/>"
634 " <INPUT type='password' id='password'/>"
635 " <INPUT type='submit' value='Login'/>"
637 LoadHTML(kPasswordFieldUsernameFormHTML
);
639 // Retrieve the input elements so the test can access them.
640 WebDocument document
= GetMainFrame()->document();
642 document
.getElementById(WebString::fromUTF8(kUsernameName
));
643 ASSERT_FALSE(element
.isNull());
644 username_element_
= element
.to
<blink::WebInputElement
>();
645 element
= document
.getElementById(WebString::fromUTF8(kPasswordName
));
646 ASSERT_FALSE(element
.isNull());
647 password_element_
= element
.to
<blink::WebInputElement
>();
649 // Set the expected form origin URL.
650 UpdateOriginForHTML(kPasswordFieldUsernameFormHTML
);
652 SimulateOnFillPasswordForm(fill_data_
);
654 // Fields should still be empty.
655 CheckTextFieldsState(std::string(), false, std::string(), false);
658 // Tests that having a matching username does not preclude the autocomplete.
659 TEST_F(PasswordAutofillAgentTest
, InitialAutocompleteForMatchingFilledField
) {
660 username_element_
.setValue(WebString::fromUTF8(kAliceUsername
));
662 // Simulate the browser sending back the login info, it triggers the
664 SimulateOnFillPasswordForm(fill_data_
);
666 // The username and password should have been autocompleted.
667 CheckTextFieldsState(kAliceUsername
, true, kAlicePassword
, true);
670 // Tests that editing the password clears the autocompleted password field.
671 TEST_F(PasswordAutofillAgentTest
, PasswordClearOnEdit
) {
672 // Simulate the browser sending back the login info, it triggers the
674 SimulateOnFillPasswordForm(fill_data_
);
676 // Simulate the user changing the username to some unknown username.
677 SimulateUsernameChange("alicia", true);
679 // The password should have been cleared.
680 CheckTextFieldsState("alicia", false, std::string(), false);
683 // Tests that we only autocomplete on focus lost and with a full username match
684 // when |wait_for_username| is true.
685 TEST_F(PasswordAutofillAgentTest
, WaitUsername
) {
686 // Simulate the browser sending back the login info.
687 fill_data_
.wait_for_username
= true;
688 SimulateOnFillPasswordForm(fill_data_
);
690 // No auto-fill should have taken place.
691 CheckTextFieldsState(std::string(), false, std::string(), false);
693 // No autocomplete should happen when text is entered in the username.
694 SimulateUsernameChange("a", true);
695 CheckTextFieldsState("a", false, std::string(), false);
696 SimulateUsernameChange("al", true);
697 CheckTextFieldsState("al", false, std::string(), false);
698 SimulateUsernameChange(kAliceUsername
, true);
699 CheckTextFieldsState(kAliceUsername
, false, std::string(), false);
701 // Autocomplete should happen only when the username textfield is blurred with
703 username_element_
.setValue("a");
704 static_cast<blink::WebAutofillClient
*>(autofill_agent_
)
705 ->textFieldDidEndEditing(username_element_
);
706 CheckTextFieldsState("a", false, std::string(), false);
707 username_element_
.setValue("al");
708 static_cast<blink::WebAutofillClient
*>(autofill_agent_
)
709 ->textFieldDidEndEditing(username_element_
);
710 CheckTextFieldsState("al", false, std::string(), false);
711 username_element_
.setValue("alices");
712 static_cast<blink::WebAutofillClient
*>(autofill_agent_
)
713 ->textFieldDidEndEditing(username_element_
);
714 CheckTextFieldsState("alices", false, std::string(), false);
715 username_element_
.setValue(ASCIIToUTF16(kAliceUsername
));
716 static_cast<blink::WebAutofillClient
*>(autofill_agent_
)
717 ->textFieldDidEndEditing(username_element_
);
718 CheckTextFieldsState(kAliceUsername
, true, kAlicePassword
, true);
721 // Tests that inline autocompletion works properly.
722 TEST_F(PasswordAutofillAgentTest
, InlineAutocomplete
) {
723 // Simulate the browser sending back the login info.
724 SimulateOnFillPasswordForm(fill_data_
);
726 ClearUsernameAndPasswordFields();
728 // Simulate the user typing in the first letter of 'alice', a stored
730 SimulateUsernameChange("a", true);
731 // Both the username and password text fields should reflect selection of the
733 CheckTextFieldsState(kAliceUsername
, true, kAlicePassword
, true);
734 // And the selection should have been set to 'lice', the last 4 letters.
735 CheckUsernameSelection(1, 5);
737 // Now the user types the next letter of the same username, 'l'.
738 SimulateUsernameChange("al", true);
739 // Now the fields should have the same value, but the selection should have a
740 // different start value.
741 CheckTextFieldsState(kAliceUsername
, true, kAlicePassword
, true);
742 CheckUsernameSelection(2, 5);
744 // Test that deleting does not trigger autocomplete.
745 SimulateKeyDownEvent(username_element_
, ui::VKEY_BACK
);
746 SimulateUsernameChange("alic", true);
747 CheckTextFieldsState("alic", false, std::string(), false);
748 CheckUsernameSelection(4, 4); // No selection.
749 // Reset the last pressed key to something other than backspace.
750 SimulateKeyDownEvent(username_element_
, ui::VKEY_A
);
752 // Now lets say the user goes astray from the stored username and types the
753 // letter 'f', spelling 'alf'. We don't know alf (that's just sad), so in
754 // practice the username should no longer be 'alice' and the selected range
756 SimulateUsernameChange("alf", true);
757 CheckTextFieldsState("alf", false, std::string(), false);
758 CheckUsernameSelection(3, 3); // No selection.
760 // Ok, so now the user removes all the text and enters the letter 'b'.
761 SimulateUsernameChange("b", true);
762 // The username and password fields should match the 'bob' entry.
763 CheckTextFieldsState(kBobUsername
, true, kBobPassword
, true);
764 CheckUsernameSelection(1, 3);
766 // Then, the user again removes all the text and types an uppercase 'C'.
767 SimulateUsernameChange("C", true);
768 // The username and password fields should match the 'Carol' entry.
769 CheckTextFieldsState(kCarolUsername
, true, kCarolPassword
, true);
770 CheckUsernameSelection(1, 5);
771 // The user removes all the text and types a lowercase 'c'. We only
772 // want case-sensitive autocompletion, so the username and the selected range
774 SimulateUsernameChange("c", true);
775 CheckTextFieldsState("c", false, std::string(), false);
776 CheckUsernameSelection(1, 1);
778 // Check that we complete other_possible_usernames as well.
779 SimulateUsernameChange("R", true);
780 CheckTextFieldsState(kCarolAlternateUsername
, true, kCarolPassword
, true);
781 CheckUsernameSelection(1, 17);
784 TEST_F(PasswordAutofillAgentTest
, IsWebNodeVisibleTest
) {
785 blink::WebVector
<blink::WebFormElement
> forms1
, forms2
, forms3
;
786 blink::WebFrame
* frame
;
788 LoadHTML(kVisibleFormHTML
);
789 frame
= GetMainFrame();
790 frame
->document().forms(forms1
);
791 ASSERT_EQ(1u, forms1
.size());
792 EXPECT_TRUE(IsWebNodeVisible(forms1
[0]));
794 LoadHTML(kEmptyFormHTML
);
795 frame
= GetMainFrame();
796 frame
->document().forms(forms2
);
797 ASSERT_EQ(1u, forms2
.size());
798 EXPECT_FALSE(IsWebNodeVisible(forms2
[0]));
800 LoadHTML(kNonVisibleFormHTML
);
801 frame
= GetMainFrame();
802 frame
->document().forms(forms3
);
803 ASSERT_EQ(1u, forms3
.size());
804 EXPECT_FALSE(IsWebNodeVisible(forms3
[0]));
807 TEST_F(PasswordAutofillAgentTest
, SendPasswordFormsTest
) {
808 render_thread_
->sink().ClearMessages();
809 LoadHTML(kVisibleFormHTML
);
810 const IPC::Message
* message
= render_thread_
->sink()
811 .GetFirstMessageMatching(AutofillHostMsg_PasswordFormsRendered::ID
);
812 EXPECT_TRUE(message
);
813 Tuple2
<std::vector
<autofill::PasswordForm
>, bool > param
;
814 AutofillHostMsg_PasswordFormsRendered::Read(message
, ¶m
);
815 EXPECT_TRUE(param
.a
.size());
817 render_thread_
->sink().ClearMessages();
818 LoadHTML(kEmptyFormHTML
);
819 message
= render_thread_
->sink().GetFirstMessageMatching(
820 AutofillHostMsg_PasswordFormsRendered::ID
);
821 EXPECT_TRUE(message
);
822 AutofillHostMsg_PasswordFormsRendered::Read(message
, ¶m
);
823 EXPECT_FALSE(param
.a
.size());
825 render_thread_
->sink().ClearMessages();
826 LoadHTML(kNonVisibleFormHTML
);
827 message
= render_thread_
->sink().GetFirstMessageMatching(
828 AutofillHostMsg_PasswordFormsRendered::ID
);
829 EXPECT_TRUE(message
);
830 AutofillHostMsg_PasswordFormsRendered::Read(message
, ¶m
);
831 EXPECT_FALSE(param
.a
.size());
834 TEST_F(PasswordAutofillAgentTest
, SendPasswordFormsTest_Redirection
) {
835 render_thread_
->sink().ClearMessages();
836 LoadHTML(kEmptyWebpage
);
837 EXPECT_FALSE(render_thread_
->sink().GetFirstMessageMatching(
838 AutofillHostMsg_PasswordFormsRendered::ID
));
840 render_thread_
->sink().ClearMessages();
841 LoadHTML(kRedirectionWebpage
);
842 EXPECT_FALSE(render_thread_
->sink().GetFirstMessageMatching(
843 AutofillHostMsg_PasswordFormsRendered::ID
));
845 render_thread_
->sink().ClearMessages();
846 LoadHTML(kSimpleWebpage
);
847 EXPECT_TRUE(render_thread_
->sink().GetFirstMessageMatching(
848 AutofillHostMsg_PasswordFormsRendered::ID
));
850 render_thread_
->sink().ClearMessages();
851 LoadHTML(kWebpageWithDynamicContent
);
852 EXPECT_TRUE(render_thread_
->sink().GetFirstMessageMatching(
853 AutofillHostMsg_PasswordFormsRendered::ID
));
856 // Tests that a password form in an iframe will not be filled in until a user
857 // interaction with the form.
858 TEST_F(PasswordAutofillAgentTest
, IframeNoFillTest
) {
859 const char kIframeName
[] = "iframe";
860 const char kWebpageWithIframeStart
[] =
863 " <meta charset='utf-8' />"
864 " <title>Title</title>"
867 " <iframe name='iframe' src=\"";
868 const char kWebpageWithIframeEnd
[] =
873 std::string
origin("data:text/html;charset=utf-8,");
874 origin
+= kSimpleWebpage
;
876 std::string
page_html(kWebpageWithIframeStart
);
878 page_html
+= kWebpageWithIframeEnd
;
880 LoadHTML(page_html
.c_str());
882 // Set the expected form origin and action URLs.
883 fill_data_
.basic_data
.origin
= GURL(origin
);
884 fill_data_
.basic_data
.action
= GURL(origin
);
886 SimulateOnFillPasswordForm(fill_data_
);
888 // Retrieve the input elements from the iframe since that is where we want to
889 // test the autofill.
890 WebFrame
* iframe
= GetMainFrame()->findChildByName(kIframeName
);
892 WebDocument document
= iframe
->document();
894 WebElement username_element
= document
.getElementById(kUsernameName
);
895 WebElement password_element
= document
.getElementById(kPasswordName
);
896 ASSERT_FALSE(username_element
.isNull());
897 ASSERT_FALSE(password_element
.isNull());
899 WebInputElement username_input
= username_element
.to
<WebInputElement
>();
900 WebInputElement password_input
= password_element
.to
<WebInputElement
>();
901 ASSERT_FALSE(username_element
.isNull());
903 CheckTextFieldsStateForElements(
904 username_input
, "", false, password_input
, "", false, false);
906 // Simulate the user typing in the username in the iframe which should cause
908 SimulateInputChangeForElement(
909 kAliceUsername
, true, iframe
, username_input
, true);
911 CheckTextFieldsStateForElements(username_input
,
920 // Tests that a password will only be filled as a suggested and will not be
921 // accessible by the DOM until a user gesture has occurred.
922 TEST_F(PasswordAutofillAgentTest
, GestureRequiredTest
) {
923 // Trigger the initial autocomplete.
924 SimulateOnFillPasswordForm(fill_data_
);
926 // The username and password should have been autocompleted.
927 CheckTextFieldsState(kAliceUsername
, true, kAlicePassword
, true);
929 // However, it should only have completed with the suggested value, as tested
930 // above, and it should not have completed into the DOM accessible value for
931 // the password field.
932 CheckTextFieldsDOMState(kAliceUsername
, true, std::string(), true);
934 // Simulate a user click so that the password field's real value is filled.
935 SimulateElementClick(kUsernameName
);
936 CheckTextFieldsDOMState(kAliceUsername
, true, kAlicePassword
, true);
939 // Verfies that a DOM-activated UI event will not cause an autofill.
940 TEST_F(PasswordAutofillAgentTest
, NoDOMActivationTest
) {
941 // Trigger the initial autocomplete.
942 SimulateOnFillPasswordForm(fill_data_
);
944 ExecuteJavaScript(kJavaScriptClick
);
945 CheckTextFieldsDOMState(kAliceUsername
, true, "", true);
948 // Regression test for http://crbug.com/326679
949 TEST_F(PasswordAutofillAgentTest
, SelectUsernameWithUsernameAutofillOff
) {
950 // Simulate the browser sending back the login info.
951 SimulateOnFillPasswordForm(fill_data_
);
953 // Set the username element to autocomplete='off'
954 username_element_
.setAttribute(WebString::fromUTF8("autocomplete"),
955 WebString::fromUTF8("off"));
957 // Simulate the user changing the username to some known username.
958 SimulateUsernameChange(kAliceUsername
, true);
960 ExpectNoSuggestionsPopup();
963 // Regression test for http://crbug.com/326679
964 TEST_F(PasswordAutofillAgentTest
,
965 SelectUnknownUsernameWithUsernameAutofillOff
) {
966 // Simulate the browser sending back the login info.
967 SimulateOnFillPasswordForm(fill_data_
);
969 // Set the username element to autocomplete='off'
970 username_element_
.setAttribute(WebString::fromUTF8("autocomplete"),
971 WebString::fromUTF8("off"));
973 // Simulate the user changing the username to some unknown username.
974 SimulateUsernameChange("foo", true);
976 ExpectNoSuggestionsPopup();
979 // Regression test for http://crbug.com/326679
980 TEST_F(PasswordAutofillAgentTest
, SelectUsernameWithPasswordAutofillOff
) {
981 // Simulate the browser sending back the login info.
982 SimulateOnFillPasswordForm(fill_data_
);
984 // Set the main password element to autocomplete='off'
985 password_element_
.setAttribute(WebString::fromUTF8("autocomplete"),
986 WebString::fromUTF8("off"));
988 // Simulate the user changing the username to some known username.
989 SimulateUsernameChange(kAliceUsername
, true);
991 ExpectNoSuggestionsPopup();
994 // Regression test for http://crbug.com/326679
995 TEST_F(PasswordAutofillAgentTest
,
996 SelectUnknownUsernameWithPasswordAutofillOff
) {
997 // Simulate the browser sending back the login info.
998 SimulateOnFillPasswordForm(fill_data_
);
1000 // Set the main password element to autocomplete='off'
1001 password_element_
.setAttribute(WebString::fromUTF8("autocomplete"),
1002 WebString::fromUTF8("off"));
1004 // Simulate the user changing the username to some unknown username.
1005 SimulateUsernameChange("foo", true);
1007 ExpectNoSuggestionsPopup();
1010 // Verifies that password autofill triggers onChange events in JavaScript for
1011 // forms that are filled on page load.
1012 TEST_F(PasswordAutofillAgentTest
,
1013 PasswordAutofillTriggersOnChangeEventsOnLoad
) {
1014 std::string html
= std::string(kFormHTML
) + kOnChangeDetectionScript
;
1015 LoadHTML(html
.c_str());
1016 UpdateOriginForHTML(html
);
1017 UpdateUsernameAndPasswordElements();
1019 // Simulate the browser sending back the login info, it triggers the
1021 SimulateOnFillPasswordForm(fill_data_
);
1023 // The username and password should have been autocompleted...
1024 CheckTextFieldsState(kAliceUsername
, true, kAlicePassword
, true);
1025 // ... but since there hasn't been a user gesture yet, the autocompleted
1026 // password should only be visible to the user.
1027 CheckTextFieldsDOMState(kAliceUsername
, true, std::string(), true);
1029 // A JavaScript onChange event should have been triggered for the username,
1030 // but not yet for the password.
1031 int username_onchange_called
= -1;
1032 int password_onchange_called
= -1;
1034 ExecuteJavaScriptAndReturnIntValue(
1035 ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"),
1036 &username_onchange_called
));
1037 EXPECT_EQ(1, username_onchange_called
);
1039 ExecuteJavaScriptAndReturnIntValue(
1040 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"),
1041 &password_onchange_called
));
1042 // TODO(isherman): Re-enable this check once http://crbug.com/333144 is fixed.
1043 // EXPECT_EQ(0, password_onchange_called);
1045 // Simulate a user click so that the password field's real value is filled.
1046 SimulateElementClick(kUsernameName
);
1047 CheckTextFieldsDOMState(kAliceUsername
, true, kAlicePassword
, true);
1049 // Now, a JavaScript onChange event should have been triggered for the
1050 // password as well.
1052 ExecuteJavaScriptAndReturnIntValue(
1053 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"),
1054 &password_onchange_called
));
1055 EXPECT_EQ(1, password_onchange_called
);
1058 // Verifies that password autofill triggers onChange events in JavaScript for
1059 // forms that are filled after page load.
1060 TEST_F(PasswordAutofillAgentTest
,
1061 PasswordAutofillTriggersOnChangeEventsWaitForUsername
) {
1062 std::string html
= std::string(kFormHTML
) + kOnChangeDetectionScript
;
1063 LoadHTML(html
.c_str());
1064 UpdateOriginForHTML(html
);
1065 UpdateUsernameAndPasswordElements();
1067 // Simulate the browser sending back the login info, it triggers the
1069 fill_data_
.wait_for_username
= true;
1070 SimulateOnFillPasswordForm(fill_data_
);
1072 // The username and password should not yet have been autocompleted.
1073 CheckTextFieldsState(std::string(), false, std::string(), false);
1075 // Simulate a click just to force a user gesture, since the username value is
1077 SimulateElementClick(kUsernameName
);
1079 // Simulate the user entering her username and selecting the matching autofill
1080 // from the dropdown.
1081 SimulateUsernameChange(kAliceUsername
, true, true);
1082 SimulateSuggestionChoice(username_element_
);
1084 // The username and password should now have been autocompleted.
1085 CheckTextFieldsDOMState(kAliceUsername
, true, kAlicePassword
, true);
1087 // JavaScript onChange events should have been triggered both for the username
1088 // and for the password.
1089 int username_onchange_called
= -1;
1090 int password_onchange_called
= -1;
1092 ExecuteJavaScriptAndReturnIntValue(
1093 ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"),
1094 &username_onchange_called
));
1095 EXPECT_EQ(1, username_onchange_called
);
1097 ExecuteJavaScriptAndReturnIntValue(
1098 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"),
1099 &password_onchange_called
));
1100 EXPECT_EQ(1, password_onchange_called
);
1103 // Tests that |FillSuggestion| properly fills the username and password.
1104 TEST_F(PasswordAutofillAgentTest
, FillSuggestion
) {
1105 // Simulate the browser sending the login info, but set |wait_for_username|
1106 // to prevent the form from being immediately filled.
1107 fill_data_
.wait_for_username
= true;
1108 SimulateOnFillPasswordForm(fill_data_
);
1110 // Neither field should have been autocompleted.
1111 CheckTextFieldsDOMState(std::string(), false, std::string(), false);
1113 // If the password field is not autocompletable, it should not be affected.
1114 SetElementReadOnly(password_element_
, true);
1115 EXPECT_FALSE(password_autofill_agent_
->FillSuggestion(
1116 username_element_
, kAliceUsername
, kAlicePassword
));
1117 CheckTextFieldsDOMState(std::string(), false, std::string(), false);
1118 SetElementReadOnly(password_element_
, false);
1120 // After filling with the suggestion, both fields should be autocompleted.
1121 EXPECT_TRUE(password_autofill_agent_
->FillSuggestion(
1122 username_element_
, kAliceUsername
, kAlicePassword
));
1123 CheckTextFieldsDOMState(kAliceUsername
, true, kAlicePassword
, true);
1124 int username_length
= strlen(kAliceUsername
);
1125 CheckUsernameSelection(username_length
, username_length
);
1127 // Try Filling with a suggestion with password different from the one that was
1128 // initially sent to the renderer.
1129 EXPECT_TRUE(password_autofill_agent_
->FillSuggestion(
1130 username_element_
, kBobUsername
, kCarolPassword
));
1131 CheckTextFieldsDOMState(kBobUsername
, true, kCarolPassword
, true);
1132 username_length
= strlen(kBobUsername
);
1133 CheckUsernameSelection(username_length
, username_length
);
1136 // Tests that |PreviewSuggestion| properly previews the username and password.
1137 TEST_F(PasswordAutofillAgentTest
, PreviewSuggestion
) {
1138 // Simulate the browser sending the login info, but set |wait_for_username|
1139 // to prevent the form from being immediately filled.
1140 fill_data_
.wait_for_username
= true;
1141 SimulateOnFillPasswordForm(fill_data_
);
1143 // Neither field should have been autocompleted.
1144 CheckTextFieldsDOMState(std::string(), false, std::string(), false);
1146 // If the password field is not autocompletable, it should not be affected.
1147 SetElementReadOnly(password_element_
, true);
1148 EXPECT_FALSE(password_autofill_agent_
->PreviewSuggestion(
1149 username_element_
, kAliceUsername
, kAlicePassword
));
1150 EXPECT_EQ(std::string(), username_element_
.suggestedValue().utf8());
1151 EXPECT_FALSE(username_element_
.isAutofilled());
1152 EXPECT_EQ(std::string(), password_element_
.suggestedValue().utf8());
1153 EXPECT_FALSE(password_element_
.isAutofilled());
1154 SetElementReadOnly(password_element_
, false);
1156 // After selecting the suggestion, both fields should be previewed
1157 // with suggested values.
1158 EXPECT_TRUE(password_autofill_agent_
->PreviewSuggestion(
1159 username_element_
, kAliceUsername
, kAlicePassword
));
1162 static_cast<std::string
>(username_element_
.suggestedValue().utf8()));
1163 EXPECT_TRUE(username_element_
.isAutofilled());
1166 static_cast<std::string
>(password_element_
.suggestedValue().utf8()));
1167 EXPECT_TRUE(password_element_
.isAutofilled());
1168 int username_length
= strlen(kAliceUsername
);
1169 CheckUsernameSelection(0, username_length
);
1171 // Try previewing with a password different from the one that was initially
1172 // sent to the renderer.
1173 EXPECT_TRUE(password_autofill_agent_
->PreviewSuggestion(
1174 username_element_
, kBobUsername
, kCarolPassword
));
1177 static_cast<std::string
>(username_element_
.suggestedValue().utf8()));
1178 EXPECT_TRUE(username_element_
.isAutofilled());
1181 static_cast<std::string
>(password_element_
.suggestedValue().utf8()));
1182 EXPECT_TRUE(password_element_
.isAutofilled());
1183 username_length
= strlen(kBobUsername
);
1184 CheckUsernameSelection(0, username_length
);
1187 // Tests that |PreviewSuggestion| properly sets the username selection range.
1188 TEST_F(PasswordAutofillAgentTest
, PreviewSuggestionSelectionRange
) {
1189 username_element_
.setValue(WebString::fromUTF8("ali"));
1190 username_element_
.setSelectionRange(3, 3);
1191 username_element_
.setAutofilled(true);
1193 CheckTextFieldsDOMState("ali", true, std::string(), false);
1195 // Simulate the browser sending the login info, but set |wait_for_username|
1196 // to prevent the form from being immediately filled.
1197 fill_data_
.wait_for_username
= true;
1198 SimulateOnFillPasswordForm(fill_data_
);
1200 EXPECT_TRUE(password_autofill_agent_
->PreviewSuggestion(
1201 username_element_
, kAliceUsername
, kAlicePassword
));
1204 static_cast<std::string
>(username_element_
.suggestedValue().utf8()));
1205 EXPECT_TRUE(username_element_
.isAutofilled());
1208 static_cast<std::string
>(password_element_
.suggestedValue().utf8()));
1209 EXPECT_TRUE(password_element_
.isAutofilled());
1210 int username_length
= strlen(kAliceUsername
);
1211 CheckUsernameSelection(3, username_length
);
1214 // Tests that |ClearPreview| properly clears previewed username and password
1215 // with password being previously autofilled.
1216 TEST_F(PasswordAutofillAgentTest
, ClearPreviewWithPasswordAutofilled
) {
1217 password_element_
.setValue(WebString::fromUTF8("sec"));
1218 password_element_
.setAutofilled(true);
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 CheckTextFieldsDOMState(std::string(), false, "sec", true);
1227 EXPECT_TRUE(password_autofill_agent_
->PreviewSuggestion(
1228 username_element_
, kAliceUsername
, kAlicePassword
));
1231 password_autofill_agent_
->DidClearAutofillSelection(username_element_
));
1233 EXPECT_TRUE(username_element_
.value().isEmpty());
1234 EXPECT_TRUE(username_element_
.suggestedValue().isEmpty());
1235 EXPECT_FALSE(username_element_
.isAutofilled());
1236 EXPECT_EQ(ASCIIToUTF16("sec"), password_element_
.value());
1237 EXPECT_TRUE(password_element_
.suggestedValue().isEmpty());
1238 EXPECT_TRUE(password_element_
.isAutofilled());
1239 CheckUsernameSelection(0, 0);
1242 // Tests that |ClearPreview| properly clears previewed username and password
1243 // with username being previously autofilled.
1244 TEST_F(PasswordAutofillAgentTest
, ClearPreviewWithUsernameAutofilled
) {
1245 username_element_
.setValue(WebString::fromUTF8("ali"));
1246 username_element_
.setSelectionRange(3, 3);
1247 username_element_
.setAutofilled(true);
1249 // Simulate the browser sending the login info, but set |wait_for_username|
1250 // to prevent the form from being immediately filled.
1251 fill_data_
.wait_for_username
= true;
1252 SimulateOnFillPasswordForm(fill_data_
);
1254 CheckTextFieldsDOMState("ali", true, std::string(), false);
1256 EXPECT_TRUE(password_autofill_agent_
->PreviewSuggestion(
1257 username_element_
, kAliceUsername
, kAlicePassword
));
1260 password_autofill_agent_
->DidClearAutofillSelection(username_element_
));
1262 EXPECT_EQ(ASCIIToUTF16("ali"), username_element_
.value());
1263 EXPECT_TRUE(username_element_
.suggestedValue().isEmpty());
1264 EXPECT_TRUE(username_element_
.isAutofilled());
1265 EXPECT_TRUE(password_element_
.value().isEmpty());
1266 EXPECT_TRUE(password_element_
.suggestedValue().isEmpty());
1267 EXPECT_FALSE(password_element_
.isAutofilled());
1268 CheckUsernameSelection(3, 3);
1271 // Tests that |ClearPreview| properly clears previewed username and password
1272 // with username and password being previously autofilled.
1273 TEST_F(PasswordAutofillAgentTest
,
1274 ClearPreviewWithAutofilledUsernameAndPassword
) {
1275 username_element_
.setValue(WebString::fromUTF8("ali"));
1276 username_element_
.setSelectionRange(3, 3);
1277 username_element_
.setAutofilled(true);
1278 password_element_
.setValue(WebString::fromUTF8("sec"));
1279 password_element_
.setAutofilled(true);
1281 // Simulate the browser sending the login info, but set |wait_for_username|
1282 // to prevent the form from being immediately filled.
1283 fill_data_
.wait_for_username
= true;
1284 SimulateOnFillPasswordForm(fill_data_
);
1286 CheckTextFieldsDOMState("ali", true, "sec", true);
1288 EXPECT_TRUE(password_autofill_agent_
->PreviewSuggestion(
1289 username_element_
, kAliceUsername
, kAlicePassword
));
1292 password_autofill_agent_
->DidClearAutofillSelection(username_element_
));
1294 EXPECT_EQ(ASCIIToUTF16("ali"), username_element_
.value());
1295 EXPECT_TRUE(username_element_
.suggestedValue().isEmpty());
1296 EXPECT_TRUE(username_element_
.isAutofilled());
1297 EXPECT_EQ(ASCIIToUTF16("sec"), password_element_
.value());
1298 EXPECT_TRUE(password_element_
.suggestedValue().isEmpty());
1299 EXPECT_TRUE(password_element_
.isAutofilled());
1300 CheckUsernameSelection(3, 3);
1303 // Tests that |ClearPreview| properly clears previewed username and password
1304 // with neither username nor password being previously autofilled.
1305 TEST_F(PasswordAutofillAgentTest
,
1306 ClearPreviewWithNotAutofilledUsernameAndPassword
) {
1307 // Simulate the browser sending the login info, but set |wait_for_username|
1308 // to prevent the form from being immediately filled.
1309 fill_data_
.wait_for_username
= true;
1310 SimulateOnFillPasswordForm(fill_data_
);
1312 CheckTextFieldsDOMState(std::string(), false, std::string(), false);
1314 EXPECT_TRUE(password_autofill_agent_
->PreviewSuggestion(
1315 username_element_
, kAliceUsername
, kAlicePassword
));
1318 password_autofill_agent_
->DidClearAutofillSelection(username_element_
));
1320 EXPECT_TRUE(username_element_
.value().isEmpty());
1321 EXPECT_TRUE(username_element_
.suggestedValue().isEmpty());
1322 EXPECT_FALSE(username_element_
.isAutofilled());
1323 EXPECT_TRUE(password_element_
.value().isEmpty());
1324 EXPECT_TRUE(password_element_
.suggestedValue().isEmpty());
1325 EXPECT_FALSE(password_element_
.isAutofilled());
1326 CheckUsernameSelection(0, 0);
1329 // Tests that |ClearPreview| properly restores the original selection range of
1330 // username field that has initially been filled by inline autocomplete.
1331 TEST_F(PasswordAutofillAgentTest
, ClearPreviewWithInlineAutocompletedUsername
) {
1332 // Simulate the browser sending back the login info.
1333 SimulateOnFillPasswordForm(fill_data_
);
1335 // Clear the text fields to start fresh.
1336 ClearUsernameAndPasswordFields();
1338 // Simulate the user typing in the first letter of 'alice', a stored username.
1339 SimulateUsernameChange("a", true);
1340 // Both the username and password text fields should reflect selection of the
1342 CheckTextFieldsState(kAliceUsername
, true, kAlicePassword
, true);
1343 // The selection should have been set to 'lice', the last 4 letters.
1344 CheckUsernameSelection(1, 5);
1346 EXPECT_TRUE(password_autofill_agent_
->PreviewSuggestion(
1347 username_element_
, "alicia", "secret"));
1350 static_cast<std::string
>(username_element_
.suggestedValue().utf8()));
1351 EXPECT_TRUE(username_element_
.isAutofilled());
1354 static_cast<std::string
>(password_element_
.suggestedValue().utf8()));
1355 EXPECT_TRUE(password_element_
.isAutofilled());
1356 CheckUsernameSelection(1, 6);
1359 password_autofill_agent_
->DidClearAutofillSelection(username_element_
));
1361 EXPECT_EQ(kAliceUsername
, username_element_
.value().utf8());
1362 EXPECT_TRUE(username_element_
.suggestedValue().isEmpty());
1363 EXPECT_TRUE(username_element_
.isAutofilled());
1364 EXPECT_TRUE(password_element_
.value().isEmpty());
1365 EXPECT_TRUE(password_element_
.suggestedValue().isEmpty());
1366 EXPECT_TRUE(password_element_
.isAutofilled());
1367 CheckUsernameSelection(1, 5);
1370 // Tests that logging is off by default.
1371 TEST_F(PasswordAutofillAgentTest
, OnChangeLoggingState_NoMessage
) {
1372 render_thread_
->sink().ClearMessages();
1373 SendVisiblePasswordForms();
1374 const IPC::Message
* message
= render_thread_
->sink().GetFirstMessageMatching(
1375 AutofillHostMsg_RecordSavePasswordProgress::ID
);
1376 EXPECT_FALSE(message
);
1379 // Test that logging can be turned on by a message.
1380 TEST_F(PasswordAutofillAgentTest
, OnChangeLoggingState_Activated
) {
1381 // Turn the logging on.
1382 AutofillMsg_SetLoggingState
msg_activate(0, true);
1383 // Up-cast to access OnMessageReceived, which is private in the agent.
1384 EXPECT_TRUE(static_cast<IPC::Listener
*>(password_autofill_agent_
)
1385 ->OnMessageReceived(msg_activate
));
1387 render_thread_
->sink().ClearMessages();
1388 SendVisiblePasswordForms();
1389 const IPC::Message
* message
= render_thread_
->sink().GetFirstMessageMatching(
1390 AutofillHostMsg_RecordSavePasswordProgress::ID
);
1391 EXPECT_TRUE(message
);
1394 // Test that logging can be turned off by a message.
1395 TEST_F(PasswordAutofillAgentTest
, OnChangeLoggingState_Deactivated
) {
1396 // Turn the logging on and then off.
1397 AutofillMsg_SetLoggingState
msg_activate(0, /*active=*/true);
1398 // Up-cast to access OnMessageReceived, which is private in the agent.
1399 EXPECT_TRUE(static_cast<IPC::Listener
*>(password_autofill_agent_
)
1400 ->OnMessageReceived(msg_activate
));
1401 AutofillMsg_SetLoggingState
msg_deactivate(0, /*active=*/false);
1402 EXPECT_TRUE(static_cast<IPC::Listener
*>(password_autofill_agent_
)
1403 ->OnMessageReceived(msg_deactivate
));
1405 render_thread_
->sink().ClearMessages();
1406 SendVisiblePasswordForms();
1407 const IPC::Message
* message
= render_thread_
->sink().GetFirstMessageMatching(
1408 AutofillHostMsg_RecordSavePasswordProgress::ID
);
1409 EXPECT_FALSE(message
);
1412 // Test that the agent sends an IPC call to get the current activity state of
1413 // password saving logging soon after construction.
1414 TEST_F(PasswordAutofillAgentTest
, SendsLoggingStateUpdatePingOnConstruction
) {
1415 const IPC::Message
* message
= render_thread_
->sink().GetFirstMessageMatching(
1416 AutofillHostMsg_PasswordAutofillAgentConstructed::ID
);
1417 EXPECT_TRUE(message
);
1420 // Tests that one user click on a username field is sufficient to bring up a
1421 // credential suggestion popup, and the user can autocomplete the password by
1422 // selecting the credential from the popup.
1423 TEST_F(PasswordAutofillAgentTest
, ClickAndSelect
) {
1424 // SimulateElementClick() is called so that a user gesture is actually made
1425 // and the password can be filled. However, SimulateElementClick() does not
1426 // actually lead to the AutofillAgent's InputElementClicked() method being
1427 // called, so SimulateSuggestionChoice has to manually call
1428 // InputElementClicked().
1429 ClearUsernameAndPasswordFields();
1430 SimulateOnFillPasswordForm(fill_data_
);
1431 SimulateElementClick(kUsernameName
);
1432 SimulateSuggestionChoice(username_element_
);
1433 CheckSuggestions(kAliceUsername
, true);
1435 CheckTextFieldsDOMState(kAliceUsername
, true, kAlicePassword
, true);
1438 // Tests the autosuggestions that are given when the element is clicked.
1439 // Specifically, tests when the user clicks on the username element after page
1440 // load and the element is autofilled, when the user clicks on an element that
1441 // has a non-matching username, and when the user clicks on an element that's
1442 // already been autofilled and they've already modified.
1443 TEST_F(PasswordAutofillAgentTest
, CredentialsOnClick
) {
1444 // Simulate the browser sending back the login info.
1445 SimulateOnFillPasswordForm(fill_data_
);
1447 // Clear the text fields to start fresh.
1448 ClearUsernameAndPasswordFields();
1450 // Call SimulateElementClick() to produce a user gesture on the page so
1451 // autofill will actually fill.
1452 SimulateElementClick(kUsernameName
);
1454 // Simulate a user clicking on the username element. This should produce a
1455 // message with all the usernames.
1456 render_thread_
->sink().ClearMessages();
1457 static_cast<PageClickListener
*>(autofill_agent_
)
1458 ->FormControlElementClicked(username_element_
, false);
1459 CheckSuggestions(std::string(), false);
1461 // Now simulate a user typing in an unrecognized username and then
1462 // clicking on the username element. This should also produce a message with
1463 // all the usernames.
1464 SimulateUsernameChange("baz", true);
1465 render_thread_
->sink().ClearMessages();
1466 static_cast<PageClickListener
*>(autofill_agent_
)
1467 ->FormControlElementClicked(username_element_
, true);
1468 CheckSuggestions("baz", true);
1470 // Now simulate a user typing in the first letter of the username and then
1471 // clicking on the username element. While the typing of the first letter will
1472 // inline autocomplete, clicking on the element should still produce a full
1474 SimulateUsernameChange("a", true);
1475 render_thread_
->sink().ClearMessages();
1476 static_cast<PageClickListener
*>(autofill_agent_
)
1477 ->FormControlElementClicked(username_element_
, true);
1478 CheckSuggestions(kAliceUsername
, true);
1481 // The user types in a password, but then just before sending the form off, a
1482 // script clears that password. This test checks that PasswordAutofillAgent can
1483 // still remember the password typed by the user.
1484 TEST_F(PasswordAutofillAgentTest
,
1485 RememberLastNonEmptyPasswordOnSubmit_ScriptCleared
) {
1486 SimulateInputChangeForElement(
1487 "temp", true, GetMainFrame(), username_element_
, true);
1488 SimulateInputChangeForElement(
1489 "random", true, GetMainFrame(), password_element_
, true);
1491 // Simulate that the password value was cleared by the site's JavaScript
1493 password_element_
.setValue(WebString());
1494 static_cast<content::RenderViewObserver
*>(password_autofill_agent_
)
1495 ->WillSubmitForm(GetMainFrame(), username_element_
.form());
1497 // Observe that the PasswordAutofillAgent still remembered the last non-empty
1498 // password and sent that to the browser.
1499 ExpectFormSubmittedWithPasswords("random", "");
1502 // Similar to RememberLastNonEmptyPasswordOnSubmit_ScriptCleared, but this time
1503 // it's the user who clears the password. This test checks that in that case,
1504 // the last non-empty password is not remembered.
1505 TEST_F(PasswordAutofillAgentTest
,
1506 RememberLastNonEmptyPasswordOnSubmit_UserCleared
) {
1507 SimulateInputChangeForElement(
1508 "temp", true, GetMainFrame(), username_element_
, true);
1509 SimulateInputChangeForElement(
1510 "random", true, GetMainFrame(), password_element_
, true);
1512 // Simulate that the user actually cleared the password again.
1513 SimulateInputChangeForElement(
1514 "", true, GetMainFrame(), password_element_
, true);
1515 static_cast<content::RenderViewObserver
*>(password_autofill_agent_
)
1516 ->WillSubmitForm(GetMainFrame(), username_element_
.form());
1518 // Observe that the PasswordAutofillAgent respects the user having cleared the
1520 ExpectFormSubmittedWithPasswords("", "");
1523 // Similar to RememberLastNonEmptyPasswordOnSubmit_ScriptCleared, but uses the
1524 // new password instead of the current password.
1525 TEST_F(PasswordAutofillAgentTest
,
1526 RememberLastNonEmptyPasswordOnSubmit_NewPassword
) {
1527 const char kNewPasswordFormHTML
[] =
1528 "<FORM name='LoginTestForm'>"
1529 " <INPUT type='text' id='username' autocomplete='username'/>"
1530 " <INPUT type='password' id='password' autocomplete='new-password'/>"
1531 " <INPUT type='submit' value='Login'/>"
1533 LoadHTML(kNewPasswordFormHTML
);
1534 UpdateUsernameAndPasswordElements();
1536 SimulateInputChangeForElement(
1537 "temp", true, GetMainFrame(), username_element_
, true);
1538 SimulateInputChangeForElement(
1539 "random", true, GetMainFrame(), password_element_
, true);
1541 // Simulate that the password value was cleared by the site's JavaScript
1543 password_element_
.setValue(WebString());
1544 static_cast<content::RenderViewObserver
*>(password_autofill_agent_
)
1545 ->WillSubmitForm(GetMainFrame(), username_element_
.form());
1547 // Observe that the PasswordAutofillAgent still remembered the last non-empty
1548 // password and sent that to the browser.
1549 ExpectFormSubmittedWithPasswords("", "random");
1552 // The user first accepts a suggestion, but then overwrites the password. This
1553 // test checks that the overwritten password is not reverted back if the user
1554 // triggers autofill through focusing (but not changing) the username again.
1555 TEST_F(PasswordAutofillAgentTest
,
1556 NoopEditingDoesNotOverwriteManuallyEditedPassword
) {
1557 // Simulate having credentials which needed to wait until the user starts
1558 // typing the username to be filled (e.g., PSL-matched credentials). Those are
1559 // the ones which can be filled as a result of TextFieldDidEndEditing.
1560 fill_data_
.wait_for_username
= true;
1561 SimulateOnFillPasswordForm(fill_data_
);
1562 // Simulate that the user typed her name to make the autofill work.
1563 SimulateInputChangeForElement(kAliceUsername
,
1564 /*move_caret_to_end=*/true,
1567 /*is_user_input=*/true);
1568 SimulateDidEndEditing(GetMainFrame(), username_element_
);
1569 const std::string
old_username(username_element_
.value().utf8());
1570 const std::string
old_password(password_element_
.value().utf8());
1571 const std::string
new_password(old_password
+ "modify");
1573 // The user changes the password.
1574 SimulateInputChangeForElement(new_password
,
1575 /*move_caret_to_end=*/true,
1578 /*is_user_input=*/true);
1580 // The user switches back into the username field, but leaves that without
1582 SimulateDidEndEditing(GetMainFrame(), username_element_
);
1584 // The password should have stayed as the user changed it.
1585 CheckTextFieldsDOMState(old_username
, true, new_password
, false);
1586 // The password should not have a suggested value.
1587 CheckTextFieldsState(old_username
, true, std::string(), false);
1590 TEST_F(PasswordAutofillAgentTest
,
1591 InlineAutocompleteOverwritesManuallyEditedPassword
) {
1592 // Simulate the browser sending back the login info.
1593 SimulateOnFillPasswordForm(fill_data_
);
1595 ClearUsernameAndPasswordFields();
1597 // The user enters a password
1598 SimulateInputChangeForElement("someOtherPassword",
1599 /*move_caret_to_end=*/true,
1602 /*is_user_input=*/true);
1604 // Simulate the user typing a stored username.
1605 SimulateUsernameChange(kAliceUsername
, true);
1606 // The autofileld password should replace the typed one.
1607 CheckTextFieldsDOMState(kAliceUsername
, true, kAlicePassword
, true);
1610 } // namespace autofill