Back to index

lightning-sunbird  0.9+nobinonly
nsAppRunner.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Communicator client code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
00024  *   Fredrik Holmqvist <thesuckiestemail@yahoo.se>
00025  *   Masayuki Nakano <masayuki@d-toybox.com>
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either of the GNU General Public License Version 2 or later (the "GPL"),
00029  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00041 
00042 #ifdef XPCOM_GLUE
00043 #include "nsXPCOMGlue.h"
00044 #endif
00045 
00046 #include "nsStringSupport.h"
00047 
00048 #include "nsXPCOM.h"
00049 #include "nsIServiceManager.h"
00050 #include "nsServiceManagerUtils.h"
00051 #include "nsIComponentManager.h"
00052 #include "nsComponentManagerUtils.h"
00053 #include "nsIGenericFactory.h"
00054 #include "nsIComponentRegistrar.h"
00055 #include "nsStaticComponents.h"
00056 
00057 #ifdef XP_OS2
00058 #include "private/pprthred.h"
00059 #endif
00060 
00061 #include "nsIPrefService.h"
00062 #include "nsIPrefBranch.h"
00063 #include "nsILocaleService.h"
00064 #include "plevent.h"
00065 #include "prmem.h"
00066 #include "prenv.h"
00067 #include "prnetdb.h"
00068 
00069 #include "nsCOMPtr.h"
00070 #include "nsIAppShell.h"
00071 #include "nsICmdLineService.h"
00072 #include "nsIAppShellService.h"
00073 #include "nsIAppStartupNotifier.h"
00074 #include "nsIAppStartup.h"
00075 #include "nsIObserverService.h"
00076 #include "prprf.h"
00077 #include "nsCRT.h"
00078 #include "nsIDirectoryService.h"
00079 #include "nsDirectoryServiceUtils.h"
00080 #include "nsAppDirectoryServiceDefs.h"
00081 #include "nsIWindowMediator.h"
00082 #include "nsIDOMWindowInternal.h"
00083 #include "nsISupportsPrimitives.h"
00084 #include "nsICmdLineHandler.h"
00085 #include "nsICategoryManager.h"
00086 #include "nsIXULWindow.h"
00087 #include "nsIChromeRegistrySea.h"
00088 #include "nsIEventQueueService.h"
00089 #include "nsDirectoryServiceDefs.h"
00090 #include "nsBuildID.h"
00091 #include "nsIWindowCreator.h"
00092 #include "nsIWindowWatcher.h"
00093 #include "nsILocalFile.h"
00094 #include "nsILookAndFeel.h"
00095 #include "nsIProcess.h"
00096 #include "nsIIOService.h"
00097 #include "nsIJARURI.h"
00098 #include "nsNetCID.h"
00099 
00100 #ifdef MOZ_XPINSTALL
00101 #include "InstallCleanupDefines.h"
00102 #include "nsISoftwareUpdate.h"
00103 #endif
00104 
00105 // Interfaces Needed
00106 #include "nsIXULWindow.h"
00107 #include "nsIWebBrowserChrome.h"
00108 #include "nsIDocShell.h"
00109 
00110 // for X remote support
00111 #ifdef MOZ_ENABLE_XREMOTE
00112 #ifdef MOZ_WIDGET_PHOTON
00113 #include "PhRemoteClient.h"
00114 #else
00115 #include "XRemoteClient.h"
00116 #endif
00117 #include "nsIRemoteService.h"
00118 #endif
00119 
00120 // see DoOnShutdown()
00121 #include "nsIProfile.h"
00122 
00123 #ifdef NS_TRACE_MALLOC
00124 #include "nsTraceMalloc.h"
00125 #endif
00126 
00127 #ifdef XP_WIN32
00128 #include <windows.h>
00129 
00130 #ifdef DEBUG
00131 #include <malloc.h>
00132 #endif
00133 #endif
00134 
00135 #if defined (XP_MACOSX)
00136 #include <Processes.h>
00137 #endif
00138 
00139 #include "nsITimelineService.h"
00140 
00141 #if defined(DEBUG_pra)
00142 #define DEBUG_CMD_LINE
00143 #endif
00144 
00145 #include "nsWidgetsCID.h"
00146 #include "nsXPFEComponentsCID.h"
00147 
00148 static NS_DEFINE_CID(kLookAndFeelCID,  NS_LOOKANDFEEL_CID);
00149 
00150 #define UILOCALE_CMD_LINE_ARG "-UILocale"
00151 #define CONTENTLOCALE_CMD_LINE_ARG "-contentLocale"
00152 
00153 extern "C" void ShowOSAlert(const char* aMessage);
00154 
00155 #define HELP_SPACER_1   "\t"
00156 #define HELP_SPACER_2   "\t\t"
00157 #define HELP_SPACER_4   "\t\t\t\t"
00158 
00159 #ifdef DEBUG
00160 #include "prlog.h"
00161 #endif
00162 
00163 #ifdef MOZ_JPROF
00164 #include "jprof.h"
00165 #endif
00166 
00167 // on x86 linux, the current builds of some popular plugins (notably
00168 // flashplayer and real) expect a few builtin symbols from libgcc
00169 // which were available in some older versions of gcc.  However,
00170 // they're _NOT_ available in newer versions of gcc (eg 3.1), so if
00171 // we want those plugin to work with a gcc-3.1 built binary, we need
00172 // to provide these symbols.  MOZ_ENABLE_OLD_ABI_COMPAT_WRAPPERS defaults
00173 // to true on x86 linux, and false everywhere else.
00174 //
00175 // The fact that the new and free operators are mismatched 
00176 // mirrors the way the original functions in egcs 1.1.2 worked.
00177 
00178 #ifdef MOZ_ENABLE_OLD_ABI_COMPAT_WRAPPERS
00179 
00180 extern "C" {
00181 
00182 # ifndef HAVE___BUILTIN_VEC_NEW
00183   void *__builtin_vec_new(size_t aSize, const std::nothrow_t &aNoThrow) throw()
00184   {
00185     return ::operator new(aSize, aNoThrow);
00186   }
00187 # endif
00188 
00189 # ifndef HAVE___BUILTIN_VEC_DELETE
00190   void __builtin_vec_delete(void *aPtr, const std::nothrow_t &) throw ()
00191   {
00192     if (aPtr) {
00193       free(aPtr);
00194     }
00195   }
00196 # endif
00197 
00198 # ifndef HAVE___BUILTIN_NEW
00199        void *__builtin_new(int aSize)
00200   {
00201     return malloc(aSize);
00202   }
00203 # endif
00204 
00205 # ifndef HAVE___BUILTIN_DELETE
00206        void __builtin_delete(void *aPtr)
00207   {
00208     free(aPtr);
00209   }
00210 # endif
00211 
00212 # ifndef HAVE___PURE_VIRTUAL
00213   void __pure_virtual(void) {
00214 #ifdef WRAP_SYSTEM_INCLUDES
00215 #pragma GCC visibility push(default)
00216 #endif
00217     extern void __cxa_pure_virtual(void);
00218 #ifdef WRAP_SYSTEM_INCLUDES
00219 #pragma GCC visibility pop
00220 #endif
00221 
00222     __cxa_pure_virtual();
00223   }
00224 # endif
00225 }
00226 #endif
00227 
00228 #ifndef _BUILD_STATIC_BIN
00229 nsStaticModuleInfo const *const kPStaticModules = nsnull;
00230 PRUint32 const kStaticModuleCount = 0;
00231 #endif
00232 
00233 #if defined(XP_UNIX) || defined(XP_BEOS)
00234   extern void InstallUnixSignalHandlers(const char *ProgramName);
00235 #endif
00236 
00237 #if defined(XP_OS2)
00238 /* Adding globals that OS/2 doesn't have so we can port the DDE code */
00239 char **__argv;
00240 int   *__pargc;
00241 #endif /* XP_OS2 */
00242 
00243 #if defined(XP_MAC)
00244 
00245 #include "macstdlibextras.h"
00246 #include <TextServices.h>
00247 
00248 // Set up the toolbox and (if DEBUG) the console.  Do this in a static initializer,
00249 // to make it as unlikely as possible that somebody calls printf() before we get initialized.
00250 static struct MacInitializer { MacInitializer() { InitializeMacToolbox(); } } gInitializer;
00251 
00252 // Initialize profile services for both standalone and regular profiles
00253 static nsresult InitializeProfileService(nsICmdLineService *cmdLineArgs);
00254 
00255 // Install global locale if possible
00256 static nsresult InstallGlobalLocale(nsICmdLineService *cmdLineArgs);
00257 static nsresult getUILangCountry(nsAString& aUILang, nsAString& aCountry);
00258 
00259 class stTSMCloser
00260 {
00261 public:
00262        stTSMCloser()
00263   {
00264     // TSM is initialized in InitializeMacToolbox
00265   };
00266 
00267        ~stTSMCloser()
00268        {
00269 #if !TARGET_CARBON
00270               (void)CloseTSMAwareApplication();
00271 #endif
00272        }
00273 };
00274 #endif // XP_MAC
00275 
00276 #if defined(XP_MACOSX)
00277 
00278 static void InitializeMacOSXApp(int argc, char* argv[])
00279 {
00280   // use the location of the executable to learn where everything is, this
00281   // is because the current working directory is ill-defined when the
00282   // application is double-clicked from the Finder.
00283   char* path = strdup(argv[0]);
00284   char* lastSlash = strrchr(path, '/');
00285   if (lastSlash) {
00286     *lastSlash = '\0';
00287     setenv("MOZILLA_FIVE_HOME", path, 1);
00288   }
00289   free(path);
00290 }
00291 
00292 #endif /* XP_MACOSX */
00293 
00294 #if defined(MOZ_WIDGET_QT)
00295 #include <qapplication.h>
00296 #endif
00297 
00298 #ifdef MOZ_X11
00299 #include <X11/Xlib.h>
00300 #endif /* MOZ_X11 */
00301 
00302 #if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_GTK2)
00303 #include <gtk/gtk.h>
00304 #endif //MOZ_WIDGET_GTK || MOZ_WIDGET_GTK2
00305 
00306 #include "nsNativeAppSupport.h"
00307 
00308 /*********************************************/
00309 // Default implemenations for nativeAppSupport
00310 // If your platform implements these functions if def out this code.
00311 #if !defined(MOZ_WIDGET_COCOA) && !defined(MOZ_WIDGET_PHOTON) && !defined( XP_WIN) && !defined(XP_OS2) && !defined(MOZ_WIDGET_GTK) && !defined(MOZ_WIDGET_GTK2)
00312 
00313 nsresult NS_CreateSplashScreen(nsISplashScreen **aResult)
00314 {
00315     nsresult rv = NS_OK;
00316     if (aResult) {
00317         *aResult = 0;
00318     } else {
00319         rv = NS_ERROR_NULL_POINTER;
00320     }
00321     return rv;
00322 }
00323 
00324 PRBool NS_CanRun()
00325 {
00326        return PR_TRUE;
00327 }
00328 #endif
00329 
00330 /*********************************************/
00331 // Default implementation for new and improved
00332 // native app support.  If your platform
00333 // implements nsINativeAppSupport then implement
00334 // this function and if def out this code.
00335 //
00336 // Note: For now, the default imiplementation returns 0 and
00337 //       the code that calls this will defalt to use the old
00338 //       nsISplashScreen interface directly.  At some point
00339 //       this function will return an instance of
00340 //       nsNativeAppSupportBase which will use the older
00341 //       "splash screen" interface.  The code below will
00342 //       then rely on nsINativeAppSupport and its use of
00343 //       nsISplashScreen will be removed.
00344 //
00345 
00346 #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))
00347 
00348 nsresult NS_CreateNativeAppSupport(nsINativeAppSupport **aResult)
00349 {
00350     nsresult rv = NS_OK;
00351     if (aResult) {
00352         *aResult = 0;
00353     } else {
00354         rv = NS_ERROR_NULL_POINTER;
00355     }
00356     return rv;
00357 }
00358 
00359 #endif
00360 
00361 static nsresult GetNativeAppSupport(nsINativeAppSupport** aNativeApp)
00362 {
00363     NS_ENSURE_ARG_POINTER(aNativeApp);
00364     *aNativeApp = nsnull;
00365 
00366     nsCOMPtr<nsIAppStartup> appStartup(do_GetService(NS_APPSTARTUP_CONTRACTID));
00367     if (appStartup)
00368         appStartup->GetNativeAppSupport(aNativeApp);
00369 
00370     return *aNativeApp ? NS_OK : NS_ERROR_FAILURE;
00371 }
00372 
00373 /*
00374  * This routine translates the nsresult into a platform specific return
00375  * code for the application...
00376  */
00377 static int TranslateReturnValue(nsresult aResult)
00378 {
00379   if (NS_SUCCEEDED(aResult)) {
00380     return 0;
00381   }
00382   return 1;
00383 }
00384 
00385 #ifdef XP_MAC
00386 #include "nsCommandLineServiceMac.h"
00387 #endif
00388 
00389 static void
00390 PrintUsage(void)
00391 {
00392   fprintf(stderr, "Usage: apprunner <url>\n");
00393   fprintf(stderr, "\t<url>:  a fully defined url string like http:// etc..\n");
00394 }
00395 
00396 static nsresult OpenWindow(const nsCString& aChromeURL,
00397                            const nsString& aAppArgs,
00398                            PRInt32 aWidth, PRInt32 aHeight);
00399 
00400 static nsresult OpenWindow(const nsCString& aChromeURL,
00401                            const nsString& aAppArgs)
00402 {
00403   return OpenWindow(aChromeURL, aAppArgs,
00404                     nsIAppShellService::SIZE_TO_CONTENT,
00405                     nsIAppShellService::SIZE_TO_CONTENT);
00406 }
00407 
00408 static nsresult OpenWindow(const nsCString& aChromeURL,
00409                            PRInt32 aWidth, PRInt32 aHeight)
00410 {
00411   return OpenWindow(aChromeURL, EmptyString(), aWidth, aHeight);
00412 }
00413 
00414 static nsresult OpenWindow(const nsCString& aChromeURL,
00415                            const nsString& aAppArgs,
00416                            PRInt32 aWidth, PRInt32 aHeight)
00417 {
00418 
00419 #ifdef DEBUG_CMD_LINE
00420   printf("OpenWindow(%s, %s, %d, %d)\n", aChromeURL.get(),
00421                                          NS_ConvertUCS2toUTF8(aAppArgs).get(),
00422                                          aWidth, aHeight);
00423 #endif /* DEBUG_CMD_LINE */
00424 
00425   nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
00426   nsCOMPtr<nsISupportsString> sarg(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID));
00427   if (!wwatch || !sarg)
00428     return NS_ERROR_FAILURE;
00429 
00430   // Make sure a profile is selected.
00431 
00432   // We need the native app support object, which we get from
00433   // the app shell service.  If this fails, we still proceed.
00434   // That's because some platforms don't have a native app
00435   // support implementation.  On those platforms, "ensuring a
00436   // profile" is moot (because they don't support "-turbo",
00437   // basically).  Specifically, because they don't do turbo, they will
00438   // *always* have a profile selected.
00439   nsCOMPtr<nsIAppStartup> appStartup(do_GetService(NS_APPSTARTUP_CONTRACTID));
00440   nsCOMPtr <nsICmdLineService> cmdLine(do_GetService(NS_COMMANDLINESERVICE_CONTRACTID));
00441   if (appStartup && cmdLine)
00442   {
00443     nsCOMPtr<nsINativeAppSupport> nativeApp;
00444     if (NS_SUCCEEDED(appStartup->GetNativeAppSupport(getter_AddRefs(nativeApp))))
00445     {
00446       // Make sure profile has been selected.
00447       // At this point, we have to look for failure.  That
00448       // handles the case where the user chooses "Exit" on
00449       // the profile manager window.
00450       if (NS_FAILED(nativeApp->EnsureProfile(cmdLine)))
00451         return NS_ERROR_NOT_INITIALIZED;
00452     }
00453   }
00454 
00455   sarg->SetData(aAppArgs);
00456 
00457   nsCAutoString features("chrome,dialog=no,all");
00458   if (aHeight != nsIAppShellService::SIZE_TO_CONTENT) {
00459     features.Append(",height=");
00460     AppendIntToString(features, aHeight);
00461   }
00462   if (aWidth != nsIAppShellService::SIZE_TO_CONTENT) {
00463     features.Append(",width=");
00464     AppendIntToString(features, aWidth);
00465   }
00466 
00467 #ifdef DEBUG_CMD_LINE
00468   printf("features: %s...\n", features.get());
00469 #endif /* DEBUG_CMD_LINE */
00470 
00471   nsCOMPtr<nsIDOMWindow> newWindow;
00472   return wwatch->OpenWindow(0, aChromeURL.get(), "_blank",
00473                             features.get(), sarg,
00474                             getter_AddRefs(newWindow));
00475 }
00476 
00477 static void DumpArbitraryHelp()
00478 {
00479   nsresult rv;
00480   nsCOMPtr<nsICategoryManager> catman(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv));
00481   if(NS_SUCCEEDED(rv) && catman) {
00482     nsCOMPtr<nsISimpleEnumerator> e;
00483     rv = catman->EnumerateCategory(COMMAND_LINE_ARGUMENT_HANDLERS, getter_AddRefs(e));
00484     if(NS_SUCCEEDED(rv) && e) {
00485       while (PR_TRUE) {
00486         nsCOMPtr<nsISupportsCString> catEntry;
00487         rv = e->GetNext(getter_AddRefs(catEntry));
00488         if (NS_FAILED(rv) || !catEntry) break;
00489 
00490         nsCAutoString entryString;
00491         rv = catEntry->GetData(entryString);
00492         if (NS_FAILED(rv) || entryString.IsEmpty()) break;
00493 
00494         nsXPIDLCString contractidString;
00495         rv = catman->GetCategoryEntry(COMMAND_LINE_ARGUMENT_HANDLERS,
00496                                       entryString.get(),
00497                                       getter_Copies(contractidString));
00498         if (NS_FAILED(rv) || contractidString.IsEmpty()) break;
00499 
00500 #ifdef DEBUG_CMD_LINE
00501         printf("cmd line handler contractid = %s\n", contractidString.get());
00502 #endif /* DEBUG_CMD_LINE */
00503 
00504         nsCOMPtr <nsICmdLineHandler> handler(do_GetService(contractidString.get(), &rv));
00505 
00506         if (handler) {
00507           nsXPIDLCString commandLineArg;
00508           rv = handler->GetCommandLineArgument(getter_Copies(commandLineArg));
00509           if (NS_FAILED(rv)) continue;
00510 
00511           nsXPIDLCString helpText;
00512           rv = handler->GetHelpText(getter_Copies(helpText));
00513           if (NS_FAILED(rv)) continue;
00514 
00515           if (!commandLineArg.IsEmpty()) {
00516             printf("%s%s", HELP_SPACER_1, commandLineArg.get());
00517 
00518             PRBool handlesArgs = PR_FALSE;
00519             rv = handler->GetHandlesArgs(&handlesArgs);
00520             if (NS_SUCCEEDED(rv) && handlesArgs) {
00521               printf(" <url>");
00522             }
00523             if (!helpText.IsEmpty()) {
00524               printf("%s%s\n", HELP_SPACER_2, helpText.get());
00525             }
00526           }
00527         }
00528 
00529       }
00530     }
00531   }
00532   return;
00533 }
00534 
00535 static nsresult
00536 LaunchApplicationWithArgs(const char *commandLineArg,
00537                           nsICmdLineService *cmdLineArgs,
00538                           const char *aParam,
00539                           PRInt32 height, PRInt32 width, PRBool *windowOpened)
00540 {
00541   NS_ENSURE_ARG(commandLineArg);
00542   NS_ENSURE_ARG(cmdLineArgs);
00543   NS_ENSURE_ARG(aParam);
00544   NS_ENSURE_ARG(windowOpened);
00545 
00546   nsresult rv;
00547 
00548   nsCOMPtr <nsICmdLineHandler> handler;
00549   rv = cmdLineArgs->GetHandlerForParam(aParam, getter_AddRefs(handler));
00550   if (NS_FAILED(rv)) return rv;
00551 
00552   if (!handler) return NS_ERROR_FAILURE;
00553 
00554   nsXPIDLCString chromeUrlForTask;
00555   rv = handler->GetChromeUrlForTask(getter_Copies(chromeUrlForTask));
00556   if (NS_FAILED(rv)) return rv;
00557 
00558 #ifdef DEBUG_CMD_LINE
00559   printf("XXX got this one:\t%s\n\t%s\n\n",commandLineArg,chromeUrlForTask.get());
00560 #endif /* DEBUG_CMD_LINE */
00561 
00562   nsXPIDLCString cmdResult;
00563   rv = cmdLineArgs->GetCmdLineValue(commandLineArg, getter_Copies(cmdResult));
00564   if (NS_FAILED(rv)) return rv;
00565 #ifdef DEBUG_CMD_LINE
00566   printf("%s, cmdResult = %s\n",commandLineArg,cmdResult.get());
00567 #endif /* DEBUG_CMD_LINE */
00568 
00569   PRBool handlesArgs = PR_FALSE;
00570   rv = handler->GetHandlesArgs(&handlesArgs);
00571   if (handlesArgs) {
00572     if (!cmdResult.IsEmpty()) {
00573       if (strcmp("1", cmdResult.get())) {
00574         PRBool openWindowWithArgs = PR_TRUE;
00575         rv = handler->GetOpenWindowWithArgs(&openWindowWithArgs);
00576         if (NS_FAILED(rv)) return rv;
00577 
00578         if (openWindowWithArgs) {
00579           nsAutoString cmdArgs;
00580           NS_CopyNativeToUnicode(cmdResult, cmdArgs);
00581 #ifdef DEBUG_CMD_LINE
00582           printf("opening %s with %s\n", chromeUrlForTask.get(), "OpenWindow");
00583 #endif /* DEBUG_CMD_LINE */
00584           rv = OpenWindow(chromeUrlForTask, cmdArgs);
00585         }
00586         else {
00587           // We need to emulate checkLoadURI because we don't have a window yet
00588           nsCOMPtr<nsIIOService> ioService = do_GetService(NS_IOSERVICE_CONTRACTID, &rv);
00589           if (NS_FAILED(rv)) return rv;
00590           nsCOMPtr<nsIURI> baseURI;
00591           rv = ioService->NewURI(cmdResult, nsnull, nsnull, getter_AddRefs(baseURI));
00592           if (NS_FAILED(rv)) return rv;
00593           nsCOMPtr<nsIJARURI> jarURI(do_QueryInterface(baseURI));
00594           while (jarURI) {
00595             rv = jarURI->GetJARFile(getter_AddRefs(baseURI));
00596             if (NS_FAILED(rv)) return rv;
00597             jarURI = do_QueryInterface(baseURI);
00598           }
00599           PRBool scriptOrData = PR_FALSE;
00600           baseURI->SchemeIs("javascript", &scriptOrData);
00601           if (!scriptOrData)
00602             baseURI->SchemeIs("data", &scriptOrData);
00603           if (scriptOrData)
00604             return NS_ERROR_FAILURE;
00605 #ifdef DEBUG_CMD_LINE
00606           printf("opening %s with %s\n", cmdResult.get(), "OpenWindow");
00607 #endif /* DEBUG_CMD_LINE */
00608           rv = OpenWindow(cmdResult, width, height);
00609           if (NS_FAILED(rv)) return rv;
00610         }
00611         // If we get here without an error, then a window was opened OK.
00612         if (NS_SUCCEEDED(rv)) {
00613           *windowOpened = PR_TRUE;
00614         }
00615       }
00616       else {
00617         nsXPIDLString defaultArgs;
00618         rv = handler->GetDefaultArgs(getter_Copies(defaultArgs));
00619         if (NS_FAILED(rv)) return rv;
00620 
00621         rv = OpenWindow(chromeUrlForTask, defaultArgs);
00622         if (NS_FAILED(rv)) return rv;
00623         // Window was opened OK.
00624         *windowOpened = PR_TRUE;
00625       }
00626     }
00627   }
00628   else {
00629     if (NS_SUCCEEDED(rv) && !cmdResult.IsEmpty()) {
00630       if (strcmp("1", cmdResult.get()) == 0) {
00631         rv = OpenWindow(chromeUrlForTask, width, height);
00632         if (NS_FAILED(rv)) return rv;
00633       }
00634       else {
00635         rv = OpenWindow(cmdResult, width, height);
00636         if (NS_FAILED(rv)) return rv;
00637       }
00638       // If we get here without an error, then a window was opened OK.
00639       if (NS_SUCCEEDED(rv)) {
00640         *windowOpened = PR_TRUE;
00641       }
00642     }
00643   }
00644 
00645   return NS_OK;
00646 }
00647 
00648 static PRBool IsStartupCommand(const char *arg)
00649 {
00650   if (!arg) return PR_FALSE;
00651 
00652   if (PL_strlen(arg) <= 1) return PR_FALSE;
00653 
00654   // windows allows /mail or -mail
00655   if ((arg[0] == '-')
00656 #if defined(XP_WIN) || defined(XP_OS2)
00657       || (arg[0] == '/')
00658 #endif /* XP_WIN || XP_OS2 */
00659       ) {
00660     return PR_TRUE;
00661   }
00662 
00663   return PR_FALSE;
00664 }
00665 
00666 
00667 // This should be done by app shell enumeration someday
00668 nsresult DoCommandLines(nsICmdLineService* cmdLineArgs, PRBool *windowOpened)
00669 {
00670   NS_ENSURE_ARG(windowOpened);
00671   *windowOpened = PR_FALSE;
00672 
00673   nsresult rv;
00674 
00675        PRInt32 height = nsIAppShellService::SIZE_TO_CONTENT;
00676        PRInt32 width  = nsIAppShellService::SIZE_TO_CONTENT;
00677        nsXPIDLCString tempString;
00678 
00679        // Get the value of -width option
00680        rv = cmdLineArgs->GetCmdLineValue("-width", getter_Copies(tempString));
00681        if (NS_SUCCEEDED(rv) && !tempString.IsEmpty())
00682     PR_sscanf(tempString.get(), "%d", &width);
00683 
00684        // Get the value of -height option
00685        rv = cmdLineArgs->GetCmdLineValue("-height", getter_Copies(tempString));
00686        if (NS_SUCCEEDED(rv) && !tempString.IsEmpty())
00687     PR_sscanf(tempString.get(), "%d", &height);
00688   
00689     PRInt32 argc = 0;
00690     rv = cmdLineArgs->GetArgc(&argc);
00691   if (NS_FAILED(rv)) 
00692     return rv;
00693 
00694     char **argv = nsnull;
00695     rv = cmdLineArgs->GetArgv(&argv);
00696   if (NS_FAILED(rv)) 
00697     return rv;
00698 
00699   // first apply command line args
00700   // if there is any window opened, startup preferences are ignored
00701     PRInt32 i = 0;
00702     for (i=1;i<argc;i++) {
00703 #ifdef DEBUG_CMD_LINE
00704       printf("XXX argv[%d] = %s\n",i,argv[i]);
00705 #endif /* DEBUG_CMD_LINE */
00706       if (IsStartupCommand(argv[i])) {
00707 
00708         // skip over the - (or / on windows)
00709         char *command = argv[i] + 1;
00710 #ifdef XP_UNIX
00711         // unix allows -mail and --mail
00712         if ((argv[i][0] == '-') && (argv[i][1] == '-')) {
00713           command = argv[i] + 2;
00714         }
00715 #endif /* XP_UNIX */
00716 
00717         // this can fail, as someone could do -foo, where -foo is not handled
00718         rv = LaunchApplicationWithArgs((const char *)(argv[i]),
00719                                        cmdLineArgs, command,
00720                                        height, width, windowOpened);
00721         if (rv == NS_ERROR_NOT_AVAILABLE || rv == NS_ERROR_ABORT)
00722           return rv;
00723       }
00724     }
00725    // second if an URL is given in the command line
00726    // then open a browser window with the URL
00727   nsXPIDLCString urlToLoad;
00728   rv = cmdLineArgs->GetURLToLoad(getter_Copies(urlToLoad));
00729   if (NS_SUCCEEDED(rv) && !urlToLoad.IsEmpty()) {
00730     nsCOMPtr<nsICmdLineHandler> handler(
00731       do_GetService("@mozilla.org/commandlinehandler/general-startup;1?type=browser"));
00732 
00733     nsXPIDLCString chromeUrlForTask;
00734     rv = handler->GetChromeUrlForTask(getter_Copies(chromeUrlForTask));
00735 
00736     if (NS_SUCCEEDED(rv)) {
00737       // convert the cmdLine URL to Unicode
00738       nsAutoString url;
00739       NS_CopyNativeToUnicode(urlToLoad, url);
00740       rv = OpenWindow(chromeUrlForTask, url, width, height);
00741     }
00742 
00743     if (NS_SUCCEEDED(rv)) {
00744       *windowOpened = PR_TRUE;
00745     }
00746   }
00747 
00748   // third if no window is opened then apply the startup preferences
00749   if (!*windowOpened) {
00750     nsCOMPtr<nsIAppStartup> appStartup(do_GetService(NS_APPSTARTUP_CONTRACTID, &rv));
00751     if (NS_FAILED(rv))
00752       return rv;
00753     rv = appStartup->CreateStartupState(width, height, windowOpened);
00754     if (NS_FAILED(rv))
00755       return rv;
00756   }
00757   return NS_OK;
00758 }
00759 
00760 static nsresult DoOnShutdown()
00761 {
00762   nsresult rv;
00763 
00764   // save the prefs, in case they weren't saved
00765   {
00766     // scoping this in a block to force release
00767     nsCOMPtr<nsIPrefService> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
00768     NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get prefs, so unable to save them");
00769     if (NS_SUCCEEDED(rv))
00770       prefs->SavePrefFile(nsnull);
00771   }
00772 
00773   // call ShutDownCurrentProfile() so we update the last modified time of the profile
00774   {
00775     // scoping this in a block to force release
00776     nsCOMPtr<nsIProfile> profileMgr(do_GetService(NS_PROFILE_CONTRACTID, &rv));
00777     NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get profile manager, so unable to update last modified time");
00778     if (NS_SUCCEEDED(rv)) {
00779       profileMgr->ShutDownCurrentProfile(nsIProfile::SHUTDOWN_PERSIST);
00780     }
00781   }
00782 
00783   return rv;
00784 }
00785 
00786 // match OS locale
00787 static char kMatchOSLocalePref[] = "intl.locale.matchOS";
00788 
00789 nsresult
00790 getCountry(const nsAString& lc_name, nsAString& aCountry)
00791 {
00792 #ifndef MOZILLA_INTERNAL_API
00793   const PRUnichar *begin = lc_name.BeginReading();
00794   const PRUnichar *end   = lc_name.EndReading();
00795   while (begin != end) {
00796     if (*begin == '-')
00797       break;
00798     ++begin;
00799   }
00800 
00801   if (begin == end)
00802     return NS_ERROR_FAILURE;
00803 
00804   aCountry.Assign(begin + 1, end - begin);
00805 #else
00806   PRInt32 i = lc_name.FindChar('-');
00807   if (i == kNotFound)
00808     return NS_ERROR_FAILURE;
00809   aCountry = Substring(lc_name, i + 1, PR_UINT32_MAX);
00810 #endif
00811   return NS_OK;
00812 }
00813 
00814 static nsresult
00815 getUILangCountry(nsAString& aUILang, nsAString& aCountry)
00816 {
00817   nsresult     result;
00818   // get a locale service 
00819   nsCOMPtr<nsILocaleService> localeService = do_GetService(NS_LOCALESERVICE_CONTRACTID, &result);
00820   NS_ASSERTION(NS_SUCCEEDED(result),"getUILangCountry: get locale service failed");
00821 
00822   result = localeService->GetLocaleComponentForUserAgent(aUILang);
00823   NS_ASSERTION(NS_SUCCEEDED(result), "getUILangCountry: get locale component failed");
00824   result = getCountry(aUILang, aCountry);
00825   return result;
00826 }
00827 
00828 // update global locale if possible (in case when user-*.rdf can be updated)
00829 // so that any apps after this can be invoked in the UILocale and contentLocale
00830 static nsresult InstallGlobalLocale(nsICmdLineService *cmdLineArgs)
00831 {
00832     nsresult rv = NS_OK;
00833 
00834     // check the pref first
00835     nsCOMPtr<nsIPrefBranch> prefService(do_GetService(NS_PREFSERVICE_CONTRACTID));
00836     PRBool matchOS = PR_FALSE;
00837     if (prefService)
00838       prefService->GetBoolPref(kMatchOSLocalePref, &matchOS);
00839 
00840     // match os locale
00841     nsAutoString uiLang;
00842     nsAutoString country;
00843     if (matchOS) {
00844       // compute lang and region code only when needed!
00845       rv = getUILangCountry(uiLang, country);
00846     }
00847 
00848     nsXPIDLCString cmdUI;
00849     rv = cmdLineArgs->GetCmdLineValue(UILOCALE_CMD_LINE_ARG, getter_Copies(cmdUI));
00850     if (NS_SUCCEEDED(rv)){
00851         if (!cmdUI.IsEmpty()) {
00852             nsCOMPtr<nsIChromeRegistrySea> chromeRegistry = do_GetService(NS_CHROMEREGISTRY_CONTRACTID, &rv);
00853             if (chromeRegistry)
00854                 rv = chromeRegistry->SelectLocale(cmdUI, PR_FALSE);
00855         }
00856     }
00857     // match OS when no cmdline override
00858     if (cmdUI.IsEmpty() && matchOS) {
00859       nsCOMPtr<nsIChromeRegistrySea> chromeRegistry = do_GetService(NS_CHROMEREGISTRY_CONTRACTID, &rv);
00860       if (chromeRegistry) {
00861         chromeRegistry->SetRuntimeProvider(PR_TRUE);
00862         rv = chromeRegistry->SelectLocale(NS_ConvertUTF16toUTF8(uiLang), PR_FALSE);
00863       }
00864     }
00865 
00866     nsXPIDLCString cmdContent;
00867     rv = cmdLineArgs->GetCmdLineValue(CONTENTLOCALE_CMD_LINE_ARG, getter_Copies(cmdContent));
00868     if (NS_SUCCEEDED(rv)){
00869         if (!cmdContent.IsEmpty()) {
00870             nsCOMPtr<nsIChromeRegistrySea> chromeRegistry = do_GetService(NS_CHROMEREGISTRY_CONTRACTID, &rv);
00871             if(chromeRegistry)
00872                 rv = chromeRegistry->SelectLocale(cmdContent, PR_FALSE);
00873         }
00874     }
00875     // match OS when no cmdline override
00876     if (cmdContent.IsEmpty() && matchOS) {
00877       nsCOMPtr<nsIChromeRegistrySea> chromeRegistry = do_GetService(NS_CHROMEREGISTRY_CONTRACTID, &rv);
00878       if (chromeRegistry) {
00879         chromeRegistry->SetRuntimeProvider(PR_TRUE);        
00880         rv = chromeRegistry->SelectLocale(NS_ConvertUTF16toUTF8(country), PR_FALSE);
00881       }
00882     }
00883 
00884     return NS_OK;
00885 }
00886 
00887 // Use classic skin if OS has indicated that the 
00888 // current theme is being used for accessibility.
00889 static void CheckUseAccessibleSkin()
00890 {
00891     PRInt32 useAccessibilityTheme = 0;
00892 
00893     nsCOMPtr<nsILookAndFeel> lookAndFeel = do_GetService(kLookAndFeelCID);
00894     if (lookAndFeel) {
00895       lookAndFeel->GetMetric(nsILookAndFeel::eMetric_UseAccessibilityTheme, 
00896                              useAccessibilityTheme);
00897     }
00898 
00899     if (useAccessibilityTheme) {
00900       // Use classic skin, it obeys the system's accessibility theme
00901       nsCOMPtr<nsIChromeRegistrySea> chromeRegistry = do_GetService(NS_CHROMEREGISTRY_CONTRACTID);
00902       if (chromeRegistry) {
00903         chromeRegistry->SetRuntimeProvider(PR_TRUE);  // The skin change isn't permanent
00904         chromeRegistry->SelectSkin(NS_LITERAL_CSTRING("classic/1.0"), PR_TRUE);
00905       }
00906     }
00907 }
00908 
00909 static nsresult InitializeProfileService(nsICmdLineService *cmdLineArgs)
00910 {
00911     // If we are being launched in -turbo mode, we cannot show UI
00912     PRBool shouldShowUI = PR_TRUE;
00913     nsCOMPtr<nsINativeAppSupport> nativeApp;
00914     if (NS_SUCCEEDED(GetNativeAppSupport(getter_AddRefs(nativeApp))))
00915       nativeApp->GetShouldShowUI(&shouldShowUI);
00916     // If we were launched with -silent, we cannot show UI, either.
00917     if (shouldShowUI) {
00918       nsXPIDLCString arg;
00919       if (NS_SUCCEEDED(cmdLineArgs->GetCmdLineValue("-silent", getter_Copies(arg)))) {
00920         if (!arg.IsEmpty()) {
00921           shouldShowUI = PR_FALSE;
00922         }
00923       }
00924     }
00925     nsresult rv;
00926     nsCOMPtr<nsIAppStartup> appStartup(do_GetService(NS_APPSTARTUP_CONTRACTID, &rv));
00927     if (NS_FAILED(rv)) return rv;
00928     rv = appStartup->DoProfileStartup(cmdLineArgs, shouldShowUI);
00929 
00930     return rv;
00931 }
00932 
00933 // Maximum allowed / used length of alert message is 255 chars, due to restrictions on Mac.
00934 // Please make sure that file contents and fallback_alert_text are at most 255 chars.
00935 // Fallback_alert_text must be non-const, because of inplace conversion on Mac.
00936 static void ShowOSAlertFromFile(int argc, char **argv, const char *alert_filename, const char* fallback_alert_text)
00937 {
00938   char message[256] = { 0 };
00939   PRInt32 numRead = 0;
00940   const char *messageToShow = fallback_alert_text;
00941   nsresult rv;
00942   nsCOMPtr<nsILocalFile> fileName;
00943   nsCOMPtr<nsIProperties> directoryService;
00944 
00945   directoryService = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
00946   if (NS_SUCCEEDED(rv)) {
00947     rv = directoryService->Get(NS_GRE_DIR,
00948                                NS_GET_IID(nsIFile),
00949                                getter_AddRefs(fileName));
00950     if (NS_SUCCEEDED(rv) && fileName) {
00951       fileName->AppendNative(NS_LITERAL_CSTRING("res"));
00952       fileName->AppendNative(nsDependentCString(alert_filename));
00953       PRFileDesc* fd = 0;
00954       fileName->OpenNSPRFileDesc(PR_RDONLY, 0664, &fd);
00955       if (fd) {
00956         numRead = PR_Read(fd, message, sizeof(message)-1);
00957         if (numRead > 0) {
00958           message[numRead] = 0;
00959           messageToShow = message;
00960         }
00961       }
00962     }
00963   }
00964 
00965   ShowOSAlert(messageToShow);
00966 }
00967 
00968 static nsresult VerifyInstallation(int argc, char **argv)
00969 {
00970 #ifdef MOZ_XPINSTALL
00971   nsresult rv;
00972   nsCOMPtr<nsILocalFile> registryFile;
00973 
00974   nsCOMPtr<nsIProperties> directoryService =
00975            do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
00976   if (NS_FAILED(rv))
00977     return NS_OK;
00978   rv = directoryService->Get(NS_APP_INSTALL_CLEANUP_DIR,
00979                              NS_GET_IID(nsIFile),
00980                              getter_AddRefs(registryFile));
00981   if (NS_FAILED(rv) || !registryFile)
00982     return NS_ERROR_FAILURE;
00983 
00984   registryFile->AppendNative(CLEANUP_REGISTRY);
00985 
00986   PRBool exists;
00987   registryFile->Exists(&exists);
00988   if (exists)
00989   {
00990     nsCOMPtr<nsIFile> binPath;
00991     const char lastResortMessage[] = "A previous install did not complete correctly.  Finishing install.";
00992 
00993     ShowOSAlertFromFile(argc, argv, CLEANUP_MESSAGE_FILENAME.get(), lastResortMessage);
00994 
00995     nsCOMPtr<nsIFile> cleanupUtility;
00996     registryFile->Clone(getter_AddRefs(cleanupUtility));
00997     cleanupUtility->SetNativeLeafName(CLEANUP_UTIL);
00998 
00999     //Create the process framework to run the cleanup utility
01000     nsCOMPtr<nsIProcess> cleanupProcess = do_CreateInstance(NS_PROCESS_CONTRACTID);
01001     rv = cleanupProcess->Init(cleanupUtility);
01002     if (NS_SUCCEEDED(rv))
01003       rv = cleanupProcess->Run(PR_FALSE,nsnull, 0, nsnull);
01004 
01005     //We must exit because all open files must be released by the system
01006     return NS_ERROR_FAILURE;
01007   }
01008 #endif
01009   return NS_OK;
01010 }
01011 
01012 #ifdef DEBUG_warren
01013 #ifdef XP_WIN
01014 #define _CRTDBG_MAP_ALLOC
01015 #include <crtdbg.h>
01016 #endif
01017 #endif
01018 
01019 #if defined(FREEBSD)
01020 // pick up fpsetmask prototype.
01021 #include <ieeefp.h>
01022 #endif
01023 
01024 // Note: nativeApp is an owning reference that this function has responsibility
01025 //       to release.  This responsibility is delegated to the app startup service
01026 //       (see nsAppStartup::Initialize call, below).
01027 static nsresult main1(int argc, char* argv[], nsISupports *nativeApp )
01028 {
01029   nsresult rv;
01030   NS_TIMELINE_ENTER("main1");
01031   nsCOMPtr<nsISupports> nativeAppOwner(dont_AddRef(nativeApp));
01032 
01033   //----------------------------------------------------------------
01034   // First we need to check if a previous installation occured and
01035   // if so, make sure it finished and cleaned up correctly.
01036   //
01037   // If there is an xpicleanup.dat file left around, that means the
01038   // previous installation did not finish correctly. We must cleanup
01039   // before a valid mozilla can run.
01040   //
01041   // Show the user a platform-specific Alert message, then spawn the
01042   // xpicleanup utility, then exit.
01043   //----------------------------------------------------------------
01044   rv = VerifyInstallation(argc, argv);
01045   if (NS_FAILED(rv))
01046     return NS_ERROR_FAILURE;
01047 
01048 #ifdef DEBUG_warren
01049 //  _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF);
01050 #endif
01051 
01052 #ifndef XP_MAC
01053   // Unbuffer debug output (necessary for automated QA performance scripts).
01054   setbuf(stdout, 0);
01055 #endif
01056 
01057 #if defined(FREEBSD)
01058   // Disable all SIGFPE's on FreeBSD, as it has non-IEEE-conformant fp
01059   // trap behavior that trips up on floating-point tests performed by
01060   // the JS engine.  See bugzilla bug 9967 details.
01061   fpsetmask(0);
01062 #endif
01063 
01064   NS_TIMELINE_ENTER("init event service");
01065   nsCOMPtr<nsIEventQueueService> eventQService(do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv));
01066   if (NS_SUCCEEDED(rv)) {
01067     // XXX: What if this fails?
01068     rv = eventQService->CreateThreadEventQueue();
01069   }
01070   NS_TIMELINE_LEAVE("init event service");
01071 
01072   // Setup an autoreg obserer, so that we can update a progress
01073   // string in the splash screen
01074   nsCOMPtr<nsIObserverService> obsService(do_GetService("@mozilla.org/observer-service;1"));
01075   if (obsService)
01076   {
01077     nsCOMPtr<nsIObserver> splashScreenObserver(do_QueryInterface(nativeAppOwner));
01078     if (splashScreenObserver)
01079     {
01080       obsService->AddObserver(splashScreenObserver, NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID, PR_FALSE);
01081       obsService->AddObserver(splashScreenObserver, "startup_user_notifcations", PR_FALSE);
01082     }
01083   }
01084 
01085 #if XP_MAC
01086   stTSMCloser  tsmCloser;
01087 
01088   rv = InitializeMacCommandLine(argc, argv);
01089   NS_ASSERTION(NS_SUCCEEDED(rv), "Initializing AppleEvents failed");
01090 #endif
01091 
01092 #ifdef DEBUG
01093   // _Always_ autoreg if we're in a debug build, under the assumption
01094   // that people are busily modifying components and will be angry if
01095   // their changes aren't noticed.
01096   nsCOMPtr<nsIComponentRegistrar> registrar;
01097   NS_GetComponentRegistrar(getter_AddRefs(registrar));
01098   registrar->AutoRegister(nsnull);
01099   registrar = nsnull;
01100 #endif
01101 
01102   NS_TIMELINE_ENTER("startupNotifier");
01103 
01104   // Start up the core services:
01105   {
01106     // Please do not add new things to main1() - please hook into the
01107     // nsIAppStartupNotifier service.
01108     nsCOMPtr<nsIObserver> startupNotifier = do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID, &rv);
01109     if(NS_FAILED(rv))
01110       return rv;
01111     startupNotifier->Observe(nsnull, APPSTARTUP_TOPIC, nsnull);
01112   }
01113   NS_TIMELINE_LEAVE("startupNotifier");
01114 
01115   NS_TIMELINE_ENTER("cmdLineArgs");
01116 
01117   // Initialize the cmd line service
01118   nsCOMPtr<nsICmdLineService> cmdLineArgs(do_GetService(NS_COMMANDLINESERVICE_CONTRACTID, &rv));
01119   NS_ASSERTION(NS_SUCCEEDED(rv), "Could not obtain CmdLine processing service\n");
01120   if (NS_FAILED(rv))
01121     return rv;
01122 
01123   rv = cmdLineArgs->Initialize(argc, argv);
01124   NS_ASSERTION(NS_SUCCEEDED(rv), "failed to initialize command line args");
01125   if (rv == NS_ERROR_INVALID_ARG) {
01126     PrintUsage();
01127     return rv;
01128   }
01129 
01130   NS_TIMELINE_LEAVE("cmdLineArgs");
01131 
01132   NS_TIMELINE_ENTER("InstallGlobalLocale");
01133   rv = InstallGlobalLocale(cmdLineArgs);
01134   if(NS_FAILED(rv))
01135     return rv;
01136   NS_TIMELINE_LEAVE("InstallGlobalLocale");
01137 
01138   NS_TIMELINE_ENTER("appStartup");
01139 
01140   nsCOMPtr<nsIAppStartup> appStartup(do_GetService(NS_APPSTARTUP_CONTRACTID));
01141   NS_ASSERTION(appStartup, "failed to get the appstartup service");
01142 
01143   /* if we couldn't get the nsIAppStartup service, then we should hide the
01144      splash screen and return (and something is seriously screwed up) */
01145   if (!appStartup)
01146   {
01147     // See if platform supports nsINativeAppSupport.
01148     nsCOMPtr<nsINativeAppSupport> nativeAppSupport(do_QueryInterface(nativeAppOwner));
01149     if (nativeAppSupport) 
01150     {
01151       // Use that interface to remove splash screen.
01152       nativeAppSupport->HideSplashScreen();
01153     }
01154     else
01155     {
01156       // See if platform supports nsISplashScreen, instead.
01157       nsCOMPtr<nsISplashScreen> splashScreen(do_QueryInterface(nativeAppOwner));
01158       if (splashScreen)
01159       {
01160         splashScreen->Hide();
01161       }
01162     }
01163     return rv;
01164   }
01165 
01166   NS_TIMELINE_LEAVE("appStartup");
01167 
01168   NS_TIMELINE_ENTER("appStartup->Initialize");
01169 
01170   // Create the Application Shell instance...
01171   rv = appStartup->Initialize(nativeAppOwner);
01172 
01173   NS_TIMELINE_LEAVE("appStartup->Initialize");
01174 
01175   NS_ASSERTION(NS_SUCCEEDED(rv), "failed to initialize appstartup");
01176   if (NS_FAILED(rv)) return rv;
01177 
01178   nsCOMPtr<nsIWindowCreator> wcreator (do_QueryInterface(appStartup));
01179   NS_ASSERTION(wcreator, "appstartup doesn't do nsIWindowCreator?");
01180   NS_ENSURE_TRUE(wcreator, NS_ERROR_FAILURE);
01181 
01182   nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
01183   NS_ASSERTION(wwatch, "Couldn't get the window watcher!");
01184   NS_ENSURE_TRUE(wwatch, NS_ERROR_FAILURE);
01185 
01186   wwatch->SetWindowCreator(wcreator);
01187 
01188   // So we can open and close windows during startup
01189   appStartup->EnterLastWindowClosingSurvivalArea();
01190 
01191   // Initialize Profile Service here.
01192   NS_TIMELINE_ENTER("InitializeProfileService");
01193   rv = InitializeProfileService(cmdLineArgs);
01194   NS_TIMELINE_LEAVE("InitializeProfileService");
01195   if (NS_FAILED(rv)) return rv;
01196 
01197   NS_TIMELINE_ENTER("CheckUseAccessibleSkin");
01198   // Need to do this after profile service init'd
01199   // If OS accessibility theme is used, then we always load classic theme 
01200   // which follows the system appearance.
01201   CheckUseAccessibleSkin();
01202   NS_TIMELINE_LEAVE("CheckUseAccessibleSkin");
01203 
01204   NS_TIMELINE_ENTER("appStartup->CreateHiddenWindow");
01205   appStartup->CreateHiddenWindow();
01206   NS_TIMELINE_LEAVE("appStartup->CreateHiddenWindow");
01207 
01208   // This will go away once Components are handling there own commandlines
01209 
01210   PRBool windowOpened = PR_FALSE;
01211   rv = DoCommandLines(cmdLineArgs, &windowOpened);
01212   if (NS_FAILED(rv))
01213   {
01214     NS_WARNING("failed to process command line");
01215     return rv;
01216   }
01217   
01218        if (obsService)
01219   {
01220     NS_NAMED_LITERAL_STRING(userMessage, "Creating first window...");
01221     obsService->NotifyObservers(nsnull, "startup_user_notifcations", userMessage.get());
01222   }
01223   
01224 
01225   // Make sure there exists at least 1 window.
01226   NS_TIMELINE_ENTER("Ensure1Window");
01227   rv = appStartup->Ensure1Window(cmdLineArgs);
01228   NS_TIMELINE_LEAVE("Ensure1Window");
01229   NS_ASSERTION(NS_SUCCEEDED(rv), "failed to Ensure1Window");
01230   if (NS_FAILED(rv)) return rv;
01231 
01232 #if !defined(XP_MAC) && !defined(XP_MACOSX)
01233   appStartup->ExitLastWindowClosingSurvivalArea();
01234 #endif
01235 
01236 #ifdef MOZ_ENABLE_XREMOTE
01237   // if we have X remote support and we have our one window up and
01238   // running start listening for requests on the proxy window.
01239   // It will shut itself down before the event queue stops processing events.
01240   nsCOMPtr<nsIRemoteService> remoteService
01241     (do_GetService("@mozilla.org/toolkit/remote-service;1"));
01242   NS_ASSERTION(remoteService, "Couldn't create remote service?");
01243   if (remoteService) {
01244     nsCAutoString pname;
01245 
01246     nsCOMPtr<nsIProfile> pm (do_GetService(NS_PROFILE_CONTRACTID));
01247     if (pm) {
01248       nsXPIDLString name;
01249       pm->GetCurrentProfile(getter_Copies(name));
01250       if (name) {
01251         CopyUTF16toUTF8(name, pname);
01252       }
01253     }
01254 
01255     remoteService->Startup(NS_STRINGIFY(MOZ_APP_NAME), pname.IsEmpty() ? nsnull : pname.get());
01256   }
01257 #endif /* MOZ_ENABLE_XREMOTE */
01258 
01259   // remove the nativeApp as an XPCOM autoreg observer
01260   if (obsService)
01261   {
01262     nsCOMPtr<nsIObserver> splashScreenObserver(do_QueryInterface(nativeAppOwner));
01263     if (splashScreenObserver)
01264     {
01265       obsService->RemoveObserver(splashScreenObserver, NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID);
01266       obsService->RemoveObserver(splashScreenObserver, "startup_user_notifcations");
01267     }
01268   }
01269 
01270   // We are done with the native app (or splash screen) object here;
01271   // the app shell owns it now.
01272   nativeAppOwner = nsnull;
01273 
01274   // Start main event loop
01275   NS_TIMELINE_ENTER("appStartup->Run");
01276   rv = appStartup->Run();
01277   NS_TIMELINE_LEAVE("appStartup->Run");
01278   NS_ASSERTION(NS_SUCCEEDED(rv), "failed to run appstartup");
01279 
01280 #ifdef MOZ_TIMELINE
01281   // Make sure we print this out even if timeline is runtime disabled
01282   if (NS_FAILED(NS_TIMELINE_LEAVE("main1")))
01283       NS_TimelineForceMark("...main1");
01284 #endif
01285 
01286   return rv;
01287 }
01288 
01289 // English text needs to go into a dtd file.
01290 // But when this is called we have no components etc. These strings must either be
01291 // here, or in a native resource file.
01292 static void DumpHelp(char *appname)
01293 {
01294   printf("Usage: %s [ options ... ] [URL]\n", appname);
01295   printf("       where options include:\n");
01296   printf("\n");
01297 
01298 #ifdef MOZ_WIDGET_GTK
01299   /* insert gtk options above moz options, like any other gtk app
01300    *
01301    * note: this isn't a very cool way to do things -- i'd rather get
01302    * these straight from a user's gtk version -- but it seems to be
01303    * what most gtk apps do. -dr
01304    */
01305 
01306   printf("GTK options\n");
01307   printf("%s--gdk-debug=FLAGS%sGdk debugging flags to set\n", HELP_SPACER_1, HELP_SPACER_2);
01308   printf("%s--gdk-no-debug=FLAGS%sGdk debugging flags to unset\n", HELP_SPACER_1, HELP_SPACER_2);
01309   printf("%s--gtk-debug=FLAGS%sGtk+ debugging flags to set\n", HELP_SPACER_1, HELP_SPACER_2);
01310   printf("%s--gtk-no-debug=FLAGS%sGtk+ debugging flags to unset\n", HELP_SPACER_1, HELP_SPACER_2);
01311   printf("%s--gtk-module=MODULE%sLoad an additional Gtk module\n", HELP_SPACER_1, HELP_SPACER_2);
01312   printf("%s-install%sInstall a private colormap\n", HELP_SPACER_1, HELP_SPACER_2);
01313 
01314   /* end gtk toolkit options */
01315 #endif /* MOZ_WIDGET_GTK */
01316 #if MOZ_WIDGET_XLIB
01317   printf("Xlib options\n");
01318   printf("%s-display=DISPLAY%sX display to use\n", HELP_SPACER_1, HELP_SPACER_2);
01319   printf("%s-visual=VISUALID%sX visual to use\n", HELP_SPACER_1, HELP_SPACER_2);
01320   printf("%s-install_colormap%sInstall own colormap\n", HELP_SPACER_1, HELP_SPACER_2);
01321   printf("%s-sync%sMake X calls synchronous\n", HELP_SPACER_1, HELP_SPACER_2);
01322   printf("%s-no-xshm%sDon't use X shared memory extension\n", HELP_SPACER_1, HELP_SPACER_2);
01323 
01324   /* end xlib toolkit options */
01325 #endif /* MOZ_WIDGET_XLIB */
01326 #ifdef MOZ_X11
01327   printf("X11 options\n");
01328   printf("%s--display=DISPLAY%sX display to use\n", HELP_SPACER_1, HELP_SPACER_2);
01329   printf("%s--sync%sMake X calls synchronous\n", HELP_SPACER_1, HELP_SPACER_2);
01330   printf("%s--no-xshm%sDon't use X shared memory extension\n", HELP_SPACER_1, HELP_SPACER_2);
01331   printf("%s--xim-preedit=STYLE\n", HELP_SPACER_1);
01332   printf("%s--xim-status=STYLE\n", HELP_SPACER_1);
01333 #endif
01334 #ifdef XP_UNIX
01335   printf("%s--g-fatal-warnings%sMake all warnings fatal\n", HELP_SPACER_1, HELP_SPACER_2);
01336 
01337   printf("\n%s options\n", NS_STRINGIFY(MOZ_APP_DISPLAYNAME));
01338 #endif
01339 
01340   printf("%s-height <value>%sSet height of startup window to <value>.\n",HELP_SPACER_1,HELP_SPACER_2);
01341   printf("%s-h or -help%sPrint this message.\n",HELP_SPACER_1,HELP_SPACER_2);
01342   printf("%s-installer%sStart with 4.x migration window.\n",HELP_SPACER_1,HELP_SPACER_2);
01343   printf("%s-width <value>%sSet width of startup window to <value>.\n",HELP_SPACER_1,HELP_SPACER_2);
01344   printf("%s-v or -version%sPrint %s version.\n",HELP_SPACER_1,HELP_SPACER_2, appname);
01345   printf("%s-CreateProfile <profile>%sCreate <profile>.\n",HELP_SPACER_1,HELP_SPACER_2);
01346   printf("%s-P <profile>%sStart with <profile>.\n",HELP_SPACER_1,HELP_SPACER_2);
01347   printf("%s-ProfileWizard%sStart with profile wizard.\n",HELP_SPACER_1,HELP_SPACER_2);
01348   printf("%s-ProfileManager%sStart with profile manager.\n",HELP_SPACER_1,HELP_SPACER_2);
01349   printf("%s-SelectProfile%sStart with profile selection dialog.\n",HELP_SPACER_1,HELP_SPACER_2);
01350   printf("%s-UILocale <locale>%sStart with <locale> resources as UI Locale.\n",HELP_SPACER_1,HELP_SPACER_2);
01351   printf("%s-contentLocale <locale>%sStart with <locale> resources as content Locale.\n",HELP_SPACER_1,HELP_SPACER_2);
01352 #if defined(XP_WIN32) || defined(XP_OS2)
01353   printf("%s-console%sStart %s with a debugging console.\n",HELP_SPACER_1,HELP_SPACER_2,NS_STRINGIFY(MOZ_APP_DISPLAYNAME));
01354 #endif
01355 #ifdef MOZ_ENABLE_XREMOTE
01356   printf("%s-remote <command>%sExecute <command> in an already running\n"
01357          "%s%s process.  For more info, see:\n"
01358          "\n%shttp://www.mozilla.org/unix/remote.html\n\n",
01359          HELP_SPACER_1,HELP_SPACER_1,HELP_SPACER_4,NS_STRINGIFY(MOZ_APP_DISPLAYNAME),HELP_SPACER_2);
01360   printf("%s-splash%sEnable splash screen.\n",HELP_SPACER_1,HELP_SPACER_2);
01361 #else
01362   printf("%s-nosplash%sDisable splash screen.\n",HELP_SPACER_1,HELP_SPACER_2);
01363 #if defined(XP_WIN) || defined(XP_OS2)
01364   printf("%s-quiet%sDisable splash screen.\n",HELP_SPACER_1,HELP_SPACER_2);
01365 #endif
01366 #endif
01367 
01368   // this works, but only after the components have registered.  so if you drop in a new command line handler, -help
01369   // won't not until the second run.
01370   // out of the bug, because we ship a component.reg file, it works correctly.
01371   DumpArbitraryHelp();
01372 }
01373 
01374 
01375 static nsresult DumpVersion(char *appname)
01376 {
01377   nsresult rv = NS_OK;
01378   long buildID = NS_BUILD_ID;  // 10-digit number
01379 
01380   printf("%s %s, Copyright (c) 2003-2008 mozilla.org", NS_STRINGIFY(MOZ_APP_DISPLAYNAME), NS_STRINGIFY(MOZ_APP_VERSION));
01381 
01382   if(buildID) {
01383     printf(", build %u\n", (unsigned int)buildID);
01384   } else {
01385     printf(" <developer build>\n");
01386   }
01387 
01388   return rv;
01389 }
01390 
01391 #ifdef MOZ_ENABLE_XREMOTE
01392 // use int here instead of a PR type since it will be returned
01393 // from main - just to keep types consistent
01394 static int HandleRemoteArguments(int argc, char* argv[], PRBool *aArgUsed)
01395 {
01396   int i = 0;
01397 
01398   const char *remote = 0;
01399   const char *profile = 0;
01400   const char *program = 0;
01401   const char *username = 0;
01402 
01403   for (i=1; i < argc; i++) {
01404     if (PL_strcasecmp(argv[i], "-remote") == 0) {
01405       // someone used a -remote flag
01406       *aArgUsed = PR_TRUE;
01407       // check to make sure there's another arg
01408       if (argc-1 == i) {
01409         PR_fprintf(PR_STDERR, "Error: -remote requires an argument\n");
01410         return 1;
01411       }
01412 
01413       // Get the remote argument and advance past it.
01414       remote = argv[++i];
01415     }
01416     else if (PL_strcasecmp(argv[i], "-p") == 0) {
01417       // someone used the -p <profile> flag - save the contents
01418       if (argc-1 == i) {
01419         continue;
01420       }
01421 
01422       // Get the argument
01423       profile = argv[++i];
01424     }
01425     else if (PL_strcasecmp(argv[i], "-a") == 0) {
01426       // someone used the -a <application> flag - save the contents
01427       if (argc-1 == i) {
01428         continue;
01429       }
01430 
01431       // Get the argument
01432       program = argv[++i];
01433     }
01434     else if (PL_strcasecmp(argv[i], "-u") == 0) {
01435       // someone used the -u <username> flag - save the contents
01436       if (argc-1 == i) {
01437         continue;
01438       }
01439 
01440       // Get the argument
01441       username = argv[++i];
01442     }
01443   }
01444 
01445   if (!remote)
01446     return 0; // No remote argument == success
01447 
01448   // try to get the X remote client
01449   XRemoteClient client;
01450 
01451   nsresult rv;
01452   // try to init - connects to the X server and stuff
01453   rv = client.Init();
01454   if (NS_FAILED(rv)) {
01455     PR_fprintf(PR_STDERR, "Error: Failed to connect to X server.\n");
01456     return 1;
01457   }
01458 
01459   // Make sure to set a username if possible
01460   if (!username) {
01461     username = PR_GetEnv("LOGNAME");
01462   }
01463 
01464   // Same with the program name
01465   if (!program) {
01466     program = NS_STRINGIFY(MOZ_APP_NAME);
01467   }
01468 
01469   char *response = NULL;
01470   PRBool success = PR_FALSE;
01471   rv = client.SendCommand(program, username, profile, remote,
01472                           &response, &success);
01473 
01474   // did the command fail?
01475   if (NS_FAILED(rv)) {
01476     PR_fprintf(PR_STDERR, "Error: Failed to send command: ");
01477     if (response) {
01478       PR_fprintf(PR_STDERR, "%s\n", response);
01479       free(response);
01480     }
01481     else {
01482       PR_fprintf(PR_STDERR, "No response included.\n");
01483     }
01484 
01485     return 1;
01486   }
01487 
01488   // was there no window running?
01489   if (!success) {
01490     PR_fprintf(PR_STDERR, "Error: No running window found.\n");
01491     return 2;
01492   }
01493 
01494   // success
01495   return 0;
01496 }
01497 #endif /* XP_UNIX */
01498 
01499 static PRBool HandleDumpArguments(int argc, char* argv[])
01500 {
01501   for (int i=1; i<argc; i++) {
01502     if ((PL_strcasecmp(argv[i], "-h") == 0)
01503         || (PL_strcasecmp(argv[i], "-help") == 0)
01504 #if defined(XP_UNIX) || defined(XP_BEOS)
01505         || (PL_strcasecmp(argv[i], "--help") == 0)
01506 #endif /* XP_UNIX || XP_BEOS*/
01507 #if defined(XP_WIN) || defined(XP_OS2)
01508         || (PL_strcasecmp(argv[i], "/h") == 0)
01509         || (PL_strcasecmp(argv[i], "/help") == 0)
01510         || (PL_strcasecmp(argv[i], "/?") == 0)
01511 #endif /* XP_WIN || XP_OS2 */
01512       ) {
01513       DumpHelp(argv[0]);
01514       return PR_TRUE;
01515     }
01516     if ((PL_strcasecmp(argv[i], "-v") == 0)
01517         || (PL_strcasecmp(argv[i], "-version") == 0)
01518 #if defined(XP_UNIX) || defined(XP_BEOS)
01519         || (PL_strcasecmp(argv[i], "--version") == 0)
01520 #endif /* XP_UNIX || XP_BEOS */
01521 #if defined(XP_WIN) || defined(XP_OS2)
01522         || (PL_strcasecmp(argv[i], "/v") == 0)
01523         || (PL_strcasecmp(argv[i], "/version") == 0)
01524 #endif /* XP_WIN || XP_OS2 */
01525       ) {
01526       DumpVersion(argv[0]);
01527       return PR_TRUE;
01528     }
01529   }
01530 
01531   return PR_FALSE;
01532 }
01533 
01534 
01535 static PRBool GetWantSplashScreen(int argc, char* argv[])
01536 {
01537   int i;
01538   PRBool dosplash;
01539   // We can't use the command line service here because it isn't running yet
01540 #if defined(XP_UNIX) && !defined(MOZ_WIDGET_PHOTON) 
01541   dosplash = PR_FALSE;
01542   for (i=1; i<argc; i++)
01543     if ((PL_strcasecmp(argv[i], "-splash") == 0)
01544         || (PL_strcasecmp(argv[i], "--splash") == 0))
01545       dosplash = PR_TRUE;
01546 #else
01547   dosplash = PR_TRUE;
01548   for (i=1; i<argc; i++)
01549     if ((PL_strcasecmp(argv[i], "-nosplash") == 0)
01550 #ifdef XP_BEOS
01551               || (PL_strcasecmp(argv[i], "--nosplash") == 0)
01552 #endif /* XP_BEOS */
01553 #if defined(XP_WIN) || defined(XP_OS2)
01554         || (PL_strcasecmp(argv[i], "/nosplash") == 0)
01555 #endif /* XP_WIN || XP_OS2 */
01556        ) {
01557       dosplash = PR_FALSE;
01558        }
01559 #endif
01560 
01561   return dosplash;
01562 }
01563 
01564 #if defined(XP_OS2)
01565 // because we use early returns, we use a stack-based helper to un-set the OS2 FP handler
01566 class ScopedFPHandler {
01567 private:
01568   EXCEPTIONREGISTRATIONRECORD excpreg;
01569 
01570 public:
01571   ScopedFPHandler() { PR_OS2_SetFloatExcpHandler(&excpreg); }
01572   ~ScopedFPHandler() { PR_OS2_UnsetFloatExcpHandler(&excpreg); }
01573 };
01574 #endif
01575 
01576 int main(int argc, char* argv[])
01577 {
01578 #ifdef XP_WIN32
01579   if (argc > 4 && !strcmp(argv[1], "-osint"))
01580     return 1;
01581 #endif
01582 
01583   NS_TIMELINE_MARK("enter main");
01584   int i; //Moved here due to portability guideline 20. See bug 258055
01585 
01586 #ifdef XP_WIN32
01587   // Suppress the "DLL Foo could not be found" dialog, such that if dependent
01588   // libraries (such as GDI+) are not preset, we gracefully fail to load those
01589   // XPCOM components, instead of being ungraceful.
01590   SetErrorMode(SEM_FAILCRITICALERRORS);
01591 
01592 #ifdef DEBUG
01593   // Disable small heap allocator to get heapwalk() giving us
01594   // accurate heap numbers. Win2k non-debug does not use small heap allocator.
01595   // Win2k debug seems to be still using it.
01596   // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt__set_sbh_threshold.asp
01597   _set_sbh_threshold(0);
01598 #endif
01599 #endif
01600 
01601 #if defined(XP_UNIX) || defined(XP_BEOS)
01602   InstallUnixSignalHandlers(argv[0]);
01603 #endif
01604 
01605 #ifdef MOZ_ACCESSIBILITY_ATK
01606   // Reset GTK_MODULES, strip atk-bridge if exists
01607   // Mozilla will load libatk-bridge.so later if necessary
01608   const char* gtkModules = PR_GetEnv("GTK_MODULES");
01609   if (gtkModules && *gtkModules) {
01610     nsCString gtkModulesStr(gtkModules);
01611     gtkModulesStr.ReplaceSubstring("atk-bridge", "");
01612     char* expr = PR_smprintf("GTK_MODULES=%s", gtkModulesStr.get());
01613     if (expr)
01614       PR_SetEnv(expr);
01615     // We intentionally leak |expr| here since it is required by PR_SetEnv.
01616   }
01617 #endif
01618 
01619 #if defined(XP_OS2)
01620   __pargc = &argc;
01621   __argv = argv;
01622 
01623   PRBool StartOS2App(int aArgc, char **aArgv);
01624   if (!StartOS2App(argc, argv))
01625     return 1;
01626 
01627   ScopedFPHandler handler;
01628 #endif /* XP_OS2 */
01629 
01630 #if defined(XP_MACOSX)
01631   InitializeMacOSXApp(argc, argv);
01632 #endif
01633 
01634   // Handle -help and -version command line arguments.
01635   // They should% return quick, so we deal with them here.
01636   if (HandleDumpArguments(argc, argv))
01637     return 0;
01638 
01639 #ifdef NS_TRACE_MALLOC
01640   argc = NS_TraceMallocStartupArgs(argc, argv);
01641 #endif
01642 
01643 #ifdef MOZ_X11
01644   /* Init threadsafe mode of Xlib API on demand
01645    * (currently this is only for testing, future builds may use this by
01646    * default) */
01647   PRBool x11threadsafe = PR_FALSE;
01648   for (i=1; i<argc; i++) {
01649     if (PL_strcmp(argv[i], "-xinitthreads") == 0) {
01650       x11threadsafe = PR_TRUE;
01651       break;
01652     }
01653   }
01654 
01655   if (PR_GetEnv("MOZILLA_X11_XINITTHREADS")) {
01656     x11threadsafe = PR_TRUE;
01657   }
01658   
01659   if (x11threadsafe) {
01660     if (XInitThreads() == False) {
01661       fprintf(stderr, "%s: XInitThreads failure.", argv[0]);
01662       exit(EXIT_FAILURE);
01663     }
01664   }
01665 #endif /* MOZ_X11 */
01666 
01667 #if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_GTK2)
01668   // setup for private colormap.  Ideally we'd like to do this
01669   // in nsAppShell::Create, but we need to get in before gtk
01670   // has been initialized to make sure everything is running
01671   // consistently.
01672 #if defined(MOZ_WIDGET_GTK2)
01673   g_thread_init(NULL);
01674 #endif
01675   for (i=1; i<argc; i++)
01676     if ((PL_strcasecmp(argv[i], "-install") == 0)
01677         || (PL_strcasecmp(argv[i], "--install") == 0)) {
01678       gdk_rgb_set_install(TRUE);
01679       break;
01680     }
01681 
01682   // Initialize GTK+1/2 here for splash
01683 #if defined(MOZ_WIDGET_GTK)
01684   gtk_set_locale();
01685 #endif
01686   gtk_init(&argc, &argv);
01687 
01688   gtk_widget_set_default_visual(gdk_rgb_get_visual());
01689   gtk_widget_set_default_colormap(gdk_rgb_get_cmap());
01690 #endif /* MOZ_WIDGET_GTK || MOZ_WIDGET_GTK2 */
01691 
01692 #if defined(MOZ_WIDGET_QT)
01693   QApplication qapp(argc, argv);
01694 #endif
01695 
01696 // #if defined(MOZ_WIDGET_XLIB)
01697 // XXXtimeless fix me! Because we don't have external shared libs holding global
01698 // refs, there isn't an easy way to get a Display from here to the widget component.
01699 // #endif
01700     
01701   // Call the code to install our handler
01702 #ifdef MOZ_JPROF
01703   setupProfilingStuff();
01704 #endif
01705     
01706 
01707 #ifdef XPCOM_GLUE
01708   NS_TIMELINE_MARK("GRE_Startup...");
01709   nsresult rv = GRE_Startup();
01710   NS_TIMELINE_MARK("...GRE_Startup done");
01711   if (NS_FAILED(rv)) {
01712        // We should be displaying a dialog here with the reason why we failed.
01713     NS_WARNING("GRE_Startup failed");
01714     return 1;
01715   }
01716 #else
01717   NS_TIMELINE_MARK("NS_InitXPCOM3...");
01718   nsresult rv = NS_InitXPCOM3(nsnull, nsnull, nsnull,
01719                               kPStaticModules, kStaticModuleCount);
01720   NS_TIMELINE_MARK("...NS_InitXPCOM3 done");
01721   if (NS_FAILED(rv)) {
01722     // We should be displaying a dialog here with the reason why we failed.
01723     NS_WARNING("NS_InitXPCOM3 failed");
01724     return 1;
01725   }
01726 #endif
01727 
01728 
01729   // Try to allocate "native app support."
01730   // Note: this object is not released here.  It is passed to main1 which
01731   //       has responsibility to release it.
01732   nsINativeAppSupport *nativeApp = 0;
01733   rv = NS_CreateNativeAppSupport(&nativeApp);
01734 
01735   // See if we can run.
01736   if (nativeApp)
01737   {
01738     PRBool canRun = PR_FALSE;
01739     rv = nativeApp->Start(&canRun);
01740     if (!canRun) {
01741         return 1;
01742     }
01743   } else {
01744     // If platform doesn't implement nsINativeAppSupport, fall
01745     // back to old method.
01746     if (!NS_CanRun())
01747       return 1;
01748   }
01749   // Note: this object is not released here.  It is passed to main1 which
01750   //       has responsibility to release it.
01751   nsISplashScreen *splash = 0;
01752   PRBool dosplash = GetWantSplashScreen(argc, argv);
01753 
01754   if (dosplash && !nativeApp) {
01755     // If showing splash screen and platform doesn't implement
01756     // nsINativeAppSupport, then use older nsISplashScreen interface.
01757     rv = NS_CreateSplashScreen(&splash);
01758     NS_ASSERTION(NS_SUCCEEDED(rv), "NS_CreateSplashScreen failed");
01759   }
01760   // If the platform has a splash screen, show it ASAP.
01761   if (dosplash && nativeApp) {
01762     nativeApp->ShowSplashScreen();
01763   } else if (splash) {
01764     splash->Show();
01765   }
01766 
01767 #ifdef MOZ_ENABLE_XREMOTE
01768   // handle -remote now that xpcom is fired up
01769   int remoterv;
01770   PRBool argused = PR_FALSE;
01771   // argused will be true if someone tried to use a -remote flag.  We
01772   // always exit in that case.
01773   remoterv = HandleRemoteArguments(argc, argv, &argused);
01774 
01775   if (argused) {
01776 #ifdef XPCOM_GLUE
01777     GRE_Shutdown();
01778 #else
01779     NS_ShutdownXPCOM(nsnull);
01780 #endif
01781     return remoterv;
01782   }
01783 #endif
01784 
01785   nsresult mainResult = main1(argc, argv, nativeApp ? (nsISupports*)nativeApp : (nsISupports*)splash);
01786 
01787   /* if main1() didn't succeed, then don't bother trying to shut down clipboard, etc */
01788   if (NS_SUCCEEDED(mainResult)) {
01789     rv = DoOnShutdown();
01790     NS_ASSERTION(NS_SUCCEEDED(rv), "DoOnShutdown failed");
01791   }
01792 #ifdef XPCOM_GLUE
01793   rv = GRE_Shutdown();
01794   NS_ASSERTION(NS_SUCCEEDED(rv), "GRE_Shutdown failed");
01795 #else
01796   rv = NS_ShutdownXPCOM(nsnull);
01797   NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed");
01798 #endif
01799 
01800   return TranslateReturnValue(mainResult);
01801 }
01802 
01803 #if defined( XP_WIN ) && defined( WIN32 ) && !defined(__GNUC__)
01804 // We need WinMain in order to not be a console app.  This function is
01805 // unused if we are a console application.
01806 int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR args, int)
01807 {
01808     // Do the real work.
01809     return main(__argc, __argv);
01810 }
01811 #endif // XP_WIN && WIN32