Bug 1363508 - Part 1: Spoofing pen/touch pointer events into mouse pointer events when fingerprinting resistance is on r=arthuredelstein,masayuki,smaug

The pointerType field in the pointer event will reveal the details of
users' hardware; this is a fingerprinting vector. So, we would spoof all
types of pointer events into mouse type pointer events for protecting
users from browser fingerprinting when fingerprinting resistance is on.

In this patch, we would spoof the pointerType as well as other fields
that mouse pointer events don't support, like pressure, tiltX/Y and so
on when fingerprinting resistance is on.

Differential Revision: https://phabricator.services.mozilla.com/D6003

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Tim Huang 2018-10-09 11:55:43 +00:00
Родитель 2139aad55e
Коммит 0a30f56cd5
7 изменённых файлов: 114 добавлений и 45 удалений

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

@ -235,6 +235,28 @@ Event::GetTarget() const
return mEvent->GetDOMEventTarget();
}
already_AddRefed<nsIDocument>
Event::GetDocument() const
{
nsCOMPtr<EventTarget> eventTarget = GetTarget();
if (!eventTarget) {
return nullptr;
}
nsCOMPtr<nsPIDOMWindowInner> win =
do_QueryInterface(eventTarget->GetOwnerGlobal());
if (!win) {
return nullptr;
}
nsCOMPtr<nsIDocument> doc;
doc = win->GetExtantDoc();
return doc.forget();
}
EventTarget*
Event::GetCurrentTarget() const
{

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

@ -214,6 +214,10 @@ public:
EventTarget* GetTarget() const;
EventTarget* GetCurrentTarget() const;
// This method returns the nsIDocument which is associated with the event
// target.
already_AddRefed<nsIDocument> GetDocument() const;
void ComposedPath(nsTArray<RefPtr<EventTarget>>& aPath);
uint16_t EventPhase() const;

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

@ -391,24 +391,6 @@ KeyboardEvent::InitKeyboardEventJS(const nsAString& aType,
keyEvent->mKeyValue = aKey;
}
already_AddRefed<nsIDocument>
KeyboardEvent::GetDocument()
{
nsCOMPtr<nsIDocument> doc;
nsCOMPtr<EventTarget> eventTarget = GetTarget();
if (eventTarget) {
nsCOMPtr<nsPIDOMWindowInner> win =
do_QueryInterface(eventTarget->GetOwnerGlobal());
if (win) {
doc = win->GetExtantDoc();
}
}
return doc.forget();
}
bool
KeyboardEvent::ShouldResistFingerprinting(CallerType aCallerType)
{

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

@ -107,10 +107,6 @@ private:
// Otherwise, it will return false.
bool ShouldResistFingerprinting(CallerType aCallerType);
// This method returns the nsIDocument which is associated with the event
// target.
already_AddRefed<nsIDocument> GetDocument();
// This method returns the spoofed modifier state of the given modifier key
// for fingerprinting resistance.
bool GetSpoofedModifierStates(const Modifiers aModifierKey,

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

@ -10,6 +10,7 @@
#include "mozilla/dom/PointerEvent.h"
#include "mozilla/dom/PointerEventBinding.h"
#include "mozilla/MouseEvents.h"
#include "nsContentUtils.h"
#include "prtime.h"
namespace mozilla {
@ -146,8 +147,13 @@ NS_IMPL_ADDREF_INHERITED(PointerEvent, MouseEvent)
NS_IMPL_RELEASE_INHERITED(PointerEvent, MouseEvent)
void
PointerEvent::GetPointerType(nsAString& aPointerType)
PointerEvent::GetPointerType(nsAString& aPointerType, CallerType aCallerType)
{
if (ShouldResistFingerprinting(aCallerType)) {
aPointerType.AssignLiteral("mouse");
return;
}
ConvertPointerTypeToString(mEvent->AsPointerEvent()->inputSource, aPointerType);
}
@ -158,45 +164,66 @@ PointerEvent::PointerId()
}
int32_t
PointerEvent::Width()
PointerEvent::Width(CallerType aCallerType)
{
return mEvent->AsPointerEvent()->mWidth;
return ShouldResistFingerprinting(aCallerType) ?
1 : mEvent->AsPointerEvent()->mWidth;
}
int32_t
PointerEvent::Height()
PointerEvent::Height(CallerType aCallerType)
{
return mEvent->AsPointerEvent()->mHeight;
return ShouldResistFingerprinting(aCallerType) ?
1 : mEvent->AsPointerEvent()->mHeight;
}
float
PointerEvent::Pressure()
PointerEvent::Pressure(CallerType aCallerType)
{
return mEvent->AsPointerEvent()->pressure;
if (mEvent->mMessage == ePointerUp ||
!ShouldResistFingerprinting(aCallerType)) {
return mEvent->AsPointerEvent()->pressure;
}
// According to [1], we should use 0.5 when it is in active buttons state and
// 0 otherwise for devices that don't support pressure. And a pointerup event
// always reports 0, so we don't need to spoof that.
//
// [1] https://www.w3.org/TR/pointerevents/#dom-pointerevent-pressure
float spoofedPressure = 0.0;
if (mEvent->AsPointerEvent()->buttons) {
spoofedPressure = 0.5;
}
return spoofedPressure;
}
float
PointerEvent::TangentialPressure()
PointerEvent::TangentialPressure(CallerType aCallerType)
{
return mEvent->AsPointerEvent()->tangentialPressure;
return ShouldResistFingerprinting(aCallerType) ?
0 : mEvent->AsPointerEvent()->tangentialPressure;
}
int32_t
PointerEvent::TiltX()
PointerEvent::TiltX(CallerType aCallerType)
{
return mEvent->AsPointerEvent()->tiltX;
return ShouldResistFingerprinting(aCallerType) ?
0 : mEvent->AsPointerEvent()->tiltX;
}
int32_t
PointerEvent::TiltY()
PointerEvent::TiltY(CallerType aCallerType)
{
return mEvent->AsPointerEvent()->tiltY;
return ShouldResistFingerprinting(aCallerType) ?
0 : mEvent->AsPointerEvent()->tiltY;
}
int32_t
PointerEvent::Twist()
PointerEvent::Twist(CallerType aCallerType)
{
return mEvent->AsPointerEvent()->twist;
return ShouldResistFingerprinting(aCallerType) ?
0 : mEvent->AsPointerEvent()->twist;
}
bool
@ -249,6 +276,30 @@ PointerEvent::GetCoalescedEvents(nsTArray<RefPtr<PointerEvent>>& aPointerEvents)
aPointerEvents.AppendElements(mCoalescedEvents);
}
bool
PointerEvent::ShouldResistFingerprinting(CallerType aCallerType)
{
// There are four situations we don't need to spoof this pointer event.
// 1. This event is generated by scripts.
// 2. This event is a mouse pointer event.
// 3. The caller type is system.
// 4. The pref privcy.resistFingerprinting' is false, we fast return here
// since we don't need to do any QI of following codes.
// We don't need to check for the system group since pointer events won't be
// dispatched to the system group.
if (!mEvent->IsTrusted() ||
aCallerType == CallerType::System ||
!nsContentUtils::ShouldResistFingerprinting() ||
mEvent->AsPointerEvent()->inputSource ==
MouseEvent_Binding::MOZ_SOURCE_MOUSE) {
return false;
}
nsCOMPtr<nsIDocument> doc = GetDocument();
return doc && !nsContentUtils::IsChromeDoc(doc);
}
} // namespace dom
} // namespace mozilla

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

