modules/libpref/src/Preferences.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "mozilla/MemoryReporting.h"
     8 #include "mozilla/dom/ContentChild.h"
    10 #include "mozilla/ArrayUtils.h"
    11 #include "mozilla/Attributes.h"
    12 #include "mozilla/HashFunctions.h"
    14 #include "nsXULAppAPI.h"
    16 #include "mozilla/Preferences.h"
    17 #include "nsAppDirectoryServiceDefs.h"
    18 #include "nsDataHashtable.h"
    19 #include "nsDirectoryServiceDefs.h"
    20 #include "nsICategoryManager.h"
    21 #include "nsCategoryManagerUtils.h"
    22 #include "nsNetUtil.h"
    23 #include "nsIFile.h"
    24 #include "nsIInputStream.h"
    25 #include "nsIObserverService.h"
    26 #include "nsIStringEnumerator.h"
    27 #include "nsIZipReader.h"
    28 #include "nsPrefBranch.h"
    29 #include "nsXPIDLString.h"
    30 #include "nsCRT.h"
    31 #include "nsCOMArray.h"
    32 #include "nsXPCOMCID.h"
    33 #include "nsAutoPtr.h"
    34 #include "nsPrintfCString.h"
    36 #include "nsQuickSort.h"
    37 #include "pldhash.h"
    39 #include "prefapi.h"
    40 #include "prefread.h"
    41 #include "prefapi_private_data.h"
    43 #include "mozilla/Omnijar.h"
    44 #include "nsZipArchive.h"
    46 #include "nsTArray.h"
    47 #include "nsRefPtrHashtable.h"
    48 #include "nsIMemoryReporter.h"
    49 #include "nsThreadUtils.h"
    51 #ifdef DEBUG
    52 #define ENSURE_MAIN_PROCESS(message, pref) do {                                \
    53   if (MOZ_UNLIKELY(XRE_GetProcessType() != GeckoProcessType_Default)) {        \
    54     nsPrintfCString msg("ENSURE_MAIN_PROCESS failed. %s %s", message, pref);   \
    55     NS_WARNING(msg.get());                                                     \
    56     return NS_ERROR_NOT_AVAILABLE;                                             \
    57   }                                                                            \
    58 } while (0);
    59 #else
    60 #define ENSURE_MAIN_PROCESS(message, pref)                                     \
    61   if (MOZ_UNLIKELY(XRE_GetProcessType() != GeckoProcessType_Default)) {        \
    62     return NS_ERROR_NOT_AVAILABLE;                                             \
    63   }
    64 #endif
    66 class PrefCallback;
    68 namespace mozilla {
    70 // Definitions
    71 #define INITIAL_PREF_FILES 10
    72 static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
    74 // Prototypes
    75 static nsresult openPrefFile(nsIFile* aFile);
    76 static nsresult pref_InitInitialObjects(void);
    77 static nsresult pref_LoadPrefsInDirList(const char *listId);
    78 static nsresult ReadExtensionPrefs(nsIFile *aFile);
    80 static const char kTelemetryPref[] = "toolkit.telemetry.enabled";
    81 static const char kOldTelemetryPref[] = "toolkit.telemetry.enabledPreRelease";
    82 static const char kChannelPref[] = "app.update.channel";
    84 Preferences* Preferences::sPreferences = nullptr;
    85 nsIPrefBranch* Preferences::sRootBranch = nullptr;
    86 nsIPrefBranch* Preferences::sDefaultRootBranch = nullptr;
    87 bool Preferences::sShutdown = false;
    89 class ValueObserverHashKey : public PLDHashEntryHdr {
    90 public:
    91   typedef ValueObserverHashKey* KeyType;
    92   typedef const ValueObserverHashKey* KeyTypePointer;
    94   static const ValueObserverHashKey* KeyToPointer(ValueObserverHashKey *aKey)
    95   {
    96     return aKey;
    97   }
    99   static PLDHashNumber HashKey(const ValueObserverHashKey *aKey)
   100   {
   101     PLDHashNumber hash = HashString(aKey->mPrefName);
   102     return AddToHash(hash, aKey->mCallback);
   103   }
   105   ValueObserverHashKey(const char *aPref, PrefChangedFunc aCallback) :
   106     mPrefName(aPref), mCallback(aCallback) { }
   108   ValueObserverHashKey(const ValueObserverHashKey *aOther) :
   109     mPrefName(aOther->mPrefName), mCallback(aOther->mCallback)
   110   { }
   112   bool KeyEquals(const ValueObserverHashKey *aOther) const
   113   {
   114     return mCallback == aOther->mCallback && mPrefName == aOther->mPrefName;
   115   }
   117   ValueObserverHashKey *GetKey() const
   118   {
   119     return const_cast<ValueObserverHashKey*>(this);
   120   }
   122   enum { ALLOW_MEMMOVE = true };
   124   nsCString mPrefName;
   125   PrefChangedFunc mCallback;
   126 };
   128 class ValueObserver MOZ_FINAL : public nsIObserver,
   129                                 public ValueObserverHashKey
   130 {
   131 public:
   132   NS_DECL_ISUPPORTS
   133   NS_DECL_NSIOBSERVER
   135   ValueObserver(const char *aPref, PrefChangedFunc aCallback)
   136     : ValueObserverHashKey(aPref, aCallback) { }
   138   ~ValueObserver() {
   139     Preferences::RemoveObserver(this, mPrefName.get());
   140   }
   142   void AppendClosure(void *aClosure) {
   143     mClosures.AppendElement(aClosure);
   144   }
   146   void RemoveClosure(void *aClosure) {
   147     mClosures.RemoveElement(aClosure);
   148   }
   150   bool HasNoClosures() {
   151     return mClosures.Length() == 0;
   152   }
   154   nsTArray<void*> mClosures;
   155 };
   157 NS_IMPL_ISUPPORTS(ValueObserver, nsIObserver)
   159 NS_IMETHODIMP
   160 ValueObserver::Observe(nsISupports     *aSubject,
   161                        const char      *aTopic,
   162                        const char16_t *aData)
   163 {
   164   NS_ASSERTION(!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID),
   165                "invalid topic");
   166   NS_ConvertUTF16toUTF8 data(aData);
   167   for (uint32_t i = 0; i < mClosures.Length(); i++) {
   168     mCallback(data.get(), mClosures.ElementAt(i));
   169   }
   171   return NS_OK;
   172 }
   174 struct CacheData {
   175   void* cacheLocation;
   176   union {
   177     bool defaultValueBool;
   178     int32_t defaultValueInt;
   179     uint32_t defaultValueUint;
   180     float defaultValueFloat;
   181   };
   182 };
   184 static nsTArray<nsAutoPtr<CacheData> >* gCacheData = nullptr;
   185 static nsRefPtrHashtable<ValueObserverHashKey,
   186                          ValueObserver>* gObserverTable = nullptr;
   188 static size_t
   189 SizeOfObserverEntryExcludingThis(ValueObserverHashKey* aKey,
   190                                  const nsRefPtr<ValueObserver>& aData,
   191                                  mozilla::MallocSizeOf aMallocSizeOf,
   192                                  void*)
   193 {
   194   size_t n = 0;
   195   n += aKey->mPrefName.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
   196   n += aData->mClosures.SizeOfExcludingThis(aMallocSizeOf);
   197   return n;
   198 }
   200 // Although this is a member of Preferences, it measures sPreferences and
   201 // several other global structures.
   202 /* static */ int64_t
   203 Preferences::SizeOfIncludingThisAndOtherStuff(mozilla::MallocSizeOf aMallocSizeOf)
   204 {
   205   NS_ENSURE_TRUE(InitStaticMembers(), 0);
   207   size_t n = aMallocSizeOf(sPreferences);
   208   if (gHashTable.ops) {
   209     // pref keys are allocated in a private arena, which we count elsewhere.
   210     // pref stringvals are allocated out of the same private arena.
   211     n += PL_DHashTableSizeOfExcludingThis(&gHashTable, nullptr, aMallocSizeOf);
   212   }
   213   if (gCacheData) {
   214     n += gCacheData->SizeOfIncludingThis(aMallocSizeOf);
   215     for (uint32_t i = 0, count = gCacheData->Length(); i < count; ++i) {
   216       n += aMallocSizeOf((*gCacheData)[i]);
   217     }
   218   }
   219   if (gObserverTable) {
   220     n += aMallocSizeOf(gObserverTable);
   221     n += gObserverTable->SizeOfExcludingThis(SizeOfObserverEntryExcludingThis,
   222                                              aMallocSizeOf);
   223   }
   224   // We don't measure sRootBranch and sDefaultRootBranch here because
   225   // DMD indicates they are not significant.
   226   n += pref_SizeOfPrivateData(aMallocSizeOf);
   227   return n;
   228 }
   230 class PreferenceServiceReporter MOZ_FINAL : public nsIMemoryReporter
   231 {
   232 public:
   233   NS_DECL_ISUPPORTS
   234   NS_DECL_NSIMEMORYREPORTER
   236 protected:
   237   static const uint32_t kSuspectReferentCount = 1000;
   238   static PLDHashOperator CountReferents(PrefCallback* aKey,
   239                                         nsAutoPtr<PrefCallback>& aCallback,
   240                                         void* aClosure);
   241 };
   243 NS_IMPL_ISUPPORTS(PreferenceServiceReporter, nsIMemoryReporter)
   245 struct PreferencesReferentCount {
   246   PreferencesReferentCount() : numStrong(0), numWeakAlive(0), numWeakDead(0) {}
   247   size_t numStrong;
   248   size_t numWeakAlive;
   249   size_t numWeakDead;
   250   nsTArray<nsCString> suspectPreferences;
   251   // Count of the number of referents for each preference.
   252   nsDataHashtable<nsCStringHashKey, uint32_t> prefCounter;
   253 };
   255 PLDHashOperator
   256 PreferenceServiceReporter::CountReferents(PrefCallback* aKey,
   257                                           nsAutoPtr<PrefCallback>& aCallback,
   258                                           void* aClosure)
   259 {
   260   PreferencesReferentCount* referentCount =
   261     static_cast<PreferencesReferentCount*>(aClosure);
   263   nsPrefBranch* prefBranch = aCallback->GetPrefBranch();
   264   const char* pref = prefBranch->getPrefName(aCallback->GetDomain().get());
   266   if (aCallback->IsWeak()) {
   267     nsCOMPtr<nsIObserver> callbackRef = do_QueryReferent(aCallback->mWeakRef);
   268     if (callbackRef) {
   269       referentCount->numWeakAlive++;
   270     } else {
   271       referentCount->numWeakDead++;
   272     }
   273   } else {
   274     referentCount->numStrong++;
   275   }
   277   nsDependentCString prefString(pref);
   278   uint32_t oldCount = 0;
   279   referentCount->prefCounter.Get(prefString, &oldCount);
   280   uint32_t currentCount = oldCount + 1;
   281   referentCount->prefCounter.Put(prefString, currentCount);
   283   // Keep track of preferences that have a suspiciously large
   284   // number of referents (symptom of leak).
   285   if (currentCount == kSuspectReferentCount) {
   286     referentCount->suspectPreferences.AppendElement(prefString);
   287   }
   289   return PL_DHASH_NEXT;
   290 }
   292 MOZ_DEFINE_MALLOC_SIZE_OF(PreferenceServiceMallocSizeOf)
   294 NS_IMETHODIMP
   295 PreferenceServiceReporter::CollectReports(nsIMemoryReporterCallback* aCb,
   296                                           nsISupports* aClosure)
   297 {
   298 #define REPORT(_path, _kind, _units, _amount, _desc)                          \
   299     do {                                                                      \
   300       nsresult rv;                                                            \
   301       rv = aCb->Callback(EmptyCString(), _path, _kind,                        \
   302                          _units, _amount, NS_LITERAL_CSTRING(_desc),          \
   303                          aClosure);                                           \
   304       NS_ENSURE_SUCCESS(rv, rv);                                              \
   305     } while (0)
   307   REPORT(NS_LITERAL_CSTRING("explicit/preferences"),
   308          KIND_HEAP, UNITS_BYTES,
   309          Preferences::SizeOfIncludingThisAndOtherStuff(PreferenceServiceMallocSizeOf),
   310          "Memory used by the preferences system.");
   312   nsPrefBranch* rootBranch =
   313     static_cast<nsPrefBranch*>(Preferences::GetRootBranch());
   314   if (!rootBranch) {
   315     return NS_OK;
   316   }
   318   PreferencesReferentCount referentCount;
   319   rootBranch->mObservers.Enumerate(&CountReferents, &referentCount);
   321   for (uint32_t i = 0; i < referentCount.suspectPreferences.Length(); i++) {
   322     nsCString& suspect = referentCount.suspectPreferences[i];
   323     uint32_t totalReferentCount = 0;
   324     referentCount.prefCounter.Get(suspect, &totalReferentCount);
   326     nsPrintfCString suspectPath("preference-service-suspect/"
   327                                 "referent(pref=%s)", suspect.get());
   329     REPORT(suspectPath,
   330            KIND_OTHER, UNITS_COUNT, totalReferentCount,
   331            "A preference with a suspiciously large number "
   332            "referents (symptom of a leak).");
   333   }
   335   REPORT(NS_LITERAL_CSTRING("preference-service/referent/strong"),
   336          KIND_OTHER, UNITS_COUNT, referentCount.numStrong,
   337          "The number of strong referents held by the preference service.");
   339   REPORT(NS_LITERAL_CSTRING("preference-service/referent/weak/alive"),
   340          KIND_OTHER, UNITS_COUNT, referentCount.numWeakAlive,
   341          "The number of weak referents held by the preference service "
   342          "that are still alive.");
   344   REPORT(NS_LITERAL_CSTRING("preference-service/referent/weak/dead"),
   345          KIND_OTHER, UNITS_COUNT, referentCount.numWeakDead,
   346          "The number of weak referents held by the preference service "
   347          "that are dead.");
   349 #undef REPORT
   351   return NS_OK;
   352 }
   354 namespace {
   355 class AddPreferencesMemoryReporterRunnable : public nsRunnable
   356 {
   357   NS_IMETHOD Run()
   358   {
   359     return RegisterStrongMemoryReporter(new PreferenceServiceReporter());
   360   }
   361 };
   362 } // anonymous namespace
   364 // static
   365 Preferences*
   366 Preferences::GetInstanceForService()
   367 {
   368   if (sPreferences) {
   369     NS_ADDREF(sPreferences);
   370     return sPreferences;
   371   }
   373   NS_ENSURE_TRUE(!sShutdown, nullptr);
   375   sRootBranch = new nsPrefBranch("", false);
   376   NS_ADDREF(sRootBranch);
   377   sDefaultRootBranch = new nsPrefBranch("", true);
   378   NS_ADDREF(sDefaultRootBranch);
   380   sPreferences = new Preferences();
   381   NS_ADDREF(sPreferences);
   383   if (NS_FAILED(sPreferences->Init())) {
   384     // The singleton instance will delete sRootBranch and sDefaultRootBranch.
   385     NS_RELEASE(sPreferences);
   386     return nullptr;
   387   }
   389   gCacheData = new nsTArray<nsAutoPtr<CacheData> >();
   391   gObserverTable = new nsRefPtrHashtable<ValueObserverHashKey, ValueObserver>();
   393   // Preferences::GetInstanceForService() can be called from GetService(), and
   394   // RegisterStrongMemoryReporter calls GetService(nsIMemoryReporter).  To
   395   // avoid a potential recursive GetService() call, we can't register the
   396   // memory reporter here; instead, do it off a runnable.
   397   nsRefPtr<AddPreferencesMemoryReporterRunnable> runnable =
   398     new AddPreferencesMemoryReporterRunnable();
   399   NS_DispatchToMainThread(runnable);
   401   NS_ADDREF(sPreferences);
   402   return sPreferences;
   403 }
   405 // static
   406 bool
   407 Preferences::InitStaticMembers()
   408 {
   409 #ifndef MOZ_B2G
   410   MOZ_ASSERT(NS_IsMainThread());
   411 #endif
   413   if (!sShutdown && !sPreferences) {
   414     nsCOMPtr<nsIPrefService> prefService =
   415       do_GetService(NS_PREFSERVICE_CONTRACTID);
   416   }
   418   return sPreferences != nullptr;
   419 }
   421 // static
   422 void
   423 Preferences::Shutdown()
   424 {
   425   if (!sShutdown) {
   426     sShutdown = true; // Don't create the singleton instance after here.
   428     // Don't set sPreferences to nullptr here.  The instance may be grabbed by
   429     // other modules.  The utility methods of Preferences should be available
   430     // until the singleton instance actually released.
   431     if (sPreferences) {
   432       sPreferences->Release();
   433     }
   434   }
   435 }
   437 //-----------------------------------------------------------------------------
   439 /*
   440  * Constructor/Destructor
   441  */
   443 Preferences::Preferences()
   444 {
   445 }
   447 Preferences::~Preferences()
   448 {
   449   NS_ASSERTION(sPreferences == this, "Isn't this the singleton instance?");
   451   delete gObserverTable;
   452   gObserverTable = nullptr;
   454   delete gCacheData;
   455   gCacheData = nullptr;
   457   NS_RELEASE(sRootBranch);
   458   NS_RELEASE(sDefaultRootBranch);
   460   sPreferences = nullptr;
   462   PREF_Cleanup();
   463 }
   466 /*
   467  * nsISupports Implementation
   468  */
   470 NS_IMPL_ADDREF(Preferences)
   471 NS_IMPL_RELEASE(Preferences)
   473 NS_INTERFACE_MAP_BEGIN(Preferences)
   474     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPrefService)
   475     NS_INTERFACE_MAP_ENTRY(nsIPrefService)
   476     NS_INTERFACE_MAP_ENTRY(nsIObserver)
   477     NS_INTERFACE_MAP_ENTRY(nsIPrefBranch)
   478     NS_INTERFACE_MAP_ENTRY(nsIPrefBranch2)
   479     NS_INTERFACE_MAP_ENTRY(nsIPrefBranchInternal)
   480     NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   481 NS_INTERFACE_MAP_END
   484 /*
   485  * nsIPrefService Implementation
   486  */
   488 nsresult
   489 Preferences::Init()
   490 {
   491   nsresult rv;
   493   rv = PREF_Init();
   494   NS_ENSURE_SUCCESS(rv, rv);
   496   rv = pref_InitInitialObjects();
   497   NS_ENSURE_SUCCESS(rv, rv);
   499   using mozilla::dom::ContentChild;
   500   if (XRE_GetProcessType() == GeckoProcessType_Content) {
   501     InfallibleTArray<PrefSetting> prefs;
   502     ContentChild::GetSingleton()->SendReadPrefsArray(&prefs);
   504     // Store the array
   505     for (uint32_t i = 0; i < prefs.Length(); ++i) {
   506       pref_SetPref(prefs[i]);
   507     }
   508     return NS_OK;
   509   }
   511   nsXPIDLCString lockFileName;
   512   /*
   513    * The following is a small hack which will allow us to only load the library
   514    * which supports the netscape.cfg file if the preference is defined. We
   515    * test for the existence of the pref, set in the all.js (mozilla) or
   516    * all-ns.js (netscape 6), and if it exists we startup the pref config
   517    * category which will do the rest.
   518    */
   520   rv = PREF_CopyCharPref("general.config.filename", getter_Copies(lockFileName), false);
   521   if (NS_SUCCEEDED(rv))
   522     NS_CreateServicesFromCategory("pref-config-startup",
   523                                   static_cast<nsISupports *>(static_cast<void *>(this)),
   524                                   "pref-config-startup");    
   526   nsCOMPtr<nsIObserverService> observerService =
   527     mozilla::services::GetObserverService();
   528   if (!observerService)
   529     return NS_ERROR_FAILURE;
   531   rv = observerService->AddObserver(this, "profile-before-change", true);
   533   observerService->AddObserver(this, "load-extension-defaults", true);
   534   observerService->AddObserver(this, "suspend_process_notification", true);
   536   return(rv);
   537 }
   539 // static
   540 nsresult
   541 Preferences::ResetAndReadUserPrefs()
   542 {
   543   sPreferences->ResetUserPrefs();
   544   return sPreferences->ReadUserPrefs(nullptr);
   545 }
   547 NS_IMETHODIMP
   548 Preferences::Observe(nsISupports *aSubject, const char *aTopic,
   549                      const char16_t *someData)
   550 {
   551   if (XRE_GetProcessType() == GeckoProcessType_Content)
   552     return NS_ERROR_NOT_AVAILABLE;
   554   nsresult rv = NS_OK;
   556   if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
   557     if (!nsCRT::strcmp(someData, MOZ_UTF16("shutdown-cleanse"))) {
   558       if (mCurrentFile) {
   559         mCurrentFile->Remove(false);
   560         mCurrentFile = nullptr;
   561       }
   562     } else {
   563       rv = SavePrefFile(nullptr);
   564     }
   565   } else if (!strcmp(aTopic, "load-extension-defaults")) {
   566     pref_LoadPrefsInDirList(NS_EXT_PREFS_DEFAULTS_DIR_LIST);
   567   } else if (!nsCRT::strcmp(aTopic, "reload-default-prefs")) {
   568     // Reload the default prefs from file.
   569     pref_InitInitialObjects();
   570   } else if (!nsCRT::strcmp(aTopic, "suspend_process_notification")) {
   571     // Our process is being suspended. The OS may wake our process later,
   572     // or it may kill the process. In case our process is going to be killed
   573     // from the suspended state, we save preferences before suspending.
   574     rv = SavePrefFile(nullptr);
   575   }
   576   return rv;
   577 }
   580 NS_IMETHODIMP
   581 Preferences::ReadUserPrefs(nsIFile *aFile)
   582 {
   583   if (XRE_GetProcessType() == GeckoProcessType_Content) {
   584     NS_ERROR("cannot load prefs from content process");
   585     return NS_ERROR_NOT_AVAILABLE;
   586   }
   588   nsresult rv;
   590   if (nullptr == aFile) {
   591     rv = UseDefaultPrefFile();
   592     // A user pref file is optional.
   593     // Ignore all errors related to it, so we retain 'rv' value :-|
   594     (void) UseUserPrefFile();
   596     // Migrate the old prerelease telemetry pref
   597     if (!Preferences::GetBool(kOldTelemetryPref, true)) {
   598       Preferences::SetBool(kTelemetryPref, false);
   599       Preferences::ClearUser(kOldTelemetryPref);
   600     }
   602     NotifyServiceObservers(NS_PREFSERVICE_READ_TOPIC_ID);
   603   } else {
   604     rv = ReadAndOwnUserPrefFile(aFile);
   605   }
   607   return rv;
   608 }
   610 NS_IMETHODIMP
   611 Preferences::ResetPrefs()
   612 {
   613   if (XRE_GetProcessType() == GeckoProcessType_Content) {
   614     NS_ERROR("cannot reset prefs from content process");
   615     return NS_ERROR_NOT_AVAILABLE;
   616   }
   618   NotifyServiceObservers(NS_PREFSERVICE_RESET_TOPIC_ID);
   619   PREF_CleanupPrefs();
   621   nsresult rv = PREF_Init();
   622   NS_ENSURE_SUCCESS(rv, rv);
   624   return pref_InitInitialObjects();
   625 }
   627 NS_IMETHODIMP
   628 Preferences::ResetUserPrefs()
   629 {
   630   if (XRE_GetProcessType() == GeckoProcessType_Content) {
   631     NS_ERROR("cannot reset user prefs from content process");
   632     return NS_ERROR_NOT_AVAILABLE;
   633   }
   635   PREF_ClearAllUserPrefs();
   636   return NS_OK;    
   637 }
   639 NS_IMETHODIMP
   640 Preferences::SavePrefFile(nsIFile *aFile)
   641 {
   642   if (XRE_GetProcessType() == GeckoProcessType_Content) {
   643     NS_ERROR("cannot save pref file from content process");
   644     return NS_ERROR_NOT_AVAILABLE;
   645   }
   647   return SavePrefFileInternal(aFile);
   648 }
   650 static nsresult
   651 ReadExtensionPrefs(nsIFile *aFile)
   652 {
   653   nsresult rv;
   654   nsCOMPtr<nsIZipReader> reader = do_CreateInstance(kZipReaderCID, &rv);
   655   NS_ENSURE_SUCCESS(rv, rv);
   657   rv = reader->Open(aFile);
   658   NS_ENSURE_SUCCESS(rv, rv);
   660   nsCOMPtr<nsIUTF8StringEnumerator> files;
   661   rv = reader->FindEntries(nsDependentCString("defaults/preferences/*.(J|j)(S|s)$"),
   662                            getter_AddRefs(files));
   663   NS_ENSURE_SUCCESS(rv, rv);
   665   char buffer[4096];
   667   bool more;
   668   while (NS_SUCCEEDED(rv = files->HasMore(&more)) && more) {
   669     nsAutoCString entry;
   670     rv = files->GetNext(entry);
   671     NS_ENSURE_SUCCESS(rv, rv);
   673     nsCOMPtr<nsIInputStream> stream;
   674     rv = reader->GetInputStream(entry, getter_AddRefs(stream));
   675     NS_ENSURE_SUCCESS(rv, rv);
   677     uint64_t avail;
   678     uint32_t read;
   680     PrefParseState ps;
   681     PREF_InitParseState(&ps, PREF_ReaderCallback, nullptr);
   682     while (NS_SUCCEEDED(rv = stream->Available(&avail)) && avail) {
   683       rv = stream->Read(buffer, 4096, &read);
   684       if (NS_FAILED(rv)) {
   685         NS_WARNING("Pref stream read failed");
   686         break;
   687       }
   689       PREF_ParseBuf(&ps, buffer, read);
   690     }
   691     PREF_FinalizeParseState(&ps);
   692   }
   693   return rv;
   694 }
   696 void
   697 Preferences::SetPreference(const PrefSetting& aPref)
   698 {
   699   pref_SetPref(aPref);
   700 }
   702 void
   703 Preferences::GetPreference(PrefSetting* aPref)
   704 {
   705   PrefHashEntry *entry = pref_HashTableLookup(aPref->name().get());
   706   if (!entry)
   707     return;
   709   pref_GetPrefFromEntry(entry, aPref);
   710 }
   712 void
   713 Preferences::GetPreferences(InfallibleTArray<PrefSetting>* aPrefs)
   714 {
   715   aPrefs->SetCapacity(PL_DHASH_TABLE_SIZE(&gHashTable));
   716   PL_DHashTableEnumerate(&gHashTable, pref_GetPrefs, aPrefs);
   717 }
   719 NS_IMETHODIMP
   720 Preferences::GetBranch(const char *aPrefRoot, nsIPrefBranch **_retval)
   721 {
   722   nsresult rv;
   724   if ((nullptr != aPrefRoot) && (*aPrefRoot != '\0')) {
   725     // TODO: - cache this stuff and allow consumers to share branches (hold weak references I think)
   726     nsPrefBranch* prefBranch = new nsPrefBranch(aPrefRoot, false);
   727     if (!prefBranch)
   728       return NS_ERROR_OUT_OF_MEMORY;
   730     rv = CallQueryInterface(prefBranch, _retval);
   731   } else {
   732     // special case caching the default root
   733     nsCOMPtr<nsIPrefBranch> root(sRootBranch);
   734     root.forget(_retval);
   735     rv = NS_OK;
   736   }
   737   return rv;
   738 }
   740 NS_IMETHODIMP
   741 Preferences::GetDefaultBranch(const char *aPrefRoot, nsIPrefBranch **_retval)
   742 {
   743   if (!aPrefRoot || !aPrefRoot[0]) {
   744     nsCOMPtr<nsIPrefBranch> root(sDefaultRootBranch);
   745     root.forget(_retval);
   746     return NS_OK;
   747   }
   749   // TODO: - cache this stuff and allow consumers to share branches (hold weak references I think)
   750   nsRefPtr<nsPrefBranch> prefBranch = new nsPrefBranch(aPrefRoot, true);
   751   if (!prefBranch)
   752     return NS_ERROR_OUT_OF_MEMORY;
   754   prefBranch.forget(_retval);
   755   return NS_OK;
   756 }
   759 nsresult
   760 Preferences::NotifyServiceObservers(const char *aTopic)
   761 {
   762   nsCOMPtr<nsIObserverService> observerService = 
   763     mozilla::services::GetObserverService();  
   764   if (!observerService)
   765     return NS_ERROR_FAILURE;
   767   nsISupports *subject = (nsISupports *)((nsIPrefService *)this);
   768   observerService->NotifyObservers(subject, aTopic, nullptr);
   770   return NS_OK;
   771 }
   773 nsresult
   774 Preferences::UseDefaultPrefFile()
   775 {
   776   nsresult rv;
   777   nsCOMPtr<nsIFile> aFile;
   779 #if defined(XP_WIN) && defined(MOZ_METRO)
   780   if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Metro) {
   781     rv = NS_GetSpecialDirectory(NS_METRO_APP_PREFS_50_FILE, getter_AddRefs(aFile));
   782   } else
   783 #endif
   784   {
   785     rv = NS_GetSpecialDirectory(NS_APP_PREFS_50_FILE, getter_AddRefs(aFile));
   786   }
   788   if (NS_SUCCEEDED(rv)) {
   789     rv = ReadAndOwnUserPrefFile(aFile);
   790     // Most likely cause of failure here is that the file didn't
   791     // exist, so save a new one. mUserPrefReadFailed will be
   792     // used to catch an error in actually reading the file.
   793     if (NS_FAILED(rv)) {
   794       if (NS_FAILED(SavePrefFileInternal(aFile)))
   795         NS_ERROR("Failed to save new shared pref file");
   796       else
   797         rv = NS_OK;
   798     }
   799   }
   801   return rv;
   802 }
   804 nsresult
   805 Preferences::UseUserPrefFile()
   806 {
   807   nsresult rv = NS_OK;
   808   nsCOMPtr<nsIFile> aFile;
   809   nsDependentCString prefsDirProp(NS_APP_PREFS_50_DIR);
   811   rv = NS_GetSpecialDirectory(prefsDirProp.get(), getter_AddRefs(aFile));
   812   if (NS_SUCCEEDED(rv) && aFile) {
   813     rv = aFile->AppendNative(NS_LITERAL_CSTRING("user.js"));
   814     if (NS_SUCCEEDED(rv)) {
   815       bool exists = false;
   816       aFile->Exists(&exists);
   817       if (exists) {
   818         rv = openPrefFile(aFile);
   819       } else {
   820         rv = NS_ERROR_FILE_NOT_FOUND;
   821       }
   822     }
   823   }
   824   return rv;
   825 }
   827 nsresult
   828 Preferences::MakeBackupPrefFile(nsIFile *aFile)
   829 {
   830   // Example: this copies "prefs.js" to "Invalidprefs.js" in the same directory.
   831   // "Invalidprefs.js" is removed if it exists, prior to making the copy.
   832   nsAutoString newFilename;
   833   nsresult rv = aFile->GetLeafName(newFilename);
   834   NS_ENSURE_SUCCESS(rv, rv);
   835   newFilename.Insert(NS_LITERAL_STRING("Invalid"), 0);
   836   nsCOMPtr<nsIFile> newFile;
   837   rv = aFile->GetParent(getter_AddRefs(newFile));
   838   NS_ENSURE_SUCCESS(rv, rv);
   839   rv = newFile->Append(newFilename);
   840   NS_ENSURE_SUCCESS(rv, rv);
   841   bool exists = false;
   842   newFile->Exists(&exists);
   843   if (exists) {
   844     rv = newFile->Remove(false);
   845     NS_ENSURE_SUCCESS(rv, rv);
   846   }
   847   rv = aFile->CopyTo(nullptr, newFilename);
   848   NS_ENSURE_SUCCESS(rv, rv);
   849   return rv;
   850 }
   852 nsresult
   853 Preferences::ReadAndOwnUserPrefFile(nsIFile *aFile)
   854 {
   855   NS_ENSURE_ARG(aFile);
   857   if (mCurrentFile == aFile)
   858     return NS_OK;
   859   mCurrentFile = aFile;
   861   nsresult rv = NS_OK;
   862   bool exists = false;
   863   mCurrentFile->Exists(&exists);
   864   if (exists) {
   865     rv = openPrefFile(mCurrentFile);
   866     if (NS_FAILED(rv)) {
   867       // Save a backup copy of the current (invalid) prefs file, since all prefs
   868       // from the error line to the end of the file will be lost (bug 361102).
   869       // TODO we should notify the user about it (bug 523725).
   870       MakeBackupPrefFile(mCurrentFile);
   871     }
   872   } else {
   873     rv = NS_ERROR_FILE_NOT_FOUND;
   874   }
   876   return rv;
   877 }
   879 nsresult
   880 Preferences::SavePrefFileInternal(nsIFile *aFile)
   881 {
   882   if (nullptr == aFile) {
   883     // the gDirty flag tells us if we should write to mCurrentFile
   884     // we only check this flag when the caller wants to write to the default
   885     if (!gDirty)
   886       return NS_OK;
   888     // It's possible that we never got a prefs file.
   889     nsresult rv = NS_OK;
   890     if (mCurrentFile)
   891       rv = WritePrefFile(mCurrentFile);
   893     return rv;
   894   } else {
   895     return WritePrefFile(aFile);
   896   }
   897 }
   899 nsresult
   900 Preferences::WritePrefFile(nsIFile* aFile)
   901 {
   902   const char                outHeader[] =
   903     "# Mozilla User Preferences"
   904     NS_LINEBREAK
   905     NS_LINEBREAK
   906     "/* Do not edit this file."
   907     NS_LINEBREAK
   908     " *"
   909     NS_LINEBREAK
   910     " * If you make changes to this file while the application is running,"
   911     NS_LINEBREAK
   912     " * the changes will be overwritten when the application exits."
   913     NS_LINEBREAK
   914     " *"
   915     NS_LINEBREAK
   916     " * To make a manual change to preferences, you can visit the URL about:config"
   917     NS_LINEBREAK
   918     " */"
   919     NS_LINEBREAK
   920     NS_LINEBREAK;
   922   nsCOMPtr<nsIOutputStream> outStreamSink;
   923   nsCOMPtr<nsIOutputStream> outStream;
   924   uint32_t                  writeAmount;
   925   nsresult                  rv;
   927   if (!gHashTable.ops)
   928     return NS_ERROR_NOT_INITIALIZED;
   930   // execute a "safe" save by saving through a tempfile
   931   rv = NS_NewSafeLocalFileOutputStream(getter_AddRefs(outStreamSink),
   932                                        aFile,
   933                                        -1,
   934                                        0600);
   935   if (NS_FAILED(rv)) 
   936       return rv;
   937   rv = NS_NewBufferedOutputStream(getter_AddRefs(outStream), outStreamSink, 4096);
   938   if (NS_FAILED(rv)) 
   939       return rv;  
   941   nsAutoArrayPtr<char*> valueArray(new char*[gHashTable.entryCount]);
   942   memset(valueArray, 0, gHashTable.entryCount * sizeof(char*));
   943   pref_saveArgs saveArgs;
   944   saveArgs.prefArray = valueArray;
   945   saveArgs.saveTypes = SAVE_ALL;
   947   // get the lines that we're supposed to be writing to the file
   948   PL_DHashTableEnumerate(&gHashTable, pref_savePref, &saveArgs);
   950   /* Sort the preferences to make a readable file on disk */
   951   NS_QuickSort(valueArray, gHashTable.entryCount, sizeof(char *), pref_CompareStrings, nullptr);
   953   // write out the file header
   954   outStream->Write(outHeader, sizeof(outHeader) - 1, &writeAmount);
   956   char** walker = valueArray;
   957   for (uint32_t valueIdx = 0; valueIdx < gHashTable.entryCount; valueIdx++, walker++) {
   958     if (*walker) {
   959       outStream->Write(*walker, strlen(*walker), &writeAmount);
   960       outStream->Write(NS_LINEBREAK, NS_LINEBREAK_LEN, &writeAmount);
   961       NS_Free(*walker);
   962     }
   963   }
   965   // tell the safe output stream to overwrite the real prefs file
   966   // (it'll abort if there were any errors during writing)
   967   nsCOMPtr<nsISafeOutputStream> safeStream = do_QueryInterface(outStream);
   968   NS_ASSERTION(safeStream, "expected a safe output stream!");
   969   if (safeStream) {
   970     rv = safeStream->Finish();
   971     if (NS_FAILED(rv)) {
   972       NS_WARNING("failed to save prefs file! possible data loss");
   973       return rv;
   974     }
   975   }
   977   gDirty = false;
   978   return NS_OK;
   979 }
   981 static nsresult openPrefFile(nsIFile* aFile)
   982 {
   983   nsCOMPtr<nsIInputStream> inStr;
   985   nsresult rv = NS_NewLocalFileInputStream(getter_AddRefs(inStr), aFile);
   986   if (NS_FAILED(rv)) 
   987     return rv;        
   989   uint64_t fileSize64;
   990   rv = inStr->Available(&fileSize64);
   991   if (NS_FAILED(rv))
   992     return rv;
   993   NS_ENSURE_TRUE(fileSize64 <= UINT32_MAX, NS_ERROR_FILE_TOO_BIG);
   995   uint32_t fileSize = (uint32_t)fileSize64;
   996   nsAutoArrayPtr<char> fileBuffer(new char[fileSize]);
   997   if (fileBuffer == nullptr)
   998     return NS_ERROR_OUT_OF_MEMORY;
  1000   PrefParseState ps;
  1001   PREF_InitParseState(&ps, PREF_ReaderCallback, nullptr);
  1003   // Read is not guaranteed to return a buf the size of fileSize,
  1004   // but usually will.
  1005   nsresult rv2 = NS_OK;
  1006   for (;;) {
  1007     uint32_t amtRead = 0;
  1008     rv = inStr->Read((char*)fileBuffer, fileSize, &amtRead);
  1009     if (NS_FAILED(rv) || amtRead == 0)
  1010       break;
  1011     if (!PREF_ParseBuf(&ps, fileBuffer, amtRead))
  1012       rv2 = NS_ERROR_FILE_CORRUPTED;
  1015   PREF_FinalizeParseState(&ps);
  1017   return NS_FAILED(rv) ? rv : rv2;
  1020 /*
  1021  * some stuff that gets called from Pref_Init()
  1022  */
  1024 static int
  1025 pref_CompareFileNames(nsIFile* aFile1, nsIFile* aFile2, void* /*unused*/)
  1027   nsAutoCString filename1, filename2;
  1028   aFile1->GetNativeLeafName(filename1);
  1029   aFile2->GetNativeLeafName(filename2);
  1031   return Compare(filename2, filename1);
  1034 /**
  1035  * Load default pref files from a directory. The files in the
  1036  * directory are sorted reverse-alphabetically; a set of "special file
  1037  * names" may be specified which are loaded after all the others.
  1038  */
  1039 static nsresult
  1040 pref_LoadPrefsInDir(nsIFile* aDir, char const *const *aSpecialFiles, uint32_t aSpecialFilesCount)
  1042   nsresult rv, rv2;
  1043   bool hasMoreElements;
  1045   nsCOMPtr<nsISimpleEnumerator> dirIterator;
  1047   // this may fail in some normal cases, such as embedders who do not use a GRE
  1048   rv = aDir->GetDirectoryEntries(getter_AddRefs(dirIterator));
  1049   if (NS_FAILED(rv)) {
  1050     // If the directory doesn't exist, then we have no reason to complain.  We
  1051     // loaded everything (and nothing) successfully.
  1052     if (rv == NS_ERROR_FILE_NOT_FOUND || rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST)
  1053       rv = NS_OK;
  1054     return rv;
  1057   rv = dirIterator->HasMoreElements(&hasMoreElements);
  1058   NS_ENSURE_SUCCESS(rv, rv);
  1060   nsCOMArray<nsIFile> prefFiles(INITIAL_PREF_FILES);
  1061   nsCOMArray<nsIFile> specialFiles(aSpecialFilesCount);
  1062   nsCOMPtr<nsIFile> prefFile;
  1064   while (hasMoreElements && NS_SUCCEEDED(rv)) {
  1065     nsAutoCString leafName;
  1067     nsCOMPtr<nsISupports> supports;
  1068     rv = dirIterator->GetNext(getter_AddRefs(supports));
  1069     prefFile = do_QueryInterface(supports);
  1070     if (NS_FAILED(rv)) {
  1071       break;
  1074     prefFile->GetNativeLeafName(leafName);
  1075     NS_ASSERTION(!leafName.IsEmpty(), "Failure in default prefs: directory enumerator returned empty file?");
  1077     // Skip non-js files
  1078     if (StringEndsWith(leafName, NS_LITERAL_CSTRING(".js"),
  1079                        nsCaseInsensitiveCStringComparator())) {
  1080       bool shouldParse = true;
  1081       // separate out special files
  1082       for (uint32_t i = 0; i < aSpecialFilesCount; ++i) {
  1083         if (leafName.Equals(nsDependentCString(aSpecialFiles[i]))) {
  1084           shouldParse = false;
  1085           // special files should be process in order; we put them into
  1086           // the array by index; this can make the array sparse
  1087           specialFiles.ReplaceObjectAt(prefFile, i);
  1091       if (shouldParse) {
  1092         prefFiles.AppendObject(prefFile);
  1096     rv = dirIterator->HasMoreElements(&hasMoreElements);
  1099   if (prefFiles.Count() + specialFiles.Count() == 0) {
  1100     NS_WARNING("No default pref files found.");
  1101     if (NS_SUCCEEDED(rv)) {
  1102       rv = NS_SUCCESS_FILE_DIRECTORY_EMPTY;
  1104     return rv;
  1107   prefFiles.Sort(pref_CompareFileNames, nullptr);
  1109   uint32_t arrayCount = prefFiles.Count();
  1110   uint32_t i;
  1111   for (i = 0; i < arrayCount; ++i) {
  1112     rv2 = openPrefFile(prefFiles[i]);
  1113     if (NS_FAILED(rv2)) {
  1114       NS_ERROR("Default pref file not parsed successfully.");
  1115       rv = rv2;
  1119   arrayCount = specialFiles.Count();
  1120   for (i = 0; i < arrayCount; ++i) {
  1121     // this may be a sparse array; test before parsing
  1122     nsIFile* file = specialFiles[i];
  1123     if (file) {
  1124       rv2 = openPrefFile(file);
  1125       if (NS_FAILED(rv2)) {
  1126         NS_ERROR("Special default pref file not parsed successfully.");
  1127         rv = rv2;
  1132   return rv;
  1135 static nsresult pref_LoadPrefsInDirList(const char *listId)
  1137   nsresult rv;
  1138   nsCOMPtr<nsIProperties> dirSvc(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv));
  1139   if (NS_FAILED(rv))
  1140     return rv;
  1142   nsCOMPtr<nsISimpleEnumerator> list;
  1143   dirSvc->Get(listId,
  1144               NS_GET_IID(nsISimpleEnumerator),
  1145               getter_AddRefs(list));
  1146   if (!list)
  1147     return NS_OK;
  1149   bool hasMore;
  1150   while (NS_SUCCEEDED(list->HasMoreElements(&hasMore)) && hasMore) {
  1151     nsCOMPtr<nsISupports> elem;
  1152     list->GetNext(getter_AddRefs(elem));
  1153     if (!elem)
  1154       continue;
  1156     nsCOMPtr<nsIFile> path = do_QueryInterface(elem);
  1157     if (!path)
  1158       continue;
  1160     nsAutoCString leaf;
  1161     path->GetNativeLeafName(leaf);
  1163     // Do we care if a file provided by this process fails to load?
  1164     if (Substring(leaf, leaf.Length() - 4).Equals(NS_LITERAL_CSTRING(".xpi")))
  1165       ReadExtensionPrefs(path);
  1166     else
  1167       pref_LoadPrefsInDir(path, nullptr, 0);
  1169   return NS_OK;
  1172 static nsresult pref_ReadPrefFromJar(nsZipArchive* jarReader, const char *name)
  1174   nsZipItemPtr<char> manifest(jarReader, name, true);
  1175   NS_ENSURE_TRUE(manifest.Buffer(), NS_ERROR_NOT_AVAILABLE);
  1177   PrefParseState ps;
  1178   PREF_InitParseState(&ps, PREF_ReaderCallback, nullptr);
  1179   PREF_ParseBuf(&ps, manifest, manifest.Length());
  1180   PREF_FinalizeParseState(&ps);
  1182   return NS_OK;
  1185 //----------------------------------------------------------------------------------------
  1186 // Initialize default preference JavaScript buffers from
  1187 // appropriate TEXT resources
  1188 //----------------------------------------------------------------------------------------
  1189 static nsresult pref_InitInitialObjects()
  1191   nsresult rv;
  1193   // In omni.jar case, we load the following prefs:
  1194   // - jar:$gre/omni.jar!/greprefs.js
  1195   // - jar:$gre/omni.jar!/defaults/pref/*.js
  1196   // In non omni.jar case, we load:
  1197   // - $gre/greprefs.js
  1198   //
  1199   // In both cases, we also load:
  1200   // - $gre/defaults/pref/*.js
  1201   // This is kept for bug 591866 (channel-prefs.js should not be in omni.jar)
  1202   // on $app == $gre case ; we load all files instead of channel-prefs.js only
  1203   // to have the same behaviour as $app != $gre, where this is required as
  1204   // a supported location for GRE preferences.
  1205   //
  1206   // When $app != $gre, we additionally load, in omni.jar case:
  1207   // - jar:$app/omni.jar!/defaults/preferences/*.js
  1208   // - $app/defaults/preferences/*.js
  1209   // and in non omni.jar case:
  1210   // - $app/defaults/preferences/*.js
  1211   // When $app == $gre, we additionally load, in omni.jar case:
  1212   // - jar:$gre/omni.jar!/defaults/preferences/*.js
  1213   // Thus, in omni.jar case, we always load app-specific default preferences
  1214   // from omni.jar, whether or not $app == $gre.
  1216   nsZipFind *findPtr;
  1217   nsAutoPtr<nsZipFind> find;
  1218   nsTArray<nsCString> prefEntries;
  1219   const char *entryName;
  1220   uint16_t entryNameLen;
  1222   nsRefPtr<nsZipArchive> jarReader = mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE);
  1223   if (jarReader) {
  1224     // Load jar:$gre/omni.jar!/greprefs.js
  1225     rv = pref_ReadPrefFromJar(jarReader, "greprefs.js");
  1226     NS_ENSURE_SUCCESS(rv, rv);
  1228     // Load jar:$gre/omni.jar!/defaults/pref/*.js
  1229     rv = jarReader->FindInit("defaults/pref/*.js$", &findPtr);
  1230     NS_ENSURE_SUCCESS(rv, rv);
  1232     find = findPtr;
  1233     while (NS_SUCCEEDED(find->FindNext(&entryName, &entryNameLen))) {
  1234       prefEntries.AppendElement(Substring(entryName, entryNameLen));
  1237     prefEntries.Sort();
  1238     for (uint32_t i = prefEntries.Length(); i--; ) {
  1239       rv = pref_ReadPrefFromJar(jarReader, prefEntries[i].get());
  1240       if (NS_FAILED(rv))
  1241         NS_WARNING("Error parsing preferences.");
  1243   } else {
  1244     // Load $gre/greprefs.js
  1245     nsCOMPtr<nsIFile> greprefsFile;
  1246     rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(greprefsFile));
  1247     NS_ENSURE_SUCCESS(rv, rv);
  1249     rv = greprefsFile->AppendNative(NS_LITERAL_CSTRING("greprefs.js"));
  1250     NS_ENSURE_SUCCESS(rv, rv);
  1252     rv = openPrefFile(greprefsFile);
  1253     if (NS_FAILED(rv))
  1254       NS_WARNING("Error parsing GRE default preferences. Is this an old-style embedding app?");
  1257   // Load $gre/defaults/pref/*.js
  1258   nsCOMPtr<nsIFile> defaultPrefDir;
  1260   rv = NS_GetSpecialDirectory(NS_APP_PREF_DEFAULTS_50_DIR, getter_AddRefs(defaultPrefDir));
  1261   NS_ENSURE_SUCCESS(rv, rv);
  1263   /* these pref file names should not be used: we process them after all other application pref files for backwards compatibility */
  1264   static const char* specialFiles[] = {
  1265 #if defined(XP_MACOSX)
  1266     "macprefs.js"
  1267 #elif defined(XP_WIN)
  1268     "winpref.js"
  1269 #elif defined(XP_UNIX)
  1270     "unix.js"
  1271 #if defined(VMS)
  1272     , "openvms.js"
  1273 #elif defined(_AIX)
  1274     , "aix.js"
  1275 #endif
  1276 #elif defined(XP_BEOS)
  1277     "beos.js"
  1278 #endif
  1279   };
  1281   rv = pref_LoadPrefsInDir(defaultPrefDir, specialFiles, ArrayLength(specialFiles));
  1282   if (NS_FAILED(rv))
  1283     NS_WARNING("Error parsing application default preferences.");
  1285   // Load jar:$app/omni.jar!/defaults/preferences/*.js
  1286   // or jar:$gre/omni.jar!/defaults/preferences/*.js.
  1287   nsRefPtr<nsZipArchive> appJarReader = mozilla::Omnijar::GetReader(mozilla::Omnijar::APP);
  1288   // GetReader(mozilla::Omnijar::APP) returns null when $app == $gre, in which
  1289   // case we look for app-specific default preferences in $gre.
  1290   if (!appJarReader)
  1291     appJarReader = mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE);
  1292   if (appJarReader) {
  1293     rv = appJarReader->FindInit("defaults/preferences/*.js$", &findPtr);
  1294     NS_ENSURE_SUCCESS(rv, rv);
  1295     find = findPtr;
  1296     prefEntries.Clear();
  1297     while (NS_SUCCEEDED(find->FindNext(&entryName, &entryNameLen))) {
  1298       prefEntries.AppendElement(Substring(entryName, entryNameLen));
  1300     prefEntries.Sort();
  1301     for (uint32_t i = prefEntries.Length(); i--; ) {
  1302       rv = pref_ReadPrefFromJar(appJarReader, prefEntries[i].get());
  1303       if (NS_FAILED(rv))
  1304         NS_WARNING("Error parsing preferences.");
  1308   rv = pref_LoadPrefsInDirList(NS_APP_PREFS_DEFAULTS_DIR_LIST);
  1309   NS_ENSURE_SUCCESS(rv, rv);
  1311   // Set up the correct default for toolkit.telemetry.enabled.
  1312   // If this build has MOZ_TELEMETRY_ON_BY_DEFAULT *or* we're on the beta
  1313   // channel, telemetry is on by default, otherwise not. This is necessary
  1314   // so that beta users who are testing final release builds don't flipflop
  1315   // defaults.
  1316   if (Preferences::GetDefaultType(kTelemetryPref) == PREF_INVALID) {
  1317     bool prerelease = false;
  1318 #ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
  1319     prerelease = true;
  1320 #else
  1321     if (Preferences::GetDefaultCString(kChannelPref).EqualsLiteral("beta")) {
  1322       prerelease = true;
  1324 #endif
  1325     PREF_SetBoolPref(kTelemetryPref, prerelease, true);
  1328   NS_CreateServicesFromCategory(NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID,
  1329                                 nullptr, NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID);
  1331   nsCOMPtr<nsIObserverService> observerService =
  1332     mozilla::services::GetObserverService();
  1333   if (!observerService)
  1334     return NS_ERROR_FAILURE;
  1336   observerService->NotifyObservers(nullptr, NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID, nullptr);
  1338   return pref_LoadPrefsInDirList(NS_EXT_PREFS_DEFAULTS_DIR_LIST);
  1342 /******************************************************************************
  1344  * static utilities
  1346  ******************************************************************************/
  1348 // static
  1349 nsresult
  1350 Preferences::GetBool(const char* aPref, bool* aResult)
  1352   NS_PRECONDITION(aResult, "aResult must not be NULL");
  1353   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1354   return PREF_GetBoolPref(aPref, aResult, false);
  1357 // static
  1358 nsresult
  1359 Preferences::GetInt(const char* aPref, int32_t* aResult)
  1361   NS_PRECONDITION(aResult, "aResult must not be NULL");
  1362   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1363   return PREF_GetIntPref(aPref, aResult, false);
  1366 // static
  1367 nsresult
  1368 Preferences::GetFloat(const char* aPref, float* aResult)
  1370   NS_PRECONDITION(aResult, "aResult must not be NULL");
  1371   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1372   nsAutoCString result;
  1373   nsresult rv = PREF_CopyCharPref(aPref, getter_Copies(result), false);
  1374   if (NS_SUCCEEDED(rv)) {
  1375     *aResult = result.ToFloat(&rv);
  1378   return rv;
  1381 // static
  1382 nsAdoptingCString
  1383 Preferences::GetCString(const char* aPref)
  1385   nsAdoptingCString result;
  1386   PREF_CopyCharPref(aPref, getter_Copies(result), false);
  1387   return result;
  1390 // static
  1391 nsAdoptingString
  1392 Preferences::GetString(const char* aPref)
  1394   nsAdoptingString result;
  1395   GetString(aPref, &result);
  1396   return result;
  1399 // static
  1400 nsresult
  1401 Preferences::GetCString(const char* aPref, nsACString* aResult)
  1403   NS_PRECONDITION(aResult, "aResult must not be NULL");
  1404   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1405   nsAutoCString result;
  1406   nsresult rv = PREF_CopyCharPref(aPref, getter_Copies(result), false);
  1407   if (NS_SUCCEEDED(rv)) {
  1408     *aResult = result;
  1410   return rv;
  1413 // static
  1414 nsresult
  1415 Preferences::GetString(const char* aPref, nsAString* aResult)
  1417   NS_PRECONDITION(aResult, "aResult must not be NULL");
  1418   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1419   nsAutoCString result;
  1420   nsresult rv = PREF_CopyCharPref(aPref, getter_Copies(result), false);
  1421   if (NS_SUCCEEDED(rv)) {
  1422     CopyUTF8toUTF16(result, *aResult);
  1424   return rv;
  1427 // static
  1428 nsAdoptingCString
  1429 Preferences::GetLocalizedCString(const char* aPref)
  1431   nsAdoptingCString result;
  1432   GetLocalizedCString(aPref, &result);
  1433   return result;
  1436 // static
  1437 nsAdoptingString
  1438 Preferences::GetLocalizedString(const char* aPref)
  1440   nsAdoptingString result;
  1441   GetLocalizedString(aPref, &result);
  1442   return result;
  1445 // static
  1446 nsresult
  1447 Preferences::GetLocalizedCString(const char* aPref, nsACString* aResult)
  1449   NS_PRECONDITION(aResult, "aResult must not be NULL");
  1450   nsAutoString result;
  1451   nsresult rv = GetLocalizedString(aPref, &result);
  1452   if (NS_SUCCEEDED(rv)) {
  1453     CopyUTF16toUTF8(result, *aResult);
  1455   return rv;
  1458 // static
  1459 nsresult
  1460 Preferences::GetLocalizedString(const char* aPref, nsAString* aResult)
  1462   NS_PRECONDITION(aResult, "aResult must not be NULL");
  1463   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1464   nsCOMPtr<nsIPrefLocalizedString> prefLocalString;
  1465   nsresult rv = sRootBranch->GetComplexValue(aPref,
  1466                                              NS_GET_IID(nsIPrefLocalizedString),
  1467                                              getter_AddRefs(prefLocalString));
  1468   if (NS_SUCCEEDED(rv)) {
  1469     NS_ASSERTION(prefLocalString, "Succeeded but the result is NULL");
  1470     prefLocalString->GetData(getter_Copies(*aResult));
  1472   return rv;
  1475 // static
  1476 nsresult
  1477 Preferences::GetComplex(const char* aPref, const nsIID &aType, void** aResult)
  1479   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1480   return sRootBranch->GetComplexValue(aPref, aType, aResult);
  1483 // static
  1484 nsresult
  1485 Preferences::SetCString(const char* aPref, const char* aValue)
  1487   ENSURE_MAIN_PROCESS("Cannot SetCString from content process:", aPref);
  1488   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1489   return PREF_SetCharPref(aPref, aValue, false);
  1492 // static
  1493 nsresult
  1494 Preferences::SetCString(const char* aPref, const nsACString &aValue)
  1496   ENSURE_MAIN_PROCESS("Cannot SetCString from content process:", aPref);
  1497   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1498   return PREF_SetCharPref(aPref, PromiseFlatCString(aValue).get(), false);
  1501 // static
  1502 nsresult
  1503 Preferences::SetString(const char* aPref, const char16_t* aValue)
  1505   ENSURE_MAIN_PROCESS("Cannot SetString from content process:", aPref);
  1506   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1507   return PREF_SetCharPref(aPref, NS_ConvertUTF16toUTF8(aValue).get(), false);
  1510 // static
  1511 nsresult
  1512 Preferences::SetString(const char* aPref, const nsAString &aValue)
  1514   ENSURE_MAIN_PROCESS("Cannot SetString from content process:", aPref);
  1515   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1516   return PREF_SetCharPref(aPref, NS_ConvertUTF16toUTF8(aValue).get(), false);
  1519 // static
  1520 nsresult
  1521 Preferences::SetBool(const char* aPref, bool aValue)
  1523   ENSURE_MAIN_PROCESS("Cannot SetBool from content process:", aPref);
  1524   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1525   return PREF_SetBoolPref(aPref, aValue, false);
  1528 // static
  1529 nsresult
  1530 Preferences::SetInt(const char* aPref, int32_t aValue)
  1532   ENSURE_MAIN_PROCESS("Cannot SetInt from content process:", aPref);
  1533   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1534   return PREF_SetIntPref(aPref, aValue, false);
  1537 // static
  1538 nsresult
  1539 Preferences::SetComplex(const char* aPref, const nsIID &aType,
  1540                         nsISupports* aValue)
  1542   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1543   return sRootBranch->SetComplexValue(aPref, aType, aValue);
  1546 // static
  1547 nsresult
  1548 Preferences::ClearUser(const char* aPref)
  1550   ENSURE_MAIN_PROCESS("Cannot ClearUser from content process:", aPref);
  1551   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1552   return PREF_ClearUserPref(aPref);
  1555 // static
  1556 bool
  1557 Preferences::HasUserValue(const char* aPref)
  1559   NS_ENSURE_TRUE(InitStaticMembers(), false);
  1560   return PREF_HasUserPref(aPref);
  1563 // static
  1564 int32_t
  1565 Preferences::GetType(const char* aPref)
  1567   NS_ENSURE_TRUE(InitStaticMembers(), nsIPrefBranch::PREF_INVALID);
  1568   int32_t result;
  1569   return NS_SUCCEEDED(sRootBranch->GetPrefType(aPref, &result)) ?
  1570     result : nsIPrefBranch::PREF_INVALID;
  1573 // static
  1574 nsresult
  1575 Preferences::AddStrongObserver(nsIObserver* aObserver,
  1576                                const char* aPref)
  1578   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1579   return sRootBranch->AddObserver(aPref, aObserver, false);
  1582 // static
  1583 nsresult
  1584 Preferences::AddWeakObserver(nsIObserver* aObserver,
  1585                              const char* aPref)
  1587   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1588   return sRootBranch->AddObserver(aPref, aObserver, true);
  1591 // static
  1592 nsresult
  1593 Preferences::RemoveObserver(nsIObserver* aObserver,
  1594                             const char* aPref)
  1596   if (!sPreferences && sShutdown) {
  1597     return NS_OK; // Observers have been released automatically.
  1599   NS_ENSURE_TRUE(sPreferences, NS_ERROR_NOT_AVAILABLE);
  1600   return sRootBranch->RemoveObserver(aPref, aObserver);
  1603 // static
  1604 nsresult
  1605 Preferences::AddStrongObservers(nsIObserver* aObserver,
  1606                                 const char** aPrefs)
  1608   for (uint32_t i = 0; aPrefs[i]; i++) {
  1609     nsresult rv = AddStrongObserver(aObserver, aPrefs[i]);
  1610     NS_ENSURE_SUCCESS(rv, rv);
  1612   return NS_OK;
  1615 // static
  1616 nsresult
  1617 Preferences::AddWeakObservers(nsIObserver* aObserver,
  1618                               const char** aPrefs)
  1620   for (uint32_t i = 0; aPrefs[i]; i++) {
  1621     nsresult rv = AddWeakObserver(aObserver, aPrefs[i]);
  1622     NS_ENSURE_SUCCESS(rv, rv);
  1624   return NS_OK;
  1627 // static
  1628 nsresult
  1629 Preferences::RemoveObservers(nsIObserver* aObserver,
  1630                              const char** aPrefs)
  1632   if (!sPreferences && sShutdown) {
  1633     return NS_OK; // Observers have been released automatically.
  1635   NS_ENSURE_TRUE(sPreferences, NS_ERROR_NOT_AVAILABLE);
  1637   for (uint32_t i = 0; aPrefs[i]; i++) {
  1638     nsresult rv = RemoveObserver(aObserver, aPrefs[i]);
  1639     NS_ENSURE_SUCCESS(rv, rv);
  1641   return NS_OK;
  1644 // static
  1645 nsresult
  1646 Preferences::RegisterCallback(PrefChangedFunc aCallback,
  1647                               const char* aPref,
  1648                               void* aClosure)
  1650   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1652   ValueObserverHashKey hashKey(aPref, aCallback);
  1653   nsRefPtr<ValueObserver> observer;
  1654   gObserverTable->Get(&hashKey, getter_AddRefs(observer));
  1655   if (observer) {
  1656     observer->AppendClosure(aClosure);
  1657     return NS_OK;
  1660   observer = new ValueObserver(aPref, aCallback);
  1661   observer->AppendClosure(aClosure);
  1662   nsresult rv = AddStrongObserver(observer, aPref);
  1663   NS_ENSURE_SUCCESS(rv, rv);
  1664   gObserverTable->Put(observer, observer);
  1665   return NS_OK;
  1668 // static
  1669 nsresult
  1670 Preferences::RegisterCallbackAndCall(PrefChangedFunc aCallback,
  1671                                      const char* aPref,
  1672                                      void* aClosure)
  1674   nsresult rv = RegisterCallback(aCallback, aPref, aClosure);
  1675   if (NS_SUCCEEDED(rv)) {
  1676     (*aCallback)(aPref, aClosure);
  1678   return rv;
  1681 // static
  1682 nsresult
  1683 Preferences::UnregisterCallback(PrefChangedFunc aCallback,
  1684                                 const char* aPref,
  1685                                 void* aClosure)
  1687   if (!sPreferences && sShutdown) {
  1688     return NS_OK; // Observers have been released automatically.
  1690   NS_ENSURE_TRUE(sPreferences, NS_ERROR_NOT_AVAILABLE);
  1692   ValueObserverHashKey hashKey(aPref, aCallback);
  1693   nsRefPtr<ValueObserver> observer;
  1694   gObserverTable->Get(&hashKey, getter_AddRefs(observer));
  1695   if (!observer) {
  1696     return NS_OK;
  1699   observer->RemoveClosure(aClosure);
  1700   if (observer->HasNoClosures()) {
  1701     // Delete the callback since its list of closures is empty.
  1702     gObserverTable->Remove(observer);
  1704   return NS_OK;
  1707 static void BoolVarChanged(const char* aPref, void* aClosure)
  1709   CacheData* cache = static_cast<CacheData*>(aClosure);
  1710   *((bool*)cache->cacheLocation) =
  1711     Preferences::GetBool(aPref, cache->defaultValueBool);
  1714 // static
  1715 nsresult
  1716 Preferences::AddBoolVarCache(bool* aCache,
  1717                              const char* aPref,
  1718                              bool aDefault)
  1720   NS_ASSERTION(aCache, "aCache must not be NULL");
  1721   *aCache = GetBool(aPref, aDefault);
  1722   CacheData* data = new CacheData();
  1723   data->cacheLocation = aCache;
  1724   data->defaultValueBool = aDefault;
  1725   gCacheData->AppendElement(data);
  1726   return RegisterCallback(BoolVarChanged, aPref, data);
  1729 static void IntVarChanged(const char* aPref, void* aClosure)
  1731   CacheData* cache = static_cast<CacheData*>(aClosure);
  1732   *((int32_t*)cache->cacheLocation) =
  1733     Preferences::GetInt(aPref, cache->defaultValueInt);
  1736 // static
  1737 nsresult
  1738 Preferences::AddIntVarCache(int32_t* aCache,
  1739                             const char* aPref,
  1740                             int32_t aDefault)
  1742   NS_ASSERTION(aCache, "aCache must not be NULL");
  1743   *aCache = Preferences::GetInt(aPref, aDefault);
  1744   CacheData* data = new CacheData();
  1745   data->cacheLocation = aCache;
  1746   data->defaultValueInt = aDefault;
  1747   gCacheData->AppendElement(data);
  1748   return RegisterCallback(IntVarChanged, aPref, data);
  1751 static void UintVarChanged(const char* aPref, void* aClosure)
  1753   CacheData* cache = static_cast<CacheData*>(aClosure);
  1754   *((uint32_t*)cache->cacheLocation) =
  1755     Preferences::GetUint(aPref, cache->defaultValueUint);
  1758 // static
  1759 nsresult
  1760 Preferences::AddUintVarCache(uint32_t* aCache,
  1761                              const char* aPref,
  1762                              uint32_t aDefault)
  1764   NS_ASSERTION(aCache, "aCache must not be NULL");
  1765   *aCache = Preferences::GetUint(aPref, aDefault);
  1766   CacheData* data = new CacheData();
  1767   data->cacheLocation = aCache;
  1768   data->defaultValueUint = aDefault;
  1769   gCacheData->AppendElement(data);
  1770   return RegisterCallback(UintVarChanged, aPref, data);
  1773 static void FloatVarChanged(const char* aPref, void* aClosure)
  1775   CacheData* cache = static_cast<CacheData*>(aClosure);
  1776   *((float*)cache->cacheLocation) =
  1777     Preferences::GetFloat(aPref, cache->defaultValueFloat);
  1780 // static
  1781 nsresult
  1782 Preferences::AddFloatVarCache(float* aCache,
  1783                              const char* aPref,
  1784                              float aDefault)
  1786   NS_ASSERTION(aCache, "aCache must not be NULL");
  1787   *aCache = Preferences::GetFloat(aPref, aDefault);
  1788   CacheData* data = new CacheData();
  1789   data->cacheLocation = aCache;
  1790   data->defaultValueFloat = aDefault;
  1791   gCacheData->AppendElement(data);
  1792   return RegisterCallback(FloatVarChanged, aPref, data);
  1795 // static
  1796 nsresult
  1797 Preferences::GetDefaultBool(const char* aPref, bool* aResult)
  1799   NS_PRECONDITION(aResult, "aResult must not be NULL");
  1800   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1801   return PREF_GetBoolPref(aPref, aResult, true);
  1804 // static
  1805 nsresult
  1806 Preferences::GetDefaultInt(const char* aPref, int32_t* aResult)
  1808   NS_PRECONDITION(aResult, "aResult must not be NULL");
  1809   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1810   return PREF_GetIntPref(aPref, aResult, true);
  1813 // static
  1814 nsresult
  1815 Preferences::GetDefaultCString(const char* aPref, nsACString* aResult)
  1817   NS_PRECONDITION(aResult, "aResult must not be NULL");
  1818   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1819   nsAutoCString result;
  1820   nsresult rv = PREF_CopyCharPref(aPref, getter_Copies(result), true);
  1821   if (NS_SUCCEEDED(rv)) {
  1822     *aResult = result;
  1824   return rv;
  1827 // static
  1828 nsresult
  1829 Preferences::GetDefaultString(const char* aPref, nsAString* aResult)
  1831   NS_PRECONDITION(aResult, "aResult must not be NULL");
  1832   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1833   nsAutoCString result;
  1834   nsresult rv = PREF_CopyCharPref(aPref, getter_Copies(result), true);
  1835   if (NS_SUCCEEDED(rv)) {
  1836     CopyUTF8toUTF16(result, *aResult);
  1838   return rv;
  1841 // static
  1842 nsresult
  1843 Preferences::GetDefaultLocalizedCString(const char* aPref,
  1844                                         nsACString* aResult)
  1846   nsAutoString result;
  1847   nsresult rv = GetDefaultLocalizedString(aPref, &result);
  1848   if (NS_SUCCEEDED(rv)) {
  1849     CopyUTF16toUTF8(result, *aResult);
  1851   return rv;
  1854 // static
  1855 nsresult
  1856 Preferences::GetDefaultLocalizedString(const char* aPref,
  1857                                        nsAString* aResult)
  1859   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1860   nsCOMPtr<nsIPrefLocalizedString> prefLocalString;
  1861   nsresult rv =
  1862     sDefaultRootBranch->GetComplexValue(aPref,
  1863                                         NS_GET_IID(nsIPrefLocalizedString),
  1864                                         getter_AddRefs(prefLocalString));
  1865   if (NS_SUCCEEDED(rv)) {
  1866     NS_ASSERTION(prefLocalString, "Succeeded but the result is NULL");
  1867     prefLocalString->GetData(getter_Copies(*aResult));
  1869   return rv;
  1872 // static
  1873 nsAdoptingString
  1874 Preferences::GetDefaultString(const char* aPref)
  1876   nsAdoptingString result;
  1877   GetDefaultString(aPref, &result);
  1878   return result;
  1881 // static
  1882 nsAdoptingCString
  1883 Preferences::GetDefaultCString(const char* aPref)
  1885   nsAdoptingCString result;
  1886   PREF_CopyCharPref(aPref, getter_Copies(result), true);
  1887   return result;
  1890 // static
  1891 nsAdoptingString
  1892 Preferences::GetDefaultLocalizedString(const char* aPref)
  1894   nsAdoptingString result;
  1895   GetDefaultLocalizedString(aPref, &result);
  1896   return result;
  1899 // static
  1900 nsAdoptingCString
  1901 Preferences::GetDefaultLocalizedCString(const char* aPref)
  1903   nsAdoptingCString result;
  1904   GetDefaultLocalizedCString(aPref, &result);
  1905   return result;
  1908 // static
  1909 nsresult
  1910 Preferences::GetDefaultComplex(const char* aPref, const nsIID &aType,
  1911                                void** aResult)
  1913   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1914   return sDefaultRootBranch->GetComplexValue(aPref, aType, aResult);
  1917 // static
  1918 int32_t
  1919 Preferences::GetDefaultType(const char* aPref)
  1921   NS_ENSURE_TRUE(InitStaticMembers(), nsIPrefBranch::PREF_INVALID);
  1922   int32_t result;
  1923   return NS_SUCCEEDED(sDefaultRootBranch->GetPrefType(aPref, &result)) ?
  1924     result : nsIPrefBranch::PREF_INVALID;
  1927 } // namespace mozilla
  1929 #undef ENSURE_MAIN_PROCESS

mercurial