Bug 1432429 Switch Fuzzyfox over to a pref 11/14 draft
authorTom Ritter <tom@mozilla.com>
Fri, 06 Jul 2018 11:22:28 -0500
changeset 826372 bb3e4c3816e1b74dc4d62ac8ed25bb674486988a
parent 826371 f5a3cfac2dc8ceebba4dfe9de210687333d8e84f
child 826373 02044aa25c75fb9532de6beca4a6613a6ffe6a84
push id118310
push userbmo:tom@mozilla.com
push dateFri, 03 Aug 2018 18:22:17 +0000
bugs1432429
milestone62.0a1
Bug 1432429 Switch Fuzzyfox over to a pref 11/14 MozReview-Commit-ID: LSMpcxQ5IN3
browser/app/profile/firefox.js
modules/libpref/init/all.js
mozglue/misc/TimeStamp.cpp
mozglue/misc/TimeStamp.h
toolkit/components/fuzzyfox/Fuzzyfox.cpp
toolkit/components/fuzzyfox/Fuzzyfox.h
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1203,16 +1203,18 @@ pref("services.sync.prefs.sync.privacy.c
 pref("services.sync.prefs.sync.privacy.clearOnShutdown.cookies", true);
 pref("services.sync.prefs.sync.privacy.clearOnShutdown.downloads", true);
 pref("services.sync.prefs.sync.privacy.clearOnShutdown.formdata", true);
 pref("services.sync.prefs.sync.privacy.clearOnShutdown.history", true);
 pref("services.sync.prefs.sync.privacy.clearOnShutdown.offlineApps", true);
 pref("services.sync.prefs.sync.privacy.clearOnShutdown.sessions", true);
 pref("services.sync.prefs.sync.privacy.clearOnShutdown.siteSettings", true);
 pref("services.sync.prefs.sync.privacy.donottrackheader.enabled", true);
+pref("services.sync.prefs.sync.privacy.fuzzyfox.enabled", true);
+pref("services.sync.prefs.sync.privacy.fuzzyfox.clockgrainus", true);
 pref("services.sync.prefs.sync.privacy.sanitize.sanitizeOnShutdown", true);
 pref("services.sync.prefs.sync.privacy.trackingprotection.enabled", true);
 pref("services.sync.prefs.sync.privacy.trackingprotection.pbmode.enabled", true);
 pref("services.sync.prefs.sync.privacy.resistFingerprinting", true);
 pref("services.sync.prefs.sync.privacy.reduceTimerPrecision", true);
 pref("services.sync.prefs.sync.privacy.resistFingerprinting.reduceTimerPrecision.microseconds", true);
 pref("services.sync.prefs.sync.privacy.resistFingerprinting.reduceTimerPrecision.jitter", true);
 pref("services.sync.prefs.sync.security.OCSP.enabled", true);
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -1294,16 +1294,20 @@ pref("privacy.firstparty.isolate.restric
 // Anti-fingerprinting, disabled by default
 pref("privacy.resistFingerprinting", false);
 // We automatically decline canvas permission requests if they are not initiated
 // from user input. Just in case that breaks something, we allow the user to revert
 // this behaior with this obscure pref. We do not intend to support this long term.
 // If you do set it, to work around some broken website, please file a bug with
 // information so we can understand why it is needed.
 pref("privacy.resistFingerprinting.autoDeclineNoUserInputCanvasPrompts", true);
+
+pref("privacy.fuzzyfox.enabled", false);
+pref("privacy.fuzzyfox.clockgrainus", 100);
+
 // A subset of Resist Fingerprinting protections focused specifically on timers for testing
 // This affects the Animation API, the performance APIs, Date.getTime, Event.timestamp,
 //   File.lastModified, audioContext.currentTime, canvas.captureStream.currentTime
 pref("privacy.reduceTimerPrecision", true);
 // Dynamically tune the resolution of the timer reduction for both of the two above prefs
 pref("privacy.resistFingerprinting.reduceTimerPrecision.microseconds", 1000);
 // Enable jittering the clock one precision value forward
 pref("privacy.resistFingerprinting.reduceTimerPrecision.jitter", true);
--- a/mozglue/misc/TimeStamp.cpp
+++ b/mozglue/misc/TimeStamp.cpp
@@ -41,16 +41,30 @@ struct TimeStampInitialization
   };
 
   ~TimeStampInitialization()
   {
     TimeStamp::Shutdown();
   };
 };
 
