Bug 1430173 - Reduce the precision of all explicit clocks to 2ms. r=baku, a=RyanVM

Backport to ESR where we don't have the ResistFingerprinting component.

MozReview-Commit-ID: 9bjycHjR3SF

--HG--
extra : transplant_source : %EA%03%21%0A%E9%3F%8E%CD%7C%D79f%96%85%96%00%5D%7F%95X
This commit is contained in:
Tom Ritter 2018-02-20 12:18:30 -06:00 • committed by Roy Tam
commit c66f2e1613
14 changed files with 109 additions and 33 deletions

3
dom/base/File.cpp Normal file → Executable file
View file

@ -29,6 +29,7 @@
#include "nsStringStream.h" #include "nsStringStream.h"
#include "nsJSUtils.h" #include "nsJSUtils.h"
#include "nsPrintfCString.h" #include "nsPrintfCString.h"
#include "mozilla/TimerClamping.h"
#include "mozilla/SHA1.h" #include "mozilla/SHA1.h"
#include "mozilla/CheckedInt.h" #include "mozilla/CheckedInt.h"
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
@ -727,7 +728,7 @@ BlobImplBase::GetLastModified(ErrorResult& aRv)
mLastModificationDate = PR_Now(); mLastModificationDate = PR_Now();
} }
return mLastModificationDate / PR_USEC_PER_MSEC; return TimerClamping::ReduceUsTimeValue(mLastModificationDate) / PR_USEC_PER_MSEC;
} }
void void

4
dom/base/MultipartBlobImpl.cpp Normal file → Executable file
View file

@ -17,6 +17,7 @@
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "nsIScriptError.h" #include "nsIScriptError.h"
#include "nsIXPConnect.h" #include "nsIXPConnect.h"
#include "mozilla/TimerClamping.h"
#include <algorithm> #include <algorithm>
using namespace mozilla; using namespace mozilla;
@ -270,8 +271,7 @@ MultipartBlobImpl::SetLengthAndModifiedDate(ErrorResult& aRv)
// var x = new Date(); var f = new File(...); // var x = new Date(); var f = new File(...);
// x.getTime() < f.dateModified.getTime() // x.getTime() < f.dateModified.getTime()
// could fail. // could fail.
mLastModificationDate = mLastModificationDate = TimerClamping::ReduceUsTimeValue(lastModifiedSet ? lastModified * PR_USEC_PER_MSEC : JS_Now());
lastModifiedSet ? lastModified * PR_USEC_PER_MSEC : JS_Now();
} }
} }

35
dom/base/TimerClamping.cpp Executable file
View file

@ -0,0 +1,35 @@
/* -*- 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 "TimerClamping.h"
namespace mozilla {
/* static */
double
TimerClamping::ReduceSTimeValue(double aTime)
{
static const double maxResolutionS = .002;
return floor(aTime / maxResolutionS) * maxResolutionS;
}
/* static */
double
TimerClamping::ReduceMsTimeValue(double aTime)
{
static const double maxResolutionMs = 2;
return floor(aTime / maxResolutionMs) * maxResolutionMs;
}
/* static */
double
TimerClamping::ReduceUsTimeValue(double aTime)
{
static const double maxResolutionUs = 2000;
return floor(aTime / maxResolutionUs) * maxResolutionUs;
}
}

22
dom/base/TimerClamping.h Executable file
View file

@ -0,0 +1,22 @@
/* -*- 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/. */
#ifndef TimerClamping_h___
#define TimerClamping_h___
namespace mozilla {
class TimerClamping
{
public:
static double ReduceSTimeValue(double aTime);
static double ReduceMsTimeValue(double aTime);
static double ReduceUsTimeValue(double aTime);
};
}
#endif /* TimerClamping_h___ */

2
dom/base/moz.build Normal file → Executable file
View file

