Mac V2 signing - Bug 1077268 - Make app update tests use the GreBinD dir service key implemented in bug 1077099. r=spohl
authorRobert Strong <robert.bugzilla@gmail.com>
Fri, 10 Oct 2014 06:15:13 -0700
changeset 209854 311c125897e53e66c7c74fb9a935b88562771008
parent 209853 28be76cd55cf317e313bc5366ef6a6b3118213d3
child 209855 e0662f559c632a79ce1021e0eada0953590d14ce
push id27628
push userkwierso@gmail.com
push dateSat, 11 Oct 2014 02:00:16 +0000
treeherdermozilla-central@f74ad36bb97b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersspohl
bugs1077268, 1077099
milestone35.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Mac V2 signing - Bug 1077268 - Make app update tests use the GreBinD dir service key implemented in bug 1077099. r=spohl
toolkit/mozapps/update/tests/shared.js
toolkit/mozapps/update/tests/unit_aus_update/head_update.js
toolkit/xre/nsUpdateDriver.cpp
--- a/toolkit/mozapps/update/tests/shared.js
+++ b/toolkit/mozapps/update/tests/shared.js
@@ -46,34 +46,34 @@ const PREF_DISTRIBUTION_ID              
 const PREF_DISTRIBUTION_VERSION           = "distribution.version";
 
 const PREF_EXTENSIONS_UPDATE_URL          = "extensions.update.url";
 const PREF_EXTENSIONS_STRICT_COMPAT       = "extensions.strictCompatibility";
 
 const NS_APP_PROFILE_DIR_STARTUP   = "ProfDS";
 const NS_APP_USER_PROFILE_50_DIR   = "ProfD";
 const NS_GRE_DIR                   = "GreD";
+const NS_GRE_BIN_DIR               = "GreBinD";
 const NS_XPCOM_CURRENT_PROCESS_DIR = "XCurProcD";
 const XRE_EXECUTABLE_FILE          = "XREExeF";
 const XRE_UPDATE_ROOT_DIR          = "UpdRootD";
 
 const CRC_ERROR   = 4;
 const WRITE_ERROR = 7;
 
 const DIR_PATCH        = "0";
 const DIR_TOBEDELETED  = "tobedeleted";
 const DIR_UPDATES      = "updates";
 #ifdef XP_MACOSX
-const DIR_BIN_REL_PATH = "Contents/MacOS/";
 const DIR_UPDATED      = "Updated.app";
 #else
-const DIR_BIN_REL_PATH = "";
 const DIR_UPDATED      = "updated";
 #endif
 
+const FILE_APPLICATION_INI           = "application.ini";
 const FILE_BACKUP_LOG                = "backup-update.log";
 const FILE_LAST_LOG                  = "last-update.log";
 const FILE_UPDATER_INI               = "updater.ini";
 const FILE_UPDATES_DB                = "updates.xml";
 const FILE_UPDATE_ACTIVE             = "active-update.xml";
 const FILE_UPDATE_ARCHIVE            = "update.mar";
 const FILE_UPDATE_LOG                = "update.log";
 const FILE_UPDATE_SETTINGS_INI       = "update-settings.ini";