+static bool sFuzzyfoxEnabled;
+
+/* static */ bool
+TimeStamp::GetFuzzyfoxEnabled()
+{
+  return sFuzzyfoxEnabled;
+}
+
+/* static */ void
+TimeStamp::SetFuzzyfoxEnabled(bool aValue)
+{
+  sFuzzyfoxEnabled = aValue;
+}
+
 #ifdef XP_WIN
 static Atomic<uint64_t> sCanonicalGTC;
 static Atomic<uint64_t> sCanonicalQPC;
 static Atomic<bool> sCanonicalHasQPC;
 #else
 static Atomic<uint64_t> sCanonicalNow;
 #endif
 
@@ -106,28 +120,35 @@ TimeStamp::RecordProcessRestart()
 MFBT_API TimeStamp
 TimeStamp::NowFuzzy(TimeStampValue aValue)
 {
 #ifdef XP_WIN
   TimeStampValue canonicalNow = TimeStampValue(sCanonicalGTC, sCanonicalQPC, sCanonicalHasQPC);
 #else
   TimeStampValue canonicalNow = sCanonicalNow;
 #endif
-  if(canonicalNow > 0) {
+  if (TimeStamp::GetFuzzyfoxEnabled()) {
+    if(MOZ_LIKELY(canonicalNow > 0)) {
+      return TimeStamp(canonicalNow, true);
+    }
+  }
+  // When we disable Fuzzyfox, time may goes backwards, so we need to make sure
+  // we don't do that.
+  else if (MOZ_UNLIKELY(canonicalNow > aValue)) {
     return TimeStamp(canonicalNow, true);
   }
 
   return TimeStamp(aValue);
 }
 
 MFBT_API void
 TimeStamp::UpdateFuzzyTimeStamp(TimeStamp aValue)
 {
   #ifdef XP_WIN
   sCanonicalGTC = aValue.mValue.mGTC;
   sCanonicalQPC = aValue.mValue.mQPC;
   sCanonicalHasQPC = aValue.mValue.mHasQPC;
   #else
-  sCanonicalNow = aValue;
+  sCanonicalNow = aValue.mValue;
   #endif
 }
 
 } // namespace mozilla
--- a/mozglue/misc/TimeStamp.h
+++ b/mozglue/misc/TimeStamp.h
@@ -451,16 +451,18 @@ public:
    * |if (timestamp) { ... }|
    */
   explicit operator bool() const
   {
     return mValue != 0;
   }
 
   bool UsedCanonicalNow() const { return mUsedCanonicalNow; }
