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, ¤tIsSelected); 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, ¤tIsSelected); 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 +