
morgan pushed to branch mullvad-browser-140.4.0esr-15.0-1 at The Tor Project / Applications / Mullvad Browser Commits: 4517a0aa by Pier Angelo Vendrame at 2025-10-15T13:56:10+00:00 BB 43869: Hide pens with RFP. - - - - - 1a3fdcf6 by Pier Angelo Vendrame at 2025-10-15T13:56:10+00:00 fixup! Firefox preference overrides. BB 43869: Remove prefs for touch. RFP now overrides them. - - - - - 11 changed files: - browser/app/profile/001-base-profile.js - dom/base/Element.cpp - dom/events/PointerEvent.cpp - dom/events/PointerEvent.h - dom/events/PointerEventHandler.cpp - dom/events/TouchEvent.cpp - dom/webidl/PointerEvent.webidl - layout/base/PositionedEventTargeting.cpp - toolkit/components/resistfingerprinting/RFPTargets.inc - toolkit/components/resistfingerprinting/nsRFPService.cpp - widget/WidgetEventImpl.cpp Changes: ===================================== browser/app/profile/001-base-profile.js ===================================== @@ -497,12 +497,6 @@ pref("dom.webmidi.enabled", false); // Bug 41398: Disable Web MIDI API // randomized IDs when this pref is true). // Defense-in-depth (already the default value) from Firefox 119 or 120. pref("media.devices.enumerate.legacy.enabled", false); -// Touch events (tor-browser#10286, tor-browser#42069, tor-browser#44062) -#if defined(XP_WIN) || defined(ANDROID) -pref("dom.w3c_touch_events.enabled", 1); -#else -pref("dom.w3c_touch_events.enabled", 0); -#endif #ifndef ANDROID // Bug 42138: Disable touch-based overscroll UX pref("apz.overscroll.enabled", false); ===================================== dom/base/Element.cpp ===================================== @@ -302,11 +302,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) { @@ -334,11 +329,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; ===================================== dom/events/PointerEvent.cpp ===================================== @@ -224,39 +224,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 (ShouldResistFingerprinting(true)) - ? PointerEventHandler::GetSpoofedPointerIdForRFP() - : mEvent->AsPointerEvent()->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; } @@ -273,14 +312,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()) { @@ -291,8 +330,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()) { @@ -303,12 +342,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()) { @@ -319,8 +360,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()) { @@ -421,22 +462,22 @@ void PointerEvent::GetPredictedEvents( aPointerEvents.AppendElements(mPredictedEvents); } -bool PointerEvent::ShouldResistFingerprinting(bool aForPointerId) 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 = - aForPointerId ? RFPTarget::PointerId : RFPTarget::PointerEvents; - if (!nsContentUtils::ShouldResistFingerprinting("Efficiency Check", target) || + RFPTarget target = RFPTarget::PointerEvents; + if (aCallerType == CallerType::System || + !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; } ===================================== dom/events/PointerEvent.h ===================================== @@ -41,17 +41,19 @@ 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(); - void GetPointerType(nsAString& aPointerType); + void GetPointerType( + nsAString& aPointerType, + mozilla::dom::CallerType aCallerType = CallerType::System); static bool EnableGetCoalescedEvents(JSContext* aCx, JSObject* aGlobal); void GetCoalescedEvents(nsTArray<RefPtr<PointerEvent>>& aPointerEvents); void GetPredictedEvents(nsTArray<RefPtr<PointerEvent>>& aPointerEvents); @@ -62,7 +64,11 @@ 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( + 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 ===================================== dom/events/PointerEventHandler.cpp ===================================== @@ -421,32 +421,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; ===================================== dom/events/TouchEvent.cpp ===================================== @@ -225,38 +225,40 @@ 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. - RefPtr<nsPresContext> pc = aDocShell->GetPresContext(); - if (pc) { - nsCOMPtr<nsIWidget> widget = pc->GetRootWidget(); - if (widget) { - 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. + RefPtr<nsPresContext> pc = aDocShell->GetPresContext(); + if (pc) { + nsCOMPtr<nsIWidget> widget = pc->GetRootWidget(); + if (widget) { + enabled &= widget->AsyncPanZoomEnabled(); } } -#endif } +#endif } else { enabled = !!prefValue; } ===================================== dom/webidl/PointerEvent.webidl ===================================== @@ -14,16 +14,26 @@ 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; ===================================== layout/base/PositionedEventTargeting.cpp ===================================== @@ -16,6 +16,7 @@ #include "mozilla/ToString.h" #include "mozilla/ViewportUtils.h" #include "mozilla/dom/MouseEventBinding.h" +#include "mozilla/dom/TouchEvent.h" #include "mozilla/gfx/Matrix.h" #include "mozilla/layers/LayersTypes.h" #include "nsContainerFrame.h" @@ -173,9 +174,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; } ===================================== toolkit/components/resistfingerprinting/RFPTargets.inc ===================================== @@ -34,7 +34,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) @@ -104,6 +104,7 @@ ITEM_VALUE(DiskStorageLimit, 70) ITEM_VALUE(WebCodecs, 71) ITEM_VALUE(NavigatorHWConcurrencyTiered,74) +// !!! Adding a new target? Rename PointerId and repurpose it. // !!! Don't forget to update kDefaultFingerprintingProtections in nsRFPService.cpp // if necessary. ===================================== toolkit/components/resistfingerprinting/nsRFPService.cpp ===================================== @@ -303,13 +303,6 @@ Maybe<bool> nsRFPService::HandleExeptionalRFPTargets( 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(); } ===================================== widget/WidgetEventImpl.cpp ===================================== @@ -589,23 +589,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; } View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/compare/fb9... -- View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/compare/fb9... You're receiving this email because of your account on gitlab.torproject.org.
participants (1)
-
morgan (@morgan)