LCOV - code coverage report
Current view: top level - toolkit/xre - nsAppRunner.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 442 1733 25.5 %
Date: 2018-08-07 16:42:27 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "mozilla/dom/ContentParent.h"
       7             : #include "mozilla/dom/ContentChild.h"
       8             : #include "mozilla/ipc/GeckoChildProcessHost.h"
       9             : 
      10             : #include "mozilla/ArrayUtils.h"
      11             : #include "mozilla/Attributes.h"
      12             : #include "mozilla/FilePreferences.h"
      13             : #include "mozilla/ChaosMode.h"
      14             : #include "mozilla/CmdLineAndEnvUtils.h"
      15             : #include "mozilla/IOInterposer.h"
      16             : #include "mozilla/Likely.h"
      17             : #include "mozilla/MemoryChecking.h"
      18             : #include "mozilla/Poison.h"
      19             : #include "mozilla/Preferences.h"
      20             : #include "mozilla/Printf.h"
      21             : #include "mozilla/ResultExtensions.h"
      22             : #include "mozilla/ScopeExit.h"
      23             : #include "mozilla/Services.h"
      24             : #include "mozilla/Telemetry.h"
      25             : #include "mozilla/intl/LocaleService.h"
      26             : 
      27             : #include "nsAppRunner.h"
      28             : #include "mozilla/XREAppData.h"
      29             : #include "mozilla/Bootstrap.h"
      30             : #if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)
      31             : #include "nsUpdateDriver.h"
      32             : #endif
      33             : #include "ProfileReset.h"
      34             : 
      35             : #ifdef MOZ_INSTRUMENT_EVENT_LOOP
      36             : #include "EventTracer.h"
      37             : #endif
      38             : 
      39             : #ifdef XP_MACOSX
      40             : #include "nsVersionComparator.h"
      41             : #include "MacLaunchHelper.h"
      42             : #include "MacApplicationDelegate.h"
      43             : #include "MacAutoreleasePool.h"
      44             : // these are needed for sysctl
      45             : #include <sys/types.h>
      46             : #include <sys/sysctl.h>
      47             : #endif
      48             : 
      49             : #include "prnetdb.h"
      50             : #include "prprf.h"
      51             : #include "prproces.h"
      52             : #include "prenv.h"
      53             : #include "prtime.h"
      54             : 
      55             : #include "nsIAppShellService.h"
      56             : #include "nsIAppStartup.h"
      57             : #include "nsIAppStartupNotifier.h"
      58             : #include "nsIMutableArray.h"
      59             : #include "nsICategoryManager.h"
      60             : #include "nsIChromeRegistry.h"
      61             : #include "nsICommandLineRunner.h"
      62             : #include "nsIComponentManager.h"
      63             : #include "nsIComponentRegistrar.h"
      64             : #include "nsIConsoleService.h"
      65             : #include "nsIContentHandler.h"
      66             : #include "nsIDialogParamBlock.h"
      67             : #include "nsIDOMWindow.h"
      68             : #include "mozilla/ModuleUtils.h"
      69             : #include "nsIIOService.h"
      70             : #include "nsIObserverService.h"
      71             : #include "nsINativeAppSupport.h"
      72             : #include "nsIPlatformInfo.h"
      73             : #include "nsIProcess.h"
      74             : #include "nsIProfileUnlocker.h"
      75             : #include "nsIPromptService.h"
      76             : #include "nsIServiceManager.h"
      77             : #include "nsIStringBundle.h"
      78             : #include "nsISupportsPrimitives.h"
      79             : #include "nsIToolkitChromeRegistry.h"
      80             : #include "nsIToolkitProfile.h"
      81             : #include "nsIToolkitProfileService.h"
      82             : #include "nsIURI.h"
      83             : #include "nsIURL.h"
      84             : #include "nsIWindowCreator.h"
      85             : #include "nsIWindowMediator.h"
      86             : #include "nsIWindowWatcher.h"
      87             : #include "nsIXULAppInfo.h"
      88             : #include "nsIXULRuntime.h"
      89             : #include "nsPIDOMWindow.h"
      90             : #include "nsIBaseWindow.h"
      91             : #include "nsIWidget.h"
      92             : #include "nsIDocShell.h"
      93             : #include "nsAppShellCID.h"
      94             : #include "mozilla/scache/StartupCache.h"
      95             : #include "gfxPlatform.h"
      96             : #include "gfxPrefs.h"
      97             : 
      98             : #include "mozilla/Unused.h"
      99             : 
     100             : #ifdef XP_WIN
     101             : #include "nsIWinAppHelper.h"
     102             : #include <windows.h>
     103             : #include <intrin.h>
     104             : #include <math.h>
     105             : #include "cairo/cairo-features.h"
     106             : #include "mozilla/WindowsDllBlocklist.h"
     107             : #include "mozilla/mscom/MainThreadRuntime.h"
     108             : #include "mozilla/widget/AudioSession.h"
     109             : 
     110             : #ifndef PROCESS_DEP_ENABLE
     111             : #define PROCESS_DEP_ENABLE 0x1
     112             : #endif
     113             : #endif
     114             : 
     115             : #if defined(MOZ_CONTENT_SANDBOX)
     116             : #include "mozilla/SandboxSettings.h"
     117             : #if (defined(XP_WIN) || defined(XP_MACOSX))
     118             : #include "nsIUUIDGenerator.h"
     119             : #endif
     120             : #endif
     121             : 
     122             : #ifdef ACCESSIBILITY
     123             : #include "nsAccessibilityService.h"
     124             : #if defined(XP_WIN)
     125             : #include "mozilla/a11y/Compatibility.h"
     126             : #include "mozilla/a11y/Platform.h"
     127             : #endif
     128             : #endif
     129             : 
     130             : #include "nsCRT.h"
     131             : #include "nsCOMPtr.h"
     132             : #include "nsDirectoryServiceDefs.h"
     133             : #include "nsDirectoryServiceUtils.h"
     134             : #include "nsEmbedCID.h"
     135             : #include "nsNetUtil.h"
     136             : #include "nsReadableUtils.h"
     137             : #include "nsXPCOM.h"
     138             : #include "nsXPCOMCIDInternal.h"
     139             : #include "nsString.h"
     140             : #include "nsPrintfCString.h"
     141             : #include "nsVersionComparator.h"
     142             : 
     143             : #include "nsAppDirectoryServiceDefs.h"
     144             : #include "nsXULAppAPI.h"
     145             : #include "nsXREDirProvider.h"
     146             : #include "nsToolkitCompsCID.h"
     147             : 
     148             : #include "nsINIParser.h"
     149             : #include "mozilla/Omnijar.h"
     150             : #include "mozilla/StartupTimeline.h"
     151             : #include "mozilla/LateWriteChecks.h"
     152             : 
     153             : #include <stdlib.h>
     154             : #include <locale.h>
     155             : 
     156             : #ifdef XP_UNIX
     157             : #include <errno.h>
     158             : #include <pwd.h>
     159             : #include <string.h>
     160             : #include <sys/resource.h>
     161             : #include <sys/stat.h>
     162             : #include <unistd.h>
     163             : #endif
     164             : 
     165             : #ifdef XP_WIN
     166             : #include <process.h>
     167             : #include <shlobj.h>
     168             : #include "mozilla/WinDllServices.h"
     169             : #include "nsThreadUtils.h"
     170             : #include <comdef.h>
     171             : #include <wbemidl.h>
     172             : #include "WinUtils.h"
     173             : #endif
     174             : 
     175             : #ifdef XP_MACOSX
     176             : #include "nsILocalFileMac.h"
     177             : #include "nsCommandLineServiceMac.h"
     178             : #endif
     179             : 
     180             : // for X remote support
     181             : #ifdef MOZ_ENABLE_XREMOTE
     182             : #include "XRemoteClient.h"
     183             : #include "nsIRemoteService.h"
     184             : #include "nsProfileLock.h"
     185             : #include "SpecialSystemDirectory.h"
     186             : #include <sched.h>
     187             : #ifdef MOZ_ENABLE_DBUS
     188             : #include "DBusRemoteClient.h"
     189             : #endif
     190             : // Time to wait for the remoting service to start
     191             : #define MOZ_XREMOTE_START_TIMEOUT_SEC 5
     192             : #endif
     193             : 
     194             : #if defined(DEBUG) && defined(XP_WIN32)
     195             : #include <malloc.h>
     196             : #endif
     197             : 
     198             : #if defined (XP_MACOSX)
     199             : #include <Carbon/Carbon.h>
     200             : #endif
     201             : 
     202             : #ifdef DEBUG
     203             : #include "mozilla/Logging.h"
     204             : #endif
     205             : 
     206             : #ifdef MOZ_JPROF
     207             : #include "jprof.h"
     208             : #endif
     209             : 
     210             : #include "nsExceptionHandler.h"
     211             : #include "nsICrashReporter.h"
     212             : #define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1"
     213             : #include "nsIPrefService.h"
     214             : #include "nsIMemoryInfoDumper.h"
     215             : #if defined(XP_LINUX) && !defined(ANDROID)
     216             : #include "mozilla/widget/LSBUtils.h"
     217             : #endif
     218             : 
     219             : #include "base/command_line.h"
     220             : #include "GTestRunner.h"
     221             : 
     222             : #ifdef MOZ_WIDGET_ANDROID
     223             : #include "GeneratedJNIWrappers.h"
     224             : #endif
     225             : 
     226             : #if defined(MOZ_SANDBOX)
     227             : #if defined(XP_LINUX) && !defined(ANDROID)
     228             : #include "mozilla/SandboxInfo.h"
     229             : #elif defined(XP_WIN)
     230             : #include "sandboxBroker.h"
     231             : #include "sandboxPermissions.h"
     232             : #endif
     233             : #endif
     234             : 
     235             : #ifdef MOZ_CODE_COVERAGE
     236             : #include "mozilla/CodeCoverageHandler.h"
     237             : #endif
     238             : 
     239             : #include "mozilla/mozalloc_oom.h"
     240             : #include "SafeMode.h"
     241             : 
     242             : extern uint32_t gRestartMode;
     243             : extern void InstallSignalHandlers(const char *ProgramName);
     244             : 
     245             : #define FILE_COMPATIBILITY_INFO NS_LITERAL_CSTRING("compatibility.ini")
     246             : #define FILE_INVALIDATE_CACHES NS_LITERAL_CSTRING(".purgecaches")
     247             : #define FILE_STARTUP_INCOMPLETE NS_LITERAL_STRING(".startup-incomplete")
     248             : 
     249             : int    gArgc;
     250             : char **gArgv;
     251             : 
     252             : #include "buildid.h"
     253             : 
     254             : static const char gToolkitVersion[] = NS_STRINGIFY(GRE_MILESTONE);
     255             : static const char gToolkitBuildID[] = NS_STRINGIFY(MOZ_BUILDID);
     256             : 
     257             : static nsIProfileLock* gProfileLock;
     258             : 
     259             : int    gRestartArgc;
     260             : char **gRestartArgv;
     261             : 
     262             : // If gRestartedByOS is set, we were automatically restarted by the OS.
     263             : bool gRestartedByOS = false;
     264             : 
     265             : bool gIsGtest = false;
     266             : 
     267           1 : nsString gAbsoluteArgv0Path;
     268             : 
     269             : #if defined(MOZ_WIDGET_GTK)
     270             : #include <glib.h>
     271             : #if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING)
     272             : #define CLEANUP_MEMORY 1
     273             : #define PANGO_ENABLE_BACKEND
     274             : #include <pango/pangofc-fontmap.h>
     275             : #endif
     276             : #include <gtk/gtk.h>
     277             : #ifdef MOZ_WAYLAND
     278             : #include <gdk/gdkwayland.h>
     279             : #endif
     280             : #ifdef MOZ_X11
     281             : #include <gdk/gdkx.h>
     282             : #endif /* MOZ_X11 */
     283             : #include "nsGTKToolkit.h"
     284             : #include <fontconfig/fontconfig.h>
     285             : #endif
     286             : #include "BinaryPath.h"
     287             : 
     288             : #ifdef MOZ_LINKER
     289             : extern "C" MFBT_API bool IsSignalHandlingBroken();
     290             : #endif
     291             : 
     292             : #ifdef FUZZING
     293             : #include "FuzzerRunner.h"
     294             : 
     295             : namespace mozilla {
     296             : FuzzerRunner* fuzzerRunner = 0;
     297             : } // namespace mozilla
     298             : 
     299             : #ifdef LIBFUZZER
     300             : void XRE_LibFuzzerSetDriver(LibFuzzerDriver aDriver) {
     301             :   mozilla::fuzzerRunner->setParams(aDriver);
     302             : }
     303             : #endif
     304             : #endif // FUZZING
     305             : 
     306             : namespace mozilla {
     307             : int (*RunGTest)(int*, char**) = 0;
     308             : } // namespace mozilla
     309             : 
     310             : using namespace mozilla;
     311             : using namespace mozilla::startup;
     312             : using mozilla::Unused;
     313             : using mozilla::scache::StartupCache;
     314             : using mozilla::dom::ContentParent;
     315             : using mozilla::dom::ContentChild;
     316             : using mozilla::intl::LocaleService;
     317             : 
     318             : // Save the given word to the specified environment variable.
     319             : static void
     320           1 : SaveWordToEnv(const char *name, const nsACString & word)
     321             : {
     322           0 :   char *expr = Smprintf("%s=%s", name, PromiseFlatCString(word).get()).release();
     323           0 :   if (expr)
     324           1 :     PR_SetEnv(expr);
     325             :   // We intentionally leak |expr| here since it is required by PR_SetEnv.
     326           1 : }
     327             : 
     328             : // Save the path of the given file to the specified environment variable.
     329             : static void
     330           0 : SaveFileToEnv(const char *name, nsIFile *file)
     331             : {
     332             : #ifdef XP_WIN
     333             :   nsAutoString path;
     334             :   file->GetPath(path);
     335             :   SetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name).get(), path.get());
     336             : #else
     337           0 :   nsAutoCString path;
     338           0 :   file->GetNativePath(path);
     339           0 :   SaveWordToEnv(name, path);
     340             : #endif
     341           0 : }
     342             : 
     343             : // Load the path of a file saved with SaveFileToEnv
     344             : static already_AddRefed<nsIFile>
     345           1 : GetFileFromEnv(const char *name)
     346             : {
     347             :   nsresult rv;
     348           2 :   nsCOMPtr<nsIFile> file;
     349             : 
     350             : #ifdef XP_WIN
     351             :   WCHAR path[_MAX_PATH];
     352             :   if (!GetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name).get(),
     353             :                                path, _MAX_PATH))
     354             :     return nullptr;
     355             : 
     356             :   rv = NS_NewLocalFile(nsDependentString(path), true, getter_AddRefs(file));
     357             :   if (NS_FAILED(rv))
     358             :     return nullptr;
     359             : 
     360             :   return file.forget();
     361             : #else
     362           0 :   const char *arg = PR_GetEnv(name);
     363           1 :   if (!arg || !*arg)
     364             :     return nullptr;
     365             : 
     366           0 :   rv = NS_NewNativeLocalFile(nsDependentCString(arg), true,
     367           0 :                              getter_AddRefs(file));
     368           0 :   if (NS_FAILED(rv))
     369             :     return nullptr;
     370             : 
     371           0 :   return file.forget();
     372             : #endif
     373             : }
     374             : 
     375             : // Save the path of the given word to the specified environment variable
     376             : // provided the environment variable does not have a value.
     377             : static void
     378           0 : SaveWordToEnvIfUnset(const char *name, const nsACString & word)
     379             : {
     380           0 :   if (!EnvHasValue(name))
     381           0 :     SaveWordToEnv(name, word);
     382           0 : }
     383             : 
     384             : // Save the path of the given file to the specified environment variable
     385             : // provided the environment variable does not have a value.
     386             : static void
     387           0 : SaveFileToEnvIfUnset(const char *name, nsIFile *file)
     388             : {
     389           0 :   if (!EnvHasValue(name))
     390           0 :     SaveFileToEnv(name, file);
     391           0 : }
     392             : 
     393             : static bool gIsExpectedExit = false;
     394             : 
     395           0 : void MozExpectedExit() {
     396           1 :   gIsExpectedExit = true;
     397           0 : }
     398             : 
     399             : /**
     400             :  * Runs atexit() to catch unexpected exit from 3rd party libraries like the
     401             :  * Intel graphics driver calling exit in an error condition. When they
     402             :  * call exit() to report an error we won't shutdown correctly and wont catch
     403             :  * the issue with our crash reporter.
     404             :  */
     405           0 : static void UnexpectedExit() {
     406           0 :   if (!gIsExpectedExit) {
     407           0 :     gIsExpectedExit = true; // Don't risk re-entrency issues when crashing.
     408           0 :     MOZ_CRASH("Exit called by third party code.");
     409             :   }
     410           0 : }
     411             : 
     412             : /**
     413             :  * Output a string to the user.  This method is really only meant to be used to
     414             :  * output last-ditch error messages designed for developers NOT END USERS.
     415             :  *
     416             :  * @param isError
     417             :  *        Pass true to indicate severe errors.
     418             :  * @param fmt
     419             :  *        printf-style format string followed by arguments.
     420             :  */
     421           0 : static MOZ_FORMAT_PRINTF(2, 3) void Output(bool isError, const char *fmt, ... )
     422             : {
     423             :   va_list ap;
     424           0 :   va_start(ap, fmt);
     425             : 
     426             : #if defined(XP_WIN) && !MOZ_WINCONSOLE
     427             :   SmprintfPointer msg = mozilla::Vsmprintf(fmt, ap);
     428             :   if (msg)
     429             :   {
     430             :     UINT flags = MB_OK;
     431             :     if (isError)
     432             :       flags |= MB_ICONERROR;
     433             :     else
     434             :       flags |= MB_ICONINFORMATION;
     435             : 
     436             :     wchar_t wide_msg[1024];
     437             :     MultiByteToWideChar(CP_ACP,
     438             :                         0,
     439             :                         msg.get(),
     440             :                         -1,
     441             :                         wide_msg,
     442             :                         sizeof(wide_msg) / sizeof(wchar_t));
     443             : 
     444             :     MessageBoxW(nullptr, wide_msg, L"XULRunner", flags);
     445             :   }
     446             : #else
     447           0 :   vfprintf(stderr, fmt, ap);
     448             : #endif
     449             : 
     450           0 :   va_end(ap);
     451           0 : }
     452             : 
     453             : enum RemoteResult {
     454             :   REMOTE_NOT_FOUND  = 0,
     455             :   REMOTE_FOUND      = 1,
     456             :   REMOTE_ARG_BAD    = 2
     457             : };
     458             : 
     459             : /**
     460             :  * Check for a commandline flag. If the flag takes a parameter, the
     461             :  * parameter is returned in aParam. Flags may be in the form -arg or
     462             :  * --arg (or /arg on win32).
     463             :  *
     464             :  * @param aArg the parameter to check. Must be lowercase.
     465             :  * @param aParam if non-null, the -arg <data> will be stored in this pointer.
     466             :  *        This is *not* allocated, but rather a pointer to the argv data.
     467             :  * @param aFlags flags @see CheckArgFlag
     468             :  */
     469             : static ArgResult
     470          20 : CheckArg(const char* aArg, const char** aParam = nullptr,
     471             :          CheckArgFlag aFlags = CheckArgFlag::RemoveArg)
     472             : {
     473           0 :   MOZ_ASSERT(gArgv, "gArgv must be initialized before CheckArg()");
     474          20 :   return CheckArg(gArgc, gArgv, aArg, aParam, aFlags);
     475             : }
     476             : 
     477             : /**
     478             :  * Check for a commandline flag. Ignore data that's passed in with the flag.
     479             :  * Flags may be in the form -arg or --arg (or /arg on win32).
     480             :  * Will not remove flag if found.
     481             :  *
     482             :  * @param aArg the parameter to check. Must be lowercase.
     483             :  */
     484             : static ArgResult
     485           1 : CheckArgExists(const char* aArg)
     486             : {
     487           1 :   return CheckArg(aArg, nullptr, CheckArgFlag::None);
     488             : }
     489             : 
     490             : #if defined(XP_WIN)
     491             : /**
     492             :  * Check for a commandline flag from the windows shell and remove it from the
     493             :  * argv used when restarting. Flags MUST be in the form -arg.
     494             :  *
     495             :  * @param aArg the parameter to check. Must be lowercase.
     496             :  */
     497             : static ArgResult
     498             : CheckArgShell(const char* aArg)
     499             : {
     500             :   char **curarg = gRestartArgv + 1; // skip argv[0]
     501             : 
     502             :   while (*curarg) {
     503             :     char *arg = curarg[0];
     504             : 
     505             :     if (arg[0] == '-') {
     506             :       ++arg;
     507             : 
     508             :       if (strimatch(aArg, arg)) {
     509             :         do {
     510             :           *curarg = *(curarg + 1);
     511             :           ++curarg;
     512             :         } while (*curarg);
     513             : 
     514             :         --gRestartArgc;
     515             : 
     516             :         return ARG_FOUND;
     517             :       }
     518             :     }
     519             : 
     520             :     ++curarg;
     521             :   }
     522             : 
     523             :   return ARG_NONE;
     524             : }
     525             : 
     526             : /**
     527             :  * Enabled Native App Support to process DDE messages when the app needs to
     528             :  * restart and the app has been launched by the Windows shell to open an url.
     529             :  * When aWait is false this will process the DDE events manually. This prevents
     530             :  * Windows from displaying an error message due to the DDE message not being
     531             :  * acknowledged.
     532             :  */
     533             : static void
     534             : ProcessDDE(nsINativeAppSupport* aNative, bool aWait)
     535             : {
     536             :   // When the app is launched by the windows shell the windows shell
     537             :   // expects the app to be available for DDE messages and if it isn't
     538             :   // windows displays an error dialog. To prevent the error the DDE server
     539             :   // is enabled and pending events are processed when the app needs to
     540             :   // restart after it was launched by the shell with the requestpending
     541             :   // argument. The requestpending pending argument is removed to
     542             :   // differentiate it from being launched when an app restart is not
     543             :   // required.
     544             :   ArgResult ar;
     545             :   ar = CheckArgShell("requestpending");
     546             :   if (ar == ARG_FOUND) {
     547             :     aNative->Enable(); // enable win32 DDE responses
     548             :     if (aWait) {
     549             :       // This is just a guesstimate based on testing different values.
     550             :       // If count is 8 or less windows will display an error dialog.
     551             :       int32_t count = 20;
     552             :       SpinEventLoopUntil([&]() { return --count < 0; });
     553             :     }
     554             :   }
     555             : }
     556             : #endif
     557             : 
     558             : /**
     559             :  * Determines if there is support for showing the profile manager
     560             :  *
     561             :  * @return true in all environments
     562             : */
     563             : static bool
     564             : CanShowProfileManager()
     565             : {
     566             :   return true;
     567             : }
     568             : 
     569             : bool gSafeMode = false;
     570             : 
     571             : /**
     572             :  * The nsXULAppInfo object implements nsIFactory so that it can be its own
     573             :  * singleton.
     574             :  */
     575             : class nsXULAppInfo : public nsIXULAppInfo,
     576             :                      public nsIObserver,
     577             : #ifdef XP_WIN
     578             :                      public nsIWinAppHelper,
     579             : #endif
     580             :                      public nsICrashReporter,
     581             :                      public nsIFinishDumpingCallback,
     582             :                      public nsIXULRuntime
     583             : 
     584             : {
     585             : public:
     586             :   constexpr nsXULAppInfo() {}
     587             :   NS_DECL_ISUPPORTS_INHERITED
     588             :   NS_DECL_NSIPLATFORMINFO
     589             :   NS_DECL_NSIXULAPPINFO
     590             :   NS_DECL_NSIXULRUNTIME
     591             :   NS_DECL_NSIOBSERVER
     592             :   NS_DECL_NSICRASHREPORTER
     593             :   NS_DECL_NSIFINISHDUMPINGCALLBACK
     594             : #ifdef XP_WIN
     595             :   NS_DECL_NSIWINAPPHELPER
     596             : #endif
     597             : };
     598             : 
     599           0 : NS_INTERFACE_MAP_BEGIN(nsXULAppInfo)
     600           0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULRuntime)
     601           0 :   NS_INTERFACE_MAP_ENTRY(nsIXULRuntime)
     602        1413 :   NS_INTERFACE_MAP_ENTRY(nsIObserver)
     603             : #ifdef XP_WIN
     604             :   NS_INTERFACE_MAP_ENTRY(nsIWinAppHelper)
     605             : #endif
     606           0 :   NS_INTERFACE_MAP_ENTRY(nsICrashReporter)
     607           0 :   NS_INTERFACE_MAP_ENTRY(nsIFinishDumpingCallback)
     608           0 :   NS_INTERFACE_MAP_ENTRY(nsIPlatformInfo)
     609         135 :   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIXULAppInfo, gAppData ||
     610             :                                      XRE_IsContentProcess())
     611        1496 : NS_INTERFACE_MAP_END
     612             : 
     613             : NS_IMETHODIMP_(MozExternalRefCountType)
     614        1409 : nsXULAppInfo::AddRef()
     615             : {
     616        1409 :   return 1;
     617             : }
     618             : 
     619             : NS_IMETHODIMP_(MozExternalRefCountType)
     620        1385 : nsXULAppInfo::Release()
     621             : {
     622        1385 :   return 1;
     623             : }
     624             : 
     625             : NS_IMETHODIMP
     626           1 : nsXULAppInfo::GetVendor(nsACString& aResult)
     627             : {
     628           0 :   if (XRE_IsContentProcess()) {
     629           0 :     ContentChild* cc = ContentChild::GetSingleton();
     630           0 :     aResult = cc->GetAppInfo().vendor;
     631           0 :     return NS_OK;
     632             :   }
     633           2 :   aResult.Assign(gAppData->vendor);
     634             : 
     635           1 :   return NS_OK;
     636             : }
     637             : 
     638             : NS_IMETHODIMP
     639           4 : nsXULAppInfo::GetName(nsACString& aResult)
     640             : {
     641           0 :   if (XRE_IsContentProcess()) {
     642           0 :     ContentChild* cc = ContentChild::GetSingleton();
     643           0 :     aResult = cc->GetAppInfo().name;
     644           0 :     return NS_OK;
     645             :   }
     646           8 :   aResult.Assign(gAppData->name);
     647             : 
     648           4 :   return NS_OK;
     649             : }
     650             : 
     651             : NS_IMETHODIMP
     652         581 : nsXULAppInfo::GetID(nsACString& aResult)
     653             : {
     654           0 :   if (XRE_IsContentProcess()) {
     655           0 :     ContentChild* cc = ContentChild::GetSingleton();
     656           0 :     aResult = cc->GetAppInfo().ID;
     657           0 :     return NS_OK;
     658             :   }
     659        1162 :   aResult.Assign(gAppData->ID);
     660             : 
     661         581 :   return NS_OK;
     662             : }
     663             : 
     664             : NS_IMETHODIMP
     665          68 : nsXULAppInfo::GetVersion(nsACString& aResult)
     666             : {
     667           0 :   if (XRE_IsContentProcess()) {
     668           0 :     ContentChild* cc = ContentChild::GetSingleton();
     669           0 :     aResult = cc->GetAppInfo().version;
     670           0 :     return NS_OK;
     671             :   }
     672         136 :   aResult.Assign(gAppData->version);
     673             : 
     674          68 :   return NS_OK;
     675             : }
     676             : 
     677             : NS_IMETHODIMP
     678          54 : nsXULAppInfo::GetPlatformVersion(nsACString& aResult)
     679             : {
     680          54 :   aResult.Assign(gToolkitVersion);
     681             : 
     682          54 :   return NS_OK;
     683             : }
     684             : 
     685             : NS_IMETHODIMP
     686           4 : nsXULAppInfo::GetAppBuildID(nsACString& aResult)
     687             : {
     688           0 :   if (XRE_IsContentProcess()) {
     689           0 :     ContentChild* cc = ContentChild::GetSingleton();
     690           0 :     aResult = cc->GetAppInfo().buildID;
     691           0 :     return NS_OK;
     692             :   }
     693           8 :   aResult.Assign(gAppData->buildID);
     694             : 
     695           4 :   return NS_OK;
     696             : }
     697             : 
     698             : NS_IMETHODIMP
     699        1265 : nsXULAppInfo::GetPlatformBuildID(nsACString& aResult)
     700             : {
     701        1265 :   aResult.Assign(gToolkitBuildID);
     702             : 
     703        1265 :   return NS_OK;
     704             : }
     705             : 
     706             : NS_IMETHODIMP
     707           1 : nsXULAppInfo::GetUAName(nsACString& aResult)
     708             : {
     709           0 :   if (XRE_IsContentProcess()) {
     710           0 :     ContentChild* cc = ContentChild::GetSingleton();
     711           0 :     aResult = cc->GetAppInfo().UAName;
     712           0 :     return NS_OK;
     713             :   }
     714           2 :   aResult.Assign(gAppData->UAName);
     715             : 
     716           1 :   return NS_OK;
     717             : }
     718             : 
     719             : NS_IMETHODIMP
     720           0 : nsXULAppInfo::GetSourceURL(nsACString& aResult)
     721             : {
     722           0 :   if (XRE_IsContentProcess()) {
     723           0 :     ContentChild* cc = ContentChild::GetSingleton();
     724           0 :     aResult = cc->GetAppInfo().sourceURL;
     725           0 :     return NS_OK;
     726             :   }
     727           0 :   aResult.Assign(gAppData->sourceURL);
     728             : 
     729           0 :   return NS_OK;
     730             : }
     731             : 
     732             : NS_IMETHODIMP
     733           0 : nsXULAppInfo::GetLogConsoleErrors(bool *aResult)
     734             : {
     735           0 :   *aResult = gLogConsoleErrors;
     736           0 :   return NS_OK;
     737             : }
     738             : 
     739             : NS_IMETHODIMP
     740           0 : nsXULAppInfo::SetLogConsoleErrors(bool aValue)
     741             : {
     742           0 :   gLogConsoleErrors = aValue;
     743           0 :   return NS_OK;
     744             : }
     745             : 
     746             : NS_IMETHODIMP
     747          51 : nsXULAppInfo::GetInSafeMode(bool *aResult)
     748             : {
     749           0 :   *aResult = gSafeMode;
     750          51 :   return NS_OK;
     751             : }
     752             : 
     753             : NS_IMETHODIMP
     754          26 : nsXULAppInfo::GetOS(nsACString& aResult)
     755             : {
     756           0 :   aResult.AssignLiteral(OS_TARGET);
     757          26 :   return NS_OK;
     758             : }
     759             : 
     760             : NS_IMETHODIMP
     761          18 : nsXULAppInfo::GetXPCOMABI(nsACString& aResult)
     762             : {
     763             : #ifdef TARGET_XPCOM_ABI
     764           0 :   aResult.AssignLiteral(TARGET_XPCOM_ABI);
     765          18 :   return NS_OK;
     766             : #else
     767             :   return NS_ERROR_NOT_AVAILABLE;
     768             : #endif
     769             : }
     770             : 
     771             : NS_IMETHODIMP
     772           0 : nsXULAppInfo::GetWidgetToolkit(nsACString& aResult)
     773             : {
     774           0 :   aResult.AssignLiteral(MOZ_WIDGET_TOOLKIT);
     775           0 :   return NS_OK;
     776             : }
     777             : 
     778             : // Ensure that the GeckoProcessType enum, defined in xpcom/build/nsXULAppAPI.h,
     779             : // is synchronized with the const unsigned longs defined in
     780             : // xpcom/system/nsIXULRuntime.idl.
     781             : #define SYNC_ENUMS(a,b) \
     782             :   static_assert(nsIXULRuntime::PROCESS_TYPE_ ## a == \
     783             :                 static_cast<int>(GeckoProcessType_ ## b), \
     784             :                 "GeckoProcessType in nsXULAppAPI.h not synchronized with nsIXULRuntime.idl");
     785             : 
     786             : SYNC_ENUMS(DEFAULT, Default)
     787             : SYNC_ENUMS(PLUGIN, Plugin)
     788             : SYNC_ENUMS(CONTENT, Content)
     789             : SYNC_ENUMS(IPDLUNITTEST, IPDLUnitTest)
     790             : SYNC_ENUMS(GMPLUGIN, GMPlugin)
     791             : SYNC_ENUMS(GPU, GPU)
     792             : SYNC_ENUMS(PDFIUM, PDFium)
     793             : 
     794             : // .. and ensure that that is all of them:
     795             : static_assert(GeckoProcessType_PDFium + 1 == GeckoProcessType_End,
     796             :               "Did not find the final GeckoProcessType");
     797             : 
     798             : NS_IMETHODIMP
     799          28 : nsXULAppInfo::GetProcessType(uint32_t* aResult)
     800             : {
     801           0 :   NS_ENSURE_ARG_POINTER(aResult);
     802           0 :   *aResult = XRE_GetProcessType();
     803          28 :   return NS_OK;
     804             : }
     805             : 
     806             : NS_IMETHODIMP
     807           2 : nsXULAppInfo::GetProcessID(uint32_t* aResult)
     808             : {
     809             : #ifdef XP_WIN
     810             :   *aResult = GetCurrentProcessId();
     811             : #else
     812           2 :   *aResult = getpid();
     813             : #endif
     814           2 :   return NS_OK;
     815             : }
     816             : 
     817             : NS_IMETHODIMP
     818           1 : nsXULAppInfo::GetUniqueProcessID(uint64_t* aResult)
     819             : {
     820           0 :   if (XRE_IsContentProcess()) {
     821           0 :     ContentChild* cc = ContentChild::GetSingleton();
     822           0 :     *aResult = cc->GetID();
     823             :   } else {
     824           1 :     *aResult = 0;
     825             :   }
     826           1 :   return NS_OK;
     827             : }
     828             : 
     829             : NS_IMETHODIMP
     830           0 : nsXULAppInfo::GetRemoteType(nsAString& aRemoteType)
     831             : {
     832           0 :   if (XRE_IsContentProcess()) {
     833           0 :     ContentChild* cc = ContentChild::GetSingleton();
     834           0 :     aRemoteType.Assign(cc->GetRemoteType());
     835             :   } else {
     836           0 :     SetDOMStringToNull(aRemoteType);
     837             :   }
     838             : 
     839           0 :   return NS_OK;
     840             : }
     841             : 
     842             : static bool gBrowserTabsRemoteAutostart = false;
     843             : static uint64_t gBrowserTabsRemoteStatus = 0;
     844             : static bool gBrowserTabsRemoteAutostartInitialized = false;
     845             : 
     846             : NS_IMETHODIMP
     847           0 : nsXULAppInfo::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *aData) {
     848           0 :   if (!nsCRT::strcmp(aTopic, "getE10SBlocked")) {
     849           0 :     nsCOMPtr<nsISupportsPRUint64> ret = do_QueryInterface(aSubject);
     850           0 :     if (!ret)
     851             :       return NS_ERROR_FAILURE;
     852             : 
     853           0 :     ret->SetData(gBrowserTabsRemoteStatus);
     854             : 
     855           0 :     return NS_OK;
     856             :   }
     857             :   return NS_ERROR_FAILURE;
     858             : }
     859             : 
     860             : NS_IMETHODIMP
     861           1 : nsXULAppInfo::GetBrowserTabsRemoteAutostart(bool* aResult)
     862             : {
     863           0 :   *aResult = BrowserTabsRemoteAutostart();
     864           1 :   return NS_OK;
     865             : }
     866             : 
     867             : NS_IMETHODIMP
     868           1 : nsXULAppInfo::GetMaxWebProcessCount(uint32_t* aResult)
     869             : {
     870           0 :   *aResult = mozilla::GetMaxWebProcessCount();
     871           1 :   return NS_OK;
     872             : }
     873             : 
     874             : NS_IMETHODIMP
     875           1 : nsXULAppInfo::GetAccessibilityEnabled(bool* aResult)
     876             : {
     877             : #ifdef ACCESSIBILITY
     878           1 :   *aResult = GetAccService() != nullptr;
     879             : #else
     880             :   *aResult = false;
     881             : #endif
     882           1 :   return NS_OK;
     883             : }
     884             : 
     885             : NS_IMETHODIMP
     886           0 : nsXULAppInfo::GetAccessibleHandlerUsed(bool* aResult)
     887             : {
     888             : #if defined(ACCESSIBILITY) && defined(XP_WIN)
     889             :   *aResult = Preferences::GetBool("accessibility.handler.enabled", false) &&
     890             :     a11y::IsHandlerRegistered();
     891             : #else
     892           0 :   *aResult = false;
     893             : #endif
     894           0 :   return NS_OK;
     895             : }
     896             : 
     897             : NS_IMETHODIMP
     898           0 : nsXULAppInfo::GetAccessibilityInstantiator(nsAString &aInstantiator)
     899             : {
     900             : #if defined(ACCESSIBILITY) && defined(XP_WIN)
     901             :   if (!GetAccService()) {
     902             :     aInstantiator = NS_LITERAL_STRING("");
     903             :     return NS_OK;
     904             :   }
     905             :   nsAutoString ipClientInfo;
     906             :   a11y::Compatibility::GetHumanReadableConsumersStr(ipClientInfo);
     907             :   aInstantiator.Append(ipClientInfo);
     908             :   aInstantiator.AppendLiteral("|");
     909             : 
     910             :   nsCOMPtr<nsIFile> oopClientExe;
     911             :   if (a11y::GetInstantiator(getter_AddRefs(oopClientExe))) {
     912             :     nsAutoString oopClientInfo;
     913             :     if (NS_SUCCEEDED(oopClientExe->GetPath(oopClientInfo))) {
     914             :       aInstantiator.Append(oopClientInfo);
     915             :     }
     916             :   }
     917             : #else
     918           0 :   aInstantiator = NS_LITERAL_STRING("");
     919             : #endif
     920           0 :   return NS_OK;
     921             : }
     922             : 
     923             : NS_IMETHODIMP
     924           0 : nsXULAppInfo::GetShouldBlockIncompatJaws(bool* aResult)
     925             : {
     926           0 :   *aResult = false;
     927             : #if defined(ACCESSIBILITY) && defined(XP_WIN)
     928             :   *aResult = mozilla::a11y::Compatibility::IsOldJAWS();
     929             : #endif
     930           0 :   return NS_OK;
     931             : }
     932             : 
     933             : NS_IMETHODIMP
     934           0 : nsXULAppInfo::GetIs64Bit(bool* aResult)
     935             : {
     936             : #ifdef HAVE_64BIT_BUILD
     937           0 :   *aResult = true;
     938             : #else
     939             :   *aResult = false;
     940             : #endif
     941           0 :   return NS_OK;
     942             : }
     943             : 
     944             : NS_IMETHODIMP
     945           0 : nsXULAppInfo::EnsureContentProcess()
     946             : {
     947           0 :   if (!XRE_IsParentProcess())
     948             :     return NS_ERROR_NOT_AVAILABLE;
     949             : 
     950           0 :   RefPtr<ContentParent> unused = ContentParent::GetNewOrUsedBrowserProcess(
     951           0 :     NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE));
     952             :   return NS_OK;
     953             : }
     954             : 
     955             : NS_IMETHODIMP
     956           0 : nsXULAppInfo::InvalidateCachesOnRestart()
     957             : {
     958           0 :   nsCOMPtr<nsIFile> file;
     959           0 :   nsresult rv = NS_GetSpecialDirectory(NS_APP_PROFILE_DIR_STARTUP,
     960           0 :                                        getter_AddRefs(file));
     961           0 :   if (NS_FAILED(rv))
     962             :     return rv;
     963           0 :   if (!file)
     964             :     return NS_ERROR_NOT_AVAILABLE;
     965             : 
     966           0 :   file->AppendNative(FILE_COMPATIBILITY_INFO);
     967             : 
     968           0 :   nsINIParser parser;
     969           0 :   rv = parser.Init(file);
     970           0 :   if (NS_FAILED(rv)) {
     971             :     // This fails if compatibility.ini is not there, so we'll
     972             :     // flush the caches on the next restart anyways.
     973             :     return NS_OK;
     974             :   }
     975             : 
     976           0 :   nsAutoCString buf;
     977           0 :   rv = parser.GetString("Compatibility", "InvalidateCaches", buf);
     978             : 
     979           0 :   if (NS_FAILED(rv)) {
     980             :     PRFileDesc *fd;
     981           0 :     rv = file->OpenNSPRFileDesc(PR_RDWR | PR_APPEND, 0600, &fd);
     982           0 :     if (NS_FAILED(rv)) {
     983           0 :       NS_ERROR("could not create output stream");
     984           0 :       return NS_ERROR_NOT_AVAILABLE;
     985             :     }
     986             :     static const char kInvalidationHeader[] = NS_LINEBREAK "InvalidateCaches=1" NS_LINEBREAK;
     987           0 :     PR_Write(fd, kInvalidationHeader, sizeof(kInvalidationHeader) - 1);
     988           0 :     PR_Close(fd);
     989             :   }
     990             :   return NS_OK;
     991             : }
     992             : 
     993             : NS_IMETHODIMP
     994           1 : nsXULAppInfo::GetReplacedLockTime(PRTime *aReplacedLockTime)
     995             : {
     996           1 :   if (!gProfileLock)
     997             :     return NS_ERROR_NOT_AVAILABLE;
     998           0 :   gProfileLock->GetReplacedLockTime(aReplacedLockTime);
     999           1 :   return NS_OK;
    1000             : }
    1001             : 
    1002             : NS_IMETHODIMP
    1003           0 : nsXULAppInfo::GetIsReleaseOrBeta(bool* aResult)
    1004             : {
    1005             : #ifdef RELEASE_OR_BETA
    1006             :   *aResult = true;
    1007             : #else
    1008           0 :   *aResult = false;
    1009             : #endif
    1010           0 :   return NS_OK;
    1011             : }
    1012             : 
    1013             : NS_IMETHODIMP
    1014           0 : nsXULAppInfo::GetIsOfficialBranding(bool* aResult)
    1015             : {
    1016             : #ifdef MOZ_OFFICIAL_BRANDING
    1017             :   *aResult = true;
    1018             : #else
    1019           0 :   *aResult = false;
    1020             : #endif
    1021           0 :   return NS_OK;
    1022             : }
    1023             : 
    1024             : NS_IMETHODIMP
    1025           0 : nsXULAppInfo::GetDefaultUpdateChannel(nsACString& aResult)
    1026             : {
    1027           0 :   aResult.AssignLiteral(NS_STRINGIFY(MOZ_UPDATE_CHANNEL));
    1028           0 :   return NS_OK;
    1029             : }
    1030             : 
    1031             : NS_IMETHODIMP
    1032           0 : nsXULAppInfo::GetDistributionID(nsACString& aResult)
    1033             : {
    1034           0 :   aResult.AssignLiteral(MOZ_DISTRIBUTION_ID);
    1035           0 :   return NS_OK;
    1036             : }
    1037             : 
    1038             : NS_IMETHODIMP
    1039           0 : nsXULAppInfo::GetWindowsDLLBlocklistStatus(bool* aResult)
    1040             : {
    1041             : #if defined(HAS_DLL_BLOCKLIST)
    1042             :   *aResult = DllBlocklist_CheckStatus();
    1043             : #else
    1044           0 :   *aResult = false;
    1045             : #endif
    1046           0 :   return NS_OK;
    1047             : }
    1048             : 
    1049             : NS_IMETHODIMP
    1050           0 : nsXULAppInfo::GetRestartedByOS(bool* aResult)
    1051             : {
    1052           0 :   *aResult = gRestartedByOS;
    1053           0 :   return NS_OK;
    1054             : }
    1055             : 
    1056             : #ifdef XP_WIN
    1057             : // Matches the enum in WinNT.h for the Vista SDK but renamed so that we can
    1058             : // safely build with the Vista SDK and without it.
    1059             : typedef enum
    1060             : {
    1061             :   VistaTokenElevationTypeDefault = 1,
    1062             :   VistaTokenElevationTypeFull,
    1063             :   VistaTokenElevationTypeLimited
    1064             : } VISTA_TOKEN_ELEVATION_TYPE;
    1065             : 
    1066             : // avoid collision with TokeElevationType enum in WinNT.h
    1067             : // of the Vista SDK
    1068             : #define VistaTokenElevationType static_cast< TOKEN_INFORMATION_CLASS >( 18 )
    1069             : 
    1070             : NS_IMETHODIMP
    1071             : nsXULAppInfo::GetUserCanElevate(bool *aUserCanElevate)
    1072             : {
    1073             :   HANDLE hToken;
    1074             : 
    1075             :   VISTA_TOKEN_ELEVATION_TYPE elevationType;
    1076             :   DWORD dwSize;
    1077             : 
    1078             :   if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken) ||
    1079             :       !GetTokenInformation(hToken, VistaTokenElevationType, &elevationType,
    1080             :                            sizeof(elevationType), &dwSize)) {
    1081             :     *aUserCanElevate = false;
    1082             :   }
    1083             :   else {
    1084             :     // The possible values returned for elevationType and their meanings are:
    1085             :     //   TokenElevationTypeDefault: The token does not have a linked token
    1086             :     //     (e.g. UAC disabled or a standard user, so they can't be elevated)
    1087             :     //   TokenElevationTypeFull: The token is linked to an elevated token
    1088             :     //     (e.g. UAC is enabled and the user is already elevated so they can't
    1089             :     //      be elevated again)
    1090             :     //   TokenElevationTypeLimited: The token is linked to a limited token
    1091             :     //     (e.g. UAC is enabled and the user is not elevated, so they can be
    1092             :     //      elevated)
    1093             :     *aUserCanElevate = (elevationType == VistaTokenElevationTypeLimited);
    1094             :   }
    1095             : 
    1096             :   if (hToken)
    1097             :     CloseHandle(hToken);
    1098             : 
    1099             :   return NS_OK;
    1100             : }
    1101             : #endif
    1102             : 
    1103             : NS_IMETHODIMP
    1104           0 : nsXULAppInfo::GetEnabled(bool *aEnabled)
    1105             : {
    1106           0 :   *aEnabled = CrashReporter::GetEnabled();
    1107           0 :   return NS_OK;
    1108             : }
    1109             : 
    1110             : NS_IMETHODIMP
    1111           0 : nsXULAppInfo::SetEnabled(bool aEnabled)
    1112             : {
    1113           0 :   if (aEnabled) {
    1114           0 :     if (CrashReporter::GetEnabled()) {
    1115             :       // no point in erroring for double-enabling
    1116             :       return NS_OK;
    1117             :     }
    1118             : 
    1119           0 :     nsCOMPtr<nsIFile> greBinDir;
    1120           0 :     NS_GetSpecialDirectory(NS_GRE_BIN_DIR, getter_AddRefs(greBinDir));
    1121           0 :     if (!greBinDir) {
    1122             :       return NS_ERROR_FAILURE;
    1123             :     }
    1124             : 
    1125           0 :     nsCOMPtr<nsIFile> xreBinDirectory = do_QueryInterface(greBinDir);
    1126           0 :     if (!xreBinDirectory) {
    1127             :       return NS_ERROR_FAILURE;
    1128             :     }
    1129             : 
    1130           0 :     return CrashReporter::SetExceptionHandler(xreBinDirectory, true);
    1131             :   }
    1132             : 
    1133           0 :   if (!CrashReporter::GetEnabled()) {
    1134             :     // no point in erroring for double-disabling
    1135             :     return NS_OK;
    1136             :   }
    1137             : 
    1138           0 :   return CrashReporter::UnsetExceptionHandler();
    1139             : }
    1140             : 
    1141             : NS_IMETHODIMP
    1142           0 : nsXULAppInfo::GetServerURL(nsIURL** aServerURL)
    1143             : {
    1144           0 :   NS_ENSURE_ARG_POINTER(aServerURL);
    1145           0 :   if (!CrashReporter::GetEnabled())
    1146             :     return NS_ERROR_NOT_INITIALIZED;
    1147             : 
    1148           0 :   nsAutoCString data;
    1149           0 :   if (!CrashReporter::GetServerURL(data)) {
    1150             :     return NS_ERROR_FAILURE;
    1151             :   }
    1152           0 :   nsCOMPtr<nsIURI> uri;
    1153           0 :   NS_NewURI(getter_AddRefs(uri), data);
    1154           0 :   if (!uri)
    1155             :     return NS_ERROR_FAILURE;
    1156             : 
    1157           0 :   nsCOMPtr<nsIURL> url;
    1158           0 :   url = do_QueryInterface(uri);
    1159           0 :   NS_ADDREF(*aServerURL = url);
    1160             : 
    1161             :   return NS_OK;
    1162             : }
    1163             : 
    1164             : NS_IMETHODIMP
    1165           0 : nsXULAppInfo::SetServerURL(nsIURL* aServerURL)
    1166             : {
    1167             :   bool schemeOk;
    1168             :   // only allow https or http URLs
    1169           0 :   nsresult rv = aServerURL->SchemeIs("https", &schemeOk);
    1170           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1171           0 :   if (!schemeOk) {
    1172           0 :     rv = aServerURL->SchemeIs("http", &schemeOk);
    1173           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1174             : 
    1175           0 :     if (!schemeOk)
    1176             :       return NS_ERROR_INVALID_ARG;
    1177             :   }
    1178           0 :   nsAutoCString spec;
    1179           0 :   rv = aServerURL->GetSpec(spec);
    1180           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1181             : 
    1182           0 :   return CrashReporter::SetServerURL(spec);
    1183             : }
    1184             : 
    1185             : NS_IMETHODIMP
    1186           0 : nsXULAppInfo::GetMinidumpPath(nsIFile** aMinidumpPath)
    1187             : {
    1188           0 :   if (!CrashReporter::GetEnabled())
    1189             :     return NS_ERROR_NOT_INITIALIZED;
    1190             : 
    1191           0 :   nsAutoString path;
    1192           0 :   if (!CrashReporter::GetMinidumpPath(path))
    1193             :     return NS_ERROR_FAILURE;
    1194             : 
    1195           0 :   nsresult rv = NS_NewLocalFile(path, false, aMinidumpPath);
    1196           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1197             :   return NS_OK;
    1198             : }
    1199             : 
    1200             : NS_IMETHODIMP
    1201           0 : nsXULAppInfo::SetMinidumpPath(nsIFile* aMinidumpPath)
    1202             : {
    1203           0 :   nsAutoString path;
    1204           0 :   nsresult rv = aMinidumpPath->GetPath(path);
    1205           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1206           0 :   return CrashReporter::SetMinidumpPath(path);
    1207             : }
    1208             : 
    1209             : NS_IMETHODIMP
    1210           0 : nsXULAppInfo::GetMinidumpForID(const nsAString& aId, nsIFile** aMinidump)
    1211             : {
    1212           0 :   if (!CrashReporter::GetMinidumpForID(aId, aMinidump)) {
    1213             :     return NS_ERROR_FILE_NOT_FOUND;
    1214             :   }
    1215             : 
    1216           0 :   return NS_OK;
    1217             : }
    1218             : 
    1219             : NS_IMETHODIMP
    1220           0 : nsXULAppInfo::GetExtraFileForID(const nsAString& aId, nsIFile** aExtraFile)
    1221             : {
    1222           0 :   if (!CrashReporter::GetExtraFileForID(aId, aExtraFile)) {
    1223             :     return NS_ERROR_FILE_NOT_FOUND;
    1224             :   }
    1225             : 
    1226           0 :   return NS_OK;
    1227             : }
    1228             : 
    1229             : NS_IMETHODIMP
    1230          14 : nsXULAppInfo::AnnotateCrashReport(const nsACString& key,
    1231             :                                   const nsACString& data)
    1232             : {
    1233          14 :   return CrashReporter::AnnotateCrashReport(key, data);
    1234             : }
    1235             : 
    1236             : NS_IMETHODIMP
    1237           0 : nsXULAppInfo::AppendAppNotesToCrashReport(const nsACString& data)
    1238             : {
    1239           0 :   return CrashReporter::AppendAppNotesToCrashReport(data);
    1240             : }
    1241             : 
    1242             : NS_IMETHODIMP
    1243           0 : nsXULAppInfo::RegisterAppMemory(uint64_t pointer,
    1244             :                                 uint64_t len)
    1245             : {
    1246           0 :   return CrashReporter::RegisterAppMemory((void *)pointer, len);
    1247             : }
    1248             : 
    1249             : NS_IMETHODIMP
    1250           0 : nsXULAppInfo::WriteMinidumpForException(void* aExceptionInfo)
    1251             : {
    1252             : #ifdef XP_WIN32
    1253             :   return CrashReporter::WriteMinidumpForException(static_cast<EXCEPTION_POINTERS*>(aExceptionInfo));
    1254             : #else
    1255           0 :   return NS_ERROR_NOT_IMPLEMENTED;
    1256             : #endif
    1257             : }
    1258             : 
    1259             : NS_IMETHODIMP
    1260           0 : nsXULAppInfo::AppendObjCExceptionInfoToAppNotes(void* aException)
    1261             : {
    1262             : #ifdef XP_MACOSX
    1263             :   return CrashReporter::AppendObjCExceptionInfoToAppNotes(aException);
    1264             : #else
    1265           0 :   return NS_ERROR_NOT_IMPLEMENTED;
    1266             : #endif
    1267             : }
    1268             : 
    1269             : NS_IMETHODIMP
    1270           0 : nsXULAppInfo::GetSubmitReports(bool* aEnabled)
    1271             : {
    1272           0 :   return CrashReporter::GetSubmitReports(aEnabled);
    1273             : }
    1274             : 
    1275             : NS_IMETHODIMP
    1276           0 : nsXULAppInfo::SetSubmitReports(bool aEnabled)
    1277             : {
    1278           0 :   return CrashReporter::SetSubmitReports(aEnabled);
    1279             : }
    1280             : 
    1281             : NS_IMETHODIMP
    1282           0 : nsXULAppInfo::UpdateCrashEventsDir()
    1283             : {
    1284           0 :   CrashReporter::UpdateCrashEventsDir();
    1285           0 :   return NS_OK;
    1286             : }
    1287             : 
    1288             : NS_IMETHODIMP
    1289           0 : nsXULAppInfo::SaveMemoryReport()
    1290             : {
    1291           0 :   if (!CrashReporter::GetEnabled()) {
    1292             :     return NS_ERROR_NOT_INITIALIZED;
    1293             :   }
    1294           0 :   nsCOMPtr<nsIFile> file;
    1295           0 :   nsresult rv = CrashReporter::GetDefaultMemoryReportFile(getter_AddRefs(file));
    1296           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
    1297             :     return rv;
    1298             :   }
    1299             : 
    1300           0 :   nsString path;
    1301           0 :   file->GetPath(path);
    1302             : 
    1303             :   nsCOMPtr<nsIMemoryInfoDumper> dumper =
    1304           0 :     do_GetService("@mozilla.org/memory-info-dumper;1");
    1305           0 :   if (NS_WARN_IF(!dumper)) {
    1306             :     return NS_ERROR_UNEXPECTED;
    1307             :   }
    1308             : 
    1309           0 :   rv = dumper->DumpMemoryReportsToNamedFile(path, this, file, true /* anonymize */);
    1310           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
    1311             :     return rv;
    1312             :   }
    1313           0 :   return NS_OK;
    1314             : }
    1315             : 
    1316             : NS_IMETHODIMP
    1317           1 : nsXULAppInfo::SetTelemetrySessionId(const nsACString& id)
    1318             : {
    1319           0 :   CrashReporter::SetTelemetrySessionId(id);
    1320           1 :   return NS_OK;
    1321             : }
    1322             : 
    1323             : // This method is from nsIFInishDumpingCallback.
    1324             : NS_IMETHODIMP
    1325           0 : nsXULAppInfo::Callback(nsISupports* aData)
    1326             : {
    1327           0 :   nsCOMPtr<nsIFile> file = do_QueryInterface(aData);
    1328           0 :   MOZ_ASSERT(file);
    1329             : 
    1330           0 :   CrashReporter::SetMemoryReportFile(file);
    1331           0 :   return NS_OK;
    1332             : }
    1333             : 
    1334             : static const nsXULAppInfo kAppInfo;
    1335           1 : static nsresult AppInfoConstructor(nsISupports* aOuter,
    1336             :                                    REFNSIID aIID, void **aResult)
    1337             : {
    1338           1 :   NS_ENSURE_NO_AGGREGATION(aOuter);
    1339             : 
    1340             :   return const_cast<nsXULAppInfo*>(&kAppInfo)->
    1341           1 :     QueryInterface(aIID, aResult);
    1342             : }
    1343             : 
    1344             : bool gLogConsoleErrors = false;
    1345             : 
    1346             : #define NS_ENSURE_TRUE_LOG(x, ret)               \
    1347             :   PR_BEGIN_MACRO                                 \
    1348             :   if (MOZ_UNLIKELY(!(x))) {                      \
    1349             :     NS_WARNING("NS_ENSURE_TRUE(" #x ") failed"); \
    1350             :     gLogConsoleErrors = true;                    \
    1351             :     return ret;                                  \
    1352             :   }                                              \
    1353             :   PR_END_MACRO
    1354             : 
    1355             : #define NS_ENSURE_SUCCESS_LOG(res, ret)          \
    1356             :   NS_ENSURE_TRUE_LOG(NS_SUCCEEDED(res), ret)
    1357             : 
    1358             : /**
    1359             :  * Because we're starting/stopping XPCOM several times in different scenarios,
    1360             :  * this class is a stack-based critter that makes sure that XPCOM is shut down
    1361             :  * during early returns.
    1362             :  */
    1363             : 
    1364             : class ScopedXPCOMStartup
    1365             : {
    1366             : public:
    1367           0 :   ScopedXPCOMStartup() :
    1368           1 :     mServiceManager(nullptr) { }
    1369             :   ~ScopedXPCOMStartup();
    1370             : 
    1371             :   nsresult Initialize();
    1372             :   nsresult SetWindowCreator(nsINativeAppSupport* native);
    1373             : 
    1374             :   static nsresult CreateAppSupport(nsISupports* aOuter, REFNSIID aIID, void** aResult);
    1375             : 
    1376             : private:
    1377             :   nsIServiceManager* mServiceManager;
    1378             :   static nsINativeAppSupport* gNativeAppSupport;
    1379             : };
    1380             : 
    1381           0 : ScopedXPCOMStartup::~ScopedXPCOMStartup()
    1382             : {
    1383           0 :   NS_IF_RELEASE(gNativeAppSupport);
    1384             : 
    1385           0 :   if (mServiceManager) {
    1386             : #ifdef XP_MACOSX
    1387             :     // On OS X, we need a pool to catch cocoa objects that are autoreleased
    1388             :     // during teardown.
    1389             :     mozilla::MacAutoreleasePool pool;
    1390             : #endif
    1391             : 
    1392           0 :     nsCOMPtr<nsIAppStartup> appStartup (do_GetService(NS_APPSTARTUP_CONTRACTID));
    1393           0 :     if (appStartup)
    1394           0 :       appStartup->DestroyHiddenWindow();
    1395             : 
    1396           0 :     gDirServiceProvider->DoShutdown();
    1397           0 :     PROFILER_ADD_MARKER("Shutdown early");
    1398             : 
    1399           0 :     WriteConsoleLog();
    1400             : 
    1401           0 :     NS_ShutdownXPCOM(mServiceManager);
    1402           0 :     mServiceManager = nullptr;
    1403             :   }
    1404           0 : }
    1405             : 
    1406             : // {95d89e3e-a169-41a3-8e56-719978e15b12}
    1407             : #define APPINFO_CID \
    1408             :   { 0x95d89e3e, 0xa169, 0x41a3, { 0x8e, 0x56, 0x71, 0x99, 0x78, 0xe1, 0x5b, 0x12 } }
    1409             : 
    1410             : // {0C4A446C-EE82-41f2-8D04-D366D2C7A7D4}
    1411             : static const nsCID kNativeAppSupportCID =
    1412             :   { 0xc4a446c, 0xee82, 0x41f2, { 0x8d, 0x4, 0xd3, 0x66, 0xd2, 0xc7, 0xa7, 0xd4 } };
    1413             : 
    1414             : // {5F5E59CE-27BC-47eb-9D1F-B09CA9049836}
    1415             : static const nsCID kProfileServiceCID =
    1416             :   { 0x5f5e59ce, 0x27bc, 0x47eb, { 0x9d, 0x1f, 0xb0, 0x9c, 0xa9, 0x4, 0x98, 0x36 } };
    1417             : 
    1418             : static already_AddRefed<nsIFactory>
    1419           1 : ProfileServiceFactoryConstructor(const mozilla::Module& module, const mozilla::Module::CIDEntry& entry)
    1420             : {
    1421           0 :   nsCOMPtr<nsIFactory> factory;
    1422           0 :   NS_NewToolkitProfileFactory(getter_AddRefs(factory));
    1423           2 :   return factory.forget();
    1424             : }
    1425             : 
    1426             : NS_DEFINE_NAMED_CID(APPINFO_CID);
    1427             : 
    1428             : static const mozilla::Module::CIDEntry kXRECIDs[] = {
    1429             :   { &kAPPINFO_CID, false, nullptr, AppInfoConstructor },
    1430             :   { &kProfileServiceCID, false, ProfileServiceFactoryConstructor, nullptr },
    1431             :   { &kNativeAppSupportCID, false, nullptr, ScopedXPCOMStartup::CreateAppSupport },
    1432             :   { nullptr }
    1433             : };
    1434             : 
    1435             : static const mozilla::Module::ContractIDEntry kXREContracts[] = {
    1436             :   { XULAPPINFO_SERVICE_CONTRACTID, &kAPPINFO_CID },
    1437             :   { XULRUNTIME_SERVICE_CONTRACTID, &kAPPINFO_CID },
    1438             : #ifdef MOZ_CRASHREPORTER
    1439             :   { NS_CRASHREPORTER_CONTRACTID, &kAPPINFO_CID },
    1440             : #endif // MOZ_CRASHREPORTER
    1441             :   { NS_PROFILESERVICE_CONTRACTID, &kProfileServiceCID },
    1442             :   { NS_NATIVEAPPSUPPORT_CONTRACTID, &kNativeAppSupportCID },
    1443             :   { nullptr }
    1444             : };
    1445             : 
    1446             : static const mozilla::Module kXREModule = {
    1447             :   mozilla::Module::kVersion,
    1448             :   kXRECIDs,
    1449             :   kXREContracts
    1450             : };
    1451             : 
    1452             : NSMODULE_DEFN(Apprunner) = &kXREModule;
    1453             : 
    1454             : nsresult
    1455           1 : ScopedXPCOMStartup::Initialize()
    1456             : {
    1457           1 :   NS_ASSERTION(gDirServiceProvider, "Should not get here!");
    1458             : 
    1459             :   nsresult rv;
    1460             : 
    1461           0 :   rv = NS_InitXPCOM2(&mServiceManager, gDirServiceProvider->GetAppDir(),
    1462           0 :                      gDirServiceProvider);
    1463           1 :   if (NS_FAILED(rv)) {
    1464           0 :     NS_ERROR("Couldn't start xpcom!");
    1465           0 :     mServiceManager = nullptr;
    1466             :   }
    1467             :   else {
    1468             : #ifdef DEBUG
    1469             :     nsCOMPtr<nsIComponentRegistrar> reg =
    1470           0 :       do_QueryInterface(mServiceManager);
    1471           1 :     NS_ASSERTION(reg, "Service Manager doesn't QI to Registrar.");
    1472             : #endif
    1473             :   }
    1474             : 
    1475           1 :   return rv;
    1476             : }
    1477             : 
    1478             : /**
    1479             :  * This is a little factory class that serves as a singleton-service-factory
    1480             :  * for the nativeappsupport object.
    1481             :  */
    1482             : class nsSingletonFactory final : public nsIFactory
    1483             : {
    1484             : public:
    1485             :   NS_DECL_ISUPPORTS
    1486             :   NS_DECL_NSIFACTORY
    1487             : 
    1488             :   explicit nsSingletonFactory(nsISupports* aSingleton);
    1489             : 
    1490             : private:
    1491           0 :   ~nsSingletonFactory() { }
    1492             :   nsCOMPtr<nsISupports> mSingleton;
    1493             : };
    1494             : 
    1495           0 : nsSingletonFactory::nsSingletonFactory(nsISupports* aSingleton)
    1496           0 :   : mSingleton(aSingleton)
    1497             : {
    1498           0 :   NS_ASSERTION(mSingleton, "Singleton was null!");
    1499           0 : }
    1500             : 
    1501           0 : NS_IMPL_ISUPPORTS(nsSingletonFactory, nsIFactory)
    1502             : 
    1503             : NS_IMETHODIMP
    1504           0 : nsSingletonFactory::CreateInstance(nsISupports* aOuter,
    1505             :                                    const nsIID& aIID,
    1506             :                                    void* *aResult)
    1507             : {
    1508           0 :   NS_ENSURE_NO_AGGREGATION(aOuter);
    1509             : 
    1510           0 :   return mSingleton->QueryInterface(aIID, aResult);
    1511             : }
    1512             : 
    1513             : NS_IMETHODIMP
    1514           0 : nsSingletonFactory::LockFactory(bool)
    1515             : {
    1516           0 :   return NS_OK;
    1517             : }
    1518             : 
    1519             : /**
    1520             :  * Set our windowcreator on the WindowWatcher service.
    1521             :  */
    1522             : nsresult
    1523           1 : ScopedXPCOMStartup::SetWindowCreator(nsINativeAppSupport* native)
    1524             : {
    1525             :   nsresult rv;
    1526             : 
    1527           1 :   NS_IF_ADDREF(gNativeAppSupport = native);
    1528             : 
    1529             :   // Inform the chrome registry about OS accessibility
    1530             :   nsCOMPtr<nsIToolkitChromeRegistry> cr =
    1531           2 :     mozilla::services::GetToolkitChromeRegistryService();
    1532             : 
    1533           0 :   if (cr)
    1534           1 :     cr->CheckForOSAccessibility();
    1535             : 
    1536           0 :   nsCOMPtr<nsIWindowCreator> creator (do_GetService(NS_APPSTARTUP_CONTRACTID));
    1537           1 :   if (!creator) return NS_ERROR_UNEXPECTED;
    1538             : 
    1539             :   nsCOMPtr<nsIWindowWatcher> wwatch
    1540           0 :     (do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv));
    1541           1 :   NS_ENSURE_SUCCESS(rv, rv);
    1542             : 
    1543           2 :   return wwatch->SetWindowCreator(creator);
    1544             : }
    1545             : 
    1546             : /* static */ nsresult
    1547           0 : ScopedXPCOMStartup::CreateAppSupport(nsISupports* aOuter, REFNSIID aIID, void** aResult)
    1548             : {
    1549           0 :   if (aOuter)
    1550             :     return NS_ERROR_NO_AGGREGATION;
    1551             : 
    1552           0 :   if (!gNativeAppSupport)
    1553             :     return NS_ERROR_NOT_INITIALIZED;
    1554             : 
    1555           0 :   return gNativeAppSupport->QueryInterface(aIID, aResult);
    1556             : }
    1557             : 
    1558             : nsINativeAppSupport* ScopedXPCOMStartup::gNativeAppSupport;
    1559             : 
    1560           0 : static void DumpArbitraryHelp()
    1561             : {
    1562             :   nsresult rv;
    1563             : 
    1564           0 :   ScopedLogging log;
    1565             : 
    1566             :   {
    1567           0 :     ScopedXPCOMStartup xpcom;
    1568           0 :     xpcom.Initialize();
    1569             : 
    1570             :     nsCOMPtr<nsICommandLineRunner> cmdline
    1571           0 :       (do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
    1572           0 :     if (!cmdline)
    1573           0 :       return;
    1574             : 
    1575           0 :     nsCString text;
    1576           0 :     rv = cmdline->GetHelpText(text);
    1577           0 :     if (NS_SUCCEEDED(rv))
    1578           0 :       printf("%s", text.get());
    1579             :   }
    1580             : }
    1581             : 
    1582             : // English text needs to go into a dtd file.
    1583             : // But when this is called we have no components etc. These strings must either be
    1584             : // here, or in a native resource file.
    1585             : static void
    1586           0 : DumpHelp()
    1587             : {
    1588           0 :   printf("Usage: %s [ options ... ] [URL]\n"
    1589           0 :          "       where options include:\n\n", gArgv[0]);
    1590             : 
    1591             : #ifdef MOZ_X11
    1592             :   printf("X11 options\n"
    1593             :          "  --display=DISPLAY  X display to use\n"
    1594           0 :          "  --sync             Make X calls synchronous\n");
    1595             : #endif
    1596             : #ifdef XP_UNIX
    1597           0 :   printf("  --g-fatal-warnings Make all warnings fatal\n"
    1598           0 :          "\n%s options\n", (const char*) gAppData->name);
    1599             : #endif
    1600             : 
    1601           0 :   printf("  -h or --help       Print this message.\n"
    1602             :          "  -v or --version    Print %s version.\n"
    1603             :          "  -P <profile>       Start with <profile>.\n"
    1604             :          "  --profile <path>   Start with profile at <path>.\n"
    1605             :          "  --migration        Start with migration wizard.\n"
    1606             :          "  --ProfileManager   Start with ProfileManager.\n"
    1607             :          "  --no-remote        Do not accept or send remote commands; implies\n"
    1608             :          "                     --new-instance.\n"
    1609             :          "  --new-instance     Open new instance, not a new window in running instance.\n"
    1610             :          "  --UILocale <locale> Start with <locale> resources as UI Locale.\n"
    1611             :          "  --safe-mode        Disables extensions and themes for this session.\n"
    1612             :          "  -MOZ_LOG=<modules> Treated as MOZ_LOG=<modules> environment variable, overrides it.\n"
    1613             :          "  -MOZ_LOG_FILE=<file> Treated as MOZ_LOG_FILE=<file> environment variable, overrides it.\n"
    1614             :          "                     If MOZ_LOG_FILE is not specified as an argument or as an environment variable,\n"
    1615             :          "                     logging will be written to stdout.\n"
    1616           0 :          , (const char*)gAppData->name);
    1617             : 
    1618             : #if defined(XP_WIN)
    1619             :   printf("  --console          Start %s with a debugging console.\n", (const char*) gAppData->name);
    1620             : #endif
    1621             : 
    1622             : #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK) || defined(XP_MACOSX)
    1623           0 :   printf("  --headless         Run without a GUI.\n");
    1624             : #endif
    1625             : 
    1626             :   // this works, but only after the components have registered.  so if you drop in a new command line handler, --help
    1627             :   // won't not until the second run.
    1628             :   // out of the bug, because we ship a component.reg file, it works correctly.
    1629           0 :   DumpArbitraryHelp();
    1630           0 : }
    1631             : 
    1632             : #if defined(DEBUG) && defined(XP_WIN)
    1633             : #ifdef DEBUG_warren
    1634             : #define _CRTDBG_MAP_ALLOC
    1635             : #endif
    1636             : // Set a CRT ReportHook function to capture and format MSCRT
    1637             : // warnings, errors and assertions.
    1638             : // See http://msdn.microsoft.com/en-US/library/74kabxyx(v=VS.80).aspx
    1639             : #include <stdio.h>
    1640             : #include <crtdbg.h>
    1641             : #include "mozilla/mozalloc_abort.h"
    1642             : static int MSCRTReportHook( int aReportType, char *aMessage, int *oReturnValue)
    1643             : {
    1644             :   *oReturnValue = 0; // continue execution
    1645             : 
    1646             :   // Do not use fprintf or other functions which may allocate
    1647             :   // memory from the heap which may be corrupted. Instead,
    1648             :   // use fputs to output the leading portion of the message
    1649             :   // and use mozalloc_abort to emit the remainder of the
    1650             :   // message.
    1651             : 
    1652             :   switch(aReportType) {
    1653             :   case 0:
    1654             :     fputs("\nWARNING: CRT WARNING", stderr);
    1655             :     fputs(aMessage, stderr);
    1656             :     fputs("\n", stderr);
    1657             :     break;
    1658             :   case 1:
    1659             :     fputs("\n###!!! ABORT: CRT ERROR ", stderr);
    1660             :     mozalloc_abort(aMessage);
    1661             :     break;
    1662             :   case 2:
    1663             :     fputs("\n###!!! ABORT: CRT ASSERT ", stderr);
    1664             :     mozalloc_abort(aMessage);
    1665             :     break;
    1666             :   }
    1667             : 
    1668             :   // do not invoke the debugger
    1669             :   return 1;
    1670             : }
    1671             : 
    1672             : #endif
    1673             : 
    1674             : static inline void
    1675           0 : DumpVersion()
    1676             : {
    1677           0 :   if (gAppData->vendor)
    1678           0 :     printf("%s ", (const char*) gAppData->vendor);
    1679           0 :   printf("%s %s", (const char*) gAppData->name, (const char*) gAppData->version);
    1680           0 :   if (gAppData->copyright)
    1681           0 :       printf(", %s", (const char*) gAppData->copyright);
    1682           0 :   printf("\n");
    1683           0 : }
    1684             : 
    1685             : #ifdef MOZ_ENABLE_XREMOTE
    1686             : static RemoteResult
    1687           0 : ParseRemoteCommandLine(nsCString& program,
    1688             :                        const char** profile,
    1689             :                        const char** username)
    1690             : {
    1691             :   ArgResult ar;
    1692             : 
    1693           0 :   ar = CheckArg("p", profile, CheckArgFlag::None);
    1694           0 :   if (ar == ARG_BAD) {
    1695             :     // Leave it to the normal command line handling to handle this situation.
    1696             :     return REMOTE_NOT_FOUND;
    1697             :   }
    1698             : 
    1699           0 :   const char *temp = nullptr;
    1700           0 :   ar = CheckArg("a", &temp, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
    1701           0 :   if (ar == ARG_BAD) {
    1702           0 :     PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n");
    1703           0 :     return REMOTE_ARG_BAD;
    1704             :   }
    1705           0 :   if (ar == ARG_FOUND) {
    1706           0 :     program.Assign(temp);
    1707             :   }
    1708             : 
    1709           0 :   ar = CheckArg("u", username, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
    1710           0 :   if (ar == ARG_BAD) {
    1711           0 :     PR_fprintf(PR_STDERR, "Error: argument -u requires a username\n");
    1712           0 :     return REMOTE_ARG_BAD;
    1713             :   }
    1714             : 
    1715             :   return REMOTE_FOUND;
    1716             : }
    1717             : 
    1718             : static RemoteResult
    1719           0 : StartRemoteClient(const char* aDesktopStartupID,
    1720             :                   nsCString& program,
    1721             :                   const char* profile,
    1722             :                   const char* username)
    1723             : {
    1724           0 :   nsAutoPtr<nsRemoteClient> client;
    1725             : 
    1726             : #if defined(MOZ_ENABLE_DBUS) && defined(MOZ_WAYLAND)
    1727             :   client = new DBusRemoteClient();
    1728             : #else
    1729           0 :   client = new XRemoteClient();
    1730             : #endif
    1731             : 
    1732           0 :   nsresult rv = client->Init();
    1733           0 :   if (NS_FAILED(rv))
    1734             :     return REMOTE_NOT_FOUND;
    1735             : 
    1736           0 :   nsCString response;
    1737           0 :   bool success = false;
    1738           0 :   rv = client->SendCommandLine(program.get(), username, profile,
    1739             :                                gArgc, gArgv, aDesktopStartupID,
    1740           0 :                                getter_Copies(response), &success);
    1741             :   // did the command fail?
    1742           0 :   if (!success)
    1743             :     return REMOTE_NOT_FOUND;
    1744             : 
    1745             :   // The "command not parseable" error is returned when the
    1746             :   // nsICommandLineHandler throws a NS_ERROR_ABORT.
    1747           0 :   if (response.EqualsLiteral("500 command not parseable"))
    1748             :     return REMOTE_ARG_BAD;
    1749             : 
    1750           0 :   if (NS_FAILED(rv))
    1751             :     return REMOTE_NOT_FOUND;
    1752             : 
    1753           0 :   return REMOTE_FOUND;
    1754             : }
    1755             : #endif // MOZ_ENABLE_XREMOTE
    1756             : 
    1757             : void
    1758           0 : XRE_InitOmnijar(nsIFile* greOmni, nsIFile* appOmni)
    1759             : {
    1760           0 :   mozilla::Omnijar::Init(greOmni, appOmni);
    1761           0 : }
    1762             : 
    1763             : nsresult
    1764           4 : XRE_GetBinaryPath(nsIFile* *aResult)
    1765             : {
    1766           7 :   return mozilla::BinaryPath::GetFile(aResult);
    1767             : }
    1768             : 
    1769             : #ifdef XP_WIN
    1770             : #include "nsWindowsRestart.cpp"
    1771             : #include <shellapi.h>
    1772             : 
    1773             : typedef BOOL (WINAPI* SetProcessDEPPolicyFunc)(DWORD dwFlags);
    1774             : 
    1775             : static void
    1776             : RegisterApplicationRestartChanged(const char* aPref, void* aData) {
    1777             :   DWORD cchCmdLine = 0;
    1778             :   HRESULT rc =
    1779             :     ::GetApplicationRestartSettings(::GetCurrentProcess(), nullptr, &cchCmdLine, nullptr);
    1780             :   bool wasRegistered = false;
    1781             :   if (rc == S_OK) {
    1782             :     wasRegistered = true;
    1783             :   }
    1784             : 
    1785             :   if (Preferences::GetBool(PREF_WIN_REGISTER_APPLICATION_RESTART, false) && !wasRegistered) {
    1786             :     // Make the command line to use when restarting.
    1787             :     // Excludes argv[0] because RegisterApplicationRestart adds the
    1788             :     // executable name, replace that temporarily with -os-restarted
    1789             :     char* exeName = gRestartArgv[0];
    1790             :     gRestartArgv[0] = "-os-restarted";
    1791             :     wchar_t** restartArgvConverted =
    1792             :       AllocConvertUTF8toUTF16Strings(gRestartArgc, gRestartArgv);
    1793             :     gRestartArgv[0] = exeName;
    1794             : 
    1795             :     mozilla::UniquePtr<wchar_t[]> restartCommandLine;
    1796             :     if (restartArgvConverted) {
    1797             :       restartCommandLine = mozilla::MakeCommandLine(gRestartArgc, restartArgvConverted);
    1798             :       FreeAllocStrings(gRestartArgc, restartArgvConverted);
    1799             :     }
    1800             : 
    1801             :     if (restartCommandLine) {
    1802             :       // Flags RESTART_NO_PATCH and RESTART_NO_REBOOT are not set, so we
    1803             :       // should be restarted if terminated by an update or restart.
    1804             :       ::RegisterApplicationRestart(restartCommandLine.get(), RESTART_NO_CRASH |
    1805             :                                                              RESTART_NO_HANG);
    1806             :     }
    1807             :   } else if (wasRegistered) {
    1808             :     ::UnregisterApplicationRestart();
    1809             :   }
    1810             : }
    1811             : #endif // XP_WIN
    1812             : 
    1813             : // If aBlankCommandLine is true, then the application will be launched with a
    1814             : // blank command line instead of being launched with the same command line that
    1815             : // it was initially started with.
    1816           0 : static nsresult LaunchChild(nsINativeAppSupport* aNative,
    1817             :                             bool aBlankCommandLine = false)
    1818             : {
    1819           0 :   aNative->Quit(); // release DDE mutex, if we're holding it
    1820             : 
    1821             :   // Restart this process by exec'ing it into the current process
    1822             :   // if supported by the platform.  Otherwise, use NSPR.
    1823             : 
    1824             : #ifdef MOZ_JPROF
    1825             :   // make sure JPROF doesn't think we're E10s
    1826             :   unsetenv("JPROF_SLAVE");
    1827             : #endif
    1828             : 
    1829           0 :   if (aBlankCommandLine) {
    1830           0 :     gRestartArgc = 1;
    1831           0 :     gRestartArgv[gRestartArgc] = nullptr;
    1832             :   }
    1833             : 
    1834           0 :   SaveToEnv("MOZ_LAUNCHED_CHILD=1");
    1835             : 
    1836             : #if !defined(MOZ_WIDGET_ANDROID) // Android has separate restart code.
    1837             : #if defined(XP_MACOSX)
    1838             :   CommandLineServiceMac::SetupMacCommandLine(gRestartArgc, gRestartArgv, true);
    1839             :   LaunchChildMac(gRestartArgc, gRestartArgv);
    1840             : #else
    1841           0 :   nsCOMPtr<nsIFile> lf;
    1842           0 :   nsresult rv = XRE_GetBinaryPath(getter_AddRefs(lf));
    1843           0 :   if (NS_FAILED(rv))
    1844             :     return rv;
    1845             : 
    1846             : #if defined(XP_WIN)
    1847             :   nsAutoString exePath;
    1848             :   rv = lf->GetPath(exePath);
    1849             :   if (NS_FAILED(rv))
    1850             :     return rv;
    1851             : 
    1852             :   HANDLE hProcess;
    1853             :   if (!WinLaunchChild(exePath.get(), gRestartArgc, gRestartArgv, nullptr, &hProcess))
    1854             :     return NS_ERROR_FAILURE;
    1855             :   // Keep the current process around until the restarted process has created
    1856             :   // its message queue, to avoid the launched process's windows being forced
    1857             :   // into the background.
    1858             :   ::WaitForInputIdle(hProcess, kWaitForInputIdleTimeoutMS);
    1859             :   ::CloseHandle(hProcess);
    1860             : 
    1861             : #else
    1862           0 :   nsAutoCString exePath;
    1863           0 :   rv = lf->GetNativePath(exePath);
    1864           0 :   if (NS_FAILED(rv))
    1865             :     return rv;
    1866             : 
    1867             : #if defined(XP_UNIX)
    1868           0 :   if (execv(exePath.get(), gRestartArgv) == -1)
    1869             :     return NS_ERROR_FAILURE;
    1870             : #else
    1871             :   PRProcess* process = PR_CreateProcess(exePath.get(), gRestartArgv,
    1872             :                                         nullptr, nullptr);
    1873             :   if (!process) return NS_ERROR_FAILURE;
    1874             : 
    1875             :   int32_t exitCode;
    1876             :   PRStatus failed = PR_WaitProcess(process, &exitCode);
    1877             :   if (failed || exitCode)
    1878             :     return NS_ERROR_FAILURE;
    1879             : #endif // XP_UNIX
    1880             : #endif // WP_WIN
    1881             : #endif // WP_MACOSX
    1882             : #endif // MOZ_WIDGET_ANDROID
    1883             : 
    1884           0 :   return NS_ERROR_LAUNCHED_CHILD_PROCESS;
    1885             : }
    1886             : 
    1887             : static const char kProfileProperties[] =
    1888             :   "chrome://mozapps/locale/profile/profileSelection.properties";
    1889             : 
    1890             : namespace {
    1891             : 
    1892             : /**
    1893             :  * This class, instead of a raw nsresult, should be the return type of any
    1894             :  * function called by SelectProfile that initializes XPCOM.
    1895             :  */
    1896             : class ReturnAbortOnError
    1897             : {
    1898             : public:
    1899           0 :   MOZ_IMPLICIT ReturnAbortOnError(nsresult aRv)
    1900           0 :   {
    1901           0 :     mRv = ConvertRv(aRv);
    1902           0 :   }
    1903             : 
    1904             :   operator nsresult()
    1905             :   {
    1906           0 :     return mRv;
    1907             :   }
    1908             : 
    1909             : private:
    1910             :   inline nsresult
    1911           0 :   ConvertRv(nsresult aRv)
    1912             :   {
    1913           0 :     if (NS_SUCCEEDED(aRv) || aRv == NS_ERROR_LAUNCHED_CHILD_PROCESS) {
    1914             :       return aRv;
    1915             :     }
    1916             :     return NS_ERROR_ABORT;
    1917             :   }
    1918             : 
    1919             :   nsresult mRv;
    1920             : };
    1921             : 
    1922             : } // namespace
    1923             : 
    1924             : static ReturnAbortOnError
    1925           0 : ProfileLockedDialog(nsIFile* aProfileDir, nsIFile* aProfileLocalDir,
    1926             :                     nsIProfileUnlocker* aUnlocker,
    1927             :                     nsINativeAppSupport* aNative, nsIProfileLock* *aResult)
    1928             : {
    1929             :   nsresult rv;
    1930             : 
    1931           0 :   ScopedXPCOMStartup xpcom;
    1932           0 :   rv = xpcom.Initialize();
    1933           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1934             : 
    1935           0 :   mozilla::Telemetry::WriteFailedProfileLock(aProfileDir);
    1936             : 
    1937           0 :   rv = xpcom.SetWindowCreator(aNative);
    1938           0 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
    1939             : 
    1940             :   { //extra scoping is needed so we release these components before xpcom shutdown
    1941             :     nsCOMPtr<nsIStringBundleService> sbs =
    1942           0 :       mozilla::services::GetStringBundleService();
    1943           0 :     NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE);
    1944             : 
    1945           0 :     nsCOMPtr<nsIStringBundle> sb;
    1946           0 :     sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
    1947           0 :     NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE);
    1948             : 
    1949           0 :     NS_ConvertUTF8toUTF16 appName(gAppData->name);
    1950           0 :     const char16_t* params[] = {appName.get(), appName.get()};
    1951             : 
    1952           0 :     nsAutoString killMessage;
    1953             : #ifndef XP_MACOSX
    1954           0 :     rv = sb->FormatStringFromName(aUnlocker ? "restartMessageUnlocker"
    1955             :                                             : "restartMessageNoUnlocker",
    1956           0 :                                   params, 2, killMessage);
    1957             : #else
    1958             :     rv = sb->FormatStringFromName(aUnlocker ? "restartMessageUnlockerMac"
    1959             :                                             : "restartMessageNoUnlockerMac",
    1960             :                                   params, 2, killMessage);
    1961             : #endif
    1962           0 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
    1963             : 
    1964           0 :     nsAutoString killTitle;
    1965           0 :     rv = sb->FormatStringFromName("restartTitle", params, 1, killTitle);
    1966           0 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
    1967             : 
    1968           0 :     if (gfxPlatform::IsHeadless()) {
    1969             :       // TODO: make a way to turn off all dialogs when headless.
    1970           0 :       Output(true, "%s\n", NS_LossyConvertUTF16toASCII(killMessage).get());
    1971           0 :       return NS_ERROR_FAILURE;
    1972             :     }
    1973             : 
    1974             :     nsCOMPtr<nsIPromptService> ps
    1975           0 :       (do_GetService(NS_PROMPTSERVICE_CONTRACTID));
    1976           0 :     NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE);
    1977             : 
    1978           0 :     if (aUnlocker) {
    1979             :       int32_t button;
    1980             : #ifdef MOZ_WIDGET_ANDROID
    1981             :       java::GeckoAppShell::KillAnyZombies();
    1982             :       button = 0;
    1983             : #else
    1984             :       const uint32_t flags =
    1985             :         (nsIPromptService::BUTTON_TITLE_IS_STRING *
    1986             :          nsIPromptService::BUTTON_POS_0) +
    1987             :         (nsIPromptService::BUTTON_TITLE_CANCEL *
    1988           0 :          nsIPromptService::BUTTON_POS_1);
    1989             : 
    1990           0 :       bool checkState = false;
    1991           0 :       rv = ps->ConfirmEx(nullptr, killTitle.get(), killMessage.get(), flags,
    1992             :                          killTitle.get(), nullptr, nullptr, nullptr,
    1993           0 :                          &checkState, &button);
    1994           0 :       NS_ENSURE_SUCCESS_LOG(rv, rv);
    1995             : #endif
    1996             : 
    1997           0 :       if (button == 0) {
    1998           0 :         rv = aUnlocker->Unlock(nsIProfileUnlocker::FORCE_QUIT);
    1999           0 :         if (NS_FAILED(rv)) {
    2000           0 :           return rv;
    2001             :         }
    2002             : 
    2003           0 :         SaveFileToEnv("XRE_PROFILE_PATH", aProfileDir);
    2004           0 :         SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", aProfileLocalDir);
    2005             : 
    2006           0 :         return LaunchChild(aNative);
    2007             :       }
    2008             :     } else {
    2009             : #ifdef MOZ_WIDGET_ANDROID
    2010             :       if (java::GeckoAppShell::UnlockProfile()) {
    2011             :         return NS_LockProfilePath(aProfileDir, aProfileLocalDir,
    2012             :                                   nullptr, aResult);
    2013             :       }
    2014             : #else
    2015           0 :       rv = ps->Alert(nullptr, killTitle.get(), killMessage.get());
    2016           0 :       NS_ENSURE_SUCCESS_LOG(rv, rv);
    2017             : #endif
    2018             :     }
    2019             : 
    2020           0 :     return NS_ERROR_ABORT;
    2021             :   }
    2022             : }
    2023             : 
    2024             : static nsresult
    2025           0 : ProfileMissingDialog(nsINativeAppSupport* aNative)
    2026             : {
    2027             :   nsresult rv;
    2028             : 
    2029           0 :   ScopedXPCOMStartup xpcom;
    2030           0 :   rv = xpcom.Initialize();
    2031           0 :   NS_ENSURE_SUCCESS(rv, rv);
    2032             : 
    2033           0 :   rv = xpcom.SetWindowCreator(aNative);
    2034           0 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
    2035             : 
    2036             :   { //extra scoping is needed so we release these components before xpcom shutdown
    2037             :     nsCOMPtr<nsIStringBundleService> sbs =
    2038           0 :       mozilla::services::GetStringBundleService();
    2039           0 :     NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE);
    2040             : 
    2041           0 :     nsCOMPtr<nsIStringBundle> sb;
    2042           0 :     sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
    2043           0 :     NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE);
    2044             : 
    2045           0 :     NS_ConvertUTF8toUTF16 appName(gAppData->name);
    2046           0 :     const char16_t* params[] = {appName.get(), appName.get()};
    2047             : 
    2048             :     // profileMissing
    2049           0 :     nsAutoString missingMessage;
    2050           0 :     rv = sb->FormatStringFromName("profileMissing", params, 2, missingMessage);
    2051           0 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_ABORT);
    2052             : 
    2053           0 :     nsAutoString missingTitle;
    2054           0 :     rv = sb->FormatStringFromName("profileMissingTitle", params, 1, missingTitle);
    2055           0 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_ABORT);
    2056             : 
    2057           0 :     nsCOMPtr<nsIPromptService> ps(do_GetService(NS_PROMPTSERVICE_CONTRACTID));
    2058           0 :     NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE);
    2059             : 
    2060           0 :     ps->Alert(nullptr, missingTitle.get(), missingMessage.get());
    2061             : 
    2062           0 :     return NS_ERROR_ABORT;
    2063             :   }
    2064             : }
    2065             : 
    2066             : static nsresult
    2067           0 : ProfileLockedDialog(nsIToolkitProfile* aProfile, nsIProfileUnlocker* aUnlocker,
    2068             :                     nsINativeAppSupport* aNative, nsIProfileLock* *aResult)
    2069             : {
    2070           0 :   nsCOMPtr<nsIFile> profileDir;
    2071           0 :   nsresult rv = aProfile->GetRootDir(getter_AddRefs(profileDir));
    2072           0 :   if (NS_FAILED(rv)) return rv;
    2073             : 
    2074             :   bool exists;
    2075           0 :   profileDir->Exists(&exists);
    2076           0 :   if (!exists) {
    2077           0 :     return ProfileMissingDialog(aNative);
    2078             :   }
    2079             : 
    2080           0 :   nsCOMPtr<nsIFile> profileLocalDir;
    2081           0 :   rv = aProfile->GetLocalDir(getter_AddRefs(profileLocalDir));
    2082           0 :   if (NS_FAILED(rv)) return rv;
    2083             : 
    2084           0 :   return ProfileLockedDialog(profileDir, profileLocalDir, aUnlocker, aNative,
    2085           0 :                              aResult);
    2086             : }
    2087             : 
    2088             : static const char kProfileManagerURL[] =
    2089             :   "chrome://mozapps/content/profile/profileSelection.xul";
    2090             : 
    2091             : static ReturnAbortOnError
    2092           0 : ShowProfileManager(nsIToolkitProfileService* aProfileSvc,
    2093             :                    nsINativeAppSupport* aNative)
    2094             : {
    2095             :   if (!CanShowProfileManager()) {
    2096             :     return NS_ERROR_NOT_IMPLEMENTED;
    2097             :   }
    2098             : 
    2099             :   nsresult rv;
    2100             : 
    2101           0 :   nsCOMPtr<nsIFile> profD, profLD;
    2102             :   char16_t* profileNamePtr;
    2103           0 :   nsAutoCString profileName;
    2104             : 
    2105             :   {
    2106           0 :     ScopedXPCOMStartup xpcom;
    2107           0 :     rv = xpcom.Initialize();
    2108           0 :     NS_ENSURE_SUCCESS(rv, rv);
    2109             : 
    2110             :     // Initialize the graphics prefs, some of the paths need them before
    2111             :     // any other graphics is initialized (e.g., showing the profile chooser.)
    2112           0 :     gfxPrefs::GetSingleton();
    2113             : 
    2114           0 :     rv = xpcom.SetWindowCreator(aNative);
    2115           0 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
    2116             : 
    2117             : #ifdef XP_MACOSX
    2118             :     CommandLineServiceMac::SetupMacCommandLine(gRestartArgc, gRestartArgv, true);
    2119             : #endif
    2120             : 
    2121             : #ifdef XP_WIN
    2122             :     // we don't have to wait here because profile manager window will pump
    2123             :     // and DDE message will be handled
    2124             :     ProcessDDE(aNative, false);
    2125             : #endif
    2126             : 
    2127             :     { //extra scoping is needed so we release these components before xpcom shutdown
    2128             :       nsCOMPtr<nsIWindowWatcher> windowWatcher
    2129           0 :         (do_GetService(NS_WINDOWWATCHER_CONTRACTID));
    2130             :       nsCOMPtr<nsIDialogParamBlock> ioParamBlock
    2131           0 :         (do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID));
    2132           0 :       nsCOMPtr<nsIMutableArray> dlgArray (do_CreateInstance(NS_ARRAY_CONTRACTID));
    2133           0 :       NS_ENSURE_TRUE(windowWatcher && ioParamBlock && dlgArray, NS_ERROR_FAILURE);
    2134             : 
    2135           0 :       ioParamBlock->SetObjects(dlgArray);
    2136             : 
    2137             :       nsCOMPtr<nsIAppStartup> appStartup
    2138           0 :         (do_GetService(NS_APPSTARTUP_CONTRACTID));
    2139           0 :       NS_ENSURE_TRUE(appStartup, NS_ERROR_FAILURE);
    2140             : 
    2141           0 :       nsCOMPtr<mozIDOMWindowProxy> newWindow;
    2142           0 :       rv = windowWatcher->OpenWindow(nullptr,
    2143             :                                      kProfileManagerURL,
    2144             :                                      "_blank",
    2145             :                                      "centerscreen,chrome,modal,titlebar",
    2146             :                                      ioParamBlock,
    2147           0 :                                      getter_AddRefs(newWindow));
    2148             : 
    2149           0 :       NS_ENSURE_SUCCESS_LOG(rv, rv);
    2150             : 
    2151           0 :       aProfileSvc->Flush();
    2152             : 
    2153             :       int32_t dialogConfirmed;
    2154           0 :       rv = ioParamBlock->GetInt(0, &dialogConfirmed);
    2155           0 :       if (NS_FAILED(rv) || dialogConfirmed == 0) return NS_ERROR_ABORT;
    2156             : 
    2157           0 :       nsCOMPtr<nsIProfileLock> lock;
    2158           0 :       rv = dlgArray->QueryElementAt(0, NS_GET_IID(nsIProfileLock),
    2159           0 :                                     getter_AddRefs(lock));
    2160           0 :       NS_ENSURE_SUCCESS_LOG(rv, rv);
    2161             : 
    2162           0 :       rv = lock->GetDirectory(getter_AddRefs(profD));
    2163           0 :       NS_ENSURE_SUCCESS(rv, rv);
    2164             : 
    2165           0 :       rv = lock->GetLocalDirectory(getter_AddRefs(profLD));
    2166           0 :       NS_ENSURE_SUCCESS(rv, rv);
    2167             : 
    2168           0 :       rv = ioParamBlock->GetString(0, &profileNamePtr);
    2169           0 :       NS_ENSURE_SUCCESS(rv, rv);
    2170             : 
    2171           0 :       CopyUTF16toUTF8(profileNamePtr, profileName);
    2172           0 :       free(profileNamePtr);
    2173             : 
    2174           0 :       lock->Unlock();
    2175             :     }
    2176             :   }
    2177             : 
    2178           0 :   SaveFileToEnv("XRE_PROFILE_PATH", profD);
    2179           0 :   SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", profLD);
    2180           0 :   SaveWordToEnv("XRE_PROFILE_NAME", profileName);
    2181             : 
    2182           0 :   bool offline = false;
    2183           0 :   aProfileSvc->GetStartOffline(&offline);
    2184           0 :   if (offline) {
    2185           0 :     SaveToEnv("XRE_START_OFFLINE=1");
    2186             :   }
    2187           0 :   if (gRestartedByOS) {
    2188             :     // Re-add this argument when actually starting the application.
    2189           0 :     char** newArgv = (char**) realloc(gRestartArgv, sizeof(char*) * (gRestartArgc + 2));
    2190           0 :     NS_ENSURE_TRUE(newArgv, NS_ERROR_OUT_OF_MEMORY);
    2191           0 :     gRestartArgv = newArgv;
    2192           0 :     gRestartArgv[gRestartArgc++] = const_cast<char*>("-os-restarted");
    2193           0 :     gRestartArgv[gRestartArgc] = nullptr;
    2194             :   }
    2195             : 
    2196           0 :   return LaunchChild(aNative);
    2197             : }
    2198             : 
    2199             : /**
    2200             :  * Get the currently running profile using its root directory.
    2201             :  *
    2202             :  * @param aProfileSvc         The profile service
    2203             :  * @param aCurrentProfileRoot The root directory of the current profile.
    2204             :  * @param aProfile            Out-param that returns the profile object.
    2205             :  * @return an error if aCurrentProfileRoot is not found
    2206             :  */
    2207             : static nsresult
    2208           0 : GetCurrentProfile(nsIToolkitProfileService* aProfileSvc,
    2209             :                   nsIFile* aCurrentProfileRoot,
    2210             :                   nsIToolkitProfile** aProfile)
    2211             : {
    2212           0 :   NS_ENSURE_ARG_POINTER(aProfileSvc);
    2213           0 :   NS_ENSURE_ARG_POINTER(aProfile);
    2214             : 
    2215           0 :   nsCOMPtr<nsISimpleEnumerator> profiles;
    2216           0 :   nsresult rv = aProfileSvc->GetProfiles(getter_AddRefs(profiles));
    2217           0 :   if (NS_FAILED(rv))
    2218             :     return rv;
    2219             : 
    2220           0 :   bool foundMatchingProfile = false;
    2221           0 :   nsCOMPtr<nsISupports> supports;
    2222           0 :   rv = profiles->GetNext(getter_AddRefs(supports));
    2223           0 :   while (NS_SUCCEEDED(rv)) {
    2224           0 :     nsCOMPtr<nsIToolkitProfile> profile = do_QueryInterface(supports);
    2225           0 :     nsCOMPtr<nsIFile> profileRoot;
    2226           0 :     profile->GetRootDir(getter_AddRefs(profileRoot));
    2227           0 :     profileRoot->Equals(aCurrentProfileRoot, &foundMatchingProfile);
    2228           0 :     if (foundMatchingProfile) {
    2229           0 :       profile.forget(aProfile);
    2230           0 :       return NS_OK;
    2231             :     }
    2232           0 :     rv = profiles->GetNext(getter_AddRefs(supports));
    2233             :   }
    2234             :   return rv;
    2235             : }
    2236             : 
    2237             : static bool gDoMigration = false;
    2238             : static bool gDoProfileReset = false;
    2239           1 : static nsAutoCString gResetOldProfileName;
    2240             : 
    2241             : // Pick a profile. We need to end up with a profile lock.
    2242             : //
    2243             : // 1) check for --profile <path>
    2244             : // 2) check for -P <name>
    2245             : // 3) check for --ProfileManager
    2246             : // 4) use the default profile, if there is one
    2247             : // 5) if there are *no* profiles, set up profile-migration
    2248             : // 6) display the profile-manager UI
    2249             : static nsresult
    2250           0 : SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, nsINativeAppSupport* aNative,
    2251             :               bool* aStartOffline, nsACString* aProfileName)
    2252             : {
    2253           0 :   StartupTimeline::Record(StartupTimeline::SELECT_PROFILE);
    2254             : 
    2255             :   nsresult rv;
    2256             :   ArgResult ar;
    2257             :   const char* arg;
    2258           0 :   *aResult = nullptr;
    2259           1 :   *aStartOffline = false;
    2260             : 
    2261           0 :   ar = CheckArg("offline", nullptr, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
    2262           0 :   if (ar == ARG_BAD) {
    2263           0 :     PR_fprintf(PR_STDERR, "Error: argument --offline is invalid when argument --osint is specified\n");
    2264           0 :     return NS_ERROR_FAILURE;
    2265             :   }
    2266             : 
    2267           1 :   if (ar || EnvHasValue("XRE_START_OFFLINE"))
    2268           0 :     *aStartOffline = true;
    2269             : 
    2270           0 :   if (EnvHasValue("MOZ_RESET_PROFILE_RESTART")) {
    2271           0 :     gDoProfileReset = true;
    2272           0 :     gDoMigration = true;
    2273           0 :     SaveToEnv("MOZ_RESET_PROFILE_RESTART=");
    2274             :     // We only want to restore the previous session if the profile refresh was
    2275             :     // triggered by user. And if it was a user-triggered profile refresh
    2276             :     // through, say, the safeMode dialog or the troubleshooting page, the MOZ_RESET_PROFILE_RESTART
    2277             :     // env variable would be set. Hence we set MOZ_RESET_PROFILE_MIGRATE_SESSION here so that
    2278             :     // Firefox profile migrator would migrate old session data later.
    2279           0 :     SaveToEnv("MOZ_RESET_PROFILE_MIGRATE_SESSION=1");
    2280             :   }
    2281             : 
    2282             :   // reset-profile and migration args need to be checked before any profiles are chosen below.
    2283           0 :   ar = CheckArg("reset-profile", nullptr, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
    2284           0 :   if (ar == ARG_BAD) {
    2285           0 :     PR_fprintf(PR_STDERR, "Error: argument --reset-profile is invalid when argument --osint is specified\n");
    2286           0 :     return NS_ERROR_FAILURE;
    2287             :   }
    2288           0 :   if (ar == ARG_FOUND) {
    2289           0 :     gDoProfileReset = true;
    2290             :   }
    2291             : 
    2292           0 :   ar = CheckArg("migration", nullptr, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
    2293           0 :   if (ar == ARG_BAD) {
    2294           0 :     PR_fprintf(PR_STDERR, "Error: argument --migration is invalid when argument --osint is specified\n");
    2295           0 :     return NS_ERROR_FAILURE;
    2296             :   }
    2297           1 :   if (ar == ARG_FOUND) {
    2298           0 :     gDoMigration = true;
    2299             :   }
    2300             : 
    2301           0 :   nsCOMPtr<nsIFile> lf = GetFileFromEnv("XRE_PROFILE_PATH");
    2302           0 :   if (lf) {
    2303             :     nsCOMPtr<nsIFile> localDir =
    2304           0 :       GetFileFromEnv("XRE_PROFILE_LOCAL_PATH");
    2305           0 :     if (!localDir) {
    2306           0 :       localDir = lf;
    2307             :     }
    2308             : 
    2309           0 :     arg = PR_GetEnv("XRE_PROFILE_NAME");
    2310           0 :     if (arg && *arg && aProfileName) {
    2311           0 :       aProfileName->Assign(nsDependentCString(arg));
    2312           0 :       if (gDoProfileReset) {
    2313           0 :         gResetOldProfileName.Assign(*aProfileName);
    2314             :       }
    2315             :     }
    2316             : 
    2317             :     // Clear out flags that we handled (or should have handled!) last startup.
    2318             :     const char *dummy;
    2319           0 :     CheckArg("p", &dummy);
    2320           0 :     CheckArg("profile", &dummy);
    2321           0 :     CheckArg("profilemanager");
    2322             : 
    2323           0 :     if (gDoProfileReset) {
    2324             :       // If we're resetting a profile, create a new one and use it to startup.
    2325           0 :       nsCOMPtr<nsIToolkitProfile> newProfile;
    2326           0 :       rv = CreateResetProfile(aProfileSvc, gResetOldProfileName, getter_AddRefs(newProfile));
    2327           0 :       if (NS_SUCCEEDED(rv)) {
    2328           0 :         rv = newProfile->GetRootDir(getter_AddRefs(lf));
    2329           0 :         NS_ENSURE_SUCCESS(rv, rv);
    2330           0 :         SaveFileToEnv("XRE_PROFILE_PATH", lf);
    2331             : 
    2332           0 :         rv = newProfile->GetLocalDir(getter_AddRefs(localDir));
    2333           0 :         NS_ENSURE_SUCCESS(rv, rv);
    2334           0 :         SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", localDir);
    2335             : 
    2336           0 :         rv = newProfile->GetName(*aProfileName);
    2337           0 :         if (NS_FAILED(rv))
    2338           0 :           aProfileName->Truncate(0);
    2339           0 :         SaveWordToEnv("XRE_PROFILE_NAME", *aProfileName);
    2340             :       } else {
    2341           0 :         NS_WARNING("Profile reset failed.");
    2342           0 :         gDoProfileReset = false;
    2343             :       }
    2344             :     }
    2345             : 
    2346           0 :     return NS_LockProfilePath(lf, localDir, nullptr, aResult);
    2347             :   }
    2348             : 
    2349           1 :   ar = CheckArg("profile", &arg, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
    2350           1 :   if (ar == ARG_BAD) {
    2351           0 :     PR_fprintf(PR_STDERR, "Error: argument --profile requires a path\n");
    2352           0 :     return NS_ERROR_FAILURE;
    2353             :   }
    2354           1 :   if (ar) {
    2355           0 :     if (gDoProfileReset) {
    2356           0 :       NS_WARNING("Profile reset is not supported in conjunction with --profile.");
    2357           0 :       gDoProfileReset = false;
    2358             :     }
    2359             : 
    2360           0 :     nsCOMPtr<nsIFile> lf;
    2361           1 :     rv = XRE_GetFileFromPath(arg, getter_AddRefs(lf));
    2362           1 :     NS_ENSURE_SUCCESS(rv, rv);
    2363             : 
    2364           2 :     nsCOMPtr<nsIProfileUnlocker> unlocker;
    2365             : 
    2366             :     // Check if the profile path exists and it's a directory.
    2367             :     bool exists;
    2368           0 :     lf->Exists(&exists);
    2369           1 :     if (!exists) {
    2370           0 :         rv = lf->Create(nsIFile::DIRECTORY_TYPE, 0700);
    2371           0 :         NS_ENSURE_SUCCESS(rv, rv);
    2372             :     }
    2373             : 
    2374             :     // If a profile path is specified directory on the command line, then
    2375             :     // assume that the temp directory is the same as the given directory.
    2376           1 :     rv = NS_LockProfilePath(lf, lf, getter_AddRefs(unlocker), aResult);
    2377           1 :     if (NS_SUCCEEDED(rv))
    2378             :       return rv;
    2379             : 
    2380           0 :     return ProfileLockedDialog(lf, lf, unlocker, aNative, aResult);
    2381             :   }
    2382             : 
    2383           0 :   ar = CheckArg("createprofile", &arg, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
    2384           0 :   if (ar == ARG_BAD) {
    2385           0 :     PR_fprintf(PR_STDERR, "Error: argument --createprofile requires a profile name\n");
    2386           0 :     return NS_ERROR_FAILURE;
    2387             :   }
    2388           0 :   if (ar) {
    2389           0 :     nsCOMPtr<nsIToolkitProfile> profile;
    2390             : 
    2391           0 :     const char* delim = strchr(arg, ' ');
    2392           0 :     if (delim) {
    2393           0 :       nsCOMPtr<nsIFile> lf;
    2394           0 :       rv = NS_NewNativeLocalFile(nsDependentCString(delim + 1),
    2395           0 :                                    true, getter_AddRefs(lf));
    2396           0 :       if (NS_FAILED(rv)) {
    2397           0 :         PR_fprintf(PR_STDERR, "Error: profile path not valid.\n");
    2398           0 :         return rv;
    2399             :       }
    2400             : 
    2401             :       // As with --profile, assume that the given path will be used for the
    2402             :       // main profile directory.
    2403           0 :       rv = aProfileSvc->CreateProfile(lf, nsDependentCSubstring(arg, delim),
    2404           0 :                                      getter_AddRefs(profile));
    2405             :     } else {
    2406           0 :       rv = aProfileSvc->CreateProfile(nullptr, nsDependentCString(arg),
    2407           0 :                                      getter_AddRefs(profile));
    2408             :     }
    2409             :     // Some pathological arguments can make it this far
    2410           0 :     if (NS_FAILED(rv)) {
    2411           0 :       PR_fprintf(PR_STDERR, "Error creating profile.\n");
    2412           0 :       return rv;
    2413             :     }
    2414           0 :     rv = NS_ERROR_ABORT;
    2415           0 :     aProfileSvc->Flush();
    2416             : 
    2417             :     // XXXben need to ensure prefs.js exists here so the tinderboxes will
    2418             :     //        not go orange.
    2419           0 :     nsCOMPtr<nsIFile> prefsJSFile;
    2420           0 :     profile->GetRootDir(getter_AddRefs(prefsJSFile));
    2421           0 :     prefsJSFile->AppendNative(NS_LITERAL_CSTRING("prefs.js"));
    2422           0 :     PR_fprintf(PR_STDERR, "Success: created profile '%s' at '%s'\n", arg,
    2423           0 :                prefsJSFile->HumanReadablePath().get());
    2424             :     bool exists;
    2425           0 :     prefsJSFile->Exists(&exists);
    2426           0 :     if (!exists) {
    2427             :       // Ignore any errors; we're about to return NS_ERROR_ABORT anyway.
    2428           0 :       Unused << prefsJSFile->Create(nsIFile::NORMAL_FILE_TYPE, 0644);
    2429             :     }
    2430             :     // XXXdarin perhaps 0600 would be better?
    2431             : 
    2432             :     return rv;
    2433             :   }
    2434             : 
    2435             :   uint32_t count;
    2436           0 :   rv = aProfileSvc->GetProfileCount(&count);
    2437           0 :   NS_ENSURE_SUCCESS(rv, rv);
    2438             : 
    2439           0 :   ar = CheckArg("p", &arg);
    2440           0 :   if (ar == ARG_BAD) {
    2441           0 :     ar = CheckArg("osint");
    2442           0 :     if (ar == ARG_FOUND) {
    2443           0 :       PR_fprintf(PR_STDERR, "Error: argument -p is invalid when argument --osint is specified\n");
    2444           0 :       return NS_ERROR_FAILURE;
    2445             :     }
    2446             : 
    2447             :     if (CanShowProfileManager()) {
    2448           0 :       return ShowProfileManager(aProfileSvc, aNative);
    2449             :     }
    2450             :   }
    2451           0 :   if (ar) {
    2452           0 :     ar = CheckArg("osint");
    2453           0 :     if (ar == ARG_FOUND) {
    2454           0 :       PR_fprintf(PR_STDERR, "Error: argument -p is invalid when argument --osint is specified\n");
    2455           0 :       return NS_ERROR_FAILURE;
    2456             :     }
    2457           0 :     nsCOMPtr<nsIToolkitProfile> profile;
    2458           0 :     rv = aProfileSvc->GetProfileByName(nsDependentCString(arg),
    2459           0 :                                       getter_AddRefs(profile));
    2460           0 :     if (NS_SUCCEEDED(rv)) {
    2461           0 :       if (gDoProfileReset) {
    2462             :         {
    2463             :           // Check that the source profile is not in use by temporarily acquiring its lock.
    2464             :           nsIProfileLock* tempProfileLock;
    2465           0 :           nsCOMPtr<nsIProfileUnlocker> unlocker;
    2466           0 :           rv = profile->Lock(getter_AddRefs(unlocker), &tempProfileLock);
    2467           0 :           if (NS_FAILED(rv))
    2468           0 :             return ProfileLockedDialog(profile, unlocker, aNative, &tempProfileLock);
    2469             :         }
    2470             : 
    2471           0 :         nsresult gotName = profile->GetName(gResetOldProfileName);
    2472           0 :         if (NS_SUCCEEDED(gotName)) {
    2473           0 :           nsCOMPtr<nsIToolkitProfile> newProfile;
    2474           0 :           rv = CreateResetProfile(aProfileSvc, gResetOldProfileName, getter_AddRefs(newProfile));
    2475           0 :           if (NS_FAILED(rv)) {
    2476           0 :             NS_WARNING("Failed to create a profile to reset to.");
    2477           0 :             gDoProfileReset = false;
    2478             :           } else {
    2479           0 :             profile = newProfile;
    2480             :           }
    2481             :         } else {
    2482           0 :           NS_WARNING("Failed to get the name of the profile we're resetting, so aborting reset.");
    2483           0 :           gResetOldProfileName.Truncate(0);
    2484           0 :           gDoProfileReset = false;
    2485             :         }
    2486             :       }
    2487             : 
    2488           0 :       nsCOMPtr<nsIProfileUnlocker> unlocker;
    2489           0 :       rv = profile->Lock(getter_AddRefs(unlocker), aResult);
    2490           0 :       if (NS_SUCCEEDED(rv)) {
    2491           0 :         if (aProfileName)
    2492           0 :           aProfileName->Assign(nsDependentCString(arg));
    2493             :         return NS_OK;
    2494             :       }
    2495             : 
    2496           0 :       return ProfileLockedDialog(profile, unlocker, aNative, aResult);
    2497             :     }
    2498             : 
    2499             :     if (CanShowProfileManager()) {
    2500           0 :       return ShowProfileManager(aProfileSvc, aNative);
    2501             :     }
    2502             :   }
    2503             : 
    2504           0 :   ar = CheckArg("profilemanager", nullptr, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
    2505           0 :   if (ar == ARG_BAD) {
    2506           0 :     PR_fprintf(PR_STDERR, "Error: argument --profilemanager is invalid when argument --osint is specified\n");
    2507           0 :     return NS_ERROR_FAILURE;
    2508             :   }
    2509           0 :   if (ar == ARG_FOUND && CanShowProfileManager()) {
    2510           0 :     return ShowProfileManager(aProfileSvc, aNative);
    2511             :   }
    2512             : 
    2513             : #ifndef MOZ_DEV_EDITION
    2514             :   // If the only existing profile is the dev-edition-profile and this is not
    2515             :   // Developer Edition, then no valid profiles were found.
    2516           0 :   if (count == 1) {
    2517           0 :     nsCOMPtr<nsIToolkitProfile> deProfile;
    2518             :     // GetSelectedProfile will auto-select the only profile if there's just one
    2519           0 :     aProfileSvc->GetSelectedProfile(getter_AddRefs(deProfile));
    2520           0 :     nsAutoCString profileName;
    2521           0 :     deProfile->GetName(profileName);
    2522           0 :     if (profileName.EqualsLiteral("dev-edition-default")) {
    2523           0 :       count = 0;
    2524             :     }
    2525             :   }
    2526             : #endif
    2527             : 
    2528           0 :   if (!count) {
    2529             :     // For a fresh install, we would like to let users decide
    2530             :     // to do profile migration on their own later after using.
    2531           0 :     gDoMigration = false;
    2532           0 :     gDoProfileReset = false;
    2533             : 
    2534             :     // create a default profile
    2535           0 :     nsCOMPtr<nsIToolkitProfile> profile;
    2536           0 :     nsresult rv = aProfileSvc->CreateProfile(nullptr, // choose a default dir for us
    2537             : #ifdef MOZ_DEV_EDITION
    2538             :                                              NS_LITERAL_CSTRING("dev-edition-default"),
    2539             : #else
    2540           0 :                                              NS_LITERAL_CSTRING("default"),
    2541             : #endif
    2542           0 :                                              getter_AddRefs(profile));
    2543           0 :     if (NS_SUCCEEDED(rv)) {
    2544             : #ifndef MOZ_DEV_EDITION
    2545           0 :       aProfileSvc->SetDefaultProfile(profile);
    2546             : #endif
    2547           0 :       aProfileSvc->Flush();
    2548           0 :       rv = profile->Lock(nullptr, aResult);
    2549           0 :       if (NS_SUCCEEDED(rv)) {
    2550           0 :         if (aProfileName)
    2551             : #ifdef MOZ_DEV_EDITION
    2552             :           aProfileName->AssignLiteral("dev-edition-default");
    2553             : #else
    2554           0 :           aProfileName->AssignLiteral("default");
    2555             : #endif
    2556           0 :         return NS_OK;
    2557             :       }
    2558             :     }
    2559             :   }
    2560             : 
    2561           0 :   bool useDefault = true;
    2562           0 :   if (count > 1 && CanShowProfileManager()) {
    2563           0 :     aProfileSvc->GetStartWithLastProfile(&useDefault);
    2564             :   }
    2565             : 
    2566           0 :   if (useDefault) {
    2567           0 :     nsCOMPtr<nsIToolkitProfile> profile;
    2568             :     // GetSelectedProfile will auto-select the only profile if there's just one
    2569           0 :     aProfileSvc->GetSelectedProfile(getter_AddRefs(profile));
    2570           0 :     if (profile) {
    2571             :       // If we're resetting a profile, create a new one and use it to startup.
    2572           0 :       if (gDoProfileReset) {
    2573             :         {
    2574             :           // Check that the source profile is not in use by temporarily acquiring its lock.
    2575             :           nsIProfileLock* tempProfileLock;
    2576           0 :           nsCOMPtr<nsIProfileUnlocker> unlocker;
    2577           0 :           rv = profile->Lock(getter_AddRefs(unlocker), &tempProfileLock);
    2578           0 :           if (NS_FAILED(rv))
    2579           0 :             return ProfileLockedDialog(profile, unlocker, aNative, &tempProfileLock);
    2580             :         }
    2581             : 
    2582           0 :         nsresult gotName = profile->GetName(gResetOldProfileName);
    2583           0 :         if (NS_SUCCEEDED(gotName)) {
    2584           0 :           nsCOMPtr<nsIToolkitProfile> newProfile;
    2585           0 :           rv = CreateResetProfile(aProfileSvc, gResetOldProfileName, getter_AddRefs(newProfile));
    2586           0 :           if (NS_FAILED(rv)) {
    2587           0 :             NS_WARNING("Failed to create a profile to reset to.");
    2588           0 :             gDoProfileReset = false;
    2589             :           }
    2590             :           else {
    2591           0 :             profile = newProfile;
    2592             :           }
    2593             :         }
    2594             :         else {
    2595           0 :           NS_WARNING("Failed to get the name of the profile we're resetting, so aborting reset.");
    2596           0 :           gResetOldProfileName.Truncate(0);
    2597           0 :           gDoProfileReset = false;
    2598             :         }
    2599             :       }
    2600             : 
    2601             :       // If you close Firefox and very quickly reopen it, the old Firefox may
    2602             :       // still be closing down. Rather than immediately showing the
    2603             :       // "Firefox is running but is not responding" message, we spend a few
    2604             :       // seconds retrying first.
    2605             : 
    2606             :       static const int kLockRetrySeconds = 5;
    2607             :       static const int kLockRetrySleepMS = 100;
    2608             : 
    2609           0 :       nsCOMPtr<nsIProfileUnlocker> unlocker;
    2610           0 :       const TimeStamp start = TimeStamp::Now();
    2611           0 :       do {
    2612           0 :         rv = profile->Lock(getter_AddRefs(unlocker), aResult);
    2613           0 :         if (NS_SUCCEEDED(rv)) {
    2614           0 :           StartupTimeline::Record(StartupTimeline::AFTER_PROFILE_LOCKED);
    2615             :           // Try to grab the profile name.
    2616           0 :           if (aProfileName) {
    2617           0 :             rv = profile->GetName(*aProfileName);
    2618           0 :             if (NS_FAILED(rv))
    2619           0 :               aProfileName->Truncate(0);
    2620             :           }
    2621             :           return NS_OK;
    2622             :         }
    2623           0 :         PR_Sleep(kLockRetrySleepMS);
    2624           0 :       } while (TimeStamp::Now() - start < TimeDuration::FromSeconds(kLockRetrySeconds));
    2625             : 
    2626           0 :       return ProfileLockedDialog(profile, unlocker, aNative, aResult);
    2627             :     }
    2628             :   }
    2629             : 
    2630             :   if (!CanShowProfileManager()) {
    2631             :     return NS_ERROR_FAILURE;
    2632             :   }
    2633             : 
    2634           0 :   return ShowProfileManager(aProfileSvc, aNative);
    2635             : }
    2636             : 
    2637             : /**
    2638             :  * Checks the compatibility.ini file to see if we have updated our application
    2639             :  * or otherwise invalidated our caches. If the application has been updated,
    2640             :  * we return false; otherwise, we return true. We also write the status
    2641             :  * of the caches (valid/invalid) into the return param aCachesOK. The aCachesOK
    2642             :  * is always invalid if the application has been updated.
    2643             :  */
    2644             : static bool
    2645           1 : CheckCompatibility(nsIFile* aProfileDir, const nsCString& aVersion,
    2646             :                    const nsCString& aOSABI, nsIFile* aXULRunnerDir,
    2647             :                    nsIFile* aAppDir, nsIFile* aFlagFile,
    2648             :                    bool* aCachesOK)
    2649             : {
    2650           0 :   *aCachesOK = false;
    2651           2 :   nsCOMPtr<nsIFile> file;
    2652           2 :   aProfileDir->Clone(getter_AddRefs(file));
    2653           0 :   if (!file)
    2654             :     return false;
    2655           0 :   file->AppendNative(FILE_COMPATIBILITY_INFO);
    2656             : 
    2657           2 :   nsINIParser parser;
    2658           0 :   nsresult rv = parser.Init(file);
    2659           0 :   if (NS_FAILED(rv))
    2660             :     return false;
    2661             : 
    2662           0 :   nsAutoCString buf;
    2663           0 :   rv = parser.GetString("Compatibility", "LastVersion", buf);
    2664           0 :   if (NS_FAILED(rv) || !aVersion.Equals(buf))
    2665             :     return false;
    2666             : 
    2667           0 :   rv = parser.GetString("Compatibility", "LastOSABI", buf);
    2668           0 :   if (NS_FAILED(rv) || !aOSABI.Equals(buf))
    2669             :     return false;
    2670             : 
    2671           0 :   rv = parser.GetString("Compatibility", "LastPlatformDir", buf);
    2672           0 :   if (NS_FAILED(rv))
    2673             :     return false;
    2674             : 
    2675           0 :   nsCOMPtr<nsIFile> lf;
    2676           0 :   rv = NS_NewNativeLocalFile(EmptyCString(), false,
    2677           0 :                              getter_AddRefs(lf));
    2678           0 :   if (NS_FAILED(rv))
    2679             :     return false;
    2680             : 
    2681           0 :   rv = lf->SetPersistentDescriptor(buf);
    2682           0 :   if (NS_FAILED(rv))
    2683             :     return false;
    2684             : 
    2685             :   bool eq;
    2686           0 :   rv = lf->Equals(aXULRunnerDir, &eq);
    2687           0 :   if (NS_FAILED(rv) || !eq)
    2688             :     return false;
    2689             : 
    2690           0 :   if (aAppDir) {
    2691           0 :     rv = parser.GetString("Compatibility", "LastAppDir", buf);
    2692           0 :     if (NS_FAILED(rv))
    2693             :       return false;
    2694             : 
    2695           0 :     rv = NS_NewNativeLocalFile(EmptyCString(), false,
    2696           0 :                                getter_AddRefs(lf));
    2697           0 :     if (NS_FAILED(rv))
    2698             :       return false;
    2699             : 
    2700           0 :     rv = lf->SetPersistentDescriptor(buf);
    2701           0 :     if (NS_FAILED(rv))
    2702             :       return false;
    2703             : 
    2704           0 :     rv = lf->Equals(aAppDir, &eq);
    2705           0 :     if (NS_FAILED(rv) || !eq)
    2706             :       return false;
    2707             :   }
    2708             : 
    2709             :   // If we see this flag, caches are invalid.
    2710           0 :   rv = parser.GetString("Compatibility", "InvalidateCaches", buf);
    2711           0 :   *aCachesOK = (NS_FAILED(rv) || !buf.EqualsLiteral("1"));
    2712             : 
    2713           0 :   bool purgeCaches = false;
    2714           0 :   if (aFlagFile) {
    2715           0 :     aFlagFile->Exists(&purgeCaches);
    2716             :   }
    2717             : 
    2718           0 :   *aCachesOK = !purgeCaches && *aCachesOK;
    2719           0 :   return true;
    2720             : }
    2721             : 
    2722           1 : static void BuildVersion(nsCString &aBuf)
    2723             : {
    2724           2 :   aBuf.Assign(gAppData->version);
    2725           1 :   aBuf.Append('_');
    2726           2 :   aBuf.Append(gAppData->buildID);
    2727           0 :   aBuf.Append('/');
    2728           0 :   aBuf.Append(gToolkitBuildID);
    2729           0 : }
    2730             : 
    2731             : static void
    2732           1 : WriteVersion(nsIFile* aProfileDir, const nsCString& aVersion,
    2733             :              const nsCString& aOSABI, nsIFile* aXULRunnerDir,
    2734             :              nsIFile* aAppDir, bool invalidateCache)
    2735             : {
    2736           0 :   nsCOMPtr<nsIFile> file;
    2737           0 :   aProfileDir->Clone(getter_AddRefs(file));
    2738           0 :   if (!file)
    2739           0 :     return;
    2740           3 :   file->AppendNative(FILE_COMPATIBILITY_INFO);
    2741             : 
    2742           0 :   nsAutoCString platformDir;
    2743           0 :   Unused << aXULRunnerDir->GetPersistentDescriptor(platformDir);
    2744             : 
    2745           1 :   nsAutoCString appDir;
    2746           1 :   if (aAppDir)
    2747           1 :     Unused << aAppDir->GetPersistentDescriptor(appDir);
    2748             : 
    2749             :   PRFileDesc *fd;
    2750             :   nsresult rv =
    2751           0 :     file->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0600, &fd);
    2752           0 :   if (NS_FAILED(rv)) {
    2753           0 :     NS_ERROR("could not create output stream");
    2754           0 :     return;
    2755             :   }
    2756             : 
    2757             :   static const char kHeader[] = "[Compatibility]" NS_LINEBREAK
    2758             :                                 "LastVersion=";
    2759             : 
    2760           0 :   PR_Write(fd, kHeader, sizeof(kHeader) - 1);
    2761           0 :   PR_Write(fd, aVersion.get(), aVersion.Length());
    2762             : 
    2763             :   static const char kOSABIHeader[] = NS_LINEBREAK "LastOSABI=";
    2764           0 :   PR_Write(fd, kOSABIHeader, sizeof(kOSABIHeader) - 1);
    2765           0 :   PR_Write(fd, aOSABI.get(), aOSABI.Length());
    2766             : 
    2767             :   static const char kPlatformDirHeader[] = NS_LINEBREAK "LastPlatformDir=";
    2768             : 
    2769           1 :   PR_Write(fd, kPlatformDirHeader, sizeof(kPlatformDirHeader) - 1);
    2770           0 :   PR_Write(fd, platformDir.get(), platformDir.Length());
    2771             : 
    2772             :   static const char kAppDirHeader[] = NS_LINEBREAK "LastAppDir=";
    2773           1 :   if (aAppDir) {
    2774           0 :     PR_Write(fd, kAppDirHeader, sizeof(kAppDirHeader) - 1);
    2775           1 :     PR_Write(fd, appDir.get(), appDir.Length());
    2776             :   }
    2777             : 
    2778             :   static const char kInvalidationHeader[] = NS_LINEBREAK "InvalidateCaches=1";
    2779           1 :   if (invalidateCache)
    2780           0 :     PR_Write(fd, kInvalidationHeader, sizeof(kInvalidationHeader) - 1);
    2781             : 
    2782             :   static const char kNL[] = NS_LINEBREAK;
    2783           1 :   PR_Write(fd, kNL, sizeof(kNL) - 1);
    2784             : 
    2785           1 :   PR_Close(fd);
    2786             : }
    2787             : 
    2788             : /**
    2789             :  * Returns true if the startup cache file was successfully removed.
    2790             :  * Returns false if file->Clone fails at any point (OOM) or if unable
    2791             :  * to remove the startup cache file. Note in particular the return value
    2792             :  * is unaffected by a failure to remove extensions.ini
    2793             :  */
    2794             : static bool
    2795           0 : RemoveComponentRegistries(nsIFile* aProfileDir, nsIFile* aLocalProfileDir,
    2796             :                                       bool aRemoveEMFiles)
    2797             : {
    2798           2 :   nsCOMPtr<nsIFile> file;
    2799           0 :   aProfileDir->Clone(getter_AddRefs(file));
    2800           0 :   if (!file)
    2801             :     return false;
    2802             : 
    2803           1 :   if (aRemoveEMFiles) {
    2804           3 :     file->SetNativeLeafName(NS_LITERAL_CSTRING("extensions.ini"));
    2805           1 :     file->Remove(false);
    2806             :   }
    2807             : 
    2808           2 :   aLocalProfileDir->Clone(getter_AddRefs(file));
    2809           0 :   if (!file)
    2810             :     return false;
    2811             : 
    2812             : #if defined(XP_UNIX) || defined(XP_BEOS)
    2813             : #define PLATFORM_FASL_SUFFIX ".mfasl"
    2814             : #elif defined(XP_WIN)
    2815             : #define PLATFORM_FASL_SUFFIX ".mfl"
    2816             : #endif
    2817             : 
    2818           3 :   file->AppendNative(NS_LITERAL_CSTRING("XUL" PLATFORM_FASL_SUFFIX));
    2819           1 :   file->Remove(false);
    2820             : 
    2821           3 :   file->SetNativeLeafName(NS_LITERAL_CSTRING("XPC" PLATFORM_FASL_SUFFIX));
    2822           1 :   file->Remove(false);
    2823             : 
    2824           3 :   file->SetNativeLeafName(NS_LITERAL_CSTRING("startupCache"));
    2825           1 :   nsresult rv = file->Remove(true);
    2826           1 :   return NS_SUCCEEDED(rv) || rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST;
    2827             : }
    2828             : 
    2829             : // To support application initiated restart via nsIAppStartup.quit, we
    2830             : // need to save various environment variables, and then restore them
    2831             : // before re-launching the application.
    2832             : 
    2833             : static struct SavedVar {
    2834             :   const char *name;
    2835             :   char *value;
    2836             : } gSavedVars[] = {
    2837             :   {"XUL_APP_FILE", nullptr}
    2838             : };
    2839             : 
    2840           1 : static void SaveStateForAppInitiatedRestart()
    2841             : {
    2842           1 :   for (auto & savedVar : gSavedVars) {
    2843           1 :     const char *s = PR_GetEnv(savedVar.name);
    2844           1 :     if (s)
    2845           0 :       savedVar.value = Smprintf("%s=%s", savedVar.name, s).release();
    2846             :   }
    2847           1 : }
    2848             : 
    2849           0 : static void RestoreStateForAppInitiatedRestart()
    2850             : {
    2851           0 :   for (auto & savedVar : gSavedVars) {
    2852           0 :     if (savedVar.value)
    2853           0 :       PR_SetEnv(savedVar.value);
    2854             :   }
    2855           0 : }
    2856             : 
    2857             : // When we first initialize the crash reporter we don't have a profile,
    2858             : // so we set the minidump path to $TEMP.  Once we have a profile,
    2859             : // we set it to $PROFILE/minidumps, creating the directory
    2860             : // if needed.
    2861           0 : static void MakeOrSetMinidumpPath(nsIFile* profD)
    2862             : {
    2863           0 :   nsCOMPtr<nsIFile> dumpD;
    2864           0 :   profD->Clone(getter_AddRefs(dumpD));
    2865             : 
    2866           1 :   if (dumpD) {
    2867             :     bool fileExists;
    2868             :     //XXX: do some more error checking here
    2869           0 :     dumpD->Append(NS_LITERAL_STRING("minidumps"));
    2870           1 :     dumpD->Exists(&fileExists);
    2871           1 :     if (!fileExists) {
    2872           1 :       nsresult rv = dumpD->Create(nsIFile::DIRECTORY_TYPE, 0700);
    2873           1 :       NS_ENSURE_SUCCESS_VOID(rv);
    2874             :     }
    2875             : 
    2876           0 :     nsAutoString pathStr;
    2877           1 :     if (NS_SUCCEEDED(dumpD->GetPath(pathStr)))
    2878           1 :       CrashReporter::SetMinidumpPath(pathStr);
    2879             :   }
    2880             : }
    2881             : 
    2882             : const XREAppData* gAppData = nullptr;
    2883             : 
    2884             : #ifdef MOZ_WIDGET_GTK
    2885           0 : static void MOZ_gdk_display_close(GdkDisplay *display)
    2886             : {
    2887             : #if CLEANUP_MEMORY
    2888             :   // XXX wallpaper for bug 417163: don't close the Display if we're using the
    2889             :   // Qt theme because we crash (in Qt code) when using jemalloc.
    2890           0 :   bool skip_display_close = false;
    2891             :   GtkSettings* settings =
    2892           0 :     gtk_settings_get_for_screen(gdk_display_get_default_screen(display));
    2893             :   gchar *theme_name;
    2894           0 :   g_object_get(settings, "gtk-theme-name", &theme_name, nullptr);
    2895           0 :   if (theme_name) {
    2896           0 :     skip_display_close = strcmp(theme_name, "Qt") == 0;
    2897           0 :     if (skip_display_close)
    2898           0 :       NS_WARNING("wallpaper bug 417163 for Qt theme");
    2899           0 :     g_free(theme_name);
    2900             :   }
    2901             : 
    2902             : #ifdef MOZ_WIDGET_GTK
    2903             :   // A workaround for https://bugzilla.gnome.org/show_bug.cgi?id=703257
    2904           0 :   if (gtk_check_version(3,9,8) != NULL)
    2905           0 :     skip_display_close = true;
    2906             : #endif
    2907             : 
    2908             :   // Get a (new) Pango context that holds a reference to the fontmap that
    2909             :   // GTK has been using.  gdk_pango_context_get() must be called while GTK
    2910             :   // has a default display.
    2911           0 :   PangoContext *pangoContext = gdk_pango_context_get();
    2912             : 
    2913           0 :   bool buggyCairoShutdown = cairo_version() < CAIRO_VERSION_ENCODE(1, 4, 0);
    2914             : 
    2915           0 :   if (!buggyCairoShutdown) {
    2916             :     // We should shut down GDK before we shut down libraries it depends on
    2917             :     // like Pango and cairo. But if cairo shutdown is buggy, we should
    2918             :     // shut down cairo first otherwise it may crash because of dangling
    2919             :     // references to Display objects (see bug 469831).
    2920           0 :     if (!skip_display_close)
    2921           0 :       gdk_display_close(display);
    2922             :   }
    2923             : 
    2924             :   // Clean up PangoCairo's default fontmap.
    2925             :   // This pango_fc_font_map_shutdown call (and the associated code to
    2926             :   // get the font map) really shouldn't be needed anymore, except that
    2927             :   // it's needed to avoid having cairo_debug_reset_static_data fatally
    2928             :   // assert if we've leaked other things that hold on to the fontmap,
    2929             :   // which is something that currently happens in mochitest-plugins.
    2930             :   // Even if it didn't happen in mochitest-plugins, we probably want to
    2931             :   // avoid the crash-on-leak problem since it makes it harder to use
    2932             :   // many of our leak tools to debug leaks.
    2933             : 
    2934             :   // This doesn't take a reference.
    2935           0 :   PangoFontMap *fontmap = pango_context_get_font_map(pangoContext);
    2936             :   // Do some shutdown of the fontmap, which releases the fonts, clearing a
    2937             :   // bunch of circular references from the fontmap through the fonts back to
    2938             :   // itself.  The shutdown that this does is much less than what's done by
    2939             :   // the fontmap's finalize, though.
    2940           0 :   if (PANGO_IS_FC_FONT_MAP(fontmap))
    2941           0 :       pango_fc_font_map_shutdown(PANGO_FC_FONT_MAP(fontmap));
    2942           0 :   g_object_unref(pangoContext);
    2943             : 
    2944             :   // Tell PangoCairo to release its default fontmap.
    2945           0 :   pango_cairo_font_map_set_default(nullptr);
    2946             : 
    2947             :   // cairo_debug_reset_static_data() is prototyped through cairo.h included
    2948             :   // by gtk.h.
    2949             : #ifdef cairo_debug_reset_static_data
    2950             : #error "Looks like we're including Mozilla's cairo instead of system cairo"
    2951             : #endif
    2952           0 :   cairo_debug_reset_static_data();
    2953             :   // FIXME: Do we need to call this in non-GTK2 cases as well?
    2954           0 :   FcFini();
    2955             : 
    2956           0 :   if (buggyCairoShutdown) {
    2957           0 :     if (!skip_display_close)
    2958           0 :       gdk_display_close(display);
    2959             :   }
    2960             : #else // not CLEANUP_MEMORY
    2961             :   // Don't do anything to avoid running into driver bugs under XCloseDisplay().
    2962             :   // See bug 973192.
    2963             :   (void) display;
    2964             : #endif
    2965           0 : }
    2966             : #endif
    2967             : 
    2968             : /**
    2969             :  * NSPR will search for the "nspr_use_zone_allocator" symbol throughout
    2970             :  * the process and use it to determine whether the application defines its own
    2971             :  * memory allocator or not.
    2972             :  *
    2973             :  * Since most applications (e.g. Firefox and Thunderbird) don't use any special
    2974             :  * allocators and therefore don't define this symbol, NSPR must search the
    2975             :  * entire process, which reduces startup performance.
    2976             :  *
    2977             :  * By defining the symbol here, we can avoid the wasted lookup and hopefully
    2978             :  * improve startup performance.
    2979             :  */
    2980             : NS_VISIBILITY_DEFAULT PRBool nspr_use_zone_allocator = PR_FALSE;
    2981             : 
    2982             : #ifdef CAIRO_HAS_DWRITE_FONT
    2983             : 
    2984             : #include <dwrite.h>
    2985             : 
    2986             : #ifdef DEBUG_DWRITE_STARTUP
    2987             : 
    2988             : #define LOGREGISTRY(msg) LogRegistryEvent(msg)
    2989             : 
    2990             : // for use when monitoring process
    2991             : static void LogRegistryEvent(const wchar_t *msg)
    2992             : {
    2993             :   HKEY dummyKey;
    2994             :   HRESULT hr;
    2995             :   wchar_t buf[512];
    2996             : 
    2997             :   wsprintf(buf, L" log %s", msg);
    2998             :   hr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, buf, 0, KEY_READ, &dummyKey);
    2999             :   if (SUCCEEDED(hr)) {
    3000             :     RegCloseKey(dummyKey);
    3001             :   }
    3002             : }
    3003             : #else
    3004             : 
    3005             : #define LOGREGISTRY(msg)
    3006             : 
    3007             : #endif
    3008             : 
    3009             : static DWORD WINAPI InitDwriteBG(LPVOID lpdwThreadParam)
    3010             : {
    3011             :   SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_BEGIN);
    3012             :   LOGREGISTRY(L"loading dwrite.dll");
    3013             :   HMODULE dwdll = LoadLibraryW(L"dwrite.dll");
    3014             :   if (dwdll) {
    3015             :     decltype(DWriteCreateFactory)* createDWriteFactory = (decltype(DWriteCreateFactory)*)
    3016             :       GetProcAddress(dwdll, "DWriteCreateFactory");
    3017             :     if (createDWriteFactory) {
    3018             :       LOGREGISTRY(L"creating dwrite factory");
    3019             :       IDWriteFactory *factory;
    3020             :       HRESULT hr = createDWriteFactory(
    3021             :         DWRITE_FACTORY_TYPE_SHARED,
    3022             :         __uuidof(IDWriteFactory),
    3023             :         reinterpret_cast<IUnknown**>(&factory));
    3024             :       if (SUCCEEDED(hr)) {
    3025             :         LOGREGISTRY(L"dwrite factory done");
    3026             :         factory->Release();
    3027             :         LOGREGISTRY(L"freed factory");
    3028             :       } else {
    3029             :         LOGREGISTRY(L"failed to create factory");
    3030             :       }
    3031             :     }
    3032             :   }
    3033             :   SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_END);
    3034             :   return 0;
    3035             : }
    3036             : #endif
    3037             : 
    3038             : #ifdef USE_GLX_TEST
    3039             : bool fire_glxtest_process();
    3040             : #endif
    3041             : 
    3042             : #include "GeckoProfiler.h"
    3043             : 
    3044             : // Encapsulates startup and shutdown state for XRE_main
    3045             : class XREMain
    3046             : {
    3047             : public:
    3048           0 :   XREMain() :
    3049             :     mStartOffline(false)
    3050             :     , mShuttingDown(false)
    3051             : #ifdef MOZ_ENABLE_XREMOTE
    3052             :     , mDisableRemote(false)
    3053             : #endif
    3054             : #if defined(MOZ_WIDGET_GTK)
    3055          10 :     , mGdkDisplay(nullptr)
    3056             : #endif
    3057           1 :   {};
    3058             : 
    3059           0 :   ~XREMain() {
    3060           0 :     mScopedXPCOM = nullptr;
    3061           0 :     mAppData = nullptr;
    3062           0 :   }
    3063             : 
    3064             :   int XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig);
    3065             :   int XRE_mainInit(bool* aExitFlag);
    3066             :   int XRE_mainStartup(bool* aExitFlag);
    3067             :   nsresult XRE_mainRun();
    3068             : 
    3069             :   Result<bool, nsresult> CheckLastStartupWasCrash();
    3070             : 
    3071             :   nsCOMPtr<nsINativeAppSupport> mNativeApp;
    3072             :   nsCOMPtr<nsIToolkitProfileService> mProfileSvc;
    3073             :   nsCOMPtr<nsIFile> mProfD;
    3074             :   nsCOMPtr<nsIFile> mProfLD;
    3075             :   nsCOMPtr<nsIProfileLock> mProfileLock;
    3076             : #ifdef MOZ_ENABLE_XREMOTE
    3077             :   nsCOMPtr<nsIRemoteService> mRemoteService;
    3078             :   nsProfileLock mRemoteLock;
    3079             :   nsCOMPtr<nsIFile> mRemoteLockDir;
    3080             : #endif
    3081             : 
    3082             :   UniquePtr<ScopedXPCOMStartup> mScopedXPCOM;
    3083             :   UniquePtr<XREAppData> mAppData;
    3084             : 
    3085             :   nsXREDirProvider mDirProvider;
    3086             :   nsAutoCString mProfileName;
    3087             :   nsAutoCString mDesktopStartupID;
    3088             : 
    3089             :   bool mStartOffline;
    3090             :   bool mShuttingDown;
    3091             : #ifdef MOZ_ENABLE_XREMOTE
    3092             :   bool mDisableRemote;
    3093             : #endif
    3094             : 
    3095             : #if defined(MOZ_WIDGET_GTK)
    3096             :   GdkDisplay* mGdkDisplay;
    3097             : #endif
    3098             : };
    3099             : 
    3100             : #if defined(XP_UNIX) && !defined(ANDROID)
    3101             : static SmprintfPointer
    3102           0 : FormatUid(uid_t aId)
    3103             : {
    3104           0 :   if (const auto pw = getpwuid(aId)) {
    3105           0 :     return mozilla::Smprintf("%s", pw->pw_name);
    3106             :   }
    3107           0 :   return mozilla::Smprintf("uid %d", static_cast<int>(aId));
    3108             : }
    3109             : 
    3110             : // Bug 1323302: refuse to run under sudo or similar.
    3111             : static bool
    3112           1 : CheckForUserMismatch()
    3113             : {
    3114             :   static char const * const kVars[] = {
    3115             :     "HOME",
    3116             : #ifdef MOZ_WIDGET_GTK
    3117             :     "XDG_RUNTIME_DIR",
    3118             : #endif
    3119             : #ifdef MOZ_X11
    3120             :     "XAUTHORITY",
    3121             : #endif
    3122             :   };
    3123             : 
    3124           1 :   const uid_t euid = geteuid();
    3125           1 :   if (euid != 0) {
    3126             :     // On Linux it's possible to have superuser capabilities with a
    3127             :     // nonzero uid, but anyone who knows enough to make that happen
    3128             :     // probably knows enough to debug the resulting problems.
    3129             :     // Otherwise, a non-root user can't cause the problems we're
    3130             :     // concerned about.
    3131             :     return false;
    3132             :   }
    3133             : 
    3134           0 :   for (const auto var : kVars) {
    3135           0 :     if (const auto path = PR_GetEnv(var)) {
    3136             :       struct stat st;
    3137           0 :       if (stat(path, &st) == 0) {
    3138           0 :         if (st.st_uid != euid) {
    3139           0 :           const auto owner = FormatUid(st.st_uid);
    3140           0 :           Output(true, "Running " MOZ_APP_DISPLAYNAME " as root in a regular"
    3141             :                  " user's session is not supported.  ($%s is %s which is"
    3142             :                  " owned by %s.)\n",
    3143           0 :                  var, path, owner.get());
    3144             :           return true;
    3145             :         }
    3146             :       }
    3147             :     }
    3148             :   }
    3149             :   return false;
    3150             : }
    3151             : #else // !XP_UNIX || ANDROID
    3152             : static bool
    3153             : CheckForUserMismatch()
    3154             : {
    3155             :   return false;
    3156             : }
    3157             : #endif
    3158             : 
    3159             : static void
    3160           1 : IncreaseDescriptorLimits()
    3161             : {
    3162             : #ifdef XP_UNIX
    3163             :   // Increase the fd limit to accomodate IPC resources like shared memory.
    3164             :   static const rlim_t kFDs = 4096;
    3165             :   struct rlimit rlim;
    3166             : 
    3167           1 :   if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) {
    3168           0 :     Output(false, "getrlimit: %s\n", strerror(errno));
    3169           0 :     return;
    3170             :   }
    3171             :   // Don't decrease the limit if it's already high enough, but don't
    3172             :   // try to go over the hard limit.  (RLIM_INFINITY isn't required to
    3173             :   // be the numerically largest rlim_t, so don't assume that.)
    3174           2 :   if (rlim.rlim_cur != RLIM_INFINITY && rlim.rlim_cur < kFDs &&
    3175           1 :       rlim.rlim_cur < rlim.rlim_max) {
    3176           1 :     if (rlim.rlim_max != RLIM_INFINITY && rlim.rlim_max < kFDs) {
    3177           0 :       rlim.rlim_cur = rlim.rlim_max;
    3178             :     } else {
    3179           1 :       rlim.rlim_cur = kFDs;
    3180             :     }
    3181           1 :     if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) {
    3182           0 :       Output(false, "setrlimit: %s\n", strerror(errno));
    3183             :     }
    3184             :   }
    3185             : #endif
    3186             : }
    3187             : 
    3188             : /*
    3189             :  * XRE_mainInit - Initial setup and command line parameter processing.
    3190             :  * Main() will exit early if either return value != 0 or if aExitFlag is
    3191             :  * true.
    3192             :  */
    3193             : int
    3194           0 : XREMain::XRE_mainInit(bool* aExitFlag)
    3195             : {
    3196           0 :   if (!aExitFlag)
    3197             :     return 1;
    3198           0 :   *aExitFlag = false;
    3199             : 
    3200           1 :   atexit(UnexpectedExit);
    3201             :   auto expectedShutdown = mozilla::MakeScopeExit([&] {
    3202             :     MozExpectedExit();
    3203           1 :   });
    3204             : 
    3205           1 :   StartupTimeline::Record(StartupTimeline::MAIN);
    3206             : 
    3207           1 :   if (CheckForUserMismatch()) {
    3208             :     return 1;
    3209             :   }
    3210             : 
    3211           1 :   if (PR_GetEnv("MOZ_CHAOSMODE")) {
    3212           0 :     ChaosFeature feature = ChaosFeature::Any;
    3213           0 :     long featureInt = strtol(PR_GetEnv("MOZ_CHAOSMODE"), nullptr, 16);
    3214           0 :     if (featureInt) {
    3215             :       // NOTE: MOZ_CHAOSMODE=0 or a non-hex value maps to Any feature.
    3216           0 :       feature = static_cast<ChaosFeature>(featureInt);
    3217             :     }
    3218             :     ChaosMode::SetChaosFeature(feature);
    3219             :   }
    3220             : 
    3221           1 :   if (ChaosMode::isActive(ChaosFeature::Any)) {
    3222           0 :     printf_stderr("*** You are running in chaos test mode. See ChaosMode.h. ***\n");
    3223             :   }
    3224             : 
    3225           1 :   if (CheckArg("headless") || CheckArgExists("screenshot")) {
    3226           0 :     PR_SetEnv("MOZ_HEADLESS=1");
    3227             :   }
    3228             : 
    3229           1 :   if (gfxPlatform::IsHeadless()) {
    3230             : #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK) || defined(XP_MACOSX)
    3231           1 :     printf_stderr("*** You are running in headless mode.\n");
    3232             : #else
    3233             :     Output(true, "Error: headless mode is not currently supported on this platform.\n");
    3234             :     return 1;
    3235             : #endif
    3236             : 
    3237             : #ifdef XP_MACOSX
    3238             :     // To avoid taking focus when running in headless mode immediately
    3239             :     // transition Firefox to a background application.
    3240             :     ProcessSerialNumber psn = { 0, kCurrentProcess };
    3241             :     OSStatus transformStatus = TransformProcessType(&psn, kProcessTransformToBackgroundApplication);
    3242             :     if (transformStatus != noErr) {
    3243             :       NS_ERROR("Failed to make process a background application.");
    3244             :       return 1;
    3245             :     }
    3246             : #endif
    3247             : 
    3248             :   }
    3249             : 
    3250             :   nsresult rv;
    3251             :   ArgResult ar;
    3252             : 
    3253             : #ifdef DEBUG
    3254           1 :   if (PR_GetEnv("XRE_MAIN_BREAK"))
    3255           0 :     NS_BREAK();
    3256             : #endif
    3257             : 
    3258           1 :   IncreaseDescriptorLimits();
    3259             : 
    3260             : #ifdef USE_GLX_TEST
    3261             :   // bug 639842 - it's very important to fire this process BEFORE we set up
    3262             :   // error handling. indeed, this process is expected to be crashy, and we
    3263             :   // don't want the user to see its crashes. That's the whole reason for
    3264             :   // doing this in a separate process.
    3265             :   //
    3266             :   // This call will cause a fork and the fork will terminate itself separately
    3267             :   // from the usual shutdown sequence
    3268           1 :   fire_glxtest_process();
    3269             : #endif
    3270             : 
    3271           1 :   SetupErrorHandling(gArgv[0]);
    3272             : 
    3273             : #ifdef CAIRO_HAS_DWRITE_FONT
    3274             :   {
    3275             :     // Bug 602792 - when DWriteCreateFactory is called the dwrite client dll
    3276             :     // starts the FntCache service if it isn't already running (it's set
    3277             :     // to manual startup by default in Windows 7 RTM).  Subsequent DirectWrite
    3278             :     // calls cause the IDWriteFactory object to communicate with the FntCache
    3279             :     // service with a timeout; if there's no response after the timeout, the
    3280             :     // DirectWrite client library will assume the service isn't around and do
    3281             :     // manual font file I/O on _all_ system fonts.  To avoid this, load the
    3282             :     // dwrite library and create a factory as early as possible so that the
    3283             :     // FntCache service is ready by the time it's needed.
    3284             : 
    3285             :     CreateThread(nullptr, 0, &InitDwriteBG, nullptr, 0, nullptr);
    3286             :   }
    3287             : #endif
    3288             : 
    3289             : #ifdef XP_UNIX
    3290           1 :   const char *home = PR_GetEnv("HOME");
    3291           1 :   if (!home || !*home) {
    3292           0 :     struct passwd *pw = getpwuid(geteuid());
    3293           0 :     if (!pw || !pw->pw_dir) {
    3294           0 :       Output(true, "Could not determine HOME directory");
    3295           0 :       return 1;
    3296             :     }
    3297           0 :     SaveWordToEnv("HOME", nsDependentCString(pw->pw_dir));
    3298             :   }
    3299             : #endif
    3300             : 
    3301             : #ifdef MOZ_ACCESSIBILITY_ATK
    3302             :   // Suppress atk-bridge init at startup, until mozilla accessibility is
    3303             :   // initialized.  This works after gnome 2.24.2.
    3304           1 :   SaveToEnv("NO_AT_BRIDGE=1");
    3305             : #endif
    3306             : 
    3307             :   // Check for application.ini overrides
    3308           1 :   const char* override = nullptr;
    3309           1 :   ar = CheckArg("override", &override, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
    3310           1 :   if (ar == ARG_BAD) {
    3311           0 :     Output(true, "Incorrect number of arguments passed to --override");
    3312           0 :     return 1;
    3313             :   }
    3314           1 :   if (ar == ARG_FOUND) {
    3315           0 :     nsCOMPtr<nsIFile> overrideLF;
    3316           0 :     rv = XRE_GetFileFromPath(override, getter_AddRefs(overrideLF));
    3317           0 :     if (NS_FAILED(rv)) {
    3318           0 :       Output(true, "Error: unrecognized override.ini path.\n");
    3319           0 :       return 1;
    3320             :     }
    3321             : 
    3322           0 :     rv = XRE_ParseAppData(overrideLF, *mAppData);
    3323           0 :     if (NS_FAILED(rv)) {
    3324           0 :       Output(true, "Couldn't read override.ini");
    3325           0 :       return 1;
    3326             :     }
    3327             :   }
    3328             : 
    3329             :   // Check sanity and correctness of app data.
    3330             : 
    3331           2 :   if (!mAppData->name) {
    3332           0 :     Output(true, "Error: App:Name not specified in application.ini\n");
    3333           0 :     return 1;
    3334             :   }
    3335           1 :   if (!mAppData->buildID) {
    3336           0 :     Output(true, "Error: App:BuildID not specified in application.ini\n");
    3337           0 :     return 1;
    3338             :   }
    3339             : 
    3340             :   // XXX Originally ScopedLogging was here? Now it's in XRE_main above
    3341             :   // XRE_mainInit.
    3342             : 
    3343           2 :   if (!mAppData->minVersion) {
    3344           0 :     Output(true, "Error: Gecko:MinVersion not specified in application.ini\n");
    3345           0 :     return 1;
    3346             :   }
    3347             : 
    3348           2 :   if (!mAppData->maxVersion) {
    3349             :     // If no maxVersion is specified, we assume the app is only compatible
    3350             :     // with the initial preview release. Do not increment this number ever!
    3351           0 :     mAppData->maxVersion = "1.*";
    3352             :   }
    3353             : 
    3354           0 :   if (mozilla::Version(mAppData->minVersion) > gToolkitVersion ||
    3355           0 :       mozilla::Version(mAppData->maxVersion) < gToolkitVersion) {
    3356           0 :     Output(true, "Error: Platform version '%s' is not compatible with\n"
    3357             :            "minVersion >= %s\nmaxVersion <= %s\n",
    3358           0 :            (const char*) gToolkitVersion, (const char*) mAppData->minVersion,
    3359           0 :            (const char*) mAppData->maxVersion);
    3360           0 :     return 1;
    3361             :   }
    3362             : 
    3363           0 :   rv = mDirProvider.Initialize(mAppData->directory, mAppData->xreDirectory);
    3364           1 :   if (NS_FAILED(rv))
    3365             :     return 1;
    3366             : 
    3367           1 :   if (EnvHasValue("MOZ_CRASHREPORTER")) {
    3368           0 :     mAppData->flags |= NS_XRE_ENABLE_CRASH_REPORTER;
    3369             :   }
    3370             : 
    3371           0 :   nsCOMPtr<nsIFile> xreBinDirectory;
    3372           2 :   xreBinDirectory = mDirProvider.GetGREBinDir();
    3373             : 
    3374           0 :   if ((mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER) &&
    3375           1 :       NS_SUCCEEDED(
    3376             :         CrashReporter::SetExceptionHandler(xreBinDirectory))) {
    3377           0 :     nsCOMPtr<nsIFile> file;
    3378           0 :     rv = nsXREDirProvider::GetUserAppDataDirectory(getter_AddRefs(file));
    3379           1 :     if (NS_SUCCEEDED(rv)) {
    3380           1 :       CrashReporter::SetUserAppDataDirectory(file);
    3381             :     }
    3382           0 :     if (mAppData->crashReporterURL)
    3383           0 :       CrashReporter::SetServerURL(nsDependentCString(mAppData->crashReporterURL));
    3384             : 
    3385             :     // We overwrite this once we finish starting up.
    3386           0 :     CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("StartupCrash"),
    3387           0 :                                        NS_LITERAL_CSTRING("1"));
    3388             : 
    3389             :     // pass some basic info from the app data
    3390           0 :     if (mAppData->vendor)
    3391           0 :       CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Vendor"),
    3392           0 :                                          nsDependentCString(mAppData->vendor));
    3393           0 :     if (mAppData->name)
    3394           0 :       CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ProductName"),
    3395           0 :                                          nsDependentCString(mAppData->name));
    3396           2 :     if (mAppData->ID)
    3397           0 :       CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ProductID"),
    3398           0 :                                          nsDependentCString(mAppData->ID));
    3399           0 :     if (mAppData->version)
    3400           1 :       CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Version"),
    3401           5 :                                          nsDependentCString(mAppData->version));
    3402           2 :     if (mAppData->buildID)
    3403           1 :       CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("BuildID"),
    3404           5 :                                          nsDependentCString(mAppData->buildID));
    3405             : 
    3406           2 :     nsDependentCString releaseChannel(NS_STRINGIFY(MOZ_UPDATE_CHANNEL));
    3407           1 :     CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ReleaseChannel"),
    3408           2 :                                        releaseChannel);
    3409             : #ifdef MOZ_LINKER
    3410             :     CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("CrashAddressLikelyWrong"),
    3411             :                                        IsSignalHandlingBroken() ? NS_LITERAL_CSTRING("1")
    3412             :                                                                 : NS_LITERAL_CSTRING("0"));
    3413             : #endif
    3414             : 
    3415             : #ifdef XP_WIN
    3416             :     nsAutoString appInitDLLs;
    3417             :     if (widget::WinUtils::GetAppInitDLLs(appInitDLLs)) {
    3418             :       CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AppInitDLLs"),
    3419             :                                          NS_ConvertUTF16toUTF8(appInitDLLs));
    3420             :     }
    3421             : #endif
    3422             : 
    3423           1 :     CrashReporter::SetRestartArgs(gArgc, gArgv);
    3424             : 
    3425             :     // annotate other data (user id etc)
    3426           0 :     nsCOMPtr<nsIFile> userAppDataDir;
    3427           0 :     if (NS_SUCCEEDED(mDirProvider.GetUserAppDataDirectory(
    3428             :                                                          getter_AddRefs(userAppDataDir)))) {
    3429           1 :       CrashReporter::SetupExtraData(userAppDataDir,
    3430           4 :                                     nsDependentCString(mAppData->buildID));
    3431             : 
    3432             :       // see if we have a crashreporter-override.ini in the application directory
    3433           2 :       nsCOMPtr<nsIFile> overrideini;
    3434             :       bool exists;
    3435           0 :       if (NS_SUCCEEDED(mDirProvider.GetAppDir()->Clone(getter_AddRefs(overrideini))) &&
    3436           0 :           NS_SUCCEEDED(overrideini->AppendNative(NS_LITERAL_CSTRING("crashreporter-override.ini"))) &&
    3437           3 :           NS_SUCCEEDED(overrideini->Exists(&exists)) &&
    3438             :           exists) {
    3439             : #ifdef XP_WIN
    3440             :         nsAutoString overridePathW;
    3441             :         overrideini->GetPath(overridePathW);
    3442             :         NS_ConvertUTF16toUTF8 overridePath(overridePathW);
    3443             : #else
    3444           2 :         nsAutoCString overridePath;
    3445           1 :         overrideini->GetNativePath(overridePath);
    3446             : #endif
    3447             : 
    3448           1 :         SaveWordToEnv("MOZ_CRASHREPORTER_STRINGS_OVERRIDE", overridePath);
    3449             :       }
    3450             :     }
    3451             :   }
    3452             : 
    3453             : #if defined(MOZ_SANDBOX) && defined(XP_WIN)
    3454             :   if (mAppData->sandboxBrokerServices) {
    3455             :     SandboxBroker::Initialize(mAppData->sandboxBrokerServices);
    3456             :   } else {
    3457             : #if defined(MOZ_CONTENT_SANDBOX)
    3458             :     // If we're sandboxing content and we fail to initialize, then crashing here
    3459             :     // seems like the sensible option.
    3460             :     if (BrowserTabsRemoteAutostart()) {
    3461             :       MOZ_CRASH("Failed to initialize broker services, can't continue.");
    3462             :     }
    3463             : #endif
    3464             :     // Otherwise just warn for the moment, as most things will work.
    3465             :     NS_WARNING("Failed to initialize broker services, sandboxed processes will "
    3466             :                "fail to start.");
    3467             :   }
    3468             :   if (mAppData->sandboxPermissionsService) {
    3469             :     SandboxPermissions::Initialize(mAppData->sandboxPermissionsService,
    3470             :                                    nullptr);
    3471             :   }
    3472             : #endif
    3473             : 
    3474             : #ifdef XP_MACOSX
    3475             :   // Set up ability to respond to system (Apple) events. This must occur before
    3476             :   // ProcessUpdates to ensure that links clicked in external applications aren't
    3477             :   // lost when updates are pending.
    3478             :   SetupMacApplicationDelegate();
    3479             : 
    3480             :   if (EnvHasValue("MOZ_LAUNCHED_CHILD")) {
    3481             :     // This is needed, on relaunch, to force the OS to use the "Cocoa Dock
    3482             :     // API".  Otherwise the call to ReceiveNextEvent() below will make it
    3483             :     // use the "Carbon Dock API".  For more info see bmo bug 377166.
    3484             :     EnsureUseCocoaDockAPI();
    3485             : 
    3486             :     // When the app relaunches, the original process exits.  This causes
    3487             :     // the dock tile to stop bouncing, lose the "running" triangle, and
    3488             :     // if the tile does not permanently reside in the Dock, even disappear.
    3489             :     // This can be confusing to the user, who is expecting the app to launch.
    3490             :     // Calling ReceiveNextEvent without requesting any event is enough to
    3491             :     // cause a dock tile for the child process to appear.
    3492             :     const EventTypeSpec kFakeEventList[] = { { INT_MAX, INT_MAX } };
    3493             :     EventRef event;
    3494             :     ::ReceiveNextEvent(GetEventTypeCount(kFakeEventList), kFakeEventList,
    3495             :                        kEventDurationNoWait, false, &event);
    3496             :   }
    3497             : 
    3498             :   if (CheckArg("foreground")) {
    3499             :     // The original process communicates that it was in the foreground by
    3500             :     // adding this argument.  This new process, which is taking over for
    3501             :     // the old one, should make itself the active application.
    3502             :     ProcessSerialNumber psn;
    3503             :     if (::GetCurrentProcess(&psn) == noErr)
    3504             :       ::SetFrontProcess(&psn);
    3505             :   }
    3506             : #endif
    3507             : 
    3508           0 :   SaveToEnv("MOZ_LAUNCHED_CHILD=");
    3509             : 
    3510             :   // On Windows, the -os-restarted command line switch lets us know when we are
    3511             :   // restarted via RegisterApplicationRestart. May be used for other OSes later.
    3512           1 :   if (CheckArg("os-restarted", nullptr, CheckArgFlag::RemoveArg) == ARG_FOUND) {
    3513           0 :     gRestartedByOS = true;
    3514             :   }
    3515             : 
    3516           1 :   gRestartArgc = gArgc;
    3517           1 :   gRestartArgv = (char**) malloc(sizeof(char*) * (gArgc + 1 + (override ? 2 : 0)));
    3518           1 :   if (!gRestartArgv) {
    3519             :     return 1;
    3520             :   }
    3521             : 
    3522             :   int i;
    3523           9 :   for (i = 0; i < gArgc; ++i) {
    3524           0 :     gRestartArgv[i] = gArgv[i];
    3525             :   }
    3526             : 
    3527             :   // Add the -override argument back (it is removed automatically be CheckArg) if there is one
    3528           1 :   if (override) {
    3529           0 :     gRestartArgv[gRestartArgc++] = const_cast<char*>("-override");
    3530           0 :     gRestartArgv[gRestartArgc++] = const_cast<char*>(override);
    3531             :   }
    3532             : 
    3533           1 :   gRestartArgv[gRestartArgc] = nullptr;
    3534             : 
    3535           1 :   Maybe<bool> safeModeRequested = IsSafeModeRequested(gArgc, gArgv);
    3536           1 :   if (!safeModeRequested) {
    3537             :     return 1;
    3538             :   }
    3539             : 
    3540           1 :   gSafeMode = safeModeRequested.value();
    3541             : 
    3542             : #ifdef XP_WIN
    3543             :   {
    3544             :     // Add CPU microcode version to the crash report as "CPUMicrocodeVersion".
    3545             :     // It feels like this code may belong in nsSystemInfo instead.
    3546             :     int cpuUpdateRevision = -1;
    3547             :     HKEY key;
    3548             :     static const WCHAR keyName[] =
    3549             :       L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0";
    3550             : 
    3551             :     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName , 0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) {
    3552             : 
    3553             :       DWORD updateRevision[2];
    3554             :       DWORD len = sizeof(updateRevision);
    3555             :       DWORD vtype;
    3556             : 
    3557             :       // Windows 7 uses "Update Signature", 8 uses "Update Revision".
    3558             :       // For AMD CPUs, "CurrentPatchLevel" is sometimes used.
    3559             :       // Take the first one we find.
    3560             :       LPCWSTR choices[] = {L"Update Signature", L"Update Revision", L"CurrentPatchLevel"};
    3561             :       for (size_t oneChoice=0; oneChoice<ArrayLength(choices); oneChoice++) {
    3562             :         if (RegQueryValueExW(key, choices[oneChoice],
    3563             :                              0, &vtype,
    3564             :                              reinterpret_cast<LPBYTE>(updateRevision),
    3565             :                              &len) == ERROR_SUCCESS) {
    3566             :           if (vtype == REG_BINARY && len == sizeof(updateRevision)) {
    3567             :             // The first word is unused
    3568             :             cpuUpdateRevision = static_cast<int>(updateRevision[1]);
    3569             :             break;
    3570             :           } else if (vtype == REG_DWORD && len == sizeof(updateRevision[0])) {
    3571             :             cpuUpdateRevision = static_cast<int>(updateRevision[0]);
    3572             :             break;
    3573             :           }
    3574             :         }
    3575             :       }
    3576             :     }
    3577             : 
    3578             :     if (cpuUpdateRevision > 0) {
    3579             :       CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("CPUMicrocodeVersion"),
    3580             :                                          nsPrintfCString("0x%x",
    3581             :                                                          cpuUpdateRevision));
    3582             :     }
    3583             :   }
    3584             : #endif
    3585             : 
    3586           1 :     CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("SafeMode"),
    3587           0 :                                        gSafeMode ? NS_LITERAL_CSTRING("1") :
    3588           5 :                                                    NS_LITERAL_CSTRING("0"));
    3589             : 
    3590             :   // Handle --no-remote and --new-instance command line arguments. Setup
    3591             :   // the environment to better accommodate other components and various
    3592             :   // restart scenarios.
    3593           0 :   ar = CheckArg("no-remote", nullptr, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
    3594           0 :   if (ar == ARG_BAD) {
    3595           0 :     PR_fprintf(PR_STDERR, "Error: argument --no-remote is invalid when argument --osint is specified\n");
    3596           0 :     return 1;
    3597             :   }
    3598           0 :   if (ar == ARG_FOUND) {
    3599           0 :     SaveToEnv("MOZ_NO_REMOTE=1");
    3600             :   }
    3601             : 
    3602           1 :   ar = CheckArg("new-instance", nullptr, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
    3603           1 :   if (ar == ARG_BAD) {
    3604           0 :     PR_fprintf(PR_STDERR, "Error: argument --new-instance is invalid when argument --osint is specified\n");
    3605           0 :     return 1;
    3606             :   }
    3607           1 :   if (ar == ARG_FOUND) {
    3608           0 :     SaveToEnv("MOZ_NEW_INSTANCE=1");
    3609             :   }
    3610             : 
    3611             :   // Handle --help and --version command line arguments.
    3612             :   // They should return quickly, so we deal with them here.
    3613           1 :   if (CheckArg("h") || CheckArg("help") || CheckArg("?")) {
    3614           0 :     DumpHelp();
    3615           0 :     *aExitFlag = true;
    3616           0 :     return 0;
    3617             :   }
    3618             : 
    3619           1 :   if (CheckArg("v") || CheckArg("version")) {
    3620           0 :     DumpVersion();
    3621           0 :     *aExitFlag = true;
    3622           0 :     return 0;
    3623             :   }
    3624             : 
    3625           0 :   rv = XRE_InitCommandLine(gArgc, gArgv);
    3626           1 :   NS_ENSURE_SUCCESS(rv, 1);
    3627             : 
    3628             :   // Check for --register, which registers chrome and then exits immediately.
    3629           1 :   ar = CheckArg("register", nullptr, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
    3630           1 :   if (ar == ARG_BAD) {
    3631           0 :     PR_fprintf(PR_STDERR, "Error: argument --register is invalid when argument --osint is specified\n");
    3632           0 :     return 1;
    3633             :   }
    3634           1 :   if (ar == ARG_FOUND) {
    3635           0 :     ScopedXPCOMStartup xpcom;
    3636           0 :     rv = xpcom.Initialize();
    3637           0 :     NS_ENSURE_SUCCESS(rv, 1);
    3638             :     {
    3639             :       nsCOMPtr<nsIChromeRegistry> chromeReg =
    3640           0 :         mozilla::services::GetChromeRegistryService();
    3641           0 :       NS_ENSURE_TRUE(chromeReg, 1);
    3642             : 
    3643           0 :       chromeReg->CheckForNewChrome();
    3644             :     }
    3645           0 :     *aExitFlag = true;
    3646           0 :     return 0;
    3647             :   }
    3648             : 
    3649             :   return 0;
    3650             : }
    3651             : 
    3652             : #ifdef XP_WIN
    3653             : /**
    3654             :  * Uses WMI to read some manufacturer information that may be useful for
    3655             :  * diagnosing hardware-specific crashes. This function is best-effort; failures
    3656             :  * shouldn't burden the caller. COM must be initialized before calling.
    3657             :  */
    3658             : static void AnnotateSystemManufacturer()
    3659             : {
    3660             :   RefPtr<IWbemLocator> locator;
    3661             : 
    3662             :   HRESULT hr = CoCreateInstance(CLSID_WbemLocator, nullptr, CLSCTX_INPROC_SERVER,
    3663             :                                 IID_IWbemLocator, getter_AddRefs(locator));
    3664             : 
    3665             :   if (FAILED(hr)) {
    3666             :     return;
    3667             :   }
    3668             : 
    3669             :   RefPtr<IWbemServices> services;
    3670             : 
    3671             :   hr = locator->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), nullptr, nullptr, nullptr,
    3672             :                               0, nullptr, nullptr, getter_AddRefs(services));
    3673             : 
    3674             :   if (FAILED(hr)) {
    3675             :     return;
    3676             :   }
    3677             : 
    3678             :   hr = CoSetProxyBlanket(services, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nullptr,
    3679             :                          RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE,
    3680             :                          nullptr, EOAC_NONE);
    3681             : 
    3682             :   if (FAILED(hr)) {
    3683             :     return;
    3684             :   }
    3685             : 
    3686             :   RefPtr<IEnumWbemClassObject> enumerator;
    3687             : 
    3688             :   hr = services->ExecQuery(_bstr_t(L"WQL"), _bstr_t(L"SELECT * FROM Win32_BIOS"),
    3689             :                            WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    3690             :                            nullptr, getter_AddRefs(enumerator));
    3691             : 
    3692             :   if (FAILED(hr) || !enumerator) {
    3693             :     return;
    3694             :   }
    3695             : 
    3696             :   RefPtr<IWbemClassObject> classObject;
    3697             :   ULONG results;
    3698             : 
    3699             :   hr = enumerator->Next(WBEM_INFINITE, 1, getter_AddRefs(classObject), &results);
    3700             : 
    3701             :   if (FAILED(hr) || results == 0) {
    3702             :     return;
    3703             :   }
    3704             : 
    3705             :   VARIANT value;
    3706             :   VariantInit(&value);
    3707             : 
    3708             :   hr = classObject->Get(L"Manufacturer", 0, &value, 0, 0);
    3709             : 
    3710             :   if (SUCCEEDED(hr) && V_VT(&value) == VT_BSTR) {
    3711             :     CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("BIOS_Manufacturer"),
    3712             :                                        NS_ConvertUTF16toUTF8(V_BSTR(&value)));
    3713             :   }
    3714             : 
    3715             :   VariantClear(&value);
    3716             : }
    3717             : 
    3718             : static void PR_CALLBACK AnnotateSystemManufacturer_ThreadStart(void*)
    3719             : {
    3720             :   HRESULT hr = CoInitialize(nullptr);
    3721             : 
    3722             :   if (FAILED(hr)) {
    3723             :     return;
    3724             :   }
    3725             : 
    3726             :   AnnotateSystemManufacturer();
    3727             : 
    3728             :   CoUninitialize();
    3729             : }
    3730             : #endif // XP_WIN
    3731             : 
    3732             : #if defined(XP_LINUX) && !defined(ANDROID)
    3733             : 
    3734             : static void
    3735           1 : AnnotateLSBRelease(void*)
    3736             : {
    3737           5 :   nsCString dist, desc, release, codename;
    3738           1 :   if (widget::lsb::GetLSBRelease(dist, desc, release, codename)) {
    3739           0 :     CrashReporter::AppendAppNotesToCrashReport(desc);
    3740             :   }
    3741           1 : }
    3742             : 
    3743             : #endif // defined(XP_LINUX) && !defined(ANDROID)
    3744             : 
    3745             : #ifdef XP_WIN
    3746             : static void ReadAheadDll(const wchar_t* dllName) {
    3747             :   wchar_t dllPath[MAX_PATH];
    3748             :   if (ConstructSystem32Path(dllName, dllPath, MAX_PATH)) {
    3749             :     ReadAheadLib(dllPath);
    3750             :   }
    3751             : }
    3752             : 
    3753             : static void PR_CALLBACK ReadAheadDlls_ThreadStart(void *) {
    3754             :   // Load DataExchange.dll and twinapi.appcore.dll for nsWindow::EnableDragDrop
    3755             :   ReadAheadDll(L"DataExchange.dll");
    3756             :   ReadAheadDll(L"twinapi.appcore.dll");
    3757             : 
    3758             :   // Load twinapi.dll for WindowsUIUtils::UpdateTabletModeState
    3759             :   ReadAheadDll(L"twinapi.dll");
    3760             : 
    3761             :   // Load explorerframe.dll for WinTaskbar::Initialize
    3762             :   ReadAheadDll(L"ExplorerFrame.dll");
    3763             : }
    3764             : #endif
    3765             : 
    3766             : namespace mozilla {
    3767             :   ShutdownChecksMode gShutdownChecks = SCM_NOTHING;
    3768             : } // namespace mozilla
    3769             : 
    3770           1 : static void SetShutdownChecks() {
    3771             :   // Set default first. On debug builds we crash. On nightly and local
    3772             :   // builds we record. Nightlies will then send the info via telemetry,
    3773             :   // but it is usefull to have the data in about:telemetry in local builds
    3774             :   // too.
    3775             : 
    3776             : #ifdef DEBUG
    3777             : #if defined(MOZ_CODE_COVERAGE)
    3778           1 :   gShutdownChecks = SCM_NOTHING;
    3779             : #else
    3780             :   gShutdownChecks = SCM_CRASH;
    3781             : #endif // MOZ_CODE_COVERAGE
    3782             : #else
    3783             :   const char* releaseChannel = NS_STRINGIFY(MOZ_UPDATE_CHANNEL);
    3784             :   if (strcmp(releaseChannel, "nightly") == 0 ||
    3785             :       strcmp(releaseChannel, "default") == 0) {
    3786             :     gShutdownChecks = SCM_RECORD;
    3787             :   } else {
    3788             :     gShutdownChecks = SCM_NOTHING;
    3789             :   }
    3790             : #endif // DEBUG
    3791             : 
    3792             :   // We let an environment variable override the default so that addons
    3793             :   // authors can use it for debugging shutdown with released firefox versions.
    3794           1 :   const char* mozShutdownChecksEnv = PR_GetEnv("MOZ_SHUTDOWN_CHECKS");
    3795           1 :   if (mozShutdownChecksEnv) {
    3796           0 :     if (strcmp(mozShutdownChecksEnv, "crash") == 0) {
    3797           0 :       gShutdownChecks = SCM_CRASH;
    3798           0 :     } else if (strcmp(mozShutdownChecksEnv, "record") == 0) {
    3799           0 :       gShutdownChecks = SCM_RECORD;
    3800           0 :     } else if (strcmp(mozShutdownChecksEnv, "nothing") == 0) {
    3801           0 :       gShutdownChecks = SCM_NOTHING;
    3802             :     }
    3803             :   }
    3804             : 
    3805           0 : }
    3806             : 
    3807             : namespace mozilla {
    3808             : namespace startup {
    3809             :   Result<nsCOMPtr<nsIFile>, nsresult>
    3810           1 :   GetIncompleteStartupFile(nsIFile* aProfLD)
    3811             :   {
    3812           2 :     nsCOMPtr<nsIFile> crashFile;
    3813           3 :     MOZ_TRY(aProfLD->Clone(getter_AddRefs(crashFile)));
    3814           4 :     MOZ_TRY(crashFile->Append(FILE_STARTUP_INCOMPLETE));
    3815           1 :     return std::move(crashFile);
    3816             :   }
    3817             : }
    3818             : }
    3819             : 
    3820             : // Check whether the last startup attempt resulted in a crash within the
    3821             : // last 6 hours.
    3822             : // Note that this duplicates the logic in nsAppStartup::TrackStartupCrashBegin,
    3823             : // which runs too late for our purposes.
    3824             : Result<bool, nsresult>
    3825           1 : XREMain::CheckLastStartupWasCrash()
    3826             : {
    3827           0 :   constexpr int32_t MAX_TIME_SINCE_STARTUP = 6 * 60 * 60 * 1000;
    3828             : 
    3829           0 :   nsCOMPtr<nsIFile> crashFile;
    3830           0 :   MOZ_TRY_VAR(crashFile, GetIncompleteStartupFile(mProfLD));
    3831             : 
    3832             :   // Attempt to create the incomplete startup canary file. If the file already
    3833             :   // exists, this fails, and we know the last startup was a success. If it
    3834             :   // doesn't already exist, it is created, and will be removed at the end of
    3835             :   // the startup crash detection window.
    3836           3 :   AutoFDClose fd;
    3837           2 :   Unused << crashFile->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_EXCL,
    3838           1 :                                         0666, &fd.rwget());
    3839           0 :   if (fd) {
    3840           0 :     return false;
    3841             :   }
    3842             : 
    3843             :   PRTime lastModifiedTime;
    3844           0 :   MOZ_TRY(crashFile->GetLastModifiedTime(&lastModifiedTime));
    3845             : 
    3846             :   // If the file exists, and was created within the appropriate time window,
    3847             :   // the last startup was recent and resulted in a crash.
    3848           0 :   PRTime now = PR_Now() / PR_USEC_PER_MSEC;
    3849           0 :   return now - lastModifiedTime <= MAX_TIME_SINCE_STARTUP;
    3850             : }
    3851             : 
    3852             : /*
    3853             :  * XRE_mainStartup - Initializes the profile and various other services.
    3854             :  * Main() will exit early if either return value != 0 or if aExitFlag is
    3855             :  * true.
    3856             :  */
    3857             : int
    3858           1 : XREMain::XRE_mainStartup(bool* aExitFlag)
    3859             : {
    3860             :   nsresult rv;
    3861             : 
    3862           1 :   if (!aExitFlag)
    3863             :     return 1;
    3864           1 :   *aExitFlag = false;
    3865             : 
    3866           1 :   SetShutdownChecks();
    3867             : 
    3868             :   // Enable Telemetry IO Reporting on DEBUG, nightly and local builds
    3869             : #ifdef DEBUG
    3870           2 :   mozilla::Telemetry::InitIOReporting(gAppData->xreDirectory);
    3871             : #else
    3872             :   {
    3873             :     const char* releaseChannel = NS_STRINGIFY(MOZ_UPDATE_CHANNEL);
    3874             :     if (strcmp(releaseChannel, "nightly") == 0 ||
    3875             :         strcmp(releaseChannel, "default") == 0) {
    3876             :       mozilla::Telemetry::InitIOReporting(gAppData->xreDirectory);
    3877             :     }
    3878             :   }
    3879             : #endif /* DEBUG */
    3880             : 
    3881             : #if defined(XP_WIN)
    3882             :   // Enable the HeapEnableTerminationOnCorruption exploit mitigation. We ignore
    3883             :   // the return code because it always returns success, although it has no
    3884             :   // effect on Windows older than XP SP3.
    3885             :   HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
    3886             : #endif /* XP_WIN */
    3887             : 
    3888             : #if defined(MOZ_WIDGET_GTK) || defined(MOZ_ENABLE_XREMOTE)
    3889             :   // Stash DESKTOP_STARTUP_ID in malloc'ed memory because gtk_init will clear it.
    3890             : #define HAVE_DESKTOP_STARTUP_ID
    3891           1 :   const char* desktopStartupIDEnv = PR_GetEnv("DESKTOP_STARTUP_ID");
    3892           1 :   if (desktopStartupIDEnv) {
    3893           0 :     mDesktopStartupID.Assign(desktopStartupIDEnv);
    3894             :   }
    3895             : #endif
    3896             : 
    3897             : #if defined(MOZ_WIDGET_GTK)
    3898             :   // setup for private colormap.  Ideally we'd like to do this
    3899             :   // in nsAppShell::Create, but we need to get in before gtk
    3900             :   // has been initialized to make sure everything is running
    3901             :   // consistently.
    3902             : 
    3903             :   // Set program name to the one defined in application.ini.
    3904             :   {
    3905           3 :     nsAutoCString program(gAppData->name);
    3906           1 :     ToLowerCase(program);
    3907           1 :     g_set_prgname(program.get());
    3908             :   }
    3909             : 
    3910             :   // Initialize GTK here for splash.
    3911             : 
    3912             : #if defined(MOZ_WIDGET_GTK) && defined(MOZ_X11)
    3913             :   // Disable XInput2 multidevice support due to focus bugginess.
    3914             :   // See bugs 1182700, 1170342.
    3915             :   // gdk_disable_multidevice() affects Gdk X11 backend only,
    3916             :   // the multidevice support is always enabled on Wayland backend.
    3917           1 :   const char* useXI2 = PR_GetEnv("MOZ_USE_XINPUT2");
    3918           1 :   if (!useXI2 || (*useXI2 == '0'))
    3919           1 :     gdk_disable_multidevice();
    3920             : #endif
    3921             : 
    3922             :   // Open the display ourselves instead of using gtk_init, so that we can
    3923             :   // close it without fear that one day gtk might clean up the display it
    3924             :   // opens.
    3925           1 :   if (!gtk_parse_args(&gArgc, &gArgv))
    3926             :     return 1;
    3927             : #endif /* MOZ_WIDGET_GTK */
    3928             : 
    3929             : #ifdef FUZZING
    3930             :   if (PR_GetEnv("FUZZER")) {
    3931             :     *aExitFlag = true;
    3932             :     return mozilla::fuzzerRunner->Run(&gArgc, &gArgv);
    3933             :   }
    3934             : #endif
    3935             : 
    3936           0 :   if (PR_GetEnv("MOZ_RUN_GTEST")) {
    3937             :     int result;
    3938             : #ifdef XP_WIN
    3939             :     UseParentConsole();
    3940             : #endif
    3941             :     // RunGTest will only be set if we're in xul-unit
    3942           0 :     if (mozilla::RunGTest) {
    3943           0 :       gIsGtest = true;
    3944           0 :       result = mozilla::RunGTest(&gArgc, gArgv);
    3945           0 :       gIsGtest = false;
    3946             :     } else {
    3947           0 :       result = 1;
    3948             :       printf("TEST-UNEXPECTED-FAIL | gtest | Not compiled with enable-tests\n");
    3949             :     }
    3950           0 :     *aExitFlag = true;
    3951           0 :     return result;
    3952             :   }
    3953             : 
    3954             : #ifdef MOZ_X11
    3955             :   // Init X11 in thread-safe mode. Must be called prior to the first call to XOpenDisplay
    3956             :   // (called inside gdk_display_open). This is a requirement for off main tread compositing.
    3957           1 :   if (!gfxPlatform::IsHeadless()) {
    3958           0 :     XInitThreads();
    3959             :   }
    3960             : #endif
    3961             : #if defined(MOZ_WIDGET_GTK)
    3962           1 :   if (!gfxPlatform::IsHeadless()) {
    3963           0 :     const char *display_name = nullptr;
    3964           0 :     bool saveDisplayArg = false;
    3965             : 
    3966             :     // display_name is owned by gdk.
    3967           0 :     display_name = gdk_get_display_arg_name();
    3968             :     // if --display argument is given make sure it's
    3969             :     // also passed to ContentChild::Init() by MOZ_GDK_DISPLAY.
    3970           0 :     if (display_name) {
    3971           0 :       SaveWordToEnv("MOZ_GDK_DISPLAY", nsDependentCString(display_name));
    3972           0 :       saveDisplayArg = true;
    3973             :     }
    3974             : 
    3975             :     // On Wayland disabled builds read X11 DISPLAY env exclusively
    3976             :     // and don't care about different displays.
    3977             : #if !defined(MOZ_WAYLAND)
    3978           0 :     if (!display_name) {
    3979           0 :       display_name = PR_GetEnv("DISPLAY");
    3980           0 :       if (!display_name) {
    3981           0 :         PR_fprintf(PR_STDERR,
    3982           0 :                    "Error: no DISPLAY environment variable specified\n");
    3983           0 :         return 1;
    3984             :       }
    3985             :     }
    3986             : #endif
    3987             : 
    3988           0 :     if (display_name) {
    3989           0 :       mGdkDisplay = gdk_display_open(display_name);
    3990           0 :       if (!mGdkDisplay) {
    3991           0 :         PR_fprintf(PR_STDERR, "Error: cannot open display: %s\n", display_name);
    3992           0 :         return 1;
    3993             :       }
    3994           0 :       gdk_display_manager_set_default_display(gdk_display_manager_get(),
    3995           0 :                                               mGdkDisplay);
    3996           0 :       if (saveDisplayArg) {
    3997           0 :         if (GDK_IS_X11_DISPLAY(mGdkDisplay)) {
    3998           0 :             SaveWordToEnv("DISPLAY", nsDependentCString(display_name));
    3999             :         }
    4000             : #ifdef MOZ_WAYLAND
    4001             :         else if (GDK_IS_WAYLAND_DISPLAY(mGdkDisplay)) {
    4002             :             SaveWordToEnv("WAYLAND_DISPLAY", nsDependentCString(display_name));
    4003             :         }
    4004             : #endif
    4005             :       }
    4006             :     }
    4007             : #ifdef MOZ_WIDGET_GTK
    4008             :     else {
    4009           0 :       mGdkDisplay = gdk_display_manager_open_display(gdk_display_manager_get(),
    4010             :                                                      nullptr);
    4011             :     }
    4012             : #endif
    4013             :   }
    4014             :   else {
    4015           0 :     mDisableRemote = true;
    4016             :   }
    4017             : #endif
    4018             : #ifdef MOZ_ENABLE_XREMOTE
    4019             :   // handle --remote now that xpcom is fired up
    4020             :   bool newInstance;
    4021             :   {
    4022           1 :     char *e = PR_GetEnv("MOZ_NO_REMOTE");
    4023           0 :     mDisableRemote = (mDisableRemote || (e && *e));
    4024           0 :     if (mDisableRemote) {
    4025             :       newInstance = true;
    4026             :     } else {
    4027           0 :       e = PR_GetEnv("MOZ_NEW_INSTANCE");
    4028           0 :       newInstance = (e && *e);
    4029             :     }
    4030             :   }
    4031             : 
    4032           1 :   if (!newInstance) {
    4033           0 :     nsAutoCString program(gAppData->remotingName);
    4034           0 :     ToLowerCase(program);
    4035             : 
    4036           0 :     const char* username = getenv("LOGNAME");
    4037           0 :     const char* profile  = nullptr;
    4038             : 
    4039           0 :     RemoteResult rr = ParseRemoteCommandLine(program, &profile, &username);
    4040           0 :     if (rr == REMOTE_ARG_BAD) {
    4041           0 :       return 1;
    4042             :     }
    4043             : 
    4044           0 :     if (!username) {
    4045           0 :       struct passwd *pw = getpwuid(geteuid());
    4046           0 :       if (pw && pw->pw_name) {
    4047             :         // Beware that another call to getpwent/getpwname/getpwuid will overwrite
    4048             :         // pw, but we don't have such another call between here and when username
    4049             :         // is used last.
    4050           0 :         username = pw->pw_name;
    4051             :       }
    4052             :     }
    4053             : 
    4054           0 :     nsCOMPtr<nsIFile> mutexDir;
    4055           0 :     rv = GetSpecialSystemDirectory(OS_TemporaryDirectory, getter_AddRefs(mutexDir));
    4056           0 :     if (NS_SUCCEEDED(rv)) {
    4057           0 :       nsAutoCString mutexPath = program + NS_LITERAL_CSTRING("_");
    4058             :       // In the unlikely even that LOGNAME is not set and getpwuid failed, just
    4059             :       // don't put the username in the mutex directory. It will conflict with
    4060             :       // other users mutex, but the worst that can happen is that they wait for
    4061             :       // MOZ_XREMOTE_START_TIMEOUT_SEC during startup in that case.
    4062           0 :       if (username) {
    4063           0 :         mutexPath.Append(username);
    4064             :       }
    4065           0 :       if (profile) {
    4066           0 :         mutexPath.Append(NS_LITERAL_CSTRING("_") + nsDependentCString(profile));
    4067             :       }
    4068           0 :       mutexDir->AppendNative(mutexPath);
    4069             : 
    4070           0 :       rv = mutexDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
    4071           0 :       if (NS_SUCCEEDED(rv) || rv == NS_ERROR_FILE_ALREADY_EXISTS) {
    4072           0 :         mRemoteLockDir = mutexDir;
    4073             :       }
    4074             :     }
    4075             : 
    4076           0 :     if (mRemoteLockDir) {
    4077           0 :       const TimeStamp epoch = mozilla::TimeStamp::Now();
    4078           0 :       do {
    4079           0 :         rv = mRemoteLock.Lock(mRemoteLockDir, nullptr);
    4080           0 :         if (NS_SUCCEEDED(rv))
    4081             :           break;
    4082           0 :         sched_yield();
    4083           0 :       } while ((TimeStamp::Now() - epoch)
    4084           0 :                < TimeDuration::FromSeconds(MOZ_XREMOTE_START_TIMEOUT_SEC));
    4085           0 :       if (NS_FAILED(rv)) {
    4086           0 :         NS_WARNING("Cannot lock XRemote start mutex");
    4087             :       }
    4088             :     }
    4089             : 
    4090             :     // Try to remote the entire command line. If this fails, start up normally.
    4091             :     const char* desktopStartupIDPtr =
    4092           0 :       mDesktopStartupID.IsEmpty() ? nullptr : mDesktopStartupID.get();
    4093             : 
    4094           0 :     rr = StartRemoteClient(desktopStartupIDPtr, program, profile, username);
    4095           0 :     if (rr == REMOTE_FOUND) {
    4096           0 :       *aExitFlag = true;
    4097           0 :       return 0;
    4098             :     }
    4099           0 :     if (rr == REMOTE_ARG_BAD) {
    4100             :       return 1;
    4101             :     }
    4102             :   }
    4103             : #endif
    4104             : #if defined(MOZ_WIDGET_GTK)
    4105           2 :   g_set_application_name(mAppData->name);
    4106           1 :   gtk_window_set_auto_startup_notification(false);
    4107             : 
    4108             : #endif /* defined(MOZ_WIDGET_GTK) */
    4109             : #ifdef MOZ_X11
    4110             :   // Do this after initializing GDK, or GDK will install its own handler.
    4111           0 :   XRE_InstallX11ErrorHandler();
    4112             : #endif
    4113             : 
    4114             :   // Call the code to install our handler
    4115             : #ifdef MOZ_JPROF
    4116             :   setupProfilingStuff();
    4117             : #endif
    4118             : 
    4119           2 :   rv = NS_CreateNativeAppSupport(getter_AddRefs(mNativeApp));
    4120           1 :   if (NS_FAILED(rv))
    4121             :     return 1;
    4122             : 
    4123           0 :   bool canRun = false;
    4124           1 :   rv = mNativeApp->Start(&canRun);
    4125           1 :   if (NS_FAILED(rv) || !canRun) {
    4126             :     return 1;
    4127             :   }
    4128             : 
    4129             : #if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK)
    4130             :   // DESKTOP_STARTUP_ID is cleared now,
    4131             :   // we recover it in case we need a restart.
    4132           1 :   if (!mDesktopStartupID.IsEmpty()) {
    4133           0 :     nsAutoCString desktopStartupEnv;
    4134           0 :     desktopStartupEnv.AssignLiteral("DESKTOP_STARTUP_ID=");
    4135           0 :     desktopStartupEnv.Append(mDesktopStartupID);
    4136             :     // Leak it with extreme prejudice!
    4137           0 :     PR_SetEnv(ToNewCString(desktopStartupEnv));
    4138             :   }
    4139             : #endif
    4140             : 
    4141             :   // Support exiting early for testing startup sequence. Bug 1360493
    4142           0 :   if (CheckArg("test-launch-without-hang")) {
    4143           0 :     *aExitFlag = true;
    4144           0 :     return 0;
    4145             :   }
    4146             : 
    4147             : #if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)
    4148             :   // Check for and process any available updates
    4149           2 :   nsCOMPtr<nsIFile> updRoot;
    4150             :   bool persistent;
    4151           1 :   rv = mDirProvider.GetFile(XRE_UPDATE_ROOT_DIR, &persistent,
    4152           2 :                             getter_AddRefs(updRoot));
    4153             :   // XRE_UPDATE_ROOT_DIR may fail. Fallback to appDir if failed
    4154           0 :   if (NS_FAILED(rv))
    4155           0 :     updRoot = mDirProvider.GetAppDir();
    4156             : 
    4157             :   // If the MOZ_TEST_PROCESS_UPDATES environment variable already exists, then
    4158             :   // we are being called from the callback application.
    4159           1 :   if (EnvHasValue("MOZ_TEST_PROCESS_UPDATES")) {
    4160             :     // If the caller has asked us to log our arguments, do so.  This is used
    4161             :     // to make sure that the maintenance service successfully launches the
    4162             :     // callback application.
    4163           0 :     const char *logFile = nullptr;
    4164           0 :     if (ARG_FOUND == CheckArg("dump-args", &logFile)) {
    4165           0 :       FILE* logFP = fopen(logFile, "wb");
    4166           0 :       if (logFP) {
    4167           0 :         for (int i = 1; i < gRestartArgc; ++i) {
    4168           0 :           fprintf(logFP, "%s\n", gRestartArgv[i]);
    4169             :         }
    4170           0 :         fclose(logFP);
    4171             :       }
    4172             :     }
    4173           0 :     *aExitFlag = true;
    4174             :     return 0;
    4175             :   }
    4176             : 
    4177             :   // Support for processing an update and exiting. The MOZ_TEST_PROCESS_UPDATES
    4178             :   // environment variable will be part of the updater's environment and the
    4179             :   // application that is relaunched by the updater. When the application is
    4180             :   // relaunched by the updater it will be removed below and the application
    4181             :   // will exit.
    4182           0 :   if (CheckArg("test-process-updates")) {
    4183           0 :     SaveToEnv("MOZ_TEST_PROCESS_UPDATES=1");
    4184             :   }
    4185           3 :   nsCOMPtr<nsIFile> exeFile, exeDir;
    4186           1 :   rv = mDirProvider.GetFile(XRE_EXECUTABLE_FILE, &persistent,
    4187           0 :                             getter_AddRefs(exeFile));
    4188           0 :   NS_ENSURE_SUCCESS(rv, 1);
    4189           0 :   rv = exeFile->GetParent(getter_AddRefs(exeDir));
    4190           0 :   NS_ENSURE_SUCCESS(rv, 1);
    4191           0 :   ProcessUpdates(mDirProvider.GetGREDir(),
    4192             :                  exeDir,
    4193             :                  updRoot,
    4194             :                  gRestartArgc,
    4195             :                  gRestartArgv,
    4196           0 :                  mAppData->version);
    4197           1 :   if (EnvHasValue("MOZ_TEST_PROCESS_UPDATES")) {
    4198           0 :     SaveToEnv("MOZ_TEST_PROCESS_UPDATES=");
    4199           0 :     *aExitFlag = true;
    4200           0 :     return 0;
    4201             :   }
    4202             : #endif
    4203             : 
    4204           2 :   rv = NS_NewToolkitProfileService(getter_AddRefs(mProfileSvc));
    4205           1 :   if (rv == NS_ERROR_FILE_ACCESS_DENIED) {
    4206           0 :     PR_fprintf(PR_STDERR, "Error: Access was denied while trying to open files in " \
    4207           0 :                 "your profile directory.\n");
    4208             :   }
    4209           0 :   if (NS_FAILED(rv)) {
    4210             :     // We failed to choose or create profile - notify user and quit
    4211           0 :     ProfileMissingDialog(mNativeApp);
    4212           0 :     return 1;
    4213             :   }
    4214             : 
    4215           5 :   rv = SelectProfile(getter_AddRefs(mProfileLock), mProfileSvc, mNativeApp, &mStartOffline,
    4216           1 :                       &mProfileName);
    4217           1 :   if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ||
    4218           1 :       rv == NS_ERROR_ABORT) {
    4219           0 :     *aExitFlag = true;
    4220           0 :     return 0;
    4221             :   }
    4222             : 
    4223           1 :   if (NS_FAILED(rv)) {
    4224             :     // We failed to choose or create profile - notify user and quit
    4225           0 :     ProfileMissingDialog(mNativeApp);
    4226           0 :     return 1;
    4227             :   }
    4228           0 :   gProfileLock = mProfileLock;
    4229             : 
    4230           2 :   rv = mProfileLock->GetDirectory(getter_AddRefs(mProfD));
    4231           1 :   NS_ENSURE_SUCCESS(rv, 1);
    4232             : 
    4233           2 :   rv = mProfileLock->GetLocalDirectory(getter_AddRefs(mProfLD));
    4234           0 :   NS_ENSURE_SUCCESS(rv, 1);
    4235             : 
    4236           3 :   rv = mDirProvider.SetProfile(mProfD, mProfLD);
    4237           0 :   NS_ENSURE_SUCCESS(rv, 1);
    4238             : 
    4239             :   //////////////////////// NOW WE HAVE A PROFILE ////////////////////////
    4240             : 
    4241           2 :   mozilla::Telemetry::SetProfileDir(mProfD);
    4242             : 
    4243           0 :   if (mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER)
    4244           2 :       MakeOrSetMinidumpPath(mProfD);
    4245             : 
    4246           2 :   CrashReporter::SetProfileDirectory(mProfD);
    4247             : 
    4248           1 :   nsAutoCString version;
    4249           1 :   BuildVersion(version);
    4250             : 
    4251             : #ifdef TARGET_OS_ABI
    4252           1 :   NS_NAMED_LITERAL_CSTRING(osABI, TARGET_OS_ABI);
    4253             : #else
    4254             :   // No TARGET_XPCOM_ABI, but at least the OS is known
    4255             :   NS_NAMED_LITERAL_CSTRING(osABI, OS_TARGET "_UNKNOWN");
    4256             : #endif
    4257             : 
    4258             :   // Check for version compatibility with the last version of the app this
    4259             :   // profile was started with.  The format of the version stamp is defined
    4260             :   // by the BuildVersion function.
    4261             :   // Also check to see if something has happened to invalidate our
    4262             :   // fastload caches, like an extension upgrade or installation.
    4263             : 
    4264             :   // If we see .purgecaches, that means someone did a make.
    4265             :   // Re-register components to catch potential changes.
    4266           2 :   nsCOMPtr<nsIFile> flagFile;
    4267           0 :   rv = NS_ERROR_FILE_NOT_FOUND;
    4268           2 :   if (mAppData->directory) {
    4269           0 :     rv = mAppData->directory->Clone(getter_AddRefs(flagFile));
    4270             :   }
    4271           1 :   if (flagFile) {
    4272           0 :     flagFile->AppendNative(FILE_INVALIDATE_CACHES);
    4273             :   }
    4274             : 
    4275             :   bool cachesOK;
    4276           0 :   bool versionOK = CheckCompatibility(mProfD, version, osABI,
    4277             :                                       mDirProvider.GetGREDir(),
    4278           1 :                                       mAppData->directory, flagFile,
    4279           2 :                                       &cachesOK);
    4280             : 
    4281           2 :   bool lastStartupWasCrash = CheckLastStartupWasCrash().unwrapOr(false);
    4282             : 
    4283           1 :   if (CheckArg("purgecaches") || PR_GetEnv("MOZ_PURGE_CACHES") ||
    4284             :       lastStartupWasCrash) {
    4285           0 :     cachesOK = false;
    4286             :   }
    4287             : 
    4288             :   // Every time a profile is loaded by a build with a different version,
    4289             :   // it updates the compatibility.ini file saying what version last wrote
    4290             :   // the fastload caches.  On subsequent launches if the version matches,
    4291             :   // there is no need for re-registration.  If the user loads the same
    4292             :   // profile in different builds the component registry must be
    4293             :   // re-generated to prevent mysterious component loading failures.
    4294             :   //
    4295           1 :   bool startupCacheValid = true;
    4296           1 :   if (gSafeMode) {
    4297           0 :     startupCacheValid = RemoveComponentRegistries(mProfD, mProfLD, false);
    4298           0 :     WriteVersion(mProfD, NS_LITERAL_CSTRING("Safe Mode"), osABI,
    4299           0 :                  mDirProvider.GetGREDir(), mAppData->directory, !startupCacheValid);
    4300             :   }
    4301           0 :   else if (versionOK) {
    4302           0 :     if (!cachesOK) {
    4303             :       // Remove caches, forcing component re-registration.
    4304             :       // The new list of additional components directories is derived from
    4305             :       // information in "extensions.ini".
    4306           0 :       startupCacheValid = RemoveComponentRegistries(mProfD, mProfLD, false);
    4307             : 
    4308             :       // Rewrite compatibility.ini to remove the flag
    4309           0 :       WriteVersion(mProfD, version, osABI,
    4310           0 :                    mDirProvider.GetGREDir(), mAppData->directory, !startupCacheValid);
    4311             :     }
    4312             :     // Nothing need be done for the normal startup case.
    4313             :   }
    4314             :   else {
    4315             :     // Remove caches, forcing component re-registration
    4316             :     // with the default set of components (this disables any potentially
    4317             :     // troublesome incompatible XPCOM components).
    4318           3 :     startupCacheValid = RemoveComponentRegistries(mProfD, mProfLD, true);
    4319             : 
    4320             :     // Write out version
    4321           6 :     WriteVersion(mProfD, version, osABI,
    4322           4 :                  mDirProvider.GetGREDir(), mAppData->directory, !startupCacheValid);
    4323             :   }
    4324             : 
    4325           1 :   if (!startupCacheValid)
    4326           0 :     StartupCache::IgnoreDiskCache();
    4327             : 
    4328           1 :   if (flagFile) {
    4329           1 :     flagFile->Remove(true);
    4330             :   }
    4331             : 
    4332             :   return 0;
    4333             : }
    4334             : 
    4335             : #if defined(MOZ_CONTENT_SANDBOX)
    4336             : void AddSandboxAnnotations()
    4337             : {
    4338             :   // Include the sandbox content level, regardless of platform
    4339             :   int level = GetEffectiveContentSandboxLevel();
    4340             : 
    4341             :   nsAutoCString levelString;
    4342             :   levelString.AppendInt(level);
    4343             : 
    4344             :   CrashReporter::AnnotateCrashReport(
    4345             :     NS_LITERAL_CSTRING("ContentSandboxLevel"), levelString);
    4346             : 
    4347             :   // Include whether or not this instance is capable of content sandboxing
    4348             :   bool sandboxCapable = false;
    4349             : 
    4350             : #if defined(XP_WIN)
    4351             :   // All supported Windows versions support some level of content sandboxing
    4352             :   sandboxCapable = true;
    4353             : #elif defined(XP_MACOSX)
    4354             :   // All supported OS X versions are capable
    4355             :   sandboxCapable = true;
    4356             : #elif defined(XP_LINUX)
    4357             :   sandboxCapable = SandboxInfo::Get().CanSandboxContent();
    4358             : #endif
    4359             : 
    4360             :   CrashReporter::AnnotateCrashReport(
    4361             :     NS_LITERAL_CSTRING("ContentSandboxCapable"),
    4362             :     sandboxCapable ? NS_LITERAL_CSTRING("1") : NS_LITERAL_CSTRING("0"));
    4363             : }
    4364             : #endif /* MOZ_CONTENT_SANDBOX */
    4365             : 
    4366             : /*
    4367             :  * XRE_mainRun - Command line startup, profile migration, and
    4368             :  * the calling of appStartup->Run().
    4369             :  */
    4370             : nsresult
    4371           1 : XREMain::XRE_mainRun()
    4372             : {
    4373           1 :   nsresult rv = NS_OK;
    4374           2 :   NS_ASSERTION(mScopedXPCOM, "Scoped xpcom not initialized.");
    4375             : 
    4376             : #if defined(XP_WIN)
    4377             :   RefPtr<mozilla::DllServices> dllServices(mozilla::DllServices::Get());
    4378             :   auto dllServicesDisable = MakeScopeExit([&dllServices]() {
    4379             :     dllServices->Disable();
    4380             :   });
    4381             : #endif // defined(XP_WIN)
    4382             : 
    4383             : #ifdef NS_FUNCTION_TIMER
    4384             :   // initialize some common services, so we don't pay the cost for these at odd times later on;
    4385             :   // SetWindowCreator -> ChromeRegistry -> IOService -> SocketTransportService -> (nspr wspm init), Prefs
    4386             :   {
    4387             :     nsCOMPtr<nsISupports> comp;
    4388             : 
    4389             :     comp = do_GetService("@mozilla.org/preferences-service;1");
    4390             : 
    4391             :     comp = do_GetService("@mozilla.org/network/socket-transport-service;1");
    4392             : 
    4393             :     comp = do_GetService("@mozilla.org/network/dns-service;1");
    4394             : 
    4395             :     comp = do_GetService("@mozilla.org/network/io-service;1");
    4396             : 
    4397             :     comp = do_GetService("@mozilla.org/chrome/chrome-registry;1");
    4398             : 
    4399             :     comp = do_GetService("@mozilla.org/focus-event-suppressor-service;1");
    4400             :   }
    4401             : #endif
    4402             : 
    4403           0 :   rv = mScopedXPCOM->SetWindowCreator(mNativeApp);
    4404           0 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
    4405             : 
    4406             :   // tell the crash reporter to also send the release channel
    4407           0 :   nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &rv);
    4408           0 :   if (NS_SUCCEEDED(rv)) {
    4409           2 :     nsCOMPtr<nsIPrefBranch> defaultPrefBranch;
    4410           2 :     rv = prefs->GetDefaultBranch(nullptr, getter_AddRefs(defaultPrefBranch));
    4411             : 
    4412           1 :     if (NS_SUCCEEDED(rv)) {
    4413           0 :       nsAutoCString sval;
    4414           0 :       rv = defaultPrefBranch->GetCharPref("app.update.channel", sval);
    4415           0 :       if (NS_SUCCEEDED(rv)) {
    4416           0 :         CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ReleaseChannel"),
    4417           2 :                                             sval);
    4418             :       }
    4419             :     }
    4420             :   }
    4421             :   // Needs to be set after xpcom initialization.
    4422           1 :   CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("FramePoisonBase"),
    4423           4 :                                      nsPrintfCString("%.16" PRIu64, uint64_t(gMozillaPoisonBase)));
    4424           1 :   CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("FramePoisonSize"),
    4425           4 :                                      nsPrintfCString("%" PRIu32, uint32_t(gMozillaPoisonSize)));
    4426             : 
    4427             :   bool includeContextHeap =
    4428           1 :     Preferences::GetBool("toolkit.crashreporter.include_context_heap", false);
    4429           0 :   CrashReporter::SetIncludeContextHeap(includeContextHeap);
    4430             : 
    4431             : #ifdef XP_WIN
    4432             :   PR_CreateThread(PR_USER_THREAD, AnnotateSystemManufacturer_ThreadStart, 0,
    4433             :                   PR_PRIORITY_LOW, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0);
    4434             : #endif
    4435             : 
    4436             : #if defined(XP_LINUX) && !defined(ANDROID)
    4437             :   PR_CreateThread(PR_USER_THREAD, AnnotateLSBRelease, 0, PR_PRIORITY_LOW,
    4438           1 :                   PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0);
    4439             : #endif
    4440             : 
    4441           1 :   if (mStartOffline) {
    4442           0 :     nsCOMPtr<nsIIOService> io(do_GetService("@mozilla.org/network/io-service;1"));
    4443           0 :     NS_ENSURE_TRUE(io, NS_ERROR_FAILURE);
    4444           0 :     io->SetManageOfflineStatus(false);
    4445           0 :     io->SetOffline(true);
    4446             :   }
    4447             : 
    4448             : 
    4449             : #ifdef XP_WIN
    4450             :   if (!PR_GetEnv("XRE_NO_DLL_READAHEAD"))
    4451             :   {
    4452             :     PR_CreateThread(PR_USER_THREAD, ReadAheadDlls_ThreadStart, 0,
    4453             :                     PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
    4454             :                     PR_UNJOINABLE_THREAD, 0);
    4455             :   }
    4456             : #endif
    4457             : 
    4458           0 :   if (gDoMigration) {
    4459           0 :     nsCOMPtr<nsIFile> file;
    4460           0 :     mDirProvider.GetAppDir()->Clone(getter_AddRefs(file));
    4461           0 :     file->AppendNative(NS_LITERAL_CSTRING("override.ini"));
    4462           0 :     nsINIParser parser;
    4463           0 :     nsresult rv = parser.Init(file);
    4464             :     // if override.ini doesn't exist, also check for distribution.ini
    4465           0 :     if (NS_FAILED(rv)) {
    4466             :       bool persistent;
    4467           0 :       mDirProvider.GetFile(XRE_APP_DISTRIBUTION_DIR, &persistent,
    4468           0 :                            getter_AddRefs(file));
    4469           0 :       file->AppendNative(NS_LITERAL_CSTRING("distribution.ini"));
    4470           0 :       rv = parser.Init(file);
    4471             :     }
    4472           0 :     if (NS_SUCCEEDED(rv)) {
    4473           0 :       nsAutoCString buf;
    4474           0 :       rv = parser.GetString("XRE", "EnableProfileMigrator", buf);
    4475           0 :       if (NS_SUCCEEDED(rv)) {
    4476           0 :         if (buf[0] == '0' || buf[0] == 'f' || buf[0] == 'F') {
    4477           0 :           gDoMigration = false;
    4478             :         }
    4479             :       }
    4480             :     }
    4481             :   }
    4482             : 
    4483             :   {
    4484           0 :     nsCOMPtr<nsIToolkitProfile> profileBeingReset;
    4485           1 :     bool profileWasSelected = false;
    4486           1 :     if (gDoProfileReset) {
    4487           0 :       if (gResetOldProfileName.IsEmpty()) {
    4488           0 :         NS_WARNING("Not resetting profile as the profile has no name.");
    4489           0 :         gDoProfileReset = false;
    4490             :       } else {
    4491           0 :         rv = mProfileSvc->GetProfileByName(gResetOldProfileName,
    4492           0 :                                            getter_AddRefs(profileBeingReset));
    4493           0 :         if (NS_FAILED(rv)) {
    4494           0 :           gDoProfileReset = false;
    4495           0 :           return NS_ERROR_FAILURE;
    4496             :         }
    4497             : 
    4498           0 :         nsCOMPtr<nsIToolkitProfile> defaultProfile;
    4499             :         // This can fail if there is no default profile.
    4500             :         // That shouldn't stop reset from proceeding.
    4501           0 :         nsresult gotSelected = mProfileSvc->GetSelectedProfile(getter_AddRefs(defaultProfile));
    4502           0 :         if (NS_SUCCEEDED(gotSelected)) {
    4503           0 :           profileWasSelected = defaultProfile == profileBeingReset;
    4504             :         }
    4505             :       }
    4506             :     }
    4507             : 
    4508             :     // Profile Migration
    4509           1 :     if (mAppData->flags & NS_XRE_ENABLE_PROFILE_MIGRATOR && gDoMigration) {
    4510           0 :       gDoMigration = false;
    4511           0 :       nsCOMPtr<nsIProfileMigrator> pm(do_CreateInstance(NS_PROFILEMIGRATOR_CONTRACTID));
    4512           0 :       if (pm) {
    4513           0 :         nsAutoCString aKey;
    4514           0 :         if (gDoProfileReset) {
    4515             :           // Automatically migrate from the current application if we just
    4516             :           // reset the profile.
    4517             :           aKey = MOZ_APP_NAME;
    4518             :         }
    4519           0 :         pm->Migrate(&mDirProvider, aKey, gResetOldProfileName);
    4520             :       }
    4521             :     }
    4522             : 
    4523           1 :     if (gDoProfileReset) {
    4524           0 :       nsresult backupCreated = ProfileResetCleanup(profileBeingReset);
    4525           0 :       if (NS_FAILED(backupCreated)) NS_WARNING("Could not cleanup the profile that was reset");
    4526             : 
    4527           0 :       nsCOMPtr<nsIToolkitProfile> newProfile;
    4528           0 :       rv = GetCurrentProfile(mProfileSvc, mProfD, getter_AddRefs(newProfile));
    4529           0 :       if (NS_SUCCEEDED(rv)) {
    4530           0 :         newProfile->SetName(gResetOldProfileName);
    4531           0 :         mProfileName.Assign(gResetOldProfileName);
    4532             :         // Set the new profile as the default after we're done cleaning up the old profile,
    4533             :         // iff that profile was already the default
    4534           0 :         if (profileWasSelected) {
    4535           0 :           rv = mProfileSvc->SetDefaultProfile(newProfile);
    4536           0 :           if (NS_FAILED(rv)) NS_WARNING("Could not set current profile as the default");
    4537             :         }
    4538             :       } else {
    4539           0 :         NS_WARNING("Could not find current profile to set as default / change name.");
    4540             :       }
    4541             : 
    4542             :       // Need to write out the fact that the profile has been removed, the new profile
    4543             :       // renamed, and potentially that the selected/default profile changed.
    4544           0 :       mProfileSvc->Flush();
    4545             :     }
    4546             :   }
    4547             : 
    4548             : #ifndef XP_WIN
    4549           1 :     nsCOMPtr<nsIFile> profileDir;
    4550           1 :     nsAutoCString path;
    4551           0 :     rv = mDirProvider.GetProfileStartupDir(getter_AddRefs(profileDir));
    4552           1 :     if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(profileDir->GetNativePath(path)) && !IsUTF8(path)) {
    4553           0 :       PR_fprintf(PR_STDERR, "Error: The profile path is not valid UTF-8. Unable to continue.\n");
    4554           0 :       return NS_ERROR_FAILURE;
    4555             :     }
    4556             : #endif
    4557             : 
    4558             :   // Initialize user preferences before notifying startup observers so they're
    4559             :   // ready in time for early consumers, such as the component loader.
    4560           1 :   mDirProvider.InitializeUserPrefs();
    4561             : 
    4562             :   {
    4563             :     nsCOMPtr<nsIObserver> startupNotifier
    4564           2 :       (do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID, &rv));
    4565           0 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
    4566             : 
    4567           0 :     startupNotifier->Observe(nullptr, APPSTARTUP_TOPIC, nullptr);
    4568             :   }
    4569             : 
    4570             :   nsCOMPtr<nsIAppStartup> appStartup
    4571           0 :     (do_GetService(NS_APPSTARTUP_CONTRACTID));
    4572           1 :   NS_ENSURE_TRUE(appStartup, NS_ERROR_FAILURE);
    4573             : 
    4574           1 :   mDirProvider.DoStartup();
    4575             : 
    4576             :   // As FilePreferences need the profile directory, we must initialize right here.
    4577           0 :   mozilla::FilePreferences::InitDirectoriesWhitelist();
    4578           0 :   mozilla::FilePreferences::InitPrefs();
    4579             : 
    4580           1 :   OverrideDefaultLocaleIfNeeded();
    4581             : 
    4582           0 :   nsCString userAgentLocale;
    4583           0 :   LocaleService::GetInstance()->GetAppLocaleAsLangTag(userAgentLocale);
    4584           2 :   CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("useragent_locale"), userAgentLocale);
    4585             : 
    4586           0 :   appStartup->GetShuttingDown(&mShuttingDown);
    4587             : 
    4588           1 :   nsCOMPtr<nsICommandLineRunner> cmdLine;
    4589             : 
    4590           1 :   nsCOMPtr<nsIFile> workingDir;
    4591           1 :   rv = NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR, getter_AddRefs(workingDir));
    4592           0 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
    4593             : 
    4594           0 :   if (!mShuttingDown) {
    4595           1 :     cmdLine = do_CreateInstance("@mozilla.org/toolkit/command-line;1");
    4596           1 :     NS_ENSURE_TRUE(cmdLine, NS_ERROR_FAILURE);
    4597             : 
    4598           2 :     rv = cmdLine->Init(gArgc, gArgv, workingDir,
    4599           1 :                        nsICommandLine::STATE_INITIAL_LAUNCH);
    4600           1 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
    4601             : 
    4602             :     /* Special-case services that need early access to the command
    4603             :         line. */
    4604             :     nsCOMPtr<nsIObserverService> obsService =
    4605           2 :       mozilla::services::GetObserverService();
    4606           1 :     if (obsService) {
    4607           2 :       obsService->NotifyObservers(cmdLine, "command-line-startup", nullptr);
    4608             :     }
    4609             :   }
    4610             : 
    4611             : #ifdef XP_WIN
    4612             :   // Hack to sync up the various environment storages. XUL_APP_FILE is special
    4613             :   // in that it comes from a different CRT (firefox.exe's static-linked copy).
    4614             :   // Ugly details in http://bugzil.la/1175039#c27
    4615             :   char appFile[MAX_PATH];
    4616             :   if (GetEnvironmentVariableA("XUL_APP_FILE", appFile, sizeof(appFile))) {
    4617             :     SmprintfPointer saved = mozilla::Smprintf("XUL_APP_FILE=%s", appFile);
    4618             :     // We intentionally leak the string here since it is required by PR_SetEnv.
    4619             :     PR_SetEnv(saved.release());
    4620             :   }
    4621             : 
    4622             : #if defined(MOZ_SANDBOX)
    4623             :   // Call SandboxBroker to initialize things that depend on Gecko machinery like
    4624             :   // the directory provider.
    4625             :   SandboxBroker::GeckoDependentInitialize();
    4626             : #endif
    4627             : #endif
    4628             : 
    4629           0 :   SaveStateForAppInitiatedRestart();
    4630             : 
    4631             :   // clear out any environment variables which may have been set
    4632             :   // during the relaunch process now that we know we won't be relaunching.
    4633           1 :   SaveToEnv("XRE_PROFILE_PATH=");
    4634           1 :   SaveToEnv("XRE_PROFILE_LOCAL_PATH=");
    4635           1 :   SaveToEnv("XRE_PROFILE_NAME=");
    4636           1 :   SaveToEnv("XRE_START_OFFLINE=");
    4637           1 :   SaveToEnv("NO_EM_RESTART=");
    4638           0 :   SaveToEnv("XUL_APP_FILE=");
    4639           0 :   SaveToEnv("XRE_BINARY_PATH=");
    4640             : 
    4641           1 :   if (!mShuttingDown) {
    4642           1 :     rv = appStartup->CreateHiddenWindow();
    4643           1 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
    4644             : 
    4645             : #ifdef XP_WIN
    4646             :     Preferences::RegisterCallbackAndCall(RegisterApplicationRestartChanged,
    4647             :                                          PREF_WIN_REGISTER_APPLICATION_RESTART);
    4648             : #endif
    4649             : 
    4650             : #if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK)
    4651           1 :     nsGTKToolkit* toolkit = nsGTKToolkit::GetToolkit();
    4652           1 :     if (toolkit && !mDesktopStartupID.IsEmpty()) {
    4653           0 :       toolkit->SetDesktopStartupID(mDesktopStartupID);
    4654             :     }
    4655             :     // Clear the environment variable so it won't be inherited by
    4656             :     // child processes and confuse things.
    4657           1 :     g_unsetenv ("DESKTOP_STARTUP_ID");
    4658             : #endif
    4659             : 
    4660             : #ifdef XP_MACOSX
    4661             :     // we re-initialize the command-line service and do appleevents munging
    4662             :     // after we are sure that we're not restarting
    4663             :     cmdLine = do_CreateInstance("@mozilla.org/toolkit/command-line;1");
    4664             :     NS_ENSURE_TRUE(cmdLine, NS_ERROR_FAILURE);
    4665             : 
    4666             :     CommandLineServiceMac::SetupMacCommandLine(gArgc, gArgv, false);
    4667             : 
    4668             :     rv = cmdLine->Init(gArgc, gArgv,
    4669             :                         workingDir, nsICommandLine::STATE_INITIAL_LAUNCH);
    4670             :     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
    4671             : #endif
    4672             : 
    4673             :     nsCOMPtr<nsIObserverService> obsService =
    4674           0 :       mozilla::services::GetObserverService();
    4675           0 :     if (obsService)
    4676           1 :       obsService->NotifyObservers(nullptr, "final-ui-startup", nullptr);
    4677             : 
    4678           1 :     (void)appStartup->DoneStartingUp();
    4679             : 
    4680           0 :     CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("StartupCrash"),
    4681           5 :                                        NS_LITERAL_CSTRING("0"));
    4682             : 
    4683           1 :     appStartup->GetShuttingDown(&mShuttingDown);
    4684             :   }
    4685             : 
    4686           0 :   if (!mShuttingDown) {
    4687           0 :     rv = cmdLine->Run();
    4688           0 :     NS_ENSURE_SUCCESS_LOG(rv, NS_ERROR_FAILURE);
    4689             : 
    4690           0 :     appStartup->GetShuttingDown(&mShuttingDown);
    4691             :   }
    4692             : 
    4693           1 :   if (!mShuttingDown) {
    4694             : #ifdef MOZ_ENABLE_XREMOTE
    4695             :     // if we have X remote support, start listening for requests on the
    4696             :     // proxy window.
    4697           1 :     if (!mDisableRemote)
    4698           0 :       mRemoteService = do_GetService("@mozilla.org/toolkit/remote-service;1");
    4699           0 :     if (mRemoteService)
    4700           0 :       mRemoteService->Startup(mAppData->remotingName, mProfileName.get());
    4701           0 :     if (mRemoteLockDir) {
    4702           0 :       mRemoteLock.Unlock();
    4703           0 :       mRemoteLock.Cleanup();
    4704           0 :       mRemoteLockDir->Remove(false);
    4705             :     }
    4706             : #endif /* MOZ_ENABLE_XREMOTE */
    4707             : 
    4708           1 :     mNativeApp->Enable();
    4709             :   }
    4710             : 
    4711             : #ifdef MOZ_INSTRUMENT_EVENT_LOOP
    4712           1 :   if (PR_GetEnv("MOZ_INSTRUMENT_EVENT_LOOP")) {
    4713           0 :     bool logToConsole = true;
    4714           0 :     mozilla::InitEventTracing(logToConsole);
    4715             :   }
    4716             : #endif /* MOZ_INSTRUMENT_EVENT_LOOP */
    4717             : 
    4718             : #if defined(MOZ_SANDBOX) && defined(XP_LINUX)
    4719             :   // If we're on Linux, we now have information about the OS capabilities
    4720             :   // available to us.
    4721             :   SandboxInfo sandboxInfo = SandboxInfo::Get();
    4722             :   Telemetry::Accumulate(Telemetry::SANDBOX_HAS_SECCOMP_BPF,
    4723             :                         sandboxInfo.Test(SandboxInfo::kHasSeccompBPF));
    4724             :   Telemetry::Accumulate(Telemetry::SANDBOX_HAS_SECCOMP_TSYNC,
    4725             :                         sandboxInfo.Test(SandboxInfo::kHasSeccompTSync));
    4726             :   Telemetry::Accumulate(Telemetry::SANDBOX_HAS_USER_NAMESPACES_PRIVILEGED,
    4727             :                         sandboxInfo.Test(SandboxInfo::kHasPrivilegedUserNamespaces));
    4728             :   Telemetry::Accumulate(Telemetry::SANDBOX_HAS_USER_NAMESPACES,
    4729             :                         sandboxInfo.Test(SandboxInfo::kHasUserNamespaces));
    4730             :   Telemetry::Accumulate(Telemetry::SANDBOX_CONTENT_ENABLED,
    4731             :                         sandboxInfo.Test(SandboxInfo::kEnabledForContent));
    4732             :   Telemetry::Accumulate(Telemetry::SANDBOX_MEDIA_ENABLED,
    4733             :                         sandboxInfo.Test(SandboxInfo::kEnabledForMedia));
    4734             :   nsAutoCString flagsString;
    4735             :   flagsString.AppendInt(sandboxInfo.AsInteger());
    4736             : 
    4737             :   CrashReporter::AnnotateCrashReport(
    4738             :     NS_LITERAL_CSTRING("ContentSandboxCapabilities"), flagsString);
    4739             : #endif /* MOZ_SANDBOX && XP_LINUX */
    4740             : 
    4741             : #if defined(MOZ_CONTENT_SANDBOX)
    4742             :   AddSandboxAnnotations();
    4743             : #endif /* MOZ_CONTENT_SANDBOX */
    4744             : 
    4745             :   {
    4746           1 :     rv = appStartup->Run();
    4747           0 :     if (NS_FAILED(rv)) {
    4748           0 :       NS_ERROR("failed to run appstartup");
    4749           0 :       gLogConsoleErrors = true;
    4750             :     }
    4751             :   }
    4752             : 
    4753           0 :   return rv;
    4754             : }
    4755             : 
    4756             : /*
    4757             :  * XRE_main - A class based main entry point used by most platforms.
    4758             :  *            Note that on OSX, aAppData->xreDirectory will point to
    4759             :  *            .app/Contents/Resources.
    4760             :  */
    4761             : int
    4762           0 : XREMain::XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig)
    4763             : {
    4764             :   ScopedLogging log;
    4765             : 
    4766           1 :   mozilla::LogModule::Init(argc, argv);
    4767             : 
    4768             : #ifdef MOZ_CODE_COVERAGE
    4769           1 :   CodeCoverageHandler::Init();
    4770             : #endif
    4771             : 
    4772           1 :   AUTO_PROFILER_INIT;
    4773           1 :   AUTO_PROFILER_LABEL("XREMain::XRE_main", OTHER);
    4774             : 
    4775           1 :   nsresult rv = NS_OK;
    4776             : 
    4777           1 :   gArgc = argc;
    4778           1 :   gArgv = argv;
    4779             : 
    4780           1 :   if (aConfig.appData) {
    4781           1 :       mAppData = MakeUnique<XREAppData>(*aConfig.appData);
    4782             :   } else {
    4783           0 :     MOZ_RELEASE_ASSERT(aConfig.appDataPath);
    4784           0 :     nsCOMPtr<nsIFile> appini;
    4785           0 :     rv = XRE_GetFileFromPath(aConfig.appDataPath, getter_AddRefs(appini));
    4786           0 :     if (NS_FAILED(rv)) {
    4787           0 :       Output(true, "Error: unrecognized path: %s\n", aConfig.appDataPath);
    4788           0 :       return 1;
    4789             :     }
    4790             : 
    4791           0 :     mAppData = MakeUnique<XREAppData>();
    4792           0 :     rv = XRE_ParseAppData(appini, *mAppData);
    4793           0 :     if (NS_FAILED(rv)) {
    4794           0 :       Output(true, "Couldn't read application.ini");
    4795           0 :       return 1;
    4796             :     }
    4797             : 
    4798           0 :     appini->GetParent(getter_AddRefs(mAppData->directory));
    4799             :   }
    4800             : 
    4801           0 :   if (!mAppData->remotingName) {
    4802           0 :     mAppData->remotingName = mAppData->name;
    4803             :   }
    4804             :   // used throughout this file
    4805           1 :   gAppData = mAppData.get();
    4806             : 
    4807           0 :   nsCOMPtr<nsIFile> binFile;
    4808           0 :   rv = XRE_GetBinaryPath(getter_AddRefs(binFile));
    4809           0 :   NS_ENSURE_SUCCESS(rv, 1);
    4810             : 
    4811           1 :   rv = binFile->GetPath(gAbsoluteArgv0Path);
    4812           1 :   NS_ENSURE_SUCCESS(rv, 1);
    4813             : 
    4814           2 :   if (!mAppData->xreDirectory) {
    4815           2 :     nsCOMPtr<nsIFile> lf;
    4816           2 :     rv = XRE_GetBinaryPath(getter_AddRefs(lf));
    4817           1 :     if (NS_FAILED(rv))
    4818           0 :       return 2;
    4819             : 
    4820           2 :     nsCOMPtr<nsIFile> greDir;
    4821           2 :     rv = lf->GetParent(getter_AddRefs(greDir));
    4822           0 :     if (NS_FAILED(rv))
    4823           0 :       return 2;
    4824             : 
    4825             : #ifdef XP_MACOSX
    4826             :     nsCOMPtr<nsIFile> parent;
    4827             :     greDir->GetParent(getter_AddRefs(parent));
    4828             :     greDir = parent.forget();
    4829             :     greDir->AppendNative(NS_LITERAL_CSTRING("Resources"));
    4830             : #endif
    4831             : 
    4832           1 :     mAppData->xreDirectory = greDir;
    4833             :   }
    4834             : 
    4835           1 :   if (aConfig.appData && aConfig.appDataPath) {
    4836           2 :     mAppData->xreDirectory->Clone(getter_AddRefs(mAppData->directory));
    4837           2 :     mAppData->directory->AppendNative(nsDependentCString(aConfig.appDataPath));
    4838             :   }
    4839             : 
    4840           2 :   if (!mAppData->directory) {
    4841           0 :     mAppData->directory = mAppData->xreDirectory;
    4842             :   }
    4843             : 
    4844             : #if defined(XP_WIN) && defined(MOZ_SANDBOX)
    4845             :   mAppData->sandboxBrokerServices = aConfig.sandboxBrokerServices;
    4846             :   mAppData->sandboxPermissionsService = aConfig.sandboxPermissionsService;
    4847             : #endif
    4848             : 
    4849             :   mozilla::IOInterposerInit ioInterposerGuard;
    4850             : 
    4851             : #if defined(XP_WIN)
    4852             :   // Some COM settings are global to the process and must be set before any non-
    4853             :   // trivial COM is run in the application. Since these settings may affect
    4854             :   // stability, we should instantiate COM ASAP so that we can ensure that these
    4855             :   // global settings are configured before anything can interfere.
    4856             :   mozilla::mscom::MainThreadRuntime msCOMRuntime;
    4857             : #endif
    4858             : 
    4859             :   // init
    4860           0 :   bool exit = false;
    4861           1 :   int result = XRE_mainInit(&exit);
    4862           1 :   if (result != 0 || exit)
    4863             :     return result;
    4864             : 
    4865             :   // If we exit gracefully, remove the startup crash canary file.
    4866           0 :   auto cleanup = MakeScopeExit([&] () -> nsresult {
    4867           0 :     if (mProfLD) {
    4868           0 :       nsCOMPtr<nsIFile> crashFile;
    4869           0 :       MOZ_TRY_VAR(crashFile, GetIncompleteStartupFile(mProfLD));
    4870           0 :       crashFile->Remove(false);
    4871             :     }
    4872             :     return NS_OK;
    4873           1 :   });
    4874             : 
    4875             :   // startup
    4876           1 :   result = XRE_mainStartup(&exit);
    4877           1 :   if (result != 0 || exit)
    4878             :     return result;
    4879             : 
    4880           1 :   bool appInitiatedRestart = false;
    4881             : 
    4882             :   // Start the real application
    4883           1 :   mScopedXPCOM = MakeUnique<ScopedXPCOMStartup>();
    4884           0 :   if (!mScopedXPCOM)
    4885             :     return 1;
    4886             : 
    4887           1 :   rv = mScopedXPCOM->Initialize();
    4888           0 :   NS_ENSURE_SUCCESS(rv, 1);
    4889             : 
    4890             :   // run!
    4891           1 :   rv = XRE_mainRun();
    4892             : 
    4893             : #ifdef MOZ_INSTRUMENT_EVENT_LOOP
    4894           0 :   mozilla::ShutdownEventTracing();
    4895             : #endif
    4896             : 
    4897           0 :   gAbsoluteArgv0Path.Truncate();
    4898             : 
    4899             :   // Check for an application initiated restart.  This is one that
    4900             :   // corresponds to nsIAppStartup.quit(eRestart)
    4901           0 :   if (rv == NS_SUCCESS_RESTART_APP
    4902           0 :       || rv == NS_SUCCESS_RESTART_APP_NOT_SAME_PROFILE) {
    4903           0 :     appInitiatedRestart = true;
    4904             : 
    4905             :     // We have an application restart don't do any shutdown checks here
    4906             :     // In particular we don't want to poison IO for checking late-writes.
    4907           0 :     gShutdownChecks = SCM_NOTHING;
    4908             :   }
    4909             : 
    4910           0 :   if (!mShuttingDown) {
    4911             : #ifdef MOZ_ENABLE_XREMOTE
    4912             :     // shut down the x remote proxy window
    4913           0 :     if (mRemoteService) {
    4914           0 :       mRemoteService->Shutdown();
    4915             :     }
    4916             : #endif /* MOZ_ENABLE_XREMOTE */
    4917             :   }
    4918             : 
    4919           0 :   mScopedXPCOM = nullptr;
    4920             : 
    4921             : #if defined(XP_WIN)
    4922             :   mozilla::widget::StopAudioSession();
    4923             : #endif
    4924             : 
    4925             :   // unlock the profile after ScopedXPCOMStartup object (xpcom)
    4926             :   // has gone out of scope.  see bug #386739 for more details
    4927           0 :   mProfileLock->Unlock();
    4928           0 :   gProfileLock = nullptr;
    4929             : 
    4930             :   // Restart the app after XPCOM has been shut down cleanly.
    4931           0 :   if (appInitiatedRestart) {
    4932           0 :     RestoreStateForAppInitiatedRestart();
    4933             : 
    4934           0 :     if (rv != NS_SUCCESS_RESTART_APP_NOT_SAME_PROFILE) {
    4935             :       // Ensure that these environment variables are set:
    4936           0 :       SaveFileToEnvIfUnset("XRE_PROFILE_PATH", mProfD);
    4937           0 :       SaveFileToEnvIfUnset("XRE_PROFILE_LOCAL_PATH", mProfLD);
    4938           0 :       SaveWordToEnvIfUnset("XRE_PROFILE_NAME", mProfileName);
    4939             :     }
    4940             : 
    4941             : #ifdef MOZ_WIDGET_GTK
    4942           0 :     if (!gfxPlatform::IsHeadless()) {
    4943           0 :       MOZ_gdk_display_close(mGdkDisplay);
    4944             :     }
    4945             : #endif
    4946             : 
    4947             :     {
    4948           0 :       rv = LaunchChild(mNativeApp, true);
    4949             :     }
    4950             : 
    4951           0 :     if (mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER)
    4952           0 :       CrashReporter::UnsetExceptionHandler();
    4953             : 
    4954           0 :     return rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ? 0 : 1;
    4955             :   }
    4956             : 
    4957             : #ifdef MOZ_WIDGET_GTK
    4958             :   // gdk_display_close also calls gdk_display_manager_set_default_display
    4959             :   // appropriately when necessary.
    4960           0 :   if (!gfxPlatform::IsHeadless()) {
    4961           0 :     MOZ_gdk_display_close(mGdkDisplay);
    4962             :   }
    4963             : #endif
    4964             : 
    4965           0 :   if (mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER)
    4966           0 :       CrashReporter::UnsetExceptionHandler();
    4967             : 
    4968           0 :   XRE_DeinitCommandLine();
    4969             : 
    4970           0 :   return NS_FAILED(rv) ? 1 : 0;
    4971             : }
    4972             : 
    4973             : void
    4974           0 : XRE_StopLateWriteChecks(void) {
    4975           0 :   mozilla::StopLateWriteChecks();
    4976           0 : }
    4977             : 
    4978             : int
    4979           1 : XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig)
    4980             : {
    4981           1 :   XREMain main;
    4982             : 
    4983           1 :   int result = main.XRE_main(argc, argv, aConfig);
    4984           0 :   mozilla::RecordShutdownEndTimeStamp();
    4985           0 :   return result;
    4986             : }
    4987             : 
    4988             : nsresult
    4989           0 : XRE_InitCommandLine(int aArgc, char* aArgv[])
    4990             : {
    4991           1 :   nsresult rv = NS_OK;
    4992             : 
    4993             : #if defined(OS_WIN)
    4994             :   CommandLine::Init(aArgc, aArgv);
    4995             : #else
    4996             : 
    4997             :   // these leak on error, but that's OK: we'll just exit()
    4998           0 :   char** canonArgs = new char*[aArgc];
    4999             : 
    5000             :   // get the canonical version of the binary's path
    5001           0 :   nsCOMPtr<nsIFile> binFile;
    5002           0 :   rv = XRE_GetBinaryPath(getter_AddRefs(binFile));
    5003           1 :   if (NS_FAILED(rv))
    5004             :     return NS_ERROR_FAILURE;
    5005             : 
    5006           0 :   nsAutoCString canonBinPath;
    5007           0 :   rv = binFile->GetNativePath(canonBinPath);
    5008           1 :   if (NS_FAILED(rv))
    5009             :     return NS_ERROR_FAILURE;
    5010             : 
    5011           0 :   canonArgs[0] = strdup(canonBinPath.get());
    5012             : 
    5013           4 :   for (int i = 1; i < aArgc; ++i) {
    5014           0 :     if (aArgv[i]) {
    5015           0 :       canonArgs[i] = strdup(aArgv[i]);
    5016             :     }
    5017             :   }
    5018             : 
    5019           1 :   NS_ASSERTION(!CommandLine::IsInitialized(), "Bad news!");
    5020           1 :   CommandLine::Init(aArgc, canonArgs);
    5021             : 
    5022           5 :   for (int i = 0; i < aArgc; ++i)
    5023           4 :       free(canonArgs[i]);
    5024           0 :   delete[] canonArgs;
    5025             : #endif
    5026             : 
    5027           1 :   const char *path = nullptr;
    5028           1 :   ArgResult ar = CheckArg("greomni", &path);
    5029           1 :   if (ar == ARG_BAD) {
    5030           0 :     PR_fprintf(PR_STDERR, "Error: argument --greomni requires a path argument\n");
    5031           0 :     return NS_ERROR_FAILURE;
    5032             :   }
    5033             : 
    5034           1 :   if (!path)
    5035             :     return rv;
    5036             : 
    5037           0 :   nsCOMPtr<nsIFile> greOmni;
    5038           0 :   rv = XRE_GetFileFromPath(path, getter_AddRefs(greOmni));
    5039           0 :   if (NS_FAILED(rv)) {
    5040           0 :     PR_fprintf(PR_STDERR, "Error: argument --greomni requires a valid path\n");
    5041           0 :     return rv;
    5042             :   }
    5043             : 
    5044           0 :   ar = CheckArg("appomni", &path);
    5045           0 :   if (ar == ARG_BAD) {
    5046           0 :     PR_fprintf(PR_STDERR, "Error: argument --appomni requires a path argument\n");
    5047           0 :     return NS_ERROR_FAILURE;
    5048             :   }
    5049             : 
    5050           0 :   nsCOMPtr<nsIFile> appOmni;
    5051           0 :   if (path) {
    5052           0 :       rv = XRE_GetFileFromPath(path, getter_AddRefs(appOmni));
    5053           0 :       if (NS_FAILED(rv)) {
    5054           0 :         PR_fprintf(PR_STDERR, "Error: argument --appomni requires a valid path\n");
    5055           0 :         return rv;
    5056             :       }
    5057             :   }
    5058             : 
    5059           0 :   mozilla::Omnijar::Init(greOmni, appOmni);
    5060           0 :   return rv;
    5061             : }
    5062             : 
    5063             : nsresult
    5064           0 : XRE_DeinitCommandLine()
    5065             : {
    5066           0 :   nsresult rv = NS_OK;
    5067             : 
    5068           0 :   CommandLine::Terminate();
    5069             : 
    5070           0 :   return rv;
    5071             : }
    5072             : 
    5073             : GeckoProcessType
    5074        1344 : XRE_GetProcessType()
    5075             : {
    5076       25736 :   return mozilla::startup::sChildProcessType;
    5077             : }
    5078             : 
    5079             : bool
    5080           1 : XRE_IsGPUProcess()
    5081             : {
    5082           1 :   return XRE_GetProcessType() == GeckoProcessType_GPU;
    5083             : }
    5084             : 
    5085             : /**
    5086             :  * Returns true in the e10s parent process and in the main process when e10s
    5087             :  * is disabled.
    5088             :  */
    5089             : bool
    5090       20700 : XRE_IsParentProcess()
    5091             : {
    5092       20700 :   return XRE_GetProcessType() == GeckoProcessType_Default;
    5093             : }
    5094             : 
    5095             : bool
    5096           0 : XRE_IsE10sParentProcess()
    5097             : {
    5098           0 :   return XRE_IsParentProcess() && BrowserTabsRemoteAutostart();
    5099             : }
    5100             : 
    5101             : bool
    5102        3001 : XRE_IsContentProcess()
    5103             : {
    5104        3001 :   return XRE_GetProcessType() == GeckoProcessType_Content;
    5105             : }
    5106             : 
    5107             : bool
    5108           0 : XRE_IsPluginProcess()
    5109             : {
    5110           0 :   return XRE_GetProcessType() == GeckoProcessType_Plugin;
    5111             : }
    5112             : 
    5113             : bool
    5114           1 : XRE_UseNativeEventProcessing()
    5115             : {
    5116           1 :   if (XRE_IsContentProcess()) {
    5117             :     static bool sInited = false;
    5118             :     static bool sUseNativeEventProcessing = false;
    5119           0 :     if (!sInited) {
    5120             :       Preferences::AddBoolVarCache(&sUseNativeEventProcessing,
    5121           0 :                                    "dom.ipc.useNativeEventProcessing.content");
    5122           0 :       sInited = true;
    5123             :     }
    5124             : 
    5125           0 :     return sUseNativeEventProcessing;
    5126             :   }
    5127             : 
    5128             :   return true;
    5129             : }
    5130             : 
    5131             : // If you add anything to this enum, please update about:support to reflect it
    5132             : enum {
    5133             :   kE10sEnabledByUser = 0,
    5134             :   kE10sEnabledByDefault = 1,
    5135             :   kE10sDisabledByUser = 2,
    5136             :   // kE10sDisabledInSafeMode = 3, was removed in bug 1172491.
    5137             :   // kE10sDisabledForAccessibility = 4,
    5138             :   // kE10sDisabledForMacGfx = 5, was removed in bug 1068674.
    5139             :   // kE10sDisabledForBidi = 6, removed in bug 1309599
    5140             :   // kE10sDisabledForAddons = 7, removed in bug 1406212
    5141             :   kE10sForceDisabled = 8,
    5142             :   // kE10sDisabledForXPAcceleration = 9, removed in bug 1296353
    5143             :   // kE10sDisabledForOperatingSystem = 10, removed due to xp-eol
    5144             : };
    5145             : 
    5146             : const char* kForceEnableE10sPref = "browser.tabs.remote.force-enable";
    5147             : const char* kForceDisableE10sPref = "browser.tabs.remote.force-disable";
    5148             : 
    5149             : namespace mozilla {
    5150             : 
    5151             : bool
    5152           0 : BrowserTabsRemoteAutostart()
    5153             : {
    5154         189 :   if (gBrowserTabsRemoteAutostartInitialized) {
    5155           0 :     return gBrowserTabsRemoteAutostart;
    5156             :   }
    5157           1 :   gBrowserTabsRemoteAutostartInitialized = true;
    5158             : 
    5159             :   // If we're in the content process, we are running E10S.
    5160           1 :   if (XRE_IsContentProcess()) {
    5161           0 :     gBrowserTabsRemoteAutostart = true;
    5162           0 :     return gBrowserTabsRemoteAutostart;
    5163             :   }
    5164             : 
    5165           1 :   bool optInPref = Preferences::GetBool("browser.tabs.remote.autostart", true);
    5166           1 :   int status = kE10sEnabledByDefault;
    5167             : 
    5168           0 :   if (optInPref) {
    5169           0 :     gBrowserTabsRemoteAutostart = true;
    5170             :   } else {
    5171             :     status = kE10sDisabledByUser;
    5172             :   }
    5173             : 
    5174             :   // Uber override pref for manual testing purposes
    5175           0 :   if (Preferences::GetBool(kForceEnableE10sPref, false)) {
    5176           0 :     gBrowserTabsRemoteAutostart = true;
    5177           0 :     status = kE10sEnabledByUser;
    5178             :   }
    5179             : 
    5180             :   // Uber override pref for emergency blocking
    5181           3 :   if (gBrowserTabsRemoteAutostart &&
    5182           0 :       (Preferences::GetBool(kForceDisableE10sPref, false) ||
    5183           1 :        EnvHasValue("MOZ_FORCE_DISABLE_E10S"))) {
    5184           0 :     gBrowserTabsRemoteAutostart = false;
    5185           0 :     status = kE10sForceDisabled;
    5186             :   }
    5187             : 
    5188           1 :   gBrowserTabsRemoteStatus = status;
    5189             : 
    5190           1 :   mozilla::Telemetry::Accumulate(mozilla::Telemetry::E10S_STATUS, status);
    5191           0 :   return gBrowserTabsRemoteAutostart;
    5192             : }
    5193             : 
    5194             : uint32_t
    5195           4 : GetMaxWebProcessCount()
    5196             : {
    5197             :   // multiOptOut is in int to allow us to run multiple experiments without
    5198             :   // introducing multiple prefs a la the autostart.N prefs.
    5199           0 :   if (Preferences::GetInt("dom.ipc.multiOptOut", 0) >=
    5200             :           nsIXULRuntime::E10S_MULTI_EXPERIMENT) {
    5201             :     return 1;
    5202             :   }
    5203             : 
    5204           4 :   const char* optInPref = "dom.ipc.processCount";
    5205           0 :   uint32_t optInPrefValue = Preferences::GetInt(optInPref, 1);
    5206           8 :   return std::max(1u, optInPrefValue);
    5207             : }
    5208             : 
    5209             : const char*
    5210           3 : PlatformBuildID()
    5211             : {
    5212           3 :   return gToolkitBuildID;
    5213             : }
    5214             : 
    5215             : } // namespace mozilla
    5216             : 
    5217             : void
    5218           1 : SetupErrorHandling(const char* progname)
    5219             : {
    5220             : #ifdef XP_WIN
    5221             :   /* On Windows XPSP3 and Windows Vista if DEP is configured off-by-default
    5222             :      we still want DEP protection: enable it explicitly and programmatically.
    5223             : 
    5224             :      This function is not available on WinXPSP2 so we dynamically load it.
    5225             :   */
    5226             : 
    5227             :   HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll");
    5228             :   SetProcessDEPPolicyFunc _SetProcessDEPPolicy =
    5229             :     (SetProcessDEPPolicyFunc) GetProcAddress(kernel32, "SetProcessDEPPolicy");
    5230             :   if (_SetProcessDEPPolicy)
    5231             :     _SetProcessDEPPolicy(PROCESS_DEP_ENABLE);
    5232             : #endif
    5233             : 
    5234             : #ifdef XP_WIN32
    5235             :   // Suppress the "DLL Foo could not be found" dialog, such that if dependent
    5236             :   // libraries (such as GDI+) are not preset, we gracefully fail to load those
    5237             :   // XPCOM components, instead of being ungraceful.
    5238             :   UINT realMode = SetErrorMode(0);
    5239             :   realMode |= SEM_FAILCRITICALERRORS;
    5240             :   // If XRE_NO_WINDOWS_CRASH_DIALOG is set, suppress displaying the "This
    5241             :   // application has crashed" dialog box.  This is mainly useful for
    5242             :   // automated testing environments, e.g. tinderbox, where there's no need
    5243             :   // for a dozen of the dialog boxes to litter the console
    5244             :   if (getenv("XRE_NO_WINDOWS_CRASH_DIALOG"))
    5245             :     realMode |= SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX;
    5246             : 
    5247             :   SetErrorMode(realMode);
    5248             : 
    5249             : #endif
    5250             : 
    5251             : #if defined (DEBUG) && defined(XP_WIN)
    5252             :   // Send MSCRT Warnings, Errors and Assertions to stderr.
    5253             :   // See http://msdn.microsoft.com/en-us/library/1y71x448(v=VS.80).aspx
    5254             :   // and http://msdn.microsoft.com/en-us/library/a68f826y(v=VS.80).aspx.
    5255             : 
    5256             :   _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
    5257             :   _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
    5258             :   _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
    5259             :   _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
    5260             :   _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
    5261             :   _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
    5262             : 
    5263             :   _CrtSetReportHook(MSCRTReportHook);
    5264             : #endif
    5265             : 
    5266           1 :   InstallSignalHandlers(progname);
    5267             : 
    5268             :   // Unbuffer stdout, needed for tinderbox tests.
    5269           1 :   setbuf(stdout, 0);
    5270           0 : }
    5271             : 
    5272             : // Note: This function should not be needed anymore. See Bug 818634 for details.
    5273             : void
    5274           0 : OverrideDefaultLocaleIfNeeded() {
    5275             :   // Read pref to decide whether to override default locale with US English.
    5276           1 :   if (mozilla::Preferences::GetBool("javascript.use_us_english_locale", false)) {
    5277             :     // Set the application-wide C-locale. Needed to resist fingerprinting
    5278             :     // of Date.toLocaleFormat(). We use the locale to "C.UTF-8" if possible,
    5279             :     // to avoid interfering with non-ASCII keyboard input on some Linux desktops.
    5280             :     // Otherwise fall back to the "C" locale, which is available on all platforms.
    5281           0 :     setlocale(LC_ALL, "C.UTF-8") || setlocale(LC_ALL, "C");
    5282             :   }
    5283           1 : }
    5284             : 
    5285             : void
    5286             : XRE_EnableSameExecutableForContentProc() {
    5287             :   if (!PR_GetEnv("MOZ_SEPARATE_CHILD_PROCESS")) {
    5288             :     mozilla::ipc::GeckoChildProcessHost::EnableSameExecutableForContentProc();
    5289             :   }
    5290             : }
    5291             : 
    5292             : // Because rust doesn't handle weak symbols, this function wraps the weak
    5293             : // malloc_handle_oom for it.
    5294             : extern "C" void
    5295             : GeckoHandleOOM(size_t size) {
    5296             :   mozalloc_handle_oom(size);
    5297             : }

Generated by: LCOV version 1.13-14-ga5dd952