| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "base/command_line.h" | 5 #include "base/command_line.h" |
| 6 #include "base/files/file_path.h" | 6 #include "base/files/file_path.h" |
| 7 #include "base/macros.h" | 7 #include "base/macros.h" |
| 8 #include "base/path_service.h" | 8 #include "base/path_service.h" |
| 9 #include "base/strings/stringprintf.h" | 9 #include "base/strings/stringprintf.h" |
| 10 #include "base/test/scoped_feature_list.h" | |
| 11 #include "chrome/browser/chrome_notification_types.h" | 10 #include "chrome/browser/chrome_notification_types.h" |
| 12 #include "chrome/browser/external_protocol/external_protocol_handler.h" | 11 #include "chrome/browser/external_protocol/external_protocol_handler.h" |
| 13 #include "chrome/browser/loader/chrome_resource_dispatcher_host_delegate.h" | 12 #include "chrome/browser/loader/chrome_resource_dispatcher_host_delegate.h" |
| 14 #include "chrome/browser/password_manager/chrome_password_manager_client.h" | |
| 15 #include "chrome/browser/profiles/profile.h" | 13 #include "chrome/browser/profiles/profile.h" |
| 16 #include "chrome/browser/ui/browser.h" | 14 #include "chrome/browser/ui/browser.h" |
| 17 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 15 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 18 #include "chrome/test/base/in_process_browser_test.h" | 16 #include "chrome/test/base/in_process_browser_test.h" |
| 19 #include "chrome/test/base/ui_test_utils.h" | 17 #include "chrome/test/base/ui_test_utils.h" |
| 20 #include "components/autofill/core/browser/autofill_client.h" | |
| 21 #include "components/autofill/core/browser/test_autofill_client.h" | |
| 22 #include "components/guest_view/browser/guest_view_manager_delegate.h" | 18 #include "components/guest_view/browser/guest_view_manager_delegate.h" |
| 23 #include "components/guest_view/browser/test_guest_view_manager.h" | 19 #include "components/guest_view/browser/test_guest_view_manager.h" |
| 24 #include "components/security_state/core/security_state.h" | |
| 25 #include "content/public/browser/focused_node_details.h" | |
| 26 #include "content/public/browser/interstitial_page.h" | 20 #include "content/public/browser/interstitial_page.h" |
| 27 #include "content/public/browser/notification_details.h" | |
| 28 #include "content/public/browser/notification_observer.h" | 21 #include "content/public/browser/notification_observer.h" |
| 29 #include "content/public/browser/notification_registrar.h" | |
| 30 #include "content/public/browser/notification_service.h" | 22 #include "content/public/browser/notification_service.h" |
| 31 #include "content/public/browser/notification_source.h" | |
| 32 #include "content/public/browser/notification_types.h" | 23 #include "content/public/browser/notification_types.h" |
| 33 #include "content/public/browser/render_frame_host.h" | 24 #include "content/public/browser/render_frame_host.h" |
| 34 #include "content/public/browser/render_widget_host_view.h" | |
| 35 #include "content/public/browser/web_contents.h" | 25 #include "content/public/browser/web_contents.h" |
| 36 #include "content/public/browser/web_contents_observer.h" | 26 #include "content/public/browser/web_contents_observer.h" |
| 37 #include "content/public/test/browser_test_utils.h" | 27 #include "content/public/test/browser_test_utils.h" |
| 38 #include "content/public/test/content_browser_test_utils.h" | 28 #include "content/public/test/content_browser_test_utils.h" |
| 39 #include "content/public/test/test_utils.h" | 29 #include "content/public/test/test_utils.h" |
| 40 #include "extensions/browser/api/extensions_api_client.h" | 30 #include "extensions/browser/api/extensions_api_client.h" |
| 41 #include "net/dns/mock_host_resolver.h" | 31 #include "net/dns/mock_host_resolver.h" |
| 42 #include "net/test/embedded_test_server/embedded_test_server.h" | 32 #include "net/test/embedded_test_server/embedded_test_server.h" |
| 43 #include "ui/display/display_switches.h" | 33 #include "ui/display/display_switches.h" |
| 44 #include "ui/gfx/geometry/point.h" | |
| 45 #include "ui/gfx/geometry/rect.h" | |
| 46 #include "ui/gfx/geometry/vector2d.h" | |
| 47 #include "url/gurl.h" | 34 #include "url/gurl.h" |
| 48 | 35 |
| 49 namespace autofill { | |
| 50 class AutofillPopupDelegate; | |
| 51 struct Suggestion; | |
| 52 } | |
| 53 | |
| 54 class ChromeSitePerProcessTest : public InProcessBrowserTest { | 36 class ChromeSitePerProcessTest : public InProcessBrowserTest { |
| 55 public: | 37 public: |
| 56 ChromeSitePerProcessTest() {} | 38 ChromeSitePerProcessTest() {} |
| 57 ~ChromeSitePerProcessTest() override {} | 39 ~ChromeSitePerProcessTest() override {} |
| 58 | 40 |
| 59 void SetUpCommandLine(base::CommandLine* command_line) override { | 41 void SetUpCommandLine(base::CommandLine* command_line) override { |
| 60 content::IsolateAllSitesForTesting(command_line); | 42 content::IsolateAllSitesForTesting(command_line); |
| 61 } | 43 } |
| 62 | 44 |
| 63 void SetUpOnMainThread() override { | 45 void SetUpOnMainThread() override { |
| (...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 519 "document.querySelector('iframe').src = '" + frame_url.spec() + "';\n" | 501 "document.querySelector('iframe').src = '" + frame_url.spec() + "';\n" |
| 520 "var w = window.open('about:blank');\n" | 502 "var w = window.open('about:blank');\n" |
| 521 "window.domAutomationController.send(!!w);\n", | 503 "window.domAutomationController.send(!!w);\n", |
| 522 &popup_handle_is_valid)); | 504 &popup_handle_is_valid)); |
| 523 popup_observer.Wait(); | 505 popup_observer.Wait(); |
| 524 | 506 |
| 525 // The popup shouldn't be blocked. | 507 // The popup shouldn't be blocked. |
| 526 EXPECT_TRUE(popup_handle_is_valid); | 508 EXPECT_TRUE(popup_handle_is_valid); |
| 527 ASSERT_EQ(2, browser()->tab_strip_model()->count()); | 509 ASSERT_EQ(2, browser()->tab_strip_model()->count()); |
| 528 } | 510 } |
| 529 | |
| 530 class ChromeSitePerProcessAutofillTest : public ChromeSitePerProcessTest { | |
| 531 public: | |
| 532 ChromeSitePerProcessAutofillTest() : ChromeSitePerProcessTest() {} | |
| 533 ~ChromeSitePerProcessAutofillTest() override{}; | |
| 534 | |
| 535 void SetUpCommandLine(base::CommandLine* command_line) override { | |
| 536 ChromeSitePerProcessTest::SetUpCommandLine(command_line); | |
| 537 // We need to set the feature state before the render process is created, | |
| 538 // in order for it to inherit the feature state from the browser process. | |
| 539 // SetUp() runs too early, and SetUpOnMainThread() runs too late. | |
| 540 scoped_feature_list_.InitAndEnableFeature( | |
| 541 security_state::kHttpFormWarningFeature); | |
| 542 } | |
| 543 | |
| 544 void SetUpOnMainThread() override { | |
| 545 ChromeSitePerProcessTest::SetUpOnMainThread(); | |
| 546 } | |
| 547 | |
| 548 protected: | |
| 549 class TestAutofillClient : public autofill::TestAutofillClient { | |
| 550 public: | |
| 551 TestAutofillClient() : popup_shown_(false){}; | |
| 552 ~TestAutofillClient() override {} | |
| 553 | |
| 554 void WaitForNextPopup() { | |
| 555 if (popup_shown_) | |
| 556 return; | |
| 557 loop_runner_ = new content::MessageLoopRunner(); | |
| 558 loop_runner_->Run(); | |
| 559 } | |
| 560 | |
| 561 void ShowAutofillPopup( | |
| 562 const gfx::RectF& element_bounds, | |
| 563 base::i18n::TextDirection text_direction, | |
| 564 const std::vector<autofill::Suggestion>& suggestions, | |
| 565 base::WeakPtr<autofill::AutofillPopupDelegate> delegate) override { | |
| 566 element_bounds_ = element_bounds; | |
| 567 popup_shown_ = true; | |
| 568 if (loop_runner_) | |
| 569 loop_runner_->Quit(); | |
| 570 } | |
| 571 | |
| 572 const gfx::RectF& last_element_bounds() const { return element_bounds_; } | |
| 573 | |
| 574 private: | |
| 575 gfx::RectF element_bounds_; | |
| 576 bool popup_shown_; | |
| 577 scoped_refptr<content::MessageLoopRunner> loop_runner_; | |
| 578 | |
| 579 DISALLOW_COPY_AND_ASSIGN(TestAutofillClient); | |
| 580 }; | |
| 581 | |
| 582 const int kIframeTopDisplacement = 150; | |
| 583 const int kIframeLeftDisplacement = 200; | |
| 584 | |
| 585 void SetupMainTab() { | |
| 586 // Add a fresh new WebContents for which we add our own version of the | |
| 587 // ChromePasswordManagerClient that uses a custom TestAutofillClient. | |
| 588 content::WebContents* new_contents = content::WebContents::Create( | |
| 589 content::WebContents::CreateParams(browser() | |
| 590 ->tab_strip_model() | |
| 591 ->GetActiveWebContents() | |
| 592 ->GetBrowserContext())); | |
| 593 ASSERT_TRUE(new_contents); | |
| 594 ASSERT_FALSE(ChromePasswordManagerClient::FromWebContents(new_contents)); | |
| 595 | |
| 596 // Create ChromePasswordManagerClient and verify it exists for the new | |
| 597 // WebContents. | |
| 598 ChromePasswordManagerClient::CreateForWebContentsWithAutofillClient( | |
| 599 new_contents, &test_autofill_client_); | |
| 600 ASSERT_TRUE(ChromePasswordManagerClient::FromWebContents(new_contents)); | |
| 601 | |
| 602 browser()->tab_strip_model()->AppendWebContents(new_contents, true); | |
| 603 } | |
| 604 | |
| 605 TestAutofillClient& autofill_client() { return test_autofill_client_; } | |
| 606 | |
| 607 private: | |
| 608 base::test::ScopedFeatureList scoped_feature_list_; | |
| 609 TestAutofillClient test_autofill_client_; | |
| 610 | |
| 611 DISALLOW_COPY_AND_ASSIGN(ChromeSitePerProcessAutofillTest); | |
| 612 }; | |
| 613 | |
| 614 // Observes the notifications for changes in focused node/element in the page. | |
| 615 // The notification contains | |
| 616 class FocusedEditableNodeChangedObserver : content::NotificationObserver { | |
| 617 public: | |
| 618 FocusedEditableNodeChangedObserver() : observed_(false) { | |
| 619 registrar_.Add(this, content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE, | |
| 620 content::NotificationService::AllSources()); | |
| 621 } | |
| 622 ~FocusedEditableNodeChangedObserver() override {} | |
| 623 | |
| 624 void WaitForFocusChangeInPage() { | |
| 625 if (observed_) | |
| 626 return; | |
| 627 loop_runner_ = new content::MessageLoopRunner(); | |
| 628 loop_runner_->Run(); | |
| 629 } | |
| 630 | |
| 631 // content::NotificationObserver override. | |
| 632 void Observe(int type, | |
| 633 const content::NotificationSource& source, | |
| 634 const content::NotificationDetails& details) override { | |
| 635 auto focused_node_details = | |
| 636 content::Details<content::FocusedNodeDetails>(details); | |
| 637 if (!focused_node_details->is_editable_node) | |
| 638 return; | |
| 639 focused_node_bounds_in_screen_ = | |
| 640 focused_node_details->node_bounds_in_screen.origin(); | |
| 641 observed_ = true; | |
| 642 if (loop_runner_) | |
| 643 loop_runner_->Quit(); | |
| 644 } | |
| 645 | |
| 646 const gfx::Point& focused_node_bounds_in_screen() const { | |
| 647 return focused_node_bounds_in_screen_; | |
| 648 } | |
| 649 | |
| 650 private: | |
| 651 content::NotificationRegistrar registrar_; | |
| 652 bool observed_; | |
| 653 gfx::Point focused_node_bounds_in_screen_; | |
| 654 scoped_refptr<content::MessageLoopRunner> loop_runner_; | |
| 655 | |
| 656 DISALLOW_COPY_AND_ASSIGN(FocusedEditableNodeChangedObserver); | |
| 657 }; | |
| 658 | |
| 659 // This test verifies that displacements (margin, etc) in the position of an | |
| 660 // OOPIF is considered when showing an AutofillClient warning pop-up for | |
| 661 // unsecure web sites. | |
| 662 IN_PROC_BROWSER_TEST_F(ChromeSitePerProcessAutofillTest, | |
| 663 AutofillClientPositionWhenInsideOOPIF) { | |
| 664 SetupMainTab(); | |
| 665 ASSERT_TRUE( | |
| 666 base::FeatureList::IsEnabled(security_state::kHttpFormWarningFeature)); | |
| 667 | |
| 668 GURL main_url(embedded_test_server()->GetURL("a.com", "/iframe.html")); | |
| 669 ui_test_utils::NavigateToURL(browser(), main_url); | |
| 670 content::WebContents* active_web_contents = | |
| 671 browser()->tab_strip_model()->GetActiveWebContents(); | |
| 672 | |
| 673 // Add some displacement for <iframe>. | |
| 674 ASSERT_TRUE(content::ExecuteScript( | |
| 675 active_web_contents, | |
| 676 base::StringPrintf("var iframe = document.querySelector('iframe');" | |
| 677 "iframe.style.marginTop = '%dpx';" | |
| 678 "iframe.style.marginLeft = '%dpx';", | |
| 679 kIframeTopDisplacement, kIframeLeftDisplacement))); | |
| 680 | |
| 681 // Navigate the <iframe> to a simple page. | |
| 682 GURL frame_url = embedded_test_server()->GetURL("b.com", "/title1.html"); | |
| 683 EXPECT_TRUE(NavigateIframeToURL(active_web_contents, "test", frame_url)); | |
| 684 content::RenderFrameHost* child_frame = content::FrameMatchingPredicate( | |
| 685 active_web_contents, base::Bind(&content::FrameIsChildOfMainFrame)); | |
| 686 | |
| 687 // We will need to listen to focus changes to find out about the container | |
| 688 // bounds of any focused <input> elements on the page. | |
| 689 FocusedEditableNodeChangedObserver focus_observer; | |
| 690 | |
| 691 // Focus the child frame, add an <input> with type "password", and focus it. | |
| 692 ASSERT_TRUE(ExecuteScript(child_frame, | |
| 693 "window.focus();" | |
| 694 "var input = document.createElement('input');" | |
| 695 "input.type = 'password';" | |
| 696 "document.body.appendChild(input);" | |
| 697 "input.focus();")); | |
| 698 focus_observer.WaitForFocusChangeInPage(); | |
| 699 | |
| 700 // The user gesture (input) should lead to a security warning. | |
| 701 content::SimulateKeyPress(active_web_contents, ui::DomKey::FromCharacter('A'), | |
| 702 ui::DomCode::US_A, ui::VKEY_A, false, false, false, | |
| 703 false); | |
| 704 autofill_client().WaitForNextPopup(); | |
| 705 | |
| 706 gfx::Point bounds_origin( | |
| 707 static_cast<int>(autofill_client().last_element_bounds().origin().x()), | |
| 708 static_cast<int>(autofill_client().last_element_bounds().origin().y())); | |
| 709 | |
| 710 // Convert the bounds to screen coordinates (to then compare against the ones | |
| 711 // reported by focus change observer). | |
| 712 bounds_origin += active_web_contents->GetRenderWidgetHostView() | |
| 713 ->GetViewBounds() | |
| 714 .OffsetFromOrigin(); | |
| 715 | |
| 716 gfx::Vector2d error = | |
| 717 bounds_origin - focus_observer.focused_node_bounds_in_screen(); | |
| 718 | |
| 719 // Ideally, the length of the error vector should be 0.0f. But due to | |
| 720 // potential rounding errors, we assume a larger limit (which is slightly | |
| 721 // larger than square root of 2). | |
| 722 EXPECT_LT(error.Length(), 1.4143f); | |
| 723 } | |
| OLD | NEW |