@ -143,6 +143,7 @@ EXPORTS.mozilla += [
'CORSMode.h', 'CORSMode.h',
'FeedWriterEnabled.h', 'FeedWriterEnabled.h',
'TextInputProcessor.h', 'TextInputProcessor.h',
'TimerClamping.h',
'UseCounter.h', 'UseCounter.h',
] ]
@ -363,6 +364,7 @@ UNIFIED_SOURCES += [
'TextInputProcessor.cpp', 'TextInputProcessor.cpp',
'ThirdPartyUtil.cpp', 'ThirdPartyUtil.cpp',
'Timeout.cpp', 'Timeout.cpp',
'TimerClamping.cpp',
'TreeWalker.cpp', 'TreeWalker.cpp',
'WebKitCSSMatrix.cpp', 'WebKitCSSMatrix.cpp',
'WebSocket.cpp', 'WebSocket.cpp',

3
dom/console/Console.cpp Normal file → Executable file
View file

@ -30,6 +30,7 @@
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "nsDocShell.h" #include "nsDocShell.h"
#include "nsProxyRelease.h" #include "nsProxyRelease.h"
#include "mozilla/TimerClamping.h"
#include "mozilla/ConsoleTimelineMarker.h" #include "mozilla/ConsoleTimelineMarker.h"
#include "mozilla/TimestampTimelineMarker.h" #include "mozilla/TimestampTimelineMarker.h"
@ -1338,7 +1339,7 @@ Console::MethodInternal(JSContext* aCx, MethodName aMethodName,
TimeDuration duration = TimeDuration duration =
mozilla::TimeStamp::Now() - workerPrivate->NowBaseTimeStamp(); mozilla::TimeStamp::Now() - workerPrivate->NowBaseTimeStamp();
monotonicTimer = duration.ToMilliseconds(); monotonicTimer = TimerClamping::ReduceMsTimeValue(duration.ToMilliseconds());
} }
} }

7
dom/events/Event.cpp Normal file → Executable file
View file