@ -45,21 +45,25 @@ public:
const PointerEventInit& aParam);
int32_t PointerId();
int32_t Width();
int32_t Height();
float Pressure();
float TangentialPressure();
int32_t TiltX();
int32_t TiltY();
int32_t Twist();
int32_t Width(CallerType aCallerType);
int32_t Height(CallerType aCallerType);
float Pressure(CallerType aCallerType);
float TangentialPressure(CallerType aCallerType);
int32_t TiltX(CallerType aCallerType);
int32_t TiltY(CallerType aCallerType);
int32_t Twist(CallerType aCallerType);
bool IsPrimary();
void GetPointerType(nsAString& aPointerType);
void GetPointerType(nsAString& aPointerType, CallerType aCallerType);
void GetCoalescedEvents(nsTArray<RefPtr<PointerEvent>>& aPointerEvents);
protected:
~PointerEvent() {}
private:
// This method returns the boolean to indicate whether spoofing pointer
// event for fingerprinting resistance.
bool ShouldResistFingerprinting(CallerType aCallerType);
nsTArray<RefPtr<PointerEvent>> mCoalescedEvents;
};

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

@ -14,13 +14,23 @@ interface WindowProxy;
interface PointerEvent : MouseEvent
{
readonly attribute long pointerId;
[NeedsCallerType]
readonly attribute long width;
[NeedsCallerType]
readonly attribute long 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 DOMString pointerType;
readonly attribute boolean isPrimary;
sequence<PointerEvent> getCoalescedEvents();