summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkenrb <kenrb@chromium.org>2016-03-01 10:53:24 -0800
committerCommit bot <commit-bot@chromium.org>2016-03-01 18:55:41 +0000
commit9d8b8320a54fc65539d99be0e2a489e2e2b1b7bc (patch)
tree52a3c40c73b9c2fcb91cf4dca8940520b5faba49
parent64484f863976b3cffc84201e8a396d1fa018cba1 (diff)
downloadchromium_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.cc10
-rw-r--r--content/browser/site_per_process_browsertest.cc76
-rw-r--r--content/test/content_browser_test_utils_internal.cc16
-rw-r--r--content/test/content_browser_test_utils_internal.h2
-rw-r--r--content/test/data/frame_tree/page_with_positioned_nested_frames.html16
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