diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.cc b/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.cc index d341b84886578..9a8d63a4eb8d7 100644 --- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.cc +++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.cc @@ -38,6 +38,11 @@ using ::ui::mojom::DragOperation; // the global XdndSelection mid-drag. Mirrors desktop_drag_drop_client_win.cc. bool g_is_dragging = false; +// Set by DesktopWindowTreeHostPlatform::RunMoveLoop. The window-move (tab-drag) +// path enters X11WholeScreenMoveLoop::RunMoveLoop without going through +// StartDragAndDrop, so g_is_dragging alone does not cover it. +bool g_window_move_in_progress = false; + // The minimum alpha required so we would treat the pixel as visible. constexpr uint32_t kMinAlpha = 32; @@ -133,6 +138,12 @@ DesktopDragDropClientOzone::DesktopDragDropClientOzone( ui::WmDragHandler* drag_handler) : root_window_(root_window), drag_handler_(drag_handler) {} +// static +base::AutoReset +DesktopDragDropClientOzone::ScopedSuppressForWindowMove() { + return base::AutoReset(&g_window_move_in_progress, true); +} + DesktopDragDropClientOzone::~DesktopDragDropClientOzone() { ResetDragDropTarget(); observers_.Notify( @@ -152,7 +163,7 @@ DragOperation DesktopDragDropClientOzone::StartDragAndDrop( // A renderer can send LocalFrameHost::StartDragging at any time, so reject // (rather than CHECK) re-entrant drags from a second top-level window. - if (g_is_dragging) { + if (g_is_dragging || g_window_move_in_progress) { return DragOperation::kNone; } base::AutoReset drag_scoper(&g_is_dragging, true); diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h b/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h index 5a14b467d43a6..b46de97a92f8f 100644 --- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h +++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h @@ -7,6 +7,7 @@ #include +#include "base/auto_reset.h" #include "base/functional/callback.h" #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" @@ -50,6 +51,11 @@ class VIEWS_EXPORT DesktopDragDropClientOzone ~DesktopDragDropClientOzone() override; + // Called by the window-move (tab-drag) entry point so that a + // renderer-initiated data drag cannot start inside the window-move's nested + // kNestableTasksAllowed RunLoop. See StartDragAndDrop. + [[nodiscard]] static base::AutoReset ScopedSuppressForWindowMove(); + protected: friend class DesktopDragDropClientOzoneTest; diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc index b958f491aefad..4a284a525e0ba 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc @@ -766,6 +766,11 @@ Widget::MoveLoopResult DesktopWindowTreeHostPlatform::RunMoveLoop( const gfx::Vector2d& drag_offset, Widget::MoveLoopSource source, Widget::MoveLoopEscapeBehavior escape_behavior) { + // The window-move loop runs a kNestableTasksAllowed RunLoop that pumps Mojo + // IPC; suppress renderer-initiated data drags for its duration so a + // compromised renderer in another window cannot hijack the user's gesture. + auto suppress_data_drag = + DesktopDragDropClientOzone::ScopedSuppressForWindowMove(); auto* move_loop_handler = ui::GetWmMoveLoopHandler(*platform_window()); if (move_loop_handler && move_loop_handler->RunMoveLoop(drag_offset)) { return Widget::MoveLoopResult::kSuccessful;