Add testing/scripts/OWNERS
[chromium-blink-merge.git] / chrome / renderer / autofill / password_autofill_agent_browsertest.cc
blob4e60b376d57f025ed61b392f32d3b47c43627e3f
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 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");
230 LoadHTML(kFormHTML);
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();
249 WebElement element =
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());
282 if (is_user_input)
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,
322 move_caret_to_end,
323 GetMainFrame(),
324 username_element_,
325 is_user_input);
328 // Tests that no suggestion popup is generated when the username_element_ is
329 // edited.
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
343 // is filled).
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()) {
351 EXPECT_TRUE(
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) {
374 EXPECT_EQ(username,
375 static_cast<std::string>(username_element.value().utf8()));
376 EXPECT_EQ(username_autofilled, username_element.isAutofilled());
377 EXPECT_EQ(password,
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_,
392 username,
393 username_autofilled,
394 password_element_,
395 password,
396 password_autofilled,
397 true);
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_,
407 username,
408 username_autofilled,
409 password_element_,
410 password,
411 password_autofilled,
412 false);
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_;
464 private:
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
479 // the form.
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
494 // autocomplete.
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'/>"
508 "</FORM>";
509 LoadHTML(kEmptyActionFormHTML);
511 // Retrieve the input elements so the test can access them.
512 WebDocument document = GetMainFrame()->document();
513 WebElement element =
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
526 // autocomplete.
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
534 // on page load.
535 TEST_F(PasswordAutofillAgentTest, NoInitialAutocompleteForReadOnlyPassword) {
536 SetElementReadOnly(password_element_, true);
538 // Simulate the browser sending back the login info, it triggers the
539 // autocomplete.
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
546 // matches.
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
573 // autocomplete.
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
581 // to a username.
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'/>"
608 "</FORM>";
609 LoadHTML(kTextFieldPasswordFormHTML);
611 // Retrieve the input elements so the test can access them.
612 WebDocument document = GetMainFrame()->document();
613 WebElement element =
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'/>"
636 "</FORM>";
637 LoadHTML(kPasswordFieldUsernameFormHTML);
639 // Retrieve the input elements so the test can access them.
640 WebDocument document = GetMainFrame()->document();
641 WebElement element =
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
663 // autocomplete.
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
673 // autocomplete.
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
702 // a full match.
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
729 // username.
730 SimulateUsernameChange("a", true);
731 // Both the username and password text fields should reflect selection of the
732 // stored login.
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
755 // should be empty.
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
773 // should be empty.
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, &param);
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, &param);
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, &param);
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[] =
861 "<html>"
862 " <head>"
863 " <meta charset='utf-8' />"
864 " <title>Title</title>"
865 " </head>"
866 " <body>"
867 " <iframe name='iframe' src=\"";
868 const char kWebpageWithIframeEnd[] =
869 "\"></iframe>"
870 " </body>"
871 "</html>";
873 std::string origin("data:text/html;charset=utf-8,");
874 origin += kSimpleWebpage;
876 std::string page_html(kWebpageWithIframeStart);
877 page_html += origin;
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);
891 ASSERT_TRUE(iframe);
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
907 // an autofill.
908 SimulateInputChangeForElement(
909 kAliceUsername, true, iframe, username_input, true);
911 CheckTextFieldsStateForElements(username_input,
912 kAliceUsername,
913 true,
914 password_input,
915 kAlicePassword,
916 true,
917 false);
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
1020 // autocomplete.
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;
1033 ASSERT_TRUE(
1034 ExecuteJavaScriptAndReturnIntValue(
1035 ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"),
1036 &username_onchange_called));
1037 EXPECT_EQ(1, username_onchange_called);
1038 ASSERT_TRUE(
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.
1051 ASSERT_TRUE(
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
1068 // autocomplete.
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
1076 // set directly.
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;
1091 ASSERT_TRUE(
1092 ExecuteJavaScriptAndReturnIntValue(
1093 ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"),
1094 &username_onchange_called));
1095 EXPECT_EQ(1, username_onchange_called);
1096 ASSERT_TRUE(
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));
1160 EXPECT_EQ(
1161 kAliceUsername,
1162 static_cast<std::string>(username_element_.suggestedValue().utf8()));
1163 EXPECT_TRUE(username_element_.isAutofilled());
1164 EXPECT_EQ(
1165 kAlicePassword,
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));
1175 EXPECT_EQ(
1176 kBobUsername,
1177 static_cast<std::string>(username_element_.suggestedValue().utf8()));
1178 EXPECT_TRUE(username_element_.isAutofilled());
1179 EXPECT_EQ(
1180 kCarolPassword,
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));
1202 EXPECT_EQ(
1203 kAliceUsername,
1204 static_cast<std::string>(username_element_.suggestedValue().utf8()));
1205 EXPECT_TRUE(username_element_.isAutofilled());
1206 EXPECT_EQ(
1207 kAlicePassword,
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));
1230 EXPECT_TRUE(
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));
1259 EXPECT_TRUE(
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));
1291 EXPECT_TRUE(
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));
1317 EXPECT_TRUE(
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
1341 // stored login.
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"));
1348 EXPECT_EQ(
1349 "alicia",
1350 static_cast<std::string>(username_element_.suggestedValue().utf8()));
1351 EXPECT_TRUE(username_element_.isAutofilled());
1352 EXPECT_EQ(
1353 "secret",
1354 static_cast<std::string>(password_element_.suggestedValue().utf8()));
1355 EXPECT_TRUE(password_element_.isAutofilled());
1356 CheckUsernameSelection(1, 6);
1358 EXPECT_TRUE(
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
1473 // suggestion list.
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
1492 // before submit.
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
1519 // password.
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'/>"
1532 "</FORM>";
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
1542 // before submit.
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,
1565 GetMainFrame(),
1566 username_element_,
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,
1576 GetMainFrame(),
1577 password_element_,
1578 /*is_user_input=*/true);
1580 // The user switches back into the username field, but leaves that without
1581 // changes.
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,
1600 GetMainFrame(),
1601 password_element_,
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