Commit f009bbf9 authored by Xianda Sun's avatar Xianda Sun Committed by Commit Bot

Do async event targeting when mid-level iframes have ask flag

We used to only look at the eventual target iframe's hit test flag to
determine whether we need async event targeting. This is fine with v1
set up because all non-trivial iframes have kHitTestAsk flag. But this
resulted in a bug in v2 in this situation:

When we have nested main_frame->parent_frame->child_frame and only the
mid-level parent_frame has kHitTestAsk flag, we will directly dispatch
event to child_frame. This is not correct because parent_frame may have
overlapping regions with main_frame divs. This patch makes RWHIER always
ask when it encouters a mid-level kHitTestAsk flag.

Bug: 896786
Change-Id: Ib9c81ad44d562b251515d8f4dcde572db8d1fa1d
Reviewed-on: https://chromium-review.googlesource.com/c/1310114Reviewed-by: default avatarKen Buchanan <kenrb@chromium.org>
Reviewed-by: default avatarRia Jiang <riajiang@chromium.org>
Commit-Queue: Xianda Sun <sunxd@chromium.org>
Cr-Commit-Position: refs/heads/master@{#606145}
parent d60f16ec
......@@ -193,6 +193,14 @@ bool HitTestQuery::FindTargetInRegionForLocation(
gfx::PointF location_in_target =
location_transformed -
hit_test_data_[region_index].rect.OffsetFromOrigin();
if (hit_test_data_[region_index].flags & HitTestRegionFlags::kHitTestAsk) {
target->frame_sink_id = hit_test_data_[region_index].frame_sink_id;
target->location_in_target = location_in_target;
target->flags = hit_test_data_[region_index].flags;
return true;
}
while (child_region < child_region_end) {
if (FindTargetInRegionForLocation(event_source, location_in_target,
child_region, target)) {
......
......@@ -2360,6 +2360,57 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
kHitTestTolerance);
}
// This test tests that browser process can successfully hit test on nested
// OOPIFs that are partially occluded by main frame elements.
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
HitTestNestedOccludedOOPIF) {
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_nested_frames_and_occluding_div.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
auto* web_contents = static_cast<WebContentsImpl*>(shell()->web_contents());
// 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* parent = root->child_at(0);
GURL site_url(embedded_test_server()->GetURL(
"bar.com", "/frame_tree/page_with_positioned_frame.html"));
EXPECT_EQ(site_url, parent->current_url());
EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
parent->current_frame_host()->GetSiteInstance());
ASSERT_EQ(1U, parent->child_count());
FrameTreeNode* child = parent->child_at(0);
GURL child_site_url(
embedded_test_server()->GetURL("baz.com", "/title1.html"));
EXPECT_EQ(child_site_url, child->current_url());
RenderWidgetHostViewBase* root_view = static_cast<RenderWidgetHostViewBase*>(
root->current_frame_host()->GetRenderWidgetHost()->GetView());
RenderWidgetHostViewBase* child_view = static_cast<RenderWidgetHostViewBase*>(
child->current_frame_host()->GetRenderWidgetHost()->GetView());
WaitForHitTestDataOrChildSurfaceReady(child->current_frame_host());
// Target input event to the overlapping region of main frame's div and child
// frame.
DispatchMouseEventAndWaitUntilDispatch(web_contents, root_view,
gfx::PointF(75, 75), root_view,
gfx::PointF(75, 75));
// Target input event to the non overlapping region of child frame.
// The div has a bound of (0, 0, 100, 100) with a border-radius of 5px, so
// point (99, 99) should not hit test the div but reach the nested child
// frame.
// The parent frame and child frame both have a default offset of (2, 2) and
// child frame's top and left properties are set to be (50, 50), so there is
// an offset of (54, 54) in total.
DispatchMouseEventAndWaitUntilDispatch(web_contents, root_view,
gfx::PointF(99, 99), child_view,
gfx::PointF(45, 45));
}
// Verify that an event is properly retargeted to the main frame when an
// asynchronous hit test to the child frame times out.
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
......
<!DOCTYPE html>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
iframe {
position:absolute;
top: 0px;
left: 0px;
width: 200px;
height: 200px;
}
div {
border-radius: 10px;
position: absolute;
top: 0px;
left: 0px;
width: 100px;
height: 100px;
background: blue;
}
</style>
<html>
<body>
<iframe src="/cross-site/bar.com/frame_tree/page_with_positioned_frame.html"></iframe>
<div></div>
</body>
</html>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment