Bug 1407112 (part 4) - Merge prefapi.{cpp,h} and prefapi_private_data.h into Preferences.cpp. r=glandium.
authorNicholas Nethercote <nnethercote@mozilla.com>
Wed, 11 Oct 2017 21:02:03 +1100
changeset 428248 ebd299dbebdae35905c4d4fd05d49fc1eb21a399
parent 428247 b09c968f6cb99fcd80f6e9a7265b4afc783ac01c
child 428250 ed95d2b8177de8f778ff88f3a69d93dec3685f60
push id97
push userfmarier@mozilla.com
push dateSat, 14 Oct 2017 01:12:59 +0000
reviewersglandium
bugs1407112
milestone58.0a1
Bug 1407112 (part 4) - Merge prefapi.{cpp,h} and prefapi_private_data.h into Preferences.cpp. r=glandium. This required moving WatchinPrefRAII and WATCHING_PREF_RAII MozReview-Commit-ID: Kkefg2ouazK
modules/libpref/Preferences.cpp
modules/libpref/moz.build
modules/libpref/prefapi.cpp
modules/libpref/prefapi.h
modules/libpref/prefapi_private_data.h
--- a/modules/libpref/Preferences.cpp
+++ b/modules/libpref/Preferences.cpp
@@ -2,43 +2,51 @@
 /* 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/. */
 
 #include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
-
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
 #include "GeckoProfiler.h"
+#include "MainThreadUtils.h"
+#include "mozilla/ArenaAllocatorExtensions.h"
+#include "mozilla/ArenaAllocator.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/ContentPrefs.h"
 #include "mozilla/dom/PContent.h"
 #include "mozilla/HashFunctions.h"
+#include "mozilla/Logging.h"
 #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/SyncRunnable.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/UniquePtrExtensions.h"
 #include "mozilla/URLPreloader.h"
 #include "mozilla/Variant.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsAutoPtr.h"
 #include "nsCategoryManagerUtils.h"
+#include "nsClassHashtable.h"
 #include "nsCOMArray.h"
 #include "nsCOMPtr.h"
 #include "nsCRT.h"
-#include "nsClassHashtable.h"
 #include "nsDataHashtable.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsICategoryManager.h"
 #include "nsIConsoleService.h"
 #include "nsIDirectoryService.h"
 #include "nsIFile.h"
 #include "nsIInputStream.h"
 #include "nsIMemoryReporter.h"
@@ -64,24 +72,29 @@
 #include "nsTArray.h"
 #include "nsThreadUtils.h"
 #include "nsUTF8Utils.h"
 #include "nsWeakReference.h"
 #include "nsXPCOMCID.h"
 #include "nsXPCOM.h"
 #include "nsXULAppAPI.h"
 #include "nsZipArchive.h"
+#include "plbase64.h"
 #include "PLDHashTable.h"
-#include "prefapi.h"
-#include "prefapi_private_data.h"
+#include "plstr.h"
+#include "prlink.h"
 
 #ifdef MOZ_CRASHREPORTER
 #include "nsICrashReporter.h"
 #endif
 