@@ -566,28 +566,40 @@ function getCurrentProcessDir() {
  *
  * @return  nsIFile object for the application base directory.
  */
 function getAppBaseDir() {
   return Services.dirsvc.get(XRE_EXECUTABLE_FILE, AUS_Ci.nsIFile).parent;
 }
 
 /**
- * Returns the Gecko Runtime Engine directory. This is used to locate the the
- * updater binary (Windows and Linux) or updater package (Mac OS X). For
- * XULRunner applications this is different than the currently running process
- * directory.
+ * Returns the Gecko Runtime Engine directory where files other than executable
+ * binaries are located. On Mac OS X this will be <bundle>/Contents/Resources/
+ * and the installation directory on all other platforms.
  *
  * @return nsIFile for the Gecko Runtime Engine directory.
  */
 function getGREDir() {
   return Services.dirsvc.get(NS_GRE_DIR, AUS_Ci.nsIFile);
 }
 
 /**
+ * Returns the Gecko Runtime Engine Binary directory where the executable
+ * binaries are located such as the updater binary (Windows and Linux) or
+ * updater package (Mac OS X). On Mac OS X this will be
+ * <bundle>/Contents/MacOS/ and the installation directory on all other
+ * platforms.
+ *
+ * @return nsIFile for the Gecko Runtime Engine Binary directory.
+ */
+function getGREBinDir() {
+  return Services.dirsvc.get(NS_GRE_BIN_DIR, AUS_Ci.nsIFile);
+}
+
+/**
  * Logs TEST-INFO messages.
  *
  * @param  aText
  *         The text to log.
  * @param  aCaller (optional)
  *         An optional Components.stack.caller. If not specified
  *         Components.stack.caller will be used.
  */
--- a/toolkit/mozapps/update/tests/unit_aus_update/head_update.js
+++ b/toolkit/mozapps/update/tests/unit_aus_update/head_update.js
@@ -170,16 +170,17 @@ var gStatusCode;
 var gStatusText;
 var gStatusResult;
 
 var gProcess;
 var gAppTimer;
 var gHandle;
 
 var gGREDirOrig;
+var gGREBinDirOrig;
 var gAppDirOrig;
 
 var gServiceLaunchedCallbackLog = null;
 var gServiceLaunchedCallbackArgs = null;
 
 // Variables are used instead of contants so tests can override these values if
 // necessary.
 var gCallbackBinFile = "callback_app" + BIN_SUFFIX;
@@ -829,16 +830,17 @@ function setupTestCommon() {
       dump = dumpOverride;
     }
   }
 
   // Don't attempt to show a prompt when an update finishes.
   Services.prefs.setBoolPref(PREF_APP_UPDATE_SILENT, true);
 
   gGREDirOrig = getGREDir();
