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 #ifdef MOZ_ENABLE_MEEGOTOUCH
58 #include <MApplication>
59 #include "MozMeegoAppService.h"
60 #endif // MOZ_ENABLE_MEEGOTOUCH
61 #endif // MOZ_WIDGET_QT
64 #include "mozilla/dom/ContentParent.h"
65 using mozilla::dom::ContentParent
;
68 #include "nsAppRunner.h"
69 #include "nsUpdateDriver.h"
72 #include "MacLaunchHelper.h"
73 #include "MacApplicationDelegate.h"
74 #include "MacAutoreleasePool.h"
78 #include "private/pprthred.h"
86 #include "nsIAppShellService.h"
87 #include "nsIAppStartup.h"
88 #include "nsIAppStartupNotifier.h"
89 #include "nsIMutableArray.h"
90 #include "nsICategoryManager.h"
91 #include "nsIChromeRegistry.h"
92 #include "nsICommandLineRunner.h"
93 #include "nsIComponentManager.h"
94 #include "nsIComponentRegistrar.h"
95 #include "nsIContentHandler.h"
96 #include "nsIDialogParamBlock.h"
97 #include "nsIDOMWindow.h"
98 #include "nsIFastLoadService.h" // for PLATFORM_FASL_SUFFIX
99 #include "mozilla/ModuleUtils.h"
100 #include "nsIIOService2.h"
101 #include "nsIObserverService.h"
102 #include "nsINativeAppSupport.h"
103 #include "nsIProcess.h"
104 #include "nsIProfileUnlocker.h"
105 #include "nsIPromptService.h"
106 #include "nsIServiceManager.h"
107 #include "nsIStringBundle.h"
108 #include "nsISupportsPrimitives.h"
109 #include "nsITimelineService.h"
110 #include "nsIToolkitChromeRegistry.h"
111 #include "nsIToolkitProfile.h"
112 #include "nsIToolkitProfileService.h"
114 #include "nsIWindowCreator.h"
115 #include "nsIWindowMediator.h"
116 #include "nsIWindowWatcher.h"
117 #include "nsIXULAppInfo.h"
118 #include "nsIXULRuntime.h"
119 #include "nsPIDOMWindow.h"
120 #include "nsIBaseWindow.h"
121 #include "nsIWidget.h"
122 #include "nsIDocShell.h"
123 #include "nsAppShellCID.h"
125 #include "mozilla/FunctionTimer.h"
128 #include "nsIWinAppHelper.h"
131 #ifndef PROCESS_DEP_ENABLE
132 #define PROCESS_DEP_ENABLE 0x1
137 #include "nsCOMPtr.h"
138 #include "nsDirectoryServiceDefs.h"
139 #include "nsDirectoryServiceUtils.h"
140 #include "nsEmbedCID.h"
141 #include "nsNetUtil.h"
142 #include "nsReadableUtils.h"
143 #include "nsStaticComponents.h"
145 #include "nsXPCOMCIDInternal.h"
146 #include "nsXPIDLString.h"
147 #include "nsVersionComparator.h"
149 #include "nsAppDirectoryServiceDefs.h"
150 #include "nsXULAppAPI.h"
151 #include "nsXREDirProvider.h"
152 #include "nsToolkitCompsCID.h"
154 #include "nsINIParser.h"
155 #include "mozilla/Omnijar.h"
159 #if defined(MOZ_SPLASHSCREEN)
160 #include "nsSplashScreen.h"
164 #include <sys/stat.h>
170 // execv() behaves bit differently in R5 and Zeta, looks unreliable in such situation
171 //#include <unistd.h>
173 #include <AppFileInfo.h>
181 #include "nsThreadUtils.h"
185 #include "nsILocalFileMac.h"
186 #include "nsCommandLineServiceMac.h"
189 // for X remote support
190 #ifdef MOZ_ENABLE_XREMOTE
191 #include "XRemoteClient.h"
192 #include "nsIRemoteService.h"
195 #ifdef NS_TRACE_MALLOC
196 #include "nsTraceMalloc.h"
199 #if defined(DEBUG) && defined(XP_WIN32)
203 #if defined (XP_MACOSX)
204 #include <Carbon/Carbon.h>
215 #ifdef MOZ_CRASHREPORTER
216 #include "nsExceptionHandler.h"
217 #include "nsICrashReporter.h"
218 #define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1"
219 #include "nsIPrefService.h"
223 #include "base/command_line.h"
226 #include "mozilla/FunctionTimer.h"
229 #include "AndroidBridge.h"
235 WindowsMutex(const wchar_t *name
) {
236 mHandle
= CreateMutexW(0, FALSE
, name
);
241 CloseHandle(mHandle
);
244 PRBool
Lock(DWORD timeout
= INFINITE
) {
245 DWORD state
= WaitForSingleObject(mHandle
, timeout
);
246 return state
== WAIT_OBJECT_0
;
251 ReleaseMutex(mHandle
);
259 extern void InstallSignalHandlers(const char *ProgramName
);
260 #include "nsX11ErrorHandler.h"
262 #define FILE_COMPATIBILITY_INFO NS_LITERAL_CSTRING("compatibility.ini")
263 #define FILE_INVALIDATE_CACHES NS_LITERAL_CSTRING(".purgecaches")
268 static const char gToolkitVersion
[] = NS_STRINGIFY(GRE_MILESTONE
);
269 static const char gToolkitBuildID
[] = NS_STRINGIFY(GRE_BUILDID
);
271 static int gRestartArgc
;
272 static char **gRestartArgv
;
275 static int gQtOnlyArgc
;
276 static char **gQtOnlyArgv
;
279 #if defined(MOZ_WIDGET_GTK2)
280 #if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING) \
281 || defined(NS_TRACE_MALLOC)
282 #define CLEANUP_MEMORY 1
283 #define PANGO_ENABLE_BACKEND
284 #include <pango/pangofc-fontmap.h>
288 #include <gdk/gdkx.h>
290 #include "nsGTKToolkit.h"
293 // Save literal putenv string to environment variable.
295 SaveToEnv(const char *putenv
)
297 char *expr
= strdup(putenv
);
300 // We intentionally leak |expr| here since it is required by PR_SetEnv.
303 // Save the given word to the specified environment variable.
305 SaveWordToEnv(const char *name
, const nsACString
& word
)
307 char *expr
= PR_smprintf("%s=%s", name
, PromiseFlatCString(word
).get());
310 // We intentionally leak |expr| here since it is required by PR_SetEnv.
313 // Save the path of the given file to the specified environment variable.
315 SaveFileToEnv(const char *name
, nsIFile
*file
)
320 SetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name
).get(), path
.get());
323 file
->GetNativePath(path
);
324 SaveWordToEnv(name
, path
);
328 // Load the path of a file saved with SaveFileToEnv
329 static already_AddRefed
<nsILocalFile
>
330 GetFileFromEnv(const char *name
)
333 nsILocalFile
*file
= nsnull
;
336 WCHAR path
[_MAX_PATH
];
337 if (!GetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name
).get(),
341 rv
= NS_NewLocalFile(nsDependentString(path
), PR_TRUE
, &file
);
347 const char *arg
= PR_GetEnv(name
);
351 rv
= NS_NewNativeLocalFile(nsDependentCString(arg
), PR_TRUE
, &file
);
359 // Save the path of the given word to the specified environment variable
360 // provided the environment variable does not have a value.
362 SaveWordToEnvIfUnset(const char *name
, const nsACString
& word
)
364 const char *val
= PR_GetEnv(name
);
366 SaveWordToEnv(name
, word
);
369 // Save the path of the given file to the specified environment variable
370 // provided the environment variable does not have a value.
372 SaveFileToEnvIfUnset(const char *name
, nsIFile
*file
)
374 const char *val
= PR_GetEnv(name
);
376 SaveFileToEnv(name
, file
);
380 strimatch(const char* lowerstr
, const char* mixedstr
)
383 if (!*mixedstr
) return PR_FALSE
; // mixedstr is shorter
384 if (tolower(*mixedstr
) != *lowerstr
) return PR_FALSE
; // no match
390 if (*mixedstr
) return PR_FALSE
; // lowerstr is shorter
396 * Output a string to the user. This method is really only meant to be used to
397 * output last-ditch error messages designed for developers NOT END USERS.
400 * Pass true to indicate severe errors.
402 * printf-style format string followed by arguments.
404 static void Output(PRBool isError
, const char *fmt
, ... )
409 #if defined(XP_WIN) && !MOZ_WINCONSOLE
410 char *msg
= PR_vsmprintf(fmt
, ap
);
415 flags
|= MB_ICONERROR
;
417 flags
|= MB_ICONINFORMATION
;
419 wchar_t wide_msg
[1024];
420 MultiByteToWideChar(CP_ACP
,
425 sizeof(wide_msg
) / sizeof(wchar_t));
427 MessageBoxW(NULL
, wide_msg
, L
"XULRunner", flags
);
428 PR_smprintf_free(msg
);
431 vfprintf(stderr
, fmt
, ap
);
438 REMOTE_NOT_FOUND
= 0,
446 ARG_BAD
= 2 // you wanted a param, but there isn't one
449 static void RemoveArg(char **argv
)
460 * Check for a commandline flag. If the flag takes a parameter, the
461 * parameter is returned in aParam. Flags may be in the form -arg or
462 * --arg (or /arg on win32/OS2).
464 * @param aArg the parameter to check. Must be lowercase.
465 * @param aCheckOSInt if true returns ARG_BAD if the osint argument is present
466 * when aArg is also present.
467 * @param if non-null, the -arg <data> will be stored in this pointer. This is *not*
468 * allocated, but rather a pointer to the argv data.
471 CheckArg(const char* aArg
, PRBool aCheckOSInt
= PR_FALSE
, const char **aParam
= nsnull
, PRBool aRemArg
= PR_TRUE
)
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 *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>
1645 #if defined(XP_OS2) && (__KLIBC__ == 0 && __KLIBC_MINOR__ >= 6) // broken kLibc
1646 // Copy the environment maintained by the C library into an ASCIIZ array
1647 // that can be used to pass it on to the OS/2 Dos* APIs (which otherwise
1648 // don't know anything about the stuff set by PR_SetEnv() or setenv()).
1651 // just allocate the maximum amount (24 kB = 0x60000 bytes), to be able to
1652 // copy the existing environment
1653 char *env
= (char *)calloc(0x6000, sizeof(char));
1658 // walk along the environ string array of the C library and copy
1659 // everything (that fits) into the output environment array, leaving
1660 // null bytes between the entries
1661 char *penv
= env
; // movable pointer to result environment ASCIIZ array
1662 int i
= 0, space
= 0x6000;
1663 while (environ
[i
] && environ
[i
][0]) {
1664 int len
= strlen(environ
[i
]);
1665 if (space
- len
<= 0) {
1668 strcpy(penv
, environ
[i
]);
1669 i
++; // next environment variable
1670 penv
+= len
+ 1; // jump to after next null byte
1671 space
-= len
- 1; // subtract consumed length from usable space
1677 // OS2LaunchChild() is there to replace _execv() which is broken in the C
1678 // runtime library that comes with GCC 3.3.5 on OS/2. It uses createEnv()
1679 // to copy the process environment and add necessary variables
1681 // returns -1 on failure and 0 on success
1682 int OS2LaunchChild(const char *aExePath
, int aArgc
, char **aArgv
)
1684 // find total length of aArgv
1686 for (int i
= 0; i
< aArgc
; i
++) {
1687 len
+= strlen(aArgv
[i
]) + 1; // plus space in between
1689 len
++; // leave space for null byte at end
1690 // allocate enough space for all strings and nulls,
1691 // calloc helpfully initializes to null
1692 char *args
= (char *)calloc(len
, sizeof(char));
1696 char *pargs
= args
; // extra pointer to after the last argument
1697 // build argument list in the format the DosStartSession() wants,
1698 // adding spaces between the arguments
1699 for (int i
= 0; i
< aArgc
; i
++, *pargs
++ = ' ') {
1700 strcpy(pargs
, aArgv
[i
]);
1701 pargs
+= strlen(aArgv
[i
]);
1704 *(pargs
-1) = '\0'; // replace last space
1707 // make sure that the program is separated by null byte
1708 pargs
= strchr(args
, ' ');
1713 char *env
= createEnv();
1715 char error
[CCHMAXPATH
] = { 0 };
1716 RESULTCODES crc
= { 0 };
1717 ULONG rc
= DosExecPgm(error
, sizeof(error
), EXEC_ASYNC
, args
, env
,
1718 &crc
, (PSZ
)aExePath
);
1719 free(args
); // done with the arguments
1723 if (rc
!= NO_ERROR
) {
1731 // If aBlankCommandLine is true, then the application will be launched with a
1732 // blank command line instead of being launched with the same command line that
1733 // it was initially started with.
1734 static nsresult
LaunchChild(nsINativeAppSupport
* aNative
,
1735 PRBool aBlankCommandLine
= PR_FALSE
)
1737 aNative
->Quit(); // release DDE mutex, if we're holding it
1739 // Restart this process by exec'ing it into the current process
1740 // if supported by the platform. Otherwise, use NSPR.
1742 if (aBlankCommandLine
) {
1743 #if defined(MOZ_WIDGET_QT)
1744 // Remove only arguments not given to Qt
1745 gRestartArgc
= gQtOnlyArgc
;
1746 gRestartArgv
= gQtOnlyArgv
;
1749 gRestartArgv
[gRestartArgc
] = nsnull
;
1753 SaveToEnv("MOZ_LAUNCHED_CHILD=1");
1755 #if defined(ANDROID)
1756 mozilla::AndroidBridge::Bridge()->ScheduleRestart();
1758 #if defined(XP_MACOSX)
1759 CommandLineServiceMac::SetupMacCommandLine(gRestartArgc
, gRestartArgv
, PR_TRUE
);
1760 LaunchChildMac(gRestartArgc
, gRestartArgv
);
1762 nsCOMPtr
<nsILocalFile
> lf
;
1763 nsresult rv
= XRE_GetBinaryPath(gArgv
[0], getter_AddRefs(lf
));
1768 nsAutoString exePath
;
1769 rv
= lf
->GetPath(exePath
);
1773 if (!WinLaunchChild(exePath
.get(), gRestartArgc
, gRestartArgv
))
1774 return NS_ERROR_FAILURE
;
1777 nsCAutoString exePath
;
1778 rv
= lf
->GetNativePath(exePath
);
1782 #if defined(XP_OS2) && (__KLIBC__ == 0 && __KLIBC_MINOR__ >= 6)
1783 // implementation of _execv() is broken with kLibc 0.6.x and later
1784 if (OS2LaunchChild(exePath
.get(), gRestartArgc
, gRestartArgv
) == -1)
1785 return NS_ERROR_FAILURE
;
1786 #elif defined(XP_OS2)
1787 if (_execv(exePath
.get(), gRestartArgv
) == -1)
1788 return NS_ERROR_FAILURE
;
1789 #elif defined(XP_UNIX)
1790 if (execv(exePath
.get(), gRestartArgv
) == -1)
1791 return NS_ERROR_FAILURE
;
1792 #elif defined(XP_BEOS)
1793 extern char **environ
;
1795 res
= resume_thread(load_image(gRestartArgc
,(const char **)gRestartArgv
,(const char **)environ
));
1797 return NS_ERROR_FAILURE
;
1799 PRProcess
* process
= PR_CreateProcess(exePath
.get(), gRestartArgv
,
1801 if (!process
) return NS_ERROR_FAILURE
;
1804 PRStatus failed
= PR_WaitProcess(process
, &exitCode
);
1805 if (failed
|| exitCode
)
1806 return NS_ERROR_FAILURE
;
1807 #endif // XP_OS2 series
1812 return NS_ERROR_LAUNCHED_CHILD_PROCESS
;
1815 static const char kProfileProperties
[] =
1816 "chrome://mozapps/locale/profile/profileSelection.properties";
1819 ProfileLockedDialog(nsILocalFile
* aProfileDir
, nsILocalFile
* aProfileLocalDir
,
1820 nsIProfileUnlocker
* aUnlocker
,
1821 nsINativeAppSupport
* aNative
, nsIProfileLock
* *aResult
)
1825 ScopedXPCOMStartup xpcom
;
1826 rv
= xpcom
.Initialize();
1827 NS_ENSURE_SUCCESS(rv
, rv
);
1829 rv
= xpcom
.SetWindowCreator(aNative
);
1830 NS_ENSURE_SUCCESS(rv
, NS_ERROR_FAILURE
);
1832 { //extra scoping is needed so we release these components before xpcom shutdown
1833 nsCOMPtr
<nsIStringBundleService
> sbs
=
1834 mozilla::services::GetStringBundleService();
1835 NS_ENSURE_TRUE(sbs
, NS_ERROR_FAILURE
);
1837 nsCOMPtr
<nsIStringBundle
> sb
;
1838 sbs
->CreateBundle(kProfileProperties
, getter_AddRefs(sb
));
1839 NS_ENSURE_TRUE_LOG(sbs
, NS_ERROR_FAILURE
);
1841 NS_ConvertUTF8toUTF16
appName(gAppData
->name
);
1842 const PRUnichar
* params
[] = {appName
.get(), appName
.get()};
1844 nsXPIDLString killMessage
;
1846 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"
1847 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"
1849 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"
1850 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"
1853 sb
->FormatStringFromName(aUnlocker
? kRestartUnlocker
: kRestartNoUnlocker
,
1854 params
, 2, getter_Copies(killMessage
));
1856 nsXPIDLString killTitle
;
1857 sb
->FormatStringFromName(NS_LITERAL_STRING("restartTitle").get(),
1858 params
, 1, getter_Copies(killTitle
));
1860 if (!killMessage
|| !killTitle
)
1861 return NS_ERROR_FAILURE
;
1863 nsCOMPtr
<nsIPromptService
> ps
1864 (do_GetService(NS_PROMPTSERVICE_CONTRACTID
));
1865 NS_ENSURE_TRUE(ps
, NS_ERROR_FAILURE
);
1867 PRUint32 flags
= nsIPromptService::BUTTON_TITLE_OK
* nsIPromptService::BUTTON_POS_0
;
1871 nsIPromptService::BUTTON_TITLE_CANCEL
* nsIPromptService::BUTTON_POS_0
+
1872 nsIPromptService::BUTTON_TITLE_IS_STRING
* nsIPromptService::BUTTON_POS_1
+
1873 nsIPromptService::BUTTON_POS_1_DEFAULT
;
1878 rv
= ps
->ConfirmEx(nsnull
, killTitle
, killMessage
, flags
,
1879 killTitle
, nsnull
, nsnull
, nsnull
, &checkState
, &button
);
1880 NS_ENSURE_SUCCESS_LOG(rv
, rv
);
1882 if (button
== 1 && aUnlocker
) {
1883 rv
= aUnlocker
->Unlock(nsIProfileUnlocker::FORCE_QUIT
);
1884 if (NS_FAILED(rv
)) return rv
;
1886 return NS_LockProfilePath(aProfileDir
, aProfileLocalDir
, nsnull
, aResult
);
1889 return NS_ERROR_ABORT
;
1894 ProfileMissingDialog(nsINativeAppSupport
* aNative
)
1898 ScopedXPCOMStartup xpcom
;
1899 rv
= xpcom
.Initialize();
1900 NS_ENSURE_SUCCESS(rv
, rv
);
1902 rv
= xpcom
.SetWindowCreator(aNative
);
1903 NS_ENSURE_SUCCESS(rv
, NS_ERROR_FAILURE
);
1905 { //extra scoping is needed so we release these components before xpcom shutdown
1906 nsCOMPtr
<nsIStringBundleService
> sbs
=
1907 mozilla::services::GetStringBundleService();
1908 NS_ENSURE_TRUE(sbs
, NS_ERROR_FAILURE
);
1910 nsCOMPtr
<nsIStringBundle
> sb
;
1911 sbs
->CreateBundle(kProfileProperties
, getter_AddRefs(sb
));
1912 NS_ENSURE_TRUE_LOG(sbs
, NS_ERROR_FAILURE
);
1914 NS_ConvertUTF8toUTF16
appName(gAppData
->name
);
1915 const PRUnichar
* params
[] = {appName
.get(), appName
.get()};
1917 nsXPIDLString missingMessage
;
1920 static const PRUnichar kMissing
[] = {'p','r','o','f','i','l','e','M','i','s','s','i','n','g','\0'};
1921 sb
->FormatStringFromName(kMissing
, params
, 2, getter_Copies(missingMessage
));
1923 nsXPIDLString missingTitle
;
1924 sb
->FormatStringFromName(NS_LITERAL_STRING("profileMissingTitle").get(),
1925 params
, 1, getter_Copies(missingTitle
));
1927 if (missingMessage
&& missingTitle
) {
1928 nsCOMPtr
<nsIPromptService
> ps
1929 (do_GetService(NS_PROMPTSERVICE_CONTRACTID
));
1930 NS_ENSURE_TRUE(ps
, NS_ERROR_FAILURE
);
1932 ps
->Alert(nsnull
, missingTitle
, missingMessage
);
1935 return NS_ERROR_ABORT
;
1939 static const char kProfileManagerURL
[] =
1940 "chrome://mozapps/content/profile/profileSelection.xul";
1943 ShowProfileManager(nsIToolkitProfileService
* aProfileSvc
,
1944 nsINativeAppSupport
* aNative
)
1948 nsCOMPtr
<nsILocalFile
> profD
, profLD
;
1949 PRUnichar
* profileNamePtr
;
1950 nsCAutoString profileName
;
1953 ScopedXPCOMStartup xpcom
;
1954 rv
= xpcom
.Initialize();
1955 NS_ENSURE_SUCCESS(rv
, rv
);
1957 rv
= xpcom
.SetWindowCreator(aNative
);
1958 NS_ENSURE_SUCCESS(rv
, NS_ERROR_FAILURE
);
1961 CommandLineServiceMac::SetupMacCommandLine(gRestartArgc
, gRestartArgv
, PR_TRUE
);
1965 // we don't have to wait here because profile manager window will pump
1966 // and DDE message will be handled
1967 ProcessDDE(aNative
, PR_FALSE
);
1970 { //extra scoping is needed so we release these components before xpcom shutdown
1971 nsCOMPtr
<nsIWindowWatcher
> windowWatcher
1972 (do_GetService(NS_WINDOWWATCHER_CONTRACTID
));
1973 nsCOMPtr
<nsIDialogParamBlock
> ioParamBlock
1974 (do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID
));
1975 nsCOMPtr
<nsIMutableArray
> dlgArray (do_CreateInstance(NS_ARRAY_CONTRACTID
));
1976 NS_ENSURE_TRUE(windowWatcher
&& ioParamBlock
&& dlgArray
, NS_ERROR_FAILURE
);
1978 ioParamBlock
->SetObjects(dlgArray
);
1980 nsCOMPtr
<nsIAppStartup
> appStartup
1981 (do_GetService(NS_APPSTARTUP_CONTRACTID
));
1982 NS_ENSURE_TRUE(appStartup
, NS_ERROR_FAILURE
);
1984 nsCOMPtr
<nsIDOMWindow
> newWindow
;
1985 rv
= windowWatcher
->OpenWindow(nsnull
,
1988 "centerscreen,chrome,modal,titlebar",
1990 getter_AddRefs(newWindow
));
1992 NS_ENSURE_SUCCESS_LOG(rv
, rv
);
1994 aProfileSvc
->Flush();
1996 PRInt32 dialogConfirmed
;
1997 rv
= ioParamBlock
->GetInt(0, &dialogConfirmed
);
1998 if (NS_FAILED(rv
) || dialogConfirmed
== 0) return NS_ERROR_ABORT
;
2000 nsCOMPtr
<nsIProfileLock
> lock
;
2001 rv
= dlgArray
->QueryElementAt(0, NS_GET_IID(nsIProfileLock
),
2002 getter_AddRefs(lock
));
2003 NS_ENSURE_SUCCESS_LOG(rv
, rv
);
2005 rv
= lock
->GetDirectory(getter_AddRefs(profD
));
2006 NS_ENSURE_SUCCESS(rv
, rv
);
2008 rv
= lock
->GetLocalDirectory(getter_AddRefs(profLD
));
2009 NS_ENSURE_SUCCESS(rv
, rv
);
2011 rv
= ioParamBlock
->GetString(0, &profileNamePtr
);
2012 NS_ENSURE_SUCCESS(rv
, rv
);
2014 CopyUTF16toUTF8(profileNamePtr
, profileName
);
2015 NS_Free(profileNamePtr
);
2021 SaveFileToEnv("XRE_PROFILE_PATH", profD
);
2022 SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", profLD
);
2023 SaveWordToEnv("XRE_PROFILE_NAME", profileName
);
2025 PRBool offline
= PR_FALSE
;
2026 aProfileSvc
->GetStartOffline(&offline
);
2028 SaveToEnv("XRE_START_OFFLINE=1");
2031 return LaunchChild(aNative
);
2035 ImportProfiles(nsIToolkitProfileService
* aPService
,
2036 nsINativeAppSupport
* aNative
)
2040 SaveToEnv("XRE_IMPORT_PROFILES=1");
2042 // try to import old-style profiles
2044 ScopedXPCOMStartup xpcom
;
2045 rv
= xpcom
.Initialize();
2046 if (NS_SUCCEEDED(rv
)) {
2048 CommandLineServiceMac::SetupMacCommandLine(gRestartArgc
, gRestartArgv
, PR_TRUE
);
2051 nsCOMPtr
<nsIProfileMigrator
> migrator
2052 (do_GetService(NS_PROFILEMIGRATOR_CONTRACTID
));
2060 return LaunchChild(aNative
);
2063 // Pick a profile. We need to end up with a profile lock.
2065 // 1) check for -profile <path>
2066 // 2) check for -P <name>
2067 // 3) check for -ProfileManager
2068 // 4) use the default profile, if there is one
2069 // 5) if there are *no* profiles, set up profile-migration
2070 // 6) display the profile-manager UI
2072 static PRBool gDoMigration
= PR_FALSE
;
2075 SelectProfile(nsIProfileLock
* *aResult
, nsINativeAppSupport
* aNative
,
2076 PRBool
* aStartOffline
, nsACString
* aProfileName
)
2082 *aStartOffline
= PR_FALSE
;
2084 ar
= CheckArg("offline", PR_TRUE
);
2085 if (ar
== ARG_BAD
) {
2086 PR_fprintf(PR_STDERR
, "Error: argument -offline is invalid when argument -osint is specified\n");
2087 return NS_ERROR_FAILURE
;
2090 arg
= PR_GetEnv("XRE_START_OFFLINE");
2091 if ((arg
&& *arg
) || ar
)
2092 *aStartOffline
= PR_TRUE
;
2095 nsCOMPtr
<nsILocalFile
> lf
= GetFileFromEnv("XRE_PROFILE_PATH");
2097 nsCOMPtr
<nsILocalFile
> localDir
=
2098 GetFileFromEnv("XRE_PROFILE_LOCAL_PATH");
2103 arg
= PR_GetEnv("XRE_PROFILE_NAME");
2104 if (arg
&& *arg
&& aProfileName
)
2105 aProfileName
->Assign(nsDependentCString(arg
));
2107 // Clear out flags that we handled (or should have handled!) last startup.
2109 CheckArg("p", PR_FALSE
, &dummy
);
2110 CheckArg("profile", PR_FALSE
, &dummy
);
2111 CheckArg("profilemanager");
2113 return NS_LockProfilePath(lf
, localDir
, nsnull
, aResult
);
2116 ar
= CheckArg("migration", PR_TRUE
);
2117 if (ar
== ARG_BAD
) {
2118 PR_fprintf(PR_STDERR
, "Error: argument -migration is invalid when argument -osint is specified\n");
2119 return NS_ERROR_FAILURE
;
2120 } else if (ar
== ARG_FOUND
) {
2121 gDoMigration
= PR_TRUE
;
2124 ar
= CheckArg("profile", PR_TRUE
, &arg
);
2125 if (ar
== ARG_BAD
) {
2126 PR_fprintf(PR_STDERR
, "Error: argument -profile requires a path\n");
2127 return NS_ERROR_FAILURE
;
2130 nsCOMPtr
<nsILocalFile
> lf
;
2131 rv
= XRE_GetFileFromPath(arg
, getter_AddRefs(lf
));
2132 NS_ENSURE_SUCCESS(rv
, rv
);
2134 nsCOMPtr
<nsIProfileUnlocker
> unlocker
;
2136 // Check if the profile path exists and it's a directory.
2138 lf
->Exists(&exists
);
2140 rv
= lf
->Create(nsIFile::DIRECTORY_TYPE
, 0700);
2141 NS_ENSURE_SUCCESS(rv
, rv
);
2144 // If a profile path is specified directory on the command line, then
2145 // assume that the temp directory is the same as the given directory.
2146 rv
= NS_LockProfilePath(lf
, lf
, getter_AddRefs(unlocker
), aResult
);
2147 if (NS_SUCCEEDED(rv
))
2150 return ProfileLockedDialog(lf
, lf
, unlocker
, aNative
, aResult
);
2153 nsCOMPtr
<nsIToolkitProfileService
> profileSvc
;
2154 rv
= NS_NewToolkitProfileService(getter_AddRefs(profileSvc
));
2155 if (rv
== NS_ERROR_FILE_ACCESS_DENIED
)
2156 PR_fprintf(PR_STDERR
, "Error: Access was denied while trying to open files in " \
2157 "your profile directory.\n");
2158 NS_ENSURE_SUCCESS(rv
, rv
);
2160 ar
= CheckArg("createprofile", PR_TRUE
, &arg
);
2161 if (ar
== ARG_BAD
) {
2162 PR_fprintf(PR_STDERR
, "Error: argument -createprofile requires a profile name\n");
2163 return NS_ERROR_FAILURE
;
2166 nsCOMPtr
<nsIToolkitProfile
> profile
;
2168 const char* delim
= strchr(arg
, ' ');
2170 nsCOMPtr
<nsILocalFile
> lf
;
2171 rv
= NS_NewNativeLocalFile(nsDependentCString(delim
+ 1),
2172 PR_TRUE
, getter_AddRefs(lf
));
2173 if (NS_FAILED(rv
)) {
2174 PR_fprintf(PR_STDERR
, "Error: profile path not valid.\n");
2178 // As with -profile, assume that the given path will be used for both the
2179 // main profile directory and the temp profile directory.
2180 rv
= profileSvc
->CreateProfile(lf
, lf
, nsDependentCSubstring(arg
, delim
),
2181 getter_AddRefs(profile
));
2183 rv
= profileSvc
->CreateProfile(nsnull
, nsnull
, nsDependentCString(arg
),
2184 getter_AddRefs(profile
));
2186 // Some pathological arguments can make it this far
2187 if (NS_FAILED(rv
)) {
2188 PR_fprintf(PR_STDERR
, "Error creating profile.\n");
2191 rv
= NS_ERROR_ABORT
;
2192 profileSvc
->Flush();
2194 // XXXben need to ensure prefs.js exists here so the tinderboxes will
2196 nsCOMPtr
<nsILocalFile
> prefsJSFile
;
2197 profile
->GetRootDir(getter_AddRefs(prefsJSFile
));
2198 prefsJSFile
->AppendNative(NS_LITERAL_CSTRING("prefs.js"));
2199 nsCAutoString pathStr
;
2200 prefsJSFile
->GetNativePath(pathStr
);
2201 PR_fprintf(PR_STDERR
, "Success: created profile '%s' at '%s'\n", arg
, pathStr
.get());
2203 prefsJSFile
->Exists(&exists
);
2205 prefsJSFile
->Create(nsIFile::NORMAL_FILE_TYPE
, 0644);
2206 // XXXdarin perhaps 0600 would be better?
2212 rv
= profileSvc
->GetProfileCount(&count
);
2213 NS_ENSURE_SUCCESS(rv
, rv
);
2215 if (gAppData
->flags
& NS_XRE_ENABLE_PROFILE_MIGRATOR
) {
2216 arg
= PR_GetEnv("XRE_IMPORT_PROFILES");
2217 if (!count
&& (!arg
|| !*arg
)) {
2218 return ImportProfiles(profileSvc
, aNative
);
2222 ar
= CheckArg("p", PR_FALSE
, &arg
);
2223 if (ar
== ARG_BAD
) {
2224 ar
= CheckArg("osint");
2225 if (ar
== ARG_FOUND
) {
2226 PR_fprintf(PR_STDERR
, "Error: argument -p is invalid when argument -osint is specified\n");
2227 return NS_ERROR_FAILURE
;
2229 return ShowProfileManager(profileSvc
, aNative
);
2232 ar
= CheckArg("osint");
2233 if (ar
== ARG_FOUND
) {
2234 PR_fprintf(PR_STDERR
, "Error: argument -p is invalid when argument -osint is specified\n");
2235 return NS_ERROR_FAILURE
;
2237 nsCOMPtr
<nsIToolkitProfile
> profile
;
2238 rv
= profileSvc
->GetProfileByName(nsDependentCString(arg
),
2239 getter_AddRefs(profile
));
2240 if (NS_SUCCEEDED(rv
)) {
2241 nsCOMPtr
<nsIProfileUnlocker
> unlocker
;
2242 rv
= profile
->Lock(nsnull
, aResult
);
2243 if (NS_SUCCEEDED(rv
)) {
2245 aProfileName
->Assign(nsDependentCString(arg
));
2249 nsCOMPtr
<nsILocalFile
> profileDir
;
2250 rv
= profile
->GetRootDir(getter_AddRefs(profileDir
));
2251 NS_ENSURE_SUCCESS(rv
, rv
);
2253 nsCOMPtr
<nsILocalFile
> profileLocalDir
;
2254 rv
= profile
->GetLocalDir(getter_AddRefs(profileLocalDir
));
2255 NS_ENSURE_SUCCESS(rv
, rv
);
2257 return ProfileLockedDialog(profileDir
, profileLocalDir
, unlocker
,
2261 return ShowProfileManager(profileSvc
, aNative
);
2264 ar
= CheckArg("profilemanager", PR_TRUE
);
2265 if (ar
== ARG_BAD
) {
2266 PR_fprintf(PR_STDERR
, "Error: argument -profilemanager is invalid when argument -osint is specified\n");
2267 return NS_ERROR_FAILURE
;
2268 } else if (ar
== ARG_FOUND
) {
2269 return ShowProfileManager(profileSvc
, aNative
);
2273 gDoMigration
= PR_TRUE
;
2275 // create a default profile
2276 nsCOMPtr
<nsIToolkitProfile
> profile
;
2277 nsresult rv
= profileSvc
->CreateProfile(nsnull
, // choose a default dir for us
2278 nsnull
, // choose a default dir for us
2279 NS_LITERAL_CSTRING("default"),
2280 getter_AddRefs(profile
));
2281 if (NS_SUCCEEDED(rv
)) {
2282 profileSvc
->Flush();
2283 rv
= profile
->Lock(nsnull
, aResult
);
2284 if (NS_SUCCEEDED(rv
)) {
2286 aProfileName
->Assign(NS_LITERAL_CSTRING("default"));
2292 PRBool useDefault
= PR_TRUE
;
2294 profileSvc
->GetStartWithLastProfile(&useDefault
);
2297 nsCOMPtr
<nsIToolkitProfile
> profile
;
2298 // GetSelectedProfile will auto-select the only profile if there's just one
2299 profileSvc
->GetSelectedProfile(getter_AddRefs(profile
));
2301 nsCOMPtr
<nsIProfileUnlocker
> unlocker
;
2302 rv
= profile
->Lock(getter_AddRefs(unlocker
), aResult
);
2303 if (NS_SUCCEEDED(rv
)) {
2304 // Try to grab the profile name.
2306 rv
= profile
->GetName(*aProfileName
);
2308 aProfileName
->Truncate(0);
2313 nsCOMPtr
<nsILocalFile
> profileDir
;
2314 rv
= profile
->GetRootDir(getter_AddRefs(profileDir
));
2315 NS_ENSURE_SUCCESS(rv
, rv
);
2317 nsCOMPtr
<nsILocalFile
> profileLocalDir
;
2318 rv
= profile
->GetRootDir(getter_AddRefs(profileLocalDir
));
2319 NS_ENSURE_SUCCESS(rv
, rv
);
2321 return ProfileLockedDialog(profileDir
, profileLocalDir
, unlocker
,
2326 return ShowProfileManager(profileSvc
, aNative
);
2330 * Checks the compatibility.ini file to see if we have updated our application
2331 * or otherwise invalidated our caches. If the application has been updated,
2332 * we return PR_FALSE; otherwise, we return PR_TRUE. We also write the status
2333 * of the caches (valid/invalid) into the return param aCachesOK. The aCachesOK
2334 * is always invalid if the application has been updated.
2337 CheckCompatibility(nsIFile
* aProfileDir
, const nsCString
& aVersion
,
2338 const nsCString
& aOSABI
, nsIFile
* aXULRunnerDir
,
2339 nsIFile
* aAppDir
, nsILocalFile
* aFlagFile
,
2342 *aCachesOK
= PR_FALSE
;
2343 nsCOMPtr
<nsIFile
> file
;
2344 aProfileDir
->Clone(getter_AddRefs(file
));
2347 file
->AppendNative(FILE_COMPATIBILITY_INFO
);
2350 nsCOMPtr
<nsILocalFile
> localFile(do_QueryInterface(file
));
2351 nsresult rv
= parser
.Init(localFile
);
2356 rv
= parser
.GetString("Compatibility", "LastVersion", buf
);
2357 if (NS_FAILED(rv
) || !aVersion
.Equals(buf
))
2360 rv
= parser
.GetString("Compatibility", "LastOSABI", buf
);
2361 if (NS_FAILED(rv
) || !aOSABI
.Equals(buf
))
2364 rv
= parser
.GetString("Compatibility", "LastPlatformDir", buf
);
2368 nsCOMPtr
<nsILocalFile
> lf
;
2369 rv
= NS_NewNativeLocalFile(buf
, PR_FALSE
,
2370 getter_AddRefs(lf
));
2375 rv
= lf
->Equals(aXULRunnerDir
, &eq
);
2376 if (NS_FAILED(rv
) || !eq
)
2380 rv
= parser
.GetString("Compatibility", "LastAppDir", buf
);
2384 rv
= NS_NewNativeLocalFile(buf
, PR_FALSE
,
2385 getter_AddRefs(lf
));
2389 rv
= lf
->Equals(aAppDir
, &eq
);
2390 if (NS_FAILED(rv
) || !eq
)
2394 // If we see this flag, caches are invalid.
2395 rv
= parser
.GetString("Compatibility", "InvalidateCaches", buf
);
2396 *aCachesOK
= (NS_FAILED(rv
) || !buf
.EqualsLiteral("1"));
2399 PRBool purgeCaches
= PR_FALSE
;
2401 aFlagFile
->Exists(&purgeCaches
);
2404 *aCachesOK
= !purgeCaches
&& *aCachesOK
;
2409 static void BuildVersion(nsCString
&aBuf
)
2411 aBuf
.Assign(gAppData
->version
);
2413 aBuf
.Append(gAppData
->buildID
);
2415 aBuf
.Append(gToolkitBuildID
);
2419 WriteVersion(nsIFile
* aProfileDir
, const nsCString
& aVersion
,
2420 const nsCString
& aOSABI
, nsIFile
* aXULRunnerDir
,
2423 nsCOMPtr
<nsIFile
> file
;
2424 aProfileDir
->Clone(getter_AddRefs(file
));
2427 file
->AppendNative(FILE_COMPATIBILITY_INFO
);
2429 nsCOMPtr
<nsILocalFile
> lf
= do_QueryInterface(file
);
2431 nsCAutoString platformDir
;
2432 aXULRunnerDir
->GetNativePath(platformDir
);
2434 nsCAutoString appDir
;
2436 aAppDir
->GetNativePath(appDir
);
2438 PRFileDesc
*fd
= nsnull
;
2439 lf
->OpenNSPRFileDesc(PR_WRONLY
| PR_CREATE_FILE
| PR_TRUNCATE
, 0600, &fd
);
2441 NS_ERROR("could not create output stream");
2445 static const char kHeader
[] = "[Compatibility]" NS_LINEBREAK
2448 PR_Write(fd
, kHeader
, sizeof(kHeader
) - 1);
2449 PR_Write(fd
, aVersion
.get(), aVersion
.Length());
2451 static const char kOSABIHeader
[] = NS_LINEBREAK
"LastOSABI=";
2452 PR_Write(fd
, kOSABIHeader
, sizeof(kOSABIHeader
) - 1);
2453 PR_Write(fd
, aOSABI
.get(), aOSABI
.Length());
2455 static const char kPlatformDirHeader
[] = NS_LINEBREAK
"LastPlatformDir=";
2457 PR_Write(fd
, kPlatformDirHeader
, sizeof(kPlatformDirHeader
) - 1);
2458 PR_Write(fd
, platformDir
.get(), platformDir
.Length());
2460 static const char kAppDirHeader
[] = NS_LINEBREAK
"LastAppDir=";
2462 PR_Write(fd
, kAppDirHeader
, sizeof(kAppDirHeader
) - 1);
2463 PR_Write(fd
, appDir
.get(), appDir
.Length());
2466 static const char kNL
[] = NS_LINEBREAK
;
2467 PR_Write(fd
, kNL
, sizeof(kNL
) - 1);
2472 static void RemoveComponentRegistries(nsIFile
* aProfileDir
, nsIFile
* aLocalProfileDir
,
2473 PRBool aRemoveEMFiles
)
2475 nsCOMPtr
<nsIFile
> file
;
2476 aProfileDir
->Clone(getter_AddRefs(file
));
2480 if (aRemoveEMFiles
) {
2481 file
->SetNativeLeafName(NS_LITERAL_CSTRING("extensions.ini"));
2482 file
->Remove(PR_FALSE
);
2485 aLocalProfileDir
->Clone(getter_AddRefs(file
));
2489 file
->AppendNative(NS_LITERAL_CSTRING("XUL" PLATFORM_FASL_SUFFIX
));
2490 file
->Remove(PR_FALSE
);
2492 file
->SetNativeLeafName(NS_LITERAL_CSTRING("XPC" PLATFORM_FASL_SUFFIX
));
2493 file
->Remove(PR_FALSE
);
2495 file
->SetNativeLeafName(NS_LITERAL_CSTRING("startupCache"));
2496 file
->Remove(PR_TRUE
);
2499 // To support application initiated restart via nsIAppStartup.quit, we
2500 // need to save various environment variables, and then restore them
2501 // before re-launching the application.
2507 {"XUL_APP_FILE", nsnull
}
2510 static void SaveStateForAppInitiatedRestart()
2512 for (size_t i
= 0; i
< NS_ARRAY_LENGTH(gSavedVars
); ++i
) {
2513 const char *s
= PR_GetEnv(gSavedVars
[i
].name
);
2515 gSavedVars
[i
].value
= PR_smprintf("%s=%s", gSavedVars
[i
].name
, s
);
2519 static void RestoreStateForAppInitiatedRestart()
2521 for (size_t i
= 0; i
< NS_ARRAY_LENGTH(gSavedVars
); ++i
) {
2522 if (gSavedVars
[i
].value
)
2523 PR_SetEnv(gSavedVars
[i
].value
);
2527 #ifdef MOZ_CRASHREPORTER
2528 // When we first initialize the crash reporter we don't have a profile,
2529 // so we set the minidump path to $TEMP. Once we have a profile,
2530 // we set it to $PROFILE/minidumps, creating the directory
2532 static void MakeOrSetMinidumpPath(nsIFile
* profD
)
2534 nsCOMPtr
<nsIFile
> dumpD
;
2535 nsresult rv
= profD
->Clone(getter_AddRefs(dumpD
));
2539 //XXX: do some more error checking here
2540 dumpD
->Append(NS_LITERAL_STRING("minidumps"));
2541 rv
= dumpD
->Exists(&fileExists
);
2543 dumpD
->Create(nsIFile::DIRECTORY_TYPE
, 0700);
2546 nsAutoString pathStr
;
2547 if(NS_SUCCEEDED(dumpD
->GetPath(pathStr
)))
2548 CrashReporter::SetMinidumpPath(pathStr
);
2553 const nsXREAppData
* gAppData
= nsnull
;
2556 // because we use early returns, we use a stack-based helper to un-set the OS2 FP handler
2557 class ScopedFPHandler
{
2559 EXCEPTIONREGISTRATIONRECORD excpreg
;
2562 ScopedFPHandler() { PR_OS2_SetFloatExcpHandler(&excpreg
); }
2563 ~ScopedFPHandler() { PR_OS2_UnsetFloatExcpHandler(&excpreg
); }
2567 #ifdef MOZ_WIDGET_GTK2
2569 typedef void (*_g_set_application_name_fn
)(const gchar
*application_name
);
2570 typedef void (*_gtk_window_set_auto_startup_notification_fn
)(gboolean setting
);
2572 static PRFuncPtr
FindFunction(const char* aName
)
2574 PRLibrary
*lib
= nsnull
;
2575 PRFuncPtr result
= PR_FindFunctionSymbolAndLibrary(aName
, &lib
);
2576 // Since the library was already loaded, we can safely unload it here.
2578 PR_UnloadLibrary(lib
);
2583 static nsIWidget
* GetMainWidget(nsIDOMWindow
* aWindow
)
2585 // get the native window for this instance
2586 nsCOMPtr
<nsPIDOMWindow
> window(do_QueryInterface(aWindow
));
2587 NS_ENSURE_TRUE(window
, nsnull
);
2589 nsCOMPtr
<nsIBaseWindow
> baseWindow
2590 (do_QueryInterface(window
->GetDocShell()));
2591 NS_ENSURE_TRUE(baseWindow
, nsnull
);
2593 nsCOMPtr
<nsIWidget
> mainWidget
;
2594 baseWindow
->GetMainWidget(getter_AddRefs(mainWidget
));
2598 static nsGTKToolkit
* GetGTKToolkit()
2600 nsCOMPtr
<nsIAppShellService
> svc
= do_GetService(NS_APPSHELLSERVICE_CONTRACTID
);
2603 nsCOMPtr
<nsIDOMWindowInternal
> window
;
2604 svc
->GetHiddenDOMWindow(getter_AddRefs(window
));
2607 nsIWidget
* widget
= GetMainWidget(window
);
2610 nsIToolkit
* toolkit
= widget
->GetToolkit();
2613 return static_cast<nsGTKToolkit
*>(toolkit
);
2616 static void MOZ_gdk_display_close(GdkDisplay
*display
)
2618 // XXX wallpaper for bug 417163: don't close the Display if we're using the
2619 // Qt theme because we crash (in Qt code) when using jemalloc.
2620 PRBool theme_is_qt
= PR_FALSE
;
2621 GtkSettings
* settings
=
2622 gtk_settings_get_for_screen(gdk_display_get_default_screen(display
));
2624 g_object_get(settings
, "gtk-theme-name", &theme_name
, NULL
);
2626 theme_is_qt
= strcmp(theme_name
, "Qt") == 0;
2628 NS_WARNING("wallpaper bug 417163 for Qt theme");
2632 // gdk_display_close was broken prior to gtk+-2.10.0.
2633 // (http://bugzilla.gnome.org/show_bug.cgi?id=85715)
2634 // gdk_display_manager_set_default_display (gdk_display_manager_get(), NULL)
2636 if (gtk_check_version(2,10,0) != NULL
) {
2638 // Version check failed - broken gdk_display_close.
2640 // Let the gdk structures leak but at least close the Display,
2641 // assuming that gdk will not use it again.
2642 Display
* dpy
= GDK_DISPLAY_XDISPLAY(display
);
2646 gdk_display_close(display
);
2647 #endif /* MOZ_X11 */
2651 // Get a (new) Pango context that holds a reference to the fontmap that
2652 // GTK has been using. gdk_pango_context_get() must be called while GTK
2653 // has a default display.
2654 PangoContext
*pangoContext
= gdk_pango_context_get();
2657 PRBool buggyCairoShutdown
= cairo_version() < CAIRO_VERSION_ENCODE(1, 4, 0);
2659 if (!buggyCairoShutdown
) {
2660 // We should shut down GDK before we shut down libraries it depends on
2661 // like Pango and cairo. But if cairo shutdown is buggy, we should
2662 // shut down cairo first otherwise it may crash because of dangling
2663 // references to Display objects (see bug 469831).
2665 gdk_display_close(display
);
2669 // This doesn't take a reference.
2670 PangoFontMap
*fontmap
= pango_context_get_font_map(pangoContext
);
2671 // Do some shutdown of the fontmap, which releases the fonts, clearing a
2672 // bunch of circular references from the fontmap through the fonts back to
2673 // itself. The shutdown that this does is much less than what's done by
2674 // the fontmap's finalize, though.
2675 if (PANGO_IS_FC_FONT_MAP(fontmap
))
2676 pango_fc_font_map_shutdown(PANGO_FC_FONT_MAP(fontmap
));
2677 g_object_unref(pangoContext
);
2678 // PangoCairo still holds a reference to the fontmap.
2679 // Now that we have finished with GTK and Pango, we could unref fontmap,
2680 // which would allow us to call FcFini, but removing what is really
2681 // Pango's ref feels a bit evil. Pango-1.22 will have support for
2682 // pango_cairo_font_map_set_default(NULL), which would release the
2683 // reference on the old fontmap.
2685 #if GTK_CHECK_VERSION(2,8,0)
2686 // cairo_debug_reset_static_data() is prototyped through cairo.h included
2688 #ifdef cairo_debug_reset_static_data
2689 #error "Looks like we're including Mozilla's cairo instead of system cairo"
2691 cairo_debug_reset_static_data();
2693 #endif // CLEANUP_MEMORY
2695 if (buggyCairoShutdown
) {
2697 gdk_display_close(display
);
2701 #endif // MOZ_WIDGET_GTK2
2704 * NSPR will search for the "nspr_use_zone_allocator" symbol throughout
2705 * the process and use it to determine whether the application defines its own
2706 * memory allocator or not.
2708 * Since most applications (e.g. Firefox and Thunderbird) don't use any special
2709 * allocators and therefore don't define this symbol, NSPR must search the
2710 * entire process, which reduces startup performance.
2712 * By defining the symbol here, we can avoid the wasted lookup and hopefully
2713 * improve startup performance.
2715 NS_VISIBILITY_DEFAULT PRBool nspr_use_zone_allocator
= PR_FALSE
;
2717 #ifdef MOZ_SPLASHSCREEN
2718 #define MOZ_SPLASHSCREEN_UPDATE(_i) do { if (splashScreen) splashScreen->Update(_i); } while(0)
2720 #define MOZ_SPLASHSCREEN_UPDATE(_i) do { } while(0)
2724 typedef BOOL (WINAPI
* SetProcessDEPPolicyFunc
)(DWORD dwFlags
);
2728 XRE_main(int argc
, char* argv
[], const nsXREAppData
* aAppData
)
2732 #ifdef MOZ_SPLASHSCREEN
2733 nsSplashScreen
*splashScreen
= nsnull
;
2738 NS_TIMELINE_MARK("enter main");
2741 if (PR_GetEnv("XRE_MAIN_BREAK"))
2745 SetupErrorHandling(argv
[0]);
2748 const char *home
= PR_GetEnv("HOME");
2749 if (!home
|| !*home
) {
2750 struct passwd
*pw
= getpwuid(geteuid());
2751 if (!pw
|| !pw
->pw_dir
) {
2752 Output(PR_TRUE
, "Could not determine HOME directory");
2755 SaveWordToEnv("HOME", nsDependentCString(pw
->pw_dir
));
2759 #ifdef MOZ_ACCESSIBILITY_ATK
2760 // Reset GTK_MODULES, strip atk-bridge if exists
2761 // Mozilla will load libatk-bridge.so later if necessary
2762 const char* gtkModules
= PR_GetEnv("GTK_MODULES");
2763 if (gtkModules
&& *gtkModules
) {
2764 nsCString
gtkModulesStr(gtkModules
);
2765 gtkModulesStr
.ReplaceSubstring("atk-bridge", "");
2766 char* expr
= PR_smprintf("GTK_MODULES=%s", gtkModulesStr
.get());
2769 // We intentionally leak |expr| here since it is required by PR_SetEnv.
2772 // Suppress atk-bridge init at startup, it works after GNOME 2.24.2
2773 PR_SetEnv("NO_AT_BRIDGE=1");
2779 NS_ENSURE_TRUE(aAppData
, 2);
2782 // The xulrunner stub executable tricks CFBundleGetMainBundle on
2783 // purpose into lying about the main bundle path. It will set
2784 // XRE_BINARY_PATH to inform us of our real location.
2785 gBinaryPath
= getenv("XRE_BINARY_PATH");
2787 if (gBinaryPath
&& !*gBinaryPath
)
2788 gBinaryPath
= nsnull
;
2791 // Check for application.ini overrides
2792 const char* override
= nsnull
;
2793 ar
= CheckArg("override", PR_TRUE
, &override
);
2794 if (ar
== ARG_BAD
) {
2795 Output(PR_TRUE
, "Incorrect number of arguments passed to -override");
2798 else if (ar
== ARG_FOUND
) {
2799 nsCOMPtr
<nsILocalFile
> overrideLF
;
2800 rv
= XRE_GetFileFromPath(override
, getter_AddRefs(overrideLF
));
2801 if (NS_FAILED(rv
)) {
2802 Output(PR_TRUE
, "Error: unrecognized override.ini path.\n");
2806 nsXREAppData
* overrideAppData
= const_cast<nsXREAppData
*>(aAppData
);
2807 rv
= XRE_ParseAppData(overrideLF
, overrideAppData
);
2808 if (NS_FAILED(rv
)) {
2809 Output(PR_TRUE
, "Couldn't read override.ini");
2814 ScopedAppData
appData(aAppData
);
2815 gAppData
= &appData
;
2817 // Check sanity and correctness of app data.
2819 if (!appData
.name
) {
2820 Output(PR_TRUE
, "Error: App:Name not specified in application.ini\n");
2823 if (!appData
.buildID
) {
2824 Output(PR_TRUE
, "Error: App:BuildID not specified in application.ini\n");
2828 #ifdef MOZ_SPLASHSCREEN
2829 // check to see if we need to do a splash screen
2830 PRBool wantsSplash
= PR_TRUE
;
2831 PRBool isNoSplash
= (CheckArg("nosplash", PR_FALSE
, NULL
, PR_FALSE
) == ARG_FOUND
);
2832 isNoSplash
|= (PR_GetEnv("NO_SPLASH") != 0);
2833 PRBool isNoRemote
= (CheckArg("no-remote", PR_FALSE
, NULL
, PR_FALSE
) == ARG_FOUND
);
2836 // synchronize startup; if it looks like we're going to have to
2837 // wait, then open up a splash screen
2838 WindowsMutex
winStartupMutex(L
"FirefoxStartupMutex");
2840 // try to lock the mutex, but only wait 100ms to do so
2841 PRBool needsMutexLock
= ! winStartupMutex
.Lock(100);
2843 // If we failed to lock the mutex quickly, then we'll want
2844 // a splash screen for sure.
2846 // If we did manage to lock it, then we'll only want one
2847 // a splash screen if there is no existing message window;
2848 // that is, if we are the first instance of the app.
2849 if (!needsMutexLock
&& !isNoRemote
) {
2850 // check to see if there's a remote firefox up
2851 static PRUnichar classNameBuffer
[128];
2852 _snwprintf(classNameBuffer
, sizeof(classNameBuffer
) / sizeof(PRUnichar
),
2854 gAppData
->name
, L
"MessageWindow");
2855 HANDLE h
= FindWindowW(classNameBuffer
, 0);
2857 // Someone else has the window, and we were able to grab the mutex,
2858 // meaning the other instance ahs presumably already finished starting
2859 // up by now. So no need for a splash screen.
2860 wantsSplash
= PR_FALSE
;
2863 // We couldn't find another window, and we were able to lock the mutex;
2864 // we're likely the first instance starting up, so make sure a splash
2865 // screen gets thrown up.
2866 wantsSplash
= PR_TRUE
;
2871 if (wantsSplash
&& !isNoSplash
)
2872 splashScreen
= nsSplashScreen::GetOrCreate();
2875 splashScreen
->Open();
2878 // Now that the splash screen is open, wait indefinitely
2879 // for the startup mutex on this thread if we need to.
2881 winStartupMutex
.Lock();
2884 #endif //MOZ_SPLASHSCREEN
2889 if (!appData
.xreDirectory
) {
2890 nsCOMPtr
<nsILocalFile
> lf
;
2891 rv
= XRE_GetBinaryPath(gArgv
[0], getter_AddRefs(lf
));
2895 nsCOMPtr
<nsIFile
> greDir
;
2896 rv
= lf
->GetParent(getter_AddRefs(greDir
));
2900 rv
= CallQueryInterface(greDir
, &appData
.xreDirectory
);
2905 if (appData
.size
> offsetof(nsXREAppData
, minVersion
)) {
2906 if (!appData
.minVersion
) {
2907 Output(PR_TRUE
, "Error: Gecko:MinVersion not specified in application.ini\n");
2911 if (!appData
.maxVersion
) {
2912 // If no maxVersion is specified, we assume the app is only compatible
2913 // with the initial preview release. Do not increment this number ever!
2914 SetAllocatedString(appData
.maxVersion
, "1.*");
2917 if (NS_CompareVersions(appData
.minVersion
, gToolkitVersion
) > 0 ||
2918 NS_CompareVersions(appData
.maxVersion
, gToolkitVersion
) < 0) {
2919 Output(PR_TRUE
, "Error: Platform version '%s' is not compatible with\n"
2920 "minVersion >= %s\nmaxVersion <= %s\n",
2922 appData
.minVersion
, appData
.maxVersion
);
2927 nsXREDirProvider dirProvider
;
2928 rv
= dirProvider
.Initialize(gAppData
->directory
, gAppData
->xreDirectory
);
2932 #ifdef MOZ_CRASHREPORTER
2933 const char* crashreporterEnv
= PR_GetEnv("MOZ_CRASHREPORTER");
2934 if (crashreporterEnv
&& *crashreporterEnv
) {
2935 appData
.flags
|= NS_XRE_ENABLE_CRASH_REPORTER
;
2938 if ((appData
.flags
& NS_XRE_ENABLE_CRASH_REPORTER
) &&
2940 CrashReporter::SetExceptionHandler(appData
.xreDirectory
))) {
2941 if (appData
.crashReporterURL
)
2942 CrashReporter::SetServerURL(nsDependentCString(appData
.crashReporterURL
));
2944 // pass some basic info from the app data
2946 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Vendor"),
2947 nsDependentCString(appData
.vendor
));
2949 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ProductName"),
2950 nsDependentCString(appData
.name
));
2951 if (appData
.version
)
2952 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Version"),
2953 nsDependentCString(appData
.version
));
2954 if (appData
.buildID
)
2955 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("BuildID"),
2956 nsDependentCString(appData
.buildID
));
2957 CrashReporter::SetRestartArgs(argc
, argv
);
2959 // annotate other data (user id etc)
2960 nsCOMPtr
<nsILocalFile
> userAppDataDir
;
2961 if (NS_SUCCEEDED(dirProvider
.GetUserAppDataDirectory(
2962 getter_AddRefs(userAppDataDir
)))) {
2963 CrashReporter::SetupExtraData(userAppDataDir
,
2964 nsDependentCString(appData
.buildID
));
2966 // see if we have a crashreporter-override.ini in the application directory
2967 nsCOMPtr
<nsIFile
> overrideini
;
2969 static char overrideEnv
[MAXPATHLEN
];
2970 if (NS_SUCCEEDED(dirProvider
.GetAppDir()->Clone(getter_AddRefs(overrideini
))) &&
2971 NS_SUCCEEDED(overrideini
->AppendNative(NS_LITERAL_CSTRING("crashreporter-override.ini"))) &&
2972 NS_SUCCEEDED(overrideini
->Exists(&exists
)) &&
2975 nsAutoString overridePathW
;
2976 overrideini
->GetPath(overridePathW
);
2977 NS_ConvertUTF16toUTF8
overridePath(overridePathW
);
2979 nsCAutoString overridePath
;
2980 overrideini
->GetNativePath(overridePath
);
2983 sprintf(overrideEnv
, "MOZ_CRASHREPORTER_STRINGS_OVERRIDE=%s",
2984 overridePath
.get());
2985 PR_SetEnv(overrideEnv
);
2992 if (PR_GetEnv("MOZ_LAUNCHED_CHILD")) {
2993 // This is needed, on relaunch, to force the OS to use the "Cocoa Dock
2994 // API". Otherwise the call to ReceiveNextEvent() below will make it
2995 // use the "Carbon Dock API". For more info see bmo bug 377166.
2996 EnsureUseCocoaDockAPI();
2998 // When the app relaunches, the original process exits. This causes
2999 // the dock tile to stop bouncing, lose the "running" triangle, and
3000 // if the tile does not permanently reside in the Dock, even disappear.
3001 // This can be confusing to the user, who is expecting the app to launch.
3002 // Calling ReceiveNextEvent without requesting any event is enough to
3003 // cause a dock tile for the child process to appear.
3004 const EventTypeSpec kFakeEventList
[] = { { INT_MAX
, INT_MAX
} };
3006 ::ReceiveNextEvent(GetEventTypeCount(kFakeEventList
), kFakeEventList
,
3007 kEventDurationNoWait
, PR_FALSE
, &event
);
3010 if (CheckArg("foreground")) {
3011 // The original process communicates that it was in the foreground by
3012 // adding this argument. This new process, which is taking over for
3013 // the old one, should make itself the active application.
3014 ProcessSerialNumber psn
;
3015 if (::GetCurrentProcess(&psn
) == noErr
)
3016 ::SetFrontProcess(&psn
);
3020 SaveToEnv("MOZ_LAUNCHED_CHILD=");
3022 gRestartArgc
= gArgc
;
3023 gRestartArgv
= (char**) malloc(sizeof(char*) * (gArgc
+ 1 + (override
? 2 : 0)));
3024 if (!gRestartArgv
) return 1;
3027 for (i
= 0; i
< gArgc
; ++i
) {
3028 gRestartArgv
[i
] = gArgv
[i
];
3031 // Add the -override argument back (it is removed automatically be CheckArg) if there is one
3033 gRestartArgv
[gRestartArgc
++] = const_cast<char*>("-override");
3034 gRestartArgv
[gRestartArgc
++] = const_cast<char*>(override
);
3037 gRestartArgv
[gRestartArgc
] = nsnull
;
3041 PRBool
StartOS2App(int aArgc
, char **aArgv
);
3042 if (!StartOS2App(gArgc
, gArgv
))
3044 ScopedFPHandler handler
;
3047 ar
= CheckArg("safe-mode", PR_TRUE
);
3048 if (ar
== ARG_BAD
) {
3049 PR_fprintf(PR_STDERR
, "Error: argument -safe-mode is invalid when argument -osint is specified\n");
3051 } else if (ar
== ARG_FOUND
) {
3052 gSafeMode
= PR_TRUE
;
3056 if (GetCurrentEventKeyModifiers() & optionKey
)
3057 gSafeMode
= PR_TRUE
;
3060 // Handle -no-remote command line argument. Setup the environment to
3061 // better accommodate other components and various restart scenarios.
3062 ar
= CheckArg("no-remote", PR_TRUE
);
3063 if (ar
== ARG_BAD
) {
3064 PR_fprintf(PR_STDERR
, "Error: argument -a requires an application name\n");
3066 } else if (ar
== ARG_FOUND
) {
3067 SaveToEnv("MOZ_NO_REMOTE=1");
3070 // Handle -help and -version command line arguments.
3071 // They should return quickly, so we deal with them here.
3072 if (CheckArg("h") || CheckArg("help") || CheckArg("?")) {
3077 if (CheckArg("v") || CheckArg("version")) {
3082 #ifdef NS_TRACE_MALLOC
3083 gArgc
= argc
= NS_TraceMallocStartupArgs(gArgc
, gArgv
);
3086 MOZ_SPLASHSCREEN_UPDATE(20);
3088 rv
= XRE_InitCommandLine(gArgc
, gArgv
);
3089 NS_ENSURE_SUCCESS(rv
, 1);
3092 // Check for -register, which registers chrome and then exits immediately.
3093 ar
= CheckArg("register", PR_TRUE
);
3094 if (ar
== ARG_BAD
) {
3095 PR_fprintf(PR_STDERR
, "Error: argument -register is invalid when argument -osint is specified\n");
3097 } else if (ar
== ARG_FOUND
) {
3098 ScopedXPCOMStartup xpcom
;
3099 rv
= xpcom
.Initialize();
3100 NS_ENSURE_SUCCESS(rv
, 1);
3103 nsCOMPtr
<nsIChromeRegistry
> chromeReg
=
3104 mozilla::services::GetChromeRegistryService();
3105 NS_ENSURE_TRUE(chromeReg
, 1);
3107 chromeReg
->CheckForNewChrome();
3112 #if defined(MOZ_WIDGET_GTK2) || defined(MOZ_ENABLE_XREMOTE)
3113 // Stash DESKTOP_STARTUP_ID in malloc'ed memory because gtk_init will clear it.
3114 #define HAVE_DESKTOP_STARTUP_ID
3115 const char* desktopStartupIDEnv
= PR_GetEnv("DESKTOP_STARTUP_ID");
3116 nsCAutoString desktopStartupID
;
3117 if (desktopStartupIDEnv
) {
3118 desktopStartupID
.Assign(desktopStartupIDEnv
);
3122 #if defined(MOZ_WIDGET_QT)
3123 const char* qgraphicssystemARG
= NULL
;
3124 ar
= CheckArg("graphicssystem", PR_TRUE
, &qgraphicssystemARG
, PR_FALSE
);
3125 if (ar
== ARG_FOUND
)
3126 PR_SetEnv(PR_smprintf("MOZ_QT_GRAPHICSSYSTEM=%s", qgraphicssystemARG
));
3128 #ifdef MOZ_ENABLE_MEEGOTOUCH
3129 QScopedPointer
<QApplication
> app
;
3130 if (XRE_GetProcessType() == GeckoProcessType_Default
) {
3131 MozMeegoAppService
*appService
= new MozMeegoAppService
;
3132 app
.reset(new MApplication(gArgc
, gArgv
, appService
));
3134 app
.reset(new QApplication(gArgc
, gArgv
));
3137 QScopedPointer
<QApplication
> app(new QApplication(gArgc
, gArgv
));
3140 #if MOZ_PLATFORM_MAEMO > 5
3141 if (XRE_GetProcessType() == GeckoProcessType_Default
) {
3142 // try to get the MInputContext if possible to support the MeeGo VKB
3143 QInputContext
* inputContext
= app
->inputContext();
3144 if (inputContext
&& inputContext
->identifierName() != "MInputContext") {
3145 QInputContext
* context
= QInputContextFactory::create("MInputContext",
3148 app
->setInputContext(context
);
3152 QStringList nonQtArguments
= app
->arguments();
3154 gQtOnlyArgv
= (char**) malloc(sizeof(char*)
3155 * (gRestartArgc
- nonQtArguments
.size() + 2));
3158 gQtOnlyArgv
[0] = gRestartArgv
[0];
3160 for (int i
= 1; i
< gRestartArgc
; ++i
) {
3161 if (!nonQtArguments
.contains(gRestartArgv
[i
])) {
3162 // copy arguments used by Qt for later
3163 gQtOnlyArgv
[gQtOnlyArgc
++] = gRestartArgv
[i
];
3166 gQtOnlyArgv
[gQtOnlyArgc
] = nsnull
;
3168 #if defined(MOZ_WIDGET_GTK2)
3170 // Disable the slice allocator, since jemalloc already uses similar layout
3171 // algorithms, and using a sub-allocator tends to increase fragmentation.
3172 // This must be done before g_thread_init() is called.
3173 g_slice_set_config(G_SLICE_CONFIG_ALWAYS_MALLOC
, 1);
3175 g_thread_init(NULL
);
3176 // setup for private colormap. Ideally we'd like to do this
3177 // in nsAppShell::Create, but we need to get in before gtk
3178 // has been initialized to make sure everything is running
3180 if (CheckArg("install"))
3181 gdk_rgb_set_install(TRUE
);
3183 // Initialize GTK here for splash.
3185 // Open the display ourselves instead of using gtk_init, so that we can
3186 // close it without fear that one day gtk might clean up the display it
3188 if (!gtk_parse_args(&gArgc
, &gArgv
))
3191 // display_name is owned by gdk.
3192 const char *display_name
= gdk_get_display_arg_name();
3194 SaveWordToEnv("DISPLAY", nsDependentCString(display_name
));
3196 display_name
= PR_GetEnv("DISPLAY");
3197 if (!display_name
) {
3198 PR_fprintf(PR_STDERR
, "Error: no display specified\n");
3202 #endif /* MOZ_WIDGET_GTK2 */
3204 #ifdef MOZ_ENABLE_XREMOTE
3205 // handle -remote now that xpcom is fired up
3207 const char* xremotearg
;
3208 ar
= CheckArg("remote", PR_TRUE
, &xremotearg
);
3209 if (ar
== ARG_BAD
) {
3210 PR_fprintf(PR_STDERR
, "Error: -remote requires an argument\n");
3213 const char* desktopStartupIDPtr
=
3214 desktopStartupID
.IsEmpty() ? nsnull
: desktopStartupID
.get();
3216 return HandleRemoteArgument(xremotearg
, desktopStartupIDPtr
);
3219 if (!PR_GetEnv("MOZ_NO_REMOTE")) {
3220 // Try to remote the entire command line. If this fails, start up normally.
3221 RemoteResult rr
= RemoteCommandLine(desktopStartupIDPtr
);
3222 if (rr
== REMOTE_FOUND
)
3224 else if (rr
== REMOTE_ARG_BAD
)
3229 #if defined(MOZ_WIDGET_GTK2)
3230 GdkDisplay
* display
= nsnull
;
3231 display
= gdk_display_open(display_name
);
3233 PR_fprintf(PR_STDERR
, "Error: cannot open display: %s\n", display_name
);
3236 gdk_display_manager_set_default_display (gdk_display_manager_get(),
3239 // g_set_application_name () is only defined in glib2.2 and higher.
3240 _g_set_application_name_fn _g_set_application_name
=
3241 (_g_set_application_name_fn
)FindFunction("g_set_application_name");
3242 if (_g_set_application_name
) {
3243 _g_set_application_name(gAppData
->name
);
3245 _gtk_window_set_auto_startup_notification_fn _gtk_window_set_auto_startup_notification
=
3246 (_gtk_window_set_auto_startup_notification_fn
)FindFunction("gtk_window_set_auto_startup_notification");
3247 if (_gtk_window_set_auto_startup_notification
) {
3248 _gtk_window_set_auto_startup_notification(PR_FALSE
);
3251 gtk_widget_set_default_colormap(gdk_rgb_get_colormap());
3252 #endif /* MOZ_WIDGET_GTK2 */
3254 // Do this after initializing GDK, or GDK will install its own handler.
3255 InstallX11ErrorHandler();
3258 // Call the code to install our handler
3260 setupProfilingStuff();
3263 // Try to allocate "native app support."
3264 nsCOMPtr
<nsINativeAppSupport
> nativeApp
;
3265 rv
= NS_CreateNativeAppSupport(getter_AddRefs(nativeApp
));
3269 PRBool canRun
= PR_FALSE
;
3270 rv
= nativeApp
->Start(&canRun
);
3271 if (NS_FAILED(rv
) || !canRun
) {
3275 #if defined(MOZ_UPDATER) && !defined(ANDROID)
3276 // Check for and process any available updates
3277 nsCOMPtr
<nsIFile
> updRoot
;
3279 rv
= dirProvider
.GetFile(XRE_UPDATE_ROOT_DIR
, &persistent
,
3280 getter_AddRefs(updRoot
));
3281 // XRE_UPDATE_ROOT_DIR may fail. Fallback to appDir if failed
3283 updRoot
= dirProvider
.GetAppDir();
3285 ProcessUpdates(dirProvider
.GetGREDir(),
3286 dirProvider
.GetAppDir(),
3293 nsCOMPtr
<nsIProfileLock
> profileLock
;
3294 PRBool startOffline
= PR_FALSE
;
3295 nsCAutoString profileName
;
3297 rv
= SelectProfile(getter_AddRefs(profileLock
), nativeApp
, &startOffline
,
3299 if (rv
== NS_ERROR_LAUNCHED_CHILD_PROCESS
||
3300 rv
== NS_ERROR_ABORT
) return 0;
3302 if (NS_FAILED(rv
)) {
3303 // We failed to choose or create profile - notify user and quit
3304 ProfileMissingDialog(nativeApp
);
3308 nsCOMPtr
<nsILocalFile
> profD
;
3309 rv
= profileLock
->GetDirectory(getter_AddRefs(profD
));
3310 NS_ENSURE_SUCCESS(rv
, 1);
3312 nsCOMPtr
<nsILocalFile
> profLD
;
3313 rv
= profileLock
->GetLocalDirectory(getter_AddRefs(profLD
));
3314 NS_ENSURE_SUCCESS(rv
, 1);
3316 rv
= dirProvider
.SetProfile(profD
, profLD
);
3317 NS_ENSURE_SUCCESS(rv
, 1);
3319 #if defined(WINCE) && defined(MOZ_SPLASHSCREEN)
3320 // give up the mutex, let other app startups happen
3321 winStartupMutex
.Unlock();
3324 //////////////////////// NOW WE HAVE A PROFILE ////////////////////////
3326 #ifdef MOZ_CRASHREPORTER
3327 if (appData
.flags
& NS_XRE_ENABLE_CRASH_REPORTER
)
3328 MakeOrSetMinidumpPath(profD
);
3331 nsCAutoString version
;
3332 BuildVersion(version
);
3334 #ifdef TARGET_OS_ABI
3335 NS_NAMED_LITERAL_CSTRING(osABI
, TARGET_OS_ABI
);
3337 // No TARGET_XPCOM_ABI, but at least the OS is known
3338 NS_NAMED_LITERAL_CSTRING(osABI
, OS_TARGET
"_UNKNOWN");
3341 // Check for version compatibility with the last version of the app this
3342 // profile was started with. The format of the version stamp is defined
3343 // by the BuildVersion function.
3344 // Also check to see if something has happened to invalidate our
3345 // fastload caches, like an extension upgrade or installation.
3347 // If we see .purgecaches, that means someone did a make.
3348 // Re-register components to catch potential changes.
3349 // We only offer this in debug builds, though.
3350 nsCOMPtr
<nsILocalFile
> flagFile
;
3352 rv
= NS_ERROR_FILE_NOT_FOUND
;
3353 nsCOMPtr
<nsIFile
> fFlagFile
;
3354 if (gAppData
->directory
) {
3355 rv
= gAppData
->directory
->Clone(getter_AddRefs(fFlagFile
));
3357 flagFile
= do_QueryInterface(fFlagFile
);
3359 flagFile
->AppendNative(FILE_INVALIDATE_CACHES
);
3363 PRBool versionOK
= CheckCompatibility(profD
, version
, osABI
,
3364 dirProvider
.GetGREDir(),
3365 gAppData
->directory
, flagFile
,
3367 if (CheckArg("purgecaches")) {
3368 cachesOK
= PR_FALSE
;
3370 if (PR_GetEnv("MOZ_PURGE_CACHES")) {
3371 cachesOK
= PR_FALSE
;
3374 // Every time a profile is loaded by a build with a different version,
3375 // it updates the compatibility.ini file saying what version last wrote
3376 // the fastload caches. On subsequent launches if the version matches,
3377 // there is no need for re-registration. If the user loads the same
3378 // profile in different builds the component registry must be
3379 // re-generated to prevent mysterious component loading failures.
3382 RemoveComponentRegistries(profD
, profLD
, PR_FALSE
);
3383 WriteVersion(profD
, NS_LITERAL_CSTRING("Safe Mode"), osABI
,
3384 dirProvider
.GetGREDir(), gAppData
->directory
);
3386 else if (versionOK
) {
3388 // Remove caches, forcing component re-registration.
3389 // The new list of additional components directories is derived from
3390 // information in "extensions.ini".
3391 RemoveComponentRegistries(profD
, profLD
, PR_FALSE
);
3393 // Rewrite compatibility.ini to remove the flag
3394 WriteVersion(profD
, version
, osABI
,
3395 dirProvider
.GetGREDir(), gAppData
->directory
);
3397 // Nothing need be done for the normal startup case.
3400 // Remove caches, forcing component re-registration
3401 // with the default set of components (this disables any potentially
3402 // troublesome incompatible XPCOM components).
3403 RemoveComponentRegistries(profD
, profLD
, PR_TRUE
);
3405 // Write out version
3406 WriteVersion(profD
, version
, osABI
,
3407 dirProvider
.GetGREDir(), gAppData
->directory
);
3412 flagFile
->Remove(PR_TRUE
);
3415 PRBool appInitiatedRestart
= PR_FALSE
;
3417 MOZ_SPLASHSCREEN_UPDATE(30);
3419 NS_TIME_FUNCTION_MARK("Next: ScopedXPCOMStartup");
3421 NS_TIME_FUNCTION_MARK("ScopedXPCOMStartup");
3423 // Allows the user to forcefully bypass the restart process at their
3424 // own risk. Useful for debugging or for tinderboxes where child
3425 // processes can be problematic.
3427 // Start the real application
3428 ScopedXPCOMStartup xpcom
;
3429 rv
= xpcom
.Initialize();
3430 NS_TIME_FUNCTION_MARK("ScopedXPCOMStartup: Initialize");
3431 NS_ENSURE_SUCCESS(rv
, 1);
3434 #ifdef NS_FUNCTION_TIMER
3435 // initialize some common services, so we don't pay the cost for these at odd times later on;
3436 // SetWindowCreator -> ChromeRegistry -> IOService -> SocketTransportService -> (nspr wspm init), Prefs
3438 nsCOMPtr
<nsISupports
> comp
;
3440 comp
= do_GetService("@mozilla.org/preferences-service;1");
3441 NS_TIME_FUNCTION_MARK("Pref Service");
3443 comp
= do_GetService("@mozilla.org/network/socket-transport-service;1");
3444 NS_TIME_FUNCTION_MARK("Socket Transport Service");
3446 comp
= do_GetService("@mozilla.org/network/dns-service;1");
3447 NS_TIME_FUNCTION_MARK("DNS Service");
3449 comp
= do_GetService("@mozilla.org/network/io-service;1");
3450 NS_TIME_FUNCTION_MARK("IO Service");
3452 comp
= do_GetService("@mozilla.org/chrome/chrome-registry;1");
3453 NS_TIME_FUNCTION_MARK("Chrome Registry Service");
3455 comp
= do_GetService("@mozilla.org/focus-event-suppressor-service;1");
3456 NS_TIME_FUNCTION_MARK("Focus Event Suppressor Service");
3460 rv
= xpcom
.SetWindowCreator(nativeApp
);
3461 NS_TIME_FUNCTION_MARK("ScopedXPCOMStartup: SetWindowCreator");
3462 NS_ENSURE_SUCCESS(rv
, 1);
3464 NS_TIME_FUNCTION_MARK("ScopedXPCOMStartup: Done");
3466 #ifdef MOZ_CRASHREPORTER
3467 // tell the crash reporter to also send the release channel
3468 nsCOMPtr
<nsIPrefService
> prefs
= do_GetService("@mozilla.org/preferences-service;1", &rv
);
3469 if (NS_SUCCEEDED(rv
)) {
3470 nsCOMPtr
<nsIPrefBranch
> defaultPrefBranch
;
3471 rv
= prefs
->GetDefaultBranch(nsnull
, getter_AddRefs(defaultPrefBranch
));
3473 if (NS_SUCCEEDED(rv
)) {
3474 nsXPIDLCString sval
;
3475 rv
= defaultPrefBranch
->GetCharPref("app.update.channel", getter_Copies(sval
));
3476 if (NS_SUCCEEDED(rv
)) {
3477 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ReleaseChannel"),
3484 NS_TIME_FUNCTION_MARK("Next: AppStartup");
3488 nsCOMPtr
<nsIIOService2
> io (do_GetService("@mozilla.org/network/io-service;1"));
3489 NS_ENSURE_TRUE(io
, 1);
3490 io
->SetManageOfflineStatus(PR_FALSE
);
3491 io
->SetOffline(PR_TRUE
);
3495 NS_TIMELINE_ENTER("startupNotifier");
3496 nsCOMPtr
<nsIObserver
> startupNotifier
3497 (do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID
, &rv
));
3498 NS_ENSURE_SUCCESS(rv
, 1);
3500 startupNotifier
->Observe(nsnull
, APPSTARTUP_TOPIC
, nsnull
);
3501 NS_TIMELINE_LEAVE("startupNotifier");
3504 NS_TIME_FUNCTION_MARK("Finished startupNotifier");
3506 nsCOMPtr
<nsIAppStartup2
> appStartup
3507 (do_GetService(NS_APPSTARTUP_CONTRACTID
));
3508 NS_ENSURE_TRUE(appStartup
, 1);
3510 NS_TIME_FUNCTION_MARK("Created AppStartup");
3513 nsCOMPtr
<nsIFile
> file
;
3514 dirProvider
.GetAppDir()->Clone(getter_AddRefs(file
));
3515 file
->AppendNative(NS_LITERAL_CSTRING("override.ini"));
3517 nsCOMPtr
<nsILocalFile
> localFile(do_QueryInterface(file
));
3518 nsresult rv
= parser
.Init(localFile
);
3519 if (NS_SUCCEEDED(rv
)) {
3521 rv
= parser
.GetString("XRE", "EnableProfileMigrator", buf
);
3522 if (NS_SUCCEEDED(rv
)) {
3523 if (buf
[0] == '0' || buf
[0] == 'f' || buf
[0] == 'F') {
3524 gDoMigration
= PR_FALSE
;
3530 // Profile Migration
3531 if (gAppData
->flags
& NS_XRE_ENABLE_PROFILE_MIGRATOR
&& gDoMigration
) {
3532 gDoMigration
= PR_FALSE
;
3533 nsCOMPtr
<nsIProfileMigrator
> pm
3534 (do_CreateInstance(NS_PROFILEMIGRATOR_CONTRACTID
));
3536 pm
->Migrate(&dirProvider
);
3539 NS_TIME_FUNCTION_MARK("Profile migration");
3541 dirProvider
.DoStartup();
3543 NS_TIME_FUNCTION_MARK("dirProvider.DoStartup() (profile-after-change)");
3545 PRBool shuttingDown
= PR_FALSE
;
3546 appStartup
->GetShuttingDown(&shuttingDown
);
3548 nsCOMPtr
<nsICommandLineRunner
> cmdLine
;
3550 nsCOMPtr
<nsIFile
> workingDir
;
3551 rv
= NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR
, getter_AddRefs(workingDir
));
3552 NS_ENSURE_SUCCESS(rv
, 1);
3554 if (!shuttingDown
) {
3555 cmdLine
= do_CreateInstance("@mozilla.org/toolkit/command-line;1");
3556 NS_ENSURE_TRUE(cmdLine
, 1);
3558 rv
= cmdLine
->Init(gArgc
, gArgv
,
3559 workingDir
, nsICommandLine::STATE_INITIAL_LAUNCH
);
3560 NS_ENSURE_SUCCESS(rv
, 1);
3562 /* Special-case services that need early access to the command
3564 nsCOMPtr
<nsIObserverService
> obsService
=
3565 mozilla::services::GetObserverService();
3567 obsService
->NotifyObservers(cmdLine
, "command-line-startup", nsnull
);
3570 NS_TIME_FUNCTION_MARK("Early command line init");
3572 NS_TIME_FUNCTION_MARK("Next: prepare for Run");
3575 SaveStateForAppInitiatedRestart();
3577 // clear out any environment variables which may have been set
3578 // during the relaunch process now that we know we won't be relaunching.
3579 SaveToEnv("XRE_PROFILE_PATH=");
3580 SaveToEnv("XRE_PROFILE_LOCAL_PATH=");
3581 SaveToEnv("XRE_PROFILE_NAME=");
3582 SaveToEnv("XRE_START_OFFLINE=");
3583 SaveToEnv("XRE_IMPORT_PROFILES=");
3584 SaveToEnv("NO_EM_RESTART=");
3585 SaveToEnv("XUL_APP_FILE=");
3586 SaveToEnv("XRE_BINARY_PATH=");
3588 NS_TIME_FUNCTION_MARK("env munging");
3590 if (!shuttingDown
) {
3591 NS_TIME_FUNCTION_MARK("Next: CreateHiddenWindow");
3593 NS_TIMELINE_ENTER("appStartup->CreateHiddenWindow");
3594 rv
= appStartup
->CreateHiddenWindow();
3595 NS_TIMELINE_LEAVE("appStartup->CreateHiddenWindow");
3596 NS_ENSURE_SUCCESS(rv
, 1);
3598 MOZ_SPLASHSCREEN_UPDATE(50);
3600 #if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK2)
3601 nsRefPtr
<nsGTKToolkit
> toolkit
= GetGTKToolkit();
3602 if (toolkit
&& !desktopStartupID
.IsEmpty()) {
3603 toolkit
->SetDesktopStartupID(desktopStartupID
);
3608 // we re-initialize the command-line service and do appleevents munging
3609 // after we are sure that we're not restarting
3610 cmdLine
= do_CreateInstance("@mozilla.org/toolkit/command-line;1");
3611 NS_ENSURE_TRUE(cmdLine
, 1);
3613 CommandLineServiceMac::SetupMacCommandLine(gArgc
, gArgv
, PR_FALSE
);
3615 rv
= cmdLine
->Init(gArgc
, gArgv
,
3616 workingDir
, nsICommandLine::STATE_INITIAL_LAUNCH
);
3617 NS_ENSURE_SUCCESS(rv
, 1);
3619 // Set up ability to respond to system (Apple) events.
3620 SetupMacApplicationDelegate();
3623 MOZ_SPLASHSCREEN_UPDATE(70);
3625 nsCOMPtr
<nsIObserverService
> obsService
=
3626 mozilla::services::GetObserverService();
3628 obsService
->NotifyObservers(nsnull
, "final-ui-startup", nsnull
);
3630 NS_TIME_FUNCTION_MARK("final-ui-startup done");
3632 appStartup
->GetShuttingDown(&shuttingDown
);
3635 if (!shuttingDown
) {
3636 rv
= cmdLine
->Run();
3637 NS_ENSURE_SUCCESS_LOG(rv
, 1);
3639 appStartup
->GetShuttingDown(&shuttingDown
);
3642 #ifdef MOZ_ENABLE_XREMOTE
3643 nsCOMPtr
<nsIRemoteService
> remoteService
;
3644 #endif /* MOZ_ENABLE_XREMOTE */
3645 if (!shuttingDown
) {
3646 #ifdef MOZ_ENABLE_XREMOTE
3647 // if we have X remote support, start listening for requests on the
3649 remoteService
= do_GetService("@mozilla.org/toolkit/remote-service;1");
3651 remoteService
->Startup(gAppData
->name
,
3652 PromiseFlatCString(profileName
).get());
3653 #endif /* MOZ_ENABLE_XREMOTE */
3655 nativeApp
->Enable();
3658 NS_TIME_FUNCTION_MARK("Next: Run");
3660 NS_TIME_FUNCTION_MARK("appStartup->Run");
3662 MOZ_SPLASHSCREEN_UPDATE(90);
3664 NS_TIMELINE_ENTER("appStartup->Run");
3665 rv
= appStartup
->Run();
3666 NS_TIMELINE_LEAVE("appStartup->Run");
3667 if (NS_FAILED(rv
)) {
3668 NS_ERROR("failed to run appstartup");
3669 gLogConsoleErrors
= PR_TRUE
;
3673 NS_TIME_FUNCTION_MARK("Next: Finish");
3675 NS_TIME_FUNCTION_MARK("appStartup->Run done");
3677 // Check for an application initiated restart. This is one that
3678 // corresponds to nsIAppStartup.quit(eRestart)
3679 if (rv
== NS_SUCCESS_RESTART_APP
)
3680 appInitiatedRestart
= PR_TRUE
;
3682 if (!shuttingDown
) {
3683 #ifdef MOZ_ENABLE_XREMOTE
3684 // shut down the x remote proxy window
3686 remoteService
->Shutdown();
3687 #endif /* MOZ_ENABLE_XREMOTE */
3691 // Make sure we print this out even if timeline is runtime disabled
3692 if (NS_FAILED(NS_TIMELINE_LEAVE("main1")))
3693 NS_TimelineForceMark("...main1");
3698 // unlock the profile after ScopedXPCOMStartup object (xpcom)
3699 // has gone out of scope. see bug #386739 for more details
3700 profileLock
->Unlock();
3702 // Restart the app after XPCOM has been shut down cleanly.
3703 if (appInitiatedRestart
) {
3704 MOZ_SPLASHSCREEN_UPDATE(90);
3706 RestoreStateForAppInitiatedRestart();
3708 // Ensure that these environment variables are set:
3709 SaveFileToEnvIfUnset("XRE_PROFILE_PATH", profD
);
3710 SaveFileToEnvIfUnset("XRE_PROFILE_LOCAL_PATH", profLD
);
3711 SaveWordToEnvIfUnset("XRE_PROFILE_NAME", profileName
);
3715 static char kEnvVar
[MAXPATHLEN
];
3716 sprintf(kEnvVar
, "XRE_BINARY_PATH=%s", gBinaryPath
);
3721 #if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK2)
3722 if (!desktopStartupID
.IsEmpty()) {
3723 nsCAutoString desktopStartupEnv
;
3724 desktopStartupEnv
.AssignLiteral("DESKTOP_STARTUP_ID=");
3725 desktopStartupEnv
.Append(desktopStartupID
);
3726 // Leak it with extreme prejudice!
3727 PR_SetEnv(ToNewCString(desktopStartupEnv
));
3731 #ifdef MOZ_WIDGET_GTK2
3732 MOZ_gdk_display_close(display
);
3735 rv
= LaunchChild(nativeApp
, PR_TRUE
);
3737 #ifdef MOZ_CRASHREPORTER
3738 if (appData
.flags
& NS_XRE_ENABLE_CRASH_REPORTER
)
3739 CrashReporter::UnsetExceptionHandler();
3742 return rv
== NS_ERROR_LAUNCHED_CHILD_PROCESS
? 0 : 1;
3745 #ifdef MOZ_WIDGET_GTK2
3746 // gdk_display_close also calls gdk_display_manager_set_default_display
3747 // appropriately when necessary.
3748 MOZ_gdk_display_close(display
);
3752 #ifdef MOZ_CRASHREPORTER
3753 if (appData
.flags
& NS_XRE_ENABLE_CRASH_REPORTER
)
3754 CrashReporter::UnsetExceptionHandler();
3757 XRE_DeinitCommandLine();
3759 return NS_FAILED(rv
) ? 1 : 0;
3763 XRE_InitCommandLine(int aArgc
, char* aArgv
[])
3765 nsresult rv
= NS_OK
;
3767 #if defined(MOZ_IPC)
3770 CommandLine::Init(aArgc
, aArgv
);
3773 // these leak on error, but that's OK: we'll just exit()
3774 char** canonArgs
= new char*[aArgc
];
3776 // get the canonical version of the binary's path
3777 nsCOMPtr
<nsILocalFile
> binFile
;
3778 rv
= XRE_GetBinaryPath(aArgv
[0], getter_AddRefs(binFile
));
3780 return NS_ERROR_FAILURE
;
3782 nsCAutoString canonBinPath
;
3783 rv
= binFile
->GetNativePath(canonBinPath
);
3785 return NS_ERROR_FAILURE
;
3787 canonArgs
[0] = strdup(canonBinPath
.get());
3789 for (int i
= 1; i
< aArgc
; ++i
) {
3791 canonArgs
[i
] = strdup(aArgv
[i
]);
3795 NS_ASSERTION(!CommandLine::IsInitialized(), "Bad news!");
3796 CommandLine::Init(aArgc
, canonArgs
);
3798 for (int i
= 0; i
< aArgc
; ++i
)
3805 const char *omnijarPath
= nsnull
;
3806 ArgResult ar
= CheckArg("omnijar", PR_FALSE
, &omnijarPath
);
3807 if (ar
== ARG_BAD
) {
3808 PR_fprintf(PR_STDERR
, "Error: argument -omnijar requires an omnijar path\n");
3809 return NS_ERROR_FAILURE
;
3815 nsCOMPtr
<nsILocalFile
> omnijar
;
3816 rv
= NS_NewNativeLocalFile(nsDependentCString(omnijarPath
), PR_TRUE
,
3817 getter_AddRefs(omnijar
));
3818 if (NS_SUCCEEDED(rv
))
3819 mozilla::SetOmnijar(omnijar
);
3826 XRE_DeinitCommandLine()
3828 nsresult rv
= NS_OK
;
3830 #if defined(MOZ_IPC)
3831 CommandLine::Terminate();
3838 XRE_GetProcessType()
3841 return mozilla::startup::sChildProcessType
;
3843 return GeckoProcessType_Default
;
3848 SetupErrorHandling(const char* progname
)
3851 /* On Windows XPSP3 and Windows Vista if DEP is configured off-by-default
3852 we still want DEP protection: enable it explicitly and programmatically.
3854 This function is not available on WinXPSP2 so we dynamically load it.
3857 HMODULE kernel32
= GetModuleHandleW(L
"kernel32.dll");
3858 SetProcessDEPPolicyFunc _SetProcessDEPPolicy
=
3859 (SetProcessDEPPolicyFunc
) GetProcAddress(kernel32
, "SetProcessDEPPolicy");
3860 if (_SetProcessDEPPolicy
)
3861 _SetProcessDEPPolicy(PROCESS_DEP_ENABLE
);
3864 #if defined (XP_WIN32) && !defined (WINCE)
3865 // Suppress the "DLL Foo could not be found" dialog, such that if dependent
3866 // libraries (such as GDI+) are not preset, we gracefully fail to load those
3867 // XPCOM components, instead of being ungraceful.
3868 UINT realMode
= SetErrorMode(0);
3869 realMode
|= SEM_FAILCRITICALERRORS
;
3870 // If XRE_NO_WINDOWS_CRASH_DIALOG is set, suppress displaying the "This
3871 // application has crashed" dialog box. This is mainly useful for
3872 // automated testing environments, e.g. tinderbox, where there's no need
3873 // for a dozen of the dialog boxes to litter the console
3874 if (getenv("XRE_NO_WINDOWS_CRASH_DIALOG"))
3875 realMode
|= SEM_NOGPFAULTERRORBOX
| SEM_NOOPENFILEERRORBOX
;
3877 SetErrorMode(realMode
);
3882 InstallSignalHandlers(progname
);
3886 // Unbuffer stdout, needed for tinderbox tests.
3890 #if defined(FREEBSD)
3891 // Disable all SIGFPE's on FreeBSD, as it has non-IEEE-conformant fp
3892 // trap behavior that trips up on floating-point tests performed by
3893 // the JS engine. See bugzilla bug 9967 details.