Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/mozilla/CmdLineAndEnvUtils.h
Warning:line 710, 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 -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=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/toolkit/xre -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/toolkit/xre -resource-dir /usr/lib/llvm-19/lib/clang/19 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D 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="132.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=132.0a1 -D MOZ_APP_VERSION_DISPLAY=132.0a1 -D APP_VERSION=132.0a1 -D APP_ID={ec8030f7-c20a-464f-9b0e-13a3a9e97384} -D MOZ_BUILD_APP_IS_BROWSER -D MAR_NSS -D TOPOBJDIR=/var/lib/jenkins/workspace/firefox-scan-build/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 /var/lib/jenkins/workspace/firefox-scan-build/toolkit/xre -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/toolkit/xre -I /var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/remote -I /var/lib/jenkins/workspace/firefox-scan-build/widget -I /var/lib/jenkins/workspace/firefox-scan-build/widget/gtk -I /var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/printingui -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /var/lib/jenkins/workspace/firefox-scan-build/ipc/chromium/src -I /var/lib/jenkins/workspace/firefox-scan-build/other-licenses/nsis/Contrib/CityHash/cityhash -I /var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/find -I /var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/printingui/ipc -I /var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/windowwatcher -I /var/lib/jenkins/workspace/firefox-scan-build/toolkit/mozapps/update/common -I /var/lib/jenkins/workspace/firefox-scan-build/toolkit/profile -I /var/lib/jenkins/workspace/firefox-scan-build/config -I /var/lib/jenkins/workspace/firefox-scan-build/dom/base -I /var/lib/jenkins/workspace/firefox-scan-build/dom/commandhandler -I /var/lib/jenkins/workspace/firefox-scan-build/dom/ipc -I /var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist -I /var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/loader -I /var/lib/jenkins/workspace/firefox-scan-build/testing/gtest/mozilla -I /var/lib/jenkins/workspace/firefox-scan-build/toolkit/crashreporter -I /var/lib/jenkins/workspace/firefox-scan-build/xpcom/build -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -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/gtk-3.0/unix-print -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-09-22-115206-3586786-1 -x c++ /var/lib/jenkins/workspace/firefox-scan-build/toolkit/xre/nsAppRunner.cpp

/var/lib/jenkins/workspace/firefox-scan-build/toolkit/xre/nsAppRunner.cpp

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

/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/mozilla/CmdLineAndEnvUtils.h

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