+#ifdef XP_WIN
+#include "windows.h"
+#endif
+
 using namespace mozilla;
 
 #ifdef DEBUG
 
 #define ENSURE_MAIN_PROCESS(func, pref)                                        \
   do {                                                                         \
     if (MOZ_UNLIKELY(!XRE_IsParentProcess())) {                                \
       nsPrintfCString msg(                                                     \
@@ -98,41 +111,1407 @@ using namespace mozilla;
       nsPrintfCString msg(                                                     \
         "ENSURE_MAIN_PROCESS: called %s on %s in a non-main process",          \
         func, pref);                                                           \
       NS_WARNING(msg.get());                                                   \
       return NS_ERROR_NOT_AVAILABLE;                                           \
     }                                                                          \
   } while (0)
 
-class WatchinPrefRAII
-{
-public:
-  WatchinPrefRAII() { pref_SetWatchingPref(true); }
-  ~WatchinPrefRAII() { pref_SetWatchingPref(false); }
-};
-
-#define WATCHING_PREF_RAII() WatchinPrefRAII watchingPrefRAII
-
 #else // DEBUG
 
 #define ENSURE_MAIN_PROCESS(func, pref)                                        \
   if (MOZ_UNLIKELY(!XRE_IsParentProcess())) {                                  \
     return NS_ERROR_NOT_AVAILABLE;                                             \
   }
 
 #define ENSURE_MAIN_PROCESS_WITH_WARNING(func, pref)                           \
   if (MOZ_UNLIKELY(!XRE_IsParentProcess())) {                                  \
     return NS_ERROR_NOT_AVAILABLE;                                             \
   }
 
+#endif // DEBUG
+
+//===========================================================================
+// The old low-level prefs API
+//===========================================================================
+
+struct PrefHashEntry;
+
+extern PLDHashTable* gHashTable;
+
+namespace mozilla {
+namespace dom {
+class PrefSetting;
+} // namespace dom
+} // namespace mozilla
+
+typedef nsTArray<mozilla::UniqueFreePtr<char>> PrefSaveData;
+
+PrefSaveData
+pref_savePrefs(PLDHashTable* aTable);
+
+nsresult
+pref_SetPref(const mozilla::dom::PrefSetting& aPref);
+
+#ifdef DEBUG
+void
+pref_SetInitPhase(pref_initPhase aPhase);
+
+pref_initPhase
+pref_GetInitPhase();
+
+void
+pref_SetWatchingPref(bool aWatching);
+#endif
+
+PrefHashEntry*
+pref_HashTableLookup(const char* aKey);
+
+bool
+pref_EntryHasAdvisablySizedValues(PrefHashEntry* aHashEntry);
+
+void
+pref_GetPrefFromEntry(PrefHashEntry* aHashEntry,
+                      mozilla::dom::PrefSetting* aPref);
+
+size_t
+pref_SizeOfPrivateData(mozilla::MallocSizeOf aMallocSizeOf);
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// 1 MB should be enough for everyone.
+static const uint32_t MAX_PREF_LENGTH = 1 * 1024 * 1024;
+// Actually, 4kb should be enough for everyone.
+static const uint32_t MAX_ADVISABLE_PREF_LENGTH = 4 * 1024;
+
+typedef union {
+  char* mStringVal;
+  int32_t mIntVal;
+  bool mBoolVal;
+} PrefValue;
+
+// The Init function initializes the preference context and creates the
+// preference hashtable.
+void
+PREF_Init();
+
+// Cleanup should be called at program exit to free the list of registered
+// callbacks.
+void
+PREF_Cleanup();
+void
+PREF_CleanupPrefs();
+
+// Preference flags, including the native type of the preference. Changing any
+// of these values will require modifying the code inside of PrefTypeFlags
+// class.
+enum class PrefType
+{
+  Invalid = 0,
+  String = 1,
+  Int = 2,
+  Bool = 3,
+};
+
+// Keep the type of the preference, as well as the flags guiding its behaviour.
+class PrefTypeFlags
+{
+public:
+  PrefTypeFlags()
+    : mValue(AsInt(PrefType::Invalid))
+  {
+  }
+
+  explicit PrefTypeFlags(PrefType aType)
+    : mValue(AsInt(aType))
+  {
+  }
+
+  PrefTypeFlags& Reset()
+  {
+    mValue = AsInt(PrefType::Invalid);
+    return *this;
+  }
+
+  bool IsTypeValid() const { return !IsPrefType(PrefType::Invalid); }
+  bool IsTypeString() const { return IsPrefType(PrefType::String); }
+  bool IsTypeInt() const { return IsPrefType(PrefType::Int); }
+  bool IsTypeBool() const { return IsPrefType(PrefType::Bool); }
+  bool IsPrefType(PrefType type) const { return GetPrefType() == type; }
+
+  PrefTypeFlags& SetPrefType(PrefType aType)
+  {
+    mValue = mValue - AsInt(GetPrefType()) + AsInt(aType);
+    return *this;
+  }
+
+  PrefType GetPrefType() const
+  {
+    return (PrefType)(mValue & (AsInt(PrefType::String) | AsInt(PrefType::Int) |
+                                AsInt(PrefType::Bool)));
+  }
+
+  bool HasDefault() const { return mValue & PREF_FLAG_HAS_DEFAULT; }
+
+  PrefTypeFlags& SetHasDefault(bool aSetOrUnset)
+  {
+    return SetFlag(PREF_FLAG_HAS_DEFAULT, aSetOrUnset);
+  }
+
+  bool HasStickyDefault() const { return mValue & PREF_FLAG_STICKY_DEFAULT; }
+
+  PrefTypeFlags& SetHasStickyDefault(bool aSetOrUnset)
+  {
+    return SetFlag(PREF_FLAG_STICKY_DEFAULT, aSetOrUnset);
+  }
+
+  bool IsLocked() const { return mValue & PREF_FLAG_LOCKED; }
+
+  PrefTypeFlags& SetLocked(bool aSetOrUnset)
+  {
+    return SetFlag(PREF_FLAG_LOCKED, aSetOrUnset);
+  }
+
+  bool HasUserValue() const { return mValue & PREF_FLAG_USERSET; }
+
+  PrefTypeFlags& SetHasUserValue(bool aSetOrUnset)
+  {
+    return SetFlag(PREF_FLAG_USERSET, aSetOrUnset);
+  }
+
+private:
+  static uint16_t AsInt(PrefType aType) { return (uint16_t)aType; }
+
+  PrefTypeFlags& SetFlag(uint16_t aFlag, bool aSetOrUnset)
+  {
+    mValue = aSetOrUnset ? mValue | aFlag : mValue & ~aFlag;
+    return *this;
+  }
+
+  // We pack both the value of type (PrefType) and flags into the same int. The
+  // flag enum starts at 4 so that the PrefType can occupy the bottom two bits.
+  enum
+  {
+    PREF_FLAG_LOCKED = 4,
+    PREF_FLAG_USERSET = 8,
+    PREF_FLAG_CONFIG = 16,
+    PREF_FLAG_REMOTE = 32,
+    PREF_FLAG_LILOCAL = 64,
+    PREF_FLAG_HAS_DEFAULT = 128,
+    PREF_FLAG_STICKY_DEFAULT = 256,
+  };
+  uint16_t mValue;
+};
+
+struct PrefHashEntry : PLDHashEntryHdr
+{
+  PrefTypeFlags mPrefFlags; // this field first to minimize 64-bit struct size
+  const char* mKey;
+  PrefValue mDefaultPref;
+  PrefValue mUserPref;
+};
+
+// Set the various types of preferences. These functions take a dotted notation
+// of the preference name (e.g. "browser.startup.homepage"). Note that this
+// will cause the preference to be saved to the file if it is different from
+// the default. In other words, these are used to set the _user_ preferences.
+//
+// If aSetDefault is set to true however, it sets the default value. This will
+// only affect the program behavior if the user does not have a value saved
+// over it for the particular preference. In addition, these will never be
+// saved out to disk.
+//
+// Each set returns PREF_VALUECHANGED if the user value changed (triggering a
+// callback), or PREF_NOERROR if the value was unchanged.
+nsresult
+PREF_SetCharPref(const char* aPref, const char* aVal, bool aSetDefault = false);
+nsresult
+PREF_SetIntPref(const char* aPref, int32_t aVal, bool aSetDefault = false);
+nsresult
+PREF_SetBoolPref(const char* aPref, bool aVal, bool aSetDefault = false);
+
+bool
+PREF_HasUserPref(const char* aPrefName);
+
+// Get the various types of preferences. These functions take a dotted
+// notation of the preference name (e.g. "browser.startup.homepage")
+//
+// They also take a pointer to fill in with the return value and return an
+// error value. At the moment, this is simply an int but it may
+// be converted to an enum once the global error strategy is worked out.
+//
+// They will perform conversion if the type doesn't match what was requested.
+// (if it is reasonably possible)
+nsresult
+PREF_GetIntPref(const char* aPref, int32_t* aValueOut, bool aGetDefault);
+nsresult
+PREF_GetBoolPref(const char* aPref, bool* aValueOut, bool aGetDefault);
+
+// These functions are similar to the above "Get" version with the significant
+// difference that the preference module will alloc the memory (e.g. XP_STRDUP)
+// and the caller will need to be responsible for freeing it...
+nsresult
+PREF_CopyCharPref(const char* aPref, char** aValueOut, bool aGetDefault);
+
+// Bool function that returns whether or not the preference is locked and
+// therefore cannot be changed.
+bool
+PREF_PrefIsLocked(const char* aPrefName);
+
+// Function that sets whether or not the preference is locked and therefore
+// cannot be changed.
+nsresult
+PREF_LockPref(const char* aKey, bool aLockIt);
+
+PrefType
+PREF_GetPrefType(const char* aPrefName);
+
+// Delete a branch of the tree.
+nsresult
+PREF_DeleteBranch(const char* aBranchName);
+
+// Clears the given pref (reverts it to its default value).
+nsresult
+PREF_ClearUserPref(const char* aPrefName);
+
+// Clears all user prefs.
+nsresult
+PREF_ClearAllUserPrefs();
+
+// The callback function will get passed the pref_node which triggered the call
+// and the void* instance_data which was passed to the registered callback
+// function. Return a non-zero result (nsresult) to pass an error up to the
+// caller.
+//
+// Temporarily conditionally compile PrefChangedFunc typedef. During migration
+// from old libpref to nsIPref we need it in both header files. Eventually
+// prefapi.h will become a private file. The two types need to be in sync for
+// now. Certain compilers were having problems with multiple definitions.
+#ifndef have_PrefChangedFunc_typedef
+typedef void (*PrefChangedFunc)(const char*, void*);
+#define have_PrefChangedFunc_typedef
+#endif
+
+// Register a callback. This takes a node in the preference tree and will call
+// the callback function if anything below that node is modified. Unregister
+// returns PREF_NOERROR if a callback was found that matched all the
+// parameters; otherwise it returns PREF_ERROR.
+void
+PREF_RegisterPriorityCallback(const char* aPrefNode,
+                              PrefChangedFunc aCallback,
+                              void* aData);
+void
+PREF_RegisterCallback(const char* aPrefNode,
+                      PrefChangedFunc aCallback,
+                      void* aData);
+nsresult
+PREF_UnregisterCallback(const char* aPrefNode,
+                        PrefChangedFunc aCallback,
+                        void* aData);
+
+// Used by nsPrefService as the callback function of the prefs parser.
+void
+PREF_ReaderCallback(void* aClosure,
+                    const char* aPref,
+                    PrefValue aValue,
+                    PrefType aType,
+                    bool aIsDefault,
+                    bool aIsStickyDefault);
+
+// Callback for whenever we change a preference.
+typedef void (*PrefsDirtyFunc)();
+void PREF_SetDirtyCallback(PrefsDirtyFunc);
+
+#ifdef __cplusplus
+}
+#endif
+
+static void
+ClearPrefEntry(PLDHashTable* aTable, PLDHashEntryHdr* aEntry)
+{
+  auto pref = static_cast<PrefHashEntry*>(aEntry);
+  if (pref->mPrefFlags.IsTypeString()) {
+    if (pref->mDefaultPref.mStringVal) {
+      PL_strfree(pref->mDefaultPref.mStringVal);
+    }
+    if (pref->mUserPref.mStringVal) {
+      PL_strfree(pref->mUserPref.mStringVal);
+    }
+  }
+
+  // Don't need to free this because it's allocated in memory owned by
+  // gPrefNameArena.
+  pref->mKey = nullptr;
+  memset(aEntry, 0, aTable->EntrySize());
+}
+
+static bool
+MatchPrefEntry(const PLDHashEntryHdr* aEntry, const void* aKey)
+{
+  auto prefEntry = static_cast<const PrefHashEntry*>(aEntry);
+
+  if (prefEntry->mKey == aKey) {
+    return true;
+  }
+
+  if (!prefEntry->mKey || !aKey) {
+    return false;
+  }
+
+  auto otherKey = static_cast<const char*>(aKey);
+  return (strcmp(prefEntry->mKey, otherKey) == 0);
+}
+
+struct CallbackNode
+{
+  char* mDomain;
+
+  // If someone attempts to remove the node from the callback list while
+  // pref_DoCallback is running, |func| is set to nullptr. Such nodes will
+  // be removed at the end of pref_DoCallback.
+  PrefChangedFunc mFunc;
+  void* mData;
+  CallbackNode* mNext;
+};
+
+PLDHashTable* gHashTable;
+
+static ArenaAllocator<8192, 4> gPrefNameArena;
+
+static CallbackNode* gFirstCallback = nullptr;
+static CallbackNode* gLastPriorityNode = nullptr;
+
+static bool gIsAnyPrefLocked = false;
+
+// These are only used during the call to pref_DoCallback.
+static bool gCallbacksInProgress = false;
+static bool gShouldCleanupDeadNodes = false;
+
+static PLDHashTableOps pref_HashTableOps = {
+  PLDHashTable::HashStringKey,
+  MatchPrefEntry,
+  PLDHashTable::MoveEntryStub,
+  ClearPrefEntry,
+  nullptr,
+};
+
+// PR_ALIGN_OF_WORD is only defined on some platforms. ALIGN_OF_WORD has
+// already been defined to PR_ALIGN_OF_WORD everywhere.
+#ifndef PR_ALIGN_OF_WORD
+#define PR_ALIGN_OF_WORD PR_ALIGN_OF_POINTER
+#endif
+
+#define WORD_ALIGN_MASK (PR_ALIGN_OF_WORD - 1)
+
+// Sanity checking.
+#if (PR_ALIGN_OF_WORD & WORD_ALIGN_MASK) != 0
+#error "PR_ALIGN_OF_WORD must be a power of 2!"
+#endif
+
+static PrefsDirtyFunc gDirtyCallback = nullptr;
+
+inline void
+MakeDirtyCallback()
+{
+  // Right now the callback function is always set, so we don't need
+  // to complicate the code to cover the scenario where we set the callback
+  // after we've already tried to make it dirty.  If this assert triggers
+  // we will add that code.
+  MOZ_ASSERT(gDirtyCallback);
+  if (gDirtyCallback) {
+    gDirtyCallback();
+  }
+}
+
+void
+PREF_SetDirtyCallback(PrefsDirtyFunc aFunc)
+{
+  gDirtyCallback = aFunc;
+}
+
+//---------------------------------------------------------------------------
+
+static bool
+pref_ValueChanged(PrefValue aOldValue, PrefValue aNewValue, PrefType aType);
+
+static nsresult
+pref_DoCallback(const char* aChangedPref);
+
+enum
+{
+  kPrefSetDefault = 1,
+  kPrefForceSet = 2,
+  kPrefStickyDefault = 4,
+};
+
+static nsresult
+pref_HashPref(const char* aKey,
+              PrefValue aValue,
+              PrefType aType,
+              uint32_t aFlags);
+
+#define PREF_HASHTABLE_INITIAL_LENGTH 1024
+
+void
+PREF_Init()
+{
+  if (!gHashTable) {
+    gHashTable = new PLDHashTable(
+      &pref_HashTableOps, sizeof(PrefHashEntry), PREF_HASHTABLE_INITIAL_LENGTH);
+  }
+}
+
+// Frees the callback list.
+void
+PREF_Cleanup()
+{
+  NS_ASSERTION(!gCallbacksInProgress,
+               "PREF_Cleanup was called while gCallbacksInProgress is true!");
+
+  CallbackNode* node = gFirstCallback;
+  CallbackNode* next_node;
+
+  while (node) {
+    next_node = node->mNext;
+    PL_strfree(node->mDomain);
+    free(node);
+    node = next_node;
+  }
+  gLastPriorityNode = gFirstCallback = nullptr;
+
+  PREF_CleanupPrefs();
+}
+
+// Frees up all the objects except the callback list.
+void
+PREF_CleanupPrefs()
+{
+  if (gHashTable) {
+    delete gHashTable;
+    gHashTable = nullptr;
+    gPrefNameArena.Clear();
+  }
+}
+
+// Note that this appends to aResult, and does not assign!
+static void
+StrEscape(const char* aOriginal, nsCString& aResult)
+{
+  // JavaScript does not allow quotes, slashes, or line terminators inside
+  // strings so we must escape them. ECMAScript defines four line terminators,
+  // but we're only worrying about \r and \n here.  We currently feed our pref
+  // script to the JS interpreter as Latin-1 so  we won't encounter \u2028
+  // (line separator) or \u2029 (paragraph separator).
+  //
+  // WARNING: There are hints that we may be moving to storing prefs as utf8.
+  // If we ever feed them to the JS compiler as UTF8 then we'll have to worry
+  // about the multibyte sequences that would be interpreted as \u2028 and
+  // \u2029.
+  const char* p;
+
+  if (aOriginal == nullptr) {
+    return;
+  }
+
+  // Paranoid worst case all slashes will free quickly.
+  for (p = aOriginal; *p; ++p) {
+    switch (*p) {
+      case '\n':
+        aResult.AppendLiteral("\\n");
+        break;
+
+      case '\r':
+        aResult.AppendLiteral("\\r");
+        break;
+
+      case '\\':
+        aResult.AppendLiteral("\\\\");
+        break;
+
+      case '\"':
+        aResult.AppendLiteral("\\\"");
+        break;
+
+      default:
+        aResult.Append(*p);
+        break;
+    }
+  }
+}
+
+//
+// External calls
+//
+
+nsresult
+PREF_SetCharPref(const char* aPrefName, const char* aValue, bool aSetDefault)
+{
+  if (strlen(aValue) > MAX_PREF_LENGTH) {
+    return NS_ERROR_ILLEGAL_VALUE;
+  }
+
+  PrefValue pref;
+  pref.mStringVal = const_cast<char*>(aValue);
+
+  return pref_HashPref(
+    aPrefName, pref, PrefType::String, aSetDefault ? kPrefSetDefault : 0);
+}
+
+nsresult
+PREF_SetIntPref(const char* aPrefName, int32_t aValue, bool aSetDefault)
+{
+  PrefValue pref;
+  pref.mIntVal = aValue;
+
+  return pref_HashPref(
+    aPrefName, pref, PrefType::Int, aSetDefault ? kPrefSetDefault : 0);
+}
+
+nsresult
+PREF_SetBoolPref(const char* aPrefName, bool aValue, bool aSetDefault)
+{
+  PrefValue pref;
+  pref.mBoolVal = aValue;
+
+  return pref_HashPref(
+    aPrefName, pref, PrefType::Bool, aSetDefault ? kPrefSetDefault : 0);
+}
+
+enum WhichValue
+{
+  DEFAULT_VALUE,
+  USER_VALUE
+};
+
+static nsresult
+SetPrefValue(const char* aPrefName,
+             const dom::PrefValue& aValue,
+             WhichValue aWhich)
+{
+  bool setDefault = (aWhich == DEFAULT_VALUE);
+
+  switch (aValue.type()) {
+    case dom::PrefValue::TnsCString:
+      return PREF_SetCharPref(
+        aPrefName, aValue.get_nsCString().get(), setDefault);
+
+    case dom::PrefValue::Tint32_t:
+      return PREF_SetIntPref(aPrefName, aValue.get_int32_t(), setDefault);
+
+    case dom::PrefValue::Tbool:
+      return PREF_SetBoolPref(aPrefName, aValue.get_bool(), setDefault);
+
+    default:
+      MOZ_CRASH();
+  }
+}
+
+nsresult
+pref_SetPref(const dom::PrefSetting& aPref)
+{
+  const char* prefName = aPref.name().get();
+  const dom::MaybePrefValue& defaultValue = aPref.defaultValue();
+  const dom::MaybePrefValue& userValue = aPref.userValue();
+
+  nsresult rv;
+  if (defaultValue.type() == dom::MaybePrefValue::TPrefValue) {
+    rv = SetPrefValue(prefName, defaultValue.get_PrefValue(), DEFAULT_VALUE);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+  }
+
+  if (userValue.type() == dom::MaybePrefValue::TPrefValue) {
+    rv = SetPrefValue(prefName, userValue.get_PrefValue(), USER_VALUE);
+  } else {
+    rv = PREF_ClearUserPref(prefName);
+  }
+
+  // NB: we should never try to clear a default value, that doesn't
+  // make sense
+
+  return rv;
+}
+
+PrefSaveData
+pref_savePrefs(PLDHashTable* aTable)
+{
+  PrefSaveData savedPrefs(aTable->EntryCount());
+
+  for (auto iter = aTable->Iter(); !iter.Done(); iter.Next()) {
+    auto pref = static_cast<PrefHashEntry*>(iter.Get());
+
+    nsAutoCString prefValue;
+    nsAutoCString prefPrefix;
+    prefPrefix.AssignLiteral("user_pref(\"");
+
+    // where we're getting our pref from
+    PrefValue* sourcePref;
+
+    if (pref->mPrefFlags.HasUserValue() &&
+        (pref_ValueChanged(pref->mDefaultPref,
+                           pref->mUserPref,
+                           pref->mPrefFlags.GetPrefType()) ||
+         !pref->mPrefFlags.HasDefault() ||
+         pref->mPrefFlags.HasStickyDefault())) {
+      sourcePref = &pref->mUserPref;
+    } else {
+      // do not save default prefs that haven't changed
+      continue;
+    }
+
+    // strings are in quotes!
+    if (pref->mPrefFlags.IsTypeString()) {
+      prefValue = '\"';
+      StrEscape(sourcePref->mStringVal, prefValue);
+      prefValue += '\"';
+
+    } else if (pref->mPrefFlags.IsTypeInt()) {
+      prefValue.AppendInt(sourcePref->mIntVal);
+
+    } else if (pref->mPrefFlags.IsTypeBool()) {
+      prefValue = (sourcePref->mBoolVal) ? "true" : "false";
+    }
+
+    nsAutoCString prefName;
+    StrEscape(pref->mKey, prefName);
+
+    savedPrefs.AppendElement()->reset(
+      ToNewCString(prefPrefix + prefName + NS_LITERAL_CSTRING("\", ") +
+                   prefValue + NS_LITERAL_CSTRING(");")));
+  }
+
+  return savedPrefs;
+}
+
+bool
+pref_EntryHasAdvisablySizedValues(PrefHashEntry* aHashEntry)
+{
+  if (aHashEntry->mPrefFlags.GetPrefType() != PrefType::String) {
+    return true;
+  }
+
+  char* stringVal;
+  if (aHashEntry->mPrefFlags.HasDefault()) {
+    stringVal = aHashEntry->mDefaultPref.mStringVal;
+    if (strlen(stringVal) > MAX_ADVISABLE_PREF_LENGTH) {
+      return false;
+    }
+  }
+
+  if (aHashEntry->mPrefFlags.HasUserValue()) {
+    stringVal = aHashEntry->mUserPref.mStringVal;
+    if (strlen(stringVal) > MAX_ADVISABLE_PREF_LENGTH) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+static void
+GetPrefValueFromEntry(PrefHashEntry* aHashEntry,
+                      dom::PrefSetting* aPref,
+                      WhichValue aWhich)
+{
+  PrefValue* value;
+  dom::PrefValue* settingValue;
+  if (aWhich == USER_VALUE) {
+    value = &aHashEntry->mUserPref;
+    aPref->userValue() = dom::PrefValue();
+    settingValue = &aPref->userValue().get_PrefValue();
+  } else {
+    value = &aHashEntry->mDefaultPref;
+    aPref->defaultValue() = dom::PrefValue();
+    settingValue = &aPref->defaultValue().get_PrefValue();
+  }
+
+  switch (aHashEntry->mPrefFlags.GetPrefType()) {
+    case PrefType::String:
+      *settingValue = nsDependentCString(value->mStringVal);
+      return;
+    case PrefType::Int:
+      *settingValue = value->mIntVal;
+      return;
+    case PrefType::Bool:
+      *settingValue = !!value->mBoolVal;
+      return;
+    default:
+      MOZ_CRASH();
+  }
+}
+
+void
+pref_GetPrefFromEntry(PrefHashEntry* aHashEntry, dom::PrefSetting* aPref)
+{
+  aPref->name() = aHashEntry->mKey;
+
+  if (aHashEntry->mPrefFlags.HasDefault()) {
+    GetPrefValueFromEntry(aHashEntry, aPref, DEFAULT_VALUE);
+  } else {
+    aPref->defaultValue() = null_t();
+  }
+
+  if (aHashEntry->mPrefFlags.HasUserValue()) {
+    GetPrefValueFromEntry(aHashEntry, aPref, USER_VALUE);
+  } else {
+    aPref->userValue() = null_t();
+  }
+
+  MOZ_ASSERT(aPref->defaultValue().type() == dom::MaybePrefValue::Tnull_t ||
+             aPref->userValue().type() == dom::MaybePrefValue::Tnull_t ||
+             (aPref->defaultValue().get_PrefValue().type() ==
+              aPref->userValue().get_PrefValue().type()));
+}
+
+bool
+PREF_HasUserPref(const char* aPrefName)
+{
+  if (!gHashTable) {
+    return false;
+  }
+
+  PrefHashEntry* pref = pref_HashTableLookup(aPrefName);
+  return pref && pref->mPrefFlags.HasUserValue();
+}
+
+nsresult
+PREF_CopyCharPref(const char* aPrefName, char** aValueOut, bool aGetDefault)
+{
+  if (!gHashTable) {
+    return NS_ERROR_NOT_INITIALIZED;
+  }
+
+  nsresult rv = NS_ERROR_UNEXPECTED;
+  char* stringVal;
+  PrefHashEntry* pref = pref_HashTableLookup(aPrefName);
+
+  if (pref && pref->mPrefFlags.IsTypeString()) {
+    if (aGetDefault || pref->mPrefFlags.IsLocked() ||
+        !pref->mPrefFlags.HasUserValue()) {
+      stringVal = pref->mDefaultPref.mStringVal;
+    } else {
+      stringVal = pref->mUserPref.mStringVal;
+    }
+
+    if (stringVal) {
+      *aValueOut = NS_strdup(stringVal);
+      rv = NS_OK;
+    }
+  }
+
+  return rv;
+}
+
+nsresult
+PREF_GetIntPref(const char* aPrefName, int32_t* aValueOut, bool aGetDefault)
+{
+  if (!gHashTable) {
+    return NS_ERROR_NOT_INITIALIZED;
+  }
+
+  nsresult rv = NS_ERROR_UNEXPECTED;
+  PrefHashEntry* pref = pref_HashTableLookup(aPrefName);
+  if (pref && pref->mPrefFlags.IsTypeInt()) {
+    if (aGetDefault || pref->mPrefFlags.IsLocked() ||
+        !pref->mPrefFlags.HasUserValue()) {
+      int32_t tempInt = pref->mDefaultPref.mIntVal;
+
+      // Check to see if we even had a default.
+      if (!pref->mPrefFlags.HasDefault()) {
+        return NS_ERROR_UNEXPECTED;
+      }
+      *aValueOut = tempInt;
+    } else {
+      *aValueOut = pref->mUserPref.mIntVal;
+    }
+    rv = NS_OK;
+  }
+
+  return rv;
+}
+
+nsresult
+PREF_GetBoolPref(const char* aPrefName, bool* aValueOut, bool aGetDefault)
+{
+  if (!gHashTable) {
+    return NS_ERROR_NOT_INITIALIZED;
+  }
+
+  nsresult rv = NS_ERROR_UNEXPECTED;
+  PrefHashEntry* pref = pref_HashTableLookup(aPrefName);
+  //NS_ASSERTION(pref, aPrefName);
+  if (pref && pref->mPrefFlags.IsTypeBool()) {
+    if (aGetDefault || pref->mPrefFlags.IsLocked() ||
+        !pref->mPrefFlags.HasUserValue()) {
+      bool tempBool = pref->mDefaultPref.mBoolVal;
+
+      // Check to see if we even had a default.
+      if (pref->mPrefFlags.HasDefault()) {
+        *aValueOut = tempBool;
+        rv = NS_OK;
+      }
+    } else {
+      *aValueOut = pref->mUserPref.mBoolVal;
+      rv = NS_OK;
+    }
+  }
+
+  return rv;
+}
+
+nsresult
+PREF_DeleteBranch(const char* aBranchName)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  size_t len = strlen(aBranchName);
+
+  if (!gHashTable) {
+    return NS_ERROR_NOT_INITIALIZED;
+  }
+
+  // The following check insures that if the branch name already has a "." at
+  // the end, we don't end up with a "..". This fixes an incompatibility
+  // between nsIPref, which needs the period added, and nsIPrefBranch which
+  // does not. When nsIPref goes away this function should be fixed to never
+  // add the period at all.
+  nsAutoCString branch_dot(aBranchName);
+  if (len > 1 && aBranchName[len - 1] != '.') {
+    branch_dot += '.';
+  }
+
+  // Delete a branch. Used for deleting mime types.
+  const char* to_delete = branch_dot.get();
+  MOZ_ASSERT(to_delete);
+  len = strlen(to_delete);
+  for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
+    auto entry = static_cast<PrefHashEntry*>(iter.Get());
+
+    // Note: if we're deleting "ldap" then we want to delete "ldap.xxx" and
+    // "ldap" (if such a leaf node exists) but not "ldap_1.xxx".
+    if (PL_strncmp(entry->mKey, to_delete, len) == 0 ||
+        (len - 1 == strlen(entry->mKey) &&
+         PL_strncmp(entry->mKey, to_delete, len - 1) == 0)) {
+      iter.Remove();
+    }
+  }
+
+  MakeDirtyCallback();
+  return NS_OK;
+}
+
+nsresult
+PREF_ClearUserPref(const char* aPrefName)
+{
+  if (!gHashTable) {
+    return NS_ERROR_NOT_INITIALIZED;
+  }
+
+  PrefHashEntry* pref = pref_HashTableLookup(aPrefName);
+  if (pref && pref->mPrefFlags.HasUserValue()) {
+    pref->mPrefFlags.SetHasUserValue(false);
+
+    if (!pref->mPrefFlags.HasDefault()) {
+      gHashTable->RemoveEntry(pref);
+    }
+
+    pref_DoCallback(aPrefName);
+    MakeDirtyCallback();
+  }
+  return NS_OK;
+}
+
+nsresult
+PREF_ClearAllUserPrefs()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (!gHashTable) {
+    return NS_ERROR_NOT_INITIALIZED;
+  }
+
+  std::vector<std::string> prefStrings;
+  for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
+    auto pref = static_cast<PrefHashEntry*>(iter.Get());
+
+    if (pref->mPrefFlags.HasUserValue()) {
+      prefStrings.push_back(std::string(pref->mKey));
+
+      pref->mPrefFlags.SetHasUserValue(false);
+      if (!pref->mPrefFlags.HasDefault()) {
+        iter.Remove();
+      }
+    }
+  }
+
+  for (std::string& prefString : prefStrings) {
+    pref_DoCallback(prefString.c_str());
+  }
+
+  MakeDirtyCallback();
+  return NS_OK;
+}
+
+nsresult
+PREF_LockPref(const char* aKey, bool aLockIt)
+{
+  if (!gHashTable) {
+    return NS_ERROR_NOT_INITIALIZED;
+  }
+
+  PrefHashEntry* pref = pref_HashTableLookup(aKey);
+  if (!pref) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  if (aLockIt) {
+    if (!pref->mPrefFlags.IsLocked()) {
+      pref->mPrefFlags.SetLocked(true);
+      gIsAnyPrefLocked = true;
+      pref_DoCallback(aKey);
+    }
+  } else if (pref->mPrefFlags.IsLocked()) {
+    pref->mPrefFlags.SetLocked(false);
+    pref_DoCallback(aKey);
+  }
+
+  return NS_OK;
+}
+
+//
+// Hash table functions
+//
+
+static bool
+pref_ValueChanged(PrefValue aOldValue, PrefValue aNewValue, PrefType aType)
+{
+  bool changed = true;
+  switch (aType) {
+    case PrefType::String:
+      if (aOldValue.mStringVal && aNewValue.mStringVal) {
+        changed = (strcmp(aOldValue.mStringVal, aNewValue.mStringVal) != 0);
+      }
+      break;
+
+    case PrefType::Int:
+      changed = aOldValue.mIntVal != aNewValue.mIntVal;
+      break;
+
+    case PrefType::Bool:
+      changed = aOldValue.mBoolVal != aNewValue.mBoolVal;
+      break;
+
+    case PrefType::Invalid:
+    default:
+      changed = false;
+      break;
+  }
+
+  return changed;
+}
+
+// Overwrite the type and value of an existing preference. Caller must ensure
+// that they are not changing the type of a preference that has a default
+// value.
+static PrefTypeFlags
+pref_SetValue(PrefValue* aExistingValue,
+              PrefTypeFlags aFlags,
+              PrefValue aNewValue,
+              PrefType aNewType)
+{
+  if (aFlags.IsTypeString() && aExistingValue->mStringVal) {
+    PL_strfree(aExistingValue->mStringVal);
+  }
+
+  aFlags.SetPrefType(aNewType);
+  if (aFlags.IsTypeString()) {
+    MOZ_ASSERT(aNewValue.mStringVal);
+    aExistingValue->mStringVal =
+      aNewValue.mStringVal ? PL_strdup(aNewValue.mStringVal) : nullptr;
+  } else {
+    *aExistingValue = aNewValue;
+  }
+
+  return aFlags;
+}
+
+#ifdef DEBUG
+
+static pref_initPhase gPhase = START;
+
+static bool gWatchingPref = false;
+
+void
+pref_SetInitPhase(pref_initPhase aPhase)
+{
+  gPhase = aPhase;
+}
+
+pref_initPhase
+pref_GetInitPhase()
+{
+  return gPhase;
+}
+
+void
+pref_SetWatchingPref(bool aWatching)
+{
+  gWatchingPref = aWatching;
+}
+
+struct StringComparator
+{
+  const char* mKey;
+  explicit StringComparator(const char* aKey)
+    : mKey(aKey)
+  {
+  }
+  int operator()(const char* aString) const { return strcmp(mKey, aString); }
+};
+
+bool
+InInitArray(const char* aKey)
+{
+  size_t prefsLen;
+  size_t found;
+  const char** list = mozilla::dom::ContentPrefs::GetContentPrefs(&prefsLen);
+  return BinarySearchIf(list, 0, prefsLen, StringComparator(aKey), &found);
+}
+
+class WatchingPrefRAII
+{
+public:
+  WatchingPrefRAII() { pref_SetWatchingPref(true); }
+  ~WatchingPrefRAII() { pref_SetWatchingPref(false); }
+};
+
+#define WATCHING_PREF_RAII() WatchingPrefRAII watchingPrefRAII
+
+#else // DEBUG
+
 #define WATCHING_PREF_RAII()
 
 #endif // DEBUG
 
