Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / chrome / renderer / autofill / password_autofill_agent_browsertest.cc
blobf17aeb63127b985df577ec84794cf32e049e6e99
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;
36 using blink::WebView;
38 namespace {
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'/>"
57 "</FORM>";
59 const char kVisibleFormHTML[] =
60 "<head> <style> form {display: inline;} </style> </head>"
61 "<body>"
62 " <form>"
63 " <div>"
64 " <input type='password' id='password'/>"
65 " </div>"
66 " </form>"
67 "</body>";
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>"
75 "<body>"
76 " <form>"
77 " <div>"
78 " <input type='password' id='password'/>"
79 " </div>"
80 " </form>"
81 "</body>";
83 const char kEmptyWebpage[] =
84 "<html>"
85 " <head>"
86 " </head>"
87 " <body>"
88 " </body>"
89 "</html>";
91 const char kRedirectionWebpage[] =
92 "<html>"
93 " <head>"
94 " <meta http-equiv='Content-Type' content='text/html'>"
95 " <title>Redirection page</title>"
96 " <script></script>"
97 " </head>"
98 " <body>"
99 " <script type='text/javascript'>"
100 " function test(){}"
101 " </script>"
102 " </body>"
103 "</html>";
105 const char kSimpleWebpage[] =
106 "<html>"
107 " <head>"
108 " <meta charset='utf-8' />"
109 " <title>Title</title>"
110 " </head>"
111 " <body>"
112 " <form name='LoginTestForm'>"
113 " <input type='text' id='username'/>"
114 " <input type='password' id='password'/>"
115 " <input type='submit' value='Login'/>"
116 " </form>"
117 " </body>"
118 "</html>";
120 const char kWebpageWithDynamicContent[] =
121 "<html>"
122 " <head>"
123 " <meta charset='utf-8' />"
124 " <title>Title</title>"
125 " </head>"
126 " <body>"
127 " <script type='text/javascript'>"
128 " function addParagraph() {"
129 " var p = document.createElement('p');"
130 " document.body.appendChild(p);"
131 " }"
132 " window.onload = addParagraph;"
133 " </script>"
134 " </body>"
135 "</html>";
137 const char kJavaScriptClick[] =
138 "var event = new MouseEvent('click', {"
139 " 'view': window,"
140 " 'bubbles': true,"
141 " 'cancelable': true"
142 "});"
143 "var form = document.getElementById('myform1');"
144 "form.dispatchEvent(event);"
145 "console.log('clicked!');";
147 const char kOnChangeDetectionScript[] =
148 "<script>"
149 " usernameOnchangeCalled = false;"
150 " passwordOnchangeCalled = false;"
151 " document.getElementById('username').onchange = function() {"
152 " usernameOnchangeCalled = true;"
153 " };"
154 " document.getElementById('password').onchange = function() {"
155 " passwordOnchangeCalled = true;"
156 " };"
157 "</script>";
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());
165 } // namespace
167 namespace autofill {
169 class PasswordAutofillAgentTest : public ChromeRenderViewTest {
170 public:
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()
176 // protected.
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");
229 LoadHTML(kFormHTML);
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();
248 WebElement element =
249 document.getElementById(WebString::fromUTF8(kUsernameName));
250 ASSERT_FALSE(element.isNull());
251 username_element_ = element.to<blink::WebInputElement>();
252 element = document.getElementById(WebString::fromUTF8(kPasswordName));
253 ASSERT_FALSE(element.isNull());
254 password_element_ = element.to<blink::WebInputElement>();
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());
280 if (is_user_input)
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,
318 move_caret_to_end,
319 GetMainFrame(),
320 username_element_,
321 is_user_input);
324 // Tests that no suggestion popup is generated when the username_element_ is
325 // edited.
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
339 // is filled).
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()) {
347 EXPECT_TRUE(
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) {
369 EXPECT_EQ(username,
370 static_cast<std::string>(username_element.value().utf8()));
371 EXPECT_EQ(username_autofilled, username_element.isAutofilled());
372 EXPECT_EQ(password,
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_,
387 username,
388 username_autofilled,
389 password_element_,
390 password,
391 password_autofilled,
392 true);
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_,
402 username,
403 username_autofilled,
404 password_element_,
405 password,
406 password_autofilled,
407 false);
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,
421 gfx::RectF,
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,
441 gfx::RectF,
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())
452 usernames.erase(it);
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_;
488 private:
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
503 // the form.
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
518 // autocomplete.
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'/>"
532 "</FORM>";
533 LoadHTML(kEmptyActionFormHTML);
535 // Retrieve the input elements so the test can access them.
536 WebDocument document = GetMainFrame()->document();
537 WebElement element =
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
550 // autocomplete.
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
558 // on page load.
559 TEST_F(PasswordAutofillAgentTest, NoInitialAutocompleteForReadOnlyPassword) {
560 SetElementReadOnly(password_element_, true);
562 // Simulate the browser sending back the login info, it triggers the
563 // autocomplete.
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
570 // matches.
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
597 // autocomplete.
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
605 // to a username.
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'/>"
632 "</FORM>";
633 LoadHTML(kTextFieldPasswordFormHTML);
635 // Retrieve the input elements so the test can access them.
636 WebDocument document = GetMainFrame()->document();
637 WebElement element =
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'/>"
660 "</FORM>";
661 LoadHTML(kPasswordFieldUsernameFormHTML);
663 // Retrieve the input elements so the test can access them.
664 WebDocument document = GetMainFrame()->document();
665 WebElement element =
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
687 // autocomplete.
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
697 // autocomplete.
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
726 // a full match.
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
749 // username.
750 SimulateUsernameChange("a", true);
751 // Both the username and password text fields should reflect selection of the
752 // stored login.
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
775 // should be empty.
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
793 // should be empty.
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, &param);
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, &param);
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, &param);
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[] =
881 "<html>"
882 " <head>"
883 " <meta charset='utf-8' />"
884 " <title>Title</title>"
885 " </head>"
886 " <body>"
887 " <iframe name='iframe' src=\"";
888 const char kWebpageWithIframeEnd[] =
889 "\"></iframe>"
890 " </body>"
891 "</html>";
893 std::string origin("data:text/html;charset=utf-8,");
894 origin += kSimpleWebpage;
896 std::string page_html(kWebpageWithIframeStart);
897 page_html += origin;
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);
911 ASSERT_TRUE(iframe);
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
927 // an autofill.
928 SimulateInputChangeForElement(
929 kAliceUsername, true, iframe, username_input, true);
931 CheckTextFieldsStateForElements(username_input,
932 kAliceUsername,
933 true,
934 password_input,
935 kAlicePassword,
936 true,
937 false);
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
1040 // autocomplete.
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;
1053 ASSERT_TRUE(
1054 ExecuteJavaScriptAndReturnIntValue(
1055 ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"),
1056 &username_onchange_called));
1057 EXPECT_EQ(1, username_onchange_called);
1058 ASSERT_TRUE(
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.
1071 ASSERT_TRUE(
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
1088 // autocomplete.
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
1096 // set directly.
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;
1111 ASSERT_TRUE(
1112 ExecuteJavaScriptAndReturnIntValue(
1113 ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"),
1114 &username_onchange_called));
1115 EXPECT_EQ(1, username_onchange_called);
1116 ASSERT_TRUE(
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));
1180 EXPECT_EQ(
1181 kAliceUsername,
1182 static_cast<std::string>(username_element_.suggestedValue().utf8()));
1183 EXPECT_TRUE(username_element_.isAutofilled());
1184 EXPECT_EQ(
1185 kAlicePassword,
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));
1195 EXPECT_EQ(
1196 kBobUsername,
1197 static_cast<std::string>(username_element_.suggestedValue().utf8()));
1198 EXPECT_TRUE(username_element_.isAutofilled());
1199 EXPECT_EQ(
1200 kCarolPassword,
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));
1222 EXPECT_EQ(
1223 kAliceUsername,
1224 static_cast<std::string>(username_element_.suggestedValue().utf8()));
1225 EXPECT_TRUE(username_element_.isAutofilled());
1226 EXPECT_EQ(
1227 kAlicePassword,
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
1361 // stored login.
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"));
1368 EXPECT_EQ(
1369 "alicia",
1370 static_cast<std::string>(username_element_.suggestedValue().utf8()));
1371 EXPECT_TRUE(username_element_.isAutofilled());
1372 EXPECT_EQ(
1373 "secret",
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
1491 // suggestion list.
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
1509 // before submit.
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
1536 // password.
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'/>"
1549 "</FORM>";
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
1559 // before submit.
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,
1582 GetMainFrame(),
1583 username_element_,
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,
1593 GetMainFrame(),
1594 password_element_,
1595 /*is_user_input=*/true);
1597 // The user switches back into the username field, but leaves that without
1598 // changes.
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,
1617 GetMainFrame(),
1618 password_element_,
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