toolkit/xre/nsAppRunner.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/xre/nsAppRunner.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,4488 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#if defined(MOZ_WIDGET_QT)
    1.10 +#include <QGuiApplication>
    1.11 +#include <QStringList>
    1.12 +#include "nsQAppInstance.h"
    1.13 +#endif // MOZ_WIDGET_QT
    1.14 +
    1.15 +#include "mozilla/dom/ContentParent.h"
    1.16 +#include "mozilla/dom/ContentChild.h"
    1.17 +
    1.18 +#include "mozilla/ArrayUtils.h"
    1.19 +#include "mozilla/Attributes.h"
    1.20 +#include "mozilla/IOInterposer.h"
    1.21 +#include "mozilla/Likely.h"
    1.22 +#include "mozilla/Poison.h"
    1.23 +#include "mozilla/Preferences.h"
    1.24 +#include "mozilla/Telemetry.h"
    1.25 +
    1.26 +#include "nsAppRunner.h"
    1.27 +#include "mozilla/AppData.h"
    1.28 +#include "nsUpdateDriver.h"
    1.29 +#include "ProfileReset.h"
    1.30 +
    1.31 +#ifdef MOZ_INSTRUMENT_EVENT_LOOP
    1.32 +#include "EventTracer.h"
    1.33 +#endif
    1.34 +
    1.35 +#ifdef XP_MACOSX
    1.36 +#include "nsVersionComparator.h"
    1.37 +#include "MacLaunchHelper.h"
    1.38 +#include "MacApplicationDelegate.h"
    1.39 +#include "MacAutoreleasePool.h"
    1.40 +// these are needed for sysctl
    1.41 +#include <sys/types.h>
    1.42 +#include <sys/sysctl.h>
    1.43 +#endif
    1.44 +
    1.45 +#include "prmem.h"
    1.46 +#include "prnetdb.h"
    1.47 +#include "prprf.h"
    1.48 +#include "prproces.h"
    1.49 +#include "prenv.h"
    1.50 +
    1.51 +#include "nsIAppShellService.h"
    1.52 +#include "nsIAppStartup.h"
    1.53 +#include "nsIAppStartupNotifier.h"
    1.54 +#include "nsIMutableArray.h"
    1.55 +#include "nsICategoryManager.h"
    1.56 +#include "nsIChromeRegistry.h"
    1.57 +#include "nsICommandLineRunner.h"
    1.58 +#include "nsIComponentManager.h"
    1.59 +#include "nsIComponentRegistrar.h"
    1.60 +#include "nsIContentHandler.h"
    1.61 +#include "nsIDialogParamBlock.h"
    1.62 +#include "nsIDOMWindow.h"
    1.63 +#include "mozilla/ModuleUtils.h"
    1.64 +#include "nsIIOService2.h"
    1.65 +#include "nsIObserverService.h"
    1.66 +#include "nsINativeAppSupport.h"
    1.67 +#include "nsIProcess.h"
    1.68 +#include "nsIProfileUnlocker.h"
    1.69 +#include "nsIPromptService.h"
    1.70 +#include "nsIServiceManager.h"
    1.71 +#include "nsIStringBundle.h"
    1.72 +#include "nsISupportsPrimitives.h"
    1.73 +#include "nsIToolkitChromeRegistry.h"
    1.74 +#include "nsIToolkitProfile.h"
    1.75 +#include "nsIToolkitProfileService.h"
    1.76 +#include "nsIURI.h"
    1.77 +#include "nsIWindowCreator.h"
    1.78 +#include "nsIWindowMediator.h"
    1.79 +#include "nsIWindowWatcher.h"
    1.80 +#include "nsIXULAppInfo.h"
    1.81 +#include "nsIXULRuntime.h"
    1.82 +#include "nsPIDOMWindow.h"
    1.83 +#include "nsIBaseWindow.h"
    1.84 +#include "nsIWidget.h"
    1.85 +#include "nsIDocShell.h"
    1.86 +#include "nsAppShellCID.h"
    1.87 +#include "mozilla/scache/StartupCache.h"
    1.88 +
    1.89 +#include "mozilla/unused.h"
    1.90 +
    1.91 +#ifdef XP_WIN
    1.92 +#include "nsIWinAppHelper.h"
    1.93 +#include <windows.h>
    1.94 +#include "cairo/cairo-features.h"
    1.95 +#include "mozilla/WindowsVersion.h"
    1.96 +#ifdef MOZ_METRO
    1.97 +#include <roapi.h>
    1.98 +#endif
    1.99 +
   1.100 +#ifndef PROCESS_DEP_ENABLE
   1.101 +#define PROCESS_DEP_ENABLE 0x1
   1.102 +#endif
   1.103 +#endif
   1.104 +
   1.105 +#include "nsCRT.h"
   1.106 +#include "nsCOMPtr.h"
   1.107 +#include "nsDirectoryServiceDefs.h"
   1.108 +#include "nsDirectoryServiceUtils.h"
   1.109 +#include "nsEmbedCID.h"
   1.110 +#include "nsNetUtil.h"
   1.111 +#include "nsReadableUtils.h"
   1.112 +#include "nsXPCOM.h"
   1.113 +#include "nsXPCOMCIDInternal.h"
   1.114 +#include "nsXPIDLString.h"
   1.115 +#include "nsPrintfCString.h"
   1.116 +#include "nsVersionComparator.h"
   1.117 +
   1.118 +#include "nsAppDirectoryServiceDefs.h"
   1.119 +#include "nsXULAppAPI.h"
   1.120 +#include "nsXREDirProvider.h"
   1.121 +#include "nsToolkitCompsCID.h"
   1.122 +
   1.123 +#if defined(XP_WIN) && defined(MOZ_METRO)
   1.124 +#include "updatehelper.h"
   1.125 +#endif
   1.126 +
   1.127 +#include "nsINIParser.h"
   1.128 +#include "mozilla/Omnijar.h"
   1.129 +#include "mozilla/StartupTimeline.h"
   1.130 +#include "mozilla/LateWriteChecks.h"
   1.131 +
   1.132 +#include <stdlib.h>
   1.133 +
   1.134 +#ifdef XP_UNIX
   1.135 +#include <sys/stat.h>
   1.136 +#include <unistd.h>
   1.137 +#include <pwd.h>
   1.138 +#endif
   1.139 +
   1.140 +#ifdef XP_WIN
   1.141 +#include <process.h>
   1.142 +#include <shlobj.h>
   1.143 +#include "nsThreadUtils.h"
   1.144 +#include <comdef.h>
   1.145 +#include <wbemidl.h>
   1.146 +#endif
   1.147 +
   1.148 +#ifdef XP_MACOSX
   1.149 +#include "nsILocalFileMac.h"
   1.150 +#include "nsCommandLineServiceMac.h"
   1.151 +#endif
   1.152 +
   1.153 +// for X remote support
   1.154 +#ifdef MOZ_ENABLE_XREMOTE
   1.155 +#include "XRemoteClient.h"
   1.156 +#include "nsIRemoteService.h"
   1.157 +#endif
   1.158 +
   1.159 +#ifdef NS_TRACE_MALLOC
   1.160 +#include "nsTraceMalloc.h"
   1.161 +#endif
   1.162 +
   1.163 +#if defined(DEBUG) && defined(XP_WIN32)
   1.164 +#include <malloc.h>
   1.165 +#endif
   1.166 +
   1.167 +#if defined (XP_MACOSX)
   1.168 +#include <Carbon/Carbon.h>
   1.169 +#endif
   1.170 +
   1.171 +#ifdef DEBUG
   1.172 +#include "prlog.h"
   1.173 +#endif
   1.174 +
   1.175 +#ifdef MOZ_JPROF
   1.176 +#include "jprof.h"
   1.177 +#endif
   1.178 +
   1.179 +#ifdef MOZ_CRASHREPORTER
   1.180 +#include "nsExceptionHandler.h"
   1.181 +#include "nsICrashReporter.h"
   1.182 +#define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1"
   1.183 +#include "nsIPrefService.h"
   1.184 +#endif
   1.185 +
   1.186 +#include "base/command_line.h"
   1.187 +#ifdef MOZ_ENABLE_TESTS
   1.188 +#include "GTestRunner.h"
   1.189 +#endif
   1.190 +
   1.191 +#ifdef MOZ_WIDGET_ANDROID
   1.192 +#include "AndroidBridge.h"
   1.193 +#endif
   1.194 +
   1.195 +extern uint32_t gRestartMode;
   1.196 +extern void InstallSignalHandlers(const char *ProgramName);
   1.197 +#include "nsX11ErrorHandler.h"
   1.198 +
   1.199 +#define FILE_COMPATIBILITY_INFO NS_LITERAL_CSTRING("compatibility.ini")
   1.200 +#define FILE_INVALIDATE_CACHES NS_LITERAL_CSTRING(".purgecaches")
   1.201 +
   1.202 +int    gArgc;
   1.203 +char **gArgv;
   1.204 +
   1.205 +static const char gToolkitVersion[] = NS_STRINGIFY(GRE_MILESTONE);
   1.206 +static const char gToolkitBuildID[] = NS_STRINGIFY(GRE_BUILDID);
   1.207 +
   1.208 +static nsIProfileLock* gProfileLock;
   1.209 +
   1.210 +int    gRestartArgc;
   1.211 +char **gRestartArgv;
   1.212 +
   1.213 +#ifdef MOZ_WIDGET_QT
   1.214 +static int    gQtOnlyArgc;
   1.215 +static char **gQtOnlyArgv;
   1.216 +#endif
   1.217 +
   1.218 +#if defined(MOZ_WIDGET_GTK)
   1.219 +#if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING) \
   1.220 +  || defined(NS_TRACE_MALLOC)
   1.221 +#define CLEANUP_MEMORY 1
   1.222 +#define PANGO_ENABLE_BACKEND
   1.223 +#include <pango/pangofc-fontmap.h>
   1.224 +#endif
   1.225 +#include <gtk/gtk.h>
   1.226 +#ifdef MOZ_X11
   1.227 +#include <gdk/gdkx.h>
   1.228 +#endif /* MOZ_X11 */
   1.229 +#include "nsGTKToolkit.h"
   1.230 +#include <fontconfig/fontconfig.h>
   1.231 +#endif
   1.232 +#include "BinaryPath.h"
   1.233 +
   1.234 +#ifdef MOZ_LINKER
   1.235 +extern "C" MFBT_API bool IsSignalHandlingBroken();
   1.236 +#endif
   1.237 +
   1.238 +namespace mozilla {
   1.239 +int (*RunGTest)() = 0;
   1.240 +}
   1.241 +
   1.242 +using namespace mozilla;
   1.243 +using mozilla::unused;
   1.244 +using mozilla::scache::StartupCache;
   1.245 +using mozilla::dom::ContentParent;
   1.246 +using mozilla::dom::ContentChild;
   1.247 +
   1.248 +// Save literal putenv string to environment variable.
   1.249 +static void
   1.250 +SaveToEnv(const char *putenv)
   1.251 +{
   1.252 +  char *expr = strdup(putenv);
   1.253 +  if (expr)
   1.254 +    PR_SetEnv(expr);
   1.255 +  // We intentionally leak |expr| here since it is required by PR_SetEnv.
   1.256 +}
   1.257 +
   1.258 +// Tests that an environment variable exists and has a value
   1.259 +static bool
   1.260 +EnvHasValue(const char *name)
   1.261 +{
   1.262 +  const char *val = PR_GetEnv(name);
   1.263 +  return (val && *val);
   1.264 +}
   1.265 +
   1.266 +// Save the given word to the specified environment variable.
   1.267 +static void
   1.268 +SaveWordToEnv(const char *name, const nsACString & word)
   1.269 +{
   1.270 +  char *expr = PR_smprintf("%s=%s", name, PromiseFlatCString(word).get());
   1.271 +  if (expr)
   1.272 +    PR_SetEnv(expr);
   1.273 +  // We intentionally leak |expr| here since it is required by PR_SetEnv.
   1.274 +}
   1.275 +
   1.276 +// Save the path of the given file to the specified environment variable.
   1.277 +static void
   1.278 +SaveFileToEnv(const char *name, nsIFile *file)
   1.279 +{
   1.280 +#ifdef XP_WIN
   1.281 +  nsAutoString path;
   1.282 +  file->GetPath(path);
   1.283 +  SetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name).get(), path.get());
   1.284 +#else
   1.285 +  nsAutoCString path;
   1.286 +  file->GetNativePath(path);
   1.287 +  SaveWordToEnv(name, path);
   1.288 +#endif
   1.289 +}
   1.290 +
   1.291 +// Load the path of a file saved with SaveFileToEnv
   1.292 +static already_AddRefed<nsIFile>
   1.293 +GetFileFromEnv(const char *name)
   1.294 +{
   1.295 +  nsresult rv;
   1.296 +  nsCOMPtr<nsIFile> file;
   1.297 +
   1.298 +#ifdef XP_WIN
   1.299 +  WCHAR path[_MAX_PATH];
   1.300 +  if (!GetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name).get(),
   1.301 +                               path, _MAX_PATH))
   1.302 +    return nullptr;
   1.303 +
   1.304 +  rv = NS_NewLocalFile(nsDependentString(path), true, getter_AddRefs(file));
   1.305 +  if (NS_FAILED(rv))
   1.306 +    return nullptr;
   1.307 +
   1.308 +  return file.forget();
   1.309 +#else
   1.310 +  const char *arg = PR_GetEnv(name);
   1.311 +  if (!arg || !*arg)
   1.312 +    return nullptr;
   1.313 +
   1.314 +  rv = NS_NewNativeLocalFile(nsDependentCString(arg), true,
   1.315 +                             getter_AddRefs(file));
   1.316 +  if (NS_FAILED(rv))
   1.317 +    return nullptr;
   1.318 +
   1.319 +  return file.forget();
   1.320 +#endif
   1.321 +}
   1.322 +
   1.323 +// Save the path of the given word to the specified environment variable
   1.324 +// provided the environment variable does not have a value.
   1.325 +static void
   1.326 +SaveWordToEnvIfUnset(const char *name, const nsACString & word)
   1.327 +{
   1.328 +  if (!EnvHasValue(name))
   1.329 +    SaveWordToEnv(name, word);
   1.330 +}
   1.331 +
   1.332 +// Save the path of the given file to the specified environment variable
   1.333 +// provided the environment variable does not have a value.
   1.334 +static void
   1.335 +SaveFileToEnvIfUnset(const char *name, nsIFile *file)
   1.336 +{
   1.337 +  if (!EnvHasValue(name))
   1.338 +    SaveFileToEnv(name, file);
   1.339 +}
   1.340 +
   1.341 +static bool
   1.342 +strimatch(const char* lowerstr, const char* mixedstr)
   1.343 +{
   1.344 +  while(*lowerstr) {
   1.345 +    if (!*mixedstr) return false; // mixedstr is shorter
   1.346 +    if (tolower(*mixedstr) != *lowerstr) return false; // no match
   1.347 +
   1.348 +    ++lowerstr;
   1.349 +    ++mixedstr;
   1.350 +  }
   1.351 +
   1.352 +  if (*mixedstr) return false; // lowerstr is shorter
   1.353 +
   1.354 +  return true;
   1.355 +}
   1.356 +
   1.357 +/**
   1.358 + * Output a string to the user.  This method is really only meant to be used to
   1.359 + * output last-ditch error messages designed for developers NOT END USERS.
   1.360 + *
   1.361 + * @param isError
   1.362 + *        Pass true to indicate severe errors.
   1.363 + * @param fmt
   1.364 + *        printf-style format string followed by arguments.
   1.365 + */
   1.366 +static void Output(bool isError, const char *fmt, ... )
   1.367 +{
   1.368 +  va_list ap;
   1.369 +  va_start(ap, fmt);
   1.370 +
   1.371 +#if defined(XP_WIN) && !MOZ_WINCONSOLE
   1.372 +  char *msg = PR_vsmprintf(fmt, ap);
   1.373 +  if (msg)
   1.374 +  {
   1.375 +    UINT flags = MB_OK;
   1.376 +    if (isError)
   1.377 +      flags |= MB_ICONERROR;
   1.378 +    else 
   1.379 +      flags |= MB_ICONINFORMATION;
   1.380 +
   1.381 +    wchar_t wide_msg[1024];
   1.382 +    MultiByteToWideChar(CP_ACP,
   1.383 +                        0,
   1.384 +                        msg,
   1.385 +                        -1,
   1.386 +                        wide_msg,
   1.387 +                        sizeof(wide_msg) / sizeof(wchar_t));
   1.388 +
   1.389 +    MessageBoxW(nullptr, wide_msg, L"XULRunner", flags);
   1.390 +    PR_smprintf_free(msg);
   1.391 +  }
   1.392 +#else
   1.393 +  vfprintf(stderr, fmt, ap);
   1.394 +#endif
   1.395 +
   1.396 +  va_end(ap);
   1.397 +}
   1.398 +
   1.399 +enum RemoteResult {
   1.400 +  REMOTE_NOT_FOUND  = 0,
   1.401 +  REMOTE_FOUND      = 1,
   1.402 +  REMOTE_ARG_BAD    = 2
   1.403 +};
   1.404 +
   1.405 +enum ArgResult {
   1.406 +  ARG_NONE  = 0,
   1.407 +  ARG_FOUND = 1,
   1.408 +  ARG_BAD   = 2 // you wanted a param, but there isn't one
   1.409 +};
   1.410 +
   1.411 +static void RemoveArg(char **argv)
   1.412 +{
   1.413 +  do {
   1.414 +    *argv = *(argv + 1);
   1.415 +    ++argv;
   1.416 +  } while (*argv);
   1.417 +
   1.418 +  --gArgc;
   1.419 +}
   1.420 +
   1.421 +/**
   1.422 + * Check for a commandline flag. If the flag takes a parameter, the
   1.423 + * parameter is returned in aParam. Flags may be in the form -arg or
   1.424 + * --arg (or /arg on win32).
   1.425 + *
   1.426 + * @param aArg the parameter to check. Must be lowercase.
   1.427 + * @param aCheckOSInt if true returns ARG_BAD if the osint argument is present
   1.428 + *        when aArg is also present.
   1.429 + * @param aParam if non-null, the -arg <data> will be stored in this pointer.
   1.430 + *        This is *not* allocated, but rather a pointer to the argv data.
   1.431 + * @param aRemArg if true, the argument is removed from the gArgv array.
   1.432 + */
   1.433 +static ArgResult
   1.434 +CheckArg(const char* aArg, bool aCheckOSInt = false, const char **aParam = nullptr, bool aRemArg = true)
   1.435 +{
   1.436 +  NS_ABORT_IF_FALSE(gArgv, "gArgv must be initialized before CheckArg()");
   1.437 +
   1.438 +  char **curarg = gArgv + 1; // skip argv[0]
   1.439 +  ArgResult ar = ARG_NONE;
   1.440 +
   1.441 +  while (*curarg) {
   1.442 +    char *arg = curarg[0];
   1.443 +
   1.444 +    if (arg[0] == '-'
   1.445 +#if defined(XP_WIN)
   1.446 +        || *arg == '/'
   1.447 +#endif
   1.448 +        ) {
   1.449 +      ++arg;
   1.450 +      if (*arg == '-')
   1.451 +        ++arg;
   1.452 +
   1.453 +      if (strimatch(aArg, arg)) {
   1.454 +        if (aRemArg)
   1.455 +          RemoveArg(curarg);
   1.456 +        if (!aParam) {
   1.457 +          ar = ARG_FOUND;
   1.458 +          break;
   1.459 +        }
   1.460 +
   1.461 +        if (*curarg) {
   1.462 +          if (**curarg == '-'
   1.463 +#if defined(XP_WIN)
   1.464 +              || **curarg == '/'
   1.465 +#endif
   1.466 +              )
   1.467 +            return ARG_BAD;
   1.468 +
   1.469 +          *aParam = *curarg;
   1.470 +          if (aRemArg)
   1.471 +            RemoveArg(curarg);
   1.472 +          ar = ARG_FOUND;
   1.473 +          break;
   1.474 +        }
   1.475 +        return ARG_BAD;
   1.476 +      }
   1.477 +    }
   1.478 +
   1.479 +    ++curarg;
   1.480 +  }
   1.481 +
   1.482 +  if (aCheckOSInt && ar == ARG_FOUND) {
   1.483 +    ArgResult arOSInt = CheckArg("osint");
   1.484 +    if (arOSInt == ARG_FOUND) {
   1.485 +      ar = ARG_BAD;
   1.486 +      PR_fprintf(PR_STDERR, "Error: argument -osint is invalid\n");
   1.487 +    }
   1.488 +  }
   1.489 +
   1.490 +  return ar;
   1.491 +}
   1.492 +
   1.493 +#if defined(XP_WIN)
   1.494 +/**
   1.495 + * Check for a commandline flag from the windows shell and remove it from the
   1.496 + * argv used when restarting. Flags MUST be in the form -arg.
   1.497 + *
   1.498 + * @param aArg the parameter to check. Must be lowercase.
   1.499 + */
   1.500 +static ArgResult
   1.501 +CheckArgShell(const char* aArg)
   1.502 +{
   1.503 +  char **curarg = gRestartArgv + 1; // skip argv[0]
   1.504 +
   1.505 +  while (*curarg) {
   1.506 +    char *arg = curarg[0];
   1.507 +
   1.508 +    if (arg[0] == '-') {
   1.509 +      ++arg;
   1.510 +
   1.511 +      if (strimatch(aArg, arg)) {
   1.512 +        do {
   1.513 +          *curarg = *(curarg + 1);
   1.514 +          ++curarg;
   1.515 +        } while (*curarg);
   1.516 +
   1.517 +        --gRestartArgc;
   1.518 +
   1.519 +        return ARG_FOUND;
   1.520 +      }
   1.521 +    }
   1.522 +
   1.523 +    ++curarg;
   1.524 +  }
   1.525 +
   1.526 +  return ARG_NONE;
   1.527 +}
   1.528 +
   1.529 +/**
   1.530 + * Enabled Native App Support to process DDE messages when the app needs to
   1.531 + * restart and the app has been launched by the Windows shell to open an url.
   1.532 + * When aWait is false this will process the DDE events manually. This prevents
   1.533 + * Windows from displaying an error message due to the DDE message not being
   1.534 + * acknowledged.
   1.535 + */
   1.536 +static void
   1.537 +ProcessDDE(nsINativeAppSupport* aNative, bool aWait)
   1.538 +{
   1.539 +  // When the app is launched by the windows shell the windows shell
   1.540 +  // expects the app to be available for DDE messages and if it isn't
   1.541 +  // windows displays an error dialog. To prevent the error the DDE server
   1.542 +  // is enabled and pending events are processed when the app needs to
   1.543 +  // restart after it was launched by the shell with the requestpending
   1.544 +  // argument. The requestpending pending argument is removed to
   1.545 +  // differentiate it from being launched when an app restart is not
   1.546 +  // required.
   1.547 +  ArgResult ar;
   1.548 +  ar = CheckArgShell("requestpending");
   1.549 +  if (ar == ARG_FOUND) {
   1.550 +    aNative->Enable(); // enable win32 DDE responses
   1.551 +    if (aWait) {
   1.552 +      nsIThread *thread = NS_GetCurrentThread();
   1.553 +      // This is just a guesstimate based on testing different values.
   1.554 +      // If count is 8 or less windows will display an error dialog.
   1.555 +      int32_t count = 20;
   1.556 +      while(--count >= 0) {
   1.557 +        NS_ProcessNextEvent(thread);
   1.558 +        PR_Sleep(PR_MillisecondsToInterval(1));
   1.559 +      }
   1.560 +    }
   1.561 +  }
   1.562 +}
   1.563 +#endif
   1.564 +
   1.565 +/**
   1.566 + * Determines if there is support for showing the profile manager
   1.567 + *
   1.568 + * @return true in all environments except for Windows Metro
   1.569 +*/
   1.570 +static bool
   1.571 +CanShowProfileManager()
   1.572 +{
   1.573 +#if defined(XP_WIN)
   1.574 +  return XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop;
   1.575 +#else
   1.576 +  return true;
   1.577 +#endif
   1.578 +}
   1.579 +
   1.580 +
   1.581 +bool gSafeMode = false;
   1.582 +
   1.583 +/**
   1.584 + * The nsXULAppInfo object implements nsIFactory so that it can be its own
   1.585 + * singleton.
   1.586 + */
   1.587 +class nsXULAppInfo : public nsIXULAppInfo,
   1.588 +#ifdef XP_WIN
   1.589 +                     public nsIWinAppHelper,
   1.590 +#endif
   1.591 +#ifdef MOZ_CRASHREPORTER
   1.592 +                     public nsICrashReporter,
   1.593 +#endif
   1.594 +                     public nsIXULRuntime
   1.595 +
   1.596 +{
   1.597 +public:
   1.598 +  MOZ_CONSTEXPR nsXULAppInfo() {}
   1.599 +  NS_DECL_ISUPPORTS_INHERITED
   1.600 +  NS_DECL_NSIXULAPPINFO
   1.601 +  NS_DECL_NSIXULRUNTIME
   1.602 +#ifdef MOZ_CRASHREPORTER
   1.603 +  NS_DECL_NSICRASHREPORTER
   1.604 +#endif
   1.605 +#ifdef XP_WIN
   1.606 +  NS_DECL_NSIWINAPPHELPER
   1.607 +#endif
   1.608 +};
   1.609 +
   1.610 +NS_INTERFACE_MAP_BEGIN(nsXULAppInfo)
   1.611 +  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULRuntime)
   1.612 +  NS_INTERFACE_MAP_ENTRY(nsIXULRuntime)
   1.613 +#ifdef XP_WIN
   1.614 +  NS_INTERFACE_MAP_ENTRY(nsIWinAppHelper)
   1.615 +#endif
   1.616 +#ifdef MOZ_CRASHREPORTER
   1.617 +  NS_INTERFACE_MAP_ENTRY(nsICrashReporter)
   1.618 +#endif
   1.619 +  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIXULAppInfo, gAppData || 
   1.620 +                                     XRE_GetProcessType() == GeckoProcessType_Content)
   1.621 +NS_INTERFACE_MAP_END
   1.622 +
   1.623 +NS_IMETHODIMP_(MozExternalRefCountType)
   1.624 +nsXULAppInfo::AddRef()
   1.625 +{
   1.626 +  return 1;
   1.627 +}
   1.628 +
   1.629 +NS_IMETHODIMP_(MozExternalRefCountType)
   1.630 +nsXULAppInfo::Release()
   1.631 +{
   1.632 +  return 1;
   1.633 +}
   1.634 +
   1.635 +NS_IMETHODIMP
   1.636 +nsXULAppInfo::GetVendor(nsACString& aResult)
   1.637 +{
   1.638 +  if (XRE_GetProcessType() == GeckoProcessType_Content) {
   1.639 +    return NS_ERROR_NOT_AVAILABLE;
   1.640 +  }
   1.641 +  aResult.Assign(gAppData->vendor);
   1.642 +
   1.643 +  return NS_OK;
   1.644 +}
   1.645 +
   1.646 +NS_IMETHODIMP
   1.647 +nsXULAppInfo::GetName(nsACString& aResult)
   1.648 +{
   1.649 +  if (XRE_GetProcessType() == GeckoProcessType_Content) {
   1.650 +    ContentChild* cc = ContentChild::GetSingleton();
   1.651 +    aResult = cc->GetAppInfo().name;
   1.652 +    return NS_OK;
   1.653 +  }
   1.654 +  aResult.Assign(gAppData->name);
   1.655 +
   1.656 +  return NS_OK;
   1.657 +}
   1.658 +
   1.659 +NS_IMETHODIMP
   1.660 +nsXULAppInfo::GetID(nsACString& aResult)
   1.661 +{
   1.662 +  if (XRE_GetProcessType() == GeckoProcessType_Content) {
   1.663 +    return NS_ERROR_NOT_AVAILABLE;
   1.664 +  }
   1.665 +  aResult.Assign(gAppData->ID);
   1.666 +
   1.667 +  return NS_OK;
   1.668 +}
   1.669 +
   1.670 +NS_IMETHODIMP
   1.671 +nsXULAppInfo::GetVersion(nsACString& aResult)
   1.672 +{
   1.673 +  if (XRE_GetProcessType() == GeckoProcessType_Content) {
   1.674 +    ContentChild* cc = ContentChild::GetSingleton();
   1.675 +    aResult = cc->GetAppInfo().version;
   1.676 +    return NS_OK;
   1.677 +  }
   1.678 +  aResult.Assign(gAppData->version);
   1.679 +
   1.680 +  return NS_OK;
   1.681 +}
   1.682 +
   1.683 +NS_IMETHODIMP
   1.684 +nsXULAppInfo::GetPlatformVersion(nsACString& aResult)
   1.685 +{
   1.686 +  aResult.Assign(gToolkitVersion);
   1.687 +
   1.688 +  return NS_OK;
   1.689 +}
   1.690 +
   1.691 +NS_IMETHODIMP
   1.692 +nsXULAppInfo::GetAppBuildID(nsACString& aResult)
   1.693 +{
   1.694 +  if (XRE_GetProcessType() == GeckoProcessType_Content) {
   1.695 +    ContentChild* cc = ContentChild::GetSingleton();
   1.696 +    aResult = cc->GetAppInfo().buildID;
   1.697 +    return NS_OK;
   1.698 +  }
   1.699 +  aResult.Assign(gAppData->buildID);
   1.700 +
   1.701 +  return NS_OK;
   1.702 +}
   1.703 +
   1.704 +NS_IMETHODIMP
   1.705 +nsXULAppInfo::GetPlatformBuildID(nsACString& aResult)
   1.706 +{
   1.707 +  aResult.Assign(gToolkitBuildID);
   1.708 +
   1.709 +  return NS_OK;
   1.710 +}
   1.711 +
   1.712 +NS_IMETHODIMP
   1.713 +nsXULAppInfo::GetUAName(nsACString& aResult)
   1.714 +{
   1.715 +  if (XRE_GetProcessType() == GeckoProcessType_Content) {
   1.716 +    ContentChild* cc = ContentChild::GetSingleton();
   1.717 +    aResult = cc->GetAppInfo().UAName;
   1.718 +    return NS_OK;
   1.719 +  }
   1.720 +  aResult.Assign(gAppData->UAName);
   1.721 +
   1.722 +  return NS_OK;
   1.723 +}
   1.724 +
   1.725 +NS_IMETHODIMP
   1.726 +nsXULAppInfo::GetLogConsoleErrors(bool *aResult)
   1.727 +{
   1.728 +  *aResult = gLogConsoleErrors;
   1.729 +  return NS_OK;
   1.730 +}
   1.731 +
   1.732 +NS_IMETHODIMP
   1.733 +nsXULAppInfo::SetLogConsoleErrors(bool aValue)
   1.734 +{
   1.735 +  gLogConsoleErrors = aValue;
   1.736 +  return NS_OK;
   1.737 +}
   1.738 +
   1.739 +NS_IMETHODIMP
   1.740 +nsXULAppInfo::GetInSafeMode(bool *aResult)
   1.741 +{
   1.742 +  *aResult = gSafeMode;
   1.743 +  return NS_OK;
   1.744 +}
   1.745 +
   1.746 +NS_IMETHODIMP
   1.747 +nsXULAppInfo::GetOS(nsACString& aResult)
   1.748 +{
   1.749 +  aResult.AssignLiteral(OS_TARGET);
   1.750 +  return NS_OK;
   1.751 +}
   1.752 +
   1.753 +NS_IMETHODIMP
   1.754 +nsXULAppInfo::GetXPCOMABI(nsACString& aResult)
   1.755 +{
   1.756 +#ifdef TARGET_XPCOM_ABI
   1.757 +  aResult.AssignLiteral(TARGET_XPCOM_ABI);
   1.758 +  return NS_OK;
   1.759 +#else
   1.760 +  return NS_ERROR_NOT_AVAILABLE;
   1.761 +#endif
   1.762 +}
   1.763 +
   1.764 +NS_IMETHODIMP
   1.765 +nsXULAppInfo::GetWidgetToolkit(nsACString& aResult)
   1.766 +{
   1.767 +  aResult.AssignLiteral(MOZ_WIDGET_TOOLKIT);
   1.768 +  return NS_OK;
   1.769 +}
   1.770 +
   1.771 +// Ensure that the GeckoProcessType enum, defined in xpcom/build/nsXULAppAPI.h,
   1.772 +// is synchronized with the const unsigned longs defined in
   1.773 +// xpcom/system/nsIXULRuntime.idl.
   1.774 +#define SYNC_ENUMS(a,b) \
   1.775 +  static_assert(nsIXULRuntime::PROCESS_TYPE_ ## a == \
   1.776 +                static_cast<int>(GeckoProcessType_ ## b), \
   1.777 +                "GeckoProcessType in nsXULAppAPI.h not synchronized with nsIXULRuntime.idl");
   1.778 +
   1.779 +SYNC_ENUMS(DEFAULT, Default)
   1.780 +SYNC_ENUMS(PLUGIN, Plugin)
   1.781 +SYNC_ENUMS(CONTENT, Content)
   1.782 +SYNC_ENUMS(IPDLUNITTEST, IPDLUnitTest)
   1.783 +
   1.784 +// .. and ensure that that is all of them:
   1.785 +static_assert(GeckoProcessType_IPDLUnitTest + 1 == GeckoProcessType_End,
   1.786 +              "Did not find the final GeckoProcessType");
   1.787 +
   1.788 +NS_IMETHODIMP
   1.789 +nsXULAppInfo::GetProcessType(uint32_t* aResult)
   1.790 +{
   1.791 +  NS_ENSURE_ARG_POINTER(aResult);
   1.792 +  *aResult = XRE_GetProcessType();
   1.793 +  return NS_OK;
   1.794 +}
   1.795 +
   1.796 +NS_IMETHODIMP
   1.797 +nsXULAppInfo::GetProcessID(uint32_t* aResult)
   1.798 +{
   1.799 +#ifdef XP_WIN
   1.800 +  *aResult = GetCurrentProcessId();
   1.801 +#else
   1.802 +  *aResult = getpid();
   1.803 +#endif
   1.804 +  return NS_OK;
   1.805 +}
   1.806 +
   1.807 +static bool gBrowserTabsRemote = false;
   1.808 +static bool gBrowserTabsRemoteInitialized = false;
   1.809 +
   1.810 +NS_IMETHODIMP
   1.811 +nsXULAppInfo::GetBrowserTabsRemote(bool* aResult)
   1.812 +{
   1.813 +  *aResult = BrowserTabsRemote();
   1.814 +  return NS_OK;
   1.815 +}
   1.816 +
   1.817 +NS_IMETHODIMP
   1.818 +nsXULAppInfo::EnsureContentProcess()
   1.819 +{
   1.820 +  if (XRE_GetProcessType() != GeckoProcessType_Default)
   1.821 +    return NS_ERROR_NOT_AVAILABLE;
   1.822 +
   1.823 +  nsRefPtr<ContentParent> unused = ContentParent::GetNewOrUsed();
   1.824 +  return NS_OK;
   1.825 +}
   1.826 +
   1.827 +NS_IMETHODIMP
   1.828 +nsXULAppInfo::InvalidateCachesOnRestart()
   1.829 +{
   1.830 +  nsCOMPtr<nsIFile> file;
   1.831 +  nsresult rv = NS_GetSpecialDirectory(NS_APP_PROFILE_DIR_STARTUP, 
   1.832 +                                       getter_AddRefs(file));
   1.833 +  if (NS_FAILED(rv))
   1.834 +    return rv;
   1.835 +  if (!file)
   1.836 +    return NS_ERROR_NOT_AVAILABLE;
   1.837 +  
   1.838 +  file->AppendNative(FILE_COMPATIBILITY_INFO);
   1.839 +
   1.840 +  nsINIParser parser;
   1.841 +  rv = parser.Init(file);
   1.842 +  if (NS_FAILED(rv)) {
   1.843 +    // This fails if compatibility.ini is not there, so we'll
   1.844 +    // flush the caches on the next restart anyways.
   1.845 +    return NS_OK;
   1.846 +  }
   1.847 +  
   1.848 +  nsAutoCString buf;
   1.849 +  rv = parser.GetString("Compatibility", "InvalidateCaches", buf);
   1.850 +  
   1.851 +  if (NS_FAILED(rv)) {
   1.852 +    PRFileDesc *fd = nullptr;
   1.853 +    file->OpenNSPRFileDesc(PR_RDWR | PR_APPEND, 0600, &fd);
   1.854 +    if (!fd) {
   1.855 +      NS_ERROR("could not create output stream");
   1.856 +      return NS_ERROR_NOT_AVAILABLE;
   1.857 +    }
   1.858 +    static const char kInvalidationHeader[] = NS_LINEBREAK "InvalidateCaches=1" NS_LINEBREAK;
   1.859 +    PR_Write(fd, kInvalidationHeader, sizeof(kInvalidationHeader) - 1);
   1.860 +    PR_Close(fd);
   1.861 +  }
   1.862 +  return NS_OK;
   1.863 +}
   1.864 +
   1.865 +NS_IMETHODIMP
   1.866 +nsXULAppInfo::GetReplacedLockTime(PRTime *aReplacedLockTime)
   1.867 +{
   1.868 +  if (!gProfileLock)
   1.869 +    return NS_ERROR_NOT_AVAILABLE;
   1.870 +  gProfileLock->GetReplacedLockTime(aReplacedLockTime);
   1.871 +  return NS_OK;
   1.872 +}
   1.873 +
   1.874 +NS_IMETHODIMP
   1.875 +nsXULAppInfo::GetLastRunCrashID(nsAString &aLastRunCrashID)
   1.876 +{
   1.877 +#ifdef MOZ_CRASHREPORTER
   1.878 +  CrashReporter::GetLastRunCrashID(aLastRunCrashID);
   1.879 +  return NS_OK;
   1.880 +#else
   1.881 +  return NS_ERROR_NOT_IMPLEMENTED;
   1.882 +#endif
   1.883 +}
   1.884 +
   1.885 +NS_IMETHODIMP
   1.886 +nsXULAppInfo::GetIsReleaseBuild(bool* aResult)
   1.887 +{
   1.888 +#ifdef RELEASE_BUILD
   1.889 +  *aResult = true;
   1.890 +#else
   1.891 +  *aResult = false;
   1.892 +#endif
   1.893 +  return NS_OK;
   1.894 +}
   1.895 +
   1.896 +NS_IMETHODIMP
   1.897 +nsXULAppInfo::GetIsOfficialBranding(bool* aResult)
   1.898 +{
   1.899 +#ifdef MOZ_OFFICIAL_BRANDING
   1.900 +  *aResult = true;
   1.901 +#else
   1.902 +  *aResult = false;
   1.903 +#endif
   1.904 +  return NS_OK;
   1.905 +}
   1.906 +
   1.907 +NS_IMETHODIMP
   1.908 +nsXULAppInfo::GetDefaultUpdateChannel(nsACString& aResult)
   1.909 +{
   1.910 +  aResult.AssignLiteral(NS_STRINGIFY(MOZ_UPDATE_CHANNEL));
   1.911 +  return NS_OK;
   1.912 +}
   1.913 +
   1.914 +NS_IMETHODIMP
   1.915 +nsXULAppInfo::GetDistributionID(nsACString& aResult)
   1.916 +{
   1.917 +  aResult.AssignLiteral(MOZ_DISTRIBUTION_ID);
   1.918 +  return NS_OK;
   1.919 +}
   1.920 +
   1.921 +#ifdef XP_WIN
   1.922 +// Matches the enum in WinNT.h for the Vista SDK but renamed so that we can
   1.923 +// safely build with the Vista SDK and without it.
   1.924 +typedef enum 
   1.925 +{
   1.926 +  VistaTokenElevationTypeDefault = 1,
   1.927 +  VistaTokenElevationTypeFull,
   1.928 +  VistaTokenElevationTypeLimited
   1.929 +} VISTA_TOKEN_ELEVATION_TYPE;
   1.930 +
   1.931 +// avoid collision with TokeElevationType enum in WinNT.h
   1.932 +// of the Vista SDK
   1.933 +#define VistaTokenElevationType static_cast< TOKEN_INFORMATION_CLASS >( 18 )
   1.934 +
   1.935 +NS_IMETHODIMP
   1.936 +nsXULAppInfo::GetUserCanElevate(bool *aUserCanElevate)
   1.937 +{
   1.938 +  HANDLE hToken;
   1.939 +
   1.940 +  VISTA_TOKEN_ELEVATION_TYPE elevationType;
   1.941 +  DWORD dwSize; 
   1.942 +
   1.943 +  if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken) ||
   1.944 +      !GetTokenInformation(hToken, VistaTokenElevationType, &elevationType,
   1.945 +                           sizeof(elevationType), &dwSize)) {
   1.946 +    *aUserCanElevate = false;
   1.947 +  } 
   1.948 +  else {
   1.949 +    // The possible values returned for elevationType and their meanings are:
   1.950 +    //   TokenElevationTypeDefault: The token does not have a linked token 
   1.951 +    //     (e.g. UAC disabled or a standard user, so they can't be elevated)
   1.952 +    //   TokenElevationTypeFull: The token is linked to an elevated token 
   1.953 +    //     (e.g. UAC is enabled and the user is already elevated so they can't
   1.954 +    //      be elevated again)
   1.955 +    //   TokenElevationTypeLimited: The token is linked to a limited token 
   1.956 +    //     (e.g. UAC is enabled and the user is not elevated, so they can be
   1.957 +    //      elevated)
   1.958 +    *aUserCanElevate = (elevationType == VistaTokenElevationTypeLimited);
   1.959 +  }
   1.960 +
   1.961 +  if (hToken)
   1.962 +    CloseHandle(hToken);
   1.963 +
   1.964 +  return NS_OK;
   1.965 +}
   1.966 +#endif
   1.967 +
   1.968 +#ifdef MOZ_CRASHREPORTER
   1.969 +NS_IMETHODIMP
   1.970 +nsXULAppInfo::GetEnabled(bool *aEnabled)
   1.971 +{
   1.972 +  *aEnabled = CrashReporter::GetEnabled();
   1.973 +  return NS_OK;
   1.974 +}
   1.975 +
   1.976 +NS_IMETHODIMP
   1.977 +nsXULAppInfo::SetEnabled(bool aEnabled)
   1.978 +{
   1.979 +  if (aEnabled) {
   1.980 +    if (CrashReporter::GetEnabled())
   1.981 +      // no point in erroring for double-enabling
   1.982 +      return NS_OK;
   1.983 +
   1.984 +    nsCOMPtr<nsIFile> xreDirectory;
   1.985 +    if (gAppData) {
   1.986 +      xreDirectory = gAppData->xreDirectory;
   1.987 +    }
   1.988 +    else {
   1.989 +      // We didn't get started through XRE_Main, probably
   1.990 +      nsCOMPtr<nsIFile> greDir;
   1.991 +      NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(greDir));
   1.992 +      if (!greDir)
   1.993 +        return NS_ERROR_FAILURE;
   1.994 +
   1.995 +      xreDirectory = do_QueryInterface(greDir);
   1.996 +      if (!xreDirectory)
   1.997 +        return NS_ERROR_FAILURE;
   1.998 +    }
   1.999 +    return CrashReporter::SetExceptionHandler(xreDirectory, true);
  1.1000 +  }
  1.1001 +  else {
  1.1002 +    if (!CrashReporter::GetEnabled())
  1.1003 +      // no point in erroring for double-disabling
  1.1004 +      return NS_OK;
  1.1005 +
  1.1006 +    return CrashReporter::UnsetExceptionHandler();
  1.1007 +  }
  1.1008 +}
  1.1009 +
  1.1010 +NS_IMETHODIMP
  1.1011 +nsXULAppInfo::GetServerURL(nsIURL** aServerURL)
  1.1012 +{
  1.1013 +  if (!CrashReporter::GetEnabled())
  1.1014 +    return NS_ERROR_NOT_INITIALIZED;
  1.1015 +
  1.1016 +  nsAutoCString data;
  1.1017 +  if (!CrashReporter::GetServerURL(data)) {
  1.1018 +    return NS_ERROR_FAILURE;
  1.1019 +  }
  1.1020 +  nsCOMPtr<nsIURI> uri;
  1.1021 +  NS_NewURI(getter_AddRefs(uri), data);
  1.1022 +  if (!uri)
  1.1023 +    return NS_ERROR_FAILURE;
  1.1024 +
  1.1025 +  nsCOMPtr<nsIURL> url;
  1.1026 +  url = do_QueryInterface(uri);
  1.1027 +  NS_ADDREF(*aServerURL = url);
  1.1028 +
  1.1029 +  return NS_OK;
  1.1030 +}
  1.1031 +
  1.1032 +NS_IMETHODIMP
  1.1033 +nsXULAppInfo::SetServerURL(nsIURL* aServerURL)
  1.1034 +{
  1.1035 +  bool schemeOk;
  1.1036 +  // only allow https or http URLs
  1.1037 +  nsresult rv = aServerURL->SchemeIs("https", &schemeOk);
  1.1038 +  NS_ENSURE_SUCCESS(rv, rv);
  1.1039 +  if (!schemeOk) {
  1.1040 +    rv = aServerURL->SchemeIs("http", &schemeOk);
  1.1041 +    NS_ENSURE_SUCCESS(rv, rv);
  1.1042 +
  1.1043 +    if (!schemeOk)
  1.1044 +      return NS_ERROR_INVALID_ARG;
  1.1045 +  }
  1.1046 +  nsAutoCString spec;
  1.1047 +  rv = aServerURL->GetSpec(spec);
  1.1048 +  NS_ENSURE_SUCCESS(rv, rv);
  1.1049 +  
  1.1050 +  return CrashReporter::SetServerURL(spec);
  1.1051 +}
  1.1052 +
  1.1053 +NS_IMETHODIMP
  1.1054 +nsXULAppInfo::GetMinidumpPath(nsIFile** aMinidumpPath)
  1.1055 +{
  1.1056 +  if (!CrashReporter::GetEnabled())
  1.1057 +    return NS_ERROR_NOT_INITIALIZED;
  1.1058 +
  1.1059 +  nsAutoString path;
  1.1060 +  if (!CrashReporter::GetMinidumpPath(path))
  1.1061 +    return NS_ERROR_FAILURE;
  1.1062 +
  1.1063 +  nsresult rv = NS_NewLocalFile(path, false, aMinidumpPath);
  1.1064 +  NS_ENSURE_SUCCESS(rv, rv);
  1.1065 +  return NS_OK;
  1.1066 +}
  1.1067 +
  1.1068 +NS_IMETHODIMP
  1.1069 +nsXULAppInfo::SetMinidumpPath(nsIFile* aMinidumpPath)
  1.1070 +{
  1.1071 +  nsAutoString path;
  1.1072 +  nsresult rv = aMinidumpPath->GetPath(path);
  1.1073 +  NS_ENSURE_SUCCESS(rv, rv);
  1.1074 +  return CrashReporter::SetMinidumpPath(path);
  1.1075 +}
  1.1076 +
  1.1077 +NS_IMETHODIMP
  1.1078 +nsXULAppInfo::AnnotateCrashReport(const nsACString& key,
  1.1079 +                                  const nsACString& data)
  1.1080 +{
  1.1081 +  return CrashReporter::AnnotateCrashReport(key, data);
  1.1082 +}
  1.1083 +
  1.1084 +NS_IMETHODIMP
  1.1085 +nsXULAppInfo::AppendAppNotesToCrashReport(const nsACString& data)
  1.1086 +{
  1.1087 +  return CrashReporter::AppendAppNotesToCrashReport(data);
  1.1088 +}
  1.1089 +
  1.1090 +NS_IMETHODIMP
  1.1091 +nsXULAppInfo::RegisterAppMemory(uint64_t pointer,
  1.1092 +                                uint64_t len)
  1.1093 +{
  1.1094 +  return CrashReporter::RegisterAppMemory((void *)pointer, len);
  1.1095 +}
  1.1096 +
  1.1097 +NS_IMETHODIMP
  1.1098 +nsXULAppInfo::WriteMinidumpForException(void* aExceptionInfo)
  1.1099 +{
  1.1100 +#ifdef XP_WIN32
  1.1101 +  return CrashReporter::WriteMinidumpForException(static_cast<EXCEPTION_POINTERS*>(aExceptionInfo));
  1.1102 +#else
  1.1103 +  return NS_ERROR_NOT_IMPLEMENTED;
  1.1104 +#endif
  1.1105 +}
  1.1106 +
  1.1107 +NS_IMETHODIMP
  1.1108 +nsXULAppInfo::AppendObjCExceptionInfoToAppNotes(void* aException)
  1.1109 +{
  1.1110 +#ifdef XP_MACOSX
  1.1111 +  return CrashReporter::AppendObjCExceptionInfoToAppNotes(aException);
  1.1112 +#else
  1.1113 +  return NS_ERROR_NOT_IMPLEMENTED;
  1.1114 +#endif
  1.1115 +}
  1.1116 +
  1.1117 +NS_IMETHODIMP
  1.1118 +nsXULAppInfo::GetSubmitReports(bool* aEnabled)
  1.1119 +{
  1.1120 +  return CrashReporter::GetSubmitReports(aEnabled);
  1.1121 +}
  1.1122 +
  1.1123 +NS_IMETHODIMP
  1.1124 +nsXULAppInfo::SetSubmitReports(bool aEnabled)
  1.1125 +{
  1.1126 +  return CrashReporter::SetSubmitReports(aEnabled);
  1.1127 +}
  1.1128 +
  1.1129 +NS_IMETHODIMP
  1.1130 +nsXULAppInfo::UpdateCrashEventsDir()
  1.1131 +{
  1.1132 +  CrashReporter::UpdateCrashEventsDir();
  1.1133 +  return NS_OK;
  1.1134 +}
  1.1135 +
  1.1136 +#endif
  1.1137 +
  1.1138 +static const nsXULAppInfo kAppInfo;
  1.1139 +static nsresult AppInfoConstructor(nsISupports* aOuter,
  1.1140 +                                   REFNSIID aIID, void **aResult)
  1.1141 +{
  1.1142 +  NS_ENSURE_NO_AGGREGATION(aOuter);
  1.1143 +
  1.1144 +  return const_cast<nsXULAppInfo*>(&kAppInfo)->
  1.1145 +    QueryInterface(aIID, aResult);
  1.1146 +}
  1.1147 +
  1.1148 +bool gLogConsoleErrors = false;
  1.1149 +
  1.1150 +#define NS_ENSURE_TRUE_LOG(x, ret)               \
  1.1151 +  PR_BEGIN_MACRO                                 \
  1.1152 +  if (MOZ_UNLIKELY(!(x))) {                      \
  1.1153 +    NS_WARNING("NS_ENSURE_TRUE(" #x ") failed"); \
  1.1154 +    gLogConsoleErrors = true;                    \
  1.1155 +    return ret;                                  \
  1.1156 +  }                                              \
  1.1157 +  PR_END_MACRO
  1.1158 +
  1.1159 +#define NS_ENSURE_SUCCESS_LOG(res, ret)          \
  1.1160 +  NS_ENSURE_TRUE_LOG(NS_SUCCEEDED(res), ret)
  1.1161 +
  1.1162 +/**
  1.1163 + * Because we're starting/stopping XPCOM several times in different scenarios,
  1.1164 + * this class is a stack-based critter that makes sure that XPCOM is shut down
  1.1165 + * during early returns.
  1.1166 + */
  1.1167 +
  1.1168 +class ScopedXPCOMStartup
  1.1169 +{
  1.1170 +public:
  1.1171 +  ScopedXPCOMStartup() :
  1.1172 +    mServiceManager(nullptr) { }
  1.1173 +  ~ScopedXPCOMStartup();
  1.1174 +
  1.1175 +  nsresult Initialize();
  1.1176 +  nsresult SetWindowCreator(nsINativeAppSupport* native);
  1.1177 +
  1.1178 +  static nsresult CreateAppSupport(nsISupports* aOuter, REFNSIID aIID, void** aResult);
  1.1179 +
  1.1180 +private:
  1.1181 +  nsIServiceManager* mServiceManager;
  1.1182 +  static nsINativeAppSupport* gNativeAppSupport;
  1.1183 +};
  1.1184 +
  1.1185 +ScopedXPCOMStartup::~ScopedXPCOMStartup()
  1.1186 +{
  1.1187 +  NS_IF_RELEASE(gNativeAppSupport);
  1.1188 +
  1.1189 +  if (mServiceManager) {
  1.1190 +#ifdef XP_MACOSX
  1.1191 +    // On OS X, we need a pool to catch cocoa objects that are autoreleased
  1.1192 +    // during teardown.
  1.1193 +    mozilla::MacAutoreleasePool pool;
  1.1194 +#endif
  1.1195 +
  1.1196 +    nsCOMPtr<nsIAppStartup> appStartup (do_GetService(NS_APPSTARTUP_CONTRACTID));
  1.1197 +    if (appStartup)
  1.1198 +      appStartup->DestroyHiddenWindow();
  1.1199 +
  1.1200 +    gDirServiceProvider->DoShutdown();
  1.1201 +    PROFILER_MARKER("Shutdown early");
  1.1202 +
  1.1203 +    WriteConsoleLog();
  1.1204 +
  1.1205 +    NS_ShutdownXPCOM(mServiceManager);
  1.1206 +    mServiceManager = nullptr;
  1.1207 +  }
  1.1208 +}
  1.1209 +
  1.1210 +// {95d89e3e-a169-41a3-8e56-719978e15b12}
  1.1211 +#define APPINFO_CID \
  1.1212 +  { 0x95d89e3e, 0xa169, 0x41a3, { 0x8e, 0x56, 0x71, 0x99, 0x78, 0xe1, 0x5b, 0x12 } }
  1.1213 +
  1.1214 +// {0C4A446C-EE82-41f2-8D04-D366D2C7A7D4}
  1.1215 +static const nsCID kNativeAppSupportCID =
  1.1216 +  { 0xc4a446c, 0xee82, 0x41f2, { 0x8d, 0x4, 0xd3, 0x66, 0xd2, 0xc7, 0xa7, 0xd4 } };
  1.1217 +
  1.1218 +// {5F5E59CE-27BC-47eb-9D1F-B09CA9049836}
  1.1219 +static const nsCID kProfileServiceCID =
  1.1220 +  { 0x5f5e59ce, 0x27bc, 0x47eb, { 0x9d, 0x1f, 0xb0, 0x9c, 0xa9, 0x4, 0x98, 0x36 } };
  1.1221 +
  1.1222 +static already_AddRefed<nsIFactory>
  1.1223 +ProfileServiceFactoryConstructor(const mozilla::Module& module, const mozilla::Module::CIDEntry& entry)
  1.1224 +{
  1.1225 +  nsCOMPtr<nsIFactory> factory;
  1.1226 +  NS_NewToolkitProfileFactory(getter_AddRefs(factory));
  1.1227 +  return factory.forget();
  1.1228 +}
  1.1229 +
  1.1230 +NS_DEFINE_NAMED_CID(APPINFO_CID);
  1.1231 +
  1.1232 +static const mozilla::Module::CIDEntry kXRECIDs[] = {
  1.1233 +  { &kAPPINFO_CID, false, nullptr, AppInfoConstructor },
  1.1234 +  { &kProfileServiceCID, false, ProfileServiceFactoryConstructor, nullptr },
  1.1235 +  { &kNativeAppSupportCID, false, nullptr, ScopedXPCOMStartup::CreateAppSupport },
  1.1236 +  { nullptr }
  1.1237 +};
  1.1238 +
  1.1239 +static const mozilla::Module::ContractIDEntry kXREContracts[] = {
  1.1240 +  { XULAPPINFO_SERVICE_CONTRACTID, &kAPPINFO_CID },
  1.1241 +  { XULRUNTIME_SERVICE_CONTRACTID, &kAPPINFO_CID },
  1.1242 +#ifdef MOZ_CRASHREPORTER
  1.1243 +  { NS_CRASHREPORTER_CONTRACTID, &kAPPINFO_CID },
  1.1244 +#endif
  1.1245 +  { NS_PROFILESERVICE_CONTRACTID, &kProfileServiceCID },
  1.1246 +  { NS_NATIVEAPPSUPPORT_CONTRACTID, &kNativeAppSupportCID },
  1.1247 +  { nullptr }
  1.1248 +};
  1.1249 +
  1.1250 +static const mozilla::Module kXREModule = {
  1.1251 +  mozilla::Module::kVersion,
  1.1252 +  kXRECIDs,
  1.1253 +  kXREContracts
  1.1254 +};
  1.1255 +
  1.1256 +NSMODULE_DEFN(Apprunner) = &kXREModule;
  1.1257 +
  1.1258 +nsresult
  1.1259 +ScopedXPCOMStartup::Initialize()
  1.1260 +{
  1.1261 +  NS_ASSERTION(gDirServiceProvider, "Should not get here!");
  1.1262 +
  1.1263 +  nsresult rv;
  1.1264 +
  1.1265 +  rv = NS_InitXPCOM2(&mServiceManager, gDirServiceProvider->GetAppDir(),
  1.1266 +                     gDirServiceProvider);
  1.1267 +  if (NS_FAILED(rv)) {
  1.1268 +    NS_ERROR("Couldn't start xpcom!");
  1.1269 +    mServiceManager = nullptr;
  1.1270 +  }
  1.1271 +  else {
  1.1272 +    nsCOMPtr<nsIComponentRegistrar> reg =
  1.1273 +      do_QueryInterface(mServiceManager);
  1.1274 +    NS_ASSERTION(reg, "Service Manager doesn't QI to Registrar.");
  1.1275 +  }
  1.1276 +
  1.1277 +  return rv;
  1.1278 +}
  1.1279 +
  1.1280 +/**
  1.1281 + * This is a little factory class that serves as a singleton-service-factory
  1.1282 + * for the nativeappsupport object.
  1.1283 + */
  1.1284 +class nsSingletonFactory MOZ_FINAL : public nsIFactory
  1.1285 +{
  1.1286 +public:
  1.1287 +  NS_DECL_ISUPPORTS
  1.1288 +  NS_DECL_NSIFACTORY
  1.1289 +
  1.1290 +  nsSingletonFactory(nsISupports* aSingleton);
  1.1291 +  ~nsSingletonFactory() { }
  1.1292 +
  1.1293 +private:
  1.1294 +  nsCOMPtr<nsISupports> mSingleton;
  1.1295 +};
  1.1296 +
  1.1297 +nsSingletonFactory::nsSingletonFactory(nsISupports* aSingleton)
  1.1298 +  : mSingleton(aSingleton)
  1.1299 +{
  1.1300 +  NS_ASSERTION(mSingleton, "Singleton was null!");
  1.1301 +}
  1.1302 +
  1.1303 +NS_IMPL_ISUPPORTS(nsSingletonFactory, nsIFactory)
  1.1304 +
  1.1305 +NS_IMETHODIMP
  1.1306 +nsSingletonFactory::CreateInstance(nsISupports* aOuter,
  1.1307 +                                   const nsIID& aIID,
  1.1308 +                                   void* *aResult)
  1.1309 +{
  1.1310 +  NS_ENSURE_NO_AGGREGATION(aOuter);
  1.1311 +
  1.1312 +  return mSingleton->QueryInterface(aIID, aResult);
  1.1313 +}
  1.1314 +
  1.1315 +NS_IMETHODIMP
  1.1316 +nsSingletonFactory::LockFactory(bool)
  1.1317 +{
  1.1318 +  return NS_OK;
  1.1319 +}
  1.1320 +
  1.1321 +/**
  1.1322 + * Set our windowcreator on the WindowWatcher service.
  1.1323 + */
  1.1324 +nsresult
  1.1325 +ScopedXPCOMStartup::SetWindowCreator(nsINativeAppSupport* native)
  1.1326 +{
  1.1327 +  nsresult rv;
  1.1328 +
  1.1329 +  NS_IF_ADDREF(gNativeAppSupport = native);
  1.1330 +
  1.1331 +  // Inform the chrome registry about OS accessibility
  1.1332 +  nsCOMPtr<nsIToolkitChromeRegistry> cr =
  1.1333 +    mozilla::services::GetToolkitChromeRegistryService();
  1.1334 +
  1.1335 +  if (cr)
  1.1336 +    cr->CheckForOSAccessibility();
  1.1337 +
  1.1338 +  nsCOMPtr<nsIWindowCreator> creator (do_GetService(NS_APPSTARTUP_CONTRACTID));
  1.1339 +  if (!creator) return NS_ERROR_UNEXPECTED;
  1.1340 +
  1.1341 +  nsCOMPtr<nsIWindowWatcher> wwatch
  1.1342 +    (do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv));
  1.1343 +  NS_ENSURE_SUCCESS(rv, rv);
  1.1344 +
  1.1345 +  return wwatch->SetWindowCreator(creator);
  1.1346 +}
  1.1347 +
  1.1348 +/* static */ nsresult
  1.1349 +ScopedXPCOMStartup::CreateAppSupport(nsISupports* aOuter, REFNSIID aIID, void** aResult)
  1.1350 +{
  1.1351 +  if (aOuter)
  1.1352 +    return NS_ERROR_NO_AGGREGATION;
  1.1353 +
  1.1354 +  if (!gNativeAppSupport)
  1.1355 +    return NS_ERROR_NOT_INITIALIZED;
  1.1356 +
  1.1357 +  return gNativeAppSupport->QueryInterface(aIID, aResult);
  1.1358 +}
  1.1359 +
  1.1360 +nsINativeAppSupport* ScopedXPCOMStartup::gNativeAppSupport;
  1.1361 +
  1.1362 +/**
  1.1363 + * A helper class which calls NS_LogInit/NS_LogTerm in its scope.
  1.1364 + */
  1.1365 +class ScopedLogging
  1.1366 +{
  1.1367 +public:
  1.1368 +  ScopedLogging() { NS_LogInit(); }
  1.1369 +  ~ScopedLogging() { NS_LogTerm(); }
  1.1370 +};
  1.1371 +
  1.1372 +static void DumpArbitraryHelp()
  1.1373 +{
  1.1374 +  nsresult rv;
  1.1375 +
  1.1376 +  ScopedLogging log;
  1.1377 +
  1.1378 +  {
  1.1379 +    ScopedXPCOMStartup xpcom;
  1.1380 +    xpcom.Initialize();
  1.1381 +
  1.1382 +    nsCOMPtr<nsICommandLineRunner> cmdline
  1.1383 +      (do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
  1.1384 +    if (!cmdline)
  1.1385 +      return;
  1.1386 +
  1.1387 +    nsCString text;
  1.1388 +    rv = cmdline->GetHelpText(text);
  1.1389 +    if (NS_SUCCEEDED(rv))
  1.1390 +      printf("%s", text.get());
  1.1391 +  }
  1.1392 +}
  1.1393 +
  1.1394 +// English text needs to go into a dtd file.
  1.1395 +// But when this is called we have no components etc. These strings must either be
  1.1396 +// here, or in a native resource file.
  1.1397 +static void
  1.1398 +DumpHelp()
  1.1399 +{
  1.1400 +  printf("Usage: %s [ options ... ] [URL]\n"
  1.1401 +         "       where options include:\n\n", gArgv[0]);
  1.1402 +
  1.1403 +#ifdef MOZ_X11
  1.1404 +  printf("X11 options\n"
  1.1405 +         "  --display=DISPLAY  X display to use\n"
  1.1406 +         "  --sync             Make X calls synchronous\n");
  1.1407 +#endif
  1.1408 +#ifdef XP_UNIX
  1.1409 +  printf("  --g-fatal-warnings Make all warnings fatal\n"
  1.1410 +         "\n%s options\n", gAppData->name);
  1.1411 +#endif
  1.1412 +
  1.1413 +  printf("  -h or -help        Print this message.\n"
  1.1414 +         "  -v or -version     Print %s version.\n"
  1.1415 +         "  -P <profile>       Start with <profile>.\n"
  1.1416 +         "  -migration         Start with migration wizard.\n"
  1.1417 +         "  -ProfileManager    Start with ProfileManager.\n"
  1.1418 +         "  -no-remote         (default) Do not accept or send remote commands; implies -new-instance.\n"
  1.1419 +         "  -allow-remote      Accept and send remote commands.\n"
  1.1420 +         "  -new-instance      Open new instance, not a new window in running instance.\n"
  1.1421 +         "  -UILocale <locale> Start with <locale> resources as UI Locale.\n"
  1.1422 +         "  -safe-mode         Disables extensions and themes for this session.\n", gAppData->name);
  1.1423 +
  1.1424 +#if defined(XP_WIN)
  1.1425 +  printf("  -console           Start %s with a debugging console.\n", gAppData->name);
  1.1426 +#endif
  1.1427 +
  1.1428 +  // this works, but only after the components have registered.  so if you drop in a new command line handler, -help
  1.1429 +  // won't not until the second run.
  1.1430 +  // out of the bug, because we ship a component.reg file, it works correctly.
  1.1431 +  DumpArbitraryHelp();
  1.1432 +}
  1.1433 +
  1.1434 +#if defined(DEBUG) && defined(XP_WIN)
  1.1435 +#ifdef DEBUG_warren
  1.1436 +#define _CRTDBG_MAP_ALLOC
  1.1437 +#endif
  1.1438 +// Set a CRT ReportHook function to capture and format MSCRT
  1.1439 +// warnings, errors and assertions.
  1.1440 +// See http://msdn.microsoft.com/en-US/library/74kabxyx(v=VS.80).aspx
  1.1441 +#include <stdio.h>
  1.1442 +#include <crtdbg.h>
  1.1443 +#include "mozilla/mozalloc_abort.h"
  1.1444 +static int MSCRTReportHook( int aReportType, char *aMessage, int *oReturnValue)
  1.1445 +{
  1.1446 +  *oReturnValue = 0; // continue execution
  1.1447 +
  1.1448 +  // Do not use fprintf or other functions which may allocate
  1.1449 +  // memory from the heap which may be corrupted. Instead,
  1.1450 +  // use fputs to output the leading portion of the message
  1.1451 +  // and use mozalloc_abort to emit the remainder of the
  1.1452 +  // message.
  1.1453 +
  1.1454 +  switch(aReportType) {
  1.1455 +  case 0:
  1.1456 +    fputs("\nWARNING: CRT WARNING", stderr);
  1.1457 +    fputs(aMessage, stderr);
  1.1458 +    fputs("\n", stderr);
  1.1459 +    break;
  1.1460 +  case 1:
  1.1461 +    fputs("\n###!!! ABORT: CRT ERROR ", stderr);
  1.1462 +    mozalloc_abort(aMessage);
  1.1463 +    break;
  1.1464 +  case 2:
  1.1465 +    fputs("\n###!!! ABORT: CRT ASSERT ", stderr);
  1.1466 +    mozalloc_abort(aMessage);
  1.1467 +    break;
  1.1468 +  }
  1.1469 +
  1.1470 +  // do not invoke the debugger
  1.1471 +  return 1;
  1.1472 +}
  1.1473 +
  1.1474 +#endif
  1.1475 +
  1.1476 +static inline void
  1.1477 +DumpVersion()
  1.1478 +{
  1.1479 +  if (gAppData->vendor)
  1.1480 +    printf("%s ", gAppData->vendor);
  1.1481 +  printf("%s %s", gAppData->name, gAppData->version);
  1.1482 +  if (gAppData->copyright)
  1.1483 +      printf(", %s", gAppData->copyright);
  1.1484 +  printf("\n");
  1.1485 +}
  1.1486 +
  1.1487 +#ifdef MOZ_ENABLE_XREMOTE
  1.1488 +// use int here instead of a PR type since it will be returned
  1.1489 +// from main - just to keep types consistent
  1.1490 +static int
  1.1491 +HandleRemoteArgument(const char* remote, const char* aDesktopStartupID)
  1.1492 +{
  1.1493 +  nsresult rv;
  1.1494 +  ArgResult ar;
  1.1495 +
  1.1496 +  const char *profile = 0;
  1.1497 +  nsAutoCString program(gAppData->name);
  1.1498 +  ToLowerCase(program);
  1.1499 +  const char *username = getenv("LOGNAME");
  1.1500 +
  1.1501 +  ar = CheckArg("p", false, &profile);
  1.1502 +  if (ar == ARG_BAD) {
  1.1503 +    PR_fprintf(PR_STDERR, "Error: argument -p requires a profile name\n");
  1.1504 +    return 1;
  1.1505 +  }
  1.1506 +
  1.1507 +  const char *temp = nullptr;
  1.1508 +  ar = CheckArg("a", false, &temp);
  1.1509 +  if (ar == ARG_BAD) {
  1.1510 +    PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n");
  1.1511 +    return 1;
  1.1512 +  } else if (ar == ARG_FOUND) {
  1.1513 +    program.Assign(temp);
  1.1514 +  }
  1.1515 +
  1.1516 +  ar = CheckArg("u", false, &username);
  1.1517 +  if (ar == ARG_BAD) {
  1.1518 +    PR_fprintf(PR_STDERR, "Error: argument -u requires a username\n");
  1.1519 +    return 1;
  1.1520 +  }
  1.1521 +
  1.1522 +  XRemoteClient client;
  1.1523 +  rv = client.Init();
  1.1524 +  if (NS_FAILED(rv)) {
  1.1525 +    PR_fprintf(PR_STDERR, "Error: Failed to connect to X server.\n");
  1.1526 +    return 1;
  1.1527 +  }
  1.1528 +
  1.1529 +  nsXPIDLCString response;
  1.1530 +  bool success = false;
  1.1531 +  rv = client.SendCommand(program.get(), username, profile, remote,
  1.1532 +                          aDesktopStartupID, getter_Copies(response), &success);
  1.1533 +  // did the command fail?
  1.1534 +  if (NS_FAILED(rv)) {
  1.1535 +    PR_fprintf(PR_STDERR, "Error: Failed to send command: %s\n",
  1.1536 +               response ? response.get() : "No response included");
  1.1537 +    return 1;
  1.1538 +  }
  1.1539 +
  1.1540 +  if (!success) {
  1.1541 +    PR_fprintf(PR_STDERR, "Error: No running window found\n");
  1.1542 +    return 2;
  1.1543 +  }
  1.1544 +
  1.1545 +  return 0;
  1.1546 +}
  1.1547 +
  1.1548 +static RemoteResult
  1.1549 +RemoteCommandLine(const char* aDesktopStartupID)
  1.1550 +{
  1.1551 +  nsresult rv;
  1.1552 +  ArgResult ar;
  1.1553 +
  1.1554 +  nsAutoCString program(gAppData->name);
  1.1555 +  ToLowerCase(program);
  1.1556 +  const char *username = getenv("LOGNAME");
  1.1557 +
  1.1558 +  const char *temp = nullptr;
  1.1559 +  ar = CheckArg("a", true, &temp);
  1.1560 +  if (ar == ARG_BAD) {
  1.1561 +    PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n");
  1.1562 +    return REMOTE_ARG_BAD;
  1.1563 +  } else if (ar == ARG_FOUND) {
  1.1564 +    program.Assign(temp);
  1.1565 +  }
  1.1566 +
  1.1567 +  ar = CheckArg("u", true, &username);
  1.1568 +  if (ar == ARG_BAD) {
  1.1569 +    PR_fprintf(PR_STDERR, "Error: argument -u requires a username\n");
  1.1570 +    return REMOTE_ARG_BAD;
  1.1571 +  }
  1.1572 +
  1.1573 +  XRemoteClient client;
  1.1574 +  rv = client.Init();
  1.1575 +  if (NS_FAILED(rv))
  1.1576 +    return REMOTE_NOT_FOUND;
  1.1577 + 
  1.1578 +  nsXPIDLCString response;
  1.1579 +  bool success = false;
  1.1580 +  rv = client.SendCommandLine(program.get(), username, nullptr,
  1.1581 +                              gArgc, gArgv, aDesktopStartupID,
  1.1582 +                              getter_Copies(response), &success);
  1.1583 +  // did the command fail?
  1.1584 +  if (NS_FAILED(rv) || !success)
  1.1585 +    return REMOTE_NOT_FOUND;
  1.1586 +
  1.1587 +  return REMOTE_FOUND;
  1.1588 +}
  1.1589 +#endif // MOZ_ENABLE_XREMOTE
  1.1590 +
  1.1591 +void
  1.1592 +XRE_InitOmnijar(nsIFile* greOmni, nsIFile* appOmni)
  1.1593 +{
  1.1594 +  mozilla::Omnijar::Init(greOmni, appOmni);
  1.1595 +}
  1.1596 +
  1.1597 +nsresult
  1.1598 +XRE_GetBinaryPath(const char* argv0, nsIFile* *aResult)
  1.1599 +{
  1.1600 +  return mozilla::BinaryPath::GetFile(argv0, aResult);
  1.1601 +}
  1.1602 +
  1.1603 +#ifdef XP_WIN
  1.1604 +#include "nsWindowsRestart.cpp"
  1.1605 +#include <shellapi.h>
  1.1606 +
  1.1607 +typedef BOOL (WINAPI* SetProcessDEPPolicyFunc)(DWORD dwFlags);
  1.1608 +#endif
  1.1609 +
  1.1610 +// If aBlankCommandLine is true, then the application will be launched with a
  1.1611 +// blank command line instead of being launched with the same command line that
  1.1612 +// it was initially started with.
  1.1613 +static nsresult LaunchChild(nsINativeAppSupport* aNative,
  1.1614 +                            bool aBlankCommandLine = false)
  1.1615 +{
  1.1616 +  aNative->Quit(); // release DDE mutex, if we're holding it
  1.1617 +
  1.1618 +  // Restart this process by exec'ing it into the current process
  1.1619 +  // if supported by the platform.  Otherwise, use NSPR.
  1.1620 +
  1.1621 +#ifdef MOZ_JPROF
  1.1622 +  // make sure JPROF doesn't think we're E10s
  1.1623 +  unsetenv("JPROF_SLAVE");
  1.1624 +#endif
  1.1625 +
  1.1626 +  if (aBlankCommandLine) {
  1.1627 +#if defined(MOZ_WIDGET_QT)
  1.1628 +    // Remove only arguments not given to Qt
  1.1629 +    gRestartArgc = gQtOnlyArgc;
  1.1630 +    gRestartArgv = gQtOnlyArgv;
  1.1631 +#else
  1.1632 +    gRestartArgc = 1;
  1.1633 +    gRestartArgv[gRestartArgc] = nullptr;
  1.1634 +#endif
  1.1635 +  }
  1.1636 +
  1.1637 +  SaveToEnv("MOZ_LAUNCHED_CHILD=1");
  1.1638 +
  1.1639 +#if defined(MOZ_WIDGET_ANDROID)
  1.1640 +  mozilla::widget::android::GeckoAppShell::ScheduleRestart();
  1.1641 +#else
  1.1642 +#if defined(XP_MACOSX)
  1.1643 +  CommandLineServiceMac::SetupMacCommandLine(gRestartArgc, gRestartArgv, true);
  1.1644 +  uint32_t restartMode = 0;
  1.1645 +  restartMode = gRestartMode;
  1.1646 +  LaunchChildMac(gRestartArgc, gRestartArgv, restartMode);
  1.1647 +#else
  1.1648 +  nsCOMPtr<nsIFile> lf;
  1.1649 +  nsresult rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
  1.1650 +  if (NS_FAILED(rv))
  1.1651 +    return rv;
  1.1652 +
  1.1653 +#if defined(XP_WIN)
  1.1654 +  nsAutoString exePath;
  1.1655 +  rv = lf->GetPath(exePath);
  1.1656 +  if (NS_FAILED(rv))
  1.1657 +    return rv;
  1.1658 +
  1.1659 +  if (!WinLaunchChild(exePath.get(), gRestartArgc, gRestartArgv))
  1.1660 +    return NS_ERROR_FAILURE;
  1.1661 +
  1.1662 +#else
  1.1663 +  nsAutoCString exePath;
  1.1664 +  rv = lf->GetNativePath(exePath);
  1.1665 +  if (NS_FAILED(rv))
  1.1666 +    return rv;
  1.1667 +
  1.1668 +#if defined(XP_UNIX)
  1.1669 +  if (execv(exePath.get(), gRestartArgv) == -1)
  1.1670 +    return NS_ERROR_FAILURE;
  1.1671 +#else
  1.1672 +  PRProcess* process = PR_CreateProcess(exePath.get(), gRestartArgv,
  1.1673 +                                        nullptr, nullptr);
  1.1674 +  if (!process) return NS_ERROR_FAILURE;
  1.1675 +
  1.1676 +  int32_t exitCode;
  1.1677 +  PRStatus failed = PR_WaitProcess(process, &exitCode);
  1.1678 +  if (failed || exitCode)
  1.1679 +    return NS_ERROR_FAILURE;
  1.1680 +#endif // XP_UNIX
  1.1681 +#endif // WP_WIN
  1.1682 +#endif // WP_MACOSX
  1.1683 +#endif // MOZ_WIDGET_ANDROID
  1.1684 +
  1.1685 +  return NS_ERROR_LAUNCHED_CHILD_PROCESS;
  1.1686 +}
  1.1687 +
  1.1688 +static const char kProfileProperties[] =
  1.1689 +  "chrome://mozapps/locale/profile/profileSelection.properties";
  1.1690 +
  1.1691 +static nsresult
  1.1692 +ProfileLockedDialog(nsIFile* aProfileDir, nsIFile* aProfileLocalDir,
  1.1693 +                    nsIProfileUnlocker* aUnlocker,
  1.1694 +                    nsINativeAppSupport* aNative, nsIProfileLock* *aResult)
  1.1695 +{
  1.1696 +  nsresult rv;
  1.1697 +
  1.1698 +  ScopedXPCOMStartup xpcom;
  1.1699 +  rv = xpcom.Initialize();
  1.1700 +  NS_ENSURE_SUCCESS(rv, rv);
  1.1701 +
  1.1702 +  mozilla::Telemetry::WriteFailedProfileLock(aProfileDir);
  1.1703 +
  1.1704 +  rv = xpcom.SetWindowCreator(aNative);
  1.1705 +  NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  1.1706 +
  1.1707 +  { //extra scoping is needed so we release these components before xpcom shutdown
  1.1708 +    nsCOMPtr<nsIStringBundleService> sbs =
  1.1709 +      mozilla::services::GetStringBundleService();
  1.1710 +    NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE);
  1.1711 +
  1.1712 +    nsCOMPtr<nsIStringBundle> sb;
  1.1713 +    sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
  1.1714 +    NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE);
  1.1715 +
  1.1716 +    NS_ConvertUTF8toUTF16 appName(gAppData->name);
  1.1717 +    const char16_t* params[] = {appName.get(), appName.get()};
  1.1718 +
  1.1719 +    nsXPIDLString killMessage;
  1.1720 +#ifndef XP_MACOSX
  1.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','\0'}; // "restartMessageNoUnlocker"
  1.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','\0'}; // "restartMessageUnlocker"
  1.1723 +#else
  1.1724 +    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"
  1.1725 +    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"
  1.1726 +#endif
  1.1727 +
  1.1728 +    sb->FormatStringFromName(aUnlocker ? kRestartUnlocker : kRestartNoUnlocker,
  1.1729 +                             params, 2, getter_Copies(killMessage));
  1.1730 +
  1.1731 +    nsXPIDLString killTitle;
  1.1732 +    sb->FormatStringFromName(MOZ_UTF16("restartTitle"),
  1.1733 +                             params, 1, getter_Copies(killTitle));
  1.1734 +
  1.1735 +    if (!killMessage || !killTitle)
  1.1736 +      return NS_ERROR_FAILURE;
  1.1737 +
  1.1738 +    nsCOMPtr<nsIPromptService> ps
  1.1739 +      (do_GetService(NS_PROMPTSERVICE_CONTRACTID));
  1.1740 +    NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE);
  1.1741 +
  1.1742 +    if (aUnlocker) {
  1.1743 +      int32_t button;
  1.1744 +#ifdef MOZ_WIDGET_ANDROID
  1.1745 +      mozilla::widget::android::GeckoAppShell::KillAnyZombies();
  1.1746 +      button = 1;
  1.1747 +#else
  1.1748 +      const uint32_t flags =
  1.1749 +        (nsIPromptService::BUTTON_TITLE_CANCEL * 
  1.1750 +         nsIPromptService::BUTTON_POS_0) +
  1.1751 +        (nsIPromptService::BUTTON_TITLE_IS_STRING * 
  1.1752 +         nsIPromptService::BUTTON_POS_1) +
  1.1753 +        nsIPromptService::BUTTON_POS_1_DEFAULT;
  1.1754 +
  1.1755 +      bool checkState = false;
  1.1756 +      rv = ps->ConfirmEx(nullptr, killTitle, killMessage, flags,
  1.1757 +                         killTitle, nullptr, nullptr, nullptr, 
  1.1758 +                         &checkState, &button);
  1.1759 +      NS_ENSURE_SUCCESS_LOG(rv, rv);
  1.1760 +#endif
  1.1761 +
  1.1762 +      if (button == 1) {
  1.1763 +        rv = aUnlocker->Unlock(nsIProfileUnlocker::FORCE_QUIT);
  1.1764 +        if (NS_FAILED(rv)) 
  1.1765 +          return rv;
  1.1766 +
  1.1767 +        return NS_LockProfilePath(aProfileDir, aProfileLocalDir, 
  1.1768 +                                  nullptr, aResult);
  1.1769 +      }
  1.1770 +    } else {
  1.1771 +#ifdef MOZ_WIDGET_ANDROID
  1.1772 +      if (mozilla::widget::android::GeckoAppShell::UnlockProfile()) {
  1.1773 +        return NS_LockProfilePath(aProfileDir, aProfileLocalDir, 
  1.1774 +                                  nullptr, aResult);
  1.1775 +      }
  1.1776 +#else
  1.1777 +      rv = ps->Alert(nullptr, killTitle, killMessage);
  1.1778 +      NS_ENSURE_SUCCESS_LOG(rv, rv);
  1.1779 +#endif
  1.1780 +    }
  1.1781 +
  1.1782 +    return NS_ERROR_ABORT;
  1.1783 +  }
  1.1784 +}
  1.1785 +
  1.1786 +
  1.1787 +static nsresult
  1.1788 +ProfileMissingDialog(nsINativeAppSupport* aNative)
  1.1789 +{
  1.1790 +  nsresult rv;
  1.1791 +
  1.1792 +  ScopedXPCOMStartup xpcom;
  1.1793 +  rv = xpcom.Initialize();
  1.1794 +  NS_ENSURE_SUCCESS(rv, rv);
  1.1795 +
  1.1796 +  rv = xpcom.SetWindowCreator(aNative);
  1.1797 +  NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  1.1798 +
  1.1799 +  { //extra scoping is needed so we release these components before xpcom shutdown
  1.1800 +    nsCOMPtr<nsIStringBundleService> sbs =
  1.1801 +      mozilla::services::GetStringBundleService();
  1.1802 +    NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE);
  1.1803 +  
  1.1804 +    nsCOMPtr<nsIStringBundle> sb;
  1.1805 +    sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
  1.1806 +    NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE);
  1.1807 +  
  1.1808 +    NS_ConvertUTF8toUTF16 appName(gAppData->name);
  1.1809 +    const char16_t* params[] = {appName.get(), appName.get()};
  1.1810 +  
  1.1811 +    nsXPIDLString missingMessage;
  1.1812 +  
  1.1813 +    // profileMissing  
  1.1814 +    static const char16_t kMissing[] = {'p','r','o','f','i','l','e','M','i','s','s','i','n','g','\0'};
  1.1815 +    sb->FormatStringFromName(kMissing, params, 2, getter_Copies(missingMessage));
  1.1816 +  
  1.1817 +    nsXPIDLString missingTitle;
  1.1818 +    sb->FormatStringFromName(MOZ_UTF16("profileMissingTitle"),
  1.1819 +                             params, 1, getter_Copies(missingTitle));
  1.1820 +  
  1.1821 +    if (missingMessage && missingTitle) {
  1.1822 +      nsCOMPtr<nsIPromptService> ps
  1.1823 +        (do_GetService(NS_PROMPTSERVICE_CONTRACTID));
  1.1824 +      NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE);
  1.1825 +  
  1.1826 +      ps->Alert(nullptr, missingTitle, missingMessage);
  1.1827 +    }
  1.1828 +
  1.1829 +    return NS_ERROR_ABORT;
  1.1830 +  }
  1.1831 +}
  1.1832 +
  1.1833 +static nsresult
  1.1834 +ProfileLockedDialog(nsIToolkitProfile* aProfile, nsIProfileUnlocker* aUnlocker,
  1.1835 +                    nsINativeAppSupport* aNative, nsIProfileLock* *aResult)
  1.1836 +{
  1.1837 +  nsCOMPtr<nsIFile> profileDir;
  1.1838 +  nsresult rv = aProfile->GetRootDir(getter_AddRefs(profileDir));
  1.1839 +  if (NS_FAILED(rv)) return rv;
  1.1840 +
  1.1841 +  bool exists;
  1.1842 +  profileDir->Exists(&exists);
  1.1843 +  if (!exists) {
  1.1844 +    return ProfileMissingDialog(aNative);
  1.1845 +  }
  1.1846 +
  1.1847 +  nsCOMPtr<nsIFile> profileLocalDir;
  1.1848 +  rv = aProfile->GetLocalDir(getter_AddRefs(profileLocalDir));
  1.1849 +  if (NS_FAILED(rv)) return rv;
  1.1850 +
  1.1851 +  return ProfileLockedDialog(profileDir, profileLocalDir, aUnlocker, aNative,
  1.1852 +                             aResult);
  1.1853 +}
  1.1854 +
  1.1855 +static const char kProfileManagerURL[] =
  1.1856 +  "chrome://mozapps/content/profile/profileSelection.xul";
  1.1857 +
  1.1858 +static nsresult
  1.1859 +ShowProfileManager(nsIToolkitProfileService* aProfileSvc,
  1.1860 +                   nsINativeAppSupport* aNative)
  1.1861 +{
  1.1862 +  if (!CanShowProfileManager()) {
  1.1863 +    return NS_ERROR_NOT_IMPLEMENTED;
  1.1864 +  }
  1.1865 +
  1.1866 +  nsresult rv;
  1.1867 +
  1.1868 +  nsCOMPtr<nsIFile> profD, profLD;
  1.1869 +  char16_t* profileNamePtr;
  1.1870 +  nsAutoCString profileName;
  1.1871 +
  1.1872 +  {
  1.1873 +    ScopedXPCOMStartup xpcom;
  1.1874 +    rv = xpcom.Initialize();
  1.1875 +    NS_ENSURE_SUCCESS(rv, rv);
  1.1876 +
  1.1877 +    rv = xpcom.SetWindowCreator(aNative);
  1.1878 +    NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  1.1879 +
  1.1880 +#ifdef XP_MACOSX
  1.1881 +    CommandLineServiceMac::SetupMacCommandLine(gRestartArgc, gRestartArgv, true);
  1.1882 +#endif
  1.1883 +
  1.1884 +#ifdef XP_WIN
  1.1885 +    // we don't have to wait here because profile manager window will pump
  1.1886 +    // and DDE message will be handled
  1.1887 +    ProcessDDE(aNative, false);
  1.1888 +#endif
  1.1889 +
  1.1890 +    { //extra scoping is needed so we release these components before xpcom shutdown
  1.1891 +      nsCOMPtr<nsIWindowWatcher> windowWatcher
  1.1892 +        (do_GetService(NS_WINDOWWATCHER_CONTRACTID));
  1.1893 +      nsCOMPtr<nsIDialogParamBlock> ioParamBlock
  1.1894 +        (do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID));
  1.1895 +      nsCOMPtr<nsIMutableArray> dlgArray (do_CreateInstance(NS_ARRAY_CONTRACTID));
  1.1896 +      NS_ENSURE_TRUE(windowWatcher && ioParamBlock && dlgArray, NS_ERROR_FAILURE);
  1.1897 +
  1.1898 +      ioParamBlock->SetObjects(dlgArray);
  1.1899 +
  1.1900 +      nsCOMPtr<nsIAppStartup> appStartup
  1.1901 +        (do_GetService(NS_APPSTARTUP_CONTRACTID));
  1.1902 +      NS_ENSURE_TRUE(appStartup, NS_ERROR_FAILURE);
  1.1903 +
  1.1904 +      nsCOMPtr<nsIDOMWindow> newWindow;
  1.1905 +      rv = windowWatcher->OpenWindow(nullptr,
  1.1906 +                                     kProfileManagerURL,
  1.1907 +                                     "_blank",
  1.1908 +                                     "centerscreen,chrome,modal,titlebar",
  1.1909 +                                     ioParamBlock,
  1.1910 +                                     getter_AddRefs(newWindow));
  1.1911 +
  1.1912 +      NS_ENSURE_SUCCESS_LOG(rv, rv);
  1.1913 +
  1.1914 +      aProfileSvc->Flush();
  1.1915 +
  1.1916 +      int32_t dialogConfirmed;
  1.1917 +      rv = ioParamBlock->GetInt(0, &dialogConfirmed);
  1.1918 +      if (NS_FAILED(rv) || dialogConfirmed == 0) return NS_ERROR_ABORT;
  1.1919 +
  1.1920 +      nsCOMPtr<nsIProfileLock> lock;
  1.1921 +      rv = dlgArray->QueryElementAt(0, NS_GET_IID(nsIProfileLock),
  1.1922 +                                    getter_AddRefs(lock));
  1.1923 +      NS_ENSURE_SUCCESS_LOG(rv, rv);
  1.1924 +
  1.1925 +      rv = lock->GetDirectory(getter_AddRefs(profD));
  1.1926 +      NS_ENSURE_SUCCESS(rv, rv);
  1.1927 +
  1.1928 +      rv = lock->GetLocalDirectory(getter_AddRefs(profLD));
  1.1929 +      NS_ENSURE_SUCCESS(rv, rv);
  1.1930 +
  1.1931 +      rv = ioParamBlock->GetString(0, &profileNamePtr);
  1.1932 +      NS_ENSURE_SUCCESS(rv, rv);
  1.1933 +
  1.1934 +      CopyUTF16toUTF8(profileNamePtr, profileName);
  1.1935 +      NS_Free(profileNamePtr);
  1.1936 +
  1.1937 +      lock->Unlock();
  1.1938 +    }
  1.1939 +  }
  1.1940 +
  1.1941 +  SaveFileToEnv("XRE_PROFILE_PATH", profD);
  1.1942 +  SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", profLD);
  1.1943 +  SaveWordToEnv("XRE_PROFILE_NAME", profileName);
  1.1944 +
  1.1945 +  bool offline = false;
  1.1946 +  aProfileSvc->GetStartOffline(&offline);
  1.1947 +  if (offline) {
  1.1948 +    SaveToEnv("XRE_START_OFFLINE=1");
  1.1949 +  }
  1.1950 +
  1.1951 +  return LaunchChild(aNative);
  1.1952 +}
  1.1953 +
  1.1954 +static nsresult
  1.1955 +GetCurrentProfileIsDefault(nsIToolkitProfileService* aProfileSvc,
  1.1956 +                           nsIFile* aCurrentProfileRoot, bool *aResult)
  1.1957 +{
  1.1958 +  nsresult rv;
  1.1959 +  // Check that the profile to reset is the default since reset and the associated migration are
  1.1960 +  // only supported in that case.
  1.1961 +  nsCOMPtr<nsIToolkitProfile> selectedProfile;
  1.1962 +  nsCOMPtr<nsIFile> selectedProfileRoot;
  1.1963 +  rv = aProfileSvc->GetSelectedProfile(getter_AddRefs(selectedProfile));
  1.1964 +  NS_ENSURE_SUCCESS(rv, rv);
  1.1965 +
  1.1966 +  rv = selectedProfile->GetRootDir(getter_AddRefs(selectedProfileRoot));
  1.1967 +  NS_ENSURE_SUCCESS(rv, rv);
  1.1968 +
  1.1969 +  bool currentIsSelected;
  1.1970 +  rv = aCurrentProfileRoot->Equals(selectedProfileRoot, &currentIsSelected);
  1.1971 +
  1.1972 +  *aResult = currentIsSelected;
  1.1973 +  return rv;
  1.1974 +}
  1.1975 +
  1.1976 +/**
  1.1977 + * Set the currently running profile as the default/selected one.
  1.1978 + *
  1.1979 + * @param aCurrentProfileRoot The root directory of the current profile.
  1.1980 + * @return an error if aCurrentProfileRoot is not found or the profile could not
  1.1981 + * be set as the default.
  1.1982 + */
  1.1983 +static nsresult
  1.1984 +SetCurrentProfileAsDefault(nsIToolkitProfileService* aProfileSvc,
  1.1985 +                           nsIFile* aCurrentProfileRoot)
  1.1986 +{
  1.1987 +  NS_ENSURE_ARG_POINTER(aProfileSvc);
  1.1988 +
  1.1989 +  nsCOMPtr<nsISimpleEnumerator> profiles;
  1.1990 +  nsresult rv = aProfileSvc->GetProfiles(getter_AddRefs(profiles));
  1.1991 +  if (NS_FAILED(rv))
  1.1992 +    return rv;
  1.1993 +
  1.1994 +  bool foundMatchingProfile = false;
  1.1995 +  nsCOMPtr<nsISupports> supports;
  1.1996 +  rv = profiles->GetNext(getter_AddRefs(supports));
  1.1997 +  while (NS_SUCCEEDED(rv)) {
  1.1998 +    nsCOMPtr<nsIToolkitProfile> profile = do_QueryInterface(supports);
  1.1999 +    nsCOMPtr<nsIFile> profileRoot;
  1.2000 +    profile->GetRootDir(getter_AddRefs(profileRoot));
  1.2001 +    profileRoot->Equals(aCurrentProfileRoot, &foundMatchingProfile);
  1.2002 +    if (foundMatchingProfile && profile) {
  1.2003 +      rv = aProfileSvc->SetSelectedProfile(profile);
  1.2004 +      if (NS_SUCCEEDED(rv))
  1.2005 +        rv = aProfileSvc->Flush();
  1.2006 +      return rv;
  1.2007 +    }
  1.2008 +    rv = profiles->GetNext(getter_AddRefs(supports));
  1.2009 +  }
  1.2010 +  return rv;
  1.2011 +}
  1.2012 +
  1.2013 +static bool gDoMigration = false;
  1.2014 +static bool gDoProfileReset = false;
  1.2015 +
  1.2016 +// Pick a profile. We need to end up with a profile lock.
  1.2017 +//
  1.2018 +// 1) check for -profile <path>
  1.2019 +// 2) check for -P <name>
  1.2020 +// 3) check for -ProfileManager
  1.2021 +// 4) use the default profile, if there is one
  1.2022 +// 5) if there are *no* profiles, set up profile-migration
  1.2023 +// 6) display the profile-manager UI
  1.2024 +static nsresult
  1.2025 +SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, nsINativeAppSupport* aNative,
  1.2026 +              bool* aStartOffline, nsACString* aProfileName)
  1.2027 +{
  1.2028 +  StartupTimeline::Record(StartupTimeline::SELECT_PROFILE);
  1.2029 +
  1.2030 +  nsresult rv;
  1.2031 +  ArgResult ar;
  1.2032 +  const char* arg;
  1.2033 +  *aResult = nullptr;
  1.2034 +  *aStartOffline = false;
  1.2035 +
  1.2036 +  ar = CheckArg("offline", true);
  1.2037 +  if (ar == ARG_BAD) {
  1.2038 +    PR_fprintf(PR_STDERR, "Error: argument -offline is invalid when argument -osint is specified\n");
  1.2039 +    return NS_ERROR_FAILURE;
  1.2040 +  }
  1.2041 +
  1.2042 +  if (ar || EnvHasValue("XRE_START_OFFLINE"))
  1.2043 +    *aStartOffline = true;
  1.2044 +
  1.2045 +  if (EnvHasValue("MOZ_RESET_PROFILE_RESTART")) {
  1.2046 +    gDoProfileReset = true;
  1.2047 +    gDoMigration = true;
  1.2048 +    SaveToEnv("MOZ_RESET_PROFILE_RESTART=");
  1.2049 +  }
  1.2050 +
  1.2051 +  // reset-profile and migration args need to be checked before any profiles are chosen below.
  1.2052 +  ar = CheckArg("reset-profile", true);
  1.2053 +  if (ar == ARG_BAD) {
  1.2054 +    PR_fprintf(PR_STDERR, "Error: argument -reset-profile is invalid when argument -osint is specified\n");
  1.2055 +    return NS_ERROR_FAILURE;
  1.2056 +  } else if (ar == ARG_FOUND) {
  1.2057 +    gDoProfileReset = true;
  1.2058 +  }
  1.2059 +
  1.2060 +  ar = CheckArg("migration", true);
  1.2061 +  if (ar == ARG_BAD) {
  1.2062 +    PR_fprintf(PR_STDERR, "Error: argument -migration is invalid when argument -osint is specified\n");
  1.2063 +    return NS_ERROR_FAILURE;
  1.2064 +  } else if (ar == ARG_FOUND) {
  1.2065 +    gDoMigration = true;
  1.2066 +  }
  1.2067 +
  1.2068 +  nsCOMPtr<nsIFile> lf = GetFileFromEnv("XRE_PROFILE_PATH");
  1.2069 +  if (lf) {
  1.2070 +    nsCOMPtr<nsIFile> localDir =
  1.2071 +      GetFileFromEnv("XRE_PROFILE_LOCAL_PATH");
  1.2072 +    if (!localDir) {
  1.2073 +      localDir = lf;
  1.2074 +    }
  1.2075 +
  1.2076 +    arg = PR_GetEnv("XRE_PROFILE_NAME");
  1.2077 +    if (arg && *arg && aProfileName)
  1.2078 +      aProfileName->Assign(nsDependentCString(arg));
  1.2079 +
  1.2080 +    // Clear out flags that we handled (or should have handled!) last startup.
  1.2081 +    const char *dummy;
  1.2082 +    CheckArg("p", false, &dummy);
  1.2083 +    CheckArg("profile", false, &dummy);
  1.2084 +    CheckArg("profilemanager");
  1.2085 +
  1.2086 +    if (gDoProfileReset) {
  1.2087 +      // Check that the profile to reset is the default since reset and migration are only
  1.2088 +      // supported in that case.
  1.2089 +      bool currentIsSelected;
  1.2090 +      GetCurrentProfileIsDefault(aProfileSvc, lf, &currentIsSelected);
  1.2091 +      if (!currentIsSelected) {
  1.2092 +        NS_WARNING("Profile reset is only supported for the default profile.");
  1.2093 +        gDoProfileReset = gDoMigration = false;
  1.2094 +      }
  1.2095 +
  1.2096 +      // If we're resetting a profile, create a new one and use it to startup.
  1.2097 +      nsCOMPtr<nsIToolkitProfile> newProfile;
  1.2098 +      rv = CreateResetProfile(aProfileSvc, getter_AddRefs(newProfile));
  1.2099 +      if (NS_SUCCEEDED(rv)) {
  1.2100 +        rv = newProfile->GetRootDir(getter_AddRefs(lf));
  1.2101 +        NS_ENSURE_SUCCESS(rv, rv);
  1.2102 +        SaveFileToEnv("XRE_PROFILE_PATH", lf);
  1.2103 +
  1.2104 +        rv = newProfile->GetLocalDir(getter_AddRefs(localDir));
  1.2105 +        NS_ENSURE_SUCCESS(rv, rv);
  1.2106 +        SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", localDir);
  1.2107 +
  1.2108 +        rv = newProfile->GetName(*aProfileName);
  1.2109 +        if (NS_FAILED(rv))
  1.2110 +          aProfileName->Truncate(0);
  1.2111 +        SaveWordToEnv("XRE_PROFILE_NAME", *aProfileName);
  1.2112 +      } else {
  1.2113 +        NS_WARNING("Profile reset failed.");
  1.2114 +        gDoProfileReset = false;
  1.2115 +      }
  1.2116 +    }
  1.2117 +
  1.2118 +    return NS_LockProfilePath(lf, localDir, nullptr, aResult);
  1.2119 +  }
  1.2120 +
  1.2121 +  ar = CheckArg("profile", true, &arg);
  1.2122 +  if (ar == ARG_BAD) {
  1.2123 +    PR_fprintf(PR_STDERR, "Error: argument -profile requires a path\n");
  1.2124 +    return NS_ERROR_FAILURE;
  1.2125 +  }
  1.2126 +  if (ar) {
  1.2127 +    if (gDoProfileReset) {
  1.2128 +      NS_WARNING("Profile reset is only supported for the default profile.");
  1.2129 +      gDoProfileReset = false;
  1.2130 +    }
  1.2131 +
  1.2132 +    nsCOMPtr<nsIFile> lf;
  1.2133 +    rv = XRE_GetFileFromPath(arg, getter_AddRefs(lf));
  1.2134 +    NS_ENSURE_SUCCESS(rv, rv);
  1.2135 +
  1.2136 +    nsCOMPtr<nsIProfileUnlocker> unlocker;
  1.2137 +
  1.2138 +    // Check if the profile path exists and it's a directory.
  1.2139 +    bool exists;
  1.2140 +    lf->Exists(&exists);
  1.2141 +    if (!exists) {
  1.2142 +        rv = lf->Create(nsIFile::DIRECTORY_TYPE, 0700);
  1.2143 +        NS_ENSURE_SUCCESS(rv, rv);
  1.2144 +    }
  1.2145 +
  1.2146 +    // If a profile path is specified directory on the command line, then
  1.2147 +    // assume that the temp directory is the same as the given directory.
  1.2148 +    rv = NS_LockProfilePath(lf, lf, getter_AddRefs(unlocker), aResult);
  1.2149 +    if (NS_SUCCEEDED(rv))
  1.2150 +      return rv;
  1.2151 +
  1.2152 +    return ProfileLockedDialog(lf, lf, unlocker, aNative, aResult);
  1.2153 +  }
  1.2154 +
  1.2155 +  ar = CheckArg("createprofile", true, &arg);
  1.2156 +  if (ar == ARG_BAD) {
  1.2157 +    PR_fprintf(PR_STDERR, "Error: argument -createprofile requires a profile name\n");
  1.2158 +    return NS_ERROR_FAILURE;
  1.2159 +  }
  1.2160 +  if (ar) {
  1.2161 +    nsCOMPtr<nsIToolkitProfile> profile;
  1.2162 +
  1.2163 +    const char* delim = strchr(arg, ' ');
  1.2164 +    if (delim) {
  1.2165 +      nsCOMPtr<nsIFile> lf;
  1.2166 +      rv = NS_NewNativeLocalFile(nsDependentCString(delim + 1),
  1.2167 +                                   true, getter_AddRefs(lf));
  1.2168 +      if (NS_FAILED(rv)) {
  1.2169 +        PR_fprintf(PR_STDERR, "Error: profile path not valid.\n");
  1.2170 +        return rv;
  1.2171 +      }
  1.2172 +      
  1.2173 +      // As with -profile, assume that the given path will be used for the
  1.2174 +      // main profile directory.
  1.2175 +      rv = aProfileSvc->CreateProfile(lf, nsDependentCSubstring(arg, delim),
  1.2176 +                                     getter_AddRefs(profile));
  1.2177 +    } else {
  1.2178 +      rv = aProfileSvc->CreateProfile(nullptr, nsDependentCString(arg),
  1.2179 +                                     getter_AddRefs(profile));
  1.2180 +    }
  1.2181 +    // Some pathological arguments can make it this far
  1.2182 +    if (NS_FAILED(rv)) {
  1.2183 +      PR_fprintf(PR_STDERR, "Error creating profile.\n");
  1.2184 +      return rv; 
  1.2185 +    }
  1.2186 +    rv = NS_ERROR_ABORT;  
  1.2187 +    aProfileSvc->Flush();
  1.2188 +
  1.2189 +    // XXXben need to ensure prefs.js exists here so the tinderboxes will
  1.2190 +    //        not go orange.
  1.2191 +    nsCOMPtr<nsIFile> prefsJSFile;
  1.2192 +    profile->GetRootDir(getter_AddRefs(prefsJSFile));
  1.2193 +    prefsJSFile->AppendNative(NS_LITERAL_CSTRING("prefs.js"));
  1.2194 +    nsAutoCString pathStr;
  1.2195 +    prefsJSFile->GetNativePath(pathStr);
  1.2196 +    PR_fprintf(PR_STDERR, "Success: created profile '%s' at '%s'\n", arg, pathStr.get());
  1.2197 +    bool exists;
  1.2198 +    prefsJSFile->Exists(&exists);
  1.2199 +    if (!exists)
  1.2200 +      prefsJSFile->Create(nsIFile::NORMAL_FILE_TYPE, 0644);
  1.2201 +    // XXXdarin perhaps 0600 would be better?
  1.2202 +
  1.2203 +    return rv;
  1.2204 +  }
  1.2205 +
  1.2206 +  uint32_t count;
  1.2207 +  rv = aProfileSvc->GetProfileCount(&count);
  1.2208 +  NS_ENSURE_SUCCESS(rv, rv);
  1.2209 +
  1.2210 +  ar = CheckArg("p", false, &arg);
  1.2211 +  if (ar == ARG_BAD) {
  1.2212 +    ar = CheckArg("osint");
  1.2213 +    if (ar == ARG_FOUND) {
  1.2214 +      PR_fprintf(PR_STDERR, "Error: argument -p is invalid when argument -osint is specified\n");
  1.2215 +      return NS_ERROR_FAILURE;
  1.2216 +    }
  1.2217 +
  1.2218 +    if (CanShowProfileManager()) {
  1.2219 +      return ShowProfileManager(aProfileSvc, aNative);
  1.2220 +    }
  1.2221 +  }
  1.2222 +  if (ar) {
  1.2223 +    ar = CheckArg("osint");
  1.2224 +    if (ar == ARG_FOUND) {
  1.2225 +      PR_fprintf(PR_STDERR, "Error: argument -p is invalid when argument -osint is specified\n");
  1.2226 +      return NS_ERROR_FAILURE;
  1.2227 +    }
  1.2228 +    nsCOMPtr<nsIToolkitProfile> profile;
  1.2229 +    rv = aProfileSvc->GetProfileByName(nsDependentCString(arg),
  1.2230 +                                      getter_AddRefs(profile));
  1.2231 +    if (NS_SUCCEEDED(rv)) {
  1.2232 +      if (gDoProfileReset) {
  1.2233 +        NS_WARNING("Profile reset is only supported for the default profile.");
  1.2234 +        gDoProfileReset = false;
  1.2235 +      }
  1.2236 +
  1.2237 +      nsCOMPtr<nsIProfileUnlocker> unlocker;
  1.2238 +      rv = profile->Lock(getter_AddRefs(unlocker), aResult);
  1.2239 +      if (NS_SUCCEEDED(rv)) {
  1.2240 +        if (aProfileName)
  1.2241 +          aProfileName->Assign(nsDependentCString(arg));
  1.2242 +        return NS_OK;
  1.2243 +      }
  1.2244 +
  1.2245 +      return ProfileLockedDialog(profile, unlocker, aNative, aResult);
  1.2246 +    }
  1.2247 +
  1.2248 +    if (CanShowProfileManager()) {
  1.2249 +      return ShowProfileManager(aProfileSvc, aNative);
  1.2250 +    }
  1.2251 +  }
  1.2252 +
  1.2253 +  ar = CheckArg("profilemanager", true);
  1.2254 +  if (ar == ARG_BAD) {
  1.2255 +    PR_fprintf(PR_STDERR, "Error: argument -profilemanager is invalid when argument -osint is specified\n");
  1.2256 +    return NS_ERROR_FAILURE;
  1.2257 +  } else if (ar == ARG_FOUND && CanShowProfileManager()) {
  1.2258 +    return ShowProfileManager(aProfileSvc, aNative);
  1.2259 +  }
  1.2260 +
  1.2261 +  if (!count) {
  1.2262 +    gDoMigration = true;
  1.2263 +    gDoProfileReset = false;
  1.2264 +
  1.2265 +    // create a default profile
  1.2266 +    nsCOMPtr<nsIToolkitProfile> profile;
  1.2267 +    nsresult rv = aProfileSvc->CreateProfile(nullptr, // choose a default dir for us
  1.2268 +                                             NS_LITERAL_CSTRING("default"),
  1.2269 +                                             getter_AddRefs(profile));
  1.2270 +    if (NS_SUCCEEDED(rv)) {
  1.2271 +      aProfileSvc->Flush();
  1.2272 +      rv = profile->Lock(nullptr, aResult);
  1.2273 +      if (NS_SUCCEEDED(rv)) {
  1.2274 +        if (aProfileName)
  1.2275 +          aProfileName->Assign(NS_LITERAL_CSTRING("default"));
  1.2276 +        return NS_OK;
  1.2277 +      }
  1.2278 +    }
  1.2279 +  }
  1.2280 +
  1.2281 +  bool useDefault = true;
  1.2282 +  if (count > 1 && CanShowProfileManager()) {
  1.2283 +    aProfileSvc->GetStartWithLastProfile(&useDefault);
  1.2284 +  }
  1.2285 +
  1.2286 +  if (useDefault) {
  1.2287 +    nsCOMPtr<nsIToolkitProfile> profile;
  1.2288 +    // GetSelectedProfile will auto-select the only profile if there's just one
  1.2289 +    aProfileSvc->GetSelectedProfile(getter_AddRefs(profile));
  1.2290 +    if (profile) {
  1.2291 +      // If we're resetting a profile, create a new one and use it to startup.
  1.2292 +      if (gDoProfileReset) {
  1.2293 +        {
  1.2294 +          // Check that the source profile is not in use by temporarily acquiring its lock.
  1.2295 +          nsIProfileLock* tempProfileLock;
  1.2296 +          nsCOMPtr<nsIProfileUnlocker> unlocker;
  1.2297 +          rv = profile->Lock(getter_AddRefs(unlocker), &tempProfileLock);
  1.2298 +          if (NS_FAILED(rv))
  1.2299 +            return ProfileLockedDialog(profile, unlocker, aNative, &tempProfileLock);
  1.2300 +        }
  1.2301 +
  1.2302 +        nsCOMPtr<nsIToolkitProfile> newProfile;
  1.2303 +        rv = CreateResetProfile(aProfileSvc, getter_AddRefs(newProfile));
  1.2304 +        if (NS_SUCCEEDED(rv))
  1.2305 +          profile = newProfile;
  1.2306 +        else
  1.2307 +          gDoProfileReset = false;
  1.2308 +      }
  1.2309 +
  1.2310 +      // If you close Firefox and very quickly reopen it, the old Firefox may
  1.2311 +      // still be closing down. Rather than immediately showing the
  1.2312 +      // "Firefox is running but is not responding" message, we spend a few
  1.2313 +      // seconds retrying first.
  1.2314 +
  1.2315 +      static const int kLockRetrySeconds = 5;
  1.2316 +      static const int kLockRetrySleepMS = 100;
  1.2317 +
  1.2318 +      nsCOMPtr<nsIProfileUnlocker> unlocker;
  1.2319 +      const TimeStamp start = TimeStamp::Now();
  1.2320 +      do {
  1.2321 +        rv = profile->Lock(getter_AddRefs(unlocker), aResult);
  1.2322 +        if (NS_SUCCEEDED(rv)) {
  1.2323 +          StartupTimeline::Record(StartupTimeline::AFTER_PROFILE_LOCKED);
  1.2324 +          // Try to grab the profile name.
  1.2325 +          if (aProfileName) {
  1.2326 +            rv = profile->GetName(*aProfileName);
  1.2327 +            if (NS_FAILED(rv))
  1.2328 +              aProfileName->Truncate(0);
  1.2329 +          }
  1.2330 +          return NS_OK;
  1.2331 +        }
  1.2332 +        PR_Sleep(kLockRetrySleepMS);
  1.2333 +      } while (TimeStamp::Now() - start < TimeDuration::FromSeconds(kLockRetrySeconds));
  1.2334 +
  1.2335 +      return ProfileLockedDialog(profile, unlocker, aNative, aResult);
  1.2336 +    }
  1.2337 +  }
  1.2338 +
  1.2339 +  if (!CanShowProfileManager()) {
  1.2340 +    return NS_ERROR_FAILURE;
  1.2341 +  }
  1.2342 +
  1.2343 +  return ShowProfileManager(aProfileSvc, aNative);
  1.2344 +}
  1.2345 +
  1.2346 +/** 
  1.2347 + * Checks the compatibility.ini file to see if we have updated our application
  1.2348 + * or otherwise invalidated our caches. If the application has been updated, 
  1.2349 + * we return false; otherwise, we return true. We also write the status 
  1.2350 + * of the caches (valid/invalid) into the return param aCachesOK. The aCachesOK
  1.2351 + * is always invalid if the application has been updated. 
  1.2352 + */
  1.2353 +static bool
  1.2354 +CheckCompatibility(nsIFile* aProfileDir, const nsCString& aVersion,
  1.2355 +                   const nsCString& aOSABI, nsIFile* aXULRunnerDir,
  1.2356 +                   nsIFile* aAppDir, nsIFile* aFlagFile, 
  1.2357 +                   bool* aCachesOK)
  1.2358 +{
  1.2359 +  *aCachesOK = false;
  1.2360 +  nsCOMPtr<nsIFile> file;
  1.2361 +  aProfileDir->Clone(getter_AddRefs(file));
  1.2362 +  if (!file)
  1.2363 +    return false;
  1.2364 +  file->AppendNative(FILE_COMPATIBILITY_INFO);
  1.2365 +
  1.2366 +  nsINIParser parser;
  1.2367 +  nsresult rv = parser.Init(file);
  1.2368 +  if (NS_FAILED(rv))
  1.2369 +    return false;
  1.2370 +
  1.2371 +  nsAutoCString buf;
  1.2372 +  rv = parser.GetString("Compatibility", "LastVersion", buf);
  1.2373 +  if (NS_FAILED(rv) || !aVersion.Equals(buf))
  1.2374 +    return false;
  1.2375 +
  1.2376 +  rv = parser.GetString("Compatibility", "LastOSABI", buf);
  1.2377 +  if (NS_FAILED(rv) || !aOSABI.Equals(buf))
  1.2378 +    return false;
  1.2379 +
  1.2380 +  rv = parser.GetString("Compatibility", "LastPlatformDir", buf);
  1.2381 +  if (NS_FAILED(rv))
  1.2382 +    return false;
  1.2383 +
  1.2384 +  nsCOMPtr<nsIFile> lf;
  1.2385 +  rv = NS_NewNativeLocalFile(buf, false,
  1.2386 +                             getter_AddRefs(lf));
  1.2387 +  if (NS_FAILED(rv))
  1.2388 +    return false;
  1.2389 +
  1.2390 +  bool eq;
  1.2391 +  rv = lf->Equals(aXULRunnerDir, &eq);
  1.2392 +  if (NS_FAILED(rv) || !eq)
  1.2393 +    return false;
  1.2394 +
  1.2395 +  if (aAppDir) {
  1.2396 +    rv = parser.GetString("Compatibility", "LastAppDir", buf);
  1.2397 +    if (NS_FAILED(rv))
  1.2398 +      return false;
  1.2399 +
  1.2400 +    rv = NS_NewNativeLocalFile(buf, false,
  1.2401 +                               getter_AddRefs(lf));
  1.2402 +    if (NS_FAILED(rv))
  1.2403 +      return false;
  1.2404 +
  1.2405 +    rv = lf->Equals(aAppDir, &eq);
  1.2406 +    if (NS_FAILED(rv) || !eq)
  1.2407 +      return false;
  1.2408 +  }
  1.2409 +
  1.2410 +  // If we see this flag, caches are invalid.
  1.2411 +  rv = parser.GetString("Compatibility", "InvalidateCaches", buf);
  1.2412 +  *aCachesOK = (NS_FAILED(rv) || !buf.EqualsLiteral("1"));
  1.2413 +  
  1.2414 +  bool purgeCaches = false;
  1.2415 +  if (aFlagFile) {
  1.2416 +    aFlagFile->Exists(&purgeCaches);
  1.2417 +  }
  1.2418 +
  1.2419 +  *aCachesOK = !purgeCaches && *aCachesOK;
  1.2420 +  return true;
  1.2421 +}
  1.2422 +
  1.2423 +static void BuildVersion(nsCString &aBuf)
  1.2424 +{
  1.2425 +  aBuf.Assign(gAppData->version);
  1.2426 +  aBuf.Append('_');
  1.2427 +  aBuf.Append(gAppData->buildID);
  1.2428 +  aBuf.Append('/');
  1.2429 +  aBuf.Append(gToolkitBuildID);
  1.2430 +}
  1.2431 +
  1.2432 +static void
  1.2433 +WriteVersion(nsIFile* aProfileDir, const nsCString& aVersion,
  1.2434 +             const nsCString& aOSABI, nsIFile* aXULRunnerDir,
  1.2435 +             nsIFile* aAppDir, bool invalidateCache)
  1.2436 +{
  1.2437 +  nsCOMPtr<nsIFile> file;
  1.2438 +  aProfileDir->Clone(getter_AddRefs(file));
  1.2439 +  if (!file)
  1.2440 +    return;
  1.2441 +  file->AppendNative(FILE_COMPATIBILITY_INFO);
  1.2442 +
  1.2443 +  nsAutoCString platformDir;
  1.2444 +  aXULRunnerDir->GetNativePath(platformDir);
  1.2445 +
  1.2446 +  nsAutoCString appDir;
  1.2447 +  if (aAppDir)
  1.2448 +    aAppDir->GetNativePath(appDir);
  1.2449 +
  1.2450 +  PRFileDesc *fd = nullptr;
  1.2451 +  file->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0600, &fd);
  1.2452 +  if (!fd) {
  1.2453 +    NS_ERROR("could not create output stream");
  1.2454 +    return;
  1.2455 +  }
  1.2456 +
  1.2457 +  static const char kHeader[] = "[Compatibility]" NS_LINEBREAK
  1.2458 +                                "LastVersion=";
  1.2459 +
  1.2460 +  PR_Write(fd, kHeader, sizeof(kHeader) - 1);
  1.2461 +  PR_Write(fd, aVersion.get(), aVersion.Length());
  1.2462 +
  1.2463 +  static const char kOSABIHeader[] = NS_LINEBREAK "LastOSABI=";
  1.2464 +  PR_Write(fd, kOSABIHeader, sizeof(kOSABIHeader) - 1);
  1.2465 +  PR_Write(fd, aOSABI.get(), aOSABI.Length());
  1.2466 +
  1.2467 +  static const char kPlatformDirHeader[] = NS_LINEBREAK "LastPlatformDir=";
  1.2468 +
  1.2469 +  PR_Write(fd, kPlatformDirHeader, sizeof(kPlatformDirHeader) - 1);
  1.2470 +  PR_Write(fd, platformDir.get(), platformDir.Length());
  1.2471 +
  1.2472 +  static const char kAppDirHeader[] = NS_LINEBREAK "LastAppDir=";
  1.2473 +  if (aAppDir) {
  1.2474 +    PR_Write(fd, kAppDirHeader, sizeof(kAppDirHeader) - 1);
  1.2475 +    PR_Write(fd, appDir.get(), appDir.Length());
  1.2476 +  }
  1.2477 +
  1.2478 +  static const char kInvalidationHeader[] = NS_LINEBREAK "InvalidateCaches=1";
  1.2479 +  if (invalidateCache)
  1.2480 +    PR_Write(fd, kInvalidationHeader, sizeof(kInvalidationHeader) - 1);
  1.2481 +
  1.2482 +  static const char kNL[] = NS_LINEBREAK;
  1.2483 +  PR_Write(fd, kNL, sizeof(kNL) - 1);
  1.2484 +
  1.2485 +  PR_Close(fd);
  1.2486 +}
  1.2487 +
  1.2488 +/**
  1.2489 + * Returns true if the startup cache file was successfully removed.
  1.2490 + * Returns false if file->Clone fails at any point (OOM) or if unable
  1.2491 + * to remove the startup cache file. Note in particular the return value
  1.2492 + * is unaffected by a failure to remove extensions.ini
  1.2493 + */
  1.2494 +static bool
  1.2495 +RemoveComponentRegistries(nsIFile* aProfileDir, nsIFile* aLocalProfileDir,
  1.2496 +                                      bool aRemoveEMFiles)
  1.2497 +{
  1.2498 +  nsCOMPtr<nsIFile> file;
  1.2499 +  aProfileDir->Clone(getter_AddRefs(file));
  1.2500 +  if (!file)
  1.2501 +    return false;
  1.2502 +
  1.2503 +  if (aRemoveEMFiles) {
  1.2504 +    file->SetNativeLeafName(NS_LITERAL_CSTRING("extensions.ini"));
  1.2505 +    file->Remove(false);
  1.2506 +  }
  1.2507 +
  1.2508 +  aLocalProfileDir->Clone(getter_AddRefs(file));
  1.2509 +  if (!file)
  1.2510 +    return false;
  1.2511 +
  1.2512 +#if defined(XP_UNIX) || defined(XP_BEOS)
  1.2513 +#define PLATFORM_FASL_SUFFIX ".mfasl"
  1.2514 +#elif defined(XP_WIN)
  1.2515 +#define PLATFORM_FASL_SUFFIX ".mfl"
  1.2516 +#endif
  1.2517 +
  1.2518 +  file->AppendNative(NS_LITERAL_CSTRING("XUL" PLATFORM_FASL_SUFFIX));
  1.2519 +  file->Remove(false);
  1.2520 +  
  1.2521 +  file->SetNativeLeafName(NS_LITERAL_CSTRING("XPC" PLATFORM_FASL_SUFFIX));
  1.2522 +  file->Remove(false);
  1.2523 +
  1.2524 +  file->SetNativeLeafName(NS_LITERAL_CSTRING("startupCache"));
  1.2525 +  nsresult rv = file->Remove(true);
  1.2526 +  return NS_SUCCEEDED(rv) || rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST;
  1.2527 +}
  1.2528 +
  1.2529 +// To support application initiated restart via nsIAppStartup.quit, we
  1.2530 +// need to save various environment variables, and then restore them
  1.2531 +// before re-launching the application.
  1.2532 +
  1.2533 +static struct SavedVar {
  1.2534 +  const char *name;
  1.2535 +  char *value;
  1.2536 +} gSavedVars[] = {
  1.2537 +  {"XUL_APP_FILE", nullptr}
  1.2538 +};
  1.2539 +
  1.2540 +static void SaveStateForAppInitiatedRestart()
  1.2541 +{
  1.2542 +  for (size_t i = 0; i < ArrayLength(gSavedVars); ++i) {
  1.2543 +    const char *s = PR_GetEnv(gSavedVars[i].name);
  1.2544 +    if (s)
  1.2545 +      gSavedVars[i].value = PR_smprintf("%s=%s", gSavedVars[i].name, s);
  1.2546 +  }
  1.2547 +}
  1.2548 +
  1.2549 +static void RestoreStateForAppInitiatedRestart()
  1.2550 +{
  1.2551 +  for (size_t i = 0; i < ArrayLength(gSavedVars); ++i) {
  1.2552 +    if (gSavedVars[i].value)
  1.2553 +      PR_SetEnv(gSavedVars[i].value);
  1.2554 +  }
  1.2555 +}
  1.2556 +
  1.2557 +#ifdef MOZ_CRASHREPORTER
  1.2558 +// When we first initialize the crash reporter we don't have a profile,
  1.2559 +// so we set the minidump path to $TEMP.  Once we have a profile,
  1.2560 +// we set it to $PROFILE/minidumps, creating the directory
  1.2561 +// if needed.
  1.2562 +static void MakeOrSetMinidumpPath(nsIFile* profD)
  1.2563 +{
  1.2564 +  nsCOMPtr<nsIFile> dumpD;
  1.2565 +  profD->Clone(getter_AddRefs(dumpD));
  1.2566 +  
  1.2567 +  if(dumpD) {
  1.2568 +    bool fileExists;
  1.2569 +    //XXX: do some more error checking here
  1.2570 +    dumpD->Append(NS_LITERAL_STRING("minidumps"));
  1.2571 +    dumpD->Exists(&fileExists);
  1.2572 +    if(!fileExists) {
  1.2573 +      dumpD->Create(nsIFile::DIRECTORY_TYPE, 0700);
  1.2574 +    }
  1.2575 +
  1.2576 +    nsAutoString pathStr;
  1.2577 +    if(NS_SUCCEEDED(dumpD->GetPath(pathStr)))
  1.2578 +      CrashReporter::SetMinidumpPath(pathStr);
  1.2579 +  }
  1.2580 +}
  1.2581 +#endif
  1.2582 +
  1.2583 +const nsXREAppData* gAppData = nullptr;
  1.2584 +
  1.2585 +#ifdef MOZ_WIDGET_GTK
  1.2586 +#include "prlink.h"
  1.2587 +typedef void (*_g_set_application_name_fn)(const gchar *application_name);
  1.2588 +typedef void (*_gtk_window_set_auto_startup_notification_fn)(gboolean setting);
  1.2589 +
  1.2590 +static PRFuncPtr FindFunction(const char* aName)
  1.2591 +{
  1.2592 +  PRLibrary *lib = nullptr;
  1.2593 +  PRFuncPtr result = PR_FindFunctionSymbolAndLibrary(aName, &lib);
  1.2594 +  // Since the library was already loaded, we can safely unload it here.
  1.2595 +  if (lib) {
  1.2596 +    PR_UnloadLibrary(lib);
  1.2597 +  }
  1.2598 +  return result;
  1.2599 +}
  1.2600 +
  1.2601 +static void MOZ_gdk_display_close(GdkDisplay *display)
  1.2602 +{
  1.2603 +#if CLEANUP_MEMORY
  1.2604 +  // XXX wallpaper for bug 417163: don't close the Display if we're using the
  1.2605 +  // Qt theme because we crash (in Qt code) when using jemalloc.
  1.2606 +  bool theme_is_qt = false;
  1.2607 +  GtkSettings* settings =
  1.2608 +    gtk_settings_get_for_screen(gdk_display_get_default_screen(display));
  1.2609 +  gchar *theme_name;
  1.2610 +  g_object_get(settings, "gtk-theme-name", &theme_name, nullptr);
  1.2611 +  if (theme_name) {
  1.2612 +    theme_is_qt = strcmp(theme_name, "Qt") == 0;
  1.2613 +    if (theme_is_qt)
  1.2614 +      NS_WARNING("wallpaper bug 417163 for Qt theme");
  1.2615 +    g_free(theme_name);
  1.2616 +  }
  1.2617 +
  1.2618 +  // Get a (new) Pango context that holds a reference to the fontmap that
  1.2619 +  // GTK has been using.  gdk_pango_context_get() must be called while GTK
  1.2620 +  // has a default display.
  1.2621 +  PangoContext *pangoContext = gdk_pango_context_get();
  1.2622 +
  1.2623 +  bool buggyCairoShutdown = cairo_version() < CAIRO_VERSION_ENCODE(1, 4, 0);
  1.2624 +
  1.2625 +  if (!buggyCairoShutdown) {
  1.2626 +    // We should shut down GDK before we shut down libraries it depends on
  1.2627 +    // like Pango and cairo. But if cairo shutdown is buggy, we should
  1.2628 +    // shut down cairo first otherwise it may crash because of dangling
  1.2629 +    // references to Display objects (see bug 469831).
  1.2630 +    if (!theme_is_qt)
  1.2631 +      gdk_display_close(display);
  1.2632 +  }
  1.2633 +
  1.2634 +  // Clean up PangoCairo's default fontmap.
  1.2635 +  // This pango_fc_font_map_shutdown call (and the associated code to
  1.2636 +  // get the font map) really shouldn't be needed anymore, except that
  1.2637 +  // it's needed to avoid having cairo_debug_reset_static_data fatally
  1.2638 +  // assert if we've leaked other things that hold on to the fontmap,
  1.2639 +  // which is something that currently happens in mochitest-plugins.
  1.2640 +  // Even if it didn't happen in mochitest-plugins, we probably want to
  1.2641 +  // avoid the crash-on-leak problem since it makes it harder to use
  1.2642 +  // many of our leak tools to debug leaks.
  1.2643 +
  1.2644 +  // This doesn't take a reference.
  1.2645 +  PangoFontMap *fontmap = pango_context_get_font_map(pangoContext);
  1.2646 +  // Do some shutdown of the fontmap, which releases the fonts, clearing a
  1.2647 +  // bunch of circular references from the fontmap through the fonts back to
  1.2648 +  // itself.  The shutdown that this does is much less than what's done by
  1.2649 +  // the fontmap's finalize, though.
  1.2650 +  if (PANGO_IS_FC_FONT_MAP(fontmap))
  1.2651 +      pango_fc_font_map_shutdown(PANGO_FC_FONT_MAP(fontmap));
  1.2652 +  g_object_unref(pangoContext);
  1.2653 +
  1.2654 +  // Tell PangoCairo to release its default fontmap.
  1.2655 +  pango_cairo_font_map_set_default(nullptr);
  1.2656 +
  1.2657 +  // cairo_debug_reset_static_data() is prototyped through cairo.h included
  1.2658 +  // by gtk.h.
  1.2659 +#ifdef cairo_debug_reset_static_data
  1.2660 +#error "Looks like we're including Mozilla's cairo instead of system cairo"
  1.2661 +#endif
  1.2662 +  cairo_debug_reset_static_data();
  1.2663 +  // FIXME: Do we need to call this in non-GTK2 cases as well?
  1.2664 +  FcFini();
  1.2665 +
  1.2666 +  if (buggyCairoShutdown) {
  1.2667 +    if (!theme_is_qt)
  1.2668 +      gdk_display_close(display);
  1.2669 +  }
  1.2670 +#else // not CLEANUP_MEMORY
  1.2671 +  // Don't do anything to avoid running into driver bugs under XCloseDisplay().
  1.2672 +  // See bug 973192.
  1.2673 +  (void) display;
  1.2674 +#endif
  1.2675 +}
  1.2676 +#endif // MOZ_WIDGET_GTK2
  1.2677 +
  1.2678 +/** 
  1.2679 + * NSPR will search for the "nspr_use_zone_allocator" symbol throughout
  1.2680 + * the process and use it to determine whether the application defines its own
  1.2681 + * memory allocator or not.
  1.2682 + *
  1.2683 + * Since most applications (e.g. Firefox and Thunderbird) don't use any special
  1.2684 + * allocators and therefore don't define this symbol, NSPR must search the
  1.2685 + * entire process, which reduces startup performance.
  1.2686 + *
  1.2687 + * By defining the symbol here, we can avoid the wasted lookup and hopefully
  1.2688 + * improve startup performance.
  1.2689 + */
  1.2690 +NS_VISIBILITY_DEFAULT PRBool nspr_use_zone_allocator = PR_FALSE;
  1.2691 +
  1.2692 +#ifdef CAIRO_HAS_DWRITE_FONT
  1.2693 +
  1.2694 +#include <dwrite.h>
  1.2695 +
  1.2696 +#ifdef DEBUG_DWRITE_STARTUP
  1.2697 +
  1.2698 +#define LOGREGISTRY(msg) LogRegistryEvent(msg)
  1.2699 +
  1.2700 +// for use when monitoring process
  1.2701 +static void LogRegistryEvent(const wchar_t *msg)
  1.2702 +{
  1.2703 +  HKEY dummyKey;
  1.2704 +  HRESULT hr;
  1.2705 +  wchar_t buf[512];
  1.2706 +
  1.2707 +  wsprintf(buf, L" log %s", msg);
  1.2708 +  hr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, buf, 0, KEY_READ, &dummyKey);
  1.2709 +  if (SUCCEEDED(hr)) {
  1.2710 +    RegCloseKey(dummyKey);
  1.2711 +  }
  1.2712 +}
  1.2713 +#else
  1.2714 +
  1.2715 +#define LOGREGISTRY(msg)
  1.2716 +
  1.2717 +#endif
  1.2718 +
  1.2719 +static DWORD InitDwriteBG(LPVOID lpdwThreadParam)
  1.2720 +{
  1.2721 +  SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_BEGIN);
  1.2722 +  LOGREGISTRY(L"loading dwrite.dll");
  1.2723 +  HMODULE dwdll = LoadLibraryW(L"dwrite.dll");
  1.2724 +  if (dwdll) {
  1.2725 +    decltype(DWriteCreateFactory)* createDWriteFactory = (decltype(DWriteCreateFactory)*)
  1.2726 +      GetProcAddress(dwdll, "DWriteCreateFactory");
  1.2727 +    if (createDWriteFactory) {
  1.2728 +      LOGREGISTRY(L"creating dwrite factory");
  1.2729 +      IDWriteFactory *factory;
  1.2730 +      HRESULT hr = createDWriteFactory(
  1.2731 +        DWRITE_FACTORY_TYPE_SHARED,
  1.2732 +        __uuidof(IDWriteFactory),
  1.2733 +        reinterpret_cast<IUnknown**>(&factory));
  1.2734 +      if (SUCCEEDED(hr)) {
  1.2735 +        LOGREGISTRY(L"dwrite factory done");
  1.2736 +        factory->Release();
  1.2737 +        LOGREGISTRY(L"freed factory");
  1.2738 +      } else {
  1.2739 +        LOGREGISTRY(L"failed to create factory");
  1.2740 +      }
  1.2741 +    }
  1.2742 +  }
  1.2743 +  SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_END);
  1.2744 +  return 0;
  1.2745 +}
  1.2746 +#endif
  1.2747 +
  1.2748 +#ifdef USE_GLX_TEST
  1.2749 +bool fire_glxtest_process();
  1.2750 +#endif
  1.2751 +
  1.2752 +#if defined(XP_WIN) && defined(MOZ_METRO)
  1.2753 +#ifndef AHE_TYPE
  1.2754 +enum AHE_TYPE {
  1.2755 +  AHE_DESKTOP = 0,
  1.2756 +  AHE_IMMERSIVE = 1
  1.2757 +};
  1.2758 +#endif
  1.2759 +
  1.2760 +/*
  1.2761 + * The Windows launcher uses this value to decide what front end ui
  1.2762 + * to launch. We always launch the same ui unless the user
  1.2763 + * specifically asks to switch. Update the value on every startup
  1.2764 + * based on the environment requested.
  1.2765 + */
  1.2766 +void
  1.2767 +SetLastWinRunType(AHE_TYPE aType)
  1.2768 +{
  1.2769 +  HKEY key;
  1.2770 +  LONG result = RegOpenKeyExW(HKEY_CURRENT_USER,
  1.2771 +                              L"SOFTWARE\\Mozilla\\Firefox",
  1.2772 +                              0, KEY_WRITE, &key);
  1.2773 +  if (result != ERROR_SUCCESS) {
  1.2774 +    return;
  1.2775 +  }
  1.2776 +  DWORD value = (DWORD)aType;
  1.2777 +  result = RegSetValueEx(key, L"MetroLastAHE", 0, REG_DWORD,
  1.2778 +                         reinterpret_cast<LPBYTE>(&value),
  1.2779 +                         sizeof(DWORD));
  1.2780 +  RegCloseKey(key);
  1.2781 +}
  1.2782 +#endif // defined(XP_WIN) && defined(MOZ_METRO)
  1.2783 +
  1.2784 +#include "GeckoProfiler.h"
  1.2785 +
  1.2786 +// Encapsulates startup and shutdown state for XRE_main
  1.2787 +class XREMain
  1.2788 +{
  1.2789 +public:
  1.2790 +  XREMain() :
  1.2791 +    mScopedXPCom(nullptr)
  1.2792 +    , mAppData(nullptr)
  1.2793 +    , mStartOffline(false)
  1.2794 +    , mShuttingDown(false)
  1.2795 +#ifdef MOZ_ENABLE_XREMOTE
  1.2796 +    , mDisableRemote(false)
  1.2797 +#endif
  1.2798 +#if defined(MOZ_WIDGET_GTK)
  1.2799 +    , mGdkDisplay(nullptr)
  1.2800 +#endif
  1.2801 +  {};
  1.2802 +
  1.2803 +  ~XREMain() {
  1.2804 +    if (mAppData) {
  1.2805 +      delete mAppData;
  1.2806 +    }
  1.2807 +    if (mScopedXPCom) {
  1.2808 +      NS_WARNING("Scoped xpcom should have been deleted!");
  1.2809 +      delete mScopedXPCom;
  1.2810 +    }
  1.2811 +  }
  1.2812 +
  1.2813 +  int XRE_main(int argc, char* argv[], const nsXREAppData* aAppData);
  1.2814 +  int XRE_mainInit(bool* aExitFlag);
  1.2815 +  int XRE_mainStartup(bool* aExitFlag);
  1.2816 +  nsresult XRE_mainRun();
  1.2817 +  
  1.2818 +  nsCOMPtr<nsINativeAppSupport> mNativeApp;
  1.2819 +  nsCOMPtr<nsIToolkitProfileService> mProfileSvc;
  1.2820 +  nsCOMPtr<nsIFile> mProfD;
  1.2821 +  nsCOMPtr<nsIFile> mProfLD;
  1.2822 +  nsCOMPtr<nsIProfileLock> mProfileLock;
  1.2823 +#ifdef MOZ_ENABLE_XREMOTE
  1.2824 +  nsCOMPtr<nsIRemoteService> mRemoteService;
  1.2825 +#endif
  1.2826 +
  1.2827 +  ScopedXPCOMStartup* mScopedXPCom;
  1.2828 +  ScopedAppData* mAppData;
  1.2829 +  nsXREDirProvider mDirProvider;
  1.2830 +  nsAutoCString mProfileName;
  1.2831 +  nsAutoCString mDesktopStartupID;
  1.2832 +
  1.2833 +  bool mStartOffline;
  1.2834 +  bool mShuttingDown;
  1.2835 +#ifdef MOZ_ENABLE_XREMOTE
  1.2836 +  bool mDisableRemote;
  1.2837 +#endif
  1.2838 +
  1.2839 +#if defined(MOZ_WIDGET_GTK)
  1.2840 +  GdkDisplay* mGdkDisplay;
  1.2841 +#endif
  1.2842 +};
  1.2843 +
  1.2844 +/*
  1.2845 + * XRE_mainInit - Initial setup and command line parameter processing.
  1.2846 + * Main() will exit early if either return value != 0 or if aExitFlag is
  1.2847 + * true.
  1.2848 + */
  1.2849 +int
  1.2850 +XREMain::XRE_mainInit(bool* aExitFlag)
  1.2851 +{
  1.2852 +  if (!aExitFlag)
  1.2853 +    return 1;
  1.2854 +  *aExitFlag = false;
  1.2855 +
  1.2856 +  StartupTimeline::Record(StartupTimeline::MAIN);
  1.2857 +
  1.2858 +  nsresult rv;
  1.2859 +  ArgResult ar;
  1.2860 +
  1.2861 +#ifdef DEBUG
  1.2862 +  if (PR_GetEnv("XRE_MAIN_BREAK"))
  1.2863 +    NS_BREAK();
  1.2864 +#endif
  1.2865 +
  1.2866 +#ifdef USE_GLX_TEST
  1.2867 +  // bug 639842 - it's very important to fire this process BEFORE we set up
  1.2868 +  // error handling. indeed, this process is expected to be crashy, and we
  1.2869 +  // don't want the user to see its crashes. That's the whole reason for
  1.2870 +  // doing this in a separate process.
  1.2871 +  //
  1.2872 +  // This call will cause a fork and the fork will terminate itself separately
  1.2873 +  // from the usual shutdown sequence
  1.2874 +  fire_glxtest_process();
  1.2875 +#endif
  1.2876 +
  1.2877 +#if defined(XP_WIN) && defined(MOZ_METRO)
  1.2878 +  // Don't remove this arg, we want to pass it on to nsUpdateDriver 
  1.2879 +  if (CheckArg("metro-update", false, nullptr, false) == ARG_FOUND ||
  1.2880 +      XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Metro) {
  1.2881 +    // If we're doing a restart update that was initiated from metro land,
  1.2882 +    // we'll be running desktop to handle the actual update. Request that
  1.2883 +    // after the restart we launch into metro.
  1.2884 +    SetLastWinRunType(AHE_IMMERSIVE);
  1.2885 +  } else {
  1.2886 +    SetLastWinRunType(AHE_DESKTOP);
  1.2887 +  }
  1.2888 +#endif
  1.2889 +
  1.2890 +  SetupErrorHandling(gArgv[0]);
  1.2891 +
  1.2892 +#ifdef CAIRO_HAS_DWRITE_FONT
  1.2893 +  {
  1.2894 +    // Bug 602792 - when DWriteCreateFactory is called the dwrite client dll
  1.2895 +    // starts the FntCache service if it isn't already running (it's set
  1.2896 +    // to manual startup by default in Windows 7 RTM).  Subsequent DirectWrite
  1.2897 +    // calls cause the IDWriteFactory object to communicate with the FntCache
  1.2898 +    // service with a timeout; if there's no response after the timeout, the
  1.2899 +    // DirectWrite client library will assume the service isn't around and do
  1.2900 +    // manual font file I/O on _all_ system fonts.  To avoid this, load the
  1.2901 +    // dwrite library and create a factory as early as possible so that the
  1.2902 +    // FntCache service is ready by the time it's needed.
  1.2903 +
  1.2904 +    if (IsVistaOrLater()) {
  1.2905 +      CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)&InitDwriteBG,
  1.2906 +                   nullptr, 0, nullptr);
  1.2907 +    }
  1.2908 +  }
  1.2909 +#endif
  1.2910 +
  1.2911 +#ifdef XP_UNIX
  1.2912 +  const char *home = PR_GetEnv("HOME");
  1.2913 +  if (!home || !*home) {
  1.2914 +    struct passwd *pw = getpwuid(geteuid());
  1.2915 +    if (!pw || !pw->pw_dir) {
  1.2916 +      Output(true, "Could not determine HOME directory");
  1.2917 +      return 1;
  1.2918 +    }
  1.2919 +    SaveWordToEnv("HOME", nsDependentCString(pw->pw_dir));
  1.2920 +  }
  1.2921 +#endif
  1.2922 +
  1.2923 +#ifdef MOZ_ACCESSIBILITY_ATK
  1.2924 +  // Suppress atk-bridge init at startup, until mozilla accessibility is
  1.2925 +  // initialized.  This works after gnome 2.24.2.
  1.2926 +  SaveToEnv("NO_AT_BRIDGE=1");
  1.2927 +#endif
  1.2928 +
  1.2929 +  // Check for application.ini overrides
  1.2930 +  const char* override = nullptr;
  1.2931 +  ar = CheckArg("override", true, &override);
  1.2932 +  if (ar == ARG_BAD) {
  1.2933 +    Output(true, "Incorrect number of arguments passed to -override");
  1.2934 +    return 1;
  1.2935 +  }
  1.2936 +  else if (ar == ARG_FOUND) {
  1.2937 +    nsCOMPtr<nsIFile> overrideLF;
  1.2938 +    rv = XRE_GetFileFromPath(override, getter_AddRefs(overrideLF));
  1.2939 +    if (NS_FAILED(rv)) {
  1.2940 +      Output(true, "Error: unrecognized override.ini path.\n");
  1.2941 +      return 1;
  1.2942 +    }
  1.2943 +
  1.2944 +    rv = XRE_ParseAppData(overrideLF, mAppData);
  1.2945 +    if (NS_FAILED(rv)) {
  1.2946 +      Output(true, "Couldn't read override.ini");
  1.2947 +      return 1;
  1.2948 +    }
  1.2949 +  }
  1.2950 +
  1.2951 +  // Check sanity and correctness of app data.
  1.2952 +
  1.2953 +  if (!mAppData->name) {
  1.2954 +    Output(true, "Error: App:Name not specified in application.ini\n");
  1.2955 +    return 1;
  1.2956 +  }
  1.2957 +  if (!mAppData->buildID) {
  1.2958 +    Output(true, "Error: App:BuildID not specified in application.ini\n");
  1.2959 +    return 1;
  1.2960 +  }
  1.2961 +
  1.2962 +  // XXX Originally ScopedLogging was here? Now it's in XRE_main above
  1.2963 +  // XRE_mainInit.
  1.2964 +
  1.2965 +  if (!mAppData->xreDirectory) {
  1.2966 +    nsCOMPtr<nsIFile> lf;
  1.2967 +    rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
  1.2968 +    if (NS_FAILED(rv))
  1.2969 +      return 2;
  1.2970 +
  1.2971 +    nsCOMPtr<nsIFile> greDir;
  1.2972 +    rv = lf->GetParent(getter_AddRefs(greDir));
  1.2973 +    if (NS_FAILED(rv))
  1.2974 +      return 2;
  1.2975 +
  1.2976 +    greDir.forget(&mAppData->xreDirectory);
  1.2977 +  }
  1.2978 +
  1.2979 +  if (!mAppData->directory) {
  1.2980 +    NS_IF_ADDREF(mAppData->directory = mAppData->xreDirectory);
  1.2981 +  }
  1.2982 +
  1.2983 +  if (mAppData->size > offsetof(nsXREAppData, minVersion)) {
  1.2984 +    if (!mAppData->minVersion) {
  1.2985 +      Output(true, "Error: Gecko:MinVersion not specified in application.ini\n");
  1.2986 +      return 1;
  1.2987 +    }
  1.2988 +
  1.2989 +    if (!mAppData->maxVersion) {
  1.2990 +      // If no maxVersion is specified, we assume the app is only compatible
  1.2991 +      // with the initial preview release. Do not increment this number ever!
  1.2992 +      SetAllocatedString(mAppData->maxVersion, "1.*");
  1.2993 +    }
  1.2994 +
  1.2995 +    if (mozilla::Version(mAppData->minVersion) > gToolkitVersion ||
  1.2996 +        mozilla::Version(mAppData->maxVersion) < gToolkitVersion) {
  1.2997 +      Output(true, "Error: Platform version '%s' is not compatible with\n"
  1.2998 +             "minVersion >= %s\nmaxVersion <= %s\n",
  1.2999 +             gToolkitVersion,
  1.3000 +             mAppData->minVersion, mAppData->maxVersion);
  1.3001 +      return 1;
  1.3002 +    }
  1.3003 +  }
  1.3004 +
  1.3005 +  rv = mDirProvider.Initialize(mAppData->directory, mAppData->xreDirectory);
  1.3006 +  if (NS_FAILED(rv))
  1.3007 +    return 1;
  1.3008 +
  1.3009 +#ifdef MOZ_CRASHREPORTER
  1.3010 +  if (EnvHasValue("MOZ_CRASHREPORTER")) {
  1.3011 +    mAppData->flags |= NS_XRE_ENABLE_CRASH_REPORTER;
  1.3012 +  }
  1.3013 +
  1.3014 +  if ((mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER) &&
  1.3015 +      NS_SUCCEEDED(
  1.3016 +         CrashReporter::SetExceptionHandler(mAppData->xreDirectory))) {
  1.3017 +    CrashReporter::UpdateCrashEventsDir();
  1.3018 +    if (mAppData->crashReporterURL)
  1.3019 +      CrashReporter::SetServerURL(nsDependentCString(mAppData->crashReporterURL));
  1.3020 +
  1.3021 +    // pass some basic info from the app data
  1.3022 +    if (mAppData->vendor)
  1.3023 +      CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Vendor"),
  1.3024 +                                         nsDependentCString(mAppData->vendor));
  1.3025 +    if (mAppData->name)
  1.3026 +      CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ProductName"),
  1.3027 +                                         nsDependentCString(mAppData->name));
  1.3028 +    if (mAppData->ID)
  1.3029 +      CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ProductID"),
  1.3030 +                                         nsDependentCString(mAppData->ID));
  1.3031 +    if (mAppData->version)
  1.3032 +      CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Version"),
  1.3033 +                                         nsDependentCString(mAppData->version));
  1.3034 +    if (mAppData->buildID)
  1.3035 +      CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("BuildID"),
  1.3036 +                                         nsDependentCString(mAppData->buildID));
  1.3037 +
  1.3038 +    nsDependentCString releaseChannel(NS_STRINGIFY(MOZ_UPDATE_CHANNEL));
  1.3039 +    CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ReleaseChannel"),
  1.3040 +                                       releaseChannel);
  1.3041 +#ifdef MOZ_LINKER
  1.3042 +    CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("CrashAddressLikelyWrong"),
  1.3043 +                                       IsSignalHandlingBroken() ? NS_LITERAL_CSTRING("1")
  1.3044 +                                                                : NS_LITERAL_CSTRING("0"));
  1.3045 +#endif
  1.3046 +    CrashReporter::SetRestartArgs(gArgc, gArgv);
  1.3047 +
  1.3048 +    // annotate other data (user id etc)
  1.3049 +    nsCOMPtr<nsIFile> userAppDataDir;
  1.3050 +    if (NS_SUCCEEDED(mDirProvider.GetUserAppDataDirectory(
  1.3051 +                                                         getter_AddRefs(userAppDataDir)))) {
  1.3052 +      CrashReporter::SetupExtraData(userAppDataDir,
  1.3053 +                                    nsDependentCString(mAppData->buildID));
  1.3054 +
  1.3055 +      // see if we have a crashreporter-override.ini in the application directory
  1.3056 +      nsCOMPtr<nsIFile> overrideini;
  1.3057 +      bool exists;
  1.3058 +      if (NS_SUCCEEDED(mDirProvider.GetAppDir()->Clone(getter_AddRefs(overrideini))) &&
  1.3059 +          NS_SUCCEEDED(overrideini->AppendNative(NS_LITERAL_CSTRING("crashreporter-override.ini"))) &&
  1.3060 +          NS_SUCCEEDED(overrideini->Exists(&exists)) &&
  1.3061 +          exists) {
  1.3062 +#ifdef XP_WIN
  1.3063 +        nsAutoString overridePathW;
  1.3064 +        overrideini->GetPath(overridePathW);
  1.3065 +        NS_ConvertUTF16toUTF8 overridePath(overridePathW);
  1.3066 +#else
  1.3067 +        nsAutoCString overridePath;
  1.3068 +        overrideini->GetNativePath(overridePath);
  1.3069 +#endif
  1.3070 +
  1.3071 +        SaveWordToEnv("MOZ_CRASHREPORTER_STRINGS_OVERRIDE", overridePath);
  1.3072 +      }
  1.3073 +    }
  1.3074 +  }
  1.3075 +#endif
  1.3076 +
  1.3077 +#ifdef XP_MACOSX
  1.3078 +  if (EnvHasValue("MOZ_LAUNCHED_CHILD")) {
  1.3079 +    // This is needed, on relaunch, to force the OS to use the "Cocoa Dock
  1.3080 +    // API".  Otherwise the call to ReceiveNextEvent() below will make it
  1.3081 +    // use the "Carbon Dock API".  For more info see bmo bug 377166.
  1.3082 +    EnsureUseCocoaDockAPI();
  1.3083 +
  1.3084 +    // When the app relaunches, the original process exits.  This causes
  1.3085 +    // the dock tile to stop bouncing, lose the "running" triangle, and
  1.3086 +    // if the tile does not permanently reside in the Dock, even disappear.
  1.3087 +    // This can be confusing to the user, who is expecting the app to launch.
  1.3088 +    // Calling ReceiveNextEvent without requesting any event is enough to
  1.3089 +    // cause a dock tile for the child process to appear.
  1.3090 +    const EventTypeSpec kFakeEventList[] = { { INT_MAX, INT_MAX } };
  1.3091 +    EventRef event;
  1.3092 +    ::ReceiveNextEvent(GetEventTypeCount(kFakeEventList), kFakeEventList,
  1.3093 +                       kEventDurationNoWait, false, &event);
  1.3094 +  }
  1.3095 +
  1.3096 +  if (CheckArg("foreground")) {
  1.3097 +    // The original process communicates that it was in the foreground by
  1.3098 +    // adding this argument.  This new process, which is taking over for
  1.3099 +    // the old one, should make itself the active application.
  1.3100 +    ProcessSerialNumber psn;
  1.3101 +    if (::GetCurrentProcess(&psn) == noErr)
  1.3102 +      ::SetFrontProcess(&psn);
  1.3103 +  }
  1.3104 +#endif
  1.3105 +
  1.3106 +  SaveToEnv("MOZ_LAUNCHED_CHILD=");
  1.3107 +
  1.3108 +  gRestartArgc = gArgc;
  1.3109 +  gRestartArgv = (char**) malloc(sizeof(char*) * (gArgc + 1 + (override ? 2 : 0)));
  1.3110 +  if (!gRestartArgv) {
  1.3111 +    return 1;
  1.3112 +  }
  1.3113 +
  1.3114 +  int i;
  1.3115 +  for (i = 0; i < gArgc; ++i) {
  1.3116 +    gRestartArgv[i] = gArgv[i];
  1.3117 +  }
  1.3118 +  
  1.3119 +  // Add the -override argument back (it is removed automatically be CheckArg) if there is one
  1.3120 +  if (override) {
  1.3121 +    gRestartArgv[gRestartArgc++] = const_cast<char*>("-override");
  1.3122 +    gRestartArgv[gRestartArgc++] = const_cast<char*>(override);
  1.3123 +  }
  1.3124 +
  1.3125 +  gRestartArgv[gRestartArgc] = nullptr;
  1.3126 +  
  1.3127 +
  1.3128 +  if (EnvHasValue("MOZ_SAFE_MODE_RESTART")) {
  1.3129 +    gSafeMode = true;
  1.3130 +    // unset the env variable
  1.3131 +    SaveToEnv("MOZ_SAFE_MODE_RESTART=");
  1.3132 +  }
  1.3133 +
  1.3134 +  ar = CheckArg("safe-mode", true);
  1.3135 +  if (ar == ARG_BAD) {
  1.3136 +    PR_fprintf(PR_STDERR, "Error: argument -safe-mode is invalid when argument -osint is specified\n");
  1.3137 +    return 1;
  1.3138 +  } else if (ar == ARG_FOUND) {
  1.3139 +    gSafeMode = true;
  1.3140 +  }
  1.3141 +
  1.3142 +#ifdef XP_WIN
  1.3143 +  // If the shift key is pressed and the ctrl and / or alt keys are not pressed
  1.3144 +  // during startup start in safe mode. GetKeyState returns a short and the high
  1.3145 +  // order bit will be 1 if the key is pressed. By masking the returned short
  1.3146 +  // with 0x8000 the result will be 0 if the key is not pressed and non-zero
  1.3147 +  // otherwise.
  1.3148 +  if (GetKeyState(VK_SHIFT) & 0x8000 &&
  1.3149 +      !(GetKeyState(VK_CONTROL) & 0x8000) && !(GetKeyState(VK_MENU) & 0x8000)) {
  1.3150 +    gSafeMode = true;
  1.3151 +  }
  1.3152 +#endif
  1.3153 +
  1.3154 +#ifdef XP_MACOSX
  1.3155 +  if (GetCurrentEventKeyModifiers() & optionKey)
  1.3156 +    gSafeMode = true;
  1.3157 +#endif
  1.3158 +
  1.3159 +  // In the Tor Browser, remoting is disabled by default unless -osint is used.
  1.3160 +  bool allowRemote = (CheckArg("allow-remote") == ARG_FOUND);
  1.3161 +  if (!allowRemote && (CheckArg("osint", false, nullptr, false) != ARG_FOUND))
  1.3162 +      SaveToEnv("MOZ_NO_REMOTE=1");
  1.3163 +
  1.3164 +  // Handle -no-remote and -new-instance command line arguments. Setup
  1.3165 +  // the environment to better accommodate other components and various
  1.3166 +  // restart scenarios.
  1.3167 +  ar = CheckArg("no-remote", true);
  1.3168 +  if (ar == ARG_BAD) {
  1.3169 +    PR_fprintf(PR_STDERR, "Error: argument -no-remote is invalid when argument -osint is specified\n");
  1.3170 +    return 1;
  1.3171 +  } else if ((ar == ARG_FOUND) && allowRemote) {
  1.3172 +    PR_fprintf(PR_STDERR, "Error: argument -no-remote is invalid when argument -allow-remote is specified\n");
  1.3173 +    return 1;
  1.3174 +  }
  1.3175 +
  1.3176 +  ar = CheckArg("new-instance", true);
  1.3177 +  if (ar == ARG_BAD) {
  1.3178 +    PR_fprintf(PR_STDERR, "Error: argument -new-instance is invalid when argument -osint is specified\n");
  1.3179 +    return 1;
  1.3180 +  } else if (ar == ARG_FOUND) {
  1.3181 +    SaveToEnv("MOZ_NEW_INSTANCE=1");
  1.3182 +  }
  1.3183 +
  1.3184 +  // Handle -help and -version command line arguments.
  1.3185 +  // They should return quickly, so we deal with them here.
  1.3186 +  if (CheckArg("h") || CheckArg("help") || CheckArg("?")) {
  1.3187 +    DumpHelp();
  1.3188 +    *aExitFlag = true;
  1.3189 +    return 0;
  1.3190 +  }
  1.3191 +
  1.3192 +  if (CheckArg("v") || CheckArg("version")) {
  1.3193 +    DumpVersion();
  1.3194 +    *aExitFlag = true;
  1.3195 +    return 0;
  1.3196 +  }
  1.3197 +    
  1.3198 +#ifdef NS_TRACE_MALLOC
  1.3199 +  gArgc = NS_TraceMallocStartupArgs(gArgc, gArgv);
  1.3200 +#endif
  1.3201 +
  1.3202 +  rv = XRE_InitCommandLine(gArgc, gArgv);
  1.3203 +  NS_ENSURE_SUCCESS(rv, 1);
  1.3204 +
  1.3205 +  // Check for -register, which registers chrome and then exits immediately.
  1.3206 +  ar = CheckArg("register", true);
  1.3207 +  if (ar == ARG_BAD) {
  1.3208 +    PR_fprintf(PR_STDERR, "Error: argument -register is invalid when argument -osint is specified\n");
  1.3209 +    return 1;
  1.3210 +  } else if (ar == ARG_FOUND) {
  1.3211 +    ScopedXPCOMStartup xpcom;
  1.3212 +    rv = xpcom.Initialize();
  1.3213 +    NS_ENSURE_SUCCESS(rv, 1);
  1.3214 +    {
  1.3215 +      nsCOMPtr<nsIChromeRegistry> chromeReg =
  1.3216 +        mozilla::services::GetChromeRegistryService();
  1.3217 +      NS_ENSURE_TRUE(chromeReg, 1);
  1.3218 +
  1.3219 +      chromeReg->CheckForNewChrome();
  1.3220 +    }
  1.3221 +    *aExitFlag = true;
  1.3222 +    return 0;
  1.3223 +  }
  1.3224 +
  1.3225 +  if (PR_GetEnv("MOZ_RUN_GTEST")) {
  1.3226 +    int result;
  1.3227 +    // RunGTest will only be set if we're in xul-unit
  1.3228 +    if (mozilla::RunGTest) {
  1.3229 +      result = mozilla::RunGTest();
  1.3230 +    } else {
  1.3231 +      result = 1;
  1.3232 +      printf("TEST-UNEXPECTED-FAIL | gtest | Not compiled with enable-tests\n");
  1.3233 +    }
  1.3234 +    *aExitFlag = true;
  1.3235 +    return result;
  1.3236 +  }
  1.3237 +
  1.3238 +  return 0;
  1.3239 +}
  1.3240 +
  1.3241 +#ifdef MOZ_CRASHREPORTER
  1.3242 +#ifdef XP_WIN
  1.3243 +/**
  1.3244 + * Uses WMI to read some manufacturer information that may be useful for
  1.3245 + * diagnosing hardware-specific crashes. This function is best-effort; failures
  1.3246 + * shouldn't burden the caller. COM must be initialized before calling.
  1.3247 + */
  1.3248 +static void AnnotateSystemManufacturer()
  1.3249 +{
  1.3250 +  nsRefPtr<IWbemLocator> locator;
  1.3251 +
  1.3252 +  HRESULT hr = CoCreateInstance(CLSID_WbemLocator, nullptr, CLSCTX_INPROC_SERVER,
  1.3253 +                                IID_IWbemLocator, getter_AddRefs(locator));
  1.3254 +
  1.3255 +  if (FAILED(hr)) {
  1.3256 +    return;
  1.3257 +  }
  1.3258 +
  1.3259 +  nsRefPtr<IWbemServices> services;
  1.3260 +
  1.3261 +  hr = locator->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), nullptr, nullptr, nullptr,
  1.3262 +                              0, nullptr, nullptr, getter_AddRefs(services));
  1.3263 +
  1.3264 +  if (FAILED(hr)) {
  1.3265 +    return;
  1.3266 +  }
  1.3267 +
  1.3268 +  hr = CoSetProxyBlanket(services, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nullptr,
  1.3269 +                         RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE,
  1.3270 +                         nullptr, EOAC_NONE);
  1.3271 +
  1.3272 +  if (FAILED(hr)) {
  1.3273 +    return;
  1.3274 +  }
  1.3275 +
  1.3276 +  nsRefPtr<IEnumWbemClassObject> enumerator;
  1.3277 +
  1.3278 +  hr = services->ExecQuery(_bstr_t(L"WQL"), _bstr_t(L"SELECT * FROM Win32_BIOS"),
  1.3279 +                           WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
  1.3280 +                           nullptr, getter_AddRefs(enumerator));
  1.3281 +
  1.3282 +  if (FAILED(hr) || !enumerator) {
  1.3283 +    return;
  1.3284 +  }
  1.3285 +
  1.3286 +  nsRefPtr<IWbemClassObject> classObject;
  1.3287 +  ULONG results;
  1.3288 +
  1.3289 +  hr = enumerator->Next(WBEM_INFINITE, 1, getter_AddRefs(classObject), &results);
  1.3290 +
  1.3291 +  if (FAILED(hr) || results == 0) {
  1.3292 +    return;
  1.3293 +  }
  1.3294 +
  1.3295 +  VARIANT value;
  1.3296 +  VariantInit(&value);
  1.3297 +
  1.3298 +  hr = classObject->Get(L"Manufacturer", 0, &value, 0, 0);
  1.3299 +
  1.3300 +  if (SUCCEEDED(hr) && V_VT(&value) == VT_BSTR) {
  1.3301 +    CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("BIOS_Manufacturer"),
  1.3302 +                                       NS_ConvertUTF16toUTF8(V_BSTR(&value)));
  1.3303 +  }
  1.3304 +
  1.3305 +  VariantClear(&value);
  1.3306 +}
  1.3307 +
  1.3308 +static void PR_CALLBACK AnnotateSystemManufacturer_ThreadStart(void*)
  1.3309 +{
  1.3310 +  HRESULT hr = CoInitialize(nullptr);
  1.3311 +
  1.3312 +  if (FAILED(hr)) {
  1.3313 +    return;
  1.3314 +  }
  1.3315 +
  1.3316 +  AnnotateSystemManufacturer();
  1.3317 +
  1.3318 +  CoUninitialize();
  1.3319 +}
  1.3320 +#endif
  1.3321 +#endif
  1.3322 +
  1.3323 +namespace mozilla {
  1.3324 +  ShutdownChecksMode gShutdownChecks = SCM_NOTHING;
  1.3325 +}
  1.3326 +
  1.3327 +static void SetShutdownChecks() {
  1.3328 +  // Set default first. On debug builds we crash. On nightly and local
  1.3329 +  // builds we record. Nightlies will then send the info via telemetry,
  1.3330 +  // but it is usefull to have the data in about:telemetry in local builds
  1.3331 +  // too.
  1.3332 +
  1.3333 +#ifdef DEBUG
  1.3334 +  gShutdownChecks = SCM_CRASH;
  1.3335 +#else
  1.3336 +  const char* releaseChannel = NS_STRINGIFY(MOZ_UPDATE_CHANNEL);
  1.3337 +  if (strcmp(releaseChannel, "nightly") == 0 ||
  1.3338 +      strcmp(releaseChannel, "default") == 0) {
  1.3339 +    gShutdownChecks = SCM_RECORD;
  1.3340 +  } else {
  1.3341 +    gShutdownChecks = SCM_NOTHING;
  1.3342 +  }
  1.3343 +#endif
  1.3344 +
  1.3345 +  // We let an environment variable override the default so that addons
  1.3346 +  // authors can use it for debugging shutdown with released firefox versions.
  1.3347 +  const char* mozShutdownChecksEnv = PR_GetEnv("MOZ_SHUTDOWN_CHECKS");
  1.3348 +  if (mozShutdownChecksEnv) {
  1.3349 +    if (strcmp(mozShutdownChecksEnv, "crash") == 0) {
  1.3350 +      gShutdownChecks = SCM_CRASH;
  1.3351 +    } else if (strcmp(mozShutdownChecksEnv, "record") == 0) {
  1.3352 +      gShutdownChecks = SCM_RECORD;
  1.3353 +    } else if (strcmp(mozShutdownChecksEnv, "nothing") == 0) {
  1.3354 +      gShutdownChecks = SCM_NOTHING;
  1.3355 +    }
  1.3356 +  }
  1.3357 +
  1.3358 +}
  1.3359 +
  1.3360 +/*
  1.3361 + * XRE_mainStartup - Initializes the profile and various other services.
  1.3362 + * Main() will exit early if either return value != 0 or if aExitFlag is
  1.3363 + * true.
  1.3364 + */
  1.3365 +int
  1.3366 +XREMain::XRE_mainStartup(bool* aExitFlag)
  1.3367 +{
  1.3368 +  nsresult rv;
  1.3369 +
  1.3370 +  if (!aExitFlag)
  1.3371 +    return 1;
  1.3372 +  *aExitFlag = false;
  1.3373 +
  1.3374 +  SetShutdownChecks();
  1.3375 +
  1.3376 +
  1.3377 +  // Enable Telemetry IO Reporting on DEBUG, nightly and local builds
  1.3378 +#ifdef DEBUG
  1.3379 +  mozilla::Telemetry::InitIOReporting(gAppData->xreDirectory);
  1.3380 +#else
  1.3381 +  {
  1.3382 +    const char* releaseChannel = NS_STRINGIFY(MOZ_UPDATE_CHANNEL);
  1.3383 +    if (strcmp(releaseChannel, "nightly") == 0 ||
  1.3384 +        strcmp(releaseChannel, "default") == 0) {
  1.3385 +      mozilla::Telemetry::InitIOReporting(gAppData->xreDirectory);
  1.3386 +    }
  1.3387 +  }
  1.3388 +#endif /* DEBUG */
  1.3389 +
  1.3390 +#if defined(MOZ_WIDGET_GTK) || defined(MOZ_ENABLE_XREMOTE)
  1.3391 +  // Stash DESKTOP_STARTUP_ID in malloc'ed memory because gtk_init will clear it.
  1.3392 +#define HAVE_DESKTOP_STARTUP_ID
  1.3393 +  const char* desktopStartupIDEnv = PR_GetEnv("DESKTOP_STARTUP_ID");
  1.3394 +  if (desktopStartupIDEnv) {
  1.3395 +    mDesktopStartupID.Assign(desktopStartupIDEnv);
  1.3396 +  }
  1.3397 +#endif
  1.3398 +
  1.3399 +#if defined(MOZ_WIDGET_QT)
  1.3400 +  nsQAppInstance::AddRef(gArgc, gArgv, true);
  1.3401 +
  1.3402 +  QStringList nonQtArguments = qApp->arguments();
  1.3403 +  gQtOnlyArgc = 1;
  1.3404 +  gQtOnlyArgv = (char**) malloc(sizeof(char*) 
  1.3405 +                * (gRestartArgc - nonQtArguments.size() + 2));
  1.3406 +
  1.3407 +  // copy binary path
  1.3408 +  gQtOnlyArgv[0] = gRestartArgv[0];
  1.3409 +
  1.3410 +  for (int i = 1; i < gRestartArgc; ++i) {
  1.3411 +    if (!nonQtArguments.contains(gRestartArgv[i])) {
  1.3412 +      // copy arguments used by Qt for later
  1.3413 +      gQtOnlyArgv[gQtOnlyArgc++] = gRestartArgv[i];
  1.3414 +    }
  1.3415 +  }
  1.3416 +  gQtOnlyArgv[gQtOnlyArgc] = nullptr;
  1.3417 +#endif
  1.3418 +#if defined(MOZ_WIDGET_GTK)
  1.3419 +  // setup for private colormap.  Ideally we'd like to do this
  1.3420 +  // in nsAppShell::Create, but we need to get in before gtk
  1.3421 +  // has been initialized to make sure everything is running
  1.3422 +  // consistently.
  1.3423 +#if (MOZ_WIDGET_GTK == 2)
  1.3424 +  if (CheckArg("install"))
  1.3425 +    gdk_rgb_set_install(TRUE);
  1.3426 +#endif
  1.3427 +
  1.3428 +  // Set program name to the one defined in application.ini.
  1.3429 +  {
  1.3430 +    nsAutoCString program(gAppData->name);
  1.3431 +    ToLowerCase(program);
  1.3432 +    g_set_prgname(program.get());
  1.3433 +  }
  1.3434 +
  1.3435 +  // Initialize GTK here for splash.
  1.3436 +
  1.3437 +  // Open the display ourselves instead of using gtk_init, so that we can
  1.3438 +  // close it without fear that one day gtk might clean up the display it
  1.3439 +  // opens.
  1.3440 +  if (!gtk_parse_args(&gArgc, &gArgv))
  1.3441 +    return 1;
  1.3442 +
  1.3443 +  // display_name is owned by gdk.
  1.3444 +  const char *display_name = gdk_get_display_arg_name();
  1.3445 +  if (display_name) {
  1.3446 +    SaveWordToEnv("DISPLAY", nsDependentCString(display_name));
  1.3447 +  } else {
  1.3448 +    display_name = PR_GetEnv("DISPLAY");
  1.3449 +    if (!display_name) {
  1.3450 +      PR_fprintf(PR_STDERR, "Error: no display specified\n");
  1.3451 +      return 1;
  1.3452 +    }
  1.3453 +  }
  1.3454 +#endif /* MOZ_WIDGET_GTK2 */
  1.3455 +
  1.3456 +#ifdef MOZ_ENABLE_XREMOTE
  1.3457 +  // handle -remote now that xpcom is fired up
  1.3458 +  bool newInstance;
  1.3459 +  {
  1.3460 +    char *e = PR_GetEnv("MOZ_NO_REMOTE");
  1.3461 +    mDisableRemote = (e && *e);
  1.3462 +    if (mDisableRemote) {
  1.3463 +      newInstance = true;
  1.3464 +    } else {
  1.3465 +      e = PR_GetEnv("MOZ_NEW_INSTANCE");
  1.3466 +      newInstance = (e && *e);
  1.3467 +    }
  1.3468 +  }
  1.3469 +
  1.3470 +  const char* xremotearg;
  1.3471 +  ArgResult ar = CheckArg("remote", true, &xremotearg);
  1.3472 +  if (ar == ARG_BAD) {
  1.3473 +    PR_fprintf(PR_STDERR, "Error: -remote requires an argument\n");
  1.3474 +    return 1;
  1.3475 +  }
  1.3476 +  const char* desktopStartupIDPtr =
  1.3477 +    mDesktopStartupID.IsEmpty() ? nullptr : mDesktopStartupID.get();
  1.3478 +  if (ar) {
  1.3479 +    *aExitFlag = true;
  1.3480 +    return HandleRemoteArgument(xremotearg, desktopStartupIDPtr);
  1.3481 +  }
  1.3482 +
  1.3483 +  if (!newInstance) {
  1.3484 +    // Try to remote the entire command line. If this fails, start up normally.
  1.3485 +    RemoteResult rr = RemoteCommandLine(desktopStartupIDPtr);
  1.3486 +    if (rr == REMOTE_FOUND) {
  1.3487 +      *aExitFlag = true;
  1.3488 +      return 0;
  1.3489 +    }
  1.3490 +    else if (rr == REMOTE_ARG_BAD)
  1.3491 +      return 1;
  1.3492 +  }
  1.3493 +#endif
  1.3494 +#ifdef MOZ_X11
  1.3495 +  // Init X11 in thread-safe mode. Must be called prior to the first call to XOpenDisplay 
  1.3496 +  // (called inside gdk_display_open). This is a requirement for off main tread compositing.
  1.3497 +  // This is done only on X11 platforms if the environment variable MOZ_USE_OMTC is set so 
  1.3498 +  // as to avoid overhead when omtc is not used. 
  1.3499 +  //
  1.3500 +  // On nightly builds, we call this by default to enable OMTC for Electrolysis testing. On
  1.3501 +  // aurora, beta, and release builds, there is a small tpaint regression from enabling this
  1.3502 +  // call, so it sits behind an environment variable.
  1.3503 +  //
  1.3504 +  // An environment variable is used instead of a pref on X11 platforms because we start having 
  1.3505 +  // access to prefs long after the first call to XOpenDisplay which is hard to change due to 
  1.3506 +  // interdependencies in the initialization.
  1.3507 +# ifndef NIGHTLY_BUILD
  1.3508 +  if (PR_GetEnv("MOZ_USE_OMTC") ||
  1.3509 +      PR_GetEnv("MOZ_OMTC_ENABLED"))
  1.3510 +# endif
  1.3511 +  {
  1.3512 +    XInitThreads();
  1.3513 +  }
  1.3514 +#endif
  1.3515 +#if defined(MOZ_WIDGET_GTK)
  1.3516 +  mGdkDisplay = gdk_display_open(display_name);
  1.3517 +  if (!mGdkDisplay) {
  1.3518 +    PR_fprintf(PR_STDERR, "Error: cannot open display: %s\n", display_name);
  1.3519 +    return 1;
  1.3520 +  }
  1.3521 +  gdk_display_manager_set_default_display (gdk_display_manager_get(),
  1.3522 +                                           mGdkDisplay);
  1.3523 +    
  1.3524 +  // g_set_application_name () is only defined in glib2.2 and higher.
  1.3525 +  _g_set_application_name_fn _g_set_application_name =
  1.3526 +    (_g_set_application_name_fn)FindFunction("g_set_application_name");
  1.3527 +  if (_g_set_application_name) {
  1.3528 +    _g_set_application_name(mAppData->name);
  1.3529 +  }
  1.3530 +  _gtk_window_set_auto_startup_notification_fn _gtk_window_set_auto_startup_notification =
  1.3531 +    (_gtk_window_set_auto_startup_notification_fn)FindFunction("gtk_window_set_auto_startup_notification");
  1.3532 +  if (_gtk_window_set_auto_startup_notification) {
  1.3533 +    _gtk_window_set_auto_startup_notification(false);
  1.3534 +  }
  1.3535 +
  1.3536 +#if (MOZ_WIDGET_GTK == 2)
  1.3537 +  gtk_widget_set_default_colormap(gdk_rgb_get_colormap());
  1.3538 +#endif /* (MOZ_WIDGET_GTK == 2) */
  1.3539 +#endif /* defined(MOZ_WIDGET_GTK) */
  1.3540 +#ifdef MOZ_X11
  1.3541 +  // Do this after initializing GDK, or GDK will install its own handler.
  1.3542 +  InstallX11ErrorHandler();
  1.3543 +#endif
  1.3544 +
  1.3545 +  // Call the code to install our handler
  1.3546 +#ifdef MOZ_JPROF
  1.3547 +  setupProfilingStuff();
  1.3548 +#endif
  1.3549 +
  1.3550 +  rv = NS_CreateNativeAppSupport(getter_AddRefs(mNativeApp));
  1.3551 +  if (NS_FAILED(rv))
  1.3552 +    return 1;
  1.3553 +
  1.3554 +  bool canRun = false;
  1.3555 +  rv = mNativeApp->Start(&canRun);
  1.3556 +  if (NS_FAILED(rv) || !canRun) {
  1.3557 +    return 1;
  1.3558 +  }
  1.3559 +
  1.3560 +#if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK)
  1.3561 +  // DESKTOP_STARTUP_ID is cleared now,
  1.3562 +  // we recover it in case we need a restart.
  1.3563 +  if (!mDesktopStartupID.IsEmpty()) {
  1.3564 +    nsAutoCString desktopStartupEnv;
  1.3565 +    desktopStartupEnv.AssignLiteral("DESKTOP_STARTUP_ID=");
  1.3566 +    desktopStartupEnv.Append(mDesktopStartupID);
  1.3567 +    // Leak it with extreme prejudice!
  1.3568 +    PR_SetEnv(ToNewCString(desktopStartupEnv));
  1.3569 +  }
  1.3570 +#endif
  1.3571 +
  1.3572 +#if defined(USE_MOZ_UPDATER)
  1.3573 +  // Check for and process any available updates
  1.3574 +  nsCOMPtr<nsIFile> updRoot;
  1.3575 +  bool persistent;
  1.3576 +  rv = mDirProvider.GetFile(XRE_UPDATE_ROOT_DIR, &persistent,
  1.3577 +                            getter_AddRefs(updRoot));
  1.3578 +  // XRE_UPDATE_ROOT_DIR may fail. Fallback to appDir if failed
  1.3579 +  if (NS_FAILED(rv))
  1.3580 +    updRoot = mDirProvider.GetAppDir();
  1.3581 +
  1.3582 +  // If the MOZ_PROCESS_UPDATES environment variable already exists, then
  1.3583 +  // we are being called from the callback application.
  1.3584 +  if (EnvHasValue("MOZ_PROCESS_UPDATES")) {
  1.3585 +    // If the caller has asked us to log our arguments, do so.  This is used
  1.3586 +    // to make sure that the maintenance service successfully launches the
  1.3587 +    // callback application.
  1.3588 +    const char *logFile = nullptr;
  1.3589 +    if (ARG_FOUND == CheckArg("dump-args", false, &logFile)) {
  1.3590 +      FILE* logFP = fopen(logFile, "wb");
  1.3591 +      if (logFP) {
  1.3592 +        for (int i = 1; i < gRestartArgc; ++i) {
  1.3593 +          fprintf(logFP, "%s\n", gRestartArgv[i]);
  1.3594 +        }
  1.3595 +        fclose(logFP);
  1.3596 +      }
  1.3597 +    }
  1.3598 +    *aExitFlag = true;
  1.3599 +    return 0;
  1.3600 +  }
  1.3601 +
  1.3602 +  // Support for processing an update and exiting. The MOZ_PROCESS_UPDATES
  1.3603 +  // environment variable will be part of the updater's environment and the
  1.3604 +  // application that is relaunched by the updater. When the application is
  1.3605 +  // relaunched by the updater it will be removed below and the application
  1.3606 +  // will exit.
  1.3607 +  if (CheckArg("process-updates")) {
  1.3608 +    SaveToEnv("MOZ_PROCESS_UPDATES=1");
  1.3609 +  }
  1.3610 +  nsCOMPtr<nsIFile> exeFile, exeDir;
  1.3611 +  rv = mDirProvider.GetFile(XRE_EXECUTABLE_FILE, &persistent,
  1.3612 +                            getter_AddRefs(exeFile));
  1.3613 +  NS_ENSURE_SUCCESS(rv, 1);
  1.3614 +  rv = exeFile->GetParent(getter_AddRefs(exeDir));
  1.3615 +  NS_ENSURE_SUCCESS(rv, 1);
  1.3616 +#ifdef TOR_BROWSER_UPDATE
  1.3617 +  nsAutoCString compatVersion(TOR_BROWSER_VERSION);
  1.3618 +#endif
  1.3619 +  ProcessUpdates(mDirProvider.GetGREDir(),
  1.3620 +                 exeDir,
  1.3621 +                 updRoot,
  1.3622 +                 gRestartArgc,
  1.3623 +                 gRestartArgv,
  1.3624 +#ifdef TOR_BROWSER_UPDATE
  1.3625 +                 compatVersion.get()
  1.3626 +#else
  1.3627 +                 mAppData->version
  1.3628 +#endif
  1.3629 +                 );
  1.3630 +  if (EnvHasValue("MOZ_PROCESS_UPDATES")) {
  1.3631 +    SaveToEnv("MOZ_PROCESS_UPDATES=");
  1.3632 +    *aExitFlag = true;
  1.3633 +    return 0;
  1.3634 +  }
  1.3635 +#if defined(XP_WIN) && defined(MOZ_METRO)
  1.3636 +  if (CheckArg("metro-update", false) == ARG_FOUND) {
  1.3637 +    *aExitFlag = true;
  1.3638 +    return 0;
  1.3639 +  }
  1.3640 +#endif
  1.3641 +#endif
  1.3642 +
  1.3643 +  rv = NS_NewToolkitProfileService(getter_AddRefs(mProfileSvc));
  1.3644 +  if (rv == NS_ERROR_FILE_ACCESS_DENIED) {
  1.3645 +    PR_fprintf(PR_STDERR, "Error: Access was denied while trying to open files in " \
  1.3646 +                "your profile directory.\n");
  1.3647 +  }
  1.3648 +  if (NS_FAILED(rv)) {
  1.3649 +    // We failed to choose or create profile - notify user and quit
  1.3650 +    ProfileMissingDialog(mNativeApp);
  1.3651 +    return 1;
  1.3652 +  }
  1.3653 +
  1.3654 +  rv = SelectProfile(getter_AddRefs(mProfileLock), mProfileSvc, mNativeApp, &mStartOffline,
  1.3655 +                      &mProfileName);
  1.3656 +  if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ||
  1.3657 +      rv == NS_ERROR_ABORT) {
  1.3658 +    *aExitFlag = true;
  1.3659 +    return 0;
  1.3660 +  }
  1.3661 +
  1.3662 +  if (NS_FAILED(rv)) {
  1.3663 +    // We failed to choose or create profile - notify user and quit
  1.3664 +    ProfileMissingDialog(mNativeApp);
  1.3665 +    return 1;
  1.3666 +  }
  1.3667 +  gProfileLock = mProfileLock;
  1.3668 +
  1.3669 +  rv = mProfileLock->GetDirectory(getter_AddRefs(mProfD));
  1.3670 +  NS_ENSURE_SUCCESS(rv, 1);
  1.3671 +
  1.3672 +  rv = mProfileLock->GetLocalDirectory(getter_AddRefs(mProfLD));
  1.3673 +  NS_ENSURE_SUCCESS(rv, 1);
  1.3674 +
  1.3675 +  rv = mDirProvider.SetProfile(mProfD, mProfLD);
  1.3676 +  NS_ENSURE_SUCCESS(rv, 1);
  1.3677 +
  1.3678 +  //////////////////////// NOW WE HAVE A PROFILE ////////////////////////
  1.3679 +
  1.3680 +  mozilla::Telemetry::SetProfileDir(mProfD);
  1.3681 +
  1.3682 +#ifdef MOZ_CRASHREPORTER
  1.3683 +  if (mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER)
  1.3684 +      MakeOrSetMinidumpPath(mProfD);
  1.3685 +
  1.3686 +  CrashReporter::UpdateCrashEventsDir();
  1.3687 +#endif
  1.3688 +
  1.3689 +  nsAutoCString version;
  1.3690 +  BuildVersion(version);
  1.3691 +
  1.3692 +#ifdef TARGET_OS_ABI
  1.3693 +  NS_NAMED_LITERAL_CSTRING(osABI, TARGET_OS_ABI);
  1.3694 +#else
  1.3695 +  // No TARGET_XPCOM_ABI, but at least the OS is known
  1.3696 +  NS_NAMED_LITERAL_CSTRING(osABI, OS_TARGET "_UNKNOWN");
  1.3697 +#endif
  1.3698 +
  1.3699 +  // Check for version compatibility with the last version of the app this 
  1.3700 +  // profile was started with.  The format of the version stamp is defined
  1.3701 +  // by the BuildVersion function.
  1.3702 +  // Also check to see if something has happened to invalidate our
  1.3703 +  // fastload caches, like an extension upgrade or installation.
  1.3704 + 
  1.3705 +  // If we see .purgecaches, that means someone did a make. 
  1.3706 +  // Re-register components to catch potential changes.
  1.3707 +  nsCOMPtr<nsIFile> flagFile;
  1.3708 +
  1.3709 +  rv = NS_ERROR_FILE_NOT_FOUND;
  1.3710 +  nsCOMPtr<nsIFile> fFlagFile;
  1.3711 +  if (mAppData->directory) {
  1.3712 +    rv = mAppData->directory->Clone(getter_AddRefs(fFlagFile));
  1.3713 +  }
  1.3714 +  flagFile = do_QueryInterface(fFlagFile);
  1.3715 +  if (flagFile) {
  1.3716 +    flagFile->AppendNative(FILE_INVALIDATE_CACHES);
  1.3717 +  }
  1.3718 +
  1.3719 +  bool cachesOK;
  1.3720 +  bool versionOK = CheckCompatibility(mProfD, version, osABI, 
  1.3721 +                                      mDirProvider.GetGREDir(),
  1.3722 +                                      mAppData->directory, flagFile,
  1.3723 +                                      &cachesOK);
  1.3724 +  if (CheckArg("purgecaches")) {
  1.3725 +    cachesOK = false;
  1.3726 +  }
  1.3727 +  if (PR_GetEnv("MOZ_PURGE_CACHES")) {
  1.3728 +    cachesOK = false;
  1.3729 +  }
  1.3730 + 
  1.3731 +  // Every time a profile is loaded by a build with a different version,
  1.3732 +  // it updates the compatibility.ini file saying what version last wrote
  1.3733 +  // the fastload caches.  On subsequent launches if the version matches, 
  1.3734 +  // there is no need for re-registration.  If the user loads the same
  1.3735 +  // profile in different builds the component registry must be
  1.3736 +  // re-generated to prevent mysterious component loading failures.
  1.3737 +  //
  1.3738 +  bool startupCacheValid = true;
  1.3739 +  if (gSafeMode) {
  1.3740 +    startupCacheValid = RemoveComponentRegistries(mProfD, mProfLD, false);
  1.3741 +    WriteVersion(mProfD, NS_LITERAL_CSTRING("Safe Mode"), osABI,
  1.3742 +                 mDirProvider.GetGREDir(), mAppData->directory, !startupCacheValid);
  1.3743 +  }
  1.3744 +  else if (versionOK) {
  1.3745 +    if (!cachesOK) {
  1.3746 +      // Remove caches, forcing component re-registration.
  1.3747 +      // The new list of additional components directories is derived from
  1.3748 +      // information in "extensions.ini".
  1.3749 +      startupCacheValid = RemoveComponentRegistries(mProfD, mProfLD, false);
  1.3750 +        
  1.3751 +      // Rewrite compatibility.ini to remove the flag
  1.3752 +      WriteVersion(mProfD, version, osABI,
  1.3753 +                   mDirProvider.GetGREDir(), mAppData->directory, !startupCacheValid);
  1.3754 +    }
  1.3755 +    // Nothing need be done for the normal startup case.
  1.3756 +  }
  1.3757 +  else {
  1.3758 +    // Remove caches, forcing component re-registration
  1.3759 +    // with the default set of components (this disables any potentially
  1.3760 +    // troublesome incompatible XPCOM components). 
  1.3761 +    startupCacheValid = RemoveComponentRegistries(mProfD, mProfLD, true);
  1.3762 +
  1.3763 +    // Write out version
  1.3764 +    WriteVersion(mProfD, version, osABI,
  1.3765 +                 mDirProvider.GetGREDir(), mAppData->directory, !startupCacheValid);
  1.3766 +  }
  1.3767 +
  1.3768 +  if (!startupCacheValid)
  1.3769 +    StartupCache::IgnoreDiskCache();
  1.3770 +
  1.3771 +  if (flagFile) {
  1.3772 +    flagFile->Remove(true);
  1.3773 +  }
  1.3774 +
  1.3775 +  return 0;
  1.3776 +}
  1.3777 +
  1.3778 +/*
  1.3779 + * XRE_mainRun - Command line startup, profile migration, and
  1.3780 + * the calling of appStartup->Run().
  1.3781 + */
  1.3782 +nsresult
  1.3783 +XREMain::XRE_mainRun()
  1.3784 +{
  1.3785 +  nsresult rv = NS_OK;
  1.3786 +  NS_ASSERTION(mScopedXPCom, "Scoped xpcom not initialized.");
  1.3787 +
  1.3788 +#ifdef NS_FUNCTION_TIMER
  1.3789 +  // initialize some common services, so we don't pay the cost for these at odd times later on;
  1.3790 +  // SetWindowCreator -> ChromeRegistry -> IOService -> SocketTransportService -> (nspr wspm init), Prefs
  1.3791 +  {
  1.3792 +    nsCOMPtr<nsISupports> comp;
  1.3793 +
  1.3794 +    comp = do_GetService("@mozilla.org/preferences-service;1");
  1.3795 +
  1.3796 +    comp = do_GetService("@mozilla.org/network/socket-transport-service;1");
  1.3797 +
  1.3798 +    comp = do_GetService("@mozilla.org/network/dns-service;1");
  1.3799 +
  1.3800 +    comp = do_GetService("@mozilla.org/network/io-service;1");
  1.3801 +
  1.3802 +    comp = do_GetService("@mozilla.org/chrome/chrome-registry;1");
  1.3803 +
  1.3804 +    comp = do_GetService("@mozilla.org/focus-event-suppressor-service;1");
  1.3805 +  }
  1.3806 +#endif
  1.3807 +
  1.3808 +  rv = mScopedXPCom->SetWindowCreator(mNativeApp);
  1.3809 +  NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  1.3810 +
  1.3811 +#ifdef MOZ_CRASHREPORTER
  1.3812 +  // tell the crash reporter to also send the release channel
  1.3813 +  nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &rv);
  1.3814 +  if (NS_SUCCEEDED(rv)) {
  1.3815 +    nsCOMPtr<nsIPrefBranch> defaultPrefBranch;
  1.3816 +    rv = prefs->GetDefaultBranch(nullptr, getter_AddRefs(defaultPrefBranch));
  1.3817 +
  1.3818 +    if (NS_SUCCEEDED(rv)) {
  1.3819 +      nsXPIDLCString sval;
  1.3820 +      rv = defaultPrefBranch->GetCharPref("app.update.channel", getter_Copies(sval));
  1.3821 +      if (NS_SUCCEEDED(rv)) {
  1.3822 +        CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ReleaseChannel"),
  1.3823 +                                            sval);
  1.3824 +      }
  1.3825 +    }
  1.3826 +  }
  1.3827 +  // Needs to be set after xpcom initialization.
  1.3828 +  CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("FramePoisonBase"),
  1.3829 +                                     nsPrintfCString("%.16llx", uint64_t(gMozillaPoisonBase)));
  1.3830 +  CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("FramePoisonSize"),
  1.3831 +                                     nsPrintfCString("%lu", uint32_t(gMozillaPoisonSize)));
  1.3832 +
  1.3833 +#ifdef XP_WIN
  1.3834 +  PR_CreateThread(PR_USER_THREAD, AnnotateSystemManufacturer_ThreadStart, 0,
  1.3835 +                  PR_PRIORITY_LOW, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0);
  1.3836 +#endif
  1.3837 +
  1.3838 +#endif
  1.3839 +
  1.3840 +  if (mStartOffline) {
  1.3841 +    nsCOMPtr<nsIIOService2> io (do_GetService("@mozilla.org/network/io-service;1"));
  1.3842 +    NS_ENSURE_TRUE(io, NS_ERROR_FAILURE);
  1.3843 +    io->SetManageOfflineStatus(false);
  1.3844 +    io->SetOffline(true);
  1.3845 +  }
  1.3846 +
  1.3847 +  {
  1.3848 +    nsCOMPtr<nsIObserver> startupNotifier
  1.3849 +      (do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID, &rv));
  1.3850 +    NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  1.3851 +
  1.3852 +    startupNotifier->Observe(nullptr, APPSTARTUP_TOPIC, nullptr);
  1.3853 +  }
  1.3854 +
  1.3855 +  nsCOMPtr<nsIAppStartup> appStartup
  1.3856 +    (do_GetService(NS_APPSTARTUP_CONTRACTID));
  1.3857 +  NS_ENSURE_TRUE(appStartup, NS_ERROR_FAILURE);
  1.3858 +
  1.3859 +  if (gDoMigration) {
  1.3860 +    nsCOMPtr<nsIFile> file;
  1.3861 +    mDirProvider.GetAppDir()->Clone(getter_AddRefs(file));
  1.3862 +    file->AppendNative(NS_LITERAL_CSTRING("override.ini"));
  1.3863 +    nsINIParser parser;
  1.3864 +    nsresult rv = parser.Init(file);
  1.3865 +    if (NS_SUCCEEDED(rv)) {
  1.3866 +      nsAutoCString buf;
  1.3867 +      rv = parser.GetString("XRE", "EnableProfileMigrator", buf);
  1.3868 +      if (NS_SUCCEEDED(rv)) {
  1.3869 +        if (buf[0] == '0' || buf[0] == 'f' || buf[0] == 'F') {
  1.3870 +          gDoMigration = false;
  1.3871 +        }
  1.3872 +      }
  1.3873 +    }
  1.3874 +  }
  1.3875 +
  1.3876 +  {
  1.3877 +    nsCOMPtr<nsIToolkitProfile> selectedProfile;
  1.3878 +    if (gDoProfileReset) {
  1.3879 +      // At this point we can be sure that profile reset is happening on the default profile.
  1.3880 +      rv = mProfileSvc->GetSelectedProfile(getter_AddRefs(selectedProfile));
  1.3881 +      if (NS_FAILED(rv)) {
  1.3882 +        gDoProfileReset = false;
  1.3883 +        return NS_ERROR_FAILURE;
  1.3884 +      }
  1.3885 +    }
  1.3886 +
  1.3887 +    // Profile Migration
  1.3888 +    if (mAppData->flags & NS_XRE_ENABLE_PROFILE_MIGRATOR && gDoMigration) {
  1.3889 +      gDoMigration = false;
  1.3890 +      nsCOMPtr<nsIProfileMigrator> pm(do_CreateInstance(NS_PROFILEMIGRATOR_CONTRACTID));
  1.3891 +      if (pm) {
  1.3892 +        nsAutoCString aKey;
  1.3893 +        if (gDoProfileReset) {
  1.3894 +          // Automatically migrate from the current application if we just
  1.3895 +          // reset the profile.
  1.3896 +          aKey = MOZ_APP_NAME;
  1.3897 +        }
  1.3898 +        pm->Migrate(&mDirProvider, aKey);
  1.3899 +      }
  1.3900 +    }
  1.3901 +
  1.3902 +    if (gDoProfileReset) {
  1.3903 +      nsresult backupCreated = ProfileResetCleanup(selectedProfile);
  1.3904 +      if (NS_FAILED(backupCreated)) NS_WARNING("Could not cleanup the profile that was reset");
  1.3905 +
  1.3906 +      // Set the new profile as the default after we're done cleaning up the old default.
  1.3907 +      rv = SetCurrentProfileAsDefault(mProfileSvc, mProfD);
  1.3908 +      if (NS_FAILED(rv)) NS_WARNING("Could not set current profile as the default");
  1.3909 +    }
  1.3910 +  }
  1.3911 +
  1.3912 +  mDirProvider.DoStartup();
  1.3913 +
  1.3914 +#ifdef MOZ_CRASHREPORTER
  1.3915 +  nsCString userAgentLocale;
  1.3916 +  if (NS_SUCCEEDED(Preferences::GetCString("general.useragent.locale", &userAgentLocale))) {
  1.3917 +    CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("useragent_locale"), userAgentLocale);
  1.3918 +  }
  1.3919 +#endif
  1.3920 +
  1.3921 +  appStartup->GetShuttingDown(&mShuttingDown);
  1.3922 +
  1.3923 +  nsCOMPtr<nsICommandLineRunner> cmdLine;
  1.3924 +
  1.3925 +  nsCOMPtr<nsIFile> workingDir;
  1.3926 +  rv = NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR, getter_AddRefs(workingDir));
  1.3927 +  NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  1.3928 +
  1.3929 +  if (!mShuttingDown) {
  1.3930 +    cmdLine = do_CreateInstance("@mozilla.org/toolkit/command-line;1");
  1.3931 +    NS_ENSURE_TRUE(cmdLine, NS_ERROR_FAILURE);
  1.3932 +
  1.3933 +    rv = cmdLine->Init(gArgc, gArgv, workingDir,
  1.3934 +                       nsICommandLine::STATE_INITIAL_LAUNCH);
  1.3935 +    NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  1.3936 +
  1.3937 +    /* Special-case services that need early access to the command
  1.3938 +        line. */
  1.3939 +    nsCOMPtr<nsIObserverService> obsService =
  1.3940 +      mozilla::services::GetObserverService();
  1.3941 +    if (obsService) {
  1.3942 +      obsService->NotifyObservers(cmdLine, "command-line-startup", nullptr);
  1.3943 +    }
  1.3944 +  }
  1.3945 +
  1.3946 +  SaveStateForAppInitiatedRestart();
  1.3947 +
  1.3948 +  // clear out any environment variables which may have been set 
  1.3949 +  // during the relaunch process now that we know we won't be relaunching.
  1.3950 +  SaveToEnv("XRE_PROFILE_PATH=");
  1.3951 +  SaveToEnv("XRE_PROFILE_LOCAL_PATH=");
  1.3952 +  SaveToEnv("XRE_PROFILE_NAME=");
  1.3953 +  SaveToEnv("XRE_START_OFFLINE=");
  1.3954 +  SaveToEnv("NO_EM_RESTART=");
  1.3955 +  SaveToEnv("XUL_APP_FILE=");
  1.3956 +  SaveToEnv("XRE_BINARY_PATH=");
  1.3957 +
  1.3958 +  if (!mShuttingDown) {
  1.3959 +    rv = appStartup->CreateHiddenWindow();
  1.3960 +    NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  1.3961 +
  1.3962 +#if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK)
  1.3963 +    nsGTKToolkit* toolkit = nsGTKToolkit::GetToolkit();
  1.3964 +    if (toolkit && !mDesktopStartupID.IsEmpty()) {
  1.3965 +      toolkit->SetDesktopStartupID(mDesktopStartupID);
  1.3966 +    }
  1.3967 +    // Clear the environment variable so it won't be inherited by
  1.3968 +    // child processes and confuse things.
  1.3969 +    g_unsetenv ("DESKTOP_STARTUP_ID");
  1.3970 +#endif
  1.3971 +
  1.3972 +#ifdef XP_MACOSX
  1.3973 +    // Set up ability to respond to system (Apple) events. This must be
  1.3974 +    // done before setting up the command line service.
  1.3975 +    SetupMacApplicationDelegate();
  1.3976 +
  1.3977 +    // we re-initialize the command-line service and do appleevents munging
  1.3978 +    // after we are sure that we're not restarting
  1.3979 +    cmdLine = do_CreateInstance("@mozilla.org/toolkit/command-line;1");
  1.3980 +    NS_ENSURE_TRUE(cmdLine, NS_ERROR_FAILURE);
  1.3981 +
  1.3982 +    CommandLineServiceMac::SetupMacCommandLine(gArgc, gArgv, false);
  1.3983 +
  1.3984 +    rv = cmdLine->Init(gArgc, gArgv,
  1.3985 +                        workingDir, nsICommandLine::STATE_INITIAL_LAUNCH);
  1.3986 +    NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  1.3987 +#endif
  1.3988 +
  1.3989 +    nsCOMPtr<nsIObserverService> obsService =
  1.3990 +      mozilla::services::GetObserverService();
  1.3991 +    if (obsService)
  1.3992 +      obsService->NotifyObservers(nullptr, "final-ui-startup", nullptr);
  1.3993 +
  1.3994 +    (void)appStartup->DoneStartingUp();
  1.3995 +    appStartup->GetShuttingDown(&mShuttingDown);
  1.3996 +  }
  1.3997 +
  1.3998 +  if (!mShuttingDown) {
  1.3999 +    rv = cmdLine->Run();
  1.4000 +    NS_ENSURE_SUCCESS_LOG(rv, NS_ERROR_FAILURE);
  1.4001 +
  1.4002 +    appStartup->GetShuttingDown(&mShuttingDown);
  1.4003 +  }
  1.4004 +
  1.4005 +  if (!mShuttingDown) {
  1.4006 +#ifdef MOZ_ENABLE_XREMOTE
  1.4007 +    // if we have X remote support, start listening for requests on the
  1.4008 +    // proxy window.
  1.4009 +    if (!mDisableRemote)
  1.4010 +      mRemoteService = do_GetService("@mozilla.org/toolkit/remote-service;1");
  1.4011 +    if (mRemoteService)
  1.4012 +      mRemoteService->Startup(mAppData->name, mProfileName.get());
  1.4013 +#endif /* MOZ_ENABLE_XREMOTE */
  1.4014 +
  1.4015 +    mNativeApp->Enable();
  1.4016 +  }
  1.4017 +
  1.4018 +#ifdef MOZ_INSTRUMENT_EVENT_LOOP
  1.4019 +  if (PR_GetEnv("MOZ_INSTRUMENT_EVENT_LOOP") || profiler_is_active()) {
  1.4020 +    bool logToConsole = !!PR_GetEnv("MOZ_INSTRUMENT_EVENT_LOOP");
  1.4021 +    mozilla::InitEventTracing(logToConsole);
  1.4022 +  }
  1.4023 +#endif /* MOZ_INSTRUMENT_EVENT_LOOP */
  1.4024 +
  1.4025 +  {
  1.4026 +    rv = appStartup->Run();
  1.4027 +    if (NS_FAILED(rv)) {
  1.4028 +      NS_ERROR("failed to run appstartup");
  1.4029 +      gLogConsoleErrors = true;
  1.4030 +    }
  1.4031 +  }
  1.4032 +
  1.4033 +  return rv;
  1.4034 +}
  1.4035 +
  1.4036 +/*
  1.4037 + * XRE_main - A class based main entry point used by most platforms.
  1.4038 + */
  1.4039 +int
  1.4040 +XREMain::XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
  1.4041 +{
  1.4042 +  char aLocal;
  1.4043 +  GeckoProfilerInitRAII profilerGuard(&aLocal);
  1.4044 +  PROFILER_LABEL("Startup", "XRE_Main");
  1.4045 +
  1.4046 +  mozilla::IOInterposerInit ioInterposerGuard;
  1.4047 +
  1.4048 +  nsresult rv = NS_OK;
  1.4049 +
  1.4050 +  gArgc = argc;
  1.4051 +  gArgv = argv;
  1.4052 +
  1.4053 +  NS_ENSURE_TRUE(aAppData, 2);
  1.4054 +
  1.4055 +  mAppData = new ScopedAppData(aAppData);
  1.4056 +  if (!mAppData)
  1.4057 +    return 1;
  1.4058 +  // used throughout this file
  1.4059 +  gAppData = mAppData;
  1.4060 +
  1.4061 +  ScopedLogging log;
  1.4062 +
  1.4063 +#if defined(MOZ_WIDGET_GTK)
  1.4064 +#if defined(MOZ_MEMORY) || defined(__FreeBSD__) || defined(__NetBSD__)
  1.4065 +  // Disable the slice allocator, since jemalloc already uses similar layout
  1.4066 +  // algorithms, and using a sub-allocator tends to increase fragmentation.
  1.4067 +  // This must be done before g_thread_init() is called.
  1.4068 +  g_slice_set_config(G_SLICE_CONFIG_ALWAYS_MALLOC, 1);
  1.4069 +#endif
  1.4070 +  g_thread_init(nullptr);
  1.4071 +#endif
  1.4072 +
  1.4073 +  // init
  1.4074 +  bool exit = false;
  1.4075 +  int result = XRE_mainInit(&exit);
  1.4076 +  if (result != 0 || exit)
  1.4077 +    return result;
  1.4078 +
  1.4079 +  // startup
  1.4080 +  result = XRE_mainStartup(&exit);
  1.4081 +  if (result != 0 || exit)
  1.4082 +    return result;
  1.4083 +
  1.4084 +  bool appInitiatedRestart = false;
  1.4085 +
  1.4086 +  // Start the real application
  1.4087 +  mScopedXPCom = new ScopedXPCOMStartup();
  1.4088 +  if (!mScopedXPCom)
  1.4089 +    return 1;
  1.4090 +
  1.4091 +  rv = mScopedXPCom->Initialize();
  1.4092 +  NS_ENSURE_SUCCESS(rv, 1);
  1.4093 +
  1.4094 +  // run!
  1.4095 +  rv = XRE_mainRun();
  1.4096 +
  1.4097 +#ifdef MOZ_INSTRUMENT_EVENT_LOOP
  1.4098 +  mozilla::ShutdownEventTracing();
  1.4099 +#endif
  1.4100 +
  1.4101 +  // Check for an application initiated restart.  This is one that
  1.4102 +  // corresponds to nsIAppStartup.quit(eRestart)
  1.4103 +  if (rv == NS_SUCCESS_RESTART_APP || rv == NS_SUCCESS_RESTART_METRO_APP) {
  1.4104 +    appInitiatedRestart = true;
  1.4105 +
  1.4106 +    // We have an application restart don't do any shutdown checks here
  1.4107 +    // In particular we don't want to poison IO for checking late-writes.
  1.4108 +    gShutdownChecks = SCM_NOTHING;
  1.4109 +  }
  1.4110 +
  1.4111 +  if (!mShuttingDown) {
  1.4112 +#ifdef MOZ_ENABLE_XREMOTE
  1.4113 +    // shut down the x remote proxy window
  1.4114 +    if (mRemoteService) {
  1.4115 +      mRemoteService->Shutdown();
  1.4116 +    }
  1.4117 +#endif /* MOZ_ENABLE_XREMOTE */
  1.4118 +  }
  1.4119 +
  1.4120 +  delete mScopedXPCom;
  1.4121 +  mScopedXPCom = nullptr;
  1.4122 +
  1.4123 +  // unlock the profile after ScopedXPCOMStartup object (xpcom) 
  1.4124 +  // has gone out of scope.  see bug #386739 for more details
  1.4125 +  mProfileLock->Unlock();
  1.4126 +  gProfileLock = nullptr;
  1.4127 +
  1.4128 +#if defined(MOZ_WIDGET_QT)
  1.4129 +  nsQAppInstance::Release();
  1.4130 +#endif
  1.4131 +
  1.4132 +  // Restart the app after XPCOM has been shut down cleanly. 
  1.4133 +  if (appInitiatedRestart) {
  1.4134 +    RestoreStateForAppInitiatedRestart();
  1.4135 +
  1.4136 +    // Ensure that these environment variables are set:
  1.4137 +    SaveFileToEnvIfUnset("XRE_PROFILE_PATH", mProfD);
  1.4138 +    SaveFileToEnvIfUnset("XRE_PROFILE_LOCAL_PATH", mProfLD);
  1.4139 +    SaveWordToEnvIfUnset("XRE_PROFILE_NAME", mProfileName);
  1.4140 +
  1.4141 +#ifdef MOZ_WIDGET_GTK
  1.4142 +    MOZ_gdk_display_close(mGdkDisplay);
  1.4143 +#endif
  1.4144 +
  1.4145 +#if defined(MOZ_METRO) && defined(XP_WIN)
  1.4146 +    if (rv == NS_SUCCESS_RESTART_METRO_APP) {
  1.4147 +      LaunchDefaultMetroBrowser();
  1.4148 +      rv = NS_OK;
  1.4149 +    } else
  1.4150 +#endif
  1.4151 +    {
  1.4152 +      rv = LaunchChild(mNativeApp, true);
  1.4153 +    }
  1.4154 +
  1.4155 +#ifdef MOZ_CRASHREPORTER
  1.4156 +    if (mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER)
  1.4157 +      CrashReporter::UnsetExceptionHandler();
  1.4158 +#endif
  1.4159 +    return rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ? 0 : 1;
  1.4160 +  }
  1.4161 +
  1.4162 +#ifdef MOZ_WIDGET_GTK
  1.4163 +  // gdk_display_close also calls gdk_display_manager_set_default_display
  1.4164 +  // appropriately when necessary.
  1.4165 +  MOZ_gdk_display_close(mGdkDisplay);
  1.4166 +#endif
  1.4167 +
  1.4168 +#ifdef MOZ_CRASHREPORTER
  1.4169 +  if (mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER)
  1.4170 +      CrashReporter::UnsetExceptionHandler();
  1.4171 +#endif
  1.4172 +
  1.4173 +  XRE_DeinitCommandLine();
  1.4174 +
  1.4175 +  return NS_FAILED(rv) ? 1 : 0;
  1.4176 +}
  1.4177 +
  1.4178 +#if defined(MOZ_METRO) && defined(XP_WIN)
  1.4179 +extern bool XRE_MetroCoreApplicationRun();
  1.4180 +static XREMain* xreMainPtr;
  1.4181 +
  1.4182 +// must be called by the thread we want as the main thread
  1.4183 +nsresult
  1.4184 +XRE_metroStartup(bool runXREMain)
  1.4185 +{
  1.4186 +  nsresult rv;
  1.4187 +
  1.4188 +  bool exit = false;
  1.4189 +  if (xreMainPtr->XRE_mainStartup(&exit) != 0 || exit)
  1.4190 +    return NS_ERROR_FAILURE;
  1.4191 +
  1.4192 +  // Start the real application
  1.4193 +  xreMainPtr->mScopedXPCom = new ScopedXPCOMStartup();
  1.4194 +  if (!xreMainPtr->mScopedXPCom)
  1.4195 +    return NS_ERROR_FAILURE;
  1.4196 +
  1.4197 +  rv = xreMainPtr->mScopedXPCom->Initialize();
  1.4198 +  NS_ENSURE_SUCCESS(rv, rv);
  1.4199 +
  1.4200 +  if (runXREMain) {
  1.4201 +    rv = xreMainPtr->XRE_mainRun();
  1.4202 +    NS_ENSURE_SUCCESS(rv, rv);
  1.4203 +  }
  1.4204 +  return NS_OK;
  1.4205 +}
  1.4206 +
  1.4207 +void
  1.4208 +XRE_metroShutdown()
  1.4209 +{
  1.4210 +  delete xreMainPtr->mScopedXPCom;
  1.4211 +  xreMainPtr->mScopedXPCom = nullptr;
  1.4212 +
  1.4213 +#ifdef MOZ_INSTRUMENT_EVENT_LOOP
  1.4214 +  mozilla::ShutdownEventTracing();
  1.4215 +#endif
  1.4216 +
  1.4217 +  // unlock the profile after ScopedXPCOMStartup object (xpcom) 
  1.4218 +  // has gone out of scope.  see bug #386739 for more details
  1.4219 +  xreMainPtr->mProfileLock->Unlock();
  1.4220 +  gProfileLock = nullptr;
  1.4221 +
  1.4222 +#ifdef MOZ_CRASHREPORTER
  1.4223 +  if (xreMainPtr->mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER)
  1.4224 +      CrashReporter::UnsetExceptionHandler();
  1.4225 +#endif
  1.4226 +
  1.4227 +  XRE_DeinitCommandLine();
  1.4228 +}
  1.4229 +
  1.4230 +class WinRTInitWrapper
  1.4231 +{
  1.4232 +public:
  1.4233 +  WinRTInitWrapper() {
  1.4234 +    mResult = ::RoInitialize(RO_INIT_MULTITHREADED);
  1.4235 +  }
  1.4236 +  ~WinRTInitWrapper() {
  1.4237 +    if (SUCCEEDED(mResult)) {
  1.4238 +      ::RoUninitialize();
  1.4239 +    }
  1.4240 +  }
  1.4241 +  HRESULT mResult;
  1.4242 +};
  1.4243 +
  1.4244 +int
  1.4245 +XRE_mainMetro(int argc, char* argv[], const nsXREAppData* aAppData)
  1.4246 +{
  1.4247 +  char aLocal;
  1.4248 +  GeckoProfilerInitRAII profilerGuard(&aLocal);
  1.4249 +  PROFILER_LABEL("Startup", "XRE_Main");
  1.4250 +
  1.4251 +  mozilla::IOInterposerInit ioInterposerGuard;
  1.4252 +
  1.4253 +  nsresult rv = NS_OK;
  1.4254 +
  1.4255 +  xreMainPtr = new XREMain();
  1.4256 +  if (!xreMainPtr) {
  1.4257 +    return 1;
  1.4258 +  }
  1.4259 +
  1.4260 +  // Inits Winrt and COM underneath it.
  1.4261 +  WinRTInitWrapper wrap;
  1.4262 +
  1.4263 +  gArgc = argc;
  1.4264 +  gArgv = argv;
  1.4265 +
  1.4266 +  NS_ENSURE_TRUE(aAppData, 2);
  1.4267 +
  1.4268 +  xreMainPtr->mAppData = new ScopedAppData(aAppData);
  1.4269 +  if (!xreMainPtr->mAppData)
  1.4270 +    return 1;
  1.4271 +  // used throughout this file
  1.4272 +  gAppData = xreMainPtr->mAppData;
  1.4273 +
  1.4274 +  ScopedLogging log;
  1.4275 +
  1.4276 +  // init
  1.4277 +  bool exit = false;
  1.4278 +  if (xreMainPtr->XRE_mainInit(&exit) != 0 || exit)
  1.4279 +    return 1;
  1.4280 +
  1.4281 +  // Located in widget, will call back into XRE_metroStartup and
  1.4282 +  // XRE_metroShutdown above.
  1.4283 +  if (!XRE_MetroCoreApplicationRun()) {
  1.4284 +    return 1;
  1.4285 +  }
  1.4286 +
  1.4287 +  // XRE_metroShutdown should have already been called on the worker
  1.4288 +  // thread that called XRE_metroStartup.
  1.4289 +  NS_ASSERTION(!xreMainPtr->mScopedXPCom,
  1.4290 +               "XPCOM Shutdown hasn't occured, and we are exiting.");
  1.4291 +  return 0;
  1.4292 +}
  1.4293 +
  1.4294 +void SetWindowsEnvironment(WindowsEnvironmentType aEnvID);
  1.4295 +#endif // MOZ_METRO || !defined(XP_WIN)
  1.4296 +
  1.4297 +void
  1.4298 +XRE_StopLateWriteChecks(void) {
  1.4299 +  mozilla::StopLateWriteChecks();
  1.4300 +}
  1.4301 +
  1.4302 +int
  1.4303 +XRE_main(int argc, char* argv[], const nsXREAppData* aAppData, uint32_t aFlags)
  1.4304 +{
  1.4305 +#if !defined(MOZ_METRO) || !defined(XP_WIN)
  1.4306 +  XREMain main;
  1.4307 +  int result = main.XRE_main(argc, argv, aAppData);
  1.4308 +  mozilla::RecordShutdownEndTimeStamp();
  1.4309 +  return result;
  1.4310 +#else
  1.4311 +  if (aFlags == XRE_MAIN_FLAG_USE_METRO) {
  1.4312 +    SetWindowsEnvironment(WindowsEnvironmentType_Metro);
  1.4313 +  }
  1.4314 +
  1.4315 +  // Desktop
  1.4316 +  if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop) {
  1.4317 +    XREMain main;
  1.4318 +    int result = main.XRE_main(argc, argv, aAppData);
  1.4319 +    mozilla::RecordShutdownEndTimeStamp();
  1.4320 +    return result;
  1.4321 +  }
  1.4322 +
  1.4323 +  // Metro
  1.4324 +  NS_ASSERTION(XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Metro,
  1.4325 +               "Unknown Windows environment");
  1.4326 +
  1.4327 +  SetLastWinRunType(AHE_IMMERSIVE);
  1.4328 +
  1.4329 +  int result = XRE_mainMetro(argc, argv, aAppData);
  1.4330 +  mozilla::RecordShutdownEndTimeStamp();
  1.4331 +  return result;
  1.4332 +#endif // MOZ_METRO || !defined(XP_WIN)
  1.4333 +}
  1.4334 +
  1.4335 +nsresult
  1.4336 +XRE_InitCommandLine(int aArgc, char* aArgv[])
  1.4337 +{
  1.4338 +  nsresult rv = NS_OK;
  1.4339 +
  1.4340 +#if defined(OS_WIN)
  1.4341 +  CommandLine::Init(aArgc, aArgv);
  1.4342 +#else
  1.4343 +
  1.4344 +  // these leak on error, but that's OK: we'll just exit()
  1.4345 +  char** canonArgs = new char*[aArgc];
  1.4346 +
  1.4347 +  // get the canonical version of the binary's path
  1.4348 +  nsCOMPtr<nsIFile> binFile;
  1.4349 +  rv = XRE_GetBinaryPath(aArgv[0], getter_AddRefs(binFile));
  1.4350 +  if (NS_FAILED(rv))
  1.4351 +    return NS_ERROR_FAILURE;
  1.4352 +
  1.4353 +  nsAutoCString canonBinPath;
  1.4354 +  rv = binFile->GetNativePath(canonBinPath);
  1.4355 +  if (NS_FAILED(rv))
  1.4356 +    return NS_ERROR_FAILURE;
  1.4357 +
  1.4358 +  canonArgs[0] = strdup(canonBinPath.get());
  1.4359 +
  1.4360 +  for (int i = 1; i < aArgc; ++i) {
  1.4361 +    if (aArgv[i]) {
  1.4362 +      canonArgs[i] = strdup(aArgv[i]);
  1.4363 +    }
  1.4364 +  }
  1.4365 + 
  1.4366 +  NS_ASSERTION(!CommandLine::IsInitialized(), "Bad news!");
  1.4367 +  CommandLine::Init(aArgc, canonArgs);
  1.4368 +
  1.4369 +  for (int i = 0; i < aArgc; ++i)
  1.4370 +      free(canonArgs[i]);
  1.4371 +  delete[] canonArgs;
  1.4372 +#endif
  1.4373 +
  1.4374 +  const char *path = nullptr;
  1.4375 +  ArgResult ar = CheckArg("greomni", false, &path);
  1.4376 +  if (ar == ARG_BAD) {
  1.4377 +    PR_fprintf(PR_STDERR, "Error: argument -greomni requires a path argument\n");
  1.4378 +    return NS_ERROR_FAILURE;
  1.4379 +  }
  1.4380 +
  1.4381 +  if (!path)
  1.4382 +    return rv;
  1.4383 +
  1.4384 +  nsCOMPtr<nsIFile> greOmni;
  1.4385 +  rv = XRE_GetFileFromPath(path, getter_AddRefs(greOmni));
  1.4386 +  if (NS_FAILED(rv)) {
  1.4387 +    PR_fprintf(PR_STDERR, "Error: argument -greomni requires a valid path\n");
  1.4388 +    return rv;
  1.4389 +  }
  1.4390 +
  1.4391 +  ar = CheckArg("appomni", false, &path);
  1.4392 +  if (ar == ARG_BAD) {
  1.4393 +    PR_fprintf(PR_STDERR, "Error: argument -appomni requires a path argument\n");
  1.4394 +    return NS_ERROR_FAILURE;
  1.4395 +  }
  1.4396 +
  1.4397 +  nsCOMPtr<nsIFile> appOmni;
  1.4398 +  if (path) {
  1.4399 +      rv = XRE_GetFileFromPath(path, getter_AddRefs(appOmni));
  1.4400 +      if (NS_FAILED(rv)) {
  1.4401 +        PR_fprintf(PR_STDERR, "Error: argument -appomni requires a valid path\n");
  1.4402 +        return rv;
  1.4403 +      }
  1.4404 +  }
  1.4405 +
  1.4406 +  mozilla::Omnijar::Init(greOmni, appOmni);
  1.4407 +  return rv;
  1.4408 +}
  1.4409 +
  1.4410 +nsresult
  1.4411 +XRE_DeinitCommandLine()
  1.4412 +{
  1.4413 +  nsresult rv = NS_OK;
  1.4414 +
  1.4415 +  CommandLine::Terminate();
  1.4416 +
  1.4417 +  return rv;
  1.4418 +}
  1.4419 +
  1.4420 +GeckoProcessType
  1.4421 +XRE_GetProcessType()
  1.4422 +{
  1.4423 +  return mozilla::startup::sChildProcessType;
  1.4424 +}
  1.4425 +
  1.4426 +bool
  1.4427 +mozilla::BrowserTabsRemote()
  1.4428 +{
  1.4429 +  if (!gBrowserTabsRemoteInitialized) {
  1.4430 +    gBrowserTabsRemote = Preferences::GetBool("browser.tabs.remote", false);
  1.4431 +    gBrowserTabsRemoteInitialized = true;
  1.4432 +  }
  1.4433 +
  1.4434 +  return gBrowserTabsRemote;
  1.4435 +}
  1.4436 +
  1.4437 +void
  1.4438 +SetupErrorHandling(const char* progname)
  1.4439 +{
  1.4440 +#ifdef XP_WIN
  1.4441 +  /* On Windows XPSP3 and Windows Vista if DEP is configured off-by-default
  1.4442 +     we still want DEP protection: enable it explicitly and programmatically.
  1.4443 +     
  1.4444 +     This function is not available on WinXPSP2 so we dynamically load it.
  1.4445 +  */
  1.4446 +
  1.4447 +  HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll");
  1.4448 +  SetProcessDEPPolicyFunc _SetProcessDEPPolicy =
  1.4449 +    (SetProcessDEPPolicyFunc) GetProcAddress(kernel32, "SetProcessDEPPolicy");
  1.4450 +  if (_SetProcessDEPPolicy)
  1.4451 +    _SetProcessDEPPolicy(PROCESS_DEP_ENABLE);
  1.4452 +#endif
  1.4453 +
  1.4454 +#ifdef XP_WIN32
  1.4455 +  // Suppress the "DLL Foo could not be found" dialog, such that if dependent
  1.4456 +  // libraries (such as GDI+) are not preset, we gracefully fail to load those
  1.4457 +  // XPCOM components, instead of being ungraceful.
  1.4458 +  UINT realMode = SetErrorMode(0);
  1.4459 +  realMode |= SEM_FAILCRITICALERRORS;
  1.4460 +  // If XRE_NO_WINDOWS_CRASH_DIALOG is set, suppress displaying the "This
  1.4461 +  // application has crashed" dialog box.  This is mainly useful for
  1.4462 +  // automated testing environments, e.g. tinderbox, where there's no need
  1.4463 +  // for a dozen of the dialog boxes to litter the console
  1.4464 +  if (getenv("XRE_NO_WINDOWS_CRASH_DIALOG"))
  1.4465 +    realMode |= SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX;
  1.4466 +
  1.4467 +  SetErrorMode(realMode);
  1.4468 +
  1.4469 +#endif
  1.4470 +
  1.4471 +#if defined (DEBUG) && defined(XP_WIN)
  1.4472 +  // Send MSCRT Warnings, Errors and Assertions to stderr.
  1.4473 +  // See http://msdn.microsoft.com/en-us/library/1y71x448(v=VS.80).aspx
  1.4474 +  // and http://msdn.microsoft.com/en-us/library/a68f826y(v=VS.80).aspx.
  1.4475 +
  1.4476 +  _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
  1.4477 +  _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
  1.4478 +  _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
  1.4479 +  _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
  1.4480 +  _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
  1.4481 +  _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
  1.4482 +
  1.4483 +  _CrtSetReportHook(MSCRTReportHook);
  1.4484 +#endif
  1.4485 +
  1.4486 +  InstallSignalHandlers(progname);
  1.4487 +
  1.4488 +  // Unbuffer stdout, needed for tinderbox tests.
  1.4489 +  setbuf(stdout, 0);
  1.4490 +}
  1.4491 +

mercurial