OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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 <string.h> | 5 #include <string.h> |
6 | 6 |
7 #include "base/memory/scoped_ptr.h" | 7 #include "base/memory/scoped_ptr.h" |
8 #include "base/memory/scoped_vector.h" | |
9 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" |
10 #include "chrome/test/base/chrome_render_view_test.h" | 9 #include "chrome/test/base/chrome_render_view_test.h" |
11 #include "components/autofill/content/common/autofill_messages.h" | 10 #include "components/autofill/content/common/autofill_messages.h" |
12 #include "components/autofill/content/renderer/password_generation_agent.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" | 13 #include "components/autofill/core/common/form_data.h" |
14 #include "testing/gtest/include/gtest/gtest.h" | 14 #include "testing/gtest/include/gtest/gtest.h" |
15 #include "third_party/WebKit/public/platform/WebString.h" | 15 #include "third_party/WebKit/public/platform/WebString.h" |
16 #include "third_party/WebKit/public/web/WebDocument.h" | 16 #include "third_party/WebKit/public/web/WebDocument.h" |
17 #include "third_party/WebKit/public/web/WebWidget.h" | 17 #include "third_party/WebKit/public/web/WebWidget.h" |
18 | 18 |
19 using blink::WebDocument; | 19 using blink::WebDocument; |
20 using blink::WebElement; | 20 using blink::WebElement; |
21 using blink::WebInputElement; | 21 using blink::WebInputElement; |
22 using blink::WebNode; | 22 using blink::WebNode; |
23 using blink::WebString; | 23 using blink::WebString; |
24 | 24 |
25 namespace autofill { | 25 namespace autofill { |
26 | 26 |
27 class TestPasswordGenerationAgent : public PasswordGenerationAgent { | |
28 public: | |
29 explicit TestPasswordGenerationAgent(content::RenderView* view) | |
30 : PasswordGenerationAgent(view) {} | |
31 virtual ~TestPasswordGenerationAgent() {} | |
32 | |
33 // Make this public | |
34 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { | |
35 return PasswordGenerationAgent::OnMessageReceived(message); | |
36 } | |
37 | |
38 const std::vector<IPC::Message*>& messages() { | |
39 return messages_.get(); | |
40 } | |
41 | |
42 void ClearMessages() { | |
43 messages_.clear(); | |
44 } | |
45 | |
46 protected: | |
47 virtual bool ShouldAnalyzeDocument(const blink::WebDocument& document) const | |
48 OVERRIDE { | |
49 return true; | |
50 } | |
51 | |
52 virtual bool Send(IPC::Message* message) OVERRIDE { | |
53 messages_.push_back(message); | |
54 return true; | |
55 } | |
56 | |
57 private: | |
58 ScopedVector<IPC::Message> messages_; | |
59 | |
60 DISALLOW_COPY_AND_ASSIGN(TestPasswordGenerationAgent); | |
61 }; | |
62 | |
63 class PasswordGenerationAgentTest : public ChromeRenderViewTest { | 27 class PasswordGenerationAgentTest : public ChromeRenderViewTest { |
64 public: | 28 public: |
65 PasswordGenerationAgentTest() {} | 29 PasswordGenerationAgentTest() {} |
66 | 30 |
67 virtual void SetUp() { | |
68 // We don't actually create a PasswordGenerationAgent during | |
69 // ChromeRenderViewTest::SetUp because it's behind a flag. Since we want | |
70 // to use a test manager anyway, we just create our own. | |
71 ChromeRenderViewTest::SetUp(); | |
72 generation_manager_.reset(new TestPasswordGenerationAgent(view_)); | |
73 } | |
74 | |
75 virtual void TearDown() { | 31 virtual void TearDown() { |
76 LoadHTML(""); | 32 LoadHTML(""); |
77 generation_manager_.reset(); | |
78 ChromeRenderViewTest::TearDown(); | 33 ChromeRenderViewTest::TearDown(); |
79 } | 34 } |
80 | 35 |
81 void SimulateClickOnDecoration(blink::WebInputElement* input_element) { | |
82 generation_manager_->ClearMessages(); | |
83 blink::WebElement decoration = | |
84 input_element->decorationElementFor(generation_manager_.get()); | |
85 decoration.simulateClick(); | |
86 } | |
87 | |
88 bool DecorationIsVisible(blink::WebInputElement* input_element) { | |
89 blink::WebElement decoration = | |
90 input_element->decorationElementFor(generation_manager_.get()); | |
91 return decoration.hasNonEmptyBoundingBox(); | |
92 } | |
93 | |
94 void SetNotBlacklistedMessage(const char* form_str) { | 36 void SetNotBlacklistedMessage(const char* form_str) { |
95 autofill::PasswordForm form; | 37 autofill::PasswordForm form; |
96 form.origin = | 38 form.origin = |
97 GURL(base::StringPrintf("data:text/html;charset=utf-8,%s", form_str)); | 39 GURL(base::StringPrintf("data:text/html;charset=utf-8,%s", form_str)); |
98 AutofillMsg_FormNotBlacklisted msg(0, form); | 40 AutofillMsg_FormNotBlacklisted msg(0, form); |
99 generation_manager_->OnMessageReceived(msg); | 41 password_generation_->OnMessageReceived(msg); |
100 } | 42 } |
101 | 43 |
102 void SetAccountCreationFormsDetectedMessage(const char* form_str) { | 44 void SetAccountCreationFormsDetectedMessage(const char* form_str) { |
103 autofill::FormData form; | 45 autofill::FormData form; |
104 form.origin = | 46 form.origin = |
105 GURL(base::StringPrintf("data:text/html;charset=utf-8,%s", form_str)); | 47 GURL(base::StringPrintf("data:text/html;charset=utf-8,%s", form_str)); |
106 std::vector<autofill::FormData> forms; | 48 std::vector<autofill::FormData> forms; |
107 forms.push_back(form); | 49 forms.push_back(form); |
108 AutofillMsg_AccountCreationFormsDetected msg(0, forms); | 50 AutofillMsg_AccountCreationFormsDetected msg(0, forms); |
109 generation_manager_->OnMessageReceived(msg); | 51 password_generation_->OnMessageReceived(msg); |
110 } | 52 } |
111 | 53 |
112 void ExpectPasswordGenerationIconShown(const char* element_id, bool shown) { | 54 void ExpectPasswordGenerationAvailable(const char* element_id, |
| 55 bool available) { |
113 WebDocument document = GetMainFrame()->document(); | 56 WebDocument document = GetMainFrame()->document(); |
114 WebElement element = | 57 WebElement element = |
115 document.getElementById(WebString::fromUTF8(element_id)); | 58 document.getElementById(WebString::fromUTF8(element_id)); |
116 ASSERT_FALSE(element.isNull()); | 59 ASSERT_FALSE(element.isNull()); |
117 WebInputElement target_element = element.to<WebInputElement>(); | 60 WebInputElement target_element = element.to<WebInputElement>(); |
118 if (shown) { | 61 ExecuteJavaScript( |
119 EXPECT_TRUE(DecorationIsVisible(&target_element)); | 62 base::StringPrintf("document.getElementById('%s').focus();", |
120 SimulateClickOnDecoration(&target_element); | 63 element_id).c_str()); |
121 EXPECT_EQ(1u, generation_manager_->messages().size()); | 64 if (available) { |
| 65 ASSERT_EQ(1u, password_generation_->messages().size()); |
122 EXPECT_EQ(AutofillHostMsg_ShowPasswordGenerationPopup::ID, | 66 EXPECT_EQ(AutofillHostMsg_ShowPasswordGenerationPopup::ID, |
123 generation_manager_->messages()[0]->type()); | 67 password_generation_->messages()[0]->type()); |
124 } else { | 68 } else { |
125 EXPECT_FALSE(DecorationIsVisible(&target_element)); | 69 EXPECT_EQ(0u, password_generation_->messages().size()); |
126 } | 70 } |
| 71 password_generation_->clear_messages(); |
127 } | 72 } |
128 | 73 |
129 protected: | |
130 scoped_ptr<TestPasswordGenerationAgent> generation_manager_; | |
131 | |
132 private: | 74 private: |
133 DISALLOW_COPY_AND_ASSIGN(PasswordGenerationAgentTest); | 75 DISALLOW_COPY_AND_ASSIGN(PasswordGenerationAgentTest); |
134 }; | 76 }; |
135 | 77 |
136 const char kSigninFormHTML[] = | 78 const char kSigninFormHTML[] = |
137 "<FORM name = 'blah' action = 'http://www.random.com/'> " | 79 "<FORM name = 'blah' action = 'http://www.random.com/'> " |
138 " <INPUT type = 'text' id = 'username'/> " | 80 " <INPUT type = 'text' id = 'username'/> " |
139 " <INPUT type = 'password' id = 'password'/> " | 81 " <INPUT type = 'password' id = 'password'/> " |
140 " <INPUT type = 'submit' value = 'LOGIN' />" | 82 " <INPUT type = 'submit' value = 'LOGIN' />" |
141 "</FORM>"; | 83 "</FORM>"; |
(...skipping 20 matching lines...) Expand all Loading... |
162 "<FORM name = 'blah' action = 'invalid'> " | 104 "<FORM name = 'blah' action = 'invalid'> " |
163 " <INPUT type = 'text' id = 'username'/> " | 105 " <INPUT type = 'text' id = 'username'/> " |
164 " <INPUT type = 'password' id = 'first_password'/> " | 106 " <INPUT type = 'password' id = 'first_password'/> " |
165 " <INPUT type = 'password' id = 'second_password'/> " | 107 " <INPUT type = 'password' id = 'second_password'/> " |
166 " <INPUT type = 'submit' value = 'LOGIN' />" | 108 " <INPUT type = 'submit' value = 'LOGIN' />" |
167 "</FORM>"; | 109 "</FORM>"; |
168 | 110 |
169 TEST_F(PasswordGenerationAgentTest, DetectionTest) { | 111 TEST_F(PasswordGenerationAgentTest, DetectionTest) { |
170 // Don't shown the icon for non account creation forms. | 112 // Don't shown the icon for non account creation forms. |
171 LoadHTML(kSigninFormHTML); | 113 LoadHTML(kSigninFormHTML); |
172 ExpectPasswordGenerationIconShown("password", false); | 114 ExpectPasswordGenerationAvailable("password", false); |
173 | 115 |
174 // We don't show the decoration yet because the feature isn't enabled. | 116 // We don't show the decoration yet because the feature isn't enabled. |
175 LoadHTML(kAccountCreationFormHTML); | 117 LoadHTML(kAccountCreationFormHTML); |
176 ExpectPasswordGenerationIconShown("first_password", false); | 118 ExpectPasswordGenerationAvailable("first_password", false); |
177 | 119 |
178 // Pretend like We have received message indicating site is not blacklisted, | 120 // Pretend like We have received message indicating site is not blacklisted, |
179 // and we have received message indicating the form is classified as | 121 // and we have received message indicating the form is classified as |
180 // ACCOUNT_CREATION_FORM form Autofill server. We should show the icon. | 122 // ACCOUNT_CREATION_FORM form Autofill server. We should show the icon. |
181 LoadHTML(kAccountCreationFormHTML); | 123 LoadHTML(kAccountCreationFormHTML); |
182 SetNotBlacklistedMessage(kAccountCreationFormHTML); | 124 SetNotBlacklistedMessage(kAccountCreationFormHTML); |
183 SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML); | 125 SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML); |
184 ExpectPasswordGenerationIconShown("first_password", true); | 126 ExpectPasswordGenerationAvailable("first_password", true); |
185 | 127 |
186 // This doesn't trigger because hidden password fields are ignored. | 128 // This doesn't trigger because hidden password fields are ignored. |
187 LoadHTML(kHiddenPasswordAccountCreationFormHTML); | 129 LoadHTML(kHiddenPasswordAccountCreationFormHTML); |
188 SetNotBlacklistedMessage(kHiddenPasswordAccountCreationFormHTML); | 130 SetNotBlacklistedMessage(kHiddenPasswordAccountCreationFormHTML); |
189 SetAccountCreationFormsDetectedMessage( | 131 SetAccountCreationFormsDetectedMessage( |
190 kHiddenPasswordAccountCreationFormHTML); | 132 kHiddenPasswordAccountCreationFormHTML); |
191 ExpectPasswordGenerationIconShown("first_password", false); | 133 ExpectPasswordGenerationAvailable("first_password", false); |
192 | 134 |
193 // This doesn't trigger because the form action is invalid. | 135 // This doesn't trigger because the form action is invalid. |
194 LoadHTML(kInvalidActionAccountCreationFormHTML); | 136 LoadHTML(kInvalidActionAccountCreationFormHTML); |
195 SetNotBlacklistedMessage(kInvalidActionAccountCreationFormHTML); | 137 SetNotBlacklistedMessage(kInvalidActionAccountCreationFormHTML); |
196 SetAccountCreationFormsDetectedMessage(kInvalidActionAccountCreationFormHTML); | 138 SetAccountCreationFormsDetectedMessage(kInvalidActionAccountCreationFormHTML); |
197 ExpectPasswordGenerationIconShown("first_password", false); | 139 ExpectPasswordGenerationAvailable("first_password", false); |
198 } | 140 } |
199 | 141 |
200 TEST_F(PasswordGenerationAgentTest, FillTest) { | 142 TEST_F(PasswordGenerationAgentTest, FillTest) { |
201 // Make sure that we are enabled before loading HTML. | 143 // Make sure that we are enabled before loading HTML. |
202 LoadHTML(kAccountCreationFormHTML); | 144 LoadHTML(kAccountCreationFormHTML); |
203 | 145 |
204 WebDocument document = GetMainFrame()->document(); | 146 WebDocument document = GetMainFrame()->document(); |
205 WebElement element = | 147 WebElement element = |
206 document.getElementById(WebString::fromUTF8("first_password")); | 148 document.getElementById(WebString::fromUTF8("first_password")); |
207 ASSERT_FALSE(element.isNull()); | 149 ASSERT_FALSE(element.isNull()); |
208 WebInputElement first_password_element = element.to<WebInputElement>(); | 150 WebInputElement first_password_element = element.to<WebInputElement>(); |
209 element = document.getElementById(WebString::fromUTF8("second_password")); | 151 element = document.getElementById(WebString::fromUTF8("second_password")); |
210 ASSERT_FALSE(element.isNull()); | 152 ASSERT_FALSE(element.isNull()); |
211 WebInputElement second_password_element = element.to<WebInputElement>(); | 153 WebInputElement second_password_element = element.to<WebInputElement>(); |
212 | 154 |
213 // Both password fields should be empty. | 155 // Both password fields should be empty. |
214 EXPECT_TRUE(first_password_element.value().isNull()); | 156 EXPECT_TRUE(first_password_element.value().isNull()); |
215 EXPECT_TRUE(second_password_element.value().isNull()); | 157 EXPECT_TRUE(second_password_element.value().isNull()); |
216 | 158 |
217 base::string16 password = base::ASCIIToUTF16("random_password"); | 159 base::string16 password = base::ASCIIToUTF16("random_password"); |
218 AutofillMsg_GeneratedPasswordAccepted msg(0, password); | 160 AutofillMsg_GeneratedPasswordAccepted msg(0, password); |
219 generation_manager_->OnMessageReceived(msg); | 161 password_generation_->OnMessageReceived(msg); |
220 | 162 |
221 // Password fields are filled out and set as being autofilled. | 163 // Password fields are filled out and set as being autofilled. |
222 EXPECT_EQ(password, first_password_element.value()); | 164 EXPECT_EQ(password, first_password_element.value()); |
223 EXPECT_EQ(password, second_password_element.value()); | 165 EXPECT_EQ(password, second_password_element.value()); |
224 EXPECT_TRUE(first_password_element.isAutofilled()); | 166 EXPECT_TRUE(first_password_element.isAutofilled()); |
225 EXPECT_TRUE(second_password_element.isAutofilled()); | 167 EXPECT_TRUE(second_password_element.isAutofilled()); |
226 | 168 |
227 // Focus moved to the next input field. | 169 // Focus moved to the next input field. |
228 // TODO(zysxqn): Change this back to the address element once Bug 90224 | 170 // TODO(zysxqn): Change this back to the address element once Bug 90224 |
229 // https://bugs.webkit.org/show_bug.cgi?id=90224 has been fixed. | 171 // https://bugs.webkit.org/show_bug.cgi?id=90224 has been fixed. |
230 element = document.getElementById(WebString::fromUTF8("first_password")); | 172 element = document.getElementById(WebString::fromUTF8("first_password")); |
231 ASSERT_FALSE(element.isNull()); | 173 ASSERT_FALSE(element.isNull()); |
232 EXPECT_EQ(element, document.focusedNode()); | 174 EXPECT_EQ(element, document.focusedNode()); |
233 } | 175 } |
234 | 176 |
| 177 TEST_F(PasswordGenerationAgentTest, EditingTest) { |
| 178 LoadHTML(kAccountCreationFormHTML); |
| 179 SetNotBlacklistedMessage(kAccountCreationFormHTML); |
| 180 SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML); |
| 181 |
| 182 WebDocument document = GetMainFrame()->document(); |
| 183 WebElement element = |
| 184 document.getElementById(WebString::fromUTF8("first_password")); |
| 185 ASSERT_FALSE(element.isNull()); |
| 186 WebInputElement first_password_element = element.to<WebInputElement>(); |
| 187 element = document.getElementById(WebString::fromUTF8("second_password")); |
| 188 ASSERT_FALSE(element.isNull()); |
| 189 WebInputElement second_password_element = element.to<WebInputElement>(); |
| 190 |
| 191 base::string16 password = base::ASCIIToUTF16("random_password"); |
| 192 AutofillMsg_GeneratedPasswordAccepted msg(0, password); |
| 193 password_generation_->OnMessageReceived(msg); |
| 194 |
| 195 // Passwords start out the same. |
| 196 EXPECT_EQ(password, first_password_element.value()); |
| 197 EXPECT_EQ(password, second_password_element.value()); |
| 198 |
| 199 // After editing the first field they are still the same. |
| 200 base::string16 edited_password = base::ASCIIToUTF16("edited_password"); |
| 201 first_password_element.setValue(edited_password); |
| 202 // Cast to WebAutofillClient where textFieldDidChange() is public. |
| 203 static_cast<blink::WebAutofillClient*>(autofill_agent_)->textFieldDidChange( |
| 204 first_password_element); |
| 205 // textFieldDidChange posts a task, so we need to wait until it's been |
| 206 // processed. |
| 207 base::MessageLoop::current()->RunUntilIdle(); |
| 208 |
| 209 EXPECT_EQ(edited_password, first_password_element.value()); |
| 210 EXPECT_EQ(edited_password, second_password_element.value()); |
| 211 } |
| 212 |
235 TEST_F(PasswordGenerationAgentTest, BlacklistedTest) { | 213 TEST_F(PasswordGenerationAgentTest, BlacklistedTest) { |
236 // Did not receive not blacklisted message. Don't show password generation | 214 // Did not receive not blacklisted message. Don't show password generation |
237 // icon. | 215 // icon. |
238 LoadHTML(kAccountCreationFormHTML); | 216 LoadHTML(kAccountCreationFormHTML); |
239 SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML); | 217 SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML); |
240 ExpectPasswordGenerationIconShown("first_password", false); | 218 ExpectPasswordGenerationAvailable("first_password", false); |
241 | 219 |
242 // Receive one not blacklisted message for non account creation form. Don't | 220 // Receive one not blacklisted message for non account creation form. Don't |
243 // show password generation icon. | 221 // show password generation icon. |
244 LoadHTML(kAccountCreationFormHTML); | 222 LoadHTML(kAccountCreationFormHTML); |
245 SetNotBlacklistedMessage(kSigninFormHTML); | 223 SetNotBlacklistedMessage(kSigninFormHTML); |
246 SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML); | 224 SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML); |
247 ExpectPasswordGenerationIconShown("first_password", false); | 225 ExpectPasswordGenerationAvailable("first_password", false); |
248 | 226 |
249 // Receive one not blackliste message for account creation form. Show password | 227 // Receive one not blackliste message for account creation form. Show password |
250 // generation icon. | 228 // generation icon. |
251 LoadHTML(kAccountCreationFormHTML); | 229 LoadHTML(kAccountCreationFormHTML); |
252 SetNotBlacklistedMessage(kAccountCreationFormHTML); | 230 SetNotBlacklistedMessage(kAccountCreationFormHTML); |
253 SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML); | 231 SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML); |
254 ExpectPasswordGenerationIconShown("first_password", true); | 232 ExpectPasswordGenerationAvailable("first_password", true); |
255 | 233 |
256 // Receive two not blacklisted messages, one is for account creation form and | 234 // Receive two not blacklisted messages, one is for account creation form and |
257 // the other is not. Show password generation icon. | 235 // the other is not. Show password generation icon. |
258 LoadHTML(kAccountCreationFormHTML); | 236 LoadHTML(kAccountCreationFormHTML); |
259 SetNotBlacklistedMessage(kAccountCreationFormHTML); | 237 SetNotBlacklistedMessage(kAccountCreationFormHTML); |
260 SetNotBlacklistedMessage(kSigninFormHTML); | 238 SetNotBlacklistedMessage(kSigninFormHTML); |
261 SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML); | 239 SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML); |
262 ExpectPasswordGenerationIconShown("first_password", true); | 240 ExpectPasswordGenerationAvailable("first_password", true); |
263 } | 241 } |
264 | 242 |
265 TEST_F(PasswordGenerationAgentTest, AccountCreationFormsDetectedTest) { | 243 TEST_F(PasswordGenerationAgentTest, AccountCreationFormsDetectedTest) { |
266 // Did not receive account creation forms detected messege. Don't show | 244 // Did not receive account creation forms detected messege. Don't show |
267 // password generation icon. | 245 // password generation icon. |
268 LoadHTML(kAccountCreationFormHTML); | 246 LoadHTML(kAccountCreationFormHTML); |
269 SetNotBlacklistedMessage(kAccountCreationFormHTML); | 247 SetNotBlacklistedMessage(kAccountCreationFormHTML); |
270 ExpectPasswordGenerationIconShown("first_password", false); | 248 ExpectPasswordGenerationAvailable("first_password", false); |
271 | 249 |
272 // Receive the account creation forms detected message. Show password | 250 // Receive the account creation forms detected message. Show password |
273 // generation icon. | 251 // generation icon. |
274 LoadHTML(kAccountCreationFormHTML); | 252 LoadHTML(kAccountCreationFormHTML); |
275 SetNotBlacklistedMessage(kAccountCreationFormHTML); | 253 SetNotBlacklistedMessage(kAccountCreationFormHTML); |
276 SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML); | 254 SetAccountCreationFormsDetectedMessage(kAccountCreationFormHTML); |
277 ExpectPasswordGenerationIconShown("first_password", true); | 255 ExpectPasswordGenerationAvailable("first_password", true); |
278 } | 256 } |
279 | 257 |
280 } // namespace autofill | 258 } // namespace autofill |
OLD | NEW |