+  static MFBT_API bool GetFuzzyfoxEnabled();
+  static MFBT_API void SetFuzzyfoxEnabled(bool aValue);
 
   /**
    * Return a timestamp reflecting the current elapsed system time. This
    * is monotonically increasing (i.e., does not decrease) over the
    * lifetime of this process' XPCOM session.
    *
    * Now() is trying to ensure the best possible precision on each platform,
    * at least one millisecond.
--- a/toolkit/components/fuzzyfox/Fuzzyfox.cpp
+++ b/toolkit/components/fuzzyfox/Fuzzyfox.cpp
@@ -1,87 +1,177 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "Fuzzyfox.h"
 #include "mozilla/Logging.h"
+#include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/SystemGroup.h"
 #include "mozilla/TimeStamp.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIObserverService.h"
-#include "nsISupportsPrimitives.h"
+#include "nsIPrefBranch.h"
+#include "nsIPrefService.h"
+#include "nsServiceManagerUtils.h"
 #include "prrng.h"
 #include "prtime.h"
 
 // For usleep/Sleep & QueryPerformanceFrequency
 #ifdef XP_WIN
 #include <windows.h>
 #else
 #include <unistd.h>
 #endif
 
 using namespace mozilla;
 
 static LazyLogModule sFuzzyfoxLog("Fuzzyfox");
 
-#define PT_STATIC_CLOCK_GRAIN 80
-#define PT_DURATION_CENTER 100000
-
 #define US_TO_NS(x) ((x)*1000)
 #define NS_TO_US(x) ((x)/1000)
 
 #ifdef LOG
 #undef LOG
 #endif
 
 #define LOG(level, args) MOZ_LOG(sFuzzyfoxLog, mozilla::LogLevel::level, args)
 
+#define FUZZYFOX_ENABLED_PREF             "privacy.fuzzyfox.enabled"
+#define FUZZYFOX_ENABLED_PREF_DEFAULT     false
+#define FUZZYFOX_CLOCKGRAIN_PREF          "privacy.fuzzyfox.clockgrainus"
+#define FUZZYFOX_CLOCKGRAIN_PREF_DEFAULT  100
+
+Atomic<bool, Relaxed>     Fuzzyfox::sFuzzyfoxEnabledPrefMapped;
+Atomic<uint32_t, Relaxed> Fuzzyfox::sFuzzyfoxClockGrain;
+
+NS_IMPL_ISUPPORTS_INHERITED(Fuzzyfox, Runnable, nsIObserver)
+
 /* static */ void
 Fuzzyfox::Start()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   RefPtr<Fuzzyfox> r = new Fuzzyfox();
   SystemGroup::Dispatch(TaskCategory::Other, r.forget());
 }
 
 Fuzzyfox::Fuzzyfox()
   : Runnable("Fuzzyfox")
-  , mStartTime(ActualTime())
+  , mSanityCheck(false)
+  , mStartTime(0)
   , mDuration(PickDuration())
   , mTickType(eUptick)
 {
   MOZ_ASSERT(NS_IsMainThread());
+
+  // [[ I originally ran this after observing profile-after-change, but
+  // it turned out that this contructor was getting called _after_ that
+  // event had already fired. ]]
+  Preferences::AddAtomicBoolVarCache(&sFuzzyfoxEnabledPrefMapped,
+                                     FUZZYFOX_ENABLED_PREF,
+                                     FUZZYFOX_ENABLED_PREF_DEFAULT);
+  Preferences::AddAtomicUintVarCache(&sFuzzyfoxClockGrain,
+                                     FUZZYFOX_CLOCKGRAIN_PREF,
+                                     FUZZYFOX_CLOCKGRAIN_PREF_DEFAULT);
+
+  LOG(Info, ("PT(%p) Created Fuzzyfox, sFuzzyfoxEnabled is now %s \n",
+         this, (sFuzzyfoxEnabledPrefMapped ? "enabled" : "disabled")));
+
+  TimeStamp::SetFuzzyfoxEnabled(sFuzzyfoxEnabledPrefMapped);
+
+  // Should I see if these fail? And do what?
+  nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
+  prefs->AddObserver(FUZZYFOX_ENABLED_PREF, this, false);
+  prefs->AddObserver(FUZZYFOX_CLOCKGRAIN_PREF, this, false);
 }
 
 Fuzzyfox::~Fuzzyfox() = default;
 
 NS_IMETHODIMP
