Source code

Revision control

Other Tools

1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* This Source Code Form is subject to the terms of the Mozilla Public
3
* License, v. 2.0. If a copy of the MPL was not distributed with this
4
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6
#ifndef __nsRFPService_h__
7
#define __nsRFPService_h__
8
9
#include "mozilla/Atomics.h"
10
#include "mozilla/EventForwards.h"
11
#include "mozilla/Mutex.h"
12
#include "mozilla/dom/Document.h"
13
#include "nsIObserver.h"
14
15
#include "nsDataHashtable.h"
16
#include "nsString.h"
17
18
// Defines regarding spoofed values of Navigator object. These spoofed values
19
// are returned when 'privacy.resistFingerprinting' is true.
20
// We decided to give different spoofed values according to the platform. The
21
// reason is that it is easy to detect the real platform. So there is no benefit
22
// for hiding the platform: it only brings breakages, like keyboard shortcuts
23
// won't work in macOS if we spoof it as a Windows platform.
24
#ifdef XP_WIN
25
# define SPOOFED_UA_OS "Windows NT 10.0; Win64; x64"
26
# define SPOOFED_APPVERSION "5.0 (Windows)"
27
# define SPOOFED_OSCPU "Windows NT 10.0; Win64; x64"
28
# define SPOOFED_PLATFORM "Win32"
29
#elif defined(XP_MACOSX)
30
# define SPOOFED_UA_OS "Macintosh; Intel Mac OS X 10.14"
31
# define SPOOFED_APPVERSION "5.0 (Macintosh)"
32
# define SPOOFED_OSCPU "Intel Mac OS X 10.14"
33
# define SPOOFED_PLATFORM "MacIntel"
34
#elif defined(MOZ_WIDGET_ANDROID)
35
# define SPOOFED_UA_OS "Android 8.1; Mobile"
36
# define SPOOFED_APPVERSION "5.0 (Android 8.1)"
37
# define SPOOFED_OSCPU "Linux armv7l"
38
# define SPOOFED_PLATFORM "Linux armv7l"
39
#else
40
// For Linux and other platforms, like BSDs, SunOS and etc, we will use Linux
41
// platform.
42
# define SPOOFED_UA_OS "X11; Linux x86_64"
43
# define SPOOFED_APPVERSION "5.0 (X11)"
44
# define SPOOFED_OSCPU "Linux x86_64"
45
# define SPOOFED_PLATFORM "Linux x86_64"
46
#endif
47
48
#define SPOOFED_APPNAME "Netscape"
49
#define LEGACY_BUILD_ID "20181001000000"
50
#define LEGACY_UA_GECKO_TRAIL "20100101"
51
52
#define SPOOFED_POINTER_INTERFACE MouseEvent_Binding::MOZ_SOURCE_MOUSE
53
54
// For the HTTP User-Agent header, we use a simpler set of spoofed values
55
// that do not reveal the specific desktop platform.
56
#if defined(MOZ_WIDGET_ANDROID)
57
# define SPOOFED_HTTP_UA_OS "Android 6.0; Mobile"
58
#else
59
# define SPOOFED_HTTP_UA_OS "Windows NT 10.0"
60
#endif
61
62
// Forward declare LRUCache, defined in nsRFPService.cpp
63
class LRUCache;
64
65
namespace mozilla {
66
67
enum KeyboardLang { EN = 0x01 };
68
69
#define RFP_KEYBOARD_LANG_STRING_EN "en"
70
71
typedef uint8_t KeyboardLangs;
72
73
enum KeyboardRegion { US = 0x01 };
74
75
#define RFP_KEYBOARD_REGION_STRING_US "US"
76
77
typedef uint8_t KeyboardRegions;
78
79
// This struct has the information about how to spoof the keyboardEvent.code,
80
// keyboardEvent.keycode and modifier states.
81
struct SpoofingKeyboardCode {
82
CodeNameIndex mCode;
83
uint8_t mKeyCode;
84
Modifiers mModifierStates;
85
};
86
87
struct SpoofingKeyboardInfo {
88
KeyNameIndex mKeyIdx;
89
nsString mKey;
90
SpoofingKeyboardCode mSpoofingCode;
91
};
92
93
class KeyboardHashKey : public PLDHashEntryHdr {
94
public:
95
typedef const KeyboardHashKey& KeyType;
96
typedef const KeyboardHashKey* KeyTypePointer;
97
98
KeyboardHashKey(const KeyboardLangs aLang, const KeyboardRegions aRegion,
99
const KeyNameIndexType aKeyIdx, const nsAString& aKey)
100
: mLang(aLang), mRegion(aRegion), mKeyIdx(aKeyIdx), mKey(aKey) {}
101
102
explicit KeyboardHashKey(KeyTypePointer aOther)
103
: mLang(aOther->mLang),
104
mRegion(aOther->mRegion),
105
mKeyIdx(aOther->mKeyIdx),
106
mKey(aOther->mKey) {}
107
108
KeyboardHashKey(KeyboardHashKey&& aOther)
109
: PLDHashEntryHdr(std::move(aOther)),
110
mLang(std::move(aOther.mLang)),
111
mRegion(std::move(aOther.mRegion)),
112
mKeyIdx(std::move(aOther.mKeyIdx)),
113
mKey(std::move(aOther.mKey)) {}
114
115
~KeyboardHashKey() {}
116
117
bool KeyEquals(KeyTypePointer aOther) const {
118
return mLang == aOther->mLang && mRegion == aOther->mRegion &&
119
mKeyIdx == aOther->mKeyIdx && mKey == aOther->mKey;
120
}
121
122
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
123
124
static PLDHashNumber HashKey(KeyTypePointer aKey) {
125
PLDHashNumber hash = mozilla::HashString(aKey->mKey);
126
return mozilla::AddToHash(hash, aKey->mRegion, aKey->mKeyIdx, aKey->mLang);
127
}
128
129
enum { ALLOW_MEMMOVE = true };
130
131
KeyboardLangs mLang;
132
KeyboardRegions mRegion;
133
KeyNameIndexType mKeyIdx;
134
nsString mKey;
135
};
136
137
enum TimerPrecisionType { All = 1, RFPOnly = 2 };
138
139
class nsRFPService final : public nsIObserver {
140
public:
141
NS_DECL_ISUPPORTS
142
NS_DECL_NSIOBSERVER
143
144
static nsRFPService* GetOrCreate();
145
static bool IsResistFingerprintingEnabled();
146
static bool IsTimerPrecisionReductionEnabled(TimerPrecisionType aType);
147
static double TimerResolution();
148
149
enum TimeScale { Seconds = 1, MilliSeconds = 1000, MicroSeconds = 1000000 };
150
151
// The following Reduce methods can be called off main thread.
152
static double ReduceTimePrecisionAsUSecs(
153
double aTime, int64_t aContextMixin,
154
TimerPrecisionType aType = TimerPrecisionType::All);
155
static double ReduceTimePrecisionAsMSecs(
156
double aTime, int64_t aContextMixin,
157
TimerPrecisionType aType = TimerPrecisionType::All);
158
static double ReduceTimePrecisionAsSecs(
159
double aTime, int64_t aContextMixin,
160
TimerPrecisionType aType = TimerPrecisionType::All);
161
162
// Used by the JS Engine, as it doesn't know about the TimerPrecisionType enum
163
static double ReduceTimePrecisionAsUSecsWrapper(double aTime);
164
165
// Public only for testing purposes
166
static double ReduceTimePrecisionImpl(double aTime, TimeScale aTimeScale,
167
double aResolutionUSec,
168
int64_t aContextMixin,
169
TimerPrecisionType aType);
170
static nsresult RandomMidpoint(long long aClampedTimeUSec,
171
long long aResolutionUSec,
172
int64_t aContextMixin, long long* aMidpointOut,
173
uint8_t* aSecretSeed = nullptr);
174
175
// This method calculates the video resolution (i.e. height x width) based
176
// on the video quality (480p, 720p, etc).
177
static uint32_t CalculateTargetVideoResolution(uint32_t aVideoQuality);
178
179
// Methods for getting spoofed media statistics and the return value will
180
// depend on the video resolution.
181
static uint32_t GetSpoofedTotalFrames(double aTime);
182
static uint32_t GetSpoofedDroppedFrames(double aTime, uint32_t aWidth,
183
uint32_t aHeight);
184
static uint32_t GetSpoofedPresentedFrames(double aTime, uint32_t aWidth,
185
uint32_t aHeight);
186
187
// This method generates the spoofed value of User Agent.
188
static void GetSpoofedUserAgent(nsACString& userAgent, bool isForHTTPHeader);
189
190
/**
191
* This method for getting spoofed modifier states for the given keyboard
192
* event.
193
*
194
* @param aDoc [in] the owner's document for getting content
195
* language.
196
* @param aKeyboardEvent [in] the keyboard event that needs to be spoofed.
197
* @param aModifier [in] the modifier that needs to be spoofed.
198
* @param aOut [out] the spoofed state for the given modifier.
199
* @return true if there is a spoofed state for the modifier.
200
*/
201
static bool GetSpoofedModifierStates(
202
const mozilla::dom::Document* aDoc,
203
const WidgetKeyboardEvent* aKeyboardEvent, const Modifiers aModifier,
204
bool& aOut);
205
206
/**
207
* This method for getting spoofed code for the given keyboard event.
208
*
209
* @param aDoc [in] the owner's document for getting content
210
* language.
211
* @param aKeyboardEvent [in] the keyboard event that needs to be spoofed.
212
* @param aOut [out] the spoofed code.
213
* @return true if there is a spoofed code in the fake keyboard
214
* layout.
215
*/
216
static bool GetSpoofedCode(const dom::Document* aDoc,
217
const WidgetKeyboardEvent* aKeyboardEvent,
218
nsAString& aOut);
219
220
/**
221
* This method for getting spoofed keyCode for the given keyboard event.
222
*
223
* @param aDoc [in] the owner's document for getting content
224
* language.
225
* @param aKeyboardEvent [in] the keyboard event that needs to be spoofed.
226
* @param aOut [out] the spoofed keyCode.
227
* @return true if there is a spoofed keyCode in the fake
228
* keyboard layout.
229
*/
230
static bool GetSpoofedKeyCode(const mozilla::dom::Document* aDoc,
231
const WidgetKeyboardEvent* aKeyboardEvent,
232
uint32_t& aOut);
233
234
private:
235
nsresult Init();
236
237
nsRFPService() {}
238
239
~nsRFPService() {}
240
241
void UpdateTimers();
242
void UpdateRFPPref();
243
void StartShutdown();
244
245
void PrefChanged(const char* aPref);
246
static void PrefChanged(const char* aPref, void* aSelf);
247
248
static void MaybeCreateSpoofingKeyCodes(const KeyboardLangs aLang,
249
const KeyboardRegions aRegion);
250
static void MaybeCreateSpoofingKeyCodesForEnUS();
251
252
static void GetKeyboardLangAndRegion(const nsAString& aLanguage,
253
KeyboardLangs& aLocale,
254
KeyboardRegions& aRegion);
255
static bool GetSpoofedKeyCodeInfo(const mozilla::dom::Document* aDoc,
256
const WidgetKeyboardEvent* aKeyboardEvent,
257
SpoofingKeyboardCode& aOut);
258
259
static nsDataHashtable<KeyboardHashKey, const SpoofingKeyboardCode*>*
260
sSpoofingKeyboardCodes;
261
262
nsCString mInitialTZValue;
263
};
264
265
} // namespace mozilla
266
267
#endif /* __nsRFPService_h__ */