Bug 1587162 - Fix UBSAN complaints about pref callbacks. r=erahm
authorNicholas Nethercote <nnethercote@mozilla.com>
Fri, 01 Nov 2019 02:57:20 +0000
changeset 500122 30ee2029152cc2048cd1d963276f575e4a6aead4
parent 500121 f477785eb9ba737f6310a0add902cb5c04cff45b
child 500123 272775d127445bbbd2cbe9895828e198f79f2b8a
push id36754
push userbtara@mozilla.com
push dateFri, 01 Nov 2019 16:13:11 +0000
treeherdermozilla-central@475496111203 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerserahm
bugs1587162, 1473631
milestone72.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1587162 - Fix UBSAN complaints about pref callbacks. r=erahm Lots of these callbacks have a non-`void*` final parameter, which UBSAN complains about. This commit changes them to have a `void*` parameter. This requires undoing the machinery added in the first two commits of bug 1473631: `TypePrefChangeFunc` and `PREF_CHANGE_METHOD`. The resulting code is simpler (which is good) and more boilerplate-y (which is bad) but avoids the undefined behaviour (which is good). Differential Revision: https://phabricator.services.mozilla.com/D50901
caps/nsScriptSecurityManager.cpp
caps/nsScriptSecurityManager.h
docshell/shistory/nsSHistory.cpp
dom/base/nsFocusManager.cpp
dom/base/nsFocusManager.h
dom/base/nsNameSpaceManager.cpp
dom/base/nsNameSpaceManager.h
dom/indexedDB/IndexedDatabaseManager.cpp
dom/payments/PaymentRequestManager.cpp
dom/plugins/ipc/PluginModuleParent.cpp
dom/plugins/ipc/PluginModuleParent.h
js/xpconnect/src/XPCJSContext.cpp
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
layout/style/nsComputedDOMStyle.cpp
modules/libpref/Preferences.h
modules/libpref/test/gtest/CallbackAndVarCacheOrder.cpp
netwerk/base/nsIOService.cpp
netwerk/base/nsIOService.h
netwerk/base/nsSocketTransportService2.cpp
netwerk/base/nsSocketTransportService2.h
netwerk/dns/nsHostResolver.cpp
netwerk/dns/nsIDNService.h
netwerk/protocol/http/nsHttpHandler.cpp
netwerk/protocol/http/nsHttpHandler.h
netwerk/url-classifier/UrlClassifierFeatureBase.cpp
netwerk/url-classifier/nsChannelClassifier.cpp
security/manager/ssl/CertBlocklist.cpp
security/manager/ssl/DataStorage.cpp
security/manager/ssl/DataStorage.h
toolkit/components/places/nsNavHistoryResult.cpp
toolkit/components/places/nsNavHistoryResult.h
toolkit/components/resistfingerprinting/nsRFPService.cpp
toolkit/components/resistfingerprinting/nsRFPService.h
widget/windows/WinMouseScrollHandler.h
--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -1388,18 +1388,17 @@ nsresult nsScriptSecurityManager::Init()
 
   return NS_OK;
 }
 
 static StaticRefPtr<nsScriptSecurityManager> gScriptSecMan;
 
 nsScriptSecurityManager::~nsScriptSecurityManager(void) {
   Preferences::UnregisterPrefixCallbacks(
-      PREF_CHANGE_METHOD(nsScriptSecurityManager::ScriptSecurityPrefChanged),
-      kObservedPrefs, this);
+      nsScriptSecurityManager::ScriptSecurityPrefChanged, kObservedPrefs, this);
   if (mDomainPolicy) {
     mDomainPolicy->Deactivate();
   }
   // ContentChild might hold a reference to the domain policy,
   // and it might release it only after the security manager is
   // gone. But we can still assert this for the main process.
   MOZ_ASSERT_IF(XRE_IsParentProcess(), !mDomainPolicy);
 }
