OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "content/browser/site_per_process_browsertest.h" | 5 #include "content/browser/site_per_process_browsertest.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 const std::string& name) { | 90 const std::string& name) { |
91 bool success = false; | 91 bool success = false; |
92 EXPECT_TRUE(ExecuteScriptAndExtractBool( | 92 EXPECT_TRUE(ExecuteScriptAndExtractBool( |
93 caller_frame, | 93 caller_frame, |
94 "window.domAutomationController.send(" | 94 "window.domAutomationController.send(" |
95 " !!window.open('" + url.spec() + "', '" + name + "'));", | 95 " !!window.open('" + url.spec() + "', '" + name + "'));", |
96 &success)); | 96 &success)); |
97 EXPECT_TRUE(success); | 97 EXPECT_TRUE(success); |
98 } | 98 } |
99 | 99 |
| 100 // Helper function to generate a click on the given RenderWidgetHost. The |
| 101 // mouse event is forwarded directly to the RenderWidgetHost without any |
| 102 // hit-testing. |
| 103 void SimulateMouseClick(RenderWidgetHost* rwh, int x, int y) { |
| 104 blink::WebMouseEvent mouse_event; |
| 105 mouse_event.type = blink::WebInputEvent::MouseDown; |
| 106 mouse_event.button = blink::WebPointerProperties::ButtonLeft; |
| 107 mouse_event.x = x; |
| 108 mouse_event.y = y; |
| 109 rwh->ForwardMouseEvent(mouse_event); |
| 110 } |
| 111 |
100 class RedirectNotificationObserver : public NotificationObserver { | 112 class RedirectNotificationObserver : public NotificationObserver { |
101 public: | 113 public: |
102 // Register to listen for notifications of the given type from either a | 114 // Register to listen for notifications of the given type from either a |
103 // specific source, or from all sources if |source| is | 115 // specific source, or from all sources if |source| is |
104 // NotificationService::AllSources(). | 116 // NotificationService::AllSources(). |
105 RedirectNotificationObserver(int notification_type, | 117 RedirectNotificationObserver(int notification_type, |
106 const NotificationSource& source); | 118 const NotificationSource& source); |
107 ~RedirectNotificationObserver() override; | 119 ~RedirectNotificationObserver() override; |
108 | 120 |
109 // Wait until the specified notification occurs. If the notification was | 121 // Wait until the specified notification occurs. If the notification was |
(...skipping 3536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3646 EXPECT_TRUE(ExecuteScriptAndExtractString(shell()->web_contents(), | 3658 EXPECT_TRUE(ExecuteScriptAndExtractString(shell()->web_contents(), |
3647 "focusInputField()", &result)); | 3659 "focusInputField()", &result)); |
3648 EXPECT_EQ(result, "input-focus"); | 3660 EXPECT_EQ(result, "input-focus"); |
3649 | 3661 |
3650 // The main frame should be focused. | 3662 // The main frame should be focused. |
3651 EXPECT_EQ(root, root->frame_tree()->GetFocusedFrame()); | 3663 EXPECT_EQ(root, root->frame_tree()->GetFocusedFrame()); |
3652 | 3664 |
3653 DOMMessageQueue msg_queue; | 3665 DOMMessageQueue msg_queue; |
3654 | 3666 |
3655 // Click on the cross-process subframe. | 3667 // Click on the cross-process subframe. |
3656 blink::WebMouseEvent mouse_event; | 3668 SimulateMouseClick( |
3657 mouse_event.type = blink::WebInputEvent::MouseDown; | 3669 root->child_at(0)->current_frame_host()->GetRenderWidgetHost(), 1, 1); |
3658 mouse_event.button = blink::WebPointerProperties::ButtonLeft; | |
3659 mouse_event.x = 1; | |
3660 mouse_event.y = 1; | |
3661 RenderWidgetHost* rwh_child = | |
3662 root->child_at(0)->current_frame_host()->GetRenderWidgetHost(); | |
3663 rwh_child->ForwardMouseEvent(mouse_event); | |
3664 | 3670 |
3665 // Check that the main frame lost focus and fired blur event on the input | 3671 // Check that the main frame lost focus and fired blur event on the input |
3666 // text field. | 3672 // text field. |
3667 std::string status; | 3673 std::string status; |
3668 while (msg_queue.WaitForMessage(&status)) { | 3674 while (msg_queue.WaitForMessage(&status)) { |
3669 if (status == "\"input-blur\"") | 3675 if (status == "\"input-blur\"") |
3670 break; | 3676 break; |
3671 } | 3677 } |
3672 | 3678 |
3673 // The subframe should now be focused. | 3679 // The subframe should now be focused. |
3674 EXPECT_EQ(root->child_at(0), root->frame_tree()->GetFocusedFrame()); | 3680 EXPECT_EQ(root->child_at(0), root->frame_tree()->GetFocusedFrame()); |
3675 | 3681 |
3676 // Click on the root frame. | 3682 // Click on the root frame. |
3677 shell()->web_contents()->GetRenderViewHost()->GetWidget()->ForwardMouseEvent( | 3683 SimulateMouseClick( |
3678 mouse_event); | 3684 shell()->web_contents()->GetRenderViewHost()->GetWidget(), 1, 1); |
3679 | 3685 |
3680 // Check that the subframe lost focus and fired blur event on its | 3686 // Check that the subframe lost focus and fired blur event on its |
3681 // document's body. | 3687 // document's body. |
3682 while (msg_queue.WaitForMessage(&status)) { | 3688 while (msg_queue.WaitForMessage(&status)) { |
3683 if (status == "\"document-blur\"") | 3689 if (status == "\"document-blur\"") |
3684 break; | 3690 break; |
3685 } | 3691 } |
3686 | 3692 |
3687 // The root frame should be focused again. | 3693 // The root frame should be focused again. |
3688 EXPECT_EQ(root, root->frame_tree()->GetFocusedFrame()); | 3694 EXPECT_EQ(root, root->frame_tree()->GetFocusedFrame()); |
3689 } | 3695 } |
3690 | 3696 |
| 3697 // Check that when a cross-process subframe is focused, its parent's |
| 3698 // document.activeElement correctly returns the corresponding <iframe> element. |
| 3699 // The test sets up an A-embed-B-embed-C page and shifts focus A->B->A->C, |
| 3700 // checking document.activeElement after each change. |
| 3701 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DocumentActiveElement) { |
| 3702 GURL main_url(embedded_test_server()->GetURL( |
| 3703 "a.com", "/cross_site_iframe_factory.html?a(b(c))")); |
| 3704 EXPECT_TRUE(NavigateToURL(shell(), main_url)); |
| 3705 |
| 3706 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) |
| 3707 ->GetFrameTree() |
| 3708 ->root(); |
| 3709 |
| 3710 EXPECT_EQ( |
| 3711 " Site A ------------ proxies for B C\n" |
| 3712 " +--Site B ------- proxies for A C\n" |
| 3713 " +--Site C -- proxies for A B\n" |
| 3714 "Where A = http://a.com/\n" |
| 3715 " B = http://b.com/\n" |
| 3716 " C = http://c.com/", |
| 3717 DepictFrameTree(root)); |
| 3718 |
| 3719 FrameTreeNode* child = root->child_at(0); |
| 3720 FrameTreeNode* grandchild = root->child_at(0)->child_at(0); |
| 3721 |
| 3722 // The main frame should be focused to start with. |
| 3723 EXPECT_EQ(root, root->frame_tree()->GetFocusedFrame()); |
| 3724 |
| 3725 DOMMessageQueue msg_queue; |
| 3726 |
| 3727 // Register focus and blur events that will send messages when main frame's |
| 3728 // document body gets or loses focus. |
| 3729 std::string setup_focus_events = |
| 3730 "document.body.onfocus = function() { " |
| 3731 " domAutomationController.setAutomationId(0);" |
| 3732 " domAutomationController.send('got-focus');" |
| 3733 "};" |
| 3734 "document.body.onblur = function() { " |
| 3735 " domAutomationController.setAutomationId(0);" |
| 3736 " domAutomationController.send('lost-focus');" |
| 3737 "};"; |
| 3738 EXPECT_TRUE(ExecuteScript(shell()->web_contents(), setup_focus_events)); |
| 3739 |
| 3740 // Click on the b.com frame. |
| 3741 SimulateMouseClick(child->current_frame_host()->GetRenderWidgetHost(), 1, 1); |
| 3742 |
| 3743 // Wait for the main frame to lose focus and fire a blur event on its |
| 3744 // document body. |
| 3745 std::string status; |
| 3746 while (msg_queue.WaitForMessage(&status)) { |
| 3747 if (status == "\"lost-focus\"") |
| 3748 break; |
| 3749 } |
| 3750 |
| 3751 // The b.com frame should now be focused. |
| 3752 EXPECT_EQ(child, root->frame_tree()->GetFocusedFrame()); |
| 3753 |
| 3754 // Helper function to check a property of document.activeElement in the main |
| 3755 // frame. |
| 3756 auto verify_active_element_property = [](RenderFrameHost* rfh, |
| 3757 const std::string& property, |
| 3758 const std::string& expected_value) { |
| 3759 std::string script = base::StringPrintf( |
| 3760 "window.domAutomationController.send(document.activeElement.%s);", |
| 3761 property.c_str()); |
| 3762 std::string result; |
| 3763 EXPECT_TRUE(ExecuteScriptAndExtractString(rfh, script, &result)); |
| 3764 EXPECT_EQ(expected_value, base::ToLowerASCII(result)); |
| 3765 }; |
| 3766 |
| 3767 // Verify that document.activeElement points to the <iframe> element for the |
| 3768 // b.com frame. |
| 3769 RenderFrameHost* root_rfh = root->current_frame_host(); |
| 3770 verify_active_element_property(root_rfh, "tagName", "iframe"); |
| 3771 verify_active_element_property(root_rfh, "src", child->current_url().spec()); |
| 3772 |
| 3773 // Click on the main frame and wait for it to be focused again. |
| 3774 SimulateMouseClick( |
| 3775 shell()->web_contents()->GetRenderViewHost()->GetWidget(), 1, 1); |
| 3776 while (msg_queue.WaitForMessage(&status)) { |
| 3777 if (status == "\"got-focus\"") |
| 3778 break; |
| 3779 } |
| 3780 EXPECT_EQ(root, root->frame_tree()->GetFocusedFrame()); |
| 3781 |
| 3782 // Main frame document's <body> should now be the active element. |
| 3783 verify_active_element_property(root_rfh, "tagName", "body"); |
| 3784 |
| 3785 // Click on the grandchild frame to focus it. |
| 3786 SimulateMouseClick( |
| 3787 grandchild->current_frame_host()->GetRenderWidgetHost(), 1, 1); |
| 3788 |
| 3789 // Wait for main frame to lose focus. |
| 3790 while (msg_queue.WaitForMessage(&status)) { |
| 3791 if (status == "\"lost-focus\"") |
| 3792 break; |
| 3793 } |
| 3794 |
| 3795 // Check document.activeElement in main frame. It should still point to |
| 3796 // <iframe> for the b.com frame, since Blink computes the focused iframe |
| 3797 // element by walking the parent chain of the focused frame until it hits the |
| 3798 // current frame. This logic should still work with remote frames. |
| 3799 verify_active_element_property(root_rfh, "tagName", "iframe"); |
| 3800 verify_active_element_property(root_rfh, "src", child->current_url().spec()); |
| 3801 |
| 3802 // Check document.activeElement in b.com subframe. It should point to |
| 3803 // <iframe> for the c.com frame. This is a tricky case where B needs to find |
| 3804 // out that focus changed from one remote frame to another (A to C). |
| 3805 RenderFrameHost* child_rfh = child->current_frame_host(); |
| 3806 verify_active_element_property(child_rfh, "tagName", "iframe"); |
| 3807 verify_active_element_property(child_rfh, "src", |
| 3808 grandchild->current_url().spec()); |
| 3809 } |
| 3810 |
3691 // There are no cursors on Android. | 3811 // There are no cursors on Android. |
3692 #if !defined(OS_ANDROID) | 3812 #if !defined(OS_ANDROID) |
3693 class CursorMessageFilter : public content::BrowserMessageFilter { | 3813 class CursorMessageFilter : public content::BrowserMessageFilter { |
3694 public: | 3814 public: |
3695 CursorMessageFilter() | 3815 CursorMessageFilter() |
3696 : content::BrowserMessageFilter(ViewMsgStart), | 3816 : content::BrowserMessageFilter(ViewMsgStart), |
3697 message_loop_runner_(new content::MessageLoopRunner), | 3817 message_loop_runner_(new content::MessageLoopRunner), |
3698 last_set_cursor_routing_id_(MSG_ROUTING_NONE) {} | 3818 last_set_cursor_routing_id_(MSG_ROUTING_NONE) {} |
3699 | 3819 |
3700 bool OnMessageReceived(const IPC::Message& message) override { | 3820 bool OnMessageReceived(const IPC::Message& message) override { |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3785 | 3905 |
3786 // Use new window to navigate main window. | 3906 // Use new window to navigate main window. |
3787 std::string script = | 3907 std::string script = |
3788 "window.opener.location.href = '" + cross_url.spec() + "'"; | 3908 "window.opener.location.href = '" + cross_url.spec() + "'"; |
3789 EXPECT_TRUE(ExecuteScript(popup->web_contents(), script)); | 3909 EXPECT_TRUE(ExecuteScript(popup->web_contents(), script)); |
3790 EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); | 3910 EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); |
3791 EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), cross_url); | 3911 EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), cross_url); |
3792 } | 3912 } |
3793 | 3913 |
3794 } // namespace content | 3914 } // namespace content |
OLD | NEW |