mirror of
https://github.com/daijro/camoufox.git
synced 2026-09-08 16:01:00 +00:00
navigator.maxTouchPoints could already be spoofed, but nothing moved with it, so a spoofed digitizer contradicted itself in two places a script reads in one line: (any-pointer: coarse) stayed false, and window.TouchEvent and window.Touch were absent entirely. Restore the aID branch in force-default-pointer.patch so the coarse bit joins the *any-pointer* set, and only when maxTouchPoints > 0. The primary pointer stays Fine|Hover: a touchscreen laptop still drives its trackpad, and reporting (pointer: coarse) would claim a phone while the accompanying desktop UA said otherwise. The host LookAndFeel value is still not consulted -- the capability set must not vary with the machine the browser runs on. Expose the touch interfaces by moving TouchEvent::PrefEnabled only, never LegacyAPIEnabled. dom.w3c_touch_events.legacy_apis.enabled is false everywhere but Android, so a real Windows touchscreen laptop exposes TouchEvent and Touch while 'ontouchstart' in window is false. Matching that shape matters more than exposing the whole touch API: a build that switches touch on wholesale is more detectable than one that does nothing. Rename mobile-fingerprint-spoofing.patch to touchscreen-fingerprint-spoofing .patch, since the rationale is the ordinary Windows touchscreen laptop rather than a phone, and carry the new TouchEvent.cpp hunk there beside the existing Navigator.cpp one. The rename moves it after navigator-spoofing.patch in basename order, so its Navigator.cpp hunk now lands with an offset; verified to still apply cleanly with no rejects. Warn at launch whenever navigator.maxTouchPoints is set, separately from the blanket navigator warning, because the knock-on effects reach past navigator into the CSS pointer media queries and the TouchEvent interfaces. tests/patches/touchscreen-digitizer.py checks all 16 signals and asserts that maxTouchPoints=0 still looks like a machine with no digitizer. It fails on a binary built without this change (13/16) and passes on one built with it. The reference values it carries are RECONSTRUCTED, not captured: the recording from the Dell XPS 15 9510 was not reachable from the build host, so eight values come from the specification and eight from Gecko's own gating logic. Each is marked in the table. Check them against the real capture when the reference machine is available; the capture wins. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W2RfR387Mh1JhZ9LZvkptP
58 lines
2.2 KiB
Diff
58 lines
2.2 KiB
Diff
diff --git a/layout/style/nsMediaFeatures.cpp b/layout/style/nsMediaFeatures.cpp
|
|
--- a/layout/style/nsMediaFeatures.cpp
|
|
+++ b/layout/style/nsMediaFeatures.cpp
|
|
@@ -408,34 +433,41 @@ static PointerCapabilities GetPointerCapabilities(const Document* aDocument,
|
|
// that we don't need to care about ResistFingerprinting.
|
|
if (bc->TouchEventsOverride() == dom::TouchEventsOverride::Enabled) {
|
|
return PointerCapabilities::Coarse;
|
|
}
|
|
}
|
|
|
|
// The default value for Desktop is mouse-type pointer, and for Android
|
|
// a coarse pointer.
|
|
- const PointerCapabilities kDefaultCapabilities =
|
|
#ifdef ANDROID
|
|
- PointerCapabilities::Coarse;
|
|
+ return PointerCapabilities::Coarse;
|
|
#else
|
|
+ // Report the desktop default rather than whatever the host toolkit
|
|
+ // advertises, so the capability set never varies with the machine the
|
|
+ // browser happens to be running on.
|
|
+ PointerCapabilities capabilities =
|
|
PointerCapabilities::Fine | PointerCapabilities::Hover;
|
|
-#endif
|
|
- if (aDocument->ShouldResistFingerprinting(
|
|
- RFPTarget::CSSPointerCapabilities)) {
|
|
- return kDefaultCapabilities;
|
|
- }
|
|
|
|
- int32_t intValue;
|
|
- nsresult rv = LookAndFeel::GetInt(aID, &intValue);
|
|
- if (NS_FAILED(rv)) {
|
|
- return kDefaultCapabilities;
|
|
+ // A touchscreen laptop still drives a fine, hovering *primary* pointer --
|
|
+ // its trackpad -- and the digitizer only ever joins the `any-pointer` set.
|
|
+ // Keeping that split is the whole point: a spoofed maxTouchPoints paired
|
|
+ // with `(pointer: coarse)` would claim a phone, while the accompanying
|
|
+ // desktop UA said otherwise.
|
|
+ if (aID == LookAndFeel::IntID::AllPointerCapabilities) {
|
|
+ if (auto maxTouchPoints =
|
|
+ MaskConfig::GetUint32("navigator.maxTouchPoints")) {
|
|
+ if (maxTouchPoints.value() > 0) {
|
|
+ capabilities |= PointerCapabilities::Coarse;
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
- return static_cast<PointerCapabilities>(intValue);
|
|
+ return capabilities;
|
|
+#endif
|
|
}
|
|
|
|
PointerCapabilities Gecko_MediaFeatures_PrimaryPointerCapabilities(
|
|
const Document* aDocument) {
|
|
return GetPointerCapabilities(aDocument,
|
|
LookAndFeel::IntID::PrimaryPointerCapabilities);
|
|
}
|
|
|