aboutsummaryrefslogblamecommitdiff
path: root/www/waterfox/files/patch-bug1429764
blob: 112692fd51ee92a794a8e37c9cdc4e4e84d69e22 (plain) (tree)














































































































































































































                                                                                                                                 
commit 6a927d435699
Author: Tom Ritter <tom@mozilla.com>
Date:   Fri Jan 12 13:36:04 2018 -0600

    Bug 1429764 - Do not call ReduceTimerPrecision twice for DOM Navigation timers. r=bkelly, r=timhuang, a=jcristau
    
    Bug 1429764 details a test failure that was asserting that the performance navigation
    timers were strictly increasing (or equal). fetchStart should have a timestamp before
    domainLookupStart.  But it didn't.
    
    The problem is two-fold.  This corrects the test and the issue by addressing one part
    of the problem, the second part of the problem needs to be written up in a new bug
    and addressed there. (That bug is not yet filed at writing, but see dependencies of
    1429764 in the future to find it.)
    
    The second, and underlying, problem is that calling ReduceTimerPrecision with the
    same value multiple times may continually reduce it. Meaning that the first you call
    it with, say, .75, (and a precision of .20), it will be reduced to .6. The second time
    you call it (with .6), instead of staying at .6 it will be reduced to .4. This is
    because floats are fuzzy. Inside ReduceTimerPrecision we are multiplying a decimal by
    a decimal, so while floor(.6 / .20)  should equal 3, sometimes it's actually 2.999...
    which gets floors to 2, gets multiplied again by .2, and which results in .4
    
    If that's the underlying problem, the first, and surface, problem is - why are we
    calling ReduceTimerPrecision multiple times? We shouldn't be. That's what this
    patch fixes.
    
    TimeStampToDOMHighResOrFetchStart will return either TimeStampToDOMHighRes() or
    FetchStartHighRes(). FetchStartHighRes() internally calls TimeStampToDOMHighRes
    and then ReduceTimerPrecision - this is where (some of) the two reduction calls
    happen - because TimeStampToDOMHighRes itself calls ReduceTimerPrecision also.
    
    I remove the ReduceTimerPrecision from TimeStampToDOMHighRes. FetchStartHighRes
    will now only call ReduceTimerPrecision once, at the end of the return.
    
    But we have to fix places we call TimeStampToDOMHighResOrFetchStart, because the
    callers of that function also call ReduceTimerPrecision. So if
    TimeStampToDOMHighResOrFetchStart returned FetchStartHighRes, we'd be calling
    ReduceTimerPrecision twice for those callers.
    
    So inside first off, we remove the outer call to ReduceTimerPrecision. that
    surrounds the 5 or so callsites of TimeStampToDOMHighResOrFetchStart. Then
    inside of TimeStampToDOMHighResOrFetchStart we return either FetchStartHighRes
    (which is has already called ReduceTimerPrecision) or we call
    ReduceTimerPrecision with the value.
    
    Now. TimeStampToDOMHighRes was used in more places than just FetchStartHighRes -
    there were several other places where we were doing double rounding, and this
    fixed those as well. AsyncOpenHighRes, WorkerStartHighRes, DomainLookupEndHighRes,
    ConnectStartHighRes, SecureConnectionStartHighRes, ConnectEndHighRes, and
    ResponseEndHighRes.
    
    MozReview-Commit-ID: K5nHql135rb
    
    --HG--
    extra : source : 17bf5819b42fa3b656f2d3c565bc4fb0ca050066
---
 dom/performance/PerformanceTiming.cpp              | 15 +++------
 dom/performance/PerformanceTiming.h                |  7 ++--
 .../resistfingerprinting/nsRFPService.cpp          | 38 +++++++++++++++++++---
 3 files changed, 42 insertions(+), 18 deletions(-)

diff --git dom/performance/PerformanceTiming.cpp dom/performance/PerformanceTiming.cpp
index 3d7e55a0c80f..f80d7f509a40 100644
--- dom/performance/PerformanceTiming.cpp
+++ dom/performance/PerformanceTiming.cpp
@@ -222,7 +222,7 @@ PerformanceTiming::RedirectStartHighRes()
       nsContentUtils::ShouldResistFingerprinting()) {
     return mZeroTime;
   }
-  return TimeStampToDOMHighResOrFetchStart(mRedirectStart);
+  return TimeStampToReducedDOMHighResOrFetchStart(mRedirectStart);
 }
 
 DOMTimeMilliSec
@@ -256,7 +256,7 @@ PerformanceTiming::RedirectEndHighRes()
       nsContentUtils::ShouldResistFingerprinting()) {
     return mZeroTime;
   }
-  return TimeStampToDOMHighResOrFetchStart(mRedirectEnd);
+  return TimeStampToReducedDOMHighResOrFetchStart(mRedirectEnd);
 }
 
 DOMTimeMilliSec
@@ -280,7 +280,7 @@ PerformanceTiming::DomainLookupStartHighRes()
       nsContentUtils::ShouldResistFingerprinting()) {
     return mZeroTime;
   }
-  return TimeStampToDOMHighResOrFetchStart(mDomainLookupStart);
+  return TimeStampToReducedDOMHighResOrFetchStart(mDomainLookupStart);
 }
 
 DOMTimeMilliSec
@@ -366,7 +366,7 @@ PerformanceTiming::RequestStartHighRes()
       nsContentUtils::ShouldResistFingerprinting()) {
     return mZeroTime;
   }
-  return TimeStampToDOMHighResOrFetchStart(mRequestStart);
+  return TimeStampToReducedDOMHighResOrFetchStart(mRequestStart);
 }
 
 DOMTimeMilliSec
