1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #if defined(XP_OS2) && defined(MOZ_OS2_HIGH_MEMORY)
7 // os2safe.h has to be included before os2.h, needed for high mem
11 #if defined(MOZ_WIDGET_QT)
12 #include <QApplication>
13 #include <QStringList>
14 #include "nsQAppInstance.h"
15 #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
16 #include <QInputContextFactory>
17 #include <QInputContext>
19 #endif // MOZ_WIDGET_QT
21 #include "mozilla/dom/ContentParent.h"
22 #include "mozilla/dom/ContentChild.h"
24 #include "mozilla/Attributes.h"
25 #include "mozilla/Likely.h"
26 #include "mozilla/Poison.h"
27 #include "mozilla/Telemetry.h"
28 #include "mozilla/Util.h"
30 #include "nsAppRunner.h"
31 #include "mozilla/AppData.h"
32 #include "nsUpdateDriver.h"
33 #include "ProfileReset.h"
35 #ifdef MOZ_INSTRUMENT_EVENT_LOOP
36 #include "EventTracer.h"
40 #include "nsVersionComparator.h"
41 #include "MacLaunchHelper.h"
42 #include "MacApplicationDelegate.h"
43 #include "MacAutoreleasePool.h"
44 // these are needed for sysctl
45 #include <sys/types.h>
46 #include <sys/sysctl.h>
50 #include "private/pprthred.h"
58 #include "nsIAppShellService.h"
59 #include "nsIAppStartup.h"
60 #include "nsIAppStartupNotifier.h"
61 #include "nsIMutableArray.h"
62 #include "nsICategoryManager.h"
63 #include "nsIChromeRegistry.h"
64 #include "nsICommandLineRunner.h"
65 #include "nsIComponentManager.h"
66 #include "nsIComponentRegistrar.h"
67 #include "nsIContentHandler.h"
68 #include "nsIDialogParamBlock.h"
69 #include "nsIDOMWindow.h"
70 #include "mozilla/ModuleUtils.h"
71 #include "nsIIOService2.h"
72 #include "nsIObserverService.h"
73 #include "nsINativeAppSupport.h"
74 #include "nsIProcess.h"
75 #include "nsIProfileUnlocker.h"
76 #include "nsIPromptService.h"
77 #include "nsIServiceManager.h"
78 #include "nsIStringBundle.h"
79 #include "nsISupportsPrimitives.h"
80 #include "nsIToolkitChromeRegistry.h"
81 #include "nsIToolkitProfile.h"
82 #include "nsIToolkitProfileService.h"
84 #include "nsIWindowCreator.h"
85 #include "nsIWindowMediator.h"
86 #include "nsIWindowWatcher.h"
87 #include "nsIXULAppInfo.h"
88 #include "nsIXULRuntime.h"
89 #include "nsPIDOMWindow.h"
90 #include "nsIBaseWindow.h"
91 #include "nsIWidget.h"
92 #include "nsIDocShell.h"
93 #include "nsAppShellCID.h"
94 #include "mozilla/scache/StartupCache.h"
96 #include "mozilla/unused.h"
99 #include "nsIWinAppHelper.h"
101 #include "cairo/cairo-features.h"
102 #include "mozilla/WindowsVersion.h"
107 #ifndef PROCESS_DEP_ENABLE
108 #define PROCESS_DEP_ENABLE 0x1
113 #include "nsCOMPtr.h"
114 #include "nsDirectoryServiceDefs.h"
115 #include "nsDirectoryServiceUtils.h"
116 #include "nsEmbedCID.h"
117 #include "nsNetUtil.h"
118 #include "nsReadableUtils.h"
120 #include "nsXPCOMCIDInternal.h"
121 #include "nsXPIDLString.h"
122 #include "nsPrintfCString.h"
123 #include "nsVersionComparator.h"
125 #include "nsAppDirectoryServiceDefs.h"
126 #include "nsXULAppAPI.h"
127 #include "nsXREDirProvider.h"
128 #include "nsToolkitCompsCID.h"
130 #include "nsINIParser.h"
131 #include "mozilla/Omnijar.h"
132 #include "mozilla/StartupTimeline.h"
133 #include "mozilla/LateWriteChecks.h"
137 // for old system jemalloc version check
138 #if !defined(MOZ_MEMORY) && defined(__NetBSD__)
139 #include <sys/param.h>
143 #include <sys/stat.h>
151 #include "nsThreadUtils.h"
157 #include "nsILocalFileMac.h"
158 #include "nsCommandLineServiceMac.h"
161 // for X remote support
162 #ifdef MOZ_ENABLE_XREMOTE
163 #include "XRemoteClient.h"
164 #include "nsIRemoteService.h"
167 #ifdef NS_TRACE_MALLOC
168 #include "nsTraceMalloc.h"
171 #if defined(DEBUG) && defined(XP_WIN32)
175 #if defined (XP_MACOSX)
176 #include <Carbon/Carbon.h>
187 #ifdef MOZ_CRASHREPORTER
188 #include "nsExceptionHandler.h"
189 #include "nsICrashReporter.h"
190 #define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1"
191 #include "nsIPrefService.h"
192 #include "mozilla/Preferences.h"
195 #include "base/command_line.h"
196 #ifdef MOZ_ENABLE_TESTS
197 #include "GTestRunner.h"
200 #ifdef MOZ_WIDGET_ANDROID
201 #include "AndroidBridge.h"
204 extern uint32_t gRestartMode
;
205 extern void InstallSignalHandlers(const char *ProgramName
);
206 #include "nsX11ErrorHandler.h"
208 #define FILE_COMPATIBILITY_INFO NS_LITERAL_CSTRING("compatibility.ini")
209 #define FILE_INVALIDATE_CACHES NS_LITERAL_CSTRING(".purgecaches")
214 static const char gToolkitVersion
[] = NS_STRINGIFY(GRE_MILESTONE
);
215 static const char gToolkitBuildID
[] = NS_STRINGIFY(GRE_BUILDID
);
217 static nsIProfileLock
* gProfileLock
;
223 static int gQtOnlyArgc
;
224 static char **gQtOnlyArgv
;
227 #if defined(MOZ_WIDGET_GTK)
228 #if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING) \
229 || defined(NS_TRACE_MALLOC)
230 #define CLEANUP_MEMORY 1
231 #define PANGO_ENABLE_BACKEND
232 #include <pango/pangofc-fontmap.h>
236 #include <gdk/gdkx.h>
238 #include "nsGTKToolkit.h"
240 #include "BinaryPath.h"
243 extern "C" MFBT_API
bool IsSignalHandlingBroken();
247 int (*RunGTest
)() = 0;
250 using namespace mozilla
;
251 using mozilla::unused
;
252 using mozilla::scache::StartupCache
;
253 using mozilla::dom::ContentParent
;
254 using mozilla::dom::ContentChild
;
256 // Save literal putenv string to environment variable.
258 SaveToEnv(const char *putenv
)
260 char *expr
= strdup(putenv
);
263 // We intentionally leak |expr| here since it is required by PR_SetEnv.
266 // Tests that an environment variable exists and has a value
268 EnvHasValue(const char *name
)
270 const char *val
= PR_GetEnv(name
);
271 return (val
&& *val
);
274 // Save the given word to the specified environment variable.
276 SaveWordToEnv(const char *name
, const nsACString
& word
)
278 char *expr
= PR_smprintf("%s=%s", name
, PromiseFlatCString(word
).get());
281 // We intentionally leak |expr| here since it is required by PR_SetEnv.
284 // Save the path of the given file to the specified environment variable.
286 SaveFileToEnv(const char *name
, nsIFile
*file
)
291 SetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name
).get(), path
.get());
294 file
->GetNativePath(path
);
295 SaveWordToEnv(name
, path
);
299 // Load the path of a file saved with SaveFileToEnv
300 static already_AddRefed
<nsIFile
>
301 GetFileFromEnv(const char *name
)
304 nsCOMPtr
<nsIFile
> file
;
307 WCHAR path
[_MAX_PATH
];
308 if (!GetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name
).get(),
312 rv
= NS_NewLocalFile(nsDependentString(path
), true, getter_AddRefs(file
));
316 return file
.forget();
318 const char *arg
= PR_GetEnv(name
);
322 rv
= NS_NewNativeLocalFile(nsDependentCString(arg
), true,
323 getter_AddRefs(file
));
327 return file
.forget();
331 // Save the path of the given word to the specified environment variable
332 // provided the environment variable does not have a value.
334 SaveWordToEnvIfUnset(const char *name
, const nsACString
& word
)
336 if (!EnvHasValue(name
))
337 SaveWordToEnv(name
, word
);
340 // Save the path of the given file to the specified environment variable
341 // provided the environment variable does not have a value.
343 SaveFileToEnvIfUnset(const char *name
, nsIFile
*file
)
345 if (!EnvHasValue(name
))
346 SaveFileToEnv(name
, file
);
350 strimatch(const char* lowerstr
, const char* mixedstr
)
353 if (!*mixedstr
) return false; // mixedstr is shorter
354 if (tolower(*mixedstr
) != *lowerstr
) return false; // no match
360 if (*mixedstr
) return false; // lowerstr is shorter
366 * Output a string to the user. This method is really only meant to be used to
367 * output last-ditch error messages designed for developers NOT END USERS.
370 * Pass true to indicate severe errors.
372 * printf-style format string followed by arguments.
374 static void Output(bool isError
, const char *fmt
, ... )
379 #if defined(XP_WIN) && !MOZ_WINCONSOLE
380 char *msg
= PR_vsmprintf(fmt
, ap
);
385 flags
|= MB_ICONERROR
;
387 flags
|= MB_ICONINFORMATION
;
389 wchar_t wide_msg
[1024];
390 MultiByteToWideChar(CP_ACP
,
395 sizeof(wide_msg
) / sizeof(wchar_t));
397 MessageBoxW(nullptr, wide_msg
, L
"XULRunner", flags
);
398 PR_smprintf_free(msg
);
401 vfprintf(stderr
, fmt
, ap
);
408 REMOTE_NOT_FOUND
= 0,
416 ARG_BAD
= 2 // you wanted a param, but there isn't one
419 static void RemoveArg(char **argv
)
430 * Check for a commandline flag. If the flag takes a parameter, the
431 * parameter is returned in aParam. Flags may be in the form -arg or
432 * --arg (or /arg on win32/OS2).
434 * @param aArg the parameter to check. Must be lowercase.
435 * @param aCheckOSInt if true returns ARG_BAD if the osint argument is present
436 * when aArg is also present.
437 * @param aParam if non-null, the -arg <data> will be stored in this pointer.
438 * This is *not* allocated, but rather a pointer to the argv data.
439 * @param aRemArg if true, the argument is removed from the gArgv array.
442 CheckArg(const char* aArg
, bool aCheckOSInt
= false, const char **aParam
= nullptr, bool aRemArg
= true)
444 NS_ABORT_IF_FALSE(gArgv
, "gArgv must be initialized before CheckArg()");
446 char **curarg
= gArgv
+ 1; // skip argv[0]
447 ArgResult ar
= ARG_NONE
;
450 char *arg
= curarg
[0];
453 #if defined(XP_WIN) || defined(XP_OS2)
461 if (strimatch(aArg
, arg
)) {
471 #if defined(XP_WIN) || defined(XP_OS2)
490 if (aCheckOSInt
&& ar
== ARG_FOUND
) {
491 ArgResult arOSInt
= CheckArg("osint");
492 if (arOSInt
== ARG_FOUND
) {
494 PR_fprintf(PR_STDERR
, "Error: argument -osint is invalid\n");
503 * Check for a commandline flag from the windows shell and remove it from the
504 * argv used when restarting. Flags MUST be in the form -arg.
506 * @param aArg the parameter to check. Must be lowercase.
509 CheckArgShell(const char* aArg
)
511 char **curarg
= gRestartArgv
+ 1; // skip argv[0]
514 char *arg
= curarg
[0];
519 if (strimatch(aArg
, arg
)) {
521 *curarg
= *(curarg
+ 1);
538 * Enabled Native App Support to process DDE messages when the app needs to
539 * restart and the app has been launched by the Windows shell to open an url.
540 * When aWait is false this will process the DDE events manually. This prevents
541 * Windows from displaying an error message due to the DDE message not being
545 ProcessDDE(nsINativeAppSupport
* aNative
, bool aWait
)
547 // When the app is launched by the windows shell the windows shell
548 // expects the app to be available for DDE messages and if it isn't
549 // windows displays an error dialog. To prevent the error the DDE server
550 // is enabled and pending events are processed when the app needs to
551 // restart after it was launched by the shell with the requestpending
552 // argument. The requestpending pending argument is removed to
553 // differentiate it from being launched when an app restart is not
556 ar
= CheckArgShell("requestpending");
557 if (ar
== ARG_FOUND
) {
558 aNative
->Enable(); // enable win32 DDE responses
560 nsIThread
*thread
= NS_GetCurrentThread();
561 // This is just a guesstimate based on testing different values.
562 // If count is 8 or less windows will display an error dialog.
564 while(--count
>= 0) {
565 NS_ProcessNextEvent(thread
);
566 PR_Sleep(PR_MillisecondsToInterval(1));
573 bool gSafeMode
= false;
576 * The nsXULAppInfo object implements nsIFactory so that it can be its own
579 class nsXULAppInfo
: public nsIXULAppInfo
,
581 public nsIWinAppHelper
,
583 #ifdef MOZ_CRASHREPORTER
584 public nsICrashReporter
,
591 NS_DECL_ISUPPORTS_INHERITED
592 NS_DECL_NSIXULAPPINFO
593 NS_DECL_NSIXULRUNTIME
594 #ifdef MOZ_CRASHREPORTER
595 NS_DECL_NSICRASHREPORTER
598 NS_DECL_NSIWINAPPHELPER
602 NS_INTERFACE_MAP_BEGIN(nsXULAppInfo
)
603 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIXULRuntime
)
604 NS_INTERFACE_MAP_ENTRY(nsIXULRuntime
)
606 NS_INTERFACE_MAP_ENTRY(nsIWinAppHelper
)
608 #ifdef MOZ_CRASHREPORTER
609 NS_INTERFACE_MAP_ENTRY(nsICrashReporter
)
611 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIXULAppInfo
, gAppData
||
612 XRE_GetProcessType() == GeckoProcessType_Content
)
615 NS_IMETHODIMP_(nsrefcnt
)
616 nsXULAppInfo::AddRef()
621 NS_IMETHODIMP_(nsrefcnt
)
622 nsXULAppInfo::Release()
628 nsXULAppInfo::GetVendor(nsACString
& aResult
)
630 if (XRE_GetProcessType() == GeckoProcessType_Content
) {
631 return NS_ERROR_NOT_AVAILABLE
;
633 aResult
.Assign(gAppData
->vendor
);
639 nsXULAppInfo::GetName(nsACString
& aResult
)
641 if (XRE_GetProcessType() == GeckoProcessType_Content
) {
642 ContentChild
* cc
= ContentChild::GetSingleton();
643 aResult
= cc
->GetAppInfo().name
;
646 aResult
.Assign(gAppData
->name
);
652 nsXULAppInfo::GetID(nsACString
& aResult
)
654 if (XRE_GetProcessType() == GeckoProcessType_Content
) {
655 return NS_ERROR_NOT_AVAILABLE
;
657 aResult
.Assign(gAppData
->ID
);
663 nsXULAppInfo::GetVersion(nsACString
& aResult
)
665 if (XRE_GetProcessType() == GeckoProcessType_Content
) {
666 ContentChild
* cc
= ContentChild::GetSingleton();
667 aResult
= cc
->GetAppInfo().version
;
670 aResult
.Assign(gAppData
->version
);
676 nsXULAppInfo::GetPlatformVersion(nsACString
& aResult
)
678 aResult
.Assign(gToolkitVersion
);
684 nsXULAppInfo::GetAppBuildID(nsACString
& aResult
)
686 if (XRE_GetProcessType() == GeckoProcessType_Content
) {
687 ContentChild
* cc
= ContentChild::GetSingleton();
688 aResult
= cc
->GetAppInfo().buildID
;
691 aResult
.Assign(gAppData
->buildID
);
697 nsXULAppInfo::GetPlatformBuildID(nsACString
& aResult
)
699 aResult
.Assign(gToolkitBuildID
);
705 nsXULAppInfo::GetUAName(nsACString
& aResult
)
707 if (XRE_GetProcessType() == GeckoProcessType_Content
) {
708 ContentChild
* cc
= ContentChild::GetSingleton();
709 aResult
= cc
->GetAppInfo().UAName
;
712 aResult
.Assign(gAppData
->UAName
);
718 nsXULAppInfo::GetLogConsoleErrors(bool *aResult
)
720 *aResult
= gLogConsoleErrors
;
725 nsXULAppInfo::SetLogConsoleErrors(bool aValue
)
727 gLogConsoleErrors
= aValue
;
732 nsXULAppInfo::GetInSafeMode(bool *aResult
)
734 *aResult
= gSafeMode
;
739 nsXULAppInfo::GetOS(nsACString
& aResult
)
741 aResult
.AssignLiteral(OS_TARGET
);
746 nsXULAppInfo::GetXPCOMABI(nsACString
& aResult
)
748 #ifdef TARGET_XPCOM_ABI
749 aResult
.AssignLiteral(TARGET_XPCOM_ABI
);
752 return NS_ERROR_NOT_AVAILABLE
;
757 nsXULAppInfo::GetWidgetToolkit(nsACString
& aResult
)
759 aResult
.AssignLiteral(MOZ_WIDGET_TOOLKIT
);
763 // Ensure that the GeckoProcessType enum, defined in xpcom/build/nsXULAppAPI.h,
764 // is synchronized with the const unsigned longs defined in
765 // xpcom/system/nsIXULRuntime.idl.
766 #define SYNC_ENUMS(a,b) \
767 static_assert(nsIXULRuntime::PROCESS_TYPE_ ## a == \
768 static_cast<int>(GeckoProcessType_ ## b), \
769 "GeckoProcessType in nsXULAppAPI.h not synchronized with nsIXULRuntime.idl");
771 SYNC_ENUMS(DEFAULT
, Default
)
772 SYNC_ENUMS(PLUGIN
, Plugin
)
773 SYNC_ENUMS(CONTENT
, Content
)
774 SYNC_ENUMS(IPDLUNITTEST
, IPDLUnitTest
)
776 // .. and ensure that that is all of them:
777 static_assert(GeckoProcessType_IPDLUnitTest
+ 1 == GeckoProcessType_End
,
778 "Did not find the final GeckoProcessType");
781 nsXULAppInfo::GetProcessType(uint32_t* aResult
)
783 NS_ENSURE_ARG_POINTER(aResult
);
784 *aResult
= XRE_GetProcessType();
789 nsXULAppInfo::EnsureContentProcess()
791 if (XRE_GetProcessType() != GeckoProcessType_Default
)
792 return NS_ERROR_NOT_AVAILABLE
;
794 nsRefPtr
<ContentParent
> unused
= ContentParent::GetNewOrUsed();
799 nsXULAppInfo::InvalidateCachesOnRestart()
801 nsCOMPtr
<nsIFile
> file
;
802 nsresult rv
= NS_GetSpecialDirectory(NS_APP_PROFILE_DIR_STARTUP
,
803 getter_AddRefs(file
));
807 return NS_ERROR_NOT_AVAILABLE
;
809 file
->AppendNative(FILE_COMPATIBILITY_INFO
);
812 rv
= parser
.Init(file
);
814 // This fails if compatibility.ini is not there, so we'll
815 // flush the caches on the next restart anyways.
820 rv
= parser
.GetString("Compatibility", "InvalidateCaches", buf
);
823 PRFileDesc
*fd
= nullptr;
824 file
->OpenNSPRFileDesc(PR_RDWR
| PR_APPEND
, 0600, &fd
);
826 NS_ERROR("could not create output stream");
827 return NS_ERROR_NOT_AVAILABLE
;
829 static const char kInvalidationHeader
[] = NS_LINEBREAK
"InvalidateCaches=1" NS_LINEBREAK
;
830 PR_Write(fd
, kInvalidationHeader
, sizeof(kInvalidationHeader
) - 1);
837 nsXULAppInfo::GetReplacedLockTime(PRTime
*aReplacedLockTime
)
840 return NS_ERROR_NOT_AVAILABLE
;
841 gProfileLock
->GetReplacedLockTime(aReplacedLockTime
);
846 nsXULAppInfo::GetLastRunCrashID(nsAString
&aLastRunCrashID
)
848 #ifdef MOZ_CRASHREPORTER
849 CrashReporter::GetLastRunCrashID(aLastRunCrashID
);
852 return NS_ERROR_NOT_IMPLEMENTED
;
857 // Matches the enum in WinNT.h for the Vista SDK but renamed so that we can
858 // safely build with the Vista SDK and without it.
861 VistaTokenElevationTypeDefault
= 1,
862 VistaTokenElevationTypeFull
,
863 VistaTokenElevationTypeLimited
864 } VISTA_TOKEN_ELEVATION_TYPE
;
866 // avoid collision with TokeElevationType enum in WinNT.h
868 #define VistaTokenElevationType static_cast< TOKEN_INFORMATION_CLASS >( 18 )
871 nsXULAppInfo::GetUserCanElevate(bool *aUserCanElevate
)
875 VISTA_TOKEN_ELEVATION_TYPE elevationType
;
878 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
) ||
879 !GetTokenInformation(hToken
, VistaTokenElevationType
, &elevationType
,
880 sizeof(elevationType
), &dwSize
)) {
881 *aUserCanElevate
= false;
884 // The possible values returned for elevationType and their meanings are:
885 // TokenElevationTypeDefault: The token does not have a linked token
886 // (e.g. UAC disabled or a standard user, so they can't be elevated)
887 // TokenElevationTypeFull: The token is linked to an elevated token
888 // (e.g. UAC is enabled and the user is already elevated so they can't
889 // be elevated again)
890 // TokenElevationTypeLimited: The token is linked to a limited token
891 // (e.g. UAC is enabled and the user is not elevated, so they can be
893 *aUserCanElevate
= (elevationType
== VistaTokenElevationTypeLimited
);
903 #ifdef MOZ_CRASHREPORTER
905 nsXULAppInfo::GetEnabled(bool *aEnabled
)
907 *aEnabled
= CrashReporter::GetEnabled();
912 nsXULAppInfo::SetEnabled(bool aEnabled
)
915 if (CrashReporter::GetEnabled())
916 // no point in erroring for double-enabling
919 nsCOMPtr
<nsIFile
> xreDirectory
;
921 xreDirectory
= gAppData
->xreDirectory
;
924 // We didn't get started through XRE_Main, probably
925 nsCOMPtr
<nsIFile
> greDir
;
926 NS_GetSpecialDirectory(NS_GRE_DIR
, getter_AddRefs(greDir
));
928 return NS_ERROR_FAILURE
;
930 xreDirectory
= do_QueryInterface(greDir
);
932 return NS_ERROR_FAILURE
;
934 return CrashReporter::SetExceptionHandler(xreDirectory
, true);
937 if (!CrashReporter::GetEnabled())
938 // no point in erroring for double-disabling
941 return CrashReporter::UnsetExceptionHandler();
946 nsXULAppInfo::GetServerURL(nsIURL
** aServerURL
)
948 if (!CrashReporter::GetEnabled())
949 return NS_ERROR_NOT_INITIALIZED
;
952 if (!CrashReporter::GetServerURL(data
)) {
953 return NS_ERROR_FAILURE
;
955 nsCOMPtr
<nsIURI
> uri
;
956 NS_NewURI(getter_AddRefs(uri
), data
);
958 return NS_ERROR_FAILURE
;
960 nsCOMPtr
<nsIURL
> url
;
961 url
= do_QueryInterface(uri
);
962 NS_ADDREF(*aServerURL
= url
);
968 nsXULAppInfo::SetServerURL(nsIURL
* aServerURL
)
971 // only allow https or http URLs
972 nsresult rv
= aServerURL
->SchemeIs("https", &schemeOk
);
973 NS_ENSURE_SUCCESS(rv
, rv
);
975 rv
= aServerURL
->SchemeIs("http", &schemeOk
);
976 NS_ENSURE_SUCCESS(rv
, rv
);
979 return NS_ERROR_INVALID_ARG
;
982 rv
= aServerURL
->GetSpec(spec
);
983 NS_ENSURE_SUCCESS(rv
, rv
);
985 return CrashReporter::SetServerURL(spec
);
989 nsXULAppInfo::GetMinidumpPath(nsIFile
** aMinidumpPath
)
991 if (!CrashReporter::GetEnabled())
992 return NS_ERROR_NOT_INITIALIZED
;
995 if (!CrashReporter::GetMinidumpPath(path
))
996 return NS_ERROR_FAILURE
;
998 nsresult rv
= NS_NewLocalFile(path
, false, aMinidumpPath
);
999 NS_ENSURE_SUCCESS(rv
, rv
);
1004 nsXULAppInfo::SetMinidumpPath(nsIFile
* aMinidumpPath
)
1007 nsresult rv
= aMinidumpPath
->GetPath(path
);
1008 NS_ENSURE_SUCCESS(rv
, rv
);
1009 return CrashReporter::SetMinidumpPath(path
);
1013 nsXULAppInfo::AnnotateCrashReport(const nsACString
& key
,
1014 const nsACString
& data
)
1016 return CrashReporter::AnnotateCrashReport(key
, data
);
1020 nsXULAppInfo::AppendAppNotesToCrashReport(const nsACString
& data
)
1022 return CrashReporter::AppendAppNotesToCrashReport(data
);
1026 nsXULAppInfo::RegisterAppMemory(uint64_t pointer
,
1029 return CrashReporter::RegisterAppMemory((void *)pointer
, len
);
1033 nsXULAppInfo::WriteMinidumpForException(void* aExceptionInfo
)
1036 return CrashReporter::WriteMinidumpForException(static_cast<EXCEPTION_POINTERS
*>(aExceptionInfo
));
1038 return NS_ERROR_NOT_IMPLEMENTED
;
1043 nsXULAppInfo::AppendObjCExceptionInfoToAppNotes(void* aException
)
1046 return CrashReporter::AppendObjCExceptionInfoToAppNotes(aException
);
1048 return NS_ERROR_NOT_IMPLEMENTED
;
1053 nsXULAppInfo::GetSubmitReports(bool* aEnabled
)
1055 return CrashReporter::GetSubmitReports(aEnabled
);
1059 nsXULAppInfo::SetSubmitReports(bool aEnabled
)
1061 return CrashReporter::SetSubmitReports(aEnabled
);
1066 static const nsXULAppInfo kAppInfo
;
1067 static nsresult
AppInfoConstructor(nsISupports
* aOuter
,
1068 REFNSIID aIID
, void **aResult
)
1070 NS_ENSURE_NO_AGGREGATION(aOuter
);
1072 return const_cast<nsXULAppInfo
*>(&kAppInfo
)->
1073 QueryInterface(aIID
, aResult
);
1076 bool gLogConsoleErrors
= false;
1078 #define NS_ENSURE_TRUE_LOG(x, ret) \
1080 if (MOZ_UNLIKELY(!(x))) { \
1081 NS_WARNING("NS_ENSURE_TRUE(" #x ") failed"); \
1082 gLogConsoleErrors = true; \
1087 #define NS_ENSURE_SUCCESS_LOG(res, ret) \
1088 NS_ENSURE_TRUE_LOG(NS_SUCCEEDED(res), ret)
1091 * Because we're starting/stopping XPCOM several times in different scenarios,
1092 * this class is a stack-based critter that makes sure that XPCOM is shut down
1093 * during early returns.
1096 class ScopedXPCOMStartup
1099 ScopedXPCOMStartup() :
1100 mServiceManager(nullptr) { }
1101 ~ScopedXPCOMStartup();
1103 nsresult
Initialize();
1104 nsresult
SetWindowCreator(nsINativeAppSupport
* native
);
1106 static nsresult
CreateAppSupport(nsISupports
* aOuter
, REFNSIID aIID
, void** aResult
);
1109 nsIServiceManager
* mServiceManager
;
1110 static nsINativeAppSupport
* gNativeAppSupport
;
1113 ScopedXPCOMStartup::~ScopedXPCOMStartup()
1115 NS_IF_RELEASE(gNativeAppSupport
);
1117 if (mServiceManager
) {
1119 // On OS X, we need a pool to catch cocoa objects that are autoreleased
1121 mozilla::MacAutoreleasePool pool
;
1124 nsCOMPtr
<nsIAppStartup
> appStartup (do_GetService(NS_APPSTARTUP_CONTRACTID
));
1126 appStartup
->DestroyHiddenWindow();
1128 gDirServiceProvider
->DoShutdown();
1129 PROFILER_MARKER("Shutdown early");
1133 NS_ShutdownXPCOM(mServiceManager
);
1134 mServiceManager
= nullptr;
1138 // {95d89e3e-a169-41a3-8e56-719978e15b12}
1139 #define APPINFO_CID \
1140 { 0x95d89e3e, 0xa169, 0x41a3, { 0x8e, 0x56, 0x71, 0x99, 0x78, 0xe1, 0x5b, 0x12 } }
1142 // {0C4A446C-EE82-41f2-8D04-D366D2C7A7D4}
1143 static const nsCID kNativeAppSupportCID
=
1144 { 0xc4a446c, 0xee82, 0x41f2, { 0x8d, 0x4, 0xd3, 0x66, 0xd2, 0xc7, 0xa7, 0xd4 } };
1146 // {5F5E59CE-27BC-47eb-9D1F-B09CA9049836}
1147 static const nsCID kProfileServiceCID
=
1148 { 0x5f5e59ce, 0x27bc, 0x47eb, { 0x9d, 0x1f, 0xb0, 0x9c, 0xa9, 0x4, 0x98, 0x36 } };
1150 static already_AddRefed
<nsIFactory
>
1151 ProfileServiceFactoryConstructor(const mozilla::Module
& module
, const mozilla::Module::CIDEntry
& entry
)
1153 nsCOMPtr
<nsIFactory
> factory
;
1154 NS_NewToolkitProfileFactory(getter_AddRefs(factory
));
1155 return factory
.forget();
1158 NS_DEFINE_NAMED_CID(APPINFO_CID
);
1160 static const mozilla::Module::CIDEntry kXRECIDs
[] = {
1161 { &kAPPINFO_CID
, false, nullptr, AppInfoConstructor
},
1162 { &kProfileServiceCID
, false, ProfileServiceFactoryConstructor
, nullptr },
1163 { &kNativeAppSupportCID
, false, nullptr, ScopedXPCOMStartup::CreateAppSupport
},
1167 static const mozilla::Module::ContractIDEntry kXREContracts
[] = {
1168 { XULAPPINFO_SERVICE_CONTRACTID
, &kAPPINFO_CID
},
1169 { XULRUNTIME_SERVICE_CONTRACTID
, &kAPPINFO_CID
},
1170 #ifdef MOZ_CRASHREPORTER
1171 { NS_CRASHREPORTER_CONTRACTID
, &kAPPINFO_CID
},
1173 { NS_PROFILESERVICE_CONTRACTID
, &kProfileServiceCID
},
1174 { NS_NATIVEAPPSUPPORT_CONTRACTID
, &kNativeAppSupportCID
},
1178 static const mozilla::Module kXREModule
= {
1179 mozilla::Module::kVersion
,
1184 NSMODULE_DEFN(Apprunner
) = &kXREModule
;
1187 ScopedXPCOMStartup::Initialize()
1189 NS_ASSERTION(gDirServiceProvider
, "Should not get here!");
1193 rv
= NS_InitXPCOM2(&mServiceManager
, gDirServiceProvider
->GetAppDir(),
1194 gDirServiceProvider
);
1195 if (NS_FAILED(rv
)) {
1196 NS_ERROR("Couldn't start xpcom!");
1197 mServiceManager
= nullptr;
1200 nsCOMPtr
<nsIComponentRegistrar
> reg
=
1201 do_QueryInterface(mServiceManager
);
1202 NS_ASSERTION(reg
, "Service Manager doesn't QI to Registrar.");
1209 * This is a little factory class that serves as a singleton-service-factory
1210 * for the nativeappsupport object.
1212 class nsSingletonFactory MOZ_FINAL
: public nsIFactory
1218 nsSingletonFactory(nsISupports
* aSingleton
);
1219 ~nsSingletonFactory() { }
1222 nsCOMPtr
<nsISupports
> mSingleton
;
1225 nsSingletonFactory::nsSingletonFactory(nsISupports
* aSingleton
)
1226 : mSingleton(aSingleton
)
1228 NS_ASSERTION(mSingleton
, "Singleton was null!");
1231 NS_IMPL_ISUPPORTS1(nsSingletonFactory
, nsIFactory
)
1234 nsSingletonFactory::CreateInstance(nsISupports
* aOuter
,
1238 NS_ENSURE_NO_AGGREGATION(aOuter
);
1240 return mSingleton
->QueryInterface(aIID
, aResult
);
1244 nsSingletonFactory::LockFactory(bool)
1250 * Set our windowcreator on the WindowWatcher service.
1253 ScopedXPCOMStartup::SetWindowCreator(nsINativeAppSupport
* native
)
1257 NS_IF_ADDREF(gNativeAppSupport
= native
);
1259 // Inform the chrome registry about OS accessibility
1260 nsCOMPtr
<nsIToolkitChromeRegistry
> cr
=
1261 mozilla::services::GetToolkitChromeRegistryService();
1264 cr
->CheckForOSAccessibility();
1266 nsCOMPtr
<nsIWindowCreator
> creator (do_GetService(NS_APPSTARTUP_CONTRACTID
));
1267 if (!creator
) return NS_ERROR_UNEXPECTED
;
1269 nsCOMPtr
<nsIWindowWatcher
> wwatch
1270 (do_GetService(NS_WINDOWWATCHER_CONTRACTID
, &rv
));
1271 NS_ENSURE_SUCCESS(rv
, rv
);
1273 return wwatch
->SetWindowCreator(creator
);
1276 /* static */ nsresult
1277 ScopedXPCOMStartup::CreateAppSupport(nsISupports
* aOuter
, REFNSIID aIID
, void** aResult
)
1280 return NS_ERROR_NO_AGGREGATION
;
1282 if (!gNativeAppSupport
)
1283 return NS_ERROR_NOT_INITIALIZED
;
1285 return gNativeAppSupport
->QueryInterface(aIID
, aResult
);
1288 nsINativeAppSupport
* ScopedXPCOMStartup::gNativeAppSupport
;
1291 * A helper class which calls NS_LogInit/NS_LogTerm in its scope.
1296 ScopedLogging() { NS_LogInit(); }
1297 ~ScopedLogging() { NS_LogTerm(); }
1300 static void DumpArbitraryHelp()
1307 ScopedXPCOMStartup xpcom
;
1310 nsCOMPtr
<nsICommandLineRunner
> cmdline
1311 (do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
1316 rv
= cmdline
->GetHelpText(text
);
1317 if (NS_SUCCEEDED(rv
))
1318 printf("%s", text
.get());
1322 // English text needs to go into a dtd file.
1323 // But when this is called we have no components etc. These strings must either be
1324 // here, or in a native resource file.
1328 printf("Usage: %s [ options ... ] [URL]\n"
1329 " where options include:\n\n", gArgv
[0]);
1332 printf("X11 options\n"
1333 " --display=DISPLAY X display to use\n"
1334 " --sync Make X calls synchronous\n");
1337 printf(" --g-fatal-warnings Make all warnings fatal\n"
1338 "\n%s options\n", gAppData
->name
);
1341 printf(" -h or -help Print this message.\n"
1342 " -v or -version Print %s version.\n"
1343 " -P <profile> Start with <profile>.\n"
1344 " -migration Start with migration wizard.\n"
1345 " -ProfileManager Start with ProfileManager.\n"
1346 " -no-remote Do not accept or send remote commands; implies -new-instance.\n"
1347 " -new-instance Open new instance, not a new window in running instance.\n"
1348 " -UILocale <locale> Start with <locale> resources as UI Locale.\n"
1349 " -safe-mode Disables extensions and themes for this session.\n", gAppData
->name
);
1351 #if defined(XP_WIN) || defined(XP_OS2)
1352 printf(" -console Start %s with a debugging console.\n", gAppData
->name
);
1355 // this works, but only after the components have registered. so if you drop in a new command line handler, -help
1356 // won't not until the second run.
1357 // out of the bug, because we ship a component.reg file, it works correctly.
1358 DumpArbitraryHelp();
1361 #if defined(DEBUG) && defined(XP_WIN)
1363 #define _CRTDBG_MAP_ALLOC
1365 // Set a CRT ReportHook function to capture and format MSCRT
1366 // warnings, errors and assertions.
1367 // See http://msdn.microsoft.com/en-US/library/74kabxyx(v=VS.80).aspx
1370 #include "mozilla/mozalloc_abort.h"
1371 static int MSCRTReportHook( int aReportType
, char *aMessage
, int *oReturnValue
)
1373 *oReturnValue
= 0; // continue execution
1375 // Do not use fprintf or other functions which may allocate
1376 // memory from the heap which may be corrupted. Instead,
1377 // use fputs to output the leading portion of the message
1378 // and use mozalloc_abort to emit the remainder of the
1381 switch(aReportType
) {
1383 fputs("\nWARNING: CRT WARNING", stderr
);
1384 fputs(aMessage
, stderr
);
1385 fputs("\n", stderr
);
1388 fputs("\n###!!! ABORT: CRT ERROR ", stderr
);
1389 mozalloc_abort(aMessage
);
1392 fputs("\n###!!! ABORT: CRT ASSERT ", stderr
);
1393 mozalloc_abort(aMessage
);
1397 // do not invoke the debugger
1406 if (gAppData
->vendor
)
1407 printf("%s ", gAppData
->vendor
);
1408 printf("%s %s", gAppData
->name
, gAppData
->version
);
1409 if (gAppData
->copyright
)
1410 printf(", %s", gAppData
->copyright
);
1414 #ifdef MOZ_ENABLE_XREMOTE
1415 // use int here instead of a PR type since it will be returned
1416 // from main - just to keep types consistent
1418 HandleRemoteArgument(const char* remote
, const char* aDesktopStartupID
)
1423 const char *profile
= 0;
1424 nsAutoCString
program(gAppData
->name
);
1425 ToLowerCase(program
);
1426 const char *username
= getenv("LOGNAME");
1428 ar
= CheckArg("p", false, &profile
);
1429 if (ar
== ARG_BAD
) {
1430 PR_fprintf(PR_STDERR
, "Error: argument -p requires a profile name\n");
1434 const char *temp
= nullptr;
1435 ar
= CheckArg("a", false, &temp
);
1436 if (ar
== ARG_BAD
) {
1437 PR_fprintf(PR_STDERR
, "Error: argument -a requires an application name\n");
1439 } else if (ar
== ARG_FOUND
) {
1440 program
.Assign(temp
);
1443 ar
= CheckArg("u", false, &username
);
1444 if (ar
== ARG_BAD
) {
1445 PR_fprintf(PR_STDERR
, "Error: argument -u requires a username\n");
1449 XRemoteClient client
;
1451 if (NS_FAILED(rv
)) {
1452 PR_fprintf(PR_STDERR
, "Error: Failed to connect to X server.\n");
1456 nsXPIDLCString response
;
1457 bool success
= false;
1458 rv
= client
.SendCommand(program
.get(), username
, profile
, remote
,
1459 aDesktopStartupID
, getter_Copies(response
), &success
);
1460 // did the command fail?
1461 if (NS_FAILED(rv
)) {
1462 PR_fprintf(PR_STDERR
, "Error: Failed to send command: %s\n",
1463 response
? response
.get() : "No response included");
1468 PR_fprintf(PR_STDERR
, "Error: No running window found\n");
1476 RemoteCommandLine(const char* aDesktopStartupID
)
1481 nsAutoCString
program(gAppData
->name
);
1482 ToLowerCase(program
);
1483 const char *username
= getenv("LOGNAME");
1485 const char *temp
= nullptr;
1486 ar
= CheckArg("a", true, &temp
);
1487 if (ar
== ARG_BAD
) {
1488 PR_fprintf(PR_STDERR
, "Error: argument -a requires an application name\n");
1489 return REMOTE_ARG_BAD
;
1490 } else if (ar
== ARG_FOUND
) {
1491 program
.Assign(temp
);
1494 ar
= CheckArg("u", true, &username
);
1495 if (ar
== ARG_BAD
) {
1496 PR_fprintf(PR_STDERR
, "Error: argument -u requires a username\n");
1497 return REMOTE_ARG_BAD
;
1500 XRemoteClient client
;
1503 return REMOTE_NOT_FOUND
;
1505 nsXPIDLCString response
;
1506 bool success
= false;
1507 rv
= client
.SendCommandLine(program
.get(), username
, nullptr,
1508 gArgc
, gArgv
, aDesktopStartupID
,
1509 getter_Copies(response
), &success
);
1510 // did the command fail?
1511 if (NS_FAILED(rv
) || !success
)
1512 return REMOTE_NOT_FOUND
;
1514 return REMOTE_FOUND
;
1516 #endif // MOZ_ENABLE_XREMOTE
1519 XRE_InitOmnijar(nsIFile
* greOmni
, nsIFile
* appOmni
)
1521 mozilla::Omnijar::Init(greOmni
, appOmni
);
1525 XRE_GetBinaryPath(const char* argv0
, nsIFile
* *aResult
)
1527 return mozilla::BinaryPath::GetFile(argv0
, aResult
);
1531 #include "nsWindowsRestart.cpp"
1532 #include <shellapi.h>
1534 typedef BOOL (WINAPI
* SetProcessDEPPolicyFunc
)(DWORD dwFlags
);
1537 #if defined(XP_OS2) && (__KLIBC__ == 0 && __KLIBC_MINOR__ >= 6) // broken kLibc
1538 // Copy the environment maintained by the C library into an ASCIIZ array
1539 // that can be used to pass it on to the OS/2 Dos* APIs (which otherwise
1540 // don't know anything about the stuff set by PR_SetEnv() or setenv()).
1543 // just allocate the maximum amount (24 kB = 0x60000 bytes), to be able to
1544 // copy the existing environment
1545 char *env
= (char *)calloc(0x6000, sizeof(char));
1550 // walk along the environ string array of the C library and copy
1551 // everything (that fits) into the output environment array, leaving
1552 // null bytes between the entries
1553 char *penv
= env
; // movable pointer to result environment ASCIIZ array
1554 int i
= 0, space
= 0x6000;
1555 while (environ
[i
] && environ
[i
][0]) {
1556 int len
= strlen(environ
[i
]);
1557 if (space
- len
<= 0) {
1560 strcpy(penv
, environ
[i
]);
1561 i
++; // next environment variable
1562 penv
+= len
+ 1; // jump to after next null byte
1563 space
-= len
- 1; // subtract consumed length from usable space
1569 // OS2LaunchChild() is there to replace _execv() which is broken in the C
1570 // runtime library that comes with GCC 3.3.5 on OS/2. It uses createEnv()
1571 // to copy the process environment and add necessary variables
1573 // returns -1 on failure and 0 on success
1574 int OS2LaunchChild(const char *aExePath
, int aArgc
, char **aArgv
)
1576 // find total length of aArgv
1578 for (int i
= 0; i
< aArgc
; i
++) {
1579 len
+= strlen(aArgv
[i
]) + 1; // plus space in between
1581 len
++; // leave space for null byte at end
1582 // allocate enough space for all strings and nulls,
1583 // calloc helpfully initializes to null
1584 char *args
= (char *)calloc(len
, sizeof(char));
1588 char *pargs
= args
; // extra pointer to after the last argument
1589 // build argument list in the format the DosStartSession() wants,
1590 // adding spaces between the arguments
1591 for (int i
= 0; i
< aArgc
; i
++, *pargs
++ = ' ') {
1592 strcpy(pargs
, aArgv
[i
]);
1593 pargs
+= strlen(aArgv
[i
]);
1596 *(pargs
-1) = '\0'; // replace last space
1599 // make sure that the program is separated by null byte
1600 pargs
= strchr(args
, ' ');
1605 char *env
= createEnv();
1607 char error
[CCHMAXPATH
] = { 0 };
1608 RESULTCODES crc
= { 0 };
1609 ULONG rc
= DosExecPgm(error
, sizeof(error
), EXEC_ASYNC
, args
, env
,
1610 &crc
, (PSZ
)aExePath
);
1611 free(args
); // done with the arguments
1615 if (rc
!= NO_ERROR
) {
1623 // If aBlankCommandLine is true, then the application will be launched with a
1624 // blank command line instead of being launched with the same command line that
1625 // it was initially started with.
1626 static nsresult
LaunchChild(nsINativeAppSupport
* aNative
,
1627 bool aBlankCommandLine
= false)
1629 aNative
->Quit(); // release DDE mutex, if we're holding it
1631 // Restart this process by exec'ing it into the current process
1632 // if supported by the platform. Otherwise, use NSPR.
1635 // make sure JPROF doesn't think we're E10s
1636 unsetenv("JPROF_SLAVE");
1639 if (aBlankCommandLine
) {
1640 #if defined(MOZ_WIDGET_QT)
1641 // Remove only arguments not given to Qt
1642 gRestartArgc
= gQtOnlyArgc
;
1643 gRestartArgv
= gQtOnlyArgv
;
1646 gRestartArgv
[gRestartArgc
] = nullptr;
1650 SaveToEnv("MOZ_LAUNCHED_CHILD=1");
1652 #if defined(MOZ_WIDGET_ANDROID)
1653 mozilla::widget::android::GeckoAppShell::ScheduleRestart();
1655 #if defined(XP_MACOSX)
1656 CommandLineServiceMac::SetupMacCommandLine(gRestartArgc
, gRestartArgv
, true);
1657 uint32_t restartMode
= 0;
1658 restartMode
= gRestartMode
;
1659 LaunchChildMac(gRestartArgc
, gRestartArgv
, restartMode
);
1661 nsCOMPtr
<nsIFile
> lf
;
1662 nsresult rv
= XRE_GetBinaryPath(gArgv
[0], getter_AddRefs(lf
));
1667 nsAutoString exePath
;
1668 rv
= lf
->GetPath(exePath
);
1672 if (!WinLaunchChild(exePath
.get(), gRestartArgc
, gRestartArgv
))
1673 return NS_ERROR_FAILURE
;
1676 nsAutoCString exePath
;
1677 rv
= lf
->GetNativePath(exePath
);
1681 #if defined(XP_OS2) && (__KLIBC__ == 0 && __KLIBC_MINOR__ >= 6)
1682 // implementation of _execv() is broken with kLibc 0.6.x and later
1683 if (OS2LaunchChild(exePath
.get(), gRestartArgc
, gRestartArgv
) == -1)
1684 return NS_ERROR_FAILURE
;
1685 #elif defined(XP_OS2)
1686 if (_execv(exePath
.get(), gRestartArgv
) == -1)
1687 return NS_ERROR_FAILURE
;
1688 #elif defined(XP_UNIX)
1689 if (execv(exePath
.get(), gRestartArgv
) == -1)
1690 return NS_ERROR_FAILURE
;
1692 PRProcess
* process
= PR_CreateProcess(exePath
.get(), gRestartArgv
,
1694 if (!process
) return NS_ERROR_FAILURE
;
1697 PRStatus failed
= PR_WaitProcess(process
, &exitCode
);
1698 if (failed
|| exitCode
)
1699 return NS_ERROR_FAILURE
;
1700 #endif // XP_OS2 series
1703 #endif // MOZ_WIDGET_ANDROID
1705 return NS_ERROR_LAUNCHED_CHILD_PROCESS
;
1708 static const char kProfileProperties
[] =
1709 "chrome://mozapps/locale/profile/profileSelection.properties";
1712 ProfileLockedDialog(nsIFile
* aProfileDir
, nsIFile
* aProfileLocalDir
,
1713 nsIProfileUnlocker
* aUnlocker
,
1714 nsINativeAppSupport
* aNative
, nsIProfileLock
* *aResult
)
1718 ScopedXPCOMStartup xpcom
;
1719 rv
= xpcom
.Initialize();
1720 NS_ENSURE_SUCCESS(rv
, rv
);
1722 mozilla::Telemetry::WriteFailedProfileLock(aProfileDir
);
1724 rv
= xpcom
.SetWindowCreator(aNative
);
1725 NS_ENSURE_SUCCESS(rv
, NS_ERROR_FAILURE
);
1727 { //extra scoping is needed so we release these components before xpcom shutdown
1728 nsCOMPtr
<nsIStringBundleService
> sbs
=
1729 mozilla::services::GetStringBundleService();
1730 NS_ENSURE_TRUE(sbs
, NS_ERROR_FAILURE
);
1732 nsCOMPtr
<nsIStringBundle
> sb
;
1733 sbs
->CreateBundle(kProfileProperties
, getter_AddRefs(sb
));
1734 NS_ENSURE_TRUE_LOG(sbs
, NS_ERROR_FAILURE
);
1736 NS_ConvertUTF8toUTF16
appName(gAppData
->name
);
1737 const PRUnichar
* params
[] = {appName
.get(), appName
.get()};
1739 nsXPIDLString killMessage
;
1741 static const PRUnichar 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"
1742 static const PRUnichar 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"
1744 static const PRUnichar 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"
1745 static const PRUnichar 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"
1748 sb
->FormatStringFromName(aUnlocker
? kRestartUnlocker
: kRestartNoUnlocker
,
1749 params
, 2, getter_Copies(killMessage
));
1751 nsXPIDLString killTitle
;
1752 sb
->FormatStringFromName(NS_LITERAL_STRING("restartTitle").get(),
1753 params
, 1, getter_Copies(killTitle
));
1755 if (!killMessage
|| !killTitle
)
1756 return NS_ERROR_FAILURE
;
1758 nsCOMPtr
<nsIPromptService
> ps
1759 (do_GetService(NS_PROMPTSERVICE_CONTRACTID
));
1760 NS_ENSURE_TRUE(ps
, NS_ERROR_FAILURE
);
1764 #ifdef MOZ_WIDGET_ANDROID
1765 mozilla::widget::android::GeckoAppShell::KillAnyZombies();
1768 const uint32_t flags
=
1769 (nsIPromptService::BUTTON_TITLE_CANCEL
*
1770 nsIPromptService::BUTTON_POS_0
) +
1771 (nsIPromptService::BUTTON_TITLE_IS_STRING
*
1772 nsIPromptService::BUTTON_POS_1
) +
1773 nsIPromptService::BUTTON_POS_1_DEFAULT
;
1775 bool checkState
= false;
1776 rv
= ps
->ConfirmEx(nullptr, killTitle
, killMessage
, flags
,
1777 killTitle
, nullptr, nullptr, nullptr,
1778 &checkState
, &button
);
1779 NS_ENSURE_SUCCESS_LOG(rv
, rv
);
1783 rv
= aUnlocker
->Unlock(nsIProfileUnlocker::FORCE_QUIT
);
1787 return NS_LockProfilePath(aProfileDir
, aProfileLocalDir
,
1791 #ifdef MOZ_WIDGET_ANDROID
1792 if (mozilla::widget::android::GeckoAppShell::UnlockProfile()) {
1793 return NS_LockProfilePath(aProfileDir
, aProfileLocalDir
,
1797 rv
= ps
->Alert(nullptr, killTitle
, killMessage
);
1798 NS_ENSURE_SUCCESS_LOG(rv
, rv
);
1802 return NS_ERROR_ABORT
;
1808 ProfileMissingDialog(nsINativeAppSupport
* aNative
)
1812 ScopedXPCOMStartup xpcom
;
1813 rv
= xpcom
.Initialize();
1814 NS_ENSURE_SUCCESS(rv
, rv
);
1816 rv
= xpcom
.SetWindowCreator(aNative
);
1817 NS_ENSURE_SUCCESS(rv
, NS_ERROR_FAILURE
);
1819 { //extra scoping is needed so we release these components before xpcom shutdown
1820 nsCOMPtr
<nsIStringBundleService
> sbs
=
1821 mozilla::services::GetStringBundleService();
1822 NS_ENSURE_TRUE(sbs
, NS_ERROR_FAILURE
);
1824 nsCOMPtr
<nsIStringBundle
> sb
;
1825 sbs
->CreateBundle(kProfileProperties
, getter_AddRefs(sb
));
1826 NS_ENSURE_TRUE_LOG(sbs
, NS_ERROR_FAILURE
);
1828 NS_ConvertUTF8toUTF16
appName(gAppData
->name
);
1829 const PRUnichar
* params
[] = {appName
.get(), appName
.get()};
1831 nsXPIDLString missingMessage
;
1834 static const PRUnichar kMissing
[] = {'p','r','o','f','i','l','e','M','i','s','s','i','n','g','\0'};
1835 sb
->FormatStringFromName(kMissing
, params
, 2, getter_Copies(missingMessage
));
1837 nsXPIDLString missingTitle
;
1838 sb
->FormatStringFromName(NS_LITERAL_STRING("profileMissingTitle").get(),
1839 params
, 1, getter_Copies(missingTitle
));
1841 if (missingMessage
&& missingTitle
) {
1842 nsCOMPtr
<nsIPromptService
> ps
1843 (do_GetService(NS_PROMPTSERVICE_CONTRACTID
));
1844 NS_ENSURE_TRUE(ps
, NS_ERROR_FAILURE
);
1846 ps
->Alert(nullptr, missingTitle
, missingMessage
);
1849 return NS_ERROR_ABORT
;
1854 ProfileLockedDialog(nsIToolkitProfile
* aProfile
, nsIProfileUnlocker
* aUnlocker
,
1855 nsINativeAppSupport
* aNative
, nsIProfileLock
* *aResult
)
1857 nsCOMPtr
<nsIFile
> profileDir
;
1858 nsresult rv
= aProfile
->GetRootDir(getter_AddRefs(profileDir
));
1859 if (NS_FAILED(rv
)) return rv
;
1862 profileDir
->Exists(&exists
);
1864 return ProfileMissingDialog(aNative
);
1867 nsCOMPtr
<nsIFile
> profileLocalDir
;
1868 rv
= aProfile
->GetLocalDir(getter_AddRefs(profileLocalDir
));
1869 if (NS_FAILED(rv
)) return rv
;
1871 return ProfileLockedDialog(profileDir
, profileLocalDir
, aUnlocker
, aNative
,
1875 static const char kProfileManagerURL
[] =
1876 "chrome://mozapps/content/profile/profileSelection.xul";
1879 ShowProfileManager(nsIToolkitProfileService
* aProfileSvc
,
1880 nsINativeAppSupport
* aNative
)
1884 nsCOMPtr
<nsIFile
> profD
, profLD
;
1885 PRUnichar
* profileNamePtr
;
1886 nsAutoCString profileName
;
1889 ScopedXPCOMStartup xpcom
;
1890 rv
= xpcom
.Initialize();
1891 NS_ENSURE_SUCCESS(rv
, rv
);
1893 rv
= xpcom
.SetWindowCreator(aNative
);
1894 NS_ENSURE_SUCCESS(rv
, NS_ERROR_FAILURE
);
1897 CommandLineServiceMac::SetupMacCommandLine(gRestartArgc
, gRestartArgv
, true);
1901 // we don't have to wait here because profile manager window will pump
1902 // and DDE message will be handled
1903 ProcessDDE(aNative
, false);
1906 { //extra scoping is needed so we release these components before xpcom shutdown
1907 nsCOMPtr
<nsIWindowWatcher
> windowWatcher
1908 (do_GetService(NS_WINDOWWATCHER_CONTRACTID
));
1909 nsCOMPtr
<nsIDialogParamBlock
> ioParamBlock
1910 (do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID
));
1911 nsCOMPtr
<nsIMutableArray
> dlgArray (do_CreateInstance(NS_ARRAY_CONTRACTID
));
1912 NS_ENSURE_TRUE(windowWatcher
&& ioParamBlock
&& dlgArray
, NS_ERROR_FAILURE
);
1914 ioParamBlock
->SetObjects(dlgArray
);
1916 nsCOMPtr
<nsIAppStartup
> appStartup
1917 (do_GetService(NS_APPSTARTUP_CONTRACTID
));
1918 NS_ENSURE_TRUE(appStartup
, NS_ERROR_FAILURE
);
1920 nsCOMPtr
<nsIDOMWindow
> newWindow
;
1921 rv
= windowWatcher
->OpenWindow(nullptr,
1924 "centerscreen,chrome,modal,titlebar",
1926 getter_AddRefs(newWindow
));
1928 NS_ENSURE_SUCCESS_LOG(rv
, rv
);
1930 aProfileSvc
->Flush();
1932 int32_t dialogConfirmed
;
1933 rv
= ioParamBlock
->GetInt(0, &dialogConfirmed
);
1934 if (NS_FAILED(rv
) || dialogConfirmed
== 0) return NS_ERROR_ABORT
;
1936 nsCOMPtr
<nsIProfileLock
> lock
;
1937 rv
= dlgArray
->QueryElementAt(0, NS_GET_IID(nsIProfileLock
),
1938 getter_AddRefs(lock
));
1939 NS_ENSURE_SUCCESS_LOG(rv
, rv
);
1941 rv
= lock
->GetDirectory(getter_AddRefs(profD
));
1942 NS_ENSURE_SUCCESS(rv
, rv
);
1944 rv
= lock
->GetLocalDirectory(getter_AddRefs(profLD
));
1945 NS_ENSURE_SUCCESS(rv
, rv
);
1947 rv
= ioParamBlock
->GetString(0, &profileNamePtr
);
1948 NS_ENSURE_SUCCESS(rv
, rv
);
1950 CopyUTF16toUTF8(profileNamePtr
, profileName
);
1951 NS_Free(profileNamePtr
);
1957 SaveFileToEnv("XRE_PROFILE_PATH", profD
);
1958 SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", profLD
);
1959 SaveWordToEnv("XRE_PROFILE_NAME", profileName
);
1961 bool offline
= false;
1962 aProfileSvc
->GetStartOffline(&offline
);
1964 SaveToEnv("XRE_START_OFFLINE=1");
1967 return LaunchChild(aNative
);
1971 GetCurrentProfileIsDefault(nsIToolkitProfileService
* aProfileSvc
,
1972 nsIFile
* aCurrentProfileRoot
, bool *aResult
)
1975 // Check that the profile to reset is the default since reset and the associated migration are
1976 // only supported in that case.
1977 nsCOMPtr
<nsIToolkitProfile
> selectedProfile
;
1978 nsCOMPtr
<nsIFile
> selectedProfileRoot
;
1979 rv
= aProfileSvc
->GetSelectedProfile(getter_AddRefs(selectedProfile
));
1980 NS_ENSURE_SUCCESS(rv
, rv
);
1982 rv
= selectedProfile
->GetRootDir(getter_AddRefs(selectedProfileRoot
));
1983 NS_ENSURE_SUCCESS(rv
, rv
);
1985 bool currentIsSelected
;
1986 rv
= aCurrentProfileRoot
->Equals(selectedProfileRoot
, ¤tIsSelected
);
1988 *aResult
= currentIsSelected
;
1993 * Set the currently running profile as the default/selected one.
1995 * @param aCurrentProfileRoot The root directory of the current profile.
1996 * @return an error if aCurrentProfileRoot is not found or the profile could not
1997 * be set as the default.
2000 SetCurrentProfileAsDefault(nsIToolkitProfileService
* aProfileSvc
,
2001 nsIFile
* aCurrentProfileRoot
)
2003 NS_ENSURE_ARG_POINTER(aProfileSvc
);
2005 nsCOMPtr
<nsISimpleEnumerator
> profiles
;
2006 nsresult rv
= aProfileSvc
->GetProfiles(getter_AddRefs(profiles
));
2010 bool foundMatchingProfile
= false;
2011 nsCOMPtr
<nsIToolkitProfile
> profile
;
2012 rv
= profiles
->GetNext(getter_AddRefs(profile
));
2013 while (NS_SUCCEEDED(rv
)) {
2014 nsCOMPtr
<nsIFile
> profileRoot
;
2015 profile
->GetRootDir(getter_AddRefs(profileRoot
));
2016 profileRoot
->Equals(aCurrentProfileRoot
, &foundMatchingProfile
);
2017 if (foundMatchingProfile
&& profile
) {
2018 rv
= aProfileSvc
->SetSelectedProfile(profile
);
2019 if (NS_SUCCEEDED(rv
))
2020 rv
= aProfileSvc
->Flush();
2023 rv
= profiles
->GetNext(getter_AddRefs(profile
));
2028 static bool gDoMigration
= false;
2029 static bool gDoProfileReset
= false;
2031 // Pick a profile. We need to end up with a profile lock.
2033 // 1) check for -profile <path>
2034 // 2) check for -P <name>
2035 // 3) check for -ProfileManager
2036 // 4) use the default profile, if there is one
2037 // 5) if there are *no* profiles, set up profile-migration
2038 // 6) display the profile-manager UI
2040 SelectProfile(nsIProfileLock
* *aResult
, nsIToolkitProfileService
* aProfileSvc
, nsINativeAppSupport
* aNative
,
2041 bool* aStartOffline
, nsACString
* aProfileName
)
2043 StartupTimeline::Record(StartupTimeline::SELECT_PROFILE
);
2049 *aStartOffline
= false;
2051 ar
= CheckArg("offline", true);
2052 if (ar
== ARG_BAD
) {
2053 PR_fprintf(PR_STDERR
, "Error: argument -offline is invalid when argument -osint is specified\n");
2054 return NS_ERROR_FAILURE
;
2057 if (ar
|| EnvHasValue("XRE_START_OFFLINE"))
2058 *aStartOffline
= true;
2060 if (EnvHasValue("MOZ_RESET_PROFILE_RESTART")) {
2061 gDoProfileReset
= true;
2062 gDoMigration
= true;
2063 SaveToEnv("MOZ_RESET_PROFILE_RESTART=");
2066 // reset-profile and migration args need to be checked before any profiles are chosen below.
2067 ar
= CheckArg("reset-profile", true);
2068 if (ar
== ARG_BAD
) {
2069 PR_fprintf(PR_STDERR
, "Error: argument -reset-profile is invalid when argument -osint is specified\n");
2070 return NS_ERROR_FAILURE
;
2071 } else if (ar
== ARG_FOUND
) {
2072 gDoProfileReset
= true;
2075 ar
= CheckArg("migration", true);
2076 if (ar
== ARG_BAD
) {
2077 PR_fprintf(PR_STDERR
, "Error: argument -migration is invalid when argument -osint is specified\n");
2078 return NS_ERROR_FAILURE
;
2079 } else if (ar
== ARG_FOUND
) {
2080 gDoMigration
= true;
2083 nsCOMPtr
<nsIFile
> lf
= GetFileFromEnv("XRE_PROFILE_PATH");
2085 nsCOMPtr
<nsIFile
> localDir
=
2086 GetFileFromEnv("XRE_PROFILE_LOCAL_PATH");
2091 arg
= PR_GetEnv("XRE_PROFILE_NAME");
2092 if (arg
&& *arg
&& aProfileName
)
2093 aProfileName
->Assign(nsDependentCString(arg
));
2095 // Clear out flags that we handled (or should have handled!) last startup.
2097 CheckArg("p", false, &dummy
);
2098 CheckArg("profile", false, &dummy
);
2099 CheckArg("profilemanager");
2101 if (gDoProfileReset
) {
2102 // Check that the profile to reset is the default since reset and migration are only
2103 // supported in that case.
2104 bool currentIsSelected
;
2105 GetCurrentProfileIsDefault(aProfileSvc
, lf
, ¤tIsSelected
);
2106 if (!currentIsSelected
) {
2107 NS_WARNING("Profile reset is only supported for the default profile.");
2108 gDoProfileReset
= gDoMigration
= false;
2111 // If we're resetting a profile, create a new one and use it to startup.
2112 nsCOMPtr
<nsIToolkitProfile
> newProfile
;
2113 rv
= CreateResetProfile(aProfileSvc
, getter_AddRefs(newProfile
));
2114 if (NS_SUCCEEDED(rv
)) {
2115 rv
= newProfile
->GetRootDir(getter_AddRefs(lf
));
2116 NS_ENSURE_SUCCESS(rv
, rv
);
2117 SaveFileToEnv("XRE_PROFILE_PATH", lf
);
2119 rv
= newProfile
->GetLocalDir(getter_AddRefs(localDir
));
2120 NS_ENSURE_SUCCESS(rv
, rv
);
2121 SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", localDir
);
2123 rv
= newProfile
->GetName(*aProfileName
);
2125 aProfileName
->Truncate(0);
2126 SaveWordToEnv("XRE_PROFILE_NAME", *aProfileName
);
2128 NS_WARNING("Profile reset failed.");
2129 gDoProfileReset
= false;
2133 return NS_LockProfilePath(lf
, localDir
, nullptr, aResult
);
2136 ar
= CheckArg("profile", true, &arg
);
2137 if (ar
== ARG_BAD
) {
2138 PR_fprintf(PR_STDERR
, "Error: argument -profile requires a path\n");
2139 return NS_ERROR_FAILURE
;
2142 if (gDoProfileReset
) {
2143 NS_WARNING("Profile reset is only supported for the default profile.");
2144 gDoProfileReset
= false;
2147 nsCOMPtr
<nsIFile
> lf
;
2148 rv
= XRE_GetFileFromPath(arg
, getter_AddRefs(lf
));
2149 NS_ENSURE_SUCCESS(rv
, rv
);
2151 nsCOMPtr
<nsIProfileUnlocker
> unlocker
;
2153 // Check if the profile path exists and it's a directory.
2155 lf
->Exists(&exists
);
2157 rv
= lf
->Create(nsIFile::DIRECTORY_TYPE
, 0700);
2158 NS_ENSURE_SUCCESS(rv
, rv
);
2161 // If a profile path is specified directory on the command line, then
2162 // assume that the temp directory is the same as the given directory.
2163 rv
= NS_LockProfilePath(lf
, lf
, getter_AddRefs(unlocker
), aResult
);
2164 if (NS_SUCCEEDED(rv
))
2167 return ProfileLockedDialog(lf
, lf
, unlocker
, aNative
, aResult
);
2170 ar
= CheckArg("createprofile", true, &arg
);
2171 if (ar
== ARG_BAD
) {
2172 PR_fprintf(PR_STDERR
, "Error: argument -createprofile requires a profile name\n");
2173 return NS_ERROR_FAILURE
;
2176 nsCOMPtr
<nsIToolkitProfile
> profile
;
2178 const char* delim
= strchr(arg
, ' ');
2180 nsCOMPtr
<nsIFile
> lf
;
2181 rv
= NS_NewNativeLocalFile(nsDependentCString(delim
+ 1),
2182 true, getter_AddRefs(lf
));
2183 if (NS_FAILED(rv
)) {
2184 PR_fprintf(PR_STDERR
, "Error: profile path not valid.\n");
2188 // As with -profile, assume that the given path will be used for the
2189 // main profile directory.
2190 rv
= aProfileSvc
->CreateProfile(lf
, nsDependentCSubstring(arg
, delim
),
2191 getter_AddRefs(profile
));
2193 rv
= aProfileSvc
->CreateProfile(nullptr, nsDependentCString(arg
),
2194 getter_AddRefs(profile
));
2196 // Some pathological arguments can make it this far
2197 if (NS_FAILED(rv
)) {
2198 PR_fprintf(PR_STDERR
, "Error creating profile.\n");
2201 rv
= NS_ERROR_ABORT
;
2202 aProfileSvc
->Flush();
2204 // XXXben need to ensure prefs.js exists here so the tinderboxes will
2206 nsCOMPtr
<nsIFile
> prefsJSFile
;
2207 profile
->GetRootDir(getter_AddRefs(prefsJSFile
));
2208 prefsJSFile
->AppendNative(NS_LITERAL_CSTRING("prefs.js"));
2209 nsAutoCString pathStr
;
2210 prefsJSFile
->GetNativePath(pathStr
);
2211 PR_fprintf(PR_STDERR
, "Success: created profile '%s' at '%s'\n", arg
, pathStr
.get());
2213 prefsJSFile
->Exists(&exists
);
2215 prefsJSFile
->Create(nsIFile::NORMAL_FILE_TYPE
, 0644);
2216 // XXXdarin perhaps 0600 would be better?
2222 rv
= aProfileSvc
->GetProfileCount(&count
);
2223 NS_ENSURE_SUCCESS(rv
, rv
);
2225 ar
= CheckArg("p", false, &arg
);
2226 if (ar
== ARG_BAD
) {
2227 ar
= CheckArg("osint");
2228 if (ar
== ARG_FOUND
) {
2229 PR_fprintf(PR_STDERR
, "Error: argument -p is invalid when argument -osint is specified\n");
2230 return NS_ERROR_FAILURE
;
2232 return ShowProfileManager(aProfileSvc
, aNative
);
2235 ar
= CheckArg("osint");
2236 if (ar
== ARG_FOUND
) {
2237 PR_fprintf(PR_STDERR
, "Error: argument -p is invalid when argument -osint is specified\n");
2238 return NS_ERROR_FAILURE
;
2240 nsCOMPtr
<nsIToolkitProfile
> profile
;
2241 rv
= aProfileSvc
->GetProfileByName(nsDependentCString(arg
),
2242 getter_AddRefs(profile
));
2243 if (NS_SUCCEEDED(rv
)) {
2244 if (gDoProfileReset
) {
2245 NS_WARNING("Profile reset is only supported for the default profile.");
2246 gDoProfileReset
= false;
2249 nsCOMPtr
<nsIProfileUnlocker
> unlocker
;
2250 rv
= profile
->Lock(getter_AddRefs(unlocker
), aResult
);
2251 if (NS_SUCCEEDED(rv
)) {
2253 aProfileName
->Assign(nsDependentCString(arg
));
2257 return ProfileLockedDialog(profile
, unlocker
, aNative
, aResult
);
2260 return ShowProfileManager(aProfileSvc
, aNative
);
2263 ar
= CheckArg("profilemanager", true);
2264 if (ar
== ARG_BAD
) {
2265 PR_fprintf(PR_STDERR
, "Error: argument -profilemanager is invalid when argument -osint is specified\n");
2266 return NS_ERROR_FAILURE
;
2267 } else if (ar
== ARG_FOUND
) {
2268 return ShowProfileManager(aProfileSvc
, aNative
);
2272 gDoMigration
= true;
2273 gDoProfileReset
= false;
2275 // create a default profile
2276 nsCOMPtr
<nsIToolkitProfile
> profile
;
2277 nsresult rv
= aProfileSvc
->CreateProfile(nullptr, // choose a default dir for us
2278 NS_LITERAL_CSTRING("default"),
2279 getter_AddRefs(profile
));
2280 if (NS_SUCCEEDED(rv
)) {
2281 aProfileSvc
->Flush();
2282 rv
= profile
->Lock(nullptr, aResult
);
2283 if (NS_SUCCEEDED(rv
)) {
2285 aProfileName
->Assign(NS_LITERAL_CSTRING("default"));
2291 bool useDefault
= true;
2293 aProfileSvc
->GetStartWithLastProfile(&useDefault
);
2296 nsCOMPtr
<nsIToolkitProfile
> profile
;
2297 // GetSelectedProfile will auto-select the only profile if there's just one
2298 aProfileSvc
->GetSelectedProfile(getter_AddRefs(profile
));
2300 // If we're resetting a profile, create a new one and use it to startup.
2301 if (gDoProfileReset
) {
2303 // Check that the source profile is not in use by temporarily acquiring its lock.
2304 nsIProfileLock
* tempProfileLock
;
2305 nsCOMPtr
<nsIProfileUnlocker
> unlocker
;
2306 rv
= profile
->Lock(getter_AddRefs(unlocker
), &tempProfileLock
);
2308 return ProfileLockedDialog(profile
, unlocker
, aNative
, &tempProfileLock
);
2311 nsCOMPtr
<nsIToolkitProfile
> newProfile
;
2312 rv
= CreateResetProfile(aProfileSvc
, getter_AddRefs(newProfile
));
2313 if (NS_SUCCEEDED(rv
))
2314 profile
= newProfile
;
2316 gDoProfileReset
= false;
2319 // If you close Firefox and very quickly reopen it, the old Firefox may
2320 // still be closing down. Rather than immediately showing the
2321 // "Firefox is running but is not responding" message, we spend a few
2322 // seconds retrying first.
2324 static const int kLockRetrySeconds
= 5;
2325 static const int kLockRetrySleepMS
= 100;
2327 nsCOMPtr
<nsIProfileUnlocker
> unlocker
;
2328 const TimeStamp start
= TimeStamp::Now();
2330 rv
= profile
->Lock(getter_AddRefs(unlocker
), aResult
);
2331 if (NS_SUCCEEDED(rv
)) {
2332 StartupTimeline::Record(StartupTimeline::AFTER_PROFILE_LOCKED
);
2333 // Try to grab the profile name.
2335 rv
= profile
->GetName(*aProfileName
);
2337 aProfileName
->Truncate(0);
2341 PR_Sleep(kLockRetrySleepMS
);
2342 } while (TimeStamp::Now() - start
< TimeDuration::FromSeconds(kLockRetrySeconds
));
2344 return ProfileLockedDialog(profile
, unlocker
, aNative
, aResult
);
2348 return ShowProfileManager(aProfileSvc
, aNative
);
2352 * Checks the compatibility.ini file to see if we have updated our application
2353 * or otherwise invalidated our caches. If the application has been updated,
2354 * we return false; otherwise, we return true. We also write the status
2355 * of the caches (valid/invalid) into the return param aCachesOK. The aCachesOK
2356 * is always invalid if the application has been updated.
2359 CheckCompatibility(nsIFile
* aProfileDir
, const nsCString
& aVersion
,
2360 const nsCString
& aOSABI
, nsIFile
* aXULRunnerDir
,
2361 nsIFile
* aAppDir
, nsIFile
* aFlagFile
,
2365 nsCOMPtr
<nsIFile
> file
;
2366 aProfileDir
->Clone(getter_AddRefs(file
));
2369 file
->AppendNative(FILE_COMPATIBILITY_INFO
);
2372 nsresult rv
= parser
.Init(file
);
2377 rv
= parser
.GetString("Compatibility", "LastVersion", buf
);
2378 if (NS_FAILED(rv
) || !aVersion
.Equals(buf
))
2381 rv
= parser
.GetString("Compatibility", "LastOSABI", buf
);
2382 if (NS_FAILED(rv
) || !aOSABI
.Equals(buf
))
2385 rv
= parser
.GetString("Compatibility", "LastPlatformDir", buf
);
2389 nsCOMPtr
<nsIFile
> lf
;
2390 rv
= NS_NewNativeLocalFile(buf
, false,
2391 getter_AddRefs(lf
));
2396 rv
= lf
->Equals(aXULRunnerDir
, &eq
);
2397 if (NS_FAILED(rv
) || !eq
)
2401 rv
= parser
.GetString("Compatibility", "LastAppDir", buf
);
2405 rv
= NS_NewNativeLocalFile(buf
, false,
2406 getter_AddRefs(lf
));
2410 rv
= lf
->Equals(aAppDir
, &eq
);
2411 if (NS_FAILED(rv
) || !eq
)
2415 // If we see this flag, caches are invalid.
2416 rv
= parser
.GetString("Compatibility", "InvalidateCaches", buf
);
2417 *aCachesOK
= (NS_FAILED(rv
) || !buf
.EqualsLiteral("1"));
2419 bool purgeCaches
= false;
2421 aFlagFile
->Exists(&purgeCaches
);
2424 *aCachesOK
= !purgeCaches
&& *aCachesOK
;
2428 static void BuildVersion(nsCString
&aBuf
)
2430 aBuf
.Assign(gAppData
->version
);
2432 aBuf
.Append(gAppData
->buildID
);
2434 aBuf
.Append(gToolkitBuildID
);
2438 WriteVersion(nsIFile
* aProfileDir
, const nsCString
& aVersion
,
2439 const nsCString
& aOSABI
, nsIFile
* aXULRunnerDir
,
2440 nsIFile
* aAppDir
, bool invalidateCache
)
2442 nsCOMPtr
<nsIFile
> file
;
2443 aProfileDir
->Clone(getter_AddRefs(file
));
2446 file
->AppendNative(FILE_COMPATIBILITY_INFO
);
2448 nsAutoCString platformDir
;
2449 aXULRunnerDir
->GetNativePath(platformDir
);
2451 nsAutoCString appDir
;
2453 aAppDir
->GetNativePath(appDir
);
2455 PRFileDesc
*fd
= nullptr;
2456 file
->OpenNSPRFileDesc(PR_WRONLY
| PR_CREATE_FILE
| PR_TRUNCATE
, 0600, &fd
);
2458 NS_ERROR("could not create output stream");
2462 static const char kHeader
[] = "[Compatibility]" NS_LINEBREAK
2465 PR_Write(fd
, kHeader
, sizeof(kHeader
) - 1);
2466 PR_Write(fd
, aVersion
.get(), aVersion
.Length());
2468 static const char kOSABIHeader
[] = NS_LINEBREAK
"LastOSABI=";
2469 PR_Write(fd
, kOSABIHeader
, sizeof(kOSABIHeader
) - 1);
2470 PR_Write(fd
, aOSABI
.get(), aOSABI
.Length());
2472 static const char kPlatformDirHeader
[] = NS_LINEBREAK
"LastPlatformDir=";
2474 PR_Write(fd
, kPlatformDirHeader
, sizeof(kPlatformDirHeader
) - 1);
2475 PR_Write(fd
, platformDir
.get(), platformDir
.Length());
2477 static const char kAppDirHeader
[] = NS_LINEBREAK
"LastAppDir=";
2479 PR_Write(fd
, kAppDirHeader
, sizeof(kAppDirHeader
) - 1);
2480 PR_Write(fd
, appDir
.get(), appDir
.Length());
2483 static const char kInvalidationHeader
[] = "InvalidateCaches=1" NS_LINEBREAK
;
2484 if (invalidateCache
)
2485 PR_Write(fd
, kInvalidationHeader
, sizeof(kInvalidationHeader
) - 1);
2487 static const char kNL
[] = NS_LINEBREAK
;
2488 PR_Write(fd
, kNL
, sizeof(kNL
) - 1);
2494 * Returns true if the startup cache file was successfully removed.
2495 * Returns false if file->Clone fails at any point (OOM) or if unable
2496 * to remove the startup cache file. Note in particular the return value
2497 * is unaffected by a failure to remove extensions.ini
2500 RemoveComponentRegistries(nsIFile
* aProfileDir
, nsIFile
* aLocalProfileDir
,
2501 bool aRemoveEMFiles
)
2503 nsCOMPtr
<nsIFile
> file
;
2504 aProfileDir
->Clone(getter_AddRefs(file
));
2508 if (aRemoveEMFiles
) {
2509 file
->SetNativeLeafName(NS_LITERAL_CSTRING("extensions.ini"));
2510 file
->Remove(false);
2513 aLocalProfileDir
->Clone(getter_AddRefs(file
));
2517 #if defined(XP_UNIX) || defined(XP_BEOS)
2518 #define PLATFORM_FASL_SUFFIX ".mfasl"
2519 #elif defined(XP_WIN) || defined(XP_OS2)
2520 #define PLATFORM_FASL_SUFFIX ".mfl"
2523 file
->AppendNative(NS_LITERAL_CSTRING("XUL" PLATFORM_FASL_SUFFIX
));
2524 file
->Remove(false);
2526 file
->SetNativeLeafName(NS_LITERAL_CSTRING("XPC" PLATFORM_FASL_SUFFIX
));
2527 file
->Remove(false);
2529 file
->SetNativeLeafName(NS_LITERAL_CSTRING("startupCache"));
2530 nsresult rv
= file
->Remove(true);
2531 return NS_SUCCEEDED(rv
) || rv
== NS_ERROR_FILE_TARGET_DOES_NOT_EXIST
;
2534 // To support application initiated restart via nsIAppStartup.quit, we
2535 // need to save various environment variables, and then restore them
2536 // before re-launching the application.
2538 static struct SavedVar
{
2542 {"XUL_APP_FILE", nullptr}
2545 static void SaveStateForAppInitiatedRestart()
2547 for (size_t i
= 0; i
< ArrayLength(gSavedVars
); ++i
) {
2548 const char *s
= PR_GetEnv(gSavedVars
[i
].name
);
2550 gSavedVars
[i
].value
= PR_smprintf("%s=%s", gSavedVars
[i
].name
, s
);
2554 static void RestoreStateForAppInitiatedRestart()
2556 for (size_t i
= 0; i
< ArrayLength(gSavedVars
); ++i
) {
2557 if (gSavedVars
[i
].value
)
2558 PR_SetEnv(gSavedVars
[i
].value
);
2562 #ifdef MOZ_CRASHREPORTER
2563 // When we first initialize the crash reporter we don't have a profile,
2564 // so we set the minidump path to $TEMP. Once we have a profile,
2565 // we set it to $PROFILE/minidumps, creating the directory
2567 static void MakeOrSetMinidumpPath(nsIFile
* profD
)
2569 nsCOMPtr
<nsIFile
> dumpD
;
2570 profD
->Clone(getter_AddRefs(dumpD
));
2574 //XXX: do some more error checking here
2575 dumpD
->Append(NS_LITERAL_STRING("minidumps"));
2576 dumpD
->Exists(&fileExists
);
2578 dumpD
->Create(nsIFile::DIRECTORY_TYPE
, 0700);
2581 nsAutoString pathStr
;
2582 if(NS_SUCCEEDED(dumpD
->GetPath(pathStr
)))
2583 CrashReporter::SetMinidumpPath(pathStr
);
2588 const nsXREAppData
* gAppData
= nullptr;
2591 // because we use early returns, we use a stack-based helper to un-set the OS2 FP handler
2592 class ScopedFPHandler
{
2594 EXCEPTIONREGISTRATIONRECORD excpreg
;
2597 ScopedFPHandler() { PR_OS2_SetFloatExcpHandler(&excpreg
); }
2598 ~ScopedFPHandler() { PR_OS2_UnsetFloatExcpHandler(&excpreg
); }
2602 #ifdef MOZ_WIDGET_GTK
2604 typedef void (*_g_set_application_name_fn
)(const gchar
*application_name
);
2605 typedef void (*_gtk_window_set_auto_startup_notification_fn
)(gboolean setting
);
2607 static PRFuncPtr
FindFunction(const char* aName
)
2609 PRLibrary
*lib
= nullptr;
2610 PRFuncPtr result
= PR_FindFunctionSymbolAndLibrary(aName
, &lib
);
2611 // Since the library was already loaded, we can safely unload it here.
2613 PR_UnloadLibrary(lib
);
2618 static void MOZ_gdk_display_close(GdkDisplay
*display
)
2620 // XXX wallpaper for bug 417163: don't close the Display if we're using the
2621 // Qt theme because we crash (in Qt code) when using jemalloc.
2622 bool theme_is_qt
= false;
2623 GtkSettings
* settings
=
2624 gtk_settings_get_for_screen(gdk_display_get_default_screen(display
));
2626 g_object_get(settings
, "gtk-theme-name", &theme_name
, nullptr);
2628 theme_is_qt
= strcmp(theme_name
, "Qt") == 0;
2630 NS_WARNING("wallpaper bug 417163 for Qt theme");
2635 // Get a (new) Pango context that holds a reference to the fontmap that
2636 // GTK has been using. gdk_pango_context_get() must be called while GTK
2637 // has a default display.
2638 PangoContext
*pangoContext
= gdk_pango_context_get();
2641 bool buggyCairoShutdown
= cairo_version() < CAIRO_VERSION_ENCODE(1, 4, 0);
2643 if (!buggyCairoShutdown
) {
2644 // We should shut down GDK before we shut down libraries it depends on
2645 // like Pango and cairo. But if cairo shutdown is buggy, we should
2646 // shut down cairo first otherwise it may crash because of dangling
2647 // references to Display objects (see bug 469831).
2649 gdk_display_close(display
);
2653 // This doesn't take a reference.
2654 PangoFontMap
*fontmap
= pango_context_get_font_map(pangoContext
);
2655 // Do some shutdown of the fontmap, which releases the fonts, clearing a
2656 // bunch of circular references from the fontmap through the fonts back to
2657 // itself. The shutdown that this does is much less than what's done by
2658 // the fontmap's finalize, though.
2659 if (PANGO_IS_FC_FONT_MAP(fontmap
))
2660 pango_fc_font_map_shutdown(PANGO_FC_FONT_MAP(fontmap
));
2661 g_object_unref(pangoContext
);
2662 // PangoCairo still holds a reference to the fontmap.
2663 // Now that we have finished with GTK and Pango, we could unref fontmap,
2664 // which would allow us to call FcFini, but removing what is really
2665 // Pango's ref feels a bit evil. Pango-1.22 will have support for
2666 // pango_cairo_font_map_set_default(nullptr), which would release the
2667 // reference on the old fontmap.
2669 // cairo_debug_reset_static_data() is prototyped through cairo.h included
2671 #ifdef cairo_debug_reset_static_data
2672 #error "Looks like we're including Mozilla's cairo instead of system cairo"
2674 cairo_debug_reset_static_data();
2675 #endif // CLEANUP_MEMORY
2677 if (buggyCairoShutdown
) {
2679 gdk_display_close(display
);
2682 #endif // MOZ_WIDGET_GTK2
2685 * NSPR will search for the "nspr_use_zone_allocator" symbol throughout
2686 * the process and use it to determine whether the application defines its own
2687 * memory allocator or not.
2689 * Since most applications (e.g. Firefox and Thunderbird) don't use any special
2690 * allocators and therefore don't define this symbol, NSPR must search the
2691 * entire process, which reduces startup performance.
2693 * By defining the symbol here, we can avoid the wasted lookup and hopefully
2694 * improve startup performance.
2696 NS_VISIBILITY_DEFAULT PRBool nspr_use_zone_allocator
= PR_FALSE
;
2698 #ifdef CAIRO_HAS_DWRITE_FONT
2702 typedef HRESULT (WINAPI
*DWriteCreateFactoryFunc
)(
2703 DWRITE_FACTORY_TYPE factoryType
,
2708 #ifdef DEBUG_DWRITE_STARTUP
2710 #define LOGREGISTRY(msg) LogRegistryEvent(msg)
2712 // for use when monitoring process
2713 static void LogRegistryEvent(const wchar_t *msg
)
2719 wsprintf(buf
, L
" log %s", msg
);
2720 hr
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
, buf
, 0, KEY_READ
, &dummyKey
);
2721 if (SUCCEEDED(hr
)) {
2722 RegCloseKey(dummyKey
);
2727 #define LOGREGISTRY(msg)
2731 static DWORD
InitDwriteBG(LPVOID lpdwThreadParam
)
2733 SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_BEGIN
);
2734 LOGREGISTRY(L
"loading dwrite.dll");
2735 HMODULE dwdll
= LoadLibraryW(L
"dwrite.dll");
2737 DWriteCreateFactoryFunc createDWriteFactory
= (DWriteCreateFactoryFunc
)
2738 GetProcAddress(dwdll
, "DWriteCreateFactory");
2739 if (createDWriteFactory
) {
2740 LOGREGISTRY(L
"creating dwrite factory");
2741 IDWriteFactory
*factory
;
2742 HRESULT hr
= createDWriteFactory(
2743 DWRITE_FACTORY_TYPE_SHARED
,
2744 __uuidof(IDWriteFactory
),
2745 reinterpret_cast<IUnknown
**>(&factory
));
2746 if (SUCCEEDED(hr
)) {
2747 LOGREGISTRY(L
"dwrite factory done");
2749 LOGREGISTRY(L
"freed factory");
2751 LOGREGISTRY(L
"failed to create factory");
2755 SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_END
);
2761 bool fire_glxtest_process();
2764 #include "GeckoProfiler.h"
2766 // Encapsulates startup and shutdown state for XRE_main
2771 mScopedXPCom(nullptr)
2773 , mStartOffline(false)
2774 , mShuttingDown(false)
2775 #ifdef MOZ_ENABLE_XREMOTE
2776 , mDisableRemote(false)
2778 #if defined(MOZ_WIDGET_GTK)
2779 , mGdkDisplay(nullptr)
2788 NS_WARNING("Scoped xpcom should have been deleted!");
2789 delete mScopedXPCom
;
2793 int XRE_main(int argc
, char* argv
[], const nsXREAppData
* aAppData
);
2794 int XRE_mainInit(bool* aExitFlag
);
2795 int XRE_mainStartup(bool* aExitFlag
);
2796 nsresult
XRE_mainRun();
2798 nsCOMPtr
<nsINativeAppSupport
> mNativeApp
;
2799 nsCOMPtr
<nsIToolkitProfileService
> mProfileSvc
;
2800 nsCOMPtr
<nsIFile
> mProfD
;
2801 nsCOMPtr
<nsIFile
> mProfLD
;
2802 nsCOMPtr
<nsIProfileLock
> mProfileLock
;
2803 #ifdef MOZ_ENABLE_XREMOTE
2804 nsCOMPtr
<nsIRemoteService
> mRemoteService
;
2807 ScopedXPCOMStartup
* mScopedXPCom
;
2808 ScopedAppData
* mAppData
;
2809 nsXREDirProvider mDirProvider
;
2810 nsAutoCString mProfileName
;
2811 nsAutoCString mDesktopStartupID
;
2815 #ifdef MOZ_ENABLE_XREMOTE
2816 bool mDisableRemote
;
2819 #if defined(MOZ_WIDGET_GTK)
2820 GdkDisplay
* mGdkDisplay
;
2825 * XRE_mainInit - Initial setup and command line parameter processing.
2826 * Main() will exit early if either return value != 0 or if aExitFlag is
2830 XREMain::XRE_mainInit(bool* aExitFlag
)
2836 StartupTimeline::Record(StartupTimeline::MAIN
);
2842 if (PR_GetEnv("XRE_MAIN_BREAK"))
2847 // bug 639842 - it's very important to fire this process BEFORE we set up
2848 // error handling. indeed, this process is expected to be crashy, and we
2849 // don't want the user to see its crashes. That's the whole reason for
2850 // doing this in a separate process.
2851 if (fire_glxtest_process()) {
2857 SetupErrorHandling(gArgv
[0]);
2859 #ifdef CAIRO_HAS_DWRITE_FONT
2861 // Bug 602792 - when DWriteCreateFactory is called the dwrite client dll
2862 // starts the FntCache service if it isn't already running (it's set
2863 // to manual startup by default in Windows 7 RTM). Subsequent DirectWrite
2864 // calls cause the IDWriteFactory object to communicate with the FntCache
2865 // service with a timeout; if there's no response after the timeout, the
2866 // DirectWrite client library will assume the service isn't around and do
2867 // manual font file I/O on _all_ system fonts. To avoid this, load the
2868 // dwrite library and create a factory as early as possible so that the
2869 // FntCache service is ready by the time it's needed.
2871 if (IsVistaOrLater()) {
2872 CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE
)&InitDwriteBG
,
2873 nullptr, 0, nullptr);
2879 const char *home
= PR_GetEnv("HOME");
2880 if (!home
|| !*home
) {
2881 struct passwd
*pw
= getpwuid(geteuid());
2882 if (!pw
|| !pw
->pw_dir
) {
2883 Output(true, "Could not determine HOME directory");
2886 SaveWordToEnv("HOME", nsDependentCString(pw
->pw_dir
));
2890 #ifdef MOZ_ACCESSIBILITY_ATK
2891 // Reset GTK_MODULES, strip atk-bridge if exists
2892 // Mozilla will load libatk-bridge.so later if necessary
2893 const char* gtkModules
= PR_GetEnv("GTK_MODULES");
2894 if (gtkModules
&& *gtkModules
) {
2895 nsCString
gtkModulesStr(gtkModules
);
2896 gtkModulesStr
.ReplaceSubstring("atk-bridge", "");
2897 char* expr
= PR_smprintf("GTK_MODULES=%s", gtkModulesStr
.get());
2900 // We intentionally leak |expr| here since it is required by PR_SetEnv.
2903 // Suppress atk-bridge init at startup, it works after GNOME 2.24.2
2904 SaveToEnv("NO_AT_BRIDGE=1");
2907 // Check for application.ini overrides
2908 const char* override
= nullptr;
2909 ar
= CheckArg("override", true, &override
);
2910 if (ar
== ARG_BAD
) {
2911 Output(true, "Incorrect number of arguments passed to -override");
2914 else if (ar
== ARG_FOUND
) {
2915 nsCOMPtr
<nsIFile
> overrideLF
;
2916 rv
= XRE_GetFileFromPath(override
, getter_AddRefs(overrideLF
));
2917 if (NS_FAILED(rv
)) {
2918 Output(true, "Error: unrecognized override.ini path.\n");
2922 rv
= XRE_ParseAppData(overrideLF
, mAppData
);
2923 if (NS_FAILED(rv
)) {
2924 Output(true, "Couldn't read override.ini");
2929 // Check sanity and correctness of app data.
2931 if (!mAppData
->name
) {
2932 Output(true, "Error: App:Name not specified in application.ini\n");
2935 if (!mAppData
->buildID
) {
2936 Output(true, "Error: App:BuildID not specified in application.ini\n");
2940 // XXX Originally ScopedLogging was here? Now it's in XRE_main above
2943 if (!mAppData
->xreDirectory
) {
2944 nsCOMPtr
<nsIFile
> lf
;
2945 rv
= XRE_GetBinaryPath(gArgv
[0], getter_AddRefs(lf
));
2949 nsCOMPtr
<nsIFile
> greDir
;
2950 rv
= lf
->GetParent(getter_AddRefs(greDir
));
2954 rv
= CallQueryInterface(greDir
, &mAppData
->xreDirectory
);
2959 if (!mAppData
->directory
) {
2960 NS_IF_ADDREF(mAppData
->directory
= mAppData
->xreDirectory
);
2963 if (mAppData
->size
> offsetof(nsXREAppData
, minVersion
)) {
2964 if (!mAppData
->minVersion
) {
2965 Output(true, "Error: Gecko:MinVersion not specified in application.ini\n");
2969 if (!mAppData
->maxVersion
) {
2970 // If no maxVersion is specified, we assume the app is only compatible
2971 // with the initial preview release. Do not increment this number ever!
2972 SetAllocatedString(mAppData
->maxVersion
, "1.*");
2975 if (mozilla::Version(mAppData
->minVersion
) > gToolkitVersion
||
2976 mozilla::Version(mAppData
->maxVersion
) < gToolkitVersion
) {
2977 Output(true, "Error: Platform version '%s' is not compatible with\n"
2978 "minVersion >= %s\nmaxVersion <= %s\n",
2980 mAppData
->minVersion
, mAppData
->maxVersion
);
2985 rv
= mDirProvider
.Initialize(mAppData
->directory
, mAppData
->xreDirectory
);
2989 #ifdef MOZ_CRASHREPORTER
2990 if (EnvHasValue("MOZ_CRASHREPORTER")) {
2991 mAppData
->flags
|= NS_XRE_ENABLE_CRASH_REPORTER
;
2994 if ((mAppData
->flags
& NS_XRE_ENABLE_CRASH_REPORTER
) &&
2996 CrashReporter::SetExceptionHandler(mAppData
->xreDirectory
))) {
2997 if (mAppData
->crashReporterURL
)
2998 CrashReporter::SetServerURL(nsDependentCString(mAppData
->crashReporterURL
));
3000 // pass some basic info from the app data
3001 if (mAppData
->vendor
)
3002 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Vendor"),
3003 nsDependentCString(mAppData
->vendor
));
3005 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ProductName"),
3006 nsDependentCString(mAppData
->name
));
3008 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ProductID"),
3009 nsDependentCString(mAppData
->ID
));
3010 if (mAppData
->version
)
3011 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Version"),
3012 nsDependentCString(mAppData
->version
));
3013 if (mAppData
->buildID
)
3014 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("BuildID"),
3015 nsDependentCString(mAppData
->buildID
));
3017 nsDependentCString
releaseChannel(NS_STRINGIFY(MOZ_UPDATE_CHANNEL
));
3018 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ReleaseChannel"),
3021 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("CrashAddressLikelyWrong"),
3022 IsSignalHandlingBroken() ? NS_LITERAL_CSTRING("1")
3023 : NS_LITERAL_CSTRING("0"));
3025 CrashReporter::SetRestartArgs(gArgc
, gArgv
);
3027 // annotate other data (user id etc)
3028 nsCOMPtr
<nsIFile
> userAppDataDir
;
3029 if (NS_SUCCEEDED(mDirProvider
.GetUserAppDataDirectory(
3030 getter_AddRefs(userAppDataDir
)))) {
3031 CrashReporter::SetupExtraData(userAppDataDir
,
3032 nsDependentCString(mAppData
->buildID
));
3034 // see if we have a crashreporter-override.ini in the application directory
3035 nsCOMPtr
<nsIFile
> overrideini
;
3037 if (NS_SUCCEEDED(mDirProvider
.GetAppDir()->Clone(getter_AddRefs(overrideini
))) &&
3038 NS_SUCCEEDED(overrideini
->AppendNative(NS_LITERAL_CSTRING("crashreporter-override.ini"))) &&
3039 NS_SUCCEEDED(overrideini
->Exists(&exists
)) &&
3042 nsAutoString overridePathW
;
3043 overrideini
->GetPath(overridePathW
);
3044 NS_ConvertUTF16toUTF8
overridePath(overridePathW
);
3046 nsAutoCString overridePath
;
3047 overrideini
->GetNativePath(overridePath
);
3050 SaveWordToEnv("MOZ_CRASHREPORTER_STRINGS_OVERRIDE", overridePath
);
3057 if (EnvHasValue("MOZ_LAUNCHED_CHILD")) {
3058 // This is needed, on relaunch, to force the OS to use the "Cocoa Dock
3059 // API". Otherwise the call to ReceiveNextEvent() below will make it
3060 // use the "Carbon Dock API". For more info see bmo bug 377166.
3061 EnsureUseCocoaDockAPI();
3063 // When the app relaunches, the original process exits. This causes
3064 // the dock tile to stop bouncing, lose the "running" triangle, and
3065 // if the tile does not permanently reside in the Dock, even disappear.
3066 // This can be confusing to the user, who is expecting the app to launch.
3067 // Calling ReceiveNextEvent without requesting any event is enough to
3068 // cause a dock tile for the child process to appear.
3069 const EventTypeSpec kFakeEventList
[] = { { INT_MAX
, INT_MAX
} };
3071 ::ReceiveNextEvent(GetEventTypeCount(kFakeEventList
), kFakeEventList
,
3072 kEventDurationNoWait
, false, &event
);
3075 if (CheckArg("foreground")) {
3076 // The original process communicates that it was in the foreground by
3077 // adding this argument. This new process, which is taking over for
3078 // the old one, should make itself the active application.
3079 ProcessSerialNumber psn
;
3080 if (::GetCurrentProcess(&psn
) == noErr
)
3081 ::SetFrontProcess(&psn
);
3085 SaveToEnv("MOZ_LAUNCHED_CHILD=");
3087 gRestartArgc
= gArgc
;
3088 gRestartArgv
= (char**) malloc(sizeof(char*) * (gArgc
+ 1 + (override
? 2 : 0)));
3089 if (!gRestartArgv
) {
3094 for (i
= 0; i
< gArgc
; ++i
) {
3095 gRestartArgv
[i
] = gArgv
[i
];
3098 // Add the -override argument back (it is removed automatically be CheckArg) if there is one
3100 gRestartArgv
[gRestartArgc
++] = const_cast<char*>("-override");
3101 gRestartArgv
[gRestartArgc
++] = const_cast<char*>(override
);
3104 gRestartArgv
[gRestartArgc
] = nullptr;
3108 bool StartOS2App(int aArgc
, char **aArgv
);
3109 if (!StartOS2App(gArgc
, gArgv
))
3111 ScopedFPHandler handler
;
3114 if (EnvHasValue("MOZ_SAFE_MODE_RESTART")) {
3116 // unset the env variable
3117 SaveToEnv("MOZ_SAFE_MODE_RESTART=");
3120 ar
= CheckArg("safe-mode", true);
3121 if (ar
== ARG_BAD
) {
3122 PR_fprintf(PR_STDERR
, "Error: argument -safe-mode is invalid when argument -osint is specified\n");
3124 } else if (ar
== ARG_FOUND
) {
3129 // If the shift key is pressed and the ctrl and / or alt keys are not pressed
3130 // during startup start in safe mode. GetKeyState returns a short and the high
3131 // order bit will be 1 if the key is pressed. By masking the returned short
3132 // with 0x8000 the result will be 0 if the key is not pressed and non-zero
3134 if (GetKeyState(VK_SHIFT
) & 0x8000 &&
3135 !(GetKeyState(VK_CONTROL
) & 0x8000) && !(GetKeyState(VK_MENU
) & 0x8000)) {
3141 if (GetCurrentEventKeyModifiers() & optionKey
)
3145 // Handle -no-remote and -new-instance command line arguments. Setup
3146 // the environment to better accommodate other components and various
3147 // restart scenarios.
3148 ar
= CheckArg("no-remote", true);
3149 if (ar
== ARG_BAD
) {
3150 PR_fprintf(PR_STDERR
, "Error: argument -no-remote is invalid when argument -osint is specified\n");
3152 } else if (ar
== ARG_FOUND
) {
3153 SaveToEnv("MOZ_NO_REMOTE=1");
3156 ar
= CheckArg("new-instance", true);
3157 if (ar
== ARG_BAD
) {
3158 PR_fprintf(PR_STDERR
, "Error: argument -new-instance is invalid when argument -osint is specified\n");
3160 } else if (ar
== ARG_FOUND
) {
3161 SaveToEnv("MOZ_NEW_INSTANCE=1");
3164 // Handle -help and -version command line arguments.
3165 // They should return quickly, so we deal with them here.
3166 if (CheckArg("h") || CheckArg("help") || CheckArg("?")) {
3172 if (CheckArg("v") || CheckArg("version")) {
3178 #ifdef NS_TRACE_MALLOC
3179 gArgc
= NS_TraceMallocStartupArgs(gArgc
, gArgv
);
3182 rv
= XRE_InitCommandLine(gArgc
, gArgv
);
3183 NS_ENSURE_SUCCESS(rv
, 1);
3185 // Check for -register, which registers chrome and then exits immediately.
3186 ar
= CheckArg("register", true);
3187 if (ar
== ARG_BAD
) {
3188 PR_fprintf(PR_STDERR
, "Error: argument -register is invalid when argument -osint is specified\n");
3190 } else if (ar
== ARG_FOUND
) {
3191 ScopedXPCOMStartup xpcom
;
3192 rv
= xpcom
.Initialize();
3193 NS_ENSURE_SUCCESS(rv
, 1);
3195 nsCOMPtr
<nsIChromeRegistry
> chromeReg
=
3196 mozilla::services::GetChromeRegistryService();
3197 NS_ENSURE_TRUE(chromeReg
, 1);
3199 chromeReg
->CheckForNewChrome();
3205 if (PR_GetEnv("MOZ_RUN_GTEST")) {
3207 // RunGTest will only be set if we're in xul-unit
3208 if (mozilla::RunGTest
) {
3209 result
= mozilla::RunGTest();
3212 printf("TEST-UNEXPECTED-FAIL | gtest | Not compiled with enable-tests\n");
3221 #ifdef MOZ_CRASHREPORTER
3224 * Uses WMI to read some manufacturer information that may be useful for
3225 * diagnosing hardware-specific crashes. This function is best-effort; failures
3226 * shouldn't burden the caller. COM must be initialized before calling.
3228 static void AnnotateSystemManufacturer()
3230 nsRefPtr
<IWbemLocator
> locator
;
3232 HRESULT hr
= CoCreateInstance(CLSID_WbemLocator
, nullptr, CLSCTX_INPROC_SERVER
,
3233 IID_IWbemLocator
, getter_AddRefs(locator
));
3239 nsRefPtr
<IWbemServices
> services
;
3241 hr
= locator
->ConnectServer(_bstr_t(L
"ROOT\\CIMV2"), nullptr, nullptr, nullptr,
3242 0, nullptr, nullptr, getter_AddRefs(services
));
3248 hr
= CoSetProxyBlanket(services
, RPC_C_AUTHN_WINNT
, RPC_C_AUTHZ_NONE
, nullptr,
3249 RPC_C_AUTHN_LEVEL_CALL
, RPC_C_IMP_LEVEL_IMPERSONATE
,
3250 nullptr, EOAC_NONE
);
3256 nsRefPtr
<IEnumWbemClassObject
> enumerator
;
3258 hr
= services
->ExecQuery(_bstr_t(L
"WQL"), _bstr_t(L
"SELECT * FROM Win32_BIOS"),
3259 WBEM_FLAG_FORWARD_ONLY
| WBEM_FLAG_RETURN_IMMEDIATELY
,
3260 nullptr, getter_AddRefs(enumerator
));
3262 if (FAILED(hr
) || !enumerator
) {
3266 nsRefPtr
<IWbemClassObject
> classObject
;
3269 hr
= enumerator
->Next(WBEM_INFINITE
, 1, getter_AddRefs(classObject
), &results
);
3271 if (FAILED(hr
) || results
== 0) {
3276 VariantInit(&value
);
3278 hr
= classObject
->Get(L
"Manufacturer", 0, &value
, 0, 0);
3280 if (SUCCEEDED(hr
) && V_VT(&value
) == VT_BSTR
) {
3281 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("BIOS_Manufacturer"),
3282 NS_ConvertUTF16toUTF8(V_BSTR(&value
)));
3285 VariantClear(&value
);
3288 static void PR_CALLBACK
AnnotateSystemManufacturer_ThreadStart(void*)
3290 HRESULT hr
= CoInitialize(nullptr);
3296 AnnotateSystemManufacturer();
3304 ShutdownChecksMode gShutdownChecks
= SCM_NOTHING
;
3307 static void SetShutdownChecks() {
3308 // Set default first. On debug builds we crash. On nightly and local
3309 // builds we record. Nightlies will then send the info via telemetry,
3310 // but it is usefull to have the data in about:telemetry in local builds
3314 gShutdownChecks
= SCM_CRASH
;
3316 const char* releaseChannel
= NS_STRINGIFY(MOZ_UPDATE_CHANNEL
);
3317 if (strcmp(releaseChannel
, "nightly") == 0 ||
3318 strcmp(releaseChannel
, "default") == 0) {
3319 gShutdownChecks
= SCM_RECORD
;
3321 gShutdownChecks
= SCM_NOTHING
;
3325 // We let an environment variable override the default so that addons
3326 // authors can use it for debugging shutdown with released firefox versions.
3327 const char* mozShutdownChecksEnv
= PR_GetEnv("MOZ_SHUTDOWN_CHECKS");
3328 if (mozShutdownChecksEnv
) {
3329 if (strcmp(mozShutdownChecksEnv
, "crash") == 0) {
3330 gShutdownChecks
= SCM_CRASH
;
3331 } else if (strcmp(mozShutdownChecksEnv
, "record") == 0) {
3332 gShutdownChecks
= SCM_RECORD
;
3333 } else if (strcmp(mozShutdownChecksEnv
, "nothing") == 0) {
3334 gShutdownChecks
= SCM_NOTHING
;
3341 * XRE_mainStartup - Initializes the profile and various other services.
3342 * Main() will exit early if either return value != 0 or if aExitFlag is
3346 XREMain::XRE_mainStartup(bool* aExitFlag
)
3354 SetShutdownChecks();
3356 #if defined(MOZ_WIDGET_GTK) || defined(MOZ_ENABLE_XREMOTE)
3357 // Stash DESKTOP_STARTUP_ID in malloc'ed memory because gtk_init will clear it.
3358 #define HAVE_DESKTOP_STARTUP_ID
3359 const char* desktopStartupIDEnv
= PR_GetEnv("DESKTOP_STARTUP_ID");
3360 if (desktopStartupIDEnv
) {
3361 mDesktopStartupID
.Assign(desktopStartupIDEnv
);
3365 #if defined(MOZ_WIDGET_QT)
3366 nsQAppInstance::AddRef(gArgc
, gArgv
, true);
3368 QStringList nonQtArguments
= qApp
->arguments();
3370 gQtOnlyArgv
= (char**) malloc(sizeof(char*)
3371 * (gRestartArgc
- nonQtArguments
.size() + 2));
3374 gQtOnlyArgv
[0] = gRestartArgv
[0];
3376 for (int i
= 1; i
< gRestartArgc
; ++i
) {
3377 if (!nonQtArguments
.contains(gRestartArgv
[i
])) {
3378 // copy arguments used by Qt for later
3379 gQtOnlyArgv
[gQtOnlyArgc
++] = gRestartArgv
[i
];
3382 gQtOnlyArgv
[gQtOnlyArgc
] = nullptr;
3384 #if defined(MOZ_WIDGET_GTK)
3385 // setup for private colormap. Ideally we'd like to do this
3386 // in nsAppShell::Create, but we need to get in before gtk
3387 // has been initialized to make sure everything is running
3389 #if (MOZ_WIDGET_GTK == 2)
3390 if (CheckArg("install"))
3391 gdk_rgb_set_install(TRUE
);
3394 // Set program name to the one defined in application.ini.
3396 nsAutoCString
program(gAppData
->name
);
3397 ToLowerCase(program
);
3398 g_set_prgname(program
.get());
3401 // Initialize GTK here for splash.
3403 // Open the display ourselves instead of using gtk_init, so that we can
3404 // close it without fear that one day gtk might clean up the display it
3406 if (!gtk_parse_args(&gArgc
, &gArgv
))
3409 // display_name is owned by gdk.
3410 const char *display_name
= gdk_get_display_arg_name();
3412 SaveWordToEnv("DISPLAY", nsDependentCString(display_name
));
3414 display_name
= PR_GetEnv("DISPLAY");
3415 if (!display_name
) {
3416 PR_fprintf(PR_STDERR
, "Error: no display specified\n");
3420 #endif /* MOZ_WIDGET_GTK2 */
3422 #ifdef MOZ_ENABLE_XREMOTE
3423 // handle -remote now that xpcom is fired up
3426 char *e
= PR_GetEnv("MOZ_NO_REMOTE");
3427 mDisableRemote
= (e
&& *e
);
3428 if (mDisableRemote
) {
3431 e
= PR_GetEnv("MOZ_NEW_INSTANCE");
3432 newInstance
= (e
&& *e
);
3436 const char* xremotearg
;
3437 ArgResult ar
= CheckArg("remote", true, &xremotearg
);
3438 if (ar
== ARG_BAD
) {
3439 PR_fprintf(PR_STDERR
, "Error: -remote requires an argument\n");
3442 const char* desktopStartupIDPtr
=
3443 mDesktopStartupID
.IsEmpty() ? nullptr : mDesktopStartupID
.get();
3446 return HandleRemoteArgument(xremotearg
, desktopStartupIDPtr
);
3450 // Try to remote the entire command line. If this fails, start up normally.
3451 RemoteResult rr
= RemoteCommandLine(desktopStartupIDPtr
);
3452 if (rr
== REMOTE_FOUND
) {
3456 else if (rr
== REMOTE_ARG_BAD
)
3461 // Init X11 in thread-safe mode. Must be called prior to the first call to XOpenDisplay
3462 // (called inside gdk_display_open). This is a requirement for off main tread compositing.
3463 // This is done only on X11 platforms if the environment variable MOZ_USE_OMTC is set so
3464 // as to avoid overhead when omtc is not used.
3466 // On nightly builds, we call this by default to enable OMTC for Electrolysis testing. On
3467 // aurora, beta, and release builds, there is a small tpaint regression from enabling this
3468 // call, so it sits behind an environment variable.
3470 // An environment variable is used instead of a pref on X11 platforms because we start having
3471 // access to prefs long after the first call to XOpenDisplay which is hard to change due to
3472 // interdependencies in the initialization.
3473 # ifndef NIGHTLY_BUILD
3474 if (PR_GetEnv("MOZ_USE_OMTC") ||
3475 PR_GetEnv("MOZ_OMTC_ENABLED"))
3481 #if defined(MOZ_WIDGET_GTK)
3482 mGdkDisplay
= gdk_display_open(display_name
);
3484 PR_fprintf(PR_STDERR
, "Error: cannot open display: %s\n", display_name
);
3487 gdk_display_manager_set_default_display (gdk_display_manager_get(),
3490 // g_set_application_name () is only defined in glib2.2 and higher.
3491 _g_set_application_name_fn _g_set_application_name
=
3492 (_g_set_application_name_fn
)FindFunction("g_set_application_name");
3493 if (_g_set_application_name
) {
3494 _g_set_application_name(mAppData
->name
);
3496 _gtk_window_set_auto_startup_notification_fn _gtk_window_set_auto_startup_notification
=
3497 (_gtk_window_set_auto_startup_notification_fn
)FindFunction("gtk_window_set_auto_startup_notification");
3498 if (_gtk_window_set_auto_startup_notification
) {
3499 _gtk_window_set_auto_startup_notification(false);
3502 #if (MOZ_WIDGET_GTK == 2)
3503 gtk_widget_set_default_colormap(gdk_rgb_get_colormap());
3504 #endif /* (MOZ_WIDGET_GTK == 2) */
3505 #endif /* defined(MOZ_WIDGET_GTK) */
3507 // Do this after initializing GDK, or GDK will install its own handler.
3508 InstallX11ErrorHandler();
3511 // Call the code to install our handler
3513 setupProfilingStuff();
3516 rv
= NS_CreateNativeAppSupport(getter_AddRefs(mNativeApp
));
3520 bool canRun
= false;
3521 rv
= mNativeApp
->Start(&canRun
);
3522 if (NS_FAILED(rv
) || !canRun
) {
3526 #if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK)
3527 // DESKTOP_STARTUP_ID is cleared now,
3528 // we recover it in case we need a restart.
3529 if (!mDesktopStartupID
.IsEmpty()) {
3530 nsAutoCString desktopStartupEnv
;
3531 desktopStartupEnv
.AssignLiteral("DESKTOP_STARTUP_ID=");
3532 desktopStartupEnv
.Append(mDesktopStartupID
);
3533 // Leak it with extreme prejudice!
3534 PR_SetEnv(ToNewCString(desktopStartupEnv
));
3538 #if defined(USE_MOZ_UPDATER)
3539 // Check for and process any available updates
3540 nsCOMPtr
<nsIFile
> updRoot
;
3542 rv
= mDirProvider
.GetFile(XRE_UPDATE_ROOT_DIR
, &persistent
,
3543 getter_AddRefs(updRoot
));
3544 // XRE_UPDATE_ROOT_DIR may fail. Fallback to appDir if failed
3546 updRoot
= mDirProvider
.GetAppDir();
3548 // If the MOZ_PROCESS_UPDATES environment variable already exists, then
3549 // we are being called from the callback application.
3550 if (EnvHasValue("MOZ_PROCESS_UPDATES")) {
3551 // If the caller has asked us to log our arguments, do so. This is used
3552 // to make sure that the maintenance service successfully launches the
3553 // callback application.
3554 const char *logFile
= nullptr;
3555 if (ARG_FOUND
== CheckArg("dump-args", false, &logFile
)) {
3556 FILE* logFP
= fopen(logFile
, "wb");
3558 for (int i
= 1; i
< gRestartArgc
; ++i
) {
3559 fprintf(logFP
, "%s\n", gRestartArgv
[i
]);
3568 // Support for processing an update and exiting. The MOZ_PROCESS_UPDATES
3569 // environment variable will be part of the updater's environment and the
3570 // application that is relaunched by the updater. When the application is
3571 // relaunched by the updater it will be removed below and the application
3573 if (CheckArg("process-updates")) {
3574 SaveToEnv("MOZ_PROCESS_UPDATES=1");
3576 nsCOMPtr
<nsIFile
> exeFile
, exeDir
;
3577 rv
= mDirProvider
.GetFile(XRE_EXECUTABLE_FILE
, &persistent
,
3578 getter_AddRefs(exeFile
));
3579 NS_ENSURE_SUCCESS(rv
, 1);
3580 rv
= exeFile
->GetParent(getter_AddRefs(exeDir
));
3581 NS_ENSURE_SUCCESS(rv
, 1);
3582 ProcessUpdates(mDirProvider
.GetGREDir(),
3588 if (EnvHasValue("MOZ_PROCESS_UPDATES")) {
3589 SaveToEnv("MOZ_PROCESS_UPDATES=");
3595 rv
= NS_NewToolkitProfileService(getter_AddRefs(mProfileSvc
));
3596 if (rv
== NS_ERROR_FILE_ACCESS_DENIED
) {
3597 PR_fprintf(PR_STDERR
, "Error: Access was denied while trying to open files in " \
3598 "your profile directory.\n");
3600 if (NS_FAILED(rv
)) {
3601 // We failed to choose or create profile - notify user and quit
3602 ProfileMissingDialog(mNativeApp
);
3606 rv
= SelectProfile(getter_AddRefs(mProfileLock
), mProfileSvc
, mNativeApp
, &mStartOffline
,
3608 if (rv
== NS_ERROR_LAUNCHED_CHILD_PROCESS
||
3609 rv
== NS_ERROR_ABORT
) {
3614 if (NS_FAILED(rv
)) {
3615 // We failed to choose or create profile - notify user and quit
3616 ProfileMissingDialog(mNativeApp
);
3619 gProfileLock
= mProfileLock
;
3621 rv
= mProfileLock
->GetDirectory(getter_AddRefs(mProfD
));
3622 NS_ENSURE_SUCCESS(rv
, 1);
3624 rv
= mProfileLock
->GetLocalDirectory(getter_AddRefs(mProfLD
));
3625 NS_ENSURE_SUCCESS(rv
, 1);
3627 rv
= mDirProvider
.SetProfile(mProfD
, mProfLD
);
3628 NS_ENSURE_SUCCESS(rv
, 1);
3630 //////////////////////// NOW WE HAVE A PROFILE ////////////////////////
3632 #ifdef MOZ_CRASHREPORTER
3633 if (mAppData
->flags
& NS_XRE_ENABLE_CRASH_REPORTER
)
3634 MakeOrSetMinidumpPath(mProfD
);
3637 nsAutoCString version
;
3638 BuildVersion(version
);
3640 #ifdef TARGET_OS_ABI
3641 NS_NAMED_LITERAL_CSTRING(osABI
, TARGET_OS_ABI
);
3643 // No TARGET_XPCOM_ABI, but at least the OS is known
3644 NS_NAMED_LITERAL_CSTRING(osABI
, OS_TARGET
"_UNKNOWN");
3647 // Check for version compatibility with the last version of the app this
3648 // profile was started with. The format of the version stamp is defined
3649 // by the BuildVersion function.
3650 // Also check to see if something has happened to invalidate our
3651 // fastload caches, like an extension upgrade or installation.
3653 // If we see .purgecaches, that means someone did a make.
3654 // Re-register components to catch potential changes.
3655 nsCOMPtr
<nsIFile
> flagFile
;
3657 rv
= NS_ERROR_FILE_NOT_FOUND
;
3658 nsCOMPtr
<nsIFile
> fFlagFile
;
3659 if (mAppData
->directory
) {
3660 rv
= mAppData
->directory
->Clone(getter_AddRefs(fFlagFile
));
3662 flagFile
= do_QueryInterface(fFlagFile
);
3664 flagFile
->AppendNative(FILE_INVALIDATE_CACHES
);
3668 bool versionOK
= CheckCompatibility(mProfD
, version
, osABI
,
3669 mDirProvider
.GetGREDir(),
3670 mAppData
->directory
, flagFile
,
3672 if (CheckArg("purgecaches")) {
3675 if (PR_GetEnv("MOZ_PURGE_CACHES")) {
3679 // Every time a profile is loaded by a build with a different version,
3680 // it updates the compatibility.ini file saying what version last wrote
3681 // the fastload caches. On subsequent launches if the version matches,
3682 // there is no need for re-registration. If the user loads the same
3683 // profile in different builds the component registry must be
3684 // re-generated to prevent mysterious component loading failures.
3686 bool startupCacheValid
= true;
3688 startupCacheValid
= RemoveComponentRegistries(mProfD
, mProfLD
, false);
3689 WriteVersion(mProfD
, NS_LITERAL_CSTRING("Safe Mode"), osABI
,
3690 mDirProvider
.GetGREDir(), mAppData
->directory
, !startupCacheValid
);
3692 else if (versionOK
) {
3694 // Remove caches, forcing component re-registration.
3695 // The new list of additional components directories is derived from
3696 // information in "extensions.ini".
3697 startupCacheValid
= RemoveComponentRegistries(mProfD
, mProfLD
, false);
3699 // Rewrite compatibility.ini to remove the flag
3700 WriteVersion(mProfD
, version
, osABI
,
3701 mDirProvider
.GetGREDir(), mAppData
->directory
, !startupCacheValid
);
3703 // Nothing need be done for the normal startup case.
3706 // Remove caches, forcing component re-registration
3707 // with the default set of components (this disables any potentially
3708 // troublesome incompatible XPCOM components).
3709 startupCacheValid
= RemoveComponentRegistries(mProfD
, mProfLD
, true);
3711 // Write out version
3712 WriteVersion(mProfD
, version
, osABI
,
3713 mDirProvider
.GetGREDir(), mAppData
->directory
, !startupCacheValid
);
3716 if (!startupCacheValid
)
3717 StartupCache::IgnoreDiskCache();
3720 flagFile
->Remove(true);
3727 * XRE_mainRun - Command line startup, profile migration, and
3728 * the calling of appStartup->Run().
3731 XREMain::XRE_mainRun()
3733 nsresult rv
= NS_OK
;
3734 NS_ASSERTION(mScopedXPCom
, "Scoped xpcom not initialized.");
3736 #ifdef NS_FUNCTION_TIMER
3737 // initialize some common services, so we don't pay the cost for these at odd times later on;
3738 // SetWindowCreator -> ChromeRegistry -> IOService -> SocketTransportService -> (nspr wspm init), Prefs
3740 nsCOMPtr
<nsISupports
> comp
;
3742 comp
= do_GetService("@mozilla.org/preferences-service;1");
3744 comp
= do_GetService("@mozilla.org/network/socket-transport-service;1");
3746 comp
= do_GetService("@mozilla.org/network/dns-service;1");
3748 comp
= do_GetService("@mozilla.org/network/io-service;1");
3750 comp
= do_GetService("@mozilla.org/chrome/chrome-registry;1");
3752 comp
= do_GetService("@mozilla.org/focus-event-suppressor-service;1");
3756 rv
= mScopedXPCom
->SetWindowCreator(mNativeApp
);
3757 NS_ENSURE_SUCCESS(rv
, NS_ERROR_FAILURE
);
3759 #ifdef MOZ_CRASHREPORTER
3760 // tell the crash reporter to also send the release channel
3761 nsCOMPtr
<nsIPrefService
> prefs
= do_GetService("@mozilla.org/preferences-service;1", &rv
);
3762 if (NS_SUCCEEDED(rv
)) {
3763 nsCOMPtr
<nsIPrefBranch
> defaultPrefBranch
;
3764 rv
= prefs
->GetDefaultBranch(nullptr, getter_AddRefs(defaultPrefBranch
));
3766 if (NS_SUCCEEDED(rv
)) {
3767 nsXPIDLCString sval
;
3768 rv
= defaultPrefBranch
->GetCharPref("app.update.channel", getter_Copies(sval
));
3769 if (NS_SUCCEEDED(rv
)) {
3770 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ReleaseChannel"),
3775 // Needs to be set after xpcom initialization.
3776 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("FramePoisonBase"),
3777 nsPrintfCString("%.16llx", uint64_t(gMozillaPoisonBase
)));
3778 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("FramePoisonSize"),
3779 nsPrintfCString("%lu", uint32_t(gMozillaPoisonSize
)));
3782 PR_CreateThread(PR_USER_THREAD
, AnnotateSystemManufacturer_ThreadStart
, 0,
3783 PR_PRIORITY_LOW
, PR_GLOBAL_THREAD
, PR_UNJOINABLE_THREAD
, 0);
3788 if (mStartOffline
) {
3789 nsCOMPtr
<nsIIOService2
> io (do_GetService("@mozilla.org/network/io-service;1"));
3790 NS_ENSURE_TRUE(io
, NS_ERROR_FAILURE
);
3791 io
->SetManageOfflineStatus(false);
3792 io
->SetOffline(true);
3796 nsCOMPtr
<nsIObserver
> startupNotifier
3797 (do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID
, &rv
));
3798 NS_ENSURE_SUCCESS(rv
, NS_ERROR_FAILURE
);
3800 startupNotifier
->Observe(nullptr, APPSTARTUP_TOPIC
, nullptr);
3803 nsCOMPtr
<nsIAppStartup
> appStartup
3804 (do_GetService(NS_APPSTARTUP_CONTRACTID
));
3805 NS_ENSURE_TRUE(appStartup
, NS_ERROR_FAILURE
);
3808 nsCOMPtr
<nsIFile
> file
;
3809 mDirProvider
.GetAppDir()->Clone(getter_AddRefs(file
));
3810 file
->AppendNative(NS_LITERAL_CSTRING("override.ini"));
3812 nsresult rv
= parser
.Init(file
);
3813 if (NS_SUCCEEDED(rv
)) {
3815 rv
= parser
.GetString("XRE", "EnableProfileMigrator", buf
);
3816 if (NS_SUCCEEDED(rv
)) {
3817 if (buf
[0] == '0' || buf
[0] == 'f' || buf
[0] == 'F') {
3818 gDoMigration
= false;
3825 nsCOMPtr
<nsIToolkitProfile
> selectedProfile
;
3826 if (gDoProfileReset
) {
3827 // At this point we can be sure that profile reset is happening on the default profile.
3828 rv
= mProfileSvc
->GetSelectedProfile(getter_AddRefs(selectedProfile
));
3829 if (NS_FAILED(rv
)) {
3830 gDoProfileReset
= false;
3831 return NS_ERROR_FAILURE
;
3835 // Profile Migration
3836 if (mAppData
->flags
& NS_XRE_ENABLE_PROFILE_MIGRATOR
&& gDoMigration
) {
3837 gDoMigration
= false;
3838 nsCOMPtr
<nsIProfileMigrator
> pm(do_CreateInstance(NS_PROFILEMIGRATOR_CONTRACTID
));
3841 if (gDoProfileReset
) {
3842 // Automatically migrate from the current application if we just
3843 // reset the profile.
3844 aKey
= MOZ_APP_NAME
;
3846 pm
->Migrate(&mDirProvider
, aKey
);
3850 if (gDoProfileReset
) {
3851 nsresult backupCreated
= ProfileResetCleanup(selectedProfile
);
3852 if (NS_FAILED(backupCreated
)) NS_WARNING("Could not cleanup the profile that was reset");
3854 // Set the new profile as the default after we're done cleaning up the old default.
3855 rv
= SetCurrentProfileAsDefault(mProfileSvc
, mProfD
);
3856 if (NS_FAILED(rv
)) NS_WARNING("Could not set current profile as the default");
3860 mDirProvider
.DoStartup();
3862 #ifdef MOZ_CRASHREPORTER
3863 nsCString userAgentLocale
;
3864 if (NS_SUCCEEDED(Preferences::GetCString("general.useragent.locale", &userAgentLocale
))) {
3865 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("useragent_locale"), userAgentLocale
);
3869 appStartup
->GetShuttingDown(&mShuttingDown
);
3871 nsCOMPtr
<nsICommandLineRunner
> cmdLine
;
3873 nsCOMPtr
<nsIFile
> workingDir
;
3874 rv
= NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR
, getter_AddRefs(workingDir
));
3875 NS_ENSURE_SUCCESS(rv
, NS_ERROR_FAILURE
);
3877 if (!mShuttingDown
) {
3878 cmdLine
= do_CreateInstance("@mozilla.org/toolkit/command-line;1");
3879 NS_ENSURE_TRUE(cmdLine
, NS_ERROR_FAILURE
);
3881 rv
= cmdLine
->Init(gArgc
, gArgv
, workingDir
,
3882 nsICommandLine::STATE_INITIAL_LAUNCH
);
3883 NS_ENSURE_SUCCESS(rv
, NS_ERROR_FAILURE
);
3885 /* Special-case services that need early access to the command
3887 nsCOMPtr
<nsIObserverService
> obsService
=
3888 mozilla::services::GetObserverService();
3890 obsService
->NotifyObservers(cmdLine
, "command-line-startup", nullptr);
3894 SaveStateForAppInitiatedRestart();
3896 // clear out any environment variables which may have been set
3897 // during the relaunch process now that we know we won't be relaunching.
3898 SaveToEnv("XRE_PROFILE_PATH=");
3899 SaveToEnv("XRE_PROFILE_LOCAL_PATH=");
3900 SaveToEnv("XRE_PROFILE_NAME=");
3901 SaveToEnv("XRE_START_OFFLINE=");
3902 SaveToEnv("NO_EM_RESTART=");
3903 SaveToEnv("XUL_APP_FILE=");
3904 SaveToEnv("XRE_BINARY_PATH=");
3906 if (!mShuttingDown
) {
3907 rv
= appStartup
->CreateHiddenWindow();
3908 NS_ENSURE_SUCCESS(rv
, NS_ERROR_FAILURE
);
3910 #if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK)
3911 nsGTKToolkit
* toolkit
= nsGTKToolkit::GetToolkit();
3912 if (toolkit
&& !mDesktopStartupID
.IsEmpty()) {
3913 toolkit
->SetDesktopStartupID(mDesktopStartupID
);
3915 // Clear the environment variable so it won't be inherited by
3916 // child processes and confuse things.
3917 g_unsetenv ("DESKTOP_STARTUP_ID");
3921 // Set up ability to respond to system (Apple) events. This must be
3922 // done before setting up the command line service.
3923 SetupMacApplicationDelegate();
3925 // we re-initialize the command-line service and do appleevents munging
3926 // after we are sure that we're not restarting
3927 cmdLine
= do_CreateInstance("@mozilla.org/toolkit/command-line;1");
3928 NS_ENSURE_TRUE(cmdLine
, NS_ERROR_FAILURE
);
3930 CommandLineServiceMac::SetupMacCommandLine(gArgc
, gArgv
, false);
3932 rv
= cmdLine
->Init(gArgc
, gArgv
,
3933 workingDir
, nsICommandLine::STATE_INITIAL_LAUNCH
);
3934 NS_ENSURE_SUCCESS(rv
, NS_ERROR_FAILURE
);
3937 nsCOMPtr
<nsIObserverService
> obsService
=
3938 mozilla::services::GetObserverService();
3940 obsService
->NotifyObservers(nullptr, "final-ui-startup", nullptr);
3942 (void)appStartup
->DoneStartingUp();
3943 appStartup
->GetShuttingDown(&mShuttingDown
);
3946 if (!mShuttingDown
) {
3947 rv
= cmdLine
->Run();
3948 NS_ENSURE_SUCCESS_LOG(rv
, NS_ERROR_FAILURE
);
3950 appStartup
->GetShuttingDown(&mShuttingDown
);
3953 if (!mShuttingDown
) {
3954 #ifdef MOZ_ENABLE_XREMOTE
3955 // if we have X remote support, start listening for requests on the
3957 if (!mDisableRemote
)
3958 mRemoteService
= do_GetService("@mozilla.org/toolkit/remote-service;1");
3960 mRemoteService
->Startup(mAppData
->name
, mProfileName
.get());
3961 #endif /* MOZ_ENABLE_XREMOTE */
3963 mNativeApp
->Enable();
3966 #ifdef MOZ_INSTRUMENT_EVENT_LOOP
3967 if (PR_GetEnv("MOZ_INSTRUMENT_EVENT_LOOP") || profiler_is_active()) {
3968 bool logToConsole
= !!PR_GetEnv("MOZ_INSTRUMENT_EVENT_LOOP");
3969 mozilla::InitEventTracing(logToConsole
);
3971 #endif /* MOZ_INSTRUMENT_EVENT_LOOP */
3974 rv
= appStartup
->Run();
3975 if (NS_FAILED(rv
)) {
3976 NS_ERROR("failed to run appstartup");
3977 gLogConsoleErrors
= true;
3985 * XRE_main - A class based main entry point used by most platforms.
3988 XREMain::XRE_main(int argc
, char* argv
[], const nsXREAppData
* aAppData
)
3991 GeckoProfilerInitRAII
profilerGuard(&aLocal
);
3992 PROFILER_LABEL("Startup", "XRE_Main");
3994 nsresult rv
= NS_OK
;
3999 NS_ENSURE_TRUE(aAppData
, 2);
4001 mAppData
= new ScopedAppData(aAppData
);
4004 // used throughout this file
4005 gAppData
= mAppData
;
4009 #if defined(MOZ_WIDGET_GTK)
4010 #if defined(MOZ_MEMORY) || defined(__FreeBSD__) \
4011 || defined(__NetBSD__) && __NetBSD_Version__ >= 500000000
4012 // Disable the slice allocator, since jemalloc already uses similar layout
4013 // algorithms, and using a sub-allocator tends to increase fragmentation.
4014 // This must be done before g_thread_init() is called.
4015 g_slice_set_config(G_SLICE_CONFIG_ALWAYS_MALLOC
, 1);
4017 g_thread_init(nullptr);
4022 int result
= XRE_mainInit(&exit
);
4023 if (result
!= 0 || exit
)
4027 result
= XRE_mainStartup(&exit
);
4028 if (result
!= 0 || exit
)
4031 bool appInitiatedRestart
= false;
4033 // Start the real application
4034 mScopedXPCom
= new ScopedXPCOMStartup();
4038 rv
= mScopedXPCom
->Initialize();
4039 NS_ENSURE_SUCCESS(rv
, 1);
4044 #ifdef MOZ_INSTRUMENT_EVENT_LOOP
4045 mozilla::ShutdownEventTracing();
4048 // Check for an application initiated restart. This is one that
4049 // corresponds to nsIAppStartup.quit(eRestart)
4050 if (rv
== NS_SUCCESS_RESTART_APP
) {
4051 appInitiatedRestart
= true;
4053 // We have an application restart don't do any shutdown checks here
4054 // In particular we don't want to poison IO for checking late-writes.
4055 gShutdownChecks
= SCM_NOTHING
;
4058 if (!mShuttingDown
) {
4059 #ifdef MOZ_ENABLE_XREMOTE
4060 // shut down the x remote proxy window
4061 if (mRemoteService
) {
4062 mRemoteService
->Shutdown();
4064 #endif /* MOZ_ENABLE_XREMOTE */
4067 delete mScopedXPCom
;
4068 mScopedXPCom
= nullptr;
4070 // unlock the profile after ScopedXPCOMStartup object (xpcom)
4071 // has gone out of scope. see bug #386739 for more details
4072 mProfileLock
->Unlock();
4073 gProfileLock
= nullptr;
4075 #if defined(MOZ_WIDGET_QT)
4076 nsQAppInstance::Release();
4079 // Restart the app after XPCOM has been shut down cleanly.
4080 if (appInitiatedRestart
) {
4081 RestoreStateForAppInitiatedRestart();
4083 // Ensure that these environment variables are set:
4084 SaveFileToEnvIfUnset("XRE_PROFILE_PATH", mProfD
);
4085 SaveFileToEnvIfUnset("XRE_PROFILE_LOCAL_PATH", mProfLD
);
4086 SaveWordToEnvIfUnset("XRE_PROFILE_NAME", mProfileName
);
4088 #ifdef MOZ_WIDGET_GTK
4089 MOZ_gdk_display_close(mGdkDisplay
);
4092 rv
= LaunchChild(mNativeApp
, true);
4094 #ifdef MOZ_CRASHREPORTER
4095 if (mAppData
->flags
& NS_XRE_ENABLE_CRASH_REPORTER
)
4096 CrashReporter::UnsetExceptionHandler();
4098 return rv
== NS_ERROR_LAUNCHED_CHILD_PROCESS
? 0 : 1;
4101 #ifdef MOZ_WIDGET_GTK
4102 // gdk_display_close also calls gdk_display_manager_set_default_display
4103 // appropriately when necessary.
4104 MOZ_gdk_display_close(mGdkDisplay
);
4107 #ifdef MOZ_CRASHREPORTER
4108 if (mAppData
->flags
& NS_XRE_ENABLE_CRASH_REPORTER
)
4109 CrashReporter::UnsetExceptionHandler();
4112 XRE_DeinitCommandLine();
4114 return NS_FAILED(rv
) ? 1 : 0;
4117 #if defined(MOZ_METRO) && defined(XP_WIN)
4118 extern bool XRE_MetroCoreApplicationRun();
4119 static XREMain
* xreMainPtr
;
4121 // must be called by the thread we want as the main thread
4123 XRE_metroStartup(bool runXREMain
)
4128 if (xreMainPtr
->XRE_mainStartup(&exit
) != 0 || exit
)
4129 return NS_ERROR_FAILURE
;
4131 // Start the real application
4132 xreMainPtr
->mScopedXPCom
= new ScopedXPCOMStartup();
4133 if (!xreMainPtr
->mScopedXPCom
)
4134 return NS_ERROR_FAILURE
;
4136 rv
= xreMainPtr
->mScopedXPCom
->Initialize();
4137 NS_ENSURE_SUCCESS(rv
, rv
);
4140 rv
= xreMainPtr
->XRE_mainRun();
4141 NS_ENSURE_SUCCESS(rv
, rv
);
4149 delete xreMainPtr
->mScopedXPCom
;
4150 xreMainPtr
->mScopedXPCom
= nullptr;
4152 #ifdef MOZ_INSTRUMENT_EVENT_LOOP
4153 mozilla::ShutdownEventTracing();
4156 // unlock the profile after ScopedXPCOMStartup object (xpcom)
4157 // has gone out of scope. see bug #386739 for more details
4158 xreMainPtr
->mProfileLock
->Unlock();
4159 gProfileLock
= nullptr;
4161 #ifdef MOZ_CRASHREPORTER
4162 if (xreMainPtr
->mAppData
->flags
& NS_XRE_ENABLE_CRASH_REPORTER
)
4163 CrashReporter::UnsetExceptionHandler();
4166 XRE_DeinitCommandLine();
4169 class WinRTInitWrapper
4172 WinRTInitWrapper() {
4173 mResult
= ::RoInitialize(RO_INIT_MULTITHREADED
);
4175 ~WinRTInitWrapper() {
4176 if (SUCCEEDED(mResult
)) {
4184 XRE_mainMetro(int argc
, char* argv
[], const nsXREAppData
* aAppData
)
4187 GeckoProfilerInitRAII
profilerGuard(&aLocal
);
4188 PROFILER_LABEL("Startup", "XRE_Main");
4190 nsresult rv
= NS_OK
;
4192 xreMainPtr
= new XREMain();
4197 // Inits Winrt and COM underneath it.
4198 WinRTInitWrapper wrap
;
4203 NS_ENSURE_TRUE(aAppData
, 2);
4205 xreMainPtr
->mAppData
= new ScopedAppData(aAppData
);
4206 if (!xreMainPtr
->mAppData
)
4208 // used throughout this file
4209 gAppData
= xreMainPtr
->mAppData
;
4215 if (xreMainPtr
->XRE_mainInit(&exit
) != 0 || exit
)
4218 // Located in widget, will call back into XRE_metroStartup and
4219 // XRE_metroShutdown above.
4220 if (!XRE_MetroCoreApplicationRun()) {
4224 // XRE_metroShutdown should have already been called on the worker
4225 // thread that called XRE_metroStartup.
4226 NS_ASSERTION(!xreMainPtr
->mScopedXPCom
,
4227 "XPCOM Shutdown hasn't occured, and we are exiting.");
4231 void SetWindowsEnvironment(WindowsEnvironmentType aEnvID
);
4232 #endif // MOZ_METRO || !defined(XP_WIN)
4235 XRE_StopLateWriteChecks(void) {
4236 mozilla::StopLateWriteChecks();
4240 XRE_main(int argc
, char* argv
[], const nsXREAppData
* aAppData
, uint32_t aFlags
)
4242 #if !defined(MOZ_METRO) || !defined(XP_WIN)
4244 int result
= main
.XRE_main(argc
, argv
, aAppData
);
4245 mozilla::RecordShutdownEndTimeStamp();
4248 if (aFlags
== XRE_MAIN_FLAG_USE_METRO
) {
4249 SetWindowsEnvironment(WindowsEnvironmentType_Metro
);
4253 if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop
) {
4255 int result
= main
.XRE_main(argc
, argv
, aAppData
);
4256 mozilla::RecordShutdownEndTimeStamp();
4261 NS_ASSERTION(XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Metro
,
4262 "Unknown Windows environment");
4264 int result
= XRE_mainMetro(argc
, argv
, aAppData
);
4265 mozilla::RecordShutdownEndTimeStamp();
4267 #endif // MOZ_METRO || !defined(XP_WIN)
4271 XRE_InitCommandLine(int aArgc
, char* aArgv
[])
4273 nsresult rv
= NS_OK
;
4276 CommandLine::Init(aArgc
, aArgv
);
4279 // these leak on error, but that's OK: we'll just exit()
4280 char** canonArgs
= new char*[aArgc
];
4282 // get the canonical version of the binary's path
4283 nsCOMPtr
<nsIFile
> binFile
;
4284 rv
= XRE_GetBinaryPath(aArgv
[0], getter_AddRefs(binFile
));
4286 return NS_ERROR_FAILURE
;
4288 nsAutoCString canonBinPath
;
4289 rv
= binFile
->GetNativePath(canonBinPath
);
4291 return NS_ERROR_FAILURE
;
4293 canonArgs
[0] = strdup(canonBinPath
.get());
4295 for (int i
= 1; i
< aArgc
; ++i
) {
4297 canonArgs
[i
] = strdup(aArgv
[i
]);
4301 NS_ASSERTION(!CommandLine::IsInitialized(), "Bad news!");
4302 CommandLine::Init(aArgc
, canonArgs
);
4304 for (int i
= 0; i
< aArgc
; ++i
)
4309 const char *path
= nullptr;
4310 ArgResult ar
= CheckArg("greomni", false, &path
);
4311 if (ar
== ARG_BAD
) {
4312 PR_fprintf(PR_STDERR
, "Error: argument -greomni requires a path argument\n");
4313 return NS_ERROR_FAILURE
;
4319 nsCOMPtr
<nsIFile
> greOmni
;
4320 rv
= XRE_GetFileFromPath(path
, getter_AddRefs(greOmni
));
4321 if (NS_FAILED(rv
)) {
4322 PR_fprintf(PR_STDERR
, "Error: argument -greomni requires a valid path\n");
4326 ar
= CheckArg("appomni", false, &path
);
4327 if (ar
== ARG_BAD
) {
4328 PR_fprintf(PR_STDERR
, "Error: argument -appomni requires a path argument\n");
4329 return NS_ERROR_FAILURE
;
4332 nsCOMPtr
<nsIFile
> appOmni
;
4334 rv
= XRE_GetFileFromPath(path
, getter_AddRefs(appOmni
));
4335 if (NS_FAILED(rv
)) {
4336 PR_fprintf(PR_STDERR
, "Error: argument -appomni requires a valid path\n");
4341 mozilla::Omnijar::Init(greOmni
, appOmni
);
4346 XRE_DeinitCommandLine()
4348 nsresult rv
= NS_OK
;
4350 CommandLine::Terminate();
4356 XRE_GetProcessType()
4358 return mozilla::startup::sChildProcessType
;
4362 SetupErrorHandling(const char* progname
)
4365 /* On Windows XPSP3 and Windows Vista if DEP is configured off-by-default
4366 we still want DEP protection: enable it explicitly and programmatically.
4368 This function is not available on WinXPSP2 so we dynamically load it.
4371 HMODULE kernel32
= GetModuleHandleW(L
"kernel32.dll");
4372 SetProcessDEPPolicyFunc _SetProcessDEPPolicy
=
4373 (SetProcessDEPPolicyFunc
) GetProcAddress(kernel32
, "SetProcessDEPPolicy");
4374 if (_SetProcessDEPPolicy
)
4375 _SetProcessDEPPolicy(PROCESS_DEP_ENABLE
);
4379 // Suppress the "DLL Foo could not be found" dialog, such that if dependent
4380 // libraries (such as GDI+) are not preset, we gracefully fail to load those
4381 // XPCOM components, instead of being ungraceful.
4382 UINT realMode
= SetErrorMode(0);
4383 realMode
|= SEM_FAILCRITICALERRORS
;
4384 // If XRE_NO_WINDOWS_CRASH_DIALOG is set, suppress displaying the "This
4385 // application has crashed" dialog box. This is mainly useful for
4386 // automated testing environments, e.g. tinderbox, where there's no need
4387 // for a dozen of the dialog boxes to litter the console
4388 if (getenv("XRE_NO_WINDOWS_CRASH_DIALOG"))
4389 realMode
|= SEM_NOGPFAULTERRORBOX
| SEM_NOOPENFILEERRORBOX
;
4391 SetErrorMode(realMode
);
4395 #if defined (DEBUG) && defined(XP_WIN)
4396 // Send MSCRT Warnings, Errors and Assertions to stderr.
4397 // See http://msdn.microsoft.com/en-us/library/1y71x448(v=VS.80).aspx
4398 // and http://msdn.microsoft.com/en-us/library/a68f826y(v=VS.80).aspx.
4400 _CrtSetReportMode(_CRT_WARN
, _CRTDBG_MODE_FILE
);
4401 _CrtSetReportFile(_CRT_WARN
, _CRTDBG_FILE_STDERR
);
4402 _CrtSetReportMode(_CRT_ERROR
, _CRTDBG_MODE_FILE
);
4403 _CrtSetReportFile(_CRT_ERROR
, _CRTDBG_FILE_STDERR
);
4404 _CrtSetReportMode(_CRT_ASSERT
, _CRTDBG_MODE_FILE
);
4405 _CrtSetReportFile(_CRT_ASSERT
, _CRTDBG_FILE_STDERR
);
4407 _CrtSetReportHook(MSCRTReportHook
);
4411 InstallSignalHandlers(progname
);
4414 // Unbuffer stdout, needed for tinderbox tests.