1 // Copyright 2013 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.
7 #include "base/memory/scoped_ptr.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/test/base/chrome_render_view_test.h"
10 #include "components/autofill/content/common/autofill_messages.h"
11 #include "components/autofill/content/renderer/autofill_agent.h"
12 #include "components/autofill/content/renderer/test_password_generation_agent.h"
13 #include "components/autofill/core/common/form_data.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "third_party/WebKit/public/platform/WebString.h"
16 #include "third_party/WebKit/public/web/WebDocument.h"
17 #include "third_party/WebKit/public/web/WebLocalFrame.h"
18 #include "third_party/WebKit/public/web/WebWidget.h"
20 using blink::WebDocument;
21 using blink::WebElement;
22 using blink::WebInputElement;
24 using blink::WebString;
28 class PasswordGenerationAgentTest : public ChromeRenderViewTest {
30 PasswordGenerationAgentTest() {}
32 virtual void TearDown() {
34 ChromeRenderViewTest::TearDown();
37 void SetNotBlacklistedMessage(const char* form_str) {
38 autofill::PasswordForm form;
40 GURL(base::StringPrintf("data:text/html;charset=utf-8,%s", form_str));
41 AutofillMsg_FormNotBlacklisted msg(0, form);
42 password_generation_->OnMessageReceived(msg);
45 void SetAccountCreationFormsDetectedMessage(const char* form_str) {
46 autofill::FormData form;
48 GURL(base::StringPrintf("data:text/html;charset=utf-8,%s", form_str));
49 std::vector<autofill::FormData> forms;
50 forms.push_back(form);
51 AutofillMsg_AccountCreationFormsDetected msg(0, forms);
52 password_generation_->OnMessageReceived(msg);
55 void ExpectPasswordGenerationAvailable(const char* element_id,
57 WebDocument document = GetMainFrame()->document();
59 document.getElementById(WebString::fromUTF8(element_id));
60 ASSERT_FALSE(element.isNull());
61 WebInputElement target_element = element.to<WebInputElement>();
63 base::StringPrintf("document.getElementById('%s').focus();",
66 ASSERT_EQ(1u, password_generation_->messages().size());
67 EXPECT_EQ(AutofillHostMsg_ShowPasswordGenerationPopup::ID,
68 password_generation_->messages()[0]->type());
70 EXPECT_EQ(0u, password_generation_->messages().size());
72 password_generation_->clear_messages();
76 DISALLOW_COPY_AND_ASSIGN(PasswordGenerationAgentTest);
79 const char kSigninFormHTML[] =
80 "<FORM name = 'blah' action = 'http://www.random.com/'> "
81 " <INPUT type = 'text' id = 'username'/> "
82 " <INPUT type = 'password' id = 'password'/> "
83 " <INPUT type = 'submit' value = 'LOGIN' />"
86 const char kAccountCreationFormHTML[] =
87 "<FORM name = 'blah' action = 'http://www.random.com/'> "
88 " <INPUT type = 'text' id = 'username'/> "
89 " <INPUT type = 'password' id = 'first_password' "
90 " autocomplete = 'off' size = 5/>"
91 " <INPUT type = 'password' id = 'second_password' size = 5/> "
92 " <INPUT type = 'text' id = 'address'/> "
93 " <INPUT type = 'submit' value = 'LOGIN' />"
96 const char kHiddenPasswordAccountCreationFormHTML[] =
97 "<FORM name = 'blah' action = 'http://www.random.com/'> "
98 " <INPUT type = 'text' id = 'username'/> "
99 " <INPUT type = 'password' id = 'first_password'/> "
100 " <INPUT type = 'password' id = 'second_password' style='display:none'/> "
101 " <INPUT type = 'submit' value = 'LOGIN' />"
104 const char kInvalidActionAccountCreationFormHTML[] =
105 "<FORM name = 'blah' action = 'invalid'> "
106 " <INPUT type = 'text' id = 'username'/> "
107 " <INPUT type = 'password' id = 'first_password'/> "
108 " <INPUT type = 'password' id = 'second_password'/> "
109 " <INPUT type = 'submit' value = 'LOGIN' />"
112 TEST_F(PasswordGenerationAgentTest, DetectionTest) {
113 // Don't shown the icon for non account creation forms.
114 LoadHTML(kSigninFormHTML);
115 ExpectPasswordGenerationAvailable("password", false);
117 // We don't show the decoration yet because the feature isn't enabled.
118 LoadHTML(kAccountCreationFormHTML);
119 ExpectPasswordGenerationAvailable("first_password", false);
121 // Pretend like We have received message indicating site is not blacklisted,
122 // and we have received message indicating the form is classified as
123 // ACCOUNT_CREATION_FORM form Autofill server. We should show the icon.
124 LoadHTML(kAccountCreationFormHTML);
125 SetNotBlacklistedMessage(kAccountCreationFormHTML);
126 SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML);
127 ExpectPasswordGenerationAvailable("first_password", true);
129 // This doesn't trigger because hidden password fields are ignored.
130 LoadHTML(kHiddenPasswordAccountCreationFormHTML);
131 SetNotBlacklistedMessage(kHiddenPasswordAccountCreationFormHTML);
132 SetAccountCreationFormsDetectedMessage(
133 kHiddenPasswordAccountCreationFormHTML);
134 ExpectPasswordGenerationAvailable("first_password", false);
136 // This doesn't trigger because the form action is invalid.
137 LoadHTML(kInvalidActionAccountCreationFormHTML);
138 SetNotBlacklistedMessage(kInvalidActionAccountCreationFormHTML);
139 SetAccountCreationFormsDetectedMessage(kInvalidActionAccountCreationFormHTML);
140 ExpectPasswordGenerationAvailable("first_password", false);
143 TEST_F(PasswordGenerationAgentTest, FillTest) {
144 // Make sure that we are enabled before loading HTML.
145 LoadHTML(kAccountCreationFormHTML);
147 WebDocument document = GetMainFrame()->document();
149 document.getElementById(WebString::fromUTF8("first_password"));
150 ASSERT_FALSE(element.isNull());
151 WebInputElement first_password_element = element.to<WebInputElement>();
152 element = document.getElementById(WebString::fromUTF8("second_password"));
153 ASSERT_FALSE(element.isNull());
154 WebInputElement second_password_element = element.to<WebInputElement>();
156 // Both password fields should be empty.
157 EXPECT_TRUE(first_password_element.value().isNull());
158 EXPECT_TRUE(second_password_element.value().isNull());
160 base::string16 password = base::ASCIIToUTF16("random_password");
161 AutofillMsg_GeneratedPasswordAccepted msg(0, password);
162 password_generation_->OnMessageReceived(msg);
164 // Password fields are filled out and set as being autofilled.
165 EXPECT_EQ(password, first_password_element.value());
166 EXPECT_EQ(password, second_password_element.value());
167 EXPECT_TRUE(first_password_element.isAutofilled());
168 EXPECT_TRUE(second_password_element.isAutofilled());
170 // Focus moved to the next input field.
171 // TODO(zysxqn): Change this back to the address element once Bug 90224
172 // https://bugs.webkit.org/show_bug.cgi?id=90224 has been fixed.
173 element = document.getElementById(WebString::fromUTF8("first_password"));
174 ASSERT_FALSE(element.isNull());
175 EXPECT_EQ(element, document.focusedElement());
178 TEST_F(PasswordGenerationAgentTest, EditingTest) {
179 LoadHTML(kAccountCreationFormHTML);
180 SetNotBlacklistedMessage(kAccountCreationFormHTML);
181 SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML);
183 WebDocument document = GetMainFrame()->document();
185 document.getElementById(WebString::fromUTF8("first_password"));
186 ASSERT_FALSE(element.isNull());
187 WebInputElement first_password_element = element.to<WebInputElement>();
188 element = document.getElementById(WebString::fromUTF8("second_password"));
189 ASSERT_FALSE(element.isNull());
190 WebInputElement second_password_element = element.to<WebInputElement>();
192 base::string16 password = base::ASCIIToUTF16("random_password");
193 AutofillMsg_GeneratedPasswordAccepted msg(0, password);
194 password_generation_->OnMessageReceived(msg);
196 // Passwords start out the same.
197 EXPECT_EQ(password, first_password_element.value());
198 EXPECT_EQ(password, second_password_element.value());
200 // After editing the first field they are still the same.
201 base::string16 edited_password = base::ASCIIToUTF16("edited_password");
202 first_password_element.setValue(edited_password);
203 // Cast to WebAutofillClient where textFieldDidChange() is public.
204 static_cast<blink::WebAutofillClient*>(autofill_agent_)->textFieldDidChange(
205 first_password_element);
206 // textFieldDidChange posts a task, so we need to wait until it's been
208 base::MessageLoop::current()->RunUntilIdle();
210 EXPECT_EQ(edited_password, first_password_element.value());
211 EXPECT_EQ(edited_password, second_password_element.value());
214 TEST_F(PasswordGenerationAgentTest, BlacklistedTest) {
215 // Did not receive not blacklisted message. Don't show password generation
217 LoadHTML(kAccountCreationFormHTML);
218 SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML);
219 ExpectPasswordGenerationAvailable("first_password", false);
221 // Receive one not blacklisted message for non account creation form. Don't
222 // show password generation icon.
223 LoadHTML(kAccountCreationFormHTML);
224 SetNotBlacklistedMessage(kSigninFormHTML);
225 SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML);
226 ExpectPasswordGenerationAvailable("first_password", false);
228 // Receive one not blackliste message for account creation form. Show password
230 LoadHTML(kAccountCreationFormHTML);
231 SetNotBlacklistedMessage(kAccountCreationFormHTML);
232 SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML);
233 ExpectPasswordGenerationAvailable("first_password", true);
235 // Receive two not blacklisted messages, one is for account creation form and
236 // the other is not. Show password generation icon.
237 LoadHTML(kAccountCreationFormHTML);
238 SetNotBlacklistedMessage(kAccountCreationFormHTML);
239 SetNotBlacklistedMessage(kSigninFormHTML);
240 SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML);
241 ExpectPasswordGenerationAvailable("first_password", true);
244 TEST_F(PasswordGenerationAgentTest, AccountCreationFormsDetectedTest) {
245 // Did not receive account creation forms detected messege. Don't show
246 // password generation icon.
247 LoadHTML(kAccountCreationFormHTML);
248 SetNotBlacklistedMessage(kAccountCreationFormHTML);
249 ExpectPasswordGenerationAvailable("first_password", false);
251 // Receive the account creation forms detected message. Show password
253 LoadHTML(kAccountCreationFormHTML);
254 SetNotBlacklistedMessage(kAccountCreationFormHTML);
255 SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML);
256 ExpectPasswordGenerationAvailable("first_password", true);
259 } // namespace autofill