@ -32,6 +32,7 @@
#include "nsJSEnvironment.h" #include "nsJSEnvironment.h"
#include "nsLayoutUtils.h" #include "nsLayoutUtils.h"
#include "nsPIWindowRoot.h" #include "nsPIWindowRoot.h"
#include "mozilla/TimerClamping.h"
#include "WorkerPrivate.h" #include "WorkerPrivate.h"
namespace mozilla { namespace mozilla {
@ -1084,6 +1085,12 @@ Event::DefaultPrevented(JSContext* aCx) const
double double
Event::TimeStamp() const Event::TimeStamp() const
{
return TimerClamping::ReduceMsTimeValue(TimeStampImpl());
}
double
Event::TimeStampImpl() const
{ {
if (!sReturnHighResTimeStamp) { if (!sReturnHighResTimeStamp) {
return static_cast<double>(mEvent->mTime); return static_cast<double>(mEvent->mTime);

1
dom/events/Event.h Normal file → Executable file
View file

@ -62,6 +62,7 @@ private:
void ConstructorInit(EventTarget* aOwner, void ConstructorInit(EventTarget* aOwner,
nsPresContext* aPresContext, nsPresContext* aPresContext,
WidgetEvent* aEvent); WidgetEvent* aEvent);
double TimeStampImpl() const;
public: public:
static Event* FromSupports(nsISupports* aSupports) static Event* FromSupports(nsISupports* aSupports)

5
dom/media/DOMMediaStream.cpp Normal file → Executable file
View file

@ -9,6 +9,7 @@
#include "nsIScriptError.h" #include "nsIScriptError.h"
#include "nsIUUIDGenerator.h" #include "nsIUUIDGenerator.h"
#include "nsPIDOMWindow.h" #include "nsPIDOMWindow.h"
#include "mozilla/TimerClamping.h"
#include "mozilla/dom/MediaStreamBinding.h" #include "mozilla/dom/MediaStreamBinding.h"
#include "mozilla/dom/MediaStreamTrackEvent.h" #include "mozilla/dom/MediaStreamTrackEvent.h"
#include "mozilla/dom/LocalMediaStreamBinding.h" #include "mozilla/dom/LocalMediaStreamBinding.h"
@ -544,8 +545,8 @@ DOMMediaStream::CurrentTime()
if (!mPlaybackStream) { if (!mPlaybackStream) {
return 0.0; return 0.0;
} }
return mPlaybackStream-> return TimerClamping::ReduceSTimeValue(mPlaybackStream->
StreamTimeToSeconds(mPlaybackStream->GetCurrentTime() - mLogicalStreamStartTime); StreamTimeToSeconds(mPlaybackStream->GetCurrentTime() - mLogicalStreamStartTime));
} }
void void

3
dom/media/webaudio/AudioContext.cpp Normal file → Executable file
View file

@ -41,6 +41,7 @@
#include "nsNetUtil.h" #include "nsNetUtil.h"
#include "nsPIDOMWindow.h" #include "nsPIDOMWindow.h"
#include "nsPrintfCString.h" #include "nsPrintfCString.h"
#include "mozilla/TimerClamping.h"
#include "OscillatorNode.h" #include "OscillatorNode.h"
#include "PannerNode.h" #include "PannerNode.h"
#include "PeriodicWave.h" #include "PeriodicWave.h"
@ -746,7 +747,7 @@ double
AudioContext::CurrentTime() const AudioContext::CurrentTime() const
{ {
MediaStream* stream = Destination()->Stream(); MediaStream* stream = Destination()->Stream();
return stream->StreamTimeToSeconds(stream->GetCurrentTime()); return TimerClamping::ReduceSTimeValue(stream->StreamTimeToSeconds(stream->GetCurrentTime()));
} }
void void

5
dom/performance/Performance.cpp Normal file → Executable file
View file

@ -21,6 +21,7 @@
#include "mozilla/dom/PerformanceObserverBinding.h" #include "mozilla/dom/PerformanceObserverBinding.h"
#include "mozilla/IntegerPrintfMacros.h" #include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
#include "mozilla/TimerClamping.h"
#include "WorkerPrivate.h" #include "WorkerPrivate.h"
#include "WorkerRunnable.h" #include "WorkerRunnable.h"
@ -228,9 +229,9 @@ Performance::ClearResourceTimings()
DOMHighResTimeStamp DOMHighResTimeStamp
Performance::RoundTime(double aTime) const Performance::RoundTime(double aTime) const
{ {
// Round down to the nearest 20us, because if the timer is too accurate people // Round down to the nearest 2ms, because if the timer is too accurate people
// can do nasty timing attacks with it. // can do nasty timing attacks with it.
const double maxResolutionMs = 0.020; const double maxResolutionMs = 2;
return floor(aTime / maxResolutionMs) * maxResolutionMs; return floor(aTime / maxResolutionMs) * maxResolutionMs;
} }

22
dom/performance/PerformanceTiming.cpp Normal file → Executable file
View file

@ -21,7 +21,7 @@ PerformanceTiming::PerformanceTiming(Performance* aPerformance,
DOMHighResTimeStamp aZeroTime) DOMHighResTimeStamp aZeroTime)
: mPerformance(aPerformance), : mPerformance(aPerformance),
mFetchStart(0.0), mFetchStart(0.0),
mZeroTime(aZeroTime), mZeroTime(TimerClamping::ReduceMsTimeValue(aZeroTime)),
mRedirectCount(0), mRedirectCount(0),
mTimingAllowed(true), mTimingAllowed(true),
mAllRedirectsSameOrigin(true), mAllRedirectsSameOrigin(true),
@ -117,7 +117,7 @@ PerformanceTiming::FetchStartHighRes()
? TimeStampToDOMHighRes(mAsyncOpen) ? TimeStampToDOMHighRes(mAsyncOpen)
: 0.0; : 0.0;
} }
return mFetchStart; return TimerClamping::ReduceMsTimeValue(mFetchStart);
} }
DOMTimeMilliSec DOMTimeMilliSec
@ -203,7 +203,7 @@ PerformanceTiming::RedirectStartHighRes()
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime; return mZeroTime;
} }
return TimeStampToDOMHighResOrFetchStart(mRedirectStart); return TimeStampToReducedDOMHighResOrFetchStart(mRedirectStart);
} }
DOMTimeMilliSec DOMTimeMilliSec
@ -236,7 +236,7 @@ PerformanceTiming::RedirectEndHighRes()
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime; return mZeroTime;
} }
return TimeStampToDOMHighResOrFetchStart(mRedirectEnd); return TimeStampToReducedDOMHighResOrFetchStart(mRedirectEnd);
} }
DOMTimeMilliSec DOMTimeMilliSec
@ -259,7 +259,7 @@ PerformanceTiming::DomainLookupStartHighRes()
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime; return mZeroTime;
} }
return TimeStampToDOMHighResOrFetchStart(mDomainLookupStart); return TimeStampToReducedDOMHighResOrFetchStart(mDomainLookupStart);
} }
DOMTimeMilliSec DOMTimeMilliSec
@ -276,7 +276,7 @@ PerformanceTiming::DomainLookupEndHighRes()
} }
// Bug 1155008 - nsHttpTransaction is racy. Return DomainLookupStart when null // Bug 1155008 - nsHttpTransaction is racy. Return DomainLookupStart when null
return mDomainLookupEnd.IsNull() ? DomainLookupStartHighRes() return mDomainLookupEnd.IsNull() ? DomainLookupStartHighRes()
: TimeStampToDOMHighRes(mDomainLookupEnd); : TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(mDomainLookupEnd));
} }
DOMTimeMilliSec DOMTimeMilliSec
@ -292,7 +292,7 @@ PerformanceTiming::ConnectStartHighRes()
return mZeroTime; return mZeroTime;
} }
return mConnectStart.IsNull() ? DomainLookupEndHighRes() return mConnectStart.IsNull() ? DomainLookupEndHighRes()
: TimeStampToDOMHighRes(mConnectStart); : TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(mConnectStart));
} }
DOMTimeMilliSec DOMTimeMilliSec
@ -329,7 +329,7 @@ PerformanceTiming::ConnectEndHighRes()
} }
// Bug 1155008 - nsHttpTransaction is racy. Return ConnectStart when null // Bug 1155008 - nsHttpTransaction is racy. Return ConnectStart when null
return mConnectEnd.IsNull() ? ConnectStartHighRes() return mConnectEnd.IsNull() ? ConnectStartHighRes()
: TimeStampToDOMHighRes(mConnectEnd); : TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(mConnectEnd));
} }
DOMTimeMilliSec DOMTimeMilliSec
@ -344,7 +344,7 @@ PerformanceTiming::RequestStartHighRes()
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime; return mZeroTime;
} }
return TimeStampToDOMHighResOrFetchStart(mRequestStart); return TimeStampToReducedDOMHighResOrFetchStart(mRequestStart);
} }
DOMTimeMilliSec DOMTimeMilliSec
@ -363,7 +363,7 @@ PerformanceTiming::ResponseStartHighRes()
(!mCacheReadStart.IsNull() && mCacheReadStart < mResponseStart)) { (!mCacheReadStart.IsNull() && mCacheReadStart < mResponseStart)) {
mResponseStart = mCacheReadStart; mResponseStart = mCacheReadStart;
} }
return TimeStampToDOMHighResOrFetchStart(mResponseStart); return TimeStampToReducedDOMHighResOrFetchStart(mResponseStart);
} }
DOMTimeMilliSec DOMTimeMilliSec
@ -384,7 +384,7 @@ PerformanceTiming::ResponseEndHighRes()
} }
// Bug 1155008 - nsHttpTransaction is racy. Return ResponseStart when null // Bug 1155008 - nsHttpTransaction is racy. Return ResponseStart when null
return mResponseEnd.IsNull() ? ResponseStartHighRes() return mResponseEnd.IsNull() ? ResponseStartHighRes()
: TimeStampToDOMHighRes(mResponseEnd); : TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(mResponseEnd));
} }
DOMTimeMilliSec DOMTimeMilliSec

