| OLD | NEW | 
|    1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |    1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 
|    2 // Use of this source code is governed by a BSD-style license that can be |    2 // Use of this source code is governed by a BSD-style license that can be | 
|    3 // found in the LICENSE file. |    3 // found in the LICENSE file. | 
|    4  |    4  | 
|    5 #include "base/string_util.h" |    5 #include "base/string_util.h" | 
|    6 #include "base/utf_string_conversions.h" |    6 #include "base/utf_string_conversions.h" | 
|    7 #include "chrome/common/autofill_messages.h" |    7 #include "chrome/common/autofill_messages.h" | 
|    8 #include "chrome/renderer/autofill_helper.h" |    8 #include "chrome/renderer/autofill/autofill_agent.h" | 
|    9 #include "chrome/renderer/password_autocomplete_manager.h" |    9 #include "chrome/renderer/autofill/password_autofill_manager.h" | 
|   10 #include "chrome/test/render_view_test.h" |   10 #include "chrome/test/render_view_test.h" | 
|   11 #include "testing/gtest/include/gtest/gtest.h" |   11 #include "testing/gtest/include/gtest/gtest.h" | 
|   12 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" |   12 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" | 
|   13 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" |   13 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" | 
|   14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFormElement.h" |   14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFormElement.h" | 
|   15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h" |   15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h" | 
|   16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h" |   16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h" | 
|   17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" |   17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" | 
|   18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h" |   18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h" | 
|   19 #include "ui/base/keycodes/keyboard_codes.h" |   19 #include "ui/base/keycodes/keyboard_codes.h" | 
| (...skipping 26 matching lines...) Expand all  Loading... | 
|   46  |   46  | 
|   47 const char* const kFormHTML = |   47 const char* const kFormHTML = | 
|   48     "<FORM name='LoginTestForm' action='http://www.bidule.com'>" |   48     "<FORM name='LoginTestForm' action='http://www.bidule.com'>" | 
|   49     "  <INPUT type='text' id='username'/>" |   49     "  <INPUT type='text' id='username'/>" | 
|   50     "  <INPUT type='password' id='password'/>" |   50     "  <INPUT type='password' id='password'/>" | 
|   51     "  <INPUT type='submit' value='Login'/>" |   51     "  <INPUT type='submit' value='Login'/>" | 
|   52     "</FORM>"; |   52     "</FORM>"; | 
|   53  |   53  | 
|   54 }  // namespace |   54 }  // namespace | 
|   55  |   55  | 
|   56 class PasswordAutocompleteManagerTest : public RenderViewTest { |   56 namespace autofill { | 
 |   57  | 
 |   58 class PasswordAutoFillManagerTest : public RenderViewTest { | 
|   57  public: |   59  public: | 
|   58   PasswordAutocompleteManagerTest() { |   60   PasswordAutoFillManagerTest() { | 
|   59   } |   61   } | 
|   60  |   62  | 
|   61   // Simulates the fill password form message being sent to the renderer. |   63   // Simulates the fill password form message being sent to the renderer. | 
|   62   // We use that so we don't have to make RenderView::OnFillPasswordForm() |   64   // We use that so we don't have to make RenderView::OnFillPasswordForm() | 
|   63   // protected. |   65   // protected. | 
|   64   void SimulateOnFillPasswordForm( |   66   void SimulateOnFillPasswordForm( | 
|   65       const PasswordFormFillData& fill_data) { |   67       const PasswordFormFillData& fill_data) { | 
|   66     AutoFillMsg_FillPasswordForm msg(0, fill_data); |   68     AutoFillMsg_FillPasswordForm msg(0, fill_data); | 
|   67     password_autocomplete_->OnMessageReceived(msg); |   69     password_autofill_->OnMessageReceived(msg); | 
|   68   } |   70   } | 
|   69  |   71  | 
|   70   virtual void SetUp() { |   72   virtual void SetUp() { | 
|   71     RenderViewTest::SetUp(); |   73     RenderViewTest::SetUp(); | 
|   72  |   74  | 
|   73     // Add a preferred login and an additional login to the FillData. |   75     // Add a preferred login and an additional login to the FillData. | 
|   74     username1_ = ASCIIToUTF16(kAliceUsername); |   76     username1_ = ASCIIToUTF16(kAliceUsername); | 
|   75     password1_ = ASCIIToUTF16(kAlicePassword); |   77     password1_ = ASCIIToUTF16(kAlicePassword); | 
|   76     username2_ = ASCIIToUTF16(kBobUsername); |   78     username2_ = ASCIIToUTF16(kBobUsername); | 
|   77     password2_ = ASCIIToUTF16(kBobPassword); |   79     password2_ = ASCIIToUTF16(kBobPassword); | 
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  112     username_element_.setAutofilled(false); |  114     username_element_.setAutofilled(false); | 
|  113     password_element_.setValue(""); |  115     password_element_.setValue(""); | 
|  114     password_element_.setAutofilled(false); |  116     password_element_.setAutofilled(false); | 
|  115   } |  117   } | 
|  116  |  118  | 
|  117   void SimulateUsernameChange(const std::string& username, |  119   void SimulateUsernameChange(const std::string& username, | 
|  118                               bool move_caret_to_end) { |  120                               bool move_caret_to_end) { | 
|  119     username_element_.setValue(WebString::fromUTF8(username)); |  121     username_element_.setValue(WebString::fromUTF8(username)); | 
|  120     if (move_caret_to_end) |  122     if (move_caret_to_end) | 
|  121       username_element_.setSelectionRange(username.length(), username.length()); |  123       username_element_.setSelectionRange(username.length(), username.length()); | 
|  122     autofill_helper_->textFieldDidChange(username_element_); |  124     autofill_agent_->textFieldDidChange(username_element_); | 
|  123     // Processing is delayed because of a WebKit bug, see |  125     // Processing is delayed because of a WebKit bug, see | 
|  124     // PasswordAutocompleteManager::TextDidChangeInTextField() for details. |  126     // PasswordAutocompleteManager::TextDidChangeInTextField() for details. | 
|  125     MessageLoop::current()->RunAllPending(); |  127     MessageLoop::current()->RunAllPending(); | 
|  126   } |  128   } | 
|  127  |  129  | 
|  128   void SimulateKeyDownEvent(const WebInputElement& element, |  130   void SimulateKeyDownEvent(const WebInputElement& element, | 
|  129                             ui::KeyboardCode key_code) { |  131                             ui::KeyboardCode key_code) { | 
|  130     WebKit::WebKeyboardEvent key_event; |  132     WebKit::WebKeyboardEvent key_event; | 
|  131     key_event.windowsKeyCode = key_code; |  133     key_event.windowsKeyCode = key_code; | 
|  132     autofill_helper_->textFieldDidReceiveKeyDown(element, key_event); |  134     autofill_agent_->textFieldDidReceiveKeyDown(element, key_event); | 
|  133   } |  135   } | 
|  134  |  136  | 
|  135   void CheckTextFieldsState(const std::string& username, |  137   void CheckTextFieldsState(const std::string& username, | 
|  136                             bool username_autofilled, |  138                             bool username_autofilled, | 
|  137                             const std::string& password, |  139                             const std::string& password, | 
|  138                             bool password_autofilled) { |  140                             bool password_autofilled) { | 
|  139     EXPECT_EQ(username, |  141     EXPECT_EQ(username, | 
|  140               static_cast<std::string>(username_element_.value().utf8())); |  142               static_cast<std::string>(username_element_.value().utf8())); | 
|  141     EXPECT_EQ(username_autofilled, username_element_.isAutofilled()); |  143     EXPECT_EQ(username_autofilled, username_element_.isAutofilled()); | 
|  142     EXPECT_EQ(password, |  144     EXPECT_EQ(password, | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
|  154   string16 username3_; |  156   string16 username3_; | 
|  155   string16 password1_; |  157   string16 password1_; | 
|  156   string16 password2_; |  158   string16 password2_; | 
|  157   string16 password3_; |  159   string16 password3_; | 
|  158   PasswordFormFillData fill_data_; |  160   PasswordFormFillData fill_data_; | 
|  159  |  161  | 
|  160   WebInputElement username_element_; |  162   WebInputElement username_element_; | 
|  161   WebInputElement password_element_; |  163   WebInputElement password_element_; | 
|  162  |  164  | 
|  163  private: |  165  private: | 
|  164   DISALLOW_COPY_AND_ASSIGN(PasswordAutocompleteManagerTest); |  166   DISALLOW_COPY_AND_ASSIGN(PasswordAutoFillManagerTest); | 
|  165 }; |  167 }; | 
|  166  |  168  | 
 |  169 } | 
 |  170  | 
 |  171 using autofill::PasswordAutoFillManagerTest; | 
 |  172  | 
|  167 // Tests that the password login is autocompleted as expected when the browser |  173 // Tests that the password login is autocompleted as expected when the browser | 
|  168 // sends back the password info. |  174 // sends back the password info. | 
|  169 TEST_F(PasswordAutocompleteManagerTest, InitialAutocomplete) { |  175 TEST_F(PasswordAutoFillManagerTest, InitialAutocomplete) { | 
|  170   /* |  176   /* | 
|  171    * Right now we are not sending the message to the browser because we are |  177    * Right now we are not sending the message to the browser because we are | 
|  172    * loading a data URL and the security origin canAccessPasswordManager() |  178    * loading a data URL and the security origin canAccessPasswordManager() | 
|  173    * returns false.  May be we should mock URL loading to cirmcuvent this? |  179    * returns false.  May be we should mock URL loading to cirmcuvent this? | 
|  174    TODO(jcivelli): find a way to make the security origin not deny access to the |  180    TODO(jcivelli): find a way to make the security origin not deny access to the | 
|  175                    password manager and then reenable this code. |  181                    password manager and then reenable this code. | 
|  176  |  182  | 
|  177   // The form has been loaded, we should have sent the browser a message about |  183   // The form has been loaded, we should have sent the browser a message about | 
|  178   // the form. |  184   // the form. | 
|  179   const IPC::Message* msg = render_thread_.sink().GetFirstMessageMatching( |  185   const IPC::Message* msg = render_thread_.sink().GetFirstMessageMatching( | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
|  191  |  197  | 
|  192   // Simulate the browser sending back the login info, it triggers the |  198   // Simulate the browser sending back the login info, it triggers the | 
|  193   // autocomplete. |  199   // autocomplete. | 
|  194   SimulateOnFillPasswordForm(fill_data_); |  200   SimulateOnFillPasswordForm(fill_data_); | 
|  195  |  201  | 
|  196   // The username and password should have been autocompleted. |  202   // The username and password should have been autocompleted. | 
|  197   CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); |  203   CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); | 
|  198 } |  204 } | 
|  199  |  205  | 
|  200 // Tests that changing the username does not fill a read-only password field. |  206 // Tests that changing the username does not fill a read-only password field. | 
|  201 TEST_F(PasswordAutocompleteManagerTest, NoInitialAutocompleteForReadOnly) { |  207 TEST_F(PasswordAutoFillManagerTest, NoInitialAutocompleteForReadOnly) { | 
|  202   password_element_.setAttribute(WebString::fromUTF8("readonly"), |  208   password_element_.setAttribute(WebString::fromUTF8("readonly"), | 
|  203                                  WebString::fromUTF8("true")); |  209                                  WebString::fromUTF8("true")); | 
|  204  |  210  | 
|  205   // Simulate the browser sending back the login info, it triggers the |  211   // Simulate the browser sending back the login info, it triggers the | 
|  206   // autocompleted. |  212   // autocompleted. | 
|  207   SimulateOnFillPasswordForm(fill_data_); |  213   SimulateOnFillPasswordForm(fill_data_); | 
|  208  |  214  | 
|  209   // Only the username should have been autocompleted. |  215   // Only the username should have been autocompleted. | 
|  210   // TODO(jcivelli): may be we should not event fill the username? |  216   // TODO(jcivelli): may be we should not event fill the username? | 
|  211   CheckTextFieldsState(kAliceUsername, true, "", false); |  217   CheckTextFieldsState(kAliceUsername, true, "", false); | 
|  212 } |  218 } | 
|  213  |  219  | 
|  214 // Tests that editing the password clears the autocompleted password field. |  220 // Tests that editing the password clears the autocompleted password field. | 
|  215 TEST_F(PasswordAutocompleteManagerTest, PasswordClearOnEdit) { |  221 TEST_F(PasswordAutoFillManagerTest, PasswordClearOnEdit) { | 
|  216   // Simulate the browser sending back the login info, it triggers the |  222   // Simulate the browser sending back the login info, it triggers the | 
|  217   // autocomplete. |  223   // autocomplete. | 
|  218   SimulateOnFillPasswordForm(fill_data_); |  224   SimulateOnFillPasswordForm(fill_data_); | 
|  219  |  225  | 
|  220   // Simulate the user changing the username to some unknown username. |  226   // Simulate the user changing the username to some unknown username. | 
|  221   SimulateUsernameChange("alicia", true); |  227   SimulateUsernameChange("alicia", true); | 
|  222  |  228  | 
|  223   // The password should have been cleared. |  229   // The password should have been cleared. | 
|  224   CheckTextFieldsState("alicia", false, "", false); |  230   CheckTextFieldsState("alicia", false, "", false); | 
|  225 } |  231 } | 
|  226  |  232  | 
|  227 // Tests that we only autocomplete on focus lost and with a full username match |  233 // Tests that we only autocomplete on focus lost and with a full username match | 
|  228 // when |wait_for_username| is true. |  234 // when |wait_for_username| is true. | 
|  229 TEST_F(PasswordAutocompleteManagerTest, WaitUsername) { |  235 TEST_F(PasswordAutoFillManagerTest, WaitUsername) { | 
|  230   // Simulate the browser sending back the login info. |  236   // Simulate the browser sending back the login info. | 
|  231   fill_data_.wait_for_username = true; |  237   fill_data_.wait_for_username = true; | 
|  232   SimulateOnFillPasswordForm(fill_data_); |  238   SimulateOnFillPasswordForm(fill_data_); | 
|  233  |  239  | 
|  234   // No auto-fill should have taken place. |  240   // No auto-fill should have taken place. | 
|  235   CheckTextFieldsState("", false, "", false); |  241   CheckTextFieldsState("", false, "", false); | 
|  236  |  242  | 
|  237   // No autocomplete should happen when text is entered in the username. |  243   // No autocomplete should happen when text is entered in the username. | 
|  238   SimulateUsernameChange("a", true); |  244   SimulateUsernameChange("a", true); | 
|  239   CheckTextFieldsState("a", false, "", false); |  245   CheckTextFieldsState("a", false, "", false); | 
|  240   SimulateUsernameChange("al", true); |  246   SimulateUsernameChange("al", true); | 
|  241   CheckTextFieldsState("al", false, "", false); |  247   CheckTextFieldsState("al", false, "", false); | 
|  242   SimulateUsernameChange(kAliceUsername, true); |  248   SimulateUsernameChange(kAliceUsername, true); | 
|  243   CheckTextFieldsState(kAliceUsername, false, "", false); |  249   CheckTextFieldsState(kAliceUsername, false, "", false); | 
|  244  |  250  | 
|  245   // Autocomplete should happen only when the username textfield is blurred with |  251   // Autocomplete should happen only when the username textfield is blurred with | 
|  246   // a full match. |  252   // a full match. | 
|  247   username_element_.setValue("a"); |  253   username_element_.setValue("a"); | 
|  248   autofill_helper_->textFieldDidEndEditing(username_element_); |  254   autofill_agent_->textFieldDidEndEditing(username_element_); | 
|  249   CheckTextFieldsState("a", false, "", false); |  255   CheckTextFieldsState("a", false, "", false); | 
|  250   username_element_.setValue("al"); |  256   username_element_.setValue("al"); | 
|  251   autofill_helper_->textFieldDidEndEditing(username_element_); |  257   autofill_agent_->textFieldDidEndEditing(username_element_); | 
|  252   CheckTextFieldsState("al", false, "", false); |  258   CheckTextFieldsState("al", false, "", false); | 
|  253   username_element_.setValue("alices"); |  259   username_element_.setValue("alices"); | 
|  254   autofill_helper_->textFieldDidEndEditing(username_element_); |  260   autofill_agent_->textFieldDidEndEditing(username_element_); | 
|  255   CheckTextFieldsState("alices", false, "", false); |  261   CheckTextFieldsState("alices", false, "", false); | 
|  256   username_element_.setValue(ASCIIToUTF16(kAliceUsername)); |  262   username_element_.setValue(ASCIIToUTF16(kAliceUsername)); | 
|  257   autofill_helper_->textFieldDidEndEditing(username_element_); |  263   autofill_agent_->textFieldDidEndEditing(username_element_); | 
|  258   CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); |  264   CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); | 
|  259 } |  265 } | 
|  260  |  266  | 
|  261 // Tests that inline autocompletion works properly. |  267 // Tests that inline autocompletion works properly. | 
|  262 TEST_F(PasswordAutocompleteManagerTest, InlineAutocomplete) { |  268 TEST_F(PasswordAutoFillManagerTest, InlineAutocomplete) { | 
|  263   // Simulate the browser sending back the login info. |  269   // Simulate the browser sending back the login info. | 
|  264   SimulateOnFillPasswordForm(fill_data_); |  270   SimulateOnFillPasswordForm(fill_data_); | 
|  265  |  271  | 
|  266   // Clear the textfields to start fresh. |  272   // Clear the textfields to start fresh. | 
|  267   ClearUsernameAndPasswordFields(); |  273   ClearUsernameAndPasswordFields(); | 
|  268  |  274  | 
|  269   // Simulate the user typing in the first letter of 'alice', a stored username. |  275   // Simulate the user typing in the first letter of 'alice', a stored username. | 
|  270   SimulateUsernameChange("a", true); |  276   SimulateUsernameChange("a", true); | 
|  271   // Both the username and password textfields should reflect selection of the |  277   // Both the username and password textfields should reflect selection of the | 
|  272   // stored login. |  278   // stored login. | 
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  310   CheckUsernameSelection(1, 5); |  316   CheckUsernameSelection(1, 5); | 
|  311   // Finally, the user removes all the text and types a lowercase 'c'.  We only |  317   // Finally, the user removes all the text and types a lowercase 'c'.  We only | 
|  312   // want case-sensitive autocompletion, so the username and the selected range |  318   // want case-sensitive autocompletion, so the username and the selected range | 
|  313   // should be empty. |  319   // should be empty. | 
|  314   SimulateUsernameChange("c", true); |  320   SimulateUsernameChange("c", true); | 
|  315   CheckTextFieldsState("c", false, "", false); |  321   CheckTextFieldsState("c", false, "", false); | 
|  316   CheckUsernameSelection(1, 1); |  322   CheckUsernameSelection(1, 1); | 
|  317 } |  323 } | 
|  318  |  324  | 
|  319 // Tests that selecting and item in the suggestion drop-down works. |  325 // Tests that selecting and item in the suggestion drop-down works. | 
|  320 TEST_F(PasswordAutocompleteManagerTest, SuggestionSelect) { |  326 TEST_F(PasswordAutoFillManagerTest, SuggestionSelect) { | 
|  321   // Simulate the browser sending back the login info. |  327   // Simulate the browser sending back the login info. | 
|  322   SimulateOnFillPasswordForm(fill_data_); |  328   SimulateOnFillPasswordForm(fill_data_); | 
|  323  |  329  | 
|  324   // Clear the textfields to start fresh. |  330   // Clear the textfields to start fresh. | 
|  325   ClearUsernameAndPasswordFields(); |  331   ClearUsernameAndPasswordFields(); | 
|  326  |  332  | 
|  327   // To simulate a selection in the suggestion drop-down we just mimick what the |  333   // To simulate a selection in the suggestion drop-down we just mimick what the | 
|  328   // WebView does: it sets the element value then calls |  334   // WebView does: it sets the element value then calls | 
|  329   // didSelectAutoFillSuggestion on the renderer. |  335   // didSelectAutoFillSuggestion on the renderer. | 
|  330   autofill_helper_->didSelectAutoFillSuggestion(username_element_, |  336   autofill_agent_->didSelectAutoFillSuggestion(username_element_, | 
|  331                                                 ASCIIToUTF16(kAliceUsername), |  337                                                ASCIIToUTF16(kAliceUsername), | 
|  332                                                 WebKit::WebString(), |  338                                                WebKit::WebString(), | 
|  333                                                 0); |  339                                                0); | 
|  334  |  340  | 
|  335   // Autocomplete should have kicked in. |  341   // Autocomplete should have kicked in. | 
|  336   CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); |  342   CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); | 
|  337 } |  343 } | 
| OLD | NEW |