commit 00f1baf7d5af86271b093ae8f9df906d941bbe53
parent 52b1070ba2e982964f6105932edf2dc2cb1083a7
Author: Pier Angelo Vendrame <pierov@torproject.org>
Date: Mon, 20 Oct 2025 17:37:01 +0000
Bug 1991701 - Re-enable touch on Linux with RFP and remove RFPTarget::PointerId. r=tjr,layout-reviewers,emilio
On Windows, we do not spoof touch-related inputs anymore, and we
pretend touch is always available.
There is no reason not to do the same on Linux, even though the code to
report the number of maxTouchPoints is not implemented there.
Differential Revision: https://phabricator.services.mozilla.com/D267266
Diffstat:
9 files changed, 34 insertions(+), 96 deletions(-)
diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp
@@ -305,11 +305,6 @@ nsDOMAttributeMap* Element::Attributes() {
}
void Element::SetPointerCapture(int32_t aPointerId, ErrorResult& aError) {
- if (OwnerDoc()->ShouldResistFingerprinting(RFPTarget::PointerId) &&
- aPointerId != PointerEventHandler::GetSpoofedPointerIdForRFP()) {
- aError.ThrowNotFoundError("Invalid pointer id");
- return;
- }
const PointerInfo* pointerInfo =
PointerEventHandler::GetPointerInfo(aPointerId);
if (!pointerInfo) {
@@ -336,11 +331,6 @@ void Element::SetPointerCapture(int32_t aPointerId, ErrorResult& aError) {
}
void Element::ReleasePointerCapture(int32_t aPointerId, ErrorResult& aError) {
- if (OwnerDoc()->ShouldResistFingerprinting(RFPTarget::PointerId) &&
- aPointerId != PointerEventHandler::GetSpoofedPointerIdForRFP()) {
- aError.ThrowNotFoundError("Invalid pointer id");
- return;
- }
if (!PointerEventHandler::GetPointerInfo(aPointerId)) {
aError.ThrowNotFoundError("Invalid pointer id");
return;
diff --git a/dom/events/PointerEvent.cpp b/dom/events/PointerEvent.cpp
@@ -245,9 +245,7 @@ void PointerEvent::GetPointerType(nsAString& aPointerType) {
}
int32_t PointerEvent::PointerId() {
- return (ShouldResistFingerprinting(true))
- ? PointerEventHandler::GetSpoofedPointerIdForRFP()
- : mEvent->AsPointerEvent()->pointerId;
+ return mEvent->AsPointerEvent()->pointerId;
}
double PointerEvent::Width() const {
@@ -442,7 +440,7 @@ void PointerEvent::GetPredictedEvents(
aPointerEvents.AppendElements(mPredictedEvents);
}
-bool PointerEvent::ShouldResistFingerprinting(bool aForPointerId) const {
+bool PointerEvent::ShouldResistFingerprinting() const {
// There are three simple situations we don't need to spoof this pointer
// event.
// 1. The pref privcy.resistFingerprinting' is false, we fast return here
@@ -451,13 +449,11 @@ bool PointerEvent::ShouldResistFingerprinting(bool aForPointerId) const {
// 3. This event is a mouse pointer event.
// We don't need to check for the system group since pointer events won't be
// dispatched to the system group.
- RFPTarget target =
- aForPointerId ? RFPTarget::PointerId : RFPTarget::PointerEvents;
+ RFPTarget target = RFPTarget::PointerEvents;
if (!nsContentUtils::ShouldResistFingerprinting("Efficiency Check", target) ||
!mEvent->IsTrusted() ||
- (mEvent->AsPointerEvent()->mInputSource ==
- MouseEvent_Binding::MOZ_SOURCE_MOUSE &&
- SPOOFED_MAX_TOUCH_POINTS == 0)) {
+ mEvent->AsPointerEvent()->mInputSource ==
+ MouseEvent_Binding::MOZ_SOURCE_MOUSE) {
return false;
}
diff --git a/dom/events/PointerEvent.h b/dom/events/PointerEvent.h
@@ -63,7 +63,7 @@ class PointerEvent : public MouseEvent {
private:
// This method returns the boolean to indicate whether spoofing pointer
// event for fingerprinting resistance.
- bool ShouldResistFingerprinting(bool aForPointerId = false) const;
+ bool ShouldResistFingerprinting() const;
// When the instance is a trusted `pointermove` event but the widget event
// does not have proper coalesced events (typically, the event is synthesized
diff --git a/dom/events/PointerEventHandler.cpp b/dom/events/PointerEventHandler.cpp
@@ -675,32 +675,6 @@ void PointerEventHandler::CheckPointerCaptureState(WidgetPointerEvent* aEvent) {
PointerCaptureInfo* captureInfo = GetPointerCaptureInfo(aEvent->pointerId);
- // When fingerprinting resistance is enabled, we need to map other pointer
- // ids into the spoofed one. We don't have to do the mapping if the capture
- // info exists for the non-spoofed pointer id because of we won't allow
- // content to set pointer capture other than the spoofed one. Thus, it must be
- // from chrome if the capture info exists in this case. And we don't have to
- // do anything if the pointer id is the same as the spoofed one.
- if (nsContentUtils::ShouldResistFingerprinting("Efficiency Check",
- RFPTarget::PointerId) &&
- aEvent->pointerId != (uint32_t)GetSpoofedPointerIdForRFP() &&
- !captureInfo) {
- PointerCaptureInfo* spoofedCaptureInfo =
- GetPointerCaptureInfo(GetSpoofedPointerIdForRFP());
-
- // We need to check the target element's document should resist
- // fingerprinting. If not, we don't need to send a capture event
- // since the capture info of the original pointer id doesn't exist
- // in this case.
- if (!spoofedCaptureInfo || !spoofedCaptureInfo->mPendingElement ||
- !spoofedCaptureInfo->mPendingElement->OwnerDoc()
- ->ShouldResistFingerprinting(RFPTarget::PointerEvents)) {
- return;
- }
-
- captureInfo = spoofedCaptureInfo;
- }
-
if (!captureInfo ||
captureInfo->mPendingElement == captureInfo->mOverrideElement) {
return;
diff --git a/dom/events/TouchEvent.cpp b/dom/events/TouchEvent.cpp
@@ -226,36 +226,38 @@ bool TouchEvent::PrefEnabled(nsIDocShell* aDocShell) {
} else if (touchEventsOverride ==
mozilla::dom::TouchEventsOverride::Disabled) {
enabled = false;
+ } else if (nsContentUtils::ShouldResistFingerprinting(
+ aDocShell, RFPTarget::PointerEvents)) {
+#ifdef MOZ_WIDGET_COCOA
+ enabled = false;
+#else
+ enabled = true;
+#endif
} else {
const int32_t prefValue = StaticPrefs::dom_w3c_touch_events_enabled();
if (prefValue == 2) {
- if (nsContentUtils::ShouldResistFingerprinting(
- aDocShell, RFPTarget::PointerEvents)) {
- enabled = SPOOFED_MAX_TOUCH_POINTS != 0;
- } else {
- enabled = PlatformSupportsTouch();
-
- static bool firstTime = true;
- // The touch screen data seems to be inaccurate in the parent process,
- // and we really need the crash annotation in child processes.
- if (firstTime && !XRE_IsParentProcess()) {
- CrashReporter::RecordAnnotationBool(
- CrashReporter::Annotation::HasDeviceTouchScreen, enabled);
- firstTime = false;
- }
+ enabled = PlatformSupportsTouch();
+
+ static bool firstTime = true;
+ // The touch screen data seems to be inaccurate in the parent process,
+ // and we really need the crash annotation in child processes.
+ if (firstTime && !XRE_IsParentProcess()) {
+ CrashReporter::RecordAnnotationBool(
+ CrashReporter::Annotation::HasDeviceTouchScreen, enabled);
+ firstTime = false;
+ }
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
- if (enabled && aDocShell) {
- // APZ might be disabled on this particular widget, in which case
- // TouchEvent support will also be disabled. Try to detect that.
- if (RefPtr<nsPresContext> pc = aDocShell->GetPresContext()) {
- if (nsCOMPtr<nsIWidget> widget = pc->GetRootWidget()) {
- enabled &= widget->AsyncPanZoomEnabled();
- }
+ if (enabled && aDocShell) {
+ // APZ might be disabled on this particular widget, in which case
+ // TouchEvent support will also be disabled. Try to detect that.
+ if (RefPtr<nsPresContext> pc = aDocShell->GetPresContext()) {
+ if (nsCOMPtr<nsIWidget> widget = pc->GetRootWidget()) {
+ enabled &= widget->AsyncPanZoomEnabled();
}
}
-#endif
}
+#endif
} else {
enabled = !!prefValue;
}
diff --git a/layout/base/PositionedEventTargeting.cpp b/layout/base/PositionedEventTargeting.cpp
@@ -21,6 +21,7 @@
#include "mozilla/dom/DOMIntersectionObserver.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/MouseEventBinding.h"
+#include "mozilla/dom/TouchEvent.h"
#include "mozilla/gfx/Matrix.h"
#include "mozilla/layers/LayersTypes.h"
#include "nsContainerFrame.h"
@@ -178,9 +179,7 @@ static bool HasTouchListener(const nsIContent* aContent) {
return false;
}
- // FIXME: Should this really use the pref rather than TouchEvent::PrefEnabled
- // or such?
- if (!StaticPrefs::dom_w3c_touch_events_enabled()) {
+ if (!TouchEvent::PrefEnabled(aContent->OwnerDoc()->GetDocShell())) {
return false;
}
diff --git a/toolkit/components/resistfingerprinting/RFPTargets.inc b/toolkit/components/resistfingerprinting/RFPTargets.inc
@@ -35,7 +35,7 @@ ITEM_VALUE(NavigatorHWConcurrency, 16)
ITEM_VALUE(NavigatorOscpu, 17)
ITEM_VALUE(NavigatorPlatform, 18)
ITEM_VALUE(NavigatorUserAgent, 19)
-ITEM_VALUE(PointerId, 20)
+// We no longer use PointerId, it can renamed and reused
ITEM_VALUE(StreamVideoFacingMode, 21)
ITEM_VALUE(JSDateTimeUTC, 22)
ITEM_VALUE(JSMathFdlibm, 23)
@@ -109,6 +109,7 @@ ITEM_VALUE(NavigatorHWConcurrencyTiered,74)
ITEM_VALUE(WebGLRandomization, 75)
ITEM_VALUE(EfficientCanvasRandomization, 76)
+// !!! Adding a new target? Rename PointerId and repurpose it.
/*
* In certain cases, we precompute the value of ShouldRFP for e.g. a Document.
diff --git a/toolkit/components/resistfingerprinting/nsRFPService.cpp b/toolkit/components/resistfingerprinting/nsRFPService.cpp
@@ -310,13 +310,6 @@ Maybe<bool> nsRFPService::HandleExceptionalRFPTargets(
StaticPrefs::privacy_spoof_english_DoNotUseDirectly() == 2);
}
- // We don't spoof the pointerId on multi-touch devices.
-#if SPOOFED_MAX_TOUCH_POINTS > 0
- if (aTarget == RFPTarget::PointerId) {
- return Some(false);
- }
-#endif
-
return Nothing();
}
diff --git a/widget/WidgetEventImpl.cpp b/widget/WidgetEventImpl.cpp
@@ -606,23 +606,6 @@ bool WidgetEvent::IsBlockedForFingerprintingResistance() const {
keyboardEvent->mKeyNameIndex == KEY_NAME_INDEX_Control ||
keyboardEvent->mKeyNameIndex == KEY_NAME_INDEX_AltGraph);
}
- case ePointerEventClass: {
- if (IsPointerEventMessageOriginallyMouseEventMessage(mMessage)) {
- return false;
- }
-
- if (SPOOFED_MAX_TOUCH_POINTS > 0) {
- return false;
- }
-
- const WidgetPointerEvent* pointerEvent = AsPointerEvent();
-
- // We suppress the pointer events if it is not primary for fingerprinting
- // resistance. It is because of that we want to spoof any pointer event
- // into a mouse pointer event and the mouse pointer event only has
- // isPrimary as true.
- return !pointerEvent->mIsPrimary;
- }
default:
return false;
}