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 #include "nsAppRunner.h"
52 #include "nsUpdateDriver.h"
54 #if defined(MOZ_WIDGET_QT)
56 #include <qapplication.h>
60 #include "MacLaunchHelper.h"
61 #include "MacApplicationDelegate.h"
65 #include "private/pprthred.h"
73 #include "nsIAppShellService.h"
74 #include "nsIAppStartup.h"
75 #include "nsIAppStartupNotifier.h"
76 #include "nsIMutableArray.h"
77 #include "nsICategoryManager.h"
78 #include "nsIChromeRegistry.h"
79 #include "nsICommandLineRunner.h"
80 #include "nsIComponentManager.h"
81 #include "nsIComponentRegistrar.h"
82 #include "nsIContentHandler.h"
83 #include "nsIDialogParamBlock.h"
84 #include "nsIDOMWindow.h"
85 #include "nsIExtensionManager.h"
86 #include "nsIFastLoadService.h" // for PLATFORM_FASL_SUFFIX
87 #include "nsIGenericFactory.h"
88 #include "nsIIOService2.h"
89 #include "nsIObserverService.h"
90 #include "nsINativeAppSupport.h"
91 #include "nsIProcess.h"
92 #include "nsIProfileUnlocker.h"
93 #include "nsIPromptService.h"
94 #include "nsIServiceManager.h"
95 #include "nsIStringBundle.h"
96 #include "nsISupportsPrimitives.h"
97 #include "nsITimelineService.h"
98 #include "nsIToolkitChromeRegistry.h"
99 #include "nsIToolkitProfile.h"
100 #include "nsIToolkitProfileService.h"
102 #include "nsIWindowCreator.h"
103 #include "nsIWindowMediator.h"
104 #include "nsIWindowWatcher.h"
105 #include "nsIXULAppInfo.h"
106 #include "nsIXULRuntime.h"
107 #include "nsPIDOMWindow.h"
108 #include "nsIBaseWindow.h"
109 #include "nsIWidget.h"
110 #include "nsIDocShell.h"
111 #include "nsAppShellCID.h"
114 #include "nsIWinAppHelper.h"
118 #include "nsCOMPtr.h"
119 #include "nsDirectoryServiceDefs.h"
120 #include "nsDirectoryServiceUtils.h"
121 #include "nsEmbedCID.h"
122 #include "nsNetUtil.h"
123 #include "nsReadableUtils.h"
124 #include "nsStaticComponents.h"
126 #include "nsXPIDLString.h"
127 #include "nsXPFEComponentsCID.h"
128 #include "nsVersionComparator.h"
130 #include "nsAppDirectoryServiceDefs.h"
131 #include "nsXULAppAPI.h"
132 #include "nsXREDirProvider.h"
133 #include "nsToolkitCompsCID.h"
135 #include "nsINIParser.h"
140 #include <sys/stat.h>
145 // execv() behaves bit differently in R5 and Zeta, looks unreliable in such situation
146 //#include <unistd.h>
148 #include <AppFileInfo.h>
156 #include "nsThreadUtils.h"
160 #include "nsILocalFileMac.h"
161 #include "nsCommandLineServiceMac.h"
164 // for X remote support
165 #ifdef MOZ_ENABLE_XREMOTE
166 #ifdef MOZ_WIDGET_PHOTON
167 #include "PhRemoteClient.h"
169 #include "XRemoteClient.h"
171 #include "nsIRemoteService.h"
174 #ifdef NS_TRACE_MALLOC
175 #include "nsTraceMalloc.h"
178 #if defined(DEBUG) && defined(XP_WIN32)
182 #if defined (XP_MACOSX)
183 #include <Processes.h>
195 #ifdef MOZ_CRASHREPORTER
196 #include "nsExceptionHandler.h"
197 #include "nsICrashReporter.h"
198 #define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1"
201 // on x86 linux, the current builds of some popular plugins (notably
202 // flashplayer and real) expect a few builtin symbols from libgcc
203 // which were available in some older versions of gcc. However,
204 // they're _NOT_ available in newer versions of gcc (eg 3.1), so if
205 // we want those plugin to work with a gcc-3.1 built binary, we need
206 // to provide these symbols. MOZ_ENABLE_OLD_ABI_COMPAT_WRAPPERS defaults
207 // to true on x86 linux, and false everywhere else.
209 // The fact that the new and free operators are mismatched
210 // mirrors the way the original functions in egcs 1.1.2 worked.
212 #ifdef MOZ_ENABLE_OLD_ABI_COMPAT_WRAPPERS
216 # ifndef HAVE___BUILTIN_VEC_NEW
217 void *__builtin_vec_new(size_t aSize
, const std::nothrow_t
&aNoThrow
) throw()
219 return ::operator new(aSize
, aNoThrow
);
223 # ifndef HAVE___BUILTIN_VEC_DELETE
224 void __builtin_vec_delete(void *aPtr
, const std::nothrow_t
&) throw ()
232 # ifndef HAVE___BUILTIN_NEW
233 void *__builtin_new(int aSize
)
235 return malloc(aSize
);
239 # ifndef HAVE___BUILTIN_DELETE
240 void __builtin_delete(void *aPtr
)
246 # ifndef HAVE___PURE_VIRTUAL
247 void __pure_virtual(void) {
248 #ifdef WRAP_SYSTEM_INCLUDES
249 #pragma GCC visibility push(default)
251 extern void __cxa_pure_virtual(void);
252 #ifdef WRAP_SYSTEM_INCLUDES
253 #pragma GCC visibility pop
256 __cxa_pure_virtual();
262 #if defined(XP_UNIX) || defined(XP_BEOS)
263 extern void InstallUnixSignalHandlers(const char *ProgramName
);
269 static char gToolkitVersion
[20];
270 static char gToolkitBuildID
[40];
272 static int gRestartArgc
;
273 static char **gRestartArgv
;
275 #if defined(MOZ_WIDGET_GTK2)
276 #if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING) \
277 || defined(NS_TRACE_MALLOC)
278 #define CLEANUP_MEMORY 1
279 #define PANGO_ENABLE_BACKEND
280 #include <pango/pangofc-fontmap.h>
284 #include <gdk/gdkx.h>
286 #include "nsGTKToolkit.h"
289 // Save the given word to the specified environment variable.
291 SaveWordToEnv(const char *name
, const nsACString
& word
)
293 char *expr
= PR_smprintf("%s=%s", name
, PromiseFlatCString(word
).get());
296 // We intentionally leak |expr| here since it is required by PR_SetEnv.
299 // Save the path of the given file to the specified environment variable.
301 SaveFileToEnv(const char *name
, nsIFile
*file
)
306 SetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name
).get(), path
.get());
309 file
->GetNativePath(path
);
310 SaveWordToEnv(name
, path
);
314 // Load the path of a file saved with SaveFileToEnv
315 static already_AddRefed
<nsILocalFile
>
316 GetFileFromEnv(const char *name
)
319 nsILocalFile
*file
= nsnull
;
322 WCHAR path
[_MAX_PATH
];
323 if (!GetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name
).get(),
327 rv
= NS_NewLocalFile(nsDependentString(path
), PR_TRUE
, &file
);
333 const char *arg
= PR_GetEnv(name
);
337 rv
= NS_NewNativeLocalFile(nsDependentCString(arg
), PR_TRUE
, &file
);
345 // Save the path of the given word to the specified environment variable
346 // provided the environment variable does not have a value.
348 SaveWordToEnvIfUnset(const char *name
, const nsACString
& word
)
350 const char *val
= PR_GetEnv(name
);
352 SaveWordToEnv(name
, word
);
355 // Save the path of the given file to the specified environment variable
356 // provided the environment variable does not have a value.
358 SaveFileToEnvIfUnset(const char *name
, nsIFile
*file
)
360 const char *val
= PR_GetEnv(name
);
362 SaveFileToEnv(name
, file
);
366 strimatch(const char* lowerstr
, const char* mixedstr
)
369 if (!*mixedstr
) return PR_FALSE
; // mixedstr is shorter
370 if (tolower(*mixedstr
) != *lowerstr
) return PR_FALSE
; // no match
376 if (*mixedstr
) return PR_FALSE
; // lowerstr is shorter
382 * Output a string to the user. This method is really only meant to be used to
383 * output last-ditch error messages designed for developers NOT END USERS.
386 * Pass true to indicate severe errors.
388 * printf-style format string followed by arguments.
390 static void Output(PRBool isError
, const char *fmt
, ... )
395 #if defined(XP_WIN) && !MOZ_WINCONSOLE
396 char *msg
= PR_vsmprintf(fmt
, ap
);
401 flags
|= MB_ICONERROR
;
403 flags
|= MB_ICONINFORMATION
;
405 wchar_t wide_msg
[1024];
406 MultiByteToWideChar(CP_ACP
,
411 sizeof(wide_msg
) / sizeof(wchar_t));
413 MessageBoxW(NULL
, wide_msg
, L
"XULRunner", flags
);
414 PR_smprintf_free(msg
);
417 vfprintf(stderr
, fmt
, ap
);
424 REMOTE_NOT_FOUND
= 0,
432 ARG_BAD
= 2 // you wanted a param, but there isn't one
435 static void RemoveArg(char **argv
)
446 * Check for a commandline flag. If the flag takes a parameter, the
447 * parameter is returned in aParam. Flags may be in the form -arg or
448 * --arg (or /arg on win32/OS2).
450 * @param aArg the parameter to check. Must be lowercase.
451 * @param aCheckOSInt if true returns ARG_BAD if the osint argument is present
452 * when aArg is also present.
453 * @param if non-null, the -arg <data> will be stored in this pointer. This is *not*
454 * allocated, but rather a pointer to the argv data.
457 CheckArg(const char* aArg
, PRBool aCheckOSInt
= PR_FALSE
, const char **aParam
= nsnull
)
459 char **curarg
= gArgv
+ 1; // skip argv[0]
460 ArgResult ar
= ARG_NONE
;
463 char *arg
= curarg
[0];
466 #if defined(XP_WIN) || defined(XP_OS2)
474 if (strimatch(aArg
, arg
)) {
483 #if defined(XP_WIN) || defined(XP_OS2)
501 if (aCheckOSInt
&& ar
== ARG_FOUND
) {
502 ArgResult arOSInt
= CheckArg("osint");
503 if (arOSInt
== ARG_FOUND
) {
505 PR_fprintf(PR_STDERR
, "Error: argument -osint is invalid\n");
514 * Check for a commandline flag from the windows shell and remove it from the
515 * argv used when restarting. Flags MUST be in the form -arg.
517 * @param aArg the parameter to check. Must be lowercase.
520 CheckArgShell(const char* aArg
)
522 char **curarg
= gRestartArgv
+ 1; // skip argv[0]
525 char *arg
= curarg
[0];
530 if (strimatch(aArg
, arg
)) {
532 *curarg
= *(curarg
+ 1);
549 * Enabled Native App Support to process DDE messages when the app needs to
550 * restart and the app has been launched by the Windows shell to open an url.
551 * When aWait is false this will process the DDE events manually. This prevents
552 * Windows from displaying an error message due to the DDE message not being
556 ProcessDDE(nsINativeAppSupport
* aNative
, PRBool aWait
)
558 // When the app is launched by the windows shell the windows shell
559 // expects the app to be available for DDE messages and if it isn't
560 // windows displays an error dialog. To prevent the error the DDE server
561 // is enabled and pending events are processed when the app needs to
562 // restart after it was launched by the shell with the requestpending
563 // argument. The requestpending pending argument is removed to
564 // differentiate it from being launched when an app restart is not
567 ar
= CheckArgShell("requestpending");
568 if (ar
== ARG_FOUND
) {
569 aNative
->Enable(); // enable win32 DDE responses
571 nsIThread
*thread
= NS_GetCurrentThread();
572 // This is just a guesstimate based on testing different values.
573 // If count is 8 or less windows will display an error dialog.
575 while(--count
>= 0) {
576 NS_ProcessNextEvent(thread
);
577 PR_Sleep(PR_MillisecondsToInterval(1));
584 PRBool gSafeMode
= PR_FALSE
;
587 * The nsXULAppInfo object implements nsIFactory so that it can be its own
590 class nsXULAppInfo
: public nsIXULAppInfo
,
592 public nsIWinAppHelper
,
594 #ifdef MOZ_CRASHREPORTER
595 public nsICrashReporter
,
601 NS_DECL_ISUPPORTS_INHERITED
602 NS_DECL_NSIXULAPPINFO
603 NS_DECL_NSIXULRUNTIME
604 #ifdef MOZ_CRASHREPORTER
605 NS_DECL_NSICRASHREPORTER
608 NS_DECL_NSIWINAPPHELPER
610 nsresult
LaunchAppHelperWithArgs(int aArgc
, char **aArgv
);
614 NS_INTERFACE_MAP_BEGIN(nsXULAppInfo
)
615 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIXULRuntime
)
616 NS_INTERFACE_MAP_ENTRY(nsIXULRuntime
)
618 NS_INTERFACE_MAP_ENTRY(nsIWinAppHelper
)
620 #ifdef MOZ_CRASHREPORTER
621 NS_INTERFACE_MAP_ENTRY(nsICrashReporter
)
623 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIXULAppInfo
, gAppData
)
626 NS_IMETHODIMP_(nsrefcnt
)
627 nsXULAppInfo::AddRef()
632 NS_IMETHODIMP_(nsrefcnt
)
633 nsXULAppInfo::Release()
639 nsXULAppInfo::GetVendor(nsACString
& aResult
)
641 aResult
.Assign(gAppData
->vendor
);
647 nsXULAppInfo::GetName(nsACString
& aResult
)
649 aResult
.Assign(gAppData
->name
);
655 nsXULAppInfo::GetID(nsACString
& aResult
)
657 aResult
.Assign(gAppData
->ID
);
663 nsXULAppInfo::GetVersion(nsACString
& aResult
)
665 aResult
.Assign(gAppData
->version
);
671 nsXULAppInfo::GetPlatformVersion(nsACString
& aResult
)
673 aResult
.Assign(gToolkitVersion
);
679 nsXULAppInfo::GetAppBuildID(nsACString
& aResult
)
681 aResult
.Assign(gAppData
->buildID
);
687 nsXULAppInfo::GetPlatformBuildID(nsACString
& aResult
)
689 aResult
.Assign(gToolkitBuildID
);
695 nsXULAppInfo::GetLogConsoleErrors(PRBool
*aResult
)
697 *aResult
= gLogConsoleErrors
;
702 nsXULAppInfo::SetLogConsoleErrors(PRBool aValue
)
704 gLogConsoleErrors
= aValue
;
709 nsXULAppInfo::GetInSafeMode(PRBool
*aResult
)
711 *aResult
= gSafeMode
;
716 nsXULAppInfo::GetOS(nsACString
& aResult
)
718 aResult
.AssignLiteral(OS_TARGET
);
723 nsXULAppInfo::GetXPCOMABI(nsACString
& aResult
)
725 #ifdef TARGET_XPCOM_ABI
726 aResult
.AssignLiteral(TARGET_XPCOM_ABI
);
729 return NS_ERROR_NOT_AVAILABLE
;
735 nsXULAppInfo::LaunchAppHelperWithArgs(int aArgc
, char **aArgv
)
738 nsCOMPtr
<nsIProperties
> directoryService
=
739 do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID
, &rv
);
740 NS_ENSURE_SUCCESS(rv
, rv
);
742 nsCOMPtr
<nsILocalFile
> appHelper
;
743 rv
= directoryService
->Get(NS_XPCOM_CURRENT_PROCESS_DIR
, NS_GET_IID(nsILocalFile
), getter_AddRefs(appHelper
));
744 NS_ENSURE_SUCCESS(rv
, rv
);
746 rv
= appHelper
->AppendNative(NS_LITERAL_CSTRING("uninstall"));
747 NS_ENSURE_SUCCESS(rv
, rv
);
749 rv
= appHelper
->AppendNative(NS_LITERAL_CSTRING("helper.exe"));
750 NS_ENSURE_SUCCESS(rv
, rv
);
752 nsAutoString appHelperPath
;
753 rv
= appHelper
->GetPath(appHelperPath
);
754 NS_ENSURE_SUCCESS(rv
, rv
);
756 if (!WinLaunchChild(appHelperPath
.get(), aArgc
, aArgv
, 1))
757 return NS_ERROR_FAILURE
;
763 nsXULAppInfo::PostUpdate(nsILocalFile
*aLogFile
)
766 int upgradeArgc
= aLogFile
? 3 : 2;
767 char **upgradeArgv
= (char**) malloc(sizeof(char*) * (upgradeArgc
+ 1));
770 return NS_ERROR_OUT_OF_MEMORY
;
772 upgradeArgv
[0] = "argv0ignoredbywinlaunchchild";
773 upgradeArgv
[1] = "/postupdate";
775 char *pathArg
= nsnull
;
778 nsCAutoString logFilePath
;
779 rv
= aLogFile
->GetNativePath(logFilePath
);
780 NS_ENSURE_SUCCESS(rv
, rv
);
782 pathArg
= PR_smprintf("/uninstalllog=%s", logFilePath
.get());
784 return NS_ERROR_OUT_OF_MEMORY
;
786 upgradeArgv
[2] = pathArg
;
787 upgradeArgv
[3] = nsnull
;
790 upgradeArgv
[2] = nsnull
;
793 rv
= LaunchAppHelperWithArgs(upgradeArgc
, upgradeArgv
);
796 PR_smprintf_free(pathArg
);
802 // Matches the enum in WinNT.h for the Vista SDK but renamed so that we can
803 // safely build with the Vista SDK and without it.
806 VistaTokenElevationTypeDefault
= 1,
807 VistaTokenElevationTypeFull
,
808 VistaTokenElevationTypeLimited
809 } VISTA_TOKEN_ELEVATION_TYPE
;
811 // avoid collision with TokeElevationType enum in WinNT.h
813 #define VistaTokenElevationType static_cast< TOKEN_INFORMATION_CLASS >( 18 )
816 nsXULAppInfo::GetUserCanElevate(PRBool
*aUserCanElevate
)
819 *aUserCanElevate
= PR_FALSE
;
824 VISTA_TOKEN_ELEVATION_TYPE elevationType
;
827 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
) ||
828 !GetTokenInformation(hToken
, VistaTokenElevationType
, &elevationType
,
829 sizeof(elevationType
), &dwSize
)) {
830 *aUserCanElevate
= PR_FALSE
;
833 // The possible values returned for elevationType and their meanings are:
834 // TokenElevationTypeDefault: The token does not have a linked token
835 // (e.g. UAC disabled or a standard user, so they can't be elevated)
836 // TokenElevationTypeFull: The token is linked to an elevated token
837 // (e.g. UAC is enabled and the user is already elevated so they can't
838 // be elevated again)
839 // TokenElevationTypeLimited: The token is linked to a limited token
840 // (e.g. UAC is enabled and the user is not elevated, so they can be
842 *aUserCanElevate
= (elevationType
== VistaTokenElevationTypeLimited
);
853 #ifdef MOZ_CRASHREPORTER
855 nsXULAppInfo::AnnotateCrashReport(const nsACString
& key
,
856 const nsACString
& data
)
858 return CrashReporter::AnnotateCrashReport(key
, data
);
862 nsXULAppInfo::AppendAppNotesToCrashReport(const nsACString
& data
)
864 return CrashReporter::AppendAppNotesToCrashReport(data
);
868 nsXULAppInfo::WriteMinidumpForException(void* aExceptionInfo
)
871 return CrashReporter::WriteMinidumpForException(static_cast<EXCEPTION_POINTERS
*>(aExceptionInfo
));
873 return NS_ERROR_NOT_IMPLEMENTED
;
878 nsXULAppInfo::AppendObjCExceptionInfoToAppNotes(void* aException
)
881 return CrashReporter::AppendObjCExceptionInfoToAppNotes(aException
);
883 return NS_ERROR_NOT_IMPLEMENTED
;
888 static const nsXULAppInfo kAppInfo
;
889 static NS_METHOD
AppInfoConstructor(nsISupports
* aOuter
,
890 REFNSIID aIID
, void **aResult
)
892 NS_ENSURE_NO_AGGREGATION(aOuter
);
894 return const_cast<nsXULAppInfo
*>(&kAppInfo
)->
895 QueryInterface(aIID
, aResult
);
898 PRBool gLogConsoleErrors
905 #define NS_ENSURE_TRUE_LOG(x, ret) \
907 if (NS_UNLIKELY(!(x))) { \
908 NS_WARNING("NS_ENSURE_TRUE(" #x ") failed"); \
909 gLogConsoleErrors = PR_TRUE; \
914 #define NS_ENSURE_SUCCESS_LOG(res, ret) \
915 NS_ENSURE_TRUE_LOG(NS_SUCCEEDED(res), ret)
918 * Because we're starting/stopping XPCOM several times in different scenarios,
919 * this class is a stack-based critter that makes sure that XPCOM is shut down
920 * during early returns.
923 class ScopedXPCOMStartup
926 ScopedXPCOMStartup() :
927 mServiceManager(nsnull
) { }
928 ~ScopedXPCOMStartup();
930 nsresult
Initialize();
931 nsresult
DoAutoreg();
932 nsresult
RegisterProfileService();
933 nsresult
SetWindowCreator(nsINativeAppSupport
* native
);
936 nsIServiceManager
* mServiceManager
;
939 ScopedXPCOMStartup::~ScopedXPCOMStartup()
941 if (mServiceManager
) {
942 nsCOMPtr
<nsIAppStartup
> appStartup (do_GetService(NS_APPSTARTUP_CONTRACTID
));
944 appStartup
->DestroyHiddenWindow();
946 gDirServiceProvider
->DoShutdown();
950 NS_ShutdownXPCOM(mServiceManager
);
951 mServiceManager
= nsnull
;
955 // {95d89e3e-a169-41a3-8e56-719978e15b12}
956 #define APPINFO_CID \
957 { 0x95d89e3e, 0xa169, 0x41a3, { 0x8e, 0x56, 0x71, 0x99, 0x78, 0xe1, 0x5b, 0x12 } }
959 static nsModuleComponentInfo kComponents
[] =
964 XULAPPINFO_SERVICE_CONTRACTID
,
967 #ifdef MOZ_CRASHREPORTER
972 NS_CRASHREPORTER_CONTRACTID
,
978 NS_IMPL_NSGETMODULE(Apprunner
, kComponents
)
980 #if !defined(_BUILD_STATIC_BIN) && !defined(MOZ_ENABLE_LIBXUL)
981 static nsStaticModuleInfo
const kXREStaticModules
[] =
985 Apprunner_NSGetModule
989 nsStaticModuleInfo
const *const kPStaticModules
= kXREStaticModules
;
990 PRUint32
const kStaticModuleCount
= NS_ARRAY_LENGTH(kXREStaticModules
);
994 ScopedXPCOMStartup::Initialize()
996 NS_ASSERTION(gDirServiceProvider
, "Should not get here!");
999 rv
= NS_InitXPCOM3(&mServiceManager
, gDirServiceProvider
->GetAppDir(),
1000 gDirServiceProvider
,
1001 kPStaticModules
, kStaticModuleCount
);
1002 if (NS_FAILED(rv
)) {
1003 NS_ERROR("Couldn't start xpcom!");
1004 mServiceManager
= nsnull
;
1007 nsCOMPtr
<nsIComponentRegistrar
> reg
=
1008 do_QueryInterface(mServiceManager
);
1009 NS_ASSERTION(reg
, "Service Manager doesn't QI to Registrar.");
1015 // {0C4A446C-EE82-41f2-8D04-D366D2C7A7D4}
1016 static const nsCID kNativeAppSupportCID
=
1017 { 0xc4a446c, 0xee82, 0x41f2, { 0x8d, 0x4, 0xd3, 0x66, 0xd2, 0xc7, 0xa7, 0xd4 } };
1019 // {5F5E59CE-27BC-47eb-9D1F-B09CA9049836}
1020 static const nsCID kProfileServiceCID
=
1021 { 0x5f5e59ce, 0x27bc, 0x47eb, { 0x9d, 0x1f, 0xb0, 0x9c, 0xa9, 0x4, 0x98, 0x36 } };
1024 ScopedXPCOMStartup::RegisterProfileService()
1026 NS_ASSERTION(mServiceManager
, "Not initialized!");
1028 nsCOMPtr
<nsIFactory
> factory
;
1029 NS_NewToolkitProfileFactory(getter_AddRefs(factory
));
1030 if (!factory
) return NS_ERROR_OUT_OF_MEMORY
;
1032 nsCOMPtr
<nsIComponentRegistrar
> reg (do_QueryInterface(mServiceManager
));
1033 if (!reg
) return NS_ERROR_NO_INTERFACE
;
1035 return reg
->RegisterFactory(kProfileServiceCID
,
1036 "Toolkit Profile Service",
1037 NS_PROFILESERVICE_CONTRACTID
,
1042 ScopedXPCOMStartup::DoAutoreg()
1045 // _Always_ autoreg if we're in a debug build, under the assumption
1046 // that people are busily modifying components and will be angry if
1047 // their changes aren't noticed.
1048 nsCOMPtr
<nsIComponentRegistrar
> registrar
1049 (do_QueryInterface(mServiceManager
));
1050 NS_ASSERTION(registrar
, "Where's the component registrar?");
1052 registrar
->AutoRegister(nsnull
);
1059 * This is a little factory class that serves as a singleton-service-factory
1060 * for the nativeappsupport object.
1062 class nsSingletonFactory
: public nsIFactory
1068 nsSingletonFactory(nsISupports
* aSingleton
);
1069 ~nsSingletonFactory() { }
1072 nsCOMPtr
<nsISupports
> mSingleton
;
1075 nsSingletonFactory::nsSingletonFactory(nsISupports
* aSingleton
)
1076 : mSingleton(aSingleton
)
1078 NS_ASSERTION(mSingleton
, "Singleton was null!");
1081 NS_IMPL_ISUPPORTS1(nsSingletonFactory
, nsIFactory
)
1084 nsSingletonFactory::CreateInstance(nsISupports
* aOuter
,
1088 NS_ENSURE_NO_AGGREGATION(aOuter
);
1090 return mSingleton
->QueryInterface(aIID
, aResult
);
1094 nsSingletonFactory::LockFactory(PRBool
)
1100 * Set our windowcreator on the WindowWatcher service.
1103 ScopedXPCOMStartup::SetWindowCreator(nsINativeAppSupport
* native
)
1107 nsCOMPtr
<nsIComponentRegistrar
> registrar
1108 (do_QueryInterface(mServiceManager
));
1109 NS_ASSERTION(registrar
, "Where's the component registrar?");
1111 nsCOMPtr
<nsIFactory
> nativeFactory
= new nsSingletonFactory(native
);
1112 NS_ENSURE_TRUE(nativeFactory
, NS_ERROR_OUT_OF_MEMORY
);
1114 rv
= registrar
->RegisterFactory(kNativeAppSupportCID
,
1115 "Native App Support",
1116 NS_NATIVEAPPSUPPORT_CONTRACTID
,
1118 NS_ENSURE_SUCCESS(rv
, rv
);
1120 // Inform the chrome registry about OS accessibility
1121 nsCOMPtr
<nsIToolkitChromeRegistry
> cr (do_GetService(NS_CHROMEREGISTRY_CONTRACTID
));
1123 cr
->CheckForOSAccessibility();
1125 nsCOMPtr
<nsIWindowCreator
> creator (do_GetService(NS_APPSTARTUP_CONTRACTID
));
1126 if (!creator
) return NS_ERROR_UNEXPECTED
;
1128 nsCOMPtr
<nsIWindowWatcher
> wwatch
1129 (do_GetService(NS_WINDOWWATCHER_CONTRACTID
, &rv
));
1130 NS_ENSURE_SUCCESS(rv
, rv
);
1132 return wwatch
->SetWindowCreator(creator
);
1136 * A helper class which calls NS_LogInit/NS_LogTerm in its scope.
1141 ScopedLogging() { NS_LogInit(); }
1142 ~ScopedLogging() { NS_LogTerm(); }
1145 static void DumpArbitraryHelp()
1152 nsXREDirProvider dirProvider
;
1153 dirProvider
.Initialize(nsnull
, gAppData
->xreDirectory
);
1155 ScopedXPCOMStartup xpcom
;
1159 nsCOMPtr
<nsICommandLineRunner
> cmdline
1160 (do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
1165 rv
= cmdline
->GetHelpText(text
);
1166 if (NS_SUCCEEDED(rv
))
1167 printf("%s", text
.get());
1171 // English text needs to go into a dtd file.
1172 // But when this is called we have no components etc. These strings must either be
1173 // here, or in a native resource file.
1177 printf("Usage: %s [ options ... ] [URL]\n"
1178 " where options include:\n\n", gArgv
[0]);
1181 printf("X11 options\n"
1182 "\t--display=DISPLAY\t\tX display to use\n"
1183 "\t--sync\t\tMake X calls synchronous\n"
1184 "\t--no-xshm\t\tDon't use X shared memory extension\n"
1185 "\t--xim-preedit=STYLE\n"
1186 "\t--xim-status=STYLE\n");
1189 printf("\t--g-fatal-warnings\t\tMake all warnings fatal\n"
1190 "\n%s options\n", gAppData
->name
);
1193 printf("\t-h or -help\t\tPrint this message.\n"
1194 "\t-v or -version\t\tPrint %s version.\n"
1195 "\t-P <profile>\t\tStart with <profile>.\n"
1196 "\t-migration\t\tStart with migration wizard.\n"
1197 "\t-ProfileManager\t\tStart with ProfileManager.\n"
1198 "\t-no-remote\t\tOpen new instance, not a new window in running instance.\n"
1199 "\t-UILocale <locale>\tStart with <locale> resources as UI Locale.\n"
1200 "\t-safe-mode\t\tDisables extensions and themes for this session.\n", gAppData
->name
);
1202 #if defined(XP_WIN) || defined(XP_OS2)
1203 printf("\t-console\t\tStart %s with a debugging console.\n", gAppData
->name
);
1206 // this works, but only after the components have registered. so if you drop in a new command line handler, -help
1207 // won't not until the second run.
1208 // out of the bug, because we ship a component.reg file, it works correctly.
1209 DumpArbitraryHelp();
1214 #define _CRTDBG_MAP_ALLOC
1219 #if defined(FREEBSD)
1220 // pick up fpsetmask prototype.
1228 gAppData
->vendor
? gAppData
->vendor
: "", gAppData
->name
, gAppData
->version
);
1229 if (gAppData
->copyright
)
1230 printf(", %s", gAppData
->copyright
);
1234 #ifdef MOZ_ENABLE_XREMOTE
1235 // use int here instead of a PR type since it will be returned
1236 // from main - just to keep types consistent
1238 HandleRemoteArgument(const char* remote
, const char* aDesktopStartupID
)
1243 const char *profile
= 0;
1244 nsCAutoString
program(gAppData
->name
);
1245 ToLowerCase(program
);
1246 const char *username
= getenv("LOGNAME");
1248 ar
= CheckArg("p", PR_FALSE
, &profile
);
1249 if (ar
== ARG_BAD
) {
1250 PR_fprintf(PR_STDERR
, "Error: argument -p requires a profile name\n");
1254 const char *temp
= nsnull
;
1255 ar
= CheckArg("a", PR_FALSE
, &temp
);
1256 if (ar
== ARG_BAD
) {
1257 PR_fprintf(PR_STDERR
, "Error: argument -a requires an application name\n");
1259 } else if (ar
== ARG_FOUND
) {
1260 program
.Assign(temp
);
1263 ar
= CheckArg("u", PR_FALSE
, &username
);
1264 if (ar
== ARG_BAD
) {
1265 PR_fprintf(PR_STDERR
, "Error: argument -u requires a username\n");
1269 XRemoteClient client
;
1271 if (NS_FAILED(rv
)) {
1272 PR_fprintf(PR_STDERR
, "Error: Failed to connect to X server.\n");
1276 nsXPIDLCString response
;
1277 PRBool success
= PR_FALSE
;
1278 rv
= client
.SendCommand(program
.get(), username
, profile
, remote
,
1279 aDesktopStartupID
, getter_Copies(response
), &success
);
1280 // did the command fail?
1281 if (NS_FAILED(rv
)) {
1282 PR_fprintf(PR_STDERR
, "Error: Failed to send command: %s\n",
1283 response
? response
.get() : "No response included");
1288 PR_fprintf(PR_STDERR
, "Error: No running window found\n");
1296 RemoteCommandLine(const char* aDesktopStartupID
)
1301 nsCAutoString
program(gAppData
->name
);
1302 ToLowerCase(program
);
1303 const char *username
= getenv("LOGNAME");
1305 const char *temp
= nsnull
;
1306 ar
= CheckArg("a", PR_TRUE
, &temp
);
1307 if (ar
== ARG_BAD
) {
1308 PR_fprintf(PR_STDERR
, "Error: argument -a requires an application name\n");
1309 return REMOTE_ARG_BAD
;
1310 } else if (ar
== ARG_FOUND
) {
1311 program
.Assign(temp
);
1314 ar
= CheckArg("u", PR_TRUE
, &username
);
1315 if (ar
== ARG_BAD
) {
1316 PR_fprintf(PR_STDERR
, "Error: argument -u requires a username\n");
1317 return REMOTE_ARG_BAD
;
1320 XRemoteClient client
;
1323 return REMOTE_NOT_FOUND
;
1325 nsXPIDLCString response
;
1326 PRBool success
= PR_FALSE
;
1327 rv
= client
.SendCommandLine(program
.get(), username
, nsnull
,
1328 gArgc
, gArgv
, aDesktopStartupID
,
1329 getter_Copies(response
), &success
);
1330 // did the command fail?
1331 if (NS_FAILED(rv
) || !success
)
1332 return REMOTE_NOT_FOUND
;
1334 return REMOTE_FOUND
;
1336 #endif // MOZ_ENABLE_XREMOTE
1339 static char const *gBinaryPath
;
1343 XRE_GetBinaryPath(const char* argv0
, nsILocalFile
* *aResult
)
1346 nsCOMPtr
<nsILocalFile
> lf
;
1348 // We need to use platform-specific hackery to find the
1349 // path of this executable. This is copied, with some modifications, from
1350 // nsGREDirServiceProvider.cpp
1353 PRUnichar exePath
[MAXPATHLEN
];
1355 if (!::GetModuleFileNameW(0, exePath
, MAXPATHLEN
))
1356 return NS_ERROR_FAILURE
;
1358 rv
= NS_NewLocalFile(nsDependentString(exePath
), PR_TRUE
,
1359 getter_AddRefs(lf
));
1363 #elif defined(XP_MACOSX)
1365 return NS_NewNativeLocalFile(nsDependentCString(gBinaryPath
), PR_FALSE
,
1368 NS_NewNativeLocalFile(EmptyCString(), PR_TRUE
, getter_AddRefs(lf
));
1369 nsCOMPtr
<nsILocalFileMac
> lfm (do_QueryInterface(lf
));
1371 return NS_ERROR_FAILURE
;
1373 // Works even if we're not bundled.
1374 CFBundleRef appBundle
= CFBundleGetMainBundle();
1376 return NS_ERROR_FAILURE
;
1378 CFURLRef bundleURL
= CFBundleCopyExecutableURL(appBundle
);
1380 return NS_ERROR_FAILURE
;
1383 if (!CFURLGetFSRef(bundleURL
, &fileRef
)) {
1384 CFRelease(bundleURL
);
1385 return NS_ERROR_FAILURE
;
1388 rv
= lfm
->InitWithFSRef(&fileRef
);
1389 CFRelease(bundleURL
);
1394 #elif defined(XP_UNIX)
1395 struct stat fileStat
;
1396 char exePath
[MAXPATHLEN
];
1397 char tmpPath
[MAXPATHLEN
];
1399 rv
= NS_ERROR_FAILURE
;
1401 // on unix, there is no official way to get the path of the current binary.
1402 // instead of using the MOZILLA_FIVE_HOME hack, which doesn't scale to
1403 // multiple applications, we will try a series of techniques:
1405 // 1) look for /proc/<pid>/exe which is a symlink to the executable on newer
1407 // 2) use realpath() on argv[0], which works unless we're loaded from the
1409 // 3) manually walk through the PATH and look for ourself
1414 int r
= readlink("/proc/self/exe", exePath
, MAXPATHLEN
);
1416 // apparently, /proc/self/exe can sometimes return weird data... check it
1417 if (r
> 0 && r
< MAXPATHLEN
&& stat(exePath
, &fileStat
) == 0) {
1422 if (NS_FAILED(rv
) &&
1423 realpath(argv0
, exePath
) && stat(exePath
, &fileStat
) == 0) {
1427 if (NS_FAILED(rv
)) {
1428 const char *path
= getenv("PATH");
1430 return NS_ERROR_FAILURE
;
1432 char *pathdup
= strdup(path
);
1434 return NS_ERROR_OUT_OF_MEMORY
;
1436 PRBool found
= PR_FALSE
;
1437 char *newStr
= pathdup
;
1439 while ( (token
= nsCRT::strtok(newStr
, ":", &newStr
)) ) {
1440 sprintf(tmpPath
, "%s/%s", token
, argv0
);
1441 if (realpath(tmpPath
, exePath
) && stat(exePath
, &fileStat
) == 0) {
1448 return NS_ERROR_FAILURE
;
1451 rv
= NS_NewNativeLocalFile(nsDependentCString(exePath
), PR_TRUE
,
1452 getter_AddRefs(lf
));
1456 #elif defined(XP_OS2)
1459 char exePath
[MAXPATHLEN
];
1461 DosGetInfoBlocks( &ptib
, &ppib
);
1462 DosQueryModuleName( ppib
->pib_hmte
, MAXPATHLEN
, exePath
);
1463 rv
= NS_NewNativeLocalFile(nsDependentCString(exePath
), PR_TRUE
,
1464 getter_AddRefs(lf
));
1468 #elif defined(XP_BEOS)
1472 if(get_next_image_info(0, &cookie
, &info
) != B_OK
)
1473 return NS_ERROR_FAILURE
;
1475 rv
= NS_NewNativeLocalFile(nsDependentCString(info
.name
), PR_TRUE
,
1476 getter_AddRefs(lf
));
1481 #error Oops, you need platform-specific code here
1484 NS_ADDREF(*aResult
= lf
);
1488 #define NS_ERROR_LAUNCHED_CHILD_PROCESS NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_PROFILE, 200)
1491 #include "nsWindowsRestart.cpp"
1494 #if defined(XP_OS2) && (__KLIBC__ == 0 && __KLIBC_MINOR__ >= 6) // broken kLibc
1495 // Copy the environment maintained by the C library into an ASCIIZ array
1496 // that can be used to pass it on to the OS/2 Dos* APIs (which otherwise
1497 // don't know anything about the stuff set by PR_SetEnv() or setenv()).
1500 // just allocate the maximum amount (24 kB = 0x60000 bytes), to be able to
1501 // copy the existing environment
1502 char *env
= (char *)calloc(0x6000, sizeof(char));
1507 // walk along the environ string array of the C library and copy
1508 // everything (that fits) into the output environment array, leaving
1509 // null bytes between the entries
1510 char *penv
= env
; // movable pointer to result environment ASCIIZ array
1511 int i
= 0, space
= 0x6000;
1512 while (environ
[i
] && environ
[i
][0]) {
1513 int len
= strlen(environ
[i
]);
1514 if (space
- len
<= 0) {
1517 strcpy(penv
, environ
[i
]);
1518 i
++; // next environment variable
1519 penv
+= len
+ 1; // jump to after next null byte
1520 space
-= len
- 1; // subtract consumed length from usable space
1526 // OS2LaunchChild() is there to replace _execv() which is broken in the C
1527 // runtime library that comes with GCC 3.3.5 on OS/2. It uses createEnv()
1528 // to copy the process environment and add necessary variables
1530 // returns -1 on failure and 0 on success
1531 int OS2LaunchChild(const char *aExePath
, int aArgc
, char **aArgv
)
1533 // find total length of aArgv
1535 for (int i
= 0; i
< aArgc
; i
++) {
1536 len
+= strlen(aArgv
[i
]) + 1; // plus space in between
1538 len
++; // leave space for null byte at end
1539 // allocate enough space for all strings and nulls,
1540 // calloc helpfully initializes to null
1541 char *args
= (char *)calloc(len
, sizeof(char));
1545 char *pargs
= args
; // extra pointer to after the last argument
1546 // build argument list in the format the DosStartSession() wants,
1547 // adding spaces between the arguments
1548 for (int i
= 0; i
< aArgc
; i
++, *pargs
++ = ' ') {
1549 strcpy(pargs
, aArgv
[i
]);
1550 pargs
+= strlen(aArgv
[i
]);
1553 *(pargs
-1) = '\0'; // replace last space
1556 // make sure that the program is separated by null byte
1557 pargs
= strchr(args
, ' ');
1562 char *env
= createEnv();
1564 char error
[CCHMAXPATH
] = { 0 };
1565 RESULTCODES crc
= { 0 };
1566 ULONG rc
= DosExecPgm(error
, sizeof(error
), EXEC_ASYNC
, args
, env
,
1567 &crc
, (PSZ
)aExePath
);
1568 free(args
); // done with the arguments
1572 if (rc
!= NO_ERROR
) {
1580 // If aBlankCommandLine is true, then the application will be launched with a
1581 // blank command line instead of being launched with the same command line that
1582 // it was initially started with.
1583 static nsresult
LaunchChild(nsINativeAppSupport
* aNative
,
1584 PRBool aBlankCommandLine
= PR_FALSE
)
1586 aNative
->Quit(); // release DDE mutex, if we're holding it
1588 // Restart this process by exec'ing it into the current process
1589 // if supported by the platform. Otherwise, use NSPR.
1591 if (aBlankCommandLine
) {
1593 gRestartArgv
[gRestartArgc
] = nsnull
;
1596 PR_SetEnv("MOZ_LAUNCHED_CHILD=1");
1598 #if defined(XP_MACOSX)
1599 SetupMacCommandLine(gRestartArgc
, gRestartArgv
);
1600 LaunchChildMac(gRestartArgc
, gRestartArgv
);
1602 nsCOMPtr
<nsILocalFile
> lf
;
1603 nsresult rv
= XRE_GetBinaryPath(gArgv
[0], getter_AddRefs(lf
));
1608 nsAutoString exePath
;
1609 rv
= lf
->GetPath(exePath
);
1613 if (!WinLaunchChild(exePath
.get(), gRestartArgc
, gRestartArgv
, 0))
1614 return NS_ERROR_FAILURE
;
1617 nsCAutoString exePath
;
1618 rv
= lf
->GetNativePath(exePath
);
1622 #if defined(XP_OS2) && (__KLIBC__ == 0 && __KLIBC_MINOR__ >= 6)
1623 // implementation of _execv() is broken with kLibc 0.6.x and later
1624 if (OS2LaunchChild(exePath
.get(), gRestartArgc
, gRestartArgv
) == -1)
1625 return NS_ERROR_FAILURE
;
1626 #elif defined(XP_OS2)
1627 if (_execv(exePath
.get(), gRestartArgv
) == -1)
1628 return NS_ERROR_FAILURE
;
1629 #elif defined(XP_UNIX)
1630 if (execv(exePath
.get(), gRestartArgv
) == -1)
1631 return NS_ERROR_FAILURE
;
1632 #elif defined(XP_BEOS)
1633 extern char **environ
;
1635 res
= resume_thread(load_image(gRestartArgc
,(const char **)gRestartArgv
,(const char **)environ
));
1637 return NS_ERROR_FAILURE
;
1639 PRProcess
* process
= PR_CreateProcess(exePath
.get(), gRestartArgv
,
1641 if (!process
) return NS_ERROR_FAILURE
;
1644 PRStatus failed
= PR_WaitProcess(process
, &exitCode
);
1645 if (failed
|| exitCode
)
1646 return NS_ERROR_FAILURE
;
1647 #endif // XP_OS2 series
1651 return NS_ERROR_LAUNCHED_CHILD_PROCESS
;
1654 static const char kProfileProperties
[] =
1655 "chrome://mozapps/locale/profile/profileSelection.properties";
1658 ProfileLockedDialog(nsILocalFile
* aProfileDir
, nsILocalFile
* aProfileLocalDir
,
1659 nsIProfileUnlocker
* aUnlocker
,
1660 nsINativeAppSupport
* aNative
, nsIProfileLock
* *aResult
)
1664 ScopedXPCOMStartup xpcom
;
1665 rv
= xpcom
.Initialize();
1666 NS_ENSURE_SUCCESS(rv
, rv
);
1668 rv
= xpcom
.DoAutoreg();
1669 rv
|= xpcom
.SetWindowCreator(aNative
);
1670 NS_ENSURE_SUCCESS(rv
, NS_ERROR_FAILURE
);
1672 { //extra scoping is needed so we release these components before xpcom shutdown
1673 nsCOMPtr
<nsIStringBundleService
> sbs
1674 (do_GetService(NS_STRINGBUNDLE_CONTRACTID
));
1675 NS_ENSURE_TRUE(sbs
, NS_ERROR_FAILURE
);
1677 nsCOMPtr
<nsIStringBundle
> sb
;
1678 sbs
->CreateBundle(kProfileProperties
, getter_AddRefs(sb
));
1679 NS_ENSURE_TRUE_LOG(sbs
, NS_ERROR_FAILURE
);
1681 NS_ConvertUTF8toUTF16
appName(gAppData
->name
);
1682 const PRUnichar
* params
[] = {appName
.get(), appName
.get()};
1684 nsXPIDLString killMessage
;
1686 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"
1687 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"
1689 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"
1690 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"
1693 sb
->FormatStringFromName(aUnlocker
? kRestartUnlocker
: kRestartNoUnlocker
,
1694 params
, 2, getter_Copies(killMessage
));
1696 nsXPIDLString killTitle
;
1697 sb
->FormatStringFromName(NS_LITERAL_STRING("restartTitle").get(),
1698 params
, 1, getter_Copies(killTitle
));
1700 if (!killMessage
|| !killTitle
)
1701 return NS_ERROR_FAILURE
;
1703 nsCOMPtr
<nsIPromptService
> ps
1704 (do_GetService(NS_PROMPTSERVICE_CONTRACTID
));
1705 NS_ENSURE_TRUE(ps
, NS_ERROR_FAILURE
);
1707 PRUint32 flags
= nsIPromptService::BUTTON_TITLE_OK
* nsIPromptService::BUTTON_POS_0
;
1711 nsIPromptService::BUTTON_TITLE_CANCEL
* nsIPromptService::BUTTON_POS_0
+
1712 nsIPromptService::BUTTON_TITLE_IS_STRING
* nsIPromptService::BUTTON_POS_1
+
1713 nsIPromptService::BUTTON_POS_1_DEFAULT
;
1717 rv
= ps
->ConfirmEx(nsnull
, killTitle
, killMessage
, flags
,
1718 killTitle
, nsnull
, nsnull
, nsnull
, nsnull
, &button
);
1719 NS_ENSURE_SUCCESS_LOG(rv
, rv
);
1721 if (button
== 1 && aUnlocker
) {
1722 rv
= aUnlocker
->Unlock(nsIProfileUnlocker::FORCE_QUIT
);
1723 if (NS_FAILED(rv
)) return rv
;
1725 return NS_LockProfilePath(aProfileDir
, aProfileLocalDir
, nsnull
, aResult
);
1728 return NS_ERROR_ABORT
;
1732 static const char kProfileManagerURL
[] =
1733 "chrome://mozapps/content/profile/profileSelection.xul";
1736 ShowProfileManager(nsIToolkitProfileService
* aProfileSvc
,
1737 nsINativeAppSupport
* aNative
)
1741 nsCOMPtr
<nsILocalFile
> profD
, profLD
;
1742 PRUnichar
* profileNamePtr
;
1743 nsCAutoString profileName
;
1746 ScopedXPCOMStartup xpcom
;
1747 rv
= xpcom
.Initialize();
1748 NS_ENSURE_SUCCESS(rv
, rv
);
1750 rv
= xpcom
.DoAutoreg();
1751 rv
|= xpcom
.RegisterProfileService();
1752 rv
|= xpcom
.SetWindowCreator(aNative
);
1753 NS_ENSURE_SUCCESS(rv
, NS_ERROR_FAILURE
);
1756 SetupMacCommandLine(gRestartArgc
, gRestartArgv
);
1760 // we don't have to wait here because profile manager window will pump
1761 // and DDE message will be handled
1762 ProcessDDE(aNative
, PR_FALSE
);
1765 { //extra scoping is needed so we release these components before xpcom shutdown
1766 nsCOMPtr
<nsIWindowWatcher
> windowWatcher
1767 (do_GetService(NS_WINDOWWATCHER_CONTRACTID
));
1768 nsCOMPtr
<nsIDialogParamBlock
> ioParamBlock
1769 (do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID
));
1770 nsCOMPtr
<nsIMutableArray
> dlgArray (do_CreateInstance(NS_ARRAY_CONTRACTID
));
1771 NS_ENSURE_TRUE(windowWatcher
&& ioParamBlock
&& dlgArray
, NS_ERROR_FAILURE
);
1773 ioParamBlock
->SetObjects(dlgArray
);
1775 nsCOMPtr
<nsIAppStartup
> appStartup
1776 (do_GetService(NS_APPSTARTUP_CONTRACTID
));
1777 NS_ENSURE_TRUE(appStartup
, NS_ERROR_FAILURE
);
1779 nsCOMPtr
<nsIDOMWindow
> newWindow
;
1780 rv
= windowWatcher
->OpenWindow(nsnull
,
1783 "centerscreen,chrome,modal,titlebar",
1785 getter_AddRefs(newWindow
));
1787 NS_ENSURE_SUCCESS_LOG(rv
, rv
);
1789 aProfileSvc
->Flush();
1791 PRInt32 dialogConfirmed
;
1792 rv
= ioParamBlock
->GetInt(0, &dialogConfirmed
);
1793 if (NS_FAILED(rv
) || dialogConfirmed
== 0) return NS_ERROR_ABORT
;
1795 nsCOMPtr
<nsIProfileLock
> lock
;
1796 rv
= dlgArray
->QueryElementAt(0, NS_GET_IID(nsIProfileLock
),
1797 getter_AddRefs(lock
));
1798 NS_ENSURE_SUCCESS_LOG(rv
, rv
);
1800 rv
= lock
->GetDirectory(getter_AddRefs(profD
));
1801 NS_ENSURE_SUCCESS(rv
, rv
);
1803 rv
= lock
->GetLocalDirectory(getter_AddRefs(profLD
));
1804 NS_ENSURE_SUCCESS(rv
, rv
);
1806 rv
= ioParamBlock
->GetString(0, &profileNamePtr
);
1807 NS_ENSURE_SUCCESS(rv
, rv
);
1809 CopyUTF16toUTF8(profileNamePtr
, profileName
);
1810 NS_Free(profileNamePtr
);
1816 SaveFileToEnv("XRE_PROFILE_PATH", profD
);
1817 SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", profLD
);
1818 SaveWordToEnv("XRE_PROFILE_NAME", profileName
);
1820 PRBool offline
= PR_FALSE
;
1821 aProfileSvc
->GetStartOffline(&offline
);
1823 PR_SetEnv("XRE_START_OFFLINE=1");
1826 return LaunchChild(aNative
);
1830 ImportProfiles(nsIToolkitProfileService
* aPService
,
1831 nsINativeAppSupport
* aNative
)
1835 PR_SetEnv("XRE_IMPORT_PROFILES=1");
1837 // try to import old-style profiles
1839 ScopedXPCOMStartup xpcom
;
1840 rv
= xpcom
.Initialize();
1841 if (NS_SUCCEEDED(rv
)) {
1843 xpcom
.RegisterProfileService();
1846 SetupMacCommandLine(gRestartArgc
, gRestartArgv
);
1849 nsCOMPtr
<nsIProfileMigrator
> migrator
1850 (do_GetService(NS_PROFILEMIGRATOR_CONTRACTID
));
1858 return LaunchChild(aNative
);
1861 // Pick a profile. We need to end up with a profile lock.
1863 // 1) check for -profile <path>
1864 // 2) check for -P <name>
1865 // 3) check for -ProfileManager
1866 // 4) use the default profile, if there is one
1867 // 5) if there are *no* profiles, set up profile-migration
1868 // 6) display the profile-manager UI
1870 static PRBool gDoMigration
= PR_FALSE
;
1873 SelectProfile(nsIProfileLock
* *aResult
, nsINativeAppSupport
* aNative
,
1874 PRBool
* aStartOffline
, nsACString
* aProfileName
)
1880 *aStartOffline
= PR_FALSE
;
1882 ar
= CheckArg("offline", PR_TRUE
);
1883 if (ar
== ARG_BAD
) {
1884 PR_fprintf(PR_STDERR
, "Error: argument -offline is invalid when argument -osint is specified\n");
1885 return NS_ERROR_FAILURE
;
1888 arg
= PR_GetEnv("XRE_START_OFFLINE");
1889 if ((arg
&& *arg
) || ar
)
1890 *aStartOffline
= PR_TRUE
;
1893 nsCOMPtr
<nsILocalFile
> lf
= GetFileFromEnv("XRE_PROFILE_PATH");
1895 nsCOMPtr
<nsILocalFile
> localDir
=
1896 GetFileFromEnv("XRE_PROFILE_LOCAL_PATH");
1901 arg
= PR_GetEnv("XRE_PROFILE_NAME");
1902 if (arg
&& *arg
&& aProfileName
)
1903 aProfileName
->Assign(nsDependentCString(arg
));
1905 // Clear out flags that we handled (or should have handled!) last startup.
1907 CheckArg("p", PR_FALSE
, &dummy
);
1908 CheckArg("profile", PR_FALSE
, &dummy
);
1909 CheckArg("profilemanager");
1911 return NS_LockProfilePath(lf
, localDir
, nsnull
, aResult
);
1914 ar
= CheckArg("migration", PR_TRUE
);
1915 if (ar
== ARG_BAD
) {
1916 PR_fprintf(PR_STDERR
, "Error: argument -migration is invalid when argument -osint is specified\n");
1917 return NS_ERROR_FAILURE
;
1918 } else if (ar
== ARG_FOUND
) {
1919 gDoMigration
= PR_TRUE
;
1922 ar
= CheckArg("profile", PR_TRUE
, &arg
);
1923 if (ar
== ARG_BAD
) {
1924 PR_fprintf(PR_STDERR
, "Error: argument -profile requires a path\n");
1925 return NS_ERROR_FAILURE
;
1928 nsCOMPtr
<nsILocalFile
> lf
;
1929 rv
= XRE_GetFileFromPath(arg
, getter_AddRefs(lf
));
1930 NS_ENSURE_SUCCESS(rv
, rv
);
1932 nsCOMPtr
<nsIProfileUnlocker
> unlocker
;
1934 // If a profile path is specified directory on the command line, then
1935 // assume that the temp directory is the same as the given directory.
1936 rv
= NS_LockProfilePath(lf
, lf
, getter_AddRefs(unlocker
), aResult
);
1937 if (NS_SUCCEEDED(rv
))
1940 return ProfileLockedDialog(lf
, lf
, unlocker
, aNative
, aResult
);
1943 nsCOMPtr
<nsIToolkitProfileService
> profileSvc
;
1944 rv
= NS_NewToolkitProfileService(getter_AddRefs(profileSvc
));
1945 NS_ENSURE_SUCCESS(rv
, rv
);
1947 ar
= CheckArg("createprofile", PR_TRUE
, &arg
);
1948 if (ar
== ARG_BAD
) {
1949 PR_fprintf(PR_STDERR
, "Error: argument -createprofile requires a profile name\n");
1950 return NS_ERROR_FAILURE
;
1953 nsCOMPtr
<nsIToolkitProfile
> profile
;
1955 const char* delim
= strchr(arg
, ' ');
1957 nsCOMPtr
<nsILocalFile
> lf
;
1958 rv
= NS_NewNativeLocalFile(nsDependentCString(delim
+ 1),
1959 PR_TRUE
, getter_AddRefs(lf
));
1960 if (NS_FAILED(rv
)) {
1961 PR_fprintf(PR_STDERR
, "Error: profile path not valid.\n");
1965 // As with -profile, assume that the given path will be used for both the
1966 // main profile directory and the temp profile directory.
1967 rv
= profileSvc
->CreateProfile(lf
, lf
, nsDependentCSubstring(arg
, delim
),
1968 getter_AddRefs(profile
));
1970 rv
= profileSvc
->CreateProfile(nsnull
, nsnull
, nsDependentCString(arg
),
1971 getter_AddRefs(profile
));
1973 // Some pathological arguments can make it this far
1974 if (NS_FAILED(rv
)) {
1975 PR_fprintf(PR_STDERR
, "Error creating profile.\n");
1978 rv
= NS_ERROR_ABORT
;
1979 profileSvc
->Flush();
1981 // XXXben need to ensure prefs.js exists here so the tinderboxes will
1983 nsCOMPtr
<nsILocalFile
> prefsJSFile
;
1984 profile
->GetRootDir(getter_AddRefs(prefsJSFile
));
1985 prefsJSFile
->AppendNative(NS_LITERAL_CSTRING("prefs.js"));
1986 nsCAutoString pathStr
;
1987 prefsJSFile
->GetNativePath(pathStr
);
1988 PR_fprintf(PR_STDERR
, "Success: created profile '%s' at '%s'\n", arg
, pathStr
.get());
1990 prefsJSFile
->Exists(&exists
);
1992 prefsJSFile
->Create(nsIFile::NORMAL_FILE_TYPE
, 0644);
1993 // XXXdarin perhaps 0600 would be better?
1999 rv
= profileSvc
->GetProfileCount(&count
);
2000 NS_ENSURE_SUCCESS(rv
, rv
);
2002 if (gAppData
->flags
& NS_XRE_ENABLE_PROFILE_MIGRATOR
) {
2003 arg
= PR_GetEnv("XRE_IMPORT_PROFILES");
2004 if (!count
&& (!arg
|| !*arg
)) {
2005 return ImportProfiles(profileSvc
, aNative
);
2009 ar
= CheckArg("p", PR_FALSE
, &arg
);
2010 if (ar
== ARG_BAD
) {
2011 ar
= CheckArg("osint");
2012 if (ar
== ARG_FOUND
) {
2013 PR_fprintf(PR_STDERR
, "Error: argument -p is invalid when argument -osint is specified\n");
2014 return NS_ERROR_FAILURE
;
2016 return ShowProfileManager(profileSvc
, aNative
);
2019 ar
= CheckArg("osint");
2020 if (ar
== ARG_FOUND
) {
2021 PR_fprintf(PR_STDERR
, "Error: argument -p is invalid when argument -osint is specified\n");
2022 return NS_ERROR_FAILURE
;
2024 nsCOMPtr
<nsIToolkitProfile
> profile
;
2025 rv
= profileSvc
->GetProfileByName(nsDependentCString(arg
),
2026 getter_AddRefs(profile
));
2027 if (NS_SUCCEEDED(rv
)) {
2028 nsCOMPtr
<nsIProfileUnlocker
> unlocker
;
2029 rv
= profile
->Lock(nsnull
, aResult
);
2030 if (NS_SUCCEEDED(rv
)) {
2032 aProfileName
->Assign(nsDependentCString(arg
));
2036 nsCOMPtr
<nsILocalFile
> profileDir
;
2037 rv
= profile
->GetRootDir(getter_AddRefs(profileDir
));
2038 NS_ENSURE_SUCCESS(rv
, rv
);
2040 nsCOMPtr
<nsILocalFile
> profileLocalDir
;
2041 rv
= profile
->GetLocalDir(getter_AddRefs(profileLocalDir
));
2042 NS_ENSURE_SUCCESS(rv
, rv
);
2044 return ProfileLockedDialog(profileDir
, profileLocalDir
, unlocker
,
2048 return ShowProfileManager(profileSvc
, aNative
);
2051 ar
= CheckArg("profilemanager", PR_TRUE
);
2052 if (ar
== ARG_BAD
) {
2053 PR_fprintf(PR_STDERR
, "Error: argument -profilemanager is invalid when argument -osint is specified\n");
2054 return NS_ERROR_FAILURE
;
2055 } else if (ar
== ARG_FOUND
) {
2056 return ShowProfileManager(profileSvc
, aNative
);
2060 gDoMigration
= PR_TRUE
;
2062 // create a default profile
2063 nsCOMPtr
<nsIToolkitProfile
> profile
;
2064 nsresult rv
= profileSvc
->CreateProfile(nsnull
, // choose a default dir for us
2065 nsnull
, // choose a default dir for us
2066 NS_LITERAL_CSTRING("default"),
2067 getter_AddRefs(profile
));
2068 if (NS_SUCCEEDED(rv
)) {
2069 profileSvc
->Flush();
2070 rv
= profile
->Lock(nsnull
, aResult
);
2071 if (NS_SUCCEEDED(rv
)) {
2073 aProfileName
->Assign(NS_LITERAL_CSTRING("default"));
2079 PRBool useDefault
= PR_TRUE
;
2081 profileSvc
->GetStartWithLastProfile(&useDefault
);
2084 nsCOMPtr
<nsIToolkitProfile
> profile
;
2085 // GetSelectedProfile will auto-select the only profile if there's just one
2086 profileSvc
->GetSelectedProfile(getter_AddRefs(profile
));
2088 nsCOMPtr
<nsIProfileUnlocker
> unlocker
;
2089 rv
= profile
->Lock(getter_AddRefs(unlocker
), aResult
);
2090 if (NS_SUCCEEDED(rv
)) {
2091 // Try to grab the profile name.
2093 rv
= profile
->GetName(*aProfileName
);
2095 aProfileName
->Truncate(0);
2100 nsCOMPtr
<nsILocalFile
> profileDir
;
2101 rv
= profile
->GetRootDir(getter_AddRefs(profileDir
));
2102 NS_ENSURE_SUCCESS(rv
, rv
);
2104 nsCOMPtr
<nsILocalFile
> profileLocalDir
;
2105 rv
= profile
->GetRootDir(getter_AddRefs(profileLocalDir
));
2106 NS_ENSURE_SUCCESS(rv
, rv
);
2108 return ProfileLockedDialog(profileDir
, profileLocalDir
, unlocker
,
2113 return ShowProfileManager(profileSvc
, aNative
);
2116 #define FILE_COMPATIBILITY_INFO NS_LITERAL_CSTRING("compatibility.ini")
2119 CheckCompatibility(nsIFile
* aProfileDir
, const nsCString
& aVersion
,
2120 const nsCString
& aOSABI
, nsIFile
* aXULRunnerDir
,
2123 nsCOMPtr
<nsIFile
> file
;
2124 aProfileDir
->Clone(getter_AddRefs(file
));
2127 file
->AppendNative(FILE_COMPATIBILITY_INFO
);
2130 nsCOMPtr
<nsILocalFile
> localFile(do_QueryInterface(file
));
2131 nsresult rv
= parser
.Init(localFile
);
2136 rv
= parser
.GetString("Compatibility", "LastVersion", buf
);
2137 if (NS_FAILED(rv
) || !aVersion
.Equals(buf
))
2140 rv
= parser
.GetString("Compatibility", "LastOSABI", buf
);
2141 if (NS_FAILED(rv
) || !aOSABI
.Equals(buf
))
2144 rv
= parser
.GetString("Compatibility", "LastPlatformDir", buf
);
2148 nsCOMPtr
<nsILocalFile
> lf
;
2149 rv
= NS_NewNativeLocalFile(buf
, PR_FALSE
,
2150 getter_AddRefs(lf
));
2155 rv
= lf
->Equals(aXULRunnerDir
, &eq
);
2156 if (NS_FAILED(rv
) || !eq
)
2160 rv
= parser
.GetString("Compatibility", "LastAppDir", buf
);
2164 rv
= NS_NewNativeLocalFile(buf
, PR_FALSE
,
2165 getter_AddRefs(lf
));
2169 rv
= lf
->Equals(aAppDir
, &eq
);
2170 if (NS_FAILED(rv
) || !eq
)
2177 static void BuildVersion(nsCString
&aBuf
)
2179 aBuf
.Assign(gAppData
->version
);
2181 aBuf
.Append(gAppData
->buildID
);
2183 aBuf
.Append(gToolkitBuildID
);
2187 WriteVersion(nsIFile
* aProfileDir
, const nsCString
& aVersion
,
2188 const nsCString
& aOSABI
, nsIFile
* aXULRunnerDir
,
2191 nsCOMPtr
<nsIFile
> file
;
2192 aProfileDir
->Clone(getter_AddRefs(file
));
2195 file
->AppendNative(FILE_COMPATIBILITY_INFO
);
2197 nsCOMPtr
<nsILocalFile
> lf
= do_QueryInterface(file
);
2199 nsCAutoString platformDir
;
2200 aXULRunnerDir
->GetNativePath(platformDir
);
2202 nsCAutoString appDir
;
2204 aAppDir
->GetNativePath(appDir
);
2206 PRFileDesc
*fd
= nsnull
;
2207 lf
->OpenNSPRFileDesc(PR_WRONLY
| PR_CREATE_FILE
| PR_TRUNCATE
, 0600, &fd
);
2209 NS_ERROR("could not create output stream");
2213 static const char kHeader
[] = "[Compatibility]" NS_LINEBREAK
2216 PR_Write(fd
, kHeader
, sizeof(kHeader
) - 1);
2217 PR_Write(fd
, aVersion
.get(), aVersion
.Length());
2219 static const char kOSABIHeader
[] = NS_LINEBREAK
"LastOSABI=";
2220 PR_Write(fd
, kOSABIHeader
, sizeof(kOSABIHeader
) - 1);
2221 PR_Write(fd
, aOSABI
.get(), aOSABI
.Length());
2223 static const char kPlatformDirHeader
[] = NS_LINEBREAK
"LastPlatformDir=";
2225 PR_Write(fd
, kPlatformDirHeader
, sizeof(kPlatformDirHeader
) - 1);
2226 PR_Write(fd
, platformDir
.get(), platformDir
.Length());
2228 static const char kAppDirHeader
[] = NS_LINEBREAK
"LastAppDir=";
2230 PR_Write(fd
, kAppDirHeader
, sizeof(kAppDirHeader
) - 1);
2231 PR_Write(fd
, appDir
.get(), appDir
.Length());
2234 static const char kNL
[] = NS_LINEBREAK
;
2235 PR_Write(fd
, kNL
, sizeof(kNL
) - 1);
2240 static PRBool
ComponentsListChanged(nsIFile
* aProfileDir
)
2242 nsCOMPtr
<nsIFile
> file
;
2243 aProfileDir
->Clone(getter_AddRefs(file
));
2246 file
->AppendNative(NS_LITERAL_CSTRING(".autoreg"));
2248 PRBool exists
= PR_FALSE
;
2249 file
->Exists(&exists
);
2253 static void RemoveComponentRegistries(nsIFile
* aProfileDir
, nsIFile
* aLocalProfileDir
,
2254 PRBool aRemoveEMFiles
)
2256 nsCOMPtr
<nsIFile
> file
;
2257 aProfileDir
->Clone(getter_AddRefs(file
));
2261 file
->AppendNative(NS_LITERAL_CSTRING("compreg.dat"));
2262 file
->Remove(PR_FALSE
);
2264 file
->SetNativeLeafName(NS_LITERAL_CSTRING("xpti.dat"));
2265 file
->Remove(PR_FALSE
);
2267 file
->SetNativeLeafName(NS_LITERAL_CSTRING(".autoreg"));
2268 file
->Remove(PR_FALSE
);
2270 if (aRemoveEMFiles
) {
2271 file
->SetNativeLeafName(NS_LITERAL_CSTRING("extensions.ini"));
2272 file
->Remove(PR_FALSE
);
2275 aLocalProfileDir
->Clone(getter_AddRefs(file
));
2279 file
->AppendNative(NS_LITERAL_CSTRING("XUL" PLATFORM_FASL_SUFFIX
));
2280 file
->Remove(PR_FALSE
);
2283 // To support application initiated restart via nsIAppStartup.quit, we
2284 // need to save various environment variables, and then restore them
2285 // before re-launching the application.
2291 {"XUL_APP_FILE", nsnull
}
2294 static void SaveStateForAppInitiatedRestart()
2296 for (size_t i
= 0; i
< NS_ARRAY_LENGTH(gSavedVars
); ++i
) {
2297 const char *s
= PR_GetEnv(gSavedVars
[i
].name
);
2299 gSavedVars
[i
].value
= PR_smprintf("%s=%s", gSavedVars
[i
].name
, s
);
2303 static void RestoreStateForAppInitiatedRestart()
2305 for (size_t i
= 0; i
< NS_ARRAY_LENGTH(gSavedVars
); ++i
) {
2306 if (gSavedVars
[i
].value
)
2307 PR_SetEnv(gSavedVars
[i
].value
);
2311 #ifdef MOZ_CRASHREPORTER
2312 // When we first initialize the crash reporter we don't have a profile,
2313 // so we set the minidump path to $TEMP. Once we have a profile,
2314 // we set it to $PROFILE/minidumps, creating the directory
2316 static void MakeOrSetMinidumpPath(nsIFile
* profD
)
2318 nsCOMPtr
<nsIFile
> dumpD
;
2319 nsresult rv
= profD
->Clone(getter_AddRefs(dumpD
));
2323 //XXX: do some more error checking here
2324 dumpD
->Append(NS_LITERAL_STRING("minidumps"));
2325 rv
= dumpD
->Exists(&fileExists
);
2327 dumpD
->Create(nsIFile::DIRECTORY_TYPE
, 0700);
2330 nsAutoString pathStr
;
2331 if(NS_SUCCEEDED(dumpD
->GetPath(pathStr
)))
2332 CrashReporter::SetMinidumpPath(pathStr
);
2337 const nsXREAppData
* gAppData
= nsnull
;
2340 // because we use early returns, we use a stack-based helper to un-set the OS2 FP handler
2341 class ScopedFPHandler
{
2343 EXCEPTIONREGISTRATIONRECORD excpreg
;
2346 ScopedFPHandler() { PR_OS2_SetFloatExcpHandler(&excpreg
); }
2347 ~ScopedFPHandler() { PR_OS2_UnsetFloatExcpHandler(&excpreg
); }
2351 #ifdef MOZ_WIDGET_GTK2
2353 typedef void (*_g_set_application_name_fn
)(const gchar
*application_name
);
2354 typedef void (*_gtk_window_set_auto_startup_notification_fn
)(gboolean setting
);
2356 static PRFuncPtr
FindFunction(const char* aName
)
2358 PRLibrary
*lib
= nsnull
;
2359 PRFuncPtr result
= PR_FindFunctionSymbolAndLibrary(aName
, &lib
);
2360 // Since the library was already loaded, we can safely unload it here.
2362 PR_UnloadLibrary(lib
);
2367 static nsIWidget
* GetMainWidget(nsIDOMWindow
* aWindow
)
2369 // get the native window for this instance
2370 nsCOMPtr
<nsPIDOMWindow
> window(do_QueryInterface(aWindow
));
2371 NS_ENSURE_TRUE(window
, nsnull
);
2373 nsCOMPtr
<nsIBaseWindow
> baseWindow
2374 (do_QueryInterface(window
->GetDocShell()));
2375 NS_ENSURE_TRUE(baseWindow
, nsnull
);
2377 nsCOMPtr
<nsIWidget
> mainWidget
;
2378 baseWindow
->GetMainWidget(getter_AddRefs(mainWidget
));
2382 static nsGTKToolkit
* GetGTKToolkit()
2384 nsCOMPtr
<nsIAppShellService
> svc
= do_GetService(NS_APPSHELLSERVICE_CONTRACTID
);
2387 nsCOMPtr
<nsIDOMWindowInternal
> window
;
2388 svc
->GetHiddenDOMWindow(getter_AddRefs(window
));
2391 nsIWidget
* widget
= GetMainWidget(window
);
2394 nsIToolkit
* toolkit
= widget
->GetToolkit();
2397 return static_cast<nsGTKToolkit
*>(toolkit
);
2400 static void MOZ_gdk_display_close(GdkDisplay
*display
)
2402 // XXX wallpaper for bug 417163: don't close the Display if we're using the
2403 // Qt theme because we crash (in Qt code) when using jemalloc.
2404 PRBool theme_is_qt
= PR_FALSE
;
2405 GtkSettings
* settings
=
2406 gtk_settings_get_for_screen(gdk_display_get_default_screen(display
));
2408 g_object_get(settings
, "gtk-theme-name", &theme_name
, NULL
);
2410 theme_is_qt
= strcmp(theme_name
, "Qt") == 0;
2412 NS_WARNING("wallpaper bug 417163 for Qt theme");
2416 // gdk_display_close was broken prior to gtk+-2.10.0.
2417 // (http://bugzilla.gnome.org/show_bug.cgi?id=85715)
2418 // gdk_display_manager_set_default_display (gdk_display_manager_get(), NULL)
2420 if (gtk_check_version(2,10,0) != NULL
) {
2422 // Version check failed - broken gdk_display_close.
2424 // Let the gdk structures leak but at least close the Display,
2425 // assuming that gdk will not use it again.
2426 Display
* dpy
= GDK_DISPLAY_XDISPLAY(display
);
2430 gdk_display_close(display
);
2431 #endif /* MOZ_X11 */
2435 // Get a (new) Pango context that holds a reference to the fontmap that
2436 // GTK has been using. gdk_pango_context_get() must be called while GTK
2437 // has a default display.
2438 PangoContext
*pangoContext
= gdk_pango_context_get();
2442 gdk_display_close(display
);
2445 // This doesn't take a reference.
2446 PangoFontMap
*fontmap
= pango_context_get_font_map(pangoContext
);
2447 // Do some shutdown of the fontmap, which releases the fonts, clearing a
2448 // bunch of circular references from the fontmap through the fonts back to
2449 // itself. The shutdown that this does is much less than what's done by
2450 // the fontmap's finalize, though.
2451 if (PANGO_IS_FC_FONT_MAP(fontmap
))
2452 pango_fc_font_map_shutdown(PANGO_FC_FONT_MAP(fontmap
));
2453 g_object_unref(pangoContext
);
2454 // PangoCairo still holds a reference to the fontmap.
2455 // Now that we have finished with GTK and Pango, we could unref fontmap,
2456 // which would allow us to call FcFini, but removing what is really
2457 // Pango's ref feels a bit evil. Pango-1.22 will have support for
2458 // pango_cairo_font_map_set_default(NULL), which would release the
2459 // reference on the old fontmap.
2461 #if GTK_CHECK_VERSION(2,8,0)
2462 // cairo_debug_reset_static_data() is prototyped through cairo.h included
2464 #ifdef cairo_debug_reset_static_data
2465 #error "Looks like we're including Mozilla's cairo instead of system cairo"
2467 cairo_debug_reset_static_data();
2469 #endif // CLEANUP_MEMORY
2472 #endif // MOZ_WIDGET_GTK2
2475 * NSPR will search for the "nspr_use_zone_allocator" symbol throughout
2476 * the process and use it to determine whether the application defines its own
2477 * memory allocator or not.
2479 * Since most applications (e.g. Firefox and Thunderbird) don't use any special
2480 * allocators and therefore don't define this symbol, NSPR must search the
2481 * entire process, which reduces startup performance.
2483 * By defining the symbol here, we can avoid the wasted lookup and hopefully
2484 * improve startup performance.
2486 PRBool nspr_use_zone_allocator
= PR_FALSE
;
2489 XRE_main(int argc
, char* argv
[], const nsXREAppData
* aAppData
)
2493 NS_TIMELINE_MARK("enter main");
2496 if (PR_GetEnv("XRE_MAIN_BREAK"))
2500 #if defined (XP_WIN32) && !defined (WINCE)
2501 // Suppress the "DLL Foo could not be found" dialog, such that if dependent
2502 // libraries (such as GDI+) are not preset, we gracefully fail to load those
2503 // XPCOM components, instead of being ungraceful.
2504 UINT realMode
= SetErrorMode(0);
2505 realMode
|= SEM_FAILCRITICALERRORS
;
2506 // If XRE_NO_WINDOWS_CRASH_DIALOG is set, suppress displaying the "This
2507 // application has crashed" dialog box. This is mainly useful for
2508 // automated testing environments, e.g. tinderbox, where there's no need
2509 // for a dozen of the dialog boxes to litter the console
2510 if (getenv("XRE_NO_WINDOWS_CRASH_DIALOG"))
2511 realMode
|= SEM_NOGPFAULTERRORBOX
| SEM_NOOPENFILEERRORBOX
;
2513 SetErrorMode(realMode
);
2516 // Disable small heap allocator to get heapwalk() giving us
2517 // accurate heap numbers. Win2k non-debug does not use small heap allocator.
2518 // Win2k debug seems to be still using it.
2519 // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt__set_sbh_threshold.asp
2520 _set_sbh_threshold(0);
2524 #if defined(XP_UNIX) || defined(XP_BEOS)
2525 InstallUnixSignalHandlers(argv
[0]);
2528 #ifdef MOZ_ACCESSIBILITY_ATK
2529 // Reset GTK_MODULES, strip atk-bridge if exists
2530 // Mozilla will load libatk-bridge.so later if necessary
2531 const char* gtkModules
= PR_GetEnv("GTK_MODULES");
2532 if (gtkModules
&& *gtkModules
) {
2533 nsCString
gtkModulesStr(gtkModules
);
2534 gtkModulesStr
.ReplaceSubstring("atk-bridge", "");
2535 char* expr
= PR_smprintf("GTK_MODULES=%s", gtkModulesStr
.get());
2538 // We intentionally leak |expr| here since it is required by PR_SetEnv.
2541 // Suppress atk-bridge init at startup, it works after GNOME 2.24.2
2542 PR_SetEnv("NO_AT_BRIDGE=1");
2546 // Unbuffer stdout, needed for tinderbox tests.
2550 #if defined(FREEBSD)
2551 // Disable all SIGFPE's on FreeBSD, as it has non-IEEE-conformant fp
2552 // trap behavior that trips up on floating-point tests performed by
2553 // the JS engine. See bugzilla bug 9967 details.
2560 NS_ENSURE_TRUE(aAppData
, 2);
2563 // The xulrunner stub executable tricks CFBundleGetMainBundle on
2564 // purpose into lying about the main bundle path. It will set
2565 // XRE_BINARY_PATH to inform us of our real location.
2566 gBinaryPath
= getenv("XRE_BINARY_PATH");
2568 if (gBinaryPath
&& !*gBinaryPath
)
2569 gBinaryPath
= nsnull
;
2572 // Check for application.ini overrides
2573 const char* override
= nsnull
;
2574 ar
= CheckArg("override", PR_TRUE
, &override
);
2575 if (ar
== ARG_BAD
) {
2576 Output(PR_TRUE
, "Incorrect number of arguments passed to -override");
2579 else if (ar
== ARG_FOUND
) {
2580 nsCOMPtr
<nsILocalFile
> overrideLF
;
2581 rv
= XRE_GetFileFromPath(override
, getter_AddRefs(overrideLF
));
2582 if (NS_FAILED(rv
)) {
2583 Output(PR_TRUE
, "Error: unrecognized override.ini path.\n");
2587 nsXREAppData
* overrideAppData
= const_cast<nsXREAppData
*>(aAppData
);
2588 rv
= XRE_ParseAppData(overrideLF
, overrideAppData
);
2589 if (NS_FAILED(rv
)) {
2590 Output(PR_TRUE
, "Couldn't read override.ini");
2595 ScopedAppData
appData(aAppData
);
2596 gAppData
= &appData
;
2598 // Check sanity and correctness of app data.
2600 if (!appData
.name
) {
2601 Output(PR_TRUE
, "Error: App:Name not specified in application.ini\n");
2604 if (!appData
.buildID
) {
2605 Output(PR_TRUE
, "Error: App:BuildID not specified in application.ini\n");
2611 if (!appData
.xreDirectory
) {
2612 nsCOMPtr
<nsILocalFile
> lf
;
2613 rv
= XRE_GetBinaryPath(gArgv
[0], getter_AddRefs(lf
));
2617 nsCOMPtr
<nsIFile
> greDir
;
2618 rv
= lf
->GetParent(getter_AddRefs(greDir
));
2622 rv
= CallQueryInterface(greDir
, &appData
.xreDirectory
);
2627 nsCOMPtr
<nsIFile
> iniFile
;
2628 rv
= appData
.xreDirectory
->Clone(getter_AddRefs(iniFile
));
2632 iniFile
->AppendNative(NS_LITERAL_CSTRING("platform.ini"));
2634 nsCOMPtr
<nsILocalFile
> localIniFile
= do_QueryInterface(iniFile
);
2639 rv
= parser
.Init(localIniFile
);
2640 if (NS_SUCCEEDED(rv
)) {
2641 rv
= parser
.GetString("Build", "Milestone",
2642 gToolkitVersion
, sizeof(gToolkitVersion
));
2643 NS_ASSERTION(NS_SUCCEEDED(rv
), "Failed to get toolkit version");
2645 rv
= parser
.GetString("Build", "BuildID",
2646 gToolkitBuildID
, sizeof(gToolkitBuildID
));
2647 NS_ASSERTION(NS_SUCCEEDED(rv
), "Failed to get toolkit buildid");
2650 NS_ERROR("Couldn't parse platform.ini!");
2653 if (appData
.size
> offsetof(nsXREAppData
, minVersion
)) {
2654 if (!appData
.minVersion
) {
2655 Output(PR_TRUE
, "Error: Gecko:MinVersion not specified in application.ini\n");
2659 if (!appData
.maxVersion
) {
2660 // If no maxVersion is specified, we assume the app is only compatible
2661 // with the initial preview release. Do not increment this number ever!
2662 SetAllocatedString(appData
.maxVersion
, "1.*");
2665 if (NS_CompareVersions(appData
.minVersion
, gToolkitVersion
) > 0 ||
2666 NS_CompareVersions(appData
.maxVersion
, gToolkitVersion
) < 0) {
2667 Output(PR_TRUE
, "Error: Platform version '%s' is not compatible with\n"
2668 "minVersion >= %s\nmaxVersion <= %s\n",
2670 appData
.minVersion
, appData
.maxVersion
);
2675 #ifdef MOZ_CRASHREPORTER
2676 const char* crashreporterEnv
= PR_GetEnv("MOZ_CRASHREPORTER");
2677 if (crashreporterEnv
&& *crashreporterEnv
) {
2678 appData
.flags
|= NS_XRE_ENABLE_CRASH_REPORTER
;
2681 if ((appData
.flags
& NS_XRE_ENABLE_CRASH_REPORTER
) &&
2683 CrashReporter::SetExceptionHandler(appData
.xreDirectory
,
2684 appData
.crashReporterURL
))) {
2685 // pass some basic info from the app data
2687 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Vendor"),
2688 nsDependentCString(appData
.vendor
));
2690 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ProductName"),
2691 nsDependentCString(appData
.name
));
2692 if (appData
.version
)
2693 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Version"),
2694 nsDependentCString(appData
.version
));
2695 if (appData
.buildID
)
2696 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("BuildID"),
2697 nsDependentCString(appData
.buildID
));
2698 CrashReporter::SetRestartArgs(argc
, argv
);
2700 // annotate other data (user id etc)
2701 nsXREDirProvider dirProvider
;
2702 nsCOMPtr
<nsILocalFile
> userAppDataDir
;
2703 rv
= dirProvider
.Initialize(gAppData
->directory
, gAppData
->xreDirectory
);
2704 if (NS_SUCCEEDED(rv
) &&
2705 NS_SUCCEEDED(dirProvider
.GetUserAppDataDirectory(
2706 getter_AddRefs(userAppDataDir
)))) {
2707 CrashReporter::SetupExtraData(userAppDataDir
,
2708 nsDependentCString(appData
.buildID
));
2710 // see if we have a crashreporter-override.ini in the application directory
2711 nsCOMPtr
<nsIFile
> overrideini
;
2713 static char overrideEnv
[MAXPATHLEN
];
2714 if (NS_SUCCEEDED(dirProvider
.GetAppDir()->Clone(getter_AddRefs(overrideini
))) &&
2715 NS_SUCCEEDED(overrideini
->AppendNative(NS_LITERAL_CSTRING("crashreporter-override.ini"))) &&
2716 NS_SUCCEEDED(overrideini
->Exists(&exists
)) &&
2719 nsAutoString overridePathW
;
2720 overrideini
->GetPath(overridePathW
);
2721 NS_ConvertUTF16toUTF8
overridePath(overridePathW
);
2723 nsCAutoString overridePath
;
2724 overrideini
->GetNativePath(overridePath
);
2727 sprintf(overrideEnv
, "MOZ_CRASHREPORTER_STRINGS_OVERRIDE=%s",
2728 overridePath
.get());
2729 PR_SetEnv(overrideEnv
);
2736 if (PR_GetEnv("MOZ_LAUNCHED_CHILD")) {
2737 // This is needed, on relaunch, to force the OS to use the "Cocoa Dock
2738 // API". Otherwise the call to ReceiveNextEvent() below will make it
2739 // use the "Carbon Dock API". For more info see bmo bug 377166.
2740 EnsureUseCocoaDockAPI();
2742 // When the app relaunches, the original process exits. This causes
2743 // the dock tile to stop bouncing, lose the "running" triangle, and
2744 // if the tile does not permanently reside in the Dock, even disappear.
2745 // This can be confusing to the user, who is expecting the app to launch.
2746 // Calling ReceiveNextEvent without requesting any event is enough to
2747 // cause a dock tile for the child process to appear.
2748 const EventTypeSpec kFakeEventList
[] = { { INT_MAX
, INT_MAX
} };
2750 ::ReceiveNextEvent(GetEventTypeCount(kFakeEventList
), kFakeEventList
,
2751 kEventDurationNoWait
, PR_FALSE
, &event
);
2754 if (CheckArg("foreground")) {
2755 // The original process communicates that it was in the foreground by
2756 // adding this argument. This new process, which is taking over for
2757 // the old one, should make itself the active application.
2758 ProcessSerialNumber psn
;
2759 if (::GetCurrentProcess(&psn
) == noErr
)
2760 ::SetFrontProcess(&psn
);
2764 PR_SetEnv("MOZ_LAUNCHED_CHILD=");
2766 gRestartArgc
= gArgc
;
2767 gRestartArgv
= (char**) malloc(sizeof(char*) * (gArgc
+ 1 + (override
? 2 : 0)));
2768 if (!gRestartArgv
) return 1;
2771 for (i
= 0; i
< gArgc
; ++i
) {
2772 gRestartArgv
[i
] = gArgv
[i
];
2775 // Add the -override argument back (it is removed automatically be CheckArg) if there is one
2777 gRestartArgv
[gRestartArgc
++] = const_cast<char*>("-override");
2778 gRestartArgv
[gRestartArgc
++] = const_cast<char*>(override
);
2781 gRestartArgv
[gRestartArgc
] = nsnull
;
2785 PRBool
StartOS2App(int aArgc
, char **aArgv
);
2786 if (!StartOS2App(gArgc
, gArgv
))
2788 ScopedFPHandler handler
;
2791 ar
= CheckArg("safe-mode", PR_TRUE
);
2792 if (ar
== ARG_BAD
) {
2793 PR_fprintf(PR_STDERR
, "Error: argument -safe-mode is invalid when argument -osint is specified\n");
2795 } else if (ar
== ARG_FOUND
) {
2796 gSafeMode
= PR_TRUE
;
2800 if (GetCurrentEventKeyModifiers() & optionKey
)
2801 gSafeMode
= PR_TRUE
;
2804 // Handle -no-remote command line argument. Setup the environment to
2805 // better accommodate other components and various restart scenarios.
2806 ar
= CheckArg("no-remote", PR_TRUE
);
2807 if (ar
== ARG_BAD
) {
2808 PR_fprintf(PR_STDERR
, "Error: argument -a requires an application name\n");
2810 } else if (ar
== ARG_FOUND
) {
2811 PR_SetEnv("MOZ_NO_REMOTE=1");
2814 // Handle -help and -version command line arguments.
2815 // They should return quickly, so we deal with them here.
2816 if (CheckArg("h") || CheckArg("help") || CheckArg("?")) {
2821 if (CheckArg("v") || CheckArg("version")) {
2826 #ifdef NS_TRACE_MALLOC
2827 gArgc
= argc
= NS_TraceMallocStartupArgs(gArgc
, gArgv
);
2831 nsXREDirProvider dirProvider
;
2832 rv
= dirProvider
.Initialize(gAppData
->directory
, gAppData
->xreDirectory
);
2836 // Check for -register, which registers chrome and then exits immediately.
2837 ar
= CheckArg("register", PR_TRUE
);
2838 if (ar
== ARG_BAD
) {
2839 PR_fprintf(PR_STDERR
, "Error: argument -register is invalid when argument -osint is specified\n");
2841 } else if (ar
== ARG_FOUND
) {
2842 ScopedXPCOMStartup xpcom
;
2843 rv
= xpcom
.Initialize();
2844 NS_ENSURE_SUCCESS(rv
, 1);
2847 nsCOMPtr
<nsIChromeRegistry
> chromeReg
2848 (do_GetService("@mozilla.org/chrome/chrome-registry;1"));
2849 NS_ENSURE_TRUE(chromeReg
, 1);
2851 chromeReg
->CheckForNewChrome();
2856 #if defined(MOZ_WIDGET_GTK2) || defined(MOZ_ENABLE_XREMOTE)
2857 // Stash DESKTOP_STARTUP_ID in malloc'ed memory because gtk_init will clear it.
2858 #define HAVE_DESKTOP_STARTUP_ID
2859 const char* desktopStartupIDEnv
= PR_GetEnv("DESKTOP_STARTUP_ID");
2860 nsCAutoString desktopStartupID
;
2861 if (desktopStartupIDEnv
) {
2862 desktopStartupID
.Assign(desktopStartupIDEnv
);
2866 #if defined(MOZ_WIDGET_QT)
2867 QApplication
app(gArgc
, gArgv
);
2869 #if defined(MOZ_WIDGET_GTK2)
2871 // Disable the slice allocator, since jemalloc already uses similar layout
2872 // algorithms, and using a sub-allocator tends to increase fragmentation.
2873 // This must be done before g_thread_init() is called.
2874 g_slice_set_config(G_SLICE_CONFIG_ALWAYS_MALLOC
, 1);
2876 g_thread_init(NULL
);
2877 // setup for private colormap. Ideally we'd like to do this
2878 // in nsAppShell::Create, but we need to get in before gtk
2879 // has been initialized to make sure everything is running
2881 if (CheckArg("install"))
2882 gdk_rgb_set_install(TRUE
);
2884 // Initialize GTK here for splash.
2886 // Open the display ourselves instead of using gtk_init, so that we can
2887 // close it without fear that one day gtk might clean up the display it
2889 if (!gtk_parse_args(&gArgc
, &gArgv
))
2892 // display_name is owned by gdk.
2893 const char *display_name
= gdk_get_display_arg_name();
2895 SaveWordToEnv("DISPLAY", nsDependentCString(display_name
));
2897 display_name
= PR_GetEnv("DISPLAY");
2898 if (!display_name
) {
2899 PR_fprintf(PR_STDERR
, "Error: no display specified\n");
2903 #endif /* MOZ_WIDGET_GTK2 */
2905 #ifdef MOZ_ENABLE_XREMOTE
2906 // handle -remote now that xpcom is fired up
2908 const char* xremotearg
;
2909 ar
= CheckArg("remote", PR_TRUE
, &xremotearg
);
2910 if (ar
== ARG_BAD
) {
2911 PR_fprintf(PR_STDERR
, "Error: -remote requires an argument\n");
2914 const char* desktopStartupIDPtr
=
2915 desktopStartupID
.IsEmpty() ? nsnull
: desktopStartupID
.get();
2917 return HandleRemoteArgument(xremotearg
, desktopStartupIDPtr
);
2920 if (!PR_GetEnv("MOZ_NO_REMOTE")) {
2921 // Try to remote the entire command line. If this fails, start up normally.
2922 RemoteResult rr
= RemoteCommandLine(desktopStartupIDPtr
);
2923 if (rr
== REMOTE_FOUND
)
2925 else if (rr
== REMOTE_ARG_BAD
)
2930 #if defined(MOZ_WIDGET_GTK2)
2931 GdkDisplay
* display
= nsnull
;
2932 display
= gdk_display_open(display_name
);
2934 PR_fprintf(PR_STDERR
, "Error: cannot open display: %s\n", display_name
);
2937 gdk_display_manager_set_default_display (gdk_display_manager_get(),
2940 // g_set_application_name () is only defined in glib2.2 and higher.
2941 _g_set_application_name_fn _g_set_application_name
=
2942 (_g_set_application_name_fn
)FindFunction("g_set_application_name");
2943 if (_g_set_application_name
) {
2944 _g_set_application_name(gAppData
->name
);
2946 _gtk_window_set_auto_startup_notification_fn _gtk_window_set_auto_startup_notification
=
2947 (_gtk_window_set_auto_startup_notification_fn
)FindFunction("gtk_window_set_auto_startup_notification");
2948 if (_gtk_window_set_auto_startup_notification
) {
2949 _gtk_window_set_auto_startup_notification(PR_FALSE
);
2952 gtk_widget_set_default_visual(gdk_rgb_get_visual());
2953 gtk_widget_set_default_colormap(gdk_rgb_get_cmap());
2954 #endif /* MOZ_WIDGET_GTK2 */
2956 // Call the code to install our handler
2958 setupProfilingStuff();
2961 // Try to allocate "native app support."
2962 nsCOMPtr
<nsINativeAppSupport
> nativeApp
;
2963 rv
= NS_CreateNativeAppSupport(getter_AddRefs(nativeApp
));
2967 PRBool canRun
= PR_FALSE
;
2968 rv
= nativeApp
->Start(&canRun
);
2969 if (NS_FAILED(rv
) || !canRun
) {
2973 #if defined(MOZ_UPDATER)
2974 // Check for and process any available updates
2975 nsCOMPtr
<nsIFile
> updRoot
;
2977 rv
= dirProvider
.GetFile(XRE_UPDATE_ROOT_DIR
, &persistent
,
2978 getter_AddRefs(updRoot
));
2979 // XRE_UPDATE_ROOT_DIR may fail. Fallback to appDir if failed
2981 updRoot
= dirProvider
.GetAppDir();
2983 ProcessUpdates(dirProvider
.GetGREDir(),
2984 dirProvider
.GetAppDir(),
2991 nsCOMPtr
<nsIProfileLock
> profileLock
;
2992 PRBool startOffline
= PR_FALSE
;
2993 nsCAutoString profileName
;
2995 rv
= SelectProfile(getter_AddRefs(profileLock
), nativeApp
, &startOffline
,
2997 if (rv
== NS_ERROR_LAUNCHED_CHILD_PROCESS
||
2998 rv
== NS_ERROR_ABORT
) return 0;
2999 if (NS_FAILED(rv
)) return 1;
3001 nsCOMPtr
<nsILocalFile
> profD
;
3002 rv
= profileLock
->GetDirectory(getter_AddRefs(profD
));
3003 NS_ENSURE_SUCCESS(rv
, 1);
3005 nsCOMPtr
<nsILocalFile
> profLD
;
3006 rv
= profileLock
->GetLocalDirectory(getter_AddRefs(profLD
));
3007 NS_ENSURE_SUCCESS(rv
, 1);
3009 rv
= dirProvider
.SetProfile(profD
, profLD
);
3010 NS_ENSURE_SUCCESS(rv
, 1);
3012 //////////////////////// NOW WE HAVE A PROFILE ////////////////////////
3014 #ifdef MOZ_CRASHREPORTER
3015 if (appData
.flags
& NS_XRE_ENABLE_CRASH_REPORTER
)
3016 MakeOrSetMinidumpPath(profD
);
3019 PRBool upgraded
= PR_FALSE
;
3021 nsCAutoString version
;
3022 BuildVersion(version
);
3024 #ifdef TARGET_OS_ABI
3025 NS_NAMED_LITERAL_CSTRING(osABI
, TARGET_OS_ABI
);
3027 // No TARGET_XPCOM_ABI, but at least the OS is known
3028 NS_NAMED_LITERAL_CSTRING(osABI
, OS_TARGET
"_UNKNOWN");
3031 // Check for version compatibility with the last version of the app this
3032 // profile was started with. The format of the version stamp is defined
3033 // by the BuildVersion function.
3034 PRBool versionOK
= CheckCompatibility(profD
, version
, osABI
,
3035 dirProvider
.GetGREDir(),
3036 gAppData
->directory
);
3038 // Every time a profile is loaded by a build with a different version,
3039 // it updates the compatibility.ini file saying what version last wrote
3040 // the compreg.dat. On subsequent launches if the version matches,
3041 // there is no need for re-registration. If the user loads the same
3042 // profile in different builds the component registry must be
3043 // re-generated to prevent mysterious component loading failures.
3046 RemoveComponentRegistries(profD
, profLD
, PR_FALSE
);
3047 WriteVersion(profD
, NS_LITERAL_CSTRING("Safe Mode"), osABI
,
3048 dirProvider
.GetGREDir(), gAppData
->directory
);
3050 else if (versionOK
) {
3051 if (ComponentsListChanged(profD
)) {
3052 // Remove compreg.dat and xpti.dat, forcing component re-registration.
3053 // The new list of additional components directories is derived from
3054 // information in "extensions.ini".
3055 RemoveComponentRegistries(profD
, profLD
, PR_FALSE
);
3057 // Nothing need be done for the normal startup case.
3060 // Remove compreg.dat and xpti.dat, forcing component re-registration
3061 // with the default set of components (this disables any potentially
3062 // troublesome incompatible XPCOM components).
3063 RemoveComponentRegistries(profD
, profLD
, PR_TRUE
);
3065 // Tell the Extension Manager it should check for incompatible
3066 // Extensions and re-write the "extensions.ini" file with a list of
3067 // directories for compatible extensions
3070 // Write out version
3071 WriteVersion(profD
, version
, osABI
,
3072 dirProvider
.GetGREDir(), gAppData
->directory
);
3075 PRBool needsRestart
= PR_FALSE
;
3076 PRBool appInitiatedRestart
= PR_FALSE
;
3078 // Allows the user to forcefully bypass the restart process at their
3079 // own risk. Useful for debugging or for tinderboxes where child
3080 // processes can be problematic.
3082 // Start the real application
3083 ScopedXPCOMStartup xpcom
;
3084 rv
= xpcom
.Initialize();
3085 NS_ENSURE_SUCCESS(rv
, 1);
3086 rv
= xpcom
.DoAutoreg();
3087 rv
|= xpcom
.RegisterProfileService();
3088 rv
|= xpcom
.SetWindowCreator(nativeApp
);
3089 NS_ENSURE_SUCCESS(rv
, 1);
3093 nsCOMPtr
<nsIIOService2
> io (do_GetService("@mozilla.org/network/io-service;1"));
3094 NS_ENSURE_TRUE(io
, 1);
3095 io
->SetManageOfflineStatus(PR_FALSE
);
3096 io
->SetOffline(PR_TRUE
);
3100 NS_TIMELINE_ENTER("startupNotifier");
3101 nsCOMPtr
<nsIObserver
> startupNotifier
3102 (do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID
, &rv
));
3103 NS_ENSURE_SUCCESS(rv
, 1);
3105 startupNotifier
->Observe(nsnull
, APPSTARTUP_TOPIC
, nsnull
);
3106 NS_TIMELINE_LEAVE("startupNotifier");
3109 nsCOMPtr
<nsIAppStartup
> appStartup
3110 (do_GetService(NS_APPSTARTUP_CONTRACTID
));
3111 NS_ENSURE_TRUE(appStartup
, 1);
3114 nsCOMPtr
<nsIFile
> file
;
3115 dirProvider
.GetAppDir()->Clone(getter_AddRefs(file
));
3116 file
->AppendNative(NS_LITERAL_CSTRING("override.ini"));
3118 nsCOMPtr
<nsILocalFile
> localFile(do_QueryInterface(file
));
3119 nsresult rv
= parser
.Init(localFile
);
3120 if (NS_SUCCEEDED(rv
)) {
3122 rv
= parser
.GetString("XRE", "EnableProfileMigrator", buf
);
3123 if (NS_SUCCEEDED(rv
)) {
3124 if (buf
[0] == '0' || buf
[0] == 'f' || buf
[0] == 'F') {
3125 gDoMigration
= PR_FALSE
;
3131 // Profile Migration
3132 if (gAppData
->flags
& NS_XRE_ENABLE_PROFILE_MIGRATOR
&& gDoMigration
) {
3133 gDoMigration
= PR_FALSE
;
3134 nsCOMPtr
<nsIProfileMigrator
> pm
3135 (do_CreateInstance(NS_PROFILEMIGRATOR_CONTRACTID
));
3137 pm
->Migrate(&dirProvider
);
3139 dirProvider
.DoStartup();
3141 nsCOMPtr
<nsICommandLineRunner
> cmdLine
3142 (do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
3143 NS_ENSURE_TRUE(cmdLine
, 1);
3145 nsCOMPtr
<nsIFile
> workingDir
;
3146 rv
= NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR
, getter_AddRefs(workingDir
));
3147 NS_ENSURE_SUCCESS(rv
, 1);
3149 rv
= cmdLine
->Init(gArgc
, gArgv
,
3150 workingDir
, nsICommandLine::STATE_INITIAL_LAUNCH
);
3151 NS_ENSURE_SUCCESS(rv
, 1);
3153 /* Special-case services that need early access to the command
3155 nsCOMPtr
<nsIObserver
> chromeObserver
3156 (do_GetService("@mozilla.org/chrome/chrome-registry;1"));
3157 if (chromeObserver
) {
3158 chromeObserver
->Observe(cmdLine
, "command-line-startup", nsnull
);
3161 NS_TIMELINE_ENTER("appStartup->CreateHiddenWindow");
3162 rv
= appStartup
->CreateHiddenWindow();
3163 NS_TIMELINE_LEAVE("appStartup->CreateHiddenWindow");
3164 NS_ENSURE_SUCCESS(rv
, 1);
3166 #if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK2)
3167 nsRefPtr
<nsGTKToolkit
> toolkit
= GetGTKToolkit();
3168 if (toolkit
&& !desktopStartupID
.IsEmpty()) {
3169 toolkit
->SetDesktopStartupID(desktopStartupID
);
3173 // Extension Compatibility Checking and Startup
3174 if (gAppData
->flags
& NS_XRE_ENABLE_EXTENSION_MANAGER
) {
3175 nsCOMPtr
<nsIExtensionManager
> em(do_GetService("@mozilla.org/extensions/manager;1"));
3176 NS_ENSURE_TRUE(em
, 1);
3178 ar
= CheckArg("install-global-extension", PR_TRUE
);
3179 if (ar
== ARG_BAD
) {
3180 PR_fprintf(PR_STDERR
, "Error: argument -install-global-extension is invalid when argument -osint is specified\n");
3182 } else if (ar
== ARG_FOUND
) {
3183 // Do the required processing and then shut down.
3184 em
->HandleCommandLineArgs(cmdLine
);
3188 ar
= CheckArg("install-global-theme", PR_TRUE
);
3189 if (ar
== ARG_BAD
) {
3190 PR_fprintf(PR_STDERR
, "Error: argument -install-global-theme is invalid when argument -osint is specified\n");
3192 } else if (ar
== ARG_FOUND
) {
3193 // Do the required processing and then shut down.
3194 em
->HandleCommandLineArgs(cmdLine
);
3199 rv
= em
->CheckForMismatches(&needsRestart
);
3200 if (NS_FAILED(rv
)) {
3201 needsRestart
= PR_FALSE
;
3202 upgraded
= PR_FALSE
;
3206 if (!upgraded
|| !needsRestart
)
3207 em
->Start(cmdLine
, &needsRestart
);
3210 // We want to restart no more than 2 times. The first restart,
3211 // NO_EM_RESTART == "0" , and the second time, "1".
3212 char* noEMRestart
= PR_GetEnv("NO_EM_RESTART");
3213 if (noEMRestart
&& *noEMRestart
&& *noEMRestart
== '1') {
3214 if (upgraded
|| needsRestart
) {
3215 NS_WARNING("EM tried to force us to restart twice! Forcefully preventing that.");
3217 needsRestart
= upgraded
= PR_FALSE
;
3220 if (!upgraded
&& !needsRestart
) {
3221 SaveStateForAppInitiatedRestart();
3223 // clear out any environment variables which may have been set
3224 // during the relaunch process now that we know we won't be relaunching.
3225 PR_SetEnv("XRE_PROFILE_PATH=");
3226 PR_SetEnv("XRE_PROFILE_LOCAL_PATH=");
3227 PR_SetEnv("XRE_PROFILE_NAME=");
3228 PR_SetEnv("XRE_START_OFFLINE=");
3229 PR_SetEnv("XRE_IMPORT_PROFILES=");
3230 PR_SetEnv("NO_EM_RESTART=");
3231 PR_SetEnv("XUL_APP_FILE=");
3232 PR_SetEnv("XRE_BINARY_PATH=");
3235 // we re-initialize the command-line service and do appleevents munging
3236 // after we are sure that we're not restarting
3237 cmdLine
= do_CreateInstance("@mozilla.org/toolkit/command-line;1");
3238 NS_ENSURE_TRUE(cmdLine
, 1);
3240 SetupMacCommandLine(gArgc
, gArgv
);
3242 rv
= cmdLine
->Init(gArgc
, gArgv
,
3243 workingDir
, nsICommandLine::STATE_INITIAL_LAUNCH
);
3244 NS_ENSURE_SUCCESS(rv
, 1);
3246 #ifdef MOZ_WIDGET_COCOA
3247 // Prepare Cocoa's form of Apple Event handling.
3248 SetupMacApplicationDelegate();
3250 nsCOMPtr
<nsIObserverService
> obsService
3251 (do_GetService("@mozilla.org/observer-service;1"));
3253 obsService
->NotifyObservers(nsnull
, "final-ui-startup", nsnull
);
3255 rv
= cmdLine
->Run();
3256 NS_ENSURE_SUCCESS_LOG(rv
, 1);
3258 #ifdef MOZ_ENABLE_XREMOTE
3259 // if we have X remote support, start listening for requests on the
3261 nsCOMPtr
<nsIRemoteService
> remoteService
;
3262 remoteService
= do_GetService("@mozilla.org/toolkit/remote-service;1");
3264 remoteService
->Startup(gAppData
->name
,
3265 PromiseFlatCString(profileName
).get());
3266 #endif /* MOZ_ENABLE_XREMOTE */
3268 // enable win32 DDE responses and Mac appleevents responses
3269 nativeApp
->Enable();
3271 NS_TIMELINE_ENTER("appStartup->Run");
3272 rv
= appStartup
->Run();
3273 NS_TIMELINE_LEAVE("appStartup->Run");
3274 if (NS_FAILED(rv
)) {
3275 NS_ERROR("failed to run appstartup");
3276 gLogConsoleErrors
= PR_TRUE
;
3279 // Check for an application initiated restart. This is one that
3280 // corresponds to nsIAppStartup.quit(eRestart)
3281 if (rv
== NS_SUCCESS_RESTART_APP
) {
3282 needsRestart
= PR_TRUE
;
3283 appInitiatedRestart
= PR_TRUE
;
3286 #ifdef MOZ_ENABLE_XREMOTE
3287 // shut down the x remote proxy window
3289 remoteService
->Shutdown();
3290 #endif /* MOZ_ENABLE_XREMOTE */
3293 // Make sure we print this out even if timeline is runtime disabled
3294 if (NS_FAILED(NS_TIMELINE_LEAVE("main1")))
3295 NS_TimelineForceMark("...main1");
3299 // Upgrade condition (build id changes), but the restart hint was
3300 // not set by the Extension Manager. This is because the compatibility
3301 // resolution for Extensions is different than for the component
3302 // registry - major milestone vs. build id.
3303 needsRestart
= PR_TRUE
;
3306 ProcessDDE(nativeApp
, PR_TRUE
);
3310 SetupMacCommandLine(gRestartArgc
, gRestartArgv
);
3316 // unlock the profile after ScopedXPCOMStartup object (xpcom)
3317 // has gone out of scope. see bug #386739 for more details
3318 profileLock
->Unlock();
3320 // Restart the app after XPCOM has been shut down cleanly.
3322 if (appInitiatedRestart
) {
3323 RestoreStateForAppInitiatedRestart();
3326 char* noEMRestart
= PR_GetEnv("NO_EM_RESTART");
3327 if (noEMRestart
&& *noEMRestart
) {
3328 PR_SetEnv("NO_EM_RESTART=1");
3331 PR_SetEnv("NO_EM_RESTART=0");
3335 // Ensure that these environment variables are set:
3336 SaveFileToEnvIfUnset("XRE_PROFILE_PATH", profD
);
3337 SaveFileToEnvIfUnset("XRE_PROFILE_LOCAL_PATH", profLD
);
3338 SaveWordToEnvIfUnset("XRE_PROFILE_NAME", profileName
);
3342 static char kEnvVar
[MAXPATHLEN
];
3343 sprintf(kEnvVar
, "XRE_BINARY_PATH=%s", gBinaryPath
);
3348 // XXXkt s/MOZ_TOOLKIT_GTK2/MOZ_WIDGET_GTK2/?
3349 // but the hidden window has been destroyed so toolkit is NULL anyway.
3350 #if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_TOOLKIT_GTK2)
3351 nsGTKToolkit
* toolkit
= GetGTKToolkit();
3353 nsCAutoString currentDesktopStartupID
;
3354 toolkit
->GetDesktopStartupID(¤tDesktopStartupID
);
3355 if (!currentDesktopStartupID
.IsEmpty()) {
3356 nsCAutoString desktopStartupEnv
;
3357 desktopStartupEnv
.AssignLiteral("DESKTOP_STARTUP_ID=");
3358 desktopStartupEnv
.Append(currentDesktopStartupID
);
3359 // Leak it with extreme prejudice!
3360 PR_SetEnv(ToNewCString(desktopStartupEnv
));
3365 #ifdef MOZ_WIDGET_GTK2
3366 MOZ_gdk_display_close(display
);
3369 rv
= LaunchChild(nativeApp
, appInitiatedRestart
);
3371 #ifdef MOZ_CRASHREPORTER
3372 if (appData
.flags
& NS_XRE_ENABLE_CRASH_REPORTER
)
3373 CrashReporter::UnsetExceptionHandler();
3376 return rv
== NS_ERROR_LAUNCHED_CHILD_PROCESS
? 0 : 1;
3379 #ifdef MOZ_WIDGET_GTK2
3380 // gdk_display_close also calls gdk_display_manager_set_default_display
3381 // appropriately when necessary.
3382 MOZ_gdk_display_close(display
);
3386 #ifdef MOZ_CRASHREPORTER
3387 if (appData
.flags
& NS_XRE_ENABLE_CRASH_REPORTER
)
3388 CrashReporter::UnsetExceptionHandler();
3391 return NS_FAILED(rv
) ? 1 : 0;