diff --git a/ui/ozone/platform/wayland/host/wayland_window.cc b/ui/ozone/platform/wayland/host/wayland_window.cc index 7701deda447bd..25e2d4a90df9f 100644 --- a/ui/ozone/platform/wayland/host/wayland_window.cc +++ b/ui/ozone/platform/wayland/host/wayland_window.cc @@ -918,16 +918,23 @@ void WaylandWindow::OnDragSessionClose(DragOperation operation) { // is about to shut down. Do nothing and return. return; } + // The callouts below dispatch into upper layers which may spin a nested + // message loop in which `this` is destroyed (CWE-416). Guard `this` with a + // weak pointer and lift the quit closure onto the stack so the outer drag + // RunLoop in StartDrag() is quit even if `this` is gone. + auto alive = AsWeakPtr(); + base::OnceClosure quit_closure = std::move(drag_loop_quit_closure_); std::move(drag_finished_callback_).Run(operation); // Skip releasing any pointer buttons for the case of a window drag driven by // the data drag controller. // TODO: crbug.com/40238145 - Refactor this per discussion at // crrev.com/c/5570335/comment/0b8811fc_818028c9/. - if (!connection()->data_drag_controller()->IsWindowDragSessionRunning()) { + if (alive && + !connection()->data_drag_controller()->IsWindowDragSessionRunning()) { connection()->event_source()->ReleasePressedPointerButtons( this, EventTimeForNow()); } - std::move(drag_loop_quit_closure_).Run(); + std::move(quit_closure).Run(); } bool WaylandWindow::Initialize(PlatformWindowInitProperties properties) {