commit 35055c39b060b8014a4dd74b2e97acdf2abd46ac
parent 00f1baf7d5af86271b093ae8f9df906d941bbe53
Author: Pier Angelo Vendrame <pierov@torproject.org>
Date: Mon, 20 Oct 2025 17:37:01 +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, 125 insertions(+), 54 deletions(-)
diff --git a/dom/events/PointerEvent.cpp b/dom/events/PointerEvent.cpp
@@ -227,37 +227,78 @@ 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) {
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() {
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) {
+ if (mEvent->mMessage == ePointerUp ||
+ !ShouldResistFingerprinting(aCallerType)) {
return mEvent->AsPointerEvent()->mPressure;
}
@@ -274,14 +315,14 @@ float PointerEvent::Pressure() {
return spoofedPressure;
}
-float PointerEvent::TangentialPressure() {
- return ShouldResistFingerprinting()
+float PointerEvent::TangentialPressure(CallerType aCallerType) {
+ 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()) {
@@ -292,8 +333,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()) {
@@ -304,12 +345,14 @@ int32_t PointerEvent::TiltY() {
return *mTiltY;
}
-int32_t PointerEvent::Twist() {
- return ShouldResistFingerprinting() ? 0 : mEvent->AsPointerEvent()->twist;
+int32_t PointerEvent::Twist(CallerType aCallerType) {
+ 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()) {
@@ -320,8 +363,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()) {
@@ -334,13 +377,22 @@ double PointerEvent::AzimuthAngle() {
bool PointerEvent::IsPrimary() { return mEvent->AsPointerEvent()->mIsPrimary; }
-int32_t PointerEvent::PersistentDeviceId() {
+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;
+ }
+
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 {
@@ -440,17 +492,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
@@ -41,18 +41,20 @@ 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();
+ 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);
bool IsPrimary();
- int32_t PersistentDeviceId();
- void GetPointerType(nsAString& aPointerType);
+ void GetPointerType(
+ nsAString& aPointerType,
+ mozilla::dom::CallerType aCallerType = CallerType::System);
+ 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
@@ -14,18 +14,29 @@ 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"]