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