1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/modules/libpref/src/Preferences.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1929 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "mozilla/MemoryReporting.h" 1.11 +#include "mozilla/dom/ContentChild.h" 1.12 + 1.13 +#include "mozilla/ArrayUtils.h" 1.14 +#include "mozilla/Attributes.h" 1.15 +#include "mozilla/HashFunctions.h" 1.16 + 1.17 +#include "nsXULAppAPI.h" 1.18 + 1.19 +#include "mozilla/Preferences.h" 1.20 +#include "nsAppDirectoryServiceDefs.h" 1.21 +#include "nsDataHashtable.h" 1.22 +#include "nsDirectoryServiceDefs.h" 1.23 +#include "nsICategoryManager.h" 1.24 +#include "nsCategoryManagerUtils.h" 1.25 +#include "nsNetUtil.h" 1.26 +#include "nsIFile.h" 1.27 +#include "nsIInputStream.h" 1.28 +#include "nsIObserverService.h" 1.29 +#include "nsIStringEnumerator.h" 1.30 +#include "nsIZipReader.h" 1.31 +#include "nsPrefBranch.h" 1.32 +#include "nsXPIDLString.h" 1.33 +#include "nsCRT.h" 1.34 +#include "nsCOMArray.h" 1.35 +#include "nsXPCOMCID.h" 1.36 +#include "nsAutoPtr.h" 1.37 +#include "nsPrintfCString.h" 1.38 + 1.39 +#include "nsQuickSort.h" 1.40 +#include "pldhash.h" 1.41 + 1.42 +#include "prefapi.h" 1.43 +#include "prefread.h" 1.44 +#include "prefapi_private_data.h" 1.45 + 1.46 +#include "mozilla/Omnijar.h" 1.47 +#include "nsZipArchive.h" 1.48 + 1.49 +#include "nsTArray.h" 1.50 +#include "nsRefPtrHashtable.h" 1.51 +#include "nsIMemoryReporter.h" 1.52 +#include "nsThreadUtils.h" 1.53 + 1.54 +#ifdef DEBUG 1.55 +#define ENSURE_MAIN_PROCESS(message, pref) do { \ 1.56 + if (MOZ_UNLIKELY(XRE_GetProcessType() != GeckoProcessType_Default)) { \ 1.57 + nsPrintfCString msg("ENSURE_MAIN_PROCESS failed. %s %s", message, pref); \ 1.58 + NS_WARNING(msg.get()); \ 1.59 + return NS_ERROR_NOT_AVAILABLE; \ 1.60 + } \ 1.61 +} while (0); 1.62 +#else 1.63 +#define ENSURE_MAIN_PROCESS(message, pref) \ 1.64 + if (MOZ_UNLIKELY(XRE_GetProcessType() != GeckoProcessType_Default)) { \ 1.65 + return NS_ERROR_NOT_AVAILABLE; \ 1.66 + } 1.67 +#endif 1.68 + 1.69 +class PrefCallback; 1.70 + 1.71 +namespace mozilla { 1.72 + 1.73 +// Definitions 1.74 +#define INITIAL_PREF_FILES 10 1.75 +static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID); 1.76 + 1.77 +// Prototypes 1.78 +static nsresult openPrefFile(nsIFile* aFile); 1.79 +static nsresult pref_InitInitialObjects(void); 1.80 +static nsresult pref_LoadPrefsInDirList(const char *listId); 1.81 +static nsresult ReadExtensionPrefs(nsIFile *aFile); 1.82 + 1.83 +static const char kTelemetryPref[] = "toolkit.telemetry.enabled"; 1.84 +static const char kOldTelemetryPref[] = "toolkit.telemetry.enabledPreRelease"; 1.85 +static const char kChannelPref[] = "app.update.channel"; 1.86 + 1.87 +Preferences* Preferences::sPreferences = nullptr; 1.88 +nsIPrefBranch* Preferences::sRootBranch = nullptr; 1.89 +nsIPrefBranch* Preferences::sDefaultRootBranch = nullptr; 1.90 +bool Preferences::sShutdown = false; 1.91 + 1.92 +class ValueObserverHashKey : public PLDHashEntryHdr { 1.93 +public: 1.94 + typedef ValueObserverHashKey* KeyType; 1.95 + typedef const ValueObserverHashKey* KeyTypePointer; 1.96 + 1.97 + static const ValueObserverHashKey* KeyToPointer(ValueObserverHashKey *aKey) 1.98 + { 1.99 + return aKey; 1.100 + } 1.101 + 1.102 + static PLDHashNumber HashKey(const ValueObserverHashKey *aKey) 1.103 + { 1.104 + PLDHashNumber hash = HashString(aKey->mPrefName); 1.105 + return AddToHash(hash, aKey->mCallback); 1.106 + } 1.107 + 1.108 + ValueObserverHashKey(const char *aPref, PrefChangedFunc aCallback) : 1.109 + mPrefName(aPref), mCallback(aCallback) { } 1.110 + 1.111 + ValueObserverHashKey(const ValueObserverHashKey *aOther) : 1.112 + mPrefName(aOther->mPrefName), mCallback(aOther->mCallback) 1.113 + { } 1.114 + 1.115 + bool KeyEquals(const ValueObserverHashKey *aOther) const 1.116 + { 1.117 + return mCallback == aOther->mCallback && mPrefName == aOther->mPrefName; 1.118 + } 1.119 + 1.120 + ValueObserverHashKey *GetKey() const 1.121 + { 1.122 + return const_cast<ValueObserverHashKey*>(this); 1.123 + } 1.124 + 1.125 + enum { ALLOW_MEMMOVE = true }; 1.126 + 1.127 + nsCString mPrefName; 1.128 + PrefChangedFunc mCallback; 1.129 +}; 1.130 + 1.131 +class ValueObserver MOZ_FINAL : public nsIObserver, 1.132 + public ValueObserverHashKey 1.133 +{ 1.134 +public: 1.135 + NS_DECL_ISUPPORTS 1.136 + NS_DECL_NSIOBSERVER 1.137 + 1.138 + ValueObserver(const char *aPref, PrefChangedFunc aCallback) 1.139 + : ValueObserverHashKey(aPref, aCallback) { } 1.140 + 1.141 + ~ValueObserver() { 1.142 + Preferences::RemoveObserver(this, mPrefName.get()); 1.143 + } 1.144 + 1.145 + void AppendClosure(void *aClosure) { 1.146 + mClosures.AppendElement(aClosure); 1.147 + } 1.148 + 1.149 + void RemoveClosure(void *aClosure) { 1.150 + mClosures.RemoveElement(aClosure); 1.151 + } 1.152 + 1.153 + bool HasNoClosures() { 1.154 + return mClosures.Length() == 0; 1.155 + } 1.156 + 1.157 + nsTArray<void*> mClosures; 1.158 +}; 1.159 + 1.160 +NS_IMPL_ISUPPORTS(ValueObserver, nsIObserver) 1.161 + 1.162 +NS_IMETHODIMP 1.163 +ValueObserver::Observe(nsISupports *aSubject, 1.164 + const char *aTopic, 1.165 + const char16_t *aData) 1.166 +{ 1.167 + NS_ASSERTION(!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID), 1.168 + "invalid topic"); 1.169 + NS_ConvertUTF16toUTF8 data(aData); 1.170 + for (uint32_t i = 0; i < mClosures.Length(); i++) { 1.171 + mCallback(data.get(), mClosures.ElementAt(i)); 1.172 + } 1.173 + 1.174 + return NS_OK; 1.175 +} 1.176 + 1.177 +struct CacheData { 1.178 + void* cacheLocation; 1.179 + union { 1.180 + bool defaultValueBool; 1.181 + int32_t defaultValueInt; 1.182 + uint32_t defaultValueUint; 1.183 + float defaultValueFloat; 1.184 + }; 1.185 +}; 1.186 + 1.187 +static nsTArray<nsAutoPtr<CacheData> >* gCacheData = nullptr; 1.188 +static nsRefPtrHashtable<ValueObserverHashKey, 1.189 + ValueObserver>* gObserverTable = nullptr; 1.190 + 1.191 +static size_t 1.192 +SizeOfObserverEntryExcludingThis(ValueObserverHashKey* aKey, 1.193 + const nsRefPtr<ValueObserver>& aData, 1.194 + mozilla::MallocSizeOf aMallocSizeOf, 1.195 + void*) 1.196 +{ 1.197 + size_t n = 0; 1.198 + n += aKey->mPrefName.SizeOfExcludingThisIfUnshared(aMallocSizeOf); 1.199 + n += aData->mClosures.SizeOfExcludingThis(aMallocSizeOf); 1.200 + return n; 1.201 +} 1.202 + 1.203 +// Although this is a member of Preferences, it measures sPreferences and 1.204 +// several other global structures. 1.205 +/* static */ int64_t 1.206 +Preferences::SizeOfIncludingThisAndOtherStuff(mozilla::MallocSizeOf aMallocSizeOf) 1.207 +{ 1.208 + NS_ENSURE_TRUE(InitStaticMembers(), 0); 1.209 + 1.210 + size_t n = aMallocSizeOf(sPreferences); 1.211 + if (gHashTable.ops) { 1.212 + // pref keys are allocated in a private arena, which we count elsewhere. 1.213 + // pref stringvals are allocated out of the same private arena. 1.214 + n += PL_DHashTableSizeOfExcludingThis(&gHashTable, nullptr, aMallocSizeOf); 1.215 + } 1.216 + if (gCacheData) { 1.217 + n += gCacheData->SizeOfIncludingThis(aMallocSizeOf); 1.218 + for (uint32_t i = 0, count = gCacheData->Length(); i < count; ++i) { 1.219 + n += aMallocSizeOf((*gCacheData)[i]); 1.220 + } 1.221 + } 1.222 + if (gObserverTable) { 1.223 + n += aMallocSizeOf(gObserverTable); 1.224 + n += gObserverTable->SizeOfExcludingThis(SizeOfObserverEntryExcludingThis, 1.225 + aMallocSizeOf); 1.226 + } 1.227 + // We don't measure sRootBranch and sDefaultRootBranch here because 1.228 + // DMD indicates they are not significant. 1.229 + n += pref_SizeOfPrivateData(aMallocSizeOf); 1.230 + return n; 1.231 +} 1.232 + 1.233 +class PreferenceServiceReporter MOZ_FINAL : public nsIMemoryReporter 1.234 +{ 1.235 +public: 1.236 + NS_DECL_ISUPPORTS 1.237 + NS_DECL_NSIMEMORYREPORTER 1.238 + 1.239 +protected: 1.240 + static const uint32_t kSuspectReferentCount = 1000; 1.241 + static PLDHashOperator CountReferents(PrefCallback* aKey, 1.242 + nsAutoPtr<PrefCallback>& aCallback, 1.243 + void* aClosure); 1.244 +}; 1.245 + 1.246 +NS_IMPL_ISUPPORTS(PreferenceServiceReporter, nsIMemoryReporter) 1.247 + 1.248 +struct PreferencesReferentCount { 1.249 + PreferencesReferentCount() : numStrong(0), numWeakAlive(0), numWeakDead(0) {} 1.250 + size_t numStrong; 1.251 + size_t numWeakAlive; 1.252 + size_t numWeakDead; 1.253 + nsTArray<nsCString> suspectPreferences; 1.254 + // Count of the number of referents for each preference. 1.255 + nsDataHashtable<nsCStringHashKey, uint32_t> prefCounter; 1.256 +}; 1.257 + 1.258 +PLDHashOperator 1.259 +PreferenceServiceReporter::CountReferents(PrefCallback* aKey, 1.260 + nsAutoPtr<PrefCallback>& aCallback, 1.261 + void* aClosure) 1.262 +{ 1.263 + PreferencesReferentCount* referentCount = 1.264 + static_cast<PreferencesReferentCount*>(aClosure); 1.265 + 1.266 + nsPrefBranch* prefBranch = aCallback->GetPrefBranch(); 1.267 + const char* pref = prefBranch->getPrefName(aCallback->GetDomain().get()); 1.268 + 1.269 + if (aCallback->IsWeak()) { 1.270 + nsCOMPtr<nsIObserver> callbackRef = do_QueryReferent(aCallback->mWeakRef); 1.271 + if (callbackRef) { 1.272 + referentCount->numWeakAlive++; 1.273 + } else { 1.274 + referentCount->numWeakDead++; 1.275 + } 1.276 + } else { 1.277 + referentCount->numStrong++; 1.278 + } 1.279 + 1.280 + nsDependentCString prefString(pref); 1.281 + uint32_t oldCount = 0; 1.282 + referentCount->prefCounter.Get(prefString, &oldCount); 1.283 + uint32_t currentCount = oldCount + 1; 1.284 + referentCount->prefCounter.Put(prefString, currentCount); 1.285 + 1.286 + // Keep track of preferences that have a suspiciously large 1.287 + // number of referents (symptom of leak). 1.288 + if (currentCount == kSuspectReferentCount) { 1.289 + referentCount->suspectPreferences.AppendElement(prefString); 1.290 + } 1.291 + 1.292 + return PL_DHASH_NEXT; 1.293 +} 1.294 + 1.295 +MOZ_DEFINE_MALLOC_SIZE_OF(PreferenceServiceMallocSizeOf) 1.296 + 1.297 +NS_IMETHODIMP 1.298 +PreferenceServiceReporter::CollectReports(nsIMemoryReporterCallback* aCb, 1.299 + nsISupports* aClosure) 1.300 +{ 1.301 +#define REPORT(_path, _kind, _units, _amount, _desc) \ 1.302 + do { \ 1.303 + nsresult rv; \ 1.304 + rv = aCb->Callback(EmptyCString(), _path, _kind, \ 1.305 + _units, _amount, NS_LITERAL_CSTRING(_desc), \ 1.306 + aClosure); \ 1.307 + NS_ENSURE_SUCCESS(rv, rv); \ 1.308 + } while (0) 1.309 + 1.310 + REPORT(NS_LITERAL_CSTRING("explicit/preferences"), 1.311 + KIND_HEAP, UNITS_BYTES, 1.312 + Preferences::SizeOfIncludingThisAndOtherStuff(PreferenceServiceMallocSizeOf), 1.313 + "Memory used by the preferences system."); 1.314 + 1.315 + nsPrefBranch* rootBranch = 1.316 + static_cast<nsPrefBranch*>(Preferences::GetRootBranch()); 1.317 + if (!rootBranch) { 1.318 + return NS_OK; 1.319 + } 1.320 + 1.321 + PreferencesReferentCount referentCount; 1.322 + rootBranch->mObservers.Enumerate(&CountReferents, &referentCount); 1.323 + 1.324 + for (uint32_t i = 0; i < referentCount.suspectPreferences.Length(); i++) { 1.325 + nsCString& suspect = referentCount.suspectPreferences[i]; 1.326 + uint32_t totalReferentCount = 0; 1.327 + referentCount.prefCounter.Get(suspect, &totalReferentCount); 1.328 + 1.329 + nsPrintfCString suspectPath("preference-service-suspect/" 1.330 + "referent(pref=%s)", suspect.get()); 1.331 + 1.332 + REPORT(suspectPath, 1.333 + KIND_OTHER, UNITS_COUNT, totalReferentCount, 1.334 + "A preference with a suspiciously large number " 1.335 + "referents (symptom of a leak)."); 1.336 + } 1.337 + 1.338 + REPORT(NS_LITERAL_CSTRING("preference-service/referent/strong"), 1.339 + KIND_OTHER, UNITS_COUNT, referentCount.numStrong, 1.340 + "The number of strong referents held by the preference service."); 1.341 + 1.342 + REPORT(NS_LITERAL_CSTRING("preference-service/referent/weak/alive"), 1.343 + KIND_OTHER, UNITS_COUNT, referentCount.numWeakAlive, 1.344 + "The number of weak referents held by the preference service " 1.345 + "that are still alive."); 1.346 + 1.347 + REPORT(NS_LITERAL_CSTRING("preference-service/referent/weak/dead"), 1.348 + KIND_OTHER, UNITS_COUNT, referentCount.numWeakDead, 1.349 + "The number of weak referents held by the preference service " 1.350 + "that are dead."); 1.351 + 1.352 +#undef REPORT 1.353 + 1.354 + return NS_OK; 1.355 +} 1.356 + 1.357 +namespace { 1.358 +class AddPreferencesMemoryReporterRunnable : public nsRunnable 1.359 +{ 1.360 + NS_IMETHOD Run() 1.361 + { 1.362 + return RegisterStrongMemoryReporter(new PreferenceServiceReporter()); 1.363 + } 1.364 +}; 1.365 +} // anonymous namespace 1.366 + 1.367 +// static 1.368 +Preferences* 1.369 +Preferences::GetInstanceForService() 1.370 +{ 1.371 + if (sPreferences) { 1.372 + NS_ADDREF(sPreferences); 1.373 + return sPreferences; 1.374 + } 1.375 + 1.376 + NS_ENSURE_TRUE(!sShutdown, nullptr); 1.377 + 1.378 + sRootBranch = new nsPrefBranch("", false); 1.379 + NS_ADDREF(sRootBranch); 1.380 + sDefaultRootBranch = new nsPrefBranch("", true); 1.381 + NS_ADDREF(sDefaultRootBranch); 1.382 + 1.383 + sPreferences = new Preferences(); 1.384 + NS_ADDREF(sPreferences); 1.385 + 1.386 + if (NS_FAILED(sPreferences->Init())) { 1.387 + // The singleton instance will delete sRootBranch and sDefaultRootBranch. 1.388 + NS_RELEASE(sPreferences); 1.389 + return nullptr; 1.390 + } 1.391 + 1.392 + gCacheData = new nsTArray<nsAutoPtr<CacheData> >(); 1.393 + 1.394 + gObserverTable = new nsRefPtrHashtable<ValueObserverHashKey, ValueObserver>(); 1.395 + 1.396 + // Preferences::GetInstanceForService() can be called from GetService(), and 1.397 + // RegisterStrongMemoryReporter calls GetService(nsIMemoryReporter). To 1.398 + // avoid a potential recursive GetService() call, we can't register the 1.399 + // memory reporter here; instead, do it off a runnable. 1.400 + nsRefPtr<AddPreferencesMemoryReporterRunnable> runnable = 1.401 + new AddPreferencesMemoryReporterRunnable(); 1.402 + NS_DispatchToMainThread(runnable); 1.403 + 1.404 + NS_ADDREF(sPreferences); 1.405 + return sPreferences; 1.406 +} 1.407 + 1.408 +// static 1.409 +bool 1.410 +Preferences::InitStaticMembers() 1.411 +{ 1.412 +#ifndef MOZ_B2G 1.413 + MOZ_ASSERT(NS_IsMainThread()); 1.414 +#endif 1.415 + 1.416 + if (!sShutdown && !sPreferences) { 1.417 + nsCOMPtr<nsIPrefService> prefService = 1.418 + do_GetService(NS_PREFSERVICE_CONTRACTID); 1.419 + } 1.420 + 1.421 + return sPreferences != nullptr; 1.422 +} 1.423 + 1.424 +// static 1.425 +void 1.426 +Preferences::Shutdown() 1.427 +{ 1.428 + if (!sShutdown) { 1.429 + sShutdown = true; // Don't create the singleton instance after here. 1.430 + 1.431 + // Don't set sPreferences to nullptr here. The instance may be grabbed by 1.432 + // other modules. The utility methods of Preferences should be available 1.433 + // until the singleton instance actually released. 1.434 + if (sPreferences) { 1.435 + sPreferences->Release(); 1.436 + } 1.437 + } 1.438 +} 1.439 + 1.440 +//----------------------------------------------------------------------------- 1.441 + 1.442 +/* 1.443 + * Constructor/Destructor 1.444 + */ 1.445 + 1.446 +Preferences::Preferences() 1.447 +{ 1.448 +} 1.449 + 1.450 +Preferences::~Preferences() 1.451 +{ 1.452 + NS_ASSERTION(sPreferences == this, "Isn't this the singleton instance?"); 1.453 + 1.454 + delete gObserverTable; 1.455 + gObserverTable = nullptr; 1.456 + 1.457 + delete gCacheData; 1.458 + gCacheData = nullptr; 1.459 + 1.460 + NS_RELEASE(sRootBranch); 1.461 + NS_RELEASE(sDefaultRootBranch); 1.462 + 1.463 + sPreferences = nullptr; 1.464 + 1.465 + PREF_Cleanup(); 1.466 +} 1.467 + 1.468 + 1.469 +/* 1.470 + * nsISupports Implementation 1.471 + */ 1.472 + 1.473 +NS_IMPL_ADDREF(Preferences) 1.474 +NS_IMPL_RELEASE(Preferences) 1.475 + 1.476 +NS_INTERFACE_MAP_BEGIN(Preferences) 1.477 + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPrefService) 1.478 + NS_INTERFACE_MAP_ENTRY(nsIPrefService) 1.479 + NS_INTERFACE_MAP_ENTRY(nsIObserver) 1.480 + NS_INTERFACE_MAP_ENTRY(nsIPrefBranch) 1.481 + NS_INTERFACE_MAP_ENTRY(nsIPrefBranch2) 1.482 + NS_INTERFACE_MAP_ENTRY(nsIPrefBranchInternal) 1.483 + NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) 1.484 +NS_INTERFACE_MAP_END 1.485 + 1.486 + 1.487 +/* 1.488 + * nsIPrefService Implementation 1.489 + */ 1.490 + 1.491 +nsresult 1.492 +Preferences::Init() 1.493 +{ 1.494 + nsresult rv; 1.495 + 1.496 + rv = PREF_Init(); 1.497 + NS_ENSURE_SUCCESS(rv, rv); 1.498 + 1.499 + rv = pref_InitInitialObjects(); 1.500 + NS_ENSURE_SUCCESS(rv, rv); 1.501 + 1.502 + using mozilla::dom::ContentChild; 1.503 + if (XRE_GetProcessType() == GeckoProcessType_Content) { 1.504 + InfallibleTArray<PrefSetting> prefs; 1.505 + ContentChild::GetSingleton()->SendReadPrefsArray(&prefs); 1.506 + 1.507 + // Store the array 1.508 + for (uint32_t i = 0; i < prefs.Length(); ++i) { 1.509 + pref_SetPref(prefs[i]); 1.510 + } 1.511 + return NS_OK; 1.512 + } 1.513 + 1.514 + nsXPIDLCString lockFileName; 1.515 + /* 1.516 + * The following is a small hack which will allow us to only load the library 1.517 + * which supports the netscape.cfg file if the preference is defined. We 1.518 + * test for the existence of the pref, set in the all.js (mozilla) or 1.519 + * all-ns.js (netscape 6), and if it exists we startup the pref config 1.520 + * category which will do the rest. 1.521 + */ 1.522 + 1.523 + rv = PREF_CopyCharPref("general.config.filename", getter_Copies(lockFileName), false); 1.524 + if (NS_SUCCEEDED(rv)) 1.525 + NS_CreateServicesFromCategory("pref-config-startup", 1.526 + static_cast<nsISupports *>(static_cast<void *>(this)), 1.527 + "pref-config-startup"); 1.528 + 1.529 + nsCOMPtr<nsIObserverService> observerService = 1.530 + mozilla::services::GetObserverService(); 1.531 + if (!observerService) 1.532 + return NS_ERROR_FAILURE; 1.533 + 1.534 + rv = observerService->AddObserver(this, "profile-before-change", true); 1.535 + 1.536 + observerService->AddObserver(this, "load-extension-defaults", true); 1.537 + observerService->AddObserver(this, "suspend_process_notification", true); 1.538 + 1.539 + return(rv); 1.540 +} 1.541 + 1.542 +// static 1.543 +nsresult 1.544 +Preferences::ResetAndReadUserPrefs() 1.545 +{ 1.546 + sPreferences->ResetUserPrefs(); 1.547 + return sPreferences->ReadUserPrefs(nullptr); 1.548 +} 1.549 + 1.550 +NS_IMETHODIMP 1.551 +Preferences::Observe(nsISupports *aSubject, const char *aTopic, 1.552 + const char16_t *someData) 1.553 +{ 1.554 + if (XRE_GetProcessType() == GeckoProcessType_Content) 1.555 + return NS_ERROR_NOT_AVAILABLE; 1.556 + 1.557 + nsresult rv = NS_OK; 1.558 + 1.559 + if (!nsCRT::strcmp(aTopic, "profile-before-change")) { 1.560 + if (!nsCRT::strcmp(someData, MOZ_UTF16("shutdown-cleanse"))) { 1.561 + if (mCurrentFile) { 1.562 + mCurrentFile->Remove(false); 1.563 + mCurrentFile = nullptr; 1.564 + } 1.565 + } else { 1.566 + rv = SavePrefFile(nullptr); 1.567 + } 1.568 + } else if (!strcmp(aTopic, "load-extension-defaults")) { 1.569 + pref_LoadPrefsInDirList(NS_EXT_PREFS_DEFAULTS_DIR_LIST); 1.570 + } else if (!nsCRT::strcmp(aTopic, "reload-default-prefs")) { 1.571 + // Reload the default prefs from file. 1.572 + pref_InitInitialObjects(); 1.573 + } else if (!nsCRT::strcmp(aTopic, "suspend_process_notification")) { 1.574 + // Our process is being suspended. The OS may wake our process later, 1.575 + // or it may kill the process. In case our process is going to be killed 1.576 + // from the suspended state, we save preferences before suspending. 1.577 + rv = SavePrefFile(nullptr); 1.578 + } 1.579 + return rv; 1.580 +} 1.581 + 1.582 + 1.583 +NS_IMETHODIMP 1.584 +Preferences::ReadUserPrefs(nsIFile *aFile) 1.585 +{ 1.586 + if (XRE_GetProcessType() == GeckoProcessType_Content) { 1.587 + NS_ERROR("cannot load prefs from content process"); 1.588 + return NS_ERROR_NOT_AVAILABLE; 1.589 + } 1.590 + 1.591 + nsresult rv; 1.592 + 1.593 + if (nullptr == aFile) { 1.594 + rv = UseDefaultPrefFile(); 1.595 + // A user pref file is optional. 1.596 + // Ignore all errors related to it, so we retain 'rv' value :-| 1.597 + (void) UseUserPrefFile(); 1.598 + 1.599 + // Migrate the old prerelease telemetry pref 1.600 + if (!Preferences::GetBool(kOldTelemetryPref, true)) { 1.601 + Preferences::SetBool(kTelemetryPref, false); 1.602 + Preferences::ClearUser(kOldTelemetryPref); 1.603 + } 1.604 + 1.605 + NotifyServiceObservers(NS_PREFSERVICE_READ_TOPIC_ID); 1.606 + } else { 1.607 + rv = ReadAndOwnUserPrefFile(aFile); 1.608 + } 1.609 + 1.610 + return rv; 1.611 +} 1.612 + 1.613 +NS_IMETHODIMP 1.614 +Preferences::ResetPrefs() 1.615 +{ 1.616 + if (XRE_GetProcessType() == GeckoProcessType_Content) { 1.617 + NS_ERROR("cannot reset prefs from content process"); 1.618 + return NS_ERROR_NOT_AVAILABLE; 1.619 + } 1.620 + 1.621 + NotifyServiceObservers(NS_PREFSERVICE_RESET_TOPIC_ID); 1.622 + PREF_CleanupPrefs(); 1.623 + 1.624 + nsresult rv = PREF_Init(); 1.625 + NS_ENSURE_SUCCESS(rv, rv); 1.626 + 1.627 + return pref_InitInitialObjects(); 1.628 +} 1.629 + 1.630 +NS_IMETHODIMP 1.631 +Preferences::ResetUserPrefs() 1.632 +{ 1.633 + if (XRE_GetProcessType() == GeckoProcessType_Content) { 1.634 + NS_ERROR("cannot reset user prefs from content process"); 1.635 + return NS_ERROR_NOT_AVAILABLE; 1.636 + } 1.637 + 1.638 + PREF_ClearAllUserPrefs(); 1.639 + return NS_OK; 1.640 +} 1.641 + 1.642 +NS_IMETHODIMP 1.643 +Preferences::SavePrefFile(nsIFile *aFile) 1.644 +{ 1.645 + if (XRE_GetProcessType() == GeckoProcessType_Content) { 1.646 + NS_ERROR("cannot save pref file from content process"); 1.647 + return NS_ERROR_NOT_AVAILABLE; 1.648 + } 1.649 + 1.650 + return SavePrefFileInternal(aFile); 1.651 +} 1.652 + 1.653 +static nsresult 1.654 +ReadExtensionPrefs(nsIFile *aFile) 1.655 +{ 1.656 + nsresult rv; 1.657 + nsCOMPtr<nsIZipReader> reader = do_CreateInstance(kZipReaderCID, &rv); 1.658 + NS_ENSURE_SUCCESS(rv, rv); 1.659 + 1.660 + rv = reader->Open(aFile); 1.661 + NS_ENSURE_SUCCESS(rv, rv); 1.662 + 1.663 + nsCOMPtr<nsIUTF8StringEnumerator> files; 1.664 + rv = reader->FindEntries(nsDependentCString("defaults/preferences/*.(J|j)(S|s)$"), 1.665 + getter_AddRefs(files)); 1.666 + NS_ENSURE_SUCCESS(rv, rv); 1.667 + 1.668 + char buffer[4096]; 1.669 + 1.670 + bool more; 1.671 + while (NS_SUCCEEDED(rv = files->HasMore(&more)) && more) { 1.672 + nsAutoCString entry; 1.673 + rv = files->GetNext(entry); 1.674 + NS_ENSURE_SUCCESS(rv, rv); 1.675 + 1.676 + nsCOMPtr<nsIInputStream> stream; 1.677 + rv = reader->GetInputStream(entry, getter_AddRefs(stream)); 1.678 + NS_ENSURE_SUCCESS(rv, rv); 1.679 + 1.680 + uint64_t avail; 1.681 + uint32_t read; 1.682 + 1.683 + PrefParseState ps; 1.684 + PREF_InitParseState(&ps, PREF_ReaderCallback, nullptr); 1.685 + while (NS_SUCCEEDED(rv = stream->Available(&avail)) && avail) { 1.686 + rv = stream->Read(buffer, 4096, &read); 1.687 + if (NS_FAILED(rv)) { 1.688 + NS_WARNING("Pref stream read failed"); 1.689 + break; 1.690 + } 1.691 + 1.692 + PREF_ParseBuf(&ps, buffer, read); 1.693 + } 1.694 + PREF_FinalizeParseState(&ps); 1.695 + } 1.696 + return rv; 1.697 +} 1.698 + 1.699 +void 1.700 +Preferences::SetPreference(const PrefSetting& aPref) 1.701 +{ 1.702 + pref_SetPref(aPref); 1.703 +} 1.704 + 1.705 +void 1.706 +Preferences::GetPreference(PrefSetting* aPref) 1.707 +{ 1.708 + PrefHashEntry *entry = pref_HashTableLookup(aPref->name().get()); 1.709 + if (!entry) 1.710 + return; 1.711 + 1.712 + pref_GetPrefFromEntry(entry, aPref); 1.713 +} 1.714 + 1.715 +void 1.716 +Preferences::GetPreferences(InfallibleTArray<PrefSetting>* aPrefs) 1.717 +{ 1.718 + aPrefs->SetCapacity(PL_DHASH_TABLE_SIZE(&gHashTable)); 1.719 + PL_DHashTableEnumerate(&gHashTable, pref_GetPrefs, aPrefs); 1.720 +} 1.721 + 1.722 +NS_IMETHODIMP 1.723 +Preferences::GetBranch(const char *aPrefRoot, nsIPrefBranch **_retval) 1.724 +{ 1.725 + nsresult rv; 1.726 + 1.727 + if ((nullptr != aPrefRoot) && (*aPrefRoot != '\0')) { 1.728 + // TODO: - cache this stuff and allow consumers to share branches (hold weak references I think) 1.729 + nsPrefBranch* prefBranch = new nsPrefBranch(aPrefRoot, false); 1.730 + if (!prefBranch) 1.731 + return NS_ERROR_OUT_OF_MEMORY; 1.732 + 1.733 + rv = CallQueryInterface(prefBranch, _retval); 1.734 + } else { 1.735 + // special case caching the default root 1.736 + nsCOMPtr<nsIPrefBranch> root(sRootBranch); 1.737 + root.forget(_retval); 1.738 + rv = NS_OK; 1.739 + } 1.740 + return rv; 1.741 +} 1.742 + 1.743 +NS_IMETHODIMP 1.744 +Preferences::GetDefaultBranch(const char *aPrefRoot, nsIPrefBranch **_retval) 1.745 +{ 1.746 + if (!aPrefRoot || !aPrefRoot[0]) { 1.747 + nsCOMPtr<nsIPrefBranch> root(sDefaultRootBranch); 1.748 + root.forget(_retval); 1.749 + return NS_OK; 1.750 + } 1.751 + 1.752 + // TODO: - cache this stuff and allow consumers to share branches (hold weak references I think) 1.753 + nsRefPtr<nsPrefBranch> prefBranch = new nsPrefBranch(aPrefRoot, true); 1.754 + if (!prefBranch) 1.755 + return NS_ERROR_OUT_OF_MEMORY; 1.756 + 1.757 + prefBranch.forget(_retval); 1.758 + return NS_OK; 1.759 +} 1.760 + 1.761 + 1.762 +nsresult 1.763 +Preferences::NotifyServiceObservers(const char *aTopic) 1.764 +{ 1.765 + nsCOMPtr<nsIObserverService> observerService = 1.766 + mozilla::services::GetObserverService(); 1.767 + if (!observerService) 1.768 + return NS_ERROR_FAILURE; 1.769 + 1.770 + nsISupports *subject = (nsISupports *)((nsIPrefService *)this); 1.771 + observerService->NotifyObservers(subject, aTopic, nullptr); 1.772 + 1.773 + return NS_OK; 1.774 +} 1.775 + 1.776 +nsresult 1.777 +Preferences::UseDefaultPrefFile() 1.778 +{ 1.779 + nsresult rv; 1.780 + nsCOMPtr<nsIFile> aFile; 1.781 + 1.782 +#if defined(XP_WIN) && defined(MOZ_METRO) 1.783 + if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Metro) { 1.784 + rv = NS_GetSpecialDirectory(NS_METRO_APP_PREFS_50_FILE, getter_AddRefs(aFile)); 1.785 + } else 1.786 +#endif 1.787 + { 1.788 + rv = NS_GetSpecialDirectory(NS_APP_PREFS_50_FILE, getter_AddRefs(aFile)); 1.789 + } 1.790 + 1.791 + if (NS_SUCCEEDED(rv)) { 1.792 + rv = ReadAndOwnUserPrefFile(aFile); 1.793 + // Most likely cause of failure here is that the file didn't 1.794 + // exist, so save a new one. mUserPrefReadFailed will be 1.795 + // used to catch an error in actually reading the file. 1.796 + if (NS_FAILED(rv)) { 1.797 + if (NS_FAILED(SavePrefFileInternal(aFile))) 1.798 + NS_ERROR("Failed to save new shared pref file"); 1.799 + else 1.800 + rv = NS_OK; 1.801 + } 1.802 + } 1.803 + 1.804 + return rv; 1.805 +} 1.806 + 1.807 +nsresult 1.808 +Preferences::UseUserPrefFile() 1.809 +{ 1.810 + nsresult rv = NS_OK; 1.811 + nsCOMPtr<nsIFile> aFile; 1.812 + nsDependentCString prefsDirProp(NS_APP_PREFS_50_DIR); 1.813 + 1.814 + rv = NS_GetSpecialDirectory(prefsDirProp.get(), getter_AddRefs(aFile)); 1.815 + if (NS_SUCCEEDED(rv) && aFile) { 1.816 + rv = aFile->AppendNative(NS_LITERAL_CSTRING("user.js")); 1.817 + if (NS_SUCCEEDED(rv)) { 1.818 + bool exists = false; 1.819 + aFile->Exists(&exists); 1.820 + if (exists) { 1.821 + rv = openPrefFile(aFile); 1.822 + } else { 1.823 + rv = NS_ERROR_FILE_NOT_FOUND; 1.824 + } 1.825 + } 1.826 + } 1.827 + return rv; 1.828 +} 1.829 + 1.830 +nsresult 1.831 +Preferences::MakeBackupPrefFile(nsIFile *aFile) 1.832 +{ 1.833 + // Example: this copies "prefs.js" to "Invalidprefs.js" in the same directory. 1.834 + // "Invalidprefs.js" is removed if it exists, prior to making the copy. 1.835 + nsAutoString newFilename; 1.836 + nsresult rv = aFile->GetLeafName(newFilename); 1.837 + NS_ENSURE_SUCCESS(rv, rv); 1.838 + newFilename.Insert(NS_LITERAL_STRING("Invalid"), 0); 1.839 + nsCOMPtr<nsIFile> newFile; 1.840 + rv = aFile->GetParent(getter_AddRefs(newFile)); 1.841 + NS_ENSURE_SUCCESS(rv, rv); 1.842 + rv = newFile->Append(newFilename); 1.843 + NS_ENSURE_SUCCESS(rv, rv); 1.844 + bool exists = false; 1.845 + newFile->Exists(&exists); 1.846 + if (exists) { 1.847 + rv = newFile->Remove(false); 1.848 + NS_ENSURE_SUCCESS(rv, rv); 1.849 + } 1.850 + rv = aFile->CopyTo(nullptr, newFilename); 1.851 + NS_ENSURE_SUCCESS(rv, rv); 1.852 + return rv; 1.853 +} 1.854 + 1.855 +nsresult 1.856 +Preferences::ReadAndOwnUserPrefFile(nsIFile *aFile) 1.857 +{ 1.858 + NS_ENSURE_ARG(aFile); 1.859 + 1.860 + if (mCurrentFile == aFile) 1.861 + return NS_OK; 1.862 + mCurrentFile = aFile; 1.863 + 1.864 + nsresult rv = NS_OK; 1.865 + bool exists = false; 1.866 + mCurrentFile->Exists(&exists); 1.867 + if (exists) { 1.868 + rv = openPrefFile(mCurrentFile); 1.869 + if (NS_FAILED(rv)) { 1.870 + // Save a backup copy of the current (invalid) prefs file, since all prefs 1.871 + // from the error line to the end of the file will be lost (bug 361102). 1.872 + // TODO we should notify the user about it (bug 523725). 1.873 + MakeBackupPrefFile(mCurrentFile); 1.874 + } 1.875 + } else { 1.876 + rv = NS_ERROR_FILE_NOT_FOUND; 1.877 + } 1.878 + 1.879 + return rv; 1.880 +} 1.881 + 1.882 +nsresult 1.883 +Preferences::SavePrefFileInternal(nsIFile *aFile) 1.884 +{ 1.885 + if (nullptr == aFile) { 1.886 + // the gDirty flag tells us if we should write to mCurrentFile 1.887 + // we only check this flag when the caller wants to write to the default 1.888 + if (!gDirty) 1.889 + return NS_OK; 1.890 + 1.891 + // It's possible that we never got a prefs file. 1.892 + nsresult rv = NS_OK; 1.893 + if (mCurrentFile) 1.894 + rv = WritePrefFile(mCurrentFile); 1.895 + 1.896 + return rv; 1.897 + } else { 1.898 + return WritePrefFile(aFile); 1.899 + } 1.900 +} 1.901 + 1.902 +nsresult 1.903 +Preferences::WritePrefFile(nsIFile* aFile) 1.904 +{ 1.905 + const char outHeader[] = 1.906 + "# Mozilla User Preferences" 1.907 + NS_LINEBREAK 1.908 + NS_LINEBREAK 1.909 + "/* Do not edit this file." 1.910 + NS_LINEBREAK 1.911 + " *" 1.912 + NS_LINEBREAK 1.913 + " * If you make changes to this file while the application is running," 1.914 + NS_LINEBREAK 1.915 + " * the changes will be overwritten when the application exits." 1.916 + NS_LINEBREAK 1.917 + " *" 1.918 + NS_LINEBREAK 1.919 + " * To make a manual change to preferences, you can visit the URL about:config" 1.920 + NS_LINEBREAK 1.921 + " */" 1.922 + NS_LINEBREAK 1.923 + NS_LINEBREAK; 1.924 + 1.925 + nsCOMPtr<nsIOutputStream> outStreamSink; 1.926 + nsCOMPtr<nsIOutputStream> outStream; 1.927 + uint32_t writeAmount; 1.928 + nsresult rv; 1.929 + 1.930 + if (!gHashTable.ops) 1.931 + return NS_ERROR_NOT_INITIALIZED; 1.932 + 1.933 + // execute a "safe" save by saving through a tempfile 1.934 + rv = NS_NewSafeLocalFileOutputStream(getter_AddRefs(outStreamSink), 1.935 + aFile, 1.936 + -1, 1.937 + 0600); 1.938 + if (NS_FAILED(rv)) 1.939 + return rv; 1.940 + rv = NS_NewBufferedOutputStream(getter_AddRefs(outStream), outStreamSink, 4096); 1.941 + if (NS_FAILED(rv)) 1.942 + return rv; 1.943 + 1.944 + nsAutoArrayPtr<char*> valueArray(new char*[gHashTable.entryCount]); 1.945 + memset(valueArray, 0, gHashTable.entryCount * sizeof(char*)); 1.946 + pref_saveArgs saveArgs; 1.947 + saveArgs.prefArray = valueArray; 1.948 + saveArgs.saveTypes = SAVE_ALL; 1.949 + 1.950 + // get the lines that we're supposed to be writing to the file 1.951 + PL_DHashTableEnumerate(&gHashTable, pref_savePref, &saveArgs); 1.952 + 1.953 + /* Sort the preferences to make a readable file on disk */ 1.954 + NS_QuickSort(valueArray, gHashTable.entryCount, sizeof(char *), pref_CompareStrings, nullptr); 1.955 + 1.956 + // write out the file header 1.957 + outStream->Write(outHeader, sizeof(outHeader) - 1, &writeAmount); 1.958 + 1.959 + char** walker = valueArray; 1.960 + for (uint32_t valueIdx = 0; valueIdx < gHashTable.entryCount; valueIdx++, walker++) { 1.961 + if (*walker) { 1.962 + outStream->Write(*walker, strlen(*walker), &writeAmount); 1.963 + outStream->Write(NS_LINEBREAK, NS_LINEBREAK_LEN, &writeAmount); 1.964 + NS_Free(*walker); 1.965 + } 1.966 + } 1.967 + 1.968 + // tell the safe output stream to overwrite the real prefs file 1.969 + // (it'll abort if there were any errors during writing) 1.970 + nsCOMPtr<nsISafeOutputStream> safeStream = do_QueryInterface(outStream); 1.971 + NS_ASSERTION(safeStream, "expected a safe output stream!"); 1.972 + if (safeStream) { 1.973 + rv = safeStream->Finish(); 1.974 + if (NS_FAILED(rv)) { 1.975 + NS_WARNING("failed to save prefs file! possible data loss"); 1.976 + return rv; 1.977 + } 1.978 + } 1.979 + 1.980 + gDirty = false; 1.981 + return NS_OK; 1.982 +} 1.983 + 1.984 +static nsresult openPrefFile(nsIFile* aFile) 1.985 +{ 1.986 + nsCOMPtr<nsIInputStream> inStr; 1.987 + 1.988 + nsresult rv = NS_NewLocalFileInputStream(getter_AddRefs(inStr), aFile); 1.989 + if (NS_FAILED(rv)) 1.990 + return rv; 1.991 + 1.992 + uint64_t fileSize64; 1.993 + rv = inStr->Available(&fileSize64); 1.994 + if (NS_FAILED(rv)) 1.995 + return rv; 1.996 + NS_ENSURE_TRUE(fileSize64 <= UINT32_MAX, NS_ERROR_FILE_TOO_BIG); 1.997 + 1.998 + uint32_t fileSize = (uint32_t)fileSize64; 1.999 + nsAutoArrayPtr<char> fileBuffer(new char[fileSize]); 1.1000 + if (fileBuffer == nullptr) 1.1001 + return NS_ERROR_OUT_OF_MEMORY; 1.1002 + 1.1003 + PrefParseState ps; 1.1004 + PREF_InitParseState(&ps, PREF_ReaderCallback, nullptr); 1.1005 + 1.1006 + // Read is not guaranteed to return a buf the size of fileSize, 1.1007 + // but usually will. 1.1008 + nsresult rv2 = NS_OK; 1.1009 + for (;;) { 1.1010 + uint32_t amtRead = 0; 1.1011 + rv = inStr->Read((char*)fileBuffer, fileSize, &amtRead); 1.1012 + if (NS_FAILED(rv) || amtRead == 0) 1.1013 + break; 1.1014 + if (!PREF_ParseBuf(&ps, fileBuffer, amtRead)) 1.1015 + rv2 = NS_ERROR_FILE_CORRUPTED; 1.1016 + } 1.1017 + 1.1018 + PREF_FinalizeParseState(&ps); 1.1019 + 1.1020 + return NS_FAILED(rv) ? rv : rv2; 1.1021 +} 1.1022 + 1.1023 +/* 1.1024 + * some stuff that gets called from Pref_Init() 1.1025 + */ 1.1026 + 1.1027 +static int 1.1028 +pref_CompareFileNames(nsIFile* aFile1, nsIFile* aFile2, void* /*unused*/) 1.1029 +{ 1.1030 + nsAutoCString filename1, filename2; 1.1031 + aFile1->GetNativeLeafName(filename1); 1.1032 + aFile2->GetNativeLeafName(filename2); 1.1033 + 1.1034 + return Compare(filename2, filename1); 1.1035 +} 1.1036 + 1.1037 +/** 1.1038 + * Load default pref files from a directory. The files in the 1.1039 + * directory are sorted reverse-alphabetically; a set of "special file 1.1040 + * names" may be specified which are loaded after all the others. 1.1041 + */ 1.1042 +static nsresult 1.1043 +pref_LoadPrefsInDir(nsIFile* aDir, char const *const *aSpecialFiles, uint32_t aSpecialFilesCount) 1.1044 +{ 1.1045 + nsresult rv, rv2; 1.1046 + bool hasMoreElements; 1.1047 + 1.1048 + nsCOMPtr<nsISimpleEnumerator> dirIterator; 1.1049 + 1.1050 + // this may fail in some normal cases, such as embedders who do not use a GRE 1.1051 + rv = aDir->GetDirectoryEntries(getter_AddRefs(dirIterator)); 1.1052 + if (NS_FAILED(rv)) { 1.1053 + // If the directory doesn't exist, then we have no reason to complain. We 1.1054 + // loaded everything (and nothing) successfully. 1.1055 + if (rv == NS_ERROR_FILE_NOT_FOUND || rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) 1.1056 + rv = NS_OK; 1.1057 + return rv; 1.1058 + } 1.1059 + 1.1060 + rv = dirIterator->HasMoreElements(&hasMoreElements); 1.1061 + NS_ENSURE_SUCCESS(rv, rv); 1.1062 + 1.1063 + nsCOMArray<nsIFile> prefFiles(INITIAL_PREF_FILES); 1.1064 + nsCOMArray<nsIFile> specialFiles(aSpecialFilesCount); 1.1065 + nsCOMPtr<nsIFile> prefFile; 1.1066 + 1.1067 + while (hasMoreElements && NS_SUCCEEDED(rv)) { 1.1068 + nsAutoCString leafName; 1.1069 + 1.1070 + nsCOMPtr<nsISupports> supports; 1.1071 + rv = dirIterator->GetNext(getter_AddRefs(supports)); 1.1072 + prefFile = do_QueryInterface(supports); 1.1073 + if (NS_FAILED(rv)) { 1.1074 + break; 1.1075 + } 1.1076 + 1.1077 + prefFile->GetNativeLeafName(leafName); 1.1078 + NS_ASSERTION(!leafName.IsEmpty(), "Failure in default prefs: directory enumerator returned empty file?"); 1.1079 + 1.1080 + // Skip non-js files 1.1081 + if (StringEndsWith(leafName, NS_LITERAL_CSTRING(".js"), 1.1082 + nsCaseInsensitiveCStringComparator())) { 1.1083 + bool shouldParse = true; 1.1084 + // separate out special files 1.1085 + for (uint32_t i = 0; i < aSpecialFilesCount; ++i) { 1.1086 + if (leafName.Equals(nsDependentCString(aSpecialFiles[i]))) { 1.1087 + shouldParse = false; 1.1088 + // special files should be process in order; we put them into 1.1089 + // the array by index; this can make the array sparse 1.1090 + specialFiles.ReplaceObjectAt(prefFile, i); 1.1091 + } 1.1092 + } 1.1093 + 1.1094 + if (shouldParse) { 1.1095 + prefFiles.AppendObject(prefFile); 1.1096 + } 1.1097 + } 1.1098 + 1.1099 + rv = dirIterator->HasMoreElements(&hasMoreElements); 1.1100 + } 1.1101 + 1.1102 + if (prefFiles.Count() + specialFiles.Count() == 0) { 1.1103 + NS_WARNING("No default pref files found."); 1.1104 + if (NS_SUCCEEDED(rv)) { 1.1105 + rv = NS_SUCCESS_FILE_DIRECTORY_EMPTY; 1.1106 + } 1.1107 + return rv; 1.1108 + } 1.1109 + 1.1110 + prefFiles.Sort(pref_CompareFileNames, nullptr); 1.1111 + 1.1112 + uint32_t arrayCount = prefFiles.Count(); 1.1113 + uint32_t i; 1.1114 + for (i = 0; i < arrayCount; ++i) { 1.1115 + rv2 = openPrefFile(prefFiles[i]); 1.1116 + if (NS_FAILED(rv2)) { 1.1117 + NS_ERROR("Default pref file not parsed successfully."); 1.1118 + rv = rv2; 1.1119 + } 1.1120 + } 1.1121 + 1.1122 + arrayCount = specialFiles.Count(); 1.1123 + for (i = 0; i < arrayCount; ++i) { 1.1124 + // this may be a sparse array; test before parsing 1.1125 + nsIFile* file = specialFiles[i]; 1.1126 + if (file) { 1.1127 + rv2 = openPrefFile(file); 1.1128 + if (NS_FAILED(rv2)) { 1.1129 + NS_ERROR("Special default pref file not parsed successfully."); 1.1130 + rv = rv2; 1.1131 + } 1.1132 + } 1.1133 + } 1.1134 + 1.1135 + return rv; 1.1136 +} 1.1137 + 1.1138 +static nsresult pref_LoadPrefsInDirList(const char *listId) 1.1139 +{ 1.1140 + nsresult rv; 1.1141 + nsCOMPtr<nsIProperties> dirSvc(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv)); 1.1142 + if (NS_FAILED(rv)) 1.1143 + return rv; 1.1144 + 1.1145 + nsCOMPtr<nsISimpleEnumerator> list; 1.1146 + dirSvc->Get(listId, 1.1147 + NS_GET_IID(nsISimpleEnumerator), 1.1148 + getter_AddRefs(list)); 1.1149 + if (!list) 1.1150 + return NS_OK; 1.1151 + 1.1152 + bool hasMore; 1.1153 + while (NS_SUCCEEDED(list->HasMoreElements(&hasMore)) && hasMore) { 1.1154 + nsCOMPtr<nsISupports> elem; 1.1155 + list->GetNext(getter_AddRefs(elem)); 1.1156 + if (!elem) 1.1157 + continue; 1.1158 + 1.1159 + nsCOMPtr<nsIFile> path = do_QueryInterface(elem); 1.1160 + if (!path) 1.1161 + continue; 1.1162 + 1.1163 + nsAutoCString leaf; 1.1164 + path->GetNativeLeafName(leaf); 1.1165 + 1.1166 + // Do we care if a file provided by this process fails to load? 1.1167 + if (Substring(leaf, leaf.Length() - 4).Equals(NS_LITERAL_CSTRING(".xpi"))) 1.1168 + ReadExtensionPrefs(path); 1.1169 + else 1.1170 + pref_LoadPrefsInDir(path, nullptr, 0); 1.1171 + } 1.1172 + return NS_OK; 1.1173 +} 1.1174 + 1.1175 +static nsresult pref_ReadPrefFromJar(nsZipArchive* jarReader, const char *name) 1.1176 +{ 1.1177 + nsZipItemPtr<char> manifest(jarReader, name, true); 1.1178 + NS_ENSURE_TRUE(manifest.Buffer(), NS_ERROR_NOT_AVAILABLE); 1.1179 + 1.1180 + PrefParseState ps; 1.1181 + PREF_InitParseState(&ps, PREF_ReaderCallback, nullptr); 1.1182 + PREF_ParseBuf(&ps, manifest, manifest.Length()); 1.1183 + PREF_FinalizeParseState(&ps); 1.1184 + 1.1185 + return NS_OK; 1.1186 +} 1.1187 + 1.1188 +//---------------------------------------------------------------------------------------- 1.1189 +// Initialize default preference JavaScript buffers from 1.1190 +// appropriate TEXT resources 1.1191 +//---------------------------------------------------------------------------------------- 1.1192 +static nsresult pref_InitInitialObjects() 1.1193 +{ 1.1194 + nsresult rv; 1.1195 + 1.1196 + // In omni.jar case, we load the following prefs: 1.1197 + // - jar:$gre/omni.jar!/greprefs.js 1.1198 + // - jar:$gre/omni.jar!/defaults/pref/*.js 1.1199 + // In non omni.jar case, we load: 1.1200 + // - $gre/greprefs.js 1.1201 + // 1.1202 + // In both cases, we also load: 1.1203 + // - $gre/defaults/pref/*.js 1.1204 + // This is kept for bug 591866 (channel-prefs.js should not be in omni.jar) 1.1205 + // on $app == $gre case ; we load all files instead of channel-prefs.js only 1.1206 + // to have the same behaviour as $app != $gre, where this is required as 1.1207 + // a supported location for GRE preferences. 1.1208 + // 1.1209 + // When $app != $gre, we additionally load, in omni.jar case: 1.1210 + // - jar:$app/omni.jar!/defaults/preferences/*.js 1.1211 + // - $app/defaults/preferences/*.js 1.1212 + // and in non omni.jar case: 1.1213 + // - $app/defaults/preferences/*.js 1.1214 + // When $app == $gre, we additionally load, in omni.jar case: 1.1215 + // - jar:$gre/omni.jar!/defaults/preferences/*.js 1.1216 + // Thus, in omni.jar case, we always load app-specific default preferences 1.1217 + // from omni.jar, whether or not $app == $gre. 1.1218 + 1.1219 + nsZipFind *findPtr; 1.1220 + nsAutoPtr<nsZipFind> find; 1.1221 + nsTArray<nsCString> prefEntries; 1.1222 + const char *entryName; 1.1223 + uint16_t entryNameLen; 1.1224 + 1.1225 + nsRefPtr<nsZipArchive> jarReader = mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE); 1.1226 + if (jarReader) { 1.1227 + // Load jar:$gre/omni.jar!/greprefs.js 1.1228 + rv = pref_ReadPrefFromJar(jarReader, "greprefs.js"); 1.1229 + NS_ENSURE_SUCCESS(rv, rv); 1.1230 + 1.1231 + // Load jar:$gre/omni.jar!/defaults/pref/*.js 1.1232 + rv = jarReader->FindInit("defaults/pref/*.js$", &findPtr); 1.1233 + NS_ENSURE_SUCCESS(rv, rv); 1.1234 + 1.1235 + find = findPtr; 1.1236 + while (NS_SUCCEEDED(find->FindNext(&entryName, &entryNameLen))) { 1.1237 + prefEntries.AppendElement(Substring(entryName, entryNameLen)); 1.1238 + } 1.1239 + 1.1240 + prefEntries.Sort(); 1.1241 + for (uint32_t i = prefEntries.Length(); i--; ) { 1.1242 + rv = pref_ReadPrefFromJar(jarReader, prefEntries[i].get()); 1.1243 + if (NS_FAILED(rv)) 1.1244 + NS_WARNING("Error parsing preferences."); 1.1245 + } 1.1246 + } else { 1.1247 + // Load $gre/greprefs.js 1.1248 + nsCOMPtr<nsIFile> greprefsFile; 1.1249 + rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(greprefsFile)); 1.1250 + NS_ENSURE_SUCCESS(rv, rv); 1.1251 + 1.1252 + rv = greprefsFile->AppendNative(NS_LITERAL_CSTRING("greprefs.js")); 1.1253 + NS_ENSURE_SUCCESS(rv, rv); 1.1254 + 1.1255 + rv = openPrefFile(greprefsFile); 1.1256 + if (NS_FAILED(rv)) 1.1257 + NS_WARNING("Error parsing GRE default preferences. Is this an old-style embedding app?"); 1.1258 + } 1.1259 + 1.1260 + // Load $gre/defaults/pref/*.js 1.1261 + nsCOMPtr<nsIFile> defaultPrefDir; 1.1262 + 1.1263 + rv = NS_GetSpecialDirectory(NS_APP_PREF_DEFAULTS_50_DIR, getter_AddRefs(defaultPrefDir)); 1.1264 + NS_ENSURE_SUCCESS(rv, rv); 1.1265 + 1.1266 + /* these pref file names should not be used: we process them after all other application pref files for backwards compatibility */ 1.1267 + static const char* specialFiles[] = { 1.1268 +#if defined(XP_MACOSX) 1.1269 + "macprefs.js" 1.1270 +#elif defined(XP_WIN) 1.1271 + "winpref.js" 1.1272 +#elif defined(XP_UNIX) 1.1273 + "unix.js" 1.1274 +#if defined(VMS) 1.1275 + , "openvms.js" 1.1276 +#elif defined(_AIX) 1.1277 + , "aix.js" 1.1278 +#endif 1.1279 +#elif defined(XP_BEOS) 1.1280 + "beos.js" 1.1281 +#endif 1.1282 + }; 1.1283 + 1.1284 + rv = pref_LoadPrefsInDir(defaultPrefDir, specialFiles, ArrayLength(specialFiles)); 1.1285 + if (NS_FAILED(rv)) 1.1286 + NS_WARNING("Error parsing application default preferences."); 1.1287 + 1.1288 + // Load jar:$app/omni.jar!/defaults/preferences/*.js 1.1289 + // or jar:$gre/omni.jar!/defaults/preferences/*.js. 1.1290 + nsRefPtr<nsZipArchive> appJarReader = mozilla::Omnijar::GetReader(mozilla::Omnijar::APP); 1.1291 + // GetReader(mozilla::Omnijar::APP) returns null when $app == $gre, in which 1.1292 + // case we look for app-specific default preferences in $gre. 1.1293 + if (!appJarReader) 1.1294 + appJarReader = mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE); 1.1295 + if (appJarReader) { 1.1296 + rv = appJarReader->FindInit("defaults/preferences/*.js$", &findPtr); 1.1297 + NS_ENSURE_SUCCESS(rv, rv); 1.1298 + find = findPtr; 1.1299 + prefEntries.Clear(); 1.1300 + while (NS_SUCCEEDED(find->FindNext(&entryName, &entryNameLen))) { 1.1301 + prefEntries.AppendElement(Substring(entryName, entryNameLen)); 1.1302 + } 1.1303 + prefEntries.Sort(); 1.1304 + for (uint32_t i = prefEntries.Length(); i--; ) { 1.1305 + rv = pref_ReadPrefFromJar(appJarReader, prefEntries[i].get()); 1.1306 + if (NS_FAILED(rv)) 1.1307 + NS_WARNING("Error parsing preferences."); 1.1308 + } 1.1309 + } 1.1310 + 1.1311 + rv = pref_LoadPrefsInDirList(NS_APP_PREFS_DEFAULTS_DIR_LIST); 1.1312 + NS_ENSURE_SUCCESS(rv, rv); 1.1313 + 1.1314 + // Set up the correct default for toolkit.telemetry.enabled. 1.1315 + // If this build has MOZ_TELEMETRY_ON_BY_DEFAULT *or* we're on the beta 1.1316 + // channel, telemetry is on by default, otherwise not. This is necessary 1.1317 + // so that beta users who are testing final release builds don't flipflop 1.1318 + // defaults. 1.1319 + if (Preferences::GetDefaultType(kTelemetryPref) == PREF_INVALID) { 1.1320 + bool prerelease = false; 1.1321 +#ifdef MOZ_TELEMETRY_ON_BY_DEFAULT 1.1322 + prerelease = true; 1.1323 +#else 1.1324 + if (Preferences::GetDefaultCString(kChannelPref).EqualsLiteral("beta")) { 1.1325 + prerelease = true; 1.1326 + } 1.1327 +#endif 1.1328 + PREF_SetBoolPref(kTelemetryPref, prerelease, true); 1.1329 + } 1.1330 + 1.1331 + NS_CreateServicesFromCategory(NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID, 1.1332 + nullptr, NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID); 1.1333 + 1.1334 + nsCOMPtr<nsIObserverService> observerService = 1.1335 + mozilla::services::GetObserverService(); 1.1336 + if (!observerService) 1.1337 + return NS_ERROR_FAILURE; 1.1338 + 1.1339 + observerService->NotifyObservers(nullptr, NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID, nullptr); 1.1340 + 1.1341 + return pref_LoadPrefsInDirList(NS_EXT_PREFS_DEFAULTS_DIR_LIST); 1.1342 +} 1.1343 + 1.1344 + 1.1345 +/****************************************************************************** 1.1346 + * 1.1347 + * static utilities 1.1348 + * 1.1349 + ******************************************************************************/ 1.1350 + 1.1351 +// static 1.1352 +nsresult 1.1353 +Preferences::GetBool(const char* aPref, bool* aResult) 1.1354 +{ 1.1355 + NS_PRECONDITION(aResult, "aResult must not be NULL"); 1.1356 + NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE); 1.1357 + return PREF_GetBoolPref(aPref, aResult, false); 1.1358 +} 1.1359 + 1.1360 +// static 1.1361 +nsresult 1.1362 +Preferences::GetInt(const char* aPref, int32_t* aResult) 1.1363 +{ 1.1364 + NS_PRECONDITION(aResult, "aResult must not be NULL"); 1.1365 + NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE); 1.1366 + return PREF_GetIntPref(aPref, aResult, false); 1.1367 +} 1.1368 + 1.1369 +// static 1.1370 +nsresult 1.1371 +Preferences::GetFloat(const char* aPref, float* aResult) 1.1372 +{ 1.1373 + NS_PRECONDITION(aResult, "aResult must not be NULL"); 1.1374 + NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE); 1.1375 + nsAutoCString result; 1.1376 + nsresult rv = PREF_CopyCharPref(aPref, getter_Copies(result), false); 1.1377 + if (NS_SUCCEEDED(rv)) { 1.1378 + *aResult = result.ToFloat(&rv); 1.1379 + } 1.1380 + 1.1381 + return rv; 1.1382 +} 1.1383 + 1.1384 +// static 1.1385 +nsAdoptingCString 1.1386 +Preferences::GetCString(const char* aPref) 1.1387 +{ 1.1388 + nsAdoptingCString result; 1.1389 + PREF_CopyCharPref(aPref, getter_Copies(result), false); 1.1390 + return result; 1.1391 +} 1.1392 + 1.1393 +// static 1.1394 +nsAdoptingString 1.1395 +Preferences::GetString(const char* aPref) 1.1396 +{ 1.1397 + nsAdoptingString result; 1.1398 + GetString(aPref, &result); 1.1399 + return result; 1.1400 +} 1.1401 + 1.1402 +// static 1.1403 +nsresult 1.1404 +Preferences::GetCString(const char* aPref, nsACString* aResult) 1.1405 +{ 1.1406 + NS_PRECONDITION(aResult, "aResult must not be NULL"); 1.1407 + NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE); 1.1408 + nsAutoCString result; 1.1409 + nsresult rv = PREF_CopyCharPref(aPref, getter_Copies(result), false); 1.1410 + if (NS_SUCCEEDED(rv)) { 1.1411 + *aResult = result; 1.1412 + } 1.1413 + return rv; 1.1414 +} 1.1415 + 1.1416 +// static 1.1417 +nsresult 1.1418 +Preferences::GetString(const char* aPref, nsAString* aResult) 1.1419 +{ 1.1420 + NS_PRECONDITION(aResult, "aResult must not be NULL"); 1.1421 + NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE); 1.1422 + nsAutoCString result; 1.1423 + nsresult rv = PREF_CopyCharPref(aPref, getter_Copies(result), false); 1.1424 + if (NS_SUCCEEDED(rv)) { 1.1425 + CopyUTF8toUTF16(result, *aResult); 1.1426 + } 1.1427 + return rv; 1.1428 +} 1.1429 + 1.1430 +// static 1.1431 +nsAdoptingCString 1.1432 +Preferences::GetLocalizedCString(const char* aPref) 1.1433 +{ 1.1434 + nsAdoptingCString result; 1.1435 + GetLocalizedCString(aPref, &result); 1.1436 + return result; 1.1437 +} 1.1438 + 1.1439 +// static 1.1440 +nsAdoptingString 1.1441 +Preferences::GetLocalizedString(const char* aPref) 1.1442 +{ 1.1443 + nsAdoptingString result; 1.1444 + GetLocalizedString(aPref, &result); 1.1445 + return result; 1.1446 +} 1.1447 + 1.1448 +// static 1.1449 +nsresult 1.1450 +Preferences::GetLocalizedCString(const char* aPref, nsACString* aResult) 1.1451 +{ 1.1452 + NS_PRECONDITION(aResult, "aResult must not be NULL"); 1.1453 + nsAutoString result; 1.1454 + nsresult rv = GetLocalizedString(aPref, &result); 1.1455 + if (NS_SUCCEEDED(rv)) { 1.1456 + CopyUTF16toUTF8(result, *aResult); 1.1457 + } 1.1458 + return rv; 1.1459 +} 1.1460 + 1.1461 +// static 1.1462 +nsresult 1.1463 +Preferences::GetLocalizedString(const char* aPref, nsAString* aResult) 1.1464 +{ 1.1465 + NS_PRECONDITION(aResult, "aResult must not be NULL"); 1.1466 + NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE); 1.1467 + nsCOMPtr<nsIPrefLocalizedString> prefLocalString; 1.1468 + nsresult rv = sRootBranch->GetComplexValue(aPref, 1.1469 + NS_GET_IID(nsIPrefLocalizedString), 1.1470 + getter_AddRefs(prefLocalString)); 1.1471 + if (NS_SUCCEEDED(rv)) { 1.1472 + NS_ASSERTION(prefLocalString, "Succeeded but the result is NULL"); 1.1473 + prefLocalString->GetData(getter_Copies(*aResult)); 1.1474 + } 1.1475 + return rv; 1.1476 +} 1.1477 + 1.1478 +// static 1.1479 +nsresult 1.1480 +Preferences::GetComplex(const char* aPref, const nsIID &aType, void** aResult) 1.1481 +{ 1.1482 + NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE); 1.1483 + return sRootBranch->GetComplexValue(aPref, aType, aResult); 1.1484 +} 1.1485 + 1.1486 +// static 1.1487 +nsresult 1.1488 +Preferences::SetCString(const char* aPref, const char* aValue) 1.1489 +{ 1.1490 + ENSURE_MAIN_PROCESS("Cannot SetCString from content process:", aPref); 1.1491 + NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE); 1.1492 + return PREF_SetCharPref(aPref, aValue, false); 1.1493 +} 1.1494 + 1.1495 +// static 1.1496 +nsresult 1.1497 +Preferences::SetCString(const char* aPref, const nsACString &aValue) 1.1498 +{ 1.1499 + ENSURE_MAIN_PROCESS("Cannot SetCString from content process:", aPref); 1.1500 + NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE); 1.1501 + return PREF_SetCharPref(aPref, PromiseFlatCString(aValue).get(), false); 1.1502 +} 1.1503 + 1.1504 +// static 1.1505 +nsresult 1.1506 +Preferences::SetString(const char* aPref, const char16_t* aValue) 1.1507 +{ 1.1508 + ENSURE_MAIN_PROCESS("Cannot SetString from content process:", aPref); 1.1509 + NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE); 1.1510 + return PREF_SetCharPref(aPref, NS_ConvertUTF16toUTF8(aValue).get(), false); 1.1511 +} 1.1512 + 1.1513 +// static 1.1514 +nsresult 1.1515 +Preferences::SetString(const char* aPref, const nsAString &aValue) 1.1516 +{ 1.1517 + ENSURE_MAIN_PROCESS("Cannot SetString from content process:", aPref); 1.1518 + NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE); 1.1519 + return PREF_SetCharPref(aPref, NS_ConvertUTF16toUTF8(aValue).get(), false); 1.1520 +} 1.1521 + 1.1522 +// static 1.1523 +nsresult 1.1524 +Preferences::SetBool(const char* aPref, bool aValue) 1.1525 +{ 1.1526 + ENSURE_MAIN_PROCESS("Cannot SetBool from content process:", aPref); 1.1527 + NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE); 1.1528 + return PREF_SetBoolPref(aPref, aValue, false); 1.1529 +} 1.1530 + 1.1531 +// static 1.1532 +nsresult 1.1533 +Preferences::SetInt(const char* aPref, int32_t aValue) 1.1534 +{ 1.1535 + ENSURE_MAIN_PROCESS("Cannot SetInt from content process:", aPref); 1.1536 + NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE); 1.1537 + return PREF_SetIntPref(aPref, aValue, false); 1.1538 +} 1.1539 + 1.1540 +// static 1.1541 +nsresult 1.1542 +Preferences::SetComplex(const char* aPref, const nsIID &aType, 1.1543 + nsISupports* aValue) 1.1544 +{ 1.1545 + NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE); 1.1546 + return sRootBranch->SetComplexValue(aPref, aType, aValue); 1.1547 +} 1.1548 + 1.1549 +// static 1.1550 +nsresult 1.1551 +Preferences::ClearUser(const char* aPref) 1.1552 +{ 1.1553 + ENSURE_MAIN_PROCESS("Cannot ClearUser from content process:", aPref); 1.1554 + NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE); 1.1555 + return PREF_ClearUserPref(aPref); 1.1556 +} 1.1557 + 1.1558 +// static 1.1559 +bool 1.1560 +Preferences::HasUserValue(const char* aPref) 1.1561 +{ 1.1562 + NS_ENSURE_TRUE(InitStaticMembers(), false); 1.1563 + return PREF_HasUserPref(aPref); 1.1564 +} 1.1565 + 1.1566 +// static 1.1567 +int32_t 1.1568 +Preferences::GetType(const char* aPref) 1.1569 +{ 1.1570 + NS_ENSURE_TRUE(InitStaticMembers(), nsIPrefBranch::PREF_INVALID); 1.1571 + int32_t result; 1.1572 + return NS_SUCCEEDED(sRootBranch->GetPrefType(aPref, &result)) ? 1.1573 + result : nsIPrefBranch::PREF_INVALID; 1.1574 +} 1.1575 + 1.1576 +// static 1.1577 +nsresult 1.1578 +Preferences::AddStrongObserver(nsIObserver* aObserver, 1.1579 + const char* aPref) 1.1580 +{ 1.1581 + NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE); 1.1582 + return sRootBranch->AddObserver(aPref, aObserver, false); 1.1583 +} 1.1584 + 1.1585 +// static 1.1586 +nsresult 1.1587 +Preferences::AddWeakObserver(nsIObserver* aObserver, 1.1588 + const char* aPref) 1.1589 +{ 1.1590 + NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE); 1.1591 + return sRootBranch->AddObserver(aPref, aObserver, true); 1.1592 +} 1.1593 + 1.1594 +// static 1.1595 +nsresult 1.1596 +Preferences::RemoveObserver(nsIObserver* aObserver, 1.1597 + const char* aPref) 1.1598 +{ 1.1599 + if (!sPreferences && sShutdown) { 1.1600 + return NS_OK; // Observers have been released automatically. 1.1601 + } 1.1602 + NS_ENSURE_TRUE(sPreferences, NS_ERROR_NOT_AVAILABLE); 1.1603 + return sRootBranch->RemoveObserver(aPref, aObserver); 1.1604 +} 1.1605 + 1.1606 +// static 1.1607 +nsresult 1.1608 +Preferences::AddStrongObservers(nsIObserver* aObserver, 1.1609 + const char** aPrefs) 1.1610 +{ 1.1611 + for (uint32_t i = 0; aPrefs[i]; i++) { 1.1612 + nsresult rv = AddStrongObserver(aObserver, aPrefs[i]); 1.1613 + NS_ENSURE_SUCCESS(rv, rv); 1.1614 + } 1.1615 + return NS_OK; 1.1616 +} 1.1617 + 1.1618 +// static 1.1619 +nsresult 1.1620 +Preferences::AddWeakObservers(nsIObserver* aObserver, 1.1621 + const char** aPrefs) 1.1622 +{ 1.1623 + for (uint32_t i = 0; aPrefs[i]; i++) { 1.1624 + nsresult rv = AddWeakObserver(aObserver, aPrefs[i]); 1.1625 + NS_ENSURE_SUCCESS(rv, rv); 1.1626 + } 1.1627 + return NS_OK; 1.1628 +} 1.1629 + 1.1630 +// static 1.1631 +nsresult 1.1632 +Preferences::RemoveObservers(nsIObserver* aObserver, 1.1633 + const char** aPrefs) 1.1634 +{ 1.1635 + if (!sPreferences && sShutdown) { 1.1636 + return NS_OK; // Observers have been released automatically. 1.1637 + } 1.1638 + NS_ENSURE_TRUE(sPreferences, NS_ERROR_NOT_AVAILABLE); 1.1639 + 1.1640 + for (uint32_t i = 0; aPrefs[i]; i++) { 1.1641 + nsresult rv = RemoveObserver(aObserver, aPrefs[i]); 1.1642 + NS_ENSURE_SUCCESS(rv, rv); 1.1643 + } 1.1644 + return NS_OK; 1.1645 +} 1.1646 + 1.1647 +// static 1.1648 +nsresult 1.1649 +Preferences::RegisterCallback(PrefChangedFunc aCallback, 1.1650 + const char* aPref, 1.1651 + void* aClosure) 1.1652 +{ 1.1653 + NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE); 1.1654 + 1.1655 + ValueObserverHashKey hashKey(aPref, aCallback); 1.1656 + nsRefPtr<ValueObserver> observer; 1.1657 + gObserverTable->Get(&hashKey, getter_AddRefs(observer)); 1.1658 + if (observer) { 1.1659 + observer->AppendClosure(aClosure); 1.1660 + return NS_OK; 1.1661 + } 1.1662 + 1.1663 + observer = new ValueObserver(aPref, aCallback); 1.1664 + observer->AppendClosure(aClosure); 1.1665 + nsresult rv = AddStrongObserver(observer, aPref); 1.1666 + NS_ENSURE_SUCCESS(rv, rv); 1.1667 + gObserverTable->Put(observer, observer); 1.1668 + return NS_OK; 1.1669 +} 1.1670 + 1.1671 +// static 1.1672 +nsresult 1.1673 +Preferences::RegisterCallbackAndCall(PrefChangedFunc aCallback, 1.1674 + const char* aPref, 1.1675 + void* aClosure) 1.1676 +{ 1.1677 + nsresult rv = RegisterCallback(aCallback, aPref, aClosure); 1.1678 + if (NS_SUCCEEDED(rv)) { 1.1679 + (*aCallback)(aPref, aClosure); 1.1680 + } 1.1681 + return rv; 1.1682 +} 1.1683 + 1.1684 +// static 1.1685 +nsresult 1.1686 +Preferences::UnregisterCallback(PrefChangedFunc aCallback, 1.1687 + const char* aPref, 1.1688 + void* aClosure) 1.1689 +{ 1.1690 + if (!sPreferences && sShutdown) { 1.1691 + return NS_OK; // Observers have been released automatically. 1.1692 + } 1.1693 + NS_ENSURE_TRUE(sPreferences, NS_ERROR_NOT_AVAILABLE); 1.1694 + 1.1695 + ValueObserverHashKey hashKey(aPref, aCallback); 1.1696 + nsRefPtr<ValueObserver> observer; 1.1697 + gObserverTable->Get(&hashKey, getter_AddRefs(observer)); 1.1698 + if (!observer) { 1.1699 + return NS_OK; 1.1700 + } 1.1701 + 1.1702 + observer->RemoveClosure(aClosure); 1.1703 + if (observer->HasNoClosures()) { 1.1704 + // Delete the callback since its list of closures is empty. 1.1705 + gObserverTable->Remove(observer); 1.1706 + } 1.1707 + return NS_OK; 1.1708 +} 1.1709 + 1.1710 +static void BoolVarChanged(const char* aPref, void* aClosure) 1.1711 +{ 1.1712 + CacheData* cache = static_cast<CacheData*>(aClosure); 1.1713 + *((bool*)cache->cacheLocation) = 1.1714 + Preferences::GetBool(aPref, cache->defaultValueBool); 1.1715 +} 1.1716 + 1.1717 +// static 1.1718 +nsresult 1.1719 +Preferences::AddBoolVarCache(bool* aCache, 1.1720 + const char* aPref, 1.1721 + bool aDefault) 1.1722 +{ 1.1723 + NS_ASSERTION(aCache, "aCache must not be NULL"); 1.1724 + *aCache = GetBool(aPref, aDefault); 1.1725 + CacheData* data = new CacheData(); 1.1726 + data->cacheLocation = aCache; 1.1727 + data->defaultValueBool = aDefault; 1.1728 + gCacheData->AppendElement(data); 1.1729 + return RegisterCallback(BoolVarChanged, aPref, data); 1.1730 +} 1.1731 + 1.1732 +static void IntVarChanged(const char* aPref, void* aClosure) 1.1733 +{ 1.1734 + CacheData* cache = static_cast<CacheData*>(aClosure); 1.1735 + *((int32_t*)cache->cacheLocation) = 1.1736 + Preferences::GetInt(aPref, cache->defaultValueInt); 1.1737 +} 1.1738 + 1.1739 +// static 1.1740 +nsresult 1.1741 +Preferences::AddIntVarCache(int32_t* aCache, 1.1742 + const char* aPref, 1.1743 + int32_t aDefault) 1.1744 +{ 1.1745 + NS_ASSERTION(aCache, "aCache must not be NULL"); 1.1746 + *aCache = Preferences::GetInt(aPref, aDefault); 1.1747 + CacheData* data = new CacheData(); 1.1748 + data->cacheLocation = aCache; 1.1749 + data->defaultValueInt = aDefault; 1.1750 + gCacheData->AppendElement(data); 1.1751 + return RegisterCallback(IntVarChanged, aPref, data); 1.1752 +} 1.1753 + 1.1754 +static void UintVarChanged(const char* aPref, void* aClosure) 1.1755 +{ 1.1756 + CacheData* cache = static_cast<CacheData*>(aClosure); 1.1757 + *((uint32_t*)cache->cacheLocation) = 1.1758 + Preferences::GetUint(aPref, cache->defaultValueUint); 1.1759 +} 1.1760 + 1.1761 +// static 1.1762 +nsresult 1.1763 +Preferences::AddUintVarCache(uint32_t* aCache, 1.1764 + const char* aPref, 1.1765 + uint32_t aDefault) 1.1766 +{ 1.1767 + NS_ASSERTION(aCache, "aCache must not be NULL"); 1.1768 + *aCache = Preferences::GetUint(aPref, aDefault); 1.1769 + CacheData* data = new CacheData(); 1.1770 + data->cacheLocation = aCache; 1.1771 + data->defaultValueUint = aDefault; 1.1772 + gCacheData->AppendElement(data); 1.1773 + return RegisterCallback(UintVarChanged, aPref, data); 1.1774 +} 1.1775 + 1.1776 +static void FloatVarChanged(const char* aPref, void* aClosure) 1.1777 +{ 1.1778 + CacheData* cache = static_cast<CacheData*>(aClosure); 1.1779 + *((float*)cache->cacheLocation) = 1.1780 + Preferences::GetFloat(aPref, cache->defaultValueFloat); 1.1781 +} 1.1782 + 1.1783 +// static 1.1784 +nsresult 1.1785 +Preferences::AddFloatVarCache(float* aCache, 1.1786 + const char* aPref, 1.1787 + float aDefault) 1.1788 +{ 1.1789 + NS_ASSERTION(aCache, "aCache must not be NULL"); 1.1790 + *aCache = Preferences::GetFloat(aPref, aDefault); 1.1791 + CacheData* data = new CacheData(); 1.1792 + data->cacheLocation = aCache; 1.1793 + data->defaultValueFloat = aDefault; 1.1794 + gCacheData->AppendElement(data); 1.1795 + return RegisterCallback(FloatVarChanged, aPref, data); 1.1796 +} 1.1797 + 1.1798 +// static 1.1799 +nsresult 1.1800 +Preferences::GetDefaultBool(const char* aPref, bool* aResult) 1.1801 +{ 1.1802 + NS_PRECONDITION(aResult, "aResult must not be NULL"); 1.1803 + NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE); 1.1804 + return PREF_GetBoolPref(aPref, aResult, true); 1.1805 +} 1.1806 + 1.1807 +// static 1.1808 +nsresult 1.1809 +Preferences::GetDefaultInt(const char* aPref, int32_t* aResult) 1.1810 +{ 1.1811 + NS_PRECONDITION(aResult, "aResult must not be NULL"); 1.1812 + NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE); 1.1813 + return PREF_GetIntPref(aPref, aResult, true); 1.1814 +} 1.1815 + 1.1816 +// static 1.1817 +nsresult 1.1818 +Preferences::GetDefaultCString(const char* aPref, nsACString* aResult) 1.1819 +{ 1.1820 + NS_PRECONDITION(aResult, "aResult must not be NULL"); 1.1821 + NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE); 1.1822 + nsAutoCString result; 1.1823 + nsresult rv = PREF_CopyCharPref(aPref, getter_Copies(result), true); 1.1824 + if (NS_SUCCEEDED(rv)) { 1.1825 + *aResult = result; 1.1826 + } 1.1827 + return rv; 1.1828 +} 1.1829 + 1.1830 +// static 1.1831 +nsresult 1.1832 +Preferences::GetDefaultString(const char* aPref, nsAString* aResult) 1.1833 +{ 1.1834 + NS_PRECONDITION(aResult, "aResult must not be NULL"); 1.1835 + NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE); 1.1836 + nsAutoCString result; 1.1837 + nsresult rv = PREF_CopyCharPref(aPref, getter_Copies(result), true); 1.1838 + if (NS_SUCCEEDED(rv)) { 1.1839 + CopyUTF8toUTF16(result, *aResult); 1.1840 + } 1.1841 + return rv; 1.1842 +} 1.1843 + 1.1844 +// static 1.1845 +nsresult 1.1846 +Preferences::GetDefaultLocalizedCString(const char* aPref, 1.1847 + nsACString* aResult) 1.1848 +{ 1.1849 + nsAutoString result; 1.1850 + nsresult rv = GetDefaultLocalizedString(aPref, &result); 1.1851 + if (NS_SUCCEEDED(rv)) { 1.1852 + CopyUTF16toUTF8(result, *aResult); 1.1853 + } 1.1854 + return rv; 1.1855 +} 1.1856 + 1.1857 +// static 1.1858 +nsresult 1.1859 +Preferences::GetDefaultLocalizedString(const char* aPref, 1.1860 + nsAString* aResult) 1.1861 +{ 1.1862 + NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE); 1.1863 + nsCOMPtr<nsIPrefLocalizedString> prefLocalString; 1.1864 + nsresult rv = 1.1865 + sDefaultRootBranch->GetComplexValue(aPref, 1.1866 + NS_GET_IID(nsIPrefLocalizedString), 1.1867 + getter_AddRefs(prefLocalString)); 1.1868 + if (NS_SUCCEEDED(rv)) { 1.1869 + NS_ASSERTION(prefLocalString, "Succeeded but the result is NULL"); 1.1870 + prefLocalString->GetData(getter_Copies(*aResult)); 1.1871 + } 1.1872 + return rv; 1.1873 +} 1.1874 + 1.1875 +// static 1.1876 +nsAdoptingString 1.1877 +Preferences::GetDefaultString(const char* aPref) 1.1878 +{ 1.1879 + nsAdoptingString result; 1.1880 + GetDefaultString(aPref, &result); 1.1881 + return result; 1.1882 +} 1.1883 + 1.1884 +// static 1.1885 +nsAdoptingCString 1.1886 +Preferences::GetDefaultCString(const char* aPref) 1.1887 +{ 1.1888 + nsAdoptingCString result; 1.1889 + PREF_CopyCharPref(aPref, getter_Copies(result), true); 1.1890 + return result; 1.1891 +} 1.1892 + 1.1893 +// static 1.1894 +nsAdoptingString 1.1895 +Preferences::GetDefaultLocalizedString(const char* aPref) 1.1896 +{ 1.1897 + nsAdoptingString result; 1.1898 + GetDefaultLocalizedString(aPref, &result); 1.1899 + return result; 1.1900 +} 1.1901 + 1.1902 +// static 1.1903 +nsAdoptingCString 1.1904 +Preferences::GetDefaultLocalizedCString(const char* aPref) 1.1905 +{ 1.1906 + nsAdoptingCString result; 1.1907 + GetDefaultLocalizedCString(aPref, &result); 1.1908 + return result; 1.1909 +} 1.1910 + 1.1911 +// static 1.1912 +nsresult 1.1913 +Preferences::GetDefaultComplex(const char* aPref, const nsIID &aType, 1.1914 + void** aResult) 1.1915 +{ 1.1916 + NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE); 1.1917 + return sDefaultRootBranch->GetComplexValue(aPref, aType, aResult); 1.1918 +} 1.1919 + 1.1920 +// static 1.1921 +int32_t 1.1922 +Preferences::GetDefaultType(const char* aPref) 1.1923 +{ 1.1924 + NS_ENSURE_TRUE(InitStaticMembers(), nsIPrefBranch::PREF_INVALID); 1.1925 + int32_t result; 1.1926 + return NS_SUCCEEDED(sDefaultRootBranch->GetPrefType(aPref, &result)) ? 1.1927 + result : nsIPrefBranch::PREF_INVALID; 1.1928 +} 1.1929 + 1.1930 +} // namespace mozilla 1.1931 + 1.1932 +#undef ENSURE_MAIN_PROCESS