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