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.
4
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"
27
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;
37
38 namespace {
39
40 // The name of the username/password element in the form.
41 const char kUsernameName[] = "username";
42 const char kPasswordName[] = "password";
43
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";
51
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>";
58
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>";
68
69 const char kEmptyFormHTML[] =
70 "<head> <style> form {display: inline;} </style> </head>"
71 "<body> <form> </form> </body>";
72
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>";
82
83 const char kEmptyWebpage[] =
84 "<html>"
85 " <head>"
86 " </head>"
87 " <body>"
88 " </body>"
89 "</html>";
90
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>";
104
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>";
119
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>";
136
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!');";
146
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>";
158
159 // Sets the "readonly" attribute of |element| to the value given by |read_only|.
SetElementReadOnly(WebInputElement & element,bool read_only)160 void SetElementReadOnly(WebInputElement& element, bool read_only) {
161 element.setAttribute(WebString::fromUTF8("readonly"),
162 read_only ? WebString::fromUTF8("true") : WebString());
163 }
164
165 } // namespace
166
167 namespace autofill {
168
169 class PasswordAutofillAgentTest : public ChromeRenderViewTest {
170 public:
PasswordAutofillAgentTest()171 PasswordAutofillAgentTest() {
172 }
173
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.
SimulateOnFillPasswordForm(const PasswordFormFillData & fill_data)177 void SimulateOnFillPasswordForm(
178 const PasswordFormFillData& fill_data) {
179 AutofillMsg_FillPasswordForm msg(0, fill_data);
180 password_autofill_->OnMessageReceived(msg);
181 }
182
SendVisiblePasswordForms()183 void SendVisiblePasswordForms() {
184 password_autofill_->SendPasswordForms(GetMainFrame(),
185 true /* only_visible */);
186 }
187
SetUp()188 virtual void SetUp() {
189 ChromeRenderViewTest::SetUp();
190
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);
199
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);
204
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);
210
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;
217
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_);
223
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");
228
229 LoadHTML(kFormHTML);
230
231 // Now retrieve the input elements so the test can access them.
232 UpdateUsernameAndPasswordElements();
233 }
234
TearDown()235 virtual void TearDown() {
236 username_element_.reset();
237 password_element_.reset();
238 ChromeRenderViewTest::TearDown();
239 }
240
UpdateOriginForHTML(const std::string & html)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);
244 }
245
UpdateUsernameAndPasswordElements()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>();
255 }
256
ClearUsernameAndPasswordFields()257 void ClearUsernameAndPasswordFields() {
258 username_element_.setValue("");
259 username_element_.setAutofilled(false);
260 password_element_.setValue("");
261 password_element_.setAutofilled(false);
262 }
263
SimulateUsernameChangeForElement(const std::string & username,bool move_caret_to_end,WebFrame * input_frame,WebInputElement & username_input)264 void SimulateUsernameChangeForElement(const std::string& username,
265 bool move_caret_to_end,
266 WebFrame* input_frame,
267 WebInputElement& username_input) {
268 username_input.setValue(WebString::fromUTF8(username));
269 // The field must have focus or AutofillAgent will think the
270 // change should be ignored.
271 while (!username_input.focused())
272 input_frame->document().frame()->view()->advanceFocus(false);
273 if (move_caret_to_end)
274 username_input.setSelectionRange(username.length(), username.length());
275 autofill_agent_->textFieldDidChange(username_input);
276 // Processing is delayed because of a Blink bug:
277 // https://bugs.webkit.org/show_bug.cgi?id=16976
278 // See PasswordAutofillAgent::TextDidChangeInTextField() for details.
279
280 // Autocomplete will trigger a style recalculation when we put up the next
281 // frame, but we don't want to wait that long. Instead, trigger a style
282 // recalcuation manually after TextFieldDidChangeImpl runs.
283 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
284 &PasswordAutofillAgentTest::LayoutMainFrame, base::Unretained(this)));
285
286 base::MessageLoop::current()->RunUntilIdle();
287 }
288
LayoutMainFrame()289 void LayoutMainFrame() {
290 GetMainFrame()->view()->layout();
291 }
292
SimulateUsernameChange(const std::string & username,bool move_caret_to_end)293 void SimulateUsernameChange(const std::string& username,
294 bool move_caret_to_end) {
295 SimulateUsernameChangeForElement(username, move_caret_to_end,
296 GetMainFrame(), username_element_);
297 }
298
299 // Tests that no suggestion popup is generated when the username_element_ is
300 // edited.
ExpectNoSuggestionsPopup()301 void ExpectNoSuggestionsPopup() {
302 // The first test below ensures that the suggestions have been handled by
303 // the password_autofill_agent, even though autocomplete='off' is set. The
304 // second check ensures that, although handled, no "show suggestions" IPC to
305 // the browser was generated.
306 //
307 // This is interesting in the specific case of an autocomplete='off' form
308 // that also has a remembered username and password
309 // (http://crbug.com/326679). To fix the DCHECK that this case used to hit,
310 // |true| is returned from ShowSuggestions for all forms with valid
311 // usersnames that are autocomplete='off', prentending that a selection box
312 // has been shown to the user. Of course, it hasn't, so a message is never
313 // sent to the browser on acceptance, and the DCHECK isn't hit (and nothing
314 // is filled).
315 //
316 // These tests only make sense in the context of not ignoring
317 // autocomplete='off', so only test them if the disable autocomplete='off'
318 // flag is not enabled.
319 // TODO(jww): Remove this function and callers once autocomplete='off' is
320 // permanently ignored.
321 if (!ShouldIgnoreAutocompleteOffForPasswordFields()) {
322 EXPECT_TRUE(autofill_agent_->password_autofill_agent_->ShowSuggestions(
323 username_element_));
324
325 EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching(
326 AutofillHostMsg_ShowPasswordSuggestions::ID));
327 }
328 }
329
SimulateKeyDownEvent(const WebInputElement & element,ui::KeyboardCode key_code)330 void SimulateKeyDownEvent(const WebInputElement& element,
331 ui::KeyboardCode key_code) {
332 blink::WebKeyboardEvent key_event;
333 key_event.windowsKeyCode = key_code;
334 autofill_agent_->textFieldDidReceiveKeyDown(element, key_event);
335 }
336
CheckTextFieldsStateForElements(const WebInputElement & username_element,const std::string & username,bool username_autofilled,const WebInputElement & password_element,const std::string & password,bool password_autofilled,bool checkSuggestedValue=true)337 void CheckTextFieldsStateForElements(const WebInputElement& username_element,
338 const std::string& username,
339 bool username_autofilled,
340 const WebInputElement& password_element,
341 const std::string& password,
342 bool password_autofilled,
343 bool checkSuggestedValue = true) {
344 EXPECT_EQ(username,
345 static_cast<std::string>(username_element.value().utf8()));
346 EXPECT_EQ(username_autofilled, username_element.isAutofilled());
347 EXPECT_EQ(password,
348 static_cast<std::string>(
349 checkSuggestedValue ? password_element.suggestedValue().utf8()
350 : password_element.value().utf8()));
351 EXPECT_EQ(password_autofilled, password_element.isAutofilled());
352 }
353
354 // Checks the DOM-accessible value of the username element and the
355 // *suggested* value of the password element.
CheckTextFieldsState(const std::string & username,bool username_autofilled,const std::string & password,bool password_autofilled)356 void CheckTextFieldsState(const std::string& username,
357 bool username_autofilled,
358 const std::string& password,
359 bool password_autofilled) {
360 CheckTextFieldsStateForElements(username_element_, username,
361 username_autofilled, password_element_,
362 password, password_autofilled);
363 }
364
365 // Checks the DOM-accessible value of the username element and the
366 // DOM-accessible value of the password element.
CheckTextFieldsDOMState(const std::string & username,bool username_autofilled,const std::string & password,bool password_autofilled)367 void CheckTextFieldsDOMState(const std::string& username,
368 bool username_autofilled,
369 const std::string& password,
370 bool password_autofilled) {
371 CheckTextFieldsStateForElements(username_element_,
372 username,
373 username_autofilled,
374 password_element_,
375 password,
376 password_autofilled,
377 false);
378 }
379
CheckUsernameSelection(int start,int end)380 void CheckUsernameSelection(int start, int end) {
381 EXPECT_EQ(start, username_element_.selectionStart());
382 EXPECT_EQ(end, username_element_.selectionEnd());
383 }
384
385 base::string16 username1_;
386 base::string16 username2_;
387 base::string16 username3_;
388 base::string16 password1_;
389 base::string16 password2_;
390 base::string16 password3_;
391 base::string16 alternate_username3_;
392 PasswordFormFillData fill_data_;
393
394 WebInputElement username_element_;
395 WebInputElement password_element_;
396
397 private:
398 DISALLOW_COPY_AND_ASSIGN(PasswordAutofillAgentTest);
399 };
400
401 // Tests that the password login is autocompleted as expected when the browser
402 // sends back the password info.
TEST_F(PasswordAutofillAgentTest,InitialAutocomplete)403 TEST_F(PasswordAutofillAgentTest, InitialAutocomplete) {
404 /*
405 * Right now we are not sending the message to the browser because we are
406 * loading a data URL and the security origin canAccessPasswordManager()
407 * returns false. May be we should mock URL loading to cirmcuvent this?
408 TODO(jcivelli): find a way to make the security origin not deny access to the
409 password manager and then reenable this code.
410
411 // The form has been loaded, we should have sent the browser a message about
412 // the form.
413 const IPC::Message* msg = render_thread_.sink().GetFirstMessageMatching(
414 AutofillHostMsg_PasswordFormsParsed::ID);
415 ASSERT_TRUE(msg != NULL);
416
417 Tuple1<std::vector<PasswordForm> > forms;
418 AutofillHostMsg_PasswordFormsParsed::Read(msg, &forms);
419 ASSERT_EQ(1U, forms.a.size());
420 PasswordForm password_form = forms.a[0];
421 EXPECT_EQ(PasswordForm::SCHEME_HTML, password_form.scheme);
422 EXPECT_EQ(ASCIIToUTF16(kUsernameName), password_form.username_element);
423 EXPECT_EQ(ASCIIToUTF16(kPasswordName), password_form.password_element);
424 */
425
426 // Simulate the browser sending back the login info, it triggers the
427 // autocomplete.
428 SimulateOnFillPasswordForm(fill_data_);
429
430 // The username and password should have been autocompleted.
431 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
432 }
433
434 // Tests that we correctly fill forms having an empty 'action' attribute.
TEST_F(PasswordAutofillAgentTest,InitialAutocompleteForEmptyAction)435 TEST_F(PasswordAutofillAgentTest, InitialAutocompleteForEmptyAction) {
436 const char kEmptyActionFormHTML[] =
437 "<FORM name='LoginTestForm'>"
438 " <INPUT type='text' id='username'/>"
439 " <INPUT type='password' id='password'/>"
440 " <INPUT type='submit' value='Login'/>"
441 "</FORM>";
442 LoadHTML(kEmptyActionFormHTML);
443
444 // Retrieve the input elements so the test can access them.
445 WebDocument document = GetMainFrame()->document();
446 WebElement element =
447 document.getElementById(WebString::fromUTF8(kUsernameName));
448 ASSERT_FALSE(element.isNull());
449 username_element_ = element.to<blink::WebInputElement>();
450 element = document.getElementById(WebString::fromUTF8(kPasswordName));
451 ASSERT_FALSE(element.isNull());
452 password_element_ = element.to<blink::WebInputElement>();
453
454 // Set the expected form origin and action URLs.
455 UpdateOriginForHTML(kEmptyActionFormHTML);
456 fill_data_.basic_data.action = fill_data_.basic_data.origin;
457
458 // Simulate the browser sending back the login info, it triggers the
459 // autocomplete.
460 SimulateOnFillPasswordForm(fill_data_);
461
462 // The username and password should have been autocompleted.
463 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
464 }
465
466 // Tests that if a password is marked as readonly, neither field is autofilled
467 // on page load.
TEST_F(PasswordAutofillAgentTest,NoInitialAutocompleteForReadOnlyPassword)468 TEST_F(PasswordAutofillAgentTest, NoInitialAutocompleteForReadOnlyPassword) {
469 SetElementReadOnly(password_element_, true);
470
471 // Simulate the browser sending back the login info, it triggers the
472 // autocomplete.
473 SimulateOnFillPasswordForm(fill_data_);
474
475 CheckTextFieldsState(std::string(), false, std::string(), false);
476 }
477
478 // Can still fill a password field if the username is set to a value that
479 // matches.
TEST_F(PasswordAutofillAgentTest,AutocompletePasswordForReadonlyUsernameMatched)480 TEST_F(PasswordAutofillAgentTest,
481 AutocompletePasswordForReadonlyUsernameMatched) {
482 username_element_.setValue(username3_);
483 SetElementReadOnly(username_element_, true);
484
485 // Filled even though username is not the preferred match.
486 SimulateOnFillPasswordForm(fill_data_);
487 CheckTextFieldsState(UTF16ToUTF8(username3_), false,
488 UTF16ToUTF8(password3_), true);
489 }
490
491 // If a username field is empty and readonly, don't autofill.
TEST_F(PasswordAutofillAgentTest,NoAutocompletePasswordForReadonlyUsernameUnmatched)492 TEST_F(PasswordAutofillAgentTest,
493 NoAutocompletePasswordForReadonlyUsernameUnmatched) {
494 username_element_.setValue(WebString::fromUTF8(""));
495 SetElementReadOnly(username_element_, true);
496
497 SimulateOnFillPasswordForm(fill_data_);
498 CheckTextFieldsState(std::string(), false, std::string(), false);
499 }
500
501 // Tests that having a non-matching username precludes the autocomplete.
TEST_F(PasswordAutofillAgentTest,NoAutocompleteForFilledFieldUnmatched)502 TEST_F(PasswordAutofillAgentTest, NoAutocompleteForFilledFieldUnmatched) {
503 username_element_.setValue(WebString::fromUTF8("bogus"));
504
505 // Simulate the browser sending back the login info, it triggers the
506 // autocomplete.
507 SimulateOnFillPasswordForm(fill_data_);
508
509 // Neither field should be autocompleted.
510 CheckTextFieldsState("bogus", false, std::string(), false);
511 }
512
513 // Don't try to complete a prefilled value even if it's a partial match
514 // to a username.
TEST_F(PasswordAutofillAgentTest,NoPartialMatchForPrefilledUsername)515 TEST_F(PasswordAutofillAgentTest, NoPartialMatchForPrefilledUsername) {
516 username_element_.setValue(WebString::fromUTF8("ali"));
517
518 SimulateOnFillPasswordForm(fill_data_);
519
520 CheckTextFieldsState("ali", false, std::string(), false);
521 }
522
TEST_F(PasswordAutofillAgentTest,InputWithNoForms)523 TEST_F(PasswordAutofillAgentTest, InputWithNoForms) {
524 const char kNoFormInputs[] =
525 "<input type='text' id='username'/>"
526 "<input type='password' id='password'/>";
527 LoadHTML(kNoFormInputs);
528
529 SimulateOnFillPasswordForm(fill_data_);
530
531 // Input elements that aren't in a <form> won't autofill.
532 CheckTextFieldsState(std::string(), false, std::string(), false);
533 }
534
TEST_F(PasswordAutofillAgentTest,NoAutocompleteForTextFieldPasswords)535 TEST_F(PasswordAutofillAgentTest, NoAutocompleteForTextFieldPasswords) {
536 const char kTextFieldPasswordFormHTML[] =
537 "<FORM name='LoginTestForm' action='http://www.bidule.com'>"
538 " <INPUT type='text' id='username'/>"
539 " <INPUT type='text' id='password'/>"
540 " <INPUT type='submit' value='Login'/>"
541 "</FORM>";
542 LoadHTML(kTextFieldPasswordFormHTML);
543
544 // Retrieve the input elements so the test can access them.
545 WebDocument document = GetMainFrame()->document();
546 WebElement element =
547 document.getElementById(WebString::fromUTF8(kUsernameName));
548 ASSERT_FALSE(element.isNull());
549 username_element_ = element.to<blink::WebInputElement>();
550 element = document.getElementById(WebString::fromUTF8(kPasswordName));
551 ASSERT_FALSE(element.isNull());
552 password_element_ = element.to<blink::WebInputElement>();
553
554 // Set the expected form origin URL.
555 UpdateOriginForHTML(kTextFieldPasswordFormHTML);
556
557 SimulateOnFillPasswordForm(fill_data_);
558
559 // Fields should still be empty.
560 CheckTextFieldsState(std::string(), false, std::string(), false);
561 }
562
TEST_F(PasswordAutofillAgentTest,NoAutocompleteForPasswordFieldUsernames)563 TEST_F(PasswordAutofillAgentTest, NoAutocompleteForPasswordFieldUsernames) {
564 const char kPasswordFieldUsernameFormHTML[] =
565 "<FORM name='LoginTestForm' action='http://www.bidule.com'>"
566 " <INPUT type='password' id='username'/>"
567 " <INPUT type='password' id='password'/>"
568 " <INPUT type='submit' value='Login'/>"
569 "</FORM>";
570 LoadHTML(kPasswordFieldUsernameFormHTML);
571
572 // Retrieve the input elements so the test can access them.
573 WebDocument document = GetMainFrame()->document();
574 WebElement element =
575 document.getElementById(WebString::fromUTF8(kUsernameName));
576 ASSERT_FALSE(element.isNull());
577 username_element_ = element.to<blink::WebInputElement>();
578 element = document.getElementById(WebString::fromUTF8(kPasswordName));
579 ASSERT_FALSE(element.isNull());
580 password_element_ = element.to<blink::WebInputElement>();
581
582 // Set the expected form origin URL.
583 UpdateOriginForHTML(kPasswordFieldUsernameFormHTML);
584
585 SimulateOnFillPasswordForm(fill_data_);
586
587 // Fields should still be empty.
588 CheckTextFieldsState(std::string(), false, std::string(), false);
589 }
590
591 // Tests that having a matching username does not preclude the autocomplete.
TEST_F(PasswordAutofillAgentTest,InitialAutocompleteForMatchingFilledField)592 TEST_F(PasswordAutofillAgentTest, InitialAutocompleteForMatchingFilledField) {
593 username_element_.setValue(WebString::fromUTF8(kAliceUsername));
594
595 // Simulate the browser sending back the login info, it triggers the
596 // autocomplete.
597 SimulateOnFillPasswordForm(fill_data_);
598
599 // The username and password should have been autocompleted.
600 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
601 }
602
603 // Tests that editing the password clears the autocompleted password field.
TEST_F(PasswordAutofillAgentTest,PasswordClearOnEdit)604 TEST_F(PasswordAutofillAgentTest, PasswordClearOnEdit) {
605 // Simulate the browser sending back the login info, it triggers the
606 // autocomplete.
607 SimulateOnFillPasswordForm(fill_data_);
608
609 // Simulate the user changing the username to some unknown username.
610 SimulateUsernameChange("alicia", true);
611
612 // The password should have been cleared.
613 CheckTextFieldsState("alicia", false, std::string(), false);
614 }
615
616 // Tests that we only autocomplete on focus lost and with a full username match
617 // when |wait_for_username| is true.
TEST_F(PasswordAutofillAgentTest,WaitUsername)618 TEST_F(PasswordAutofillAgentTest, WaitUsername) {
619 // Simulate the browser sending back the login info.
620 fill_data_.wait_for_username = true;
621 SimulateOnFillPasswordForm(fill_data_);
622
623 // No auto-fill should have taken place.
624 CheckTextFieldsState(std::string(), false, std::string(), false);
625
626 // No autocomplete should happen when text is entered in the username.
627 SimulateUsernameChange("a", true);
628 CheckTextFieldsState("a", false, std::string(), false);
629 SimulateUsernameChange("al", true);
630 CheckTextFieldsState("al", false, std::string(), false);
631 SimulateUsernameChange(kAliceUsername, true);
632 CheckTextFieldsState(kAliceUsername, false, std::string(), false);
633
634 // Autocomplete should happen only when the username textfield is blurred with
635 // a full match.
636 username_element_.setValue("a");
637 autofill_agent_->textFieldDidEndEditing(username_element_);
638 CheckTextFieldsState("a", false, std::string(), false);
639 username_element_.setValue("al");
640 autofill_agent_->textFieldDidEndEditing(username_element_);
641 CheckTextFieldsState("al", false, std::string(), false);
642 username_element_.setValue("alices");
643 autofill_agent_->textFieldDidEndEditing(username_element_);
644 CheckTextFieldsState("alices", false, std::string(), false);
645 username_element_.setValue(ASCIIToUTF16(kAliceUsername));
646 autofill_agent_->textFieldDidEndEditing(username_element_);
647 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
648 }
649
650 // Tests that inline autocompletion works properly.
TEST_F(PasswordAutofillAgentTest,InlineAutocomplete)651 TEST_F(PasswordAutofillAgentTest, InlineAutocomplete) {
652 // Simulate the browser sending back the login info.
653 SimulateOnFillPasswordForm(fill_data_);
654
655 // Clear the text fields to start fresh.
656 ClearUsernameAndPasswordFields();
657
658 // Simulate the user typing in the first letter of 'alice', a stored username.
659 SimulateUsernameChange("a", true);
660 // Both the username and password text fields should reflect selection of the
661 // stored login.
662 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
663 // And the selection should have been set to 'lice', the last 4 letters.
664 CheckUsernameSelection(1, 5);
665
666 // Now the user types the next letter of the same username, 'l'.
667 SimulateUsernameChange("al", true);
668 // Now the fields should have the same value, but the selection should have a
669 // different start value.
670 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
671 CheckUsernameSelection(2, 5);
672
673 // Test that deleting does not trigger autocomplete.
674 SimulateKeyDownEvent(username_element_, ui::VKEY_BACK);
675 SimulateUsernameChange("alic", true);
676 CheckTextFieldsState("alic", false, std::string(), false);
677 CheckUsernameSelection(4, 4); // No selection.
678 // Reset the last pressed key to something other than backspace.
679 SimulateKeyDownEvent(username_element_, ui::VKEY_A);
680
681 // Now lets say the user goes astray from the stored username and types the
682 // letter 'f', spelling 'alf'. We don't know alf (that's just sad), so in
683 // practice the username should no longer be 'alice' and the selected range
684 // should be empty.
685 SimulateUsernameChange("alf", true);
686 CheckTextFieldsState("alf", false, std::string(), false);
687 CheckUsernameSelection(3, 3); // No selection.
688
689 // Ok, so now the user removes all the text and enters the letter 'b'.
690 SimulateUsernameChange("b", true);
691 // The username and password fields should match the 'bob' entry.
692 CheckTextFieldsState(kBobUsername, true, kBobPassword, true);
693 CheckUsernameSelection(1, 3);
694
695 // Then, the user again removes all the text and types an uppercase 'C'.
696 SimulateUsernameChange("C", true);
697 // The username and password fields should match the 'Carol' entry.
698 CheckTextFieldsState(kCarolUsername, true, kCarolPassword, true);
699 CheckUsernameSelection(1, 5);
700 // The user removes all the text and types a lowercase 'c'. We only
701 // want case-sensitive autocompletion, so the username and the selected range
702 // should be empty.
703 SimulateUsernameChange("c", true);
704 CheckTextFieldsState("c", false, std::string(), false);
705 CheckUsernameSelection(1, 1);
706
707 // Check that we complete other_possible_usernames as well.
708 SimulateUsernameChange("R", true);
709 CheckTextFieldsState(kCarolAlternateUsername, true, kCarolPassword, true);
710 CheckUsernameSelection(1, 17);
711 }
712
TEST_F(PasswordAutofillAgentTest,IsWebNodeVisibleTest)713 TEST_F(PasswordAutofillAgentTest, IsWebNodeVisibleTest) {
714 blink::WebVector<blink::WebFormElement> forms1, forms2, forms3;
715 blink::WebFrame* frame;
716
717 LoadHTML(kVisibleFormHTML);
718 frame = GetMainFrame();
719 frame->document().forms(forms1);
720 ASSERT_EQ(1u, forms1.size());
721 EXPECT_TRUE(IsWebNodeVisible(forms1[0]));
722
723 LoadHTML(kEmptyFormHTML);
724 frame = GetMainFrame();
725 frame->document().forms(forms2);
726 ASSERT_EQ(1u, forms2.size());
727 EXPECT_FALSE(IsWebNodeVisible(forms2[0]));
728
729 LoadHTML(kNonVisibleFormHTML);
730 frame = GetMainFrame();
731 frame->document().forms(forms3);
732 ASSERT_EQ(1u, forms3.size());
733 EXPECT_FALSE(IsWebNodeVisible(forms3[0]));
734 }
735
TEST_F(PasswordAutofillAgentTest,SendPasswordFormsTest)736 TEST_F(PasswordAutofillAgentTest, SendPasswordFormsTest) {
737 render_thread_->sink().ClearMessages();
738 LoadHTML(kVisibleFormHTML);
739 const IPC::Message* message = render_thread_->sink()
740 .GetFirstMessageMatching(AutofillHostMsg_PasswordFormsRendered::ID);
741 EXPECT_TRUE(message);
742 Tuple1<std::vector<autofill::PasswordForm> > param;
743 AutofillHostMsg_PasswordFormsRendered::Read(message, ¶m);
744 EXPECT_TRUE(param.a.size());
745
746 render_thread_->sink().ClearMessages();
747 LoadHTML(kEmptyFormHTML);
748 message = render_thread_->sink().GetFirstMessageMatching(
749 AutofillHostMsg_PasswordFormsRendered::ID);
750 EXPECT_TRUE(message);
751 AutofillHostMsg_PasswordFormsRendered::Read(message, ¶m);
752 EXPECT_FALSE(param.a.size());
753
754 render_thread_->sink().ClearMessages();
755 LoadHTML(kNonVisibleFormHTML);
756 message = render_thread_->sink().GetFirstMessageMatching(
757 AutofillHostMsg_PasswordFormsRendered::ID);
758 EXPECT_TRUE(message);
759 AutofillHostMsg_PasswordFormsRendered::Read(message, ¶m);
760 EXPECT_FALSE(param.a.size());
761 }
762
TEST_F(PasswordAutofillAgentTest,SendPasswordFormsTest_Redirection)763 TEST_F(PasswordAutofillAgentTest, SendPasswordFormsTest_Redirection) {
764 render_thread_->sink().ClearMessages();
765 LoadHTML(kEmptyWebpage);
766 EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching(
767 AutofillHostMsg_PasswordFormsRendered::ID));
768
769 render_thread_->sink().ClearMessages();
770 LoadHTML(kRedirectionWebpage);
771 EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching(
772 AutofillHostMsg_PasswordFormsRendered::ID));
773
774 render_thread_->sink().ClearMessages();
775 LoadHTML(kSimpleWebpage);
776 EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching(
777 AutofillHostMsg_PasswordFormsRendered::ID));
778
779 render_thread_->sink().ClearMessages();
780 LoadHTML(kWebpageWithDynamicContent);
781 EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching(
782 AutofillHostMsg_PasswordFormsRendered::ID));
783 }
784
785 // Tests that a password form in an iframe will not be filled in until a user
786 // interaction with the form.
TEST_F(PasswordAutofillAgentTest,IframeNoFillTest)787 TEST_F(PasswordAutofillAgentTest, IframeNoFillTest) {
788 const char kIframeName[] = "iframe";
789 const char kWebpageWithIframeStart[] =
790 "<html>"
791 " <head>"
792 " <meta charset='utf-8' />"
793 " <title>Title</title>"
794 " </head>"
795 " <body>"
796 " <iframe name='iframe' src=\"";
797 const char kWebpageWithIframeEnd[] =
798 "\"></iframe>"
799 " </body>"
800 "</html>";
801
802 std::string origin("data:text/html;charset=utf-8,");
803 origin += kSimpleWebpage;
804
805 std::string page_html(kWebpageWithIframeStart);
806 page_html += origin;
807 page_html += kWebpageWithIframeEnd;
808
809 LoadHTML(page_html.c_str());
810
811 // Set the expected form origin and action URLs.
812 fill_data_.basic_data.origin = GURL(origin);
813 fill_data_.basic_data.action = GURL(origin);
814
815 SimulateOnFillPasswordForm(fill_data_);
816
817 // Retrieve the input elements from the iframe since that is where we want to
818 // test the autofill.
819 WebFrame* iframe = GetMainFrame()->findChildByName(kIframeName);
820 ASSERT_TRUE(iframe);
821 WebDocument document = iframe->document();
822
823 WebElement username_element = document.getElementById(kUsernameName);
824 WebElement password_element = document.getElementById(kPasswordName);
825 ASSERT_FALSE(username_element.isNull());
826 ASSERT_FALSE(password_element.isNull());
827
828 WebInputElement username_input = username_element.to<WebInputElement>();
829 WebInputElement password_input = password_element.to<WebInputElement>();
830 ASSERT_FALSE(username_element.isNull());
831
832 CheckTextFieldsStateForElements(username_input, "", false,
833 password_input, "", false);
834
835 // Simulate the user typing in the username in the iframe, which should cause
836 // an autofill.
837 SimulateUsernameChangeForElement(kAliceUsername, true,
838 iframe, username_input);
839
840 CheckTextFieldsStateForElements(username_input, kAliceUsername, true,
841 password_input, kAlicePassword, true);
842 }
843
844 // Tests that a password will only be filled as a suggested and will not be
845 // accessible by the DOM until a user gesture has occurred.
TEST_F(PasswordAutofillAgentTest,GestureRequiredTest)846 TEST_F(PasswordAutofillAgentTest, GestureRequiredTest) {
847 // Trigger the initial autocomplete.
848 SimulateOnFillPasswordForm(fill_data_);
849
850 // The username and password should have been autocompleted.
851 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
852
853 // However, it should only have completed with the suggested value, as tested
854 // above, and it should not have completed into the DOM accessible value for
855 // the password field.
856 CheckTextFieldsDOMState(kAliceUsername, true, std::string(), true);
857
858 // Simulate a user click so that the password field's real value is filled.
859 SimulateElementClick(kUsernameName);
860 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true);
861 }
862
863 // Verfies that a DOM-activated UI event will not cause an autofill.
TEST_F(PasswordAutofillAgentTest,NoDOMActivationTest)864 TEST_F(PasswordAutofillAgentTest, NoDOMActivationTest) {
865 // Trigger the initial autocomplete.
866 SimulateOnFillPasswordForm(fill_data_);
867
868 ExecuteJavaScript(kJavaScriptClick);
869 CheckTextFieldsDOMState(kAliceUsername, true, "", true);
870 }
871
872 // Regression test for http://crbug.com/326679
TEST_F(PasswordAutofillAgentTest,SelectUsernameWithUsernameAutofillOff)873 TEST_F(PasswordAutofillAgentTest, SelectUsernameWithUsernameAutofillOff) {
874 // Simulate the browser sending back the login info.
875 SimulateOnFillPasswordForm(fill_data_);
876
877 // Set the username element to autocomplete='off'
878 username_element_.setAttribute(WebString::fromUTF8("autocomplete"),
879 WebString::fromUTF8("off"));
880
881 // Simulate the user changing the username to some known username.
882 SimulateUsernameChange(kAliceUsername, true);
883
884 ExpectNoSuggestionsPopup();
885 }
886
887 // Regression test for http://crbug.com/326679
TEST_F(PasswordAutofillAgentTest,SelectUnknownUsernameWithUsernameAutofillOff)888 TEST_F(PasswordAutofillAgentTest,
889 SelectUnknownUsernameWithUsernameAutofillOff) {
890 // Simulate the browser sending back the login info.
891 SimulateOnFillPasswordForm(fill_data_);
892
893 // Set the username element to autocomplete='off'
894 username_element_.setAttribute(WebString::fromUTF8("autocomplete"),
895 WebString::fromUTF8("off"));
896
897 // Simulate the user changing the username to some unknown username.
898 SimulateUsernameChange("foo", true);
899
900 ExpectNoSuggestionsPopup();
901 }
902
903 // Regression test for http://crbug.com/326679
TEST_F(PasswordAutofillAgentTest,SelectUsernameWithPasswordAutofillOff)904 TEST_F(PasswordAutofillAgentTest, SelectUsernameWithPasswordAutofillOff) {
905 // Simulate the browser sending back the login info.
906 SimulateOnFillPasswordForm(fill_data_);
907
908 // Set the main password element to autocomplete='off'
909 password_element_.setAttribute(WebString::fromUTF8("autocomplete"),
910 WebString::fromUTF8("off"));
911
912 // Simulate the user changing the username to some known username.
913 SimulateUsernameChange(kAliceUsername, true);
914
915 ExpectNoSuggestionsPopup();
916 }
917
918 // Regression test for http://crbug.com/326679
TEST_F(PasswordAutofillAgentTest,SelectUnknownUsernameWithPasswordAutofillOff)919 TEST_F(PasswordAutofillAgentTest,
920 SelectUnknownUsernameWithPasswordAutofillOff) {
921 // Simulate the browser sending back the login info.
922 SimulateOnFillPasswordForm(fill_data_);
923
924 // Set the main password element to autocomplete='off'
925 password_element_.setAttribute(WebString::fromUTF8("autocomplete"),
926 WebString::fromUTF8("off"));
927
928 // Simulate the user changing the username to some unknown username.
929 SimulateUsernameChange("foo", true);
930
931 ExpectNoSuggestionsPopup();
932 }
933
934 // Verifies that password autofill triggers onChange events in JavaScript for
935 // forms that are filled on page load.
TEST_F(PasswordAutofillAgentTest,PasswordAutofillTriggersOnChangeEventsOnLoad)936 TEST_F(PasswordAutofillAgentTest,
937 PasswordAutofillTriggersOnChangeEventsOnLoad) {
938 std::string html = std::string(kFormHTML) + kOnChangeDetectionScript;
939 LoadHTML(html.c_str());
940 UpdateOriginForHTML(html);
941 UpdateUsernameAndPasswordElements();
942
943 // Simulate the browser sending back the login info, it triggers the
944 // autocomplete.
945 SimulateOnFillPasswordForm(fill_data_);
946
947 // The username and password should have been autocompleted...
948 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
949 // ... but since there hasn't been a user gesture yet, the autocompleted
950 // password should only be visible to the user.
951 CheckTextFieldsDOMState(kAliceUsername, true, std::string(), true);
952
953 // A JavaScript onChange event should have been triggered for the username,
954 // but not yet for the password.
955 int username_onchange_called = -1;
956 int password_onchange_called = -1;
957 ASSERT_TRUE(
958 ExecuteJavaScriptAndReturnIntValue(
959 ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"),
960 &username_onchange_called));
961 EXPECT_EQ(1, username_onchange_called);
962 ASSERT_TRUE(
963 ExecuteJavaScriptAndReturnIntValue(
964 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"),
965 &password_onchange_called));
966 // TODO(isherman): Re-enable this check once http://crbug.com/333144 is fixed.
967 // EXPECT_EQ(0, password_onchange_called);
968
969 // Simulate a user click so that the password field's real value is filled.
970 SimulateElementClick(kUsernameName);
971 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true);
972
973 // Now, a JavaScript onChange event should have been triggered for the
974 // password as well.
975 ASSERT_TRUE(
976 ExecuteJavaScriptAndReturnIntValue(
977 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"),
978 &password_onchange_called));
979 EXPECT_EQ(1, password_onchange_called);
980 }
981
982 // Verifies that password autofill triggers onChange events in JavaScript for
983 // forms that are filled after page load.
TEST_F(PasswordAutofillAgentTest,PasswordAutofillTriggersOnChangeEventsWaitForUsername)984 TEST_F(PasswordAutofillAgentTest,
985 PasswordAutofillTriggersOnChangeEventsWaitForUsername) {
986 std::string html = std::string(kFormHTML) + kOnChangeDetectionScript;
987 LoadHTML(html.c_str());
988 UpdateOriginForHTML(html);
989 UpdateUsernameAndPasswordElements();
990
991 // Simulate the browser sending back the login info, it triggers the
992 // autocomplete.
993 fill_data_.wait_for_username = true;
994 SimulateOnFillPasswordForm(fill_data_);
995
996 // The username and password should not yet have been autocompleted.
997 CheckTextFieldsState(std::string(), false, std::string(), false);
998
999 // Simulate a click just to force a user gesture, since the username value is
1000 // set directly.
1001 SimulateElementClick(kUsernameName);
1002
1003 // Simulate the user entering her username.
1004 username_element_.setValue(ASCIIToUTF16(kAliceUsername), true);
1005 autofill_agent_->textFieldDidEndEditing(username_element_);
1006
1007 // The username and password should now have been autocompleted.
1008 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true);
1009
1010 // JavaScript onChange events should have been triggered both for the username
1011 // and for the password.
1012 int username_onchange_called = -1;
1013 int password_onchange_called = -1;
1014 ASSERT_TRUE(
1015 ExecuteJavaScriptAndReturnIntValue(
1016 ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"),
1017 &username_onchange_called));
1018 EXPECT_EQ(1, username_onchange_called);
1019 ASSERT_TRUE(
1020 ExecuteJavaScriptAndReturnIntValue(
1021 ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"),
1022 &password_onchange_called));
1023 EXPECT_EQ(1, password_onchange_called);
1024 }
1025
1026 // Tests that |FillSuggestion| properly fills the username and password.
TEST_F(PasswordAutofillAgentTest,FillSuggestion)1027 TEST_F(PasswordAutofillAgentTest, FillSuggestion) {
1028 // Simulate the browser sending the login info, but set |wait_for_username|
1029 // to prevent the form from being immediately filled.
1030 fill_data_.wait_for_username = true;
1031 SimulateOnFillPasswordForm(fill_data_);
1032
1033 // Neither field should have been autocompleted.
1034 CheckTextFieldsDOMState(std::string(), false, std::string(), false);
1035
1036 // If the password field is not autocompletable, it should not be affected.
1037 SetElementReadOnly(password_element_, true);
1038 EXPECT_FALSE(password_autofill_->FillSuggestion(
1039 username_element_, kAliceUsername, kAlicePassword));
1040 CheckTextFieldsDOMState(std::string(), false, std::string(), false);
1041 SetElementReadOnly(password_element_, false);
1042
1043 // After filling with the suggestion, both fields should be autocompleted.
1044 EXPECT_TRUE(password_autofill_->FillSuggestion(
1045 username_element_, kAliceUsername, kAlicePassword));
1046 CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true);
1047 int username_length = strlen(kAliceUsername);
1048 CheckUsernameSelection(username_length, username_length);
1049
1050 // Try Filling with a suggestion with password different from the one that was
1051 // initially sent to the renderer.
1052 EXPECT_TRUE(password_autofill_->FillSuggestion(
1053 username_element_, kBobUsername, kCarolPassword));
1054 CheckTextFieldsDOMState(kBobUsername, true, kCarolPassword, true);
1055 username_length = strlen(kBobUsername);
1056 CheckUsernameSelection(username_length, username_length);
1057 }
1058
1059 // Tests that |PreviewSuggestion| properly previews the username and password.
TEST_F(PasswordAutofillAgentTest,PreviewSuggestion)1060 TEST_F(PasswordAutofillAgentTest, PreviewSuggestion) {
1061 // Simulate the browser sending the login info, but set |wait_for_username|
1062 // to prevent the form from being immediately filled.
1063 fill_data_.wait_for_username = true;
1064 SimulateOnFillPasswordForm(fill_data_);
1065
1066 // Neither field should have been autocompleted.
1067 CheckTextFieldsDOMState(std::string(), false, std::string(), false);
1068
1069 // If the password field is not autocompletable, it should not be affected.
1070 SetElementReadOnly(password_element_, true);
1071 EXPECT_FALSE(password_autofill_->PreviewSuggestion(
1072 username_element_, kAliceUsername, kAlicePassword));
1073 EXPECT_EQ(std::string(), username_element_.suggestedValue().utf8());
1074 EXPECT_FALSE(username_element_.isAutofilled());
1075 EXPECT_EQ(std::string(), password_element_.suggestedValue().utf8());
1076 EXPECT_FALSE(password_element_.isAutofilled());
1077 SetElementReadOnly(password_element_, false);
1078
1079 // After selecting the suggestion, both fields should be previewed
1080 // with suggested values.
1081 EXPECT_TRUE(password_autofill_->PreviewSuggestion(
1082 username_element_, kAliceUsername, kAlicePassword));
1083 EXPECT_EQ(
1084 kAliceUsername,
1085 static_cast<std::string>(username_element_.suggestedValue().utf8()));
1086 EXPECT_TRUE(username_element_.isAutofilled());
1087 EXPECT_EQ(
1088 kAlicePassword,
1089 static_cast<std::string>(password_element_.suggestedValue().utf8()));
1090 EXPECT_TRUE(password_element_.isAutofilled());
1091 int username_length = strlen(kAliceUsername);
1092 CheckUsernameSelection(0, username_length);
1093
1094 // Try previewing with a password different from the one that was initially
1095 // sent to the renderer.
1096 EXPECT_TRUE(password_autofill_->PreviewSuggestion(
1097 username_element_, kBobUsername, kCarolPassword));
1098 EXPECT_EQ(
1099 kBobUsername,
1100 static_cast<std::string>(username_element_.suggestedValue().utf8()));
1101 EXPECT_TRUE(username_element_.isAutofilled());
1102 EXPECT_EQ(
1103 kCarolPassword,
1104 static_cast<std::string>(password_element_.suggestedValue().utf8()));
1105 EXPECT_TRUE(password_element_.isAutofilled());
1106 username_length = strlen(kBobUsername);
1107 CheckUsernameSelection(0, username_length);
1108 }
1109
1110 // Tests that |PreviewSuggestion| properly sets the username selection range.
TEST_F(PasswordAutofillAgentTest,PreviewSuggestionSelectionRange)1111 TEST_F(PasswordAutofillAgentTest, PreviewSuggestionSelectionRange) {
1112 username_element_.setValue(WebString::fromUTF8("ali"));
1113 username_element_.setAutofilled(true);
1114
1115 CheckTextFieldsDOMState("ali", true, std::string(), false);
1116
1117 // Simulate the browser sending the login info, but set |wait_for_username|
1118 // to prevent the form from being immediately filled.
1119 fill_data_.wait_for_username = true;
1120 SimulateOnFillPasswordForm(fill_data_);
1121
1122 EXPECT_TRUE(password_autofill_->PreviewSuggestion(
1123 username_element_, kAliceUsername, kAlicePassword));
1124 EXPECT_EQ(
1125 kAliceUsername,
1126 static_cast<std::string>(username_element_.suggestedValue().utf8()));
1127 EXPECT_TRUE(username_element_.isAutofilled());
1128 EXPECT_EQ(
1129 kAlicePassword,
1130 static_cast<std::string>(password_element_.suggestedValue().utf8()));
1131 EXPECT_TRUE(password_element_.isAutofilled());
1132 int username_length = strlen(kAliceUsername);
1133 CheckUsernameSelection(3, username_length);
1134 }
1135
1136 // Tests that |ClearPreview| properly clears previewed username and password
1137 // with password being previously autofilled.
TEST_F(PasswordAutofillAgentTest,ClearPreviewWithPasswordAutofilled)1138 TEST_F(PasswordAutofillAgentTest, ClearPreviewWithPasswordAutofilled) {
1139 password_element_.setValue(WebString::fromUTF8("sec"));
1140 password_element_.setAutofilled(true);
1141
1142 // Simulate the browser sending the login info, but set |wait_for_username|
1143 // to prevent the form from being immediately filled.
1144 fill_data_.wait_for_username = true;
1145 SimulateOnFillPasswordForm(fill_data_);
1146
1147 CheckTextFieldsDOMState(std::string(), false, "sec", true);
1148
1149 EXPECT_TRUE(password_autofill_->PreviewSuggestion(
1150 username_element_, kAliceUsername, kAlicePassword));
1151
1152 EXPECT_TRUE(password_autofill_->DidClearAutofillSelection(
1153 username_element_));
1154
1155 EXPECT_TRUE(username_element_.value().isEmpty());
1156 EXPECT_TRUE(username_element_.suggestedValue().isEmpty());
1157 EXPECT_FALSE(username_element_.isAutofilled());
1158 EXPECT_EQ(ASCIIToUTF16("sec"), password_element_.value());
1159 EXPECT_TRUE(password_element_.suggestedValue().isEmpty());
1160 EXPECT_TRUE(password_element_.isAutofilled());
1161 CheckUsernameSelection(0, 0);
1162 }
1163
1164 // Tests that |ClearPreview| properly clears previewed username and password
1165 // with username being previously autofilled.
TEST_F(PasswordAutofillAgentTest,ClearPreviewWithUsernameAutofilled)1166 TEST_F(PasswordAutofillAgentTest, ClearPreviewWithUsernameAutofilled) {
1167 username_element_.setValue(WebString::fromUTF8("ali"));
1168 username_element_.setAutofilled(true);
1169
1170 // Simulate the browser sending the login info, but set |wait_for_username|
1171 // to prevent the form from being immediately filled.
1172 fill_data_.wait_for_username = true;
1173 SimulateOnFillPasswordForm(fill_data_);
1174
1175 CheckTextFieldsDOMState("ali", true, std::string(), false);
1176
1177 EXPECT_TRUE(password_autofill_->PreviewSuggestion(
1178 username_element_, kAliceUsername, kAlicePassword));
1179
1180 EXPECT_TRUE(password_autofill_->DidClearAutofillSelection(
1181 username_element_));
1182
1183 EXPECT_EQ(ASCIIToUTF16("ali"), username_element_.value());
1184 EXPECT_TRUE(username_element_.suggestedValue().isEmpty());
1185 EXPECT_TRUE(username_element_.isAutofilled());
1186 EXPECT_TRUE(password_element_.value().isEmpty());
1187 EXPECT_TRUE(password_element_.suggestedValue().isEmpty());
1188 EXPECT_FALSE(password_element_.isAutofilled());
1189 CheckUsernameSelection(3, 3);
1190 }
1191
1192 // Tests that |ClearPreview| properly clears previewed username and password
1193 // with username and password being previously autofilled.
TEST_F(PasswordAutofillAgentTest,ClearPreviewWithAutofilledUsernameAndPassword)1194 TEST_F(PasswordAutofillAgentTest,
1195 ClearPreviewWithAutofilledUsernameAndPassword) {
1196 username_element_.setValue(WebString::fromUTF8("ali"));
1197 username_element_.setAutofilled(true);
1198 password_element_.setValue(WebString::fromUTF8("sec"));
1199 password_element_.setAutofilled(true);
1200
1201 // Simulate the browser sending the login info, but set |wait_for_username|
1202 // to prevent the form from being immediately filled.
1203 fill_data_.wait_for_username = true;
1204 SimulateOnFillPasswordForm(fill_data_);
1205
1206 CheckTextFieldsDOMState("ali", true, "sec", true);
1207
1208 EXPECT_TRUE(password_autofill_->PreviewSuggestion(
1209 username_element_, kAliceUsername, kAlicePassword));
1210
1211 EXPECT_TRUE(password_autofill_->DidClearAutofillSelection(
1212 username_element_));
1213
1214 EXPECT_EQ(ASCIIToUTF16("ali"), username_element_.value());
1215 EXPECT_TRUE(username_element_.suggestedValue().isEmpty());
1216 EXPECT_TRUE(username_element_.isAutofilled());
1217 EXPECT_EQ(ASCIIToUTF16("sec"), password_element_.value());
1218 EXPECT_TRUE(password_element_.suggestedValue().isEmpty());
1219 EXPECT_TRUE(password_element_.isAutofilled());
1220 CheckUsernameSelection(3, 3);
1221 }
1222
1223 // Tests that |ClearPreview| properly clears previewed username and password
1224 // with neither username nor password being previously autofilled.
TEST_F(PasswordAutofillAgentTest,ClearPreviewWithNotAutofilledUsernameAndPassword)1225 TEST_F(PasswordAutofillAgentTest,
1226 ClearPreviewWithNotAutofilledUsernameAndPassword) {
1227 // Simulate the browser sending the login info, but set |wait_for_username|
1228 // to prevent the form from being immediately filled.
1229 fill_data_.wait_for_username = true;
1230 SimulateOnFillPasswordForm(fill_data_);
1231
1232 CheckTextFieldsDOMState(std::string(), false, std::string(), false);
1233
1234 EXPECT_TRUE(password_autofill_->PreviewSuggestion(
1235 username_element_, kAliceUsername, kAlicePassword));
1236
1237 EXPECT_TRUE(password_autofill_->DidClearAutofillSelection(
1238 username_element_));
1239
1240 EXPECT_TRUE(username_element_.value().isEmpty());
1241 EXPECT_TRUE(username_element_.suggestedValue().isEmpty());
1242 EXPECT_FALSE(username_element_.isAutofilled());
1243 EXPECT_TRUE(password_element_.value().isEmpty());
1244 EXPECT_TRUE(password_element_.suggestedValue().isEmpty());
1245 EXPECT_FALSE(password_element_.isAutofilled());
1246 CheckUsernameSelection(0, 0);
1247 }
1248
1249 // Tests that |ClearPreview| properly restores the original selection range of
1250 // username field that has initially been filled by inline autocomplete.
TEST_F(PasswordAutofillAgentTest,ClearPreviewWithInlineAutocompletedUsername)1251 TEST_F(PasswordAutofillAgentTest, ClearPreviewWithInlineAutocompletedUsername) {
1252 // Simulate the browser sending back the login info.
1253 SimulateOnFillPasswordForm(fill_data_);
1254
1255 // Clear the text fields to start fresh.
1256 ClearUsernameAndPasswordFields();
1257
1258 // Simulate the user typing in the first letter of 'alice', a stored username.
1259 SimulateUsernameChange("a", true);
1260 // Both the username and password text fields should reflect selection of the
1261 // stored login.
1262 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
1263 // The selection should have been set to 'lice', the last 4 letters.
1264 CheckUsernameSelection(1, 5);
1265
1266 EXPECT_TRUE(password_autofill_->PreviewSuggestion(
1267 username_element_, "alicia", "secret"));
1268 EXPECT_EQ(
1269 "alicia",
1270 static_cast<std::string>(username_element_.suggestedValue().utf8()));
1271 EXPECT_TRUE(username_element_.isAutofilled());
1272 EXPECT_EQ(
1273 "secret",
1274 static_cast<std::string>(password_element_.suggestedValue().utf8()));
1275 EXPECT_TRUE(password_element_.isAutofilled());
1276 CheckUsernameSelection(1, 6);
1277
1278 EXPECT_TRUE(password_autofill_->DidClearAutofillSelection(
1279 username_element_));
1280
1281 EXPECT_EQ(kAliceUsername, username_element_.value().utf8());
1282 EXPECT_TRUE(username_element_.suggestedValue().isEmpty());
1283 EXPECT_TRUE(username_element_.isAutofilled());
1284 EXPECT_TRUE(password_element_.value().isEmpty());
1285 EXPECT_TRUE(password_element_.suggestedValue().isEmpty());
1286 EXPECT_TRUE(password_element_.isAutofilled());
1287 CheckUsernameSelection(1, 5);
1288 }
1289
1290 // Tests that logging is off by default.
TEST_F(PasswordAutofillAgentTest,OnChangeLoggingState_NoMessage)1291 TEST_F(PasswordAutofillAgentTest, OnChangeLoggingState_NoMessage) {
1292 render_thread_->sink().ClearMessages();
1293 SendVisiblePasswordForms();
1294 const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching(
1295 AutofillHostMsg_RecordSavePasswordProgress::ID);
1296 EXPECT_FALSE(message);
1297 }
1298
1299 // Test that logging can be turned on by a message.
TEST_F(PasswordAutofillAgentTest,OnChangeLoggingState_Activated)1300 TEST_F(PasswordAutofillAgentTest, OnChangeLoggingState_Activated) {
1301 // Turn the logging on.
1302 AutofillMsg_SetLoggingState msg_activate(0, true);
1303 // Up-cast to access OnMessageReceived, which is private in the agent.
1304 EXPECT_TRUE(static_cast<IPC::Listener*>(password_autofill_)
1305 ->OnMessageReceived(msg_activate));
1306
1307 render_thread_->sink().ClearMessages();
1308 SendVisiblePasswordForms();
1309 const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching(
1310 AutofillHostMsg_RecordSavePasswordProgress::ID);
1311 EXPECT_TRUE(message);
1312 }
1313
1314 // Test that logging can be turned off by a message.
TEST_F(PasswordAutofillAgentTest,OnChangeLoggingState_Deactivated)1315 TEST_F(PasswordAutofillAgentTest, OnChangeLoggingState_Deactivated) {
1316 // Turn the logging on and then off.
1317 AutofillMsg_SetLoggingState msg_activate(0, /*active=*/true);
1318 // Up-cast to access OnMessageReceived, which is private in the agent.
1319 EXPECT_TRUE(static_cast<IPC::Listener*>(password_autofill_)
1320 ->OnMessageReceived(msg_activate));
1321 AutofillMsg_SetLoggingState msg_deactivate(0, /*active=*/false);
1322 EXPECT_TRUE(static_cast<IPC::Listener*>(password_autofill_)
1323 ->OnMessageReceived(msg_deactivate));
1324
1325 render_thread_->sink().ClearMessages();
1326 SendVisiblePasswordForms();
1327 const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching(
1328 AutofillHostMsg_RecordSavePasswordProgress::ID);
1329 EXPECT_FALSE(message);
1330 }
1331
1332 // Test that the agent sends an IPC call to get the current activity state of
1333 // password saving logging soon after construction.
TEST_F(PasswordAutofillAgentTest,SendsLoggingStateUpdatePingOnConstruction)1334 TEST_F(PasswordAutofillAgentTest, SendsLoggingStateUpdatePingOnConstruction) {
1335 const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching(
1336 AutofillHostMsg_PasswordAutofillAgentConstructed::ID);
1337 EXPECT_TRUE(message);
1338 }
1339
1340 } // namespace autofill
1341