зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1857488 - Add the RTPCallerType to JS realms. r=jandem
Differential Revision: https://phabricator.services.mozilla.com/D190676
This commit is contained in:
Родитель
f6676f428f
Коммит
5ef6bee795
|
@ -33,6 +33,7 @@
|
|||
#include "mozilla/MathAlgorithms.h" // mozilla::Abs
|
||||
|
||||
#include "js/Conversions.h" // JS::ToInteger
|
||||
#include "js/RealmOptions.h" // JS::RTPCallerTypeToken
|
||||
#include "js/TypeDecls.h"
|
||||
#include "js/Value.h" // JS::CanonicalizeNaN, JS::DoubleValue, JS::Value
|
||||
|
||||
|
@ -187,15 +188,26 @@ JS_PUBLIC_API double DayFromYear(double year);
|
|||
JS_PUBLIC_API double DayWithinYear(double time, double year);
|
||||
|
||||
// The callback will be a wrapper function that accepts a double (the time
|
||||
// to clamp and jitter). Inside the JS Engine, other parameters that may be
|
||||
// needed are all constant, so they are handled inside the wrapper function
|
||||
using ReduceMicrosecondTimePrecisionCallback = double (*)(double, JSContext*);
|
||||
// to clamp and jitter) and a JS::RTPCallerTypeToken (a wrapper for
|
||||
// mozilla::RTPCallerType) that can be used to decide the proper clamping
|
||||
// behavior to use. Inside the JS Engine, other parameters that may be needed
|
||||
// are all constant, so they are handled inside the wrapper function
|
||||
using ReduceMicrosecondTimePrecisionCallback =
|
||||
double (*)(double, JS::RTPCallerTypeToken, JSContext*);
|
||||
|
||||
// Set a callback into the toolkit/components/resistfingerprinting function that
|
||||
// will centralize time resolution and jitter into one place.
|
||||
// Defining such a callback requires all Realms that are created afterwards
|
||||
// to have a set JS::RTPCallerTypeToken, via RealmBehaviors or
|
||||
// JS::SetRealmReduceTimerPrecisionCallerType.
|
||||
JS_PUBLIC_API void SetReduceMicrosecondTimePrecisionCallback(
|
||||
ReduceMicrosecondTimePrecisionCallback callback);
|
||||
|
||||
// Get the previously set ReduceMicrosecondTimePrecisionCallback callback or
|
||||
// nullptr.
|
||||
JS_PUBLIC_API ReduceMicrosecondTimePrecisionCallback
|
||||
GetReduceMicrosecondTimePrecisionCallback();
|
||||
|
||||
// Sets the time resolution for fingerprinting protection, and whether jitter
|
||||
// should occur. If resolution is set to zero, then no rounding or jitter will
|
||||
// occur. This is used if the callback above is not specified.
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#define js_RealmOptions_h
|
||||
|
||||
#include "mozilla/Assertions.h" // MOZ_ASSERT
|
||||
#include "mozilla/Maybe.h"
|
||||
|
||||
#include "jstypes.h" // JS_PUBLIC_API
|
||||
|
||||
|
@ -320,6 +321,12 @@ class JS_PUBLIC_API RealmCreationOptions {
|
|||
bool alwaysUseFdlibm_ = false;
|
||||
};
|
||||
|
||||
// This is a wrapper for mozilla::RTPCallerType, that can't easily
|
||||
// be exposed to the JS engine for layering reasons.
|
||||
struct RTPCallerTypeToken {
|
||||
uint8_t value;
|
||||
};
|
||||
|
||||
/**
|
||||
* RealmBehaviors specifies behaviors of a realm that can be changed after the
|
||||
* realm's been created.
|
||||
|
@ -328,6 +335,17 @@ class JS_PUBLIC_API RealmBehaviors {
|
|||
public:
|
||||
RealmBehaviors() = default;
|
||||
|
||||
// When a JS::ReduceMicrosecondTimePrecisionCallback callback is defined via
|
||||
// JS::SetReduceMicrosecondTimePrecisionCallback, a JS::RTPCallerTypeToken (a
|
||||
// wrapper for mozilla::RTPCallerType) needs to be set for every Realm.
|
||||
mozilla::Maybe<RTPCallerTypeToken> reduceTimerPrecisionCallerType() const {
|
||||
return rtpCallerType;
|
||||
}
|
||||
RealmBehaviors& setReduceTimerPrecisionCallerType(RTPCallerTypeToken type) {
|
||||
rtpCallerType = mozilla::Some(type);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// For certain globals, we know enough about the code that will run in them
|
||||
// that we can discard script source entirely.
|
||||
bool discardSource() const { return discardSource_; }
|
||||
|
@ -342,29 +360,6 @@ class JS_PUBLIC_API RealmBehaviors {
|
|||
return *this;
|
||||
}
|
||||
|
||||
class Override {
|
||||
public:
|
||||
Override() : mode_(Default) {}
|
||||
|
||||
bool get(bool defaultValue) const {
|
||||
if (mode_ == Default) {
|
||||
return defaultValue;
|
||||
}
|
||||
return mode_ == ForceTrue;
|
||||
}
|
||||
|
||||
void set(bool overrideValue) {
|
||||
mode_ = overrideValue ? ForceTrue : ForceFalse;
|
||||
}
|
||||
|
||||
void reset() { mode_ = Default; }
|
||||
|
||||
private:
|
||||
enum Mode { Default, ForceTrue, ForceFalse };
|
||||
|
||||
Mode mode_;
|
||||
};
|
||||
|
||||
// A Realm can stop being "live" in all the ways that matter before its global
|
||||
// is actually GCed. Consumers that tear down parts of a Realm or its global
|
||||
// before that point should set isNonLive accordingly.
|
||||
|
@ -375,6 +370,7 @@ class JS_PUBLIC_API RealmBehaviors {
|
|||
}
|
||||
|
||||
private:
|
||||
mozilla::Maybe<RTPCallerTypeToken> rtpCallerType;
|
||||
bool discardSource_ = false;
|
||||
bool clampAndJitterTime_ = true;
|
||||
bool isNonLive_ = false;
|
||||
|
@ -423,6 +419,11 @@ extern JS_PUBLIC_API const RealmBehaviors& RealmBehaviorsRef(JSContext* cx);
|
|||
|
||||
extern JS_PUBLIC_API void SetRealmNonLive(Realm* realm);
|
||||
|
||||
// This behaves like RealmBehaviors::setReduceTimerPrecisionCallerType, but
|
||||
// can be used even after the Realm has already been created.
|
||||
extern JS_PUBLIC_API void SetRealmReduceTimerPrecisionCallerType(
|
||||
Realm* realm, RTPCallerTypeToken type);
|
||||
|
||||
} // namespace JS
|
||||
|
||||
#endif // js_RealmOptions_h
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "js/CompileOptions.h"
|
||||
#include "js/ContextOptions.h" // JS::ContextOptions{,Ref}
|
||||
#include "js/Conversions.h"
|
||||
#include "js/Date.h" // JS::GetReduceMicrosecondTimePrecisionCallback
|
||||
#include "js/ErrorInterceptor.h"
|
||||
#include "js/ErrorReport.h" // JSErrorBase
|
||||
#include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
|
||||
|
@ -1761,6 +1762,11 @@ const JS::RealmBehaviors& JS::RealmBehaviorsRef(JSContext* cx) {
|
|||
|
||||
void JS::SetRealmNonLive(Realm* realm) { realm->setNonLive(); }
|
||||
|
||||
void JS::SetRealmReduceTimerPrecisionCallerType(Realm* realm,
|
||||
JS::RTPCallerTypeToken type) {
|
||||
realm->setReduceTimerPrecisionCallerType(type);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API JSObject* JS_NewGlobalObject(JSContext* cx, const JSClass* clasp,
|
||||
JSPrincipals* principals,
|
||||
JS::OnNewGlobalHookOption hookOption,
|
||||
|
@ -1817,7 +1823,18 @@ JS_PUBLIC_API void JS_FireOnNewGlobalObject(JSContext* cx,
|
|||
// This infallibility will eat OOM and slow script, but if that happens
|
||||
// we'll likely run up into them again soon in a fallible context.
|
||||
cx->check(global);
|
||||
|
||||
Rooted<js::GlobalObject*> globalObject(cx, &global->as<GlobalObject>());
|
||||
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
||||
if (JS::GetReduceMicrosecondTimePrecisionCallback()) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(globalObject->realm()
|
||||
->behaviors()
|
||||
.reduceTimerPrecisionCallerType()
|
||||
.isSome(),
|
||||
"Trying to create a global without setting an "
|
||||
"explicit RTPCallerType!");
|
||||
}
|
||||
#endif
|
||||
DebugAPI::onNewGlobalObject(cx, globalObject);
|
||||
cx->runtime()->ensureRealmIsRecordingAllocations(globalObject);
|
||||
}
|
||||
|
|
|
@ -498,6 +498,11 @@ JS_PUBLIC_API void JS::SetReduceMicrosecondTimePrecisionCallback(
|
|||
sReduceMicrosecondTimePrecisionCallback = callback;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API JS::ReduceMicrosecondTimePrecisionCallback
|
||||
JS::GetReduceMicrosecondTimePrecisionCallback() {
|
||||
return sReduceMicrosecondTimePrecisionCallback;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API void JS::SetTimeResolutionUsec(uint32_t resolution, bool jitter) {
|
||||
sResolutionUsec = resolution;
|
||||
sJitter = jitter;
|
||||
|
@ -1856,7 +1861,9 @@ static ClippedTime NowAsMillis(JSContext* cx) {
|
|||
double now = PRMJ_Now();
|
||||
bool clampAndJitter = cx->realm()->behaviors().clampAndJitterTime();
|
||||
if (clampAndJitter && sReduceMicrosecondTimePrecisionCallback) {
|
||||
now = sReduceMicrosecondTimePrecisionCallback(now, cx);
|
||||
now = sReduceMicrosecondTimePrecisionCallback(
|
||||
now, cx->realm()->behaviors().reduceTimerPrecisionCallerType().value(),
|
||||
cx);
|
||||
} else if (clampAndJitter && sResolutionUsec) {
|
||||
double clamped = floor(now / sResolutionUsec) * sResolutionUsec;
|
||||
|
||||
|
|
|
@ -471,6 +471,9 @@ class JS::Realm : public JS::shadow::Realm {
|
|||
const JS::RealmBehaviors& behaviors() const { return behaviors_; }
|
||||
|
||||
void setNonLive() { behaviors_.setNonLive(); }
|
||||
void setReduceTimerPrecisionCallerType(JS::RTPCallerTypeToken type) {
|
||||
behaviors_.setReduceTimerPrecisionCallerType(type);
|
||||
}
|
||||
|
||||
/* Whether to preserve JIT code on non-shrinking GCs. */
|
||||
bool preserveJitCode() { return creationOptions_.preserveJitCode(); }
|
||||
|
|
|
@ -661,13 +661,14 @@ double nsRFPService::ReduceTimePrecisionAsSecsRFPOnly(
|
|||
}
|
||||
|
||||
/* static */
|
||||
double nsRFPService::ReduceTimePrecisionAsUSecsWrapper(double aTime,
|
||||
JSContext* aCx) {
|
||||
double nsRFPService::ReduceTimePrecisionAsUSecsWrapper(
|
||||
double aTime, JS::RTPCallerTypeToken aCallerType, JSContext* aCx) {
|
||||
MOZ_ASSERT(aCx);
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> global = xpc::CurrentNativeGlobal(aCx);
|
||||
MOZ_ASSERT(global);
|
||||
RTPCallerType callerType = global->GetRTPCallerType();
|
||||
|
||||
return nsRFPService::ReduceTimePrecisionImpl(
|
||||
aTime, MicroSeconds, TimerResolution(callerType),
|
||||
0, /* For absolute timestamps (all the JS engine does), supply zero
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "mozilla/BasicEvents.h"
|
||||
#include "mozilla/gfx/Types.h"
|
||||
#include "mozilla/TypedEnumBits.h"
|
||||
#include "js/RealmOptions.h"
|
||||
#include "nsHashtablesFwd.h"
|
||||
#include "nsICookieJarSettings.h"
|
||||
#include "nsIFingerprintingWebCompatService.h"
|
||||
|
@ -197,10 +198,6 @@ class nsRFPService final : public nsIObserver, public nsIRFPService {
|
|||
static double ReduceTimePrecisionAsSecsRFPOnly(double aTime,
|
||||
int64_t aContextMixin,
|
||||
RTPCallerType aRTPCallerType);
|
||||
|
||||
// Used by the JS Engine, as it doesn't know about the TimerPrecisionType enum
|
||||
static double ReduceTimePrecisionAsUSecsWrapper(double aTime, JSContext* aCx);
|
||||
|
||||
// Public only for testing purposes
|
||||
static double ReduceTimePrecisionImpl(double aTime, TimeScale aTimeScale,
|
||||
double aResolutionUSec,
|
||||
|
@ -348,6 +345,10 @@ class nsRFPService final : public nsIObserver, public nsIRFPService {
|
|||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
// Used by the JS Engine
|
||||
static double ReduceTimePrecisionAsUSecsWrapper(
|
||||
double aTime, JS::RTPCallerTypeToken aCallerType, JSContext* aCx);
|
||||
|
||||
static TimerPrecisionType GetTimerPrecisionType(RTPCallerType aRTPCallerType);
|
||||
|
||||
static TimerPrecisionType GetTimerPrecisionTypeRFPOnly(
|
||||
|
|
Загрузка…
Ссылка в новой задаче