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 <memory> | 7 #include <memory> |
8 | 8 |
9 #include "base/macros.h" | 9 #include "base/macros.h" |
10 #include "base/run_loop.h" | |
11 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
12 #include "base/test/histogram_tester.h" | 11 #include "base/test/histogram_tester.h" |
13 #include "chrome/renderer/autofill/fake_content_password_manager_driver.h" | |
14 #include "chrome/renderer/autofill/password_generation_test_utils.h" | 12 #include "chrome/renderer/autofill/password_generation_test_utils.h" |
15 #include "chrome/test/base/chrome_render_view_test.h" | 13 #include "chrome/test/base/chrome_render_view_test.h" |
16 #include "components/autofill/content/common/autofill_messages.h" | 14 #include "components/autofill/content/common/autofill_messages.h" |
17 #include "components/autofill/content/renderer/autofill_agent.h" | 15 #include "components/autofill/content/renderer/autofill_agent.h" |
18 #include "components/autofill/content/renderer/test_password_generation_agent.h" | 16 #include "components/autofill/content/renderer/test_password_generation_agent.h" |
19 #include "components/autofill/core/common/form_data.h" | 17 #include "components/autofill/core/common/form_data.h" |
20 #include "components/autofill/core/common/password_generation_util.h" | 18 #include "components/autofill/core/common/password_generation_util.h" |
21 #include "content/public/renderer/render_frame.h" | |
22 #include "content/public/renderer/render_view.h" | |
23 #include "services/shell/public/cpp/interface_provider.h" | |
24 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
25 #include "third_party/WebKit/public/platform/WebString.h" | 20 #include "third_party/WebKit/public/platform/WebString.h" |
26 #include "third_party/WebKit/public/web/WebDocument.h" | 21 #include "third_party/WebKit/public/web/WebDocument.h" |
27 #include "third_party/WebKit/public/web/WebLocalFrame.h" | 22 #include "third_party/WebKit/public/web/WebLocalFrame.h" |
28 #include "third_party/WebKit/public/web/WebWidget.h" | 23 #include "third_party/WebKit/public/web/WebWidget.h" |
29 #include "ui/events/keycodes/keyboard_codes.h" | 24 #include "ui/events/keycodes/keyboard_codes.h" |
30 | 25 |
31 using blink::WebDocument; | 26 using blink::WebDocument; |
32 using blink::WebElement; | 27 using blink::WebElement; |
33 using blink::WebInputElement; | 28 using blink::WebInputElement; |
34 using blink::WebNode; | 29 using blink::WebNode; |
35 using blink::WebString; | 30 using blink::WebString; |
36 | 31 |
37 namespace autofill { | 32 namespace autofill { |
38 | 33 |
39 class PasswordGenerationAgentTest : public ChromeRenderViewTest { | 34 class PasswordGenerationAgentTest : public ChromeRenderViewTest { |
40 public: | 35 public: |
41 PasswordGenerationAgentTest() {} | 36 PasswordGenerationAgentTest() {} |
42 | 37 |
43 void RegisterMainFrameRemoteInterfaces() override { | |
44 // We only use the fake driver for main frame | |
45 // because our test cases only involve the main frame. | |
46 shell::InterfaceProvider* remote_interfaces = | |
47 view_->GetMainRenderFrame()->GetRemoteInterfaces(); | |
48 shell::InterfaceProvider::TestApi test_api(remote_interfaces); | |
49 test_api.SetBinderForName( | |
50 mojom::PasswordManagerDriver::Name_, | |
51 base::Bind(&PasswordGenerationAgentTest::BindPasswordManagerDriver, | |
52 base::Unretained(this))); | |
53 } | |
54 | |
55 void TearDown() override { | 38 void TearDown() override { |
56 LoadHTML(""); | 39 LoadHTML(""); |
57 ChromeRenderViewTest::TearDown(); | 40 ChromeRenderViewTest::TearDown(); |
58 } | 41 } |
59 | 42 |
60 void LoadHTMLWithUserGesture(const char* html) { | 43 void LoadHTMLWithUserGesture(const char* html) { |
61 LoadHTML(html); | 44 LoadHTML(html); |
62 | 45 |
63 // Enable show-ime event when element is focused by indicating that a user | 46 // Enable show-ime event when element is focused by indicating that a user |
64 // gesture has been processed since load. | 47 // gesture has been processed since load. |
(...skipping 18 matching lines...) Expand all Loading... |
83 AutofillHostMsg_ShowPasswordGenerationPopup::ID); | 66 AutofillHostMsg_ShowPasswordGenerationPopup::ID); |
84 if (available) | 67 if (available) |
85 ASSERT_TRUE(message); | 68 ASSERT_TRUE(message); |
86 else | 69 else |
87 ASSERT_FALSE(message); | 70 ASSERT_FALSE(message); |
88 | 71 |
89 render_thread_->sink().ClearMessages(); | 72 render_thread_->sink().ClearMessages(); |
90 } | 73 } |
91 | 74 |
92 void AllowToRunFormClassifier() { | 75 void AllowToRunFormClassifier() { |
93 password_generation_->AllowToRunFormClassifier(); | 76 AutofillMsg_AllowToRunFormClassifier msg(0); |
| 77 static_cast<IPC::Listener*>(password_generation_)->OnMessageReceived(msg); |
94 } | 78 } |
95 | 79 |
96 void ExpectFormClassifierVoteReceived( | 80 void ExpectFormClassifierVoteReceived( |
97 bool received, | 81 bool received, |
98 const base::string16& expected_generation_element) { | 82 const base::string16& expected_generation_element) { |
99 base::RunLoop().RunUntilIdle(); | 83 const IPC::Message* message = |
| 84 render_thread_->sink().GetFirstMessageMatching( |
| 85 AutofillHostMsg_SaveGenerationFieldDetectedByClassifier::ID); |
100 if (received) { | 86 if (received) { |
101 ASSERT_TRUE(fake_driver_.called_save_generation_field()); | 87 ASSERT_TRUE(message); |
102 EXPECT_EQ(expected_generation_element, | 88 std::tuple<autofill::PasswordForm, base::string16> actual_parameters; |
103 fake_driver_.save_generation_field()); | 89 AutofillHostMsg_SaveGenerationFieldDetectedByClassifier::Read( |
| 90 message, &actual_parameters); |
| 91 EXPECT_EQ(expected_generation_element, std::get<1>(actual_parameters)); |
104 } else { | 92 } else { |
105 ASSERT_FALSE(fake_driver_.called_save_generation_field()); | 93 ASSERT_FALSE(message); |
106 } | 94 } |
107 | 95 |
108 fake_driver_.reset_save_generation_field(); | 96 render_thread_->sink().ClearMessages(); |
109 } | 97 } |
110 | 98 |
111 void ShowGenerationPopUpManually(const char* element_id) { | 99 void ShowGenerationPopUpManually(const char* element_id) { |
112 FocusField(element_id); | 100 FocusField(element_id); |
113 password_generation_->UserTriggeredGeneratePassword(); | 101 AutofillMsg_UserTriggeredGeneratePassword msg(0); |
| 102 static_cast<IPC::Listener*>(password_generation_)->OnMessageReceived(msg); |
114 } | 103 } |
115 | 104 |
116 void BindPasswordManagerDriver(mojo::ScopedMessagePipeHandle handle) { | |
117 fake_driver_.BindRequest( | |
118 mojo::MakeRequest<mojom::PasswordManagerDriver>(std::move(handle))); | |
119 } | |
120 | |
121 FakeContentPasswordManagerDriver fake_driver_; | |
122 | |
123 private: | 105 private: |
124 DISALLOW_COPY_AND_ASSIGN(PasswordGenerationAgentTest); | 106 DISALLOW_COPY_AND_ASSIGN(PasswordGenerationAgentTest); |
125 }; | 107 }; |
126 | 108 |
127 const char kSigninFormHTML[] = | 109 const char kSigninFormHTML[] = |
128 "<FORM name = 'blah' action = 'http://www.random.com/'> " | 110 "<FORM name = 'blah' action = 'http://www.random.com/'> " |
129 " <INPUT type = 'text' id = 'username'/> " | 111 " <INPUT type = 'text' id = 'username'/> " |
130 " <INPUT type = 'password' id = 'password'/> " | 112 " <INPUT type = 'password' id = 'password'/> " |
131 " <INPUT type = 'button' id = 'dummy'/> " | 113 " <INPUT type = 'button' id = 'dummy'/> " |
132 " <INPUT type = 'submit' value = 'LOGIN' />" | 114 " <INPUT type = 'submit' value = 'LOGIN' />" |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 WebInputElement first_password_element = element.to<WebInputElement>(); | 281 WebInputElement first_password_element = element.to<WebInputElement>(); |
300 element = document.getElementById(WebString::fromUTF8("second_password")); | 282 element = document.getElementById(WebString::fromUTF8("second_password")); |
301 ASSERT_FALSE(element.isNull()); | 283 ASSERT_FALSE(element.isNull()); |
302 WebInputElement second_password_element = element.to<WebInputElement>(); | 284 WebInputElement second_password_element = element.to<WebInputElement>(); |
303 | 285 |
304 // Both password fields should be empty. | 286 // Both password fields should be empty. |
305 EXPECT_TRUE(first_password_element.value().isNull()); | 287 EXPECT_TRUE(first_password_element.value().isNull()); |
306 EXPECT_TRUE(second_password_element.value().isNull()); | 288 EXPECT_TRUE(second_password_element.value().isNull()); |
307 | 289 |
308 base::string16 password = base::ASCIIToUTF16("random_password"); | 290 base::string16 password = base::ASCIIToUTF16("random_password"); |
309 password_generation_->GeneratedPasswordAccepted(password); | 291 AutofillMsg_GeneratedPasswordAccepted msg(0, password); |
| 292 static_cast<IPC::Listener*>(password_generation_)->OnMessageReceived(msg); |
310 | 293 |
311 // Password fields are filled out and set as being autofilled. | 294 // Password fields are filled out and set as being autofilled. |
312 EXPECT_EQ(password, first_password_element.value()); | 295 EXPECT_EQ(password, first_password_element.value()); |
313 EXPECT_EQ(password, second_password_element.value()); | 296 EXPECT_EQ(password, second_password_element.value()); |
314 EXPECT_TRUE(first_password_element.isAutofilled()); | 297 EXPECT_TRUE(first_password_element.isAutofilled()); |
315 EXPECT_TRUE(second_password_element.isAutofilled()); | 298 EXPECT_TRUE(second_password_element.isAutofilled()); |
316 | 299 |
317 // Make sure onchange events are called. | 300 // Make sure onchange events are called. |
318 int first_onchange_called = -1; | 301 int first_onchange_called = -1; |
319 int second_onchange_called = -1; | 302 int second_onchange_called = -1; |
(...skipping 25 matching lines...) Expand all Loading... |
345 WebDocument document = GetMainFrame()->document(); | 328 WebDocument document = GetMainFrame()->document(); |
346 WebElement element = | 329 WebElement element = |
347 document.getElementById(WebString::fromUTF8("first_password")); | 330 document.getElementById(WebString::fromUTF8("first_password")); |
348 ASSERT_FALSE(element.isNull()); | 331 ASSERT_FALSE(element.isNull()); |
349 WebInputElement first_password_element = element.to<WebInputElement>(); | 332 WebInputElement first_password_element = element.to<WebInputElement>(); |
350 element = document.getElementById(WebString::fromUTF8("second_password")); | 333 element = document.getElementById(WebString::fromUTF8("second_password")); |
351 ASSERT_FALSE(element.isNull()); | 334 ASSERT_FALSE(element.isNull()); |
352 WebInputElement second_password_element = element.to<WebInputElement>(); | 335 WebInputElement second_password_element = element.to<WebInputElement>(); |
353 | 336 |
354 base::string16 password = base::ASCIIToUTF16("random_password"); | 337 base::string16 password = base::ASCIIToUTF16("random_password"); |
355 password_generation_->GeneratedPasswordAccepted(password); | 338 AutofillMsg_GeneratedPasswordAccepted msg(0, password); |
| 339 static_cast<IPC::Listener*>(password_generation_)->OnMessageReceived(msg); |
356 | 340 |
357 // Passwords start out the same. | 341 // Passwords start out the same. |
358 EXPECT_EQ(password, first_password_element.value()); | 342 EXPECT_EQ(password, first_password_element.value()); |
359 EXPECT_EQ(password, second_password_element.value()); | 343 EXPECT_EQ(password, second_password_element.value()); |
360 | 344 |
361 // After editing the first field they are still the same. | 345 // After editing the first field they are still the same. |
362 std::string edited_password_ascii = "edited_password"; | 346 std::string edited_password_ascii = "edited_password"; |
363 SimulateUserInputChangeForElement(&first_password_element, | 347 SimulateUserInputChangeForElement(&first_password_element, |
364 edited_password_ascii); | 348 edited_password_ascii); |
365 base::string16 edited_password = base::ASCIIToUTF16(edited_password_ascii); | 349 base::string16 edited_password = base::ASCIIToUTF16(edited_password_ascii); |
366 EXPECT_EQ(edited_password, first_password_element.value()); | 350 EXPECT_EQ(edited_password, first_password_element.value()); |
367 EXPECT_EQ(edited_password, second_password_element.value()); | 351 EXPECT_EQ(edited_password, second_password_element.value()); |
368 | 352 |
369 // Clear any uninteresting sent messages. | 353 // Clear any uninteresting sent messages. |
370 render_thread_->sink().ClearMessages(); | 354 render_thread_->sink().ClearMessages(); |
371 fake_driver_.reset_called_password_no_longer_generated(); | |
372 | 355 |
373 // Verify that password mirroring works correctly even when the password | 356 // Verify that password mirroring works correctly even when the password |
374 // is deleted. | 357 // is deleted. |
375 SimulateUserInputChangeForElement(&first_password_element, std::string()); | 358 SimulateUserInputChangeForElement(&first_password_element, std::string()); |
376 EXPECT_EQ(base::string16(), first_password_element.value()); | 359 EXPECT_EQ(base::string16(), first_password_element.value()); |
377 EXPECT_EQ(base::string16(), second_password_element.value()); | 360 EXPECT_EQ(base::string16(), second_password_element.value()); |
378 | 361 |
379 // Should have notified the browser that the password is no longer generated | 362 // Should have notified the browser that the password is no longer generated |
380 // and trigger generation again. | 363 // and trigger generation again. |
381 base::RunLoop().RunUntilIdle(); | 364 EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching( |
382 EXPECT_TRUE(fake_driver_.called_password_no_longer_generated()); | 365 AutofillHostMsg_PasswordNoLongerGenerated::ID)); |
383 EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching( | 366 EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching( |
384 AutofillHostMsg_ShowPasswordGenerationPopup::ID)); | 367 AutofillHostMsg_ShowPasswordGenerationPopup::ID)); |
385 } | 368 } |
386 | 369 |
387 TEST_F(PasswordGenerationAgentTest, BlacklistedTest) { | 370 TEST_F(PasswordGenerationAgentTest, BlacklistedTest) { |
388 // Did not receive not blacklisted message. Don't show password generation | 371 // Did not receive not blacklisted message. Don't show password generation |
389 // icon. | 372 // icon. |
390 LoadHTMLWithUserGesture(kAccountCreationFormHTML); | 373 LoadHTMLWithUserGesture(kAccountCreationFormHTML); |
391 SetAccountCreationFormsDetectedMessage(password_generation_, | 374 SetAccountCreationFormsDetectedMessage(password_generation_, |
392 GetMainFrame()->document(), 0, 1); | 375 GetMainFrame()->document(), 0, 1); |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
660 {kPasswordChangeFormHTML, "newpassword"}}; | 643 {kPasswordChangeFormHTML, "newpassword"}}; |
661 for (auto& test_case : kTestCases) { | 644 for (auto& test_case : kTestCases) { |
662 SCOPED_TRACE(testing::Message("form: ") << test_case.form); | 645 SCOPED_TRACE(testing::Message("form: ") << test_case.form); |
663 LoadHTMLWithUserGesture(test_case.form); | 646 LoadHTMLWithUserGesture(test_case.form); |
664 // To be able to work with input elements outside <form>'s, use manual | 647 // To be able to work with input elements outside <form>'s, use manual |
665 // generation. | 648 // generation. |
666 ShowGenerationPopUpManually(test_case.generation_element); | 649 ShowGenerationPopUpManually(test_case.generation_element); |
667 ExpectGenerationAvailable(test_case.generation_element, true); | 650 ExpectGenerationAvailable(test_case.generation_element, true); |
668 | 651 |
669 base::string16 password = base::ASCIIToUTF16("random_password"); | 652 base::string16 password = base::ASCIIToUTF16("random_password"); |
670 password_generation_->GeneratedPasswordAccepted(password); | 653 AutofillMsg_GeneratedPasswordAccepted msg(0, password); |
671 base::RunLoop().RunUntilIdle(); | 654 static_cast<IPC::Listener*>(password_generation_)->OnMessageReceived(msg); |
672 EXPECT_TRUE(fake_driver_.called_presave_generated_password()); | 655 EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching( |
673 fake_driver_.reset_called_presave_generated_password(); | 656 AutofillHostMsg_PresaveGeneratedPassword::ID)); |
| 657 render_thread_->sink().ClearMessages(); |
674 | 658 |
675 FocusField(test_case.generation_element); | 659 FocusField(test_case.generation_element); |
676 SimulateUserTypingASCIICharacter('a', true); | 660 SimulateUserTypingASCIICharacter('a', true); |
677 base::RunLoop().RunUntilIdle(); | 661 EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching( |
678 EXPECT_TRUE(fake_driver_.called_presave_generated_password()); | 662 AutofillHostMsg_PresaveGeneratedPassword::ID)); |
679 fake_driver_.reset_called_presave_generated_password(); | 663 render_thread_->sink().ClearMessages(); |
680 | 664 |
681 for (size_t i = 0; i < password.length(); ++i) | 665 for (size_t i = 0; i < password.length(); ++i) |
682 SimulateUserTypingASCIICharacter(ui::VKEY_BACK, false); | 666 SimulateUserTypingASCIICharacter(ui::VKEY_BACK, false); |
683 SimulateUserTypingASCIICharacter(ui::VKEY_BACK, true); | 667 SimulateUserTypingASCIICharacter(ui::VKEY_BACK, true); |
684 base::RunLoop().RunUntilIdle(); | 668 EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching( |
685 EXPECT_TRUE(fake_driver_.called_password_no_longer_generated()); | 669 AutofillHostMsg_PasswordNoLongerGenerated::ID)); |
686 fake_driver_.reset_called_password_no_longer_generated(); | 670 render_thread_->sink().ClearMessages(); |
687 } | 671 } |
688 } | 672 } |
689 | 673 |
690 TEST_F(PasswordGenerationAgentTest, FormClassifierVotesSignupForm) { | 674 TEST_F(PasswordGenerationAgentTest, FormClassifierVotesSignupForm) { |
691 AllowToRunFormClassifier(); | 675 AllowToRunFormClassifier(); |
692 LoadHTMLWithUserGesture(kAccountCreationFormHTML); | 676 LoadHTMLWithUserGesture(kAccountCreationFormHTML); |
693 ExpectFormClassifierVoteReceived(true /* vote is expected */, | 677 ExpectFormClassifierVoteReceived(true /* vote is expected */, |
694 base::ASCIIToUTF16("first_password")); | 678 base::ASCIIToUTF16("first_password")); |
695 } | 679 } |
696 | 680 |
697 TEST_F(PasswordGenerationAgentTest, FormClassifierVotesSigninForm) { | 681 TEST_F(PasswordGenerationAgentTest, FormClassifierVotesSigninForm) { |
698 AllowToRunFormClassifier(); | 682 AllowToRunFormClassifier(); |
699 LoadHTMLWithUserGesture(kSigninFormHTML); | 683 LoadHTMLWithUserGesture(kSigninFormHTML); |
700 ExpectFormClassifierVoteReceived(true /* vote is expected */, | 684 ExpectFormClassifierVoteReceived(true /* vote is expected */, |
701 base::string16()); | 685 base::string16()); |
702 } | 686 } |
703 | 687 |
704 TEST_F(PasswordGenerationAgentTest, FormClassifierDisabled) { | 688 TEST_F(PasswordGenerationAgentTest, FormClassifierDisabled) { |
705 LoadHTMLWithUserGesture(kSigninFormHTML); | 689 LoadHTMLWithUserGesture(kSigninFormHTML); |
706 ExpectFormClassifierVoteReceived(false /* vote is not expected */, | 690 ExpectFormClassifierVoteReceived(false /* vote is not expected */, |
707 base::string16()); | 691 base::string16()); |
708 } | 692 } |
709 | 693 |
710 } // namespace autofill | 694 } // namespace autofill |
OLD | NEW |