commit 50c5bd85257cf1f48a8e510ce2a5fc0174192652
parent 2b786cc8069b9ee137c2fdc4583c634ccaa0ed79
Author: agoloman <agoloman@mozilla.com>
Date: Tue, 21 Oct 2025 03:20:40 +0300
Revert (Bug 1987929, Bug 1991701) - for causing perma failures @test_pointer_event.html.
This reverts commit 35055c39b060b8014a4dd74b2e97acdf2abd46ac.
Revert "Bug 1991701 - Re-enable touch on Linux with RFP and remove RFPTarget::PointerId. r=tjr,layout-reviewers,emilio"
This reverts commit 00f1baf7d5af86271b093ae8f9df906d941bbe53.
Diffstat:
10 files changed, 148 insertions(+), 157 deletions(-)
diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp
@@ -305,6 +305,11 @@ 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) {
@@ -331,6 +336,11 @@ 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
@@ -227,78 +227,39 @@ NS_INTERFACE_MAP_END_INHERITING(MouseEvent)
NS_IMPL_ADDREF_INHERITED(PointerEvent, MouseEvent)
NS_IMPL_RELEASE_INHERITED(PointerEvent, MouseEvent)
-uint16_t PointerEvent::ResistantInputSource(CallerType aCallerType) const {
- const uint16_t inputSource = mEvent->AsPointerEvent()->mInputSource;
- if (!ShouldResistFingerprinting(aCallerType)) {
- return inputSource;
- }
-
- MOZ_ASSERT(IsTrusted());
-
- // Bug 1953665: Pen events are inconsistent between platforms.
- // They might emit touch events on Windows and Android, but only mouse events
- // in other platforms. In particular, touch is always disabled on macOS.
-#if defined(XP_WIN)
- if (inputSource == MouseEvent_Binding::MOZ_SOURCE_TOUCH ||
- inputSource == MouseEvent_Binding::MOZ_SOURCE_MOUSE) {
- return inputSource;
- }
- // Similar to nsWindow::DispatchTouchEventFromWMPointer.
- switch (mEvent->mMessage) {
- case ePointerMove:
- return mEvent->AsPointerEvent()->mPressure == 0
- ? MouseEvent_Binding::MOZ_SOURCE_MOUSE // hover
- : MouseEvent_Binding::MOZ_SOURCE_TOUCH;
- case ePointerUp:
- case ePointerDown:
- case ePointerCancel:
- return MouseEvent_Binding::MOZ_SOURCE_TOUCH;
- default:
- return MouseEvent_Binding::MOZ_SOURCE_MOUSE;
- }
-#elif defined(MOZ_WIDGET_ANDROID)
- return inputSource == MouseEvent_Binding::MOZ_SOURCE_MOUSE
- ? MouseEvent_Binding::MOZ_SOURCE_MOUSE
- : MouseEvent_Binding::MOZ_SOURCE_TOUCH;
-#elif defined(MOZ_WIDGET_GTK)
- return inputSource == MouseEvent_Binding::MOZ_SOURCE_TOUCH
- ? MouseEvent_Binding::MOZ_SOURCE_TOUCH
- : MouseEvent_Binding::MOZ_SOURCE_MOUSE;
-#elif defined(MOZ_WIDGET_COCOA)
- return MouseEvent_Binding::MOZ_SOURCE_MOUSE;
-#else
- return inputSource;
-#endif
-}
-
-void PointerEvent::GetPointerType(nsAString& aPointerType,
- CallerType aCallerType) {
+void PointerEvent::GetPointerType(nsAString& aPointerType) {
if (mPointerType.isSome()) {
aPointerType = mPointerType.value();
return;
}
- ConvertPointerTypeToString(ResistantInputSource(aCallerType), aPointerType);
+
+#if SPOOFED_MAX_TOUCH_POINTS <= 0
+ if (ShouldResistFingerprinting()) {
+ aPointerType.AssignLiteral("mouse");
+ return;
+ }
+#endif
+
+ ConvertPointerTypeToString(mEvent->AsPointerEvent()->mInputSource,
+ aPointerType);
}
int32_t PointerEvent::PointerId() {
- return mEvent->AsPointerEvent()->pointerId;
+ return (ShouldResistFingerprinting(true))
+ ? PointerEventHandler::GetSpoofedPointerIdForRFP()
+ : mEvent->AsPointerEvent()->pointerId;
}
-double PointerEvent::Width(CallerType aCallerType) const {
- return ShouldResistFingerprinting(aCallerType)
- ? 1.0
- : mEvent->AsPointerEvent()->mWidth;
+double PointerEvent::Width() const {
+ return ShouldResistFingerprinting() ? 1.0 : mEvent->AsPointerEvent()->mWidth;
}
-double PointerEvent::Height(CallerType aCallerType) const {
- return ShouldResistFingerprinting(aCallerType)
- ? 1.0
- : mEvent->AsPointerEvent()->mHeight;
+double PointerEvent::Height() const {
+ return ShouldResistFingerprinting() ? 1.0 : mEvent->AsPointerEvent()->mHeight;
}
-float PointerEvent::Pressure(CallerType aCallerType) {
- if (mEvent->mMessage == ePointerUp ||
- !ShouldResistFingerprinting(aCallerType)) {
+float PointerEvent::Pressure() {
+ if (mEvent->mMessage == ePointerUp || !ShouldResistFingerprinting()) {
return mEvent->AsPointerEvent()->mPressure;
}
@@ -315,14 +276,14 @@ float PointerEvent::Pressure(CallerType aCallerType) {
return spoofedPressure;
}
-float PointerEvent::TangentialPressure(CallerType aCallerType) {
- return ShouldResistFingerprinting(aCallerType)
+float PointerEvent::TangentialPressure() {
+ return ShouldResistFingerprinting()
? 0
: mEvent->AsPointerEvent()->tangentialPressure;
}
-int32_t PointerEvent::TiltX(CallerType aCallerType) {
- if (ShouldResistFingerprinting(aCallerType)) {
+int32_t PointerEvent::TiltX() {
+ if (ShouldResistFingerprinting()) {
return 0;
}
if (mTiltX.isSome()) {
@@ -333,8 +294,8 @@ int32_t PointerEvent::TiltX(CallerType aCallerType) {
return *mTiltX;
}
-int32_t PointerEvent::TiltY(CallerType aCallerType) {
- if (ShouldResistFingerprinting(aCallerType)) {
+int32_t PointerEvent::TiltY() {
+ if (ShouldResistFingerprinting()) {
return 0;
}
if (mTiltY.isSome()) {
@@ -345,14 +306,12 @@ int32_t PointerEvent::TiltY(CallerType aCallerType) {
return *mTiltY;
}
-int32_t PointerEvent::Twist(CallerType aCallerType) {
- return ShouldResistFingerprinting(aCallerType)
- ? 0
- : mEvent->AsPointerEvent()->twist;
+int32_t PointerEvent::Twist() {
+ return ShouldResistFingerprinting() ? 0 : mEvent->AsPointerEvent()->twist;
}
-double PointerEvent::AltitudeAngle(CallerType aCallerType) {
- if (ShouldResistFingerprinting(aCallerType)) {
+double PointerEvent::AltitudeAngle() {
+ if (ShouldResistFingerprinting()) {
return WidgetPointerHelper::GetDefaultAltitudeAngle();
}
if (mAltitudeAngle.isSome()) {
@@ -363,8 +322,8 @@ double PointerEvent::AltitudeAngle(CallerType aCallerType) {
return *mAltitudeAngle;
}
-double PointerEvent::AzimuthAngle(CallerType aCallerType) {
- if (ShouldResistFingerprinting(aCallerType)) {
+double PointerEvent::AzimuthAngle() {
+ if (ShouldResistFingerprinting()) {
return WidgetPointerHelper::GetDefaultAzimuthAngle();
}
if (mAzimuthAngle.isSome()) {
@@ -377,22 +336,13 @@ double PointerEvent::AzimuthAngle(CallerType aCallerType) {
bool PointerEvent::IsPrimary() { return mEvent->AsPointerEvent()->mIsPrimary; }
-int32_t PointerEvent::PersistentDeviceId(CallerType aCallerType) {
- const auto MaybeNonZero = [&]() {
- return mEvent->IsTrusted() && IsPointerEventMessage(mEvent->mMessage) &&
- !IsPointerEventMessageOriginallyMouseEventMessage(mEvent->mMessage);
- };
-
- if (ShouldResistFingerprinting(aCallerType)) {
- return MaybeNonZero() && ResistantInputSource(aCallerType) ==
- MouseEvent_Binding::MOZ_SOURCE_MOUSE
- ? 1
- : 0;
- }
-
+int32_t PointerEvent::PersistentDeviceId() {
if (mPersistentDeviceId.isNothing()) {
- if (MaybeNonZero() && mEvent->AsPointerEvent()->mInputSource ==
- MouseEvent_Binding::MOZ_SOURCE_MOUSE) {
+ if (mEvent->IsTrusted() &&
+ mEvent->AsPointerEvent()->mInputSource ==
+ MouseEvent_Binding::MOZ_SOURCE_MOUSE &&
+ IsPointerEventMessage(mEvent->mMessage) &&
+ !IsPointerEventMessageOriginallyMouseEventMessage(mEvent->mMessage)) {
// Follow the behavior which Chrome has for mouse.
mPersistentDeviceId.emplace(1);
} else {
@@ -492,22 +442,22 @@ void PointerEvent::GetPredictedEvents(
aPointerEvents.AppendElements(mPredictedEvents);
}
-bool PointerEvent::ShouldResistFingerprinting(CallerType aCallerType) const {
- // There are a few simple situations we don't need to spoof this pointer
+bool PointerEvent::ShouldResistFingerprinting(bool aForPointerId) const {
+ // There are three simple situations we don't need to spoof this pointer
// event.
- // * We are being called by a System caller
- // * The pref privcy.resistFingerprinting' is false, we fast return here
- // since we don't need to do any QI of following codes.
- // * This event is generated by scripts.
- // * This event is a mouse pointer event.
+ // 1. The pref privcy.resistFingerprinting' is false, we fast return here
+ // since we don't need to do any QI of following codes.
+ // 2. This event is generated by scripts.
+ // 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 = RFPTarget::PointerEvents;
- if (aCallerType == CallerType::System ||
- !nsContentUtils::ShouldResistFingerprinting("Efficiency Check", target) ||
+ RFPTarget target =
+ aForPointerId ? RFPTarget::PointerId : RFPTarget::PointerEvents;
+ if (!nsContentUtils::ShouldResistFingerprinting("Efficiency Check", target) ||
!mEvent->IsTrusted() ||
- mEvent->AsPointerEvent()->mInputSource ==
- MouseEvent_Binding::MOZ_SOURCE_MOUSE) {
+ (mEvent->AsPointerEvent()->mInputSource ==
+ MouseEvent_Binding::MOZ_SOURCE_MOUSE &&
+ SPOOFED_MAX_TOUCH_POINTS == 0)) {
return false;
}
diff --git a/dom/events/PointerEvent.h b/dom/events/PointerEvent.h
@@ -41,20 +41,18 @@ class PointerEvent : public MouseEvent {
PointerEvent* AsPointerEvent() final { return this; }
int32_t PointerId();
- double Width(CallerType aCallerType = CallerType::System) const;
- double Height(CallerType aCallerType = CallerType::System) const;
- float Pressure(CallerType aCallerType = CallerType::System);
- float TangentialPressure(CallerType aCallerType = CallerType::System);
- int32_t TiltX(CallerType aCallerType = CallerType::System);
- int32_t TiltY(CallerType aCallerType = CallerType::System);
- int32_t Twist(CallerType aCallerType = CallerType::System);
- double AltitudeAngle(CallerType aCallerType = CallerType::System);
- double AzimuthAngle(CallerType aCallerType = CallerType::System);
+ double Width() const;
+ double Height() const;
+ float Pressure();
+ float TangentialPressure();
+ int32_t TiltX();
+ int32_t TiltY();
+ int32_t Twist();
+ double AltitudeAngle();
+ double AzimuthAngle();
bool IsPrimary();
- void GetPointerType(
- nsAString& aPointerType,
- mozilla::dom::CallerType aCallerType = CallerType::System);
- int32_t PersistentDeviceId(CallerType aCallerType = CallerType::System);
+ int32_t PersistentDeviceId();
+ void GetPointerType(nsAString& aPointerType);
static bool EnableGetCoalescedEvents(JSContext* aCx, JSObject* aGlobal);
void GetCoalescedEvents(nsTArray<RefPtr<PointerEvent>>& aPointerEvents);
void GetPredictedEvents(nsTArray<RefPtr<PointerEvent>>& aPointerEvents);
@@ -65,11 +63,7 @@ class PointerEvent : public MouseEvent {
private:
// This method returns the boolean to indicate whether spoofing pointer
// event for fingerprinting resistance.
- bool ShouldResistFingerprinting(
- CallerType aCallerType = CallerType::System) const;
-
- uint16_t ResistantInputSource(
- CallerType aCallerType = CallerType::System) const;
+ bool ShouldResistFingerprinting(bool aForPointerId = false) 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,6 +675,32 @@ 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,38 +226,36 @@ 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) {
- 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 (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;
+ }
#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
+ }
} else {
enabled = !!prefValue;
}
diff --git a/dom/webidl/PointerEvent.webidl b/dom/webidl/PointerEvent.webidl
@@ -14,29 +14,18 @@ interface PointerEvent : MouseEvent
readonly attribute long pointerId;
- [NeedsCallerType]
readonly attribute double width;
- [NeedsCallerType]
readonly attribute double height;
- [NeedsCallerType]
readonly attribute float pressure;
- [NeedsCallerType]
readonly attribute float tangentialPressure;
- [NeedsCallerType]
readonly attribute long tiltX;
- [NeedsCallerType]
readonly attribute long tiltY;
- [NeedsCallerType]
readonly attribute long twist;
- [NeedsCallerType]
readonly attribute double altitudeAngle;
- [NeedsCallerType]
readonly attribute double azimuthAngle;
- [NeedsCallerType]
readonly attribute DOMString pointerType;
readonly attribute boolean isPrimary;
- [NeedsCallerType]
readonly attribute long persistentDeviceId;
[Func="mozilla::dom::PointerEvent::EnableGetCoalescedEvents"]
diff --git a/layout/base/PositionedEventTargeting.cpp b/layout/base/PositionedEventTargeting.cpp
@@ -21,7 +21,6 @@
#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"
@@ -179,7 +178,9 @@ static bool HasTouchListener(const nsIContent* aContent) {
return false;
}
- if (!TouchEvent::PrefEnabled(aContent->OwnerDoc()->GetDocShell())) {
+ // FIXME: Should this really use the pref rather than TouchEvent::PrefEnabled
+ // or such?
+ if (!StaticPrefs::dom_w3c_touch_events_enabled()) {
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)
-// We no longer use PointerId, it can renamed and reused
+ITEM_VALUE(PointerId, 20)
ITEM_VALUE(StreamVideoFacingMode, 21)
ITEM_VALUE(JSDateTimeUTC, 22)
ITEM_VALUE(JSMathFdlibm, 23)
@@ -109,7 +109,6 @@ 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,6 +310,13 @@ 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,6 +606,23 @@ 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;
}