Bug 1826051: Improve PointerEvents RFP target for Android. r=tjr

- This patch separates RFPTarget::PointerEvents into PointerEvents and PointerId.
- PointerId protection is disabled for Android.
- WidgetEvents emit non-primary mouse events on Android because any touch other than 1nd touch is considered non-primary
- Sets maximum touch points to 5 on Android

Differential Revision: https://phabricator.services.mozilla.com/D221241
This commit is contained in:
Fatih 2024-09-10 14:37:50 +00:00
Родитель 24072971dd
Коммит d9402246b9
10 изменённых файлов: 41 добавлений и 21 удалений

Просмотреть файл

@ -14,18 +14,19 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1363508
<div id="target0" style="width: 50px; height: 50px; background: green"></div>
<div id="target1" style="width: 50px; height: 50px; background: black"></div>
<script type="application/javascript">
/** Test for Bug 1363508 */
SimpleTest.waitForExplicitFinish();
const { AppConstants } = SpecialPowers.ChromeUtils.importESModule(
"resource://gre/modules/AppConstants.sys.mjs"
);
var target0 = window.document.getElementById("target0");
var target1 = window.document.getElementById("target1");
var utils = SpecialPowers.Ci.nsIDOMWindowUtils;
// A helper function to check that whether the pointer is spoofed correctly.
function checkPointerEvent(aEvent) {
is(aEvent.pointerId, utils.DEFAULT_MOUSE_POINTER_ID,
"The spoofed pointer event should always have the mouse pointer id.");
is(aEvent.width, 1, "The spoofed pointer event should always have width as 1.");
is(aEvent.height, 1, "The spoofed pointer event should always have width as 1.");
if (aEvent.buttons === 0) {
@ -39,8 +40,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1363508
is(aEvent.tiltX, 0, "The spoofed pointer event should always have tiltX as 0.");
is(aEvent.tiltY, 0, "The spoofed pointer event should always have tiltY as 0.");
is(aEvent.twist, 0, "The spoofed pointer event should always have twist as 0.");
is(aEvent.pointerType, "mouse", "The spoofed pointer event should always has mouse pointerType.");
is(aEvent.isPrimary, true, "The spoofed pointer event should only receive primary pointer events.");
if (AppConstants.platform == "macosx") {
is(aEvent.pointerId, utils.DEFAULT_MOUSE_POINTER_ID,
"The spoofed pointer event should always have the mouse pointer id.");
is(aEvent.pointerType, "mouse", "The spoofed pointer event should always has mouse pointerType.");
is(aEvent.isPrimary, true, "The spoofed pointer event should only receive primary pointer events.");
}
}
// A helper function to create a promise for waiting the event.

Просмотреть файл

@ -299,7 +299,7 @@ nsDOMAttributeMap* Element::Attributes() {
}
void Element::SetPointerCapture(int32_t aPointerId, ErrorResult& aError) {
if (OwnerDoc()->ShouldResistFingerprinting(RFPTarget::PointerEvents) &&
if (OwnerDoc()->ShouldResistFingerprinting(RFPTarget::PointerId) &&
aPointerId != PointerEventHandler::GetSpoofedPointerIdForRFP()) {
aError.ThrowNotFoundError("Invalid pointer id");
return;
@ -328,7 +328,7 @@ void Element::SetPointerCapture(int32_t aPointerId, ErrorResult& aError) {
}
void Element::ReleasePointerCapture(int32_t aPointerId, ErrorResult& aError) {
if (OwnerDoc()->ShouldResistFingerprinting(RFPTarget::PointerEvents) &&
if (OwnerDoc()->ShouldResistFingerprinting(RFPTarget::PointerId) &&
aPointerId != PointerEventHandler::GetSpoofedPointerIdForRFP()) {
aError.ThrowNotFoundError("Invalid pointer id");
return;

Просмотреть файл

@ -886,7 +886,7 @@ uint32_t Navigator::MaxTouchPoints(CallerType aCallerType) {
if (aCallerType != CallerType::System &&
nsContentUtils::ShouldResistFingerprinting(GetDocShell(),
RFPTarget::PointerEvents)) {
return 0;
return SPOOFED_MAX_TOUCH_POINTS;
}
nsCOMPtr<nsIWidget> widget =

Просмотреть файл

@ -229,17 +229,19 @@ void PointerEvent::GetPointerType(nsAString& aPointerType) {
return;
}
#if SPOOFED_MAX_TOUCH_POINTS <= 0
if (ShouldResistFingerprinting()) {
aPointerType.AssignLiteral("mouse");
return;
}
#endif
ConvertPointerTypeToString(mEvent->AsPointerEvent()->mInputSource,
aPointerType);
}
int32_t PointerEvent::PointerId() {
return ShouldResistFingerprinting()
return (ShouldResistFingerprinting(true))
? PointerEventHandler::GetSpoofedPointerIdForRFP()
: mEvent->AsPointerEvent()->pointerId;
}
@ -419,7 +421,7 @@ void PointerEvent::GetPredictedEvents(
aPointerEvents.AppendElements(mPredictedEvents);
}
bool PointerEvent::ShouldResistFingerprinting() const {
bool PointerEvent::ShouldResistFingerprinting(bool aForPointerId) 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
@ -428,17 +430,19 @@ bool PointerEvent::ShouldResistFingerprinting() 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.
if (!nsContentUtils::ShouldResistFingerprinting("Efficiency Check",
RFPTarget::PointerEvents) ||
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;
}
// Pref is checked above, so use true as fallback.
nsCOMPtr<Document> doc = GetDocument();
return doc ? doc->ShouldResistFingerprinting(RFPTarget::PointerEvents) : true;
return doc ? doc->ShouldResistFingerprinting(target) : true;
}
} // namespace mozilla::dom

Просмотреть файл

@ -62,7 +62,7 @@ class PointerEvent : public MouseEvent {
private:
// This method returns the boolean to indicate whether spoofing pointer
// event for fingerprinting resistance.
bool ShouldResistFingerprinting() 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

Просмотреть файл

@ -343,7 +343,7 @@ void PointerEventHandler::CheckPointerCaptureState(WidgetPointerEvent* aEvent) {
// 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::PointerEvents) &&
RFPTarget::PointerId) &&
aEvent->pointerId != (uint32_t)GetSpoofedPointerIdForRFP() &&
!captureInfo) {
PointerCaptureInfo* spoofedCaptureInfo =

Просмотреть файл

@ -34,8 +34,7 @@ ITEM_VALUE(NavigatorHWConcurrency, 1llu << 15)
ITEM_VALUE(NavigatorOscpu, 1llu << 16)
ITEM_VALUE(NavigatorPlatform, 1llu << 17)
ITEM_VALUE(NavigatorUserAgent, 1llu << 18)
// We no longer use StreamTrackLabel, it can renamed and reused
ITEM_VALUE(StreamTrackLabel, 1llu << 19)
ITEM_VALUE(PointerId, 1llu << 19)
ITEM_VALUE(StreamVideoFacingMode, 1llu << 20)
ITEM_VALUE(JSDateTimeUTC, 1llu << 21)
ITEM_VALUE(JSMathFdlibm, 1llu << 22)
@ -95,8 +94,6 @@ ITEM_VALUE(SiteSpecificZoom, 1llu << 60)
// (This may block the fonts selected in Preferences from actually being used.)
ITEM_VALUE(FontVisibilityRestrictGenerics, 1llu << 61)
// !!! Adding a new target? Rename StreamTrackLabel and repurpose it.
// !!! Don't forget to update kDefaultFingerprintingProtections in nsRFPService.cpp
// if necessary.

Просмотреть файл

@ -239,6 +239,12 @@ bool nsRFPService::IsRFPEnabledFor(
const Maybe<RFPTarget>& aOverriddenFingerprintingSettings) {
MOZ_ASSERT(aTarget != RFPTarget::AllTargets);
#if SPOOFED_MAX_TOUCH_POINTS > 0
if (aTarget == RFPTarget::PointerId) {
return false;
}
#endif
if (StaticPrefs::privacy_resistFingerprinting_DoNotUseDirectly() ||
(aIsPrivateMode &&
StaticPrefs::privacy_resistFingerprinting_pbmode_DoNotUseDirectly())) {

Просмотреть файл

@ -35,20 +35,24 @@
# define SPOOFED_UA_OS "Windows NT 10.0; Win64; x64"
# define SPOOFED_APPVERSION "5.0 (Windows)"
# define SPOOFED_OSCPU "Windows NT 10.0; Win64; x64"
# define SPOOFED_MAX_TOUCH_POINTS 10
#elif defined(XP_MACOSX)
# define SPOOFED_UA_OS "Macintosh; Intel Mac OS X 10.15"
# define SPOOFED_APPVERSION "5.0 (Macintosh)"
# define SPOOFED_OSCPU "Intel Mac OS X 10.15"
# define SPOOFED_MAX_TOUCH_POINTS 0
#elif defined(MOZ_WIDGET_ANDROID)
# define SPOOFED_UA_OS "Android 10; Mobile"
# define SPOOFED_APPVERSION "5.0 (Android 10)"
# define SPOOFED_OSCPU "Linux armv81"
# define SPOOFED_MAX_TOUCH_POINTS 10
#else
// For Linux and other platforms, like BSDs, SunOS and etc, we will use Linux
// platform.
# define SPOOFED_UA_OS "X11; Linux x86_64"
# define SPOOFED_APPVERSION "5.0 (X11)"
# define SPOOFED_OSCPU "Linux x86_64"
# define SPOOFED_MAX_TOUCH_POINTS 10
#endif
#define LEGACY_BUILD_ID "20181001000000"

Просмотреть файл

@ -638,6 +638,10 @@ bool WidgetEvent::IsBlockedForFingerprintingResistance() const {
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