+PrefHashEntry*
+pref_HashTableLookup(const char* aKey)
+{
+  MOZ_ASSERT(NS_IsMainThread() || mozilla::ServoStyleSet::IsInServoTraversal());
+  MOZ_ASSERT((!XRE_IsContentProcess() || gPhase != START),
+             "pref access before commandline prefs set");
+
+  // If you're hitting this assertion, you've added a pref access to start up.
+  // Consider moving it later or add it to the whitelist in ContentPrefs.cpp
+  // and get review from a DOM peer
+#ifdef DEBUG
+  if (XRE_IsContentProcess() && gPhase <= END_INIT_PREFS && !gWatchingPref &&
+      !InInitArray(aKey)) {
+    MOZ_CRASH_UNSAFE_PRINTF(
+      "accessing non-init pref %s before the rest of the prefs are sent", aKey);
+  }
+#endif
+
+  return static_cast<PrefHashEntry*>(gHashTable->Search(aKey));
+}
+
+nsresult
+pref_HashPref(const char* aKey,
+              PrefValue aValue,
+              PrefType aType,
+              uint32_t aFlags)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (!gHashTable) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  auto pref = static_cast<PrefHashEntry*>(gHashTable->Add(aKey, fallible));
+  if (!pref) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  // New entry, need to initialize.
+  if (!pref->mKey) {
+    // Initialize the pref entry.
+    pref->mPrefFlags.Reset().SetPrefType(aType);
+    pref->mKey = ArenaStrdup(aKey, gPrefNameArena);
+    memset(&pref->mDefaultPref, 0, sizeof(pref->mDefaultPref));
+    memset(&pref->mUserPref, 0, sizeof(pref->mUserPref));
+
+  } else if (pref->mPrefFlags.HasDefault() &&
+             !pref->mPrefFlags.IsPrefType(aType)) {
+    NS_WARNING(
+      nsPrintfCString(
+        "Trying to overwrite value of default pref %s with the wrong type!",
+        aKey)
+        .get());
+
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  bool valueChanged = false;
+  if (aFlags & kPrefSetDefault) {
+    if (!pref->mPrefFlags.IsLocked()) {
+      // ?? change of semantics?
+      if (pref_ValueChanged(pref->mDefaultPref, aValue, aType) ||
+          !pref->mPrefFlags.HasDefault()) {
+        pref->mPrefFlags =
+          pref_SetValue(&pref->mDefaultPref, pref->mPrefFlags, aValue, aType)
+            .SetHasDefault(true);
+        if (aFlags & kPrefStickyDefault) {
+          pref->mPrefFlags.SetHasStickyDefault(true);
+        }
+        if (!pref->mPrefFlags.HasUserValue()) {
+          valueChanged = true;
+        }
+      }
+      // What if we change the default to be the same as the user value?
+      // Should we clear the user value?
+    }
+  } else {
+    // If new value is same as the default value and it's not a "sticky" pref,
+    // then un-set the user value. Otherwise, set the user value only if it has
+    // changed.
+    if ((pref->mPrefFlags.HasDefault()) &&
+        !(pref->mPrefFlags.HasStickyDefault()) &&
+        !pref_ValueChanged(pref->mDefaultPref, aValue, aType) &&
+        !(aFlags & kPrefForceSet)) {
+      if (pref->mPrefFlags.HasUserValue()) {
+        // XXX should we free a user-set string value if there is one?
+        pref->mPrefFlags.SetHasUserValue(false);
+        if (!pref->mPrefFlags.IsLocked()) {
+          MakeDirtyCallback();
+          valueChanged = true;
+        }
+      }
+    } else if (!pref->mPrefFlags.HasUserValue() ||
+               !pref->mPrefFlags.IsPrefType(aType) ||
+               pref_ValueChanged(pref->mUserPref, aValue, aType)) {
+      pref->mPrefFlags =
+        pref_SetValue(&pref->mUserPref, pref->mPrefFlags, aValue, aType)
+          .SetHasUserValue(true);
+      if (!pref->mPrefFlags.IsLocked()) {
+        MakeDirtyCallback();
+        valueChanged = true;
+      }
+    }
+  }
+
+  if (valueChanged) {
+    return pref_DoCallback(aKey);
+  }
+
+  return NS_OK;
+}
+
+size_t
+pref_SizeOfPrivateData(MallocSizeOf aMallocSizeOf)
+{
+  size_t n = gPrefNameArena.SizeOfExcludingThis(aMallocSizeOf);
+  for (CallbackNode* node = gFirstCallback; node; node = node->mNext) {
+    n += aMallocSizeOf(node);
+    n += aMallocSizeOf(node->mDomain);
+  }
+  return n;
+}
+
+PrefType
+PREF_GetPrefType(const char* aPrefName)
+{
+  if (gHashTable) {
+    PrefHashEntry* pref = pref_HashTableLookup(aPrefName);
+    if (pref) {
+      return pref->mPrefFlags.GetPrefType();
+    }
+  }
+  return PrefType::Invalid;
+}
+
+bool
+PREF_PrefIsLocked(const char* aPrefName)
+{
+  bool result = false;
+  if (gIsAnyPrefLocked && gHashTable) {
+    PrefHashEntry* pref = pref_HashTableLookup(aPrefName);
+    if (pref && pref->mPrefFlags.IsLocked()) {
+      result = true;
+    }
+  }
+
+  return result;
+}
+
+// Adds a node to the beginning of the callback list.
+void
+PREF_RegisterPriorityCallback(const char* aPrefNode,
+                              PrefChangedFunc aCallback,
+                              void* aData)
+{
+  NS_PRECONDITION(aPrefNode, "aPrefNode must not be nullptr");
+  NS_PRECONDITION(aCallback, "aCallback must not be nullptr");
+
+  auto node = (CallbackNode*)malloc(sizeof(struct CallbackNode));
+  if (node) {
+    node->mDomain = PL_strdup(aPrefNode);
+    node->mFunc = aCallback;
+    node->mData = aData;
+    node->mNext = gFirstCallback;
+    gFirstCallback = node;
+    if (!gLastPriorityNode) {
+      gLastPriorityNode = node;
+    }
+  }
+}
+
+// Adds a node to the end of the callback list.
+void
+PREF_RegisterCallback(const char* aPrefNode,
+                      PrefChangedFunc aCallback,
+                      void* aData)
+{
+  NS_PRECONDITION(aPrefNode, "aPrefNode must not be nullptr");
+  NS_PRECONDITION(aCallback, "aCallback must not be nullptr");
+
+  auto node = (CallbackNode*)malloc(sizeof(struct CallbackNode));
+  if (node) {
+    node->mDomain = PL_strdup(aPrefNode);
+    node->mFunc = aCallback;
+    node->mData = aData;
+    if (gLastPriorityNode) {
+      node->mNext = gLastPriorityNode->mNext;
+      gLastPriorityNode->mNext = node;
+    } else {
+      node->mNext = gFirstCallback;
+      gFirstCallback = node;
+    }
+  }
+}
+
+// Removes |node| from callback list. Returns the node after the deleted one.
+CallbackNode*
+pref_RemoveCallbackNode(CallbackNode* aNode, CallbackNode* aPrevNode)
+{
+  NS_PRECONDITION(!aPrevNode || aPrevNode->mNext == aNode, "invalid params");
+  NS_PRECONDITION(aPrevNode || gFirstCallback == aNode, "invalid params");
+
+  NS_ASSERTION(
+    !gCallbacksInProgress,
+    "modifying the callback list while gCallbacksInProgress is true");
+
+  CallbackNode* next_node = aNode->mNext;
+  if (aPrevNode) {
+    aPrevNode->mNext = next_node;
+  } else {
+    gFirstCallback = next_node;
+  }
+  if (gLastPriorityNode == aNode) {
+    gLastPriorityNode = aPrevNode;
+  }
+  PL_strfree(aNode->mDomain);
+  free(aNode);
+  return next_node;
+}
+
+// Deletes a node from the callback list or marks it for deletion.
+nsresult
+PREF_UnregisterCallback(const char* aPrefNode,
+                        PrefChangedFunc aCallback,
+                        void* aData)
+{
+  nsresult rv = NS_ERROR_FAILURE;
+  CallbackNode* node = gFirstCallback;
+  CallbackNode* prev_node = nullptr;
+
+  while (node != nullptr) {
+    if (node->mFunc == aCallback && node->mData == aData &&
+        strcmp(node->mDomain, aPrefNode) == 0) {
+      if (gCallbacksInProgress) {
+        // postpone the node removal until after
+        // callbacks enumeration is finished.
+        node->mFunc = nullptr;
+        gShouldCleanupDeadNodes = true;
+        prev_node = node;
+        node = node->mNext;
+      } else {
+        node = pref_RemoveCallbackNode(node, prev_node);
+      }
+      rv = NS_OK;
+    } else {
+      prev_node = node;
+      node = node->mNext;
+    }
+  }
+  return rv;
+}
+
+static nsresult
+pref_DoCallback(const char* aChangedPref)
+{
+  nsresult rv = NS_OK;
+  CallbackNode* node;
+
+  bool reentered = gCallbacksInProgress;
+
+  // Nodes must not be deleted while gCallbacksInProgress is true.
+  // Nodes that need to be deleted are marked for deletion by nulling
+  // out the |func| pointer. We release them at the end of this function
+  // if we haven't reentered.
+  gCallbacksInProgress = true;
+
+  for (node = gFirstCallback; node != nullptr; node = node->mNext) {
+    if (node->mFunc &&
+        PL_strncmp(aChangedPref, node->mDomain, strlen(node->mDomain)) == 0) {
+      (*node->mFunc)(aChangedPref, node->mData);
+    }
+  }
+
+  gCallbacksInProgress = reentered;
+
+  if (gShouldCleanupDeadNodes && !gCallbacksInProgress) {
+    CallbackNode* prev_node = nullptr;
+    node = gFirstCallback;
+
+    while (node != nullptr) {
+      if (!node->mFunc) {
+        node = pref_RemoveCallbackNode(node, prev_node);
+      } else {
+        prev_node = node;
+        node = node->mNext;
+      }
+    }
+    gShouldCleanupDeadNodes = false;
+  }
+
+  return rv;
+}
+
+void
+PREF_ReaderCallback(void* aClosure,
+                    const char* aPref,
+                    PrefValue aValue,
+                    PrefType aType,
+                    bool aIsDefault,
+                    bool aIsStickyDefault)
+{
+  uint32_t flags = 0;
+  if (aIsDefault) {
+    flags |= kPrefSetDefault;
+    if (aIsStickyDefault) {
+      flags |= kPrefStickyDefault;
+    }
+  } else {
+    flags |= kPrefForceSet;
+  }
+  pref_HashPref(aPref, aValue, aType, flags);
+}
+
 //===========================================================================
 // Prefs parsing
 //===========================================================================
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
@@ -2186,16 +3565,17 @@ nsRelativeFilePref::GetRelativeToKey(nsA
 }
 
 NS_IMETHODIMP
 nsRelativeFilePref::SetRelativeToKey(const nsACString& aRelativeToKey)
 {
   mRelativeToKey.Assign(aRelativeToKey);
   return NS_OK;
 }
