Firefox · DOM
CVE-2026-92018
Logic Error in DOM
Overview
High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifdom/events/EventStateManager.cpp |
modified | |
ifdom/ipc/BrowserParent.cpp |
modified | |
UserCancelledwidget/nsBaseDragService.cpp |
modified |
Files Changed
dom/base/PointerLockManager.cppdom/events/EventStateManager.cppdom/events/EventStateManager.hdom/ipc/BrowserParent.cppwidget/nsBaseDragService.cppwidget/nsIDragService.idl
Patch
diff --git a/dom/base/PointerLockManager.cpp b/dom/base/PointerLockManager.cpp
index 288361efd55..4f1e1b98311 100644
--- a/dom/base/PointerLockManager.cpp
+++ b/dom/base/PointerLockManager.cpp
@@ -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();
+ }
}
}
diff --git a/dom/events/EventStateManager.cpp b/dom/events/EventStateManager.cpp
index 3ef7a8a883b..881b2b41408 100644
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -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(
diff --git a/dom/events/EventStateManager.h b/dom/events/EventStateManager.h
index e9963a401d2..af59f10e4a7 100644
--- a/dom/events/EventStateManager.h
+++ b/dom/events/EventStateManager.h
@@ -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
diff --git a/dom/ipc/BrowserParent.cpp b/dom/ipc/BrowserParent.cpp
index 924bee2a2c5..d640d0f2653 100644
--- a/dom/ipc/BrowserParent.cpp
+++ b/dom/ipc/BrowserParent.cpp
@@ -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);
diff --git a/widget/nsBaseDragService.cpp b/widget/nsBaseDragService.cpp
index a67b8af9975..68cbacea55a 100644
--- a/widget/nsBaseDragService.cpp
+++ b/widget/nsBaseDragService.cpp
@@ -1169,6 +1169,8 @@ nsBaseDragService::Unsuppress() {
return NS_OK;
}
+bool nsBaseDragService::GetIsSuppressed() { return mSuppressLevel > 0; }
+
NS_IMETHODIMP
nsBaseDragSession::UserCancelled() {
mUserCancelled = true;
diff --git a/widget/nsIDragService.idl b/widget/nsIDragService.idl
index 5ef0fa0e6aa..8ebc5a3b8af 100644
--- a/widget/nsIDragService.idl
+++ b/widget/nsIDragService.idl
@@ -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();
Loading diff…
References
On This Page