author | Nicholas Nethercote <nnethercote@mozilla.com> |
Fri, 23 Mar 2018 15:15:22 +1100 | |
changeset 771490 | 94997d5f0885ea568f01a264d5811ba9813077c8 |
parent 771489 | 73be150e8abf58cc8436dc30f3be08a7a6373c45 |
child 771495 | 8fd78713cfa0834d61cf612cde0b6140df5e8504 |
push id | 103687 |
push user | nnethercote@mozilla.com |
push date | Fri, 23 Mar 2018 04:16:02 +0000 |
reviewers | glandium |
bugs | 1436655, 1346224 |
milestone | 61.0a1 |
--- a/modules/libpref/Preferences.cpp +++ b/modules/libpref/Preferences.cpp @@ -22,16 +22,17 @@ #include "mozilla/MemoryReporting.h" #include "mozilla/ModuleUtils.h" #include "mozilla/Omnijar.h" #include "mozilla/Preferences.h" #include "mozilla/ResultExtensions.h" #include "mozilla/ScopeExit.h" #include "mozilla/Services.h" #include "mozilla/ServoStyleSet.h" +#include "mozilla/StaticPrefs.h" #include "mozilla/SyncRunnable.h" #include "mozilla/Telemetry.h" #include "mozilla/UniquePtrExtensions.h" #include "mozilla/URLPreloader.h" #include "mozilla/Variant.h" #include "mozilla/Vector.h" #include "nsAppDirectoryServiceDefs.h" #include "nsAutoPtr.h" @@ -3243,17 +3244,20 @@ Preferences::GetInstanceForService() MOZ_ASSERT(!gHashTable); gHashTable = new PLDHashTable( &pref_HashTableOps, sizeof(PrefEntry), PREF_HASHTABLE_INITIAL_LENGTH); gTelemetryLoadData = new nsDataHashtable<nsCStringHashKey, TelemetryLoadData>(); - Result<Ok, const char*> res = InitInitialObjects(); + gCacheData = new nsTArray<nsAutoPtr<CacheData>>(); + gCacheDataDesc = "set by GetInstanceForService() (1)"; + + Result<Ok, const char*> res = InitInitialObjects(/* isStartup */ true); if (res.isErr()) { sPreferences = nullptr; gCacheDataDesc = res.unwrapErr(); return nullptr; } if (!XRE_IsParentProcess()) { MOZ_ASSERT(gChangedDomPrefs); @@ -3298,18 +3302,17 @@ Preferences::GetInstanceForService() if (NS_FAILED(rv)) { sPreferences = nullptr; gCacheDataDesc = "AddObserver(\"profile-before-change\") failed"; return nullptr; } } - gCacheData = new nsTArray<nsAutoPtr<CacheData>>(); - gCacheDataDesc = "set by GetInstanceForService()"; + gCacheDataDesc = "set by GetInstanceForService() (2)"; // Preferences::GetInstanceForService() can be called from GetService(), and // RegisterStrongMemoryReporter calls GetService(nsIMemoryReporter). To // avoid a potential recursive GetService() call, we can't register the // memory reporter here; instead, do it off a runnable. RefPtr<AddPreferencesMemoryReporterRunnable> runnable = new AddPreferencesMemoryReporterRunnable(); NS_DispatchToMainThread(runnable); @@ -3480,17 +3483,17 @@ Preferences::Observe(nsISupports* aSubje // set a pref. A blocking save here re-saves if necessary and also waits // for any pending saves to complete. SavePrefFileBlocking(); MOZ_ASSERT(!mDirty, "Preferences should not be dirty"); mProfileShutdown = true; } else if (!nsCRT::strcmp(aTopic, "reload-default-prefs")) { // Reload the default prefs from file. - Unused << InitInitialObjects(); + Unused << InitInitialObjects(/* isStartup */ false); } else if (!nsCRT::strcmp(aTopic, "suspend_process_notification")) { // Our process is being suspended. The OS may wake our process later, // or it may kill the process. In case our process is going to be killed // from the suspended state, we save preferences before suspending. rv = SavePrefFileBlocking(); } @@ -3526,17 +3529,18 @@ Preferences::ReadUserPrefsFromFile(nsIFi NS_IMETHODIMP Preferences::ResetPrefs() { ENSURE_PARENT_PROCESS("Preferences::ResetPrefs", "all prefs"); gHashTable->ClearAndPrepareForLength(PREF_HASHTABLE_INITIAL_LENGTH); gPrefNameArena.Clear(); - return InitInitialObjects().isOk() ? NS_OK : NS_ERROR_FAILURE; + return InitInitialObjects(/* isStartup */ false).isOk() ? NS_OK + : NS_ERROR_FAILURE; } NS_IMETHODIMP Preferences::ResetUserPrefs() { ENSURE_PARENT_PROCESS("Preferences::ResetUserPrefs", "all prefs"); NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE); MOZ_ASSERT(NS_IsMainThread()); @@ -4101,17 +4105,17 @@ pref_ReadPrefFromJar(nsZipArchive* aJarR } return NS_OK; } // Initialize default preference JavaScript buffers from appropriate TEXT // resources. /* static */ Result<Ok, const char*> -Preferences::InitInitialObjects() +Preferences::InitInitialObjects(bool aIsStartup) { // In the omni.jar case, we load the following prefs: // - jar:$gre/omni.jar!/greprefs.js // - jar:$gre/omni.jar!/defaults/pref/*.js // // In the non-omni.jar case, we load: // - $gre/greprefs.js // @@ -4265,16 +4269,21 @@ Preferences::InitInitialObjects() continue; } // Do we care if a file provided by this process fails to load? pref_LoadPrefsInDir(path, nullptr, 0); } } + // We initialize static prefs after prefs from data files so that we can + // detect and complain if there are any static prefs that are also defined in + // data files. + StaticPrefs::InitAll(aIsStartup); + if (XRE_IsParentProcess()) { SetupTelemetryPref(); } NS_CreateServicesFromCategory(NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID, nullptr, NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID); @@ -4733,20 +4742,25 @@ static void BoolVarChanged(const char* aPref, void* aClosure) { CacheData* cache = static_cast<CacheData*>(aClosure); *static_cast<bool*>(cache->mCacheLocation) = Preferences::GetBool(aPref, cache->mDefaultValueBool); } /* static */ nsresult -Preferences::AddBoolVarCache(bool* aCache, const char* aPref, bool aDefault) +Preferences::AddBoolVarCache(bool* aCache, + const char* aPref, + bool aDefault, + bool aSkipAssignment) { AssertNotAlreadyCached("bool", aPref, aCache); - *aCache = GetBool(aPref, aDefault); + if (!aSkipAssignment) { + *aCache = GetBool(aPref, aDefault); + } CacheData* data = new CacheData(); data->mCacheLocation = aCache; data->mDefaultValueBool = aDefault; CacheDataAppendElement(data); Preferences::RegisterCallback(BoolVarChanged, aPref, data, Preferences::ExactMatch, @@ -4762,20 +4776,23 @@ AtomicBoolVarChanged(const char* aPref, *static_cast<Atomic<bool, Order>*>(cache->mCacheLocation) = Preferences::GetBool(aPref, cache->mDefaultValueBool); } template<MemoryOrdering Order> /* static */ nsresult Preferences::AddAtomicBoolVarCache(Atomic<bool, Order>* aCache, const char* aPref, - bool aDefault) + bool aDefault, + bool aSkipAssignment) { AssertNotAlreadyCached("bool", aPref, aCache); - *aCache = Preferences::GetBool(aPref, aDefault); + if (!aSkipAssignment) { + *aCache = GetBool(aPref, aDefault); + } CacheData* data = new CacheData(); data->mCacheLocation = aCache; data->mDefaultValueBool = aDefault; CacheDataAppendElement(data); Preferences::RegisterCallback(AtomicBoolVarChanged<Order>, aPref, data, Preferences::ExactMatch, @@ -4789,20 +4806,23 @@ IntVarChanged(const char* aPref, void* a CacheData* cache = static_cast<CacheData*>(aClosure); *static_cast<int32_t*>(cache->mCacheLocation) = Preferences::GetInt(aPref, cache->mDefaultValueInt); } /* static */ nsresult Preferences::AddIntVarCache(int32_t* aCache, const char* aPref, - int32_t aDefault) + int32_t aDefault, + bool aSkipAssignment) { AssertNotAlreadyCached("int", aPref, aCache); - *aCache = Preferences::GetInt(aPref, aDefault); + if (!aSkipAssignment) { + *aCache = GetInt(aPref, aDefault); + } CacheData* data = new CacheData(); data->mCacheLocation = aCache; data->mDefaultValueInt = aDefault; CacheDataAppendElement(data); Preferences::RegisterCallback( IntVarChanged, aPref, data, Preferences::ExactMatch, /* isPriority */ true); return NS_OK; } @@ -4815,20 +4835,23 @@ AtomicIntVarChanged(const char* aPref, v *static_cast<Atomic<int32_t, Order>*>(cache->mCacheLocation) = Preferences::GetInt(aPref, cache->mDefaultValueUint); } template<MemoryOrdering Order> /* static */ nsresult Preferences::AddAtomicIntVarCache(Atomic<int32_t, Order>* aCache, const char* aPref, - int32_t aDefault) + int32_t aDefault, + bool aSkipAssignment) { AssertNotAlreadyCached("int", aPref, aCache); - *aCache = Preferences::GetInt(aPref, aDefault); + if (!aSkipAssignment) { + *aCache = GetInt(aPref, aDefault); + } CacheData* data = new CacheData(); data->mCacheLocation = aCache; data->mDefaultValueUint = aDefault; CacheDataAppendElement(data); Preferences::RegisterCallback(AtomicIntVarChanged<Order>, aPref, data, Preferences::ExactMatch, @@ -4842,20 +4865,23 @@ UintVarChanged(const char* aPref, void* CacheData* cache = static_cast<CacheData*>(aClosure); *static_cast<uint32_t*>(cache->mCacheLocation) = Preferences::GetUint(aPref, cache->mDefaultValueUint); } /* static */ nsresult Preferences::AddUintVarCache(uint32_t* aCache, const char* aPref, - uint32_t aDefault) + uint32_t aDefault, + bool aSkipAssignment) { AssertNotAlreadyCached("uint", aPref, aCache); - *aCache = Preferences::GetUint(aPref, aDefault); + if (!aSkipAssignment) { + *aCache = GetUint(aPref, aDefault); + } CacheData* data = new CacheData(); data->mCacheLocation = aCache; data->mDefaultValueUint = aDefault; CacheDataAppendElement(data); Preferences::RegisterCallback(UintVarChanged, aPref, data, Preferences::ExactMatch, @@ -4871,88 +4897,320 @@ AtomicUintVarChanged(const char* aPref, *static_cast<Atomic<uint32_t, Order>*>(cache->mCacheLocation) = Preferences::GetUint(aPref, cache->mDefaultValueUint); } template<MemoryOrdering Order> /* static */ nsresult Preferences::AddAtomicUintVarCache(Atomic<uint32_t, Order>* aCache, const char* aPref, - uint32_t aDefault) + uint32_t aDefault, + bool aSkipAssignment) { AssertNotAlreadyCached("uint", aPref, aCache); - *aCache = Preferences::GetUint(aPref, aDefault); + if (!aSkipAssignment) { + *aCache = GetUint(aPref, aDefault); + } CacheData* data = new CacheData(); data->mCacheLocation = aCache; data->mDefaultValueUint = aDefault; CacheDataAppendElement(data); Preferences::RegisterCallback(AtomicUintVarChanged<Order>, aPref, data, Preferences::ExactMatch, /* isPriority */ true); return NS_OK; } // Since the definition of template functions is not in a header file, we // need to explicitly specify the instantiations that are required. Currently // limited orders are needed and therefore implemented. template nsresult -Preferences::AddAtomicBoolVarCache(Atomic<bool, Relaxed>*, const char*, bool); +Preferences::AddAtomicBoolVarCache(Atomic<bool, Relaxed>*, + const char*, + bool, + bool); template nsresult Preferences::AddAtomicBoolVarCache(Atomic<bool, ReleaseAcquire>*, const char*, + bool, bool); template nsresult Preferences::AddAtomicBoolVarCache(Atomic<bool, SequentiallyConsistent>*, const char*, + bool, bool); template nsresult Preferences::AddAtomicIntVarCache(Atomic<int32_t, Relaxed>*, const char*, - int32_t); + int32_t, + bool); template nsresult Preferences::AddAtomicUintVarCache(Atomic<uint32_t, Relaxed>*, const char*, - uint32_t); + uint32_t, + bool); template nsresult Preferences::AddAtomicUintVarCache(Atomic<uint32_t, ReleaseAcquire>*, const char*, - uint32_t); + uint32_t, + bool); static void FloatVarChanged(const char* aPref, void* aClosure) { CacheData* cache = static_cast<CacheData*>(aClosure); *static_cast<float*>(cache->mCacheLocation) = Preferences::GetFloat(aPref, cache->mDefaultValueFloat); } /* static */ nsresult -Preferences::AddFloatVarCache(float* aCache, const char* aPref, float aDefault) +Preferences::AddFloatVarCache(float* aCache, + const char* aPref, + float aDefault, + bool aSkipAssignment) { AssertNotAlreadyCached("float", aPref, aCache); - *aCache = Preferences::GetFloat(aPref, aDefault); + if (!aSkipAssignment) { + *aCache = GetFloat(aPref, aDefault); + } CacheData* data = new CacheData(); data->mCacheLocation = aCache; data->mDefaultValueFloat = aDefault; CacheDataAppendElement(data); Preferences::RegisterCallback(FloatVarChanged, aPref, data, Preferences::ExactMatch, /* isPriority */ true); return NS_OK; } +// For a VarCache pref like this: +// +// VARCACHE_PREF("my.varcache", my_varcache, int32_t, 99) +// +// we generate a static variable definition and a getter definition: +// +// int32_t StaticPrefs::sVarCache_my_varcache(99); +// int32_t StaticPrefs::my_varcache() { return sVarCache_my_varcache; } +// +#define PREF(name, cpp_type, value) +#define VARCACHE_PREF(name, id, cpp_type, value) \ + cpp_type StaticPrefs::sVarCache_##id(value); \ + StripAtomic<cpp_type> StaticPrefs::id() { return sVarCache_##id; } +#include "mozilla/StaticPrefList.h" +#undef PREF +#undef VARCACHE_PREF + +static void +CheckForExistence(const char* aName) +{ +#ifdef DEBUG + // If this warning is hit, it's probably because a pref is present in both a + // data file (such as all.js) and StaticPrefsList.h, which is not desirable. + if (Preferences::GetType(aName) != Preferences::PREF_INVALID) { + NS_ERROR(nsPrintfCString("'%s' already registered\n", aName).get()); + } +#endif +} + +// The SetPref_*() functions below end in a `_<type>` suffix because they are +// used by the PREF macro definition in InitAll() below. + +static void +SetPref_bool(const char* aName, bool aDefaultValue) +{ + CheckForExistence(aName); + PrefValue value; + value.mBoolVal = aDefaultValue; + pref_SetPref(aName, + PrefType::Bool, + PrefValueKind::Default, + value, + /* isSticky */ false, + /* isLocked */ false, + /* fromInit */ true); +} + +static void +SetPref_int32_t(const char* aName, int32_t aDefaultValue) +{ + CheckForExistence(aName); + PrefValue value; + value.mIntVal = aDefaultValue; + pref_SetPref(aName, + PrefType::Int, + PrefValueKind::Default, + value, + /* isSticky */ false, + /* isLocked */ false, + /* fromInit */ true); +} + +static void +SetPref_float(const char* aName, float aDefaultValue) +{ + CheckForExistence(aName); + PrefValue value; + nsPrintfCString defaultValue("%f", aDefaultValue); + value.mStringVal = defaultValue.get(); + pref_SetPref(aName, + PrefType::String, + PrefValueKind::Default, + value, + /* isSticky */ false, + /* isLocked */ false, + /* fromInit */ true); +} + +// XXX: this will eventually become used +MOZ_MAYBE_UNUSED static void +SetPref_String(const char* aName, const char* aDefaultValue) +{ + CheckForExistence(aName); + PrefValue value; + value.mStringVal = aDefaultValue; + pref_SetPref(aName, + PrefType::String, + PrefValueKind::Default, + value, + /* isSticky */ false, + /* isLocked */ false, + /* fromInit */ true); +} + +static void +InitVarCachePref(const char* aName, + bool* aCache, + bool aDefaultValue, + bool aIsStartup) +{ + SetPref_bool(aName, aDefaultValue); + *aCache = aDefaultValue; + if (aIsStartup) { + Preferences::AddBoolVarCache(aCache, aName, aDefaultValue, true); + } +} + +template<MemoryOrdering Order> +static void +InitVarCachePref(const char* aName, + Atomic<bool, Order>* aCache, + bool aDefaultValue, + bool aIsStartup) +{ + SetPref_bool(aName, aDefaultValue); + *aCache = aDefaultValue; + if (aIsStartup) { + Preferences::AddAtomicBoolVarCache(aCache, aName, aDefaultValue, true); + } +} + +// XXX: this will eventually become used +MOZ_MAYBE_UNUSED static void +InitVarCachePref(const char* aName, + int32_t* aCache, + int32_t aDefaultValue, + bool aIsStartup) +{ + SetPref_int32_t(aName, aDefaultValue); + *aCache = aDefaultValue; + if (aIsStartup) { + Preferences::AddIntVarCache(aCache, aName, aDefaultValue, true); + } +} + +template<MemoryOrdering Order> +static void +InitVarCachePref(const char* aName, + Atomic<int32_t, Order>* aCache, + int32_t aDefaultValue, + bool aIsStartup) +{ + SetPref_int32_t(aName, aDefaultValue); + *aCache = aDefaultValue; + if (aIsStartup) { + Preferences::AddAtomicIntVarCache(aCache, aName, aDefaultValue, true); + } +} + +static void +InitVarCachePref(const char* aName, + uint32_t* aCache, + uint32_t aDefaultValue, + bool aIsStartup) +{ + SetPref_int32_t(aName, static_cast<int32_t>(aDefaultValue)); + *aCache = aDefaultValue; + if (aIsStartup) { + Preferences::AddUintVarCache(aCache, aName, aDefaultValue, true); + } +} + +template<MemoryOrdering Order> +static void +InitVarCachePref(const char* aName, + Atomic<uint32_t, Order>* aCache, + uint32_t aDefaultValue, + bool aIsStartup) +{ + SetPref_int32_t(aName, static_cast<int32_t>(aDefaultValue)); + *aCache = aDefaultValue; + if (aIsStartup) { + Preferences::AddAtomicUintVarCache(aCache, aName, aDefaultValue, true); + } +} + +// XXX: this will eventually become used +MOZ_MAYBE_UNUSED static void +InitVarCachePref(const char* aName, + float* aCache, + float aDefaultValue, + bool aIsStartup) +{ + SetPref_float(aName, aDefaultValue); + *aCache = aDefaultValue; + if (aIsStartup) { + Preferences::AddFloatVarCache(aCache, aName, aDefaultValue, true); + } +} + +/* static */ void +StaticPrefs::InitAll(bool aIsStartup) +{ +// For prefs like these: +// +// PREF("foo.bar.baz", bool, true) +// VARCACHE_PREF("my.varcache", my_varcache, int32_t, 99) +// +// we generate registration calls: +// +// SetPref_bool("foo.bar.baz", true); +// InitVarCachePref("my.varcache", &StaticPrefs::sVarCache_my_varcache, 99, +// aIsStartup); +// +// The SetPref_*() functions have a type suffix to avoid ambiguity between +// prefs having int32_t and float default values. That suffix is not needed for +// the InitVarCachePref() functions because they take a pointer parameter, +// which prevents automatic int-to-float coercion. +#define PREF(name, cpp_type, value) SetPref_##cpp_type(name, value); +#define VARCACHE_PREF(name, id, cpp_type, value) \ + InitVarCachePref(name, &StaticPrefs::sVarCache_##id, value, aIsStartup); +#include "mozilla/StaticPrefList.h" +#undef PREF +#undef VARCACHE_PREF +} + } // namespace mozilla #undef ENSURE_PARENT_PROCESS //=========================================================================== // Module and factory stuff //===========================================================================
--- a/modules/libpref/Preferences.h +++ b/modules/libpref/Preferences.h @@ -300,38 +300,45 @@ public: } // Adds the aVariable to cache table. |aVariable| must be a pointer for a // static variable. The value will be modified when the pref value is changed // but note that even if you modified it, the value isn't assigned to the // pref. static nsresult AddBoolVarCache(bool* aVariable, const char* aPref, - bool aDefault = false); + bool aDefault = false, + bool aSkipAssignment = false); template<MemoryOrdering Order> static nsresult AddAtomicBoolVarCache(Atomic<bool, Order>* aVariable, const char* aPref, - bool aDefault = false); + bool aDefault = false, + bool aSkipAssignment = false); static nsresult AddIntVarCache(int32_t* aVariable, const char* aPref, - int32_t aDefault = 0); + int32_t aDefault = 0, + bool aSkipAssignment = false); template<MemoryOrdering Order> static nsresult AddAtomicIntVarCache(Atomic<int32_t, Order>* aVariable, const char* aPref, - int32_t aDefault = 0); + int32_t aDefault = 0, + bool aSkipAssignment = false); static nsresult AddUintVarCache(uint32_t* aVariable, const char* aPref, - uint32_t aDefault = 0); + uint32_t aDefault = 0, + bool aSkipAssignment = false); template<MemoryOrdering Order> static nsresult AddAtomicUintVarCache(Atomic<uint32_t, Order>* aVariable, const char* aPref, - uint32_t aDefault = 0); + uint32_t aDefault = 0, + bool aSkipAssignment = false); static nsresult AddFloatVarCache(float* aVariable, const char* aPref, - float aDefault = 0.0f); + float aDefault = 0.0f, + bool aSkipAssignment = false); // When a content process is created these methods are used to pass changed // prefs in bulk from the parent process, via shared memory. static void SerializePreferences(nsCString& aStr); static void DeserializePreferences(char* aStr, size_t aPrefsLen); // When a single pref is changed in the parent process, these methods are // used to pass the update to content processes. @@ -389,17 +396,18 @@ public: enum MatchKind { PrefixMatch, ExactMatch, }; private: static void SetupTelemetryPref(); - static mozilla::Result<mozilla::Ok, const char*> InitInitialObjects(); + static mozilla::Result<mozilla::Ok, const char*> InitInitialObjects( + bool aIsStartup); static nsresult RegisterCallback(PrefChangedFunc aCallback, const char* aPref, void* aClosure, MatchKind aMatchKind, bool aIsPriority = false); static nsresult UnregisterCallback(PrefChangedFunc aCallback, const char* aPref,
new file mode 100644 --- /dev/null +++ b/modules/libpref/StaticPrefs.h @@ -0,0 +1,74 @@ +/* -*- 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 mozilla_StaticPrefs_h +#define mozilla_StaticPrefs_h + +namespace mozilla { + +// These typedefs are for use within StaticPrefList.h. + +typedef const char* String; + +typedef Atomic<bool, Relaxed> RelaxedAtomicBool; +typedef Atomic<bool, ReleaseAcquire> ReleaseAcquireAtomicBool; +typedef Atomic<bool, SequentiallyConsistent> SequentiallyConsistentAtomicBool; + +typedef Atomic<int32_t, Relaxed> RelaxedAtomicInt32; +typedef Atomic<int32_t, ReleaseAcquire> ReleaseAcquireAtomicInt32; +typedef Atomic<int32_t, SequentiallyConsistent> + SequentiallyConsistentAtomicInt32; + +typedef Atomic<uint32_t, Relaxed> RelaxedAtomicUint32; +typedef Atomic<uint32_t, ReleaseAcquire> ReleaseAcquireAtomicUint32; +typedef Atomic<uint32_t, SequentiallyConsistent> + SequentiallyConsistentAtomicUint32; + +template<typename T> +struct StripAtomicImpl +{ + typedef T Type; +}; + +template<typename T, MemoryOrdering Order> +struct StripAtomicImpl<Atomic<T, Order>> +{ + typedef T Type; +}; + +template<typename T> +using StripAtomic = typename StripAtomicImpl<T>::Type; + +class StaticPrefs +{ +// For a VarCache pref like this: +// +// VARCACHE_PREF("my.varcache", my_varcache, int32_t, 99) +// +// we generate a static variable declaration and a getter declaration: +// +// private: +// static int32_t sVarCache_my_varcache; +// public: +// static int32_t my_varcache(); +// +#define PREF(str, cpp_type, value) +#define VARCACHE_PREF(str, id, cpp_type, value) \ +private: \ + static cpp_type sVarCache_##id; \ +public: \ + static StripAtomic<cpp_type> id(); +#include "mozilla/StaticPrefList.h" +#undef PREF +#undef VARCACHE_PREF + +public: + static void InitAll(bool aIsStartup); +}; + +} // namespace mozilla + +#endif // mozilla_StaticPrefs_h
new file mode 100644 --- /dev/null +++ b/modules/libpref/init/StaticPrefList.h @@ -0,0 +1,124 @@ +/* -*- 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/. */ + +// This file defines static prefs, i.e. those that are defined at startup and +// used entirely or mostly from C++ code. +// +// Prefs defined in this file should *not* be listed in a prefs data file such +// as all.js. If they are, CheckForExistence() will issue an NS_ERROR. +// +// The file is separated into sections, where the sections are determined by +// the first segment of the prefnames within (e.g. "network.predictor.enabled" +// is within the "Network" section). Sections should be kept in alphabetical +// order, but prefs within sections need not be. +// +// Normal prefs +// ------------ +// Definitions of normal prefs in this file have the following form. +// +// PREF(<pref-name-string>, <cpp-type>, <default-value>) +// +// - <pref-name-string> is the name of the pref, as it appears in about:config. +// It is used in most libpref API functions (from both C++ and JS code). +// +// - <cpp-type> is one of bool, int32_t, float, or String (which is just a +// typedef for `const char*` in StaticPrefs.h). Note that float prefs are +// stored internally as floats. +// +// - <default-value> is the default value. Its type should match <cpp-type>. +// +// VarCache prefs +// -------------- +// A VarCache pref is a special type of pref. It can be accessed via the normal +// pref hash table lookup functions, but it also has an associated global +// variable (the VarCache) that mirrors the pref value in the prefs hash table, +// and a getter function that reads that global variable. Using the getter to +// read the pref's value has the two following advantages over the normal API +// functions. +// +// - A direct global variable access is faster than a hash table lookup. +// +// - A global variable can be accessed off the main thread. If a pref *is* +// accessed off the main thread, it should use an atomic type. (But note that +// many VarCaches that should be atomic are not, in particular because +// Atomic<float> is not available, alas.) +// +// Definitions of VarCache prefs in this file has the following form. +// +// VARCACHE_PREF( +// <pref-name-string>, +// <pref-name-id>, +// <cpp-type>, <default-value> +// ) +// +// - <pref-name-string> is the same as for normal prefs. +// +// - <pref-name-id> is the name of the static getter function generated within +// the StaticPrefs class. For consistency, the identifier for every pref +// should be created by starting with <pref-name-string> and converting any +// '.' or '-' chars to '_'. For example, "foo.bar_baz" becomes +// |foo_bar_baz|. This is arguably ugly, but clear, and you can search for +// both using the regexp /foo.bar.baz/. +// +// - <cpp-type> is one of bool, int32_t, uint32_t, float, or an Atomic version +// of one of those. The C++ preprocessor doesn't like template syntax in a +// macro argument, so use the typedefs defines in StaticPrefs.h; for example, +// use `ReleaseAcquireAtomicBool` instead of `Atomic<bool, ReleaseAcquire>`. +// +// - <default-value> is the same as for normal prefs. +// +// Note that Rust code must access the global variable directly, rather than via +// the getter. + +// clang-format off + +//--------------------------------------------------------------------------- +// Network prefs +//--------------------------------------------------------------------------- + +// Sub-resources HTTP-authentication: +// 0 - don't allow sub-resources to open HTTP authentication credentials +// dialogs +// 1 - allow sub-resources to open HTTP authentication credentials dialogs, +// but don't allow it for cross-origin sub-resources +// 2 - allow the cross-origin authentication as well. +VARCACHE_PREF( + "network.auth.subresource-http-auth-allow", + network_auth_subresource_http_auth_allow, + uint32_t, 2 +) + +// Sub-resources HTTP-authentication for cross-origin images: +// - true: It is allowed to present http auth. dialog for cross-origin images. +// - false: It is not allowed. +// If network.auth.subresource-http-auth-allow has values 0 or 1 this pref does +// not have any effect. +VARCACHE_PREF( + "network.auth.subresource-img-cross-origin-http-auth-allow", + network_auth_subresource_img_cross_origin_http_auth_allow, + bool, false +) + +// Resources that are triggered by some non-web-content: +// - true: They are allow to present http auth. dialog +// - false: They are not allow to present http auth. dialog. +VARCACHE_PREF( + "network.auth.non-web-content-triggered-resources-http-auth-allow", + network_auth_non_web_content_triggered_resources_http_auth_allow, + bool, false +) + +//--------------------------------------------------------------------------- +// Preferences prefs +//--------------------------------------------------------------------------- + +PREF("preferences.allow.omt-write", bool, true) + +//--------------------------------------------------------------------------- +// End of prefs +//--------------------------------------------------------------------------- + +// clang-format on
--- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -2244,36 +2244,16 @@ pref("network.automatic-ntlm-auth.truste // system hostname, could be used for user fingerprinting. // // However, in some network environments where allowedWorkstations is in use // to provide a level of host-based access control, it must be set to a string // that is listed in allowedWorkstations for the user's account in their // AD Domain. pref("network.generic-ntlm-auth.workstation", "WORKSTATION"); -// Sub-resources HTTP-authentication: -// 0 - don't allow sub-resources to open HTTP authentication credentials -// dialogs -// 1 - allow sub-resources to open HTTP authentication credentials dialogs, -// but don't allow it for cross-origin sub-resources -// 2 - allow the cross-origin authentication as well. -pref("network.auth.subresource-http-auth-allow", 2); - -// Sub-resources HTTP-authentication for cross-origin images: -// true - it is allowed to present http auth. dialog for cross-origin images. -// false - it is not allowed. -// If network.auth.subresource-http-auth-allow has values 0 or 1 this pref does not -// have any effect. -pref("network.auth.subresource-img-cross-origin-http-auth-allow", false); - -// Resources that are triggered by some non-web-content: -// true - they are allow to present http auth. dialog -// false - they are not allow to present http auth. dialog. -pref("network.auth.non-web-content-triggered-resources-http-auth-allow", false); - // This preference controls whether to allow sending default credentials (SSO) to // NTLM/Negotiate servers allowed in the "trusted uri" list when navigating them // in a Private Browsing window. // If set to false, Private Browsing windows will not use default credentials and ask // for credentials from the user explicitly. // If set to true, and a server URL conforms other conditions for sending default // credentials, those will be sent automatically in Private Browsing windows. //
--- a/modules/libpref/moz.build +++ b/modules/libpref/moz.build @@ -20,17 +20,19 @@ XPIDL_SOURCES += [ 'nsIPrefLocalizedString.idl', 'nsIPrefService.idl', 'nsIRelativeFilePref.idl', ] XPIDL_MODULE = 'pref' EXPORTS.mozilla += [ + 'init/StaticPrefList.h', 'Preferences.h', + 'StaticPrefs.h', ] UNIFIED_SOURCES += [ 'Preferences.cpp', ] include('/ipc/chromium/chromium-config.mozbuild')
--- a/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp +++ b/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp @@ -23,16 +23,17 @@ #include "nsIPrompt.h" #include "netCore.h" #include "nsIHttpAuthenticableChannel.h" #include "nsIURI.h" #include "nsContentUtils.h" #include "nsServiceManagerUtils.h" #include "nsILoadContext.h" #include "nsIURL.h" +#include "mozilla/StaticPrefs.h" #include "mozilla/Telemetry.h" #include "nsIProxiedChannel.h" #include "nsIProxyInfo.h" namespace mozilla { namespace net { #define SUBRESOURCE_AUTH_DIALOG_DISALLOW_ALL 0 @@ -87,37 +88,16 @@ nsHttpChannelAuthProvider::nsHttpChannel { } nsHttpChannelAuthProvider::~nsHttpChannelAuthProvider() { MOZ_ASSERT(!mAuthChannel, "Disconnect wasn't called"); } -uint32_t nsHttpChannelAuthProvider::sAuthAllowPref = - SUBRESOURCE_AUTH_DIALOG_ALLOW_ALL; - -bool nsHttpChannelAuthProvider::sImgCrossOriginAuthAllowPref = true; -bool nsHttpChannelAuthProvider::sNonWebContentTriggeredAuthAllow = false; - -void -nsHttpChannelAuthProvider::InitializePrefs() -{ - MOZ_ASSERT(NS_IsMainThread()); - mozilla::Preferences::AddUintVarCache(&sAuthAllowPref, - "network.auth.subresource-http-auth-allow", - SUBRESOURCE_AUTH_DIALOG_ALLOW_ALL); - mozilla::Preferences::AddBoolVarCache(&sImgCrossOriginAuthAllowPref, - "network.auth.subresource-img-cross-origin-http-auth-allow", - true); - mozilla::Preferences::AddBoolVarCache(&sNonWebContentTriggeredAuthAllow, - "network.auth.non-web-content-triggered-resources-http-auth-allow", - false); -} - NS_IMETHODIMP nsHttpChannelAuthProvider::Init(nsIHttpAuthenticableChannel *channel) { MOZ_ASSERT(channel, "channel expected!"); mAuthChannel = channel; nsresult rv = mAuthChannel->GetURI(getter_AddRefs(mURI)); @@ -914,18 +894,20 @@ nsHttpChannelAuthProvider::GetCredential // blocked for all sub-resources, blocked for cross-origin // sub-resources, or always allowed for sub-resources. // For more details look at the bug 647010. // BlockPrompt will set mCrossOrigin parameter as well. if (BlockPrompt(proxyAuth)) { LOG(("nsHttpChannelAuthProvider::GetCredentialsForChallenge: " "Prompt is blocked [this=%p pref=%d img-pref=%d " "non-web-content-triggered-pref=%d]\n", - this, sAuthAllowPref, sImgCrossOriginAuthAllowPref, - sNonWebContentTriggeredAuthAllow)); + this, + StaticPrefs::network_auth_subresource_http_auth_allow(), + StaticPrefs::network_auth_subresource_img_cross_origin_http_auth_allow(), + StaticPrefs::network_auth_non_web_content_triggered_resources_http_auth_allow())); return NS_ERROR_ABORT; } // at this point we are forced to interact with the user to get // their username and password for this domain. rv = PromptForIdentity(level, proxyAuth, realm.get(), authType, authFlags, *ident); if (NS_FAILED(rv)) return rv; @@ -1050,36 +1032,38 @@ nsHttpChannelAuthProvider::BlockPrompt(b HTTP_AUTH_DIALOG_SAME_ORIGIN_SUBRESOURCE); } } else { Telemetry::Accumulate(Telemetry::HTTP_AUTH_DIALOG_STATS_3, loadInfo->GetExternalContentPolicyType()); } } - if (!topDoc && !sNonWebContentTriggeredAuthAllow && nonWebContent) { + if (!topDoc && + !StaticPrefs::network_auth_non_web_content_triggered_resources_http_auth_allow() && + nonWebContent) { return true; } - switch (sAuthAllowPref) { + switch (StaticPrefs::network_auth_subresource_http_auth_allow()) { case SUBRESOURCE_AUTH_DIALOG_DISALLOW_ALL: // Do not open the http-authentication credentials dialog for // the sub-resources. return !topDoc && !xhr; case SUBRESOURCE_AUTH_DIALOG_DISALLOW_CROSS_ORIGIN: // Open the http-authentication credentials dialog for // the sub-resources only if they are not cross-origin. return !topDoc && !xhr && mCrossOrigin; case SUBRESOURCE_AUTH_DIALOG_ALLOW_ALL: // Allow the http-authentication dialog for subresources. // If pref network.auth.subresource-img-cross-origin-http-auth-allow // is set, http-authentication dialog for image subresources is // blocked. if (mCrossOrigin && - !sImgCrossOriginAuthAllowPref && + !StaticPrefs::network_auth_subresource_img_cross_origin_http_auth_allow() && loadInfo && ((loadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_IMAGE) || (loadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_IMAGESET))) { return true; } return false; default: // This is an invalid value.
--- a/netwerk/protocol/http/nsHttpChannelAuthProvider.h +++ b/netwerk/protocol/http/nsHttpChannelAuthProvider.h @@ -32,17 +32,16 @@ class nsHttpChannelAuthProvider : public public: NS_DECL_ISUPPORTS NS_DECL_NSICANCELABLE NS_DECL_NSIHTTPCHANNELAUTHPROVIDER NS_DECL_NSIAUTHPROMPTCALLBACK NS_DECL_NSIHTTPAUTHENTICATORCALLBACK nsHttpChannelAuthProvider(); - static void InitializePrefs(); private: virtual ~nsHttpChannelAuthProvider(); const char *ProxyHost() const { return mProxyInfo ? mProxyInfo->Host().get() : nullptr; } int32_t ProxyPort() const { return mProxyInfo ? mProxyInfo->Port() : -1; } @@ -177,21 +176,15 @@ private: // If a cross-origin sub-resource is being loaded, this flag will be set. // In that case, the prompt text will be different to warn users. uint32_t mCrossOrigin : 1; uint32_t mConnectionBased : 1; RefPtr<nsHttpHandler> mHttpHandler; // keep gHttpHandler alive - // A variable holding the preference settings to whether to open HTTP - // authentication credentials dialogs for sub-resources and cross-origin - // sub-resources. - static uint32_t sAuthAllowPref; - static bool sImgCrossOriginAuthAllowPref; - static bool sNonWebContentTriggeredAuthAllow; nsCOMPtr<nsICancelable> mGenerateCredentialsCancelable; }; } // namespace net } // namespace mozilla #endif // nsHttpChannelAuthProvider_h__
--- a/netwerk/protocol/http/nsHttpHandler.cpp +++ b/netwerk/protocol/http/nsHttpHandler.cpp @@ -464,18 +464,16 @@ nsHttpHandler::Init() prefBranch->AddObserver(TCP_FAST_OPEN_ENABLE, this, true); prefBranch->AddObserver(TCP_FAST_OPEN_FAILURE_LIMIT, this, true); prefBranch->AddObserver(TCP_FAST_OPEN_STALLS_LIMIT, this, true); prefBranch->AddObserver(TCP_FAST_OPEN_STALLS_IDLE, this, true); prefBranch->AddObserver(TCP_FAST_OPEN_STALLS_TIMEOUT, this, true); PrefsChanged(prefBranch, nullptr); } - nsHttpChannelAuthProvider::InitializePrefs(); - mMisc.AssignLiteral("rv:" MOZILLA_UAVERSION); mCompatFirefox.AssignLiteral("Firefox/" MOZILLA_UAVERSION); nsCOMPtr<nsIXULAppInfo> appInfo = do_GetService("@mozilla.org/xre/app-info;1"); mAppName.AssignLiteral(MOZ_APP_UA_NAME);