1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is Mozilla Communicator client code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
23 * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
24 * Benjamin Smedberg <benjamin@smedbergs.us>
25 * Ben Goodger <ben@mozilla.org>
26 * Fredrik Holmqvist <thesuckiestemail@yahoo.se>
27 * Ben Turner <mozilla@songbirdnest.com>
28 * Sergei Dolgov <sergei_d@fi.tartu.ee>
30 * Alternatively, the contents of this file may be used under the terms of
31 * either the GNU General Public License Version 2 or later (the "GPL"), or
32 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
33 * in which case the provisions of the GPL or the LGPL are applicable instead
34 * of those above. If you wish to allow use of your version of this file only
35 * under the terms of either the GPL or the LGPL, and not to allow others to
36 * use your version of this file under the terms of the MPL, indicate your
37 * decision by deleting the provisions above and replace them with the notice
38 * and other provisions required by the GPL or the LGPL. If you do not delete
39 * the provisions above, a recipient may use your version of this file under
40 * the terms of any one of the MPL, the GPL or the LGPL.
42 * ***** END LICENSE BLOCK ***** */
44 #if defined(XP_OS2) && defined(MOZ_OS2_HIGH_MEMORY)
45 // os2safe.h has to be included before os2.h, needed for high mem
49 #define XPCOM_TRANSLATE_NSGM_ENTRY_POINT 1
51 #if defined(MOZ_WIDGET_QT)
52 #include <QtGui/QApplication>
53 #include <QtCore/QScopedPointer>
54 #include <QtGui/QApplication>
55 #include <QtGui/QInputContextFactory>
56 #include <QtGui/QInputContext>
57 #endif // MOZ_WIDGET_QT
60 #include "mozilla/dom/ContentParent.h"
61 using mozilla::dom::ContentParent
;
64 #include "nsAppRunner.h"
65 #include "nsUpdateDriver.h"
68 #include "MacLaunchHelper.h"
69 #include "MacApplicationDelegate.h"
70 #include "MacAutoreleasePool.h"
74 #include "private/pprthred.h"
82 #include "nsIAppShellService.h"
83 #include "nsIAppStartup.h"
84 #include "nsIAppStartupNotifier.h"
85 #include "nsIMutableArray.h"
86 #include "nsICategoryManager.h"
87 #include "nsIChromeRegistry.h"
88 #include "nsICommandLineRunner.h"
89 #include "nsIComponentManager.h"
90 #include "nsIComponentRegistrar.h"
91 #include "nsIContentHandler.h"
92 #include "nsIDialogParamBlock.h"
93 #include "nsIDOMWindow.h"
94 #include "nsIFastLoadService.h" // for PLATFORM_FASL_SUFFIX
95 #include "mozilla/ModuleUtils.h"
96 #include "nsIIOService2.h"
97 #include "nsIObserverService.h"
98 #include "nsINativeAppSupport.h"
99 #include "nsIProcess.h"
100 #include "nsIProfileUnlocker.h"
101 #include "nsIPromptService.h"
102 #include "nsIServiceManager.h"
103 #include "nsIStringBundle.h"
104 #include "nsISupportsPrimitives.h"
105 #include "nsITimelineService.h"
106 #include "nsIToolkitChromeRegistry.h"
107 #include "nsIToolkitProfile.h"
108 #include "nsIToolkitProfileService.h"
110 #include "nsIWindowCreator.h"
111 #include "nsIWindowMediator.h"
112 #include "nsIWindowWatcher.h"
113 #include "nsIXULAppInfo.h"
114 #include "nsIXULRuntime.h"
115 #include "nsPIDOMWindow.h"
116 #include "nsIBaseWindow.h"
117 #include "nsIWidget.h"
118 #include "nsIDocShell.h"
119 #include "nsAppShellCID.h"
121 #include "mozilla/FunctionTimer.h"
124 #include "nsIWinAppHelper.h"
126 #include "cairo/cairo-features.h"
128 #ifndef PROCESS_DEP_ENABLE
129 #define PROCESS_DEP_ENABLE 0x1
134 #include "nsCOMPtr.h"
135 #include "nsDirectoryServiceDefs.h"
136 #include "nsDirectoryServiceUtils.h"
137 #include "nsEmbedCID.h"
138 #include "nsNetUtil.h"
139 #include "nsReadableUtils.h"
140 #include "nsStaticComponents.h"
142 #include "nsXPCOMCIDInternal.h"
143 #include "nsXPIDLString.h"
144 #include "nsVersionComparator.h"
146 #include "nsAppDirectoryServiceDefs.h"
147 #include "nsXULAppAPI.h"
148 #include "nsXREDirProvider.h"
149 #include "nsToolkitCompsCID.h"
151 #include "nsINIParser.h"
152 #include "mozilla/Omnijar.h"
156 #if defined(MOZ_SPLASHSCREEN)
157 #include "nsSplashScreen.h"
161 #include <sys/stat.h>
167 // execv() behaves bit differently in R5 and Zeta, looks unreliable in such situation
168 //#include <unistd.h>
170 #include <AppFileInfo.h>
178 #include "nsThreadUtils.h"
182 #include "nsILocalFileMac.h"
183 #include "nsCommandLineServiceMac.h"
186 // for X remote support
187 #ifdef MOZ_ENABLE_XREMOTE
188 #include "XRemoteClient.h"
189 #include "nsIRemoteService.h"
192 #ifdef NS_TRACE_MALLOC
193 #include "nsTraceMalloc.h"
196 #if defined(DEBUG) && defined(XP_WIN32)
200 #if defined (XP_MACOSX)
201 #include <Carbon/Carbon.h>
212 #ifdef MOZ_CRASHREPORTER
213 #include "nsExceptionHandler.h"
214 #include "nsICrashReporter.h"
215 #define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1"
216 #include "nsIPrefService.h"
220 #include "base/command_line.h"
223 #include "mozilla/FunctionTimer.h"
226 #include "AndroidBridge.h"
232 WindowsMutex(const wchar_t *name
) {
233 mHandle
= CreateMutexW(0, FALSE
, name
);
238 CloseHandle(mHandle
);
241 PRBool
Lock(DWORD timeout
= INFINITE
) {
242 DWORD state
= WaitForSingleObject(mHandle
, timeout
);
243 return state
== WAIT_OBJECT_0
;
248 ReleaseMutex(mHandle
);
256 extern PRUint32 gRestartMode
;
257 extern void InstallSignalHandlers(const char *ProgramName
);
258 #include "nsX11ErrorHandler.h"
260 #define FILE_COMPATIBILITY_INFO NS_LITERAL_CSTRING("compatibility.ini")
261 #define FILE_INVALIDATE_CACHES NS_LITERAL_CSTRING(".purgecaches")
266 static const char gToolkitVersion
[] = NS_STRINGIFY(GRE_MILESTONE
);
267 static const char gToolkitBuildID
[] = NS_STRINGIFY(GRE_BUILDID
);
269 static int gRestartArgc
;
270 static char **gRestartArgv
;
273 static int gQtOnlyArgc
;
274 static char **gQtOnlyArgv
;
277 #if defined(MOZ_WIDGET_GTK2)
278 #if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING) \
279 || defined(NS_TRACE_MALLOC)
280 #define CLEANUP_MEMORY 1
281 #define PANGO_ENABLE_BACKEND
282 #include <pango/pangofc-fontmap.h>
286 #include <gdk/gdkx.h>
288 #include "nsGTKToolkit.h"
291 // Save literal putenv string to environment variable.
293 SaveToEnv(const char *putenv
)
295 char *expr
= strdup(putenv
);
298 // We intentionally leak |expr| here since it is required by PR_SetEnv.
301 // Save the given word to the specified environment variable.
303 SaveWordToEnv(const char *name
, const nsACString
& word
)
305 char *expr
= PR_smprintf("%s=%s", name
, PromiseFlatCString(word
).get());
308 // We intentionally leak |expr| here since it is required by PR_SetEnv.
311 // Save the path of the given file to the specified environment variable.
313 SaveFileToEnv(const char *name
, nsIFile
*file
)
318 SetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name
).get(), path
.get());
321 file
->GetNativePath(path
);
322 SaveWordToEnv(name
, path
);
326 // Load the path of a file saved with SaveFileToEnv
327 static already_AddRefed
<nsILocalFile
>
328 GetFileFromEnv(const char *name
)
331 nsILocalFile
*file
= nsnull
;
334 WCHAR path
[_MAX_PATH
];
335 if (!GetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name
).get(),
339 rv
= NS_NewLocalFile(nsDependentString(path
), PR_TRUE
, &file
);
345 const char *arg
= PR_GetEnv(name
);
349 rv
= NS_NewNativeLocalFile(nsDependentCString(arg
), PR_TRUE
, &file
);
357 // Save the path of the given word to the specified environment variable
358 // provided the environment variable does not have a value.
360 SaveWordToEnvIfUnset(const char *name
, const nsACString
& word
)
362 const char *val
= PR_GetEnv(name
);
364 SaveWordToEnv(name
, word
);
367 // Save the path of the given file to the specified environment variable
368 // provided the environment variable does not have a value.
370 SaveFileToEnvIfUnset(const char *name
, nsIFile
*file
)
372 const char *val
= PR_GetEnv(name
);
374 SaveFileToEnv(name
, file
);
378 strimatch(const char* lowerstr
, const char* mixedstr
)
381 if (!*mixedstr
) return PR_FALSE
; // mixedstr is shorter
382 if (tolower(*mixedstr
) != *lowerstr
) return PR_FALSE
; // no match
388 if (*mixedstr
) return PR_FALSE
; // lowerstr is shorter
394 * Output a string to the user. This method is really only meant to be used to
395 * output last-ditch error messages designed for developers NOT END USERS.
398 * Pass true to indicate severe errors.
400 * printf-style format string followed by arguments.
402 static void Output(PRBool isError
, const char *fmt
, ... )
407 #if defined(XP_WIN) && !MOZ_WINCONSOLE
408 char *msg
= PR_vsmprintf(fmt
, ap
);
413 flags
|= MB_ICONERROR
;
415 flags
|= MB_ICONINFORMATION
;
417 wchar_t wide_msg
[1024];
418 MultiByteToWideChar(CP_ACP
,
423 sizeof(wide_msg
) / sizeof(wchar_t));
425 MessageBoxW(NULL
, wide_msg
, L
"XULRunner", flags
);
426 PR_smprintf_free(msg
);
429 vfprintf(stderr
, fmt
, ap
);
436 REMOTE_NOT_FOUND
= 0,
444 ARG_BAD
= 2 // you wanted a param, but there isn't one
447 static void RemoveArg(char **argv
)
458 * Check for a commandline flag. If the flag takes a parameter, the
459 * parameter is returned in aParam. Flags may be in the form -arg or
460 * --arg (or /arg on win32/OS2).
462 * @param aArg the parameter to check. Must be lowercase.
463 * @param aCheckOSInt if true returns ARG_BAD if the osint argument is present
464 * when aArg is also present.
465 * @param if non-null, the -arg <data> will be stored in this pointer. This is *not*
466 * allocated, but rather a pointer to the argv data.
469 CheckArg(const char* aArg
, PRBool aCheckOSInt
= PR_FALSE
, const char **aParam
= nsnull
, PRBool aRemArg
= PR_TRUE
)
471 NS_ABORT_IF_FALSE(gArgv
, "gArgv must be initialized before CheckArg()");
473 char **curarg
= gArgv
+ 1; // skip argv[0]
474 ArgResult ar
= ARG_NONE
;
477 char *arg
= curarg
[0];
480 #if defined(XP_WIN) || defined(XP_OS2)
488 if (strimatch(aArg
, arg
)) {
498 #if defined(XP_WIN) || defined(XP_OS2)
517 if (aCheckOSInt
&& ar
== ARG_FOUND
) {
518 ArgResult arOSInt
= CheckArg("osint");
519 if (arOSInt
== ARG_FOUND
) {
521 PR_fprintf(PR_STDERR
, "Error: argument -osint is invalid\n");
530 * Check for a commandline flag from the windows shell and remove it from the
531 * argv used when restarting. Flags MUST be in the form -arg.
533 * @param aArg the parameter to check. Must be lowercase.
536 CheckArgShell(const char* aArg
)
538 char **curarg
= gRestartArgv
+ 1; // skip argv[0]
541 char *arg
= curarg
[0];
546 if (strimatch(aArg
, arg
)) {
548 *curarg
= *(curarg
+ 1);
565 * Enabled Native App Support to process DDE messages when the app needs to
566 * restart and the app has been launched by the Windows shell to open an url.
567 * When aWait is false this will process the DDE events manually. This prevents
568 * Windows from displaying an error message due to the DDE message not being
572 ProcessDDE(nsINativeAppSupport
* aNative
, PRBool aWait
)
574 // When the app is launched by the windows shell the windows shell
575 // expects the app to be available for DDE messages and if it isn't
576 // windows displays an error dialog. To prevent the error the DDE server
577 // is enabled and pending events are processed when the app needs to
578 // restart after it was launched by the shell with the requestpending
579 // argument. The requestpending pending argument is removed to
580 // differentiate it from being launched when an app restart is not
583 ar
= CheckArgShell("requestpending");
584 if (ar
== ARG_FOUND
) {
585 aNative
->Enable(); // enable win32 DDE responses
587 nsIThread
*thread
= NS_GetCurrentThread();
588 // This is just a guesstimate based on testing different values.
589 // If count is 8 or less windows will display an error dialog.
591 while(--count
>= 0) {
592 NS_ProcessNextEvent(thread
);
593 PR_Sleep(PR_MillisecondsToInterval(1));
600 PRBool gSafeMode
= PR_FALSE
;
603 * The nsXULAppInfo object implements nsIFactory so that it can be its own
606 class nsXULAppInfo
: public nsIXULAppInfo
,
608 public nsIWinAppHelper
,
610 #ifdef MOZ_CRASHREPORTER
611 public nsICrashReporter
,
617 NS_DECL_ISUPPORTS_INHERITED
618 NS_DECL_NSIXULAPPINFO
619 NS_DECL_NSIXULRUNTIME
620 #ifdef MOZ_CRASHREPORTER
621 NS_DECL_NSICRASHREPORTER
624 NS_DECL_NSIWINAPPHELPER
628 NS_INTERFACE_MAP_BEGIN(nsXULAppInfo
)
629 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIXULRuntime
)
630 NS_INTERFACE_MAP_ENTRY(nsIXULRuntime
)
632 NS_INTERFACE_MAP_ENTRY(nsIWinAppHelper
)
634 #ifdef MOZ_CRASHREPORTER
635 NS_INTERFACE_MAP_ENTRY(nsICrashReporter
)
637 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIXULAppInfo
, gAppData
)
640 NS_IMETHODIMP_(nsrefcnt
)
641 nsXULAppInfo::AddRef()
646 NS_IMETHODIMP_(nsrefcnt
)
647 nsXULAppInfo::Release()
653 nsXULAppInfo::GetVendor(nsACString
& aResult
)
655 aResult
.Assign(gAppData
->vendor
);
661 nsXULAppInfo::GetName(nsACString
& aResult
)
663 aResult
.Assign(gAppData
->name
);
669 nsXULAppInfo::GetID(nsACString
& aResult
)
671 aResult
.Assign(gAppData
->ID
);
677 nsXULAppInfo::GetVersion(nsACString
& aResult
)
679 aResult
.Assign(gAppData
->version
);
685 nsXULAppInfo::GetPlatformVersion(nsACString
& aResult
)
687 aResult
.Assign(gToolkitVersion
);
693 nsXULAppInfo::GetAppBuildID(nsACString
& aResult
)
695 aResult
.Assign(gAppData
->buildID
);
701 nsXULAppInfo::GetPlatformBuildID(nsACString
& aResult
)
703 aResult
.Assign(gToolkitBuildID
);
709 nsXULAppInfo::GetLogConsoleErrors(PRBool
*aResult
)
711 *aResult
= gLogConsoleErrors
;
716 nsXULAppInfo::SetLogConsoleErrors(PRBool aValue
)
718 gLogConsoleErrors
= aValue
;
723 nsXULAppInfo::GetInSafeMode(PRBool
*aResult
)
725 *aResult
= gSafeMode
;
730 nsXULAppInfo::GetOS(nsACString
& aResult
)
732 aResult
.AssignLiteral(OS_TARGET
);
737 nsXULAppInfo::GetXPCOMABI(nsACString
& aResult
)
739 #ifdef TARGET_XPCOM_ABI
740 aResult
.AssignLiteral(TARGET_XPCOM_ABI
);
743 return NS_ERROR_NOT_AVAILABLE
;
748 nsXULAppInfo::GetWidgetToolkit(nsACString
& aResult
)
750 aResult
.AssignLiteral(MOZ_WIDGET_TOOLKIT
);
754 // Ensure that the GeckoProcessType enum, defined in xpcom/build/nsXULAppAPI.h,
755 // is synchronized with the const unsigned longs defined in
756 // xpcom/system/nsIXULRuntime.idl.
757 #define SYNC_ENUMS(a,b) \
758 PR_STATIC_ASSERT(nsIXULRuntime::PROCESS_TYPE_ ## a == \
759 static_cast<int>(GeckoProcessType_ ## b));
761 SYNC_ENUMS(DEFAULT
, Default
)
762 SYNC_ENUMS(PLUGIN
, Plugin
)
763 SYNC_ENUMS(CONTENT
, Content
)
764 SYNC_ENUMS(JETPACK
, Jetpack
)
765 SYNC_ENUMS(IPDLUNITTEST
, IPDLUnitTest
)
767 // .. and ensure that that is all of them:
768 PR_STATIC_ASSERT(GeckoProcessType_IPDLUnitTest
+ 1 == GeckoProcessType_End
);
771 nsXULAppInfo::GetProcessType(PRUint32
* aResult
)
773 NS_ENSURE_ARG_POINTER(aResult
);
774 *aResult
= XRE_GetProcessType();
779 nsXULAppInfo::EnsureContentProcess()
782 if (XRE_GetProcessType() != GeckoProcessType_Default
)
783 return NS_ERROR_NOT_AVAILABLE
;
785 ContentParent
* c
= ContentParent::GetSingleton();
787 return NS_ERROR_NOT_AVAILABLE
;
790 return NS_ERROR_NOT_AVAILABLE
;
795 nsXULAppInfo::InvalidateCachesOnRestart()
797 nsCOMPtr
<nsIFile
> file
;
798 nsresult rv
= NS_GetSpecialDirectory(NS_APP_PROFILE_DIR_STARTUP
,
799 getter_AddRefs(file
));
803 return NS_ERROR_NOT_AVAILABLE
;
805 file
->AppendNative(FILE_COMPATIBILITY_INFO
);
807 nsCOMPtr
<nsILocalFile
> localFile(do_QueryInterface(file
));
809 rv
= parser
.Init(localFile
);
811 // This fails if compatibility.ini is not there, so we'll
812 // flush the caches on the next restart anyways.
817 rv
= parser
.GetString("Compatibility", "InvalidateCaches", buf
);
820 PRFileDesc
*fd
= nsnull
;
821 localFile
->OpenNSPRFileDesc(PR_RDWR
| PR_APPEND
, 0600, &fd
);
823 NS_ERROR("could not create output stream");
824 return NS_ERROR_NOT_AVAILABLE
;
826 static const char kInvalidationHeader
[] = NS_LINEBREAK
"InvalidateCaches=1" NS_LINEBREAK
;
827 rv
= PR_Write(fd
, kInvalidationHeader
, sizeof(kInvalidationHeader
) - 1);
837 // Matches the enum in WinNT.h for the Vista SDK but renamed so that we can
838 // safely build with the Vista SDK and without it.
841 VistaTokenElevationTypeDefault
= 1,
842 VistaTokenElevationTypeFull
,
843 VistaTokenElevationTypeLimited
844 } VISTA_TOKEN_ELEVATION_TYPE
;
846 // avoid collision with TokeElevationType enum in WinNT.h
848 #define VistaTokenElevationType static_cast< TOKEN_INFORMATION_CLASS >( 18 )
851 nsXULAppInfo::GetUserCanElevate(PRBool
*aUserCanElevate
)
854 *aUserCanElevate
= PR_FALSE
;
859 VISTA_TOKEN_ELEVATION_TYPE elevationType
;
862 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
) ||
863 !GetTokenInformation(hToken
, VistaTokenElevationType
, &elevationType
,
864 sizeof(elevationType
), &dwSize
)) {
865 *aUserCanElevate
= PR_FALSE
;
868 // The possible values returned for elevationType and their meanings are:
869 // TokenElevationTypeDefault: The token does not have a linked token
870 // (e.g. UAC disabled or a standard user, so they can't be elevated)
871 // TokenElevationTypeFull: The token is linked to an elevated token
872 // (e.g. UAC is enabled and the user is already elevated so they can't
873 // be elevated again)
874 // TokenElevationTypeLimited: The token is linked to a limited token
875 // (e.g. UAC is enabled and the user is not elevated, so they can be
877 *aUserCanElevate
= (elevationType
== VistaTokenElevationTypeLimited
);
888 #ifdef MOZ_CRASHREPORTER
890 nsXULAppInfo::GetEnabled(PRBool
*aEnabled
)
892 *aEnabled
= CrashReporter::GetEnabled();
897 nsXULAppInfo::SetEnabled(PRBool aEnabled
)
900 if (CrashReporter::GetEnabled())
901 // no point in erroring for double-enabling
904 nsCOMPtr
<nsILocalFile
> xreDirectory
;
906 xreDirectory
= gAppData
->xreDirectory
;
909 // We didn't get started through XRE_Main, probably
910 nsCOMPtr
<nsIFile
> greDir
;
911 NS_GetSpecialDirectory(NS_GRE_DIR
, getter_AddRefs(greDir
));
913 return NS_ERROR_FAILURE
;
915 xreDirectory
= do_QueryInterface(greDir
);
917 return NS_ERROR_FAILURE
;
919 return CrashReporter::SetExceptionHandler(xreDirectory
, true);
922 if (!CrashReporter::GetEnabled())
923 // no point in erroring for double-disabling
926 return CrashReporter::UnsetExceptionHandler();
931 nsXULAppInfo::GetServerURL(nsIURL
** aServerURL
)
933 if (!CrashReporter::GetEnabled())
934 return NS_ERROR_NOT_INITIALIZED
;
937 if (!CrashReporter::GetServerURL(data
)) {
938 return NS_ERROR_FAILURE
;
940 nsCOMPtr
<nsIURI
> uri
;
941 NS_NewURI(getter_AddRefs(uri
), data
);
943 return NS_ERROR_FAILURE
;
945 nsCOMPtr
<nsIURL
> url
;
946 url
= do_QueryInterface(uri
);
947 NS_ADDREF(*aServerURL
= url
);
953 nsXULAppInfo::SetServerURL(nsIURL
* aServerURL
)
956 // only allow https or http URLs
957 nsresult rv
= aServerURL
->SchemeIs("https", &schemeOk
);
958 NS_ENSURE_SUCCESS(rv
, rv
);
960 rv
= aServerURL
->SchemeIs("http", &schemeOk
);
961 NS_ENSURE_SUCCESS(rv
, rv
);
964 return NS_ERROR_INVALID_ARG
;
967 rv
= aServerURL
->GetSpec(spec
);
968 NS_ENSURE_SUCCESS(rv
, rv
);
970 return CrashReporter::SetServerURL(spec
);
974 nsXULAppInfo::GetMinidumpPath(nsILocalFile
** aMinidumpPath
)
976 if (!CrashReporter::GetEnabled())
977 return NS_ERROR_NOT_INITIALIZED
;
980 if (!CrashReporter::GetMinidumpPath(path
))
981 return NS_ERROR_FAILURE
;
983 nsresult rv
= NS_NewLocalFile(path
, PR_FALSE
, aMinidumpPath
);
984 NS_ENSURE_SUCCESS(rv
, rv
);
989 nsXULAppInfo::SetMinidumpPath(nsILocalFile
* aMinidumpPath
)
992 nsresult rv
= aMinidumpPath
->GetPath(path
);
993 NS_ENSURE_SUCCESS(rv
, rv
);
994 return CrashReporter::SetMinidumpPath(path
);
998 nsXULAppInfo::AnnotateCrashReport(const nsACString
& key
,
999 const nsACString
& data
)
1001 return CrashReporter::AnnotateCrashReport(key
, data
);
1005 nsXULAppInfo::AppendAppNotesToCrashReport(const nsACString
& data
)
1007 return CrashReporter::AppendAppNotesToCrashReport(data
);
1011 nsXULAppInfo::WriteMinidumpForException(void* aExceptionInfo
)
1014 return CrashReporter::WriteMinidumpForException(static_cast<EXCEPTION_POINTERS
*>(aExceptionInfo
));
1016 return NS_ERROR_NOT_IMPLEMENTED
;
1021 nsXULAppInfo::AppendObjCExceptionInfoToAppNotes(void* aException
)
1024 return CrashReporter::AppendObjCExceptionInfoToAppNotes(aException
);
1026 return NS_ERROR_NOT_IMPLEMENTED
;
1031 nsXULAppInfo::GetSubmitReports(PRBool
* aEnabled
)
1033 return CrashReporter::GetSubmitReports(aEnabled
);
1037 nsXULAppInfo::SetSubmitReports(PRBool aEnabled
)
1039 return CrashReporter::SetSubmitReports(aEnabled
);
1044 static const nsXULAppInfo kAppInfo
;
1045 static nsresult
AppInfoConstructor(nsISupports
* aOuter
,
1046 REFNSIID aIID
, void **aResult
)
1048 NS_ENSURE_NO_AGGREGATION(aOuter
);
1050 return const_cast<nsXULAppInfo
*>(&kAppInfo
)->
1051 QueryInterface(aIID
, aResult
);
1054 PRBool gLogConsoleErrors
1061 #define NS_ENSURE_TRUE_LOG(x, ret) \
1063 if (NS_UNLIKELY(!(x))) { \
1064 NS_WARNING("NS_ENSURE_TRUE(" #x ") failed"); \
1065 gLogConsoleErrors = PR_TRUE; \
1070 #define NS_ENSURE_SUCCESS_LOG(res, ret) \
1071 NS_ENSURE_TRUE_LOG(NS_SUCCEEDED(res), ret)
1074 * Because we're starting/stopping XPCOM several times in different scenarios,
1075 * this class is a stack-based critter that makes sure that XPCOM is shut down
1076 * during early returns.
1079 class ScopedXPCOMStartup
1082 ScopedXPCOMStartup() :
1083 mServiceManager(nsnull
) { }
1084 ~ScopedXPCOMStartup();
1086 nsresult
Initialize();
1087 nsresult
SetWindowCreator(nsINativeAppSupport
* native
);
1089 static nsresult
CreateAppSupport(nsISupports
* aOuter
, REFNSIID aIID
, void** aResult
);
1092 nsIServiceManager
* mServiceManager
;
1093 static nsINativeAppSupport
* gNativeAppSupport
;
1096 ScopedXPCOMStartup::~ScopedXPCOMStartup()
1098 NS_IF_RELEASE(gNativeAppSupport
);
1100 if (mServiceManager
) {
1102 // On OS X, we need a pool to catch cocoa objects that are autoreleased
1104 mozilla::MacAutoreleasePool pool
;
1107 nsCOMPtr
<nsIAppStartup
> appStartup (do_GetService(NS_APPSTARTUP_CONTRACTID
));
1109 appStartup
->DestroyHiddenWindow();
1111 gDirServiceProvider
->DoShutdown();
1115 NS_ShutdownXPCOM(mServiceManager
);
1116 mServiceManager
= nsnull
;
1120 // {95d89e3e-a169-41a3-8e56-719978e15b12}
1121 #define APPINFO_CID \
1122 { 0x95d89e3e, 0xa169, 0x41a3, { 0x8e, 0x56, 0x71, 0x99, 0x78, 0xe1, 0x5b, 0x12 } }
1124 // {0C4A446C-EE82-41f2-8D04-D366D2C7A7D4}
1125 static const nsCID kNativeAppSupportCID
=
1126 { 0xc4a446c, 0xee82, 0x41f2, { 0x8d, 0x4, 0xd3, 0x66, 0xd2, 0xc7, 0xa7, 0xd4 } };
1128 // {5F5E59CE-27BC-47eb-9D1F-B09CA9049836}
1129 static const nsCID kProfileServiceCID
=
1130 { 0x5f5e59ce, 0x27bc, 0x47eb, { 0x9d, 0x1f, 0xb0, 0x9c, 0xa9, 0x4, 0x98, 0x36 } };
1132 static already_AddRefed
<nsIFactory
>
1133 ProfileServiceFactoryConstructor(const mozilla::Module
& module
, const mozilla::Module::CIDEntry
& entry
)
1135 nsCOMPtr
<nsIFactory
> factory
;
1136 NS_NewToolkitProfileFactory(getter_AddRefs(factory
));
1137 return factory
.forget();
1140 NS_DEFINE_NAMED_CID(APPINFO_CID
);
1142 static const mozilla::Module::CIDEntry kXRECIDs
[] = {
1143 { &kAPPINFO_CID
, false, NULL
, AppInfoConstructor
},
1144 { &kProfileServiceCID
, false, ProfileServiceFactoryConstructor
, NULL
},
1145 { &kNativeAppSupportCID
, false, NULL
, ScopedXPCOMStartup::CreateAppSupport
},
1149 static const mozilla::Module::ContractIDEntry kXREContracts
[] = {
1150 { XULAPPINFO_SERVICE_CONTRACTID
, &kAPPINFO_CID
},
1151 { XULRUNTIME_SERVICE_CONTRACTID
, &kAPPINFO_CID
},
1152 #ifdef MOZ_CRASHREPORTER
1153 { NS_CRASHREPORTER_CONTRACTID
, &kAPPINFO_CID
},
1155 { NS_PROFILESERVICE_CONTRACTID
, &kProfileServiceCID
},
1156 { NS_NATIVEAPPSUPPORT_CONTRACTID
, &kNativeAppSupportCID
},
1160 static const mozilla::Module kXREModule
= {
1161 mozilla::Module::kVersion
,
1166 NSMODULE_DEFN(Apprunner
) = &kXREModule
;
1169 ScopedXPCOMStartup::Initialize()
1171 NS_ASSERTION(gDirServiceProvider
, "Should not get here!");
1175 #ifndef MOZ_ENABLE_LIBXUL
1176 #ifndef _BUILD_STATIC_BIN
1177 XRE_AddStaticComponent(&kXREModule
);
1179 for (const mozilla::Module
*const *const *staticModules
= kPStaticModules
;
1180 *staticModules
; ++staticModules
)
1181 XRE_AddStaticComponent(**staticModules
);
1185 rv
= NS_InitXPCOM2(&mServiceManager
, gDirServiceProvider
->GetAppDir(),
1186 gDirServiceProvider
);
1187 if (NS_FAILED(rv
)) {
1188 NS_ERROR("Couldn't start xpcom!");
1189 mServiceManager
= nsnull
;
1192 nsCOMPtr
<nsIComponentRegistrar
> reg
=
1193 do_QueryInterface(mServiceManager
);
1194 NS_ASSERTION(reg
, "Service Manager doesn't QI to Registrar.");
1201 * This is a little factory class that serves as a singleton-service-factory
1202 * for the nativeappsupport object.
1204 class nsSingletonFactory
: public nsIFactory
1210 nsSingletonFactory(nsISupports
* aSingleton
);
1211 ~nsSingletonFactory() { }
1214 nsCOMPtr
<nsISupports
> mSingleton
;
1217 nsSingletonFactory::nsSingletonFactory(nsISupports
* aSingleton
)
1218 : mSingleton(aSingleton
)
1220 NS_ASSERTION(mSingleton
, "Singleton was null!");
1223 NS_IMPL_ISUPPORTS1(nsSingletonFactory
, nsIFactory
)
1226 nsSingletonFactory::CreateInstance(nsISupports
* aOuter
,
1230 NS_ENSURE_NO_AGGREGATION(aOuter
);
1232 return mSingleton
->QueryInterface(aIID
, aResult
);
1236 nsSingletonFactory::LockFactory(PRBool
)
1242 * Set our windowcreator on the WindowWatcher service.
1245 ScopedXPCOMStartup::SetWindowCreator(nsINativeAppSupport
* native
)
1250 NS_IF_ADDREF(gNativeAppSupport
= native
);
1252 // Inform the chrome registry about OS accessibility
1253 nsCOMPtr
<nsIToolkitChromeRegistry
> cr
=
1254 mozilla::services::GetToolkitChromeRegistryService();
1255 NS_TIME_FUNCTION_MARK("Got ToolkitChromeRegistry service");
1258 cr
->CheckForOSAccessibility();
1260 NS_TIME_FUNCTION_MARK("OS Accessibility check");
1262 nsCOMPtr
<nsIWindowCreator
> creator (do_GetService(NS_APPSTARTUP_CONTRACTID
));
1263 if (!creator
) return NS_ERROR_UNEXPECTED
;
1265 NS_TIME_FUNCTION_MARK("Got AppStartup service");
1267 nsCOMPtr
<nsIWindowWatcher
> wwatch
1268 (do_GetService(NS_WINDOWWATCHER_CONTRACTID
, &rv
));
1269 NS_ENSURE_SUCCESS(rv
, rv
);
1271 NS_TIME_FUNCTION_MARK("Got WindowWatcher service");
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"
1335 " --no-xshm Don't use X shared memory extension\n"
1336 " --xim-preedit=STYLE\n"
1337 " --xim-status=STYLE\n");
1340 printf(" --g-fatal-warnings Make all warnings fatal\n"
1341 "\n%s options\n", gAppData
->name
);
1344 printf(" -h or -help Print this message.\n"
1345 " -v or -version Print %s version.\n"
1346 " -P <profile> Start with <profile>.\n"
1347 " -migration Start with migration wizard.\n"
1348 " -ProfileManager Start with ProfileManager.\n"
1349 " -no-remote Open new instance, not a new window in running instance.\n"
1350 " -UILocale <locale> Start with <locale> resources as UI Locale.\n"
1351 " -safe-mode Disables extensions and themes for this session.\n", gAppData
->name
);
1353 #if defined(XP_WIN) || defined(XP_OS2)
1354 printf(" -console Start %s with a debugging console.\n", gAppData
->name
);
1357 // this works, but only after the components have registered. so if you drop in a new command line handler, -help
1358 // won't not until the second run.
1359 // out of the bug, because we ship a component.reg file, it works correctly.
1360 DumpArbitraryHelp();
1365 #define _CRTDBG_MAP_ALLOC
1370 #if defined(FREEBSD)
1371 // pick up fpsetmask prototype.
1379 gAppData
->vendor
? gAppData
->vendor
: "", gAppData
->name
, gAppData
->version
);
1380 if (gAppData
->copyright
)
1381 printf(", %s", gAppData
->copyright
);
1385 #ifdef MOZ_ENABLE_XREMOTE
1386 // use int here instead of a PR type since it will be returned
1387 // from main - just to keep types consistent
1389 HandleRemoteArgument(const char* remote
, const char* aDesktopStartupID
)
1394 const char *profile
= 0;
1395 nsCAutoString
program(gAppData
->name
);
1396 ToLowerCase(program
);
1397 const char *username
= getenv("LOGNAME");
1399 ar
= CheckArg("p", PR_FALSE
, &profile
);
1400 if (ar
== ARG_BAD
) {
1401 PR_fprintf(PR_STDERR
, "Error: argument -p requires a profile name\n");
1405 const char *temp
= nsnull
;
1406 ar
= CheckArg("a", PR_FALSE
, &temp
);
1407 if (ar
== ARG_BAD
) {
1408 PR_fprintf(PR_STDERR
, "Error: argument -a requires an application name\n");
1410 } else if (ar
== ARG_FOUND
) {
1411 program
.Assign(temp
);
1414 ar
= CheckArg("u", PR_FALSE
, &username
);
1415 if (ar
== ARG_BAD
) {
1416 PR_fprintf(PR_STDERR
, "Error: argument -u requires a username\n");
1420 XRemoteClient client
;
1422 if (NS_FAILED(rv
)) {
1423 PR_fprintf(PR_STDERR
, "Error: Failed to connect to X server.\n");
1427 nsXPIDLCString response
;
1428 PRBool success
= PR_FALSE
;
1429 rv
= client
.SendCommand(program
.get(), username
, profile
, remote
,
1430 aDesktopStartupID
, getter_Copies(response
), &success
);
1431 // did the command fail?
1432 if (NS_FAILED(rv
)) {
1433 PR_fprintf(PR_STDERR
, "Error: Failed to send command: %s\n",
1434 response
? response
.get() : "No response included");
1439 PR_fprintf(PR_STDERR
, "Error: No running window found\n");
1447 RemoteCommandLine(const char* aDesktopStartupID
)
1452 nsCAutoString
program(gAppData
->name
);
1453 ToLowerCase(program
);
1454 const char *username
= getenv("LOGNAME");
1456 const char *temp
= nsnull
;
1457 ar
= CheckArg("a", PR_TRUE
, &temp
);
1458 if (ar
== ARG_BAD
) {
1459 PR_fprintf(PR_STDERR
, "Error: argument -a requires an application name\n");
1460 return REMOTE_ARG_BAD
;
1461 } else if (ar
== ARG_FOUND
) {
1462 program
.Assign(temp
);
1465 ar
= CheckArg("u", PR_TRUE
, &username
);
1466 if (ar
== ARG_BAD
) {
1467 PR_fprintf(PR_STDERR
, "Error: argument -u requires a username\n");
1468 return REMOTE_ARG_BAD
;
1471 XRemoteClient client
;
1474 return REMOTE_NOT_FOUND
;
1476 nsXPIDLCString response
;
1477 PRBool success
= PR_FALSE
;
1478 rv
= client
.SendCommandLine(program
.get(), username
, nsnull
,
1479 gArgc
, gArgv
, aDesktopStartupID
,
1480 getter_Copies(response
), &success
);
1481 // did the command fail?
1482 if (NS_FAILED(rv
) || !success
)
1483 return REMOTE_NOT_FOUND
;
1485 return REMOTE_FOUND
;
1487 #endif // MOZ_ENABLE_XREMOTE
1490 static char const *gBinaryPath
;
1494 XRE_GetBinaryPath(const char* argv0
, nsILocalFile
* *aResult
)
1497 nsCOMPtr
<nsILocalFile
> lf
;
1499 // We need to use platform-specific hackery to find the
1500 // path of this executable. This is copied, with some modifications, from
1501 // nsGREDirServiceProvider.cpp
1504 PRUnichar exePath
[MAXPATHLEN
];
1506 if (!::GetModuleFileNameW(0, exePath
, MAXPATHLEN
))
1507 return NS_ERROR_FAILURE
;
1509 rv
= NS_NewLocalFile(nsDependentString(exePath
), PR_TRUE
,
1510 getter_AddRefs(lf
));
1514 #elif defined(XP_MACOSX)
1516 return NS_NewNativeLocalFile(nsDependentCString(gBinaryPath
), PR_FALSE
,
1519 NS_NewNativeLocalFile(EmptyCString(), PR_TRUE
, getter_AddRefs(lf
));
1520 nsCOMPtr
<nsILocalFileMac
> lfm (do_QueryInterface(lf
));
1522 return NS_ERROR_FAILURE
;
1524 // Works even if we're not bundled.
1525 CFBundleRef appBundle
= CFBundleGetMainBundle();
1527 return NS_ERROR_FAILURE
;
1529 CFURLRef executableURL
= CFBundleCopyExecutableURL(appBundle
);
1531 return NS_ERROR_FAILURE
;
1532 rv
= lfm
->InitWithCFURL(executableURL
);
1533 CFRelease(executableURL
);
1537 // Callers expect a normalized path.
1540 #elif defined(XP_UNIX)
1541 struct stat fileStat
;
1542 char exePath
[MAXPATHLEN
];
1543 char tmpPath
[MAXPATHLEN
];
1545 rv
= NS_ERROR_FAILURE
;
1547 // on unix, there is no official way to get the path of the current binary.
1548 // instead of using the MOZILLA_FIVE_HOME hack, which doesn't scale to
1549 // multiple applications, we will try a series of techniques:
1551 // 1) look for /proc/<pid>/exe which is a symlink to the executable on newer
1553 // 2) use realpath() on argv[0], which works unless we're loaded from the
1555 // 3) manually walk through the PATH and look for ourself
1559 // Commented out because it used to not work because it used to not deal
1560 // with readlink not null-terminating the buffer.
1562 int r
= readlink("/proc/self/exe", exePath
, MAXPATHLEN
);
1564 if (r
> 0 && r
< MAXPATHLEN
) {
1566 if (stat(exePath
, &fileStat
) == 0) {
1572 if (NS_FAILED(rv
) &&
1573 realpath(argv0
, exePath
) && stat(exePath
, &fileStat
) == 0) {
1577 if (NS_FAILED(rv
)) {
1578 const char *path
= getenv("PATH");
1580 return NS_ERROR_FAILURE
;
1582 char *pathdup
= strdup(path
);
1584 return NS_ERROR_OUT_OF_MEMORY
;
1586 PRBool found
= PR_FALSE
;
1587 char *newStr
= pathdup
;
1589 while ( (token
= nsCRT::strtok(newStr
, ":", &newStr
)) ) {
1590 sprintf(tmpPath
, "%s/%s", token
, argv0
);
1591 if (realpath(tmpPath
, exePath
) && stat(exePath
, &fileStat
) == 0) {
1598 return NS_ERROR_FAILURE
;
1601 rv
= NS_NewNativeLocalFile(nsDependentCString(exePath
), PR_TRUE
,
1602 getter_AddRefs(lf
));
1606 #elif defined(XP_OS2)
1609 char exePath
[MAXPATHLEN
];
1611 DosGetInfoBlocks( &ptib
, &ppib
);
1612 DosQueryModuleName( ppib
->pib_hmte
, MAXPATHLEN
, exePath
);
1613 rv
= NS_NewNativeLocalFile(nsDependentCString(exePath
), PR_TRUE
,
1614 getter_AddRefs(lf
));
1618 #elif defined(XP_BEOS)
1622 if(get_next_image_info(0, &cookie
, &info
) != B_OK
)
1623 return NS_ERROR_FAILURE
;
1625 rv
= NS_NewNativeLocalFile(nsDependentCString(info
.name
), PR_TRUE
,
1626 getter_AddRefs(lf
));
1631 #error Oops, you need platform-specific code here
1634 NS_ADDREF(*aResult
= lf
);
1638 #define NS_ERROR_LAUNCHED_CHILD_PROCESS NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_PROFILE, 200)
1641 #include "nsWindowsRestart.cpp"
1642 #include <shellapi.h>
1644 typedef BOOL (WINAPI
* SetProcessDEPPolicyFunc
)(DWORD dwFlags
);
1647 #if defined(XP_OS2) && (__KLIBC__ == 0 && __KLIBC_MINOR__ >= 6) // broken kLibc
1648 // Copy the environment maintained by the C library into an ASCIIZ array
1649 // that can be used to pass it on to the OS/2 Dos* APIs (which otherwise
1650 // don't know anything about the stuff set by PR_SetEnv() or setenv()).
1653 // just allocate the maximum amount (24 kB = 0x60000 bytes), to be able to
1654 // copy the existing environment
1655 char *env
= (char *)calloc(0x6000, sizeof(char));
1660 // walk along the environ string array of the C library and copy
1661 // everything (that fits) into the output environment array, leaving
1662 // null bytes between the entries
1663 char *penv
= env
; // movable pointer to result environment ASCIIZ array
1664 int i
= 0, space
= 0x6000;
1665 while (environ
[i
] && environ
[i
][0]) {
1666 int len
= strlen(environ
[i
]);
1667 if (space
- len
<= 0) {
1670 strcpy(penv
, environ
[i
]);
1671 i
++; // next environment variable
1672 penv
+= len
+ 1; // jump to after next null byte
1673 space
-= len
- 1; // subtract consumed length from usable space
1679 // OS2LaunchChild() is there to replace _execv() which is broken in the C
1680 // runtime library that comes with GCC 3.3.5 on OS/2. It uses createEnv()
1681 // to copy the process environment and add necessary variables
1683 // returns -1 on failure and 0 on success
1684 int OS2LaunchChild(const char *aExePath
, int aArgc
, char **aArgv
)
1686 // find total length of aArgv
1688 for (int i
= 0; i
< aArgc
; i
++) {
1689 len
+= strlen(aArgv
[i
]) + 1; // plus space in between
1691 len
++; // leave space for null byte at end
1692 // allocate enough space for all strings and nulls,
1693 // calloc helpfully initializes to null
1694 char *args
= (char *)calloc(len
, sizeof(char));
1698 char *pargs
= args
; // extra pointer to after the last argument
1699 // build argument list in the format the DosStartSession() wants,
1700 // adding spaces between the arguments
1701 for (int i
= 0; i
< aArgc
; i
++, *pargs
++ = ' ') {
1702 strcpy(pargs
, aArgv
[i
]);
1703 pargs
+= strlen(aArgv
[i
]);
1706 *(pargs
-1) = '\0'; // replace last space
1709 // make sure that the program is separated by null byte
1710 pargs
= strchr(args
, ' ');
1715 char *env
= createEnv();
1717 char error
[CCHMAXPATH
] = { 0 };
1718 RESULTCODES crc
= { 0 };
1719 ULONG rc
= DosExecPgm(error
, sizeof(error
), EXEC_ASYNC
, args
, env
,
1720 &crc
, (PSZ
)aExePath
);
1721 free(args
); // done with the arguments
1725 if (rc
!= NO_ERROR
) {
1733 // If aBlankCommandLine is true, then the application will be launched with a
1734 // blank command line instead of being launched with the same command line that
1735 // it was initially started with.
1736 static nsresult
LaunchChild(nsINativeAppSupport
* aNative
,
1737 PRBool aBlankCommandLine
= PR_FALSE
)
1739 aNative
->Quit(); // release DDE mutex, if we're holding it
1741 // Restart this process by exec'ing it into the current process
1742 // if supported by the platform. Otherwise, use NSPR.
1744 if (aBlankCommandLine
) {
1745 #if defined(MOZ_WIDGET_QT)
1746 // Remove only arguments not given to Qt
1747 gRestartArgc
= gQtOnlyArgc
;
1748 gRestartArgv
= gQtOnlyArgv
;
1751 gRestartArgv
[gRestartArgc
] = nsnull
;
1755 SaveToEnv("MOZ_LAUNCHED_CHILD=1");
1757 #if defined(ANDROID)
1758 mozilla::AndroidBridge::Bridge()->ScheduleRestart();
1760 #if defined(XP_MACOSX)
1761 CommandLineServiceMac::SetupMacCommandLine(gRestartArgc
, gRestartArgv
, PR_TRUE
);
1762 PRUint32 restartMode
= 0;
1763 #if defined(MOZ_ENABLE_LIBXUL)
1764 restartMode
= gRestartMode
;
1766 LaunchChildMac(gRestartArgc
, gRestartArgv
, restartMode
);
1768 nsCOMPtr
<nsILocalFile
> lf
;
1769 nsresult rv
= XRE_GetBinaryPath(gArgv
[0], getter_AddRefs(lf
));
1774 nsAutoString exePath
;
1775 rv
= lf
->GetPath(exePath
);
1779 if (!WinLaunchChild(exePath
.get(), gRestartArgc
, gRestartArgv
))
1780 return NS_ERROR_FAILURE
;
1783 nsCAutoString exePath
;
1784 rv
= lf
->GetNativePath(exePath
);
1788 #if defined(XP_OS2) && (__KLIBC__ == 0 && __KLIBC_MINOR__ >= 6)
1789 // implementation of _execv() is broken with kLibc 0.6.x and later
1790 if (OS2LaunchChild(exePath
.get(), gRestartArgc
, gRestartArgv
) == -1)
1791 return NS_ERROR_FAILURE
;
1792 #elif defined(XP_OS2)
1793 if (_execv(exePath
.get(), gRestartArgv
) == -1)
1794 return NS_ERROR_FAILURE
;
1795 #elif defined(XP_UNIX)
1796 if (execv(exePath
.get(), gRestartArgv
) == -1)
1797 return NS_ERROR_FAILURE
;
1798 #elif defined(XP_BEOS)
1799 extern char **environ
;
1801 res
= resume_thread(load_image(gRestartArgc
,(const char **)gRestartArgv
,(const char **)environ
));
1803 return NS_ERROR_FAILURE
;
1805 PRProcess
* process
= PR_CreateProcess(exePath
.get(), gRestartArgv
,
1807 if (!process
) return NS_ERROR_FAILURE
;
1810 PRStatus failed
= PR_WaitProcess(process
, &exitCode
);
1811 if (failed
|| exitCode
)
1812 return NS_ERROR_FAILURE
;
1813 #endif // XP_OS2 series
1818 return NS_ERROR_LAUNCHED_CHILD_PROCESS
;
1821 static const char kProfileProperties
[] =
1822 "chrome://mozapps/locale/profile/profileSelection.properties";
1825 ProfileLockedDialog(nsILocalFile
* aProfileDir
, nsILocalFile
* aProfileLocalDir
,
1826 nsIProfileUnlocker
* aUnlocker
,
1827 nsINativeAppSupport
* aNative
, nsIProfileLock
* *aResult
)
1831 ScopedXPCOMStartup xpcom
;
1832 rv
= xpcom
.Initialize();
1833 NS_ENSURE_SUCCESS(rv
, rv
);
1835 rv
= xpcom
.SetWindowCreator(aNative
);
1836 NS_ENSURE_SUCCESS(rv
, NS_ERROR_FAILURE
);
1838 { //extra scoping is needed so we release these components before xpcom shutdown
1839 nsCOMPtr
<nsIStringBundleService
> sbs
=
1840 mozilla::services::GetStringBundleService();
1841 NS_ENSURE_TRUE(sbs
, NS_ERROR_FAILURE
);
1843 nsCOMPtr
<nsIStringBundle
> sb
;
1844 sbs
->CreateBundle(kProfileProperties
, getter_AddRefs(sb
));
1845 NS_ENSURE_TRUE_LOG(sbs
, NS_ERROR_FAILURE
);
1847 NS_ConvertUTF8toUTF16
appName(gAppData
->name
);
1848 const PRUnichar
* params
[] = {appName
.get(), appName
.get()};
1850 nsXPIDLString killMessage
;
1852 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"
1853 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"
1855 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"
1856 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"
1859 sb
->FormatStringFromName(aUnlocker
? kRestartUnlocker
: kRestartNoUnlocker
,
1860 params
, 2, getter_Copies(killMessage
));
1862 nsXPIDLString killTitle
;
1863 sb
->FormatStringFromName(NS_LITERAL_STRING("restartTitle").get(),
1864 params
, 1, getter_Copies(killTitle
));
1866 if (!killMessage
|| !killTitle
)
1867 return NS_ERROR_FAILURE
;
1869 nsCOMPtr
<nsIPromptService
> ps
1870 (do_GetService(NS_PROMPTSERVICE_CONTRACTID
));
1871 NS_ENSURE_TRUE(ps
, NS_ERROR_FAILURE
);
1873 PRUint32 flags
= nsIPromptService::BUTTON_TITLE_OK
* nsIPromptService::BUTTON_POS_0
;
1877 nsIPromptService::BUTTON_TITLE_CANCEL
* nsIPromptService::BUTTON_POS_0
+
1878 nsIPromptService::BUTTON_TITLE_IS_STRING
* nsIPromptService::BUTTON_POS_1
+
1879 nsIPromptService::BUTTON_POS_1_DEFAULT
;
1884 rv
= ps
->ConfirmEx(nsnull
, killTitle
, killMessage
, flags
,
1885 killTitle
, nsnull
, nsnull
, nsnull
, &checkState
, &button
);
1886 NS_ENSURE_SUCCESS_LOG(rv
, rv
);
1888 if (button
== 1 && aUnlocker
) {
1889 rv
= aUnlocker
->Unlock(nsIProfileUnlocker::FORCE_QUIT
);
1890 if (NS_FAILED(rv
)) return rv
;
1892 return NS_LockProfilePath(aProfileDir
, aProfileLocalDir
, nsnull
, aResult
);
1895 return NS_ERROR_ABORT
;
1900 ProfileMissingDialog(nsINativeAppSupport
* aNative
)
1904 ScopedXPCOMStartup xpcom
;
1905 rv
= xpcom
.Initialize();
1906 NS_ENSURE_SUCCESS(rv
, rv
);
1908 rv
= xpcom
.SetWindowCreator(aNative
);
1909 NS_ENSURE_SUCCESS(rv
, NS_ERROR_FAILURE
);
1911 { //extra scoping is needed so we release these components before xpcom shutdown
1912 nsCOMPtr
<nsIStringBundleService
> sbs
=
1913 mozilla::services::GetStringBundleService();
1914 NS_ENSURE_TRUE(sbs
, NS_ERROR_FAILURE
);
1916 nsCOMPtr
<nsIStringBundle
> sb
;
1917 sbs
->CreateBundle(kProfileProperties
, getter_AddRefs(sb
));
1918 NS_ENSURE_TRUE_LOG(sbs
, NS_ERROR_FAILURE
);
1920 NS_ConvertUTF8toUTF16
appName(gAppData
->name
);
1921 const PRUnichar
* params
[] = {appName
.get(), appName
.get()};
1923 nsXPIDLString missingMessage
;
1926 static const PRUnichar kMissing
[] = {'p','r','o','f','i','l','e','M','i','s','s','i','n','g','\0'};
1927 sb
->FormatStringFromName(kMissing
, params
, 2, getter_Copies(missingMessage
));
1929 nsXPIDLString missingTitle
;
1930 sb
->FormatStringFromName(NS_LITERAL_STRING("profileMissingTitle").get(),
1931 params
, 1, getter_Copies(missingTitle
));
1933 if (missingMessage
&& missingTitle
) {
1934 nsCOMPtr
<nsIPromptService
> ps
1935 (do_GetService(NS_PROMPTSERVICE_CONTRACTID
));
1936 NS_ENSURE_TRUE(ps
, NS_ERROR_FAILURE
);
1938 ps
->Alert(nsnull
, missingTitle
, missingMessage
);
1941 return NS_ERROR_ABORT
;
1945 static const char kProfileManagerURL
[] =
1946 "chrome://mozapps/content/profile/profileSelection.xul";
1949 ShowProfileManager(nsIToolkitProfileService
* aProfileSvc
,
1950 nsINativeAppSupport
* aNative
)
1954 nsCOMPtr
<nsILocalFile
> profD
, profLD
;
1955 PRUnichar
* profileNamePtr
;
1956 nsCAutoString profileName
;
1959 ScopedXPCOMStartup xpcom
;
1960 rv
= xpcom
.Initialize();
1961 NS_ENSURE_SUCCESS(rv
, rv
);
1963 rv
= xpcom
.SetWindowCreator(aNative
);
1964 NS_ENSURE_SUCCESS(rv
, NS_ERROR_FAILURE
);
1967 CommandLineServiceMac::SetupMacCommandLine(gRestartArgc
, gRestartArgv
, PR_TRUE
);
1971 // we don't have to wait here because profile manager window will pump
1972 // and DDE message will be handled
1973 ProcessDDE(aNative
, PR_FALSE
);
1976 { //extra scoping is needed so we release these components before xpcom shutdown
1977 nsCOMPtr
<nsIWindowWatcher
> windowWatcher
1978 (do_GetService(NS_WINDOWWATCHER_CONTRACTID
));
1979 nsCOMPtr
<nsIDialogParamBlock
> ioParamBlock
1980 (do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID
));
1981 nsCOMPtr
<nsIMutableArray
> dlgArray (do_CreateInstance(NS_ARRAY_CONTRACTID
));
1982 NS_ENSURE_TRUE(windowWatcher
&& ioParamBlock
&& dlgArray
, NS_ERROR_FAILURE
);
1984 ioParamBlock
->SetObjects(dlgArray
);
1986 nsCOMPtr
<nsIAppStartup
> appStartup
1987 (do_GetService(NS_APPSTARTUP_CONTRACTID
));
1988 NS_ENSURE_TRUE(appStartup
, NS_ERROR_FAILURE
);
1990 nsCOMPtr
<nsIDOMWindow
> newWindow
;
1991 rv
= windowWatcher
->OpenWindow(nsnull
,
1994 "centerscreen,chrome,modal,titlebar",
1996 getter_AddRefs(newWindow
));
1998 NS_ENSURE_SUCCESS_LOG(rv
, rv
);
2000 aProfileSvc
->Flush();
2002 PRInt32 dialogConfirmed
;
2003 rv
= ioParamBlock
->GetInt(0, &dialogConfirmed
);
2004 if (NS_FAILED(rv
) || dialogConfirmed
== 0) return NS_ERROR_ABORT
;
2006 nsCOMPtr
<nsIProfileLock
> lock
;
2007 rv
= dlgArray
->QueryElementAt(0, NS_GET_IID(nsIProfileLock
),
2008 getter_AddRefs(lock
));
2009 NS_ENSURE_SUCCESS_LOG(rv
, rv
);
2011 rv
= lock
->GetDirectory(getter_AddRefs(profD
));
2012 NS_ENSURE_SUCCESS(rv
, rv
);
2014 rv
= lock
->GetLocalDirectory(getter_AddRefs(profLD
));
2015 NS_ENSURE_SUCCESS(rv
, rv
);
2017 rv
= ioParamBlock
->GetString(0, &profileNamePtr
);
2018 NS_ENSURE_SUCCESS(rv
, rv
);
2020 CopyUTF16toUTF8(profileNamePtr
, profileName
);
2021 NS_Free(profileNamePtr
);
2027 SaveFileToEnv("XRE_PROFILE_PATH", profD
);
2028 SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", profLD
);
2029 SaveWordToEnv("XRE_PROFILE_NAME", profileName
);
2031 PRBool offline
= PR_FALSE
;
2032 aProfileSvc
->GetStartOffline(&offline
);
2034 SaveToEnv("XRE_START_OFFLINE=1");
2037 return LaunchChild(aNative
);
2041 ImportProfiles(nsIToolkitProfileService
* aPService
,
2042 nsINativeAppSupport
* aNative
)
2046 SaveToEnv("XRE_IMPORT_PROFILES=1");
2048 // try to import old-style profiles
2050 ScopedXPCOMStartup xpcom
;
2051 rv
= xpcom
.Initialize();
2052 if (NS_SUCCEEDED(rv
)) {
2054 CommandLineServiceMac::SetupMacCommandLine(gRestartArgc
, gRestartArgv
, PR_TRUE
);
2057 nsCOMPtr
<nsIProfileMigrator
> migrator
2058 (do_GetService(NS_PROFILEMIGRATOR_CONTRACTID
));
2066 return LaunchChild(aNative
);
2069 // Pick a profile. We need to end up with a profile lock.
2071 // 1) check for -profile <path>
2072 // 2) check for -P <name>
2073 // 3) check for -ProfileManager
2074 // 4) use the default profile, if there is one
2075 // 5) if there are *no* profiles, set up profile-migration
2076 // 6) display the profile-manager UI
2078 static PRBool gDoMigration
= PR_FALSE
;
2081 SelectProfile(nsIProfileLock
* *aResult
, nsINativeAppSupport
* aNative
,
2082 PRBool
* aStartOffline
, nsACString
* aProfileName
)
2088 *aStartOffline
= PR_FALSE
;
2090 ar
= CheckArg("offline", PR_TRUE
);
2091 if (ar
== ARG_BAD
) {
2092 PR_fprintf(PR_STDERR
, "Error: argument -offline is invalid when argument -osint is specified\n");
2093 return NS_ERROR_FAILURE
;
2096 arg
= PR_GetEnv("XRE_START_OFFLINE");
2097 if ((arg
&& *arg
) || ar
)
2098 *aStartOffline
= PR_TRUE
;
2101 nsCOMPtr
<nsILocalFile
> lf
= GetFileFromEnv("XRE_PROFILE_PATH");
2103 nsCOMPtr
<nsILocalFile
> localDir
=
2104 GetFileFromEnv("XRE_PROFILE_LOCAL_PATH");
2109 arg
= PR_GetEnv("XRE_PROFILE_NAME");
2110 if (arg
&& *arg
&& aProfileName
)
2111 aProfileName
->Assign(nsDependentCString(arg
));
2113 // Clear out flags that we handled (or should have handled!) last startup.
2115 CheckArg("p", PR_FALSE
, &dummy
);
2116 CheckArg("profile", PR_FALSE
, &dummy
);
2117 CheckArg("profilemanager");
2119 return NS_LockProfilePath(lf
, localDir
, nsnull
, aResult
);
2122 ar
= CheckArg("migration", PR_TRUE
);
2123 if (ar
== ARG_BAD
) {
2124 PR_fprintf(PR_STDERR
, "Error: argument -migration is invalid when argument -osint is specified\n");
2125 return NS_ERROR_FAILURE
;
2126 } else if (ar
== ARG_FOUND
) {
2127 gDoMigration
= PR_TRUE
;
2130 ar
= CheckArg("profile", PR_TRUE
, &arg
);
2131 if (ar
== ARG_BAD
) {
2132 PR_fprintf(PR_STDERR
, "Error: argument -profile requires a path\n");
2133 return NS_ERROR_FAILURE
;
2136 nsCOMPtr
<nsILocalFile
> lf
;
2137 rv
= XRE_GetFileFromPath(arg
, getter_AddRefs(lf
));
2138 NS_ENSURE_SUCCESS(rv
, rv
);
2140 nsCOMPtr
<nsIProfileUnlocker
> unlocker
;
2142 // Check if the profile path exists and it's a directory.
2144 lf
->Exists(&exists
);
2146 rv
= lf
->Create(nsIFile::DIRECTORY_TYPE
, 0700);
2147 NS_ENSURE_SUCCESS(rv
, rv
);
2150 // If a profile path is specified directory on the command line, then
2151 // assume that the temp directory is the same as the given directory.
2152 rv
= NS_LockProfilePath(lf
, lf
, getter_AddRefs(unlocker
), aResult
);
2153 if (NS_SUCCEEDED(rv
))
2156 return ProfileLockedDialog(lf
, lf
, unlocker
, aNative
, aResult
);
2159 nsCOMPtr
<nsIToolkitProfileService
> profileSvc
;
2160 rv
= NS_NewToolkitProfileService(getter_AddRefs(profileSvc
));
2161 if (rv
== NS_ERROR_FILE_ACCESS_DENIED
)
2162 PR_fprintf(PR_STDERR
, "Error: Access was denied while trying to open files in " \
2163 "your profile directory.\n");
2164 NS_ENSURE_SUCCESS(rv
, rv
);
2166 ar
= CheckArg("createprofile", PR_TRUE
, &arg
);
2167 if (ar
== ARG_BAD
) {
2168 PR_fprintf(PR_STDERR
, "Error: argument -createprofile requires a profile name\n");
2169 return NS_ERROR_FAILURE
;
2172 nsCOMPtr
<nsIToolkitProfile
> profile
;
2174 const char* delim
= strchr(arg
, ' ');
2176 nsCOMPtr
<nsILocalFile
> lf
;
2177 rv
= NS_NewNativeLocalFile(nsDependentCString(delim
+ 1),
2178 PR_TRUE
, getter_AddRefs(lf
));
2179 if (NS_FAILED(rv
)) {
2180 PR_fprintf(PR_STDERR
, "Error: profile path not valid.\n");
2184 // As with -profile, assume that the given path will be used for both the
2185 // main profile directory and the temp profile directory.
2186 rv
= profileSvc
->CreateProfile(lf
, lf
, nsDependentCSubstring(arg
, delim
),
2187 getter_AddRefs(profile
));
2189 rv
= profileSvc
->CreateProfile(nsnull
, nsnull
, nsDependentCString(arg
),
2190 getter_AddRefs(profile
));
2192 // Some pathological arguments can make it this far
2193 if (NS_FAILED(rv
)) {
2194 PR_fprintf(PR_STDERR
, "Error creating profile.\n");
2197 rv
= NS_ERROR_ABORT
;
2198 profileSvc
->Flush();
2200 // XXXben need to ensure prefs.js exists here so the tinderboxes will
2202 nsCOMPtr
<nsILocalFile
> prefsJSFile
;
2203 profile
->GetRootDir(getter_AddRefs(prefsJSFile
));
2204 prefsJSFile
->AppendNative(NS_LITERAL_CSTRING("prefs.js"));
2205 nsCAutoString pathStr
;
2206 prefsJSFile
->GetNativePath(pathStr
);
2207 PR_fprintf(PR_STDERR
, "Success: created profile '%s' at '%s'\n", arg
, pathStr
.get());
2209 prefsJSFile
->Exists(&exists
);
2211 prefsJSFile
->Create(nsIFile::NORMAL_FILE_TYPE
, 0644);
2212 // XXXdarin perhaps 0600 would be better?
2218 rv
= profileSvc
->GetProfileCount(&count
);
2219 NS_ENSURE_SUCCESS(rv
, rv
);
2221 if (gAppData
->flags
& NS_XRE_ENABLE_PROFILE_MIGRATOR
) {
2222 arg
= PR_GetEnv("XRE_IMPORT_PROFILES");
2223 if (!count
&& (!arg
|| !*arg
)) {
2224 return ImportProfiles(profileSvc
, aNative
);
2228 ar
= CheckArg("p", PR_FALSE
, &arg
);
2229 if (ar
== ARG_BAD
) {
2230 ar
= CheckArg("osint");
2231 if (ar
== ARG_FOUND
) {
2232 PR_fprintf(PR_STDERR
, "Error: argument -p is invalid when argument -osint is specified\n");
2233 return NS_ERROR_FAILURE
;
2235 return ShowProfileManager(profileSvc
, aNative
);
2238 ar
= CheckArg("osint");
2239 if (ar
== ARG_FOUND
) {
2240 PR_fprintf(PR_STDERR
, "Error: argument -p is invalid when argument -osint is specified\n");
2241 return NS_ERROR_FAILURE
;
2243 nsCOMPtr
<nsIToolkitProfile
> profile
;
2244 rv
= profileSvc
->GetProfileByName(nsDependentCString(arg
),
2245 getter_AddRefs(profile
));
2246 if (NS_SUCCEEDED(rv
)) {
2247 nsCOMPtr
<nsIProfileUnlocker
> unlocker
;
2248 rv
= profile
->Lock(nsnull
, aResult
);
2249 if (NS_SUCCEEDED(rv
)) {
2251 aProfileName
->Assign(nsDependentCString(arg
));
2255 nsCOMPtr
<nsILocalFile
> profileDir
;
2256 rv
= profile
->GetRootDir(getter_AddRefs(profileDir
));
2257 NS_ENSURE_SUCCESS(rv
, rv
);
2259 nsCOMPtr
<nsILocalFile
> profileLocalDir
;
2260 rv
= profile
->GetLocalDir(getter_AddRefs(profileLocalDir
));
2261 NS_ENSURE_SUCCESS(rv
, rv
);
2263 return ProfileLockedDialog(profileDir
, profileLocalDir
, unlocker
,
2267 return ShowProfileManager(profileSvc
, aNative
);
2270 ar
= CheckArg("profilemanager", PR_TRUE
);
2271 if (ar
== ARG_BAD
) {
2272 PR_fprintf(PR_STDERR
, "Error: argument -profilemanager is invalid when argument -osint is specified\n");
2273 return NS_ERROR_FAILURE
;
2274 } else if (ar
== ARG_FOUND
) {
2275 return ShowProfileManager(profileSvc
, aNative
);
2279 gDoMigration
= PR_TRUE
;
2281 // create a default profile
2282 nsCOMPtr
<nsIToolkitProfile
> profile
;
2283 nsresult rv
= profileSvc
->CreateProfile(nsnull
, // choose a default dir for us
2284 nsnull
, // choose a default dir for us
2285 NS_LITERAL_CSTRING("default"),
2286 getter_AddRefs(profile
));
2287 if (NS_SUCCEEDED(rv
)) {
2288 profileSvc
->Flush();
2289 rv
= profile
->Lock(nsnull
, aResult
);
2290 if (NS_SUCCEEDED(rv
)) {
2292 aProfileName
->Assign(NS_LITERAL_CSTRING("default"));
2298 PRBool useDefault
= PR_TRUE
;
2300 profileSvc
->GetStartWithLastProfile(&useDefault
);
2303 nsCOMPtr
<nsIToolkitProfile
> profile
;
2304 // GetSelectedProfile will auto-select the only profile if there's just one
2305 profileSvc
->GetSelectedProfile(getter_AddRefs(profile
));
2307 nsCOMPtr
<nsIProfileUnlocker
> unlocker
;
2308 rv
= profile
->Lock(getter_AddRefs(unlocker
), aResult
);
2309 if (NS_SUCCEEDED(rv
)) {
2310 // Try to grab the profile name.
2312 rv
= profile
->GetName(*aProfileName
);
2314 aProfileName
->Truncate(0);
2319 nsCOMPtr
<nsILocalFile
> profileDir
;
2320 rv
= profile
->GetRootDir(getter_AddRefs(profileDir
));
2321 NS_ENSURE_SUCCESS(rv
, rv
);
2323 nsCOMPtr
<nsILocalFile
> profileLocalDir
;
2324 rv
= profile
->GetRootDir(getter_AddRefs(profileLocalDir
));
2325 NS_ENSURE_SUCCESS(rv
, rv
);
2327 return ProfileLockedDialog(profileDir
, profileLocalDir
, unlocker
,
2332 return ShowProfileManager(profileSvc
, aNative
);
2336 * Checks the compatibility.ini file to see if we have updated our application
2337 * or otherwise invalidated our caches. If the application has been updated,
2338 * we return PR_FALSE; otherwise, we return PR_TRUE. We also write the status
2339 * of the caches (valid/invalid) into the return param aCachesOK. The aCachesOK
2340 * is always invalid if the application has been updated.
2343 CheckCompatibility(nsIFile
* aProfileDir
, const nsCString
& aVersion
,
2344 const nsCString
& aOSABI
, nsIFile
* aXULRunnerDir
,
2345 nsIFile
* aAppDir
, nsILocalFile
* aFlagFile
,
2348 *aCachesOK
= PR_FALSE
;
2349 nsCOMPtr
<nsIFile
> file
;
2350 aProfileDir
->Clone(getter_AddRefs(file
));
2353 file
->AppendNative(FILE_COMPATIBILITY_INFO
);
2356 nsCOMPtr
<nsILocalFile
> localFile(do_QueryInterface(file
));
2357 nsresult rv
= parser
.Init(localFile
);
2362 rv
= parser
.GetString("Compatibility", "LastVersion", buf
);
2363 if (NS_FAILED(rv
) || !aVersion
.Equals(buf
))
2366 rv
= parser
.GetString("Compatibility", "LastOSABI", buf
);
2367 if (NS_FAILED(rv
) || !aOSABI
.Equals(buf
))
2370 rv
= parser
.GetString("Compatibility", "LastPlatformDir", buf
);
2374 nsCOMPtr
<nsILocalFile
> lf
;
2375 rv
= NS_NewNativeLocalFile(buf
, PR_FALSE
,
2376 getter_AddRefs(lf
));
2381 rv
= lf
->Equals(aXULRunnerDir
, &eq
);
2382 if (NS_FAILED(rv
) || !eq
)
2386 rv
= parser
.GetString("Compatibility", "LastAppDir", buf
);
2390 rv
= NS_NewNativeLocalFile(buf
, PR_FALSE
,
2391 getter_AddRefs(lf
));
2395 rv
= lf
->Equals(aAppDir
, &eq
);
2396 if (NS_FAILED(rv
) || !eq
)
2400 // If we see this flag, caches are invalid.
2401 rv
= parser
.GetString("Compatibility", "InvalidateCaches", buf
);
2402 *aCachesOK
= (NS_FAILED(rv
) || !buf
.EqualsLiteral("1"));
2404 PRBool purgeCaches
= PR_FALSE
;
2406 aFlagFile
->Exists(&purgeCaches
);
2409 *aCachesOK
= !purgeCaches
&& *aCachesOK
;
2413 static void BuildVersion(nsCString
&aBuf
)
2415 aBuf
.Assign(gAppData
->version
);
2417 aBuf
.Append(gAppData
->buildID
);
2419 aBuf
.Append(gToolkitBuildID
);
2423 WriteVersion(nsIFile
* aProfileDir
, const nsCString
& aVersion
,
2424 const nsCString
& aOSABI
, nsIFile
* aXULRunnerDir
,
2427 nsCOMPtr
<nsIFile
> file
;
2428 aProfileDir
->Clone(getter_AddRefs(file
));
2431 file
->AppendNative(FILE_COMPATIBILITY_INFO
);
2433 nsCOMPtr
<nsILocalFile
> lf
= do_QueryInterface(file
);
2435 nsCAutoString platformDir
;
2436 aXULRunnerDir
->GetNativePath(platformDir
);
2438 nsCAutoString appDir
;
2440 aAppDir
->GetNativePath(appDir
);
2442 PRFileDesc
*fd
= nsnull
;
2443 lf
->OpenNSPRFileDesc(PR_WRONLY
| PR_CREATE_FILE
| PR_TRUNCATE
, 0600, &fd
);
2445 NS_ERROR("could not create output stream");
2449 static const char kHeader
[] = "[Compatibility]" NS_LINEBREAK
2452 PR_Write(fd
, kHeader
, sizeof(kHeader
) - 1);
2453 PR_Write(fd
, aVersion
.get(), aVersion
.Length());
2455 static const char kOSABIHeader
[] = NS_LINEBREAK
"LastOSABI=";
2456 PR_Write(fd
, kOSABIHeader
, sizeof(kOSABIHeader
) - 1);
2457 PR_Write(fd
, aOSABI
.get(), aOSABI
.Length());
2459 static const char kPlatformDirHeader
[] = NS_LINEBREAK
"LastPlatformDir=";
2461 PR_Write(fd
, kPlatformDirHeader
, sizeof(kPlatformDirHeader
) - 1);
2462 PR_Write(fd
, platformDir
.get(), platformDir
.Length());
2464 static const char kAppDirHeader
[] = NS_LINEBREAK
"LastAppDir=";
2466 PR_Write(fd
, kAppDirHeader
, sizeof(kAppDirHeader
) - 1);
2467 PR_Write(fd
, appDir
.get(), appDir
.Length());
2470 static const char kNL
[] = NS_LINEBREAK
;
2471 PR_Write(fd
, kNL
, sizeof(kNL
) - 1);
2476 static void RemoveComponentRegistries(nsIFile
* aProfileDir
, nsIFile
* aLocalProfileDir
,
2477 PRBool aRemoveEMFiles
)
2479 nsCOMPtr
<nsIFile
> file
;
2480 aProfileDir
->Clone(getter_AddRefs(file
));
2484 if (aRemoveEMFiles
) {
2485 file
->SetNativeLeafName(NS_LITERAL_CSTRING("extensions.ini"));
2486 file
->Remove(PR_FALSE
);
2489 aLocalProfileDir
->Clone(getter_AddRefs(file
));
2493 file
->AppendNative(NS_LITERAL_CSTRING("XUL" PLATFORM_FASL_SUFFIX
));
2494 file
->Remove(PR_FALSE
);
2496 file
->SetNativeLeafName(NS_LITERAL_CSTRING("XPC" PLATFORM_FASL_SUFFIX
));
2497 file
->Remove(PR_FALSE
);
2499 file
->SetNativeLeafName(NS_LITERAL_CSTRING("startupCache"));
2500 file
->Remove(PR_TRUE
);
2503 // To support application initiated restart via nsIAppStartup.quit, we
2504 // need to save various environment variables, and then restore them
2505 // before re-launching the application.
2511 {"XUL_APP_FILE", nsnull
}
2514 static void SaveStateForAppInitiatedRestart()
2516 for (size_t i
= 0; i
< NS_ARRAY_LENGTH(gSavedVars
); ++i
) {
2517 const char *s
= PR_GetEnv(gSavedVars
[i
].name
);
2519 gSavedVars
[i
].value
= PR_smprintf("%s=%s", gSavedVars
[i
].name
, s
);
2523 static void RestoreStateForAppInitiatedRestart()
2525 for (size_t i
= 0; i
< NS_ARRAY_LENGTH(gSavedVars
); ++i
) {
2526 if (gSavedVars
[i
].value
)
2527 PR_SetEnv(gSavedVars
[i
].value
);
2531 #ifdef MOZ_CRASHREPORTER
2532 // When we first initialize the crash reporter we don't have a profile,
2533 // so we set the minidump path to $TEMP. Once we have a profile,
2534 // we set it to $PROFILE/minidumps, creating the directory
2536 static void MakeOrSetMinidumpPath(nsIFile
* profD
)
2538 nsCOMPtr
<nsIFile
> dumpD
;
2539 nsresult rv
= profD
->Clone(getter_AddRefs(dumpD
));
2543 //XXX: do some more error checking here
2544 dumpD
->Append(NS_LITERAL_STRING("minidumps"));
2545 rv
= dumpD
->Exists(&fileExists
);
2547 dumpD
->Create(nsIFile::DIRECTORY_TYPE
, 0700);
2550 nsAutoString pathStr
;
2551 if(NS_SUCCEEDED(dumpD
->GetPath(pathStr
)))
2552 CrashReporter::SetMinidumpPath(pathStr
);
2557 const nsXREAppData
* gAppData
= nsnull
;
2560 // because we use early returns, we use a stack-based helper to un-set the OS2 FP handler
2561 class ScopedFPHandler
{
2563 EXCEPTIONREGISTRATIONRECORD excpreg
;
2566 ScopedFPHandler() { PR_OS2_SetFloatExcpHandler(&excpreg
); }
2567 ~ScopedFPHandler() { PR_OS2_UnsetFloatExcpHandler(&excpreg
); }
2571 #ifdef MOZ_WIDGET_GTK2
2573 typedef void (*_g_set_application_name_fn
)(const gchar
*application_name
);
2574 typedef void (*_gtk_window_set_auto_startup_notification_fn
)(gboolean setting
);
2576 static PRFuncPtr
FindFunction(const char* aName
)
2578 PRLibrary
*lib
= nsnull
;
2579 PRFuncPtr result
= PR_FindFunctionSymbolAndLibrary(aName
, &lib
);
2580 // Since the library was already loaded, we can safely unload it here.
2582 PR_UnloadLibrary(lib
);
2587 static nsIWidget
* GetMainWidget(nsIDOMWindow
* aWindow
)
2589 // get the native window for this instance
2590 nsCOMPtr
<nsPIDOMWindow
> window(do_QueryInterface(aWindow
));
2591 NS_ENSURE_TRUE(window
, nsnull
);
2593 nsCOMPtr
<nsIBaseWindow
> baseWindow
2594 (do_QueryInterface(window
->GetDocShell()));
2595 NS_ENSURE_TRUE(baseWindow
, nsnull
);
2597 nsCOMPtr
<nsIWidget
> mainWidget
;
2598 baseWindow
->GetMainWidget(getter_AddRefs(mainWidget
));
2602 static nsGTKToolkit
* GetGTKToolkit()
2604 nsCOMPtr
<nsIAppShellService
> svc
= do_GetService(NS_APPSHELLSERVICE_CONTRACTID
);
2607 nsCOMPtr
<nsIDOMWindowInternal
> window
;
2608 svc
->GetHiddenDOMWindow(getter_AddRefs(window
));
2611 nsIWidget
* widget
= GetMainWidget(window
);
2614 nsIToolkit
* toolkit
= widget
->GetToolkit();
2617 return static_cast<nsGTKToolkit
*>(toolkit
);
2620 static void MOZ_gdk_display_close(GdkDisplay
*display
)
2622 // XXX wallpaper for bug 417163: don't close the Display if we're using the
2623 // Qt theme because we crash (in Qt code) when using jemalloc.
2624 PRBool theme_is_qt
= PR_FALSE
;
2625 GtkSettings
* settings
=
2626 gtk_settings_get_for_screen(gdk_display_get_default_screen(display
));
2628 g_object_get(settings
, "gtk-theme-name", &theme_name
, NULL
);
2630 theme_is_qt
= strcmp(theme_name
, "Qt") == 0;
2632 NS_WARNING("wallpaper bug 417163 for Qt theme");
2636 // gdk_display_close was broken prior to gtk+-2.10.0.
2637 // (http://bugzilla.gnome.org/show_bug.cgi?id=85715)
2638 // gdk_display_manager_set_default_display (gdk_display_manager_get(), NULL)
2640 if (gtk_check_version(2,10,0) != NULL
) {
2642 // Version check failed - broken gdk_display_close.
2644 // Let the gdk structures leak but at least close the Display,
2645 // assuming that gdk will not use it again.
2646 Display
* dpy
= GDK_DISPLAY_XDISPLAY(display
);
2650 gdk_display_close(display
);
2651 #endif /* MOZ_X11 */
2655 // Get a (new) Pango context that holds a reference to the fontmap that
2656 // GTK has been using. gdk_pango_context_get() must be called while GTK
2657 // has a default display.
2658 PangoContext
*pangoContext
= gdk_pango_context_get();
2661 PRBool buggyCairoShutdown
= cairo_version() < CAIRO_VERSION_ENCODE(1, 4, 0);
2663 if (!buggyCairoShutdown
) {
2664 // We should shut down GDK before we shut down libraries it depends on
2665 // like Pango and cairo. But if cairo shutdown is buggy, we should
2666 // shut down cairo first otherwise it may crash because of dangling
2667 // references to Display objects (see bug 469831).
2669 gdk_display_close(display
);
2673 // This doesn't take a reference.
2674 PangoFontMap
*fontmap
= pango_context_get_font_map(pangoContext
);
2675 // Do some shutdown of the fontmap, which releases the fonts, clearing a
2676 // bunch of circular references from the fontmap through the fonts back to
2677 // itself. The shutdown that this does is much less than what's done by
2678 // the fontmap's finalize, though.
2679 if (PANGO_IS_FC_FONT_MAP(fontmap
))
2680 pango_fc_font_map_shutdown(PANGO_FC_FONT_MAP(fontmap
));
2681 g_object_unref(pangoContext
);
2682 // PangoCairo still holds a reference to the fontmap.
2683 // Now that we have finished with GTK and Pango, we could unref fontmap,
2684 // which would allow us to call FcFini, but removing what is really
2685 // Pango's ref feels a bit evil. Pango-1.22 will have support for
2686 // pango_cairo_font_map_set_default(NULL), which would release the
2687 // reference on the old fontmap.
2689 #if GTK_CHECK_VERSION(2,8,0)
2690 // cairo_debug_reset_static_data() is prototyped through cairo.h included
2692 #ifdef cairo_debug_reset_static_data
2693 #error "Looks like we're including Mozilla's cairo instead of system cairo"
2695 cairo_debug_reset_static_data();
2697 #endif // CLEANUP_MEMORY
2699 if (buggyCairoShutdown
) {
2701 gdk_display_close(display
);
2705 #endif // MOZ_WIDGET_GTK2
2708 * NSPR will search for the "nspr_use_zone_allocator" symbol throughout
2709 * the process and use it to determine whether the application defines its own
2710 * memory allocator or not.
2712 * Since most applications (e.g. Firefox and Thunderbird) don't use any special
2713 * allocators and therefore don't define this symbol, NSPR must search the
2714 * entire process, which reduces startup performance.
2716 * By defining the symbol here, we can avoid the wasted lookup and hopefully
2717 * improve startup performance.
2719 NS_VISIBILITY_DEFAULT PRBool nspr_use_zone_allocator
= PR_FALSE
;
2721 #ifdef MOZ_SPLASHSCREEN
2722 #define MOZ_SPLASHSCREEN_UPDATE(_i) do { if (splashScreen) splashScreen->Update(_i); } while(0)
2724 #define MOZ_SPLASHSCREEN_UPDATE(_i) do { } while(0)
2727 #ifdef CAIRO_HAS_DWRITE_FONT
2731 typedef HRESULT (WINAPI
*DWriteCreateFactoryFunc
)(
2732 __in DWRITE_FACTORY_TYPE factoryType
,
2734 __out IUnknown
**factory
2737 #ifdef DEBUG_DWRITE_STARTUP
2739 #define LOGREGISTRY(msg) LogRegistryEvent(msg)
2741 // for use when monitoring process
2742 static void LogRegistryEvent(const wchar_t *msg
)
2748 wsprintf(buf
, L
" log %s", msg
);
2749 hr
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
, buf
, 0, KEY_READ
, &dummyKey
);
2750 if (SUCCEEDED(hr
)) {
2751 RegCloseKey(dummyKey
);
2756 #define LOGREGISTRY(msg)
2760 static DWORD
InitDwriteBG(LPVOID lpdwThreadParam
)
2762 SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_BEGIN
);
2763 LOGREGISTRY(L
"loading dwrite.dll");
2764 HMODULE dwdll
= LoadLibraryW(L
"dwrite.dll");
2765 DWriteCreateFactoryFunc createDWriteFactory
= (DWriteCreateFactoryFunc
)
2766 GetProcAddress(dwdll
, "DWriteCreateFactory");
2767 if (createDWriteFactory
) {
2768 LOGREGISTRY(L
"creating dwrite factory");
2769 IDWriteFactory
*factory
;
2770 HRESULT hr
= createDWriteFactory(
2771 DWRITE_FACTORY_TYPE_SHARED
,
2772 __uuidof(IDWriteFactory
),
2773 reinterpret_cast<IUnknown
**>(&factory
));
2775 LOGREGISTRY(L
"dwrite factory done");
2777 LOGREGISTRY(L
"freed factory");
2779 SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_END
);
2784 PRTime gXRE_mainTimestamp
= 0;
2787 XRE_main(int argc
, char* argv
[], const nsXREAppData
* aAppData
)
2791 gXRE_mainTimestamp
= PR_Now();
2793 #ifdef MOZ_SPLASHSCREEN
2794 nsSplashScreen
*splashScreen
= nsnull
;
2799 NS_TIMELINE_MARK("enter main");
2802 if (PR_GetEnv("XRE_MAIN_BREAK"))
2806 SetupErrorHandling(argv
[0]);
2808 #ifdef CAIRO_HAS_DWRITE_FONT
2810 // Bug 602792 - when DWriteCreateFactory is called the dwrite client dll
2811 // starts the FntCache service if it isn't already running (it's set
2812 // to manual startup by default in Windows 7 RTM). Subsequent DirectWrite
2813 // calls cause the IDWriteFactory object to communicate with the FntCache
2814 // service with a timeout; if there's no response after the timeout, the
2815 // DirectWrite client library will assume the service isn't around and do
2816 // manual font file I/O on _all_ system fonts. To avoid this, load the
2817 // dwrite library and create a factory as early as possible so that the
2818 // FntCache service is ready by the time it's needed.
2820 OSVERSIONINFO vinfo
;
2821 vinfo
.dwOSVersionInfoSize
= sizeof(vinfo
);
2822 if (GetVersionEx(&vinfo
) && vinfo
.dwMajorVersion
>= 6) {
2823 CreateThread(NULL
, 0, (LPTHREAD_START_ROUTINE
)&InitDwriteBG
, NULL
, 0, NULL
);
2829 const char *home
= PR_GetEnv("HOME");
2830 if (!home
|| !*home
) {
2831 struct passwd
*pw
= getpwuid(geteuid());
2832 if (!pw
|| !pw
->pw_dir
) {
2833 Output(PR_TRUE
, "Could not determine HOME directory");
2836 SaveWordToEnv("HOME", nsDependentCString(pw
->pw_dir
));
2840 #ifdef MOZ_ACCESSIBILITY_ATK
2841 // Reset GTK_MODULES, strip atk-bridge if exists
2842 // Mozilla will load libatk-bridge.so later if necessary
2843 const char* gtkModules
= PR_GetEnv("GTK_MODULES");
2844 if (gtkModules
&& *gtkModules
) {
2845 nsCString
gtkModulesStr(gtkModules
);
2846 gtkModulesStr
.ReplaceSubstring("atk-bridge", "");
2847 char* expr
= PR_smprintf("GTK_MODULES=%s", gtkModulesStr
.get());
2850 // We intentionally leak |expr| here since it is required by PR_SetEnv.
2853 // Suppress atk-bridge init at startup, it works after GNOME 2.24.2
2854 PR_SetEnv("NO_AT_BRIDGE=1");
2860 NS_ENSURE_TRUE(aAppData
, 2);
2863 // The xulrunner stub executable tricks CFBundleGetMainBundle on
2864 // purpose into lying about the main bundle path. It will set
2865 // XRE_BINARY_PATH to inform us of our real location.
2866 gBinaryPath
= getenv("XRE_BINARY_PATH");
2868 if (gBinaryPath
&& !*gBinaryPath
)
2869 gBinaryPath
= nsnull
;
2872 // Check for application.ini overrides
2873 const char* override
= nsnull
;
2874 ar
= CheckArg("override", PR_TRUE
, &override
);
2875 if (ar
== ARG_BAD
) {
2876 Output(PR_TRUE
, "Incorrect number of arguments passed to -override");
2879 else if (ar
== ARG_FOUND
) {
2880 nsCOMPtr
<nsILocalFile
> overrideLF
;
2881 rv
= XRE_GetFileFromPath(override
, getter_AddRefs(overrideLF
));
2882 if (NS_FAILED(rv
)) {
2883 Output(PR_TRUE
, "Error: unrecognized override.ini path.\n");
2887 nsXREAppData
* overrideAppData
= const_cast<nsXREAppData
*>(aAppData
);
2888 rv
= XRE_ParseAppData(overrideLF
, overrideAppData
);
2889 if (NS_FAILED(rv
)) {
2890 Output(PR_TRUE
, "Couldn't read override.ini");
2895 ScopedAppData
appData(aAppData
);
2896 gAppData
= &appData
;
2898 // Check sanity and correctness of app data.
2900 if (!appData
.name
) {
2901 Output(PR_TRUE
, "Error: App:Name not specified in application.ini\n");
2904 if (!appData
.buildID
) {
2905 Output(PR_TRUE
, "Error: App:BuildID not specified in application.ini\n");
2909 #ifdef MOZ_SPLASHSCREEN
2910 // check to see if we need to do a splash screen
2911 PRBool wantsSplash
= PR_TRUE
;
2912 PRBool isNoSplash
= (CheckArg("nosplash", PR_FALSE
, NULL
, PR_FALSE
) == ARG_FOUND
);
2913 isNoSplash
|= (PR_GetEnv("NO_SPLASH") != 0);
2914 PRBool isNoRemote
= (CheckArg("no-remote", PR_FALSE
, NULL
, PR_FALSE
) == ARG_FOUND
);
2917 // synchronize startup; if it looks like we're going to have to
2918 // wait, then open up a splash screen
2919 WindowsMutex
winStartupMutex(L
"FirefoxStartupMutex");
2921 // try to lock the mutex, but only wait 100ms to do so
2922 PRBool needsMutexLock
= ! winStartupMutex
.Lock(100);
2924 // If we failed to lock the mutex quickly, then we'll want
2925 // a splash screen for sure.
2927 // If we did manage to lock it, then we'll only want one
2928 // a splash screen if there is no existing message window;
2929 // that is, if we are the first instance of the app.
2930 if (!needsMutexLock
&& !isNoRemote
) {
2931 // check to see if there's a remote firefox up
2932 static PRUnichar classNameBuffer
[128];
2933 _snwprintf(classNameBuffer
, sizeof(classNameBuffer
) / sizeof(PRUnichar
),
2935 gAppData
->name
, L
"MessageWindow");
2936 HANDLE h
= FindWindowW(classNameBuffer
, 0);
2938 // Someone else has the window, and we were able to grab the mutex,
2939 // meaning the other instance ahs presumably already finished starting
2940 // up by now. So no need for a splash screen.
2941 wantsSplash
= PR_FALSE
;
2944 // We couldn't find another window, and we were able to lock the mutex;
2945 // we're likely the first instance starting up, so make sure a splash
2946 // screen gets thrown up.
2947 wantsSplash
= PR_TRUE
;
2952 if (wantsSplash
&& !isNoSplash
)
2953 splashScreen
= nsSplashScreen::GetOrCreate();
2956 splashScreen
->Open();
2959 // Now that the splash screen is open, wait indefinitely
2960 // for the startup mutex on this thread if we need to.
2962 winStartupMutex
.Lock();
2965 #endif //MOZ_SPLASHSCREEN
2970 if (!appData
.xreDirectory
) {
2971 nsCOMPtr
<nsILocalFile
> lf
;
2972 rv
= XRE_GetBinaryPath(gArgv
[0], getter_AddRefs(lf
));
2976 nsCOMPtr
<nsIFile
> greDir
;
2977 rv
= lf
->GetParent(getter_AddRefs(greDir
));
2981 rv
= CallQueryInterface(greDir
, &appData
.xreDirectory
);
2986 if (appData
.size
> offsetof(nsXREAppData
, minVersion
)) {
2987 if (!appData
.minVersion
) {
2988 Output(PR_TRUE
, "Error: Gecko:MinVersion not specified in application.ini\n");
2992 if (!appData
.maxVersion
) {
2993 // If no maxVersion is specified, we assume the app is only compatible
2994 // with the initial preview release. Do not increment this number ever!
2995 SetAllocatedString(appData
.maxVersion
, "1.*");
2998 if (NS_CompareVersions(appData
.minVersion
, gToolkitVersion
) > 0 ||
2999 NS_CompareVersions(appData
.maxVersion
, gToolkitVersion
) < 0) {
3000 Output(PR_TRUE
, "Error: Platform version '%s' is not compatible with\n"
3001 "minVersion >= %s\nmaxVersion <= %s\n",
3003 appData
.minVersion
, appData
.maxVersion
);
3008 nsXREDirProvider dirProvider
;
3009 rv
= dirProvider
.Initialize(gAppData
->directory
, gAppData
->xreDirectory
);
3013 #ifdef MOZ_CRASHREPORTER
3014 const char* crashreporterEnv
= PR_GetEnv("MOZ_CRASHREPORTER");
3015 if (crashreporterEnv
&& *crashreporterEnv
) {
3016 appData
.flags
|= NS_XRE_ENABLE_CRASH_REPORTER
;
3019 if ((appData
.flags
& NS_XRE_ENABLE_CRASH_REPORTER
) &&
3021 CrashReporter::SetExceptionHandler(appData
.xreDirectory
))) {
3022 if (appData
.crashReporterURL
)
3023 CrashReporter::SetServerURL(nsDependentCString(appData
.crashReporterURL
));
3025 // pass some basic info from the app data
3027 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Vendor"),
3028 nsDependentCString(appData
.vendor
));
3030 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ProductName"),
3031 nsDependentCString(appData
.name
));
3032 if (appData
.version
)
3033 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Version"),
3034 nsDependentCString(appData
.version
));
3035 if (appData
.buildID
)
3036 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("BuildID"),
3037 nsDependentCString(appData
.buildID
));
3038 CrashReporter::SetRestartArgs(argc
, argv
);
3040 // annotate other data (user id etc)
3041 nsCOMPtr
<nsILocalFile
> userAppDataDir
;
3042 if (NS_SUCCEEDED(dirProvider
.GetUserAppDataDirectory(
3043 getter_AddRefs(userAppDataDir
)))) {
3044 CrashReporter::SetupExtraData(userAppDataDir
,
3045 nsDependentCString(appData
.buildID
));
3047 // see if we have a crashreporter-override.ini in the application directory
3048 nsCOMPtr
<nsIFile
> overrideini
;
3050 static char overrideEnv
[MAXPATHLEN
];
3051 if (NS_SUCCEEDED(dirProvider
.GetAppDir()->Clone(getter_AddRefs(overrideini
))) &&
3052 NS_SUCCEEDED(overrideini
->AppendNative(NS_LITERAL_CSTRING("crashreporter-override.ini"))) &&
3053 NS_SUCCEEDED(overrideini
->Exists(&exists
)) &&
3056 nsAutoString overridePathW
;
3057 overrideini
->GetPath(overridePathW
);
3058 NS_ConvertUTF16toUTF8
overridePath(overridePathW
);
3060 nsCAutoString overridePath
;
3061 overrideini
->GetNativePath(overridePath
);
3064 sprintf(overrideEnv
, "MOZ_CRASHREPORTER_STRINGS_OVERRIDE=%s",
3065 overridePath
.get());
3066 PR_SetEnv(overrideEnv
);
3073 if (PR_GetEnv("MOZ_LAUNCHED_CHILD")) {
3074 // This is needed, on relaunch, to force the OS to use the "Cocoa Dock
3075 // API". Otherwise the call to ReceiveNextEvent() below will make it
3076 // use the "Carbon Dock API". For more info see bmo bug 377166.
3077 EnsureUseCocoaDockAPI();
3079 // When the app relaunches, the original process exits. This causes
3080 // the dock tile to stop bouncing, lose the "running" triangle, and
3081 // if the tile does not permanently reside in the Dock, even disappear.
3082 // This can be confusing to the user, who is expecting the app to launch.
3083 // Calling ReceiveNextEvent without requesting any event is enough to
3084 // cause a dock tile for the child process to appear.
3085 const EventTypeSpec kFakeEventList
[] = { { INT_MAX
, INT_MAX
} };
3087 ::ReceiveNextEvent(GetEventTypeCount(kFakeEventList
), kFakeEventList
,
3088 kEventDurationNoWait
, PR_FALSE
, &event
);
3091 if (CheckArg("foreground")) {
3092 // The original process communicates that it was in the foreground by
3093 // adding this argument. This new process, which is taking over for
3094 // the old one, should make itself the active application.
3095 ProcessSerialNumber psn
;
3096 if (::GetCurrentProcess(&psn
) == noErr
)
3097 ::SetFrontProcess(&psn
);
3101 SaveToEnv("MOZ_LAUNCHED_CHILD=");
3103 gRestartArgc
= gArgc
;
3104 gRestartArgv
= (char**) malloc(sizeof(char*) * (gArgc
+ 1 + (override
? 2 : 0)));
3105 if (!gRestartArgv
) return 1;
3108 for (i
= 0; i
< gArgc
; ++i
) {
3109 gRestartArgv
[i
] = gArgv
[i
];
3112 // Add the -override argument back (it is removed automatically be CheckArg) if there is one
3114 gRestartArgv
[gRestartArgc
++] = const_cast<char*>("-override");
3115 gRestartArgv
[gRestartArgc
++] = const_cast<char*>(override
);
3118 gRestartArgv
[gRestartArgc
] = nsnull
;
3122 PRBool
StartOS2App(int aArgc
, char **aArgv
);
3123 if (!StartOS2App(gArgc
, gArgv
))
3125 ScopedFPHandler handler
;
3128 if (PR_GetEnv("MOZ_SAFE_MODE_RESTART")) {
3129 gSafeMode
= PR_TRUE
;
3130 // unset the env variable
3131 PR_SetEnv("MOZ_SAFE_MODE_RESTART=");
3134 ar
= CheckArg("safe-mode", PR_TRUE
);
3135 if (ar
== ARG_BAD
) {
3136 PR_fprintf(PR_STDERR
, "Error: argument -safe-mode is invalid when argument -osint is specified\n");
3138 } else if (ar
== ARG_FOUND
) {
3139 gSafeMode
= PR_TRUE
;
3143 // If the shift key is pressed and the ctrl and / or alt keys are not pressed
3144 // during startup start in safe mode. GetKeyState returns a short and the high
3145 // order bit will be 1 if the key is pressed. By masking the returned short
3146 // with 0x8000 the result will be 0 if the key is not pressed and non-zero
3148 if (GetKeyState(VK_SHIFT
) & 0x8000 &&
3149 !(GetKeyState(VK_CONTROL
) & 0x8000) && !(GetKeyState(VK_MENU
) & 0x8000)) {
3150 gSafeMode
= PR_TRUE
;
3155 if (GetCurrentEventKeyModifiers() & optionKey
)
3156 gSafeMode
= PR_TRUE
;
3159 // Handle -no-remote command line argument. Setup the environment to
3160 // better accommodate other components and various restart scenarios.
3161 ar
= CheckArg("no-remote", PR_TRUE
);
3162 if (ar
== ARG_BAD
) {
3163 PR_fprintf(PR_STDERR
, "Error: argument -a requires an application name\n");
3165 } else if (ar
== ARG_FOUND
) {
3166 SaveToEnv("MOZ_NO_REMOTE=1");
3169 // Handle -help and -version command line arguments.
3170 // They should return quickly, so we deal with them here.
3171 if (CheckArg("h") || CheckArg("help") || CheckArg("?")) {
3176 if (CheckArg("v") || CheckArg("version")) {
3181 #ifdef NS_TRACE_MALLOC
3182 gArgc
= argc
= NS_TraceMallocStartupArgs(gArgc
, gArgv
);
3185 MOZ_SPLASHSCREEN_UPDATE(20);
3187 rv
= XRE_InitCommandLine(gArgc
, gArgv
);
3188 NS_ENSURE_SUCCESS(rv
, 1);
3191 // Check for -register, which registers chrome and then exits immediately.
3192 ar
= CheckArg("register", PR_TRUE
);
3193 if (ar
== ARG_BAD
) {
3194 PR_fprintf(PR_STDERR
, "Error: argument -register is invalid when argument -osint is specified\n");
3196 } else if (ar
== ARG_FOUND
) {
3197 ScopedXPCOMStartup xpcom
;
3198 rv
= xpcom
.Initialize();
3199 NS_ENSURE_SUCCESS(rv
, 1);
3202 nsCOMPtr
<nsIChromeRegistry
> chromeReg
=
3203 mozilla::services::GetChromeRegistryService();
3204 NS_ENSURE_TRUE(chromeReg
, 1);
3206 chromeReg
->CheckForNewChrome();
3211 #if defined(MOZ_WIDGET_GTK2) || defined(MOZ_ENABLE_XREMOTE)
3212 // Stash DESKTOP_STARTUP_ID in malloc'ed memory because gtk_init will clear it.
3213 #define HAVE_DESKTOP_STARTUP_ID
3214 const char* desktopStartupIDEnv
= PR_GetEnv("DESKTOP_STARTUP_ID");
3215 nsCAutoString desktopStartupID
;
3216 if (desktopStartupIDEnv
) {
3217 desktopStartupID
.Assign(desktopStartupIDEnv
);
3221 #if defined(MOZ_WIDGET_QT)
3222 const char* qgraphicssystemARG
= NULL
;
3223 ar
= CheckArg("graphicssystem", PR_TRUE
, &qgraphicssystemARG
, PR_FALSE
);
3224 if (ar
== ARG_FOUND
)
3225 PR_SetEnv(PR_smprintf("MOZ_QT_GRAPHICSSYSTEM=%s", qgraphicssystemARG
));
3227 QScopedPointer
<QApplication
> app(new QApplication(gArgc
, gArgv
));
3229 #if MOZ_PLATFORM_MAEMO > 5
3230 if (XRE_GetProcessType() == GeckoProcessType_Default
) {
3231 // try to get the MInputContext if possible to support the MeeGo VKB
3232 QInputContext
* inputContext
= app
->inputContext();
3233 if (inputContext
&& inputContext
->identifierName() != "MInputContext") {
3234 QInputContext
* context
= QInputContextFactory::create("MInputContext",
3237 app
->setInputContext(context
);
3241 QStringList nonQtArguments
= app
->arguments();
3243 gQtOnlyArgv
= (char**) malloc(sizeof(char*)
3244 * (gRestartArgc
- nonQtArguments
.size() + 2));
3247 gQtOnlyArgv
[0] = gRestartArgv
[0];
3249 for (int i
= 1; i
< gRestartArgc
; ++i
) {
3250 if (!nonQtArguments
.contains(gRestartArgv
[i
])) {
3251 // copy arguments used by Qt for later
3252 gQtOnlyArgv
[gQtOnlyArgc
++] = gRestartArgv
[i
];
3255 gQtOnlyArgv
[gQtOnlyArgc
] = nsnull
;
3257 #if defined(MOZ_WIDGET_GTK2)
3259 // Disable the slice allocator, since jemalloc already uses similar layout
3260 // algorithms, and using a sub-allocator tends to increase fragmentation.
3261 // This must be done before g_thread_init() is called.
3262 g_slice_set_config(G_SLICE_CONFIG_ALWAYS_MALLOC
, 1);
3264 g_thread_init(NULL
);
3265 // setup for private colormap. Ideally we'd like to do this
3266 // in nsAppShell::Create, but we need to get in before gtk
3267 // has been initialized to make sure everything is running
3269 if (CheckArg("install"))
3270 gdk_rgb_set_install(TRUE
);
3272 // Initialize GTK here for splash.
3274 // Open the display ourselves instead of using gtk_init, so that we can
3275 // close it without fear that one day gtk might clean up the display it
3277 if (!gtk_parse_args(&gArgc
, &gArgv
))
3280 // display_name is owned by gdk.
3281 const char *display_name
= gdk_get_display_arg_name();
3283 SaveWordToEnv("DISPLAY", nsDependentCString(display_name
));
3285 display_name
= PR_GetEnv("DISPLAY");
3286 if (!display_name
) {
3287 PR_fprintf(PR_STDERR
, "Error: no display specified\n");
3291 #endif /* MOZ_WIDGET_GTK2 */
3293 #ifdef MOZ_ENABLE_XREMOTE
3294 // handle -remote now that xpcom is fired up
3296 const char* xremotearg
;
3297 ar
= CheckArg("remote", PR_TRUE
, &xremotearg
);
3298 if (ar
== ARG_BAD
) {
3299 PR_fprintf(PR_STDERR
, "Error: -remote requires an argument\n");
3302 const char* desktopStartupIDPtr
=
3303 desktopStartupID
.IsEmpty() ? nsnull
: desktopStartupID
.get();
3305 return HandleRemoteArgument(xremotearg
, desktopStartupIDPtr
);
3308 if (!PR_GetEnv("MOZ_NO_REMOTE")) {
3309 // Try to remote the entire command line. If this fails, start up normally.
3310 RemoteResult rr
= RemoteCommandLine(desktopStartupIDPtr
);
3311 if (rr
== REMOTE_FOUND
)
3313 else if (rr
== REMOTE_ARG_BAD
)
3318 #if defined(MOZ_WIDGET_GTK2)
3319 GdkDisplay
* display
= nsnull
;
3320 display
= gdk_display_open(display_name
);
3322 PR_fprintf(PR_STDERR
, "Error: cannot open display: %s\n", display_name
);
3325 gdk_display_manager_set_default_display (gdk_display_manager_get(),
3328 // g_set_application_name () is only defined in glib2.2 and higher.
3329 _g_set_application_name_fn _g_set_application_name
=
3330 (_g_set_application_name_fn
)FindFunction("g_set_application_name");
3331 if (_g_set_application_name
) {
3332 _g_set_application_name(gAppData
->name
);
3334 _gtk_window_set_auto_startup_notification_fn _gtk_window_set_auto_startup_notification
=
3335 (_gtk_window_set_auto_startup_notification_fn
)FindFunction("gtk_window_set_auto_startup_notification");
3336 if (_gtk_window_set_auto_startup_notification
) {
3337 _gtk_window_set_auto_startup_notification(PR_FALSE
);
3340 gtk_widget_set_default_colormap(gdk_rgb_get_colormap());
3341 #endif /* MOZ_WIDGET_GTK2 */
3343 // Do this after initializing GDK, or GDK will install its own handler.
3344 InstallX11ErrorHandler();
3347 // Call the code to install our handler
3349 setupProfilingStuff();
3352 // Try to allocate "native app support."
3353 nsCOMPtr
<nsINativeAppSupport
> nativeApp
;
3354 rv
= NS_CreateNativeAppSupport(getter_AddRefs(nativeApp
));
3358 PRBool canRun
= PR_FALSE
;
3359 rv
= nativeApp
->Start(&canRun
);
3360 if (NS_FAILED(rv
) || !canRun
) {
3364 #if defined(MOZ_UPDATER) && !defined(ANDROID)
3365 // Check for and process any available updates
3366 nsCOMPtr
<nsIFile
> updRoot
;
3368 rv
= dirProvider
.GetFile(XRE_UPDATE_ROOT_DIR
, &persistent
,
3369 getter_AddRefs(updRoot
));
3370 // XRE_UPDATE_ROOT_DIR may fail. Fallback to appDir if failed
3372 updRoot
= dirProvider
.GetAppDir();
3374 // Support for processing an update and exiting. The MOZ_PROCESS_UPDATES
3375 // environment variable will be part of the updater's environment and the
3376 // application that is relaunched by the updater. When the application is
3377 // relaunched by the updater it will be removed below and the application
3379 if (CheckArg("process-updates")) {
3380 SaveToEnv("MOZ_PROCESS_UPDATES=1");
3382 ProcessUpdates(dirProvider
.GetGREDir(),
3383 dirProvider
.GetAppDir(),
3388 if (PR_GetEnv("MOZ_PROCESS_UPDATES")) {
3389 PR_SetEnv("MOZ_PROCESS_UPDATES=");
3394 nsCOMPtr
<nsIProfileLock
> profileLock
;
3395 PRBool startOffline
= PR_FALSE
;
3396 nsCAutoString profileName
;
3398 rv
= SelectProfile(getter_AddRefs(profileLock
), nativeApp
, &startOffline
,
3400 if (rv
== NS_ERROR_LAUNCHED_CHILD_PROCESS
||
3401 rv
== NS_ERROR_ABORT
) return 0;
3403 if (NS_FAILED(rv
)) {
3404 // We failed to choose or create profile - notify user and quit
3405 ProfileMissingDialog(nativeApp
);
3409 nsCOMPtr
<nsILocalFile
> profD
;
3410 rv
= profileLock
->GetDirectory(getter_AddRefs(profD
));
3411 NS_ENSURE_SUCCESS(rv
, 1);
3413 nsCOMPtr
<nsILocalFile
> profLD
;
3414 rv
= profileLock
->GetLocalDirectory(getter_AddRefs(profLD
));
3415 NS_ENSURE_SUCCESS(rv
, 1);
3417 rv
= dirProvider
.SetProfile(profD
, profLD
);
3418 NS_ENSURE_SUCCESS(rv
, 1);
3420 #if defined(WINCE) && defined(MOZ_SPLASHSCREEN)
3421 // give up the mutex, let other app startups happen
3422 winStartupMutex
.Unlock();
3425 //////////////////////// NOW WE HAVE A PROFILE ////////////////////////
3427 #ifdef MOZ_CRASHREPORTER
3428 if (appData
.flags
& NS_XRE_ENABLE_CRASH_REPORTER
)
3429 MakeOrSetMinidumpPath(profD
);
3432 nsCAutoString version
;
3433 BuildVersion(version
);
3435 #ifdef TARGET_OS_ABI
3436 NS_NAMED_LITERAL_CSTRING(osABI
, TARGET_OS_ABI
);
3438 // No TARGET_XPCOM_ABI, but at least the OS is known
3439 NS_NAMED_LITERAL_CSTRING(osABI
, OS_TARGET
"_UNKNOWN");
3442 // Check for version compatibility with the last version of the app this
3443 // profile was started with. The format of the version stamp is defined
3444 // by the BuildVersion function.
3445 // Also check to see if something has happened to invalidate our
3446 // fastload caches, like an extension upgrade or installation.
3448 // If we see .purgecaches, that means someone did a make.
3449 // Re-register components to catch potential changes.
3450 // We only offer this in debug builds, though.
3451 nsCOMPtr
<nsILocalFile
> flagFile
;
3453 rv
= NS_ERROR_FILE_NOT_FOUND
;
3454 nsCOMPtr
<nsIFile
> fFlagFile
;
3455 if (gAppData
->directory
) {
3456 rv
= gAppData
->directory
->Clone(getter_AddRefs(fFlagFile
));
3458 flagFile
= do_QueryInterface(fFlagFile
);
3460 flagFile
->AppendNative(FILE_INVALIDATE_CACHES
);
3464 PRBool versionOK
= CheckCompatibility(profD
, version
, osABI
,
3465 dirProvider
.GetGREDir(),
3466 gAppData
->directory
, flagFile
,
3468 if (CheckArg("purgecaches")) {
3469 cachesOK
= PR_FALSE
;
3471 if (PR_GetEnv("MOZ_PURGE_CACHES")) {
3472 cachesOK
= PR_FALSE
;
3475 // Every time a profile is loaded by a build with a different version,
3476 // it updates the compatibility.ini file saying what version last wrote
3477 // the fastload caches. On subsequent launches if the version matches,
3478 // there is no need for re-registration. If the user loads the same
3479 // profile in different builds the component registry must be
3480 // re-generated to prevent mysterious component loading failures.
3483 RemoveComponentRegistries(profD
, profLD
, PR_FALSE
);
3484 WriteVersion(profD
, NS_LITERAL_CSTRING("Safe Mode"), osABI
,
3485 dirProvider
.GetGREDir(), gAppData
->directory
);
3487 else if (versionOK
) {
3489 // Remove caches, forcing component re-registration.
3490 // The new list of additional components directories is derived from
3491 // information in "extensions.ini".
3492 RemoveComponentRegistries(profD
, profLD
, PR_FALSE
);
3494 // Rewrite compatibility.ini to remove the flag
3495 WriteVersion(profD
, version
, osABI
,
3496 dirProvider
.GetGREDir(), gAppData
->directory
);
3498 // Nothing need be done for the normal startup case.
3501 // Remove caches, forcing component re-registration
3502 // with the default set of components (this disables any potentially
3503 // troublesome incompatible XPCOM components).
3504 RemoveComponentRegistries(profD
, profLD
, PR_TRUE
);
3506 // Write out version
3507 WriteVersion(profD
, version
, osABI
,
3508 dirProvider
.GetGREDir(), gAppData
->directory
);
3512 flagFile
->Remove(PR_TRUE
);
3515 PRBool appInitiatedRestart
= PR_FALSE
;
3517 MOZ_SPLASHSCREEN_UPDATE(30);
3519 NS_TIME_FUNCTION_MARK("Next: ScopedXPCOMStartup");
3521 NS_TIME_FUNCTION_MARK("ScopedXPCOMStartup");
3523 // Allows the user to forcefully bypass the restart process at their
3524 // own risk. Useful for debugging or for tinderboxes where child
3525 // processes can be problematic.
3527 // Start the real application
3528 ScopedXPCOMStartup xpcom
;
3529 rv
= xpcom
.Initialize();
3530 NS_TIME_FUNCTION_MARK("ScopedXPCOMStartup: Initialize");
3531 NS_ENSURE_SUCCESS(rv
, 1);
3534 #ifdef NS_FUNCTION_TIMER
3535 // initialize some common services, so we don't pay the cost for these at odd times later on;
3536 // SetWindowCreator -> ChromeRegistry -> IOService -> SocketTransportService -> (nspr wspm init), Prefs
3538 nsCOMPtr
<nsISupports
> comp
;
3540 comp
= do_GetService("@mozilla.org/preferences-service;1");
3541 NS_TIME_FUNCTION_MARK("Pref Service");
3543 comp
= do_GetService("@mozilla.org/network/socket-transport-service;1");
3544 NS_TIME_FUNCTION_MARK("Socket Transport Service");
3546 comp
= do_GetService("@mozilla.org/network/dns-service;1");
3547 NS_TIME_FUNCTION_MARK("DNS Service");
3549 comp
= do_GetService("@mozilla.org/network/io-service;1");
3550 NS_TIME_FUNCTION_MARK("IO Service");
3552 comp
= do_GetService("@mozilla.org/chrome/chrome-registry;1");
3553 NS_TIME_FUNCTION_MARK("Chrome Registry Service");
3555 comp
= do_GetService("@mozilla.org/focus-event-suppressor-service;1");
3556 NS_TIME_FUNCTION_MARK("Focus Event Suppressor Service");
3560 rv
= xpcom
.SetWindowCreator(nativeApp
);
3561 NS_TIME_FUNCTION_MARK("ScopedXPCOMStartup: SetWindowCreator");
3562 NS_ENSURE_SUCCESS(rv
, 1);
3564 NS_TIME_FUNCTION_MARK("ScopedXPCOMStartup: Done");
3566 #ifdef MOZ_CRASHREPORTER
3567 // tell the crash reporter to also send the release channel
3568 nsCOMPtr
<nsIPrefService
> prefs
= do_GetService("@mozilla.org/preferences-service;1", &rv
);
3569 if (NS_SUCCEEDED(rv
)) {
3570 nsCOMPtr
<nsIPrefBranch
> defaultPrefBranch
;
3571 rv
= prefs
->GetDefaultBranch(nsnull
, getter_AddRefs(defaultPrefBranch
));
3573 if (NS_SUCCEEDED(rv
)) {
3574 nsXPIDLCString sval
;
3575 rv
= defaultPrefBranch
->GetCharPref("app.update.channel", getter_Copies(sval
));
3576 if (NS_SUCCEEDED(rv
)) {
3577 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ReleaseChannel"),
3584 NS_TIME_FUNCTION_MARK("Next: AppStartup");
3588 nsCOMPtr
<nsIIOService2
> io (do_GetService("@mozilla.org/network/io-service;1"));
3589 NS_ENSURE_TRUE(io
, 1);
3590 io
->SetManageOfflineStatus(PR_FALSE
);
3591 io
->SetOffline(PR_TRUE
);
3595 NS_TIMELINE_ENTER("startupNotifier");
3596 nsCOMPtr
<nsIObserver
> startupNotifier
3597 (do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID
, &rv
));
3598 NS_ENSURE_SUCCESS(rv
, 1);
3600 startupNotifier
->Observe(nsnull
, APPSTARTUP_TOPIC
, nsnull
);
3601 NS_TIMELINE_LEAVE("startupNotifier");
3604 NS_TIME_FUNCTION_MARK("Finished startupNotifier");
3606 nsCOMPtr
<nsIAppStartup2
> appStartup
3607 (do_GetService(NS_APPSTARTUP_CONTRACTID
));
3608 NS_ENSURE_TRUE(appStartup
, 1);
3610 NS_TIME_FUNCTION_MARK("Created AppStartup");
3613 nsCOMPtr
<nsIFile
> file
;
3614 dirProvider
.GetAppDir()->Clone(getter_AddRefs(file
));
3615 file
->AppendNative(NS_LITERAL_CSTRING("override.ini"));
3617 nsCOMPtr
<nsILocalFile
> localFile(do_QueryInterface(file
));
3618 nsresult rv
= parser
.Init(localFile
);
3619 if (NS_SUCCEEDED(rv
)) {
3621 rv
= parser
.GetString("XRE", "EnableProfileMigrator", buf
);
3622 if (NS_SUCCEEDED(rv
)) {
3623 if (buf
[0] == '0' || buf
[0] == 'f' || buf
[0] == 'F') {
3624 gDoMigration
= PR_FALSE
;
3630 // Profile Migration
3631 if (gAppData
->flags
& NS_XRE_ENABLE_PROFILE_MIGRATOR
&& gDoMigration
) {
3632 gDoMigration
= PR_FALSE
;
3633 nsCOMPtr
<nsIProfileMigrator
> pm
3634 (do_CreateInstance(NS_PROFILEMIGRATOR_CONTRACTID
));
3636 pm
->Migrate(&dirProvider
);
3639 NS_TIME_FUNCTION_MARK("Profile migration");
3641 dirProvider
.DoStartup();
3643 NS_TIME_FUNCTION_MARK("dirProvider.DoStartup() (profile-after-change)");
3645 PRBool shuttingDown
= PR_FALSE
;
3646 appStartup
->GetShuttingDown(&shuttingDown
);
3648 nsCOMPtr
<nsICommandLineRunner
> cmdLine
;
3650 nsCOMPtr
<nsIFile
> workingDir
;
3651 rv
= NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR
, getter_AddRefs(workingDir
));
3652 NS_ENSURE_SUCCESS(rv
, 1);
3654 if (!shuttingDown
) {
3655 cmdLine
= do_CreateInstance("@mozilla.org/toolkit/command-line;1");
3656 NS_ENSURE_TRUE(cmdLine
, 1);
3658 rv
= cmdLine
->Init(gArgc
, gArgv
,
3659 workingDir
, nsICommandLine::STATE_INITIAL_LAUNCH
);
3660 NS_ENSURE_SUCCESS(rv
, 1);
3662 /* Special-case services that need early access to the command
3664 nsCOMPtr
<nsIObserverService
> obsService
=
3665 mozilla::services::GetObserverService();
3667 obsService
->NotifyObservers(cmdLine
, "command-line-startup", nsnull
);
3670 NS_TIME_FUNCTION_MARK("Early command line init");
3672 NS_TIME_FUNCTION_MARK("Next: prepare for Run");
3675 SaveStateForAppInitiatedRestart();
3677 // clear out any environment variables which may have been set
3678 // during the relaunch process now that we know we won't be relaunching.
3679 SaveToEnv("XRE_PROFILE_PATH=");
3680 SaveToEnv("XRE_PROFILE_LOCAL_PATH=");
3681 SaveToEnv("XRE_PROFILE_NAME=");
3682 SaveToEnv("XRE_START_OFFLINE=");
3683 SaveToEnv("XRE_IMPORT_PROFILES=");
3684 SaveToEnv("NO_EM_RESTART=");
3685 SaveToEnv("XUL_APP_FILE=");
3686 SaveToEnv("XRE_BINARY_PATH=");
3688 NS_TIME_FUNCTION_MARK("env munging");
3690 if (!shuttingDown
) {
3691 NS_TIME_FUNCTION_MARK("Next: CreateHiddenWindow");
3693 NS_TIMELINE_ENTER("appStartup->CreateHiddenWindow");
3694 rv
= appStartup
->CreateHiddenWindow();
3695 NS_TIMELINE_LEAVE("appStartup->CreateHiddenWindow");
3696 NS_ENSURE_SUCCESS(rv
, 1);
3698 MOZ_SPLASHSCREEN_UPDATE(50);
3700 #if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK2)
3701 nsRefPtr
<nsGTKToolkit
> toolkit
= GetGTKToolkit();
3702 if (toolkit
&& !desktopStartupID
.IsEmpty()) {
3703 toolkit
->SetDesktopStartupID(desktopStartupID
);
3708 // Set up ability to respond to system (Apple) events. This must be
3709 // done before setting up the command line service.
3710 SetupMacApplicationDelegate();
3712 // we re-initialize the command-line service and do appleevents munging
3713 // after we are sure that we're not restarting
3714 cmdLine
= do_CreateInstance("@mozilla.org/toolkit/command-line;1");
3715 NS_ENSURE_TRUE(cmdLine
, 1);
3717 CommandLineServiceMac::SetupMacCommandLine(gArgc
, gArgv
, PR_FALSE
);
3719 rv
= cmdLine
->Init(gArgc
, gArgv
,
3720 workingDir
, nsICommandLine::STATE_INITIAL_LAUNCH
);
3721 NS_ENSURE_SUCCESS(rv
, 1);
3724 MOZ_SPLASHSCREEN_UPDATE(70);
3726 nsCOMPtr
<nsIObserverService
> obsService
=
3727 mozilla::services::GetObserverService();
3729 obsService
->NotifyObservers(nsnull
, "final-ui-startup", nsnull
);
3731 NS_TIME_FUNCTION_MARK("final-ui-startup done");
3733 appStartup
->GetShuttingDown(&shuttingDown
);
3736 if (!shuttingDown
) {
3737 rv
= cmdLine
->Run();
3738 NS_ENSURE_SUCCESS_LOG(rv
, 1);
3740 appStartup
->GetShuttingDown(&shuttingDown
);
3743 #ifdef MOZ_ENABLE_XREMOTE
3744 nsCOMPtr
<nsIRemoteService
> remoteService
;
3745 #endif /* MOZ_ENABLE_XREMOTE */
3746 if (!shuttingDown
) {
3747 #ifdef MOZ_ENABLE_XREMOTE
3748 // if we have X remote support, start listening for requests on the
3750 remoteService
= do_GetService("@mozilla.org/toolkit/remote-service;1");
3752 remoteService
->Startup(gAppData
->name
,
3753 PromiseFlatCString(profileName
).get());
3754 #endif /* MOZ_ENABLE_XREMOTE */
3756 nativeApp
->Enable();
3759 NS_TIME_FUNCTION_MARK("Next: Run");
3761 NS_TIME_FUNCTION_MARK("appStartup->Run");
3763 MOZ_SPLASHSCREEN_UPDATE(90);
3765 NS_TIMELINE_ENTER("appStartup->Run");
3766 rv
= appStartup
->Run();
3767 NS_TIMELINE_LEAVE("appStartup->Run");
3768 if (NS_FAILED(rv
)) {
3769 NS_ERROR("failed to run appstartup");
3770 gLogConsoleErrors
= PR_TRUE
;
3774 NS_TIME_FUNCTION_MARK("Next: Finish");
3776 NS_TIME_FUNCTION_MARK("appStartup->Run done");
3778 // Check for an application initiated restart. This is one that
3779 // corresponds to nsIAppStartup.quit(eRestart)
3780 if (rv
== NS_SUCCESS_RESTART_APP
)
3781 appInitiatedRestart
= PR_TRUE
;
3783 if (!shuttingDown
) {
3784 #ifdef MOZ_ENABLE_XREMOTE
3785 // shut down the x remote proxy window
3787 remoteService
->Shutdown();
3788 #endif /* MOZ_ENABLE_XREMOTE */
3792 // Make sure we print this out even if timeline is runtime disabled
3793 if (NS_FAILED(NS_TIMELINE_LEAVE("main1")))
3794 NS_TimelineForceMark("...main1");
3799 // unlock the profile after ScopedXPCOMStartup object (xpcom)
3800 // has gone out of scope. see bug #386739 for more details
3801 profileLock
->Unlock();
3803 // Restart the app after XPCOM has been shut down cleanly.
3804 if (appInitiatedRestart
) {
3805 MOZ_SPLASHSCREEN_UPDATE(90);
3807 RestoreStateForAppInitiatedRestart();
3809 // Ensure that these environment variables are set:
3810 SaveFileToEnvIfUnset("XRE_PROFILE_PATH", profD
);
3811 SaveFileToEnvIfUnset("XRE_PROFILE_LOCAL_PATH", profLD
);
3812 SaveWordToEnvIfUnset("XRE_PROFILE_NAME", profileName
);
3816 static char kEnvVar
[MAXPATHLEN
];
3817 sprintf(kEnvVar
, "XRE_BINARY_PATH=%s", gBinaryPath
);
3822 #if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK2)
3823 if (!desktopStartupID
.IsEmpty()) {
3824 nsCAutoString desktopStartupEnv
;
3825 desktopStartupEnv
.AssignLiteral("DESKTOP_STARTUP_ID=");
3826 desktopStartupEnv
.Append(desktopStartupID
);
3827 // Leak it with extreme prejudice!
3828 PR_SetEnv(ToNewCString(desktopStartupEnv
));
3832 #ifdef MOZ_WIDGET_GTK2
3833 MOZ_gdk_display_close(display
);
3836 rv
= LaunchChild(nativeApp
, PR_TRUE
);
3838 #ifdef MOZ_CRASHREPORTER
3839 if (appData
.flags
& NS_XRE_ENABLE_CRASH_REPORTER
)
3840 CrashReporter::UnsetExceptionHandler();
3843 return rv
== NS_ERROR_LAUNCHED_CHILD_PROCESS
? 0 : 1;
3846 #ifdef MOZ_WIDGET_GTK2
3847 // gdk_display_close also calls gdk_display_manager_set_default_display
3848 // appropriately when necessary.
3849 MOZ_gdk_display_close(display
);
3853 #ifdef MOZ_CRASHREPORTER
3854 if (appData
.flags
& NS_XRE_ENABLE_CRASH_REPORTER
)
3855 CrashReporter::UnsetExceptionHandler();
3858 XRE_DeinitCommandLine();
3860 return NS_FAILED(rv
) ? 1 : 0;
3864 XRE_InitCommandLine(int aArgc
, char* aArgv
[])
3866 nsresult rv
= NS_OK
;
3868 #if defined(MOZ_IPC)
3871 CommandLine::Init(aArgc
, aArgv
);
3874 // these leak on error, but that's OK: we'll just exit()
3875 char** canonArgs
= new char*[aArgc
];
3877 // get the canonical version of the binary's path
3878 nsCOMPtr
<nsILocalFile
> binFile
;
3879 rv
= XRE_GetBinaryPath(aArgv
[0], getter_AddRefs(binFile
));
3881 return NS_ERROR_FAILURE
;
3883 nsCAutoString canonBinPath
;
3884 rv
= binFile
->GetNativePath(canonBinPath
);
3886 return NS_ERROR_FAILURE
;
3888 canonArgs
[0] = strdup(canonBinPath
.get());
3890 for (int i
= 1; i
< aArgc
; ++i
) {
3892 canonArgs
[i
] = strdup(aArgv
[i
]);
3896 NS_ASSERTION(!CommandLine::IsInitialized(), "Bad news!");
3897 CommandLine::Init(aArgc
, canonArgs
);
3899 for (int i
= 0; i
< aArgc
; ++i
)
3906 const char *omnijarPath
= nsnull
;
3907 ArgResult ar
= CheckArg("omnijar", PR_FALSE
, &omnijarPath
);
3908 if (ar
== ARG_BAD
) {
3909 PR_fprintf(PR_STDERR
, "Error: argument -omnijar requires an omnijar path\n");
3910 return NS_ERROR_FAILURE
;
3916 nsCOMPtr
<nsILocalFile
> omnijar
;
3917 rv
= NS_NewNativeLocalFile(nsDependentCString(omnijarPath
), PR_TRUE
,
3918 getter_AddRefs(omnijar
));
3919 if (NS_SUCCEEDED(rv
))
3920 mozilla::SetOmnijar(omnijar
);
3927 XRE_DeinitCommandLine()
3929 nsresult rv
= NS_OK
;
3931 #if defined(MOZ_IPC)
3932 CommandLine::Terminate();
3939 XRE_GetProcessType()
3942 return mozilla::startup::sChildProcessType
;
3944 return GeckoProcessType_Default
;
3949 SetupErrorHandling(const char* progname
)
3952 /* On Windows XPSP3 and Windows Vista if DEP is configured off-by-default
3953 we still want DEP protection: enable it explicitly and programmatically.
3955 This function is not available on WinXPSP2 so we dynamically load it.
3958 HMODULE kernel32
= GetModuleHandleW(L
"kernel32.dll");
3959 SetProcessDEPPolicyFunc _SetProcessDEPPolicy
=
3960 (SetProcessDEPPolicyFunc
) GetProcAddress(kernel32
, "SetProcessDEPPolicy");
3961 if (_SetProcessDEPPolicy
)
3962 _SetProcessDEPPolicy(PROCESS_DEP_ENABLE
);
3965 #if defined (XP_WIN32) && !defined (WINCE)
3966 // Suppress the "DLL Foo could not be found" dialog, such that if dependent
3967 // libraries (such as GDI+) are not preset, we gracefully fail to load those
3968 // XPCOM components, instead of being ungraceful.
3969 UINT realMode
= SetErrorMode(0);
3970 realMode
|= SEM_FAILCRITICALERRORS
;
3971 // If XRE_NO_WINDOWS_CRASH_DIALOG is set, suppress displaying the "This
3972 // application has crashed" dialog box. This is mainly useful for
3973 // automated testing environments, e.g. tinderbox, where there's no need
3974 // for a dozen of the dialog boxes to litter the console
3975 if (getenv("XRE_NO_WINDOWS_CRASH_DIALOG"))
3976 realMode
|= SEM_NOGPFAULTERRORBOX
| SEM_NOOPENFILEERRORBOX
;
3978 SetErrorMode(realMode
);
3983 InstallSignalHandlers(progname
);
3987 // Unbuffer stdout, needed for tinderbox tests.
3991 #if defined(FREEBSD)
3992 // Disable all SIGFPE's on FreeBSD, as it has non-IEEE-conformant fp
3993 // trap behavior that trips up on floating-point tests performed by
3994 // the JS engine. See bugzilla bug 9967 details.