• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &param);
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, &param);
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, &param);
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