Coverage Report

Created: 2018-09-25 14:53

/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__ */