+Fuzzyfox::Observe(nsISupports* aObject, const char* aTopic,
+                      const char16_t* aMessage)
+{
+  if (!strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic)) {
+    NS_ConvertUTF16toUTF8 pref(aMessage);
+
+    if (pref.EqualsLiteral(FUZZYFOX_ENABLED_PREF)) {
+      LOG(Info, ("PT(%p) Observed a pref change, sFuzzyfoxEnabled is now %s \n",
+         this, (sFuzzyfoxEnabledPrefMapped ? "enabled" : "disabled")));
+
+
+      TimeStamp::SetFuzzyfoxEnabled(sFuzzyfoxEnabledPrefMapped);
+
+
+      if (TimeStamp::GetFuzzyfoxEnabled()) {
+        // Queue a runnable
+        nsCOMPtr<nsIRunnable> r = this;
+        SystemGroup::Dispatch(TaskCategory::Other, r.forget());
+      } else {
+        mStartTime = 0;
+        mTickType = eUptick;
+        mSanityCheck = false;
+      }
+    }
+  }
+  return NS_OK;
+}
 
 #define DISPATCH_AND_RETURN() \
   nsCOMPtr<nsIRunnable> r = this; \
   SystemGroup::Dispatch(TaskCategory::Other, r.forget()); \
   return NS_OK
 
 NS_IMETHODIMP
 Fuzzyfox::Run()
 {
   MOZ_ASSERT(NS_IsMainThread());
+  if (!TimeStamp::GetFuzzyfoxEnabled()) {
+    LOG(Info, ("[FuzzyfoxEvent] PT(%p) Fuzzyfox is shut down, doing nothing \n", this));
+    return NS_OK;
+  }
+
+  if (mStartTime == 0) {
+    // This is the first time we are running afer enabling FuzzyFox. We need
+    // to prevent time from going backwards, so for the first run we round the time up
+    // to the next grain.
+    mStartTime = CeilToGrain(ActualTime());
+    TimeStamp newTimeStamp = CeilToGrain(TimeStamp::NowReally());
+    Fuzzyfox::UpdateClocks(mStartTime, newTimeStamp);
+
+    mSanityCheck = true;
+    LOG(Info, ("[FuzzyfoxEvent] PT(%p) Going to start Fuzzyfox, queuing up the job \n",
+       this));
+
+    DISPATCH_AND_RETURN();
+  }
 
   // We need to check how long its been since we ran
   uint64_t endTime = ActualTime();
 
   uint64_t remaining = 0;
   uint64_t durationCount = 1;
 
   // Pick the amount to sleep
+  if (endTime < mStartTime) {
+    // This can only happen if we just enabled FuzzyFox, rounded up, and then re-ran the
+    // runnable before we advanced to the next grain.
+    // If that happens, then repeat the current time.
+    // We use mSanityCheck just to be sure (and will eventually remove it.)
+    MOZ_ASSERT(mSanityCheck);
+    LOG(Debug, ("[FuzzyfoxEvent] PT(%p) endTime < mStartTime mStartTime %" PRIu64 " endTime %" PRIu64 " \n",
+         this, mStartTime, endTime));
+
+    mSanityCheck = true;
+    DISPATCH_AND_RETURN();
+  }
+  
   if ((endTime - mStartTime) > mDuration) {
     // We ran over our budget!
     uint64_t over = (endTime - mStartTime) - mDuration;
     LOG(Verbose, ("[FuzzyfoxEvent] PT(%p) Overran budget of %" PRIu32 " by %" PRIu64 " \n",
          this, mDuration, over));
 
     //TODO: this should probably influence uptick/downtick stuff, and it doesn't
     uint64_t nextDuration = PickDuration();
@@ -92,30 +182,32 @@ Fuzzyfox::Run()
     }
 
     remaining = nextDuration - over;
   } else {
     // Didn't go over budget
     remaining = mDuration - (endTime - mStartTime);
     LOG(Verbose, ("[FuzzyfoxEvent] PT(%p) Finishing budget of %" PRIu32 " with %" PRIu64 " \n",
         this, mDuration, remaining));
-
   }
+  mSanityCheck = false;
 
   // Sleep for now
 #ifdef XP_WIN
   Sleep(remaining);
 #else
   usleep(remaining);
 #endif
 
   //TODO we slept extra long almost certainly, what do we do about that?
 
   // Update clocks (and fire pending events etc)
-  UpdateClocks();
+  uint64_t newTime = FloorToGrain(ActualTime());
+  TimeStamp newTimeStamp = FloorToGrain(TimeStamp::NowReally());
+  UpdateClocks(newTime, newTimeStamp);
 
   // Reset values
   mTickType = mTickType == eUptick ? eDowntick : eUptick;
   mStartTime = ActualTime();
   mDuration = PickDuration();
 
   DISPATCH_AND_RETURN();
 }
@@ -130,30 +222,27 @@ Fuzzyfox::ActualTime()
 }
 
 uint64_t
 Fuzzyfox::PickDuration()
 {
   // TODO: Fix to be secure
   long int rval = rand();
 
-  // We want uniform distribution from 1->PT_DURATION_CENTER*2
-  // so that the mean is PT_DURATION_CENTER
-  return 1 + (rval % (PT_DURATION_CENTER * 2));
+  // Avoid divide by zero errors
+  uint32_t duration = sFuzzyfoxClockGrain <= 0 ? 1 : sFuzzyfoxClockGrain;
+
+  // We want uniform distribution from 1->duration*2
+  // so that the mean is duration
+  return 1 + (rval % (duration * 2));
 }
 
 void
