Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp
Warning:line 4388, column 5
Value stored to 'rv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_modules_libpref0.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/modules/libpref -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/modules/libpref -resource-dir /usr/lib/llvm-18/lib/clang/18 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D OS_ARCH=Linux -D MOZ_WIDGET_TOOLKIT=gtk -D MOZ_SERVICES_SYNC -D MOZ_BUILD_APP_IS_BROWSER -D MOZ_WEBEXT_WEBIDL_ENABLED -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /var/lib/jenkins/workspace/firefox-scan-build/modules/libpref -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/modules/libpref -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /var/lib/jenkins/workspace/firefox-scan-build/ipc/chromium/src -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-07-21-021012-413605-1 -x c++ Unified_cpp_modules_libpref0.cpp
1/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3/* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7// Documentation for libpref is in modules/libpref/docs/index.rst.
8
9#include <ctype.h>
10#include <stdlib.h>
11#include <string.h>
12
13#include "SharedPrefMap.h"
14
15#include "base/basictypes.h"
16#include "MainThreadUtils.h"
17#include "mozilla/AppShutdown.h"
18#include "mozilla/ArenaAllocatorExtensions.h"
19#include "mozilla/ArenaAllocator.h"
20#include "mozilla/ArrayUtils.h"
21#include "mozilla/Attributes.h"
22#include "mozilla/Components.h"
23#include "mozilla/dom/PContent.h"
24#include "mozilla/dom/Promise.h"
25#include "mozilla/dom/RemoteType.h"
26#include "mozilla/HashFunctions.h"
27#include "mozilla/HashTable.h"
28#include "mozilla/Logging.h"
29#include "mozilla/Maybe.h"
30#include "mozilla/MemoryReporting.h"
31#include "mozilla/Omnijar.h"
32#include "mozilla/Preferences.h"
33#include "mozilla/ProfilerLabels.h"
34#include "mozilla/ProfilerMarkers.h"
35#include "mozilla/ResultExtensions.h"
36#include "mozilla/SchedulerGroup.h"
37#include "mozilla/ScopeExit.h"
38#include "mozilla/ServoStyleSet.h"
39#include "mozilla/SpinEventLoopUntil.h"
40#include "mozilla/StaticMutex.h"
41#include "mozilla/StaticPrefsAll.h"
42#include "mozilla/StaticPtr.h"
43#include "mozilla/SyncRunnable.h"
44#include "mozilla/Telemetry.h"
45#include "mozilla/TelemetryEventEnums.h"
46#include "mozilla/Try.h"
47#include "mozilla/UniquePtrExtensions.h"
48#include "mozilla/URLPreloader.h"
49#include "mozilla/Variant.h"
50#include "mozilla/Vector.h"
51#include "nsAppDirectoryServiceDefs.h"
52#include "nsCategoryManagerUtils.h"
53#include "nsClassHashtable.h"
54#include "nsCOMArray.h"
55#include "nsCOMPtr.h"
56#include "nsComponentManagerUtils.h"
57#include "nsContentUtils.h"
58#include "nsCRT.h"
59#include "nsTHashMap.h"
60#include "nsDirectoryServiceDefs.h"
61#include "nsIConsoleService.h"
62#include "nsIFile.h"
63#include "nsIMemoryReporter.h"
64#include "nsIObserver.h"
65#include "nsIObserverService.h"
66#include "nsIOutputStream.h"
67#include "nsIPrefBranch.h"
68#include "nsIPrefLocalizedString.h"
69#include "nsIRelativeFilePref.h"
70#include "nsISafeOutputStream.h"
71#include "nsISimpleEnumerator.h"
72#include "nsIStringBundle.h"
73#include "nsISupportsImpl.h"
74#include "nsISupportsPrimitives.h"
75#include "nsIZipReader.h"
76#include "nsNetUtil.h"
77#include "nsPrintfCString.h"
78#include "nsProxyRelease.h"
79#include "nsReadableUtils.h"
80#include "nsRefPtrHashtable.h"
81#include "nsRelativeFilePref.h"
82#include "nsString.h"
83#include "nsTArray.h"
84#include "nsThreadUtils.h"
85#include "nsUTF8Utils.h"
86#include "nsWeakReference.h"
87#include "nsXPCOMCID.h"
88#include "nsXPCOM.h"
89#include "nsXULAppAPI.h"
90#include "nsZipArchive.h"
91#include "plbase64.h"
92#include "PLDHashTable.h"
93#include "prdtoa.h"
94#include "prlink.h"
95#include "xpcpublic.h"
96#include "js/RootingAPI.h"
97#ifdef MOZ_BACKGROUNDTASKS1
98# include "mozilla/BackgroundTasks.h"
99#endif
100
101#ifdef DEBUG1
102# include <map>
103#endif
104
105#ifdef MOZ_MEMORY1
106# include "mozmemory.h"
107#endif
108
109#ifdef XP_WIN
110# include "windows.h"
111#endif
112
113#if defined(MOZ_WIDGET_GTK1)
114# include "mozilla/WidgetUtilsGtk.h"
115#endif // defined(MOZ_WIDGET_GTK)
116
117#ifdef MOZ_WIDGET_COCOA
118# include "ChannelPrefsUtil.h"
119#endif
120
121using namespace mozilla;
122
123using dom::Promise;
124using ipc::FileDescriptor;
125
126#ifdef DEBUG1
127
128# define ENSURE_PARENT_PROCESS(func, pref) \
129 do { \
130 if (MOZ_UNLIKELY(!XRE_IsParentProcess())(__builtin_expect(!!(!XRE_IsParentProcess()), 0))) { \
131 nsPrintfCString msg( \
132 "ENSURE_PARENT_PROCESS: called %s on %s in a non-parent process", \
133 func, pref); \
134 NS_ERROR(msg.get())do { NS_DebugBreak(NS_DEBUG_ASSERTION, msg.get(), "Error", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 134); MOZ_PretendNoReturn(); } while (0)
; \
135 return NS_ERROR_NOT_AVAILABLE; \
136 } \
137 } while (0)
138
139#else // DEBUG
140
141# define ENSURE_PARENT_PROCESS(func, pref) \
142 if (MOZ_UNLIKELY(!XRE_IsParentProcess())(__builtin_expect(!!(!XRE_IsParentProcess()), 0))) { \
143 return NS_ERROR_NOT_AVAILABLE; \
144 }
145
146#endif // DEBUG
147
148// Forward declarations.
149namespace mozilla::StaticPrefs {
150
151static void InitAll();
152static void StartObservingAlwaysPrefs();
153static void InitOncePrefs();
154static void InitStaticPrefsFromShared();
155static void RegisterOncePrefs(SharedPrefMapBuilder& aBuilder);
156static void ShutdownAlwaysPrefs();
157
158} // namespace mozilla::StaticPrefs
159
160//===========================================================================
161// Low-level types and operations
162//===========================================================================
163
164Atomic<bool, mozilla::Relaxed> sPrefTelemetryEventEnabled(false);
165
166typedef nsTArray<nsCString> PrefSaveData;
167
168// 1 MB should be enough for everyone.
169static const uint32_t MAX_PREF_LENGTH = 1 * 1024 * 1024;
170// Actually, 4kb should be enough for everyone.
171static const uint32_t MAX_ADVISABLE_PREF_LENGTH = 4 * 1024;
172
173// This is used for pref names and string pref values. We encode the string
174// length, then a '/', then the string chars. This encoding means there are no
175// special chars that are forbidden or require escaping.
176static void SerializeAndAppendString(const nsCString& aChars, nsCString& aStr) {
177 aStr.AppendInt(uint64_t(aChars.Length()));
178 aStr.Append('/');
179 aStr.Append(aChars);
180}
181
182static char* DeserializeString(char* aChars, nsCString& aStr) {
183 char* p = aChars;
184 uint32_t length = strtol(p, &p, 10);
185 MOZ_ASSERT(p[0] == '/')do { static_assert( mozilla::detail::AssertionConditionType<
decltype(p[0] == '/')>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(p[0] == '/'))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("p[0] == '/'", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 185); AnnotateMozCrashReason("MOZ_ASSERT" "(" "p[0] == '/'"
")"); do { *((volatile int*)__null) = 185; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
186 p++; // move past the '/'
187 aStr.Assign(p, length);
188 p += length; // move past the string itself
189 return p;
190}
191
192// Keep this in sync with PrefValue in parser/src/lib.rs.
193union PrefValue {
194 // PrefValues within Pref objects own their chars. PrefValues passed around
195 // as arguments don't own their chars.
196 const char* mStringVal;
197 int32_t mIntVal;
198 bool mBoolVal;
199
200 PrefValue() = default;
201
202 explicit PrefValue(bool aVal) : mBoolVal(aVal) {}
203
204 explicit PrefValue(int32_t aVal) : mIntVal(aVal) {}
205
206 explicit PrefValue(const char* aVal) : mStringVal(aVal) {}
207
208 bool Equals(PrefType aType, PrefValue aValue) {
209 switch (aType) {
210 case PrefType::String: {
211 if (mStringVal && aValue.mStringVal) {
212 return strcmp(mStringVal, aValue.mStringVal) == 0;
213 }
214 if (!mStringVal && !aValue.mStringVal) {
215 return true;
216 }
217 return false;
218 }
219
220 case PrefType::Int:
221 return mIntVal == aValue.mIntVal;
222
223 case PrefType::Bool:
224 return mBoolVal == aValue.mBoolVal;
225
226 default:
227 MOZ_CRASH("Unhandled enum value")do { do { } while (false); MOZ_ReportCrash("" "Unhandled enum value"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 227); AnnotateMozCrashReason("MOZ_CRASH(" "Unhandled enum value"
")"); do { *((volatile int*)__null) = 227; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
228 }
229 }
230
231 template <typename T>
232 T Get() const;
233
234 void Init(PrefType aNewType, PrefValue aNewValue) {
235 if (aNewType == PrefType::String) {
236 MOZ_ASSERT(aNewValue.mStringVal)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNewValue.mStringVal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aNewValue.mStringVal))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("aNewValue.mStringVal"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 236); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewValue.mStringVal"
")"); do { *((volatile int*)__null) = 236; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
237 aNewValue.mStringVal = moz_xstrdup(aNewValue.mStringVal);
238 }
239 *this = aNewValue;
240 }
241
242 void Clear(PrefType aType) {
243 if (aType == PrefType::String) {
244 free(const_cast<char*>(mStringVal));
245 }
246
247 // Zero the entire value (regardless of type) via mStringVal.
248 mStringVal = nullptr;
249 }
250
251 void Replace(bool aHasValue, PrefType aOldType, PrefType aNewType,
252 PrefValue aNewValue) {
253 if (aHasValue) {
254 Clear(aOldType);
255 }
256 Init(aNewType, aNewValue);
257 }
258
259 void ToDomPrefValue(PrefType aType, dom::PrefValue* aDomValue) {
260 switch (aType) {
261 case PrefType::String:
262 *aDomValue = nsDependentCString(mStringVal);
263 return;
264
265 case PrefType::Int:
266 *aDomValue = mIntVal;
267 return;
268
269 case PrefType::Bool:
270 *aDomValue = mBoolVal;
271 return;
272
273 default:
274 MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 274); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile
int*)__null) = 274; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
;
275 }
276 }
277
278 PrefType FromDomPrefValue(const dom::PrefValue& aDomValue) {
279 switch (aDomValue.type()) {
280 case dom::PrefValue::TnsCString:
281 mStringVal = aDomValue.get_nsCString().get();
282 return PrefType::String;
283
284 case dom::PrefValue::Tint32_t:
285 mIntVal = aDomValue.get_int32_t();
286 return PrefType::Int;
287
288 case dom::PrefValue::Tbool:
289 mBoolVal = aDomValue.get_bool();
290 return PrefType::Bool;
291
292 default:
293 MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 293); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile
int*)__null) = 293; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
;
294 }
295 }
296
297 void SerializeAndAppend(PrefType aType, nsCString& aStr) {
298 switch (aType) {
299 case PrefType::Bool:
300 aStr.Append(mBoolVal ? 'T' : 'F');
301 break;
302
303 case PrefType::Int:
304 aStr.AppendInt(mIntVal);
305 break;
306
307 case PrefType::String: {
308 SerializeAndAppendString(nsDependentCString(mStringVal), aStr);
309 break;
310 }
311
312 case PrefType::None:
313 default:
314 MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 314); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile
int*)__null) = 314; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
;
315 }
316 }
317
318 void ToString(PrefType aType, nsCString& aStr) {
319 switch (aType) {
320 case PrefType::Bool:
321 aStr.Append(mBoolVal ? "true" : "false");
322 break;
323
324 case PrefType::Int:
325 aStr.AppendInt(mIntVal);
326 break;
327
328 case PrefType::String: {
329 aStr.Append(nsDependentCString(mStringVal));
330 break;
331 }
332
333 case PrefType::None:
334 default:;
335 }
336 }
337
338 static char* Deserialize(PrefType aType, char* aStr,
339 Maybe<dom::PrefValue>* aDomValue) {
340 char* p = aStr;
341
342 switch (aType) {
343 case PrefType::Bool:
344 if (*p == 'T') {
345 *aDomValue = Some(true);
346 } else if (*p == 'F') {
347 *aDomValue = Some(false);
348 } else {
349 *aDomValue = Some(false);
350 NS_ERROR("bad bool pref value")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "bad bool pref value",
"Error", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 350); MOZ_PretendNoReturn(); } while (0)
;
351 }
352 p++;
353 return p;
354
355 case PrefType::Int: {
356 *aDomValue = Some(int32_t(strtol(p, &p, 10)));
357 return p;
358 }
359
360 case PrefType::String: {
361 nsCString str;
362 p = DeserializeString(p, str);
363 *aDomValue = Some(str);
364 return p;
365 }
366
367 default:
368 MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 368); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile
int*)__null) = 368; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
;
369 }
370 }
371};
372
373template <>
374bool PrefValue::Get() const {
375 return mBoolVal;
376}
377
378template <>
379int32_t PrefValue::Get() const {
380 return mIntVal;
381}
382
383template <>
384nsDependentCString PrefValue::Get() const {
385 return nsDependentCString(mStringVal);
386}
387
388#ifdef DEBUG1
389const char* PrefTypeToString(PrefType aType) {
390 switch (aType) {
391 case PrefType::None:
392 return "none";
393 case PrefType::String:
394 return "string";
395 case PrefType::Int:
396 return "int";
397 case PrefType::Bool:
398 return "bool";
399 default:
400 MOZ_CRASH("Unhandled enum value")do { do { } while (false); MOZ_ReportCrash("" "Unhandled enum value"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 400); AnnotateMozCrashReason("MOZ_CRASH(" "Unhandled enum value"
")"); do { *((volatile int*)__null) = 400; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
401 }
402}
403#endif
404
405// Assign to aResult a quoted, escaped copy of aOriginal.
406static void StrEscape(const char* aOriginal, nsCString& aResult) {
407 if (aOriginal == nullptr) {
408 aResult.AssignLiteral("\"\"");
409 return;
410 }
411
412 // JavaScript does not allow quotes, slashes, or line terminators inside
413 // strings so we must escape them. ECMAScript defines four line terminators,
414 // but we're only worrying about \r and \n here. We currently feed our pref
415 // script to the JS interpreter as Latin-1 so we won't encounter \u2028
416 // (line separator) or \u2029 (paragraph separator).
417 //
418 // WARNING: There are hints that we may be moving to storing prefs as utf8.
419 // If we ever feed them to the JS compiler as UTF8 then we'll have to worry
420 // about the multibyte sequences that would be interpreted as \u2028 and
421 // \u2029.
422 const char* p;
423
424 aResult.Assign('"');
425
426 // Paranoid worst case all slashes will free quickly.
427 for (p = aOriginal; *p; ++p) {
428 switch (*p) {
429 case '\n':
430 aResult.AppendLiteral("\\n");
431 break;
432
433 case '\r':
434 aResult.AppendLiteral("\\r");
435 break;
436
437 case '\\':
438 aResult.AppendLiteral("\\\\");
439 break;
440
441 case '\"':
442 aResult.AppendLiteral("\\\"");
443 break;
444
445 default:
446 aResult.Append(*p);
447 break;
448 }
449 }
450
451 aResult.Append('"');
452}
453
454// Mimic the behaviour of nsTStringRepr::ToFloat before bug 840706 to preserve
455// error case handling for parsing pref strings. Many callers do not check error
456// codes, so the returned values may be used even if an error is set.
457//
458// This method should never return NaN, but may return +-inf if the provided
459// number is too large to fit in a float.
460static float ParsePrefFloat(const nsCString& aString, nsresult* aError) {
461 if (aString.IsEmpty()) {
462 *aError = NS_ERROR_ILLEGAL_VALUE;
463 return 0.f;
464 }
465
466 // PR_strtod does a locale-independent conversion.
467 char* stopped = nullptr;
468 float result = PR_strtod(aString.get(), &stopped);
469
470 // Defensively avoid potential breakage caused by returning NaN into
471 // unsuspecting code. AFAIK this should never happen as PR_strtod cannot
472 // return NaN as currently configured.
473 if (std::isnan(result)) {
474 MOZ_ASSERT_UNREACHABLE("PR_strtod shouldn't return NaN")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"PR_strtod shouldn't return NaN" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 474); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "PR_strtod shouldn't return NaN" ")"
); do { *((volatile int*)__null) = 474; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
475 *aError = NS_ERROR_ILLEGAL_VALUE;
476 return 0.f;
477 }
478
479 *aError = (stopped == aString.EndReading()) ? NS_OK : NS_ERROR_ILLEGAL_VALUE;
480 return result;
481}
482
483struct PreferenceMarker {
484 static constexpr Span<const char> MarkerTypeName() {
485 return MakeStringSpan("Preference");
486 }
487 static void StreamJSONMarkerData(baseprofiler::SpliceableJSONWriter& aWriter,
488 const ProfilerString8View& aPrefName,
489 const Maybe<PrefValueKind>& aPrefKind,
490 PrefType aPrefType,
491 const ProfilerString8View& aPrefValue) {
492 aWriter.StringProperty("prefName", aPrefName);
493 aWriter.StringProperty("prefKind", PrefValueKindToString(aPrefKind));
494 aWriter.StringProperty("prefType", PrefTypeToString(aPrefType));
495 aWriter.StringProperty("prefValue", aPrefValue);
496 }
497 static MarkerSchema MarkerTypeDisplay() {
498 using MS = MarkerSchema;
499 MS schema{MS::Location::MarkerChart, MS::Location::MarkerTable};
500 schema.AddKeyLabelFormatSearchable("prefName", "Name", MS::Format::String,
501 MS::Searchable::Searchable);
502 schema.AddKeyLabelFormat("prefKind", "Kind", MS::Format::String);
503 schema.AddKeyLabelFormat("prefType", "Type", MS::Format::String);
504 schema.AddKeyLabelFormat("prefValue", "Value", MS::Format::String);
505 schema.SetTableLabel(
506 "{marker.name} — {marker.data.prefName}: {marker.data.prefValue} "
507 "({marker.data.prefType})");
508 return schema;
509 }
510
511 private:
512 static Span<const char> PrefValueKindToString(
513 const Maybe<PrefValueKind>& aKind) {
514 if (aKind) {
515 return *aKind == PrefValueKind::Default ? MakeStringSpan("Default")
516 : MakeStringSpan("User");
517 }
518 return "Shared";
519 }
520
521 static Span<const char> PrefTypeToString(PrefType type) {
522 switch (type) {
523 case PrefType::None:
524 return "None";
525 case PrefType::Int:
526 return "Int";
527 case PrefType::Bool:
528 return "Bool";
529 case PrefType::String:
530 return "String";
531 default:
532 MOZ_ASSERT_UNREACHABLE("Unknown preference type.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Unknown preference type." ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 532); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unknown preference type." ")"); do
{ *((volatile int*)__null) = 532; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
533 return "Unknown";
534 }
535 }
536};
537
538namespace mozilla {
539struct PrefsSizes {
540 PrefsSizes()
541 : mHashTable(0),
542 mPrefValues(0),
543 mStringValues(0),
544 mRootBranches(0),
545 mPrefNameArena(0),
546 mCallbacksObjects(0),
547 mCallbacksDomains(0),
548 mMisc(0) {}
549
550 size_t mHashTable;
551 size_t mPrefValues;
552 size_t mStringValues;
553 size_t mRootBranches;
554 size_t mPrefNameArena;
555 size_t mCallbacksObjects;
556 size_t mCallbacksDomains;
557 size_t mMisc;
558};
559} // namespace mozilla
560
561static StaticRefPtr<SharedPrefMap> gSharedMap;
562
563// Arena for Pref names.
564// Never access sPrefNameArena directly, always use PrefNameArena()
565// because it must only be accessed on the Main Thread
566typedef ArenaAllocator<4096, 1> NameArena;
567static NameArena* sPrefNameArena;
568
569static inline NameArena& PrefNameArena() {
570 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 570); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 570; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
571
572 if (!sPrefNameArena) {
573 sPrefNameArena = new NameArena();
574 }
575 return *sPrefNameArena;
576}
577
578class PrefWrapper;
579
580// Three forward declarations for immediately below
581class Pref;
582static bool IsPreferenceSanitized(const Pref* const aPref);
583static bool ShouldSanitizePreference(const Pref* const aPref);
584
585// Note that this never changes in the parent process, and is only read in
586// content processes.
587static bool gContentProcessPrefsAreInited = false;
588
589class Pref {
590 public:
591 explicit Pref(const nsACString& aName)
592 : mName(ArenaStrdup(aName, PrefNameArena()), aName.Length()),
593 mType(static_cast<uint32_t>(PrefType::None)),
594 mIsSticky(false),
595 mIsLocked(false),
596 mIsSanitized(false),
597 mHasDefaultValue(false),
598 mHasUserValue(false),
599 mIsSkippedByIteration(false),
600 mDefaultValue(),
601 mUserValue() {}
602
603 ~Pref() {
604 // There's no need to free mName because it's allocated in memory owned by
605 // sPrefNameArena.
606
607 mDefaultValue.Clear(Type());
608 mUserValue.Clear(Type());
609 }
610
611 const char* Name() const { return mName.get(); }
612 const nsDependentCString& NameString() const { return mName; }
613
614 // Types.
615
616 PrefType Type() const { return static_cast<PrefType>(mType); }
617 void SetType(PrefType aType) { mType = static_cast<uint32_t>(aType); }
618
619 bool IsType(PrefType aType) const { return Type() == aType; }
620 bool IsTypeNone() const { return IsType(PrefType::None); }
621 bool IsTypeString() const { return IsType(PrefType::String); }
622 bool IsTypeInt() const { return IsType(PrefType::Int); }
623 bool IsTypeBool() const { return IsType(PrefType::Bool); }
624
625 // Other properties.
626
627 bool IsLocked() const { return mIsLocked; }
628 void SetIsLocked(bool aValue) { mIsLocked = aValue; }
629 bool IsSkippedByIteration() const { return mIsSkippedByIteration; }
630 void SetIsSkippedByIteration(bool aValue) { mIsSkippedByIteration = aValue; }
631
632 bool IsSticky() const { return mIsSticky; }
633
634 bool IsSanitized() const { return mIsSanitized; }
635
636 bool HasDefaultValue() const { return mHasDefaultValue; }
637 bool HasUserValue() const { return mHasUserValue; }
638
639 template <typename T>
640 void AddToMap(SharedPrefMapBuilder& aMap) {
641 // Sanitized preferences should never be added to the shared pref map
642 MOZ_ASSERT(!ShouldSanitizePreference(this))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!ShouldSanitizePreference(this))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!ShouldSanitizePreference(this
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!ShouldSanitizePreference(this)", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 642); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!ShouldSanitizePreference(this)"
")"); do { *((volatile int*)__null) = 642; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
643 aMap.Add(NameString(),
644 {HasDefaultValue(), HasUserValue(), IsSticky(), IsLocked(),
645 /* isSanitized */ false, IsSkippedByIteration()},
646 HasDefaultValue() ? mDefaultValue.Get<T>() : T(),
647 HasUserValue() ? mUserValue.Get<T>() : T());
648 }
649
650 void AddToMap(SharedPrefMapBuilder& aMap) {
651 if (IsTypeBool()) {
652 AddToMap<bool>(aMap);
653 } else if (IsTypeInt()) {
654 AddToMap<int32_t>(aMap);
655 } else if (IsTypeString()) {
656 AddToMap<nsDependentCString>(aMap);
657 } else {
658 MOZ_ASSERT_UNREACHABLE("Unexpected preference type")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Unexpected preference type" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 658); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unexpected preference type" ")")
; do { *((volatile int*)__null) = 658; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
659 }
660 }
661
662 // Other operations.
663
664#define CHECK_SANITIZATION() \
665 if (IsPreferenceSanitized(this)) { \
666 if (!sPrefTelemetryEventEnabled.exchange(true)) { \
667 sPrefTelemetryEventEnabled = true; \
668 Telemetry::SetEventRecordingEnabled("security"_ns, true); \
669 } \
670 Telemetry::RecordEvent( \
671 Telemetry::EventID::Security_Prefusage_Contentprocess, \
672 mozilla::Some(Name()), mozilla::Nothing()); \
673 if (sCrashOnBlocklistedPref) { \
674 MOZ_CRASH_UNSAFE_PRINTF( \do { static_assert(1 > 0, "Did you forget arguments to MOZ_CRASH_UNSAFE_PRINTF? "
"Or maybe you want MOZ_CRASH instead?"); static_assert(1 <=
sPrintfMaxArgs, "Only up to 4 additional arguments are allowed!"
); static_assert(sizeof("Should not access the preference '%s' in the Content Processes"
) <= sPrintfCrashReasonSize, "The supplied format string is too long!"
); MOZ_Crash("/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 676, MOZ_CrashPrintf("" "Should not access the preference '%s' in the Content Processes"
, Name())); } while (false)
675 "Should not access the preference '%s' in the Content Processes", \do { static_assert(1 > 0, "Did you forget arguments to MOZ_CRASH_UNSAFE_PRINTF? "
"Or maybe you want MOZ_CRASH instead?"); static_assert(1 <=
sPrintfMaxArgs, "Only up to 4 additional arguments are allowed!"
); static_assert(sizeof("Should not access the preference '%s' in the Content Processes"
) <= sPrintfCrashReasonSize, "The supplied format string is too long!"
); MOZ_Crash("/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 676, MOZ_CrashPrintf("" "Should not access the preference '%s' in the Content Processes"
, Name())); } while (false)
676 Name())do { static_assert(1 > 0, "Did you forget arguments to MOZ_CRASH_UNSAFE_PRINTF? "
"Or maybe you want MOZ_CRASH instead?"); static_assert(1 <=
sPrintfMaxArgs, "Only up to 4 additional arguments are allowed!"
); static_assert(sizeof("Should not access the preference '%s' in the Content Processes"
) <= sPrintfCrashReasonSize, "The supplied format string is too long!"
); MOZ_Crash("/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 676, MOZ_CrashPrintf("" "Should not access the preference '%s' in the Content Processes"
, Name())); } while (false)
; \
677 } \
678 }
679
680 bool GetBoolValue(PrefValueKind aKind = PrefValueKind::User) const {
681 MOZ_ASSERT(IsTypeBool())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsTypeBool())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsTypeBool()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("IsTypeBool()", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 681); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsTypeBool()"
")"); do { *((volatile int*)__null) = 681; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
682 MOZ_ASSERT(aKind == PrefValueKind::Default ? HasDefaultValue()do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aKind == PrefValueKind::Default ? HasDefaultValue() :
HasUserValue())>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aKind == PrefValueKind::Default
? HasDefaultValue() : HasUserValue()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aKind == PrefValueKind::Default ? HasDefaultValue() : HasUserValue()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 683); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aKind == PrefValueKind::Default ? HasDefaultValue() : HasUserValue()"
")"); do { *((volatile int*)__null) = 683; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
683 : HasUserValue())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aKind == PrefValueKind::Default ? HasDefaultValue() :
HasUserValue())>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aKind == PrefValueKind::Default
? HasDefaultValue() : HasUserValue()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aKind == PrefValueKind::Default ? HasDefaultValue() : HasUserValue()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 683); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aKind == PrefValueKind::Default ? HasDefaultValue() : HasUserValue()"
")"); do { *((volatile int*)__null) = 683; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
684
685 CHECK_SANITIZATION();
686
687 return aKind == PrefValueKind::Default ? mDefaultValue.mBoolVal
688 : mUserValue.mBoolVal;
689 }
690
691 int32_t GetIntValue(PrefValueKind aKind = PrefValueKind::User) const {
692 MOZ_ASSERT(IsTypeInt())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsTypeInt())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsTypeInt()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("IsTypeInt()", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 692); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsTypeInt()"
")"); do { *((volatile int*)__null) = 692; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
693 MOZ_ASSERT(aKind == PrefValueKind::Default ? HasDefaultValue()do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aKind == PrefValueKind::Default ? HasDefaultValue() :
HasUserValue())>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aKind == PrefValueKind::Default
? HasDefaultValue() : HasUserValue()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aKind == PrefValueKind::Default ? HasDefaultValue() : HasUserValue()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aKind == PrefValueKind::Default ? HasDefaultValue() : HasUserValue()"
")"); do { *((volatile int*)__null) = 694; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
694 : HasUserValue())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aKind == PrefValueKind::Default ? HasDefaultValue() :
HasUserValue())>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aKind == PrefValueKind::Default
? HasDefaultValue() : HasUserValue()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aKind == PrefValueKind::Default ? HasDefaultValue() : HasUserValue()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aKind == PrefValueKind::Default ? HasDefaultValue() : HasUserValue()"
")"); do { *((volatile int*)__null) = 694; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
695
696 CHECK_SANITIZATION();
697
698 return aKind == PrefValueKind::Default ? mDefaultValue.mIntVal
699 : mUserValue.mIntVal;
700 }
701
702 const char* GetBareStringValue(
703 PrefValueKind aKind = PrefValueKind::User) const {
704 MOZ_ASSERT(IsTypeString())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsTypeString())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsTypeString()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("IsTypeString()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 704); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsTypeString()"
")"); do { *((volatile int*)__null) = 704; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
705 MOZ_ASSERT(aKind == PrefValueKind::Default ? HasDefaultValue()do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aKind == PrefValueKind::Default ? HasDefaultValue() :
HasUserValue())>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aKind == PrefValueKind::Default
? HasDefaultValue() : HasUserValue()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aKind == PrefValueKind::Default ? HasDefaultValue() : HasUserValue()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 706); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aKind == PrefValueKind::Default ? HasDefaultValue() : HasUserValue()"
")"); do { *((volatile int*)__null) = 706; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
706 : HasUserValue())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aKind == PrefValueKind::Default ? HasDefaultValue() :
HasUserValue())>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aKind == PrefValueKind::Default
? HasDefaultValue() : HasUserValue()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aKind == PrefValueKind::Default ? HasDefaultValue() : HasUserValue()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 706); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aKind == PrefValueKind::Default ? HasDefaultValue() : HasUserValue()"
")"); do { *((volatile int*)__null) = 706; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
707
708 CHECK_SANITIZATION();
709
710 return aKind == PrefValueKind::Default ? mDefaultValue.mStringVal
711 : mUserValue.mStringVal;
712 }
713
714#undef CHECK_SANITIZATION
715
716 nsDependentCString GetStringValue(
717 PrefValueKind aKind = PrefValueKind::User) const {
718 return nsDependentCString(GetBareStringValue(aKind));
719 }
720
721 void ToDomPref(dom::Pref* aDomPref, bool aIsDestinationWebContentProcess) {
722 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 722); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 722; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
723
724 aDomPref->name() = mName;
725
726 aDomPref->isLocked() = mIsLocked;
727
728 aDomPref->isSanitized() =
729 aIsDestinationWebContentProcess && ShouldSanitizePreference(this);
730
731 if (mHasDefaultValue) {
732 aDomPref->defaultValue() = Some(dom::PrefValue());
733 mDefaultValue.ToDomPrefValue(Type(), &aDomPref->defaultValue().ref());
734 } else {
735 aDomPref->defaultValue() = Nothing();
736 }
737
738 if (mHasUserValue &&
739 !(aDomPref->isSanitized() && sOmitBlocklistedPrefValues)) {
740 aDomPref->userValue() = Some(dom::PrefValue());
741 mUserValue.ToDomPrefValue(Type(), &aDomPref->userValue().ref());
742 } else {
743 aDomPref->userValue() = Nothing();
744 }
745
746 MOZ_ASSERT(aDomPref->defaultValue().isNothing() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDomPref->defaultValue().isNothing() || aDomPref->
userValue().isNothing() || (mIsSanitized && sOmitBlocklistedPrefValues
) || (aDomPref->defaultValue().ref().type() == aDomPref->
userValue().ref().type()))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDomPref->defaultValue().
isNothing() || aDomPref->userValue().isNothing() || (mIsSanitized
&& sOmitBlocklistedPrefValues) || (aDomPref->defaultValue
().ref().type() == aDomPref->userValue().ref().type())))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("aDomPref->defaultValue().isNothing() || aDomPref->userValue().isNothing() || (mIsSanitized && sOmitBlocklistedPrefValues) || (aDomPref->defaultValue().ref().type() == aDomPref->userValue().ref().type())"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 750); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDomPref->defaultValue().isNothing() || aDomPref->userValue().isNothing() || (mIsSanitized && sOmitBlocklistedPrefValues) || (aDomPref->defaultValue().ref().type() == aDomPref->userValue().ref().type())"
")"); do { *((volatile int*)__null) = 750; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
747 aDomPref->userValue().isNothing() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDomPref->defaultValue().isNothing() || aDomPref->
userValue().isNothing() || (mIsSanitized && sOmitBlocklistedPrefValues
) || (aDomPref->defaultValue().ref().type() == aDomPref->
userValue().ref().type()))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDomPref->defaultValue().
isNothing() || aDomPref->userValue().isNothing() || (mIsSanitized
&& sOmitBlocklistedPrefValues) || (aDomPref->defaultValue
().ref().type() == aDomPref->userValue().ref().type())))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("aDomPref->defaultValue().isNothing() || aDomPref->userValue().isNothing() || (mIsSanitized && sOmitBlocklistedPrefValues) || (aDomPref->defaultValue().ref().type() == aDomPref->userValue().ref().type())"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 750); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDomPref->defaultValue().isNothing() || aDomPref->userValue().isNothing() || (mIsSanitized && sOmitBlocklistedPrefValues) || (aDomPref->defaultValue().ref().type() == aDomPref->userValue().ref().type())"
")"); do { *((volatile int*)__null) = 750; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
748 (mIsSanitized && sOmitBlocklistedPrefValues) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDomPref->defaultValue().isNothing() || aDomPref->
userValue().isNothing() || (mIsSanitized && sOmitBlocklistedPrefValues
) || (aDomPref->defaultValue().ref().type() == aDomPref->
userValue().ref().type()))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDomPref->defaultValue().
isNothing() || aDomPref->userValue().isNothing() || (mIsSanitized
&& sOmitBlocklistedPrefValues) || (aDomPref->defaultValue
().ref().type() == aDomPref->userValue().ref().type())))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("aDomPref->defaultValue().isNothing() || aDomPref->userValue().isNothing() || (mIsSanitized && sOmitBlocklistedPrefValues) || (aDomPref->defaultValue().ref().type() == aDomPref->userValue().ref().type())"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 750); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDomPref->defaultValue().isNothing() || aDomPref->userValue().isNothing() || (mIsSanitized && sOmitBlocklistedPrefValues) || (aDomPref->defaultValue().ref().type() == aDomPref->userValue().ref().type())"
")"); do { *((volatile int*)__null) = 750; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
749 (aDomPref->defaultValue().ref().type() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDomPref->defaultValue().isNothing() || aDomPref->
userValue().isNothing() || (mIsSanitized && sOmitBlocklistedPrefValues
) || (aDomPref->defaultValue().ref().type() == aDomPref->
userValue().ref().type()))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDomPref->defaultValue().
isNothing() || aDomPref->userValue().isNothing() || (mIsSanitized
&& sOmitBlocklistedPrefValues) || (aDomPref->defaultValue
().ref().type() == aDomPref->userValue().ref().type())))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("aDomPref->defaultValue().isNothing() || aDomPref->userValue().isNothing() || (mIsSanitized && sOmitBlocklistedPrefValues) || (aDomPref->defaultValue().ref().type() == aDomPref->userValue().ref().type())"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 750); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDomPref->defaultValue().isNothing() || aDomPref->userValue().isNothing() || (mIsSanitized && sOmitBlocklistedPrefValues) || (aDomPref->defaultValue().ref().type() == aDomPref->userValue().ref().type())"
")"); do { *((volatile int*)__null) = 750; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
750 aDomPref->userValue().ref().type()))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDomPref->defaultValue().isNothing() || aDomPref->
userValue().isNothing() || (mIsSanitized && sOmitBlocklistedPrefValues
) || (aDomPref->defaultValue().ref().type() == aDomPref->
userValue().ref().type()))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDomPref->defaultValue().
isNothing() || aDomPref->userValue().isNothing() || (mIsSanitized
&& sOmitBlocklistedPrefValues) || (aDomPref->defaultValue
().ref().type() == aDomPref->userValue().ref().type())))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("aDomPref->defaultValue().isNothing() || aDomPref->userValue().isNothing() || (mIsSanitized && sOmitBlocklistedPrefValues) || (aDomPref->defaultValue().ref().type() == aDomPref->userValue().ref().type())"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 750); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDomPref->defaultValue().isNothing() || aDomPref->userValue().isNothing() || (mIsSanitized && sOmitBlocklistedPrefValues) || (aDomPref->defaultValue().ref().type() == aDomPref->userValue().ref().type())"
")"); do { *((volatile int*)__null) = 750; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
751 }
752
753 void FromDomPref(const dom::Pref& aDomPref, bool* aValueChanged) {
754 MOZ_ASSERT(!XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!XRE_IsParentProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 754); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 754; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
755 MOZ_ASSERT(mName == aDomPref.name())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mName == aDomPref.name())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mName == aDomPref.name()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("mName == aDomPref.name()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 755); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mName == aDomPref.name()"
")"); do { *((volatile int*)__null) = 755; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
756
757 mIsLocked = aDomPref.isLocked();
758 mIsSanitized = aDomPref.isSanitized();
759
760 const Maybe<dom::PrefValue>& defaultValue = aDomPref.defaultValue();
761 bool defaultValueChanged = false;
762 if (defaultValue.isSome()) {
763 PrefValue value;
764 PrefType type = value.FromDomPrefValue(defaultValue.ref());
765 if (!ValueMatches(PrefValueKind::Default, type, value)) {
766 // Type() is PrefType::None if it's a newly added pref. This is ok.
767 mDefaultValue.Replace(mHasDefaultValue, Type(), type, value);
768 SetType(type);
769 mHasDefaultValue = true;
770 defaultValueChanged = true;
771 }
772 }
773 // Note: we never clear a default value.
774
775 const Maybe<dom::PrefValue>& userValue = aDomPref.userValue();
776 bool userValueChanged = false;
777 if (userValue.isSome()) {
778 PrefValue value;
779 PrefType type = value.FromDomPrefValue(userValue.ref());
780 if (!ValueMatches(PrefValueKind::User, type, value)) {
781 // Type() is PrefType::None if it's a newly added pref. This is ok.
782 mUserValue.Replace(mHasUserValue, Type(), type, value);
783 SetType(type);
784 mHasUserValue = true;
785 userValueChanged = true;
786 }
787 } else if (mHasUserValue) {
788 ClearUserValue();
789 userValueChanged = true;
790 }
791
792 if (userValueChanged || (defaultValueChanged && !mHasUserValue)) {
793 *aValueChanged = true;
794 }
795 }
796
797 void FromWrapper(PrefWrapper& aWrapper);
798
799 bool HasAdvisablySizedValues() {
800 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 800); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 800; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
801
802 if (!IsTypeString()) {
803 return true;
804 }
805
806 if (mHasDefaultValue &&
807 strlen(mDefaultValue.mStringVal) > MAX_ADVISABLE_PREF_LENGTH) {
808 return false;
809 }
810
811 if (mHasUserValue &&
812 strlen(mUserValue.mStringVal) > MAX_ADVISABLE_PREF_LENGTH) {
813 return false;
814 }
815
816 return true;
817 }
818
819 private:
820 bool ValueMatches(PrefValueKind aKind, PrefType aType, PrefValue aValue) {
821 return IsType(aType) &&
822 (aKind == PrefValueKind::Default
823 ? mHasDefaultValue && mDefaultValue.Equals(aType, aValue)
824 : mHasUserValue && mUserValue.Equals(aType, aValue));
825 }
826
827 public:
828 void ClearUserValue() {
829 mUserValue.Clear(Type());
830 mHasUserValue = false;
831 }
832
833 nsresult SetDefaultValue(PrefType aType, PrefValue aValue, bool aIsSticky,
834 bool aIsLocked, bool* aValueChanged) {
835 // Types must always match when setting the default value.
836 if (!IsType(aType)) {
837 return NS_ERROR_UNEXPECTED;
838 }
839
840 // Should we set the default value? Only if the pref is not locked, and
841 // doing so would change the default value.
842 if (!IsLocked()) {
843 if (aIsLocked) {
844 SetIsLocked(true);
845 }
846 if (!ValueMatches(PrefValueKind::Default, aType, aValue)) {
847 mDefaultValue.Replace(mHasDefaultValue, Type(), aType, aValue);
848 mHasDefaultValue = true;
849 if (aIsSticky) {
850 mIsSticky = true;
851 }
852 if (!mHasUserValue) {
853 *aValueChanged = true;
854 }
855 // What if we change the default to be the same as the user value?
856 // Should we clear the user value? Currently we don't.
857 }
858 }
859 return NS_OK;
860 }
861
862 nsresult SetUserValue(PrefType aType, PrefValue aValue, bool aFromInit,
863 bool* aValueChanged) {
864 // If we have a default value, types must match when setting the user
865 // value.
866 if (mHasDefaultValue && !IsType(aType)) {
867 return NS_ERROR_UNEXPECTED;
868 }
869
870 // Should we clear the user value, if present? Only if the new user value
871 // matches the default value, and the pref isn't sticky, and we aren't
872 // force-setting it during initialization.
873 if (ValueMatches(PrefValueKind::Default, aType, aValue) && !mIsSticky &&
874 !aFromInit) {
875 if (mHasUserValue) {
876 ClearUserValue();
877 if (!IsLocked()) {
878 *aValueChanged = true;
879 }
880 }
881
882 // Otherwise, should we set the user value? Only if doing so would
883 // change the user value.
884 } else if (!ValueMatches(PrefValueKind::User, aType, aValue)) {
885 mUserValue.Replace(mHasUserValue, Type(), aType, aValue);
886 SetType(aType); // needed because we may have changed the type
887 mHasUserValue = true;
888 if (!IsLocked()) {
889 *aValueChanged = true;
890 }
891 }
892 return NS_OK;
893 }
894
895 // Prefs are serialized in a manner that mirrors dom::Pref. The two should be
896 // kept in sync. E.g. if something is added to one it should also be added to
897 // the other. (It would be nice to be able to use the code generated from
898 // IPDL for serializing dom::Pref here instead of writing by hand this
899 // serialization/deserialization. Unfortunately, that generated code is
900 // difficult to use directly, outside of the IPDL IPC code.)
901 //
902 // The grammar for the serialized prefs has the following form.
903 //
904 // <pref> = <type> <locked> <sanitized> ':' <name> ':' <value>? ':'
905 // <value>? '\n'
906 // <type> = 'B' | 'I' | 'S'
907 // <locked> = 'L' | '-'
908 // <sanitized> = 'S' | '-'
909 // <name> = <string-value>
910 // <value> = <bool-value> | <int-value> | <string-value>
911 // <bool-value> = 'T' | 'F'
912 // <int-value> = an integer literal accepted by strtol()
913 // <string-value> = <int-value> '/' <chars>
914 // <chars> = any char sequence of length dictated by the preceding
915 // <int-value>.
916 //
917 // No whitespace is tolerated between tokens. <type> must match the types of
918 // the values.
919 //
920 // The serialization is text-based, rather than binary, for the following
921 // reasons.
922 //
923 // - The size difference wouldn't be much different between text-based and
924 // binary. Most of the space is for strings (pref names and string pref
925 // values), which would be the same in both styles. And other differences
926 // would be minimal, e.g. small integers are shorter in text but long
927 // integers are longer in text.
928 //
929 // - Likewise, speed differences should be negligible.
930 //
931 // - It's much easier to debug a text-based serialization. E.g. you can
932 // print it and inspect it easily in a debugger.
933 //
934 // Examples of unlocked boolean prefs:
935 // - "B--:8/my.bool1:F:T\n"
936 // - "B--:8/my.bool2:F:\n"
937 // - "B--:8/my.bool3::T\n"
938 //
939 // Examples of sanitized, unlocked boolean prefs:
940 // - "B-S:8/my.bool1:F:T\n"
941 // - "B-S:8/my.bool2:F:\n"
942 // - "B-S:8/my.bool3::T\n"
943 //
944 // Examples of locked integer prefs:
945 // - "IL-:7/my.int1:0:1\n"
946 // - "IL-:7/my.int2:123:\n"
947 // - "IL-:7/my.int3::-99\n"
948 //
949 // Examples of unlocked string prefs:
950 // - "S--:10/my.string1:3/abc:4/wxyz\n"
951 // - "S--:10/my.string2:5/1.234:\n"
952 // - "S--:10/my.string3::7/string!\n"
953
954 void SerializeAndAppend(nsCString& aStr, bool aSanitizeUserValue) {
955 switch (Type()) {
956 case PrefType::Bool:
957 aStr.Append('B');
958 break;
959
960 case PrefType::Int:
961 aStr.Append('I');
962 break;
963
964 case PrefType::String: {
965 aStr.Append('S');
966 break;
967 }
968
969 case PrefType::None:
970 default:
971 MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 971); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile
int*)__null) = 971; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
;
972 }
973
974 aStr.Append(mIsLocked ? 'L' : '-');
975 aStr.Append(aSanitizeUserValue ? 'S' : '-');
976 aStr.Append(':');
977
978 SerializeAndAppendString(mName, aStr);
979 aStr.Append(':');
980
981 if (mHasDefaultValue) {
982 mDefaultValue.SerializeAndAppend(Type(), aStr);
983 }
984 aStr.Append(':');
985
986 if (mHasUserValue && !(aSanitizeUserValue && sOmitBlocklistedPrefValues)) {
987 mUserValue.SerializeAndAppend(Type(), aStr);
988 }
989 aStr.Append('\n');
990 }
991
992 static char* Deserialize(char* aStr, dom::Pref* aDomPref) {
993 char* p = aStr;
994
995 // The type.
996 PrefType type;
997 if (*p == 'B') {
998 type = PrefType::Bool;
999 } else if (*p == 'I') {
1000 type = PrefType::Int;
1001 } else if (*p == 'S') {
1002 type = PrefType::String;
1003 } else {
1004 NS_ERROR("bad pref type")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "bad pref type", "Error"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1004); MOZ_PretendNoReturn(); } while (0)
;
1005 type = PrefType::None;
1006 }
1007 p++; // move past the type char
1008
1009 // Locked?
1010 bool isLocked;
1011 if (*p == 'L') {
1012 isLocked = true;
1013 } else if (*p == '-') {
1014 isLocked = false;
1015 } else {
1016 NS_ERROR("bad pref locked status")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "bad pref locked status"
, "Error", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1016); MOZ_PretendNoReturn(); } while (0)
;
1017 isLocked = false;
1018 }
1019 p++; // move past the isLocked char
1020
1021 // Sanitize?
1022 bool isSanitized;
1023 if (*p == 'S') {
1024 isSanitized = true;
1025 } else if (*p == '-') {
1026 isSanitized = false;
1027 } else {
1028 NS_ERROR("bad pref sanitized status")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "bad pref sanitized status"
, "Error", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1028); MOZ_PretendNoReturn(); } while (0)
;
1029 isSanitized = false;
1030 }
1031 p++; // move past the isSanitized char
1032
1033 MOZ_ASSERT(*p == ':')do { static_assert( mozilla::detail::AssertionConditionType<
decltype(*p == ':')>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(*p == ':'))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("*p == ':'", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1033); AnnotateMozCrashReason("MOZ_ASSERT" "(" "*p == ':'" ")"
); do { *((volatile int*)__null) = 1033; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1034 p++; // move past the ':'
1035
1036 // The pref name.
1037 nsCString name;
1038 p = DeserializeString(p, name);
1039
1040 MOZ_ASSERT(*p == ':')do { static_assert( mozilla::detail::AssertionConditionType<
decltype(*p == ':')>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(*p == ':'))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("*p == ':'", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1040); AnnotateMozCrashReason("MOZ_ASSERT" "(" "*p == ':'" ")"
); do { *((volatile int*)__null) = 1040; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1041 p++; // move past the ':' preceding the default value
1042
1043 Maybe<dom::PrefValue> maybeDefaultValue;
1044 if (*p != ':') {
1045 dom::PrefValue defaultValue;
1046 p = PrefValue::Deserialize(type, p, &maybeDefaultValue);
1047 }
1048
1049 MOZ_ASSERT(*p == ':')do { static_assert( mozilla::detail::AssertionConditionType<
decltype(*p == ':')>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(*p == ':'))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("*p == ':'", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1049); AnnotateMozCrashReason("MOZ_ASSERT" "(" "*p == ':'" ")"
); do { *((volatile int*)__null) = 1049; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1050 p++; // move past the ':' between the default and user values
1051
1052 Maybe<dom::PrefValue> maybeUserValue;
1053 if (*p != '\n') {
1054 dom::PrefValue userValue;
1055 p = PrefValue::Deserialize(type, p, &maybeUserValue);
1056 }
1057
1058 MOZ_ASSERT(*p == '\n')do { static_assert( mozilla::detail::AssertionConditionType<
decltype(*p == '\n')>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(*p == '\n'))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("*p == '\\n'", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1058); AnnotateMozCrashReason("MOZ_ASSERT" "(" "*p == '\\n'"
")"); do { *((volatile int*)__null) = 1058; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1059 p++; // move past the '\n' following the user value
1060
1061 *aDomPref = dom::Pref(name, isLocked, isSanitized, maybeDefaultValue,
1062 maybeUserValue);
1063
1064 return p;
1065 }
1066
1067 void AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf, PrefsSizes& aSizes) {
1068 // Note: mName is allocated in sPrefNameArena, measured elsewhere.
1069 aSizes.mPrefValues += aMallocSizeOf(this);
1070 if (IsTypeString()) {
1071 if (mHasDefaultValue) {
1072 aSizes.mStringValues += aMallocSizeOf(mDefaultValue.mStringVal);
1073 }
1074 if (mHasUserValue) {
1075 aSizes.mStringValues += aMallocSizeOf(mUserValue.mStringVal);
1076 }
1077 }
1078 }
1079
1080 void RelocateName(NameArena* aArena) {
1081 mName.Rebind(ArenaStrdup(mName.get(), *aArena), mName.Length());
1082 }
1083
1084 private:
1085 nsDependentCString mName; // allocated in sPrefNameArena
1086
1087 uint32_t mType : 2;
1088 uint32_t mIsSticky : 1;
1089 uint32_t mIsLocked : 1;
1090 uint32_t mIsSanitized : 1;
1091 uint32_t mHasDefaultValue : 1;
1092 uint32_t mHasUserValue : 1;
1093 uint32_t mIsSkippedByIteration : 1;
1094
1095 PrefValue mDefaultValue;
1096 PrefValue mUserValue;
1097};
1098
1099struct PrefHasher {
1100 using Key = UniquePtr<Pref>;
1101 using Lookup = const char*;
1102
1103 static HashNumber hash(const Lookup aLookup) { return HashString(aLookup); }
1104
1105 static bool match(const Key& aKey, const Lookup aLookup) {
1106 if (!aLookup || !aKey->Name()) {
1107 return false;
1108 }
1109
1110 return strcmp(aLookup, aKey->Name()) == 0;
1111 }
1112};
1113
1114using PrefWrapperBase = Variant<Pref*, SharedPrefMap::Pref>;
1115class MOZ_STACK_CLASS PrefWrapper : public PrefWrapperBase {
1116 using SharedPref = const SharedPrefMap::Pref;
1117
1118 public:
1119 MOZ_IMPLICIT PrefWrapper(Pref* aPref) : PrefWrapperBase(AsVariant(aPref)) {}
1120
1121 MOZ_IMPLICIT PrefWrapper(const SharedPrefMap::Pref& aPref)
1122 : PrefWrapperBase(AsVariant(aPref)) {}
1123
1124 // Types.
1125
1126 bool IsType(PrefType aType) const { return Type() == aType; }
1127 bool IsTypeNone() const { return IsType(PrefType::None); }
1128 bool IsTypeString() const { return IsType(PrefType::String); }
1129 bool IsTypeInt() const { return IsType(PrefType::Int); }
1130 bool IsTypeBool() const { return IsType(PrefType::Bool); }
1131
1132#define FORWARD(retType, method) \
1133 retType method() const { \
1134 struct Matcher { \
1135 retType operator()(const Pref* aPref) { return aPref->method(); } \
1136 retType operator()(SharedPref& aPref) { return aPref.method(); } \
1137 }; \
1138 return match(Matcher()); \
1139 }
1140
1141 FORWARD(bool, IsLocked)
1142 FORWARD(bool, IsSanitized)
1143 FORWARD(bool, IsSticky)
1144 FORWARD(bool, HasDefaultValue)
1145 FORWARD(bool, HasUserValue)
1146 FORWARD(const char*, Name)
1147 FORWARD(nsCString, NameString)
1148 FORWARD(PrefType, Type)
1149#undef FORWARD
1150
1151#define FORWARD(retType, method) \
1152 retType method(PrefValueKind aKind = PrefValueKind::User) const { \
1153 struct Matcher { \
1154 PrefValueKind mKind; \
1155 \
1156 retType operator()(const Pref* aPref) { return aPref->method(mKind); } \
1157 retType operator()(SharedPref& aPref) { return aPref.method(mKind); } \
1158 }; \
1159 return match(Matcher{aKind}); \
1160 }
1161
1162 FORWARD(bool, GetBoolValue)
1163 FORWARD(int32_t, GetIntValue)
1164 FORWARD(nsCString, GetStringValue)
1165 FORWARD(const char*, GetBareStringValue)
1166#undef FORWARD
1167
1168 PrefValue GetValue(PrefValueKind aKind = PrefValueKind::User) const {
1169 switch (Type()) {
1170 case PrefType::Bool:
1171 return PrefValue{GetBoolValue(aKind)};
1172 case PrefType::Int:
1173 return PrefValue{GetIntValue(aKind)};
1174 case PrefType::String:
1175 return PrefValue{GetBareStringValue(aKind)};
1176 case PrefType::None:
1177 // This check will be performed in the above functions; but for NoneType
1178 // we need to do it explicitly, then fall-through.
1179 if (IsPreferenceSanitized(Name())) {
1180 if (!sPrefTelemetryEventEnabled.exchange(true)) {
1181 sPrefTelemetryEventEnabled = true;
1182 Telemetry::SetEventRecordingEnabled("security"_ns, true);
1183 }
1184
1185 Telemetry::RecordEvent(
1186 Telemetry::EventID::Security_Prefusage_Contentprocess,
1187 mozilla::Some(Name()), mozilla::Nothing());
1188
1189 if (sCrashOnBlocklistedPref) {
1190 MOZ_CRASH_UNSAFE_PRINTF(do { static_assert(1 > 0, "Did you forget arguments to MOZ_CRASH_UNSAFE_PRINTF? "
"Or maybe you want MOZ_CRASH instead?"); static_assert(1 <=
sPrintfMaxArgs, "Only up to 4 additional arguments are allowed!"
); static_assert(sizeof("Should not access the preference '%s' in the Content "
"Processes") <= sPrintfCrashReasonSize, "The supplied format string is too long!"
); MOZ_Crash("/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1193, MOZ_CrashPrintf("" "Should not access the preference '%s' in the Content "
"Processes", Name())); } while (false)
1191 "Should not access the preference '%s' in the Content "do { static_assert(1 > 0, "Did you forget arguments to MOZ_CRASH_UNSAFE_PRINTF? "
"Or maybe you want MOZ_CRASH instead?"); static_assert(1 <=
sPrintfMaxArgs, "Only up to 4 additional arguments are allowed!"
); static_assert(sizeof("Should not access the preference '%s' in the Content "
"Processes") <= sPrintfCrashReasonSize, "The supplied format string is too long!"
); MOZ_Crash("/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1193, MOZ_CrashPrintf("" "Should not access the preference '%s' in the Content "
"Processes", Name())); } while (false)
1192 "Processes",do { static_assert(1 > 0, "Did you forget arguments to MOZ_CRASH_UNSAFE_PRINTF? "
"Or maybe you want MOZ_CRASH instead?"); static_assert(1 <=
sPrintfMaxArgs, "Only up to 4 additional arguments are allowed!"
); static_assert(sizeof("Should not access the preference '%s' in the Content "
"Processes") <= sPrintfCrashReasonSize, "The supplied format string is too long!"
); MOZ_Crash("/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1193, MOZ_CrashPrintf("" "Should not access the preference '%s' in the Content "
"Processes", Name())); } while (false)
1193 Name())do { static_assert(1 > 0, "Did you forget arguments to MOZ_CRASH_UNSAFE_PRINTF? "
"Or maybe you want MOZ_CRASH instead?"); static_assert(1 <=
sPrintfMaxArgs, "Only up to 4 additional arguments are allowed!"
); static_assert(sizeof("Should not access the preference '%s' in the Content "
"Processes") <= sPrintfCrashReasonSize, "The supplied format string is too long!"
); MOZ_Crash("/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1193, MOZ_CrashPrintf("" "Should not access the preference '%s' in the Content "
"Processes", Name())); } while (false)
;
1194 }
1195 }
1196 [[fallthrough]];
1197 default:
1198 MOZ_ASSERT_UNREACHABLE("Unexpected pref type")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Unexpected pref type" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1198); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unexpected pref type" ")"); do {
*((volatile int*)__null) = 1198; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1199 return PrefValue{};
1200 }
1201 }
1202
1203 Result<PrefValueKind, nsresult> WantValueKind(PrefType aType,
1204 PrefValueKind aKind) const {
1205 // WantValueKind may short-circuit GetValue functions and cause them to
1206 // return early, before this check occurs in GetFooValue()
1207 if (this->is<Pref*>() && IsPreferenceSanitized(this->as<Pref*>())) {
1208 if (!sPrefTelemetryEventEnabled.exchange(true)) {
1209 sPrefTelemetryEventEnabled = true;
1210 Telemetry::SetEventRecordingEnabled("security"_ns, true);
1211 }
1212
1213 Telemetry::RecordEvent(
1214 Telemetry::EventID::Security_Prefusage_Contentprocess,
1215 mozilla::Some(Name()), mozilla::Nothing());
1216
1217 if (sCrashOnBlocklistedPref) {
1218 MOZ_CRASH_UNSAFE_PRINTF(do { static_assert(1 > 0, "Did you forget arguments to MOZ_CRASH_UNSAFE_PRINTF? "
"Or maybe you want MOZ_CRASH instead?"); static_assert(1 <=
sPrintfMaxArgs, "Only up to 4 additional arguments are allowed!"
); static_assert(sizeof("Should not access the preference '%s' in the Content Processes"
) <= sPrintfCrashReasonSize, "The supplied format string is too long!"
); MOZ_Crash("/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1220, MOZ_CrashPrintf("" "Should not access the preference '%s' in the Content Processes"
, Name())); } while (false)
1219 "Should not access the preference '%s' in the Content Processes",do { static_assert(1 > 0, "Did you forget arguments to MOZ_CRASH_UNSAFE_PRINTF? "
"Or maybe you want MOZ_CRASH instead?"); static_assert(1 <=
sPrintfMaxArgs, "Only up to 4 additional arguments are allowed!"
); static_assert(sizeof("Should not access the preference '%s' in the Content Processes"
) <= sPrintfCrashReasonSize, "The supplied format string is too long!"
); MOZ_Crash("/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1220, MOZ_CrashPrintf("" "Should not access the preference '%s' in the Content Processes"
, Name())); } while (false)
1220 Name())do { static_assert(1 > 0, "Did you forget arguments to MOZ_CRASH_UNSAFE_PRINTF? "
"Or maybe you want MOZ_CRASH instead?"); static_assert(1 <=
sPrintfMaxArgs, "Only up to 4 additional arguments are allowed!"
); static_assert(sizeof("Should not access the preference '%s' in the Content Processes"
) <= sPrintfCrashReasonSize, "The supplied format string is too long!"
); MOZ_Crash("/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1220, MOZ_CrashPrintf("" "Should not access the preference '%s' in the Content Processes"
, Name())); } while (false)
;
1221 }
1222 } else if (!this->is<Pref*>()) {
1223 // While we could use Name() above, and avoid the Variant checks, it
1224 // would less efficient than needed and we can instead do a debug-only
1225 // assert here to limit the inefficientcy
1226 MOZ_ASSERT(!IsPreferenceSanitized(Name()),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsPreferenceSanitized(Name()))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsPreferenceSanitized(Name(
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsPreferenceSanitized(Name())" " (" "We should never have a sanitized SharedPrefMap::Pref."
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1227); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsPreferenceSanitized(Name())"
") (" "We should never have a sanitized SharedPrefMap::Pref."
")"); do { *((volatile int*)__null) = 1227; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1227 "We should never have a sanitized SharedPrefMap::Pref.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsPreferenceSanitized(Name()))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsPreferenceSanitized(Name(
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsPreferenceSanitized(Name())" " (" "We should never have a sanitized SharedPrefMap::Pref."
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1227); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsPreferenceSanitized(Name())"
") (" "We should never have a sanitized SharedPrefMap::Pref."
")"); do { *((volatile int*)__null) = 1227; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1228 }
1229
1230 if (Type() != aType) {
1231 return Err(NS_ERROR_UNEXPECTED);
1232 }
1233
1234 if (aKind == PrefValueKind::Default || IsLocked() || !HasUserValue()) {
1235 if (!HasDefaultValue()) {
1236 return Err(NS_ERROR_UNEXPECTED);
1237 }
1238 return PrefValueKind::Default;
1239 }
1240 return PrefValueKind::User;
1241 }
1242
1243 nsresult GetValue(PrefValueKind aKind, bool* aResult) const {
1244 PrefValueKind kind;
1245 MOZ_TRY_VAR(kind, WantValueKind(PrefType::Bool, aKind))do { auto mozTryVarTempResult_ = (WantValueKind(PrefType::Bool
, aKind)); if ((__builtin_expect(!!(mozTryVarTempResult_.isErr
()), 0))) { return mozTryVarTempResult_.propagateErr(); } (kind
) = mozTryVarTempResult_.unwrap(); } while (0)
;
1246
1247 *aResult = GetBoolValue(kind);
1248 return NS_OK;
1249 }
1250
1251 nsresult GetValue(PrefValueKind aKind, int32_t* aResult) const {
1252 PrefValueKind kind;
1253 MOZ_TRY_VAR(kind, WantValueKind(PrefType::Int, aKind))do { auto mozTryVarTempResult_ = (WantValueKind(PrefType::Int
, aKind)); if ((__builtin_expect(!!(mozTryVarTempResult_.isErr
()), 0))) { return mozTryVarTempResult_.propagateErr(); } (kind
) = mozTryVarTempResult_.unwrap(); } while (0)
;
1254
1255 *aResult = GetIntValue(kind);
1256 return NS_OK;
1257 }
1258
1259 nsresult GetValue(PrefValueKind aKind, uint32_t* aResult) const {
1260 return GetValue(aKind, reinterpret_cast<int32_t*>(aResult));
1261 }
1262
1263 nsresult GetValue(PrefValueKind aKind, float* aResult) const {
1264 nsAutoCString result;
1265 nsresult rv = GetValue(aKind, result);
1266 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
1267 // ParsePrefFloat() does a locale-independent conversion.
1268 // FIXME: Other `GetValue` overloads don't clobber `aResult` on error.
1269 *aResult = ParsePrefFloat(result, &rv);
1270 }
1271 return rv;
1272 }
1273
1274 nsresult GetValue(PrefValueKind aKind, nsACString& aResult) const {
1275 PrefValueKind kind;
1276 MOZ_TRY_VAR(kind, WantValueKind(PrefType::String, aKind))do { auto mozTryVarTempResult_ = (WantValueKind(PrefType::String
, aKind)); if ((__builtin_expect(!!(mozTryVarTempResult_.isErr
()), 0))) { return mozTryVarTempResult_.propagateErr(); } (kind
) = mozTryVarTempResult_.unwrap(); } while (0)
;
1277
1278 aResult = GetStringValue(kind);
1279 return NS_OK;
1280 }
1281
1282 nsresult GetValue(PrefValueKind aKind, nsACString* aResult) const {
1283 return GetValue(aKind, *aResult);
1284 }
1285
1286 // Returns false if this pref doesn't have a user value worth saving.
1287 bool UserValueToStringForSaving(nsCString& aStr) {
1288 // Should we save the user value, if present? Only if it does not match the
1289 // default value, or it is sticky.
1290 if (HasUserValue() &&
1291 (!ValueMatches(PrefValueKind::Default, Type(), GetValue()) ||
1292 IsSticky())) {
1293 if (IsTypeString()) {
1294 StrEscape(GetStringValue().get(), aStr);
1295
1296 } else if (IsTypeInt()) {
1297 aStr.AppendInt(GetIntValue());
1298
1299 } else if (IsTypeBool()) {
1300 aStr = GetBoolValue() ? "true" : "false";
1301 }
1302 return true;
1303 }
1304
1305 // Do not save default prefs that haven't changed.
1306 return false;
1307 }
1308
1309 bool Matches(PrefType aType, PrefValueKind aKind, PrefValue& aValue,
1310 bool aIsSticky, bool aIsLocked) const {
1311 return (ValueMatches(aKind, aType, aValue) && aIsSticky == IsSticky() &&
1312 aIsLocked == IsLocked());
1313 }
1314
1315 bool ValueMatches(PrefValueKind aKind, PrefType aType,
1316 const PrefValue& aValue) const {
1317 if (!IsType(aType)) {
1318 return false;
1319 }
1320 if (!(aKind == PrefValueKind::Default ? HasDefaultValue()
1321 : HasUserValue())) {
1322 return false;
1323 }
1324 switch (aType) {
1325 case PrefType::Bool:
1326 return GetBoolValue(aKind) == aValue.mBoolVal;
1327 case PrefType::Int:
1328 return GetIntValue(aKind) == aValue.mIntVal;
1329 case PrefType::String:
1330 return strcmp(GetBareStringValue(aKind), aValue.mStringVal) == 0;
1331 default:
1332 MOZ_ASSERT_UNREACHABLE("Unexpected preference type")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Unexpected preference type" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1332); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unexpected preference type" ")")
; do { *((volatile int*)__null) = 1332; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1333 return false;
1334 }
1335 }
1336};
1337
1338void Pref::FromWrapper(PrefWrapper& aWrapper) {
1339 MOZ_ASSERT(aWrapper.is<SharedPrefMap::Pref>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aWrapper.is<SharedPrefMap::Pref>())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aWrapper.is<SharedPrefMap::Pref>()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aWrapper.is<SharedPrefMap::Pref>()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1339); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWrapper.is<SharedPrefMap::Pref>()"
")"); do { *((volatile int*)__null) = 1339; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1340 auto pref = aWrapper.as<SharedPrefMap::Pref>();
1341
1342 MOZ_ASSERT(IsTypeNone())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsTypeNone())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsTypeNone()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("IsTypeNone()", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1342); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsTypeNone()"
")"); do { *((volatile int*)__null) = 1342; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1343 MOZ_ASSERT(mName == pref.NameString())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mName == pref.NameString())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mName == pref.NameString()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mName == pref.NameString()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1343); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mName == pref.NameString()"
")"); do { *((volatile int*)__null) = 1343; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1344
1345 mType = uint32_t(pref.Type());
1346
1347 mIsLocked = pref.IsLocked();
1348 mIsSanitized = pref.IsSanitized();
1349 mIsSticky = pref.IsSticky();
1350
1351 mHasDefaultValue = pref.HasDefaultValue();
1352 mHasUserValue = pref.HasUserValue();
1353
1354 if (mHasDefaultValue) {
1355 mDefaultValue.Init(Type(), aWrapper.GetValue(PrefValueKind::Default));
1356 }
1357 if (mHasUserValue) {
1358 mUserValue.Init(Type(), aWrapper.GetValue(PrefValueKind::User));
1359 }
1360}
1361
1362class CallbackNode {
1363 public:
1364 CallbackNode(const nsACString& aDomain, PrefChangedFunc aFunc, void* aData,
1365 Preferences::MatchKind aMatchKind)
1366 : mDomain(AsVariant(nsCString(aDomain))),
1367 mFunc(aFunc),
1368 mData(aData),
1369 mNextAndMatchKind(aMatchKind) {}
1370
1371 CallbackNode(const char* const* aDomains, PrefChangedFunc aFunc, void* aData,
1372 Preferences::MatchKind aMatchKind)
1373 : mDomain(AsVariant(aDomains)),
1374 mFunc(aFunc),
1375 mData(aData),
1376 mNextAndMatchKind(aMatchKind) {}
1377
1378 // mDomain is a UniquePtr<>, so any uses of Domain() should only be temporary
1379 // borrows.
1380 const Variant<nsCString, const char* const*>& Domain() const {
1381 return mDomain;
1382 }
1383
1384 PrefChangedFunc Func() const { return mFunc; }
1385 void ClearFunc() { mFunc = nullptr; }
1386
1387 void* Data() const { return mData; }
1388
1389 Preferences::MatchKind MatchKind() const {
1390 return static_cast<Preferences::MatchKind>(mNextAndMatchKind &
1391 kMatchKindMask);
1392 }
1393
1394 bool DomainIs(const nsACString& aDomain) const {
1395 return mDomain.is<nsCString>() && mDomain.as<nsCString>() == aDomain;
1396 }
1397
1398 bool DomainIs(const char* const* aPrefs) const {
1399 return mDomain == AsVariant(aPrefs);
1400 }
1401
1402 bool Matches(const nsACString& aPrefName) const {
1403 auto match = [&](const nsACString& aStr) {
1404 return MatchKind() == Preferences::ExactMatch
1405 ? aPrefName == aStr
1406 : StringBeginsWith(aPrefName, aStr);
1407 };
1408
1409 if (mDomain.is<nsCString>()) {
1410 return match(mDomain.as<nsCString>());
1411 }
1412 for (const char* const* ptr = mDomain.as<const char* const*>(); *ptr;
1413 ptr++) {
1414 if (match(nsDependentCString(*ptr))) {
1415 return true;
1416 }
1417 }
1418 return false;
1419 }
1420
1421 CallbackNode* Next() const {
1422 return reinterpret_cast<CallbackNode*>(mNextAndMatchKind & kNextMask);
1423 }
1424
1425 void SetNext(CallbackNode* aNext) {
1426 uintptr_t matchKind = mNextAndMatchKind & kMatchKindMask;
1427 mNextAndMatchKind = reinterpret_cast<uintptr_t>(aNext);
1428 MOZ_ASSERT((mNextAndMatchKind & kMatchKindMask) == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype((mNextAndMatchKind & kMatchKindMask) == 0)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!((mNextAndMatchKind & kMatchKindMask) == 0))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("(mNextAndMatchKind & kMatchKindMask) == 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1428); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(mNextAndMatchKind & kMatchKindMask) == 0"
")"); do { *((volatile int*)__null) = 1428; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1429 mNextAndMatchKind |= matchKind;
1430 }
1431
1432 void AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf, PrefsSizes& aSizes) {
1433 aSizes.mCallbacksObjects += aMallocSizeOf(this);
1434 if (mDomain.is<nsCString>()) {
1435 aSizes.mCallbacksDomains +=
1436 mDomain.as<nsCString>().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
1437 }
1438 }
1439
1440 private:
1441 static const uintptr_t kMatchKindMask = uintptr_t(0x1);
1442 static const uintptr_t kNextMask = ~kMatchKindMask;
1443
1444 Variant<nsCString, const char* const*> mDomain;
1445
1446 // If someone attempts to remove the node from the callback list while
1447 // NotifyCallbacks() is running, |func| is set to nullptr. Such nodes will
1448 // be removed at the end of NotifyCallbacks().
1449 PrefChangedFunc mFunc;
1450 void* mData;
1451
1452 // Conceptually this is two fields:
1453 // - CallbackNode* mNext;
1454 // - Preferences::MatchKind mMatchKind;
1455 // They are combined into a tagged pointer to save memory.
1456 uintptr_t mNextAndMatchKind;
1457};
1458
1459using PrefsHashTable = HashSet<UniquePtr<Pref>, PrefHasher>;
1460
1461// The main prefs hash table. Inside a function so we can assert it's only
1462// accessed on the main thread. (That assertion can be avoided but only do so
1463// with great care!)
1464static inline PrefsHashTable*& HashTable(bool aOffMainThread = false) {
1465 MOZ_ASSERT(NS_IsMainThread() || ServoStyleSet::IsInServoTraversal())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread() || ServoStyleSet::IsInServoTraversal
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(NS_IsMainThread() || ServoStyleSet::IsInServoTraversal
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("NS_IsMainThread() || ServoStyleSet::IsInServoTraversal()", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1465); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread() || ServoStyleSet::IsInServoTraversal()"
")"); do { *((volatile int*)__null) = 1465; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1466 static PrefsHashTable* sHashTable = nullptr;
1467 return sHashTable;
1468}
1469
1470#ifdef DEBUG1
1471// This defines the type used to store our `once` mirrors checker. We can't use
1472// HashMap for now due to alignment restrictions when dealing with
1473// std::function<void()> (see bug 1557617).
1474typedef std::function<void()> AntiFootgunCallback;
1475struct CompareStr {
1476 bool operator()(char const* a, char const* b) const {
1477 return std::strcmp(a, b) < 0;
1478 }
1479};
1480typedef std::map<const char*, AntiFootgunCallback, CompareStr> AntiFootgunMap;
1481static StaticAutoPtr<AntiFootgunMap> gOnceStaticPrefsAntiFootgun;
1482#endif
1483
1484// The callback list contains all the priority callbacks followed by the
1485// non-priority callbacks. gLastPriorityNode records where the first part ends.
1486static CallbackNode* gFirstCallback = nullptr;
1487static CallbackNode* gLastPriorityNode = nullptr;
1488
1489#ifdef DEBUG1
1490# define ACCESS_COUNTS
1491#endif
1492
1493#ifdef ACCESS_COUNTS
1494using AccessCountsHashTable = nsTHashMap<nsCStringHashKey, uint32_t>;
1495static StaticAutoPtr<AccessCountsHashTable> gAccessCounts;
1496
1497static void AddAccessCount(const nsACString& aPrefName) {
1498 // FIXME: Servo reads preferences from background threads in unsafe ways (bug
1499 // 1474789), and triggers assertions here if we try to add usage count entries
1500 // from background threads.
1501 if (NS_IsMainThread()) {
1502 JS::AutoSuppressGCAnalysis nogc; // Hash functions will not GC.
1503 uint32_t& count = gAccessCounts->LookupOrInsert(aPrefName);
1504 count++;
1505 }
1506}
1507
1508static void AddAccessCount(const char* aPrefName) {
1509 AddAccessCount(nsDependentCString(aPrefName));
1510}
1511#else
1512static void MOZ_MAYBE_UNUSED__attribute__((__unused__)) AddAccessCount(const nsACString& aPrefName) {}
1513
1514static void AddAccessCount(const char* aPrefName) {}
1515#endif
1516
1517// These are only used during the call to NotifyCallbacks().
1518static bool gCallbacksInProgress = false;
1519static bool gShouldCleanupDeadNodes = false;
1520
1521class PrefsHashIter {
1522 using Iterator = decltype(HashTable()->modIter());
1523 using ElemType = Pref*;
1524
1525 Iterator mIter;
1526
1527 public:
1528 explicit PrefsHashIter(PrefsHashTable* aTable) : mIter(aTable->modIter()) {}
1529
1530 class Elem {
1531 friend class PrefsHashIter;
1532
1533 PrefsHashIter& mParent;
1534 bool mDone;
1535
1536 Elem(PrefsHashIter& aIter, bool aDone) : mParent(aIter), mDone(aDone) {}
1537
1538 Iterator& Iter() { return mParent.mIter; }
1539
1540 public:
1541 Elem& operator*() { return *this; }
1542
1543 ElemType get() {
1544 if (mDone) {
1545 return nullptr;
1546 }
1547 return Iter().get().get();
1548 }
1549 ElemType get() const { return const_cast<Elem*>(this)->get(); }
1550
1551 ElemType operator->() { return get(); }
1552 ElemType operator->() const { return get(); }
1553
1554 operator ElemType() { return get(); }
1555
1556 void Remove() { Iter().remove(); }
1557
1558 Elem& operator++() {
1559 MOZ_ASSERT(!mDone)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mDone)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(!mDone))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!mDone", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1559); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDone" ")"
); do { *((volatile int*)__null) = 1559; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1560 Iter().next();
1561 mDone = Iter().done();
1562 return *this;
1563 }
1564
1565 bool operator!=(Elem& other) {
1566 return mDone != other.mDone || this->get() != other.get();
1567 }
1568 };
1569
1570 Elem begin() { return Elem(*this, mIter.done()); }
1571
1572 Elem end() { return Elem(*this, true); }
1573};
1574
1575class PrefsIter {
1576 using Iterator = decltype(HashTable()->iter());
1577 using ElemType = PrefWrapper;
1578
1579 using HashElem = PrefsHashIter::Elem;
1580 using SharedElem = SharedPrefMap::Pref;
1581
1582 using ElemTypeVariant = Variant<HashElem, SharedElem>;
1583
1584 SharedPrefMap* mSharedMap;
1585 PrefsHashTable* mHashTable;
1586 PrefsHashIter mIter;
1587
1588 ElemTypeVariant mPos;
1589 ElemTypeVariant mEnd;
1590
1591 Maybe<PrefWrapper> mEntry;
1592
1593 public:
1594 PrefsIter(PrefsHashTable* aHashTable, SharedPrefMap* aSharedMap)
1595 : mSharedMap(aSharedMap),
1596 mHashTable(aHashTable),
1597 mIter(aHashTable),
1598 mPos(AsVariant(mIter.begin())),
1599 mEnd(AsVariant(mIter.end())) {
1600 if (Done()) {
1601 NextIterator();
1602 }
1603 }
1604
1605 private:
1606#define MATCH(type, ...) \
1607 do { \
1608 struct Matcher { \
1609 PrefsIter& mIter; \
1610 type operator()(HashElem& pos) { \
1611 HashElem& end MOZ_MAYBE_UNUSED__attribute__((__unused__)) = mIter.mEnd.as<HashElem>(); \
1612 __VA_ARGS__; \
1613 } \
1614 type operator()(SharedElem& pos) { \
1615 SharedElem& end MOZ_MAYBE_UNUSED__attribute__((__unused__)) = mIter.mEnd.as<SharedElem>(); \
1616 __VA_ARGS__; \
1617 } \
1618 }; \
1619 return mPos.match(Matcher{*this}); \
1620 } while (0);
1621
1622 bool Done() { MATCH(bool, return pos == end); }
1623
1624 PrefWrapper MakeEntry() { MATCH(PrefWrapper, return PrefWrapper(pos)); }
1625
1626 void NextEntry() {
1627 mEntry.reset();
1628 MATCH(void, ++pos);
1629 }
1630#undef MATCH
1631
1632 bool Next() {
1633 NextEntry();
1634 return !Done() || NextIterator();
1635 }
1636
1637 bool NextIterator() {
1638 if (mPos.is<HashElem>() && mSharedMap) {
1639 mPos = AsVariant(mSharedMap->begin());
1640 mEnd = AsVariant(mSharedMap->end());
1641 return !Done();
1642 }
1643 return false;
1644 }
1645
1646 bool IteratingBase() { return mPos.is<SharedElem>(); }
1647
1648 PrefWrapper& Entry() {
1649 MOZ_ASSERT(!Done())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!Done())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!Done()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!Done()", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1649); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!Done()" ")"
); do { *((volatile int*)__null) = 1649; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1650
1651 if (!mEntry.isSome()) {
1652 mEntry.emplace(MakeEntry());
1653 }
1654 return mEntry.ref();
1655 }
1656
1657 public:
1658 class Elem {
1659 friend class PrefsIter;
1660
1661 PrefsIter& mParent;
1662 bool mDone;
1663
1664 Elem(PrefsIter& aIter, bool aDone) : mParent(aIter), mDone(aDone) {
1665 SkipDuplicates();
1666 }
1667
1668 void Next() { mDone = !mParent.Next(); }
1669
1670 void SkipDuplicates() {
1671 while (!mDone &&
1672 (mParent.IteratingBase() ? mParent.mHashTable->has(ref().Name())
1673 : ref().IsTypeNone())) {
1674 Next();
1675 }
1676 }
1677
1678 public:
1679 Elem& operator*() { return *this; }
1680
1681 ElemType& ref() { return mParent.Entry(); }
1682 const ElemType& ref() const { return const_cast<Elem*>(this)->ref(); }
1683
1684 ElemType* operator->() { return &ref(); }
1685 const ElemType* operator->() const { return &ref(); }
1686
1687 operator ElemType() { return ref(); }
1688
1689 Elem& operator++() {
1690 MOZ_ASSERT(!mDone)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mDone)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(!mDone))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!mDone", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1690); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDone" ")"
); do { *((volatile int*)__null) = 1690; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1691 Next();
1692 SkipDuplicates();
1693 return *this;
1694 }
1695
1696 bool operator!=(Elem& other) {
1697 if (mDone != other.mDone) {
1698 return true;
1699 }
1700 if (mDone) {
1701 return false;
1702 }
1703 return &this->ref() != &other.ref();
1704 }
1705 };
1706
1707 Elem begin() { return {*this, Done()}; }
1708
1709 Elem end() { return {*this, true}; }
1710};
1711
1712static Pref* pref_HashTableLookup(const char* aPrefName);
1713
1714static void NotifyCallbacks(const nsCString& aPrefName,
1715 const PrefWrapper* aPref = nullptr);
1716
1717static void NotifyCallbacks(const nsCString& aPrefName,
1718 const PrefWrapper& aPref) {
1719 NotifyCallbacks(aPrefName, &aPref);
1720}
1721
1722// The approximate number of preferences in the dynamic hashtable for the parent
1723// and content processes, respectively. These numbers are used to determine the
1724// initial size of the dynamic preference hashtables, and should be chosen to
1725// avoid rehashing during normal usage. The actual number of preferences will,
1726// or course, change over time, but these numbers only need to be within a
1727// binary order of magnitude of the actual values to remain effective.
1728//
1729// The number for the parent process should reflect the total number of
1730// preferences in the database, since the parent process needs to initially
1731// build a dynamic hashtable of the entire preference database. The number for
1732// the child process should reflect the number of preferences which are likely
1733// to change after the startup of the first content process, since content
1734// processes only store changed preferences on top of a snapshot of the database
1735// created at startup.
1736//
1737// Note: The capacity of a hashtable doubles when its length reaches an exact
1738// power of two. A table with an initial length of 64 is twice as large as one
1739// with an initial length of 63. This is important in content processes, where
1740// lookup speed is less critical and we pay the price of the additional overhead
1741// for each content process. So the initial content length should generally be
1742// *under* the next power-of-two larger than its expected length.
1743constexpr size_t kHashTableInitialLengthParent = 3000;
1744constexpr size_t kHashTableInitialLengthContent = 64;
1745
1746static PrefSaveData pref_savePrefs() {
1747 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1747); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 1747; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1748
1749 PrefSaveData savedPrefs(HashTable()->count());
1750
1751 for (auto& pref : PrefsIter(HashTable(), gSharedMap)) {
1752 nsAutoCString prefValueStr;
1753 if (!pref->UserValueToStringForSaving(prefValueStr)) {
1754 continue;
1755 }
1756
1757 nsAutoCString prefNameStr;
1758 StrEscape(pref->Name(), prefNameStr);
1759
1760 nsPrintfCString str("user_pref(%s, %s);", prefNameStr.get(),
1761 prefValueStr.get());
1762
1763 savedPrefs.AppendElement(str);
1764 }
1765
1766 return savedPrefs;
1767}
1768
1769static Pref* pref_HashTableLookup(const char* aPrefName) {
1770 MOZ_ASSERT(NS_IsMainThread() || ServoStyleSet::IsInServoTraversal())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread() || ServoStyleSet::IsInServoTraversal
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(NS_IsMainThread() || ServoStyleSet::IsInServoTraversal
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("NS_IsMainThread() || ServoStyleSet::IsInServoTraversal()", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1770); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread() || ServoStyleSet::IsInServoTraversal()"
")"); do { *((volatile int*)__null) = 1770; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1771
1772 MOZ_ASSERT_IF(!XRE_IsParentProcess(), gContentProcessPrefsAreInited)do { if (!XRE_IsParentProcess()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(gContentProcessPrefsAreInited
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(gContentProcessPrefsAreInited))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("gContentProcessPrefsAreInited"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1772); AnnotateMozCrashReason("MOZ_ASSERT" "(" "gContentProcessPrefsAreInited"
")"); do { *((volatile int*)__null) = 1772; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1773
1774 // We use readonlyThreadsafeLookup() because we often have concurrent lookups
1775 // from multiple Stylo threads. This is safe because those threads cannot
1776 // modify sHashTable, and the main thread is blocked while Stylo threads are
1777 // doing these lookups.
1778 auto p = HashTable()->readonlyThreadsafeLookup(aPrefName);
1779 return p ? p->get() : nullptr;
1780}
1781
1782// While notifying preference callbacks, this holds the wrapper for the
1783// preference being notified, in order to optimize lookups.
1784//
1785// Note: Callbacks and lookups only happen on the main thread, so this is safe
1786// to use without locking.
1787static const PrefWrapper* gCallbackPref;
1788
1789Maybe<PrefWrapper> pref_SharedLookup(const char* aPrefName) {
1790 MOZ_DIAGNOSTIC_ASSERT(gSharedMap, "gSharedMap must be initialized")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(gSharedMap)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(gSharedMap))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("gSharedMap" " (" "gSharedMap must be initialized"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1790); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "gSharedMap"
") (" "gSharedMap must be initialized" ")"); do { *((volatile
int*)__null) = 1790; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
1791 if (Maybe<SharedPrefMap::Pref> pref = gSharedMap->Get(aPrefName)) {
1792 return Some(*pref);
1793 }
1794 return Nothing();
1795}
1796
1797Maybe<PrefWrapper> pref_Lookup(const char* aPrefName,
1798 bool aIncludeTypeNone = false) {
1799 MOZ_ASSERT(NS_IsMainThread() || ServoStyleSet::IsInServoTraversal())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread() || ServoStyleSet::IsInServoTraversal
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(NS_IsMainThread() || ServoStyleSet::IsInServoTraversal
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("NS_IsMainThread() || ServoStyleSet::IsInServoTraversal()", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1799); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread() || ServoStyleSet::IsInServoTraversal()"
")"); do { *((volatile int*)__null) = 1799; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1800
1801 AddAccessCount(aPrefName);
1802
1803 if (gCallbackPref && strcmp(aPrefName, gCallbackPref->Name()) == 0) {
1804 return Some(*gCallbackPref);
1805 }
1806 if (Pref* pref = pref_HashTableLookup(aPrefName)) {
1807 if (aIncludeTypeNone || !pref->IsTypeNone() || pref->IsSanitized()) {
1808 return Some(pref);
1809 }
1810 } else if (gSharedMap) {
1811 return pref_SharedLookup(aPrefName);
1812 }
1813
1814 return Nothing();
1815}
1816
1817static Result<Pref*, nsresult> pref_LookupForModify(
1818 const nsCString& aPrefName,
1819 const std::function<bool(const PrefWrapper&)>& aCheckFn) {
1820 Maybe<PrefWrapper> wrapper =
1821 pref_Lookup(aPrefName.get(), /* includeTypeNone */ true);
1822 if (wrapper.isNothing()) {
1823 return Err(NS_ERROR_INVALID_ARG);
1824 }
1825 if (!aCheckFn(*wrapper)) {
1826 return nullptr;
1827 }
1828 if (wrapper->is<Pref*>()) {
1829 return wrapper->as<Pref*>();
1830 }
1831
1832 Pref* pref = new Pref(aPrefName);
1833 if (!HashTable()->putNew(aPrefName.get(), pref)) {
1834 delete pref;
1835 return Err(NS_ERROR_OUT_OF_MEMORY);
1836 }
1837 pref->FromWrapper(*wrapper);
1838 return pref;
1839}
1840
1841static nsresult pref_SetPref(const nsCString& aPrefName, PrefType aType,
1842 PrefValueKind aKind, PrefValue aValue,
1843 bool aIsSticky, bool aIsLocked, bool aFromInit) {
1844 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1844); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 1844; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1845 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1845); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 1845; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1846
1847 if (AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMShutdownThreads)) {
1848 printf(
1849 "pref_SetPref: Attempt to write pref %s after XPCOMShutdownThreads "
1850 "started.\n",
1851 aPrefName.get());
1852 if (nsContentUtils::IsInitialized()) {
1853 xpc_DumpJSStack(true, true, false);
1854 }
1855 MOZ_ASSERT(false, "Late preference writes should be avoided.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Late preference writes should be avoided."
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1855); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Late preference writes should be avoided." ")"); do { *((volatile
int*)__null) = 1855; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
1856 return NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
1857 }
1858
1859 if (!HashTable()) {
1860 return NS_ERROR_OUT_OF_MEMORY;
1861 }
1862
1863 Pref* pref = nullptr;
1864 if (gSharedMap) {
1865 auto result =
1866 pref_LookupForModify(aPrefName, [&](const PrefWrapper& aWrapper) {
1867 return !aWrapper.Matches(aType, aKind, aValue, aIsSticky, aIsLocked);
1868 });
1869 if (result.isOk() && !(pref = result.unwrap())) {
1870 // No changes required.
1871 return NS_OK;
1872 }
1873 }
1874
1875 if (!pref) {
1876 auto p = HashTable()->lookupForAdd(aPrefName.get());
1877 if (!p) {
1878 pref = new Pref(aPrefName);
1879 pref->SetType(aType);
1880 if (!HashTable()->add(p, pref)) {
1881 delete pref;
1882 return NS_ERROR_OUT_OF_MEMORY;
1883 }
1884 } else {
1885 pref = p->get();
1886 }
1887 }
1888
1889 bool valueChanged = false;
1890 nsresult rv;
1891 if (aKind == PrefValueKind::Default) {
1892 rv = pref->SetDefaultValue(aType, aValue, aIsSticky, aIsLocked,
1893 &valueChanged);
1894 } else {
1895 MOZ_ASSERT(!aIsLocked)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aIsLocked)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aIsLocked))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!aIsLocked", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1895); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIsLocked"
")"); do { *((volatile int*)__null) = 1895; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
; // `locked` is disallowed in user pref files
1896 rv = pref->SetUserValue(aType, aValue, aFromInit, &valueChanged);
1897 }
1898 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1899 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString("Rejected attempt to change type of pref %s's %s value "
"from %s to %s", aPrefName.get(), (aKind == PrefValueKind::Default
) ? "default" : "user", PrefTypeToString(pref->Type()), PrefTypeToString
(aType)) .get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1905)
1900 nsPrintfCString("Rejected attempt to change type of pref %s's %s value "NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString("Rejected attempt to change type of pref %s's %s value "
"from %s to %s", aPrefName.get(), (aKind == PrefValueKind::Default
) ? "default" : "user", PrefTypeToString(pref->Type()), PrefTypeToString
(aType)) .get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1905)
1901 "from %s to %s",NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString("Rejected attempt to change type of pref %s's %s value "
"from %s to %s", aPrefName.get(), (aKind == PrefValueKind::Default
) ? "default" : "user", PrefTypeToString(pref->Type()), PrefTypeToString
(aType)) .get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1905)
1902 aPrefName.get(),NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString("Rejected attempt to change type of pref %s's %s value "
"from %s to %s", aPrefName.get(), (aKind == PrefValueKind::Default
) ? "default" : "user", PrefTypeToString(pref->Type()), PrefTypeToString
(aType)) .get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1905)
1903 (aKind == PrefValueKind::Default) ? "default" : "user",NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString("Rejected attempt to change type of pref %s's %s value "
"from %s to %s", aPrefName.get(), (aKind == PrefValueKind::Default
) ? "default" : "user", PrefTypeToString(pref->Type()), PrefTypeToString
(aType)) .get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1905)
1904 PrefTypeToString(pref->Type()), PrefTypeToString(aType))NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString("Rejected attempt to change type of pref %s's %s value "
"from %s to %s", aPrefName.get(), (aKind == PrefValueKind::Default
) ? "default" : "user", PrefTypeToString(pref->Type()), PrefTypeToString
(aType)) .get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1905)
1905 .get())NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString("Rejected attempt to change type of pref %s's %s value "
"from %s to %s", aPrefName.get(), (aKind == PrefValueKind::Default
) ? "default" : "user", PrefTypeToString(pref->Type()), PrefTypeToString
(aType)) .get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1905)
;
1906
1907 return rv;
1908 }
1909
1910 if (valueChanged) {
1911 if (!aFromInit && profiler_thread_is_being_profiled_for_markers()) {
1912 nsAutoCString value;
1913 aValue.ToString(aType, value);
1914 profiler_add_marker(do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Preference Write", baseprofiler::category::OTHER_PreferenceRead
, {}, PreferenceMarker{}, aPrefName, Some(aKind), aType, value
); } } while (false)
1915 "Preference Write", baseprofiler::category::OTHER_PreferenceRead, {},do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Preference Write", baseprofiler::category::OTHER_PreferenceRead
, {}, PreferenceMarker{}, aPrefName, Some(aKind), aType, value
); } } while (false)
1916 PreferenceMarker{}, aPrefName, Some(aKind), aType, value)do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Preference Write", baseprofiler::category::OTHER_PreferenceRead
, {}, PreferenceMarker{}, aPrefName, Some(aKind), aType, value
); } } while (false)
;
1917 }
1918
1919 if (aKind == PrefValueKind::User) {
1920 Preferences::HandleDirty();
1921 }
1922 NotifyCallbacks(aPrefName, PrefWrapper(pref));
1923 }
1924
1925 return NS_OK;
1926}
1927
1928// Removes |node| from callback list. Returns the node after the deleted one.
1929static CallbackNode* pref_RemoveCallbackNode(CallbackNode* aNode,
1930 CallbackNode* aPrevNode) {
1931 MOZ_ASSERT(!aPrevNode || aPrevNode->Next() == aNode)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aPrevNode || aPrevNode->Next() == aNode)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!aPrevNode || aPrevNode->Next() == aNode))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!aPrevNode || aPrevNode->Next() == aNode"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1931); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrevNode || aPrevNode->Next() == aNode"
")"); do { *((volatile int*)__null) = 1931; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1932 MOZ_ASSERT(aPrevNode || gFirstCallback == aNode)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPrevNode || gFirstCallback == aNode)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPrevNode || gFirstCallback ==
aNode))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aPrevNode || gFirstCallback == aNode", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1932); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrevNode || gFirstCallback == aNode"
")"); do { *((volatile int*)__null) = 1932; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1933 MOZ_ASSERT(!gCallbacksInProgress)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!gCallbacksInProgress)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!gCallbacksInProgress))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!gCallbacksInProgress"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1933); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!gCallbacksInProgress"
")"); do { *((volatile int*)__null) = 1933; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1934
1935 CallbackNode* next_node = aNode->Next();
1936 if (aPrevNode) {
1937 aPrevNode->SetNext(next_node);
1938 } else {
1939 gFirstCallback = next_node;
1940 }
1941 if (gLastPriorityNode == aNode) {
1942 gLastPriorityNode = aPrevNode;
1943 }
1944 delete aNode;
1945 return next_node;
1946}
1947
1948static void NotifyCallbacks(const nsCString& aPrefName,
1949 const PrefWrapper* aPref) {
1950 bool reentered = gCallbacksInProgress;
1951
1952 gCallbackPref = aPref;
1953 auto cleanup = MakeScopeExit([]() { gCallbackPref = nullptr; });
1954
1955 // Nodes must not be deleted while gCallbacksInProgress is true.
1956 // Nodes that need to be deleted are marked for deletion by nulling
1957 // out the |func| pointer. We release them at the end of this function
1958 // if we haven't reentered.
1959 gCallbacksInProgress = true;
1960
1961 for (CallbackNode* node = gFirstCallback; node; node = node->Next()) {
1962 if (node->Func()) {
1963 if (node->Matches(aPrefName)) {
1964 (node->Func())(aPrefName.get(), node->Data());
1965 }
1966 }
1967 }
1968
1969 gCallbacksInProgress = reentered;
1970
1971 if (gShouldCleanupDeadNodes && !gCallbacksInProgress) {
1972 CallbackNode* prev_node = nullptr;
1973 CallbackNode* node = gFirstCallback;
1974
1975 while (node) {
1976 if (!node->Func()) {
1977 node = pref_RemoveCallbackNode(node, prev_node);
1978 } else {
1979 prev_node = node;
1980 node = node->Next();
1981 }
1982 }
1983 gShouldCleanupDeadNodes = false;
1984 }
1985
1986#ifdef DEBUG1
1987 if (XRE_IsParentProcess() &&
1988 !StaticPrefs::preferences_force_disable_check_once_policy() &&
1989 (StaticPrefs::preferences_check_once_policy() || xpc::IsInAutomation())) {
1990 // Check that we aren't modifying a `once`-mirrored pref using that pref
1991 // name. We have about 100 `once`-mirrored prefs. std::map performs a
1992 // search in O(log n), so this is fast enough.
1993 MOZ_ASSERT(gOnceStaticPrefsAntiFootgun)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(gOnceStaticPrefsAntiFootgun)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(gOnceStaticPrefsAntiFootgun)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("gOnceStaticPrefsAntiFootgun"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 1993); AnnotateMozCrashReason("MOZ_ASSERT" "(" "gOnceStaticPrefsAntiFootgun"
")"); do { *((volatile int*)__null) = 1993; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1994 auto search = gOnceStaticPrefsAntiFootgun->find(aPrefName.get());
1995 if (search != gOnceStaticPrefsAntiFootgun->end()) {
1996 // Run the callback.
1997 (search->second)();
1998 }
1999 }
2000#endif
2001}
2002
2003//===========================================================================
2004// Prefs parsing
2005//===========================================================================
2006
2007extern "C" {
2008
2009// Keep this in sync with PrefFn in parser/src/lib.rs.
2010typedef void (*PrefsParserPrefFn)(const char* aPrefName, PrefType aType,
2011 PrefValueKind aKind, PrefValue aValue,
2012 bool aIsSticky, bool aIsLocked);
2013
2014// Keep this in sync with ErrorFn in parser/src/lib.rs.
2015//
2016// `aMsg` is just a borrow of the string, and must be copied if it is used
2017// outside the lifetime of the prefs_parser_parse() call.
2018typedef void (*PrefsParserErrorFn)(const char* aMsg);
2019
2020// Keep this in sync with prefs_parser_parse() in parser/src/lib.rs.
2021bool prefs_parser_parse(const char* aPath, PrefValueKind aKind,
2022 const char* aBuf, size_t aLen,
2023 PrefsParserPrefFn aPrefFn, PrefsParserErrorFn aErrorFn);
2024}
2025
2026class Parser {
2027 public:
2028 Parser() = default;
2029 ~Parser() = default;
2030
2031 bool Parse(PrefValueKind aKind, const char* aPath, const nsCString& aBuf) {
2032 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2032); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 2032; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2033 return prefs_parser_parse(aPath, aKind, aBuf.get(), aBuf.Length(),
2034 HandlePref, HandleError);
2035 }
2036
2037 private:
2038 static void HandlePref(const char* aPrefName, PrefType aType,
2039 PrefValueKind aKind, PrefValue aValue, bool aIsSticky,
2040 bool aIsLocked) {
2041 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2041); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 2041; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2042 pref_SetPref(nsDependentCString(aPrefName), aType, aKind, aValue, aIsSticky,
2043 aIsLocked,
2044 /* fromInit */ true);
2045 }
2046
2047 static void HandleError(const char* aMsg) {
2048 nsresult rv;
2049 nsCOMPtr<nsIConsoleService> console =
2050 do_GetService("@mozilla.org/consoleservice;1", &rv);
2051 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2052 console->LogStringMessage(NS_ConvertUTF8toUTF16(aMsg).get());
2053 }
2054#ifdef DEBUG1
2055 NS_ERROR(aMsg)do { NS_DebugBreak(NS_DEBUG_ASSERTION, aMsg, "Error", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2055); MOZ_PretendNoReturn(); } while (0)
;
2056#else
2057 printf_stderr("%s\n", aMsg);
2058#endif
2059 }
2060};
2061
2062// The following code is test code for the gtest.
2063
2064static void TestParseErrorHandlePref(const char* aPrefName, PrefType aType,
2065 PrefValueKind aKind, PrefValue aValue,
2066 bool aIsSticky, bool aIsLocked) {}
2067
2068static nsCString gTestParseErrorMsgs;
2069
2070static void TestParseErrorHandleError(const char* aMsg) {
2071 gTestParseErrorMsgs.Append(aMsg);
2072 gTestParseErrorMsgs.Append('\n');
2073}
2074
2075// Keep this in sync with the declaration in test/gtest/Parser.cpp.
2076void TestParseError(PrefValueKind aKind, const char* aText,
2077 nsCString& aErrorMsg) {
2078 prefs_parser_parse("test", aKind, aText, strlen(aText),
2079 TestParseErrorHandlePref, TestParseErrorHandleError);
2080
2081 // Copy the error messages into the outparam, then clear them from
2082 // gTestParseErrorMsgs.
2083 aErrorMsg.Assign(gTestParseErrorMsgs);
2084 gTestParseErrorMsgs.Truncate();
2085}
2086
2087//===========================================================================
2088// nsPrefBranch et al.
2089//===========================================================================
2090
2091namespace mozilla {
2092class PreferenceServiceReporter;
2093} // namespace mozilla
2094
2095class PrefCallback : public PLDHashEntryHdr {
2096 friend class mozilla::PreferenceServiceReporter;
2097
2098 public:
2099 typedef PrefCallback* KeyType;
2100 typedef const PrefCallback* KeyTypePointer;
2101
2102 static const PrefCallback* KeyToPointer(PrefCallback* aKey) { return aKey; }
2103
2104 static PLDHashNumber HashKey(const PrefCallback* aKey) {
2105 uint32_t hash = HashString(aKey->mDomain);
2106 return AddToHash(hash, aKey->mCanonical);
2107 }
2108
2109 public:
2110 // Create a PrefCallback with a strong reference to its observer.
2111 PrefCallback(const nsACString& aDomain, nsIObserver* aObserver,
2112 nsPrefBranch* aBranch)
2113 : mDomain(aDomain),
2114 mBranch(aBranch),
2115 mWeakRef(nullptr),
2116 mStrongRef(aObserver) {
2117 MOZ_COUNT_CTOR(PrefCallback)do { static_assert(std::is_class_v<PrefCallback>, "Token '"
"PrefCallback" "' is not a class type."); static_assert(!std
::is_base_of<nsISupports, PrefCallback>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "PrefCallback", sizeof
(*this)); } while (0)
;
2118 nsCOMPtr<nsISupports> canonical = do_QueryInterface(aObserver);
2119 mCanonical = canonical;
2120 }
2121
2122 // Create a PrefCallback with a weak reference to its observer.
2123 PrefCallback(const nsACString& aDomain, nsISupportsWeakReference* aObserver,
2124 nsPrefBranch* aBranch)
2125 : mDomain(aDomain),
2126 mBranch(aBranch),
2127 mWeakRef(do_GetWeakReference(aObserver)),
2128 mStrongRef(nullptr) {
2129 MOZ_COUNT_CTOR(PrefCallback)do { static_assert(std::is_class_v<PrefCallback>, "Token '"
"PrefCallback" "' is not a class type."); static_assert(!std
::is_base_of<nsISupports, PrefCallback>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "PrefCallback", sizeof
(*this)); } while (0)
;
2130 nsCOMPtr<nsISupports> canonical = do_QueryInterface(aObserver);
2131 mCanonical = canonical;
2132 }
2133
2134 // This is explicitly not a copy constructor.
2135 explicit PrefCallback(const PrefCallback*& aCopy)
2136 : mDomain(aCopy->mDomain),
2137 mBranch(aCopy->mBranch),
2138 mWeakRef(aCopy->mWeakRef),
2139 mStrongRef(aCopy->mStrongRef),
2140 mCanonical(aCopy->mCanonical) {
2141 MOZ_COUNT_CTOR(PrefCallback)do { static_assert(std::is_class_v<PrefCallback>, "Token '"
"PrefCallback" "' is not a class type."); static_assert(!std
::is_base_of<nsISupports, PrefCallback>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "PrefCallback", sizeof
(*this)); } while (0)
;
2142 }
2143
2144 PrefCallback(const PrefCallback&) = delete;
2145 PrefCallback(PrefCallback&&) = default;
2146
2147 MOZ_COUNTED_DTOR(PrefCallback)~PrefCallback() { do { static_assert(std::is_class_v<PrefCallback
>, "Token '" "PrefCallback" "' is not a class type."); static_assert
(!std::is_base_of<nsISupports, PrefCallback>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "PrefCallback", sizeof
(*this)); } while (0); }
2148
2149 bool KeyEquals(const PrefCallback* aKey) const {
2150 // We want to be able to look up a weakly-referencing PrefCallback after
2151 // its observer has died so we can remove it from the table. Once the
2152 // callback's observer dies, its canonical pointer is stale -- in
2153 // particular, we may have allocated a new observer in the same spot in
2154 // memory! So we can't just compare canonical pointers to determine whether
2155 // aKey refers to the same observer as this.
2156 //
2157 // Our workaround is based on the way we use this hashtable: When we ask
2158 // the hashtable to remove a PrefCallback whose weak reference has expired,
2159 // we use as the key for removal the same object as was inserted into the
2160 // hashtable. Thus we can say that if one of the keys' weak references has
2161 // expired, the two keys are equal iff they're the same object.
2162
2163 if (IsExpired() || aKey->IsExpired()) {
2164 return this == aKey;
2165 }
2166
2167 if (mCanonical != aKey->mCanonical) {
2168 return false;
2169 }
2170
2171 return mDomain.Equals(aKey->mDomain);
2172 }
2173
2174 PrefCallback* GetKey() const { return const_cast<PrefCallback*>(this); }
2175
2176 // Get a reference to the callback's observer, or null if the observer was
2177 // weakly referenced and has been destroyed.
2178 already_AddRefed<nsIObserver> GetObserver() const {
2179 if (!IsWeak()) {
2180 nsCOMPtr<nsIObserver> copy = mStrongRef;
2181 return copy.forget();
2182 }
2183
2184 nsCOMPtr<nsIObserver> observer = do_QueryReferent(mWeakRef);
2185 return observer.forget();
2186 }
2187
2188 const nsCString& GetDomain() const { return mDomain; }
2189
2190 nsPrefBranch* GetPrefBranch() const { return mBranch; }
2191
2192 // Has this callback's weak reference died?
2193 bool IsExpired() const {
2194 if (!IsWeak()) return false;
2195
2196 nsCOMPtr<nsIObserver> observer(do_QueryReferent(mWeakRef));
2197 return !observer;
2198 }
2199
2200 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
2201 size_t n = aMallocSizeOf(this);
2202 n += mDomain.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
2203
2204 // All the other fields are non-owning pointers, so we don't measure them.
2205
2206 return n;
2207 }
2208
2209 enum { ALLOW_MEMMOVE = true };
2210
2211 private:
2212 nsCString mDomain;
2213 nsPrefBranch* mBranch;
2214
2215 // Exactly one of mWeakRef and mStrongRef should be non-null.
2216 nsWeakPtr mWeakRef;
2217 nsCOMPtr<nsIObserver> mStrongRef;
2218
2219 // We need a canonical nsISupports pointer, per bug 578392.
2220 nsISupports* mCanonical;
2221
2222 bool IsWeak() const { return !!mWeakRef; }
2223};
2224
2225class nsPrefBranch final : public nsIPrefBranch,
2226 public nsIObserver,
2227 public nsSupportsWeakReference {
2228 friend class mozilla::PreferenceServiceReporter;
2229
2230 public:
2231 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
2232 NS_DECL_NSIPREFBRANCHvirtual nsresult GetRoot(nsACString& aRoot) override; virtual
nsresult GetPrefType(const char * aPrefName, int32_t *_retval
) override; virtual nsresult GetBoolPrefWithDefault(const char
* aPrefName, bool aDefaultValue, uint8_t _argc, bool *_retval
) override; virtual nsresult GetBoolPref(const char * aPrefName
, bool *_retval) override; virtual nsresult SetBoolPref(const
char * aPrefName, bool aValue) override; virtual nsresult GetFloatPrefWithDefault
(const char * aPrefName, float aDefaultValue, uint8_t _argc, float
*_retval) override; virtual nsresult GetFloatPref(const char
* aPrefName, float *_retval) override; virtual nsresult GetCharPrefWithDefault
(const char * aPrefName, const nsACString& aDefaultValue,
uint8_t _argc, nsACString& _retval) override; virtual nsresult
GetCharPref(const char * aPrefName, nsACString& _retval)
override; virtual nsresult SetCharPref(const char * aPrefName
, const nsACString& aValue) override; virtual nsresult GetStringPref
(const char * aPrefName, const nsACString& aDefaultValue,
uint8_t _argc, nsACString& _retval) override; virtual nsresult
SetStringPref(const char * aPrefName, const nsACString& aValue
) override; virtual nsresult GetIntPrefWithDefault(const char
* aPrefName, int32_t aDefaultValue, uint8_t _argc, int32_t *
_retval) override; virtual nsresult GetIntPref(const char * aPrefName
, int32_t *_retval) override; virtual nsresult SetIntPref(const
char * aPrefName, int32_t aValue) override; virtual nsresult
GetComplexValue(const char * aPrefName, const nsIID & aType
, void * * aValue) override; virtual nsresult SetComplexValue
(const char * aPrefName, const nsIID & aType, nsISupports
*aValue) override; virtual nsresult ClearUserPref(const char
* aPrefName) override; virtual nsresult LockPref(const char *
aPrefName) override; virtual nsresult PrefHasUserValue(const
char * aPrefName, bool *_retval) override; virtual nsresult PrefHasDefaultValue
(const char * aPrefName, bool *_retval) override; virtual nsresult
PrefIsLocked(const char * aPrefName, bool *_retval) override
; virtual nsresult PrefIsSanitized(const char * aPrefName, bool
*_retval) override; virtual nsresult UnlockPref(const char *
aPrefName) override; virtual nsresult DeleteBranch(const char
* aStartingAt) override; virtual nsresult GetChildList(const
char * aStartingAt, nsTArray<nsCString >& _retval)
override; virtual nsresult AddObserverImpl(const nsACString&
aDomain, nsIObserver *aObserver, bool aHoldWeak) override; virtual
nsresult RemoveObserverImpl(const nsACString& aDomain, nsIObserver
*aObserver) override;
2233 NS_DECL_NSIOBSERVERvirtual nsresult Observe(nsISupports *aSubject, const char * aTopic
, const char16_t * aData) override;
2234
2235 nsPrefBranch(const char* aPrefRoot, PrefValueKind aKind);
2236 nsPrefBranch() = delete;
2237
2238 static void NotifyObserver(const char* aNewpref, void* aData);
2239
2240 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
2241
2242 private:
2243 using PrefName = nsCString;
2244
2245 virtual ~nsPrefBranch();
2246
2247 int32_t GetRootLength() const { return mPrefRoot.Length(); }
2248
2249 nsresult GetDefaultFromPropertiesFile(const char* aPrefName,
2250 nsAString& aReturn);
2251
2252 // As SetCharPref, but without any check on the length of |aValue|.
2253 nsresult SetCharPrefNoLengthCheck(const char* aPrefName,
2254 const nsACString& aValue);
2255
2256 // Reject strings that are more than 1Mb, warn if strings are more than 16kb.
2257 nsresult CheckSanityOfStringLength(const char* aPrefName,
2258 const nsAString& aValue);
2259 nsresult CheckSanityOfStringLength(const char* aPrefName,
2260 const nsACString& aValue);
2261 nsresult CheckSanityOfStringLength(const char* aPrefName,
2262 const uint32_t aLength);
2263
2264 void RemoveExpiredCallback(PrefCallback* aCallback);
2265
2266 PrefName GetPrefName(const char* aPrefName) const {
2267 return GetPrefName(nsDependentCString(aPrefName));
2268 }
2269
2270 PrefName GetPrefName(const nsACString& aPrefName) const;
2271
2272 void FreeObserverList(void);
2273
2274 const nsCString mPrefRoot;
2275 PrefValueKind mKind;
2276
2277 bool mFreeingObserverList;
2278 nsClassHashtable<PrefCallback, PrefCallback> mObservers;
2279};
2280
2281class nsPrefLocalizedString final : public nsIPrefLocalizedString {
2282 public:
2283 nsPrefLocalizedString();
2284
2285 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
2286 NS_FORWARD_NSISUPPORTSPRIMITIVE(mUnicodeString->)virtual nsresult GetType(uint16_t *aType) override { return mUnicodeString
-> GetType(aType); }
2287 NS_FORWARD_NSISUPPORTSSTRING(mUnicodeString->)virtual nsresult GetData(nsAString& aData) override { return
mUnicodeString-> GetData(aData); } virtual nsresult SetData
(const nsAString& aData) override { return mUnicodeString
-> SetData(aData); } virtual nsresult ToString(char16_t * *
_retval) override { return mUnicodeString-> ToString(_retval
); }
2288
2289 nsresult Init();
2290
2291 private:
2292 virtual ~nsPrefLocalizedString();
2293
2294 nsCOMPtr<nsISupportsString> mUnicodeString;
2295};
2296
2297//----------------------------------------------------------------------------
2298// nsPrefBranch
2299//----------------------------------------------------------------------------
2300
2301nsPrefBranch::nsPrefBranch(const char* aPrefRoot, PrefValueKind aKind)
2302 : mPrefRoot(aPrefRoot), mKind(aKind), mFreeingObserverList(false) {
2303 nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
2304 if (observerService) {
2305 ++mRefCnt; // must be > 0 when we call this, or we'll get deleted!
2306
2307 // Add weakly so we don't have to clean up at shutdown.
2308 observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown", true);
2309 --mRefCnt;
2310 }
2311}
2312
2313nsPrefBranch::~nsPrefBranch() { FreeObserverList(); }
2314
2315NS_IMPL_ISUPPORTS(nsPrefBranch, nsIPrefBranch, nsIObserver,MozExternalRefCountType nsPrefBranch::AddRef(void) { static_assert
(!std::is_destructible_v<nsPrefBranch>, "Reference-counted class "
"nsPrefBranch" " should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2316); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
2316; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsPrefBranch" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsPrefBranch" != nullptr)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"nsPrefBranch\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2316); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsPrefBranch\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 2316; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsPrefBranch" " not thread-safe"); nsrefcnt
count = ++mRefCnt; NS_LogAddRef((this), (count), ("nsPrefBranch"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
nsPrefBranch::Release(void) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(int32_t(mRefCnt) > 0)
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2316); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 2316
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsPrefBranch" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsPrefBranch" != nullptr)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"nsPrefBranch\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2316); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsPrefBranch\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 2316; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsPrefBranch" " not thread-safe"); const char
* const nametmp = "nsPrefBranch"; nsrefcnt count = --mRefCnt;
NS_LogRelease((this), (count), (nametmp)); if (count == 0) {
mRefCnt = 1; delete (this); return 0; } return count; } nsresult
nsPrefBranch::QueryInterface(const nsIID& aIID, void** aInstancePtr
) { do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "QueryInterface requires a non-NULL destination!", "aInstancePtr"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2316); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(3 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsPrefBranch, nsIPrefBranch>, int32_t
( reinterpret_cast<char*>(static_cast<nsIPrefBranch*
>((nsPrefBranch*)0x1000)) - reinterpret_cast<char*>(
(nsPrefBranch*)0x1000))}, {&mozilla::detail::kImplementedIID
<nsPrefBranch, nsIObserver>, int32_t( reinterpret_cast<
char*>(static_cast<nsIObserver*>((nsPrefBranch*)0x1000
)) - reinterpret_cast<char*>((nsPrefBranch*)0x1000))}, {
&mozilla::detail::kImplementedIID<nsPrefBranch, nsISupportsWeakReference
>, int32_t( reinterpret_cast<char*>(static_cast<nsISupportsWeakReference
*>((nsPrefBranch*)0x1000)) - reinterpret_cast<char*>
((nsPrefBranch*)0x1000))}, {&mozilla::detail::kImplementedIID
<nsPrefBranch, nsISupports>, int32_t(reinterpret_cast<
char*>(static_cast<nsISupports*>( static_cast<nsIPrefBranch
*>((nsPrefBranch*)0x1000))) - reinterpret_cast<char*>
((nsPrefBranch*)0x1000))}, { nullptr, 0 } } ; static_assert((
sizeof(table) / sizeof(table[0])) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
2316 nsISupportsWeakReference)MozExternalRefCountType nsPrefBranch::AddRef(void) { static_assert
(!std::is_destructible_v<nsPrefBranch>, "Reference-counted class "
"nsPrefBranch" " should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2316); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
2316; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsPrefBranch" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsPrefBranch" != nullptr)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"nsPrefBranch\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2316); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsPrefBranch\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 2316; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsPrefBranch" " not thread-safe"); nsrefcnt
count = ++mRefCnt; NS_LogAddRef((this), (count), ("nsPrefBranch"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
nsPrefBranch::Release(void) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(int32_t(mRefCnt) > 0)
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2316); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 2316
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsPrefBranch" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsPrefBranch" != nullptr)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"nsPrefBranch\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2316); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsPrefBranch\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 2316; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsPrefBranch" " not thread-safe"); const char
* const nametmp = "nsPrefBranch"; nsrefcnt count = --mRefCnt;
NS_LogRelease((this), (count), (nametmp)); if (count == 0) {
mRefCnt = 1; delete (this); return 0; } return count; } nsresult
nsPrefBranch::QueryInterface(const nsIID& aIID, void** aInstancePtr
) { do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "QueryInterface requires a non-NULL destination!", "aInstancePtr"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2316); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(3 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsPrefBranch, nsIPrefBranch>, int32_t
( reinterpret_cast<char*>(static_cast<nsIPrefBranch*
>((nsPrefBranch*)0x1000)) - reinterpret_cast<char*>(
(nsPrefBranch*)0x1000))}, {&mozilla::detail::kImplementedIID
<nsPrefBranch, nsIObserver>, int32_t( reinterpret_cast<
char*>(static_cast<nsIObserver*>((nsPrefBranch*)0x1000
)) - reinterpret_cast<char*>((nsPrefBranch*)0x1000))}, {
&mozilla::detail::kImplementedIID<nsPrefBranch, nsISupportsWeakReference
>, int32_t( reinterpret_cast<char*>(static_cast<nsISupportsWeakReference
*>((nsPrefBranch*)0x1000)) - reinterpret_cast<char*>
((nsPrefBranch*)0x1000))}, {&mozilla::detail::kImplementedIID
<nsPrefBranch, nsISupports>, int32_t(reinterpret_cast<
char*>(static_cast<nsISupports*>( static_cast<nsIPrefBranch
*>((nsPrefBranch*)0x1000))) - reinterpret_cast<char*>
((nsPrefBranch*)0x1000))}, { nullptr, 0 } } ; static_assert((
sizeof(table) / sizeof(table[0])) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
2317
2318NS_IMETHODIMPnsresult
2319nsPrefBranch::GetRoot(nsACString& aRoot) {
2320 aRoot = mPrefRoot;
2321 return NS_OK;
2322}
2323
2324NS_IMETHODIMPnsresult
2325nsPrefBranch::GetPrefType(const char* aPrefName, int32_t* aRetVal) {
2326 NS_ENSURE_ARG(aPrefName)do { if ((__builtin_expect(!!(!(aPrefName)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aPrefName" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2326); return NS_ERROR_INVALID_ARG; } } while (false)
;
2327
2328 const PrefName& prefName = GetPrefName(aPrefName);
2329 *aRetVal = Preferences::GetType(prefName.get());
2330 return NS_OK;
2331}
2332
2333NS_IMETHODIMPnsresult
2334nsPrefBranch::GetBoolPrefWithDefault(const char* aPrefName, bool aDefaultValue,
2335 uint8_t aArgc, bool* aRetVal) {
2336 nsresult rv = GetBoolPref(aPrefName, aRetVal);
2337 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && aArgc == 1) {
2338 *aRetVal = aDefaultValue;
2339 return NS_OK;
2340 }
2341
2342 return rv;
2343}
2344
2345NS_IMETHODIMPnsresult
2346nsPrefBranch::GetBoolPref(const char* aPrefName, bool* aRetVal) {
2347 NS_ENSURE_ARG(aPrefName)do { if ((__builtin_expect(!!(!(aPrefName)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aPrefName" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2347); return NS_ERROR_INVALID_ARG; } } while (false)
;
2348
2349 const PrefName& pref = GetPrefName(aPrefName);
2350 return Preferences::GetBool(pref.get(), aRetVal, mKind);
2351}
2352
2353NS_IMETHODIMPnsresult
2354nsPrefBranch::SetBoolPref(const char* aPrefName, bool aValue) {
2355 NS_ENSURE_ARG(aPrefName)do { if ((__builtin_expect(!!(!(aPrefName)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aPrefName" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2355); return NS_ERROR_INVALID_ARG; } } while (false)
;
2356
2357 const PrefName& pref = GetPrefName(aPrefName);
2358 return Preferences::SetBool(pref.get(), aValue, mKind);
2359}
2360
2361NS_IMETHODIMPnsresult
2362nsPrefBranch::GetFloatPrefWithDefault(const char* aPrefName,
2363 float aDefaultValue, uint8_t aArgc,
2364 float* aRetVal) {
2365 nsresult rv = GetFloatPref(aPrefName, aRetVal);
2366
2367 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && aArgc == 1) {
2368 *aRetVal = aDefaultValue;
2369 return NS_OK;
2370 }
2371
2372 return rv;
2373}
2374
2375NS_IMETHODIMPnsresult
2376nsPrefBranch::GetFloatPref(const char* aPrefName, float* aRetVal) {
2377 NS_ENSURE_ARG(aPrefName)do { if ((__builtin_expect(!!(!(aPrefName)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aPrefName" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2377); return NS_ERROR_INVALID_ARG; } } while (false)
;
2378
2379 nsAutoCString stringVal;
2380 nsresult rv = GetCharPref(aPrefName, stringVal);
2381 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2382 // ParsePrefFloat() does a locale-independent conversion.
2383 *aRetVal = ParsePrefFloat(stringVal, &rv);
2384 }
2385
2386 return rv;
2387}
2388
2389NS_IMETHODIMPnsresult
2390nsPrefBranch::GetCharPrefWithDefault(const char* aPrefName,
2391 const nsACString& aDefaultValue,
2392 uint8_t aArgc, nsACString& aRetVal) {
2393 nsresult rv = GetCharPref(aPrefName, aRetVal);
2394
2395 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && aArgc == 1) {
2396 aRetVal = aDefaultValue;
2397 return NS_OK;
2398 }
2399
2400 return rv;
2401}
2402
2403NS_IMETHODIMPnsresult
2404nsPrefBranch::GetCharPref(const char* aPrefName, nsACString& aRetVal) {
2405 NS_ENSURE_ARG(aPrefName)do { if ((__builtin_expect(!!(!(aPrefName)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aPrefName" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2405); return NS_ERROR_INVALID_ARG; } } while (false)
;
2406
2407 const PrefName& pref = GetPrefName(aPrefName);
2408 return Preferences::GetCString(pref.get(), aRetVal, mKind);
2409}
2410
2411NS_IMETHODIMPnsresult
2412nsPrefBranch::SetCharPref(const char* aPrefName, const nsACString& aValue) {
2413 nsresult rv = CheckSanityOfStringLength(aPrefName, aValue);
2414 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2415 return rv;
2416 }
2417 return SetCharPrefNoLengthCheck(aPrefName, aValue);
2418}
2419
2420nsresult nsPrefBranch::SetCharPrefNoLengthCheck(const char* aPrefName,
2421 const nsACString& aValue) {
2422 NS_ENSURE_ARG(aPrefName)do { if ((__builtin_expect(!!(!(aPrefName)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aPrefName" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2422); return NS_ERROR_INVALID_ARG; } } while (false)
;
2423
2424 const PrefName& pref = GetPrefName(aPrefName);
2425 return Preferences::SetCString(pref.get(), aValue, mKind);
2426}
2427
2428NS_IMETHODIMPnsresult
2429nsPrefBranch::GetStringPref(const char* aPrefName,
2430 const nsACString& aDefaultValue, uint8_t aArgc,
2431 nsACString& aRetVal) {
2432 nsCString utf8String;
2433 nsresult rv = GetCharPref(aPrefName, utf8String);
2434 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2435 aRetVal = utf8String;
2436 return rv;
2437 }
2438
2439 if (aArgc == 1) {
2440 aRetVal = aDefaultValue;
2441 return NS_OK;
2442 }
2443
2444 return rv;
2445}
2446
2447NS_IMETHODIMPnsresult
2448nsPrefBranch::SetStringPref(const char* aPrefName, const nsACString& aValue) {
2449 nsresult rv = CheckSanityOfStringLength(aPrefName, aValue);
2450 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2451 return rv;
2452 }
2453
2454 return SetCharPrefNoLengthCheck(aPrefName, aValue);
2455}
2456
2457NS_IMETHODIMPnsresult
2458nsPrefBranch::GetIntPrefWithDefault(const char* aPrefName,
2459 int32_t aDefaultValue, uint8_t aArgc,
2460 int32_t* aRetVal) {
2461 nsresult rv = GetIntPref(aPrefName, aRetVal);
2462
2463 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && aArgc == 1) {
2464 *aRetVal = aDefaultValue;
2465 return NS_OK;
2466 }
2467
2468 return rv;
2469}
2470
2471NS_IMETHODIMPnsresult
2472nsPrefBranch::GetIntPref(const char* aPrefName, int32_t* aRetVal) {
2473 NS_ENSURE_ARG(aPrefName)do { if ((__builtin_expect(!!(!(aPrefName)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aPrefName" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2473); return NS_ERROR_INVALID_ARG; } } while (false)
;
2474 const PrefName& pref = GetPrefName(aPrefName);
2475 return Preferences::GetInt(pref.get(), aRetVal, mKind);
2476}
2477
2478NS_IMETHODIMPnsresult
2479nsPrefBranch::SetIntPref(const char* aPrefName, int32_t aValue) {
2480 NS_ENSURE_ARG(aPrefName)do { if ((__builtin_expect(!!(!(aPrefName)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aPrefName" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2480); return NS_ERROR_INVALID_ARG; } } while (false)
;
2481
2482 const PrefName& pref = GetPrefName(aPrefName);
2483 return Preferences::SetInt(pref.get(), aValue, mKind);
2484}
2485
2486NS_IMETHODIMPnsresult
2487nsPrefBranch::GetComplexValue(const char* aPrefName, const nsIID& aType,
2488 void** aRetVal) {
2489 NS_ENSURE_ARG(aPrefName)do { if ((__builtin_expect(!!(!(aPrefName)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aPrefName" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2489); return NS_ERROR_INVALID_ARG; } } while (false)
;
2490
2491 nsresult rv;
2492 nsAutoCString utf8String;
2493
2494 // We have to do this one first because it's different to all the rest.
2495 if (aType.Equals(NS_GET_IID(nsIPrefLocalizedString)(nsIPrefLocalizedString::COMTypeInfo<nsIPrefLocalizedString
, void>::kIID)
)) {
2496 nsCOMPtr<nsIPrefLocalizedString> theString(
2497 do_CreateInstance(NS_PREFLOCALIZEDSTRING_CONTRACTID"@mozilla.org/pref-localizedstring;1", &rv));
2498 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2499 return rv;
2500 }
2501
2502 const PrefName& pref = GetPrefName(aPrefName);
2503 bool bNeedDefault = false;
2504
2505 if (mKind == PrefValueKind::Default) {
2506 bNeedDefault = true;
2507 } else {
2508 // if there is no user (or locked) value
2509 if (!Preferences::HasUserValue(pref.get()) &&
2510 !Preferences::IsLocked(pref.get())) {
2511 bNeedDefault = true;
2512 }
2513 }
2514
2515 // if we need to fetch the default value, do that instead, otherwise use the
2516 // value we pulled in at the top of this function
2517 if (bNeedDefault) {
2518 nsAutoString utf16String;
2519 rv = GetDefaultFromPropertiesFile(pref.get(), utf16String);
2520 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2521 theString->SetData(utf16String);
2522 }
2523 } else {
2524 rv = GetCharPref(aPrefName, utf8String);
2525 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2526 theString->SetData(NS_ConvertUTF8toUTF16(utf8String));
2527 }
2528 }
2529
2530 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2531 theString.forget(reinterpret_cast<nsIPrefLocalizedString**>(aRetVal));
2532 }
2533
2534 return rv;
2535 }
2536
2537 // if we can't get the pref, there's no point in being here
2538 rv = GetCharPref(aPrefName, utf8String);
2539 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2540 return rv;
2541 }
2542
2543 if (aType.Equals(NS_GET_IID(nsIFile)(nsIFile::COMTypeInfo<nsIFile, void>::kIID))) {
2544 ENSURE_PARENT_PROCESS("GetComplexValue(nsIFile)", aPrefName);
2545
2546 nsCOMPtr<nsIFile> file(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID"@mozilla.org/file/local;1", &rv));
2547
2548 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2549 rv = file->SetPersistentDescriptor(utf8String);
2550 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2551 file.forget(reinterpret_cast<nsIFile**>(aRetVal));
2552 return NS_OK;
2553 }
2554 }
2555 return rv;
2556 }
2557
2558 if (aType.Equals(NS_GET_IID(nsIRelativeFilePref)(nsIRelativeFilePref::COMTypeInfo<nsIRelativeFilePref, void
>::kIID)
)) {
2559 ENSURE_PARENT_PROCESS("GetComplexValue(nsIRelativeFilePref)", aPrefName);
2560
2561 nsACString::const_iterator keyBegin, strEnd;
2562 utf8String.BeginReading(keyBegin);
2563 utf8String.EndReading(strEnd);
2564
2565 // The pref has the format: [fromKey]a/b/c
2566 if (*keyBegin++ != '[') {
2567 return NS_ERROR_FAILURE;
2568 }
2569
2570 nsACString::const_iterator keyEnd(keyBegin);
2571 if (!FindCharInReadable(']', keyEnd, strEnd)) {
2572 return NS_ERROR_FAILURE;
2573 }
2574
2575 nsAutoCString key(Substring(keyBegin, keyEnd));
2576
2577 nsCOMPtr<nsIFile> fromFile;
2578 nsCOMPtr<nsIProperties> directoryService(
2579 do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID"@mozilla.org/file/directory_service;1", &rv));
2580 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2581 return rv;
2582 }
2583
2584 rv = directoryService->Get(key.get(), NS_GET_IID(nsIFile)(nsIFile::COMTypeInfo<nsIFile, void>::kIID),
2585 getter_AddRefs(fromFile));
2586 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2587 return rv;
2588 }
2589
2590 nsCOMPtr<nsIFile> theFile;
2591 rv = NS_NewNativeLocalFile(""_ns, true, getter_AddRefs(theFile));
2592 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2593 return rv;
2594 }
2595
2596 rv = theFile->SetRelativeDescriptor(fromFile, Substring(++keyEnd, strEnd));
2597 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2598 return rv;
2599 }
2600
2601 nsCOMPtr<nsIRelativeFilePref> relativePref = new nsRelativeFilePref();
2602 Unused << relativePref->SetFile(theFile);
2603 Unused << relativePref->SetRelativeToKey(key);
2604
2605 relativePref.forget(reinterpret_cast<nsIRelativeFilePref**>(aRetVal));
2606 return NS_OK;
2607 }
2608
2609 NS_WARNING("nsPrefBranch::GetComplexValue - Unsupported interface type")NS_DebugBreak(NS_DEBUG_WARNING, "nsPrefBranch::GetComplexValue - Unsupported interface type"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2609)
;
2610 return NS_NOINTERFACE;
2611}
2612
2613nsresult nsPrefBranch::CheckSanityOfStringLength(const char* aPrefName,
2614 const nsAString& aValue) {
2615 return CheckSanityOfStringLength(aPrefName, aValue.Length());
2616}
2617
2618nsresult nsPrefBranch::CheckSanityOfStringLength(const char* aPrefName,
2619 const nsACString& aValue) {
2620 return CheckSanityOfStringLength(aPrefName, aValue.Length());
2621}
2622
2623nsresult nsPrefBranch::CheckSanityOfStringLength(const char* aPrefName,
2624 const uint32_t aLength) {
2625 if (aLength > MAX_PREF_LENGTH) {
2626 return NS_ERROR_ILLEGAL_VALUE;
2627 }
2628 if (aLength <= MAX_ADVISABLE_PREF_LENGTH) {
2629 return NS_OK;
2630 }
2631
2632 nsresult rv;
2633 nsCOMPtr<nsIConsoleService> console =
2634 do_GetService("@mozilla.org/consoleservice;1", &rv);
2635 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2636 return rv;
2637 }
2638
2639 nsAutoCString message(nsPrintfCString(
2640 "Warning: attempting to write %d bytes to preference %s. This is bad "
2641 "for general performance and memory usage. Such an amount of data "
2642 "should rather be written to an external file.",
2643 aLength, GetPrefName(aPrefName).get()));
2644
2645 rv = console->LogStringMessage(NS_ConvertUTF8toUTF16(message).get());
2646 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2647 return rv;
2648 }
2649 return NS_OK;
2650}
2651
2652NS_IMETHODIMPnsresult
2653nsPrefBranch::SetComplexValue(const char* aPrefName, const nsIID& aType,
2654 nsISupports* aValue) {
2655 ENSURE_PARENT_PROCESS("SetComplexValue", aPrefName);
2656 NS_ENSURE_ARG(aPrefName)do { if ((__builtin_expect(!!(!(aPrefName)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aPrefName" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2656); return NS_ERROR_INVALID_ARG; } } while (false)
;
2657
2658 nsresult rv = NS_NOINTERFACE;
2659
2660 if (aType.Equals(NS_GET_IID(nsIFile)(nsIFile::COMTypeInfo<nsIFile, void>::kIID))) {
2661 nsCOMPtr<nsIFile> file = do_QueryInterface(aValue);
2662 if (!file) {
2663 return NS_NOINTERFACE;
2664 }
2665
2666 nsAutoCString descriptorString;
2667 rv = file->GetPersistentDescriptor(descriptorString);
2668 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2669 rv = SetCharPrefNoLengthCheck(aPrefName, descriptorString);
2670 }
2671 return rv;
2672 }
2673
2674 if (aType.Equals(NS_GET_IID(nsIRelativeFilePref)(nsIRelativeFilePref::COMTypeInfo<nsIRelativeFilePref, void
>::kIID)
)) {
2675 nsCOMPtr<nsIRelativeFilePref> relFilePref = do_QueryInterface(aValue);
2676 if (!relFilePref) {
2677 return NS_NOINTERFACE;
2678 }
2679
2680 nsCOMPtr<nsIFile> file;
2681 relFilePref->GetFile(getter_AddRefs(file));
2682 if (!file) {
2683 return NS_NOINTERFACE;
2684 }
2685
2686 nsAutoCString relativeToKey;
2687 (void)relFilePref->GetRelativeToKey(relativeToKey);
2688
2689 nsCOMPtr<nsIFile> relativeToFile;
2690 nsCOMPtr<nsIProperties> directoryService(
2691 do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID"@mozilla.org/file/directory_service;1", &rv));
2692 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2693 return rv;
2694 }
2695
2696 rv = directoryService->Get(relativeToKey.get(), NS_GET_IID(nsIFile)(nsIFile::COMTypeInfo<nsIFile, void>::kIID),
2697 getter_AddRefs(relativeToFile));
2698 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2699 return rv;
2700 }
2701
2702 nsAutoCString relDescriptor;
2703 rv = file->GetRelativeDescriptor(relativeToFile, relDescriptor);
2704 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2705 return rv;
2706 }
2707
2708 nsAutoCString descriptorString;
2709 descriptorString.Append('[');
2710 descriptorString.Append(relativeToKey);
2711 descriptorString.Append(']');
2712 descriptorString.Append(relDescriptor);
2713 return SetCharPrefNoLengthCheck(aPrefName, descriptorString);
2714 }
2715
2716 if (aType.Equals(NS_GET_IID(nsIPrefLocalizedString)(nsIPrefLocalizedString::COMTypeInfo<nsIPrefLocalizedString
, void>::kIID)
)) {
2717 nsCOMPtr<nsISupportsString> theString = do_QueryInterface(aValue);
2718
2719 if (theString) {
2720 nsString wideString;
2721
2722 rv = theString->GetData(wideString);
2723 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2724 // Check sanity of string length before any lengthy conversion
2725 rv = CheckSanityOfStringLength(aPrefName, wideString);
2726 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2727 return rv;
2728 }
2729 rv = SetCharPrefNoLengthCheck(aPrefName,
2730 NS_ConvertUTF16toUTF8(wideString));
2731 }
2732 }
2733 return rv;
2734 }
2735
2736 NS_WARNING("nsPrefBranch::SetComplexValue - Unsupported interface type")NS_DebugBreak(NS_DEBUG_WARNING, "nsPrefBranch::SetComplexValue - Unsupported interface type"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2736)
;
2737 return NS_NOINTERFACE;
2738}
2739
2740NS_IMETHODIMPnsresult
2741nsPrefBranch::ClearUserPref(const char* aPrefName) {
2742 NS_ENSURE_ARG(aPrefName)do { if ((__builtin_expect(!!(!(aPrefName)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aPrefName" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2742); return NS_ERROR_INVALID_ARG; } } while (false)
;
2743
2744 const PrefName& pref = GetPrefName(aPrefName);
2745 return Preferences::ClearUser(pref.get());
2746}
2747
2748NS_IMETHODIMPnsresult
2749nsPrefBranch::PrefHasUserValue(const char* aPrefName, bool* aRetVal) {
2750 NS_ENSURE_ARG_POINTER(aRetVal)do { if ((__builtin_expect(!!(!(aRetVal)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aRetVal" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2750); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2751 NS_ENSURE_ARG(aPrefName)do { if ((__builtin_expect(!!(!(aPrefName)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aPrefName" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2751); return NS_ERROR_INVALID_ARG; } } while (false)
;
2752
2753 const PrefName& pref = GetPrefName(aPrefName);
2754 *aRetVal = Preferences::HasUserValue(pref.get());
2755 return NS_OK;
2756}
2757
2758NS_IMETHODIMPnsresult
2759nsPrefBranch::PrefHasDefaultValue(const char* aPrefName, bool* aRetVal) {
2760 NS_ENSURE_ARG_POINTER(aRetVal)do { if ((__builtin_expect(!!(!(aRetVal)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aRetVal" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2760); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2761 NS_ENSURE_ARG(aPrefName)do { if ((__builtin_expect(!!(!(aPrefName)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aPrefName" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2761); return NS_ERROR_INVALID_ARG; } } while (false)
;
2762
2763 const PrefName& pref = GetPrefName(aPrefName);
2764 *aRetVal = Preferences::HasDefaultValue(pref.get());
2765 return NS_OK;
2766}
2767
2768NS_IMETHODIMPnsresult
2769nsPrefBranch::LockPref(const char* aPrefName) {
2770 NS_ENSURE_ARG(aPrefName)do { if ((__builtin_expect(!!(!(aPrefName)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aPrefName" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2770); return NS_ERROR_INVALID_ARG; } } while (false)
;
2771
2772 const PrefName& pref = GetPrefName(aPrefName);
2773 return Preferences::Lock(pref.get());
2774}
2775
2776NS_IMETHODIMPnsresult
2777nsPrefBranch::PrefIsLocked(const char* aPrefName, bool* aRetVal) {
2778 NS_ENSURE_ARG_POINTER(aRetVal)do { if ((__builtin_expect(!!(!(aRetVal)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aRetVal" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2778); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2779 NS_ENSURE_ARG(aPrefName)do { if ((__builtin_expect(!!(!(aPrefName)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aPrefName" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2779); return NS_ERROR_INVALID_ARG; } } while (false)
;
2780
2781 const PrefName& pref = GetPrefName(aPrefName);
2782 *aRetVal = Preferences::IsLocked(pref.get());
2783 return NS_OK;
2784}
2785
2786NS_IMETHODIMPnsresult
2787nsPrefBranch::PrefIsSanitized(const char* aPrefName, bool* aRetVal) {
2788 NS_ENSURE_ARG_POINTER(aRetVal)do { if ((__builtin_expect(!!(!(aRetVal)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aRetVal" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2788); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2789 NS_ENSURE_ARG(aPrefName)do { if ((__builtin_expect(!!(!(aPrefName)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aPrefName" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2789); return NS_ERROR_INVALID_ARG; } } while (false)
;
2790
2791 const PrefName& pref = GetPrefName(aPrefName);
2792 *aRetVal = Preferences::IsSanitized(pref.get());
2793 return NS_OK;
2794}
2795
2796NS_IMETHODIMPnsresult
2797nsPrefBranch::UnlockPref(const char* aPrefName) {
2798 NS_ENSURE_ARG(aPrefName)do { if ((__builtin_expect(!!(!(aPrefName)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aPrefName" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2798); return NS_ERROR_INVALID_ARG; } } while (false)
;
2799
2800 const PrefName& pref = GetPrefName(aPrefName);
2801 return Preferences::Unlock(pref.get());
2802}
2803
2804NS_IMETHODIMPnsresult
2805nsPrefBranch::DeleteBranch(const char* aStartingAt) {
2806 ENSURE_PARENT_PROCESS("DeleteBranch", aStartingAt);
2807 NS_ENSURE_ARG(aStartingAt)do { if ((__builtin_expect(!!(!(aStartingAt)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aStartingAt" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2807); return NS_ERROR_INVALID_ARG; } } while (false)
;
2808
2809 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2809); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2809; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2810
2811 if (!HashTable()) {
2812 return NS_ERROR_NOT_INITIALIZED;
2813 }
2814
2815 const PrefName& pref = GetPrefName(aStartingAt);
2816 nsAutoCString branchName(pref.get());
2817
2818 // Add a trailing '.' if it doesn't already have one.
2819 if (branchName.Length() > 1 && !StringEndsWith(branchName, "."_ns)) {
2820 branchName += '.';
2821 }
2822
2823 const nsACString& branchNameNoDot =
2824 Substring(branchName, 0, branchName.Length() - 1);
2825
2826 for (auto iter = HashTable()->modIter(); !iter.done(); iter.next()) {
2827 // The first disjunct matches branches: e.g. a branch name "foo.bar."
2828 // matches a name "foo.bar.baz" (but it won't match "foo.barrel.baz").
2829 // The second disjunct matches leaf nodes: e.g. a branch name "foo.bar."
2830 // matches a name "foo.bar" (by ignoring the trailing '.').
2831 nsDependentCString name(iter.get()->Name());
2832 if (StringBeginsWith(name, branchName) || name.Equals(branchNameNoDot)) {
2833 iter.remove();
2834 // The saved callback pref may be invalid now.
2835 gCallbackPref = nullptr;
2836 }
2837 }
2838
2839 Preferences::HandleDirty();
2840 return NS_OK;
2841}
2842
2843NS_IMETHODIMPnsresult
2844nsPrefBranch::GetChildList(const char* aStartingAt,
2845 nsTArray<nsCString>& aChildArray) {
2846 NS_ENSURE_ARG(aStartingAt)do { if ((__builtin_expect(!!(!(aStartingAt)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aStartingAt" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2846); return NS_ERROR_INVALID_ARG; } } while (false)
;
2847
2848 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2848); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2848; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2849
2850 // This will contain a list of all the pref name strings. Allocated on the
2851 // stack for speed.
2852 AutoTArray<nsCString, 32> prefArray;
2853
2854 const PrefName& parent = GetPrefName(aStartingAt);
2855 size_t parentLen = parent.Length();
2856 for (auto& pref : PrefsIter(HashTable(), gSharedMap)) {
2857 if (strncmp(pref->Name(), parent.get(), parentLen) == 0) {
2858 prefArray.AppendElement(pref->NameString());
2859 }
2860 }
2861
2862 // Now that we've built up the list, run the callback on all the matching
2863 // elements.
2864 aChildArray.SetCapacity(prefArray.Length());
2865 for (auto& element : prefArray) {
2866 // we need to lop off mPrefRoot in case the user is planning to pass this
2867 // back to us because if they do we are going to add mPrefRoot again.
2868 aChildArray.AppendElement(Substring(element, mPrefRoot.Length()));
2869 }
2870
2871 return NS_OK;
2872}
2873
2874NS_IMETHODIMPnsresult
2875nsPrefBranch::AddObserverImpl(const nsACString& aDomain, nsIObserver* aObserver,
2876 bool aHoldWeak) {
2877 UniquePtr<PrefCallback> pCallback;
2878
2879 NS_ENSURE_ARG(aObserver)do { if ((__builtin_expect(!!(!(aObserver)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aObserver" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2879); return NS_ERROR_INVALID_ARG; } } while (false)
;
2880
2881 const nsCString& prefName = GetPrefName(aDomain);
2882
2883 // Hold a weak reference to the observer if so requested.
2884 if (aHoldWeak) {
2885 nsCOMPtr<nsISupportsWeakReference> weakRefFactory =
2886 do_QueryInterface(aObserver);
2887 if (!weakRefFactory) {
2888 // The caller didn't give us a object that supports weak reference...
2889 // tell them.
2890 return NS_ERROR_INVALID_ARG;
2891 }
2892
2893 // Construct a PrefCallback with a weak reference to the observer.
2894 pCallback = MakeUnique<PrefCallback>(prefName, weakRefFactory, this);
2895
2896 } else {
2897 // Construct a PrefCallback with a strong reference to the observer.
2898 pCallback = MakeUnique<PrefCallback>(prefName, aObserver, this);
2899 }
2900
2901 mObservers.WithEntryHandle(pCallback.get(), [&](auto&& p) {
2902 if (p) {
2903 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString("Ignoring duplicate observer: %s"
, prefName.get()) .get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2905)
2904 nsPrintfCString("Ignoring duplicate observer: %s", prefName.get())NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString("Ignoring duplicate observer: %s"
, prefName.get()) .get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2905)
2905 .get())NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString("Ignoring duplicate observer: %s"
, prefName.get()) .get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2905)
;
2906 } else {
2907 // We must pass a fully qualified preference name to the callback
2908 // aDomain == nullptr is the only possible failure, and we trapped it with
2909 // NS_ENSURE_ARG above.
2910 Preferences::RegisterCallback(NotifyObserver, prefName, pCallback.get(),
2911 Preferences::PrefixMatch,
2912 /* isPriority */ false);
2913
2914 p.Insert(std::move(pCallback));
2915 }
2916 });
2917
2918 return NS_OK;
2919}
2920
2921NS_IMETHODIMPnsresult
2922nsPrefBranch::RemoveObserverImpl(const nsACString& aDomain,
2923 nsIObserver* aObserver) {
2924 NS_ENSURE_ARG(aObserver)do { if ((__builtin_expect(!!(!(aObserver)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aObserver" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 2924); return NS_ERROR_INVALID_ARG; } } while (false)
;
2925
2926 nsresult rv = NS_OK;
2927
2928 // If we're in the middle of a call to FreeObserverList, don't process this
2929 // RemoveObserver call -- the observer in question will be removed soon, if
2930 // it hasn't been already.
2931 //
2932 // It's important that we don't touch mObservers in any way -- even a Get()
2933 // which returns null might cause the hashtable to resize itself, which will
2934 // break the iteration in FreeObserverList.
2935 if (mFreeingObserverList) {
2936 return NS_OK;
2937 }
2938
2939 // Remove the relevant PrefCallback from mObservers and get an owning pointer
2940 // to it. Unregister the callback first, and then let the owning pointer go
2941 // out of scope and destroy the callback.
2942 const nsCString& prefName = GetPrefName(aDomain);
2943 PrefCallback key(prefName, aObserver, this);
2944 mozilla::UniquePtr<PrefCallback> pCallback;
2945 mObservers.Remove(&key, &pCallback);
2946 if (pCallback) {
2947 rv = Preferences::UnregisterCallback(
2948 NotifyObserver, prefName, pCallback.get(), Preferences::PrefixMatch);
2949 }
2950
2951 return rv;
2952}
2953
2954NS_IMETHODIMPnsresult
2955nsPrefBranch::Observe(nsISupports* aSubject, const char* aTopic,
2956 const char16_t* aData) {
2957 // Watch for xpcom shutdown and free our observers to eliminate any cyclic
2958 // references.
2959 if (!nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown")) {
2960 FreeObserverList();
2961 }
2962 return NS_OK;
2963}
2964
2965/* static */
2966void nsPrefBranch::NotifyObserver(const char* aNewPref, void* aData) {
2967 PrefCallback* pCallback = (PrefCallback*)aData;
2968
2969 nsCOMPtr<nsIObserver> observer = pCallback->GetObserver();
2970 if (!observer) {
2971 // The observer has expired. Let's remove this callback.
2972 pCallback->GetPrefBranch()->RemoveExpiredCallback(pCallback);
2973 return;
2974 }
2975
2976 // Remove any root this string may contain so as to not confuse the observer
2977 // by passing them something other than what they passed us as a topic.
2978 uint32_t len = pCallback->GetPrefBranch()->GetRootLength();
2979 nsDependentCString suffix(aNewPref + len);
2980
2981 observer->Observe(static_cast<nsIPrefBranch*>(pCallback->GetPrefBranch()),
2982 NS_PREFBRANCH_PREFCHANGE_TOPIC_ID"nsPref:changed",
2983 NS_ConvertASCIItoUTF16(suffix).get());
2984}
2985
2986size_t nsPrefBranch::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
2987 size_t n = aMallocSizeOf(this);
2988
2989 n += mPrefRoot.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
2990
2991 n += mObservers.ShallowSizeOfExcludingThis(aMallocSizeOf);
2992 for (const auto& entry : mObservers) {
2993 const PrefCallback* data = entry.GetWeak();
2994 n += data->SizeOfIncludingThis(aMallocSizeOf);
2995 }
2996
2997 return n;
2998}
2999
3000void nsPrefBranch::FreeObserverList() {
3001 // We need to prevent anyone from modifying mObservers while we're iterating
3002 // over it. In particular, some clients will call RemoveObserver() when
3003 // they're removed and destructed via the iterator; we set
3004 // mFreeingObserverList to keep those calls from touching mObservers.
3005 mFreeingObserverList = true;
3006 for (auto iter = mObservers.Iter(); !iter.Done(); iter.Next()) {
3007 auto callback = iter.UserData();
3008 Preferences::UnregisterCallback(nsPrefBranch::NotifyObserver,
3009 callback->GetDomain(), callback,
3010 Preferences::PrefixMatch);
3011 iter.Remove();
3012 }
3013
3014 nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
3015 if (observerService) {
3016 observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown");
3017 }
3018
3019 mFreeingObserverList = false;
3020}
3021
3022void nsPrefBranch::RemoveExpiredCallback(PrefCallback* aCallback) {
3023 MOZ_ASSERT(aCallback->IsExpired())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aCallback->IsExpired())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aCallback->IsExpired())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("aCallback->IsExpired()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3023); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aCallback->IsExpired()"
")"); do { *((volatile int*)__null) = 3023; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3024 mObservers.Remove(aCallback);
3025}
3026
3027nsresult nsPrefBranch::GetDefaultFromPropertiesFile(const char* aPrefName,
3028 nsAString& aReturn) {
3029 // The default value contains a URL to a .properties file.
3030
3031 nsAutoCString propertyFileURL;
3032 nsresult rv = Preferences::GetCString(aPrefName, propertyFileURL,
3033 PrefValueKind::Default);
3034 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3035 return rv;
3036 }
3037
3038 nsCOMPtr<nsIStringBundleService> bundleService =
3039 components::StringBundle::Service();
3040 if (!bundleService) {
3041 return NS_ERROR_FAILURE;
3042 }
3043
3044 nsCOMPtr<nsIStringBundle> bundle;
3045 rv = bundleService->CreateBundle(propertyFileURL.get(),
3046 getter_AddRefs(bundle));
3047 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3048 return rv;
3049 }
3050
3051 return bundle->GetStringFromName(aPrefName, aReturn);
3052}
3053
3054nsPrefBranch::PrefName nsPrefBranch::GetPrefName(
3055 const nsACString& aPrefName) const {
3056 if (mPrefRoot.IsEmpty()) {
3057 return PrefName(PromiseFlatCStringTPromiseFlatString<char>(aPrefName));
3058 }
3059
3060 return PrefName(mPrefRoot + aPrefName);
3061}
3062
3063//----------------------------------------------------------------------------
3064// nsPrefLocalizedString
3065//----------------------------------------------------------------------------
3066
3067nsPrefLocalizedString::nsPrefLocalizedString() = default;
3068
3069nsPrefLocalizedString::~nsPrefLocalizedString() = default;
3070
3071NS_IMPL_ISUPPORTS(nsPrefLocalizedString, nsIPrefLocalizedString,MozExternalRefCountType nsPrefLocalizedString::AddRef(void) {
static_assert(!std::is_destructible_v<nsPrefLocalizedString
>, "Reference-counted class " "nsPrefLocalizedString" " should not have a public destructor. "
"Make this class's destructor non-public"); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
3072; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsPrefLocalizedString" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("nsPrefLocalizedString" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"nsPrefLocalizedString\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsPrefLocalizedString\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 3072; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsPrefLocalizedString" " not thread-safe");
nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), ("nsPrefLocalizedString"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
nsPrefLocalizedString::Release(void) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(int32_t(mRefCnt)
> 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 3072
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsPrefLocalizedString" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("nsPrefLocalizedString" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"nsPrefLocalizedString\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsPrefLocalizedString\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 3072; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsPrefLocalizedString" " not thread-safe");
const char* const nametmp = "nsPrefLocalizedString"; nsrefcnt
count = --mRefCnt; NS_LogRelease((this), (count), (nametmp))
; if (count == 0) { mRefCnt = 1; delete (this); return 0; } return
count; } nsresult nsPrefLocalizedString::QueryInterface(const
nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3072); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(2 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsPrefLocalizedString, nsIPrefLocalizedString
>, int32_t( reinterpret_cast<char*>(static_cast<nsIPrefLocalizedString
*>((nsPrefLocalizedString*)0x1000)) - reinterpret_cast<
char*>((nsPrefLocalizedString*)0x1000))}, {&mozilla::detail
::kImplementedIID<nsPrefLocalizedString, nsISupportsString
>, int32_t( reinterpret_cast<char*>(static_cast<nsISupportsString
*>((nsPrefLocalizedString*)0x1000)) - reinterpret_cast<
char*>((nsPrefLocalizedString*)0x1000))}, {&mozilla::detail
::kImplementedIID<nsPrefLocalizedString, nsISupports>, int32_t
(reinterpret_cast<char*>(static_cast<nsISupports*>
( static_cast<nsIPrefLocalizedString*>((nsPrefLocalizedString
*)0x1000))) - reinterpret_cast<char*>((nsPrefLocalizedString
*)0x1000))}, { nullptr, 0 } } ; static_assert((sizeof(table) /
sizeof(table[0])) > 1, "need at least 1 interface"); rv =
NS_TableDrivenQI(static_cast<void*>(this), aIID, aInstancePtr
, table); return rv; }
3072 nsISupportsString)MozExternalRefCountType nsPrefLocalizedString::AddRef(void) {
static_assert(!std::is_destructible_v<nsPrefLocalizedString
>, "Reference-counted class " "nsPrefLocalizedString" " should not have a public destructor. "
"Make this class's destructor non-public"); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
3072; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsPrefLocalizedString" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("nsPrefLocalizedString" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"nsPrefLocalizedString\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsPrefLocalizedString\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 3072; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsPrefLocalizedString" " not thread-safe");
nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), ("nsPrefLocalizedString"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
nsPrefLocalizedString::Release(void) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(int32_t(mRefCnt)
> 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 3072
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsPrefLocalizedString" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("nsPrefLocalizedString" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"nsPrefLocalizedString\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsPrefLocalizedString\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 3072; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsPrefLocalizedString" " not thread-safe");
const char* const nametmp = "nsPrefLocalizedString"; nsrefcnt
count = --mRefCnt; NS_LogRelease((this), (count), (nametmp))
; if (count == 0) { mRefCnt = 1; delete (this); return 0; } return
count; } nsresult nsPrefLocalizedString::QueryInterface(const
nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3072); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(2 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsPrefLocalizedString, nsIPrefLocalizedString
>, int32_t( reinterpret_cast<char*>(static_cast<nsIPrefLocalizedString
*>((nsPrefLocalizedString*)0x1000)) - reinterpret_cast<
char*>((nsPrefLocalizedString*)0x1000))}, {&mozilla::detail
::kImplementedIID<nsPrefLocalizedString, nsISupportsString
>, int32_t( reinterpret_cast<char*>(static_cast<nsISupportsString
*>((nsPrefLocalizedString*)0x1000)) - reinterpret_cast<
char*>((nsPrefLocalizedString*)0x1000))}, {&mozilla::detail
::kImplementedIID<nsPrefLocalizedString, nsISupports>, int32_t
(reinterpret_cast<char*>(static_cast<nsISupports*>
( static_cast<nsIPrefLocalizedString*>((nsPrefLocalizedString
*)0x1000))) - reinterpret_cast<char*>((nsPrefLocalizedString
*)0x1000))}, { nullptr, 0 } } ; static_assert((sizeof(table) /
sizeof(table[0])) > 1, "need at least 1 interface"); rv =
NS_TableDrivenQI(static_cast<void*>(this), aIID, aInstancePtr
, table); return rv; }
3073
3074nsresult nsPrefLocalizedString::Init() {
3075 nsresult rv;
3076 mUnicodeString = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID"@mozilla.org/supports-string;1", &rv);
3077
3078 return rv;
3079}
3080
3081//----------------------------------------------------------------------------
3082// nsRelativeFilePref
3083//----------------------------------------------------------------------------
3084
3085NS_IMPL_ISUPPORTS(nsRelativeFilePref, nsIRelativeFilePref)MozExternalRefCountType nsRelativeFilePref::AddRef(void) { static_assert
(!std::is_destructible_v<nsRelativeFilePref>, "Reference-counted class "
"nsRelativeFilePref" " should not have a public destructor. "
"Make this class's destructor non-public"); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3085); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
3085; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsRelativeFilePref" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsRelativeFilePref" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"nsRelativeFilePref\" != nullptr" " (" "Must specify a name"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3085); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsRelativeFilePref\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 3085; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsRelativeFilePref" " not thread-safe"); nsrefcnt
count = ++mRefCnt; NS_LogAddRef((this), (count), ("nsRelativeFilePref"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
nsRelativeFilePref::Release(void) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(int32_t(mRefCnt)
> 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3085); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 3085
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsRelativeFilePref" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsRelativeFilePref" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"nsRelativeFilePref\" != nullptr" " (" "Must specify a name"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3085); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsRelativeFilePref\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 3085; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsRelativeFilePref" " not thread-safe"); const
char* const nametmp = "nsRelativeFilePref"; nsrefcnt count =
--mRefCnt; NS_LogRelease((this), (count), (nametmp)); if (count
== 0) { mRefCnt = 1; delete (this); return 0; } return count
; } nsresult nsRelativeFilePref::QueryInterface(const nsIID&
aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3085); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsRelativeFilePref, nsIRelativeFilePref>
, int32_t( reinterpret_cast<char*>(static_cast<nsIRelativeFilePref
*>((nsRelativeFilePref*)0x1000)) - reinterpret_cast<char
*>((nsRelativeFilePref*)0x1000))}, {&mozilla::detail::
kImplementedIID<nsRelativeFilePref, nsISupports>, int32_t
(reinterpret_cast<char*>(static_cast<nsISupports*>
( static_cast<nsIRelativeFilePref*>((nsRelativeFilePref
*)0x1000))) - reinterpret_cast<char*>((nsRelativeFilePref
*)0x1000))}, { nullptr, 0 } } ; static_assert((sizeof(table) /
sizeof(table[0])) > 1, "need at least 1 interface"); rv =
NS_TableDrivenQI(static_cast<void*>(this), aIID, aInstancePtr
, table); return rv; }
3086
3087nsRelativeFilePref::nsRelativeFilePref() = default;
3088
3089nsRelativeFilePref::~nsRelativeFilePref() = default;
3090
3091NS_IMETHODIMPnsresult
3092nsRelativeFilePref::GetFile(nsIFile** aFile) {
3093 NS_ENSURE_ARG_POINTER(aFile)do { if ((__builtin_expect(!!(!(aFile)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aFile" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3093); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3094 *aFile = mFile;
3095 NS_IF_ADDREF(*aFile)ns_if_addref(*aFile);
3096 return NS_OK;
3097}
3098
3099NS_IMETHODIMPnsresult
3100nsRelativeFilePref::SetFile(nsIFile* aFile) {
3101 mFile = aFile;
3102 return NS_OK;
3103}
3104
3105NS_IMETHODIMPnsresult
3106nsRelativeFilePref::GetRelativeToKey(nsACString& aRelativeToKey) {
3107 aRelativeToKey.Assign(mRelativeToKey);
3108 return NS_OK;
3109}
3110
3111NS_IMETHODIMPnsresult
3112nsRelativeFilePref::SetRelativeToKey(const nsACString& aRelativeToKey) {
3113 mRelativeToKey.Assign(aRelativeToKey);
3114 return NS_OK;
3115}
3116
3117//===========================================================================
3118// class Preferences and related things
3119//===========================================================================
3120
3121namespace mozilla {
3122
3123#define INITIAL_PREF_FILES10 10
3124
3125void Preferences::HandleDirty() {
3126 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3126); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 3126; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3127
3128 if (!HashTable() || !sPreferences) {
3129 return;
3130 }
3131
3132 if (sPreferences->mProfileShutdown) {
3133 NS_WARNING("Setting user pref after profile shutdown.")NS_DebugBreak(NS_DEBUG_WARNING, "Setting user pref after profile shutdown."
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3133)
;
3134 return;
3135 }
3136
3137 if (!sPreferences->mDirty) {
3138 sPreferences->mDirty = true;
3139
3140 if (sPreferences->mCurrentFile && sPreferences->AllowOffMainThreadSave() &&
3141 !sPreferences->mSavePending) {
3142 sPreferences->mSavePending = true;
3143 static const int PREF_DELAY_MS = 500;
3144 NS_DelayedDispatchToCurrentThread(
3145 NewRunnableMethod("Preferences::SavePrefFileAsynchronous",
3146 sPreferences.get(),
3147 &Preferences::SavePrefFileAsynchronous),
3148 PREF_DELAY_MS);
3149 }
3150 }
3151}
3152
3153static nsresult openPrefFile(nsIFile* aFile, PrefValueKind aKind);
3154
3155static nsresult parsePrefData(const nsCString& aData, PrefValueKind aKind);
3156
3157// clang-format off
3158static const char kPrefFileHeader[] =
3159 "// Mozilla User Preferences"
3160 NS_LINEBREAK"\012"
3161 NS_LINEBREAK"\012"
3162 "// DO NOT EDIT THIS FILE."
3163 NS_LINEBREAK"\012"
3164 "//"
3165 NS_LINEBREAK"\012"
3166 "// If you make changes to this file while the application is running,"
3167 NS_LINEBREAK"\012"
3168 "// the changes will be overwritten when the application exits."
3169 NS_LINEBREAK"\012"
3170 "//"
3171 NS_LINEBREAK"\012"
3172 "// To change a preference value, you can either:"
3173 NS_LINEBREAK"\012"
3174 "// - modify it via the UI (e.g. via about:config in the browser); or"
3175 NS_LINEBREAK"\012"
3176 "// - set it within a user.js file in your profile."
3177 NS_LINEBREAK"\012"
3178 NS_LINEBREAK"\012";
3179// clang-format on
3180
3181// Note: if sShutdown is true, sPreferences will be nullptr.
3182StaticRefPtr<Preferences> Preferences::sPreferences;
3183bool Preferences::sShutdown = false;
3184
3185// This globally enables or disables OMT pref writing, both sync and async.
3186static int32_t sAllowOMTPrefWrite = -1;
3187
3188// Write the preference data to a file.
3189class PreferencesWriter final {
3190 public:
3191 PreferencesWriter() = default;
3192
3193 static nsresult Write(nsIFile* aFile, PrefSaveData& aPrefs) {
3194 nsCOMPtr<nsIOutputStream> outStreamSink;
3195 nsCOMPtr<nsIOutputStream> outStream;
3196 uint32_t writeAmount;
3197 nsresult rv;
3198
3199 // Execute a "safe" save by saving through a tempfile.
3200 rv = NS_NewSafeLocalFileOutputStream(getter_AddRefs(outStreamSink), aFile,
3201 -1, 0600);
3202 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3203 return rv;
3204 }
3205
3206 rv = NS_NewBufferedOutputStream(getter_AddRefs(outStream),
3207 outStreamSink.forget(), 4096);
3208 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3209 return rv;
3210 }
3211
3212 struct CharComparator {
3213 bool LessThan(const nsCString& aA, const nsCString& aB) const {
3214 return aA < aB;
3215 }
3216
3217 bool Equals(const nsCString& aA, const nsCString& aB) const {
3218 return aA == aB;
3219 }
3220 };
3221
3222 // Sort the preferences to make a readable file on disk.
3223 aPrefs.Sort(CharComparator());
3224
3225 // Write out the file header.
3226 outStream->Write(kPrefFileHeader, sizeof(kPrefFileHeader) - 1,
3227 &writeAmount);
3228
3229 for (nsCString& pref : aPrefs) {
3230 outStream->Write(pref.get(), pref.Length(), &writeAmount);
3231 outStream->Write(NS_LINEBREAK"\012", NS_LINEBREAK_LEN1, &writeAmount);
3232 }
3233
3234 // Tell the safe output stream to overwrite the real prefs file.
3235 // (It'll abort if there were any errors during writing.)
3236 nsCOMPtr<nsISafeOutputStream> safeStream = do_QueryInterface(outStream);
3237 MOZ_ASSERT(safeStream, "expected a safe output stream!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(safeStream)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(safeStream))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("safeStream" " (" "expected a safe output stream!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3237); AnnotateMozCrashReason("MOZ_ASSERT" "(" "safeStream"
") (" "expected a safe output stream!" ")"); do { *((volatile
int*)__null) = 3237; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
3238 if (safeStream) {
3239 rv = safeStream->Finish();
3240 }
3241
3242#ifdef DEBUG1
3243 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3244 NS_WARNING("failed to save prefs file! possible data loss")NS_DebugBreak(NS_DEBUG_WARNING, "failed to save prefs file! possible data loss"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3244)
;
3245 }
3246#endif
3247
3248 return rv;
3249 }
3250
3251 static void Flush() {
3252 MOZ_DIAGNOSTIC_ASSERT(sPendingWriteCount >= 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sPendingWriteCount >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sPendingWriteCount >= 0))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sPendingWriteCount >= 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3252); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "sPendingWriteCount >= 0"
")"); do { *((volatile int*)__null) = 3252; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3253 // SpinEventLoopUntil is unfortunate, but ultimately it's the best thing
3254 // we can do here given the constraint that we need to ensure that
3255 // the preferences on disk match what we have in memory. We could
3256 // easily perform the write here ourselves by doing exactly what
3257 // happens in PWRunnable::Run. This would be the right thing to do
3258 // if we're stuck here because other unrelated runnables are taking
3259 // a long time, and the wrong thing to do if PreferencesWriter::Write
3260 // is what takes a long time, as we would be trading a SpinEventLoopUntil
3261 // for a synchronous disk write, wherein we could not even spin the
3262 // event loop. Given that PWRunnable generally runs on a thread pool,
3263 // if we're stuck here, it's likely because of PreferencesWriter::Write
3264 // and not some other runnable. Thus, spin away.
3265 mozilla::SpinEventLoopUntil("PreferencesWriter::Flush"_ns,
3266 []() { return sPendingWriteCount <= 0; });
3267 }
3268
3269 // This is the data that all of the runnables (see below) will attempt
3270 // to write. It will always have the most up to date version, or be
3271 // null, if the up to date information has already been written out.
3272 static Atomic<PrefSaveData*> sPendingWriteData;
3273
3274 // This is the number of writes via PWRunnables which have been dispatched
3275 // but not yet completed. This is intended to be used by Flush to ensure
3276 // that there are no outstanding writes left incomplete, and thus our prefs
3277 // on disk are in sync with what we have in memory.
3278 static Atomic<int> sPendingWriteCount;
3279
3280 // See PWRunnable::Run for details on why we need this lock.
3281 static StaticMutex sWritingToFile MOZ_UNANNOTATED;
3282};
3283
3284Atomic<PrefSaveData*> PreferencesWriter::sPendingWriteData(nullptr);
3285Atomic<int> PreferencesWriter::sPendingWriteCount(0);
3286StaticMutex PreferencesWriter::sWritingToFile;
3287
3288class PWRunnable : public Runnable {
3289 public:
3290 explicit PWRunnable(
3291 nsIFile* aFile,
3292 UniquePtr<MozPromiseHolder<Preferences::WritePrefFilePromise>>
3293 aPromiseHolder)
3294 : Runnable("PWRunnable"),
3295 mFile(aFile),
3296 mPromiseHolder(std::move(aPromiseHolder)) {}
3297
3298 NS_IMETHODvirtual nsresult Run() override {
3299 // Preference writes are handled a bit strangely, in that a "newer"
3300 // write is generally regarded as always better. For this reason,
3301 // sPendingWriteData can be overwritten multiple times before anyone
3302 // gets around to actually using it, minimizing writes. However,
3303 // once we've acquired sPendingWriteData we've reached a
3304 // "point of no return" and have to complete the write.
3305 //
3306 // Unfortunately, this design allows the following behaviour:
3307 //
3308 // 1. write1 is queued up
3309 // 2. thread1 acquires write1
3310 // 3. write2 is queued up
3311 // 4. thread2 acquires write2
3312 // 5. thread1 and thread2 concurrently clobber each other
3313 //
3314 // To avoid this, we use this lock to ensure that only one thread
3315 // at a time is trying to acquire the write, and when it does,
3316 // all other threads are prevented from acquiring writes until it
3317 // completes the write. New writes are still allowed to be queued
3318 // up in this time.
3319 //
3320 // Although it's atomic, the acquire needs to be guarded by the mutex
3321 // to avoid reordering of writes -- we don't want an older write to
3322 // run after a newer one. To avoid this causing too much waiting, we check
3323 // if sPendingWriteData is already null before acquiring the mutex. If it
3324 // is, then there's definitely no work to be done (or someone is in the
3325 // middle of doing it for us).
3326 //
3327 // Note that every time a new write is queued up, a new write task is
3328 // is also queued up, so there will always be a task that can see the newest
3329 // write.
3330 //
3331 // Ideally this lock wouldn't be necessary, and the PreferencesWriter
3332 // would be used more carefully, but it's hard to untangle all that.
3333 nsresult rv = NS_OK;
3334 if (PreferencesWriter::sPendingWriteData) {
3335 StaticMutexAutoLock lock(PreferencesWriter::sWritingToFile);
3336 // If we get a nullptr on the exchange, it means that somebody
3337 // else has already processed the request, and we can just return.
3338 UniquePtr<PrefSaveData> prefs(
3339 PreferencesWriter::sPendingWriteData.exchange(nullptr));
3340 if (prefs) {
3341 rv = PreferencesWriter::Write(mFile, *prefs);
3342 // Make a copy of these so we can have them in runnable lambda.
3343 // nsIFile is only there so that we would never release the
3344 // ref counted pointer off main thread.
3345 nsresult rvCopy = rv;
3346 nsCOMPtr<nsIFile> fileCopy(mFile);
3347 SchedulerGroup::Dispatch(NS_NewRunnableFunction(
3348 "Preferences::WriterRunnable",
3349 [fileCopy, rvCopy, promiseHolder = std::move(mPromiseHolder)] {
3350 MOZ_RELEASE_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3350); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 3350; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3351 if (NS_FAILED(rvCopy)((bool)(__builtin_expect(!!(NS_FAILED_impl(rvCopy)), 0)))) {
3352 Preferences::HandleDirty();
3353 }
3354 if (promiseHolder) {
3355 promiseHolder->ResolveIfExists(true, __func__);
3356 }
3357 }));
3358 }
3359 }
3360 // We've completed the write to the best of our abilities, whether
3361 // we had prefs to write or another runnable got to them first. If
3362 // PreferencesWriter::Write failed, this is still correct as the
3363 // write is no longer outstanding, and the above HandleDirty call
3364 // will just start the cycle again.
3365 PreferencesWriter::sPendingWriteCount--;
3366 return rv;
3367 }
3368
3369 private:
3370 ~PWRunnable() {
3371 if (mPromiseHolder) {
3372 mPromiseHolder->RejectIfExists(NS_ERROR_ABORT, __func__);
3373 }
3374 }
3375
3376 protected:
3377 nsCOMPtr<nsIFile> mFile;
3378 UniquePtr<MozPromiseHolder<Preferences::WritePrefFilePromise>> mPromiseHolder;
3379};
3380
3381// Although this is a member of Preferences, it measures sPreferences and
3382// several other global structures.
3383/* static */
3384void Preferences::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
3385 PrefsSizes& aSizes) {
3386 if (!sPreferences) {
3387 return;
3388 }
3389
3390 aSizes.mMisc += aMallocSizeOf(sPreferences.get());
3391
3392 aSizes.mRootBranches +=
3393 static_cast<nsPrefBranch*>(sPreferences->mRootBranch.get())
3394 ->SizeOfIncludingThis(aMallocSizeOf) +
3395 static_cast<nsPrefBranch*>(sPreferences->mDefaultRootBranch.get())
3396 ->SizeOfIncludingThis(aMallocSizeOf);
3397}
3398
3399class PreferenceServiceReporter final : public nsIMemoryReporter {
3400 ~PreferenceServiceReporter() = default;
3401
3402 public:
3403 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
3404 NS_DECL_NSIMEMORYREPORTERvirtual nsresult CollectReports(nsIHandleReportCallback *callback
, nsISupports *data, bool anonymize) override;
3405
3406 protected:
3407 static const uint32_t kSuspectReferentCount = 1000;
3408};
3409
3410NS_IMPL_ISUPPORTS(PreferenceServiceReporter, nsIMemoryReporter)MozExternalRefCountType PreferenceServiceReporter::AddRef(void
) { static_assert(!std::is_destructible_v<PreferenceServiceReporter
>, "Reference-counted class " "PreferenceServiceReporter" " should not have a public destructor. "
"Make this class's destructor non-public"); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3410); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
3410; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("PreferenceServiceReporter" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("PreferenceServiceReporter" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"PreferenceServiceReporter\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3410); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"PreferenceServiceReporter\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 3410; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("PreferenceServiceReporter" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"PreferenceServiceReporter"), (uint32_t)(sizeof(*this))); return
count; } MozExternalRefCountType PreferenceServiceReporter::
Release(void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3410); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 3410
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("PreferenceServiceReporter" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("PreferenceServiceReporter" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"PreferenceServiceReporter\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3410); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"PreferenceServiceReporter\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 3410; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("PreferenceServiceReporter" " not thread-safe"
); const char* const nametmp = "PreferenceServiceReporter"; nsrefcnt
count = --mRefCnt; NS_LogRelease((this), (count), (nametmp))
; if (count == 0) { mRefCnt = 1; delete (this); return 0; } return
count; } nsresult PreferenceServiceReporter::QueryInterface(
const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3410); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<PreferenceServiceReporter, nsIMemoryReporter
>, int32_t( reinterpret_cast<char*>(static_cast<nsIMemoryReporter
*>((PreferenceServiceReporter*)0x1000)) - reinterpret_cast
<char*>((PreferenceServiceReporter*)0x1000))}, {&mozilla
::detail::kImplementedIID<PreferenceServiceReporter, nsISupports
>, int32_t(reinterpret_cast<char*>(static_cast<nsISupports
*>( static_cast<nsIMemoryReporter*>((PreferenceServiceReporter
*)0x1000))) - reinterpret_cast<char*>((PreferenceServiceReporter
*)0x1000))}, { nullptr, 0 } } ; static_assert((sizeof(table) /
sizeof(table[0])) > 1, "need at least 1 interface"); rv =
NS_TableDrivenQI(static_cast<void*>(this), aIID, aInstancePtr
, table); return rv; }
3411
3412MOZ_DEFINE_MALLOC_SIZE_OF(PreferenceServiceMallocSizeOf)static size_t PreferenceServiceMallocSizeOf(const void* aPtr)
{ mozilla::dmd::Report(aPtr); return moz_malloc_size_of(aPtr
); }
3413
3414NS_IMETHODIMPnsresult
3415PreferenceServiceReporter::CollectReports(
3416 nsIHandleReportCallback* aHandleReport, nsISupports* aData,
3417 bool aAnonymize) {
3418 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3418); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 3418; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3419
3420 MallocSizeOf mallocSizeOf = PreferenceServiceMallocSizeOf;
3421 PrefsSizes sizes;
3422
3423 Preferences::AddSizeOfIncludingThis(mallocSizeOf, sizes);
3424
3425 if (HashTable()) {
3426 sizes.mHashTable += HashTable()->shallowSizeOfIncludingThis(mallocSizeOf);
3427 for (auto iter = HashTable()->iter(); !iter.done(); iter.next()) {
3428 iter.get()->AddSizeOfIncludingThis(mallocSizeOf, sizes);
3429 }
3430 }
3431
3432 sizes.mPrefNameArena += PrefNameArena().SizeOfExcludingThis(mallocSizeOf);
3433
3434 for (CallbackNode* node = gFirstCallback; node; node = node->Next()) {
3435 node->AddSizeOfIncludingThis(mallocSizeOf, sizes);
3436 }
3437
3438 if (gSharedMap) {
3439 sizes.mMisc += mallocSizeOf(gSharedMap);
3440 }
3441
3442#ifdef ACCESS_COUNTS
3443 if (gAccessCounts) {
3444 sizes.mMisc += gAccessCounts->ShallowSizeOfIncludingThis(mallocSizeOf);
3445 }
3446#endif
3447
3448 MOZ_COLLECT_REPORT("explicit/preferences/hash-table", KIND_HEAP, UNITS_BYTES,(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/hash-table"
), KIND_HEAP, UNITS_BYTES, sizes.mHashTable, nsLiteralCString
("Memory used by libpref's hash table."), aData)
3449 sizes.mHashTable, "Memory used by libpref's hash table.")(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/hash-table"
), KIND_HEAP, UNITS_BYTES, sizes.mHashTable, nsLiteralCString
("Memory used by libpref's hash table."), aData)
;
3450
3451 MOZ_COLLECT_REPORT("explicit/preferences/pref-values", KIND_HEAP, UNITS_BYTES,(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/pref-values"
), KIND_HEAP, UNITS_BYTES, sizes.mPrefValues, nsLiteralCString
("Memory used by PrefValues hanging off the hash table."), aData
)
3452 sizes.mPrefValues,(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/pref-values"
), KIND_HEAP, UNITS_BYTES, sizes.mPrefValues, nsLiteralCString
("Memory used by PrefValues hanging off the hash table."), aData
)
3453 "Memory used by PrefValues hanging off the hash table.")(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/pref-values"
), KIND_HEAP, UNITS_BYTES, sizes.mPrefValues, nsLiteralCString
("Memory used by PrefValues hanging off the hash table."), aData
)
;
3454
3455 MOZ_COLLECT_REPORT("explicit/preferences/string-values", KIND_HEAP,(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/string-values"
), KIND_HEAP, UNITS_BYTES, sizes.mStringValues, nsLiteralCString
("Memory used by libpref's string pref values."), aData)
3456 UNITS_BYTES, sizes.mStringValues,(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/string-values"
), KIND_HEAP, UNITS_BYTES, sizes.mStringValues, nsLiteralCString
("Memory used by libpref's string pref values."), aData)
3457 "Memory used by libpref's string pref values.")(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/string-values"
), KIND_HEAP, UNITS_BYTES, sizes.mStringValues, nsLiteralCString
("Memory used by libpref's string pref values."), aData)
;
3458
3459 MOZ_COLLECT_REPORT("explicit/preferences/root-branches", KIND_HEAP,(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/root-branches"
), KIND_HEAP, UNITS_BYTES, sizes.mRootBranches, nsLiteralCString
("Memory used by libpref's root branches."), aData)
3460 UNITS_BYTES, sizes.mRootBranches,(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/root-branches"
), KIND_HEAP, UNITS_BYTES, sizes.mRootBranches, nsLiteralCString
("Memory used by libpref's root branches."), aData)
3461 "Memory used by libpref's root branches.")(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/root-branches"
), KIND_HEAP, UNITS_BYTES, sizes.mRootBranches, nsLiteralCString
("Memory used by libpref's root branches."), aData)
;
3462
3463 MOZ_COLLECT_REPORT("explicit/preferences/pref-name-arena", KIND_HEAP,(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/pref-name-arena"
), KIND_HEAP, UNITS_BYTES, sizes.mPrefNameArena, nsLiteralCString
("Memory used by libpref's arena for pref names."), aData)
3464 UNITS_BYTES, sizes.mPrefNameArena,(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/pref-name-arena"
), KIND_HEAP, UNITS_BYTES, sizes.mPrefNameArena, nsLiteralCString
("Memory used by libpref's arena for pref names."), aData)
3465 "Memory used by libpref's arena for pref names.")(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/pref-name-arena"
), KIND_HEAP, UNITS_BYTES, sizes.mPrefNameArena, nsLiteralCString
("Memory used by libpref's arena for pref names."), aData)
;
3466
3467 MOZ_COLLECT_REPORT("explicit/preferences/callbacks/objects", KIND_HEAP,(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/callbacks/objects"
), KIND_HEAP, UNITS_BYTES, sizes.mCallbacksObjects, nsLiteralCString
("Memory used by pref callback objects."), aData)
3468 UNITS_BYTES, sizes.mCallbacksObjects,(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/callbacks/objects"
), KIND_HEAP, UNITS_BYTES, sizes.mCallbacksObjects, nsLiteralCString
("Memory used by pref callback objects."), aData)
3469 "Memory used by pref callback objects.")(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/callbacks/objects"
), KIND_HEAP, UNITS_BYTES, sizes.mCallbacksObjects, nsLiteralCString
("Memory used by pref callback objects."), aData)
;
3470
3471 MOZ_COLLECT_REPORT("explicit/preferences/callbacks/domains", KIND_HEAP,(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/callbacks/domains"
), KIND_HEAP, UNITS_BYTES, sizes.mCallbacksDomains, nsLiteralCString
("Memory used by pref callback domains (pref names and " "prefixes)."
), aData)
3472 UNITS_BYTES, sizes.mCallbacksDomains,(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/callbacks/domains"
), KIND_HEAP, UNITS_BYTES, sizes.mCallbacksDomains, nsLiteralCString
("Memory used by pref callback domains (pref names and " "prefixes)."
), aData)
3473 "Memory used by pref callback domains (pref names and "(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/callbacks/domains"
), KIND_HEAP, UNITS_BYTES, sizes.mCallbacksDomains, nsLiteralCString
("Memory used by pref callback domains (pref names and " "prefixes)."
), aData)
3474 "prefixes).")(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/callbacks/domains"
), KIND_HEAP, UNITS_BYTES, sizes.mCallbacksDomains, nsLiteralCString
("Memory used by pref callback domains (pref names and " "prefixes)."
), aData)
;
3475
3476 MOZ_COLLECT_REPORT("explicit/preferences/misc", KIND_HEAP, UNITS_BYTES,(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/misc"
), KIND_HEAP, UNITS_BYTES, sizes.mMisc, nsLiteralCString("Miscellaneous memory used by libpref."
), aData)
3477 sizes.mMisc, "Miscellaneous memory used by libpref.")(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/misc"
), KIND_HEAP, UNITS_BYTES, sizes.mMisc, nsLiteralCString("Miscellaneous memory used by libpref."
), aData)
;
3478
3479 if (gSharedMap) {
3480 if (XRE_IsParentProcess()) {
3481 MOZ_COLLECT_REPORT("explicit/preferences/shared-memory-map", KIND_NONHEAP,(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/shared-memory-map"
), KIND_NONHEAP, UNITS_BYTES, gSharedMap->MapSize(), nsLiteralCString
("The shared memory mapping used to share a " "snapshot of preference values across processes."
), aData)
3482 UNITS_BYTES, gSharedMap->MapSize(),(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/shared-memory-map"
), KIND_NONHEAP, UNITS_BYTES, gSharedMap->MapSize(), nsLiteralCString
("The shared memory mapping used to share a " "snapshot of preference values across processes."
), aData)
3483 "The shared memory mapping used to share a "(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/shared-memory-map"
), KIND_NONHEAP, UNITS_BYTES, gSharedMap->MapSize(), nsLiteralCString
("The shared memory mapping used to share a " "snapshot of preference values across processes."
), aData)
3484 "snapshot of preference values across processes.")(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/preferences/shared-memory-map"
), KIND_NONHEAP, UNITS_BYTES, gSharedMap->MapSize(), nsLiteralCString
("The shared memory mapping used to share a " "snapshot of preference values across processes."
), aData)
;
3485 }
3486 }
3487
3488 nsPrefBranch* rootBranch =
3489 static_cast<nsPrefBranch*>(Preferences::GetRootBranch());
3490 if (!rootBranch) {
3491 return NS_OK;
3492 }
3493
3494 size_t numStrong = 0;
3495 size_t numWeakAlive = 0;
3496 size_t numWeakDead = 0;
3497 nsTArray<nsCString> suspectPreferences;
3498 // Count of the number of referents for each preference.
3499 nsTHashMap<nsCStringHashKey, uint32_t> prefCounter;
3500
3501 for (const auto& entry : rootBranch->mObservers) {
3502 auto* callback = entry.GetWeak();
3503
3504 if (callback->IsWeak()) {
3505 nsCOMPtr<nsIObserver> callbackRef = do_QueryReferent(callback->mWeakRef);
3506 if (callbackRef) {
3507 numWeakAlive++;
3508 } else {
3509 numWeakDead++;
3510 }
3511 } else {
3512 numStrong++;
3513 }
3514
3515 const uint32_t currentCount = prefCounter.Get(callback->GetDomain()) + 1;
3516 prefCounter.InsertOrUpdate(callback->GetDomain(), currentCount);
3517
3518 // Keep track of preferences that have a suspiciously large number of
3519 // referents (a symptom of a leak).
3520 if (currentCount == kSuspectReferentCount) {
3521 suspectPreferences.AppendElement(callback->GetDomain());
3522 }
3523 }
3524
3525 for (uint32_t i = 0; i < suspectPreferences.Length(); i++) {
3526 nsCString& suspect = suspectPreferences[i];
3527 const uint32_t totalReferentCount = prefCounter.Get(suspect);
3528
3529 nsPrintfCString suspectPath(
3530 "preference-service-suspect/"
3531 "referent(pref=%s)",
3532 suspect.get());
3533
3534 aHandleReport->Callback(
3535 /* process = */ ""_ns, suspectPath, KIND_OTHER, UNITS_COUNT,
3536 totalReferentCount,
3537 "A preference with a suspiciously large number "
3538 "referents (symptom of a leak)."_ns,
3539 aData);
3540 }
3541
3542 MOZ_COLLECT_REPORT((void)aHandleReport->Callback(""_ns, nsLiteralCString("preference-service/referent/strong"
), KIND_OTHER, UNITS_COUNT, numStrong, nsLiteralCString("The number of strong referents held by the preference service."
), aData)
3543 "preference-service/referent/strong", KIND_OTHER, UNITS_COUNT, numStrong,(void)aHandleReport->Callback(""_ns, nsLiteralCString("preference-service/referent/strong"
), KIND_OTHER, UNITS_COUNT, numStrong, nsLiteralCString("The number of strong referents held by the preference service."
), aData)
3544 "The number of strong referents held by the preference service.")(void)aHandleReport->Callback(""_ns, nsLiteralCString("preference-service/referent/strong"
), KIND_OTHER, UNITS_COUNT, numStrong, nsLiteralCString("The number of strong referents held by the preference service."
), aData)
;
3545
3546 MOZ_COLLECT_REPORT((void)aHandleReport->Callback(""_ns, nsLiteralCString("preference-service/referent/weak/alive"
), KIND_OTHER, UNITS_COUNT, numWeakAlive, nsLiteralCString("The number of weak referents held by the preference service that are "
"still alive."), aData)
3547 "preference-service/referent/weak/alive", KIND_OTHER, UNITS_COUNT,(void)aHandleReport->Callback(""_ns, nsLiteralCString("preference-service/referent/weak/alive"
), KIND_OTHER, UNITS_COUNT, numWeakAlive, nsLiteralCString("The number of weak referents held by the preference service that are "
"still alive."), aData)
3548 numWeakAlive,(void)aHandleReport->Callback(""_ns, nsLiteralCString("preference-service/referent/weak/alive"
), KIND_OTHER, UNITS_COUNT, numWeakAlive, nsLiteralCString("The number of weak referents held by the preference service that are "
"still alive."), aData)
3549 "The number of weak referents held by the preference service that are "(void)aHandleReport->Callback(""_ns, nsLiteralCString("preference-service/referent/weak/alive"
), KIND_OTHER, UNITS_COUNT, numWeakAlive, nsLiteralCString("The number of weak referents held by the preference service that are "
"still alive."), aData)
3550 "still alive.")(void)aHandleReport->Callback(""_ns, nsLiteralCString("preference-service/referent/weak/alive"
), KIND_OTHER, UNITS_COUNT, numWeakAlive, nsLiteralCString("The number of weak referents held by the preference service that are "
"still alive."), aData)
;
3551
3552 MOZ_COLLECT_REPORT((void)aHandleReport->Callback(""_ns, nsLiteralCString("preference-service/referent/weak/dead"
), KIND_OTHER, UNITS_COUNT, numWeakDead, nsLiteralCString("The number of weak referents held by the preference service that are "
"dead."), aData)
3553 "preference-service/referent/weak/dead", KIND_OTHER, UNITS_COUNT,(void)aHandleReport->Callback(""_ns, nsLiteralCString("preference-service/referent/weak/dead"
), KIND_OTHER, UNITS_COUNT, numWeakDead, nsLiteralCString("The number of weak referents held by the preference service that are "
"dead."), aData)
3554 numWeakDead,(void)aHandleReport->Callback(""_ns, nsLiteralCString("preference-service/referent/weak/dead"
), KIND_OTHER, UNITS_COUNT, numWeakDead, nsLiteralCString("The number of weak referents held by the preference service that are "
"dead."), aData)
3555 "The number of weak referents held by the preference service that are "(void)aHandleReport->Callback(""_ns, nsLiteralCString("preference-service/referent/weak/dead"
), KIND_OTHER, UNITS_COUNT, numWeakDead, nsLiteralCString("The number of weak referents held by the preference service that are "
"dead."), aData)
3556 "dead.")(void)aHandleReport->Callback(""_ns, nsLiteralCString("preference-service/referent/weak/dead"
), KIND_OTHER, UNITS_COUNT, numWeakDead, nsLiteralCString("The number of weak referents held by the preference service that are "
"dead."), aData)
;
3557
3558 return NS_OK;
3559}
3560
3561namespace {
3562
3563class AddPreferencesMemoryReporterRunnable : public Runnable {
3564 public:
3565 AddPreferencesMemoryReporterRunnable()
3566 : Runnable("AddPreferencesMemoryReporterRunnable") {}
3567
3568 NS_IMETHODvirtual nsresult Run() override {
3569 return RegisterStrongMemoryReporter(new PreferenceServiceReporter());
3570 }
3571};
3572
3573} // namespace
3574
3575// A list of changed prefs sent from the parent via shared memory.
3576static StaticAutoPtr<nsTArray<dom::Pref>> gChangedDomPrefs;
3577
3578static const char kTelemetryPref[] = "toolkit.telemetry.enabled";
3579static const char kChannelPref[] = "app.update.channel";
3580
3581#ifdef MOZ_WIDGET_ANDROID
3582
3583static Maybe<bool> TelemetryPrefValue() {
3584 // Leave it unchanged if it's already set.
3585 // XXX: how could it already be set?
3586 if (Preferences::GetType(kTelemetryPref) != nsIPrefBranch::PREF_INVALID) {
3587 return Nothing();
3588 }
3589
3590 // Determine the correct default for toolkit.telemetry.enabled. If this
3591 // build has MOZ_TELEMETRY_ON_BY_DEFAULT *or* we're on the beta channel,
3592 // telemetry is on by default, otherwise not. This is necessary so that
3593 // beta users who are testing final release builds don't flipflop defaults.
3594# ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
3595 return Some(true);
3596# else
3597 nsAutoCString channelPrefValue;
3598 Unused << Preferences::GetCString(kChannelPref, channelPrefValue,
3599 PrefValueKind::Default);
3600 return Some(channelPrefValue.EqualsLiteral("beta"));
3601# endif
3602}
3603
3604/* static */
3605void Preferences::SetupTelemetryPref() {
3606 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3606); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 3606; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3607
3608 Maybe<bool> telemetryPrefValue = TelemetryPrefValue();
3609 if (telemetryPrefValue.isSome()) {
3610 Preferences::SetBool(kTelemetryPref, *telemetryPrefValue,
3611 PrefValueKind::Default);
3612 }
3613}
3614
3615#else // !MOZ_WIDGET_ANDROID
3616
3617static bool TelemetryPrefValue() {
3618 // For platforms with Unified Telemetry (here meaning not-Android),
3619 // toolkit.telemetry.enabled determines whether we send "extended" data.
3620 // We only want extended data from pre-release channels due to size.
3621
3622 constexpr auto channel = MOZ_STRINGIFY(MOZ_UPDATE_CHANNEL)"default" ""_ns;
3623
3624 // Easy cases: Nightly, Aurora, Beta.
3625 if (channel.EqualsLiteral("nightly") || channel.EqualsLiteral("aurora") ||
3626 channel.EqualsLiteral("beta")) {
3627 return true;
3628 }
3629
3630# ifndef MOZILLA_OFFICIAL
3631 // Local developer builds: non-official builds on the "default" channel.
3632 if (channel.EqualsLiteral("default")) {
3633 return true;
3634 }
3635# endif
3636
3637 // Release Candidate builds: builds that think they are release builds, but
3638 // are shipped to beta users.
3639 if (channel.EqualsLiteral("release")) {
3640 nsAutoCString channelPrefValue;
3641 Unused << Preferences::GetCString(kChannelPref, channelPrefValue,
3642 PrefValueKind::Default);
3643 if (channelPrefValue.EqualsLiteral("beta")) {
3644 return true;
3645 }
3646 }
3647
3648 return false;
3649}
3650
3651/* static */
3652void Preferences::SetupTelemetryPref() {
3653 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3653); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 3653; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3654
3655 Preferences::SetBool(kTelemetryPref, TelemetryPrefValue(),
3656 PrefValueKind::Default);
3657 Preferences::Lock(kTelemetryPref);
3658}
3659
3660#endif // MOZ_WIDGET_ANDROID
3661
3662/* static */
3663already_AddRefed<Preferences> Preferences::GetInstanceForService() {
3664 if (sPreferences) {
3665 return do_AddRef(sPreferences);
3666 }
3667
3668 if (sShutdown) {
3669 return nullptr;
3670 }
3671
3672 sPreferences = new Preferences();
3673
3674 MOZ_ASSERT(!HashTable())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!HashTable())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!HashTable()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!HashTable()", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3674); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!HashTable()"
")"); do { *((volatile int*)__null) = 3674; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3675 HashTable() = new PrefsHashTable(XRE_IsParentProcess()
3676 ? kHashTableInitialLengthParent
3677 : kHashTableInitialLengthContent);
3678
3679#ifdef DEBUG1
3680 gOnceStaticPrefsAntiFootgun = new AntiFootgunMap();
3681#endif
3682
3683#ifdef ACCESS_COUNTS
3684 MOZ_ASSERT(!gAccessCounts)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!gAccessCounts)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!gAccessCounts))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!gAccessCounts"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3684); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!gAccessCounts"
")"); do { *((volatile int*)__null) = 3684; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3685 gAccessCounts = new AccessCountsHashTable();
3686#endif
3687
3688 nsresult rv = InitInitialObjects(/* isStartup */ true);
3689 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3690 sPreferences = nullptr;
3691 return nullptr;
3692 }
3693
3694 if (!XRE_IsParentProcess()) {
3695 MOZ_ASSERT(gChangedDomPrefs)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(gChangedDomPrefs)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(gChangedDomPrefs))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("gChangedDomPrefs"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3695); AnnotateMozCrashReason("MOZ_ASSERT" "(" "gChangedDomPrefs"
")"); do { *((volatile int*)__null) = 3695; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3696 for (unsigned int i = 0; i < gChangedDomPrefs->Length(); i++) {
3697 Preferences::SetPreference(gChangedDomPrefs->ElementAt(i));
3698 }
3699 gChangedDomPrefs = nullptr;
3700 } else {
3701 // Check if there is a deployment configuration file. If so, set up the
3702 // pref config machinery, which will actually read the file.
3703 nsAutoCString lockFileName;
3704 nsresult rv = Preferences::GetCString("general.config.filename",
3705 lockFileName, PrefValueKind::User);
3706 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3707 NS_CreateServicesFromCategory(
3708 "pref-config-startup",
3709 static_cast<nsISupports*>(static_cast<void*>(sPreferences)),
3710 "pref-config-startup");
3711 }
3712
3713 nsCOMPtr<nsIObserverService> observerService =
3714 services::GetObserverService();
3715 if (!observerService) {
3716 sPreferences = nullptr;
3717 return nullptr;
3718 }
3719
3720 observerService->AddObserver(sPreferences,
3721 "profile-before-change-telemetry", true);
3722 rv = observerService->AddObserver(sPreferences, "profile-before-change",
3723 true);
3724
3725 observerService->AddObserver(sPreferences, "suspend_process_notification",
3726 true);
3727
3728 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3729 sPreferences = nullptr;
3730 return nullptr;
3731 }
3732 }
3733
3734 const char* defaultPrefs = getenv("MOZ_DEFAULT_PREFS");
3735 if (defaultPrefs) {
3736 parsePrefData(nsCString(defaultPrefs), PrefValueKind::Default);
3737 }
3738
3739 // Preferences::GetInstanceForService() can be called from GetService(), and
3740 // RegisterStrongMemoryReporter calls GetService(nsIMemoryReporter). To
3741 // avoid a potential recursive GetService() call, we can't register the
3742 // memory reporter here; instead, do it off a runnable.
3743 RefPtr<AddPreferencesMemoryReporterRunnable> runnable =
3744 new AddPreferencesMemoryReporterRunnable();
3745 NS_DispatchToMainThread(runnable);
3746
3747 return do_AddRef(sPreferences);
3748}
3749
3750/* static */
3751bool Preferences::IsServiceAvailable() { return !!sPreferences; }
3752
3753/* static */
3754bool Preferences::InitStaticMembers() {
3755 MOZ_ASSERT(NS_IsMainThread() || ServoStyleSet::IsInServoTraversal())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread() || ServoStyleSet::IsInServoTraversal
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(NS_IsMainThread() || ServoStyleSet::IsInServoTraversal
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("NS_IsMainThread() || ServoStyleSet::IsInServoTraversal()", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3755); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread() || ServoStyleSet::IsInServoTraversal()"
")"); do { *((volatile int*)__null) = 3755; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3756
3757 if (MOZ_LIKELY(sPreferences)(__builtin_expect(!!(sPreferences), 1))) {
3758 return true;
3759 }
3760
3761 if (!sShutdown) {
3762 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3762); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 3762; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3763 nsCOMPtr<nsIPrefService> prefService =
3764 do_GetService(NS_PREFSERVICE_CONTRACTID"@mozilla.org/preferences-service;1");
3765 }
3766
3767 return sPreferences != nullptr;
3768}
3769
3770/* static */
3771void Preferences::Shutdown() {
3772 if (!sShutdown) {
3773 sShutdown = true; // Don't create the singleton instance after here.
3774 sPreferences = nullptr;
3775 StaticPrefs::ShutdownAlwaysPrefs();
3776 }
3777}
3778
3779Preferences::Preferences()
3780 : mRootBranch(new nsPrefBranch("", PrefValueKind::User)),
3781 mDefaultRootBranch(new nsPrefBranch("", PrefValueKind::Default)) {}
3782
3783Preferences::~Preferences() {
3784 MOZ_ASSERT(!sPreferences)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!sPreferences)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!sPreferences))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!sPreferences",
"/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3784); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sPreferences"
")"); do { *((volatile int*)__null) = 3784; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3785
3786 MOZ_ASSERT(!gCallbacksInProgress)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!gCallbacksInProgress)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!gCallbacksInProgress))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!gCallbacksInProgress"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3786); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!gCallbacksInProgress"
")"); do { *((volatile int*)__null) = 3786; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3787
3788 CallbackNode* node = gFirstCallback;
3789 while (node) {
3790 CallbackNode* next_node = node->Next();
3791 delete node;
3792 node = next_node;
3793 }
3794 gLastPriorityNode = gFirstCallback = nullptr;
3795
3796 delete HashTable();
3797 HashTable() = nullptr;
3798
3799#ifdef DEBUG1
3800 gOnceStaticPrefsAntiFootgun = nullptr;
3801#endif
3802
3803#ifdef ACCESS_COUNTS
3804 gAccessCounts = nullptr;
3805#endif
3806
3807 gSharedMap = nullptr;
3808
3809 PrefNameArena().Clear();
3810}
3811
3812NS_IMPL_ISUPPORTS(Preferences, nsIPrefService, nsIObserver, nsIPrefBranch,MozExternalRefCountType Preferences::AddRef(void) { static_assert
(!std::is_destructible_v<Preferences>, "Reference-counted class "
"Preferences" " should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3813); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
3813; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("Preferences" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("Preferences" != nullptr))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("\"Preferences\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3813); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"Preferences\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 3813; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("Preferences" " not thread-safe"); nsrefcnt count
= ++mRefCnt; NS_LogAddRef((this), (count), ("Preferences"), (
uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
Preferences::Release(void) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(int32_t(mRefCnt) > 0)
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3813); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 3813
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("Preferences" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("Preferences" != nullptr))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("\"Preferences\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3813); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"Preferences\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 3813; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("Preferences" " not thread-safe"); const char
* const nametmp = "Preferences"; nsrefcnt count = --mRefCnt; NS_LogRelease
((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete
(this); return 0; } return count; } nsresult Preferences::QueryInterface
(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3813); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(4 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<Preferences, nsIPrefService>, int32_t
( reinterpret_cast<char*>(static_cast<nsIPrefService
*>((Preferences*)0x1000)) - reinterpret_cast<char*>(
(Preferences*)0x1000))}, {&mozilla::detail::kImplementedIID
<Preferences, nsIObserver>, int32_t( reinterpret_cast<
char*>(static_cast<nsIObserver*>((Preferences*)0x1000
)) - reinterpret_cast<char*>((Preferences*)0x1000))}, {
&mozilla::detail::kImplementedIID<Preferences, nsIPrefBranch
>, int32_t( reinterpret_cast<char*>(static_cast<nsIPrefBranch
*>((Preferences*)0x1000)) - reinterpret_cast<char*>(
(Preferences*)0x1000))}, {&mozilla::detail::kImplementedIID
<Preferences, nsISupportsWeakReference>, int32_t( reinterpret_cast
<char*>(static_cast<nsISupportsWeakReference*>((Preferences
*)0x1000)) - reinterpret_cast<char*>((Preferences*)0x1000
))}, {&mozilla::detail::kImplementedIID<Preferences, nsISupports
>, int32_t(reinterpret_cast<char*>(static_cast<nsISupports
*>( static_cast<nsIPrefService*>((Preferences*)0x1000
))) - reinterpret_cast<char*>((Preferences*)0x1000))}, {
nullptr, 0 } } ; static_assert((sizeof(table) / sizeof(table
[0])) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
3813 nsISupportsWeakReference)MozExternalRefCountType Preferences::AddRef(void) { static_assert
(!std::is_destructible_v<Preferences>, "Reference-counted class "
"Preferences" " should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3813); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
3813; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("Preferences" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("Preferences" != nullptr))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("\"Preferences\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3813); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"Preferences\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 3813; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("Preferences" " not thread-safe"); nsrefcnt count
= ++mRefCnt; NS_LogAddRef((this), (count), ("Preferences"), (
uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
Preferences::Release(void) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(int32_t(mRefCnt) > 0)
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3813); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 3813
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("Preferences" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("Preferences" != nullptr))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("\"Preferences\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3813); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"Preferences\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 3813; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("Preferences" " not thread-safe"); const char
* const nametmp = "Preferences"; nsrefcnt count = --mRefCnt; NS_LogRelease
((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete
(this); return 0; } return count; } nsresult Preferences::QueryInterface
(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3813); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(4 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<Preferences, nsIPrefService>, int32_t
( reinterpret_cast<char*>(static_cast<nsIPrefService
*>((Preferences*)0x1000)) - reinterpret_cast<char*>(
(Preferences*)0x1000))}, {&mozilla::detail::kImplementedIID
<Preferences, nsIObserver>, int32_t( reinterpret_cast<
char*>(static_cast<nsIObserver*>((Preferences*)0x1000
)) - reinterpret_cast<char*>((Preferences*)0x1000))}, {
&mozilla::detail::kImplementedIID<Preferences, nsIPrefBranch
>, int32_t( reinterpret_cast<char*>(static_cast<nsIPrefBranch
*>((Preferences*)0x1000)) - reinterpret_cast<char*>(
(Preferences*)0x1000))}, {&mozilla::detail::kImplementedIID
<Preferences, nsISupportsWeakReference>, int32_t( reinterpret_cast
<char*>(static_cast<nsISupportsWeakReference*>((Preferences
*)0x1000)) - reinterpret_cast<char*>((Preferences*)0x1000
))}, {&mozilla::detail::kImplementedIID<Preferences, nsISupports
>, int32_t(reinterpret_cast<char*>(static_cast<nsISupports
*>( static_cast<nsIPrefService*>((Preferences*)0x1000
))) - reinterpret_cast<char*>((Preferences*)0x1000))}, {
nullptr, 0 } } ; static_assert((sizeof(table) / sizeof(table
[0])) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
3814
3815/* static */
3816void Preferences::SerializePreferences(nsCString& aStr,
3817 bool aIsDestinationWebContentProcess) {
3818 MOZ_RELEASE_ASSERT(InitStaticMembers())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(InitStaticMembers())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(InitStaticMembers()))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("InitStaticMembers()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3818); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "InitStaticMembers()"
")"); do { *((volatile int*)__null) = 3818; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3819
3820 aStr.Truncate();
3821
3822 for (auto iter = HashTable()->iter(); !iter.done(); iter.next()) {
3823 Pref* pref = iter.get().get();
3824 if (!pref->IsTypeNone() && pref->HasAdvisablySizedValues()) {
3825 pref->SerializeAndAppend(aStr, aIsDestinationWebContentProcess &&
3826 ShouldSanitizePreference(pref));
3827 }
3828 }
3829
3830 aStr.Append('\0');
3831}
3832
3833/* static */
3834void Preferences::DeserializePreferences(char* aStr, size_t aPrefsLen) {
3835 MOZ_ASSERT(!XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!XRE_IsParentProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3835); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 3835; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3836
3837 MOZ_ASSERT(!gChangedDomPrefs)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!gChangedDomPrefs)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!gChangedDomPrefs))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!gChangedDomPrefs"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3837); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!gChangedDomPrefs"
")"); do { *((volatile int*)__null) = 3837; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3838 gChangedDomPrefs = new nsTArray<dom::Pref>();
3839
3840 char* p = aStr;
3841 while (*p != '\0') {
3842 dom::Pref pref;
3843 p = Pref::Deserialize(p, &pref);
3844 gChangedDomPrefs->AppendElement(pref);
3845 }
3846
3847 // We finished parsing on a '\0'. That should be the last char in the shared
3848 // memory. (aPrefsLen includes the '\0'.)
3849 MOZ_ASSERT(p == aStr + aPrefsLen - 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(p == aStr + aPrefsLen - 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(p == aStr + aPrefsLen - 1)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("p == aStr + aPrefsLen - 1"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3849); AnnotateMozCrashReason("MOZ_ASSERT" "(" "p == aStr + aPrefsLen - 1"
")"); do { *((volatile int*)__null) = 3849; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3850
3851 MOZ_ASSERT(!gContentProcessPrefsAreInited)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!gContentProcessPrefsAreInited)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!gContentProcessPrefsAreInited
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!gContentProcessPrefsAreInited", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3851); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!gContentProcessPrefsAreInited"
")"); do { *((volatile int*)__null) = 3851; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3852 gContentProcessPrefsAreInited = true;
3853}
3854
3855/* static */
3856FileDescriptor Preferences::EnsureSnapshot(size_t* aSize) {
3857 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3857); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 3857; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3858 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3858); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 3858; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3859
3860 if (!gSharedMap) {
3861 SharedPrefMapBuilder builder;
3862
3863 nsTArray<Pref*> toRepopulate;
3864 NameArena* newPrefNameArena = new NameArena();
3865 for (auto iter = HashTable()->modIter(); !iter.done(); iter.next()) {
3866 if (!ShouldSanitizePreference(iter.get().get())) {
3867 iter.get()->AddToMap(builder);
3868 } else {
3869 Pref* pref = iter.getMutable().release();
3870 pref->RelocateName(newPrefNameArena);
3871 toRepopulate.AppendElement(pref);
3872 }
3873 }
3874
3875 // Store the current value of `once`-mirrored prefs. After this point they
3876 // will be immutable.
3877 StaticPrefs::RegisterOncePrefs(builder);
3878
3879 gSharedMap = new SharedPrefMap(std::move(builder));
3880
3881 // Once we've built a snapshot of the database, there's no need to continue
3882 // storing dynamic copies of the preferences it contains. Once we reset the
3883 // hashtable, preference lookups will fall back to the snapshot for any
3884 // preferences not in the dynamic hashtable.
3885 //
3886 // And since the majority of the database is now contained in the snapshot,
3887 // we can initialize the hashtable with the expected number of per-session
3888 // changed preferences, rather than the expected total number of
3889 // preferences.
3890 HashTable()->clearAndCompact();
3891 Unused << HashTable()->reserve(kHashTableInitialLengthContent);
3892
3893 delete sPrefNameArena;
3894 sPrefNameArena = newPrefNameArena;
3895 gCallbackPref = nullptr;
3896
3897 for (uint32_t i = 0; i < toRepopulate.Length(); i++) {
3898 auto pref = toRepopulate[i];
3899 auto p = HashTable()->lookupForAdd(pref->Name());
3900 MOZ_ASSERT(!p.found())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!p.found())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!p.found()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!p.found()", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3900); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!p.found()"
")"); do { *((volatile int*)__null) = 3900; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3901 Unused << HashTable()->add(p, pref);
3902 }
3903 }
3904
3905 *aSize = gSharedMap->MapSize();
3906 return gSharedMap->CloneFileDescriptor();
3907}
3908
3909/* static */
3910void Preferences::InitSnapshot(const FileDescriptor& aHandle, size_t aSize) {
3911 MOZ_ASSERT(!XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!XRE_IsParentProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 3911; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3912 MOZ_ASSERT(!gSharedMap)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!gSharedMap)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!gSharedMap))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!gSharedMap", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3912); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!gSharedMap"
")"); do { *((volatile int*)__null) = 3912; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3913
3914 gSharedMap = new SharedPrefMap(aHandle, aSize);
3915
3916 StaticPrefs::InitStaticPrefsFromShared();
3917}
3918
3919/* static */
3920void Preferences::InitializeUserPrefs() {
3921 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3921); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 3921; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3922 MOZ_ASSERT(!sPreferences->mCurrentFile, "Should only initialize prefs once")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!sPreferences->mCurrentFile)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!sPreferences->mCurrentFile
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!sPreferences->mCurrentFile" " (" "Should only initialize prefs once"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3922); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sPreferences->mCurrentFile"
") (" "Should only initialize prefs once" ")"); do { *((volatile
int*)__null) = 3922; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
3923
3924 // Prefs which are set before we initialize the profile are silently
3925 // discarded. This is stupid, but there are various tests which depend on
3926 // this behavior.
3927 sPreferences->ResetUserPrefs();
3928
3929 nsCOMPtr<nsIFile> prefsFile = sPreferences->ReadSavedPrefs();
3930 sPreferences->ReadUserOverridePrefs();
3931
3932 sPreferences->mDirty = false;
3933
3934 // Don't set mCurrentFile until we're done so that dirty flags work properly.
3935 sPreferences->mCurrentFile = std::move(prefsFile);
3936}
3937
3938/* static */
3939void Preferences::FinishInitializingUserPrefs() {
3940 sPreferences->NotifyServiceObservers(NS_PREFSERVICE_READ_TOPIC_ID"prefservice:before-read-userprefs");
3941}
3942
3943NS_IMETHODIMPnsresult
3944Preferences::Observe(nsISupports* aSubject, const char* aTopic,
3945 const char16_t* someData) {
3946 if (MOZ_UNLIKELY(!XRE_IsParentProcess())(__builtin_expect(!!(!XRE_IsParentProcess()), 0))) {
3947 return NS_ERROR_NOT_AVAILABLE;
3948 }
3949
3950 nsresult rv = NS_OK;
3951
3952 if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
3953 // Normally prefs aren't written after this point, and so we kick off
3954 // an asynchronous pref save so that I/O can be done in parallel with
3955 // other shutdown.
3956 if (AllowOffMainThreadSave()) {
3957 SavePrefFile(nullptr);
3958 }
3959
3960 } else if (!nsCRT::strcmp(aTopic, "profile-before-change-telemetry")) {
3961 // It's possible that a profile-before-change observer after ours
3962 // set a pref. A blocking save here re-saves if necessary and also waits
3963 // for any pending saves to complete.
3964 SavePrefFileBlocking();
3965 MOZ_ASSERT(!mDirty, "Preferences should not be dirty")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mDirty)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mDirty))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!mDirty" " (" "Preferences should not be dirty"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3965); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDirty" ") ("
"Preferences should not be dirty" ")"); do { *((volatile int
*)__null) = 3965; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
3966 mProfileShutdown = true;
3967
3968 } else if (!nsCRT::strcmp(aTopic, "suspend_process_notification")) {
3969 // Our process is being suspended. The OS may wake our process later,
3970 // or it may kill the process. In case our process is going to be killed
3971 // from the suspended state, we save preferences before suspending.
3972 rv = SavePrefFileBlocking();
3973 }
3974
3975 return rv;
3976}
3977
3978NS_IMETHODIMPnsresult
3979Preferences::ReadDefaultPrefsFromFile(nsIFile* aFile) {
3980 ENSURE_PARENT_PROCESS("Preferences::ReadDefaultPrefsFromFile", "all prefs");
3981
3982 if (!aFile) {
3983 NS_ERROR("ReadDefaultPrefsFromFile requires a parameter")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "ReadDefaultPrefsFromFile requires a parameter"
, "Error", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3983); MOZ_PretendNoReturn(); } while (0)
;
3984 return NS_ERROR_INVALID_ARG;
3985 }
3986
3987 return openPrefFile(aFile, PrefValueKind::Default);
3988}
3989
3990NS_IMETHODIMPnsresult
3991Preferences::ReadUserPrefsFromFile(nsIFile* aFile) {
3992 ENSURE_PARENT_PROCESS("Preferences::ReadUserPrefsFromFile", "all prefs");
3993
3994 if (!aFile) {
3995 NS_ERROR("ReadUserPrefsFromFile requires a parameter")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "ReadUserPrefsFromFile requires a parameter"
, "Error", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 3995); MOZ_PretendNoReturn(); } while (0)
;
3996 return NS_ERROR_INVALID_ARG;
3997 }
3998
3999 return openPrefFile(aFile, PrefValueKind::User);
4000}
4001
4002NS_IMETHODIMPnsresult
4003Preferences::ResetPrefs() {
4004 ENSURE_PARENT_PROCESS("Preferences::ResetPrefs", "all prefs");
4005
4006 if (gSharedMap) {
4007 return NS_ERROR_NOT_AVAILABLE;
4008 }
4009
4010 HashTable()->clearAndCompact();
4011 Unused << HashTable()->reserve(kHashTableInitialLengthParent);
4012
4013 PrefNameArena().Clear();
4014
4015 return InitInitialObjects(/* isStartup */ false);
4016}
4017
4018nsresult Preferences::ResetUserPrefs() {
4019 ENSURE_PARENT_PROCESS("Preferences::ResetUserPrefs", "all prefs");
4020 NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(InitStaticMembers())), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "InitStaticMembers()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4020); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
4021 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4021); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 4021; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4022
4023 Vector<const char*> prefNames;
4024 for (auto iter = HashTable()->modIter(); !iter.done(); iter.next()) {
4025 Pref* pref = iter.get().get();
4026
4027 if (pref->HasUserValue()) {
4028 if (!prefNames.append(pref->Name())) {
4029 return NS_ERROR_OUT_OF_MEMORY;
4030 }
4031
4032 pref->ClearUserValue();
4033 if (!pref->HasDefaultValue()) {
4034 iter.remove();
4035 }
4036 }
4037 }
4038
4039 for (const char* prefName : prefNames) {
4040 NotifyCallbacks(nsDependentCString(prefName));
4041 }
4042
4043 Preferences::HandleDirty();
4044 return NS_OK;
4045}
4046
4047bool Preferences::AllowOffMainThreadSave() {
4048 // Put in a preference that allows us to disable off main thread preference
4049 // file save.
4050 if (sAllowOMTPrefWrite < 0) {
4051 bool value = false;
4052 Preferences::GetBool("preferences.allow.omt-write", &value);
4053 sAllowOMTPrefWrite = value ? 1 : 0;
4054 }
4055
4056 return !!sAllowOMTPrefWrite;
4057}
4058
4059nsresult Preferences::SavePrefFileBlocking() {
4060 if (mDirty) {
4061 return SavePrefFileInternal(nullptr, SaveMethod::Blocking);
4062 }
4063
4064 // If we weren't dirty to start, SavePrefFileInternal will early exit so
4065 // there is no guarantee that we don't have oustanding async saves in the
4066 // pipe. Since the contract of SavePrefFileOnMainThread is that the file on
4067 // disk matches the preferences, we have to make sure those requests are
4068 // completed.
4069
4070 if (AllowOffMainThreadSave()) {
4071 PreferencesWriter::Flush();
4072 }
4073
4074 return NS_OK;
4075}
4076
4077nsresult Preferences::SavePrefFileAsynchronous() {
4078 return SavePrefFileInternal(nullptr, SaveMethod::Asynchronous);
4079}
4080
4081NS_IMETHODIMPnsresult
4082Preferences::SavePrefFile(nsIFile* aFile) {
4083 // This is the method accessible from service API. Make it off main thread.
4084 return SavePrefFileInternal(aFile, SaveMethod::Asynchronous);
4085}
4086
4087NS_IMETHODIMPnsresult
4088Preferences::BackupPrefFile(nsIFile* aFile, JSContext* aCx,
4089 Promise** aPromise) {
4090 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4090); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 4090; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4091
4092 if (!aFile) {
4093 return NS_ERROR_INVALID_ARG;
4094 }
4095
4096 if (mCurrentFile) {
4097 bool equalsCurrent = false;
4098 nsresult rv = aFile->Equals(mCurrentFile, &equalsCurrent);
4099
4100 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4101 return rv;
4102 }
4103
4104 if (equalsCurrent) {
4105 return NS_ERROR_INVALID_ARG;
4106 }
4107 }
4108
4109 ErrorResult result;
4110 RefPtr<Promise> promise =
4111 Promise::Create(xpc::CurrentNativeGlobal(aCx), result);
4112
4113 if (MOZ_UNLIKELY(result.Failed())(__builtin_expect(!!(result.Failed()), 0))) {
4114 return result.StealNSResult();
4115 }
4116
4117 nsMainThreadPtrHandle<Promise> domPromiseHolder(
4118 new nsMainThreadPtrHolder<Promise>("Preferences::BackupPrefFile promise",
4119 promise));
4120
4121 auto mozPromiseHolder = MakeUnique<MozPromiseHolder<WritePrefFilePromise>>();
4122 RefPtr<WritePrefFilePromise> writePrefPromise =
4123 mozPromiseHolder->Ensure(__func__);
4124
4125 nsresult rv = WritePrefFile(aFile, SaveMethod::Asynchronous,
4126 std::move(mozPromiseHolder));
4127 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4128 // WritePrefFile is responsible for rejecting the underlying MozPromise in
4129 // the event that it the method failed somewhere.
4130 return rv;
4131 }
4132
4133 writePrefPromise->Then(
4134 GetMainThreadSerialEventTarget(), __func__,
4135 [domPromiseHolder](bool) {
4136 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4136); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 4136; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4137 domPromiseHolder.get()->MaybeResolveWithUndefined();
4138 },
4139 [domPromiseHolder](nsresult rv) {
4140 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4140); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 4140; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4141 domPromiseHolder.get()->MaybeReject(rv);
4142 });
4143
4144 promise.forget(aPromise);
4145 return NS_OK;
4146}
4147
4148/* static */
4149void Preferences::SetPreference(const dom::Pref& aDomPref) {
4150 MOZ_ASSERT(!XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!XRE_IsParentProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4150); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 4150; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4151 NS_ENSURE_TRUE(InitStaticMembers(), (void)0)do { if ((__builtin_expect(!!(!(InitStaticMembers())), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "InitStaticMembers()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4151); return (void)0; } } while (false)
;
4152
4153 const nsCString& prefName = aDomPref.name();
4154
4155 Pref* pref;
4156 auto p = HashTable()->lookupForAdd(prefName.get());
4157 if (!p) {
4158 pref = new Pref(prefName);
4159 if (!HashTable()->add(p, pref)) {
4160 delete pref;
4161 return;
4162 }
4163 } else {
4164 pref = p->get();
4165 }
4166
4167 bool valueChanged = false;
4168 pref->FromDomPref(aDomPref, &valueChanged);
4169
4170 // When the parent process clears a pref's user value we get a DomPref here
4171 // with no default value and no user value. There are two possibilities.
4172 //
4173 // - There was an existing pref with only a user value. FromDomPref() will
4174 // have just cleared that user value, so the pref can be removed.
4175 //
4176 // - There was no existing pref. FromDomPref() will have done nothing, and
4177 // `pref` will be valueless. We will end up adding and removing the value
4178 // needlessly, but that's ok because this case is rare.
4179 //
4180 if (!pref->HasDefaultValue() && !pref->HasUserValue() &&
4181 !pref->IsSanitized()) {
4182 // If the preference exists in the shared map, we need to keep the dynamic
4183 // entry around to mask it.
4184 if (gSharedMap->Has(pref->Name())) {
4185 pref->SetType(PrefType::None);
4186 } else {
4187 HashTable()->remove(prefName.get());
4188 }
4189 pref = nullptr;
4190 }
4191
4192 // Note: we don't have to worry about HandleDirty() because we are setting
4193 // prefs in the content process that have come from the parent process.
4194
4195 if (valueChanged) {
4196 if (pref) {
4197 NotifyCallbacks(prefName, PrefWrapper(pref));
4198 } else {
4199 NotifyCallbacks(prefName);
4200 }
4201 }
4202}
4203
4204/* static */
4205void Preferences::GetPreference(dom::Pref* aDomPref,
4206 const GeckoProcessType aDestinationProcessType,
4207 const nsACString& aDestinationRemoteType) {
4208 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4208); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 4208; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4209 bool destIsWebContent =
4210 aDestinationProcessType == GeckoProcessType_Content &&
4211 (StringBeginsWith(aDestinationRemoteType, WEB_REMOTE_TYPE"web"_ns) ||
4212 StringBeginsWith(aDestinationRemoteType, PREALLOC_REMOTE_TYPE"prealloc"_ns) ||
4213 StringBeginsWith(aDestinationRemoteType, PRIVILEGEDMOZILLA_REMOTE_TYPE"privilegedmozilla"_ns));
4214
4215 Pref* pref = pref_HashTableLookup(aDomPref->name().get());
4216 if (pref && pref->HasAdvisablySizedValues()) {
4217 pref->ToDomPref(aDomPref, destIsWebContent);
4218 }
4219}
4220
4221#ifdef DEBUG1
4222bool Preferences::ArePrefsInitedInContentProcess() {
4223 MOZ_ASSERT(!XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!XRE_IsParentProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4223); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 4223; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4224 return gContentProcessPrefsAreInited;
4225}
4226#endif
4227
4228NS_IMETHODIMPnsresult
4229Preferences::GetBranch(const char* aPrefRoot, nsIPrefBranch** aRetVal) {
4230 if ((nullptr != aPrefRoot) && (*aPrefRoot != '\0')) {
4231 // TODO: Cache this stuff and allow consumers to share branches (hold weak
4232 // references, I think).
4233 RefPtr<nsPrefBranch> prefBranch =
4234 new nsPrefBranch(aPrefRoot, PrefValueKind::User);
4235 prefBranch.forget(aRetVal);
4236 } else {
4237 // Special case: caching the default root.
4238 nsCOMPtr<nsIPrefBranch> root(sPreferences->mRootBranch);
4239 root.forget(aRetVal);
4240 }
4241
4242 return NS_OK;
4243}
4244
4245NS_IMETHODIMPnsresult
4246Preferences::GetDefaultBranch(const char* aPrefRoot, nsIPrefBranch** aRetVal) {
4247 if (!aPrefRoot || !aPrefRoot[0]) {
4248 nsCOMPtr<nsIPrefBranch> root(sPreferences->mDefaultRootBranch);
4249 root.forget(aRetVal);
4250 return NS_OK;
4251 }
4252
4253 // TODO: Cache this stuff and allow consumers to share branches (hold weak
4254 // references, I think).
4255 RefPtr<nsPrefBranch> prefBranch =
4256 new nsPrefBranch(aPrefRoot, PrefValueKind::Default);
4257 if (!prefBranch) {
4258 return NS_ERROR_OUT_OF_MEMORY;
4259 }
4260
4261 prefBranch.forget(aRetVal);
4262 return NS_OK;
4263}
4264
4265NS_IMETHODIMPnsresult
4266Preferences::ReadStats(nsIPrefStatsCallback* aCallback) {
4267#ifdef ACCESS_COUNTS
4268 for (const auto& entry : *gAccessCounts) {
4269 aCallback->Visit(entry.GetKey(), entry.GetData());
4270 }
4271
4272 return NS_OK;
4273#else
4274 return NS_ERROR_NOT_IMPLEMENTED;
4275#endif
4276}
4277
4278NS_IMETHODIMPnsresult
4279Preferences::ResetStats() {
4280#ifdef ACCESS_COUNTS
4281 gAccessCounts->Clear();
4282 return NS_OK;
4283#else
4284 return NS_ERROR_NOT_IMPLEMENTED;
4285#endif
4286}
4287
4288// We would much prefer to use C++ lambdas, but we cannot convert
4289// lambdas that capture (here, the underlying observer) to C pointer
4290// to functions. So, here we are, with icky C callbacks. Be aware
4291// that nothing is thread-safe here because there's a single global
4292// `nsIPrefObserver` instance. Use this from the main thread only.
4293nsIPrefObserver* PrefObserver = nullptr;
4294
4295void HandlePref(const char* aPrefName, PrefType aType, PrefValueKind aKind,
4296 PrefValue aValue, bool aIsSticky, bool aIsLocked) {
4297 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 4297; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4298
4299 if (!PrefObserver) {
4300 return;
4301 }
4302
4303 const char* kind = aKind == PrefValueKind::Default ? "Default" : "User";
4304
4305 switch (aType) {
4306 case PrefType::String:
4307 PrefObserver->OnStringPref(kind, aPrefName, aValue.mStringVal, aIsSticky,
4308 aIsLocked);
4309 break;
4310 case PrefType::Int:
4311 PrefObserver->OnIntPref(kind, aPrefName, aValue.mIntVal, aIsSticky,
4312 aIsLocked);
4313 break;
4314 case PrefType::Bool:
4315 PrefObserver->OnBoolPref(kind, aPrefName, aValue.mBoolVal, aIsSticky,
4316 aIsLocked);
4317 break;
4318 default:
4319 PrefObserver->OnError("Unexpected pref type.");
4320 }
4321}
4322
4323void HandleError(const char* aMsg) {
4324 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4324); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 4324; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4325
4326 if (!PrefObserver) {
4327 return;
4328 }
4329
4330 PrefObserver->OnError(aMsg);
4331}
4332
4333NS_IMETHODIMPnsresult
4334Preferences::ParsePrefsFromBuffer(const nsTArray<uint8_t>& aBytes,
4335 nsIPrefObserver* aObserver,
4336 const char* aPathLabel) {
4337 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4337); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 4337; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4338
4339 // We need a null-terminated buffer.
4340 nsTArray<uint8_t> data = aBytes.Clone();
4341 data.AppendElement(0);
4342
4343 // Parsing as default handles both `pref` and `user_pref`.
4344 PrefObserver = aObserver;
4345 prefs_parser_parse(aPathLabel ? aPathLabel : "<ParsePrefsFromBuffer data>",
4346 PrefValueKind::Default, (const char*)data.Elements(),
4347 data.Length() - 1, HandlePref, HandleError);
4348 PrefObserver = nullptr;
4349
4350 return NS_OK;
4351}
4352
4353NS_IMETHODIMPnsresult
4354Preferences::GetUserPrefsFileLastModifiedAtStartup(PRTime* aLastModified) {
4355 *aLastModified = mUserPrefsFileLastModifiedAtStartup;
4356 return NS_OK;
4357}
4358
4359NS_IMETHODIMPnsresult
4360Preferences::GetDirty(bool* aRetVal) {
4361 *aRetVal = mDirty;
4362 return NS_OK;
4363}
4364
4365nsresult Preferences::NotifyServiceObservers(const char* aTopic) {
4366 nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
4367 if (!observerService) {
4368 return NS_ERROR_FAILURE;
4369 }
4370
4371 auto subject = static_cast<nsIPrefService*>(this);
4372 observerService->NotifyObservers(subject, aTopic, nullptr);
4373
4374 return NS_OK;
4375}
4376
4377already_AddRefed<nsIFile> Preferences::ReadSavedPrefs() {
4378 nsCOMPtr<nsIFile> file;
4379 nsresult rv =
4380 NS_GetSpecialDirectory(NS_APP_PREFS_50_FILE"PrefF", getter_AddRefs(file));
4381 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4381)
) {
4382 return nullptr;
4383 }
4384
4385 rv = openPrefFile(file, PrefValueKind::User);
4386 if (rv == NS_ERROR_FILE_NOT_FOUND) {
4387 // This is a normal case for new users.
4388 rv = NS_OK;
Value stored to 'rv' is never read
4389 } else {
4390 // Store the last modified time of the file while we've got it.
4391 // We don't really care if this fails.
4392 Unused << file->GetLastModifiedTime(&mUserPrefsFileLastModifiedAtStartup);
4393
4394 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4395 // Save a backup copy of the current (invalid) prefs file, since all prefs
4396 // from the error line to the end of the file will be lost (bug 361102).
4397 // TODO we should notify the user about it (bug 523725).
4398 Telemetry::ScalarSet(
4399 Telemetry::ScalarID::PREFERENCES_PREFS_FILE_WAS_INVALID, true);
4400 MakeBackupPrefFile(file);
4401 }
4402 }
4403
4404 return file.forget();
4405}
4406
4407void Preferences::ReadUserOverridePrefs() {
4408 nsCOMPtr<nsIFile> aFile;
4409 nsresult rv =
4410 NS_GetSpecialDirectory(NS_APP_PREFS_50_DIR"PrefD", getter_AddRefs(aFile));
4411 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4411)
) {
4412 return;
4413 }
4414
4415 aFile->AppendNative("user.js"_ns);
4416 rv = openPrefFile(aFile, PrefValueKind::User);
4417}
4418
4419nsresult Preferences::MakeBackupPrefFile(nsIFile* aFile) {
4420 // Example: this copies "prefs.js" to "Invalidprefs.js" in the same directory.
4421 // "Invalidprefs.js" is removed if it exists, prior to making the copy.
4422 nsAutoString newFilename;
4423 nsresult rv = aFile->GetLeafName(newFilename);
4424 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4424); return rv; } } while (false)
;
4425
4426 newFilename.InsertLiteral(u"Invalid", 0);
4427 nsCOMPtr<nsIFile> newFile;
4428 rv = aFile->GetParent(getter_AddRefs(newFile));
4429 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4429); return rv; } } while (false)
;
4430
4431 rv = newFile->Append(newFilename);
4432 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4432); return rv; } } while (false)
;
4433
4434 bool exists = false;
4435 newFile->Exists(&exists);
4436 if (exists) {
4437 rv = newFile->Remove(false);
4438 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4438); return rv; } } while (false)
;
4439 }
4440
4441 rv = aFile->CopyTo(nullptr, newFilename);
4442 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4442); return rv; } } while (false)
;
4443
4444 return rv;
4445}
4446
4447nsresult Preferences::SavePrefFileInternal(nsIFile* aFile,
4448 SaveMethod aSaveMethod) {
4449 ENSURE_PARENT_PROCESS("Preferences::SavePrefFileInternal", "all prefs");
4450
4451 // We allow different behavior here when aFile argument is not null, but it
4452 // happens to be the same as the current file. It is not clear that we
4453 // should, but it does give us a "force" save on the unmodified pref file
4454 // (see the original bug 160377 when we added this.)
4455
4456 if (nullptr == aFile) {
4457 mSavePending = false;
4458
4459 // Off main thread writing only if allowed.
4460 if (!AllowOffMainThreadSave()) {
4461 aSaveMethod = SaveMethod::Blocking;
4462 }
4463
4464 // The mDirty flag tells us if we should write to mCurrentFile. We only
4465 // check this flag when the caller wants to write to the default.
4466 if (!mDirty) {
4467 return NS_OK;
4468 }
4469
4470 // Check for profile shutdown after mDirty because the runnables from
4471 // HandleDirty() can still be pending.
4472 if (mProfileShutdown) {
4473 NS_WARNING("Cannot save pref file after profile shutdown.")NS_DebugBreak(NS_DEBUG_WARNING, "Cannot save pref file after profile shutdown."
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4473)
;
4474 return NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
4475 }
4476
4477 // It's possible that we never got a prefs file.
4478 nsresult rv = NS_OK;
4479 if (mCurrentFile) {
4480 rv = WritePrefFile(mCurrentFile, aSaveMethod);
4481 }
4482
4483 // If we succeeded writing to mCurrentFile, reset the dirty flag.
4484 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4485 mDirty = false;
4486 }
4487 return rv;
4488
4489 } else {
4490 // We only allow off main thread writes on mCurrentFile using this method.
4491 // If you want to write asynchronously, use BackupPrefFile instead.
4492 return WritePrefFile(aFile, SaveMethod::Blocking);
4493 }
4494}
4495
4496nsresult Preferences::WritePrefFile(
4497 nsIFile* aFile, SaveMethod aSaveMethod,
4498 UniquePtr<MozPromiseHolder<WritePrefFilePromise>>
4499 aPromiseHolder /* = nullptr */) {
4500 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4500); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 4500; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4501
4502#define REJECT_IF_PROMISE_HOLDER_EXISTS(rv) \
4503 if (aPromiseHolder) { \
4504 aPromiseHolder->RejectIfExists(rv, __func__); \
4505 } \
4506 return rv;
4507
4508 if (!HashTable()) {
4509 REJECT_IF_PROMISE_HOLDER_EXISTS(NS_ERROR_NOT_INITIALIZED);
4510 }
4511
4512 AUTO_PROFILER_LABEL("Preferences::WritePrefFile", OTHER)mozilla::AutoProfilerLabel raiiObject4512( "Preferences::WritePrefFile"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
4513
4514 if (AllowOffMainThreadSave()) {
4515 UniquePtr<PrefSaveData> prefs = MakeUnique<PrefSaveData>(pref_savePrefs());
4516
4517 nsresult rv = NS_OK;
4518 bool writingToCurrent = false;
4519
4520 if (mCurrentFile) {
4521 rv = mCurrentFile->Equals(aFile, &writingToCurrent);
4522 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4523 REJECT_IF_PROMISE_HOLDER_EXISTS(rv);
4524 }
4525 }
4526
4527 // Put the newly constructed preference data into sPendingWriteData
4528 // for the next request to pick up
4529 prefs.reset(PreferencesWriter::sPendingWriteData.exchange(prefs.release()));
4530 if (prefs && !writingToCurrent) {
4531 MOZ_ASSERT(!aPromiseHolder,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aPromiseHolder)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aPromiseHolder))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!aPromiseHolder"
" (" "Shouldn't be able to enter here if aPromiseHolder is set"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4532); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPromiseHolder"
") (" "Shouldn't be able to enter here if aPromiseHolder is set"
")"); do { *((volatile int*)__null) = 4532; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4532 "Shouldn't be able to enter here if aPromiseHolder is set")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aPromiseHolder)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aPromiseHolder))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!aPromiseHolder"
" (" "Shouldn't be able to enter here if aPromiseHolder is set"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4532); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPromiseHolder"
") (" "Shouldn't be able to enter here if aPromiseHolder is set"
")"); do { *((volatile int*)__null) = 4532; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4533 // There was a previous request writing to the default location that
4534 // hasn't been processed. It will do the work of eventually writing this
4535 // latest batch of data to disk.
4536 return NS_OK;
4537 }
4538
4539 // There were no previous requests. Dispatch one since sPendingWriteData has
4540 // the up to date information.
4541 nsCOMPtr<nsIEventTarget> target =
4542 do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID"@mozilla.org/network/stream-transport-service;1", &rv);
4543 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4544 bool async = aSaveMethod == SaveMethod::Asynchronous;
4545
4546 // Increment sPendingWriteCount, even though it's redundant to track this
4547 // in the case of a sync runnable; it just makes it easier to simply
4548 // decrement this inside PWRunnable. We cannot use the constructor /
4549 // destructor for increment/decrement, as on dispatch failure we might
4550 // leak the runnable in order to not destroy it on the wrong thread, which
4551 // would make us get stuck in an infinite SpinEventLoopUntil inside
4552 // PreferencesWriter::Flush. Better that in future code we miss an
4553 // increment of sPendingWriteCount and cause a simple crash due to it
4554 // ending up negative.
4555 //
4556 // If aPromiseHolder is not null, ownership is transferred to PWRunnable.
4557 // The PWRunnable will automatically reject the MozPromise if it is
4558 // destroyed before being resolved or rejected by the Run method.
4559 PreferencesWriter::sPendingWriteCount++;
4560 if (async) {
4561 rv = target->Dispatch(new PWRunnable(aFile, std::move(aPromiseHolder)),
4562 nsIEventTarget::DISPATCH_NORMAL);
4563 } else {
4564 rv = SyncRunnable::DispatchToThread(
4565 target, new PWRunnable(aFile, std::move(aPromiseHolder)), true);
4566 }
4567 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4568 // If our dispatch failed, we should correct our bookkeeping to
4569 // avoid shutdown hangs.
4570 PreferencesWriter::sPendingWriteCount--;
4571 // No need to reject the aPromiseHolder here, as the PWRunnable will
4572 // have already done so.
4573 return rv;
4574 }
4575 return NS_OK;
4576 }
4577
4578 // If we can't get the thread for writing, for whatever reason, do the main
4579 // thread write after making some noise.
4580 MOZ_ASSERT(false, "failed to get the target thread for OMT pref write")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "failed to get the target thread for OMT pref write"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4580); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"failed to get the target thread for OMT pref write" ")"); do
{ *((volatile int*)__null) = 4580; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4581 }
4582
4583 // This will do a main thread write. It is safe to do it this way because
4584 // AllowOffMainThreadSave() returns a consistent value for the lifetime of
4585 // the parent process.
4586 PrefSaveData prefsData = pref_savePrefs();
4587
4588 // If we were given a MozPromiseHolder, this means the caller is attempting
4589 // to write prefs asynchronously to the disk - but if we get here, it means
4590 // that AllowOffMainThreadSave() return false, and that we will be forced
4591 // to write on the main thread instead. We still have to resolve or reject
4592 // that MozPromise regardless.
4593 nsresult rv = PreferencesWriter::Write(aFile, prefsData);
4594 if (aPromiseHolder) {
4595 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Cannot write to prefs asynchronously, as AllowOffMainThreadSave() "
"returned false.", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4597)
4596 "Cannot write to prefs asynchronously, as AllowOffMainThreadSave() "NS_DebugBreak(NS_DEBUG_WARNING, "Cannot write to prefs asynchronously, as AllowOffMainThreadSave() "
"returned false.", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4597)
4597 "returned false.")NS_DebugBreak(NS_DEBUG_WARNING, "Cannot write to prefs asynchronously, as AllowOffMainThreadSave() "
"returned false.", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4597)
;
4598 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4599 aPromiseHolder->ResolveIfExists(true, __func__);
4600 } else {
4601 aPromiseHolder->RejectIfExists(rv, __func__);
4602 }
4603 }
4604 return rv;
4605
4606#undef REJECT_IF_PROMISE_HOLDER_EXISTS
4607}
4608
4609static nsresult openPrefFile(nsIFile* aFile, PrefValueKind aKind) {
4610 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4610); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 4610; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4611
4612 nsCString data;
4613 MOZ_TRY_VAR(data, URLPreloader::ReadFile(aFile))do { auto mozTryVarTempResult_ = (URLPreloader::ReadFile(aFile
)); if ((__builtin_expect(!!(mozTryVarTempResult_.isErr()), 0
))) { return mozTryVarTempResult_.propagateErr(); } (data) = mozTryVarTempResult_
.unwrap(); } while (0)
;
4614
4615 nsAutoString filenameUtf16;
4616 aFile->GetLeafName(filenameUtf16);
4617 NS_ConvertUTF16toUTF8 filename(filenameUtf16);
4618
4619 nsAutoString path;
4620 aFile->GetPath(path);
4621
4622 Parser parser;
4623 if (!parser.Parse(aKind, NS_ConvertUTF16toUTF8(path).get(), data)) {
4624 return NS_ERROR_FILE_CORRUPTED;
4625 }
4626
4627 return NS_OK;
4628}
4629
4630static nsresult parsePrefData(const nsCString& aData, PrefValueKind aKind) {
4631 const nsCString path = "$MOZ_DEFAULT_PREFS"_ns;
4632
4633 Parser parser;
4634 if (!parser.Parse(aKind, path.get(), aData)) {
4635 return NS_ERROR_FILE_CORRUPTED;
4636 }
4637
4638 return NS_OK;
4639}
4640
4641static int pref_CompareFileNames(nsIFile* aFile1, nsIFile* aFile2) {
4642 nsAutoCString filename1, filename2;
4643 aFile1->GetNativeLeafName(filename1);
4644 aFile2->GetNativeLeafName(filename2);
4645
4646 return Compare(filename2, filename1);
4647}
4648
4649// Load default pref files from a directory. The files in the directory are
4650// sorted reverse-alphabetically.
4651static nsresult pref_LoadPrefsInDir(nsIFile* aDir) {
4652 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4652); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 4652; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4653
4654 nsresult rv, rv2;
4655
4656 nsCOMPtr<nsIDirectoryEnumerator> dirIterator;
4657
4658 // This may fail in some normal cases, such as embedders who do not use a
4659 // GRE.
4660 rv = aDir->GetDirectoryEntries(getter_AddRefs(dirIterator));
4661 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4662 // If the directory doesn't exist, then we have no reason to complain. We
4663 // loaded everything (and nothing) successfully.
4664 if (rv == NS_ERROR_FILE_NOT_FOUND) {
4665 rv = NS_OK;
4666 }
4667 return rv;
4668 }
4669
4670 nsCOMArray<nsIFile> prefFiles(INITIAL_PREF_FILES10);
4671 nsCOMPtr<nsIFile> prefFile;
4672
4673 while (NS_SUCCEEDED(dirIterator->GetNextFile(getter_AddRefs(prefFile)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(dirIterator->GetNextFile
(getter_AddRefs(prefFile)))), 1)))
&&
4674 prefFile) {
4675 nsAutoCString leafName;
4676 prefFile->GetNativeLeafName(leafName);
4677 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!leafName.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!leafName.IsEmpty()))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!leafName.IsEmpty()"
" (" "Failure in default prefs: directory enumerator returned empty file?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4679); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!leafName.IsEmpty()"
") (" "Failure in default prefs: directory enumerator returned empty file?"
")"); do { *((volatile int*)__null) = 4679; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4678 !leafName.IsEmpty(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!leafName.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!leafName.IsEmpty()))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!leafName.IsEmpty()"
" (" "Failure in default prefs: directory enumerator returned empty file?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4679); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!leafName.IsEmpty()"
") (" "Failure in default prefs: directory enumerator returned empty file?"
")"); do { *((volatile int*)__null) = 4679; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4679 "Failure in default prefs: directory enumerator returned empty file?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!leafName.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!leafName.IsEmpty()))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!leafName.IsEmpty()"
" (" "Failure in default prefs: directory enumerator returned empty file?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4679); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!leafName.IsEmpty()"
") (" "Failure in default prefs: directory enumerator returned empty file?"
")"); do { *((volatile int*)__null) = 4679; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4680
4681 // Skip non-js files.
4682 if (StringEndsWith(leafName, ".js"_ns,
4683 nsCaseInsensitiveCStringComparator)) {
4684 prefFiles.AppendObject(prefFile);
4685 }
4686 }
4687
4688 if (prefFiles.Count() == 0) {
4689 NS_WARNING("No default pref files found.")NS_DebugBreak(NS_DEBUG_WARNING, "No default pref files found."
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4689)
;
4690 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4691 rv = NS_SUCCESS_FILE_DIRECTORY_EMPTY;
4692 }
4693 return rv;
4694 }
4695
4696 prefFiles.Sort(pref_CompareFileNames);
4697
4698 uint32_t arrayCount = prefFiles.Count();
4699 uint32_t i;
4700 for (i = 0; i < arrayCount; ++i) {
4701 rv2 = openPrefFile(prefFiles[i], PrefValueKind::Default);
4702 if (NS_FAILED(rv2)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv2)), 0)))) {
4703 NS_ERROR("Default pref file not parsed successfully.")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Default pref file not parsed successfully."
, "Error", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4703); MOZ_PretendNoReturn(); } while (0)
;
4704 rv = rv2;
4705 }
4706 }
4707
4708 return rv;
4709}
4710
4711static nsresult pref_ReadPrefFromJar(nsZipArchive* aJarReader,
4712 const char* aName) {
4713 nsCString manifest;
4714 MOZ_TRY_VAR(manifest,do { auto mozTryVarTempResult_ = (URLPreloader::ReadZip(aJarReader
, nsDependentCString(aName))); if ((__builtin_expect(!!(mozTryVarTempResult_
.isErr()), 0))) { return mozTryVarTempResult_.propagateErr();
} (manifest) = mozTryVarTempResult_.unwrap(); } while (0)
4715 URLPreloader::ReadZip(aJarReader, nsDependentCString(aName)))do { auto mozTryVarTempResult_ = (URLPreloader::ReadZip(aJarReader
, nsDependentCString(aName))); if ((__builtin_expect(!!(mozTryVarTempResult_
.isErr()), 0))) { return mozTryVarTempResult_.propagateErr();
} (manifest) = mozTryVarTempResult_.unwrap(); } while (0)
;
4716
4717 Parser parser;
4718 if (!parser.Parse(PrefValueKind::Default, aName, manifest)) {
4719 return NS_ERROR_FILE_CORRUPTED;
4720 }
4721
4722 return NS_OK;
4723}
4724
4725static nsresult pref_ReadDefaultPrefs(const RefPtr<nsZipArchive> jarReader,
4726 const char* path) {
4727 UniquePtr<nsZipFind> find;
4728 nsTArray<nsCString> prefEntries;
4729 const char* entryName;
4730 uint16_t entryNameLen;
4731
4732 nsresult rv = jarReader->FindInit(path, getter_Transfers(find));
4733 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4733); return rv; } } while (false)
;
4734
4735 while (NS_SUCCEEDED(find->FindNext(&entryName, &entryNameLen))((bool)(__builtin_expect(!!(!NS_FAILED_impl(find->FindNext
(&entryName, &entryNameLen))), 1)))
) {
4736 prefEntries.AppendElement(Substring(entryName, entryNameLen));
4737 }
4738
4739 prefEntries.Sort();
4740 for (uint32_t i = prefEntries.Length(); i--;) {
4741 rv = pref_ReadPrefFromJar(jarReader, prefEntries[i].get());
4742 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4743 NS_WARNING("Error parsing preferences.")NS_DebugBreak(NS_DEBUG_WARNING, "Error parsing preferences.",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4743)
;
4744 }
4745 }
4746
4747 return NS_OK;
4748}
4749
4750static nsCString PrefValueToString(const bool* b) {
4751 return nsCString(*b ? "true" : "false");
4752}
4753static nsCString PrefValueToString(const int* i) {
4754 return nsPrintfCString("%d", *i);
4755}
4756static nsCString PrefValueToString(const uint32_t* u) {
4757 return nsPrintfCString("%d", *u);
4758}
4759static nsCString PrefValueToString(const float* f) {
4760 return nsPrintfCString("%f", *f);
4761}
4762static nsCString PrefValueToString(const nsACString* s) {
4763 return nsCString(*s);
4764}
4765static nsCString PrefValueToString(const nsACString& s) { return nsCString(s); }
4766
4767// These preference getter wrappers allow us to look up the value for static
4768// preferences based on their native types, rather than manually mapping them to
4769// the appropriate Preferences::Get* functions.
4770// We define these methods in a struct which is made friend of Preferences in
4771// order to access private members.
4772struct Internals {
4773 template <typename T>
4774 static nsresult GetPrefValue(const char* aPrefName, T&& aResult,
4775 PrefValueKind aKind) {
4776 nsresult rv = NS_ERROR_UNEXPECTED;
4777 NS_ENSURE_TRUE(Preferences::InitStaticMembers(), NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(Preferences::InitStaticMembers
())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"Preferences::InitStaticMembers()" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4777); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
4778
4779 if (Maybe<PrefWrapper> pref = pref_Lookup(aPrefName)) {
4780 rv = pref->GetValue(aKind, std::forward<T>(aResult));
4781
4782 if (profiler_thread_is_being_profiled_for_markers()) {
4783 profiler_add_marker(do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Preference Read", baseprofiler::category::OTHER_PreferenceRead
, {}, PreferenceMarker{}, ProfilerString8View::WrapNullTerminatedString
(aPrefName), Some(aKind), pref->Type(), PrefValueToString(
aResult)); } } while (false)
4784 "Preference Read", baseprofiler::category::OTHER_PreferenceRead, {},do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Preference Read", baseprofiler::category::OTHER_PreferenceRead
, {}, PreferenceMarker{}, ProfilerString8View::WrapNullTerminatedString
(aPrefName), Some(aKind), pref->Type(), PrefValueToString(
aResult)); } } while (false)
4785 PreferenceMarker{},do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Preference Read", baseprofiler::category::OTHER_PreferenceRead
, {}, PreferenceMarker{}, ProfilerString8View::WrapNullTerminatedString
(aPrefName), Some(aKind), pref->Type(), PrefValueToString(
aResult)); } } while (false)
4786 ProfilerString8View::WrapNullTerminatedString(aPrefName),do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Preference Read", baseprofiler::category::OTHER_PreferenceRead
, {}, PreferenceMarker{}, ProfilerString8View::WrapNullTerminatedString
(aPrefName), Some(aKind), pref->Type(), PrefValueToString(
aResult)); } } while (false)
4787 Some(aKind), pref->Type(), PrefValueToString(aResult))do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Preference Read", baseprofiler::category::OTHER_PreferenceRead
, {}, PreferenceMarker{}, ProfilerString8View::WrapNullTerminatedString
(aPrefName), Some(aKind), pref->Type(), PrefValueToString(
aResult)); } } while (false)
;
4788 }
4789 }
4790
4791 return rv;
4792 }
4793
4794 template <typename T>
4795 static nsresult GetSharedPrefValue(const char* aName, T* aResult) {
4796 nsresult rv = NS_ERROR_UNEXPECTED;
4797
4798 if (Maybe<PrefWrapper> pref = pref_SharedLookup(aName)) {
4799 rv = pref->GetValue(PrefValueKind::User, aResult);
4800
4801 if (profiler_thread_is_being_profiled_for_markers()) {
4802 profiler_add_marker(do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Preference Read", baseprofiler::category::OTHER_PreferenceRead
, {}, PreferenceMarker{}, ProfilerString8View::WrapNullTerminatedString
(aName), Nothing() , pref->Type(), PrefValueToString(aResult
)); } } while (false)
4803 "Preference Read", baseprofiler::category::OTHER_PreferenceRead, {},do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Preference Read", baseprofiler::category::OTHER_PreferenceRead
, {}, PreferenceMarker{}, ProfilerString8View::WrapNullTerminatedString
(aName), Nothing() , pref->Type(), PrefValueToString(aResult
)); } } while (false)
4804 PreferenceMarker{},do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Preference Read", baseprofiler::category::OTHER_PreferenceRead
, {}, PreferenceMarker{}, ProfilerString8View::WrapNullTerminatedString
(aName), Nothing() , pref->Type(), PrefValueToString(aResult
)); } } while (false)
4805 ProfilerString8View::WrapNullTerminatedString(aName),do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Preference Read", baseprofiler::category::OTHER_PreferenceRead
, {}, PreferenceMarker{}, ProfilerString8View::WrapNullTerminatedString
(aName), Nothing() , pref->Type(), PrefValueToString(aResult
)); } } while (false)
4806 Nothing() /* indicates Shared */, pref->Type(),do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Preference Read", baseprofiler::category::OTHER_PreferenceRead
, {}, PreferenceMarker{}, ProfilerString8View::WrapNullTerminatedString
(aName), Nothing() , pref->Type(), PrefValueToString(aResult
)); } } while (false)
4807 PrefValueToString(aResult))do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Preference Read", baseprofiler::category::OTHER_PreferenceRead
, {}, PreferenceMarker{}, ProfilerString8View::WrapNullTerminatedString
(aName), Nothing() , pref->Type(), PrefValueToString(aResult
)); } } while (false)
;
4808 }
4809 }
4810
4811 return rv;
4812 }
4813
4814 template <typename T>
4815 static T GetPref(const char* aPrefName, T aFallback,
4816 PrefValueKind aKind = PrefValueKind::User) {
4817 T result = aFallback;
4818 GetPrefValue(aPrefName, &result, aKind);
4819 return result;
4820 }
4821
4822 template <typename T, typename V>
4823 static void MOZ_NEVER_INLINE__attribute__((noinline)) AssignMirror(T& aMirror, V aValue) {
4824 aMirror = aValue;
4825 }
4826
4827 static void MOZ_NEVER_INLINE__attribute__((noinline)) AssignMirror(DataMutexString& aMirror,
4828 nsCString&& aValue) {
4829 auto lock = aMirror.Lock();
4830 lock->Assign(std::move(aValue));
4831 }
4832
4833 static void MOZ_NEVER_INLINE__attribute__((noinline)) AssignMirror(DataMutexString& aMirror,
4834 const nsLiteralCString& aValue) {
4835 auto lock = aMirror.Lock();
4836 lock->Assign(aValue);
4837 }
4838
4839 static void ClearMirror(DataMutexString& aMirror) {
4840 auto lock = aMirror.Lock();
4841 lock->Assign(nsCString());
4842 }
4843
4844 template <typename T>
4845 static void UpdateMirror(const char* aPref, void* aMirror) {
4846 StripAtomic<T> value;
4847
4848 nsresult rv = GetPrefValue(aPref, &value, PrefValueKind::User);
4849 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4850 AssignMirror(*static_cast<T*>(aMirror),
4851 std::forward<StripAtomic<T>>(value));
4852 } else {
4853 // GetPrefValue() can fail if the update is caused by the pref being
4854 // deleted or if it fails to make a cast. This assertion is the only place
4855 // where we safeguard these. In this case the mirror variable will be
4856 // untouched, thus keeping the value it had prior to the change.
4857 // (Note that this case won't happen for a deletion via DeleteBranch()
4858 // unless bug 343600 is fixed, but it will happen for a deletion via
4859 // ClearUserPref().)
4860 NS_WARNING(nsPrintfCString("Pref changed failure: %s\n", aPref).get())NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString("Pref changed failure: %s\n"
, aPref).get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4860)
;
4861 MOZ_ASSERT(false)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4861); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ")")
; do { *((volatile int*)__null) = 4861; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4862 }
4863 }
4864
4865 template <typename T>
4866 static nsresult RegisterCallback(void* aMirror, const nsACString& aPref) {
4867 return Preferences::RegisterCallback(UpdateMirror<T>, aPref, aMirror,
4868 Preferences::ExactMatch,
4869 /* isPriority */ true);
4870 }
4871};
4872
4873// Initialize default preference JavaScript buffers from appropriate TEXT
4874// resources.
4875/* static */
4876nsresult Preferences::InitInitialObjects(bool aIsStartup) {
4877 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4877); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 4877; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4878
4879 if (!XRE_IsParentProcess()) {
4880 MOZ_DIAGNOSTIC_ASSERT(gSharedMap)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(gSharedMap)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(gSharedMap))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("gSharedMap", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4880); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "gSharedMap"
")"); do { *((volatile int*)__null) = 4880; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4881 if (aIsStartup) {
4882 StaticPrefs::StartObservingAlwaysPrefs();
4883 }
4884 return NS_OK;
4885 }
4886
4887 // Initialize static prefs before prefs from data files so that the latter
4888 // will override the former.
4889 StaticPrefs::InitAll();
4890
4891 // In the omni.jar case, we load the following prefs:
4892 // - jar:$gre/omni.jar!/greprefs.js
4893 // - jar:$gre/omni.jar!/defaults/pref/*.js
4894 //
4895 // In the non-omni.jar case, we load:
4896 // - $gre/greprefs.js
4897 //
4898 // In both cases, we also load:
4899 // - $gre/defaults/pref/*.js
4900 //
4901 // This is kept for bug 591866 (channel-prefs.js should not be in omni.jar)
4902 // in the `$app == $gre` case; we load all files instead of channel-prefs.js
4903 // only to have the same behaviour as `$app != $gre`, where this is required
4904 // as a supported location for GRE preferences.
4905 //
4906 // When `$app != $gre`, we additionally load, in the omni.jar case:
4907 // - jar:$app/omni.jar!/defaults/preferences/*.js
4908 // - $app/defaults/preferences/*.js
4909 //
4910 // and in the non-omni.jar case:
4911 // - $app/defaults/preferences/*.js
4912 //
4913 // When `$app == $gre`, we additionally load, in the omni.jar case:
4914 // - jar:$gre/omni.jar!/defaults/preferences/*.js
4915 //
4916 // Thus, in the omni.jar case, we always load app-specific default
4917 // preferences from omni.jar, whether or not `$app == $gre`.
4918
4919 nsresult rv = NS_ERROR_FAILURE;
4920 UniquePtr<nsZipFind> find;
4921 nsTArray<nsCString> prefEntries;
4922 const char* entryName;
4923 uint16_t entryNameLen;
4924
4925 RefPtr<nsZipArchive> jarReader = Omnijar::GetReader(Omnijar::GRE);
4926 if (jarReader) {
4927#ifdef MOZ_WIDGET_ANDROID
4928 // Try to load an architecture-specific greprefs.js first. This will be
4929 // present in FAT AAR builds of GeckoView on Android.
4930 const char* abi = getenv("MOZ_ANDROID_CPU_ABI");
4931 if (abi) {
4932 nsAutoCString path;
4933 path.AppendPrintf("%s/greprefs.js", abi);
4934 rv = pref_ReadPrefFromJar(jarReader, path.get());
4935 }
4936
4937 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4938 // Fallback to toplevel greprefs.js if arch-specific load fails.
4939 rv = pref_ReadPrefFromJar(jarReader, "greprefs.js");
4940 }
4941#else
4942 // Load jar:$gre/omni.jar!/greprefs.js.
4943 rv = pref_ReadPrefFromJar(jarReader, "greprefs.js");
4944#endif
4945 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4945); return rv; } } while (false)
;
4946
4947 // Load jar:$gre/omni.jar!/defaults/pref/*.js.
4948 rv = pref_ReadDefaultPrefs(jarReader, "defaults/pref/*.js$");
4949 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4949); return rv; } } while (false)
;
4950
4951#ifdef MOZ_BACKGROUNDTASKS1
4952 if (BackgroundTasks::IsBackgroundTaskMode()) {
4953 rv = pref_ReadDefaultPrefs(jarReader, "defaults/backgroundtasks/*.js$");
4954 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4954); return rv; } } while (false)
;
4955 }
4956#endif
4957
4958#ifdef MOZ_WIDGET_ANDROID
4959 // Load jar:$gre/omni.jar!/defaults/pref/$MOZ_ANDROID_CPU_ABI/*.js.
4960 nsAutoCString path;
4961 path.AppendPrintf("jar:$gre/omni.jar!/defaults/pref/%s/*.js$", abi);
4962 pref_ReadDefaultPrefs(jarReader, path.get());
4963 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4963); return rv; } } while (false)
;
4964#endif
4965 } else {
4966 // Load $gre/greprefs.js.
4967 nsCOMPtr<nsIFile> greprefsFile;
4968 rv = NS_GetSpecialDirectory(NS_GRE_DIR"GreD", getter_AddRefs(greprefsFile));
4969 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4969); return rv; } } while (false)
;
4970
4971 rv = greprefsFile->AppendNative("greprefs.js"_ns);
4972 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4972); return rv; } } while (false)
;
4973
4974 rv = openPrefFile(greprefsFile, PrefValueKind::Default);
4975 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4976 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Error parsing GRE default preferences. Is this an old-style "
"embedding app?", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4978)
4977 "Error parsing GRE default preferences. Is this an old-style "NS_DebugBreak(NS_DEBUG_WARNING, "Error parsing GRE default preferences. Is this an old-style "
"embedding app?", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4978)
4978 "embedding app?")NS_DebugBreak(NS_DEBUG_WARNING, "Error parsing GRE default preferences. Is this an old-style "
"embedding app?", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4978)
;
4979 }
4980 }
4981
4982 // Load $gre/defaults/pref/*.js.
4983 nsCOMPtr<nsIFile> defaultPrefDir;
4984 rv = NS_GetSpecialDirectory(NS_APP_PREF_DEFAULTS_50_DIR"PrfDef",
4985 getter_AddRefs(defaultPrefDir));
4986 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4986); return rv; } } while (false)
;
4987
4988 rv = pref_LoadPrefsInDir(defaultPrefDir);
4989 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4990 NS_WARNING("Error parsing application default preferences.")NS_DebugBreak(NS_DEBUG_WARNING, "Error parsing application default preferences."
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 4990)
;
4991 }
4992
4993#ifdef MOZ_WIDGET_COCOA
4994 // On macOS, channel-prefs.js is no longer bundled with the application and
4995 // the "app.update.channel" pref is now read from a Framework instead.
4996 // Previously, channel-prefs.js was read as one of the files in
4997 // NS_APP_PREF_DEFAULTS_50_DIR (see just above). See bug 1799332 for more
4998 // info.
4999 nsAutoCString appUpdatePrefKey;
5000 appUpdatePrefKey.Assign(kChannelPref);
5001 nsAutoCString appUpdatePrefValue;
5002 PrefValue channelPrefValue;
5003 channelPrefValue.mStringVal = MOZ_STRINGIFY(MOZ_UPDATE_CHANNEL)"default";
5004 if (ChannelPrefsUtil::GetChannelPrefValue(appUpdatePrefValue)) {
5005 channelPrefValue.mStringVal = appUpdatePrefValue.get();
5006 }
5007 pref_SetPref(appUpdatePrefKey, PrefType::String, PrefValueKind::Default,
5008 channelPrefValue,
5009 /* isSticky */ false,
5010 /* isLocked */ true,
5011 /* fromInit */ true);
5012#endif
5013
5014 // Load jar:$app/omni.jar!/defaults/preferences/*.js
5015 // or jar:$gre/omni.jar!/defaults/preferences/*.js.
5016 RefPtr<nsZipArchive> appJarReader = Omnijar::GetReader(Omnijar::APP);
5017
5018 // GetReader(Omnijar::APP) returns null when `$app == $gre`, in
5019 // which case we look for app-specific default preferences in $gre.
5020 if (!appJarReader) {
5021 appJarReader = Omnijar::GetReader(Omnijar::GRE);
5022 }
5023
5024 if (appJarReader) {
5025 rv = appJarReader->FindInit("defaults/preferences/*.js$",
5026 getter_Transfers(find));
5027 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5027); return rv; } } while (false)
;
5028 prefEntries.Clear();
5029 while (NS_SUCCEEDED(find->FindNext(&entryName, &entryNameLen))((bool)(__builtin_expect(!!(!NS_FAILED_impl(find->FindNext
(&entryName, &entryNameLen))), 1)))
) {
5030 prefEntries.AppendElement(Substring(entryName, entryNameLen));
5031 }
5032 prefEntries.Sort();
5033 for (uint32_t i = prefEntries.Length(); i--;) {
5034 rv = pref_ReadPrefFromJar(appJarReader, prefEntries[i].get());
5035 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5036 NS_WARNING("Error parsing preferences.")NS_DebugBreak(NS_DEBUG_WARNING, "Error parsing preferences.",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5036)
;
5037 }
5038 }
5039
5040#ifdef MOZ_BACKGROUNDTASKS1
5041 if (BackgroundTasks::IsBackgroundTaskMode()) {
5042 rv = appJarReader->FindInit("defaults/backgroundtasks/*.js$",
5043 getter_Transfers(find));
5044 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5044); return rv; } } while (false)
;
5045 prefEntries.Clear();
5046 while (NS_SUCCEEDED(find->FindNext(&entryName, &entryNameLen))((bool)(__builtin_expect(!!(!NS_FAILED_impl(find->FindNext
(&entryName, &entryNameLen))), 1)))
) {
5047 prefEntries.AppendElement(Substring(entryName, entryNameLen));
5048 }
5049 prefEntries.Sort();
5050 for (uint32_t i = prefEntries.Length(); i--;) {
5051 rv = pref_ReadPrefFromJar(appJarReader, prefEntries[i].get());
5052 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5053 NS_WARNING("Error parsing preferences.")NS_DebugBreak(NS_DEBUG_WARNING, "Error parsing preferences.",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5053)
;
5054 }
5055 }
5056 }
5057#endif
5058 }
5059
5060 nsCOMPtr<nsIProperties> dirSvc(
5061 do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID"@mozilla.org/file/directory_service;1", &rv));
5062 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5062); return rv; } } while (false)
;
5063
5064 nsCOMPtr<nsISimpleEnumerator> list;
5065 dirSvc->Get(NS_APP_PREFS_DEFAULTS_DIR_LIST"PrefDL", NS_GET_IID(nsISimpleEnumerator)(nsISimpleEnumerator::COMTypeInfo<nsISimpleEnumerator, void
>::kIID)
,
5066 getter_AddRefs(list));
5067 if (list) {
5068 bool hasMore;
5069 while (NS_SUCCEEDED(list->HasMoreElements(&hasMore))((bool)(__builtin_expect(!!(!NS_FAILED_impl(list->HasMoreElements
(&hasMore))), 1)))
&& hasMore) {
5070 nsCOMPtr<nsISupports> elem;
5071 list->GetNext(getter_AddRefs(elem));
5072 if (!elem) {
5073 continue;
5074 }
5075
5076 nsCOMPtr<nsIFile> path = do_QueryInterface(elem);
5077 if (!path) {
5078 continue;
5079 }
5080
5081 // Do we care if a file provided by this process fails to load?
5082 pref_LoadPrefsInDir(path);
5083 }
5084 }
5085
5086#if defined(MOZ_WIDGET_GTK1)
5087 // To ensure the system-wide preferences are not overwritten by
5088 // firefox/browser/defauts/preferences/*.js we need to load
5089 // the /etc/firefox/defaults/pref/*.js settings as last.
5090 // Under Flatpak, the NS_OS_SYSTEM_CONFIG_DIR points to /app/etc/firefox
5091 nsCOMPtr<nsIFile> defaultSystemPrefDir;
5092 rv = NS_GetSpecialDirectory(NS_OS_SYSTEM_CONFIG_DIR"SysConfD",
5093 getter_AddRefs(defaultSystemPrefDir));
5094 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5094); return rv; } } while (false)
;
5095 defaultSystemPrefDir->AppendNative("defaults"_ns);
5096 defaultSystemPrefDir->AppendNative("pref"_ns);
5097
5098 rv = pref_LoadPrefsInDir(defaultSystemPrefDir);
5099 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5100 NS_WARNING("Error parsing application default preferences.")NS_DebugBreak(NS_DEBUG_WARNING, "Error parsing application default preferences."
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5100)
;
5101 }
5102#endif
5103
5104 if (XRE_IsParentProcess()) {
5105 SetupTelemetryPref();
5106 }
5107
5108 if (aIsStartup) {
5109 // Now that all prefs have their initial values, install the callbacks for
5110 // `always`-mirrored static prefs. We do this now rather than in
5111 // StaticPrefs::InitAll() so that the callbacks don't need to be traversed
5112 // while we load prefs from data files.
5113 StaticPrefs::StartObservingAlwaysPrefs();
5114 }
5115
5116 NS_CreateServicesFromCategory(NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID"prefservice:after-app-defaults", nullptr,
5117 NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID"prefservice:after-app-defaults");
5118
5119 nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
5120 if (NS_WARN_IF(!observerService)NS_warn_if_impl(!observerService, "!observerService", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5120)
) {
5121 return NS_ERROR_FAILURE;
5122 }
5123
5124 observerService->NotifyObservers(nullptr, NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID"prefservice:after-app-defaults",
5125 nullptr);
5126
5127 return NS_OK;
5128}
5129
5130/* static */
5131nsresult Preferences::GetBool(const char* aPrefName, bool* aResult,
5132 PrefValueKind aKind) {
5133 MOZ_ASSERT(aResult)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aResult)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aResult))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aResult", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5133); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aResult" ")"
); do { *((volatile int*)__null) = 5133; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5134 return Internals::GetPrefValue(aPrefName, aResult, aKind);
5135}
5136
5137/* static */
5138nsresult Preferences::GetInt(const char* aPrefName, int32_t* aResult,
5139 PrefValueKind aKind) {
5140 MOZ_ASSERT(aResult)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aResult)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aResult))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aResult", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5140); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aResult" ")"
); do { *((volatile int*)__null) = 5140; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5141 return Internals::GetPrefValue(aPrefName, aResult, aKind);
5142}
5143
5144/* static */
5145nsresult Preferences::GetFloat(const char* aPrefName, float* aResult,
5146 PrefValueKind aKind) {
5147 MOZ_ASSERT(aResult)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aResult)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aResult))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aResult", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5147); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aResult" ")"
); do { *((volatile int*)__null) = 5147; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5148 return Internals::GetPrefValue(aPrefName, aResult, aKind);
5149}
5150
5151/* static */
5152nsresult Preferences::GetCString(const char* aPrefName, nsACString& aResult,
5153 PrefValueKind aKind) {
5154 aResult.SetIsVoid(true);
5155 return Internals::GetPrefValue(aPrefName, aResult, aKind);
5156}
5157
5158/* static */
5159nsresult Preferences::GetString(const char* aPrefName, nsAString& aResult,
5160 PrefValueKind aKind) {
5161 nsAutoCString result;
5162 nsresult rv = Preferences::GetCString(aPrefName, result, aKind);
5163 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5164 CopyUTF8toUTF16(result, aResult);
5165 }
5166 return rv;
5167}
5168
5169/* static */
5170nsresult Preferences::GetLocalizedCString(const char* aPrefName,
5171 nsACString& aResult,
5172 PrefValueKind aKind) {
5173 nsAutoString result;
5174 nsresult rv = GetLocalizedString(aPrefName, result, aKind);
5175 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5176 CopyUTF16toUTF8(result, aResult);
5177 }
5178 return rv;
5179}
5180
5181/* static */
5182nsresult Preferences::GetLocalizedString(const char* aPrefName,
5183 nsAString& aResult,
5184 PrefValueKind aKind) {
5185 NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(InitStaticMembers())), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "InitStaticMembers()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5185); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
5186 nsCOMPtr<nsIPrefLocalizedString> prefLocalString;
5187 nsresult rv = GetRootBranch(aKind)->GetComplexValue(
5188 aPrefName, NS_GET_IID(nsIPrefLocalizedString)(nsIPrefLocalizedString::COMTypeInfo<nsIPrefLocalizedString
, void>::kIID)
,
5189 getter_AddRefs(prefLocalString));
5190 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5191 MOZ_ASSERT(prefLocalString, "Succeeded but the result is NULL")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(prefLocalString)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(prefLocalString))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("prefLocalString"
" (" "Succeeded but the result is NULL" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5191); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prefLocalString"
") (" "Succeeded but the result is NULL" ")"); do { *((volatile
int*)__null) = 5191; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5192 prefLocalString->GetData(aResult);
5193 }
5194 return rv;
5195}
5196
5197/* static */
5198nsresult Preferences::GetComplex(const char* aPrefName, const nsIID& aType,
5199 void** aResult, PrefValueKind aKind) {
5200 NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(InitStaticMembers())), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "InitStaticMembers()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5200); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
5201 return GetRootBranch(aKind)->GetComplexValue(aPrefName, aType, aResult);
5202}
5203
5204/* static */
5205bool Preferences::GetBool(const char* aPrefName, bool aFallback,
5206 PrefValueKind aKind) {
5207 return Internals::GetPref(aPrefName, aFallback, aKind);
5208}
5209
5210/* static */
5211int32_t Preferences::GetInt(const char* aPrefName, int32_t aFallback,
5212 PrefValueKind aKind) {
5213 return Internals::GetPref(aPrefName, aFallback, aKind);
5214}
5215
5216/* static */
5217uint32_t Preferences::GetUint(const char* aPrefName, uint32_t aFallback,
5218 PrefValueKind aKind) {
5219 return Internals::GetPref(aPrefName, aFallback, aKind);
5220}
5221
5222/* static */
5223float Preferences::GetFloat(const char* aPrefName, float aFallback,
5224 PrefValueKind aKind) {
5225 return Internals::GetPref(aPrefName, aFallback, aKind);
5226}
5227
5228/* static */
5229nsresult Preferences::SetCString(const char* aPrefName,
5230 const nsACString& aValue,
5231 PrefValueKind aKind) {
5232 ENSURE_PARENT_PROCESS("SetCString", aPrefName);
5233 NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(InitStaticMembers())), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "InitStaticMembers()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5233); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
5234
5235 if (aValue.Length() > MAX_PREF_LENGTH) {
5236 return NS_ERROR_ILLEGAL_VALUE;
5237 }
5238
5239 // It's ok to stash a pointer to the temporary PromiseFlatCString's chars in
5240 // pref because pref_SetPref() duplicates those chars.
5241 PrefValue prefValue;
5242 const nsCString& flat = PromiseFlatCStringTPromiseFlatString<char>(aValue);
5243 prefValue.mStringVal = flat.get();
5244 return pref_SetPref(nsDependentCString(aPrefName), PrefType::String, aKind,
5245 prefValue,
5246 /* isSticky */ false,
5247 /* isLocked */ false,
5248 /* fromInit */ false);
5249}
5250
5251/* static */
5252nsresult Preferences::SetBool(const char* aPrefName, bool aValue,
5253 PrefValueKind aKind) {
5254 ENSURE_PARENT_PROCESS("SetBool", aPrefName);
5255 NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(InitStaticMembers())), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "InitStaticMembers()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5255); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
5256
5257 PrefValue prefValue;
5258 prefValue.mBoolVal = aValue;
5259 return pref_SetPref(nsDependentCString(aPrefName), PrefType::Bool, aKind,
5260 prefValue,
5261 /* isSticky */ false,
5262 /* isLocked */ false,
5263 /* fromInit */ false);
5264}
5265
5266/* static */
5267nsresult Preferences::SetInt(const char* aPrefName, int32_t aValue,
5268 PrefValueKind aKind) {
5269 ENSURE_PARENT_PROCESS("SetInt", aPrefName);
5270 NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(InitStaticMembers())), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "InitStaticMembers()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5270); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
5271
5272 PrefValue prefValue;
5273 prefValue.mIntVal = aValue;
5274 return pref_SetPref(nsDependentCString(aPrefName), PrefType::Int, aKind,
5275 prefValue,
5276 /* isSticky */ false,
5277 /* isLocked */ false,
5278 /* fromInit */ false);
5279}
5280
5281/* static */
5282nsresult Preferences::SetComplex(const char* aPrefName, const nsIID& aType,
5283 nsISupports* aValue, PrefValueKind aKind) {
5284 NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(InitStaticMembers())), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "InitStaticMembers()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5284); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
5285 return GetRootBranch(aKind)->SetComplexValue(aPrefName, aType, aValue);
5286}
5287
5288/* static */
5289nsresult Preferences::Lock(const char* aPrefName) {
5290 ENSURE_PARENT_PROCESS("Lock", aPrefName);
5291 NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(InitStaticMembers())), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "InitStaticMembers()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5291); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
5292
5293 const auto& prefName = nsDependentCString(aPrefName);
5294
5295 Pref* pref;
5296 MOZ_TRY_VAR(pref,do { auto mozTryVarTempResult_ = (pref_LookupForModify(prefName
, [](const PrefWrapper& aPref) { return !aPref.IsLocked()
; })); if ((__builtin_expect(!!(mozTryVarTempResult_.isErr())
, 0))) { return mozTryVarTempResult_.propagateErr(); } (pref)
= mozTryVarTempResult_.unwrap(); } while (0)
5297 pref_LookupForModify(prefName, [](const PrefWrapper& aPref) {do { auto mozTryVarTempResult_ = (pref_LookupForModify(prefName
, [](const PrefWrapper& aPref) { return !aPref.IsLocked()
; })); if ((__builtin_expect(!!(mozTryVarTempResult_.isErr())
, 0))) { return mozTryVarTempResult_.propagateErr(); } (pref)
= mozTryVarTempResult_.unwrap(); } while (0)
5298 return !aPref.IsLocked();do { auto mozTryVarTempResult_ = (pref_LookupForModify(prefName
, [](const PrefWrapper& aPref) { return !aPref.IsLocked()
; })); if ((__builtin_expect(!!(mozTryVarTempResult_.isErr())
, 0))) { return mozTryVarTempResult_.propagateErr(); } (pref)
= mozTryVarTempResult_.unwrap(); } while (0)
5299 }))do { auto mozTryVarTempResult_ = (pref_LookupForModify(prefName
, [](const PrefWrapper& aPref) { return !aPref.IsLocked()
; })); if ((__builtin_expect(!!(mozTryVarTempResult_.isErr())
, 0))) { return mozTryVarTempResult_.propagateErr(); } (pref)
= mozTryVarTempResult_.unwrap(); } while (0)
;
5300
5301 if (pref) {
5302 pref->SetIsLocked(true);
5303 NotifyCallbacks(prefName, PrefWrapper(pref));
5304 }
5305
5306 return NS_OK;
5307}
5308
5309/* static */
5310nsresult Preferences::Unlock(const char* aPrefName) {
5311 ENSURE_PARENT_PROCESS("Unlock", aPrefName);
5312 NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(InitStaticMembers())), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "InitStaticMembers()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5312); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
5313
5314 const auto& prefName = nsDependentCString(aPrefName);
5315
5316 Pref* pref;
5317 MOZ_TRY_VAR(pref,do { auto mozTryVarTempResult_ = (pref_LookupForModify(prefName
, [](const PrefWrapper& aPref) { return aPref.IsLocked();
})); if ((__builtin_expect(!!(mozTryVarTempResult_.isErr()),
0))) { return mozTryVarTempResult_.propagateErr(); } (pref) =
mozTryVarTempResult_.unwrap(); } while (0)
5318 pref_LookupForModify(prefName, [](const PrefWrapper& aPref) {do { auto mozTryVarTempResult_ = (pref_LookupForModify(prefName
, [](const PrefWrapper& aPref) { return aPref.IsLocked();
})); if ((__builtin_expect(!!(mozTryVarTempResult_.isErr()),
0))) { return mozTryVarTempResult_.propagateErr(); } (pref) =
mozTryVarTempResult_.unwrap(); } while (0)
5319 return aPref.IsLocked();do { auto mozTryVarTempResult_ = (pref_LookupForModify(prefName
, [](const PrefWrapper& aPref) { return aPref.IsLocked();
})); if ((__builtin_expect(!!(mozTryVarTempResult_.isErr()),
0))) { return mozTryVarTempResult_.propagateErr(); } (pref) =
mozTryVarTempResult_.unwrap(); } while (0)
5320 }))do { auto mozTryVarTempResult_ = (pref_LookupForModify(prefName
, [](const PrefWrapper& aPref) { return aPref.IsLocked();
})); if ((__builtin_expect(!!(mozTryVarTempResult_.isErr()),
0))) { return mozTryVarTempResult_.propagateErr(); } (pref) =
mozTryVarTempResult_.unwrap(); } while (0)
;
5321
5322 if (pref) {
5323 pref->SetIsLocked(false);
5324 NotifyCallbacks(prefName, PrefWrapper(pref));
5325 }
5326
5327 return NS_OK;
5328}
5329
5330/* static */
5331bool Preferences::IsLocked(const char* aPrefName) {
5332 NS_ENSURE_TRUE(InitStaticMembers(), false)do { if ((__builtin_expect(!!(!(InitStaticMembers())), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "InitStaticMembers()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5332); return false; } } while (false)
;
5333
5334 Maybe<PrefWrapper> pref = pref_Lookup(aPrefName);
5335 return pref.isSome() && pref->IsLocked();
5336}
5337
5338/* static */
5339bool Preferences::IsSanitized(const char* aPrefName) {
5340 NS_ENSURE_TRUE(InitStaticMembers(), false)do { if ((__builtin_expect(!!(!(InitStaticMembers())), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "InitStaticMembers()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5340); return false; } } while (false)
;
5341
5342 Maybe<PrefWrapper> pref = pref_Lookup(aPrefName);
5343 return pref.isSome() && pref->IsSanitized();
5344}
5345
5346/* static */
5347nsresult Preferences::ClearUser(const char* aPrefName) {
5348 ENSURE_PARENT_PROCESS("ClearUser", aPrefName);
5349 NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(InitStaticMembers())), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "InitStaticMembers()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5349); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
5350
5351 const auto& prefName = nsDependentCString{aPrefName};
5352 auto result = pref_LookupForModify(
5353 prefName, [](const PrefWrapper& aPref) { return aPref.HasUserValue(); });
5354 if (result.isErr()) {
5355 return NS_OK;
5356 }
5357
5358 if (Pref* pref = result.unwrap()) {
5359 pref->ClearUserValue();
5360
5361 if (!pref->HasDefaultValue()) {
5362 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!gSharedMap || !pref->IsSanitized() || !gSharedMap
->Has(pref->Name()))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!gSharedMap || !pref->IsSanitized
() || !gSharedMap->Has(pref->Name())))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!gSharedMap || !pref->IsSanitized() || !gSharedMap->Has(pref->Name())"
" (" "A sanitized pref should never be in the shared pref map."
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5364); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!gSharedMap || !pref->IsSanitized() || !gSharedMap->Has(pref->Name())"
") (" "A sanitized pref should never be in the shared pref map."
")"); do { *((volatile int*)__null) = 5364; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5363 !gSharedMap || !pref->IsSanitized() || !gSharedMap->Has(pref->Name()),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!gSharedMap || !pref->IsSanitized() || !gSharedMap
->Has(pref->Name()))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!gSharedMap || !pref->IsSanitized
() || !gSharedMap->Has(pref->Name())))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!gSharedMap || !pref->IsSanitized() || !gSharedMap->Has(pref->Name())"
" (" "A sanitized pref should never be in the shared pref map."
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5364); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!gSharedMap || !pref->IsSanitized() || !gSharedMap->Has(pref->Name())"
") (" "A sanitized pref should never be in the shared pref map."
")"); do { *((volatile int*)__null) = 5364; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5364 "A sanitized pref should never be in the shared pref map.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!gSharedMap || !pref->IsSanitized() || !gSharedMap
->Has(pref->Name()))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!gSharedMap || !pref->IsSanitized
() || !gSharedMap->Has(pref->Name())))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!gSharedMap || !pref->IsSanitized() || !gSharedMap->Has(pref->Name())"
" (" "A sanitized pref should never be in the shared pref map."
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5364); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!gSharedMap || !pref->IsSanitized() || !gSharedMap->Has(pref->Name())"
") (" "A sanitized pref should never be in the shared pref map."
")"); do { *((volatile int*)__null) = 5364; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5365 if (!pref->IsSanitized() &&
5366 (!gSharedMap || !gSharedMap->Has(pref->Name()))) {
5367 HashTable()->remove(aPrefName);
5368 } else {
5369 pref->SetType(PrefType::None);
5370 }
5371
5372 NotifyCallbacks(prefName);
5373 } else {
5374 NotifyCallbacks(prefName, PrefWrapper(pref));
5375 }
5376
5377 Preferences::HandleDirty();
5378 }
5379 return NS_OK;
5380}
5381
5382/* static */
5383bool Preferences::HasUserValue(const char* aPrefName) {
5384 NS_ENSURE_TRUE(InitStaticMembers(), false)do { if ((__builtin_expect(!!(!(InitStaticMembers())), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "InitStaticMembers()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5384); return false; } } while (false)
;
5385
5386 Maybe<PrefWrapper> pref = pref_Lookup(aPrefName);
5387 return pref.isSome() && pref->HasUserValue();
5388}
5389
5390/* static */
5391bool Preferences::HasDefaultValue(const char* aPrefName) {
5392 NS_ENSURE_TRUE(InitStaticMembers(), false)do { if ((__builtin_expect(!!(!(InitStaticMembers())), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "InitStaticMembers()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5392); return false; } } while (false)
;
5393
5394 Maybe<PrefWrapper> pref = pref_Lookup(aPrefName);
5395 return pref.isSome() && pref->HasDefaultValue();
5396}
5397
5398/* static */
5399int32_t Preferences::GetType(const char* aPrefName) {
5400 NS_ENSURE_TRUE(InitStaticMembers(), nsIPrefBranch::PREF_INVALID)do { if ((__builtin_expect(!!(!(InitStaticMembers())), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "InitStaticMembers()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5400); return nsIPrefBranch::PREF_INVALID; } } while (false
)
;
5401
5402 if (!HashTable()) {
5403 return PREF_INVALID;
5404 }
5405
5406 Maybe<PrefWrapper> pref = pref_Lookup(aPrefName);
5407 if (!pref.isSome()) {
5408 return PREF_INVALID;
5409 }
5410
5411 switch (pref->Type()) {
5412 case PrefType::String:
5413 return PREF_STRING;
5414
5415 case PrefType::Int:
5416 return PREF_INT;
5417
5418 case PrefType::Bool:
5419 return PREF_BOOL;
5420
5421 case PrefType::None:
5422 if (IsPreferenceSanitized(aPrefName)) {
5423 if (!sPrefTelemetryEventEnabled.exchange(true)) {
5424 sPrefTelemetryEventEnabled = true;
5425 Telemetry::SetEventRecordingEnabled("security"_ns, true);
5426 }
5427
5428 Telemetry::RecordEvent(
5429 Telemetry::EventID::Security_Prefusage_Contentprocess,
5430 mozilla::Some(aPrefName), mozilla::Nothing());
5431
5432 if (sCrashOnBlocklistedPref) {
5433 MOZ_CRASH_UNSAFE_PRINTF(do { static_assert(1 > 0, "Did you forget arguments to MOZ_CRASH_UNSAFE_PRINTF? "
"Or maybe you want MOZ_CRASH instead?"); static_assert(1 <=
sPrintfMaxArgs, "Only up to 4 additional arguments are allowed!"
); static_assert(sizeof("Should not access the preference '%s' in the Content Processes"
) <= sPrintfCrashReasonSize, "The supplied format string is too long!"
); MOZ_Crash("/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5435, MOZ_CrashPrintf("" "Should not access the preference '%s' in the Content Processes"
, aPrefName)); } while (false)
5434 "Should not access the preference '%s' in the Content Processes",do { static_assert(1 > 0, "Did you forget arguments to MOZ_CRASH_UNSAFE_PRINTF? "
"Or maybe you want MOZ_CRASH instead?"); static_assert(1 <=
sPrintfMaxArgs, "Only up to 4 additional arguments are allowed!"
); static_assert(sizeof("Should not access the preference '%s' in the Content Processes"
) <= sPrintfCrashReasonSize, "The supplied format string is too long!"
); MOZ_Crash("/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5435, MOZ_CrashPrintf("" "Should not access the preference '%s' in the Content Processes"
, aPrefName)); } while (false)
5435 aPrefName)do { static_assert(1 > 0, "Did you forget arguments to MOZ_CRASH_UNSAFE_PRINTF? "
"Or maybe you want MOZ_CRASH instead?"); static_assert(1 <=
sPrintfMaxArgs, "Only up to 4 additional arguments are allowed!"
); static_assert(sizeof("Should not access the preference '%s' in the Content Processes"
) <= sPrintfCrashReasonSize, "The supplied format string is too long!"
); MOZ_Crash("/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5435, MOZ_CrashPrintf("" "Should not access the preference '%s' in the Content Processes"
, aPrefName)); } while (false)
;
5436 } else {
5437 return PREF_INVALID;
5438 }
5439 }
5440 [[fallthrough]];
5441
5442 default:
5443 MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5443); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile
int*)__null) = 5443; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
;
5444 }
5445}
5446
5447/* static */
5448nsresult Preferences::AddStrongObserver(nsIObserver* aObserver,
5449 const nsACString& aPref) {
5450 MOZ_ASSERT(aObserver)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aObserver)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aObserver))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aObserver", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5450); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aObserver" ")"
); do { *((volatile int*)__null) = 5450; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5451 NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(InitStaticMembers())), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "InitStaticMembers()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5451); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
5452 return sPreferences->mRootBranch->AddObserver(aPref, aObserver, false);
5453}
5454
5455/* static */
5456nsresult Preferences::AddWeakObserver(nsIObserver* aObserver,
5457 const nsACString& aPref) {
5458 MOZ_ASSERT(aObserver)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aObserver)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aObserver))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aObserver", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5458); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aObserver" ")"
); do { *((volatile int*)__null) = 5458; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5459 NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(InitStaticMembers())), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "InitStaticMembers()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5459); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
5460 return sPreferences->mRootBranch->AddObserver(aPref, aObserver, true);
5461}
5462
5463/* static */
5464nsresult Preferences::RemoveObserver(nsIObserver* aObserver,
5465 const nsACString& aPref) {
5466 MOZ_ASSERT(aObserver)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aObserver)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aObserver))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aObserver", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5466); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aObserver" ")"
); do { *((volatile int*)__null) = 5466; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5467 if (sShutdown) {
5468 MOZ_ASSERT(!sPreferences)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!sPreferences)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!sPreferences))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!sPreferences",
"/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5468); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sPreferences"
")"); do { *((volatile int*)__null) = 5468; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5469 return NS_OK; // Observers have been released automatically.
5470 }
5471 NS_ENSURE_TRUE(sPreferences, NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(sPreferences)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "sPreferences" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5471); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
5472 return sPreferences->mRootBranch->RemoveObserver(aPref, aObserver);
5473}
5474
5475template <typename T>
5476static void AssertNotMallocAllocated(T* aPtr) {
5477#if defined(DEBUG1) && defined(MOZ_MEMORY1)
5478 jemalloc_ptr_info_t info;
5479 jemalloc_ptr_info((void*)aPtr, &info);
5480 MOZ_ASSERT(info.tag == TagUnknown)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(info.tag == TagUnknown)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(info.tag == TagUnknown))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("info.tag == TagUnknown"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5480); AnnotateMozCrashReason("MOZ_ASSERT" "(" "info.tag == TagUnknown"
")"); do { *((volatile int*)__null) = 5480; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5481#endif
5482}
5483
5484/* static */
5485nsresult Preferences::AddStrongObservers(nsIObserver* aObserver,
5486 const char* const* aPrefs) {
5487 MOZ_ASSERT(aObserver)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aObserver)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aObserver))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aObserver", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5487); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aObserver" ")"
); do { *((volatile int*)__null) = 5487; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5488 for (uint32_t i = 0; aPrefs[i]; i++) {
5489 AssertNotMallocAllocated(aPrefs[i]);
5490
5491 nsCString pref;
5492 pref.AssignLiteral(aPrefs[i], strlen(aPrefs[i]));
5493 nsresult rv = AddStrongObserver(aObserver, pref);
5494 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5494); return rv; } } while (false)
;
5495 }
5496 return NS_OK;
5497}
5498
5499/* static */
5500nsresult Preferences::AddWeakObservers(nsIObserver* aObserver,
5501 const char* const* aPrefs) {
5502 MOZ_ASSERT(aObserver)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aObserver)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aObserver))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aObserver", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5502); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aObserver" ")"
); do { *((volatile int*)__null) = 5502; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5503 for (uint32_t i = 0; aPrefs[i]; i++) {
5504 AssertNotMallocAllocated(aPrefs[i]);
5505
5506 nsCString pref;
5507 pref.AssignLiteral(aPrefs[i], strlen(aPrefs[i]));
5508 nsresult rv = AddWeakObserver(aObserver, pref);
5509 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5509); return rv; } } while (false)
;
5510 }
5511 return NS_OK;
5512}
5513
5514/* static */
5515nsresult Preferences::RemoveObservers(nsIObserver* aObserver,
5516 const char* const* aPrefs) {
5517 MOZ_ASSERT(aObserver)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aObserver)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aObserver))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aObserver", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5517); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aObserver" ")"
); do { *((volatile int*)__null) = 5517; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5518 if (sShutdown) {
5519 MOZ_ASSERT(!sPreferences)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!sPreferences)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!sPreferences))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!sPreferences",
"/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5519); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sPreferences"
")"); do { *((volatile int*)__null) = 5519; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5520 return NS_OK; // Observers have been released automatically.
5521 }
5522 NS_ENSURE_TRUE(sPreferences, NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(sPreferences)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "sPreferences" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5522); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
5523
5524 for (uint32_t i = 0; aPrefs[i]; i++) {
5525 nsresult rv = RemoveObserver(aObserver, nsDependentCString(aPrefs[i]));
5526 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5526); return rv; } } while (false)
;
5527 }
5528 return NS_OK;
5529}
5530
5531template <typename T>
5532/* static */
5533nsresult Preferences::RegisterCallbackImpl(PrefChangedFunc aCallback,
5534 T& aPrefNode, void* aData,
5535 MatchKind aMatchKind,
5536 bool aIsPriority) {
5537 NS_ENSURE_ARG(aCallback)do { if ((__builtin_expect(!!(!(aCallback)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aCallback" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5537); return NS_ERROR_INVALID_ARG; } } while (false)
;
5538
5539 NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(InitStaticMembers())), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "InitStaticMembers()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5539); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
5540
5541 auto node = new CallbackNode(aPrefNode, aCallback, aData, aMatchKind);
5542
5543 if (aIsPriority) {
5544 // Add to the start of the list.
5545 node->SetNext(gFirstCallback);
5546 gFirstCallback = node;
5547 if (!gLastPriorityNode) {
5548 gLastPriorityNode = node;
5549 }
5550 } else {
5551 // Add to the start of the non-priority part of the list.
5552 if (gLastPriorityNode) {
5553 node->SetNext(gLastPriorityNode->Next());
5554 gLastPriorityNode->SetNext(node);
5555 } else {
5556 node->SetNext(gFirstCallback);
5557 gFirstCallback = node;
5558 }
5559 }
5560
5561 return NS_OK;
5562}
5563
5564/* static */
5565nsresult Preferences::RegisterCallback(PrefChangedFunc aCallback,
5566 const nsACString& aPrefNode, void* aData,
5567 MatchKind aMatchKind, bool aIsPriority) {
5568 return RegisterCallbackImpl(aCallback, aPrefNode, aData, aMatchKind,
5569 aIsPriority);
5570}
5571
5572/* static */
5573nsresult Preferences::RegisterCallbacks(PrefChangedFunc aCallback,
5574 const char* const* aPrefs, void* aData,
5575 MatchKind aMatchKind) {
5576 return RegisterCallbackImpl(aCallback, aPrefs, aData, aMatchKind);
5577}
5578
5579/* static */
5580nsresult Preferences::RegisterCallbackAndCall(PrefChangedFunc aCallback,
5581 const nsACString& aPref,
5582 void* aClosure,
5583 MatchKind aMatchKind) {
5584 MOZ_ASSERT(aCallback)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aCallback)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aCallback))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aCallback", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5584); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aCallback" ")"
); do { *((volatile int*)__null) = 5584; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5585 nsresult rv = RegisterCallback(aCallback, aPref, aClosure, aMatchKind);
5586 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5587 (*aCallback)(PromiseFlatCStringTPromiseFlatString<char>(aPref).get(), aClosure);
5588 }
5589 return rv;
5590}
5591
5592/* static */
5593nsresult Preferences::RegisterCallbacksAndCall(PrefChangedFunc aCallback,
5594 const char* const* aPrefs,
5595 void* aClosure) {
5596 MOZ_ASSERT(aCallback)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aCallback)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aCallback))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aCallback", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5596); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aCallback" ")"
); do { *((volatile int*)__null) = 5596; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5597
5598 nsresult rv =
5599 RegisterCallbacks(aCallback, aPrefs, aClosure, MatchKind::ExactMatch);
5600 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5601 for (const char* const* ptr = aPrefs; *ptr; ptr++) {
5602 (*aCallback)(*ptr, aClosure);
5603 }
5604 }
5605 return rv;
5606}
5607
5608template <typename T>
5609/* static */
5610nsresult Preferences::UnregisterCallbackImpl(PrefChangedFunc aCallback,
5611 T& aPrefNode, void* aData,
5612 MatchKind aMatchKind) {
5613 MOZ_ASSERT(aCallback)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aCallback)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aCallback))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aCallback", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5613); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aCallback" ")"
); do { *((volatile int*)__null) = 5613; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5614 if (sShutdown) {
5615 MOZ_ASSERT(!sPreferences)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!sPreferences)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!sPreferences))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!sPreferences",
"/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5615); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sPreferences"
")"); do { *((volatile int*)__null) = 5615; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5616 return NS_OK; // Observers have been released automatically.
5617 }
5618 NS_ENSURE_TRUE(sPreferences, NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(sPreferences)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "sPreferences" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5618); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
5619
5620 nsresult rv = NS_ERROR_FAILURE;
5621 CallbackNode* node = gFirstCallback;
5622 CallbackNode* prev_node = nullptr;
5623
5624 while (node) {
5625 if (node->Func() == aCallback && node->Data() == aData &&
5626 node->MatchKind() == aMatchKind && node->DomainIs(aPrefNode)) {
5627 if (gCallbacksInProgress) {
5628 // Postpone the node removal until after callbacks enumeration is
5629 // finished.
5630 node->ClearFunc();
5631 gShouldCleanupDeadNodes = true;
5632 prev_node = node;
5633 node = node->Next();
5634 } else {
5635 node = pref_RemoveCallbackNode(node, prev_node);
5636 }
5637 rv = NS_OK;
5638 } else {
5639 prev_node = node;
5640 node = node->Next();
5641 }
5642 }
5643 return rv;
5644}
5645
5646/* static */
5647nsresult Preferences::UnregisterCallback(PrefChangedFunc aCallback,
5648 const nsACString& aPrefNode,
5649 void* aData, MatchKind aMatchKind) {
5650 return UnregisterCallbackImpl<const nsACString&>(aCallback, aPrefNode, aData,
5651 aMatchKind);
5652}
5653
5654/* static */
5655nsresult Preferences::UnregisterCallbacks(PrefChangedFunc aCallback,
5656 const char* const* aPrefs,
5657 void* aData, MatchKind aMatchKind) {
5658 return UnregisterCallbackImpl(aCallback, aPrefs, aData, aMatchKind);
5659}
5660
5661template <typename T>
5662static void AddMirrorCallback(T* aMirror, const nsACString& aPref) {
5663 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5663); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5663; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5664
5665 Internals::RegisterCallback<T>(aMirror, aPref);
5666}
5667
5668// Don't inline because it explodes compile times.
5669template <typename T>
5670static MOZ_NEVER_INLINE__attribute__((noinline)) void AddMirror(T* aMirror, const nsACString& aPref,
5671 StripAtomic<T> aDefault) {
5672 *aMirror = Internals::GetPref(PromiseFlatCStringTPromiseFlatString<char>(aPref).get(), aDefault);
5673 AddMirrorCallback(aMirror, aPref);
5674}
5675
5676static MOZ_NEVER_INLINE__attribute__((noinline)) void AddMirror(DataMutexString& aMirror,
5677 const nsACString& aPref) {
5678 auto lock = aMirror.Lock();
5679 nsCString result(*lock);
5680 Internals::GetPrefValue(PromiseFlatCStringTPromiseFlatString<char>(aPref).get(), result,
5681 PrefValueKind::User);
5682 lock->Assign(std::move(result));
5683 AddMirrorCallback(&aMirror, aPref);
5684}
5685
5686// The InitPref_*() functions below end in a `_<type>` suffix because they are
5687// used by the PREF macro definition in InitAll() below.
5688
5689static void InitPref_bool(const nsCString& aName, bool aDefaultValue) {
5690 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5690); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 5690; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5691 PrefValue value;
5692 value.mBoolVal = aDefaultValue;
5693 pref_SetPref(aName, PrefType::Bool, PrefValueKind::Default, value,
5694 /* isSticky */ false,
5695 /* isLocked */ false,
5696 /* fromInit */ true);
5697}
5698
5699static void InitPref_int32_t(const nsCString& aName, int32_t aDefaultValue) {
5700 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5700); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 5700; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5701 PrefValue value;
5702 value.mIntVal = aDefaultValue;
5703 pref_SetPref(aName, PrefType::Int, PrefValueKind::Default, value,
5704 /* isSticky */ false,
5705 /* isLocked */ false,
5706 /* fromInit */ true);
5707}
5708
5709static void InitPref_uint32_t(const nsCString& aName, uint32_t aDefaultValue) {
5710 InitPref_int32_t(aName, int32_t(aDefaultValue));
5711}
5712
5713static void InitPref_float(const nsCString& aName, float aDefaultValue) {
5714 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5714); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 5714; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5715 PrefValue value;
5716 // Convert the value in a locale-independent way, including a trailing ".0"
5717 // if necessary to distinguish floating-point from integer prefs when viewing
5718 // them in about:config.
5719 nsAutoCString defaultValue;
5720 defaultValue.AppendFloat(aDefaultValue);
5721 if (!defaultValue.Contains('.') && !defaultValue.Contains('e')) {
5722 defaultValue.AppendLiteral(".0");
5723 }
5724 value.mStringVal = defaultValue.get();
5725 pref_SetPref(aName, PrefType::String, PrefValueKind::Default, value,
5726 /* isSticky */ false,
5727 /* isLocked */ false,
5728 /* fromInit */ true);
5729}
5730
5731static void InitPref_String(const nsCString& aName, const char* aDefaultValue) {
5732 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5732); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 5732; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5733 PrefValue value;
5734 value.mStringVal = aDefaultValue;
5735 pref_SetPref(aName, PrefType::String, PrefValueKind::Default, value,
5736 /* isSticky */ false,
5737 /* isLocked */ false,
5738 /* fromInit */ true);
5739}
5740
5741static void InitPref(const nsCString& aName, bool aDefaultValue) {
5742 InitPref_bool(aName, aDefaultValue);
5743}
5744static void InitPref(const nsCString& aName, int32_t aDefaultValue) {
5745 InitPref_int32_t(aName, aDefaultValue);
5746}
5747static void InitPref(const nsCString& aName, uint32_t aDefaultValue) {
5748 InitPref_uint32_t(aName, aDefaultValue);
5749}
5750static void InitPref(const nsCString& aName, float aDefaultValue) {
5751 InitPref_float(aName, aDefaultValue);
5752}
5753
5754template <typename T>
5755static void InitAlwaysPref(const nsCString& aName, T* aCache,
5756 StripAtomic<T> aDefaultValue) {
5757 // Only called in the parent process. Set/reset the pref value and the
5758 // `always` mirror to the default value.
5759 // `once` mirrors will be initialized lazily in InitOncePrefs().
5760 InitPref(aName, aDefaultValue);
5761 *aCache = aDefaultValue;
5762}
5763
5764static void InitAlwaysPref(const nsCString& aName, DataMutexString& aCache,
5765 const nsLiteralCString& aDefaultValue) {
5766 // Only called in the parent process. Set/reset the pref value and the
5767 // `always` mirror to the default value.
5768 // `once` mirrors will be initialized lazily in InitOncePrefs().
5769 InitPref_String(aName, aDefaultValue.get());
5770 Internals::AssignMirror(aCache, aDefaultValue);
5771}
5772
5773static Atomic<bool> sOncePrefRead(false);
5774static StaticMutex sOncePrefMutex MOZ_UNANNOTATED;
5775
5776namespace StaticPrefs {
5777
5778void MaybeInitOncePrefs() {
5779 if (MOZ_LIKELY(sOncePrefRead)(__builtin_expect(!!(sOncePrefRead), 1))) {
5780 // `once`-mirrored prefs have already been initialized to their default
5781 // value.
5782 return;
5783 }
5784 StaticMutexAutoLock lock(sOncePrefMutex);
5785 if (NS_IsMainThread()) {
5786 InitOncePrefs();
5787 } else {
5788 RefPtr<Runnable> runnable = NS_NewRunnableFunction(
5789 "Preferences::MaybeInitOncePrefs", [&]() { InitOncePrefs(); });
5790 // This logic needs to run on the main thread
5791 SyncRunnable::DispatchToThread(GetMainThreadSerialEventTarget(), runnable);
5792 }
5793 sOncePrefRead = true;
5794}
5795
5796// For mirrored prefs we generate a variable definition.
5797#define NEVER_PREF(name, cpp_type, value)
5798#define ALWAYS_PREF(name, base_id, full_id, cpp_type, default_value) \
5799 cpp_type sMirror_##full_id(default_value);
5800#define ALWAYS_DATAMUTEX_PREF(name, base_id, full_id, cpp_type, default_value) \
5801 cpp_type sMirror_##full_id("DataMutexString");
5802#define ONCE_PREF(name, base_id, full_id, cpp_type, default_value) \
5803 cpp_type sMirror_##full_id(default_value);
5804#include "mozilla/StaticPrefListAll.h"
5805#undef NEVER_PREF
5806#undef ALWAYS_PREF
5807#undef ALWAYS_DATAMUTEX_PREF
5808#undef ONCE_PREF
5809
5810static void InitAll() {
5811 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5811); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5811; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5812 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5812); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 5812; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5813
5814 // For all prefs we generate some initialization code.
5815 //
5816 // The InitPref_*() functions have a type suffix to avoid ambiguity between
5817 // prefs having int32_t and float default values. That suffix is not needed
5818 // for the InitAlwaysPref() functions because they take a pointer parameter,
5819 // which prevents automatic int-to-float coercion.
5820#define NEVER_PREF(name, cpp_type, value) \
5821 InitPref_##cpp_type(name ""_ns, value);
5822#define ALWAYS_PREF(name, base_id, full_id, cpp_type, value) \
5823 InitAlwaysPref(name ""_ns, &sMirror_##full_id, value);
5824#define ALWAYS_DATAMUTEX_PREF(name, base_id, full_id, cpp_type, value) \
5825 InitAlwaysPref(name ""_ns, sMirror_##full_id, value);
5826#define ONCE_PREF(name, base_id, full_id, cpp_type, value) \
5827 InitPref_##cpp_type(name ""_ns, value);
5828#include "mozilla/StaticPrefListAll.h"
5829#undef NEVER_PREF
5830#undef ALWAYS_PREF
5831#undef ALWAYS_DATAMUTEX_PREF
5832#undef ONCE_PREF
5833}
5834
5835static void StartObservingAlwaysPrefs() {
5836 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5836); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5836; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5837
5838 // Call AddMirror so that our mirrors for `always` prefs will stay updated.
5839 // The call to AddMirror re-reads the current pref value into the mirror, so
5840 // our mirror will now be up-to-date even if some of the prefs have changed
5841 // since the call to InitAll().
5842#define NEVER_PREF(name, cpp_type, value)
5843#define ALWAYS_PREF(name, base_id, full_id, cpp_type, value) \
5844 AddMirror(&sMirror_##full_id, name ""_ns, sMirror_##full_id);
5845#define ALWAYS_DATAMUTEX_PREF(name, base_id, full_id, cpp_type, value) \
5846 AddMirror(sMirror_##full_id, name ""_ns);
5847#define ONCE_PREF(name, base_id, full_id, cpp_type, value)
5848#include "mozilla/StaticPrefListAll.h"
5849#undef NEVER_PREF
5850#undef ALWAYS_PREF
5851#undef ALWAYS_DATAMUTEX_PREF
5852#undef ONCE_PREF
5853}
5854
5855static void InitOncePrefs() {
5856 // For `once`-mirrored prefs we generate some initialization code. This is
5857 // done in case the pref value was updated when reading pref data files. It's
5858 // necessary because we don't have callbacks registered for `once`-mirrored
5859 // prefs.
5860 //
5861 // In debug builds, we also install a mechanism that can check if the
5862 // preference value is modified after `once`-mirrored prefs are initialized.
5863 // In tests this would indicate a likely misuse of a `once`-mirrored pref and
5864 // suggest that it should instead be `always`-mirrored.
5865#define NEVER_PREF(name, cpp_type, value)
5866#define ALWAYS_PREF(name, base_id, full_id, cpp_type, value)
5867#define ALWAYS_DATAMUTEX_PREF(name, base_id, full_id, cpp_type, value)
5868#ifdef DEBUG1
5869# define ONCE_PREF(name, base_id, full_id, cpp_type, value) \
5870 { \
5871 MOZ_ASSERT(gOnceStaticPrefsAntiFootgun)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(gOnceStaticPrefsAntiFootgun)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(gOnceStaticPrefsAntiFootgun)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("gOnceStaticPrefsAntiFootgun"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5871); AnnotateMozCrashReason("MOZ_ASSERT" "(" "gOnceStaticPrefsAntiFootgun"
")"); do { *((volatile int*)__null) = 5871; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
; \
5872 sMirror_##full_id = Internals::GetPref(name, cpp_type(value)); \
5873 auto checkPref = [&]() { \
5874 MOZ_ASSERT(sOncePrefRead)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sOncePrefRead)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sOncePrefRead))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("sOncePrefRead",
"/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5874); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sOncePrefRead"
")"); do { *((volatile int*)__null) = 5874; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
; \
5875 cpp_type staticPrefValue = full_id(); \
5876 cpp_type preferenceValue = \
5877 Internals::GetPref(GetPrefName_##base_id(), cpp_type(value)); \
5878 MOZ_ASSERT(staticPrefValue == preferenceValue, \do { static_assert( mozilla::detail::AssertionConditionType<
decltype(staticPrefValue == preferenceValue)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(staticPrefValue == preferenceValue
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"staticPrefValue == preferenceValue" " (" "Preference '" name
"' got modified since StaticPrefs::" #full_id " was initialized. Consider using an `always` mirror kind "
"instead" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "staticPrefValue == preferenceValue"
") (" "Preference '" name "' got modified since StaticPrefs::"
#full_id " was initialized. Consider using an `always` mirror kind "
"instead" ")"); do { *((volatile int*)__null) = 5882; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
5879 "Preference '" name \do { static_assert( mozilla::detail::AssertionConditionType<
decltype(staticPrefValue == preferenceValue)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(staticPrefValue == preferenceValue
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"staticPrefValue == preferenceValue" " (" "Preference '" name
"' got modified since StaticPrefs::" #full_id " was initialized. Consider using an `always` mirror kind "
"instead" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "staticPrefValue == preferenceValue"
") (" "Preference '" name "' got modified since StaticPrefs::"
#full_id " was initialized. Consider using an `always` mirror kind "
"instead" ")"); do { *((volatile int*)__null) = 5882; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
5880 "' got modified since StaticPrefs::" #full_id \do { static_assert( mozilla::detail::AssertionConditionType<
decltype(staticPrefValue == preferenceValue)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(staticPrefValue == preferenceValue
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"staticPrefValue == preferenceValue" " (" "Preference '" name
"' got modified since StaticPrefs::" #full_id " was initialized. Consider using an `always` mirror kind "
"instead" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "staticPrefValue == preferenceValue"
") (" "Preference '" name "' got modified since StaticPrefs::"
#full_id " was initialized. Consider using an `always` mirror kind "
"instead" ")"); do { *((volatile int*)__null) = 5882; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
5881 " was initialized. Consider using an `always` mirror kind " \do { static_assert( mozilla::detail::AssertionConditionType<
decltype(staticPrefValue == preferenceValue)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(staticPrefValue == preferenceValue
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"staticPrefValue == preferenceValue" " (" "Preference '" name
"' got modified since StaticPrefs::" #full_id " was initialized. Consider using an `always` mirror kind "
"instead" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "staticPrefValue == preferenceValue"
") (" "Preference '" name "' got modified since StaticPrefs::"
#full_id " was initialized. Consider using an `always` mirror kind "
"instead" ")"); do { *((volatile int*)__null) = 5882; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
5882 "instead")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(staticPrefValue == preferenceValue)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(staticPrefValue == preferenceValue
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"staticPrefValue == preferenceValue" " (" "Preference '" name
"' got modified since StaticPrefs::" #full_id " was initialized. Consider using an `always` mirror kind "
"instead" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "staticPrefValue == preferenceValue"
") (" "Preference '" name "' got modified since StaticPrefs::"
#full_id " was initialized. Consider using an `always` mirror kind "
"instead" ")"); do { *((volatile int*)__null) = 5882; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
; \
5883 }; \
5884 gOnceStaticPrefsAntiFootgun->insert( \
5885 std::pair<const char*, AntiFootgunCallback>(GetPrefName_##base_id(), \
5886 std::move(checkPref))); \
5887 }
5888#else
5889# define ONCE_PREF(name, base_id, full_id, cpp_type, value) \
5890 sMirror_##full_id = Internals::GetPref(name, cpp_type(value));
5891#endif
5892
5893#include "mozilla/StaticPrefListAll.h"
5894#undef NEVER_PREF
5895#undef ALWAYS_PREF
5896#undef ALWAYS_DATAMUTEX_PREF
5897#undef ONCE_PREF
5898}
5899
5900static void ShutdownAlwaysPrefs() {
5901 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5901); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5901; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5902
5903 // We may need to do clean up for leak detection for some StaticPrefs.
5904#define NEVER_PREF(name, cpp_type, value)
5905#define ALWAYS_PREF(name, base_id, full_id, cpp_type, value)
5906#define ALWAYS_DATAMUTEX_PREF(name, base_id, full_id, cpp_type, value) \
5907 Internals::ClearMirror(sMirror_##full_id);
5908#define ONCE_PREF(name, base_id, full_id, cpp_type, value)
5909#include "mozilla/StaticPrefListAll.h"
5910#undef NEVER_PREF
5911#undef ALWAYS_PREF
5912#undef ALWAYS_DATAMUTEX_PREF
5913#undef ONCE_PREF
5914}
5915
5916} // namespace StaticPrefs
5917
5918static MOZ_MAYBE_UNUSED__attribute__((__unused__)) void SaveOncePrefToSharedMap(
5919 SharedPrefMapBuilder& aBuilder, const nsACString& aName, bool aValue) {
5920 auto oncePref = MakeUnique<Pref>(aName);
5921 oncePref->SetType(PrefType::Bool);
5922 oncePref->SetIsSkippedByIteration(true);
5923 bool valueChanged = false;
5924 MOZ_ALWAYS_SUCCEEDS(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(oncePref->SetDefaultValue(PrefType::Bool, PrefValue(aValue
), true, true, &valueChanged))), 1)))), 1))) { } else { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(oncePref->SetDefaultValue(PrefType::Bool, PrefValue(aValue), true, true, &valueChanged))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5927); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(oncePref->SetDefaultValue(PrefType::Bool, PrefValue(aValue), true, true, &valueChanged))"
")"); do { *((volatile int*)__null) = 5927; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
5925 oncePref->SetDefaultValue(PrefType::Bool, PrefValue(aValue),do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(oncePref->SetDefaultValue(PrefType::Bool, PrefValue(aValue
), true, true, &valueChanged))), 1)))), 1))) { } else { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(oncePref->SetDefaultValue(PrefType::Bool, PrefValue(aValue), true, true, &valueChanged))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5927); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(oncePref->SetDefaultValue(PrefType::Bool, PrefValue(aValue), true, true, &valueChanged))"
")"); do { *((volatile int*)__null) = 5927; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
5926 /* isSticky */ true,do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(oncePref->SetDefaultValue(PrefType::Bool, PrefValue(aValue
), true, true, &valueChanged))), 1)))), 1))) { } else { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(oncePref->SetDefaultValue(PrefType::Bool, PrefValue(aValue), true, true, &valueChanged))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5927); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(oncePref->SetDefaultValue(PrefType::Bool, PrefValue(aValue), true, true, &valueChanged))"
")"); do { *((volatile int*)__null) = 5927; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
5927 /* isLocked */ true, &valueChanged))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(oncePref->SetDefaultValue(PrefType::Bool, PrefValue(aValue
), true, true, &valueChanged))), 1)))), 1))) { } else { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(oncePref->SetDefaultValue(PrefType::Bool, PrefValue(aValue), true, true, &valueChanged))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5927); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(oncePref->SetDefaultValue(PrefType::Bool, PrefValue(aValue), true, true, &valueChanged))"
")"); do { *((volatile int*)__null) = 5927; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5928 oncePref->AddToMap(aBuilder);
5929}
5930
5931static MOZ_MAYBE_UNUSED__attribute__((__unused__)) void SaveOncePrefToSharedMap(
5932 SharedPrefMapBuilder& aBuilder, const nsACString& aName, int32_t aValue) {
5933 auto oncePref = MakeUnique<Pref>(aName);
5934 oncePref->SetType(PrefType::Int);
5935 oncePref->SetIsSkippedByIteration(true);
5936 bool valueChanged = false;
5937 MOZ_ALWAYS_SUCCEEDS(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(oncePref->SetDefaultValue(PrefType::Int, PrefValue(aValue
), true, true, &valueChanged))), 1)))), 1))) { } else { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(oncePref->SetDefaultValue(PrefType::Int, PrefValue(aValue), true, true, &valueChanged))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5940); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(oncePref->SetDefaultValue(PrefType::Int, PrefValue(aValue), true, true, &valueChanged))"
")"); do { *((volatile int*)__null) = 5940; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
5938 oncePref->SetDefaultValue(PrefType::Int, PrefValue(aValue),do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(oncePref->SetDefaultValue(PrefType::Int, PrefValue(aValue
), true, true, &valueChanged))), 1)))), 1))) { } else { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(oncePref->SetDefaultValue(PrefType::Int, PrefValue(aValue), true, true, &valueChanged))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5940); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(oncePref->SetDefaultValue(PrefType::Int, PrefValue(aValue), true, true, &valueChanged))"
")"); do { *((volatile int*)__null) = 5940; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
5939 /* isSticky */ true,do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(oncePref->SetDefaultValue(PrefType::Int, PrefValue(aValue
), true, true, &valueChanged))), 1)))), 1))) { } else { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(oncePref->SetDefaultValue(PrefType::Int, PrefValue(aValue), true, true, &valueChanged))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5940); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(oncePref->SetDefaultValue(PrefType::Int, PrefValue(aValue), true, true, &valueChanged))"
")"); do { *((volatile int*)__null) = 5940; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
5940 /* isLocked */ true, &valueChanged))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(oncePref->SetDefaultValue(PrefType::Int, PrefValue(aValue
), true, true, &valueChanged))), 1)))), 1))) { } else { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(oncePref->SetDefaultValue(PrefType::Int, PrefValue(aValue), true, true, &valueChanged))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5940); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(oncePref->SetDefaultValue(PrefType::Int, PrefValue(aValue), true, true, &valueChanged))"
")"); do { *((volatile int*)__null) = 5940; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5941 oncePref->AddToMap(aBuilder);
5942}
5943
5944static MOZ_MAYBE_UNUSED__attribute__((__unused__)) void SaveOncePrefToSharedMap(
5945 SharedPrefMapBuilder& aBuilder, const nsACString& aName, uint32_t aValue) {
5946 SaveOncePrefToSharedMap(aBuilder, aName, int32_t(aValue));
5947}
5948
5949static MOZ_MAYBE_UNUSED__attribute__((__unused__)) void SaveOncePrefToSharedMap(
5950 SharedPrefMapBuilder& aBuilder, const nsACString& aName, float aValue) {
5951 auto oncePref = MakeUnique<Pref>(aName);
5952 oncePref->SetType(PrefType::String);
5953 oncePref->SetIsSkippedByIteration(true);
5954 nsAutoCString value;
5955 value.AppendFloat(aValue);
5956 bool valueChanged = false;
5957 // It's ok to stash a pointer to the temporary PromiseFlatCString's chars in
5958 // pref because pref_SetPref() duplicates those chars.
5959 const nsCString& flat = PromiseFlatCStringTPromiseFlatString<char>(value);
5960 MOZ_ALWAYS_SUCCEEDS(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(oncePref->SetDefaultValue(PrefType::String, PrefValue(flat
.get()), true, true, &valueChanged))), 1)))), 1))) { } else
{ do { static_assert( mozilla::detail::AssertionConditionType
<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(oncePref->SetDefaultValue(PrefType::String, PrefValue(flat.get()), true, true, &valueChanged))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5963); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(oncePref->SetDefaultValue(PrefType::String, PrefValue(flat.get()), true, true, &valueChanged))"
")"); do { *((volatile int*)__null) = 5963; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
5961 oncePref->SetDefaultValue(PrefType::String, PrefValue(flat.get()),do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(oncePref->SetDefaultValue(PrefType::String, PrefValue(flat
.get()), true, true, &valueChanged))), 1)))), 1))) { } else
{ do { static_assert( mozilla::detail::AssertionConditionType
<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(oncePref->SetDefaultValue(PrefType::String, PrefValue(flat.get()), true, true, &valueChanged))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5963); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(oncePref->SetDefaultValue(PrefType::String, PrefValue(flat.get()), true, true, &valueChanged))"
")"); do { *((volatile int*)__null) = 5963; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
5962 /* isSticky */ true,do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(oncePref->SetDefaultValue(PrefType::String, PrefValue(flat
.get()), true, true, &valueChanged))), 1)))), 1))) { } else
{ do { static_assert( mozilla::detail::AssertionConditionType
<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(oncePref->SetDefaultValue(PrefType::String, PrefValue(flat.get()), true, true, &valueChanged))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5963); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(oncePref->SetDefaultValue(PrefType::String, PrefValue(flat.get()), true, true, &valueChanged))"
")"); do { *((volatile int*)__null) = 5963; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
5963 /* isLocked */ true, &valueChanged))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(oncePref->SetDefaultValue(PrefType::String, PrefValue(flat
.get()), true, true, &valueChanged))), 1)))), 1))) { } else
{ do { static_assert( mozilla::detail::AssertionConditionType
<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(oncePref->SetDefaultValue(PrefType::String, PrefValue(flat.get()), true, true, &valueChanged))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5963); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(oncePref->SetDefaultValue(PrefType::String, PrefValue(flat.get()), true, true, &valueChanged))"
")"); do { *((volatile int*)__null) = 5963; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5964 oncePref->AddToMap(aBuilder);
5965}
5966
5967#define ONCE_PREF_NAME(name)"$$$" name "$$$" "$$$" name "$$$"
5968
5969namespace StaticPrefs {
5970
5971static void RegisterOncePrefs(SharedPrefMapBuilder& aBuilder) {
5972 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5972); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 5972; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5973 MOZ_DIAGNOSTIC_ASSERT(!gSharedMap,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!gSharedMap)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!gSharedMap))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!gSharedMap" " ("
"Must be called before gSharedMap has been created" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5974); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!gSharedMap"
") (" "Must be called before gSharedMap has been created" ")"
); do { *((volatile int*)__null) = 5974; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5974 "Must be called before gSharedMap has been created")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!gSharedMap)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!gSharedMap))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!gSharedMap" " ("
"Must be called before gSharedMap has been created" ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 5974); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!gSharedMap"
") (" "Must be called before gSharedMap has been created" ")"
); do { *((volatile int*)__null) = 5974; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5975 MaybeInitOncePrefs();
5976
5977 // For `once`-mirrored prefs we generate a save call, which saves the value
5978 // as it was at parent startup. It is stored in a special (hidden and locked)
5979 // entry in the global SharedPreferenceMap. In order for the entry to be
5980 // hidden and not appear in about:config nor ever be stored to disk, we set
5981 // its IsSkippedByIteration flag to true. We also distinguish it by adding a
5982 // "$$$" prefix and suffix to the preference name.
5983#define NEVER_PREF(name, cpp_type, value)
5984#define ALWAYS_PREF(name, base_id, full_id, cpp_type, value)
5985#define ALWAYS_DATAMUTEX_PREF(name, base_id, full_id, cpp_type, value)
5986#define ONCE_PREF(name, base_id, full_id, cpp_type, value) \
5987 SaveOncePrefToSharedMap(aBuilder, ONCE_PREF_NAME(name)"$$$" name "$$$" ""_ns, \
5988 cpp_type(sMirror_##full_id));
5989#include "mozilla/StaticPrefListAll.h"
5990#undef NEVER_PREF
5991#undef ALWAYS_PREF
5992#undef ALWAYS_DATAMUTEX_PREF
5993#undef ONCE_PREF
5994}
5995
5996// Disable thread safety analysis on this function, because it explodes build
5997// times and memory usage.
5998MOZ_NO_THREAD_SAFETY_ANALYSIS__attribute__((no_thread_safety_analysis))
5999static void InitStaticPrefsFromShared() {
6000 MOZ_ASSERT(!XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!XRE_IsParentProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 6000); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 6000; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6001 MOZ_DIAGNOSTIC_ASSERT(gSharedMap,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(gSharedMap)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(gSharedMap))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("gSharedMap" " (" "Must be called once gSharedMap has been created"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 6002); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "gSharedMap"
") (" "Must be called once gSharedMap has been created" ")")
; do { *((volatile int*)__null) = 6002; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6002 "Must be called once gSharedMap has been created")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(gSharedMap)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(gSharedMap))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("gSharedMap" " (" "Must be called once gSharedMap has been created"
")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 6002); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "gSharedMap"
") (" "Must be called once gSharedMap has been created" ")")
; do { *((volatile int*)__null) = 6002; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6003
6004#ifdef DEBUG1
6005# define ASSERT_PREF_NOT_SANITIZED(name, cpp_type) \
6006 if (IsString<cpp_type>::value && IsPreferenceSanitized(name)) { \
6007 MOZ_CRASH("Unexpected sanitized string preference '" name \do { do { } while (false); MOZ_ReportCrash("" "Unexpected sanitized string preference '"
name "'. " "Static Preferences cannot be sanitized currently, because "
"they expect to be initialized from the Static Map, and " "sanitized preferences are not present there."
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 6011); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected sanitized string preference '"
name "'. " "Static Preferences cannot be sanitized currently, because "
"they expect to be initialized from the Static Map, and " "sanitized preferences are not present there."
")"); do { *((volatile int*)__null) = 6011; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
6008 "'. " \do { do { } while (false); MOZ_ReportCrash("" "Unexpected sanitized string preference '"
name "'. " "Static Preferences cannot be sanitized currently, because "
"they expect to be initialized from the Static Map, and " "sanitized preferences are not present there."
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 6011); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected sanitized string preference '"
name "'. " "Static Preferences cannot be sanitized currently, because "
"they expect to be initialized from the Static Map, and " "sanitized preferences are not present there."
")"); do { *((volatile int*)__null) = 6011; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
6009 "Static Preferences cannot be sanitized currently, because " \do { do { } while (false); MOZ_ReportCrash("" "Unexpected sanitized string preference '"
name "'. " "Static Preferences cannot be sanitized currently, because "
"they expect to be initialized from the Static Map, and " "sanitized preferences are not present there."
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 6011); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected sanitized string preference '"
name "'. " "Static Preferences cannot be sanitized currently, because "
"they expect to be initialized from the Static Map, and " "sanitized preferences are not present there."
")"); do { *((volatile int*)__null) = 6011; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
6010 "they expect to be initialized from the Static Map, and " \do { do { } while (false); MOZ_ReportCrash("" "Unexpected sanitized string preference '"
name "'. " "Static Preferences cannot be sanitized currently, because "
"they expect to be initialized from the Static Map, and " "sanitized preferences are not present there."
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 6011); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected sanitized string preference '"
name "'. " "Static Preferences cannot be sanitized currently, because "
"they expect to be initialized from the Static Map, and " "sanitized preferences are not present there."
")"); do { *((volatile int*)__null) = 6011; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
6011 "sanitized preferences are not present there.")do { do { } while (false); MOZ_ReportCrash("" "Unexpected sanitized string preference '"
name "'. " "Static Preferences cannot be sanitized currently, because "
"they expect to be initialized from the Static Map, and " "sanitized preferences are not present there."
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 6011); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected sanitized string preference '"
name "'. " "Static Preferences cannot be sanitized currently, because "
"they expect to be initialized from the Static Map, and " "sanitized preferences are not present there."
")"); do { *((volatile int*)__null) = 6011; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
; \
6012 }
6013#else
6014# define ASSERT_PREF_NOT_SANITIZED(name, cpp_type)
6015#endif
6016
6017 // For mirrored static prefs we generate some initialization code. Each
6018 // mirror variable is already initialized in the binary with the default
6019 // value. If the pref value hasn't changed from the default in the main
6020 // process (the common case) then the overwriting here won't change the
6021 // mirror variable's value.
6022 //
6023 // Note that the MOZ_ASSERT calls below can fail in one obscure case: when a
6024 // Firefox update occurs and we get a main process from the old binary (with
6025 // static prefs {A,B,C,D}) plus a new content process from the new binary
6026 // (with static prefs {A,B,C,D,E}). The content process' call to
6027 // GetSharedPrefValue() for pref E will fail because the shared pref map was
6028 // created by the main process, which doesn't have pref E.
6029 //
6030 // This silent failure is safe. The mirror variable for pref E is already
6031 // initialized to the default value in the content process, and the main
6032 // process cannot have changed pref E because it doesn't know about it!
6033 //
6034 // Nonetheless, it's useful to have the MOZ_ASSERT here for testing of debug
6035 // builds, where this scenario involving inconsistent binaries should not
6036 // occur.
6037#define NEVER_PREF(name, cpp_type, default_value)
6038#define ALWAYS_PREF(name, base_id, full_id, cpp_type, default_value) \
6039 { \
6040 StripAtomic<cpp_type> val; \
6041 ASSERT_PREF_NOT_SANITIZED(name, cpp_type); \
6042 DebugOnly<nsresult> rv = Internals::GetSharedPrefValue(name, &val); \
6043 MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed accessing " name)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" " ("
"Failed accessing " name ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 6043); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed accessing " name ")"); do { *((volatile int*)__null
) = 6043; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
; \
6044 StaticPrefs::sMirror_##full_id = val; \
6045 }
6046#define ALWAYS_DATAMUTEX_PREF(name, base_id, full_id, cpp_type, default_value) \
6047 { \
6048 StripAtomic<cpp_type> val; \
6049 ASSERT_PREF_NOT_SANITIZED(name, cpp_type); \
6050 DebugOnly<nsresult> rv = Internals::GetSharedPrefValue(name, &val); \
6051 MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed accessing " name)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" " ("
"Failed accessing " name ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 6051); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed accessing " name ")"); do { *((volatile int*)__null
) = 6051; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
; \
6052 Internals::AssignMirror(StaticPrefs::sMirror_##full_id, \
6053 std::forward<StripAtomic<cpp_type>>(val)); \
6054 }
6055#define ONCE_PREF(name, base_id, full_id, cpp_type, default_value) \
6056 { \
6057 cpp_type val; \
6058 ASSERT_PREF_NOT_SANITIZED(name, cpp_type); \
6059 DebugOnly<nsresult> rv = \
6060 Internals::GetSharedPrefValue(ONCE_PREF_NAME(name)"$$$" name "$$$", &val); \
6061 MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed accessing " name)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" " ("
"Failed accessing " name ")", "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 6061); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed accessing " name ")"); do { *((volatile int*)__null
) = 6061; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
; \
6062 StaticPrefs::sMirror_##full_id = val; \
6063 }
6064#include "mozilla/StaticPrefListAll.h"
6065#undef NEVER_PREF
6066#undef ALWAYS_PREF
6067#undef ALWAYS_DATAMUTEX_PREF
6068#undef ONCE_PREF
6069#undef ASSERT_PREF_NOT_SANITIZED
6070
6071 // `once`-mirrored prefs have been set to their value in the step above and
6072 // outside the parent process they are immutable. We set sOncePrefRead so
6073 // that we can directly skip any lazy initializations.
6074 sOncePrefRead = true;
6075}
6076
6077} // namespace StaticPrefs
6078
6079} // namespace mozilla
6080
6081#undef ENSURE_PARENT_PROCESS
6082
6083//===========================================================================
6084// Module and factory stuff
6085//===========================================================================
6086
6087NS_IMPL_COMPONENT_FACTORY(nsPrefLocalizedString)template <> already_AddRefed<nsISupports> mozCreateComponent
<nsPrefLocalizedString>()
{
6088 auto str = MakeRefPtr<nsPrefLocalizedString>();
6089 if (NS_SUCCEEDED(str->Init())((bool)(__builtin_expect(!!(!NS_FAILED_impl(str->Init())),
1)))
) {
6090 return str.forget().downcast<nsISupports>();
6091 }
6092 return nullptr;
6093}
6094
6095namespace mozilla {
6096
6097void UnloadPrefsModule() { Preferences::Shutdown(); }
6098
6099} // namespace mozilla
6100
6101// Preference Sanitization Related Code ---------------------------------------
6102
6103#define PREF_LIST_ENTRY(s) {s, (sizeof(s) / sizeof(char)) - 1}
6104struct PrefListEntry {
6105 const char* mPrefBranch;
6106 size_t mLen;
6107};
6108
6109// A preference is 'sanitized' (i.e. not sent to web content processes) if
6110// one of two criteria are met:
6111// 1. The pref name matches one of the prefixes in the following list
6112// 2. The pref is dynamically named (i.e. not specified in all.js or
6113// StaticPrefList.yml), a string pref, and it is NOT exempted in
6114// sDynamicPrefOverrideList
6115//
6116// This behavior is codified in ShouldSanitizePreference() below.
6117// Exclusions of preferences can be defined in sOverrideRestrictionsList[].
6118static const PrefListEntry sRestrictFromWebContentProcesses[] = {
6119 // Remove prefs with user data
6120 PREF_LIST_ENTRY("datareporting.policy."),
6121 PREF_LIST_ENTRY("browser.download.lastDir"),
6122 PREF_LIST_ENTRY("browser.newtabpage.pinned"),
6123 PREF_LIST_ENTRY("browser.uiCustomization.state"),
6124 PREF_LIST_ENTRY("browser.urlbar"),
6125 PREF_LIST_ENTRY("devtools.debugger.pending-selected-location"),
6126 PREF_LIST_ENTRY("identity.fxaccounts.account.device.name"),
6127 PREF_LIST_ENTRY("identity.fxaccounts.account.telemetry.sanitized_uid"),
6128 PREF_LIST_ENTRY("identity.fxaccounts.lastSignedInUserHash"),
6129 PREF_LIST_ENTRY("print_printer"),
6130 PREF_LIST_ENTRY("services."),
6131
6132 // Remove UUIDs
6133 PREF_LIST_ENTRY("app.normandy.user_id"),
6134 PREF_LIST_ENTRY("browser.newtabpage.activity-stream.impressionId"),
6135 PREF_LIST_ENTRY("browser.pageActions.persistedActions"),
6136 PREF_LIST_ENTRY("browser.startup.lastColdStartupCheck"),
6137 PREF_LIST_ENTRY("dom.push.userAgentID"),
6138 PREF_LIST_ENTRY("extensions.webextensions.uuids"),
6139 PREF_LIST_ENTRY("privacy.userContext.extension"),
6140 PREF_LIST_ENTRY("toolkit.telemetry.cachedClientID"),
6141
6142 // Remove IDs that could be used to correlate across origins
6143 PREF_LIST_ENTRY("app.update.lastUpdateTime."),
6144 PREF_LIST_ENTRY(
6145 "browser.contentblocking.cfr-milestone.milestone-shown-time"),
6146 PREF_LIST_ENTRY("browser.contextual-services.contextId"),
6147 PREF_LIST_ENTRY("browser.laterrun.bookkeeping.profileCreationTime"),
6148 PREF_LIST_ENTRY("browser.newtabpage.activity-stream.discoverystream."),
6149 PREF_LIST_ENTRY("browser.sessionstore.upgradeBackup.latestBuildID"),
6150 PREF_LIST_ENTRY("browser.shell.mostRecentDateSetAsDefault"),
6151 PREF_LIST_ENTRY("idle.lastDailyNotification"),
6152 PREF_LIST_ENTRY("media.gmp-gmpopenh264.lastUpdate"),
6153 PREF_LIST_ENTRY("media.gmp-manager.lastCheck"),
6154 PREF_LIST_ENTRY("places.database.lastMaintenance"),
6155 PREF_LIST_ENTRY("privacy.purge_trackers.last_purge"),
6156 PREF_LIST_ENTRY("storage.vacuum.last.places.sqlite"),
6157 PREF_LIST_ENTRY("toolkit.startup.last_success"),
6158
6159 // Remove fingerprintable things
6160 PREF_LIST_ENTRY("browser.startup.homepage_override.buildID"),
6161 PREF_LIST_ENTRY("extensions.lastAppBuildId"),
6162 PREF_LIST_ENTRY("media.gmp-manager.buildID"),
6163 PREF_LIST_ENTRY("toolkit.telemetry.previousBuildID"),
6164};
6165
6166// Allowlist for prefs and branches blocklisted in
6167// sRestrictFromWebContentProcesses[], including prefs from
6168// StaticPrefList.yaml and *.js, to let them pass.
6169static const PrefListEntry sOverrideRestrictionsList[]{
6170 PREF_LIST_ENTRY("services.settings.clock_skew_seconds"),
6171 PREF_LIST_ENTRY("services.settings.last_update_seconds"),
6172 PREF_LIST_ENTRY("services.settings.loglevel"),
6173 // This is really a boolean dynamic pref, but one Nightly user
6174 // has it set as a string...
6175 PREF_LIST_ENTRY("services.settings.preview_enabled"),
6176 PREF_LIST_ENTRY("services.settings.server"),
6177};
6178
6179// These prefs are dynamically-named (i.e. not specified in prefs.js or
6180// StaticPrefList) and would normally by blocklisted but we allow them through
6181// anyway, so this override list acts as an allowlist
6182static const PrefListEntry sDynamicPrefOverrideList[]{
6183 PREF_LIST_ENTRY("accessibility.tabfocus"),
6184 PREF_LIST_ENTRY("app.update.channel"),
6185 PREF_LIST_ENTRY("apz.subtest"),
6186 PREF_LIST_ENTRY("autoadmin.global_config_url"), // Bug 1780575
6187 PREF_LIST_ENTRY("browser.contentblocking.category"),
6188 PREF_LIST_ENTRY("browser.dom.window.dump.file"),
6189 PREF_LIST_ENTRY("browser.search.region"),
6190 PREF_LIST_ENTRY(
6191 "browser.tabs.remote.testOnly.failPBrowserCreation.browsingContext"),
6192 PREF_LIST_ENTRY("browser.uitour.testingOrigins"),
6193 PREF_LIST_ENTRY("browser.urlbar.loglevel"),
6194 PREF_LIST_ENTRY("browser.urlbar.opencompanionsearch.enabled"),
6195 PREF_LIST_ENTRY("capability.policy"),
6196 PREF_LIST_ENTRY("dom.securecontext.allowlist"),
6197 PREF_LIST_ENTRY("extensions.foobaz"),
6198 PREF_LIST_ENTRY(
6199 "extensions.formautofill.creditCards.heuristics.testConfidence"),
6200 PREF_LIST_ENTRY("general.appversion.override"),
6201 PREF_LIST_ENTRY("general.buildID.override"),
6202 PREF_LIST_ENTRY("general.oscpu.override"),
6203 PREF_LIST_ENTRY("general.useragent.override"),
6204 PREF_LIST_ENTRY("general.platform.override"),
6205 PREF_LIST_ENTRY("gfx.blacklist."),
6206 PREF_LIST_ENTRY("font.system.whitelist"),
6207 PREF_LIST_ENTRY("font.name."),
6208 PREF_LIST_ENTRY("intl.date_time.pattern_override."),
6209 PREF_LIST_ENTRY("intl.hyphenation-alias."),
6210 PREF_LIST_ENTRY("logging.config.LOG_FILE"),
6211 PREF_LIST_ENTRY("media.audio_loopback_dev"),
6212 PREF_LIST_ENTRY("media.decoder-doctor."),
6213 PREF_LIST_ENTRY("media.cubeb.backend"),
6214 PREF_LIST_ENTRY("media.cubeb.output_device"),
6215 PREF_LIST_ENTRY("media.getusermedia.fake-camera-name"),
6216 PREF_LIST_ENTRY("media.hls.server.url"),
6217 PREF_LIST_ENTRY("media.peerconnection.nat_simulator.filtering_type"),
6218 PREF_LIST_ENTRY("media.peerconnection.nat_simulator.mapping_type"),
6219 PREF_LIST_ENTRY("media.peerconnection.nat_simulator.redirect_address"),
6220 PREF_LIST_ENTRY("media.peerconnection.nat_simulator.redirect_targets"),
6221 PREF_LIST_ENTRY("media.video_loopback_dev"),
6222 PREF_LIST_ENTRY("media.webspeech.service.endpoint"),
6223 PREF_LIST_ENTRY("network.gio.supported-protocols"),
6224 PREF_LIST_ENTRY("network.protocol-handler.external."),
6225 PREF_LIST_ENTRY("network.security.ports.banned"),
6226 PREF_LIST_ENTRY("nimbus.syncdatastore."),
6227 PREF_LIST_ENTRY("pdfjs."),
6228 PREF_LIST_ENTRY("plugins.force.wmode"),
6229 PREF_LIST_ENTRY("print.printer_"),
6230 PREF_LIST_ENTRY("print_printer"),
6231 PREF_LIST_ENTRY("places.interactions.customBlocklist"),
6232 PREF_LIST_ENTRY("remote.log.level"),
6233 // services.* preferences should be added in sOverrideRestrictionsList[] -
6234 // the whole preference branch gets sanitized by default.
6235 PREF_LIST_ENTRY("spellchecker.dictionary"),
6236 PREF_LIST_ENTRY("test.char"),
6237 PREF_LIST_ENTRY("Test.IPC."),
6238 PREF_LIST_ENTRY("exists.thenDoesNot"),
6239 PREF_LIST_ENTRY("type.String."),
6240 PREF_LIST_ENTRY("toolkit.mozprotocol.url"),
6241 PREF_LIST_ENTRY("toolkit.telemetry.log.level"),
6242 PREF_LIST_ENTRY("ui."),
6243};
6244
6245#undef PREF_LIST_ENTRY
6246
6247static bool ShouldSanitizePreference(const Pref* const aPref) {
6248 // In the parent process, we use a heuristic to decide if a pref
6249 // value should be sanitized before sending to subprocesses.
6250 MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 6250); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 6250; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6251
6252 const char* prefName = aPref->Name();
6253
6254 // If a pref starts with this magic string, it is a Once-Initialized pref
6255 // from Static Prefs. It should* not be in the above list and while it looks
6256 // like a dnyamically named pref, it is not.
6257 // * nothing enforces this
6258 if (strncmp(prefName, "$$$", 3) == 0) {
6259 return false;
6260 }
6261
6262 // First check against the denylist.
6263 // The services pref is an annoying one - it's much easier to blocklist
6264 // the whole branch and then add this one check to let this one annoying
6265 // pref through.
6266 for (const auto& entry : sRestrictFromWebContentProcesses) {
6267 if (strncmp(entry.mPrefBranch, prefName, entry.mLen) == 0) {
6268 for (const auto& pasEnt : sOverrideRestrictionsList) {
6269 if (strncmp(pasEnt.mPrefBranch, prefName, pasEnt.mLen) == 0) {
6270 return false;
6271 }
6272 }
6273 return true;
6274 }
6275 }
6276
6277 // Then check if it's a dynamically named string preference and not
6278 // in the override list
6279 if (aPref->Type() == PrefType::String && !aPref->HasDefaultValue()) {
6280 for (const auto& entry : sDynamicPrefOverrideList) {
6281 if (strncmp(entry.mPrefBranch, prefName, entry.mLen) == 0) {
6282 return false;
6283 }
6284 }
6285 return true;
6286 }
6287
6288 return false;
6289}
6290
6291// Forward Declaration - it's not defined in the .h, because we don't need to;
6292// it's only used here.
6293template <class T>
6294static bool IsPreferenceSanitized_Impl(const T& aPref);
6295
6296static bool IsPreferenceSanitized(const Pref* const aPref) {
6297 return IsPreferenceSanitized_Impl(*aPref);
6298}
6299
6300static bool IsPreferenceSanitized(const PrefWrapper& aPref) {
6301 return IsPreferenceSanitized_Impl(aPref);
6302}
6303
6304template <class T>
6305static bool IsPreferenceSanitized_Impl(const T& aPref) {
6306 if (aPref.IsSanitized()) {
6307 MOZ_DIAGNOSTIC_ASSERT(!XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!XRE_IsParentProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 6307); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 6307; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6308 MOZ_DIAGNOSTIC_ASSERT(XRE_IsContentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsContentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsContentProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsContentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 6308); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsContentProcess()"
")"); do { *((volatile int*)__null) = 6308; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6309 return true;
6310 }
6311 return false;
6312}
6313
6314namespace mozilla {
6315
6316// This is the only Check Sanitization function exposed outside of
6317// Preferences.cpp, because this is the only one ever called from
6318// outside this file.
6319bool IsPreferenceSanitized(const char* aPrefName) {
6320 // Perform this comparison (see notes above) early to avoid a lookup
6321 // if we can avoid it.
6322 if (strncmp(aPrefName, "$$$", 3) == 0) {
6323 return false;
6324 }
6325
6326 if (!gContentProcessPrefsAreInited) {
6327 return false;
6328 }
6329
6330 if (Maybe<PrefWrapper> pref = pref_Lookup(aPrefName)) {
6331 if (pref.isNothing()) {
6332 return true;
6333 }
6334 return IsPreferenceSanitized(pref.value());
6335 }
6336
6337 return true;
6338}
6339
6340Atomic<bool, Relaxed> sOmitBlocklistedPrefValues(false);
6341Atomic<bool, Relaxed> sCrashOnBlocklistedPref(false);
6342
6343void OnFissionBlocklistPrefChange(const char* aPref, void* aData) {
6344 if (strcmp(aPref, kFissionEnforceBlockList) == 0) {
6345 sCrashOnBlocklistedPref =
6346 StaticPrefs::fission_enforceBlocklistedPrefsInSubprocesses();
6347 } else if (strcmp(aPref, kFissionOmitBlockListValues) == 0) {
6348 sOmitBlocklistedPrefValues =
6349 StaticPrefs::fission_omitBlocklistedPrefsInSubprocesses();
6350 } else {
6351 MOZ_CRASH("Unknown pref passed to callback")do { do { } while (false); MOZ_ReportCrash("" "Unknown pref passed to callback"
, "/var/lib/jenkins/workspace/firefox-scan-build/modules/libpref/Preferences.cpp"
, 6351); AnnotateMozCrashReason("MOZ_CRASH(" "Unknown pref passed to callback"
")"); do { *((volatile int*)__null) = 6351; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
6352 }
6353}
6354
6355} // namespace mozilla
6356
6357// This file contains the C wrappers for the C++ static pref getters, as used
6358// by Rust code.
6359#include "init/StaticPrefsCGetters.cpp"