/src/mozilla-central/toolkit/components/resistfingerprinting/nsRFPService.h
Line | Count | Source (jump to first uncovered line) |
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 "nsIDocument.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 won't |
23 | | // work in MAC OS if we spoof it as a window platform. |
24 | | #ifdef XP_WIN |
25 | | #define SPOOFED_UA_OS "Windows NT 6.1; Win64; x64" |
26 | | #define SPOOFED_APPVERSION "5.0 (Windows)" |
27 | | #define SPOOFED_OSCPU "Windows NT 6.1; Win64; x64" |
28 | | #define SPOOFED_PLATFORM "Win32" |
29 | | #elif defined(XP_MACOSX) |
30 | | #define SPOOFED_UA_OS "Macintosh; Intel Mac OS X 10.13" |
31 | | #define SPOOFED_APPVERSION "5.0 (Macintosh)" |
32 | | #define SPOOFED_OSCPU "Intel Mac OS X 10.13" |
33 | | #define SPOOFED_PLATFORM "MacIntel" |
34 | | #elif defined(MOZ_WIDGET_ANDROID) |
35 | | #define SPOOFED_UA_OS "Android 6.0; Mobile" |
36 | | #define SPOOFED_APPVERSION "5.0 (Android 6.0)" |
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 | 1 | #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 | 1 | #define LEGACY_BUILD_ID "20100101" |
50 | | |
51 | | // Forward declare LRUCache, defined in nsRFPService.cpp |
52 | | class LRUCache; |
53 | | |
54 | | namespace mozilla { |
55 | | |
56 | | enum KeyboardLang { |
57 | | EN = 0x01 |
58 | | }; |
59 | | |
60 | 0 | #define RFP_KEYBOARD_LANG_STRING_EN "en" |
61 | | |
62 | | typedef uint8_t KeyboardLangs; |
63 | | |
64 | | enum KeyboardRegion { |
65 | | US = 0x01 |
66 | | }; |
67 | | |
68 | 0 | #define RFP_KEYBOARD_REGION_STRING_US "US" |
69 | | |
70 | | typedef uint8_t KeyboardRegions; |
71 | | |
72 | | // This struct has the information about how to spoof the keyboardEvent.code, |
73 | | // keyboardEvent.keycode and modifier states. |
74 | | struct SpoofingKeyboardCode |
75 | | { |
76 | | CodeNameIndex mCode; |
77 | | uint8_t mKeyCode; |
78 | | Modifiers mModifierStates; |
79 | | }; |
80 | | |
81 | | struct SpoofingKeyboardInfo |
82 | | { |
83 | | KeyNameIndex mKeyIdx; |
84 | | nsString mKey; |
85 | | SpoofingKeyboardCode mSpoofingCode; |
86 | | }; |
87 | | |
88 | | class KeyboardHashKey : public PLDHashEntryHdr |
89 | | { |
90 | | public: |
91 | | typedef const KeyboardHashKey& KeyType; |
92 | | typedef const KeyboardHashKey* KeyTypePointer; |
93 | | |
94 | | KeyboardHashKey(const KeyboardLangs aLang, |
95 | | const KeyboardRegions aRegion, |
96 | | const KeyNameIndexType aKeyIdx, |
97 | | const nsAString &aKey) |
98 | | : mLang(aLang) |
99 | | , mRegion(aRegion) |
100 | | , mKeyIdx(aKeyIdx) |
101 | | , mKey(aKey) |
102 | 0 | {} |
103 | | |
104 | | explicit KeyboardHashKey(KeyTypePointer aOther) |
105 | | : mLang(aOther->mLang) |
106 | | , mRegion(aOther->mRegion) |
107 | | , mKeyIdx(aOther->mKeyIdx) |
108 | | , mKey(aOther->mKey) |
109 | 0 | {} |
110 | | |
111 | | KeyboardHashKey(KeyboardHashKey&& aOther) |
112 | | : PLDHashEntryHdr(std::move(aOther)) |
113 | | , mLang(std::move(aOther.mLang)) |
114 | | , mRegion(std::move(aOther.mRegion)) |
115 | | , mKeyIdx(std::move(aOther.mKeyIdx)) |
116 | | , mKey(std::move(aOther.mKey)) |
117 | | {} |
118 | | |
119 | | ~KeyboardHashKey() |
120 | 0 | {} |
121 | | |
122 | | bool KeyEquals(KeyTypePointer aOther) const |
123 | 0 | { |
124 | 0 | return mLang == aOther->mLang && |
125 | 0 | mRegion == aOther->mRegion && |
126 | 0 | mKeyIdx == aOther->mKeyIdx && |
127 | 0 | mKey == aOther->mKey; |
128 | 0 | } |
129 | | |
130 | | static KeyTypePointer KeyToPointer(KeyType aKey) |
131 | 0 | { |
132 | 0 | return &aKey; |
133 | 0 | } |
134 | | |
135 | | static PLDHashNumber HashKey(KeyTypePointer aKey) |
136 | 0 | { |
137 | 0 | PLDHashNumber hash = mozilla::HashString(aKey->mKey); |
138 | 0 | return mozilla::AddToHash(hash, |
139 | 0 | aKey->mRegion, |
140 | 0 | aKey->mKeyIdx, |
141 | 0 | aKey->mLang); |
142 | 0 | } |
143 | | |
144 | | enum { ALLOW_MEMMOVE = true }; |
145 | | |
146 | | KeyboardLangs mLang; |
147 | | KeyboardRegions mRegion; |
148 | | KeyNameIndexType mKeyIdx; |
149 | | nsString mKey; |
150 | | }; |
151 | | |
152 | | enum TimerPrecisionType { |
153 | | All = 1, |
154 | | RFPOnly = 2 |
155 | | }; |
156 | | |
157 | | class nsRFPService final : public nsIObserver |
158 | | { |
159 | | public: |
160 | | NS_DECL_ISUPPORTS |
161 | | NS_DECL_NSIOBSERVER |
162 | | |
163 | | static nsRFPService* GetOrCreate(); |
164 | | static bool IsResistFingerprintingEnabled(); |
165 | | static bool IsTimerPrecisionReductionEnabled(TimerPrecisionType aType); |
166 | | static double TimerResolution(); |
167 | | |
168 | | enum TimeScale { |
169 | | Seconds = 1, |
170 | | MilliSeconds = 1000, |
171 | | MicroSeconds = 1000000 |
172 | | }; |
173 | | |
174 | | // The following Reduce methods can be called off main thread. |
175 | | static double ReduceTimePrecisionAsUSecs( |
176 | | double aTime, |
177 | | int64_t aContextMixin, |
178 | | TimerPrecisionType aType = TimerPrecisionType::All); |
179 | | static double ReduceTimePrecisionAsMSecs( |
180 | | double aTime, |
181 | | int64_t aContextMixin, |
182 | | TimerPrecisionType aType = TimerPrecisionType::All); |
183 | | static double ReduceTimePrecisionAsSecs( |
184 | | double aTime, |
185 | | int64_t aContextMixin, |
186 | | TimerPrecisionType aType = TimerPrecisionType::All); |
187 | | |
188 | | // Used by the JS Engine, as it doesn't know about the TimerPrecisionType enum |
189 | | static double ReduceTimePrecisionAsUSecsWrapper( |
190 | | double aTime); |
191 | | |
192 | | // Public only for testing purposes |
193 | | static double ReduceTimePrecisionImpl( |
194 | | double aTime, |
195 | | TimeScale aTimeScale, |
196 | | double aResolutionUSec, |
197 | | int64_t aContextMixin, |
198 | | TimerPrecisionType aType); |
199 | | static nsresult RandomMidpoint(long long aClampedTimeUSec, |
200 | | long long aResolutionUSec, |
201 | | int64_t aContextMixin, |
202 | | long long* aMidpointOut, |
203 | | uint8_t * aSecretSeed = nullptr); |
204 | | |
205 | | // This method calculates the video resolution (i.e. height x width) based |
206 | | // on the video quality (480p, 720p, etc). |
207 | | static uint32_t CalculateTargetVideoResolution(uint32_t aVideoQuality); |
208 | | |
209 | | // Methods for getting spoofed media statistics and the return value will |
210 | | // depend on the video resolution. |
211 | | static uint32_t GetSpoofedTotalFrames(double aTime); |
212 | | static uint32_t GetSpoofedDroppedFrames(double aTime, uint32_t aWidth, uint32_t aHeight); |
213 | | static uint32_t GetSpoofedPresentedFrames(double aTime, uint32_t aWidth, uint32_t aHeight); |
214 | | |
215 | | // This method generates the spoofed value of User Agent. |
216 | | static nsresult GetSpoofedUserAgent(nsACString &userAgent); |
217 | | |
218 | | /** |
219 | | * This method for getting spoofed modifier states for the given keyboard event. |
220 | | * |
221 | | * @param aDoc [in] the owner's document for getting content language. |
222 | | * @param aKeyboardEvent [in] the keyboard event that needs to be spoofed. |
223 | | * @param aModifier [in] the modifier that needs to be spoofed. |
224 | | * @param aOut [out] the spoofed state for the given modifier. |
225 | | * @return true if there is a spoofed state for the modifier. |
226 | | */ |
227 | | static bool GetSpoofedModifierStates(const nsIDocument* aDoc, |
228 | | const WidgetKeyboardEvent* aKeyboardEvent, |
229 | | const Modifiers aModifier, |
230 | | bool& aOut); |
231 | | |
232 | | /** |
233 | | * This method for getting spoofed code for the given keyboard event. |
234 | | * |
235 | | * @param aDoc [in] the owner's document for getting content language. |
236 | | * @param aKeyboardEvent [in] the keyboard event that needs to be spoofed. |
237 | | * @param aOut [out] the spoofed code. |
238 | | * @return true if there is a spoofed code in the fake keyboard layout. |
239 | | */ |
240 | | static bool GetSpoofedCode(const nsIDocument* aDoc, |
241 | | const WidgetKeyboardEvent* aKeyboardEvent, |
242 | | nsAString& aOut); |
243 | | |
244 | | /** |
245 | | * This method for getting spoofed keyCode for the given keyboard event. |
246 | | * |
247 | | * @param aDoc [in] the owner's document for getting content language. |
248 | | * @param aKeyboardEvent [in] the keyboard event that needs to be spoofed. |
249 | | * @param aOut [out] the spoofed keyCode. |
250 | | * @return true if there is a spoofed keyCode in the fake keyboard layout. |
251 | | */ |
252 | | static bool GetSpoofedKeyCode(const nsIDocument* aDoc, |
253 | | const WidgetKeyboardEvent* aKeyboardEvent, |
254 | | uint32_t& aOut); |
255 | | |
256 | | private: |
257 | | nsresult Init(); |
258 | | |
259 | 3 | nsRFPService() {} |
260 | | |
261 | 0 | ~nsRFPService() {} |
262 | | |
263 | | void UpdateTimers(); |
264 | | void UpdateRFPPref(); |
265 | | void StartShutdown(); |
266 | | |
267 | | void PrefChanged(const char* aPref); |
268 | | |
269 | | static void MaybeCreateSpoofingKeyCodes(const KeyboardLangs aLang, |
270 | | const KeyboardRegions aRegion); |
271 | | static void MaybeCreateSpoofingKeyCodesForEnUS(); |
272 | | |
273 | | static void GetKeyboardLangAndRegion(const nsAString& aLanguage, |
274 | | KeyboardLangs& aLang, |
275 | | KeyboardRegions& aRegion); |
276 | | static bool GetSpoofedKeyCodeInfo(const nsIDocument* aDoc, |
277 | | const WidgetKeyboardEvent* aKeyboardEvent, |
278 | | SpoofingKeyboardCode& aOut); |
279 | | |
280 | | static Atomic<bool, Relaxed> sPrivacyResistFingerprinting; |
281 | | static Atomic<bool, Relaxed> sPrivacyTimerPrecisionReduction; |
282 | | |
283 | | static nsDataHashtable<KeyboardHashKey, const SpoofingKeyboardCode*>* sSpoofingKeyboardCodes; |
284 | | |
285 | | nsCString mInitialTZValue; |
286 | | }; |
287 | | |
288 | | } // mozilla namespace |
289 | | |
290 | | #endif /* __nsRFPService_h__ */ |