| 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 |