Index: content/browser/site_per_process_browsertest.cc |
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc |
index ea4bb0da5c3fc3c61f87442773244420a49bf876..8a42ff77585a780d894c592ab5fc799419ef077e 100644 |
--- a/content/browser/site_per_process_browsertest.cc |
+++ b/content/browser/site_per_process_browsertest.cc |
@@ -1298,6 +1298,126 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, |
EXPECT_FALSE(child_frame_monitor.EventWasReceived()); |
} |
+// Verify that mouse capture works on a RenderWidgetHostView level, so that |
+// dragging scroll bars and selecting text continues even when the mouse |
+// cursor crosses over inter-process frame boundaries. |
nasko
2016/09/14 16:36:47
nit: s/inter-process/cross-process/
kenrb
2016/09/14 20:33:32
Done.
|
+#if defined(OS_ANDROID) |
+// Browser process hit testing is not implemented on Android. |
+// https://crbug.com/491334 |
+#define MAYBE_CrossProcessMouseCapture DISABLED_CrossProcessMouseCapture |
+#else |
+#define MAYBE_CrossProcessMouseCapture CrossProcessMouseCapture |
+#endif |
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, |
+ MAYBE_CrossProcessMouseCapture) { |
+ GURL main_url(embedded_test_server()->GetURL( |
+ "/frame_tree/page_with_positioned_frame.html")); |
+ NavigateToURL(shell(), main_url); |
nasko
2016/09/14 16:36:48
EXPECT_TRUE
kenrb
2016/09/14 20:33:32
Done.
|
+ |
+ // It is safe to obtain the root frame tree node here, as it doesn't change. |
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root(); |
+ ASSERT_EQ(1U, root->child_count()); |
+ |
+ FrameTreeNode* child_node = root->child_at(0); |
+ GURL site_url(embedded_test_server()->GetURL("baz.com", "/title1.html")); |
+ EXPECT_EQ(site_url, child_node->current_url()); |
+ EXPECT_NE(shell()->web_contents()->GetSiteInstance(), |
+ child_node->current_frame_host()->GetSiteInstance()); |
+ |
+ // Create listeners for mouse events. |
+ RenderWidgetHostMouseEventMonitor main_frame_monitor( |
+ root->current_frame_host()->GetRenderWidgetHost()); |
+ RenderWidgetHostMouseEventMonitor child_frame_monitor( |
+ child_node->current_frame_host()->GetRenderWidgetHost()); |
+ |
+ RenderWidgetHostInputEventRouter* router = |
+ web_contents()->GetInputEventRouter(); |
+ |
+ RenderWidgetHostViewBase* root_view = static_cast<RenderWidgetHostViewBase*>( |
+ root->current_frame_host()->GetRenderWidgetHost()->GetView()); |
+ RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>( |
+ child_node->current_frame_host()->GetRenderWidgetHost()->GetView()); |
+ |
+ SurfaceHitTestReadyNotifier notifier( |
+ static_cast<RenderWidgetHostViewChildFrame*>(rwhv_child)); |
+ notifier.WaitForSurfaceReady(); |
+ |
+ // Target MouseDown to child frame. |
+ blink::WebMouseEvent mouse_event; |
+ mouse_event.type = blink::WebInputEvent::MouseDown; |
+ mouse_event.button = blink::WebPointerProperties::Button::Left; |
+ mouse_event.x = 75; |
+ mouse_event.y = 75; |
+ mouse_event.clickCount = 1; |
+ main_frame_monitor.ResetEventReceived(); |
+ child_frame_monitor.ResetEventReceived(); |
+ router->RouteMouseEvent(root_view, &mouse_event); |
+ |
+ EXPECT_FALSE(main_frame_monitor.EventWasReceived()); |
+ EXPECT_TRUE(child_frame_monitor.EventWasReceived()); |
+ |
+ // Target MouseMove to main frame. This should still be routed to the |
+ // child frame because it is now capturing mouse input. |
+ mouse_event.type = blink::WebInputEvent::MouseMove; |
+ mouse_event.modifiers = blink::WebInputEvent::LeftButtonDown; |
+ mouse_event.x = 1; |
+ mouse_event.y = 1; |
+ main_frame_monitor.ResetEventReceived(); |
+ child_frame_monitor.ResetEventReceived(); |
+ router->RouteMouseEvent(root_view, &mouse_event); |
+ |
+ EXPECT_FALSE(main_frame_monitor.EventWasReceived()); |
+ EXPECT_TRUE(child_frame_monitor.EventWasReceived()); |
+ |
+ // A MouseUp to the child frame should cancel the mouse capture. |
+ mouse_event.type = blink::WebInputEvent::MouseUp; |
+ mouse_event.modifiers = 0; |
+ mouse_event.x = 75; |
+ mouse_event.y = 75; |
+ main_frame_monitor.ResetEventReceived(); |
+ child_frame_monitor.ResetEventReceived(); |
+ router->RouteMouseEvent(root_view, &mouse_event); |
+ |
+ EXPECT_FALSE(main_frame_monitor.EventWasReceived()); |
+ EXPECT_TRUE(child_frame_monitor.EventWasReceived()); |
+ |
+ // Subsequent MouseMove events targeted to the main frame should be routed |
+ // to that frame. |
+ mouse_event.type = blink::WebInputEvent::MouseMove; |
+ mouse_event.x = 1; |
+ mouse_event.y = 1; |
nasko
2016/09/14 16:36:48
nit: Should we actually move the mouse event to a
kenrb
2016/09/14 20:33:32
Done.
|
+ main_frame_monitor.ResetEventReceived(); |
+ child_frame_monitor.ResetEventReceived(); |
+ router->RouteMouseEvent(root_view, &mouse_event); |
+ |
+ EXPECT_TRUE(main_frame_monitor.EventWasReceived()); |
+ EXPECT_FALSE(child_frame_monitor.EventWasReceived()); |
+ |
+ // Target MouseDown to the main frame to cause it to capture input. |
+ mouse_event.type = blink::WebInputEvent::MouseDown; |
+ mouse_event.x = 1; |
+ mouse_event.y = 1; |
+ main_frame_monitor.ResetEventReceived(); |
+ child_frame_monitor.ResetEventReceived(); |
+ router->RouteMouseEvent(root_view, &mouse_event); |
+ |
+ EXPECT_TRUE(main_frame_monitor.EventWasReceived()); |
+ EXPECT_FALSE(child_frame_monitor.EventWasReceived()); |
+ |
+ // Sending a MouseMove to the child frame should still result in the main |
+ // frame receiving the event. |
+ mouse_event.type = blink::WebInputEvent::MouseMove; |
+ mouse_event.modifiers = blink::WebInputEvent::LeftButtonDown; |
+ mouse_event.x = 75; |
+ mouse_event.y = 75; |
+ main_frame_monitor.ResetEventReceived(); |
+ child_frame_monitor.ResetEventReceived(); |
+ router->RouteMouseEvent(root_view, &mouse_event); |
+ |
+ EXPECT_TRUE(main_frame_monitor.EventWasReceived()); |
+ EXPECT_FALSE(child_frame_monitor.EventWasReceived()); |
+} |
+ |
// Tests OOPIF rendering by checking that the RWH of the iframe generates |
// OnSwapCompositorFrame message. |
#if defined(OS_ANDROID) |