--- a/toolkit/components/resistfingerprinting/nsRFPService.cpp
+++ b/toolkit/components/resistfingerprinting/nsRFPService.cpp
@@ -240,18 +240,18 @@ static StaticRefPtr<LRUCache> sCache;
* random midpoint (e.g. 360)
*
* If our actual timestamp (e.g. 325) is below the midpoint, we keep it clamped
* downwards. If it were equal to or above the midpoint (e.g. 365) we would
* round it upwards to the largest clamped value (in this example: 400).
*
* The question is: does time go backwards?
*
- * The midpoint is deterministicly random
- * and generated from two components: a secret seed and a clamped time.
+ * The midpoint is deterministicly random and generated from three components:
+ * a secret seed, a per-timeline (context) 'mix-in', and a clamped time.
*
* When comparing times across different seed values: time may go backwards.
* For a clamped time of 300, one seed may generate a midpoint of 305 and another
* 395. So comparing an (actual) timestamp of 325 and 351 could see the 325 clamped
* up to 400 and the 351 clamped down to 300. The seed is per-process, so this case
* occurs when one can compare timestamps cross-process. This is uncommon (because
* we don't have site isolation.) The circumstances this could occur are
* BroadcastChannel, Storage Notification, and in theory (but not yet implemented)
@@ -263,37 +263,46 @@ static StaticRefPtr<LRUCache> sCache;
* Assume a page and a worker. If one calls performance.now() in the page and then
* triggers a call to performance.now() in the worker, the following invariant should
* hold true:
* page.performance.timeOrigin + page.performance.now() <
* worker.performance.timeOrigin + worker.performance.now()
*
* We break this invariant.
*
+ * The 'Context Mix-in' is a securely generated random seed that is unique for each
+ * timeline that starts over at zero. It is needed to ensure that the sequence of
+ * midpoints (as calculated by the secret seed and clamped time) does not repeat.
+ * In RelativeTimeline.h, we define a 'RelativeTimeline' class that can be inherited by
+ * any object that has a relative timeline. The most obvious examples are Documents
+ * and Workers. An attacker could let time go forward and observe (roughly) where
+ * the random midpoints fall. Then they create a new object, time starts back over at
+ * zero, and they know (approximately) where the random midpoints are.
*
- * TODO: The above comment is going to need to be entirely rewritten when we mix in
- * a per-context shared secret. Context is 'Any new object that gets a time origin
- * starting from zero'. The most obvious example is Documents and Workers. An attacker
- * could let time go forward and observe (roughly) where the random midpoints fall.
- * Then they create a new object, time starts back ovr at zero, and they know
- * (approximately) where the random midpoints are.
+ * When the timestamp given is a non-relative timestamp (e.g. it is relative to the
+ * unix epoch) it is not possible to replay a sequence of random values. Thus,
+ * providing a zero context pointer is an indicator that the timestamp given is
+ * absolute and does not need any additional randomness.
*
* @param aClampedTimeUSec [in] The clamped input time in microseconds.
* @param aResolutionUSec [in] The current resolution for clamping in microseconds.
* @param aMidpointOut [out] The midpoint, in microseconds, between [0, aResolutionUSec].
+ * @param aContextMixin [in] An opaque random value for relative timestamps. 0 for
+ * absolute timestamps
* @param aSecretSeed [in] TESTING ONLY. When provided, the current seed will be
* replaced with this value.
* @return A nsresult indicating success of failure. If the function failed,
* nothing is written to aMidpointOut
*/
/* static */
nsresult
nsRFPService::RandomMidpoint(long long aClampedTimeUSec,
long long aResolutionUSec,
+ int64_t aContextMixin,
long long* aMidpointOut,
uint8_t * aSecretSeed /* = nullptr */)
{
nsresult rv;
const int kSeedSize = 16;
const int kClampTimesPerDigest = HASH_DIGEST_SIZE_BITS / 32;
static uint8_t * sSecretMidpointSeed = nullptr;
@@ -424,47 +433,66 @@ nsRFPService::RandomMidpoint(long long a
* Given a precision value, this function will reduce a given input time to the nearest
* multiple of that precision.
*
* It will check if it is appropriate to clamp the input time according to the values
* of the privacy.resistFingerprinting and privacy.reduceTimerPrecision preferences.
* Note that while it will check these prefs, it will use whatever precision is given to
* it, so if one desires a minimum precision for Resist Fingerprinting, it is the
* caller's responsibility to provide the correct value. This means you should pass
- * TimerPrecision(), which enforces a minimum vale on the precision based on
+ * TimerResolution(), which enforces a minimum vale on the precision based on
* preferences.
*
* It ensures the given precision value is greater than zero, if it is not it returns
* the input time.
*
* @param aTime [in] The input time to be clamped.
* @param aTimeScale [in] The units the input time is in (Seconds, Milliseconds, or Microseconds).
* @param aResolutionUSec [in] The precision (in microseconds) to clamp to.
+ * @param aContextMixin [in] An opaque random value for relative timestamps. 0 for absolute timestamps
* @return If clamping is appropriate, the clamped value of the input, otherwise the input.
*/
/* static */
double
nsRFPService::ReduceTimePrecisionImpl(
double aTime,
TimeScale aTimeScale,
double aResolutionUSec,
+ int64_t aContextMixin,
TimerPrecisionType aType)
{
if (!IsTimerPrecisionReductionEnabled(aType) || aResolutionUSec <= 0) {
return aTime;
}
// Increase the time as needed until it is in microseconds.
// Note that a double can hold up to 2**53 with integer precision. This gives us
// only until June 5, 2255 in time-since-the-epoch with integer precision.
// So we will be losing microseconds precision after that date.
// We think this is okay, and we codify it in some tests.
double timeScaled = aTime * (1000000 / aTimeScale);
// Cut off anything less than a microsecond.
long long timeAsInt = timeScaled;
+
+ // If we have a blank context mixin, this indicates we (should) have an absolute timestamp.
+ // We check the time, and if it less than a unix timestamp about 10 years in the past, we
+ // output to the log and, in debug builds, assert. This is an error case we want to
+ // understand and fix: we must have given a relative timestamp with a mixin of 0 which is
+ // incorrect.
+ // Anyone running a debug build _probably_ has an accurate clock, and if they don't, they'll
+ // hopefully find this message and understand why things are crashing.
+ if (aContextMixin == 0 && aType == TimerPrecisionType::All && timeAsInt < 1204233985000) {
+ MOZ_LOG(gResistFingerprintingLog, LogLevel::Error,
+ ("About to assert. aTime=%lli<1204233985000 aContextMixin=%" PRId64 " aType=%s",
+ timeAsInt, aContextMixin, (aType == TimerPrecisionType::RFPOnly ? "RFPOnly" : "All")));
+ MOZ_ASSERT(false, "ReduceTimePrecisionImpl was given a relative time "
+ "with an empty context mix-in (or your clock is 10+ years off.) "
+ "Run this with MOZ_LOG=nsResistFingerprinting:1 to get more details.");
+}
+
// Cast the resolution (in microseconds) to an int.
long long resolutionAsInt = aResolutionUSec;
// Perform the clamping.
// We do a cast back to double to perform the division with doubles, then floor the result
// and the rest occurs with integer precision.
// This is because it gives consistency above and below zero. Above zero, performing the
// division in integers truncates decimals, taking the result closer to zero (a floor).
// Below zero, performing the division in integers truncates decimals, taking the result
@@ -480,92 +508,125 @@ nsRFPService::ReduceTimePrecisionImpl(
clampedAndJittered = clamped;
// RandomMidpoint uses crypto functions from NSS. But we wind up in this code _very_ early
// on in and we don't want to initialize NSS earlier than it would be initialized naturally.
// Doing so caused nearly every xpcshell test to fail, as well as Marionette.
// This is safe, because we're not going to be doing any web context stuff before NSS is
// initialized, so anything that winds up here won't be exposed to content so we don't
// really need to worry about fuzzing its value.
if (sJitter && NSS_IsInitialized()) {
- if(!NS_FAILED(RandomMidpoint(clamped, resolutionAsInt, &midpoint)) &&
+ if(!NS_FAILED(RandomMidpoint(clamped, resolutionAsInt, aContextMixin, &midpoint)) &&
timeAsInt >= clamped + midpoint) {
clampedAndJittered += resolutionAsInt;
}
}
// Cast it back to a double and reduce it to the correct units.
double ret = double(clampedAndJittered) / (1000000.0 / aTimeScale);
bool tmp_jitter = sJitter;
MOZ_LOG(gResistFingerprintingLog, LogLevel::Verbose,
("Given: (%.*f, Scaled: %.*f, Converted: %lli), Rounding with (%lli, Originally %.*f), "
- "Intermediate: (%lli), Clamped: (%lli) Jitter: (%i Midpoint: %lli) Final: (%lli Converted: %.*f)",
+ "Intermediate: (%lli), Clamped: (%lli) Jitter: (%i Context: %" PRId64 " Midpoint: %lli) "
+ "Final: (%lli Converted: %.*f)",
DBL_DIG-1, aTime, DBL_DIG-1, timeScaled, timeAsInt, resolutionAsInt, DBL_DIG-1, aResolutionUSec,
- (long long)floor(double(timeAsInt) / resolutionAsInt), clamped, tmp_jitter, midpoint, clampedAndJittered, DBL_DIG-1, ret));
+ (long long)floor(double(timeAsInt) / resolutionAsInt), clamped, tmp_jitter, aContextMixin, midpoint,
+ clampedAndJittered, DBL_DIG-1, ret));
return ret;
}
/* static */
double
-nsRFPService::ReduceTimePrecisionAsUSecs(double aTime, TimerPrecisionType aType /* = TimerPrecisionType::All */)
+nsRFPService::ReduceTimePrecisionAsUSecs(
+ double aTime,
+ int64_t aContextMixin,
+ TimerPrecisionType aType /* = TimerPrecisionType::All */)
{
- return nsRFPService::ReduceTimePrecisionImpl(aTime, MicroSeconds, TimerResolution(), aType);
+ return nsRFPService::ReduceTimePrecisionImpl(
+ aTime,
+ MicroSeconds,
+ TimerResolution(),
+ aContextMixin,
+ aType);
}
/* static */
double
nsRFPService::ReduceTimePrecisionAsUSecsWrapper(double aTime)
{
- return nsRFPService::ReduceTimePrecisionImpl(aTime, MicroSeconds, TimerResolution(), TimerPrecisionType::All);
+ return nsRFPService::ReduceTimePrecisionImpl(
+ aTime,
+ MicroSeconds,
+ TimerResolution(),
+ 0,
+ TimerPrecisionType::All);
}
/* static */
double
-nsRFPService::ReduceTimePrecisionAsMSecs(double aTime, TimerPrecisionType aType /* = TimerPrecisionType::All */)
+nsRFPService::ReduceTimePrecisionAsMSecs(
+ double aTime,
+ int64_t aContextMixin,
+ TimerPrecisionType aType /* = TimerPrecisionType::All */)
{
- return nsRFPService::ReduceTimePrecisionImpl(aTime, MilliSeconds, TimerResolution(), aType);
+ return nsRFPService::ReduceTimePrecisionImpl(
+ aTime,
+ MilliSeconds,
+ TimerResolution(),
+ aContextMixin,
+ aType);
}
/* static */
double
-nsRFPService::ReduceTimePrecisionAsSecs(double aTime, TimerPrecisionType aType /* = TimerPrecisionType::All */)
+nsRFPService::ReduceTimePrecisionAsSecs(
+ double aTime,
+ int64_t aContextMixin,
+ TimerPrecisionType aType /* = TimerPrecisionType::All */)
{
- return nsRFPService::ReduceTimePrecisionImpl(aTime, Seconds, TimerResolution(), aType);
+ return nsRFPService::ReduceTimePrecisionImpl(
+ aTime,
+ Seconds,
+ TimerResolution(),
+ aContextMixin,
+ aType);
}
/* static */
uint32_t
nsRFPService::CalculateTargetVideoResolution(uint32_t aVideoQuality)
{
return aVideoQuality * NSToIntCeil(aVideoQuality * 16 / 9.0);
}
/* static */
uint32_t
nsRFPService::GetSpoofedTotalFrames(double aTime)
{
- double time = ReduceTimePrecisionAsSecs(aTime);
+ double precision = TimerResolution() / 1000 / 1000;
+ double time = floor(aTime / precision) * precision;
return NSToIntFloor(time * sVideoFramesPerSec);
}
/* static */
uint32_t
nsRFPService::GetSpoofedDroppedFrames(double aTime, uint32_t aWidth, uint32_t aHeight)
{
uint32_t targetRes = CalculateTargetVideoResolution(sTargetVideoRes);
// The video resolution is less than or equal to the target resolution, we
// report a zero dropped rate for this case.
if (targetRes >= aWidth * aHeight) {
return 0;
}
- double time = ReduceTimePrecisionAsSecs(aTime);
+ double precision = TimerResolution() / 1000 / 1000;
+ double time = floor(aTime / precision) * precision;
// Bound the dropped ratio from 0 to 100.
uint32_t boundedDroppedRatio = min(sVideoDroppedRatio, 100u);
return NSToIntFloor(time * sVideoFramesPerSec * (boundedDroppedRatio / 100.0));
}
/* static */
uint32_t
@@ -574,17 +635,18 @@ nsRFPService::GetSpoofedPresentedFrames(
uint32_t targetRes = CalculateTargetVideoResolution(sTargetVideoRes);
// The target resolution is greater than the current resolution. For this case,
// there will be no dropped frames, so we report total frames directly.
if (targetRes >= aWidth * aHeight) {
return GetSpoofedTotalFrames(aTime);
}
- double time = ReduceTimePrecisionAsSecs(aTime);
+ double precision = TimerResolution() / 1000 / 1000;
+ double time = floor(aTime / precision) * precision;
// Bound the dropped ratio from 0 to 100.
uint32_t boundedDroppedRatio = min(sVideoDroppedRatio, 100u);
return NSToIntFloor(time * sVideoFramesPerSec * ((100 - boundedDroppedRatio) / 100.0));
}
/* static */
nsresult
--- a/toolkit/components/resistfingerprinting/tests/test_reduceprecision.cpp
+++ b/toolkit/components/resistfingerprinting/tests/test_reduceprecision.cpp
@@ -59,18 +59,18 @@ bool setupJitter(bool enabled) {
void cleanupJitter(bool jitterWasEnabled) {
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
if (prefs) {
prefs->SetBoolPref("privacy.resistFingerprinting.reduceTimerPrecision.jitter", jitterWasEnabled);
}
}
void process(double clock, nsRFPService::TimeScale clockUnits, double precision) {
- double reduced1 = nsRFPService::ReduceTimePrecisionImpl(clock, clockUnits, precision, TimerPrecisionType::All);
- double reduced2 = nsRFPService::ReduceTimePrecisionImpl(reduced1, clockUnits, precision, TimerPrecisionType::All);
+ double reduced1 = nsRFPService::ReduceTimePrecisionImpl(clock, clockUnits, precision, -1, TimerPrecisionType::All);
+ double reduced2 = nsRFPService::ReduceTimePrecisionImpl(reduced1, clockUnits, precision, -1, TimerPrecisionType::All);
ASSERT_EQ(reduced1, reduced2);
}
TEST(ResistFingerprinting, ReducePrecision_Assumptions) {
ASSERT_EQ(FLT_RADIX, 2);
ASSERT_EQ(DBL_MANT_DIG, 53);
}
@@ -110,45 +110,45 @@ TEST(ResistFingerprinting, ReducePrecisi
process(2595.16, nsRFPService::TimeScale::MilliSeconds, 20);
process(2578.66, nsRFPService::TimeScale::MilliSeconds, 20);
cleanupJitter(jitterEnabled);
}
TEST(ResistFingerprinting, ReducePrecision_Expectations) {
bool jitterEnabled = setupJitter(false);
double result;
- result = nsRFPService::ReduceTimePrecisionImpl(2611.14, nsRFPService::TimeScale::MilliSeconds, 20, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(2611.14, nsRFPService::TimeScale::MilliSeconds, 20, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 2611.14);
- result = nsRFPService::ReduceTimePrecisionImpl(2611.145, nsRFPService::TimeScale::MilliSeconds, 20, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(2611.145, nsRFPService::TimeScale::MilliSeconds, 20, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 2611.14);
- result = nsRFPService::ReduceTimePrecisionImpl(2611.141, nsRFPService::TimeScale::MilliSeconds, 20, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(2611.141, nsRFPService::TimeScale::MilliSeconds, 20, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 2611.14);
- result = nsRFPService::ReduceTimePrecisionImpl(2611.15999, nsRFPService::TimeScale::MilliSeconds, 20, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(2611.15999, nsRFPService::TimeScale::MilliSeconds, 20, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 2611.14);
- result = nsRFPService::ReduceTimePrecisionImpl(2611.15, nsRFPService::TimeScale::MilliSeconds, 20, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(2611.15, nsRFPService::TimeScale::MilliSeconds, 20, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 2611.14);
- result = nsRFPService::ReduceTimePrecisionImpl(2611.13, nsRFPService::TimeScale::MilliSeconds, 20, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(2611.13, nsRFPService::TimeScale::MilliSeconds, 20, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 2611.12);
cleanupJitter(jitterEnabled);
}
TEST(ResistFingerprinting, ReducePrecision_ExpectedLossOfPrecision) {
bool jitterEnabled = setupJitter(false);
double result;
// We lose integer precision at 9007199254740992 - let's confirm that.
- result = nsRFPService::ReduceTimePrecisionImpl(9007199254740992.0, nsRFPService::TimeScale::MicroSeconds, 5, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(9007199254740992.0, nsRFPService::TimeScale::MicroSeconds, 5, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 9007199254740990.0);
// 9007199254740995 is approximated to 9007199254740996
- result = nsRFPService::ReduceTimePrecisionImpl(9007199254740995.0, nsRFPService::TimeScale::MicroSeconds, 5, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(9007199254740995.0, nsRFPService::TimeScale::MicroSeconds, 5, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 9007199254740996);
// 9007199254740999 is approximated as 9007199254741000
- result = nsRFPService::ReduceTimePrecisionImpl(9007199254740999.0, nsRFPService::TimeScale::MicroSeconds, 5, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(9007199254740999.0, nsRFPService::TimeScale::MicroSeconds, 5, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 9007199254741000.0);
// 9007199254743568 can be represented exactly, but will be clamped to 9007199254743564
- result = nsRFPService::ReduceTimePrecisionImpl(9007199254743568.0, nsRFPService::TimeScale::MicroSeconds, 5, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(9007199254743568.0, nsRFPService::TimeScale::MicroSeconds, 5, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 9007199254743564.0);
cleanupJitter(jitterEnabled);
}
// Use an ugly but simple hack to turn an integer-based rand()
// function to a double-based one.
#define RAND_DOUBLE (rand() * (rand() / (double)rand()))
@@ -242,65 +242,65 @@ TEST(ResistFingerprinting, ReducePrecisi
*/
// Set the secret
long long throwAway;
uint8_t hardcodedSecret[16] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 };
- nsRFPService::RandomMidpoint(0, 500, &throwAway, hardcodedSecret);
+ nsRFPService::RandomMidpoint(0, 500, -1, &throwAway, hardcodedSecret);
// Run the test vectors
double result;
- result = nsRFPService::ReduceTimePrecisionImpl(1, nsRFPService::TimeScale::MicroSeconds, 500, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(1, nsRFPService::TimeScale::MicroSeconds, 500, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 0);
- result = nsRFPService::ReduceTimePrecisionImpl(129, nsRFPService::TimeScale::MicroSeconds, 500, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(129, nsRFPService::TimeScale::MicroSeconds, 500, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 0);
- result = nsRFPService::ReduceTimePrecisionImpl(130, nsRFPService::TimeScale::MicroSeconds, 500, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(130, nsRFPService::TimeScale::MicroSeconds, 500, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 500);
- result = nsRFPService::ReduceTimePrecisionImpl(131, nsRFPService::TimeScale::MicroSeconds, 500, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(131, nsRFPService::TimeScale::MicroSeconds, 500, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 500);
- result = nsRFPService::ReduceTimePrecisionImpl(499, nsRFPService::TimeScale::MicroSeconds, 500, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(499, nsRFPService::TimeScale::MicroSeconds, 500, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 500);
- result = nsRFPService::ReduceTimePrecisionImpl(500, nsRFPService::TimeScale::MicroSeconds, 500, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(500, nsRFPService::TimeScale::MicroSeconds, 500, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 500);
- result = nsRFPService::ReduceTimePrecisionImpl(600, nsRFPService::TimeScale::MicroSeconds, 500, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(600, nsRFPService::TimeScale::MicroSeconds, 500, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 500);
- result = nsRFPService::ReduceTimePrecisionImpl(928, nsRFPService::TimeScale::MicroSeconds, 500, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(928, nsRFPService::TimeScale::MicroSeconds, 500, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 500);
- result = nsRFPService::ReduceTimePrecisionImpl(929, nsRFPService::TimeScale::MicroSeconds, 500, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(929, nsRFPService::TimeScale::MicroSeconds, 500, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 1000);
- result = nsRFPService::ReduceTimePrecisionImpl(930, nsRFPService::TimeScale::MicroSeconds, 500, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(930, nsRFPService::TimeScale::MicroSeconds, 500, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 1000);
- result = nsRFPService::ReduceTimePrecisionImpl(1255, nsRFPService::TimeScale::MicroSeconds, 500, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(1255, nsRFPService::TimeScale::MicroSeconds, 500, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 1000);
- result = nsRFPService::ReduceTimePrecisionImpl(4000, nsRFPService::TimeScale::MicroSeconds, 500, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(4000, nsRFPService::TimeScale::MicroSeconds, 500, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 4000);
- result = nsRFPService::ReduceTimePrecisionImpl(4295, nsRFPService::TimeScale::MicroSeconds, 500, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(4295, nsRFPService::TimeScale::MicroSeconds, 500, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 4000);
- result = nsRFPService::ReduceTimePrecisionImpl(4296, nsRFPService::TimeScale::MicroSeconds, 500, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(4296, nsRFPService::TimeScale::MicroSeconds, 500, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 4000);
- result = nsRFPService::ReduceTimePrecisionImpl(4297, nsRFPService::TimeScale::MicroSeconds, 500, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(4297, nsRFPService::TimeScale::MicroSeconds, 500, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 4500);
- result = nsRFPService::ReduceTimePrecisionImpl(4298, nsRFPService::TimeScale::MicroSeconds, 500, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(4298, nsRFPService::TimeScale::MicroSeconds, 500, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 4500);
- result = nsRFPService::ReduceTimePrecisionImpl(4499, nsRFPService::TimeScale::MicroSeconds, 500, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(4499, nsRFPService::TimeScale::MicroSeconds, 500, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 4500);
- result = nsRFPService::ReduceTimePrecisionImpl(4500, nsRFPService::TimeScale::MicroSeconds, 500, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(4500, nsRFPService::TimeScale::MicroSeconds, 500, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 4500);
- result = nsRFPService::ReduceTimePrecisionImpl(4536, nsRFPService::TimeScale::MicroSeconds, 500, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(4536, nsRFPService::TimeScale::MicroSeconds, 500, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 4500);
- result = nsRFPService::ReduceTimePrecisionImpl(4537, nsRFPService::TimeScale::MicroSeconds, 500, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(4537, nsRFPService::TimeScale::MicroSeconds, 500, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 4500);
- result = nsRFPService::ReduceTimePrecisionImpl(4538, nsRFPService::TimeScale::MicroSeconds, 500, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(4538, nsRFPService::TimeScale::MicroSeconds, 500, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 5000);
- result = nsRFPService::ReduceTimePrecisionImpl(4539, nsRFPService::TimeScale::MicroSeconds, 500, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(4539, nsRFPService::TimeScale::MicroSeconds, 500, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 5000);
- result = nsRFPService::ReduceTimePrecisionImpl(5106, nsRFPService::TimeScale::MicroSeconds, 500, TimerPrecisionType::All);
+ result = nsRFPService::ReduceTimePrecisionImpl(5106, nsRFPService::TimeScale::MicroSeconds, 500, -1, TimerPrecisionType::All);
ASSERT_EQ(result, 5000);
cleanupJitter(jitterEnabled);
}