Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name nsAppRunner.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/toolkit/xre -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/toolkit/xre -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D TELEMETRY_PING_FORMAT_VERSION=4 -D PROXY_PRINTING=1 -D USE_GLX_TEST -D MOZ_APP_NAME="firefox" -D MOZ_APP_BASENAME="Firefox" -D MOZ_APP_DISPLAYNAME="Nightly" -D MOZ_APP_VENDOR="Mozilla" -D MOZ_APP_VERSION="162.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=162.0a1 -D MOZ_APP_VERSION_DISPLAY=162.0a1 -D APP_VERSION=162.0a1 -D APP_ID={ec8030f7-c20a-464f-9b0e-13a3a9e97384} -D MOZ_BUILD_APP_IS_BROWSER -D MAR_NSS -D TOPOBJDIR=/root/firefox-clang/obj-x86_64-pc-linux-gnu -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/toolkit/xre -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/toolkit/xre -I /root/firefox-clang/toolkit/components/remote -I /root/firefox-clang/widget -I /root/firefox-clang/widget/gtk -I /root/firefox-clang/toolkit/components/printingui -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/third_party/abseil-cpp -I /root/firefox-clang/other-licenses/nsis/Contrib/CityHash/cityhash -I /root/firefox-clang/toolkit/components/find -I /root/firefox-clang/toolkit/components/printingui/ipc -I /root/firefox-clang/toolkit/components/windowwatcher -I /root/firefox-clang/toolkit/mozapps/update/common -I /root/firefox-clang/toolkit/profile -I /root/firefox-clang/config -I /root/firefox-clang/dom/base -I /root/firefox-clang/dom/commandhandler -I /root/firefox-clang/dom/ipc -I /root/firefox-clang/dom/webbrowserpersist -I /root/firefox-clang/js/xpconnect/loader -I /root/firefox-clang/testing/gtest/mozilla -I /root/firefox-clang/third_party/sqlite3/ext -I /root/firefox-clang/toolkit/components/jsoncpp/include -I /root/firefox-clang/toolkit/crashreporter -I /root/firefox-clang/xpcom/build -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -I /usr/include/uuid -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gtk-3.0/unix-print -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cloudproviders -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/fribidi -I /usr/include/harfbuzz -I /usr/include/atk-1.0 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/glycin-2 -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/gio-unix-2.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/sysprof-6 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-11-12-001017-1011516-1 -x c++ /root/firefox-clang/toolkit/xre/nsAppRunner.cpp

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

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

←

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

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