@@ -386,7 +386,7 @@ PerformanceTiming::ResponseStartHighRes()
      (!mCacheReadStart.IsNull() && mCacheReadStart < mResponseStart)) {
     mResponseStart = mCacheReadStart;
   }
-  return TimeStampToDOMHighResOrFetchStart(mResponseStart);
+  return TimeStampToReducedDOMHighResOrFetchStart(mResponseStart);
 }
 
 DOMTimeMilliSec
diff --git dom/performance/PerformanceTiming.h dom/performance/PerformanceTiming.h
index 0558fc11d64e..9fba3210ef1d 100644
--- dom/performance/PerformanceTiming.h
+++ dom/performance/PerformanceTiming.h
@@ -68,10 +68,10 @@ public:
    *          page), if the given TimeStamp is valid. Otherwise, it will return
    *          the FetchStart timing value.
    */
-  inline DOMHighResTimeStamp TimeStampToDOMHighResOrFetchStart(TimeStamp aStamp)
+  inline DOMHighResTimeStamp TimeStampToReducedDOMHighResOrFetchStart(TimeStamp aStamp)
   {
     return (!aStamp.IsNull())
-        ? TimeStampToDOMHighRes(aStamp)
+        ? nsRFPService::ReduceTimePrecisionAsMSecs(TimeStampToDOMHighRes(aStamp))
         : FetchStartHighRes();
   }
 
diff --git toolkit/components/resistfingerprinting/nsRFPService.cpp toolkit/components/resistfingerprinting/nsRFPService.cpp
index 51552da69923..98857a764721 100644
--- toolkit/components/resistfingerprinting/nsRFPService.cpp
+++ toolkit/components/resistfingerprinting/nsRFPService.cpp
@@ -8,6 +8,7 @@
 #include <time.h>
 
 #include "mozilla/ClearOnShutdown.h"
+#include "mozilla/Logging.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
@@ -28,6 +29,10 @@
 
 using namespace mozilla;
 
+#ifdef DEBUG
+static mozilla::LazyLogModule gResistFingerprintingLog("nsResistFingerprinting");
+#endif
+
 #define RESIST_FINGERPRINTING_PREF "privacy.resistFingerprinting"
 #define PROFILE_INITIALIZED_TOPIC "profile-initial-state"
 
@@ -66,7 +71,13 @@ nsRFPService::ReduceTimePrecisionAsMSecs(double aTime)
     return aTime;
   }
   const double resolutionMSec = kResolutionUSec / 1000.0;
-  return floor(aTime / resolutionMSec) * resolutionMSec;
+  double ret = floor(aTime / resolutionMSec) * resolutionMSec;
+#if defined(DEBUG)
+  MOZ_LOG(gResistFingerprintingLog, LogLevel::Verbose,
+    ("Given: %.*f, Rounding with %.*f, Intermediate: %.*f, Got: %.*f",
+      DBL_DIG-1, aTime, DBL_DIG-1, resolutionMSec, DBL_DIG-1, floor(aTime / resolutionMSec), DBL_DIG-1, ret));
+#endif
+  return ret;
 }
 
 /* static */
@@ -76,7 +87,14 @@ nsRFPService::ReduceTimePrecisionAsUSecs(double aTime)
   if (!IsResistFingerprintingEnabled()) {
     return aTime;
   }
-  return floor(aTime / kResolutionUSec) * kResolutionUSec;
+  double ret = floor(aTime / kResolutionUSec) * kResolutionUSec;
+#if defined(DEBUG)
+  double tmp_kResolutionUSec = kResolutionUSec;
+  MOZ_LOG(gResistFingerprintingLog, LogLevel::Verbose,
+    ("Given: %.*f, Rounding with %.*f, Intermediate: %.*f, Got: %.*f",
+      DBL_DIG-1, aTime, DBL_DIG-1, tmp_kResolutionUSec, DBL_DIG-1, floor(aTime / tmp_kResolutionUSec), DBL_DIG-1, ret));
+#endif
+  return ret;
 }
 
 /* static */
@@ -90,10 +108,22 @@ nsRFPService::ReduceTimePrecisionAsSecs(double aTime)
     // The resolution is smaller than one sec.  Use the reciprocal to avoid
     // floating point error.
     const double resolutionSecReciprocal = 1000000.0 / kResolutionUSec;
-    return floor(aTime * resolutionSecReciprocal) / resolutionSecReciprocal;
+    double ret = floor(aTime * resolutionSecReciprocal) / resolutionSecReciprocal;
+#if defined(DEBUG)
+  MOZ_LOG(gResistFingerprintingLog, LogLevel::Verbose,
+    ("Given: %.*f, Reciprocal Rounding with %.*f, Intermediate: %.*f, Got: %.*f",
+      DBL_DIG-1, aTime, DBL_DIG-1, resolutionSecReciprocal, DBL_DIG-1, floor(aTime * resolutionSecReciprocal), DBL_DIG-1, ret));
+#endif
+    return ret;
   }
   const double resolutionSec = kResolutionUSec / 1000000.0;
-  return floor(aTime / resolutionSec) * resolutionSec;
+  double ret = floor(aTime / resolutionSec) * resolutionSec;
+#if defined(DEBUG)
+  MOZ_LOG(gResistFingerprintingLog, LogLevel::Verbose,
+    ("Given: %.*f, Rounding with %.*f, Intermediate: %.*f, Got: %.*f",
+      DBL_DIG-1, aTime, DBL_DIG-1, resolutionSec, DBL_DIG-1, floor(aTime / resolutionSec), DBL_DIG-1, ret));
+#endif
+  return ret;
 }
 
 nsresult