Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / renderer / autofill / password_autofill_agent_browsertest.cc
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/WebFrame.h"
23 #include "third_party/WebKit/public/web/WebInputElement.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
53 const char kFormHTML[] =
54     "<FORM name='LoginTestForm' action='http://www.bidule.com'>"
55     "  <INPUT type='text' id='username'/>"
56     "  <INPUT type='password' id='password'/>"
57     "  <INPUT type='submit' value='Login'/>"
58     "</FORM>";
59
60 const char kVisibleFormHTML[] =
61     "<head> <style> form {display: inline;} </style> </head>"
62     "<body>"
63     "  <form>"
64     "    <div>"
65     "      <input type='password' id='password'/>"
66     "    </div>"
67     "  </form>"
68     "</body>";
69
70 const char kEmptyFormHTML[] =
71     "<head> <style> form {display: inline;} </style> </head>"
72     "<body> <form> </form> </body>";
73
74 const char kNonVisibleFormHTML[] =
75     "<head> <style> form {display: none;} </style> </head>"
76     "<body>"
77     "  <form>"
78     "    <div>"
79     "      <input type='password' id='password'/>"
80     "    </div>"
81     "  </form>"
82     "</body>";
83
84 const char kEmptyWebpage[] =
85     "<html>"
86     "   <head>"
87     "   </head>"
88     "   <body>"
89     "   </body>"
90     "</html>";
91
92 const char kRedirectionWebpage[] =
93     "<html>"
94     "   <head>"
95     "       <meta http-equiv='Content-Type' content='text/html'>"
96     "       <title>Redirection page</title>"
97     "       <script></script>"
98     "   </head>"
99     "   <body>"
100     "       <script type='text/javascript'>"
101     "         function test(){}"
102     "       </script>"
103     "   </body>"
104     "</html>";
105
106 const char kSimpleWebpage[] =
107     "<html>"
108     "   <head>"
109     "       <meta charset='utf-8' />"
110     "       <title>Title</title>"
111     "   </head>"
112     "   <body>"
113     "       <form name='LoginTestForm'>"
114     "           <input type='text' id='username'/>"
115     "           <input type='password' id='password'/>"
116     "           <input type='submit' value='Login'/>"
117     "       </form>"
118     "   </body>"
119     "</html>";
120
121 const char kWebpageWithDynamicContent[] =
122     "<html>"
123     "   <head>"
124     "       <meta charset='utf-8' />"
125     "       <title>Title</title>"
126     "   </head>"
127     "   <body>"
128     "       <script type='text/javascript'>"
129     "           function addParagraph() {"
130     "             var p = document.createElement('p');"
131     "             document.body.appendChild(p);"
132     "            }"
133     "           window.onload = addParagraph;"
134     "       </script>"
135     "   </body>"
136     "</html>";
137
138 const char kJavaScriptClick[] =
139     "var event = new MouseEvent('click', {"
140     "   'view': window,"
141     "   'bubbles': true,"
142     "   'cancelable': true"
143     "});"
144     "var form = document.getElementById('myform1');"
145     "form.dispatchEvent(event);"
146     "console.log('clicked!');";
147
148 const char kOnChangeDetectionScript[] =
149     "<script>"
150     "  usernameOnchangeCalled = false;"
151     "  passwordOnchangeCalled = false;"
152     "  document.getElementById('username').onchange = function() {"
153     "    usernameOnchangeCalled = true;"
154     "  };"
155     "  document.getElementById('password').onchange = function() {"
156     "    passwordOnchangeCalled = true;"
157     "  };"
158     "</script>";
159
160 }  // namespace
161
162 namespace autofill {
163
164 class PasswordAutofillAgentTest : public ChromeRenderViewTest {
165  public:
166   PasswordAutofillAgentTest() {
167   }
168
169   // Simulates the fill password form message being sent to the renderer.
170   // We use that so we don't have to make RenderView::OnFillPasswordForm()
171   // protected.
172   void SimulateOnFillPasswordForm(
173       const PasswordFormFillData& fill_data) {
174     AutofillMsg_FillPasswordForm msg(0, fill_data);
175     password_autofill_->OnMessageReceived(msg);
176   }
177
178   virtual void SetUp() {
179     ChromeRenderViewTest::SetUp();
180
181     // Add a preferred login and an additional login to the FillData.
182     username1_ = ASCIIToUTF16(kAliceUsername);
183     password1_ = ASCIIToUTF16(kAlicePassword);
184     username2_ = ASCIIToUTF16(kBobUsername);
185     password2_ = ASCIIToUTF16(kBobPassword);
186     username3_ = ASCIIToUTF16(kCarolUsername);
187     password3_ = ASCIIToUTF16(kCarolPassword);
188     alternate_username3_ = ASCIIToUTF16(kCarolAlternateUsername);
189
190     FormFieldData username_field;
191     username_field.name = ASCIIToUTF16(kUsernameName);
192     username_field.value = username1_;
193     fill_data_.basic_data.fields.push_back(username_field);
194
195     FormFieldData password_field;
196     password_field.name = ASCIIToUTF16(kPasswordName);
197     password_field.value = password1_;
198     password_field.form_control_type = "password";
199     fill_data_.basic_data.fields.push_back(password_field);
200
201     PasswordAndRealm password2;
202     password2.password = password2_;
203     fill_data_.additional_logins[username2_] = password2;
204     PasswordAndRealm password3;
205     password3.password = password3_;
206     fill_data_.additional_logins[username3_] = password3;
207
208     UsernamesCollectionKey key;
209     key.username = username3_;
210     key.password = password3_;
211     key.realm = "google.com";
212     fill_data_.other_possible_usernames[key].push_back(alternate_username3_);
213
214     // We need to set the origin so it matches the frame URL and the action so
215     // it matches the form action, otherwise we won't autocomplete.
216     UpdateOriginForHTML(kFormHTML);
217     fill_data_.basic_data.action = GURL("http://www.bidule.com");
218
219     LoadHTML(kFormHTML);
220
221     // Now retrieve the input elements so the test can access them.
222     UpdateUsernameAndPasswordElements();
223   }
224
225   virtual void TearDown() {
226     username_element_.reset();
227     password_element_.reset();
228     ChromeRenderViewTest::TearDown();
229   }
230
231   void UpdateOriginForHTML(const std::string& html) {
232     std::string origin = "data:text/html;charset=utf-8," + html;
233     fill_data_.basic_data.origin = GURL(origin);
234   }
235
236   void UpdateUsernameAndPasswordElements() {
237     WebDocument document = GetMainFrame()->document();
238     WebElement element =
239         document.getElementById(WebString::fromUTF8(kUsernameName));
240     ASSERT_FALSE(element.isNull());
241     username_element_ = element.to<blink::WebInputElement>();
242     element = document.getElementById(WebString::fromUTF8(kPasswordName));
243     ASSERT_FALSE(element.isNull());
244     password_element_ = element.to<blink::WebInputElement>();
245   }
246
247   void ClearUsernameAndPasswordFields() {
248     username_element_.setValue("");
249     username_element_.setAutofilled(false);
250     password_element_.setValue("");
251     password_element_.setAutofilled(false);
252   }
253
254   void SimulateUsernameChangeForElement(const std::string& username,
255                                         bool move_caret_to_end,
256                                         WebFrame* input_frame,
257                                         WebInputElement& username_input) {
258     username_input.setValue(WebString::fromUTF8(username));
259     // The field must have focus or AutofillAgent will think the
260     // change should be ignored.
261     while (!username_input.focused())
262       input_frame->document().frame()->view()->advanceFocus(false);
263     if (move_caret_to_end)
264       username_input.setSelectionRange(username.length(), username.length());
265     autofill_agent_->textFieldDidChange(username_input);
266     // Processing is delayed because of a Blink bug:
267     // https://bugs.webkit.org/show_bug.cgi?id=16976
268     // See PasswordAutofillAgent::TextDidChangeInTextField() for details.
269
270     // Autocomplete will trigger a style recalculation when we put up the next
271     // frame, but we don't want to wait that long. Instead, trigger a style
272     // recalcuation manually after TextFieldDidChangeImpl runs.
273     base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
274         &PasswordAutofillAgentTest::LayoutMainFrame, base::Unretained(this)));
275
276     base::MessageLoop::current()->RunUntilIdle();
277   }
278
279   void LayoutMainFrame() {
280     GetMainFrame()->view()->layout();
281   }
282
283   void SimulateUsernameChange(const std::string& username,
284                               bool move_caret_to_end) {
285     SimulateUsernameChangeForElement(username, move_caret_to_end,
286                                      GetMainFrame(), username_element_);
287   }
288
289   // Tests that no suggestion popup is generated when the username_element_ is
290   // edited.
291   void ExpectNoSuggestionsPopup() {
292     // The first test below ensures that the suggestions have been handled by
293     // the password_autofill_agent, even though autocomplete='off' is set. The
294     // second check ensures that, although handled, no "show suggestions" IPC to
295     // the browser was generated.
296     //
297     // This is interesting in the specific case of an autocomplete='off' form
298     // that also has a remembered username and password
299     // (http://crbug.com/326679). To fix the DCHECK that this case used to hit,
300     // |true| is returned from ShowSuggestions for all forms with valid
301     // usersnames that are autocomplete='off', prentending that a selection box
302     // has been shown to the user. Of course, it hasn't, so a message is never
303     // sent to the browser on acceptance, and the DCHECK isn't hit (and nothing
304     // is filled).
305     //
306     // These tests only make sense in the context of not ignoring
307     // autocomplete='off', so only test them if the disable autocomplete='off'
308     // flag is not enabled.
309     // TODO(jww): Remove this function and callers once autocomplete='off' is
310     // permanently ignored.
311     if (!ShouldIgnoreAutocompleteOffForPasswordFields()) {
312       EXPECT_TRUE(autofill_agent_->password_autofill_agent_->ShowSuggestions(
313           username_element_));
314
315       EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching(
316           AutofillHostMsg_ShowPasswordSuggestions::ID));
317     }
318   }
319
320   void SimulateKeyDownEvent(const WebInputElement& element,
321                             ui::KeyboardCode key_code) {
322     blink::WebKeyboardEvent key_event;
323     key_event.windowsKeyCode = key_code;
324     autofill_agent_->textFieldDidReceiveKeyDown(element, key_event);
325   }
326
327   void CheckTextFieldsStateForElements(const WebInputElement& username_element,
328                                        const std::string& username,
329                                        bool username_autofilled,
330                                        const WebInputElement& password_element,
331                                        const std::string& password,
332                                        bool password_autofilled,
333                                        bool checkSuggestedValue = true) {
334     EXPECT_EQ(username,
335               static_cast<std::string>(username_element.value().utf8()));
336     EXPECT_EQ(username_autofilled, username_element.isAutofilled());
337     EXPECT_EQ(password,
338               static_cast<std::string>(
339                   checkSuggestedValue ? password_element.suggestedValue().utf8()
340                                       : password_element.value().utf8()));
341     EXPECT_EQ(password_autofilled, password_element.isAutofilled());
342   }
343
344   // Checks the DOM-accessible value of the username element and the
345   // *suggested* value of the password element.
346   void CheckTextFieldsState(const std::string& username,
347                             bool username_autofilled,
348                             const std::string& password,
349                             bool password_autofilled) {
350     CheckTextFieldsStateForElements(username_element_, username,
351                                     username_autofilled, password_element_,
352                                     password, password_autofilled);
353   }
354
355   // Checks the DOM-accessible value of the username element and the
356   // DOM-accessible value of the password element.
357   void CheckTextFieldsDOMState(const std::string& username,
358                                bool username_autofilled,
359                                const std::string& password,
360                                bool password_autofilled) {
361     CheckTextFieldsStateForElements(username_element_,
362                                     username,
363                                     username_autofilled,
364                                     password_element_,
365                                     password,
366                                     password_autofilled,
367                                     false);
368   }
369
370   void CheckUsernameSelection(int start, int end) {
371     EXPECT_EQ(start, username_element_.selectionStart());
372     EXPECT_EQ(end, username_element_.selectionEnd());
373   }
374
375   base::string16 username1_;
376   base::string16 username2_;
377   base::string16 username3_;
378   base::string16 password1_;
379   base::string16 password2_;
380   base::string16 password3_;
381   base::string16 alternate_username3_;
382   PasswordFormFillData fill_data_;
383
384   WebInputElement username_element_;
385   WebInputElement password_element_;
386
387  private:
388   DISALLOW_COPY_AND_ASSIGN(PasswordAutofillAgentTest);
389 };
390
391 // Tests that the password login is autocompleted as expected when the browser
392 // sends back the password info.
393 TEST_F(PasswordAutofillAgentTest, InitialAutocomplete) {
394   /*
395    * Right now we are not sending the message to the browser because we are
396    * loading a data URL and the security origin canAccessPasswordManager()
397    * returns false.  May be we should mock URL loading to cirmcuvent this?
398    TODO(jcivelli): find a way to make the security origin not deny access to the
399                    password manager and then reenable this code.
400
401   // The form has been loaded, we should have sent the browser a message about
402   // the form.
403   const IPC::Message* msg = render_thread_.sink().GetFirstMessageMatching(
404       AutofillHostMsg_PasswordFormsParsed::ID);
405   ASSERT_TRUE(msg != NULL);
406
407   Tuple1<std::vector<PasswordForm> > forms;
408   AutofillHostMsg_PasswordFormsParsed::Read(msg, &forms);
409   ASSERT_EQ(1U, forms.a.size());
410   PasswordForm password_form = forms.a[0];
411   EXPECT_EQ(PasswordForm::SCHEME_HTML, password_form.scheme);
412   EXPECT_EQ(ASCIIToUTF16(kUsernameName), password_form.username_element);
413   EXPECT_EQ(ASCIIToUTF16(kPasswordName), password_form.password_element);
414   */
415
416   // Simulate the browser sending back the login info, it triggers the
417   // autocomplete.
418   SimulateOnFillPasswordForm(fill_data_);
419
420   // The username and password should have been autocompleted.
421   CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
422 }
423
424 // Tests that we correctly fill forms having an empty 'action' attribute.
425 TEST_F(PasswordAutofillAgentTest, InitialAutocompleteForEmptyAction) {
426   const char kEmptyActionFormHTML[] =
427       "<FORM name='LoginTestForm'>"
428       "  <INPUT type='text' id='username'/>"
429       "  <INPUT type='password' id='password'/>"
430       "  <INPUT type='submit' value='Login'/>"
431       "</FORM>";
432   LoadHTML(kEmptyActionFormHTML);
433
434   // Retrieve the input elements so the test can access them.
435   WebDocument document = GetMainFrame()->document();
436   WebElement element =
437       document.getElementById(WebString::fromUTF8(kUsernameName));
438   ASSERT_FALSE(element.isNull());
439   username_element_ = element.to<blink::WebInputElement>();
440   element = document.getElementById(WebString::fromUTF8(kPasswordName));
441   ASSERT_FALSE(element.isNull());
442   password_element_ = element.to<blink::WebInputElement>();
443
444   // Set the expected form origin and action URLs.
445   UpdateOriginForHTML(kEmptyActionFormHTML);
446   fill_data_.basic_data.action = fill_data_.basic_data.origin;
447
448   // Simulate the browser sending back the login info, it triggers the
449   // autocomplete.
450   SimulateOnFillPasswordForm(fill_data_);
451
452   // The username and password should have been autocompleted.
453   CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
454 }
455
456 // Tests that if a password is marked as readonly, neither field is autofilled
457 // on page load.
458 TEST_F(PasswordAutofillAgentTest, NoInitialAutocompleteForReadOnlyPassword) {
459   password_element_.setAttribute(WebString::fromUTF8("readonly"),
460                                  WebString::fromUTF8("true"));
461
462   // Simulate the browser sending back the login info, it triggers the
463   // autocomplete.
464   SimulateOnFillPasswordForm(fill_data_);
465
466   CheckTextFieldsState(std::string(), false, std::string(), false);
467 }
468
469 // Can still fill a password field if the username is set to a value that
470 // matches.
471 TEST_F(PasswordAutofillAgentTest,
472        AutocompletePasswordForReadonlyUsernameMatched) {
473   username_element_.setValue(username3_);
474   username_element_.setAttribute(WebString::fromUTF8("readonly"),
475                                  WebString::fromUTF8("true"));
476
477   // Filled even though username is not the preferred match.
478   SimulateOnFillPasswordForm(fill_data_);
479   CheckTextFieldsState(UTF16ToUTF8(username3_), false,
480                        UTF16ToUTF8(password3_), true);
481 }
482
483 // If a username field is empty and readonly, don't autofill.
484 TEST_F(PasswordAutofillAgentTest,
485        NoAutocompletePasswordForReadonlyUsernameUnmatched) {
486   username_element_.setValue(WebString::fromUTF8(""));
487   username_element_.setAttribute(WebString::fromUTF8("readonly"),
488                                  WebString::fromUTF8("true"));
489
490   SimulateOnFillPasswordForm(fill_data_);
491   CheckTextFieldsState(std::string(), false, std::string(), false);
492 }
493
494 // Tests that having a non-matching username precludes the autocomplete.
495 TEST_F(PasswordAutofillAgentTest, NoAutocompleteForFilledFieldUnmatched) {
496   username_element_.setValue(WebString::fromUTF8("bogus"));
497
498   // Simulate the browser sending back the login info, it triggers the
499   // autocomplete.
500   SimulateOnFillPasswordForm(fill_data_);
501
502   // Neither field should be autocompleted.
503   CheckTextFieldsState("bogus", false, std::string(), false);
504 }
505
506 // Don't try to complete a prefilled value even if it's a partial match
507 // to a username.
508 TEST_F(PasswordAutofillAgentTest, NoPartialMatchForPrefilledUsername) {
509   username_element_.setValue(WebString::fromUTF8("ali"));
510
511   SimulateOnFillPasswordForm(fill_data_);
512
513   CheckTextFieldsState("ali", false, std::string(), false);
514 }
515
516 TEST_F(PasswordAutofillAgentTest, InputWithNoForms) {
517   const char kNoFormInputs[] =
518       "<input type='text' id='username'/>"
519       "<input type='password' id='password'/>";
520   LoadHTML(kNoFormInputs);
521
522   SimulateOnFillPasswordForm(fill_data_);
523
524   // Input elements that aren't in a <form> won't autofill.
525   CheckTextFieldsState(std::string(), false, std::string(), false);
526 }
527
528 TEST_F(PasswordAutofillAgentTest, NoAutocompleteForTextFieldPasswords) {
529   const char kTextFieldPasswordFormHTML[] =
530       "<FORM name='LoginTestForm' action='http://www.bidule.com'>"
531       "  <INPUT type='text' id='username'/>"
532       "  <INPUT type='text' id='password'/>"
533       "  <INPUT type='submit' value='Login'/>"
534       "</FORM>";
535   LoadHTML(kTextFieldPasswordFormHTML);
536
537   // Retrieve the input elements so the test can access them.
538   WebDocument document = GetMainFrame()->document();
539   WebElement element =
540       document.getElementById(WebString::fromUTF8(kUsernameName));
541   ASSERT_FALSE(element.isNull());
542   username_element_ = element.to<blink::WebInputElement>();
543   element = document.getElementById(WebString::fromUTF8(kPasswordName));
544   ASSERT_FALSE(element.isNull());
545   password_element_ = element.to<blink::WebInputElement>();
546
547   // Set the expected form origin URL.
548   UpdateOriginForHTML(kTextFieldPasswordFormHTML);
549
550   SimulateOnFillPasswordForm(fill_data_);
551
552   // Fields should still be empty.
553   CheckTextFieldsState(std::string(), false, std::string(), false);
554 }
555
556 TEST_F(PasswordAutofillAgentTest, NoAutocompleteForPasswordFieldUsernames) {
557   const char kPasswordFieldUsernameFormHTML[] =
558       "<FORM name='LoginTestForm' action='http://www.bidule.com'>"
559       "  <INPUT type='password' id='username'/>"
560       "  <INPUT type='password' id='password'/>"
561       "  <INPUT type='submit' value='Login'/>"
562       "</FORM>";
563   LoadHTML(kPasswordFieldUsernameFormHTML);
564
565   // Retrieve the input elements so the test can access them.
566   WebDocument document = GetMainFrame()->document();
567   WebElement element =
568       document.getElementById(WebString::fromUTF8(kUsernameName));
569   ASSERT_FALSE(element.isNull());
570   username_element_ = element.to<blink::WebInputElement>();
571   element = document.getElementById(WebString::fromUTF8(kPasswordName));
572   ASSERT_FALSE(element.isNull());
573   password_element_ = element.to<blink::WebInputElement>();
574
575   // Set the expected form origin URL.
576   UpdateOriginForHTML(kPasswordFieldUsernameFormHTML);
577
578   SimulateOnFillPasswordForm(fill_data_);
579
580   // Fields should still be empty.
581   CheckTextFieldsState(std::string(), false, std::string(), false);
582 }
583
584 // Tests that having a matching username does not preclude the autocomplete.
585 TEST_F(PasswordAutofillAgentTest, InitialAutocompleteForMatchingFilledField) {
586   username_element_.setValue(WebString::fromUTF8(kAliceUsername));
587
588   // Simulate the browser sending back the login info, it triggers the
589   // autocomplete.
590   SimulateOnFillPasswordForm(fill_data_);
591
592   // The username and password should have been autocompleted.
593   CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
594 }
595
596 // Tests that editing the password clears the autocompleted password field.
597 TEST_F(PasswordAutofillAgentTest, PasswordClearOnEdit) {
598   // Simulate the browser sending back the login info, it triggers the
599   // autocomplete.
600   SimulateOnFillPasswordForm(fill_data_);
601
602   // Simulate the user changing the username to some unknown username.
603   SimulateUsernameChange("alicia", true);
604
605   // The password should have been cleared.
606   CheckTextFieldsState("alicia", false, std::string(), false);
607 }
608
609 // Tests that we only autocomplete on focus lost and with a full username match
610 // when |wait_for_username| is true.
611 TEST_F(PasswordAutofillAgentTest, WaitUsername) {
612   // Simulate the browser sending back the login info.
613   fill_data_.wait_for_username = true;
614   SimulateOnFillPasswordForm(fill_data_);
615
616   // No auto-fill should have taken place.
617   CheckTextFieldsState(std::string(), false, std::string(), false);
618
619   // No autocomplete should happen when text is entered in the username.
620   SimulateUsernameChange("a", true);
621   CheckTextFieldsState("a", false, std::string(), false);
622   SimulateUsernameChange("al", true);
623   CheckTextFieldsState("al", false, std::string(), false);
624   SimulateUsernameChange(kAliceUsername, true);
625   CheckTextFieldsState(kAliceUsername, false, std::string(), false);
626
627   // Autocomplete should happen only when the username textfield is blurred with
628   // a full match.
629   username_element_.setValue("a");
630   autofill_agent_->textFieldDidEndEditing(username_element_);
631   CheckTextFieldsState("a", false, std::string(), false);
632   username_element_.setValue("al");
633   autofill_agent_->textFieldDidEndEditing(username_element_);
634   CheckTextFieldsState("al", false, std::string(), false);
635   username_element_.setValue("alices");
636   autofill_agent_->textFieldDidEndEditing(username_element_);
637   CheckTextFieldsState("alices", false, std::string(), false);
638   username_element_.setValue(ASCIIToUTF16(kAliceUsername));
639   autofill_agent_->textFieldDidEndEditing(username_element_);
640   CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
641 }
642
643 // Tests that inline autocompletion works properly.
644 TEST_F(PasswordAutofillAgentTest, InlineAutocomplete) {
645   // Simulate the browser sending back the login info.
646   SimulateOnFillPasswordForm(fill_data_);
647
648   // Clear the text fields to start fresh.
649   ClearUsernameAndPasswordFields();
650
651   // Simulate the user typing in the first letter of 'alice', a stored username.
652   SimulateUsernameChange("a", true);
653   // Both the username and password text fields should reflect selection of the
654   // stored login.
655   CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
656   // And the selection should have been set to 'lice', the last 4 letters.
657   CheckUsernameSelection(1, 5);
658
659   // Now the user types the next letter of the same username, 'l'.
660   SimulateUsernameChange("al", true);
661   // Now the fields should have the same value, but the selection should have a
662   // different start value.
663   CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
664   CheckUsernameSelection(2, 5);
665
666   // Test that deleting does not trigger autocomplete.
667   SimulateKeyDownEvent(username_element_, ui::VKEY_BACK);
668   SimulateUsernameChange("alic", true);
669   CheckTextFieldsState("alic", false, std::string(), false);
670   CheckUsernameSelection(4, 4);  // No selection.
671   // Reset the last pressed key to something other than backspace.
672   SimulateKeyDownEvent(username_element_, ui::VKEY_A);
673
674   // Now lets say the user goes astray from the stored username and types the
675   // letter 'f', spelling 'alf'.  We don't know alf (that's just sad), so in
676   // practice the username should no longer be 'alice' and the selected range
677   // should be empty.
678   SimulateUsernameChange("alf", true);
679   CheckTextFieldsState("alf", false, std::string(), false);
680   CheckUsernameSelection(3, 3);  // No selection.
681
682   // Ok, so now the user removes all the text and enters the letter 'b'.
683   SimulateUsernameChange("b", true);
684   // The username and password fields should match the 'bob' entry.
685   CheckTextFieldsState(kBobUsername, true, kBobPassword, true);
686   CheckUsernameSelection(1, 3);
687
688   // Then, the user again removes all the text and types an uppercase 'C'.
689   SimulateUsernameChange("C", true);
690   // The username and password fields should match the 'Carol' entry.
691   CheckTextFieldsState(kCarolUsername, true, kCarolPassword, true);
692   CheckUsernameSelection(1, 5);
693   // The user removes all the text and types a lowercase 'c'.  We only
694   // want case-sensitive autocompletion, so the username and the selected range
695   // should be empty.
696   SimulateUsernameChange("c", true);
697   CheckTextFieldsState("c", false, std::string(), false);
698   CheckUsernameSelection(1, 1);
699
700   // Check that we complete other_possible_usernames as well.
701   SimulateUsernameChange("R", true);
702   CheckTextFieldsState(kCarolAlternateUsername, true, kCarolPassword, true);
703   CheckUsernameSelection(1, 17);
704 }
705
706 TEST_F(PasswordAutofillAgentTest, IsWebNodeVisibleTest) {
707   blink::WebVector<blink::WebFormElement> forms1, forms2, forms3;
708   blink::WebFrame* frame;
709
710   LoadHTML(kVisibleFormHTML);
711   frame = GetMainFrame();
712   frame->document().forms(forms1);
713   ASSERT_EQ(1u, forms1.size());
714   EXPECT_TRUE(IsWebNodeVisible(forms1[0]));
715
716   LoadHTML(kEmptyFormHTML);
717   frame = GetMainFrame();
718   frame->document().forms(forms2);
719   ASSERT_EQ(1u, forms2.size());
720   EXPECT_FALSE(IsWebNodeVisible(forms2[0]));
721
722   LoadHTML(kNonVisibleFormHTML);
723   frame = GetMainFrame();
724   frame->document().forms(forms3);
725   ASSERT_EQ(1u, forms3.size());
726   EXPECT_FALSE(IsWebNodeVisible(forms3[0]));
727 }
728
729 TEST_F(PasswordAutofillAgentTest, SendPasswordFormsTest) {
730   render_thread_->sink().ClearMessages();
731   LoadHTML(kVisibleFormHTML);
732   const IPC::Message* message = render_thread_->sink()
733       .GetFirstMessageMatching(AutofillHostMsg_PasswordFormsRendered::ID);
734   EXPECT_TRUE(message);
735   Tuple1<std::vector<autofill::PasswordForm> > param;
736   AutofillHostMsg_PasswordFormsRendered::Read(message, &param);
737   EXPECT_TRUE(param.a.size());
738
739   render_thread_->sink().ClearMessages();
740   LoadHTML(kEmptyFormHTML);
741   message = render_thread_->sink().GetFirstMessageMatching(
742       AutofillHostMsg_PasswordFormsRendered::ID);
743   EXPECT_TRUE(message);
744   AutofillHostMsg_PasswordFormsRendered::Read(message, &param);
745   EXPECT_FALSE(param.a.size());
746
747   render_thread_->sink().ClearMessages();
748   LoadHTML(kNonVisibleFormHTML);
749   message = render_thread_->sink().GetFirstMessageMatching(
750       AutofillHostMsg_PasswordFormsRendered::ID);
751   EXPECT_TRUE(message);
752   AutofillHostMsg_PasswordFormsRendered::Read(message, &param);
753   EXPECT_FALSE(param.a.size());
754 }
755
756 TEST_F(PasswordAutofillAgentTest, SendPasswordFormsTest_Redirection) {
757   render_thread_->sink().ClearMessages();
758   LoadHTML(kEmptyWebpage);
759   EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching(
760       AutofillHostMsg_PasswordFormsRendered::ID));
761
762   render_thread_->sink().ClearMessages();
763   LoadHTML(kRedirectionWebpage);
764   EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching(
765       AutofillHostMsg_PasswordFormsRendered::ID));
766
767   render_thread_->sink().ClearMessages();
768   LoadHTML(kSimpleWebpage);
769   EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching(
770       AutofillHostMsg_PasswordFormsRendered::ID));
771
772   render_thread_->sink().ClearMessages();
773   LoadHTML(kWebpageWithDynamicContent);
774   EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching(
775       AutofillHostMsg_PasswordFormsRendered::ID));
776 }
777
778 // Tests that a password form in an iframe will not be filled in until a user
779 // interaction with the form.
780 TEST_F(PasswordAutofillAgentTest, IframeNoFillTest) {
781   const char kIframeName[] = "iframe";
782   const char kWebpageWithIframeStart[] =
783       "<html>"
784       "   <head>"
785       "       <meta charset='utf-8' />"
786       "       <title>Title</title>"
787       "   </head>"
788       "   <body>"
789       "       <iframe id='iframe' src=\"";
790   const char kWebpageWithIframeEnd[] =
791       "\"></iframe>"
792       "   </body>"
793       "</html>";
794
795   std::string origin("data:text/html;charset=utf-8,");
796   origin += kSimpleWebpage;
797
798   std::string page_html(kWebpageWithIframeStart);
799   page_html += origin;
800   page_html += kWebpageWithIframeEnd;
801
802   LoadHTML(page_html.c_str());
803
804   // Set the expected form origin and action URLs.
805   fill_data_.basic_data.origin = GURL(origin);
806   fill_data_.basic_data.action = GURL(origin);
807
808   SimulateOnFillPasswordForm(fill_data_);
809
810   // Retrieve the input elements from the iframe since that is where we want to
811   // test the autofill.
812   WebFrame* iframe = GetMainFrame()->findChildByName(kIframeName);
813   ASSERT_TRUE(iframe);
814   WebDocument document = iframe->document();
815
816   WebElement username_element = document.getElementById(kUsernameName);
817   WebElement password_element = document.getElementById(kPasswordName);
818   ASSERT_FALSE(username_element.isNull());
819   ASSERT_FALSE(password_element.isNull());
820
821   WebInputElement username_input = username_element.to<WebInputElement>();
822   WebInputElement password_input = password_element.to<WebInputElement>();
823   ASSERT_FALSE(username_element.isNull());
824
825   CheckTextFieldsStateForElements(username_input, "", false,
826                                   password_input, "", false);
827
828   // Simulate the user typing in the username in the iframe, which should cause
829   // an autofill.
830   SimulateUsernameChangeForElement(kAliceUsername, true,
831                                    iframe, username_input);
832
833   CheckTextFieldsStateForElements(username_input, kAliceUsername, true,
834                                   password_input, kAlicePassword, true);
835 }
836
837 // Tests that a password will only be filled as a suggested and will not be
838 // accessible by the DOM until a user gesture has occurred.
839 TEST_F(PasswordAutofillAgentTest, GestureRequiredTest) {
840   // Trigger the initial autocomplete.
841   SimulateOnFillPasswordForm(fill_data_);
842
843   // The username and password should have been autocompleted.
844   CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
845
846   // However, it should only have completed with the suggested value, as tested
847   // above, and it should not have completed into the DOM accessible value for
848   // the password field.
849   CheckTextFieldsDOMState(kAliceUsername, true, std::string(), true);
850
851   // Simulate a user click so that the password field's real value is filled.
852   SimulateElementClick(kUsernameName);
853   CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true);
854 }
855
856 // Verfies that a DOM-activated UI event will not cause an autofill.
857 TEST_F(PasswordAutofillAgentTest, NoDOMActivationTest) {
858   // Trigger the initial autocomplete.
859   SimulateOnFillPasswordForm(fill_data_);
860
861   ExecuteJavaScript(kJavaScriptClick);
862   CheckTextFieldsDOMState(kAliceUsername, true, "", true);
863 }
864
865 // Regression test for http://crbug.com/326679
866 TEST_F(PasswordAutofillAgentTest, SelectUsernameWithUsernameAutofillOff) {
867   // Simulate the browser sending back the login info.
868   SimulateOnFillPasswordForm(fill_data_);
869
870   // Set the username element to autocomplete='off'
871   username_element_.setAttribute(WebString::fromUTF8("autocomplete"),
872                                  WebString::fromUTF8("off"));
873
874   // Simulate the user changing the username to some known username.
875   SimulateUsernameChange(kAliceUsername, true);
876
877   ExpectNoSuggestionsPopup();
878 }
879
880 // Regression test for http://crbug.com/326679
881 TEST_F(PasswordAutofillAgentTest,
882        SelectUnknownUsernameWithUsernameAutofillOff) {
883   // Simulate the browser sending back the login info.
884   SimulateOnFillPasswordForm(fill_data_);
885
886   // Set the username element to autocomplete='off'
887   username_element_.setAttribute(WebString::fromUTF8("autocomplete"),
888                                  WebString::fromUTF8("off"));
889
890   // Simulate the user changing the username to some unknown username.
891   SimulateUsernameChange("foo", true);
892
893   ExpectNoSuggestionsPopup();
894 }
895
896 // Regression test for http://crbug.com/326679
897 TEST_F(PasswordAutofillAgentTest, SelectUsernameWithPasswordAutofillOff) {
898   // Simulate the browser sending back the login info.
899   SimulateOnFillPasswordForm(fill_data_);
900
901   // Set the main password element to autocomplete='off'
902   password_element_.setAttribute(WebString::fromUTF8("autocomplete"),
903                                  WebString::fromUTF8("off"));
904
905  // Simulate the user changing the username to some known username.
906   SimulateUsernameChange(kAliceUsername, true);
907
908   ExpectNoSuggestionsPopup();
909 }
910
911 // Regression test for http://crbug.com/326679
912 TEST_F(PasswordAutofillAgentTest,
913        SelectUnknownUsernameWithPasswordAutofillOff) {
914   // Simulate the browser sending back the login info.
915   SimulateOnFillPasswordForm(fill_data_);
916
917   // Set the main password element to autocomplete='off'
918   password_element_.setAttribute(WebString::fromUTF8("autocomplete"),
919                                  WebString::fromUTF8("off"));
920
921   // Simulate the user changing the username to some unknown username.
922   SimulateUsernameChange("foo", true);
923
924   ExpectNoSuggestionsPopup();
925 }
926
927 // Verifies that password autofill triggers onChange events in JavaScript for
928 // forms that are filled on page load.
929 TEST_F(PasswordAutofillAgentTest,
930        PasswordAutofillTriggersOnChangeEventsOnLoad) {
931   std::string html = std::string(kFormHTML) + kOnChangeDetectionScript;
932   LoadHTML(html.c_str());
933   UpdateOriginForHTML(html);
934   UpdateUsernameAndPasswordElements();
935
936   // Simulate the browser sending back the login info, it triggers the
937   // autocomplete.
938   SimulateOnFillPasswordForm(fill_data_);
939
940   // The username and password should have been autocompleted...
941   CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
942   // ... but since there hasn't been a user gesture yet, the autocompleted
943   // password should only be visible to the user.
944   CheckTextFieldsDOMState(kAliceUsername, true, std::string(), true);
945
946   // A JavaScript onChange event should have been triggered for the username,
947   // but not yet for the password.
948   int username_onchange_called = -1;
949   int password_onchange_called = -1;
950   ASSERT_TRUE(
951       ExecuteJavaScriptAndReturnIntValue(
952           ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"),
953           &username_onchange_called));
954   EXPECT_EQ(1, username_onchange_called);
955   ASSERT_TRUE(
956       ExecuteJavaScriptAndReturnIntValue(
957           ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"),
958           &password_onchange_called));
959   // TODO(isherman): Re-enable this check once http://crbug.com/333144 is fixed.
960   // EXPECT_EQ(0, password_onchange_called);
961
962   // Simulate a user click so that the password field's real value is filled.
963   SimulateElementClick(kUsernameName);
964   CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true);
965
966   // Now, a JavaScript onChange event should have been triggered for the
967   // password as well.
968   ASSERT_TRUE(
969       ExecuteJavaScriptAndReturnIntValue(
970           ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"),
971           &password_onchange_called));
972   EXPECT_EQ(1, password_onchange_called);
973 }
974
975 // Verifies that password autofill triggers onChange events in JavaScript for
976 // forms that are filled after page load.
977 TEST_F(PasswordAutofillAgentTest,
978        PasswordAutofillTriggersOnChangeEventsWaitForUsername) {
979   std::string html = std::string(kFormHTML) + kOnChangeDetectionScript;
980   LoadHTML(html.c_str());
981   UpdateOriginForHTML(html);
982   UpdateUsernameAndPasswordElements();
983
984   // Simulate the browser sending back the login info, it triggers the
985   // autocomplete.
986   fill_data_.wait_for_username = true;
987   SimulateOnFillPasswordForm(fill_data_);
988
989   // The username and password should not yet have been autocompleted.
990   CheckTextFieldsState(std::string(), false, std::string(), false);
991
992   // Simulate a click just to force a user gesture, since the username value is
993   // set directly.
994   SimulateElementClick(kUsernameName);
995
996   // Simulate the user entering her username.
997   username_element_.setValue(ASCIIToUTF16(kAliceUsername), true);
998   autofill_agent_->textFieldDidEndEditing(username_element_);
999
1000   // The username and password should now have been autocompleted.
1001   CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true);
1002
1003   // JavaScript onChange events should have been triggered both for the username
1004   // and for the password.
1005   int username_onchange_called = -1;
1006   int password_onchange_called = -1;
1007   ASSERT_TRUE(
1008       ExecuteJavaScriptAndReturnIntValue(
1009           ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"),
1010           &username_onchange_called));
1011   EXPECT_EQ(1, username_onchange_called);
1012   ASSERT_TRUE(
1013       ExecuteJavaScriptAndReturnIntValue(
1014           ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"),
1015           &password_onchange_called));
1016   EXPECT_EQ(1, password_onchange_called);
1017 }
1018
1019 }  // namespace autofill