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

Generated by: LCOV version 1.13