 Chromium Code Reviews
 Chromium Code Reviews Issue 1752833002:
  Implement Gesture event hit testing/forwarding for OOPIF.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@wjmCFTouch.v2
    
  
    Issue 1752833002:
  Implement Gesture event hit testing/forwarding for OOPIF.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@wjmCFTouch.v2| 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 <stddef.h> | 7 #include <stddef.h> | 
| 8 #include <stdint.h> | 8 #include <stdint.h> | 
| 9 | 9 | 
| 10 #include <algorithm> | 10 #include <algorithm> | 
| 11 #include <vector> | 11 #include <vector> | 
| 12 | 12 | 
| 13 #include "base/command_line.h" | 13 #include "base/command_line.h" | 
| 14 #include "base/location.h" | 14 #include "base/location.h" | 
| 15 #include "base/macros.h" | 15 #include "base/macros.h" | 
| 16 #include "base/single_thread_task_runner.h" | 16 #include "base/single_thread_task_runner.h" | 
| 17 #include "base/strings/pattern.h" | 17 #include "base/strings/pattern.h" | 
| 18 #include "base/strings/stringprintf.h" | 18 #include "base/strings/stringprintf.h" | 
| 19 #include "base/strings/utf_string_conversions.h" | 19 #include "base/strings/utf_string_conversions.h" | 
| 20 #include "base/test/test_timeouts.h" | 20 #include "base/test/test_timeouts.h" | 
| 21 #include "base/thread_task_runner_handle.h" | 21 #include "base/thread_task_runner_handle.h" | 
| 22 #include "build/build_config.h" | 22 #include "build/build_config.h" | 
| 23 #include "content/browser/frame_host/cross_process_frame_connector.h" | 23 #include "content/browser/frame_host/cross_process_frame_connector.h" | 
| 24 #include "content/browser/frame_host/frame_tree.h" | 24 #include "content/browser/frame_host/frame_tree.h" | 
| 25 #include "content/browser/frame_host/navigator.h" | 25 #include "content/browser/frame_host/navigator.h" | 
| 26 #include "content/browser/frame_host/render_frame_proxy_host.h" | 26 #include "content/browser/frame_host/render_frame_proxy_host.h" | 
| 27 #include "content/browser/frame_host/render_widget_host_view_child_frame.h" | 27 #include "content/browser/frame_host/render_widget_host_view_child_frame.h" | 
| 28 #include "content/browser/gpu/compositor_util.h" | 28 #include "content/browser/gpu/compositor_util.h" | 
| 29 #include "content/browser/renderer_host/input/synthetic_tap_gesture.h" | |
| 29 #include "content/browser/renderer_host/render_view_host_impl.h" | 30 #include "content/browser/renderer_host/render_view_host_impl.h" | 
| 30 #include "content/browser/renderer_host/render_widget_host_input_event_router.h" | 31 #include "content/browser/renderer_host/render_widget_host_input_event_router.h" | 
| 32 #include "content/browser/renderer_host/render_widget_host_view_aura.h" | |
| 31 #include "content/browser/web_contents/web_contents_impl.h" | 33 #include "content/browser/web_contents/web_contents_impl.h" | 
| 32 #include "content/common/frame_messages.h" | 34 #include "content/common/frame_messages.h" | 
| 35 #include "content/common/input/synthetic_tap_gesture_params.h" | |
| 33 #include "content/common/view_messages.h" | 36 #include "content/common/view_messages.h" | 
| 34 #include "content/public/browser/notification_observer.h" | 37 #include "content/public/browser/notification_observer.h" | 
| 35 #include "content/public/browser/notification_service.h" | 38 #include "content/public/browser/notification_service.h" | 
| 36 #include "content/public/browser/notification_types.h" | 39 #include "content/public/browser/notification_types.h" | 
| 37 #include "content/public/browser/resource_dispatcher_host.h" | 40 #include "content/public/browser/resource_dispatcher_host.h" | 
| 38 #include "content/public/common/browser_side_navigation_policy.h" | 41 #include "content/public/common/browser_side_navigation_policy.h" | 
| 39 #include "content/public/common/content_switches.h" | 42 #include "content/public/common/content_switches.h" | 
| 40 #include "content/public/test/browser_test_utils.h" | 43 #include "content/public/test/browser_test_utils.h" | 
| 41 #include "content/public/test/content_browser_test_utils.h" | 44 #include "content/public/test/content_browser_test_utils.h" | 
| 42 #include "content/public/test/test_navigation_observer.h" | 45 #include "content/public/test/test_navigation_observer.h" | 
| (...skipping 4524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4567 ui::EventTimeForNow(), 30.f, 30.f, 0.f, 0.f); | 4570 ui::EventTimeForNow(), 30.f, 30.f, 0.f, 0.f); | 
| 4568 rwhv->OnTouchEvent(&touch_event); | 4571 rwhv->OnTouchEvent(&touch_event); | 
| 4569 | 4572 | 
| 4570 // Verify touch handler in subframe was invoked | 4573 // Verify touch handler in subframe was invoked | 
| 4571 std::string result; | 4574 std::string result; | 
| 4572 EXPECT_TRUE(ExecuteScriptAndExtractString( | 4575 EXPECT_TRUE(ExecuteScriptAndExtractString( | 
| 4573 root->child_at(0)->current_frame_host(), | 4576 root->child_at(0)->current_frame_host(), | 
| 4574 "window.domAutomationController.send(getLastTouchEvent());", &result)); | 4577 "window.domAutomationController.send(getLastTouchEvent());", &result)); | 
| 4575 EXPECT_EQ("touchstart", result); | 4578 EXPECT_EQ("touchstart", result); | 
| 4576 } | 4579 } | 
| 4580 | |
| 4581 namespace { | |
| 4582 | |
| 4583 // Declared here to be close to the SubframeGestureEventRouting test. | |
| 4584 void OnSyntheticGestureCompleted(scoped_refptr<MessageLoopRunner> runner, | |
| 4585 SyntheticGesture::Result result) { | |
| 4586 EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result); | |
| 4587 runner->Quit(); | |
| 4588 } | |
| 4589 | |
| 4590 } // namespace anonymous | |
| 4591 | |
| 4592 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, | |
| 4593 SubframeGestureEventRouting) { | |
| 4594 GURL main_url(embedded_test_server()->GetURL( | |
| 4595 "/frame_tree/page_with_positioned_nested_frames.html")); | |
| 4596 EXPECT_TRUE(NavigateToURL(shell(), main_url)); | |
| 4597 | |
| 4598 WebContentsImpl* web_contents = | |
| 4599 static_cast<WebContentsImpl*>(shell()->web_contents()); | |
| 4600 FrameTreeNode* root = web_contents->GetFrameTree()->root(); | |
| 4601 ASSERT_EQ(1U, root->child_count()); | |
| 4602 | |
| 4603 GURL frame_url( | |
| 4604 embedded_test_server()->GetURL("b.com", "/page_with_click_handler.html")); | |
| 4605 NavigateFrameToURL(root->child_at(0), frame_url); | |
| 4606 auto child_frame_host = root->child_at(0)->current_frame_host(); | |
| 4607 EXPECT_TRUE(WaitForRenderFrameReady(child_frame_host)); | |
| 4608 | |
| 4609 // Synchronize with the child and parent renderers to guarantee that the | |
| 4610 // surface information required for event hit testing is ready. | |
| 4611 RenderWidgetHostViewBase* child_rwhv = static_cast<RenderWidgetHostViewBase*>( | |
| 4612 child_frame_host->GetView()); | |
| 4613 SurfaceHitTestReadyNotifier notifier( | |
| 4614 static_cast<RenderWidgetHostViewChildFrame*>(child_rwhv)); | |
| 4615 notifier.WaitForSurfaceReady(); | |
| 4616 | |
| 4617 // There have been no GestureTaps sent yet. | |
| 4618 { | |
| 4619 std::string result; | |
| 4620 EXPECT_TRUE(ExecuteScriptAndExtractString( | |
| 4621 child_frame_host, | |
| 4622 "window.domAutomationController.send(getClickStatus());", &result)); | |
| 4623 EXPECT_EQ("0 clicks received", result); | |
| 4624 } | |
| 4625 | |
| 4626 // Simulate touch sequence to send GestureTap to sub-frame. | |
| 4627 SyntheticTapGestureParams params; | |
| 4628 params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; | |
| 4629 gfx::Point center(150, 150); | |
| 4630 params.position = gfx::PointF(center.x(), center.y()); | |
| 4631 params.duration_ms = 100; | |
| 4632 scoped_ptr<SyntheticTapGesture> gesture(new SyntheticTapGesture(params)); | |
| 4633 | |
| 4634 scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner(); | |
| 4635 | |
| 4636 RenderWidgetHostImpl* render_widget_host = | |
| 4637 root->current_frame_host()->GetRenderWidgetHost(); | |
| 4638 // TODO(wjmaclean): Convert the call to base::Bind() to a lambda someday. | |
| 4639 render_widget_host->QueueSyntheticGesture( | |
| 4640 std::move(gesture), base::Bind(OnSyntheticGestureCompleted, runner)); | |
| 4641 | |
| 4642 // We need to run the message loop while we wait for the synthetic gesture | |
| 4643 // to be processed; the callback registered above will get us out of the | |
| 4644 // message loop when that happens. | |
| 4645 runner->Run(); | |
| 4646 runner = nullptr; | |
| 4647 | |
| 4648 // Verify click handler in subframe was invoked | |
| 4649 { | |
| 4650 std::string result; | |
| 4651 EXPECT_TRUE(ExecuteScriptAndExtractString( | |
| 4652 child_frame_host, | |
| 4653 "window.domAutomationController.send(getClickStatus());", &result)); | |
| 4654 EXPECT_EQ("1 click received", result); | |
| 4655 } | |
| 4656 } | |
| 4657 | |
| 4658 namespace { | |
| 4659 | |
| 4660 // Defined here to be close to | |
| 4661 // SitePerProcessBrowserTest.InputEventRouterGestureTargetQueueTest. | |
| 4662 void SendTouchTapWithExpectedTarget( | |
| 4663 RenderWidgetHostViewBase* root_view, | |
| 4664 const gfx::Point& touch_point, | |
| 4665 RenderWidgetHostViewBase*& router_touch_target, | |
| 4666 const RenderWidgetHostViewBase* expected_target) { | |
| 4667 auto root_view_aura = static_cast<RenderWidgetHostViewAura*>(root_view); | |
| 4668 ui::TouchEvent touch_event_pressed(ui::ET_TOUCH_PRESSED, touch_point, 0, | |
| 4669 0, ui::EventTimeForNow(), 30.f, 30.f, 0.f, | |
| 4670 0.f); | |
| 4671 root_view_aura->OnTouchEvent(&touch_event_pressed); | |
| 4672 EXPECT_EQ(expected_target, router_touch_target); | |
| 4673 ui::TouchEvent touch_event_released(ui::ET_TOUCH_RELEASED, touch_point, | |
| 4674 0, 0, ui::EventTimeForNow(), 30.f, 30.f, | |
| 4675 0.f, 0.f); | |
| 4676 root_view_aura->OnTouchEvent(&touch_event_released); | |
| 4677 EXPECT_EQ(nullptr, router_touch_target); | |
| 4678 } | |
| 4679 | |
| 4680 void SendGestureTapSequenceWithExpectedTarget( | |
| 4681 RenderWidgetHostViewBase* root_view, | |
| 4682 gfx::Point gesture_point, | |
| 4683 RenderWidgetHostViewBase*& router_gesture_target, | |
| 4684 const RenderWidgetHostViewBase* old_expected_target, | |
| 4685 const RenderWidgetHostViewBase* expected_target) { | |
| 4686 auto root_view_aura = static_cast<RenderWidgetHostViewAura*>(root_view); | |
| 4687 | |
| 4688 ui::GestureEvent gesture_begin_event( | |
| 4689 gesture_point.x(), gesture_point.y(), 0, ui::EventTimeForNow(), | |
| 4690 ui::GestureEventDetails(ui::ET_GESTURE_BEGIN)); | |
| 4691 root_view_aura->OnGestureEvent(&gesture_begin_event); | |
| 4692 // We expect to still have the old gesture target in place for the | |
| 4693 // GestureFlingCancel that will be inserted before GestureTapDown. | |
| 
tdresser
2016/03/04 19:51:01
We don't get a GFC in this test, correct? That mak
 
wjmaclean
2016/03/04 20:02:37
Actually, there is a GestureFlingCancel in the tes
 | |
| 4694 EXPECT_EQ(old_expected_target, router_gesture_target); | |
| 4695 | |
| 4696 ui::GestureEvent gesture_tap_down_event( | |
| 4697 gesture_point.x(), gesture_point.y(), 0, ui::EventTimeForNow(), | |
| 4698 ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN)); | |
| 4699 root_view_aura->OnGestureEvent(&gesture_tap_down_event); | |
| 4700 EXPECT_EQ(expected_target, router_gesture_target); | |
| 4701 | |
| 4702 ui::GestureEvent gesture_show_press_event( | |
| 4703 gesture_point.x(), gesture_point.y(), 0, ui::EventTimeForNow(), | |
| 4704 ui::GestureEventDetails(ui::ET_GESTURE_SHOW_PRESS)); | |
| 4705 root_view_aura->OnGestureEvent(&gesture_show_press_event); | |
| 4706 EXPECT_EQ(expected_target, router_gesture_target); | |
| 4707 | |
| 4708 ui::GestureEventDetails gesture_tap_details(ui::ET_GESTURE_TAP); | |
| 4709 gesture_tap_details.set_tap_count(1); | |
| 4710 ui::GestureEvent gesture_tap_event( | |
| 4711 gesture_point.x(), gesture_point.y(), 0, ui::EventTimeForNow(), | |
| 4712 gesture_tap_details); | |
| 4713 root_view_aura->OnGestureEvent(&gesture_tap_event); | |
| 4714 EXPECT_EQ(expected_target, router_gesture_target); | |
| 4715 | |
| 4716 ui::GestureEvent gesture_end_event( | |
| 4717 gesture_point.x(), gesture_point.y(), 0, ui::EventTimeForNow(), | |
| 4718 ui::GestureEventDetails(ui::ET_GESTURE_END)); | |
| 4719 root_view_aura->OnGestureEvent(&gesture_end_event); | |
| 4720 EXPECT_EQ(expected_target, router_gesture_target); | |
| 4721 } | |
| 4722 | |
| 4723 } // namespace anonymous | |
| 4724 | |
| 4725 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, | |
| 4726 InputEventRouterGestureTargetQueueTest) { | |
| 4727 GURL main_url(embedded_test_server()->GetURL( | |
| 4728 "/frame_tree/page_with_positioned_nested_frames.html")); | |
| 4729 EXPECT_TRUE(NavigateToURL(shell(), main_url)); | |
| 4730 | |
| 4731 WebContentsImpl* web_contents = | |
| 4732 static_cast<WebContentsImpl*>(shell()->web_contents()); | |
| 4733 FrameTreeNode* root = web_contents->GetFrameTree()->root(); | |
| 4734 ASSERT_EQ(1U, root->child_count()); | |
| 4735 | |
| 4736 GURL frame_url( | |
| 4737 embedded_test_server()->GetURL("b.com", "/page_with_click_handler.html")); | |
| 4738 NavigateFrameToURL(root->child_at(0), frame_url); | |
| 4739 auto child_frame_host = root->child_at(0)->current_frame_host(); | |
| 4740 EXPECT_TRUE(WaitForRenderFrameReady(child_frame_host)); | |
| 4741 | |
| 4742 // Synchronize with the child and parent renderers to guarantee that the | |
| 4743 // surface information required for event hit testing is ready. | |
| 4744 auto rwhv_child = | |
| 4745 static_cast<RenderWidgetHostViewBase*>(child_frame_host->GetView()); | |
| 4746 SurfaceHitTestReadyNotifier notifier( | |
| 4747 static_cast<RenderWidgetHostViewChildFrame*>(rwhv_child)); | |
| 4748 notifier.WaitForSurfaceReady(); | |
| 4749 | |
| 4750 // All touches & gestures are sent to the main frame's view, and should be | |
| 4751 // routed appropriately from there. | |
| 4752 auto rwhv_parent = static_cast<RenderWidgetHostViewBase*>( | |
| 4753 web_contents->GetRenderWidgetHostView()); | |
| 4754 | |
| 4755 RenderWidgetHostInputEventRouter* router = | |
| 4756 web_contents->GetInputEventRouter(); | |
| 4757 EXPECT_TRUE(router->gesture_target_queue_.empty()); | |
| 4758 EXPECT_EQ(nullptr, router->gesture_target_); | |
| 4759 | |
| 4760 // Send touch sequence to main-frame. | |
| 4761 gfx::Point main_frame_point(25, 25); | |
| 4762 SendTouchTapWithExpectedTarget(rwhv_parent, main_frame_point, | |
| 4763 router->touch_target_, rwhv_parent); | |
| 4764 EXPECT_EQ(1LU, router->gesture_target_queue_.size()); | |
| 4765 EXPECT_EQ(nullptr, router->gesture_target_); | |
| 4766 | |
| 4767 | |
| 4768 // Send touch sequence to child. | |
| 4769 gfx::Point child_center(150, 150); | |
| 4770 SendTouchTapWithExpectedTarget(rwhv_parent, child_center, | |
| 4771 router->touch_target_, rwhv_child); | |
| 4772 EXPECT_EQ(2LU, router->gesture_target_queue_.size()); | |
| 4773 EXPECT_EQ(nullptr, router->gesture_target_); | |
| 4774 | |
| 4775 // Send another touch sequence to main frame. | |
| 4776 SendTouchTapWithExpectedTarget(rwhv_parent, main_frame_point, | |
| 4777 router->touch_target_, rwhv_parent); | |
| 4778 EXPECT_EQ(3LU, router->gesture_target_queue_.size()); | |
| 4779 EXPECT_EQ(nullptr, router->gesture_target_); | |
| 4780 | |
| 4781 // Send Gestures to clear GestureTargetQueue. | |
| 4782 | |
| 4783 // The first touch sequence should generate a GestureTapDown, sent to the | |
| 4784 // main frame. | |
| 4785 SendGestureTapSequenceWithExpectedTarget(rwhv_parent, main_frame_point, | |
| 4786 router->gesture_target_, nullptr, | |
| 4787 rwhv_parent); | |
| 4788 EXPECT_EQ(2LU, router->gesture_target_queue_.size()); | |
| 4789 // Note: rwhv_parent is the target used for GestureFlingCancel sent by | |
| 4790 // RenderWidgetHostViewAura::OnGestureEvent() at the start of the next gesture | |
| 4791 // sequence; the sequence itself goes to rwhv_child. | |
| 4792 EXPECT_EQ(rwhv_parent, router->gesture_target_); | |
| 4793 | |
| 4794 // The second touch sequence should generate a GestureTapDown, sent to the | |
| 4795 // child frame. | |
| 4796 SendGestureTapSequenceWithExpectedTarget(rwhv_parent, child_center, | |
| 4797 router->gesture_target_, rwhv_parent, | |
| 4798 rwhv_child); | |
| 4799 EXPECT_EQ(1LU, router->gesture_target_queue_.size()); | |
| 4800 EXPECT_EQ(rwhv_child, router->gesture_target_); | |
| 4801 | |
| 4802 // The third touch sequence should generate a GestureTapDown, sent to the | |
| 4803 // main frame. | |
| 4804 SendGestureTapSequenceWithExpectedTarget(rwhv_parent, main_frame_point, | |
| 4805 router->gesture_target_, rwhv_child, | |
| 4806 rwhv_parent); | |
| 4807 EXPECT_EQ(0LU, router->gesture_target_queue_.size()); | |
| 4808 EXPECT_EQ(rwhv_parent, router->gesture_target_); | |
| 4809 } | |
| 4577 #endif // defined(USE_AURA) | 4810 #endif // defined(USE_AURA) | 
| 4578 | 4811 | 
| 4579 // Ensure that a cross-process subframe can receive keyboard events when in | 4812 // Ensure that a cross-process subframe can receive keyboard events when in | 
| 4580 // focus. | 4813 // focus. | 
| 4581 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, | 4814 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, | 
| 4582 SubframeKeyboardEventRouting) { | 4815 SubframeKeyboardEventRouting) { | 
| 4583 GURL main_url(embedded_test_server()->GetURL( | 4816 GURL main_url(embedded_test_server()->GetURL( | 
| 4584 "a.com", "/frame_tree/page_with_one_frame.html")); | 4817 "a.com", "/frame_tree/page_with_one_frame.html")); | 
| 4585 EXPECT_TRUE(NavigateToURL(shell(), main_url)); | 4818 EXPECT_TRUE(NavigateToURL(shell(), main_url)); | 
| 4586 | 4819 | 
| (...skipping 907 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5494 | 5727 | 
| 5495 // Force the renderer to generate a new frame. | 5728 // Force the renderer to generate a new frame. | 
| 5496 EXPECT_TRUE(ExecuteScript(shell()->web_contents(), | 5729 EXPECT_TRUE(ExecuteScript(shell()->web_contents(), | 
| 5497 "document.body.style.background = 'black'")); | 5730 "document.body.style.background = 'black'")); | 
| 5498 | 5731 | 
| 5499 // Waits for the next frame. | 5732 // Waits for the next frame. | 
| 5500 observer->Wait(); | 5733 observer->Wait(); | 
| 5501 } | 5734 } | 
| 5502 | 5735 | 
| 5503 } // namespace content | 5736 } // namespace content | 
| OLD | NEW |