Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / renderer / autofill / password_generation_agent_browsertest.cc
blobcd8e276aa6e8556a188e7f57e636d9071b93deb5
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.
5 #include <string.h>
7 #include "base/memory/scoped_ptr.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "base/test/histogram_tester.h"
10 #include "chrome/renderer/autofill/password_generation_test_utils.h"
11 #include "chrome/test/base/chrome_render_view_test.h"
12 #include "components/autofill/content/common/autofill_messages.h"
13 #include "components/autofill/content/renderer/autofill_agent.h"
14 #include "components/autofill/content/renderer/test_password_generation_agent.h"
15 #include "components/autofill/core/common/form_data.h"
16 #include "components/autofill/core/common/password_generation_util.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "third_party/WebKit/public/platform/WebString.h"
19 #include "third_party/WebKit/public/web/WebDocument.h"
20 #include "third_party/WebKit/public/web/WebLocalFrame.h"
21 #include "third_party/WebKit/public/web/WebWidget.h"
22 #include "ui/events/keycodes/keyboard_codes.h"
24 using blink::WebDocument;
25 using blink::WebElement;
26 using blink::WebInputElement;
27 using blink::WebNode;
28 using blink::WebString;
30 namespace autofill {
32 class PasswordGenerationAgentTest : public ChromeRenderViewTest {
33 public:
34 PasswordGenerationAgentTest() {}
36 void TearDown() override {
37 LoadHTML("");
38 ChromeRenderViewTest::TearDown();
41 void LoadHTMLWithUserGesture(const char* html) {
42 LoadHTML(html);
44 // Enable show-ime event when element is focused by indicating that a user
45 // gesture has been processed since load.
46 EXPECT_TRUE(SimulateElementClick("dummy"));
49 void FocusField(const char* element_id) {
50 WebDocument document = GetMainFrame()->document();
51 blink::WebElement element =
52 document.getElementById(blink::WebString::fromUTF8(element_id));
53 ASSERT_FALSE(element.isNull());
54 ExecuteJavaScriptForTests(
55 base::StringPrintf("document.getElementById('%s').focus();",
56 element_id).c_str());
59 void ExpectGenerationAvailable(const char* element_id,
60 bool available) {
61 FocusField(element_id);
62 const IPC::Message* message =
63 render_thread_->sink().GetFirstMessageMatching(
64 AutofillHostMsg_ShowPasswordGenerationPopup::ID);
65 if (available)
66 ASSERT_TRUE(message);
67 else
68 ASSERT_FALSE(message);
70 render_thread_->sink().ClearMessages();
73 private:
74 DISALLOW_COPY_AND_ASSIGN(PasswordGenerationAgentTest);
77 const char kSigninFormHTML[] =
78 "<FORM name = 'blah' action = 'http://www.random.com/'> "
79 " <INPUT type = 'text' id = 'username'/> "
80 " <INPUT type = 'password' id = 'password'/> "
81 " <INPUT type = 'button' id = 'dummy'/> "
82 " <INPUT type = 'submit' value = 'LOGIN' />"
83 "</FORM>";
85 const char kAccountCreationFormHTML[] =
86 "<FORM name = 'blah' action = 'http://www.random.com/'> "
87 " <INPUT type = 'text' id = 'username'/> "
88 " <INPUT type = 'password' id = 'first_password' "
89 " autocomplete = 'off' size = 5/>"
90 " <INPUT type = 'password' id = 'second_password' size = 5/> "
91 " <INPUT type = 'text' id = 'address'/> "
92 " <INPUT type = 'button' id = 'dummy'/> "
93 " <INPUT type = 'submit' value = 'LOGIN' />"
94 "</FORM>";
96 const char kDisabledElementAccountCreationFormHTML[] =
97 "<FORM name = 'blah' action = 'http://www.random.com/'> "
98 " <INPUT type = 'text' id = 'username'/> "
99 " <INPUT type = 'password' id = 'first_password' "
100 " autocomplete = 'off' size = 5/>"
101 " <INPUT type = 'password' id = 'second_password' size = 5/> "
102 " <INPUT type = 'text' id = 'address'/> "
103 " <INPUT type = 'text' id = 'disabled' disabled/> "
104 " <INPUT type = 'button' id = 'dummy'/> "
105 " <INPUT type = 'submit' value = 'LOGIN' />"
106 "</FORM>";
108 const char kHiddenPasswordAccountCreationFormHTML[] =
109 "<FORM name = 'blah' action = 'http://www.random.com/'> "
110 " <INPUT type = 'text' id = 'username'/> "
111 " <INPUT type = 'password' id = 'first_password'/> "
112 " <INPUT type = 'password' id = 'second_password' style='display:none'/> "
113 " <INPUT type = 'button' id = 'dummy'/> "
114 " <INPUT type = 'submit' value = 'LOGIN' />"
115 "</FORM>";
117 const char kInvalidActionAccountCreationFormHTML[] =
118 "<FORM name = 'blah' action = 'invalid'> "
119 " <INPUT type = 'text' id = 'username'/> "
120 " <INPUT type = 'password' id = 'first_password'/> "
121 " <INPUT type = 'password' id = 'second_password'/> "
122 " <INPUT type = 'button' id = 'dummy'/> "
123 " <INPUT type = 'submit' value = 'LOGIN' />"
124 "</FORM>";
126 const char kMultipleAccountCreationFormHTML[] =
127 "<FORM name = 'login' action = 'http://www.random.com/'> "
128 " <INPUT type = 'text' id = 'random'/> "
129 " <INPUT type = 'text' id = 'username'/> "
130 " <INPUT type = 'password' id = 'password'/> "
131 " <INPUT type = 'button' id = 'dummy'/> "
132 " <INPUT type = 'submit' value = 'LOGIN' />"
133 "</FORM>"
134 "<FORM name = 'signup' action = 'http://www.random.com/signup'> "
135 " <INPUT type = 'text' id = 'username'/> "
136 " <INPUT type = 'password' id = 'first_password' "
137 " autocomplete = 'off' size = 5/>"
138 " <INPUT type = 'password' id = 'second_password' size = 5/> "
139 " <INPUT type = 'text' id = 'address'/> "
140 " <INPUT type = 'submit' value = 'LOGIN' />"
141 "</FORM>";
143 const char kBothAutocompleteAttributesFormHTML[] =
144 "<FORM name = 'blah' action = 'http://www.random.com/'> "
145 " <INPUT type = 'text' autocomplete='username' id = 'username'/> "
146 " <INPUT type = 'password' id = 'first_password' "
147 " autocomplete = 'new-password' size = 5/>"
148 " <INPUT type = 'password' id = 'second_password' size = 5/> "
149 " <INPUT type = 'button' id = 'dummy'/> "
150 " <INPUT type = 'submit' value = 'LOGIN' />"
151 "</FORM>";
153 const char kUsernameAutocompleteAttributeFormHTML[] =
154 "<FORM name = 'blah' action = 'http://www.random.com/'> "
155 " <INPUT type = 'text' autocomplete='username' id = 'username'/> "
156 " <INPUT type = 'password' id = 'first_password' size = 5/>"
157 " <INPUT type = 'password' id = 'second_password' size = 5/> "
158 " <INPUT type = 'button' id = 'dummy'/> "
159 " <INPUT type = 'submit' value = 'LOGIN' />"
160 "</FORM>";
162 const char kNewPasswordAutocompleteAttributeFormHTML[] =
163 "<FORM name = 'blah' action = 'http://www.random.com/'> "
164 " <INPUT type = 'text' id = 'username'/> "
165 " <INPUT type = 'password' id = 'first_password' "
166 " autocomplete='new-password' size = 5/>"
167 " <INPUT type = 'password' id = 'second_password' size = 5/> "
168 " <INPUT type = 'button' id = 'dummy'/> "
169 " <INPUT type = 'submit' value = 'LOGIN' />"
170 "</FORM>";
172 const char ChangeDetectionScript[] =
173 "<script>"
174 " firstOnChangeCalled = false;"
175 " secondOnChangeCalled = false;"
176 " document.getElementById('first_password').onchange = function() {"
177 " firstOnChangeCalled = true;"
178 " };"
179 " document.getElementById('second_password').onchange = function() {"
180 " secondOnChangeCalled = true;"
181 " };"
182 "</script>";
184 TEST_F(PasswordGenerationAgentTest, DetectionTest) {
185 // Don't shown the icon for non account creation forms.
186 LoadHTMLWithUserGesture(kSigninFormHTML);
187 ExpectGenerationAvailable("password", false);
189 // We don't show the decoration yet because the feature isn't enabled.
190 LoadHTMLWithUserGesture(kAccountCreationFormHTML);
191 ExpectGenerationAvailable("first_password", false);
193 // Pretend like We have received message indicating site is not blacklisted,
194 // and we have received message indicating the form is classified as
195 // ACCOUNT_CREATION_FORM form Autofill server. We should show the icon.
196 LoadHTMLWithUserGesture(kAccountCreationFormHTML);
197 SetNotBlacklistedMessage(password_generation_, kAccountCreationFormHTML);
198 SetAccountCreationFormsDetectedMessage(password_generation_,
199 GetMainFrame()->document(),
201 ExpectGenerationAvailable("first_password", true);
203 // Hidden fields are not treated differently.
204 LoadHTMLWithUserGesture(kHiddenPasswordAccountCreationFormHTML);
205 SetNotBlacklistedMessage(password_generation_,
206 kHiddenPasswordAccountCreationFormHTML);
207 SetAccountCreationFormsDetectedMessage(password_generation_,
208 GetMainFrame()->document(),
210 ExpectGenerationAvailable("first_password", true);
212 // This doesn't trigger because the form action is invalid.
213 LoadHTMLWithUserGesture(kInvalidActionAccountCreationFormHTML);
214 SetNotBlacklistedMessage(password_generation_,
215 kInvalidActionAccountCreationFormHTML);
216 SetAccountCreationFormsDetectedMessage(password_generation_,
217 GetMainFrame()->document(),
219 ExpectGenerationAvailable("first_password", false);
222 TEST_F(PasswordGenerationAgentTest, FillTest) {
223 // Make sure that we are enabled before loading HTML.
224 std::string html = std::string(kAccountCreationFormHTML) +
225 ChangeDetectionScript;
226 LoadHTMLWithUserGesture(html.c_str());
227 SetNotBlacklistedMessage(password_generation_, html.c_str());
228 SetAccountCreationFormsDetectedMessage(password_generation_,
229 GetMainFrame()->document(),
232 WebDocument document = GetMainFrame()->document();
233 WebElement element =
234 document.getElementById(WebString::fromUTF8("first_password"));
235 ASSERT_FALSE(element.isNull());
236 WebInputElement first_password_element = element.to<WebInputElement>();
237 element = document.getElementById(WebString::fromUTF8("second_password"));
238 ASSERT_FALSE(element.isNull());
239 WebInputElement second_password_element = element.to<WebInputElement>();
241 // Both password fields should be empty.
242 EXPECT_TRUE(first_password_element.value().isNull());
243 EXPECT_TRUE(second_password_element.value().isNull());
245 base::string16 password = base::ASCIIToUTF16("random_password");
246 AutofillMsg_GeneratedPasswordAccepted msg(0, password);
247 password_generation_->OnMessageReceived(msg);
249 // Password fields are filled out and set as being autofilled.
250 EXPECT_EQ(password, first_password_element.value());
251 EXPECT_EQ(password, second_password_element.value());
252 EXPECT_TRUE(first_password_element.isAutofilled());
253 EXPECT_TRUE(second_password_element.isAutofilled());
255 // Make sure onchange events are called.
256 int first_onchange_called = -1;
257 int second_onchange_called = -1;
258 ASSERT_TRUE(
259 ExecuteJavaScriptAndReturnIntValue(
260 base::ASCIIToUTF16("firstOnChangeCalled ? 1 : 0"),
261 &first_onchange_called));
262 EXPECT_EQ(1, first_onchange_called);
263 ASSERT_TRUE(
264 ExecuteJavaScriptAndReturnIntValue(
265 base::ASCIIToUTF16("secondOnChangeCalled ? 1 : 0"),
266 &second_onchange_called));
267 EXPECT_EQ(1, second_onchange_called);
269 // Focus moved to the next input field.
270 // TODO(zysxqn): Change this back to the address element once Bug 90224
271 // https://bugs.webkit.org/show_bug.cgi?id=90224 has been fixed.
272 element = document.getElementById(WebString::fromUTF8("first_password"));
273 ASSERT_FALSE(element.isNull());
274 EXPECT_EQ(element, document.focusedElement());
277 TEST_F(PasswordGenerationAgentTest, EditingTest) {
278 LoadHTMLWithUserGesture(kAccountCreationFormHTML);
279 SetNotBlacklistedMessage(password_generation_, kAccountCreationFormHTML);
280 SetAccountCreationFormsDetectedMessage(password_generation_,
281 GetMainFrame()->document(),
284 WebDocument document = GetMainFrame()->document();
285 WebElement element =
286 document.getElementById(WebString::fromUTF8("first_password"));
287 ASSERT_FALSE(element.isNull());
288 WebInputElement first_password_element = element.to<WebInputElement>();
289 element = document.getElementById(WebString::fromUTF8("second_password"));
290 ASSERT_FALSE(element.isNull());
291 WebInputElement second_password_element = element.to<WebInputElement>();
293 base::string16 password = base::ASCIIToUTF16("random_password");
294 AutofillMsg_GeneratedPasswordAccepted msg(0, password);
295 password_generation_->OnMessageReceived(msg);
297 // Passwords start out the same.
298 EXPECT_EQ(password, first_password_element.value());
299 EXPECT_EQ(password, second_password_element.value());
301 // After editing the first field they are still the same.
302 std::string edited_password_ascii = "edited_password";
303 SimulateUserInputChangeForElement(&first_password_element,
304 edited_password_ascii);
305 base::string16 edited_password = base::ASCIIToUTF16(edited_password_ascii);
306 EXPECT_EQ(edited_password, first_password_element.value());
307 EXPECT_EQ(edited_password, second_password_element.value());
309 // Clear any uninteresting sent messages.
310 render_thread_->sink().ClearMessages();
312 // Verify that password mirroring works correctly even when the password
313 // is deleted.
314 SimulateUserInputChangeForElement(&first_password_element, std::string());
315 EXPECT_EQ(base::string16(), first_password_element.value());
316 EXPECT_EQ(base::string16(), second_password_element.value());
318 // Should have notified the browser that the password is no longer generated
319 // and trigger generation again.
320 EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching(
321 AutofillHostMsg_PasswordNoLongerGenerated::ID));
322 EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching(
323 AutofillHostMsg_ShowPasswordGenerationPopup::ID));
326 TEST_F(PasswordGenerationAgentTest, BlacklistedTest) {
327 // Did not receive not blacklisted message. Don't show password generation
328 // icon.
329 LoadHTMLWithUserGesture(kAccountCreationFormHTML);
330 SetAccountCreationFormsDetectedMessage(password_generation_,
331 GetMainFrame()->document(),
333 ExpectGenerationAvailable("first_password", false);
335 // Receive one not blacklisted message for non account creation form. Don't
336 // show password generation icon.
337 LoadHTMLWithUserGesture(kAccountCreationFormHTML);
338 SetNotBlacklistedMessage(password_generation_, kSigninFormHTML);
339 SetAccountCreationFormsDetectedMessage(password_generation_,
340 GetMainFrame()->document(),
342 ExpectGenerationAvailable("first_password", false);
344 // Receive one not blacklisted message for account creation form. Show
345 // password generation icon.
346 LoadHTMLWithUserGesture(kAccountCreationFormHTML);
347 SetNotBlacklistedMessage(password_generation_, kAccountCreationFormHTML);
348 SetAccountCreationFormsDetectedMessage(password_generation_,
349 GetMainFrame()->document(),
351 ExpectGenerationAvailable("first_password", true);
353 // Receive two not blacklisted messages, one is for account creation form and
354 // the other is not. Show password generation icon.
355 LoadHTMLWithUserGesture(kAccountCreationFormHTML);
356 SetNotBlacklistedMessage(password_generation_, kAccountCreationFormHTML);
357 SetNotBlacklistedMessage(password_generation_, kSigninFormHTML);
358 SetAccountCreationFormsDetectedMessage(password_generation_,
359 GetMainFrame()->document(),
361 ExpectGenerationAvailable("first_password", true);
364 TEST_F(PasswordGenerationAgentTest, AccountCreationFormsDetectedTest) {
365 // Did not receive account creation forms detected message. Don't show
366 // password generation icon.
367 LoadHTMLWithUserGesture(kAccountCreationFormHTML);
368 SetNotBlacklistedMessage(password_generation_, kAccountCreationFormHTML);
369 ExpectGenerationAvailable("first_password", false);
371 // Receive the account creation forms detected message. Show password
372 // generation icon.
373 LoadHTMLWithUserGesture(kAccountCreationFormHTML);
374 SetNotBlacklistedMessage(password_generation_, kAccountCreationFormHTML);
375 SetAccountCreationFormsDetectedMessage(password_generation_,
376 GetMainFrame()->document(),
378 ExpectGenerationAvailable("first_password", true);
381 TEST_F(PasswordGenerationAgentTest, MaximumOfferSize) {
382 base::HistogramTester histogram_tester;
384 LoadHTMLWithUserGesture(kAccountCreationFormHTML);
385 SetNotBlacklistedMessage(password_generation_, kAccountCreationFormHTML);
386 SetAccountCreationFormsDetectedMessage(password_generation_,
387 GetMainFrame()->document(),
389 ExpectGenerationAvailable("first_password", true);
391 WebDocument document = GetMainFrame()->document();
392 WebElement element =
393 document.getElementById(WebString::fromUTF8("first_password"));
394 ASSERT_FALSE(element.isNull());
395 WebInputElement first_password_element = element.to<WebInputElement>();
397 // Make a password just under maximum offer size.
398 SimulateUserInputChangeForElement(
399 &first_password_element,
400 std::string(password_generation_->kMaximumOfferSize - 1, 'a'));
401 // There should now be a message to show the UI.
402 EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching(
403 AutofillHostMsg_ShowPasswordGenerationPopup::ID));
404 render_thread_->sink().ClearMessages();
406 // Simulate a user typing a password just over maximum offer size.
407 SimulateUserTypingASCIICharacter('a', false);
408 SimulateUserTypingASCIICharacter('a', true);
409 // There should now be a message to hide the UI.
410 EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching(
411 AutofillHostMsg_HidePasswordGenerationPopup::ID));
412 render_thread_->sink().ClearMessages();
414 // Simulate the user deleting characters. The generation popup should be shown
415 // again.
416 SimulateUserTypingASCIICharacter(ui::VKEY_BACK, true);
417 // There should now be a message to show the UI.
418 EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching(
419 AutofillHostMsg_ShowPasswordGenerationPopup::ID));
420 render_thread_->sink().ClearMessages();
422 // Change focus. Bubble should be hidden, but that is handled by AutofilAgent,
423 // so no messages are sent.
424 ExecuteJavaScriptForTests("document.getElementById('username').focus();");
425 EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching(
426 AutofillHostMsg_ShowPasswordGenerationPopup::ID));
427 render_thread_->sink().ClearMessages();
429 // Focusing the password field will bring up the generation UI again.
430 ExecuteJavaScriptForTests(
431 "document.getElementById('first_password').focus();");
432 EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching(
433 AutofillHostMsg_ShowPasswordGenerationPopup::ID));
434 render_thread_->sink().ClearMessages();
436 // Loading a different page triggers UMA stat upload. Verify that only one
437 // display event is sent even though
438 LoadHTMLWithUserGesture(kSigninFormHTML);
440 histogram_tester.ExpectBucketCount(
441 "PasswordGeneration.Event",
442 autofill::password_generation::GENERATION_POPUP_SHOWN,
446 TEST_F(PasswordGenerationAgentTest, DynamicFormTest) {
447 LoadHTMLWithUserGesture(kSigninFormHTML);
448 SetNotBlacklistedMessage(password_generation_, kSigninFormHTML);
450 ExecuteJavaScriptForTests(
451 "var form = document.createElement('form');"
452 "var username = document.createElement('input');"
453 "username.type = 'text';"
454 "username.id = 'dynamic_username';"
455 "var first_password = document.createElement('input');"
456 "first_password.type = 'password';"
457 "first_password.id = 'first_password';"
458 "first_password.name = 'first_password';"
459 "var second_password = document.createElement('input');"
460 "second_password.type = 'password';"
461 "second_password.id = 'second_password';"
462 "second_password.name = 'second_password';"
463 "form.appendChild(username);"
464 "form.appendChild(first_password);"
465 "form.appendChild(second_password);"
466 "document.body.appendChild(form);");
467 ProcessPendingMessages();
469 // This needs to come after the DOM has been modified.
470 SetAccountCreationFormsDetectedMessage(password_generation_,
471 GetMainFrame()->document(),
474 // TODO(gcasto): I'm slightly worried about flakes in this test where
475 // didAssociateFormControls() isn't called. If this turns out to be a problem
476 // adding a call to OnDynamicFormsSeen(GetMainFrame()) will fix it, though
477 // it will weaken the test.
478 ExpectGenerationAvailable("first_password", true);
481 TEST_F(PasswordGenerationAgentTest, MultiplePasswordFormsTest) {
482 // If two forms on the page looks like possible account creation forms, make
483 // sure to trigger on the one that is specified from Autofill.
484 LoadHTMLWithUserGesture(kMultipleAccountCreationFormHTML);
485 SetNotBlacklistedMessage(password_generation_,
486 kMultipleAccountCreationFormHTML);
488 // Should trigger on the second form.
489 SetAccountCreationFormsDetectedMessage(password_generation_,
490 GetMainFrame()->document(),
493 ExpectGenerationAvailable("password", false);
494 ExpectGenerationAvailable("first_password", true);
497 TEST_F(PasswordGenerationAgentTest, MessagesAfterAccountSignupFormFound) {
498 LoadHTMLWithUserGesture(kAccountCreationFormHTML);
499 SetNotBlacklistedMessage(password_generation_, kAccountCreationFormHTML);
500 SetAccountCreationFormsDetectedMessage(password_generation_,
501 GetMainFrame()->document(),
504 // Generation should be enabled.
505 ExpectGenerationAvailable("first_password", true);
507 // Extra not blacklisted messages can be sent. Make sure that they are handled
508 // correctly (generation should still be available).
509 SetNotBlacklistedMessage(password_generation_, kAccountCreationFormHTML);
511 // Need to focus another field first for verification to work.
512 ExpectGenerationAvailable("second_password", false);
513 ExpectGenerationAvailable("first_password", true);
516 // Losing focus should not trigger a password generation popup.
517 TEST_F(PasswordGenerationAgentTest, BlurTest) {
518 render_thread_->sink().ClearMessages();
519 LoadHTMLWithUserGesture(kDisabledElementAccountCreationFormHTML);
520 SetNotBlacklistedMessage(password_generation_,
521 kDisabledElementAccountCreationFormHTML);
522 SetAccountCreationFormsDetectedMessage(password_generation_,
523 GetMainFrame()->document(),
526 // Focus on the first password field: password generation popup should show
527 // up.
528 ExpectGenerationAvailable("first_password", true);
530 // Remove focus from everywhere by clicking an unfocusable element: password
531 // generation popup should not show up.
532 EXPECT_TRUE(SimulateElementClick("disabled"));
533 EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching(
534 AutofillHostMsg_GenerationAvailableForForm::ID));
535 EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching(
536 AutofillHostMsg_ShowPasswordGenerationPopup::ID));
539 TEST_F(PasswordGenerationAgentTest, AutocompleteAttributesTest) {
540 // Verify that autocomplete attributes can override Autofill to enable
541 // generation
542 LoadHTMLWithUserGesture(kBothAutocompleteAttributesFormHTML);
543 SetNotBlacklistedMessage(password_generation_,
544 kBothAutocompleteAttributesFormHTML);
546 ExpectGenerationAvailable("first_password", true);
548 // Only setting one of the two attributes doesn't trigger generation.
549 LoadHTMLWithUserGesture(kUsernameAutocompleteAttributeFormHTML);
550 SetNotBlacklistedMessage(password_generation_,
551 kUsernameAutocompleteAttributeFormHTML);
553 ExpectGenerationAvailable("first_password", false);
555 LoadHTMLWithUserGesture(kNewPasswordAutocompleteAttributeFormHTML);
556 SetNotBlacklistedMessage(password_generation_,
557 kNewPasswordAutocompleteAttributeFormHTML);
559 ExpectGenerationAvailable("first_password", false);
562 } // namespace autofill