From 3705fef918b7c7afaef570dc517de62bd069d645 Mon Sep 17 00:00:00 2001 From: Tom Ritter Date: Tue, 17 Apr 2018 15:35:51 -0500 Subject: [PATCH] Bug 1446346 Do not clamp or jitter the AudioContext's CurrentTime if its interval is larger than our precision. r=jib MozReview-Commit-ID: Bc1cto3pBKL --HG-- extra : rebase_source : ace58df9f1669beacc176ab968f45a09ca44be2e --- .../mochitest/test_reduce_time_precision.html | 10 ++++++++++ dom/media/webaudio/AudioContext.cpp | 15 ++++++++++----- .../resistfingerprinting/nsRFPService.cpp | 5 +++-- .../resistfingerprinting/nsRFPService.h | 1 + 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/browser/components/resistfingerprinting/test/mochitest/test_reduce_time_precision.html b/browser/components/resistfingerprinting/test/mochitest/test_reduce_time_precision.html index 19273a9f687e..93c97148000d 100644 --- a/browser/components/resistfingerprinting/test/mochitest/test_reduce_time_precision.html +++ b/browser/components/resistfingerprinting/test/mochitest/test_reduce_time_precision.html @@ -175,6 +175,16 @@ https://trac.torproject.org/projects/tor/ticket/1517 // and check if it is rounded for (let timeStampCode of timeStampCodesDOM) { let timeStamp = eval(timeStampCode); + + // Audio Contexts increment in intervals of (minimum) 5.4ms, so we don't + // clamp/jitter if the timer precision is les than that. + // (Technically on MBPs they increment in intervals of 2.6 but this is + // non-standard and will eventually be changed. We don't cover this situation + // because we don't really support arbitrary Timer Precision, especially in + // the 2.6 - 5.4ms interval.) + if (timeStampCode.includes("audioContext") && expectedPrecision < 5.4) + continue; + ok(isRounded(timeStamp, expectedPrecision), "pref: " + prefname + " - '" + "'" + timeStampCode + diff --git a/dom/media/webaudio/AudioContext.cpp b/dom/media/webaudio/AudioContext.cpp index e6222656a3ec..80d3e9689aac 100644 --- a/dom/media/webaudio/AudioContext.cpp +++ b/dom/media/webaudio/AudioContext.cpp @@ -668,17 +668,22 @@ AudioContext::CurrentTime() { MediaStream* stream = Destination()->Stream(); - if (!mIsStarted && - stream->StreamTimeToSeconds(stream->GetCurrentTime()) == 0) { - return 0; + double rawTime = stream->StreamTimeToSeconds(stream->GetCurrentTime()); + + // CurrentTime increments in intervals of 128/sampleRate. If the Timer + // Precision Reduction is smaller than this interval, the jittered time + // can always be reversed to the raw step of the interval. In that case + // we can simply return the un-reduced time; and avoid breaking tests. + // We have to convert each variable into a common magnitude, we choose ms. + if ((128/mSampleRate) * 1000.0 > nsRFPService::TimerResolution() / 1000.0) { + return rawTime; } // The value of a MediaStream's CurrentTime will always advance forward; it will never // reset (even if one rewinds a video.) Therefore we can use a single Random Seed // initialized at the same time as the object. return nsRFPService::ReduceTimePrecisionAsSecs( - stream->StreamTimeToSeconds(stream->GetCurrentTime()), - GetRandomTimelineSeed()); + rawTime, GetRandomTimelineSeed()); } void AudioContext::DisconnectFromOwner() diff --git a/toolkit/components/resistfingerprinting/nsRFPService.cpp b/toolkit/components/resistfingerprinting/nsRFPService.cpp index 31a6e5dfc633..e303aa45c643 100644 --- a/toolkit/components/resistfingerprinting/nsRFPService.cpp +++ b/toolkit/components/resistfingerprinting/nsRFPService.cpp @@ -107,8 +107,9 @@ nsRFPService::GetOrCreate() return sRFPService; } -inline double -TimerResolution() +/* static */ +double +nsRFPService::TimerResolution() { if(nsRFPService::IsResistFingerprintingEnabled()) { return max(100000.0, (double)sResolutionUSec); diff --git a/toolkit/components/resistfingerprinting/nsRFPService.h b/toolkit/components/resistfingerprinting/nsRFPService.h index 34641ceb1246..9708d362496f 100644 --- a/toolkit/components/resistfingerprinting/nsRFPService.h +++ b/toolkit/components/resistfingerprinting/nsRFPService.h @@ -162,6 +162,7 @@ public: static nsRFPService* GetOrCreate(); static bool IsResistFingerprintingEnabled(); static bool IsTimerPrecisionReductionEnabled(TimerPrecisionType aType); + static double TimerResolution(); enum TimeScale { Seconds = 1,