Home | History | Annotate | Download | only in autofill
      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 "testing/gtest/include/gtest/gtest.h"
     16 #include "third_party/WebKit/public/platform/WebString.h"
     17 #include "third_party/WebKit/public/platform/WebVector.h"
     18 #include "third_party/WebKit/public/web/WebDocument.h"
     19 #include "third_party/WebKit/public/web/WebElement.h"
     20 #include "third_party/WebKit/public/web/WebFormElement.h"
     21 #include "third_party/WebKit/public/web/WebFrame.h"
     22 #include "third_party/WebKit/public/web/WebInputElement.h"
     23 #include "third_party/WebKit/public/web/WebNode.h"
     24 #include "third_party/WebKit/public/web/WebView.h"
     25 #include "ui/events/keycodes/keyboard_codes.h"
     26 
     27 using autofill::PasswordForm;
     28 using blink::WebDocument;
     29 using blink::WebElement;
     30 using blink::WebFrame;
     31 using blink::WebInputElement;
     32 using blink::WebString;
     33 using blink::WebView;
     34 
     35 namespace {
     36 
     37 // The name of the username/password element in the form.
     38 const char kUsernameName[] = "username";
     39 const char kPasswordName[] = "password";
     40 
     41 const char kAliceUsername[] = "alice";
     42 const char kAlicePassword[] = "password";
     43 const char kBobUsername[] = "bob";
     44 const char kBobPassword[] = "secret";
     45 const char kCarolUsername[] = "Carol";
     46 const char kCarolPassword[] = "test";
     47 const char kCarolAlternateUsername[] = "RealCarolUsername";
     48 
     49 
     50 const char kFormHTML[] =
     51     "<FORM name='LoginTestForm' action='http://www.bidule.com'>"
     52     "  <INPUT type='text' id='username'/>"
     53     "  <INPUT type='password' id='password'/>"
     54     "  <INPUT type='submit' value='Login'/>"
     55     "</FORM>";
     56 
     57 const char kVisibleFormHTML[] =
     58     "<head> <style> form {display: inline;} </style> </head>"
     59     "<body>"
     60     "  <form>"
     61     "    <div>"
     62     "      <input type='password' id='password'/>"
     63     "    </div>"
     64     "  </form>"
     65     "</body>";
     66 
     67 const char kEmptyFormHTML[] =
     68     "<head> <style> form {display: inline;} </style> </head>"
     69     "<body> <form> </form> </body>";
     70 
     71 const char kNonVisibleFormHTML[] =
     72     "<head> <style> form {display: none;} </style> </head>"
     73     "<body>"
     74     "  <form>"
     75     "    <div>"
     76     "      <input type='password' id='password'/>"
     77     "    </div>"
     78     "  </form>"
     79     "</body>";
     80 
     81 const char kEmptyWebpage[] =
     82     "<html>"
     83     "   <head>"
     84     "   </head>"
     85     "   <body>"
     86     "   </body>"
     87     "</html>";
     88 
     89 const char kRedirectionWebpage[] =
     90     "<html>"
     91     "   <head>"
     92     "       <meta http-equiv='Content-Type' content='text/html'>"
     93     "       <title>Redirection page</title>"
     94     "       <script></script>"
     95     "   </head>"
     96     "   <body>"
     97     "       <script type='text/javascript'>"
     98     "         function test(){}"
     99     "       </script>"
    100     "   </body>"
    101     "</html>";
    102 
    103 const char kSimpleWebpage[] =
    104     "<html>"
    105     "   <head>"
    106     "       <meta charset='utf-8' />"
    107     "       <title>Title</title>"
    108     "   </head>"
    109     "   <body>"
    110     "       <form name='LoginTestForm'>"
    111     "           <input type='text' id='username'/>"
    112     "           <input type='password' id='password'/>"
    113     "           <input type='submit' value='Login'/>"
    114     "       </form>"
    115     "   </body>"
    116     "</html>";
    117 
    118 const char kWebpageWithDynamicContent[] =
    119     "<html>"
    120     "   <head>"
    121     "       <meta charset='utf-8' />"
    122     "       <title>Title</title>"
    123     "   </head>"
    124     "   <body>"
    125     "       <script type='text/javascript'>"
    126     "           function addParagraph() {"
    127     "             var p = document.createElement('p');"
    128     "             document.body.appendChild(p);"
    129     "            }"
    130     "           window.onload = addParagraph;"
    131     "       </script>"
    132     "   </body>"
    133     "</html>";
    134 
    135 }  // namespace
    136 
    137 namespace autofill {
    138 
    139 class PasswordAutofillAgentTest : public ChromeRenderViewTest {
    140  public:
    141   PasswordAutofillAgentTest() {
    142   }
    143 
    144   // Simulates the fill password form message being sent to the renderer.
    145   // We use that so we don't have to make RenderView::OnFillPasswordForm()
    146   // protected.
    147   void SimulateOnFillPasswordForm(
    148       const PasswordFormFillData& fill_data) {
    149     AutofillMsg_FillPasswordForm msg(0, fill_data);
    150     password_autofill_->OnMessageReceived(msg);
    151   }
    152 
    153   virtual void SetUp() {
    154     ChromeRenderViewTest::SetUp();
    155 
    156     // Add a preferred login and an additional login to the FillData.
    157     username1_ = ASCIIToUTF16(kAliceUsername);
    158     password1_ = ASCIIToUTF16(kAlicePassword);
    159     username2_ = ASCIIToUTF16(kBobUsername);
    160     password2_ = ASCIIToUTF16(kBobPassword);
    161     username3_ = ASCIIToUTF16(kCarolUsername);
    162     password3_ = ASCIIToUTF16(kCarolPassword);
    163     alternate_username3_ = ASCIIToUTF16(kCarolAlternateUsername);
    164 
    165     FormFieldData username_field;
    166     username_field.name = ASCIIToUTF16(kUsernameName);
    167     username_field.value = username1_;
    168     fill_data_.basic_data.fields.push_back(username_field);
    169 
    170     FormFieldData password_field;
    171     password_field.name = ASCIIToUTF16(kPasswordName);
    172     password_field.value = password1_;
    173     password_field.form_control_type = "password";
    174     fill_data_.basic_data.fields.push_back(password_field);
    175 
    176     PasswordAndRealm password2;
    177     password2.password = password2_;
    178     fill_data_.additional_logins[username2_] = password2;
    179     PasswordAndRealm password3;
    180     password3.password = password3_;
    181     fill_data_.additional_logins[username3_] = password3;
    182 
    183     UsernamesCollectionKey key;
    184     key.username = username3_;
    185     key.password = password3_;
    186     key.realm = "google.com";
    187     fill_data_.other_possible_usernames[key].push_back(alternate_username3_);
    188 
    189     // We need to set the origin so it matches the frame URL and the action so
    190     // it matches the form action, otherwise we won't autocomplete.
    191     std::string origin("data:text/html;charset=utf-8,");
    192     origin += kFormHTML;
    193     fill_data_.basic_data.origin = GURL(origin);
    194     fill_data_.basic_data.action = GURL("http://www.bidule.com");
    195 
    196     LoadHTML(kFormHTML);
    197 
    198     // Now retrieves the input elements so the test can access them.
    199     WebDocument document = GetMainFrame()->document();
    200     WebElement element =
    201         document.getElementById(WebString::fromUTF8(kUsernameName));
    202     ASSERT_FALSE(element.isNull());
    203     username_element_ = element.to<blink::WebInputElement>();
    204     element = document.getElementById(WebString::fromUTF8(kPasswordName));
    205     ASSERT_FALSE(element.isNull());
    206     password_element_ = element.to<blink::WebInputElement>();
    207   }
    208 
    209   virtual void TearDown() {
    210     username_element_.reset();
    211     password_element_.reset();
    212     ChromeRenderViewTest::TearDown();
    213   }
    214 
    215   void ClearUsernameAndPasswordFields() {
    216     username_element_.setValue("");
    217     username_element_.setAutofilled(false);
    218     password_element_.setValue("");
    219     password_element_.setAutofilled(false);
    220   }
    221 
    222   void SimulateUsernameChangeForElement(const std::string& username,
    223                                         bool move_caret_to_end,
    224                                         WebFrame* input_frame,
    225                                         WebInputElement& username_input) {
    226     username_input.setValue(WebString::fromUTF8(username));
    227     // The field must have focus or AutofillAgent will think the
    228     // change should be ignored.
    229     while (!username_input.focused())
    230       input_frame->document().frame()->view()->advanceFocus(false);
    231     if (move_caret_to_end)
    232       username_input.setSelectionRange(username.length(), username.length());
    233     autofill_agent_->textFieldDidChange(username_input);
    234     // Processing is delayed because of a WebKit bug, see
    235     // PasswordAutocompleteManager::TextDidChangeInTextField() for details.
    236     base::MessageLoop::current()->RunUntilIdle();
    237   }
    238 
    239   void SimulateUsernameChange(const std::string& username,
    240                               bool move_caret_to_end) {
    241     SimulateUsernameChangeForElement(username, move_caret_to_end,
    242                                      GetMainFrame(), username_element_);
    243   }
    244 
    245 
    246   void SimulateKeyDownEvent(const WebInputElement& element,
    247                             ui::KeyboardCode key_code) {
    248     blink::WebKeyboardEvent key_event;
    249     key_event.windowsKeyCode = key_code;
    250     autofill_agent_->textFieldDidReceiveKeyDown(element, key_event);
    251   }
    252 
    253   void CheckTextFieldsStateForElements(const WebInputElement& username_element,
    254                                        const std::string& username,
    255                                        bool username_autofilled,
    256                                        const WebInputElement& password_element,
    257                                        const std::string& password,
    258                                        bool password_autofilled) {
    259     EXPECT_EQ(username,
    260               static_cast<std::string>(username_element.value().utf8()));
    261     EXPECT_EQ(username_autofilled, username_element.isAutofilled());
    262     EXPECT_EQ(password,
    263               static_cast<std::string>(password_element.value().utf8()));
    264     EXPECT_EQ(password_autofilled, password_element.isAutofilled());
    265   }
    266 
    267   void CheckTextFieldsState(const std::string& username,
    268                             bool username_autofilled,
    269                             const std::string& password,
    270                             bool password_autofilled) {
    271     CheckTextFieldsStateForElements(username_element_, username,
    272                                     username_autofilled, password_element_,
    273                                     password, password_autofilled);
    274   }
    275 
    276   void CheckUsernameSelection(int start, int end) {
    277     EXPECT_EQ(start, username_element_.selectionStart());
    278     EXPECT_EQ(end, username_element_.selectionEnd());
    279   }
    280 
    281   base::string16 username1_;
    282   base::string16 username2_;
    283   base::string16 username3_;
    284   base::string16 password1_;
    285   base::string16 password2_;
    286   base::string16 password3_;
    287   base::string16 alternate_username3_;
    288   PasswordFormFillData fill_data_;
    289 
    290   WebInputElement username_element_;
    291   WebInputElement password_element_;
    292 
    293  private:
    294   DISALLOW_COPY_AND_ASSIGN(PasswordAutofillAgentTest);
    295 };
    296 
    297 // Tests that the password login is autocompleted as expected when the browser
    298 // sends back the password info.
    299 TEST_F(PasswordAutofillAgentTest, InitialAutocomplete) {
    300   /*
    301    * Right now we are not sending the message to the browser because we are
    302    * loading a data URL and the security origin canAccessPasswordManager()
    303    * returns false.  May be we should mock URL loading to cirmcuvent this?
    304    TODO(jcivelli): find a way to make the security origin not deny access to the
    305                    password manager and then reenable this code.
    306 
    307   // The form has been loaded, we should have sent the browser a message about
    308   // the form.
    309   const IPC::Message* msg = render_thread_.sink().GetFirstMessageMatching(
    310       AutofillHostMsg_PasswordFormsParsed::ID);
    311   ASSERT_TRUE(msg != NULL);
    312 
    313   Tuple1<std::vector<PasswordForm> > forms;
    314   AutofillHostMsg_PasswordFormsParsed::Read(msg, &forms);
    315   ASSERT_EQ(1U, forms.a.size());
    316   PasswordForm password_form = forms.a[0];
    317   EXPECT_EQ(PasswordForm::SCHEME_HTML, password_form.scheme);
    318   EXPECT_EQ(ASCIIToUTF16(kUsernameName), password_form.username_element);
    319   EXPECT_EQ(ASCIIToUTF16(kPasswordName), password_form.password_element);
    320   */
    321 
    322   // Simulate the browser sending back the login info, it triggers the
    323   // autocomplete.
    324   SimulateOnFillPasswordForm(fill_data_);
    325 
    326   // The username and password should have been autocompleted.
    327   CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
    328 }
    329 
    330 // Tests that we correctly fill forms having an empty 'action' attribute.
    331 TEST_F(PasswordAutofillAgentTest, InitialAutocompleteForEmptyAction) {
    332   const char kEmptyActionFormHTML[] =
    333       "<FORM name='LoginTestForm'>"
    334       "  <INPUT type='text' id='username'/>"
    335       "  <INPUT type='password' id='password'/>"
    336       "  <INPUT type='submit' value='Login'/>"
    337       "</FORM>";
    338   LoadHTML(kEmptyActionFormHTML);
    339 
    340   // Retrieve the input elements so the test can access them.
    341   WebDocument document = GetMainFrame()->document();
    342   WebElement element =
    343       document.getElementById(WebString::fromUTF8(kUsernameName));
    344   ASSERT_FALSE(element.isNull());
    345   username_element_ = element.to<blink::WebInputElement>();
    346   element = document.getElementById(WebString::fromUTF8(kPasswordName));
    347   ASSERT_FALSE(element.isNull());
    348   password_element_ = element.to<blink::WebInputElement>();
    349 
    350   // Set the expected form origin and action URLs.
    351   std::string origin("data:text/html;charset=utf-8,");
    352   origin += kEmptyActionFormHTML;
    353   fill_data_.basic_data.origin = GURL(origin);
    354   fill_data_.basic_data.action = GURL(origin);
    355 
    356   // Simulate the browser sending back the login info, it triggers the
    357   // autocomplete.
    358   SimulateOnFillPasswordForm(fill_data_);
    359 
    360   // The username and password should have been autocompleted.
    361   CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
    362 }
    363 
    364 // Tests that if a password is marked as readonly, neither field is autofilled
    365 // on page load.
    366 TEST_F(PasswordAutofillAgentTest, NoInitialAutocompleteForReadOnlyPassword) {
    367   password_element_.setAttribute(WebString::fromUTF8("readonly"),
    368                                  WebString::fromUTF8("true"));
    369 
    370   // Simulate the browser sending back the login info, it triggers the
    371   // autocomplete.
    372   SimulateOnFillPasswordForm(fill_data_);
    373 
    374   CheckTextFieldsState(std::string(), false, std::string(), false);
    375 }
    376 
    377 // Can still fill a password field if the username is set to a value that
    378 // matches.
    379 TEST_F(PasswordAutofillAgentTest,
    380        AutocompletePasswordForReadonlyUsernameMatched) {
    381   username_element_.setValue(username3_);
    382   username_element_.setAttribute(WebString::fromUTF8("readonly"),
    383                                  WebString::fromUTF8("true"));
    384 
    385   // Filled even though username is not the preferred match.
    386   SimulateOnFillPasswordForm(fill_data_);
    387   CheckTextFieldsState(UTF16ToUTF8(username3_), false,
    388                        UTF16ToUTF8(password3_), true);
    389 }
    390 
    391 // If a username field is empty and readonly, don't autofill.
    392 TEST_F(PasswordAutofillAgentTest,
    393        NoAutocompletePasswordForReadonlyUsernameUnmatched) {
    394   username_element_.setValue(WebString::fromUTF8(""));
    395   username_element_.setAttribute(WebString::fromUTF8("readonly"),
    396                                  WebString::fromUTF8("true"));
    397 
    398   SimulateOnFillPasswordForm(fill_data_);
    399   CheckTextFieldsState(std::string(), false, std::string(), false);
    400 }
    401 
    402 // Tests that having a non-matching username precludes the autocomplete.
    403 TEST_F(PasswordAutofillAgentTest, NoAutocompleteForFilledFieldUnmatched) {
    404   username_element_.setValue(WebString::fromUTF8("bogus"));
    405 
    406   // Simulate the browser sending back the login info, it triggers the
    407   // autocomplete.
    408   SimulateOnFillPasswordForm(fill_data_);
    409 
    410   // Neither field should be autocompleted.
    411   CheckTextFieldsState("bogus", false, std::string(), false);
    412 }
    413 
    414 // Don't try to complete a prefilled value even if it's a partial match
    415 // to a username.
    416 TEST_F(PasswordAutofillAgentTest, NoPartialMatchForPrefilledUsername) {
    417   username_element_.setValue(WebString::fromUTF8("ali"));
    418 
    419   SimulateOnFillPasswordForm(fill_data_);
    420 
    421   CheckTextFieldsState("ali", false, std::string(), false);
    422 }
    423 
    424 TEST_F(PasswordAutofillAgentTest, InputWithNoForms) {
    425   const char kNoFormInputs[] =
    426       "<input type='text' id='username'/>"
    427       "<input type='password' id='password'/>";
    428   LoadHTML(kNoFormInputs);
    429 
    430   SimulateOnFillPasswordForm(fill_data_);
    431 
    432   // Input elements that aren't in a <form> won't autofill.
    433   CheckTextFieldsState(std::string(), false, std::string(), false);
    434 }
    435 
    436 TEST_F(PasswordAutofillAgentTest, NoAutocompleteForTextFieldPasswords) {
    437   const char kTextFieldPasswordFormHTML[] =
    438       "<FORM name='LoginTestForm' action='http://www.bidule.com'>"
    439       "  <INPUT type='text' id='username'/>"
    440       "  <INPUT type='text' id='password'/>"
    441       "  <INPUT type='submit' value='Login'/>"
    442       "</FORM>";
    443   LoadHTML(kTextFieldPasswordFormHTML);
    444 
    445   // Retrieve the input elements so the test can access them.
    446   WebDocument document = GetMainFrame()->document();
    447   WebElement element =
    448       document.getElementById(WebString::fromUTF8(kUsernameName));
    449   ASSERT_FALSE(element.isNull());
    450   username_element_ = element.to<blink::WebInputElement>();
    451   element = document.getElementById(WebString::fromUTF8(kPasswordName));
    452   ASSERT_FALSE(element.isNull());
    453   password_element_ = element.to<blink::WebInputElement>();
    454 
    455   // Set the expected form origin URL.
    456   std::string origin("data:text/html;charset=utf-8,");
    457   origin += kTextFieldPasswordFormHTML;
    458   fill_data_.basic_data.origin = GURL(origin);
    459 
    460   SimulateOnFillPasswordForm(fill_data_);
    461 
    462   // Fields should still be empty.
    463   CheckTextFieldsState(std::string(), false, std::string(), false);
    464 }
    465 
    466 TEST_F(PasswordAutofillAgentTest, NoAutocompleteForPasswordFieldUsernames) {
    467   const char kPasswordFieldUsernameFormHTML[] =
    468       "<FORM name='LoginTestForm' action='http://www.bidule.com'>"
    469       "  <INPUT type='password' id='username'/>"
    470       "  <INPUT type='password' id='password'/>"
    471       "  <INPUT type='submit' value='Login'/>"
    472       "</FORM>";
    473   LoadHTML(kPasswordFieldUsernameFormHTML);
    474 
    475   // Retrieve the input elements so the test can access them.
    476   WebDocument document = GetMainFrame()->document();
    477   WebElement element =
    478       document.getElementById(WebString::fromUTF8(kUsernameName));
    479   ASSERT_FALSE(element.isNull());
    480   username_element_ = element.to<blink::WebInputElement>();
    481   element = document.getElementById(WebString::fromUTF8(kPasswordName));
    482   ASSERT_FALSE(element.isNull());
    483   password_element_ = element.to<blink::WebInputElement>();
    484 
    485   // Set the expected form origin URL.
    486   std::string origin("data:text/html;charset=utf-8,");
    487   origin += kPasswordFieldUsernameFormHTML;
    488   fill_data_.basic_data.origin = GURL(origin);
    489 
    490   SimulateOnFillPasswordForm(fill_data_);
    491 
    492   // Fields should still be empty.
    493   CheckTextFieldsState(std::string(), false, std::string(), false);
    494 }
    495 
    496 // Tests that having a matching username does not preclude the autocomplete.
    497 TEST_F(PasswordAutofillAgentTest, InitialAutocompleteForMatchingFilledField) {
    498   username_element_.setValue(WebString::fromUTF8(kAliceUsername));
    499 
    500   // Simulate the browser sending back the login info, it triggers the
    501   // autocomplete.
    502   SimulateOnFillPasswordForm(fill_data_);
    503 
    504   // The username and password should have been autocompleted.
    505   CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
    506 }
    507 
    508 // Tests that editing the password clears the autocompleted password field.
    509 TEST_F(PasswordAutofillAgentTest, PasswordClearOnEdit) {
    510   // Simulate the browser sending back the login info, it triggers the
    511   // autocomplete.
    512   SimulateOnFillPasswordForm(fill_data_);
    513 
    514   // Simulate the user changing the username to some unknown username.
    515   SimulateUsernameChange("alicia", true);
    516 
    517   // The password should have been cleared.
    518   CheckTextFieldsState("alicia", false, std::string(), false);
    519 }
    520 
    521 // Tests that we only autocomplete on focus lost and with a full username match
    522 // when |wait_for_username| is true.
    523 TEST_F(PasswordAutofillAgentTest, WaitUsername) {
    524   // Simulate the browser sending back the login info.
    525   fill_data_.wait_for_username = true;
    526   SimulateOnFillPasswordForm(fill_data_);
    527 
    528   // No auto-fill should have taken place.
    529   CheckTextFieldsState(std::string(), false, std::string(), false);
    530 
    531   // No autocomplete should happen when text is entered in the username.
    532   SimulateUsernameChange("a", true);
    533   CheckTextFieldsState("a", false, std::string(), false);
    534   SimulateUsernameChange("al", true);
    535   CheckTextFieldsState("al", false, std::string(), false);
    536   SimulateUsernameChange(kAliceUsername, true);
    537   CheckTextFieldsState(kAliceUsername, false, std::string(), false);
    538 
    539   // Autocomplete should happen only when the username textfield is blurred with
    540   // a full match.
    541   username_element_.setValue("a");
    542   autofill_agent_->textFieldDidEndEditing(username_element_);
    543   CheckTextFieldsState("a", false, std::string(), false);
    544   username_element_.setValue("al");
    545   autofill_agent_->textFieldDidEndEditing(username_element_);
    546   CheckTextFieldsState("al", false, std::string(), false);
    547   username_element_.setValue("alices");
    548   autofill_agent_->textFieldDidEndEditing(username_element_);
    549   CheckTextFieldsState("alices", false, std::string(), false);
    550   username_element_.setValue(ASCIIToUTF16(kAliceUsername));
    551   autofill_agent_->textFieldDidEndEditing(username_element_);
    552   CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
    553 }
    554 
    555 // Tests that inline autocompletion works properly.
    556 TEST_F(PasswordAutofillAgentTest, InlineAutocomplete) {
    557   // Simulate the browser sending back the login info.
    558   SimulateOnFillPasswordForm(fill_data_);
    559 
    560   // Clear the text fields to start fresh.
    561   ClearUsernameAndPasswordFields();
    562 
    563   // Simulate the user typing in the first letter of 'alice', a stored username.
    564   SimulateUsernameChange("a", true);
    565   // Both the username and password text fields should reflect selection of the
    566   // stored login.
    567   CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
    568   // And the selection should have been set to 'lice', the last 4 letters.
    569   CheckUsernameSelection(1, 5);
    570 
    571   // Now the user types the next letter of the same username, 'l'.
    572   SimulateUsernameChange("al", true);
    573   // Now the fields should have the same value, but the selection should have a
    574   // different start value.
    575   CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
    576   CheckUsernameSelection(2, 5);
    577 
    578   // Test that deleting does not trigger autocomplete.
    579   SimulateKeyDownEvent(username_element_, ui::VKEY_BACK);
    580   SimulateUsernameChange("alic", true);
    581   CheckTextFieldsState("alic", false, std::string(), false);
    582   CheckUsernameSelection(4, 4);  // No selection.
    583   // Reset the last pressed key to something other than backspace.
    584   SimulateKeyDownEvent(username_element_, ui::VKEY_A);
    585 
    586   // Now lets say the user goes astray from the stored username and types the
    587   // letter 'f', spelling 'alf'.  We don't know alf (that's just sad), so in
    588   // practice the username should no longer be 'alice' and the selected range
    589   // should be empty.
    590   SimulateUsernameChange("alf", true);
    591   CheckTextFieldsState("alf", false, std::string(), false);
    592   CheckUsernameSelection(3, 3);  // No selection.
    593 
    594   // Ok, so now the user removes all the text and enters the letter 'b'.
    595   SimulateUsernameChange("b", true);
    596   // The username and password fields should match the 'bob' entry.
    597   CheckTextFieldsState(kBobUsername, true, kBobPassword, true);
    598   CheckUsernameSelection(1, 3);
    599 
    600   // Then, the user again removes all the text and types an uppercase 'C'.
    601   SimulateUsernameChange("C", true);
    602   // The username and password fields should match the 'Carol' entry.
    603   CheckTextFieldsState(kCarolUsername, true, kCarolPassword, true);
    604   CheckUsernameSelection(1, 5);
    605   // The user removes all the text and types a lowercase 'c'.  We only
    606   // want case-sensitive autocompletion, so the username and the selected range
    607   // should be empty.
    608   SimulateUsernameChange("c", true);
    609   CheckTextFieldsState("c", false, std::string(), false);
    610   CheckUsernameSelection(1, 1);
    611 
    612   // Check that we complete other_possible_usernames as well.
    613   SimulateUsernameChange("R", true);
    614   CheckTextFieldsState(kCarolAlternateUsername, true, kCarolPassword, true);
    615   CheckUsernameSelection(1, 17);
    616 }
    617 
    618 // Tests that selecting an item in the suggestion drop-down no-ops.
    619 TEST_F(PasswordAutofillAgentTest, SuggestionSelect) {
    620   // Simulate the browser sending back the login info.
    621   SimulateOnFillPasswordForm(fill_data_);
    622 
    623   // Clear the text fields to start fresh.
    624   ClearUsernameAndPasswordFields();
    625 
    626   // To simulate accepting an item in the suggestion drop-down we just mimic
    627   // what the WebView does: it sets the element value then calls
    628   // didSelectAutofillSuggestion on the renderer.
    629   autofill_agent_->didSelectAutofillSuggestion(username_element_,
    630                                                ASCIIToUTF16(kAliceUsername),
    631                                                blink::WebString(),
    632                                                0);
    633   // Autocomplete should not have kicked in.
    634   CheckTextFieldsState(std::string(), false, std::string(), false);
    635 }
    636 
    637 TEST_F(PasswordAutofillAgentTest, IsWebNodeVisibleTest) {
    638   blink::WebVector<blink::WebFormElement> forms1, forms2, forms3;
    639   blink::WebFrame* frame;
    640 
    641   LoadHTML(kVisibleFormHTML);
    642   frame = GetMainFrame();
    643   frame->document().forms(forms1);
    644   ASSERT_EQ(1u, forms1.size());
    645   EXPECT_TRUE(IsWebNodeVisible(forms1[0]));
    646 
    647   LoadHTML(kEmptyFormHTML);
    648   frame = GetMainFrame();
    649   frame->document().forms(forms2);
    650   ASSERT_EQ(1u, forms2.size());
    651   EXPECT_FALSE(IsWebNodeVisible(forms2[0]));
    652 
    653   LoadHTML(kNonVisibleFormHTML);
    654   frame = GetMainFrame();
    655   frame->document().forms(forms3);
    656   ASSERT_EQ(1u, forms3.size());
    657   EXPECT_FALSE(IsWebNodeVisible(forms3[0]));
    658 }
    659 
    660 TEST_F(PasswordAutofillAgentTest, SendPasswordFormsTest) {
    661   render_thread_->sink().ClearMessages();
    662   LoadHTML(kVisibleFormHTML);
    663   const IPC::Message* message = render_thread_->sink()
    664       .GetFirstMessageMatching(AutofillHostMsg_PasswordFormsRendered::ID);
    665   EXPECT_TRUE(message);
    666   Tuple1<std::vector<autofill::PasswordForm> > param;
    667   AutofillHostMsg_PasswordFormsRendered::Read(message, &param);
    668   EXPECT_TRUE(param.a.size());
    669 
    670   render_thread_->sink().ClearMessages();
    671   LoadHTML(kEmptyFormHTML);
    672   message = render_thread_->sink().GetFirstMessageMatching(
    673       AutofillHostMsg_PasswordFormsRendered::ID);
    674   EXPECT_TRUE(message);
    675   AutofillHostMsg_PasswordFormsRendered::Read(message, &param);
    676   EXPECT_FALSE(param.a.size());
    677 
    678   render_thread_->sink().ClearMessages();
    679   LoadHTML(kNonVisibleFormHTML);
    680   message = render_thread_->sink().GetFirstMessageMatching(
    681       AutofillHostMsg_PasswordFormsRendered::ID);
    682   EXPECT_TRUE(message);
    683   AutofillHostMsg_PasswordFormsRendered::Read(message, &param);
    684   EXPECT_FALSE(param.a.size());
    685 }
    686 
    687 TEST_F(PasswordAutofillAgentTest, SendPasswordFormsTest_Redirection) {
    688   render_thread_->sink().ClearMessages();
    689   LoadHTML(kEmptyWebpage);
    690   EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching(
    691       AutofillHostMsg_PasswordFormsRendered::ID));
    692 
    693   render_thread_->sink().ClearMessages();
    694   LoadHTML(kRedirectionWebpage);
    695   EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching(
    696       AutofillHostMsg_PasswordFormsRendered::ID));
    697 
    698   render_thread_->sink().ClearMessages();
    699   LoadHTML(kSimpleWebpage);
    700   EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching(
    701       AutofillHostMsg_PasswordFormsRendered::ID));
    702 
    703   render_thread_->sink().ClearMessages();
    704   LoadHTML(kWebpageWithDynamicContent);
    705   EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching(
    706       AutofillHostMsg_PasswordFormsRendered::ID));
    707 }
    708 
    709 // Tests that a password form in an iframe will not be filled in until a user
    710 // interaction with the form.
    711 TEST_F(PasswordAutofillAgentTest, IframeNoFillTest) {
    712   const char kIframeName[] = "iframe";
    713   const char kWebpageWithIframeStart[] =
    714       "<html>"
    715       "   <head>"
    716       "       <meta charset='utf-8' />"
    717       "       <title>Title</title>"
    718       "   </head>"
    719       "   <body>"
    720       "       <iframe id='iframe' src=\"";
    721   const char kWebpageWithIframeEnd[] =
    722       "\"></iframe>"
    723       "   </body>"
    724       "</html>";
    725 
    726   std::string origin("data:text/html;charset=utf-8,");
    727   origin += kSimpleWebpage;
    728 
    729   std::string page_html(kWebpageWithIframeStart);
    730   page_html += origin;
    731   page_html += kWebpageWithIframeEnd;
    732 
    733   LoadHTML(page_html.c_str());
    734 
    735   // Set the expected form origin and action URLs.
    736   fill_data_.basic_data.origin = GURL(origin);
    737   fill_data_.basic_data.action = GURL(origin);
    738 
    739   SimulateOnFillPasswordForm(fill_data_);
    740 
    741   // Retrieve the input elements from the iframe since that is where we want to
    742   // test the autofill.
    743   WebFrame* iframe = GetMainFrame()->findChildByName(kIframeName);
    744   ASSERT_TRUE(iframe);
    745   WebDocument document = iframe->document();
    746 
    747   WebElement username_element = document.getElementById(kUsernameName);
    748   WebElement password_element = document.getElementById(kPasswordName);
    749   ASSERT_FALSE(username_element.isNull());
    750   ASSERT_FALSE(password_element.isNull());
    751 
    752   WebInputElement username_input = username_element.to<WebInputElement>();
    753   WebInputElement password_input = password_element.to<WebInputElement>();
    754   ASSERT_FALSE(username_element.isNull());
    755 
    756   CheckTextFieldsStateForElements(username_input, "", false,
    757                                   password_input, "", false);
    758 
    759   // Simulate the user typing in the username in the iframe, which should cause
    760   // an autofill.
    761   SimulateUsernameChangeForElement(kAliceUsername, true,
    762                                    iframe, username_input);
    763 
    764   CheckTextFieldsStateForElements(username_input, kAliceUsername, true,
    765                                   password_input, kAlicePassword, true);
    766 }
    767 
    768 }  // namespace autofill
    769