Bug 1217238 - Propagate changes of javascript.options.resistFingerprinting to workers.
This pref is created for the next patch. Because we need to get this pref in
workers, I added this pref to WorkerPrefs.h so RuntimeService will broadcast
pref changes for us, and update all the workers recursively. This pref is also
added to the js context options because the Date API needs it.
MozReview-Commit-ID: JOkOR2Wek5C
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -1352,16 +1352,29 @@ PlatformOverrideChanged(const char* /* a
mozilla::Preferences::GetString("general.platform.override");
RuntimeService* runtime = RuntimeService::GetService();
if (runtime) {
runtime->UpdatePlatformOverridePreference(override);
}
}
+void
+ResistFingerprintingChanged(const char* /* aPrefName */, void* /* aClosure */)
+{
+ AssertIsOnMainThread();
+ bool resistFingerprinting = mozilla::Preferences::GetBool(
+ "privacy.resistFingerprinting");
+
+ RuntimeService* runtime = RuntimeService::GetService();
+ if (runtime) {
+ runtime->UpdateResistFingerprintingPreference(resistFingerprinting);
+ }
+}
+
class BackgroundChildCallback final
: public nsIIPCBackgroundChildCreateCallback
{
public:
BackgroundChildCallback()
{
AssertIsOnMainThread();
}
@@ -2651,16 +2664,23 @@ RuntimeService::UpdateAppVersionOverride
void
RuntimeService::UpdatePlatformOverridePreference(const nsAString& aValue)
{
AssertIsOnMainThread();
mNavigatorProperties.mPlatformOverridden = aValue;
}
void
+RuntimeService::UpdateResistFingerprintingPreference(bool aResistFingerprinting)
+{
+ AssertIsOnMainThread();
+ BROADCAST_ALL_WORKERS(UpdateResistFingerprinting, aResistFingerprinting);
+}
+
+void
RuntimeService::UpdateAllWorkerPreference(WorkerPreference aPref, bool aValue)
{
BROADCAST_ALL_WORKERS(UpdatePreference, aPref, aValue);
}
void
RuntimeService::UpdateAllWorkerLanguages(const nsTArray<nsString>& aLanguages)
{
--- a/dom/workers/RuntimeService.h
+++ b/dom/workers/RuntimeService.h
@@ -192,16 +192,19 @@ public:
void
UpdateAppVersionOverridePreference(const nsAString& aValue);
void
UpdatePlatformOverridePreference(const nsAString& aValue);
void
+ UpdateResistFingerprintingPreference(bool aResistFingerprinting);
+
+ void
UpdateAllWorkerContextOptions();
void
UpdateAllWorkerLanguages(const nsTArray<nsString>& aLanguages);
void
UpdateAllWorkerPreference(WorkerPreference aPref, bool aValue);
--- a/dom/workers/WorkerPrefs.h
+++ b/dom/workers/WorkerPrefs.h
@@ -42,11 +42,12 @@ WORKER_SIMPLE_PREF("gfx.offscreencanvas.
WORKER_SIMPLE_PREF("dom.webkitBlink.dirPicker.enabled", WebkitBlinkDirectoryPickerEnabled, DOM_WEBKITBLINK_DIRPICKER_WEBKITBLINK)
WORKER_SIMPLE_PREF("dom.netinfo.enabled", NetworkInformationEnabled, NETWORKINFORMATION_ENABLED)
WORKER_SIMPLE_PREF("dom.fetchController.enabled", FetchControllerEnabled, FETCHCONTROLLER_ENABLED)
WORKER_SIMPLE_PREF("dom.fetchObserver.enabled", FetchObserverEnabled, FETCHOBSERVER_ENABLED)
WORKER_PREF("intl.accept_languages", PrefLanguagesChanged)
WORKER_PREF("general.appname.override", AppNameOverrideChanged)
WORKER_PREF("general.appversion.override", AppVersionOverrideChanged)
WORKER_PREF("general.platform.override", PlatformOverrideChanged)
+WORKER_PREF("privacy.resistFingerprinting", ResistFingerprintingChanged)
#ifdef JS_GC_ZEAL
WORKER_PREF("dom.workers.options.gcZeal", LoadGCZealOptions)
#endif
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -1322,16 +1322,36 @@ private:
virtual bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
{
aWorkerPrivate->UpdateContextOptionsInternal(aCx, mContextOptions);
return true;
}
};
+class UpdateResistFingerprintingRunnable final : public WorkerControlRunnable
+{
+ bool mResistFingerprinting;
+
+public:
+ UpdateResistFingerprintingRunnable(WorkerPrivate* aWorkerPrivate,
+ bool aResistFingerprinting)
+ : WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount),
+ mResistFingerprinting(aResistFingerprinting)
+ { }
+
+private:
+ virtual bool
+ WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
+ {
+ aWorkerPrivate->UpdateResistFingerprintingInternal(mResistFingerprinting);
+ return true;
+ }
+};
+
class UpdatePreferenceRunnable final : public WorkerControlRunnable
{
WorkerPreference mPref;
bool mValue;
public:
UpdatePreferenceRunnable(WorkerPrivate* aWorkerPrivate,
WorkerPreference aPref,
@@ -3427,16 +3447,30 @@ WorkerPrivateParent<Derived>::UpdateCont
new UpdateContextOptionsRunnable(ParentAsWorkerPrivate(), aContextOptions);
if (!runnable->Dispatch()) {
NS_WARNING("Failed to update worker context options!");
}
}
template <class Derived>
void
+WorkerPrivateParent<Derived>::UpdateResistFingerprinting(bool aResistFingerprinting)
+{
+ AssertIsOnParentThread();
+
+ RefPtr<UpdateResistFingerprintingRunnable> runnable =
+ new UpdateResistFingerprintingRunnable(ParentAsWorkerPrivate(),
+ aResistFingerprinting);
+ if (!runnable->Dispatch()) {
+ NS_WARNING("Failed to update worker time precision!");
+ }
+}
+
+template <class Derived>
+void
WorkerPrivateParent<Derived>::UpdatePreference(WorkerPreference aPref, bool aValue)
{
AssertIsOnParentThread();
MOZ_ASSERT(aPref >= 0 && aPref < WORKERPREF_COUNT);
RefPtr<UpdatePreferenceRunnable> runnable =
new UpdatePreferenceRunnable(ParentAsWorkerPrivate(), aPref, aValue);
if (!runnable->Dispatch()) {
@@ -4449,21 +4483,23 @@ WorkerPrivate::WorkerPrivate(WorkerPriva
{
MOZ_ASSERT_IF(!IsDedicatedWorker(), !aWorkerName.IsVoid());
MOZ_ASSERT_IF(IsDedicatedWorker(), aWorkerName.IsEmpty());
if (aParent) {
aParent->AssertIsOnWorkerThread();
aParent->GetAllPreferences(mPreferences);
mOnLine = aParent->OnLine();
+ mResistFingerprinting = aParent->ResistFingerprinting();
}
else {
AssertIsOnMainThread();
RuntimeService::GetDefaultPreferences(mPreferences);
mOnLine = !NS_IsOffline();
+ mResistFingerprinting = nsContentUtils::ShouldResistFingerprinting();
}
nsCOMPtr<nsIEventTarget> target;
// A child worker just inherits the parent workers ThrottledEventQueue
// and main thread target for now. This is mainly due to the restriction
// that ThrottledEventQueue can only be created on the main thread at the
// moment.
@@ -4970,16 +5006,18 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
{
MutexAutoLock lock(mMutex);
mJSContext = aCx;
MOZ_ASSERT(mStatus == Pending);
mStatus = Running;
}
+ JS::ContextOptionsRef(mJSContext).setResistFingerprinting(mResistFingerprinting);
+
// Now that we've done that, we can go ahead and set up our AutoJSAPI. We
// can't before this point, because it can't find the right JSContext before
// then, since it gets it from our mJSContext.
AutoJSAPI jsapi;
jsapi.Init();
MOZ_ASSERT(jsapi.cx() == aCx);
EnableMemoryReporter();
@@ -6656,16 +6694,29 @@ WorkerPrivate::UpdateLanguagesInternal(c
}
for (uint32_t index = 0; index < mChildWorkers.Length(); index++) {
mChildWorkers[index]->UpdateLanguages(aLanguages);
}
}
void
+WorkerPrivate::UpdateResistFingerprintingInternal(bool aResistFingerprinting)
+{
+ AssertIsOnWorkerThread();
+
+ JS::ContextOptionsRef(mJSContext).setResistFingerprinting(aResistFingerprinting);
+ mResistFingerprinting = aResistFingerprinting;
+
+ for (uint32_t index = 0; index < mChildWorkers.Length(); index++) {
+ mChildWorkers[index]->UpdateResistFingerprinting(aResistFingerprinting);
+ }
+}
+
+void
WorkerPrivate::UpdatePreferenceInternal(WorkerPreference aPref, bool aValue)
{
AssertIsOnWorkerThread();
MOZ_ASSERT(aPref >= 0 && aPref < WORKERPREF_COUNT);
mPreferences[aPref] = aValue;
for (uint32_t index = 0; index < mChildWorkers.Length(); index++) {
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -402,16 +402,19 @@ public:
void
UpdateContextOptions(const JS::ContextOptions& aContextOptions);
void
UpdateLanguages(const nsTArray<nsString>& aLanguages);
void
+ UpdateResistFingerprinting(bool aResistFingerprinting);
+
+ void
UpdatePreference(WorkerPreference aPref, bool aValue);
void
UpdateJSWorkerMemoryParameter(JSGCParamKey key, uint32_t value);
#ifdef JS_GC_ZEAL
void
UpdateGCZeal(uint8_t aGCZeal, uint32_t aFrequency);
@@ -1041,16 +1044,17 @@ class WorkerPrivate : public WorkerPriva
bool mPendingEventQueueClearing;
bool mCancelAllPendingRunnables;
bool mPeriodicGCTimerRunning;
bool mIdleGCTimerRunning;
bool mWorkerScriptExecutedSuccessfully;
bool mFetchHandlerWasAdded;
bool mPreferences[WORKERPREF_COUNT];
bool mOnLine;
+ bool mResistFingerprinting;
protected:
~WorkerPrivate();
public:
static already_AddRefed<WorkerPrivate>
Constructor(const GlobalObject& aGlobal, const nsAString& aScriptURL,
ErrorResult& aRv);
@@ -1242,16 +1246,19 @@ public:
void
UpdateContextOptionsInternal(JSContext* aCx, const JS::ContextOptions& aContextOptions);
void
UpdateLanguagesInternal(const nsTArray<nsString>& aLanguages);
void
+ UpdateResistFingerprintingInternal(bool aResistFingerprinting);
+
+ void
UpdatePreferenceInternal(WorkerPreference aPref, bool aValue);
void
UpdateJSWorkerMemoryParameterInternal(JSContext* aCx, JSGCParamKey key, uint32_t aValue);
enum WorkerRanOrNot {
WorkerNeverRan = 0,
WorkerRan
@@ -1385,16 +1392,23 @@ public:
bool
OnLine() const
{
AssertIsOnWorkerThread();
return mOnLine;
}
+ bool
+ ResistFingerprinting() const
+ {
+ AssertIsOnWorkerThread();
+ return mResistFingerprinting;
+ }
+
void
StopSyncLoop(nsIEventTarget* aSyncLoopTarget, bool aResult);
bool
AllPendingRunnablesShouldBeCanceled() const
{
return mCancelAllPendingRunnables;
}
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1139,16 +1139,17 @@ class JS_PUBLIC_API(ContextOptions) {
ContextOptions()
: baseline_(true),
ion_(true),
asmJS_(true),
wasm_(false),
wasmAlwaysBaseline_(false),
throwOnAsmJSValidationFailure_(false),
nativeRegExp_(true),
+ resistFingerprinting_(false),
unboxedArrays_(false),
asyncStack_(true),
throwOnDebuggeeWouldRun_(true),
dumpStackOnDebuggeeWouldRun_(false),
werror_(false),
strictMode_(false),
extraWarnings_(false),
#ifdef NIGHTLY_BUILD
@@ -1220,16 +1221,22 @@ class JS_PUBLIC_API(ContextOptions) {
}
bool nativeRegExp() const { return nativeRegExp_; }
ContextOptions& setNativeRegExp(bool flag) {
nativeRegExp_ = flag;
return *this;
}
+ bool resistFingerprinting() const { return resistFingerprinting_; }
+ ContextOptions& setResistFingerprinting(bool flag) {
+ resistFingerprinting_ = flag;
+ return *this;
+ }
+
bool unboxedArrays() const { return unboxedArrays_; }
ContextOptions& setUnboxedArrays(bool flag) {
unboxedArrays_ = flag;
return *this;
}
bool asyncStack() const { return asyncStack_; }
ContextOptions& setAsyncStack(bool flag) {
@@ -1296,16 +1303,17 @@ class JS_PUBLIC_API(ContextOptions) {
private:
bool baseline_ : 1;
bool ion_ : 1;
bool asmJS_ : 1;
bool wasm_ : 1;
bool wasmAlwaysBaseline_ : 1;
bool throwOnAsmJSValidationFailure_ : 1;
bool nativeRegExp_ : 1;
+ bool resistFingerprinting_ : 1;
bool unboxedArrays_ : 1;
bool asyncStack_ : 1;
bool throwOnDebuggeeWouldRun_ : 1;
bool dumpStackOnDebuggeeWouldRun_ : 1;
bool werror_ : 1;
bool strictMode_ : 1;
bool extraWarnings_ : 1;
bool forEachStatement_: 1;
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -349,16 +349,17 @@ struct MOZ_STACK_CLASS EnvironmentPrepar
static bool enableCodeCoverage = false;
static bool enableDisassemblyDumps = false;
static bool offthreadCompilation = false;
static bool enableBaseline = false;
static bool enableIon = false;
static bool enableAsmJS = false;
static bool enableWasm = false;
static bool enableNativeRegExp = false;
+static bool enableResistFingerprinting = false;
static bool enableUnboxedArrays = false;
static bool enableSharedMemory = SHARED_MEMORY_DEFAULT;
static bool enableWasmAlwaysBaseline = false;
#ifdef JS_GC_ZEAL
static uint32_t gZealBits = 0;
static uint32_t gZealFrequency = 0;
#endif
static bool printTiming = false;
@@ -7804,25 +7805,27 @@ ProcessArgs(JSContext* cx, OptionParser*
static bool
SetContextOptions(JSContext* cx, const OptionParser& op)
{
enableBaseline = !op.getBoolOption("no-baseline");
enableIon = !op.getBoolOption("no-ion");
enableAsmJS = !op.getBoolOption("no-asmjs");
enableWasm = !op.getBoolOption("no-wasm");
enableNativeRegExp = !op.getBoolOption("no-native-regexp");
+ enableResistFingerprinting = op.getBoolOption("resist-fingerprinting");
enableUnboxedArrays = op.getBoolOption("unboxed-arrays");
enableWasmAlwaysBaseline = op.getBoolOption("wasm-always-baseline");
JS::ContextOptionsRef(cx).setBaseline(enableBaseline)
.setIon(enableIon)
.setAsmJS(enableAsmJS)
.setWasm(enableWasm)
.setWasmAlwaysBaseline(enableWasmAlwaysBaseline)
.setNativeRegExp(enableNativeRegExp)
+ .setResistFingerprinting(enableResistFingerprinting)
.setUnboxedArrays(enableUnboxedArrays);
if (op.getBoolOption("wasm-check-bce"))
jit::JitOptions.wasmAlwaysCheckBounds = true;
if (op.getBoolOption("wasm-test-mode"))
jit::JitOptions.wasmTestMode = true;
@@ -8097,16 +8100,17 @@ SetWorkerContextOptions(JSContext* cx)
{
// Copy option values from the main thread.
JS::ContextOptionsRef(cx).setBaseline(enableBaseline)
.setIon(enableIon)
.setAsmJS(enableAsmJS)
.setWasm(enableWasm)
.setWasmAlwaysBaseline(enableWasmAlwaysBaseline)
.setNativeRegExp(enableNativeRegExp)
+ .setResistFingerprinting(enableResistFingerprinting)
.setUnboxedArrays(enableUnboxedArrays);
cx->runtime()->setOffthreadIonCompilationEnabled(offthreadCompilation);
cx->runtime()->profilingScripts = enableCodeCoverage || enableDisassemblyDumps;
#ifdef JS_GC_ZEAL
if (gZealBits && gZealFrequency) {
#define ZEAL_MODE(_, value) \
if (gZealBits & (1 << value)) \
@@ -8291,16 +8295,17 @@ main(int argc, char** argv, char** envp)
"shell's global")
|| !op.addIntOption('\0', "thread-count", "COUNT", "Use COUNT auxiliary threads "
"(default: # of cores - 1)", -1)
|| !op.addBoolOption('\0', "ion", "Enable IonMonkey (default)")
|| !op.addBoolOption('\0', "no-ion", "Disable IonMonkey")
|| !op.addBoolOption('\0', "no-asmjs", "Disable asm.js compilation")
|| !op.addBoolOption('\0', "no-wasm", "Disable WebAssembly compilation")
|| !op.addBoolOption('\0', "no-native-regexp", "Disable native regexp compilation")
+ || !op.addBoolOption('\0', "resist-fingerprinting", "Enable anti-fingerprinting features")
|| !op.addBoolOption('\0', "no-unboxed-objects", "Disable creating unboxed plain objects")
|| !op.addBoolOption('\0', "unboxed-arrays", "Allow creating unboxed arrays")
|| !op.addBoolOption('\0', "wasm-always-baseline", "Enable wasm baseline compiler when possible")
|| !op.addBoolOption('\0', "wasm-check-bce", "Always generate wasm bounds check, even redundant ones.")
|| !op.addBoolOption('\0', "wasm-test-mode", "Enable wasm testing mode, creating synthetic "
"objects for non-canonical NaNs and i64 returned from wasm.")
#ifdef ENABLE_SHARED_ARRAY_BUFFER
|| !op.addStringOption('\0', "shared-memory", "on/off",
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -1073,16 +1073,17 @@ ReloadPrefsCallback(const char* pref, vo
bool useBaseline = Preferences::GetBool(JS_OPTIONS_DOT_STR "baselinejit") && !safeMode;
bool useIon = Preferences::GetBool(JS_OPTIONS_DOT_STR "ion") && !safeMode;
bool useAsmJS = Preferences::GetBool(JS_OPTIONS_DOT_STR "asmjs") && !safeMode;
bool useWasm = Preferences::GetBool(JS_OPTIONS_DOT_STR "wasm") && !safeMode;
bool useWasmBaseline = Preferences::GetBool(JS_OPTIONS_DOT_STR "wasm_baselinejit") && !safeMode;
bool throwOnAsmJSValidationFailure = Preferences::GetBool(JS_OPTIONS_DOT_STR
"throw_on_asmjs_validation_failure");
bool useNativeRegExp = Preferences::GetBool(JS_OPTIONS_DOT_STR "native_regexp") && !safeMode;
+ bool resistFingerprinting = Preferences::GetBool("privacy.resistFingerprinting") && !safeMode;
bool parallelParsing = Preferences::GetBool(JS_OPTIONS_DOT_STR "parallel_parsing");
bool offthreadIonCompilation = Preferences::GetBool(JS_OPTIONS_DOT_STR
"ion.offthread_compilation");
bool useBaselineEager = Preferences::GetBool(JS_OPTIONS_DOT_STR
"baselinejit.unsafe_eager_compilation");
bool useIonEager = Preferences::GetBool(JS_OPTIONS_DOT_STR "ion.unsafe_eager_compilation");
#ifdef DEBUG
@@ -1128,16 +1129,17 @@ ReloadPrefsCallback(const char* pref, vo
JS::ContextOptionsRef(cx).setBaseline(useBaseline)
.setIon(useIon)
.setAsmJS(useAsmJS)
.setWasm(useWasm)
.setWasmAlwaysBaseline(useWasmBaseline)
.setThrowOnAsmJSValidationFailure(throwOnAsmJSValidationFailure)
.setNativeRegExp(useNativeRegExp)
+ .setResistFingerprinting(resistFingerprinting)
.setAsyncStack(useAsyncStack)
.setThrowOnDebuggeeWouldRun(throwOnDebuggeeWouldRun)
.setDumpStackOnDebuggeeWouldRun(dumpStackOnDebuggeeWouldRun)
.setWerror(werror)
#ifdef FUZZING
.setFuzzing(fuzzingEnabled)
#endif
.setExtraWarnings(extraWarnings);
@@ -3008,16 +3010,18 @@ XPCJSRuntime::Initialize(JSContext* cx)
RegisterJSMainRuntimeCompartmentsUserDistinguishedAmount(JSMainRuntimeCompartmentsUserDistinguishedAmount);
mozilla::RegisterJSSizeOfTab(JSSizeOfTab);
// Watch for the JS boolean options.
ReloadPrefsCallback(nullptr, nullptr);
Preferences::RegisterPrefixCallback(ReloadPrefsCallback,
JS_OPTIONS_DOT_STR);
+ Preferences::RegisterPrefixCallback(ReloadPrefsCallback,
+ "privacy.resistFingerprinting");
#ifdef FUZZING
Preferences::RegisterCallback(ReloadPrefsCallback, "fuzzing.enabled");
#endif
}
bool
XPCJSRuntime::InitializeStrings(JSContext* cx)
{