LCOV - code coverage report
Current view: directory - toolkit/xre - nsAppRunner.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 1389 244 17.6 %
Date: 2012-06-02 Functions: 92 26 28.3 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       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                 :  *   Benjamin Smedberg <benjamin@smedbergs.us>
      25                 :  *   Ben Goodger <ben@mozilla.org>
      26                 :  *   Fredrik Holmqvist <thesuckiestemail@yahoo.se>
      27                 :  *   Ben Turner <mozilla@songbirdnest.com>
      28                 :  *   Sergei Dolgov <sergei_d@fi.tartu.ee>
      29                 :  *
      30                 :  * Alternatively, the contents of this file may be used under the terms of
      31                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      32                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      33                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      34                 :  * of those above. If you wish to allow use of your version of this file only
      35                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      36                 :  * use your version of this file under the terms of the MPL, indicate your
      37                 :  * decision by deleting the provisions above and replace them with the notice
      38                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      39                 :  * the provisions above, a recipient may use your version of this file under
      40                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      41                 :  *
      42                 :  * ***** END LICENSE BLOCK ***** */
      43                 : 
      44                 : #if defined(XP_OS2) && defined(MOZ_OS2_HIGH_MEMORY)
      45                 : // os2safe.h has to be included before os2.h, needed for high mem
      46                 : #include <os2safe.h>
      47                 : #endif
      48                 : 
      49                 : #define XPCOM_TRANSLATE_NSGM_ENTRY_POINT 1
      50                 : 
      51                 : #if defined(MOZ_WIDGET_QT)
      52                 : #include <QtGui/QApplication>
      53                 : #include "nsQAppInstance.h"
      54                 : #include <QtGui/QInputContextFactory>
      55                 : #include <QtGui/QInputContext>
      56                 : #endif // MOZ_WIDGET_QT
      57                 : 
      58                 : #include "mozilla/dom/ContentParent.h"
      59                 : #include "mozilla/dom/ContentChild.h"
      60                 : 
      61                 : #include "mozilla/Util.h"
      62                 : 
      63                 : #include "nsAppRunner.h"
      64                 : #include "nsUpdateDriver.h"
      65                 : 
      66                 : #ifdef MOZ_INSTRUMENT_EVENT_LOOP
      67                 : #include "EventTracer.h"
      68                 : #endif
      69                 : 
      70                 : #ifdef XP_MACOSX
      71                 : #include "nsVersionComparator.h"
      72                 : #include "MacLaunchHelper.h"
      73                 : #include "MacApplicationDelegate.h"
      74                 : #include "MacAutoreleasePool.h"
      75                 : // these are needed for sysctl
      76                 : #include <sys/types.h>
      77                 : #include <sys/sysctl.h>
      78                 : #endif
      79                 : 
      80                 : #ifdef XP_OS2
      81                 : #include "private/pprthred.h"
      82                 : #endif
      83                 : #include "prmem.h"
      84                 : #include "prnetdb.h"
      85                 : #include "prprf.h"
      86                 : #include "prproces.h"
      87                 : #include "prenv.h"
      88                 : 
      89                 : #include "nsIAppShellService.h"
      90                 : #include "nsIAppStartup.h"
      91                 : #include "nsIAppStartupNotifier.h"
      92                 : #include "nsIMutableArray.h"
      93                 : #include "nsICategoryManager.h"
      94                 : #include "nsIChromeRegistry.h"
      95                 : #include "nsICommandLineRunner.h"
      96                 : #include "nsIComponentManager.h"
      97                 : #include "nsIComponentRegistrar.h"
      98                 : #include "nsIContentHandler.h"
      99                 : #include "nsIDialogParamBlock.h"
     100                 : #include "nsIDOMWindow.h"
     101                 : #include "mozilla/ModuleUtils.h"
     102                 : #include "nsIIOService2.h"
     103                 : #include "nsIObserverService.h"
     104                 : #include "nsINativeAppSupport.h"
     105                 : #include "nsIProcess.h"
     106                 : #include "nsIProfileUnlocker.h"
     107                 : #include "nsIPromptService.h"
     108                 : #include "nsIServiceManager.h"
     109                 : #include "nsIStringBundle.h"
     110                 : #include "nsISupportsPrimitives.h"
     111                 : #include "nsIToolkitChromeRegistry.h"
     112                 : #include "nsIToolkitProfile.h"
     113                 : #include "nsIToolkitProfileService.h"
     114                 : #include "nsIURI.h"
     115                 : #include "nsIWindowCreator.h"
     116                 : #include "nsIWindowMediator.h"
     117                 : #include "nsIWindowWatcher.h"
     118                 : #include "nsIXULAppInfo.h"
     119                 : #include "nsIXULRuntime.h"
     120                 : #include "nsPIDOMWindow.h"
     121                 : #include "nsIBaseWindow.h"
     122                 : #include "nsIWidget.h"
     123                 : #include "nsIDocShell.h"
     124                 : #include "nsAppShellCID.h"
     125                 : 
     126                 : #include "mozilla/FunctionTimer.h"
     127                 : #include "mozilla/unused.h"
     128                 : 
     129                 : using namespace mozilla;
     130                 : using mozilla::unused;
     131                 : 
     132                 : #ifdef XP_WIN
     133                 : #include "nsIWinAppHelper.h"
     134                 : #include <windows.h>
     135                 : #include "cairo/cairo-features.h"
     136                 : 
     137                 : #ifndef PROCESS_DEP_ENABLE
     138                 : #define PROCESS_DEP_ENABLE 0x1
     139                 : #endif
     140                 : #endif
     141                 : 
     142                 : #include "nsCRT.h"
     143                 : #include "nsCOMPtr.h"
     144                 : #include "nsDirectoryServiceDefs.h"
     145                 : #include "nsDirectoryServiceUtils.h"
     146                 : #include "nsEmbedCID.h"
     147                 : #include "nsNetUtil.h"
     148                 : #include "nsReadableUtils.h"
     149                 : #include "nsStaticComponents.h"
     150                 : #include "nsXPCOM.h"
     151                 : #include "nsXPCOMCIDInternal.h"
     152                 : #include "nsXPIDLString.h"
     153                 : #include "nsPrintfCString.h"
     154                 : #include "nsVersionComparator.h"
     155                 : 
     156                 : #include "nsAppDirectoryServiceDefs.h"
     157                 : #include "nsXULAppAPI.h"
     158                 : #include "nsXREDirProvider.h"
     159                 : #include "nsToolkitCompsCID.h"
     160                 : 
     161                 : #include "nsINIParser.h"
     162                 : #include "mozilla/Omnijar.h"
     163                 : #include "mozilla/StartupTimeline.h"
     164                 : 
     165                 : #include <stdlib.h>
     166                 : 
     167                 : #ifdef XP_UNIX
     168                 : #include <sys/stat.h>
     169                 : #include <unistd.h>
     170                 : #include <pwd.h>
     171                 : #endif
     172                 : 
     173                 : #ifdef XP_WIN
     174                 : #include <process.h>
     175                 : #include <shlobj.h>
     176                 : #include "nsThreadUtils.h"
     177                 : #endif
     178                 : 
     179                 : #ifdef XP_MACOSX
     180                 : #include "nsILocalFileMac.h"
     181                 : #include "nsCommandLineServiceMac.h"
     182                 : #endif
     183                 : 
     184                 : // for X remote support
     185                 : #ifdef MOZ_ENABLE_XREMOTE
     186                 : #include "XRemoteClient.h"
     187                 : #include "nsIRemoteService.h"
     188                 : #endif
     189                 : 
     190                 : #ifdef NS_TRACE_MALLOC
     191                 : #include "nsTraceMalloc.h"
     192                 : #endif
     193                 : 
     194                 : #if defined(DEBUG) && defined(XP_WIN32)
     195                 : #include <malloc.h>
     196                 : #endif
     197                 : 
     198                 : #if defined (XP_MACOSX)
     199                 : #include <Carbon/Carbon.h>
     200                 : #endif
     201                 : 
     202                 : #ifdef DEBUG
     203                 : #include "prlog.h"
     204                 : #endif
     205                 : 
     206                 : #ifdef MOZ_JPROF
     207                 : #include "jprof.h"
     208                 : #endif
     209                 : 
     210                 : #ifdef MOZ_CRASHREPORTER
     211                 : #include "nsExceptionHandler.h"
     212                 : #include "nsICrashReporter.h"
     213                 : #define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1"
     214                 : #include "nsIPrefService.h"
     215                 : #endif
     216                 : 
     217                 : #include "base/command_line.h"
     218                 : 
     219                 : #include "mozilla/FunctionTimer.h"
     220                 : 
     221                 : #ifdef MOZ_WIDGET_ANDROID
     222                 : #include "AndroidBridge.h"
     223                 : #endif
     224                 : 
     225                 : extern PRUint32 gRestartMode;
     226                 : extern void InstallSignalHandlers(const char *ProgramName);
     227                 : #include "nsX11ErrorHandler.h"
     228                 : 
     229                 : #define FILE_COMPATIBILITY_INFO NS_LITERAL_CSTRING("compatibility.ini")
     230                 : #define FILE_INVALIDATE_CACHES NS_LITERAL_CSTRING(".purgecaches")
     231                 : 
     232                 : int    gArgc;
     233                 : char **gArgv;
     234                 : 
     235                 : static const char gToolkitVersion[] = NS_STRINGIFY(GRE_MILESTONE);
     236                 : static const char gToolkitBuildID[] = NS_STRINGIFY(GRE_BUILDID);
     237                 : 
     238                 : static nsIProfileLock* gProfileLock;
     239                 : 
     240                 : static int    gRestartArgc;
     241                 : static char **gRestartArgv;
     242                 : 
     243                 : #ifdef MOZ_WIDGET_QT
     244                 : static int    gQtOnlyArgc;
     245                 : static char **gQtOnlyArgv;
     246                 : #endif
     247                 : 
     248                 : #if defined(MOZ_WIDGET_GTK2)
     249                 : #if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING) \
     250                 :   || defined(NS_TRACE_MALLOC)
     251                 : #define CLEANUP_MEMORY 1
     252                 : #define PANGO_ENABLE_BACKEND
     253                 : #include <pango/pangofc-fontmap.h>
     254                 : #endif
     255                 : #include <gtk/gtk.h>
     256                 : #ifdef MOZ_X11
     257                 : #include <gdk/gdkx.h>
     258                 : #endif /* MOZ_X11 */
     259                 : #include "nsGTKToolkit.h"
     260                 : #endif
     261                 : #include "BinaryPath.h"
     262                 : 
     263                 : using mozilla::dom::ContentParent;
     264                 : using mozilla::dom::ContentChild;
     265                 : 
     266                 : // Save literal putenv string to environment variable.
     267                 : static void
     268              69 : SaveToEnv(const char *putenv)
     269                 : {
     270              69 :   char *expr = strdup(putenv);
     271              69 :   if (expr)
     272              69 :     PR_SetEnv(expr);
     273                 :   // We intentionally leak |expr| here since it is required by PR_SetEnv.
     274              69 : }
     275                 : 
     276                 : // Tests that an environment variable exists and has a value
     277                 : static bool
     278              46 : EnvHasValue(const char *name)
     279                 : {
     280              46 :   const char *val = PR_GetEnv(name);
     281              46 :   return (val && *val);
     282                 : }
     283                 : 
     284                 : // Save the given word to the specified environment variable.
     285                 : static void
     286              22 : SaveWordToEnv(const char *name, const nsACString & word)
     287                 : {
     288              22 :   char *expr = PR_smprintf("%s=%s", name, PromiseFlatCString(word).get());
     289              22 :   if (expr)
     290              22 :     PR_SetEnv(expr);
     291                 :   // We intentionally leak |expr| here since it is required by PR_SetEnv.
     292              22 : }
     293                 : 
     294                 : // Save the path of the given file to the specified environment variable.
     295                 : static void
     296               0 : SaveFileToEnv(const char *name, nsIFile *file)
     297                 : {
     298                 : #ifdef XP_WIN
     299                 :   nsAutoString path;
     300                 :   file->GetPath(path);
     301                 :   SetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name).get(), path.get());
     302                 : #else
     303               0 :   nsCAutoString path;
     304               0 :   file->GetNativePath(path);
     305               0 :   SaveWordToEnv(name, path);
     306                 : #endif
     307               0 : }
     308                 : 
     309                 : // Load the path of a file saved with SaveFileToEnv
     310                 : static already_AddRefed<nsILocalFile>
     311               0 : GetFileFromEnv(const char *name)
     312                 : {
     313                 :   nsresult rv;
     314               0 :   nsILocalFile *file = nsnull;
     315                 : 
     316                 : #ifdef XP_WIN
     317                 :   WCHAR path[_MAX_PATH];
     318                 :   if (!GetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name).get(),
     319                 :                                path, _MAX_PATH))
     320                 :     return nsnull;
     321                 : 
     322                 :   rv = NS_NewLocalFile(nsDependentString(path), true, &file);
     323                 :   if (NS_FAILED(rv))
     324                 :     return nsnull;
     325                 : 
     326                 :   return file;
     327                 : #else
     328               0 :   const char *arg = PR_GetEnv(name);
     329               0 :   if (!arg || !*arg)
     330               0 :     return nsnull;
     331                 : 
     332               0 :   rv = NS_NewNativeLocalFile(nsDependentCString(arg), true, &file);
     333               0 :   if (NS_FAILED(rv))
     334               0 :     return nsnull;
     335                 : 
     336               0 :   return file;
     337                 : #endif
     338                 : }
     339                 : 
     340                 : // Save the path of the given word to the specified environment variable
     341                 : // provided the environment variable does not have a value.
     342                 : static void
     343               0 : SaveWordToEnvIfUnset(const char *name, const nsACString & word)
     344                 : {
     345               0 :   if (!EnvHasValue(name))
     346               0 :     SaveWordToEnv(name, word);
     347               0 : }
     348                 : 
     349                 : // Save the path of the given file to the specified environment variable
     350                 : // provided the environment variable does not have a value.
     351                 : static void
     352               0 : SaveFileToEnvIfUnset(const char *name, nsIFile *file)
     353                 : {
     354               0 :   if (!EnvHasValue(name))
     355               0 :     SaveFileToEnv(name, file);
     356               0 : }
     357                 : 
     358                 : static bool
     359             369 : strimatch(const char* lowerstr, const char* mixedstr)
     360                 : {
     361             949 :   while(*lowerstr) {
     362             557 :     if (!*mixedstr) return false; // mixedstr is shorter
     363             557 :     if (tolower(*mixedstr) != *lowerstr) return false; // no match
     364                 : 
     365             211 :     ++lowerstr;
     366             211 :     ++mixedstr;
     367                 :   }
     368                 : 
     369              23 :   if (*mixedstr) return false; // lowerstr is shorter
     370                 : 
     371              23 :   return true;
     372                 : }
     373                 : 
     374                 : /**
     375                 :  * Output a string to the user.  This method is really only meant to be used to
     376                 :  * output last-ditch error messages designed for developers NOT END USERS.
     377                 :  *
     378                 :  * @param isError
     379                 :  *        Pass true to indicate severe errors.
     380                 :  * @param fmt
     381                 :  *        printf-style format string followed by arguments.
     382                 :  */
     383               0 : static void Output(bool isError, const char *fmt, ... )
     384                 : {
     385                 :   va_list ap;
     386               0 :   va_start(ap, fmt);
     387                 : 
     388                 : #if defined(XP_WIN) && !MOZ_WINCONSOLE
     389                 :   char *msg = PR_vsmprintf(fmt, ap);
     390                 :   if (msg)
     391                 :   {
     392                 :     UINT flags = MB_OK;
     393                 :     if (isError)
     394                 :       flags |= MB_ICONERROR;
     395                 :     else 
     396                 :       flags |= MB_ICONINFORMATION;
     397                 : 
     398                 :     wchar_t wide_msg[1024];
     399                 :     MultiByteToWideChar(CP_ACP,
     400                 :                         0,
     401                 :                         msg,
     402                 :                         -1,
     403                 :                         wide_msg,
     404                 :                         sizeof(wide_msg) / sizeof(wchar_t));
     405                 : 
     406                 :     MessageBoxW(NULL, wide_msg, L"XULRunner", flags);
     407                 :     PR_smprintf_free(msg);
     408                 :   }
     409                 : #else
     410               0 :   vfprintf(stderr, fmt, ap);
     411                 : #endif
     412                 : 
     413               0 :   va_end(ap);
     414               0 : }
     415                 : 
     416                 : enum RemoteResult {
     417                 :   REMOTE_NOT_FOUND  = 0,
     418                 :   REMOTE_FOUND      = 1,
     419                 :   REMOTE_ARG_BAD    = 2
     420                 : };
     421                 : 
     422                 : enum ArgResult {
     423                 :   ARG_NONE  = 0,
     424                 :   ARG_FOUND = 1,
     425                 :   ARG_BAD   = 2 // you wanted a param, but there isn't one
     426                 : };
     427                 : 
     428              92 : static void RemoveArg(char **argv)
     429                 : {
     430              92 :   do {
     431              92 :     *argv = *(argv + 1);
     432              92 :     ++argv;
     433                 :   } while (*argv);
     434                 : 
     435              23 :   --gArgc;
     436              23 : }
     437                 : 
     438                 : /**
     439                 :  * Check for a commandline flag. If the flag takes a parameter, the
     440                 :  * parameter is returned in aParam. Flags may be in the form -arg or
     441                 :  * --arg (or /arg on win32/OS2).
     442                 :  *
     443                 :  * @param aArg the parameter to check. Must be lowercase.
     444                 :  * @param aCheckOSInt if true returns ARG_BAD if the osint argument is present
     445                 :  *        when aArg is also present.
     446                 :  * @param if non-null, the -arg <data> will be stored in this pointer. This is *not*
     447                 :  *        allocated, but rather a pointer to the argv data.
     448                 :  */
     449                 : static ArgResult
     450             300 : CheckArg(const char* aArg, bool aCheckOSInt = false, const char **aParam = nsnull, bool aRemArg = true)
     451                 : {
     452             300 :   NS_ABORT_IF_FALSE(gArgv, "gArgv must be initialized before CheckArg()");
     453                 : 
     454             300 :   char **curarg = gArgv + 1; // skip argv[0]
     455             300 :   ArgResult ar = ARG_NONE;
     456                 : 
     457            1477 :   while (*curarg) {
     458             900 :     char *arg = curarg[0];
     459                 : 
     460             900 :     if (arg[0] == '-'
     461                 : #if defined(XP_WIN) || defined(XP_OS2)
     462                 :         || *arg == '/'
     463                 : #endif
     464                 :         ) {
     465             369 :       ++arg;
     466             369 :       if (*arg == '-')
     467               0 :         ++arg;
     468                 : 
     469             369 :       if (strimatch(aArg, arg)) {
     470              23 :         if (aRemArg)
     471              23 :           RemoveArg(curarg);
     472              23 :         if (!aParam) {
     473              23 :           ar = ARG_FOUND;
     474              23 :           break;
     475                 :         }
     476                 : 
     477               0 :         if (*curarg) {
     478               0 :           if (**curarg == '-'
     479                 : #if defined(XP_WIN) || defined(XP_OS2)
     480                 :               || **curarg == '/'
     481                 : #endif
     482                 :               )
     483               0 :             return ARG_BAD;
     484                 : 
     485               0 :           *aParam = *curarg;
     486               0 :           if (aRemArg)
     487               0 :             RemoveArg(curarg);
     488               0 :           ar = ARG_FOUND;
     489               0 :           break;
     490                 :         }
     491               0 :         return ARG_BAD;
     492                 :       }
     493                 :     }
     494                 : 
     495             877 :     ++curarg;
     496                 :   }
     497                 : 
     498             300 :   if (aCheckOSInt && ar == ARG_FOUND) {
     499              23 :     ArgResult arOSInt = CheckArg("osint");
     500              23 :     if (arOSInt == ARG_FOUND) {
     501               0 :       ar = ARG_BAD;
     502               0 :       PR_fprintf(PR_STDERR, "Error: argument -osint is invalid\n");
     503                 :     }
     504                 :   }
     505                 : 
     506             300 :   return ar;
     507                 : }
     508                 : 
     509                 : #if defined(XP_WIN)
     510                 : /**
     511                 :  * Check for a commandline flag from the windows shell and remove it from the
     512                 :  * argv used when restarting. Flags MUST be in the form -arg.
     513                 :  *
     514                 :  * @param aArg the parameter to check. Must be lowercase.
     515                 :  */
     516                 : static ArgResult
     517                 : CheckArgShell(const char* aArg)
     518                 : {
     519                 :   char **curarg = gRestartArgv + 1; // skip argv[0]
     520                 : 
     521                 :   while (*curarg) {
     522                 :     char *arg = curarg[0];
     523                 : 
     524                 :     if (arg[0] == '-') {
     525                 :       ++arg;
     526                 : 
     527                 :       if (strimatch(aArg, arg)) {
     528                 :         do {
     529                 :           *curarg = *(curarg + 1);
     530                 :           ++curarg;
     531                 :         } while (*curarg);
     532                 : 
     533                 :         --gRestartArgc;
     534                 : 
     535                 :         return ARG_FOUND;
     536                 :       }
     537                 :     }
     538                 : 
     539                 :     ++curarg;
     540                 :   }
     541                 : 
     542                 :   return ARG_NONE;
     543                 : }
     544                 : 
     545                 : /**
     546                 :  * Enabled Native App Support to process DDE messages when the app needs to
     547                 :  * restart and the app has been launched by the Windows shell to open an url.
     548                 :  * When aWait is false this will process the DDE events manually. This prevents
     549                 :  * Windows from displaying an error message due to the DDE message not being
     550                 :  * acknowledged.
     551                 :  */
     552                 : static void
     553                 : ProcessDDE(nsINativeAppSupport* aNative, bool aWait)
     554                 : {
     555                 :   // When the app is launched by the windows shell the windows shell
     556                 :   // expects the app to be available for DDE messages and if it isn't
     557                 :   // windows displays an error dialog. To prevent the error the DDE server
     558                 :   // is enabled and pending events are processed when the app needs to
     559                 :   // restart after it was launched by the shell with the requestpending
     560                 :   // argument. The requestpending pending argument is removed to
     561                 :   // differentiate it from being launched when an app restart is not
     562                 :   // required.
     563                 :   ArgResult ar;
     564                 :   ar = CheckArgShell("requestpending");
     565                 :   if (ar == ARG_FOUND) {
     566                 :     aNative->Enable(); // enable win32 DDE responses
     567                 :     if (aWait) {
     568                 :       nsIThread *thread = NS_GetCurrentThread();
     569                 :       // This is just a guesstimate based on testing different values.
     570                 :       // If count is 8 or less windows will display an error dialog.
     571                 :       PRInt32 count = 20;
     572                 :       while(--count >= 0) {
     573                 :         NS_ProcessNextEvent(thread);
     574                 :         PR_Sleep(PR_MillisecondsToInterval(1));
     575                 :       }
     576                 :     }
     577                 :   }
     578                 : }
     579                 : #endif
     580                 : 
     581                 : bool gSafeMode = false;
     582                 : 
     583                 : /**
     584                 :  * The nsXULAppInfo object implements nsIFactory so that it can be its own
     585                 :  * singleton.
     586                 :  */
     587                 : class nsXULAppInfo : public nsIXULAppInfo,
     588                 : #ifdef XP_WIN
     589                 :                      public nsIWinAppHelper,
     590                 : #endif
     591                 : #ifdef MOZ_CRASHREPORTER
     592                 :                      public nsICrashReporter,
     593                 : #endif
     594                 :                      public nsIXULRuntime
     595                 : 
     596                 : {
     597                 : public:
     598            1464 :   nsXULAppInfo() {}
     599                 :   NS_DECL_ISUPPORTS_INHERITED
     600                 :   NS_DECL_NSIXULAPPINFO
     601                 :   NS_DECL_NSIXULRUNTIME
     602                 : #ifdef MOZ_CRASHREPORTER
     603                 :   NS_DECL_NSICRASHREPORTER
     604                 : #endif
     605                 : #ifdef XP_WIN
     606                 :   NS_DECL_NSIWINAPPHELPER
     607                 : #endif
     608                 : };
     609                 : 
     610          110381 : NS_INTERFACE_MAP_BEGIN(nsXULAppInfo)
     611          110381 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULRuntime)
     612          107528 :   NS_INTERFACE_MAP_ENTRY(nsIXULRuntime)
     613                 : #ifdef XP_WIN
     614                 :   NS_INTERFACE_MAP_ENTRY(nsIWinAppHelper)
     615                 : #endif
     616                 : #ifdef MOZ_CRASHREPORTER
     617          102807 :   NS_INTERFACE_MAP_ENTRY(nsICrashReporter)
     618                 : #endif
     619           98648 :   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIXULAppInfo, gAppData || 
     620                 :                                      XRE_GetProcessType() == GeckoProcessType_Content)
     621           98648 : NS_INTERFACE_MAP_END
     622                 : 
     623                 : NS_IMETHODIMP_(nsrefcnt)
     624           99380 : nsXULAppInfo::AddRef()
     625                 : {
     626           99380 :   return 1;
     627                 : }
     628                 : 
     629                 : NS_IMETHODIMP_(nsrefcnt)
     630           99380 : nsXULAppInfo::Release()
     631                 : {
     632           99380 :   return 1;
     633                 : }
     634                 : 
     635                 : NS_IMETHODIMP
     636               0 : nsXULAppInfo::GetVendor(nsACString& aResult)
     637                 : {
     638               0 :   if (XRE_GetProcessType() == GeckoProcessType_Content) {
     639               0 :     NS_WARNING("Attempt to get unavailable information in content process.");
     640               0 :     return NS_ERROR_NOT_AVAILABLE;
     641                 :   }
     642               0 :   aResult.Assign(gAppData->vendor);
     643                 : 
     644               0 :   return NS_OK;
     645                 : }
     646                 : 
     647                 : NS_IMETHODIMP
     648               0 : nsXULAppInfo::GetName(nsACString& aResult)
     649                 : {
     650               0 :   if (XRE_GetProcessType() == GeckoProcessType_Content) {
     651               0 :     NS_WARNING("Attempt to get unavailable information in content process.");
     652               0 :     return NS_ERROR_NOT_AVAILABLE;
     653                 :   }
     654               0 :   aResult.Assign(gAppData->name);
     655                 : 
     656               0 :   return NS_OK;
     657                 : }
     658                 : 
     659                 : NS_IMETHODIMP
     660               0 : nsXULAppInfo::GetID(nsACString& aResult)
     661                 : {
     662               0 :   if (XRE_GetProcessType() == GeckoProcessType_Content) {
     663               0 :     NS_WARNING("Attempt to get unavailable information in content process.");
     664               0 :     return NS_ERROR_NOT_AVAILABLE;
     665                 :   }
     666               0 :   aResult.Assign(gAppData->ID);
     667                 : 
     668               0 :   return NS_OK;
     669                 : }
     670                 : 
     671                 : NS_IMETHODIMP
     672               0 : nsXULAppInfo::GetVersion(nsACString& aResult)
     673                 : {
     674               0 :   if (XRE_GetProcessType() == GeckoProcessType_Content) {
     675               0 :     ContentChild* cc = ContentChild::GetSingleton();
     676               0 :     aResult = cc->GetAppInfo().version;
     677               0 :     return NS_OK;
     678                 :   }
     679               0 :   aResult.Assign(gAppData->version);
     680                 : 
     681               0 :   return NS_OK;
     682                 : }
     683                 : 
     684                 : NS_IMETHODIMP
     685               0 : nsXULAppInfo::GetPlatformVersion(nsACString& aResult)
     686                 : {
     687               0 :   aResult.Assign(gToolkitVersion);
     688                 : 
     689               0 :   return NS_OK;
     690                 : }
     691                 : 
     692                 : NS_IMETHODIMP
     693               0 : nsXULAppInfo::GetAppBuildID(nsACString& aResult)
     694                 : {
     695               0 :   if (XRE_GetProcessType() == GeckoProcessType_Content) {
     696               0 :     ContentChild* cc = ContentChild::GetSingleton();
     697               0 :     aResult = cc->GetAppInfo().buildID;
     698               0 :     return NS_OK;
     699                 :   }
     700               0 :   aResult.Assign(gAppData->buildID);
     701                 : 
     702               0 :   return NS_OK;
     703                 : }
     704                 : 
     705                 : NS_IMETHODIMP
     706               0 : nsXULAppInfo::GetPlatformBuildID(nsACString& aResult)
     707                 : {
     708               0 :   aResult.Assign(gToolkitBuildID);
     709                 : 
     710               0 :   return NS_OK;
     711                 : }
     712                 : 
     713                 : NS_IMETHODIMP
     714               0 : nsXULAppInfo::GetLogConsoleErrors(bool *aResult)
     715                 : {
     716               0 :   *aResult = gLogConsoleErrors;
     717               0 :   return NS_OK;
     718                 : }
     719                 : 
     720                 : NS_IMETHODIMP
     721               0 : nsXULAppInfo::SetLogConsoleErrors(bool aValue)
     722                 : {
     723               0 :   gLogConsoleErrors = aValue;
     724               0 :   return NS_OK;
     725                 : }
     726                 : 
     727                 : NS_IMETHODIMP
     728            1419 : nsXULAppInfo::GetInSafeMode(bool *aResult)
     729                 : {
     730            1419 :   *aResult = gSafeMode;
     731            1419 :   return NS_OK;
     732                 : }
     733                 : 
     734                 : NS_IMETHODIMP
     735              22 : nsXULAppInfo::GetOS(nsACString& aResult)
     736                 : {
     737              22 :   aResult.AssignLiteral(OS_TARGET);
     738              22 :   return NS_OK;
     739                 : }
     740                 : 
     741                 : NS_IMETHODIMP
     742             166 : nsXULAppInfo::GetXPCOMABI(nsACString& aResult)
     743                 : {
     744                 : #ifdef TARGET_XPCOM_ABI
     745             166 :   aResult.AssignLiteral(TARGET_XPCOM_ABI);
     746             166 :   return NS_OK;
     747                 : #else
     748                 :   return NS_ERROR_NOT_AVAILABLE;
     749                 : #endif
     750                 : }
     751                 : 
     752                 : NS_IMETHODIMP
     753               0 : nsXULAppInfo::GetWidgetToolkit(nsACString& aResult)
     754                 : {
     755               0 :   aResult.AssignLiteral(MOZ_WIDGET_TOOLKIT);
     756               0 :   return NS_OK;
     757                 : }
     758                 : 
     759                 : // Ensure that the GeckoProcessType enum, defined in xpcom/build/nsXULAppAPI.h,
     760                 : // is synchronized with the const unsigned longs defined in
     761                 : // xpcom/system/nsIXULRuntime.idl.
     762                 : #define SYNC_ENUMS(a,b) \
     763                 :   PR_STATIC_ASSERT(nsIXULRuntime::PROCESS_TYPE_ ## a == \
     764                 :                    static_cast<int>(GeckoProcessType_ ## b));
     765                 : 
     766                 : SYNC_ENUMS(DEFAULT, Default)
     767                 : SYNC_ENUMS(PLUGIN, Plugin)
     768                 : SYNC_ENUMS(CONTENT, Content)
     769                 : SYNC_ENUMS(IPDLUNITTEST, IPDLUnitTest)
     770                 : 
     771                 : // .. and ensure that that is all of them:
     772                 : PR_STATIC_ASSERT(GeckoProcessType_IPDLUnitTest + 1 == GeckoProcessType_End);
     773                 : 
     774                 : NS_IMETHODIMP
     775            1684 : nsXULAppInfo::GetProcessType(PRUint32* aResult)
     776                 : {
     777            1684 :   NS_ENSURE_ARG_POINTER(aResult);
     778            1684 :   *aResult = XRE_GetProcessType();
     779            1684 :   return NS_OK;
     780                 : }
     781                 : 
     782                 : NS_IMETHODIMP
     783               0 : nsXULAppInfo::EnsureContentProcess()
     784                 : {
     785               0 :   if (XRE_GetProcessType() != GeckoProcessType_Default)
     786               0 :     return NS_ERROR_NOT_AVAILABLE;
     787                 : 
     788               0 :   unused << ContentParent::GetNewOrUsed();
     789               0 :   return NS_OK;
     790                 : }
     791                 : 
     792                 : NS_IMETHODIMP
     793               0 : nsXULAppInfo::InvalidateCachesOnRestart()
     794                 : {
     795               0 :   nsCOMPtr<nsIFile> file;
     796                 :   nsresult rv = NS_GetSpecialDirectory(NS_APP_PROFILE_DIR_STARTUP, 
     797               0 :                                        getter_AddRefs(file));
     798               0 :   if (NS_FAILED(rv))
     799               0 :     return rv;
     800               0 :   if (!file)
     801               0 :     return NS_ERROR_NOT_AVAILABLE;
     802                 :   
     803               0 :   file->AppendNative(FILE_COMPATIBILITY_INFO);
     804                 : 
     805               0 :   nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(file));
     806               0 :   nsINIParser parser;
     807               0 :   rv = parser.Init(localFile);
     808               0 :   if (NS_FAILED(rv)) {
     809                 :     // This fails if compatibility.ini is not there, so we'll
     810                 :     // flush the caches on the next restart anyways.
     811               0 :     return NS_OK;
     812                 :   }
     813                 :   
     814               0 :   nsCAutoString buf;
     815               0 :   rv = parser.GetString("Compatibility", "InvalidateCaches", buf);
     816                 :   
     817               0 :   if (NS_FAILED(rv)) {
     818               0 :     PRFileDesc *fd = nsnull;
     819               0 :     localFile->OpenNSPRFileDesc(PR_RDWR | PR_APPEND, 0600, &fd);
     820               0 :     if (!fd) {
     821               0 :       NS_ERROR("could not create output stream");
     822               0 :       return NS_ERROR_NOT_AVAILABLE;
     823                 :     }
     824                 :     static const char kInvalidationHeader[] = NS_LINEBREAK "InvalidateCaches=1" NS_LINEBREAK;
     825               0 :     rv = PR_Write(fd, kInvalidationHeader, sizeof(kInvalidationHeader) - 1);
     826               0 :     PR_Close(fd);
     827                 :     
     828               0 :     if (NS_FAILED(rv))
     829               0 :       return rv;
     830                 :   }
     831               0 :   return NS_OK;
     832                 : }
     833                 : 
     834                 : NS_IMETHODIMP
     835               0 : nsXULAppInfo::GetReplacedLockTime(PRInt64 *aReplacedLockTime)
     836                 : {
     837               0 :   if (!gProfileLock)
     838               0 :     return NS_ERROR_NOT_AVAILABLE;
     839               0 :   gProfileLock->GetReplacedLockTime(aReplacedLockTime);
     840               0 :   return NS_OK;
     841                 : }
     842                 : 
     843                 : #ifdef XP_WIN
     844                 : // Matches the enum in WinNT.h for the Vista SDK but renamed so that we can
     845                 : // safely build with the Vista SDK and without it.
     846                 : typedef enum 
     847                 : {
     848                 :   VistaTokenElevationTypeDefault = 1,
     849                 :   VistaTokenElevationTypeFull,
     850                 :   VistaTokenElevationTypeLimited
     851                 : } VISTA_TOKEN_ELEVATION_TYPE;
     852                 : 
     853                 : // avoid collision with TokeElevationType enum in WinNT.h
     854                 : // of the Vista SDK
     855                 : #define VistaTokenElevationType static_cast< TOKEN_INFORMATION_CLASS >( 18 )
     856                 : 
     857                 : NS_IMETHODIMP
     858                 : nsXULAppInfo::GetUserCanElevate(bool *aUserCanElevate)
     859                 : {
     860                 :   HANDLE hToken;
     861                 : 
     862                 :   VISTA_TOKEN_ELEVATION_TYPE elevationType;
     863                 :   DWORD dwSize; 
     864                 : 
     865                 :   if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken) ||
     866                 :       !GetTokenInformation(hToken, VistaTokenElevationType, &elevationType,
     867                 :                            sizeof(elevationType), &dwSize)) {
     868                 :     *aUserCanElevate = false;
     869                 :   } 
     870                 :   else {
     871                 :     // The possible values returned for elevationType and their meanings are:
     872                 :     //   TokenElevationTypeDefault: The token does not have a linked token 
     873                 :     //     (e.g. UAC disabled or a standard user, so they can't be elevated)
     874                 :     //   TokenElevationTypeFull: The token is linked to an elevated token 
     875                 :     //     (e.g. UAC is enabled and the user is already elevated so they can't
     876                 :     //      be elevated again)
     877                 :     //   TokenElevationTypeLimited: The token is linked to a limited token 
     878                 :     //     (e.g. UAC is enabled and the user is not elevated, so they can be
     879                 :     //      elevated)
     880                 :     *aUserCanElevate = (elevationType == VistaTokenElevationTypeLimited);
     881                 :   }
     882                 : 
     883                 :   if (hToken)
     884                 :     CloseHandle(hToken);
     885                 : 
     886                 :   return NS_OK;
     887                 : }
     888                 : #endif
     889                 : 
     890                 : #ifdef MOZ_CRASHREPORTER
     891                 : NS_IMETHODIMP
     892               0 : nsXULAppInfo::GetEnabled(bool *aEnabled)
     893                 : {
     894               0 :   *aEnabled = CrashReporter::GetEnabled();
     895               0 :   return NS_OK;
     896                 : }
     897                 : 
     898                 : NS_IMETHODIMP
     899            2773 : nsXULAppInfo::SetEnabled(bool aEnabled)
     900                 : {
     901            2773 :   if (aEnabled) {
     902            1386 :     if (CrashReporter::GetEnabled())
     903                 :       // no point in erroring for double-enabling
     904               0 :       return NS_OK;
     905                 : 
     906            2772 :     nsCOMPtr<nsILocalFile> xreDirectory;
     907            1386 :     if (gAppData) {
     908               0 :       xreDirectory = gAppData->xreDirectory;
     909                 :     }
     910                 :     else {
     911                 :       // We didn't get started through XRE_Main, probably
     912            2772 :       nsCOMPtr<nsIFile> greDir;
     913            1386 :       NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(greDir));
     914            1386 :       if (!greDir)
     915               0 :         return NS_ERROR_FAILURE;
     916                 : 
     917            1386 :       xreDirectory = do_QueryInterface(greDir);
     918            1386 :       if (!xreDirectory)
     919               0 :         return NS_ERROR_FAILURE;
     920                 :     }
     921            1386 :     return CrashReporter::SetExceptionHandler(xreDirectory, true);
     922                 :   }
     923                 :   else {
     924            1387 :     if (!CrashReporter::GetEnabled())
     925                 :       // no point in erroring for double-disabling
     926               1 :       return NS_OK;
     927                 : 
     928            1386 :     return CrashReporter::UnsetExceptionHandler();
     929                 :   }
     930                 : }
     931                 : 
     932                 : NS_IMETHODIMP
     933               0 : nsXULAppInfo::GetServerURL(nsIURL** aServerURL)
     934                 : {
     935               0 :   if (!CrashReporter::GetEnabled())
     936               0 :     return NS_ERROR_NOT_INITIALIZED;
     937                 : 
     938               0 :   nsCAutoString data;
     939               0 :   if (!CrashReporter::GetServerURL(data)) {
     940               0 :     return NS_ERROR_FAILURE;
     941                 :   }
     942               0 :   nsCOMPtr<nsIURI> uri;
     943               0 :   NS_NewURI(getter_AddRefs(uri), data);
     944               0 :   if (!uri)
     945               0 :     return NS_ERROR_FAILURE;
     946                 : 
     947               0 :   nsCOMPtr<nsIURL> url;
     948               0 :   url = do_QueryInterface(uri);
     949               0 :   NS_ADDREF(*aServerURL = url);
     950                 : 
     951               0 :   return NS_OK;
     952                 : }
     953                 : 
     954                 : NS_IMETHODIMP
     955               0 : nsXULAppInfo::SetServerURL(nsIURL* aServerURL)
     956                 : {
     957                 :   bool schemeOk;
     958                 :   // only allow https or http URLs
     959               0 :   nsresult rv = aServerURL->SchemeIs("https", &schemeOk);
     960               0 :   NS_ENSURE_SUCCESS(rv, rv);
     961               0 :   if (!schemeOk) {
     962               0 :     rv = aServerURL->SchemeIs("http", &schemeOk);
     963               0 :     NS_ENSURE_SUCCESS(rv, rv);
     964                 : 
     965               0 :     if (!schemeOk)
     966               0 :       return NS_ERROR_INVALID_ARG;
     967                 :   }
     968               0 :   nsCAutoString spec;
     969               0 :   rv = aServerURL->GetSpec(spec);
     970               0 :   NS_ENSURE_SUCCESS(rv, rv);
     971                 :   
     972               0 :   return CrashReporter::SetServerURL(spec);
     973                 : }
     974                 : 
     975                 : NS_IMETHODIMP
     976               0 : nsXULAppInfo::GetMinidumpPath(nsILocalFile** aMinidumpPath)
     977                 : {
     978               0 :   if (!CrashReporter::GetEnabled())
     979               0 :     return NS_ERROR_NOT_INITIALIZED;
     980                 : 
     981               0 :   nsAutoString path;
     982               0 :   if (!CrashReporter::GetMinidumpPath(path))
     983               0 :     return NS_ERROR_FAILURE;
     984                 : 
     985               0 :   nsresult rv = NS_NewLocalFile(path, false, aMinidumpPath);
     986               0 :   NS_ENSURE_SUCCESS(rv, rv);
     987               0 :   return NS_OK;
     988                 : }
     989                 : 
     990                 : NS_IMETHODIMP
     991            1386 : nsXULAppInfo::SetMinidumpPath(nsILocalFile* aMinidumpPath)
     992                 : {
     993            2772 :   nsAutoString path;
     994            1386 :   nsresult rv = aMinidumpPath->GetPath(path);
     995            1386 :   NS_ENSURE_SUCCESS(rv, rv);
     996            1386 :   return CrashReporter::SetMinidumpPath(path);
     997                 : }
     998                 : 
     999                 : NS_IMETHODIMP
    1000               0 : nsXULAppInfo::AnnotateCrashReport(const nsACString& key,
    1001                 :                                   const nsACString& data)
    1002                 : {
    1003               0 :   return CrashReporter::AnnotateCrashReport(key, data);
    1004                 : }
    1005                 : 
    1006                 : NS_IMETHODIMP
    1007               0 : nsXULAppInfo::AppendAppNotesToCrashReport(const nsACString& data)
    1008                 : {
    1009               0 :   return CrashReporter::AppendAppNotesToCrashReport(data);
    1010                 : }
    1011                 : 
    1012                 : NS_IMETHODIMP
    1013               0 : nsXULAppInfo::RegisterAppMemory(PRUint64 pointer,
    1014                 :                                 PRUint64 len)
    1015                 : {
    1016               0 :   return CrashReporter::RegisterAppMemory((void *)pointer, len);
    1017                 : }
    1018                 : 
    1019                 : NS_IMETHODIMP
    1020               0 : nsXULAppInfo::WriteMinidumpForException(void* aExceptionInfo)
    1021                 : {
    1022                 : #ifdef XP_WIN32
    1023                 :   return CrashReporter::WriteMinidumpForException(static_cast<EXCEPTION_POINTERS*>(aExceptionInfo));
    1024                 : #else
    1025               0 :   return NS_ERROR_NOT_IMPLEMENTED;
    1026                 : #endif
    1027                 : }
    1028                 : 
    1029                 : NS_IMETHODIMP
    1030               0 : nsXULAppInfo::AppendObjCExceptionInfoToAppNotes(void* aException)
    1031                 : {
    1032                 : #ifdef XP_MACOSX
    1033                 :   return CrashReporter::AppendObjCExceptionInfoToAppNotes(aException);
    1034                 : #else
    1035               0 :   return NS_ERROR_NOT_IMPLEMENTED;
    1036                 : #endif
    1037                 : }
    1038                 : 
    1039                 : NS_IMETHODIMP
    1040               0 : nsXULAppInfo::GetSubmitReports(bool* aEnabled)
    1041                 : {
    1042               0 :   return CrashReporter::GetSubmitReports(aEnabled);
    1043                 : }
    1044                 : 
    1045                 : NS_IMETHODIMP
    1046               0 : nsXULAppInfo::SetSubmitReports(bool aEnabled)
    1047                 : {
    1048               0 :   return CrashReporter::SetSubmitReports(aEnabled);
    1049                 : }
    1050                 : 
    1051                 : #endif
    1052                 : 
    1053            1464 : static const nsXULAppInfo kAppInfo;
    1054            8514 : static nsresult AppInfoConstructor(nsISupports* aOuter,
    1055                 :                                    REFNSIID aIID, void **aResult)
    1056                 : {
    1057            8514 :   NS_ENSURE_NO_AGGREGATION(aOuter);
    1058                 : 
    1059                 :   return const_cast<nsXULAppInfo*>(&kAppInfo)->
    1060            8514 :     QueryInterface(aIID, aResult);
    1061                 : }
    1062                 : 
    1063                 : bool gLogConsoleErrors
    1064                 : #ifdef DEBUG
    1065                 :          = true;
    1066                 : #else
    1067                 :          = false;
    1068                 : #endif
    1069                 : 
    1070                 : #define NS_ENSURE_TRUE_LOG(x, ret)               \
    1071                 :   PR_BEGIN_MACRO                                 \
    1072                 :   if (NS_UNLIKELY(!(x))) {                       \
    1073                 :     NS_WARNING("NS_ENSURE_TRUE(" #x ") failed"); \
    1074                 :     gLogConsoleErrors = true;                 \
    1075                 :     return ret;                                  \
    1076                 :   }                                              \
    1077                 :   PR_END_MACRO
    1078                 : 
    1079                 : #define NS_ENSURE_SUCCESS_LOG(res, ret)          \
    1080                 :   NS_ENSURE_TRUE_LOG(NS_SUCCEEDED(res), ret)
    1081                 : 
    1082                 : /**
    1083                 :  * Because we're starting/stopping XPCOM several times in different scenarios,
    1084                 :  * this class is a stack-based critter that makes sure that XPCOM is shut down
    1085                 :  * during early returns.
    1086                 :  */
    1087                 : 
    1088                 : class ScopedXPCOMStartup
    1089                 : {
    1090                 : public:
    1091               0 :   ScopedXPCOMStartup() :
    1092               0 :     mServiceManager(nsnull) { }
    1093                 :   ~ScopedXPCOMStartup();
    1094                 : 
    1095                 :   nsresult Initialize();
    1096                 :   nsresult SetWindowCreator(nsINativeAppSupport* native);
    1097                 : 
    1098                 :   static nsresult CreateAppSupport(nsISupports* aOuter, REFNSIID aIID, void** aResult);
    1099                 : 
    1100                 : private:
    1101                 :   nsIServiceManager* mServiceManager;
    1102                 :   static nsINativeAppSupport* gNativeAppSupport;
    1103                 : };
    1104                 : 
    1105               0 : ScopedXPCOMStartup::~ScopedXPCOMStartup()
    1106                 : {
    1107               0 :   NS_IF_RELEASE(gNativeAppSupport);
    1108                 : 
    1109               0 :   if (mServiceManager) {
    1110                 : #ifdef XP_MACOSX
    1111                 :     // On OS X, we need a pool to catch cocoa objects that are autoreleased
    1112                 :     // during teardown.
    1113                 :     mozilla::MacAutoreleasePool pool;
    1114                 : #endif
    1115                 : 
    1116               0 :     nsCOMPtr<nsIAppStartup> appStartup (do_GetService(NS_APPSTARTUP_CONTRACTID));
    1117               0 :     if (appStartup)
    1118               0 :       appStartup->DestroyHiddenWindow();
    1119                 : 
    1120               0 :     gDirServiceProvider->DoShutdown();
    1121                 : 
    1122               0 :     WriteConsoleLog();
    1123                 : 
    1124               0 :     NS_ShutdownXPCOM(mServiceManager);
    1125               0 :     mServiceManager = nsnull;
    1126                 :   }
    1127               0 : }
    1128                 : 
    1129                 : // {95d89e3e-a169-41a3-8e56-719978e15b12}
    1130                 : #define APPINFO_CID \
    1131                 :   { 0x95d89e3e, 0xa169, 0x41a3, { 0x8e, 0x56, 0x71, 0x99, 0x78, 0xe1, 0x5b, 0x12 } }
    1132                 : 
    1133                 : // {0C4A446C-EE82-41f2-8D04-D366D2C7A7D4}
    1134                 : static const nsCID kNativeAppSupportCID =
    1135                 :   { 0xc4a446c, 0xee82, 0x41f2, { 0x8d, 0x4, 0xd3, 0x66, 0xd2, 0xc7, 0xa7, 0xd4 } };
    1136                 : 
    1137                 : // {5F5E59CE-27BC-47eb-9D1F-B09CA9049836}
    1138                 : static const nsCID kProfileServiceCID =
    1139                 :   { 0x5f5e59ce, 0x27bc, 0x47eb, { 0x9d, 0x1f, 0xb0, 0x9c, 0xa9, 0x4, 0x98, 0x36 } };
    1140                 : 
    1141                 : static already_AddRefed<nsIFactory>
    1142               0 : ProfileServiceFactoryConstructor(const mozilla::Module& module, const mozilla::Module::CIDEntry& entry)
    1143                 : {
    1144               0 :   nsCOMPtr<nsIFactory> factory;
    1145               0 :   NS_NewToolkitProfileFactory(getter_AddRefs(factory));
    1146               0 :   return factory.forget();
    1147                 : }
    1148                 : 
    1149                 : NS_DEFINE_NAMED_CID(APPINFO_CID);
    1150                 : 
    1151                 : static const mozilla::Module::CIDEntry kXRECIDs[] = {
    1152                 :   { &kAPPINFO_CID, false, NULL, AppInfoConstructor },
    1153                 :   { &kProfileServiceCID, false, ProfileServiceFactoryConstructor, NULL },
    1154                 :   { &kNativeAppSupportCID, false, NULL, ScopedXPCOMStartup::CreateAppSupport },
    1155                 :   { NULL }
    1156                 : };
    1157                 : 
    1158                 : static const mozilla::Module::ContractIDEntry kXREContracts[] = {
    1159                 :   { XULAPPINFO_SERVICE_CONTRACTID, &kAPPINFO_CID },
    1160                 :   { XULRUNTIME_SERVICE_CONTRACTID, &kAPPINFO_CID },
    1161                 : #ifdef MOZ_CRASHREPORTER
    1162                 :   { NS_CRASHREPORTER_CONTRACTID, &kAPPINFO_CID },
    1163                 : #endif
    1164                 :   { NS_PROFILESERVICE_CONTRACTID, &kProfileServiceCID },
    1165                 :   { NS_NATIVEAPPSUPPORT_CONTRACTID, &kNativeAppSupportCID },
    1166                 :   { NULL }
    1167                 : };
    1168                 : 
    1169                 : static const mozilla::Module kXREModule = {
    1170                 :   mozilla::Module::kVersion,
    1171                 :   kXRECIDs,
    1172                 :   kXREContracts
    1173                 : };
    1174                 : 
    1175                 : NSMODULE_DEFN(Apprunner) = &kXREModule;
    1176                 : 
    1177                 : nsresult
    1178               0 : ScopedXPCOMStartup::Initialize()
    1179                 : {
    1180               0 :   NS_ASSERTION(gDirServiceProvider, "Should not get here!");
    1181                 : 
    1182                 :   nsresult rv;
    1183                 : 
    1184                 :   rv = NS_InitXPCOM2(&mServiceManager, gDirServiceProvider->GetAppDir(),
    1185               0 :                      gDirServiceProvider);
    1186               0 :   if (NS_FAILED(rv)) {
    1187               0 :     NS_ERROR("Couldn't start xpcom!");
    1188               0 :     mServiceManager = nsnull;
    1189                 :   }
    1190                 :   else {
    1191                 :     nsCOMPtr<nsIComponentRegistrar> reg =
    1192               0 :       do_QueryInterface(mServiceManager);
    1193               0 :     NS_ASSERTION(reg, "Service Manager doesn't QI to Registrar.");
    1194                 :   }
    1195                 : 
    1196               0 :   return rv;
    1197                 : }
    1198                 : 
    1199                 : /**
    1200                 :  * This is a little factory class that serves as a singleton-service-factory
    1201                 :  * for the nativeappsupport object.
    1202                 :  */
    1203                 : class nsSingletonFactory : public nsIFactory
    1204                 : {
    1205                 : public:
    1206                 :   NS_DECL_ISUPPORTS
    1207                 :   NS_DECL_NSIFACTORY
    1208                 : 
    1209                 :   nsSingletonFactory(nsISupports* aSingleton);
    1210               0 :   ~nsSingletonFactory() { }
    1211                 : 
    1212                 : private:
    1213                 :   nsCOMPtr<nsISupports> mSingleton;
    1214                 : };
    1215                 : 
    1216               0 : nsSingletonFactory::nsSingletonFactory(nsISupports* aSingleton)
    1217               0 :   : mSingleton(aSingleton)
    1218                 : {
    1219               0 :   NS_ASSERTION(mSingleton, "Singleton was null!");
    1220               0 : }
    1221                 : 
    1222               0 : NS_IMPL_ISUPPORTS1(nsSingletonFactory, nsIFactory)
    1223                 : 
    1224                 : NS_IMETHODIMP
    1225               0 : nsSingletonFactory::CreateInstance(nsISupports* aOuter,
    1226                 :                                    const nsIID& aIID,
    1227                 :                                    void* *aResult)
    1228                 : {
    1229               0 :   NS_ENSURE_NO_AGGREGATION(aOuter);
    1230                 : 
    1231               0 :   return mSingleton->QueryInterface(aIID, aResult);
    1232                 : }
    1233                 : 
    1234                 : NS_IMETHODIMP
    1235               0 : nsSingletonFactory::LockFactory(bool)
    1236                 : {
    1237               0 :   return NS_OK;
    1238                 : }
    1239                 : 
    1240                 : /**
    1241                 :  * Set our windowcreator on the WindowWatcher service.
    1242                 :  */
    1243                 : nsresult
    1244               0 : ScopedXPCOMStartup::SetWindowCreator(nsINativeAppSupport* native)
    1245                 : {
    1246                 :   NS_TIME_FUNCTION;
    1247                 :   nsresult rv;
    1248                 : 
    1249               0 :   NS_IF_ADDREF(gNativeAppSupport = native);
    1250                 : 
    1251                 :   // Inform the chrome registry about OS accessibility
    1252                 :   nsCOMPtr<nsIToolkitChromeRegistry> cr =
    1253               0 :     mozilla::services::GetToolkitChromeRegistryService();
    1254                 :   NS_TIME_FUNCTION_MARK("Got ToolkitChromeRegistry service");
    1255                 : 
    1256               0 :   if (cr)
    1257               0 :     cr->CheckForOSAccessibility();
    1258                 : 
    1259                 :   NS_TIME_FUNCTION_MARK("OS Accessibility check");
    1260                 : 
    1261               0 :   nsCOMPtr<nsIWindowCreator> creator (do_GetService(NS_APPSTARTUP_CONTRACTID));
    1262               0 :   if (!creator) return NS_ERROR_UNEXPECTED;
    1263                 : 
    1264                 :   NS_TIME_FUNCTION_MARK("Got AppStartup service");
    1265                 : 
    1266                 :   nsCOMPtr<nsIWindowWatcher> wwatch
    1267               0 :     (do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv));
    1268               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1269                 :   
    1270                 :   NS_TIME_FUNCTION_MARK("Got WindowWatcher service");
    1271                 : 
    1272               0 :   return wwatch->SetWindowCreator(creator);
    1273                 : }
    1274                 : 
    1275                 : /* static */ nsresult
    1276               0 : ScopedXPCOMStartup::CreateAppSupport(nsISupports* aOuter, REFNSIID aIID, void** aResult)
    1277                 : {
    1278               0 :   if (aOuter)
    1279               0 :     return NS_ERROR_NO_AGGREGATION;
    1280                 : 
    1281               0 :   if (!gNativeAppSupport)
    1282               0 :     return NS_ERROR_NOT_INITIALIZED;
    1283                 : 
    1284               0 :   return gNativeAppSupport->QueryInterface(aIID, aResult);
    1285                 : }
    1286                 : 
    1287                 : nsINativeAppSupport* ScopedXPCOMStartup::gNativeAppSupport;
    1288                 : 
    1289                 : /**
    1290                 :  * A helper class which calls NS_LogInit/NS_LogTerm in its scope.
    1291                 :  */
    1292                 : class ScopedLogging
    1293                 : {
    1294                 : public:
    1295              23 :   ScopedLogging() { NS_LogInit(); }
    1296              23 :   ~ScopedLogging() { NS_LogTerm(); }
    1297                 : };
    1298                 : 
    1299               0 : static void DumpArbitraryHelp()
    1300                 : {
    1301                 :   nsresult rv;
    1302                 : 
    1303               0 :   ScopedLogging log;
    1304                 : 
    1305                 :   {
    1306               0 :     ScopedXPCOMStartup xpcom;
    1307               0 :     xpcom.Initialize();
    1308                 : 
    1309                 :     nsCOMPtr<nsICommandLineRunner> cmdline
    1310               0 :       (do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
    1311               0 :     if (!cmdline)
    1312                 :       return;
    1313                 : 
    1314               0 :     nsCString text;
    1315               0 :     rv = cmdline->GetHelpText(text);
    1316               0 :     if (NS_SUCCEEDED(rv))
    1317               0 :       printf("%s", text.get());
    1318                 :   }
    1319                 : }
    1320                 : 
    1321                 : // English text needs to go into a dtd file.
    1322                 : // But when this is called we have no components etc. These strings must either be
    1323                 : // here, or in a native resource file.
    1324                 : static void
    1325               0 : DumpHelp()
    1326                 : {
    1327                 :   printf("Usage: %s [ options ... ] [URL]\n"
    1328               0 :          "       where options include:\n\n", gArgv[0]);
    1329                 : 
    1330                 : #ifdef MOZ_X11
    1331                 :   printf("X11 options\n"
    1332                 :          "  --display=DISPLAY  X display to use\n"
    1333               0 :          "  --sync             Make X calls synchronous\n");
    1334                 : #endif
    1335                 : #ifdef XP_UNIX
    1336                 :   printf("  --g-fatal-warnings Make all warnings fatal\n"
    1337               0 :          "\n%s options\n", gAppData->name);
    1338                 : #endif
    1339                 : 
    1340                 :   printf("  -h or -help        Print this message.\n"
    1341                 :          "  -v or -version     Print %s version.\n"
    1342                 :          "  -P <profile>       Start with <profile>.\n"
    1343                 :          "  -migration         Start with migration wizard.\n"
    1344                 :          "  -ProfileManager    Start with ProfileManager.\n"
    1345                 :          "  -no-remote         Do not accept or send remote commands; implies -new-instance.\n"
    1346                 :          "  -new-instance      Open new instance, not a new window in running instance.\n"
    1347                 :          "  -UILocale <locale> Start with <locale> resources as UI Locale.\n"
    1348               0 :          "  -safe-mode         Disables extensions and themes for this session.\n", gAppData->name);
    1349                 : 
    1350                 : #if defined(XP_WIN) || defined(XP_OS2)
    1351                 :   printf("  -console           Start %s with a debugging console.\n", gAppData->name);
    1352                 : #endif
    1353                 : 
    1354                 :   // this works, but only after the components have registered.  so if you drop in a new command line handler, -help
    1355                 :   // won't not until the second run.
    1356                 :   // out of the bug, because we ship a component.reg file, it works correctly.
    1357               0 :   DumpArbitraryHelp();
    1358               0 : }
    1359                 : 
    1360                 : #ifdef DEBUG_warren
    1361                 : #ifdef XP_WIN
    1362                 : #define _CRTDBG_MAP_ALLOC
    1363                 : #include <crtdbg.h>
    1364                 : #endif
    1365                 : #endif
    1366                 : 
    1367                 : #if defined(FREEBSD)
    1368                 : // pick up fpsetmask prototype.
    1369                 : #include <ieeefp.h>
    1370                 : #endif
    1371                 : 
    1372                 : static inline void
    1373               0 : DumpVersion()
    1374                 : {
    1375                 :   printf("%s %s %s", 
    1376               0 :          gAppData->vendor ? gAppData->vendor : "", gAppData->name, gAppData->version);
    1377               0 :   if (gAppData->copyright)
    1378               0 :       printf(", %s", gAppData->copyright);
    1379               0 :   printf("\n");
    1380               0 : }
    1381                 : 
    1382                 : #ifdef MOZ_ENABLE_XREMOTE
    1383                 : // use int here instead of a PR type since it will be returned
    1384                 : // from main - just to keep types consistent
    1385                 : static int
    1386               0 : HandleRemoteArgument(const char* remote, const char* aDesktopStartupID)
    1387                 : {
    1388                 :   nsresult rv;
    1389                 :   ArgResult ar;
    1390                 : 
    1391               0 :   const char *profile = 0;
    1392               0 :   nsCAutoString program(gAppData->name);
    1393               0 :   ToLowerCase(program);
    1394               0 :   const char *username = getenv("LOGNAME");
    1395                 : 
    1396               0 :   ar = CheckArg("p", false, &profile);
    1397               0 :   if (ar == ARG_BAD) {
    1398               0 :     PR_fprintf(PR_STDERR, "Error: argument -p requires a profile name\n");
    1399               0 :     return 1;
    1400                 :   }
    1401                 : 
    1402               0 :   const char *temp = nsnull;
    1403               0 :   ar = CheckArg("a", false, &temp);
    1404               0 :   if (ar == ARG_BAD) {
    1405               0 :     PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n");
    1406               0 :     return 1;
    1407               0 :   } else if (ar == ARG_FOUND) {
    1408               0 :     program.Assign(temp);
    1409                 :   }
    1410                 : 
    1411               0 :   ar = CheckArg("u", false, &username);
    1412               0 :   if (ar == ARG_BAD) {
    1413               0 :     PR_fprintf(PR_STDERR, "Error: argument -u requires a username\n");
    1414               0 :     return 1;
    1415                 :   }
    1416                 : 
    1417               0 :   XRemoteClient client;
    1418               0 :   rv = client.Init();
    1419               0 :   if (NS_FAILED(rv)) {
    1420               0 :     PR_fprintf(PR_STDERR, "Error: Failed to connect to X server.\n");
    1421               0 :     return 1;
    1422                 :   }
    1423                 : 
    1424               0 :   nsXPIDLCString response;
    1425               0 :   bool success = false;
    1426                 :   rv = client.SendCommand(program.get(), username, profile, remote,
    1427               0 :                           aDesktopStartupID, getter_Copies(response), &success);
    1428                 :   // did the command fail?
    1429               0 :   if (NS_FAILED(rv)) {
    1430                 :     PR_fprintf(PR_STDERR, "Error: Failed to send command: %s\n",
    1431               0 :                response ? response.get() : "No response included");
    1432               0 :     return 1;
    1433                 :   }
    1434                 : 
    1435               0 :   if (!success) {
    1436               0 :     PR_fprintf(PR_STDERR, "Error: No running window found\n");
    1437               0 :     return 2;
    1438                 :   }
    1439                 : 
    1440               0 :   return 0;
    1441                 : }
    1442                 : 
    1443                 : static RemoteResult
    1444               0 : RemoteCommandLine(const char* aDesktopStartupID)
    1445                 : {
    1446                 :   nsresult rv;
    1447                 :   ArgResult ar;
    1448                 : 
    1449               0 :   nsCAutoString program(gAppData->name);
    1450               0 :   ToLowerCase(program);
    1451               0 :   const char *username = getenv("LOGNAME");
    1452                 : 
    1453               0 :   const char *temp = nsnull;
    1454               0 :   ar = CheckArg("a", true, &temp);
    1455               0 :   if (ar == ARG_BAD) {
    1456               0 :     PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n");
    1457               0 :     return REMOTE_ARG_BAD;
    1458               0 :   } else if (ar == ARG_FOUND) {
    1459               0 :     program.Assign(temp);
    1460                 :   }
    1461                 : 
    1462               0 :   ar = CheckArg("u", true, &username);
    1463               0 :   if (ar == ARG_BAD) {
    1464               0 :     PR_fprintf(PR_STDERR, "Error: argument -u requires a username\n");
    1465               0 :     return REMOTE_ARG_BAD;
    1466                 :   }
    1467                 : 
    1468               0 :   XRemoteClient client;
    1469               0 :   rv = client.Init();
    1470               0 :   if (NS_FAILED(rv))
    1471               0 :     return REMOTE_NOT_FOUND;
    1472                 :  
    1473               0 :   nsXPIDLCString response;
    1474               0 :   bool success = false;
    1475                 :   rv = client.SendCommandLine(program.get(), username, nsnull,
    1476                 :                               gArgc, gArgv, aDesktopStartupID,
    1477               0 :                               getter_Copies(response), &success);
    1478                 :   // did the command fail?
    1479               0 :   if (NS_FAILED(rv) || !success)
    1480               0 :     return REMOTE_NOT_FOUND;
    1481                 : 
    1482               0 :   return REMOTE_FOUND;
    1483                 : }
    1484                 : #endif // MOZ_ENABLE_XREMOTE
    1485                 : 
    1486                 : void
    1487               0 : XRE_InitOmnijar(nsILocalFile* greOmni, nsILocalFile* appOmni)
    1488                 : {
    1489               0 :   mozilla::Omnijar::Init(greOmni, appOmni);
    1490               0 : }
    1491                 : 
    1492                 : nsresult
    1493            1434 : XRE_GetBinaryPath(const char* argv0, nsILocalFile* *aResult)
    1494                 : {
    1495            1434 :   return mozilla::BinaryPath::GetFile(argv0, aResult);
    1496                 : }
    1497                 : 
    1498                 : #define NS_ERROR_LAUNCHED_CHILD_PROCESS NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_PROFILE, 200)
    1499                 : 
    1500                 : #ifdef XP_WIN
    1501                 : #include "nsWindowsRestart.cpp"
    1502                 : #include <shellapi.h>
    1503                 : 
    1504                 : typedef BOOL (WINAPI* SetProcessDEPPolicyFunc)(DWORD dwFlags);
    1505                 : #endif
    1506                 : 
    1507                 : #if defined(XP_OS2) && (__KLIBC__ == 0 && __KLIBC_MINOR__ >= 6) // broken kLibc
    1508                 : // Copy the environment maintained by the C library into an ASCIIZ array
    1509                 : // that can be used to pass it on to the OS/2 Dos* APIs (which otherwise
    1510                 : // don't know anything about the stuff set by PR_SetEnv() or setenv()).
    1511                 : char *createEnv()
    1512                 : {
    1513                 :   // just allocate the maximum amount (24 kB = 0x60000 bytes), to be able to
    1514                 :   // copy the existing environment
    1515                 :   char *env = (char *)calloc(0x6000, sizeof(char));
    1516                 :   if (!env) {
    1517                 :     return NULL;
    1518                 :   }
    1519                 : 
    1520                 :   // walk along the environ string array of the C library and copy
    1521                 :   // everything (that fits) into the output environment array, leaving
    1522                 :   // null bytes between the entries
    1523                 :   char *penv = env; // movable pointer to result environment ASCIIZ array
    1524                 :   int i = 0, space = 0x6000;
    1525                 :   while (environ[i] && environ[i][0]) {
    1526                 :     int len = strlen(environ[i]);
    1527                 :     if (space - len <= 0) {
    1528                 :       break;
    1529                 :     }
    1530                 :     strcpy(penv, environ[i]);
    1531                 :     i++; // next environment variable
    1532                 :     penv += len + 1; // jump to after next null byte
    1533                 :     space -= len - 1; // subtract consumed length from usable space
    1534                 :   }
    1535                 : 
    1536                 :   return env;
    1537                 : }
    1538                 : 
    1539                 : // OS2LaunchChild() is there to replace _execv() which is broken in the C
    1540                 : // runtime library that comes with GCC 3.3.5 on OS/2. It uses createEnv()
    1541                 : // to copy the process environment and add necessary variables
    1542                 : //
    1543                 : // returns -1 on failure and 0 on success
    1544                 : int OS2LaunchChild(const char *aExePath, int aArgc, char **aArgv)
    1545                 : {
    1546                 :   // find total length of aArgv
    1547                 :   int len = 0;
    1548                 :   for (int i = 0; i < aArgc; i++) {
    1549                 :     len += strlen(aArgv[i]) + 1; // plus space in between
    1550                 :   }
    1551                 :   len++; // leave space for null byte at end
    1552                 :   // allocate enough space for all strings and nulls,
    1553                 :   // calloc helpfully initializes to null
    1554                 :   char *args = (char *)calloc(len, sizeof(char));
    1555                 :   if (!args) {
    1556                 :     return -1;
    1557                 :   }
    1558                 :   char *pargs = args; // extra pointer to after the last argument
    1559                 :   // build argument list in the format the DosStartSession() wants,
    1560                 :   // adding spaces between the arguments
    1561                 :   for (int i = 0; i < aArgc; i++, *pargs++ = ' ') {
    1562                 :     strcpy(pargs, aArgv[i]);
    1563                 :     pargs += strlen(aArgv[i]);
    1564                 :   }
    1565                 :   if (aArgc > 1) {
    1566                 :     *(pargs-1) = '\0'; // replace last space
    1567                 :   }
    1568                 :   *pargs = '\0';
    1569                 :   // make sure that the program is separated by null byte
    1570                 :   pargs = strchr(args, ' ');
    1571                 :   if (pargs) {
    1572                 :     *pargs = '\0';
    1573                 :   }
    1574                 : 
    1575                 :   char *env = createEnv();
    1576                 : 
    1577                 :   char error[CCHMAXPATH] = { 0 };
    1578                 :   RESULTCODES crc = { 0 };
    1579                 :   ULONG rc = DosExecPgm(error, sizeof(error), EXEC_ASYNC, args, env,
    1580                 :                         &crc, (PSZ)aExePath);
    1581                 :   free(args); // done with the arguments
    1582                 :   if (env) {
    1583                 :     free(env);
    1584                 :   }
    1585                 :   if (rc != NO_ERROR) {
    1586                 :     return -1;
    1587                 :   }
    1588                 : 
    1589                 :   return 0;
    1590                 : }
    1591                 : #endif
    1592                 : 
    1593                 : // If aBlankCommandLine is true, then the application will be launched with a
    1594                 : // blank command line instead of being launched with the same command line that
    1595                 : // it was initially started with.
    1596               0 : static nsresult LaunchChild(nsINativeAppSupport* aNative,
    1597                 :                             bool aBlankCommandLine = false)
    1598                 : {
    1599               0 :   aNative->Quit(); // release DDE mutex, if we're holding it
    1600                 : 
    1601                 :   // Restart this process by exec'ing it into the current process
    1602                 :   // if supported by the platform.  Otherwise, use NSPR.
    1603                 : 
    1604                 : #ifdef MOZ_JPROF
    1605                 :   // make sure JPROF doesn't think we're E10s
    1606                 :   unsetenv("JPROF_SLAVE");
    1607                 : #endif
    1608                 : 
    1609               0 :   if (aBlankCommandLine) {
    1610                 : #if defined(MOZ_WIDGET_QT)
    1611                 :     // Remove only arguments not given to Qt
    1612                 :     gRestartArgc = gQtOnlyArgc;
    1613                 :     gRestartArgv = gQtOnlyArgv;
    1614                 : #else
    1615               0 :     gRestartArgc = 1;
    1616               0 :     gRestartArgv[gRestartArgc] = nsnull;
    1617                 : #endif
    1618                 :   }
    1619                 : 
    1620               0 :   SaveToEnv("MOZ_LAUNCHED_CHILD=1");
    1621                 : 
    1622                 : #if defined(MOZ_WIDGET_ANDROID)
    1623                 :   mozilla::AndroidBridge::Bridge()->ScheduleRestart();
    1624                 : #else
    1625                 : #if defined(XP_MACOSX)
    1626                 :   CommandLineServiceMac::SetupMacCommandLine(gRestartArgc, gRestartArgv, true);
    1627                 :   PRUint32 restartMode = 0;
    1628                 :   restartMode = gRestartMode;
    1629                 :   LaunchChildMac(gRestartArgc, gRestartArgv, restartMode);
    1630                 : #else
    1631               0 :   nsCOMPtr<nsILocalFile> lf;
    1632               0 :   nsresult rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
    1633               0 :   if (NS_FAILED(rv))
    1634               0 :     return rv;
    1635                 : 
    1636                 : #if defined(XP_WIN)
    1637                 :   nsAutoString exePath;
    1638                 :   rv = lf->GetPath(exePath);
    1639                 :   if (NS_FAILED(rv))
    1640                 :     return rv;
    1641                 : 
    1642                 :   if (!WinLaunchChild(exePath.get(), gRestartArgc, gRestartArgv))
    1643                 :     return NS_ERROR_FAILURE;
    1644                 : 
    1645                 : #else
    1646               0 :   nsCAutoString exePath;
    1647               0 :   rv = lf->GetNativePath(exePath);
    1648               0 :   if (NS_FAILED(rv))
    1649               0 :     return rv;
    1650                 : 
    1651                 : #if defined(XP_OS2) && (__KLIBC__ == 0 && __KLIBC_MINOR__ >= 6)
    1652                 :   // implementation of _execv() is broken with kLibc 0.6.x and later
    1653                 :   if (OS2LaunchChild(exePath.get(), gRestartArgc, gRestartArgv) == -1)
    1654                 :     return NS_ERROR_FAILURE;
    1655                 : #elif defined(XP_OS2)
    1656                 :   if (_execv(exePath.get(), gRestartArgv) == -1)
    1657                 :     return NS_ERROR_FAILURE;
    1658                 : #elif defined(XP_UNIX)
    1659               0 :   if (execv(exePath.get(), gRestartArgv) == -1)
    1660               0 :     return NS_ERROR_FAILURE;
    1661                 : #else
    1662                 :   PRProcess* process = PR_CreateProcess(exePath.get(), gRestartArgv,
    1663                 :                                         nsnull, nsnull);
    1664                 :   if (!process) return NS_ERROR_FAILURE;
    1665                 : 
    1666                 :   PRInt32 exitCode;
    1667                 :   PRStatus failed = PR_WaitProcess(process, &exitCode);
    1668                 :   if (failed || exitCode)
    1669                 :     return NS_ERROR_FAILURE;
    1670                 : #endif // XP_OS2 series
    1671                 : #endif // WP_WIN
    1672                 : #endif // WP_MACOSX
    1673                 : #endif // MOZ_WIDGET_ANDROID
    1674                 : 
    1675               0 :   return NS_ERROR_LAUNCHED_CHILD_PROCESS;
    1676                 : }
    1677                 : 
    1678                 : static const char kProfileProperties[] =
    1679                 :   "chrome://mozapps/locale/profile/profileSelection.properties";
    1680                 : 
    1681                 : static nsresult
    1682               0 : ProfileLockedDialog(nsILocalFile* aProfileDir, nsILocalFile* aProfileLocalDir,
    1683                 :                     nsIProfileUnlocker* aUnlocker,
    1684                 :                     nsINativeAppSupport* aNative, nsIProfileLock* *aResult)
    1685                 : {
    1686                 :   nsresult rv;
    1687                 : 
    1688               0 :   ScopedXPCOMStartup xpcom;
    1689               0 :   rv = xpcom.Initialize();
    1690               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1691                 : 
    1692               0 :   rv = xpcom.SetWindowCreator(aNative);
    1693               0 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
    1694                 : 
    1695                 :   { //extra scoping is needed so we release these components before xpcom shutdown
    1696                 :     nsCOMPtr<nsIStringBundleService> sbs =
    1697               0 :       mozilla::services::GetStringBundleService();
    1698               0 :     NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE);
    1699                 : 
    1700               0 :     nsCOMPtr<nsIStringBundle> sb;
    1701               0 :     sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
    1702               0 :     NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE);
    1703                 : 
    1704               0 :     NS_ConvertUTF8toUTF16 appName(gAppData->name);
    1705               0 :     const PRUnichar* params[] = {appName.get(), appName.get()};
    1706                 : 
    1707               0 :     nsXPIDLString killMessage;
    1708                 : #ifndef XP_MACOSX
    1709                 :     static const PRUnichar kRestartNoUnlocker[] = {'r','e','s','t','a','r','t','M','e','s','s','a','g','e','N','o','U','n','l','o','c','k','e','r','\0'}; // "restartMessageNoUnlocker"
    1710                 :     static const PRUnichar kRestartUnlocker[] = {'r','e','s','t','a','r','t','M','e','s','s','a','g','e','U','n','l','o','c','k','e','r','\0'}; // "restartMessageUnlocker"
    1711                 : #else
    1712                 :     static const PRUnichar kRestartNoUnlocker[] = {'r','e','s','t','a','r','t','M','e','s','s','a','g','e','N','o','U','n','l','o','c','k','e','r','M','a','c','\0'}; // "restartMessageNoUnlockerMac"
    1713                 :     static const PRUnichar kRestartUnlocker[] = {'r','e','s','t','a','r','t','M','e','s','s','a','g','e','U','n','l','o','c','k','e','r','M','a','c','\0'}; // "restartMessageUnlockerMac"
    1714                 : #endif
    1715                 : 
    1716               0 :     sb->FormatStringFromName(aUnlocker ? kRestartUnlocker : kRestartNoUnlocker,
    1717               0 :                              params, 2, getter_Copies(killMessage));
    1718                 : 
    1719               0 :     nsXPIDLString killTitle;
    1720               0 :     sb->FormatStringFromName(NS_LITERAL_STRING("restartTitle").get(),
    1721               0 :                              params, 1, getter_Copies(killTitle));
    1722                 : 
    1723               0 :     if (!killMessage || !killTitle)
    1724               0 :       return NS_ERROR_FAILURE;
    1725                 : 
    1726                 :     nsCOMPtr<nsIPromptService> ps
    1727               0 :       (do_GetService(NS_PROMPTSERVICE_CONTRACTID));
    1728               0 :     NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE);
    1729                 : 
    1730               0 :     if (aUnlocker) {
    1731                 :       const PRUint32 flags =
    1732                 :         (nsIPromptService::BUTTON_TITLE_CANCEL * 
    1733                 :          nsIPromptService::BUTTON_POS_0) +
    1734                 :         (nsIPromptService::BUTTON_TITLE_IS_STRING * 
    1735                 :          nsIPromptService::BUTTON_POS_1) +
    1736               0 :         nsIPromptService::BUTTON_POS_1_DEFAULT;
    1737                 : 
    1738                 :       PRInt32 button;
    1739                 :       // The actual value is irrelevant but we shouldn't be handing out
    1740                 :       // malformed JSBools to XPConnect.
    1741               0 :       bool checkState = false;
    1742               0 :       rv = ps->ConfirmEx(nsnull, killTitle, killMessage, flags,
    1743                 :                          killTitle, nsnull, nsnull, nsnull, 
    1744               0 :                          &checkState, &button);
    1745               0 :       NS_ENSURE_SUCCESS_LOG(rv, rv);
    1746                 : 
    1747               0 :       if (button == 1) {
    1748               0 :         rv = aUnlocker->Unlock(nsIProfileUnlocker::FORCE_QUIT);
    1749               0 :         if (NS_FAILED(rv)) 
    1750               0 :           return rv;
    1751                 : 
    1752                 :         return NS_LockProfilePath(aProfileDir, aProfileLocalDir, 
    1753               0 :                                   nsnull, aResult);
    1754                 :       }
    1755                 :     } else {
    1756               0 :       rv = ps->Alert(nsnull, killTitle, killMessage);
    1757               0 :       NS_ENSURE_SUCCESS_LOG(rv, rv);
    1758                 :     }
    1759                 : 
    1760               0 :     return NS_ERROR_ABORT;
    1761                 :   }
    1762                 : }
    1763                 : 
    1764                 : static nsresult
    1765               0 : ProfileMissingDialog(nsINativeAppSupport* aNative)
    1766                 : {
    1767                 :   nsresult rv;
    1768                 : 
    1769               0 :   ScopedXPCOMStartup xpcom;
    1770               0 :   rv = xpcom.Initialize();
    1771               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1772                 : 
    1773               0 :   rv = xpcom.SetWindowCreator(aNative);
    1774               0 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
    1775                 : 
    1776                 :   { //extra scoping is needed so we release these components before xpcom shutdown
    1777                 :     nsCOMPtr<nsIStringBundleService> sbs =
    1778               0 :       mozilla::services::GetStringBundleService();
    1779               0 :     NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE);
    1780                 :   
    1781               0 :     nsCOMPtr<nsIStringBundle> sb;
    1782               0 :     sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
    1783               0 :     NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE);
    1784                 :   
    1785               0 :     NS_ConvertUTF8toUTF16 appName(gAppData->name);
    1786               0 :     const PRUnichar* params[] = {appName.get(), appName.get()};
    1787                 :   
    1788               0 :     nsXPIDLString missingMessage;
    1789                 :   
    1790                 :     // profileMissing  
    1791                 :     static const PRUnichar kMissing[] = {'p','r','o','f','i','l','e','M','i','s','s','i','n','g','\0'};
    1792               0 :     sb->FormatStringFromName(kMissing, params, 2, getter_Copies(missingMessage));
    1793                 :   
    1794               0 :     nsXPIDLString missingTitle;
    1795               0 :     sb->FormatStringFromName(NS_LITERAL_STRING("profileMissingTitle").get(),
    1796               0 :                              params, 1, getter_Copies(missingTitle));
    1797                 :   
    1798               0 :     if (missingMessage && missingTitle) {
    1799                 :       nsCOMPtr<nsIPromptService> ps
    1800               0 :         (do_GetService(NS_PROMPTSERVICE_CONTRACTID));
    1801               0 :       NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE);
    1802                 :   
    1803               0 :       ps->Alert(nsnull, missingTitle, missingMessage);
    1804                 :     }
    1805                 : 
    1806               0 :     return NS_ERROR_ABORT;
    1807                 :   }
    1808                 : }
    1809                 : 
    1810                 : static const char kProfileManagerURL[] =
    1811                 :   "chrome://mozapps/content/profile/profileSelection.xul";
    1812                 : 
    1813                 : static nsresult
    1814               0 : ShowProfileManager(nsIToolkitProfileService* aProfileSvc,
    1815                 :                    nsINativeAppSupport* aNative)
    1816                 : {
    1817                 :   nsresult rv;
    1818                 : 
    1819               0 :   nsCOMPtr<nsILocalFile> profD, profLD;
    1820                 :   PRUnichar* profileNamePtr;
    1821               0 :   nsCAutoString profileName;
    1822                 : 
    1823                 :   {
    1824               0 :     ScopedXPCOMStartup xpcom;
    1825               0 :     rv = xpcom.Initialize();
    1826               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1827                 : 
    1828               0 :     rv = xpcom.SetWindowCreator(aNative);
    1829               0 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
    1830                 : 
    1831                 : #ifdef XP_MACOSX
    1832                 :     CommandLineServiceMac::SetupMacCommandLine(gRestartArgc, gRestartArgv, true);
    1833                 : #endif
    1834                 : 
    1835                 : #ifdef XP_WIN
    1836                 :     // we don't have to wait here because profile manager window will pump
    1837                 :     // and DDE message will be handled
    1838                 :     ProcessDDE(aNative, false);
    1839                 : #endif
    1840                 : 
    1841                 :     { //extra scoping is needed so we release these components before xpcom shutdown
    1842                 :       nsCOMPtr<nsIWindowWatcher> windowWatcher
    1843               0 :         (do_GetService(NS_WINDOWWATCHER_CONTRACTID));
    1844                 :       nsCOMPtr<nsIDialogParamBlock> ioParamBlock
    1845               0 :         (do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID));
    1846               0 :       nsCOMPtr<nsIMutableArray> dlgArray (do_CreateInstance(NS_ARRAY_CONTRACTID));
    1847               0 :       NS_ENSURE_TRUE(windowWatcher && ioParamBlock && dlgArray, NS_ERROR_FAILURE);
    1848                 : 
    1849               0 :       ioParamBlock->SetObjects(dlgArray);
    1850                 : 
    1851                 :       nsCOMPtr<nsIAppStartup> appStartup
    1852               0 :         (do_GetService(NS_APPSTARTUP_CONTRACTID));
    1853               0 :       NS_ENSURE_TRUE(appStartup, NS_ERROR_FAILURE);
    1854                 : 
    1855               0 :       nsCOMPtr<nsIDOMWindow> newWindow;
    1856               0 :       rv = windowWatcher->OpenWindow(nsnull,
    1857                 :                                      kProfileManagerURL,
    1858                 :                                      "_blank",
    1859                 :                                      "centerscreen,chrome,modal,titlebar",
    1860                 :                                      ioParamBlock,
    1861               0 :                                      getter_AddRefs(newWindow));
    1862                 : 
    1863               0 :       NS_ENSURE_SUCCESS_LOG(rv, rv);
    1864                 : 
    1865               0 :       aProfileSvc->Flush();
    1866                 : 
    1867                 :       PRInt32 dialogConfirmed;
    1868               0 :       rv = ioParamBlock->GetInt(0, &dialogConfirmed);
    1869               0 :       if (NS_FAILED(rv) || dialogConfirmed == 0) return NS_ERROR_ABORT;
    1870                 : 
    1871               0 :       nsCOMPtr<nsIProfileLock> lock;
    1872               0 :       rv = dlgArray->QueryElementAt(0, NS_GET_IID(nsIProfileLock),
    1873               0 :                                     getter_AddRefs(lock));
    1874               0 :       NS_ENSURE_SUCCESS_LOG(rv, rv);
    1875                 : 
    1876               0 :       rv = lock->GetDirectory(getter_AddRefs(profD));
    1877               0 :       NS_ENSURE_SUCCESS(rv, rv);
    1878                 : 
    1879               0 :       rv = lock->GetLocalDirectory(getter_AddRefs(profLD));
    1880               0 :       NS_ENSURE_SUCCESS(rv, rv);
    1881                 : 
    1882               0 :       rv = ioParamBlock->GetString(0, &profileNamePtr);
    1883               0 :       NS_ENSURE_SUCCESS(rv, rv);
    1884                 : 
    1885               0 :       CopyUTF16toUTF8(profileNamePtr, profileName);
    1886               0 :       NS_Free(profileNamePtr);
    1887                 : 
    1888               0 :       lock->Unlock();
    1889                 :     }
    1890                 :   }
    1891                 : 
    1892               0 :   SaveFileToEnv("XRE_PROFILE_PATH", profD);
    1893               0 :   SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", profLD);
    1894               0 :   SaveWordToEnv("XRE_PROFILE_NAME", profileName);
    1895                 : 
    1896               0 :   bool offline = false;
    1897               0 :   aProfileSvc->GetStartOffline(&offline);
    1898               0 :   if (offline) {
    1899               0 :     SaveToEnv("XRE_START_OFFLINE=1");
    1900                 :   }
    1901                 : 
    1902               0 :   return LaunchChild(aNative);
    1903                 : }
    1904                 : 
    1905                 : // Pick a profile. We need to end up with a profile lock.
    1906                 : //
    1907                 : // 1) check for -profile <path>
    1908                 : // 2) check for -P <name>
    1909                 : // 3) check for -ProfileManager
    1910                 : // 4) use the default profile, if there is one
    1911                 : // 5) if there are *no* profiles, set up profile-migration
    1912                 : // 6) display the profile-manager UI
    1913                 : 
    1914                 : static bool gDoMigration = false;
    1915                 : static bool gDoProfileReset = false;
    1916                 : 
    1917                 : /**
    1918                 :  * Creates a new profile with a timestamp in the name to use for profile reset.
    1919                 :  */
    1920                 : static nsresult
    1921               0 : ResetProfile(nsIToolkitProfileService* aProfileSvc, nsIToolkitProfile* *aNewProfile)
    1922                 : {
    1923               0 :   NS_ENSURE_ARG_POINTER(aProfileSvc);
    1924                 : 
    1925               0 :   nsCOMPtr<nsIToolkitProfile> newProfile;
    1926                 :   // Make the new profile "default-" + the time in seconds since epoch for uniqueness.
    1927               0 :   nsCAutoString newProfileName("default-");
    1928               0 :   newProfileName.Append(nsPrintfCString("%lld", PR_Now() / 1000));
    1929                 :   nsresult rv = aProfileSvc->CreateProfile(nsnull, // choose a default dir for us
    1930                 :                                            nsnull, // choose a default dir for us
    1931                 :                                            newProfileName,
    1932               0 :                                            getter_AddRefs(newProfile));
    1933               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1934                 : 
    1935               0 :   rv = aProfileSvc->Flush();
    1936               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1937                 : 
    1938               0 :   NS_IF_ADDREF(*aNewProfile = newProfile);
    1939                 : 
    1940               0 :   return NS_OK;
    1941                 : }
    1942                 : 
    1943                 : /**
    1944                 :  * Set the currently running profile as the default/selected one.
    1945                 :  *
    1946                 :  * @param aCurrentProfileRoot The root directory of the current profile.
    1947                 :  * @return an error if aCurrentProfileRoot is not found or the profile could not
    1948                 :  * be set as the default.
    1949                 :  */
    1950                 : static nsresult
    1951               0 : SetCurrentProfileAsDefault(nsIToolkitProfileService* aProfileSvc,
    1952                 :                            nsILocalFile* aCurrentProfileRoot)
    1953                 : {
    1954               0 :   NS_ENSURE_ARG_POINTER(aProfileSvc);
    1955                 : 
    1956               0 :   nsCOMPtr<nsISimpleEnumerator> profiles;
    1957               0 :   nsresult rv = aProfileSvc->GetProfiles(getter_AddRefs(profiles));
    1958               0 :   if (NS_FAILED(rv))
    1959               0 :     return rv;
    1960                 : 
    1961               0 :   bool foundMatchingProfile = false;
    1962               0 :   nsCOMPtr<nsIToolkitProfile> profile;
    1963               0 :   rv = profiles->GetNext(getter_AddRefs(profile));
    1964               0 :   while (NS_SUCCEEDED(rv)) {
    1965               0 :     nsCOMPtr<nsILocalFile> profileRoot;
    1966               0 :     profile->GetRootDir(getter_AddRefs(profileRoot));
    1967               0 :     profileRoot->Equals(aCurrentProfileRoot, &foundMatchingProfile);
    1968               0 :     if (foundMatchingProfile && profile) {
    1969               0 :       rv = aProfileSvc->SetSelectedProfile(profile);
    1970               0 :       if (NS_SUCCEEDED(rv))
    1971               0 :         rv = aProfileSvc->Flush();
    1972               0 :       return rv;
    1973                 :     }
    1974               0 :     rv = profiles->GetNext(getter_AddRefs(profile));
    1975                 :   }
    1976               0 :   return rv;
    1977                 : }
    1978                 : 
    1979                 : static nsresult
    1980               0 : SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, nsINativeAppSupport* aNative,
    1981                 :               bool* aStartOffline, nsACString* aProfileName)
    1982                 : {
    1983                 :   nsresult rv;
    1984                 :   ArgResult ar;
    1985                 :   const char* arg;
    1986               0 :   *aResult = nsnull;
    1987               0 :   *aStartOffline = false;
    1988                 : 
    1989               0 :   ar = CheckArg("offline", true);
    1990               0 :   if (ar == ARG_BAD) {
    1991               0 :     PR_fprintf(PR_STDERR, "Error: argument -offline is invalid when argument -osint is specified\n");
    1992               0 :     return NS_ERROR_FAILURE;
    1993                 :   }
    1994                 : 
    1995               0 :   if (ar || EnvHasValue("XRE_START_OFFLINE"))
    1996               0 :     *aStartOffline = true;
    1997                 : 
    1998               0 :   if (EnvHasValue("MOZ_RESET_PROFILE_RESTART")) {
    1999               0 :     gDoProfileReset = true;
    2000               0 :     gDoMigration = true;
    2001               0 :     SaveToEnv("MOZ_RESET_PROFILE_RESTART=");
    2002                 :   }
    2003                 : 
    2004                 :   // reset-profile and migration args need to be checked before any profiles are chosen below.
    2005               0 :   ar = CheckArg("reset-profile", true);
    2006               0 :   if (ar == ARG_BAD) {
    2007               0 :     PR_fprintf(PR_STDERR, "Error: argument -reset-profile is invalid when argument -osint is specified\n");
    2008               0 :     return NS_ERROR_FAILURE;
    2009               0 :   } else if (ar == ARG_FOUND) {
    2010               0 :     gDoProfileReset = true;
    2011                 :   }
    2012                 : 
    2013               0 :   ar = CheckArg("migration", true);
    2014               0 :   if (ar == ARG_BAD) {
    2015               0 :     PR_fprintf(PR_STDERR, "Error: argument -migration is invalid when argument -osint is specified\n");
    2016               0 :     return NS_ERROR_FAILURE;
    2017               0 :   } else if (ar == ARG_FOUND) {
    2018               0 :     gDoMigration = true;
    2019                 :   }
    2020                 : 
    2021               0 :   nsCOMPtr<nsILocalFile> lf = GetFileFromEnv("XRE_PROFILE_PATH");
    2022               0 :   if (lf) {
    2023                 :     nsCOMPtr<nsILocalFile> localDir =
    2024               0 :       GetFileFromEnv("XRE_PROFILE_LOCAL_PATH");
    2025               0 :     if (!localDir) {
    2026               0 :       localDir = lf;
    2027                 :     }
    2028                 : 
    2029               0 :     arg = PR_GetEnv("XRE_PROFILE_NAME");
    2030               0 :     if (arg && *arg && aProfileName)
    2031               0 :       aProfileName->Assign(nsDependentCString(arg));
    2032                 : 
    2033                 :     // Clear out flags that we handled (or should have handled!) last startup.
    2034                 :     const char *dummy;
    2035               0 :     CheckArg("p", false, &dummy);
    2036               0 :     CheckArg("profile", false, &dummy);
    2037               0 :     CheckArg("profilemanager");
    2038                 : 
    2039               0 :     if (gDoProfileReset) {
    2040                 :       // If we're resetting a profile, create a new one and use it to startup.
    2041               0 :       nsCOMPtr<nsIToolkitProfile> newProfile;
    2042               0 :       rv = ResetProfile(aProfileSvc, getter_AddRefs(newProfile));
    2043               0 :       if (NS_SUCCEEDED(rv)) {
    2044               0 :         rv = newProfile->GetRootDir(getter_AddRefs(lf));
    2045               0 :         NS_ENSURE_SUCCESS(rv, rv);
    2046               0 :         SaveFileToEnv("XRE_PROFILE_PATH", lf);
    2047                 : 
    2048               0 :         rv = newProfile->GetLocalDir(getter_AddRefs(localDir));
    2049               0 :         NS_ENSURE_SUCCESS(rv, rv);
    2050               0 :         SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", localDir);
    2051                 : 
    2052               0 :         rv = newProfile->GetName(*aProfileName);
    2053               0 :         if (NS_FAILED(rv))
    2054               0 :           aProfileName->Truncate(0);
    2055               0 :         SaveWordToEnv("XRE_PROFILE_NAME", *aProfileName);
    2056                 :       } else {
    2057               0 :         NS_WARNING("Profile reset failed.");
    2058               0 :         gDoProfileReset = false;
    2059                 :       }
    2060                 :     }
    2061                 : 
    2062               0 :     return NS_LockProfilePath(lf, localDir, nsnull, aResult);
    2063                 :   }
    2064                 : 
    2065               0 :   ar = CheckArg("profile", true, &arg);
    2066               0 :   if (ar == ARG_BAD) {
    2067               0 :     PR_fprintf(PR_STDERR, "Error: argument -profile requires a path\n");
    2068               0 :     return NS_ERROR_FAILURE;
    2069                 :   }
    2070               0 :   if (ar) {
    2071               0 :     if (gDoProfileReset) {
    2072               0 :       NS_WARNING("Profile reset is only supported for the default profile.");
    2073               0 :       gDoProfileReset = false;
    2074                 :     }
    2075                 : 
    2076               0 :     nsCOMPtr<nsILocalFile> lf;
    2077               0 :     rv = XRE_GetFileFromPath(arg, getter_AddRefs(lf));
    2078               0 :     NS_ENSURE_SUCCESS(rv, rv);
    2079                 : 
    2080               0 :     nsCOMPtr<nsIProfileUnlocker> unlocker;
    2081                 : 
    2082                 :     // Check if the profile path exists and it's a directory.
    2083                 :     bool exists;
    2084               0 :     lf->Exists(&exists);
    2085               0 :     if (!exists) {
    2086               0 :         rv = lf->Create(nsIFile::DIRECTORY_TYPE, 0700);
    2087               0 :         NS_ENSURE_SUCCESS(rv, rv);
    2088                 :     }
    2089                 : 
    2090                 :     // If a profile path is specified directory on the command line, then
    2091                 :     // assume that the temp directory is the same as the given directory.
    2092               0 :     rv = NS_LockProfilePath(lf, lf, getter_AddRefs(unlocker), aResult);
    2093               0 :     if (NS_SUCCEEDED(rv))
    2094               0 :       return rv;
    2095                 : 
    2096               0 :     return ProfileLockedDialog(lf, lf, unlocker, aNative, aResult);
    2097                 :   }
    2098                 : 
    2099               0 :   ar = CheckArg("createprofile", true, &arg);
    2100               0 :   if (ar == ARG_BAD) {
    2101               0 :     PR_fprintf(PR_STDERR, "Error: argument -createprofile requires a profile name\n");
    2102               0 :     return NS_ERROR_FAILURE;
    2103                 :   }
    2104               0 :   if (ar) {
    2105               0 :     nsCOMPtr<nsIToolkitProfile> profile;
    2106                 : 
    2107               0 :     const char* delim = strchr(arg, ' ');
    2108               0 :     if (delim) {
    2109               0 :       nsCOMPtr<nsILocalFile> lf;
    2110               0 :       rv = NS_NewNativeLocalFile(nsDependentCString(delim + 1),
    2111               0 :                                    true, getter_AddRefs(lf));
    2112               0 :       if (NS_FAILED(rv)) {
    2113               0 :         PR_fprintf(PR_STDERR, "Error: profile path not valid.\n");
    2114               0 :         return rv;
    2115                 :       }
    2116                 :       
    2117                 :       // As with -profile, assume that the given path will be used for both the
    2118                 :       // main profile directory and the temp profile directory.
    2119               0 :       rv = aProfileSvc->CreateProfile(lf, lf, nsDependentCSubstring(arg, delim),
    2120               0 :                                      getter_AddRefs(profile));
    2121                 :     } else {
    2122               0 :       rv = aProfileSvc->CreateProfile(nsnull, nsnull, nsDependentCString(arg),
    2123               0 :                                      getter_AddRefs(profile));
    2124                 :     }
    2125                 :     // Some pathological arguments can make it this far
    2126               0 :     if (NS_FAILED(rv)) {
    2127               0 :       PR_fprintf(PR_STDERR, "Error creating profile.\n");
    2128               0 :       return rv; 
    2129                 :     }
    2130               0 :     rv = NS_ERROR_ABORT;  
    2131               0 :     aProfileSvc->Flush();
    2132                 : 
    2133                 :     // XXXben need to ensure prefs.js exists here so the tinderboxes will
    2134                 :     //        not go orange.
    2135               0 :     nsCOMPtr<nsILocalFile> prefsJSFile;
    2136               0 :     profile->GetRootDir(getter_AddRefs(prefsJSFile));
    2137               0 :     prefsJSFile->AppendNative(NS_LITERAL_CSTRING("prefs.js"));
    2138               0 :     nsCAutoString pathStr;
    2139               0 :     prefsJSFile->GetNativePath(pathStr);
    2140               0 :     PR_fprintf(PR_STDERR, "Success: created profile '%s' at '%s'\n", arg, pathStr.get());
    2141                 :     bool exists;
    2142               0 :     prefsJSFile->Exists(&exists);
    2143               0 :     if (!exists)
    2144               0 :       prefsJSFile->Create(nsIFile::NORMAL_FILE_TYPE, 0644);
    2145                 :     // XXXdarin perhaps 0600 would be better?
    2146                 : 
    2147               0 :     return rv;
    2148                 :   }
    2149                 : 
    2150                 :   PRUint32 count;
    2151               0 :   rv = aProfileSvc->GetProfileCount(&count);
    2152               0 :   NS_ENSURE_SUCCESS(rv, rv);
    2153                 : 
    2154               0 :   ar = CheckArg("p", false, &arg);
    2155               0 :   if (ar == ARG_BAD) {
    2156               0 :     ar = CheckArg("osint");
    2157               0 :     if (ar == ARG_FOUND) {
    2158               0 :       PR_fprintf(PR_STDERR, "Error: argument -p is invalid when argument -osint is specified\n");
    2159               0 :       return NS_ERROR_FAILURE;
    2160                 :     }
    2161               0 :     return ShowProfileManager(aProfileSvc, aNative);
    2162                 :   }
    2163               0 :   if (ar) {
    2164               0 :     ar = CheckArg("osint");
    2165               0 :     if (ar == ARG_FOUND) {
    2166               0 :       PR_fprintf(PR_STDERR, "Error: argument -p is invalid when argument -osint is specified\n");
    2167               0 :       return NS_ERROR_FAILURE;
    2168                 :     }
    2169               0 :     nsCOMPtr<nsIToolkitProfile> profile;
    2170               0 :     rv = aProfileSvc->GetProfileByName(nsDependentCString(arg),
    2171               0 :                                       getter_AddRefs(profile));
    2172               0 :     if (NS_SUCCEEDED(rv)) {
    2173                 :       // If we're resetting a profile, create a new one and use it to startup.
    2174               0 :       if (gDoProfileReset) {
    2175               0 :         NS_WARNING("Profile reset is only supported for the default profile.");
    2176               0 :         gDoProfileReset = false;
    2177                 :       }
    2178                 : 
    2179               0 :       nsCOMPtr<nsIProfileUnlocker> unlocker;
    2180               0 :       rv = profile->Lock(nsnull, aResult);
    2181               0 :       if (NS_SUCCEEDED(rv)) {
    2182               0 :         if (aProfileName)
    2183               0 :           aProfileName->Assign(nsDependentCString(arg));
    2184               0 :         return NS_OK;
    2185                 :       }
    2186                 : 
    2187               0 :       nsCOMPtr<nsILocalFile> profileDir;
    2188               0 :       rv = profile->GetRootDir(getter_AddRefs(profileDir));
    2189               0 :       NS_ENSURE_SUCCESS(rv, rv);
    2190                 : 
    2191               0 :       nsCOMPtr<nsILocalFile> profileLocalDir;
    2192               0 :       rv = profile->GetLocalDir(getter_AddRefs(profileLocalDir));
    2193               0 :       NS_ENSURE_SUCCESS(rv, rv);
    2194                 : 
    2195                 :       return ProfileLockedDialog(profileDir, profileLocalDir, unlocker,
    2196               0 :                                  aNative, aResult);
    2197                 :     }
    2198                 : 
    2199               0 :     return ShowProfileManager(aProfileSvc, aNative);
    2200                 :   }
    2201                 : 
    2202               0 :   ar = CheckArg("profilemanager", true);
    2203               0 :   if (ar == ARG_BAD) {
    2204               0 :     PR_fprintf(PR_STDERR, "Error: argument -profilemanager is invalid when argument -osint is specified\n");
    2205               0 :     return NS_ERROR_FAILURE;
    2206               0 :   } else if (ar == ARG_FOUND) {
    2207               0 :     return ShowProfileManager(aProfileSvc, aNative);
    2208                 :   }
    2209                 : 
    2210               0 :   if (!count) {
    2211               0 :     gDoMigration = true;
    2212               0 :     gDoProfileReset = false;
    2213                 : 
    2214                 :     // create a default profile
    2215               0 :     nsCOMPtr<nsIToolkitProfile> profile;
    2216                 :     nsresult rv = aProfileSvc->CreateProfile(nsnull, // choose a default dir for us
    2217                 :                                              nsnull, // choose a default dir for us
    2218               0 :                                              NS_LITERAL_CSTRING("default"),
    2219               0 :                                              getter_AddRefs(profile));
    2220               0 :     if (NS_SUCCEEDED(rv)) {
    2221               0 :       aProfileSvc->Flush();
    2222               0 :       rv = profile->Lock(nsnull, aResult);
    2223               0 :       if (NS_SUCCEEDED(rv)) {
    2224               0 :         if (aProfileName)
    2225               0 :           aProfileName->Assign(NS_LITERAL_CSTRING("default"));
    2226               0 :         return NS_OK;
    2227                 :       }
    2228                 :     }
    2229                 :   }
    2230                 : 
    2231               0 :   bool useDefault = true;
    2232               0 :   if (count > 1)
    2233               0 :     aProfileSvc->GetStartWithLastProfile(&useDefault);
    2234                 : 
    2235               0 :   if (useDefault) {
    2236               0 :     nsCOMPtr<nsIToolkitProfile> profile;
    2237                 :     // GetSelectedProfile will auto-select the only profile if there's just one
    2238               0 :     aProfileSvc->GetSelectedProfile(getter_AddRefs(profile));
    2239               0 :     if (profile) {
    2240                 :       // If we're resetting a profile, create a new one and use it to startup.
    2241               0 :       if (gDoProfileReset) {
    2242               0 :         nsCOMPtr<nsIToolkitProfile> newProfile;
    2243               0 :         rv = ResetProfile(aProfileSvc, getter_AddRefs(newProfile));
    2244               0 :         if (NS_SUCCEEDED(rv))
    2245               0 :           profile = newProfile;
    2246                 :         else
    2247               0 :           gDoProfileReset = false;
    2248                 :       }
    2249               0 :       nsCOMPtr<nsIProfileUnlocker> unlocker;
    2250               0 :       rv = profile->Lock(getter_AddRefs(unlocker), aResult);
    2251               0 :       if (NS_SUCCEEDED(rv)) {
    2252                 :         // Try to grab the profile name.
    2253               0 :         if (aProfileName) {
    2254               0 :           rv = profile->GetName(*aProfileName);
    2255               0 :           if (NS_FAILED(rv))
    2256               0 :             aProfileName->Truncate(0);
    2257                 :         }
    2258               0 :         return NS_OK;
    2259                 :       }
    2260                 : 
    2261               0 :       nsCOMPtr<nsILocalFile> profileDir;
    2262               0 :       rv = profile->GetRootDir(getter_AddRefs(profileDir));
    2263               0 :       NS_ENSURE_SUCCESS(rv, rv);
    2264                 : 
    2265               0 :       nsCOMPtr<nsILocalFile> profileLocalDir;
    2266               0 :       rv = profile->GetRootDir(getter_AddRefs(profileLocalDir));
    2267               0 :       NS_ENSURE_SUCCESS(rv, rv);
    2268                 : 
    2269                 :       return ProfileLockedDialog(profileDir, profileLocalDir, unlocker,
    2270               0 :                                  aNative, aResult);
    2271                 :     }
    2272                 :   }
    2273                 : 
    2274               0 :   return ShowProfileManager(aProfileSvc, aNative);
    2275                 : }
    2276                 : 
    2277                 : /** 
    2278                 :  * Checks the compatibility.ini file to see if we have updated our application
    2279                 :  * or otherwise invalidated our caches. If the application has been updated, 
    2280                 :  * we return false; otherwise, we return true. We also write the status 
    2281                 :  * of the caches (valid/invalid) into the return param aCachesOK. The aCachesOK
    2282                 :  * is always invalid if the application has been updated. 
    2283                 :  */
    2284                 : static bool
    2285               0 : CheckCompatibility(nsIFile* aProfileDir, const nsCString& aVersion,
    2286                 :                    const nsCString& aOSABI, nsIFile* aXULRunnerDir,
    2287                 :                    nsIFile* aAppDir, nsILocalFile* aFlagFile, 
    2288                 :                    bool* aCachesOK)
    2289                 : {
    2290               0 :   *aCachesOK = false;
    2291               0 :   nsCOMPtr<nsIFile> file;
    2292               0 :   aProfileDir->Clone(getter_AddRefs(file));
    2293               0 :   if (!file)
    2294               0 :     return false;
    2295               0 :   file->AppendNative(FILE_COMPATIBILITY_INFO);
    2296                 : 
    2297               0 :   nsINIParser parser;
    2298               0 :   nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(file));
    2299               0 :   nsresult rv = parser.Init(localFile);
    2300               0 :   if (NS_FAILED(rv))
    2301               0 :     return false;
    2302                 : 
    2303               0 :   nsCAutoString buf;
    2304               0 :   rv = parser.GetString("Compatibility", "LastVersion", buf);
    2305               0 :   if (NS_FAILED(rv) || !aVersion.Equals(buf))
    2306               0 :     return false;
    2307                 : 
    2308               0 :   rv = parser.GetString("Compatibility", "LastOSABI", buf);
    2309               0 :   if (NS_FAILED(rv) || !aOSABI.Equals(buf))
    2310               0 :     return false;
    2311                 : 
    2312               0 :   rv = parser.GetString("Compatibility", "LastPlatformDir", buf);
    2313               0 :   if (NS_FAILED(rv))
    2314               0 :     return false;
    2315                 : 
    2316               0 :   nsCOMPtr<nsILocalFile> lf;
    2317                 :   rv = NS_NewNativeLocalFile(buf, false,
    2318               0 :                              getter_AddRefs(lf));
    2319               0 :   if (NS_FAILED(rv))
    2320               0 :     return false;
    2321                 : 
    2322                 :   bool eq;
    2323               0 :   rv = lf->Equals(aXULRunnerDir, &eq);
    2324               0 :   if (NS_FAILED(rv) || !eq)
    2325               0 :     return false;
    2326                 : 
    2327               0 :   if (aAppDir) {
    2328               0 :     rv = parser.GetString("Compatibility", "LastAppDir", buf);
    2329               0 :     if (NS_FAILED(rv))
    2330               0 :       return false;
    2331                 : 
    2332                 :     rv = NS_NewNativeLocalFile(buf, false,
    2333               0 :                                getter_AddRefs(lf));
    2334               0 :     if (NS_FAILED(rv))
    2335               0 :       return false;
    2336                 : 
    2337               0 :     rv = lf->Equals(aAppDir, &eq);
    2338               0 :     if (NS_FAILED(rv) || !eq)
    2339               0 :       return false;
    2340                 :   }
    2341                 : 
    2342                 :   // If we see this flag, caches are invalid.
    2343               0 :   rv = parser.GetString("Compatibility", "InvalidateCaches", buf);
    2344               0 :   *aCachesOK = (NS_FAILED(rv) || !buf.EqualsLiteral("1"));
    2345                 :   
    2346               0 :   bool purgeCaches = false;
    2347               0 :   if (aFlagFile) {
    2348               0 :     aFlagFile->Exists(&purgeCaches);
    2349                 :   }
    2350                 : 
    2351               0 :   *aCachesOK = !purgeCaches && *aCachesOK;
    2352               0 :   return true;
    2353                 : }
    2354                 : 
    2355               0 : static void BuildVersion(nsCString &aBuf)
    2356                 : {
    2357               0 :   aBuf.Assign(gAppData->version);
    2358               0 :   aBuf.Append('_');
    2359               0 :   aBuf.Append(gAppData->buildID);
    2360               0 :   aBuf.Append('/');
    2361               0 :   aBuf.Append(gToolkitBuildID);
    2362               0 : }
    2363                 : 
    2364                 : static void
    2365               0 : WriteVersion(nsIFile* aProfileDir, const nsCString& aVersion,
    2366                 :              const nsCString& aOSABI, nsIFile* aXULRunnerDir,
    2367                 :              nsIFile* aAppDir)
    2368                 : {
    2369               0 :   nsCOMPtr<nsIFile> file;
    2370               0 :   aProfileDir->Clone(getter_AddRefs(file));
    2371               0 :   if (!file)
    2372                 :     return;
    2373               0 :   file->AppendNative(FILE_COMPATIBILITY_INFO);
    2374                 : 
    2375               0 :   nsCOMPtr<nsILocalFile> lf = do_QueryInterface(file);
    2376                 : 
    2377               0 :   nsCAutoString platformDir;
    2378               0 :   aXULRunnerDir->GetNativePath(platformDir);
    2379                 : 
    2380               0 :   nsCAutoString appDir;
    2381               0 :   if (aAppDir)
    2382               0 :     aAppDir->GetNativePath(appDir);
    2383                 : 
    2384               0 :   PRFileDesc *fd = nsnull;
    2385               0 :   lf->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0600, &fd);
    2386               0 :   if (!fd) {
    2387               0 :     NS_ERROR("could not create output stream");
    2388                 :     return;
    2389                 :   }
    2390                 : 
    2391                 :   static const char kHeader[] = "[Compatibility]" NS_LINEBREAK
    2392                 :                                 "LastVersion=";
    2393                 : 
    2394               0 :   PR_Write(fd, kHeader, sizeof(kHeader) - 1);
    2395               0 :   PR_Write(fd, aVersion.get(), aVersion.Length());
    2396                 : 
    2397                 :   static const char kOSABIHeader[] = NS_LINEBREAK "LastOSABI=";
    2398               0 :   PR_Write(fd, kOSABIHeader, sizeof(kOSABIHeader) - 1);
    2399               0 :   PR_Write(fd, aOSABI.get(), aOSABI.Length());
    2400                 : 
    2401                 :   static const char kPlatformDirHeader[] = NS_LINEBREAK "LastPlatformDir=";
    2402                 : 
    2403               0 :   PR_Write(fd, kPlatformDirHeader, sizeof(kPlatformDirHeader) - 1);
    2404               0 :   PR_Write(fd, platformDir.get(), platformDir.Length());
    2405                 : 
    2406                 :   static const char kAppDirHeader[] = NS_LINEBREAK "LastAppDir=";
    2407               0 :   if (aAppDir) {
    2408               0 :     PR_Write(fd, kAppDirHeader, sizeof(kAppDirHeader) - 1);
    2409               0 :     PR_Write(fd, appDir.get(), appDir.Length());
    2410                 :   }
    2411                 : 
    2412                 :   static const char kNL[] = NS_LINEBREAK;
    2413               0 :   PR_Write(fd, kNL, sizeof(kNL) - 1);
    2414                 : 
    2415               0 :   PR_Close(fd);
    2416                 : }
    2417                 : 
    2418               0 : static void RemoveComponentRegistries(nsIFile* aProfileDir, nsIFile* aLocalProfileDir,
    2419                 :                                       bool aRemoveEMFiles)
    2420                 : {
    2421               0 :   nsCOMPtr<nsIFile> file;
    2422               0 :   aProfileDir->Clone(getter_AddRefs(file));
    2423               0 :   if (!file)
    2424                 :     return;
    2425                 : 
    2426               0 :   if (aRemoveEMFiles) {
    2427               0 :     file->SetNativeLeafName(NS_LITERAL_CSTRING("extensions.ini"));
    2428               0 :     file->Remove(false);
    2429                 :   }
    2430                 : 
    2431               0 :   aLocalProfileDir->Clone(getter_AddRefs(file));
    2432               0 :   if (!file)
    2433                 :     return;
    2434                 : 
    2435                 : #if defined(XP_UNIX) || defined(XP_BEOS)
    2436                 : #define PLATFORM_FASL_SUFFIX ".mfasl"
    2437                 : #elif defined(XP_WIN) || defined(XP_OS2)
    2438                 : #define PLATFORM_FASL_SUFFIX ".mfl"
    2439                 : #endif
    2440                 : 
    2441               0 :   file->AppendNative(NS_LITERAL_CSTRING("XUL" PLATFORM_FASL_SUFFIX));
    2442               0 :   file->Remove(false);
    2443                 :   
    2444               0 :   file->SetNativeLeafName(NS_LITERAL_CSTRING("XPC" PLATFORM_FASL_SUFFIX));
    2445               0 :   file->Remove(false);
    2446                 : 
    2447               0 :   file->SetNativeLeafName(NS_LITERAL_CSTRING("startupCache"));
    2448               0 :   file->Remove(true);
    2449                 : }
    2450                 : 
    2451                 : // To support application initiated restart via nsIAppStartup.quit, we
    2452                 : // need to save various environment variables, and then restore them
    2453                 : // before re-launching the application.
    2454                 : 
    2455                 : static struct SavedVar {
    2456                 :   const char *name;
    2457                 :   char *value;
    2458                 : } gSavedVars[] = {
    2459                 :   {"XUL_APP_FILE", nsnull}
    2460                 : };
    2461                 : 
    2462               0 : static void SaveStateForAppInitiatedRestart()
    2463                 : {
    2464               0 :   for (size_t i = 0; i < ArrayLength(gSavedVars); ++i) {
    2465               0 :     const char *s = PR_GetEnv(gSavedVars[i].name);
    2466               0 :     if (s)
    2467               0 :       gSavedVars[i].value = PR_smprintf("%s=%s", gSavedVars[i].name, s);
    2468                 :   }
    2469               0 : }
    2470                 : 
    2471               0 : static void RestoreStateForAppInitiatedRestart()
    2472                 : {
    2473               0 :   for (size_t i = 0; i < ArrayLength(gSavedVars); ++i) {
    2474               0 :     if (gSavedVars[i].value)
    2475               0 :       PR_SetEnv(gSavedVars[i].value);
    2476                 :   }
    2477               0 : }
    2478                 : 
    2479                 : #ifdef MOZ_CRASHREPORTER
    2480                 : // When we first initialize the crash reporter we don't have a profile,
    2481                 : // so we set the minidump path to $TEMP.  Once we have a profile,
    2482                 : // we set it to $PROFILE/minidumps, creating the directory
    2483                 : // if needed.
    2484               0 : static void MakeOrSetMinidumpPath(nsIFile* profD)
    2485                 : {
    2486               0 :   nsCOMPtr<nsIFile> dumpD;
    2487               0 :   nsresult rv = profD->Clone(getter_AddRefs(dumpD));
    2488                 :   
    2489               0 :   if(dumpD) {
    2490                 :     bool fileExists;
    2491                 :     //XXX: do some more error checking here
    2492               0 :     dumpD->Append(NS_LITERAL_STRING("minidumps"));
    2493               0 :     rv = dumpD->Exists(&fileExists);
    2494               0 :     if(!fileExists) {
    2495               0 :       dumpD->Create(nsIFile::DIRECTORY_TYPE, 0700);
    2496                 :     }
    2497                 : 
    2498               0 :     nsAutoString pathStr;
    2499               0 :     if(NS_SUCCEEDED(dumpD->GetPath(pathStr)))
    2500               0 :       CrashReporter::SetMinidumpPath(pathStr);
    2501                 :   }
    2502               0 : }
    2503                 : #endif
    2504                 : 
    2505                 : const nsXREAppData* gAppData = nsnull;
    2506                 : 
    2507                 : #if defined(XP_OS2)
    2508                 : // because we use early returns, we use a stack-based helper to un-set the OS2 FP handler
    2509                 : class ScopedFPHandler {
    2510                 : private:
    2511                 :   EXCEPTIONREGISTRATIONRECORD excpreg;
    2512                 : 
    2513                 : public:
    2514                 :   ScopedFPHandler() { PR_OS2_SetFloatExcpHandler(&excpreg); }
    2515                 :   ~ScopedFPHandler() { PR_OS2_UnsetFloatExcpHandler(&excpreg); }
    2516                 : };
    2517                 : #endif
    2518                 : 
    2519                 : #ifdef MOZ_WIDGET_GTK2
    2520                 : #include "prlink.h"
    2521                 : typedef void (*_g_set_application_name_fn)(const gchar *application_name);
    2522                 : typedef void (*_gtk_window_set_auto_startup_notification_fn)(gboolean setting);
    2523                 : 
    2524               0 : static PRFuncPtr FindFunction(const char* aName)
    2525                 : {
    2526               0 :   PRLibrary *lib = nsnull;
    2527               0 :   PRFuncPtr result = PR_FindFunctionSymbolAndLibrary(aName, &lib);
    2528                 :   // Since the library was already loaded, we can safely unload it here.
    2529               0 :   if (lib) {
    2530               0 :     PR_UnloadLibrary(lib);
    2531                 :   }
    2532               0 :   return result;
    2533                 : }
    2534                 : 
    2535               0 : static void MOZ_gdk_display_close(GdkDisplay *display)
    2536                 : {
    2537                 :   // XXX wallpaper for bug 417163: don't close the Display if we're using the
    2538                 :   // Qt theme because we crash (in Qt code) when using jemalloc.
    2539               0 :   bool theme_is_qt = false;
    2540                 :   GtkSettings* settings =
    2541               0 :     gtk_settings_get_for_screen(gdk_display_get_default_screen(display));
    2542                 :   gchar *theme_name;
    2543               0 :   g_object_get(settings, "gtk-theme-name", &theme_name, NULL);
    2544               0 :   if (theme_name) {
    2545               0 :     theme_is_qt = strcmp(theme_name, "Qt") == 0;
    2546               0 :     if (theme_is_qt)
    2547               0 :       NS_WARNING("wallpaper bug 417163 for Qt theme");
    2548               0 :     g_free(theme_name);
    2549                 :   }
    2550                 : 
    2551                 :   // gdk_display_close was broken prior to gtk+-2.10.0.
    2552                 :   // (http://bugzilla.gnome.org/show_bug.cgi?id=85715)
    2553                 :   // gdk_display_manager_set_default_display (gdk_display_manager_get(), NULL)
    2554                 :   // was also broken.
    2555               0 :   if (gtk_check_version(2,10,0) != NULL) {
    2556                 : #ifdef MOZ_X11
    2557                 :     // Version check failed - broken gdk_display_close.
    2558                 :     //
    2559                 :     // Let the gdk structures leak but at least close the Display,
    2560                 :     // assuming that gdk will not use it again.
    2561               0 :     Display* dpy = GDK_DISPLAY_XDISPLAY(display);
    2562               0 :     if (!theme_is_qt)
    2563               0 :       XCloseDisplay(dpy);
    2564                 : #else
    2565                 :     gdk_display_close(display);
    2566                 : #endif /* MOZ_X11 */
    2567                 :   }
    2568                 :   else {
    2569                 : #if CLEANUP_MEMORY
    2570                 :     // Get a (new) Pango context that holds a reference to the fontmap that
    2571                 :     // GTK has been using.  gdk_pango_context_get() must be called while GTK
    2572                 :     // has a default display.
    2573               0 :     PangoContext *pangoContext = gdk_pango_context_get();
    2574                 : #endif
    2575                 : 
    2576               0 :     bool buggyCairoShutdown = cairo_version() < CAIRO_VERSION_ENCODE(1, 4, 0);
    2577                 : 
    2578               0 :     if (!buggyCairoShutdown) {
    2579                 :       // We should shut down GDK before we shut down libraries it depends on
    2580                 :       // like Pango and cairo. But if cairo shutdown is buggy, we should
    2581                 :       // shut down cairo first otherwise it may crash because of dangling
    2582                 :       // references to Display objects (see bug 469831).
    2583               0 :       if (!theme_is_qt)
    2584               0 :         gdk_display_close(display);
    2585                 :     }
    2586                 : 
    2587                 : #if CLEANUP_MEMORY
    2588                 :     // This doesn't take a reference.
    2589               0 :     PangoFontMap *fontmap = pango_context_get_font_map(pangoContext);
    2590                 :     // Do some shutdown of the fontmap, which releases the fonts, clearing a
    2591                 :     // bunch of circular references from the fontmap through the fonts back to
    2592                 :     // itself.  The shutdown that this does is much less than what's done by
    2593                 :     // the fontmap's finalize, though.
    2594               0 :     if (PANGO_IS_FC_FONT_MAP(fontmap))
    2595               0 :         pango_fc_font_map_shutdown(PANGO_FC_FONT_MAP(fontmap));
    2596               0 :     g_object_unref(pangoContext);
    2597                 :     // PangoCairo still holds a reference to the fontmap.
    2598                 :     // Now that we have finished with GTK and Pango, we could unref fontmap,
    2599                 :     // which would allow us to call FcFini, but removing what is really
    2600                 :     // Pango's ref feels a bit evil.  Pango-1.22 will have support for
    2601                 :     // pango_cairo_font_map_set_default(NULL), which would release the
    2602                 :     // reference on the old fontmap.
    2603                 : 
    2604                 : #if GTK_CHECK_VERSION(2,8,0)
    2605                 :     // cairo_debug_reset_static_data() is prototyped through cairo.h included
    2606                 :     // by gtk.h.
    2607                 : #ifdef cairo_debug_reset_static_data
    2608                 : #error "Looks like we're including Mozilla's cairo instead of system cairo"
    2609                 : #endif
    2610               0 :     cairo_debug_reset_static_data();
    2611                 : #endif // 2.8.0
    2612                 : #endif // CLEANUP_MEMORY
    2613                 : 
    2614               0 :     if (buggyCairoShutdown) {
    2615               0 :       if (!theme_is_qt)
    2616               0 :         gdk_display_close(display);
    2617                 :     }
    2618                 :   }
    2619               0 : }
    2620                 : #endif // MOZ_WIDGET_GTK2
    2621                 : 
    2622                 : /** 
    2623                 :  * NSPR will search for the "nspr_use_zone_allocator" symbol throughout
    2624                 :  * the process and use it to determine whether the application defines its own
    2625                 :  * memory allocator or not.
    2626                 :  *
    2627                 :  * Since most applications (e.g. Firefox and Thunderbird) don't use any special
    2628                 :  * allocators and therefore don't define this symbol, NSPR must search the
    2629                 :  * entire process, which reduces startup performance.
    2630                 :  *
    2631                 :  * By defining the symbol here, we can avoid the wasted lookup and hopefully
    2632                 :  * improve startup performance.
    2633                 :  */
    2634                 : NS_VISIBILITY_DEFAULT PRBool nspr_use_zone_allocator = PR_FALSE;
    2635                 : 
    2636                 : #ifdef CAIRO_HAS_DWRITE_FONT
    2637                 : 
    2638                 : #include <dwrite.h>
    2639                 : 
    2640                 : typedef HRESULT (WINAPI*DWriteCreateFactoryFunc)(
    2641                 :   DWRITE_FACTORY_TYPE factoryType,
    2642                 :   REFIID iid,
    2643                 :   IUnknown **factory
    2644                 : );
    2645                 : 
    2646                 : #ifdef DEBUG_DWRITE_STARTUP
    2647                 : 
    2648                 : #define LOGREGISTRY(msg) LogRegistryEvent(msg)
    2649                 : 
    2650                 : // for use when monitoring process
    2651                 : static void LogRegistryEvent(const wchar_t *msg)
    2652                 : {
    2653                 :   HKEY dummyKey;
    2654                 :   HRESULT hr;
    2655                 :   wchar_t buf[512];
    2656                 : 
    2657                 :   wsprintf(buf, L" log %s", msg);
    2658                 :   hr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, buf, 0, KEY_READ, &dummyKey);
    2659                 :   if (SUCCEEDED(hr)) {
    2660                 :     RegCloseKey(dummyKey);
    2661                 :   }
    2662                 : }
    2663                 : #else
    2664                 : 
    2665                 : #define LOGREGISTRY(msg)
    2666                 : 
    2667                 : #endif
    2668                 : 
    2669                 : static DWORD InitDwriteBG(LPVOID lpdwThreadParam)
    2670                 : {
    2671                 :   SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_BEGIN);
    2672                 :   LOGREGISTRY(L"loading dwrite.dll");
    2673                 :   HMODULE dwdll = LoadLibraryW(L"dwrite.dll");
    2674                 :   if (dwdll) {
    2675                 :     DWriteCreateFactoryFunc createDWriteFactory = (DWriteCreateFactoryFunc)
    2676                 :       GetProcAddress(dwdll, "DWriteCreateFactory");
    2677                 :     if (createDWriteFactory) {
    2678                 :       LOGREGISTRY(L"creating dwrite factory");
    2679                 :       IDWriteFactory *factory;
    2680                 :       HRESULT hr = createDWriteFactory(
    2681                 :         DWRITE_FACTORY_TYPE_SHARED,
    2682                 :         __uuidof(IDWriteFactory),
    2683                 :         reinterpret_cast<IUnknown**>(&factory));
    2684                 :       if (SUCCEEDED(hr)) {
    2685                 :         LOGREGISTRY(L"dwrite factory done");
    2686                 :         factory->Release();
    2687                 :         LOGREGISTRY(L"freed factory");
    2688                 :       } else {
    2689                 :         LOGREGISTRY(L"failed to create factory");
    2690                 :       }
    2691                 :     }
    2692                 :   }
    2693                 :   SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_END);
    2694                 :   return 0;
    2695                 : }
    2696                 : #endif
    2697                 : 
    2698                 : #ifdef MOZ_X11
    2699                 : #ifndef MOZ_PLATFORM_MAEMO
    2700                 : bool fire_glxtest_process();
    2701                 : #endif
    2702                 : #endif
    2703                 : 
    2704                 : #include "sampler.h"
    2705                 : 
    2706                 : int
    2707              23 : XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
    2708                 : {
    2709                 :   NS_TIME_FUNCTION;
    2710              23 :   SAMPLER_INIT();
    2711              46 :   SAMPLE_LABEL("Startup", "XRE_Main");
    2712                 : 
    2713              23 :   StartupTimeline::Record(StartupTimeline::MAIN);
    2714                 : 
    2715                 :   nsresult rv;
    2716                 :   ArgResult ar;
    2717                 : 
    2718                 : #ifdef DEBUG
    2719              23 :   if (PR_GetEnv("XRE_MAIN_BREAK"))
    2720               0 :     NS_BREAK();
    2721                 : #endif
    2722                 : 
    2723                 :   // see bug 639842
    2724                 :   // it's very important to fire this process BEFORE we set up error handling.
    2725                 :   // indeed, this process is expected to be crashy, and we don't want the user to see its crashes.
    2726                 :   // That's the whole reason for doing this in a separate process.
    2727                 : #ifdef MOZ_X11
    2728                 : #ifndef MOZ_PLATFORM_MAEMO
    2729              23 :   if (fire_glxtest_process())
    2730               0 :     return 0;
    2731                 : #endif
    2732                 : #endif
    2733                 : 
    2734                 : #ifdef XP_WIN
    2735                 :   // Vista API.  Mozilla is DPI Aware.
    2736                 :   typedef BOOL (*SetProcessDPIAwareFunc)(VOID);
    2737                 : 
    2738                 :   SetProcessDPIAwareFunc setDPIAware = (SetProcessDPIAwareFunc)
    2739                 :     GetProcAddress(LoadLibraryW(L"user32.dll"), "SetProcessDPIAware");
    2740                 : 
    2741                 :   if (setDPIAware)
    2742                 :     setDPIAware();
    2743                 : #endif
    2744                 : 
    2745              23 :   SetupErrorHandling(argv[0]);
    2746                 : 
    2747                 : #ifdef CAIRO_HAS_DWRITE_FONT
    2748                 : 
    2749                 :   // Bug 602792 - when DWriteCreateFactory is called the dwrite client dll
    2750                 :   // starts the FntCache service if it isn't already running (it's set
    2751                 :   // to manual startup by default in Windows 7 RTM).  Subsequent DirectWrite
    2752                 :   // calls cause the IDWriteFactory object to communicate with the FntCache
    2753                 :   // service with a timeout; if there's no response after the timeout, the
    2754                 :   // DirectWrite client library will assume the service isn't around and do
    2755                 :   // manual font file I/O on _all_ system fonts.  To avoid this, load the
    2756                 :   // dwrite library and create a factory as early as possible so that the
    2757                 :   // FntCache service is ready by the time it's needed.
    2758                 :       
    2759                 :   OSVERSIONINFO vinfo;
    2760                 :   vinfo.dwOSVersionInfoSize = sizeof(vinfo);
    2761                 :   if (GetVersionEx(&vinfo) && vinfo.dwMajorVersion >= 6) {
    2762                 :     CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&InitDwriteBG, NULL, 0, NULL);
    2763                 :   }
    2764                 : 
    2765                 : #endif
    2766                 : 
    2767                 : #ifdef XP_UNIX
    2768              23 :   const char *home = PR_GetEnv("HOME");
    2769              23 :   if (!home || !*home) {
    2770               0 :     struct passwd *pw = getpwuid(geteuid());
    2771               0 :     if (!pw || !pw->pw_dir) {
    2772               0 :       Output(true, "Could not determine HOME directory");
    2773               0 :       return 1;
    2774                 :     }
    2775               0 :     SaveWordToEnv("HOME", nsDependentCString(pw->pw_dir));
    2776                 :   }
    2777                 : #endif
    2778                 : 
    2779                 : #ifdef MOZ_ACCESSIBILITY_ATK
    2780                 :   // Reset GTK_MODULES, strip atk-bridge if exists
    2781                 :   // Mozilla will load libatk-bridge.so later if necessary
    2782              23 :   const char* gtkModules = PR_GetEnv("GTK_MODULES");
    2783              23 :   if (gtkModules && *gtkModules) {
    2784               0 :     nsCString gtkModulesStr(gtkModules);
    2785               0 :     gtkModulesStr.ReplaceSubstring("atk-bridge", "");
    2786               0 :     char* expr = PR_smprintf("GTK_MODULES=%s", gtkModulesStr.get());
    2787               0 :     if (expr)
    2788               0 :       PR_SetEnv(expr);
    2789                 :     // We intentionally leak |expr| here since it is required by PR_SetEnv.
    2790                 :   }
    2791                 : 
    2792                 :   // Suppress atk-bridge init at startup, it works after GNOME 2.24.2
    2793              23 :   SaveToEnv("NO_AT_BRIDGE=1");
    2794                 : #endif
    2795                 : 
    2796              23 :   gArgc = argc;
    2797              23 :   gArgv = argv;
    2798                 : 
    2799              23 :   NS_ENSURE_TRUE(aAppData, 2);
    2800                 : 
    2801                 :   // Check for application.ini overrides
    2802              23 :   const char* override = nsnull;
    2803              23 :   ar = CheckArg("override", true, &override);
    2804              23 :   if (ar == ARG_BAD) {
    2805               0 :     Output(true, "Incorrect number of arguments passed to -override");
    2806               0 :     return 1;
    2807                 :   }
    2808              23 :   else if (ar == ARG_FOUND) {
    2809               0 :     nsCOMPtr<nsILocalFile> overrideLF;
    2810               0 :     rv = XRE_GetFileFromPath(override, getter_AddRefs(overrideLF));
    2811               0 :     if (NS_FAILED(rv)) {
    2812               0 :       Output(true, "Error: unrecognized override.ini path.\n");
    2813               0 :       return 1;
    2814                 :     }
    2815                 : 
    2816               0 :     nsXREAppData* overrideAppData = const_cast<nsXREAppData*>(aAppData);
    2817               0 :     rv = XRE_ParseAppData(overrideLF, overrideAppData);
    2818               0 :     if (NS_FAILED(rv)) {
    2819               0 :       Output(true, "Couldn't read override.ini");
    2820               0 :       return 1;
    2821                 :     }
    2822                 :   }
    2823                 : 
    2824              46 :   ScopedAppData appData(aAppData);
    2825              23 :   gAppData = &appData;
    2826                 : 
    2827                 :   // Check sanity and correctness of app data.
    2828                 : 
    2829              23 :   if (!appData.name) {
    2830               0 :     Output(true, "Error: App:Name not specified in application.ini\n");
    2831               0 :     return 1;
    2832                 :   }
    2833              23 :   if (!appData.buildID) {
    2834               0 :     Output(true, "Error: App:BuildID not specified in application.ini\n");
    2835               0 :     return 1;
    2836                 :   }
    2837                 : 
    2838              46 :   ScopedLogging log;
    2839                 : 
    2840              23 :   if (!appData.xreDirectory) {
    2841              46 :     nsCOMPtr<nsILocalFile> lf;
    2842              23 :     rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
    2843              23 :     if (NS_FAILED(rv))
    2844               0 :       return 2;
    2845                 : 
    2846              46 :     nsCOMPtr<nsIFile> greDir;
    2847              23 :     rv = lf->GetParent(getter_AddRefs(greDir));
    2848              23 :     if (NS_FAILED(rv))
    2849               0 :       return 2;
    2850                 :     
    2851              23 :     rv = CallQueryInterface(greDir, &appData.xreDirectory);
    2852              23 :     if (NS_FAILED(rv))
    2853               0 :       return 2;
    2854                 :   }
    2855                 : 
    2856              23 :   if (!appData.directory) {
    2857              23 :     NS_IF_ADDREF(appData.directory = appData.xreDirectory);
    2858                 :   }
    2859                 : 
    2860              23 :   if (appData.size > offsetof(nsXREAppData, minVersion)) {
    2861              23 :     if (!appData.minVersion) {
    2862               0 :       Output(true, "Error: Gecko:MinVersion not specified in application.ini\n");
    2863               0 :       return 1;
    2864                 :     }
    2865                 : 
    2866              23 :     if (!appData.maxVersion) {
    2867                 :       // If no maxVersion is specified, we assume the app is only compatible
    2868                 :       // with the initial preview release. Do not increment this number ever!
    2869               0 :       SetAllocatedString(appData.maxVersion, "1.*");
    2870                 :     }
    2871                 : 
    2872              46 :     if (NS_CompareVersions(appData.minVersion, gToolkitVersion) > 0 ||
    2873              23 :         NS_CompareVersions(appData.maxVersion, gToolkitVersion) < 0) {
    2874                 :       Output(true, "Error: Platform version '%s' is not compatible with\n"
    2875                 :              "minVersion >= %s\nmaxVersion <= %s\n",
    2876                 :              gToolkitVersion,
    2877               0 :              appData.minVersion, appData.maxVersion);
    2878               0 :       return 1;
    2879                 :     }
    2880                 :   }
    2881                 : 
    2882              46 :   nsXREDirProvider dirProvider;
    2883              23 :   rv = dirProvider.Initialize(gAppData->directory, gAppData->xreDirectory);
    2884              23 :   if (NS_FAILED(rv))
    2885               0 :     return 1;
    2886                 : 
    2887                 : #ifdef MOZ_CRASHREPORTER
    2888              23 :   if (EnvHasValue("MOZ_CRASHREPORTER")) {
    2889              22 :     appData.flags |= NS_XRE_ENABLE_CRASH_REPORTER;
    2890                 :   }
    2891                 : 
    2892              45 :   if ((appData.flags & NS_XRE_ENABLE_CRASH_REPORTER) &&
    2893              22 :       NS_SUCCEEDED(
    2894                 :          CrashReporter::SetExceptionHandler(appData.xreDirectory))) {
    2895              22 :     if (appData.crashReporterURL)
    2896              22 :       CrashReporter::SetServerURL(nsDependentCString(appData.crashReporterURL));
    2897                 : 
    2898                 :     // pass some basic info from the app data
    2899              22 :     if (appData.vendor)
    2900              22 :       CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Vendor"),
    2901              44 :                                          nsDependentCString(appData.vendor));
    2902              22 :     if (appData.name)
    2903              22 :       CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ProductName"),
    2904              44 :                                          nsDependentCString(appData.name));
    2905              22 :     if (appData.ID)
    2906              22 :       CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ProductID"),
    2907              44 :                                          nsDependentCString(appData.ID));
    2908              22 :     if (appData.version)
    2909              22 :       CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Version"),
    2910              44 :                                          nsDependentCString(appData.version));
    2911              22 :     if (appData.buildID)
    2912              22 :       CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("BuildID"),
    2913              44 :                                          nsDependentCString(appData.buildID));
    2914                 : 
    2915              44 :     nsDependentCString releaseChannel(NS_STRINGIFY(MOZ_UPDATE_CHANNEL));
    2916              22 :     CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ReleaseChannel"),
    2917              22 :                                        releaseChannel);
    2918              22 :     CrashReporter::SetRestartArgs(argc, argv);
    2919                 : 
    2920                 :     // annotate other data (user id etc)
    2921              44 :     nsCOMPtr<nsILocalFile> userAppDataDir;
    2922              22 :     if (NS_SUCCEEDED(dirProvider.GetUserAppDataDirectory(
    2923                 :                                                          getter_AddRefs(userAppDataDir)))) {
    2924                 :       CrashReporter::SetupExtraData(userAppDataDir,
    2925              22 :                                     nsDependentCString(appData.buildID));
    2926                 : 
    2927                 :       // see if we have a crashreporter-override.ini in the application directory
    2928              44 :       nsCOMPtr<nsIFile> overrideini;
    2929                 :       bool exists;
    2930             110 :       if (NS_SUCCEEDED(dirProvider.GetAppDir()->Clone(getter_AddRefs(overrideini))) &&
    2931              66 :           NS_SUCCEEDED(overrideini->AppendNative(NS_LITERAL_CSTRING("crashreporter-override.ini"))) &&
    2932              22 :           NS_SUCCEEDED(overrideini->Exists(&exists)) &&
    2933                 :           exists) {
    2934                 : #ifdef XP_WIN
    2935                 :         nsAutoString overridePathW;
    2936                 :         overrideini->GetPath(overridePathW);
    2937                 :         NS_ConvertUTF16toUTF8 overridePath(overridePathW);
    2938                 : #else
    2939              44 :         nsCAutoString overridePath;
    2940              22 :         overrideini->GetNativePath(overridePath);
    2941                 : #endif
    2942                 : 
    2943              22 :         SaveWordToEnv("MOZ_CRASHREPORTER_STRINGS_OVERRIDE", overridePath);
    2944                 :       }
    2945                 :     }
    2946                 :   }
    2947                 : #endif
    2948                 : 
    2949                 : #ifdef XP_MACOSX
    2950                 :   if (EnvHasValue("MOZ_LAUNCHED_CHILD")) {
    2951                 :     // This is needed, on relaunch, to force the OS to use the "Cocoa Dock
    2952                 :     // API".  Otherwise the call to ReceiveNextEvent() below will make it
    2953                 :     // use the "Carbon Dock API".  For more info see bmo bug 377166.
    2954                 :     EnsureUseCocoaDockAPI();
    2955                 : 
    2956                 :     // When the app relaunches, the original process exits.  This causes
    2957                 :     // the dock tile to stop bouncing, lose the "running" triangle, and
    2958                 :     // if the tile does not permanently reside in the Dock, even disappear.
    2959                 :     // This can be confusing to the user, who is expecting the app to launch.
    2960                 :     // Calling ReceiveNextEvent without requesting any event is enough to
    2961                 :     // cause a dock tile for the child process to appear.
    2962                 :     const EventTypeSpec kFakeEventList[] = { { INT_MAX, INT_MAX } };
    2963                 :     EventRef event;
    2964                 :     ::ReceiveNextEvent(GetEventTypeCount(kFakeEventList), kFakeEventList,
    2965                 :                        kEventDurationNoWait, false, &event);
    2966                 :   }
    2967                 : 
    2968                 :   if (CheckArg("foreground")) {
    2969                 :     // The original process communicates that it was in the foreground by
    2970                 :     // adding this argument.  This new process, which is taking over for
    2971                 :     // the old one, should make itself the active application.
    2972                 :     ProcessSerialNumber psn;
    2973                 :     if (::GetCurrentProcess(&psn) == noErr)
    2974                 :       ::SetFrontProcess(&psn);
    2975                 :   }
    2976                 : #endif
    2977                 : 
    2978              23 :   SaveToEnv("MOZ_LAUNCHED_CHILD=");
    2979                 : 
    2980              23 :   gRestartArgc = gArgc;
    2981              23 :   gRestartArgv = (char**) malloc(sizeof(char*) * (gArgc + 1 + (override ? 2 : 0)));
    2982              23 :   if (!gRestartArgv) return 1;
    2983                 : 
    2984                 :   int i;
    2985             138 :   for (i = 0; i < gArgc; ++i) {
    2986             115 :     gRestartArgv[i] = gArgv[i];
    2987                 :   }
    2988                 :   
    2989                 :   // Add the -override argument back (it is removed automatically be CheckArg) if there is one
    2990              23 :   if (override) {
    2991               0 :     gRestartArgv[gRestartArgc++] = const_cast<char*>("-override");
    2992               0 :     gRestartArgv[gRestartArgc++] = const_cast<char*>(override);
    2993                 :   }
    2994                 : 
    2995              23 :   gRestartArgv[gRestartArgc] = nsnull;
    2996                 :   
    2997                 : 
    2998                 : #if defined(XP_OS2)
    2999                 :   bool StartOS2App(int aArgc, char **aArgv);
    3000                 :   if (!StartOS2App(gArgc, gArgv))
    3001                 :     return 1;
    3002                 :   ScopedFPHandler handler;
    3003                 : #endif /* XP_OS2 */
    3004                 : 
    3005              23 :   if (EnvHasValue("MOZ_SAFE_MODE_RESTART")) {
    3006               0 :     gSafeMode = true;
    3007                 :     // unset the env variable
    3008               0 :     SaveToEnv("MOZ_SAFE_MODE_RESTART=");
    3009                 :   }
    3010                 : 
    3011              23 :   ar = CheckArg("safe-mode", true);
    3012              23 :   if (ar == ARG_BAD) {
    3013               0 :     PR_fprintf(PR_STDERR, "Error: argument -safe-mode is invalid when argument -osint is specified\n");
    3014               0 :     return 1;
    3015              23 :   } else if (ar == ARG_FOUND) {
    3016               0 :     gSafeMode = true;
    3017                 :   }
    3018                 : 
    3019                 : #ifdef XP_WIN
    3020                 :   // If the shift key is pressed and the ctrl and / or alt keys are not pressed
    3021                 :   // during startup start in safe mode. GetKeyState returns a short and the high
    3022                 :   // order bit will be 1 if the key is pressed. By masking the returned short
    3023                 :   // with 0x8000 the result will be 0 if the key is not pressed and non-zero
    3024                 :   // otherwise.
    3025                 :   if (GetKeyState(VK_SHIFT) & 0x8000 &&
    3026                 :       !(GetKeyState(VK_CONTROL) & 0x8000) && !(GetKeyState(VK_MENU) & 0x8000)) {
    3027                 :     gSafeMode = true;
    3028                 :   }
    3029                 : #endif
    3030                 : 
    3031                 : #ifdef XP_MACOSX
    3032                 :   if (GetCurrentEventKeyModifiers() & optionKey)
    3033                 :     gSafeMode = true;
    3034                 : #endif
    3035                 : 
    3036                 :   // Handle -no-remote and -new-instance command line arguments. Setup
    3037                 :   // the environment to better accommodate other components and various
    3038                 :   // restart scenarios.
    3039              23 :   ar = CheckArg("no-remote", true);
    3040              23 :   if (ar == ARG_BAD) {
    3041               0 :     PR_fprintf(PR_STDERR, "Error: argument -no-remote is invalid when argument -osint is specified\n");
    3042               0 :     return 1;
    3043              23 :   } else if (ar == ARG_FOUND) {
    3044              23 :     SaveToEnv("MOZ_NO_REMOTE=1");
    3045                 :   }
    3046              23 :   ar = CheckArg("new-instance", true);
    3047              23 :   if (ar == ARG_BAD) {
    3048               0 :     PR_fprintf(PR_STDERR, "Error: argument -new-instance is invalid when argument -osint is specified\n");
    3049               0 :     return 1;
    3050              23 :   } else if (ar == ARG_FOUND) {
    3051               0 :     SaveToEnv("MOZ_NEW_INSTANCE=1");
    3052                 :   }
    3053                 : 
    3054                 :   // Handle -help and -version command line arguments.
    3055                 :   // They should return quickly, so we deal with them here.
    3056              23 :   if (CheckArg("h") || CheckArg("help") || CheckArg("?")) {
    3057               0 :     DumpHelp();
    3058               0 :     return 0;
    3059                 :   }
    3060                 : 
    3061              23 :   if (CheckArg("v") || CheckArg("version")) {
    3062               0 :     DumpVersion();
    3063               0 :     return 0;
    3064                 :   }
    3065                 :     
    3066                 : #ifdef NS_TRACE_MALLOC
    3067                 :   gArgc = argc = NS_TraceMallocStartupArgs(gArgc, gArgv);
    3068                 : #endif
    3069                 : 
    3070              23 :   rv = XRE_InitCommandLine(gArgc, gArgv);
    3071              23 :   NS_ENSURE_SUCCESS(rv, 1);
    3072                 : 
    3073                 :   {
    3074                 :     // Check for -register, which registers chrome and then exits immediately.
    3075              23 :     ar = CheckArg("register", true);
    3076              23 :     if (ar == ARG_BAD) {
    3077               0 :       PR_fprintf(PR_STDERR, "Error: argument -register is invalid when argument -osint is specified\n");
    3078               0 :       return 1;
    3079              23 :     } else if (ar == ARG_FOUND) {
    3080               0 :       ScopedXPCOMStartup xpcom;
    3081               0 :       rv = xpcom.Initialize();
    3082               0 :       NS_ENSURE_SUCCESS(rv, 1);
    3083                 : 
    3084                 :       {
    3085                 :         nsCOMPtr<nsIChromeRegistry> chromeReg =
    3086               0 :           mozilla::services::GetChromeRegistryService();
    3087               0 :         NS_ENSURE_TRUE(chromeReg, 1);
    3088                 : 
    3089               0 :         chromeReg->CheckForNewChrome();
    3090                 :       }
    3091               0 :       return 0;
    3092                 :     }
    3093                 : 
    3094                 : #if defined(MOZ_WIDGET_GTK2) || defined(MOZ_ENABLE_XREMOTE)
    3095                 :     // Stash DESKTOP_STARTUP_ID in malloc'ed memory because gtk_init will clear it.
    3096                 : #define HAVE_DESKTOP_STARTUP_ID
    3097              23 :     const char* desktopStartupIDEnv = PR_GetEnv("DESKTOP_STARTUP_ID");
    3098              46 :     nsCAutoString desktopStartupID;
    3099              23 :     if (desktopStartupIDEnv) {
    3100               0 :       desktopStartupID.Assign(desktopStartupIDEnv);
    3101                 :     }
    3102                 : #endif
    3103                 : 
    3104                 : #if defined(MOZ_WIDGET_QT)
    3105                 :     nsQAppInstance::AddRef(gArgc, gArgv, true);
    3106                 : 
    3107                 : #if MOZ_PLATFORM_MAEMO > 5
    3108                 :     if (XRE_GetProcessType() == GeckoProcessType_Default) {
    3109                 :       // try to get the MInputContext if possible to support the MeeGo VKB
    3110                 :       QInputContext* inputContext = qApp->inputContext();
    3111                 :       if (inputContext && inputContext->identifierName() != "MInputContext") {
    3112                 :           QInputContext* context = QInputContextFactory::create("MInputContext",
    3113                 :                                                                 qApp);
    3114                 :           if (context)
    3115                 :               qApp->setInputContext(context);
    3116                 :       }
    3117                 :     }
    3118                 : #endif
    3119                 :     QStringList nonQtArguments = qApp->arguments();
    3120                 :     gQtOnlyArgc = 1;
    3121                 :     gQtOnlyArgv = (char**) malloc(sizeof(char*) 
    3122                 :                   * (gRestartArgc - nonQtArguments.size() + 2));
    3123                 : 
    3124                 :     // copy binary path
    3125                 :     gQtOnlyArgv[0] = gRestartArgv[0];
    3126                 : 
    3127                 :     for (int i = 1; i < gRestartArgc; ++i) {
    3128                 :       if (!nonQtArguments.contains(gRestartArgv[i])) {
    3129                 :         // copy arguments used by Qt for later
    3130                 :         gQtOnlyArgv[gQtOnlyArgc++] = gRestartArgv[i];
    3131                 :       }
    3132                 :     }
    3133                 :     gQtOnlyArgv[gQtOnlyArgc] = nsnull;
    3134                 : #endif
    3135                 : #if defined(MOZ_WIDGET_GTK2)
    3136                 : #ifdef MOZ_MEMORY
    3137                 :     // Disable the slice allocator, since jemalloc already uses similar layout
    3138                 :     // algorithms, and using a sub-allocator tends to increase fragmentation.
    3139                 :     // This must be done before g_thread_init() is called.
    3140              23 :     g_slice_set_config(G_SLICE_CONFIG_ALWAYS_MALLOC, 1);
    3141                 : #endif
    3142              23 :     g_thread_init(NULL);
    3143                 :     // setup for private colormap.  Ideally we'd like to do this
    3144                 :     // in nsAppShell::Create, but we need to get in before gtk
    3145                 :     // has been initialized to make sure everything is running
    3146                 :     // consistently.
    3147              23 :     if (CheckArg("install"))
    3148               0 :       gdk_rgb_set_install(TRUE);
    3149                 : 
    3150                 :     // Initialize GTK here for splash.
    3151                 : 
    3152                 :     // Open the display ourselves instead of using gtk_init, so that we can
    3153                 :     // close it without fear that one day gtk might clean up the display it
    3154                 :     // opens.
    3155              23 :     if (!gtk_parse_args(&gArgc, &gArgv))
    3156               0 :       return 1;
    3157                 : 
    3158                 :     // display_name is owned by gdk.
    3159              23 :     const char *display_name = gdk_get_display_arg_name();
    3160              23 :     if (display_name) {
    3161               0 :       SaveWordToEnv("DISPLAY", nsDependentCString(display_name));
    3162                 :     } else {
    3163              23 :       display_name = PR_GetEnv("DISPLAY");
    3164              23 :       if (!display_name) {
    3165              23 :         PR_fprintf(PR_STDERR, "Error: no display specified\n");
    3166              23 :         return 1;
    3167                 :       }
    3168                 :     }
    3169                 : #endif /* MOZ_WIDGET_GTK2 */
    3170                 : 
    3171                 : #ifdef MOZ_ENABLE_XREMOTE
    3172                 :     // handle -remote now that xpcom is fired up
    3173                 :     bool disableRemote, newInstance;
    3174                 :     {
    3175               0 :       char *e = PR_GetEnv("MOZ_NO_REMOTE");
    3176               0 :       disableRemote = (e && *e);
    3177               0 :       if (disableRemote) {
    3178               0 :         newInstance = true;
    3179                 :       } else {
    3180               0 :         e = PR_GetEnv("MOZ_NEW_INSTANCE");
    3181               0 :         newInstance = (e && *e);
    3182                 :       }
    3183                 :     }
    3184                 : 
    3185                 :     const char* xremotearg;
    3186               0 :     ar = CheckArg("remote", true, &xremotearg);
    3187               0 :     if (ar == ARG_BAD) {
    3188               0 :       PR_fprintf(PR_STDERR, "Error: -remote requires an argument\n");
    3189               0 :       return 1;
    3190                 :     }
    3191                 :     const char* desktopStartupIDPtr =
    3192               0 :       desktopStartupID.IsEmpty() ? nsnull : desktopStartupID.get();
    3193               0 :     if (ar) {
    3194               0 :       return HandleRemoteArgument(xremotearg, desktopStartupIDPtr);
    3195                 :     }
    3196                 : 
    3197               0 :     if (!newInstance) {
    3198                 :       // Try to remote the entire command line. If this fails, start up normally.
    3199               0 :       RemoteResult rr = RemoteCommandLine(desktopStartupIDPtr);
    3200               0 :       if (rr == REMOTE_FOUND)
    3201               0 :         return 0;
    3202               0 :       else if (rr == REMOTE_ARG_BAD)
    3203               0 :         return 1;
    3204                 :     }
    3205                 : #endif
    3206                 : 
    3207                 : #if defined(MOZ_WIDGET_GTK2)
    3208               0 :     GdkDisplay* display = nsnull;
    3209               0 :     display = gdk_display_open(display_name);
    3210               0 :     if (!display) {
    3211               0 :       PR_fprintf(PR_STDERR, "Error: cannot open display: %s\n", display_name);
    3212               0 :       return 1;
    3213                 :     }
    3214                 :     gdk_display_manager_set_default_display (gdk_display_manager_get(),
    3215               0 :                                              display);
    3216                 :     
    3217                 :     // g_set_application_name () is only defined in glib2.2 and higher.
    3218                 :     _g_set_application_name_fn _g_set_application_name =
    3219               0 :       (_g_set_application_name_fn)FindFunction("g_set_application_name");
    3220               0 :     if (_g_set_application_name) {
    3221               0 :       _g_set_application_name(gAppData->name);
    3222                 :     }
    3223                 :     _gtk_window_set_auto_startup_notification_fn _gtk_window_set_auto_startup_notification =
    3224               0 :       (_gtk_window_set_auto_startup_notification_fn)FindFunction("gtk_window_set_auto_startup_notification");
    3225               0 :     if (_gtk_window_set_auto_startup_notification) {
    3226               0 :       _gtk_window_set_auto_startup_notification(false);
    3227                 :     }
    3228                 : 
    3229               0 :     gtk_widget_set_default_colormap(gdk_rgb_get_colormap());
    3230                 : #endif /* MOZ_WIDGET_GTK2 */
    3231                 : #ifdef MOZ_X11
    3232                 :     // Do this after initializing GDK, or GDK will install its own handler.
    3233               0 :     InstallX11ErrorHandler();
    3234                 : #endif
    3235                 : 
    3236                 :     // Call the code to install our handler
    3237                 : #ifdef MOZ_JPROF
    3238                 :     setupProfilingStuff();
    3239                 : #endif
    3240                 : 
    3241                 :     // Try to allocate "native app support."
    3242               0 :     nsCOMPtr<nsINativeAppSupport> nativeApp;
    3243               0 :     rv = NS_CreateNativeAppSupport(getter_AddRefs(nativeApp));
    3244               0 :     if (NS_FAILED(rv))
    3245               0 :       return 1;
    3246                 : 
    3247               0 :     bool canRun = false;
    3248               0 :     rv = nativeApp->Start(&canRun);
    3249               0 :     if (NS_FAILED(rv) || !canRun) {
    3250               0 :       return 1;
    3251                 :     }
    3252                 : 
    3253                 : #if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK2)
    3254                 :     // DESKTOP_STARTUP_ID is cleared now,
    3255                 :     // we recover it in case we need a restart.
    3256               0 :     if (!desktopStartupID.IsEmpty()) {
    3257               0 :       nsCAutoString desktopStartupEnv;
    3258               0 :       desktopStartupEnv.AssignLiteral("DESKTOP_STARTUP_ID=");
    3259               0 :       desktopStartupEnv.Append(desktopStartupID);
    3260                 :       // Leak it with extreme prejudice!
    3261               0 :       PR_SetEnv(ToNewCString(desktopStartupEnv));
    3262                 :     }
    3263                 : #endif
    3264                 : 
    3265                 : #if defined(MOZ_UPDATER) && !defined(ANDROID)
    3266                 :     // Check for and process any available updates
    3267               0 :     nsCOMPtr<nsIFile> updRoot;
    3268                 :     bool persistent;
    3269                 :     rv = dirProvider.GetFile(XRE_UPDATE_ROOT_DIR, &persistent,
    3270               0 :                              getter_AddRefs(updRoot));
    3271                 :     // XRE_UPDATE_ROOT_DIR may fail. Fallback to appDir if failed
    3272               0 :     if (NS_FAILED(rv))
    3273               0 :       updRoot = dirProvider.GetAppDir();
    3274                 : 
    3275                 :     // If the MOZ_PROCESS_UPDATES environment variable already exists, then
    3276                 :     // we are being called from the callback application.
    3277               0 :     if (EnvHasValue("MOZ_PROCESS_UPDATES")) {
    3278                 :       // If the caller has asked us to log our arguments, do so.  This is used
    3279                 :       // to make sure that the maintenance service successfully launches the
    3280                 :       // callback application.
    3281               0 :       const char *logFile = nsnull;
    3282               0 :       if (ARG_FOUND == CheckArg("dump-args", false, &logFile)) {
    3283               0 :         FILE* logFP = fopen(logFile, "wb");
    3284               0 :         if (logFP) {
    3285               0 :           for (i = 1; i < gRestartArgc; ++i) {
    3286               0 :             fprintf(logFP, "%s\n", gRestartArgv[i]);
    3287                 :           }
    3288               0 :           fclose(logFP);
    3289                 :         }
    3290                 :       }
    3291               0 :       return 0;
    3292                 :     }
    3293                 : 
    3294                 :     // Support for processing an update and exiting. The MOZ_PROCESS_UPDATES
    3295                 :     // environment variable will be part of the updater's environment and the
    3296                 :     // application that is relaunched by the updater. When the application is
    3297                 :     // relaunched by the updater it will be removed below and the application
    3298                 :     // will exit.
    3299               0 :     if (CheckArg("process-updates")) {
    3300               0 :       SaveToEnv("MOZ_PROCESS_UPDATES=1");
    3301                 :     }
    3302                 :     ProcessUpdates(dirProvider.GetGREDir(),
    3303                 :                    dirProvider.GetAppDir(),
    3304                 :                    updRoot,
    3305                 :                    gRestartArgc,
    3306                 :                    gRestartArgv,
    3307               0 :                    appData.version);
    3308               0 :     if (EnvHasValue("MOZ_PROCESS_UPDATES")) {
    3309               0 :       SaveToEnv("MOZ_PROCESS_UPDATES=");
    3310               0 :       return 0;
    3311                 :     }
    3312                 : #endif
    3313                 : 
    3314               0 :     nsCOMPtr<nsIProfileLock> profileLock;
    3315               0 :     bool startOffline = false;
    3316               0 :     nsCAutoString profileName;
    3317                 : 
    3318               0 :     nsCOMPtr<nsIToolkitProfileService> profileSvc;
    3319               0 :     rv = NS_NewToolkitProfileService(getter_AddRefs(profileSvc));
    3320               0 :     if (rv == NS_ERROR_FILE_ACCESS_DENIED) {
    3321                 :       PR_fprintf(PR_STDERR, "Error: Access was denied while trying to open files in " \
    3322               0 :                  "your profile directory.\n");
    3323                 :     }
    3324               0 :     if (NS_FAILED(rv)) {
    3325                 :       // We failed to choose or create profile - notify user and quit
    3326               0 :       ProfileMissingDialog(nativeApp);
    3327               0 :       return 1;
    3328                 :     }
    3329                 : 
    3330               0 :     rv = SelectProfile(getter_AddRefs(profileLock), profileSvc, nativeApp, &startOffline,
    3331               0 :                        &profileName);
    3332               0 :     if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ||
    3333               0 :         rv == NS_ERROR_ABORT) return 0;
    3334                 : 
    3335               0 :     if (NS_FAILED(rv)) {
    3336                 :       // We failed to choose or create profile - notify user and quit
    3337               0 :       ProfileMissingDialog(nativeApp);
    3338               0 :       return 1;
    3339                 :     }
    3340               0 :     gProfileLock = profileLock;
    3341                 : 
    3342               0 :     nsCOMPtr<nsILocalFile> profD;
    3343               0 :     rv = profileLock->GetDirectory(getter_AddRefs(profD));
    3344               0 :     NS_ENSURE_SUCCESS(rv, 1);
    3345                 : 
    3346               0 :     nsCOMPtr<nsILocalFile> profLD;
    3347               0 :     rv = profileLock->GetLocalDirectory(getter_AddRefs(profLD));
    3348               0 :     NS_ENSURE_SUCCESS(rv, 1);
    3349                 : 
    3350               0 :     rv = dirProvider.SetProfile(profD, profLD);
    3351               0 :     NS_ENSURE_SUCCESS(rv, 1);
    3352                 : 
    3353                 :     //////////////////////// NOW WE HAVE A PROFILE ////////////////////////
    3354                 : 
    3355                 : #ifdef MOZ_CRASHREPORTER
    3356               0 :     if (appData.flags & NS_XRE_ENABLE_CRASH_REPORTER)
    3357               0 :         MakeOrSetMinidumpPath(profD);
    3358                 : #endif
    3359                 : 
    3360               0 :     nsCAutoString version;
    3361               0 :     BuildVersion(version);
    3362                 : 
    3363                 : #ifdef TARGET_OS_ABI
    3364               0 :     NS_NAMED_LITERAL_CSTRING(osABI, TARGET_OS_ABI);
    3365                 : #else
    3366                 :     // No TARGET_XPCOM_ABI, but at least the OS is known
    3367                 :     NS_NAMED_LITERAL_CSTRING(osABI, OS_TARGET "_UNKNOWN");
    3368                 : #endif
    3369                 : 
    3370                 :     // Check for version compatibility with the last version of the app this 
    3371                 :     // profile was started with.  The format of the version stamp is defined
    3372                 :     // by the BuildVersion function.
    3373                 :     // Also check to see if something has happened to invalidate our
    3374                 :     // fastload caches, like an extension upgrade or installation.
    3375                 :  
    3376                 :     // If we see .purgecaches, that means someone did a make. 
    3377                 :     // Re-register components to catch potential changes.
    3378                 :     // We only offer this in debug builds, though.
    3379               0 :     nsCOMPtr<nsILocalFile> flagFile;
    3380                 : 
    3381               0 :     rv = NS_ERROR_FILE_NOT_FOUND;
    3382               0 :     nsCOMPtr<nsIFile> fFlagFile;
    3383               0 :     if (gAppData->directory) {
    3384               0 :       rv = gAppData->directory->Clone(getter_AddRefs(fFlagFile));
    3385                 :     }
    3386               0 :     flagFile = do_QueryInterface(fFlagFile);
    3387               0 :     if (flagFile) {
    3388               0 :       flagFile->AppendNative(FILE_INVALIDATE_CACHES);
    3389                 :     }
    3390                 : 
    3391                 :     bool cachesOK;
    3392                 :     bool versionOK = CheckCompatibility(profD, version, osABI, 
    3393                 :                                           dirProvider.GetGREDir(),
    3394                 :                                           gAppData->directory, flagFile,
    3395               0 :                                           &cachesOK);
    3396               0 :     if (CheckArg("purgecaches")) {
    3397               0 :       cachesOK = false;
    3398                 :     }
    3399               0 :     if (PR_GetEnv("MOZ_PURGE_CACHES")) {
    3400               0 :       cachesOK = false;
    3401                 :     }
    3402                 :  
    3403                 :     // Every time a profile is loaded by a build with a different version,
    3404                 :     // it updates the compatibility.ini file saying what version last wrote
    3405                 :     // the fastload caches.  On subsequent launches if the version matches, 
    3406                 :     // there is no need for re-registration.  If the user loads the same
    3407                 :     // profile in different builds the component registry must be
    3408                 :     // re-generated to prevent mysterious component loading failures.
    3409                 :     //
    3410               0 :     if (gSafeMode) {
    3411               0 :       RemoveComponentRegistries(profD, profLD, false);
    3412               0 :       WriteVersion(profD, NS_LITERAL_CSTRING("Safe Mode"), osABI,
    3413               0 :                    dirProvider.GetGREDir(), gAppData->directory);
    3414                 :     }
    3415               0 :     else if (versionOK) {
    3416               0 :       if (!cachesOK) {
    3417                 :         // Remove caches, forcing component re-registration.
    3418                 :         // The new list of additional components directories is derived from
    3419                 :         // information in "extensions.ini".
    3420               0 :         RemoveComponentRegistries(profD, profLD, false);
    3421                 :         
    3422                 :         // Rewrite compatibility.ini to remove the flag
    3423                 :         WriteVersion(profD, version, osABI,
    3424               0 :                      dirProvider.GetGREDir(), gAppData->directory);
    3425                 :       }
    3426                 :       // Nothing need be done for the normal startup case.
    3427                 :     }
    3428                 :     else {
    3429                 :       // Remove caches, forcing component re-registration
    3430                 :       // with the default set of components (this disables any potentially
    3431                 :       // troublesome incompatible XPCOM components). 
    3432               0 :       RemoveComponentRegistries(profD, profLD, true);
    3433                 : 
    3434                 :       // Write out version
    3435                 :       WriteVersion(profD, version, osABI,
    3436               0 :                    dirProvider.GetGREDir(), gAppData->directory);
    3437                 :     }
    3438                 : 
    3439               0 :     if (flagFile) {
    3440               0 :       flagFile->Remove(true);
    3441                 :     }
    3442                 : 
    3443               0 :     bool appInitiatedRestart = false;
    3444                 : 
    3445                 :     NS_TIME_FUNCTION_MARK("Next: ScopedXPCOMStartup");
    3446                 : 
    3447                 :     NS_TIME_FUNCTION_MARK("ScopedXPCOMStartup");
    3448                 : 
    3449                 :     // Allows the user to forcefully bypass the restart process at their
    3450                 :     // own risk. Useful for debugging or for tinderboxes where child 
    3451                 :     // processes can be problematic.
    3452                 :     {
    3453                 :       // Start the real application
    3454               0 :       ScopedXPCOMStartup xpcom;
    3455               0 :       rv = xpcom.Initialize();
    3456                 :       NS_TIME_FUNCTION_MARK("ScopedXPCOMStartup: Initialize");
    3457               0 :       NS_ENSURE_SUCCESS(rv, 1); 
    3458                 : 
    3459                 : 
    3460                 : #ifdef NS_FUNCTION_TIMER
    3461                 :       // initialize some common services, so we don't pay the cost for these at odd times later on;
    3462                 :       // SetWindowCreator -> ChromeRegistry -> IOService -> SocketTransportService -> (nspr wspm init), Prefs
    3463                 :       {
    3464                 :         nsCOMPtr<nsISupports> comp;
    3465                 : 
    3466                 :         comp = do_GetService("@mozilla.org/preferences-service;1");
    3467                 :         NS_TIME_FUNCTION_MARK("Pref Service");
    3468                 : 
    3469                 :         comp = do_GetService("@mozilla.org/network/socket-transport-service;1");
    3470                 :         NS_TIME_FUNCTION_MARK("Socket Transport Service");
    3471                 : 
    3472                 :         comp = do_GetService("@mozilla.org/network/dns-service;1");
    3473                 :         NS_TIME_FUNCTION_MARK("DNS Service");
    3474                 : 
    3475                 :         comp = do_GetService("@mozilla.org/network/io-service;1");
    3476                 :         NS_TIME_FUNCTION_MARK("IO Service");
    3477                 : 
    3478                 :         comp = do_GetService("@mozilla.org/chrome/chrome-registry;1");
    3479                 :         NS_TIME_FUNCTION_MARK("Chrome Registry Service");
    3480                 : 
    3481                 :         comp = do_GetService("@mozilla.org/focus-event-suppressor-service;1");
    3482                 :         NS_TIME_FUNCTION_MARK("Focus Event Suppressor Service");
    3483                 :       }
    3484                 : #endif
    3485                 : 
    3486               0 :       rv = xpcom.SetWindowCreator(nativeApp);
    3487                 :       NS_TIME_FUNCTION_MARK("ScopedXPCOMStartup: SetWindowCreator");
    3488               0 :       NS_ENSURE_SUCCESS(rv, 1);
    3489                 : 
    3490                 :       NS_TIME_FUNCTION_MARK("ScopedXPCOMStartup: Done");
    3491                 : 
    3492                 : #ifdef MOZ_CRASHREPORTER
    3493                 :       // tell the crash reporter to also send the release channel
    3494               0 :       nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &rv);
    3495               0 :       if (NS_SUCCEEDED(rv)) {
    3496               0 :         nsCOMPtr<nsIPrefBranch> defaultPrefBranch;
    3497               0 :         rv = prefs->GetDefaultBranch(nsnull, getter_AddRefs(defaultPrefBranch));
    3498                 : 
    3499               0 :         if (NS_SUCCEEDED(rv)) {
    3500               0 :           nsXPIDLCString sval;
    3501               0 :           rv = defaultPrefBranch->GetCharPref("app.update.channel", getter_Copies(sval));
    3502               0 :           if (NS_SUCCEEDED(rv)) {
    3503               0 :             CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ReleaseChannel"),
    3504               0 :                                                sval);
    3505                 :           }
    3506                 :         }
    3507                 :       }
    3508                 : #endif
    3509                 : 
    3510                 :       NS_TIME_FUNCTION_MARK("Next: AppStartup");
    3511                 : 
    3512                 :       {
    3513               0 :         if (startOffline) {
    3514               0 :           nsCOMPtr<nsIIOService2> io (do_GetService("@mozilla.org/network/io-service;1"));
    3515               0 :           NS_ENSURE_TRUE(io, 1);
    3516               0 :           io->SetManageOfflineStatus(false);
    3517               0 :           io->SetOffline(true);
    3518                 :         }
    3519                 : 
    3520                 :         {
    3521                 :           nsCOMPtr<nsIObserver> startupNotifier
    3522               0 :             (do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID, &rv));
    3523               0 :           NS_ENSURE_SUCCESS(rv, 1);
    3524                 : 
    3525               0 :           startupNotifier->Observe(nsnull, APPSTARTUP_TOPIC, nsnull);
    3526                 :         }
    3527                 : 
    3528                 :         NS_TIME_FUNCTION_MARK("Finished startupNotifier");
    3529                 : 
    3530                 :         nsCOMPtr<nsIAppStartup> appStartup
    3531               0 :           (do_GetService(NS_APPSTARTUP_CONTRACTID));
    3532               0 :         NS_ENSURE_TRUE(appStartup, 1);
    3533                 : 
    3534                 :         NS_TIME_FUNCTION_MARK("Created AppStartup");
    3535                 : 
    3536               0 :         if (gDoMigration) {
    3537               0 :           nsCOMPtr<nsIFile> file;
    3538               0 :           dirProvider.GetAppDir()->Clone(getter_AddRefs(file));
    3539               0 :           file->AppendNative(NS_LITERAL_CSTRING("override.ini"));
    3540               0 :           nsINIParser parser;
    3541               0 :           nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(file));
    3542               0 :           nsresult rv = parser.Init(localFile);
    3543               0 :           if (NS_SUCCEEDED(rv)) {
    3544               0 :             nsCAutoString buf;
    3545               0 :             rv = parser.GetString("XRE", "EnableProfileMigrator", buf);
    3546               0 :             if (NS_SUCCEEDED(rv)) {
    3547               0 :               if (buf[0] == '0' || buf[0] == 'f' || buf[0] == 'F') {
    3548               0 :                 gDoMigration = false;
    3549                 :               }
    3550                 :             }
    3551                 :           }
    3552                 :         }
    3553                 : 
    3554                 :         // Profile Migration
    3555               0 :         if (gAppData->flags & NS_XRE_ENABLE_PROFILE_MIGRATOR && gDoMigration) {
    3556               0 :           gDoMigration = false;
    3557                 :           nsCOMPtr<nsIProfileMigrator> pm
    3558               0 :             (do_CreateInstance(NS_PROFILEMIGRATOR_CONTRACTID));
    3559               0 :           if (pm) {
    3560               0 :             nsCAutoString aKey;
    3561               0 :             if (gDoProfileReset) {
    3562                 :               // Automatically migrate from the current application if we just
    3563                 :               // reset the profile.
    3564               0 :               aKey = MOZ_APP_NAME;
    3565               0 :               pm->Migrate(&dirProvider, aKey);
    3566                 :               // Set the new profile as the default after migration.
    3567               0 :               rv = SetCurrentProfileAsDefault(profileSvc, profD);
    3568               0 :               if (NS_FAILED(rv)) NS_WARNING("Could not set current profile as the default");
    3569                 :             } else {
    3570               0 :               pm->Migrate(&dirProvider, aKey);
    3571                 :             }
    3572                 :           }
    3573                 :         }
    3574                 : 
    3575                 :         NS_TIME_FUNCTION_MARK("Profile migration");
    3576                 : 
    3577               0 :         dirProvider.DoStartup();
    3578                 : 
    3579                 :         NS_TIME_FUNCTION_MARK("dirProvider.DoStartup() (profile-after-change)");
    3580                 : 
    3581               0 :         bool shuttingDown = false;
    3582               0 :         appStartup->GetShuttingDown(&shuttingDown);
    3583                 : 
    3584               0 :         nsCOMPtr<nsICommandLineRunner> cmdLine;
    3585                 : 
    3586               0 :         nsCOMPtr<nsIFile> workingDir;
    3587               0 :         rv = NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR, getter_AddRefs(workingDir));
    3588               0 :         NS_ENSURE_SUCCESS(rv, 1);
    3589                 : 
    3590               0 :         if (!shuttingDown) {
    3591               0 :           cmdLine = do_CreateInstance("@mozilla.org/toolkit/command-line;1");
    3592               0 :           NS_ENSURE_TRUE(cmdLine, 1);
    3593                 : 
    3594               0 :           rv = cmdLine->Init(gArgc, gArgv,
    3595               0 :                              workingDir, nsICommandLine::STATE_INITIAL_LAUNCH);
    3596               0 :           NS_ENSURE_SUCCESS(rv, 1);
    3597                 : 
    3598                 :           /* Special-case services that need early access to the command
    3599                 :              line. */
    3600                 :           nsCOMPtr<nsIObserverService> obsService =
    3601               0 :             mozilla::services::GetObserverService();
    3602               0 :           if (obsService) {
    3603               0 :             obsService->NotifyObservers(cmdLine, "command-line-startup", nsnull);
    3604                 :           }
    3605                 : 
    3606                 :           NS_TIME_FUNCTION_MARK("Early command line init");
    3607                 : 
    3608                 :           NS_TIME_FUNCTION_MARK("Next: prepare for Run");
    3609                 :         }
    3610                 : 
    3611               0 :         SaveStateForAppInitiatedRestart();
    3612                 : 
    3613                 :         // clear out any environment variables which may have been set 
    3614                 :         // during the relaunch process now that we know we won't be relaunching.
    3615               0 :         SaveToEnv("XRE_PROFILE_PATH=");
    3616               0 :         SaveToEnv("XRE_PROFILE_LOCAL_PATH=");
    3617               0 :         SaveToEnv("XRE_PROFILE_NAME=");
    3618               0 :         SaveToEnv("XRE_START_OFFLINE=");
    3619               0 :         SaveToEnv("NO_EM_RESTART=");
    3620               0 :         SaveToEnv("XUL_APP_FILE=");
    3621               0 :         SaveToEnv("XRE_BINARY_PATH=");
    3622                 : 
    3623                 :         NS_TIME_FUNCTION_MARK("env munging");
    3624                 : 
    3625               0 :         if (!shuttingDown) {
    3626                 :           NS_TIME_FUNCTION_MARK("Next: CreateHiddenWindow");
    3627                 : 
    3628               0 :           rv = appStartup->CreateHiddenWindow();
    3629               0 :           NS_ENSURE_SUCCESS(rv, 1);
    3630                 : 
    3631                 : #if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK2)
    3632               0 :           nsGTKToolkit* toolkit = nsGTKToolkit::GetToolkit();
    3633               0 :           if (toolkit && !desktopStartupID.IsEmpty()) {
    3634               0 :             toolkit->SetDesktopStartupID(desktopStartupID);
    3635                 :           }
    3636                 :           // Clear the environment variable so it won't be inherited by
    3637                 :           // child processes and confuse things.
    3638               0 :           g_unsetenv ("DESKTOP_STARTUP_ID");
    3639                 : #endif
    3640                 : 
    3641                 : #ifdef XP_MACOSX
    3642                 :           // Set up ability to respond to system (Apple) events. This must be
    3643                 :           // done before setting up the command line service.
    3644                 :           SetupMacApplicationDelegate();
    3645                 : 
    3646                 :           // we re-initialize the command-line service and do appleevents munging
    3647                 :           // after we are sure that we're not restarting
    3648                 :           cmdLine = do_CreateInstance("@mozilla.org/toolkit/command-line;1");
    3649                 :           NS_ENSURE_TRUE(cmdLine, 1);
    3650                 : 
    3651                 :           CommandLineServiceMac::SetupMacCommandLine(gArgc, gArgv, false);
    3652                 : 
    3653                 :           rv = cmdLine->Init(gArgc, gArgv,
    3654                 :                              workingDir, nsICommandLine::STATE_INITIAL_LAUNCH);
    3655                 :           NS_ENSURE_SUCCESS(rv, 1);
    3656                 : #endif
    3657                 : 
    3658                 :           nsCOMPtr<nsIObserverService> obsService =
    3659               0 :             mozilla::services::GetObserverService();
    3660               0 :           if (obsService)
    3661               0 :             obsService->NotifyObservers(nsnull, "final-ui-startup", nsnull);
    3662                 : 
    3663                 :           NS_TIME_FUNCTION_MARK("final-ui-startup done");
    3664                 : 
    3665               0 :           appStartup->GetShuttingDown(&shuttingDown);
    3666                 :         }
    3667                 : 
    3668               0 :         if (!shuttingDown) {
    3669               0 :           rv = cmdLine->Run();
    3670               0 :           NS_ENSURE_SUCCESS_LOG(rv, 1);
    3671                 : 
    3672               0 :           appStartup->GetShuttingDown(&shuttingDown);
    3673                 :         }
    3674                 : 
    3675                 : #ifdef MOZ_ENABLE_XREMOTE
    3676               0 :         nsCOMPtr<nsIRemoteService> remoteService;
    3677                 : #endif /* MOZ_ENABLE_XREMOTE */
    3678               0 :         if (!shuttingDown) {
    3679                 : #ifdef MOZ_ENABLE_XREMOTE
    3680                 :           // if we have X remote support, start listening for requests on the
    3681                 :           // proxy window.
    3682               0 :           if (!disableRemote)
    3683               0 :             remoteService = do_GetService("@mozilla.org/toolkit/remote-service;1");
    3684               0 :           if (remoteService)
    3685               0 :             remoteService->Startup(gAppData->name,
    3686               0 :                                    PromiseFlatCString(profileName).get());
    3687                 : #endif /* MOZ_ENABLE_XREMOTE */
    3688                 : 
    3689               0 :           nativeApp->Enable();
    3690                 :         }
    3691                 : 
    3692                 : #ifdef MOZ_INSTRUMENT_EVENT_LOOP
    3693               0 :         if (PR_GetEnv("MOZ_INSTRUMENT_EVENT_LOOP") || SAMPLER_IS_ACTIVE()) {
    3694               0 :           mozilla::InitEventTracing();
    3695                 :         }
    3696                 : #endif /* MOZ_INSTRUMENT_EVENT_LOOP */
    3697                 : 
    3698                 :         NS_TIME_FUNCTION_MARK("Next: Run");
    3699                 : 
    3700                 :         NS_TIME_FUNCTION_MARK("appStartup->Run");
    3701                 : 
    3702                 :         {
    3703               0 :           rv = appStartup->Run();
    3704               0 :           if (NS_FAILED(rv)) {
    3705               0 :             NS_ERROR("failed to run appstartup");
    3706               0 :             gLogConsoleErrors = true;
    3707                 :           }
    3708                 :         }
    3709                 : 
    3710                 :         NS_TIME_FUNCTION_MARK("Next: Finish");
    3711                 : 
    3712                 :         NS_TIME_FUNCTION_MARK("appStartup->Run done");
    3713                 : 
    3714                 : #ifdef MOZ_INSTRUMENT_EVENT_LOOP
    3715               0 :         mozilla::ShutdownEventTracing();
    3716                 : #endif
    3717                 : 
    3718                 :         // Check for an application initiated restart.  This is one that
    3719                 :         // corresponds to nsIAppStartup.quit(eRestart)
    3720               0 :         if (rv == NS_SUCCESS_RESTART_APP)
    3721               0 :           appInitiatedRestart = true;
    3722                 : 
    3723               0 :         if (!shuttingDown) {
    3724                 : #ifdef MOZ_ENABLE_XREMOTE
    3725                 :           // shut down the x remote proxy window
    3726               0 :           if (remoteService)
    3727               0 :             remoteService->Shutdown();
    3728                 : #endif /* MOZ_ENABLE_XREMOTE */
    3729                 :         }
    3730                 : 
    3731                 :       }
    3732                 :     }
    3733                 : 
    3734                 :     // unlock the profile after ScopedXPCOMStartup object (xpcom) 
    3735                 :     // has gone out of scope.  see bug #386739 for more details
    3736               0 :     profileLock->Unlock();
    3737               0 :     gProfileLock = nsnull;
    3738                 : 
    3739                 : #if defined(MOZ_WIDGET_QT)
    3740                 :     nsQAppInstance::Release();
    3741                 : #endif
    3742                 : 
    3743                 :     // Restart the app after XPCOM has been shut down cleanly. 
    3744               0 :     if (appInitiatedRestart) {
    3745               0 :       RestoreStateForAppInitiatedRestart();
    3746                 : 
    3747                 :       // Ensure that these environment variables are set:
    3748               0 :       SaveFileToEnvIfUnset("XRE_PROFILE_PATH", profD);
    3749               0 :       SaveFileToEnvIfUnset("XRE_PROFILE_LOCAL_PATH", profLD);
    3750               0 :       SaveWordToEnvIfUnset("XRE_PROFILE_NAME", profileName);
    3751                 : 
    3752                 : #ifdef MOZ_WIDGET_GTK2
    3753               0 :       MOZ_gdk_display_close(display);
    3754                 : #endif
    3755                 : 
    3756               0 :       rv = LaunchChild(nativeApp, true);
    3757                 : 
    3758                 : #ifdef MOZ_CRASHREPORTER
    3759               0 :       if (appData.flags & NS_XRE_ENABLE_CRASH_REPORTER)
    3760               0 :         CrashReporter::UnsetExceptionHandler();
    3761                 : #endif
    3762                 : 
    3763               0 :       return rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ? 0 : 1;
    3764                 :     }
    3765                 : 
    3766                 : #ifdef MOZ_WIDGET_GTK2
    3767                 :     // gdk_display_close also calls gdk_display_manager_set_default_display
    3768                 :     // appropriately when necessary.
    3769               0 :     MOZ_gdk_display_close(display);
    3770                 : #endif
    3771                 :   }
    3772                 : 
    3773                 : #ifdef MOZ_CRASHREPORTER
    3774               0 :   if (appData.flags & NS_XRE_ENABLE_CRASH_REPORTER)
    3775               0 :       CrashReporter::UnsetExceptionHandler();
    3776                 : #endif
    3777                 : 
    3778               0 :   XRE_DeinitCommandLine();
    3779                 : 
    3780               0 :   return NS_FAILED(rv) ? 1 : 0;
    3781                 : }
    3782                 : 
    3783                 : nsresult
    3784              24 : XRE_InitCommandLine(int aArgc, char* aArgv[])
    3785                 : {
    3786              24 :   nsresult rv = NS_OK;
    3787                 : 
    3788                 : #if defined(OS_WIN)
    3789                 :   CommandLine::Init(aArgc, aArgv);
    3790                 : #else
    3791                 : 
    3792                 :   // these leak on error, but that's OK: we'll just exit()
    3793              48 :   char** canonArgs = new char*[aArgc];
    3794                 : 
    3795                 :   // get the canonical version of the binary's path
    3796              48 :   nsCOMPtr<nsILocalFile> binFile;
    3797              24 :   rv = XRE_GetBinaryPath(aArgv[0], getter_AddRefs(binFile));
    3798              24 :   if (NS_FAILED(rv))
    3799               0 :     return NS_ERROR_FAILURE;
    3800                 : 
    3801              48 :   nsCAutoString canonBinPath;
    3802              24 :   rv = binFile->GetNativePath(canonBinPath);
    3803              24 :   if (NS_FAILED(rv))
    3804               0 :     return NS_ERROR_FAILURE;
    3805                 : 
    3806              24 :   canonArgs[0] = strdup(canonBinPath.get());
    3807                 : 
    3808              93 :   for (int i = 1; i < aArgc; ++i) {
    3809              69 :     if (aArgv[i]) {
    3810              69 :       canonArgs[i] = strdup(aArgv[i]);
    3811                 :     }
    3812                 :   }
    3813                 :  
    3814              24 :   NS_ASSERTION(!CommandLine::IsInitialized(), "Bad news!");
    3815              24 :   CommandLine::Init(aArgc, canonArgs);
    3816                 : 
    3817             117 :   for (int i = 0; i < aArgc; ++i)
    3818              93 :       free(canonArgs[i]);
    3819              24 :   delete[] canonArgs;
    3820                 : #endif
    3821                 : 
    3822              24 :   const char *path = nsnull;
    3823              24 :   ArgResult ar = CheckArg("greomni", false, &path);
    3824              24 :   if (ar == ARG_BAD) {
    3825               0 :     PR_fprintf(PR_STDERR, "Error: argument -greomni requires a path argument\n");
    3826               0 :     return NS_ERROR_FAILURE;
    3827                 :   }
    3828                 : 
    3829              24 :   if (!path)
    3830              24 :     return rv;
    3831                 : 
    3832               0 :   nsCOMPtr<nsILocalFile> greOmni;
    3833               0 :   rv = XRE_GetFileFromPath(path, getter_AddRefs(greOmni));
    3834               0 :   if (NS_FAILED(rv)) {
    3835               0 :     PR_fprintf(PR_STDERR, "Error: argument -greomni requires a valid path\n");
    3836               0 :     return rv;
    3837                 :   }
    3838                 : 
    3839               0 :   ar = CheckArg("appomni", false, &path);
    3840               0 :   if (ar == ARG_BAD) {
    3841               0 :     PR_fprintf(PR_STDERR, "Error: argument -appomni requires a path argument\n");
    3842               0 :     return NS_ERROR_FAILURE;
    3843                 :   }
    3844                 : 
    3845               0 :   nsCOMPtr<nsILocalFile> appOmni;
    3846               0 :   if (path) {
    3847               0 :       rv = XRE_GetFileFromPath(path, getter_AddRefs(appOmni));
    3848               0 :       if (NS_FAILED(rv)) {
    3849               0 :         PR_fprintf(PR_STDERR, "Error: argument -appomni requires a valid path\n");
    3850               0 :         return rv;
    3851                 :       }
    3852                 :   }
    3853                 : 
    3854               0 :   mozilla::Omnijar::Init(greOmni, appOmni);
    3855               0 :   return rv;
    3856                 : }
    3857                 : 
    3858                 : nsresult
    3859               0 : XRE_DeinitCommandLine()
    3860                 : {
    3861               0 :   nsresult rv = NS_OK;
    3862                 : 
    3863               0 :   CommandLine::Terminate();
    3864                 : 
    3865               0 :   return rv;
    3866                 : }
    3867                 : 
    3868                 : GeckoProcessType
    3869          313843 : XRE_GetProcessType()
    3870                 : {
    3871          313843 :   return mozilla::startup::sChildProcessType;
    3872                 : }
    3873                 : 
    3874                 : void
    3875              24 : SetupErrorHandling(const char* progname)
    3876                 : {
    3877                 : #ifdef XP_WIN
    3878                 :   /* On Windows XPSP3 and Windows Vista if DEP is configured off-by-default
    3879                 :      we still want DEP protection: enable it explicitly and programmatically.
    3880                 :      
    3881                 :      This function is not available on WinXPSP2 so we dynamically load it.
    3882                 :   */
    3883                 : 
    3884                 :   HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll");
    3885                 :   SetProcessDEPPolicyFunc _SetProcessDEPPolicy =
    3886                 :     (SetProcessDEPPolicyFunc) GetProcAddress(kernel32, "SetProcessDEPPolicy");
    3887                 :   if (_SetProcessDEPPolicy)
    3888                 :     _SetProcessDEPPolicy(PROCESS_DEP_ENABLE);
    3889                 : #endif
    3890                 : 
    3891                 : #ifdef XP_WIN32
    3892                 :   // Suppress the "DLL Foo could not be found" dialog, such that if dependent
    3893                 :   // libraries (such as GDI+) are not preset, we gracefully fail to load those
    3894                 :   // XPCOM components, instead of being ungraceful.
    3895                 :   UINT realMode = SetErrorMode(0);
    3896                 :   realMode |= SEM_FAILCRITICALERRORS;
    3897                 :   // If XRE_NO_WINDOWS_CRASH_DIALOG is set, suppress displaying the "This
    3898                 :   // application has crashed" dialog box.  This is mainly useful for
    3899                 :   // automated testing environments, e.g. tinderbox, where there's no need
    3900                 :   // for a dozen of the dialog boxes to litter the console
    3901                 :   if (getenv("XRE_NO_WINDOWS_CRASH_DIALOG"))
    3902                 :     realMode |= SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX;
    3903                 : 
    3904                 :   SetErrorMode(realMode);
    3905                 : 
    3906                 : #endif
    3907                 : 
    3908                 : #ifndef XP_OS2
    3909              24 :   InstallSignalHandlers(progname);
    3910                 : #endif
    3911                 : 
    3912                 :   // Unbuffer stdout, needed for tinderbox tests.
    3913              24 :   setbuf(stdout, 0);
    3914                 : 
    3915                 : #if defined(FREEBSD)
    3916                 :   // Disable all SIGFPE's on FreeBSD, as it has non-IEEE-conformant fp
    3917                 :   // trap behavior that trips up on floating-point tests performed by
    3918                 :   // the JS engine.  See bugzilla bug 9967 details.
    3919                 :   fpsetmask(0);
    3920                 : #endif
    3921            4416 : }
    3922                 : 

Generated by: LCOV version 1.7