LCOV - code coverage report
Current view: directory - toolkit/xre - nsUpdateDriver.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 164 2 1.2 %
Date: 2012-06-02 Functions: 13 2 15.4 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* vim:set ts=2 sw=2 sts=2 et cindent: */
       3                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is mozilla.org code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is Google Inc.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2005
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *  Darin Fisher <darin@meer.net>
      24                 :  *  Ben Turner <mozilla@songbirdnest.com>
      25                 :  *  Robert Strong <robert.bugzilla@gmail.com>
      26                 :  *  Josh Aas <josh@mozilla.com>
      27                 :  *  Brian R. Bondy <netzen@gmail.com>
      28                 :  *
      29                 :  * Alternatively, the contents of this file may be used under the terms of
      30                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      31                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      32                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      33                 :  * of those above. If you wish to allow use of your version of this file only
      34                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      35                 :  * use your version of this file under the terms of the MPL, indicate your
      36                 :  * decision by deleting the provisions above and replace them with the notice
      37                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      38                 :  * the provisions above, a recipient may use your version of this file under
      39                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      40                 :  *
      41                 :  * ***** END LICENSE BLOCK ***** */
      42                 : 
      43                 : #include <stdlib.h>
      44                 : #include <stdio.h>
      45                 : #include "nsUpdateDriver.h"
      46                 : #include "nsXULAppAPI.h"
      47                 : #include "nsAppRunner.h"
      48                 : #include "nsILocalFile.h"
      49                 : #include "nsCOMPtr.h"
      50                 : #include "nsString.h"
      51                 : #include "prproces.h"
      52                 : #include "prlog.h"
      53                 : #include "prenv.h"
      54                 : #include "nsVersionComparator.h"
      55                 : 
      56                 : #ifdef XP_MACOSX
      57                 : #include "nsILocalFileMac.h"
      58                 : #include "nsCommandLineServiceMac.h"
      59                 : #include "MacLaunchHelper.h"
      60                 : #endif
      61                 : 
      62                 : #if defined(XP_WIN)
      63                 : # include <direct.h>
      64                 : # include <process.h>
      65                 : # include <windows.h>
      66                 : # define getcwd(path, size) _getcwd(path, size)
      67                 : # define getpid() GetCurrentProcessId()
      68                 : #elif defined(XP_OS2)
      69                 : # include <unistd.h>
      70                 : # define INCL_DOSFILEMGR
      71                 : # include <os2.h>
      72                 : #elif defined(XP_UNIX)
      73                 : # include <unistd.h>
      74                 : #endif
      75                 : 
      76                 : //
      77                 : // We use execv to spawn the updater process on all UNIX systems except Mac OSX
      78                 : // since it is known to cause problems on the Mac.  Windows has execv, but it
      79                 : // is a faked implementation that doesn't really replace the current process.
      80                 : // Instead it spawns a new process, so we gain nothing from using execv on
      81                 : // Windows.
      82                 : //
      83                 : // On platforms where we are not calling execv, we may need to make the
      84                 : // updater executable wait for the calling process to exit.  Otherwise, the
      85                 : // updater may have trouble modifying our executable image (because it might
      86                 : // still be in use).  This is accomplished by passing our PID to the updater so
      87                 : // that it can wait for us to exit.  This is not perfect as there is a race
      88                 : // condition that could bite us.  It's possible that the calling process could
      89                 : // exit before the updater waits on the specified PID, and in the meantime a
      90                 : // new process with the same PID could be created.  This situation is unlikely,
      91                 : // however, given the way most operating systems recycle PIDs.  We'll take our
      92                 : // chances ;-)
      93                 : //
      94                 : // A similar #define lives in updater.cpp and should be kept in sync with this.
      95                 : //
      96                 : #if defined(XP_UNIX) && !defined(XP_MACOSX)
      97                 : #define USE_EXECV
      98                 : #endif
      99                 : 
     100                 : #ifdef PR_LOGGING
     101            1464 : static PRLogModuleInfo *sUpdateLog = PR_NewLogModule("updatedriver");
     102                 : #endif
     103                 : #define LOG(args) PR_LOG(sUpdateLog, PR_LOG_DEBUG, args)
     104                 : 
     105                 : #ifdef XP_WIN
     106                 : static const char kUpdaterBin[] = "updater.exe";
     107                 : #else
     108                 : static const char kUpdaterBin[] = "updater";
     109                 : #endif
     110                 : static const char kUpdaterINI[] = "updater.ini";
     111                 : #ifdef XP_MACOSX
     112                 : static const char kUpdaterApp[] = "updater.app";
     113                 : #endif
     114                 : #if defined(XP_UNIX) && !defined(XP_MACOSX)
     115                 : static const char kUpdaterPNG[] = "updater.png";
     116                 : #endif
     117                 : 
     118                 : static nsresult
     119               0 : GetCurrentWorkingDir(char *buf, size_t size)
     120                 : {
     121                 :   // Cannot use NS_GetSpecialDirectory because XPCOM is not yet initialized.
     122                 :   // This code is duplicated from xpcom/io/SpecialSystemDirectory.cpp:
     123                 : 
     124                 : #if defined(XP_OS2)
     125                 :   if (DosQueryPathInfo( ".", FIL_QUERYFULLNAME, buf, size))
     126                 :     return NS_ERROR_FAILURE;
     127                 : #elif defined(XP_WIN)
     128                 :   wchar_t wpath[MAX_PATH];
     129                 :   if (!_wgetcwd(wpath, size))
     130                 :     return NS_ERROR_FAILURE;
     131                 :   NS_ConvertUTF16toUTF8 path(wpath);
     132                 :   strncpy(buf, path.get(), size);
     133                 : #else
     134               0 :   if(!getcwd(buf, size))
     135               0 :     return NS_ERROR_FAILURE;
     136                 : #endif
     137               0 :   return NS_OK;
     138                 : }
     139                 : 
     140                 : #if defined(XP_MACOSX)
     141                 : // This is a copy of OS X's XRE_GetBinaryPath from nsAppRunner.cpp with the
     142                 : // gBinaryPath check removed so that the updater can reload the stub executable
     143                 : // instead of xulrunner-bin. See bug 349737.
     144                 : static nsresult
     145                 : GetXULRunnerStubPath(const char* argv0, nsILocalFile* *aResult)
     146                 : {
     147                 :   // Works even if we're not bundled.
     148                 :   CFBundleRef appBundle = ::CFBundleGetMainBundle();
     149                 :   if (!appBundle)
     150                 :     return NS_ERROR_FAILURE;
     151                 : 
     152                 :   CFURLRef bundleURL = ::CFBundleCopyExecutableURL(appBundle);
     153                 :   if (!bundleURL)
     154                 :     return NS_ERROR_FAILURE;
     155                 : 
     156                 :   nsCOMPtr<nsILocalFileMac> lfm;
     157                 :   nsresult rv = NS_NewLocalFileWithCFURL(bundleURL, true, getter_AddRefs(lfm));
     158                 : 
     159                 :   ::CFRelease(bundleURL);
     160                 : 
     161                 :   if (NS_FAILED(rv))
     162                 :     return rv;
     163                 : 
     164                 :   NS_ADDREF(*aResult = static_cast<nsILocalFile*>(lfm.get()));
     165                 :   return NS_OK;
     166                 : }
     167                 : #endif /* XP_MACOSX */
     168                 : 
     169                 : static bool
     170               0 : GetFile(nsIFile *dir, const nsCSubstring &name, nsCOMPtr<nsILocalFile> &result)
     171                 : {
     172                 :   nsresult rv;
     173                 :   
     174               0 :   nsCOMPtr<nsIFile> file;
     175               0 :   rv = dir->Clone(getter_AddRefs(file));
     176               0 :   if (NS_FAILED(rv))
     177               0 :     return false;
     178                 : 
     179               0 :   rv = file->AppendNative(name);
     180               0 :   if (NS_FAILED(rv))
     181               0 :     return false;
     182                 : 
     183               0 :   result = do_QueryInterface(file, &rv);
     184               0 :   return NS_SUCCEEDED(rv);
     185                 : }
     186                 : 
     187                 : static bool
     188               0 : GetStatusFile(nsIFile *dir, nsCOMPtr<nsILocalFile> &result)
     189                 : {
     190               0 :   return GetFile(dir, NS_LITERAL_CSTRING("update.status"), result);
     191                 : }
     192                 : 
     193                 : static bool
     194               0 : IsPending(nsILocalFile *statusFile)
     195                 : {
     196               0 :   PRFileDesc *fd = nsnull;
     197               0 :   nsresult rv = statusFile->OpenNSPRFileDesc(PR_RDONLY, 0660, &fd);
     198               0 :   if (NS_FAILED(rv))
     199               0 :     return false;
     200                 : 
     201                 :   char buf[32];
     202               0 :   const PRInt32 n = PR_Read(fd, buf, sizeof(buf));
     203               0 :   PR_Close(fd);
     204                 : 
     205               0 :   if (n < 0)
     206               0 :     return false;
     207                 :   
     208               0 :   const char kPending[] = "pending";
     209               0 :   bool isPending = (strncmp(buf, kPending, sizeof(kPending) - 1) == 0);
     210               0 :   return isPending;
     211                 : }
     212                 : 
     213                 : static bool
     214               0 : GetVersionFile(nsIFile *dir, nsCOMPtr<nsILocalFile> &result)
     215                 : {
     216               0 :   return GetFile(dir, NS_LITERAL_CSTRING("update.version"), result);
     217                 : }
     218                 : 
     219                 : // Compares the current application version with the update's application
     220                 : // version.
     221                 : static bool
     222               0 : IsOlderVersion(nsILocalFile *versionFile, const char *appVersion)
     223                 : {
     224               0 :   PRFileDesc *fd = nsnull;
     225               0 :   nsresult rv = versionFile->OpenNSPRFileDesc(PR_RDONLY, 0660, &fd);
     226               0 :   if (NS_FAILED(rv))
     227               0 :     return true;
     228                 : 
     229                 :   char buf[32];
     230               0 :   const PRInt32 n = PR_Read(fd, buf, sizeof(buf));
     231               0 :   PR_Close(fd);
     232                 : 
     233               0 :   if (n < 0)
     234               0 :     return false;
     235                 : 
     236                 :   // Trim off the trailing newline
     237               0 :   if (buf[n - 1] == '\n')
     238               0 :     buf[n - 1] = '\0';
     239                 : 
     240                 :   // If the update xml doesn't provide the application version the file will
     241                 :   // contain the string "null" and it is assumed that the update is not older.
     242               0 :   const char kNull[] = "null";
     243               0 :   if (strncmp(buf, kNull, sizeof(kNull) - 1) == 0)
     244               0 :     return false;
     245                 : 
     246               0 :   if (NS_CompareVersions(appVersion, buf) > 0)
     247               0 :     return true;
     248                 : 
     249               0 :   return false;
     250                 : }
     251                 : 
     252                 : static bool
     253               0 : CopyFileIntoUpdateDir(nsIFile *parentDir, const char *leafName, nsIFile *updateDir)
     254                 : {
     255               0 :   nsDependentCString leaf(leafName);
     256               0 :   nsCOMPtr<nsIFile> file;
     257                 : 
     258                 :   // Make sure there is not an existing file in the target location.
     259               0 :   nsresult rv = updateDir->Clone(getter_AddRefs(file));
     260               0 :   if (NS_FAILED(rv))
     261               0 :     return false;
     262               0 :   rv = file->AppendNative(leaf);
     263               0 :   if (NS_FAILED(rv))
     264               0 :     return false;
     265               0 :   file->Remove(false);
     266                 : 
     267                 :   // Now, copy into the target location.
     268               0 :   rv = parentDir->Clone(getter_AddRefs(file));
     269               0 :   if (NS_FAILED(rv))
     270               0 :     return false;
     271               0 :   rv = file->AppendNative(leaf);
     272               0 :   if (NS_FAILED(rv))
     273               0 :     return false;
     274               0 :   rv = file->CopyToNative(updateDir, EmptyCString());
     275               0 :   if (NS_FAILED(rv))
     276               0 :     return false;
     277                 : 
     278               0 :   return true;
     279                 : }
     280                 : 
     281                 : static bool
     282               0 : CopyUpdaterIntoUpdateDir(nsIFile *greDir, nsIFile *appDir, nsIFile *updateDir,
     283                 :                          nsCOMPtr<nsIFile> &updater)
     284                 : {
     285                 :   // Copy the updater application from the GRE and the updater ini from the app
     286                 : #if defined(XP_MACOSX)
     287                 :   if (!CopyFileIntoUpdateDir(greDir, kUpdaterApp, updateDir))
     288                 :     return false;
     289                 : #else
     290               0 :   if (!CopyFileIntoUpdateDir(greDir, kUpdaterBin, updateDir))
     291               0 :     return false;
     292                 : #endif
     293               0 :   CopyFileIntoUpdateDir(appDir, kUpdaterINI, updateDir);
     294                 : #if defined(XP_UNIX) && !defined(XP_MACOSX)
     295               0 :   nsCOMPtr<nsIFile> iconDir;
     296               0 :   appDir->Clone(getter_AddRefs(iconDir));
     297               0 :   iconDir->AppendNative(NS_LITERAL_CSTRING("icons"));
     298               0 :   if (!CopyFileIntoUpdateDir(iconDir, kUpdaterPNG, updateDir))
     299               0 :     return false;
     300                 : #endif
     301                 :   // Finally, return the location of the updater binary.
     302               0 :   nsresult rv = updateDir->Clone(getter_AddRefs(updater));
     303               0 :   if (NS_FAILED(rv))
     304               0 :     return false;
     305                 : #if defined(XP_MACOSX)
     306                 :   rv  = updater->AppendNative(NS_LITERAL_CSTRING(kUpdaterApp));
     307                 :   rv |= updater->AppendNative(NS_LITERAL_CSTRING("Contents"));
     308                 :   rv |= updater->AppendNative(NS_LITERAL_CSTRING("MacOS"));
     309                 :   if (NS_FAILED(rv))
     310                 :     return false;
     311                 : #endif
     312               0 :   rv = updater->AppendNative(NS_LITERAL_CSTRING(kUpdaterBin));
     313               0 :   return NS_SUCCEEDED(rv); 
     314                 : }
     315                 : 
     316                 : static void
     317               0 : ApplyUpdate(nsIFile *greDir, nsIFile *updateDir, nsILocalFile *statusFile,
     318                 :             nsIFile *appDir, int appArgc, char **appArgv)
     319                 : {
     320                 :   nsresult rv;
     321                 : 
     322                 :   // Steps:
     323                 :   //  - mark update as 'applying'
     324                 :   //  - copy updater into update dir
     325                 :   //  - run updater w/ appDir as the current working dir
     326                 : 
     327               0 :   nsCOMPtr<nsIFile> updater;
     328               0 :   if (!CopyUpdaterIntoUpdateDir(greDir, appDir, updateDir, updater)) {
     329               0 :     LOG(("failed copying updater\n"));
     330                 :     return;
     331                 :   }
     332                 : 
     333                 :   // We need to use the value returned from XRE_GetBinaryPath when attempting
     334                 :   // to restart the running application.
     335               0 :   nsCOMPtr<nsILocalFile> appFile;
     336                 : 
     337                 : #if defined(XP_MACOSX)
     338                 :   // On OS X we need to pass the location of the xulrunner-stub executable
     339                 :   // rather than xulrunner-bin. See bug 349737.
     340                 :   GetXULRunnerStubPath(appArgv[0], getter_AddRefs(appFile));
     341                 : #else
     342               0 :   XRE_GetBinaryPath(appArgv[0], getter_AddRefs(appFile));
     343                 : #endif
     344                 : 
     345               0 :   if (!appFile)
     346                 :     return;
     347                 : 
     348                 : #ifdef XP_WIN
     349                 :   nsAutoString appFilePathW;
     350                 :   rv = appFile->GetPath(appFilePathW);
     351                 :   if (NS_FAILED(rv))
     352                 :     return;
     353                 :   NS_ConvertUTF16toUTF8 appFilePath(appFilePathW);
     354                 : 
     355                 :   nsAutoString updaterPathW;
     356                 :   rv = updater->GetPath(updaterPathW);
     357                 :   if (NS_FAILED(rv))
     358                 :     return;
     359                 : 
     360                 :   NS_ConvertUTF16toUTF8 updaterPath(updaterPathW);
     361                 : 
     362                 : #else
     363               0 :   nsCAutoString appFilePath;
     364               0 :   rv = appFile->GetNativePath(appFilePath);
     365               0 :   if (NS_FAILED(rv))
     366                 :     return;
     367                 :   
     368               0 :   nsCAutoString updaterPath;
     369               0 :   rv = updater->GetNativePath(updaterPath);
     370               0 :   if (NS_FAILED(rv))
     371                 :     return;
     372                 : 
     373                 : #endif
     374                 : 
     375                 :   // Get the directory to which the update will be applied. On Mac OSX we need
     376                 :   // to apply the update to the Foo.app directory which is the parent of the
     377                 :   // parent of the appDir. On other platforms we will just apply to the appDir.
     378                 : #if defined(XP_MACOSX)
     379                 :   nsCAutoString applyToDir;
     380                 :   {
     381                 :     nsCOMPtr<nsIFile> parentDir1, parentDir2;
     382                 :     rv = appDir->GetParent(getter_AddRefs(parentDir1));
     383                 :     if (NS_FAILED(rv))
     384                 :       return;
     385                 :     rv = parentDir1->GetParent(getter_AddRefs(parentDir2));
     386                 :     if (NS_FAILED(rv))
     387                 :       return;
     388                 :     rv = parentDir2->GetNativePath(applyToDir);
     389                 :   }
     390                 : #elif defined(XP_WIN)
     391                 :   nsAutoString applyToDirW;
     392                 :   rv = appDir->GetPath(applyToDirW);
     393                 : 
     394                 :   NS_ConvertUTF16toUTF8 applyToDir(applyToDirW);
     395                 : #else
     396               0 :   nsCAutoString applyToDir;
     397               0 :   rv = appDir->GetNativePath(applyToDir);
     398                 : #endif
     399               0 :   if (NS_FAILED(rv))
     400                 :     return;
     401                 : 
     402                 : #if defined(XP_WIN)
     403                 :   nsAutoString updateDirPathW;
     404                 :   rv = updateDir->GetPath(updateDirPathW);
     405                 : 
     406                 :   NS_ConvertUTF16toUTF8 updateDirPath(updateDirPathW);
     407                 : #else
     408               0 :   nsCAutoString updateDirPath;
     409               0 :   rv = updateDir->GetNativePath(updateDirPath);
     410                 : #endif
     411                 : 
     412               0 :   if (NS_FAILED(rv))
     413                 :     return;
     414                 : 
     415                 :   // Get the current working directory.
     416                 :   char workingDirPath[MAXPATHLEN];
     417               0 :   rv = GetCurrentWorkingDir(workingDirPath, sizeof(workingDirPath));
     418               0 :   if (NS_FAILED(rv))
     419                 :     return;
     420                 : 
     421                 :   // We used to write out "Applying" to the update.status file here.
     422                 :   // Instead we do this from within the updater application now.
     423                 :   // This is so that we don't overwrite the status of pending-service
     424                 :   // in the Windows case.  This change was made for all platforms so
     425                 :   // that it stays consistent across all OS.
     426                 : 
     427                 :   // Construct the PID argument for this process.  If we are using execv, then
     428                 :   // we pass "0" which is then ignored by the updater.
     429                 : #if defined(USE_EXECV)
     430               0 :   NS_NAMED_LITERAL_CSTRING(pid, "0");
     431                 : #else
     432                 :   nsCAutoString pid;
     433                 :   pid.AppendInt((PRInt32) getpid());
     434                 : #endif
     435                 : 
     436               0 :   int argc = appArgc + 5;
     437               0 :   char **argv = new char*[argc + 1];
     438               0 :   if (!argv)
     439                 :     return;
     440               0 :   argv[0] = (char*) updaterPath.get();
     441               0 :   argv[1] = (char*) updateDirPath.get();
     442               0 :   argv[2] = (char*) applyToDir.get();
     443               0 :   argv[3] = (char*) pid.get();
     444               0 :   if (appArgc) {
     445               0 :     argv[4] = workingDirPath;
     446               0 :     argv[5] = (char*) appFilePath.get();
     447               0 :     for (int i = 1; i < appArgc; ++i)
     448               0 :       argv[5 + i] = appArgv[i];
     449               0 :     argc = 5 + appArgc;
     450               0 :     argv[argc] = NULL;
     451                 :   } else {
     452               0 :     argc = 4;
     453               0 :     argv[4] = NULL;
     454                 :   }
     455                 : 
     456               0 :   if (gSafeMode) {
     457               0 :     PR_SetEnv("MOZ_SAFE_MODE_RESTART=1");
     458                 :   }
     459                 : 
     460               0 :   LOG(("spawning updater process [%s]\n", updaterPath.get()));
     461                 : 
     462                 : #if defined(USE_EXECV)
     463               0 :   execv(updaterPath.get(), argv);
     464                 : #elif defined(XP_WIN)
     465                 : 
     466                 :   // Launch the update using updater.exe
     467                 :   if (!WinLaunchChild(updaterPathW.get(), argc, argv)) {
     468                 :     return;
     469                 :   }
     470                 : 
     471                 :   // We are going to process an update so we should exit now
     472                 :   _exit(0);
     473                 : #elif defined(XP_MACOSX)
     474                 :   CommandLineServiceMac::SetupMacCommandLine(argc, argv, true);
     475                 :   // LaunchChildMac uses posix_spawnp and prefers the current
     476                 :   // architecture when launching. It doesn't require a
     477                 :   // null-terminated string but it doesn't matter if we pass one.
     478                 :   LaunchChildMac(argc, argv);
     479                 :   exit(0);
     480                 : #else
     481                 :   PR_CreateProcessDetached(updaterPath.get(), argv, NULL, NULL);
     482                 :   exit(0);
     483                 : #endif
     484                 : }
     485                 : 
     486                 : nsresult
     487               0 : ProcessUpdates(nsIFile *greDir, nsIFile *appDir, nsIFile *updRootDir,
     488                 :                int argc, char **argv, const char *appVersion)
     489                 : {
     490                 :   nsresult rv;
     491                 : 
     492               0 :   nsCOMPtr<nsIFile> updatesDir;
     493               0 :   rv = updRootDir->Clone(getter_AddRefs(updatesDir));
     494               0 :   if (NS_FAILED(rv))
     495               0 :     return rv;
     496                 : 
     497               0 :   rv = updatesDir->AppendNative(NS_LITERAL_CSTRING("updates"));
     498               0 :   if (NS_FAILED(rv))
     499               0 :     return rv;
     500                 : 
     501               0 :   rv = updatesDir->AppendNative(NS_LITERAL_CSTRING("0"));
     502               0 :   if (NS_FAILED(rv))
     503               0 :     return rv;
     504                 :  
     505               0 :   const char *processingUpdates = PR_GetEnv("MOZ_PROCESS_UPDATES");
     506               0 :   if (processingUpdates && *processingUpdates) {
     507                 :     // Enable the tests to request us to use a different update root directory
     508               0 :     const char *updRootOverride = PR_GetEnv("MOZ_UPDATE_ROOT_OVERRIDE");
     509               0 :     if (updRootOverride && *updRootOverride) {
     510               0 :       nsCOMPtr<nsILocalFile> overrideDir;
     511               0 :       nsCAutoString path(updRootOverride);
     512               0 :       rv = NS_NewNativeLocalFile(path, false, getter_AddRefs(overrideDir));
     513               0 :       if (NS_FAILED(rv)) {
     514               0 :         return rv;
     515                 :       }
     516               0 :       updatesDir = do_QueryInterface(overrideDir);
     517                 :     }
     518                 :     // Enable the tests to request us to use a different app directory
     519               0 :     const char *appDirOverride = PR_GetEnv("MOZ_UPDATE_APPDIR_OVERRIDE");
     520               0 :     if (appDirOverride && *appDirOverride) {
     521               0 :       nsCOMPtr<nsILocalFile> overrideDir;
     522               0 :       nsCAutoString path(appDirOverride);
     523               0 :       rv = NS_NewNativeLocalFile(path, false, getter_AddRefs(overrideDir));
     524               0 :       if (NS_FAILED(rv)) {
     525               0 :         return rv;
     526                 :       }
     527               0 :       NS_RELEASE(appDir);
     528               0 :       NS_ADDREF(appDir = overrideDir);
     529                 :     }
     530                 :   }
     531                 : 
     532               0 :   nsCOMPtr<nsILocalFile> statusFile;
     533               0 :   if (GetStatusFile(updatesDir, statusFile) && 
     534               0 :       IsPending(statusFile)) {
     535               0 :     nsCOMPtr<nsILocalFile> versionFile;
     536                 :     // Remove the update if the update application version file doesn't exist
     537                 :     // or if the update's application version is less than the current
     538                 :     // application version.
     539               0 :     if (!GetVersionFile(updatesDir, versionFile) ||
     540               0 :         IsOlderVersion(versionFile, appVersion)) {
     541               0 :       updatesDir->Remove(true);
     542                 :     } else {
     543                 :       ApplyUpdate(greDir, updatesDir, statusFile, appDir, 
     544               0 :                   argc, argv);
     545                 :     }
     546                 :   }
     547                 : 
     548               0 :   return NS_OK;
     549            4392 : }

Generated by: LCOV version 1.7