1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/mozapps/update/tests/shared.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,639 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +/* Shared code for xpcshell and mochitests-chrome */ 1.9 + 1.10 +// const Cc, Ci, and Cr are defined in netwerk/test/httpserver/httpd.js so we 1.11 +// need to define unique ones. 1.12 +const AUS_Cc = Components.classes; 1.13 +const AUS_Ci = Components.interfaces; 1.14 +const AUS_Cr = Components.results; 1.15 +const AUS_Cu = Components.utils; 1.16 +const AUS_Cm = Components.manager; 1.17 + 1.18 +const PREF_APP_UPDATE_AUTO = "app.update.auto"; 1.19 +const PREF_APP_UPDATE_BACKGROUNDERRORS = "app.update.backgroundErrors"; 1.20 +const PREF_APP_UPDATE_BACKGROUNDMAXERRORS = "app.update.backgroundMaxErrors"; 1.21 +const PREF_APP_UPDATE_CERTS_BRANCH = "app.update.certs."; 1.22 +const PREF_APP_UPDATE_CERT_CHECKATTRS = "app.update.cert.checkAttributes"; 1.23 +const PREF_APP_UPDATE_CERT_ERRORS = "app.update.cert.errors"; 1.24 +const PREF_APP_UPDATE_CERT_MAXERRORS = "app.update.cert.maxErrors"; 1.25 +const PREF_APP_UPDATE_CERT_REQUIREBUILTIN = "app.update.cert.requireBuiltIn"; 1.26 +const PREF_APP_UPDATE_CHANNEL = "app.update.channel"; 1.27 +const PREF_APP_UPDATE_ENABLED = "app.update.enabled"; 1.28 +const PREF_APP_UPDATE_METRO_ENABLED = "app.update.metro.enabled"; 1.29 +const PREF_APP_UPDATE_IDLETIME = "app.update.idletime"; 1.30 +const PREF_APP_UPDATE_LOG = "app.update.log"; 1.31 +const PREF_APP_UPDATE_NEVER_BRANCH = "app.update.never."; 1.32 +const PREF_APP_UPDATE_NOTIFIEDUNSUPPORTED = "app.update.notifiedUnsupported"; 1.33 +const PREF_APP_UPDATE_PROMPTWAITTIME = "app.update.promptWaitTime"; 1.34 +const PREF_APP_UPDATE_SERVICE_ENABLED = "app.update.service.enabled"; 1.35 +const PREF_APP_UPDATE_SHOW_INSTALLED_UI = "app.update.showInstalledUI"; 1.36 +const PREF_APP_UPDATE_SILENT = "app.update.silent"; 1.37 +const PREF_APP_UPDATE_STAGING_ENABLED = "app.update.staging.enabled"; 1.38 +const PREF_APP_UPDATE_URL = "app.update.url"; 1.39 +const PREF_APP_UPDATE_URL_DETAILS = "app.update.url.details"; 1.40 +const PREF_APP_UPDATE_URL_OVERRIDE = "app.update.url.override"; 1.41 +const PREF_APP_UPDATE_SOCKET_ERRORS = "app.update.socket.maxErrors"; 1.42 +const PREF_APP_UPDATE_RETRY_TIMEOUT = "app.update.socket.retryTimeout"; 1.43 + 1.44 +const PREF_APP_UPDATE_CERT_INVALID_ATTR_NAME = PREF_APP_UPDATE_CERTS_BRANCH + 1.45 + "1.invalidName"; 1.46 + 1.47 +const PREF_APP_PARTNER_BRANCH = "app.partner."; 1.48 +const PREF_DISTRIBUTION_ID = "distribution.id"; 1.49 +const PREF_DISTRIBUTION_VERSION = "distribution.version"; 1.50 + 1.51 +const PREF_EXTENSIONS_UPDATE_URL = "extensions.update.url"; 1.52 +const PREF_EXTENSIONS_STRICT_COMPAT = "extensions.strictCompatibility"; 1.53 + 1.54 +const NS_APP_PROFILE_DIR_STARTUP = "ProfDS"; 1.55 +const NS_APP_USER_PROFILE_50_DIR = "ProfD"; 1.56 +const NS_GRE_DIR = "GreD"; 1.57 +const NS_XPCOM_CURRENT_PROCESS_DIR = "XCurProcD"; 1.58 +const XRE_EXECUTABLE_FILE = "XREExeF"; 1.59 +const XRE_UPDATE_ROOT_DIR = "UpdRootD"; 1.60 + 1.61 +const CRC_ERROR = 4; 1.62 +const WRITE_ERROR = 7; 1.63 + 1.64 +const DIR_PATCH = "0"; 1.65 +const DIR_TOBEDELETED = "tobedeleted"; 1.66 +const DIR_UPDATES = "updates"; 1.67 +#ifdef XP_MACOSX 1.68 +const DIR_BIN_REL_PATH = "Contents/MacOS/"; 1.69 +const DIR_UPDATED = "Updated.app"; 1.70 +#else 1.71 +const DIR_BIN_REL_PATH = ""; 1.72 +const DIR_UPDATED = "updated"; 1.73 +#endif 1.74 + 1.75 +const FILE_BACKUP_LOG = "backup-update.log"; 1.76 +const FILE_LAST_LOG = "last-update.log"; 1.77 +const FILE_UPDATER_INI = "updater.ini"; 1.78 +const FILE_UPDATES_DB = "updates.xml"; 1.79 +const FILE_UPDATE_ACTIVE = "active-update.xml"; 1.80 +const FILE_UPDATE_ARCHIVE = "update.mar"; 1.81 +const FILE_UPDATE_LOG = "update.log"; 1.82 +const FILE_UPDATE_SETTINGS_INI = "update-settings.ini"; 1.83 +const FILE_UPDATE_SETTINGS_INI_BAK = "update-settings.ini.bak"; 1.84 +const FILE_UPDATE_STATUS = "update.status"; 1.85 +const FILE_UPDATE_VERSION = "update.version"; 1.86 + 1.87 +const UPDATE_SETTINGS_CONTENTS = "[Settings]\n" + 1.88 + "ACCEPTED_MAR_CHANNEL_IDS=xpcshell-test\n" 1.89 + 1.90 +const PR_RDWR = 0x04; 1.91 +const PR_CREATE_FILE = 0x08; 1.92 +const PR_APPEND = 0x10; 1.93 +const PR_TRUNCATE = 0x20; 1.94 +const PR_SYNC = 0x40; 1.95 +const PR_EXCL = 0x80; 1.96 + 1.97 +const DEFAULT_UPDATE_VERSION = "999999.0"; 1.98 + 1.99 +var gChannel; 1.100 + 1.101 +#include sharedUpdateXML.js 1.102 + 1.103 +AUS_Cu.import("resource://gre/modules/FileUtils.jsm"); 1.104 +AUS_Cu.import("resource://gre/modules/Services.jsm"); 1.105 +AUS_Cu.import("resource://gre/modules/XPCOMUtils.jsm"); 1.106 + 1.107 +const PERMS_FILE = FileUtils.PERMS_FILE; 1.108 +const PERMS_DIRECTORY = FileUtils.PERMS_DIRECTORY; 1.109 + 1.110 +const MODE_RDONLY = FileUtils.MODE_RDONLY; 1.111 +const MODE_WRONLY = FileUtils.MODE_WRONLY; 1.112 +const MODE_RDWR = FileUtils.MODE_RDWR; 1.113 +const MODE_CREATE = FileUtils.MODE_CREATE; 1.114 +const MODE_APPEND = FileUtils.MODE_APPEND; 1.115 +const MODE_TRUNCATE = FileUtils.MODE_TRUNCATE; 1.116 + 1.117 +const URI_UPDATES_PROPERTIES = "chrome://mozapps/locale/update/updates.properties"; 1.118 +const gUpdateBundle = Services.strings.createBundle(URI_UPDATES_PROPERTIES); 1.119 + 1.120 +XPCOMUtils.defineLazyGetter(this, "gAUS", function test_gAUS() { 1.121 + return AUS_Cc["@mozilla.org/updates/update-service;1"]. 1.122 + getService(AUS_Ci.nsIApplicationUpdateService). 1.123 + QueryInterface(AUS_Ci.nsITimerCallback). 1.124 + QueryInterface(AUS_Ci.nsIObserver). 1.125 + QueryInterface(AUS_Ci.nsIUpdateCheckListener); 1.126 +}); 1.127 + 1.128 +XPCOMUtils.defineLazyServiceGetter(this, "gUpdateManager", 1.129 + "@mozilla.org/updates/update-manager;1", 1.130 + "nsIUpdateManager"); 1.131 + 1.132 +XPCOMUtils.defineLazyGetter(this, "gUpdateChecker", function test_gUC() { 1.133 + return AUS_Cc["@mozilla.org/updates/update-checker;1"]. 1.134 + createInstance(AUS_Ci.nsIUpdateChecker); 1.135 +}); 1.136 + 1.137 +XPCOMUtils.defineLazyGetter(this, "gUP", function test_gUP() { 1.138 + return AUS_Cc["@mozilla.org/updates/update-prompt;1"]. 1.139 + createInstance(AUS_Ci.nsIUpdatePrompt); 1.140 +}); 1.141 + 1.142 +XPCOMUtils.defineLazyGetter(this, "gDefaultPrefBranch", function test_gDPB() { 1.143 + return Services.prefs.getDefaultBranch(null); 1.144 +}); 1.145 + 1.146 +XPCOMUtils.defineLazyGetter(this, "gPrefRoot", function test_gPR() { 1.147 + return Services.prefs.getBranch(null); 1.148 +}); 1.149 + 1.150 +XPCOMUtils.defineLazyGetter(this, "gZipW", function test_gZipW() { 1.151 + return AUS_Cc["@mozilla.org/zipwriter;1"]. 1.152 + createInstance(AUS_Ci.nsIZipWriter); 1.153 +}); 1.154 + 1.155 +/* Initializes the update service stub */ 1.156 +function initUpdateServiceStub() { 1.157 + AUS_Cc["@mozilla.org/updates/update-service-stub;1"]. 1.158 + createInstance(AUS_Ci.nsISupports); 1.159 +} 1.160 + 1.161 +/* Reloads the update metadata from disk */ 1.162 +function reloadUpdateManagerData() { 1.163 + gUpdateManager.QueryInterface(AUS_Ci.nsIObserver). 1.164 + observe(null, "um-reload-update-data", ""); 1.165 +} 1.166 + 1.167 +/** 1.168 + * Sets the app.update.channel preference. 1.169 + * 1.170 + * @param aChannel 1.171 + * The update channel. 1.172 + */ 1.173 +function setUpdateChannel(aChannel) { 1.174 + gChannel = aChannel; 1.175 + debugDump("setting default pref " + PREF_APP_UPDATE_CHANNEL + " to " + gChannel); 1.176 + gDefaultPrefBranch.setCharPref(PREF_APP_UPDATE_CHANNEL, gChannel); 1.177 + gPrefRoot.addObserver(PREF_APP_UPDATE_CHANNEL, observer, false); 1.178 +} 1.179 + 1.180 +var observer = { 1.181 + observe: function(aSubject, aTopic, aData) { 1.182 + if (aTopic == "nsPref:changed" && aData == PREF_APP_UPDATE_CHANNEL) { 1.183 + var channel = gDefaultPrefBranch.getCharPref(PREF_APP_UPDATE_CHANNEL); 1.184 + if (channel != gChannel) { 1.185 + debugDump("Changing channel from " + channel + " to " + gChannel); 1.186 + gDefaultPrefBranch.setCharPref(PREF_APP_UPDATE_CHANNEL, gChannel); 1.187 + } 1.188 + } 1.189 + }, 1.190 + QueryInterface: XPCOMUtils.generateQI([AUS_Ci.nsIObserver]) 1.191 +}; 1.192 + 1.193 +/** 1.194 + * Sets the app.update.url.override preference. 1.195 + * 1.196 + * @param aURL 1.197 + * The update url. If not specified 'URL_HOST + "/update.xml"' will be 1.198 + * used. 1.199 + */ 1.200 +function setUpdateURLOverride(aURL) { 1.201 + let url = aURL ? aURL : URL_HOST + "/update.xml"; 1.202 + debugDump("setting " + PREF_APP_UPDATE_URL_OVERRIDE + " to " + url); 1.203 + Services.prefs.setCharPref(PREF_APP_UPDATE_URL_OVERRIDE, url); 1.204 +} 1.205 + 1.206 +/** 1.207 + * Returns either the active or regular update database XML file. 1.208 + * 1.209 + * @param isActiveUpdate 1.210 + * If true this will return the active-update.xml otherwise it will 1.211 + * return the updates.xml file. 1.212 + */ 1.213 +function getUpdatesXMLFile(aIsActiveUpdate) { 1.214 + var file = getUpdatesRootDir(); 1.215 + file.append(aIsActiveUpdate ? FILE_UPDATE_ACTIVE : FILE_UPDATES_DB); 1.216 + return file; 1.217 +} 1.218 + 1.219 +/** 1.220 + * Writes the updates specified to either the active-update.xml or the 1.221 + * updates.xml. 1.222 + * 1.223 + * @param aContent 1.224 + * The updates represented as a string to write to the XML file. 1.225 + * @param isActiveUpdate 1.226 + * If true this will write to the active-update.xml otherwise it will 1.227 + * write to the updates.xml file. 1.228 + */ 1.229 +function writeUpdatesToXMLFile(aContent, aIsActiveUpdate) { 1.230 + writeFile(getUpdatesXMLFile(aIsActiveUpdate), aContent); 1.231 +} 1.232 + 1.233 +/** 1.234 + * Writes the current update operation/state to a file in the patch 1.235 + * directory, indicating to the patching system that operations need 1.236 + * to be performed. 1.237 + * 1.238 + * @param aStatus 1.239 + * The status value to write. 1.240 + */ 1.241 +function writeStatusFile(aStatus) { 1.242 + let file = getUpdatesPatchDir(); 1.243 + file.append(FILE_UPDATE_STATUS); 1.244 + writeFile(file, aStatus + "\n"); 1.245 +} 1.246 + 1.247 +/** 1.248 + * Writes the current update version to a file in the patch directory, 1.249 + * indicating to the patching system the version of the update. 1.250 + * 1.251 + * @param aVersion 1.252 + * The version value to write. 1.253 + */ 1.254 +function writeVersionFile(aVersion) { 1.255 + let file = getUpdatesPatchDir(); 1.256 + file.append(FILE_UPDATE_VERSION); 1.257 + writeFile(file, aVersion + "\n"); 1.258 +} 1.259 + 1.260 +/** 1.261 + * Gets the root directory for the updates directory. 1.262 + * 1.263 + * @return nsIFile for the updates root directory. 1.264 + */ 1.265 +function getUpdatesRootDir() { 1.266 + return Services.dirsvc.get(XRE_UPDATE_ROOT_DIR, AUS_Ci.nsIFile); 1.267 +} 1.268 + 1.269 +/** 1.270 + * Gets the updates directory. 1.271 + * 1.272 + * @return nsIFile for the updates directory. 1.273 + */ 1.274 +function getUpdatesDir() { 1.275 + var dir = getUpdatesRootDir(); 1.276 + dir.append(DIR_UPDATES); 1.277 + return dir; 1.278 +} 1.279 + 1.280 +/** 1.281 + * Gets the directory for update patches. 1.282 + * 1.283 + * @return nsIFile for the updates directory. 1.284 + */ 1.285 +function getUpdatesPatchDir() { 1.286 + let dir = getUpdatesDir(); 1.287 + dir.append(DIR_PATCH); 1.288 + return dir; 1.289 +} 1.290 + 1.291 +/** 1.292 + * Writes text to a file. This will replace existing text if the file exists 1.293 + * and create the file if it doesn't exist. 1.294 + * 1.295 + * @param aFile 1.296 + * The file to write to. Will be created if it doesn't exist. 1.297 + * @param aText 1.298 + * The text to write to the file. If there is existing text it will be 1.299 + * replaced. 1.300 + */ 1.301 +function writeFile(aFile, aText) { 1.302 + var fos = AUS_Cc["@mozilla.org/network/file-output-stream;1"]. 1.303 + createInstance(AUS_Ci.nsIFileOutputStream); 1.304 + if (!aFile.exists()) 1.305 + aFile.create(AUS_Ci.nsILocalFile.NORMAL_FILE_TYPE, PERMS_FILE); 1.306 + fos.init(aFile, MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE, PERMS_FILE, 0); 1.307 + fos.write(aText, aText.length); 1.308 + fos.close(); 1.309 +} 1.310 + 1.311 +/** 1.312 + * Reads the current update operation/state in the status file in the patch 1.313 + * directory including the error code if it is present. 1.314 + * 1.315 + * @return The status value. 1.316 + */ 1.317 +function readStatusFile() { 1.318 + let file = getUpdatesPatchDir(); 1.319 + file.append(FILE_UPDATE_STATUS); 1.320 + 1.321 + if (!file.exists()) { 1.322 + logTestInfo("update status file does not exists! Path: " + file.path); 1.323 + return STATE_NONE; 1.324 + } 1.325 + 1.326 + return readFile(file).split("\n")[0]; 1.327 +} 1.328 + 1.329 +/** 1.330 + * Reads the current update operation/state in the status file in the patch 1.331 + * directory without the error code if it is present. 1.332 + * 1.333 + * @return The state value. 1.334 + */ 1.335 +function readStatusState() { 1.336 + return readStatusFile().split(": ")[0]; 1.337 +} 1.338 + 1.339 +/** 1.340 + * Reads the current update operation/state in the status file in the patch 1.341 + * directory with the error code. 1.342 + * 1.343 + * @return The state value. 1.344 + */ 1.345 +function readStatusFailedCode() { 1.346 + return readStatusFile().split(": ")[1]; 1.347 +} 1.348 + 1.349 +/** 1.350 + * Reads text from a file and returns the string. 1.351 + * 1.352 + * @param aFile 1.353 + * The file to read from. 1.354 + * @return The string of text read from the file. 1.355 + */ 1.356 +function readFile(aFile) { 1.357 + var fis = AUS_Cc["@mozilla.org/network/file-input-stream;1"]. 1.358 + createInstance(AUS_Ci.nsIFileInputStream); 1.359 + if (!aFile.exists()) 1.360 + return null; 1.361 + fis.init(aFile, MODE_RDONLY, PERMS_FILE, 0); 1.362 + var sis = AUS_Cc["@mozilla.org/scriptableinputstream;1"]. 1.363 + createInstance(AUS_Ci.nsIScriptableInputStream); 1.364 + sis.init(fis); 1.365 + var text = sis.read(sis.available()); 1.366 + sis.close(); 1.367 + return text; 1.368 +} 1.369 + 1.370 +/** 1.371 + * Reads the binary contents of a file and returns it as a string. 1.372 + * 1.373 + * @param aFile 1.374 + * The file to read from. 1.375 + * @return The contents of the file as a string. 1.376 + */ 1.377 +function readFileBytes(aFile) { 1.378 + var fis = AUS_Cc["@mozilla.org/network/file-input-stream;1"]. 1.379 + createInstance(AUS_Ci.nsIFileInputStream); 1.380 + fis.init(aFile, -1, -1, false); 1.381 + var bis = AUS_Cc["@mozilla.org/binaryinputstream;1"]. 1.382 + createInstance(AUS_Ci.nsIBinaryInputStream); 1.383 + bis.setInputStream(fis); 1.384 + var data = []; 1.385 + var count = fis.available(); 1.386 + while (count > 0) { 1.387 + var bytes = bis.readByteArray(Math.min(65535, count)); 1.388 + data.push(String.fromCharCode.apply(null, bytes)); 1.389 + count -= bytes.length; 1.390 + if (bytes.length == 0) 1.391 + throw "Nothing read from input stream!"; 1.392 + } 1.393 + data.join(''); 1.394 + fis.close(); 1.395 + return data.toString(); 1.396 +} 1.397 + 1.398 +/* Returns human readable status text from the updates.properties bundle */ 1.399 +function getStatusText(aErrCode) { 1.400 + return getString("check_error-" + aErrCode); 1.401 +} 1.402 + 1.403 +/* Returns a string from the updates.properties bundle */ 1.404 +function getString(aName) { 1.405 + try { 1.406 + return gUpdateBundle.GetStringFromName(aName); 1.407 + } catch (e) { 1.408 + } 1.409 + return null; 1.410 +} 1.411 + 1.412 +/** 1.413 + * Gets the file extension for an nsIFile. 1.414 + * 1.415 + * @param aFile 1.416 + * The file to get the file extension for. 1.417 + * @return The file extension. 1.418 + */ 1.419 +function getFileExtension(aFile) { 1.420 + return Services.io.newFileURI(aFile).QueryInterface(AUS_Ci.nsIURL). 1.421 + fileExtension; 1.422 +} 1.423 + 1.424 +/** 1.425 + * Removes the updates.xml file, active-update.xml file, and all files and 1.426 + * sub-directories in the updates directory except for the "0" sub-directory. 1.427 + * This prevents some tests from failing due to files being left behind when the 1.428 + * tests are interrupted. 1.429 + */ 1.430 +function removeUpdateDirsAndFiles() { 1.431 + var file = getUpdatesXMLFile(true); 1.432 + try { 1.433 + if (file.exists()) 1.434 + file.remove(false); 1.435 + } catch (e) { 1.436 + dump("Unable to remove file\nPath: " + file.path + 1.437 + "\nException: " + e + "\n"); 1.438 + } 1.439 + 1.440 + file = getUpdatesXMLFile(false); 1.441 + try { 1.442 + if (file.exists()) 1.443 + file.remove(false); 1.444 + } catch (e) { 1.445 + dump("Unable to remove file\nPath: " + file.path + 1.446 + "\nException: " + e + "\n"); 1.447 + } 1.448 + 1.449 + // This fails sporadically on Mac OS X so wrap it in a try catch 1.450 + var updatesDir = getUpdatesDir(); 1.451 + try { 1.452 + cleanUpdatesDir(updatesDir); 1.453 + } catch (e) { 1.454 + dump("Unable to remove files / directories from directory\nPath: " + 1.455 + updatesDir.path + "\nException: " + e + "\n"); 1.456 + } 1.457 +} 1.458 + 1.459 +/** 1.460 + * Removes all files and sub-directories in the updates directory except for 1.461 + * the "0" sub-directory. 1.462 + * 1.463 + * @param aDir 1.464 + * nsIFile for the directory to be deleted. 1.465 + */ 1.466 +function cleanUpdatesDir(aDir) { 1.467 + if (!aDir.exists()) 1.468 + return; 1.469 + 1.470 + var dirEntries = aDir.directoryEntries; 1.471 + while (dirEntries.hasMoreElements()) { 1.472 + var entry = dirEntries.getNext().QueryInterface(AUS_Ci.nsIFile); 1.473 + 1.474 + if (entry.isDirectory()) { 1.475 + if (entry.leafName == DIR_PATCH && entry.parent.leafName == DIR_UPDATES) { 1.476 + cleanUpdatesDir(entry); 1.477 + entry.permissions = PERMS_DIRECTORY; 1.478 + } else { 1.479 + try { 1.480 + entry.remove(true); 1.481 + return; 1.482 + } catch (e) { 1.483 + } 1.484 + cleanUpdatesDir(entry); 1.485 + entry.permissions = PERMS_DIRECTORY; 1.486 + try { 1.487 + entry.remove(true); 1.488 + } catch (e) { 1.489 + dump("cleanUpdatesDir: unable to remove directory\nPath: " + 1.490 + entry.path + "\nException: " + e + "\n"); 1.491 + throw(e); 1.492 + } 1.493 + } 1.494 + } else { 1.495 + entry.permissions = PERMS_FILE; 1.496 + try { 1.497 + entry.remove(false); 1.498 + } catch (e) { 1.499 + dump("cleanUpdatesDir: unable to remove file\nPath: " + entry.path + 1.500 + "\nException: " + e + "\n"); 1.501 + throw(e); 1.502 + } 1.503 + } 1.504 + } 1.505 +} 1.506 + 1.507 +/** 1.508 + * Deletes a directory and its children. First it tries nsIFile::Remove(true). 1.509 + * If that fails it will fall back to recursing, setting the appropriate 1.510 + * permissions, and deleting the current entry. 1.511 + * 1.512 + * @param aDir 1.513 + * nsIFile for the directory to be deleted. 1.514 + */ 1.515 +function removeDirRecursive(aDir) { 1.516 + if (!aDir.exists()) { 1.517 + return; 1.518 + } 1.519 + 1.520 + try { 1.521 + logTestInfo("attempting to remove directory. Path: " + aDir.path); 1.522 + aDir.remove(true); 1.523 + return; 1.524 + } catch (e) { 1.525 + logTestInfo("non-fatal error removing directory. Exception: " + e); 1.526 + } 1.527 + 1.528 + var dirEntries = aDir.directoryEntries; 1.529 + while (dirEntries.hasMoreElements()) { 1.530 + var entry = dirEntries.getNext().QueryInterface(AUS_Ci.nsIFile); 1.531 + 1.532 + if (entry.isDirectory()) { 1.533 + removeDirRecursive(entry); 1.534 + } else { 1.535 + entry.permissions = PERMS_FILE; 1.536 + try { 1.537 + logTestInfo("attempting to remove file. Path: " + entry.path); 1.538 + entry.remove(false); 1.539 + } catch (e) { 1.540 + logTestInfo("error removing file. Exception: " + e); 1.541 + throw(e); 1.542 + } 1.543 + } 1.544 + } 1.545 + 1.546 + aDir.permissions = PERMS_DIRECTORY; 1.547 + try { 1.548 + logTestInfo("attempting to remove directory. Path: " + aDir.path); 1.549 + aDir.remove(true); 1.550 + } catch (e) { 1.551 + logTestInfo("error removing directory. Exception: " + e); 1.552 + throw(e); 1.553 + } 1.554 +} 1.555 + 1.556 +/** 1.557 + * Returns the directory for the currently running process. This is used to 1.558 + * clean up after the tests and to locate the active-update.xml and updates.xml 1.559 + * files. 1.560 + * 1.561 + * @return nsIFile for the current process directory. 1.562 + */ 1.563 +function getCurrentProcessDir() { 1.564 + return Services.dirsvc.get(NS_XPCOM_CURRENT_PROCESS_DIR, AUS_Ci.nsIFile); 1.565 +} 1.566 + 1.567 +/** 1.568 + * Gets the application base directory. 1.569 + * 1.570 + * @return nsIFile object for the application base directory. 1.571 + */ 1.572 +function getAppBaseDir() { 1.573 + return Services.dirsvc.get(XRE_EXECUTABLE_FILE, AUS_Ci.nsIFile).parent; 1.574 +} 1.575 + 1.576 +/** 1.577 + * Returns the Gecko Runtime Engine directory. This is used to locate the the 1.578 + * updater binary (Windows and Linux) or updater package (Mac OS X). For 1.579 + * XULRunner applications this is different than the currently running process 1.580 + * directory. 1.581 + * 1.582 + * @return nsIFile for the Gecko Runtime Engine directory. 1.583 + */ 1.584 +function getGREDir() { 1.585 + return Services.dirsvc.get(NS_GRE_DIR, AUS_Ci.nsIFile); 1.586 +} 1.587 + 1.588 +/** 1.589 + * Get the "updated" directory inside the directory where we apply the 1.590 + * staged updates. 1.591 + * @return The active updates directory inside the updated directory, as a 1.592 + * nsIFile object. 1.593 + */ 1.594 +function getUpdatedDir() { 1.595 + let dir = getAppBaseDir(); 1.596 +#ifdef XP_MACOSX 1.597 + dir = dir.parent.parent; // the bundle directory 1.598 +#endif 1.599 + dir.append(DIR_UPDATED); 1.600 + logTestInfo("updated directory path: " + dir.path); 1.601 + return dir; 1.602 +} 1.603 + 1.604 +/** 1.605 + * Logs TEST-INFO messages. 1.606 + * 1.607 + * @param aText 1.608 + * The text to log. 1.609 + * @param aCaller (optional) 1.610 + * An optional Components.stack.caller. If not specified 1.611 + * Components.stack.caller will be used. 1.612 + */ 1.613 +function logTestInfo(aText, aCaller) { 1.614 + let caller = (aCaller ? aCaller : Components.stack.caller); 1.615 + let now = new Date; 1.616 + let hh = now.getHours(); 1.617 + let mm = now.getMinutes(); 1.618 + let ss = now.getSeconds(); 1.619 + let ms = now.getMilliseconds(); 1.620 + let time = (hh < 10 ? "0" + hh : hh) + ":" + 1.621 + (mm < 10 ? "0" + mm : mm) + ":" + 1.622 + (ss < 10 ? "0" + ss : ss) + ":" + 1.623 + (ms < 10 ? "00" + ms : ms < 100 ? "0" + ms : ms); 1.624 + dump(time + " | TEST-INFO | " + caller.filename + " | [" + caller.name + 1.625 + " : " + caller.lineNumber + "] " + aText + "\n"); 1.626 +} 1.627 + 1.628 +/** 1.629 + * Logs TEST-INFO messages when DEBUG_AUS_TEST evaluates to true. 1.630 + * 1.631 + * @param aText 1.632 + * The text to log. 1.633 + * @param aCaller (optional) 1.634 + * An optional Components.stack.caller. If not specified 1.635 + * Components.stack.caller will be used. 1.636 + */ 1.637 +function debugDump(aText, aCaller) { 1.638 + if (DEBUG_AUS_TEST) { 1.639 + let caller = aCaller ? aCaller : Components.stack.caller; 1.640 + logTestInfo(aText, caller); 1.641 + } 1.642 +}