diff options
author | kenrb <kenrb@chromium.org> | 2016-03-01 10:53:24 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-01 18:55:41 +0000 |
commit | 9d8b8320a54fc65539d99be0e2a489e2e2b1b7bc (patch) | |
tree | 52a3c40c73b9c2fcb91cf4dca8940520b5faba49 | |
parent | 64484f863976b3cffc84201e8a396d1fa018cba1 (diff) | |
download | chromium_src-9d8b8320a54fc65539d99be0e2a489e2e2b1b7bc.zip chromium_src-9d8b8320a54fc65539d99be0e2a489e2e2b1b7bc.tar.gz chromium_src-9d8b8320a54fc65539d99be0e2a489e2e2b1b7bc.tar.bz2 |
Make browser hit testing return correct SurfaceId with nested Surfaces
A regression caused SurfaceHittest::GetTargetSurfaceAtPoint() to return
the incorrect SurfaceId when the correct Surface was nested more than
one layer from the root Surface. This fixes the regression.
BUG=589572
CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel
Review URL: https://codereview.chromium.org/1743303002
Cr-Commit-Position: refs/heads/master@{#378495}
-rw-r--r-- | cc/surfaces/surface_hittest.cc | 10 | ||||
-rw-r--r-- | content/browser/site_per_process_browsertest.cc | 76 | ||||
-rw-r--r-- | content/test/content_browser_test_utils_internal.cc | 16 | ||||
-rw-r--r-- | content/test/content_browser_test_utils_internal.h | 2 | ||||
-rw-r--r-- | content/test/data/frame_tree/page_with_positioned_nested_frames.html | 16 |
5 files changed, 109 insertions, 11 deletions
diff --git a/cc/surfaces/surface_hittest.cc b/cc/surfaces/surface_hittest.cc index 6db66e2..b9be19e 100644 --- a/cc/surfaces/surface_hittest.cc +++ b/cc/surfaces/surface_hittest.cc @@ -104,9 +104,13 @@ bool SurfaceHittest::GetTargetSurfaceAtPointInternal( gfx::Transform transform_to_child_space; if (GetTargetSurfaceAtPointInternal( surface_quad->surface_id, RenderPassId(), point_in_quad_space, - referenced_passes, out_surface_id, &transform_to_child_space) || - (delegate_ && - delegate_->AcceptHitTarget(surface_quad, point_in_quad_space))) { + referenced_passes, out_surface_id, &transform_to_child_space)) { + *out_transform = transform_to_child_space * target_to_quad_transform * + transform_from_root_target; + return true; + } else if (delegate_ && + delegate_->AcceptHitTarget(surface_quad, + point_in_quad_space)) { *out_surface_id = surface_quad->surface_id; *out_transform = transform_to_child_space * target_to_quad_transform * transform_from_root_target; diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index c91e6b1..24fb1e9 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc @@ -740,6 +740,82 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessHighDPIBrowserTest, SurfaceHitTestTestHelper(shell(), embedded_test_server()); } +// Test that mouse events are being routed to the correct RenderWidgetHostView +// when there are nested out-of-process iframes. +#if defined(OS_ANDROID) +// Browser process hit testing is not implemented on Android. +// https://crbug.com/491334 +#define MAYBE_NestedSurfaceHitTestTest DISABLED_NestedSurfaceHitTestTest +#else +#define MAYBE_NestedSurfaceHitTestTest NestedSurfaceHitTestTest +#endif +IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, + MAYBE_NestedSurfaceHitTestTest) { + GURL main_url(embedded_test_server()->GetURL( + "/frame_tree/page_with_positioned_nested_frames.html")); + NavigateToURL(shell(), main_url); + + // It is safe to obtain the root frame tree node here, as it doesn't change. + FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) + ->GetFrameTree() + ->root(); + ASSERT_EQ(1U, root->child_count()); + + FrameTreeNode* parent_iframe_node = root->child_at(0); + GURL site_url(embedded_test_server()->GetURL( + "a.com", "/frame_tree/page_with_positioned_frame.html")); + EXPECT_EQ(site_url, parent_iframe_node->current_url()); + EXPECT_NE(shell()->web_contents()->GetSiteInstance(), + parent_iframe_node->current_frame_host()->GetSiteInstance()); + + FrameTreeNode* nested_iframe_node = parent_iframe_node->child_at(0); + GURL nested_site_url( + embedded_test_server()->GetURL("baz.com", "/title1.html")); + EXPECT_EQ(nested_site_url, nested_iframe_node->current_url()); + EXPECT_NE(shell()->web_contents()->GetSiteInstance(), + nested_iframe_node->current_frame_host()->GetSiteInstance()); + EXPECT_NE(parent_iframe_node->current_frame_host()->GetSiteInstance(), + nested_iframe_node->current_frame_host()->GetSiteInstance()); + + // Create listeners for mouse events. + RenderWidgetHostMouseEventMonitor main_frame_monitor( + root->current_frame_host()->GetRenderWidgetHost()); + RenderWidgetHostMouseEventMonitor nested_frame_monitor( + nested_iframe_node->current_frame_host()->GetRenderWidgetHost()); + + RenderWidgetHostInputEventRouter* router = + static_cast<WebContentsImpl*>(shell()->web_contents()) + ->GetInputEventRouter(); + + RenderWidgetHostViewBase* root_view = static_cast<RenderWidgetHostViewBase*>( + root->current_frame_host()->GetRenderWidgetHost()->GetView()); + RenderWidgetHostViewBase* rwhv_nested = + static_cast<RenderWidgetHostViewBase*>( + nested_iframe_node->current_frame_host() + ->GetRenderWidgetHost() + ->GetView()); + + SurfaceHitTestReadyNotifier notifier( + static_cast<RenderWidgetHostViewChildFrame*>(rwhv_nested)); + notifier.WaitForSurfaceReady(); + + // Target input event to nested frame. + blink::WebMouseEvent nested_event; + nested_event.type = blink::WebInputEvent::MouseDown; + nested_event.button = blink::WebPointerProperties::ButtonLeft; + nested_event.x = 125; + nested_event.y = 125; + nested_event.clickCount = 1; + nested_frame_monitor.ResetEventReceived(); + main_frame_monitor.ResetEventReceived(); + router->RouteMouseEvent(root_view, &nested_event); + + EXPECT_TRUE(nested_frame_monitor.EventWasReceived()); + EXPECT_EQ(21, nested_frame_monitor.event().x); + EXPECT_EQ(21, nested_frame_monitor.event().y); + EXPECT_FALSE(main_frame_monitor.EventWasReceived()); +} + // This test tests that browser process hittesting ignores frames with // pointer-events: none. #if defined(OS_ANDROID) diff --git a/content/test/content_browser_test_utils_internal.cc b/content/test/content_browser_test_utils_internal.cc index af3d347..dad702c 100644 --- a/content/test/content_browser_test_utils_internal.cc +++ b/content/test/content_browser_test_utils_internal.cc @@ -281,7 +281,7 @@ void SurfaceHitTestReadyNotifier::WaitForSurfaceReady() { root_surface_id_ = target_view_->FrameConnectorForTesting() ->GetRootRenderWidgetHostViewForTesting() ->SurfaceIdForTesting(); - if (ContainsSurfaceId()) + if (ContainsSurfaceId(root_surface_id_)) return; while (true) { @@ -294,17 +294,19 @@ void SurfaceHitTestReadyNotifier::WaitForSurfaceReady() { base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout()); run_loop.Run(); - if (ContainsSurfaceId()) + if (ContainsSurfaceId(root_surface_id_)) break; } } -bool SurfaceHitTestReadyNotifier::ContainsSurfaceId() { - if (root_surface_id_.is_null()) +bool SurfaceHitTestReadyNotifier::ContainsSurfaceId( + cc::SurfaceId container_surface_id) { + if (container_surface_id.is_null()) return false; - for (cc::SurfaceId id : surface_manager_->GetSurfaceForId(root_surface_id_) - ->referenced_surfaces()) { - if (id == target_view_->SurfaceIdForTesting()) + for (cc::SurfaceId id : + surface_manager_->GetSurfaceForId(container_surface_id) + ->referenced_surfaces()) { + if (id == target_view_->SurfaceIdForTesting() || ContainsSurfaceId(id)) return true; } return false; diff --git a/content/test/content_browser_test_utils_internal.h b/content/test/content_browser_test_utils_internal.h index 12e7f84..f4a4dde 100644 --- a/content/test/content_browser_test_utils_internal.h +++ b/content/test/content_browser_test_utils_internal.h @@ -115,7 +115,7 @@ class SurfaceHitTestReadyNotifier { void WaitForSurfaceReady(); private: - bool ContainsSurfaceId(); + bool ContainsSurfaceId(cc::SurfaceId container_surface_id); cc::SurfaceManager* surface_manager_; cc::SurfaceId root_surface_id_; diff --git a/content/test/data/frame_tree/page_with_positioned_nested_frames.html b/content/test/data/frame_tree/page_with_positioned_nested_frames.html new file mode 100644 index 0000000..3d472a5 --- /dev/null +++ b/content/test/data/frame_tree/page_with_positioned_nested_frames.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<style> +iframe { + position:absolute; + top: 50px; + left: 50px; + width: 200px; + height: 200px; +} +</style> +<html> +<body> +<iframe src="/cross-site/a.com/frame_tree/page_with_positioned_frame.html"></iframe> +This page contains a nested and positioned cross-origin frames. +</body> +</html>
\ No newline at end of file |