Bug 2064287 - Harden drag handling; r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D321984
This commit is contained in:
Edgar Chen
2026-09-04 14:59:04 +00:00
committed by echen@mozilla.com
parent a48a2abebd
commit 5197db7444
8 changed files with 71 additions and 10 deletions
+11
View File
@@ -510,6 +510,12 @@ void PointerLockManager::SetLockedRemoteTarget(BrowserParent* aBrowserParent,
return;
}
if (nsCOMPtr<nsIDragService> dragService =
do_GetService("@mozilla.org/widget/dragservice;1")) {
dragService->Suppress();
}
presContext->EventStateManager()->StopTrackingDragGesture(true);
MOZ_POINTERLOCK_LOG("Set locked remote target to 0x%p", aBrowserParent);
sLockedRemoteTarget = aBrowserParent;
PointerEventHandler::ReleaseAllPointerCaptureRemoteTarget();
@@ -539,6 +545,11 @@ void PointerLockManager::ReleaseLockedRemoteTarget(
nsCOMPtr<nsIWidget> widget = aBrowserParent->GetTopLevelWidget();
EventStateManager::ReleaseLockedPointer(widget);
if (nsCOMPtr<nsIDragService> dragService =
do_GetService("@mozilla.org/widget/dragservice;1")) {
dragService->Unsuppress();
}
}
}
+1
View File
@@ -54,6 +54,7 @@ class PointerLockManager final {
// Set/release pointer lock remote target. Should only be called in parent
// process.
MOZ_CAN_RUN_SCRIPT
static void SetLockedRemoteTarget(dom::BrowserParent* aBrowserParent,
const bool& aUnadjustedMovement,
nsACString& aError);
+5
View File
@@ -2636,6 +2636,8 @@ void EventStateManager::BeginTrackingDragGesture(
if (!mGestureDownFrameOwner) {
mGestureDownFrameOwner = mGestureDownContent;
}
mGestureDownTopLevelRemoteTarget =
BrowserParent::GetFrom(mGestureDownContent);
}
mGestureModifiers = aMouseDownOrTouchDragEvent.mModifiers;
mGestureDownButtons = aMouseDownOrTouchDragEvent.mButtons;
@@ -2687,6 +2689,8 @@ void EventStateManager::StopTrackingDragGesture(bool aClearInChildProcesses) {
return;
}
mGestureDownTopLevelRemoteTarget = nullptr;
// Only notify if there is NOT a drag session active in the parent.
RefPtr<nsIDragSession> dragSession =
nsContentUtils::GetDragSession(mPresContext);
@@ -7990,6 +7994,7 @@ bool EventStateManager::WheelPrefs::IsOverOnePageScrollAllowedY(
void EventStateManager::UpdateGestureContent(nsIContent* aContent) {
mGestureDownContent = aContent;
mGestureDownFrameOwner = aContent;
mGestureDownTopLevelRemoteTarget = BrowserParent::GetFrom(aContent);
}
void EventStateManager::NotifyContentWillBeRemovedForGesture(
+5
View File
@@ -561,6 +561,10 @@ class EventStateManager : public nsSupportsWeakReference, public nsIObserver {
return mGestureDownContent;
}
dom::BrowserParent* GetTrackingDragGestureTopLevelRemoteTarget() const {
return mGestureDownTopLevelRemoteTarget;
}
// Update the tracked gesture content to the parent of its frame when it's
// removed, so that the gesture can be continued.
void NotifyContentWillBeRemovedForGesture(nsIContent& aContent);
@@ -1446,6 +1450,7 @@ class EventStateManager : public nsSupportsWeakReference, public nsIObserver {
// as the target in most cases but not always - for example when dragging
// an <area> of an image map this is the image. (bug 289667)
nsCOMPtr<nsIContent> mGestureDownFrameOwner;
RefPtr<dom::BrowserParent> mGestureDownTopLevelRemoteTarget;
// Data associated with a drag started in a content process.
RefPtr<dom::RemoteDragStartData> mGestureDownDragStartData;
// State of keys when the original gesture-down happened
+40 -10
View File
@@ -1060,6 +1060,20 @@ mozilla::ipc::IPCResult BrowserParent::RecvSetDimensions(
nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = do_QueryInterface(treeOwner);
NS_ENSURE_TRUE(treeOwnerAsWin, IPC_OK());
if (nsCOMPtr<nsIDragService> dragService =
do_GetService("@mozilla.org/widget/dragservice;1")) {
RefPtr<nsIWidget> widget = GetTopLevelWidget();
if (RefPtr<nsIDragSession> session =
dragService->GetCurrentSession(widget)) {
session->EndDragSession(false, 0);
}
}
if (nsPresContext* presContext =
mFrameElement->OwnerDoc()->GetPresContext()) {
presContext->EventStateManager()->StopTrackingDragGesture(true);
}
// `BrowserChild` only sends the values to actually be changed, see more
// details in `BrowserChild::SetDimensions()`.
// Note that `BrowserChild::SetDimensions()` may be called before receiving
@@ -3883,8 +3897,29 @@ mozilla::ipc::IPCResult BrowserParent::RecvInvokeDragSession(
const CookieJarSettingsArgs& aCookieJarSettingsArgs,
const MaybeDiscarded<WindowContext>& aSourceWindowContext,
const MaybeDiscarded<WindowContext>& aSourceTopWindowContext) {
PresShell* presShell = mFrameElement->OwnerDoc()->GetPresShell();
if (!presShell) {
nsCOMPtr<nsIDragService> dragService =
do_GetService("@mozilla.org/widget/dragservice;1");
nsPresContext* presContext = mFrameElement->OwnerDoc()->GetPresContext();
const bool isValidRemoteDrag = [&]() {
if (!dragService || !presContext) {
return false;
}
if (dragService->GetIsSuppressed()) {
return false;
}
BrowserParent* dragTopLevelRemoteTarget =
presContext->EventStateManager()
->GetTrackingDragGestureTopLevelRemoteTarget();
if (NS_WARN_IF(dragTopLevelRemoteTarget != TopLevelBrowserParent())) {
return false;
}
return true;
}();
if (!isValidRemoteDrag) {
(void)SendEndDragSession(true, true, LayoutDeviceIntPoint(), 0,
nsIDragService::DRAGDROP_ACTION_NONE);
// Continue sending input events with input priority when stopping the dnd
@@ -3922,15 +3957,10 @@ mozilla::ipc::IPCResult BrowserParent::RecvInvokeDragSession(
}
}
nsCOMPtr<nsIDragService> dragService =
do_GetService("@mozilla.org/widget/dragservice;1");
if (dragService) {
dragService->MaybeAddBrowser(this);
}
dragService->MaybeAddBrowser(this);
presShell->GetPresContext()
->EventStateManager()
->BeginTrackingRemoteDragGesture(mFrameElement, dragStartData);
presContext->EventStateManager()->BeginTrackingRemoteDragGesture(
mFrameElement, dragStartData);
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
os->NotifyObservers(nullptr, "content-invoked-drag", nullptr);
+2
View File
@@ -739,6 +739,7 @@ class BrowserParent final : public PBrowserParent,
mozilla::ipc::IPCResult RecvRemoteIsReadyToHandleInputEvents();
MOZ_CAN_RUN_SCRIPT_BOUNDARY
mozilla::ipc::IPCResult RecvSetDimensions(mozilla::DimensionRequest aRequest,
const double& aScale);
@@ -758,6 +759,7 @@ class BrowserParent final : public PBrowserParent,
mozilla::ipc::IPCResult RecvMaybeFireEmbedderLoadEvents(
EmbedderElementEventType aFireEventAtEmbeddingElement);
MOZ_CAN_RUN_SCRIPT_BOUNDARY
mozilla::ipc::IPCResult RecvRequestPointerLock(
const bool& aUnadjustedMovement, RequestPointerLockResolver&& aResolve);
mozilla::ipc::IPCResult RecvReleasePointerLock();
+2
View File
@@ -1169,6 +1169,8 @@ nsBaseDragService::Unsuppress() {
return NS_OK;
}
bool nsBaseDragService::GetIsSuppressed() { return mSuppressLevel > 0; }
NS_IMETHODIMP
nsBaseDragSession::UserCancelled() {
mUserCancelled = true;
+5
View File
@@ -172,6 +172,11 @@ interface nsIDragService : nsISupports
void suppress();
void unsuppress();
/**
* True if the dragging is disabled.
*/
[notxpcom, nostdcall] readonly attribute boolean isSuppressed;
[notxpcom, nostdcall] boolean maybeAddBrowser(in BrowserParentPtr aBP);
[notxpcom, nostdcall] boolean removeAllBrowsers();