Commit c5fece63 authored by Navid Zolghadr's avatar Navid Zolghadr Committed by Commit Bot

Use async targeting to find drag and drop targets

Add callback supports to the RenderWidgetTargeter
and use the async targeting in drag and drop code
and register a callback to send drag events using
the callback. Note that since drag and drop events
aren't WebInputEvent it is not possible to use
FindTargetAndDispatch function of RenderWidgetTargeter
at this time.

This is exactly the same as the CL before:
https://chromium-review.googlesource.com/c/chromium/src/+/1641383
but rebased on top of another change that moves the
drop operations to take ownership of the OSExchangeData:
https://chromium-review.googlesource.com/c/chromium/src/+/1666910

TBR=sadrul@chromium.org

Bug: 804633, 967801
Change-Id: If4f53e880bb805c87d13869348a57cd857adee5a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1693442Reviewed-by: default avatarNavid Zolghadr <nzolghadr@chromium.org>
Commit-Queue: Navid Zolghadr <nzolghadr@chromium.org>
Auto-Submit: Navid Zolghadr <nzolghadr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#678475}
parent 4fc9d002
...@@ -1389,6 +1389,13 @@ RenderWidgetHostInputEventRouter::GetRenderWidgetHostAtPoint( ...@@ -1389,6 +1389,13 @@ RenderWidgetHostInputEventRouter::GetRenderWidgetHostAtPoint(
.view->GetRenderWidgetHost()); .view->GetRenderWidgetHost());
} }
void RenderWidgetHostInputEventRouter::GetRenderWidgetHostAtPointAsynchronously(
RenderWidgetHostViewBase* root_view,
const gfx::PointF& point,
RenderWidgetTargeter::RenderWidgetHostAtPointCallback callback) {
event_targeter_->FindTargetAndCallback(root_view, point, std::move(callback));
}
RenderWidgetTargetResult RenderWidgetTargetResult
RenderWidgetHostInputEventRouter::FindTouchscreenGestureEventTarget( RenderWidgetHostInputEventRouter::FindTouchscreenGestureEventTarget(
RenderWidgetHostViewBase* root_view, RenderWidgetHostViewBase* root_view,
...@@ -1761,6 +1768,16 @@ RenderWidgetHostInputEventRouter::GetRenderWidgetTargeterForTests() { ...@@ -1761,6 +1768,16 @@ RenderWidgetHostInputEventRouter::GetRenderWidgetTargeterForTests() {
return event_targeter_.get(); return event_targeter_.get();
} }
RenderWidgetTargetResult
RenderWidgetHostInputEventRouter::FindTargetSynchronouslyAtPoint(
RenderWidgetHostViewBase* root_view,
const gfx::PointF& location) {
gfx::PointF transformed_pt;
// The transformed point is already in the return value of FindViewAtLocation.
return FindViewAtLocation(root_view, location, viz::EventSource::MOUSE,
&transformed_pt);
}
RenderWidgetTargetResult RenderWidgetTargetResult
RenderWidgetHostInputEventRouter::FindTargetSynchronously( RenderWidgetHostInputEventRouter::FindTargetSynchronously(
RenderWidgetHostViewBase* root_view, RenderWidgetHostViewBase* root_view,
......
...@@ -132,6 +132,17 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter ...@@ -132,6 +132,17 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
const gfx::PointF& point, const gfx::PointF& point,
gfx::PointF* transformed_point); gfx::PointF* transformed_point);
// Finds the RenderWidgetHostImpl inside the |root_view| at |point| where
// |point| is with respect to |root_view|'s coordinates. If a RWHI is found,
// it is passed along with the coordinate of the point with
// respect to the RWHI's coordinates to the callback function. If
// |root_view| is nullptr or RWHI is not found, the callback is called with
// nullptr and no location.
void GetRenderWidgetHostAtPointAsynchronously(
RenderWidgetHostViewBase* root_view,
const gfx::PointF& point,
RenderWidgetTargeter::RenderWidgetHostAtPointCallback callback);
// RenderWidgetTargeter::Delegate: // RenderWidgetTargeter::Delegate:
RenderWidgetHostViewBase* FindViewFromFrameSinkId( RenderWidgetHostViewBase* FindViewFromFrameSinkId(
const viz::FrameSinkId& frame_sink_id) const override; const viz::FrameSinkId& frame_sink_id) const override;
...@@ -293,6 +304,10 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter ...@@ -293,6 +304,10 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
const RenderWidgetHostViewBase* view); const RenderWidgetHostViewBase* view);
// RenderWidgetTargeter::Delegate: // RenderWidgetTargeter::Delegate:
RenderWidgetTargetResult FindTargetSynchronouslyAtPoint(
RenderWidgetHostViewBase* root_view,
const gfx::PointF& location) override;
RenderWidgetTargetResult FindTargetSynchronously( RenderWidgetTargetResult FindTargetSynchronously(
RenderWidgetHostViewBase* root_view, RenderWidgetHostViewBase* root_view,
const blink::WebInputEvent& event) override; const blink::WebInputEvent& event) override;
......
...@@ -73,6 +73,7 @@ class CONTENT_EXPORT WebContentsViewAura ...@@ -73,6 +73,7 @@ class CONTENT_EXPORT WebContentsViewAura
FRIEND_TEST_ALL_PREFIXES(WebContentsViewAuraTest, FRIEND_TEST_ALL_PREFIXES(WebContentsViewAuraTest,
DragDropVirtualFilesOriginateFromRenderer); DragDropVirtualFilesOriginateFromRenderer);
FRIEND_TEST_ALL_PREFIXES(WebContentsViewAuraTest, DragDropUrlData); FRIEND_TEST_ALL_PREFIXES(WebContentsViewAuraTest, DragDropUrlData);
FRIEND_TEST_ALL_PREFIXES(WebContentsViewAuraTest, DragDropOnOopif);
class WindowObserver; class WindowObserver;
...@@ -193,6 +194,18 @@ class CONTENT_EXPORT WebContentsViewAura ...@@ -193,6 +194,18 @@ class CONTENT_EXPORT WebContentsViewAura
void OnDragExited() override; void OnDragExited() override;
int OnPerformDrop(const ui::DropTargetEvent& event, int OnPerformDrop(const ui::DropTargetEvent& event,
std::unique_ptr<ui::OSExchangeData> data) override; std::unique_ptr<ui::OSExchangeData> data) override;
void DragEnteredCallback(ui::DropTargetEvent event,
std::unique_ptr<DropData> drop_data,
base::WeakPtr<RenderWidgetHostViewBase> target,
base::Optional<gfx::PointF> transformed_pt);
void DragUpdatedCallback(ui::DropTargetEvent event,
std::unique_ptr<DropData> drop_data,
base::WeakPtr<RenderWidgetHostViewBase> target,
base::Optional<gfx::PointF> transformed_pt);
void PerformDropCallback(ui::DropTargetEvent event,
std::unique_ptr<ui::OSExchangeData> data,
base::WeakPtr<RenderWidgetHostViewBase> target,
base::Optional<gfx::PointF> transformed_pt);
// Completes a drop operation by communicating the drop data to the renderer // Completes a drop operation by communicating the drop data to the renderer
// process. // process.
...@@ -269,13 +282,16 @@ class CONTENT_EXPORT WebContentsViewAura ...@@ -269,13 +282,16 @@ class CONTENT_EXPORT WebContentsViewAura
// Responsible for handling gesture-nav and pull-to-refresh UI. // Responsible for handling gesture-nav and pull-to-refresh UI.
std::unique_ptr<GestureNavSimple> gesture_nav_simple_; std::unique_ptr<GestureNavSimple> gesture_nav_simple_;
// This is true when the drag is in process from the perspective of this
// class. It means it gets true when drag enters and gets reset when either
// drop happens or drag exits.
bool drag_in_progress_;
bool init_rwhv_with_null_parent_for_testing_; bool init_rwhv_with_null_parent_for_testing_;
#if defined(OS_WIN) // Used to ensure the drag and drop callbacks bound to this
// Used to ensure that the virtual files retrieval callback bound to this // object are canceled when this object is destroyed.
// object is canceled when this object is destroyed.
base::WeakPtrFactory<WebContentsViewAura> weak_ptr_factory_{this}; base::WeakPtrFactory<WebContentsViewAura> weak_ptr_factory_{this};
#endif
DISALLOW_COPY_AND_ASSIGN(WebContentsViewAura); DISALLOW_COPY_AND_ASSIGN(WebContentsViewAura);
}; };
......
...@@ -41,9 +41,12 @@ ...@@ -41,9 +41,12 @@
#include "content/public/test/test_renderer_host.h" #include "content/public/test/test_renderer_host.h"
#include "content/public/test/test_utils.h" #include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h" #include "content/shell/browser/shell.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/embedded_test_server.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h" #include "ui/aura/window_tree_host.h"
#include "ui/base/dragdrop/drop_target_event.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/events/base_event_utils.h" #include "ui/events/base_event_utils.h"
#include "ui/events/event_sink.h" #include "ui/events/event_sink.h"
...@@ -87,11 +90,28 @@ class WebContentsViewAuraTest : public ContentBrowserTest { ...@@ -87,11 +90,28 @@ class WebContentsViewAuraTest : public ContentBrowserTest {
shell()->web_contents()); shell()->web_contents());
} }
void SetUpOnMainThread() override {
// Setup the server to allow serving separate sites, so we can perform
// cross-process navigation.
host_resolver()->AddRule("*", "127.0.0.1");
}
void SetUpCommandLine(base::CommandLine* cmd) override { void SetUpCommandLine(base::CommandLine* cmd) override {
cmd->AppendSwitchASCII(switches::kTouchEventFeatureDetection, cmd->AppendSwitchASCII(switches::kTouchEventFeatureDetection,
switches::kTouchEventFeatureDetectionEnabled); switches::kTouchEventFeatureDetectionEnabled);
} }
void OnDropComplete(RenderWidgetHostImpl* target_rwh,
const DropData& drop_data,
const gfx::PointF& client_pt,
const gfx::PointF& screen_pt,
int key_modifiers,
bool drop_allowed) {
// Cache the data for verification.
drop_target_widget_ = target_rwh;
std::move(async_drop_closure_).Run();
}
void TestOverscrollNavigation(bool touch_handler) { void TestOverscrollNavigation(bool touch_handler) {
ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/overscroll_navigation.html")); ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/overscroll_navigation.html"));
WebContentsImpl* web_contents = WebContentsImpl* web_contents =
...@@ -231,6 +251,11 @@ class WebContentsViewAuraTest : public ContentBrowserTest { ...@@ -231,6 +251,11 @@ class WebContentsViewAuraTest : public ContentBrowserTest {
ContentBrowserTest::PostRunTestOnMainThread(); ContentBrowserTest::PostRunTestOnMainThread();
} }
RenderWidgetHostImpl* drop_target_widget_;
// A closure indicating that async drop operation has completed.
base::OnceClosure async_drop_closure_;
private: private:
std::unique_ptr<RenderFrameSubmissionObserver> frame_observer_; std::unique_ptr<RenderFrameSubmissionObserver> frame_observer_;
...@@ -487,6 +512,73 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, ...@@ -487,6 +512,73 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
window->AddChild(shell()->web_contents()->GetContentNativeView()); window->AddChild(shell()->web_contents()->GetContentNativeView());
} }
IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, DragDropOnOopif) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url = embedded_test_server()->GetURL(
"a.com", "/overlapping_cross_site_iframe.html");
EXPECT_TRUE(NavigateToURL(shell(), url));
WebContentsImpl* contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
WebContentsViewAura* view =
static_cast<WebContentsViewAura*>(contents->GetView());
// Drop on the root frame.
{
std::unique_ptr<ui::OSExchangeData> data =
std::make_unique<ui::OSExchangeData>();
view->RegisterDropCallbackForTesting(base::BindOnce(
&WebContentsViewAuraTest::OnDropComplete, base::Unretained(this)));
base::RunLoop run_loop;
async_drop_closure_ = run_loop.QuitClosure();
gfx::PointF point = {10, 10};
ui::DropTargetEvent event(*data.get(), point, point,
ui::DragDropTypes::DRAG_COPY);
view->OnDragEntered(event);
view->OnPerformDrop(event, std::move(data));
run_loop.Run();
EXPECT_EQ(drop_target_widget_,
RenderWidgetHostImpl::From(contents->GetFrameTree()
->root()
->current_frame_host()
->GetRenderWidgetHost()));
}
// Drop on the element in the root frame overlapping the embedded OOPIF.
{
std::unique_ptr<ui::OSExchangeData> data =
std::make_unique<ui::OSExchangeData>();
view->RegisterDropCallbackForTesting(base::BindOnce(
&WebContentsViewAuraTest::OnDropComplete, base::Unretained(this)));
base::RunLoop run_loop;
async_drop_closure_ = run_loop.QuitClosure();
int left =
EvalJs(contents,
"document.getElementById('target').getBoundingClientRect().left")
.ExtractInt();
int top =
EvalJs(contents,
"document.getElementById('target').getBoundingClientRect().top")
.ExtractInt();
gfx::PointF point = {left + 5, top + 5};
ui::DropTargetEvent event(*data.get(), point, point,
ui::DragDropTypes::DRAG_COPY);
view->OnDragEntered(event);
view->OnPerformDrop(event, std::move(data));
run_loop.Run();
EXPECT_EQ(drop_target_widget_,
RenderWidgetHostImpl::From(contents->GetFrameTree()
->root()
->current_frame_host()
->GetRenderWidgetHost()));
}
}
IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, ContentWindowClose) { IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, ContentWindowClose) {
ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/overscroll_navigation.html")); ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/overscroll_navigation.html"));
......
<html>
<title>Overlapping cross site iframe</title>
This is the main body content.
<iframe id="iframe" style="width:300px; height:300px; position:absolute; left:100px; top:100px"></iframe>
<div id="target" style="background-color: yellow; position: absolute; top: 120px; left: 120px; width: 100px; height: 100px"></div>
<script>
var url = window.location.protocol + '//b.com';
if (window.location.port)
url += ':' + window.location.port;
url += "/cross_site_iframe_factory.html?b()";
document.getElementById('iframe').src = url;
</script>
</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