toolkit/xre/nsAppRunner.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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/. */
     6 #if defined(MOZ_WIDGET_QT)
     7 #include <QGuiApplication>
     8 #include <QStringList>
     9 #include "nsQAppInstance.h"
    10 #endif // MOZ_WIDGET_QT
    12 #include "mozilla/dom/ContentParent.h"
    13 #include "mozilla/dom/ContentChild.h"
    15 #include "mozilla/ArrayUtils.h"
    16 #include "mozilla/Attributes.h"
    17 #include "mozilla/IOInterposer.h"
    18 #include "mozilla/Likely.h"
    19 #include "mozilla/Poison.h"
    20 #include "mozilla/Preferences.h"
    21 #include "mozilla/Telemetry.h"
    23 #include "nsAppRunner.h"
    24 #include "mozilla/AppData.h"
    25 #include "nsUpdateDriver.h"
    26 #include "ProfileReset.h"
    28 #ifdef MOZ_INSTRUMENT_EVENT_LOOP
    29 #include "EventTracer.h"
    30 #endif
    32 #ifdef XP_MACOSX
    33 #include "nsVersionComparator.h"
    34 #include "MacLaunchHelper.h"
    35 #include "MacApplicationDelegate.h"
    36 #include "MacAutoreleasePool.h"
    37 // these are needed for sysctl
    38 #include <sys/types.h>
    39 #include <sys/sysctl.h>
    40 #endif
    42 #include "prmem.h"
    43 #include "prnetdb.h"
    44 #include "prprf.h"
    45 #include "prproces.h"
    46 #include "prenv.h"
    48 #include "nsIAppShellService.h"
    49 #include "nsIAppStartup.h"
    50 #include "nsIAppStartupNotifier.h"
    51 #include "nsIMutableArray.h"
    52 #include "nsICategoryManager.h"
    53 #include "nsIChromeRegistry.h"
    54 #include "nsICommandLineRunner.h"
    55 #include "nsIComponentManager.h"
    56 #include "nsIComponentRegistrar.h"
    57 #include "nsIContentHandler.h"
    58 #include "nsIDialogParamBlock.h"
    59 #include "nsIDOMWindow.h"
    60 #include "mozilla/ModuleUtils.h"
    61 #include "nsIIOService2.h"
    62 #include "nsIObserverService.h"
    63 #include "nsINativeAppSupport.h"
    64 #include "nsIProcess.h"
    65 #include "nsIProfileUnlocker.h"
    66 #include "nsIPromptService.h"
    67 #include "nsIServiceManager.h"
    68 #include "nsIStringBundle.h"
    69 #include "nsISupportsPrimitives.h"
    70 #include "nsIToolkitChromeRegistry.h"
    71 #include "nsIToolkitProfile.h"
    72 #include "nsIToolkitProfileService.h"
    73 #include "nsIURI.h"
    74 #include "nsIWindowCreator.h"
    75 #include "nsIWindowMediator.h"
    76 #include "nsIWindowWatcher.h"
    77 #include "nsIXULAppInfo.h"
    78 #include "nsIXULRuntime.h"
    79 #include "nsPIDOMWindow.h"
    80 #include "nsIBaseWindow.h"
    81 #include "nsIWidget.h"
    82 #include "nsIDocShell.h"
    83 #include "nsAppShellCID.h"
    84 #include "mozilla/scache/StartupCache.h"
    86 #include "mozilla/unused.h"
    88 #ifdef XP_WIN
    89 #include "nsIWinAppHelper.h"
    90 #include <windows.h>
    91 #include "cairo/cairo-features.h"
    92 #include "mozilla/WindowsVersion.h"
    93 #ifdef MOZ_METRO
    94 #include <roapi.h>
    95 #endif
    97 #ifndef PROCESS_DEP_ENABLE
    98 #define PROCESS_DEP_ENABLE 0x1
    99 #endif
   100 #endif
   102 #include "nsCRT.h"
   103 #include "nsCOMPtr.h"
   104 #include "nsDirectoryServiceDefs.h"
   105 #include "nsDirectoryServiceUtils.h"
   106 #include "nsEmbedCID.h"
   107 #include "nsNetUtil.h"
   108 #include "nsReadableUtils.h"
   109 #include "nsXPCOM.h"
   110 #include "nsXPCOMCIDInternal.h"
   111 #include "nsXPIDLString.h"
   112 #include "nsPrintfCString.h"
   113 #include "nsVersionComparator.h"
   115 #include "nsAppDirectoryServiceDefs.h"
   116 #include "nsXULAppAPI.h"
   117 #include "nsXREDirProvider.h"
   118 #include "nsToolkitCompsCID.h"
   120 #if defined(XP_WIN) && defined(MOZ_METRO)
   121 #include "updatehelper.h"
   122 #endif
   124 #include "nsINIParser.h"
   125 #include "mozilla/Omnijar.h"
   126 #include "mozilla/StartupTimeline.h"
   127 #include "mozilla/LateWriteChecks.h"
   129 #include <stdlib.h>
   131 #ifdef XP_UNIX
   132 #include <sys/stat.h>
   133 #include <unistd.h>
   134 #include <pwd.h>
   135 #endif
   137 #ifdef XP_WIN
   138 #include <process.h>
   139 #include <shlobj.h>
   140 #include "nsThreadUtils.h"
   141 #include <comdef.h>
   142 #include <wbemidl.h>
   143 #endif
   145 #ifdef XP_MACOSX
   146 #include "nsILocalFileMac.h"
   147 #include "nsCommandLineServiceMac.h"
   148 #endif
   150 // for X remote support
   151 #ifdef MOZ_ENABLE_XREMOTE
   152 #include "XRemoteClient.h"
   153 #include "nsIRemoteService.h"
   154 #endif
   156 #ifdef NS_TRACE_MALLOC
   157 #include "nsTraceMalloc.h"
   158 #endif
   160 #if defined(DEBUG) && defined(XP_WIN32)
   161 #include <malloc.h>
   162 #endif
   164 #if defined (XP_MACOSX)
   165 #include <Carbon/Carbon.h>
   166 #endif
   168 #ifdef DEBUG
   169 #include "prlog.h"
   170 #endif
   172 #ifdef MOZ_JPROF
   173 #include "jprof.h"
   174 #endif
   176 #ifdef MOZ_CRASHREPORTER
   177 #include "nsExceptionHandler.h"
   178 #include "nsICrashReporter.h"
   179 #define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1"
   180 #include "nsIPrefService.h"
   181 #endif
   183 #include "base/command_line.h"
   184 #ifdef MOZ_ENABLE_TESTS
   185 #include "GTestRunner.h"
   186 #endif
   188 #ifdef MOZ_WIDGET_ANDROID
   189 #include "AndroidBridge.h"
   190 #endif
   192 extern uint32_t gRestartMode;
   193 extern void InstallSignalHandlers(const char *ProgramName);
   194 #include "nsX11ErrorHandler.h"
   196 #define FILE_COMPATIBILITY_INFO NS_LITERAL_CSTRING("compatibility.ini")
   197 #define FILE_INVALIDATE_CACHES NS_LITERAL_CSTRING(".purgecaches")
   199 int    gArgc;
   200 char **gArgv;
   202 static const char gToolkitVersion[] = NS_STRINGIFY(GRE_MILESTONE);
   203 static const char gToolkitBuildID[] = NS_STRINGIFY(GRE_BUILDID);
   205 static nsIProfileLock* gProfileLock;
   207 int    gRestartArgc;
   208 char **gRestartArgv;
   210 #ifdef MOZ_WIDGET_QT
   211 static int    gQtOnlyArgc;
   212 static char **gQtOnlyArgv;
   213 #endif
   215 #if defined(MOZ_WIDGET_GTK)
   216 #if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING) \
   217   || defined(NS_TRACE_MALLOC)
   218 #define CLEANUP_MEMORY 1
   219 #define PANGO_ENABLE_BACKEND
   220 #include <pango/pangofc-fontmap.h>
   221 #endif
   222 #include <gtk/gtk.h>
   223 #ifdef MOZ_X11
   224 #include <gdk/gdkx.h>
   225 #endif /* MOZ_X11 */
   226 #include "nsGTKToolkit.h"
   227 #include <fontconfig/fontconfig.h>
   228 #endif
   229 #include "BinaryPath.h"
   231 #ifdef MOZ_LINKER
   232 extern "C" MFBT_API bool IsSignalHandlingBroken();
   233 #endif
   235 namespace mozilla {
   236 int (*RunGTest)() = 0;
   237 }
   239 using namespace mozilla;
   240 using mozilla::unused;
   241 using mozilla::scache::StartupCache;
   242 using mozilla::dom::ContentParent;
   243 using mozilla::dom::ContentChild;
   245 // Save literal putenv string to environment variable.
   246 static void
   247 SaveToEnv(const char *putenv)
   248 {
   249   char *expr = strdup(putenv);
   250   if (expr)
   251     PR_SetEnv(expr);
   252   // We intentionally leak |expr| here since it is required by PR_SetEnv.
   253 }
   255 // Tests that an environment variable exists and has a value
   256 static bool
   257 EnvHasValue(const char *name)
   258 {
   259   const char *val = PR_GetEnv(name);
   260   return (val && *val);
   261 }
   263 // Save the given word to the specified environment variable.
   264 static void
   265 SaveWordToEnv(const char *name, const nsACString & word)
   266 {
   267   char *expr = PR_smprintf("%s=%s", name, PromiseFlatCString(word).get());
   268   if (expr)
   269     PR_SetEnv(expr);
   270   // We intentionally leak |expr| here since it is required by PR_SetEnv.
   271 }
   273 // Save the path of the given file to the specified environment variable.
   274 static void
   275 SaveFileToEnv(const char *name, nsIFile *file)
   276 {
   277 #ifdef XP_WIN
   278   nsAutoString path;
   279   file->GetPath(path);
   280   SetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name).get(), path.get());
   281 #else
   282   nsAutoCString path;
   283   file->GetNativePath(path);
   284   SaveWordToEnv(name, path);
   285 #endif
   286 }
   288 // Load the path of a file saved with SaveFileToEnv
   289 static already_AddRefed<nsIFile>
   290 GetFileFromEnv(const char *name)
   291 {
   292   nsresult rv;
   293   nsCOMPtr<nsIFile> file;
   295 #ifdef XP_WIN
   296   WCHAR path[_MAX_PATH];
   297   if (!GetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name).get(),
   298                                path, _MAX_PATH))
   299     return nullptr;
   301   rv = NS_NewLocalFile(nsDependentString(path), true, getter_AddRefs(file));
   302   if (NS_FAILED(rv))
   303     return nullptr;
   305   return file.forget();
   306 #else
   307   const char *arg = PR_GetEnv(name);
   308   if (!arg || !*arg)
   309     return nullptr;
   311   rv = NS_NewNativeLocalFile(nsDependentCString(arg), true,
   312                              getter_AddRefs(file));
   313   if (NS_FAILED(rv))
   314     return nullptr;
   316   return file.forget();
   317 #endif
   318 }
   320 // Save the path of the given word to the specified environment variable
   321 // provided the environment variable does not have a value.
   322 static void
   323 SaveWordToEnvIfUnset(const char *name, const nsACString & word)
   324 {
   325   if (!EnvHasValue(name))
   326     SaveWordToEnv(name, word);
   327 }
   329 // Save the path of the given file to the specified environment variable
   330 // provided the environment variable does not have a value.
   331 static void
   332 SaveFileToEnvIfUnset(const char *name, nsIFile *file)
   333 {
   334   if (!EnvHasValue(name))
   335     SaveFileToEnv(name, file);
   336 }
   338 static bool
   339 strimatch(const char* lowerstr, const char* mixedstr)
   340 {
   341   while(*lowerstr) {
   342     if (!*mixedstr) return false; // mixedstr is shorter
   343     if (tolower(*mixedstr) != *lowerstr) return false; // no match
   345     ++lowerstr;
   346     ++mixedstr;
   347   }
   349   if (*mixedstr) return false; // lowerstr is shorter
   351   return true;
   352 }
   354 /**
   355  * Output a string to the user.  This method is really only meant to be used to
   356  * output last-ditch error messages designed for developers NOT END USERS.
   357  *
   358  * @param isError
   359  *        Pass true to indicate severe errors.
   360  * @param fmt
   361  *        printf-style format string followed by arguments.
   362  */
   363 static void Output(bool isError, const char *fmt, ... )
   364 {
   365   va_list ap;
   366   va_start(ap, fmt);
   368 #if defined(XP_WIN) && !MOZ_WINCONSOLE
   369   char *msg = PR_vsmprintf(fmt, ap);
   370   if (msg)
   371   {
   372     UINT flags = MB_OK;
   373     if (isError)
   374       flags |= MB_ICONERROR;
   375     else 
   376       flags |= MB_ICONINFORMATION;
   378     wchar_t wide_msg[1024];
   379     MultiByteToWideChar(CP_ACP,
   380                         0,
   381                         msg,
   382                         -1,
   383                         wide_msg,
   384                         sizeof(wide_msg) / sizeof(wchar_t));
   386     MessageBoxW(nullptr, wide_msg, L"XULRunner", flags);
   387     PR_smprintf_free(msg);
   388   }
   389 #else
   390   vfprintf(stderr, fmt, ap);
   391 #endif
   393   va_end(ap);
   394 }
   396 enum RemoteResult {
   397   REMOTE_NOT_FOUND  = 0,
   398   REMOTE_FOUND      = 1,
   399   REMOTE_ARG_BAD    = 2
   400 };
   402 enum ArgResult {
   403   ARG_NONE  = 0,
   404   ARG_FOUND = 1,
   405   ARG_BAD   = 2 // you wanted a param, but there isn't one
   406 };
   408 static void RemoveArg(char **argv)
   409 {
   410   do {
   411     *argv = *(argv + 1);
   412     ++argv;
   413   } while (*argv);
   415   --gArgc;
   416 }
   418 /**
   419  * Check for a commandline flag. If the flag takes a parameter, the
   420  * parameter is returned in aParam. Flags may be in the form -arg or
   421  * --arg (or /arg on win32).
   422  *
   423  * @param aArg the parameter to check. Must be lowercase.
   424  * @param aCheckOSInt if true returns ARG_BAD if the osint argument is present
   425  *        when aArg is also present.
   426  * @param aParam if non-null, the -arg <data> will be stored in this pointer.
   427  *        This is *not* allocated, but rather a pointer to the argv data.
   428  * @param aRemArg if true, the argument is removed from the gArgv array.
   429  */
   430 static ArgResult
   431 CheckArg(const char* aArg, bool aCheckOSInt = false, const char **aParam = nullptr, bool aRemArg = true)
   432 {
   433   NS_ABORT_IF_FALSE(gArgv, "gArgv must be initialized before CheckArg()");
   435   char **curarg = gArgv + 1; // skip argv[0]
   436   ArgResult ar = ARG_NONE;
   438   while (*curarg) {
   439     char *arg = curarg[0];
   441     if (arg[0] == '-'
   442 #if defined(XP_WIN)
   443         || *arg == '/'
   444 #endif
   445         ) {
   446       ++arg;
   447       if (*arg == '-')
   448         ++arg;
   450       if (strimatch(aArg, arg)) {
   451         if (aRemArg)
   452           RemoveArg(curarg);
   453         if (!aParam) {
   454           ar = ARG_FOUND;
   455           break;
   456         }
   458         if (*curarg) {
   459           if (**curarg == '-'
   460 #if defined(XP_WIN)
   461               || **curarg == '/'
   462 #endif
   463               )
   464             return ARG_BAD;
   466           *aParam = *curarg;
   467           if (aRemArg)
   468             RemoveArg(curarg);
   469           ar = ARG_FOUND;
   470           break;
   471         }
   472         return ARG_BAD;
   473       }
   474     }
   476     ++curarg;
   477   }
   479   if (aCheckOSInt && ar == ARG_FOUND) {
   480     ArgResult arOSInt = CheckArg("osint");
   481     if (arOSInt == ARG_FOUND) {
   482       ar = ARG_BAD;
   483       PR_fprintf(PR_STDERR, "Error: argument -osint is invalid\n");
   484     }
   485   }
   487   return ar;
   488 }
   490 #if defined(XP_WIN)
   491 /**
   492  * Check for a commandline flag from the windows shell and remove it from the
   493  * argv used when restarting. Flags MUST be in the form -arg.
   494  *
   495  * @param aArg the parameter to check. Must be lowercase.
   496  */
   497 static ArgResult
   498 CheckArgShell(const char* aArg)
   499 {
   500   char **curarg = gRestartArgv + 1; // skip argv[0]
   502   while (*curarg) {
   503     char *arg = curarg[0];
   505     if (arg[0] == '-') {
   506       ++arg;
   508       if (strimatch(aArg, arg)) {
   509         do {
   510           *curarg = *(curarg + 1);
   511           ++curarg;
   512         } while (*curarg);
   514         --gRestartArgc;
   516         return ARG_FOUND;
   517       }
   518     }
   520     ++curarg;
   521   }
   523   return ARG_NONE;
   524 }
   526 /**
   527  * Enabled Native App Support to process DDE messages when the app needs to
   528  * restart and the app has been launched by the Windows shell to open an url.
   529  * When aWait is false this will process the DDE events manually. This prevents
   530  * Windows from displaying an error message due to the DDE message not being
   531  * acknowledged.
   532  */
   533 static void
   534 ProcessDDE(nsINativeAppSupport* aNative, bool aWait)
   535 {
   536   // When the app is launched by the windows shell the windows shell
   537   // expects the app to be available for DDE messages and if it isn't
   538   // windows displays an error dialog. To prevent the error the DDE server
   539   // is enabled and pending events are processed when the app needs to
   540   // restart after it was launched by the shell with the requestpending
   541   // argument. The requestpending pending argument is removed to
   542   // differentiate it from being launched when an app restart is not
   543   // required.
   544   ArgResult ar;
   545   ar = CheckArgShell("requestpending");
   546   if (ar == ARG_FOUND) {
   547     aNative->Enable(); // enable win32 DDE responses
   548     if (aWait) {
   549       nsIThread *thread = NS_GetCurrentThread();
   550       // This is just a guesstimate based on testing different values.
   551       // If count is 8 or less windows will display an error dialog.
   552       int32_t count = 20;
   553       while(--count >= 0) {
   554         NS_ProcessNextEvent(thread);
   555         PR_Sleep(PR_MillisecondsToInterval(1));
   556       }
   557     }
   558   }
   559 }
   560 #endif
   562 /**
   563  * Determines if there is support for showing the profile manager
   564  *
   565  * @return true in all environments except for Windows Metro
   566 */
   567 static bool
   568 CanShowProfileManager()
   569 {
   570 #if defined(XP_WIN)
   571   return XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop;
   572 #else
   573   return true;
   574 #endif
   575 }
   578 bool gSafeMode = false;
   580 /**
   581  * The nsXULAppInfo object implements nsIFactory so that it can be its own
   582  * singleton.
   583  */
   584 class nsXULAppInfo : public nsIXULAppInfo,
   585 #ifdef XP_WIN
   586                      public nsIWinAppHelper,
   587 #endif
   588 #ifdef MOZ_CRASHREPORTER
   589                      public nsICrashReporter,
   590 #endif
   591                      public nsIXULRuntime
   593 {
   594 public:
   595   MOZ_CONSTEXPR nsXULAppInfo() {}
   596   NS_DECL_ISUPPORTS_INHERITED
   597   NS_DECL_NSIXULAPPINFO
   598   NS_DECL_NSIXULRUNTIME
   599 #ifdef MOZ_CRASHREPORTER
   600   NS_DECL_NSICRASHREPORTER
   601 #endif
   602 #ifdef XP_WIN
   603   NS_DECL_NSIWINAPPHELPER
   604 #endif
   605 };
   607 NS_INTERFACE_MAP_BEGIN(nsXULAppInfo)
   608   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULRuntime)
   609   NS_INTERFACE_MAP_ENTRY(nsIXULRuntime)
   610 #ifdef XP_WIN
   611   NS_INTERFACE_MAP_ENTRY(nsIWinAppHelper)
   612 #endif
   613 #ifdef MOZ_CRASHREPORTER
   614   NS_INTERFACE_MAP_ENTRY(nsICrashReporter)
   615 #endif
   616   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIXULAppInfo, gAppData || 
   617                                      XRE_GetProcessType() == GeckoProcessType_Content)
   618 NS_INTERFACE_MAP_END
   620 NS_IMETHODIMP_(MozExternalRefCountType)
   621 nsXULAppInfo::AddRef()
   622 {
   623   return 1;
   624 }
   626 NS_IMETHODIMP_(MozExternalRefCountType)
   627 nsXULAppInfo::Release()
   628 {
   629   return 1;
   630 }
   632 NS_IMETHODIMP
   633 nsXULAppInfo::GetVendor(nsACString& aResult)
   634 {
   635   if (XRE_GetProcessType() == GeckoProcessType_Content) {
   636     return NS_ERROR_NOT_AVAILABLE;
   637   }
   638   aResult.Assign(gAppData->vendor);
   640   return NS_OK;
   641 }
   643 NS_IMETHODIMP
   644 nsXULAppInfo::GetName(nsACString& aResult)
   645 {
   646   if (XRE_GetProcessType() == GeckoProcessType_Content) {
   647     ContentChild* cc = ContentChild::GetSingleton();
   648     aResult = cc->GetAppInfo().name;
   649     return NS_OK;
   650   }
   651   aResult.Assign(gAppData->name);
   653   return NS_OK;
   654 }
   656 NS_IMETHODIMP
   657 nsXULAppInfo::GetID(nsACString& aResult)
   658 {
   659   if (XRE_GetProcessType() == GeckoProcessType_Content) {
   660     return NS_ERROR_NOT_AVAILABLE;
   661   }
   662   aResult.Assign(gAppData->ID);
   664   return NS_OK;
   665 }
   667 NS_IMETHODIMP
   668 nsXULAppInfo::GetVersion(nsACString& aResult)
   669 {
   670   if (XRE_GetProcessType() == GeckoProcessType_Content) {
   671     ContentChild* cc = ContentChild::GetSingleton();
   672     aResult = cc->GetAppInfo().version;
   673     return NS_OK;
   674   }
   675   aResult.Assign(gAppData->version);
   677   return NS_OK;
   678 }
   680 NS_IMETHODIMP
   681 nsXULAppInfo::GetPlatformVersion(nsACString& aResult)
   682 {
   683   aResult.Assign(gToolkitVersion);
   685   return NS_OK;
   686 }
   688 NS_IMETHODIMP
   689 nsXULAppInfo::GetAppBuildID(nsACString& aResult)
   690 {
   691   if (XRE_GetProcessType() == GeckoProcessType_Content) {
   692     ContentChild* cc = ContentChild::GetSingleton();
   693     aResult = cc->GetAppInfo().buildID;
   694     return NS_OK;
   695   }
   696   aResult.Assign(gAppData->buildID);
   698   return NS_OK;
   699 }
   701 NS_IMETHODIMP
   702 nsXULAppInfo::GetPlatformBuildID(nsACString& aResult)
   703 {
   704   aResult.Assign(gToolkitBuildID);
   706   return NS_OK;
   707 }
   709 NS_IMETHODIMP
   710 nsXULAppInfo::GetUAName(nsACString& aResult)
   711 {
   712   if (XRE_GetProcessType() == GeckoProcessType_Content) {
   713     ContentChild* cc = ContentChild::GetSingleton();
   714     aResult = cc->GetAppInfo().UAName;
   715     return NS_OK;
   716   }
   717   aResult.Assign(gAppData->UAName);
   719   return NS_OK;
   720 }
   722 NS_IMETHODIMP
   723 nsXULAppInfo::GetLogConsoleErrors(bool *aResult)
   724 {
   725   *aResult = gLogConsoleErrors;
   726   return NS_OK;
   727 }
   729 NS_IMETHODIMP
   730 nsXULAppInfo::SetLogConsoleErrors(bool aValue)
   731 {
   732   gLogConsoleErrors = aValue;
   733   return NS_OK;
   734 }
   736 NS_IMETHODIMP
   737 nsXULAppInfo::GetInSafeMode(bool *aResult)
   738 {
   739   *aResult = gSafeMode;
   740   return NS_OK;
   741 }
   743 NS_IMETHODIMP
   744 nsXULAppInfo::GetOS(nsACString& aResult)
   745 {
   746   aResult.AssignLiteral(OS_TARGET);
   747   return NS_OK;
   748 }
   750 NS_IMETHODIMP
   751 nsXULAppInfo::GetXPCOMABI(nsACString& aResult)
   752 {
   753 #ifdef TARGET_XPCOM_ABI
   754   aResult.AssignLiteral(TARGET_XPCOM_ABI);
   755   return NS_OK;
   756 #else
   757   return NS_ERROR_NOT_AVAILABLE;
   758 #endif
   759 }
   761 NS_IMETHODIMP
   762 nsXULAppInfo::GetWidgetToolkit(nsACString& aResult)
   763 {
   764   aResult.AssignLiteral(MOZ_WIDGET_TOOLKIT);
   765   return NS_OK;
   766 }
   768 // Ensure that the GeckoProcessType enum, defined in xpcom/build/nsXULAppAPI.h,
   769 // is synchronized with the const unsigned longs defined in
   770 // xpcom/system/nsIXULRuntime.idl.
   771 #define SYNC_ENUMS(a,b) \
   772   static_assert(nsIXULRuntime::PROCESS_TYPE_ ## a == \
   773                 static_cast<int>(GeckoProcessType_ ## b), \
   774                 "GeckoProcessType in nsXULAppAPI.h not synchronized with nsIXULRuntime.idl");
   776 SYNC_ENUMS(DEFAULT, Default)
   777 SYNC_ENUMS(PLUGIN, Plugin)
   778 SYNC_ENUMS(CONTENT, Content)
   779 SYNC_ENUMS(IPDLUNITTEST, IPDLUnitTest)
   781 // .. and ensure that that is all of them:
   782 static_assert(GeckoProcessType_IPDLUnitTest + 1 == GeckoProcessType_End,
   783               "Did not find the final GeckoProcessType");
   785 NS_IMETHODIMP
   786 nsXULAppInfo::GetProcessType(uint32_t* aResult)
   787 {
   788   NS_ENSURE_ARG_POINTER(aResult);
   789   *aResult = XRE_GetProcessType();
   790   return NS_OK;
   791 }
   793 NS_IMETHODIMP
   794 nsXULAppInfo::GetProcessID(uint32_t* aResult)
   795 {
   796 #ifdef XP_WIN
   797   *aResult = GetCurrentProcessId();
   798 #else
   799   *aResult = getpid();
   800 #endif
   801   return NS_OK;
   802 }
   804 static bool gBrowserTabsRemote = false;
   805 static bool gBrowserTabsRemoteInitialized = false;
   807 NS_IMETHODIMP
   808 nsXULAppInfo::GetBrowserTabsRemote(bool* aResult)
   809 {
   810   *aResult = BrowserTabsRemote();
   811   return NS_OK;
   812 }
   814 NS_IMETHODIMP
   815 nsXULAppInfo::EnsureContentProcess()
   816 {
   817   if (XRE_GetProcessType() != GeckoProcessType_Default)
   818     return NS_ERROR_NOT_AVAILABLE;
   820   nsRefPtr<ContentParent> unused = ContentParent::GetNewOrUsed();
   821   return NS_OK;
   822 }
   824 NS_IMETHODIMP
   825 nsXULAppInfo::InvalidateCachesOnRestart()
   826 {
   827   nsCOMPtr<nsIFile> file;
   828   nsresult rv = NS_GetSpecialDirectory(NS_APP_PROFILE_DIR_STARTUP, 
   829                                        getter_AddRefs(file));
   830   if (NS_FAILED(rv))
   831     return rv;
   832   if (!file)
   833     return NS_ERROR_NOT_AVAILABLE;
   835   file->AppendNative(FILE_COMPATIBILITY_INFO);
   837   nsINIParser parser;
   838   rv = parser.Init(file);
   839   if (NS_FAILED(rv)) {
   840     // This fails if compatibility.ini is not there, so we'll
   841     // flush the caches on the next restart anyways.
   842     return NS_OK;
   843   }
   845   nsAutoCString buf;
   846   rv = parser.GetString("Compatibility", "InvalidateCaches", buf);
   848   if (NS_FAILED(rv)) {
   849     PRFileDesc *fd = nullptr;
   850     file->OpenNSPRFileDesc(PR_RDWR | PR_APPEND, 0600, &fd);
   851     if (!fd) {
   852       NS_ERROR("could not create output stream");
   853       return NS_ERROR_NOT_AVAILABLE;
   854     }
   855     static const char kInvalidationHeader[] = NS_LINEBREAK "InvalidateCaches=1" NS_LINEBREAK;
   856     PR_Write(fd, kInvalidationHeader, sizeof(kInvalidationHeader) - 1);
   857     PR_Close(fd);
   858   }
   859   return NS_OK;
   860 }
   862 NS_IMETHODIMP
   863 nsXULAppInfo::GetReplacedLockTime(PRTime *aReplacedLockTime)
   864 {
   865   if (!gProfileLock)
   866     return NS_ERROR_NOT_AVAILABLE;
   867   gProfileLock->GetReplacedLockTime(aReplacedLockTime);
   868   return NS_OK;
   869 }
   871 NS_IMETHODIMP
   872 nsXULAppInfo::GetLastRunCrashID(nsAString &aLastRunCrashID)
   873 {
   874 #ifdef MOZ_CRASHREPORTER
   875   CrashReporter::GetLastRunCrashID(aLastRunCrashID);
   876   return NS_OK;
   877 #else
   878   return NS_ERROR_NOT_IMPLEMENTED;
   879 #endif
   880 }
   882 NS_IMETHODIMP
   883 nsXULAppInfo::GetIsReleaseBuild(bool* aResult)
   884 {
   885 #ifdef RELEASE_BUILD
   886   *aResult = true;
   887 #else
   888   *aResult = false;
   889 #endif
   890   return NS_OK;
   891 }
   893 NS_IMETHODIMP
   894 nsXULAppInfo::GetIsOfficialBranding(bool* aResult)
   895 {
   896 #ifdef MOZ_OFFICIAL_BRANDING
   897   *aResult = true;
   898 #else
   899   *aResult = false;
   900 #endif
   901   return NS_OK;
   902 }
   904 NS_IMETHODIMP
   905 nsXULAppInfo::GetDefaultUpdateChannel(nsACString& aResult)
   906 {
   907   aResult.AssignLiteral(NS_STRINGIFY(MOZ_UPDATE_CHANNEL));
   908   return NS_OK;
   909 }
   911 NS_IMETHODIMP
   912 nsXULAppInfo::GetDistributionID(nsACString& aResult)
   913 {
   914   aResult.AssignLiteral(MOZ_DISTRIBUTION_ID);
   915   return NS_OK;
   916 }
   918 #ifdef XP_WIN
   919 // Matches the enum in WinNT.h for the Vista SDK but renamed so that we can
   920 // safely build with the Vista SDK and without it.
   921 typedef enum 
   922 {
   923   VistaTokenElevationTypeDefault = 1,
   924   VistaTokenElevationTypeFull,
   925   VistaTokenElevationTypeLimited
   926 } VISTA_TOKEN_ELEVATION_TYPE;
   928 // avoid collision with TokeElevationType enum in WinNT.h
   929 // of the Vista SDK
   930 #define VistaTokenElevationType static_cast< TOKEN_INFORMATION_CLASS >( 18 )
   932 NS_IMETHODIMP
   933 nsXULAppInfo::GetUserCanElevate(bool *aUserCanElevate)
   934 {
   935   HANDLE hToken;
   937   VISTA_TOKEN_ELEVATION_TYPE elevationType;
   938   DWORD dwSize; 
   940   if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken) ||
   941       !GetTokenInformation(hToken, VistaTokenElevationType, &elevationType,
   942                            sizeof(elevationType), &dwSize)) {
   943     *aUserCanElevate = false;
   944   } 
   945   else {
   946     // The possible values returned for elevationType and their meanings are:
   947     //   TokenElevationTypeDefault: The token does not have a linked token 
   948     //     (e.g. UAC disabled or a standard user, so they can't be elevated)
   949     //   TokenElevationTypeFull: The token is linked to an elevated token 
   950     //     (e.g. UAC is enabled and the user is already elevated so they can't
   951     //      be elevated again)
   952     //   TokenElevationTypeLimited: The token is linked to a limited token 
   953     //     (e.g. UAC is enabled and the user is not elevated, so they can be
   954     //      elevated)
   955     *aUserCanElevate = (elevationType == VistaTokenElevationTypeLimited);
   956   }
   958   if (hToken)
   959     CloseHandle(hToken);
   961   return NS_OK;
   962 }
   963 #endif
   965 #ifdef MOZ_CRASHREPORTER
   966 NS_IMETHODIMP
   967 nsXULAppInfo::GetEnabled(bool *aEnabled)
   968 {
   969   *aEnabled = CrashReporter::GetEnabled();
   970   return NS_OK;
   971 }
   973 NS_IMETHODIMP
   974 nsXULAppInfo::SetEnabled(bool aEnabled)
   975 {
   976   if (aEnabled) {
   977     if (CrashReporter::GetEnabled())
   978       // no point in erroring for double-enabling
   979       return NS_OK;
   981     nsCOMPtr<nsIFile> xreDirectory;
   982     if (gAppData) {
   983       xreDirectory = gAppData->xreDirectory;
   984     }
   985     else {
   986       // We didn't get started through XRE_Main, probably
   987       nsCOMPtr<nsIFile> greDir;
   988       NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(greDir));
   989       if (!greDir)
   990         return NS_ERROR_FAILURE;
   992       xreDirectory = do_QueryInterface(greDir);
   993       if (!xreDirectory)
   994         return NS_ERROR_FAILURE;
   995     }
   996     return CrashReporter::SetExceptionHandler(xreDirectory, true);
   997   }
   998   else {
   999     if (!CrashReporter::GetEnabled())
  1000       // no point in erroring for double-disabling
  1001       return NS_OK;
  1003     return CrashReporter::UnsetExceptionHandler();
  1007 NS_IMETHODIMP
  1008 nsXULAppInfo::GetServerURL(nsIURL** aServerURL)
  1010   if (!CrashReporter::GetEnabled())
  1011     return NS_ERROR_NOT_INITIALIZED;
  1013   nsAutoCString data;
  1014   if (!CrashReporter::GetServerURL(data)) {
  1015     return NS_ERROR_FAILURE;
  1017   nsCOMPtr<nsIURI> uri;
  1018   NS_NewURI(getter_AddRefs(uri), data);
  1019   if (!uri)
  1020     return NS_ERROR_FAILURE;
  1022   nsCOMPtr<nsIURL> url;
  1023   url = do_QueryInterface(uri);
  1024   NS_ADDREF(*aServerURL = url);
  1026   return NS_OK;
  1029 NS_IMETHODIMP
  1030 nsXULAppInfo::SetServerURL(nsIURL* aServerURL)
  1032   bool schemeOk;
  1033   // only allow https or http URLs
  1034   nsresult rv = aServerURL->SchemeIs("https", &schemeOk);
  1035   NS_ENSURE_SUCCESS(rv, rv);
  1036   if (!schemeOk) {
  1037     rv = aServerURL->SchemeIs("http", &schemeOk);
  1038     NS_ENSURE_SUCCESS(rv, rv);
  1040     if (!schemeOk)
  1041       return NS_ERROR_INVALID_ARG;
  1043   nsAutoCString spec;
  1044   rv = aServerURL->GetSpec(spec);
  1045   NS_ENSURE_SUCCESS(rv, rv);
  1047   return CrashReporter::SetServerURL(spec);
  1050 NS_IMETHODIMP
  1051 nsXULAppInfo::GetMinidumpPath(nsIFile** aMinidumpPath)
  1053   if (!CrashReporter::GetEnabled())
  1054     return NS_ERROR_NOT_INITIALIZED;
  1056   nsAutoString path;
  1057   if (!CrashReporter::GetMinidumpPath(path))
  1058     return NS_ERROR_FAILURE;
  1060   nsresult rv = NS_NewLocalFile(path, false, aMinidumpPath);
  1061   NS_ENSURE_SUCCESS(rv, rv);
  1062   return NS_OK;
  1065 NS_IMETHODIMP
  1066 nsXULAppInfo::SetMinidumpPath(nsIFile* aMinidumpPath)
  1068   nsAutoString path;
  1069   nsresult rv = aMinidumpPath->GetPath(path);
  1070   NS_ENSURE_SUCCESS(rv, rv);
  1071   return CrashReporter::SetMinidumpPath(path);
  1074 NS_IMETHODIMP
  1075 nsXULAppInfo::AnnotateCrashReport(const nsACString& key,
  1076                                   const nsACString& data)
  1078   return CrashReporter::AnnotateCrashReport(key, data);
  1081 NS_IMETHODIMP
  1082 nsXULAppInfo::AppendAppNotesToCrashReport(const nsACString& data)
  1084   return CrashReporter::AppendAppNotesToCrashReport(data);
  1087 NS_IMETHODIMP
  1088 nsXULAppInfo::RegisterAppMemory(uint64_t pointer,
  1089                                 uint64_t len)
  1091   return CrashReporter::RegisterAppMemory((void *)pointer, len);
  1094 NS_IMETHODIMP
  1095 nsXULAppInfo::WriteMinidumpForException(void* aExceptionInfo)
  1097 #ifdef XP_WIN32
  1098   return CrashReporter::WriteMinidumpForException(static_cast<EXCEPTION_POINTERS*>(aExceptionInfo));
  1099 #else
  1100   return NS_ERROR_NOT_IMPLEMENTED;
  1101 #endif
  1104 NS_IMETHODIMP
  1105 nsXULAppInfo::AppendObjCExceptionInfoToAppNotes(void* aException)
  1107 #ifdef XP_MACOSX
  1108   return CrashReporter::AppendObjCExceptionInfoToAppNotes(aException);
  1109 #else
  1110   return NS_ERROR_NOT_IMPLEMENTED;
  1111 #endif
  1114 NS_IMETHODIMP
  1115 nsXULAppInfo::GetSubmitReports(bool* aEnabled)
  1117   return CrashReporter::GetSubmitReports(aEnabled);
  1120 NS_IMETHODIMP
  1121 nsXULAppInfo::SetSubmitReports(bool aEnabled)
  1123   return CrashReporter::SetSubmitReports(aEnabled);
  1126 NS_IMETHODIMP
  1127 nsXULAppInfo::UpdateCrashEventsDir()
  1129   CrashReporter::UpdateCrashEventsDir();
  1130   return NS_OK;
  1133 #endif
  1135 static const nsXULAppInfo kAppInfo;
  1136 static nsresult AppInfoConstructor(nsISupports* aOuter,
  1137                                    REFNSIID aIID, void **aResult)
  1139   NS_ENSURE_NO_AGGREGATION(aOuter);
  1141   return const_cast<nsXULAppInfo*>(&kAppInfo)->
  1142     QueryInterface(aIID, aResult);
  1145 bool gLogConsoleErrors = false;
  1147 #define NS_ENSURE_TRUE_LOG(x, ret)               \
  1148   PR_BEGIN_MACRO                                 \
  1149   if (MOZ_UNLIKELY(!(x))) {                      \
  1150     NS_WARNING("NS_ENSURE_TRUE(" #x ") failed"); \
  1151     gLogConsoleErrors = true;                    \
  1152     return ret;                                  \
  1153   }                                              \
  1154   PR_END_MACRO
  1156 #define NS_ENSURE_SUCCESS_LOG(res, ret)          \
  1157   NS_ENSURE_TRUE_LOG(NS_SUCCEEDED(res), ret)
  1159 /**
  1160  * Because we're starting/stopping XPCOM several times in different scenarios,
  1161  * this class is a stack-based critter that makes sure that XPCOM is shut down
  1162  * during early returns.
  1163  */
  1165 class ScopedXPCOMStartup
  1167 public:
  1168   ScopedXPCOMStartup() :
  1169     mServiceManager(nullptr) { }
  1170   ~ScopedXPCOMStartup();
  1172   nsresult Initialize();
  1173   nsresult SetWindowCreator(nsINativeAppSupport* native);
  1175   static nsresult CreateAppSupport(nsISupports* aOuter, REFNSIID aIID, void** aResult);
  1177 private:
  1178   nsIServiceManager* mServiceManager;
  1179   static nsINativeAppSupport* gNativeAppSupport;
  1180 };
  1182 ScopedXPCOMStartup::~ScopedXPCOMStartup()
  1184   NS_IF_RELEASE(gNativeAppSupport);
  1186   if (mServiceManager) {
  1187 #ifdef XP_MACOSX
  1188     // On OS X, we need a pool to catch cocoa objects that are autoreleased
  1189     // during teardown.
  1190     mozilla::MacAutoreleasePool pool;
  1191 #endif
  1193     nsCOMPtr<nsIAppStartup> appStartup (do_GetService(NS_APPSTARTUP_CONTRACTID));
  1194     if (appStartup)
  1195       appStartup->DestroyHiddenWindow();
  1197     gDirServiceProvider->DoShutdown();
  1198     PROFILER_MARKER("Shutdown early");
  1200     WriteConsoleLog();
  1202     NS_ShutdownXPCOM(mServiceManager);
  1203     mServiceManager = nullptr;
  1207 // {95d89e3e-a169-41a3-8e56-719978e15b12}
  1208 #define APPINFO_CID \
  1209   { 0x95d89e3e, 0xa169, 0x41a3, { 0x8e, 0x56, 0x71, 0x99, 0x78, 0xe1, 0x5b, 0x12 } }
  1211 // {0C4A446C-EE82-41f2-8D04-D366D2C7A7D4}
  1212 static const nsCID kNativeAppSupportCID =
  1213   { 0xc4a446c, 0xee82, 0x41f2, { 0x8d, 0x4, 0xd3, 0x66, 0xd2, 0xc7, 0xa7, 0xd4 } };
  1215 // {5F5E59CE-27BC-47eb-9D1F-B09CA9049836}
  1216 static const nsCID kProfileServiceCID =
  1217   { 0x5f5e59ce, 0x27bc, 0x47eb, { 0x9d, 0x1f, 0xb0, 0x9c, 0xa9, 0x4, 0x98, 0x36 } };
  1219 static already_AddRefed<nsIFactory>
  1220 ProfileServiceFactoryConstructor(const mozilla::Module& module, const mozilla::Module::CIDEntry& entry)
  1222   nsCOMPtr<nsIFactory> factory;
  1223   NS_NewToolkitProfileFactory(getter_AddRefs(factory));
  1224   return factory.forget();
  1227 NS_DEFINE_NAMED_CID(APPINFO_CID);
  1229 static const mozilla::Module::CIDEntry kXRECIDs[] = {
  1230   { &kAPPINFO_CID, false, nullptr, AppInfoConstructor },
  1231   { &kProfileServiceCID, false, ProfileServiceFactoryConstructor, nullptr },
  1232   { &kNativeAppSupportCID, false, nullptr, ScopedXPCOMStartup::CreateAppSupport },
  1233   { nullptr }
  1234 };
  1236 static const mozilla::Module::ContractIDEntry kXREContracts[] = {
  1237   { XULAPPINFO_SERVICE_CONTRACTID, &kAPPINFO_CID },
  1238   { XULRUNTIME_SERVICE_CONTRACTID, &kAPPINFO_CID },
  1239 #ifdef MOZ_CRASHREPORTER
  1240   { NS_CRASHREPORTER_CONTRACTID, &kAPPINFO_CID },
  1241 #endif
  1242   { NS_PROFILESERVICE_CONTRACTID, &kProfileServiceCID },
  1243   { NS_NATIVEAPPSUPPORT_CONTRACTID, &kNativeAppSupportCID },
  1244   { nullptr }
  1245 };
  1247 static const mozilla::Module kXREModule = {
  1248   mozilla::Module::kVersion,
  1249   kXRECIDs,
  1250   kXREContracts
  1251 };
  1253 NSMODULE_DEFN(Apprunner) = &kXREModule;
  1255 nsresult
  1256 ScopedXPCOMStartup::Initialize()
  1258   NS_ASSERTION(gDirServiceProvider, "Should not get here!");
  1260   nsresult rv;
  1262   rv = NS_InitXPCOM2(&mServiceManager, gDirServiceProvider->GetAppDir(),
  1263                      gDirServiceProvider);
  1264   if (NS_FAILED(rv)) {
  1265     NS_ERROR("Couldn't start xpcom!");
  1266     mServiceManager = nullptr;
  1268   else {
  1269     nsCOMPtr<nsIComponentRegistrar> reg =
  1270       do_QueryInterface(mServiceManager);
  1271     NS_ASSERTION(reg, "Service Manager doesn't QI to Registrar.");
  1274   return rv;
  1277 /**
  1278  * This is a little factory class that serves as a singleton-service-factory
  1279  * for the nativeappsupport object.
  1280  */
  1281 class nsSingletonFactory MOZ_FINAL : public nsIFactory
  1283 public:
  1284   NS_DECL_ISUPPORTS
  1285   NS_DECL_NSIFACTORY
  1287   nsSingletonFactory(nsISupports* aSingleton);
  1288   ~nsSingletonFactory() { }
  1290 private:
  1291   nsCOMPtr<nsISupports> mSingleton;
  1292 };
  1294 nsSingletonFactory::nsSingletonFactory(nsISupports* aSingleton)
  1295   : mSingleton(aSingleton)
  1297   NS_ASSERTION(mSingleton, "Singleton was null!");
  1300 NS_IMPL_ISUPPORTS(nsSingletonFactory, nsIFactory)
  1302 NS_IMETHODIMP
  1303 nsSingletonFactory::CreateInstance(nsISupports* aOuter,
  1304                                    const nsIID& aIID,
  1305                                    void* *aResult)
  1307   NS_ENSURE_NO_AGGREGATION(aOuter);
  1309   return mSingleton->QueryInterface(aIID, aResult);
  1312 NS_IMETHODIMP
  1313 nsSingletonFactory::LockFactory(bool)
  1315   return NS_OK;
  1318 /**
  1319  * Set our windowcreator on the WindowWatcher service.
  1320  */
  1321 nsresult
  1322 ScopedXPCOMStartup::SetWindowCreator(nsINativeAppSupport* native)
  1324   nsresult rv;
  1326   NS_IF_ADDREF(gNativeAppSupport = native);
  1328   // Inform the chrome registry about OS accessibility
  1329   nsCOMPtr<nsIToolkitChromeRegistry> cr =
  1330     mozilla::services::GetToolkitChromeRegistryService();
  1332   if (cr)
  1333     cr->CheckForOSAccessibility();
  1335   nsCOMPtr<nsIWindowCreator> creator (do_GetService(NS_APPSTARTUP_CONTRACTID));
  1336   if (!creator) return NS_ERROR_UNEXPECTED;
  1338   nsCOMPtr<nsIWindowWatcher> wwatch
  1339     (do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv));
  1340   NS_ENSURE_SUCCESS(rv, rv);
  1342   return wwatch->SetWindowCreator(creator);
  1345 /* static */ nsresult
  1346 ScopedXPCOMStartup::CreateAppSupport(nsISupports* aOuter, REFNSIID aIID, void** aResult)
  1348   if (aOuter)
  1349     return NS_ERROR_NO_AGGREGATION;
  1351   if (!gNativeAppSupport)
  1352     return NS_ERROR_NOT_INITIALIZED;
  1354   return gNativeAppSupport->QueryInterface(aIID, aResult);
  1357 nsINativeAppSupport* ScopedXPCOMStartup::gNativeAppSupport;
  1359 /**
  1360  * A helper class which calls NS_LogInit/NS_LogTerm in its scope.
  1361  */
  1362 class ScopedLogging
  1364 public:
  1365   ScopedLogging() { NS_LogInit(); }
  1366   ~ScopedLogging() { NS_LogTerm(); }
  1367 };
  1369 static void DumpArbitraryHelp()
  1371   nsresult rv;
  1373   ScopedLogging log;
  1376     ScopedXPCOMStartup xpcom;
  1377     xpcom.Initialize();
  1379     nsCOMPtr<nsICommandLineRunner> cmdline
  1380       (do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
  1381     if (!cmdline)
  1382       return;
  1384     nsCString text;
  1385     rv = cmdline->GetHelpText(text);
  1386     if (NS_SUCCEEDED(rv))
  1387       printf("%s", text.get());
  1391 // English text needs to go into a dtd file.
  1392 // But when this is called we have no components etc. These strings must either be
  1393 // here, or in a native resource file.
  1394 static void
  1395 DumpHelp()
  1397   printf("Usage: %s [ options ... ] [URL]\n"
  1398          "       where options include:\n\n", gArgv[0]);
  1400 #ifdef MOZ_X11
  1401   printf("X11 options\n"
  1402          "  --display=DISPLAY  X display to use\n"
  1403          "  --sync             Make X calls synchronous\n");
  1404 #endif
  1405 #ifdef XP_UNIX
  1406   printf("  --g-fatal-warnings Make all warnings fatal\n"
  1407          "\n%s options\n", gAppData->name);
  1408 #endif
  1410   printf("  -h or -help        Print this message.\n"
  1411          "  -v or -version     Print %s version.\n"
  1412          "  -P <profile>       Start with <profile>.\n"
  1413          "  -migration         Start with migration wizard.\n"
  1414          "  -ProfileManager    Start with ProfileManager.\n"
  1415          "  -no-remote         (default) Do not accept or send remote commands; implies -new-instance.\n"
  1416          "  -allow-remote      Accept and send remote commands.\n"
  1417          "  -new-instance      Open new instance, not a new window in running instance.\n"
  1418          "  -UILocale <locale> Start with <locale> resources as UI Locale.\n"
  1419          "  -safe-mode         Disables extensions and themes for this session.\n", gAppData->name);
  1421 #if defined(XP_WIN)
  1422   printf("  -console           Start %s with a debugging console.\n", gAppData->name);
  1423 #endif
  1425   // this works, but only after the components have registered.  so if you drop in a new command line handler, -help
  1426   // won't not until the second run.
  1427   // out of the bug, because we ship a component.reg file, it works correctly.
  1428   DumpArbitraryHelp();
  1431 #if defined(DEBUG) && defined(XP_WIN)
  1432 #ifdef DEBUG_warren
  1433 #define _CRTDBG_MAP_ALLOC
  1434 #endif
  1435 // Set a CRT ReportHook function to capture and format MSCRT
  1436 // warnings, errors and assertions.
  1437 // See http://msdn.microsoft.com/en-US/library/74kabxyx(v=VS.80).aspx
  1438 #include <stdio.h>
  1439 #include <crtdbg.h>
  1440 #include "mozilla/mozalloc_abort.h"
  1441 static int MSCRTReportHook( int aReportType, char *aMessage, int *oReturnValue)
  1443   *oReturnValue = 0; // continue execution
  1445   // Do not use fprintf or other functions which may allocate
  1446   // memory from the heap which may be corrupted. Instead,
  1447   // use fputs to output the leading portion of the message
  1448   // and use mozalloc_abort to emit the remainder of the
  1449   // message.
  1451   switch(aReportType) {
  1452   case 0:
  1453     fputs("\nWARNING: CRT WARNING", stderr);
  1454     fputs(aMessage, stderr);
  1455     fputs("\n", stderr);
  1456     break;
  1457   case 1:
  1458     fputs("\n###!!! ABORT: CRT ERROR ", stderr);
  1459     mozalloc_abort(aMessage);
  1460     break;
  1461   case 2:
  1462     fputs("\n###!!! ABORT: CRT ASSERT ", stderr);
  1463     mozalloc_abort(aMessage);
  1464     break;
  1467   // do not invoke the debugger
  1468   return 1;
  1471 #endif
  1473 static inline void
  1474 DumpVersion()
  1476   if (gAppData->vendor)
  1477     printf("%s ", gAppData->vendor);
  1478   printf("%s %s", gAppData->name, gAppData->version);
  1479   if (gAppData->copyright)
  1480       printf(", %s", gAppData->copyright);
  1481   printf("\n");
  1484 #ifdef MOZ_ENABLE_XREMOTE
  1485 // use int here instead of a PR type since it will be returned
  1486 // from main - just to keep types consistent
  1487 static int
  1488 HandleRemoteArgument(const char* remote, const char* aDesktopStartupID)
  1490   nsresult rv;
  1491   ArgResult ar;
  1493   const char *profile = 0;
  1494   nsAutoCString program(gAppData->name);
  1495   ToLowerCase(program);
  1496   const char *username = getenv("LOGNAME");
  1498   ar = CheckArg("p", false, &profile);
  1499   if (ar == ARG_BAD) {
  1500     PR_fprintf(PR_STDERR, "Error: argument -p requires a profile name\n");
  1501     return 1;
  1504   const char *temp = nullptr;
  1505   ar = CheckArg("a", false, &temp);
  1506   if (ar == ARG_BAD) {
  1507     PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n");
  1508     return 1;
  1509   } else if (ar == ARG_FOUND) {
  1510     program.Assign(temp);
  1513   ar = CheckArg("u", false, &username);
  1514   if (ar == ARG_BAD) {
  1515     PR_fprintf(PR_STDERR, "Error: argument -u requires a username\n");
  1516     return 1;
  1519   XRemoteClient client;
  1520   rv = client.Init();
  1521   if (NS_FAILED(rv)) {
  1522     PR_fprintf(PR_STDERR, "Error: Failed to connect to X server.\n");
  1523     return 1;
  1526   nsXPIDLCString response;
  1527   bool success = false;
  1528   rv = client.SendCommand(program.get(), username, profile, remote,
  1529                           aDesktopStartupID, getter_Copies(response), &success);
  1530   // did the command fail?
  1531   if (NS_FAILED(rv)) {
  1532     PR_fprintf(PR_STDERR, "Error: Failed to send command: %s\n",
  1533                response ? response.get() : "No response included");
  1534     return 1;
  1537   if (!success) {
  1538     PR_fprintf(PR_STDERR, "Error: No running window found\n");
  1539     return 2;
  1542   return 0;
  1545 static RemoteResult
  1546 RemoteCommandLine(const char* aDesktopStartupID)
  1548   nsresult rv;
  1549   ArgResult ar;
  1551   nsAutoCString program(gAppData->name);
  1552   ToLowerCase(program);
  1553   const char *username = getenv("LOGNAME");
  1555   const char *temp = nullptr;
  1556   ar = CheckArg("a", true, &temp);
  1557   if (ar == ARG_BAD) {
  1558     PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n");
  1559     return REMOTE_ARG_BAD;
  1560   } else if (ar == ARG_FOUND) {
  1561     program.Assign(temp);
  1564   ar = CheckArg("u", true, &username);
  1565   if (ar == ARG_BAD) {
  1566     PR_fprintf(PR_STDERR, "Error: argument -u requires a username\n");
  1567     return REMOTE_ARG_BAD;
  1570   XRemoteClient client;
  1571   rv = client.Init();
  1572   if (NS_FAILED(rv))
  1573     return REMOTE_NOT_FOUND;
  1575   nsXPIDLCString response;
  1576   bool success = false;
  1577   rv = client.SendCommandLine(program.get(), username, nullptr,
  1578                               gArgc, gArgv, aDesktopStartupID,
  1579                               getter_Copies(response), &success);
  1580   // did the command fail?
  1581   if (NS_FAILED(rv) || !success)
  1582     return REMOTE_NOT_FOUND;
  1584   return REMOTE_FOUND;
  1586 #endif // MOZ_ENABLE_XREMOTE
  1588 void
  1589 XRE_InitOmnijar(nsIFile* greOmni, nsIFile* appOmni)
  1591   mozilla::Omnijar::Init(greOmni, appOmni);
  1594 nsresult
  1595 XRE_GetBinaryPath(const char* argv0, nsIFile* *aResult)
  1597   return mozilla::BinaryPath::GetFile(argv0, aResult);
  1600 #ifdef XP_WIN
  1601 #include "nsWindowsRestart.cpp"
  1602 #include <shellapi.h>
  1604 typedef BOOL (WINAPI* SetProcessDEPPolicyFunc)(DWORD dwFlags);
  1605 #endif
  1607 // If aBlankCommandLine is true, then the application will be launched with a
  1608 // blank command line instead of being launched with the same command line that
  1609 // it was initially started with.
  1610 static nsresult LaunchChild(nsINativeAppSupport* aNative,
  1611                             bool aBlankCommandLine = false)
  1613   aNative->Quit(); // release DDE mutex, if we're holding it
  1615   // Restart this process by exec'ing it into the current process
  1616   // if supported by the platform.  Otherwise, use NSPR.
  1618 #ifdef MOZ_JPROF
  1619   // make sure JPROF doesn't think we're E10s
  1620   unsetenv("JPROF_SLAVE");
  1621 #endif
  1623   if (aBlankCommandLine) {
  1624 #if defined(MOZ_WIDGET_QT)
  1625     // Remove only arguments not given to Qt
  1626     gRestartArgc = gQtOnlyArgc;
  1627     gRestartArgv = gQtOnlyArgv;
  1628 #else
  1629     gRestartArgc = 1;
  1630     gRestartArgv[gRestartArgc] = nullptr;
  1631 #endif
  1634   SaveToEnv("MOZ_LAUNCHED_CHILD=1");
  1636 #if defined(MOZ_WIDGET_ANDROID)
  1637   mozilla::widget::android::GeckoAppShell::ScheduleRestart();
  1638 #else
  1639 #if defined(XP_MACOSX)
  1640   CommandLineServiceMac::SetupMacCommandLine(gRestartArgc, gRestartArgv, true);
  1641   uint32_t restartMode = 0;
  1642   restartMode = gRestartMode;
  1643   LaunchChildMac(gRestartArgc, gRestartArgv, restartMode);
  1644 #else
  1645   nsCOMPtr<nsIFile> lf;
  1646   nsresult rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
  1647   if (NS_FAILED(rv))
  1648     return rv;
  1650 #if defined(XP_WIN)
  1651   nsAutoString exePath;
  1652   rv = lf->GetPath(exePath);
  1653   if (NS_FAILED(rv))
  1654     return rv;
  1656   if (!WinLaunchChild(exePath.get(), gRestartArgc, gRestartArgv))
  1657     return NS_ERROR_FAILURE;
  1659 #else
  1660   nsAutoCString exePath;
  1661   rv = lf->GetNativePath(exePath);
  1662   if (NS_FAILED(rv))
  1663     return rv;
  1665 #if defined(XP_UNIX)
  1666   if (execv(exePath.get(), gRestartArgv) == -1)
  1667     return NS_ERROR_FAILURE;
  1668 #else
  1669   PRProcess* process = PR_CreateProcess(exePath.get(), gRestartArgv,
  1670                                         nullptr, nullptr);
  1671   if (!process) return NS_ERROR_FAILURE;
  1673   int32_t exitCode;
  1674   PRStatus failed = PR_WaitProcess(process, &exitCode);
  1675   if (failed || exitCode)
  1676     return NS_ERROR_FAILURE;
  1677 #endif // XP_UNIX
  1678 #endif // WP_WIN
  1679 #endif // WP_MACOSX
  1680 #endif // MOZ_WIDGET_ANDROID
  1682   return NS_ERROR_LAUNCHED_CHILD_PROCESS;
  1685 static const char kProfileProperties[] =
  1686   "chrome://mozapps/locale/profile/profileSelection.properties";
  1688 static nsresult
  1689 ProfileLockedDialog(nsIFile* aProfileDir, nsIFile* aProfileLocalDir,
  1690                     nsIProfileUnlocker* aUnlocker,
  1691                     nsINativeAppSupport* aNative, nsIProfileLock* *aResult)
  1693   nsresult rv;
  1695   ScopedXPCOMStartup xpcom;
  1696   rv = xpcom.Initialize();
  1697   NS_ENSURE_SUCCESS(rv, rv);
  1699   mozilla::Telemetry::WriteFailedProfileLock(aProfileDir);
  1701   rv = xpcom.SetWindowCreator(aNative);
  1702   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  1704   { //extra scoping is needed so we release these components before xpcom shutdown
  1705     nsCOMPtr<nsIStringBundleService> sbs =
  1706       mozilla::services::GetStringBundleService();
  1707     NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE);
  1709     nsCOMPtr<nsIStringBundle> sb;
  1710     sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
  1711     NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE);
  1713     NS_ConvertUTF8toUTF16 appName(gAppData->name);
  1714     const char16_t* params[] = {appName.get(), appName.get()};
  1716     nsXPIDLString killMessage;
  1717 #ifndef XP_MACOSX
  1718     static const char16_t kRestartNoUnlocker[] = {'r','e','s','t','a','r','t','M','e','s','s','a','g','e','N','o','U','n','l','o','c','k','e','r','\0'}; // "restartMessageNoUnlocker"
  1719     static const char16_t kRestartUnlocker[] = {'r','e','s','t','a','r','t','M','e','s','s','a','g','e','U','n','l','o','c','k','e','r','\0'}; // "restartMessageUnlocker"
  1720 #else
  1721     static const char16_t kRestartNoUnlocker[] = {'r','e','s','t','a','r','t','M','e','s','s','a','g','e','N','o','U','n','l','o','c','k','e','r','M','a','c','\0'}; // "restartMessageNoUnlockerMac"
  1722     static const char16_t kRestartUnlocker[] = {'r','e','s','t','a','r','t','M','e','s','s','a','g','e','U','n','l','o','c','k','e','r','M','a','c','\0'}; // "restartMessageUnlockerMac"
  1723 #endif
  1725     sb->FormatStringFromName(aUnlocker ? kRestartUnlocker : kRestartNoUnlocker,
  1726                              params, 2, getter_Copies(killMessage));
  1728     nsXPIDLString killTitle;
  1729     sb->FormatStringFromName(MOZ_UTF16("restartTitle"),
  1730                              params, 1, getter_Copies(killTitle));
  1732     if (!killMessage || !killTitle)
  1733       return NS_ERROR_FAILURE;
  1735     nsCOMPtr<nsIPromptService> ps
  1736       (do_GetService(NS_PROMPTSERVICE_CONTRACTID));
  1737     NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE);
  1739     if (aUnlocker) {
  1740       int32_t button;
  1741 #ifdef MOZ_WIDGET_ANDROID
  1742       mozilla::widget::android::GeckoAppShell::KillAnyZombies();
  1743       button = 1;
  1744 #else
  1745       const uint32_t flags =
  1746         (nsIPromptService::BUTTON_TITLE_CANCEL * 
  1747          nsIPromptService::BUTTON_POS_0) +
  1748         (nsIPromptService::BUTTON_TITLE_IS_STRING * 
  1749          nsIPromptService::BUTTON_POS_1) +
  1750         nsIPromptService::BUTTON_POS_1_DEFAULT;
  1752       bool checkState = false;
  1753       rv = ps->ConfirmEx(nullptr, killTitle, killMessage, flags,
  1754                          killTitle, nullptr, nullptr, nullptr, 
  1755                          &checkState, &button);
  1756       NS_ENSURE_SUCCESS_LOG(rv, rv);
  1757 #endif
  1759       if (button == 1) {
  1760         rv = aUnlocker->Unlock(nsIProfileUnlocker::FORCE_QUIT);
  1761         if (NS_FAILED(rv)) 
  1762           return rv;
  1764         return NS_LockProfilePath(aProfileDir, aProfileLocalDir, 
  1765                                   nullptr, aResult);
  1767     } else {
  1768 #ifdef MOZ_WIDGET_ANDROID
  1769       if (mozilla::widget::android::GeckoAppShell::UnlockProfile()) {
  1770         return NS_LockProfilePath(aProfileDir, aProfileLocalDir, 
  1771                                   nullptr, aResult);
  1773 #else
  1774       rv = ps->Alert(nullptr, killTitle, killMessage);
  1775       NS_ENSURE_SUCCESS_LOG(rv, rv);
  1776 #endif
  1779     return NS_ERROR_ABORT;
  1784 static nsresult
  1785 ProfileMissingDialog(nsINativeAppSupport* aNative)
  1787   nsresult rv;
  1789   ScopedXPCOMStartup xpcom;
  1790   rv = xpcom.Initialize();
  1791   NS_ENSURE_SUCCESS(rv, rv);
  1793   rv = xpcom.SetWindowCreator(aNative);
  1794   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  1796   { //extra scoping is needed so we release these components before xpcom shutdown
  1797     nsCOMPtr<nsIStringBundleService> sbs =
  1798       mozilla::services::GetStringBundleService();
  1799     NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE);
  1801     nsCOMPtr<nsIStringBundle> sb;
  1802     sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
  1803     NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE);
  1805     NS_ConvertUTF8toUTF16 appName(gAppData->name);
  1806     const char16_t* params[] = {appName.get(), appName.get()};
  1808     nsXPIDLString missingMessage;
  1810     // profileMissing  
  1811     static const char16_t kMissing[] = {'p','r','o','f','i','l','e','M','i','s','s','i','n','g','\0'};
  1812     sb->FormatStringFromName(kMissing, params, 2, getter_Copies(missingMessage));
  1814     nsXPIDLString missingTitle;
  1815     sb->FormatStringFromName(MOZ_UTF16("profileMissingTitle"),
  1816                              params, 1, getter_Copies(missingTitle));
  1818     if (missingMessage && missingTitle) {
  1819       nsCOMPtr<nsIPromptService> ps
  1820         (do_GetService(NS_PROMPTSERVICE_CONTRACTID));
  1821       NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE);
  1823       ps->Alert(nullptr, missingTitle, missingMessage);
  1826     return NS_ERROR_ABORT;
  1830 static nsresult
  1831 ProfileLockedDialog(nsIToolkitProfile* aProfile, nsIProfileUnlocker* aUnlocker,
  1832                     nsINativeAppSupport* aNative, nsIProfileLock* *aResult)
  1834   nsCOMPtr<nsIFile> profileDir;
  1835   nsresult rv = aProfile->GetRootDir(getter_AddRefs(profileDir));
  1836   if (NS_FAILED(rv)) return rv;
  1838   bool exists;
  1839   profileDir->Exists(&exists);
  1840   if (!exists) {
  1841     return ProfileMissingDialog(aNative);
  1844   nsCOMPtr<nsIFile> profileLocalDir;
  1845   rv = aProfile->GetLocalDir(getter_AddRefs(profileLocalDir));
  1846   if (NS_FAILED(rv)) return rv;
  1848   return ProfileLockedDialog(profileDir, profileLocalDir, aUnlocker, aNative,
  1849                              aResult);
  1852 static const char kProfileManagerURL[] =
  1853   "chrome://mozapps/content/profile/profileSelection.xul";
  1855 static nsresult
  1856 ShowProfileManager(nsIToolkitProfileService* aProfileSvc,
  1857                    nsINativeAppSupport* aNative)
  1859   if (!CanShowProfileManager()) {
  1860     return NS_ERROR_NOT_IMPLEMENTED;
  1863   nsresult rv;
  1865   nsCOMPtr<nsIFile> profD, profLD;
  1866   char16_t* profileNamePtr;
  1867   nsAutoCString profileName;
  1870     ScopedXPCOMStartup xpcom;
  1871     rv = xpcom.Initialize();
  1872     NS_ENSURE_SUCCESS(rv, rv);
  1874     rv = xpcom.SetWindowCreator(aNative);
  1875     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  1877 #ifdef XP_MACOSX
  1878     CommandLineServiceMac::SetupMacCommandLine(gRestartArgc, gRestartArgv, true);
  1879 #endif
  1881 #ifdef XP_WIN
  1882     // we don't have to wait here because profile manager window will pump
  1883     // and DDE message will be handled
  1884     ProcessDDE(aNative, false);
  1885 #endif
  1887     { //extra scoping is needed so we release these components before xpcom shutdown
  1888       nsCOMPtr<nsIWindowWatcher> windowWatcher
  1889         (do_GetService(NS_WINDOWWATCHER_CONTRACTID));
  1890       nsCOMPtr<nsIDialogParamBlock> ioParamBlock
  1891         (do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID));
  1892       nsCOMPtr<nsIMutableArray> dlgArray (do_CreateInstance(NS_ARRAY_CONTRACTID));
  1893       NS_ENSURE_TRUE(windowWatcher && ioParamBlock && dlgArray, NS_ERROR_FAILURE);
  1895       ioParamBlock->SetObjects(dlgArray);
  1897       nsCOMPtr<nsIAppStartup> appStartup
  1898         (do_GetService(NS_APPSTARTUP_CONTRACTID));
  1899       NS_ENSURE_TRUE(appStartup, NS_ERROR_FAILURE);
  1901       nsCOMPtr<nsIDOMWindow> newWindow;
  1902       rv = windowWatcher->OpenWindow(nullptr,
  1903                                      kProfileManagerURL,
  1904                                      "_blank",
  1905                                      "centerscreen,chrome,modal,titlebar",
  1906                                      ioParamBlock,
  1907                                      getter_AddRefs(newWindow));
  1909       NS_ENSURE_SUCCESS_LOG(rv, rv);
  1911       aProfileSvc->Flush();
  1913       int32_t dialogConfirmed;
  1914       rv = ioParamBlock->GetInt(0, &dialogConfirmed);
  1915       if (NS_FAILED(rv) || dialogConfirmed == 0) return NS_ERROR_ABORT;
  1917       nsCOMPtr<nsIProfileLock> lock;
  1918       rv = dlgArray->QueryElementAt(0, NS_GET_IID(nsIProfileLock),
  1919                                     getter_AddRefs(lock));
  1920       NS_ENSURE_SUCCESS_LOG(rv, rv);
  1922       rv = lock->GetDirectory(getter_AddRefs(profD));
  1923       NS_ENSURE_SUCCESS(rv, rv);
  1925       rv = lock->GetLocalDirectory(getter_AddRefs(profLD));
  1926       NS_ENSURE_SUCCESS(rv, rv);
  1928       rv = ioParamBlock->GetString(0, &profileNamePtr);
  1929       NS_ENSURE_SUCCESS(rv, rv);
  1931       CopyUTF16toUTF8(profileNamePtr, profileName);
  1932       NS_Free(profileNamePtr);
  1934       lock->Unlock();
  1938   SaveFileToEnv("XRE_PROFILE_PATH", profD);
  1939   SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", profLD);
  1940   SaveWordToEnv("XRE_PROFILE_NAME", profileName);
  1942   bool offline = false;
  1943   aProfileSvc->GetStartOffline(&offline);
  1944   if (offline) {
  1945     SaveToEnv("XRE_START_OFFLINE=1");
  1948   return LaunchChild(aNative);
  1951 static nsresult
  1952 GetCurrentProfileIsDefault(nsIToolkitProfileService* aProfileSvc,
  1953                            nsIFile* aCurrentProfileRoot, bool *aResult)
  1955   nsresult rv;
  1956   // Check that the profile to reset is the default since reset and the associated migration are
  1957   // only supported in that case.
  1958   nsCOMPtr<nsIToolkitProfile> selectedProfile;
  1959   nsCOMPtr<nsIFile> selectedProfileRoot;
  1960   rv = aProfileSvc->GetSelectedProfile(getter_AddRefs(selectedProfile));
  1961   NS_ENSURE_SUCCESS(rv, rv);
  1963   rv = selectedProfile->GetRootDir(getter_AddRefs(selectedProfileRoot));
  1964   NS_ENSURE_SUCCESS(rv, rv);
  1966   bool currentIsSelected;
  1967   rv = aCurrentProfileRoot->Equals(selectedProfileRoot, &currentIsSelected);
  1969   *aResult = currentIsSelected;
  1970   return rv;
  1973 /**
  1974  * Set the currently running profile as the default/selected one.
  1976  * @param aCurrentProfileRoot The root directory of the current profile.
  1977  * @return an error if aCurrentProfileRoot is not found or the profile could not
  1978  * be set as the default.
  1979  */
  1980 static nsresult
  1981 SetCurrentProfileAsDefault(nsIToolkitProfileService* aProfileSvc,
  1982                            nsIFile* aCurrentProfileRoot)
  1984   NS_ENSURE_ARG_POINTER(aProfileSvc);
  1986   nsCOMPtr<nsISimpleEnumerator> profiles;
  1987   nsresult rv = aProfileSvc->GetProfiles(getter_AddRefs(profiles));
  1988   if (NS_FAILED(rv))
  1989     return rv;
  1991   bool foundMatchingProfile = false;
  1992   nsCOMPtr<nsISupports> supports;
  1993   rv = profiles->GetNext(getter_AddRefs(supports));
  1994   while (NS_SUCCEEDED(rv)) {
  1995     nsCOMPtr<nsIToolkitProfile> profile = do_QueryInterface(supports);
  1996     nsCOMPtr<nsIFile> profileRoot;
  1997     profile->GetRootDir(getter_AddRefs(profileRoot));
  1998     profileRoot->Equals(aCurrentProfileRoot, &foundMatchingProfile);
  1999     if (foundMatchingProfile && profile) {
  2000       rv = aProfileSvc->SetSelectedProfile(profile);
  2001       if (NS_SUCCEEDED(rv))
  2002         rv = aProfileSvc->Flush();
  2003       return rv;
  2005     rv = profiles->GetNext(getter_AddRefs(supports));
  2007   return rv;
  2010 static bool gDoMigration = false;
  2011 static bool gDoProfileReset = false;
  2013 // Pick a profile. We need to end up with a profile lock.
  2014 //
  2015 // 1) check for -profile <path>
  2016 // 2) check for -P <name>
  2017 // 3) check for -ProfileManager
  2018 // 4) use the default profile, if there is one
  2019 // 5) if there are *no* profiles, set up profile-migration
  2020 // 6) display the profile-manager UI
  2021 static nsresult
  2022 SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, nsINativeAppSupport* aNative,
  2023               bool* aStartOffline, nsACString* aProfileName)
  2025   StartupTimeline::Record(StartupTimeline::SELECT_PROFILE);
  2027   nsresult rv;
  2028   ArgResult ar;
  2029   const char* arg;
  2030   *aResult = nullptr;
  2031   *aStartOffline = false;
  2033   ar = CheckArg("offline", true);
  2034   if (ar == ARG_BAD) {
  2035     PR_fprintf(PR_STDERR, "Error: argument -offline is invalid when argument -osint is specified\n");
  2036     return NS_ERROR_FAILURE;
  2039   if (ar || EnvHasValue("XRE_START_OFFLINE"))
  2040     *aStartOffline = true;
  2042   if (EnvHasValue("MOZ_RESET_PROFILE_RESTART")) {
  2043     gDoProfileReset = true;
  2044     gDoMigration = true;
  2045     SaveToEnv("MOZ_RESET_PROFILE_RESTART=");
  2048   // reset-profile and migration args need to be checked before any profiles are chosen below.
  2049   ar = CheckArg("reset-profile", true);
  2050   if (ar == ARG_BAD) {
  2051     PR_fprintf(PR_STDERR, "Error: argument -reset-profile is invalid when argument -osint is specified\n");
  2052     return NS_ERROR_FAILURE;
  2053   } else if (ar == ARG_FOUND) {
  2054     gDoProfileReset = true;
  2057   ar = CheckArg("migration", true);
  2058   if (ar == ARG_BAD) {
  2059     PR_fprintf(PR_STDERR, "Error: argument -migration is invalid when argument -osint is specified\n");
  2060     return NS_ERROR_FAILURE;
  2061   } else if (ar == ARG_FOUND) {
  2062     gDoMigration = true;
  2065   nsCOMPtr<nsIFile> lf = GetFileFromEnv("XRE_PROFILE_PATH");
  2066   if (lf) {
  2067     nsCOMPtr<nsIFile> localDir =
  2068       GetFileFromEnv("XRE_PROFILE_LOCAL_PATH");
  2069     if (!localDir) {
  2070       localDir = lf;
  2073     arg = PR_GetEnv("XRE_PROFILE_NAME");
  2074     if (arg && *arg && aProfileName)
  2075       aProfileName->Assign(nsDependentCString(arg));
  2077     // Clear out flags that we handled (or should have handled!) last startup.
  2078     const char *dummy;
  2079     CheckArg("p", false, &dummy);
  2080     CheckArg("profile", false, &dummy);
  2081     CheckArg("profilemanager");
  2083     if (gDoProfileReset) {
  2084       // Check that the profile to reset is the default since reset and migration are only
  2085       // supported in that case.
  2086       bool currentIsSelected;
  2087       GetCurrentProfileIsDefault(aProfileSvc, lf, &currentIsSelected);
  2088       if (!currentIsSelected) {
  2089         NS_WARNING("Profile reset is only supported for the default profile.");
  2090         gDoProfileReset = gDoMigration = false;
  2093       // If we're resetting a profile, create a new one and use it to startup.
  2094       nsCOMPtr<nsIToolkitProfile> newProfile;
  2095       rv = CreateResetProfile(aProfileSvc, getter_AddRefs(newProfile));
  2096       if (NS_SUCCEEDED(rv)) {
  2097         rv = newProfile->GetRootDir(getter_AddRefs(lf));
  2098         NS_ENSURE_SUCCESS(rv, rv);
  2099         SaveFileToEnv("XRE_PROFILE_PATH", lf);
  2101         rv = newProfile->GetLocalDir(getter_AddRefs(localDir));
  2102         NS_ENSURE_SUCCESS(rv, rv);
  2103         SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", localDir);
  2105         rv = newProfile->GetName(*aProfileName);
  2106         if (NS_FAILED(rv))
  2107           aProfileName->Truncate(0);
  2108         SaveWordToEnv("XRE_PROFILE_NAME", *aProfileName);
  2109       } else {
  2110         NS_WARNING("Profile reset failed.");
  2111         gDoProfileReset = false;
  2115     return NS_LockProfilePath(lf, localDir, nullptr, aResult);
  2118   ar = CheckArg("profile", true, &arg);
  2119   if (ar == ARG_BAD) {
  2120     PR_fprintf(PR_STDERR, "Error: argument -profile requires a path\n");
  2121     return NS_ERROR_FAILURE;
  2123   if (ar) {
  2124     if (gDoProfileReset) {
  2125       NS_WARNING("Profile reset is only supported for the default profile.");
  2126       gDoProfileReset = false;
  2129     nsCOMPtr<nsIFile> lf;
  2130     rv = XRE_GetFileFromPath(arg, getter_AddRefs(lf));
  2131     NS_ENSURE_SUCCESS(rv, rv);
  2133     nsCOMPtr<nsIProfileUnlocker> unlocker;
  2135     // Check if the profile path exists and it's a directory.
  2136     bool exists;
  2137     lf->Exists(&exists);
  2138     if (!exists) {
  2139         rv = lf->Create(nsIFile::DIRECTORY_TYPE, 0700);
  2140         NS_ENSURE_SUCCESS(rv, rv);
  2143     // If a profile path is specified directory on the command line, then
  2144     // assume that the temp directory is the same as the given directory.
  2145     rv = NS_LockProfilePath(lf, lf, getter_AddRefs(unlocker), aResult);
  2146     if (NS_SUCCEEDED(rv))
  2147       return rv;
  2149     return ProfileLockedDialog(lf, lf, unlocker, aNative, aResult);
  2152   ar = CheckArg("createprofile", true, &arg);
  2153   if (ar == ARG_BAD) {
  2154     PR_fprintf(PR_STDERR, "Error: argument -createprofile requires a profile name\n");
  2155     return NS_ERROR_FAILURE;
  2157   if (ar) {
  2158     nsCOMPtr<nsIToolkitProfile> profile;
  2160     const char* delim = strchr(arg, ' ');
  2161     if (delim) {
  2162       nsCOMPtr<nsIFile> lf;
  2163       rv = NS_NewNativeLocalFile(nsDependentCString(delim + 1),
  2164                                    true, getter_AddRefs(lf));
  2165       if (NS_FAILED(rv)) {
  2166         PR_fprintf(PR_STDERR, "Error: profile path not valid.\n");
  2167         return rv;
  2170       // As with -profile, assume that the given path will be used for the
  2171       // main profile directory.
  2172       rv = aProfileSvc->CreateProfile(lf, nsDependentCSubstring(arg, delim),
  2173                                      getter_AddRefs(profile));
  2174     } else {
  2175       rv = aProfileSvc->CreateProfile(nullptr, nsDependentCString(arg),
  2176                                      getter_AddRefs(profile));
  2178     // Some pathological arguments can make it this far
  2179     if (NS_FAILED(rv)) {
  2180       PR_fprintf(PR_STDERR, "Error creating profile.\n");
  2181       return rv; 
  2183     rv = NS_ERROR_ABORT;  
  2184     aProfileSvc->Flush();
  2186     // XXXben need to ensure prefs.js exists here so the tinderboxes will
  2187     //        not go orange.
  2188     nsCOMPtr<nsIFile> prefsJSFile;
  2189     profile->GetRootDir(getter_AddRefs(prefsJSFile));
  2190     prefsJSFile->AppendNative(NS_LITERAL_CSTRING("prefs.js"));
  2191     nsAutoCString pathStr;
  2192     prefsJSFile->GetNativePath(pathStr);
  2193     PR_fprintf(PR_STDERR, "Success: created profile '%s' at '%s'\n", arg, pathStr.get());
  2194     bool exists;
  2195     prefsJSFile->Exists(&exists);
  2196     if (!exists)
  2197       prefsJSFile->Create(nsIFile::NORMAL_FILE_TYPE, 0644);
  2198     // XXXdarin perhaps 0600 would be better?
  2200     return rv;
  2203   uint32_t count;
  2204   rv = aProfileSvc->GetProfileCount(&count);
  2205   NS_ENSURE_SUCCESS(rv, rv);
  2207   ar = CheckArg("p", false, &arg);
  2208   if (ar == ARG_BAD) {
  2209     ar = CheckArg("osint");
  2210     if (ar == ARG_FOUND) {
  2211       PR_fprintf(PR_STDERR, "Error: argument -p is invalid when argument -osint is specified\n");
  2212       return NS_ERROR_FAILURE;
  2215     if (CanShowProfileManager()) {
  2216       return ShowProfileManager(aProfileSvc, aNative);
  2219   if (ar) {
  2220     ar = CheckArg("osint");
  2221     if (ar == ARG_FOUND) {
  2222       PR_fprintf(PR_STDERR, "Error: argument -p is invalid when argument -osint is specified\n");
  2223       return NS_ERROR_FAILURE;
  2225     nsCOMPtr<nsIToolkitProfile> profile;
  2226     rv = aProfileSvc->GetProfileByName(nsDependentCString(arg),
  2227                                       getter_AddRefs(profile));
  2228     if (NS_SUCCEEDED(rv)) {
  2229       if (gDoProfileReset) {
  2230         NS_WARNING("Profile reset is only supported for the default profile.");
  2231         gDoProfileReset = false;
  2234       nsCOMPtr<nsIProfileUnlocker> unlocker;
  2235       rv = profile->Lock(getter_AddRefs(unlocker), aResult);
  2236       if (NS_SUCCEEDED(rv)) {
  2237         if (aProfileName)
  2238           aProfileName->Assign(nsDependentCString(arg));
  2239         return NS_OK;
  2242       return ProfileLockedDialog(profile, unlocker, aNative, aResult);
  2245     if (CanShowProfileManager()) {
  2246       return ShowProfileManager(aProfileSvc, aNative);
  2250   ar = CheckArg("profilemanager", true);
  2251   if (ar == ARG_BAD) {
  2252     PR_fprintf(PR_STDERR, "Error: argument -profilemanager is invalid when argument -osint is specified\n");
  2253     return NS_ERROR_FAILURE;
  2254   } else if (ar == ARG_FOUND && CanShowProfileManager()) {
  2255     return ShowProfileManager(aProfileSvc, aNative);
  2258   if (!count) {
  2259     gDoMigration = true;
  2260     gDoProfileReset = false;
  2262     // create a default profile
  2263     nsCOMPtr<nsIToolkitProfile> profile;
  2264     nsresult rv = aProfileSvc->CreateProfile(nullptr, // choose a default dir for us
  2265                                              NS_LITERAL_CSTRING("default"),
  2266                                              getter_AddRefs(profile));
  2267     if (NS_SUCCEEDED(rv)) {
  2268       aProfileSvc->Flush();
  2269       rv = profile->Lock(nullptr, aResult);
  2270       if (NS_SUCCEEDED(rv)) {
  2271         if (aProfileName)
  2272           aProfileName->Assign(NS_LITERAL_CSTRING("default"));
  2273         return NS_OK;
  2278   bool useDefault = true;
  2279   if (count > 1 && CanShowProfileManager()) {
  2280     aProfileSvc->GetStartWithLastProfile(&useDefault);
  2283   if (useDefault) {
  2284     nsCOMPtr<nsIToolkitProfile> profile;
  2285     // GetSelectedProfile will auto-select the only profile if there's just one
  2286     aProfileSvc->GetSelectedProfile(getter_AddRefs(profile));
  2287     if (profile) {
  2288       // If we're resetting a profile, create a new one and use it to startup.
  2289       if (gDoProfileReset) {
  2291           // Check that the source profile is not in use by temporarily acquiring its lock.
  2292           nsIProfileLock* tempProfileLock;
  2293           nsCOMPtr<nsIProfileUnlocker> unlocker;
  2294           rv = profile->Lock(getter_AddRefs(unlocker), &tempProfileLock);
  2295           if (NS_FAILED(rv))
  2296             return ProfileLockedDialog(profile, unlocker, aNative, &tempProfileLock);
  2299         nsCOMPtr<nsIToolkitProfile> newProfile;
  2300         rv = CreateResetProfile(aProfileSvc, getter_AddRefs(newProfile));
  2301         if (NS_SUCCEEDED(rv))
  2302           profile = newProfile;
  2303         else
  2304           gDoProfileReset = false;
  2307       // If you close Firefox and very quickly reopen it, the old Firefox may
  2308       // still be closing down. Rather than immediately showing the
  2309       // "Firefox is running but is not responding" message, we spend a few
  2310       // seconds retrying first.
  2312       static const int kLockRetrySeconds = 5;
  2313       static const int kLockRetrySleepMS = 100;
  2315       nsCOMPtr<nsIProfileUnlocker> unlocker;
  2316       const TimeStamp start = TimeStamp::Now();
  2317       do {
  2318         rv = profile->Lock(getter_AddRefs(unlocker), aResult);
  2319         if (NS_SUCCEEDED(rv)) {
  2320           StartupTimeline::Record(StartupTimeline::AFTER_PROFILE_LOCKED);
  2321           // Try to grab the profile name.
  2322           if (aProfileName) {
  2323             rv = profile->GetName(*aProfileName);
  2324             if (NS_FAILED(rv))
  2325               aProfileName->Truncate(0);
  2327           return NS_OK;
  2329         PR_Sleep(kLockRetrySleepMS);
  2330       } while (TimeStamp::Now() - start < TimeDuration::FromSeconds(kLockRetrySeconds));
  2332       return ProfileLockedDialog(profile, unlocker, aNative, aResult);
  2336   if (!CanShowProfileManager()) {
  2337     return NS_ERROR_FAILURE;
  2340   return ShowProfileManager(aProfileSvc, aNative);
  2343 /** 
  2344  * Checks the compatibility.ini file to see if we have updated our application
  2345  * or otherwise invalidated our caches. If the application has been updated, 
  2346  * we return false; otherwise, we return true. We also write the status 
  2347  * of the caches (valid/invalid) into the return param aCachesOK. The aCachesOK
  2348  * is always invalid if the application has been updated. 
  2349  */
  2350 static bool
  2351 CheckCompatibility(nsIFile* aProfileDir, const nsCString& aVersion,
  2352                    const nsCString& aOSABI, nsIFile* aXULRunnerDir,
  2353                    nsIFile* aAppDir, nsIFile* aFlagFile, 
  2354                    bool* aCachesOK)
  2356   *aCachesOK = false;
  2357   nsCOMPtr<nsIFile> file;
  2358   aProfileDir->Clone(getter_AddRefs(file));
  2359   if (!file)
  2360     return false;
  2361   file->AppendNative(FILE_COMPATIBILITY_INFO);
  2363   nsINIParser parser;
  2364   nsresult rv = parser.Init(file);
  2365   if (NS_FAILED(rv))
  2366     return false;
  2368   nsAutoCString buf;
  2369   rv = parser.GetString("Compatibility", "LastVersion", buf);
  2370   if (NS_FAILED(rv) || !aVersion.Equals(buf))
  2371     return false;
  2373   rv = parser.GetString("Compatibility", "LastOSABI", buf);
  2374   if (NS_FAILED(rv) || !aOSABI.Equals(buf))
  2375     return false;
  2377   rv = parser.GetString("Compatibility", "LastPlatformDir", buf);
  2378   if (NS_FAILED(rv))
  2379     return false;
  2381   nsCOMPtr<nsIFile> lf;
  2382   rv = NS_NewNativeLocalFile(buf, false,
  2383                              getter_AddRefs(lf));
  2384   if (NS_FAILED(rv))
  2385     return false;
  2387   bool eq;
  2388   rv = lf->Equals(aXULRunnerDir, &eq);
  2389   if (NS_FAILED(rv) || !eq)
  2390     return false;
  2392   if (aAppDir) {
  2393     rv = parser.GetString("Compatibility", "LastAppDir", buf);
  2394     if (NS_FAILED(rv))
  2395       return false;
  2397     rv = NS_NewNativeLocalFile(buf, false,
  2398                                getter_AddRefs(lf));
  2399     if (NS_FAILED(rv))
  2400       return false;
  2402     rv = lf->Equals(aAppDir, &eq);
  2403     if (NS_FAILED(rv) || !eq)
  2404       return false;
  2407   // If we see this flag, caches are invalid.
  2408   rv = parser.GetString("Compatibility", "InvalidateCaches", buf);
  2409   *aCachesOK = (NS_FAILED(rv) || !buf.EqualsLiteral("1"));
  2411   bool purgeCaches = false;
  2412   if (aFlagFile) {
  2413     aFlagFile->Exists(&purgeCaches);
  2416   *aCachesOK = !purgeCaches && *aCachesOK;
  2417   return true;
  2420 static void BuildVersion(nsCString &aBuf)
  2422   aBuf.Assign(gAppData->version);
  2423   aBuf.Append('_');
  2424   aBuf.Append(gAppData->buildID);
  2425   aBuf.Append('/');
  2426   aBuf.Append(gToolkitBuildID);
  2429 static void
  2430 WriteVersion(nsIFile* aProfileDir, const nsCString& aVersion,
  2431              const nsCString& aOSABI, nsIFile* aXULRunnerDir,
  2432              nsIFile* aAppDir, bool invalidateCache)
  2434   nsCOMPtr<nsIFile> file;
  2435   aProfileDir->Clone(getter_AddRefs(file));
  2436   if (!file)
  2437     return;
  2438   file->AppendNative(FILE_COMPATIBILITY_INFO);
  2440   nsAutoCString platformDir;
  2441   aXULRunnerDir->GetNativePath(platformDir);
  2443   nsAutoCString appDir;
  2444   if (aAppDir)
  2445     aAppDir->GetNativePath(appDir);
  2447   PRFileDesc *fd = nullptr;
  2448   file->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0600, &fd);
  2449   if (!fd) {
  2450     NS_ERROR("could not create output stream");
  2451     return;
  2454   static const char kHeader[] = "[Compatibility]" NS_LINEBREAK
  2455                                 "LastVersion=";
  2457   PR_Write(fd, kHeader, sizeof(kHeader) - 1);
  2458   PR_Write(fd, aVersion.get(), aVersion.Length());
  2460   static const char kOSABIHeader[] = NS_LINEBREAK "LastOSABI=";
  2461   PR_Write(fd, kOSABIHeader, sizeof(kOSABIHeader) - 1);
  2462   PR_Write(fd, aOSABI.get(), aOSABI.Length());
  2464   static const char kPlatformDirHeader[] = NS_LINEBREAK "LastPlatformDir=";
  2466   PR_Write(fd, kPlatformDirHeader, sizeof(kPlatformDirHeader) - 1);
  2467   PR_Write(fd, platformDir.get(), platformDir.Length());
  2469   static const char kAppDirHeader[] = NS_LINEBREAK "LastAppDir=";
  2470   if (aAppDir) {
  2471     PR_Write(fd, kAppDirHeader, sizeof(kAppDirHeader) - 1);
  2472     PR_Write(fd, appDir.get(), appDir.Length());
  2475   static const char kInvalidationHeader[] = NS_LINEBREAK "InvalidateCaches=1";
  2476   if (invalidateCache)
  2477     PR_Write(fd, kInvalidationHeader, sizeof(kInvalidationHeader) - 1);
  2479   static const char kNL[] = NS_LINEBREAK;
  2480   PR_Write(fd, kNL, sizeof(kNL) - 1);
  2482   PR_Close(fd);
  2485 /**
  2486  * Returns true if the startup cache file was successfully removed.
  2487  * Returns false if file->Clone fails at any point (OOM) or if unable
  2488  * to remove the startup cache file. Note in particular the return value
  2489  * is unaffected by a failure to remove extensions.ini
  2490  */
  2491 static bool
  2492 RemoveComponentRegistries(nsIFile* aProfileDir, nsIFile* aLocalProfileDir,
  2493                                       bool aRemoveEMFiles)
  2495   nsCOMPtr<nsIFile> file;
  2496   aProfileDir->Clone(getter_AddRefs(file));
  2497   if (!file)
  2498     return false;
  2500   if (aRemoveEMFiles) {
  2501     file->SetNativeLeafName(NS_LITERAL_CSTRING("extensions.ini"));
  2502     file->Remove(false);
  2505   aLocalProfileDir->Clone(getter_AddRefs(file));
  2506   if (!file)
  2507     return false;
  2509 #if defined(XP_UNIX) || defined(XP_BEOS)
  2510 #define PLATFORM_FASL_SUFFIX ".mfasl"
  2511 #elif defined(XP_WIN)
  2512 #define PLATFORM_FASL_SUFFIX ".mfl"
  2513 #endif
  2515   file->AppendNative(NS_LITERAL_CSTRING("XUL" PLATFORM_FASL_SUFFIX));
  2516   file->Remove(false);
  2518   file->SetNativeLeafName(NS_LITERAL_CSTRING("XPC" PLATFORM_FASL_SUFFIX));
  2519   file->Remove(false);
  2521   file->SetNativeLeafName(NS_LITERAL_CSTRING("startupCache"));
  2522   nsresult rv = file->Remove(true);
  2523   return NS_SUCCEEDED(rv) || rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST;
  2526 // To support application initiated restart via nsIAppStartup.quit, we
  2527 // need to save various environment variables, and then restore them
  2528 // before re-launching the application.
  2530 static struct SavedVar {
  2531   const char *name;
  2532   char *value;
  2533 } gSavedVars[] = {
  2534   {"XUL_APP_FILE", nullptr}
  2535 };
  2537 static void SaveStateForAppInitiatedRestart()
  2539   for (size_t i = 0; i < ArrayLength(gSavedVars); ++i) {
  2540     const char *s = PR_GetEnv(gSavedVars[i].name);
  2541     if (s)
  2542       gSavedVars[i].value = PR_smprintf("%s=%s", gSavedVars[i].name, s);
  2546 static void RestoreStateForAppInitiatedRestart()
  2548   for (size_t i = 0; i < ArrayLength(gSavedVars); ++i) {
  2549     if (gSavedVars[i].value)
  2550       PR_SetEnv(gSavedVars[i].value);
  2554 #ifdef MOZ_CRASHREPORTER
  2555 // When we first initialize the crash reporter we don't have a profile,
  2556 // so we set the minidump path to $TEMP.  Once we have a profile,
  2557 // we set it to $PROFILE/minidumps, creating the directory
  2558 // if needed.
  2559 static void MakeOrSetMinidumpPath(nsIFile* profD)
  2561   nsCOMPtr<nsIFile> dumpD;
  2562   profD->Clone(getter_AddRefs(dumpD));
  2564   if(dumpD) {
  2565     bool fileExists;
  2566     //XXX: do some more error checking here
  2567     dumpD->Append(NS_LITERAL_STRING("minidumps"));
  2568     dumpD->Exists(&fileExists);
  2569     if(!fileExists) {
  2570       dumpD->Create(nsIFile::DIRECTORY_TYPE, 0700);
  2573     nsAutoString pathStr;
  2574     if(NS_SUCCEEDED(dumpD->GetPath(pathStr)))
  2575       CrashReporter::SetMinidumpPath(pathStr);
  2578 #endif
  2580 const nsXREAppData* gAppData = nullptr;
  2582 #ifdef MOZ_WIDGET_GTK
  2583 #include "prlink.h"
  2584 typedef void (*_g_set_application_name_fn)(const gchar *application_name);
  2585 typedef void (*_gtk_window_set_auto_startup_notification_fn)(gboolean setting);
  2587 static PRFuncPtr FindFunction(const char* aName)
  2589   PRLibrary *lib = nullptr;
  2590   PRFuncPtr result = PR_FindFunctionSymbolAndLibrary(aName, &lib);
  2591   // Since the library was already loaded, we can safely unload it here.
  2592   if (lib) {
  2593     PR_UnloadLibrary(lib);
  2595   return result;
  2598 static void MOZ_gdk_display_close(GdkDisplay *display)
  2600 #if CLEANUP_MEMORY
  2601   // XXX wallpaper for bug 417163: don't close the Display if we're using the
  2602   // Qt theme because we crash (in Qt code) when using jemalloc.
  2603   bool theme_is_qt = false;
  2604   GtkSettings* settings =
  2605     gtk_settings_get_for_screen(gdk_display_get_default_screen(display));
  2606   gchar *theme_name;
  2607   g_object_get(settings, "gtk-theme-name", &theme_name, nullptr);
  2608   if (theme_name) {
  2609     theme_is_qt = strcmp(theme_name, "Qt") == 0;
  2610     if (theme_is_qt)
  2611       NS_WARNING("wallpaper bug 417163 for Qt theme");
  2612     g_free(theme_name);
  2615   // Get a (new) Pango context that holds a reference to the fontmap that
  2616   // GTK has been using.  gdk_pango_context_get() must be called while GTK
  2617   // has a default display.
  2618   PangoContext *pangoContext = gdk_pango_context_get();
  2620   bool buggyCairoShutdown = cairo_version() < CAIRO_VERSION_ENCODE(1, 4, 0);
  2622   if (!buggyCairoShutdown) {
  2623     // We should shut down GDK before we shut down libraries it depends on
  2624     // like Pango and cairo. But if cairo shutdown is buggy, we should
  2625     // shut down cairo first otherwise it may crash because of dangling
  2626     // references to Display objects (see bug 469831).
  2627     if (!theme_is_qt)
  2628       gdk_display_close(display);
  2631   // Clean up PangoCairo's default fontmap.
  2632   // This pango_fc_font_map_shutdown call (and the associated code to
  2633   // get the font map) really shouldn't be needed anymore, except that
  2634   // it's needed to avoid having cairo_debug_reset_static_data fatally
  2635   // assert if we've leaked other things that hold on to the fontmap,
  2636   // which is something that currently happens in mochitest-plugins.
  2637   // Even if it didn't happen in mochitest-plugins, we probably want to
  2638   // avoid the crash-on-leak problem since it makes it harder to use
  2639   // many of our leak tools to debug leaks.
  2641   // This doesn't take a reference.
  2642   PangoFontMap *fontmap = pango_context_get_font_map(pangoContext);
  2643   // Do some shutdown of the fontmap, which releases the fonts, clearing a
  2644   // bunch of circular references from the fontmap through the fonts back to
  2645   // itself.  The shutdown that this does is much less than what's done by
  2646   // the fontmap's finalize, though.
  2647   if (PANGO_IS_FC_FONT_MAP(fontmap))
  2648       pango_fc_font_map_shutdown(PANGO_FC_FONT_MAP(fontmap));
  2649   g_object_unref(pangoContext);
  2651   // Tell PangoCairo to release its default fontmap.
  2652   pango_cairo_font_map_set_default(nullptr);
  2654   // cairo_debug_reset_static_data() is prototyped through cairo.h included
  2655   // by gtk.h.
  2656 #ifdef cairo_debug_reset_static_data
  2657 #error "Looks like we're including Mozilla's cairo instead of system cairo"
  2658 #endif
  2659   cairo_debug_reset_static_data();
  2660   // FIXME: Do we need to call this in non-GTK2 cases as well?
  2661   FcFini();
  2663   if (buggyCairoShutdown) {
  2664     if (!theme_is_qt)
  2665       gdk_display_close(display);
  2667 #else // not CLEANUP_MEMORY
  2668   // Don't do anything to avoid running into driver bugs under XCloseDisplay().
  2669   // See bug 973192.
  2670   (void) display;
  2671 #endif
  2673 #endif // MOZ_WIDGET_GTK2
  2675 /** 
  2676  * NSPR will search for the "nspr_use_zone_allocator" symbol throughout
  2677  * the process and use it to determine whether the application defines its own
  2678  * memory allocator or not.
  2680  * Since most applications (e.g. Firefox and Thunderbird) don't use any special
  2681  * allocators and therefore don't define this symbol, NSPR must search the
  2682  * entire process, which reduces startup performance.
  2684  * By defining the symbol here, we can avoid the wasted lookup and hopefully
  2685  * improve startup performance.
  2686  */
  2687 NS_VISIBILITY_DEFAULT PRBool nspr_use_zone_allocator = PR_FALSE;
  2689 #ifdef CAIRO_HAS_DWRITE_FONT
  2691 #include <dwrite.h>
  2693 #ifdef DEBUG_DWRITE_STARTUP
  2695 #define LOGREGISTRY(msg) LogRegistryEvent(msg)
  2697 // for use when monitoring process
  2698 static void LogRegistryEvent(const wchar_t *msg)
  2700   HKEY dummyKey;
  2701   HRESULT hr;
  2702   wchar_t buf[512];
  2704   wsprintf(buf, L" log %s", msg);
  2705   hr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, buf, 0, KEY_READ, &dummyKey);
  2706   if (SUCCEEDED(hr)) {
  2707     RegCloseKey(dummyKey);
  2710 #else
  2712 #define LOGREGISTRY(msg)
  2714 #endif
  2716 static DWORD InitDwriteBG(LPVOID lpdwThreadParam)
  2718   SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_BEGIN);
  2719   LOGREGISTRY(L"loading dwrite.dll");
  2720   HMODULE dwdll = LoadLibraryW(L"dwrite.dll");
  2721   if (dwdll) {
  2722     decltype(DWriteCreateFactory)* createDWriteFactory = (decltype(DWriteCreateFactory)*)
  2723       GetProcAddress(dwdll, "DWriteCreateFactory");
  2724     if (createDWriteFactory) {
  2725       LOGREGISTRY(L"creating dwrite factory");
  2726       IDWriteFactory *factory;
  2727       HRESULT hr = createDWriteFactory(
  2728         DWRITE_FACTORY_TYPE_SHARED,
  2729         __uuidof(IDWriteFactory),
  2730         reinterpret_cast<IUnknown**>(&factory));
  2731       if (SUCCEEDED(hr)) {
  2732         LOGREGISTRY(L"dwrite factory done");
  2733         factory->Release();
  2734         LOGREGISTRY(L"freed factory");
  2735       } else {
  2736         LOGREGISTRY(L"failed to create factory");
  2740   SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_END);
  2741   return 0;
  2743 #endif
  2745 #ifdef USE_GLX_TEST
  2746 bool fire_glxtest_process();
  2747 #endif
  2749 #if defined(XP_WIN) && defined(MOZ_METRO)
  2750 #ifndef AHE_TYPE
  2751 enum AHE_TYPE {
  2752   AHE_DESKTOP = 0,
  2753   AHE_IMMERSIVE = 1
  2754 };
  2755 #endif
  2757 /*
  2758  * The Windows launcher uses this value to decide what front end ui
  2759  * to launch. We always launch the same ui unless the user
  2760  * specifically asks to switch. Update the value on every startup
  2761  * based on the environment requested.
  2762  */
  2763 void
  2764 SetLastWinRunType(AHE_TYPE aType)
  2766   HKEY key;
  2767   LONG result = RegOpenKeyExW(HKEY_CURRENT_USER,
  2768                               L"SOFTWARE\\Mozilla\\Firefox",
  2769                               0, KEY_WRITE, &key);
  2770   if (result != ERROR_SUCCESS) {
  2771     return;
  2773   DWORD value = (DWORD)aType;
  2774   result = RegSetValueEx(key, L"MetroLastAHE", 0, REG_DWORD,
  2775                          reinterpret_cast<LPBYTE>(&value),
  2776                          sizeof(DWORD));
  2777   RegCloseKey(key);
  2779 #endif // defined(XP_WIN) && defined(MOZ_METRO)
  2781 #include "GeckoProfiler.h"
  2783 // Encapsulates startup and shutdown state for XRE_main
  2784 class XREMain
  2786 public:
  2787   XREMain() :
  2788     mScopedXPCom(nullptr)
  2789     , mAppData(nullptr)
  2790     , mStartOffline(false)
  2791     , mShuttingDown(false)
  2792 #ifdef MOZ_ENABLE_XREMOTE
  2793     , mDisableRemote(false)
  2794 #endif
  2795 #if defined(MOZ_WIDGET_GTK)
  2796     , mGdkDisplay(nullptr)
  2797 #endif
  2798   {};
  2800   ~XREMain() {
  2801     if (mAppData) {
  2802       delete mAppData;
  2804     if (mScopedXPCom) {
  2805       NS_WARNING("Scoped xpcom should have been deleted!");
  2806       delete mScopedXPCom;
  2810   int XRE_main(int argc, char* argv[], const nsXREAppData* aAppData);
  2811   int XRE_mainInit(bool* aExitFlag);
  2812   int XRE_mainStartup(bool* aExitFlag);
  2813   nsresult XRE_mainRun();
  2815   nsCOMPtr<nsINativeAppSupport> mNativeApp;
  2816   nsCOMPtr<nsIToolkitProfileService> mProfileSvc;
  2817   nsCOMPtr<nsIFile> mProfD;
  2818   nsCOMPtr<nsIFile> mProfLD;
  2819   nsCOMPtr<nsIProfileLock> mProfileLock;
  2820 #ifdef MOZ_ENABLE_XREMOTE
  2821   nsCOMPtr<nsIRemoteService> mRemoteService;
  2822 #endif
  2824   ScopedXPCOMStartup* mScopedXPCom;
  2825   ScopedAppData* mAppData;
  2826   nsXREDirProvider mDirProvider;
  2827   nsAutoCString mProfileName;
  2828   nsAutoCString mDesktopStartupID;
  2830   bool mStartOffline;
  2831   bool mShuttingDown;
  2832 #ifdef MOZ_ENABLE_XREMOTE
  2833   bool mDisableRemote;
  2834 #endif
  2836 #if defined(MOZ_WIDGET_GTK)
  2837   GdkDisplay* mGdkDisplay;
  2838 #endif
  2839 };
  2841 /*
  2842  * XRE_mainInit - Initial setup and command line parameter processing.
  2843  * Main() will exit early if either return value != 0 or if aExitFlag is
  2844  * true.
  2845  */
  2846 int
  2847 XREMain::XRE_mainInit(bool* aExitFlag)
  2849   if (!aExitFlag)
  2850     return 1;
  2851   *aExitFlag = false;
  2853   StartupTimeline::Record(StartupTimeline::MAIN);
  2855   nsresult rv;
  2856   ArgResult ar;
  2858 #ifdef DEBUG
  2859   if (PR_GetEnv("XRE_MAIN_BREAK"))
  2860     NS_BREAK();
  2861 #endif
  2863 #ifdef USE_GLX_TEST
  2864   // bug 639842 - it's very important to fire this process BEFORE we set up
  2865   // error handling. indeed, this process is expected to be crashy, and we
  2866   // don't want the user to see its crashes. That's the whole reason for
  2867   // doing this in a separate process.
  2868   //
  2869   // This call will cause a fork and the fork will terminate itself separately
  2870   // from the usual shutdown sequence
  2871   fire_glxtest_process();
  2872 #endif
  2874 #if defined(XP_WIN) && defined(MOZ_METRO)
  2875   // Don't remove this arg, we want to pass it on to nsUpdateDriver 
  2876   if (CheckArg("metro-update", false, nullptr, false) == ARG_FOUND ||
  2877       XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Metro) {
  2878     // If we're doing a restart update that was initiated from metro land,
  2879     // we'll be running desktop to handle the actual update. Request that
  2880     // after the restart we launch into metro.
  2881     SetLastWinRunType(AHE_IMMERSIVE);
  2882   } else {
  2883     SetLastWinRunType(AHE_DESKTOP);
  2885 #endif
  2887   SetupErrorHandling(gArgv[0]);
  2889 #ifdef CAIRO_HAS_DWRITE_FONT
  2891     // Bug 602792 - when DWriteCreateFactory is called the dwrite client dll
  2892     // starts the FntCache service if it isn't already running (it's set
  2893     // to manual startup by default in Windows 7 RTM).  Subsequent DirectWrite
  2894     // calls cause the IDWriteFactory object to communicate with the FntCache
  2895     // service with a timeout; if there's no response after the timeout, the
  2896     // DirectWrite client library will assume the service isn't around and do
  2897     // manual font file I/O on _all_ system fonts.  To avoid this, load the
  2898     // dwrite library and create a factory as early as possible so that the
  2899     // FntCache service is ready by the time it's needed.
  2901     if (IsVistaOrLater()) {
  2902       CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)&InitDwriteBG,
  2903                    nullptr, 0, nullptr);
  2906 #endif
  2908 #ifdef XP_UNIX
  2909   const char *home = PR_GetEnv("HOME");
  2910   if (!home || !*home) {
  2911     struct passwd *pw = getpwuid(geteuid());
  2912     if (!pw || !pw->pw_dir) {
  2913       Output(true, "Could not determine HOME directory");
  2914       return 1;
  2916     SaveWordToEnv("HOME", nsDependentCString(pw->pw_dir));
  2918 #endif
  2920 #ifdef MOZ_ACCESSIBILITY_ATK
  2921   // Suppress atk-bridge init at startup, until mozilla accessibility is
  2922   // initialized.  This works after gnome 2.24.2.
  2923   SaveToEnv("NO_AT_BRIDGE=1");
  2924 #endif
  2926   // Check for application.ini overrides
  2927   const char* override = nullptr;
  2928   ar = CheckArg("override", true, &override);
  2929   if (ar == ARG_BAD) {
  2930     Output(true, "Incorrect number of arguments passed to -override");
  2931     return 1;
  2933   else if (ar == ARG_FOUND) {
  2934     nsCOMPtr<nsIFile> overrideLF;
  2935     rv = XRE_GetFileFromPath(override, getter_AddRefs(overrideLF));
  2936     if (NS_FAILED(rv)) {
  2937       Output(true, "Error: unrecognized override.ini path.\n");
  2938       return 1;
  2941     rv = XRE_ParseAppData(overrideLF, mAppData);
  2942     if (NS_FAILED(rv)) {
  2943       Output(true, "Couldn't read override.ini");
  2944       return 1;
  2948   // Check sanity and correctness of app data.
  2950   if (!mAppData->name) {
  2951     Output(true, "Error: App:Name not specified in application.ini\n");
  2952     return 1;
  2954   if (!mAppData->buildID) {
  2955     Output(true, "Error: App:BuildID not specified in application.ini\n");
  2956     return 1;
  2959   // XXX Originally ScopedLogging was here? Now it's in XRE_main above
  2960   // XRE_mainInit.
  2962   if (!mAppData->xreDirectory) {
  2963     nsCOMPtr<nsIFile> lf;
  2964     rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
  2965     if (NS_FAILED(rv))
  2966       return 2;
  2968     nsCOMPtr<nsIFile> greDir;
  2969     rv = lf->GetParent(getter_AddRefs(greDir));
  2970     if (NS_FAILED(rv))
  2971       return 2;
  2973     greDir.forget(&mAppData->xreDirectory);
  2976   if (!mAppData->directory) {
  2977     NS_IF_ADDREF(mAppData->directory = mAppData->xreDirectory);
  2980   if (mAppData->size > offsetof(nsXREAppData, minVersion)) {
  2981     if (!mAppData->minVersion) {
  2982       Output(true, "Error: Gecko:MinVersion not specified in application.ini\n");
  2983       return 1;
  2986     if (!mAppData->maxVersion) {
  2987       // If no maxVersion is specified, we assume the app is only compatible
  2988       // with the initial preview release. Do not increment this number ever!
  2989       SetAllocatedString(mAppData->maxVersion, "1.*");
  2992     if (mozilla::Version(mAppData->minVersion) > gToolkitVersion ||
  2993         mozilla::Version(mAppData->maxVersion) < gToolkitVersion) {
  2994       Output(true, "Error: Platform version '%s' is not compatible with\n"
  2995              "minVersion >= %s\nmaxVersion <= %s\n",
  2996              gToolkitVersion,
  2997              mAppData->minVersion, mAppData->maxVersion);
  2998       return 1;
  3002   rv = mDirProvider.Initialize(mAppData->directory, mAppData->xreDirectory);
  3003   if (NS_FAILED(rv))
  3004     return 1;
  3006 #ifdef MOZ_CRASHREPORTER
  3007   if (EnvHasValue("MOZ_CRASHREPORTER")) {
  3008     mAppData->flags |= NS_XRE_ENABLE_CRASH_REPORTER;
  3011   if ((mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER) &&
  3012       NS_SUCCEEDED(
  3013          CrashReporter::SetExceptionHandler(mAppData->xreDirectory))) {
  3014     CrashReporter::UpdateCrashEventsDir();
  3015     if (mAppData->crashReporterURL)
  3016       CrashReporter::SetServerURL(nsDependentCString(mAppData->crashReporterURL));
  3018     // pass some basic info from the app data
  3019     if (mAppData->vendor)
  3020       CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Vendor"),
  3021                                          nsDependentCString(mAppData->vendor));
  3022     if (mAppData->name)
  3023       CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ProductName"),
  3024                                          nsDependentCString(mAppData->name));
  3025     if (mAppData->ID)
  3026       CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ProductID"),
  3027                                          nsDependentCString(mAppData->ID));
  3028     if (mAppData->version)
  3029       CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Version"),
  3030                                          nsDependentCString(mAppData->version));
  3031     if (mAppData->buildID)
  3032       CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("BuildID"),
  3033                                          nsDependentCString(mAppData->buildID));
  3035     nsDependentCString releaseChannel(NS_STRINGIFY(MOZ_UPDATE_CHANNEL));
  3036     CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ReleaseChannel"),
  3037                                        releaseChannel);
  3038 #ifdef MOZ_LINKER
  3039     CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("CrashAddressLikelyWrong"),
  3040                                        IsSignalHandlingBroken() ? NS_LITERAL_CSTRING("1")
  3041                                                                 : NS_LITERAL_CSTRING("0"));
  3042 #endif
  3043     CrashReporter::SetRestartArgs(gArgc, gArgv);
  3045     // annotate other data (user id etc)
  3046     nsCOMPtr<nsIFile> userAppDataDir;
  3047     if (NS_SUCCEEDED(mDirProvider.GetUserAppDataDirectory(
  3048                                                          getter_AddRefs(userAppDataDir)))) {
  3049       CrashReporter::SetupExtraData(userAppDataDir,
  3050                                     nsDependentCString(mAppData->buildID));
  3052       // see if we have a crashreporter-override.ini in the application directory
  3053       nsCOMPtr<nsIFile> overrideini;
  3054       bool exists;
  3055       if (NS_SUCCEEDED(mDirProvider.GetAppDir()->Clone(getter_AddRefs(overrideini))) &&
  3056           NS_SUCCEEDED(overrideini->AppendNative(NS_LITERAL_CSTRING("crashreporter-override.ini"))) &&
  3057           NS_SUCCEEDED(overrideini->Exists(&exists)) &&
  3058           exists) {
  3059 #ifdef XP_WIN
  3060         nsAutoString overridePathW;
  3061         overrideini->GetPath(overridePathW);
  3062         NS_ConvertUTF16toUTF8 overridePath(overridePathW);
  3063 #else
  3064         nsAutoCString overridePath;
  3065         overrideini->GetNativePath(overridePath);
  3066 #endif
  3068         SaveWordToEnv("MOZ_CRASHREPORTER_STRINGS_OVERRIDE", overridePath);
  3072 #endif
  3074 #ifdef XP_MACOSX
  3075   if (EnvHasValue("MOZ_LAUNCHED_CHILD")) {
  3076     // This is needed, on relaunch, to force the OS to use the "Cocoa Dock
  3077     // API".  Otherwise the call to ReceiveNextEvent() below will make it
  3078     // use the "Carbon Dock API".  For more info see bmo bug 377166.
  3079     EnsureUseCocoaDockAPI();
  3081     // When the app relaunches, the original process exits.  This causes
  3082     // the dock tile to stop bouncing, lose the "running" triangle, and
  3083     // if the tile does not permanently reside in the Dock, even disappear.
  3084     // This can be confusing to the user, who is expecting the app to launch.
  3085     // Calling ReceiveNextEvent without requesting any event is enough to
  3086     // cause a dock tile for the child process to appear.
  3087     const EventTypeSpec kFakeEventList[] = { { INT_MAX, INT_MAX } };
  3088     EventRef event;
  3089     ::ReceiveNextEvent(GetEventTypeCount(kFakeEventList), kFakeEventList,
  3090                        kEventDurationNoWait, false, &event);
  3093   if (CheckArg("foreground")) {
  3094     // The original process communicates that it was in the foreground by
  3095     // adding this argument.  This new process, which is taking over for
  3096     // the old one, should make itself the active application.
  3097     ProcessSerialNumber psn;
  3098     if (::GetCurrentProcess(&psn) == noErr)
  3099       ::SetFrontProcess(&psn);
  3101 #endif
  3103   SaveToEnv("MOZ_LAUNCHED_CHILD=");
  3105   gRestartArgc = gArgc;
  3106   gRestartArgv = (char**) malloc(sizeof(char*) * (gArgc + 1 + (override ? 2 : 0)));
  3107   if (!gRestartArgv) {
  3108     return 1;
  3111   int i;
  3112   for (i = 0; i < gArgc; ++i) {
  3113     gRestartArgv[i] = gArgv[i];
  3116   // Add the -override argument back (it is removed automatically be CheckArg) if there is one
  3117   if (override) {
  3118     gRestartArgv[gRestartArgc++] = const_cast<char*>("-override");
  3119     gRestartArgv[gRestartArgc++] = const_cast<char*>(override);
  3122   gRestartArgv[gRestartArgc] = nullptr;
  3125   if (EnvHasValue("MOZ_SAFE_MODE_RESTART")) {
  3126     gSafeMode = true;
  3127     // unset the env variable
  3128     SaveToEnv("MOZ_SAFE_MODE_RESTART=");
  3131   ar = CheckArg("safe-mode", true);
  3132   if (ar == ARG_BAD) {
  3133     PR_fprintf(PR_STDERR, "Error: argument -safe-mode is invalid when argument -osint is specified\n");
  3134     return 1;
  3135   } else if (ar == ARG_FOUND) {
  3136     gSafeMode = true;
  3139 #ifdef XP_WIN
  3140   // If the shift key is pressed and the ctrl and / or alt keys are not pressed
  3141   // during startup start in safe mode. GetKeyState returns a short and the high
  3142   // order bit will be 1 if the key is pressed. By masking the returned short
  3143   // with 0x8000 the result will be 0 if the key is not pressed and non-zero
  3144   // otherwise.
  3145   if (GetKeyState(VK_SHIFT) & 0x8000 &&
  3146       !(GetKeyState(VK_CONTROL) & 0x8000) && !(GetKeyState(VK_MENU) & 0x8000)) {
  3147     gSafeMode = true;
  3149 #endif
  3151 #ifdef XP_MACOSX
  3152   if (GetCurrentEventKeyModifiers() & optionKey)
  3153     gSafeMode = true;
  3154 #endif
  3156   // In the Tor Browser, remoting is disabled by default unless -osint is used.
  3157   bool allowRemote = (CheckArg("allow-remote") == ARG_FOUND);
  3158   if (!allowRemote && (CheckArg("osint", false, nullptr, false) != ARG_FOUND))
  3159       SaveToEnv("MOZ_NO_REMOTE=1");
  3161   // Handle -no-remote and -new-instance command line arguments. Setup
  3162   // the environment to better accommodate other components and various
  3163   // restart scenarios.
  3164   ar = CheckArg("no-remote", true);
  3165   if (ar == ARG_BAD) {
  3166     PR_fprintf(PR_STDERR, "Error: argument -no-remote is invalid when argument -osint is specified\n");
  3167     return 1;
  3168   } else if ((ar == ARG_FOUND) && allowRemote) {
  3169     PR_fprintf(PR_STDERR, "Error: argument -no-remote is invalid when argument -allow-remote is specified\n");
  3170     return 1;
  3173   ar = CheckArg("new-instance", true);
  3174   if (ar == ARG_BAD) {
  3175     PR_fprintf(PR_STDERR, "Error: argument -new-instance is invalid when argument -osint is specified\n");
  3176     return 1;
  3177   } else if (ar == ARG_FOUND) {
  3178     SaveToEnv("MOZ_NEW_INSTANCE=1");
  3181   // Handle -help and -version command line arguments.
  3182   // They should return quickly, so we deal with them here.
  3183   if (CheckArg("h") || CheckArg("help") || CheckArg("?")) {
  3184     DumpHelp();
  3185     *aExitFlag = true;
  3186     return 0;
  3189   if (CheckArg("v") || CheckArg("version")) {
  3190     DumpVersion();
  3191     *aExitFlag = true;
  3192     return 0;
  3195 #ifdef NS_TRACE_MALLOC
  3196   gArgc = NS_TraceMallocStartupArgs(gArgc, gArgv);
  3197 #endif
  3199   rv = XRE_InitCommandLine(gArgc, gArgv);
  3200   NS_ENSURE_SUCCESS(rv, 1);
  3202   // Check for -register, which registers chrome and then exits immediately.
  3203   ar = CheckArg("register", true);
  3204   if (ar == ARG_BAD) {
  3205     PR_fprintf(PR_STDERR, "Error: argument -register is invalid when argument -osint is specified\n");
  3206     return 1;
  3207   } else if (ar == ARG_FOUND) {
  3208     ScopedXPCOMStartup xpcom;
  3209     rv = xpcom.Initialize();
  3210     NS_ENSURE_SUCCESS(rv, 1);
  3212       nsCOMPtr<nsIChromeRegistry> chromeReg =
  3213         mozilla::services::GetChromeRegistryService();
  3214       NS_ENSURE_TRUE(chromeReg, 1);
  3216       chromeReg->CheckForNewChrome();
  3218     *aExitFlag = true;
  3219     return 0;
  3222   if (PR_GetEnv("MOZ_RUN_GTEST")) {
  3223     int result;
  3224     // RunGTest will only be set if we're in xul-unit
  3225     if (mozilla::RunGTest) {
  3226       result = mozilla::RunGTest();
  3227     } else {
  3228       result = 1;
  3229       printf("TEST-UNEXPECTED-FAIL | gtest | Not compiled with enable-tests\n");
  3231     *aExitFlag = true;
  3232     return result;
  3235   return 0;
  3238 #ifdef MOZ_CRASHREPORTER
  3239 #ifdef XP_WIN
  3240 /**
  3241  * Uses WMI to read some manufacturer information that may be useful for
  3242  * diagnosing hardware-specific crashes. This function is best-effort; failures
  3243  * shouldn't burden the caller. COM must be initialized before calling.
  3244  */
  3245 static void AnnotateSystemManufacturer()
  3247   nsRefPtr<IWbemLocator> locator;
  3249   HRESULT hr = CoCreateInstance(CLSID_WbemLocator, nullptr, CLSCTX_INPROC_SERVER,
  3250                                 IID_IWbemLocator, getter_AddRefs(locator));
  3252   if (FAILED(hr)) {
  3253     return;
  3256   nsRefPtr<IWbemServices> services;
  3258   hr = locator->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), nullptr, nullptr, nullptr,
  3259                               0, nullptr, nullptr, getter_AddRefs(services));
  3261   if (FAILED(hr)) {
  3262     return;
  3265   hr = CoSetProxyBlanket(services, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nullptr,
  3266                          RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE,
  3267                          nullptr, EOAC_NONE);
  3269   if (FAILED(hr)) {
  3270     return;
  3273   nsRefPtr<IEnumWbemClassObject> enumerator;
  3275   hr = services->ExecQuery(_bstr_t(L"WQL"), _bstr_t(L"SELECT * FROM Win32_BIOS"),
  3276                            WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
  3277                            nullptr, getter_AddRefs(enumerator));
  3279   if (FAILED(hr) || !enumerator) {
  3280     return;
  3283   nsRefPtr<IWbemClassObject> classObject;
  3284   ULONG results;
  3286   hr = enumerator->Next(WBEM_INFINITE, 1, getter_AddRefs(classObject), &results);
  3288   if (FAILED(hr) || results == 0) {
  3289     return;
  3292   VARIANT value;
  3293   VariantInit(&value);
  3295   hr = classObject->Get(L"Manufacturer", 0, &value, 0, 0);
  3297   if (SUCCEEDED(hr) && V_VT(&value) == VT_BSTR) {
  3298     CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("BIOS_Manufacturer"),
  3299                                        NS_ConvertUTF16toUTF8(V_BSTR(&value)));
  3302   VariantClear(&value);
  3305 static void PR_CALLBACK AnnotateSystemManufacturer_ThreadStart(void*)
  3307   HRESULT hr = CoInitialize(nullptr);
  3309   if (FAILED(hr)) {
  3310     return;
  3313   AnnotateSystemManufacturer();
  3315   CoUninitialize();
  3317 #endif
  3318 #endif
  3320 namespace mozilla {
  3321   ShutdownChecksMode gShutdownChecks = SCM_NOTHING;
  3324 static void SetShutdownChecks() {
  3325   // Set default first. On debug builds we crash. On nightly and local
  3326   // builds we record. Nightlies will then send the info via telemetry,
  3327   // but it is usefull to have the data in about:telemetry in local builds
  3328   // too.
  3330 #ifdef DEBUG
  3331   gShutdownChecks = SCM_CRASH;
  3332 #else
  3333   const char* releaseChannel = NS_STRINGIFY(MOZ_UPDATE_CHANNEL);
  3334   if (strcmp(releaseChannel, "nightly") == 0 ||
  3335       strcmp(releaseChannel, "default") == 0) {
  3336     gShutdownChecks = SCM_RECORD;
  3337   } else {
  3338     gShutdownChecks = SCM_NOTHING;
  3340 #endif
  3342   // We let an environment variable override the default so that addons
  3343   // authors can use it for debugging shutdown with released firefox versions.
  3344   const char* mozShutdownChecksEnv = PR_GetEnv("MOZ_SHUTDOWN_CHECKS");
  3345   if (mozShutdownChecksEnv) {
  3346     if (strcmp(mozShutdownChecksEnv, "crash") == 0) {
  3347       gShutdownChecks = SCM_CRASH;
  3348     } else if (strcmp(mozShutdownChecksEnv, "record") == 0) {
  3349       gShutdownChecks = SCM_RECORD;
  3350     } else if (strcmp(mozShutdownChecksEnv, "nothing") == 0) {
  3351       gShutdownChecks = SCM_NOTHING;
  3357 /*
  3358  * XRE_mainStartup - Initializes the profile and various other services.
  3359  * Main() will exit early if either return value != 0 or if aExitFlag is
  3360  * true.
  3361  */
  3362 int
  3363 XREMain::XRE_mainStartup(bool* aExitFlag)
  3365   nsresult rv;
  3367   if (!aExitFlag)
  3368     return 1;
  3369   *aExitFlag = false;
  3371   SetShutdownChecks();
  3374   // Enable Telemetry IO Reporting on DEBUG, nightly and local builds
  3375 #ifdef DEBUG
  3376   mozilla::Telemetry::InitIOReporting(gAppData->xreDirectory);
  3377 #else
  3379     const char* releaseChannel = NS_STRINGIFY(MOZ_UPDATE_CHANNEL);
  3380     if (strcmp(releaseChannel, "nightly") == 0 ||
  3381         strcmp(releaseChannel, "default") == 0) {
  3382       mozilla::Telemetry::InitIOReporting(gAppData->xreDirectory);
  3385 #endif /* DEBUG */
  3387 #if defined(MOZ_WIDGET_GTK) || defined(MOZ_ENABLE_XREMOTE)
  3388   // Stash DESKTOP_STARTUP_ID in malloc'ed memory because gtk_init will clear it.
  3389 #define HAVE_DESKTOP_STARTUP_ID
  3390   const char* desktopStartupIDEnv = PR_GetEnv("DESKTOP_STARTUP_ID");
  3391   if (desktopStartupIDEnv) {
  3392     mDesktopStartupID.Assign(desktopStartupIDEnv);
  3394 #endif
  3396 #if defined(MOZ_WIDGET_QT)
  3397   nsQAppInstance::AddRef(gArgc, gArgv, true);
  3399   QStringList nonQtArguments = qApp->arguments();
  3400   gQtOnlyArgc = 1;
  3401   gQtOnlyArgv = (char**) malloc(sizeof(char*) 
  3402                 * (gRestartArgc - nonQtArguments.size() + 2));
  3404   // copy binary path
  3405   gQtOnlyArgv[0] = gRestartArgv[0];
  3407   for (int i = 1; i < gRestartArgc; ++i) {
  3408     if (!nonQtArguments.contains(gRestartArgv[i])) {
  3409       // copy arguments used by Qt for later
  3410       gQtOnlyArgv[gQtOnlyArgc++] = gRestartArgv[i];
  3413   gQtOnlyArgv[gQtOnlyArgc] = nullptr;
  3414 #endif
  3415 #if defined(MOZ_WIDGET_GTK)
  3416   // setup for private colormap.  Ideally we'd like to do this
  3417   // in nsAppShell::Create, but we need to get in before gtk
  3418   // has been initialized to make sure everything is running
  3419   // consistently.
  3420 #if (MOZ_WIDGET_GTK == 2)
  3421   if (CheckArg("install"))
  3422     gdk_rgb_set_install(TRUE);
  3423 #endif
  3425   // Set program name to the one defined in application.ini.
  3427     nsAutoCString program(gAppData->name);
  3428     ToLowerCase(program);
  3429     g_set_prgname(program.get());
  3432   // Initialize GTK here for splash.
  3434   // Open the display ourselves instead of using gtk_init, so that we can
  3435   // close it without fear that one day gtk might clean up the display it
  3436   // opens.
  3437   if (!gtk_parse_args(&gArgc, &gArgv))
  3438     return 1;
  3440   // display_name is owned by gdk.
  3441   const char *display_name = gdk_get_display_arg_name();
  3442   if (display_name) {
  3443     SaveWordToEnv("DISPLAY", nsDependentCString(display_name));
  3444   } else {
  3445     display_name = PR_GetEnv("DISPLAY");
  3446     if (!display_name) {
  3447       PR_fprintf(PR_STDERR, "Error: no display specified\n");
  3448       return 1;
  3451 #endif /* MOZ_WIDGET_GTK2 */
  3453 #ifdef MOZ_ENABLE_XREMOTE
  3454   // handle -remote now that xpcom is fired up
  3455   bool newInstance;
  3457     char *e = PR_GetEnv("MOZ_NO_REMOTE");
  3458     mDisableRemote = (e && *e);
  3459     if (mDisableRemote) {
  3460       newInstance = true;
  3461     } else {
  3462       e = PR_GetEnv("MOZ_NEW_INSTANCE");
  3463       newInstance = (e && *e);
  3467   const char* xremotearg;
  3468   ArgResult ar = CheckArg("remote", true, &xremotearg);
  3469   if (ar == ARG_BAD) {
  3470     PR_fprintf(PR_STDERR, "Error: -remote requires an argument\n");
  3471     return 1;
  3473   const char* desktopStartupIDPtr =
  3474     mDesktopStartupID.IsEmpty() ? nullptr : mDesktopStartupID.get();
  3475   if (ar) {
  3476     *aExitFlag = true;
  3477     return HandleRemoteArgument(xremotearg, desktopStartupIDPtr);
  3480   if (!newInstance) {
  3481     // Try to remote the entire command line. If this fails, start up normally.
  3482     RemoteResult rr = RemoteCommandLine(desktopStartupIDPtr);
  3483     if (rr == REMOTE_FOUND) {
  3484       *aExitFlag = true;
  3485       return 0;
  3487     else if (rr == REMOTE_ARG_BAD)
  3488       return 1;
  3490 #endif
  3491 #ifdef MOZ_X11
  3492   // Init X11 in thread-safe mode. Must be called prior to the first call to XOpenDisplay 
  3493   // (called inside gdk_display_open). This is a requirement for off main tread compositing.
  3494   // This is done only on X11 platforms if the environment variable MOZ_USE_OMTC is set so 
  3495   // as to avoid overhead when omtc is not used. 
  3496   //
  3497   // On nightly builds, we call this by default to enable OMTC for Electrolysis testing. On
  3498   // aurora, beta, and release builds, there is a small tpaint regression from enabling this
  3499   // call, so it sits behind an environment variable.
  3500   //
  3501   // An environment variable is used instead of a pref on X11 platforms because we start having 
  3502   // access to prefs long after the first call to XOpenDisplay which is hard to change due to 
  3503   // interdependencies in the initialization.
  3504 # ifndef NIGHTLY_BUILD
  3505   if (PR_GetEnv("MOZ_USE_OMTC") ||
  3506       PR_GetEnv("MOZ_OMTC_ENABLED"))
  3507 # endif
  3509     XInitThreads();
  3511 #endif
  3512 #if defined(MOZ_WIDGET_GTK)
  3513   mGdkDisplay = gdk_display_open(display_name);
  3514   if (!mGdkDisplay) {
  3515     PR_fprintf(PR_STDERR, "Error: cannot open display: %s\n", display_name);
  3516     return 1;
  3518   gdk_display_manager_set_default_display (gdk_display_manager_get(),
  3519                                            mGdkDisplay);
  3521   // g_set_application_name () is only defined in glib2.2 and higher.
  3522   _g_set_application_name_fn _g_set_application_name =
  3523     (_g_set_application_name_fn)FindFunction("g_set_application_name");
  3524   if (_g_set_application_name) {
  3525     _g_set_application_name(mAppData->name);
  3527   _gtk_window_set_auto_startup_notification_fn _gtk_window_set_auto_startup_notification =
  3528     (_gtk_window_set_auto_startup_notification_fn)FindFunction("gtk_window_set_auto_startup_notification");
  3529   if (_gtk_window_set_auto_startup_notification) {
  3530     _gtk_window_set_auto_startup_notification(false);
  3533 #if (MOZ_WIDGET_GTK == 2)
  3534   gtk_widget_set_default_colormap(gdk_rgb_get_colormap());
  3535 #endif /* (MOZ_WIDGET_GTK == 2) */
  3536 #endif /* defined(MOZ_WIDGET_GTK) */
  3537 #ifdef MOZ_X11
  3538   // Do this after initializing GDK, or GDK will install its own handler.
  3539   InstallX11ErrorHandler();
  3540 #endif
  3542   // Call the code to install our handler
  3543 #ifdef MOZ_JPROF
  3544   setupProfilingStuff();
  3545 #endif
  3547   rv = NS_CreateNativeAppSupport(getter_AddRefs(mNativeApp));
  3548   if (NS_FAILED(rv))
  3549     return 1;
  3551   bool canRun = false;
  3552   rv = mNativeApp->Start(&canRun);
  3553   if (NS_FAILED(rv) || !canRun) {
  3554     return 1;
  3557 #if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK)
  3558   // DESKTOP_STARTUP_ID is cleared now,
  3559   // we recover it in case we need a restart.
  3560   if (!mDesktopStartupID.IsEmpty()) {
  3561     nsAutoCString desktopStartupEnv;
  3562     desktopStartupEnv.AssignLiteral("DESKTOP_STARTUP_ID=");
  3563     desktopStartupEnv.Append(mDesktopStartupID);
  3564     // Leak it with extreme prejudice!
  3565     PR_SetEnv(ToNewCString(desktopStartupEnv));
  3567 #endif
  3569 #if defined(USE_MOZ_UPDATER)
  3570   // Check for and process any available updates
  3571   nsCOMPtr<nsIFile> updRoot;
  3572   bool persistent;
  3573   rv = mDirProvider.GetFile(XRE_UPDATE_ROOT_DIR, &persistent,
  3574                             getter_AddRefs(updRoot));
  3575   // XRE_UPDATE_ROOT_DIR may fail. Fallback to appDir if failed
  3576   if (NS_FAILED(rv))
  3577     updRoot = mDirProvider.GetAppDir();
  3579   // If the MOZ_PROCESS_UPDATES environment variable already exists, then
  3580   // we are being called from the callback application.
  3581   if (EnvHasValue("MOZ_PROCESS_UPDATES")) {
  3582     // If the caller has asked us to log our arguments, do so.  This is used
  3583     // to make sure that the maintenance service successfully launches the
  3584     // callback application.
  3585     const char *logFile = nullptr;
  3586     if (ARG_FOUND == CheckArg("dump-args", false, &logFile)) {
  3587       FILE* logFP = fopen(logFile, "wb");
  3588       if (logFP) {
  3589         for (int i = 1; i < gRestartArgc; ++i) {
  3590           fprintf(logFP, "%s\n", gRestartArgv[i]);
  3592         fclose(logFP);
  3595     *aExitFlag = true;
  3596     return 0;
  3599   // Support for processing an update and exiting. The MOZ_PROCESS_UPDATES
  3600   // environment variable will be part of the updater's environment and the
  3601   // application that is relaunched by the updater. When the application is
  3602   // relaunched by the updater it will be removed below and the application
  3603   // will exit.
  3604   if (CheckArg("process-updates")) {
  3605     SaveToEnv("MOZ_PROCESS_UPDATES=1");
  3607   nsCOMPtr<nsIFile> exeFile, exeDir;
  3608   rv = mDirProvider.GetFile(XRE_EXECUTABLE_FILE, &persistent,
  3609                             getter_AddRefs(exeFile));
  3610   NS_ENSURE_SUCCESS(rv, 1);
  3611   rv = exeFile->GetParent(getter_AddRefs(exeDir));
  3612   NS_ENSURE_SUCCESS(rv, 1);
  3613 #ifdef TOR_BROWSER_UPDATE
  3614   nsAutoCString compatVersion(TOR_BROWSER_VERSION);
  3615 #endif
  3616   ProcessUpdates(mDirProvider.GetGREDir(),
  3617                  exeDir,
  3618                  updRoot,
  3619                  gRestartArgc,
  3620                  gRestartArgv,
  3621 #ifdef TOR_BROWSER_UPDATE
  3622                  compatVersion.get()
  3623 #else
  3624                  mAppData->version
  3625 #endif
  3626                  );
  3627   if (EnvHasValue("MOZ_PROCESS_UPDATES")) {
  3628     SaveToEnv("MOZ_PROCESS_UPDATES=");
  3629     *aExitFlag = true;
  3630     return 0;
  3632 #if defined(XP_WIN) && defined(MOZ_METRO)
  3633   if (CheckArg("metro-update", false) == ARG_FOUND) {
  3634     *aExitFlag = true;
  3635     return 0;
  3637 #endif
  3638 #endif
  3640   rv = NS_NewToolkitProfileService(getter_AddRefs(mProfileSvc));
  3641   if (rv == NS_ERROR_FILE_ACCESS_DENIED) {
  3642     PR_fprintf(PR_STDERR, "Error: Access was denied while trying to open files in " \
  3643                 "your profile directory.\n");
  3645   if (NS_FAILED(rv)) {
  3646     // We failed to choose or create profile - notify user and quit
  3647     ProfileMissingDialog(mNativeApp);
  3648     return 1;
  3651   rv = SelectProfile(getter_AddRefs(mProfileLock), mProfileSvc, mNativeApp, &mStartOffline,
  3652                       &mProfileName);
  3653   if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ||
  3654       rv == NS_ERROR_ABORT) {
  3655     *aExitFlag = true;
  3656     return 0;
  3659   if (NS_FAILED(rv)) {
  3660     // We failed to choose or create profile - notify user and quit
  3661     ProfileMissingDialog(mNativeApp);
  3662     return 1;
  3664   gProfileLock = mProfileLock;
  3666   rv = mProfileLock->GetDirectory(getter_AddRefs(mProfD));
  3667   NS_ENSURE_SUCCESS(rv, 1);
  3669   rv = mProfileLock->GetLocalDirectory(getter_AddRefs(mProfLD));
  3670   NS_ENSURE_SUCCESS(rv, 1);
  3672   rv = mDirProvider.SetProfile(mProfD, mProfLD);
  3673   NS_ENSURE_SUCCESS(rv, 1);
  3675   //////////////////////// NOW WE HAVE A PROFILE ////////////////////////
  3677   mozilla::Telemetry::SetProfileDir(mProfD);
  3679 #ifdef MOZ_CRASHREPORTER
  3680   if (mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER)
  3681       MakeOrSetMinidumpPath(mProfD);
  3683   CrashReporter::UpdateCrashEventsDir();
  3684 #endif
  3686   nsAutoCString version;
  3687   BuildVersion(version);
  3689 #ifdef TARGET_OS_ABI
  3690   NS_NAMED_LITERAL_CSTRING(osABI, TARGET_OS_ABI);
  3691 #else
  3692   // No TARGET_XPCOM_ABI, but at least the OS is known
  3693   NS_NAMED_LITERAL_CSTRING(osABI, OS_TARGET "_UNKNOWN");
  3694 #endif
  3696   // Check for version compatibility with the last version of the app this 
  3697   // profile was started with.  The format of the version stamp is defined
  3698   // by the BuildVersion function.
  3699   // Also check to see if something has happened to invalidate our
  3700   // fastload caches, like an extension upgrade or installation.
  3702   // If we see .purgecaches, that means someone did a make. 
  3703   // Re-register components to catch potential changes.
  3704   nsCOMPtr<nsIFile> flagFile;
  3706   rv = NS_ERROR_FILE_NOT_FOUND;
  3707   nsCOMPtr<nsIFile> fFlagFile;
  3708   if (mAppData->directory) {
  3709     rv = mAppData->directory->Clone(getter_AddRefs(fFlagFile));
  3711   flagFile = do_QueryInterface(fFlagFile);
  3712   if (flagFile) {
  3713     flagFile->AppendNative(FILE_INVALIDATE_CACHES);
  3716   bool cachesOK;
  3717   bool versionOK = CheckCompatibility(mProfD, version, osABI, 
  3718                                       mDirProvider.GetGREDir(),
  3719                                       mAppData->directory, flagFile,
  3720                                       &cachesOK);
  3721   if (CheckArg("purgecaches")) {
  3722     cachesOK = false;
  3724   if (PR_GetEnv("MOZ_PURGE_CACHES")) {
  3725     cachesOK = false;
  3728   // Every time a profile is loaded by a build with a different version,
  3729   // it updates the compatibility.ini file saying what version last wrote
  3730   // the fastload caches.  On subsequent launches if the version matches, 
  3731   // there is no need for re-registration.  If the user loads the same
  3732   // profile in different builds the component registry must be
  3733   // re-generated to prevent mysterious component loading failures.
  3734   //
  3735   bool startupCacheValid = true;
  3736   if (gSafeMode) {
  3737     startupCacheValid = RemoveComponentRegistries(mProfD, mProfLD, false);
  3738     WriteVersion(mProfD, NS_LITERAL_CSTRING("Safe Mode"), osABI,
  3739                  mDirProvider.GetGREDir(), mAppData->directory, !startupCacheValid);
  3741   else if (versionOK) {
  3742     if (!cachesOK) {
  3743       // Remove caches, forcing component re-registration.
  3744       // The new list of additional components directories is derived from
  3745       // information in "extensions.ini".
  3746       startupCacheValid = RemoveComponentRegistries(mProfD, mProfLD, false);
  3748       // Rewrite compatibility.ini to remove the flag
  3749       WriteVersion(mProfD, version, osABI,
  3750                    mDirProvider.GetGREDir(), mAppData->directory, !startupCacheValid);
  3752     // Nothing need be done for the normal startup case.
  3754   else {
  3755     // Remove caches, forcing component re-registration
  3756     // with the default set of components (this disables any potentially
  3757     // troublesome incompatible XPCOM components). 
  3758     startupCacheValid = RemoveComponentRegistries(mProfD, mProfLD, true);
  3760     // Write out version
  3761     WriteVersion(mProfD, version, osABI,
  3762                  mDirProvider.GetGREDir(), mAppData->directory, !startupCacheValid);
  3765   if (!startupCacheValid)
  3766     StartupCache::IgnoreDiskCache();
  3768   if (flagFile) {
  3769     flagFile->Remove(true);
  3772   return 0;
  3775 /*
  3776  * XRE_mainRun - Command line startup, profile migration, and
  3777  * the calling of appStartup->Run().
  3778  */
  3779 nsresult
  3780 XREMain::XRE_mainRun()
  3782   nsresult rv = NS_OK;
  3783   NS_ASSERTION(mScopedXPCom, "Scoped xpcom not initialized.");
  3785 #ifdef NS_FUNCTION_TIMER
  3786   // initialize some common services, so we don't pay the cost for these at odd times later on;
  3787   // SetWindowCreator -> ChromeRegistry -> IOService -> SocketTransportService -> (nspr wspm init), Prefs
  3789     nsCOMPtr<nsISupports> comp;
  3791     comp = do_GetService("@mozilla.org/preferences-service;1");
  3793     comp = do_GetService("@mozilla.org/network/socket-transport-service;1");
  3795     comp = do_GetService("@mozilla.org/network/dns-service;1");
  3797     comp = do_GetService("@mozilla.org/network/io-service;1");
  3799     comp = do_GetService("@mozilla.org/chrome/chrome-registry;1");
  3801     comp = do_GetService("@mozilla.org/focus-event-suppressor-service;1");
  3803 #endif
  3805   rv = mScopedXPCom->SetWindowCreator(mNativeApp);
  3806   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  3808 #ifdef MOZ_CRASHREPORTER
  3809   // tell the crash reporter to also send the release channel
  3810   nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &rv);
  3811   if (NS_SUCCEEDED(rv)) {
  3812     nsCOMPtr<nsIPrefBranch> defaultPrefBranch;
  3813     rv = prefs->GetDefaultBranch(nullptr, getter_AddRefs(defaultPrefBranch));
  3815     if (NS_SUCCEEDED(rv)) {
  3816       nsXPIDLCString sval;
  3817       rv = defaultPrefBranch->GetCharPref("app.update.channel", getter_Copies(sval));
  3818       if (NS_SUCCEEDED(rv)) {
  3819         CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ReleaseChannel"),
  3820                                             sval);
  3824   // Needs to be set after xpcom initialization.
  3825   CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("FramePoisonBase"),
  3826                                      nsPrintfCString("%.16llx", uint64_t(gMozillaPoisonBase)));
  3827   CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("FramePoisonSize"),
  3828                                      nsPrintfCString("%lu", uint32_t(gMozillaPoisonSize)));
  3830 #ifdef XP_WIN
  3831   PR_CreateThread(PR_USER_THREAD, AnnotateSystemManufacturer_ThreadStart, 0,
  3832                   PR_PRIORITY_LOW, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0);
  3833 #endif
  3835 #endif
  3837   if (mStartOffline) {
  3838     nsCOMPtr<nsIIOService2> io (do_GetService("@mozilla.org/network/io-service;1"));
  3839     NS_ENSURE_TRUE(io, NS_ERROR_FAILURE);
  3840     io->SetManageOfflineStatus(false);
  3841     io->SetOffline(true);
  3845     nsCOMPtr<nsIObserver> startupNotifier
  3846       (do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID, &rv));
  3847     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  3849     startupNotifier->Observe(nullptr, APPSTARTUP_TOPIC, nullptr);
  3852   nsCOMPtr<nsIAppStartup> appStartup
  3853     (do_GetService(NS_APPSTARTUP_CONTRACTID));
  3854   NS_ENSURE_TRUE(appStartup, NS_ERROR_FAILURE);
  3856   if (gDoMigration) {
  3857     nsCOMPtr<nsIFile> file;
  3858     mDirProvider.GetAppDir()->Clone(getter_AddRefs(file));
  3859     file->AppendNative(NS_LITERAL_CSTRING("override.ini"));
  3860     nsINIParser parser;
  3861     nsresult rv = parser.Init(file);
  3862     if (NS_SUCCEEDED(rv)) {
  3863       nsAutoCString buf;
  3864       rv = parser.GetString("XRE", "EnableProfileMigrator", buf);
  3865       if (NS_SUCCEEDED(rv)) {
  3866         if (buf[0] == '0' || buf[0] == 'f' || buf[0] == 'F') {
  3867           gDoMigration = false;
  3874     nsCOMPtr<nsIToolkitProfile> selectedProfile;
  3875     if (gDoProfileReset) {
  3876       // At this point we can be sure that profile reset is happening on the default profile.
  3877       rv = mProfileSvc->GetSelectedProfile(getter_AddRefs(selectedProfile));
  3878       if (NS_FAILED(rv)) {
  3879         gDoProfileReset = false;
  3880         return NS_ERROR_FAILURE;
  3884     // Profile Migration
  3885     if (mAppData->flags & NS_XRE_ENABLE_PROFILE_MIGRATOR && gDoMigration) {
  3886       gDoMigration = false;
  3887       nsCOMPtr<nsIProfileMigrator> pm(do_CreateInstance(NS_PROFILEMIGRATOR_CONTRACTID));
  3888       if (pm) {
  3889         nsAutoCString aKey;
  3890         if (gDoProfileReset) {
  3891           // Automatically migrate from the current application if we just
  3892           // reset the profile.
  3893           aKey = MOZ_APP_NAME;
  3895         pm->Migrate(&mDirProvider, aKey);
  3899     if (gDoProfileReset) {
  3900       nsresult backupCreated = ProfileResetCleanup(selectedProfile);
  3901       if (NS_FAILED(backupCreated)) NS_WARNING("Could not cleanup the profile that was reset");
  3903       // Set the new profile as the default after we're done cleaning up the old default.
  3904       rv = SetCurrentProfileAsDefault(mProfileSvc, mProfD);
  3905       if (NS_FAILED(rv)) NS_WARNING("Could not set current profile as the default");
  3909   mDirProvider.DoStartup();
  3911 #ifdef MOZ_CRASHREPORTER
  3912   nsCString userAgentLocale;
  3913   if (NS_SUCCEEDED(Preferences::GetCString("general.useragent.locale", &userAgentLocale))) {
  3914     CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("useragent_locale"), userAgentLocale);
  3916 #endif
  3918   appStartup->GetShuttingDown(&mShuttingDown);
  3920   nsCOMPtr<nsICommandLineRunner> cmdLine;
  3922   nsCOMPtr<nsIFile> workingDir;
  3923   rv = NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR, getter_AddRefs(workingDir));
  3924   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  3926   if (!mShuttingDown) {
  3927     cmdLine = do_CreateInstance("@mozilla.org/toolkit/command-line;1");
  3928     NS_ENSURE_TRUE(cmdLine, NS_ERROR_FAILURE);
  3930     rv = cmdLine->Init(gArgc, gArgv, workingDir,
  3931                        nsICommandLine::STATE_INITIAL_LAUNCH);
  3932     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  3934     /* Special-case services that need early access to the command
  3935         line. */
  3936     nsCOMPtr<nsIObserverService> obsService =
  3937       mozilla::services::GetObserverService();
  3938     if (obsService) {
  3939       obsService->NotifyObservers(cmdLine, "command-line-startup", nullptr);
  3943   SaveStateForAppInitiatedRestart();
  3945   // clear out any environment variables which may have been set 
  3946   // during the relaunch process now that we know we won't be relaunching.
  3947   SaveToEnv("XRE_PROFILE_PATH=");
  3948   SaveToEnv("XRE_PROFILE_LOCAL_PATH=");
  3949   SaveToEnv("XRE_PROFILE_NAME=");
  3950   SaveToEnv("XRE_START_OFFLINE=");
  3951   SaveToEnv("NO_EM_RESTART=");
  3952   SaveToEnv("XUL_APP_FILE=");
  3953   SaveToEnv("XRE_BINARY_PATH=");
  3955   if (!mShuttingDown) {
  3956     rv = appStartup->CreateHiddenWindow();
  3957     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  3959 #if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK)
  3960     nsGTKToolkit* toolkit = nsGTKToolkit::GetToolkit();
  3961     if (toolkit && !mDesktopStartupID.IsEmpty()) {
  3962       toolkit->SetDesktopStartupID(mDesktopStartupID);
  3964     // Clear the environment variable so it won't be inherited by
  3965     // child processes and confuse things.
  3966     g_unsetenv ("DESKTOP_STARTUP_ID");
  3967 #endif
  3969 #ifdef XP_MACOSX
  3970     // Set up ability to respond to system (Apple) events. This must be
  3971     // done before setting up the command line service.
  3972     SetupMacApplicationDelegate();
  3974     // we re-initialize the command-line service and do appleevents munging
  3975     // after we are sure that we're not restarting
  3976     cmdLine = do_CreateInstance("@mozilla.org/toolkit/command-line;1");
  3977     NS_ENSURE_TRUE(cmdLine, NS_ERROR_FAILURE);
  3979     CommandLineServiceMac::SetupMacCommandLine(gArgc, gArgv, false);
  3981     rv = cmdLine->Init(gArgc, gArgv,
  3982                         workingDir, nsICommandLine::STATE_INITIAL_LAUNCH);
  3983     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  3984 #endif
  3986     nsCOMPtr<nsIObserverService> obsService =
  3987       mozilla::services::GetObserverService();
  3988     if (obsService)
  3989       obsService->NotifyObservers(nullptr, "final-ui-startup", nullptr);
  3991     (void)appStartup->DoneStartingUp();
  3992     appStartup->GetShuttingDown(&mShuttingDown);
  3995   if (!mShuttingDown) {
  3996     rv = cmdLine->Run();
  3997     NS_ENSURE_SUCCESS_LOG(rv, NS_ERROR_FAILURE);
  3999     appStartup->GetShuttingDown(&mShuttingDown);
  4002   if (!mShuttingDown) {
  4003 #ifdef MOZ_ENABLE_XREMOTE
  4004     // if we have X remote support, start listening for requests on the
  4005     // proxy window.
  4006     if (!mDisableRemote)
  4007       mRemoteService = do_GetService("@mozilla.org/toolkit/remote-service;1");
  4008     if (mRemoteService)
  4009       mRemoteService->Startup(mAppData->name, mProfileName.get());
  4010 #endif /* MOZ_ENABLE_XREMOTE */
  4012     mNativeApp->Enable();
  4015 #ifdef MOZ_INSTRUMENT_EVENT_LOOP
  4016   if (PR_GetEnv("MOZ_INSTRUMENT_EVENT_LOOP") || profiler_is_active()) {
  4017     bool logToConsole = !!PR_GetEnv("MOZ_INSTRUMENT_EVENT_LOOP");
  4018     mozilla::InitEventTracing(logToConsole);
  4020 #endif /* MOZ_INSTRUMENT_EVENT_LOOP */
  4023     rv = appStartup->Run();
  4024     if (NS_FAILED(rv)) {
  4025       NS_ERROR("failed to run appstartup");
  4026       gLogConsoleErrors = true;
  4030   return rv;
  4033 /*
  4034  * XRE_main - A class based main entry point used by most platforms.
  4035  */
  4036 int
  4037 XREMain::XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
  4039   char aLocal;
  4040   GeckoProfilerInitRAII profilerGuard(&aLocal);
  4041   PROFILER_LABEL("Startup", "XRE_Main");
  4043   mozilla::IOInterposerInit ioInterposerGuard;
  4045   nsresult rv = NS_OK;
  4047   gArgc = argc;
  4048   gArgv = argv;
  4050   NS_ENSURE_TRUE(aAppData, 2);
  4052   mAppData = new ScopedAppData(aAppData);
  4053   if (!mAppData)
  4054     return 1;
  4055   // used throughout this file
  4056   gAppData = mAppData;
  4058   ScopedLogging log;
  4060 #if defined(MOZ_WIDGET_GTK)
  4061 #if defined(MOZ_MEMORY) || defined(__FreeBSD__) || defined(__NetBSD__)
  4062   // Disable the slice allocator, since jemalloc already uses similar layout
  4063   // algorithms, and using a sub-allocator tends to increase fragmentation.
  4064   // This must be done before g_thread_init() is called.
  4065   g_slice_set_config(G_SLICE_CONFIG_ALWAYS_MALLOC, 1);
  4066 #endif
  4067   g_thread_init(nullptr);
  4068 #endif
  4070   // init
  4071   bool exit = false;
  4072   int result = XRE_mainInit(&exit);
  4073   if (result != 0 || exit)
  4074     return result;
  4076   // startup
  4077   result = XRE_mainStartup(&exit);
  4078   if (result != 0 || exit)
  4079     return result;
  4081   bool appInitiatedRestart = false;
  4083   // Start the real application
  4084   mScopedXPCom = new ScopedXPCOMStartup();
  4085   if (!mScopedXPCom)
  4086     return 1;
  4088   rv = mScopedXPCom->Initialize();
  4089   NS_ENSURE_SUCCESS(rv, 1);
  4091   // run!
  4092   rv = XRE_mainRun();
  4094 #ifdef MOZ_INSTRUMENT_EVENT_LOOP
  4095   mozilla::ShutdownEventTracing();
  4096 #endif
  4098   // Check for an application initiated restart.  This is one that
  4099   // corresponds to nsIAppStartup.quit(eRestart)
  4100   if (rv == NS_SUCCESS_RESTART_APP || rv == NS_SUCCESS_RESTART_METRO_APP) {
  4101     appInitiatedRestart = true;
  4103     // We have an application restart don't do any shutdown checks here
  4104     // In particular we don't want to poison IO for checking late-writes.
  4105     gShutdownChecks = SCM_NOTHING;
  4108   if (!mShuttingDown) {
  4109 #ifdef MOZ_ENABLE_XREMOTE
  4110     // shut down the x remote proxy window
  4111     if (mRemoteService) {
  4112       mRemoteService->Shutdown();
  4114 #endif /* MOZ_ENABLE_XREMOTE */
  4117   delete mScopedXPCom;
  4118   mScopedXPCom = nullptr;
  4120   // unlock the profile after ScopedXPCOMStartup object (xpcom) 
  4121   // has gone out of scope.  see bug #386739 for more details
  4122   mProfileLock->Unlock();
  4123   gProfileLock = nullptr;
  4125 #if defined(MOZ_WIDGET_QT)
  4126   nsQAppInstance::Release();
  4127 #endif
  4129   // Restart the app after XPCOM has been shut down cleanly. 
  4130   if (appInitiatedRestart) {
  4131     RestoreStateForAppInitiatedRestart();
  4133     // Ensure that these environment variables are set:
  4134     SaveFileToEnvIfUnset("XRE_PROFILE_PATH", mProfD);
  4135     SaveFileToEnvIfUnset("XRE_PROFILE_LOCAL_PATH", mProfLD);
  4136     SaveWordToEnvIfUnset("XRE_PROFILE_NAME", mProfileName);
  4138 #ifdef MOZ_WIDGET_GTK
  4139     MOZ_gdk_display_close(mGdkDisplay);
  4140 #endif
  4142 #if defined(MOZ_METRO) && defined(XP_WIN)
  4143     if (rv == NS_SUCCESS_RESTART_METRO_APP) {
  4144       LaunchDefaultMetroBrowser();
  4145       rv = NS_OK;
  4146     } else
  4147 #endif
  4149       rv = LaunchChild(mNativeApp, true);
  4152 #ifdef MOZ_CRASHREPORTER
  4153     if (mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER)
  4154       CrashReporter::UnsetExceptionHandler();
  4155 #endif
  4156     return rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ? 0 : 1;
  4159 #ifdef MOZ_WIDGET_GTK
  4160   // gdk_display_close also calls gdk_display_manager_set_default_display
  4161   // appropriately when necessary.
  4162   MOZ_gdk_display_close(mGdkDisplay);
  4163 #endif
  4165 #ifdef MOZ_CRASHREPORTER
  4166   if (mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER)
  4167       CrashReporter::UnsetExceptionHandler();
  4168 #endif
  4170   XRE_DeinitCommandLine();
  4172   return NS_FAILED(rv) ? 1 : 0;
  4175 #if defined(MOZ_METRO) && defined(XP_WIN)
  4176 extern bool XRE_MetroCoreApplicationRun();
  4177 static XREMain* xreMainPtr;
  4179 // must be called by the thread we want as the main thread
  4180 nsresult
  4181 XRE_metroStartup(bool runXREMain)
  4183   nsresult rv;
  4185   bool exit = false;
  4186   if (xreMainPtr->XRE_mainStartup(&exit) != 0 || exit)
  4187     return NS_ERROR_FAILURE;
  4189   // Start the real application
  4190   xreMainPtr->mScopedXPCom = new ScopedXPCOMStartup();
  4191   if (!xreMainPtr->mScopedXPCom)
  4192     return NS_ERROR_FAILURE;
  4194   rv = xreMainPtr->mScopedXPCom->Initialize();
  4195   NS_ENSURE_SUCCESS(rv, rv);
  4197   if (runXREMain) {
  4198     rv = xreMainPtr->XRE_mainRun();
  4199     NS_ENSURE_SUCCESS(rv, rv);
  4201   return NS_OK;
  4204 void
  4205 XRE_metroShutdown()
  4207   delete xreMainPtr->mScopedXPCom;
  4208   xreMainPtr->mScopedXPCom = nullptr;
  4210 #ifdef MOZ_INSTRUMENT_EVENT_LOOP
  4211   mozilla::ShutdownEventTracing();
  4212 #endif
  4214   // unlock the profile after ScopedXPCOMStartup object (xpcom) 
  4215   // has gone out of scope.  see bug #386739 for more details
  4216   xreMainPtr->mProfileLock->Unlock();
  4217   gProfileLock = nullptr;
  4219 #ifdef MOZ_CRASHREPORTER
  4220   if (xreMainPtr->mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER)
  4221       CrashReporter::UnsetExceptionHandler();
  4222 #endif
  4224   XRE_DeinitCommandLine();
  4227 class WinRTInitWrapper
  4229 public:
  4230   WinRTInitWrapper() {
  4231     mResult = ::RoInitialize(RO_INIT_MULTITHREADED);
  4233   ~WinRTInitWrapper() {
  4234     if (SUCCEEDED(mResult)) {
  4235       ::RoUninitialize();
  4238   HRESULT mResult;
  4239 };
  4241 int
  4242 XRE_mainMetro(int argc, char* argv[], const nsXREAppData* aAppData)
  4244   char aLocal;
  4245   GeckoProfilerInitRAII profilerGuard(&aLocal);
  4246   PROFILER_LABEL("Startup", "XRE_Main");
  4248   mozilla::IOInterposerInit ioInterposerGuard;
  4250   nsresult rv = NS_OK;
  4252   xreMainPtr = new XREMain();
  4253   if (!xreMainPtr) {
  4254     return 1;
  4257   // Inits Winrt and COM underneath it.
  4258   WinRTInitWrapper wrap;
  4260   gArgc = argc;
  4261   gArgv = argv;
  4263   NS_ENSURE_TRUE(aAppData, 2);
  4265   xreMainPtr->mAppData = new ScopedAppData(aAppData);
  4266   if (!xreMainPtr->mAppData)
  4267     return 1;
  4268   // used throughout this file
  4269   gAppData = xreMainPtr->mAppData;
  4271   ScopedLogging log;
  4273   // init
  4274   bool exit = false;
  4275   if (xreMainPtr->XRE_mainInit(&exit) != 0 || exit)
  4276     return 1;
  4278   // Located in widget, will call back into XRE_metroStartup and
  4279   // XRE_metroShutdown above.
  4280   if (!XRE_MetroCoreApplicationRun()) {
  4281     return 1;
  4284   // XRE_metroShutdown should have already been called on the worker
  4285   // thread that called XRE_metroStartup.
  4286   NS_ASSERTION(!xreMainPtr->mScopedXPCom,
  4287                "XPCOM Shutdown hasn't occured, and we are exiting.");
  4288   return 0;
  4291 void SetWindowsEnvironment(WindowsEnvironmentType aEnvID);
  4292 #endif // MOZ_METRO || !defined(XP_WIN)
  4294 void
  4295 XRE_StopLateWriteChecks(void) {
  4296   mozilla::StopLateWriteChecks();
  4299 int
  4300 XRE_main(int argc, char* argv[], const nsXREAppData* aAppData, uint32_t aFlags)
  4302 #if !defined(MOZ_METRO) || !defined(XP_WIN)
  4303   XREMain main;
  4304   int result = main.XRE_main(argc, argv, aAppData);
  4305   mozilla::RecordShutdownEndTimeStamp();
  4306   return result;
  4307 #else
  4308   if (aFlags == XRE_MAIN_FLAG_USE_METRO) {
  4309     SetWindowsEnvironment(WindowsEnvironmentType_Metro);
  4312   // Desktop
  4313   if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop) {
  4314     XREMain main;
  4315     int result = main.XRE_main(argc, argv, aAppData);
  4316     mozilla::RecordShutdownEndTimeStamp();
  4317     return result;
  4320   // Metro
  4321   NS_ASSERTION(XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Metro,
  4322                "Unknown Windows environment");
  4324   SetLastWinRunType(AHE_IMMERSIVE);
  4326   int result = XRE_mainMetro(argc, argv, aAppData);
  4327   mozilla::RecordShutdownEndTimeStamp();
  4328   return result;
  4329 #endif // MOZ_METRO || !defined(XP_WIN)
  4332 nsresult
  4333 XRE_InitCommandLine(int aArgc, char* aArgv[])
  4335   nsresult rv = NS_OK;
  4337 #if defined(OS_WIN)
  4338   CommandLine::Init(aArgc, aArgv);
  4339 #else
  4341   // these leak on error, but that's OK: we'll just exit()
  4342   char** canonArgs = new char*[aArgc];
  4344   // get the canonical version of the binary's path
  4345   nsCOMPtr<nsIFile> binFile;
  4346   rv = XRE_GetBinaryPath(aArgv[0], getter_AddRefs(binFile));
  4347   if (NS_FAILED(rv))
  4348     return NS_ERROR_FAILURE;
  4350   nsAutoCString canonBinPath;
  4351   rv = binFile->GetNativePath(canonBinPath);
  4352   if (NS_FAILED(rv))
  4353     return NS_ERROR_FAILURE;
  4355   canonArgs[0] = strdup(canonBinPath.get());
  4357   for (int i = 1; i < aArgc; ++i) {
  4358     if (aArgv[i]) {
  4359       canonArgs[i] = strdup(aArgv[i]);
  4363   NS_ASSERTION(!CommandLine::IsInitialized(), "Bad news!");
  4364   CommandLine::Init(aArgc, canonArgs);
  4366   for (int i = 0; i < aArgc; ++i)
  4367       free(canonArgs[i]);
  4368   delete[] canonArgs;
  4369 #endif
  4371   const char *path = nullptr;
  4372   ArgResult ar = CheckArg("greomni", false, &path);
  4373   if (ar == ARG_BAD) {
  4374     PR_fprintf(PR_STDERR, "Error: argument -greomni requires a path argument\n");
  4375     return NS_ERROR_FAILURE;
  4378   if (!path)
  4379     return rv;
  4381   nsCOMPtr<nsIFile> greOmni;
  4382   rv = XRE_GetFileFromPath(path, getter_AddRefs(greOmni));
  4383   if (NS_FAILED(rv)) {
  4384     PR_fprintf(PR_STDERR, "Error: argument -greomni requires a valid path\n");
  4385     return rv;
  4388   ar = CheckArg("appomni", false, &path);
  4389   if (ar == ARG_BAD) {
  4390     PR_fprintf(PR_STDERR, "Error: argument -appomni requires a path argument\n");
  4391     return NS_ERROR_FAILURE;
  4394   nsCOMPtr<nsIFile> appOmni;
  4395   if (path) {
  4396       rv = XRE_GetFileFromPath(path, getter_AddRefs(appOmni));
  4397       if (NS_FAILED(rv)) {
  4398         PR_fprintf(PR_STDERR, "Error: argument -appomni requires a valid path\n");
  4399         return rv;
  4403   mozilla::Omnijar::Init(greOmni, appOmni);
  4404   return rv;
  4407 nsresult
  4408 XRE_DeinitCommandLine()
  4410   nsresult rv = NS_OK;
  4412   CommandLine::Terminate();
  4414   return rv;
  4417 GeckoProcessType
  4418 XRE_GetProcessType()
  4420   return mozilla::startup::sChildProcessType;
  4423 bool
  4424 mozilla::BrowserTabsRemote()
  4426   if (!gBrowserTabsRemoteInitialized) {
  4427     gBrowserTabsRemote = Preferences::GetBool("browser.tabs.remote", false);
  4428     gBrowserTabsRemoteInitialized = true;
  4431   return gBrowserTabsRemote;
  4434 void
  4435 SetupErrorHandling(const char* progname)
  4437 #ifdef XP_WIN
  4438   /* On Windows XPSP3 and Windows Vista if DEP is configured off-by-default
  4439      we still want DEP protection: enable it explicitly and programmatically.
  4441      This function is not available on WinXPSP2 so we dynamically load it.
  4442   */
  4444   HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll");
  4445   SetProcessDEPPolicyFunc _SetProcessDEPPolicy =
  4446     (SetProcessDEPPolicyFunc) GetProcAddress(kernel32, "SetProcessDEPPolicy");
  4447   if (_SetProcessDEPPolicy)
  4448     _SetProcessDEPPolicy(PROCESS_DEP_ENABLE);
  4449 #endif
  4451 #ifdef XP_WIN32
  4452   // Suppress the "DLL Foo could not be found" dialog, such that if dependent
  4453   // libraries (such as GDI+) are not preset, we gracefully fail to load those
  4454   // XPCOM components, instead of being ungraceful.
  4455   UINT realMode = SetErrorMode(0);
  4456   realMode |= SEM_FAILCRITICALERRORS;
  4457   // If XRE_NO_WINDOWS_CRASH_DIALOG is set, suppress displaying the "This
  4458   // application has crashed" dialog box.  This is mainly useful for
  4459   // automated testing environments, e.g. tinderbox, where there's no need
  4460   // for a dozen of the dialog boxes to litter the console
  4461   if (getenv("XRE_NO_WINDOWS_CRASH_DIALOG"))
  4462     realMode |= SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX;
  4464   SetErrorMode(realMode);
  4466 #endif
  4468 #if defined (DEBUG) && defined(XP_WIN)
  4469   // Send MSCRT Warnings, Errors and Assertions to stderr.
  4470   // See http://msdn.microsoft.com/en-us/library/1y71x448(v=VS.80).aspx
  4471   // and http://msdn.microsoft.com/en-us/library/a68f826y(v=VS.80).aspx.
  4473   _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
  4474   _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
  4475   _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
  4476   _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
  4477   _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
  4478   _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
  4480   _CrtSetReportHook(MSCRTReportHook);
  4481 #endif
  4483   InstallSignalHandlers(progname);
  4485   // Unbuffer stdout, needed for tinderbox tests.
  4486   setbuf(stdout, 0);

mercurial