Index: chrome/renderer/autofill/password_autofill_manager_unittest.cc |
diff --git a/chrome/renderer/autofill/password_autofill_manager_unittest.cc b/chrome/renderer/autofill/password_autofill_manager_unittest.cc |
deleted file mode 100644 |
index b2c5d3a3808ada3249708abfb79da69505b2adb0..0000000000000000000000000000000000000000 |
--- a/chrome/renderer/autofill/password_autofill_manager_unittest.cc |
+++ /dev/null |
@@ -1,420 +0,0 @@ |
-// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "base/string_util.h" |
-#include "base/utf_string_conversions.h" |
-#include "chrome/common/autofill_messages.h" |
-#include "chrome/renderer/autofill/autofill_agent.h" |
-#include "chrome/renderer/autofill/password_autofill_manager.h" |
-#include "chrome/test/base/render_view_test.h" |
-#include "testing/gtest/include/gtest/gtest.h" |
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" |
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" |
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebFormElement.h" |
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h" |
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h" |
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" |
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h" |
-#include "ui/base/keycodes/keyboard_codes.h" |
-#include "webkit/glue/form_data.h" |
-#include "webkit/glue/form_field.h" |
- |
-using webkit_glue::FormField; |
-using webkit_glue::PasswordFormFillData; |
-using webkit_glue::PasswordForm; |
-using webkit_glue::PasswordFormDomManager; |
-using WebKit::WebDocument; |
-using WebKit::WebElement; |
-using WebKit::WebFrame; |
-using WebKit::WebInputElement; |
-using WebKit::WebString; |
- |
-namespace { |
- |
-// The name of the username/password element in the form. |
-const char* const kUsernameName = "username"; |
-const char* const kPasswordName = "password"; |
- |
-const char* const kAliceUsername = "alice"; |
-const char* const kAlicePassword = "password"; |
-const char* const kBobUsername = "bob"; |
-const char* const kBobPassword = "secret"; |
-const char* const kCarolUsername = "Carol"; |
-const char* const kCarolPassword = "test"; |
- |
- |
-const char* const kFormHTML = |
- "<FORM name='LoginTestForm' action='http://www.bidule.com'>" |
- " <INPUT type='text' id='username'/>" |
- " <INPUT type='password' id='password'/>" |
- " <INPUT type='submit' value='Login'/>" |
- "</FORM>"; |
- |
-} // namespace |
- |
-namespace autofill { |
- |
-class PasswordAutofillManagerTest : public RenderViewTest { |
- public: |
- PasswordAutofillManagerTest() { |
- } |
- |
- // Simulates the fill password form message being sent to the renderer. |
- // We use that so we don't have to make RenderView::OnFillPasswordForm() |
- // protected. |
- void SimulateOnFillPasswordForm( |
- const PasswordFormFillData& fill_data) { |
- AutofillMsg_FillPasswordForm msg(0, fill_data); |
- password_autofill_->OnMessageReceived(msg); |
- } |
- |
- virtual void SetUp() { |
- RenderViewTest::SetUp(); |
- |
- // Add a preferred login and an additional login to the FillData. |
- username1_ = ASCIIToUTF16(kAliceUsername); |
- password1_ = ASCIIToUTF16(kAlicePassword); |
- username2_ = ASCIIToUTF16(kBobUsername); |
- password2_ = ASCIIToUTF16(kBobPassword); |
- username3_ = ASCIIToUTF16(kCarolUsername); |
- password3_ = ASCIIToUTF16(kCarolPassword); |
- |
- fill_data_.basic_data.fields.push_back( |
- FormField(string16(), ASCIIToUTF16(kUsernameName), |
- username1_, string16(), 0, false)); |
- fill_data_.basic_data.fields.push_back( |
- FormField(string16(), ASCIIToUTF16(kPasswordName), |
- password1_, string16(), 0, false)); |
- fill_data_.additional_logins[username2_] = password2_; |
- fill_data_.additional_logins[username3_] = password3_; |
- |
- // We need to set the origin so it matches the frame URL and the action so |
- // it matches the form action, otherwise we won't autocomplete. |
- std::string origin("data:text/html;charset=utf-8,"); |
- origin += kFormHTML; |
- fill_data_.basic_data.origin = GURL(origin); |
- fill_data_.basic_data.action = GURL("http://www.bidule.com"); |
- |
- LoadHTML(kFormHTML); |
- |
- // Now retrieves the input elements so the test can access them. |
- WebDocument document = GetMainFrame()->document(); |
- WebElement element = |
- document.getElementById(WebString::fromUTF8(kUsernameName)); |
- ASSERT_FALSE(element.isNull()); |
- username_element_ = element.to<WebKit::WebInputElement>(); |
- element = document.getElementById(WebString::fromUTF8(kPasswordName)); |
- ASSERT_FALSE(element.isNull()); |
- password_element_ = element.to<WebKit::WebInputElement>(); |
- } |
- |
- void ClearUsernameAndPasswordFields() { |
- username_element_.setValue(""); |
- username_element_.setAutofilled(false); |
- password_element_.setValue(""); |
- password_element_.setAutofilled(false); |
- } |
- |
- void SimulateUsernameChange(const std::string& username, |
- bool move_caret_to_end) { |
- username_element_.setValue(WebString::fromUTF8(username)); |
- if (move_caret_to_end) |
- username_element_.setSelectionRange(username.length(), username.length()); |
- autofill_agent_->textFieldDidChange(username_element_); |
- // Processing is delayed because of a WebKit bug, see |
- // PasswordAutocompleteManager::TextDidChangeInTextField() for details. |
- MessageLoop::current()->RunAllPending(); |
- } |
- |
- void SimulateKeyDownEvent(const WebInputElement& element, |
- ui::KeyboardCode key_code) { |
- WebKit::WebKeyboardEvent key_event; |
- key_event.windowsKeyCode = key_code; |
- autofill_agent_->textFieldDidReceiveKeyDown(element, key_event); |
- } |
- |
- void CheckTextFieldsState(const std::string& username, |
- bool username_autofilled, |
- const std::string& password, |
- bool password_autofilled) { |
- EXPECT_EQ(username, |
- static_cast<std::string>(username_element_.value().utf8())); |
- EXPECT_EQ(username_autofilled, username_element_.isAutofilled()); |
- EXPECT_EQ(password, |
- static_cast<std::string>(password_element_.value().utf8())); |
- EXPECT_EQ(password_autofilled, password_element_.isAutofilled()); |
- } |
- |
- void CheckUsernameSelection(int start, int end) { |
- EXPECT_EQ(start, username_element_.selectionStart()); |
- EXPECT_EQ(end, username_element_.selectionEnd()); |
- } |
- |
- string16 username1_; |
- string16 username2_; |
- string16 username3_; |
- string16 password1_; |
- string16 password2_; |
- string16 password3_; |
- PasswordFormFillData fill_data_; |
- |
- WebInputElement username_element_; |
- WebInputElement password_element_; |
- |
- private: |
- DISALLOW_COPY_AND_ASSIGN(PasswordAutofillManagerTest); |
-}; |
- |
-} |
- |
-using autofill::PasswordAutofillManagerTest; |
- |
-// Tests that the password login is autocompleted as expected when the browser |
-// sends back the password info. |
-TEST_F(PasswordAutofillManagerTest, InitialAutocomplete) { |
- /* |
- * Right now we are not sending the message to the browser because we are |
- * loading a data URL and the security origin canAccessPasswordManager() |
- * returns false. May be we should mock URL loading to cirmcuvent this? |
- TODO(jcivelli): find a way to make the security origin not deny access to the |
- password manager and then reenable this code. |
- |
- // The form has been loaded, we should have sent the browser a message about |
- // the form. |
- const IPC::Message* msg = render_thread_.sink().GetFirstMessageMatching( |
- AutofillHostMsg_PasswordFormsFound::ID); |
- ASSERT_TRUE(msg != NULL); |
- |
- Tuple1<std::vector<PasswordForm> > forms; |
- AutofillHostMsg_PasswordFormsFound::Read(msg, &forms); |
- ASSERT_EQ(1U, forms.a.size()); |
- PasswordForm password_form = forms.a[0]; |
- EXPECT_EQ(PasswordForm::SCHEME_HTML, password_form.scheme); |
- EXPECT_EQ(ASCIIToUTF16(kUsernameName), password_form.username_element); |
- EXPECT_EQ(ASCIIToUTF16(kPasswordName), password_form.password_element); |
- */ |
- |
- // Simulate the browser sending back the login info, it triggers the |
- // autocomplete. |
- SimulateOnFillPasswordForm(fill_data_); |
- |
- // The username and password should have been autocompleted. |
- CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); |
-} |
- |
-// Tests that we correctly fill forms having an empty 'action' attribute. |
-TEST_F(PasswordAutofillManagerTest, InitialAutocompleteForEmptyAction) { |
- const char kEmptyActionFormHTML[] = |
- "<FORM name='LoginTestForm'>" |
- " <INPUT type='text' id='username'/>" |
- " <INPUT type='password' id='password'/>" |
- " <INPUT type='submit' value='Login'/>" |
- "</FORM>"; |
- LoadHTML(kEmptyActionFormHTML); |
- |
- // Retrieve the input elements so the test can access them. |
- WebDocument document = GetMainFrame()->document(); |
- WebElement element = |
- document.getElementById(WebString::fromUTF8(kUsernameName)); |
- ASSERT_FALSE(element.isNull()); |
- username_element_ = element.to<WebKit::WebInputElement>(); |
- element = document.getElementById(WebString::fromUTF8(kPasswordName)); |
- ASSERT_FALSE(element.isNull()); |
- password_element_ = element.to<WebKit::WebInputElement>(); |
- |
- // Set the expected form origin and action URLs. |
- std::string origin("data:text/html;charset=utf-8,"); |
- origin += kEmptyActionFormHTML; |
- fill_data_.basic_data.origin = GURL(origin); |
- fill_data_.basic_data.action = GURL(origin); |
- |
- // Simulate the browser sending back the login info, it triggers the |
- // autocomplete. |
- SimulateOnFillPasswordForm(fill_data_); |
- |
- // The username and password should have been autocompleted. |
- CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); |
-} |
- |
-// Tests that changing the username does not fill a read-only password field. |
-TEST_F(PasswordAutofillManagerTest, NoInitialAutocompleteForReadOnly) { |
- password_element_.setAttribute(WebString::fromUTF8("readonly"), |
- WebString::fromUTF8("true")); |
- |
- // Simulate the browser sending back the login info, it triggers the |
- // autocomplete. |
- SimulateOnFillPasswordForm(fill_data_); |
- |
- // Only the username should have been autocompleted. |
- // TODO(jcivelli): may be we should not event fill the username? |
- CheckTextFieldsState(kAliceUsername, true, "", false); |
-} |
- |
-// Tests that having a non-matching username precludes the autocomplete. |
-TEST_F(PasswordAutofillManagerTest, NoInitialAutocompleteForFilledField) { |
- username_element_.setValue(WebString::fromUTF8("bogus")); |
- |
- // Simulate the browser sending back the login info, it triggers the |
- // autocomplete. |
- SimulateOnFillPasswordForm(fill_data_); |
- |
- // Neither field should be autocompleted. |
- CheckTextFieldsState("bogus", false, "", false); |
-} |
- |
-// Tests that having a matching username does not preclude the autocomplete. |
-TEST_F(PasswordAutofillManagerTest, InitialAutocompleteForMatchingFilledField) { |
- username_element_.setValue(WebString::fromUTF8(kAliceUsername)); |
- |
- // Simulate the browser sending back the login info, it triggers the |
- // autocomplete. |
- SimulateOnFillPasswordForm(fill_data_); |
- |
- // The username and password should have been autocompleted. |
- CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); |
-} |
- |
-// Tests that editing the password clears the autocompleted password field. |
-TEST_F(PasswordAutofillManagerTest, PasswordClearOnEdit) { |
- // Simulate the browser sending back the login info, it triggers the |
- // autocomplete. |
- SimulateOnFillPasswordForm(fill_data_); |
- |
- // Simulate the user changing the username to some unknown username. |
- SimulateUsernameChange("alicia", true); |
- |
- // The password should have been cleared. |
- CheckTextFieldsState("alicia", false, "", false); |
-} |
- |
-// Tests that we only autocomplete on focus lost and with a full username match |
-// when |wait_for_username| is true. |
-TEST_F(PasswordAutofillManagerTest, WaitUsername) { |
- // Simulate the browser sending back the login info. |
- fill_data_.wait_for_username = true; |
- SimulateOnFillPasswordForm(fill_data_); |
- |
- // No auto-fill should have taken place. |
- CheckTextFieldsState("", false, "", false); |
- |
- // No autocomplete should happen when text is entered in the username. |
- SimulateUsernameChange("a", true); |
- CheckTextFieldsState("a", false, "", false); |
- SimulateUsernameChange("al", true); |
- CheckTextFieldsState("al", false, "", false); |
- SimulateUsernameChange(kAliceUsername, true); |
- CheckTextFieldsState(kAliceUsername, false, "", false); |
- |
- // Autocomplete should happen only when the username textfield is blurred with |
- // a full match. |
- username_element_.setValue("a"); |
- autofill_agent_->textFieldDidEndEditing(username_element_); |
- CheckTextFieldsState("a", false, "", false); |
- username_element_.setValue("al"); |
- autofill_agent_->textFieldDidEndEditing(username_element_); |
- CheckTextFieldsState("al", false, "", false); |
- username_element_.setValue("alices"); |
- autofill_agent_->textFieldDidEndEditing(username_element_); |
- CheckTextFieldsState("alices", false, "", false); |
- username_element_.setValue(ASCIIToUTF16(kAliceUsername)); |
- autofill_agent_->textFieldDidEndEditing(username_element_); |
- CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); |
-} |
- |
-// Tests that inline autocompletion works properly. |
-TEST_F(PasswordAutofillManagerTest, InlineAutocomplete) { |
- // Simulate the browser sending back the login info. |
- SimulateOnFillPasswordForm(fill_data_); |
- |
- // Clear the text fields to start fresh. |
- ClearUsernameAndPasswordFields(); |
- |
- // Simulate the user typing in the first letter of 'alice', a stored username. |
- SimulateUsernameChange("a", true); |
- // Both the username and password text fields should reflect selection of the |
- // stored login. |
- CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); |
- // And the selection should have been set to 'lice', the last 4 letters. |
- CheckUsernameSelection(1, 5); |
- |
- // Now the user types the next letter of the same username, 'l'. |
- SimulateUsernameChange("al", true); |
- // Now the fields should have the same value, but the selection should have a |
- // different start value. |
- CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); |
- CheckUsernameSelection(2, 5); |
- |
- // Test that deleting does not trigger autocomplete. |
- SimulateKeyDownEvent(username_element_, ui::VKEY_BACK); |
- SimulateUsernameChange("alic", true); |
- CheckTextFieldsState("alic", false, "", false); |
- CheckUsernameSelection(4, 4); // No selection. |
- // Reset the last pressed key to something other than backspace. |
- SimulateKeyDownEvent(username_element_, ui::VKEY_A); |
- |
- // Now lets say the user goes astray from the stored username and types the |
- // letter 'f', spelling 'alf'. We don't know alf (that's just sad), so in |
- // practice the username should no longer be 'alice' and the selected range |
- // should be empty. |
- SimulateUsernameChange("alf", true); |
- CheckTextFieldsState("alf", false, "", false); |
- CheckUsernameSelection(3, 3); // No selection. |
- |
- // Ok, so now the user removes all the text and enters the letter 'b'. |
- SimulateUsernameChange("b", true); |
- // The username and password fields should match the 'bob' entry. |
- CheckTextFieldsState(kBobUsername, true, kBobPassword, true); |
- CheckUsernameSelection(1, 3); |
- |
- // Then, the user again removes all the text and types an uppercase 'C'. |
- SimulateUsernameChange("C", true); |
- // The username and password fields should match the 'Carol' entry. |
- CheckTextFieldsState(kCarolUsername, true, kCarolPassword, true); |
- CheckUsernameSelection(1, 5); |
- // Finally, the user removes all the text and types a lowercase 'c'. We only |
- // want case-sensitive autocompletion, so the username and the selected range |
- // should be empty. |
- SimulateUsernameChange("c", true); |
- CheckTextFieldsState("c", false, "", false); |
- CheckUsernameSelection(1, 1); |
-} |
- |
-// Tests that accepting an item in the suggestion drop-down works. |
-TEST_F(PasswordAutofillManagerTest, SuggestionAccept) { |
- // Simulate the browser sending back the login info. |
- SimulateOnFillPasswordForm(fill_data_); |
- |
- // Clear the text fields to start fresh. |
- ClearUsernameAndPasswordFields(); |
- |
- // To simulate accepting an item in the suggestion drop-down we just mimic |
- // what the WebView does: it sets the element value then calls |
- // didAcceptAutofillSuggestion on the renderer. |
- autofill_agent_->didAcceptAutofillSuggestion(username_element_, |
- ASCIIToUTF16(kAliceUsername), |
- WebKit::WebString(), |
- 0, |
- 0); |
- // Autocomplete should have kicked in. |
- CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); |
-} |
- |
-// Tests that selecting an item in the suggestion drop-down no-ops. |
-TEST_F(PasswordAutofillManagerTest, SuggestionSelect) { |
- // Simulate the browser sending back the login info. |
- SimulateOnFillPasswordForm(fill_data_); |
- |
- // Clear the text fields to start fresh. |
- ClearUsernameAndPasswordFields(); |
- |
- // To simulate accepting an item in the suggestion drop-down we just mimic |
- // what the WebView does: it sets the element value then calls |
- // didSelectAutofillSuggestion on the renderer. |
- autofill_agent_->didSelectAutofillSuggestion(username_element_, |
- ASCIIToUTF16(kAliceUsername), |
- WebKit::WebString(), |
- 0); |
- // Autocomplete should not have kicked in. |
- CheckTextFieldsState("", false, "", false); |
-} |