1 // Copyright (c) 2012 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 "base/strings/string_util.h"
6 #include "base/strings/utf_string_conversions.h"
7 #include "chrome/test/base/chrome_render_view_test.h"
8 #include "components/autofill/content/renderer/autofill_agent.h"
9 #include "components/autofill/content/renderer/form_autofill_util.h"
10 #include "components/autofill/content/renderer/password_autofill_agent.h"
11 #include "components/autofill/content/renderer/test_password_autofill_agent.h"
12 #include "components/autofill/core/common/autofill_messages.h"
13 #include "components/autofill/core/common/form_data.h"
14 #include "components/autofill/core/common/form_field_data.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "third_party/WebKit/public/platform/WebString.h"
17 #include "third_party/WebKit/public/platform/WebVector.h"
18 #include "third_party/WebKit/public/web/WebDocument.h"
19 #include "third_party/WebKit/public/web/WebElement.h"
20 #include "third_party/WebKit/public/web/WebFormElement.h"
21 #include "third_party/WebKit/public/web/WebInputElement.h"
22 #include "third_party/WebKit/public/web/WebNode.h"
23 #include "third_party/WebKit/public/web/WebView.h"
24 #include "ui/events/keycodes/keyboard_codes.h"
26 using autofill::PasswordForm;
27 using WebKit::WebDocument;
28 using WebKit::WebElement;
29 using WebKit::WebFrame;
30 using WebKit::WebInputElement;
31 using WebKit::WebString;
32 using WebKit::WebView;
36 // The name of the username/password element in the form.
37 const char kUsernameName[] = "username";
38 const char kPasswordName[] = "password";
40 const char kAliceUsername[] = "alice";
41 const char kAlicePassword[] = "password";
42 const char kBobUsername[] = "bob";
43 const char kBobPassword[] = "secret";
44 const char kCarolUsername[] = "Carol";
45 const char kCarolPassword[] = "test";
46 const char kCarolAlternateUsername[] = "RealCarolUsername";
49 const char kFormHTML[] =
50 "<FORM name='LoginTestForm' action='http://www.bidule.com'>"
51 " <INPUT type='text' id='username'/>"
52 " <INPUT type='password' id='password'/>"
53 " <INPUT type='submit' value='Login'/>"
56 const char kVisibleFormHTML[] =
57 "<head> <style> form {display: inline;} </style> </head>"
61 " <input type='password' id='password'/>"
66 const char kEmptyFormHTML[] =
67 "<head> <style> form {display: inline;} </style> </head>"
68 "<body> <form> </form> </body>";
70 const char kNonVisibleFormHTML[] =
71 "<head> <style> form {display: none;} </style> </head>"
75 " <input type='password' id='password'/>"
80 const char kEmptyWebpage[] =
88 const char kRedirectionWebpage[] =
91 " <meta http-equiv='Content-Type' content='text/html'>"
92 " <title>Redirection page</title>"
96 " <script type='text/javascript'>"
102 const char kSimpleWebpage[] =
105 " <meta charset='utf-8' />"
106 " <title>Title</title>"
109 " <form name='LoginTestForm'>"
110 " <input type='text' id='username'/>"
111 " <input type='password' id='password'/>"
112 " <input type='submit' value='Login'/>"
117 const char kWebpageWithDynamicContent[] =
120 " <meta charset='utf-8' />"
121 " <title>Title</title>"
124 " <script type='text/javascript'>"
125 " function addParagraph() {"
126 " var p = document.createElement('p');"
127 " document.body.appendChild(p);"
129 " window.onload = addParagraph;"
138 class PasswordAutofillAgentTest : public ChromeRenderViewTest {
140 PasswordAutofillAgentTest() {
143 // Simulates the fill password form message being sent to the renderer.
144 // We use that so we don't have to make RenderView::OnFillPasswordForm()
146 void SimulateOnFillPasswordForm(
147 const PasswordFormFillData& fill_data) {
148 AutofillMsg_FillPasswordForm msg(0, fill_data);
149 password_autofill_->OnMessageReceived(msg);
152 virtual void SetUp() {
153 ChromeRenderViewTest::SetUp();
155 // Add a preferred login and an additional login to the FillData.
156 username1_ = ASCIIToUTF16(kAliceUsername);
157 password1_ = ASCIIToUTF16(kAlicePassword);
158 username2_ = ASCIIToUTF16(kBobUsername);
159 password2_ = ASCIIToUTF16(kBobPassword);
160 username3_ = ASCIIToUTF16(kCarolUsername);
161 password3_ = ASCIIToUTF16(kCarolPassword);
162 alternate_username3_ = ASCIIToUTF16(kCarolAlternateUsername);
164 FormFieldData username_field;
165 username_field.name = ASCIIToUTF16(kUsernameName);
166 username_field.value = username1_;
167 fill_data_.basic_data.fields.push_back(username_field);
169 FormFieldData password_field;
170 password_field.name = ASCIIToUTF16(kPasswordName);
171 password_field.value = password1_;
172 password_field.form_control_type = "password";
173 fill_data_.basic_data.fields.push_back(password_field);
175 PasswordAndRealm password2;
176 password2.password = password2_;
177 fill_data_.additional_logins[username2_] = password2;
178 PasswordAndRealm password3;
179 password3.password = password3_;
180 fill_data_.additional_logins[username3_] = password3;
182 UsernamesCollectionKey key;
183 key.username = username3_;
184 key.password = password3_;
185 key.realm = "google.com";
186 fill_data_.other_possible_usernames[key].push_back(alternate_username3_);
188 // We need to set the origin so it matches the frame URL and the action so
189 // it matches the form action, otherwise we won't autocomplete.
190 std::string origin("data:text/html;charset=utf-8,");
192 fill_data_.basic_data.origin = GURL(origin);
193 fill_data_.basic_data.action = GURL("http://www.bidule.com");
197 // Now retrieves the input elements so the test can access them.
198 WebDocument document = GetMainFrame()->document();
200 document.getElementById(WebString::fromUTF8(kUsernameName));
201 ASSERT_FALSE(element.isNull());
202 username_element_ = element.to<WebKit::WebInputElement>();
203 element = document.getElementById(WebString::fromUTF8(kPasswordName));
204 ASSERT_FALSE(element.isNull());
205 password_element_ = element.to<WebKit::WebInputElement>();
208 virtual void TearDown() {
209 username_element_.reset();
210 password_element_.reset();
211 ChromeRenderViewTest::TearDown();
214 void ClearUsernameAndPasswordFields() {
215 username_element_.setValue("");
216 username_element_.setAutofilled(false);
217 password_element_.setValue("");
218 password_element_.setAutofilled(false);
221 void SimulateUsernameChange(const std::string& username,
222 bool move_caret_to_end) {
223 username_element_.setValue(WebString::fromUTF8(username));
224 // The field must have focus or AutofillAgent will think the
225 // change should be ignored.
226 while (!username_element_.focused())
227 GetMainFrame()->document().frame()->view()->advanceFocus(false);
228 if (move_caret_to_end)
229 username_element_.setSelectionRange(username.length(), username.length());
230 autofill_agent_->textFieldDidChange(username_element_);
231 // Processing is delayed because of a WebKit bug, see
232 // PasswordAutocompleteManager::TextDidChangeInTextField() for details.
233 base::MessageLoop::current()->RunUntilIdle();
236 void SimulateKeyDownEvent(const WebInputElement& element,
237 ui::KeyboardCode key_code) {
238 WebKit::WebKeyboardEvent key_event;
239 key_event.windowsKeyCode = key_code;
240 autofill_agent_->textFieldDidReceiveKeyDown(element, key_event);
243 void CheckTextFieldsState(const std::string& username,
244 bool username_autofilled,
245 const std::string& password,
246 bool password_autofilled) {
248 static_cast<std::string>(username_element_.value().utf8()));
249 EXPECT_EQ(username_autofilled, username_element_.isAutofilled());
251 static_cast<std::string>(password_element_.value().utf8()));
252 EXPECT_EQ(password_autofilled, password_element_.isAutofilled());
255 void CheckUsernameSelection(int start, int end) {
256 EXPECT_EQ(start, username_element_.selectionStart());
257 EXPECT_EQ(end, username_element_.selectionEnd());
266 string16 alternate_username3_;
267 PasswordFormFillData fill_data_;
269 WebInputElement username_element_;
270 WebInputElement password_element_;
273 DISALLOW_COPY_AND_ASSIGN(PasswordAutofillAgentTest);
276 // Tests that the password login is autocompleted as expected when the browser
277 // sends back the password info.
278 TEST_F(PasswordAutofillAgentTest, InitialAutocomplete) {
280 * Right now we are not sending the message to the browser because we are
281 * loading a data URL and the security origin canAccessPasswordManager()
282 * returns false. May be we should mock URL loading to cirmcuvent this?
283 TODO(jcivelli): find a way to make the security origin not deny access to the
284 password manager and then reenable this code.
286 // The form has been loaded, we should have sent the browser a message about
288 const IPC::Message* msg = render_thread_.sink().GetFirstMessageMatching(
289 AutofillHostMsg_PasswordFormsParsed::ID);
290 ASSERT_TRUE(msg != NULL);
292 Tuple1<std::vector<PasswordForm> > forms;
293 AutofillHostMsg_PasswordFormsParsed::Read(msg, &forms);
294 ASSERT_EQ(1U, forms.a.size());
295 PasswordForm password_form = forms.a[0];
296 EXPECT_EQ(PasswordForm::SCHEME_HTML, password_form.scheme);
297 EXPECT_EQ(ASCIIToUTF16(kUsernameName), password_form.username_element);
298 EXPECT_EQ(ASCIIToUTF16(kPasswordName), password_form.password_element);
301 // Simulate the browser sending back the login info, it triggers the
303 SimulateOnFillPasswordForm(fill_data_);
305 // The username and password should have been autocompleted.
306 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
309 // Tests that we correctly fill forms having an empty 'action' attribute.
310 TEST_F(PasswordAutofillAgentTest, InitialAutocompleteForEmptyAction) {
311 const char kEmptyActionFormHTML[] =
312 "<FORM name='LoginTestForm'>"
313 " <INPUT type='text' id='username'/>"
314 " <INPUT type='password' id='password'/>"
315 " <INPUT type='submit' value='Login'/>"
317 LoadHTML(kEmptyActionFormHTML);
319 // Retrieve the input elements so the test can access them.
320 WebDocument document = GetMainFrame()->document();
322 document.getElementById(WebString::fromUTF8(kUsernameName));
323 ASSERT_FALSE(element.isNull());
324 username_element_ = element.to<WebKit::WebInputElement>();
325 element = document.getElementById(WebString::fromUTF8(kPasswordName));
326 ASSERT_FALSE(element.isNull());
327 password_element_ = element.to<WebKit::WebInputElement>();
329 // Set the expected form origin and action URLs.
330 std::string origin("data:text/html;charset=utf-8,");
331 origin += kEmptyActionFormHTML;
332 fill_data_.basic_data.origin = GURL(origin);
333 fill_data_.basic_data.action = GURL(origin);
335 // Simulate the browser sending back the login info, it triggers the
337 SimulateOnFillPasswordForm(fill_data_);
339 // The username and password should have been autocompleted.
340 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
343 // Tests that if a password or input element is marked as readonly, neither
344 // field is autofilled on page load.
345 TEST_F(PasswordAutofillAgentTest, NoInitialAutocompleteForReadOnly) {
346 password_element_.setAttribute(WebString::fromUTF8("readonly"),
347 WebString::fromUTF8("true"));
349 // Simulate the browser sending back the login info, it triggers the
351 SimulateOnFillPasswordForm(fill_data_);
353 CheckTextFieldsState(std::string(), false, std::string(), false);
356 // Tests that having a non-matching username precludes the autocomplete.
357 TEST_F(PasswordAutofillAgentTest, NoInitialAutocompleteForFilledField) {
358 username_element_.setValue(WebString::fromUTF8("bogus"));
360 // Simulate the browser sending back the login info, it triggers the
362 SimulateOnFillPasswordForm(fill_data_);
364 // Neither field should be autocompleted.
365 CheckTextFieldsState("bogus", false, std::string(), false);
368 // Tests that we do not autofill username/passwords if marked as
369 // autocomplete="off".
370 TEST_F(PasswordAutofillAgentTest, NoInitialAutocompleteForAutocompleteOff) {
371 username_element_.setAttribute(WebString::fromUTF8("autocomplete"),
372 WebString::fromUTF8("off"));
374 // Simulate the browser sending back the login info, it triggers the
376 SimulateOnFillPasswordForm(fill_data_);
378 CheckTextFieldsState(std::string(), false, std::string(), false);
381 TEST_F(PasswordAutofillAgentTest, NoAutocompleteForTextFieldPasswords) {
382 const char kTextFieldPasswordFormHTML[] =
383 "<FORM name='LoginTestForm' action='http://www.bidule.com'>"
384 " <INPUT type='text' id='username'/>"
385 " <INPUT type='text' id='password'/>"
386 " <INPUT type='submit' value='Login'/>"
388 LoadHTML(kTextFieldPasswordFormHTML);
390 // Retrieve the input elements so the test can access them.
391 WebDocument document = GetMainFrame()->document();
393 document.getElementById(WebString::fromUTF8(kUsernameName));
394 ASSERT_FALSE(element.isNull());
395 username_element_ = element.to<WebKit::WebInputElement>();
396 element = document.getElementById(WebString::fromUTF8(kPasswordName));
397 ASSERT_FALSE(element.isNull());
398 password_element_ = element.to<WebKit::WebInputElement>();
400 // Set the expected form origin URL.
401 std::string origin("data:text/html;charset=utf-8,");
402 origin += kTextFieldPasswordFormHTML;
403 fill_data_.basic_data.origin = GURL(origin);
405 SimulateOnFillPasswordForm(fill_data_);
407 // Fields should still be empty.
408 CheckTextFieldsState(std::string(), false, std::string(), false);
411 TEST_F(PasswordAutofillAgentTest, NoAutocompleteForPasswordFieldUsernames) {
412 const char kPasswordFieldUsernameFormHTML[] =
413 "<FORM name='LoginTestForm' action='http://www.bidule.com'>"
414 " <INPUT type='password' id='username'/>"
415 " <INPUT type='password' id='password'/>"
416 " <INPUT type='submit' value='Login'/>"
418 LoadHTML(kPasswordFieldUsernameFormHTML);
420 // Retrieve the input elements so the test can access them.
421 WebDocument document = GetMainFrame()->document();
423 document.getElementById(WebString::fromUTF8(kUsernameName));
424 ASSERT_FALSE(element.isNull());
425 username_element_ = element.to<WebKit::WebInputElement>();
426 element = document.getElementById(WebString::fromUTF8(kPasswordName));
427 ASSERT_FALSE(element.isNull());
428 password_element_ = element.to<WebKit::WebInputElement>();
430 // Set the expected form origin URL.
431 std::string origin("data:text/html;charset=utf-8,");
432 origin += kPasswordFieldUsernameFormHTML;
433 fill_data_.basic_data.origin = GURL(origin);
435 SimulateOnFillPasswordForm(fill_data_);
437 // Fields should still be empty.
438 CheckTextFieldsState(std::string(), false, std::string(), false);
441 // Tests that having a matching username does not preclude the autocomplete.
442 TEST_F(PasswordAutofillAgentTest, InitialAutocompleteForMatchingFilledField) {
443 username_element_.setValue(WebString::fromUTF8(kAliceUsername));
445 // Simulate the browser sending back the login info, it triggers the
447 SimulateOnFillPasswordForm(fill_data_);
449 // The username and password should have been autocompleted.
450 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
453 // Tests that editing the password clears the autocompleted password field.
454 TEST_F(PasswordAutofillAgentTest, PasswordClearOnEdit) {
455 // Simulate the browser sending back the login info, it triggers the
457 SimulateOnFillPasswordForm(fill_data_);
459 // Simulate the user changing the username to some unknown username.
460 SimulateUsernameChange("alicia", true);
462 // The password should have been cleared.
463 CheckTextFieldsState("alicia", false, std::string(), false);
466 // Tests that we only autocomplete on focus lost and with a full username match
467 // when |wait_for_username| is true.
468 TEST_F(PasswordAutofillAgentTest, WaitUsername) {
469 // Simulate the browser sending back the login info.
470 fill_data_.wait_for_username = true;
471 SimulateOnFillPasswordForm(fill_data_);
473 // No auto-fill should have taken place.
474 CheckTextFieldsState(std::string(), false, std::string(), false);
476 // No autocomplete should happen when text is entered in the username.
477 SimulateUsernameChange("a", true);
478 CheckTextFieldsState("a", false, std::string(), false);
479 SimulateUsernameChange("al", true);
480 CheckTextFieldsState("al", false, std::string(), false);
481 SimulateUsernameChange(kAliceUsername, true);
482 CheckTextFieldsState(kAliceUsername, false, std::string(), false);
484 // Autocomplete should happen only when the username textfield is blurred with
486 username_element_.setValue("a");
487 autofill_agent_->textFieldDidEndEditing(username_element_);
488 CheckTextFieldsState("a", false, std::string(), false);
489 username_element_.setValue("al");
490 autofill_agent_->textFieldDidEndEditing(username_element_);
491 CheckTextFieldsState("al", false, std::string(), false);
492 username_element_.setValue("alices");
493 autofill_agent_->textFieldDidEndEditing(username_element_);
494 CheckTextFieldsState("alices", false, std::string(), false);
495 username_element_.setValue(ASCIIToUTF16(kAliceUsername));
496 autofill_agent_->textFieldDidEndEditing(username_element_);
497 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
500 // Tests that inline autocompletion works properly.
501 TEST_F(PasswordAutofillAgentTest, InlineAutocomplete) {
502 // Simulate the browser sending back the login info.
503 SimulateOnFillPasswordForm(fill_data_);
505 // Clear the text fields to start fresh.
506 ClearUsernameAndPasswordFields();
508 // Simulate the user typing in the first letter of 'alice', a stored username.
509 SimulateUsernameChange("a", true);
510 // Both the username and password text fields should reflect selection of the
512 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
513 // And the selection should have been set to 'lice', the last 4 letters.
514 CheckUsernameSelection(1, 5);
516 // Now the user types the next letter of the same username, 'l'.
517 SimulateUsernameChange("al", true);
518 // Now the fields should have the same value, but the selection should have a
519 // different start value.
520 CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
521 CheckUsernameSelection(2, 5);
523 // Test that deleting does not trigger autocomplete.
524 SimulateKeyDownEvent(username_element_, ui::VKEY_BACK);
525 SimulateUsernameChange("alic", true);
526 CheckTextFieldsState("alic", false, std::string(), false);
527 CheckUsernameSelection(4, 4); // No selection.
528 // Reset the last pressed key to something other than backspace.
529 SimulateKeyDownEvent(username_element_, ui::VKEY_A);
531 // Now lets say the user goes astray from the stored username and types the
532 // letter 'f', spelling 'alf'. We don't know alf (that's just sad), so in
533 // practice the username should no longer be 'alice' and the selected range
535 SimulateUsernameChange("alf", true);
536 CheckTextFieldsState("alf", false, std::string(), false);
537 CheckUsernameSelection(3, 3); // No selection.
539 // Ok, so now the user removes all the text and enters the letter 'b'.
540 SimulateUsernameChange("b", true);
541 // The username and password fields should match the 'bob' entry.
542 CheckTextFieldsState(kBobUsername, true, kBobPassword, true);
543 CheckUsernameSelection(1, 3);
545 // Then, the user again removes all the text and types an uppercase 'C'.
546 SimulateUsernameChange("C", true);
547 // The username and password fields should match the 'Carol' entry.
548 CheckTextFieldsState(kCarolUsername, true, kCarolPassword, true);
549 CheckUsernameSelection(1, 5);
550 // The user removes all the text and types a lowercase 'c'. We only
551 // want case-sensitive autocompletion, so the username and the selected range
553 SimulateUsernameChange("c", true);
554 CheckTextFieldsState("c", false, std::string(), false);
555 CheckUsernameSelection(1, 1);
557 // Check that we complete other_possible_usernames as well.
558 SimulateUsernameChange("R", true);
559 CheckTextFieldsState(kCarolAlternateUsername, true, kCarolPassword, true);
560 CheckUsernameSelection(1, 17);
563 // Tests that selecting an item in the suggestion drop-down no-ops.
564 TEST_F(PasswordAutofillAgentTest, SuggestionSelect) {
565 // Simulate the browser sending back the login info.
566 SimulateOnFillPasswordForm(fill_data_);
568 // Clear the text fields to start fresh.
569 ClearUsernameAndPasswordFields();
571 // To simulate accepting an item in the suggestion drop-down we just mimic
572 // what the WebView does: it sets the element value then calls
573 // didSelectAutofillSuggestion on the renderer.
574 autofill_agent_->didSelectAutofillSuggestion(username_element_,
575 ASCIIToUTF16(kAliceUsername),
578 // Autocomplete should not have kicked in.
579 CheckTextFieldsState(std::string(), false, std::string(), false);
582 TEST_F(PasswordAutofillAgentTest, IsWebNodeVisibleTest) {
583 WebKit::WebVector<WebKit::WebFormElement> forms1, forms2, forms3;
584 WebKit::WebFrame* frame;
586 LoadHTML(kVisibleFormHTML);
587 frame = GetMainFrame();
588 frame->document().forms(forms1);
589 ASSERT_EQ(1u, forms1.size());
590 EXPECT_TRUE(IsWebNodeVisible(forms1[0]));
592 LoadHTML(kEmptyFormHTML);
593 frame = GetMainFrame();
594 frame->document().forms(forms2);
595 ASSERT_EQ(1u, forms2.size());
596 EXPECT_FALSE(IsWebNodeVisible(forms2[0]));
598 LoadHTML(kNonVisibleFormHTML);
599 frame = GetMainFrame();
600 frame->document().forms(forms3);
601 ASSERT_EQ(1u, forms3.size());
602 EXPECT_FALSE(IsWebNodeVisible(forms3[0]));
605 TEST_F(PasswordAutofillAgentTest, SendPasswordFormsTest) {
606 render_thread_->sink().ClearMessages();
607 LoadHTML(kVisibleFormHTML);
608 const IPC::Message* message = render_thread_->sink()
609 .GetFirstMessageMatching(AutofillHostMsg_PasswordFormsRendered::ID);
610 EXPECT_TRUE(message);
611 Tuple1<std::vector<autofill::PasswordForm> > param;
612 AutofillHostMsg_PasswordFormsRendered::Read(message, ¶m);
613 EXPECT_TRUE(param.a.size());
615 render_thread_->sink().ClearMessages();
616 LoadHTML(kEmptyFormHTML);
617 message = render_thread_->sink().GetFirstMessageMatching(
618 AutofillHostMsg_PasswordFormsRendered::ID);
619 EXPECT_TRUE(message);
620 AutofillHostMsg_PasswordFormsRendered::Read(message, ¶m);
621 EXPECT_FALSE(param.a.size());
623 render_thread_->sink().ClearMessages();
624 LoadHTML(kNonVisibleFormHTML);
625 message = render_thread_->sink().GetFirstMessageMatching(
626 AutofillHostMsg_PasswordFormsRendered::ID);
627 EXPECT_TRUE(message);
628 AutofillHostMsg_PasswordFormsRendered::Read(message, ¶m);
629 EXPECT_FALSE(param.a.size());
632 TEST_F(PasswordAutofillAgentTest, SendPasswordFormsTest_Redirection) {
633 render_thread_->sink().ClearMessages();
634 LoadHTML(kEmptyWebpage);
635 EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching(
636 AutofillHostMsg_PasswordFormsRendered::ID));
638 render_thread_->sink().ClearMessages();
639 LoadHTML(kRedirectionWebpage);
640 EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching(
641 AutofillHostMsg_PasswordFormsRendered::ID));
643 render_thread_->sink().ClearMessages();
644 LoadHTML(kSimpleWebpage);
645 EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching(
646 AutofillHostMsg_PasswordFormsRendered::ID));
648 render_thread_->sink().ClearMessages();
649 LoadHTML(kWebpageWithDynamicContent);
650 EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching(
651 AutofillHostMsg_PasswordFormsRendered::ID));
654 } // namespace autofill