1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014 |
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* 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 "mozilla/MemoryReporting.h"
- #include "mozilla/dom/ContentChild.h"
- #include "mozilla/ArrayUtils.h"
- #include "mozilla/Attributes.h"
- #include "mozilla/HashFunctions.h"
- #include "mozilla/UniquePtrExtensions.h"
- #include "nsXULAppAPI.h"
- #include "mozilla/Preferences.h"
- #include "nsAppDirectoryServiceDefs.h"
- #include "nsDataHashtable.h"
- #include "nsDirectoryServiceDefs.h"
- #include "nsICategoryManager.h"
- #include "nsCategoryManagerUtils.h"
- #include "nsNetUtil.h"
- #include "nsIFile.h"
- #include "nsIInputStream.h"
- #include "nsIObserverService.h"
- #include "nsIOutputStream.h"
- #include "nsISafeOutputStream.h"
- #include "nsISimpleEnumerator.h"
- #include "nsIStringEnumerator.h"
- #include "nsIZipReader.h"
- #include "nsPrefBranch.h"
- #include "nsXPIDLString.h"
- #include "nsCRT.h"
- #include "nsCOMArray.h"
- #include "nsXPCOMCID.h"
- #include "nsAutoPtr.h"
- #include "nsPrintfCString.h"
- #include "nsQuickSort.h"
- #include "PLDHashTable.h"
- #include "prefapi.h"
- #include "prefread.h"
- #include "prefapi_private_data.h"
- #include "mozilla/Omnijar.h"
- #include "nsZipArchive.h"
- #include "nsTArray.h"
- #include "nsRefPtrHashtable.h"
- #include "nsIMemoryReporter.h"
- #include "nsThreadUtils.h"
- #ifdef DEBUG
- #define ENSURE_MAIN_PROCESS(message, pref) do { \
- if (MOZ_UNLIKELY(!XRE_IsParentProcess())) { \
- nsPrintfCString msg("ENSURE_MAIN_PROCESS failed. %s %s", message, pref); \
- NS_WARNING(msg.get()); \
- return NS_ERROR_NOT_AVAILABLE; \
- } \
- } while (0);
- #else
- #define ENSURE_MAIN_PROCESS(message, pref) \
- if (MOZ_UNLIKELY(!XRE_IsParentProcess())) { \
- return NS_ERROR_NOT_AVAILABLE; \
- }
- #endif
- class PrefCallback;
- namespace mozilla {
- // Definitions
- #define INITIAL_PREF_FILES 10
- static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
- void
- Preferences::DirtyCallback()
- {
- if (gHashTable && sPreferences && !sPreferences->mDirty) {
- sPreferences->mDirty = true;
- }
- }
- // Prototypes
- static nsresult openPrefFile(nsIFile* aFile);
- static nsresult pref_InitInitialObjects(void);
- static nsresult pref_LoadPrefsInDirList(const char *listId);
- static nsresult ReadExtensionPrefs(nsIFile *aFile);
- static const char kTelemetryPref[] = "toolkit.telemetry.enabled";
- static const char kOldTelemetryPref[] = "toolkit.telemetry.enabledPreRelease";
- static const char kChannelPref[] = "app.update.channel";
- static const char kPrefFileHeader[] =
- "# Mozilla User Preferences"
- NS_LINEBREAK
- NS_LINEBREAK
- "/* Do not edit this file."
- NS_LINEBREAK
- " *"
- NS_LINEBREAK
- " * If you make changes to this file while the application is running,"
- NS_LINEBREAK
- " * the changes will be overwritten when the application exits."
- NS_LINEBREAK
- " *"
- NS_LINEBREAK
- " * To make a manual change to preferences, you can visit the URL about:config"
- NS_LINEBREAK
- " */"
- NS_LINEBREAK
- NS_LINEBREAK;
- Preferences* Preferences::sPreferences = nullptr;
- nsIPrefBranch* Preferences::sRootBranch = nullptr;
- nsIPrefBranch* Preferences::sDefaultRootBranch = nullptr;
- bool Preferences::sShutdown = false;
- class ValueObserverHashKey : public PLDHashEntryHdr {
- public:
- typedef ValueObserverHashKey* KeyType;
- typedef const ValueObserverHashKey* KeyTypePointer;
- static const ValueObserverHashKey* KeyToPointer(ValueObserverHashKey *aKey)
- {
- return aKey;
- }
- static PLDHashNumber HashKey(const ValueObserverHashKey *aKey)
- {
- PLDHashNumber hash = HashString(aKey->mPrefName);
- hash = AddToHash(hash, aKey->mMatchKind);
- return AddToHash(hash, aKey->mCallback);
- }
- ValueObserverHashKey(const char *aPref, PrefChangedFunc aCallback, Preferences::MatchKind aMatchKind) :
- mPrefName(aPref), mCallback(aCallback), mMatchKind(aMatchKind) { }
- explicit ValueObserverHashKey(const ValueObserverHashKey *aOther) :
- mPrefName(aOther->mPrefName),
- mCallback(aOther->mCallback),
- mMatchKind(aOther->mMatchKind)
- { }
- bool KeyEquals(const ValueObserverHashKey *aOther) const
- {
- return mCallback == aOther->mCallback &&
- mPrefName == aOther->mPrefName &&
- mMatchKind == aOther->mMatchKind;
- }
- ValueObserverHashKey *GetKey() const
- {
- return const_cast<ValueObserverHashKey*>(this);
- }
- enum { ALLOW_MEMMOVE = true };
- nsCString mPrefName;
- PrefChangedFunc mCallback;
- Preferences::MatchKind mMatchKind;
- };
- class ValueObserver final : public nsIObserver,
- public ValueObserverHashKey
- {
- ~ValueObserver() {
- Preferences::RemoveObserver(this, mPrefName.get());
- }
- public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIOBSERVER
- ValueObserver(const char *aPref, PrefChangedFunc aCallback, Preferences::MatchKind aMatchKind)
- : ValueObserverHashKey(aPref, aCallback, aMatchKind) { }
- void AppendClosure(void *aClosure) {
- mClosures.AppendElement(aClosure);
- }
- void RemoveClosure(void *aClosure) {
- mClosures.RemoveElement(aClosure);
- }
- bool HasNoClosures() {
- return mClosures.Length() == 0;
- }
- nsTArray<void*> mClosures;
- };
- NS_IMPL_ISUPPORTS(ValueObserver, nsIObserver)
- NS_IMETHODIMP
- ValueObserver::Observe(nsISupports *aSubject,
- const char *aTopic,
- const char16_t *aData)
- {
- NS_ASSERTION(!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID),
- "invalid topic");
- NS_ConvertUTF16toUTF8 data(aData);
- if (mMatchKind == Preferences::ExactMatch && !mPrefName.EqualsASCII(data.get())) {
- return NS_OK;
- }
- for (uint32_t i = 0; i < mClosures.Length(); i++) {
- mCallback(data.get(), mClosures.ElementAt(i));
- }
- return NS_OK;
- }
- struct CacheData {
- void* cacheLocation;
- union {
- bool defaultValueBool;
- int32_t defaultValueInt;
- uint32_t defaultValueUint;
- float defaultValueFloat;
- };
- };
- static nsTArray<nsAutoPtr<CacheData> >* gCacheData = nullptr;
- static nsRefPtrHashtable<ValueObserverHashKey,
- ValueObserver>* gObserverTable = nullptr;
- #ifdef DEBUG
- static bool
- HaveExistingCacheFor(void* aPtr)
- {
- MOZ_ASSERT(NS_IsMainThread());
- if (gCacheData) {
- for (size_t i = 0, count = gCacheData->Length(); i < count; ++i) {
- if ((*gCacheData)[i]->cacheLocation == aPtr) {
- return true;
- }
- }
- }
- return false;
- }
- static void
- AssertNotAlreadyCached(const char* aPrefType,
- const char* aPref,
- void* aPtr)
- {
- if (HaveExistingCacheFor(aPtr)) {
- fprintf_stderr(stderr,
- "Attempt to add a %s pref cache for preference '%s' at address '%p'"
- "was made. However, a pref was already cached at this address.\n",
- aPrefType, aPref, aPtr);
- MOZ_ASSERT(false, "Should not have an existing pref cache for this address");
- }
- }
- #endif
- static void
- ReportToConsole(const char* aMessage, int aLine, bool aError)
- {
- nsPrintfCString message("** Preference parsing %s (line %d) = %s **\n",
- (aError ? "error" : "warning"), aLine, aMessage);
- nsPrefBranch::ReportToConsole(NS_ConvertUTF8toUTF16(message.get()));
- }
- // Although this is a member of Preferences, it measures sPreferences and
- // several other global structures.
- /* static */ int64_t
- Preferences::SizeOfIncludingThisAndOtherStuff(mozilla::MallocSizeOf aMallocSizeOf)
- {
- NS_ENSURE_TRUE(InitStaticMembers(), 0);
- size_t n = aMallocSizeOf(sPreferences);
- if (gHashTable) {
- // pref keys are allocated in a private arena, which we count elsewhere.
- // pref stringvals are allocated out of the same private arena.
- n += gHashTable->ShallowSizeOfIncludingThis(aMallocSizeOf);
- }
- if (gCacheData) {
- n += gCacheData->ShallowSizeOfIncludingThis(aMallocSizeOf);
- for (uint32_t i = 0, count = gCacheData->Length(); i < count; ++i) {
- n += aMallocSizeOf((*gCacheData)[i]);
- }
- }
- if (gObserverTable) {
- n += gObserverTable->ShallowSizeOfIncludingThis(aMallocSizeOf);
- for (auto iter = gObserverTable->Iter(); !iter.Done(); iter.Next()) {
- n += iter.Key()->mPrefName.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
- n += iter.Data()->mClosures.ShallowSizeOfExcludingThis(aMallocSizeOf);
- }
- }
- if (sRootBranch) {
- n += reinterpret_cast<nsPrefBranch*>(sRootBranch)->SizeOfIncludingThis(aMallocSizeOf);
- }
- if (sDefaultRootBranch) {
- n += reinterpret_cast<nsPrefBranch*>(sDefaultRootBranch)->SizeOfIncludingThis(aMallocSizeOf);
- }
- n += pref_SizeOfPrivateData(aMallocSizeOf);
- return n;
- }
- class PreferenceServiceReporter final : public nsIMemoryReporter
- {
- ~PreferenceServiceReporter() {}
- public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIMEMORYREPORTER
- protected:
- static const uint32_t kSuspectReferentCount = 1000;
- };
- NS_IMPL_ISUPPORTS(PreferenceServiceReporter, nsIMemoryReporter)
- MOZ_DEFINE_MALLOC_SIZE_OF(PreferenceServiceMallocSizeOf)
- NS_IMETHODIMP
- PreferenceServiceReporter::CollectReports(
- nsIHandleReportCallback* aHandleReport, nsISupports* aData, bool aAnonymize)
- {
- MOZ_COLLECT_REPORT(
- "explicit/preferences", KIND_HEAP, UNITS_BYTES,
- Preferences::SizeOfIncludingThisAndOtherStuff(PreferenceServiceMallocSizeOf),
- "Memory used by the preferences system.");
- nsPrefBranch* rootBranch =
- static_cast<nsPrefBranch*>(Preferences::GetRootBranch());
- if (!rootBranch) {
- return NS_OK;
- }
- size_t numStrong = 0;
- size_t numWeakAlive = 0;
- size_t numWeakDead = 0;
- nsTArray<nsCString> suspectPreferences;
- // Count of the number of referents for each preference.
- nsDataHashtable<nsCStringHashKey, uint32_t> prefCounter;
- for (auto iter = rootBranch->mObservers.Iter(); !iter.Done(); iter.Next()) {
- nsAutoPtr<PrefCallback>& callback = iter.Data();
- nsPrefBranch* prefBranch = callback->GetPrefBranch();
- const char* pref = prefBranch->getPrefName(callback->GetDomain().get());
- if (callback->IsWeak()) {
- nsCOMPtr<nsIObserver> callbackRef = do_QueryReferent(callback->mWeakRef);
- if (callbackRef) {
- numWeakAlive++;
- } else {
- numWeakDead++;
- }
- } else {
- numStrong++;
- }
- nsDependentCString prefString(pref);
- uint32_t oldCount = 0;
- prefCounter.Get(prefString, &oldCount);
- uint32_t currentCount = oldCount + 1;
- prefCounter.Put(prefString, currentCount);
- // Keep track of preferences that have a suspiciously large number of
- // referents (a symptom of a leak).
- if (currentCount == kSuspectReferentCount) {
- suspectPreferences.AppendElement(prefString);
- }
- }
- for (uint32_t i = 0; i < suspectPreferences.Length(); i++) {
- nsCString& suspect = suspectPreferences[i];
- uint32_t totalReferentCount = 0;
- prefCounter.Get(suspect, &totalReferentCount);
- nsPrintfCString suspectPath("preference-service-suspect/"
- "referent(pref=%s)", suspect.get());
- aHandleReport->Callback(
- /* process = */ EmptyCString(),
- suspectPath, KIND_OTHER, UNITS_COUNT, totalReferentCount,
- NS_LITERAL_CSTRING(
- "A preference with a suspiciously large number referents (symptom of a "
- "leak)."),
- aData);
- }
- MOZ_COLLECT_REPORT(
- "preference-service/referent/strong", KIND_OTHER, UNITS_COUNT,
- numStrong,
- "The number of strong referents held by the preference service.");
- MOZ_COLLECT_REPORT(
- "preference-service/referent/weak/alive", KIND_OTHER, UNITS_COUNT,
- numWeakAlive,
- "The number of weak referents held by the preference service that are "
- "still alive.");
- MOZ_COLLECT_REPORT(
- "preference-service/referent/weak/dead", KIND_OTHER, UNITS_COUNT,
- numWeakDead,
- "The number of weak referents held by the preference service that are "
- "dead.");
- return NS_OK;
- }
- namespace {
- class AddPreferencesMemoryReporterRunnable : public Runnable
- {
- NS_IMETHOD Run() override
- {
- return RegisterStrongMemoryReporter(new PreferenceServiceReporter());
- }
- };
- } // namespace
- // static
- Preferences*
- Preferences::GetInstanceForService()
- {
- if (sPreferences) {
- NS_ADDREF(sPreferences);
- return sPreferences;
- }
- NS_ENSURE_TRUE(!sShutdown, nullptr);
- sRootBranch = new nsPrefBranch("", false);
- NS_ADDREF(sRootBranch);
- sDefaultRootBranch = new nsPrefBranch("", true);
- NS_ADDREF(sDefaultRootBranch);
- sPreferences = new Preferences();
- NS_ADDREF(sPreferences);
- if (NS_FAILED(sPreferences->Init())) {
- // The singleton instance will delete sRootBranch and sDefaultRootBranch.
- NS_RELEASE(sPreferences);
- return nullptr;
- }
- gCacheData = new nsTArray<nsAutoPtr<CacheData> >();
- gObserverTable = new nsRefPtrHashtable<ValueObserverHashKey, ValueObserver>();
- // Preferences::GetInstanceForService() can be called from GetService(), and
- // RegisterStrongMemoryReporter calls GetService(nsIMemoryReporter). To
- // avoid a potential recursive GetService() call, we can't register the
- // memory reporter here; instead, do it off a runnable.
- RefPtr<AddPreferencesMemoryReporterRunnable> runnable =
- new AddPreferencesMemoryReporterRunnable();
- NS_DispatchToMainThread(runnable);
- NS_ADDREF(sPreferences);
- return sPreferences;
- }
- // static
- bool
- Preferences::IsServiceAvailable()
- {
- return !!sPreferences;
- }
- // static
- bool
- Preferences::InitStaticMembers()
- {
- MOZ_ASSERT(NS_IsMainThread());
- if (!sShutdown && !sPreferences) {
- nsCOMPtr<nsIPrefService> prefService =
- do_GetService(NS_PREFSERVICE_CONTRACTID);
- }
- return sPreferences != nullptr;
- }
- // static
- void
- Preferences::Shutdown()
- {
- if (!sShutdown) {
- sShutdown = true; // Don't create the singleton instance after here.
- // Don't set sPreferences to nullptr here. The instance may be grabbed by
- // other modules. The utility methods of Preferences should be available
- // until the singleton instance actually released.
- if (sPreferences) {
- sPreferences->Release();
- }
- }
- }
- //-----------------------------------------------------------------------------
- /*
- * Constructor/Destructor
- */
- Preferences::Preferences()
- : mDirty(false)
- {
- }
- Preferences::~Preferences()
- {
- NS_ASSERTION(sPreferences == this, "Isn't this the singleton instance?");
- delete gObserverTable;
- gObserverTable = nullptr;
- delete gCacheData;
- gCacheData = nullptr;
- NS_RELEASE(sRootBranch);
- NS_RELEASE(sDefaultRootBranch);
- sPreferences = nullptr;
- PREF_Cleanup();
- }
- /*
- * nsISupports Implementation
- */
- NS_IMPL_ADDREF(Preferences)
- NS_IMPL_RELEASE(Preferences)
- NS_INTERFACE_MAP_BEGIN(Preferences)
- NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPrefService)
- NS_INTERFACE_MAP_ENTRY(nsIPrefService)
- NS_INTERFACE_MAP_ENTRY(nsIObserver)
- NS_INTERFACE_MAP_ENTRY(nsIPrefBranch)
- NS_INTERFACE_MAP_ENTRY(nsIPrefBranch2)
- NS_INTERFACE_MAP_ENTRY(nsIPrefBranchInternal)
- NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
- NS_INTERFACE_MAP_END
- /*
- * nsIPrefService Implementation
- */
- nsresult
- Preferences::Init()
- {
- nsresult rv;
- PREF_SetDirtyCallback(&DirtyCallback);
- PREF_Init();
- rv = pref_InitInitialObjects();
- NS_ENSURE_SUCCESS(rv, rv);
- using mozilla::dom::ContentChild;
- if (XRE_IsContentProcess()) {
- InfallibleTArray<PrefSetting> prefs;
- ContentChild::GetSingleton()->SendReadPrefsArray(&prefs);
- // Store the array
- for (uint32_t i = 0; i < prefs.Length(); ++i) {
- pref_SetPref(prefs[i]);
- }
- return NS_OK;
- }
- nsXPIDLCString lockFileName;
- /*
- * The following is a small hack which will allow us to only load the library
- * which supports the netscape.cfg file if the preference is defined. We
- * test for the existence of the pref, set in the all.js (mozilla) or
- * all-ns.js (netscape 6), and if it exists we startup the pref config
- * category which will do the rest.
- */
- rv = PREF_CopyCharPref("general.config.filename", getter_Copies(lockFileName), false);
- if (NS_SUCCEEDED(rv))
- NS_CreateServicesFromCategory("pref-config-startup",
- static_cast<nsISupports *>(static_cast<void *>(this)),
- "pref-config-startup");
- nsCOMPtr<nsIObserverService> observerService =
- mozilla::services::GetObserverService();
- if (!observerService)
- return NS_ERROR_FAILURE;
- rv = observerService->AddObserver(this, "profile-before-change", true);
- observerService->AddObserver(this, "load-extension-defaults", true);
- observerService->AddObserver(this, "suspend_process_notification", true);
- return(rv);
- }
- // static
- nsresult
- Preferences::ResetAndReadUserPrefs()
- {
- sPreferences->ResetUserPrefs();
- return sPreferences->ReadUserPrefs(nullptr);
- }
- NS_IMETHODIMP
- Preferences::Observe(nsISupports *aSubject, const char *aTopic,
- const char16_t *someData)
- {
- if (XRE_IsContentProcess())
- return NS_ERROR_NOT_AVAILABLE;
- nsresult rv = NS_OK;
- if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
- rv = SavePrefFile(nullptr);
- } else if (!strcmp(aTopic, "load-extension-defaults")) {
- pref_LoadPrefsInDirList(NS_EXT_PREFS_DEFAULTS_DIR_LIST);
- } else if (!nsCRT::strcmp(aTopic, "reload-default-prefs")) {
- // Reload the default prefs from file.
- pref_InitInitialObjects();
- } else if (!nsCRT::strcmp(aTopic, "suspend_process_notification")) {
- // Our process is being suspended. The OS may wake our process later,
- // or it may kill the process. In case our process is going to be killed
- // from the suspended state, we save preferences before suspending.
- rv = SavePrefFile(nullptr);
- }
- return rv;
- }
- NS_IMETHODIMP
- Preferences::ReadUserPrefs(nsIFile *aFile)
- {
- if (XRE_IsContentProcess()) {
- NS_ERROR("cannot load prefs from content process");
- return NS_ERROR_NOT_AVAILABLE;
- }
- nsresult rv;
- if (nullptr == aFile) {
- rv = UseDefaultPrefFile();
- // A user pref file is optional.
- // Ignore all errors related to it, so we retain 'rv' value :-|
- (void) UseUserPrefFile();
- // Migrate the old prerelease telemetry pref
- if (!Preferences::GetBool(kOldTelemetryPref, true)) {
- Preferences::SetBool(kTelemetryPref, false);
- Preferences::ClearUser(kOldTelemetryPref);
- }
- NotifyServiceObservers(NS_PREFSERVICE_READ_TOPIC_ID);
- } else {
- rv = ReadAndOwnUserPrefFile(aFile);
- }
- return rv;
- }
- NS_IMETHODIMP
- Preferences::ResetPrefs()
- {
- if (XRE_IsContentProcess()) {
- NS_ERROR("cannot reset prefs from content process");
- return NS_ERROR_NOT_AVAILABLE;
- }
- NotifyServiceObservers(NS_PREFSERVICE_RESET_TOPIC_ID);
- PREF_CleanupPrefs();
- PREF_Init();
- return pref_InitInitialObjects();
- }
- NS_IMETHODIMP
- Preferences::ResetUserPrefs()
- {
- if (XRE_IsContentProcess()) {
- NS_ERROR("cannot reset user prefs from content process");
- return NS_ERROR_NOT_AVAILABLE;
- }
- PREF_ClearAllUserPrefs();
- return NS_OK;
- }
- NS_IMETHODIMP
- Preferences::SavePrefFile(nsIFile *aFile)
- {
- if (XRE_IsContentProcess()) {
- NS_ERROR("cannot save pref file from content process");
- return NS_ERROR_NOT_AVAILABLE;
- }
- return SavePrefFileInternal(aFile);
- }
- static nsresult
- ReadExtensionPrefs(nsIFile *aFile)
- {
- nsresult rv;
- nsCOMPtr<nsIZipReader> reader = do_CreateInstance(kZipReaderCID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = reader->Open(aFile);
- NS_ENSURE_SUCCESS(rv, rv);
- nsCOMPtr<nsIUTF8StringEnumerator> files;
- rv = reader->FindEntries(nsDependentCString("defaults/preferences/*.(J|j)(S|s)$"),
- getter_AddRefs(files));
- NS_ENSURE_SUCCESS(rv, rv);
- char buffer[4096];
- bool more;
- while (NS_SUCCEEDED(rv = files->HasMore(&more)) && more) {
- nsAutoCString entry;
- rv = files->GetNext(entry);
- NS_ENSURE_SUCCESS(rv, rv);
- nsCOMPtr<nsIInputStream> stream;
- rv = reader->GetInputStream(entry, getter_AddRefs(stream));
- NS_ENSURE_SUCCESS(rv, rv);
- uint64_t avail;
- uint32_t read;
- PrefParseState ps;
- PREF_InitParseState(&ps, PREF_ReaderCallback, ReportToConsole, nullptr);
- while (NS_SUCCEEDED(rv = stream->Available(&avail)) && avail) {
- rv = stream->Read(buffer, 4096, &read);
- if (NS_FAILED(rv)) {
- NS_WARNING("Pref stream read failed");
- break;
- }
- PREF_ParseBuf(&ps, buffer, read);
- }
- PREF_FinalizeParseState(&ps);
- }
- return rv;
- }
- void
- Preferences::SetPreference(const PrefSetting& aPref)
- {
- pref_SetPref(aPref);
- }
- void
- Preferences::GetPreference(PrefSetting* aPref)
- {
- PrefHashEntry *entry = pref_HashTableLookup(aPref->name().get());
- if (!entry)
- return;
- if (pref_EntryHasAdvisablySizedValues(entry)) {
- pref_GetPrefFromEntry(entry, aPref);
- }
- }
- void
- Preferences::GetPreferences(InfallibleTArray<PrefSetting>* aPrefs)
- {
- aPrefs->SetCapacity(gHashTable->Capacity());
- for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
- auto entry = static_cast<PrefHashEntry*>(iter.Get());
- if (!pref_EntryHasAdvisablySizedValues(entry)) {
- continue;
- }
- dom::PrefSetting *pref = aPrefs->AppendElement();
- pref_GetPrefFromEntry(entry, pref);
- }
- }
- NS_IMETHODIMP
- Preferences::GetBranch(const char *aPrefRoot, nsIPrefBranch **_retval)
- {
- nsresult rv;
- if ((nullptr != aPrefRoot) && (*aPrefRoot != '\0')) {
- // TODO: - cache this stuff and allow consumers to share branches (hold weak references I think)
- RefPtr<nsPrefBranch> prefBranch = new nsPrefBranch(aPrefRoot, false);
- prefBranch.forget(_retval);
- rv = NS_OK;
- } else {
- // special case caching the default root
- nsCOMPtr<nsIPrefBranch> root(sRootBranch);
- root.forget(_retval);
- rv = NS_OK;
- }
- return rv;
- }
- NS_IMETHODIMP
- Preferences::GetDefaultBranch(const char *aPrefRoot, nsIPrefBranch **_retval)
- {
- if (!aPrefRoot || !aPrefRoot[0]) {
- nsCOMPtr<nsIPrefBranch> root(sDefaultRootBranch);
- root.forget(_retval);
- return NS_OK;
- }
- // TODO: - cache this stuff and allow consumers to share branches (hold weak references I think)
- RefPtr<nsPrefBranch> prefBranch = new nsPrefBranch(aPrefRoot, true);
- if (!prefBranch)
- return NS_ERROR_OUT_OF_MEMORY;
- prefBranch.forget(_retval);
- return NS_OK;
- }
- NS_IMETHODIMP
- Preferences::GetDirty(bool *_retval) {
- *_retval = mDirty;
- return NS_OK;
- }
- nsresult
- Preferences::NotifyServiceObservers(const char *aTopic)
- {
- nsCOMPtr<nsIObserverService> observerService =
- mozilla::services::GetObserverService();
- if (!observerService)
- return NS_ERROR_FAILURE;
- nsISupports *subject = (nsISupports *)((nsIPrefService *)this);
- observerService->NotifyObservers(subject, aTopic, nullptr);
-
- return NS_OK;
- }
- nsresult
- Preferences::UseDefaultPrefFile()
- {
- nsCOMPtr<nsIFile> aFile;
- nsresult rv = NS_GetSpecialDirectory(NS_APP_PREFS_50_FILE, getter_AddRefs(aFile));
- if (NS_SUCCEEDED(rv)) {
- rv = ReadAndOwnUserPrefFile(aFile);
- // Most likely cause of failure here is that the file didn't
- // exist, so save a new one. mUserPrefReadFailed will be
- // used to catch an error in actually reading the file.
- if (NS_FAILED(rv)) {
- if (NS_FAILED(SavePrefFileInternal(aFile)))
- NS_ERROR("Failed to save new shared pref file");
- else
- rv = NS_OK;
- }
- }
-
- return rv;
- }
- nsresult
- Preferences::UseUserPrefFile()
- {
- nsresult rv = NS_OK;
- nsCOMPtr<nsIFile> aFile;
- nsDependentCString prefsDirProp(NS_APP_PREFS_50_DIR);
- rv = NS_GetSpecialDirectory(prefsDirProp.get(), getter_AddRefs(aFile));
- if (NS_SUCCEEDED(rv) && aFile) {
- rv = aFile->AppendNative(NS_LITERAL_CSTRING("user.js"));
- if (NS_SUCCEEDED(rv)) {
- bool exists = false;
- aFile->Exists(&exists);
- if (exists) {
- rv = openPrefFile(aFile);
- } else {
- rv = NS_ERROR_FILE_NOT_FOUND;
- }
- }
- }
- return rv;
- }
- nsresult
- Preferences::MakeBackupPrefFile(nsIFile *aFile)
- {
- // Example: this copies "prefs.js" to "Invalidprefs.js" in the same directory.
- // "Invalidprefs.js" is removed if it exists, prior to making the copy.
- nsAutoString newFilename;
- nsresult rv = aFile->GetLeafName(newFilename);
- NS_ENSURE_SUCCESS(rv, rv);
- newFilename.Insert(NS_LITERAL_STRING("Invalid"), 0);
- nsCOMPtr<nsIFile> newFile;
- rv = aFile->GetParent(getter_AddRefs(newFile));
- NS_ENSURE_SUCCESS(rv, rv);
- rv = newFile->Append(newFilename);
- NS_ENSURE_SUCCESS(rv, rv);
- bool exists = false;
- newFile->Exists(&exists);
- if (exists) {
- rv = newFile->Remove(false);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- rv = aFile->CopyTo(nullptr, newFilename);
- NS_ENSURE_SUCCESS(rv, rv);
- return rv;
- }
- nsresult
- Preferences::ReadAndOwnUserPrefFile(nsIFile *aFile)
- {
- NS_ENSURE_ARG(aFile);
-
- if (mCurrentFile == aFile)
- return NS_OK;
- mCurrentFile = aFile;
- nsresult rv = NS_OK;
- bool exists = false;
- mCurrentFile->Exists(&exists);
- if (exists) {
- rv = openPrefFile(mCurrentFile);
- if (NS_FAILED(rv)) {
- // Save a backup copy of the current (invalid) prefs file, since all prefs
- // from the error line to the end of the file will be lost (bug 361102).
- // TODO we should notify the user about it (bug 523725).
- MakeBackupPrefFile(mCurrentFile);
- }
- } else {
- rv = NS_ERROR_FILE_NOT_FOUND;
- }
- return rv;
- }
- nsresult
- Preferences::SavePrefFileInternal(nsIFile *aFile)
- {
- if (nullptr == aFile) {
- // the mDirty flag tells us if we should write to mCurrentFile
- // we only check this flag when the caller wants to write to the default
- if (!mDirty) {
- return NS_OK;
- }
- // It's possible that we never got a prefs file.
- nsresult rv = NS_OK;
- if (mCurrentFile)
- rv = WritePrefFile(mCurrentFile);
- return rv;
- } else {
- return WritePrefFile(aFile);
- }
- }
- nsresult
- Preferences::WritePrefFile(nsIFile* aFile)
- {
- nsCOMPtr<nsIOutputStream> outStreamSink;
- nsCOMPtr<nsIOutputStream> outStream;
- uint32_t writeAmount;
- nsresult rv;
- if (!gHashTable)
- return NS_ERROR_NOT_INITIALIZED;
- // execute a "safe" save by saving through a tempfile
- rv = NS_NewSafeLocalFileOutputStream(getter_AddRefs(outStreamSink),
- aFile,
- -1,
- 0600);
- if (NS_FAILED(rv))
- return rv;
- rv = NS_NewBufferedOutputStream(getter_AddRefs(outStream), outStreamSink, 4096);
- if (NS_FAILED(rv))
- return rv;
- // get the lines that we're supposed to be writing to the file
- uint32_t prefCount;
- UniquePtr<char*[]> valueArray = pref_savePrefs(gHashTable, &prefCount);
- /* Sort the preferences to make a readable file on disk */
- NS_QuickSort(valueArray.get(), prefCount, sizeof(char *),
- pref_CompareStrings, nullptr);
- // write out the file header
- outStream->Write(kPrefFileHeader, sizeof(kPrefFileHeader) - 1, &writeAmount);
- for (uint32_t valueIdx = 0; valueIdx < prefCount; valueIdx++) {
- char*& pref = valueArray[valueIdx];
- MOZ_ASSERT(pref);
- outStream->Write(pref, strlen(pref), &writeAmount);
- outStream->Write(NS_LINEBREAK, NS_LINEBREAK_LEN, &writeAmount);
- free(pref);
- pref = nullptr;
- }
- // tell the safe output stream to overwrite the real prefs file
- // (it'll abort if there were any errors during writing)
- nsCOMPtr<nsISafeOutputStream> safeStream = do_QueryInterface(outStream);
- NS_ASSERTION(safeStream, "expected a safe output stream!");
- if (safeStream) {
- rv = safeStream->Finish();
- if (NS_FAILED(rv)) {
- NS_WARNING("failed to save prefs file! possible data loss");
- return rv;
- }
- }
- mDirty = false;
- return NS_OK;
- }
- static nsresult openPrefFile(nsIFile* aFile)
- {
- nsCOMPtr<nsIInputStream> inStr;
- nsresult rv = NS_NewLocalFileInputStream(getter_AddRefs(inStr), aFile);
- if (NS_FAILED(rv))
- return rv;
- int64_t fileSize64;
- rv = aFile->GetFileSize(&fileSize64);
- if (NS_FAILED(rv))
- return rv;
- NS_ENSURE_TRUE(fileSize64 <= UINT32_MAX, NS_ERROR_FILE_TOO_BIG);
- uint32_t fileSize = (uint32_t)fileSize64;
- auto fileBuffer = MakeUniqueFallible<char[]>(fileSize);
- if (fileBuffer == nullptr)
- return NS_ERROR_OUT_OF_MEMORY;
- PrefParseState ps;
- PREF_InitParseState(&ps, PREF_ReaderCallback, ReportToConsole, nullptr);
- // Read is not guaranteed to return a buf the size of fileSize,
- // but usually will.
- nsresult rv2 = NS_OK;
- uint32_t offset = 0;
- for (;;) {
- uint32_t amtRead = 0;
- rv = inStr->Read(fileBuffer.get(), fileSize, &amtRead);
- if (NS_FAILED(rv) || amtRead == 0)
- break;
- if (!PREF_ParseBuf(&ps, fileBuffer.get(), amtRead))
- rv2 = NS_ERROR_FILE_CORRUPTED;
- offset += amtRead;
- if (offset == fileSize) {
- break;
- }
- }
- PREF_FinalizeParseState(&ps);
- return NS_FAILED(rv) ? rv : rv2;
- }
- /*
- * some stuff that gets called from Pref_Init()
- */
- static int
- pref_CompareFileNames(nsIFile* aFile1, nsIFile* aFile2, void* /*unused*/)
- {
- nsAutoCString filename1, filename2;
- aFile1->GetNativeLeafName(filename1);
- aFile2->GetNativeLeafName(filename2);
- return Compare(filename2, filename1);
- }
- /**
- * Load default pref files from a directory. The files in the
- * directory are sorted reverse-alphabetically; a set of "special file
- * names" may be specified which are loaded after all the others.
- */
- static nsresult
- pref_LoadPrefsInDir(nsIFile* aDir, char const *const *aSpecialFiles, uint32_t aSpecialFilesCount)
- {
- nsresult rv, rv2;
- bool hasMoreElements;
- nsCOMPtr<nsISimpleEnumerator> dirIterator;
- // this may fail in some normal cases, such as embedders who do not use a GRE
- rv = aDir->GetDirectoryEntries(getter_AddRefs(dirIterator));
- if (NS_FAILED(rv)) {
- // If the directory doesn't exist, then we have no reason to complain. We
- // loaded everything (and nothing) successfully.
- if (rv == NS_ERROR_FILE_NOT_FOUND || rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST)
- rv = NS_OK;
- return rv;
- }
- rv = dirIterator->HasMoreElements(&hasMoreElements);
- NS_ENSURE_SUCCESS(rv, rv);
- nsCOMArray<nsIFile> prefFiles(INITIAL_PREF_FILES);
- nsCOMArray<nsIFile> specialFiles(aSpecialFilesCount);
- nsCOMPtr<nsIFile> prefFile;
- while (hasMoreElements && NS_SUCCEEDED(rv)) {
- nsAutoCString leafName;
- nsCOMPtr<nsISupports> supports;
- rv = dirIterator->GetNext(getter_AddRefs(supports));
- prefFile = do_QueryInterface(supports);
- if (NS_FAILED(rv)) {
- break;
- }
- prefFile->GetNativeLeafName(leafName);
- NS_ASSERTION(!leafName.IsEmpty(), "Failure in default prefs: directory enumerator returned empty file?");
- // Skip non-js files
- if (StringEndsWith(leafName, NS_LITERAL_CSTRING(".js"),
- nsCaseInsensitiveCStringComparator())) {
- bool shouldParse = true;
- // separate out special files
- for (uint32_t i = 0; i < aSpecialFilesCount; ++i) {
- if (leafName.Equals(nsDependentCString(aSpecialFiles[i]))) {
- shouldParse = false;
- // special files should be process in order; we put them into
- // the array by index; this can make the array sparse
- specialFiles.ReplaceObjectAt(prefFile, i);
- }
- }
- if (shouldParse) {
- prefFiles.AppendObject(prefFile);
- }
- }
- rv = dirIterator->HasMoreElements(&hasMoreElements);
- }
- if (prefFiles.Count() + specialFiles.Count() == 0) {
- NS_WARNING("No default pref files found.");
- if (NS_SUCCEEDED(rv)) {
- rv = NS_SUCCESS_FILE_DIRECTORY_EMPTY;
- }
- return rv;
- }
- prefFiles.Sort(pref_CompareFileNames, nullptr);
-
- uint32_t arrayCount = prefFiles.Count();
- uint32_t i;
- for (i = 0; i < arrayCount; ++i) {
- rv2 = openPrefFile(prefFiles[i]);
- if (NS_FAILED(rv2)) {
- NS_ERROR("Default pref file not parsed successfully.");
- rv = rv2;
- }
- }
- arrayCount = specialFiles.Count();
- for (i = 0; i < arrayCount; ++i) {
- // this may be a sparse array; test before parsing
- nsIFile* file = specialFiles[i];
- if (file) {
- rv2 = openPrefFile(file);
- if (NS_FAILED(rv2)) {
- NS_ERROR("Special default pref file not parsed successfully.");
- rv = rv2;
- }
- }
- }
- return rv;
- }
- static nsresult pref_LoadPrefsInDirList(const char *listId)
- {
- nsresult rv;
- nsCOMPtr<nsIProperties> dirSvc(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv));
- if (NS_FAILED(rv))
- return rv;
- nsCOMPtr<nsISimpleEnumerator> list;
- dirSvc->Get(listId,
- NS_GET_IID(nsISimpleEnumerator),
- getter_AddRefs(list));
- if (!list)
- return NS_OK;
- bool hasMore;
- while (NS_SUCCEEDED(list->HasMoreElements(&hasMore)) && hasMore) {
- nsCOMPtr<nsISupports> elem;
- list->GetNext(getter_AddRefs(elem));
- if (!elem)
- continue;
- nsCOMPtr<nsIFile> path = do_QueryInterface(elem);
- if (!path)
- continue;
- nsAutoCString leaf;
- path->GetNativeLeafName(leaf);
- // Do we care if a file provided by this process fails to load?
- if (Substring(leaf, leaf.Length() - 4).EqualsLiteral(".xpi"))
- ReadExtensionPrefs(path);
- else
- pref_LoadPrefsInDir(path, nullptr, 0);
- }
- return NS_OK;
- }
- static nsresult pref_ReadPrefFromJar(nsZipArchive* jarReader, const char *name)
- {
- nsZipItemPtr<char> manifest(jarReader, name, true);
- NS_ENSURE_TRUE(manifest.Buffer(), NS_ERROR_NOT_AVAILABLE);
- PrefParseState ps;
- PREF_InitParseState(&ps, PREF_ReaderCallback, ReportToConsole, nullptr);
- PREF_ParseBuf(&ps, manifest, manifest.Length());
- PREF_FinalizeParseState(&ps);
- return NS_OK;
- }
- //----------------------------------------------------------------------------------------
- // Initialize default preference JavaScript buffers from
- // appropriate TEXT resources
- //----------------------------------------------------------------------------------------
- static nsresult pref_InitInitialObjects()
- {
- nsresult rv;
- // In omni.jar case, we load the following prefs:
- // - jar:$gre/omni.jar!/goanna.js
- // - jar:$gre/omni.jar!/defaults/pref/*.js
- // In non omni.jar case, we load:
- // - $gre/goanna.js
- //
- // In both cases, we also load:
- // - $gre/defaults/pref/*.js
- // This is kept for bug 591866 (channel-prefs.js should not be in omni.jar)
- // on $app == $gre case ; we load all files instead of channel-prefs.js only
- // to have the same behaviour as $app != $gre, where this is required as
- // a supported location for GRE preferences.
- //
- // When $app != $gre, we additionally load, in omni.jar case:
- // - jar:$app/omni.jar!/defaults/preferences/*.js
- // - $app/defaults/preferences/*.js
- // and in non omni.jar case:
- // - $app/defaults/preferences/*.js
- // When $app == $gre, we additionally load, in omni.jar case:
- // - jar:$gre/omni.jar!/defaults/preferences/*.js
- // Thus, in omni.jar case, we always load app-specific default preferences
- // from omni.jar, whether or not $app == $gre.
- nsZipFind *findPtr;
- nsAutoPtr<nsZipFind> find;
- nsTArray<nsCString> prefEntries;
- const char *entryName;
- uint16_t entryNameLen;
- RefPtr<nsZipArchive> jarReader = mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE);
- if (jarReader) {
- // Load jar:$gre/omni.jar!/goanna.js
- rv = pref_ReadPrefFromJar(jarReader, "goanna.js");
- NS_ENSURE_SUCCESS(rv, rv);
- // Load jar:$gre/omni.jar!/defaults/pref/*.js
- rv = jarReader->FindInit("defaults/pref/*.js$", &findPtr);
- NS_ENSURE_SUCCESS(rv, rv);
- find = findPtr;
- while (NS_SUCCEEDED(find->FindNext(&entryName, &entryNameLen))) {
- prefEntries.AppendElement(Substring(entryName, entryNameLen));
- }
- prefEntries.Sort();
- for (uint32_t i = prefEntries.Length(); i--; ) {
- rv = pref_ReadPrefFromJar(jarReader, prefEntries[i].get());
- if (NS_FAILED(rv))
- NS_WARNING("Error parsing preferences.");
- }
- } else {
- // Load $gre/goanna.js
- nsCOMPtr<nsIFile> greprefsFile;
- rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(greprefsFile));
- NS_ENSURE_SUCCESS(rv, rv);
- rv = greprefsFile->AppendNative(NS_LITERAL_CSTRING("goanna.js"));
- NS_ENSURE_SUCCESS(rv, rv);
- rv = openPrefFile(greprefsFile);
- if (NS_FAILED(rv))
- NS_WARNING("Error parsing GRE default preferences. Is this an old-style embedding app?");
- }
- // Load $gre/defaults/pref/*.js
- nsCOMPtr<nsIFile> defaultPrefDir;
- rv = NS_GetSpecialDirectory(NS_APP_PREF_DEFAULTS_50_DIR, getter_AddRefs(defaultPrefDir));
- NS_ENSURE_SUCCESS(rv, rv);
- /* these pref file names should not be used: we process them after all other application pref files for backwards compatibility */
- static const char* specialFiles[] = {
- #if defined(XP_WIN)
- "winpref.js"
- #elif defined(XP_UNIX)
- "unix.js"
- #endif
- };
- rv = pref_LoadPrefsInDir(defaultPrefDir, specialFiles, ArrayLength(specialFiles));
- if (NS_FAILED(rv))
- NS_WARNING("Error parsing application default preferences.");
- // Load jar:$app/omni.jar!/defaults/preferences/*.js
- // or jar:$gre/omni.jar!/defaults/preferences/*.js.
- RefPtr<nsZipArchive> appJarReader = mozilla::Omnijar::GetReader(mozilla::Omnijar::APP);
- // GetReader(mozilla::Omnijar::APP) returns null when $app == $gre, in which
- // case we look for app-specific default preferences in $gre.
- if (!appJarReader)
- appJarReader = mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE);
- if (appJarReader) {
- rv = appJarReader->FindInit("defaults/preferences/*.js$", &findPtr);
- NS_ENSURE_SUCCESS(rv, rv);
- find = findPtr;
- prefEntries.Clear();
- while (NS_SUCCEEDED(find->FindNext(&entryName, &entryNameLen))) {
- prefEntries.AppendElement(Substring(entryName, entryNameLen));
- }
- prefEntries.Sort();
- for (uint32_t i = prefEntries.Length(); i--; ) {
- rv = pref_ReadPrefFromJar(appJarReader, prefEntries[i].get());
- if (NS_FAILED(rv))
- NS_WARNING("Error parsing preferences.");
- }
- }
- rv = pref_LoadPrefsInDirList(NS_APP_PREFS_DEFAULTS_DIR_LIST);
- NS_ENSURE_SUCCESS(rv, rv);
- // Set up the correct default for toolkit.telemetry.enabled.
- // If this build has MOZ_TELEMETRY_ON_BY_DEFAULT *or* we're on the beta
- // channel, telemetry is on by default, otherwise not. This is necessary
- // so that beta users who are testing final release builds don't flipflop
- // defaults.
- if (Preferences::GetDefaultType(kTelemetryPref) == nsIPrefBranch::PREF_INVALID) {
- bool prerelease = false;
- #ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
- prerelease = true;
- #else
- if (Preferences::GetDefaultCString(kChannelPref).EqualsLiteral("beta")) {
- prerelease = true;
- }
- #endif
- PREF_SetBoolPref(kTelemetryPref, prerelease, true);
- }
- NS_CreateServicesFromCategory(NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID,
- nullptr, NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID);
- nsCOMPtr<nsIObserverService> observerService =
- mozilla::services::GetObserverService();
- if (!observerService)
- return NS_ERROR_FAILURE;
- observerService->NotifyObservers(nullptr, NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID, nullptr);
- return pref_LoadPrefsInDirList(NS_EXT_PREFS_DEFAULTS_DIR_LIST);
- }
- /******************************************************************************
- *
- * static utilities
- *
- ******************************************************************************/
- // static
- nsresult
- Preferences::GetBool(const char* aPref, bool* aResult)
- {
- NS_PRECONDITION(aResult, "aResult must not be NULL");
- NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
- return PREF_GetBoolPref(aPref, aResult, false);
- }
- // static
- nsresult
- Preferences::GetInt(const char* aPref, int32_t* aResult)
- {
- NS_PRECONDITION(aResult, "aResult must not be NULL");
- NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
- return PREF_GetIntPref(aPref, aResult, false);
- }
- // static
- nsresult
- Preferences::GetFloat(const char* aPref, float* aResult)
- {
- NS_PRECONDITION(aResult, "aResult must not be NULL");
- NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
- nsAutoCString result;
- nsresult rv = PREF_CopyCharPref(aPref, getter_Copies(result), false);
- if (NS_SUCCEEDED(rv)) {
- *aResult = result.ToFloat(&rv);
- }
- return rv;
- }
- // static
- nsAdoptingCString
- Preferences::GetCString(const char* aPref)
- {
- nsAdoptingCString result;
- PREF_CopyCharPref(aPref, getter_Copies(result), false);
- return result;
- }
- // static
- nsAdoptingString
- Preferences::GetString(const char* aPref)
- {
- nsAdoptingString result;
- GetString(aPref, &result);
- return result;
- }
- // static
- nsresult
- Preferences::GetCString(const char* aPref, nsACString* aResult)
- {
- NS_PRECONDITION(aResult, "aResult must not be NULL");
- NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
- nsAutoCString result;
- nsresult rv = PREF_CopyCharPref(aPref, getter_Copies(result), false);
- if (NS_SUCCEEDED(rv)) {
- *aResult = result;
- }
- return rv;
- }
- // static
- nsresult
- Preferences::GetString(const char* aPref, nsAString* aResult)
- {
- NS_PRECONDITION(aResult, "aResult must not be NULL");
- NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
- nsAutoCString result;
- nsresult rv = PREF_CopyCharPref(aPref, getter_Copies(result), false);
- if (NS_SUCCEEDED(rv)) {
- CopyUTF8toUTF16(result, *aResult);
- }
- return rv;
- }
- // static
- nsAdoptingCString
- Preferences::GetLocalizedCString(const char* aPref)
- {
- nsAdoptingCString result;
- GetLocalizedCString(aPref, &result);
- return result;
- }
- // static
- nsAdoptingString
- Preferences::GetLocalizedString(const char* aPref)
- {
- nsAdoptingString result;
- GetLocalizedString(aPref, &result);
- return result;
- }
- // static
- nsresult
- Preferences::GetLocalizedCString(const char* aPref, nsACString* aResult)
- {
- NS_PRECONDITION(aResult, "aResult must not be NULL");
- nsAutoString result;
- nsresult rv = GetLocalizedString(aPref, &result);
- if (NS_SUCCEEDED(rv)) {
- CopyUTF16toUTF8(result, *aResult);
- }
- return rv;
- }
- // static
- nsresult
- Preferences::GetLocalizedString(const char* aPref, nsAString* aResult)
- {
- NS_PRECONDITION(aResult, "aResult must not be NULL");
- NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
- nsCOMPtr<nsIPrefLocalizedString> prefLocalString;
- nsresult rv = sRootBranch->GetComplexValue(aPref,
- NS_GET_IID(nsIPrefLocalizedString),
- getter_AddRefs(prefLocalString));
- if (NS_SUCCEEDED(rv)) {
- NS_ASSERTION(prefLocalString, "Succeeded but the result is NULL");
- prefLocalString->GetData(getter_Copies(*aResult));
- }
- return rv;
- }
- // static
- nsresult
- Preferences::GetComplex(const char* aPref, const nsIID &aType, void** aResult)
- {
- NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
- return sRootBranch->GetComplexValue(aPref, aType, aResult);
- }
- // static
- nsresult
- Preferences::SetCString(const char* aPref, const char* aValue)
- {
- ENSURE_MAIN_PROCESS("Cannot SetCString from content process:", aPref);
- NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
- return PREF_SetCharPref(aPref, aValue, false);
- }
- // static
- nsresult
- Preferences::SetCString(const char* aPref, const nsACString &aValue)
- {
- ENSURE_MAIN_PROCESS("Cannot SetCString from content process:", aPref);
- NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
- return PREF_SetCharPref(aPref, PromiseFlatCString(aValue).get(), false);
- }
- // static
- nsresult
- Preferences::SetString(const char* aPref, const char16ptr_t aValue)
- {
- ENSURE_MAIN_PROCESS("Cannot SetString from content process:", aPref);
- NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
- return PREF_SetCharPref(aPref, NS_ConvertUTF16toUTF8(aValue).get(), false);
- }
- // static
- nsresult
- Preferences::SetString(const char* aPref, const nsAString &aValue)
- {
- ENSURE_MAIN_PROCESS("Cannot SetString from content process:", aPref);
- NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
- return PREF_SetCharPref(aPref, NS_ConvertUTF16toUTF8(aValue).get(), false);
- }
- // static
- nsresult
- Preferences::SetBool(const char* aPref, bool aValue)
- {
- ENSURE_MAIN_PROCESS("Cannot SetBool from content process:", aPref);
- NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
- return PREF_SetBoolPref(aPref, aValue, false);
- }
- // static
- nsresult
- Preferences::SetInt(const char* aPref, int32_t aValue)
- {
- ENSURE_MAIN_PROCESS("Cannot SetInt from content process:", aPref);
- NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
- return PREF_SetIntPref(aPref, aValue, false);
- }
- // static
- nsresult
- Preferences::SetFloat(const char* aPref, float aValue)
- {
- return SetCString(aPref, nsPrintfCString("%f", aValue).get());
- }
- // static
- nsresult
- Preferences::SetComplex(const char* aPref, const nsIID &aType,
- nsISupports* aValue)
- {
- NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
- return sRootBranch->SetComplexValue(aPref, aType, aValue);
- }
- // static
- nsresult
- Preferences::ClearUser(const char* aPref)
- {
- ENSURE_MAIN_PROCESS("Cannot ClearUser from content process:", aPref);
- NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
- return PREF_ClearUserPref(aPref);
- }
- // static
- bool
- Preferences::HasUserValue(const char* aPref)
- {
- NS_ENSURE_TRUE(InitStaticMembers(), false);
- return PREF_HasUserPref(aPref);
- }
- // static
- int32_t
- Preferences::GetType(const char* aPref)
- {
- NS_ENSURE_TRUE(InitStaticMembers(), nsIPrefBranch::PREF_INVALID);
- int32_t result;
- return NS_SUCCEEDED(sRootBranch->GetPrefType(aPref, &result)) ?
- result : nsIPrefBranch::PREF_INVALID;
- }
- // static
- nsresult
- Preferences::AddStrongObserver(nsIObserver* aObserver,
- const char* aPref)
- {
- NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
- return sRootBranch->AddObserver(aPref, aObserver, false);
- }
- // static
- nsresult
- Preferences::AddWeakObserver(nsIObserver* aObserver,
- const char* aPref)
- {
- NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
- return sRootBranch->AddObserver(aPref, aObserver, true);
- }
- // static
- nsresult
- Preferences::RemoveObserver(nsIObserver* aObserver,
- const char* aPref)
- {
- if (!sPreferences && sShutdown) {
- return NS_OK; // Observers have been released automatically.
- }
- NS_ENSURE_TRUE(sPreferences, NS_ERROR_NOT_AVAILABLE);
- return sRootBranch->RemoveObserver(aPref, aObserver);
- }
- // static
- nsresult
- Preferences::AddStrongObservers(nsIObserver* aObserver,
- const char** aPrefs)
- {
- for (uint32_t i = 0; aPrefs[i]; i++) {
- nsresult rv = AddStrongObserver(aObserver, aPrefs[i]);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
- }
- // static
- nsresult
- Preferences::AddWeakObservers(nsIObserver* aObserver,
- const char** aPrefs)
- {
- for (uint32_t i = 0; aPrefs[i]; i++) {
- nsresult rv = AddWeakObserver(aObserver, aPrefs[i]);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
- }
- // static
- nsresult
- Preferences::RemoveObservers(nsIObserver* aObserver,
- const char** aPrefs)
- {
- if (!sPreferences && sShutdown) {
- return NS_OK; // Observers have been released automatically.
- }
- NS_ENSURE_TRUE(sPreferences, NS_ERROR_NOT_AVAILABLE);
- for (uint32_t i = 0; aPrefs[i]; i++) {
- nsresult rv = RemoveObserver(aObserver, aPrefs[i]);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
- }
- // static
- nsresult
- Preferences::RegisterCallback(PrefChangedFunc aCallback,
- const char* aPref,
- void* aClosure,
- MatchKind aMatchKind)
- {
- NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
- ValueObserverHashKey hashKey(aPref, aCallback, aMatchKind);
- RefPtr<ValueObserver> observer;
- gObserverTable->Get(&hashKey, getter_AddRefs(observer));
- if (observer) {
- observer->AppendClosure(aClosure);
- return NS_OK;
- }
- observer = new ValueObserver(aPref, aCallback, aMatchKind);
- observer->AppendClosure(aClosure);
- nsresult rv = AddStrongObserver(observer, aPref);
- NS_ENSURE_SUCCESS(rv, rv);
- gObserverTable->Put(observer, observer);
- return NS_OK;
- }
- // static
- nsresult
- Preferences::RegisterCallbackAndCall(PrefChangedFunc aCallback,
- const char* aPref,
- void* aClosure,
- MatchKind aMatchKind)
- {
- nsresult rv = RegisterCallback(aCallback, aPref, aClosure, aMatchKind);
- if (NS_SUCCEEDED(rv)) {
- (*aCallback)(aPref, aClosure);
- }
- return rv;
- }
- // static
- nsresult
- Preferences::UnregisterCallback(PrefChangedFunc aCallback,
- const char* aPref,
- void* aClosure,
- MatchKind aMatchKind)
- {
- if (!sPreferences && sShutdown) {
- return NS_OK; // Observers have been released automatically.
- }
- NS_ENSURE_TRUE(sPreferences, NS_ERROR_NOT_AVAILABLE);
- ValueObserverHashKey hashKey(aPref, aCallback, aMatchKind);
- RefPtr<ValueObserver> observer;
- gObserverTable->Get(&hashKey, getter_AddRefs(observer));
- if (!observer) {
- return NS_OK;
- }
- observer->RemoveClosure(aClosure);
- if (observer->HasNoClosures()) {
- // Delete the callback since its list of closures is empty.
- gObserverTable->Remove(observer);
- }
- return NS_OK;
- }
- static void BoolVarChanged(const char* aPref, void* aClosure)
- {
- CacheData* cache = static_cast<CacheData*>(aClosure);
- *((bool*)cache->cacheLocation) =
- Preferences::GetBool(aPref, cache->defaultValueBool);
- }
- // static
- nsresult
- Preferences::AddBoolVarCache(bool* aCache,
- const char* aPref,
- bool aDefault)
- {
- NS_ASSERTION(aCache, "aCache must not be NULL");
- #ifdef DEBUG
- AssertNotAlreadyCached("bool", aPref, aCache);
- #endif
- *aCache = GetBool(aPref, aDefault);
- CacheData* data = new CacheData();
- data->cacheLocation = aCache;
- data->defaultValueBool = aDefault;
- gCacheData->AppendElement(data);
- return RegisterCallback(BoolVarChanged, aPref, data, ExactMatch);
- }
- static void IntVarChanged(const char* aPref, void* aClosure)
- {
- CacheData* cache = static_cast<CacheData*>(aClosure);
- *((int32_t*)cache->cacheLocation) =
- Preferences::GetInt(aPref, cache->defaultValueInt);
- }
- // static
- nsresult
- Preferences::AddIntVarCache(int32_t* aCache,
- const char* aPref,
- int32_t aDefault)
- {
- NS_ASSERTION(aCache, "aCache must not be NULL");
- #ifdef DEBUG
- AssertNotAlreadyCached("int", aPref, aCache);
- #endif
- *aCache = Preferences::GetInt(aPref, aDefault);
- CacheData* data = new CacheData();
- data->cacheLocation = aCache;
- data->defaultValueInt = aDefault;
- gCacheData->AppendElement(data);
- return RegisterCallback(IntVarChanged, aPref, data, ExactMatch);
- }
- static void UintVarChanged(const char* aPref, void* aClosure)
- {
- CacheData* cache = static_cast<CacheData*>(aClosure);
- *((uint32_t*)cache->cacheLocation) =
- Preferences::GetUint(aPref, cache->defaultValueUint);
- }
- // static
- nsresult
- Preferences::AddUintVarCache(uint32_t* aCache,
- const char* aPref,
- uint32_t aDefault)
- {
- NS_ASSERTION(aCache, "aCache must not be NULL");
- #ifdef DEBUG
- AssertNotAlreadyCached("uint", aPref, aCache);
- #endif
- *aCache = Preferences::GetUint(aPref, aDefault);
- CacheData* data = new CacheData();
- data->cacheLocation = aCache;
- data->defaultValueUint = aDefault;
- gCacheData->AppendElement(data);
- return RegisterCallback(UintVarChanged, aPref, data, ExactMatch);
- }
- template <MemoryOrdering Order>
- static void AtomicUintVarChanged(const char* aPref, void* aClosure)
- {
- CacheData* cache = static_cast<CacheData*>(aClosure);
- *((Atomic<uint32_t, Order>*)cache->cacheLocation) =
- Preferences::GetUint(aPref, cache->defaultValueUint);
- }
- template <MemoryOrdering Order>
- // static
- nsresult
- Preferences::AddAtomicUintVarCache(Atomic<uint32_t, Order>* aCache,
- const char* aPref,
- uint32_t aDefault)
- {
- NS_ASSERTION(aCache, "aCache must not be NULL");
- #ifdef DEBUG
- AssertNotAlreadyCached("uint", aPref, aCache);
- #endif
- *aCache = Preferences::GetUint(aPref, aDefault);
- CacheData* data = new CacheData();
- data->cacheLocation = aCache;
- data->defaultValueUint = aDefault;
- gCacheData->AppendElement(data);
- return RegisterCallback(AtomicUintVarChanged<Order>, aPref, data, ExactMatch);
- }
- // Since the definition of this template function is not in a header file,
- // we need to explicitly specify the instantiations that are required.
- // Currently only the order=Relaxed variant is needed.
- template
- nsresult Preferences::AddAtomicUintVarCache(Atomic<uint32_t,Relaxed>*,
- const char*, uint32_t);
- static void FloatVarChanged(const char* aPref, void* aClosure)
- {
- CacheData* cache = static_cast<CacheData*>(aClosure);
- *((float*)cache->cacheLocation) =
- Preferences::GetFloat(aPref, cache->defaultValueFloat);
- }
- // static
- nsresult
- Preferences::AddFloatVarCache(float* aCache,
- const char* aPref,
- float aDefault)
- {
- NS_ASSERTION(aCache, "aCache must not be NULL");
- #ifdef DEBUG
- AssertNotAlreadyCached("float", aPref, aCache);
- #endif
- *aCache = Preferences::GetFloat(aPref, aDefault);
- CacheData* data = new CacheData();
- data->cacheLocation = aCache;
- data->defaultValueFloat = aDefault;
- gCacheData->AppendElement(data);
- return RegisterCallback(FloatVarChanged, aPref, data, ExactMatch);
- }
- // static
- nsresult
- Preferences::GetDefaultBool(const char* aPref, bool* aResult)
- {
- NS_PRECONDITION(aResult, "aResult must not be NULL");
- NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
- return PREF_GetBoolPref(aPref, aResult, true);
- }
- // static
- nsresult
- Preferences::GetDefaultInt(const char* aPref, int32_t* aResult)
- {
- NS_PRECONDITION(aResult, "aResult must not be NULL");
- NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
- return PREF_GetIntPref(aPref, aResult, true);
- }
- // static
- nsresult
- Preferences::GetDefaultCString(const char* aPref, nsACString* aResult)
- {
- NS_PRECONDITION(aResult, "aResult must not be NULL");
- NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
- nsAutoCString result;
- nsresult rv = PREF_CopyCharPref(aPref, getter_Copies(result), true);
- if (NS_SUCCEEDED(rv)) {
- *aResult = result;
- }
- return rv;
- }
- // static
- nsresult
- Preferences::GetDefaultString(const char* aPref, nsAString* aResult)
- {
- NS_PRECONDITION(aResult, "aResult must not be NULL");
- NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
- nsAutoCString result;
- nsresult rv = PREF_CopyCharPref(aPref, getter_Copies(result), true);
- if (NS_SUCCEEDED(rv)) {
- CopyUTF8toUTF16(result, *aResult);
- }
- return rv;
- }
- // static
- nsresult
- Preferences::GetDefaultLocalizedCString(const char* aPref,
- nsACString* aResult)
- {
- nsAutoString result;
- nsresult rv = GetDefaultLocalizedString(aPref, &result);
- if (NS_SUCCEEDED(rv)) {
- CopyUTF16toUTF8(result, *aResult);
- }
- return rv;
- }
- // static
- nsresult
- Preferences::GetDefaultLocalizedString(const char* aPref,
- nsAString* aResult)
- {
- NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
- nsCOMPtr<nsIPrefLocalizedString> prefLocalString;
- nsresult rv =
- sDefaultRootBranch->GetComplexValue(aPref,
- NS_GET_IID(nsIPrefLocalizedString),
- getter_AddRefs(prefLocalString));
- if (NS_SUCCEEDED(rv)) {
- NS_ASSERTION(prefLocalString, "Succeeded but the result is NULL");
- prefLocalString->GetData(getter_Copies(*aResult));
- }
- return rv;
- }
- // static
- nsAdoptingString
- Preferences::GetDefaultString(const char* aPref)
- {
- nsAdoptingString result;
- GetDefaultString(aPref, &result);
- return result;
- }
- // static
- nsAdoptingCString
- Preferences::GetDefaultCString(const char* aPref)
- {
- nsAdoptingCString result;
- PREF_CopyCharPref(aPref, getter_Copies(result), true);
- return result;
- }
- // static
- nsAdoptingString
- Preferences::GetDefaultLocalizedString(const char* aPref)
- {
- nsAdoptingString result;
- GetDefaultLocalizedString(aPref, &result);
- return result;
- }
- // static
- nsAdoptingCString
- Preferences::GetDefaultLocalizedCString(const char* aPref)
- {
- nsAdoptingCString result;
- GetDefaultLocalizedCString(aPref, &result);
- return result;
- }
- // static
- nsresult
- Preferences::GetDefaultComplex(const char* aPref, const nsIID &aType,
- void** aResult)
- {
- NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
- return sDefaultRootBranch->GetComplexValue(aPref, aType, aResult);
- }
- // static
- int32_t
- Preferences::GetDefaultType(const char* aPref)
- {
- NS_ENSURE_TRUE(InitStaticMembers(), nsIPrefBranch::PREF_INVALID);
- int32_t result;
- return NS_SUCCEEDED(sDefaultRootBranch->GetPrefType(aPref, &result)) ?
- result : nsIPrefBranch::PREF_INVALID;
- }
- } // namespace mozilla
- #undef ENSURE_MAIN_PROCESS
|