-Fuzzyfox::UpdateClocks()
+Fuzzyfox::UpdateClocks(uint64_t aNewTime, TimeStamp aNewTimeStamp)
 {
-  uint64_t time = ActualTime();
-  TimeStamp timestamp = TimeStamp::NowReally();
-
-  uint64_t newTime = RoundToGrain(time);
-  TimeStamp newTimeStamp = RoundToGrain(timestamp);
-
   // newTime is the new canonical time for this scope!
   #ifndef XP_WIN
   LOG(Verbose, ("[Time] New time is %" PRIu64 " (compare to %" PRIu64 ") and timestamp is %" PRIu64 " (compare to %" PRIu64 ")\n",
     aNewTime, ActualTime(), aNewTimeStamp.mValue, TimeStamp::NowReally().mValue));
   #else
   LOG(Verbose, ("[Time] New time is %" PRIu64 " (compare to %" PRIu64 ") \n", aNewTime, ActualTime()));
   #endif
 
@@ -163,57 +252,100 @@ Fuzzyfox::UpdateClocks()
     return;
   }
 
   // Event firings on occur on downticks and have no data
   if (mTickType == eDowntick) {
     os->NotifyObservers(nullptr, "fuzzyfox-fire-outbound", nullptr);
   }
 
-  nsCOMPtr<nsISupportsPRInt64> wrapper =
-    do_CreateInstance(NS_SUPPORTS_PRINT64_CONTRACTID);
-  if (NS_WARN_IF(!wrapper)) {
-    return;
+  if (!mTimeUpdateWrapper) {
+    mTimeUpdateWrapper = do_CreateInstance(NS_SUPPORTS_PRINT64_CONTRACTID);
+    if (NS_WARN_IF(!mTimeUpdateWrapper)) {
+      return;
+    }
   }
 
-  wrapper->SetData(newTime);
+  mTimeUpdateWrapper->SetData(aNewTime);
 
   // Clocks get the official 'realtime' time in microseconds
   // This happens on all ticks
-  os->NotifyObservers(wrapper, "fuzzyfox-update-clocks", nullptr);
+  os->NotifyObservers(mTimeUpdateWrapper, "fuzzyfox-update-clocks", nullptr);
 
   // Update the timestamp canonicaltime
-  TimeStamp::UpdateFuzzyTimeStamp(newTimeStamp);
+  TimeStamp::UpdateFuzzyTimeStamp(aNewTimeStamp);
 }
 
 uint64_t
 Fuzzyfox::GetClockGrain()
 {
-  // Static for now
-  // Should be reading from some config probably
-  return PT_STATIC_CLOCK_GRAIN;
+  return sFuzzyfoxClockGrain;
+}
+
+
+/*
+ * FloorToGrain accepts a timestamp in microsecond precision
+ * and returns it in microseconds, rounded down to the nearest
+ * ClockGrain value.
+ */
+uint64_t
+Fuzzyfox::FloorToGrain(uint64_t aValue)
+{
+  return aValue - (aValue % GetClockGrain());
 }
 
-uint64_t
-Fuzzyfox::RoundToGrain(uint64_t aValue)
+
+/*
+ * FloorToGrain accepts a timestamp and returns it, rounded down
+ * to the nearest ClockGrain value.
+ */
+TimeStamp
+Fuzzyfox::FloorToGrain(TimeStamp aValue)
 {
+#ifdef XP_WIN
+  // grain is in us
   uint64_t grain = GetClockGrain();
-  return US_TO_NS(aValue - (aValue % grain));
+  // GTC and QPS are stored in |mt| and need to be converted to
+  uint64_t GTC = mt2ms(aValue.mValue.mGTC) * 1000;
+  uint64_t QPC = mt2ms(aValue.mValue.mQPC) * 1000;
+
+  return TimeStamp(TimeStampValue(
+    ms2mt((GTC - (GTC % grain)) / 1000),
+    ms2mt((QPC - (QPC % grain)) / 1000),
+    aValue.mValue.mHasQPC), true);
+#else
+  return TimeStamp(US_TO_NS(FloorToGrain(NS_TO_US(aValue.mValue))));
+#endif
 }
 