+
 //===========================================================================
 // Core prefs code
 //===========================================================================
 
 class PrefCallback;
 
 namespace mozilla {
 
--- a/modules/libpref/moz.build
+++ b/modules/libpref/moz.build
@@ -24,17 +24,16 @@ XPIDL_SOURCES += [
 
 XPIDL_MODULE = 'pref'
 
 EXPORTS.mozilla += [
     'Preferences.h',
 ]
 
 UNIFIED_SOURCES += [
-    'prefapi.cpp',
     'Preferences.cpp',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 DEFINES['OS_ARCH'] = CONFIG['OS_ARCH']
deleted file mode 100644
--- a/modules/libpref/prefapi.cpp
+++ /dev/null
@@ -1,1100 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* 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/. */
-
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "MainThreadUtils.h"
-#include "mozilla/ArenaAllocatorExtensions.h"
-#include "mozilla/ArenaAllocator.h"
-#include "mozilla/dom/ContentPrefs.h"
-#include "mozilla/dom/PContent.h"
-#include "mozilla/Logging.h"
-#include "mozilla/MemoryReporting.h"
-#include "mozilla/ServoStyleSet.h"
-#include "nsCRT.h"
-#include "nsPrintfCString.h"
-#include "nsQuickSort.h"
-#include "nsReadableUtils.h"
-#include "nsString.h"
-#include "plbase64.h"
-#include "PLDHashTable.h"
-#include "plstr.h"
-#include "prefapi.h"
-#include "prefapi_private_data.h"
-#include "prlink.h"
-
-#ifdef _WIN32
-#include "windows.h"
-#endif
-
-using namespace mozilla;
-
-static void
-ClearPrefEntry(PLDHashTable* aTable, PLDHashEntryHdr* aEntry)
-{
-  auto pref = static_cast<PrefHashEntry*>(aEntry);
-  if (pref->mPrefFlags.IsTypeString()) {
-    if (pref->mDefaultPref.mStringVal) {
-      PL_strfree(pref->mDefaultPref.mStringVal);
-    }
-    if (pref->mUserPref.mStringVal) {
-      PL_strfree(pref->mUserPref.mStringVal);
-    }
-  }
-
-  // Don't need to free this because it's allocated in memory owned by
-  // gPrefNameArena.
-  pref->mKey = nullptr;
-  memset(aEntry, 0, aTable->EntrySize());
-}
-
-static bool
-MatchPrefEntry(const PLDHashEntryHdr* aEntry, const void* aKey)
-{
-  auto prefEntry = static_cast<const PrefHashEntry*>(aEntry);
-
-  if (prefEntry->mKey == aKey) {
-    return true;
-  }
-
-  if (!prefEntry->mKey || !aKey) {
-    return false;
-  }
-
-  auto otherKey = static_cast<const char*>(aKey);
-  return (strcmp(prefEntry->mKey, otherKey) == 0);
-}
-
-struct CallbackNode
-{
-  char* mDomain;
-
-  // If someone attempts to remove the node from the callback list while
-  // pref_DoCallback is running, |func| is set to nullptr. Such nodes will
-  // be removed at the end of pref_DoCallback.
-  PrefChangedFunc mFunc;
-  void* mData;
-  CallbackNode* mNext;
-};
-
-PLDHashTable* gHashTable;
-
-static ArenaAllocator<8192, 4> gPrefNameArena;
-
-static CallbackNode* gFirstCallback = nullptr;
-static CallbackNode* gLastPriorityNode = nullptr;
-
-static bool gIsAnyPrefLocked = false;
-
-// These are only used during the call to pref_DoCallback.
-static bool gCallbacksInProgress = false;
-static bool gShouldCleanupDeadNodes = false;
-
-static PLDHashTableOps pref_HashTableOps = {
-  PLDHashTable::HashStringKey,
-  MatchPrefEntry,
-  PLDHashTable::MoveEntryStub,
-  ClearPrefEntry,
-  nullptr,
-};
-
-// PR_ALIGN_OF_WORD is only defined on some platforms. ALIGN_OF_WORD has
-// already been defined to PR_ALIGN_OF_WORD everywhere.
-#ifndef PR_ALIGN_OF_WORD
-#define PR_ALIGN_OF_WORD PR_ALIGN_OF_POINTER
-#endif
-
-#define WORD_ALIGN_MASK (PR_ALIGN_OF_WORD - 1)
-
-// Sanity checking.
-#if (PR_ALIGN_OF_WORD & WORD_ALIGN_MASK) != 0
-#error "PR_ALIGN_OF_WORD must be a power of 2!"
-#endif
-
-static PrefsDirtyFunc gDirtyCallback = nullptr;
-
-inline void
-MakeDirtyCallback()
-{
-  // Right now the callback function is always set, so we don't need
-  // to complicate the code to cover the scenario where we set the callback
-  // after we've already tried to make it dirty.  If this assert triggers
-  // we will add that code.
-  MOZ_ASSERT(gDirtyCallback);
-  if (gDirtyCallback) {
-    gDirtyCallback();
-  }
-}
-
-void
-PREF_SetDirtyCallback(PrefsDirtyFunc aFunc)
-{
-  gDirtyCallback = aFunc;
-}
-
-//---------------------------------------------------------------------------
-
-static bool
-pref_ValueChanged(PrefValue aOldValue, PrefValue aNewValue, PrefType aType);
-
-static nsresult
-pref_DoCallback(const char* aChangedPref);
-
-enum
-{
-  kPrefSetDefault = 1,
-  kPrefForceSet = 2,
-  kPrefStickyDefault = 4,
-};
-
-static nsresult
-pref_HashPref(const char* aKey,
-              PrefValue aValue,
-              PrefType aType,
-              uint32_t aFlags);
-
-#define PREF_HASHTABLE_INITIAL_LENGTH 1024
-
-void
-PREF_Init()
-{
-  if (!gHashTable) {
-    gHashTable = new PLDHashTable(
-      &pref_HashTableOps, sizeof(PrefHashEntry), PREF_HASHTABLE_INITIAL_LENGTH);
-  }
-}
-
-// Frees the callback list.
-void
-PREF_Cleanup()
-{
-  NS_ASSERTION(!gCallbacksInProgress,
-               "PREF_Cleanup was called while gCallbacksInProgress is true!");
-
-  CallbackNode* node = gFirstCallback;
-  CallbackNode* next_node;
-
-  while (node) {
-    next_node = node->mNext;
-    PL_strfree(node->mDomain);
-    free(node);
-    node = next_node;
-  }
-  gLastPriorityNode = gFirstCallback = nullptr;
-
-  PREF_CleanupPrefs();
-}
-
-// Frees up all the objects except the callback list.
-void
-PREF_CleanupPrefs()
-{
-  if (gHashTable) {
-    delete gHashTable;
-    gHashTable = nullptr;
-    gPrefNameArena.Clear();
-  }
-}
-
-// Note that this appends to aResult, and does not assign!
-static void
-StrEscape(const char* aOriginal, nsCString& aResult)
-{
-  // JavaScript does not allow quotes, slashes, or line terminators inside
-  // strings so we must escape them. ECMAScript defines four line terminators,
-  // but we're only worrying about \r and \n here.  We currently feed our pref
-  // script to the JS interpreter as Latin-1 so  we won't encounter \u2028
-  // (line separator) or \u2029 (paragraph separator).
-  //
-  // WARNING: There are hints that we may be moving to storing prefs as utf8.
-  // If we ever feed them to the JS compiler as UTF8 then we'll have to worry
-  // about the multibyte sequences that would be interpreted as \u2028 and
-  // \u2029.
-  const char* p;
-
-  if (aOriginal == nullptr) {
-    return;
-  }
-
-  // Paranoid worst case all slashes will free quickly.
-  for (p = aOriginal; *p; ++p) {
-    switch (*p) {
-      case '\n':
-        aResult.AppendLiteral("\\n");
-        break;
-
-      case '\r':
-        aResult.AppendLiteral("\\r");
-        break;
-
-      case '\\':
-        aResult.AppendLiteral("\\\\");
-        break;
-
-      case '\"':
-        aResult.AppendLiteral("\\\"");
-        break;
-
-      default:
-        aResult.Append(*p);
-        break;
-    }
-  }
-}
-
-//
-// External calls
-//
-
-nsresult
-PREF_SetCharPref(const char* aPrefName, const char* aValue, bool aSetDefault)
-{
-  if (strlen(aValue) > MAX_PREF_LENGTH) {
-    return NS_ERROR_ILLEGAL_VALUE;
-  }
-
-  PrefValue pref;
-  pref.mStringVal = const_cast<char*>(aValue);
-
-  return pref_HashPref(
-    aPrefName, pref, PrefType::String, aSetDefault ? kPrefSetDefault : 0);
-}
-
-nsresult
-PREF_SetIntPref(const char* aPrefName, int32_t aValue, bool aSetDefault)
-{
-  PrefValue pref;
-  pref.mIntVal = aValue;
-
-  return pref_HashPref(
-    aPrefName, pref, PrefType::Int, aSetDefault ? kPrefSetDefault : 0);
-}
-
-nsresult
-PREF_SetBoolPref(const char* aPrefName, bool aValue, bool aSetDefault)
-{
-  PrefValue pref;
-  pref.mBoolVal = aValue;
-
-  return pref_HashPref(
-    aPrefName, pref, PrefType::Bool, aSetDefault ? kPrefSetDefault : 0);
-}
-
-enum WhichValue
-{
-  DEFAULT_VALUE,
-  USER_VALUE
-};
-
-static nsresult
-SetPrefValue(const char* aPrefName,
-             const dom::PrefValue& aValue,
-             WhichValue aWhich)
-{
-  bool setDefault = (aWhich == DEFAULT_VALUE);
-
-  switch (aValue.type()) {
-    case dom::PrefValue::TnsCString:
-      return PREF_SetCharPref(
-        aPrefName, aValue.get_nsCString().get(), setDefault);
-
-    case dom::PrefValue::Tint32_t:
-      return PREF_SetIntPref(aPrefName, aValue.get_int32_t(), setDefault);
-
-    case dom::PrefValue::Tbool:
-      return PREF_SetBoolPref(aPrefName, aValue.get_bool(), setDefault);
-
-    default:
-      MOZ_CRASH();
-  }
-}
-
-nsresult
-pref_SetPref(const dom::PrefSetting& aPref)
-{
-  const char* prefName = aPref.name().get();
-  const dom::MaybePrefValue& defaultValue = aPref.defaultValue();
-  const dom::MaybePrefValue& userValue = aPref.userValue();
-
-  nsresult rv;
-  if (defaultValue.type() == dom::MaybePrefValue::TPrefValue) {
-    rv = SetPrefValue(prefName, defaultValue.get_PrefValue(), DEFAULT_VALUE);
-    if (NS_FAILED(rv)) {
-      return rv;
-    }
-  }
-
-  if (userValue.type() == dom::MaybePrefValue::TPrefValue) {
-    rv = SetPrefValue(prefName, userValue.get_PrefValue(), USER_VALUE);
-  } else {
-    rv = PREF_ClearUserPref(prefName);
-  }
-
-  // NB: we should never try to clear a default value, that doesn't
-  // make sense
-
-  return rv;
-}
-
-PrefSaveData
-pref_savePrefs(PLDHashTable* aTable)
-{
-  PrefSaveData savedPrefs(aTable->EntryCount());
-
-  for (auto iter = aTable->Iter(); !iter.Done(); iter.Next()) {
-    auto pref = static_cast<PrefHashEntry*>(iter.Get());
-
-    nsAutoCString prefValue;
-    nsAutoCString prefPrefix;
-    prefPrefix.AssignLiteral("user_pref(\"");
-
-    // where we're getting our pref from
-    PrefValue* sourcePref;
-
-    if (pref->mPrefFlags.HasUserValue() &&
-        (pref_ValueChanged(pref->mDefaultPref,
-                           pref->mUserPref,
-                           pref->mPrefFlags.GetPrefType()) ||
-         !pref->mPrefFlags.HasDefault() ||
-         pref->mPrefFlags.HasStickyDefault())) {
-      sourcePref = &pref->mUserPref;
-    } else {
-      // do not save default prefs that haven't changed
-      continue;
-    }
-
-    // strings are in quotes!
-    if (pref->mPrefFlags.IsTypeString()) {
-      prefValue = '\"';
-      StrEscape(sourcePref->mStringVal, prefValue);
-      prefValue += '\"';
-
-    } else if (pref->mPrefFlags.IsTypeInt()) {
-      prefValue.AppendInt(sourcePref->mIntVal);
-
-    } else if (pref->mPrefFlags.IsTypeBool()) {
-      prefValue = (sourcePref->mBoolVal) ? "true" : "false";
-    }
-
-    nsAutoCString prefName;
-    StrEscape(pref->mKey, prefName);
-
-    savedPrefs.AppendElement()->reset(
-      ToNewCString(prefPrefix + prefName + NS_LITERAL_CSTRING("\", ") +
-                   prefValue + NS_LITERAL_CSTRING(");")));
-  }
-
-  return savedPrefs;
-}
-
-bool
-pref_EntryHasAdvisablySizedValues(PrefHashEntry* aHashEntry)
-{
-  if (aHashEntry->mPrefFlags.GetPrefType() != PrefType::String) {
-    return true;
-  }
-
-  char* stringVal;
-  if (aHashEntry->mPrefFlags.HasDefault()) {
-    stringVal = aHashEntry->mDefaultPref.mStringVal;
-    if (strlen(stringVal) > MAX_ADVISABLE_PREF_LENGTH) {
-      return false;
-    }
-  }
-
-  if (aHashEntry->mPrefFlags.HasUserValue()) {
-    stringVal = aHashEntry->mUserPref.mStringVal;
-    if (strlen(stringVal) > MAX_ADVISABLE_PREF_LENGTH) {
-      return false;
-    }
-  }
-
-  return true;
-}
-
-static void
-GetPrefValueFromEntry(PrefHashEntry* aHashEntry,
-                      dom::PrefSetting* aPref,
-                      WhichValue aWhich)
-{
-  PrefValue* value;
-  dom::PrefValue* settingValue;
-  if (aWhich == USER_VALUE) {
-    value = &aHashEntry->mUserPref;
-    aPref->userValue() = dom::PrefValue();
-    settingValue = &aPref->userValue().get_PrefValue();
-  } else {
-    value = &aHashEntry->mDefaultPref;
-    aPref->defaultValue() = dom::PrefValue();
-    settingValue = &aPref->defaultValue().get_PrefValue();
-  }
-
-  switch (aHashEntry->mPrefFlags.GetPrefType()) {
-    case PrefType::String:
-      *settingValue = nsDependentCString(value->mStringVal);
-      return;
-    case PrefType::Int:
-      *settingValue = value->mIntVal;
-      return;
-    case PrefType::Bool:
-      *settingValue = !!value->mBoolVal;
-      return;
-    default:
-      MOZ_CRASH();
-  }
-}
-
-void
-pref_GetPrefFromEntry(PrefHashEntry* aHashEntry, dom::PrefSetting* aPref)
-{
-  aPref->name() = aHashEntry->mKey;
-
-  if (aHashEntry->mPrefFlags.HasDefault()) {
-    GetPrefValueFromEntry(aHashEntry, aPref, DEFAULT_VALUE);
-  } else {
-    aPref->defaultValue() = null_t();
-  }
-
-  if (aHashEntry->mPrefFlags.HasUserValue()) {
-    GetPrefValueFromEntry(aHashEntry, aPref, USER_VALUE);
-  } else {
-    aPref->userValue() = null_t();
-  }
-
-  MOZ_ASSERT(aPref->defaultValue().type() == dom::MaybePrefValue::Tnull_t ||
-             aPref->userValue().type() == dom::MaybePrefValue::Tnull_t ||
-             (aPref->defaultValue().get_PrefValue().type() ==
-              aPref->userValue().get_PrefValue().type()));
-}
-
-bool
-PREF_HasUserPref(const char* aPrefName)
-{
-  if (!gHashTable) {
-    return false;
-  }
-
-  PrefHashEntry* pref = pref_HashTableLookup(aPrefName);
-  return pref && pref->mPrefFlags.HasUserValue();
-}
-
-nsresult
-PREF_CopyCharPref(const char* aPrefName, char** aValueOut, bool aGetDefault)
-{
-  if (!gHashTable) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
-  nsresult rv = NS_ERROR_UNEXPECTED;
-  char* stringVal;
-  PrefHashEntry* pref = pref_HashTableLookup(aPrefName);
-
-  if (pref && pref->mPrefFlags.IsTypeString()) {
-    if (aGetDefault || pref->mPrefFlags.IsLocked() ||
-        !pref->mPrefFlags.HasUserValue()) {
-      stringVal = pref->mDefaultPref.mStringVal;
-    } else {
-      stringVal = pref->mUserPref.mStringVal;
-    }
-
-    if (stringVal) {
-      *aValueOut = NS_strdup(stringVal);
-      rv = NS_OK;
-    }
-  }
-
-  return rv;
-}
-
-nsresult
-PREF_GetIntPref(const char* aPrefName, int32_t* aValueOut, bool aGetDefault)
-{
-  if (!gHashTable) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
-  nsresult rv = NS_ERROR_UNEXPECTED;
-  PrefHashEntry* pref = pref_HashTableLookup(aPrefName);
-  if (pref && pref->mPrefFlags.IsTypeInt()) {
-    if (aGetDefault || pref->mPrefFlags.IsLocked() ||
-        !pref->mPrefFlags.HasUserValue()) {
-      int32_t tempInt = pref->mDefaultPref.mIntVal;
-
-      // Check to see if we even had a default.
-      if (!pref->mPrefFlags.HasDefault()) {
-        return NS_ERROR_UNEXPECTED;
-      }
-      *aValueOut = tempInt;
-    } else {
-      *aValueOut = pref->mUserPref.mIntVal;
-    }
-    rv = NS_OK;
-  }
-
-  return rv;
-}
-
-nsresult
-PREF_GetBoolPref(const char* aPrefName, bool* aValueOut, bool aGetDefault)
-{
-  if (!gHashTable) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
-  nsresult rv = NS_ERROR_UNEXPECTED;
-  PrefHashEntry* pref = pref_HashTableLookup(aPrefName);
-  //NS_ASSERTION(pref, aPrefName);
-  if (pref && pref->mPrefFlags.IsTypeBool()) {
-    if (aGetDefault || pref->mPrefFlags.IsLocked() ||
-        !pref->mPrefFlags.HasUserValue()) {
-      bool tempBool = pref->mDefaultPref.mBoolVal;
-
-      // Check to see if we even had a default.
-      if (pref->mPrefFlags.HasDefault()) {
-        *aValueOut = tempBool;
-        rv = NS_OK;
-      }
-    } else {
-      *aValueOut = pref->mUserPref.mBoolVal;
-      rv = NS_OK;
-    }
-  }
-
-  return rv;
-}
-
-nsresult
-PREF_DeleteBranch(const char* aBranchName)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  size_t len = strlen(aBranchName);
-
-  if (!gHashTable) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
-  // The following check insures that if the branch name already has a "." at
-  // the end, we don't end up with a "..". This fixes an incompatibility
-  // between nsIPref, which needs the period added, and nsIPrefBranch which
-  // does not. When nsIPref goes away this function should be fixed to never
-  // add the period at all.
-  nsAutoCString branch_dot(aBranchName);
-  if (len > 1 && aBranchName[len - 1] != '.') {
-    branch_dot += '.';
-  }
-
-  // Delete a branch. Used for deleting mime types.
-  const char* to_delete = branch_dot.get();
-  MOZ_ASSERT(to_delete);
-  len = strlen(to_delete);
-  for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
-    auto entry = static_cast<PrefHashEntry*>(iter.Get());
-
-    // Note: if we're deleting "ldap" then we want to delete "ldap.xxx" and
-    // "ldap" (if such a leaf node exists) but not "ldap_1.xxx".
-    if (PL_strncmp(entry->mKey, to_delete, len) == 0 ||
-        (len - 1 == strlen(entry->mKey) &&
-         PL_strncmp(entry->mKey, to_delete, len - 1) == 0)) {
-      iter.Remove();
-    }
-  }
-
-  MakeDirtyCallback();
-  return NS_OK;
-}
-
-nsresult
-PREF_ClearUserPref(const char* aPrefName)
-{
-  if (!gHashTable) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
-  PrefHashEntry* pref = pref_HashTableLookup(aPrefName);
-  if (pref && pref->mPrefFlags.HasUserValue()) {
-    pref->mPrefFlags.SetHasUserValue(false);
-
-    if (!pref->mPrefFlags.HasDefault()) {
-      gHashTable->RemoveEntry(pref);
-    }
-
-    pref_DoCallback(aPrefName);
-    MakeDirtyCallback();
-  }
-  return NS_OK;
-}
-
-nsresult
-PREF_ClearAllUserPrefs()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  if (!gHashTable) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
-  std::vector<std::string> prefStrings;
-  for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
-    auto pref = static_cast<PrefHashEntry*>(iter.Get());
-
-    if (pref->mPrefFlags.HasUserValue()) {
-      prefStrings.push_back(std::string(pref->mKey));
-
-      pref->mPrefFlags.SetHasUserValue(false);
-      if (!pref->mPrefFlags.HasDefault()) {
-        iter.Remove();
-      }
-    }
-  }
-
-  for (std::string& prefString : prefStrings) {
-    pref_DoCallback(prefString.c_str());
-  }
-
-  MakeDirtyCallback();
-  return NS_OK;
-}
-
-nsresult
-PREF_LockPref(const char* aKey, bool aLockIt)
-{
-  if (!gHashTable) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
-  PrefHashEntry* pref = pref_HashTableLookup(aKey);
-  if (!pref) {
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  if (aLockIt) {
-    if (!pref->mPrefFlags.IsLocked()) {
-      pref->mPrefFlags.SetLocked(true);
-      gIsAnyPrefLocked = true;
-      pref_DoCallback(aKey);
-    }
-  } else if (pref->mPrefFlags.IsLocked()) {
-    pref->mPrefFlags.SetLocked(false);
-    pref_DoCallback(aKey);
-  }
-
-  return NS_OK;
-}
-
-//
-// Hash table functions
-//
-
-static bool
-pref_ValueChanged(PrefValue aOldValue, PrefValue aNewValue, PrefType aType)
-{
-  bool changed = true;
-  switch (aType) {
-    case PrefType::String:
-      if (aOldValue.mStringVal && aNewValue.mStringVal) {
-        changed = (strcmp(aOldValue.mStringVal, aNewValue.mStringVal) != 0);
-      }
-      break;
-
-    case PrefType::Int:
-      changed = aOldValue.mIntVal != aNewValue.mIntVal;
-      break;
-
-    case PrefType::Bool:
-      changed = aOldValue.mBoolVal != aNewValue.mBoolVal;
-      break;
-
-    case PrefType::Invalid:
-    default:
-      changed = false;
-      break;
-  }
-
-  return changed;
-}
-
-// Overwrite the type and value of an existing preference. Caller must ensure
-// that they are not changing the type of a preference that has a default
-// value.
-static PrefTypeFlags
-pref_SetValue(PrefValue* aExistingValue,
-              PrefTypeFlags aFlags,
-              PrefValue aNewValue,
-              PrefType aNewType)
-{
-  if (aFlags.IsTypeString() && aExistingValue->mStringVal) {
-    PL_strfree(aExistingValue->mStringVal);
-  }
-
-  aFlags.SetPrefType(aNewType);
-  if (aFlags.IsTypeString()) {
-    MOZ_ASSERT(aNewValue.mStringVal);
-    aExistingValue->mStringVal =
-      aNewValue.mStringVal ? PL_strdup(aNewValue.mStringVal) : nullptr;
-  } else {
-    *aExistingValue = aNewValue;
-  }
-
-  return aFlags;
-}
-
-#ifdef DEBUG
-static pref_initPhase gPhase = START;
-
-static bool gWatchingPref = false;
-
-void
-pref_SetInitPhase(pref_initPhase aPhase)
-{
-  gPhase = aPhase;
-}
-
-pref_initPhase
-pref_GetInitPhase()
-{
-  return gPhase;
-}
-
-void
-pref_SetWatchingPref(bool aWatching)
-{
-  gWatchingPref = aWatching;
-}
-
-struct StringComparator
-{
-  const char* mKey;
-  explicit StringComparator(const char* aKey)
-    : mKey(aKey)
-  {
-  }
-  int operator()(const char* aString) const { return strcmp(mKey, aString); }
-};
-
-bool
-InInitArray(const char* aKey)
-{
-  size_t prefsLen;
-  size_t found;
-  const char** list = mozilla::dom::ContentPrefs::GetContentPrefs(&prefsLen);
-  return BinarySearchIf(list, 0, prefsLen, StringComparator(aKey), &found);
-}
-#endif
-
-PrefHashEntry*
-pref_HashTableLookup(const char* aKey)
-{
-  MOZ_ASSERT(NS_IsMainThread() || mozilla::ServoStyleSet::IsInServoTraversal());
-  MOZ_ASSERT((!XRE_IsContentProcess() || gPhase != START),
-             "pref access before commandline prefs set");
-
-  // If you're hitting this assertion, you've added a pref access to start up.
-  // Consider moving it later or add it to the whitelist in ContentPrefs.cpp
-  // and get review from a DOM peer
-#ifdef DEBUG
-  if (XRE_IsContentProcess() && gPhase <= END_INIT_PREFS && !gWatchingPref &&
-      !InInitArray(aKey)) {
-    MOZ_CRASH_UNSAFE_PRINTF(
-      "accessing non-init pref %s before the rest of the prefs are sent", aKey);
-  }
-#endif
-
-  return static_cast<PrefHashEntry*>(gHashTable->Search(aKey));
-}
-
-nsresult
-pref_HashPref(const char* aKey,
-              PrefValue aValue,
-              PrefType aType,
-              uint32_t aFlags)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  if (!gHashTable) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
-  auto pref = static_cast<PrefHashEntry*>(gHashTable->Add(aKey, fallible));
-  if (!pref) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
-  // New entry, need to initialize.
-  if (!pref->mKey) {
-    // Initialize the pref entry.
-    pref->mPrefFlags.Reset().SetPrefType(aType);
-    pref->mKey = ArenaStrdup(aKey, gPrefNameArena);
-    memset(&pref->mDefaultPref, 0, sizeof(pref->mDefaultPref));
-    memset(&pref->mUserPref, 0, sizeof(pref->mUserPref));
-
-  } else if (pref->mPrefFlags.HasDefault() &&
-             !pref->mPrefFlags.IsPrefType(aType)) {
-    NS_WARNING(
-      nsPrintfCString(
-        "Trying to overwrite value of default pref %s with the wrong type!",
-        aKey)
-        .get());
-
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  bool valueChanged = false;
-  if (aFlags & kPrefSetDefault) {
-    if (!pref->mPrefFlags.IsLocked()) {
-      // ?? change of semantics?
-      if (pref_ValueChanged(pref->mDefaultPref, aValue, aType) ||
-          !pref->mPrefFlags.HasDefault()) {
-        pref->mPrefFlags =
-          pref_SetValue(&pref->mDefaultPref, pref->mPrefFlags, aValue, aType)
-            .SetHasDefault(true);
-        if (aFlags & kPrefStickyDefault) {
-          pref->mPrefFlags.SetHasStickyDefault(true);
-        }
-        if (!pref->mPrefFlags.HasUserValue()) {
-          valueChanged = true;
-        }
-      }
-      // What if we change the default to be the same as the user value?
-      // Should we clear the user value?
-    }
-  } else {
-    // If new value is same as the default value and it's not a "sticky" pref,
-    // then un-set the user value. Otherwise, set the user value only if it has
-    // changed.
-    if ((pref->mPrefFlags.HasDefault()) &&
-        !(pref->mPrefFlags.HasStickyDefault()) &&
-        !pref_ValueChanged(pref->mDefaultPref, aValue, aType) &&
-        !(aFlags & kPrefForceSet)) {
-      if (pref->mPrefFlags.HasUserValue()) {
-        // XXX should we free a user-set string value if there is one?
-        pref->mPrefFlags.SetHasUserValue(false);
-        if (!pref->mPrefFlags.IsLocked()) {
-          MakeDirtyCallback();
-          valueChanged = true;
-        }
-      }
-    } else if (!pref->mPrefFlags.HasUserValue() ||
-               !pref->mPrefFlags.IsPrefType(aType) ||
-               pref_ValueChanged(pref->mUserPref, aValue, aType)) {
-      pref->mPrefFlags =
-        pref_SetValue(&pref->mUserPref, pref->mPrefFlags, aValue, aType)
-          .SetHasUserValue(true);
-      if (!pref->mPrefFlags.IsLocked()) {
-        MakeDirtyCallback();
-        valueChanged = true;
-      }
-    }
-  }
-
-  if (valueChanged) {
-    return pref_DoCallback(aKey);
-  }
-
-  return NS_OK;
-}
-
-size_t
-pref_SizeOfPrivateData(MallocSizeOf aMallocSizeOf)
-{
-  size_t n = gPrefNameArena.SizeOfExcludingThis(aMallocSizeOf);
-  for (CallbackNode* node = gFirstCallback; node; node = node->mNext) {
-    n += aMallocSizeOf(node);
-    n += aMallocSizeOf(node->mDomain);
-  }
-  return n;
-}
-
-PrefType
-PREF_GetPrefType(const char* aPrefName)
-{
-  if (gHashTable) {
-    PrefHashEntry* pref = pref_HashTableLookup(aPrefName);
-    if (pref) {
-      return pref->mPrefFlags.GetPrefType();
-    }
-  }
-  return PrefType::Invalid;
-}
-
-bool
-PREF_PrefIsLocked(const char* aPrefName)
-{
-  bool result = false;
-  if (gIsAnyPrefLocked && gHashTable) {
-    PrefHashEntry* pref = pref_HashTableLookup(aPrefName);
-    if (pref && pref->mPrefFlags.IsLocked()) {
-      result = true;
-    }
-  }
-
-  return result;
-}
-
-// Adds a node to the beginning of the callback list.
-void
-PREF_RegisterPriorityCallback(const char* aPrefNode,
-                              PrefChangedFunc aCallback,
-                              void* aData)
-{
-  NS_PRECONDITION(aPrefNode, "aPrefNode must not be nullptr");
-  NS_PRECONDITION(aCallback, "aCallback must not be nullptr");
-
-  auto node = (CallbackNode*)malloc(sizeof(struct CallbackNode));
-  if (node) {
-    node->mDomain = PL_strdup(aPrefNode);
-    node->mFunc = aCallback;
-    node->mData = aData;
-    node->mNext = gFirstCallback;
-    gFirstCallback = node;
-    if (!gLastPriorityNode) {
-      gLastPriorityNode = node;
-    }
-  }
-}
-
-// Adds a node to the end of the callback list.
-void
-PREF_RegisterCallback(const char* aPrefNode,
-                      PrefChangedFunc aCallback,
-                      void* aData)
-{
-  NS_PRECONDITION(aPrefNode, "aPrefNode must not be nullptr");
-  NS_PRECONDITION(aCallback, "aCallback must not be nullptr");
-
-  auto node = (CallbackNode*)malloc(sizeof(struct CallbackNode));
-  if (node) {
-    node->mDomain = PL_strdup(aPrefNode);
-    node->mFunc = aCallback;
-    node->mData = aData;
-    if (gLastPriorityNode) {
-      node->mNext = gLastPriorityNode->mNext;
-      gLastPriorityNode->mNext = node;
-    } else {
-      node->mNext = gFirstCallback;
-      gFirstCallback = node;
-    }
-  }
-}
-
-// Removes |node| from callback list. Returns the node after the deleted one.
-CallbackNode*
-pref_RemoveCallbackNode(CallbackNode* aNode, CallbackNode* aPrevNode)
-{
-  NS_PRECONDITION(!aPrevNode || aPrevNode->mNext == aNode, "invalid params");
-  NS_PRECONDITION(aPrevNode || gFirstCallback == aNode, "invalid params");
-
-  NS_ASSERTION(
-    !gCallbacksInProgress,
-    "modifying the callback list while gCallbacksInProgress is true");
-
-  CallbackNode* next_node = aNode->mNext;
-  if (aPrevNode) {
-    aPrevNode->mNext = next_node;
-  } else {
-    gFirstCallback = next_node;
-  }
-  if (gLastPriorityNode == aNode) {
-    gLastPriorityNode = aPrevNode;
-  }
-  PL_strfree(aNode->mDomain);
-  free(aNode);
-  return next_node;
-}
-
-// Deletes a node from the callback list or marks it for deletion.
-nsresult
-PREF_UnregisterCallback(const char* aPrefNode,
-                        PrefChangedFunc aCallback,
-                        void* aData)
-{
-  nsresult rv = NS_ERROR_FAILURE;
-  CallbackNode* node = gFirstCallback;
-  CallbackNode* prev_node = nullptr;
-
-  while (node != nullptr) {
-    if (node->mFunc == aCallback && node->mData == aData &&
-        strcmp(node->mDomain, aPrefNode) == 0) {
-      if (gCallbacksInProgress) {
-        // postpone the node removal until after
-        // callbacks enumeration is finished.
-        node->mFunc = nullptr;
-        gShouldCleanupDeadNodes = true;
-        prev_node = node;
-        node = node->mNext;
-      } else {
-        node = pref_RemoveCallbackNode(node, prev_node);
-      }
-      rv = NS_OK;
-    } else {
-      prev_node = node;
-      node = node->mNext;
-    }
-  }
-  return rv;
-}
-
-static nsresult
-pref_DoCallback(const char* aChangedPref)
-{
-  nsresult rv = NS_OK;
-  CallbackNode* node;
-
-  bool reentered = gCallbacksInProgress;
-
-  // Nodes must not be deleted while gCallbacksInProgress is true.
-  // Nodes that need to be deleted are marked for deletion by nulling
-  // out the |func| pointer. We release them at the end of this function
-  // if we haven't reentered.
-  gCallbacksInProgress = true;
-
-  for (node = gFirstCallback; node != nullptr; node = node->mNext) {
-    if (node->mFunc &&
-        PL_strncmp(aChangedPref, node->mDomain, strlen(node->mDomain)) == 0) {
-      (*node->mFunc)(aChangedPref, node->mData);
-    }
-  }
-
-  gCallbacksInProgress = reentered;
-
-  if (gShouldCleanupDeadNodes && !gCallbacksInProgress) {
-    CallbackNode* prev_node = nullptr;
-    node = gFirstCallback;
-
-    while (node != nullptr) {
-      if (!node->mFunc) {
-        node = pref_RemoveCallbackNode(node, prev_node);
-      } else {
-        prev_node = node;
-        node = node->mNext;
-      }
-    }
-    gShouldCleanupDeadNodes = false;
-  }
-
-  return rv;
-}
-
-void
-PREF_ReaderCallback(void* aClosure,
-                    const char* aPref,
-                    PrefValue aValue,
-                    PrefType aType,
-                    bool aIsDefault,
-                    bool aIsStickyDefault)
-{
-  uint32_t flags = 0;
-  if (aIsDefault) {
-    flags |= kPrefSetDefault;
-    if (aIsStickyDefault) {
-      flags |= kPrefStickyDefault;
-    }
-  } else {
-    flags |= kPrefForceSet;
-  }
-  pref_HashPref(aPref, aValue, aType, flags);
-}
deleted file mode 100644
--- a/modules/libpref/prefapi.h
+++ /dev/null
@@ -1,264 +0,0 @@
-/* -*- 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 prefapi_h
-#define prefapi_h
-
-#include "nscore.h"
-#include "PLDHashTable.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// 1 MB should be enough for everyone.
-static const uint32_t MAX_PREF_LENGTH = 1 * 1024 * 1024;
-// Actually, 4kb should be enough for everyone.
-static const uint32_t MAX_ADVISABLE_PREF_LENGTH = 4 * 1024;
-
-typedef union {
-  char* mStringVal;
-  int32_t mIntVal;
-  bool mBoolVal;
-} PrefValue;
-
-// The Init function initializes the preference context and creates the
-// preference hashtable.
-void
-PREF_Init();
-
-// Cleanup should be called at program exit to free the list of registered
-// callbacks.
-void
-PREF_Cleanup();
-void
-PREF_CleanupPrefs();
-
-// Preference flags, including the native type of the preference. Changing any
-// of these values will require modifying the code inside of PrefTypeFlags
-// class.
-enum class PrefType
-{
-  Invalid = 0,
-  String = 1,
-  Int = 2,
-  Bool = 3,
-};
-
-// Keep the type of the preference, as well as the flags guiding its behaviour.
-class PrefTypeFlags
-{
-public:
-  PrefTypeFlags()
-    : mValue(AsInt(PrefType::Invalid))
-  {
-  }
-
-  explicit PrefTypeFlags(PrefType aType)
-    : mValue(AsInt(aType))
-  {
-  }
-
-  PrefTypeFlags& Reset()
-  {
-    mValue = AsInt(PrefType::Invalid);
-    return *this;
-  }
-
-  bool IsTypeValid() const { return !IsPrefType(PrefType::Invalid); }
-  bool IsTypeString() const { return IsPrefType(PrefType::String); }
-  bool IsTypeInt() const { return IsPrefType(PrefType::Int); }
-  bool IsTypeBool() const { return IsPrefType(PrefType::Bool); }
-  bool IsPrefType(PrefType type) const { return GetPrefType() == type; }
-
-  PrefTypeFlags& SetPrefType(PrefType aType)
-  {
-    mValue = mValue - AsInt(GetPrefType()) + AsInt(aType);
-    return *this;
-  }
-
-  PrefType GetPrefType() const
-  {
-    return (PrefType)(mValue & (AsInt(PrefType::String) | AsInt(PrefType::Int) |
-                                AsInt(PrefType::Bool)));
-  }
-
-  bool HasDefault() const { return mValue & PREF_FLAG_HAS_DEFAULT; }
-
-  PrefTypeFlags& SetHasDefault(bool aSetOrUnset)
-  {
-    return SetFlag(PREF_FLAG_HAS_DEFAULT, aSetOrUnset);
-  }
-
-  bool HasStickyDefault() const { return mValue & PREF_FLAG_STICKY_DEFAULT; }
-
-  PrefTypeFlags& SetHasStickyDefault(bool aSetOrUnset)
-  {
-    return SetFlag(PREF_FLAG_STICKY_DEFAULT, aSetOrUnset);
-  }
-
-  bool IsLocked() const { return mValue & PREF_FLAG_LOCKED; }
-
-  PrefTypeFlags& SetLocked(bool aSetOrUnset)
-  {
-    return SetFlag(PREF_FLAG_LOCKED, aSetOrUnset);
-  }
-
-  bool HasUserValue() const { return mValue & PREF_FLAG_USERSET; }
-
-  PrefTypeFlags& SetHasUserValue(bool aSetOrUnset)
-  {
-    return SetFlag(PREF_FLAG_USERSET, aSetOrUnset);
-  }
-
-private:
-  static uint16_t AsInt(PrefType aType) { return (uint16_t)aType; }
-
-  PrefTypeFlags& SetFlag(uint16_t aFlag, bool aSetOrUnset)
-  {
-    mValue = aSetOrUnset ? mValue | aFlag : mValue & ~aFlag;
-    return *this;
-  }
-
-  // We pack both the value of type (PrefType) and flags into the same int. The
-  // flag enum starts at 4 so that the PrefType can occupy the bottom two bits.
-  enum
-  {
-    PREF_FLAG_LOCKED = 4,
-    PREF_FLAG_USERSET = 8,
-    PREF_FLAG_CONFIG = 16,
-    PREF_FLAG_REMOTE = 32,
-    PREF_FLAG_LILOCAL = 64,
-    PREF_FLAG_HAS_DEFAULT = 128,
-    PREF_FLAG_STICKY_DEFAULT = 256,
-  };
-  uint16_t mValue;
-};
-
-struct PrefHashEntry : PLDHashEntryHdr
-{
-  PrefTypeFlags mPrefFlags; // this field first to minimize 64-bit struct size
-  const char* mKey;
-  PrefValue mDefaultPref;
-  PrefValue mUserPref;
-};
-
-// Set the various types of preferences. These functions take a dotted notation
-// of the preference name (e.g. "browser.startup.homepage"). Note that this
-// will cause the preference to be saved to the file if it is different from
-// the default. In other words, these are used to set the _user_ preferences.
-//
-// If aSetDefault is set to true however, it sets the default value. This will
-// only affect the program behavior if the user does not have a value saved
-// over it for the particular preference. In addition, these will never be
-// saved out to disk.
-//
-// Each set returns PREF_VALUECHANGED if the user value changed (triggering a
-// callback), or PREF_NOERROR if the value was unchanged.
-nsresult
-PREF_SetCharPref(const char* aPref, const char* aVal, bool aSetDefault = false);
-nsresult
-PREF_SetIntPref(const char* aPref, int32_t aVal, bool aSetDefault = false);
-nsresult
-PREF_SetBoolPref(const char* aPref, bool aVal, bool aSetDefault = false);
-
-bool
-PREF_HasUserPref(const char* aPrefName);
-
-// Get the various types of preferences. These functions take a dotted
-// notation of the preference name (e.g. "browser.startup.homepage")
-//
-// They also take a pointer to fill in with the return value and return an
-// error value. At the moment, this is simply an int but it may
-// be converted to an enum once the global error strategy is worked out.
-//
-// They will perform conversion if the type doesn't match what was requested.
-// (if it is reasonably possible)
-nsresult
-PREF_GetIntPref(const char* aPref, int32_t* aValueOut, bool aGetDefault);
-nsresult
-PREF_GetBoolPref(const char* aPref, bool* aValueOut, bool aGetDefault);
-
-// These functions are similar to the above "Get" version with the significant
-// difference that the preference module will alloc the memory (e.g. XP_STRDUP)
-// and the caller will need to be responsible for freeing it...
-nsresult
-PREF_CopyCharPref(const char* aPref, char** aValueOut, bool aGetDefault);
-
-// Bool function that returns whether or not the preference is locked and
-// therefore cannot be changed.
-bool
-PREF_PrefIsLocked(const char* aPrefName);
-
-// Function that sets whether or not the preference is locked and therefore
-// cannot be changed.
-nsresult
-PREF_LockPref(const char* aKey, bool aLockIt);
-
-PrefType
-PREF_GetPrefType(const char* aPrefName);
-
-// Delete a branch of the tree.
-nsresult
-PREF_DeleteBranch(const char* aBranchName);
-
-// Clears the given pref (reverts it to its default value).
-nsresult
-PREF_ClearUserPref(const char* aPrefName);
-
-// Clears all user prefs.
-nsresult
-PREF_ClearAllUserPrefs();
-
-// The callback function will get passed the pref_node which triggered the call
-// and the void* instance_data which was passed to the registered callback
-// function. Return a non-zero result (nsresult) to pass an error up to the
-// caller.
-//
-// Temporarily conditionally compile PrefChangedFunc typedef. During migration
-// from old libpref to nsIPref we need it in both header files. Eventually
-// prefapi.h will become a private file. The two types need to be in sync for
-// now. Certain compilers were having problems with multiple definitions.
-#ifndef have_PrefChangedFunc_typedef
-typedef void (*PrefChangedFunc)(const char*, void*);
-#define have_PrefChangedFunc_typedef
-#endif
-
-// Register a callback. This takes a node in the preference tree and will call
-// the callback function if anything below that node is modified. Unregister
-// returns PREF_NOERROR if a callback was found that matched all the
-// parameters; otherwise it returns PREF_ERROR.
-void
-PREF_RegisterPriorityCallback(const char* aPrefNode,
-                              PrefChangedFunc aCallback,
-                              void* aData);
-void
-PREF_RegisterCallback(const char* aPrefNode,
-                      PrefChangedFunc aCallback,
-                      void* aData);
-nsresult
-PREF_UnregisterCallback(const char* aPrefNode,
-                        PrefChangedFunc aCallback,
-                        void* aData);
-
-// Used by nsPrefService as the callback function of the prefs parser.
-void
-PREF_ReaderCallback(void* aClosure,
-                    const char* aPref,
-                    PrefValue aValue,
-                    PrefType aType,
-                    bool aIsDefault,
-                    bool aIsStickyDefault);
-
-// Callback for whenever we change a preference.
-typedef void (*PrefsDirtyFunc)();
-void PREF_SetDirtyCallback(PrefsDirtyFunc);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // prefapi_h
deleted file mode 100644
--- a/modules/libpref/prefapi_private_data.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* -*- 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/. */
-
-// Data shared between prefapi.c and nsPref.cpp.
-
-#ifndef prefapi_private_data_h
-#define prefapi_private_data_h
-
-#include "mozilla/MemoryReporting.h"
-#include "mozilla/UniquePtr.h"
-#include "Preferences.h"
-
-extern PLDHashTable* gHashTable;
-
-namespace mozilla {
-namespace dom {
-class PrefSetting;
-} // namespace dom
-} // namespace mozilla
-
-typedef nsTArray<mozilla::UniqueFreePtr<char>> PrefSaveData;
-
-PrefSaveData
-pref_savePrefs(PLDHashTable* aTable);
-
-nsresult
-pref_SetPref(const mozilla::dom::PrefSetting& aPref);
-
-#ifdef DEBUG
-void
-pref_SetInitPhase(pref_initPhase aPhase);
-
-pref_initPhase
-pref_GetInitPhase();
-
-void
-pref_SetWatchingPref(bool aWatching);
-#endif
-
-PrefHashEntry*
-pref_HashTableLookup(const char* aKey);
-
-bool
-pref_EntryHasAdvisablySizedValues(PrefHashEntry* aHashEntry);
-
-void
-pref_GetPrefFromEntry(PrefHashEntry* aHashEntry,
-                      mozilla::dom::PrefSetting* aPref);
-
-size_t
-pref_SizeOfPrivateData(mozilla::MallocSizeOf aMallocSizeOf);
-
-#endif