Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/CmdLineAndEnvUtils.h
Warning:line 751, column 1
Potential leak of memory pointed to by 'expr'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name nsAppRunner.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=/root/firefox-clang/obj-x86_64-pc-linux-gnu/toolkit/xre -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/toolkit/xre -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D TELEMETRY_PING_FORMAT_VERSION=4 -D PROXY_PRINTING=1 -D USE_GLX_TEST -D MOZ_APP_NAME="firefox" -D MOZ_APP_BASENAME="Firefox" -D MOZ_APP_DISPLAYNAME="Nightly" -D MOZ_APP_VENDOR="Mozilla" -D MOZ_APP_VERSION="158.0a1" -D OS_TARGET="Linux" -D MOZ_WIDGET_TOOLKIT="gtk" -D MOZ_UPDATER -D MOZ_DISTRIBUTION_ID="org.mozilla" -D TARGET_OS_ABI="Linux_x86_64-gcc3" -D GRE_MILESTONE=158.0a1 -D MOZ_APP_VERSION_DISPLAY=158.0a1 -D APP_VERSION=158.0a1 -D APP_ID={ec8030f7-c20a-464f-9b0e-13a3a9e97384} -D MOZ_BUILD_APP_IS_BROWSER -D MAR_NSS -D TOPOBJDIR=/root/firefox-clang/obj-x86_64-pc-linux-gnu -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/toolkit/xre -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/toolkit/xre -I /root/firefox-clang/toolkit/components/remote -I /root/firefox-clang/widget -I /root/firefox-clang/widget/gtk -I /root/firefox-clang/toolkit/components/printingui -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/third_party/abseil-cpp -I /root/firefox-clang/toolkit/components/telemetry -I /root/firefox-clang/xpcom/base -I /root/firefox-clang/other-licenses/nsis/Contrib/CityHash/cityhash -I /root/firefox-clang/toolkit/components/find -I /root/firefox-clang/toolkit/components/printingui/ipc -I /root/firefox-clang/toolkit/components/windowwatcher -I /root/firefox-clang/toolkit/mozapps/update/common -I /root/firefox-clang/toolkit/profile -I /root/firefox-clang/config -I /root/firefox-clang/dom/base -I /root/firefox-clang/dom/commandhandler -I /root/firefox-clang/dom/ipc -I /root/firefox-clang/dom/webbrowserpersist -I /root/firefox-clang/js/xpconnect/loader -I /root/firefox-clang/testing/gtest/mozilla -I /root/firefox-clang/third_party/sqlite3/ext -I /root/firefox-clang/toolkit/crashreporter -I /root/firefox-clang/xpcom/build -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -I /usr/include/uuid -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gtk-3.0/unix-print -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cloudproviders -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/fribidi -I /usr/include/harfbuzz -I /usr/include/atk-1.0 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/glycin-2 -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/gio-unix-2.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/sysprof-6 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -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-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 -Wno-character-conversion -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-11-105204-3678582-1 -x c++ /root/firefox-clang/toolkit/xre/nsAppRunner.cpp

/root/firefox-clang/toolkit/xre/nsAppRunner.cpp

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5#include "mozilla/dom/ContentParent.h"
6#include "mozilla/dom/ContentChild.h"
7#include "mozilla/ipc/GeckoChildProcessHost.h"
8
9#include "mozilla/AppShutdown.h"
10#include "mozilla/Assertions.h"
11#include "mozilla/Attributes.h"
12#include "mozilla/BaseProfiler.h"
13#include "mozilla/Components.h"
14#include "mozilla/FilePreferences.h"
15#include "mozilla/FOG.h"
16#include "mozilla/ChaosMode.h"
17#include "mozilla/HelperMacros.h"
18#include "mozilla/CmdLineAndEnvUtils.h"
19#include "mozilla/IOInterposer.h"
20#include "mozilla/ipc/UtilityProcessChild.h"
21#include "mozilla/Likely.h"
22#include "mozilla/Logging.h"
23#include "mozilla/Preferences.h"
24#include "mozilla/PreferenceSheet.h"
25#include "mozilla/Printf.h"
26#include "mozilla/ProcessType.h"
27#include "mozilla/ResultExtensions.h"
28#include "mozilla/RuntimeExceptionModule.h"
29#include "mozilla/ScopeExit.h"
30#include "mozilla/StaticPrefs_browser.h"
31#include "mozilla/StaticPrefs_fission.h"
32#include "mozilla/StaticPrefs_security.h"
33#include "mozilla/StaticPrefs_widget.h"
34#include "mozilla/glean/SecuritySandboxMetrics.h"
35#include "mozilla/Telemetry.h"
36#include "mozilla/Try.h"
37#include "mozilla/intl/LocaleService.h"
38#include "mozilla/JSONWriter.h"
39#include "mozilla/gfx/gfxVars.h"
40#include "mozilla/glean/ToolkitMozappsUpdateSharedMetrics.h"
41#include "mozilla/glean/ToolkitXreMetrics.h"
42#include "mozilla/glean/GleanPings.h"
43#include "mozilla/widget/TextRecognition.h"
44#include "mozJSModuleLoader.h"
45
46#include "nsAppRunner.h"
47#include "mozilla/XREAppData.h"
48#include "mozilla/Bootstrap.h"
49#if defined(MOZ_UPDATER1) && !defined(MOZ_WIDGET_ANDROID)
50# include "nsUpdateDriver.h"
51# include "nsUpdateSyncManager.h"
52#endif
53#include "ProfileReset.h"
54
55#ifdef XP_MACOSX
56# include "nsVersionComparator.h"
57# include "nsCocoaFeatures.h"
58# include "mozilla/glean/WidgetCocoaMetrics.h"
59# include "MacLaunchHelper.h"
60# include "MacApplicationDelegate.h"
61# include "MacAutoreleasePool.h"
62# include "MacRunFromDmgUtils.h"
63# ifdef NIGHTLY_BUILD1
64# include "ASWebAuthSessionHandler.h"
65# endif
66// these are needed for sysctl
67# include <sys/types.h>
68# include <sys/sysctl.h>
69#endif
70
71#include "prnetdb.h"
72#include "prprf.h"
73#include "prproces.h"
74#include "prenv.h"
75#include "prtime.h"
76
77#include "nsIAppStartup.h"
78#include "nsCategoryManagerUtils.h"
79#include "nsIMutableArray.h"
80#include "nsCommandLine.h"
81#include "nsIComponentRegistrar.h"
82#include "nsIDialogParamBlock.h"
83#include "mozilla/ModuleUtils.h"
84#include "nsIIOService.h"
85#include "nsIObserverService.h"
86#include "nsINativeAppSupport.h"
87#include "nsIPlatformInfo.h"
88#include "nsIProcess.h"
89#include "nsIProfileUnlocker.h"
90#include "nsIPromptService.h"
91#include "nsIPropertyBag2.h"
92#include "nsIServiceManager.h"
93#include "nsIStringBundle.h"
94#include "nsISupportsPrimitives.h"
95#include "nsIToolkitProfile.h"
96#include "nsToolkitProfileService.h"
97#include "nsIURI.h"
98#include "nsIURL.h"
99#include "nsIWindowCreator.h"
100#include "nsIWindowWatcher.h"
101#include "nsIXULAppInfo.h"
102#include "nsIXULRuntime.h"
103#include "nsPIDOMWindow.h"
104#include "nsIWidget.h"
105#include "nsAppShellCID.h"
106#include "mozilla/dom/quota/QuotaManager.h"
107#include "mozilla/scache/StartupCache.h"
108#include "gfxPlatform.h"
109#include "PDMFactory.h"
110#ifdef XP_MACOSX
111# include "gfxPlatformMac.h"
112#endif
113
114#ifdef XP_WIN
115# include "nsIWinAppHelper.h"
116# include <windows.h>
117# include <intrin.h>
118# include <math.h>
119# include "cairo/cairo-features.h"
120# include "detect_win32k_conflicts.h"
121# include "mozilla/PreXULSkeletonUI.h"
122# include "mozilla/DllPrefetchExperimentRegistryInfo.h"
123# include "mozilla/WindowsDllBlocklist.h"
124# include "mozilla/WindowsMsctfInitialization.h"
125# include "mozilla/WindowsOleAut32Initialization.h"
126# include "mozilla/WindowsProcessMitigations.h"
127# include "mozilla/WindowsVersion.h"
128# include "mozilla/WinHeaderOnlyUtils.h"
129# include "mozilla/mscom/ProcessRuntime.h"
130# include "mozilla/mscom/ProfilerMarkers.h"
131# include "WinTokenUtils.h"
132
133# if defined(MOZ_LAUNCHER_PROCESS)
134# include "mozilla/LauncherRegistryInfo.h"
135# endif
136
137# if defined(MOZ_DEFAULT_BROWSER_AGENT)
138# include "nsIWindowsRegKey.h"
139# endif
140
141# ifndef PROCESS_DEP_ENABLE
142# define PROCESS_DEP_ENABLE 0x1
143# endif
144#endif
145
146#if defined(MOZ_SANDBOX1)
147# include "mozilla/SandboxSettings.h"
148#endif
149
150#ifdef ACCESSIBILITY1
151# include "nsAccessibilityService.h"
152# include "mozilla/a11y/Platform.h"
153# if defined(XP_WIN)
154# include "mozilla/a11y/Compatibility.h"
155# endif
156#endif
157
158#include "nsCRT.h"
159#include "nsCOMPtr.h"
160#include "nsDirectoryServiceDefs.h"
161#include "nsDirectoryServiceUtils.h"
162#include "nsEmbedCID.h"
163#include "nsIDUtils.h"
164#include "nsNetUtil.h"
165#include "nsReadableUtils.h"
166#include "nsXPCOM.h"
167#include "nsXPCOMCIDInternal.h"
168#include "nsString.h"
169#include "nsPrintfCString.h"
170#include "nsVersionComparator.h"
171
172#include "nsAppDirectoryServiceDefs.h"
173#include "nsXULAppAPI.h"
174#include "nsXREDirProvider.h"
175
176#include "nsINIParser.h"
177#include "mozilla/Omnijar.h"
178#include "mozilla/StartupTimeline.h"
179#include "mozilla/LateWriteChecks.h"
180
181#include <stdlib.h>
182
183#ifdef XP_UNIX1
184# include <errno(*__errno_location ()).h>
185# include <pwd.h>
186# include <string.h>
187# include <sys/resource.h>
188# include <sys/stat.h>
189# include <unistd.h>
190#endif
191
192#ifdef XP_WIN
193# include <process.h>
194# include <shlobj.h>
195# include "mozilla/WinDllServices.h"
196# include "nsThreadUtils.h"
197# include "WinUtils.h"
198#endif
199
200#ifdef XP_MACOSX
201# include "nsILocalFileMac.h"
202# include "nsCommandLineServiceMac.h"
203#endif
204
205// for X remote support
206#if defined(MOZ_HAS_REMOTE1)
207# include "nsRemoteService.h"
208#endif
209
210#if defined(DEBUG1) && defined(XP_WIN)
211# include <malloc.h>
212#endif
213
214#if defined(XP_MACOSX)
215# include <Carbon/Carbon.h>
216#endif
217
218#ifdef DEBUG1
219# include "mozilla/Logging.h"
220# include "mozilla/StaticPrefs_toolkit.h"
221#endif
222
223#include "nsExceptionHandler.h"
224#include "nsICrashReporter.h"
225#include "nsIPrefService.h"
226#include "nsIMemoryInfoDumper.h"
227#include "js/String.h"
228#if defined(XP_LINUX1) && !defined(ANDROID)
229# include "mozilla/widget/LSBUtils.h"
230#endif
231
232#include "base/command_line.h"
233#include "GTestRunner.h"
234
235#ifdef MOZ_WIDGET_ANDROID
236# include "gfxAndroidPlatform.h"
237# include "mozilla/java/GeckoAppShellWrappers.h"
238#endif
239
240#if defined(MOZ_SANDBOX1)
241# if defined(XP_LINUX1) && !defined(ANDROID)
242# include "mozilla/SandboxInfo.h"
243# elif defined(XP_WIN)
244# include "sandboxBroker.h"
245# endif
246#endif
247
248#ifdef MOZ_CODE_COVERAGE
249# include "mozilla/CodeCoverageHandler.h"
250#endif
251
252#include "GMPProcessChild.h"
253#include "SafeMode.h"
254
255#ifdef MOZ_BACKGROUNDTASKS1
256# include "mozilla/BackgroundTasks.h"
257# include "nsIPowerManagerService.h"
258# include "nsIStringBundle.h"
259#endif
260
261#ifdef USE_GLX_TEST1
262# include "mozilla/GUniquePtr.h"
263# include "mozilla/GfxInfo.h"
264#endif
265
266#ifdef MOZ_WIDGET_GTK1
267# include "nsAppShell.h"
268#endif
269#ifdef MOZ_ENABLE_DBUS1
270# include "DBusService.h"
271#endif
272
273extern void InstallSignalHandlers(const char* ProgramName);
274
275#define FILE_COMPATIBILITY_INFO"compatibility.ini"_ns "compatibility.ini"_ns
276#define FILE_INVALIDATE_CACHES".purgecaches"_ns ".purgecaches"_ns
277#define FILE_STARTUP_INCOMPLETEu".startup-incomplete"_ns u".startup-incomplete"_ns
278
279#if defined(MOZ_BLOCK_PROFILE_DOWNGRADE1) || defined(MOZ_LAUNCHER_PROCESS) || \
280 defined(MOZ_DEFAULT_BROWSER_AGENT)
281static const char kPrefHealthReportUploadEnabled[] =
282 "datareporting.healthreport.uploadEnabled";
283#endif // defined(MOZ_BLOCK_PROFILE_DOWNGRADE) || defined(MOZ_LAUNCHER_PROCESS)
284 // || defined(MOZ_DEFAULT_BROWSER_AGENT)
285#if defined(MOZ_DEFAULT_BROWSER_AGENT)
286static const char kPrefDefaultAgentEnabled[] = "default-browser-agent.enabled";
287
288static const char kPrefServicesSettingsServer[] = "services.settings.server";
289static const char kPrefSetDefaultBrowserUserChoicePref[] =
290 "browser.shell.setDefaultBrowserUserChoice";
291#endif // defined(MOZ_DEFAULT_BROWSER_AGENT)
292
293#if defined(XP_WIN)
294static const char kPrefThemeId[] = "extensions.activeThemeID";
295# if defined(MOZ_DEFAULT_BROWSER_AGENT)
296static const char kPrefBrowserStartupBlankWindow[] =
297 "browser.startup.blankWindow";
298static const char kPrefPreXulSkeletonUI[] = "browser.startup.preXulSkeletonUI";
299# endif // defined(MOZ_DEFAULT_BROWSER_AGENT)
300#endif // defined(XP_WIN)
301
302#if defined(MOZ_WIDGET_GTK1)
303constexpr nsLiteralCString kStartupTokenNames[] = {
304 "XDG_ACTIVATION_TOKEN"_ns,
305 "DESKTOP_STARTUP_ID"_ns,
306};
307#endif
308
309int gArgc;
310char** gArgv;
311
312static const char gToolkitVersion[] = MOZ_STRINGIFY(GRE_MILESTONE)"158.0a1";
313// The gToolkitBuildID global is defined to MOZ_BUILDID via gen_buildid.py
314// in toolkit/library. See related comment in toolkit/library/moz.build.
315extern const char gToolkitBuildID[];
316
317static nsIProfileLock* gProfileLock;
318#if defined(MOZ_HAS_REMOTE1)
319constinit static RefPtr<nsRemoteService> gRemoteService;
320constinit static RefPtr<nsStartupLock> gStartupLock;
321#endif
322
323int gRestartArgc;
324char** gRestartArgv;
325
326// If gRestartedByOS is set, we were automatically restarted by the OS.
327bool gRestartedByOS = false;
328
329bool gIsGtest = false;
330
331bool gKioskMode = false;
332int gKioskMonitor = -1;
333
334bool gAllowContentAnalysisArgPresent = false;
335
336constinit nsString gAbsoluteArgv0Path;
337
338#if defined(XP_WIN)
339constinit nsString gProcessStartupShortcut;
340#endif
341
342#if defined(MOZ_WIDGET_GTK1)
343# include <glib.h>
344# include "mozilla/WidgetUtilsGtk.h"
345# include <gtk/gtk.h>
346# ifdef MOZ_WAYLAND1
347# include <gdk/gdkwayland.h>
348# include "mozilla/widget/nsWaylandDisplay.h"
349# include "wayland-proxy.h"
350# endif
351# ifdef MOZ_X111
352# include <gdk/gdkx.h>
353# endif /* MOZ_X11 */
354#endif
355
356#if defined(MOZ_WAYLAND1)
357constinit std::unique_ptr<WaylandProxy> gWaylandProxy;
358#endif
359
360#include "BinaryPath.h"
361
362#ifdef FUZZING
363# include "FuzzerRunner.h"
364
365namespace mozilla {
366FuzzerRunner* fuzzerRunner = 0;
367} // namespace mozilla
368
369# ifdef LIBFUZZER
370void XRE_LibFuzzerSetDriver(LibFuzzerDriver aDriver) {
371 mozilla::fuzzerRunner->setParams(aDriver);
372}
373# endif
374#endif // FUZZING
375
376// Undo X11/X.h's definition of None
377#undef None
378
379namespace mozilla {
380int (*RunGTest)(int*, char**) = nullptr;
381
382bool RunningGTest() { return RunGTest; }
383} // namespace mozilla
384
385using namespace mozilla;
386using namespace mozilla::widget;
387using namespace mozilla::startup;
388using mozilla::dom::ContentChild;
389using mozilla::dom::ContentParent;
390using mozilla::dom::quota::QuotaManager;
391using mozilla::intl::LocaleService;
392using mozilla::scache::StartupCache;
393
394#ifndef XP_WIN
395// Save the given word to the specified environment variable.
396static void MOZ_NEVER_INLINE__attribute__((noinline)) SaveWordToEnv(const char* name,
397 const nsACString& word) {
398 char* expr =
399 Smprintf("%s=%s", name, PromiseFlatCStringTPromiseFlatString<char>(word).get()).release();
400 if (expr) PR_SetEnv(expr);
401 // We intentionally leak |expr| here since it is required by PR_SetEnv.
402}
403#endif
404
405// Save the path of the given file to the specified environment variable.
406static void SaveFileToEnv(const char* name, nsIFile* file) {
407#ifdef XP_WIN
408 nsAutoString path;
409 file->GetPath(path);
410 SetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name).get(), path.get());
411#else
412 nsAutoCString path;
413 file->GetNativePath(path);
414 SaveWordToEnv(name, path);
415#endif
416}
417
418static bool gIsExpectedExit = false;
419
420void MozExpectedExit() { gIsExpectedExit = true; }
421
422/**
423 * Runs atexit() to catch unexpected exit from 3rd party libraries like the
424 * Intel graphics driver calling exit in an error condition. When they
425 * call exit() to report an error we won't shutdown correctly and wont catch
426 * the issue with our crash reporter.
427 */
428static void UnexpectedExit() {
429 if (!gIsExpectedExit) {
430 gIsExpectedExit = true; // Don't risk re-entrency issues when crashing.
431 MOZ_CRASH("Exit called by third party code.")do { do { } while (false); MOZ_ReportCrash("" "Exit called by third party code."
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 431); AnnotateMozCrashReason
("MOZ_CRASH(" "Exit called by third party code." ")"); do { MOZ_CrashSequence
(__null, 431); __attribute__((nomerge)) ::abort(); } while (false
); } while (false)
;
432 }
433}
434
435#if defined(MOZ_WAYLAND1)
436bool IsWaylandEnabled() {
437 static bool isWaylandEnabled = []() {
438 const char* waylandDisplay = PR_GetEnv("WAYLAND_DISPLAY");
439 if (!waylandDisplay) {
440 return false;
441 }
442 if (!PR_GetEnv("DISPLAY")) {
443 // No X11 display, so try to run wayland.
444 return true;
445 }
446 // MOZ_ENABLE_WAYLAND is our primary Wayland on/off switch.
447 if (const char* waylandPref = PR_GetEnv("MOZ_ENABLE_WAYLAND")) {
448 return *waylandPref == '1';
449 }
450 if (const char* backendPref = PR_GetEnv("GDK_BACKEND")) {
451 if (!strncmp(backendPref, "wayland", 7)) {
452 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Wayland backend should be enabled by MOZ_ENABLE_WAYLAND=1."
"GDK_BACKEND is a Gtk3 debug variable and may cause issues."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
454)
453 "Wayland backend should be enabled by MOZ_ENABLE_WAYLAND=1."NS_DebugBreak(NS_DEBUG_WARNING, "Wayland backend should be enabled by MOZ_ENABLE_WAYLAND=1."
"GDK_BACKEND is a Gtk3 debug variable and may cause issues."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
454)
454 "GDK_BACKEND is a Gtk3 debug variable and may cause issues.")NS_DebugBreak(NS_DEBUG_WARNING, "Wayland backend should be enabled by MOZ_ENABLE_WAYLAND=1."
"GDK_BACKEND is a Gtk3 debug variable and may cause issues."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
454)
;
455 return true;
456 }
457 }
458 // Enable by default when we're running on a recent enough GTK version. We'd
459 // like to check further details like compositor version and so on ideally
460 // to make sure we don't enable it on old Mutter or what not, but we can't,
461 // so let's assume that if the user is running on a Wayland session by
462 // default we're ok, since either the distro has enabled Wayland by default,
463 // or the user has gone out of their way to use Wayland.
464 return !gtk_check_version(3, 24, 30);
465 }();
466 return isWaylandEnabled;
467}
468#else
469bool IsWaylandEnabled() { return false; }
470#endif
471
472/**
473 * Output a string to the user. This method is really only meant to be used to
474 * output last-ditch error messages designed for developers NOT END USERS.
475 *
476 * @param isError
477 * Pass true to indicate severe errors.
478 * @param fmt
479 * printf-style format string followed by arguments.
480 */
481static MOZ_FORMAT_PRINTF(2, 3)__attribute__((format(printf, 2, 3))) void Output(bool isError, const char* fmt, ...) {
482 va_list ap;
483 va_start(ap, fmt)__builtin_va_start(ap, fmt);
484
485#if defined(XP_WIN) && !MOZ_WINCONSOLE
486 SmprintfPointer msg = mozilla::Vsmprintf(fmt, ap);
487 if (msg) {
488 UINT flags = MB_OK;
489 if (isError)
490 flags |= MB_ICONERROR;
491 else
492 flags |= MB_ICONINFORMATION;
493
494 wchar_t wide_msg[1024];
495 MultiByteToWideChar(CP_ACP, 0, msg.get(), -1, wide_msg,
496 sizeof(wide_msg) / sizeof(wchar_t));
497
498 wchar_t wide_caption[128];
499 MultiByteToWideChar(CP_ACP, 0, gAppData ? gAppData->name : "XULRunner", -1,
500 wide_caption, sizeof(wide_caption) / sizeof(wchar_t));
501 MessageBoxW(nullptr, wide_msg, wide_caption, flags);
502 }
503#elif defined(MOZ_WIDGET_ANDROID)
504 SmprintfPointer msg = mozilla::Vsmprintf(fmt, ap);
505 if (msg) {
506 __android_log_print(isError ? ANDROID_LOG_ERROR : ANDROID_LOG_INFO,
507 "GeckoRuntime", "%s", msg.get());
508 }
509#else
510 vfprintf(stderrstderr, fmt, ap);
511#endif
512
513 va_end(ap)__builtin_va_end(ap);
514}
515
516/**
517 * Check for a commandline flag. If the flag takes a parameter, the
518 * parameter is returned in aParam. Flags may be in the form -arg or
519 * --arg (or /arg on win32).
520 *
521 * @param aArg the parameter to check. Must be lowercase.
522 * @param aParam if non-null, the -arg <data> will be stored in this pointer.
523 * This is *not* allocated, but rather a pointer to the argv data.
524 * @param aFlags flags @see CheckArgFlag
525 */
526static ArgResult CheckArg(const char* aArg, const char** aParam = nullptr,
527 CheckArgFlag aFlags = CheckArgFlag::RemoveArg) {
528 MOZ_ASSERT(gArgv, "gArgv must be initialized before CheckArg()")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(gArgv)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(gArgv))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("gArgv" " (" "gArgv must be initialized before CheckArg()"
")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 528)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "gArgv" ") (" "gArgv must be initialized before CheckArg()"
")"); do { MOZ_CrashSequence(__null, 528); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
529 return CheckArg(gArgc, gArgv, aArg, aParam, aFlags);
530}
531
532/**
533 * Check for a commandline flag. Ignore data that's passed in with the flag.
534 * Flags may be in the form -arg or --arg (or /arg on win32).
535 * Will not remove flag if found.
536 *
537 * @param aArg the parameter to check. Must be lowercase.
538 */
539static ArgResult CheckArgExists(const char* aArg) {
540 return CheckArg(aArg, nullptr, CheckArgFlag::None);
541}
542
543bool gSafeMode = false;
544bool gFxREmbedded = false;
545
546enum E10sStatus {
547 kE10sEnabledByDefault,
548 kE10sForceDisabled,
549};
550
551static bool gBrowserTabsRemoteAutostart = false;
552static E10sStatus gBrowserTabsRemoteStatus;
553static bool gBrowserTabsRemoteAutostartInitialized = false;
554
555namespace mozilla {
556
557bool BrowserTabsRemoteAutostart() {
558 if (gBrowserTabsRemoteAutostartInitialized) {
559 return gBrowserTabsRemoteAutostart;
560 }
561 gBrowserTabsRemoteAutostartInitialized = true;
562
563 // If we're not in the parent process, we are running E10s.
564 if (!XRE_IsParentProcess()) {
565 gBrowserTabsRemoteAutostart = true;
566 return gBrowserTabsRemoteAutostart;
567 }
568
569 gBrowserTabsRemoteAutostart = true;
570 E10sStatus status = kE10sEnabledByDefault;
571
572// We are checking to ensure that either MOZILLA_OFFICIAL is undefined or that
573// xpc::AreNonLocalConnectionsDisabled() is true. If either check matches,
574// we move on to check the MOZ_FORCE_DISABLE_E10S environment variable which
575// must equal "1" to proceed with disabling e10s.
576#if defined(MOZILLA_OFFICIAL)
577 bool allowDisablingE10s = xpc::AreNonLocalConnectionsDisabled();
578#else
579 bool allowDisablingE10s = true;
580#endif
581
582 if (gBrowserTabsRemoteAutostart && allowDisablingE10s) {
583 const char* forceDisable = PR_GetEnv("MOZ_FORCE_DISABLE_E10S");
584 if (forceDisable && !strcmp(forceDisable, "1")) {
585 gBrowserTabsRemoteAutostart = false;
586 status = kE10sForceDisabled;
587 }
588 }
589
590 gBrowserTabsRemoteStatus = status;
591
592 return gBrowserTabsRemoteAutostart;
593}
594
595} // namespace mozilla
596
597// Win32k Infrastructure ==============================================
598
599// This bool tells us if we have initialized the following two statics
600// upon startup.
601
602static bool gWin32kInitialized = false;
603
604// Win32k Lockdown for the current session is determined once, at startup,
605// and then remains the same for the duration of the session.
606
607static nsIXULRuntime::ContentWin32kLockdownState gWin32kStatus;
608
609// The status of the win32k experiment. It is determined once, at startup,
610// and then remains the same for the duration of the session.
611
612static nsIXULRuntime::ExperimentStatus gWin32kExperimentStatus =
613 nsIXULRuntime::eExperimentStatusUnenrolled;
614
615#ifdef XP_WIN
616// The states for win32k lockdown can be generalized to:
617// - User doesn't meet requirements (bad OS, webrender, remotegl) aka
618// PersistentRequirement
619// - User has Safe Mode enabled, Win32k Disabled by Env Var, or E10S disabled
620// by Env Var aka TemporaryRequirement
621// - User has set the win32k pref to something non-default aka NonDefaultPref
622// - User has been enrolled in the experiment and does what it says aka
623// Enrolled
624// - User does the default aka Default
625//
626// We expect the below behvaior. In the code, there may be references to these
627// behaviors (e.g. [A]) but not always.
628//
629// [A] Becoming enrolled in the experiment while NonDefaultPref disqualifies
630// you upon next browser start
631// [B] Becoming enrolled in the experiment while PersistentRequirement
632// disqualifies you upon next browser start
633// [C] Becoming enrolled in the experiment while TemporaryRequirement does not
634// disqualify you
635// [D] Becoming enrolled in the experiment will only take effect after restart
636// [E] While enrolled, becoming PersistentRequirement will not disqualify you
637// until browser restart, but if the state is present at browser start,
638// will disqualify you. Additionally, it will not affect the session value
639// of gWin32kStatus.
640// XXX(bobowen): I hope both webrender and wbgl.out-of-process require a
641// restart to take effect!
642// [F] While enrolled, becoming NonDefaultPref will disqualify you upon next
643// browser start
644// [G] While enrolled, becoming TemporaryRequirement will _not_ disqualify you,
645// but the session status will prevent win32k lockdown from taking effect.
646
647// The win32k pref
648static const char kPrefWin32k[] = "security.sandbox.content.win32k-disable";
649
650// The current enrollment status as controlled by Normandy. This value is only
651// stored in the default preference branch, and is not persisted across
652// sessions by the preference service. It therefore isn't available early
653// enough at startup, and needs to be synced to a preference in the user
654// branch which is persisted across sessions.
655static const char kPrefWin32kExperimentEnrollmentStatus[] =
656 "security.sandbox.content.win32k-experiment.enrollmentStatus";
657
658// The enrollment status to be used at browser startup. This automatically
659// synced from the above enrollmentStatus preference whenever the latter is
660// changed. We reused the Fission experiment enum - it can have any of the
661// values defined in the `nsIXULRuntime_ExperimentStatus` enum _except_ rollout.
662// Meanings are documented in the declaration of
663// `nsIXULRuntime.fissionExperimentStatus`
664static const char kPrefWin32kExperimentStartupEnrollmentStatus[] =
665 "security.sandbox.content.win32k-experiment.startupEnrollmentStatus";
666
667namespace mozilla {
668
669bool Win32kExperimentEnrolled() {
670 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()"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 670); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "XRE_IsParentProcess()" ")"); do { MOZ_CrashSequence
(__null, 670); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
671 return gWin32kExperimentStatus == nsIXULRuntime::eExperimentStatusControl ||
672 gWin32kExperimentStatus == nsIXULRuntime::eExperimentStatusTreatment;
673}
674
675} // namespace mozilla
676
677static bool Win32kRequirementsUnsatisfied(
678 nsIXULRuntime::ContentWin32kLockdownState aStatus) {
679 return aStatus == nsIXULRuntime::ContentWin32kLockdownState::
680 OperatingSystemNotSupported ||
681 aStatus ==
682 nsIXULRuntime::ContentWin32kLockdownState::MissingWebRender ||
683 aStatus ==
684 nsIXULRuntime::ContentWin32kLockdownState::DecodersArentRemote;
685}
686
687static void Win32kExperimentDisqualify() {
688 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()"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 688); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "XRE_IsParentProcess()" ")"); do { MOZ_CrashSequence
(__null, 688); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
689 Preferences::SetUint(kPrefWin32kExperimentEnrollmentStatus,
690 nsIXULRuntime::eExperimentStatusDisqualified);
691}
692
693static void OnWin32kEnrollmentStatusChanged(const char* aPref, void* aData) {
694 auto newStatusInt =
695 Preferences::GetUint(kPrefWin32kExperimentEnrollmentStatus,
696 nsIXULRuntime::eExperimentStatusUnenrolled);
697 auto newStatus = newStatusInt < nsIXULRuntime::eExperimentStatusCount
698 ? nsIXULRuntime::ExperimentStatus(newStatusInt)
699 : nsIXULRuntime::eExperimentStatusDisqualified;
700
701 // Set the startup pref for next browser start [D]
702 Preferences::SetUint(kPrefWin32kExperimentStartupEnrollmentStatus, newStatus);
703}
704
705namespace {
706// This observer is notified during `profile-before-change`, and ensures that
707// the experiment enrollment status is synced over before the browser shuts
708// down, even if it was not modified since win32k was initialized.
709class Win32kEnrollmentStatusShutdownObserver final : public nsIObserver {
710 public:
711 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:
712
713 NS_IMETHODvirtual nsresult Observe(nsISupports* aSubject, const char* aTopic,
714 const char16_t* aData) override {
715 MOZ_ASSERT(!strcmp("profile-before-change", aTopic))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!strcmp("profile-before-change", aTopic))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!strcmp("profile-before-change", aTopic)))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!strcmp(\"profile-before-change\", aTopic)"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 715); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!strcmp(\"profile-before-change\", aTopic)"
")"); do { MOZ_CrashSequence(__null, 715); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
716 OnWin32kEnrollmentStatusChanged(kPrefWin32kExperimentEnrollmentStatus,
717 nullptr);
718 return NS_OK;
719 }
720
721 private:
722 ~Win32kEnrollmentStatusShutdownObserver() = default;
723};
724NS_IMPL_ISUPPORTS(Win32kEnrollmentStatusShutdownObserver, nsIObserver)MozExternalRefCountType Win32kEnrollmentStatusShutdownObserver
::AddRef(void) { static_assert(!std::is_destructible_v<Win32kEnrollmentStatusShutdownObserver
>, "Reference-counted class " "Win32kEnrollmentStatusShutdownObserver"
" 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" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 724); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 724
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("Win32kEnrollmentStatusShutdownObserver" != nullptr
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("Win32kEnrollmentStatusShutdownObserver" != nullptr)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"Win32kEnrollmentStatusShutdownObserver\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 724); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"Win32kEnrollmentStatusShutdownObserver\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 724); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("Win32kEnrollmentStatusShutdownObserver" " not thread-safe")
; nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"Win32kEnrollmentStatusShutdownObserver"), (uint32_t)(sizeof(
*this))); return count; } MozExternalRefCountType Win32kEnrollmentStatusShutdownObserver
::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" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 724); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 724
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("Win32kEnrollmentStatusShutdownObserver" != nullptr
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("Win32kEnrollmentStatusShutdownObserver" != nullptr)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"Win32kEnrollmentStatusShutdownObserver\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 724); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"Win32kEnrollmentStatusShutdownObserver\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 724); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("Win32kEnrollmentStatusShutdownObserver" " not thread-safe")
; const char* const nametmp = "Win32kEnrollmentStatusShutdownObserver"
; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult Win32kEnrollmentStatusShutdownObserver
::QueryInterface(const nsIID& aIID, void** aInstancePtr) {
do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "QueryInterface requires a non-NULL destination!", "aInstancePtr"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 724); 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
<Win32kEnrollmentStatusShutdownObserver, nsIObserver>, int32_t
( reinterpret_cast<char*>(static_cast<nsIObserver*>
((Win32kEnrollmentStatusShutdownObserver*)0x1000)) - reinterpret_cast
<char*>((Win32kEnrollmentStatusShutdownObserver*)0x1000
))}, {&mozilla::detail::kImplementedIID<Win32kEnrollmentStatusShutdownObserver
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIObserver*>((Win32kEnrollmentStatusShutdownObserver
*)0x1000))) - reinterpret_cast<char*>((Win32kEnrollmentStatusShutdownObserver
*)0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table
) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
725} // namespace
726
727static void OnWin32kChanged(const char* aPref, void* aData) {
728 // If we're actively enrolled in the Win32k experiment, disqualify the user
729 // from the experiment if the Win32k pref is modified. [F]
730 if (Win32kExperimentEnrolled() && Preferences::HasUserValue(kPrefWin32k)) {
731 Win32kExperimentDisqualify();
732 }
733}
734
735#endif // XP_WIN
736
737namespace mozilla {
738void EnsureWin32kInitialized();
739}
740
741nsIXULRuntime::ContentWin32kLockdownState GetLiveWin32kLockdownState() {
742#ifdef XP_WIN
743
744 // HasUserValue The Pref functions can only be called on main thread
745 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()"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 745); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 745); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
746
747# ifdef MOZ_BACKGROUNDTASKS1
748 if (BackgroundTasks::IsBackgroundTaskMode()) {
749 // Let's bail out before loading all the graphics libs.
750 return nsIXULRuntime::ContentWin32kLockdownState::DisabledByDefault;
751 }
752# endif
753
754 mozilla::EnsureWin32kInitialized();
755 gfxPlatform::GetPlatform();
756
757 if (EnvHasValue("MOZ_ENABLE_WIN32K")) {
758 return nsIXULRuntime::ContentWin32kLockdownState::DisabledByEnvVar;
759 }
760
761 if (!mozilla::BrowserTabsRemoteAutostart()) {
762 return nsIXULRuntime::ContentWin32kLockdownState::DisabledByE10S;
763 }
764
765 // Win32k lockdown is available on Win8+, but we are initially limiting it to
766 // Windows 10 v1709 (build 16299) or later. Before this COM initialization
767 // currently fails if user32.dll has loaded before it is called.
768 if (!IsWin10FallCreatorsUpdateOrLater()) {
769 return nsIXULRuntime::ContentWin32kLockdownState::
770 OperatingSystemNotSupported;
771 }
772
773 // Some (not sure exactly which) decoders are not compatible
774 if (!PDMFactory::AllDecodersAreRemote()) {
775 return nsIXULRuntime::ContentWin32kLockdownState::DecodersArentRemote;
776 }
777
778 bool prefSetByUser =
779 Preferences::HasUserValue("security.sandbox.content.win32k-disable");
780 bool prefValue = Preferences::GetBool(
781 "security.sandbox.content.win32k-disable", false, PrefValueKind::User);
782 bool defaultValue = Preferences::GetBool(
783 "security.sandbox.content.win32k-disable", false, PrefValueKind::Default);
784
785 if (prefSetByUser) {
786 if (prefValue) {
787 return nsIXULRuntime::ContentWin32kLockdownState::EnabledByUserPref;
788 } else {
789 return nsIXULRuntime::ContentWin32kLockdownState::DisabledByUserPref;
790 }
791 }
792
793 if (gWin32kExperimentStatus ==
794 nsIXULRuntime::ExperimentStatus::eExperimentStatusControl) {
795 return nsIXULRuntime::ContentWin32kLockdownState::DisabledByControlGroup;
796 } else if (gWin32kExperimentStatus ==
797 nsIXULRuntime::ExperimentStatus::eExperimentStatusTreatment) {
798 return nsIXULRuntime::ContentWin32kLockdownState::EnabledByTreatmentGroup;
799 }
800
801 if (defaultValue) {
802 return nsIXULRuntime::ContentWin32kLockdownState::EnabledByDefault;
803 } else {
804 return nsIXULRuntime::ContentWin32kLockdownState::DisabledByDefault;
805 }
806
807#else
808
809 return nsIXULRuntime::ContentWin32kLockdownState::OperatingSystemNotSupported;
810
811#endif
812}
813
814namespace mozilla {
815
816void EnsureWin32kInitialized() {
817 if (gWin32kInitialized) {
818 return;
819 }
820 gWin32kInitialized = true;
821
822#ifdef XP_WIN
823
824 // Initialize the Win32k experiment, configuring win32k's
825 // default, before checking other overrides. This allows opting-out of a
826 // Win32k experiment through about:preferences or about:config from a
827 // safemode session.
828 uint32_t experimentRaw =
829 Preferences::GetUint(kPrefWin32kExperimentStartupEnrollmentStatus,
830 nsIXULRuntime::eExperimentStatusUnenrolled);
831 gWin32kExperimentStatus =
832 experimentRaw < nsIXULRuntime::eExperimentStatusCount
833 ? nsIXULRuntime::ExperimentStatus(experimentRaw)
834 : nsIXULRuntime::eExperimentStatusDisqualified;
835
836 // Watch the experiment enrollment status pref to detect experiment
837 // disqualification, and ensure it is propagated for the next restart.
838 Preferences::RegisterCallback(&OnWin32kEnrollmentStatusChanged,
839 kPrefWin32kExperimentEnrollmentStatus);
840 if (nsCOMPtr<nsIObserverService> observerService =
841 mozilla::services::GetObserverService()) {
842 nsCOMPtr<nsIObserver> shutdownObserver =
843 new Win32kEnrollmentStatusShutdownObserver();
844 observerService->AddObserver(shutdownObserver, "profile-before-change",
845 false);
846 }
847
848 // If the user no longer qualifies because they edited a required pref, check
849 // that. [B] [E]
850 auto tmpStatus = GetLiveWin32kLockdownState();
851 if (Win32kExperimentEnrolled() && Win32kRequirementsUnsatisfied(tmpStatus)) {
852 Win32kExperimentDisqualify();
853 gWin32kExperimentStatus = nsIXULRuntime::eExperimentStatusDisqualified;
854 }
855
856 // If the user has overridden an active experiment by setting a user value for
857 // "security.sandbox.content.win32k-disable", disqualify the user from the
858 // experiment. [A] [F]
859 if (Preferences::HasUserValue(kPrefWin32k) && Win32kExperimentEnrolled()) {
860 Win32kExperimentDisqualify();
861 gWin32kExperimentStatus = nsIXULRuntime::eExperimentStatusDisqualified;
862 }
863
864 // Unlike Fission, we do not configure the default branch based on experiment
865 // enrollment status. Instead we check the startupEnrollmentPref in
866 // GetContentWin32kLockdownState()
867
868 Preferences::RegisterCallback(&OnWin32kChanged, kPrefWin32k);
869
870 // Set the state
871 gWin32kStatus = GetLiveWin32kLockdownState();
872
873#else
874 gWin32kStatus =
875 nsIXULRuntime::ContentWin32kLockdownState::OperatingSystemNotSupported;
876 gWin32kExperimentStatus = nsIXULRuntime::eExperimentStatusUnenrolled;
877
878#endif // XP_WIN
879}
880
881nsIXULRuntime::ContentWin32kLockdownState GetWin32kLockdownState() {
882#ifdef XP_WIN
883
884 mozilla::EnsureWin32kInitialized();
885 return gWin32kStatus;
886
887#else
888
889 return nsIXULRuntime::ContentWin32kLockdownState::OperatingSystemNotSupported;
890
891#endif
892}
893
894} // namespace mozilla
895
896// End Win32k Infrastructure ==========================================
897
898// Fission Infrastructure =============================================
899
900// Fission enablement for the current session is determined once, at startup,
901// and then remains the same for the duration of the session.
902//
903// The following factors determine whether or not Fission is enabled for a
904// session, in order of precedence:
905//
906// - Safe mode: In safe mode, Fission is never enabled.
907//
908// - The MOZ_FORCE_ENABLE_FISSION environment variable: If set to any value,
909// Fission will be enabled.
910//
911// - The 'fission.autostart' preference, if it has been configured by the user.
912static const char kPrefFissionAutostart[] = "fission.autostart";
913
914// The computed FissionAutostart value for the session, read by content
915// processes to initialize gFissionAutostart.
916//
917// This pref is locked, and only configured on the default branch, so should
918// never be persisted in a profile.
919static const char kPrefFissionAutostartSession[] = "fission.autostart.session";
920
921//
922// The computed FissionAutostart value for the session, read by content
923// processes to initialize gFissionAutostart.
924
925static bool gFissionAutostart = false;
926static bool gFissionAutostartInitialized = false;
927static nsIXULRuntime::FissionDecisionStatus gFissionDecisionStatus;
928static void EnsureFissionAutostartInitialized() {
929 if (gFissionAutostartInitialized) {
930 return;
931 }
932 gFissionAutostartInitialized = true;
933
934 if (!XRE_IsParentProcess()) {
935 // This pref is configured for the current session by the parent process.
936 gFissionAutostart = Preferences::GetBool(kPrefFissionAutostartSession,
937 false, PrefValueKind::Default);
938 return;
939 }
940
941 if (!BrowserTabsRemoteAutostart()) {
942 gFissionAutostart = false;
943 if (gBrowserTabsRemoteStatus == kE10sForceDisabled) {
944 gFissionDecisionStatus = nsIXULRuntime::eFissionDisabledByE10sEnv;
945 } else {
946 gFissionDecisionStatus = nsIXULRuntime::eFissionDisabledByE10sOther;
947 }
948 } else if (EnvHasValue("MOZ_FORCE_ENABLE_FISSION")) {
949 gFissionAutostart = true;
950 gFissionDecisionStatus = nsIXULRuntime::eFissionEnabledByEnv;
951 } else if (EnvHasValue("MOZ_FORCE_DISABLE_FISSION")) {
952 gFissionAutostart = false;
953 gFissionDecisionStatus = nsIXULRuntime::eFissionDisabledByEnv;
954 } else {
955 // NOTE: This will take into account changes to the default due to
956 // `InitializeFissionExperimentStatus`.
957 gFissionAutostart = Preferences::GetBool(kPrefFissionAutostart, false);
958 if (Preferences::HasUserValue(kPrefFissionAutostart)) {
959 gFissionDecisionStatus = gFissionAutostart
960 ? nsIXULRuntime::eFissionEnabledByUserPref
961 : nsIXULRuntime::eFissionDisabledByUserPref;
962 } else {
963 gFissionDecisionStatus = gFissionAutostart
964 ? nsIXULRuntime::eFissionEnabledByDefault
965 : nsIXULRuntime::eFissionDisabledByDefault;
966 }
967 }
968
969 // Content processes cannot run the same logic as we're running in the parent
970 // process, as the current value of various preferences may have changed
971 // between launches. Instead, the content process will read the default branch
972 // of the locked `fission.autostart.session` preference to determine the value
973 // determined by this method.
974 Preferences::Unlock(kPrefFissionAutostartSession);
975 Preferences::ClearUser(kPrefFissionAutostartSession);
976 Preferences::SetBool(kPrefFissionAutostartSession, gFissionAutostart,
977 PrefValueKind::Default);
978 Preferences::Lock(kPrefFissionAutostartSession);
979}
980
981namespace mozilla {
982
983bool FissionAutostart() {
984 EnsureFissionAutostartInitialized();
985 return gFissionAutostart;
986}
987
988} // namespace mozilla
989
990// End Fission Infrastructure =========================================
991
992namespace mozilla {
993
994bool SessionStorePlatformCollection() {
995 return !StaticPrefs::
996 browser_sessionstore_disable_platform_collection_AtStartup_DoNotUseDirectly();
997}
998
999bool BFCacheInParent() {
1000 return StaticPrefs::fission_bfcacheInParent_DoNotUseDirectly();
1001}
1002
1003} // namespace mozilla
1004
1005/**
1006 * The nsXULAppInfo object implements nsIFactory so that it can be its own
1007 * singleton.
1008 */
1009class nsXULAppInfo : public nsIXULAppInfo,
1010#ifdef XP_WIN
1011 public nsIWinAppHelper,
1012#endif
1013 public nsICrashReporter,
1014 public nsIFinishDumpingCallback,
1015 public nsIXULRuntime
1016
1017{
1018 public:
1019 constexpr nsXULAppInfo() = default;
1020 NS_DECL_ISUPPORTS_INHERITEDpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override;
1021 NS_DECL_NSIPLATFORMINFOvirtual nsresult GetPlatformVersion(nsACString& aPlatformVersion
) override; virtual nsresult GetPlatformBuildID(nsACString&
aPlatformBuildID) override;
1022 NS_DECL_NSIXULAPPINFOvirtual nsresult GetVendor(nsACString& aVendor) override;
virtual nsresult GetName(nsACString& aName) override; virtual
nsresult GetID(nsACString& aID) override; virtual nsresult
GetVersion(nsACString& aVersion) override; virtual nsresult
GetAppBuildID(nsACString& aAppBuildID) override; virtual
nsresult GetUAName(nsACString& aUAName) override; virtual
nsresult GetSourceURL(nsACString& aSourceURL) override; virtual
nsresult GetUpdateURL(nsACString& aUpdateURL) override; virtual
nsresult GetRemotingName(nsACString& aRemotingName) override
;
1023 NS_DECL_NSIXULRUNTIMEvirtual nsresult GetInSafeMode(bool *aInSafeMode) override; virtual
nsresult GetWin32kExperimentStatus(nsIXULRuntime::ExperimentStatus
*aWin32kExperimentStatus) override; virtual nsresult GetWin32kLiveStatusTestingOnly
(nsIXULRuntime::ContentWin32kLockdownState *aWin32kLiveStatusTestingOnly
) override; virtual nsresult GetWin32kSessionStatus(nsIXULRuntime
::ContentWin32kLockdownState *aWin32kSessionStatus) override;
virtual nsresult GetFissionAutostart(bool *aFissionAutostart
) override; virtual nsresult GetFissionDecisionStatus(nsIXULRuntime
::FissionDecisionStatus *aFissionDecisionStatus) override; virtual
nsresult GetFissionDecisionStatusString(nsACString& aFissionDecisionStatusString
) override; virtual nsresult GetSessionStorePlatformCollection
(bool *aSessionStorePlatformCollection) override; virtual nsresult
GetLogConsoleErrors(bool *aLogConsoleErrors) override; virtual
nsresult SetLogConsoleErrors(bool aLogConsoleErrors) override
; virtual nsresult GetOS(nsACString& aOS) override; virtual
nsresult GetXPCOMABI(nsACString& aXPCOMABI) override; virtual
nsresult GetWidgetToolkit(nsACString& aWidgetToolkit) override
; virtual nsresult GetProcessType(uint32_t *aProcessType) override
; virtual nsresult GetProcessID(uint32_t *aProcessID) override
; virtual nsresult GetUniqueProcessID(uint64_t *aUniqueProcessID
) override; virtual nsresult GetRemoteType(nsACString& aRemoteType
) override; virtual nsresult GetBrowserTabsRemoteAutostart(bool
*aBrowserTabsRemoteAutostart) override; virtual nsresult GetMaxWebProcessCount
(uint32_t *aMaxWebProcessCount) override; virtual nsresult GetAccessibilityEnabled
(bool *aAccessibilityEnabled) override; virtual nsresult GetAccessibilityInstantiator
(nsAString& aAccessibilityInstantiator) override; virtual
nsresult GetIs64Bit(bool *aIs64Bit) override; virtual nsresult
GetIsTextRecognitionSupported(bool *aIsTextRecognitionSupported
) override; virtual nsresult InvalidateCachesOnRestart(void) override
; virtual nsresult MarkProfileEncryptedDatabases(void) override
; virtual nsresult GetReplacedLockTime(PRTime *aReplacedLockTime
) override; virtual nsresult GetDefaultUpdateChannel(nsACString
& aDefaultUpdateChannel) override; virtual nsresult GetDistributionID
(nsACString& aDistributionID) override; virtual nsresult GetWindowsDLLBlocklistStatus
(bool *aWindowsDLLBlocklistStatus) override; virtual nsresult
GetRestartedByOS(bool *aRestartedByOS) override; virtual nsresult
GetNativeMenubar(bool *aNativeMenubar) override; virtual nsresult
GetChromeColorSchemeIsDark(bool *aChromeColorSchemeIsDark) override
; virtual nsresult GetContentThemeDerivedColorSchemeIsDark(bool
*aContentThemeDerivedColorSchemeIsDark) override; virtual nsresult
GetPrefersReducedMotion(bool *aPrefersReducedMotion) override
; virtual nsresult GetDrawInTitlebar(bool *aDrawInTitlebar) override
; virtual nsresult GetCaretBlinkCount(int32_t *aCaretBlinkCount
) override; virtual nsresult GetCaretBlinkTime(int32_t *aCaretBlinkTime
) override; virtual nsresult GetDesktopEnvironment(nsACString
& aDesktopEnvironment) override; virtual nsresult GetIsWayland
(bool *aIsWayland) override; virtual nsresult GetProcessStartupShortcut
(nsAString& aProcessStartupShortcut) override; virtual nsresult
GetLauncherProcessState(uint32_t *aLauncherProcessState) override
; virtual nsresult GetLastAppVersion(nsACString& aLastAppVersion
) override; virtual nsresult GetLastAppBuildID(nsACString&
aLastAppBuildID) override;
1024 NS_DECL_NSICRASHREPORTERvirtual nsresult GetCrashReporterEnabled(bool *aCrashReporterEnabled
) override; virtual nsresult SetEnabled(bool enabled) override
; virtual nsresult GetServerURL(nsIURL **aServerURL) override
; virtual nsresult SetServerURL(nsIURL *aServerURL) override;
virtual nsresult GetMinidumpPath(nsIFile **aMinidumpPath) override
; virtual nsresult SetMinidumpPath(nsIFile *aMinidumpPath) override
; virtual nsresult GetMinidumpForID(const nsAString& id, nsIFile
**_retval) override; virtual nsresult GetExtraFileForID(const
nsAString& id, nsIFile **_retval) override; virtual nsresult
AnnotateCrashReport(const nsACString& key, JS::Handle<
JS::Value> data, JSContext* cx) override; virtual nsresult
RemoveCrashReportAnnotation(const nsACString& key) override
; virtual nsresult IsAnnotationValid(const nsACString& value
, bool *_retval) override; virtual nsresult IsAnnotationAllowedForReport
(const nsACString& value, bool *_retval) override; virtual
nsresult AppendAppNotesToCrashReport(const nsACString& data
) override; virtual nsresult RegisterAppMemory(uint64_t ptr, uint64_t
size) override; virtual nsresult WriteMinidumpForException(void
* aExceptionInfo) override; virtual nsresult AppendObjCExceptionInfoToAppNotes
(void * aException) override; virtual nsresult GetSubmitReports
(bool *aSubmitReports) override; virtual nsresult SetSubmitReports
(bool aSubmitReports) override; virtual nsresult UpdateCrashEventsDir
(void) override; virtual nsresult SaveMemoryReport(void) override
;
1025 NS_DECL_NSIFINISHDUMPINGCALLBACKvirtual nsresult Callback(nsISupports *data) override;
1026#ifdef XP_WIN
1027 NS_DECL_NSIWINAPPHELPER
1028#endif
1029};
1030
1031NS_INTERFACE_MAP_BEGIN(nsXULAppInfo)nsresult nsXULAppInfo::QueryInterface(const nsIID& aIID, void
** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak(
NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1031); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
;
1032 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULRuntime)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupports>)) foundInterface = static_cast
<nsISupports*>(static_cast<nsIXULRuntime*>(this))
; else
1033 NS_INTERFACE_MAP_ENTRY(nsIXULRuntime)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIXULRuntime>)) foundInterface =
static_cast<nsIXULRuntime*>(this); else
1034#ifdef XP_WIN
1035 NS_INTERFACE_MAP_ENTRY(nsIWinAppHelper)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIWinAppHelper>)) foundInterface
= static_cast<nsIWinAppHelper*>(this); else
1036#endif
1037 NS_INTERFACE_MAP_ENTRY(nsICrashReporter)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICrashReporter>)) foundInterface
= static_cast<nsICrashReporter*>(this); else
1038 NS_INTERFACE_MAP_ENTRY(nsIFinishDumpingCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIFinishDumpingCallback>)) foundInterface
= static_cast<nsIFinishDumpingCallback*>(this); else
1039 NS_INTERFACE_MAP_ENTRY(nsIPlatformInfo)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIPlatformInfo>)) foundInterface
= static_cast<nsIPlatformInfo*>(this); else
1040 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIXULAppInfo,if ((gAppData || XRE_IsContentProcess()) && aIID.Equals
(mozilla::detail::kImplementedIID<std::remove_reference_t<
decltype(*this)>, nsIXULAppInfo>)) foundInterface = static_cast
<nsIXULAppInfo*>(this); else
1041 gAppData || XRE_IsContentProcess())if ((gAppData || XRE_IsContentProcess()) && aIID.Equals
(mozilla::detail::kImplementedIID<std::remove_reference_t<
decltype(*this)>, nsIXULAppInfo>)) foundInterface = static_cast
<nsIXULAppInfo*>(this); else
1042NS_INTERFACE_MAP_ENDfoundInterface = 0; nsresult status; if (!foundInterface) { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(!aIID.Equals((nsISupports::kIID)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aIID.Equals((nsISupports::kIID
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aIID.Equals((nsISupports::kIID))", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1042); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::kIID))"
")"); do { MOZ_CrashSequence(__null, 1042); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
1043
1044NS_IMETHODIMP_(MozExternalRefCountType)MozExternalRefCountType
1045nsXULAppInfo::AddRef() { return 1; }
1046
1047NS_IMETHODIMP_(MozExternalRefCountType)MozExternalRefCountType
1048nsXULAppInfo::Release() { return 1; }
1049
1050NS_IMETHODIMPnsresult
1051nsXULAppInfo::GetVendor(nsACString& aResult) {
1052 if (XRE_IsContentProcess()) {
1053 ContentChild* cc = ContentChild::GetSingleton();
1054 aResult = cc->GetAppInfo().vendor;
1055 return NS_OK;
1056 }
1057 aResult.Assign(gAppData->vendor);
1058
1059 return NS_OK;
1060}
1061
1062NS_IMETHODIMPnsresult
1063nsXULAppInfo::GetName(nsACString& aResult) {
1064 if (XRE_IsContentProcess()) {
1065 ContentChild* cc = ContentChild::GetSingleton();
1066 aResult = cc->GetAppInfo().name;
1067 return NS_OK;
1068 }
1069
1070#ifdef MOZ_WIDGET_ANDROID
1071 nsCString name = java::GeckoAppShell::GetAppName()->ToCString();
1072 aResult.Assign(std::move(name));
1073#else
1074 aResult.Assign(gAppData->name);
1075#endif
1076
1077 return NS_OK;
1078}
1079
1080NS_IMETHODIMPnsresult
1081nsXULAppInfo::GetID(nsACString& aResult) {
1082 if (XRE_IsContentProcess()) {
1083 ContentChild* cc = ContentChild::GetSingleton();
1084 aResult = cc->GetAppInfo().ID;
1085 return NS_OK;
1086 }
1087 aResult.Assign(gAppData->ID);
1088
1089 return NS_OK;
1090}
1091
1092NS_IMETHODIMPnsresult
1093nsXULAppInfo::GetVersion(nsACString& aResult) {
1094 if (XRE_IsContentProcess()) {
1095 ContentChild* cc = ContentChild::GetSingleton();
1096 aResult = cc->GetAppInfo().version;
1097 return NS_OK;
1098 }
1099 aResult.Assign(gAppData->version);
1100
1101 return NS_OK;
1102}
1103
1104NS_IMETHODIMPnsresult
1105nsXULAppInfo::GetPlatformVersion(nsACString& aResult) {
1106 aResult.Assign(gToolkitVersion);
1107
1108 return NS_OK;
1109}
1110
1111NS_IMETHODIMPnsresult
1112nsXULAppInfo::GetAppBuildID(nsACString& aResult) {
1113 if (XRE_IsContentProcess()) {
1114 ContentChild* cc = ContentChild::GetSingleton();
1115 aResult = cc->GetAppInfo().buildID;
1116 return NS_OK;
1117 }
1118 aResult.Assign(gAppData->buildID);
1119
1120 return NS_OK;
1121}
1122
1123NS_IMETHODIMPnsresult
1124nsXULAppInfo::GetPlatformBuildID(nsACString& aResult) {
1125 aResult.Assign(gToolkitBuildID);
1126
1127 return NS_OK;
1128}
1129
1130NS_IMETHODIMPnsresult
1131nsXULAppInfo::GetUAName(nsACString& aResult) {
1132 if (XRE_IsContentProcess()) {
1133 ContentChild* cc = ContentChild::GetSingleton();
1134 aResult = cc->GetAppInfo().UAName;
1135 return NS_OK;
1136 }
1137 aResult.Assign(gAppData->UAName);
1138
1139 return NS_OK;
1140}
1141
1142NS_IMETHODIMPnsresult
1143nsXULAppInfo::GetSourceURL(nsACString& aResult) {
1144 if (XRE_IsContentProcess()) {
1145 ContentChild* cc = ContentChild::GetSingleton();
1146 aResult = cc->GetAppInfo().sourceURL;
1147 return NS_OK;
1148 }
1149 aResult.Assign(gAppData->sourceURL);
1150
1151 return NS_OK;
1152}
1153
1154NS_IMETHODIMPnsresult
1155nsXULAppInfo::GetUpdateURL(nsACString& aResult) {
1156 if (XRE_IsContentProcess()) {
1157 ContentChild* cc = ContentChild::GetSingleton();
1158 aResult = cc->GetAppInfo().updateURL;
1159 return NS_OK;
1160 }
1161 aResult.Assign(gAppData->updateURL);
1162
1163 return NS_OK;
1164}
1165
1166NS_IMETHODIMPnsresult
1167nsXULAppInfo::GetRemotingName(nsACString& aResult) {
1168 if (XRE_IsContentProcess()) {
1169 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" " (" "nsXULAppInfo::remotingName should not be accessed from the "
"content process" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1171); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"nsXULAppInfo::remotingName should not be accessed from the "
"content process" ")"); do { MOZ_CrashSequence(__null, 1171)
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
1170 "nsXULAppInfo::remotingName should not be accessed from the "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "nsXULAppInfo::remotingName should not be accessed from the "
"content process" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1171); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"nsXULAppInfo::remotingName should not be accessed from the "
"content process" ")"); do { MOZ_CrashSequence(__null, 1171)
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
1171 "content process")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "nsXULAppInfo::remotingName should not be accessed from the "
"content process" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1171); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"nsXULAppInfo::remotingName should not be accessed from the "
"content process" ")"); do { MOZ_CrashSequence(__null, 1171)
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
1172 return NS_ERROR_UNEXPECTED;
1173 }
1174 aResult.Assign(gAppData->remotingName);
1175
1176 return NS_OK;
1177}
1178
1179NS_IMETHODIMPnsresult
1180nsXULAppInfo::GetLogConsoleErrors(bool* aResult) {
1181 *aResult = gLogConsoleErrors;
1182 return NS_OK;
1183}
1184
1185NS_IMETHODIMPnsresult
1186nsXULAppInfo::SetLogConsoleErrors(bool aValue) {
1187 gLogConsoleErrors = aValue;
1188 return NS_OK;
1189}
1190
1191NS_IMETHODIMPnsresult
1192nsXULAppInfo::GetInSafeMode(bool* aResult) {
1193 *aResult = gSafeMode;
1194 return NS_OK;
1195}
1196
1197NS_IMETHODIMPnsresult
1198nsXULAppInfo::GetOS(nsACString& aResult) {
1199 aResult.AssignLiteral(OS_TARGET"Linux");
1200 return NS_OK;
1201}
1202
1203NS_IMETHODIMPnsresult
1204nsXULAppInfo::GetXPCOMABI(nsACString& aResult) {
1205#ifdef TARGET_XPCOM_ABI"x86_64-gcc3"
1206 aResult.AssignLiteral(TARGET_XPCOM_ABI"x86_64-gcc3");
1207 return NS_OK;
1208#else
1209 return NS_ERROR_NOT_AVAILABLE;
1210#endif
1211}
1212
1213NS_IMETHODIMPnsresult
1214nsXULAppInfo::GetWidgetToolkit(nsACString& aResult) {
1215 aResult.AssignLiteral(MOZ_WIDGET_TOOLKIT"gtk");
1216 return NS_OK;
1217}
1218
1219// Ensure that the GeckoProcessType enum, defined in xpcom/build/nsXULAppAPI.h,
1220// is synchronized with the const unsigned longs defined in
1221// xpcom/system/nsIXULRuntime.idl.
1222#define GECKO_PROCESS_TYPE(enum_value, enum_name, string_name, proc_typename, \
1223 process_bin_type, procinfo_typename, \
1224 webidl_typename, allcaps_name) \
1225 static_assert(nsIXULRuntime::PROCESS_TYPE_##allcaps_name == \
1226 static_cast<int>(GeckoProcessType_##enum_name), \
1227 "GeckoProcessType in nsXULAppAPI.h not synchronized with " \
1228 "nsIXULRuntime.idl");
1229#include "mozilla/GeckoProcessTypes.h"
1230#undef GECKO_PROCESS_TYPE
1231
1232// .. and ensure that that is all of them:
1233static_assert(GeckoProcessType_Utility + 1 == GeckoProcessType_End,
1234 "Did not find the final GeckoProcessType");
1235
1236NS_IMETHODIMPnsresult
1237nsXULAppInfo::GetProcessType(uint32_t* aResult) {
1238 NS_ENSURE_ARG_POINTER(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 1238); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
1239 *aResult = XRE_GetProcessType();
1240 return NS_OK;
1241}
1242
1243NS_IMETHODIMPnsresult
1244nsXULAppInfo::GetProcessID(uint32_t* aResult) {
1245#ifdef XP_WIN
1246 *aResult = GetCurrentProcessId();
1247#else
1248 *aResult = getpid();
1249#endif
1250 return NS_OK;
1251}
1252
1253NS_IMETHODIMPnsresult
1254nsXULAppInfo::GetUniqueProcessID(uint64_t* aResult) {
1255 if (XRE_IsContentProcess()) {
1256 ContentChild* cc = ContentChild::GetSingleton();
1257 *aResult = cc->GetID();
1258 } else {
1259 *aResult = 0;
1260 }
1261 return NS_OK;
1262}
1263
1264NS_IMETHODIMPnsresult
1265nsXULAppInfo::GetRemoteType(nsACString& aRemoteType) {
1266 if (XRE_IsContentProcess()) {
1267 aRemoteType = ContentChild::GetSingleton()->GetRemoteType().Stringify();
1268 } else {
1269 aRemoteType = dom::RemoteType::NotRemote().Stringify();
1270 }
1271
1272 return NS_OK;
1273}
1274
1275constinit static nsCString gLastAppVersion;
1276constinit static nsCString gLastAppBuildID;
1277
1278// Whether the loaded profile's compatibility.ini carries EncryptedDatabases=1.
1279// Populated by CheckCompatibility() (which already parses compatibility.ini)
1280// and consulted by the encryption-compatibility gate in XRE_mainStartup.
1281static bool gProfileEncryptedDatabases = false;
1282
1283NS_IMETHODIMPnsresult
1284nsXULAppInfo::GetLastAppVersion(nsACString& aResult) {
1285 if (XRE_IsContentProcess()) {
1286 return NS_ERROR_NOT_AVAILABLE;
1287 }
1288
1289 if (!gLastAppVersion.IsVoid() && gLastAppVersion.IsEmpty()) {
1290 NS_WARNING("Attempt to retrieve lastAppVersion before it has been set.")NS_DebugBreak(NS_DEBUG_WARNING, "Attempt to retrieve lastAppVersion before it has been set."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
1290)
;
1291 return NS_ERROR_NOT_AVAILABLE;
1292 }
1293
1294 aResult.Assign(gLastAppVersion);
1295 return NS_OK;
1296}
1297
1298NS_IMETHODIMPnsresult
1299nsXULAppInfo::GetLastAppBuildID(nsACString& aResult) {
1300 if (XRE_IsContentProcess()) {
1301 return NS_ERROR_NOT_AVAILABLE;
1302 }
1303
1304 if (!gLastAppBuildID.IsVoid() && gLastAppBuildID.IsEmpty()) {
1305 NS_WARNING("Attempt to retrieve lastAppBuildID before it has been set.")NS_DebugBreak(NS_DEBUG_WARNING, "Attempt to retrieve lastAppBuildID before it has been set."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
1305)
;
1306 return NS_ERROR_NOT_AVAILABLE;
1307 }
1308
1309 aResult.Assign(gLastAppBuildID);
1310 return NS_OK;
1311}
1312
1313NS_IMETHODIMPnsresult
1314nsXULAppInfo::GetFissionAutostart(bool* aResult) {
1315 *aResult = FissionAutostart();
1316 return NS_OK;
1317}
1318
1319NS_IMETHODIMPnsresult
1320nsXULAppInfo::GetWin32kExperimentStatus(ExperimentStatus* aResult) {
1321 if (!XRE_IsParentProcess()) {
1322 return NS_ERROR_NOT_AVAILABLE;
1323 }
1324
1325 EnsureWin32kInitialized();
1326 *aResult = gWin32kExperimentStatus;
1327 return NS_OK;
1328}
1329
1330NS_IMETHODIMPnsresult
1331nsXULAppInfo::GetWin32kLiveStatusTestingOnly(
1332 nsIXULRuntime::ContentWin32kLockdownState* aResult) {
1333 if (!XRE_IsParentProcess()) {
1334 return NS_ERROR_NOT_AVAILABLE;
1335 }
1336
1337 EnsureWin32kInitialized();
1338 *aResult = GetLiveWin32kLockdownState();
1339 return NS_OK;
1340}
1341
1342NS_IMETHODIMPnsresult
1343nsXULAppInfo::GetWin32kSessionStatus(
1344 nsIXULRuntime::ContentWin32kLockdownState* aResult) {
1345 if (!XRE_IsParentProcess()) {
1346 return NS_ERROR_NOT_AVAILABLE;
1347 }
1348
1349 EnsureWin32kInitialized();
1350 *aResult = gWin32kStatus;
1351 return NS_OK;
1352}
1353
1354NS_IMETHODIMPnsresult
1355nsXULAppInfo::GetFissionDecisionStatus(FissionDecisionStatus* aResult) {
1356 if (!XRE_IsParentProcess()) {
1357 return NS_ERROR_NOT_AVAILABLE;
1358 }
1359
1360 EnsureFissionAutostartInitialized();
1361
1362 MOZ_ASSERT(gFissionDecisionStatus != eFissionStatusUnknown)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(gFissionDecisionStatus != eFissionStatusUnknown)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(gFissionDecisionStatus != eFissionStatusUnknown))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("gFissionDecisionStatus != eFissionStatusUnknown"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 1362); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "gFissionDecisionStatus != eFissionStatusUnknown"
")"); do { MOZ_CrashSequence(__null, 1362); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1363 *aResult = gFissionDecisionStatus;
1364 return NS_OK;
1365}
1366
1367NS_IMETHODIMPnsresult
1368nsXULAppInfo::GetFissionDecisionStatusString(nsACString& aResult) {
1369 if (!XRE_IsParentProcess()) {
1370 return NS_ERROR_NOT_AVAILABLE;
1371 }
1372
1373 EnsureFissionAutostartInitialized();
1374 switch (gFissionDecisionStatus) {
1375 case eFissionDisabledByE10sEnv:
1376 aResult = "disabledByE10sEnv";
1377 break;
1378 case eFissionEnabledByEnv:
1379 aResult = "enabledByEnv";
1380 break;
1381 case eFissionDisabledByEnv:
1382 aResult = "disabledByEnv";
1383 break;
1384 case eFissionEnabledByDefault:
1385 aResult = "enabledByDefault";
1386 break;
1387 case eFissionDisabledByDefault:
1388 aResult = "disabledByDefault";
1389 break;
1390 case eFissionEnabledByUserPref:
1391 aResult = "enabledByUserPref";
1392 break;
1393 case eFissionDisabledByUserPref:
1394 aResult = "disabledByUserPref";
1395 break;
1396 case eFissionDisabledByE10sOther:
1397 aResult = "disabledByE10sOther";
1398 break;
1399 default:
1400 MOZ_ASSERT_UNREACHABLE("Unexpected enum value")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 enum value" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1400); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unexpected enum value" ")"); do {
MOZ_CrashSequence(__null, 1400); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1401 }
1402 return NS_OK;
1403}
1404
1405NS_IMETHODIMPnsresult
1406nsXULAppInfo::GetSessionStorePlatformCollection(bool* aResult) {
1407 *aResult = SessionStorePlatformCollection();
1408 return NS_OK;
1409}
1410
1411NS_IMETHODIMPnsresult
1412nsXULAppInfo::GetBrowserTabsRemoteAutostart(bool* aResult) {
1413 *aResult = BrowserTabsRemoteAutostart();
1414 return NS_OK;
1415}
1416
1417NS_IMETHODIMPnsresult
1418nsXULAppInfo::GetMaxWebProcessCount(uint32_t* aResult) {
1419 *aResult = mozilla::GetMaxWebProcessCount();
1420 return NS_OK;
1421}
1422
1423NS_IMETHODIMPnsresult
1424nsXULAppInfo::GetAccessibilityEnabled(bool* aResult) {
1425#ifdef ACCESSIBILITY1
1426 *aResult = GetAccService() != nullptr;
1427#else
1428 *aResult = false;
1429#endif
1430 return NS_OK;
1431}
1432
1433NS_IMETHODIMPnsresult
1434nsXULAppInfo::GetAccessibilityInstantiator(nsAString& aInstantiator) {
1435 aInstantiator.Truncate();
1436#if defined(ACCESSIBILITY1)
1437 if (GetAccService()) {
1438 a11y::GetHumanReadableInstantiatorStr(aInstantiator);
1439# if defined(XP_WIN)
1440 aInstantiator.AppendLiteral("|");
1441
1442 nsCOMPtr<nsIFile> oopClientExe;
1443 if (a11y::GetInstantiator(getter_AddRefs(oopClientExe))) {
1444 nsAutoString oopClientInfo;
1445 if (NS_SUCCEEDED(oopClientExe->GetPath(oopClientInfo))((bool)(__builtin_expect(!!(!NS_FAILED_impl(oopClientExe->
GetPath(oopClientInfo))), 1)))
) {
1446 aInstantiator.Append(oopClientInfo);
1447 }
1448 }
1449# endif
1450 }
1451#endif
1452 return NS_OK;
1453}
1454
1455NS_IMETHODIMPnsresult
1456nsXULAppInfo::GetIs64Bit(bool* aResult) {
1457#ifdef HAVE_64BIT_BUILD1
1458 *aResult = true;
1459#else
1460 *aResult = false;
1461#endif
1462 return NS_OK;
1463}
1464
1465NS_IMETHODIMPnsresult
1466nsXULAppInfo::GetIsTextRecognitionSupported(bool* aResult) {
1467 *aResult = widget::TextRecognition::IsSupported();
1468 return NS_OK;
1469}
1470
1471NS_IMETHODIMPnsresult
1472nsXULAppInfo::InvalidateCachesOnRestart() {
1473 nsCOMPtr<nsIFile> file;
1474 nsresult rv =
1475 NS_GetSpecialDirectory(NS_APP_PROFILE_DIR_STARTUP"ProfDS", getter_AddRefs(file));
1476 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
1477 if (!file) return NS_ERROR_NOT_AVAILABLE;
1478
1479 file->AppendNative(FILE_COMPATIBILITY_INFO"compatibility.ini"_ns);
1480
1481 nsINIParsernsINIParser_internal parser;
1482 rv = parser.Init(file);
1483 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1484 // This fails if compatibility.ini is not there, so we'll
1485 // flush the caches on the next restart anyways.
1486 return NS_OK;
1487 }
1488
1489 nsAutoCString buf;
1490 rv = parser.GetString("Compatibility", "InvalidateCaches", buf);
1491
1492 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1493 PRFileDesc* fd;
1494 rv = file->OpenNSPRFileDesc(PR_RDWR0x04 | PR_APPEND0x10, 0600, &fd);
1495 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1496 NS_ERROR("could not create output stream")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "could not create output stream"
, "Error", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
1496); MOZ_PretendNoReturn(); } while (0)
;
1497 return NS_ERROR_NOT_AVAILABLE;
1498 }
1499 static const char kInvalidationHeader[] =
1500 NS_LINEBREAK"\012" "InvalidateCaches=1" NS_LINEBREAK"\012";
1501 PR_Write(fd, kInvalidationHeader, sizeof(kInvalidationHeader) - 1);
1502 PR_Close(fd);
1503 }
1504 return NS_OK;
1505}
1506
1507nsresult mozilla::MarkProfileEncryptedDatabases() {
1508 // Append the EncryptedDatabases marker to compatibility.ini (modeled on
1509 // InvalidateCachesOnRestart above). Read back by CheckCompatibility() on the
1510 // next startup so the encryption gate can refuse to launch a build whose
1511 // pref disagrees with the now-encrypted profile. Append-only: the marker is
1512 // never removed (a profile that has held encrypted databases stays marked).
1513 nsCOMPtr<nsIFile> file;
1514 nsresult rv =
1515 NS_GetSpecialDirectory(NS_APP_PROFILE_DIR_STARTUP"ProfDS", getter_AddRefs(file));
1516 // No resolvable startup profile directory (xpcshell, or a background task /
1517 // very early startup with no profile yet): there is no persistent
1518 // compatibility.ini to gate a future launch, so there is nothing to mark and
1519 // nothing to protect. Treat this as a benign no-op. Returning a failure here
1520 // would flip sMarkerWriteFailed (see MarkProfileEncryptedIfNeeded) and refuse
1521 // every DEK mint for the session, breaking all in-profile opens under
1522 // xpcshell with the pref on. A genuine write failure on an existing profile
1523 // is still surfaced below.
1524 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !file) return NS_OK;
1525
1526 file->AppendNative(FILE_COMPATIBILITY_INFO"compatibility.ini"_ns);
1527
1528 nsINIParsernsINIParser_internal parser;
1529 rv = parser.Init(file);
1530 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1531 // No compatibility.ini yet (WriteVersion creates it once per profile);
1532 // the marker will be written on a later startup.
1533 return NS_OK;
1534 }
1535
1536 nsAutoCString buf;
1537 rv = parser.GetString("Compatibility", "EncryptedDatabases", buf);
1538 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
1539 // Already marked.
1540 return NS_OK;
1541 }
1542
1543 PRFileDesc* fd;
1544 rv = file->OpenNSPRFileDesc(PR_RDWR0x04 | PR_APPEND0x10, 0600, &fd);
1545 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1546 return NS_ERROR_NOT_AVAILABLE;
1547 }
1548 static const char kEncryptedHeader[] =
1549 NS_LINEBREAK"\012" "EncryptedDatabases=1" NS_LINEBREAK"\012";
1550 PR_Write(fd, kEncryptedHeader, sizeof(kEncryptedHeader) - 1);
1551 PR_Close(fd);
1552 return NS_OK;
1553}
1554
1555NS_IMETHODIMPnsresult
1556nsXULAppInfo::MarkProfileEncryptedDatabases() {
1557 return mozilla::MarkProfileEncryptedDatabases();
1558}
1559
1560NS_IMETHODIMPnsresult
1561nsXULAppInfo::GetReplacedLockTime(PRTime* aReplacedLockTime) {
1562 if (!gProfileLock) return NS_ERROR_NOT_AVAILABLE;
1563 gProfileLock->GetReplacedLockTime(aReplacedLockTime);
1564 return NS_OK;
1565}
1566
1567NS_IMETHODIMPnsresult
1568nsXULAppInfo::GetDefaultUpdateChannel(nsACString& aResult) {
1569 aResult.AssignLiteral(MOZ_STRINGIFY(MOZ_UPDATE_CHANNEL)"default");
1570 return NS_OK;
1571}
1572
1573NS_IMETHODIMPnsresult
1574nsXULAppInfo::GetDistributionID(nsACString& aResult) {
1575 aResult.AssignLiteral(MOZ_DISTRIBUTION_ID"org.mozilla");
1576 return NS_OK;
1577}
1578
1579NS_IMETHODIMPnsresult
1580nsXULAppInfo::GetWindowsDLLBlocklistStatus(bool* aResult) {
1581#if defined(HAS_DLL_BLOCKLIST)
1582 *aResult = DllBlocklist_CheckStatus();
1583#else
1584 *aResult = false;
1585#endif
1586 return NS_OK;
1587}
1588
1589NS_IMETHODIMPnsresult
1590nsXULAppInfo::GetRestartedByOS(bool* aResult) {
1591 *aResult = gRestartedByOS;
1592 return NS_OK;
1593}
1594
1595NS_IMETHODIMPnsresult
1596nsXULAppInfo::GetChromeColorSchemeIsDark(bool* aResult) {
1597 *aResult = PreferenceSheet::ColorSchemeForChrome() == ColorScheme::Dark;
1598 return NS_OK;
1599}
1600
1601NS_IMETHODIMPnsresult
1602nsXULAppInfo::GetNativeMenubar(bool* aResult) {
1603 *aResult = !!LookAndFeel::GetInt(LookAndFeel::IntID::NativeMenubar);
1604 return NS_OK;
1605}
1606
1607NS_IMETHODIMPnsresult
1608nsXULAppInfo::GetContentThemeDerivedColorSchemeIsDark(bool* aResult) {
1609 *aResult =
1610 PreferenceSheet::ThemeDerivedColorSchemeForContent() == ColorScheme::Dark;
1611 return NS_OK;
1612}
1613
1614NS_IMETHODIMPnsresult
1615nsXULAppInfo::GetPrefersReducedMotion(bool* aResult) {
1616 *aResult =
1617 LookAndFeel::GetInt(LookAndFeel::IntID::PrefersReducedMotion, 0) == 1;
1618 return NS_OK;
1619}
1620
1621NS_IMETHODIMPnsresult
1622nsXULAppInfo::GetDrawInTitlebar(bool* aResult) {
1623 *aResult = LookAndFeel::DrawInTitlebar();
1624 return NS_OK;
1625}
1626
1627NS_IMETHODIMPnsresult
1628nsXULAppInfo::GetCaretBlinkCount(int32_t* aResult) {
1629 *aResult = LookAndFeel::CaretBlinkCount();
1630 return NS_OK;
1631}
1632
1633NS_IMETHODIMPnsresult
1634nsXULAppInfo::GetCaretBlinkTime(int32_t* aResult) {
1635 *aResult = LookAndFeel::CaretBlinkTime();
1636 return NS_OK;
1637}
1638
1639NS_IMETHODIMPnsresult
1640nsXULAppInfo::GetDesktopEnvironment(nsACString& aDesktopEnvironment) {
1641#ifdef MOZ_WIDGET_GTK1
1642 aDesktopEnvironment.Assign(GetDesktopEnvironmentIdentifier());
1643#endif
1644 return NS_OK;
1645}
1646
1647NS_IMETHODIMPnsresult
1648nsXULAppInfo::GetIsWayland(bool* aResult) {
1649#ifdef MOZ_WIDGET_GTK1
1650 *aResult = GdkIsWaylandDisplay();
1651#else
1652 *aResult = false;
1653#endif
1654 return NS_OK;
1655}
1656
1657NS_IMETHODIMPnsresult
1658nsXULAppInfo::GetProcessStartupShortcut(nsAString& aShortcut) {
1659#if defined(XP_WIN)
1660 if (XRE_IsParentProcess()) {
1661 aShortcut.Assign(gProcessStartupShortcut);
1662 return NS_OK;
1663 }
1664#endif
1665 return NS_ERROR_NOT_AVAILABLE;
1666}
1667
1668#if defined(XP_WIN) && defined(MOZ_LAUNCHER_PROCESS)
1669// Forward declaration
1670void SetupLauncherProcessPref();
1671
1672static Maybe<LauncherRegistryInfo::EnabledState> gLauncherProcessState;
1673#endif // defined(XP_WIN) && defined(MOZ_LAUNCHER_PROCESS)
1674
1675NS_IMETHODIMPnsresult
1676nsXULAppInfo::GetLauncherProcessState(uint32_t* aResult) {
1677#if defined(XP_WIN) && defined(MOZ_LAUNCHER_PROCESS)
1678 SetupLauncherProcessPref();
1679
1680 if (!gLauncherProcessState) {
1681 return NS_ERROR_UNEXPECTED;
1682 }
1683
1684 *aResult = static_cast<uint32_t>(gLauncherProcessState.value());
1685 return NS_OK;
1686#else
1687 return NS_ERROR_NOT_AVAILABLE;
1688#endif
1689}
1690
1691#ifdef XP_WIN
1692NS_IMETHODIMPnsresult
1693nsXULAppInfo::GetUserCanElevate(bool* aUserCanElevate) {
1694 HANDLE rawToken;
1695 if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &rawToken)) {
1696 *aUserCanElevate = false;
1697 return NS_OK;
1698 }
1699
1700 nsAutoHandle token(rawToken);
1701 LauncherResult<TOKEN_ELEVATION_TYPE> elevationType = GetElevationType(token);
1702 if (elevationType.isErr()) {
1703 *aUserCanElevate = false;
1704 return NS_OK;
1705 }
1706
1707 // The possible values returned for elevationType and their meanings are:
1708 // TokenElevationTypeDefault: The token does not have a linked token
1709 // (e.g. UAC disabled or a standard user, so they can't be elevated)
1710 // TokenElevationTypeFull: The token is linked to an elevated token
1711 // (e.g. UAC is enabled and the user is already elevated so they can't
1712 // be elevated again)
1713 // TokenElevationTypeLimited: The token is linked to a limited token
1714 // (e.g. UAC is enabled and the user is not elevated, so they can be
1715 // elevated)
1716 *aUserCanElevate = (elevationType.inspect() == TokenElevationTypeLimited);
1717 return NS_OK;
1718}
1719#endif
1720
1721// Get the CrashReporter::Annotation referred to by the `aKey` string. This
1722// wraps `CrashReporter::AnnotationFromString` to assert the annotation string
1723// is valid in debug builds, and otherwise returns an NS_ERROR_INVALID_ARG if
1724// it is invalid.
1725static Result<CrashReporter::Annotation, nsresult> GetCrashAnnotation(
1726 const nsACString& aKey) {
1727 auto maybeAnnotation = CrashReporter::AnnotationFromString(aKey);
1728#ifdef DEBUG1
1729 if (!maybeAnnotation.isSome()) {
1730 std::string warning = "Annotation identifier not found: \"";
1731 warning += aKey.View();
1732 warning += "\"";
1733 NS_WARNING(warning.c_str())NS_DebugBreak(NS_DEBUG_WARNING, warning.c_str(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1733)
;
1734 }
1735 if (!StaticPrefs::toolkit_crash_annotation_testing_validation()) {
1736 MOZ_ASSERT(maybeAnnotation.isSome(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(maybeAnnotation.isSome())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(maybeAnnotation.isSome()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("maybeAnnotation.isSome()"
" (" "Invalid annotation identifier; ensure it exists in " "CrashAnnotations.yaml"
")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 1738
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeAnnotation.isSome()"
") (" "Invalid annotation identifier; ensure it exists in " "CrashAnnotations.yaml"
")"); do { MOZ_CrashSequence(__null, 1738); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1737 "Invalid annotation identifier; ensure it exists in "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(maybeAnnotation.isSome())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(maybeAnnotation.isSome()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("maybeAnnotation.isSome()"
" (" "Invalid annotation identifier; ensure it exists in " "CrashAnnotations.yaml"
")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 1738
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeAnnotation.isSome()"
") (" "Invalid annotation identifier; ensure it exists in " "CrashAnnotations.yaml"
")"); do { MOZ_CrashSequence(__null, 1738); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1738 "CrashAnnotations.yaml")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(maybeAnnotation.isSome())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(maybeAnnotation.isSome()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("maybeAnnotation.isSome()"
" (" "Invalid annotation identifier; ensure it exists in " "CrashAnnotations.yaml"
")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 1738
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeAnnotation.isSome()"
") (" "Invalid annotation identifier; ensure it exists in " "CrashAnnotations.yaml"
")"); do { MOZ_CrashSequence(__null, 1738); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1739 }
1740#endif
1741 NS_ENSURE_TRUE(maybeAnnotation.isSome(), Err(NS_ERROR_INVALID_ARG))do { if ((__builtin_expect(!!(!(maybeAnnotation.isSome())), 0
))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "maybeAnnotation.isSome()"
") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1741); return Err(NS_ERROR_INVALID_ARG); } } while (false)
;
1742 return maybeAnnotation.extract();
1743}
1744
1745NS_IMETHODIMPnsresult
1746nsXULAppInfo::GetCrashReporterEnabled(bool* aEnabled) {
1747 *aEnabled = CrashReporter::GetEnabled();
1748 return NS_OK;
1749}
1750
1751NS_IMETHODIMPnsresult
1752nsXULAppInfo::SetEnabled(bool aEnabled) {
1753 if (aEnabled) {
1754 if (CrashReporter::GetEnabled()) {
1755 // no point in erroring for double-enabling
1756 return NS_OK;
1757 }
1758
1759 nsCOMPtr<nsIFile> greBinDir;
1760 NS_GetSpecialDirectory(NS_GRE_BIN_DIR"GreBinD", getter_AddRefs(greBinDir));
1761 if (!greBinDir) {
1762 return NS_ERROR_FAILURE;
1763 }
1764
1765 nsCOMPtr<nsIFile> xreBinDirectory = greBinDir;
1766 if (!xreBinDirectory) {
1767 return NS_ERROR_FAILURE;
1768 }
1769
1770 nsresult rv = CrashReporter::OOPInit(xreBinDirectory, true);
1771 if (rv != NS_OK) {
1772 return rv;
1773 }
1774
1775 return CrashReporter::SetExceptionHandler(xreBinDirectory, true);
1776 }
1777
1778 if (!CrashReporter::GetEnabled()) {
1779 // no point in erroring for double-disabling
1780 return NS_OK;
1781 }
1782
1783 nsresult rv = CrashReporter::UnsetExceptionHandler();
1784#if !defined(MOZ_WIDGET_ANDROID)
1785 // Don't deinit on Android as we can't get back up again
1786 // (bug 2040673 comment 20).
1787 // TODO: Fix it
1788 CrashReporter::OOPDeinit();
1789#endif
1790 return rv;
1791}
1792
1793NS_IMETHODIMPnsresult
1794nsXULAppInfo::GetServerURL(nsIURL** aServerURL) {
1795 NS_ENSURE_ARG_POINTER(aServerURL)do { if ((__builtin_expect(!!(!(aServerURL)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aServerURL" ") failed",
nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 1795
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1796 if (!CrashReporter::GetEnabled()) return NS_ERROR_NOT_INITIALIZED;
1797
1798 nsAutoCString data;
1799 if (!CrashReporter::GetServerURL(data)) {
1800 return NS_ERROR_FAILURE;
1801 }
1802 nsCOMPtr<nsIURI> uri;
1803 NS_NewURI(getter_AddRefs(uri), data);
1804 if (!uri) return NS_ERROR_FAILURE;
1805
1806 nsCOMPtr<nsIURL> url;
1807 url = do_QueryInterface(uri);
1808 NS_ADDREF(*aServerURL = url)(*aServerURL = url)->AddRef();
1809
1810 return NS_OK;
1811}
1812
1813NS_IMETHODIMPnsresult
1814nsXULAppInfo::SetServerURL(nsIURL* aServerURL) {
1815 // Only allow https or http URLs
1816 if (!net::SchemeIsHttpOrHttps(aServerURL)) {
1817 return NS_ERROR_INVALID_ARG;
1818 }
1819
1820 nsAutoCString spec;
1821 nsresult rv = aServerURL->GetSpec(spec);
1822 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, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1822); return rv; } } while (false)
;
1823
1824 return CrashReporter::SetServerURL(spec);
1825}
1826
1827NS_IMETHODIMPnsresult
1828nsXULAppInfo::GetMinidumpPath(nsIFile** aMinidumpPath) {
1829 if (!CrashReporter::GetEnabled()) {
1830 return NS_ERROR_NOT_INITIALIZED;
1831 }
1832
1833 nsAutoString path;
1834 if (!CrashReporter::GetMinidumpPath(path)) {
1835 return NS_ERROR_FAILURE;
1836 }
1837
1838 return NS_NewLocalFile(path, aMinidumpPath);
1839}
1840
1841NS_IMETHODIMPnsresult
1842nsXULAppInfo::SetMinidumpPath(nsIFile* aMinidumpPath) {
1843 nsAutoString path;
1844 nsresult rv = aMinidumpPath->GetPath(path);
1845 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, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1845); return rv; } } while (false)
;
1846 return CrashReporter::SetMinidumpPath(path);
1847}
1848
1849NS_IMETHODIMPnsresult
1850nsXULAppInfo::GetMinidumpForID(const nsAString& aId, nsIFile** aMinidump) {
1851 if (!CrashReporter::GetMinidumpForID(aId, aMinidump)) {
1852 return NS_ERROR_FILE_NOT_FOUND;
1853 }
1854
1855 return NS_OK;
1856}
1857
1858NS_IMETHODIMPnsresult
1859nsXULAppInfo::GetExtraFileForID(const nsAString& aId, nsIFile** aExtraFile) {
1860 if (!CrashReporter::GetExtraFileForID(aId, aExtraFile)) {
1861 return NS_ERROR_FILE_NOT_FOUND;
1862 }
1863
1864 return NS_OK;
1865}
1866
1867NS_IMETHODIMPnsresult
1868nsXULAppInfo::AnnotateCrashReport(const nsACString& key,
1869 JS::Handle<JS::Value> data, JSContext* cx) {
1870 CrashReporter::Annotation annotation = MOZ_TRY(GetCrashAnnotation(key))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(GetCrashAnnotation(key)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
;
1871 switch (data.type()) {
1872 case JS::ValueType::Int32:
1873 CrashReporter::RecordAnnotationU32(annotation, data.toInt32());
1874 break;
1875 case JS::ValueType::Boolean:
1876 CrashReporter::RecordAnnotationBool(annotation, data.toBoolean());
1877 break;
1878 case JS::ValueType::String: {
1879 JSString* value = data.toString();
1880 size_t length = (JS_GetStringLength(value) * 3) + 1;
1881 nsCString buffer;
1882 auto res = JS_EncodeStringToUTF8BufferPartial(
1883 cx, value, buffer.GetMutableData(length));
1884
1885 if (!res) {
1886 return NS_ERROR_OUT_OF_MEMORY;
1887 }
1888
1889 size_t written;
1890 std::tie(std::ignore, written) = *res;
1891
1892 buffer.SetLength(written);
1893
1894 CrashReporter::RecordAnnotationNSCString(annotation, buffer);
1895 } break;
1896 default:
1897 return NS_ERROR_INVALID_ARG;
1898 }
1899 return NS_OK;
1900}
1901
1902NS_IMETHODIMPnsresult
1903nsXULAppInfo::RemoveCrashReportAnnotation(const nsACString& key) {
1904 CrashReporter::Annotation annotation = MOZ_TRY(GetCrashAnnotation(key))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(GetCrashAnnotation(key)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
;
1905 CrashReporter::UnrecordAnnotation(annotation);
1906 return NS_OK;
1907}
1908
1909NS_IMETHODIMPnsresult
1910nsXULAppInfo::IsAnnotationValid(const nsACString& aValue, bool* aIsValid) {
1911 auto annotation = CrashReporter::AnnotationFromString(aValue);
1912 *aIsValid = annotation.isSome();
1913 return NS_OK;
1914}
1915
1916NS_IMETHODIMPnsresult
1917nsXULAppInfo::IsAnnotationAllowedForReport(const nsACString& aValue,
1918 bool* aIsAllowed) {
1919 CrashReporter::Annotation annotation = MOZ_TRY(GetCrashAnnotation(aValue))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(GetCrashAnnotation(aValue)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
;
1920 *aIsAllowed = CrashReporter::IsAnnotationAllowedForReport(annotation);
1921 return NS_OK;
1922}
1923
1924NS_IMETHODIMPnsresult
1925nsXULAppInfo::AppendAppNotesToCrashReport(const nsACString& data) {
1926 return CrashReporter::AppendAppNotesToCrashReport(data);
1927}
1928
1929NS_IMETHODIMPnsresult
1930nsXULAppInfo::RegisterAppMemory(uint64_t pointer, uint64_t len) {
1931 return CrashReporter::RegisterAppMemory((void*)pointer, len);
1932}
1933
1934NS_IMETHODIMPnsresult
1935nsXULAppInfo::WriteMinidumpForException(void* aExceptionInfo) {
1936#ifdef XP_WIN
1937 return CrashReporter::WriteMinidumpForException(
1938 static_cast<EXCEPTION_POINTERS*>(aExceptionInfo));
1939#else
1940 return NS_ERROR_NOT_IMPLEMENTED;
1941#endif
1942}
1943
1944NS_IMETHODIMPnsresult
1945nsXULAppInfo::AppendObjCExceptionInfoToAppNotes(void* aException) {
1946#ifdef XP_MACOSX
1947 return CrashReporter::AppendObjCExceptionInfoToAppNotes(aException);
1948#else
1949 return NS_ERROR_NOT_IMPLEMENTED;
1950#endif
1951}
1952
1953NS_IMETHODIMPnsresult
1954nsXULAppInfo::GetSubmitReports(bool* aEnabled) {
1955 return CrashReporter::GetSubmitReports(aEnabled);
1956}
1957
1958NS_IMETHODIMPnsresult
1959nsXULAppInfo::SetSubmitReports(bool aEnabled) {
1960 return CrashReporter::SetSubmitReports(aEnabled);
1961}
1962
1963NS_IMETHODIMPnsresult
1964nsXULAppInfo::UpdateCrashEventsDir() {
1965 CrashReporter::UpdateCrashEventsDir();
1966 return NS_OK;
1967}
1968
1969NS_IMETHODIMPnsresult
1970nsXULAppInfo::SaveMemoryReport() {
1971 if (!CrashReporter::GetEnabled()) {
1972 return NS_ERROR_NOT_INITIALIZED;
1973 }
1974 nsCOMPtr<nsIFile> file;
1975 nsresult rv = CrashReporter::GetDefaultMemoryReportFile(getter_AddRefs(file));
1976 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1976)
) {
1977 return rv;
1978 }
1979
1980 nsString path;
1981 file->GetPath(path);
1982
1983 nsCOMPtr<nsIMemoryInfoDumper> dumper =
1984 do_GetService("@mozilla.org/memory-info-dumper;1");
1985 if (NS_WARN_IF(!dumper)NS_warn_if_impl(!dumper, "!dumper", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1985)
) {
1986 return NS_ERROR_UNEXPECTED;
1987 }
1988
1989 rv = dumper->DumpMemoryReportsToNamedFile(
1990 path, this, file, true /* anonymize */, false /* minimizeMemoryUsage */);
1991 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1991)
) {
1992 return rv;
1993 }
1994 return NS_OK;
1995}
1996
1997// This method is from nsIFInishDumpingCallback.
1998NS_IMETHODIMPnsresult
1999nsXULAppInfo::Callback(nsISupports* aData) {
2000 nsCOMPtr<nsIFile> file = do_QueryInterface(aData);
2001 MOZ_ASSERT(file)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(file)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(file))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("file", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2001); AnnotateMozCrashReason("MOZ_ASSERT" "(" "file" ")");
do { MOZ_CrashSequence(__null, 2001); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2002
2003 CrashReporter::SetMemoryReportFile(file);
2004 return NS_OK;
2005}
2006
2007static const nsXULAppInfo kAppInfo;
2008namespace mozilla {
2009nsresult AppInfoConstructor(REFNSIIDconst nsIID& aIID, void** aResult) {
2010 return const_cast<nsXULAppInfo*>(&kAppInfo)->QueryInterface(aIID, aResult);
2011}
2012} // namespace mozilla
2013
2014bool gLogConsoleErrors = false;
2015
2016#define NS_ENSURE_TRUE_LOG(x, ret)do { if ((__builtin_expect(!!(!(x)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "x" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2016); gLogConsoleErrors = true; return ret; } } while (0)
\
2017 PR_BEGIN_MACROdo { \
2018 if (MOZ_UNLIKELY(!(x))(__builtin_expect(!!(!(x)), 0))) { \
2019 NS_WARNING("NS_ENSURE_TRUE(" #x ") failed")NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" #x ") failed"
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
2019)
; \
2020 gLogConsoleErrors = true; \
2021 return ret; \
2022 } \
2023 PR_END_MACRO} while (0)
2024
2025#define NS_ENSURE_SUCCESS_LOG(res, ret)do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(!
NS_FAILED_impl(res)), 1))))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "NS_SUCCEEDED(res)" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2025); gLogConsoleErrors = true; return ret; } } while (0)
\
2026 NS_ENSURE_TRUE_LOG(NS_SUCCEEDED(res), ret)do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(!
NS_FAILED_impl(res)), 1))))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "NS_SUCCEEDED(res)" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2026); gLogConsoleErrors = true; return ret; } } while (0)
2027
2028/**
2029 * Because we're starting/stopping XPCOM several times in different scenarios,
2030 * this class is a stack-based critter that makes sure that XPCOM is shut down
2031 * during early returns.
2032 */
2033
2034class ScopedXPCOMStartup {
2035 public:
2036 ScopedXPCOMStartup() : mServiceManager(nullptr) {}
2037 ~ScopedXPCOMStartup();
2038
2039 nsresult Initialize(bool aInitJSContext = true);
2040 nsresult SetWindowCreator(nsINativeAppSupport* native);
2041
2042 private:
2043 nsIServiceManager* mServiceManager;
2044 static nsINativeAppSupport* gNativeAppSupport;
2045
2046 friend already_AddRefed<nsINativeAppSupport> NS_GetNativeAppSupport();
2047};
2048
2049ScopedXPCOMStartup::~ScopedXPCOMStartup() {
2050 NS_IF_RELEASE(gNativeAppSupport)do { if (gNativeAppSupport) { (gNativeAppSupport)->Release
(); (gNativeAppSupport) = 0; } } while (0)
;
2051
2052 if (mServiceManager) {
2053#ifdef XP_MACOSX
2054 // On OS X, we need a pool to catch cocoa objects that are autoreleased
2055 // during teardown.
2056 mozilla::MacAutoreleasePool pool;
2057#endif
2058
2059 nsCOMPtr<nsIAppStartup> appStartup(components::AppStartup::Service());
2060 if (appStartup) appStartup->DestroyHiddenWindow();
2061
2062 gDirServiceProvider->DoShutdown();
2063 PROFILER_MARKER_UNTYPED("Shutdown early", OTHER)do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Shutdown early", ::geckoprofiler::category::OTHER); } } while
(false); } while (false)
;
2064
2065 WriteConsoleLog();
2066
2067 NS_ShutdownXPCOM(mServiceManager);
2068 mServiceManager = nullptr;
2069 }
2070}
2071
2072nsresult ScopedXPCOMStartup::Initialize(bool aInitJSContext) {
2073 NS_ASSERTION(gDirServiceProvider, "Should not get here!")do { if (!(gDirServiceProvider)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Should not get here!", "gDirServiceProvider", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2073); MOZ_PretendNoReturn(); } } while (0)
;
2074
2075 nsresult rv;
2076
2077 rv = NS_InitXPCOM(&mServiceManager, gDirServiceProvider->GetAppDir(),
2078 gDirServiceProvider, aInitJSContext);
2079 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2080 NS_ERROR("Couldn't start xpcom!")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Couldn't start xpcom!"
, "Error", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
2080); MOZ_PretendNoReturn(); } while (0)
;
2081 mServiceManager = nullptr;
2082 } else {
2083#ifdef DEBUG1
2084 nsCOMPtr<nsIComponentRegistrar> reg = do_QueryInterface(mServiceManager);
2085 NS_ASSERTION(reg, "Service Manager doesn't QI to Registrar.")do { if (!(reg)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Service Manager doesn't QI to Registrar."
, "reg", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2085
); MOZ_PretendNoReturn(); } } while (0)
;
2086#endif
2087 }
2088
2089 return rv;
2090}
2091
2092/**
2093 * This is a little factory class that serves as a singleton-service-factory
2094 * for the nativeappsupport object.
2095 */
2096class nsSingletonFactory final : public nsIFactory {
2097 public:
2098 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:
2099 NS_DECL_NSIFACTORYvirtual nsresult CreateInstance(const nsIID & iid, void *
* result) override;
2100
2101 explicit nsSingletonFactory(nsISupports* aSingleton);
2102
2103 private:
2104 ~nsSingletonFactory() = default;
2105 nsCOMPtr<nsISupports> mSingleton;
2106};
2107
2108nsSingletonFactory::nsSingletonFactory(nsISupports* aSingleton)
2109 : mSingleton(aSingleton) {
2110 NS_ASSERTION(mSingleton, "Singleton was null!")do { if (!(mSingleton)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Singleton was null!"
, "mSingleton", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2110); MOZ_PretendNoReturn(); } } while (0)
;
2111}
2112
2113NS_IMPL_ISUPPORTS(nsSingletonFactory, nsIFactory)MozExternalRefCountType nsSingletonFactory::AddRef(void) { static_assert
(!std::is_destructible_v<nsSingletonFactory>, "Reference-counted class "
"nsSingletonFactory" " 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" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2113); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 2113
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsSingletonFactory" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsSingletonFactory" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"nsSingletonFactory\" != nullptr" " (" "Must specify a name"
")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2113
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsSingletonFactory\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 2113); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsSingletonFactory" " not thread-safe"); nsrefcnt
count = ++mRefCnt; NS_LogAddRef((this), (count), ("nsSingletonFactory"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
nsSingletonFactory::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"
")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2113
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 2113
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsSingletonFactory" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsSingletonFactory" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"nsSingletonFactory\" != nullptr" " (" "Must specify a name"
")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2113
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsSingletonFactory\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 2113); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsSingletonFactory" " not thread-safe"); const
char* const nametmp = "nsSingletonFactory"; nsrefcnt count =
--mRefCnt; NS_LogRelease((this), (count), (nametmp)); if (count
== 0) { mRefCnt = 1; delete (this); return 0; } return count
; } nsresult nsSingletonFactory::QueryInterface(const nsIID&
aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2113); 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<nsSingletonFactory, nsIFactory>, int32_t
( reinterpret_cast<char*>(static_cast<nsIFactory*>
((nsSingletonFactory*)0x1000)) - reinterpret_cast<char*>
((nsSingletonFactory*)0x1000))}, {&mozilla::detail::kImplementedIID
<nsSingletonFactory, nsISupports>, int32_t(reinterpret_cast
<char*>(static_cast<nsISupports*>( static_cast<
nsIFactory*>((nsSingletonFactory*)0x1000))) - reinterpret_cast
<char*>((nsSingletonFactory*)0x1000))}, { nullptr, 0 } }
; static_assert(std::size(table) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
2114
2115NS_IMETHODIMPnsresult
2116nsSingletonFactory::CreateInstance(const nsIID& aIID, void** aResult) {
2117 return mSingleton->QueryInterface(aIID, aResult);
2118}
2119
2120/**
2121 * Set our windowcreator on the WindowWatcher service.
2122 */
2123nsresult ScopedXPCOMStartup::SetWindowCreator(nsINativeAppSupport* native) {
2124 nsresult rv;
2125
2126 NS_IF_ADDREF(gNativeAppSupport = native)ns_if_addref(gNativeAppSupport = native);
2127
2128 nsCOMPtr<nsIWindowCreator> creator(components::AppStartup::Service());
2129 if (!creator) return NS_ERROR_UNEXPECTED;
2130
2131 nsCOMPtr<nsIWindowWatcher> wwatch(
2132 do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1", &rv));
2133 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, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2133); return rv; } } while (false)
;
2134
2135 return wwatch->SetWindowCreator(creator);
2136}
2137
2138/* static */ already_AddRefed<nsINativeAppSupport> NS_GetNativeAppSupport() {
2139 if (!ScopedXPCOMStartup::gNativeAppSupport) {
2140 return nullptr;
2141 }
2142
2143 return do_AddRef(ScopedXPCOMStartup::gNativeAppSupport);
2144}
2145
2146#ifdef MOZ_HAS_REMOTE1
2147/* static */ already_AddRefed<nsIRemoteService> GetRemoteService() {
2148 AssertIsOnMainThread();
2149
2150 if (!gRemoteService) {
2151 gRemoteService = new nsRemoteService();
2152 }
2153 nsCOMPtr<nsIRemoteService> remoteService = gRemoteService.get();
2154 return remoteService.forget();
2155}
2156#endif
2157
2158nsINativeAppSupport* ScopedXPCOMStartup::gNativeAppSupport;
2159
2160static void DumpArbitraryHelp() {
2161 nsresult rv;
2162
2163 ScopedLogging log;
2164
2165 {
2166 ScopedXPCOMStartup xpcom;
2167 xpcom.Initialize();
2168
2169 nsCOMPtr<nsICommandLineRunner> cmdline(new nsCommandLine());
2170
2171 nsCString text;
2172 rv = cmdline->GetHelpText(text);
2173 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) printf("%s", text.get());
2174 }
2175}
2176
2177// English text needs to go into a dtd file.
2178// But when this is called we have no components etc. These strings must either
2179// be here, or in a native resource file.
2180static void DumpHelp() {
2181 printf(
2182 "Usage: %s [ options ... ] [URL]\n"
2183 " where options include:\n\n",
2184 gArgv[0]);
2185
2186#ifdef MOZ_X111
2187 printf(
2188 "X11 options\n"
2189 " --display=DISPLAY X display to use\n"
2190 " --sync Make X calls synchronous\n");
2191#endif
2192#ifdef XP_UNIX1
2193 printf(
2194 " --g-fatal-warnings Make all warnings fatal\n"
2195 "\n%s options\n",
2196 (const char*)gAppData->name);
2197#endif
2198
2199 printf(
2200 " -h or --help Print this message.\n"
2201 " -v or --version Print %s version.\n"
2202 " --full-version Print %s version, build and platform build ids.\n"
2203 " -P <profile> Start with <profile>.\n"
2204 " --profile <path> Start with profile at <path>.\n"
2205 " --migration Start with migration wizard.\n"
2206 " --ProfileManager Start with ProfileManager.\n"
2207 " --origin-to-force-quic-on <origin>\n"
2208 " Force to use QUIC for the specified origin.\n"
2209#ifdef MOZ_HAS_REMOTE1
2210 " --new-instance Open new instance, not a new window in running "
2211 "instance.\n"
2212#endif
2213 " --safe-mode Disables extensions and themes for this session.\n"
2214#ifdef MOZ_BLOCK_PROFILE_DOWNGRADE1
2215 " --allow-downgrade Allows downgrading a profile.\n"
2216#endif
2217 " --MOZ_LOG=<modules> Treated as MOZ_LOG=<modules> environment "
2218 "variable,\n"
2219 " overrides it.\n"
2220 " --MOZ_LOG_FILE=<file> Treated as MOZ_LOG_FILE=<file> environment "
2221 "variable,\n"
2222 " overrides it. If MOZ_LOG_FILE is not specified as "
2223 "an\n"
2224 " argument or as an environment variable, logging "
2225 "will be\n"
2226 " written to stdout.\n",
2227 (const char*)gAppData->name, (const char*)gAppData->name);
2228
2229#if defined(XP_WIN)
2230 printf(" --console Start %s with a debugging console.\n",
2231 (const char*)gAppData->name);
2232#endif
2233
2234#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK1) || defined(XP_MACOSX)
2235 printf(" --headless Run without a GUI.\n");
2236#endif
2237
2238#if defined(MOZ_ENABLE_DBUS1)
2239 printf(
2240 " --dbus-service <launcher> Run as DBus service for "
2241 "org.freedesktop.Application and\n"
2242 " set a launcher (usually /usr/bin/appname "
2243 "script) for it.\n");
2244#endif
2245
2246 // this works, but only after the components have registered. so if you drop
2247 // in a new command line handler, --help won't not until the second run. out
2248 // of the bug, because we ship a component.reg file, it works correctly.
2249 DumpArbitraryHelp();
2250}
2251
2252static inline void DumpVersion() {
2253 if (gAppData->vendor && *gAppData->vendor) {
2254 printf("%s ", (const char*)gAppData->vendor);
2255 }
2256 printf("%s ", (const char*)gAppData->name);
2257
2258 // Use the displayed version
2259 // For example, for beta, we would display 42.0b2 instead of 42.0
2260 printf("%s", MOZ_STRINGIFY(MOZ_APP_VERSION_DISPLAY)"158.0a1");
2261
2262 if (gAppData->copyright && *gAppData->copyright) {
2263 printf(", %s", (const char*)gAppData->copyright);
2264 }
2265 printf("\n");
2266}
2267
2268static inline void DumpFullVersion() {
2269 if (gAppData->vendor && *gAppData->vendor) {
2270 printf("%s ", (const char*)gAppData->vendor);
2271 }
2272 printf("%s ", (const char*)gAppData->name);
2273
2274 // Use the displayed version
2275 // For example, for beta, we would display 42.0b2 instead of 42.0
2276 printf("%s ", MOZ_STRINGIFY(MOZ_APP_VERSION_DISPLAY)"158.0a1");
2277
2278 printf("%s ", (const char*)gAppData->buildID);
2279 printf("%s ", (const char*)PlatformBuildID());
2280 if (gAppData->copyright && *gAppData->copyright) {
2281 printf(", %s", (const char*)gAppData->copyright);
2282 }
2283 printf("\n");
2284}
2285
2286void XRE_InitOmnijar(nsIFile* greOmni, nsIFile* appOmni) {
2287 mozilla::Omnijar::Init(greOmni, appOmni);
2288}
2289
2290nsresult XRE_GetBinaryPath(nsIFile** aResult) {
2291 return mozilla::BinaryPath::GetFile(aResult);
2292}
2293
2294#ifdef XP_WIN
2295# include "nsWindowsRestart.cpp"
2296# include <shellapi.h>
2297
2298typedef BOOL(WINAPI* SetProcessDEPPolicyFunc)(DWORD dwFlags);
2299
2300static void RegisterApplicationRestartChanged(const char* aPref, void* aData) {
2301 DWORD cchCmdLine = 0;
2302 HRESULT rc = ::GetApplicationRestartSettings(::GetCurrentProcess(), nullptr,
2303 &cchCmdLine, nullptr);
2304 bool wasRegistered = false;
2305 if (rc == S_OK) {
2306 wasRegistered = true;
2307 }
2308
2309 if (Preferences::GetBool(PREF_WIN_REGISTER_APPLICATION_RESTART, false) &&
2310 !wasRegistered) {
2311 // Make the command line to use when restarting.
2312 // Excludes argv[0] because RegisterApplicationRestart adds the
2313 // executable name, replace that temporarily with -os-restarted
2314 char* exeName = gRestartArgv[0];
2315 gRestartArgv[0] = const_cast<char*>("-os-restarted");
2316 wchar_t** restartArgvConverted =
2317 AllocConvertUTF8toUTF16Strings(gRestartArgc, gRestartArgv);
2318 gRestartArgv[0] = exeName;
2319
2320 mozilla::UniquePtr<wchar_t[]> restartCommandLine;
2321 if (restartArgvConverted) {
2322 restartCommandLine =
2323 mozilla::MakeCommandLine(gRestartArgc, restartArgvConverted);
2324 FreeAllocStrings(gRestartArgc, restartArgvConverted);
2325 }
2326
2327 if (restartCommandLine) {
2328 // Flags RESTART_NO_PATCH and RESTART_NO_REBOOT are not set, so we
2329 // should be restarted if terminated by an update or restart.
2330 ::RegisterApplicationRestart(restartCommandLine.get(),
2331 RESTART_NO_CRASH | RESTART_NO_HANG);
2332 }
2333 } else if (wasRegistered) {
2334 ::UnregisterApplicationRestart();
2335 }
2336}
2337
2338static void OnAlteredPrefetchPrefChanged(const char* aPref, void* aData) {
2339 int32_t prefVal = Preferences::GetInt(PREF_WIN_ALTERED_DLL_PREFETCH, 0);
2340
2341 mozilla::DllPrefetchExperimentRegistryInfo prefetchRegInfo;
2342 mozilla::DebugOnly<mozilla::Result<Ok, nsresult>> reflectResult =
2343 prefetchRegInfo.ReflectPrefToRegistry(prefVal);
2344
2345 MOZ_ASSERT(reflectResult.value.isOk())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(reflectResult.value.isOk())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(reflectResult.value.isOk()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("reflectResult.value.isOk()"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2345); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "reflectResult.value.isOk()" ")"); do { MOZ_CrashSequence
(__null, 2345); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2346}
2347
2348static void SetupAlteredPrefetchPref() {
2349 mozilla::DllPrefetchExperimentRegistryInfo prefetchRegInfo;
2350
2351 mozilla::DebugOnly<mozilla::Result<Ok, nsresult>> reflectResult =
2352 prefetchRegInfo.ReflectPrefToRegistry(
2353 Preferences::GetInt(PREF_WIN_ALTERED_DLL_PREFETCH, 0));
2354 MOZ_ASSERT(reflectResult.value.isOk())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(reflectResult.value.isOk())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(reflectResult.value.isOk()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("reflectResult.value.isOk()"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2354); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "reflectResult.value.isOk()" ")"); do { MOZ_CrashSequence
(__null, 2354); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2355
2356 Preferences::RegisterCallback(&OnAlteredPrefetchPrefChanged,
2357 PREF_WIN_ALTERED_DLL_PREFETCH);
2358}
2359
2360static LazyLogModule gSkeletonLog("PreXULSkeletonUI");
2361# define SKELETON_LOG(str, ...) \
2362 MOZ_LOG(gSkeletonLog, LogLevel::Debug, (str, ##__VA_ARGS__))do { const ::mozilla::LogModule* moz_real_module = gSkeletonLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, str, ##__VA_ARGS__); } } while (0)
2363static void ReflectSkeletonUIPrefToRegistry(const char* aPref, void* aData) {
2364 (void)aPref;
2365 (void)aData;
2366
2367 RefPtr<nsToolkitProfileService> mProfileSvc;
2368 mProfileSvc = NS_GetToolkitProfileService();
2369
2370 bool hasShowProfileSelector = mProfileSvc->HasShowProfileSelector();
2371 bool skeletonUIPref = StaticPrefs::browser_startup_preXulSkeletonUI();
2372 bool startupBlankWindowPref = StaticPrefs::browser_startup_blankWindow();
2373 bool drawInTitlebar = LookAndFeel::DrawInTitlebar();
2374 SKELETON_LOG(
2375 "ReflectSkeletonUIPrefToRegistry: hasShowProfileSelector %d, "
2376 "skeletonUIPref %d, startupBlankWindowPref %d, drawInTitlebar %d",
2377 hasShowProfileSelector ? 1 : 0, skeletonUIPref ? 1 : 0,
2378 startupBlankWindowPref ? 1 : 0, drawInTitlebar ? 1 : 0);
2379
2380 bool shouldBeEnabled = !hasShowProfileSelector && skeletonUIPref &&
2381 startupBlankWindowPref && drawInTitlebar;
2382 SKELETON_LOG("ReflectSkeletonUIPrefToRegistry: shouldBeEnabled %d",
2383 shouldBeEnabled ? 1 : 0);
2384 if (shouldBeEnabled && Preferences::HasUserValue(kPrefThemeId)) {
2385 nsCString themeId;
2386 Preferences::GetCString(kPrefThemeId, themeId);
2387 if (themeId.EqualsLiteral("default-theme@mozilla.org")) {
2388 (void)SetPreXULSkeletonUIThemeId(ThemeMode::Default);
2389 } else if (themeId.EqualsLiteral("firefox-compact-dark@mozilla.org")) {
2390 (void)SetPreXULSkeletonUIThemeId(ThemeMode::Dark);
2391 } else if (themeId.EqualsLiteral("firefox-compact-light@mozilla.org")) {
2392 (void)SetPreXULSkeletonUIThemeId(ThemeMode::Light);
2393 } else {
2394 SKELETON_LOG(
2395 "ReflectSkeletonUIPrefToRegistry: clearing shouldBeEnabled "
2396 "because of bad themeId %s",
2397 themeId.get());
2398 shouldBeEnabled = false;
2399 }
2400 } else if (shouldBeEnabled) {
2401 (void)SetPreXULSkeletonUIThemeId(ThemeMode::Default);
2402 }
2403
2404 SKELETON_LOG(
2405 "ReflectSkeletonUIPrefToRegistry: old enabled %d, new enabled "
2406 "%d",
2407 GetPreXULSkeletonUIEnabled() ? 1 : 0, shouldBeEnabled ? 1 : 0);
2408 if (GetPreXULSkeletonUIEnabled() != shouldBeEnabled) {
2409 (void)SetPreXULSkeletonUIEnabledIfAllowed(shouldBeEnabled);
2410 }
2411}
2412# undef SKELETON_LOG
2413
2414class ShowProfileSelectorObserver final : public nsIObserver {
2415 public:
2416 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:
2417 NS_DECL_NSIOBSERVERvirtual nsresult Observe(nsISupports *aSubject, const char * aTopic
, const char16_t * aData) override;
2418
2419 ShowProfileSelectorObserver() = default;
2420
2421 protected:
2422 ~ShowProfileSelectorObserver() = default;
2423};
2424
2425NS_IMPL_ISUPPORTS(ShowProfileSelectorObserver, nsIObserver)MozExternalRefCountType ShowProfileSelectorObserver::AddRef(void
) { static_assert(!std::is_destructible_v<ShowProfileSelectorObserver
>, "Reference-counted class " "ShowProfileSelectorObserver"
" 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" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2425); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 2425
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("ShowProfileSelectorObserver" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("ShowProfileSelectorObserver" != nullptr))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("\"ShowProfileSelectorObserver\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2425); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"ShowProfileSelectorObserver\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 2425); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("ShowProfileSelectorObserver" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"ShowProfileSelectorObserver"), (uint32_t)(sizeof(*this))); return
count; } MozExternalRefCountType ShowProfileSelectorObserver
::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" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2425); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 2425
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("ShowProfileSelectorObserver" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("ShowProfileSelectorObserver" != nullptr))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("\"ShowProfileSelectorObserver\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2425); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"ShowProfileSelectorObserver\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 2425); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("ShowProfileSelectorObserver" " not thread-safe"
); const char* const nametmp = "ShowProfileSelectorObserver";
nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult ShowProfileSelectorObserver::QueryInterface
(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2425); 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<ShowProfileSelectorObserver, nsIObserver
>, int32_t( reinterpret_cast<char*>(static_cast<nsIObserver
*>((ShowProfileSelectorObserver*)0x1000)) - reinterpret_cast
<char*>((ShowProfileSelectorObserver*)0x1000))}, {&
mozilla::detail::kImplementedIID<ShowProfileSelectorObserver
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIObserver*>((ShowProfileSelectorObserver
*)0x1000))) - reinterpret_cast<char*>((ShowProfileSelectorObserver
*)0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table
) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
;
2426
2427NS_IMETHODIMPnsresult
2428ShowProfileSelectorObserver::Observe(nsISupports* aSubject, const char* aTopic,
2429 const char16_t* aData) {
2430 (void)aSubject;
2431 (void)aData;
2432 if (!strcmp(aTopic, "profile-show-selector-changed")) {
2433 ReflectSkeletonUIPrefToRegistry(nullptr, nullptr);
2434 }
2435
2436 return NS_OK;
2437}
2438
2439# if defined(MOZ_DEFAULT_BROWSER_AGENT)
2440
2441static void SetupSkeletonUIPrefs() {
2442 ReflectSkeletonUIPrefToRegistry(nullptr, nullptr);
2443 Preferences::RegisterCallback(&ReflectSkeletonUIPrefToRegistry,
2444 kPrefPreXulSkeletonUI);
2445 Preferences::RegisterCallback(&ReflectSkeletonUIPrefToRegistry,
2446 kPrefBrowserStartupBlankWindow);
2447 Preferences::RegisterCallback(&ReflectSkeletonUIPrefToRegistry, kPrefThemeId);
2448 Preferences::RegisterCallback(
2449 &ReflectSkeletonUIPrefToRegistry,
2450 nsDependentCString(StaticPrefs::GetPrefName_browser_tabs_inTitlebar()));
2451 nsCOMPtr<nsIObserverService> obsService =
2452 mozilla::services::GetObserverService();
2453 nsCOMPtr<nsIObserver> obs = new ShowProfileSelectorObserver();
2454 obsService->AddObserver(obs, "profile-show-selector-changed", false);
2455}
2456
2457# endif // defined(MOZ_DEFAULT_BROWSER_AGENT)
2458
2459# if defined(MOZ_LAUNCHER_PROCESS)
2460
2461static void OnLauncherPrefChanged(const char* aPref, void* aData) {
2462 bool prefVal = Preferences::GetBool(PREF_WIN_LAUNCHER_PROCESS_ENABLED, true);
2463
2464 mozilla::LauncherRegistryInfo launcherRegInfo;
2465 mozilla::DebugOnly<mozilla::LauncherVoidResult> reflectResult =
2466 launcherRegInfo.ReflectPrefToRegistry(prefVal);
2467 MOZ_ASSERT(reflectResult.inspect().isOk())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(reflectResult.inspect().isOk())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(reflectResult.inspect().isOk
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("reflectResult.inspect().isOk()", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2467); AnnotateMozCrashReason("MOZ_ASSERT" "(" "reflectResult.inspect().isOk()"
")"); do { MOZ_CrashSequence(__null, 2467); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2468}
2469
2470static void OnLauncherTelemetryPrefChanged(const char* aPref, void* aData) {
2471 bool prefVal = Preferences::GetBool(kPrefHealthReportUploadEnabled, true);
2472
2473 mozilla::LauncherRegistryInfo launcherRegInfo;
2474 mozilla::DebugOnly<mozilla::LauncherVoidResult> reflectResult =
2475 launcherRegInfo.ReflectTelemetryPrefToRegistry(prefVal);
2476 MOZ_ASSERT(reflectResult.inspect().isOk())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(reflectResult.inspect().isOk())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(reflectResult.inspect().isOk
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("reflectResult.inspect().isOk()", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2476); AnnotateMozCrashReason("MOZ_ASSERT" "(" "reflectResult.inspect().isOk()"
")"); do { MOZ_CrashSequence(__null, 2476); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2477}
2478
2479static void SetupLauncherProcessPref() {
2480 if (gLauncherProcessState) {
2481 // We've already successfully run
2482 return;
2483 }
2484
2485 mozilla::LauncherRegistryInfo launcherRegInfo;
2486
2487 mozilla::LauncherResult<mozilla::LauncherRegistryInfo::EnabledState>
2488 enabledState = launcherRegInfo.IsEnabled();
2489
2490 if (enabledState.isOk()) {
2491 gLauncherProcessState = Some(enabledState.unwrap());
2492
2493 CrashReporter::RecordAnnotationU32(
2494 CrashReporter::Annotation::LauncherProcessState,
2495 static_cast<uint32_t>(enabledState.unwrap()));
2496
2497 // Reflect the launcher process registry state into user prefs
2498 Preferences::SetBool(
2499 PREF_WIN_LAUNCHER_PROCESS_ENABLED,
2500 enabledState.unwrap() !=
2501 mozilla::LauncherRegistryInfo::EnabledState::ForceDisabled);
2502 }
2503
2504 mozilla::DebugOnly<mozilla::LauncherVoidResult> reflectResult =
2505 launcherRegInfo.ReflectTelemetryPrefToRegistry(
2506 Preferences::GetBool(kPrefHealthReportUploadEnabled, true));
2507 MOZ_ASSERT(reflectResult.inspect().isOk())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(reflectResult.inspect().isOk())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(reflectResult.inspect().isOk
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("reflectResult.inspect().isOk()", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2507); AnnotateMozCrashReason("MOZ_ASSERT" "(" "reflectResult.inspect().isOk()"
")"); do { MOZ_CrashSequence(__null, 2507); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2508
2509 Preferences::RegisterCallback(&OnLauncherPrefChanged,
2510 PREF_WIN_LAUNCHER_PROCESS_ENABLED);
2511 Preferences::RegisterCallback(&OnLauncherTelemetryPrefChanged,
2512 kPrefHealthReportUploadEnabled);
2513}
2514
2515# endif // defined(MOZ_LAUNCHER_PROCESS)
2516
2517# if defined(MOZ_DEFAULT_BROWSER_AGENT)
2518
2519# define DEFAULT_BROWSER_AGENT_KEY_NAME \
2520 "SOFTWARE\\" MOZ_APP_VENDOR"Mozilla" "\\" MOZ_APP_NAME"firefox" "\\Default Browser Agent"
2521
2522static nsresult PrependRegistryValueName(nsAutoString& aValueName) {
2523 nsresult rv;
2524
2525 nsCOMPtr<nsIFile> binaryPath;
2526 rv = XRE_GetBinaryPath(getter_AddRefs(binaryPath));
2527 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, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2527); return rv; } } while (false)
;
2528
2529 nsCOMPtr<nsIFile> binaryDir;
2530 rv = binaryPath->GetParent(getter_AddRefs(binaryDir));
2531 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, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2531); return rv; } } while (false)
;
2532
2533 nsAutoString prefix;
2534 rv = binaryDir->GetPath(prefix);
2535 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, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2535); return rv; } } while (false)
;
2536
2537 prefix.AppendLiteral("|");
2538 aValueName.Insert(prefix, 0);
2539
2540 return NS_OK;
2541}
2542
2543static void OnDefaultAgentTelemetryPrefChanged(const char* aPref, void* aData) {
2544 nsresult rv;
2545 nsAutoString valueName;
2546 if (strcmp(aPref, kPrefHealthReportUploadEnabled) == 0) {
2547 valueName.AssignLiteral("DisableTelemetry");
2548 } else if (strcmp(aPref, kPrefDefaultAgentEnabled) == 0) {
2549 valueName.AssignLiteral("DisableDefaultBrowserAgent");
2550 } else {
2551 return;
2552 }
2553 rv = PrependRegistryValueName(valueName);
2554 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2554); return; } } while (false)
;
2555
2556 nsCOMPtr<nsIWindowsRegKey> regKey =
2557 do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
2558 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2558); return; } } while (false)
;
2559
2560 nsAutoString keyName;
2561 keyName.AppendLiteral(DEFAULT_BROWSER_AGENT_KEY_NAME);
2562 rv = regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER, keyName,
2563 nsIWindowsRegKey::ACCESS_WRITE);
2564
2565 bool prefVal = Preferences::GetBool(aPref, true);
2566
2567 // We're recording whether the pref is *disabled*, so invert the value.
2568 rv = regKey->WriteIntValue(valueName, prefVal ? 0 : 1);
2569 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2569); return; } } while (false)
;
2570}
2571
2572static void OnSetDefaultBrowserUserChoicePrefChanged(const char* aPref,
2573 void* aData) {
2574 nsresult rv;
2575 if (strcmp(aPref, kPrefSetDefaultBrowserUserChoicePref) != 0) {
2576 return;
2577 }
2578 nsAutoString valueName;
2579 valueName.AssignLiteral("SetDefaultBrowserUserChoice");
2580 rv = PrependRegistryValueName(valueName);
2581 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2581); return; } } while (false)
;
2582
2583 nsCOMPtr<nsIWindowsRegKey> regKey =
2584 do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
2585 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2585); return; } } while (false)
;
2586
2587 nsAutoString keyName;
2588 keyName.AppendLiteral(DEFAULT_BROWSER_AGENT_KEY_NAME);
2589 rv = regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER, keyName,
2590 nsIWindowsRegKey::ACCESS_WRITE);
2591
2592 bool prefVal = Preferences::GetBool(aPref, true);
2593
2594 rv = regKey->WriteIntValue(valueName, prefVal);
2595 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2595); return; } } while (false)
;
2596}
2597
2598static void OnDefaultAgentRemoteSettingsPrefChanged(const char* aPref,
2599 void* aData) {
2600 nsresult rv;
2601 nsAutoString valueName;
2602 if (strcmp(aPref, kPrefServicesSettingsServer) == 0) {
2603 valueName.AssignLiteral("ServicesSettingsServer");
2604 } else {
2605 return;
2606 }
2607 rv = PrependRegistryValueName(valueName);
2608 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2608); return; } } while (false)
;
2609
2610 nsCOMPtr<nsIWindowsRegKey> regKey =
2611 do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
2612 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2612); return; } } while (false)
;
2613
2614 nsAutoString keyName;
2615 keyName.AppendLiteral(DEFAULT_BROWSER_AGENT_KEY_NAME);
2616 rv = regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER, keyName,
2617 nsIWindowsRegKey::ACCESS_WRITE);
2618
2619 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2619); return; } } while (false)
;
2620
2621 nsAutoString prefVal;
2622 rv = Preferences::GetString(aPref, prefVal);
2623 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2624 return;
2625 }
2626
2627 if (prefVal.IsEmpty()) {
2628 rv = regKey->RemoveValue(valueName);
2629 } else {
2630 rv = regKey->WriteStringValue(valueName, prefVal);
2631 }
2632 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2632); return; } } while (false)
;
2633}
2634
2635static void SetDefaultAgentLastRunTime() {
2636 nsresult rv;
2637 nsAutoString valueName;
2638 valueName.AppendLiteral("AppLastRunTime");
2639 rv = PrependRegistryValueName(valueName);
2640 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2640); return; } } while (false)
;
2641
2642 nsCOMPtr<nsIWindowsRegKey> regKey =
2643 do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
2644 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2644); return; } } while (false)
;
2645
2646 nsAutoString keyName;
2647 keyName.AppendLiteral(DEFAULT_BROWSER_AGENT_KEY_NAME);
2648 rv = regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER, keyName,
2649 nsIWindowsRegKey::ACCESS_WRITE);
2650 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2650); return; } } while (false)
;
2651
2652 FILETIME fileTime;
2653 GetSystemTimeAsFileTime(&fileTime);
2654
2655 ULARGE_INTEGER integerTime;
2656 integerTime.u.LowPart = fileTime.dwLowDateTime;
2657 integerTime.u.HighPart = fileTime.dwHighDateTime;
2658
2659 rv = regKey->WriteInt64Value(valueName, integerTime.QuadPart);
2660 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2660); return; } } while (false)
;
2661}
2662
2663# endif // defined(MOZ_DEFAULT_BROWSER_AGENT)
2664
2665#endif // XP_WIN
2666
2667void UnlockProfile() {
2668 if (gProfileLock) {
2669 gProfileLock->Unlock();
2670 }
2671}
2672
2673nsresult LaunchChild(bool aBlankCommandLine, bool aTryExec) {
2674 // Restart this process by exec'ing it into the current process
2675 // if supported by the platform. Otherwise, use NSPR.
2676
2677 if (aBlankCommandLine) {
2678 gRestartArgc = 1;
2679 gRestartArgv[gRestartArgc] = nullptr;
2680 }
2681
2682 SaveToEnv("MOZ_LAUNCHED_CHILD=1");
2683#if defined(MOZ_LAUNCHER_PROCESS)
2684 SaveToEnv("MOZ_LAUNCHER_PROCESS=1");
2685#endif // defined(MOZ_LAUNCHER_PROCESS)
2686
2687#if !defined(MOZ_WIDGET_ANDROID) // Android has separate restart code.
2688# if defined(XP_MACOSX)
2689 InitializeMacApp();
2690 CommandLineServiceMac::SetupMacCommandLine(gRestartArgc, gRestartArgv, true);
2691 LaunchMacApp(gRestartArgc, gRestartArgv);
2692# else
2693 nsCOMPtr<nsIFile> lf;
2694 nsresult rv = XRE_GetBinaryPath(getter_AddRefs(lf));
2695 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
2696
2697# if defined(XP_WIN)
2698 nsAutoString exePath;
2699 rv = lf->GetPath(exePath);
2700 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
2701
2702 HANDLE hProcess;
2703 if (!WinLaunchChild(exePath.get(), gRestartArgc, gRestartArgv, nullptr,
2704 &hProcess))
2705 return NS_ERROR_FAILURE;
2706 // Keep the current process around until the restarted process has created
2707 // its message queue, to avoid the launched process's windows being forced
2708 // into the background.
2709 mozilla::WaitForInputIdle(hProcess);
2710 ::CloseHandle(hProcess);
2711
2712# else
2713 nsAutoCString exePath;
2714 rv = lf->GetNativePath(exePath);
2715 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
2716
2717# if defined(XP_UNIX1)
2718 if (aTryExec) {
2719 execv(exePath.get(), gRestartArgv);
2720
2721 // If execv returns we know it's because it failed.
2722 return NS_ERROR_FAILURE;
2723 }
2724# endif
2725 if (PR_CreateProcessDetached(exePath.get(), gRestartArgv, nullptr, nullptr) ==
2726 PR_FAILURE) {
2727 return NS_ERROR_FAILURE;
2728 }
2729
2730 // Note that we don't know if the child process starts okay, if it
2731 // immediately returns non-zero then we may mask that by returning a zero
2732 // exit status.
2733
2734# endif // WP_WIN
2735# endif // WP_MACOSX
2736#endif // MOZ_WIDGET_ANDROID
2737
2738 return NS_ERROR_LAUNCHED_CHILD_PROCESS;
2739}
2740
2741static const char kProfileProperties[] =
2742 "chrome://mozapps/locale/profile/profileSelection.properties";
2743
2744namespace {
2745
2746/**
2747 * This class, instead of a raw nsresult, should be the return type of any
2748 * function called by SelectProfile that initializes XPCOM.
2749 */
2750class ReturnAbortOnError {
2751 public:
2752 MOZ_IMPLICIT ReturnAbortOnError(nsresult aRv) { mRv = ConvertRv(aRv); }
2753
2754 operator nsresult() { return mRv; }
2755
2756 private:
2757 inline nsresult ConvertRv(nsresult aRv) {
2758 if (NS_SUCCEEDED(aRv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1))) || aRv == NS_ERROR_LAUNCHED_CHILD_PROCESS) {
2759 return aRv;
2760 }
2761#ifdef MOZ_BACKGROUNDTASKS1
2762 // A background task that fails to lock its profile will return
2763 // NS_ERROR_UNEXPECTED and this will allow the task to exit with a
2764 // non-zero exit code.
2765 if (aRv == NS_ERROR_UNEXPECTED && BackgroundTasks::IsBackgroundTaskMode()) {
2766 return aRv;
2767 }
2768#endif
2769 return NS_ERROR_ABORT;
2770 }
2771
2772 nsresult mRv;
2773};
2774
2775} // namespace
2776
2777static nsresult ProfileMissingDialog(nsINativeAppSupport* aNative) {
2778#ifdef MOZ_WIDGET_ANDROID
2779 // We cannot really do anything this early during initialization, so we just
2780 // return as this is likely the effect of misconfiguration on the test side.
2781 // Non-test code paths cannot set the profile folder, which is always the
2782 // default one.
2783 Output(true, "Could not find profile folder.\n");
2784 return NS_ERROR_ABORT;
2785#else
2786# ifdef MOZ_BACKGROUNDTASKS1
2787 if (BackgroundTasks::IsBackgroundTaskMode()) {
2788 // We should never get to this point in background task mode.
2789 printf_stderr(
2790 "Could not determine any profile running in backgroundtask mode!\n");
2791 return NS_ERROR_ABORT;
2792 }
2793# endif // MOZ_BACKGROUNDTASKS
2794
2795 if (gfxPlatform::IsHeadless()) {
2796 // Nothing can dismiss a modal dialog in headless mode, so report the
2797 // failure on stderr and exit instead of spinning in the event loop.
2798 Output(true, "Could not find profile folder.\n");
2799 return NS_ERROR_ABORT;
2800 }
2801
2802 nsresult rv;
2803
2804 ScopedXPCOMStartup xpcom;
2805 rv = xpcom.Initialize();
2806 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, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2806); return rv; } } while (false)
;
2807
2808 rv = xpcom.SetWindowCreator(aNative);
2809 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)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", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2809); return
NS_ERROR_FAILURE; } } while (false)
;
2810
2811# ifdef XP_MACOSX
2812 InitializeMacApp();
2813# endif
2814
2815 { // extra scoping is needed so we release these components before xpcom
2816 // shutdown
2817 nsCOMPtr<nsIStringBundleService> sbs =
2818 mozilla::components::StringBundle::Service();
2819 NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(sbs)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "sbs" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2819); return NS_ERROR_FAILURE; } } while (false)
;
2820
2821 nsCOMPtr<nsIStringBundle> sb;
2822 sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
2823 NS_ENSURE_TRUE_LOG(sb, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(sb)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "sb" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2823); gLogConsoleErrors = true; return NS_ERROR_FAILURE; }
} while (0)
;
2824
2825 NS_ConvertUTF8toUTF16 appName(gAppData->name);
2826 AutoTArray<nsString, 2> params = {appName, appName};
2827
2828 // profileMissing
2829 nsAutoString missingMessage;
2830 rv = sb->FormatStringFromName("profileMissing", params, missingMessage);
2831 NS_ENSURE_SUCCESS(rv, NS_ERROR_ABORT)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", "NS_ERROR_ABORT", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2831); return
NS_ERROR_ABORT; } } while (false)
;
2832
2833 nsAutoString missingTitle;
2834 params.SetLength(1);
2835 rv = sb->FormatStringFromName("profileMissingTitle", params, missingTitle);
2836 NS_ENSURE_SUCCESS(rv, NS_ERROR_ABORT)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", "NS_ERROR_ABORT", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2836); return
NS_ERROR_ABORT; } } while (false)
;
2837
2838 nsCOMPtr<nsIPromptService> ps(do_GetService(NS_PROMPTSERVICE_CONTRACTID"@mozilla.org/prompter;1"));
2839 NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(ps)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "ps" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2839); return NS_ERROR_FAILURE; } } while (false)
;
2840
2841 ps->Alert(nullptr, missingTitle.get(), missingMessage.get());
2842
2843 return NS_ERROR_ABORT;
2844 }
2845#endif // MOZ_WIDGET_ANDROID
2846}
2847
2848// Shows the "encryption pref vs on-disk state" mismatch dialog and
2849// returns NS_ERROR_ABORT so the caller can exit cleanly. aMsgKey /
2850// aTitleKey select which of the two scenarios (encrypted-but-pref-off
2851// or pref-on-but-plaintext) is being reported.
2852static nsresult ProfileEncryptionMismatchDialog(const char* aMsgKey,
2853 const char* aTitleKey,
2854 nsINativeAppSupport* aNative) {
2855#ifdef MOZ_WIDGET_ANDROID
2856 Output(true, "Profile encryption state does not match launching build.\n");
2857 return NS_ERROR_ABORT;
2858#else
2859# ifdef MOZ_BACKGROUNDTASKS1
2860 if (BackgroundTasks::IsBackgroundTaskMode()) {
2861 printf_stderr(
2862 "Profile encryption state does not match launching build in "
2863 "backgroundtask mode\n");
2864 return NS_ERROR_ABORT;
2865 }
2866# endif // MOZ_BACKGROUNDTASKS
2867
2868 if (gfxPlatform::IsHeadless()) {
2869 // Nothing can dismiss a modal dialog in headless mode.
2870 Output(true, "Profile encryption state does not match launching build.\n");
2871 return NS_ERROR_ABORT;
2872 }
2873
2874 nsresult rv;
2875
2876 ScopedXPCOMStartup xpcom;
2877 rv = xpcom.Initialize();
2878 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, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2878); return rv; } } while (false)
;
2879
2880 rv = xpcom.SetWindowCreator(aNative);
2881 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)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", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2881); return
NS_ERROR_FAILURE; } } while (false)
;
2882
2883# ifdef XP_MACOSX
2884 InitializeMacApp();
2885# endif
2886
2887 { // extra scoping is needed so we release these components before xpcom
2888 // shutdown
2889 nsCOMPtr<nsIStringBundleService> sbs =
2890 mozilla::components::StringBundle::Service();
2891 NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(sbs)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "sbs" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2891); return NS_ERROR_FAILURE; } } while (false)
;
2892
2893 nsCOMPtr<nsIStringBundle> sb;
2894 sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
2895 NS_ENSURE_TRUE_LOG(sb, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(sb)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "sb" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2895); gLogConsoleErrors = true; return NS_ERROR_FAILURE; }
} while (0)
;
2896
2897 NS_ConvertUTF8toUTF16 appName(gAppData->name);
2898 AutoTArray<nsString, 3> params = {appName, appName, appName};
2899
2900 nsAutoString msg;
2901 rv = sb->FormatStringFromName(aMsgKey, params, msg);
2902 NS_ENSURE_SUCCESS(rv, NS_ERROR_ABORT)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", "NS_ERROR_ABORT", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2902); return
NS_ERROR_ABORT; } } while (false)
;
2903
2904 nsAutoString title;
2905 params.SetLength(1);
2906 rv = sb->FormatStringFromName(aTitleKey, params, title);
2907 NS_ENSURE_SUCCESS(rv, NS_ERROR_ABORT)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", "NS_ERROR_ABORT", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2907); return
NS_ERROR_ABORT; } } while (false)
;
2908
2909 nsCOMPtr<nsIPromptService> ps(do_GetService(NS_PROMPTSERVICE_CONTRACTID"@mozilla.org/prompter;1"));
2910 NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(ps)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "ps" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2910); return NS_ERROR_FAILURE; } } while (false)
;
2911
2912 ps->Alert(nullptr, title.get(), msg.get());
2913 return NS_ERROR_ABORT;
2914 }
2915#endif // MOZ_WIDGET_ANDROID
2916}
2917
2918static ReturnAbortOnError ProfileLockedDialog(nsIFile* aProfileDir,
2919 nsIFile* aProfileLocalDir,
2920 nsIProfileUnlocker* aUnlocker,
2921 nsINativeAppSupport* aNative,
2922 nsIProfileLock** aResult) {
2923 nsresult rv;
2924
2925 // We aren't going to start this instance so we can unblock other instances
2926 // from starting up.
2927#if defined(MOZ_HAS_REMOTE1)
2928 gStartupLock = nullptr;
2929#endif
2930
2931 bool exists;
2932 aProfileDir->Exists(&exists);
2933 if (!exists) {
2934 return ProfileMissingDialog(aNative);
2935 }
2936
2937 ScopedXPCOMStartup xpcom;
2938 rv = xpcom.Initialize();
2939 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, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2939); return rv; } } while (false)
;
2940
2941#if defined(MOZ_TELEMETRY_REPORTING)
2942 // We cannot check if telemetry has been disabled by the user, yet.
2943 // So, rely on the build time settings, instead.
2944 mozilla::Telemetry::WriteFailedProfileLock(aProfileDir);
2945#endif
2946
2947 rv = xpcom.SetWindowCreator(aNative);
2948 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)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", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2948); return
NS_ERROR_FAILURE; } } while (false)
;
2949
2950#ifdef XP_MACOSX
2951 InitializeMacApp();
2952#endif
2953
2954 { // extra scoping is needed so we release these components before xpcom
2955 // shutdown
2956 nsCOMPtr<nsIStringBundleService> sbs =
2957 mozilla::components::StringBundle::Service();
2958 NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(sbs)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "sbs" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2958); return NS_ERROR_FAILURE; } } while (false)
;
2959
2960 nsCOMPtr<nsIStringBundle> sb;
2961 sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
2962 NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(sbs)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "sbs" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2962); gLogConsoleErrors = true; return NS_ERROR_FAILURE; }
} while (0)
;
2963
2964 NS_ConvertUTF8toUTF16 appName(gAppData->name);
2965 AutoTArray<nsString, 3> params = {appName, appName, appName};
2966
2967 nsAutoString killMessage;
2968#ifndef XP_MACOSX
2969 rv = sb->FormatStringFromName(
2970 aUnlocker ? "restartMessageUnlocker" : "restartMessageNoUnlocker2",
2971 params, killMessage);
2972#else
2973 rv = sb->FormatStringFromName(
2974 aUnlocker ? "restartMessageUnlockerMac" : "restartMessageNoUnlockerMac",
2975 params, killMessage);
2976#endif
2977 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)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", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2977); return
NS_ERROR_FAILURE; } } while (false)
;
2978
2979 params.SetLength(1);
2980 nsAutoString killTitle;
2981 rv = sb->FormatStringFromName("restartTitle", params, killTitle);
2982 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)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", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2982); return
NS_ERROR_FAILURE; } } while (false)
;
2983
2984#ifdef MOZ_BACKGROUNDTASKS1
2985 if (BackgroundTasks::IsBackgroundTaskMode()) {
2986 // This error is handled specially to exit with a non-zero exit code.
2987 printf_stderr("%s\n", NS_LossyConvertUTF16toASCII(killMessage).get());
2988 return NS_ERROR_UNEXPECTED;
2989 }
2990#endif
2991
2992 if (gfxPlatform::IsHeadless()) {
2993 // TODO: make a way to turn off all dialogs when headless.
2994 Output(true, "%s\n", NS_LossyConvertUTF16toASCII(killMessage).get());
2995 return NS_ERROR_FAILURE;
2996 }
2997
2998 nsCOMPtr<nsIPromptService> ps(do_GetService(NS_PROMPTSERVICE_CONTRACTID"@mozilla.org/prompter;1"));
2999 NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(ps)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "ps" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2999); return NS_ERROR_FAILURE; } } while (false)
;
3000
3001 if (aUnlocker) {
3002 int32_t button;
3003#ifdef MOZ_WIDGET_ANDROID
3004 // On Android we always kill the process if the lock is still being held
3005 button = 0;
3006#else
3007 const uint32_t flags = (nsIPromptService::BUTTON_TITLE_IS_STRING *
3008 nsIPromptService::BUTTON_POS_0) +
3009 (nsIPromptService::BUTTON_TITLE_CANCEL *
3010 nsIPromptService::BUTTON_POS_1);
3011
3012 bool checkState = false;
3013 rv = ps->ConfirmEx(nullptr, killTitle.get(), killMessage.get(), flags,
3014 killTitle.get(), nullptr, nullptr, nullptr,
3015 &checkState, &button);
3016 NS_ENSURE_SUCCESS_LOG(rv, rv)do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(!
NS_FAILED_impl(rv)), 1))))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "NS_SUCCEEDED(rv)" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3016); gLogConsoleErrors = true; return rv; } } while (0)
;
3017#endif
3018
3019 if (button == 0) {
3020 rv = aUnlocker->Unlock(nsIProfileUnlocker::FORCE_QUIT);
3021 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3022 return rv;
3023 }
3024
3025 SaveFileToEnv("XRE_PROFILE_PATH", aProfileDir);
3026 SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", aProfileLocalDir);
3027
3028 return LaunchChild(false, true);
3029 }
3030 } else {
3031 rv = ps->Alert(nullptr, killTitle.get(), killMessage.get());
3032 NS_ENSURE_SUCCESS_LOG(rv, rv)do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(!
NS_FAILED_impl(rv)), 1))))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "NS_SUCCEEDED(rv)" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3032); gLogConsoleErrors = true; return rv; } } while (0)
;
3033 }
3034
3035 return NS_ERROR_ABORT;
3036 }
3037}
3038
3039static ReturnAbortOnError ShowProfileDialog(
3040 nsIToolkitProfileService* aProfileSvc, nsINativeAppSupport* aNative,
3041 const char* aDialogURL, const char* aTelemetryEnvVar) {
3042 nsresult rv;
3043
3044 nsCOMPtr<nsIFile> profD, profLD;
3045 bool offline = false;
3046 int32_t dialogReturn;
3047
3048 // We aren't going to start this instance so we can unblock other instances
3049 // from starting up.
3050#if defined(MOZ_HAS_REMOTE1)
3051 gStartupLock = nullptr;
3052#endif
3053
3054 {
3055 ScopedXPCOMStartup xpcom;
3056 rv = xpcom.Initialize();
3057 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, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3057); return rv; } } while (false)
;
3058
3059 rv = xpcom.SetWindowCreator(aNative);
3060 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)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", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3060); return
NS_ERROR_FAILURE; } } while (false)
;
3061
3062#ifdef XP_MACOSX
3063 InitializeMacApp();
3064 CommandLineServiceMac::SetupMacCommandLine(gRestartArgc, gRestartArgv,
3065 true);
3066#endif
3067
3068 { // extra scoping is needed so we release these components before xpcom
3069 // shutdown
3070 nsCOMPtr<nsIWindowWatcher> windowWatcher(
3071 do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1"));
3072 nsCOMPtr<nsIDialogParamBlock> ioParamBlock(
3073 do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID"@mozilla.org/embedcomp/dialogparam;1"));
3074 nsCOMPtr<nsIMutableArray> dlgArray(
3075 do_CreateInstance(NS_ARRAY_CONTRACTID"@mozilla.org/array;1"));
3076 NS_ENSURE_TRUE(windowWatcher && ioParamBlock && dlgArray,do { if ((__builtin_expect(!!(!(windowWatcher && ioParamBlock
&& dlgArray)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "windowWatcher && ioParamBlock && dlgArray"
") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3077); return NS_ERROR_FAILURE; } } while (false)
3077 NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(windowWatcher && ioParamBlock
&& dlgArray)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "windowWatcher && ioParamBlock && dlgArray"
") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3077); return NS_ERROR_FAILURE; } } while (false)
;
3078
3079 ioParamBlock->SetObjects(dlgArray);
3080
3081 nsCOMPtr<nsIAppStartup> appStartup(components::AppStartup::Service());
3082 NS_ENSURE_TRUE(appStartup, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(appStartup)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "appStartup" ") failed",
nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3082
); return NS_ERROR_FAILURE; } } while (false)
;
3083
3084 nsAutoCString features("centerscreen,chrome,modal,titlebar");
3085 // If we're launching a private browsing window make sure to set that
3086 // feature for the Profile Manager window as well, so it groups correctly
3087 // on the Windows taskbar.
3088 if (CheckArgExists("private-window") == ARG_FOUND) {
3089 features.AppendLiteral(",private");
3090 }
3091 nsCOMPtr<mozIDOMWindowProxy> newWindow;
3092 rv = windowWatcher->OpenWindow(nullptr, nsDependentCString(aDialogURL),
3093 u"_blank"_ns, features, ioParamBlock,
3094 getter_AddRefs(newWindow));
3095
3096 NS_ENSURE_SUCCESS_LOG(rv, rv)do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(!
NS_FAILED_impl(rv)), 1))))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "NS_SUCCEEDED(rv)" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3096); gLogConsoleErrors = true; return rv; } } while (0)
;
3097
3098 rv = ioParamBlock->GetInt(0, &dialogReturn);
3099 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || dialogReturn == nsIToolkitProfileService::exit) {
3100 return NS_ERROR_ABORT;
3101 }
3102
3103 int32_t startOffline;
3104 rv = ioParamBlock->GetInt(1, &startOffline);
3105 offline = NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && startOffline == 1;
3106
3107 rv = dlgArray->QueryElementAt(0, NS_GET_IID(nsIFile)(nsIFile::kIID),
3108 getter_AddRefs(profD));
3109 NS_ENSURE_SUCCESS_LOG(rv, rv)do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(!
NS_FAILED_impl(rv)), 1))))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "NS_SUCCEEDED(rv)" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3109); gLogConsoleErrors = true; return rv; } } while (0)
;
3110
3111 rv = dlgArray->QueryElementAt(1, NS_GET_IID(nsIFile)(nsIFile::kIID),
3112 getter_AddRefs(profLD));
3113 NS_ENSURE_SUCCESS_LOG(rv, rv)do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(!
NS_FAILED_impl(rv)), 1))))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "NS_SUCCEEDED(rv)" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3113); gLogConsoleErrors = true; return rv; } } while (0)
;
3114
3115 if (dialogReturn == nsIToolkitProfileService::launchWithProfile) {
3116 int32_t newArguments;
3117 rv = ioParamBlock->GetInt(2, &newArguments);
3118
3119 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && newArguments > 0) {
3120 char** newArgv = (char**)realloc(
3121 gRestartArgv, sizeof(char*) * (gRestartArgc + newArguments + 1));
3122 NS_ENSURE_TRUE(newArgv, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(newArgv)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "newArgv" ") failed", nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3122); return
NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
3123
3124 gRestartArgv = newArgv;
3125
3126 for (auto i = 0; i < newArguments; i++) {
3127 char16_t* arg;
3128 ioParamBlock->GetString(i, &arg);
3129 gRestartArgv[gRestartArgc++] =
3130 strdup(NS_ConvertUTF16toUTF8(nsDependentString(arg)).get());
3131 }
3132
3133 gRestartArgv[gRestartArgc] = nullptr;
3134 }
3135 }
3136 }
3137 }
3138
3139 if (offline) {
3140 SaveToEnv("XRE_START_OFFLINE=1");
3141 }
3142
3143 // User requested that we restart back into the profile manager.
3144 if (dialogReturn == nsIToolkitProfileService::restart) {
3145 SaveToEnv("XRE_RESTART_TO_PROFILE_MANAGER=1");
3146 } else {
3147 MOZ_ASSERT(dialogReturn == nsIToolkitProfileService::launchWithProfile)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(dialogReturn == nsIToolkitProfileService::launchWithProfile
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(dialogReturn == nsIToolkitProfileService::launchWithProfile
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"dialogReturn == nsIToolkitProfileService::launchWithProfile"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3147); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "dialogReturn == nsIToolkitProfileService::launchWithProfile"
")"); do { MOZ_CrashSequence(__null, 3147); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3148 SaveFileToEnv("XRE_PROFILE_PATH", profD);
3149 SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", profLD);
3150 }
3151 SaveToEnv(aTelemetryEnvVar);
3152
3153 if (gRestartedByOS) {
3154 // Re-add this argument when actually starting the application.
3155 char** newArgv =
3156 (char**)realloc(gRestartArgv, sizeof(char*) * (gRestartArgc + 2));
3157 NS_ENSURE_TRUE(newArgv, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(newArgv)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "newArgv" ") failed", nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3157); return
NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
3158 gRestartArgv = newArgv;
3159 gRestartArgv[gRestartArgc++] = const_cast<char*>("-os-restarted");
3160 gRestartArgv[gRestartArgc] = nullptr;
3161 }
3162
3163 return LaunchChild(false, true);
3164}
3165
3166static ReturnAbortOnError ShowProfileManager(
3167 nsIToolkitProfileService* aProfileSvc, nsINativeAppSupport* aNative) {
3168 static const char kProfileManagerURL[] =
3169 "chrome://mozapps/content/profile/profileSelection.xhtml";
3170 static const char kTelemetryEnv[] = "XRE_RESTARTED_BY_PROFILE_MANAGER=1";
3171
3172 return ShowProfileDialog(aProfileSvc, aNative, kProfileManagerURL,
3173 kTelemetryEnv);
3174}
3175
3176static ReturnAbortOnError ShowProfileSelector(
3177 nsIToolkitProfileService* aProfileSvc, nsINativeAppSupport* aNative) {
3178 static const char kProfileSelectorURL[] = "about:profilemanager";
3179 static const char kTelemetryEnv[] = "XRE_RESTARTED_BY_PROFILE_SELECTOR=1";
3180
3181 return ShowProfileDialog(aProfileSvc, aNative, kProfileSelectorURL,
3182 kTelemetryEnv);
3183}
3184
3185static bool gDoMigration = false;
3186static bool gDoProfileReset = false;
3187constinit static nsCOMPtr<nsIToolkitProfile> gResetOldProfile;
3188
3189static nsresult LockProfile(nsINativeAppSupport* aNative, nsIFile* aRootDir,
3190 nsIFile* aLocalDir, nsIToolkitProfile* aProfile,
3191 nsIProfileLock** aResult) {
3192 // If you close Firefox and very quickly reopen it, the old Firefox may
3193 // still be closing down. Rather than immediately showing the
3194 // "Firefox is running but is not responding" message, we spend a few
3195 // seconds retrying first.
3196
3197 static const int kLockRetrySeconds = 5;
3198 static const int kLockRetrySleepMS = 100;
3199
3200 nsresult rv;
3201 nsCOMPtr<nsIProfileUnlocker> unlocker;
3202 const TimeStamp start = TimeStamp::Now();
3203 do {
3204 if (aProfile) {
3205 rv = aProfile->Lock(getter_AddRefs(unlocker), aResult);
3206 } else {
3207 rv = NS_LockProfilePath(aRootDir, aLocalDir, getter_AddRefs(unlocker),
3208 aResult);
3209 }
3210 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3211 StartupTimeline::Record(StartupTimeline::AFTER_PROFILE_LOCKED);
3212 return NS_OK;
3213 }
3214 PR_Sleep(kLockRetrySleepMS);
3215 } while (TimeStamp::Now() - start <
3216 TimeDuration::FromSeconds(kLockRetrySeconds));
3217
3218 return ProfileLockedDialog(aRootDir, aLocalDir, unlocker, aNative, aResult);
3219}
3220
3221// Pick a profile. We need to end up with a profile root dir, local dir and
3222// potentially an nsIToolkitProfile instance.
3223//
3224// 1) check for --profile <path>
3225// 2) check for -P <name>
3226// 3) check for --ProfileManager
3227// 4) use the default profile, if there is one
3228// 5) if there are *no* profiles, set up profile-migration
3229// 6) display the profile-manager UI
3230static nsresult SelectProfile(nsToolkitProfileService* aProfileSvc,
3231 nsINativeAppSupport* aNative, nsIFile** aRootDir,
3232 nsIFile** aLocalDir, nsIToolkitProfile** aProfile,
3233 bool* aWasDefaultSelection) {
3234 StartupTimeline::Record(StartupTimeline::SELECT_PROFILE);
3235
3236 nsresult rv;
3237
3238 if (EnvHasValue("MOZ_RESET_PROFILE_RESTART")) {
3239 gDoProfileReset = true;
3240 gDoMigration = true;
3241 }
3242
3243 // reset-profile and migration args need to be checked before any profiles are
3244 // chosen below.
3245 ArgResult ar = CheckArg("reset-profile");
3246 if (ar == ARG_FOUND) {
3247 gDoProfileReset = true;
3248 }
3249
3250 ar = CheckArg("migration");
3251 if (ar == ARG_FOUND) {
3252 gDoMigration = true;
3253 }
3254
3255#if defined(XP_WIN)
3256 // This arg is only used to indicate to telemetry that a profile refresh
3257 // (reset+migration) was requested from the uninstaller, pass this along
3258 // via an environment variable for simplicity.
3259 ar = CheckArg("uninstaller-profile-refresh");
3260 if (ar == ARG_FOUND) {
3261 SaveToEnv("MOZ_UNINSTALLER_PROFILE_REFRESH=1");
3262 }
3263#endif
3264
3265 if (EnvHasValue("XRE_RESTART_TO_PROFILE_MANAGER")) {
3266 return ShowProfileManager(aProfileSvc, aNative);
3267 }
3268
3269 // Ask the profile manager to select the profile directories to use.
3270 bool didCreate = false;
3271 rv = aProfileSvc->SelectStartupProfile(&gArgc, gArgv, gDoProfileReset,
3272 aRootDir, aLocalDir, aProfile,
3273 &didCreate, aWasDefaultSelection);
3274
3275 if (rv == NS_ERROR_SHOW_PROFILE_MANAGER) {
3276 return ShowProfileManager(aProfileSvc, aNative);
3277 }
3278
3279 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, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3279); return rv; } } while (false)
;
3280
3281 if (didCreate) {
3282 // For a fresh install, we would like to let users decide
3283 // to do profile migration on their own later after using.
3284 gDoProfileReset = false;
3285 gDoMigration = false;
3286 }
3287
3288 if (gDoProfileReset && !*aProfile) {
3289 NS_WARNING("Profile reset is only supported for named profiles.")NS_DebugBreak(NS_DEBUG_WARNING, "Profile reset is only supported for named profiles."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
3289)
;
3290 return NS_ERROR_ABORT;
3291 }
3292
3293 // Block reset without migration for selectable profiles.
3294 // Bug 2020801: Update this to allow resetting without migration
3295 if (gDoProfileReset && !gDoMigration && *aProfile) {
3296 nsCString storeID;
3297 (*aProfile)->GetStoreID(storeID);
3298 if (!storeID.IsVoid()) {
3299 NS_WARNING("Selectable profiles cannot be reset without migration.")NS_DebugBreak(NS_DEBUG_WARNING, "Selectable profiles cannot be reset without migration."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
3299)
;
3300 return NS_ERROR_ABORT;
3301 }
3302 }
3303
3304 // No profile could be found. This generally shouldn't happen, a new profile
3305 // should be created in all cases except for profile reset which is covered
3306 // above, but just in case...
3307 if (!*aRootDir) {
3308 NS_WARNING("Failed to select or create profile.")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to select or create profile."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
3308)
;
3309 return NS_ERROR_ABORT;
3310 }
3311
3312 return NS_OK;
3313}
3314
3315#ifdef MOZ_BLOCK_PROFILE_DOWNGRADE1
3316struct FileWriteFunc final : public JSONWriteFunc {
3317 FILE* mFile;
3318 explicit FileWriteFunc(FILE* aFile) : mFile(aFile) {}
3319
3320 void Write(const Span<const char>& aStr) final {
3321 fprintf(mFile, "%.*s", int(aStr.size()), aStr.data());
3322 }
3323};
3324
3325static void SubmitDowngradeTelemetry(const nsCString& aLastVersion,
3326 bool aHasSync, int32_t aButton) {
3327 nsCOMPtr<nsIPrefService> prefSvc =
3328 do_GetService("@mozilla.org/preferences-service;1");
3329 NS_ENSURE_TRUE_VOID(prefSvc)do { if ((__builtin_expect(!!(!(prefSvc)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "prefSvc" ") failed", nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3329); return
; } } while (false)
;
3330
3331 nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(prefSvc);
3332 NS_ENSURE_TRUE_VOID(prefBranch)do { if ((__builtin_expect(!!(!(prefBranch)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "prefBranch" ") failed",
nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3332
); return; } } while (false)
;
3333
3334 bool enabled;
3335 nsresult rv =
3336 prefBranch->GetBoolPref(kPrefHealthReportUploadEnabled, &enabled);
3337 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3337); return; } } while (false)
;
3338 if (!enabled) {
3339 return;
3340 }
3341
3342 nsCString server;
3343 rv = prefBranch->GetCharPref("toolkit.telemetry.server", server);
3344 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3344); return; } } while (false)
;
3345
3346 nsCString clientId;
3347 rv = prefBranch->GetCharPref("toolkit.telemetry.cachedClientID", clientId);
3348 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3348); return; } } while (false)
;
3349
3350 nsCString profileGroupId;
3351 rv = prefBranch->GetCharPref("toolkit.telemetry.cachedProfileGroupID",
3352 profileGroupId);
3353 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3353); return; } } while (false)
;
3354
3355 rv = prefSvc->GetDefaultBranch(nullptr, getter_AddRefs(prefBranch));
3356 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3356); return; } } while (false)
;
3357
3358 nsCString channel("default");
3359 rv = prefBranch->GetCharPref("app.update.channel", channel);
3360 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3360); return; } } while (false)
;
3361
3362 nsID uuid;
3363 rv = nsID::GenerateUUIDInPlace(uuid);
3364 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3364); return; } } while (false)
;
3365
3366 nsCString arch("null");
3367 nsCOMPtr<nsIPropertyBag2> sysInfo =
3368 do_GetService("@mozilla.org/system-info;1");
3369 NS_ENSURE_TRUE_VOID(sysInfo)do { if ((__builtin_expect(!!(!(sysInfo)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "sysInfo" ") failed", nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3369); return
; } } while (false)
;
3370 sysInfo->GetPropertyAsACString(u"arch"_ns, arch);
3371
3372 bool isMSIX = false;
3373# ifdef XP_WIN
3374 rv = sysInfo->GetPropertyAsBool(u"hasWinPackageId"_ns, &isMSIX);
3375 if (rv != NS_OK) {
3376 // Don't early return.
3377 NS_ERROR("Failed to get property: hasWinPackageId")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Failed to get property: hasWinPackageId"
, "Error", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
3377); MOZ_PretendNoReturn(); } while (0)
;
3378 }
3379# endif
3380
3381 time_t now;
3382 time(&now);
3383 char date[sizeof "YYYY-MM-DDThh:mm:ss.000Z"];
3384 strftime(date, sizeof date, "%FT%T.000Z", gmtime(&now));
3385
3386 NSID_TrimBracketsASCII pingId(uuid);
3387 constexpr auto pingType = "downgrade"_ns;
3388
3389 int32_t pos = aLastVersion.Find("_");
3390 if (pos == kNotFound) {
3391 return;
3392 }
3393
3394 const nsDependentCSubstring lastVersion = Substring(aLastVersion, 0, pos);
3395 const nsDependentCSubstring lastBuildId =
3396 Substring(aLastVersion, pos + 1, 14);
3397
3398 nsPrintfCString url("%s/submit/telemetry/%s/%s/%s/%s/%s/%s?v=%d",
3399 server.get(), PromiseFlatCStringTPromiseFlatString<char>(pingId).get(),
3400 pingType.get(), (const char*)gAppData->name,
3401 (const char*)gAppData->version, channel.get(),
3402 (const char*)gAppData->buildID,
3403 TELEMETRY_PING_FORMAT_VERSION4);
3404
3405 nsCOMPtr<nsIFile> pingFile;
3406 rv = NS_GetSpecialDirectory(XRE_USER_APP_DATA_DIR"UAppData", getter_AddRefs(pingFile));
3407 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3407); return; } } while (false)
;
3408 rv = pingFile->Append(u"Pending Pings"_ns);
3409 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3409); return; } } while (false)
;
3410 rv = pingFile->Create(nsIFile::DIRECTORY_TYPE, 0755);
3411 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && rv != NS_ERROR_FILE_ALREADY_EXISTS) {
3412 return;
3413 }
3414 rv = pingFile->Append(NS_ConvertUTF8toUTF16(pingId));
3415 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3415); return; } } while (false)
;
3416
3417 nsCOMPtr<nsIFile> pingSender;
3418 rv = NS_GetSpecialDirectory(NS_GRE_BIN_DIR"GreBinD", getter_AddRefs(pingSender));
3419 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3419); return; } } while (false)
;
3420# ifdef XP_WIN
3421 pingSender->Append(u"pingsender.exe"_ns);
3422# else
3423 pingSender->Append(u"pingsender"_ns);
3424# endif
3425
3426 bool exists;
3427 rv = pingSender->Exists(&exists);
3428 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3428); return; } } while (false)
;
3429 if (!exists) {
3430 return;
3431 }
3432
3433 FILE* file;
3434 rv = pingFile->OpenANSIFileDesc("w", &file);
3435 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3435); return; } } while (false)
;
3436
3437 JSONWriter w(MakeUnique<FileWriteFunc>(file));
3438 w.Start();
3439 {
3440 w.StringProperty("type",
3441 Span<const char>(pingType.Data(), pingType.Length()));
3442 w.StringProperty("id", PromiseFlatCStringTPromiseFlatString<char>(pingId));
3443 w.StringProperty("creationDate", MakeStringSpan(date));
3444 w.IntProperty("version", TELEMETRY_PING_FORMAT_VERSION4);
3445 w.StringProperty("clientId", clientId);
3446 w.StringProperty("profileGroupId", profileGroupId);
3447 w.StartObjectProperty("application");
3448 {
3449 w.StringProperty("architecture", arch);
3450 w.StringProperty(
3451 "buildId",
3452 MakeStringSpan(static_cast<const char*>(gAppData->buildID)));
3453 w.StringProperty(
3454 "name", MakeStringSpan(static_cast<const char*>(gAppData->name)));
3455 w.StringProperty(
3456 "version",
3457 MakeStringSpan(static_cast<const char*>(gAppData->version)));
3458 w.StringProperty("displayVersion",
3459 MOZ_STRINGIFY(MOZ_APP_VERSION_DISPLAY)"158.0a1");
3460 w.StringProperty(
3461 "vendor", MakeStringSpan(static_cast<const char*>(gAppData->vendor)));
3462 w.StringProperty("platformVersion", gToolkitVersion);
3463# ifdef TARGET_XPCOM_ABI"x86_64-gcc3"
3464 w.StringProperty("xpcomAbi", TARGET_XPCOM_ABI"x86_64-gcc3");
3465# else
3466 w.StringProperty("xpcomAbi", "unknown");
3467# endif
3468 w.StringProperty("channel", channel);
3469 }
3470 w.EndObject();
3471 w.StartObjectProperty("payload");
3472 {
3473 w.StringProperty("lastVersion", PromiseFlatCStringTPromiseFlatString<char>(lastVersion));
3474 w.StringProperty("lastBuildId", PromiseFlatCStringTPromiseFlatString<char>(lastBuildId));
3475 w.BoolProperty("hasSync", aHasSync);
3476 w.IntProperty("button", aButton);
3477 w.BoolProperty("isMSIX", isMSIX);
3478 }
3479 w.EndObject();
3480 }
3481 w.End();
3482
3483 fclose(file);
3484
3485 PathString filePath = pingFile->NativePath();
3486 const filesystem::Path::value_type* args[2];
3487# ifdef XP_WIN
3488 nsString urlw = NS_ConvertUTF8toUTF16(url);
3489 args[0] = urlw.get();
3490# else
3491 args[0] = url.get();
3492# endif
3493 args[1] = filePath.get();
3494
3495 nsCOMPtr<nsIProcess> process =
3496 do_CreateInstance("@mozilla.org/process/util;1");
3497 NS_ENSURE_TRUE_VOID(process)do { if ((__builtin_expect(!!(!(process)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "process" ") failed", nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3497); return
; } } while (false)
;
3498 process->Init(pingSender);
3499 process->SetStartHidden(true);
3500 process->SetNoShell(true);
3501
3502# ifdef XP_WIN
3503 process->Runw(false, args, 2);
3504# else
3505 process->Run(false, args, 2);
3506# endif
3507}
3508
3509static const char kProfileDowngradeURL[] =
3510 "chrome://mozapps/content/profile/profileDowngrade.xhtml";
3511
3512static ReturnAbortOnError HandleDetectedDowngrade(
3513 nsIFile* aProfileDir, nsINativeAppSupport* aNative,
3514 nsIToolkitProfileService* aProfileSvc, const nsCString& aLastVersion) {
3515 int32_t result = 0;
3516 nsresult rv;
3517
3518 {
3519 if (gfxPlatform::IsHeadless()) {
3520 // TODO: make a way to turn off all dialogs when headless.
3521 Output(true,
3522 "This profile was last used with a newer version of this "
3523 "application. Please create a new profile.\n");
3524 return NS_ERROR_ABORT;
3525 }
3526
3527 ScopedXPCOMStartup xpcom;
3528 rv = xpcom.Initialize();
3529 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, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3529); return rv; } } while (false)
;
3530
3531 rv = xpcom.SetWindowCreator(aNative);
3532 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, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3532); return rv; } } while (false)
;
3533
3534# ifdef XP_MACOSX
3535 InitializeMacApp();
3536# endif
3537
3538 { // extra scoping is needed so we release these components before xpcom
3539 // shutdown
3540 bool hasSync = false;
3541 nsCOMPtr<nsIPrefService> prefSvc =
3542 do_GetService("@mozilla.org/preferences-service;1");
3543 NS_ENSURE_TRUE(prefSvc, rv)do { if ((__builtin_expect(!!(!(prefSvc)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "prefSvc" ") failed", nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3543); return
rv; } } while (false)
;
3544
3545 nsCOMPtr<nsIFile> prefsFile;
3546 rv = aProfileDir->Clone(getter_AddRefs(prefsFile));
3547 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, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3547); return rv; } } while (false)
;
3548
3549 rv = prefsFile->Append(u"prefs.js"_ns);
3550 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, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3550); return rv; } } while (false)
;
3551
3552 rv = prefSvc->ReadUserPrefsFromFile(prefsFile);
3553 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3554 nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(prefSvc);
3555
3556 rv = prefBranch->PrefHasUserValue("services.sync.username", &hasSync);
3557 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, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3557); return rv; } } while (false)
;
3558 }
3559
3560 nsCOMPtr<nsIWindowWatcher> windowWatcher =
3561 do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1");
3562 NS_ENSURE_TRUE(windowWatcher, NS_ERROR_ABORT)do { if ((__builtin_expect(!!(!(windowWatcher)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "windowWatcher" ") failed"
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
3562); return NS_ERROR_ABORT; } } while (false)
;
3563
3564 nsCOMPtr<nsIAppStartup> appStartup(components::AppStartup::Service());
3565 NS_ENSURE_TRUE(appStartup, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(appStartup)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "appStartup" ") failed",
nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3565
); return NS_ERROR_FAILURE; } } while (false)
;
3566
3567 nsCOMPtr<nsIDialogParamBlock> paramBlock =
3568 do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID"@mozilla.org/embedcomp/dialogparam;1");
3569 NS_ENSURE_TRUE(paramBlock, NS_ERROR_ABORT)do { if ((__builtin_expect(!!(!(paramBlock)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "paramBlock" ") failed",
nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3569
); return NS_ERROR_ABORT; } } while (false)
;
3570
3571 uint8_t flags = 0;
3572 if (hasSync) {
3573 flags |= nsIToolkitProfileService::hasSync;
3574 }
3575
3576 paramBlock->SetInt(0, flags);
3577
3578 nsAutoCString features("centerscreen,chrome,modal,titlebar");
3579 // If we're launching a private browsing window make sure to set that
3580 // feature for the Profile Manager window as well, so it groups correctly
3581 // on the Windows taskbar.
3582 if (CheckArgExists("private-window") == ARG_FOUND) {
3583 features.AppendLiteral(",private");
3584 }
3585 nsCOMPtr<mozIDOMWindowProxy> newWindow;
3586 rv = windowWatcher->OpenWindow(
3587 nullptr, nsDependentCString(kProfileDowngradeURL), u"_blank"_ns,
3588 features, paramBlock, getter_AddRefs(newWindow));
3589 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, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3589); return rv; } } while (false)
;
3590
3591 paramBlock->GetInt(1, &result);
3592
3593 SubmitDowngradeTelemetry(aLastVersion, hasSync, result);
3594 }
3595 }
3596
3597 if (result == nsIToolkitProfileService::createNewProfile) {
3598 // Create a new profile and start it.
3599 nsCString profileName;
3600 profileName.AssignLiteral("default");
3601# ifdef MOZ_DEDICATED_PROFILES1
3602 profileName.Append("-" MOZ_STRINGIFY(MOZ_UPDATE_CHANNEL)"default");
3603# endif
3604 nsCOMPtr<nsIToolkitProfile> newProfile;
3605 rv = aProfileSvc->CreateUniqueProfile(nullptr, profileName, "downgrade"_ns,
3606 getter_AddRefs(newProfile));
3607 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, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3607); return rv; } } while (false)
;
3608 rv = aProfileSvc->SetDefaultProfile(newProfile);
3609 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, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3609); return rv; } } while (false)
;
3610 rv = aProfileSvc->Flush();
3611 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, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3611); return rv; } } while (false)
;
3612
3613 nsCOMPtr<nsIFile> profD, profLD;
3614 rv = newProfile->GetRootDir(getter_AddRefs(profD));
3615 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, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3615); return rv; } } while (false)
;
3616 rv = newProfile->GetLocalDir(getter_AddRefs(profLD));
3617 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, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3617); return rv; } } while (false)
;
3618
3619 SaveFileToEnv("XRE_PROFILE_PATH", profD);
3620 SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", profLD);
3621
3622 return LaunchChild(false, true);
3623 }
3624
3625 // Cancel
3626 return NS_ERROR_ABORT;
3627}
3628#endif
3629
3630/**
3631 * Extracts the various parts of a compatibility version string.
3632 *
3633 * Compatibility versions are of the form
3634 * "<appversion>_<appbuildid>/<platformbuildid>". The toolkit version comparator
3635 * can only handle 32-bit numbers and in the normal case build IDs are larger
3636 * than this. So if the build ID is numeric we split it into two version parts.
3637 */
3638static void ExtractCompatVersionInfo(const nsACString& aCompatVersion,
3639 nsACString& aAppVersion,
3640 nsACString& aAppBuildID) {
3641 int32_t underscorePos = aCompatVersion.FindChar('_');
3642 int32_t slashPos = aCompatVersion.FindChar('/');
3643
3644 if (underscorePos == kNotFound || slashPos == kNotFound ||
3645 slashPos < underscorePos) {
3646 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "compatibility.ini Version string does not match the expected format."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
3647)
3647 "compatibility.ini Version string does not match the expected format.")NS_DebugBreak(NS_DEBUG_WARNING, "compatibility.ini Version string does not match the expected format."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
3647)
;
3648
3649 // Fall back to just using the entire string as the version.
3650 aAppVersion = aCompatVersion;
3651 aAppBuildID.Truncate(0);
3652 return;
3653 }
3654
3655 aAppVersion = Substring(aCompatVersion, 0, underscorePos);
3656 aAppBuildID = Substring(aCompatVersion, underscorePos + 1,
3657 slashPos - (underscorePos + 1));
3658}
3659
3660/**
3661 * Compares the provided compatibility versions. Returns 0 if they match,
3662 * < 0 if the new version is considered an upgrade from the old version and
3663 * > 0 if the new version is considered a downgrade from the old version.
3664 */
3665int32_t CompareCompatVersions(const nsACString& aOldCompatVersion,
3666 const nsACString& aNewCompatVersion) {
3667 // Hardcode the case where the last run was in safe mode (Bug 1556612). We
3668 // cannot tell if this is a downgrade or not so just assume it isn't and let
3669 // the user proceed.
3670 if (aOldCompatVersion.EqualsLiteral("Safe Mode")) {
3671 return -1;
3672 }
3673
3674 // Extract the major version part from the version string and only use that
3675 // for version comparison.
3676 int32_t index = aOldCompatVersion.FindChar('.');
3677 const nsACString& oldMajorVersion = Substring(
3678 aOldCompatVersion, 0, index < 0 ? aOldCompatVersion.Length() : index);
3679 index = aNewCompatVersion.FindChar('.');
3680 const nsACString& newMajorVersion = Substring(
3681 aNewCompatVersion, 0, index < 0 ? aNewCompatVersion.Length() : index);
3682
3683 return CompareVersions(PromiseFlatCStringTPromiseFlatString<char>(oldMajorVersion).get(),
3684 PromiseFlatCStringTPromiseFlatString<char>(newMajorVersion).get());
3685}
3686
3687/**
3688 * Checks the compatibility.ini file to see if we have updated our application
3689 * or otherwise invalidated our caches. If the application has been updated,
3690 * we return false; otherwise, we return true.
3691 *
3692 * We also write the status of the caches (valid/invalid) into the return param
3693 * aCachesOK. The aCachesOK is always invalid if the application has been
3694 * updated.
3695 *
3696 * Finally, aIsDowngrade is set to true if the current application is older
3697 * than that previously used by the profile.
3698 */
3699static bool CheckCompatibility(nsIFile* aProfileDir, const nsCString& aVersion,
3700 const nsCString& aOSABI, nsIFile* aXULRunnerDir,
3701 nsIFile* aAppDir, nsIFile* aFlagFile,
3702 bool* aCachesOK, bool* aIsDowngrade,
3703 nsCString& aLastVersion) {
3704 *aCachesOK = false;
3705 *aIsDowngrade = false;
3706 gLastAppVersion.SetIsVoid(true);
3707 gLastAppBuildID.SetIsVoid(true);
3708 gProfileEncryptedDatabases = false;
3709
3710 nsCOMPtr<nsIFile> file;
3711 aProfileDir->Clone(getter_AddRefs(file));
3712 if (!file) return false;
3713 file->AppendNative(FILE_COMPATIBILITY_INFO"compatibility.ini"_ns);
3714
3715 nsINIParsernsINIParser_internal parser;
3716 nsresult rv = parser.Init(file);
3717 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return false;
3718
3719 // The EncryptedDatabases marker is independent of version compatibility, so
3720 // read it here -- compatibility.ini is already parsed -- before the early
3721 // returns below. Consumed by the encryption gate in XRE_mainStartup.
3722 {
3723 nsAutoCString encBuf;
3724 gProfileEncryptedDatabases =
3725 NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(parser.GetString(
"Compatibility", "EncryptedDatabases", encBuf))), 1)))
3726 parser.GetString("Compatibility", "EncryptedDatabases", encBuf))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parser.GetString(
"Compatibility", "EncryptedDatabases", encBuf))), 1)))
&&
3727 encBuf.EqualsLiteral("1");
3728 }
3729
3730 rv = parser.GetString("Compatibility", "LastVersion", aLastVersion);
3731 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3732 return false;
3733 }
3734
3735 if (!aLastVersion.Equals(aVersion)) {
3736 // The version is not the same. Whether it's a downgrade depends on an
3737 // actual comparison:
3738 *aIsDowngrade = 0 < CompareCompatVersions(aLastVersion, aVersion);
3739 ExtractCompatVersionInfo(aLastVersion, gLastAppVersion, gLastAppBuildID);
3740 return false;
3741 }
3742
3743 // If we get here, the version matched, but there may still be other
3744 // differences between us and the build that the profile last ran under.
3745
3746 gLastAppVersion.Assign(gAppData->version);
3747 gLastAppBuildID.Assign(gAppData->buildID);
3748
3749 nsAutoCString buf;
3750 rv = parser.GetString("Compatibility", "LastOSABI", buf);
3751 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !aOSABI.Equals(buf)) return false;
3752
3753 rv = parser.GetString("Compatibility", "LastPlatformDir", buf);
3754 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return false;
3755
3756 nsCOMPtr<nsIFile> lf;
3757 rv = NS_NewLocalFileWithPersistentDescriptor(buf, getter_AddRefs(lf));
3758 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return false;
3759
3760 bool eq;
3761 rv = lf->Equals(aXULRunnerDir, &eq);
3762 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !eq) return false;
3763
3764 if (aAppDir) {
3765 rv = parser.GetString("Compatibility", "LastAppDir", buf);
3766 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return false;
3767
3768 rv = NS_NewLocalFileWithPersistentDescriptor(buf, getter_AddRefs(lf));
3769 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return false;
3770
3771 rv = lf->Equals(aAppDir, &eq);
3772 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !eq) return false;
3773 }
3774
3775 // If we see this flag, caches are invalid.
3776 rv = parser.GetString("Compatibility", "InvalidateCaches", buf);
3777 *aCachesOK = (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !buf.EqualsLiteral("1"));
3778
3779 bool purgeCaches = false;
3780 if (aFlagFile && NS_SUCCEEDED(aFlagFile->Exists(&purgeCaches))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aFlagFile->Exists
(&purgeCaches))), 1)))
&&
3781 purgeCaches) {
3782 *aCachesOK = false;
3783 }
3784
3785 return true;
3786}
3787
3788void BuildCompatVersion(const char* aAppVersion, const char* aAppBuildID,
3789 const char* aToolkitBuildID, nsACString& aBuf) {
3790 aBuf.Assign(aAppVersion);
3791 aBuf.Append('_');
3792 aBuf.Append(aAppBuildID);
3793 aBuf.Append('/');
3794 aBuf.Append(aToolkitBuildID);
3795}
3796
3797static void BuildVersion(nsCString& aBuf) {
3798 BuildCompatVersion(gAppData->version, gAppData->buildID, gToolkitBuildID,
3799 aBuf);
3800}
3801
3802static void WriteVersion(nsIFile* aProfileDir, const nsCString& aVersion,
3803 const nsCString& aOSABI, nsIFile* aXULRunnerDir,
3804 nsIFile* aAppDir, bool invalidateCache) {
3805 nsCOMPtr<nsIFile> file;
3806 aProfileDir->Clone(getter_AddRefs(file));
3807 if (!file) return;
3808 file->AppendNative(FILE_COMPATIBILITY_INFO"compatibility.ini"_ns);
3809
3810 nsAutoCString platformDir;
3811 (void)aXULRunnerDir->GetPersistentDescriptor(platformDir);
3812
3813 nsAutoCString appDir;
3814 if (aAppDir) (void)aAppDir->GetPersistentDescriptor(appDir);
3815
3816 PRFileDesc* fd;
3817 nsresult rv = file->OpenNSPRFileDesc(PR_WRONLY0x02 | PR_CREATE_FILE0x08 | PR_TRUNCATE0x20,
3818 0600, &fd);
3819 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3820 NS_ERROR("could not create output stream")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "could not create output stream"
, "Error", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
3820); MOZ_PretendNoReturn(); } while (0)
;
3821 return;
3822 }
3823
3824 static const char kHeader[] = "[Compatibility]" NS_LINEBREAK"\012" "LastVersion=";
3825
3826 PR_Write(fd, kHeader, sizeof(kHeader) - 1);
3827 PR_Write(fd, aVersion.get(), aVersion.Length());
3828
3829 static const char kOSABIHeader[] = NS_LINEBREAK"\012" "LastOSABI=";
3830 PR_Write(fd, kOSABIHeader, sizeof(kOSABIHeader) - 1);
3831 PR_Write(fd, aOSABI.get(), aOSABI.Length());
3832
3833 static const char kPlatformDirHeader[] = NS_LINEBREAK"\012" "LastPlatformDir=";
3834
3835 PR_Write(fd, kPlatformDirHeader, sizeof(kPlatformDirHeader) - 1);
3836 PR_Write(fd, platformDir.get(), platformDir.Length());
3837
3838 static const char kAppDirHeader[] = NS_LINEBREAK"\012" "LastAppDir=";
3839 if (aAppDir) {
3840 PR_Write(fd, kAppDirHeader, sizeof(kAppDirHeader) - 1);
3841 PR_Write(fd, appDir.get(), appDir.Length());
3842 }
3843
3844 static const char kInvalidationHeader[] = NS_LINEBREAK"\012" "InvalidateCaches=1";
3845 if (invalidateCache)
3846 PR_Write(fd, kInvalidationHeader, sizeof(kInvalidationHeader) - 1);
3847
3848 // Re-emit the SQLite at-rest encryption marker (set in
3849 // gProfileEncryptedDatabases by CheckCompatibility); WriteVersion truncates
3850 // compatibility.ini, so otherwise the marker is lost on update and the
3851 // next-startup encryption gate would mistake an encrypted profile for a
3852 // plaintext one.
3853 static const char kEncryptedHeader[] = NS_LINEBREAK"\012" "EncryptedDatabases=1";
3854 if (gProfileEncryptedDatabases)
3855 PR_Write(fd, kEncryptedHeader, sizeof(kEncryptedHeader) - 1);
3856
3857 static const char kNL[] = NS_LINEBREAK"\012";
3858 PR_Write(fd, kNL, sizeof(kNL) - 1);
3859
3860 PR_Close(fd);
3861}
3862
3863// Read the first 24 bytes of the first existing canonical app DB and
3864// classify its encryption state by header inspection. No SQLite, no
3865// mozStorage -- a pure file read. Returns NoDBs if none of the canonical
3866// DBs exist in the profile.
3867enum class DBHeaderResult { Encrypted, Plaintext, NoDBs };
3868
3869static DBHeaderResult DetectEncryptedDBHeader(nsIFile* aProfileDir) {
3870 // Canonical DB list: any one of these existing is evidence of a
3871 // non-fresh profile. Order matters for cheapness only.
3872 static const char* const kCandidates[] = {
3873 "cookies.sqlite", "places.sqlite", "permissions.sqlite",
3874 "storage.sqlite", "favicons.sqlite",
3875 };
3876
3877 for (const char* name : kCandidates) {
3878 nsCOMPtr<nsIFile> file;
3879 if (NS_FAILED(aProfileDir->Clone(getter_AddRefs(file)))((bool)(__builtin_expect(!!(NS_FAILED_impl(aProfileDir->Clone
(getter_AddRefs(file)))), 0)))
|| !file) continue;
3880 if (NS_FAILED(file->AppendNative(nsDependentCString(name)))((bool)(__builtin_expect(!!(NS_FAILED_impl(file->AppendNative
(nsDependentCString(name)))), 0)))
) continue;
3881
3882 bool exists = false;
3883 if (NS_FAILED(file->Exists(&exists))((bool)(__builtin_expect(!!(NS_FAILED_impl(file->Exists(&
exists))), 0)))
|| !exists) continue;
3884
3885 PRFileDesc* fd = nullptr;
3886 if (NS_FAILED(file->OpenNSPRFileDesc(PR_RDONLY, 0, &fd))((bool)(__builtin_expect(!!(NS_FAILED_impl(file->OpenNSPRFileDesc
(0x01, 0, &fd))), 0)))
|| !fd) continue;
3887
3888 // SQLite database header layout (https://sqlite.org/fileformat.html): the
3889 // page size is a big-endian u16 at offset 16 and the per-page reserved-byte
3890 // count is a u8 at offset 20. obfsvfs always writes 8192-byte pages with 32
3891 // reserved bytes, which is how an at-rest-encrypted database is recognized.
3892 static constexpr int32_t kSQLiteHeaderReadBytes = 24;
3893 static constexpr int32_t kSQLiteHeaderMinBytes = 21;
3894 static constexpr size_t kSQLitePageSizeOffset = 16;
3895 static constexpr size_t kSQLiteReservedOffset = 20;
3896 static constexpr uint16_t kObfsPageSize = 8192;
3897 static constexpr uint8_t kObfsReservedBytes = 32;
3898
3899 uint8_t hdr[kSQLiteHeaderReadBytes];
3900 int32_t got = PR_Read(fd, hdr, sizeof(hdr));
3901 PR_Close(fd);
3902 if (got < kSQLiteHeaderMinBytes) continue;
3903
3904 uint16_t pageSize = (uint16_t(hdr[kSQLitePageSizeOffset]) << 8) |
3905 uint16_t(hdr[kSQLitePageSizeOffset + 1]);
3906 uint8_t reserved = hdr[kSQLiteReservedOffset];
3907
3908 if (pageSize == kObfsPageSize && reserved == kObfsReservedBytes) {
3909 return DBHeaderResult::Encrypted;
3910 }
3911 return DBHeaderResult::Plaintext;
3912 }
3913 return DBHeaderResult::NoDBs;
3914}
3915
3916enum class EncryptionCompatResult {
3917 OK,
3918 RefuseEncryptedButPrefOff,
3919 RefuseMigrationRequired,
3920};
3921
3922// Decide whether the on-disk state and the launching build's encryption
3923// pref are compatible. Must be called after CheckCompatibility() has run
3924// (it populates gProfileEncryptedDatabases). aPrefEnabled is the current
3925// value of security.storage.encryption.sqlite.enabled.
3926static EncryptionCompatResult CheckEncryptionCompatibility(nsIFile* aProfileDir,
3927 bool aPrefEnabled) {
3928 // Pref off: we cannot read an encrypted profile, so refuse it. The marker is
3929 // the fast path, but it can be absent on a profile that a prior build
3930 // encrypted without recording it (e.g. storage initialized too late to
3931 // mark), so also inspect the on-disk headers. The probe runs only when the
3932 // marker is absent, so the common (plaintext, never-encrypted) profile pays
3933 // it once at startup; an encrypted-looking profile is hard-failed rather
3934 // than opened as plaintext and corrupted.
3935 if (!aPrefEnabled) {
3936 if (gProfileEncryptedDatabases ||
3937 DetectEncryptedDBHeader(aProfileDir) == DBHeaderResult::Encrypted) {
3938 return EncryptionCompatResult::RefuseEncryptedButPrefOff;
3939 }
3940 return EncryptionCompatResult::OK;
3941 }
3942
3943 // Pref on, marker absent (or =0). Disambiguate by header inspection:
3944 // - empty profile or already-encrypted DBs -> OK (the marker is
3945 // (re)written by the storage layer on profile-after-change).
3946 // - plaintext DBs present -> refuse, migration required.
3947 if (!gProfileEncryptedDatabases &&
3948 DetectEncryptedDBHeader(aProfileDir) == DBHeaderResult::Plaintext) {
3949 return EncryptionCompatResult::RefuseMigrationRequired;
3950 }
3951
3952 return EncryptionCompatResult::OK;
3953}
3954
3955/**
3956 * Returns true if the startup cache file was successfully removed.
3957 * Returns false if file->Clone fails at any point (OOM) or if unable
3958 * to remove the startup cache file. Note in particular the return value
3959 * is unaffected by a failure to remove extensions.ini
3960 */
3961static bool RemoveComponentRegistries(nsIFile* aProfileDir,
3962 nsIFile* aLocalProfileDir,
3963 bool aRemoveEMFiles) {
3964 nsCOMPtr<nsIFile> file;
3965 aProfileDir->Clone(getter_AddRefs(file));
3966 if (!file) return false;
3967
3968 if (aRemoveEMFiles) {
3969 file->SetNativeLeafName("extensions.ini"_ns);
3970 file->Remove(false);
3971 }
3972
3973 aLocalProfileDir->Clone(getter_AddRefs(file));
3974 if (!file) return false;
3975
3976 file->AppendNative("startupCache"_ns);
3977 nsresult rv = file->Remove(true);
3978 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) || rv == NS_ERROR_FILE_NOT_FOUND;
3979}
3980
3981// When we first initialize the crash reporter we don't have a profile,
3982// so we set the minidump path to $TEMP. Once we have a profile,
3983// we set it to $PROFILE/minidumps, creating the directory
3984// if needed.
3985static void MakeOrSetMinidumpPath(nsIFile* profD) {
3986 nsCOMPtr<nsIFile> dumpD;
3987 profD->Clone(getter_AddRefs(dumpD));
3988
3989 if (dumpD) {
3990 bool fileExists;
3991 // XXX: do some more error checking here
3992 dumpD->Append(u"minidumps"_ns);
3993 dumpD->Exists(&fileExists);
3994 if (!fileExists) {
3995 nsresult rv = dumpD->Create(nsIFile::DIRECTORY_TYPE, 0700);
3996 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3996); return; } } while (false)
;
3997 }
3998
3999 nsAutoString pathStr;
4000 if (NS_SUCCEEDED(dumpD->GetPath(pathStr))((bool)(__builtin_expect(!!(!NS_FAILED_impl(dumpD->GetPath
(pathStr))), 1)))
)
4001 CrashReporter::SetMinidumpPath(pathStr);
4002 }
4003}
4004
4005const XREAppData* gAppData = nullptr;
4006
4007/**
4008 * NSPR will search for the "nspr_use_zone_allocator" symbol throughout
4009 * the process and use it to determine whether the application defines its own
4010 * memory allocator or not.
4011 *
4012 * Since most applications (e.g. Firefox and Thunderbird) don't use any special
4013 * allocators and therefore don't define this symbol, NSPR must search the
4014 * entire process, which reduces startup performance.
4015 *
4016 * By defining the symbol here, we can avoid the wasted lookup and hopefully
4017 * improve startup performance.
4018 */
4019NS_VISIBILITY_DEFAULT__attribute__((visibility("default"))) PRBool nspr_use_zone_allocator = PR_FALSE0;
4020
4021#ifdef CAIRO_HAS_DWRITE_FONT
4022
4023# include <dwrite.h>
4024# include "nsWindowsHelpers.h"
4025
4026# ifdef DEBUG_DWRITE_STARTUP
4027
4028# define LOGREGISTRY(msg) LogRegistryEvent(msg)
4029
4030// for use when monitoring process
4031static void LogRegistryEvent(const wchar_t* msg) {
4032 HKEY dummyKey;
4033 HRESULT hr;
4034 wchar_t buf[512];
4035
4036 wsprintf(buf, L" log %s", msg);
4037 hr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, buf, 0, KEY_READ, &dummyKey);
4038 if (SUCCEEDED(hr)) {
4039 RegCloseKey(dummyKey);
4040 }
4041}
4042# else
4043
4044# define LOGREGISTRY(msg)
4045
4046# endif
4047
4048static DWORD WINAPI InitDwriteBG(LPVOID lpdwThreadParam) {
4049 SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_BEGIN);
4050 LOGREGISTRY(L"loading dwrite.dll");
4051 HMODULE dwdll = LoadLibrarySystem32(L"dwrite.dll");
4052 if (dwdll) {
4053 decltype(DWriteCreateFactory)* createDWriteFactory =
4054 (decltype(DWriteCreateFactory)*)GetProcAddress(dwdll,
4055 "DWriteCreateFactory");
4056 if (createDWriteFactory) {
4057 LOGREGISTRY(L"creating dwrite factory");
4058 IDWriteFactory* factory;
4059 HRESULT hr = createDWriteFactory(DWRITE_FACTORY_TYPE_SHARED,
4060 __uuidof(IDWriteFactory),
4061 reinterpret_cast<IUnknown**>(&factory));
4062 if (SUCCEEDED(hr)) {
4063 LOGREGISTRY(L"dwrite factory done");
4064 factory->Release();
4065 LOGREGISTRY(L"freed factory");
4066 } else {
4067 LOGREGISTRY(L"failed to create factory");
4068 }
4069 }
4070 }
4071 SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_END);
4072 return 0;
4073}
4074#endif
4075
4076#include "GeckoProfiler.h"
4077#include "ProfilerControl.h"
4078
4079// Encapsulates startup and shutdown state for XRE_main
4080class XREMain {
4081 public:
4082 XREMain() = default;
4083
4084 ~XREMain() {
4085 mScopedXPCOM = nullptr;
4086 mAppData = nullptr;
4087 }
4088
4089 int XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig);
4090 int XRE_mainInit(bool* aExitFlag);
4091 int XRE_mainStartup(bool* aExitFlag);
4092 MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult XRE_mainRun();
4093
4094 bool CheckLastStartupWasCrash();
4095
4096 nsCOMPtr<nsINativeAppSupport> mNativeApp;
4097 RefPtr<nsToolkitProfileService> mProfileSvc;
4098 nsCOMPtr<nsIFile> mProfD;
4099 nsCOMPtr<nsIFile> mProfLD;
4100 nsCOMPtr<nsIProfileLock> mProfileLock;
4101
4102 UniquePtr<ScopedXPCOMStartup> mScopedXPCOM;
4103 UniquePtr<XREAppData> mAppData;
4104
4105 nsXREDirProvider mDirProvider;
4106
4107#ifdef MOZ_WIDGET_GTK1
4108 nsAutoCString mXDGActivationToken;
4109 nsAutoCString mDesktopStartupID;
4110#endif
4111
4112 bool mStartOffline = false;
4113 nsAutoCString mOriginToForceQUIC;
4114#if defined(MOZ_HAS_REMOTE1)
4115 bool mDisableRemoteClient = false;
4116#endif
4117};
4118
4119#if defined(XP_UNIX1) && !defined(ANDROID)
4120static SmprintfPointer FormatUid(uid_t aId) {
4121 if (const auto pw = getpwuid(aId)) {
4122 return mozilla::Smprintf("%s", pw->pw_name);
4123 }
4124 return mozilla::Smprintf("uid %d", static_cast<int>(aId));
4125}
4126
4127// Bug 1323302: refuse to run under sudo or similar.
4128static bool CheckForUserMismatch() {
4129 static char const* const kVars[] = {
4130 "HOME",
4131# ifdef MOZ_WIDGET_GTK1
4132 "XDG_RUNTIME_DIR",
4133# endif
4134# ifdef MOZ_X111
4135 "XAUTHORITY",
4136# endif
4137 };
4138
4139 const uid_t euid = geteuid();
4140 if (euid != 0) {
4141 // On Linux it's possible to have superuser capabilities with a
4142 // nonzero uid, but anyone who knows enough to make that happen
4143 // probably knows enough to debug the resulting problems.
4144 // Otherwise, a non-root user can't cause the problems we're
4145 // concerned about.
4146 return false;
4147 }
4148
4149 for (const auto var : kVars) {
4150 if (const auto path = PR_GetEnv(var)) {
4151 struct stat st;
4152 if (stat(path, &st) == 0) {
4153 if (st.st_uid != euid) {
4154 const auto owner = FormatUid(st.st_uid);
4155 Output(true,
4156 "Running " MOZ_APP_DISPLAYNAME"Nightly"
4157 " as root in a regular"
4158 " user's session is not supported. ($%s is %s which is"
4159 " owned by %s.)\n",
4160 var, path, owner.get());
4161 return true;
4162 }
4163 }
4164 }
4165 }
4166 return false;
4167}
4168#else // !XP_UNIX || ANDROID
4169static bool CheckForUserMismatch() { return false; }
4170#endif
4171
4172void mozilla::startup::IncreaseDescriptorLimits() {
4173#ifdef XP_UNIX1
4174 // Increase the fd limit to accomodate IPC resources like shared memory.
4175# ifdef XP_DARWIN
4176 // We use Mach IPC for shared memory, so a lower limit suffices.
4177 // See also the Darwin case in config/external/nspr/pr/moz.build
4178 static constexpr rlim_t kFDs = 4096;
4179# else // Unix but not Darwin
4180 // This can be increased if needed, but also be aware that Linux
4181 // distributions may impose hard limits less than this.
4182 static constexpr rlim_t kFDs = 65536;
4183# endif // Darwin or not
4184 struct rlimit rlim;
4185
4186 if (getrlimit(RLIMIT_NOFILERLIMIT_NOFILE, &rlim) != 0) {
4187 Output(false, "getrlimit: %s\n", strerror(errno(*__errno_location ())));
4188 return;
4189 }
4190 // Don't decrease the limit if it's already high enough, but don't
4191 // try to go over the hard limit. (RLIM_INFINITY isn't required to
4192 // be the numerically largest rlim_t, so don't assume that.)
4193 if (rlim.rlim_cur != RLIM_INFINITY((__rlim_t) -1) && rlim.rlim_cur < kFDs &&
4194 rlim.rlim_cur < rlim.rlim_max) {
4195 if (rlim.rlim_max != RLIM_INFINITY((__rlim_t) -1) && rlim.rlim_max < kFDs) {
4196 rlim.rlim_cur = rlim.rlim_max;
4197 } else {
4198 rlim.rlim_cur = kFDs;
4199 }
4200 if (setrlimit(RLIMIT_NOFILERLIMIT_NOFILE, &rlim) != 0) {
4201 Output(false, "setrlimit: %s\n", strerror(errno(*__errno_location ())));
4202 }
4203 }
4204#endif
4205}
4206
4207#ifdef XP_WIN
4208// Looks for the current CPU microcode version, returns 0 if it cannot find it
4209static uint32_t FindCPUMicrocodeVersion(HKEY key) {
4210 // Windows uses different registry values to surface the current microcode
4211 // value, and sometimes different update levels of the same version use
4212 // different values (e.g. Windows 11 24H2 uses "Current Record Version",
4213 // older Windows 11 and Windows 8/10 use "Update Revision", Windows 7 uses
4214 // "Update Signature" or sometimes "CurrentPatchLevel" for AMD CPUs.
4215 // Microcode version is represented by a 32-bit value but sometimes a 64-bit
4216 // value is surfaced instead with only half of it populated (e.g.
4217 // "Update Revision" on Windows 8, 10 and 11 pre-24H2). Since in these cases
4218 // the other half is zero, we pick the first non-zero 32-bit value we find
4219 // starting with the most "modern" registry value.
4220 LPCWSTR choices[] = {L"Current Record Version", L"Update Revision",
4221 L"Update Signature", L"CurrentPatchLevel"};
4222 for (const auto& oneChoice : choices) {
4223 DWORD keyValue[2] = {};
4224 DWORD len = sizeof(keyValue);
4225 DWORD vtype;
4226
4227 if (RegQueryValueExW(key, oneChoice, nullptr, &vtype,
4228 reinterpret_cast<LPBYTE>(keyValue),
4229 &len) == ERROR_SUCCESS) {
4230 if ((vtype == REG_BINARY) || (vtype == REG_DWORD)) {
4231 for (size_t i = 0; i < (len / sizeof(DWORD)); i++) {
4232 uint32_t value = keyValue[i];
4233
4234 if (value != 0) {
4235 return value;
4236 }
4237 }
4238 }
4239 }
4240 }
4241
4242 return 0;
4243}
4244#endif
4245
4246static void MaybeAddCPUMicrocodeCrashAnnotation() {
4247#ifdef XP_WIN
4248 // Add CPU microcode version to the crash report as "CPUMicrocodeVersion".
4249 // It feels like this code may belong in nsSystemInfo instead.
4250 HKEY key;
4251 static const WCHAR keyName[] =
4252 L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0";
4253
4254 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName, 0, KEY_QUERY_VALUE, &key) ==
4255 ERROR_SUCCESS) {
4256 uint32_t cpuMicrocodeVersion = FindCPUMicrocodeVersion(key);
4257
4258 if (cpuMicrocodeVersion != 0) {
4259 CrashReporter::RecordAnnotationNSCString(
4260 CrashReporter::Annotation::CPUMicrocodeVersion,
4261 nsPrintfCString("0x%" PRIx32"x", cpuMicrocodeVersion));
4262 }
4263 }
4264#endif
4265}
4266
4267#if defined(MOZ_BACKGROUNDTASKS1)
4268static void SetupConsoleForBackgroundTask(
4269 const nsCString& aBackgroundTaskName) {
4270 // We do not suppress output on Windows because:
4271 // 1. Background task subprocesses launched via LaunchApp() does not attach to
4272 // the console.
4273 // 2. Suppressing output intermittently causes failures on when running
4274 // multiple tasks (see bug 1831631)
4275# ifndef XP_WIN
4276 if (BackgroundTasks::IsNoOutputTaskName(aBackgroundTaskName) &&
4277 !CheckArg("attach-console") &&
4278 !EnvHasValue("MOZ_BACKGROUNDTASKS_IGNORE_NO_OUTPUT")) {
4279 // Suppress output, somewhat crudely. We need to suppress stderr as well
4280 // as stdout because assertions, of which there are many, write to stderr.
4281 [[maybe_unused]] FILE* r0 = freopen("/dev/null", "w", stdoutstdout);
4282 [[maybe_unused]] FILE* r1 = freopen("/dev/null", "w", stderrstderr);
4283 return;
4284 }
4285# endif
4286 printf_stderr("*** You are running in background task mode. ***\n");
4287}
4288#endif
4289
4290/*
4291 * XRE_mainInit - Initial setup and command line parameter processing.
4292 * Main() will exit early if either return value != 0 or if aExitFlag is
4293 * true.
4294 */
4295int XREMain::XRE_mainInit(bool* aExitFlag) {
4296 if (!aExitFlag) return 1;
1
Assuming 'aExitFlag' is non-null
2
Taking false branch
4297 *aExitFlag = false;
4298
4299 atexit(UnexpectedExit);
4300 auto expectedShutdown = mozilla::MakeScopeExit([&] { MozExpectedExit(); });
4301
4302 StartupTimeline::Record(StartupTimeline::MAIN);
4303
4304 // On Windows, to get working console arrangements so help/version/etc
4305 // print something, we need to initialize the native app support.
4306 nsresult rv = NS_CreateNativeAppSupport(getter_AddRefs(mNativeApp));
4307 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return 1;
3
Assuming the condition is true
4308
4309 // Handle --*version arguments early to avoid initializing full XPCOM.
4310 // Note: we *cannot* handle --help here, as it requires more components
4311 // to be initialized.
4312 if (CheckArg("v") || CheckArg("version")) {
4
Assuming the condition is false
5
Assuming the condition is false
6
Taking false branch
4313 DumpVersion();
4314 *aExitFlag = true;
4315 return 0;
4316 }
4317
4318 if (CheckArg("full-version")) {
7
Assuming the condition is false
8
Taking false branch
4319 DumpFullVersion();
4320 *aExitFlag = true;
4321 return 0;
4322 }
4323
4324 if (CheckForUserMismatch()) {
9
Taking false branch
4325 return 1;
4326 }
4327
4328#ifdef XP_MACOSX
4329 mozilla::MacAutoreleasePool pool;
4330
4331 DisableAppNap();
4332#endif
4333
4334#ifdef MOZ_BACKGROUNDTASKS1
4335 Maybe<nsCString> backgroundTask = Nothing();
4336 const char* backgroundTaskName = nullptr;
4337 if (ARG_FOUND ==
10
Assuming the condition is false
11
Taking false branch
4338 CheckArg("backgroundtask", &backgroundTaskName, CheckArgFlag::None)) {
4339 backgroundTask = Some(backgroundTaskName);
4340 SetupConsoleForBackgroundTask(backgroundTask.ref());
4341 }
4342
4343 BackgroundTasks::Init(backgroundTask);
4344#endif
4345
4346#ifndef ANDROID
4347 if (PR_GetEnv("MOZ_RUN_GTEST")
12
Assuming the condition is false
14
Taking false branch
4348# ifdef FUZZING
4349 || PR_GetEnv("FUZZER")
4350# endif
4351# ifdef MOZ_BACKGROUNDTASKS1
4352 || BackgroundTasks::IsBackgroundTaskMode()
13
Assuming the condition is false
4353# endif
4354 ) {
4355 // Enable headless mode and assert that it worked, since gfxPlatform
4356 // uses a static bool set after the first call to `IsHeadless`.
4357 // Note: Android gtests seem to require an Activity and fail to start
4358 // with headless mode enabled.
4359 PR_SetEnv("MOZ_HEADLESS=1");
4360 MOZ_ASSERT(gfxPlatform::IsHeadless())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(gfxPlatform::IsHeadless())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(gfxPlatform::IsHeadless())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("gfxPlatform::IsHeadless()"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 4360); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "gfxPlatform::IsHeadless()" ")"); do { MOZ_CrashSequence
(__null, 4360); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4361 }
4362#endif // ANDROID
4363
4364 if (auto* featureStr = PR_GetEnv("MOZ_CHAOSMODE")) {
15
Assuming 'featureStr' is null
16
Taking false branch
4365 ChaosFeature feature = ChaosFeature::Any;
4366 long featureInt = strtol(featureStr, nullptr, 16);
4367 if (featureInt) {
4368 // NOTE: MOZ_CHAOSMODE=0 or a non-hex value maps to Any feature.
4369 feature = static_cast<ChaosFeature>(featureInt);
4370 }
4371 ChaosMode::SetChaosFeature(feature);
4372 ChaosMode::enterChaosMode();
4373 MOZ_ASSERT(ChaosMode::isActive(ChaosFeature::Any))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ChaosMode::isActive(ChaosFeature::Any))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(ChaosMode::isActive(ChaosFeature::Any)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("ChaosMode::isActive(ChaosFeature::Any)"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 4373); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "ChaosMode::isActive(ChaosFeature::Any)" ")"
); do { MOZ_CrashSequence(__null, 4373); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4374 }
4375
4376 if (CheckArgExists("fxr")) {
17
Assuming the condition is false
18
Taking false branch
4377 gFxREmbedded = true;
4378 }
4379
4380 if (ChaosMode::isActive(ChaosFeature::Any)) {
4381 printf_stderr(
4382 "*** You are running in chaos test mode. See ChaosMode.h. ***\n");
4383 }
4384
4385 if (CheckArg("headless") || CheckArgExists("screenshot")) {
19
Assuming the condition is true
4386 PR_SetEnv("MOZ_HEADLESS=1");
4387 }
4388
4389 if (gfxPlatform::IsHeadless()) {
20
Assuming the condition is false
21
Taking false branch
4390#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK1) || defined(XP_MACOSX)
4391 printf_stderr("*** You are running in headless mode.\n");
4392#else
4393 Output(
4394 true,
4395 "Error: headless mode is not currently supported on this platform.\n");
4396 return 1;
4397#endif
4398
4399#ifdef XP_MACOSX
4400 // To avoid taking focus when running in headless mode immediately
4401 // transition Firefox to a background application.
4402 ProcessSerialNumber psn = {0, kCurrentProcess};
4403 OSStatus transformStatus =
4404 TransformProcessType(&psn, kProcessTransformToBackgroundApplication);
4405 if (transformStatus != noErr) {
4406 NS_ERROR("Failed to make process a background application.")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Failed to make process a background application."
, "Error", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
4406); MOZ_PretendNoReturn(); } while (0)
;
4407 return 1;
4408 }
4409#endif
4410 }
4411
4412 gKioskMode = CheckArg("kiosk", nullptr, CheckArgFlag::None);
4413 const char* kioskMonitorNumber = nullptr;
4414 if (CheckArg("kiosk-monitor", &kioskMonitorNumber, CheckArgFlag::None)) {
22
Assuming the condition is false
23
Taking false branch
4415 gKioskMode = true;
4416 gKioskMonitor = atoi(kioskMonitorNumber);
4417 }
4418
4419#if defined(NIGHTLY_BUILD1)
4420 if (XRE_IsParentProcess()) {
24
Taking false branch
4421 gAllowContentAnalysisArgPresent =
4422 CheckArg("allow-content-analysis", nullptr, CheckArgFlag::None) ==
4423 ARG_FOUND;
4424 }
4425#endif
4426
4427 ArgResult ar;
4428
4429#ifdef DEBUG1
4430 if (PR_GetEnv("XRE_MAIN_BREAK")) NS_BREAK()do { NS_DebugBreak(NS_DEBUG_BREAK, nullptr, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 4430); MOZ_PretendNoReturn(); } while (0)
;
25
Assuming the condition is false
26
Taking false branch
4431#endif
4432
4433 mozilla::startup::IncreaseDescriptorLimits();
4434
4435 SetupErrorHandling(gArgv[0]);
4436
4437#ifdef CAIRO_HAS_DWRITE_FONT
4438 {
4439 // Bug 602792 - when DWriteCreateFactory is called the dwrite client dll
4440 // starts the FntCache service if it isn't already running (it's set
4441 // to manual startup by default in Windows 7 RTM). Subsequent DirectWrite
4442 // calls cause the IDWriteFactory object to communicate with the FntCache
4443 // service with a timeout; if there's no response after the timeout, the
4444 // DirectWrite client library will assume the service isn't around and do
4445 // manual font file I/O on _all_ system fonts. To avoid this, load the
4446 // dwrite library and create a factory as early as possible so that the
4447 // FntCache service is ready by the time it's needed.
4448
4449 CreateThread(nullptr, 0, &InitDwriteBG, nullptr, 0, nullptr);
4450 }
4451#endif
4452
4453#ifdef XP_UNIX1
4454 const char* home = PR_GetEnv("HOME");
4455 if (!home || !*home) {
27
Assuming 'home' is non-null
28
Assuming the condition is false
29
Taking false branch
4456 struct passwd* pw = getpwuid(geteuid());
4457 if (!pw || !pw->pw_dir) {
4458 Output(true, "Could not determine HOME directory");
4459 return 1;
4460 }
4461 SaveWordToEnv("HOME", nsDependentCString(pw->pw_dir));
4462 }
4463#endif
4464
4465#ifdef MOZ_ACCESSIBILITY_ATK1
4466 // Suppress atk-bridge init at startup, until mozilla accessibility is
4467 // initialized. This works after gnome 2.24.2.
4468 SaveToEnv("NO_AT_BRIDGE=1");
30
Calling 'SaveToEnv'
4469#endif
4470
4471 // Check for application.ini overrides
4472 const char* override = nullptr;
4473 ar = CheckArg("override", &override);
4474 if (ar == ARG_BAD) {
4475 Output(true, "Incorrect number of arguments passed to --override");
4476 return 1;
4477 }
4478 if (ar == ARG_FOUND) {
4479 nsCOMPtr<nsIFile> overrideLF;
4480 rv = XRE_GetFileFromPath(override, getter_AddRefs(overrideLF));
4481 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4482 Output(true, "Error: unrecognized override.ini path.\n");
4483 return 1;
4484 }
4485
4486 rv = XRE_ParseAppData(overrideLF, *mAppData);
4487 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4488 Output(true, "Couldn't read override.ini");
4489 return 1;
4490 }
4491 }
4492
4493 // Check sanity and correctness of app data.
4494
4495 if (!mAppData->name) {
4496 Output(true, "Error: App:Name not specified in application.ini\n");
4497 return 1;
4498 }
4499 if (!mAppData->buildID) {
4500 Output(true, "Error: App:BuildID not specified in application.ini\n");
4501 return 1;
4502 }
4503
4504 // XXX Originally ScopedLogging was here? Now it's in XRE_main above
4505 // XRE_mainInit.
4506
4507 if (!mAppData->minVersion) {
4508 Output(true, "Error: Gecko:MinVersion not specified in application.ini\n");
4509 return 1;
4510 }
4511
4512 if (!mAppData->maxVersion) {
4513 // If no maxVersion is specified, we assume the app is only compatible
4514 // with the initial preview release. Do not increment this number ever!
4515 mAppData->maxVersion = "1.*";
4516 }
4517
4518 if (mozilla::Version(mAppData->minVersion) > gToolkitVersion ||
4519 mozilla::Version(mAppData->maxVersion) < gToolkitVersion) {
4520 Output(true,
4521 "Error: Platform version '%s' is not compatible with\n"
4522 "minVersion >= %s\nmaxVersion <= %s\n"
4523 "Maybe try to reinstall " MOZ_APP_DISPLAYNAME"Nightly" "?\n",
4524 (const char*)gToolkitVersion, (const char*)mAppData->minVersion,
4525 (const char*)mAppData->maxVersion);
4526 return 1;
4527 }
4528
4529 rv = mDirProvider.Initialize(mAppData->directory, mAppData->xreDirectory);
4530 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return 1;
4531
4532 if (EnvHasValue("MOZ_CRASHREPORTER")) {
4533 mAppData->flags |= NS_XRE_ENABLE_CRASH_REPORTER(1 << 3);
4534 }
4535
4536#ifdef MOZ_THUNDERBIRD
4537 // Set an explicit application name for Thunderbird.
4538 // We do NOT set one for `firefox`.
4539 // FOG uses a default one,
4540 // background tasks overwrite it using `initializeFOG`.
4541 FOG::SetApplicationID("thunderbird.desktop"_ns);
4542#endif // MOZ_THUNDERBIRD
4543
4544 nsCOMPtr<nsIFile> xreBinDirectory;
4545 xreBinDirectory = mDirProvider.GetGREBinDir();
4546
4547 // Unconditionally set the ServerURL exception before we launch the crash
4548 // helper or set the exception handler. This guarantees that the annotation
4549 // will be populated when we need it.
4550 if (mAppData->crashReporterURL) {
4551 CrashReporter::SetServerURL(nsDependentCString(mAppData->crashReporterURL));
4552 }
4553
4554 if ((mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER(1 << 3)) &&
4555 NS_FAILED(CrashReporter::OOPInit(xreBinDirectory))((bool)(__builtin_expect(!!(NS_FAILED_impl(CrashReporter::OOPInit
(xreBinDirectory))), 0)))
) {
4556 NS_WARNING("Could not launch the crash helper")NS_DebugBreak(NS_DEBUG_WARNING, "Could not launch the crash helper"
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
4556)
;
4557 }
4558
4559 if ((mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER(1 << 3)) &&
4560 NS_SUCCEEDED(CrashReporter::SetExceptionHandler(xreBinDirectory))((bool)(__builtin_expect(!!(!NS_FAILED_impl(CrashReporter::SetExceptionHandler
(xreBinDirectory))), 1)))
) {
4561 nsCOMPtr<nsIFile> file;
4562 rv = nsXREDirProvider::GetUserAppDataDirectory(getter_AddRefs(file));
4563 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4564 CrashReporter::SetUserAppDataDirectory(file);
4565 }
4566
4567 // We overwrite this once we finish starting up.
4568 CrashReporter::RecordAnnotationBool(CrashReporter::Annotation::StartupCrash,
4569 true);
4570
4571 // pass some basic info from the app data
4572 if (mAppData->vendor) {
4573 CrashReporter::RecordAnnotationCString(CrashReporter::Annotation::Vendor,
4574 mAppData->vendor);
4575 }
4576 if (mAppData->name) {
4577 CrashReporter::RecordAnnotationCString(
4578 CrashReporter::Annotation::ProductName, mAppData->name);
4579 }
4580 if (mAppData->ID) {
4581 CrashReporter::RecordAnnotationCString(
4582 CrashReporter::Annotation::ProductID, mAppData->ID);
4583 }
4584 if (mAppData->version) {
4585 CrashReporter::RecordAnnotationCString(CrashReporter::Annotation::Version,
4586 mAppData->version);
4587 }
4588 if (mAppData->buildID) {
4589 CrashReporter::RecordAnnotationCString(CrashReporter::Annotation::BuildID,
4590 mAppData->buildID);
4591 }
4592
4593 nsDependentCString releaseChannel(MOZ_STRINGIFY(MOZ_UPDATE_CHANNEL)"default");
4594 CrashReporter::RecordAnnotationNSCString(
4595 CrashReporter::Annotation::ReleaseChannel, releaseChannel);
4596
4597 CrashReporter::RecordPlatformAnnotations();
4598
4599#ifdef XP_WIN
4600 nsAutoString appInitDLLs;
4601 if (widget::WinUtils::GetAppInitDLLs(appInitDLLs)) {
4602 CrashReporter::RecordAnnotationNSString(
4603 CrashReporter::Annotation::AppInitDLLs, appInitDLLs);
4604 }
4605
4606 nsString packageFamilyName = widget::WinUtils::GetPackageFamilyName();
4607 if (StringBeginsWith(packageFamilyName, u"Mozilla."_ns) ||
4608 StringBeginsWith(packageFamilyName, u"MozillaCorporation."_ns)) {
4609 CrashReporter::RecordAnnotationNSCString(
4610 CrashReporter::Annotation::WindowsPackageFamilyName,
4611 NS_ConvertUTF16toUTF8(packageFamilyName));
4612 }
4613#endif
4614
4615 bool isBackgroundTaskMode = false;
4616#ifdef MOZ_BACKGROUNDTASKS1
4617 Maybe<nsCString> backgroundTasks = BackgroundTasks::GetBackgroundTasks();
4618 if (backgroundTasks.isSome()) {
4619 isBackgroundTaskMode = true;
4620 CrashReporter::RecordAnnotationNSCString(
4621 CrashReporter::Annotation::BackgroundTaskName, backgroundTasks.ref());
4622 }
4623#endif
4624 CrashReporter::RecordAnnotationBool(
4625 CrashReporter::Annotation::BackgroundTaskMode, isBackgroundTaskMode);
4626
4627 CrashReporter::RecordAnnotationBool(CrashReporter::Annotation::HeadlessMode,
4628 gfxPlatform::IsHeadless());
4629
4630 CrashReporter::SetRestartArgs(gArgc, gArgv);
4631
4632 // annotate other data (user id etc)
4633 nsCOMPtr<nsIFile> userAppDataDir;
4634 if (NS_SUCCEEDED(mDirProvider.GetUserAppDataDirectory(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mDirProvider.GetUserAppDataDirectory
( getter_AddRefs(userAppDataDir)))), 1)))
4635 getter_AddRefs(userAppDataDir)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mDirProvider.GetUserAppDataDirectory
( getter_AddRefs(userAppDataDir)))), 1)))
) {
4636 CrashReporter::SetupExtraData(userAppDataDir, mAppData->xreDirectory);
4637 }
4638 } else {
4639 // We might have registered a runtime exception module very early in process
4640 // startup to catch early crashes. This is before we have access to ini file
4641 // data, so unregister here if it turns out the crash reporter is disabled.
4642 CrashReporter::UnregisterRuntimeExceptionModule();
4643 }
4644
4645#if defined(MOZ_SANDBOX1) && defined(XP_WIN)
4646 if (mAppData->sandboxBrokerServices) {
4647 nsAutoString binDirPath;
4648 MOZ_ALWAYS_SUCCEEDS(xreBinDirectory->GetPath(binDirPath))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(xreBinDirectory->GetPath(binDirPath))), 1)))), 1))) { } else
{ do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(xreBinDirectory->GetPath(binDirPath))"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 4648); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(xreBinDirectory->GetPath(binDirPath))"
")"); do { MOZ_CrashSequence(__null, 4648); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
4649 SandboxBroker::Initialize(mAppData->sandboxBrokerServices, binDirPath);
4650 } else {
4651# if defined(MOZ_SANDBOX1)
4652 // If we're sandboxing content and we fail to initialize, then crashing here
4653 // seems like the sensible option.
4654 if (BrowserTabsRemoteAutostart()) {
4655 MOZ_CRASH("Failed to initialize broker services, can't continue.")do { do { } while (false); MOZ_ReportCrash("" "Failed to initialize broker services, can't continue."
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 4655); AnnotateMozCrashReason
("MOZ_CRASH(" "Failed to initialize broker services, can't continue."
")"); do { MOZ_CrashSequence(__null, 4655); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
4656 }
4657# endif
4658 // Otherwise just warn for the moment, as most things will work.
4659 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Failed to initialize broker services, sandboxed processes will "
"fail to start.", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 4661)
4660 "Failed to initialize broker services, sandboxed processes will "NS_DebugBreak(NS_DEBUG_WARNING, "Failed to initialize broker services, sandboxed processes will "
"fail to start.", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 4661)
4661 "fail to start.")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to initialize broker services, sandboxed processes will "
"fail to start.", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 4661)
;
4662 }
4663#endif
4664
4665#ifdef XP_MACOSX
4666 // Set up ability to respond to system (Apple) events. This must occur before
4667 // ProcessUpdates to ensure that links clicked in external applications aren't
4668 // lost when updates are pending.
4669 SetupMacApplicationDelegate(&gRestartedByOS);
4670
4671 if (EnvHasValue("MOZ_LAUNCHED_CHILD")) {
4672 // Initialize the shared NSApplication early on relaunch so the dock
4673 // tile for the child process gets registered before the original
4674 // process exits. `[NSApplication sharedApplication]` calls
4675 // `_NSDoOneTimeDockRegistration` internally, which is enough.
4676 EnsureUseCocoaDockAPI();
4677 }
4678
4679 if (CheckArg("foreground")) {
4680 // The original process communicates that it was in the foreground by
4681 // adding this argument. This new process, which is taking over for
4682 // the old one, should make itself the active application.
4683 ProcessSerialNumber psn;
4684 if (::GetCurrentProcess(&psn) == noErr) {
4685 ::SetFrontProcess(&psn);
4686 }
4687 }
4688#endif
4689
4690 SaveToEnv("MOZ_LAUNCHED_CHILD=");
4691
4692 // On Windows, the -os-restarted command line switch lets us know when we are
4693 // restarted via RegisterApplicationRestart. May be used for other OSes later.
4694 if (CheckArg("os-restarted", nullptr, CheckArgFlag::RemoveArg) == ARG_FOUND) {
4695 gRestartedByOS = true;
4696 }
4697
4698 gRestartArgc = gArgc;
4699 gRestartArgv =
4700 (char**)malloc(sizeof(char*) * (gArgc + 1 + (override ? 2 : 0)));
4701 if (!gRestartArgv) {
4702 return 1;
4703 }
4704
4705 int i;
4706 for (i = 0; i < gArgc; ++i) {
4707 gRestartArgv[i] = gArgv[i];
4708 }
4709
4710 // Add the -override argument back (it is removed automatically be CheckArg)
4711 // if there is one
4712 if (override) {
4713 gRestartArgv[gRestartArgc++] = const_cast<char*>("-override");
4714 gRestartArgv[gRestartArgc++] = const_cast<char*>(override);
4715 }
4716
4717 gRestartArgv[gRestartArgc] = nullptr;
4718
4719 Maybe<bool> safeModeRequested = IsSafeModeRequested(gArgc, gArgv);
4720 if (!safeModeRequested) {
4721 return 1;
4722 }
4723#ifdef MOZ_BACKGROUNDTASKS1
4724 if (BackgroundTasks::IsBackgroundTaskMode()) {
4725 safeModeRequested = Some(false);
4726
4727 // Remove the --backgroundtask arg now that it has been saved in
4728 // gRestartArgv.
4729 const char* tmpBackgroundTaskName = nullptr;
4730 (void)CheckArg("backgroundtask", &tmpBackgroundTaskName,
4731 CheckArgFlag::RemoveArg);
4732 }
4733#endif
4734
4735 gSafeMode = safeModeRequested.value();
4736
4737 MaybeAddCPUMicrocodeCrashAnnotation();
4738 CrashReporter::RegisterAnnotationBool(CrashReporter::Annotation::SafeMode,
4739 &gSafeMode);
4740
4741 // Strip the now unsupported no-remote command line argument.
4742 CheckArg("no-remote");
4743
4744#if defined(MOZ_HAS_REMOTE1)
4745 // Handle the --new-instance command line arguments.
4746 ar = CheckArg("new-instance");
4747 if (ar == ARG_FOUND || EnvHasValue("MOZ_NEW_INSTANCE")) {
4748 mDisableRemoteClient = true;
4749 }
4750#else
4751 // These arguments do nothing in platforms with no remoting support but we
4752 // should remove them from the command line anyway.
4753 CheckArg("new-instance");
4754#endif
4755
4756#ifndef XP_WIN
4757 // This command line argument is only implemented on Windows. It should be
4758 // removed from the command line if present on other platforms.
4759 CheckArg("wait-for-browser");
4760#endif
4761
4762 ar = CheckArg("offline");
4763 if (ar || EnvHasValue("XRE_START_OFFLINE")) {
4764 mStartOffline = true;
4765 }
4766
4767 const char* origin = nullptr;
4768 if (!PR_GetEnv("MOZ_FORCE_QUIC_ON") &&
4769 ARG_FOUND == CheckArg("origin-to-force-quic-on", &origin,
4770 CheckArgFlag::RemoveArg)) {
4771 mOriginToForceQUIC.Assign(origin);
4772 }
4773
4774 // Handle --help command line argument.
4775 // It should return rather quickly, so we deal with it here.
4776 // Note: we *cannot* handle the argument as early as --*version because it
4777 // requires ScopedXPCOMStartup and other components be registered.
4778 if (CheckArg("h") || CheckArg("help") || CheckArg("?")) {
4779 DumpHelp();
4780 *aExitFlag = true;
4781 return 0;
4782 }
4783
4784#ifdef MOZ_ENABLE_DBUS1
4785 const char* dbusServiceLauncher = nullptr;
4786 ar = CheckArg("dbus-service", &dbusServiceLauncher, CheckArgFlag::None);
4787 if (ar == ARG_BAD) {
4788 Output(true, "Missing launcher param for --dbus-service\n");
4789 return 1;
4790 }
4791 if (ar == ARG_FOUND) {
4792 UniquePtr<DBusService> dbusService =
4793 MakeUnique<DBusService>(dbusServiceLauncher);
4794 if (dbusService->Init()) {
4795 dbusService->Run();
4796 }
4797 *aExitFlag = true;
4798 return 0;
4799 }
4800
4801# ifdef MOZ_WIDGET_GTK1
4802 if (XRE_IsParentProcess()) {
4803 widget::RegisterHostApp();
4804 }
4805# endif
4806#endif
4807
4808 rv = XRE_InitCommandLine(gArgc, gArgv);
4809 NS_ENSURE_SUCCESS(rv, 1)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", "1", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 4809); return 1; } } while (false)
;
4810
4811 return 0;
4812}
4813
4814#if defined(XP_LINUX1) && !defined(ANDROID)
4815
4816static void AnnotateLSBRelease(void*) {
4817 nsCString dist, desc, release, codename;
4818 if (widget::lsb::GetLSBRelease(dist, desc, release, codename)) {
4819 CrashReporter::AppendAppNotesToCrashReport(desc);
4820 }
4821}
4822
4823#endif // defined(XP_LINUX) && !defined(ANDROID)
4824
4825#ifdef XP_WIN
4826static void ReadAheadSystemDll(const wchar_t* dllName) {
4827 wchar_t dllPath[MAX_PATH];
4828 if (ConstructSystem32Path(dllName, dllPath, MAX_PATH)) {
4829 ReadAheadLib(dllPath);
4830 }
4831}
4832
4833static void ReadAheadPackagedDll(const wchar_t* dllName,
4834 const wchar_t* aGREDir) {
4835 wchar_t dllPath[MAX_PATH];
4836 swprintf(dllPath, MAX_PATH, L"%s\\%s", aGREDir, dllName);
4837 ReadAheadLib(dllPath);
4838}
4839
4840static void ReadAheadDlls(const wchar_t* greDir) {
4841 // In Bug 1628903, we investigated which DLLs we should prefetch in
4842 // order to reduce disk I/O and improve startup on Windows machines.
4843 // Our ultimate goal is to measure the impact of these improvements on
4844 // retention (see Bug 1640087). Before we place this within a pref,
4845 // we should ensure this feature only ships to the nightly channel
4846 // and monitor results from that subset.
4847 if (greDir) {
4848 // Prefetch the DLLs shipped with firefox
4849 ReadAheadPackagedDll(L"libegl.dll", greDir);
4850 ReadAheadPackagedDll(L"libGLESv2.dll", greDir);
4851 ReadAheadPackagedDll(L"freebl3.dll", greDir);
4852 ReadAheadPackagedDll(L"softokn3.dll", greDir);
4853
4854 // Prefetch the system DLLs
4855 ReadAheadSystemDll(L"DWrite.dll");
4856 ReadAheadSystemDll(L"D3DCompiler_47.dll");
4857 } else {
4858 // Load DataExchange.dll and twinapi.appcore.dll for
4859 // nsWindow::EnableDragDrop
4860 ReadAheadSystemDll(L"DataExchange.dll");
4861 ReadAheadSystemDll(L"twinapi.appcore.dll");
4862
4863 // Load twinapi.dll for WindowsUIUtils::UpdateTabletModeState
4864 ReadAheadSystemDll(L"twinapi.dll");
4865
4866 // Load explorerframe.dll for WinTaskbar::Initialize
4867 ReadAheadSystemDll(L"ExplorerFrame.dll");
4868
4869 // Load WinTypes.dll for nsOSHelperAppService::GetApplicationDescription
4870 ReadAheadSystemDll(L"WinTypes.dll");
4871 }
4872}
4873#endif
4874
4875#if defined(MOZ_UPDATER1) && !defined(MOZ_WIDGET_ANDROID)
4876enum struct ShouldNotProcessUpdatesReason {
4877 DevToolsLaunching,
4878 NotAnUpdatingTask,
4879 OtherInstanceRunning,
4880 FirstStartup,
4881 DisabledByEnvironment
4882};
4883
4884const char* ShouldNotProcessUpdatesReasonAsString(
4885 ShouldNotProcessUpdatesReason aReason) {
4886 switch (aReason) {
4887 case ShouldNotProcessUpdatesReason::DevToolsLaunching:
4888 return "DevToolsLaunching";
4889 case ShouldNotProcessUpdatesReason::NotAnUpdatingTask:
4890 return "NotAnUpdatingTask";
4891 case ShouldNotProcessUpdatesReason::OtherInstanceRunning:
4892 return "OtherInstanceRunning";
4893 case ShouldNotProcessUpdatesReason::DisabledByEnvironment:
4894 return "DisabledByEnvironment";
4895 default:
4896 MOZ_CRASH("impossible value for ShouldNotProcessUpdatesReason")do { do { } while (false); MOZ_ReportCrash("" "impossible value for ShouldNotProcessUpdatesReason"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 4896); AnnotateMozCrashReason
("MOZ_CRASH(" "impossible value for ShouldNotProcessUpdatesReason"
")"); do { MOZ_CrashSequence(__null, 4896); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
4897 }
4898}
4899
4900Maybe<ShouldNotProcessUpdatesReason> ShouldNotProcessUpdates(
4901 nsXREDirProvider& aDirProvider) {
4902 // Don't process updates when launched from the installer.
4903 // It's possible for a stale update to be present in the case of a paveover;
4904 // ignore it and leave the update service to discard it.
4905 if (ARG_FOUND == CheckArgExists("first-startup")) {
4906 NS_WARNING("ShouldNotProcessUpdates(): FirstStartup")NS_DebugBreak(NS_DEBUG_WARNING, "ShouldNotProcessUpdates(): FirstStartup"
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
4906)
;
4907 return Some(ShouldNotProcessUpdatesReason::FirstStartup);
4908 }
4909
4910 // Bug 2055849: Don't process updates if MOZ_DISABLE_UPDATE_PROCESSING is set.
4911 // Set by default when using https://github.com/mozilla/firefox-devtools-mcp.
4912 if (EnvHasValue("MOZ_DISABLE_UPDATE_PROCESSING")) {
4913 NS_WARNING("ShouldNotProcessUpdates(): DisabledByEnvironment")NS_DebugBreak(NS_DEBUG_WARNING, "ShouldNotProcessUpdates(): DisabledByEnvironment"
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
4913)
;
4914 return Some(ShouldNotProcessUpdatesReason::DisabledByEnvironment);
4915 }
4916
4917 // Do not process updates if we're launching devtools, as evidenced by
4918 // "--chrome ..." with the browser toolbox chrome document URL.
4919
4920 // Keep this synchronized with the value of the same name in
4921 // devtools/client/framework/browser-toolbox/Launcher.sys.mjs. Or, for bonus
4922 // points, lift this value to nsIXulRuntime or similar, so that it can be
4923 // accessed in both locations. (The prefs service isn't available at this
4924 // point so the simplest manner of sharing the value is not available to us.)
4925 const char* BROWSER_TOOLBOX_WINDOW_URL =
4926 "chrome://devtools/content/framework/browser-toolbox/window.html";
4927
4928 const char* chromeParam = nullptr;
4929 if (ARG_FOUND == CheckArg("chrome", &chromeParam, CheckArgFlag::None)) {
4930 if (!chromeParam || !strcmp(BROWSER_TOOLBOX_WINDOW_URL, chromeParam)) {
4931 NS_WARNING("ShouldNotProcessUpdates(): DevToolsLaunching")NS_DebugBreak(NS_DEBUG_WARNING, "ShouldNotProcessUpdates(): DevToolsLaunching"
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
4931)
;
4932 return Some(ShouldNotProcessUpdatesReason::DevToolsLaunching);
4933 }
4934 }
4935
4936# ifdef MOZ_BACKGROUNDTASKS1
4937 // Do not process updates if we're running a background task mode and another
4938 // instance is already running. This avoids periodic maintenance updating
4939 // underneath a browsing session.
4940 Maybe<nsCString> backgroundTasks = BackgroundTasks::GetBackgroundTasks();
4941 if (backgroundTasks.isSome()) {
4942 // Only process updates for specific tasks: at this time, the
4943 // `backgroundupdate` task and the test-only `shouldprocessupdates` task.
4944 //
4945 // Background tasks can be sparked by Firefox instances that are shutting
4946 // down, which can cause races between the task startup trying to update and
4947 // Firefox trying to invoke the updater. This happened when converting
4948 // `pingsender` to a background task, since it is launched to send pings at
4949 // shutdown: Bug 1736373.
4950 //
4951 // We'd prefer to have this be a property of the task definition sibling to
4952 // `backgroundTaskTimeoutSec`, but when we reach this code we're well before
4953 // we can load the task JSM.
4954 if (!BackgroundTasks::IsUpdatingTaskName(backgroundTasks.ref())) {
4955 NS_WARNING("ShouldNotProcessUpdates(): NotAnUpdatingTask")NS_DebugBreak(NS_DEBUG_WARNING, "ShouldNotProcessUpdates(): NotAnUpdatingTask"
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
4955)
;
4956 return Some(ShouldNotProcessUpdatesReason::NotAnUpdatingTask);
4957 }
4958
4959 // At this point we have a dir provider but no XPCOM directory service. We
4960 // launch the update sync manager using that information so that it doesn't
4961 // need to ask for (and fail to find) the directory service.
4962 nsCOMPtr<nsIFile> anAppFile;
4963 bool persistent;
4964 nsresult rv = aDirProvider.GetFile(XRE_EXECUTABLE_FILE"XREExeF", &persistent,
4965 getter_AddRefs(anAppFile));
4966 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !anAppFile) {
4967 // Strange, but not a reason to skip processing updates.
4968 return Nothing();
4969 }
4970
4971 auto updateSyncManager = new nsUpdateSyncManager(anAppFile);
4972
4973 bool otherInstance = false;
4974 updateSyncManager->IsOtherInstanceRunning(&otherInstance);
4975 if (otherInstance) {
4976 NS_WARNING("ShouldNotProcessUpdates(): OtherInstanceRunning")NS_DebugBreak(NS_DEBUG_WARNING, "ShouldNotProcessUpdates(): OtherInstanceRunning"
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
4976)
;
4977 return Some(ShouldNotProcessUpdatesReason::OtherInstanceRunning);
4978 }
4979 }
4980# endif
4981
4982 return Nothing();
4983}
4984#endif
4985
4986namespace mozilla::startup {
4987Result<nsCOMPtr<nsIFile>, nsresult> GetIncompleteStartupFile(nsIFile* aProfLD) {
4988 nsCOMPtr<nsIFile> crashFile;
4989 MOZ_TRY(aProfLD->Clone(getter_AddRefs(crashFile)))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(aProfLD->Clone(getter_AddRefs(crashFile))); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
4990 MOZ_TRY(crashFile->Append(FILE_STARTUP_INCOMPLETE))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(crashFile->Append(u".startup-incomplete"_ns)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
4991 return std::move(crashFile);
4992}
4993} // namespace mozilla::startup
4994
4995// Check whether the last startup attempt resulted in a crash or hang.
4996// This is distinct from the definition of a startup crash from
4997// nsAppStartup::TrackStartupCrashBegin.
4998bool XREMain::CheckLastStartupWasCrash() {
4999 Result<nsCOMPtr<nsIFile>, nsresult> crashFile =
5000 GetIncompleteStartupFile(mProfLD);
5001 if (crashFile.isErr()) {
5002 return true;
5003 }
5004
5005 // Attempt to create the incomplete startup canary file. If the file already
5006 // exists, this fails, and we know the last startup was a crash. If it
5007 // doesn't already exist, it is created, and will be removed at the end of
5008 // the startup crash detection window.
5009 AutoFDClose fd;
5010 (void)crashFile.inspect()->OpenNSPRFileDesc(
5011 PR_WRONLY0x02 | PR_CREATE_FILE0x08 | PR_EXCL0x80, 0666, getter_Transfers(fd));
5012 return !fd;
5013}
5014
5015/*
5016 * XRE_mainStartup - Initializes the profile and various other services.
5017 * Main() will exit early if either return value != 0 or if aExitFlag is
5018 * true.
5019 */
5020int XREMain::XRE_mainStartup(bool* aExitFlag) {
5021 nsresult rv;
5022
5023 if (!aExitFlag) return 1;
5024 *aExitFlag = false;
5025
5026#ifdef XP_MACOSX
5027 mozilla::MacAutoreleasePool pool;
5028#endif
5029
5030 // Enable Telemetry IO Reporting on DEBUG, nightly and local builds,
5031 // but disable it on FUZZING builds and for ANDROID.
5032#ifndef FUZZING
5033# ifndef ANDROID
5034# ifdef DEBUG1
5035 mozilla::Telemetry::InitIOReporting(gAppData->xreDirectory);
5036# else
5037 {
5038 const char* releaseChannel = MOZ_STRINGIFY(MOZ_UPDATE_CHANNEL)"default";
5039 if (strcmp(releaseChannel, "nightly") == 0 ||
5040 strcmp(releaseChannel, "default") == 0) {
5041 mozilla::Telemetry::InitIOReporting(gAppData->xreDirectory);
5042 }
5043 }
5044# endif /* DEBUG */
5045# endif /* ANDROID */
5046#endif /* FUZZING */
5047
5048#if defined(XP_WIN)
5049 // Enable the HeapEnableTerminationOnCorruption exploit mitigation. We ignore
5050 // the return code because it always returns success, although it has no
5051 // effect on Windows older than XP SP3.
5052 HeapSetInformation(NULL__null, HeapEnableTerminationOnCorruption, NULL__null, 0);
5053#endif /* XP_WIN */
5054
5055#ifdef MOZ_WIDGET_GTK1
5056 // Stash startup token in owned memory because gtk_init will clear
5057 // DESKTOP_STARTUP_ID it.
5058 if (const char* v = PR_GetEnv("DESKTOP_STARTUP_ID")) {
5059 mDesktopStartupID.Assign(v);
5060 }
5061 if (const char* v = PR_GetEnv("XDG_ACTIVATION_TOKEN")) {
5062 mXDGActivationToken.Assign(v);
5063 }
5064#endif
5065
5066#if defined(XP_WIN)
5067 {
5068 // Save the shortcut path before lpTitle is replaced by an AUMID,
5069 // such as by WinTaskbar
5070 STARTUPINFOW si;
5071 GetStartupInfoW(&si);
5072 if (si.dwFlags & STARTF_TITLEISAPPID) {
5073 NS_WARNING("AUMID was already set, shortcut may have been lost.")NS_DebugBreak(NS_DEBUG_WARNING, "AUMID was already set, shortcut may have been lost."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
5073)
;
5074 } else if ((si.dwFlags & STARTF_TITLEISLINKNAME) && si.lpTitle) {
5075 gProcessStartupShortcut.Assign(si.lpTitle);
5076 }
5077 }
5078#endif /* XP_WIN */
5079
5080#if defined(MOZ_WIDGET_GTK1)
5081 // setup for private colormap. Ideally we'd like to do this
5082 // in nsAppShell::Create, but we need to get in before gtk
5083 // has been initialized to make sure everything is running
5084 // consistently.
5085
5086 // Set program name to the one defined in application.ini.
5087 g_set_prgname(gAppData->remotingName);
5088
5089 // Initialize GTK here for splash.
5090
5091# if defined(MOZ_X111)
5092 // Disable XInput2 multidevice support due to focus bugginess.
5093 // See bugs 1182700, 1170342.
5094 // gdk_disable_multidevice() affects Gdk X11 backend only,
5095 // the multidevice support is always enabled on Wayland backend.
5096 int32_t useXI2 = 0;
5097 if (const char* useXI2Env = PR_GetEnv("MOZ_USE_XINPUT2")) {
5098 useXI2 = (*useXI2Env != '0');
5099 } else {
5100 // Steam Deck needs multidevice support for touchscreen
5101 if (const char* currentDesktop = PR_GetEnv("XDG_CURRENT_DESKTOP")) {
5102 useXI2 |= (nsDependentCString(currentDesktop) == "gamescope"_ns);
5103 }
5104# ifdef EARLY_BETA_OR_EARLIER1
5105 // We tried 3.24.0+ but had problems, let's retry with newer versions. See
5106 // bug 1660212.
5107 useXI2 |= !gtk_check_version(3, 24, 49);
5108# endif
5109 }
5110 if (!useXI2) {
5111 gdk_disable_multidevice();
5112 }
5113# endif /* MOZ_X11 */
5114
5115 // Open the display ourselves instead of using gtk_init, so that we can
5116 // close it without fear that one day gtk might clean up the display it
5117 // opens.
5118 if (!gtk_parse_args(&gArgc, &gArgv)) return 1;
5119#endif /* MOZ_WIDGET_GTK */
5120
5121#ifdef FUZZING
5122 if (PR_GetEnv("FUZZER")) {
5123 *aExitFlag = true;
5124 return mozilla::fuzzerRunner->Run(&gArgc, &gArgv);
5125 }
5126#endif
5127
5128 if (PR_GetEnv("MOZ_RUN_GTEST")) {
5129 int result;
5130#ifdef XP_WIN
5131 UseParentConsole();
5132#endif
5133 // RunGTest will only be set if we're in xul-unit
5134 if (mozilla::RunGTest) {
5135 gIsGtest = true;
5136 result = mozilla::RunGTest(&gArgc, gArgv);
5137 gIsGtest = false;
5138 } else {
5139 result = 1;
5140 printf("TEST-UNEXPECTED-FAIL | gtest | Not compiled with enable-tests\n");
5141 }
5142 *aExitFlag = true;
5143 return result;
5144 }
5145
5146 bool isBackgroundTaskMode = false;
5147#ifdef MOZ_BACKGROUNDTASKS1
5148 isBackgroundTaskMode = BackgroundTasks::IsBackgroundTaskMode();
5149#endif
5150
5151#ifdef MOZ_HAS_REMOTE1
5152 if (gfxPlatform::IsHeadless()) {
5153 mDisableRemoteClient = true;
5154 }
5155#endif
5156
5157#ifdef MOZ_X111
5158 // Init X11 in thread-safe mode. Must be called prior to the first call to
5159 // XOpenDisplay (called inside gdk_display_open). This is a requirement for
5160 // off main tread compositing.
5161 if (!isBackgroundTaskMode && !gfxPlatform::IsHeadless()) {
5162 XInitThreads();
5163 }
5164#endif
5165#if defined(MOZ_WIDGET_GTK1)
5166 if (!isBackgroundTaskMode && !gfxPlatform::IsHeadless()) {
5167 const char* display_name = nullptr;
5168 bool saveDisplayArg = false;
5169
5170 // display_name is owned by gdk.
5171 display_name = gdk_get_display_arg_name();
5172 bool waylandEnabled = IsWaylandEnabled();
5173# ifdef MOZ_WAYLAND1
5174 if (!display_name) {
5175 auto* proxyEnv = getenv("MOZ_DISABLE_WAYLAND_PROXY");
5176 bool disableWaylandProxy = proxyEnv && *proxyEnv;
5177 if (!disableWaylandProxy && XRE_IsParentProcess() && waylandEnabled) {
5178 auto* proxyLog = getenv("WAYLAND_PROXY_LOG");
5179 WaylandProxy::SetVerbose(proxyLog && *proxyLog);
5180
5181# ifdef NIGHTLY_BUILD1
5182 bool captureProtocolErrors = true;
5183# else
5184 bool captureProtocolErrors = false;
5185# endif
5186 // MOZ_WAYLAND_PROTOCOL_ERROR_DETAILS=0 turns capture off on Nightly;
5187 // any other non-empty value turns it on elsewhere.
5188 if (auto* errorDetails = getenv("MOZ_WAYLAND_PROTOCOL_ERROR_DETAILS")) {
5189 captureProtocolErrors = *errorDetails && *errorDetails != '0';
5190 }
5191 WaylandProxy::SetCaptureProtocolErrors(captureProtocolErrors);
5192
5193 WaylandProxy::SetThreadStartCallback(
5194 [] { PROFILER_REGISTER_THREAD("WaylandProxy")do { char stackTop; profiler_register_thread("WaylandProxy", &
stackTop); } while (0)
; });
5195 WaylandProxy::SetThreadStopCallback(
5196 [] { PROFILER_UNREGISTER_THREAD()profiler_unregister_thread(); });
5197 WaylandProxy::SetCompositorUnavailableHandler(
5198 WlCompositorUnavailableHandler);
5199 WaylandProxy::SetCompositorSilentDisconnectHandler(
5200 WlCompositorSilentDisconnectHandler);
5201 WaylandProxy::AddState(WAYLAND_PROXY_ENABLED(1 << 0));
5202 gWaylandProxy = WaylandProxy::Create();
5203 if (gWaylandProxy) {
5204 if (!gWaylandProxy->RunThread()) {
5205 Output(true, "Failed to run Wayland proxy\n");
5206 }
5207 }
5208 } else {
5209 WaylandProxy::AddState(WAYLAND_PROXY_DISABLED(1 << 1));
5210 }
5211 }
5212# endif
5213
5214 // if --display argument is given make sure it's
5215 // also passed to ContentChild::Init() by MOZ_GDK_DISPLAY.
5216 if (display_name) {
5217 SaveWordToEnv("MOZ_GDK_DISPLAY", nsDependentCString(display_name));
5218 saveDisplayArg = true;
5219 }
5220
5221 // On Wayland disabled builds read X11 DISPLAY env exclusively
5222 // and don't care about different displays.
5223 if (!waylandEnabled && !display_name) {
5224 display_name = PR_GetEnv("DISPLAY");
5225 if (!display_name) {
5226 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
5227 "Error: no DISPLAY environment variable specified\n");
5228 return 1;
5229 }
5230 }
5231
5232 if (display_name) {
5233 GdkDisplay* disp = gdk_display_open(display_name);
5234 if (!disp) {
5235 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Error: cannot open display: %s\n", display_name);
5236 return 1;
5237 }
5238 if (saveDisplayArg) {
5239 if (GdkIsX11Display(disp)) {
5240 SaveWordToEnv("DISPLAY", nsDependentCString(display_name));
5241 } else if (GdkIsWaylandDisplay(disp)) {
5242 SaveWordToEnv("WAYLAND_DISPLAY", nsDependentCString(display_name));
5243 }
5244 }
5245 } else {
5246 gdk_display_manager_open_display(gdk_display_manager_get(), nullptr);
5247 }
5248# if defined(MOZ_WAYLAND1)
5249 // We want to use proxy for main connection only so
5250 // restore original Wayland display for next potential Wayland connections
5251 // from gfx probe code and so on.
5252 if (gWaylandProxy) {
5253 gWaylandProxy->RestoreWaylandDisplay();
5254 }
5255 if (waylandEnabled && PR_GetEnv("WAYLAND_DISPLAY") && GdkIsX11Display()) {
5256 // Gtk somehow switched to X11 display but we want Wayland.
5257 // It may happen if compositor response is missig or it's slow
5258 // or WAYLAND_DISPLAY is wrong. In such case throw warning but
5259 // run with X11.
5260 Output(true,
5261 "Error: Failed to open Wayland display, fallback to X11. "
5262 "WAYLAND_DISPLAY='%s' DISPLAY='%s'\n",
5263 PR_GetEnv("WAYLAND_DISPLAY"), PR_GetEnv("DISPLAY"));
5264
5265 // We need to unset WAYLAND_DISPLAY. Gfx probe code doesn't have fallback
5266 // to X11 and we'll end with Browser running SW rendering only then.
5267 g_unsetenv("WAYLAND_DISPLAY");
5268 gWaylandProxy = nullptr;
5269 }
5270# endif
5271 if (!gdk_display_get_default()) {
5272 Output(true,
5273 "Error: we don't have any display, WAYLAND_DISPLAY='%s' "
5274 "DISPLAY='%s'\n",
5275 PR_GetEnv("WAYLAND_DISPLAY"), PR_GetEnv("DISPLAY"));
5276 return 1;
5277 }
5278 // Check that Wayland only and X11 only builds
5279 // use appropriate displays.
5280# if defined(MOZ_WAYLAND1) && !defined(MOZ_X111)
5281 if (!GdkIsWaylandDisplay()) {
5282 Output(true, "Wayland only build is missig Wayland display!\n");
5283 return 1;
5284 }
5285# endif
5286# if !defined(MOZ_WAYLAND1) && defined(MOZ_X111)
5287 if (!GdkIsX11Display()) {
5288 Output(true, "X11 only build is missig X11 display!\n");
5289 return 1;
5290 }
5291# endif
5292 }
5293#endif
5294#if defined(MOZ_HAS_REMOTE1)
5295 // handle --remote now that xpcom is fired up
5296 gRemoteService = new nsRemoteService();
5297 if (gRemoteService) {
5298 gRemoteService->SetProgram(gAppData->remotingName);
5299 gStartupLock = gRemoteService->LockStartup();
5300 if (!gStartupLock) {
5301 NS_WARNING("Failed to lock for startup, continuing anyway.")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to lock for startup, continuing anyway."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
5301)
;
5302 }
5303 }
5304#endif
5305#if defined(MOZ_WIDGET_GTK1)
5306 g_set_application_name(mAppData->name);
5307
5308#endif /* defined(MOZ_WIDGET_GTK) */
5309#ifdef MOZ_X111
5310 // Do this after initializing GDK, or GDK will install its own handler.
5311 XRE_InstallX11ErrorHandler();
5312#endif
5313
5314 bool canRun = false;
5315 rv = mNativeApp->Start(&canRun);
5316 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !canRun) {
5317 return 1;
5318 }
5319
5320#ifdef MOZ_WIDGET_GTK1
5321 // startup token might be cleared now, we recover it in case we need a
5322 // restart.
5323 if (!mDesktopStartupID.IsEmpty()) {
5324 // Leak it with extreme prejudice!
5325 PR_SetEnv(ToNewCString("DESKTOP_STARTUP_ID="_ns + mDesktopStartupID));
5326 }
5327
5328 if (!mXDGActivationToken.IsEmpty()) {
5329 // Leak it with extreme prejudice!
5330 PR_SetEnv(ToNewCString("XDG_ACTIVATION_TOKEN="_ns + mXDGActivationToken));
5331 }
5332#endif
5333
5334 // Support exiting early for testing startup sequence. Bug 1360493
5335 if (CheckArg("test-launch-without-hang")) {
5336 *aExitFlag = true;
5337 return 0;
5338 }
5339
5340 mProfileSvc = NS_GetToolkitProfileService();
5341 if (!mProfileSvc) {
5342 // We failed to choose or create profile - notify user and quit
5343 ProfileMissingDialog(mNativeApp);
5344 return 1;
5345 }
5346
5347 bool wasDefaultSelection;
5348 nsCOMPtr<nsIToolkitProfile> profile;
5349 rv = SelectProfile(mProfileSvc, mNativeApp, getter_AddRefs(mProfD),
5350 getter_AddRefs(mProfLD), getter_AddRefs(profile),
5351 &wasDefaultSelection);
5352 if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS || rv == NS_ERROR_ABORT) {
5353 *aExitFlag = true;
5354 return 0;
5355 }
5356
5357 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5358 // We failed to choose or create profile - notify user and quit
5359 ProfileMissingDialog(mNativeApp);
5360 return 1;
5361 }
5362
5363#if defined(MOZ_HAS_REMOTE1)
5364 if (gRemoteService) {
5365 // Use the full profile path to identify the profile.
5366 nsCString profilePath;
5367
5368# ifdef XP_WIN
5369 nsString path;
5370 rv = mProfD->GetPath(path);
5371 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5372 CopyUTF16toUTF8(path, profilePath);
5373 }
5374# else
5375 rv = mProfD->GetNativePath(profilePath);
5376# endif
5377
5378 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5379 gRemoteService->SetProfile(profilePath);
5380
5381 if (!mDisableRemoteClient) {
5382 // Try to remote the entire command line. If this fails, start up
5383 // normally.
5384# ifdef MOZ_WIDGET_GTK1
5385 auto& startupToken =
5386 GdkIsWaylandDisplay() ? mXDGActivationToken : mDesktopStartupID;
5387# ifdef MOZ_X111
5388 if (GdkIsX11Display() && startupToken.IsEmpty()) {
5389 startupToken = SynthesizeStartupToken();
5390 }
5391# endif /* MOZ_X11 */
5392 gRemoteService->SetStartupToken(startupToken);
5393# endif
5394 rv = gRemoteService->StartClient();
5395
5396 if (rv == NS_ERROR_NOT_AVAILABLE && profile) {
5397 // Older versions would use the profile name in preference to the
5398 // path.
5399 nsCString profileName;
5400 profile->GetName(profileName);
5401 gRemoteService->SetProfile(profileName);
5402
5403 rv = gRemoteService->StartClient();
5404
5405 // Reset back to the path.
5406 gRemoteService->SetProfile(profilePath);
5407 }
5408
5409 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5410 *aExitFlag = true;
5411 gStartupLock = nullptr;
5412 return 0;
5413 }
5414
5415 if (rv == NS_ERROR_INVALID_ARG) {
5416 gStartupLock = nullptr;
5417 return 1;
5418 }
5419 }
5420 }
5421 }
5422#endif /* MOZ_HAS_REMOTE */
5423
5424#if defined(MOZ_UPDATER1) && !defined(MOZ_WIDGET_ANDROID)
5425# ifdef XP_WIN
5426 {
5427 // When automatically restarting for a staged background update
5428 // we want the child process to wait here so that the updater
5429 // does not register two instances running and use that as a
5430 // reason to not process updates. This function requires having
5431 // -restart-pid <param> in the command line to function properly.
5432 // Ensure we keep -restart-pid if we are running tests
5433 if (ARG_FOUND == CheckArgExists("restart-pid") &&
5434 !CheckArg("test-only-automatic-restart-no-wait")) {
5435 // We're not testing and can safely remove it now and read the pid.
5436 const char* restartPidString = nullptr;
5437 CheckArg("restart-pid", &restartPidString, CheckArgFlag::RemoveArg);
5438 // pid should be first parameter following -restart-pid.
5439 uint32_t pid = nsDependentCString(restartPidString).ToInteger(&rv, 10U);
5440 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && pid > 0) {
5441 printf_stderr(
5442 "*** MaybeWaitForProcessExit: launched pidDWORD = %u ***\n", pid);
5443 RefPtr<nsUpdateProcessor> updater = new nsUpdateProcessor();
5444 rv = updater->WaitForProcessExit(pid, MAYBE_WAIT_TIMEOUT_MS);
5445 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5446 NS_WARNING("Failure in nsUpdateProcessor::WaitForProcessExit.")NS_DebugBreak(NS_DEBUG_WARNING, "Failure in nsUpdateProcessor::WaitForProcessExit."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
5446)
;
5447 }
5448 } else {
5449 NS_WARNING("Failed to parse pid from -restart-pid.")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to parse pid from -restart-pid."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
5449)
;
5450 }
5451 }
5452 }
5453# endif
5454 // Check for and process any available updates
5455 nsCOMPtr<nsIFile> updRoot;
5456 bool persistent;
5457 rv = mDirProvider.GetFile(XRE_UPDATE_ROOT_DIR"UpdRootD", &persistent,
5458 getter_AddRefs(updRoot));
5459 // XRE_UPDATE_ROOT_DIR may fail. Fallback to appDir if failed
5460 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5461 updRoot = mDirProvider.GetAppDir();
5462 }
5463
5464 Maybe<ShouldNotProcessUpdatesReason> shouldNotProcessUpdatesReason =
5465 ShouldNotProcessUpdates(mDirProvider);
5466 if (shouldNotProcessUpdatesReason.isNothing()) {
5467 nsCOMPtr<nsIFile> exeFile, exeDir;
5468 rv = mDirProvider.GetFile(XRE_EXECUTABLE_FILE"XREExeF", &persistent,
5469 getter_AddRefs(exeFile));
5470 NS_ENSURE_SUCCESS(rv, 1)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", "1", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 5470); return 1; } } while (false)
;
5471 rv = exeFile->GetParent(getter_AddRefs(exeDir));
5472 NS_ENSURE_SUCCESS(rv, 1)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", "1", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 5472); return 1; } } while (false)
;
5473 ProcessUpdates(mDirProvider.GetGREDir(), exeDir, updRoot, gRestartArgc,
5474 gRestartArgv, mAppData->version);
5475 } else {
5476 if (CheckArg("test-should-not-process-updates") ||
5477 EnvHasValue("MOZ_TEST_SHOULD_NOT_PROCESS_UPDATES")) {
5478 // Support for testing *not* processing an update. The launched process
5479 // can witness this environment variable and conclude that its runtime
5480 // environment resulted in not processing updates.
5481
5482 SaveToEnv(nsPrintfCString("MOZ_TEST_SHOULD_NOT_PROCESS_UPDATES="
5483 "ShouldNotProcessUpdates(): %s",
5484 ShouldNotProcessUpdatesReasonAsString(
5485 shouldNotProcessUpdatesReason.value()))
5486 .get());
5487 }
5488 }
5489 if (CheckArg("test-process-updates") ||
5490 EnvHasValue("MOZ_TEST_PROCESS_UPDATES")) {
5491 SaveToEnv("MOZ_TEST_PROCESS_UPDATES=");
5492
5493 // If the caller has asked us to log our arguments, do so. This is used
5494 // to make sure that the maintenance service successfully launches the
5495 // callback application.
5496 const char* logFile = nullptr;
5497 if (ARG_FOUND == CheckArg("dump-args", &logFile)) {
5498 FILE* logFP = fopen(logFile, "wb");
5499 if (logFP) {
5500 for (int i = 1; i < gRestartArgc; ++i) {
5501 fprintf(logFP, "%s\n", gRestartArgv[i]);
5502 }
5503 fclose(logFP);
5504 }
5505 }
5506
5507 // Tests may want to know when we are done. We are about to exit, so we are
5508 // done here. Write out a file to indicate this to the caller.
5509 WriteUpdateCompleteTestFile(updRoot);
5510
5511 *aExitFlag = true;
5512 return 0;
5513 }
5514#endif
5515
5516 // We now know there is no existing instance using the selected profile.
5517
5518 // We only ever show the profile selector if a specific profile wasn't chosen
5519 // via command line arguments or environment variables.
5520 if (wasDefaultSelection) {
5521 if (!mProfileSvc->GetStartWithLastProfile()) {
5522 // First check the old style profile manager
5523 rv = ShowProfileManager(mProfileSvc, mNativeApp);
5524 } else if (profile && profile->GetShowProfileSelector()) {
5525 // Now check the new profile group selector
5526 rv = ShowProfileSelector(mProfileSvc, mNativeApp);
5527 } else {
5528 rv = NS_OK;
5529 }
5530
5531 if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS || rv == NS_ERROR_ABORT) {
5532 *aExitFlag = true;
5533 return 0;
5534 }
5535
5536 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5537 return 1;
5538 }
5539 }
5540
5541 // We always want to lock the profile even if we're actually going to reset
5542 // it later.
5543 rv = LockProfile(mNativeApp, mProfD, mProfLD, profile,
5544 getter_AddRefs(mProfileLock));
5545 if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS || rv == NS_ERROR_ABORT) {
5546 *aExitFlag = true;
5547 return 0;
5548 }
5549 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5550 return 1;
5551 }
5552
5553 if (gDoProfileReset) {
5554 if (!EnvHasValue("MOZ_RESET_PROFILE_RESTART")) {
5555 if (ARG_FOUND == CheckArgExists("first-startup")) {
5556 // If the profile reset was initiated by the stub installer, we want to
5557 // set MOZ_RESET_PROFILE_SESSION so we can check for it later when the
5558 // Firefox Profile Migrator runs. At that point we set overrides to
5559 // ensure users see the right homepage.
5560 SaveToEnv("MOZ_RESET_PROFILE_SESSION=0");
5561 } else if (gDoMigration) {
5562 // Otherwise this is a profile reset and migration triggered via the
5563 // command line during development and we want to restore the session
5564 // and perform the approriate homepage overrides.
5565 SaveToEnv("MOZ_RESET_PROFILE_SESSION=1");
5566 }
5567 } else {
5568 // If the profile reset was initiated by the user, such as through
5569 // about:support, we want to restore their session.
5570 SaveToEnv("MOZ_RESET_PROFILE_SESSION=1");
5571 SaveToEnv("MOZ_RESET_PROFILE_RESTART=");
5572 }
5573 // Unlock the source profile.
5574 mProfileLock->Unlock();
5575
5576 // If we're resetting a profile, create a new one and use it to startup.
5577 gResetOldProfile = profile;
5578 rv = mProfileSvc->CreateResetProfile(getter_AddRefs(profile));
5579 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5580 rv = profile->GetRootDir(getter_AddRefs(mProfD));
5581 NS_ENSURE_SUCCESS(rv, 1)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", "1", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 5581); return 1; } } while (false)
;
5582 SaveFileToEnv("XRE_PROFILE_PATH", mProfD);
5583
5584 rv = profile->GetLocalDir(getter_AddRefs(mProfLD));
5585 NS_ENSURE_SUCCESS(rv, 1)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", "1", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 5585); return 1; } } while (false)
;
5586 SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", mProfLD);
5587
5588 // Lock the new profile
5589 rv = LockProfile(mNativeApp, mProfD, mProfLD, profile,
5590 getter_AddRefs(mProfileLock));
5591 if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS || rv == NS_ERROR_ABORT) {
5592 *aExitFlag = true;
5593 return 0;
5594 }
5595 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5596 return 1;
5597 }
5598 } else {
5599 NS_WARNING("Profile reset failed.")NS_DebugBreak(NS_DEBUG_WARNING, "Profile reset failed.", nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 5599)
;
5600 return 1;
5601 }
5602 }
5603
5604 gProfileLock = mProfileLock;
5605
5606 nsAutoCString version;
5607 BuildVersion(version);
5608
5609#ifdef TARGET_OS_ABI"Linux_x86_64-gcc3"
5610 constexpr auto osABI = nsLiteralCString{TARGET_OS_ABI"Linux_x86_64-gcc3"};
5611#else
5612 // No TARGET_XPCOM_ABI, but at least the OS is known
5613 constexpr auto osABI = nsLiteralCString{OS_TARGET"Linux" "_UNKNOWN"};
5614#endif
5615
5616 // Check for version compatibility with the last version of the app this
5617 // profile was started with. The format of the version stamp is defined
5618 // by the BuildVersion function.
5619 // Also check to see if something has happened to invalidate our
5620 // fastload caches, like an app upgrade.
5621
5622 // If we see .purgecaches, that means someone did a make.
5623 // Re-register components to catch potential changes.
5624 nsCOMPtr<nsIFile> flagFile;
5625 if (mAppData->directory) {
5626 (void)mAppData->directory->Clone(getter_AddRefs(flagFile));
5627 }
5628 if (flagFile) {
5629 flagFile->AppendNative(FILE_INVALIDATE_CACHES".purgecaches"_ns);
5630 }
5631
5632 bool cachesOK;
5633 bool isDowngrade;
5634 nsCString lastVersion;
5635 bool versionOK = CheckCompatibility(
5636 mProfD, version, osABI, mDirProvider.GetGREDir(), mAppData->directory,
5637 flagFile, &cachesOK, &isDowngrade, lastVersion);
5638
5639 MOZ_RELEASE_ASSERT(!cachesOK || lastVersion.Equals(version),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!cachesOK || lastVersion.Equals(version))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!cachesOK || lastVersion.Equals(version)))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!cachesOK || lastVersion.Equals(version)"
" (" "Caches cannot be good if the version has changed." ")"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 5640); AnnotateMozCrashReason
("MOZ_RELEASE_ASSERT" "(" "!cachesOK || lastVersion.Equals(version)"
") (" "Caches cannot be good if the version has changed." ")"
); do { MOZ_CrashSequence(__null, 5640); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5640 "Caches cannot be good if the version has changed.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!cachesOK || lastVersion.Equals(version))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!cachesOK || lastVersion.Equals(version)))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!cachesOK || lastVersion.Equals(version)"
" (" "Caches cannot be good if the version has changed." ")"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 5640); AnnotateMozCrashReason
("MOZ_RELEASE_ASSERT" "(" "!cachesOK || lastVersion.Equals(version)"
") (" "Caches cannot be good if the version has changed." ")"
); do { MOZ_CrashSequence(__null, 5640); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5641
5642 // Refuse to launch if the profile's on-disk encryption state and the
5643 // launching build's pref disagree: silently opening encrypted DBs with
5644 // the wrong VFS (or plaintext DBs as ciphertext) would corrupt them.
5645 // This must run before any storage code. Skip in backgroundtask mode:
5646 // those tasks operate on profile files independently of any SQLite
5647 // consumer and must succeed regardless of the gate.
5648#ifdef MOZ_BACKGROUNDTASKS1
5649 if (!BackgroundTasks::IsBackgroundTaskMode())
5650#endif
5651 {
5652 bool prefEnabled =
5653 StaticPrefs::security_storage_encryption_sqlite_enabled();
5654 EncryptionCompatResult ec =
5655 CheckEncryptionCompatibility(mProfD, prefEnabled);
5656 if (ec != EncryptionCompatResult::OK) {
5657 const char* msgKey =
5658 ec == EncryptionCompatResult::RefuseEncryptedButPrefOff
5659 ? "profileEncryptedButPrefOff"
5660 : "profileNotEncryptedButPrefOn";
5661 const char* titleKey =
5662 ec == EncryptionCompatResult::RefuseEncryptedButPrefOff
5663 ? "profileEncryptedButPrefOffTitle"
5664 : "profileNotEncryptedButPrefOnTitle";
5665 (void)ProfileEncryptionMismatchDialog(msgKey, titleKey, mNativeApp);
5666 *aExitFlag = true;
5667 return 0;
5668 }
5669 }
5670
5671#ifdef MOZ_BLOCK_PROFILE_DOWNGRADE1
5672 // The argument check must come first so the argument is always removed from
5673 // the command line regardless of whether this is a downgrade or not.
5674 if (!CheckArg("allow-downgrade") && isDowngrade &&
5675 !EnvHasValue("MOZ_ALLOW_DOWNGRADE")) {
5676# ifdef XP_MACOSX
5677 InitializeMacApp();
5678# endif
5679 rv = HandleDetectedDowngrade(mProfD, mNativeApp, mProfileSvc, lastVersion);
5680 if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS || rv == NS_ERROR_ABORT) {
5681 *aExitFlag = true;
5682 return 0;
5683 }
5684 }
5685#endif
5686
5687 rv = mDirProvider.SetProfile(mProfD, mProfLD);
5688 NS_ENSURE_SUCCESS(rv, 1)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", "1", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 5688); return 1; } } while (false)
;
5689
5690 //////////////////////// NOW WE HAVE A PROFILE ////////////////////////
5691
5692 mozilla::Telemetry::SetProfileDir(mProfD);
5693
5694 if (mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER(1 << 3)) {
5695 MakeOrSetMinidumpPath(mProfD);
5696 }
5697
5698 CrashReporter::SetProfileDirectory(mProfD);
5699
5700#ifdef MOZ_ASAN_REPORTER
5701 // In ASan reporter builds, we need to set ASan's log_path as early as
5702 // possible, so it dumps its errors into files there instead of using
5703 // the default stderr location. Since this is crucial for ASan reporter
5704 // to work at all (and we don't want people to use a non-functional
5705 // ASan reporter build), all failures while setting log_path are fatal.
5706 setASanReporterPath(mProfD);
5707
5708 // Export to env for child processes
5709 SaveFileToEnv("ASAN_REPORTER_PATH", mProfD);
5710#endif
5711
5712 bool lastStartupWasCrash = CheckLastStartupWasCrash();
5713
5714 CrashReporter::RecordAnnotationBool(
5715 CrashReporter::Annotation::LastStartupWasCrash, lastStartupWasCrash);
5716
5717 if (CheckArg("purgecaches") || PR_GetEnv("MOZ_PURGE_CACHES") ||
5718 lastStartupWasCrash || gSafeMode) {
5719 cachesOK = false;
5720 }
5721
5722 CrashReporter::RecordAnnotationBool(
5723 CrashReporter::Annotation::StartupCacheValid, cachesOK && versionOK);
5724
5725#ifdef XP_MACOSX
5726 static bool status = nsCocoaFeatures::ProcessIsRosettaTranslated();
5727 CrashReporter::RecordAnnotationBool(CrashReporter::Annotation::RosettaStatus,
5728 status);
5729 mozilla::glean::widget::rosetta_status.Set(status);
5730#endif
5731
5732 // Every time a profile is loaded by a build with a different version,
5733 // it updates the compatibility.ini file saying what version last wrote
5734 // the fastload caches. On subsequent launches if the version matches,
5735 // there is no need for re-registration. If the user loads the same
5736 // profile in different builds the component registry must be
5737 // re-generated to prevent mysterious component loading failures.
5738 //
5739 bool startupCacheValid = true;
5740
5741 if (!cachesOK || !versionOK) {
5742 QuotaManager::InvalidateQuotaCache(
5743 QuotaManager::CacheInvalidationLevel::Soft);
5744
5745 startupCacheValid = RemoveComponentRegistries(mProfD, mProfLD, false);
5746
5747 // Rewrite compatibility.ini to match the current build. The next run
5748 // should attempt to invalidate the caches if either this run is safe mode
5749 // or the attempt to invalidate the caches this time failed.
5750 WriteVersion(mProfD, version, osABI, mDirProvider.GetGREDir(),
5751 mAppData->directory, gSafeMode || !startupCacheValid);
5752 }
5753
5754 if (!startupCacheValid) StartupCache::IgnoreDiskCache();
5755
5756 if (flagFile) {
5757 flagFile->Remove(true);
5758 }
5759
5760 // Flush any pending page load events.
5761 mozilla::glean_pings::Pageload.Submit("startup"_ns);
5762
5763 if (!isBackgroundTaskMode) {
5764#ifdef USE_GLX_TEST1
5765 GfxInfo::FireGLXTestProcess();
5766#endif
5767#ifdef MOZ_WAYLAND1
5768 // Make sure we have wayland connection for main thread.
5769 // It's used as template to create display connections
5770 // for different threads.
5771 if (IsWaylandEnabled()) {
5772 (void)WaylandDisplayGet();
5773 }
5774#endif
5775#ifdef MOZ_WIDGET_GTK1
5776 nsAppShell::InstallTermSignalHandler();
5777#endif
5778 }
5779
5780 return 0;
5781}
5782
5783#if defined(MOZ_SANDBOX1)
5784void AddSandboxAnnotations() MOZ_CAN_RUN_SCRIPT_BOUNDARY {
5785 CrashReporter::RecordAnnotationU32(
5786 CrashReporter::Annotation::ContentSandboxLevel,
5787 GetEffectiveContentSandboxLevel());
5788 CrashReporter::RecordAnnotationU32(CrashReporter::Annotation::GpuSandboxLevel,
5789 GetEffectiveGpuSandboxLevel());
5790
5791 // Include whether or not this instance is capable of content sandboxing
5792 bool sSandboxCapable = false;
5793
5794# if defined(XP_WIN)
5795 // All supported Windows versions support some level of content sandboxing
5796 sSandboxCapable = true;
5797# elif defined(XP_MACOSX)
5798 // All supported OS X versions are capable
5799 sSandboxCapable = true;
5800# elif defined(XP_LINUX1)
5801 sSandboxCapable = SandboxInfo::Get().CanSandboxContent();
5802# elif defined(__OpenBSD__)
5803 sSandboxCapable = true;
5804 StartOpenBSDSandbox(GeckoProcessType_Default);
5805# endif
5806
5807 CrashReporter::RecordAnnotationBool(
5808 CrashReporter::Annotation::ContentSandboxCapable, sSandboxCapable);
5809}
5810#endif /* MOZ_SANDBOX */
5811
5812/*
5813 * XRE_mainRun - Command line startup, profile migration, and
5814 * the calling of appStartup->Run().
5815 */
5816nsresult XREMain::XRE_mainRun() {
5817 nsresult rv = NS_OK;
5818 NS_ASSERTION(mScopedXPCOM, "Scoped xpcom not initialized.")do { if (!(mScopedXPCOM)) { NS_DebugBreak(NS_DEBUG_ASSERTION,
"Scoped xpcom not initialized.", "mScopedXPCOM", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 5818); MOZ_PretendNoReturn(); } } while (0)
;
5819
5820#if defined(XP_WIN)
5821 RefPtr<mozilla::DllServices> dllServices(mozilla::DllServices::Get());
5822 dllServices->StartUntrustedModulesProcessor(false);
5823 auto dllServicesDisable =
5824 MakeScopeExit([&dllServices]() { dllServices->DisableFull(); });
5825
5826 mozilla::mscom::InitProfilerMarkers();
5827#endif // defined(XP_WIN)
5828
5829 // We need the appStartup pointer to span multiple scopes, so we declare
5830 // it here.
5831 nsCOMPtr<nsIAppStartup> appStartup;
5832 // Ditto with the command line.
5833 nsCOMPtr<nsICommandLineRunner> cmdLine;
5834
5835 {
5836#ifdef XP_MACOSX
5837 // In this scope, create an autorelease pool that will leave scope with
5838 // it just before entering our event loop.
5839 mozilla::MacAutoreleasePool pool;
5840#endif
5841
5842 rv = mScopedXPCOM->SetWindowCreator(mNativeApp);
5843 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)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", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 5843); return
NS_ERROR_FAILURE; } } while (false)
;
5844
5845 // Record platform annotations which need XPCOM initialized.
5846 CrashReporter::RecordXPCOMPlatformAnnotations();
5847
5848 // tell the crash reporter to also send the release channel
5849 nsCOMPtr<nsIPrefService> prefs =
5850 do_GetService("@mozilla.org/preferences-service;1", &rv);
5851 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5852 nsCOMPtr<nsIPrefBranch> defaultPrefBranch;
5853 rv = prefs->GetDefaultBranch(nullptr, getter_AddRefs(defaultPrefBranch));
5854
5855 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5856 nsAutoCString sval;
5857 rv = defaultPrefBranch->GetCharPref("app.update.channel", sval);
5858 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5859 CrashReporter::RecordAnnotationNSCString(
5860 CrashReporter::Annotation::ReleaseChannel, sval);
5861 }
5862 }
5863 }
5864 // Needs to be set after xpcom initialization.
5865 bool includeContextHeap = Preferences::GetBool(
5866 "toolkit.crashreporter.include_context_heap", false);
5867 CrashReporter::SetIncludeContextHeap(includeContextHeap);
5868
5869#if defined(XP_LINUX1) && !defined(ANDROID)
5870 PR_CreateThread(PR_USER_THREAD, AnnotateLSBRelease, nullptr,
5871 PR_PRIORITY_LOW, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0);
5872#endif
5873
5874 if (mStartOffline) {
5875 nsCOMPtr<nsIIOService> io(
5876 do_GetService("@mozilla.org/network/io-service;1"));
5877 NS_ENSURE_TRUE(io, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(io)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "io" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 5877); return NS_ERROR_FAILURE; } } while (false)
;
5878 io->SetManageOfflineStatus(false);
5879 io->SetOffline(true);
5880 }
5881
5882 if (!mOriginToForceQUIC.IsEmpty()) {
5883 PR_SetEnv(ToNewCString("MOZ_FORCE_QUIC_ON="_ns + mOriginToForceQUIC));
5884 }
5885
5886#ifdef XP_WIN
5887 mozilla::DllPrefetchExperimentRegistryInfo prefetchRegInfo;
5888 mozilla::AlteredDllPrefetchMode dllPrefetchMode =
5889 prefetchRegInfo.GetAlteredDllPrefetchMode();
5890
5891 if (!PR_GetEnv("XRE_NO_DLL_READAHEAD") &&
5892 dllPrefetchMode != mozilla::AlteredDllPrefetchMode::NoPrefetch) {
5893 nsCOMPtr<nsIFile> greDir = mDirProvider.GetGREDir();
5894 nsAutoString path;
5895 rv = greDir->GetPath(path);
5896 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5897 // We use the presence of a path argument inside the thread to determine
5898 // which list of Dlls to use. The old list does not need access to the
5899 // GRE dir, so the path argument is voided.
5900 if (dllPrefetchMode !=
5901 mozilla::AlteredDllPrefetchMode::OptimizedPrefetch) {
5902 path.SetIsVoid(true);
5903 }
5904
5905 NS_DispatchBackgroundTask(
5906 NS_NewRunnableFunction("ReadAheadDlls", [path = std::move(path)] {
5907 ReadAheadDlls(path.IsVoid() ? nullptr : path.get());
5908 }));
5909 }
5910 }
5911#endif
5912
5913 if (gDoMigration) {
5914 nsCOMPtr<nsIFile> file;
5915 mDirProvider.GetAppDir()->Clone(getter_AddRefs(file));
5916 file->AppendNative("override.ini"_ns);
5917 nsINIParsernsINIParser_internal parser;
5918 nsresult rv = parser.Init(file);
5919 // if override.ini doesn't exist, also check for distribution.ini
5920 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5921 bool persistent;
5922 mDirProvider.GetFile(XRE_APP_DISTRIBUTION_DIR"XREAppDist", &persistent,
5923 getter_AddRefs(file));
5924 file->AppendNative("distribution.ini"_ns);
5925 rv = parser.Init(file);
5926 }
5927 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5928 nsAutoCString buf;
5929 rv = parser.GetString("XRE", "EnableProfileMigrator", buf);
5930 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5931 if (buf[0] == '0' || buf[0] == 'f' || buf[0] == 'F') {
5932 gDoMigration = false;
5933 }
5934 }
5935 }
5936 }
5937
5938 // We'd like to initialize the JSContext *after* reading the user prefs.
5939 // Unfortunately that's not possible if we have to do profile migration
5940 // because that requires us to execute JS before reading user prefs.
5941 // Restarting the browser after profile migration would fix this. See
5942 // bug 1592523.
5943 bool initializedJSContext = false;
5944
5945 {
5946 // Profile Migration
5947 if (mAppData->flags & NS_XRE_ENABLE_PROFILE_MIGRATOR(1 << 1) && gDoMigration) {
5948 gDoMigration = false;
5949
5950 xpc::InitializeJSContext();
5951 initializedJSContext = true;
5952
5953 nsCOMPtr<nsIProfileMigrator> pm(
5954 do_CreateInstance(NS_PROFILEMIGRATOR_CONTRACTID"@mozilla.org/toolkit/profile-migrator;1"));
5955 if (pm) {
5956 nsAutoCString aKey;
5957 nsAutoCString aProfilePath;
5958 if (gDoProfileReset) {
5959 // Automatically migrate from the current application if we just
5960 // reset the profile.
5961 nsCOMPtr<nsIFile> rootDir = gResetOldProfile->GetRootDir();
5962 nsAutoString path;
5963 rootDir->GetPath(path);
5964 CopyUTF16toUTF8(path, aProfilePath);
5965
5966 nsCString storeID;
5967 gResetOldProfile->GetStoreID(storeID);
5968 if (!storeID.IsVoid()) {
5969 aKey = "firefox-selectable-profile";
5970 // In the case that Firefox is launched with --reset-profile,
5971 // the storeID and path env variables won't be set, so we set
5972 // them here if we are in a profile with a storeID.
5973 nsAutoCString envStoreID("SELECTABLE_PROFILE_RESET_STORE_ID=");
5974 envStoreID.Append(storeID);
5975 SaveToEnv(envStoreID.get());
5976
5977 nsAutoCString envProfilePath("SELECTABLE_PROFILE_RESET_PATH=");
5978 envProfilePath.Append(aProfilePath);
5979 SaveToEnv(envProfilePath.get());
5980 } else {
5981 aKey = MOZ_APP_NAME"firefox";
5982 }
5983 }
5984#ifdef XP_MACOSX
5985 // Necessary for migration wizard to be accessible.
5986 InitializeMacApp();
5987#endif
5988 pm->Migrate(&mDirProvider, aKey, aProfilePath);
5989 }
5990 }
5991
5992 if (gDoProfileReset) {
5993 if (!initializedJSContext) {
5994 xpc::InitializeJSContext();
5995 initializedJSContext = true;
5996 }
5997
5998 const RefPtr<nsToolkitProfileService> profileSvc = mProfileSvc;
5999 const nsCOMPtr<nsIToolkitProfile> oldProfile = gResetOldProfile;
6000 nsresult backupCreated = ProfileResetCleanup(profileSvc, oldProfile);
6001 if (NS_FAILED(backupCreated)((bool)(__builtin_expect(!!(NS_FAILED_impl(backupCreated)), 0
)))
) {
6002 NS_WARNING("Could not cleanup the profile that was reset")NS_DebugBreak(NS_DEBUG_WARNING, "Could not cleanup the profile that was reset"
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
6002)
;
6003 }
6004 }
6005 }
6006
6007 // Initialize user preferences before notifying startup observers so they're
6008 // ready in time for early consumers, such as the component loader.
6009 mDirProvider.InitializeUserPrefs();
6010
6011 // Now that preferences are loaded the profile service may be able to
6012 // determine the correct startup profile.
6013 mProfileSvc->UpdateCurrentProfile();
6014
6015 // Now that all (user) prefs have been loaded we can initialize the main
6016 // thread's JSContext.
6017 if (!initializedJSContext) {
6018 xpc::InitializeJSContext();
6019 }
6020
6021 // Finally, now that JS has been initialized, we can finish pref loading.
6022 // This needs to happen after JS and XPConnect initialization because
6023 // AutoConfig files require JS execution. Note that this means AutoConfig
6024 // files can't override JS engine start-up prefs.
6025 mDirProvider.FinishInitializingUserPrefs();
6026
6027 // Now that the profiler, directory services, and prefs have been
6028 // initialized we can find the download directory, where the profiler can
6029 // write profiles when user stops the profiler using POSIX signal handling.
6030 //
6031 // It's possible to start and stop the profiler by sending POSIX signals to
6032 // the profiler binary when Firefox is frozen. At the time when stop signal
6033 // is handled, Firefox stops the profiler and dumps the profile to disk. But
6034 // getting the download directory is not really possible at that time
6035 // because main thread will be unresponsive. That's why we are getting this
6036 // information right now.
6037 profiler_lookup_async_signal_dump_directory();
6038
6039 // Do a canary load of a JS based module here. This will help us detect
6040 // missing resources during startup and make us react appropriate, that
6041 // is inform the user before exiting with a crash.
6042 {
6043 mozilla::dom::AutoJSAPI jsapi;
6044 MOZ_ALWAYS_TRUE(jsapi.Init(xpc::PrivilegedJunkScope()))do { if ((__builtin_expect(!!(jsapi.Init(xpc::PrivilegedJunkScope
())), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "jsapi.Init(xpc::PrivilegedJunkScope())", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6044); AnnotateMozCrashReason("MOZ_CRASH(" "jsapi.Init(xpc::PrivilegedJunkScope())"
")"); do { MOZ_CrashSequence(__null, 6044); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
6045 JS::Rooted<JSObject*> mod(jsapi.cx());
6046 // AppConstants.sys.mjs is small, widely used and most likely will
6047 // never go away.
6048 rv = mozJSModuleLoader::Get()->ImportESModule(
6049 jsapi.cx(), "resource://gre/modules/AppConstants.sys.mjs"_ns, &mod);
6050 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6051 return NS_ERROR_OMNIJAR_OR_DIR_MISSING;
6052 }
6053 }
6054
6055#if defined(MOZ_SANDBOX1) && defined(XP_WIN)
6056 // Now that we have preferences and the directory provider, we can
6057 // finish initializing SandboxBroker. This must happen before the GFX
6058 // platform is initialized (which will launch the GPU process), which
6059 // occurs when the "app-startup" category is started up below
6060 //
6061 // After this completes, we are ready to launch sandboxed processes
6062 mozilla::SandboxBroker::GeckoDependentInitialize();
6063#endif
6064
6065 nsCOMPtr<nsIFile> workingDir;
6066 rv = NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR"CurWorkD",
6067 getter_AddRefs(workingDir));
6068 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6069 // No working dir? This can happen if it gets deleted before we start.
6070 workingDir = nullptr;
6071 }
6072
6073 cmdLine = new nsCommandLine();
6074
6075 rv = cmdLine->Init(gArgc, gArgv, workingDir,
6076 nsICommandLine::STATE_INITIAL_LAUNCH);
6077 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)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", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 6077); return
NS_ERROR_FAILURE; } } while (false)
;
6078
6079 // "app-startup" is the name of both the category and the event
6080 NS_CreateServicesFromCategory("app-startup", cmdLine, "app-startup",
6081 nullptr);
6082
6083 appStartup = components::AppStartup::Service();
6084 NS_ENSURE_TRUE(appStartup, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(appStartup)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "appStartup" ") failed",
nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 6084
); return NS_ERROR_FAILURE; } } while (false)
;
6085
6086 mDirProvider.DoStartup();
6087
6088#ifdef XP_WIN
6089 // It needs to be called on the main thread because it has to use
6090 // nsObserverService.
6091 EnsureWin32kInitialized();
6092#endif
6093
6094 // As FilePreferences need the profile directory, we must initialize right
6095 // here.
6096 mozilla::FilePreferences::InitDirectoriesAllowlist();
6097 mozilla::FilePreferences::InitPrefs();
6098
6099 nsCString userAgentLocale;
6100 LocaleService::GetInstance()->GetAppLocaleAsBCP47(userAgentLocale);
6101 CrashReporter::RecordAnnotationNSCString(
6102 CrashReporter::Annotation::useragent_locale, userAgentLocale);
6103
6104 if (!AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
6105 /* Special-case services that need early access to the command
6106 line. */
6107 nsCOMPtr<nsIObserverService> obsService =
6108 mozilla::services::GetObserverService();
6109 if (obsService) {
6110 obsService->NotifyObservers(cmdLine, "command-line-startup", nullptr);
6111 }
6112 }
6113
6114#ifdef XP_WIN
6115 // Hack to sync up the various environment storages. XUL_APP_FILE is special
6116 // in that it comes from a different CRT (firefox.exe's static-linked copy).
6117 // Ugly details in http://bugzil.la/1175039#c27
6118 char appFile[MAX_PATH];
6119 if (GetEnvironmentVariableA("XUL_APP_FILE", appFile, sizeof(appFile))) {
6120 SmprintfPointer saved = mozilla::Smprintf("XUL_APP_FILE=%s", appFile);
6121 // We intentionally leak the string here since it is required by
6122 // PR_SetEnv.
6123 PR_SetEnv(saved.release());
6124 }
6125#endif
6126
6127 mozilla::AppShutdown::SaveEnvVarsForPotentialRestart();
6128
6129 // clear out any environment variables which may have been set
6130 // during the relaunch process now that we know we won't be relaunching.
6131 SaveToEnv("XRE_PROFILE_PATH=");
6132 SaveToEnv("XRE_PROFILE_LOCAL_PATH=");
6133 SaveToEnv("XRE_START_OFFLINE=");
6134 SaveToEnv("XUL_APP_FILE=");
6135 SaveToEnv("XRE_BINARY_PATH=");
6136 SaveToEnv("XRE_RESTARTED_BY_PROFILE_MANAGER=");
6137
6138 if (!AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
6139#ifdef XP_MACOSX
6140 bool isBackgroundTaskMode = false;
6141# ifdef MOZ_BACKGROUNDTASKS1
6142 isBackgroundTaskMode = BackgroundTasks::IsBackgroundTaskMode();
6143# endif
6144 if (!isBackgroundTaskMode) {
6145 rv = appStartup->CreateHiddenWindow();
6146 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)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", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 6146); return
NS_ERROR_FAILURE; } } while (false)
;
6147 }
6148#endif
6149
6150#ifdef XP_WIN
6151 Preferences::RegisterCallbackAndCall(
6152 RegisterApplicationRestartChanged,
6153 PREF_WIN_REGISTER_APPLICATION_RESTART);
6154 SetupAlteredPrefetchPref();
6155# if defined(MOZ_LAUNCHER_PROCESS)
6156 SetupLauncherProcessPref();
6157# endif // defined(MOZ_LAUNCHER_PROCESS)
6158# if defined(MOZ_DEFAULT_BROWSER_AGENT)
6159# if defined(MOZ_BACKGROUNDTASKS1)
6160 // The backgroundtask profile is not a browsing profile, let alone the new
6161 // default profile, so don't mirror its properties into the registry.
6162 if (!BackgroundTasks::IsBackgroundTaskMode())
6163# endif // defined(MOZ_BACKGROUNDTASKS)
6164 {
6165 SetupSkeletonUIPrefs();
6166 Preferences::RegisterCallbackAndCall(
6167 &OnDefaultAgentTelemetryPrefChanged,
6168 kPrefHealthReportUploadEnabled);
6169 Preferences::RegisterCallbackAndCall(
6170 &OnDefaultAgentTelemetryPrefChanged, kPrefDefaultAgentEnabled);
6171
6172 Preferences::RegisterCallbackAndCall(
6173 &OnDefaultAgentRemoteSettingsPrefChanged,
6174 kPrefServicesSettingsServer);
6175
6176 Preferences::RegisterCallbackAndCall(
6177 &OnSetDefaultBrowserUserChoicePrefChanged,
6178 kPrefSetDefaultBrowserUserChoicePref);
6179
6180 SetDefaultAgentLastRunTime();
6181 }
6182# endif // defined(MOZ_DEFAULT_BROWSER_AGENT)
6183#endif
6184
6185#if defined(MOZ_WIDGET_GTK1)
6186 // Clear the environment variables so they won't be inherited by child
6187 // processes and confuse things.
6188 for (const auto& name : kStartupTokenNames) {
6189 g_unsetenv(name.get());
6190 }
6191 nsAppShell::InitSessionRestore();
6192#endif
6193
6194#ifdef XP_MACOSX
6195 InitializeMacApp();
6196
6197 // we re-initialize the command-line service and do appleevents munging
6198 // after we are sure that we're not restarting
6199 cmdLine = new nsCommandLine();
6200
6201 char** tempArgv = static_cast<char**>(malloc(gArgc * sizeof(char*)));
6202 for (int i = 0; i < gArgc; i++) {
6203 tempArgv[i] = strdup(gArgv[i]);
6204 }
6205 CommandLineServiceMac::SetupMacCommandLine(gArgc, tempArgv, false);
6206 rv = cmdLine->Init(gArgc, tempArgv, workingDir,
6207 nsICommandLine::STATE_INITIAL_LAUNCH);
6208 free(tempArgv);
6209 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)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", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 6209); return
NS_ERROR_FAILURE; } } while (false)
;
6210
6211# if defined(MOZILLA_OFFICIAL) || defined(DMG_INSTALL_HELPER_DEBUG)
6212 // Check if we're running from a DMG or an app translocated location and
6213 // allow the user to install to the Applications directory.
6214 if (MacRunFromDmgUtils::MaybeInstallAndRelaunch()) {
6215 bool userAllowedQuit = true;
6216 appStartup->Quit(nsIAppStartup::eForceQuit, 0, &userAllowedQuit);
6217 }
6218# endif
6219#endif
6220
6221#if defined(XP_MACOSX) && defined(NIGHTLY_BUILD1)
6222 RegisterASWebAuthSessionObservers();
6223#endif
6224
6225 nsCOMPtr<nsIObserverService> obsService =
6226 mozilla::services::GetObserverService();
6227 if (obsService)
6228 obsService->NotifyObservers(nullptr, "final-ui-startup", nullptr);
6229
6230 (void)appStartup->DoneStartingUp();
6231
6232 CrashReporter::RecordAnnotationBool(
6233 CrashReporter::Annotation::StartupCrash, false);
6234
6235 AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed);
6236 }
6237
6238 if (!AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
6239 rv = cmdLine->Run();
6240 NS_ENSURE_SUCCESS_LOG(rv, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(!
NS_FAILED_impl(rv)), 1))))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "NS_SUCCEEDED(rv)" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6240); gLogConsoleErrors = true; return NS_ERROR_FAILURE; }
} while (0)
;
6241 }
6242
6243 if (!AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
6244#if defined(MOZ_HAS_REMOTE1)
6245 // if we have X remote support, start listening for requests on the
6246 // proxy window.
6247 if (gRemoteService) {
6248 gRemoteService->StartupServer();
6249 gStartupLock = nullptr;
6250 }
6251#endif
6252
6253 mNativeApp->Enable();
6254 }
6255
6256 // Send Telemetry about Gecko version and buildid
6257 mozilla::glean::gecko::version.Set(nsDependentCString(gAppData->version));
6258 mozilla::glean::gecko::build_id.Set(nsDependentCString(gAppData->buildID));
6259
6260#if defined(MOZ_SANDBOX1) && defined(XP_LINUX1)
6261 // If we're on Linux, we now have information about the OS capabilities
6262 // available to us.
6263 SandboxInfo sandboxInfo = SandboxInfo::Get();
6264 // If we need telemetry probes for sandboxInfo bits, they can go here.
6265
6266 CrashReporter::RecordAnnotationU32(
6267 CrashReporter::Annotation::ContentSandboxCapabilities,
6268 sandboxInfo.AsInteger());
6269#endif /* MOZ_SANDBOX && XP_LINUX */
6270
6271#if defined(XP_WIN)
6272 LauncherResult<bool> isAdminWithoutUac = IsAdminWithoutUac();
6273 if (isAdminWithoutUac.isOk()) {
6274 glean::os_environment::is_admin_without_uac.Set(
6275 isAdminWithoutUac.unwrap());
6276 }
6277#endif /* XP_WIN */
6278
6279#if defined(MOZ_SANDBOX1)
6280 AddSandboxAnnotations();
6281#endif /* MOZ_SANDBOX */
6282
6283 mProfileSvc->CompleteStartup();
6284 }
6285
6286#ifdef MOZ_BACKGROUNDTASKS1
6287 if (BackgroundTasks::IsBackgroundTaskMode()) {
6288 // In background task mode, we don't fire various delayed initialization
6289 // notifications, which in the regular browser is how startup crash tracking
6290 // is marked as finished. Here, getting this far means we don't have a
6291 // startup crash.
6292 rv = appStartup->TrackStartupCrashEnd();
6293 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, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6293); return rv; } } while (false)
;
6294
6295 // We never open a window, but don't want to exit immediately.
6296 rv = appStartup->EnterLastWindowClosingSurvivalArea();
6297 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, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6297); return rv; } } while (false)
;
6298
6299 // Avoid some small differences in initialization order across platforms.
6300 nsCOMPtr<nsIPowerManagerService> powerManagerService =
6301 do_GetService(POWERMANAGERSERVICE_CONTRACTID"@mozilla.org/power/powermanagerservice;1");
6302 nsCOMPtr<nsIStringBundleService> stringBundleService =
6303 do_GetService(NS_STRINGBUNDLE_CONTRACTID"@mozilla.org/intl/stringbundle;1");
6304
6305 rv = BackgroundTasks::RunBackgroundTask(cmdLine);
6306 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, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6306); return rv; } } while (false)
;
6307 }
6308#endif
6309
6310 // We're entering the main run loop now, so we don't need to keep holding onto
6311 // the `nsICommandLineRunner` anymore.
6312 cmdLine = nullptr;
6313
6314#ifdef ACCESSIBILITY1
6315 // If accessibility.force_disabled is force enabled, start accessibility
6316 // now rather than waiting for something to request it. This is the one
6317 // place we can do this reliably on every platform.
6318 a11y::MaybeStartForceEnabled();
6319#endif
6320
6321 {
6322 rv = appStartup->Run();
6323 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6324 NS_ERROR("failed to run appstartup")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "failed to run appstartup"
, "Error", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
6324); MOZ_PretendNoReturn(); } while (0)
;
6325 gLogConsoleErrors = true;
6326 }
6327 }
6328
6329 return rv;
6330}
6331
6332#if defined(MOZ_WIDGET_ANDROID)
6333static already_AddRefed<nsIFile> GreOmniPath(int argc, char** argv) {
6334 nsresult rv;
6335
6336 const char* path = nullptr;
6337 ArgResult ar = CheckArg(argc, argv, "greomni", &path, CheckArgFlag::None);
6338 if (ar == ARG_BAD) {
6339 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
6340 "Error: argument --greomni requires a path argument\n");
6341 return nullptr;
6342 }
6343
6344 if (!path) return nullptr;
6345
6346 nsCOMPtr<nsIFile> greOmni;
6347 rv = XRE_GetFileFromPath(path, getter_AddRefs(greOmni));
6348 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6349 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Error: argument --greomni requires a valid path\n");
6350 return nullptr;
6351 }
6352
6353 return greOmni.forget();
6354}
6355#endif
6356
6357/*
6358 * XRE_main - A class based main entry point used by most platforms.
6359 * Note that on OSX, aAppData->xreDirectory will point to
6360 * .app/Contents/Resources.
6361 */
6362int XREMain::XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig) {
6363 gArgc = argc;
6364 gArgv = argv;
6365 ScopedLogging log;
6366
6367 mozilla::LogModule::Init(gArgc, gArgv);
6368
6369#ifndef XP_LINUX1
6370 NS_SetCurrentThreadName("MainThread");
6371#endif
6372
6373 AUTO_BASE_PROFILER_LABEL("XREMain::XRE_main (around Gecko Profiler)", OTHER)::mozilla::baseprofiler::AutoProfilerLabel raiiObject6373( "XREMain::XRE_main (around Gecko Profiler)"
, nullptr, ::mozilla::baseprofiler::ProfilingCategoryPair::OTHER
)
;
6374 AUTO_PROFILER_INITmozilla::AutoProfilerInit raiiObject6374;
6375 AUTO_PROFILER_LABEL("XREMain::XRE_main", OTHER)mozilla::AutoProfilerLabel raiiObject6375( "XREMain::XRE_main"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
6376
6377#ifdef XP_MACOSX
6378 // We call this early because it will kick off a background-thread task
6379 // to register the fonts, and we'd like it to have a chance to complete
6380 // before gfxPlatform initialization actually requires it.
6381 auto _supplementalFontThread = gfxPlatformMac::RegisterSupplementalFonts();
6382#endif
6383
6384#ifdef MOZ_WIDGET_ANDROID
6385 // We call the early because we run system font API on a background-thread
6386 // to initialize internal font API data in Android. (Bug 1895926)
6387 gfxAndroidPlatform::InitializeFontAPI();
6388#endif
6389
6390#ifdef MOZ_CODE_COVERAGE
6391 CodeCoverageHandler::Init();
6392#endif
6393
6394 nsresult rv = NS_OK;
6395
6396 if (aConfig.appData) {
6397 mAppData = MakeUnique<XREAppData>(*aConfig.appData);
6398 } else {
6399 MOZ_RELEASE_ASSERT(aConfig.appDataPath)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aConfig.appDataPath)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aConfig.appDataPath))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("aConfig.appDataPath"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 6399); AnnotateMozCrashReason
("MOZ_RELEASE_ASSERT" "(" "aConfig.appDataPath" ")"); do { MOZ_CrashSequence
(__null, 6399); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6400 nsCOMPtr<nsIFile> appini;
6401 rv = XRE_GetFileFromPath(aConfig.appDataPath, getter_AddRefs(appini));
6402 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6403 Output(true, "Error: unrecognized path: %s\n", aConfig.appDataPath);
6404 return 1;
6405 }
6406
6407 mAppData = MakeUnique<XREAppData>();
6408 rv = XRE_ParseAppData(appini, *mAppData);
6409 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6410 Output(true, "Couldn't read application.ini");
6411 return 1;
6412 }
6413
6414 appini->GetParent(getter_AddRefs(mAppData->directory));
6415 }
6416
6417 const char* appRemotingName = getenv("MOZ_APP_REMOTINGNAME");
6418 if (appRemotingName) {
6419 mAppData->remotingName = appRemotingName;
6420 } else if (!mAppData->remotingName) {
6421 mAppData->remotingName = mAppData->name;
6422 }
6423 // used throughout this file
6424 gAppData = mAppData.get();
6425
6426 nsCOMPtr<nsIFile> binFile;
6427 rv = XRE_GetBinaryPath(getter_AddRefs(binFile));
6428 NS_ENSURE_SUCCESS(rv, 1)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", "1", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6428); return 1; } } while (false)
;
6429
6430 rv = binFile->GetPath(gAbsoluteArgv0Path);
6431 NS_ENSURE_SUCCESS(rv, 1)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", "1", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6431); return 1; } } while (false)
;
6432
6433 if (!mAppData->xreDirectory) {
6434 nsCOMPtr<nsIFile> greDir;
6435
6436#if defined(MOZ_WIDGET_ANDROID)
6437 greDir = GreOmniPath(argc, argv);
6438 if (!greDir) {
6439 return 2;
6440 }
6441#else
6442 rv = binFile->GetParent(getter_AddRefs(greDir));
6443 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return 2;
6444#endif
6445
6446#ifdef XP_MACOSX
6447 nsCOMPtr<nsIFile> parent;
6448 greDir->GetParent(getter_AddRefs(parent));
6449 greDir = parent.forget();
6450 greDir->AppendNative("Resources"_ns);
6451#elif defined(XP_IOS)
6452 // FIXME: Consider looking up the GeckoView.framework bundle directly,
6453 // rather than deriving it from XRE_GetBinaryPath on iOS. This may be more
6454 // resilient especially once we properly bundle XUL into a separate
6455 // framework or support multiple embedders.
6456 rv = greDir->AppendNative("Frameworks"_ns);
6457 NS_ENSURE_SUCCESS(rv, 2)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", "2", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6457); return 2; } } while (false)
;
6458 rv = greDir->AppendNative("GeckoView.framework"_ns);
6459 NS_ENSURE_SUCCESS(rv, 2)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", "2", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6459); return 2; } } while (false)
;
6460 rv = greDir->AppendNative("Frameworks"_ns);
6461 NS_ENSURE_SUCCESS(rv, 2)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", "2", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6461); return 2; } } while (false)
;
6462#endif
6463
6464 mAppData->xreDirectory = greDir;
6465 }
6466
6467#if defined(MOZ_WIDGET_ANDROID)
6468 nsCOMPtr<nsIFile> dataDir;
6469 rv = binFile->GetParent(getter_AddRefs(dataDir));
6470 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return 2;
6471
6472 mAppData->directory = dataDir;
6473#else
6474 if (aConfig.appData && aConfig.appDataPath) {
6475 mAppData->xreDirectory->Clone(getter_AddRefs(mAppData->directory));
6476 mAppData->directory->AppendNative(nsDependentCString(aConfig.appDataPath));
6477 }
6478#endif
6479
6480 if (!mAppData->directory) {
6481 mAppData->directory = mAppData->xreDirectory;
6482 }
6483
6484#if defined(XP_WIN)
6485# if defined(MOZ_SANDBOX1)
6486 mAppData->sandboxBrokerServices = aConfig.sandboxBrokerServices;
6487# endif // defined(MOZ_SANDBOX)
6488
6489# if defined(_M_IX86) || defined(_M_X64)
6490 {
6491 DebugOnly<bool> result = WindowsMsctfInitialization();
6492 MOZ_ASSERT(result)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(result)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(result))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("result", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6492); AnnotateMozCrashReason("MOZ_ASSERT" "(" "result" ")"
); do { MOZ_CrashSequence(__null, 6492); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6493 }
6494# endif // _M_IX86 || _M_X64
6495
6496 // Bug 1924623: Detouring VariantClear resulted in a huge crash spike for
6497 // Thunderbird, so let's only do that for Firefox.
6498# ifdef MOZ_BUILD_APP_IS_BROWSER1
6499 {
6500 DebugOnly<bool> result = WindowsOleAut32Initialization();
6501 MOZ_ASSERT(result)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(result)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(result))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("result", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6501); AnnotateMozCrashReason("MOZ_ASSERT" "(" "result" ")"
); do { MOZ_CrashSequence(__null, 6501); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6502 }
6503# endif // MOZ_BUILD_APP_IS_BROWSER
6504
6505#endif // defined(XP_WIN)
6506
6507 // Once we unset the exception handler, we lose the ability to properly
6508 // detect hangs -- they show up as crashes. We do this as late as possible.
6509 // In particular, after ProcessRuntime is destroyed on Windows.
6510 auto unsetExceptionHandler = MakeScopeExit([&] {
6511 if (mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER(1 << 3)) {
6512 nsresult rv = CrashReporter::UnsetExceptionHandler();
6513 CrashReporter::OOPDeinit();
6514 return rv;
6515 }
6516 return NS_OK;
6517 });
6518
6519#if defined(MOZ_WIDGET_ANDROID)
6520 CrashReporter::SetCrashHelperPipes(aConfig.crashChildNotificationSocket,
6521 aConfig.crashHelperSocket);
6522#endif // defined(MOZ_WIDGET_ANDROID)
6523
6524 mozilla::AutoIOInterposer ioInterposerGuard;
6525 ioInterposerGuard.Init();
6526
6527#if defined(XP_WIN)
6528 // We should have already done this when we created the skeleton UI. However,
6529 // there is code in here which needs xul in order to work, like EnsureMTA. It
6530 // should be setup that running it again is safe.
6531 mozilla::mscom::ProcessRuntime msCOMRuntime;
6532#endif
6533
6534 // init
6535 bool exit = false;
6536 int result = XRE_mainInit(&exit);
6537 if (result != 0 || exit) return result;
6538
6539 // If we exit gracefully, remove the startup crash canary file.
6540 auto cleanup = MakeScopeExit([&]() -> nsresult {
6541 if (mProfLD) {
6542 nsCOMPtr<nsIFile> crashFile = MOZ_TRY(GetIncompleteStartupFile(mProfLD))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(GetIncompleteStartupFile(mProfLD)); if ((__builtin_expect(!!
(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
6543 crashFile->Remove(false);
6544 }
6545 return NS_OK;
6546 });
6547
6548 // startup
6549 result = XRE_mainStartup(&exit);
6550 if (result != 0 || exit) return result;
6551
6552 // Start the real application. We use |aInitJSContext = false| because
6553 // XRE_mainRun wants to initialize the JSContext after reading user prefs.
6554
6555 mScopedXPCOM = MakeUnique<ScopedXPCOMStartup>();
6556
6557 rv = mScopedXPCOM->Initialize(/* aInitJSContext = */ false);
6558 if (rv == NS_ERROR_OMNIJAR_CORRUPT) {
6559 if (XRE_IsParentProcess()
6560#ifdef MOZ_BACKGROUNDTASKS1
6561 && !mozilla::BackgroundTasks::IsBackgroundTaskMode()
6562#endif
6563 ) {
6564 Output(
6565 true,
6566 "The installation seems to be corrupt.\nPlease check your hardware "
6567 "and disk setup\nand/or re-install.\n");
6568 }
6569 MOZ_CRASH("NS_ERROR_OMNIJAR_CORRUPT")do { do { } while (false); MOZ_ReportCrash("" "NS_ERROR_OMNIJAR_CORRUPT"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 6569); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_ERROR_OMNIJAR_CORRUPT" ")"); do { MOZ_CrashSequence
(__null, 6569); __attribute__((nomerge)) ::abort(); } while (
false); } while (false)
;
6570 }
6571 NS_ENSURE_SUCCESS(rv, 1)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", "1", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6571); return 1; } } while (false)
;
6572
6573 // run!
6574 rv = XRE_mainRun();
6575 if (rv == NS_ERROR_OMNIJAR_OR_DIR_MISSING) {
6576 if (XRE_IsParentProcess()
6577#ifdef MOZ_BACKGROUNDTASKS1
6578 && !mozilla::BackgroundTasks::IsBackgroundTaskMode()
6579#endif
6580 ) {
6581 Output(true,
6582 "The installation seems to be incomplete.\nPlease check your "
6583 "hardware and disk setup\nand/or re-install.\n");
6584 }
6585 if (mozilla::IsPackagedBuild()) {
6586 // IsPackagedBuild just looks for omni.ja on disk. If we were able to
6587 // find and open it before but not to load the expected JS module from
6588 // it now, signal corruption.
6589 MOZ_CRASH("NS_ERROR_OMNIJAR_CORRUPT")do { do { } while (false); MOZ_ReportCrash("" "NS_ERROR_OMNIJAR_CORRUPT"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 6589); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_ERROR_OMNIJAR_CORRUPT" ")"); do { MOZ_CrashSequence
(__null, 6589); __attribute__((nomerge)) ::abort(); } while (
false); } while (false)
;
6590 }
6591 MOZ_CRASH("NS_ERROR_OMNIJAR_OR_DIR_MISSING")do { do { } while (false); MOZ_ReportCrash("" "NS_ERROR_OMNIJAR_OR_DIR_MISSING"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 6591); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_ERROR_OMNIJAR_OR_DIR_MISSING" ")"); do { MOZ_CrashSequence
(__null, 6591); __attribute__((nomerge)) ::abort(); } while (
false); } while (false)
;
6592 }
6593
6594#ifdef MOZ_X111
6595 XRE_CleanupX11ErrorHandler();
6596#endif
6597
6598 gAbsoluteArgv0Path.Truncate();
6599
6600#if defined(MOZ_HAS_REMOTE1)
6601 // Shut down the remote service. We must do this before calling LaunchChild
6602 // if we're restarting because otherwise the new instance will attempt to
6603 // remote to this instance.
6604 if (gRemoteService) {
6605 gRemoteService->ShutdownServer();
6606 gStartupLock = nullptr;
6607 gRemoteService = nullptr;
6608 }
6609#endif
6610
6611 mScopedXPCOM = nullptr;
6612
6613 // unlock the profile after ScopedXPCOMStartup object (xpcom)
6614 // has gone out of scope. see bug #386739 for more details
6615 mProfileLock->Unlock();
6616 gProfileLock = nullptr;
6617
6618 gLastAppVersion.Truncate();
6619 gLastAppBuildID.Truncate();
6620
6621#ifdef MOZ_WIDGET_GTK1
6622 // gdk_display_close also calls gdk_display_manager_set_default_display
6623 // appropriately when necessary.
6624 if (!gfxPlatform::IsHeadless()) {
6625# ifdef MOZ_WAYLAND1
6626 WaylandDisplayRelease();
6627 gWaylandProxy = nullptr;
6628# endif
6629 }
6630#endif
6631
6632 mozilla::AppShutdown::MaybeDoRestart();
6633
6634 XRE_DeinitCommandLine();
6635
6636 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6637 return 1;
6638 }
6639 return mozilla::AppShutdown::GetExitCode();
6640}
6641
6642void XRE_StopLateWriteChecks(void) { mozilla::StopLateWriteChecks(); }
6643
6644int XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig) {
6645 XREMain main;
6646
6647 int result = main.XRE_main(argc, argv, aConfig);
6648 mozilla::RecordShutdownEndTimeStamp();
6649#ifdef MOZ_BACKGROUNDTASKS1
6650 // This is well after the profile has been unlocked, so it's okay if this does
6651 // delete this background task's temporary profile.
6652 mozilla::BackgroundTasks::Shutdown();
6653#endif
6654 return result;
6655}
6656
6657nsresult XRE_InitCommandLine(int aArgc, char* aArgv[]) {
6658 nsresult rv = NS_OK;
6659
6660#if defined(XP_WIN)
6661 CommandLine::Init(aArgc, aArgv);
6662#else
6663
6664 // these leak on error, but that's OK: we'll just exit()
6665 char** canonArgs = new char*[aArgc];
6666
6667 // get the canonical version of the binary's path
6668 nsCOMPtr<nsIFile> binFile;
6669 rv = XRE_GetBinaryPath(getter_AddRefs(binFile));
6670 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return NS_ERROR_FAILURE;
6671
6672 nsAutoCString canonBinPath;
6673 rv = binFile->GetNativePath(canonBinPath);
6674 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return NS_ERROR_FAILURE;
6675
6676 canonArgs[0] = strdup(canonBinPath.get());
6677
6678 for (int i = 1; i < aArgc; ++i) {
6679 if (aArgv[i]) {
6680 canonArgs[i] = strdup(aArgv[i]);
6681 }
6682 }
6683
6684 NS_ASSERTION(!CommandLine::IsInitialized(), "Bad news!")do { if (!(!CommandLine::IsInitialized())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Bad news!", "!CommandLine::IsInitialized()", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6684); MOZ_PretendNoReturn(); } } while (0)
;
6685 CommandLine::Init(aArgc, canonArgs);
6686
6687 for (int i = 0; i < aArgc; ++i) free(canonArgs[i]);
6688 delete[] canonArgs;
6689#endif
6690
6691#if defined(MOZ_WIDGET_ANDROID)
6692 // gAppData is non-null iff this is the parent process. Otherwise,
6693 // the `-greomni`/`-appomni` flags are cross-platform and handled in
6694 // ContentProcess::Init.
6695 if (gAppData) {
6696 nsCOMPtr<nsIFile> greOmni = gAppData->xreDirectory;
6697 if (!greOmni) {
6698 return NS_ERROR_FAILURE;
6699 }
6700 mozilla::Omnijar::Init(greOmni, greOmni);
6701 MOZ_RELEASE_ASSERT(IsPackagedBuild(), "Android builds are always packaged")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsPackagedBuild())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsPackagedBuild()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("IsPackagedBuild()"
" (" "Android builds are always packaged" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6701); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "IsPackagedBuild()"
") (" "Android builds are always packaged" ")"); do { MOZ_CrashSequence
(__null, 6701); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6702 }
6703#endif
6704
6705 return rv;
6706}
6707
6708nsresult XRE_DeinitCommandLine() {
6709 nsresult rv = NS_OK;
6710
6711 CommandLine::Terminate();
6712
6713 return rv;
6714}
6715
6716GeckoProcessType XRE_GetProcessType() { return GetGeckoProcessType(); }
6717
6718const char* XRE_GetProcessTypeString() {
6719 return XRE_GeckoProcessTypeToString(XRE_GetProcessType());
6720}
6721
6722GeckoChildID XRE_GetChildID() { return GetGeckoChildID(); }
6723
6724bool XRE_IsE10sParentProcess() {
6725#ifdef MOZ_WIDGET_ANDROID
6726 return XRE_IsParentProcess() && BrowserTabsRemoteAutostart() &&
6727 mozilla::jni::IsAvailable();
6728#else
6729 return XRE_IsParentProcess() && BrowserTabsRemoteAutostart();
6730#endif
6731}
6732
6733#define GECKO_PROCESS_TYPE(enum_value, enum_name, string_name, proc_typename, \
6734 process_bin_type, procinfo_typename, \
6735 webidl_typename, allcaps_name) \
6736 bool XRE_Is##proc_typename##Process() { \
6737 return XRE_GetProcessType() == GeckoProcessType_##enum_name; \
6738 }
6739#include "mozilla/GeckoProcessTypes.h"
6740#undef GECKO_PROCESS_TYPE
6741
6742bool XRE_UseNativeEventProcessing() {
6743#if defined(XP_WIN)
6744 // If win32k is locked down we can't use native event processing.
6745 if (IsWin32kLockedDown()) {
6746 return false;
6747 }
6748#endif
6749
6750 switch (XRE_GetProcessType()) {
6751#if defined(XP_DARWIN) || defined(XP_WIN)
6752 case GeckoProcessType_RDD:
6753 case GeckoProcessType_Socket:
6754 return false;
6755 case GeckoProcessType_Utility: {
6756# if defined(XP_WIN)
6757 auto upc = mozilla::ipc::UtilityProcessChild::Get();
6758 MOZ_ASSERT(upc)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(upc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(upc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("upc", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6758); AnnotateMozCrashReason("MOZ_ASSERT" "(" "upc" ")"); do
{ MOZ_CrashSequence(__null, 6758); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
6759
6760 using SboxKind = mozilla::ipc::SandboxingKind;
6761 // These processes are used as external hosts for accessing Windows
6762 // APIs which (may) require a Windows native event loop.
6763 return upc->mSandbox == SboxKind::WINDOWS_UTILS ||
6764 upc->mSandbox == SboxKind::WINDOWS_FILE_DIALOG;
6765# else
6766 return false;
6767# endif // defined(XP_WIN)
6768 }
6769#endif // defined(XP_DARWIN) || defined(XP_WIN)
6770 case GeckoProcessType_GMPlugin:
6771 return mozilla::gmp::GMPProcessChild::UseNativeEventProcessing();
6772 case GeckoProcessType_Content:
6773#if defined(XP_DARWIN)
6774 return false;
6775#else
6776 return StaticPrefs::dom_ipc_useNativeEventProcessing_content();
6777#endif // defined (XP_DARWIN)
6778 default:
6779 return true;
6780 }
6781}
6782
6783namespace mozilla {
6784
6785uint32_t GetMaxWebProcessCount() {
6786 // multiOptOut is in int to allow us to run multiple experiments without
6787 // introducing multiple prefs a la the autostart.N prefs.
6788 if (Preferences::GetInt("dom.ipc.multiOptOut", 0) >=
6789 nsIXULRuntime::E10S_MULTI_EXPERIMENT) {
6790 return 1;
6791 }
6792
6793 const char* optInPref = "dom.ipc.processCount";
6794 uint32_t optInPrefValue = Preferences::GetInt(optInPref, 1);
6795 return std::max(1u, optInPrefValue);
6796}
6797
6798const char* PlatformBuildID() { return gToolkitBuildID; }
6799
6800} // namespace mozilla
6801
6802void SetupErrorHandling(const char* progname) {
6803#ifdef XP_WIN
6804 /* On Windows XPSP3 and Windows Vista if DEP is configured off-by-default
6805 we still want DEP protection: enable it explicitly and programmatically.
6806
6807 This function is not available on WinXPSP2 so we dynamically load it.
6808 */
6809
6810 HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll");
6811 SetProcessDEPPolicyFunc _SetProcessDEPPolicy =
6812 (SetProcessDEPPolicyFunc)GetProcAddress(kernel32, "SetProcessDEPPolicy");
6813 if (_SetProcessDEPPolicy) _SetProcessDEPPolicy(PROCESS_DEP_ENABLE);
6814
6815 // Suppress the "DLL Foo could not be found" dialog, such that if dependent
6816 // libraries (such as GDI+) are not preset, we gracefully fail to load those
6817 // XPCOM components, instead of being ungraceful.
6818 UINT realMode = SetErrorMode(0);
6819 realMode |= SEM_FAILCRITICALERRORS;
6820 // If XRE_NO_WINDOWS_CRASH_DIALOG is set, suppress displaying the "This
6821 // application has crashed" dialog box. This is mainly useful for
6822 // automated testing environments, e.g. tinderbox, where there's no need
6823 // for a dozen of the dialog boxes to litter the console
6824 if (getenv("XRE_NO_WINDOWS_CRASH_DIALOG"))
6825 realMode |= SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX;
6826
6827 SetErrorMode(realMode);
6828
6829#endif
6830
6831 InstallSignalHandlers(progname);
6832
6833 // Unbuffer stdout, needed for tinderbox tests.
6834 setbuf(stdoutstdout, nullptr);
6835}
6836
6837static bool gRunSelfAsContentProc = false;
6838
6839void XRE_EnableSameExecutableForContentProc() {
6840 if (!PR_GetEnv("MOZ_SEPARATE_CHILD_PROCESS")) {
6841 gRunSelfAsContentProc = true;
6842 }
6843}
6844
6845mozilla::BinPathType XRE_GetChildProcBinPathType(
6846 GeckoProcessType aProcessType) {
6847 MOZ_ASSERT(aProcessType != GeckoProcessType_Default)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aProcessType != GeckoProcessType_Default)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aProcessType != GeckoProcessType_Default))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aProcessType != GeckoProcessType_Default"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 6847); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aProcessType != GeckoProcessType_Default" ")"
); do { MOZ_CrashSequence(__null, 6847); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6848
6849 if (!gRunSelfAsContentProc) {
6850 return BinPathType::PluginContainer;
6851 }
6852
6853#ifdef XP_WIN
6854 // Removing this pref and always using the parent binary, along with other
6855 // related clean up work, is tracked in Bug 2014843.
6856 if (StaticPrefs::dom_ipc_alwaysUseParentBinary()) {
6857 return BinPathType::Self;
6858 }
6859
6860 // On Windows, plugin-container may or may not be used depending on
6861 // the process type (e.g., actual plugins vs. content processes)
6862 switch (aProcessType) {
6863# define GECKO_PROCESS_TYPE(enum_value, enum_name, string_name, \
6864 proc_typename, process_bin_type, \
6865 procinfo_typename, webidl_typename, allcaps_name) \
6866 case GeckoProcessType_##enum_name: \
6867 return BinPathType::process_bin_type;
6868# include "mozilla/GeckoProcessTypes.h"
6869# undef GECKO_PROCESS_TYPE
6870 default:
6871 return BinPathType::PluginContainer;
6872 }
6873#else
6874 // On (non-macOS) Unix, plugin-container isn't used (except in cases
6875 // like xpcshell that are handled by the gRunSelfAsContentProc check
6876 // above). It isn't necessary the way it is on other platforms, and
6877 // it interferes with using the fork server.
6878 return BinPathType::Self;
6879#endif
6880}
6881
6882// From mozglue/static/rust/lib.rs
6883extern "C" void install_rust_hooks();
6884
6885struct InstallRustHooks {
6886 InstallRustHooks() { install_rust_hooks(); }
6887};
6888
6889MOZ_RUNINIT InstallRustHooks sInstallRustHooks;
6890
6891#ifdef MOZ_ASAN_REPORTER
6892void setASanReporterPath(nsIFile* aDir) {
6893 nsCOMPtr<nsIFile> dir;
6894 aDir->Clone(getter_AddRefs(dir));
6895
6896 dir->Append(u"asan"_ns);
6897 nsresult rv = dir->Create(nsIFile::DIRECTORY_TYPE, 0700);
6898 if (NS_WARN_IF(NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS)NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))) && rv != NS_ERROR_FILE_ALREADY_EXISTS, "NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 6898)
) {
6899 MOZ_CRASH("[ASan Reporter] Unable to create crash directory.")do { do { } while (false); MOZ_ReportCrash("" "[ASan Reporter] Unable to create crash directory."
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 6899); AnnotateMozCrashReason
("MOZ_CRASH(" "[ASan Reporter] Unable to create crash directory."
")"); do { MOZ_CrashSequence(__null, 6899); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
6900 }
6901
6902 dir->Append(u"ff_asan_log"_ns);
6903
6904# ifdef XP_WIN
6905 nsAutoString nspathW;
6906 rv = dir->GetPath(nspathW);
6907 NS_ConvertUTF16toUTF8 nspath(nspathW);
6908# else
6909 nsAutoCString nspath;
6910 rv = dir->GetNativePath(nspath);
6911# endif
6912 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6913 MOZ_CRASH("[ASan Reporter] Unable to get native path for crash directory.")do { do { } while (false); MOZ_ReportCrash("" "[ASan Reporter] Unable to get native path for crash directory."
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 6913); AnnotateMozCrashReason
("MOZ_CRASH(" "[ASan Reporter] Unable to get native path for crash directory."
")"); do { MOZ_CrashSequence(__null, 6913); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
6914 }
6915
6916 __sanitizer_set_report_path(nspath.get());
6917}
6918#endif

/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/CmdLineAndEnvUtils.h

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5#ifndef mozilla_CmdLineAndEnvUtils_h
6#define mozilla_CmdLineAndEnvUtils_h
7
8// NB: This code may be used outside of xul and thus must not depend on XPCOM
9
10#if defined(MOZILLA_INTERNAL_API1)
11# include "prenv.h"
12# include "prprf.h"
13# include <string.h>
14#endif
15
16#if defined(XP_WIN)
17# include "mozilla/UniquePtr.h"
18# include "mozilla/WinHeaderOnlyUtils.h"
19
20# include <wchar.h>
21# include <windows.h>
22#endif // defined(XP_WIN)
23
24#include "mozilla/Maybe.h"
25#include "mozilla/MemoryChecking.h"
26#include "mozilla/TypedEnumBits.h"
27
28#include <ctype.h>
29#include <stdint.h>
30#include <stdlib.h>
31
32#ifndef NS_NO_XPCOM
33# include "nsIFile.h"
34# include "mozilla/AlreadyAddRefed.h"
35#endif
36
37// Undo X11/X.h's definition of None
38#undef None
39
40namespace mozilla {
41
42enum ArgResult {
43 ARG_NONE = 0,
44 ARG_FOUND = 1,
45 ARG_BAD = 2 // you wanted a param, but there isn't one or you didn't want a
46 // param and there is one.
47};
48
49template <typename CharT>
50inline void RemoveArg(int& argc, CharT** argv) {
51 do {
52 *argv = *(argv + 1);
53 ++argv;
54 } while (*argv);
55
56 --argc;
57}
58
59namespace internal {
60
61#if 'a' == '\x61'
62// Valid option characters must have the same representation in every locale
63// (which is true for most of ASCII, barring \x5C and \x7E).
64static inline constexpr bool isValidOptionCharacter(char c) {
65 // We specifically avoid the use of `islower` here; it's locale-dependent, and
66 // may return true for non-ASCII values in some locales.
67 return ('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || c == '-';
68};
69
70// Convert uppercase to lowercase, locale-insensitively.
71static inline constexpr char toLowercase(char c) {
72 // We specifically avoid the use of `tolower` here; it's locale-dependent, and
73 // may output ASCII values for non-ASCII input (or vice versa) in some
74 // locales.
75 return ('A' <= c && c <= 'Z') ? char(c | ' ') : c;
76};
77
78// Convert a CharT to a char, ensuring that no CharT is mapped to any valid
79// option character except the unique CharT naturally corresponding thereto.
80template <typename CharT>
81static inline constexpr char toNarrow(CharT c) {
82 // confirmed to compile down to nothing when `CharT` is `char`
83 return (c & static_cast<CharT>(0xff)) == c ? c : 0xff;
84};
85#else
86// The target system's character set isn't even ASCII-compatible. If you're
87// porting Gecko to such a platform, you'll have to implement these yourself.
88# error Character conversion functions not implemented for this platform.
89#endif
90
91// Case-insensitively compare a string taken from the command-line (`mixedstr`)
92// to the text of some known command-line option (`lowerstr`).
93// Returns true if mixedstr starts with lowerstr.
94template <typename CharT>
95static inline bool ArgStartsWith(const CharT* mixedstr, const char* lowerstr) {
96 while (*lowerstr) {
97 if (!*mixedstr) {
98 return false; // mixedstr is shorter
99 }
100
101 // Non-ASCII strings may compare incorrectly depending on the user's locale.
102 // Some ASCII-safe characters are also dispermitted for semantic reasons
103 // and simplicity.
104 if (!isValidOptionCharacter(*lowerstr)) {
105 return false;
106 }
107
108 if (toLowercase(toNarrow(*mixedstr)) != *lowerstr) {
109 return false; // no match
110 }
111
112 ++lowerstr;
113 ++mixedstr;
114 }
115
116 return true;
117}
118
119// Case-insensitively compare a string taken from the command-line (`mixedstr`)
120// to the text of some known command-line option (`lowerstr`).
121template <typename CharT>
122static inline bool strimatch(const char* lowerstr, const CharT* mixedstr) {
123 if (ArgStartsWith(mixedstr, lowerstr)) {
124 return *(mixedstr + strlen(lowerstr)) == '\0';
125 }
126
127 return false;
128}
129
130// Given a command-line argument, return Nothing if it isn't structurally a
131// command-line option, and Some(<the option text>) if it is.
132template <typename CharT>
133mozilla::Maybe<const CharT*> ReadAsOption(const CharT* str) {
134 if (!str) {
135 return Nothing();
136 }
137 if (*str == '-') {
138 str++;
139 if (*str == '-') {
140 str++;
141 }
142 return Some(str);
143 }
144#ifdef XP_WIN
145 if (*str == '/') {
146 return Some(str + 1);
147 }
148#endif
149 return Nothing();
150}
151
152} // namespace internal
153
154using internal::ArgStartsWith;
155using internal::strimatch;
156
157const wchar_t kCommandLineDelimiter[] = L" \t";
158
159enum class CheckArgFlag : uint32_t {
160 None = 0,
161 // (1 << 0) Used to be CheckOSInt
162 RemoveArg = (1 << 1) // Remove the argument from the argv array.
163};
164
165MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CheckArgFlag)inline constexpr mozilla::CastableTypedEnumResult<CheckArgFlag
> operator |( CheckArgFlag a, CheckArgFlag b) { typedef mozilla
::CastableTypedEnumResult<CheckArgFlag> Result; typedef
mozilla::detail::UnsignedIntegerTypeForEnum<CheckArgFlag>
::Type U; return Result(CheckArgFlag(U(a) | U(b))); } inline CheckArgFlag
& operator |=(CheckArgFlag & a, CheckArgFlag b) { return
a = a | b; } inline constexpr mozilla::CastableTypedEnumResult
<CheckArgFlag> operator &( CheckArgFlag a, CheckArgFlag
b) { typedef mozilla::CastableTypedEnumResult<CheckArgFlag
> Result; typedef mozilla::detail::UnsignedIntegerTypeForEnum
<CheckArgFlag>::Type U; return Result(CheckArgFlag(U(a)
& U(b))); } inline CheckArgFlag& operator &=(CheckArgFlag
& a, CheckArgFlag b) { return a = a & b; } inline constexpr
mozilla::CastableTypedEnumResult<CheckArgFlag> operator
^( CheckArgFlag a, CheckArgFlag b) { typedef mozilla::CastableTypedEnumResult
<CheckArgFlag> Result; typedef mozilla::detail::UnsignedIntegerTypeForEnum
<CheckArgFlag>::Type U; return Result(CheckArgFlag(U(a)
^ U(b))); } inline CheckArgFlag& operator ^=(CheckArgFlag
& a, CheckArgFlag b) { return a = a ^ b; } inline constexpr
mozilla::CastableTypedEnumResult<CheckArgFlag> operator
~(CheckArgFlag a) { typedef mozilla::CastableTypedEnumResult<
CheckArgFlag> Result; typedef mozilla::detail::UnsignedIntegerTypeForEnum
<CheckArgFlag>::Type U; return Result(CheckArgFlag(~(U(
a)))); }
166
167/**
168 * Check for a commandline flag. If the flag takes a parameter, the
169 * parameter is returned in aParam. Flags may be in the form -arg, --arg,
170 * /arg (on win32), or in the form -arg=<data> or --arg=<data>.
171 *
172 * @param aArgc The argc value.
173 * @param aArgv The original argv.
174 * @param aArg the parameter to check. Must be lowercase.
175 * @param aParam if non-null, the -arg <data> or -arg=<data> will be stored in
176 * this pointer. This is *not* allocated, but rather a pointer to the argv data
177 * or the value after '='.
178 * @param aFlags Flags @see CheckArgFlag
179 */
180template <typename CharT>
181inline ArgResult CheckArg(int& aArgc, CharT** aArgv, const char* aArg,
182 const CharT** aParam = nullptr,
183 CheckArgFlag aFlags = CheckArgFlag::RemoveArg) {
184 using internal::ReadAsOption;
185 MOZ_ASSERT(aArgv && aArg)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aArgv && aArg)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aArgv && aArg))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("aArgv && aArg"
, "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/CmdLineAndEnvUtils.h"
, 185); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aArgv && aArg"
")"); do { MOZ_CrashSequence(__null, 185); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
186
187 CharT** curarg = aArgv + 1; // skip argv[0]
188 ArgResult ar = ARG_NONE;
189
190 while (*curarg) {
191 if (const auto arg = ReadAsOption(*curarg)) {
192 if (ArgStartsWith(arg.value(), aArg)) {
193 const auto nextChar = arg.value() + strlen(aArg);
194 if (*nextChar == 0) {
195 // Exact match: --flag or -flag. Remove this from aArgv if the
196 // appropriate flag is set.
197 if (aFlags & CheckArgFlag::RemoveArg) {
198 RemoveArg(aArgc, curarg);
199 } else {
200 ++curarg;
201 }
202
203 if (!aParam) {
204 ar = ARG_FOUND;
205 break;
206 }
207
208 if (*curarg) {
209 if (ReadAsOption(*curarg)) {
210 return ARG_BAD;
211 }
212
213 *aParam = *curarg;
214
215 // This argument also has a value as a separate command line
216 // argument so we must remove this from aArgv as well.
217 if (aFlags & CheckArgFlag::RemoveArg) {
218 RemoveArg(aArgc, curarg);
219 }
220
221 ar = ARG_FOUND;
222 break;
223 }
224
225 return ARG_BAD;
226 }
227
228 if (*nextChar == '=') {
229 if (aParam) {
230 // Here we have an argument with a value, like --foo=bar or
231 // -foo=bar. We need to pass the "value" part of it to `aParam` and
232 // then remove only one item from `aArgv` if the relevant flag was
233 // passed.
234 *aParam = nextChar + 1; // value after '='
235
236 if (aFlags & CheckArgFlag::RemoveArg) {
237 RemoveArg(aArgc, curarg);
238 }
239
240 ar = ARG_FOUND;
241 } else {
242 ar = ARG_BAD;
243 }
244
245 break;
246 }
247 }
248 }
249
250 ++curarg;
251 }
252
253 return ar;
254}
255
256template <typename CharT>
257inline ArgResult CheckArg(int& aArgc, CharT** aArgv, const char* aArg,
258 std::nullptr_t,
259 CheckArgFlag aFlags = CheckArgFlag::RemoveArg) {
260 return CheckArg<CharT>(aArgc, aArgv, aArg,
261 static_cast<const CharT**>(nullptr), aFlags);
262}
263
264namespace internal {
265// template <typename T>
266// constexpr bool IsStringRange =
267// std::convertible_to<std::ranges::range_value_t<T>, const char *>;
268
269template <typename CharT, typename ListT>
270// requires IsStringRange<ListT>
271bool MatchesAnyOf(CharT const* unknown, ListT const& known) {
272 for (const char* k : known) {
273 if (strimatch(k, unknown)) {
274 return true;
275 }
276 }
277 return false;
278}
279
280template <typename CharT, typename ReqContainerT, typename OptContainerT>
281// requires IsStringRange<ReqContainerT> && IsStringRange<OptContainerT>
282inline bool EnsureCommandlineSafeImpl(int aArgc, CharT** aArgv,
283 ReqContainerT const& requiredParams,
284 OptContainerT const& optionalParams) {
285 // We expect either no -osint, or the full commandline to be:
286 //
287 // app -osint [<optional-param>...] <required-param> <required-argument>
288 //
289 // Otherwise, we abort to avoid abuse of other command-line handlers from apps
290 // that do a poor job escaping links they give to the OS.
291 //
292 // Note that the above implies that optional parameters do not themselves take
293 // arguments. This is a security feature, to prevent the possible injection of
294 // additional parameters via such arguments. (See, e.g., bug 384384.)
295
296 static constexpr const char* osintLit = "osint";
297
298 // If "-osint" (or the equivalent) is not present, then this is trivially
299 // satisfied.
300 if (CheckArg(aArgc, aArgv, osintLit, nullptr, CheckArgFlag::None) !=
301 ARG_FOUND) {
302 return true;
303 }
304
305 // There should be at least 4 items present:
306 // <app name> -osint <required param> <arg>.
307 if (aArgc < 4) {
308 return false;
309 }
310
311 // The first parameter must be osint.
312 const auto arg1 = ReadAsOption(aArgv[1]);
313 if (!arg1) return false;
314 if (!strimatch(osintLit, arg1.value())) {
315 return false;
316 }
317 // Following this is any number of optional parameters, terminated by a
318 // required parameter.
319 int pos = 2;
320 while (true) {
321 if (pos >= aArgc) return false;
322
323 auto const arg = ReadAsOption(aArgv[pos]);
324 if (!arg) return false;
325
326 if (MatchesAnyOf(arg.value(), optionalParams)) {
327 ++pos;
328 continue;
329 }
330
331 if (MatchesAnyOf(arg.value(), requiredParams)) {
332 ++pos;
333 break;
334 }
335
336 return false;
337 }
338
339 // There must be one argument remaining...
340 if (pos + 1 != aArgc) return false;
341 // ... which must not be another option.
342 if (ReadAsOption(aArgv[pos])) {
343 return false;
344 }
345
346 // Nothing ill-formed was passed.
347 return true;
348}
349
350// C (and so C++) disallows empty arrays. Rather than require callers to jump
351// through hoops to specify an empty optional-argument list, allow either its
352// omission or its specification as `nullptr`, and do the hoop-jumping here.
353//
354// No such facility is provided for requiredParams, which must have at least one
355// entry.
356template <typename CharT, typename ReqContainerT>
357inline bool EnsureCommandlineSafeImpl(int aArgc, CharT** aArgv,
358 ReqContainerT const& requiredParams,
359 std::nullptr_t _ = nullptr) {
360 struct {
361 inline const char** begin() const { return nullptr; }
362 inline const char** end() const { return nullptr; }
363 } emptyContainer;
364 return EnsureCommandlineSafeImpl(aArgc, aArgv, requiredParams,
365 emptyContainer);
366}
367} // namespace internal
368
369template <typename CharT, typename ReqContainerT,
370 typename OptContainerT = std::nullptr_t>
371inline void EnsureCommandlineSafe(
372 int aArgc, CharT** aArgv, ReqContainerT const& requiredParams,
373 OptContainerT const& optionalParams = nullptr) {
374 if (!internal::EnsureCommandlineSafeImpl(aArgc, aArgv, requiredParams,
375 optionalParams)) {
376 exit(127);
377 }
378}
379
380#if defined(XP_WIN)
381namespace internal {
382
383/**
384 * Attempt to copy the string `s` (considered as a command-line argument) into
385 * the buffer `d` with all necessary escaping and quoting. Returns the number of
386 * characters written.
387 *
388 * If `d` is NULL, doesn't actually write anything to `d`, and merely returns
389 * the number of characters that _would_ have been written.
390 *
391 * (This moderately-awkward conflation ensures that the pre-allocation counting
392 * step and post-allocation copying step use the same algorithm.)
393 */
394inline size_t CopyArgImpl_(wchar_t* d, const wchar_t* s) {
395 size_t len = 0;
396
397 bool const actuallyCopy = d != nullptr;
398 auto const appendChar = [&](wchar_t c) {
399 if (actuallyCopy) {
400 *d++ = c;
401 }
402 len++;
403 };
404
405 bool hasDoubleQuote = wcschr(s, L'"') != nullptr;
406 // Only add doublequotes if...
407 bool addDoubleQuotes =
408 // ... the string is empty, or...
409 *s == '\0' ||
410 // ... the string contains a space or a tab.
411 wcspbrk(s, kCommandLineDelimiter) != nullptr;
412
413 if (addDoubleQuotes) {
414 appendChar('"');
415 }
416
417 if (hasDoubleQuote) {
418 size_t backslashes = 0;
419 while (*s) {
420 if (*s == '\\') {
421 ++backslashes;
422 } else {
423 if (*s == '"') {
424 // Escape the doublequote and all backslashes preceding the
425 // doublequote
426 for (size_t i = 0; i <= backslashes; ++i) {
427 appendChar('\\');
428 }
429 }
430
431 backslashes = 0;
432 }
433
434 appendChar(*s);
435 ++s;
436 }
437 } else {
438 // optimization: just blit
439 auto const src_len = wcslen(s);
440 if (actuallyCopy) {
441 ::wcscpy(d, s);
442 d += src_len;
443 }
444 len += src_len;
445 }
446
447 if (addDoubleQuotes) {
448 appendChar('"');
449 }
450
451 return len;
452}
453
454/**
455 * Compute the space required for the serialized form of this argument. Includes
456 * any additional space needed for quotes and backslash-escapes.
457 */
458inline size_t ArgStrLen(const wchar_t* s) { return CopyArgImpl_(nullptr, s); }
459
460/**
461 * Copy string "s" to string "d", quoting the argument as appropriate and
462 * escaping doublequotes along with any backslashes that immediately precede
463 * doublequotes.
464 * The CRT parses this to retrieve the original argc/argv that we meant,
465 * see STDARGV.C in the MSVC CRT sources.
466 *
467 * @return the end of the string
468 */
469inline wchar_t* ArgToString(wchar_t* d, const wchar_t* s) {
470 return d + CopyArgImpl_(d, s);
471}
472
473} // namespace internal
474
475/**
476 * Creates a command line from a list of arguments.
477 *
478 * @param argc Number of elements in |argv|
479 * @param argv Array of arguments
480 * @param aArgcExtra Number of elements in |aArgvExtra|
481 * @param aArgvExtra Optional array of arguments to be appended to the resulting
482 * command line after those provided by |argv|.
483 */
484inline UniquePtr<wchar_t[]> MakeCommandLine(
485 int argc, const wchar_t* const* argv, int aArgcExtra = 0,
486 const wchar_t* const* aArgvExtra = nullptr) {
487 int i;
488 size_t len = 0;
489
490 // The + 1 for each argument reserves space for either a ' ' or the null
491 // terminator, depending on the position of the argument.
492 for (i = 0; i < argc; ++i) {
493 len += internal::ArgStrLen(argv[i]) + 1;
494 }
495
496 for (i = 0; i < aArgcExtra; ++i) {
497 len += internal::ArgStrLen(aArgvExtra[i]) + 1;
498 }
499
500 // Protect against callers that pass 0 arguments
501 if (len == 0) {
502 len = 1;
503 }
504
505 auto s = MakeUnique<wchar_t[]>(len);
506
507 int totalArgc = argc + aArgcExtra;
508
509 wchar_t* c = s.get();
510 for (i = 0; i < argc; ++i) {
511 c = internal::ArgToString(c, argv[i]);
512 if (i + 1 != totalArgc) {
513 *c = ' ';
514 ++c;
515 }
516 }
517
518 for (i = 0; i < aArgcExtra; ++i) {
519 c = internal::ArgToString(c, aArgvExtra[i]);
520 if (i + 1 != aArgcExtra) {
521 *c = ' ';
522 ++c;
523 }
524 }
525
526 *c = '\0';
527
528 return s;
529}
530
531inline bool SetArgv0ToFullBinaryPath(wchar_t* aArgv[]) {
532 if (!aArgv) {
533 return false;
534 }
535
536 UniquePtr<wchar_t[]> newArgv_0(GetFullBinaryPath());
537 if (!newArgv_0) {
538 return false;
539 }
540
541 // We intentionally leak newArgv_0 into argv[0]
542 aArgv[0] = newArgv_0.release();
543 MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(aArgv[0]);
544 return true;
545}
546
547# if defined(MOZILLA_INTERNAL_API1)
548// This class converts a command line string into an array of the arguments.
549// It's basically the opposite of MakeCommandLine. However, the behavior is
550// different from ::CommandLineToArgvW in several ways, such as escaping a
551// backslash or quoting an argument containing whitespaces. This satisfies
552// the examples at:
553// https://docs.microsoft.com/en-us/cpp/cpp/main-function-command-line-args#results-of-parsing-command-lines
554// https://docs.microsoft.com/en-us/previous-versions/17w5ykft(v=vs.85)
555template <typename T>
556class CommandLineParserWin final {
557 int mArgc;
558 T** mArgv;
559
560 void Release() {
561 if (mArgv) {
562 while (mArgc) {
563 delete[] mArgv[--mArgc];
564 }
565 delete[] mArgv;
566 mArgv = nullptr;
567 }
568 }
569
570 public:
571 CommandLineParserWin() : mArgc(0), mArgv(nullptr) {}
572 ~CommandLineParserWin() { Release(); }
573
574 CommandLineParserWin(const CommandLineParserWin&) = delete;
575 CommandLineParserWin(CommandLineParserWin&&) = delete;
576 CommandLineParserWin& operator=(const CommandLineParserWin&) = delete;
577 CommandLineParserWin& operator=(CommandLineParserWin&&) = delete;
578
579 int Argc() const { return mArgc; }
580 const T* const* Argv() const { return mArgv; }
581
582 // Returns the number of characters handled
583 int HandleCommandLine(const nsTSubstring<T>& aCmdLineString) {
584 Release();
585
586 if (aCmdLineString.IsEmpty()) {
587 return 0;
588 }
589
590 int justCounting = 1;
591 // Flags, etc.
592 int init = 1;
593 int between, quoted, bSlashCount;
594 const T* p;
595 const T* const pEnd = aCmdLineString.EndReading();
596 nsTAutoString<T> arg;
597
598 // We loop if we've not finished the second pass through.
599 while (1) {
600 // Initialize if required.
601 if (init) {
602 p = aCmdLineString.BeginReading();
603 between = 1;
604 mArgc = quoted = bSlashCount = 0;
605
606 init = 0;
607 }
608
609 const T charCurr = (p < pEnd) ? *p : 0;
610 const T charNext = (p + 1 < pEnd) ? *(p + 1) : 0;
611
612 if (between) {
613 // We are traversing whitespace between args.
614 // Check for start of next arg.
615 if (charCurr != 0 && !wcschr(kCommandLineDelimiter, charCurr)) {
616 // Start of another arg.
617 between = 0;
618 arg.Truncate();
619 switch (charCurr) {
620 case '\\':
621 // Count the backslash.
622 bSlashCount = 1;
623 break;
624 case '"':
625 // Remember we're inside quotes.
626 quoted = 1;
627 break;
628 default:
629 // Add character to arg.
630 arg += charCurr;
631 break;
632 }
633 } else {
634 // Another space between args, ignore it.
635 }
636 } else {
637 // We are processing the contents of an argument.
638 // Check for whitespace or end.
639 if (charCurr == 0 ||
640 (!quoted && wcschr(kCommandLineDelimiter, charCurr))) {
641 // Process pending backslashes (interpret them
642 // literally since they're not followed by a ").
643 while (bSlashCount) {
644 arg += '\\';
645 bSlashCount--;
646 }
647 // End current arg.
648 if (!justCounting) {
649 mArgv[mArgc] = new T[arg.Length() + 1];
650 memcpy(mArgv[mArgc], arg.get(), (arg.Length() + 1) * sizeof(T));
651 }
652 mArgc++;
653 // We're now between args.
654 between = 1;
655 } else {
656 // Still inside argument, process the character.
657 switch (charCurr) {
658 case '"':
659 // First, digest preceding backslashes (if any).
660 while (bSlashCount > 1) {
661 // Put one backsplash in arg for each pair.
662 arg += '\\';
663 bSlashCount -= 2;
664 }
665 if (bSlashCount) {
666 // Quote is literal.
667 arg += '"';
668 bSlashCount = 0;
669 } else {
670 // Quote starts or ends a quoted section.
671 if (quoted) {
672 // Check for special case of consecutive double
673 // quotes inside a quoted section.
674 if (charNext == '"') {
675 // This implies a literal double-quote. Fake that
676 // out by causing next double-quote to look as
677 // if it was preceded by a backslash.
678 bSlashCount = 1;
679 } else {
680 quoted = 0;
681 }
682 } else {
683 quoted = 1;
684 }
685 }
686 break;
687 case '\\':
688 // Add to count.
689 bSlashCount++;
690 break;
691 default:
692 // Accept any preceding backslashes literally.
693 while (bSlashCount) {
694 arg += '\\';
695 bSlashCount--;
696 }
697 // Just add next char to the current arg.
698 arg += charCurr;
699 break;
700 }
701 }
702 }
703
704 // Check for end of input.
705 if (charCurr) {
706 // Go to next character.
707 p++;
708 } else {
709 // If on first pass, go on to second.
710 if (justCounting) {
711 // Allocate argv array.
712 mArgv = new T*[mArgc];
713
714 // Start second pass
715 justCounting = 0;
716 init = 1;
717 } else {
718 // Quit.
719 break;
720 }
721 }
722 }
723
724 return p - aCmdLineString.BeginReading();
725 }
726};
727# endif // defined(MOZILLA_INTERNAL_API)
728
729#endif // defined(XP_WIN)
730
731// SaveToEnv and EnvHasValue are only available on Windows or when
732// MOZILLA_INTERNAL_API is defined
733#if defined(MOZILLA_INTERNAL_API1) || defined(XP_WIN)
734
735// Save literal putenv string to environment variable.
736MOZ_NEVER_INLINE__attribute__((noinline)) inline void SaveToEnv(const char* aEnvString) {
737# if defined(MOZILLA_INTERNAL_API1)
738 char* expr = strdup(aEnvString);
31
Memory is allocated
739 if (expr) {
32
Assuming 'expr' is non-null
33
Taking true branch
740 PR_SetEnv(expr);
741 }
742
743 // We intentionally leak |expr| here since it is required by PR_SetEnv.
744 MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(expr);
745# elif defined(XP_WIN)
746 // This is the same as the NSPR implementation
747 // (Note that we don't need to do a strdup for this case; the CRT makes a
748 // copy)
749 _putenv(aEnvString);
750# endif
751}
34
Potential leak of memory pointed to by 'expr'
752
753inline bool EnvHasValue(const char* aVarName) {
754# if defined(MOZILLA_INTERNAL_API1)
755 const char* val = PR_GetEnv(aVarName);
756 return val && *val;
757# elif defined(XP_WIN)
758 // This is the same as the NSPR implementation
759 const char* val = getenv(aVarName);
760 return val && *val;
761# endif
762}
763
764#endif // end windows/internal_api-only definitions
765
766#ifndef NS_NO_XPCOM
767already_AddRefed<nsIFile> GetFileFromEnv(const char* name);
768#endif
769
770} // namespace mozilla
771
772#endif // mozilla_CmdLineAndEnvUtils_h