+/*
+ * CeilToGrain accepts a timestamp in microsecond precision
+ * and returns it in microseconds, rounded up to the nearest
+ * ClockGrain value.
+ */
+uint64_t
+Fuzzyfox::CeilToGrain(uint64_t aValue)
+{
+  return (aValue / GetClockGrain()) * GetClockGrain();
+}
+
+/*
+ * CeilToGrain accepts a timestamp and returns it, rounded up
+ * to the nearest ClockGrain value.
+ */
 TimeStamp
-Fuzzyfox::RoundToGrain(TimeStamp aValue)
+Fuzzyfox::CeilToGrain(TimeStamp aValue)
 {
 #ifdef XP_WIN
   // grain is in us
   uint64_t grain = GetClockGrain();
   // GTC and QPS are stored in |mt| and need to be converted
-  uint64_t GTC = mt2ms(aValue.mValue.mGTC);
-  uint64_t QPC = mt2ms(aValue.mValue.mQPC);
+  uint64_t GTC = mt2ms(aValue.mValue.mGTC) * 1000;
+  uint64_t QPC = mt2ms(aValue.mValue.mQPC) * 1000;
 
   return TimeStamp(TimeStampValue(
-    ms2mt(GTC - (GTC % grain)),
-    ms2mt(GTC - (GTC % grain)),
+    ms2mt(((GTC / grain) * grain) / 1000),
+    ms2mt(((QPC / grain) * grain) / 1000),
     aValue.mValue.mHasQPC), true);
 #else
-  return TimeStamp(RoundToGrain(aValue.mValue));
+  return TimeStamp(US_TO_NS(CeilToGrain(NS_TO_US(aValue.mValue))));
 #endif
 }
\ No newline at end of file
--- a/toolkit/components/fuzzyfox/Fuzzyfox.h
+++ b/toolkit/components/fuzzyfox/Fuzzyfox.h
@@ -2,58 +2,78 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_Fuzzyfox_h
 #define mozilla_Fuzzyfox_h
 
+#include "nsIObserver.h"
+#include "nsISupportsPrimitives.h"
 #include "nsThreadUtils.h"
 #include "mozilla/TimeStamp.h"
 
 namespace mozilla {
 
-class Fuzzyfox final : public Runnable
+class Fuzzyfox final : public Runnable, public nsIObserver
 {
 public:
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_NSIOBSERVER
+
   static void
   Start();
 
   NS_IMETHOD
   Run() override;
 
+  static bool
+  Enabled();
+
 private:
   Fuzzyfox();
   ~Fuzzyfox();
 
   uint64_t
   ActualTime();
 
   uint64_t
   PickDuration();
 
   void
-  UpdateClocks();
+  UpdateClocks(uint64_t aNewTime, TimeStamp aNewTimeStamp);
 
   uint64_t
   GetClockGrain();
 
   uint64_t
-  RoundToGrain(uint64_t aValue);
+  FloorToGrain(uint64_t aValue);
 
   TimeStamp
-  RoundToGrain(TimeStamp aValue);
+  FloorToGrain(TimeStamp aValue);
+
+  uint64_t
+  CeilToGrain(uint64_t aValue);
 
+  TimeStamp
+  CeilToGrain(TimeStamp aValue);
+
+  bool mSanityCheck;
   uint64_t mStartTime;
   uint32_t mDuration;
 
   enum Tick {
     eUptick,
     eDowntick,
   };
 
   Tick mTickType;
+
+  nsCOMPtr<nsISupportsPRInt64> mTimeUpdateWrapper = nullptr;
+
+  static Atomic<bool, Relaxed> sFuzzyfoxEnabledPrefMapped;
+  static Atomic<uint32_t, Relaxed> sFuzzyfoxClockGrain;
 };
 
 } // mozilla namespace
 
 #endif /* mozilla_Fuzzyfox_h */