source: trunk/third/mozilla/xpfe/bootstrap/nsAppRunner.cpp @ 19518

Revision 19518, 51.4 KB checked in by rbasch, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r19517, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: NPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Netscape Public License
6 * Version 1.1 (the "License"); you may not use this file except in
7 * compliance with the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/NPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is Mozilla Communicator client code.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
24 *
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the NPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the NPL, the GPL or the LGPL.
36 *
37 * ***** END LICENSE BLOCK ***** */
38
39
40#ifdef XPCOM_GLUE
41#include "nsXPCOMGlue.h"
42#endif
43
44#include "nsIServiceManager.h"
45#include "nsIComponentManager.h"
46#include "nsIGenericFactory.h"
47#include "nsIComponentRegistrar.h"
48
49#include "nsIPref.h"
50#include "nsILocaleService.h"
51#include "plevent.h"
52#include "prmem.h"
53#include "prnetdb.h"
54
55#include "nsCOMPtr.h"
56#include "nsIAppShell.h"
57#include "nsICmdLineService.h"
58#include "nsIAppShellService.h"
59#include "nsIAppStartupNotifier.h"
60#include "nsIObserverService.h"
61#include "nsAppShellCIDs.h"
62#include "prprf.h"
63#include "nsCRT.h"
64#include "nsIDirectoryService.h"
65#include "nsAppDirectoryServiceDefs.h"
66#include "nsIWindowMediator.h"
67#include "nsIDOMWindowInternal.h"
68#include "nsIClipboard.h"
69#include "nsXPCOM.h"
70#include "nsISupportsPrimitives.h"
71#include "nsICmdLineHandler.h"
72#include "nsICategoryManager.h"
73#include "nsXPIDLString.h"
74#include "nsIXULWindow.h"
75#include "nsIChromeRegistry.h"
76#include "nsIContentHandler.h"
77#include "nsIEventQueueService.h"
78#include "nsDirectoryServiceDefs.h"
79#include "nsBuildID.h"
80#include "nsWindowCreator.h"
81#include "nsIWindowWatcher.h"
82#include "nsProcess.h"
83#include "nsILocalFile.h"
84
85#ifdef MOZ_XPINSTALL
86#include "InstallCleanupDefines.h"
87#include "nsISoftwareUpdate.h"
88#endif
89
90// Interfaces Needed
91#include "nsIXULWindow.h"
92#include "nsIWebBrowserChrome.h"
93#include "nsIDocShell.h"
94
95// for X remote support
96#ifdef MOZ_ENABLE_XREMOTE
97#include "nsXRemoteClientCID.h"
98#include "nsIXRemoteClient.h"
99#include "nsIXRemoteService.h"
100#endif
101
102// see DoOnShutdown()
103#include "nsIProfile.h"
104
105#ifdef NS_TRACE_MALLOC
106#include "nsTraceMalloc.h"
107#endif
108
109#if defined(DEBUG) && defined(XP_WIN32)
110#include <malloc.h>
111#endif
112
113#if defined (XP_MACOSX)
114#include <Processes.h>
115#endif
116
117#include "nsITimelineService.h"
118
119#if defined(DEBUG_pra)
120#define DEBUG_CMD_LINE
121#endif
122
123static NS_DEFINE_CID(kWindowMediatorCID, NS_WINDOWMEDIATOR_CID);
124static NS_DEFINE_CID(kIProcessCID, NS_PROCESS_CID);
125
126#define UILOCALE_CMD_LINE_ARG "-UILocale"
127#define CONTENTLOCALE_CMD_LINE_ARG "-contentLocale"
128
129extern "C" void ShowOSAlert(const char* aMessage);
130
131#define HELP_SPACER_1   "\t"
132#define HELP_SPACER_2   "\t\t"
133#define HELP_SPACER_4   "\t\t\t\t"
134
135#ifdef DEBUG
136#include "prlog.h"
137#endif
138
139#ifdef MOZ_JPROF
140#include "jprof.h"
141#endif
142
143// on x86 linux, the current builds of some popular plugins (notably
144// flashplayer and real) expect a few builtin symbols from libgcc
145// which were available in some older versions of gcc.  However,
146// they're _NOT_ available in newer versions of gcc (eg 3.1), so if
147// we want those plugin to work with a gcc-3.1 built binary, we need
148// to provide these symbols.  MOZ_ENABLE_OLD_ABI_COMPAT_WRAPPERS defaults
149// to true on x86 linux, and false everywhere else.
150//
151// The fact that the new and free operators are mismatched
152// mirrors the way the original functions in egcs 1.1.2 worked.
153
154#ifdef MOZ_ENABLE_OLD_ABI_COMPAT_WRAPPERS
155
156extern "C" {
157
158# ifndef HAVE___BUILTIN_VEC_NEW
159  void *__builtin_vec_new(size_t aSize, const std::nothrow_t &aNoThrow) throw()
160  {
161    return ::operator new(aSize, aNoThrow);
162  }
163# endif
164
165# ifndef HAVE___BUILTIN_VEC_DELETE
166  void __builtin_vec_delete(void *aPtr, const std::nothrow_t &) throw ()
167  {
168    if (aPtr) {
169      free(aPtr);
170    }
171  }
172# endif
173
174# ifndef HAVE___BUILTIN_NEW
175        void *__builtin_new(int aSize)
176  {
177    return malloc(aSize);
178  }
179# endif
180
181# ifndef HAVE___BUILTIN_DELETE
182        void __builtin_delete(void *aPtr)
183  {
184    free(aPtr);
185  }
186# endif
187
188# ifndef HAVE___PURE_VIRTUAL
189  void __pure_virtual(void) {
190    extern void __cxa_pure_virtual(void);
191
192    __cxa_pure_virtual();
193  }
194# endif
195}
196#endif
197
198#ifdef _BUILD_STATIC_BIN
199#include "nsStaticComponent.h"
200nsresult PR_CALLBACK
201app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
202#endif
203
204#if defined(XP_UNIX) || defined(XP_BEOS)
205  extern void InstallUnixSignalHandlers(const char *ProgramName);
206#endif
207
208#if defined(XP_OS2)
209/* Adding globals that OS/2 doesn't have so we can port the DDE code */
210char **__argv;
211int   __argc;
212#endif /* XP_OS2 */
213
214#if defined(XP_BEOS)
215
216#include <AppKit.h>
217#include <AppFileInfo.h>
218
219class nsBeOSApp : public BApplication
220{
221public:
222  nsBeOSApp(sem_id sem)
223  : BApplication(GetAppSig()), init(sem)
224  {
225  }
226
227  void ReadyToRun(void)
228  {
229    release_sem(init);
230  }
231
232  static int32 Main(void *args)
233  {
234    nsBeOSApp *app = new nsBeOSApp((sem_id)args);
235    if (nsnull == app)
236      return B_ERROR;
237    return app->Run();
238  }
239
240private:
241  char *GetAppSig(void)
242  {
243    app_info appInfo;
244    BFile file;
245    BAppFileInfo appFileInfo;
246    image_info info;
247    int32 cookie = 0;
248    static char sig[B_MIME_TYPE_LENGTH];
249
250    sig[0] = 0;
251    if (get_next_image_info(0, &cookie, &info) != B_OK ||
252        file.SetTo(info.name, B_READ_ONLY) != B_OK ||
253        appFileInfo.SetTo(&file) != B_OK ||
254        appFileInfo.GetSignature(sig) != B_OK)
255    {
256      return "application/x-vnd.Mozilla";
257    }
258    return sig;
259  }
260
261  sem_id init;
262};
263
264static nsresult InitializeBeOSApp(void)
265{
266  nsresult rv = NS_OK;
267
268  sem_id initsem = create_sem(0, "beapp init");
269  if (initsem < B_OK)
270    return NS_ERROR_FAILURE;
271
272  thread_id tid = spawn_thread(nsBeOSApp::Main, "BApplication", B_NORMAL_PRIORITY, (void *)initsem);
273  if (tid < B_OK || B_OK != resume_thread(tid))
274    rv = NS_ERROR_FAILURE;
275
276  if (B_OK != acquire_sem(initsem))
277    rv = NS_ERROR_FAILURE;
278  if (B_OK != delete_sem(initsem))
279    rv = NS_ERROR_FAILURE;
280
281  return rv;
282}
283
284#endif // XP_BEOS
285
286#if defined(XP_MAC)
287
288#include "macstdlibextras.h"
289#include <TextServices.h>
290
291// Set up the toolbox and (if DEBUG) the console.  Do this in a static initializer,
292// to make it as unlikely as possible that somebody calls printf() before we get initialized.
293static struct MacInitializer { MacInitializer() { InitializeMacToolbox(); } } gInitializer;
294
295// Initialize profile services for both standalone and regular profiles
296static nsresult InitializeProfileService(nsICmdLineService *cmdLineArgs);
297
298// Install global locale if possible
299static nsresult InstallGlobalLocale(nsICmdLineService *cmdLineArgs);
300static nsresult getUILangCountry(nsAString& aUILang, nsAString& aCountry);
301
302class stTSMCloser
303{
304public:
305        stTSMCloser()
306  {
307    // TSM is initialized in InitializeMacToolbox
308  };
309
310        ~stTSMCloser()
311        {
312#if !TARGET_CARBON
313                (void)CloseTSMAwareApplication();
314#endif
315        }
316};
317#endif // XP_MAC
318
319#if defined(XP_MACOSX)
320
321static void InitializeMacOSXApp(int argc, char* argv[])
322{
323  // use the location of the executable to learn where everything is, this
324  // is because the current working directory is ill-defined when the
325  // application is double-clicked from the Finder.
326  char* path = strdup(argv[0]);
327  char* lastSlash = strrchr(path, '/');
328  if (lastSlash) {
329    *lastSlash = '\0';
330    setenv("MOZILLA_FIVE_HOME", path, 1);
331  }
332  free(path);
333}
334
335#endif /* XP_MACOSX */
336
337#if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_GTK2)
338#include <gtk/gtk.h>
339#endif //MOZ_WIDGET_GTK || MOZ_WIDGET_GTK2
340
341/* Define Class IDs */
342static NS_DEFINE_CID(kAppShellServiceCID,   NS_APPSHELL_SERVICE_CID);
343static NS_DEFINE_CID(kCmdLineServiceCID,    NS_COMMANDLINE_SERVICE_CID);
344
345#include "nsNativeAppSupport.h"
346
347/*********************************************/
348// Default implemenations for nativeAppSupport
349// If your platform implements these functions if def out this code.
350#if !defined(MOZ_WIDGET_COCOA) && !defined(MOZ_WIDGET_PHOTON) && !defined( XP_WIN) && !defined(XP_OS2) && !defined( XP_BEOS ) && !defined(MOZ_WIDGET_GTK) && !defined(MOZ_WIDGET_GTK2)
351
352nsresult NS_CreateSplashScreen(nsISplashScreen **aResult)
353{
354    nsresult rv = NS_OK;
355    if (aResult) {
356        *aResult = 0;
357    } else {
358        rv = NS_ERROR_NULL_POINTER;
359    }
360    return rv;
361}
362
363PRBool NS_CanRun()
364{
365        return PR_TRUE;
366}
367#endif
368
369/*********************************************/
370// Default implementation for new and improved
371// native app support.  If your platform
372// implements nsINativeAppSupport then implement
373// this function and if def out this code.
374//
375// Note: For now, the default imiplementation returns 0 and
376//       the code that calls this will defalt to use the old
377//       nsISplashScreen interface directly.  At some point
378//       this function will return an instance of
379//       nsNativeAppSupportBase which will use the older
380//       "splash screen" interface.  The code below will
381//       then rely on nsINativeAppSupport and its use of
382//       nsISplashScreen will be removed.
383//
384
385#if !defined(XP_WIN) && !defined(XP_OS2) && !defined(MOZ_WIDGET_GTK) && !defined(MOZ_WIDGET_GTK2) && !defined(XP_MAC) && (!defined(XP_MACOSX) || defined(MOZ_WIDGET_COCOA))
386
387nsresult NS_CreateNativeAppSupport(nsINativeAppSupport **aResult)
388{
389    nsresult rv = NS_OK;
390    if (aResult) {
391        *aResult = 0;
392    } else {
393        rv = NS_ERROR_NULL_POINTER;
394    }
395    return rv;
396}
397
398#endif
399
400static nsresult GetNativeAppSupport(nsINativeAppSupport** aNativeApp)
401{
402    NS_ENSURE_ARG_POINTER(aNativeApp);
403    *aNativeApp = nsnull;
404
405    nsCOMPtr<nsIAppShellService> appShellService(do_GetService(kAppShellServiceCID));
406    if (appShellService)
407        appShellService->GetNativeAppSupport(aNativeApp);
408
409    return *aNativeApp ? NS_OK : NS_ERROR_FAILURE;
410}
411
412/*
413 * This routine translates the nsresult into a platform specific return
414 * code for the application...
415 */
416static int TranslateReturnValue(nsresult aResult)
417{
418  if (NS_SUCCEEDED(aResult)) {
419    return 0;
420  }
421  return 1;
422}
423
424#ifdef XP_MAC
425#include "nsCommandLineServiceMac.h"
426#endif
427
428static void
429PrintUsage(void)
430{
431  fprintf(stderr, "Usage: apprunner <url>\n");
432  fprintf(stderr, "\t<url>:  a fully defined url string like http:// etc..\n");
433}
434
435static nsresult OpenWindow(const nsAFlatCString& aChromeURL,
436                           const nsAFlatString& aAppArgs,
437                           PRInt32 aWidth, PRInt32 aHeight);
438
439static nsresult OpenWindow(const nsAFlatCString& aChromeURL,
440                           const nsAFlatString& aAppArgs)
441{
442  return OpenWindow(aChromeURL, aAppArgs,
443                    nsIAppShellService::SIZE_TO_CONTENT,
444                    nsIAppShellService::SIZE_TO_CONTENT);
445}
446
447static nsresult OpenWindow(const nsAFlatCString& aChromeURL,
448                           PRInt32 aWidth, PRInt32 aHeight)
449{
450  return OpenWindow(aChromeURL, NS_LITERAL_STRING(""), aWidth, aHeight);
451}
452
453static nsresult OpenWindow(const nsAFlatCString& aChromeURL,
454                           const nsAFlatString& aAppArgs,
455                           PRInt32 aWidth, PRInt32 aHeight)
456{
457
458#ifdef DEBUG_CMD_LINE
459  printf("OpenWindow(%s, %s, %d, %d)\n", aChromeURL.get(),
460                                         NS_ConvertUCS2toUTF8(aAppArgs).get(),
461                                         aWidth, aHeight);
462#endif /* DEBUG_CMD_LINE */
463
464  nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
465  nsCOMPtr<nsISupportsString> sarg(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID));
466  if (!wwatch || !sarg)
467    return NS_ERROR_FAILURE;
468
469  // Make sure a profile is selected.
470
471  // We need the native app support object, which we get from
472  // the app shell service.  If this fails, we still proceed.
473  // That's because some platforms don't have a native app
474  // support implementation.  On those platforms, "ensuring a
475  // profile" is moot (because they don't support "-turbo",
476  // basically).  Specifically, because they don't do turbo, they will
477  // *always* have a profile selected.
478  nsCOMPtr<nsIAppShellService> appShell(do_GetService("@mozilla.org/appshell/appShellService;1"));
479  nsCOMPtr <nsICmdLineService> cmdLine(do_GetService("@mozilla.org/appshell/commandLineService;1"));
480  if (appShell && cmdLine)
481  {
482    nsCOMPtr<nsINativeAppSupport> nativeApp;
483    if (NS_SUCCEEDED(appShell->GetNativeAppSupport(getter_AddRefs(nativeApp))))
484    {
485      // Make sure profile has been selected.
486      // At this point, we have to look for failure.  That
487      // handles the case where the user chooses "Exit" on
488      // the profile manager window.
489      if (NS_FAILED(nativeApp->EnsureProfile(cmdLine)))
490        return NS_ERROR_NOT_INITIALIZED;
491    }
492  }
493
494  sarg->SetData(aAppArgs);
495
496  nsCAutoString features("chrome,dialog=no,all");
497  if (aHeight != nsIAppShellService::SIZE_TO_CONTENT) {
498    features.Append(",height=");
499    features.AppendInt(aHeight);
500  }
501  if (aWidth != nsIAppShellService::SIZE_TO_CONTENT) {
502    features.Append(",width=");
503    features.AppendInt(aWidth);
504  }
505
506#ifdef DEBUG_CMD_LINE
507  printf("features: %s...\n", features.get());
508#endif /* DEBUG_CMD_LINE */
509
510  nsCOMPtr<nsIDOMWindow> newWindow;
511  return wwatch->OpenWindow(0, aChromeURL.get(), "_blank",
512                            features.get(), sarg,
513                            getter_AddRefs(newWindow));
514}
515
516static void DumpArbitraryHelp()
517{
518  nsresult rv;
519  nsCOMPtr<nsICategoryManager> catman(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv));
520  if(NS_SUCCEEDED(rv) && catman) {
521    nsCOMPtr<nsISimpleEnumerator> e;
522    rv = catman->EnumerateCategory(COMMAND_LINE_ARGUMENT_HANDLERS, getter_AddRefs(e));
523    if(NS_SUCCEEDED(rv) && e) {
524      while (PR_TRUE) {
525        nsCOMPtr<nsISupportsCString> catEntry;
526        rv = e->GetNext(getter_AddRefs(catEntry));
527        if (NS_FAILED(rv) || !catEntry) break;
528
529        nsCAutoString entryString;
530        rv = catEntry->GetData(entryString);
531        if (NS_FAILED(rv) || entryString.IsEmpty()) break;
532
533        nsXPIDLCString contractidString;
534        rv = catman->GetCategoryEntry(COMMAND_LINE_ARGUMENT_HANDLERS,
535                                      entryString.get(),
536                                      getter_Copies(contractidString));
537        if (NS_FAILED(rv) || !((const char *)contractidString)) break;
538
539#ifdef DEBUG_CMD_LINE
540        printf("cmd line handler contractid = %s\n", (const char *)contractidString);
541#endif /* DEBUG_CMD_LINE */
542
543        nsCOMPtr <nsICmdLineHandler> handler(do_GetService((const char *)contractidString, &rv));
544
545        if (handler) {
546          nsXPIDLCString commandLineArg;
547          rv = handler->GetCommandLineArgument(getter_Copies(commandLineArg));
548          if (NS_FAILED(rv)) continue;
549
550          nsXPIDLCString helpText;
551          rv = handler->GetHelpText(getter_Copies(helpText));
552          if (NS_FAILED(rv)) continue;
553
554          if ((const char *)commandLineArg) {
555            printf("%s%s", HELP_SPACER_1,(const char *)commandLineArg);
556
557            PRBool handlesArgs = PR_FALSE;
558            rv = handler->GetHandlesArgs(&handlesArgs);
559            if (NS_SUCCEEDED(rv) && handlesArgs) {
560              printf(" <url>");
561            }
562            if ((const char *)helpText) {
563              printf("%s%s\n",HELP_SPACER_2,(const char *)helpText);
564            }
565          }
566        }
567
568      }
569    }
570  }
571  return;
572}
573
574static nsresult
575LaunchApplicationWithArgs(const char *commandLineArg,
576                          nsICmdLineService *cmdLineArgs,
577                          const char *aParam,
578                          PRInt32 height, PRInt32 width, PRBool *windowOpened)
579{
580  NS_ENSURE_ARG(commandLineArg);
581  NS_ENSURE_ARG(cmdLineArgs);
582  NS_ENSURE_ARG(aParam);
583  NS_ENSURE_ARG(windowOpened);
584
585  nsresult rv;
586
587  nsCOMPtr<nsICmdLineService> cmdLine =
588    do_GetService("@mozilla.org/appshell/commandLineService;1",&rv);
589  if (NS_FAILED(rv)) return rv;
590
591  nsCOMPtr <nsICmdLineHandler> handler;
592  rv = cmdLine->GetHandlerForParam(aParam, getter_AddRefs(handler));
593  if (NS_FAILED(rv)) return rv;
594
595  if (!handler) return NS_ERROR_FAILURE;
596
597  nsXPIDLCString chromeUrlForTask;
598  rv = handler->GetChromeUrlForTask(getter_Copies(chromeUrlForTask));
599  if (NS_FAILED(rv)) return rv;
600
601#ifdef DEBUG_CMD_LINE
602  printf("XXX got this one:\t%s\n\t%s\n\n",commandLineArg,(const char *)chromeUrlForTask);
603#endif /* DEBUG_CMD_LINE */
604
605  nsXPIDLCString cmdResult;
606  rv = cmdLineArgs->GetCmdLineValue(commandLineArg, getter_Copies(cmdResult));
607  if (NS_FAILED(rv)) return rv;
608#ifdef DEBUG_CMD_LINE
609  printf("%s, cmdResult = %s\n",commandLineArg,(const char *)cmdResult);
610#endif /* DEBUG_CMD_LINE */
611
612  PRBool handlesArgs = PR_FALSE;
613  rv = handler->GetHandlesArgs(&handlesArgs);
614  if (handlesArgs) {
615    if ((const char *)cmdResult) {
616      if (PL_strcmp("1",(const char *)cmdResult)) {
617        PRBool openWindowWithArgs = PR_TRUE;
618        rv = handler->GetOpenWindowWithArgs(&openWindowWithArgs);
619        if (NS_FAILED(rv)) return rv;
620
621        if (openWindowWithArgs) {
622          nsAutoString cmdArgs; cmdArgs.AssignWithConversion(cmdResult);
623#ifdef DEBUG_CMD_LINE
624          printf("opening %s with %s\n", chromeUrlForTask.get(), "OpenWindow");
625#endif /* DEBUG_CMD_LINE */
626          rv = OpenWindow(chromeUrlForTask, cmdArgs);
627        }
628        else {
629#ifdef DEBUG_CMD_LINE
630          printf("opening %s with %s\n", cmdResult.get(), "OpenWindow");
631#endif /* DEBUG_CMD_LINE */
632          rv = OpenWindow(cmdResult, width, height);
633          if (NS_FAILED(rv)) return rv;
634        }
635        // If we get here without an error, then a window was opened OK.
636        if (NS_SUCCEEDED(rv)) {
637          *windowOpened = PR_TRUE;
638        }
639      }
640      else {
641        nsXPIDLString defaultArgs;
642        rv = handler->GetDefaultArgs(getter_Copies(defaultArgs));
643        if (NS_FAILED(rv)) return rv;
644
645        rv = OpenWindow(chromeUrlForTask, defaultArgs);
646        if (NS_FAILED(rv)) return rv;
647        // Window was opened OK.
648        *windowOpened = PR_TRUE;
649      }
650    }
651  }
652  else {
653    if (NS_SUCCEEDED(rv) && (const char*)cmdResult) {
654      if (PL_strcmp("1",cmdResult) == 0) {
655        rv = OpenWindow(chromeUrlForTask, width, height);
656        if (NS_FAILED(rv)) return rv;
657      }
658      else {
659        rv = OpenWindow(cmdResult, width, height);
660        if (NS_FAILED(rv)) return rv;
661      }
662      // If we get here without an error, then a window was opened OK.
663      if (NS_SUCCEEDED(rv)) {
664        *windowOpened = PR_TRUE;
665      }
666    }
667  }
668
669  return NS_OK;
670}
671
672static PRBool IsStartupCommand(const char *arg)
673{
674  if (!arg) return PR_FALSE;
675
676  if (PL_strlen(arg) <= 1) return PR_FALSE;
677
678  // windows allows /mail or -mail
679  if ((arg[0] == '-')
680#if defined(XP_WIN) || defined(XP_OS2)
681      || (arg[0] == '/')
682#endif /* XP_WIN || XP_OS2 */
683      ) {
684    return PR_TRUE;
685  }
686
687  return PR_FALSE;
688}
689
690
691// This should be done by app shell enumeration someday
692nsresult DoCommandLines(nsICmdLineService* cmdLineArgs, PRBool heedGeneralStartupPrefs, PRBool *windowOpened)
693{
694  NS_ENSURE_ARG(windowOpened);
695  *windowOpened = PR_FALSE;
696
697  nsresult rv;
698
699        PRInt32 height = nsIAppShellService::SIZE_TO_CONTENT;
700        PRInt32 width  = nsIAppShellService::SIZE_TO_CONTENT;
701        nsXPIDLCString tempString;
702
703        // Get the value of -width option
704        rv = cmdLineArgs->GetCmdLineValue("-width", getter_Copies(tempString));
705        if (NS_SUCCEEDED(rv) && !tempString.IsEmpty())
706    PR_sscanf(tempString.get(), "%d", &width);
707
708        // Get the value of -height option
709        rv = cmdLineArgs->GetCmdLineValue("-height", getter_Copies(tempString));
710        if (NS_SUCCEEDED(rv) && !tempString.IsEmpty())
711    PR_sscanf(tempString.get(), "%d", &height);
712 
713  if (heedGeneralStartupPrefs) {
714    nsCOMPtr<nsIAppShellService> appShell(do_GetService("@mozilla.org/appshell/appShellService;1", &rv));
715    if (NS_FAILED(rv)) return rv;
716    rv = appShell->CreateStartupState(width, height, windowOpened);
717    if (NS_FAILED(rv)) return rv;
718  }
719  else {
720    PRInt32 argc = 0;
721    rv = cmdLineArgs->GetArgc(&argc);
722    if (NS_FAILED(rv)) return rv;
723
724    char **argv = nsnull;
725    rv = cmdLineArgs->GetArgv(&argv);
726    if (NS_FAILED(rv)) return rv;
727
728    PRInt32 i = 0;
729    for (i=1;i<argc;i++) {
730#ifdef DEBUG_CMD_LINE
731      printf("XXX argv[%d] = %s\n",i,argv[i]);
732#endif /* DEBUG_CMD_LINE */
733      if (IsStartupCommand(argv[i])) {
734
735        // skip over the - (or / on windows)
736        char *command = argv[i] + 1;
737#ifdef XP_UNIX
738        // unix allows -mail and --mail
739        if ((argv[i][0] == '-') && (argv[i][1] == '-')) {
740          command = argv[i] + 2;
741        }
742#endif /* XP_UNIX */
743
744        // this can fail, as someone could do -foo, where -foo is not handled
745        rv = LaunchApplicationWithArgs((const char *)(argv[i]),
746                                       cmdLineArgs, command,
747                                       height, width, windowOpened);
748        if (rv == NS_ERROR_NOT_AVAILABLE || rv == NS_ERROR_ABORT)
749          return rv;
750      }
751    }
752  }
753  return NS_OK;
754}
755
756static nsresult DoOnShutdown()
757{
758  nsresult rv;
759
760  // save the prefs, in case they weren't saved
761  {
762    // scoping this in a block to force release
763    nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID, &rv));
764    NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get prefs, so unable to save them");
765    if (NS_SUCCEEDED(rv))
766      prefs->SavePrefFile(nsnull);
767  }
768
769  // call ShutDownCurrentProfile() so we update the last modified time of the profile
770  {
771    // scoping this in a block to force release
772    nsCOMPtr<nsIProfile> profileMgr(do_GetService(NS_PROFILE_CONTRACTID, &rv));
773    NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get profile manager, so unable to update last modified time");
774    if (NS_SUCCEEDED(rv)) {
775      profileMgr->ShutDownCurrentProfile(nsIProfile::SHUTDOWN_PERSIST);
776    }
777  }
778
779  // at this point, all that is on the clipboard is a proxy object, but that object
780  // won't be valid once the app goes away. As a result, we need to force the data
781  // out of that proxy and properly onto the clipboard. This can't be done in the
782  // clipboard service's shutdown routine because it requires the parser/etc which
783  // has already been shutdown by the time the clipboard is shut down.
784  {
785    // scoping this in a block to force release
786    nsCOMPtr<nsIClipboard> clipService(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
787    if (NS_SUCCEEDED(rv))
788      clipService->ForceDataToClipboard(nsIClipboard::kGlobalClipboard);
789  }
790
791  return rv;
792}
793
794// match OS locale
795static char kMatchOSLocalePref[] = "intl.locale.matchOS";
796
797nsresult
798getCountry(const nsAString& lc_name, nsAString& aCountry)
799{
800
801  nsresult        result = NS_OK;
802
803  PRInt32 dash = lc_name.FindChar('-');
804  if (dash > 0)
805    aCountry = Substring(lc_name, dash+1, lc_name.Length()-dash);
806  else
807    result = NS_ERROR_FAILURE;
808
809  return result;
810}
811
812static nsresult
813getUILangCountry(nsAString& aUILang, nsAString& aCountry)
814{
815  nsresult       result;
816  // get a locale service
817  nsCOMPtr<nsILocaleService> localeService = do_GetService(NS_LOCALESERVICE_CONTRACTID, &result);
818  NS_ASSERTION(NS_SUCCEEDED(result),"getUILangCountry: get locale service failed");
819
820  nsXPIDLString uiLang;
821  result = localeService->GetLocaleComponentForUserAgent(getter_Copies(uiLang));
822  aUILang = uiLang;
823  result = getCountry(aUILang, aCountry);
824  return result;
825}
826
827// update global locale if possible (in case when user-*.rdf can be updated)
828// so that any apps after this can be invoked in the UILocale and contentLocale
829static nsresult InstallGlobalLocale(nsICmdLineService *cmdLineArgs)
830{
831    nsresult rv = NS_OK;
832
833    // check the pref first
834    nsCOMPtr<nsIPref> prefService(do_GetService(NS_PREF_CONTRACTID));
835    PRBool matchOS = PR_FALSE;
836    if (prefService)
837      prefService->GetBoolPref(kMatchOSLocalePref, &matchOS);
838
839    // match os locale
840    nsAutoString uiLang;
841    nsAutoString country;
842    if (matchOS) {
843      // compute lang and region code only when needed!
844      rv = getUILangCountry(uiLang, country);
845    }
846
847    nsXPIDLCString cmdUI;
848    rv = cmdLineArgs->GetCmdLineValue(UILOCALE_CMD_LINE_ARG, getter_Copies(cmdUI));
849    if (NS_SUCCEEDED(rv)){
850        if (cmdUI) {
851            nsCAutoString UILocaleName(cmdUI);
852            nsCOMPtr<nsIXULChromeRegistry> chromeRegistry = do_GetService(NS_CHROMEREGISTRY_CONTRACTID, &rv);
853            if (chromeRegistry)
854                rv = chromeRegistry->SelectLocale(UILocaleName, PR_FALSE);
855        }
856    }
857    // match OS when no cmdline override
858    if (!cmdUI && matchOS) {
859      nsCOMPtr<nsIXULChromeRegistry> chromeRegistry = do_GetService(NS_CHROMEREGISTRY_CONTRACTID, &rv);
860      if (chromeRegistry) {
861        chromeRegistry->SetRuntimeProvider(PR_TRUE);
862        rv = chromeRegistry->SelectLocale(NS_ConvertUCS2toUTF8(uiLang), PR_FALSE);
863      }
864    }
865
866    nsXPIDLCString cmdContent;
867    rv = cmdLineArgs->GetCmdLineValue(CONTENTLOCALE_CMD_LINE_ARG, getter_Copies(cmdContent));
868    if (NS_SUCCEEDED(rv)){
869        if (cmdContent) {
870            nsCAutoString contentLocaleName(cmdContent);
871            nsCOMPtr<nsIXULChromeRegistry> chromeRegistry = do_GetService(NS_CHROMEREGISTRY_CONTRACTID, &rv);
872            if(chromeRegistry)
873                rv = chromeRegistry->SelectLocale(contentLocaleName, PR_FALSE);
874        }
875    }
876    // match OS when no cmdline override
877    if (!cmdContent && matchOS) {
878      nsCOMPtr<nsIXULChromeRegistry> chromeRegistry = do_GetService(NS_CHROMEREGISTRY_CONTRACTID, &rv);
879      if (chromeRegistry) {
880        chromeRegistry->SetRuntimeProvider(PR_TRUE);       
881        rv = chromeRegistry->SelectLocale(NS_ConvertUCS2toUTF8(country), PR_FALSE);
882      }
883    }
884
885    return NS_OK;
886}
887
888static nsresult InitializeProfileService(nsICmdLineService *cmdLineArgs)
889{
890    // If we are being launched in -turbo mode, we cannot show UI
891    PRBool shouldShowUI = PR_TRUE;
892    nsCOMPtr<nsINativeAppSupport> nativeApp;
893    if (NS_SUCCEEDED(GetNativeAppSupport(getter_AddRefs(nativeApp))))
894      nativeApp->GetShouldShowUI(&shouldShowUI);
895    // If we were launched with -silent, we cannot show UI, either.
896    if (shouldShowUI) {
897      nsXPIDLCString arg;
898      if (NS_SUCCEEDED(cmdLineArgs->GetCmdLineValue("-silent", getter_Copies(arg))) && (const char*)arg) {
899        shouldShowUI = PR_FALSE;
900      }
901    }
902    nsresult rv;
903    nsCOMPtr<nsIAppShellService> appShellService(do_GetService(kAppShellServiceCID, &rv));
904    if (NS_FAILED(rv)) return rv;
905    rv = appShellService->DoProfileStartup(cmdLineArgs, shouldShowUI);
906
907    return rv;
908}
909
910static nsresult InitializeWindowCreator()
911{
912  // create an nsWindowCreator and give it to the WindowWatcher service
913  nsWindowCreator *creatorCallback = new nsWindowCreator();
914  if (!creatorCallback)
915    return NS_ERROR_OUT_OF_MEMORY;
916
917  nsCOMPtr<nsIWindowCreator> windowCreator(NS_STATIC_CAST(nsIWindowCreator *, creatorCallback));
918  if (windowCreator) {
919    nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
920    if (wwatch) {
921      wwatch->SetWindowCreator(windowCreator);
922      return NS_OK;
923    }
924  }
925  return NS_ERROR_FAILURE;
926}
927
928// Maximum allowed / used length of alert message is 255 chars, due to restrictions on Mac.
929// Please make sure that file contents and fallback_alert_text are at most 255 chars.
930// Fallback_alert_text must be non-const, because of inplace conversion on Mac.
931static void ShowOSAlertFromFile(int argc, char **argv, const char *alert_filename, const char* fallback_alert_text)
932{
933  char message[256] = { 0 };
934  PRInt32 numRead = 0;
935  const char *messageToShow = fallback_alert_text;
936  nsresult rv;
937  nsCOMPtr<nsILocalFile> fileName;
938  nsCOMPtr<nsIProperties> directoryService;
939
940  directoryService = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
941  if (NS_SUCCEEDED(rv)) {
942    rv = directoryService->Get(NS_APP_RES_DIR,
943                               NS_GET_IID(nsIFile),
944                               getter_AddRefs(fileName));
945    if (NS_SUCCEEDED(rv) && fileName) {
946      fileName->AppendNative(nsDependentCString(alert_filename));
947      PRFileDesc* fd = 0;
948      fileName->OpenNSPRFileDesc(PR_RDONLY, 0664, &fd);
949      if (fd) {
950        numRead = PR_Read(fd, message, sizeof(message)-1);
951        if (numRead > 0) {
952          message[numRead] = 0;
953          messageToShow = message;
954        }
955      }
956    }
957  }
958
959  ShowOSAlert(messageToShow);
960}
961
962static nsresult VerifyInstallation(int argc, char **argv)
963{
964#ifdef MOZ_XPINSTALL
965  nsresult rv;
966  nsCOMPtr<nsILocalFile> registryFile;
967
968  nsCOMPtr<nsIProperties> directoryService =
969           do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
970  if (NS_FAILED(rv))
971    return NS_OK;
972  rv = directoryService->Get(NS_APP_INSTALL_CLEANUP_DIR,
973                             NS_GET_IID(nsIFile),
974                             getter_AddRefs(registryFile));
975  if (NS_FAILED(rv) || !registryFile)
976    return NS_ERROR_FAILURE;
977
978  registryFile->AppendNative(CLEANUP_REGISTRY);
979
980  PRBool exists;
981  registryFile->Exists(&exists);
982  if (exists)
983  {
984    nsCOMPtr<nsIFile> binPath;
985    const char lastResortMessage[] = "A previous install did not complete correctly.  Finishing install.";
986
987    ShowOSAlertFromFile(argc, argv, CLEANUP_MESSAGE_FILENAME.get(), lastResortMessage);
988
989    nsCOMPtr<nsIFile> cleanupUtility;
990    registryFile->Clone(getter_AddRefs(cleanupUtility));
991    cleanupUtility->SetNativeLeafName(CLEANUP_UTIL);
992
993    //Create the process framework to run the cleanup utility
994    nsCOMPtr<nsIProcess> cleanupProcess = do_CreateInstance(kIProcessCID);
995    rv = cleanupProcess->Init(cleanupUtility);
996    if (NS_SUCCEEDED(rv))
997      rv = cleanupProcess->Run(PR_FALSE,nsnull, 0, nsnull);
998
999    //We must exit because all open files must be released by the system
1000    return NS_ERROR_FAILURE;
1001  }
1002#endif
1003  return NS_OK;
1004}
1005
1006#ifdef DEBUG_warren
1007#ifdef XP_WIN
1008#define _CRTDBG_MAP_ALLOC
1009#include <crtdbg.h>
1010#endif
1011#endif
1012
1013#if defined(FREEBSD)
1014// pick up fpsetmask prototype.
1015#include <ieeefp.h>
1016#endif
1017
1018// Note: nativeApp is an owning reference that this function has responsibility
1019//       to release.  This responsibility is delegated to the app shell service
1020//       (see nsAppShellService::Initialize call, below).
1021static nsresult main1(int argc, char* argv[], nsISupports *nativeApp )
1022{
1023  nsresult rv;
1024  NS_TIMELINE_ENTER("main1");
1025  nsCOMPtr<nsISupports> nativeAppOwner(dont_AddRef(nativeApp));
1026
1027  //----------------------------------------------------------------
1028  // First we need to check if a previous installation occured and
1029  // if so, make sure it finished and cleaned up correctly.
1030  //
1031  // If there is an xpicleanup.dat file left around, that means the
1032  // previous installation did not finish correctly. We must cleanup
1033  // before a valid mozilla can run.
1034  //
1035  // Show the user a platform-specific Alert message, then spawn the
1036  // xpicleanup utility, then exit.
1037  //----------------------------------------------------------------
1038  rv = VerifyInstallation(argc, argv);
1039  if (NS_FAILED(rv))
1040    return NS_ERROR_FAILURE;
1041
1042#ifdef DEBUG_warren
1043//  _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF);
1044#endif
1045
1046#ifndef XP_MAC
1047  // Unbuffer debug output (necessary for automated QA performance scripts).
1048  setbuf(stdout, 0);
1049#endif
1050
1051#if defined(FREEBSD)
1052  // Disable all SIGFPE's on FreeBSD, as it has non-IEEE-conformant fp
1053  // trap behavior that trips up on floating-point tests performed by
1054  // the JS engine.  See bugzilla bug 9967 details.
1055  fpsetmask(0);
1056#endif
1057
1058  NS_TIMELINE_ENTER("init event service");
1059  nsCOMPtr<nsIEventQueueService> eventQService(do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv));
1060  if (NS_SUCCEEDED(rv)) {
1061    // XXX: What if this fails?
1062    rv = eventQService->CreateThreadEventQueue();
1063  }
1064  NS_TIMELINE_LEAVE("init event service");
1065
1066  // Setup an autoreg obserer, so that we can update a progress
1067  // string in the splash screen
1068  nsCOMPtr<nsIObserverService> obsService(do_GetService("@mozilla.org/observer-service;1"));
1069  if (obsService)
1070  {
1071    nsCOMPtr<nsIObserver> splashScreenObserver(do_QueryInterface(nativeAppOwner));
1072    if (splashScreenObserver)
1073    {
1074      obsService->AddObserver(splashScreenObserver, NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID, PR_FALSE);
1075      obsService->AddObserver(splashScreenObserver, "startup_user_notifcations", PR_FALSE);
1076    }
1077  }
1078
1079#if XP_MAC
1080  stTSMCloser  tsmCloser;
1081
1082  rv = InitializeMacCommandLine(argc, argv);
1083  NS_ASSERTION(NS_SUCCEEDED(rv), "Initializing AppleEvents failed");
1084#endif
1085
1086#ifdef DEBUG
1087  // _Always_ autoreg if we're in a debug build, under the assumption
1088  // that people are busily modifying components and will be angry if
1089  // their changes aren't noticed.
1090  nsCOMPtr<nsIComponentRegistrar> registrar;
1091  NS_GetComponentRegistrar(getter_AddRefs(registrar));
1092  registrar->AutoRegister(nsnull);
1093  registrar = nsnull;
1094#endif
1095
1096  NS_TIMELINE_ENTER("startupNotifier");
1097
1098  // Start up the core services:
1099
1100  // Please do not add new things to main1() - please hook into the
1101  // nsIAppStartupNotifier service.
1102  nsCOMPtr<nsIObserver> startupNotifier = do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID, &rv);
1103  if(NS_FAILED(rv))
1104    return rv;
1105  startupNotifier->Observe(nsnull, APPSTARTUP_TOPIC, nsnull);
1106  NS_TIMELINE_LEAVE("startupNotifier");
1107
1108  NS_TIMELINE_ENTER("cmdLineArgs");
1109
1110  // Initialize the cmd line service
1111  nsCOMPtr<nsICmdLineService> cmdLineArgs(do_GetService(kCmdLineServiceCID, &rv));
1112  NS_ASSERTION(NS_SUCCEEDED(rv), "Could not obtain CmdLine processing service\n");
1113  if (NS_FAILED(rv))
1114    return rv;
1115
1116  rv = cmdLineArgs->Initialize(argc, argv);
1117  NS_ASSERTION(NS_SUCCEEDED(rv), "failed to initialize command line args");
1118  if (rv == NS_ERROR_INVALID_ARG) {
1119    PrintUsage();
1120    return rv;
1121  }
1122
1123  NS_TIMELINE_LEAVE("cmdLineArgs");
1124
1125  NS_TIMELINE_ENTER("InstallGlobalLocale");
1126  rv = InstallGlobalLocale(cmdLineArgs);
1127  if(NS_FAILED(rv))
1128    return rv;
1129  NS_TIMELINE_LEAVE("InstallGlobalLocale");
1130
1131  NS_TIMELINE_ENTER("appShell");
1132
1133  nsCOMPtr<nsIAppShellService> appShell(do_GetService(kAppShellServiceCID, &rv));
1134  NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get the appshell service");
1135
1136  /* if we couldn't get the nsIAppShellService service, then we should hide the
1137     splash screen and return */
1138  if (NS_FAILED(rv))
1139  {
1140    // See if platform supports nsINativeAppSupport.
1141    nsCOMPtr<nsINativeAppSupport> nativeAppSupport(do_QueryInterface(nativeAppOwner));
1142    if (nativeAppSupport)
1143    {
1144      // Use that interface to remove splash screen.
1145      nativeAppSupport->HideSplashScreen();
1146    }
1147    else
1148    {
1149      // See if platform supports nsISplashScreen, instead.
1150      nsCOMPtr<nsISplashScreen> splashScreen(do_QueryInterface(nativeAppOwner));
1151      if (splashScreen)
1152      {
1153        splashScreen->Hide();
1154      }
1155    }
1156    return rv;
1157  }
1158
1159  NS_TIMELINE_LEAVE("appShell");
1160
1161  NS_TIMELINE_ENTER("appShell->Initialize");
1162
1163  // Create the Application Shell instance...
1164  rv = appShell->Initialize(cmdLineArgs, nativeAppOwner);
1165
1166  NS_TIMELINE_LEAVE("appShell->Initialize");
1167
1168  NS_ASSERTION(NS_SUCCEEDED(rv), "failed to initialize appshell");
1169  if (NS_FAILED(rv)) return rv;
1170
1171  rv = InitializeWindowCreator();
1172  NS_ASSERTION(NS_SUCCEEDED(rv), "failed to initialize window creator");
1173  if (NS_FAILED(rv)) return rv;
1174
1175  // So we can open and close windows during startup
1176  appShell->EnterLastWindowClosingSurvivalArea();
1177
1178  // Initialize Profile Service here.
1179  NS_TIMELINE_ENTER("InitializeProfileService");
1180  rv = InitializeProfileService(cmdLineArgs);
1181  NS_TIMELINE_LEAVE("InitializeProfileService");
1182  if (NS_FAILED(rv)) return rv;
1183
1184  NS_TIMELINE_ENTER("appShell->CreateHiddenWindow");
1185  appShell->CreateHiddenWindow();
1186  NS_TIMELINE_LEAVE("appShell->CreateHiddenWindow");
1187
1188  // This will go away once Components are handling there own commandlines
1189  // if we have no command line arguments, we need to heed the
1190  // "general.startup.*" prefs
1191  // if we had no command line arguments, argc == 1.
1192
1193  PRBool windowOpened = PR_FALSE;
1194  PRBool defaultStartup;
1195#if defined(XP_MAC) || defined(XP_MACOSX)
1196  // On Mac, nsCommandLineServiceMac may have added synthetic
1197  // args. Check this adjusted value instead of the raw value.
1198  PRInt32 processedArgc;
1199  cmdLineArgs->GetArgc(&processedArgc);
1200  defaultStartup = (processedArgc == 1);
1201#if defined(XP_MACOSX)
1202  // On OSX, we get passed two args if double-clicked from the Finder.
1203  // The second is our PSN. Check for this and consider it to be default.
1204  if (argc == 2 && processedArgc == 2) {
1205    ProcessSerialNumber ourPSN;
1206    if (::MacGetCurrentProcess(&ourPSN) == noErr) {
1207      char argBuf[64];
1208      sprintf(argBuf, "-psn_%ld_%ld", ourPSN.highLongOfPSN, ourPSN.lowLongOfPSN);
1209      if (!strcmp(argBuf, argv[1]))
1210        defaultStartup = PR_TRUE;
1211    }
1212  }
1213#endif /* XP_MACOSX */
1214#else
1215  defaultStartup = (argc == 1);
1216#endif
1217  rv = DoCommandLines(cmdLineArgs, defaultStartup, &windowOpened);
1218  if (NS_FAILED(rv))
1219  {
1220    NS_WARNING("failed to process command line");
1221    return rv;
1222  }
1223 
1224        if (obsService)
1225  {
1226    nsAutoString userMessage; userMessage.AssignWithConversion("Creating first window...");
1227    obsService->NotifyObservers(nsnull, "startup_user_notifcations", userMessage.get());
1228  }
1229 
1230
1231  // Make sure there exists at least 1 window.
1232  NS_TIMELINE_ENTER("Ensure1Window");
1233  rv = appShell->Ensure1Window(cmdLineArgs);
1234  NS_TIMELINE_LEAVE("Ensure1Window");
1235  NS_ASSERTION(NS_SUCCEEDED(rv), "failed to Ensure1Window");
1236  if (NS_FAILED(rv)) return rv;
1237
1238#if !defined(XP_MAC) && !defined(XP_MACOSX)
1239  appShell->ExitLastWindowClosingSurvivalArea();
1240#endif
1241
1242#ifdef MOZ_ENABLE_XREMOTE
1243  // if we have X remote support and we have our one window up and
1244  // running start listening for requests on the proxy window.
1245  nsCOMPtr<nsIXRemoteService> remoteService;
1246  remoteService = do_GetService(NS_IXREMOTESERVICE_CONTRACTID);
1247  if (remoteService)
1248    remoteService->Startup();
1249#endif /* MOZ_ENABLE_XREMOTE */
1250
1251  // remove the nativeApp as an XPCOM autoreg observer
1252  if (obsService)
1253  {
1254    nsCOMPtr<nsIObserver> splashScreenObserver(do_QueryInterface(nativeAppOwner));
1255    if (splashScreenObserver)
1256    {
1257      obsService->RemoveObserver(splashScreenObserver, NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID);
1258      obsService->RemoveObserver(splashScreenObserver, "startup_user_notifcations");
1259    }
1260  }
1261
1262  // We are done with the native app (or splash screen) object here;
1263  // the app shell owns it now.
1264  nativeAppOwner = nsnull;
1265
1266  // Start main event loop
1267  NS_TIMELINE_ENTER("appShell->Run");
1268  rv = appShell->Run();
1269  NS_TIMELINE_LEAVE("appShell->Run");
1270  NS_ASSERTION(NS_SUCCEEDED(rv), "failed to run appshell");
1271
1272#ifdef MOZ_ENABLE_XREMOTE
1273  // shut down the x remote proxy window
1274  if (remoteService)
1275    remoteService->Shutdown();
1276#endif /* MOZ_ENABLE_XREMOTE */
1277
1278#ifdef MOZ_TIMELINE
1279  // Make sure we print this out even if timeline is runtime disabled
1280  if (NS_FAILED(NS_TIMELINE_LEAVE("main1")))
1281      NS_TimelineForceMark("...main1");
1282#endif
1283
1284  return rv;
1285}
1286
1287// English text needs to go into a dtd file.
1288// But when this is called we have no components etc. These strings must either be
1289// here, or in a native resource file.
1290static void DumpHelp(char *appname)
1291{
1292  printf("Usage: %s [ options ... ] [URL]\n", appname);
1293  printf("       where options include:\n");
1294  printf("\n");
1295
1296#ifdef MOZ_WIDGET_GTK
1297  /* insert gtk options above moz options, like any other gtk app
1298   *
1299   * note: this isn't a very cool way to do things -- i'd rather get
1300   * these straight from a user's gtk version -- but it seems to be
1301   * what most gtk apps do. -dr
1302   */
1303
1304  printf("GTK options\n");
1305  printf("%s--gdk-debug=FLAGS%sGdk debugging flags to set\n", HELP_SPACER_1, HELP_SPACER_2);
1306  printf("%s--gdk-no-debug=FLAGS%sGdk debugging flags to unset\n", HELP_SPACER_1, HELP_SPACER_2);
1307  printf("%s--gtk-debug=FLAGS%sGtk+ debugging flags to set\n", HELP_SPACER_1, HELP_SPACER_2);
1308  printf("%s--gtk-no-debug=FLAGS%sGtk+ debugging flags to unset\n", HELP_SPACER_1, HELP_SPACER_2);
1309  printf("%s--gtk-module=MODULE%sLoad an additional Gtk module\n", HELP_SPACER_1, HELP_SPACER_2);
1310  printf("%s-install%sInstall a private colormap\n", HELP_SPACER_1, HELP_SPACER_2);
1311
1312  /* end gtk toolkit options */
1313#endif /* MOZ_WIDGET_GTK */
1314#if MOZ_WIDGET_XLIB
1315  printf("Xlib options\n");
1316  printf("%s-display=DISPLAY%sX display to use\n", HELP_SPACER_1, HELP_SPACER_2);
1317  printf("%s-visual=VISUALID%sX visual to use\n", HELP_SPACER_1, HELP_SPACER_2);
1318  printf("%s-install_colormap%sInstall own colormap\n", HELP_SPACER_1, HELP_SPACER_2);
1319  printf("%s-sync%sMake X calls synchronous\n", HELP_SPACER_1, HELP_SPACER_2);
1320  printf("%s-no-xshm%sDon't use X shared memory extension\n", HELP_SPACER_1, HELP_SPACER_2);
1321
1322  /* end xlib toolkit options */
1323#endif /* MOZ_WIDGET_XLIB */
1324#ifdef MOZ_X11
1325  printf("X11 options\n");
1326  printf("%s--display=DISPLAY%sX display to use\n", HELP_SPACER_1, HELP_SPACER_2);
1327  printf("%s--sync%sMake X calls synchronous\n", HELP_SPACER_1, HELP_SPACER_2);
1328  printf("%s--no-xshm%sDon't use X shared memory extension\n", HELP_SPACER_1, HELP_SPACER_2);
1329  printf("%s--xim-preedit=STYLE\n", HELP_SPACER_1);
1330  printf("%s--xim-status=STYLE\n", HELP_SPACER_1);
1331#endif
1332#ifdef XP_UNIX
1333  printf("%s--g-fatal-warnings%sMake all warnings fatal\n", HELP_SPACER_1, HELP_SPACER_2);
1334
1335  printf("\nMozilla options\n");
1336#endif
1337
1338  printf("%s-height <value>%sSet height of startup window to <value>.\n",HELP_SPACER_1,HELP_SPACER_2);
1339  printf("%s-h or -help%sPrint this message.\n",HELP_SPACER_1,HELP_SPACER_2);
1340  printf("%s-installer%sStart with 4.x migration window.\n",HELP_SPACER_1,HELP_SPACER_2);
1341  printf("%s-width <value>%sSet width of startup window to <value>.\n",HELP_SPACER_1,HELP_SPACER_2);
1342  printf("%s-v or -version%sPrint %s version.\n",HELP_SPACER_1,HELP_SPACER_2, appname);
1343  printf("%s-CreateProfile <profile>%sCreate <profile>.\n",HELP_SPACER_1,HELP_SPACER_2);
1344  printf("%s-P <profile>%sStart with <profile>.\n",HELP_SPACER_1,HELP_SPACER_2);
1345  printf("%s-ProfileWizard%sStart with profile wizard.\n",HELP_SPACER_1,HELP_SPACER_2);
1346  printf("%s-ProfileManager%sStart with profile manager.\n",HELP_SPACER_1,HELP_SPACER_2);
1347  printf("%s-SelectProfile%sStart with profile selection dialog.\n",HELP_SPACER_1,HELP_SPACER_2);
1348  printf("%s-UILocale <locale>%sStart with <locale> resources as UI Locale.\n",HELP_SPACER_1,HELP_SPACER_2);
1349  printf("%s-contentLocale <locale>%sStart with <locale> resources as content Locale.\n",HELP_SPACER_1,HELP_SPACER_2);
1350#ifdef XP_WIN32
1351  printf("%s-console%sStart Mozilla with a debugging console.\n",HELP_SPACER_1,HELP_SPACER_2);
1352#endif
1353#ifdef MOZ_ENABLE_XREMOTE
1354  printf("%s-remote <command>%sExecute <command> in an already running\n"
1355         "%sMozilla process.  For more info, see:\n"
1356         "\n%shttp://www.mozilla.org/unix/remote.html\n\n",
1357         HELP_SPACER_1,HELP_SPACER_1,HELP_SPACER_4,HELP_SPACER_2);
1358  printf("%s-splash%sEnable splash screen.\n",HELP_SPACER_1,HELP_SPACER_2);
1359#else
1360  printf("%s-nosplash%sDisable splash screen.\n",HELP_SPACER_1,HELP_SPACER_2);
1361#if defined(XP_WIN) || defined(XP_OS2)
1362  printf("%s-quiet%sDisable splash screen.\n",HELP_SPACER_1,HELP_SPACER_2);
1363#endif
1364#endif
1365
1366  // this works, but only after the components have registered.  so if you drop in a new command line handler, -help
1367  // won't not until the second run.
1368  // out of the bug, because we ship a component.reg file, it works correctly.
1369  DumpArbitraryHelp();
1370}
1371
1372
1373static nsresult DumpVersion(char *appname)
1374{
1375  nsresult rv = NS_OK;
1376  long buildID = NS_BUILD_ID;  // 10-digit number
1377
1378  printf("Mozilla %s, Copyright (c) 2003 mozilla.org", MOZILLA_VERSION);
1379
1380  if(buildID) {
1381    printf(", build %u\n", (unsigned int)buildID);
1382  } else {
1383    printf(" <developer build>\n");
1384  }
1385
1386  return rv;
1387}
1388
1389#ifdef MOZ_ENABLE_XREMOTE
1390// use int here instead of a PR type since it will be returned
1391// from main - just to keep types consistent
1392static int HandleRemoteArguments(int argc, char* argv[], PRBool *aArgUsed)
1393{
1394  int i = 0;
1395  for (i=1; i < argc; i++) {
1396    if (PL_strcasecmp(argv[i], "-remote") == 0) {
1397      // someone used a -remote flag
1398      *aArgUsed = PR_TRUE;
1399      // check to make sure there's another arg
1400      if (argc-1 == i) {
1401        PR_fprintf(PR_STDERR, "-remote requires an argument\n");
1402        return 1;
1403      }
1404      // try to get the X remote client
1405      nsCOMPtr<nsIXRemoteClient> client (do_CreateInstance(NS_XREMOTECLIENT_CONTRACTID));
1406      if (!client)
1407        return 1;
1408      nsresult rv;
1409      // try to init - connects to the X server and stuff
1410      rv = client->Init();
1411      if (NS_FAILED(rv)) {
1412        PR_fprintf(PR_STDERR, "Failed to connect to X server.\n");
1413        return 1;
1414      }
1415      PRBool success = PR_FALSE;
1416      rv = client->SendCommand(argv[i+1], &success);
1417      // did the command fail?
1418      if (NS_FAILED(rv)) {
1419        PR_fprintf(PR_STDERR, "Failed to send command.\n");
1420        return 1;
1421      }
1422      // was there a window not running?
1423      if (!success) {
1424        PR_fprintf(PR_STDERR, "No running window found.\n");
1425        return 2;
1426      }
1427      client->Shutdown();
1428      // success
1429      return 0;
1430    }
1431  }
1432  return 0;
1433}
1434#endif /* XP_UNIX */
1435
1436static PRBool HandleDumpArguments(int argc, char* argv[])
1437{
1438  for (int i=1; i<argc; i++) {
1439    if ((PL_strcasecmp(argv[i], "-h") == 0)
1440        || (PL_strcasecmp(argv[i], "-help") == 0)
1441#if defined(XP_UNIX) || defined(XP_BEOS)
1442        || (PL_strcasecmp(argv[i], "--help") == 0)
1443#endif /* XP_UNIX || XP_BEOS*/
1444#if defined(XP_WIN) || defined(XP_OS2)
1445        || (PL_strcasecmp(argv[i], "/h") == 0)
1446        || (PL_strcasecmp(argv[i], "/help") == 0)
1447        || (PL_strcasecmp(argv[i], "/?") == 0)
1448#endif /* XP_WIN || XP_OS2 */
1449      ) {
1450      DumpHelp(argv[0]);
1451      return PR_TRUE;
1452    }
1453    if ((PL_strcasecmp(argv[i], "-v") == 0)
1454        || (PL_strcasecmp(argv[i], "-version") == 0)
1455#if defined(XP_UNIX) || defined(XP_BEOS)
1456        || (PL_strcasecmp(argv[i], "--version") == 0)
1457#endif /* XP_UNIX || XP_BEOS */
1458#if defined(XP_WIN) || defined(XP_OS2)
1459        || (PL_strcasecmp(argv[i], "/v") == 0)
1460        || (PL_strcasecmp(argv[i], "/version") == 0)
1461#endif /* XP_WIN || XP_OS2 */
1462      ) {
1463      DumpVersion(argv[0]);
1464      return PR_TRUE;
1465    }
1466  }
1467
1468  return PR_FALSE;
1469}
1470
1471
1472static PRBool GetWantSplashScreen(int argc, char* argv[])
1473{
1474  int i;
1475  PRBool dosplash;
1476  // We can't use the command line service here because it isn't running yet
1477#if defined(XP_UNIX) && !defined(MOZ_WIDGET_PHOTON)
1478  dosplash = PR_FALSE;
1479  for (i=1; i<argc; i++)
1480    if ((PL_strcasecmp(argv[i], "-splash") == 0)
1481        || (PL_strcasecmp(argv[i], "--splash") == 0))
1482      dosplash = PR_TRUE;
1483#else
1484  dosplash = PR_TRUE;
1485  for (i=1; i<argc; i++)
1486    if ((PL_strcasecmp(argv[i], "-nosplash") == 0)
1487#ifdef XP_BEOS
1488                || (PL_strcasecmp(argv[i], "--nosplash") == 0)
1489#endif /* XP_BEOS */
1490#if defined(XP_WIN) || defined(XP_OS2)
1491        || (PL_strcasecmp(argv[i], "/nosplash") == 0)
1492#endif /* XP_WIN || XP_OS2 */
1493        ) {
1494      dosplash = PR_FALSE;
1495        }
1496#endif
1497
1498  return dosplash;
1499}
1500
1501int main(int argc, char* argv[])
1502{
1503  NS_TIMELINE_MARK("enter main");
1504
1505#if defined(DEBUG) && defined(XP_WIN32)
1506  // Disable small heap allocator to get heapwalk() giving us
1507  // accurate heap numbers. Win2k non-debug does not use small heap allocator.
1508  // Win2k debug seems to be still using it.
1509  // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt__set_sbh_threshold.asp
1510  _set_sbh_threshold(0);
1511#endif
1512
1513#if defined(XP_UNIX) || defined(XP_BEOS)
1514  InstallUnixSignalHandlers(argv[0]);
1515#endif
1516
1517#if defined(XP_OS2)
1518  __argc = argc;
1519  __argv = argv;
1520
1521  ULONG    ulMaxFH = 0;
1522  LONG     ulReqCount = 0;
1523  APIRET   rc = NO_ERROR;
1524
1525  DosSetRelMaxFH(&ulReqCount,
1526                 &ulMaxFH);
1527
1528  if (ulMaxFH < 256) {
1529    DosSetMaxFH(256);
1530  }
1531#endif /* XP_OS2 */
1532
1533#if defined(XP_BEOS)
1534  if (NS_OK != InitializeBeOSApp())
1535    return 1;
1536#endif
1537
1538#if defined(XP_MACOSX)
1539  InitializeMacOSXApp(argc, argv);
1540#endif
1541
1542#ifdef _BUILD_STATIC_BIN
1543  // Initialize XPCOM's module info table
1544  NSGetStaticModuleInfo = app_getModuleInfo;
1545#endif
1546
1547  // Handle -help and -version command line arguments.
1548  // They should% return quick, so we deal with them here.
1549  if (HandleDumpArguments(argc, argv))
1550    return 0;
1551
1552#ifdef NS_TRACE_MALLOC
1553  argc = NS_TraceMallocStartupArgs(argc, argv);
1554#endif
1555
1556#if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_GTK2)
1557  // Initialize GTK+1/2 here for splash
1558#if defined(MOZ_WIDGET_GTK)
1559  gtk_set_locale();
1560#endif
1561  gtk_init(&argc, &argv);
1562#endif /* MOZ_WIDGET_GTK || MOZ_WIDGET_GTK2 */
1563   
1564  // Call the code to install our handler
1565#ifdef MOZ_JPROF
1566  setupProfilingStuff();
1567#endif
1568   
1569
1570#ifdef XPCOM_GLUE
1571  NS_TIMELINE_MARK("GRE_Startup...");
1572  nsresult rv = GRE_Startup();
1573  NS_TIMELINE_MARK("...GRE_Startup done");
1574  if (NS_FAILED(rv)) {
1575       // We should be displaying a dialog here with the reason why we failed.
1576    NS_WARNING("GRE_Startup failed");
1577    return 1;
1578  }
1579#else
1580  NS_TIMELINE_MARK("NS_InitXPCOM2...");
1581  nsresult rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
1582  NS_TIMELINE_MARK("...NS_InitXPCOM2 done");
1583  if (NS_FAILED(rv)) {
1584    // We should be displaying a dialog here with the reason why we failed.
1585    NS_WARNING("NS_InitXPCOM2 failed");
1586    return 1;
1587  }
1588#endif
1589
1590
1591  // Try to allocate "native app support."
1592  // Note: this object is not released here.  It is passed to main1 which
1593  //       has responsibility to release it.
1594  nsINativeAppSupport *nativeApp = 0;
1595  rv = NS_CreateNativeAppSupport(&nativeApp);
1596
1597  // See if we can run.
1598  if (nativeApp)
1599  {
1600    PRBool canRun = PR_FALSE;
1601    rv = nativeApp->Start(&canRun);
1602    if (!canRun) {
1603        return 1;
1604    }
1605  } else {
1606    // If platform doesn't implement nsINativeAppSupport, fall
1607    // back to old method.
1608    if (!NS_CanRun())
1609      return 1;
1610  }
1611  // Note: this object is not released here.  It is passed to main1 which
1612  //       has responsibility to release it.
1613  nsISplashScreen *splash = 0;
1614  PRBool dosplash = GetWantSplashScreen(argc, argv);
1615
1616  if (dosplash && !nativeApp) {
1617    // If showing splash screen and platform doesn't implement
1618    // nsINativeAppSupport, then use older nsISplashScreen interface.
1619    rv = NS_CreateSplashScreen(&splash);
1620    NS_ASSERTION(NS_SUCCEEDED(rv), "NS_CreateSplashScreen failed");
1621  }
1622  // If the platform has a splash screen, show it ASAP.
1623  if (dosplash && nativeApp) {
1624    nativeApp->ShowSplashScreen();
1625  } else if (splash) {
1626    splash->Show();
1627  }
1628
1629#ifdef MOZ_ENABLE_XREMOTE
1630  // handle -remote now that xpcom is fired up
1631  int remoterv;
1632  PRBool argused = PR_FALSE;
1633  // argused will be true if someone tried to use a -remote flag.  We
1634  // always exit in that case.
1635  remoterv = HandleRemoteArguments(argc, argv, &argused);
1636
1637  if (argused) {
1638#ifdef XPCOM_GLUE
1639    GRE_Shutdown();
1640#else
1641    NS_ShutdownXPCOM(nsnull);
1642#endif
1643    return remoterv;
1644  }
1645#endif
1646
1647  nsresult mainResult = main1(argc, argv, nativeApp ? (nsISupports*)nativeApp : (nsISupports*)splash);
1648
1649  /* if main1() didn't succeed, then don't bother trying to shut down clipboard, etc */
1650  if (NS_SUCCEEDED(mainResult)) {
1651    rv = DoOnShutdown();
1652    NS_ASSERTION(NS_SUCCEEDED(rv), "DoOnShutdown failed");
1653  }
1654#ifdef XPCOM_GLUE
1655  rv = GRE_Shutdown();
1656  NS_ASSERTION(NS_SUCCEEDED(rv), "GRE_Shutdown failed");
1657#else
1658  rv = NS_ShutdownXPCOM(nsnull);
1659  NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed");
1660#endif
1661
1662  return TranslateReturnValue(mainResult);
1663}
1664
1665#if defined( XP_WIN ) && defined( WIN32 )
1666// We need WinMain in order to not be a console app.  This function is
1667// unused if we are a console application.
1668int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR args, int)
1669{
1670    // Do the real work.
1671    return main(__argc, __argv);
1672}
1673#endif // XP_WIN && WIN32
Note: See TracBrowser for help on using the repository browser.