/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Roland Mainz * Fredrik Holmqvist * Masayuki Nakano * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #ifdef XPCOM_GLUE #include "nsXPCOMGlue.h" #endif #include "nsStringSupport.h" #include "nsXPCOM.h" #include "nsIServiceManager.h" #include "nsServiceManagerUtils.h" #include "nsIComponentManager.h" #include "nsComponentManagerUtils.h" #include "nsIGenericFactory.h" #include "nsIComponentRegistrar.h" #include "nsStaticComponents.h" #ifdef XP_OS2 #include "private/pprthred.h" #endif #include "nsIPrefService.h" #include "nsIPrefBranch.h" #include "nsILocaleService.h" #include "plevent.h" #include "prmem.h" #include "prenv.h" #include "prnetdb.h" #include "nsCOMPtr.h" #include "nsIAppShell.h" #include "nsICmdLineService.h" #include "nsIAppShellService.h" #include "nsIAppStartupNotifier.h" #include "nsIAppStartup.h" #include "nsIObserverService.h" #include "prprf.h" #include "nsCRT.h" #include "nsIDirectoryService.h" #include "nsDirectoryServiceUtils.h" #include "nsAppDirectoryServiceDefs.h" #include "nsIWindowMediator.h" #include "nsIDOMWindowInternal.h" #include "nsISupportsPrimitives.h" #include "nsICmdLineHandler.h" #include "nsICategoryManager.h" #include "nsIXULWindow.h" #include "nsIChromeRegistrySea.h" #include "nsIEventQueueService.h" #include "nsDirectoryServiceDefs.h" #include "nsBuildID.h" #include "nsIWindowCreator.h" #include "nsIWindowWatcher.h" #include "nsILocalFile.h" #include "nsILookAndFeel.h" #include "nsIProcess.h" #include "nsIIOService.h" #include "nsIJARURI.h" #include "nsNetCID.h" #ifdef MOZ_XPINSTALL #include "InstallCleanupDefines.h" #include "nsISoftwareUpdate.h" #endif // Interfaces Needed #include "nsIXULWindow.h" #include "nsIWebBrowserChrome.h" #include "nsIDocShell.h" // for X remote support #ifdef MOZ_ENABLE_XREMOTE #ifdef MOZ_WIDGET_PHOTON #include "PhRemoteClient.h" #else #include "XRemoteClient.h" #endif #include "nsIRemoteService.h" #endif // see DoOnShutdown() #include "nsIProfile.h" #ifdef NS_TRACE_MALLOC #include "nsTraceMalloc.h" #endif #ifdef XP_WIN32 #include #ifdef DEBUG #include #endif #endif #if defined (XP_MACOSX) #include #endif #include "nsITimelineService.h" #if defined(DEBUG_pra) #define DEBUG_CMD_LINE #endif #include "nsWidgetsCID.h" #include "nsXPFEComponentsCID.h" static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID); #define UILOCALE_CMD_LINE_ARG "-UILocale" #define CONTENTLOCALE_CMD_LINE_ARG "-contentLocale" extern "C" void ShowOSAlert(const char* aMessage); #define HELP_SPACER_1 "\t" #define HELP_SPACER_2 "\t\t" #define HELP_SPACER_4 "\t\t\t\t" #ifdef DEBUG #include "prlog.h" #endif #ifdef MOZ_JPROF #include "jprof.h" #endif // on x86 linux, the current builds of some popular plugins (notably // flashplayer and real) expect a few builtin symbols from libgcc // which were available in some older versions of gcc. However, // they're _NOT_ available in newer versions of gcc (eg 3.1), so if // we want those plugin to work with a gcc-3.1 built binary, we need // to provide these symbols. MOZ_ENABLE_OLD_ABI_COMPAT_WRAPPERS defaults // to true on x86 linux, and false everywhere else. // // The fact that the new and free operators are mismatched // mirrors the way the original functions in egcs 1.1.2 worked. #ifdef MOZ_ENABLE_OLD_ABI_COMPAT_WRAPPERS extern "C" { # ifndef HAVE___BUILTIN_VEC_NEW void *__builtin_vec_new(size_t aSize, const std::nothrow_t &aNoThrow) throw() { return ::operator new(aSize, aNoThrow); } # endif # ifndef HAVE___BUILTIN_VEC_DELETE void __builtin_vec_delete(void *aPtr, const std::nothrow_t &) throw () { if (aPtr) { free(aPtr); } } # endif # ifndef HAVE___BUILTIN_NEW void *__builtin_new(int aSize) { return malloc(aSize); } # endif # ifndef HAVE___BUILTIN_DELETE void __builtin_delete(void *aPtr) { free(aPtr); } # endif # ifndef HAVE___PURE_VIRTUAL void __pure_virtual(void) { #ifdef WRAP_SYSTEM_INCLUDES #pragma GCC visibility push(default) #endif extern void __cxa_pure_virtual(void); #ifdef WRAP_SYSTEM_INCLUDES #pragma GCC visibility pop #endif __cxa_pure_virtual(); } # endif } #endif #ifndef _BUILD_STATIC_BIN nsStaticModuleInfo const *const kPStaticModules = nsnull; PRUint32 const kStaticModuleCount = 0; #endif #if defined(XP_UNIX) || defined(XP_BEOS) extern void InstallUnixSignalHandlers(const char *ProgramName); #endif #if defined(XP_OS2) /* Adding globals that OS/2 doesn't have so we can port the DDE code */ char **__argv; int *__pargc; #endif /* XP_OS2 */ #if defined(XP_MAC) #include "macstdlibextras.h" #include // Set up the toolbox and (if DEBUG) the console. Do this in a static initializer, // to make it as unlikely as possible that somebody calls printf() before we get initialized. static struct MacInitializer { MacInitializer() { InitializeMacToolbox(); } } gInitializer; // Initialize profile services for both standalone and regular profiles static nsresult InitializeProfileService(nsICmdLineService *cmdLineArgs); // Install global locale if possible static nsresult InstallGlobalLocale(nsICmdLineService *cmdLineArgs); static nsresult getUILangCountry(nsAString& aUILang, nsAString& aCountry); class stTSMCloser { public: stTSMCloser() { // TSM is initialized in InitializeMacToolbox }; ~stTSMCloser() { #if !TARGET_CARBON (void)CloseTSMAwareApplication(); #endif } }; #endif // XP_MAC #if defined(XP_MACOSX) static void InitializeMacOSXApp(int argc, char* argv[]) { // use the location of the executable to learn where everything is, this // is because the current working directory is ill-defined when the // application is double-clicked from the Finder. char* path = strdup(argv[0]); char* lastSlash = strrchr(path, '/'); if (lastSlash) { *lastSlash = '\0'; setenv("MOZILLA_FIVE_HOME", path, 1); } free(path); } #endif /* XP_MACOSX */ #if defined(MOZ_WIDGET_QT) #include #endif #ifdef MOZ_X11 #include #endif /* MOZ_X11 */ #if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_GTK2) #include #endif //MOZ_WIDGET_GTK || MOZ_WIDGET_GTK2 #include "nsNativeAppSupport.h" /*********************************************/ // Default implemenations for nativeAppSupport // If your platform implements these functions if def out this code. #if !defined(MOZ_WIDGET_COCOA) && !defined(MOZ_WIDGET_PHOTON) && !defined( XP_WIN) && !defined(XP_OS2) && !defined(MOZ_WIDGET_GTK) && !defined(MOZ_WIDGET_GTK2) nsresult NS_CreateSplashScreen(nsISplashScreen **aResult) { nsresult rv = NS_OK; if (aResult) { *aResult = 0; } else { rv = NS_ERROR_NULL_POINTER; } return rv; } PRBool NS_CanRun() { return PR_TRUE; } #endif /*********************************************/ // Default implementation for new and improved // native app support. If your platform // implements nsINativeAppSupport then implement // this function and if def out this code. // // Note: For now, the default imiplementation returns 0 and // the code that calls this will defalt to use the old // nsISplashScreen interface directly. At some point // this function will return an instance of // nsNativeAppSupportBase which will use the older // "splash screen" interface. The code below will // then rely on nsINativeAppSupport and its use of // nsISplashScreen will be removed. // #if !defined(XP_WIN) && !defined(XP_OS2)&& !defined( XP_BEOS ) && !defined(MOZ_WIDGET_GTK) && !defined(MOZ_WIDGET_GTK2) && !defined(XP_MAC) && (!defined(XP_MACOSX) || defined(MOZ_WIDGET_COCOA)) nsresult NS_CreateNativeAppSupport(nsINativeAppSupport **aResult) { nsresult rv = NS_OK; if (aResult) { *aResult = 0; } else { rv = NS_ERROR_NULL_POINTER; } return rv; } #endif static nsresult GetNativeAppSupport(nsINativeAppSupport** aNativeApp) { NS_ENSURE_ARG_POINTER(aNativeApp); *aNativeApp = nsnull; nsCOMPtr appStartup(do_GetService(NS_APPSTARTUP_CONTRACTID)); if (appStartup) appStartup->GetNativeAppSupport(aNativeApp); return *aNativeApp ? NS_OK : NS_ERROR_FAILURE; } /* * This routine translates the nsresult into a platform specific return * code for the application... */ static int TranslateReturnValue(nsresult aResult) { if (NS_SUCCEEDED(aResult)) { return 0; } return 1; } #ifdef XP_MAC #include "nsCommandLineServiceMac.h" #endif static void PrintUsage(void) { fprintf(stderr, "Usage: apprunner \n"); fprintf(stderr, "\t: a fully defined url string like http:// etc..\n"); } static nsresult OpenWindow(const nsCString& aChromeURL, const nsString& aAppArgs, PRInt32 aWidth, PRInt32 aHeight); static nsresult OpenWindow(const nsCString& aChromeURL, const nsString& aAppArgs) { return OpenWindow(aChromeURL, aAppArgs, nsIAppShellService::SIZE_TO_CONTENT, nsIAppShellService::SIZE_TO_CONTENT); } static nsresult OpenWindow(const nsCString& aChromeURL, PRInt32 aWidth, PRInt32 aHeight) { return OpenWindow(aChromeURL, EmptyString(), aWidth, aHeight); } static nsresult OpenWindow(const nsCString& aChromeURL, const nsString& aAppArgs, PRInt32 aWidth, PRInt32 aHeight) { #ifdef DEBUG_CMD_LINE printf("OpenWindow(%s, %s, %d, %d)\n", aChromeURL.get(), NS_ConvertUCS2toUTF8(aAppArgs).get(), aWidth, aHeight); #endif /* DEBUG_CMD_LINE */ nsCOMPtr wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID)); nsCOMPtr sarg(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID)); if (!wwatch || !sarg) return NS_ERROR_FAILURE; // Make sure a profile is selected. // We need the native app support object, which we get from // the app shell service. If this fails, we still proceed. // That's because some platforms don't have a native app // support implementation. On those platforms, "ensuring a // profile" is moot (because they don't support "-turbo", // basically). Specifically, because they don't do turbo, they will // *always* have a profile selected. nsCOMPtr appStartup(do_GetService(NS_APPSTARTUP_CONTRACTID)); nsCOMPtr cmdLine(do_GetService(NS_COMMANDLINESERVICE_CONTRACTID)); if (appStartup && cmdLine) { nsCOMPtr nativeApp; if (NS_SUCCEEDED(appStartup->GetNativeAppSupport(getter_AddRefs(nativeApp)))) { // Make sure profile has been selected. // At this point, we have to look for failure. That // handles the case where the user chooses "Exit" on // the profile manager window. if (NS_FAILED(nativeApp->EnsureProfile(cmdLine))) return NS_ERROR_NOT_INITIALIZED; } } sarg->SetData(aAppArgs); nsCAutoString features("chrome,dialog=no,all"); if (aHeight != nsIAppShellService::SIZE_TO_CONTENT) { features.Append(",height="); AppendIntToString(features, aHeight); } if (aWidth != nsIAppShellService::SIZE_TO_CONTENT) { features.Append(",width="); AppendIntToString(features, aWidth); } #ifdef DEBUG_CMD_LINE printf("features: %s...\n", features.get()); #endif /* DEBUG_CMD_LINE */ nsCOMPtr newWindow; return wwatch->OpenWindow(0, aChromeURL.get(), "_blank", features.get(), sarg, getter_AddRefs(newWindow)); } static void DumpArbitraryHelp() { nsresult rv; nsCOMPtr catman(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv)); if(NS_SUCCEEDED(rv) && catman) { nsCOMPtr e; rv = catman->EnumerateCategory(COMMAND_LINE_ARGUMENT_HANDLERS, getter_AddRefs(e)); if(NS_SUCCEEDED(rv) && e) { while (PR_TRUE) { nsCOMPtr catEntry; rv = e->GetNext(getter_AddRefs(catEntry)); if (NS_FAILED(rv) || !catEntry) break; nsCAutoString entryString; rv = catEntry->GetData(entryString); if (NS_FAILED(rv) || entryString.IsEmpty()) break; nsXPIDLCString contractidString; rv = catman->GetCategoryEntry(COMMAND_LINE_ARGUMENT_HANDLERS, entryString.get(), getter_Copies(contractidString)); if (NS_FAILED(rv) || contractidString.IsEmpty()) break; #ifdef DEBUG_CMD_LINE printf("cmd line handler contractid = %s\n", contractidString.get()); #endif /* DEBUG_CMD_LINE */ nsCOMPtr handler(do_GetService(contractidString.get(), &rv)); if (handler) { nsXPIDLCString commandLineArg; rv = handler->GetCommandLineArgument(getter_Copies(commandLineArg)); if (NS_FAILED(rv)) continue; nsXPIDLCString helpText; rv = handler->GetHelpText(getter_Copies(helpText)); if (NS_FAILED(rv)) continue; if (!commandLineArg.IsEmpty()) { printf("%s%s", HELP_SPACER_1, commandLineArg.get()); PRBool handlesArgs = PR_FALSE; rv = handler->GetHandlesArgs(&handlesArgs); if (NS_SUCCEEDED(rv) && handlesArgs) { printf(" "); } if (!helpText.IsEmpty()) { printf("%s%s\n", HELP_SPACER_2, helpText.get()); } } } } } } return; } static nsresult LaunchApplicationWithArgs(const char *commandLineArg, nsICmdLineService *cmdLineArgs, const char *aParam, PRInt32 height, PRInt32 width, PRBool *windowOpened) { NS_ENSURE_ARG(commandLineArg); NS_ENSURE_ARG(cmdLineArgs); NS_ENSURE_ARG(aParam); NS_ENSURE_ARG(windowOpened); nsresult rv; nsCOMPtr handler; rv = cmdLineArgs->GetHandlerForParam(aParam, getter_AddRefs(handler)); if (NS_FAILED(rv)) return rv; if (!handler) return NS_ERROR_FAILURE; nsXPIDLCString chromeUrlForTask; rv = handler->GetChromeUrlForTask(getter_Copies(chromeUrlForTask)); if (NS_FAILED(rv)) return rv; #ifdef DEBUG_CMD_LINE printf("XXX got this one:\t%s\n\t%s\n\n",commandLineArg,chromeUrlForTask.get()); #endif /* DEBUG_CMD_LINE */ nsXPIDLCString cmdResult; rv = cmdLineArgs->GetCmdLineValue(commandLineArg, getter_Copies(cmdResult)); if (NS_FAILED(rv)) return rv; #ifdef DEBUG_CMD_LINE printf("%s, cmdResult = %s\n",commandLineArg,cmdResult.get()); #endif /* DEBUG_CMD_LINE */ PRBool handlesArgs = PR_FALSE; rv = handler->GetHandlesArgs(&handlesArgs); if (handlesArgs) { if (!cmdResult.IsEmpty()) { if (strcmp("1", cmdResult.get())) { PRBool openWindowWithArgs = PR_TRUE; rv = handler->GetOpenWindowWithArgs(&openWindowWithArgs); if (NS_FAILED(rv)) return rv; if (openWindowWithArgs) { nsAutoString cmdArgs; NS_CopyNativeToUnicode(cmdResult, cmdArgs); #ifdef DEBUG_CMD_LINE printf("opening %s with %s\n", chromeUrlForTask.get(), "OpenWindow"); #endif /* DEBUG_CMD_LINE */ rv = OpenWindow(chromeUrlForTask, cmdArgs); } else { // We need to emulate checkLoadURI because we don't have a window yet nsCOMPtr ioService = do_GetService(NS_IOSERVICE_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; nsCOMPtr baseURI; rv = ioService->NewURI(cmdResult, nsnull, nsnull, getter_AddRefs(baseURI)); if (NS_FAILED(rv)) return rv; nsCOMPtr jarURI(do_QueryInterface(baseURI)); while (jarURI) { rv = jarURI->GetJARFile(getter_AddRefs(baseURI)); if (NS_FAILED(rv)) return rv; jarURI = do_QueryInterface(baseURI); } PRBool scriptOrData = PR_FALSE; baseURI->SchemeIs("javascript", &scriptOrData); if (!scriptOrData) baseURI->SchemeIs("data", &scriptOrData); if (scriptOrData) return NS_ERROR_FAILURE; #ifdef DEBUG_CMD_LINE printf("opening %s with %s\n", cmdResult.get(), "OpenWindow"); #endif /* DEBUG_CMD_LINE */ rv = OpenWindow(cmdResult, width, height); if (NS_FAILED(rv)) return rv; } // If we get here without an error, then a window was opened OK. if (NS_SUCCEEDED(rv)) { *windowOpened = PR_TRUE; } } else { nsXPIDLString defaultArgs; rv = handler->GetDefaultArgs(getter_Copies(defaultArgs)); if (NS_FAILED(rv)) return rv; rv = OpenWindow(chromeUrlForTask, defaultArgs); if (NS_FAILED(rv)) return rv; // Window was opened OK. *windowOpened = PR_TRUE; } } } else { if (NS_SUCCEEDED(rv) && !cmdResult.IsEmpty()) { if (strcmp("1", cmdResult.get()) == 0) { rv = OpenWindow(chromeUrlForTask, width, height); if (NS_FAILED(rv)) return rv; } else { rv = OpenWindow(cmdResult, width, height); if (NS_FAILED(rv)) return rv; } // If we get here without an error, then a window was opened OK. if (NS_SUCCEEDED(rv)) { *windowOpened = PR_TRUE; } } } return NS_OK; } static PRBool IsStartupCommand(const char *arg) { if (!arg) return PR_FALSE; if (PL_strlen(arg) <= 1) return PR_FALSE; // windows allows /mail or -mail if ((arg[0] == '-') #if defined(XP_WIN) || defined(XP_OS2) || (arg[0] == '/') #endif /* XP_WIN || XP_OS2 */ ) { return PR_TRUE; } return PR_FALSE; } // This should be done by app shell enumeration someday nsresult DoCommandLines(nsICmdLineService* cmdLineArgs, PRBool *windowOpened) { NS_ENSURE_ARG(windowOpened); *windowOpened = PR_FALSE; nsresult rv; PRInt32 height = nsIAppShellService::SIZE_TO_CONTENT; PRInt32 width = nsIAppShellService::SIZE_TO_CONTENT; nsXPIDLCString tempString; // Get the value of -width option rv = cmdLineArgs->GetCmdLineValue("-width", getter_Copies(tempString)); if (NS_SUCCEEDED(rv) && !tempString.IsEmpty()) PR_sscanf(tempString.get(), "%d", &width); // Get the value of -height option rv = cmdLineArgs->GetCmdLineValue("-height", getter_Copies(tempString)); if (NS_SUCCEEDED(rv) && !tempString.IsEmpty()) PR_sscanf(tempString.get(), "%d", &height); PRInt32 argc = 0; rv = cmdLineArgs->GetArgc(&argc); if (NS_FAILED(rv)) return rv; char **argv = nsnull; rv = cmdLineArgs->GetArgv(&argv); if (NS_FAILED(rv)) return rv; // first apply command line args // if there is any window opened, startup preferences are ignored PRInt32 i = 0; for (i=1;iGetURLToLoad(getter_Copies(urlToLoad)); if (NS_SUCCEEDED(rv) && !urlToLoad.IsEmpty()) { nsCOMPtr handler( do_GetService("@mozilla.org/commandlinehandler/general-startup;1?type=browser")); nsXPIDLCString chromeUrlForTask; rv = handler->GetChromeUrlForTask(getter_Copies(chromeUrlForTask)); if (NS_SUCCEEDED(rv)) { // convert the cmdLine URL to Unicode nsAutoString url; NS_CopyNativeToUnicode(urlToLoad, url); rv = OpenWindow(chromeUrlForTask, url, width, height); } if (NS_SUCCEEDED(rv)) { *windowOpened = PR_TRUE; } } // third if no window is opened then apply the startup preferences if (!*windowOpened) { nsCOMPtr appStartup(do_GetService(NS_APPSTARTUP_CONTRACTID, &rv)); if (NS_FAILED(rv)) return rv; rv = appStartup->CreateStartupState(width, height, windowOpened); if (NS_FAILED(rv)) return rv; } return NS_OK; } static nsresult DoOnShutdown() { nsresult rv; // save the prefs, in case they weren't saved { // scoping this in a block to force release nsCOMPtr prefs(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv)); NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get prefs, so unable to save them"); if (NS_SUCCEEDED(rv)) prefs->SavePrefFile(nsnull); } // call ShutDownCurrentProfile() so we update the last modified time of the profile { // scoping this in a block to force release nsCOMPtr profileMgr(do_GetService(NS_PROFILE_CONTRACTID, &rv)); NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get profile manager, so unable to update last modified time"); if (NS_SUCCEEDED(rv)) { profileMgr->ShutDownCurrentProfile(nsIProfile::SHUTDOWN_PERSIST); } } return rv; } // match OS locale static char kMatchOSLocalePref[] = "intl.locale.matchOS"; nsresult getCountry(const nsAString& lc_name, nsAString& aCountry) { #ifndef MOZILLA_INTERNAL_API const PRUnichar *begin = lc_name.BeginReading(); const PRUnichar *end = lc_name.EndReading(); while (begin != end) { if (*begin == '-') break; ++begin; } if (begin == end) return NS_ERROR_FAILURE; aCountry.Assign(begin + 1, end - begin); #else PRInt32 i = lc_name.FindChar('-'); if (i == kNotFound) return NS_ERROR_FAILURE; aCountry = Substring(lc_name, i + 1, PR_UINT32_MAX); #endif return NS_OK; } static nsresult getUILangCountry(nsAString& aUILang, nsAString& aCountry) { nsresult result; // get a locale service nsCOMPtr localeService = do_GetService(NS_LOCALESERVICE_CONTRACTID, &result); NS_ASSERTION(NS_SUCCEEDED(result),"getUILangCountry: get locale service failed"); result = localeService->GetLocaleComponentForUserAgent(aUILang); NS_ASSERTION(NS_SUCCEEDED(result), "getUILangCountry: get locale component failed"); result = getCountry(aUILang, aCountry); return result; } // update global locale if possible (in case when user-*.rdf can be updated) // so that any apps after this can be invoked in the UILocale and contentLocale static nsresult InstallGlobalLocale(nsICmdLineService *cmdLineArgs) { nsresult rv = NS_OK; // check the pref first nsCOMPtr prefService(do_GetService(NS_PREFSERVICE_CONTRACTID)); PRBool matchOS = PR_FALSE; if (prefService) prefService->GetBoolPref(kMatchOSLocalePref, &matchOS); // match os locale nsAutoString uiLang; nsAutoString country; if (matchOS) { // compute lang and region code only when needed! rv = getUILangCountry(uiLang, country); } nsXPIDLCString cmdUI; rv = cmdLineArgs->GetCmdLineValue(UILOCALE_CMD_LINE_ARG, getter_Copies(cmdUI)); if (NS_SUCCEEDED(rv)){ if (!cmdUI.IsEmpty()) { nsCOMPtr chromeRegistry = do_GetService(NS_CHROMEREGISTRY_CONTRACTID, &rv); if (chromeRegistry) rv = chromeRegistry->SelectLocale(cmdUI, PR_FALSE); } } // match OS when no cmdline override if (cmdUI.IsEmpty() && matchOS) { nsCOMPtr chromeRegistry = do_GetService(NS_CHROMEREGISTRY_CONTRACTID, &rv); if (chromeRegistry) { chromeRegistry->SetRuntimeProvider(PR_TRUE); rv = chromeRegistry->SelectLocale(NS_ConvertUTF16toUTF8(uiLang), PR_FALSE); } } nsXPIDLCString cmdContent; rv = cmdLineArgs->GetCmdLineValue(CONTENTLOCALE_CMD_LINE_ARG, getter_Copies(cmdContent)); if (NS_SUCCEEDED(rv)){ if (!cmdContent.IsEmpty()) { nsCOMPtr chromeRegistry = do_GetService(NS_CHROMEREGISTRY_CONTRACTID, &rv); if(chromeRegistry) rv = chromeRegistry->SelectLocale(cmdContent, PR_FALSE); } } // match OS when no cmdline override if (cmdContent.IsEmpty() && matchOS) { nsCOMPtr chromeRegistry = do_GetService(NS_CHROMEREGISTRY_CONTRACTID, &rv); if (chromeRegistry) { chromeRegistry->SetRuntimeProvider(PR_TRUE); rv = chromeRegistry->SelectLocale(NS_ConvertUTF16toUTF8(country), PR_FALSE); } } return NS_OK; } // Use classic skin if OS has indicated that the // current theme is being used for accessibility. static void CheckUseAccessibleSkin() { PRInt32 useAccessibilityTheme = 0; nsCOMPtr lookAndFeel = do_GetService(kLookAndFeelCID); if (lookAndFeel) { lookAndFeel->GetMetric(nsILookAndFeel::eMetric_UseAccessibilityTheme, useAccessibilityTheme); } if (useAccessibilityTheme) { // Use classic skin, it obeys the system's accessibility theme nsCOMPtr chromeRegistry = do_GetService(NS_CHROMEREGISTRY_CONTRACTID); if (chromeRegistry) { chromeRegistry->SetRuntimeProvider(PR_TRUE); // The skin change isn't permanent chromeRegistry->SelectSkin(NS_LITERAL_CSTRING("classic/1.0"), PR_TRUE); } } } static nsresult InitializeProfileService(nsICmdLineService *cmdLineArgs) { // If we are being launched in -turbo mode, we cannot show UI PRBool shouldShowUI = PR_TRUE; nsCOMPtr nativeApp; if (NS_SUCCEEDED(GetNativeAppSupport(getter_AddRefs(nativeApp)))) nativeApp->GetShouldShowUI(&shouldShowUI); // If we were launched with -silent, we cannot show UI, either. if (shouldShowUI) { nsXPIDLCString arg; if (NS_SUCCEEDED(cmdLineArgs->GetCmdLineValue("-silent", getter_Copies(arg)))) { if (!arg.IsEmpty()) { shouldShowUI = PR_FALSE; } } } nsresult rv; nsCOMPtr appStartup(do_GetService(NS_APPSTARTUP_CONTRACTID, &rv)); if (NS_FAILED(rv)) return rv; rv = appStartup->DoProfileStartup(cmdLineArgs, shouldShowUI); return rv; } // Maximum allowed / used length of alert message is 255 chars, due to restrictions on Mac. // Please make sure that file contents and fallback_alert_text are at most 255 chars. // Fallback_alert_text must be non-const, because of inplace conversion on Mac. static void ShowOSAlertFromFile(int argc, char **argv, const char *alert_filename, const char* fallback_alert_text) { char message[256] = { 0 }; PRInt32 numRead = 0; const char *messageToShow = fallback_alert_text; nsresult rv; nsCOMPtr fileName; nsCOMPtr directoryService; directoryService = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv); if (NS_SUCCEEDED(rv)) { rv = directoryService->Get(NS_GRE_DIR, NS_GET_IID(nsIFile), getter_AddRefs(fileName)); if (NS_SUCCEEDED(rv) && fileName) { fileName->AppendNative(NS_LITERAL_CSTRING("res")); fileName->AppendNative(nsDependentCString(alert_filename)); PRFileDesc* fd = 0; fileName->OpenNSPRFileDesc(PR_RDONLY, 0664, &fd); if (fd) { numRead = PR_Read(fd, message, sizeof(message)-1); if (numRead > 0) { message[numRead] = 0; messageToShow = message; } } } } ShowOSAlert(messageToShow); } static nsresult VerifyInstallation(int argc, char **argv) { #ifdef MOZ_XPINSTALL nsresult rv; nsCOMPtr registryFile; nsCOMPtr directoryService = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv); if (NS_FAILED(rv)) return NS_OK; rv = directoryService->Get(NS_APP_INSTALL_CLEANUP_DIR, NS_GET_IID(nsIFile), getter_AddRefs(registryFile)); if (NS_FAILED(rv) || !registryFile) return NS_ERROR_FAILURE; registryFile->AppendNative(CLEANUP_REGISTRY); PRBool exists; registryFile->Exists(&exists); if (exists) { nsCOMPtr binPath; const char lastResortMessage[] = "A previous install did not complete correctly. Finishing install."; ShowOSAlertFromFile(argc, argv, CLEANUP_MESSAGE_FILENAME.get(), lastResortMessage); nsCOMPtr cleanupUtility; registryFile->Clone(getter_AddRefs(cleanupUtility)); cleanupUtility->SetNativeLeafName(CLEANUP_UTIL); //Create the process framework to run the cleanup utility nsCOMPtr cleanupProcess = do_CreateInstance(NS_PROCESS_CONTRACTID); rv = cleanupProcess->Init(cleanupUtility); if (NS_SUCCEEDED(rv)) rv = cleanupProcess->Run(PR_FALSE,nsnull, 0, nsnull); //We must exit because all open files must be released by the system return NS_ERROR_FAILURE; } #endif return NS_OK; } #ifdef DEBUG_warren #ifdef XP_WIN #define _CRTDBG_MAP_ALLOC #include #endif #endif #if defined(FREEBSD) // pick up fpsetmask prototype. #include #endif // Note: nativeApp is an owning reference that this function has responsibility // to release. This responsibility is delegated to the app startup service // (see nsAppStartup::Initialize call, below). static nsresult main1(int argc, char* argv[], nsISupports *nativeApp ) { nsresult rv; NS_TIMELINE_ENTER("main1"); nsCOMPtr nativeAppOwner(dont_AddRef(nativeApp)); //---------------------------------------------------------------- // First we need to check if a previous installation occured and // if so, make sure it finished and cleaned up correctly. // // If there is an xpicleanup.dat file left around, that means the // previous installation did not finish correctly. We must cleanup // before a valid mozilla can run. // // Show the user a platform-specific Alert message, then spawn the // xpicleanup utility, then exit. //---------------------------------------------------------------- rv = VerifyInstallation(argc, argv); if (NS_FAILED(rv)) return NS_ERROR_FAILURE; #ifdef DEBUG_warren // _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF); #endif #ifndef XP_MAC // Unbuffer debug output (necessary for automated QA performance scripts). setbuf(stdout, 0); #endif #if defined(FREEBSD) // Disable all SIGFPE's on FreeBSD, as it has non-IEEE-conformant fp // trap behavior that trips up on floating-point tests performed by // the JS engine. See bugzilla bug 9967 details. fpsetmask(0); #endif NS_TIMELINE_ENTER("init event service"); nsCOMPtr eventQService(do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv)); if (NS_SUCCEEDED(rv)) { // XXX: What if this fails? rv = eventQService->CreateThreadEventQueue(); } NS_TIMELINE_LEAVE("init event service"); // Setup an autoreg obserer, so that we can update a progress // string in the splash screen nsCOMPtr obsService(do_GetService("@mozilla.org/observer-service;1")); if (obsService) { nsCOMPtr splashScreenObserver(do_QueryInterface(nativeAppOwner)); if (splashScreenObserver) { obsService->AddObserver(splashScreenObserver, NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID, PR_FALSE); obsService->AddObserver(splashScreenObserver, "startup_user_notifcations", PR_FALSE); } } #if XP_MAC stTSMCloser tsmCloser; rv = InitializeMacCommandLine(argc, argv); NS_ASSERTION(NS_SUCCEEDED(rv), "Initializing AppleEvents failed"); #endif #ifdef DEBUG // _Always_ autoreg if we're in a debug build, under the assumption // that people are busily modifying components and will be angry if // their changes aren't noticed. nsCOMPtr registrar; NS_GetComponentRegistrar(getter_AddRefs(registrar)); registrar->AutoRegister(nsnull); registrar = nsnull; #endif NS_TIMELINE_ENTER("startupNotifier"); // Start up the core services: { // Please do not add new things to main1() - please hook into the // nsIAppStartupNotifier service. nsCOMPtr startupNotifier = do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID, &rv); if(NS_FAILED(rv)) return rv; startupNotifier->Observe(nsnull, APPSTARTUP_TOPIC, nsnull); } NS_TIMELINE_LEAVE("startupNotifier"); NS_TIMELINE_ENTER("cmdLineArgs"); // Initialize the cmd line service nsCOMPtr cmdLineArgs(do_GetService(NS_COMMANDLINESERVICE_CONTRACTID, &rv)); NS_ASSERTION(NS_SUCCEEDED(rv), "Could not obtain CmdLine processing service\n"); if (NS_FAILED(rv)) return rv; rv = cmdLineArgs->Initialize(argc, argv); NS_ASSERTION(NS_SUCCEEDED(rv), "failed to initialize command line args"); if (rv == NS_ERROR_INVALID_ARG) { PrintUsage(); return rv; } NS_TIMELINE_LEAVE("cmdLineArgs"); NS_TIMELINE_ENTER("InstallGlobalLocale"); rv = InstallGlobalLocale(cmdLineArgs); if(NS_FAILED(rv)) return rv; NS_TIMELINE_LEAVE("InstallGlobalLocale"); NS_TIMELINE_ENTER("appStartup"); nsCOMPtr appStartup(do_GetService(NS_APPSTARTUP_CONTRACTID)); NS_ASSERTION(appStartup, "failed to get the appstartup service"); /* if we couldn't get the nsIAppStartup service, then we should hide the splash screen and return (and something is seriously screwed up) */ if (!appStartup) { // See if platform supports nsINativeAppSupport. nsCOMPtr nativeAppSupport(do_QueryInterface(nativeAppOwner)); if (nativeAppSupport) { // Use that interface to remove splash screen. nativeAppSupport->HideSplashScreen(); } else { // See if platform supports nsISplashScreen, instead. nsCOMPtr splashScreen(do_QueryInterface(nativeAppOwner)); if (splashScreen) { splashScreen->Hide(); } } return rv; } NS_TIMELINE_LEAVE("appStartup"); NS_TIMELINE_ENTER("appStartup->Initialize"); // Create the Application Shell instance... rv = appStartup->Initialize(nativeAppOwner); NS_TIMELINE_LEAVE("appStartup->Initialize"); NS_ASSERTION(NS_SUCCEEDED(rv), "failed to initialize appstartup"); if (NS_FAILED(rv)) return rv; nsCOMPtr wcreator (do_QueryInterface(appStartup)); NS_ASSERTION(wcreator, "appstartup doesn't do nsIWindowCreator?"); NS_ENSURE_TRUE(wcreator, NS_ERROR_FAILURE); nsCOMPtr wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID)); NS_ASSERTION(wwatch, "Couldn't get the window watcher!"); NS_ENSURE_TRUE(wwatch, NS_ERROR_FAILURE); wwatch->SetWindowCreator(wcreator); // So we can open and close windows during startup appStartup->EnterLastWindowClosingSurvivalArea(); // Initialize Profile Service here. NS_TIMELINE_ENTER("InitializeProfileService"); rv = InitializeProfileService(cmdLineArgs); NS_TIMELINE_LEAVE("InitializeProfileService"); if (NS_FAILED(rv)) return rv; NS_TIMELINE_ENTER("CheckUseAccessibleSkin"); // Need to do this after profile service init'd // If OS accessibility theme is used, then we always load classic theme // which follows the system appearance. CheckUseAccessibleSkin(); NS_TIMELINE_LEAVE("CheckUseAccessibleSkin"); NS_TIMELINE_ENTER("appStartup->CreateHiddenWindow"); appStartup->CreateHiddenWindow(); NS_TIMELINE_LEAVE("appStartup->CreateHiddenWindow"); // This will go away once Components are handling there own commandlines PRBool windowOpened = PR_FALSE; rv = DoCommandLines(cmdLineArgs, &windowOpened); if (NS_FAILED(rv)) { NS_WARNING("failed to process command line"); return rv; } if (obsService) { NS_NAMED_LITERAL_STRING(userMessage, "Creating first window..."); obsService->NotifyObservers(nsnull, "startup_user_notifcations", userMessage.get()); } // Make sure there exists at least 1 window. NS_TIMELINE_ENTER("Ensure1Window"); rv = appStartup->Ensure1Window(cmdLineArgs); NS_TIMELINE_LEAVE("Ensure1Window"); NS_ASSERTION(NS_SUCCEEDED(rv), "failed to Ensure1Window"); if (NS_FAILED(rv)) return rv; #if !defined(XP_MAC) && !defined(XP_MACOSX) appStartup->ExitLastWindowClosingSurvivalArea(); #endif #ifdef MOZ_ENABLE_XREMOTE // if we have X remote support and we have our one window up and // running start listening for requests on the proxy window. // It will shut itself down before the event queue stops processing events. nsCOMPtr remoteService (do_GetService("@mozilla.org/toolkit/remote-service;1")); NS_ASSERTION(remoteService, "Couldn't create remote service?"); if (remoteService) { nsCAutoString pname; nsCOMPtr pm (do_GetService(NS_PROFILE_CONTRACTID)); if (pm) { nsXPIDLString name; pm->GetCurrentProfile(getter_Copies(name)); if (name) { CopyUTF16toUTF8(name, pname); } } remoteService->Startup(NS_STRINGIFY(MOZ_APP_NAME), pname.IsEmpty() ? nsnull : pname.get()); } #endif /* MOZ_ENABLE_XREMOTE */ // remove the nativeApp as an XPCOM autoreg observer if (obsService) { nsCOMPtr splashScreenObserver(do_QueryInterface(nativeAppOwner)); if (splashScreenObserver) { obsService->RemoveObserver(splashScreenObserver, NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID); obsService->RemoveObserver(splashScreenObserver, "startup_user_notifcations"); } } // We are done with the native app (or splash screen) object here; // the app shell owns it now. nativeAppOwner = nsnull; // Start main event loop NS_TIMELINE_ENTER("appStartup->Run"); rv = appStartup->Run(); NS_TIMELINE_LEAVE("appStartup->Run"); NS_ASSERTION(NS_SUCCEEDED(rv), "failed to run appstartup"); #ifdef MOZ_TIMELINE // Make sure we print this out even if timeline is runtime disabled if (NS_FAILED(NS_TIMELINE_LEAVE("main1"))) NS_TimelineForceMark("...main1"); #endif return rv; } // English text needs to go into a dtd file. // But when this is called we have no components etc. These strings must either be // here, or in a native resource file. static void DumpHelp(char *appname) { printf("Usage: %s [ options ... ] [URL]\n", appname); printf(" where options include:\n"); printf("\n"); #ifdef MOZ_WIDGET_GTK /* insert gtk options above moz options, like any other gtk app * * note: this isn't a very cool way to do things -- i'd rather get * these straight from a user's gtk version -- but it seems to be * what most gtk apps do. -dr */ printf("GTK options\n"); printf("%s--gdk-debug=FLAGS%sGdk debugging flags to set\n", HELP_SPACER_1, HELP_SPACER_2); printf("%s--gdk-no-debug=FLAGS%sGdk debugging flags to unset\n", HELP_SPACER_1, HELP_SPACER_2); printf("%s--gtk-debug=FLAGS%sGtk+ debugging flags to set\n", HELP_SPACER_1, HELP_SPACER_2); printf("%s--gtk-no-debug=FLAGS%sGtk+ debugging flags to unset\n", HELP_SPACER_1, HELP_SPACER_2); printf("%s--gtk-module=MODULE%sLoad an additional Gtk module\n", HELP_SPACER_1, HELP_SPACER_2); printf("%s-install%sInstall a private colormap\n", HELP_SPACER_1, HELP_SPACER_2); /* end gtk toolkit options */ #endif /* MOZ_WIDGET_GTK */ #if MOZ_WIDGET_XLIB printf("Xlib options\n"); printf("%s-display=DISPLAY%sX display to use\n", HELP_SPACER_1, HELP_SPACER_2); printf("%s-visual=VISUALID%sX visual to use\n", HELP_SPACER_1, HELP_SPACER_2); printf("%s-install_colormap%sInstall own colormap\n", HELP_SPACER_1, HELP_SPACER_2); printf("%s-sync%sMake X calls synchronous\n", HELP_SPACER_1, HELP_SPACER_2); printf("%s-no-xshm%sDon't use X shared memory extension\n", HELP_SPACER_1, HELP_SPACER_2); /* end xlib toolkit options */ #endif /* MOZ_WIDGET_XLIB */ #ifdef MOZ_X11 printf("X11 options\n"); printf("%s--display=DISPLAY%sX display to use\n", HELP_SPACER_1, HELP_SPACER_2); printf("%s--sync%sMake X calls synchronous\n", HELP_SPACER_1, HELP_SPACER_2); printf("%s--no-xshm%sDon't use X shared memory extension\n", HELP_SPACER_1, HELP_SPACER_2); printf("%s--xim-preedit=STYLE\n", HELP_SPACER_1); printf("%s--xim-status=STYLE\n", HELP_SPACER_1); #endif #ifdef XP_UNIX printf("%s--g-fatal-warnings%sMake all warnings fatal\n", HELP_SPACER_1, HELP_SPACER_2); printf("\n%s options\n", NS_STRINGIFY(MOZ_APP_DISPLAYNAME)); #endif printf("%s-height %sSet height of startup window to .\n",HELP_SPACER_1,HELP_SPACER_2); printf("%s-h or -help%sPrint this message.\n",HELP_SPACER_1,HELP_SPACER_2); printf("%s-installer%sStart with 4.x migration window.\n",HELP_SPACER_1,HELP_SPACER_2); printf("%s-width %sSet width of startup window to .\n",HELP_SPACER_1,HELP_SPACER_2); printf("%s-v or -version%sPrint %s version.\n",HELP_SPACER_1,HELP_SPACER_2, appname); printf("%s-CreateProfile %sCreate .\n",HELP_SPACER_1,HELP_SPACER_2); printf("%s-P %sStart with .\n",HELP_SPACER_1,HELP_SPACER_2); printf("%s-ProfileWizard%sStart with profile wizard.\n",HELP_SPACER_1,HELP_SPACER_2); printf("%s-ProfileManager%sStart with profile manager.\n",HELP_SPACER_1,HELP_SPACER_2); printf("%s-SelectProfile%sStart with profile selection dialog.\n",HELP_SPACER_1,HELP_SPACER_2); printf("%s-UILocale %sStart with resources as UI Locale.\n",HELP_SPACER_1,HELP_SPACER_2); printf("%s-contentLocale %sStart with resources as content Locale.\n",HELP_SPACER_1,HELP_SPACER_2); #if defined(XP_WIN32) || defined(XP_OS2) printf("%s-console%sStart %s with a debugging console.\n",HELP_SPACER_1,HELP_SPACER_2,NS_STRINGIFY(MOZ_APP_DISPLAYNAME)); #endif #ifdef MOZ_ENABLE_XREMOTE printf("%s-remote %sExecute in an already running\n" "%s%s process. For more info, see:\n" "\n%shttp://www.mozilla.org/unix/remote.html\n\n", HELP_SPACER_1,HELP_SPACER_1,HELP_SPACER_4,NS_STRINGIFY(MOZ_APP_DISPLAYNAME),HELP_SPACER_2); printf("%s-splash%sEnable splash screen.\n",HELP_SPACER_1,HELP_SPACER_2); #else printf("%s-nosplash%sDisable splash screen.\n",HELP_SPACER_1,HELP_SPACER_2); #if defined(XP_WIN) || defined(XP_OS2) printf("%s-quiet%sDisable splash screen.\n",HELP_SPACER_1,HELP_SPACER_2); #endif #endif // this works, but only after the components have registered. so if you drop in a new command line handler, -help // won't not until the second run. // out of the bug, because we ship a component.reg file, it works correctly. DumpArbitraryHelp(); } static nsresult DumpVersion(char *appname) { nsresult rv = NS_OK; long buildID = NS_BUILD_ID; // 10-digit number printf("%s %s, Copyright (c) 2003-2010 mozilla.org", NS_STRINGIFY(MOZ_APP_DISPLAYNAME), NS_STRINGIFY(MOZ_APP_VERSION)); if(buildID) { printf(", build %u\n", (unsigned int)buildID); } else { printf(" \n"); } return rv; } #ifdef MOZ_ENABLE_XREMOTE // use int here instead of a PR type since it will be returned // from main - just to keep types consistent static int HandleRemoteArguments(int argc, char* argv[], PRBool *aArgUsed) { int i = 0; const char *remote = 0; const char *profile = 0; const char *program = 0; const char *username = 0; for (i=1; i < argc; i++) { if (PL_strcasecmp(argv[i], "-remote") == 0) { // someone used a -remote flag *aArgUsed = PR_TRUE; // check to make sure there's another arg if (argc-1 == i) { PR_fprintf(PR_STDERR, "Error: -remote requires an argument\n"); return 1; } // Get the remote argument and advance past it. remote = argv[++i]; } else if (PL_strcasecmp(argv[i], "-p") == 0) { // someone used the -p flag - save the contents if (argc-1 == i) { continue; } // Get the argument profile = argv[++i]; } else if (PL_strcasecmp(argv[i], "-a") == 0) { // someone used the -a flag - save the contents if (argc-1 == i) { continue; } // Get the argument program = argv[++i]; } else if (PL_strcasecmp(argv[i], "-u") == 0) { // someone used the -u flag - save the contents if (argc-1 == i) { continue; } // Get the argument username = argv[++i]; } } if (!remote) return 0; // No remote argument == success // try to get the X remote client XRemoteClient client; nsresult rv; // try to init - connects to the X server and stuff rv = client.Init(); if (NS_FAILED(rv)) { PR_fprintf(PR_STDERR, "Error: Failed to connect to X server.\n"); return 1; } // Make sure to set a username if possible if (!username) { username = PR_GetEnv("LOGNAME"); } // Same with the program name if (!program) { program = NS_STRINGIFY(MOZ_APP_NAME); } char *response = NULL; PRBool success = PR_FALSE; rv = client.SendCommand(program, username, profile, remote, &response, &success); // did the command fail? if (NS_FAILED(rv)) { PR_fprintf(PR_STDERR, "Error: Failed to send command: "); if (response) { PR_fprintf(PR_STDERR, "%s\n", response); free(response); } else { PR_fprintf(PR_STDERR, "No response included.\n"); } return 1; } // was there no window running? if (!success) { PR_fprintf(PR_STDERR, "Error: No running window found.\n"); return 2; } // success return 0; } #endif /* XP_UNIX */ static PRBool HandleDumpArguments(int argc, char* argv[]) { for (int i=1; i 4 && !strcmp(argv[1], "-osint")) return 1; #endif NS_TIMELINE_MARK("enter main"); int i; //Moved here due to portability guideline 20. See bug 258055 #ifdef XP_WIN32 // Suppress the "DLL Foo could not be found" dialog, such that if dependent // libraries (such as GDI+) are not preset, we gracefully fail to load those // XPCOM components, instead of being ungraceful. SetErrorMode(SEM_FAILCRITICALERRORS); #ifdef DEBUG // Disable small heap allocator to get heapwalk() giving us // accurate heap numbers. Win2k non-debug does not use small heap allocator. // Win2k debug seems to be still using it. // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt__set_sbh_threshold.asp _set_sbh_threshold(0); #endif #endif #if defined(XP_UNIX) || defined(XP_BEOS) InstallUnixSignalHandlers(argv[0]); #endif #ifdef MOZ_ACCESSIBILITY_ATK // Reset GTK_MODULES, strip atk-bridge if exists // Mozilla will load libatk-bridge.so later if necessary const char* gtkModules = PR_GetEnv("GTK_MODULES"); if (gtkModules && *gtkModules) { nsCString gtkModulesStr(gtkModules); gtkModulesStr.ReplaceSubstring("atk-bridge", ""); char* expr = PR_smprintf("GTK_MODULES=%s", gtkModulesStr.get()); if (expr) PR_SetEnv(expr); // We intentionally leak |expr| here since it is required by PR_SetEnv. } #endif #if defined(XP_OS2) __pargc = &argc; __argv = argv; PRBool StartOS2App(int aArgc, char **aArgv); if (!StartOS2App(argc, argv)) return 1; ScopedFPHandler handler; #endif /* XP_OS2 */ #if defined(XP_MACOSX) InitializeMacOSXApp(argc, argv); #endif // Handle -help and -version command line arguments. // They should% return quick, so we deal with them here. if (HandleDumpArguments(argc, argv)) return 0; #ifdef NS_TRACE_MALLOC argc = NS_TraceMallocStartupArgs(argc, argv); #endif #ifdef MOZ_X11 /* Init threadsafe mode of Xlib API on demand * (currently this is only for testing, future builds may use this by * default) */ PRBool x11threadsafe = PR_FALSE; for (i=1; iStart(&canRun); if (!canRun) { return 1; } } else { // If platform doesn't implement nsINativeAppSupport, fall // back to old method. if (!NS_CanRun()) return 1; } // Note: this object is not released here. It is passed to main1 which // has responsibility to release it. nsISplashScreen *splash = 0; PRBool dosplash = GetWantSplashScreen(argc, argv); if (dosplash && !nativeApp) { // If showing splash screen and platform doesn't implement // nsINativeAppSupport, then use older nsISplashScreen interface. rv = NS_CreateSplashScreen(&splash); NS_ASSERTION(NS_SUCCEEDED(rv), "NS_CreateSplashScreen failed"); } // If the platform has a splash screen, show it ASAP. if (dosplash && nativeApp) { nativeApp->ShowSplashScreen(); } else if (splash) { splash->Show(); } #ifdef MOZ_ENABLE_XREMOTE // handle -remote now that xpcom is fired up int remoterv; PRBool argused = PR_FALSE; // argused will be true if someone tried to use a -remote flag. We // always exit in that case. remoterv = HandleRemoteArguments(argc, argv, &argused); if (argused) { #ifdef XPCOM_GLUE GRE_Shutdown(); #else NS_ShutdownXPCOM(nsnull); #endif return remoterv; } #endif nsresult mainResult = main1(argc, argv, nativeApp ? (nsISupports*)nativeApp : (nsISupports*)splash); /* if main1() didn't succeed, then don't bother trying to shut down clipboard, etc */ if (NS_SUCCEEDED(mainResult)) { rv = DoOnShutdown(); NS_ASSERTION(NS_SUCCEEDED(rv), "DoOnShutdown failed"); } #ifdef XPCOM_GLUE rv = GRE_Shutdown(); NS_ASSERTION(NS_SUCCEEDED(rv), "GRE_Shutdown failed"); #else rv = NS_ShutdownXPCOM(nsnull); NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed"); #endif return TranslateReturnValue(mainResult); } #if defined( XP_WIN ) && defined( WIN32 ) && !defined(__GNUC__) // We need WinMain in order to not be a console app. This function is // unused if we are a console application. int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR args, int) { // Do the real work. return main(__argc, __argv); } #endif // XP_WIN && WIN32