@@ -1462,16 +1461,23 @@ uint32_t SkipPast(const nsCString& str, 
 template <typename Predicate>
 uint32_t SkipUntil(const nsCString& str, uint32_t base) {
   while (base < str.Length() && !Predicate::Test(str[base])) {
     ++base;
   }
   return base;
 }
 
+// static
+void nsScriptSecurityManager::ScriptSecurityPrefChanged(const char* aPref,
+                                                        void* aSelf) {
+  static_cast<nsScriptSecurityManager*>(aSelf)->ScriptSecurityPrefChanged(
+      aPref);
+}
+
 inline void nsScriptSecurityManager::ScriptSecurityPrefChanged(
     const char* aPref) {
   MOZ_ASSERT(mPrefInitialized);
   mIsJavaScriptEnabled =
       Preferences::GetBool(sJSEnabledPrefName, mIsJavaScriptEnabled);
   sStrictFileOriginPolicy =
       Preferences::GetBool(sFileOriginPolicyPrefName, false);
   mFileURIAllowlist.reset();
@@ -1519,18 +1525,17 @@ nsresult nsScriptSecurityManager::InitPr
 
   mPrefInitialized = true;
 
   // Set the initial value of the "javascript.enabled" prefs
   ScriptSecurityPrefChanged();
 
   // set observer callbacks in case the value of the prefs change
   Preferences::RegisterPrefixCallbacks(
-      PREF_CHANGE_METHOD(nsScriptSecurityManager::ScriptSecurityPrefChanged),
-      kObservedPrefs, this);
+      nsScriptSecurityManager::ScriptSecurityPrefChanged, kObservedPrefs, this);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsScriptSecurityManager::GetDomainPolicyActive(bool* aRv) {
   *aRv = !!mDomainPolicy;
   return NS_OK;
--- a/caps/nsScriptSecurityManager.h
+++ b/caps/nsScriptSecurityManager.h
@@ -82,16 +82,17 @@ class nsScriptSecurityManager final : pu
                                                    JS::HandleValue aValue);
 
   static bool JSPrincipalsSubsume(JSPrincipals* first, JSPrincipals* second);
 
   nsresult Init();
 
   nsresult InitPrefs();
 
+  static void ScriptSecurityPrefChanged(const char* aPref, void* aSelf);
   void ScriptSecurityPrefChanged(const char* aPref = nullptr);
 
   inline void AddSitesToFileURIAllowlist(const nsCString& aSiteList);
 
   nsresult GetChannelResultPrincipal(nsIChannel* aChannel,
                                      nsIPrincipal** aPrincipal,
                                      bool aIgnoreSandboxing);
 
--- a/docshell/shistory/nsSHistory.cpp
+++ b/docshell/shistory/nsSHistory.cpp
@@ -131,26 +131,32 @@ enum HistCmd { HIST_CMD_GOTOINDEX, HIST_
 
 class nsSHistoryObserver final : public nsIObserver {
  public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
   nsSHistoryObserver() {}
 
+  static void PrefChanged(const char* aPref, void* aSelf);
   void PrefChanged(const char* aPref);
 
  protected:
   ~nsSHistoryObserver() {}
 };
 
 StaticRefPtr<nsSHistoryObserver> gObserver;
 
 NS_IMPL_ISUPPORTS(nsSHistoryObserver, nsIObserver)
 
+// static
+void nsSHistoryObserver::PrefChanged(const char* aPref, void* aSelf) {
+  static_cast<nsSHistoryObserver*>(aSelf)->PrefChanged(aPref);
+}
+
 void nsSHistoryObserver::PrefChanged(const char* aPref) {
   nsSHistory::UpdatePrefs();
   nsSHistory::GloballyEvictContentViewers();
 }
 
 NS_IMETHODIMP
 nsSHistoryObserver::Observe(nsISupports* aSubject, const char* aTopic,
                             const char16_t* aData) {
@@ -308,19 +314,18 @@ nsresult nsSHistory::Startup() {
   if (gHistoryMaxSize < defaultHistoryMaxSize) {
     gHistoryMaxSize = defaultHistoryMaxSize;
   }
 
   // Allow the user to override the max total number of cached viewers,
   // but keep the per SHistory cached viewer limit constant
   if (!gObserver) {
     gObserver = new nsSHistoryObserver();
-    Preferences::RegisterCallbacks(
-        PREF_CHANGE_METHOD(nsSHistoryObserver::PrefChanged), kObservedPrefs,
-        gObserver.get());
+    Preferences::RegisterCallbacks(nsSHistoryObserver::PrefChanged,
+                                   kObservedPrefs, gObserver.get());
 
     nsCOMPtr<nsIObserverService> obsSvc =
         mozilla::services::GetObserverService();
     if (obsSvc) {
       // Observe empty-cache notifications so tahat clearing the disk/memory
       // cache will also evict all content viewers.
       obsSvc->AddObserver(gObserver, "cacheservice:empty-cache", false);
 
@@ -330,19 +335,18 @@ nsresult nsSHistory::Startup() {
   }
 
   return NS_OK;
 }
 
 // static
 void nsSHistory::Shutdown() {
   if (gObserver) {
-    Preferences::UnregisterCallbacks(
-        PREF_CHANGE_METHOD(nsSHistoryObserver::PrefChanged), kObservedPrefs,
-        gObserver.get());
+    Preferences::UnregisterCallbacks(nsSHistoryObserver::PrefChanged,
+                                     kObservedPrefs, gObserver.get());
 
     nsCOMPtr<nsIObserverService> obsSvc =
         mozilla::services::GetObserverService();
     if (obsSvc) {
       obsSvc->RemoveObserver(gObserver, "cacheservice:empty-cache");
       obsSvc->RemoveObserver(gObserver, "memory-pressure");
     }
     gObserver = nullptr;
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -169,18 +169,18 @@ bool nsFocusManager::sTestMode = false;
 static const char* kObservedPrefs[] = {
     "accessibility.browsewithcaret", "accessibility.tabfocus_applies_to_xul",
     "accessibility.mouse_focuses_formcontrol", "focusmanager.testmode",
     nullptr};
 
 nsFocusManager::nsFocusManager() : mEventHandlingNeedsFlush(false) {}
 
 nsFocusManager::~nsFocusManager() {
-  Preferences::UnregisterCallbacks(
-      PREF_CHANGE_METHOD(nsFocusManager::PrefChanged), kObservedPrefs, this);
+  Preferences::UnregisterCallbacks(nsFocusManager::PrefChanged, kObservedPrefs,
+                                   this);
 
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (obs) {
     obs->RemoveObserver(this, "xpcom-shutdown");
   }
 }
 
 // static
@@ -193,30 +193,35 @@ nsresult nsFocusManager::Init() {
       Preferences::GetBool("accessibility.tabfocus_applies_to_xul",
                            nsIContent::sTabFocusModelAppliesToXUL);
 
   sMouseFocusesFormControl =
       Preferences::GetBool("accessibility.mouse_focuses_formcontrol", false);
 
   sTestMode = Preferences::GetBool("focusmanager.testmode", false);
 
-  Preferences::RegisterCallbacks(
-      PREF_CHANGE_METHOD(nsFocusManager::PrefChanged), kObservedPrefs, fm);
+  Preferences::RegisterCallbacks(nsFocusManager::PrefChanged, kObservedPrefs,
+                                 fm);
 
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (obs) {
     obs->AddObserver(fm, "xpcom-shutdown", true);
   }
 
   return NS_OK;
 }
 
 // static
 void nsFocusManager::Shutdown() { NS_IF_RELEASE(sInstance); }
 
+// static
+void nsFocusManager::PrefChanged(const char* aPref, void* aSelf) {
+  static_cast<nsFocusManager*>(aSelf)->PrefChanged(aPref);
+}
+
 void nsFocusManager::PrefChanged(const char* aPref) {
   nsDependentCString pref(aPref);
   if (pref.EqualsLiteral("accessibility.browsewithcaret")) {
     UpdateCaretForCaretBrowsingMode();
   } else if (pref.EqualsLiteral("accessibility.tabfocus_applies_to_xul")) {
     nsIContent::sTabFocusModelAppliesToXUL =
         Preferences::GetBool("accessibility.tabfocus_applies_to_xul",
                              nsIContent::sTabFocusModelAppliesToXUL);
--- a/dom/base/nsFocusManager.h
+++ b/dom/base/nsFocusManager.h
@@ -58,16 +58,17 @@ class nsFocusManager final : public nsIF
   static nsresult Init();
   static void Shutdown();
 
   // Simple helper to call SetFocusedWindow on the instance.
   //
   // This raises the window and switches to the tab as needed.
   static void FocusWindow(nsPIDOMWindowOuter* aWindow);
 
+  static void PrefChanged(const char* aPref, void* aSelf);
   void PrefChanged(const char* aPref);
 
   /**
    * Retrieve the single focus manager.
    */
   static nsFocusManager* GetFocusManager() { return sInstance; }
 
   /**
--- a/dom/base/nsNameSpaceManager.cpp
+++ b/dom/base/nsNameSpaceManager.cpp
@@ -56,19 +56,18 @@ bool nsNameSpaceManager::Init() {
 #define REGISTER_NAMESPACE(uri, id)        \
   rv = AddNameSpace(dont_AddRef(uri), id); \
   NS_ENSURE_SUCCESS(rv, false)
 
 #define REGISTER_DISABLED_NAMESPACE(uri, id)       \
   rv = AddDisabledNameSpace(dont_AddRef(uri), id); \
   NS_ENSURE_SUCCESS(rv, false)
 
-  mozilla::Preferences::RegisterCallbacks(
-      PREF_CHANGE_METHOD(nsNameSpaceManager::PrefChanged), kObservedNSPrefs,
-      this);
+  mozilla::Preferences::RegisterCallbacks(nsNameSpaceManager::PrefChanged,
+                                          kObservedNSPrefs, this);
 
   PrefChanged(nullptr);
 
   // Need to be ordered according to ID.
   MOZ_ASSERT(mURIArray.IsEmpty());
   REGISTER_NAMESPACE(nsGkAtoms::_empty, kNameSpaceID_None);
   REGISTER_NAMESPACE(nsGkAtoms::nsuri_xmlns, kNameSpaceID_XMLNS);
   REGISTER_NAMESPACE(nsGkAtoms::nsuri_xml, kNameSpaceID_XML);
@@ -250,12 +249,17 @@ nsresult nsNameSpaceManager::AddDisabled
 
   MOZ_ASSERT(aNameSpaceID == (int32_t)mURIArray.Length());
   mURIArray.AppendElement(uri.forget());
   mDisabledURIToIDTable.Put(mURIArray.LastElement(), aNameSpaceID);
 
   return NS_OK;
 }
 
+// static
+void nsNameSpaceManager::PrefChanged(const char* aPref, void* aSelf) {
+  static_cast<nsNameSpaceManager*>(aSelf)->PrefChanged(aPref);
+}
+
 void nsNameSpaceManager::PrefChanged(const char* aPref) {
   mMathMLDisabled = mozilla::Preferences::GetBool(kPrefMathMLDisabled);
   mSVGDisabled = mozilla::Preferences::GetBool(kPrefSVGDisabled);
 }
--- a/dom/base/nsNameSpaceManager.h
+++ b/dom/base/nsNameSpaceManager.h
@@ -58,16 +58,17 @@ class nsNameSpaceManager final {
 
   bool HasElementCreator(int32_t aNameSpaceID);
 
   static nsNameSpaceManager* GetInstance();
   bool mMathMLDisabled;
   bool mSVGDisabled;
 
  private:
+  static void PrefChanged(const char* aPref, void* aSelf);
   void PrefChanged(const char* aPref);
 
   bool Init();
   nsresult AddNameSpace(already_AddRefed<nsAtom> aURI,
                         const int32_t aNameSpaceID);
   nsresult AddDisabledNameSpace(already_AddRefed<nsAtom> aURI,
                                 const int32_t aNameSpaceID);
   ~nsNameSpaceManager(){};
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -144,22 +144,21 @@ Atomic<bool> gClosed(false);
 Atomic<bool> gTestingMode(false);
 Atomic<bool> gExperimentalFeaturesEnabled(false);
 Atomic<bool> gFileHandleEnabled(false);
 Atomic<bool> gPrefErrorEventToSelfError(false);
 Atomic<int32_t> gDataThresholdBytes(0);
 Atomic<int32_t> gMaxSerializedMsgSize(0);
 Atomic<bool> gPreprocessingEnabled(false);
 
-void AtomicBoolPrefChangedCallback(const char* aPrefName,
-                                   Atomic<bool>* aClosure) {
+void AtomicBoolPrefChangedCallback(const char* aPrefName, void* aBool) {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(aClosure);
+  MOZ_ASSERT(aBool);
 
-  *aClosure = Preferences::GetBool(aPrefName);
+  *static_cast<Atomic<bool>*>(aBool) = Preferences::GetBool(aPrefName);
 }
 
 void DataThresholdPrefChangedCallback(const char* aPrefName, void* aClosure) {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!strcmp(aPrefName, kDataThresholdPref));
   MOZ_ASSERT(!aClosure);
 
   int32_t dataThresholdBytes =
--- a/dom/payments/PaymentRequestManager.cpp
+++ b/dom/payments/PaymentRequestManager.cpp
@@ -306,26 +306,26 @@ void ConvertMethodChangeDetails(const IP
 }
 }  // end of namespace
 
 /* PaymentRequestManager */
 
 StaticRefPtr<PaymentRequestManager> gPaymentManager;
 const char kSupportedRegionsPref[] = "dom.payments.request.supportedRegions";
 
-void SupportedRegionsPrefChangedCallback(const char* aPrefName,
-                                         nsTArray<nsString>* aRetval) {
+void SupportedRegionsPrefChangedCallback(const char* aPrefName, void* aRetval) {
+  auto retval = static_cast<nsTArray<nsString>*>(aRetval);
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!strcmp(aPrefName, kSupportedRegionsPref));
 
   nsAutoString supportedRegions;
   Preferences::GetString(aPrefName, supportedRegions);
-  aRetval->Clear();
+  retval->Clear();
   for (const nsAString& each : supportedRegions.Split(',')) {
-    aRetval->AppendElement(each);
+    retval->AppendElement(each);
   }
 }
 
 PaymentRequestManager::PaymentRequestManager() {
   Preferences::RegisterCallbackAndCall(SupportedRegionsPrefChangedCallback,
                                        kSupportedRegionsPref,
                                        &this->mSupportedRegions);
 }
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -709,42 +709,43 @@ void PluginModuleChromeParent::AddCrashA
 }
 
 void PluginModuleParent::SetChildTimeout(const int32_t aChildTimeout) {
   int32_t timeoutMs =
       (aChildTimeout > 0) ? (1000 * aChildTimeout) : MessageChannel::kNoTimeout;
   SetReplyTimeoutMs(timeoutMs);
 }
 
-void PluginModuleParent::TimeoutChanged(const char* aPref,
-                                        PluginModuleParent* aModule) {
+void PluginModuleParent::TimeoutChanged(const char* aPref, void* aModule) {
+  auto module = static_cast<PluginModuleParent*>(aModule);
+
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 #ifndef XP_WIN
   if (!strcmp(aPref, kChildTimeoutPref)) {
-    MOZ_ASSERT(aModule->IsChrome());
+    MOZ_ASSERT(module->IsChrome());
     // The timeout value used by the parent for children
     int32_t timeoutSecs = Preferences::GetInt(kChildTimeoutPref, 0);
-    aModule->SetChildTimeout(timeoutSecs);
+    module->SetChildTimeout(timeoutSecs);
 #else
   if (!strcmp(aPref, kChildTimeoutPref) ||
       !strcmp(aPref, kHangUIMinDisplayPref) ||
       !strcmp(aPref, kHangUITimeoutPref)) {
-    MOZ_ASSERT(aModule->IsChrome());
-    static_cast<PluginModuleChromeParent*>(aModule)->EvaluateHangUIState(true);
+    MOZ_ASSERT(module->IsChrome());
+    static_cast<PluginModuleChromeParent*>(module)->EvaluateHangUIState(true);
 #endif  // XP_WIN
   } else if (!strcmp(aPref, kParentTimeoutPref)) {
     // The timeout value used by the child for its parent
-    MOZ_ASSERT(aModule->IsChrome());
+    MOZ_ASSERT(module->IsChrome());
     int32_t timeoutSecs = Preferences::GetInt(kParentTimeoutPref, 0);
-    Unused << static_cast<PluginModuleChromeParent*>(aModule)
+    Unused << static_cast<PluginModuleChromeParent*>(module)
                   ->SendSetParentHangTimeout(timeoutSecs);
   } else if (!strcmp(aPref, kContentTimeoutPref)) {
-    MOZ_ASSERT(!aModule->IsChrome());
+    MOZ_ASSERT(!module->IsChrome());
     int32_t timeoutSecs = Preferences::GetInt(kContentTimeoutPref, 0);
-    aModule->SetChildTimeout(timeoutSecs);
+    module->SetChildTimeout(timeoutSecs);
   }
 }
 
 void PluginModuleChromeParent::CleanupFromTimeout(const bool aFromHangUI) {
   if (mShutdown) {
     return;
   }
 
@@ -1757,19 +1758,20 @@ void PluginModuleParent::GetSettings(Plu
 
 void PluginModuleChromeParent::CachedSettingChanged() {
   PluginSettings settings;
   GetSettings(&settings);
   Unused << SendSettingChanged(settings);
 }
 
 /* static */
-void PluginModuleChromeParent::CachedSettingChanged(
-    const char* aPref, PluginModuleChromeParent* aModule) {
-  aModule->CachedSettingChanged();
+void PluginModuleChromeParent::CachedSettingChanged(const char* aPref,
+                                                    void* aModule) {
+  auto module = static_cast<PluginModuleChromeParent*>(aModule);
+  module->CachedSettingChanged();
 }
 
 #if defined(XP_UNIX) && !defined(XP_MACOSX)
 nsresult PluginModuleParent::NP_Initialize(NPNetscapeFuncs* bFuncs,
                                            NPPluginFuncs* pFuncs,
                                            NPError* error) {
   PLUGIN_LOG_DEBUG_METHOD;
 
--- a/dom/plugins/ipc/PluginModuleParent.h
+++ b/dom/plugins/ipc/PluginModuleParent.h
@@ -143,17 +143,17 @@ class PluginModuleParent : public PPlugi
   static BrowserStreamParent* StreamCast(NPP instance, NPStream* s);
 
   virtual mozilla::ipc::IPCResult
   AnswerNPN_SetValue_NPPVpluginRequiresAudioDeviceChanges(
       const bool& shouldRegister, NPError* result);
 
  protected:
   void SetChildTimeout(const int32_t aChildTimeout);
-  static void TimeoutChanged(const char* aPref, PluginModuleParent* aModule);
+  static void TimeoutChanged(const char* aPref, void* aModule);
 
   virtual void UpdatePluginTimeout() {}
 
   virtual mozilla::ipc::IPCResult RecvNotifyContentModuleDestroyed() {
     return IPC_OK();
   }
 
   mozilla::ipc::IPCResult RecvReturnClearSiteData(const NPError& aRv,
@@ -452,18 +452,17 @@ class PluginModuleChromeParent : public 
 
   void RegisterSettingsCallbacks();
   void UnregisterSettingsCallbacks();
 
   bool InitCrashReporter();
 
   mozilla::ipc::IPCResult RecvNotifyContentModuleDestroyed() override;
 
-  static void CachedSettingChanged(const char* aPref,
-                                   PluginModuleChromeParent* aModule);
+  static void CachedSettingChanged(const char* aPref, void* aModule);
 
   mozilla::ipc::IPCResult
   AnswerNPN_SetValue_NPPVpluginRequiresAudioDeviceChanges(
       const bool& shouldRegister, NPError* result) override;
 
   PluginProcessParent* mSubprocess;
   uint32_t mPluginId;
 
--- a/js/xpconnect/src/XPCJSContext.cpp
+++ b/js/xpconnect/src/XPCJSContext.cpp
@@ -273,18 +273,18 @@ class WatchdogManager {
   virtual ~WatchdogManager() {
     // Shutting down the watchdog requires context-switching to the watchdog
     // thread, which isn't great to do in a destructor. So we require
     // consumers to shut it down manually before releasing it.
     MOZ_ASSERT(!mWatchdog);
   }
 
  private:
-  static void PrefsChanged(const char* aPref, WatchdogManager* aSelf) {
-    aSelf->RefreshWatchdog();
+  static void PrefsChanged(const char* aPref, void* aSelf) {
+    static_cast<WatchdogManager*>(aSelf)->RefreshWatchdog();
   }
 
  public:
   void Shutdown() {
     Preferences::UnregisterCallbacks(PrefsChanged, gCallbackPrefs, this);
   }
 
   void RegisterContext(XPCJSContext* aContext) {
@@ -884,19 +884,20 @@ static void LoadStartupJSPrefs(XPCJSCont
   JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_SPECTRE_JIT_TO_CXX_CALLS,
                                 spectreJitToCxxCalls);
   if (disableWasmHugeMemory) {
     bool disabledHugeMemory = JS::DisableWasmHugeMemory();
     MOZ_RELEASE_ASSERT(disabledHugeMemory);
   }
 }
 
-static void ReloadPrefsCallback(const char* pref, XPCJSContext* xpccx) {
+static void ReloadPrefsCallback(const char* pref, void* aXpccx) {
   // Note: Prefs that require a restart are handled in LoadStartupJSPrefs above.
 
+  auto xpccx = static_cast<XPCJSContext*>(aXpccx);
   JSContext* cx = xpccx->Context();
 
   bool useAsmJS = Preferences::GetBool(JS_OPTIONS_DOT_STR "asmjs");
   bool useWasm = Preferences::GetBool(JS_OPTIONS_DOT_STR "wasm");
   bool useWasmTrustedPrincipals =
       Preferences::GetBool(JS_OPTIONS_DOT_STR "wasm_trustedprincipals");
   bool useWasmIon = Preferences::GetBool(JS_OPTIONS_DOT_STR "wasm_ionjit");
   bool useWasmBaseline =
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -265,22 +265,20 @@ void nsPresContext::Destroy() {
   if (mEventManager) {
     // unclear if these are needed, but can't hurt
     mEventManager->NotifyDestroyPresContext(this);
     mEventManager->SetPresContext(nullptr);
     mEventManager = nullptr;
   }
 
   // Unregister preference callbacks
-  Preferences::UnregisterPrefixCallbacks(
-      PREF_CHANGE_METHOD(nsPresContext::PreferenceChanged),
-      gPrefixCallbackPrefs, this);
-  Preferences::UnregisterCallbacks(
-      PREF_CHANGE_METHOD(nsPresContext::PreferenceChanged), gExactCallbackPrefs,
-      this);
+  Preferences::UnregisterPrefixCallbacks(nsPresContext::PreferenceChanged,
+                                         gPrefixCallbackPrefs, this);
+  Preferences::UnregisterCallbacks(nsPresContext::PreferenceChanged,
+                                   gExactCallbackPrefs, this);
 
   mRefreshDriver = nullptr;
 }
 
 nsPresContext::~nsPresContext() {
   MOZ_ASSERT(!mPresShell, "Presshell forgot to clear our mPresShell pointer");
   DetachPresShell();
 
@@ -440,16 +438,21 @@ void nsPresContext::AppUnitsPerDevPixelC
     }
   }
 
   // We would also have to look at all of our child subdocuments but the
   // InvalidatePaintedLayers call above calls InvalidateFrameSubtree which
   // would invalidate all subdocument frames already.
 }
 
+// static
+void nsPresContext::PreferenceChanged(const char* aPrefName, void* aSelf) {
+  static_cast<nsPresContext*>(aSelf)->PreferenceChanged(aPrefName);
+}
+
 void nsPresContext::PreferenceChanged(const char* aPrefName) {
   nsDependentCString prefName(aPrefName);
   if (prefName.EqualsLiteral("layout.css.dpi") ||
       prefName.EqualsLiteral("layout.css.devPixelsPerPx")) {
     int32_t oldAppUnitsPerDevPixel = mDeviceContext->AppUnitsPerDevPixel();
     // We need to assume the DPI changes, since `mDeviceContext` is shared with
     // other documents, and we'd need to save the return value of the first call
     // for all of them.
@@ -644,22 +647,20 @@ nsresult nsPresContext::Init(nsDeviceCon
       mRefreshDriver = new nsRefreshDriver(this);
       if (XRE_IsContentProcess()) {
         mRefreshDriver->InitializeTimer();
       }
     }
   }
 
   // Register callbacks so we're notified when the preferences change
-  Preferences::RegisterPrefixCallbacks(
-      PREF_CHANGE_METHOD(nsPresContext::PreferenceChanged),
-      gPrefixCallbackPrefs, this);
-  Preferences::RegisterCallbacks(
-      PREF_CHANGE_METHOD(nsPresContext::PreferenceChanged), gExactCallbackPrefs,
-      this);
+  Preferences::RegisterPrefixCallbacks(nsPresContext::PreferenceChanged,
+                                       gPrefixCallbackPrefs, this);
+  Preferences::RegisterCallbacks(nsPresContext::PreferenceChanged,
+                                 gExactCallbackPrefs, this);
 
   nsresult rv = mEventManager->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
   mEventManager->SetPresContext(this);
 
 #ifdef DEBUG
   mInitialized = true;
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -1036,16 +1036,17 @@ class nsPresContext : public nsISupports
   // device context instead of retrieving a scale from the widget.
   static bool UIResolutionChangedSubdocumentCallback(
       mozilla::dom::Document* aDocument, void* aData);
 
   void SetImgAnimations(nsIContent* aParent, uint16_t aMode);
   void SetSMILAnimations(mozilla::dom::Document* aDoc, uint16_t aNewMode,
                          uint16_t aOldMode);
 
+  static void PreferenceChanged(const char* aPrefName, void* aSelf);
   void PreferenceChanged(const char* aPrefName);
 
   void UpdateAfterPreferencesChanged();
   void DispatchPrefChangedRunnableIfNeeded();
 
   void GetUserPreferences();
 
   void UpdateCharSet(NotNull<const Encoding*> aCharSet);
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -2499,19 +2499,18 @@ already_AddRefed<CSSValue> nsComputedDOM
 
   return val.forget();
 }
 
 already_AddRefed<CSSValue> nsComputedDOMStyle::DummyGetter() {
   MOZ_CRASH("DummyGetter is not supposed to be invoked");
 }
 
-static void MarkComputedStyleMapDirty(const char* aPref,
-                                      ComputedStyleMap* aData) {
-  aData->MarkDirty();
+static void MarkComputedStyleMapDirty(const char* aPref, void* aMap) {
+  static_cast<ComputedStyleMap*>(aMap)->MarkDirty();
 }
 
 void nsComputedDOMStyle::ParentChainChanged(nsIContent* aContent) {
   NS_ASSERTION(mElement == aContent, "didn't we register mElement?");
   NS_ASSERTION(mResolvedComputedStyle,
                "should have only registered an observer when "
                "mResolvedComputedStyle is true");
 
--- a/modules/libpref/Preferences.h
+++ b/modules/libpref/Preferences.h
@@ -35,86 +35,16 @@ typedef void (*PrefChangedFunc)(const ch
 class nsPrefBranch;
 
 namespace mozilla {
 
 struct RegisterCallbacksInternal;
 
 void UnloadPrefsModule();
 
-// A typesafe version of PrefChangeFunc, with its data argument type deduced
-// from the type of the argument passed to RegisterCallback.
-//
-// Note: We specify this as a dependent type TypedPrefChangeFunc<T>::SelfType so
-// that it does not participate in argument type deduction. This allows us to
-// use its implicit conversion constructor, and also allows our Register and
-// Unregister methods to accept non-capturing lambdas (which will not match
-// void(*)(const char*, T*) when used in type deduction) as callback functions.
-template <typename T>
-struct TypedPrefChangeFunc {
-  using Type = TypedPrefChangeFunc<T>;
-  using CallbackType = void (*)(const char*, T*);
-
-  MOZ_IMPLICIT TypedPrefChangeFunc(CallbackType aCallback)
-      : mCallback(aCallback) {}
-
-  template <typename F>
-  MOZ_IMPLICIT TypedPrefChangeFunc(F&& aLambda) : mCallback(aLambda) {}
-
-  operator PrefChangedFunc() const {
-    return reinterpret_cast<PrefChangedFunc>(mCallback);
-  }
-
-  CallbackType mCallback;
-};
-
-// Similar to PrefChangedFunc, but for use with instance methods.
-//
-// Any instance method with this signature may be passed to the
-// PREF_CHANGE_METHOD macro, which will wrap it into a typesafe preference
-// callback function, which accepts a preference name as its first argument, and
-// an instance of the appropriate class as the second.
-//
-// When called, the wrapper will forward the call to the wrapped method on the
-// given instance, with the notified preference as its only argument.
-typedef void(PrefChangedMethod)(const char* aPref);
-
-namespace detail {
-// Helper to extract the instance type from any instance method. For an instance
-// method `Method = U T::*`, InstanceType<Method>::Type returns T.
-template <typename T>
-struct InstanceType;
-
-template <typename T, typename U>
-struct InstanceType<U T::*> {
-  using Type = T;
-};
-
-// A wrapper for a PrefChangeMethod instance method which forwards calls to the
-// wrapped method on the given instance.
-template <typename T, PrefChangedMethod T::*Method>
-void PrefChangeMethod(const char* aPref, T* aInst) {
-  ((*aInst).*Method)(aPref);
-}
-}  // namespace detail
-
-// Creates a wrapper around an instance method, with the signature of
-// PrefChangedMethod, from an arbitrary class, so that it can be used as a
-// preference callback. The closure data passed to RegisterCallback must be an
-// instance of this class.
-//
-// Note: This is implemented as a macro rather than a pure template function
-// because, prior to C++17, value template arguments must have their types
-// fully-specified. Once all of our supported compilers have C++17 support, we
-// can give PrefChangeMethod a single <auto Method> argument, and use
-// PrefChangeMethod<&meth> directly.
-#define PREF_CHANGE_METHOD(meth)         \
-  (&::mozilla::detail::PrefChangeMethod< \
-      ::mozilla::detail::InstanceType<decltype(&meth)>::Type, &meth>)
-
 class PreferenceServiceReporter;
 
 namespace dom {
 class Pref;
 class PrefValue;
 }  // namespace dom
 
 namespace ipc {
@@ -323,146 +253,146 @@ class Preferences final : public nsIPref
   // literals.
   static nsresult AddStrongObservers(nsIObserver* aObserver,
                                      const char** aPrefs);
   static nsresult AddWeakObservers(nsIObserver* aObserver, const char** aPrefs);
   static nsresult RemoveObservers(nsIObserver* aObserver, const char** aPrefs);
 
   // Registers/Unregisters the callback function for the aPref.
   template <typename T = void>
-  static nsresult RegisterCallback(
-      typename TypedPrefChangeFunc<T>::Type aCallback, const nsACString& aPref,
-      T* aClosure = nullptr) {
+  static nsresult RegisterCallback(PrefChangedFunc aCallback,
+                                   const nsACString& aPref,
+                                   T* aClosure = nullptr) {
     return RegisterCallback(aCallback, aPref, aClosure, ExactMatch);
   }
 
   template <typename T = void>
-  static nsresult UnregisterCallback(
-      typename TypedPrefChangeFunc<T>::Type aCallback, const nsACString& aPref,
-      T* aClosure = nullptr) {
+  static nsresult UnregisterCallback(PrefChangedFunc aCallback,
+                                     const nsACString& aPref,
+                                     T* aClosure = nullptr) {
     return UnregisterCallback(aCallback, aPref, aClosure, ExactMatch);
   }
 
   // Like RegisterCallback, but also calls the callback immediately for
   // initialization.
   template <typename T = void>
-  static nsresult RegisterCallbackAndCall(
-      typename TypedPrefChangeFunc<T>::Type aCallback, const nsACString& aPref,
-      T* aClosure = nullptr) {
+  static nsresult RegisterCallbackAndCall(PrefChangedFunc aCallback,
+                                          const nsACString& aPref,
+                                          T* aClosure = nullptr) {
     return RegisterCallbackAndCall(aCallback, aPref, aClosure, ExactMatch);
   }
 
   // Like RegisterCallback, but registers a callback for a prefix of multiple
   // pref names, not a single pref name.
   template <typename T = void>
-  static nsresult RegisterPrefixCallback(
-      typename TypedPrefChangeFunc<T>::Type aCallback, const nsACString& aPref,
-      T* aClosure = nullptr) {
+  static nsresult RegisterPrefixCallback(PrefChangedFunc aCallback,
+                                         const nsACString& aPref,
+                                         T* aClosure = nullptr) {
     return RegisterCallback(aCallback, aPref, aClosure, PrefixMatch);
   }
 
   // Like RegisterPrefixCallback, but also calls the callback immediately for
   // initialization.
   template <typename T = void>
-  static nsresult RegisterPrefixCallbackAndCall(
-      typename TypedPrefChangeFunc<T>::Type aCallback, const nsACString& aPref,
-      T* aClosure = nullptr) {
+  static nsresult RegisterPrefixCallbackAndCall(PrefChangedFunc aCallback,
+                                                const nsACString& aPref,
+                                                T* aClosure = nullptr) {
     return RegisterCallbackAndCall(aCallback, aPref, aClosure, PrefixMatch);
   }
 
   // Unregister a callback registered with RegisterPrefixCallback or
   // RegisterPrefixCallbackAndCall.
   template <typename T = void>
-  static nsresult UnregisterPrefixCallback(
-      typename TypedPrefChangeFunc<T>::Type aCallback, const nsACString& aPref,
-      T* aClosure = nullptr) {
+  static nsresult UnregisterPrefixCallback(PrefChangedFunc aCallback,
+                                           const nsACString& aPref,
+                                           T* aClosure = nullptr) {
     return UnregisterCallback(aCallback, aPref, aClosure, PrefixMatch);
   }
 
   // Variants of the above which register a single callback to handle multiple
   // preferences.
   //
   // The array of preference names must be null terminated. It may be
   // dynamically allocated, but the caller is responsible for keeping it alive
   // until the callback is unregistered.
   //
   // Also note that the exact same aPrefs pointer must be passed to the
   // Unregister call as was passed to the Register call.
   template <typename T = void>
-  static nsresult RegisterCallbacks(
-      typename TypedPrefChangeFunc<T>::Type aCallback, const char** aPrefs,
-      T* aClosure = nullptr) {
+  static nsresult RegisterCallbacks(PrefChangedFunc aCallback,
+                                    const char** aPrefs,
+                                    T* aClosure = nullptr) {
     return RegisterCallbacks(aCallback, aPrefs, aClosure, ExactMatch);
   }
   static nsresult RegisterCallbacksAndCall(PrefChangedFunc aCallback,
                                            const char** aPrefs,
                                            void* aClosure = nullptr);
   template <typename T = void>
-  static nsresult UnregisterCallbacks(
-      typename TypedPrefChangeFunc<T>::Type aCallback, const char** aPrefs,
-      T* aClosure = nullptr) {
+  static nsresult UnregisterCallbacks(PrefChangedFunc aCallback,
+                                      const char** aPrefs,
+                                      T* aClosure = nullptr) {
     return UnregisterCallbacks(aCallback, aPrefs, aClosure, ExactMatch);
   }
   template <typename T = void>
-  static nsresult RegisterPrefixCallbacks(
-      typename TypedPrefChangeFunc<T>::Type aCallback, const char** aPrefs,
-      T* aClosure = nullptr) {
+  static nsresult RegisterPrefixCallbacks(PrefChangedFunc aCallback,
+                                          const char** aPrefs,
+                                          T* aClosure = nullptr) {
     return RegisterCallbacks(aCallback, aPrefs, aClosure, PrefixMatch);
   }
   template <typename T = void>
-  static nsresult UnregisterPrefixCallbacks(
-      typename TypedPrefChangeFunc<T>::Type aCallback, const char** aPrefs,
-      T* aClosure = nullptr) {
+  static nsresult UnregisterPrefixCallbacks(PrefChangedFunc aCallback,
+                                            const char** aPrefs,
+                                            T* aClosure = nullptr) {
     return UnregisterCallbacks(aCallback, aPrefs, aClosure, PrefixMatch);
   }
 
   template <int N, typename T = void>
-  static nsresult RegisterCallback(
-      typename TypedPrefChangeFunc<T>::Type aCallback, const char (&aPref)[N],
-      T* aClosure = nullptr) {
+  static nsresult RegisterCallback(PrefChangedFunc aCallback,
+                                   const char (&aPref)[N],
+                                   T* aClosure = nullptr) {
     return RegisterCallback(aCallback, nsLiteralCString(aPref), aClosure,
                             ExactMatch);
   }
 
   template <int N, typename T = void>
-  static nsresult UnregisterCallback(
-      typename TypedPrefChangeFunc<T>::Type aCallback, const char (&aPref)[N],
-      T* aClosure = nullptr) {
+  static nsresult UnregisterCallback(PrefChangedFunc aCallback,
+                                     const char (&aPref)[N],
+                                     T* aClosure = nullptr) {
     return UnregisterCallback(aCallback, nsLiteralCString(aPref), aClosure,
                               ExactMatch);
   }
 
   template <int N, typename T = void>
-  static nsresult RegisterCallbackAndCall(
-      typename TypedPrefChangeFunc<T>::Type aCallback, const char (&aPref)[N],
-      T* aClosure = nullptr) {
+  static nsresult RegisterCallbackAndCall(PrefChangedFunc aCallback,
+                                          const char (&aPref)[N],
+                                          T* aClosure = nullptr) {
     return RegisterCallbackAndCall(aCallback, nsLiteralCString(aPref), aClosure,
                                    ExactMatch);
   }
 
   template <int N, typename T = void>
-  static nsresult RegisterPrefixCallback(
-      typename TypedPrefChangeFunc<T>::Type aCallback, const char (&aPref)[N],
-      T* aClosure = nullptr) {
+  static nsresult RegisterPrefixCallback(PrefChangedFunc aCallback,
+                                         const char (&aPref)[N],
+                                         T* aClosure = nullptr) {
     return RegisterCallback(aCallback, nsLiteralCString(aPref), aClosure,
                             PrefixMatch);
   }
 
   template <int N, typename T = void>
-  static nsresult RegisterPrefixCallbackAndCall(
-      typename TypedPrefChangeFunc<T>::Type aCallback, const char (&aPref)[N],
-      T* aClosure = nullptr) {
+  static nsresult RegisterPrefixCallbackAndCall(PrefChangedFunc aCallback,
+                                                const char (&aPref)[N],
+                                                T* aClosure = nullptr) {
     return RegisterCallbackAndCall(aCallback, nsLiteralCString(aPref), aClosure,
                                    PrefixMatch);
   }
 
   template <int N, typename T = void>
-  static nsresult UnregisterPrefixCallback(
-      typename TypedPrefChangeFunc<T>::Type aCallback, const char (&aPref)[N],
-      T* aClosure = nullptr) {
+  static nsresult UnregisterPrefixCallback(PrefChangedFunc aCallback,
+                                           const char (&aPref)[N],
+                                           T* aClosure = nullptr) {
     return UnregisterCallback(aCallback, nsLiteralCString(aPref), aClosure,
                               PrefixMatch);
   }
 
   // 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.
--- a/modules/libpref/test/gtest/CallbackAndVarCacheOrder.cpp
+++ b/modules/libpref/test/gtest/CallbackAndVarCacheOrder.cpp
@@ -14,20 +14,21 @@ namespace mozilla {
 template <typename T, typename U>
 struct Closure {
   U* mLocation;
   T mExpected;
   bool mCalled;
 };
 
 template <typename T, typename U>
-void VarChanged(const char* aPrefName, Closure<T, U>* aClosure) {
-  ASSERT_EQ(*aClosure->mLocation, aClosure->mExpected);
-  ASSERT_FALSE(aClosure->mCalled);
-  aClosure->mCalled = true;
+void VarChanged(const char* aPrefName, void* aClosure) {
+  auto closure = static_cast<Closure<T, U>*>(aClosure);
+  ASSERT_EQ(*closure->mLocation, closure->mExpected);
+  ASSERT_FALSE(closure->mCalled);
+  closure->mCalled = true;
 }
 
 void SetFunc(const nsCString& aPrefName, bool aValue) {
   nsresult rv = Preferences::SetBool(aPrefName.get(), aValue);
   ASSERT_TRUE(NS_SUCCEEDED(rv));
 }
 
 void SetFunc(const nsCString& aPrefName, int32_t aValue) {
--- a/netwerk/base/nsIOService.cpp
+++ b/netwerk/base/nsIOService.cpp
@@ -237,18 +237,18 @@ nsresult nsIOService::Init() {
 
   InitializeCaptivePortalService();
 
   // setup our bad port list stuff
   for (int i = 0; gBadPortList[i]; i++)
     mRestrictedPortList.AppendElement(gBadPortList[i]);
 
   // Further modifications to the port list come from prefs
-  Preferences::RegisterPrefixCallbacks(
-      PREF_CHANGE_METHOD(nsIOService::PrefsChanged), gCallbackPrefs, this);
+  Preferences::RegisterPrefixCallbacks(nsIOService::PrefsChanged,
+                                       gCallbackPrefs, this);
   PrefsChanged();
 
   // Register for profile change notifications
   nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
   if (observerService) {
     observerService->AddObserver(this, kProfileChangeNetTeardownTopic, true);
     observerService->AddObserver(this, kProfileChangeNetRestoreTopic, true);
     observerService->AddObserver(this, kProfileDoChange, true);
@@ -408,17 +408,17 @@ nsresult nsIOService::LaunchSocketProces
   }
 
   if (!Preferences::GetBool("network.process.enabled", true)) {
     LOG(("nsIOService skipping LaunchSocketProcess because of the pref"));
     return NS_OK;
   }
 
   Preferences::RegisterPrefixCallbacks(
-      PREF_CHANGE_METHOD(nsIOService::NotifySocketProcessPrefsChanged),
+      nsIOService::NotifySocketProcessPrefsChanged,
       gCallbackPrefsForSocketProcess, this);
 
   // The subprocess is launched asynchronously, so we wait for a callback to
   // acquire the IPDL actor.
   mSocketProcess = new SocketProcessHost(new SocketProcessListenerProxy());
   LOG(("nsIOService::LaunchSocketProcess"));
   if (!mSocketProcess->Launch()) {
     NS_WARNING("Failed to launch socket process!!");
@@ -432,27 +432,33 @@ nsresult nsIOService::LaunchSocketProces
 void nsIOService::DestroySocketProcess() {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (XRE_GetProcessType() != GeckoProcessType_Default || !mSocketProcess) {
     return;
   }
 
   Preferences::UnregisterPrefixCallbacks(
-      PREF_CHANGE_METHOD(nsIOService::NotifySocketProcessPrefsChanged),
+      nsIOService::NotifySocketProcessPrefsChanged,
       gCallbackPrefsForSocketProcess, this);
 
   mSocketProcess->Shutdown();
   mSocketProcess = nullptr;
 }
 
 bool nsIOService::SocketProcessReady() {
   return mSocketProcess && mSocketProcess->IsConnected();
 }
 
+// static
+void nsIOService::NotifySocketProcessPrefsChanged(const char* aName,
+                                                  void* aSelf) {
+  static_cast<nsIOService*>(aSelf)->NotifySocketProcessPrefsChanged(aName);
+}
+
 void nsIOService::NotifySocketProcessPrefsChanged(const char* aName) {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!XRE_IsParentProcess()) {
     return;
   }
 
   dom::Pref pref(nsCString(aName), /* isLocked */ false, Nothing(), Nothing());
@@ -1247,16 +1253,21 @@ nsIOService::AllowPort(int32_t inPort, c
   }
 
   *_retval = true;
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
+// static
+void nsIOService::PrefsChanged(const char* pref, void* self) {
+  static_cast<nsIOService*>(self)->PrefsChanged(pref);
+}
+
 void nsIOService::PrefsChanged(const char* pref) {
   // Look for extra ports to block
   if (!pref || strcmp(pref, PORT_PREF("banned")) == 0)
     ParsePortList(PORT_PREF("banned"), false);
 
   // ...as well as previous blocks to remove.
   if (!pref || strcmp(pref, PORT_PREF("banned.override")) == 0)
     ParsePortList(PORT_PREF("banned.override"), true);
--- a/netwerk/base/nsIOService.h
+++ b/netwerk/base/nsIOService.h
@@ -112,16 +112,17 @@ class nsIOService final : public nsIIOSe
   uint32_t GetNetWonRequestNumber() { return mNetWon; }
 
   // Used to trigger a recheck of the captive portal status
   nsresult RecheckCaptivePortal();
 
   void OnProcessLaunchComplete(SocketProcessHost* aHost, bool aSucceeded);
   void OnProcessUnexpectedShutdown(SocketProcessHost* aHost);
   bool SocketProcessReady();
+  static void NotifySocketProcessPrefsChanged(const char* aName, void* aSelf);
   void NotifySocketProcessPrefsChanged(const char* aName);
 
   bool IsSocketProcessLaunchComplete();
 
   // Call func immediately if socket process is launched completely. Otherwise,
   // |func| will be queued and then executed in the *main thread* once socket
   // process is launced.
   void CallOrWaitForSocketProcess(const std::function<void()>& aFunc);
@@ -146,16 +147,17 @@ class nsIOService final : public nsIIOSe
                                     nsIProtocolHandler** hdlrResult,
                                     uint32_t start = 0, uint32_t end = 0);
   nsresult CacheProtocolHandler(const char* scheme, nsIProtocolHandler* hdlr);
 
   nsresult InitializeCaptivePortalService();
   nsresult RecheckCaptivePortalIfLocalRedirect(nsIChannel* newChan);
 
   // Prefs wrangling
+  static void PrefsChanged(const char* pref, void* self);
   void PrefsChanged(const char* pref = nullptr);
   void ParsePortList(const char* pref, bool remove);
 
   nsresult InitializeSocketTransportService();
   nsresult InitializeNetworkLinkService();
   nsresult InitializeProtocolProxyService();
 
   // consolidated helper function
--- a/netwerk/base/nsSocketTransportService2.cpp
+++ b/netwerk/base/nsSocketTransportService2.cpp
@@ -582,19 +582,18 @@ static const char* gCallbackPrefs[] = {
     MAX_TIME_FOR_PR_CLOSE_DURING_SHUTDOWN,
     POLLABLE_EVENT_TIMEOUT,
     ESNI_ENABLED,
     ESNI_DISABLED_MITM,
     nullptr,
 };
 
 /* static */
-void nsSocketTransportService::PrefCallback(const char* aPref,
-                                            nsSocketTransportService* aSelf) {
-  aSelf->UpdatePrefs();
+void nsSocketTransportService::UpdatePrefs(const char* aPref, void* aSelf) {
+  static_cast<nsSocketTransportService*>(aSelf)->UpdatePrefs();
 }
 
 // called from main thread only
 NS_IMETHODIMP
 nsSocketTransportService::Init() {
   if (!NS_IsMainThread()) {
     NS_ERROR("wrong thread");
     return NS_ERROR_UNEXPECTED;
@@ -610,17 +609,17 @@ nsSocketTransportService::Init() {
   if (NS_FAILED(rv)) return rv;
 
   {
     MutexAutoLock lock(mLock);
     // Install our mThread, protecting against concurrent readers
     thread.swap(mThread);
   }
 
-  Preferences::RegisterCallbacks(PrefCallback, gCallbackPrefs, this);
+  Preferences::RegisterCallbacks(UpdatePrefs, gCallbackPrefs, this);
   UpdatePrefs();
 
   nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService();
   if (obsSvc) {
     obsSvc->AddObserver(this, "profile-initial-state", false);
     obsSvc->AddObserver(this, "last-pb-context-exited", false);
     obsSvc->AddObserver(this, NS_WIDGET_SLEEP_OBSERVER_TOPIC, true);
     obsSvc->AddObserver(this, NS_WIDGET_WAKE_OBSERVER_TOPIC, true);
@@ -672,17 +671,17 @@ nsresult nsSocketTransportService::Shutd
   mThread->Shutdown();
   {
     MutexAutoLock lock(mLock);
     // Drop our reference to mThread and make sure that any concurrent
     // readers are excluded
     mThread = nullptr;
   }
 
-  Preferences::UnregisterCallbacks(PrefCallback, gCallbackPrefs, this);
+  Preferences::UnregisterCallbacks(UpdatePrefs, gCallbackPrefs, this);
 
   nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService();
   if (obsSvc) {
     obsSvc->RemoveObserver(this, "profile-initial-state");
     obsSvc->RemoveObserver(this, "last-pb-context-exited");
     obsSvc->RemoveObserver(this, NS_WIDGET_SLEEP_OBSERVER_TOPIC);
     obsSvc->RemoveObserver(this, NS_WIDGET_WAKE_OBSERVER_TOPIC);
     obsSvc->RemoveObserver(this, "xpcom-shutdown-threads");
--- a/netwerk/base/nsSocketTransportService2.h
+++ b/netwerk/base/nsSocketTransportService2.h
@@ -237,17 +237,17 @@ class nsSocketTransportService final : p
 
   //-------------------------------------------------------------------------
   // pending socket queue - see NotifyWhenCanAttachSocket
   //-------------------------------------------------------------------------
   AutoCleanLinkedList<LinkedRunnableEvent> mPendingSocketQueue;
 
   // Preference Monitor for SendBufferSize and Keepalive prefs.
   nsresult UpdatePrefs();
-  static void PrefCallback(const char* aPref, nsSocketTransportService* aSelf);
+  static void UpdatePrefs(const char* aPref, void* aSelf);
   void UpdateSendBufferPref();
   int32_t mSendBufferSize;
   // Number of seconds of connection is idle before first keepalive ping.
   int32_t mKeepaliveIdleTimeS;
   // Number of seconds between retries should keepalive pings fail.
   int32_t mKeepaliveRetryIntervalS;
   // Number of keepalive probes to send.
   int32_t mKeepaliveProbeCount;
--- a/netwerk/dns/nsHostResolver.cpp
+++ b/netwerk/dns/nsHostResolver.cpp
@@ -547,17 +547,17 @@ static const char kPrefGetTtl[] = "netwo
 static const char kPrefNativeIsLocalhost[] = "network.dns.native-is-localhost";
 static const char kPrefThreadIdleTime[] =
     "network.dns.resolver-thread-extra-idle-time-seconds";
 static const char kPrefSkipTRRParentalControl[] =
     "network.dns.skipTRR-when-parental-control-enabled";
 static bool sGetTtlEnabled = false;
 mozilla::Atomic<bool, mozilla::Relaxed> gNativeIsLocalhost;
 
-static void DnsPrefChanged(const char* aPref, nsHostResolver* aSelf) {
+static void DnsPrefChanged(const char* aPref, void* aSelf) {
   MOZ_ASSERT(NS_IsMainThread(),
              "Should be getting pref changed notification on main thread!");
 
   MOZ_ASSERT(aSelf);
 
   if (!strcmp(aPref, kPrefGetTtl)) {
 #ifdef DNSQUERY_AVAILABLE
     sGetTtlEnabled = Preferences::GetBool(kPrefGetTtl);
--- a/netwerk/dns/nsIDNService.h
+++ b/netwerk/dns/nsIDNService.h
@@ -93,19 +93,20 @@ class nsIDNService final : public nsIIDN
   nsresult UTF8toACE(const nsACString& input, nsACString& ace,
                      stringPrepFlag flag);
   nsresult ACEtoUTF8(const nsACString& input, nsACString& _retval,
                      stringPrepFlag flag);
 
   bool isInWhitelist(const nsACString& host);
   void prefsChanged(const char* pref);
 
-  static void PrefChanged(const char* aPref, nsIDNService* aSelf) {
-    mozilla::MutexAutoLock lock(aSelf->mLock);
-    aSelf->prefsChanged(aPref);
+  static void PrefChanged(const char* aPref, void* aSelf) {
+    auto self = static_cast<nsIDNService*>(aSelf);
+    mozilla::MutexAutoLock lock(self->mLock);
+    self->prefsChanged(aPref);
   }
 
   /**
    * Determine whether a label is considered safe to display to the user
    * according to the algorithm defined in UTR 39 and the profile
    * selected in mRestrictionProfile.
    *
    * For the ASCII-only profile, returns false for all labels containing
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -449,18 +449,18 @@ nsresult nsHttpHandler::Init() {
 
   // This perference is only used in parent process.
   if (!IsNeckoChild()) {
     mActiveTabPriority =
         Preferences::GetBool(HTTP_PREF("active_tab_priority"), true);
   }
 
   // monitor some preference changes
-  Preferences::RegisterPrefixCallbacks(
-      PREF_CHANGE_METHOD(nsHttpHandler::PrefsChanged), gCallbackPrefs, this);
+  Preferences::RegisterPrefixCallbacks(nsHttpHandler::PrefsChanged,
+                                       gCallbackPrefs, this);
   PrefsChanged(nullptr);
 
   mMisc.AssignLiteral("rv:" MOZILLA_UAVERSION);
 
   mCompatFirefox.AssignLiteral("Firefox/" MOZILLA_UAVERSION);
 
   nsCOMPtr<nsIXULAppInfo> appInfo =
       do_GetService("@mozilla.org/xre/app-info;1");
@@ -1080,16 +1080,21 @@ uint32_t nsHttpHandler::MaxSocketCount()
   if (maxCount <= 8)
     maxCount = 1;
   else
     maxCount -= 8;
 
   return maxCount;
 }
 
+// static
+void nsHttpHandler::PrefsChanged(const char* pref, void* self) {
+  static_cast<nsHttpHandler*>(self)->PrefsChanged(pref);
+}
+
 void nsHttpHandler::PrefsChanged(const char* pref) {
   nsresult rv = NS_OK;
   int32_t val;
 
   LOG(("nsHttpHandler::PrefsChanged [pref=%s]\n", pref));
 
   if (pref) {
     gIOService->NotifySocketProcessPrefsChanged(pref);
--- a/netwerk/protocol/http/nsHttpHandler.h
+++ b/netwerk/protocol/http/nsHttpHandler.h
@@ -467,16 +467,17 @@ class nsHttpHandler final : public nsIHt
 
   MOZ_MUST_USE nsresult Init();
 
   //
   // Useragent/prefs helper methods
   //
   void BuildUserAgent();
   void InitUserAgentComponents();
+  static void PrefsChanged(const char* pref, void* self);
   void PrefsChanged(const char* pref);
 
   MOZ_MUST_USE nsresult SetAcceptLanguages();
   MOZ_MUST_USE nsresult SetAcceptEncodings(const char*, bool mIsSecure);
 
   MOZ_MUST_USE nsresult InitConnectionMgr();
 
   void NotifyObservers(nsIChannel* chan, const char* event);
--- a/netwerk/url-classifier/UrlClassifierFeatureBase.cpp
+++ b/netwerk/url-classifier/UrlClassifierFeatureBase.cpp
@@ -11,22 +11,23 @@
 namespace mozilla {
 
 using namespace safebrowsing;
 
 namespace net {
 
 namespace {
 
-void OnPrefsChange(const char* aPrefName, nsTArray<nsCString>* aArray) {
-  MOZ_ASSERT(aArray);
+void OnPrefsChange(const char* aPrefName, void* aArray) {
+  auto array = static_cast<nsTArray<nsCString>*>(aArray);
+  MOZ_ASSERT(array);
 
   nsAutoCString value;
   Preferences::GetCString(aPrefName, value);
-  Classifier::SplitTables(value, *aArray);
+  Classifier::SplitTables(value, *array);
 }
 
 }  // namespace
 
 NS_INTERFACE_MAP_BEGIN(UrlClassifierFeatureBase)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIUrlClassifierFeature)
   NS_INTERFACE_MAP_ENTRY(nsIUrlClassifierFeature)
   NS_INTERFACE_MAP_ENTRY(nsIUrlClassifierSkipListObserver)
--- a/netwerk/url-classifier/nsChannelClassifier.cpp
+++ b/netwerk/url-classifier/nsChannelClassifier.cpp
@@ -58,32 +58,34 @@ class CachedPrefs final {
     mSkipHostnames = aHostnames;
   }
 
  private:
   friend class StaticAutoPtr<CachedPrefs>;
   CachedPrefs();
   ~CachedPrefs();
 
-  static void OnPrefsChange(const char* aPrefName, CachedPrefs*);
+  static void OnPrefsChange(const char* aPrefName, void*);
 
   nsCString mSkipHostnames;
 
   static StaticAutoPtr<CachedPrefs> sInstance;
 };
 
 StaticAutoPtr<CachedPrefs> CachedPrefs::sInstance;
 
 // static
-void CachedPrefs::OnPrefsChange(const char* aPref, CachedPrefs* aPrefs) {
+void CachedPrefs::OnPrefsChange(const char* aPref, void* aPrefs) {
+  auto prefs = static_cast<CachedPrefs*>(aPrefs);
+
   if (!strcmp(aPref, URLCLASSIFIER_SKIP_HOSTNAMES)) {
     nsCString skipHostnames;
     Preferences::GetCString(URLCLASSIFIER_SKIP_HOSTNAMES, skipHostnames);
     ToLowerCase(skipHostnames);
-    aPrefs->SetSkipHostnames(skipHostnames);
+    prefs->SetSkipHostnames(skipHostnames);
   }
 }
 
 void CachedPrefs::Init() {
   Preferences::RegisterCallbackAndCall(CachedPrefs::OnPrefsChange,
                                        URLCLASSIFIER_SKIP_HOSTNAMES, this);
 }
 
--- a/security/manager/ssl/CertBlocklist.cpp
+++ b/security/manager/ssl/CertBlocklist.cpp
@@ -604,21 +604,19 @@ CertBlocklist::IsBlocklistFresh(bool* _r
   }
   MOZ_LOG(
       gCertBlockPRLog, LogLevel::Warning,
       ("CertBlocklist::IsBlocklistFresh ? %s", *_retval ? "true" : "false"));
   return NS_OK;
 }
 
 /* static */
-void CertBlocklist::PreferenceChanged(const char* aPref,
-                                      CertBlocklist* aBlocklist)
-
-{
-  MutexAutoLock lock(aBlocklist->mMutex);
+void CertBlocklist::PreferenceChanged(const char* aPref, void* aBlocklist) {
+  auto blocklist = static_cast<CertBlocklist*>(aBlocklist);
+  MutexAutoLock lock(blocklist->mMutex);
 
   MOZ_LOG(gCertBlockPRLog, LogLevel::Warning,
           ("CertBlocklist::PreferenceChanged %s changed", aPref));
   if (strcmp(aPref, PREF_BLOCKLIST_ONECRL_CHECKED) == 0) {
     sLastBlocklistUpdate =
         Preferences::GetUint(PREF_BLOCKLIST_ONECRL_CHECKED, uint32_t(0));
   } else if (strcmp(aPref, PREF_MAX_STALENESS_IN_SECONDS) == 0) {
     sMaxStaleness =
--- a/security/manager/ssl/DataStorage.cpp
+++ b/security/manager/ssl/DataStorage.cpp
@@ -181,17 +181,17 @@ DataStorage::DataStorage(const nsString&
       mPendingWrite(false),
       mShuttingDown(false),
       mInitCalled(false),
       mReadyMonitor("DataStorage::mReadyMonitor"),
       mReady(false),
       mFilename(aFilename) {}
 
 DataStorage::~DataStorage() {
-  Preferences::UnregisterCallback(PREF_CHANGE_METHOD(DataStorage::PrefChanged),
+  Preferences::UnregisterCallback(DataStorage::PrefChanged,
                                   "test.datastorage.write_timer_ms", this);
 }
 
 // static
 already_AddRefed<DataStorage> DataStorage::Get(DataStorageClass aFilename) {
   switch (aFilename) {
 #define DATA_STORAGE(_)     \
   case DataStorageClass::_: \
@@ -373,17 +373,17 @@ nsresult DataStorage::Init(
   }
   // In the Parent process, this is a backstop for xpcshell and other cases
   // where profile-before-change might not get sent.
   os->AddObserver(this, "xpcom-shutdown-threads", false);
 
   // For test purposes, we can set the write timer to be very fast.
   mTimerDelay = Preferences::GetInt("test.datastorage.write_timer_ms",
                                     sDataStorageDefaultTimerDelay);
-  Preferences::RegisterCallback(PREF_CHANGE_METHOD(DataStorage::PrefChanged),
+  Preferences::RegisterCallback(DataStorage::PrefChanged,
                                 "test.datastorage.write_timer_ms", this);
 
   return NS_OK;
 }
 
 class DataStorage::Reader : public Runnable {
  public:
   explicit Reader(DataStorage* aDataStorage)
@@ -1068,16 +1068,21 @@ DataStorage::Observe(nsISupports* /*aSub
     }
     sDataStorages->Clear();
     DataStorageSharedThread::Shutdown();
   }
 
   return NS_OK;
 }
 
+// static
+void DataStorage::PrefChanged(const char* aPref, void* aSelf) {
+  static_cast<DataStorage*>(aSelf)->PrefChanged(aPref);
+}
+
 void DataStorage::PrefChanged(const char* aPref) {
   MutexAutoLock lock(mMutex);
   mTimerDelay = Preferences::GetInt("test.datastorage.write_timer_ms",
                                     sDataStorageDefaultTimerDelay);
 }
 
 DataStorage::Entry::Entry()
     : mScore(0), mLastAccessed((int32_t)(PR_Now() / sOneDayInMicroseconds)) {}
--- a/security/manager/ssl/DataStorage.h
+++ b/security/manager/ssl/DataStorage.h
@@ -189,16 +189,17 @@ class DataStorage : public nsIObserver {
 
   static nsresult ValidateKeyAndValue(const nsCString& aKey,
                                       const nsCString& aValue);
   static void TimerCallback(nsITimer* aTimer, void* aClosure);
   void SetTimer();
   void ShutdownTimer();
   void NotifyObservers(const char* aTopic);
 
+  static void PrefChanged(const char* aPref, void* aSelf);
   void PrefChanged(const char* aPref);
 
   bool GetInternal(const nsCString& aKey, Entry* aEntry, DataStorageType aType,
                    const MutexAutoLock& aProofOfLock);
   nsresult PutInternal(const nsCString& aKey, Entry& aEntry,
                        DataStorageType aType,
                        const MutexAutoLock& aProofOfLock);
   void MaybeEvictOneEntry(DataStorageType aType,
--- a/toolkit/components/places/nsNavHistoryResult.cpp
+++ b/toolkit/components/places/nsNavHistoryResult.cpp
@@ -4182,14 +4182,14 @@ nsNavHistoryResult::OnDeleteVisits(nsIUR
 }
 
 void nsNavHistoryResult::OnMobilePrefChanged() {
   ENUMERATE_MOBILE_PREF_OBSERVERS(
       OnMobilePrefChanged(Preferences::GetBool(MOBILE_BOOKMARKS_PREF, false)));
 }
 
 void nsNavHistoryResult::OnMobilePrefChangedCallback(const char* prefName,
-                                                     nsNavHistoryResult* self) {
+                                                     void* self) {
   MOZ_ASSERT(!strcmp(prefName, MOBILE_BOOKMARKS_PREF),
              "We only expected Mobile Bookmarks pref change.");
 
-  self->OnMobilePrefChanged();
+  static_cast<nsNavHistoryResult*>(self)->OnMobilePrefChanged();
 }
--- a/toolkit/components/places/nsNavHistoryResult.h
+++ b/toolkit/components/places/nsNavHistoryResult.h
@@ -184,18 +184,17 @@ class nsNavHistoryResult final
 
   ContainerObserverList mRefreshParticipants;
   void requestRefresh(nsNavHistoryContainerResultNode* aContainer);
 
   void HandlePlacesEvent(const PlacesEventSequence& aEvents) override;
 
   void OnMobilePrefChanged();
 
-  static void OnMobilePrefChangedCallback(const char* prefName,
-                                          nsNavHistoryResult* self);
+  static void OnMobilePrefChangedCallback(const char* prefName, void* self);
 
  protected:
   virtual ~nsNavHistoryResult();
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryResult, NS_NAVHISTORYRESULT_IID)
 
 // nsNavHistoryResultNode
--- a/toolkit/components/resistfingerprinting/nsRFPService.cpp
+++ b/toolkit/components/resistfingerprinting/nsRFPService.cpp
@@ -720,18 +720,18 @@ nsresult nsRFPService::Init() {
   rv = obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
   NS_ENSURE_SUCCESS(rv, rv);
 
 #if defined(XP_WIN)
   rv = obs->AddObserver(this, PROFILE_INITIALIZED_TOPIC, false);
   NS_ENSURE_SUCCESS(rv, rv);
 #endif
 
-  Preferences::RegisterCallbacks(PREF_CHANGE_METHOD(nsRFPService::PrefChanged),
-                                 gCallbackPrefs, this);
+  Preferences::RegisterCallbacks(nsRFPService::PrefChanged, gCallbackPrefs,
+                                 this);
 
   // We backup the original TZ value here.
   const char* tzValue = PR_GetEnv("TZ");
   if (tzValue != nullptr) {
     mInitialTZValue = nsCString(tzValue);
   }
 
   // Call Update here to cache the values of the prefs and set the timezone.
@@ -830,18 +830,18 @@ void nsRFPService::StartShutdown() {
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
 
   StaticMutexAutoLock lock(sLock);
   { sCache = nullptr; }
 
   if (obs) {
     obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
   }
-  Preferences::UnregisterCallbacks(
-      PREF_CHANGE_METHOD(nsRFPService::PrefChanged), gCallbackPrefs, this);
+  Preferences::UnregisterCallbacks(nsRFPService::PrefChanged, gCallbackPrefs,
+                                   this);
 }
 
 /* static */
 void nsRFPService::MaybeCreateSpoofingKeyCodes(const KeyboardLangs aLang,
                                                const KeyboardRegions aRegion) {
   if (sSpoofingKeyboardCodes == nullptr) {
     sSpoofingKeyboardCodes =
         new nsDataHashtable<KeyboardHashKey, const SpoofingKeyboardCode*>();
@@ -1044,16 +1044,21 @@ bool nsRFPService::GetSpoofedKeyCode(con
   if (GetSpoofedKeyCodeInfo(aDoc, aKeyboardEvent, keyCodeInfo)) {
     aOut = keyCodeInfo.mKeyCode;
     return true;
   }
 
   return false;
 }
 
+// static
+void nsRFPService::PrefChanged(const char* aPref, void* aSelf) {
+  static_cast<nsRFPService*>(aSelf)->PrefChanged(aPref);
+}
+
 void nsRFPService::PrefChanged(const char* aPref) {
   nsDependentCString pref(aPref);
 
   if (pref.EqualsLiteral(RFP_TIMER_PREF) ||
       pref.EqualsLiteral(RFP_TIMER_UNCONDITIONAL_PREF) ||
       pref.EqualsLiteral(RFP_TIMER_VALUE_PREF) ||
       pref.EqualsLiteral(RFP_JITTER_VALUE_PREF)) {
     UpdateTimers();
--- a/toolkit/components/resistfingerprinting/nsRFPService.h
+++ b/toolkit/components/resistfingerprinting/nsRFPService.h
@@ -238,16 +238,17 @@ class nsRFPService final : public nsIObs
 
   ~nsRFPService() {}
 
   void UpdateTimers();
   void UpdateRFPPref();
   void StartShutdown();
 
   void PrefChanged(const char* aPref);
+  static void PrefChanged(const char* aPref, void* aSelf);
 
   static void MaybeCreateSpoofingKeyCodes(const KeyboardLangs aLang,
                                           const KeyboardRegions aRegion);
   static void MaybeCreateSpoofingKeyCodesForEnUS();
 
   static void GetKeyboardLangAndRegion(const nsAString& aLanguage,
                                        KeyboardLangs& aLocale,
                                        KeyboardRegions& aRegion);
--- a/widget/windows/WinMouseScrollHandler.h
+++ b/widget/windows/WinMouseScrollHandler.h
@@ -345,18 +345,18 @@ class MouseScrollHandler {
     int32_t GetMouseScrollTransactionTimeout() {
       Init();
       return mMouseScrollTransactionTimeout;
     }
 
    private:
     void Init();
 
-    static void OnChange(const char* aPrefName, UserPrefs* aClosure) {
-      aClosure->MarkDirty();
+    static void OnChange(const char* aPrefName, void* aSelf) {
+      static_cast<UserPrefs*>(aSelf)->MarkDirty();
     }
 
     bool mInitialized;
     bool mScrollMessageHandledAsWheelMessage;
     bool mEnableSystemSettingCache;
     bool mForceEnableSystemSettingCache;
     bool mEmulateToMakeWindowUnderCursorForeground;
     int32_t mOverriddenVerticalScrollAmount;