commit 996938e0bc68f1eafeb22819beb9428c97df4388
parent e9fa485e4ac0f53d50f0a7ae49e10de7ca2deb84
Author: Pier Angelo Vendrame <pierov@torproject.org>
Date: Thu, 6 Nov 2025 08:03:53 +0000
Bug 1987929 - Hide pen input in RFP on desktop. r=masayuki,webidl,saschanaz
The pen features (pressure, angles, etc...) are already spoofed.
However, we still tell that the input comes from a pen.
At this point, we can pretend it came from a mouse.
Differential Revision: https://phabricator.services.mozilla.com/D267267
Diffstat:
3 files changed, 133 insertions(+), 59 deletions(-)
diff --git a/dom/events/PointerEvent.cpp b/dom/events/PointerEvent.cpp
@@ -227,42 +227,83 @@ NS_INTERFACE_MAP_END_INHERITING(MouseEvent)
NS_IMPL_ADDREF_INHERITED(PointerEvent, MouseEvent)
NS_IMPL_RELEASE_INHERITED(PointerEvent, MouseEvent)
-void PointerEvent::GetPointerType(nsAString& aPointerType) {
+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) const {
if (mPointerType.isSome()) {
aPointerType = mPointerType.value();
return;
}
-
-#if SPOOFED_MAX_TOUCH_POINTS <= 0
- if (ShouldResistFingerprinting()) {
- aPointerType.AssignLiteral("mouse");
- return;
- }
-#endif
-
- ConvertPointerTypeToString(mEvent->AsPointerEvent()->mInputSource,
- aPointerType);
+ ConvertPointerTypeToString(ResistantInputSource(aCallerType), aPointerType);
}
-int32_t PointerEvent::PointerId() {
+int32_t PointerEvent::PointerId(CallerType aCallerType) const {
#ifdef MOZ_WIDGET_COCOA
- if (ShouldResistFingerprinting()) {
+ if (ShouldResistFingerprinting(aCallerType)) {
return PointerEventHandler::GetSpoofedPointerIdForRFP();
}
#endif
return mEvent->AsPointerEvent()->pointerId;
}
-double PointerEvent::Width() const {
- return ShouldResistFingerprinting() ? 1.0 : mEvent->AsPointerEvent()->mWidth;
+double PointerEvent::Width(CallerType aCallerType) const {
+ return ShouldResistFingerprinting(aCallerType)
+ ? 1.0
+ : mEvent->AsPointerEvent()->mWidth;
}
-double PointerEvent::Height() const {
- return ShouldResistFingerprinting() ? 1.0 : mEvent->AsPointerEvent()->mHeight;
+double PointerEvent::Height(CallerType aCallerType) const {
+ return ShouldResistFingerprinting(aCallerType)
+ ? 1.0
+ : mEvent->AsPointerEvent()->mHeight;
}
-float PointerEvent::Pressure() {
- if (mEvent->mMessage == ePointerUp || !ShouldResistFingerprinting()) {
+float PointerEvent::Pressure(CallerType aCallerType) const {
+ if (mEvent->mMessage == ePointerUp ||
+ !ShouldResistFingerprinting(aCallerType)) {
return mEvent->AsPointerEvent()->mPressure;
}
@@ -279,14 +320,14 @@ float PointerEvent::Pressure() {
return spoofedPressure;
}
-float PointerEvent::TangentialPressure() {
- return ShouldResistFingerprinting()
+float PointerEvent::TangentialPressure(CallerType aCallerType) const {
+ return ShouldResistFingerprinting(aCallerType)
? 0
: mEvent->AsPointerEvent()->tangentialPressure;
}
-int32_t PointerEvent::TiltX() {
- if (ShouldResistFingerprinting()) {
+int32_t PointerEvent::TiltX(CallerType aCallerType) {
+ if (ShouldResistFingerprinting(aCallerType)) {
return 0;
}
if (mTiltX.isSome()) {
@@ -297,8 +338,8 @@ int32_t PointerEvent::TiltX() {
return *mTiltX;
}
-int32_t PointerEvent::TiltY() {
- if (ShouldResistFingerprinting()) {
+int32_t PointerEvent::TiltY(CallerType aCallerType) {
+ if (ShouldResistFingerprinting(aCallerType)) {
return 0;
}
if (mTiltY.isSome()) {
@@ -309,12 +350,14 @@ int32_t PointerEvent::TiltY() {
return *mTiltY;
}
-int32_t PointerEvent::Twist() {
- return ShouldResistFingerprinting() ? 0 : mEvent->AsPointerEvent()->twist;
+int32_t PointerEvent::Twist(CallerType aCallerType) const {
+ return ShouldResistFingerprinting(aCallerType)
+ ? 0
+ : mEvent->AsPointerEvent()->twist;
}
-double PointerEvent::AltitudeAngle() {
- if (ShouldResistFingerprinting()) {
+double PointerEvent::AltitudeAngle(CallerType aCallerType) {
+ if (ShouldResistFingerprinting(aCallerType)) {
return WidgetPointerHelper::GetDefaultAltitudeAngle();
}
if (mAltitudeAngle.isSome()) {
@@ -325,8 +368,8 @@ double PointerEvent::AltitudeAngle() {
return *mAltitudeAngle;
}
-double PointerEvent::AzimuthAngle() {
- if (ShouldResistFingerprinting()) {
+double PointerEvent::AzimuthAngle(CallerType aCallerType) {
+ if (ShouldResistFingerprinting(aCallerType)) {
return WidgetPointerHelper::GetDefaultAzimuthAngle();
}
if (mAzimuthAngle.isSome()) {
@@ -337,15 +380,26 @@ double PointerEvent::AzimuthAngle() {
return *mAzimuthAngle;
}
-bool PointerEvent::IsPrimary() { return mEvent->AsPointerEvent()->mIsPrimary; }
+bool PointerEvent::IsPrimary() const {
+ 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 (mEvent->IsTrusted() &&
- mEvent->AsPointerEvent()->mInputSource ==
- MouseEvent_Binding::MOZ_SOURCE_MOUSE &&
- IsPointerEventMessage(mEvent->mMessage) &&
- !IsPointerEventMessageOriginallyMouseEventMessage(mEvent->mMessage)) {
+ if (MaybeNonZero() && mEvent->AsPointerEvent()->mInputSource ==
+ MouseEvent_Binding::MOZ_SOURCE_MOUSE) {
// Follow the behavior which Chrome has for mouse.
mPersistentDeviceId.emplace(1);
} else {
@@ -445,17 +499,19 @@ void PointerEvent::GetPredictedEvents(
aPointerEvents.AppendElements(mPredictedEvents);
}
-bool PointerEvent::ShouldResistFingerprinting() const {
- // There are three simple situations we don't need to spoof this pointer
+bool PointerEvent::ShouldResistFingerprinting(CallerType aCallerType) const {
+ // There are a few simple situations we don't need to spoof this 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 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.
// 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 (!nsContentUtils::ShouldResistFingerprinting("Efficiency Check", target) ||
+ if (aCallerType == CallerType::System ||
+ !nsContentUtils::ShouldResistFingerprinting("Efficiency Check", target) ||
!mEvent->IsTrusted() ||
mEvent->AsPointerEvent()->mInputSource ==
MouseEvent_Binding::MOZ_SOURCE_MOUSE) {
diff --git a/dom/events/PointerEvent.h b/dom/events/PointerEvent.h
@@ -40,19 +40,21 @@ class PointerEvent : public MouseEvent {
PointerEvent* AsPointerEvent() final { return this; }
- int32_t PointerId();
- 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();
- int32_t PersistentDeviceId();
- void GetPointerType(nsAString& aPointerType);
+ int32_t PointerId(CallerType aCallerType = CallerType::System) const;
+ double Width(CallerType aCallerType = CallerType::System) const;
+ double Height(CallerType aCallerType = CallerType::System) const;
+ float Pressure(CallerType aCallerType = CallerType::System) const;
+ float TangentialPressure(CallerType aCallerType = CallerType::System) const;
+ int32_t TiltX(CallerType aCallerType = CallerType::System);
+ int32_t TiltY(CallerType aCallerType = CallerType::System);
+ int32_t Twist(CallerType aCallerType = CallerType::System) const;
+ double AltitudeAngle(CallerType aCallerType = CallerType::System);
+ double AzimuthAngle(CallerType aCallerType = CallerType::System);
+ bool IsPrimary() const;
+ void GetPointerType(
+ nsAString& aPointerType,
+ mozilla::dom::CallerType aCallerType = CallerType::System) const;
+ int32_t PersistentDeviceId(CallerType aCallerType = CallerType::System);
static bool EnableGetCoalescedEvents(JSContext* aCx, JSObject* aGlobal);
void GetCoalescedEvents(nsTArray<RefPtr<PointerEvent>>& aPointerEvents);
void GetPredictedEvents(nsTArray<RefPtr<PointerEvent>>& aPointerEvents);
@@ -63,7 +65,11 @@ class PointerEvent : public MouseEvent {
private:
// This method returns the boolean to indicate whether spoofing pointer
// event for fingerprinting resistance.
- bool ShouldResistFingerprinting() const;
+ bool ShouldResistFingerprinting(
+ CallerType aCallerType = CallerType::System) const;
+
+ uint16_t ResistantInputSource(
+ CallerType aCallerType = CallerType::System) 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/webidl/PointerEvent.webidl b/dom/webidl/PointerEvent.webidl
@@ -12,20 +12,32 @@ interface PointerEvent : MouseEvent
{
constructor(DOMString type, optional PointerEventInit eventInitDict = {});
+ [NeedsCallerType]
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"]