LCOV - code coverage report
Current view: directory - toolkit/components/startup - nsAppStartup.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 328 166 50.6 %
Date: 2012-06-02 Functions: 30 18 60.0 %

       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. This file was split
      16                 :  * from xpfe/appshell/src/nsAppShellService.cpp
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Pierre Phaneuf <pp@ludusdesign.com>
      25                 :  *   Robert O'Callahan <roc+moz@cs.cmu.edu>
      26                 :  *   Benjamin Smedberg <bsmedberg@covad.net>
      27                 :  *   Daniel Brooks <db48x@db48x.net>
      28                 :  *   Taras Glek <tglek@mozilla.com>
      29                 :  *   Landry Breuil <landry@openbsd.org>
      30                 :  *   David Rajchenbach-Teller <dteller@mozilla.com>
      31                 :  *
      32                 :  * Alternatively, the contents of this file may be used under the terms of
      33                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      34                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      35                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      36                 :  * of those above. If you wish to allow use of your version of this file only
      37                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      38                 :  * use your version of this file under the terms of the MPL, indicate your
      39                 :  * decision by deleting the provisions above and replace them with the notice
      40                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      41                 :  * the provisions above, a recipient may use your version of this file under
      42                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      43                 :  *
      44                 :  * ***** END LICENSE BLOCK ***** */
      45                 : 
      46                 : #include "nsAppStartup.h"
      47                 : 
      48                 : #include "nsIAppShellService.h"
      49                 : #include "nsPIDOMWindow.h"
      50                 : #include "nsIInterfaceRequestor.h"
      51                 : #include "nsILocalFile.h"
      52                 : #include "nsIObserverService.h"
      53                 : #include "nsIPrefBranch.h"
      54                 : #include "nsIPrefService.h"
      55                 : #include "nsIProfileChangeStatus.h"
      56                 : #include "nsIPromptService.h"
      57                 : #include "nsIStringBundle.h"
      58                 : #include "nsISupportsPrimitives.h"
      59                 : #include "nsIWebBrowserChrome.h"
      60                 : #include "nsIWindowMediator.h"
      61                 : #include "nsIWindowWatcher.h"
      62                 : #include "nsIXULRuntime.h"
      63                 : #include "nsIXULWindow.h"
      64                 : #include "nsNativeCharsetUtils.h"
      65                 : #include "nsThreadUtils.h"
      66                 : #include "nsAutoPtr.h"
      67                 : #include "nsStringGlue.h"
      68                 : #include "mozilla/Preferences.h"
      69                 : 
      70                 : #include "prprf.h"
      71                 : #include "nsCRT.h"
      72                 : #include "nsIInterfaceRequestorUtils.h"
      73                 : #include "nsWidgetsCID.h"
      74                 : #include "nsAppShellCID.h"
      75                 : #include "nsXPCOMCIDInternal.h"
      76                 : #include "mozilla/Services.h"
      77                 : #include "mozilla/FunctionTimer.h"
      78                 : #include "nsIXPConnect.h"
      79                 : #include "jsapi.h"
      80                 : #include "prenv.h"
      81                 : 
      82                 : #if defined(XP_WIN)
      83                 : #include <windows.h>
      84                 : // windows.h can go to hell 
      85                 : #undef GetStartupInfo
      86                 : #elif defined(XP_UNIX)
      87                 : #include <unistd.h>
      88                 : #include <sys/syscall.h>
      89                 : #endif
      90                 : 
      91                 : #ifdef XP_MACOSX
      92                 : #include <sys/sysctl.h>
      93                 : #endif
      94                 : 
      95                 : #ifdef __OpenBSD__
      96                 : #include <sys/param.h>
      97                 : #include <sys/sysctl.h>
      98                 : #endif
      99                 : 
     100                 : #include "mozilla/Telemetry.h"
     101                 : #include "mozilla/StartupTimeline.h"
     102                 : 
     103                 : static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
     104                 : 
     105                 : #define kPrefLastSuccess "toolkit.startup.last_success"
     106                 : #define kPrefMaxResumedCrashes "toolkit.startup.max_resumed_crashes"
     107                 : #define kPrefRecentCrashes "toolkit.startup.recent_crashes"
     108                 : 
     109                 : #if defined(XP_WIN)
     110                 : #include "mozilla/perfprobe.h"
     111                 : /**
     112                 :  * Events sent to the system for profiling purposes
     113                 :  */
     114                 : //Keep them syncronized with the .mof file
     115                 : 
     116                 : //Process-wide GUID, used by the OS to differentiate sources
     117                 : // {509962E0-406B-46F4-99BA-5A009F8D2225}
     118                 : //Keep it synchronized with the .mof file
     119                 : #define NS_APPLICATION_TRACING_CID \
     120                 :   { 0x509962E0, 0x406B, 0x46F4, \
     121                 :   { 0x99, 0xBA, 0x5A, 0x00, 0x9F, 0x8D, 0x22, 0x25} }
     122                 : 
     123                 : //Event-specific GUIDs, used by the OS to differentiate events
     124                 : // {A3DA04E0-57D7-482A-A1C1-61DA5F95BACB}
     125                 : #define NS_PLACES_INIT_COMPLETE_EVENT_CID \
     126                 :   { 0xA3DA04E0, 0x57D7, 0x482A, \
     127                 :   { 0xA1, 0xC1, 0x61, 0xDA, 0x5F, 0x95, 0xBA, 0xCB} }
     128                 : // {917B96B1-ECAD-4DAB-A760-8D49027748AE}
     129                 : #define NS_SESSION_STORE_WINDOW_RESTORED_EVENT_CID \
     130                 :   { 0x917B96B1, 0xECAD, 0x4DAB, \
     131                 :   { 0xA7, 0x60, 0x8D, 0x49, 0x02, 0x77, 0x48, 0xAE} }
     132                 : 
     133                 : static NS_DEFINE_CID(kApplicationTracingCID,
     134                 :   NS_APPLICATION_TRACING_CID);
     135                 : static NS_DEFINE_CID(kPlacesInitCompleteCID,
     136                 :   NS_PLACES_INIT_COMPLETE_EVENT_CID);
     137                 : static NS_DEFINE_CID(kSessionStoreWindowRestoredCID,
     138                 :   NS_SESSION_STORE_WINDOW_RESTORED_EVENT_CID);
     139                 : #endif //defined(XP_WIN)
     140                 : 
     141                 : using namespace mozilla;
     142                 : 
     143                 : PRUint32 gRestartMode = 0;
     144                 : 
     145               0 : class nsAppExitEvent : public nsRunnable {
     146                 : private:
     147                 :   nsRefPtr<nsAppStartup> mService;
     148                 : 
     149                 : public:
     150               0 :   nsAppExitEvent(nsAppStartup *service) : mService(service) {}
     151                 : 
     152               0 :   NS_IMETHOD Run() {
     153                 :     // Tell the appshell to exit
     154               0 :     mService->mAppShell->Exit();
     155                 : 
     156                 :     // We're done "shutting down".
     157               0 :     mService->mShuttingDown = false;
     158               0 :     mService->mRunning = false;
     159               0 :     return NS_OK;
     160                 :   }
     161                 : };
     162                 : 
     163                 : //
     164                 : // nsAppStartup
     165                 : //
     166                 : 
     167              16 : nsAppStartup::nsAppStartup() :
     168                 :   mConsiderQuitStopper(0),
     169                 :   mRunning(false),
     170                 :   mShuttingDown(false),
     171                 :   mAttemptingQuit(false),
     172                 :   mRestart(false),
     173                 :   mInterrupted(false),
     174                 :   mIsSafeModeNecessary(false),
     175              16 :   mStartupCrashTrackingEnded(false)
     176              16 : { }
     177                 : 
     178                 : 
     179                 : nsresult
     180              16 : nsAppStartup::Init()
     181                 : {
     182                 :   NS_TIME_FUNCTION;
     183                 :   nsresult rv;
     184                 : 
     185                 :   // Create widget application shell
     186              16 :   mAppShell = do_GetService(kAppShellCID, &rv);
     187              16 :   NS_ENSURE_SUCCESS(rv, rv);
     188                 : 
     189                 :   NS_TIME_FUNCTION_MARK("Got AppShell service");
     190                 : 
     191                 :   nsCOMPtr<nsIObserverService> os =
     192              32 :     mozilla::services::GetObserverService();
     193              16 :   if (!os)
     194               0 :     return NS_ERROR_FAILURE;
     195                 : 
     196                 :   NS_TIME_FUNCTION_MARK("Got Observer service");
     197                 : 
     198              16 :   os->AddObserver(this, "quit-application-forced", true);
     199              16 :   os->AddObserver(this, "sessionstore-windows-restored", true);
     200              16 :   os->AddObserver(this, "profile-change-teardown", true);
     201              16 :   os->AddObserver(this, "xul-window-registered", true);
     202              16 :   os->AddObserver(this, "xul-window-destroyed", true);
     203                 : 
     204                 : #if defined(XP_WIN)
     205                 :   os->AddObserver(this, "places-init-complete", true);
     206                 :   // This last event is only interesting to us for xperf-based measures
     207                 : 
     208                 :   // Initialize interaction with profiler
     209                 :   mProbesManager =
     210                 :     new ProbeManager(
     211                 :                      kApplicationTracingCID,
     212                 :                      NS_LITERAL_CSTRING("Application startup probe"));
     213                 :   // Note: The operation is meant mostly for in-house profiling.
     214                 :   // Therefore, we do not warn if probes manager cannot be initialized
     215                 : 
     216                 :   if (mProbesManager) {
     217                 :     mPlacesInitCompleteProbe =
     218                 :       mProbesManager->
     219                 :       GetProbe(kPlacesInitCompleteCID,
     220                 :                NS_LITERAL_CSTRING("places-init-complete"));
     221                 :     NS_WARN_IF_FALSE(mPlacesInitCompleteProbe,
     222                 :                      "Cannot initialize probe 'places-init-complete'");
     223                 : 
     224                 :     mSessionWindowRestoredProbe =
     225                 :       mProbesManager->
     226                 :       GetProbe(kSessionStoreWindowRestoredCID,
     227                 :                NS_LITERAL_CSTRING("sessionstore-windows-restored"));
     228                 :     NS_WARN_IF_FALSE(mSessionWindowRestoredProbe,
     229                 :                      "Cannot initialize probe 'sessionstore-windows-restored'");
     230                 : 
     231                 :     rv = mProbesManager->StartSession();
     232                 :     NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
     233                 :                      "Cannot initialize system probe manager");
     234                 :   }
     235                 : #endif //defined(XP_WIN)
     236                 : 
     237              16 :   return NS_OK;
     238                 : }
     239                 : 
     240                 : 
     241                 : //
     242                 : // nsAppStartup->nsISupports
     243                 : //
     244                 : 
     245             758 : NS_IMPL_THREADSAFE_ISUPPORTS5(nsAppStartup,
     246                 :                               nsIAppStartup,
     247                 :                               nsIWindowCreator,
     248                 :                               nsIWindowCreator2,
     249                 :                               nsIObserver,
     250                 :                               nsISupportsWeakReference)
     251                 : 
     252                 : 
     253                 : //
     254                 : // nsAppStartup->nsIAppStartup
     255                 : //
     256                 : 
     257                 : NS_IMETHODIMP
     258               0 : nsAppStartup::CreateHiddenWindow()
     259                 : {
     260                 :   nsCOMPtr<nsIAppShellService> appShellService
     261               0 :     (do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
     262               0 :   NS_ENSURE_TRUE(appShellService, NS_ERROR_FAILURE);
     263                 : 
     264               0 :   return appShellService->CreateHiddenWindow();
     265                 : }
     266                 : 
     267                 : 
     268                 : NS_IMETHODIMP
     269               0 : nsAppStartup::DestroyHiddenWindow()
     270                 : {
     271                 :   nsCOMPtr<nsIAppShellService> appShellService
     272               0 :     (do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
     273               0 :   NS_ENSURE_TRUE(appShellService, NS_ERROR_FAILURE);
     274                 : 
     275               0 :   return appShellService->DestroyHiddenWindow();
     276                 : }
     277                 : 
     278                 : NS_IMETHODIMP
     279               0 : nsAppStartup::Run(void)
     280                 : {
     281               0 :   NS_ASSERTION(!mRunning, "Reentrant appstartup->Run()");
     282                 : 
     283                 :   // If we have no windows open and no explicit calls to
     284                 :   // enterLastWindowClosingSurvivalArea, or somebody has explicitly called
     285                 :   // quit, don't bother running the event loop which would probably leave us
     286                 :   // with a zombie process.
     287                 : 
     288               0 :   if (!mShuttingDown && mConsiderQuitStopper != 0) {
     289                 : #ifdef XP_MACOSX
     290                 :     EnterLastWindowClosingSurvivalArea();
     291                 : #endif
     292                 : 
     293               0 :     mRunning = true;
     294                 : 
     295               0 :     nsresult rv = mAppShell->Run();
     296               0 :     if (NS_FAILED(rv))
     297               0 :       return rv;
     298                 :   }
     299                 : 
     300               0 :   return mRestart ? NS_SUCCESS_RESTART_APP : NS_OK;
     301                 : }
     302                 : 
     303                 : 
     304                 : NS_IMETHODIMP
     305               0 : nsAppStartup::Quit(PRUint32 aMode)
     306                 : {
     307               0 :   PRUint32 ferocity = (aMode & 0xF);
     308                 : 
     309                 :   // Quit the application. We will asynchronously call the appshell's
     310                 :   // Exit() method via nsAppExitEvent to allow one last pass
     311                 :   // through any events in the queue. This guarantees a tidy cleanup.
     312               0 :   nsresult rv = NS_OK;
     313               0 :   bool postedExitEvent = false;
     314                 : 
     315               0 :   if (mShuttingDown)
     316               0 :     return NS_OK;
     317                 : 
     318                 :   // If we're considering quitting, we will only do so if:
     319               0 :   if (ferocity == eConsiderQuit) {
     320               0 :     if (mConsiderQuitStopper == 0) {
     321                 :       // there are no windows...
     322               0 :       ferocity = eAttemptQuit;
     323                 :     }
     324                 : #ifdef XP_MACOSX
     325                 :     else if (mConsiderQuitStopper == 1) {
     326                 :       // ... or there is only a hiddenWindow left, and it's useless:
     327                 :       nsCOMPtr<nsIAppShellService> appShell
     328                 :         (do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
     329                 : 
     330                 :       // Failure shouldn't be fatal, but will abort quit attempt:
     331                 :       if (!appShell)
     332                 :         return NS_OK;
     333                 : 
     334                 :       bool usefulHiddenWindow;
     335                 :       appShell->GetApplicationProvidedHiddenWindow(&usefulHiddenWindow);
     336                 :       nsCOMPtr<nsIXULWindow> hiddenWindow;
     337                 :       appShell->GetHiddenWindow(getter_AddRefs(hiddenWindow));
     338                 :       // If the one window is useful, we won't quit:
     339                 :       if (!hiddenWindow || usefulHiddenWindow)
     340                 :         return NS_OK;
     341                 : 
     342                 :       ferocity = eAttemptQuit;
     343                 :     }
     344                 : #endif
     345                 :   }
     346                 : 
     347               0 :   nsCOMPtr<nsIObserverService> obsService;
     348               0 :   if (ferocity == eAttemptQuit || ferocity == eForceQuit) {
     349                 : 
     350               0 :     nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
     351               0 :     nsCOMPtr<nsIWindowMediator> mediator (do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
     352               0 :     if (mediator) {
     353               0 :       mediator->GetEnumerator(nsnull, getter_AddRefs(windowEnumerator));
     354               0 :       if (windowEnumerator) {
     355                 :         bool more;
     356               0 :         while (windowEnumerator->HasMoreElements(&more), more) {
     357               0 :           nsCOMPtr<nsISupports> window;
     358               0 :           windowEnumerator->GetNext(getter_AddRefs(window));
     359               0 :           nsCOMPtr<nsPIDOMWindow> domWindow(do_QueryInterface(window));
     360               0 :           if (domWindow) {
     361               0 :             if (!domWindow->CanClose())
     362               0 :               return NS_OK;
     363                 :           }
     364                 :         }
     365                 :       }
     366                 :     }
     367                 : 
     368               0 :     mShuttingDown = true;
     369               0 :     if (!mRestart) {
     370               0 :       mRestart = (aMode & eRestart) != 0;
     371               0 :       gRestartMode = (aMode & 0xF0);
     372                 :     }
     373                 : 
     374               0 :     if (mRestart) {
     375                 :       // Firefox-restarts reuse the process. Process start-time isn't a useful indicator of startup time
     376               0 :       PR_SetEnv(PR_smprintf("MOZ_APP_RESTART=%lld", (PRInt64) PR_Now() / PR_USEC_PER_MSEC));
     377                 :     }
     378                 : 
     379               0 :     obsService = mozilla::services::GetObserverService();
     380                 : 
     381               0 :     if (!mAttemptingQuit) {
     382               0 :       mAttemptingQuit = true;
     383                 : #ifdef XP_MACOSX
     384                 :       // now even the Mac wants to quit when the last window is closed
     385                 :       ExitLastWindowClosingSurvivalArea();
     386                 : #endif
     387               0 :       if (obsService)
     388               0 :         obsService->NotifyObservers(nsnull, "quit-application-granted", nsnull);
     389                 :     }
     390                 : 
     391                 :     /* Enumerate through each open window and close it. It's important to do
     392                 :        this before we forcequit because this can control whether we really quit
     393                 :        at all. e.g. if one of these windows has an unload handler that
     394                 :        opens a new window. Ugh. I know. */
     395               0 :     CloseAllWindows();
     396                 : 
     397               0 :     if (mediator) {
     398               0 :       if (ferocity == eAttemptQuit) {
     399               0 :         ferocity = eForceQuit; // assume success
     400                 : 
     401                 :         /* Were we able to immediately close all windows? if not, eAttemptQuit
     402                 :            failed. This could happen for a variety of reasons; in fact it's
     403                 :            very likely. Perhaps we're being called from JS and the window->Close
     404                 :            method hasn't had a chance to wrap itself up yet. So give up.
     405                 :            We'll return (with eConsiderQuit) as the remaining windows are
     406                 :            closed. */
     407               0 :         mediator->GetEnumerator(nsnull, getter_AddRefs(windowEnumerator));
     408               0 :         if (windowEnumerator) {
     409                 :           bool more;
     410               0 :           while (windowEnumerator->HasMoreElements(&more), more) {
     411                 :             /* we can't quit immediately. we'll try again as the last window
     412                 :                finally closes. */
     413               0 :             ferocity = eAttemptQuit;
     414               0 :             nsCOMPtr<nsISupports> window;
     415               0 :             windowEnumerator->GetNext(getter_AddRefs(window));
     416               0 :             nsCOMPtr<nsIDOMWindow> domWindow = do_QueryInterface(window);
     417               0 :             if (domWindow) {
     418               0 :               bool closed = false;
     419               0 :               domWindow->GetClosed(&closed);
     420               0 :               if (!closed) {
     421               0 :                 rv = NS_ERROR_FAILURE;
     422                 :                 break;
     423                 :               }
     424                 :             }
     425                 :           }
     426                 :         }
     427                 :       }
     428                 :     }
     429                 :   }
     430                 : 
     431               0 :   if (ferocity == eForceQuit) {
     432                 :     // do it!
     433                 : 
     434                 :     // No chance of the shutdown being cancelled from here on; tell people
     435                 :     // we're shutting down for sure while all services are still available.
     436               0 :     if (obsService) {
     437               0 :       NS_NAMED_LITERAL_STRING(shutdownStr, "shutdown");
     438               0 :       NS_NAMED_LITERAL_STRING(restartStr, "restart");
     439               0 :       obsService->NotifyObservers(nsnull, "quit-application",
     440               0 :         mRestart ? restartStr.get() : shutdownStr.get());
     441                 :     }
     442                 : 
     443               0 :     if (!mRunning) {
     444               0 :       postedExitEvent = true;
     445                 :     }
     446                 :     else {
     447                 :       // no matter what, make sure we send the exit event.  If
     448                 :       // worst comes to worst, we'll do a leaky shutdown but we WILL
     449                 :       // shut down. Well, assuming that all *this* stuff works ;-).
     450               0 :       nsCOMPtr<nsIRunnable> event = new nsAppExitEvent(this);
     451               0 :       rv = NS_DispatchToCurrentThread(event);
     452               0 :       if (NS_SUCCEEDED(rv)) {
     453               0 :         postedExitEvent = true;
     454                 :       }
     455                 :       else {
     456               0 :         NS_WARNING("failed to dispatch nsAppExitEvent");
     457                 :       }
     458                 :     }
     459                 :   }
     460                 : 
     461                 :   // turn off the reentrancy check flag, but not if we have
     462                 :   // more asynchronous work to do still.
     463               0 :   if (!postedExitEvent)
     464               0 :     mShuttingDown = false;
     465               0 :   return rv;
     466                 : }
     467                 : 
     468                 : 
     469                 : void
     470              15 : nsAppStartup::CloseAllWindows()
     471                 : {
     472                 :   nsCOMPtr<nsIWindowMediator> mediator
     473              30 :     (do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
     474                 : 
     475              30 :   nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
     476                 : 
     477              15 :   mediator->GetEnumerator(nsnull, getter_AddRefs(windowEnumerator));
     478                 : 
     479              15 :   if (!windowEnumerator)
     480                 :     return;
     481                 : 
     482                 :   bool more;
     483              30 :   while (NS_SUCCEEDED(windowEnumerator->HasMoreElements(&more)) && more) {
     484               0 :     nsCOMPtr<nsISupports> isupports;
     485               0 :     if (NS_FAILED(windowEnumerator->GetNext(getter_AddRefs(isupports))))
     486                 :       break;
     487                 : 
     488               0 :     nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(isupports);
     489               0 :     NS_ASSERTION(window, "not an nsPIDOMWindow");
     490               0 :     if (window)
     491               0 :       window->ForceClose();
     492                 :   }
     493                 : }
     494                 : 
     495                 : NS_IMETHODIMP
     496              15 : nsAppStartup::EnterLastWindowClosingSurvivalArea(void)
     497                 : {
     498              15 :   ++mConsiderQuitStopper;
     499              15 :   return NS_OK;
     500                 : }
     501                 : 
     502                 : 
     503                 : NS_IMETHODIMP
     504              15 : nsAppStartup::ExitLastWindowClosingSurvivalArea(void)
     505                 : {
     506              15 :   NS_ASSERTION(mConsiderQuitStopper > 0, "consider quit stopper out of bounds");
     507              15 :   --mConsiderQuitStopper;
     508                 : 
     509              15 :   if (mRunning)
     510               0 :     Quit(eConsiderQuit);
     511                 : 
     512              15 :   return NS_OK;
     513                 : }
     514                 : 
     515                 : //
     516                 : // nsAppStartup->nsIAppStartup2
     517                 : //
     518                 : 
     519                 : NS_IMETHODIMP
     520               0 : nsAppStartup::GetShuttingDown(bool *aResult)
     521                 : {
     522               0 :   *aResult = mShuttingDown;
     523               0 :   return NS_OK;
     524                 : }
     525                 : 
     526                 : NS_IMETHODIMP
     527              17 : nsAppStartup::SetInterrupted(bool aInterrupted)
     528                 : {
     529              17 :   mInterrupted = aInterrupted;
     530              17 :   return NS_OK;
     531                 : }
     532                 : 
     533                 : NS_IMETHODIMP
     534              13 : nsAppStartup::GetInterrupted(bool *aInterrupted)
     535                 : {
     536              13 :   *aInterrupted = mInterrupted;
     537              13 :   return NS_OK;
     538                 : }
     539                 : 
     540                 : //
     541                 : // nsAppStartup->nsIWindowCreator
     542                 : //
     543                 : 
     544                 : NS_IMETHODIMP
     545               0 : nsAppStartup::CreateChromeWindow(nsIWebBrowserChrome *aParent,
     546                 :                                  PRUint32 aChromeFlags,
     547                 :                                  nsIWebBrowserChrome **_retval)
     548                 : {
     549                 :   bool cancel;
     550               0 :   return CreateChromeWindow2(aParent, aChromeFlags, 0, 0, &cancel, _retval);
     551                 : }
     552                 : 
     553                 : 
     554                 : //
     555                 : // nsAppStartup->nsIWindowCreator2
     556                 : //
     557                 : 
     558                 : NS_IMETHODIMP
     559               0 : nsAppStartup::CreateChromeWindow2(nsIWebBrowserChrome *aParent,
     560                 :                                   PRUint32 aChromeFlags,
     561                 :                                   PRUint32 aContextFlags,
     562                 :                                   nsIURI *aURI,
     563                 :                                   bool *aCancel,
     564                 :                                   nsIWebBrowserChrome **_retval)
     565                 : {
     566               0 :   NS_ENSURE_ARG_POINTER(aCancel);
     567               0 :   NS_ENSURE_ARG_POINTER(_retval);
     568               0 :   *aCancel = false;
     569               0 :   *_retval = 0;
     570                 : 
     571                 :   // Non-modal windows cannot be opened if we are attempting to quit
     572               0 :   if (mAttemptingQuit && (aChromeFlags & nsIWebBrowserChrome::CHROME_MODAL) == 0)
     573               0 :     return NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
     574                 : 
     575               0 :   nsCOMPtr<nsIXULWindow> newWindow;
     576                 : 
     577               0 :   if (aParent) {
     578               0 :     nsCOMPtr<nsIXULWindow> xulParent(do_GetInterface(aParent));
     579               0 :     NS_ASSERTION(xulParent, "window created using non-XUL parent. that's unexpected, but may work.");
     580                 : 
     581               0 :     if (xulParent)
     582               0 :       xulParent->CreateNewWindow(aChromeFlags, getter_AddRefs(newWindow));
     583                 :     // And if it fails, don't try again without a parent. It could fail
     584                 :     // intentionally (bug 115969).
     585                 :   } else { // try using basic methods:
     586                 :     /* You really shouldn't be making dependent windows without a parent.
     587                 :       But unparented modal (and therefore dependent) windows happen
     588                 :       in our codebase, so we allow it after some bellyaching: */
     589               0 :     if (aChromeFlags & nsIWebBrowserChrome::CHROME_DEPENDENT)
     590               0 :       NS_WARNING("dependent window created without a parent");
     591                 : 
     592               0 :     nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
     593               0 :     if (!appShell)
     594               0 :       return NS_ERROR_FAILURE;
     595                 :     
     596               0 :     appShell->CreateTopLevelWindow(0, 0, aChromeFlags,
     597                 :                                    nsIAppShellService::SIZE_TO_CONTENT,
     598                 :                                    nsIAppShellService::SIZE_TO_CONTENT,
     599               0 :                                    getter_AddRefs(newWindow));
     600                 :   }
     601                 : 
     602                 :   // if anybody gave us anything to work with, use it
     603               0 :   if (newWindow) {
     604               0 :     newWindow->SetContextFlags(aContextFlags);
     605               0 :     nsCOMPtr<nsIInterfaceRequestor> thing(do_QueryInterface(newWindow));
     606               0 :     if (thing)
     607               0 :       CallGetInterface(thing.get(), _retval);
     608                 :   }
     609                 : 
     610               0 :   return *_retval ? NS_OK : NS_ERROR_FAILURE;
     611                 : }
     612                 : 
     613                 : 
     614                 : //
     615                 : // nsAppStartup->nsIObserver
     616                 : //
     617                 : 
     618                 : NS_IMETHODIMP
     619              15 : nsAppStartup::Observe(nsISupports *aSubject,
     620                 :                       const char *aTopic, const PRUnichar *aData)
     621                 : {
     622              15 :   NS_ASSERTION(mAppShell, "appshell service notified before appshell built");
     623              15 :   if (!strcmp(aTopic, "quit-application-forced")) {
     624               0 :     mShuttingDown = true;
     625                 :   }
     626              15 :   else if (!strcmp(aTopic, "profile-change-teardown")) {
     627              15 :     if (!mShuttingDown) {
     628              15 :       EnterLastWindowClosingSurvivalArea();
     629              15 :       CloseAllWindows();
     630              15 :       ExitLastWindowClosingSurvivalArea();
     631                 :     }
     632               0 :   } else if (!strcmp(aTopic, "xul-window-registered")) {
     633               0 :     EnterLastWindowClosingSurvivalArea();
     634               0 :   } else if (!strcmp(aTopic, "xul-window-destroyed")) {
     635               0 :     ExitLastWindowClosingSurvivalArea();
     636               0 :   } else if (!strcmp(aTopic, "sessionstore-windows-restored")) {
     637               0 :     StartupTimeline::Record(StartupTimeline::SESSION_RESTORED);
     638                 : #if defined(XP_WIN)
     639                 :     if (mSessionWindowRestoredProbe) {
     640                 :       mSessionWindowRestoredProbe->Trigger();
     641                 :     }
     642                 :   } else if (!strcmp(aTopic, "places-init-complete")) {
     643                 :     if (mPlacesInitCompleteProbe) {
     644                 :       mPlacesInitCompleteProbe->Trigger();
     645                 :     }
     646                 : #endif //defined(XP_WIN)
     647                 :   } else {
     648               0 :     NS_ERROR("Unexpected observer topic.");
     649                 :   }
     650                 : 
     651              15 :   return NS_OK;
     652                 : }
     653                 : 
     654                 : #if defined(LINUX) || defined(ANDROID)
     655                 : static PRUint64 
     656              18 : JiffiesSinceBoot(const char *file)
     657                 : {
     658                 :   char stat[512];
     659              18 :   FILE *f = fopen(file, "r");
     660              18 :   if (!f)
     661               0 :     return 0;
     662              18 :   int n = fread(&stat, 1, sizeof(stat) - 1, f);
     663              18 :   fclose(f);
     664              18 :   if (n <= 0)
     665               0 :     return 0;
     666              18 :   stat[n] = 0;
     667                 :   
     668              18 :   long long unsigned starttime = 0; // instead of PRUint64 to keep GCC quiet
     669                 :   
     670              18 :   char *s = strrchr(stat, ')');
     671              18 :   if (!s)
     672               0 :     return 0;
     673                 :   int ret = sscanf(s + 2,
     674                 :                    "%*c %*d %*d %*d %*d %*d %*u %*u %*u %*u "
     675                 :                    "%*u %*u %*u %*u %*u %*d %*d %*d %*d %llu",
     676              18 :                    &starttime);
     677              18 :   if (ret != 1 || !starttime)
     678               0 :     return 0;
     679              18 :   return starttime;
     680                 : }
     681                 : 
     682                 : static void
     683               9 : ThreadedCalculateProcessCreationTimestamp(void *aClosure)
     684                 : {
     685               9 :   PRTime now = PR_Now();
     686               9 :   long hz = sysconf(_SC_CLK_TCK);
     687               9 :   if (!hz)
     688               0 :     return;
     689                 : 
     690                 :   char thread_stat[40];
     691               9 :   sprintf(thread_stat, "/proc/self/task/%d/stat", (pid_t) syscall(__NR_gettid));
     692                 :   
     693               9 :   PRUint64 thread_jiffies = JiffiesSinceBoot(thread_stat);
     694               9 :   PRUint64 self_jiffies = JiffiesSinceBoot("/proc/self/stat");
     695                 :   
     696               9 :   if (!thread_jiffies || !self_jiffies)
     697               0 :     return;
     698                 : 
     699               9 :   PRTime interval = (thread_jiffies - self_jiffies) * PR_USEC_PER_SEC / hz;
     700               9 :   StartupTimeline::Record(StartupTimeline::PROCESS_CREATION, now - interval);
     701                 : }
     702                 : 
     703                 : static PRTime
     704               9 : CalculateProcessCreationTimestamp()
     705                 : {
     706                 :  PRThread *thread = PR_CreateThread(PR_USER_THREAD,
     707                 :                                     ThreadedCalculateProcessCreationTimestamp,
     708                 :                                     NULL,
     709                 :                                     PR_PRIORITY_NORMAL,
     710                 :                                     PR_LOCAL_THREAD,
     711                 :                                     PR_JOINABLE_THREAD,
     712               9 :                                     0);
     713                 : 
     714               9 :   PR_JoinThread(thread);
     715               9 :   return StartupTimeline::Get(StartupTimeline::PROCESS_CREATION);
     716                 : }
     717                 : #elif defined(XP_WIN)
     718                 : static PRTime
     719                 : CalculateProcessCreationTimestamp()
     720                 : {
     721                 :   FILETIME start, foo, bar, baz;
     722                 :   bool success = GetProcessTimes(GetCurrentProcess(), &start, &foo, &bar, &baz);
     723                 :   if (!success)
     724                 :     return 0;
     725                 :   // copied from NSPR _PR_FileTimeToPRTime
     726                 :   PRUint64 timestamp = 0;
     727                 :   CopyMemory(&timestamp, &start, sizeof(PRTime));
     728                 : #ifdef __GNUC__
     729                 :   timestamp = (timestamp - 116444736000000000LL) / 10LL;
     730                 : #else
     731                 :   timestamp = (timestamp - 116444736000000000i64) / 10i64;
     732                 : #endif
     733                 :   return timestamp;
     734                 : }
     735                 : #elif defined(XP_MACOSX)
     736                 : static PRTime
     737                 : CalculateProcessCreationTimestamp()
     738                 : {
     739                 :   int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() };
     740                 :   size_t buffer_size;
     741                 :   if (sysctl(mib, 4, NULL, &buffer_size, NULL, 0))
     742                 :     return 0;
     743                 : 
     744                 :   struct kinfo_proc *proc = (kinfo_proc*) malloc(buffer_size);  
     745                 :   if (sysctl(mib, 4, proc, &buffer_size, NULL, 0)) {
     746                 :     free(proc);
     747                 :     return 0;
     748                 :   }
     749                 :   PRTime starttime = static_cast<PRTime>(proc->kp_proc.p_un.__p_starttime.tv_sec) * PR_USEC_PER_SEC;
     750                 :   starttime += proc->kp_proc.p_un.__p_starttime.tv_usec;
     751                 :   free(proc);
     752                 :   return starttime;
     753                 : }
     754                 : #elif defined(__OpenBSD__)
     755                 : static PRTime
     756                 : CalculateProcessCreationTimestamp()
     757                 : {
     758                 :   int mib[6] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid(), sizeof(struct kinfo_proc), 1 };
     759                 :   size_t buffer_size;
     760                 :   if (sysctl(mib, 6, NULL, &buffer_size, NULL, 0))
     761                 :     return 0;
     762                 : 
     763                 :   struct kinfo_proc *proc = (struct kinfo_proc*) malloc(buffer_size);
     764                 :   if (sysctl(mib, 6, proc, &buffer_size, NULL, 0)) {
     765                 :     free(proc);
     766                 :     return 0;
     767                 :   }
     768                 :   PRTime starttime = static_cast<PRTime>(proc->p_ustart_sec) * PR_USEC_PER_SEC;
     769                 :   starttime += proc->p_ustart_usec;
     770                 :   free(proc);
     771                 :   return starttime;
     772                 : }
     773                 : #else
     774                 : static PRTime
     775                 : CalculateProcessCreationTimestamp()
     776                 : {
     777                 :   return 0;
     778                 : }
     779                 : #endif
     780                 :  
     781                 : NS_IMETHODIMP
     782              15 : nsAppStartup::GetStartupInfo(JSContext* aCx, JS::Value* aRetval)
     783                 : {
     784              15 :   JSObject *obj = JS_NewObject(aCx, NULL, NULL, NULL);
     785              15 :   *aRetval = OBJECT_TO_JSVAL(obj);
     786                 : 
     787              15 :   PRTime ProcessCreationTimestamp = StartupTimeline::Get(StartupTimeline::PROCESS_CREATION);
     788                 : 
     789              15 :   if (!ProcessCreationTimestamp) {
     790               9 :     char *moz_app_restart = PR_GetEnv("MOZ_APP_RESTART");
     791               9 :     if (moz_app_restart) {
     792               0 :       ProcessCreationTimestamp = nsCRT::atoll(moz_app_restart) * PR_USEC_PER_MSEC;
     793                 :     } else {
     794               9 :       ProcessCreationTimestamp = CalculateProcessCreationTimestamp();
     795                 :     }
     796                 :     // Bug 670008: Avoid obviously invalid process creation times
     797               9 :     if (PR_Now() <= ProcessCreationTimestamp) {
     798               0 :       ProcessCreationTimestamp = -1;
     799               0 :       Telemetry::Accumulate(Telemetry::STARTUP_MEASUREMENT_ERRORS, StartupTimeline::PROCESS_CREATION);
     800                 :     }
     801               9 :     StartupTimeline::Record(StartupTimeline::PROCESS_CREATION, ProcessCreationTimestamp);
     802                 :   }
     803                 : 
     804             165 :   for (int i = StartupTimeline::PROCESS_CREATION; i < StartupTimeline::MAX_EVENT_ID; ++i) {
     805             150 :     StartupTimeline::Event ev = static_cast<StartupTimeline::Event>(i);
     806             150 :     if (StartupTimeline::Get(ev) > 0) {
     807                 :       // always define main to aid with bug 689256
     808              30 :       if ((ev != StartupTimeline::MAIN) &&
     809              15 :           (StartupTimeline::Get(ev) < StartupTimeline::Get(StartupTimeline::PROCESS_CREATION))) {
     810               0 :         Telemetry::Accumulate(Telemetry::STARTUP_MEASUREMENT_ERRORS, i);
     811               0 :         StartupTimeline::Record(ev, -1);
     812                 :       } else {
     813              15 :         JSObject *date = JS_NewDateObjectMsec(aCx, StartupTimeline::Get(ev) / PR_USEC_PER_MSEC);
     814              15 :         JS_DefineProperty(aCx, obj, StartupTimeline::Describe(ev), OBJECT_TO_JSVAL(date), NULL, NULL, JSPROP_ENUMERATE);
     815                 :       }
     816                 :     }
     817                 :   }
     818                 : 
     819              15 :   return NS_OK;
     820                 : }
     821                 : 
     822                 : NS_IMETHODIMP
     823              52 : nsAppStartup::GetAutomaticSafeModeNecessary(bool *_retval)
     824                 : {
     825              52 :   NS_ENSURE_ARG_POINTER(_retval);
     826                 : 
     827              52 :   *_retval = mIsSafeModeNecessary;
     828              52 :   return NS_OK;
     829                 : }
     830                 : 
     831                 : NS_IMETHODIMP
     832              43 : nsAppStartup::TrackStartupCrashBegin(bool *aIsSafeModeNecessary)
     833                 : {
     834              43 :   const PRInt32 MAX_TIME_SINCE_STARTUP = 6 * 60 * 60 * 1000;
     835              43 :   const PRInt32 MAX_STARTUP_BUFFER = 10;
     836                 :   nsresult rv;
     837                 : 
     838              43 :   mStartupCrashTrackingEnded = false;
     839                 : 
     840              43 :   StartupTimeline::Record(StartupTimeline::STARTUP_CRASH_DETECTION_BEGIN);
     841                 : 
     842              43 :   bool hasLastSuccess = Preferences::HasUserValue(kPrefLastSuccess);
     843              43 :   if (!hasLastSuccess) {
     844                 :     // Clear so we don't get stuck with SafeModeNecessary returning true if we
     845                 :     // have had too many recent crashes and the last success pref is missing.
     846              10 :     Preferences::ClearUser(kPrefRecentCrashes);
     847              10 :     return NS_ERROR_NOT_AVAILABLE;
     848                 :   }
     849                 : 
     850              33 :   bool inSafeMode = false;
     851              66 :   nsCOMPtr<nsIXULRuntime> xr = do_GetService(XULRUNTIME_SERVICE_CONTRACTID);
     852              33 :   NS_ENSURE_TRUE(xr, NS_ERROR_FAILURE);
     853                 : 
     854              33 :   xr->GetInSafeMode(&inSafeMode);
     855                 : 
     856                 :   PRInt64 replacedLockTime;
     857              33 :   rv = xr->GetReplacedLockTime(&replacedLockTime);
     858                 : 
     859              33 :   if (NS_FAILED(rv) || !replacedLockTime) {
     860               0 :     if (!inSafeMode)
     861               0 :       Preferences::ClearUser(kPrefRecentCrashes);
     862               0 :     GetAutomaticSafeModeNecessary(aIsSafeModeNecessary);
     863               0 :     return NS_OK;
     864                 :   }
     865                 : 
     866                 :   // check whether safe mode is necessary
     867              33 :   PRInt32 maxResumedCrashes = -1;
     868              33 :   rv = Preferences::GetInt(kPrefMaxResumedCrashes, &maxResumedCrashes);
     869              33 :   NS_ENSURE_SUCCESS(rv, NS_OK);
     870                 : 
     871              33 :   PRInt32 recentCrashes = 0;
     872              33 :   Preferences::GetInt(kPrefRecentCrashes, &recentCrashes);
     873              33 :   mIsSafeModeNecessary = (recentCrashes > maxResumedCrashes && maxResumedCrashes != -1);
     874                 : 
     875                 :   // Bug 731613 - Don't check if the last startup was a crash if XRE_PROFILE_PATH is set.  After
     876                 :   // profile manager, the profile lock's mod. time has been changed so can't be used on this startup.
     877                 :   // After a restart, it's safe to assume the last startup was successful.
     878              33 :   char *xreProfilePath = PR_GetEnv("XRE_PROFILE_PATH");
     879              33 :   if (xreProfilePath) {
     880               0 :     GetAutomaticSafeModeNecessary(aIsSafeModeNecessary);
     881               0 :     return NS_ERROR_NOT_AVAILABLE;
     882                 :   }
     883                 : 
     884                 :   // time of last successful startup
     885                 :   PRInt32 lastSuccessfulStartup;
     886              33 :   rv = Preferences::GetInt(kPrefLastSuccess, &lastSuccessfulStartup);
     887              33 :   NS_ENSURE_SUCCESS(rv, rv);
     888                 : 
     889              33 :   PRInt32 lockSeconds = (PRInt32)(replacedLockTime / PR_MSEC_PER_SEC);
     890                 : 
     891                 :   // started close enough to good startup so call it good
     892              33 :   if (lockSeconds <= lastSuccessfulStartup + MAX_STARTUP_BUFFER
     893                 :       && lockSeconds >= lastSuccessfulStartup - MAX_STARTUP_BUFFER) {
     894              18 :     GetAutomaticSafeModeNecessary(aIsSafeModeNecessary);
     895              18 :     return NS_OK;
     896                 :   }
     897                 : 
     898                 :   // sanity check that the pref set at last success is not greater than the current time
     899              15 :   if (PR_Now() / PR_USEC_PER_SEC <= lastSuccessfulStartup)
     900               0 :     return NS_ERROR_FAILURE;
     901                 : 
     902                 :   // The last startup was a crash so include it in the count regardless of when it happened.
     903              15 :   Telemetry::Accumulate(Telemetry::STARTUP_CRASH_DETECTED, true);
     904                 : 
     905              15 :   if (inSafeMode) {
     906               5 :     GetAutomaticSafeModeNecessary(aIsSafeModeNecessary);
     907               5 :     return NS_OK;
     908                 :   }
     909                 : 
     910              10 :   PRTime now = (PR_Now() / PR_USEC_PER_MSEC);
     911                 :   // if the last startup attempt which crashed was in the last 6 hours
     912              10 :   if (replacedLockTime >= now - MAX_TIME_SINCE_STARTUP) {
     913               6 :     NS_WARNING("Last startup was detected as a crash.");
     914               6 :     recentCrashes++;
     915               6 :     rv = Preferences::SetInt(kPrefRecentCrashes, recentCrashes);
     916                 :   } else {
     917                 :     // Otherwise ignore that crash and all previous since it may not be applicable anymore
     918                 :     // and we don't want someone to get stuck in safe mode if their prefs are read-only.
     919               4 :     rv = Preferences::ClearUser(kPrefRecentCrashes);
     920                 :   }
     921              10 :   NS_ENSURE_SUCCESS(rv, rv);
     922                 : 
     923                 :   // recalculate since recent crashes count may have changed above
     924              10 :   mIsSafeModeNecessary = (recentCrashes > maxResumedCrashes && maxResumedCrashes != -1);
     925                 : 
     926              20 :   nsCOMPtr<nsIPrefService> prefs = Preferences::GetService();
     927              10 :   rv = prefs->SavePrefFile(nsnull); // flush prefs to disk since we are tracking crashes
     928              10 :   NS_ENSURE_SUCCESS(rv, rv);
     929                 : 
     930              10 :   GetAutomaticSafeModeNecessary(aIsSafeModeNecessary);
     931              10 :   return rv;
     932                 : }
     933                 : 
     934                 : NS_IMETHODIMP
     935               5 : nsAppStartup::TrackStartupCrashEnd()
     936                 : {
     937               5 :   bool inSafeMode = false;
     938              10 :   nsCOMPtr<nsIXULRuntime> xr = do_GetService(XULRUNTIME_SERVICE_CONTRACTID);
     939               5 :   if (xr)
     940               5 :     xr->GetInSafeMode(&inSafeMode);
     941                 : 
     942                 :   // return if we already ended or we're restarting into safe mode
     943               5 :   if (mStartupCrashTrackingEnded || (mIsSafeModeNecessary && !inSafeMode))
     944               0 :     return NS_OK;
     945               5 :   mStartupCrashTrackingEnded = true;
     946                 : 
     947               5 :   StartupTimeline::Record(StartupTimeline::STARTUP_CRASH_DETECTION_END);
     948                 : 
     949                 :   // Use the timestamp of XRE_main as an approximation for the lock file timestamp.
     950                 :   // See MAX_STARTUP_BUFFER for the buffer time period.
     951                 :   nsresult rv;
     952               5 :   PRTime mainTime = StartupTimeline::Get(StartupTimeline::MAIN);
     953               5 :   if (mainTime <= 0) {
     954               5 :     NS_WARNING("Could not get StartupTimeline::MAIN time.");
     955                 :   } else {
     956               0 :     PRInt32 lockFileTime = (PRInt32)(mainTime / PR_USEC_PER_SEC);
     957               0 :     rv = Preferences::SetInt(kPrefLastSuccess, lockFileTime);
     958               0 :     if (NS_FAILED(rv)) NS_WARNING("Could not set startup crash detection pref.");
     959                 :   }
     960                 : 
     961               5 :   if (inSafeMode && mIsSafeModeNecessary) {
     962                 :     // On a successful startup in automatic safe mode, allow the user one more crash
     963                 :     // in regular mode before returning to safe mode.
     964               1 :     PRInt32 maxResumedCrashes = 0;
     965                 :     PRInt32 prefType;
     966               1 :     rv = Preferences::GetDefaultRootBranch()->GetPrefType(kPrefMaxResumedCrashes, &prefType);
     967               1 :     NS_ENSURE_SUCCESS(rv, rv);
     968               1 :     if (prefType == nsIPrefBranch::PREF_INT) {
     969               1 :       rv = Preferences::GetInt(kPrefMaxResumedCrashes, &maxResumedCrashes);
     970               1 :       NS_ENSURE_SUCCESS(rv, rv);
     971                 :     }
     972               1 :     rv = Preferences::SetInt(kPrefRecentCrashes, maxResumedCrashes);
     973               1 :     NS_ENSURE_SUCCESS(rv, rv);
     974               4 :   } else if (!inSafeMode) {
     975                 :     // clear the count of recent crashes after a succesful startup when not in safe mode
     976               3 :     rv = Preferences::ClearUser(kPrefRecentCrashes);
     977               3 :     if (NS_FAILED(rv)) NS_WARNING("Could not clear startup crash count.");
     978                 :   }
     979              10 :   nsCOMPtr<nsIPrefService> prefs = Preferences::GetService();
     980               5 :   rv = prefs->SavePrefFile(nsnull); // flush prefs to disk since we are tracking crashes
     981                 : 
     982               5 :   return rv;
     983                 : }
     984                 : 
     985                 : NS_IMETHODIMP
     986               0 : nsAppStartup::RestartInSafeMode(PRUint32 aQuitMode)
     987                 : {
     988               0 :   PR_SetEnv("MOZ_SAFE_MODE_RESTART=1");
     989               0 :   this->Quit(aQuitMode | nsIAppStartup::eRestart);
     990                 : 
     991               0 :   return NS_OK;
     992                 : }

Generated by: LCOV version 1.7