+  gGREBinDirOrig = getGREBinDir();
   gAppDirOrig = getAppBaseDir();
 
   let applyDir = getApplyDirFile(null, true).parent;
 
   // Try to remove the directory used to apply updates and the updates directory
   // on platforms other than Windows. Since the test hasn't ran yet and the
   // directory shouldn't exist finished this is non-fatal for the test.
   if (applyDir.exists()) {
@@ -1123,23 +1125,23 @@ function pathHandler(aMetadata, aRespons
  * application.ini file.
  *
  * @return  The version string from the application.ini file.
  * @throws  If the application.ini file is not found.
  */
 function getAppVersion() {
   // Read the application.ini and use its application version.
   let iniFile = gGREDirOrig.clone();
-  iniFile.append("application.ini");
+  iniFile.append(FILE_APPLICATION_INI);
   if (!iniFile.exists()) {
-    iniFile = gAppDirOrig.clone();
-    iniFile.append("application.ini");
-  }
-  if (!iniFile.exists()) {
-    do_throw("Unable to find application.ini!");
+    iniFile = gGREBinDirOrig.clone();
+    iniFile.append(FILE_APPLICATION_INI);
+    if (!iniFile.exists()) {
+      do_throw("Unable to find application.ini!");
+    }
   }
   let iniParser = AUS_Cc["@mozilla.org/xpcom/ini-parser-factory;1"].
                   getService(AUS_Ci.nsIINIParserFactory).
                   createINIParser(iniFile);
   return iniParser.getString("App", "Version");
 }
 
 /**
@@ -1411,17 +1413,17 @@ function getMockUpdRootD() {
 #else
 /**
  * Helper function for getting the update root directory used by the tests. This
  * returns the same directory as returned by nsXREDirProvider::GetUpdateRootDir
  * in nsXREDirProvider.cpp so an application will be able to find the update
  * when running a test that launches the application.
  */
 function getMockUpdRootD() {
-  return getApplyDirFile(DIR_BIN_REL_PATH, true);
+  return getApplyDirFile(DIR_MACOS, true);
 }
 #endif
 
 if (IS_WIN) {
   const kLockFileName = "updated.update_in_progress.lock";
   /**
    * Helper function for locking a directory on Windows.
    *
@@ -1468,17 +1470,17 @@ if (IS_WIN) {
  * @param   aCallback (optional)
  *          A callback function that will be called when this function finishes.
  *          If null no function will be called when this function finishes.
  *          If not specified the checkUpdateApplied function will be called when
  *          this function finishes.
  */
 function runUpdate(aExpectedExitValue, aExpectedStatus, aCallback) {
   // Copy the updater binary to the updates directory.
-  let binDir = gAppDirOrig.clone();
+  let binDir = gGREBinDirOrig.clone();
   let updater = binDir.clone();
   updater.append("updater.app");
   if (!updater.exists()) {
     updater = binDir.clone();
     updater.append(FILE_UPDATER_BIN);
     if (!updater.exists()) {
       do_throw("Unable to find updater binary!");
     }
@@ -1568,31 +1570,32 @@ function runUpdate(aExpectedExitValue, a
   if (aCallback !== null) {
     if (typeof(aCallback) == typeof(Function)) {
       aCallback();
     } else {
       checkUpdateApplied();
     }
   }
 }
+
 /**
  * Helper function for updater tests to stage an update.
  */
 function stageUpdate() {
-  logTestInfo("start - staging update");
+  logTestInfo("start - attempting to stage update");
   Services.obs.addObserver(gUpdateStagedObserver, "update-staged", false);
 
   setEnvironment();
   // Stage the update.
   AUS_Cc["@mozilla.org/updates/update-processor;1"].
     createInstance(AUS_Ci.nsIUpdateProcessor).
     processUpdate(gUpdateManager.activeUpdate);
   resetEnvironment();
 
-  logTestInfo("finish - staging update");
+  logTestInfo("finish - attempting to stage update");
 }
 
 /**
  * Helper function to check whether the maintenance service updater tests should
  * run. See bug 711660 for more details.
  *
  * @param  aFirstTest
  *         Whether this is the first test within the test.
@@ -1600,17 +1603,17 @@ function stageUpdate() {
  *         Whether to skip this test if the installed maintenance service
  *         isn't the same as the build's maintenance service. This is a
  *         temporary workaround until all build systems grant write access to
  *         the maintenance service install directory so the tests can copy the
  *         version of the maintenance service that should be tests.
  * @return true if the test should run and false if it shouldn't.
  */
 function shouldRunServiceTest(aFirstTest, aSkipTest) {
-  let binDir = getGREDir();
+  let binDir = getGREBinDir();
   let updaterBin = binDir.clone();
   updaterBin.append(FILE_UPDATER_BIN);
   if (!updaterBin.exists()) {
     do_throw("Unable to find updater binary!");
   }
 
   let updaterBinPath = updaterBin.path;
   if (/ /.test(updaterBinPath)) {
@@ -1725,117 +1728,126 @@ function setupAppFilesAsync() {
  * Helper function for setting up the application files required to launch the
  * application for the updater tests by either copying or creating symlinks to
  * the files.
  */
 function setupAppFiles() {
   logTestInfo("start - copying or creating symlinks to application files " +
               "for the test");
 
-  let srcDir = getCurrentProcessDir();
   let destDir = getApplyDirFile(null, true);
   if (!destDir.exists()) {
     try {
       destDir.create(AUS_Ci.nsIFile.DIRECTORY_TYPE, PERMS_DIRECTORY);
     } catch (e) {
       logTestInfo("unable to create directory, Path: " + destDir.path +
                   ", Exception: " + e);
       do_throw(e);
     }
   }
 
   // Required files for the application or the test that aren't listed in the
   // dependentlibs.list file.
-  let fileRelPaths = [ { src: FILE_APP_BIN },
-                       { src: FILE_UPDATER_BIN} ];
-  if (IS_MACOSX) {
-    fileRelPaths.push( { src: "../Resources/application.ini", dst: "../Resources/application.ini" } );
-    fileRelPaths.push( { src: "../Resources/dependentlibs.list", dst: "../Resources/dependentlibs.list" } );
-  } else {
-    fileRelPaths.push( { src: "application.ini" } );
-    fileRelPaths.push( { src: "dependentlibs.list" } );
-  }
+  let appFiles = [ { relPath  : FILE_APP_BIN,
+                     inGreDir : false },
+                   { relPath  : FILE_UPDATER_BIN,
+                     inGreDir : false },
+                   { relPath  : FILE_APPLICATION_INI,
+                     inGreDir : true },
+                   { relPath  : "dependentlibs.list",
+                     inGreDir : true } ];
 
   // On Linux the updater.png must also be copied
   if (IS_UNIX && !IS_MACOSX) {
-    fileRelPaths.push( { src: "icons/updater.png" } );
+    appFiles.push( { relPath  : "icons/updater.png",
+                     inGreDir : true } );
   }
 
   // Read the dependent libs file leafnames from the dependentlibs.list file
   // into the array.
-  let deplibsFile = srcDir.clone();
+  let deplibsFile = gGREDirOrig.clone();
   deplibsFile.append("dependentlibs.list");
   let istream = AUS_Cc["@mozilla.org/network/file-input-stream;1"].
                 createInstance(AUS_Ci.nsIFileInputStream);
   istream.init(deplibsFile, 0x01, 0o444, 0);
   istream.QueryInterface(AUS_Ci.nsILineInputStream);
 
   let hasMore;
   let line = {};
   do {
     hasMore = istream.readLine(line);
-    fileRelPaths.push( { src: line.value } );
+    appFiles.push( { relPath  : line.value,
+                     inGreDir : false } );
   } while(hasMore);
 
   istream.close();
 
-  fileRelPaths.forEach(function CMAF_FLN_FE(aFileRelPath) {
-    copyFileToTestAppDir(aFileRelPath.src, aFileRelPath.dst ? aFileRelPath.dst
-                                                            : null);
+  appFiles.forEach(function CMAF_FLN_FE(aAppFile) {
+    copyFileToTestAppDir(aAppFile.relPath, aAppFile.inGreDir);
   });
 
   logTestInfo("finish - copying or creating symlinks to application files " +
               "for the test");
 }
 
 /**
  * Copies the specified files from the dist/bin directory into the test's
  * application directory.
  *
  * @param  aFileRelPath
- *         The relative path of the file to copy.
- * @param  aDestFileRelPath (optional)
- *         The relative path of the destination file.
+ *         The relative path to the source and the destination of the file to
+ *         copy.
+ * @param  aInGreDir
+ *         Whether the file is located in the GRE directory which is
+ *         <bundle>/Contents/Resources on Mac OS X and is the installation
+ *         directory on all other platforms. If false the file must be in the
+ *         GRE Binary directory which is <bundle>/Contents/MacOS on Mac OS X and
+ *         is the installation directory on on all other platforms.
  */
-function copyFileToTestAppDir(aFileRelPath, aDestFileRelPath) {
+function copyFileToTestAppDir(aFileRelPath, aInGreDir) {
+  // gGREDirOrig and gGREBinDirOrig must always be cloned when changing its
+  // properties
+  let srcFile = aInGreDir ? gGREDirOrig.clone() : gGREBinDirOrig.clone();
+  let destFile = aInGreDir ? getGREDir() : getGREBinDir();
   let fileRelPath = aFileRelPath;
-  let srcFile = gAppDirOrig.clone();
   let pathParts = fileRelPath.split("/");
   for (let i = 0; i < pathParts.length; i++) {
     if (pathParts[i]) {
       srcFile.append(pathParts[i]);
+      destFile.append(pathParts[i]);
     }
   }
 
   if (IS_MACOSX && !srcFile.exists()) {
     logTestInfo("unable to copy file since it doesn't exist! Checking if " +
                  fileRelPath + ".app exists. Path: " +
                  srcFile.path);
-    srcFile = gAppDirOrig.clone();
+    // gGREDirOrig and gGREBinDirOrig must always be cloned when changing its
+    // properties
+    srcFile = aInGreDir ? gGREDirOrig.clone() : gGREBinDirOrig.clone();
+    destFile = aInGreDir ? getGREDir() : getGREBinDir();
     for (let i = 0; i < pathParts.length; i++) {
       if (pathParts[i]) {
         srcFile.append(pathParts[i] + (pathParts.length - 1 == i ? ".app" : ""));
+        destFile.append(pathParts[i] + (pathParts.length - 1 == i ? ".app" : ""));
       }
     }
     fileRelPath = fileRelPath + ".app";
   }
 
   if (!srcFile.exists()) {
     do_throw("Unable to copy file since it doesn't exist! Path: " +
              srcFile.path);
   }
 
   // Symlink libraries. Note that the XUL library on Mac OS X doesn't have a
-  // file extension and this will always be false on Windows.
+  // file extension and shouldSymlink will always be false on Windows.
   let shouldSymlink = (pathParts[pathParts.length - 1] == "XUL" ||
                        fileRelPath.substr(fileRelPath.length - 3) == ".so" ||
                        fileRelPath.substr(fileRelPath.length - 6) == ".dylib");
-  let destFile = getApplyDirFile(DIR_BIN_REL_PATH +
-                                 (aDestFileRelPath ? aDestFileRelPath
-                                                   : fileRelPath), true);
   if (!shouldSymlink) {
     if (!destFile.exists()) {
       try {
         srcFile.copyToFollowingLinks(destFile.parent, destFile.leafName);
       } catch (e) {
         // Just in case it is partially copied
         if (destFile.exists()) {
           try {
@@ -1904,17 +1916,17 @@ function attemptServiceInstall(aSkipTest
     do_throw("maintenance service install directory doesn't exist!");
   }
   let oldMaintSvcBin = maintSvcDir.clone();
   oldMaintSvcBin.append(FILE_MAINTENANCE_SERVICE_BIN);
   if (!oldMaintSvcBin.exists()) {
     do_throw("maintenance service install directory binary doesn't exist! " +
              "Path: " + oldMaintSvcBin.path);
   }
-  let buildMaintSvcBin = getGREDir();
+  let buildMaintSvcBin = getGREBinDir();
   buildMaintSvcBin.append(FILE_MAINTENANCE_SERVICE_BIN);
   if (readFileBytes(oldMaintSvcBin) == readFileBytes(buildMaintSvcBin)) {
     logTestInfo("installed maintenance service binary is the same as the " +
                 "build's maintenance service binary");
     return true;
   }
   let backupMaintSvcBin = maintSvcDir.clone();
   backupMaintSvcBin.append(FILE_MAINTENANCE_SERVICE_BIN + ".backup");
@@ -2089,24 +2101,24 @@ function runUpdateUsingService(aInitialS
     gShouldResetEnv = undefined;
   }
 
   setEnvironment();
 
   // There is a security check done by the service to make sure the updater
   // we are executing is the same as the one in the apply-to dir.
   // To make sure they match from tests we copy updater.exe to the apply-to dir.
-  copyFileToTestAppDir(FILE_UPDATER_BIN);
+  copyFileToTestAppDir(FILE_UPDATER_BIN, false);
 
   // The service will execute maintenanceservice_installer.exe and
   // will copy maintenanceservice.exe out of the same directory from
   // the installation directory.  So we need to make sure both of those
   // bins always exist in the installation directory.
-  copyFileToTestAppDir(FILE_MAINTENANCE_SERVICE_BIN);
-  copyFileToTestAppDir(FILE_MAINTENANCE_SERVICE_INSTALLER_BIN);
+  copyFileToTestAppDir(FILE_MAINTENANCE_SERVICE_BIN, false);
+  copyFileToTestAppDir(FILE_MAINTENANCE_SERVICE_INSTALLER_BIN, false);
 
   let launchBin = getLaunchBin();
   let args = getProcessArgs(["-dump-args", appArgsLogPath]);
 
   let process = AUS_Cc["@mozilla.org/process/util;1"].
                    createInstance(AUS_Ci.nsIProcess);
   process.init(launchBin);
   logTestInfo("launching " + launchBin.path + " " + args.join(" "));
@@ -2399,18 +2411,17 @@ function createUpdaterINI(aIsExeAsync) {
                            "ExeRelPath=" + DIR_RESOURCES + gPostUpdateBinFile + "\n" +
                            exeArg +
                            exeAsync +
                            "\n" +
                            "[PostUpdateWin]\n" +
                            "ExeRelPath=" + gPostUpdateBinFile + "\n" +
                            exeArg +
                            exeAsync;
-  let updaterIni = getApplyDirFile((IS_MACOSX ? "Contents/Resources/" : "") +
-                                    FILE_UPDATER_INI, true);
+  let updaterIni = getApplyDirFile(DIR_RESOURCES + FILE_UPDATER_INI, true);
   writeFile(updaterIni, updaterIniContents);
 }
 
 /**
  * Helper function for updater binary tests for verifying the contents of the
  * update log after a successful update.
  *
  * @param   aCompareLogFile
@@ -3316,17 +3327,17 @@ function createAppInfo(aID, aName, aVers
  * and stderr to null. This is needed to prevent output from the application
  * from ending up in the xpchsell log.
  */
 function getProcessArgs(aExtraArgs) {
   if (!aExtraArgs) {
     aExtraArgs = [];
   }
 
-  let appBinPath = getApplyDirFile(DIR_BIN_REL_PATH + FILE_APP_BIN, false).path;
+  let appBinPath = getApplyDirFile(DIR_MACOS + FILE_APP_BIN, false).path;
   if (/ /.test(appBinPath)) {
     appBinPath = '"' + appBinPath + '"';
   }
 
   let args;
   if (IS_UNIX) {
     let launchScript = getLaunchScript();
     // Precreate the script with executable permissions
@@ -3386,38 +3397,44 @@ function getLaunchScript() {
  */
 function adjustGeneralPaths() {
   let dirProvider = {
     getFile: function AGP_DP_getFile(aProp, aPersistent) {
       aPersistent.value = true;
       switch (aProp) {
         case NS_GRE_DIR:
           if (gUseTestAppDir) {
-            return getApplyDirFile(DIR_BIN_REL_PATH, true);
+            return getApplyDirFile(DIR_RESOURCES, true);
+          }
+          break;
+        case NS_GRE_BIN_DIR:
+          if (gUseTestAppDir) {
+            return getApplyDirFile(DIR_MACOS, true);
           }
           break;
         case XRE_EXECUTABLE_FILE:
           if (gUseTestAppDir) {
-            return getApplyDirFile(DIR_BIN_REL_PATH + FILE_APP_BIN, true);
+            return getApplyDirFile(DIR_MACOS + FILE_APP_BIN, true);
           }
           break;
         case XRE_UPDATE_ROOT_DIR:
           return getMockUpdRootD();
       }
       return null;
     },
     QueryInterface: function(aIID) {
       if (aIID.equals(AUS_Ci.nsIDirectoryServiceProvider) ||
           aIID.equals(AUS_Ci.nsISupports))
         return this;
       throw AUS_Cr.NS_ERROR_NO_INTERFACE;
     }
   };
   let ds = Services.dirsvc.QueryInterface(AUS_Ci.nsIDirectoryService);
   ds.QueryInterface(AUS_Ci.nsIProperties).undefine(NS_GRE_DIR);
+  ds.QueryInterface(AUS_Ci.nsIProperties).undefine(NS_GRE_BIN_DIR);
   ds.QueryInterface(AUS_Ci.nsIProperties).undefine(XRE_EXECUTABLE_FILE);
   ds.registerProvider(dirProvider);
   do_register_cleanup(function AGP_cleanup() {
     logTestInfo("start - unregistering directory provider");
 
     if (gAppTimer) {
       logTestInfo("start - cancel app timer");
       gAppTimer.cancel();
@@ -3469,17 +3486,17 @@ function adjustGeneralPaths() {
 
 
 /**
  * Helper function for launching the application to apply an update.
  */
 function launchAppToApplyUpdate() {
   logTestInfo("start - launching application to apply update");
 
-  let appBin = getApplyDirFile(DIR_BIN_REL_PATH + FILE_APP_BIN, false);
+  let appBin = getApplyDirFile(DIR_MACOS + FILE_APP_BIN, false);
 
   if (typeof(customLaunchAppToApplyUpdate) == typeof(Function)) {
     customLaunchAppToApplyUpdate();
   }
 
   let launchBin = getLaunchBin();
   let args = getProcessArgs();
   logTestInfo("launching " + launchBin.path + " " + args.join(" "));
@@ -3563,49 +3580,49 @@ function setEnvironment() {
   if (IS_WIN && !env.exists("XRE_NO_WINDOWS_CRASH_DIALOG")) {
     gAddedEnvXRENoWindowsCrashDialog = true;
     logTestInfo("setting the XRE_NO_WINDOWS_CRASH_DIALOG environment " +
                 "variable to 1... previously it didn't exist");
     env.set("XRE_NO_WINDOWS_CRASH_DIALOG", "1");
   }
 
   if (IS_UNIX) {
-    let appGreDir = gGREDirOrig.clone();
-    let envGreDir = AUS_Cc["@mozilla.org/file/local;1"].
-                    createInstance(AUS_Ci.nsILocalFile);
+    let appGreBinDir = gGREBinDirOrig.clone();
+    let envGreBinDir = AUS_Cc["@mozilla.org/file/local;1"].
+                       createInstance(AUS_Ci.nsILocalFile);
     let shouldSetEnv = true;
     if (IS_MACOSX) {
       if (env.exists("DYLD_LIBRARY_PATH")) {
         gEnvDyldLibraryPath = env.get("DYLD_LIBRARY_PATH");
-        envGreDir.initWithPath(gEnvDyldLibraryPath);
-        if (envGreDir.path == appGreDir.path) {
+        envGreBinDir.initWithPath(gEnvDyldLibraryPath);
+        if (envGreBinDir.path == appGreBinDir.path) {
           gEnvDyldLibraryPath = null;
           shouldSetEnv = false;
         }
       }
 
       if (shouldSetEnv) {
         logTestInfo("setting DYLD_LIBRARY_PATH environment variable value to " +
-                    appGreDir.path);
-        env.set("DYLD_LIBRARY_PATH", appGreDir.path);
+                    appGreBinDir.path);
+        env.set("DYLD_LIBRARY_PATH", appGreBinDir.path);
       }
     } else {
       if (env.exists("LD_LIBRARY_PATH")) {
         gEnvLdLibraryPath = env.get("LD_LIBRARY_PATH");
-        envGreDir.initWithPath(gEnvLdLibraryPath);
-        if (envGreDir.path == appGreDir.path) {
+        envGreBinDir.initWithPath(gEnvLdLibraryPath);
+        if (envGreBinDir.path == appGreBinDir.path) {
           gEnvLdLibraryPath = null;
           shouldSetEnv = false;
         }
       }
 
       if (shouldSetEnv) {
         logTestInfo("setting LD_LIBRARY_PATH environment variable value to " +
-                    appGreDir.path);
-        env.set("LD_LIBRARY_PATH", appGreDir.path);
+                    appGreBinDir.path);
+        env.set("LD_LIBRARY_PATH", appGreBinDir.path);
       }
     }
   }
 
   if (env.exists("XPCOM_MEM_LEAK_LOG")) {
     gEnvXPCOMMemLeakLog = env.get("XPCOM_MEM_LEAK_LOG");
     logTestInfo("removing the XPCOM_MEM_LEAK_LOG environment variable... " +
                 "previous value " + gEnvXPCOMMemLeakLog);
--- a/toolkit/xre/nsUpdateDriver.cpp
+++ b/toolkit/xre/nsUpdateDriver.cpp
@@ -1087,22 +1087,28 @@ nsUpdateProcessor::ProcessUpdate(nsIUpda
       do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
     if (!ds) {
       NS_ABORT(); // There's nothing which we can do if this fails!
     }
 
     nsresult rv = ds->Get(NS_GRE_DIR, NS_GET_IID(nsIFile),
                           getter_AddRefs(greDir));
     NS_ASSERTION(NS_SUCCEEDED(rv), "Can't get the GRE dir");
-    appDir = greDir;
+
+    nsCOMPtr<nsIFile> exeFile;
+    rv = ds->Get(XRE_EXECUTABLE_FILE, NS_GET_IID(nsIFile),
+                 getter_AddRefs(exeFile));
+    if (NS_SUCCEEDED(rv))
+      rv = exeFile->GetParent(getter_AddRefs(appDir));
+
+    NS_ASSERTION(NS_SUCCEEDED(rv), "Can't get the XREExeF parent dir");
 
     rv = ds->Get(XRE_UPDATE_ROOT_DIR, NS_GET_IID(nsIFile),
                  getter_AddRefs(updRoot));
-    if (NS_FAILED(rv))
-      updRoot = appDir;
+    NS_ASSERTION(NS_SUCCEEDED(rv), "Can't get the UpdRootD dir");
 
     nsCOMPtr<nsIXULAppInfo> appInfo =
       do_GetService("@mozilla.org/xre/app-info;1");
     if (appInfo) {
       rv = appInfo->GetVersion(appVersion);
       NS_ENSURE_SUCCESS(rv, rv);
     } else {
       appVersion = MOZ_APP_VERSION;