25
dom/performance/PerformanceTiming.h Normal file → Executable file
View file

@ -10,6 +10,7 @@
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "nsDOMNavigationTiming.h" #include "nsDOMNavigationTiming.h"
#include "mozilla/TimerClamping.h"
#include "nsWrapperCache.h" #include "nsWrapperCache.h"
#include "Performance.h" #include "Performance.h"
@ -68,10 +69,10 @@ public:
* page), if the given TimeStamp is valid. Otherwise, it will return * page), if the given TimeStamp is valid. Otherwise, it will return
* the FetchStart timing value. * the FetchStart timing value.
*/ */
inline DOMHighResTimeStamp TimeStampToDOMHighResOrFetchStart(TimeStamp aStamp) inline DOMHighResTimeStamp TimeStampToReducedDOMHighResOrFetchStart(TimeStamp aStamp)
{ {
return (!aStamp.IsNull()) return (!aStamp.IsNull())
? TimeStampToDOMHighRes(aStamp) ? TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(aStamp))
: FetchStartHighRes(); : FetchStartHighRes();
} }
@ -119,7 +120,7 @@ public:
if (!nsContentUtils::IsPerformanceTimingEnabled()) { if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0; return 0;
} }
return GetDOMTiming()->GetNavigationStart(); return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetNavigationStart());
} }
DOMTimeMilliSec UnloadEventStart() DOMTimeMilliSec UnloadEventStart()
@ -127,7 +128,7 @@ public:
if (!nsContentUtils::IsPerformanceTimingEnabled()) { if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0; return 0;
} }
return GetDOMTiming()->GetUnloadEventStart(); return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetUnloadEventStart());
} }
DOMTimeMilliSec UnloadEventEnd() DOMTimeMilliSec UnloadEventEnd()
@ -135,7 +136,7 @@ public:
if (!nsContentUtils::IsPerformanceTimingEnabled()) { if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0; return 0;
} }
return GetDOMTiming()->GetUnloadEventEnd(); return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetUnloadEventEnd());
} }
uint16_t GetRedirectCount() const; uint16_t GetRedirectCount() const;
@ -185,7 +186,7 @@ public:
if (!nsContentUtils::IsPerformanceTimingEnabled()) { if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0; return 0;
} }
return GetDOMTiming()->GetDomLoading(); return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetDomLoading());
} }
DOMTimeMilliSec DomInteractive() const DOMTimeMilliSec DomInteractive() const
@ -193,7 +194,7 @@ public:
if (!nsContentUtils::IsPerformanceTimingEnabled()) { if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0; return 0;
} }
return GetDOMTiming()->GetDomInteractive(); return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetDomInteractive());
} }
DOMTimeMilliSec DomContentLoadedEventStart() const DOMTimeMilliSec DomContentLoadedEventStart() const
@ -201,7 +202,7 @@ public:
if (!nsContentUtils::IsPerformanceTimingEnabled()) { if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0; return 0;
} }
return GetDOMTiming()->GetDomContentLoadedEventStart(); return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetDomContentLoadedEventStart());
} }
DOMTimeMilliSec DomContentLoadedEventEnd() const DOMTimeMilliSec DomContentLoadedEventEnd() const
@ -209,7 +210,7 @@ public:
if (!nsContentUtils::IsPerformanceTimingEnabled()) { if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0; return 0;
} }
return GetDOMTiming()->GetDomContentLoadedEventEnd(); return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetDomContentLoadedEventEnd());
} }
DOMTimeMilliSec DomComplete() const DOMTimeMilliSec DomComplete() const
@ -217,7 +218,7 @@ public:
if (!nsContentUtils::IsPerformanceTimingEnabled()) { if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0; return 0;
} }
return GetDOMTiming()->GetDomComplete(); return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetDomComplete());
} }
DOMTimeMilliSec LoadEventStart() const DOMTimeMilliSec LoadEventStart() const
@ -225,7 +226,7 @@ public:
if (!nsContentUtils::IsPerformanceTimingEnabled()) { if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0; return 0;
} }
return GetDOMTiming()->GetLoadEventStart(); return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetLoadEventStart());
} }
DOMTimeMilliSec LoadEventEnd() const DOMTimeMilliSec LoadEventEnd() const
@ -233,7 +234,7 @@ public:
if (!nsContentUtils::IsPerformanceTimingEnabled()) { if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0; return 0;
} }
return GetDOMTiming()->GetLoadEventEnd(); return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetLoadEventEnd());
} }
private: private:

5
js/src/jsdate.cpp Normal file → Executable file
View file

@ -1232,7 +1232,10 @@ date_parse(JSContext* cx, unsigned argc, Value* vp)
static ClippedTime static ClippedTime
NowAsMillis() NowAsMillis()
{ {
return TimeClip(static_cast<double>(PRMJ_Now()) / PRMJ_USEC_PER_MSEC); const double maxResolutionMs = 2;
double timestamp = static_cast<double>(PRMJ_Now()) / PRMJ_USEC_PER_MSEC;
timestamp = floor(timestamp / maxResolutionMs) * maxResolutionMs;
return TimeClip(timestamp);
} }
bool bool