Preferences.cpp 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "mozilla/MemoryReporting.h"
  6. #include "mozilla/dom/ContentChild.h"
  7. #include "mozilla/ArrayUtils.h"
  8. #include "mozilla/Attributes.h"
  9. #include "mozilla/HashFunctions.h"
  10. #include "mozilla/UniquePtrExtensions.h"
  11. #include "nsXULAppAPI.h"
  12. #include "mozilla/Preferences.h"
  13. #include "nsAppDirectoryServiceDefs.h"
  14. #include "nsDataHashtable.h"
  15. #include "nsDirectoryServiceDefs.h"
  16. #include "nsICategoryManager.h"
  17. #include "nsCategoryManagerUtils.h"
  18. #include "nsNetUtil.h"
  19. #include "nsIFile.h"
  20. #include "nsIInputStream.h"
  21. #include "nsIObserverService.h"
  22. #include "nsIOutputStream.h"
  23. #include "nsISafeOutputStream.h"
  24. #include "nsISimpleEnumerator.h"
  25. #include "nsIStringEnumerator.h"
  26. #include "nsIZipReader.h"
  27. #include "nsPrefBranch.h"
  28. #include "nsXPIDLString.h"
  29. #include "nsCRT.h"
  30. #include "nsCOMArray.h"
  31. #include "nsXPCOMCID.h"
  32. #include "nsAutoPtr.h"
  33. #include "nsPrintfCString.h"
  34. #include "nsQuickSort.h"
  35. #include "PLDHashTable.h"
  36. #include "prefapi.h"
  37. #include "prefread.h"
  38. #include "prefapi_private_data.h"
  39. #include "mozilla/Omnijar.h"
  40. #include "nsZipArchive.h"
  41. #include "nsTArray.h"
  42. #include "nsRefPtrHashtable.h"
  43. #include "nsIMemoryReporter.h"
  44. #include "nsThreadUtils.h"
  45. #ifdef DEBUG
  46. #define ENSURE_MAIN_PROCESS(message, pref) do { \
  47. if (MOZ_UNLIKELY(!XRE_IsParentProcess())) { \
  48. nsPrintfCString msg("ENSURE_MAIN_PROCESS failed. %s %s", message, pref); \
  49. NS_WARNING(msg.get()); \
  50. return NS_ERROR_NOT_AVAILABLE; \
  51. } \
  52. } while (0);
  53. #else
  54. #define ENSURE_MAIN_PROCESS(message, pref) \
  55. if (MOZ_UNLIKELY(!XRE_IsParentProcess())) { \
  56. return NS_ERROR_NOT_AVAILABLE; \
  57. }
  58. #endif
  59. class PrefCallback;
  60. namespace mozilla {
  61. // Definitions
  62. #define INITIAL_PREF_FILES 10
  63. static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
  64. void
  65. Preferences::DirtyCallback()
  66. {
  67. if (gHashTable && sPreferences && !sPreferences->mDirty) {
  68. sPreferences->mDirty = true;
  69. }
  70. }
  71. // Prototypes
  72. static nsresult openPrefFile(nsIFile* aFile);
  73. static nsresult pref_InitInitialObjects(void);
  74. static nsresult pref_LoadPrefsInDirList(const char *listId);
  75. static nsresult ReadExtensionPrefs(nsIFile *aFile);
  76. static const char kTelemetryPref[] = "toolkit.telemetry.enabled";
  77. static const char kOldTelemetryPref[] = "toolkit.telemetry.enabledPreRelease";
  78. static const char kChannelPref[] = "app.update.channel";
  79. static const char kPrefFileHeader[] =
  80. "# Mozilla User Preferences"
  81. NS_LINEBREAK
  82. NS_LINEBREAK
  83. "/* Do not edit this file."
  84. NS_LINEBREAK
  85. " *"
  86. NS_LINEBREAK
  87. " * If you make changes to this file while the application is running,"
  88. NS_LINEBREAK
  89. " * the changes will be overwritten when the application exits."
  90. NS_LINEBREAK
  91. " *"
  92. NS_LINEBREAK
  93. " * To make a manual change to preferences, you can visit the URL about:config"
  94. NS_LINEBREAK
  95. " */"
  96. NS_LINEBREAK
  97. NS_LINEBREAK;
  98. Preferences* Preferences::sPreferences = nullptr;
  99. nsIPrefBranch* Preferences::sRootBranch = nullptr;
  100. nsIPrefBranch* Preferences::sDefaultRootBranch = nullptr;
  101. bool Preferences::sShutdown = false;
  102. class ValueObserverHashKey : public PLDHashEntryHdr {
  103. public:
  104. typedef ValueObserverHashKey* KeyType;
  105. typedef const ValueObserverHashKey* KeyTypePointer;
  106. static const ValueObserverHashKey* KeyToPointer(ValueObserverHashKey *aKey)
  107. {
  108. return aKey;
  109. }
  110. static PLDHashNumber HashKey(const ValueObserverHashKey *aKey)
  111. {
  112. PLDHashNumber hash = HashString(aKey->mPrefName);
  113. hash = AddToHash(hash, aKey->mMatchKind);
  114. return AddToHash(hash, aKey->mCallback);
  115. }
  116. ValueObserverHashKey(const char *aPref, PrefChangedFunc aCallback, Preferences::MatchKind aMatchKind) :
  117. mPrefName(aPref), mCallback(aCallback), mMatchKind(aMatchKind) { }
  118. explicit ValueObserverHashKey(const ValueObserverHashKey *aOther) :
  119. mPrefName(aOther->mPrefName),
  120. mCallback(aOther->mCallback),
  121. mMatchKind(aOther->mMatchKind)
  122. { }
  123. bool KeyEquals(const ValueObserverHashKey *aOther) const
  124. {
  125. return mCallback == aOther->mCallback &&
  126. mPrefName == aOther->mPrefName &&
  127. mMatchKind == aOther->mMatchKind;
  128. }
  129. ValueObserverHashKey *GetKey() const
  130. {
  131. return const_cast<ValueObserverHashKey*>(this);
  132. }
  133. enum { ALLOW_MEMMOVE = true };
  134. nsCString mPrefName;
  135. PrefChangedFunc mCallback;
  136. Preferences::MatchKind mMatchKind;
  137. };
  138. class ValueObserver final : public nsIObserver,
  139. public ValueObserverHashKey
  140. {
  141. ~ValueObserver() {
  142. Preferences::RemoveObserver(this, mPrefName.get());
  143. }
  144. public:
  145. NS_DECL_ISUPPORTS
  146. NS_DECL_NSIOBSERVER
  147. ValueObserver(const char *aPref, PrefChangedFunc aCallback, Preferences::MatchKind aMatchKind)
  148. : ValueObserverHashKey(aPref, aCallback, aMatchKind) { }
  149. void AppendClosure(void *aClosure) {
  150. mClosures.AppendElement(aClosure);
  151. }
  152. void RemoveClosure(void *aClosure) {
  153. mClosures.RemoveElement(aClosure);
  154. }
  155. bool HasNoClosures() {
  156. return mClosures.Length() == 0;
  157. }
  158. nsTArray<void*> mClosures;
  159. };
  160. NS_IMPL_ISUPPORTS(ValueObserver, nsIObserver)
  161. NS_IMETHODIMP
  162. ValueObserver::Observe(nsISupports *aSubject,
  163. const char *aTopic,
  164. const char16_t *aData)
  165. {
  166. NS_ASSERTION(!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID),
  167. "invalid topic");
  168. NS_ConvertUTF16toUTF8 data(aData);
  169. if (mMatchKind == Preferences::ExactMatch && !mPrefName.EqualsASCII(data.get())) {
  170. return NS_OK;
  171. }
  172. for (uint32_t i = 0; i < mClosures.Length(); i++) {
  173. mCallback(data.get(), mClosures.ElementAt(i));
  174. }
  175. return NS_OK;
  176. }
  177. struct CacheData {
  178. void* cacheLocation;
  179. union {
  180. bool defaultValueBool;
  181. int32_t defaultValueInt;
  182. uint32_t defaultValueUint;
  183. float defaultValueFloat;
  184. };
  185. };
  186. static nsTArray<nsAutoPtr<CacheData> >* gCacheData = nullptr;
  187. static nsRefPtrHashtable<ValueObserverHashKey,
  188. ValueObserver>* gObserverTable = nullptr;
  189. #ifdef DEBUG
  190. static bool
  191. HaveExistingCacheFor(void* aPtr)
  192. {
  193. MOZ_ASSERT(NS_IsMainThread());
  194. if (gCacheData) {
  195. for (size_t i = 0, count = gCacheData->Length(); i < count; ++i) {
  196. if ((*gCacheData)[i]->cacheLocation == aPtr) {
  197. return true;
  198. }
  199. }
  200. }
  201. return false;
  202. }
  203. static void
  204. AssertNotAlreadyCached(const char* aPrefType,
  205. const char* aPref,
  206. void* aPtr)
  207. {
  208. if (HaveExistingCacheFor(aPtr)) {
  209. fprintf_stderr(stderr,
  210. "Attempt to add a %s pref cache for preference '%s' at address '%p'"
  211. "was made. However, a pref was already cached at this address.\n",
  212. aPrefType, aPref, aPtr);
  213. MOZ_ASSERT(false, "Should not have an existing pref cache for this address");
  214. }
  215. }
  216. #endif
  217. static void
  218. ReportToConsole(const char* aMessage, int aLine, bool aError)
  219. {
  220. nsPrintfCString message("** Preference parsing %s (line %d) = %s **\n",
  221. (aError ? "error" : "warning"), aLine, aMessage);
  222. nsPrefBranch::ReportToConsole(NS_ConvertUTF8toUTF16(message.get()));
  223. }
  224. // Although this is a member of Preferences, it measures sPreferences and
  225. // several other global structures.
  226. /* static */ int64_t
  227. Preferences::SizeOfIncludingThisAndOtherStuff(mozilla::MallocSizeOf aMallocSizeOf)
  228. {
  229. NS_ENSURE_TRUE(InitStaticMembers(), 0);
  230. size_t n = aMallocSizeOf(sPreferences);
  231. if (gHashTable) {
  232. // pref keys are allocated in a private arena, which we count elsewhere.
  233. // pref stringvals are allocated out of the same private arena.
  234. n += gHashTable->ShallowSizeOfIncludingThis(aMallocSizeOf);
  235. }
  236. if (gCacheData) {
  237. n += gCacheData->ShallowSizeOfIncludingThis(aMallocSizeOf);
  238. for (uint32_t i = 0, count = gCacheData->Length(); i < count; ++i) {
  239. n += aMallocSizeOf((*gCacheData)[i]);
  240. }
  241. }
  242. if (gObserverTable) {
  243. n += gObserverTable->ShallowSizeOfIncludingThis(aMallocSizeOf);
  244. for (auto iter = gObserverTable->Iter(); !iter.Done(); iter.Next()) {
  245. n += iter.Key()->mPrefName.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
  246. n += iter.Data()->mClosures.ShallowSizeOfExcludingThis(aMallocSizeOf);
  247. }
  248. }
  249. if (sRootBranch) {
  250. n += reinterpret_cast<nsPrefBranch*>(sRootBranch)->SizeOfIncludingThis(aMallocSizeOf);
  251. }
  252. if (sDefaultRootBranch) {
  253. n += reinterpret_cast<nsPrefBranch*>(sDefaultRootBranch)->SizeOfIncludingThis(aMallocSizeOf);
  254. }
  255. n += pref_SizeOfPrivateData(aMallocSizeOf);
  256. return n;
  257. }
  258. class PreferenceServiceReporter final : public nsIMemoryReporter
  259. {
  260. ~PreferenceServiceReporter() {}
  261. public:
  262. NS_DECL_ISUPPORTS
  263. NS_DECL_NSIMEMORYREPORTER
  264. protected:
  265. static const uint32_t kSuspectReferentCount = 1000;
  266. };
  267. NS_IMPL_ISUPPORTS(PreferenceServiceReporter, nsIMemoryReporter)
  268. MOZ_DEFINE_MALLOC_SIZE_OF(PreferenceServiceMallocSizeOf)
  269. NS_IMETHODIMP
  270. PreferenceServiceReporter::CollectReports(
  271. nsIHandleReportCallback* aHandleReport, nsISupports* aData, bool aAnonymize)
  272. {
  273. MOZ_COLLECT_REPORT(
  274. "explicit/preferences", KIND_HEAP, UNITS_BYTES,
  275. Preferences::SizeOfIncludingThisAndOtherStuff(PreferenceServiceMallocSizeOf),
  276. "Memory used by the preferences system.");
  277. nsPrefBranch* rootBranch =
  278. static_cast<nsPrefBranch*>(Preferences::GetRootBranch());
  279. if (!rootBranch) {
  280. return NS_OK;
  281. }
  282. size_t numStrong = 0;
  283. size_t numWeakAlive = 0;
  284. size_t numWeakDead = 0;
  285. nsTArray<nsCString> suspectPreferences;
  286. // Count of the number of referents for each preference.
  287. nsDataHashtable<nsCStringHashKey, uint32_t> prefCounter;
  288. for (auto iter = rootBranch->mObservers.Iter(); !iter.Done(); iter.Next()) {
  289. nsAutoPtr<PrefCallback>& callback = iter.Data();
  290. nsPrefBranch* prefBranch = callback->GetPrefBranch();
  291. const char* pref = prefBranch->getPrefName(callback->GetDomain().get());
  292. if (callback->IsWeak()) {
  293. nsCOMPtr<nsIObserver> callbackRef = do_QueryReferent(callback->mWeakRef);
  294. if (callbackRef) {
  295. numWeakAlive++;
  296. } else {
  297. numWeakDead++;
  298. }
  299. } else {
  300. numStrong++;
  301. }
  302. nsDependentCString prefString(pref);
  303. uint32_t oldCount = 0;
  304. prefCounter.Get(prefString, &oldCount);
  305. uint32_t currentCount = oldCount + 1;
  306. prefCounter.Put(prefString, currentCount);
  307. // Keep track of preferences that have a suspiciously large number of
  308. // referents (a symptom of a leak).
  309. if (currentCount == kSuspectReferentCount) {
  310. suspectPreferences.AppendElement(prefString);
  311. }
  312. }
  313. for (uint32_t i = 0; i < suspectPreferences.Length(); i++) {
  314. nsCString& suspect = suspectPreferences[i];
  315. uint32_t totalReferentCount = 0;
  316. prefCounter.Get(suspect, &totalReferentCount);
  317. nsPrintfCString suspectPath("preference-service-suspect/"
  318. "referent(pref=%s)", suspect.get());
  319. aHandleReport->Callback(
  320. /* process = */ EmptyCString(),
  321. suspectPath, KIND_OTHER, UNITS_COUNT, totalReferentCount,
  322. NS_LITERAL_CSTRING(
  323. "A preference with a suspiciously large number referents (symptom of a "
  324. "leak)."),
  325. aData);
  326. }
  327. MOZ_COLLECT_REPORT(
  328. "preference-service/referent/strong", KIND_OTHER, UNITS_COUNT,
  329. numStrong,
  330. "The number of strong referents held by the preference service.");
  331. MOZ_COLLECT_REPORT(
  332. "preference-service/referent/weak/alive", KIND_OTHER, UNITS_COUNT,
  333. numWeakAlive,
  334. "The number of weak referents held by the preference service that are "
  335. "still alive.");
  336. MOZ_COLLECT_REPORT(
  337. "preference-service/referent/weak/dead", KIND_OTHER, UNITS_COUNT,
  338. numWeakDead,
  339. "The number of weak referents held by the preference service that are "
  340. "dead.");
  341. return NS_OK;
  342. }
  343. namespace {
  344. class AddPreferencesMemoryReporterRunnable : public Runnable
  345. {
  346. NS_IMETHOD Run() override
  347. {
  348. return RegisterStrongMemoryReporter(new PreferenceServiceReporter());
  349. }
  350. };
  351. } // namespace
  352. // static
  353. Preferences*
  354. Preferences::GetInstanceForService()
  355. {
  356. if (sPreferences) {
  357. NS_ADDREF(sPreferences);
  358. return sPreferences;
  359. }
  360. NS_ENSURE_TRUE(!sShutdown, nullptr);
  361. sRootBranch = new nsPrefBranch("", false);
  362. NS_ADDREF(sRootBranch);
  363. sDefaultRootBranch = new nsPrefBranch("", true);
  364. NS_ADDREF(sDefaultRootBranch);
  365. sPreferences = new Preferences();
  366. NS_ADDREF(sPreferences);
  367. if (NS_FAILED(sPreferences->Init())) {
  368. // The singleton instance will delete sRootBranch and sDefaultRootBranch.
  369. NS_RELEASE(sPreferences);
  370. return nullptr;
  371. }
  372. gCacheData = new nsTArray<nsAutoPtr<CacheData> >();
  373. gObserverTable = new nsRefPtrHashtable<ValueObserverHashKey, ValueObserver>();
  374. // Preferences::GetInstanceForService() can be called from GetService(), and
  375. // RegisterStrongMemoryReporter calls GetService(nsIMemoryReporter). To
  376. // avoid a potential recursive GetService() call, we can't register the
  377. // memory reporter here; instead, do it off a runnable.
  378. RefPtr<AddPreferencesMemoryReporterRunnable> runnable =
  379. new AddPreferencesMemoryReporterRunnable();
  380. NS_DispatchToMainThread(runnable);
  381. NS_ADDREF(sPreferences);
  382. return sPreferences;
  383. }
  384. // static
  385. bool
  386. Preferences::IsServiceAvailable()
  387. {
  388. return !!sPreferences;
  389. }
  390. // static
  391. bool
  392. Preferences::InitStaticMembers()
  393. {
  394. MOZ_ASSERT(NS_IsMainThread());
  395. if (!sShutdown && !sPreferences) {
  396. nsCOMPtr<nsIPrefService> prefService =
  397. do_GetService(NS_PREFSERVICE_CONTRACTID);
  398. }
  399. return sPreferences != nullptr;
  400. }
  401. // static
  402. void
  403. Preferences::Shutdown()
  404. {
  405. if (!sShutdown) {
  406. sShutdown = true; // Don't create the singleton instance after here.
  407. // Don't set sPreferences to nullptr here. The instance may be grabbed by
  408. // other modules. The utility methods of Preferences should be available
  409. // until the singleton instance actually released.
  410. if (sPreferences) {
  411. sPreferences->Release();
  412. }
  413. }
  414. }
  415. //-----------------------------------------------------------------------------
  416. /*
  417. * Constructor/Destructor
  418. */
  419. Preferences::Preferences()
  420. : mDirty(false)
  421. {
  422. }
  423. Preferences::~Preferences()
  424. {
  425. NS_ASSERTION(sPreferences == this, "Isn't this the singleton instance?");
  426. delete gObserverTable;
  427. gObserverTable = nullptr;
  428. delete gCacheData;
  429. gCacheData = nullptr;
  430. NS_RELEASE(sRootBranch);
  431. NS_RELEASE(sDefaultRootBranch);
  432. sPreferences = nullptr;
  433. PREF_Cleanup();
  434. }
  435. /*
  436. * nsISupports Implementation
  437. */
  438. NS_IMPL_ADDREF(Preferences)
  439. NS_IMPL_RELEASE(Preferences)
  440. NS_INTERFACE_MAP_BEGIN(Preferences)
  441. NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPrefService)
  442. NS_INTERFACE_MAP_ENTRY(nsIPrefService)
  443. NS_INTERFACE_MAP_ENTRY(nsIObserver)
  444. NS_INTERFACE_MAP_ENTRY(nsIPrefBranch)
  445. NS_INTERFACE_MAP_ENTRY(nsIPrefBranch2)
  446. NS_INTERFACE_MAP_ENTRY(nsIPrefBranchInternal)
  447. NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
  448. NS_INTERFACE_MAP_END
  449. /*
  450. * nsIPrefService Implementation
  451. */
  452. nsresult
  453. Preferences::Init()
  454. {
  455. nsresult rv;
  456. PREF_SetDirtyCallback(&DirtyCallback);
  457. PREF_Init();
  458. rv = pref_InitInitialObjects();
  459. NS_ENSURE_SUCCESS(rv, rv);
  460. using mozilla::dom::ContentChild;
  461. if (XRE_IsContentProcess()) {
  462. InfallibleTArray<PrefSetting> prefs;
  463. ContentChild::GetSingleton()->SendReadPrefsArray(&prefs);
  464. // Store the array
  465. for (uint32_t i = 0; i < prefs.Length(); ++i) {
  466. pref_SetPref(prefs[i]);
  467. }
  468. return NS_OK;
  469. }
  470. nsXPIDLCString lockFileName;
  471. /*
  472. * The following is a small hack which will allow us to only load the library
  473. * which supports the netscape.cfg file if the preference is defined. We
  474. * test for the existence of the pref, set in the all.js (mozilla) or
  475. * all-ns.js (netscape 6), and if it exists we startup the pref config
  476. * category which will do the rest.
  477. */
  478. rv = PREF_CopyCharPref("general.config.filename", getter_Copies(lockFileName), false);
  479. if (NS_SUCCEEDED(rv))
  480. NS_CreateServicesFromCategory("pref-config-startup",
  481. static_cast<nsISupports *>(static_cast<void *>(this)),
  482. "pref-config-startup");
  483. nsCOMPtr<nsIObserverService> observerService =
  484. mozilla::services::GetObserverService();
  485. if (!observerService)
  486. return NS_ERROR_FAILURE;
  487. rv = observerService->AddObserver(this, "profile-before-change", true);
  488. observerService->AddObserver(this, "load-extension-defaults", true);
  489. observerService->AddObserver(this, "suspend_process_notification", true);
  490. return(rv);
  491. }
  492. // static
  493. nsresult
  494. Preferences::ResetAndReadUserPrefs()
  495. {
  496. sPreferences->ResetUserPrefs();
  497. return sPreferences->ReadUserPrefs(nullptr);
  498. }
  499. NS_IMETHODIMP
  500. Preferences::Observe(nsISupports *aSubject, const char *aTopic,
  501. const char16_t *someData)
  502. {
  503. if (XRE_IsContentProcess())
  504. return NS_ERROR_NOT_AVAILABLE;
  505. nsresult rv = NS_OK;
  506. if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
  507. rv = SavePrefFile(nullptr);
  508. } else if (!strcmp(aTopic, "load-extension-defaults")) {
  509. pref_LoadPrefsInDirList(NS_EXT_PREFS_DEFAULTS_DIR_LIST);
  510. } else if (!nsCRT::strcmp(aTopic, "reload-default-prefs")) {
  511. // Reload the default prefs from file.
  512. pref_InitInitialObjects();
  513. } else if (!nsCRT::strcmp(aTopic, "suspend_process_notification")) {
  514. // Our process is being suspended. The OS may wake our process later,
  515. // or it may kill the process. In case our process is going to be killed
  516. // from the suspended state, we save preferences before suspending.
  517. rv = SavePrefFile(nullptr);
  518. }
  519. return rv;
  520. }
  521. NS_IMETHODIMP
  522. Preferences::ReadUserPrefs(nsIFile *aFile)
  523. {
  524. if (XRE_IsContentProcess()) {
  525. NS_ERROR("cannot load prefs from content process");
  526. return NS_ERROR_NOT_AVAILABLE;
  527. }
  528. nsresult rv;
  529. if (nullptr == aFile) {
  530. rv = UseDefaultPrefFile();
  531. // A user pref file is optional.
  532. // Ignore all errors related to it, so we retain 'rv' value :-|
  533. (void) UseUserPrefFile();
  534. // Migrate the old prerelease telemetry pref
  535. if (!Preferences::GetBool(kOldTelemetryPref, true)) {
  536. Preferences::SetBool(kTelemetryPref, false);
  537. Preferences::ClearUser(kOldTelemetryPref);
  538. }
  539. NotifyServiceObservers(NS_PREFSERVICE_READ_TOPIC_ID);
  540. } else {
  541. rv = ReadAndOwnUserPrefFile(aFile);
  542. }
  543. return rv;
  544. }
  545. NS_IMETHODIMP
  546. Preferences::ResetPrefs()
  547. {
  548. if (XRE_IsContentProcess()) {
  549. NS_ERROR("cannot reset prefs from content process");
  550. return NS_ERROR_NOT_AVAILABLE;
  551. }
  552. NotifyServiceObservers(NS_PREFSERVICE_RESET_TOPIC_ID);
  553. PREF_CleanupPrefs();
  554. PREF_Init();
  555. return pref_InitInitialObjects();
  556. }
  557. NS_IMETHODIMP
  558. Preferences::ResetUserPrefs()
  559. {
  560. if (XRE_IsContentProcess()) {
  561. NS_ERROR("cannot reset user prefs from content process");
  562. return NS_ERROR_NOT_AVAILABLE;
  563. }
  564. PREF_ClearAllUserPrefs();
  565. return NS_OK;
  566. }
  567. NS_IMETHODIMP
  568. Preferences::SavePrefFile(nsIFile *aFile)
  569. {
  570. if (XRE_IsContentProcess()) {
  571. NS_ERROR("cannot save pref file from content process");
  572. return NS_ERROR_NOT_AVAILABLE;
  573. }
  574. return SavePrefFileInternal(aFile);
  575. }
  576. static nsresult
  577. ReadExtensionPrefs(nsIFile *aFile)
  578. {
  579. nsresult rv;
  580. nsCOMPtr<nsIZipReader> reader = do_CreateInstance(kZipReaderCID, &rv);
  581. NS_ENSURE_SUCCESS(rv, rv);
  582. rv = reader->Open(aFile);
  583. NS_ENSURE_SUCCESS(rv, rv);
  584. nsCOMPtr<nsIUTF8StringEnumerator> files;
  585. rv = reader->FindEntries(nsDependentCString("defaults/preferences/*.(J|j)(S|s)$"),
  586. getter_AddRefs(files));
  587. NS_ENSURE_SUCCESS(rv, rv);
  588. char buffer[4096];
  589. bool more;
  590. while (NS_SUCCEEDED(rv = files->HasMore(&more)) && more) {
  591. nsAutoCString entry;
  592. rv = files->GetNext(entry);
  593. NS_ENSURE_SUCCESS(rv, rv);
  594. nsCOMPtr<nsIInputStream> stream;
  595. rv = reader->GetInputStream(entry, getter_AddRefs(stream));
  596. NS_ENSURE_SUCCESS(rv, rv);
  597. uint64_t avail;
  598. uint32_t read;
  599. PrefParseState ps;
  600. PREF_InitParseState(&ps, PREF_ReaderCallback, ReportToConsole, nullptr);
  601. while (NS_SUCCEEDED(rv = stream->Available(&avail)) && avail) {
  602. rv = stream->Read(buffer, 4096, &read);
  603. if (NS_FAILED(rv)) {
  604. NS_WARNING("Pref stream read failed");
  605. break;
  606. }
  607. PREF_ParseBuf(&ps, buffer, read);
  608. }
  609. PREF_FinalizeParseState(&ps);
  610. }
  611. return rv;
  612. }
  613. void
  614. Preferences::SetPreference(const PrefSetting& aPref)
  615. {
  616. pref_SetPref(aPref);
  617. }
  618. void
  619. Preferences::GetPreference(PrefSetting* aPref)
  620. {
  621. PrefHashEntry *entry = pref_HashTableLookup(aPref->name().get());
  622. if (!entry)
  623. return;
  624. if (pref_EntryHasAdvisablySizedValues(entry)) {
  625. pref_GetPrefFromEntry(entry, aPref);
  626. }
  627. }
  628. void
  629. Preferences::GetPreferences(InfallibleTArray<PrefSetting>* aPrefs)
  630. {
  631. aPrefs->SetCapacity(gHashTable->Capacity());
  632. for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
  633. auto entry = static_cast<PrefHashEntry*>(iter.Get());
  634. if (!pref_EntryHasAdvisablySizedValues(entry)) {
  635. continue;
  636. }
  637. dom::PrefSetting *pref = aPrefs->AppendElement();
  638. pref_GetPrefFromEntry(entry, pref);
  639. }
  640. }
  641. NS_IMETHODIMP
  642. Preferences::GetBranch(const char *aPrefRoot, nsIPrefBranch **_retval)
  643. {
  644. nsresult rv;
  645. if ((nullptr != aPrefRoot) && (*aPrefRoot != '\0')) {
  646. // TODO: - cache this stuff and allow consumers to share branches (hold weak references I think)
  647. RefPtr<nsPrefBranch> prefBranch = new nsPrefBranch(aPrefRoot, false);
  648. prefBranch.forget(_retval);
  649. rv = NS_OK;
  650. } else {
  651. // special case caching the default root
  652. nsCOMPtr<nsIPrefBranch> root(sRootBranch);
  653. root.forget(_retval);
  654. rv = NS_OK;
  655. }
  656. return rv;
  657. }
  658. NS_IMETHODIMP
  659. Preferences::GetDefaultBranch(const char *aPrefRoot, nsIPrefBranch **_retval)
  660. {
  661. if (!aPrefRoot || !aPrefRoot[0]) {
  662. nsCOMPtr<nsIPrefBranch> root(sDefaultRootBranch);
  663. root.forget(_retval);
  664. return NS_OK;
  665. }
  666. // TODO: - cache this stuff and allow consumers to share branches (hold weak references I think)
  667. RefPtr<nsPrefBranch> prefBranch = new nsPrefBranch(aPrefRoot, true);
  668. if (!prefBranch)
  669. return NS_ERROR_OUT_OF_MEMORY;
  670. prefBranch.forget(_retval);
  671. return NS_OK;
  672. }
  673. NS_IMETHODIMP
  674. Preferences::GetDirty(bool *_retval) {
  675. *_retval = mDirty;
  676. return NS_OK;
  677. }
  678. nsresult
  679. Preferences::NotifyServiceObservers(const char *aTopic)
  680. {
  681. nsCOMPtr<nsIObserverService> observerService =
  682. mozilla::services::GetObserverService();
  683. if (!observerService)
  684. return NS_ERROR_FAILURE;
  685. nsISupports *subject = (nsISupports *)((nsIPrefService *)this);
  686. observerService->NotifyObservers(subject, aTopic, nullptr);
  687. return NS_OK;
  688. }
  689. nsresult
  690. Preferences::UseDefaultPrefFile()
  691. {
  692. nsCOMPtr<nsIFile> aFile;
  693. nsresult rv = NS_GetSpecialDirectory(NS_APP_PREFS_50_FILE, getter_AddRefs(aFile));
  694. if (NS_SUCCEEDED(rv)) {
  695. rv = ReadAndOwnUserPrefFile(aFile);
  696. // Most likely cause of failure here is that the file didn't
  697. // exist, so save a new one. mUserPrefReadFailed will be
  698. // used to catch an error in actually reading the file.
  699. if (NS_FAILED(rv)) {
  700. if (NS_FAILED(SavePrefFileInternal(aFile)))
  701. NS_ERROR("Failed to save new shared pref file");
  702. else
  703. rv = NS_OK;
  704. }
  705. }
  706. return rv;
  707. }
  708. nsresult
  709. Preferences::UseUserPrefFile()
  710. {
  711. nsresult rv = NS_OK;
  712. nsCOMPtr<nsIFile> aFile;
  713. nsDependentCString prefsDirProp(NS_APP_PREFS_50_DIR);
  714. rv = NS_GetSpecialDirectory(prefsDirProp.get(), getter_AddRefs(aFile));
  715. if (NS_SUCCEEDED(rv) && aFile) {
  716. rv = aFile->AppendNative(NS_LITERAL_CSTRING("user.js"));
  717. if (NS_SUCCEEDED(rv)) {
  718. bool exists = false;
  719. aFile->Exists(&exists);
  720. if (exists) {
  721. rv = openPrefFile(aFile);
  722. } else {
  723. rv = NS_ERROR_FILE_NOT_FOUND;
  724. }
  725. }
  726. }
  727. return rv;
  728. }
  729. nsresult
  730. Preferences::MakeBackupPrefFile(nsIFile *aFile)
  731. {
  732. // Example: this copies "prefs.js" to "Invalidprefs.js" in the same directory.
  733. // "Invalidprefs.js" is removed if it exists, prior to making the copy.
  734. nsAutoString newFilename;
  735. nsresult rv = aFile->GetLeafName(newFilename);
  736. NS_ENSURE_SUCCESS(rv, rv);
  737. newFilename.Insert(NS_LITERAL_STRING("Invalid"), 0);
  738. nsCOMPtr<nsIFile> newFile;
  739. rv = aFile->GetParent(getter_AddRefs(newFile));
  740. NS_ENSURE_SUCCESS(rv, rv);
  741. rv = newFile->Append(newFilename);
  742. NS_ENSURE_SUCCESS(rv, rv);
  743. bool exists = false;
  744. newFile->Exists(&exists);
  745. if (exists) {
  746. rv = newFile->Remove(false);
  747. NS_ENSURE_SUCCESS(rv, rv);
  748. }
  749. rv = aFile->CopyTo(nullptr, newFilename);
  750. NS_ENSURE_SUCCESS(rv, rv);
  751. return rv;
  752. }
  753. nsresult
  754. Preferences::ReadAndOwnUserPrefFile(nsIFile *aFile)
  755. {
  756. NS_ENSURE_ARG(aFile);
  757. if (mCurrentFile == aFile)
  758. return NS_OK;
  759. mCurrentFile = aFile;
  760. nsresult rv = NS_OK;
  761. bool exists = false;
  762. mCurrentFile->Exists(&exists);
  763. if (exists) {
  764. rv = openPrefFile(mCurrentFile);
  765. if (NS_FAILED(rv)) {
  766. // Save a backup copy of the current (invalid) prefs file, since all prefs
  767. // from the error line to the end of the file will be lost (bug 361102).
  768. // TODO we should notify the user about it (bug 523725).
  769. MakeBackupPrefFile(mCurrentFile);
  770. }
  771. } else {
  772. rv = NS_ERROR_FILE_NOT_FOUND;
  773. }
  774. return rv;
  775. }
  776. nsresult
  777. Preferences::SavePrefFileInternal(nsIFile *aFile)
  778. {
  779. if (nullptr == aFile) {
  780. // the mDirty flag tells us if we should write to mCurrentFile
  781. // we only check this flag when the caller wants to write to the default
  782. if (!mDirty) {
  783. return NS_OK;
  784. }
  785. // It's possible that we never got a prefs file.
  786. nsresult rv = NS_OK;
  787. if (mCurrentFile)
  788. rv = WritePrefFile(mCurrentFile);
  789. return rv;
  790. } else {
  791. return WritePrefFile(aFile);
  792. }
  793. }
  794. nsresult
  795. Preferences::WritePrefFile(nsIFile* aFile)
  796. {
  797. nsCOMPtr<nsIOutputStream> outStreamSink;
  798. nsCOMPtr<nsIOutputStream> outStream;
  799. uint32_t writeAmount;
  800. nsresult rv;
  801. if (!gHashTable)
  802. return NS_ERROR_NOT_INITIALIZED;
  803. // execute a "safe" save by saving through a tempfile
  804. rv = NS_NewSafeLocalFileOutputStream(getter_AddRefs(outStreamSink),
  805. aFile,
  806. -1,
  807. 0600);
  808. if (NS_FAILED(rv))
  809. return rv;
  810. rv = NS_NewBufferedOutputStream(getter_AddRefs(outStream), outStreamSink, 4096);
  811. if (NS_FAILED(rv))
  812. return rv;
  813. // get the lines that we're supposed to be writing to the file
  814. uint32_t prefCount;
  815. UniquePtr<char*[]> valueArray = pref_savePrefs(gHashTable, &prefCount);
  816. /* Sort the preferences to make a readable file on disk */
  817. NS_QuickSort(valueArray.get(), prefCount, sizeof(char *),
  818. pref_CompareStrings, nullptr);
  819. // write out the file header
  820. outStream->Write(kPrefFileHeader, sizeof(kPrefFileHeader) - 1, &writeAmount);
  821. for (uint32_t valueIdx = 0; valueIdx < prefCount; valueIdx++) {
  822. char*& pref = valueArray[valueIdx];
  823. MOZ_ASSERT(pref);
  824. outStream->Write(pref, strlen(pref), &writeAmount);
  825. outStream->Write(NS_LINEBREAK, NS_LINEBREAK_LEN, &writeAmount);
  826. free(pref);
  827. pref = nullptr;
  828. }
  829. // tell the safe output stream to overwrite the real prefs file
  830. // (it'll abort if there were any errors during writing)
  831. nsCOMPtr<nsISafeOutputStream> safeStream = do_QueryInterface(outStream);
  832. NS_ASSERTION(safeStream, "expected a safe output stream!");
  833. if (safeStream) {
  834. rv = safeStream->Finish();
  835. if (NS_FAILED(rv)) {
  836. NS_WARNING("failed to save prefs file! possible data loss");
  837. return rv;
  838. }
  839. }
  840. mDirty = false;
  841. return NS_OK;
  842. }
  843. static nsresult openPrefFile(nsIFile* aFile)
  844. {
  845. nsCOMPtr<nsIInputStream> inStr;
  846. nsresult rv = NS_NewLocalFileInputStream(getter_AddRefs(inStr), aFile);
  847. if (NS_FAILED(rv))
  848. return rv;
  849. int64_t fileSize64;
  850. rv = aFile->GetFileSize(&fileSize64);
  851. if (NS_FAILED(rv))
  852. return rv;
  853. NS_ENSURE_TRUE(fileSize64 <= UINT32_MAX, NS_ERROR_FILE_TOO_BIG);
  854. uint32_t fileSize = (uint32_t)fileSize64;
  855. auto fileBuffer = MakeUniqueFallible<char[]>(fileSize);
  856. if (fileBuffer == nullptr)
  857. return NS_ERROR_OUT_OF_MEMORY;
  858. PrefParseState ps;
  859. PREF_InitParseState(&ps, PREF_ReaderCallback, ReportToConsole, nullptr);
  860. // Read is not guaranteed to return a buf the size of fileSize,
  861. // but usually will.
  862. nsresult rv2 = NS_OK;
  863. uint32_t offset = 0;
  864. for (;;) {
  865. uint32_t amtRead = 0;
  866. rv = inStr->Read(fileBuffer.get(), fileSize, &amtRead);
  867. if (NS_FAILED(rv) || amtRead == 0)
  868. break;
  869. if (!PREF_ParseBuf(&ps, fileBuffer.get(), amtRead))
  870. rv2 = NS_ERROR_FILE_CORRUPTED;
  871. offset += amtRead;
  872. if (offset == fileSize) {
  873. break;
  874. }
  875. }
  876. PREF_FinalizeParseState(&ps);
  877. return NS_FAILED(rv) ? rv : rv2;
  878. }
  879. /*
  880. * some stuff that gets called from Pref_Init()
  881. */
  882. static int
  883. pref_CompareFileNames(nsIFile* aFile1, nsIFile* aFile2, void* /*unused*/)
  884. {
  885. nsAutoCString filename1, filename2;
  886. aFile1->GetNativeLeafName(filename1);
  887. aFile2->GetNativeLeafName(filename2);
  888. return Compare(filename2, filename1);
  889. }
  890. /**
  891. * Load default pref files from a directory. The files in the
  892. * directory are sorted reverse-alphabetically; a set of "special file
  893. * names" may be specified which are loaded after all the others.
  894. */
  895. static nsresult
  896. pref_LoadPrefsInDir(nsIFile* aDir, char const *const *aSpecialFiles, uint32_t aSpecialFilesCount)
  897. {
  898. nsresult rv, rv2;
  899. bool hasMoreElements;
  900. nsCOMPtr<nsISimpleEnumerator> dirIterator;
  901. // this may fail in some normal cases, such as embedders who do not use a GRE
  902. rv = aDir->GetDirectoryEntries(getter_AddRefs(dirIterator));
  903. if (NS_FAILED(rv)) {
  904. // If the directory doesn't exist, then we have no reason to complain. We
  905. // loaded everything (and nothing) successfully.
  906. if (rv == NS_ERROR_FILE_NOT_FOUND || rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST)
  907. rv = NS_OK;
  908. return rv;
  909. }
  910. rv = dirIterator->HasMoreElements(&hasMoreElements);
  911. NS_ENSURE_SUCCESS(rv, rv);
  912. nsCOMArray<nsIFile> prefFiles(INITIAL_PREF_FILES);
  913. nsCOMArray<nsIFile> specialFiles(aSpecialFilesCount);
  914. nsCOMPtr<nsIFile> prefFile;
  915. while (hasMoreElements && NS_SUCCEEDED(rv)) {
  916. nsAutoCString leafName;
  917. nsCOMPtr<nsISupports> supports;
  918. rv = dirIterator->GetNext(getter_AddRefs(supports));
  919. prefFile = do_QueryInterface(supports);
  920. if (NS_FAILED(rv)) {
  921. break;
  922. }
  923. prefFile->GetNativeLeafName(leafName);
  924. NS_ASSERTION(!leafName.IsEmpty(), "Failure in default prefs: directory enumerator returned empty file?");
  925. // Skip non-js files
  926. if (StringEndsWith(leafName, NS_LITERAL_CSTRING(".js"),
  927. nsCaseInsensitiveCStringComparator())) {
  928. bool shouldParse = true;
  929. // separate out special files
  930. for (uint32_t i = 0; i < aSpecialFilesCount; ++i) {
  931. if (leafName.Equals(nsDependentCString(aSpecialFiles[i]))) {
  932. shouldParse = false;
  933. // special files should be process in order; we put them into
  934. // the array by index; this can make the array sparse
  935. specialFiles.ReplaceObjectAt(prefFile, i);
  936. }
  937. }
  938. if (shouldParse) {
  939. prefFiles.AppendObject(prefFile);
  940. }
  941. }
  942. rv = dirIterator->HasMoreElements(&hasMoreElements);
  943. }
  944. if (prefFiles.Count() + specialFiles.Count() == 0) {
  945. NS_WARNING("No default pref files found.");
  946. if (NS_SUCCEEDED(rv)) {
  947. rv = NS_SUCCESS_FILE_DIRECTORY_EMPTY;
  948. }
  949. return rv;
  950. }
  951. prefFiles.Sort(pref_CompareFileNames, nullptr);
  952. uint32_t arrayCount = prefFiles.Count();
  953. uint32_t i;
  954. for (i = 0; i < arrayCount; ++i) {
  955. rv2 = openPrefFile(prefFiles[i]);
  956. if (NS_FAILED(rv2)) {
  957. NS_ERROR("Default pref file not parsed successfully.");
  958. rv = rv2;
  959. }
  960. }
  961. arrayCount = specialFiles.Count();
  962. for (i = 0; i < arrayCount; ++i) {
  963. // this may be a sparse array; test before parsing
  964. nsIFile* file = specialFiles[i];
  965. if (file) {
  966. rv2 = openPrefFile(file);
  967. if (NS_FAILED(rv2)) {
  968. NS_ERROR("Special default pref file not parsed successfully.");
  969. rv = rv2;
  970. }
  971. }
  972. }
  973. return rv;
  974. }
  975. static nsresult pref_LoadPrefsInDirList(const char *listId)
  976. {
  977. nsresult rv;
  978. nsCOMPtr<nsIProperties> dirSvc(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv));
  979. if (NS_FAILED(rv))
  980. return rv;
  981. nsCOMPtr<nsISimpleEnumerator> list;
  982. dirSvc->Get(listId,
  983. NS_GET_IID(nsISimpleEnumerator),
  984. getter_AddRefs(list));
  985. if (!list)
  986. return NS_OK;
  987. bool hasMore;
  988. while (NS_SUCCEEDED(list->HasMoreElements(&hasMore)) && hasMore) {
  989. nsCOMPtr<nsISupports> elem;
  990. list->GetNext(getter_AddRefs(elem));
  991. if (!elem)
  992. continue;
  993. nsCOMPtr<nsIFile> path = do_QueryInterface(elem);
  994. if (!path)
  995. continue;
  996. nsAutoCString leaf;
  997. path->GetNativeLeafName(leaf);
  998. // Do we care if a file provided by this process fails to load?
  999. if (Substring(leaf, leaf.Length() - 4).EqualsLiteral(".xpi"))
  1000. ReadExtensionPrefs(path);
  1001. else
  1002. pref_LoadPrefsInDir(path, nullptr, 0);
  1003. }
  1004. return NS_OK;
  1005. }
  1006. static nsresult pref_ReadPrefFromJar(nsZipArchive* jarReader, const char *name)
  1007. {
  1008. nsZipItemPtr<char> manifest(jarReader, name, true);
  1009. NS_ENSURE_TRUE(manifest.Buffer(), NS_ERROR_NOT_AVAILABLE);
  1010. PrefParseState ps;
  1011. PREF_InitParseState(&ps, PREF_ReaderCallback, ReportToConsole, nullptr);
  1012. PREF_ParseBuf(&ps, manifest, manifest.Length());
  1013. PREF_FinalizeParseState(&ps);
  1014. return NS_OK;
  1015. }
  1016. //----------------------------------------------------------------------------------------
  1017. // Initialize default preference JavaScript buffers from
  1018. // appropriate TEXT resources
  1019. //----------------------------------------------------------------------------------------
  1020. static nsresult pref_InitInitialObjects()
  1021. {
  1022. nsresult rv;
  1023. // In omni.jar case, we load the following prefs:
  1024. // - jar:$gre/omni.jar!/goanna.js
  1025. // - jar:$gre/omni.jar!/defaults/pref/*.js
  1026. // In non omni.jar case, we load:
  1027. // - $gre/goanna.js
  1028. //
  1029. // In both cases, we also load:
  1030. // - $gre/defaults/pref/*.js
  1031. // This is kept for bug 591866 (channel-prefs.js should not be in omni.jar)
  1032. // on $app == $gre case ; we load all files instead of channel-prefs.js only
  1033. // to have the same behaviour as $app != $gre, where this is required as
  1034. // a supported location for GRE preferences.
  1035. //
  1036. // When $app != $gre, we additionally load, in omni.jar case:
  1037. // - jar:$app/omni.jar!/defaults/preferences/*.js
  1038. // - $app/defaults/preferences/*.js
  1039. // and in non omni.jar case:
  1040. // - $app/defaults/preferences/*.js
  1041. // When $app == $gre, we additionally load, in omni.jar case:
  1042. // - jar:$gre/omni.jar!/defaults/preferences/*.js
  1043. // Thus, in omni.jar case, we always load app-specific default preferences
  1044. // from omni.jar, whether or not $app == $gre.
  1045. nsZipFind *findPtr;
  1046. nsAutoPtr<nsZipFind> find;
  1047. nsTArray<nsCString> prefEntries;
  1048. const char *entryName;
  1049. uint16_t entryNameLen;
  1050. RefPtr<nsZipArchive> jarReader = mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE);
  1051. if (jarReader) {
  1052. // Load jar:$gre/omni.jar!/goanna.js
  1053. rv = pref_ReadPrefFromJar(jarReader, "goanna.js");
  1054. NS_ENSURE_SUCCESS(rv, rv);
  1055. // Load jar:$gre/omni.jar!/defaults/pref/*.js
  1056. rv = jarReader->FindInit("defaults/pref/*.js$", &findPtr);
  1057. NS_ENSURE_SUCCESS(rv, rv);
  1058. find = findPtr;
  1059. while (NS_SUCCEEDED(find->FindNext(&entryName, &entryNameLen))) {
  1060. prefEntries.AppendElement(Substring(entryName, entryNameLen));
  1061. }
  1062. prefEntries.Sort();
  1063. for (uint32_t i = prefEntries.Length(); i--; ) {
  1064. rv = pref_ReadPrefFromJar(jarReader, prefEntries[i].get());
  1065. if (NS_FAILED(rv))
  1066. NS_WARNING("Error parsing preferences.");
  1067. }
  1068. } else {
  1069. // Load $gre/goanna.js
  1070. nsCOMPtr<nsIFile> greprefsFile;
  1071. rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(greprefsFile));
  1072. NS_ENSURE_SUCCESS(rv, rv);
  1073. rv = greprefsFile->AppendNative(NS_LITERAL_CSTRING("goanna.js"));
  1074. NS_ENSURE_SUCCESS(rv, rv);
  1075. rv = openPrefFile(greprefsFile);
  1076. if (NS_FAILED(rv))
  1077. NS_WARNING("Error parsing GRE default preferences. Is this an old-style embedding app?");
  1078. }
  1079. // Load $gre/defaults/pref/*.js
  1080. nsCOMPtr<nsIFile> defaultPrefDir;
  1081. rv = NS_GetSpecialDirectory(NS_APP_PREF_DEFAULTS_50_DIR, getter_AddRefs(defaultPrefDir));
  1082. NS_ENSURE_SUCCESS(rv, rv);
  1083. /* these pref file names should not be used: we process them after all other application pref files for backwards compatibility */
  1084. static const char* specialFiles[] = {
  1085. #if defined(XP_WIN)
  1086. "winpref.js"
  1087. #elif defined(XP_UNIX)
  1088. "unix.js"
  1089. #endif
  1090. };
  1091. rv = pref_LoadPrefsInDir(defaultPrefDir, specialFiles, ArrayLength(specialFiles));
  1092. if (NS_FAILED(rv))
  1093. NS_WARNING("Error parsing application default preferences.");
  1094. // Load jar:$app/omni.jar!/defaults/preferences/*.js
  1095. // or jar:$gre/omni.jar!/defaults/preferences/*.js.
  1096. RefPtr<nsZipArchive> appJarReader = mozilla::Omnijar::GetReader(mozilla::Omnijar::APP);
  1097. // GetReader(mozilla::Omnijar::APP) returns null when $app == $gre, in which
  1098. // case we look for app-specific default preferences in $gre.
  1099. if (!appJarReader)
  1100. appJarReader = mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE);
  1101. if (appJarReader) {
  1102. rv = appJarReader->FindInit("defaults/preferences/*.js$", &findPtr);
  1103. NS_ENSURE_SUCCESS(rv, rv);
  1104. find = findPtr;
  1105. prefEntries.Clear();
  1106. while (NS_SUCCEEDED(find->FindNext(&entryName, &entryNameLen))) {
  1107. prefEntries.AppendElement(Substring(entryName, entryNameLen));
  1108. }
  1109. prefEntries.Sort();
  1110. for (uint32_t i = prefEntries.Length(); i--; ) {
  1111. rv = pref_ReadPrefFromJar(appJarReader, prefEntries[i].get());
  1112. if (NS_FAILED(rv))
  1113. NS_WARNING("Error parsing preferences.");
  1114. }
  1115. }
  1116. rv = pref_LoadPrefsInDirList(NS_APP_PREFS_DEFAULTS_DIR_LIST);
  1117. NS_ENSURE_SUCCESS(rv, rv);
  1118. // Set up the correct default for toolkit.telemetry.enabled.
  1119. // If this build has MOZ_TELEMETRY_ON_BY_DEFAULT *or* we're on the beta
  1120. // channel, telemetry is on by default, otherwise not. This is necessary
  1121. // so that beta users who are testing final release builds don't flipflop
  1122. // defaults.
  1123. if (Preferences::GetDefaultType(kTelemetryPref) == nsIPrefBranch::PREF_INVALID) {
  1124. bool prerelease = false;
  1125. #ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
  1126. prerelease = true;
  1127. #else
  1128. if (Preferences::GetDefaultCString(kChannelPref).EqualsLiteral("beta")) {
  1129. prerelease = true;
  1130. }
  1131. #endif
  1132. PREF_SetBoolPref(kTelemetryPref, prerelease, true);
  1133. }
  1134. NS_CreateServicesFromCategory(NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID,
  1135. nullptr, NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID);
  1136. nsCOMPtr<nsIObserverService> observerService =
  1137. mozilla::services::GetObserverService();
  1138. if (!observerService)
  1139. return NS_ERROR_FAILURE;
  1140. observerService->NotifyObservers(nullptr, NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID, nullptr);
  1141. return pref_LoadPrefsInDirList(NS_EXT_PREFS_DEFAULTS_DIR_LIST);
  1142. }
  1143. /******************************************************************************
  1144. *
  1145. * static utilities
  1146. *
  1147. ******************************************************************************/
  1148. // static
  1149. nsresult
  1150. Preferences::GetBool(const char* aPref, bool* aResult)
  1151. {
  1152. NS_PRECONDITION(aResult, "aResult must not be NULL");
  1153. NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1154. return PREF_GetBoolPref(aPref, aResult, false);
  1155. }
  1156. // static
  1157. nsresult
  1158. Preferences::GetInt(const char* aPref, int32_t* aResult)
  1159. {
  1160. NS_PRECONDITION(aResult, "aResult must not be NULL");
  1161. NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1162. return PREF_GetIntPref(aPref, aResult, false);
  1163. }
  1164. // static
  1165. nsresult
  1166. Preferences::GetFloat(const char* aPref, float* aResult)
  1167. {
  1168. NS_PRECONDITION(aResult, "aResult must not be NULL");
  1169. NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1170. nsAutoCString result;
  1171. nsresult rv = PREF_CopyCharPref(aPref, getter_Copies(result), false);
  1172. if (NS_SUCCEEDED(rv)) {
  1173. *aResult = result.ToFloat(&rv);
  1174. }
  1175. return rv;
  1176. }
  1177. // static
  1178. nsAdoptingCString
  1179. Preferences::GetCString(const char* aPref)
  1180. {
  1181. nsAdoptingCString result;
  1182. PREF_CopyCharPref(aPref, getter_Copies(result), false);
  1183. return result;
  1184. }
  1185. // static
  1186. nsAdoptingString
  1187. Preferences::GetString(const char* aPref)
  1188. {
  1189. nsAdoptingString result;
  1190. GetString(aPref, &result);
  1191. return result;
  1192. }
  1193. // static
  1194. nsresult
  1195. Preferences::GetCString(const char* aPref, nsACString* aResult)
  1196. {
  1197. NS_PRECONDITION(aResult, "aResult must not be NULL");
  1198. NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1199. nsAutoCString result;
  1200. nsresult rv = PREF_CopyCharPref(aPref, getter_Copies(result), false);
  1201. if (NS_SUCCEEDED(rv)) {
  1202. *aResult = result;
  1203. }
  1204. return rv;
  1205. }
  1206. // static
  1207. nsresult
  1208. Preferences::GetString(const char* aPref, nsAString* aResult)
  1209. {
  1210. NS_PRECONDITION(aResult, "aResult must not be NULL");
  1211. NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1212. nsAutoCString result;
  1213. nsresult rv = PREF_CopyCharPref(aPref, getter_Copies(result), false);
  1214. if (NS_SUCCEEDED(rv)) {
  1215. CopyUTF8toUTF16(result, *aResult);
  1216. }
  1217. return rv;
  1218. }
  1219. // static
  1220. nsAdoptingCString
  1221. Preferences::GetLocalizedCString(const char* aPref)
  1222. {
  1223. nsAdoptingCString result;
  1224. GetLocalizedCString(aPref, &result);
  1225. return result;
  1226. }
  1227. // static
  1228. nsAdoptingString
  1229. Preferences::GetLocalizedString(const char* aPref)
  1230. {
  1231. nsAdoptingString result;
  1232. GetLocalizedString(aPref, &result);
  1233. return result;
  1234. }
  1235. // static
  1236. nsresult
  1237. Preferences::GetLocalizedCString(const char* aPref, nsACString* aResult)
  1238. {
  1239. NS_PRECONDITION(aResult, "aResult must not be NULL");
  1240. nsAutoString result;
  1241. nsresult rv = GetLocalizedString(aPref, &result);
  1242. if (NS_SUCCEEDED(rv)) {
  1243. CopyUTF16toUTF8(result, *aResult);
  1244. }
  1245. return rv;
  1246. }
  1247. // static
  1248. nsresult
  1249. Preferences::GetLocalizedString(const char* aPref, nsAString* aResult)
  1250. {
  1251. NS_PRECONDITION(aResult, "aResult must not be NULL");
  1252. NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1253. nsCOMPtr<nsIPrefLocalizedString> prefLocalString;
  1254. nsresult rv = sRootBranch->GetComplexValue(aPref,
  1255. NS_GET_IID(nsIPrefLocalizedString),
  1256. getter_AddRefs(prefLocalString));
  1257. if (NS_SUCCEEDED(rv)) {
  1258. NS_ASSERTION(prefLocalString, "Succeeded but the result is NULL");
  1259. prefLocalString->GetData(getter_Copies(*aResult));
  1260. }
  1261. return rv;
  1262. }
  1263. // static
  1264. nsresult
  1265. Preferences::GetComplex(const char* aPref, const nsIID &aType, void** aResult)
  1266. {
  1267. NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1268. return sRootBranch->GetComplexValue(aPref, aType, aResult);
  1269. }
  1270. // static
  1271. nsresult
  1272. Preferences::SetCString(const char* aPref, const char* aValue)
  1273. {
  1274. ENSURE_MAIN_PROCESS("Cannot SetCString from content process:", aPref);
  1275. NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1276. return PREF_SetCharPref(aPref, aValue, false);
  1277. }
  1278. // static
  1279. nsresult
  1280. Preferences::SetCString(const char* aPref, const nsACString &aValue)
  1281. {
  1282. ENSURE_MAIN_PROCESS("Cannot SetCString from content process:", aPref);
  1283. NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1284. return PREF_SetCharPref(aPref, PromiseFlatCString(aValue).get(), false);
  1285. }
  1286. // static
  1287. nsresult
  1288. Preferences::SetString(const char* aPref, const char16ptr_t aValue)
  1289. {
  1290. ENSURE_MAIN_PROCESS("Cannot SetString from content process:", aPref);
  1291. NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1292. return PREF_SetCharPref(aPref, NS_ConvertUTF16toUTF8(aValue).get(), false);
  1293. }
  1294. // static
  1295. nsresult
  1296. Preferences::SetString(const char* aPref, const nsAString &aValue)
  1297. {
  1298. ENSURE_MAIN_PROCESS("Cannot SetString from content process:", aPref);
  1299. NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1300. return PREF_SetCharPref(aPref, NS_ConvertUTF16toUTF8(aValue).get(), false);
  1301. }
  1302. // static
  1303. nsresult
  1304. Preferences::SetBool(const char* aPref, bool aValue)
  1305. {
  1306. ENSURE_MAIN_PROCESS("Cannot SetBool from content process:", aPref);
  1307. NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1308. return PREF_SetBoolPref(aPref, aValue, false);
  1309. }
  1310. // static
  1311. nsresult
  1312. Preferences::SetInt(const char* aPref, int32_t aValue)
  1313. {
  1314. ENSURE_MAIN_PROCESS("Cannot SetInt from content process:", aPref);
  1315. NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1316. return PREF_SetIntPref(aPref, aValue, false);
  1317. }
  1318. // static
  1319. nsresult
  1320. Preferences::SetFloat(const char* aPref, float aValue)
  1321. {
  1322. return SetCString(aPref, nsPrintfCString("%f", aValue).get());
  1323. }
  1324. // static
  1325. nsresult
  1326. Preferences::SetComplex(const char* aPref, const nsIID &aType,
  1327. nsISupports* aValue)
  1328. {
  1329. NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1330. return sRootBranch->SetComplexValue(aPref, aType, aValue);
  1331. }
  1332. // static
  1333. nsresult
  1334. Preferences::ClearUser(const char* aPref)
  1335. {
  1336. ENSURE_MAIN_PROCESS("Cannot ClearUser from content process:", aPref);
  1337. NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1338. return PREF_ClearUserPref(aPref);
  1339. }
  1340. // static
  1341. bool
  1342. Preferences::HasUserValue(const char* aPref)
  1343. {
  1344. NS_ENSURE_TRUE(InitStaticMembers(), false);
  1345. return PREF_HasUserPref(aPref);
  1346. }
  1347. // static
  1348. int32_t
  1349. Preferences::GetType(const char* aPref)
  1350. {
  1351. NS_ENSURE_TRUE(InitStaticMembers(), nsIPrefBranch::PREF_INVALID);
  1352. int32_t result;
  1353. return NS_SUCCEEDED(sRootBranch->GetPrefType(aPref, &result)) ?
  1354. result : nsIPrefBranch::PREF_INVALID;
  1355. }
  1356. // static
  1357. nsresult
  1358. Preferences::AddStrongObserver(nsIObserver* aObserver,
  1359. const char* aPref)
  1360. {
  1361. NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1362. return sRootBranch->AddObserver(aPref, aObserver, false);
  1363. }
  1364. // static
  1365. nsresult
  1366. Preferences::AddWeakObserver(nsIObserver* aObserver,
  1367. const char* aPref)
  1368. {
  1369. NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1370. return sRootBranch->AddObserver(aPref, aObserver, true);
  1371. }
  1372. // static
  1373. nsresult
  1374. Preferences::RemoveObserver(nsIObserver* aObserver,
  1375. const char* aPref)
  1376. {
  1377. if (!sPreferences && sShutdown) {
  1378. return NS_OK; // Observers have been released automatically.
  1379. }
  1380. NS_ENSURE_TRUE(sPreferences, NS_ERROR_NOT_AVAILABLE);
  1381. return sRootBranch->RemoveObserver(aPref, aObserver);
  1382. }
  1383. // static
  1384. nsresult
  1385. Preferences::AddStrongObservers(nsIObserver* aObserver,
  1386. const char** aPrefs)
  1387. {
  1388. for (uint32_t i = 0; aPrefs[i]; i++) {
  1389. nsresult rv = AddStrongObserver(aObserver, aPrefs[i]);
  1390. NS_ENSURE_SUCCESS(rv, rv);
  1391. }
  1392. return NS_OK;
  1393. }
  1394. // static
  1395. nsresult
  1396. Preferences::AddWeakObservers(nsIObserver* aObserver,
  1397. const char** aPrefs)
  1398. {
  1399. for (uint32_t i = 0; aPrefs[i]; i++) {
  1400. nsresult rv = AddWeakObserver(aObserver, aPrefs[i]);
  1401. NS_ENSURE_SUCCESS(rv, rv);
  1402. }
  1403. return NS_OK;
  1404. }
  1405. // static
  1406. nsresult
  1407. Preferences::RemoveObservers(nsIObserver* aObserver,
  1408. const char** aPrefs)
  1409. {
  1410. if (!sPreferences && sShutdown) {
  1411. return NS_OK; // Observers have been released automatically.
  1412. }
  1413. NS_ENSURE_TRUE(sPreferences, NS_ERROR_NOT_AVAILABLE);
  1414. for (uint32_t i = 0; aPrefs[i]; i++) {
  1415. nsresult rv = RemoveObserver(aObserver, aPrefs[i]);
  1416. NS_ENSURE_SUCCESS(rv, rv);
  1417. }
  1418. return NS_OK;
  1419. }
  1420. // static
  1421. nsresult
  1422. Preferences::RegisterCallback(PrefChangedFunc aCallback,
  1423. const char* aPref,
  1424. void* aClosure,
  1425. MatchKind aMatchKind)
  1426. {
  1427. NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1428. ValueObserverHashKey hashKey(aPref, aCallback, aMatchKind);
  1429. RefPtr<ValueObserver> observer;
  1430. gObserverTable->Get(&hashKey, getter_AddRefs(observer));
  1431. if (observer) {
  1432. observer->AppendClosure(aClosure);
  1433. return NS_OK;
  1434. }
  1435. observer = new ValueObserver(aPref, aCallback, aMatchKind);
  1436. observer->AppendClosure(aClosure);
  1437. nsresult rv = AddStrongObserver(observer, aPref);
  1438. NS_ENSURE_SUCCESS(rv, rv);
  1439. gObserverTable->Put(observer, observer);
  1440. return NS_OK;
  1441. }
  1442. // static
  1443. nsresult
  1444. Preferences::RegisterCallbackAndCall(PrefChangedFunc aCallback,
  1445. const char* aPref,
  1446. void* aClosure,
  1447. MatchKind aMatchKind)
  1448. {
  1449. nsresult rv = RegisterCallback(aCallback, aPref, aClosure, aMatchKind);
  1450. if (NS_SUCCEEDED(rv)) {
  1451. (*aCallback)(aPref, aClosure);
  1452. }
  1453. return rv;
  1454. }
  1455. // static
  1456. nsresult
  1457. Preferences::UnregisterCallback(PrefChangedFunc aCallback,
  1458. const char* aPref,
  1459. void* aClosure,
  1460. MatchKind aMatchKind)
  1461. {
  1462. if (!sPreferences && sShutdown) {
  1463. return NS_OK; // Observers have been released automatically.
  1464. }
  1465. NS_ENSURE_TRUE(sPreferences, NS_ERROR_NOT_AVAILABLE);
  1466. ValueObserverHashKey hashKey(aPref, aCallback, aMatchKind);
  1467. RefPtr<ValueObserver> observer;
  1468. gObserverTable->Get(&hashKey, getter_AddRefs(observer));
  1469. if (!observer) {
  1470. return NS_OK;
  1471. }
  1472. observer->RemoveClosure(aClosure);
  1473. if (observer->HasNoClosures()) {
  1474. // Delete the callback since its list of closures is empty.
  1475. gObserverTable->Remove(observer);
  1476. }
  1477. return NS_OK;
  1478. }
  1479. static void BoolVarChanged(const char* aPref, void* aClosure)
  1480. {
  1481. CacheData* cache = static_cast<CacheData*>(aClosure);
  1482. *((bool*)cache->cacheLocation) =
  1483. Preferences::GetBool(aPref, cache->defaultValueBool);
  1484. }
  1485. // static
  1486. nsresult
  1487. Preferences::AddBoolVarCache(bool* aCache,
  1488. const char* aPref,
  1489. bool aDefault)
  1490. {
  1491. NS_ASSERTION(aCache, "aCache must not be NULL");
  1492. #ifdef DEBUG
  1493. AssertNotAlreadyCached("bool", aPref, aCache);
  1494. #endif
  1495. *aCache = GetBool(aPref, aDefault);
  1496. CacheData* data = new CacheData();
  1497. data->cacheLocation = aCache;
  1498. data->defaultValueBool = aDefault;
  1499. gCacheData->AppendElement(data);
  1500. return RegisterCallback(BoolVarChanged, aPref, data, ExactMatch);
  1501. }
  1502. static void IntVarChanged(const char* aPref, void* aClosure)
  1503. {
  1504. CacheData* cache = static_cast<CacheData*>(aClosure);
  1505. *((int32_t*)cache->cacheLocation) =
  1506. Preferences::GetInt(aPref, cache->defaultValueInt);
  1507. }
  1508. // static
  1509. nsresult
  1510. Preferences::AddIntVarCache(int32_t* aCache,
  1511. const char* aPref,
  1512. int32_t aDefault)
  1513. {
  1514. NS_ASSERTION(aCache, "aCache must not be NULL");
  1515. #ifdef DEBUG
  1516. AssertNotAlreadyCached("int", aPref, aCache);
  1517. #endif
  1518. *aCache = Preferences::GetInt(aPref, aDefault);
  1519. CacheData* data = new CacheData();
  1520. data->cacheLocation = aCache;
  1521. data->defaultValueInt = aDefault;
  1522. gCacheData->AppendElement(data);
  1523. return RegisterCallback(IntVarChanged, aPref, data, ExactMatch);
  1524. }
  1525. static void UintVarChanged(const char* aPref, void* aClosure)
  1526. {
  1527. CacheData* cache = static_cast<CacheData*>(aClosure);
  1528. *((uint32_t*)cache->cacheLocation) =
  1529. Preferences::GetUint(aPref, cache->defaultValueUint);
  1530. }
  1531. // static
  1532. nsresult
  1533. Preferences::AddUintVarCache(uint32_t* aCache,
  1534. const char* aPref,
  1535. uint32_t aDefault)
  1536. {
  1537. NS_ASSERTION(aCache, "aCache must not be NULL");
  1538. #ifdef DEBUG
  1539. AssertNotAlreadyCached("uint", aPref, aCache);
  1540. #endif
  1541. *aCache = Preferences::GetUint(aPref, aDefault);
  1542. CacheData* data = new CacheData();
  1543. data->cacheLocation = aCache;
  1544. data->defaultValueUint = aDefault;
  1545. gCacheData->AppendElement(data);
  1546. return RegisterCallback(UintVarChanged, aPref, data, ExactMatch);
  1547. }
  1548. template <MemoryOrdering Order>
  1549. static void AtomicUintVarChanged(const char* aPref, void* aClosure)
  1550. {
  1551. CacheData* cache = static_cast<CacheData*>(aClosure);
  1552. *((Atomic<uint32_t, Order>*)cache->cacheLocation) =
  1553. Preferences::GetUint(aPref, cache->defaultValueUint);
  1554. }
  1555. template <MemoryOrdering Order>
  1556. // static
  1557. nsresult
  1558. Preferences::AddAtomicUintVarCache(Atomic<uint32_t, Order>* aCache,
  1559. const char* aPref,
  1560. uint32_t aDefault)
  1561. {
  1562. NS_ASSERTION(aCache, "aCache must not be NULL");
  1563. #ifdef DEBUG
  1564. AssertNotAlreadyCached("uint", aPref, aCache);
  1565. #endif
  1566. *aCache = Preferences::GetUint(aPref, aDefault);
  1567. CacheData* data = new CacheData();
  1568. data->cacheLocation = aCache;
  1569. data->defaultValueUint = aDefault;
  1570. gCacheData->AppendElement(data);
  1571. return RegisterCallback(AtomicUintVarChanged<Order>, aPref, data, ExactMatch);
  1572. }
  1573. // Since the definition of this template function is not in a header file,
  1574. // we need to explicitly specify the instantiations that are required.
  1575. // Currently only the order=Relaxed variant is needed.
  1576. template
  1577. nsresult Preferences::AddAtomicUintVarCache(Atomic<uint32_t,Relaxed>*,
  1578. const char*, uint32_t);
  1579. static void FloatVarChanged(const char* aPref, void* aClosure)
  1580. {
  1581. CacheData* cache = static_cast<CacheData*>(aClosure);
  1582. *((float*)cache->cacheLocation) =
  1583. Preferences::GetFloat(aPref, cache->defaultValueFloat);
  1584. }
  1585. // static
  1586. nsresult
  1587. Preferences::AddFloatVarCache(float* aCache,
  1588. const char* aPref,
  1589. float aDefault)
  1590. {
  1591. NS_ASSERTION(aCache, "aCache must not be NULL");
  1592. #ifdef DEBUG
  1593. AssertNotAlreadyCached("float", aPref, aCache);
  1594. #endif
  1595. *aCache = Preferences::GetFloat(aPref, aDefault);
  1596. CacheData* data = new CacheData();
  1597. data->cacheLocation = aCache;
  1598. data->defaultValueFloat = aDefault;
  1599. gCacheData->AppendElement(data);
  1600. return RegisterCallback(FloatVarChanged, aPref, data, ExactMatch);
  1601. }
  1602. // static
  1603. nsresult
  1604. Preferences::GetDefaultBool(const char* aPref, bool* aResult)
  1605. {
  1606. NS_PRECONDITION(aResult, "aResult must not be NULL");
  1607. NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1608. return PREF_GetBoolPref(aPref, aResult, true);
  1609. }
  1610. // static
  1611. nsresult
  1612. Preferences::GetDefaultInt(const char* aPref, int32_t* aResult)
  1613. {
  1614. NS_PRECONDITION(aResult, "aResult must not be NULL");
  1615. NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1616. return PREF_GetIntPref(aPref, aResult, true);
  1617. }
  1618. // static
  1619. nsresult
  1620. Preferences::GetDefaultCString(const char* aPref, nsACString* aResult)
  1621. {
  1622. NS_PRECONDITION(aResult, "aResult must not be NULL");
  1623. NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1624. nsAutoCString result;
  1625. nsresult rv = PREF_CopyCharPref(aPref, getter_Copies(result), true);
  1626. if (NS_SUCCEEDED(rv)) {
  1627. *aResult = result;
  1628. }
  1629. return rv;
  1630. }
  1631. // static
  1632. nsresult
  1633. Preferences::GetDefaultString(const char* aPref, nsAString* aResult)
  1634. {
  1635. NS_PRECONDITION(aResult, "aResult must not be NULL");
  1636. NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1637. nsAutoCString result;
  1638. nsresult rv = PREF_CopyCharPref(aPref, getter_Copies(result), true);
  1639. if (NS_SUCCEEDED(rv)) {
  1640. CopyUTF8toUTF16(result, *aResult);
  1641. }
  1642. return rv;
  1643. }
  1644. // static
  1645. nsresult
  1646. Preferences::GetDefaultLocalizedCString(const char* aPref,
  1647. nsACString* aResult)
  1648. {
  1649. nsAutoString result;
  1650. nsresult rv = GetDefaultLocalizedString(aPref, &result);
  1651. if (NS_SUCCEEDED(rv)) {
  1652. CopyUTF16toUTF8(result, *aResult);
  1653. }
  1654. return rv;
  1655. }
  1656. // static
  1657. nsresult
  1658. Preferences::GetDefaultLocalizedString(const char* aPref,
  1659. nsAString* aResult)
  1660. {
  1661. NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1662. nsCOMPtr<nsIPrefLocalizedString> prefLocalString;
  1663. nsresult rv =
  1664. sDefaultRootBranch->GetComplexValue(aPref,
  1665. NS_GET_IID(nsIPrefLocalizedString),
  1666. getter_AddRefs(prefLocalString));
  1667. if (NS_SUCCEEDED(rv)) {
  1668. NS_ASSERTION(prefLocalString, "Succeeded but the result is NULL");
  1669. prefLocalString->GetData(getter_Copies(*aResult));
  1670. }
  1671. return rv;
  1672. }
  1673. // static
  1674. nsAdoptingString
  1675. Preferences::GetDefaultString(const char* aPref)
  1676. {
  1677. nsAdoptingString result;
  1678. GetDefaultString(aPref, &result);
  1679. return result;
  1680. }
  1681. // static
  1682. nsAdoptingCString
  1683. Preferences::GetDefaultCString(const char* aPref)
  1684. {
  1685. nsAdoptingCString result;
  1686. PREF_CopyCharPref(aPref, getter_Copies(result), true);
  1687. return result;
  1688. }
  1689. // static
  1690. nsAdoptingString
  1691. Preferences::GetDefaultLocalizedString(const char* aPref)
  1692. {
  1693. nsAdoptingString result;
  1694. GetDefaultLocalizedString(aPref, &result);
  1695. return result;
  1696. }
  1697. // static
  1698. nsAdoptingCString
  1699. Preferences::GetDefaultLocalizedCString(const char* aPref)
  1700. {
  1701. nsAdoptingCString result;
  1702. GetDefaultLocalizedCString(aPref, &result);
  1703. return result;
  1704. }
  1705. // static
  1706. nsresult
  1707. Preferences::GetDefaultComplex(const char* aPref, const nsIID &aType,
  1708. void** aResult)
  1709. {
  1710. NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
  1711. return sDefaultRootBranch->GetComplexValue(aPref, aType, aResult);
  1712. }
  1713. // static
  1714. int32_t
  1715. Preferences::GetDefaultType(const char* aPref)
  1716. {
  1717. NS_ENSURE_TRUE(InitStaticMembers(), nsIPrefBranch::PREF_INVALID);
  1718. int32_t result;
  1719. return NS_SUCCEEDED(sDefaultRootBranch->GetPrefType(aPref, &result)) ?
  1720. result : nsIPrefBranch::PREF_INVALID;
  1721. }
  1722. } // namespace mozilla
  1723. #undef ENSURE_MAIN_PROCESS