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