Commit 295cfd68 authored by Kevin McNee's avatar Kevin McNee Committed by Commit Bot

Ignore portals for async hit testing.

If an async hit test results in a renderer hitting a remote frame,
ignore it if input events should not be routed to that frame, as is the
case with portals.

Bug: 932581
Change-Id: I610442ac56383257dc02d6b3f0f0e2bea1f0fbb0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1553914Reviewed-by: default avatarLucas Gadani <lfg@chromium.org>
Reviewed-by: default avatarAlex Moshchuk <alexmos@chromium.org>
Commit-Queue: Kevin McNee <mcnee@chromium.org>
Cr-Commit-Position: refs/heads/master@{#648704}
parent 89f8c0d0
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/callback.h" #include "base/callback.h"
#include "base/test/bind_test_util.h"
#include "base/test/scoped_feature_list.h" #include "base/test/scoped_feature_list.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "content/browser/frame_host/render_frame_host_impl.h" #include "content/browser/frame_host/render_frame_host_impl.h"
...@@ -426,4 +427,59 @@ IN_PROC_BROWSER_TEST_F(PortalBrowserTest, DispatchInputEvent) { ...@@ -426,4 +427,59 @@ IN_PROC_BROWSER_TEST_F(PortalBrowserTest, DispatchInputEvent) {
EXPECT_EQ(false, EvalJs(portal_frame, "clicked")); EXPECT_EQ(false, EvalJs(portal_frame, "clicked"));
} }
// Tests that async hit testing does not target portals.
IN_PROC_BROWSER_TEST_F(PortalBrowserTest, AsyncEventTargetingIgnoresPortals) {
EXPECT_TRUE(NavigateToURL(
shell(), embedded_test_server()->GetURL("portal.test", "/title1.html")));
WebContentsImpl* web_contents_impl =
static_cast<WebContentsImpl*>(shell()->web_contents());
RenderFrameHostImpl* main_frame = web_contents_impl->GetMainFrame();
// Create portal and wait for navigation.
PortalCreatedObserver portal_created_observer(main_frame);
GURL a_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
EXPECT_TRUE(ExecJs(main_frame,
JsReplace("var portal = document.createElement('portal');"
"portal.src = $1;"
"document.body.appendChild(portal);",
a_url)));
Portal* portal = portal_created_observer.WaitUntilPortalCreated();
WebContentsImpl* portal_contents = portal->GetPortalContents();
RenderFrameHostImpl* portal_frame = portal_contents->GetMainFrame();
ASSERT_TRUE(static_cast<RenderWidgetHostViewBase*>(portal_frame->GetView())
->IsRenderWidgetHostViewChildFrame());
RenderWidgetHostViewChildFrame* portal_view =
static_cast<RenderWidgetHostViewChildFrame*>(portal_frame->GetView());
TestNavigationObserver navigation_observer(portal_contents);
navigation_observer.Wait();
WaitForHitTestDataOrChildSurfaceReady(portal_frame);
viz::mojom::InputTargetClient* target_client =
main_frame->GetRenderWidgetHost()->input_target_client();
ASSERT_TRUE(target_client);
gfx::PointF root_location =
portal_view->TransformPointToRootCoordSpaceF(gfx::PointF(5, 5));
// Query the renderer for the target widget. The root should claim the point
// for itself, not the portal.
base::RunLoop run_loop;
base::OnceClosure quit_closure = run_loop.QuitClosure();
viz::FrameSinkId received_frame_sink_id;
target_client->FrameSinkIdAt(
root_location, 0,
base::BindLambdaForTesting(
[&](const viz::FrameSinkId& id, const gfx::PointF& point) {
received_frame_sink_id = id;
std::move(quit_closure).Run();
}));
run_loop.Run();
viz::FrameSinkId root_frame_sink_id =
static_cast<RenderWidgetHostViewBase*>(main_frame->GetView())
->GetFrameSinkId();
EXPECT_EQ(root_frame_sink_id, received_frame_sink_id)
<< "Note: The portal's FrameSinkId is " << portal_view->GetFrameSinkId();
}
} // namespace content } // namespace content
...@@ -192,8 +192,11 @@ blink::WebCoalescedInputEvent GetCoalescedWebPointerEventForTouch( ...@@ -192,8 +192,11 @@ blink::WebCoalescedInputEvent GetCoalescedWebPointerEventForTouch(
viz::FrameSinkId GetRemoteFrameSinkId(const blink::WebNode& node) { viz::FrameSinkId GetRemoteFrameSinkId(const blink::WebNode& node) {
blink::WebFrame* result_frame = blink::WebFrame::FromFrameOwnerElement(node); blink::WebFrame* result_frame = blink::WebFrame::FromFrameOwnerElement(node);
if (result_frame && result_frame->IsWebRemoteFrame()) { if (result_frame && result_frame->IsWebRemoteFrame()) {
return RenderFrameProxy::FromWebFrame(result_frame->ToWebRemoteFrame()) blink::WebRemoteFrame* remote_frame = result_frame->ToWebRemoteFrame();
->frame_sink_id(); if (remote_frame->IsIgnoredForHitTest())
return viz::FrameSinkId();
return RenderFrameProxy::FromWebFrame(remote_frame)->frame_sink_id();
} }
auto* plugin = BrowserPlugin::GetFromNode(node); auto* plugin = BrowserPlugin::GetFromNode(node);
return plugin ? plugin->frame_sink_id() : viz::FrameSinkId(); return plugin ? plugin->frame_sink_id() : viz::FrameSinkId();
......
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