import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

View file

@ -0,0 +1,7 @@
"use strict";
module.exports = {
"extends": [
"../../../../../testing/xpcshell/xpcshell.eslintrc.js"
]
};

View file

@ -0,0 +1,138 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
function run_test() {
setupTestCommon();
// Verify write access to the custom app dir
debugDump("testing write access to the application directory");
let testFile = getCurrentProcessDir();
testFile.append("update_write_access_test");
testFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, PERMS_FILE);
Assert.ok(testFile.exists(), MSG_SHOULD_EXIST);
testFile.remove(false);
Assert.ok(!testFile.exists(), MSG_SHOULD_NOT_EXIST);
standardInit();
if (IS_WIN) {
// Create a mutex to prevent being able to check for or apply updates.
debugDump("attempting to create mutex");
let handle = createMutex(getPerInstallationMutexName());
Assert.ok(!!handle, "the update mutex should have been created");
// Check if available updates cannot be checked for when there is a mutex
// for this installation.
Assert.ok(!gAUS.canCheckForUpdates, "should not be able to check for " +
"updates when there is an update mutex");
// Check if updates cannot be applied when there is a mutex for this
// installation.
Assert.ok(!gAUS.canApplyUpdates, "should not be able to apply updates " +
"when there is an update mutex");
debugDump("destroying mutex");
closeHandle(handle);
}
// Check if available updates can be checked for
Assert.ok(gAUS.canCheckForUpdates, "should be able to check for updates");
// Check if updates can be applied
Assert.ok(gAUS.canApplyUpdates, "should be able to apply updates");
if (IS_WIN) {
// Attempt to create a mutex when application update has already created one
// with the same name.
debugDump("attempting to create mutex");
let handle = createMutex(getPerInstallationMutexName());
Assert.ok(!handle, "should not be able to create the update mutex when " +
"the application has created the update mutex");
}
doTestFinish();
}
/**
* Determines a unique mutex name for the installation.
*
* @return Global mutex path.
*/
function getPerInstallationMutexName() {
if (!IS_WIN) {
do_throw("Windows only function called by a different platform!");
}
let hasher = Cc["@mozilla.org/security/hash;1"].
createInstance(Ci.nsICryptoHash);
hasher.init(hasher.SHA1);
let exeFile = Services.dirsvc.get(XRE_EXECUTABLE_FILE, Ci.nsILocalFile);
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
createInstance(Ci.nsIScriptableUnicodeConverter);
converter.charset = "UTF-8";
let data = converter.convertToByteArray(exeFile.path.toLowerCase());
hasher.update(data, data.length);
return "Global\\MozillaUpdateMutex-" + hasher.finish(true);
}
/**
* Closes a Win32 handle.
*
* @param aHandle
* The handle to close.
*/
function closeHandle(aHandle) {
if (!IS_WIN) {
do_throw("Windows only function called by a different platform!");
}
let lib = ctypes.open("kernel32.dll");
let CloseHandle = lib.declare("CloseHandle",
ctypes.winapi_abi,
ctypes.int32_t, /* success */
ctypes.void_t.ptr); /* handle */
CloseHandle(aHandle);
lib.close();
}
/**
* Creates a mutex.
*
* @param aName
* The name for the mutex.
* @return The Win32 handle to the mutex.
*/
function createMutex(aName) {
if (!IS_WIN) {
do_throw("Windows only function called by a different platform!");
}
const INITIAL_OWN = 1;
const ERROR_ALREADY_EXISTS = 0xB7;
let lib = ctypes.open("kernel32.dll");
let CreateMutexW = lib.declare("CreateMutexW",
ctypes.winapi_abi,
ctypes.void_t.ptr, /* return handle */
ctypes.void_t.ptr, /* security attributes */
ctypes.int32_t, /* initial owner */
ctypes.char16_t.ptr); /* name */
let handle = CreateMutexW(null, INITIAL_OWN, aName);
lib.close();
let alreadyExists = ctypes.winLastError == ERROR_ALREADY_EXISTS;
if (handle && !handle.isNull() && alreadyExists) {
closeHandle(handle);
handle = null;
}
if (handle && handle.isNull()) {
handle = null;
}
return handle;
}

View file

@ -0,0 +1,46 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/* General Update Manager Tests */
function run_test() {
setupTestCommon();
debugDump("testing removal of an active update for a channel that is not" +
"valid due to switching channels (Bug 486275).");
let patches = getLocalPatchString(null, null, null, null, null, null,
STATE_DOWNLOADING);
let updates = getLocalUpdateString(patches, null, null, "version 1.0", "1.0");
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
writeStatusFile(STATE_DOWNLOADING);
patches = getLocalPatchString(null, null, null, null, null, null,
STATE_FAILED);
updates = getLocalUpdateString(patches, null, "Existing", "version 3.0",
"3.0", "3.0", null, null, null, null,
getString("patchApplyFailure"));
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), false);
setUpdateChannel("original_channel");
standardInit();
Assert.equal(gUpdateManager.updateCount, 1,
"the update manager update count" + MSG_SHOULD_EQUAL);
let update = gUpdateManager.getUpdateAt(0);
Assert.equal(update.name, "Existing",
"the update's name" + MSG_SHOULD_EQUAL);
Assert.ok(!gUpdateManager.activeUpdate,
"there should not be an active update");
// Verify that the active-update.xml file has had the update from the old
// channel removed.
let file = getUpdatesXMLFile(true);
Assert.equal(readFile(file), getLocalUpdatesXMLString(""),
"the contents of active-update.xml" + MSG_SHOULD_EQUAL);
doTestFinish();
}

View file

@ -0,0 +1,29 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
function run_test() {
setupTestCommon();
debugDump("testing cleanup of an update download in progress for an " +
"older version of the application on startup (Bug 485624)");
let patches = getLocalPatchString(null, null, null, null, null, null,
STATE_DOWNLOADING);
let updates = getLocalUpdateString(patches, null, null, "version 0.9", "0.9");
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
writeStatusFile(STATE_DOWNLOADING);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
standardInit();
Assert.ok(!gUpdateManager.activeUpdate,
"there should not be an active update");
Assert.equal(gUpdateManager.updateCount, 0,
"the update manager update count" + MSG_SHOULD_EQUAL);
doTestFinish();
}

View file

@ -0,0 +1,30 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
function run_test() {
setupTestCommon();
debugDump("testing removal of an update download in progress for the " +
"same version of the application with the same application " +
"build id on startup (Bug 536547)");
let patches = getLocalPatchString(null, null, null, null, null, null,
STATE_DOWNLOADING);
let updates = getLocalUpdateString(patches, null, null, "version 1.0", "1.0",
"2007010101");
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
writeStatusFile(STATE_DOWNLOADING);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
standardInit();
Assert.ok(!gUpdateManager.activeUpdate,
"there should not be an active update");
Assert.equal(gUpdateManager.updateCount, 0,
"the update manager update count" + MSG_SHOULD_EQUAL);
doTestFinish();
}

View file

@ -0,0 +1,35 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
function run_test() {
setupTestCommon();
debugDump("testing update cleanup when reading the status file returns " +
"STATUS_NONE and the update xml has an update with " +
"STATE_DOWNLOADING (Bug 539717).");
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
let patches = getLocalPatchString(null, null, null, null, null, null,
STATE_DOWNLOADING);
let updates = getLocalUpdateString(patches);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
writeStatusFile(STATE_NONE);
standardInit();
let dir = getUpdatesDir();
dir.append(DIR_PATCH);
Assert.ok(dir.exists(), MSG_SHOULD_EXIST);
let statusFile = dir.clone();
statusFile.append(FILE_UPDATE_STATUS);
Assert.ok(!statusFile.exists(), MSG_SHOULD_NOT_EXIST);
Assert.ok(!gUpdateManager.activeUpdate,
"there should not be an active update");
Assert.equal(gUpdateManager.updateCount, 0,
"the update manager update count" + MSG_SHOULD_EQUAL);
doTestFinish();
}

View file

@ -0,0 +1,37 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
function run_test() {
setupTestCommon();
debugDump("testing update cleanup when reading the status file returns " +
"STATUS_NONE, the version file is for a newer version, and the " +
"update xml has an update with STATE_PENDING (Bug 601701).");
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
let patches = getLocalPatchString(null, null, null, null, null, null,
STATE_PENDING);
let updates = getLocalUpdateString(patches);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
writeVersionFile("99.9");
standardInit();
// Check that there is no activeUpdate first so the updates directory is
// cleaned up by the UpdateManager before the remaining tests.
Assert.ok(!gUpdateManager.activeUpdate,
"there should not be an active update");
Assert.equal(gUpdateManager.updateCount, 0,
"the update manager update count" + MSG_SHOULD_EQUAL);
let dir = getUpdatesDir();
dir.append(DIR_PATCH);
Assert.ok(dir.exists(), MSG_SHOULD_EXIST);
let versionFile = dir.clone();
versionFile.append(FILE_UPDATE_VERSION);
Assert.ok(!versionFile.exists(), MSG_SHOULD_NOT_EXIST);
doTestFinish();
}

View file

@ -0,0 +1,37 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
function run_test() {
setupTestCommon();
debugDump("testing that the update.log is moved after a successful update");
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
let patches = getLocalPatchString(null, null, null, null, null, null,
STATE_PENDING);
let updates = getLocalUpdateString(patches);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
writeStatusFile(STATE_SUCCEEDED);
let log = getUpdateLog(FILE_UPDATE_LOG);
writeFile(log, "Last Update Log");
standardInit();
Assert.ok(!log.exists(), MSG_SHOULD_NOT_EXIST);
log = getUpdateLog(FILE_LAST_UPDATE_LOG);
Assert.ok(log.exists(), MSG_SHOULD_EXIST);
Assert.equal(readFile(log), "Last Update Log",
"the last update log contents" + MSG_SHOULD_EQUAL);
log = getUpdateLog(FILE_BACKUP_UPDATE_LOG);
Assert.ok(!log.exists(), MSG_SHOULD_NOT_EXIST);
let dir = getUpdatesPatchDir();
Assert.ok(dir.exists(), MSG_SHOULD_EXIST);
doTestFinish();
}

View file

@ -0,0 +1,45 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
function run_test() {
setupTestCommon();
debugDump("testing update logs are first in first out deleted");
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
let patches = getLocalPatchString(null, null, null, null, null, null,
STATE_PENDING);
let updates = getLocalUpdateString(patches);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
writeStatusFile(STATE_SUCCEEDED);
let log = getUpdateLog(FILE_LAST_UPDATE_LOG);
writeFile(log, "Backup Update Log");
log = getUpdateLog(FILE_BACKUP_UPDATE_LOG);
writeFile(log, "To Be Deleted Backup Update Log");
log = getUpdateLog(FILE_UPDATE_LOG);
writeFile(log, "Last Update Log");
standardInit();
Assert.ok(!log.exists(), MSG_SHOULD_NOT_EXIST);
log = getUpdateLog(FILE_LAST_UPDATE_LOG);
Assert.ok(log.exists(), MSG_SHOULD_EXIST);
Assert.equal(readFile(log), "Last Update Log",
"the last update log contents" + MSG_SHOULD_EQUAL);
log = getUpdateLog(FILE_BACKUP_UPDATE_LOG);
Assert.ok(log.exists(), MSG_SHOULD_EXIST);
Assert.equal(readFile(log), "Backup Update Log",
"the backup update log contents" + MSG_SHOULD_EQUAL);
let dir = getUpdatesPatchDir();
Assert.ok(dir.exists(), MSG_SHOULD_EXIST);
doTestFinish();
}

View file

@ -0,0 +1,161 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
var gNextRunFunc;
var gExpectedStatusResult;
function run_test() {
// The network code that downloads the mar file accesses the profile to cache
// the download, but the profile is only available after calling
// do_get_profile in xpcshell tests. This prevents an error from being logged.
do_get_profile();
setupTestCommon();
debugDump("testing mar download and mar hash verification");
Services.prefs.setBoolPref(PREF_APP_UPDATE_STAGING_ENABLED, false);
start_httpserver();
setUpdateURL(gURLData + gHTTPHandlerPath);
standardInit();
// Only perform the non hash check tests when mar signing is enabled since the
// update service doesn't perform hash checks when mar signing is enabled.
if (MOZ_VERIFY_MAR_SIGNATURE) {
do_execute_soon(run_test_pt11);
} else {
do_execute_soon(run_test_pt1);
}
}
// The HttpServer must be stopped before calling do_test_finished
function finish_test() {
stop_httpserver(doTestFinish);
}
// Helper function for testing mar downloads that have the correct size
// specified in the update xml.
function run_test_helper_pt1(aMsg, aExpectedStatusResult, aNextRunFunc) {
gUpdates = null;
gUpdateCount = null;
gStatusResult = null;
gCheckFunc = check_test_helper_pt1_1;
gNextRunFunc = aNextRunFunc;
gExpectedStatusResult = aExpectedStatusResult;
debugDump(aMsg, Components.stack.caller);
gUpdateChecker.checkForUpdates(updateCheckListener, true);
}
function check_test_helper_pt1_1() {
Assert.equal(gUpdateCount, 1,
"the update count" + MSG_SHOULD_EQUAL);
gCheckFunc = check_test_helper_pt1_2;
let bestUpdate = gAUS.selectUpdate(gUpdates, gUpdateCount);
let state = gAUS.downloadUpdate(bestUpdate, false);
if (state == STATE_NONE || state == STATE_FAILED) {
do_throw("nsIApplicationUpdateService:downloadUpdate returned " + state);
}
gAUS.addDownloadListener(downloadListener);
}
function check_test_helper_pt1_2() {
Assert.equal(gStatusResult, gExpectedStatusResult,
"the download status result" + MSG_SHOULD_EQUAL);
gAUS.removeDownloadListener(downloadListener);
gNextRunFunc();
}
function setResponseBody(aHashFunction, aHashValue, aSize) {
let patches = getRemotePatchString(null, null,
aHashFunction, aHashValue, aSize);
let updates = getRemoteUpdateString(patches);
gResponseBody = getRemoteUpdatesXMLString(updates);
}
// mar download with a valid MD5 hash
function run_test_pt1() {
setResponseBody("MD5", MD5_HASH_SIMPLE_MAR);
run_test_helper_pt1("mar download with a valid MD5 hash",
Cr.NS_OK, run_test_pt2);
}
// mar download with an invalid MD5 hash
function run_test_pt2() {
setResponseBody("MD5", MD5_HASH_SIMPLE_MAR + "0");
run_test_helper_pt1("mar download with an invalid MD5 hash",
Cr.NS_ERROR_CORRUPTED_CONTENT, run_test_pt3);
}
// mar download with a valid SHA1 hash
function run_test_pt3() {
setResponseBody("SHA1", SHA1_HASH_SIMPLE_MAR);
run_test_helper_pt1("mar download with a valid SHA1 hash",
Cr.NS_OK, run_test_pt4);
}
// mar download with an invalid SHA1 hash
function run_test_pt4() {
setResponseBody("SHA1", SHA1_HASH_SIMPLE_MAR + "0");
run_test_helper_pt1("mar download with an invalid SHA1 hash",
Cr.NS_ERROR_CORRUPTED_CONTENT, run_test_pt5);
}
// mar download with a valid SHA256 hash
function run_test_pt5() {
setResponseBody("SHA256", SHA256_HASH_SIMPLE_MAR);
run_test_helper_pt1("mar download with a valid SHA256 hash",
Cr.NS_OK, run_test_pt6);
}
// mar download with an invalid SHA256 hash
function run_test_pt6() {
setResponseBody("SHA256", SHA256_HASH_SIMPLE_MAR + "0");
run_test_helper_pt1("mar download with an invalid SHA256 hash",
Cr.NS_ERROR_CORRUPTED_CONTENT, run_test_pt7);
}
// mar download with a valid SHA384 hash
function run_test_pt7() {
setResponseBody("SHA384", SHA384_HASH_SIMPLE_MAR);
run_test_helper_pt1("mar download with a valid SHA384 hash",
Cr.NS_OK, run_test_pt8);
}
// mar download with an invalid SHA384 hash
function run_test_pt8() {
setResponseBody("SHA384", SHA384_HASH_SIMPLE_MAR + "0");
run_test_helper_pt1("mar download with an invalid SHA384 hash",
Cr.NS_ERROR_CORRUPTED_CONTENT, run_test_pt9);
}
// mar download with a valid SHA512 hash
function run_test_pt9() {
setResponseBody("SHA512", SHA512_HASH_SIMPLE_MAR);
run_test_helper_pt1("mar download with a valid SHA512 hash",
Cr.NS_OK, run_test_pt10);
}
// mar download with an invalid SHA512 hash
function run_test_pt10() {
setResponseBody("SHA512", SHA512_HASH_SIMPLE_MAR + "0");
run_test_helper_pt1("mar download with an invalid SHA512 hash",
Cr.NS_ERROR_CORRUPTED_CONTENT, run_test_pt11);
}
// mar download with the mar not found
function run_test_pt11() {
let patches = getRemotePatchString(null, gURLData + "missing.mar");
let updates = getRemoteUpdateString(patches);
gResponseBody = getRemoteUpdatesXMLString(updates);
run_test_helper_pt1("mar download with the mar not found",
Cr.NS_ERROR_UNEXPECTED, run_test_pt12);
}
// mar download with a valid MD5 hash but invalid file size
function run_test_pt12() {
const arbitraryFileSize = 1024000;
setResponseBody("MD5", MD5_HASH_SIMPLE_MAR, arbitraryFileSize);
run_test_helper_pt1("mar download with a valid MD5 hash but invalid file size",
Cr.NS_ERROR_UNEXPECTED, finish_test);
}

View file

@ -0,0 +1,66 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
Components.utils.import("resource://testing-common/MockRegistrar.jsm");
const WindowWatcher = {
getNewPrompter: function WW_getNewPrompter(aParent) {
Assert.ok(!aParent,
"the aParent parameter should not be defined");
return {
alert: function WW_GNP_alert(aTitle, aText) {
let title = getString("updaterIOErrorTitle");
Assert.equal(aTitle, title,
"the ui string for title" + MSG_SHOULD_EQUAL);
let text = gUpdateBundle.formatStringFromName("updaterIOErrorMsg",
[Services.appinfo.name,
Services.appinfo.name], 2);
Assert.equal(aText, text,
"the ui string for message" + MSG_SHOULD_EQUAL);
doTestFinish();
}
};
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWindowWatcher])
};
function run_test() {
setupTestCommon();
debugDump("testing download a complete on partial failure. Calling " +
"nsIUpdatePrompt::showUpdateError should call getNewPrompter " +
"and alert on the object returned by getNewPrompter when the " +
"update.state == " + STATE_FAILED + " and the update.errorCode " +
"== " + WRITE_ERROR + " (Bug 595059).");
Services.prefs.setBoolPref(PREF_APP_UPDATE_SILENT, false);
let windowWatcherCID =
MockRegistrar.register("@mozilla.org/embedcomp/window-watcher;1",
WindowWatcher);
do_register_cleanup(() => {
MockRegistrar.unregister(windowWatcherCID);
});
standardInit();
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
let url = URL_HOST + "/" + FILE_COMPLETE_MAR;
let patches = getLocalPatchString("complete", url, null, null, null, null,
STATE_FAILED);
let updates = getLocalUpdateString(patches, null, null, "version 1.0", "1.0",
null, null, null, null, url);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
writeStatusFile(STATE_FAILED);
reloadUpdateManagerData();
let update = gUpdateManager.activeUpdate;
update.errorCode = WRITE_ERROR;
let prompter = Cc["@mozilla.org/updates/update-prompt;1"].
createInstance(Ci.nsIUpdatePrompt);
prompter.showUpdateError(update);
}

View file

@ -0,0 +1,225 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/* General MAR File Download Tests */
Components.utils.import("resource://testing-common/MockRegistrar.jsm");
const INC_CONTRACT_ID = "@mozilla.org/network/incremental-download;1";
// gIncrementalDownloadErrorType is used to loop through each of the connection
// error types in the Mock incremental downloader.
var gIncrementalDownloadErrorType = 0;
var gNextRunFunc;
var gExpectedStatusResult;
function run_test() {
setupTestCommon();
debugDump("testing mar downloads, mar hash verification, and " +
"mar download interrupted recovery");
Services.prefs.setBoolPref(PREF_APP_UPDATE_STAGING_ENABLED, false);
start_httpserver();
setUpdateURL(gURLData + gHTTPHandlerPath);
standardInit();
do_execute_soon(run_test_pt1);
}
// The HttpServer must be stopped before calling do_test_finished
function finish_test() {
stop_httpserver(doTestFinish);
}
// Helper function for testing mar downloads that have the correct size
// specified in the update xml.
function run_test_helper_pt1(aMsg, aExpectedStatusResult, aNextRunFunc) {
gUpdates = null;
gUpdateCount = null;
gStatusResult = null;
gCheckFunc = check_test_helper_pt1_1;
gNextRunFunc = aNextRunFunc;
gExpectedStatusResult = aExpectedStatusResult;
debugDump(aMsg, Components.stack.caller);
gUpdateChecker.checkForUpdates(updateCheckListener, true);
}
function check_test_helper_pt1_1() {
Assert.equal(gUpdateCount, 1,
"the update count" + MSG_SHOULD_EQUAL);
gCheckFunc = check_test_helper_pt1_2;
let bestUpdate = gAUS.selectUpdate(gUpdates, gUpdateCount);
let state = gAUS.downloadUpdate(bestUpdate, false);
if (state == STATE_NONE || state == STATE_FAILED) {
do_throw("nsIApplicationUpdateService:downloadUpdate returned " + state);
}
gAUS.addDownloadListener(downloadListener);
}
function check_test_helper_pt1_2() {
Assert.equal(gStatusResult, gExpectedStatusResult,
"the download status result" + MSG_SHOULD_EQUAL);
gAUS.removeDownloadListener(downloadListener);
gNextRunFunc();
}
function setResponseBody(aHashFunction, aHashValue, aSize) {
let patches = getRemotePatchString(null, null,
aHashFunction, aHashValue, aSize);
let updates = getRemoteUpdateString(patches);
gResponseBody = getRemoteUpdatesXMLString(updates);
}
function initMockIncrementalDownload() {
let incrementalDownloadCID =
MockRegistrar.register(INC_CONTRACT_ID, IncrementalDownload);
do_register_cleanup(() => {
MockRegistrar.unregister(incrementalDownloadCID);
});
}
/* This Mock incremental downloader is used to verify that connection
* interrupts work correctly in updater code. The implementation of
* the mock incremental downloader is very simple, it simply copies
* the file to the destination location.
*/
function IncrementalDownload() {
this.wrappedJSObject = this;
}
IncrementalDownload.prototype = {
/* nsIIncrementalDownload */
init: function(uri, file, chunkSize, intervalInSeconds) {
this._destination = file;
this._URI = uri;
this._finalURI = uri;
},
start: function(observer, ctxt) {
let tm = Cc["@mozilla.org/thread-manager;1"].
getService(Ci.nsIThreadManager);
// Do the actual operation async to give a chance for observers
// to add themselves.
tm.mainThread.dispatch(function() {
this._observer = observer.QueryInterface(Ci.nsIRequestObserver);
this._ctxt = ctxt;
this._observer.onStartRequest(this, this._ctxt);
let mar = getTestDirFile(FILE_SIMPLE_MAR);
mar.copyTo(this._destination.parent, this._destination.leafName);
let status = Cr.NS_OK;
switch (gIncrementalDownloadErrorType++) {
case 0:
status = Cr.NS_ERROR_NET_RESET;
break;
case 1:
status = Cr.NS_ERROR_CONNECTION_REFUSED;
break;
case 2:
status = Cr.NS_ERROR_NET_RESET;
break;
case 3:
status = Cr.NS_OK;
break;
case 4:
status = Cr.NS_ERROR_OFFLINE;
// After we report offline, we want to eventually show offline
// status being changed to online.
let tm2 = Cc["@mozilla.org/thread-manager;1"].
getService(Ci.nsIThreadManager);
tm2.mainThread.dispatch(function() {
Services.obs.notifyObservers(gAUS,
"network:offline-status-changed",
"online");
}, Ci.nsIThread.DISPATCH_NORMAL);
break;
}
this._observer.onStopRequest(this, this._ctxt, status);
}.bind(this), Ci.nsIThread.DISPATCH_NORMAL);
},
get URI() {
return this._URI;
},
get currentSize() {
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
},
get destination() {
return this._destination;
},
get finalURI() {
return this._finalURI;
},
get totalSize() {
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
},
/* nsIRequest */
cancel: function(aStatus) {
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
},
suspend: function() {
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
},
isPending: function() {
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
},
_loadFlags: 0,
get loadFlags() {
return this._loadFlags;
},
set loadFlags(val) {
this._loadFlags = val;
},
_loadGroup: null,
get loadGroup() {
return this._loadGroup;
},
set loadGroup(val) {
this._loadGroup = val;
},
_name: "",
get name() {
return this._name;
},
_status: 0,
get status() {
return this._status;
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIIncrementalDownload])
};
// Test disconnecting during an update
function run_test_pt1() {
initMockIncrementalDownload();
setResponseBody("MD5", MD5_HASH_SIMPLE_MAR);
run_test_helper_pt1("mar download with connection interruption",
Cr.NS_OK, run_test_pt2);
}
// Test disconnecting during an update
function run_test_pt2() {
gIncrementalDownloadErrorType = 0;
Services.prefs.setIntPref(PREF_APP_UPDATE_SOCKET_MAXERRORS, 2);
Services.prefs.setIntPref(PREF_APP_UPDATE_RETRYTIMEOUT, 0);
setResponseBody("MD5", MD5_HASH_SIMPLE_MAR);
run_test_helper_pt1("mar download with connection interruption without recovery",
Cr.NS_ERROR_NET_RESET, run_test_pt3);
}
// Test entering offline mode while downloading
function run_test_pt3() {
gIncrementalDownloadErrorType = 4;
setResponseBody("MD5", MD5_HASH_SIMPLE_MAR);
run_test_helper_pt1("mar download with offline mode",
Cr.NS_OK, finish_test);
}

View file

@ -0,0 +1,37 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
function run_test() {
setupTestCommon();
debugDump("testing resuming an update download in progress for the same " +
"version of the application on startup (Bug 485624)");
let patches = getLocalPatchString(null, null, null, null, null, null,
STATE_DOWNLOADING);
let updates = getLocalUpdateString(patches, null, null, "1.0", "1.0");
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
writeStatusFile(STATE_DOWNLOADING);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
standardInit();
Assert.equal(gUpdateManager.updateCount, 1,
"the update manager updateCount attribute" + MSG_SHOULD_EQUAL);
Assert.equal(gUpdateManager.activeUpdate.state, STATE_DOWNLOADING,
"the update manager activeUpdate state attribute" +
MSG_SHOULD_EQUAL);
// Pause the download and reload the Update Manager with an empty update so
// the Application Update Service doesn't write the update xml files during
// xpcom-shutdown which will leave behind the test directory.
gAUS.pauseDownload();
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), true);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
reloadUpdateManagerData();
do_execute_soon(doTestFinish);
}

View file

@ -0,0 +1,8 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
const IS_SERVICE_TEST = false;
/* import-globals-from ../data/xpcshellUtilsAUS.js */
load("../data/xpcshellUtilsAUS.js");

View file

@ -0,0 +1,285 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
var gNextRunFunc;
var gExpectedCount;
function run_test() {
setupTestCommon();
debugDump("testing remote update xml attributes");
start_httpserver();
setUpdateURL(gURLData + gHTTPHandlerPath);
setUpdateChannel("test_channel");
// This test expects that the app.update.download.backgroundInterval
// preference doesn't already exist.
Services.prefs.deleteBranch("app.update.download.backgroundInterval");
standardInit();
do_execute_soon(run_test_pt01);
}
// Helper function for testing update counts returned from an update xml
function run_test_helper_pt1(aMsg, aExpectedCount, aNextRunFunc) {
gUpdates = null;
gUpdateCount = null;
gCheckFunc = check_test_helper_pt1;
gNextRunFunc = aNextRunFunc;
gExpectedCount = aExpectedCount;
debugDump(aMsg, Components.stack.caller);
gUpdateChecker.checkForUpdates(updateCheckListener, true);
}
function check_test_helper_pt1() {
Assert.equal(gUpdateCount, gExpectedCount,
"the update count" + MSG_SHOULD_EQUAL);
gNextRunFunc();
}
// update xml not found
function run_test_pt01() {
run_test_helper_pt1("testing update xml not available",
null, run_test_pt02);
}
// one update available and the update's property values
function run_test_pt02() {
debugDump("testing one update available and the update's property values");
gUpdates = null;
gUpdateCount = null;
gCheckFunc = check_test_pt02;
let patches = getRemotePatchString("complete", "http://complete/", "SHA1",
"98db9dad8e1d80eda7e1170d0187d6f53e477059",
"9856459");
patches += getRemotePatchString("partial", "http://partial/", "SHA1",
"e6678ca40ae7582316acdeddf3c133c9c8577de4",
"1316138");
let updates = getRemoteUpdateString(patches, "minor", "Minor Test",
"version 2.1a1pre", "2.1a1pre",
"20080811053724",
"http://details/",
"true",
"true", "345600", "1200",
"custom1_attr=\"custom1 value\"",
"custom2_attr=\"custom2 value\"");
gResponseBody = getRemoteUpdatesXMLString(updates);
gUpdateChecker.checkForUpdates(updateCheckListener, true);
}
function check_test_pt02() {
// XXXrstrong - not specifying a detailsURL will cause a leak due to bug 470244
// and until this is fixed this will not test the value for detailsURL when it
// isn't specified in the update xml.
// let defaultDetailsURL;
// try {
// Try using a default details URL supplied by the distribution
// if the update XML does not supply one.
// let formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].
// getService(Ci.nsIURLFormatter);
// defaultDetailsURL = formatter.formatURLPref(PREF_APP_UPDATE_URL_DETAILS);
// } catch (e) {
// defaultDetailsURL = "";
// }
Assert.equal(gUpdateCount, 1,
"the update count" + MSG_SHOULD_EQUAL);
let bestUpdate = gAUS.selectUpdate(gUpdates, gUpdateCount).QueryInterface(Ci.nsIPropertyBag);
Assert.equal(bestUpdate.type, "minor",
"the update type attribute" + MSG_SHOULD_EQUAL);
Assert.equal(bestUpdate.name, "Minor Test",
"the update name attribute" + MSG_SHOULD_EQUAL);
Assert.equal(bestUpdate.displayVersion, "version 2.1a1pre",
"the update displayVersion attribute" + MSG_SHOULD_EQUAL);
Assert.equal(bestUpdate.appVersion, "2.1a1pre",
"the update appVersion attribute" + MSG_SHOULD_EQUAL);
Assert.equal(bestUpdate.buildID, "20080811053724",
"the update buildID attribute" + MSG_SHOULD_EQUAL);
Assert.equal(bestUpdate.detailsURL, "http://details/",
"the update detailsURL attribute" + MSG_SHOULD_EQUAL);
Assert.ok(bestUpdate.showPrompt,
"the update showPrompt attribute" + MSG_SHOULD_EQUAL);
Assert.ok(bestUpdate.showNeverForVersion,
"the update showNeverForVersion attribute" + MSG_SHOULD_EQUAL);
Assert.equal(bestUpdate.promptWaitTime, "345600",
"the update promptWaitTime attribute" + MSG_SHOULD_EQUAL);
// The default and maximum value for backgroundInterval is 600
Assert.equal(bestUpdate.getProperty("backgroundInterval"), "600",
"the update backgroundInterval attribute" + MSG_SHOULD_EQUAL);
Assert.equal(bestUpdate.serviceURL, gURLData + gHTTPHandlerPath + "?force=1",
"the update serviceURL attribute" + MSG_SHOULD_EQUAL);
Assert.equal(bestUpdate.channel, "test_channel",
"the update channel attribute" + MSG_SHOULD_EQUAL);
Assert.ok(!bestUpdate.isCompleteUpdate,
"the update isCompleteUpdate attribute" + MSG_SHOULD_EQUAL);
Assert.ok(!bestUpdate.isSecurityUpdate,
"the update isSecurityUpdate attribute" + MSG_SHOULD_EQUAL);
// Check that installDate is within 10 seconds of the current date.
Assert.ok((Date.now() - bestUpdate.installDate) < 10000,
"the update installDate attribute should be within 10 seconds of " +
"the current time");
Assert.ok(!bestUpdate.statusText,
"the update statusText attribute" + MSG_SHOULD_EQUAL);
// nsIUpdate:state returns an empty string when no action has been performed
// on an available update
Assert.equal(bestUpdate.state, "",
"the update state attribute" + MSG_SHOULD_EQUAL);
Assert.equal(bestUpdate.errorCode, 0,
"the update errorCode attribute" + MSG_SHOULD_EQUAL);
Assert.equal(bestUpdate.patchCount, 2,
"the update patchCount attribute" + MSG_SHOULD_EQUAL);
// XXX TODO - test nsIUpdate:serialize
Assert.equal(bestUpdate.getProperty("custom1_attr"), "custom1 value",
"the update custom1_attr property" + MSG_SHOULD_EQUAL);
Assert.equal(bestUpdate.getProperty("custom2_attr"), "custom2 value",
"the update custom2_attr property" + MSG_SHOULD_EQUAL);
let patch = bestUpdate.getPatchAt(0);
Assert.equal(patch.type, "complete",
"the update patch type attribute" + MSG_SHOULD_EQUAL);
Assert.equal(patch.URL, "http://complete/",
"the update patch URL attribute" + MSG_SHOULD_EQUAL);
Assert.equal(patch.hashFunction, "SHA1",
"the update patch hashFunction attribute" + MSG_SHOULD_EQUAL);
Assert.equal(patch.hashValue, "98db9dad8e1d80eda7e1170d0187d6f53e477059",
"the update patch hashValue attribute" + MSG_SHOULD_EQUAL);
Assert.equal(patch.size, 9856459,
"the update patch size attribute" + MSG_SHOULD_EQUAL);
// The value for patch.state can be the string 'null' as a valid value. This
// is confusing if it returns null which is an invalid value since the test
// failure output will show a failure for null == null. To lessen the
// confusion first check that the typeof for patch.state is string.
Assert.equal(typeof patch.state, "string",
"the update patch state typeof value should equal |string|");
Assert.equal(patch.state, STATE_NONE,
"the update patch state attribute" + MSG_SHOULD_EQUAL);
Assert.ok(!patch.selected,
"the update patch selected attribute" + MSG_SHOULD_EQUAL);
// XXX TODO - test nsIUpdatePatch:serialize
patch = bestUpdate.getPatchAt(1);
Assert.equal(patch.type, "partial",
"the update patch type attribute" + MSG_SHOULD_EQUAL);
Assert.equal(patch.URL, "http://partial/",
"the update patch URL attribute" + MSG_SHOULD_EQUAL);
Assert.equal(patch.hashFunction, "SHA1",
"the update patch hashFunction attribute" + MSG_SHOULD_EQUAL);
Assert.equal(patch.hashValue, "e6678ca40ae7582316acdeddf3c133c9c8577de4",
"the update patch hashValue attribute" + MSG_SHOULD_EQUAL);
Assert.equal(patch.size, 1316138,
"the update patch size attribute" + MSG_SHOULD_EQUAL);
Assert.equal(patch.state, STATE_NONE,
"the update patch state attribute" + MSG_SHOULD_EQUAL);
Assert.ok(!patch.selected,
"the update patch selected attribute" + MSG_SHOULD_EQUAL);
// XXX TODO - test nsIUpdatePatch:serialize
run_test_pt03();
}
// Empty update xml (an empty xml file returns a root node name of parsererror)
function run_test_pt03() {
gResponseBody = "<parsererror/>";
run_test_helper_pt1("testing empty update xml",
null, run_test_pt04);
}
// no updates available
function run_test_pt04() {
gResponseBody = getRemoteUpdatesXMLString("");
run_test_helper_pt1("testing no updates available",
0, run_test_pt05);
}
// one update available with two patches
function run_test_pt05() {
let patches = getRemotePatchString("complete");
patches += getRemotePatchString("partial");
let updates = getRemoteUpdateString(patches);
gResponseBody = getRemoteUpdatesXMLString(updates);
run_test_helper_pt1("testing one update available",
1, run_test_pt06);
}
// three updates available each with two patches
function run_test_pt06() {
let patches = getRemotePatchString("complete");
patches += getRemotePatchString("partial");
let updates = getRemoteUpdateString(patches);
updates += getRemoteUpdateString(patches);
updates += getRemoteUpdateString(patches);
gResponseBody = getRemoteUpdatesXMLString(updates);
run_test_helper_pt1("testing three updates available",
3, run_test_pt07);
}
// one update with complete and partial patches with size 0 specified in the
// update xml
function run_test_pt07() {
let patches = getRemotePatchString("complete", null, null, null, "0");
patches += getRemotePatchString("partial", null, null, null, "0");
let updates = getRemoteUpdateString(patches);
gResponseBody = getRemoteUpdatesXMLString(updates);
run_test_helper_pt1("testing one update with complete and partial " +
"patches with size 0", 0, run_test_pt08);
}
// one update with complete patch with size 0 specified in the update xml
function run_test_pt08() {
let patches = getRemotePatchString("complete", null, null, null, "0");
let updates = getRemoteUpdateString(patches);
gResponseBody = getRemoteUpdatesXMLString(updates);
run_test_helper_pt1("testing one update with complete patch with size 0",
0, run_test_pt9);
}
// one update with partial patch with size 0 specified in the update xml
function run_test_pt9() {
let patches = getRemotePatchString("partial", null, null, null, "0");
let updates = getRemoteUpdateString(patches);
gResponseBody = getRemoteUpdatesXMLString(updates);
run_test_helper_pt1("testing one update with partial patch with size 0",
0, run_test_pt10);
}
// check that updates for older versions of the application aren't selected
function run_test_pt10() {
let patches = getRemotePatchString("complete");
patches += getRemotePatchString("partial");
let updates = getRemoteUpdateString(patches, "minor", null, null, "1.0pre");
updates += getRemoteUpdateString(patches, "minor", null, null, "1.0a");
gResponseBody = getRemoteUpdatesXMLString(updates);
run_test_helper_pt1("testing two updates older than the current version",
2, check_test_pt10);
}
function check_test_pt10() {
let bestUpdate = gAUS.selectUpdate(gUpdates, gUpdateCount);
Assert.ok(!bestUpdate,
"there should be no update available");
run_test_pt11();
}
// check that updates for the current version of the application are selected
function run_test_pt11() {
let patches = getRemotePatchString("complete");
patches += getRemotePatchString("partial");
let updates = getRemoteUpdateString(patches, "minor", null, "version 1.0");
gResponseBody = getRemoteUpdatesXMLString(updates);
run_test_helper_pt1("testing one update equal to the current version",
1, check_test_pt11);
}
function check_test_pt11() {
let bestUpdate = gAUS.selectUpdate(gUpdates, gUpdateCount);
Assert.ok(!!bestUpdate,
"there should be one update available");
Assert.equal(bestUpdate.displayVersion, "version 1.0",
"the update displayVersion attribute" + MSG_SHOULD_EQUAL);
doTestFinish();
}

View file

@ -0,0 +1,75 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
Components.utils.import("resource://testing-common/MockRegistrar.jsm");
const WindowWatcher = {
openWindow: function(aParent, aUrl, aName, aFeatures, aArgs) {
gCheckFunc();
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWindowWatcher])
};
const WindowMediator = {
getMostRecentWindow: function(aWindowType) {
do_execute_soon(check_status);
return { getInterface: XPCOMUtils.generateQI([Ci.nsIDOMWindow]) };
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWindowMediator])
};
function run_test() {
setupTestCommon();
// Calling do_get_profile prevents an error from being logged
do_get_profile();
debugDump("testing that an update download doesn't start when the " +
PREF_APP_UPDATE_AUTO + " preference is false");
Services.prefs.setBoolPref(PREF_APP_UPDATE_AUTO, false);
Services.prefs.setBoolPref(PREF_APP_UPDATE_SILENT, false);
start_httpserver();
setUpdateURL(gURLData + gHTTPHandlerPath);
standardInit();
let windowWatcherCID =
MockRegistrar.register("@mozilla.org/embedcomp/window-watcher;1",
WindowWatcher);
let windowMediatorCID =
MockRegistrar.register("@mozilla.org/appshell/window-mediator;1",
WindowMediator);
do_register_cleanup(() => {
MockRegistrar.unregister(windowWatcherCID);
MockRegistrar.unregister(windowMediatorCID);
});
gCheckFunc = check_showUpdateAvailable;
let patches = getRemotePatchString("complete");
let updates = getRemoteUpdateString(patches, "minor", null, null, "1.0");
gResponseBody = getRemoteUpdatesXMLString(updates);
gAUS.notify(null);
}
function check_status() {
let status = readStatusFile();
Assert.notEqual(status, STATE_DOWNLOADING,
"the update state" + MSG_SHOULD_EQUAL);
// Pause the download and reload the Update Manager with an empty update so
// the Application Update Service doesn't write the update xml files during
// xpcom-shutdown which will leave behind the test directory.
gAUS.pauseDownload();
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), true);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
reloadUpdateManagerData();
do_execute_soon(doTestFinish);
}
function check_showUpdateAvailable() {
do_throw("showUpdateAvailable should not have called openWindow!");
}

View file

@ -0,0 +1,76 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
Components.utils.import("resource://testing-common/MockRegistrar.jsm");
/**
* Test that nsIUpdatePrompt doesn't display UI for showUpdateAvailable and
* showUpdateError when the app.update.silent preference is true.
*/
const WindowWatcher = {
openWindow: function(aParent, aUrl, aName, aFeatures, aArgs) {
gCheckFunc();
},
getNewPrompter: function(aParent) {
gCheckFunc();
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWindowWatcher])
};
function run_test() {
setupTestCommon();
debugDump("testing nsIUpdatePrompt notifications should not be seen " +
"when the " + PREF_APP_UPDATE_SILENT + " preference is true");
Services.prefs.setBoolPref(PREF_APP_UPDATE_SILENT, true);
let windowWatcherCID =
MockRegistrar.register("@mozilla.org/embedcomp/window-watcher;1",
WindowWatcher);
do_register_cleanup(() => {
MockRegistrar.unregister(windowWatcherCID);
});
standardInit();
debugDump("testing showUpdateAvailable should not call openWindow");
writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
let patches = getLocalPatchString(null, null, null, null, null, null,
STATE_FAILED);
let updates = getLocalUpdateString(patches);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
writeStatusFile(STATE_FAILED);
reloadUpdateManagerData();
gCheckFunc = check_showUpdateAvailable;
let update = gUpdateManager.activeUpdate;
gUP.showUpdateAvailable(update);
// Report a successful check after the call to showUpdateAvailable since it
// didn't throw and otherwise it would report no tests run.
Assert.ok(true,
"calling showUpdateAvailable should not attempt to open a window");
debugDump("testing showUpdateError should not call getNewPrompter");
gCheckFunc = check_showUpdateError;
update.errorCode = WRITE_ERROR;
gUP.showUpdateError(update);
// Report a successful check after the call to showUpdateError since it
// didn't throw and otherwise it would report no tests run.
Assert.ok(true,
"calling showUpdateError should not attempt to open a window");
doTestFinish();
}
function check_showUpdateAvailable() {
do_throw("showUpdateAvailable should not have called openWindow!");
}
function check_showUpdateError() {
do_throw("showUpdateError should not have seen getNewPrompter!");
}

View file

@ -0,0 +1,74 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
Cu.import("resource://testing-common/MockRegistrar.jsm");
const WindowWatcher = {
openWindow: function(aParent, aUrl, aName, aFeatures, aArgs) {
check_showUpdateAvailable();
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWindowWatcher])
};
const WindowMediator = {
getMostRecentWindow: function(aWindowType) {
return null;
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWindowMediator])
};
function run_test() {
setupTestCommon();
debugDump("testing nsIUpdatePrompt notifications should not be displayed " +
"when showUpdateAvailable is called for an unsupported system " +
"update when the unsupported notification has already been " +
"shown (bug 843497)");
start_httpserver();
setUpdateURL(gURLData + gHTTPHandlerPath);
standardInit();
let windowWatcherCID =
MockRegistrar.register("@mozilla.org/embedcomp/window-watcher;1",
WindowWatcher);
let windowMediatorCID =
MockRegistrar.register("@mozilla.org/appshell/window-mediator;1",
WindowMediator);
do_register_cleanup(() => {
MockRegistrar.unregister(windowWatcherCID);
MockRegistrar.unregister(windowMediatorCID);
});
Services.prefs.setBoolPref(PREF_APP_UPDATE_SILENT, false);
Services.prefs.setBoolPref(PREF_APP_UPDATE_NOTIFIEDUNSUPPORTED, true);
// This preference is used to determine when the background update check has
// completed since a successful check will clear the preference.
Services.prefs.setIntPref(PREF_APP_UPDATE_BACKGROUNDERRORS, 1);
gResponseBody = getRemoteUpdatesXMLString(" <update type=\"major\" " +
"name=\"Unsupported Update\" " +
"unsupported=\"true\" " +
"detailsURL=\"" + URL_HOST +
"\"></update>\n");
gAUS.notify(null);
do_execute_soon(check_test);
}
function check_test() {
if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_BACKGROUNDERRORS)) {
do_execute_soon(check_test);
return;
}
Assert.ok(true,
PREF_APP_UPDATE_BACKGROUNDERRORS + " preference should not exist");
stop_httpserver(doTestFinish);
}
function check_showUpdateAvailable() {
do_throw("showUpdateAvailable should not have called openWindow!");
}

View file

@ -0,0 +1,177 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
function run_test() {
setupTestCommon();
debugDump("testing addition of a successful update to " + FILE_UPDATES_XML +
" and verification of update properties including the format " +
"prior to bug 530872");
setUpdateChannel("test_channel");
// This test expects that the app.update.download.backgroundInterval
// preference doesn't already exist.
Services.prefs.deleteBranch("app.update.download.backgroundInterval");
// XXXrstrong - not specifying a detailsURL will cause a leak due to bug 470244
// and until bug 470244 is fixed this will not test the value for detailsURL
// when it isn't specified in the update xml.
let patches = getLocalPatchString("partial", "http://partial/", "SHA256",
"cd43", "86", "true", STATE_PENDING);
let updates = getLocalUpdateString(patches, "major", "New", "version 4",
"4.0", "20070811053724",
"http://details1/",
"http://service1/", "1238441300314",
"test status text", "false",
"test_channel", "true", "true", "true",
"345600", "300", "3.0",
"custom1_attr=\"custom1 value\"",
"custom2_attr=\"custom2 value\"");
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
writeStatusFile(STATE_SUCCEEDED);
patches = getLocalPatchString("complete", "http://complete/", "SHA1", "6232",
"75", "true", STATE_FAILED);
updates = getLocalUpdateString(patches, "major", "Existing", null, "3.0",
null,
"http://details2/",
"http://service2/", null,
getString("patchApplyFailure"), "true",
"test_channel", "false", null, null, "691200",
null, null,
"custom3_attr=\"custom3 value\"",
"custom4_attr=\"custom4 value\"");
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), false);
standardInit();
Assert.ok(!gUpdateManager.activeUpdate,
"the update manager activeUpdate attribute" + MSG_SHOULD_EQUAL);
Assert.equal(gUpdateManager.updateCount, 2,
"the update manager updateCount attribute" + MSG_SHOULD_EQUAL);
debugDump("checking the activeUpdate properties");
let update = gUpdateManager.getUpdateAt(0).QueryInterface(Ci.nsIPropertyBag);
Assert.equal(update.state, STATE_SUCCEEDED,
"the update state attribute" + MSG_SHOULD_EQUAL);
Assert.equal(update.type, "major",
"the update type attribute" + MSG_SHOULD_EQUAL);
Assert.equal(update.name, "New",
"the update name attribute" + MSG_SHOULD_EQUAL);
Assert.equal(update.displayVersion, "version 4",
"the update displayVersion attribute" + MSG_SHOULD_EQUAL);
Assert.equal(update.appVersion, "4.0",
"the update appVersion attribute" + MSG_SHOULD_EQUAL);
Assert.equal(update.buildID, "20070811053724",
"the update buildID attribute" + MSG_SHOULD_EQUAL);
Assert.equal(update.detailsURL, "http://details1/",
"the update detailsURL attribute" + MSG_SHOULD_EQUAL);
Assert.equal(update.serviceURL, "http://service1/",
"the update serviceURL attribute" + MSG_SHOULD_EQUAL);
Assert.equal(update.installDate, "1238441300314",
"the update installDate attribute" + MSG_SHOULD_EQUAL);
// statusText is updated
Assert.equal(update.statusText, getString("installSuccess"),
"the update statusText attribute" + MSG_SHOULD_EQUAL);
Assert.ok(!update.isCompleteUpdate,
"the update isCompleteUpdate attribute" + MSG_SHOULD_EQUAL);
Assert.equal(update.channel, "test_channel",
"the update channel attribute" + MSG_SHOULD_EQUAL);
Assert.ok(!!update.showPrompt,
"the update showPrompt attribute" + MSG_SHOULD_EQUAL);
Assert.ok(!!update.showNeverForVersion,
"the update showNeverForVersion attribute" + MSG_SHOULD_EQUAL);
Assert.equal(update.promptWaitTime, "345600",
"the update promptWaitTime attribute" + MSG_SHOULD_EQUAL);
Assert.equal(update.getProperty("backgroundInterval"), "300",
"the update backgroundInterval attribute" + MSG_SHOULD_EQUAL);
Assert.equal(update.previousAppVersion, "3.0",
"the update previousAppVersion attribute" + MSG_SHOULD_EQUAL);
// Custom attributes
Assert.equal(update.getProperty("custom1_attr"), "custom1 value",
"the update custom1_attr property" + MSG_SHOULD_EQUAL);
Assert.equal(update.getProperty("custom2_attr"), "custom2 value",
"the update custom2_attr property" + MSG_SHOULD_EQUAL);
debugDump("checking the activeUpdate patch properties");
let patch = update.selectedPatch;
Assert.equal(patch.type, "partial",
"the update patch type attribute" + MSG_SHOULD_EQUAL);
Assert.equal(patch.URL, "http://partial/",
"the update patch URL attribute" + MSG_SHOULD_EQUAL);
Assert.equal(patch.hashFunction, "SHA256",
"the update patch hashFunction attribute" + MSG_SHOULD_EQUAL);
Assert.equal(patch.hashValue, "cd43",
"the update patch hashValue attribute" + MSG_SHOULD_EQUAL);
Assert.equal(patch.size, "86",
"the update patch size attribute" + MSG_SHOULD_EQUAL);
Assert.ok(!!patch.selected,
"the update patch selected attribute" + MSG_SHOULD_EQUAL);
Assert.equal(patch.state, STATE_SUCCEEDED,
"the update patch state attribute" + MSG_SHOULD_EQUAL);
debugDump("checking the first update properties");
update = gUpdateManager.getUpdateAt(1).QueryInterface(Ci.nsIPropertyBag);
Assert.equal(update.state, STATE_FAILED,
"the update state attribute" + MSG_SHOULD_EQUAL);
Assert.equal(update.name, "Existing",
"the update name attribute" + MSG_SHOULD_EQUAL);
Assert.equal(update.type, "major",
"the update type attribute" + MSG_SHOULD_EQUAL);
Assert.equal(update.displayVersion, "3.0",
"the update displayVersion attribute" + MSG_SHOULD_EQUAL);
Assert.equal(update.appVersion, "3.0",
"the update appVersion attribute" + MSG_SHOULD_EQUAL);
Assert.equal(update.detailsURL, "http://details2/",
"the update detailsURL attribute" + MSG_SHOULD_EQUAL);
Assert.equal(update.serviceURL, "http://service2/",
"the update serviceURL attribute" + MSG_SHOULD_EQUAL);
Assert.equal(update.installDate, "1238441400314",
"the update installDate attribute" + MSG_SHOULD_EQUAL);
Assert.equal(update.statusText, getString("patchApplyFailure"),
"the update statusText attribute" + MSG_SHOULD_EQUAL);
Assert.equal(update.buildID, "20080811053724",
"the update buildID attribute" + MSG_SHOULD_EQUAL);
Assert.ok(!!update.isCompleteUpdate,
"the update isCompleteUpdate attribute" + MSG_SHOULD_EQUAL);
Assert.equal(update.channel, "test_channel",
"the update channel attribute" + MSG_SHOULD_EQUAL);
Assert.ok(!update.showPrompt,
"the update showPrompt attribute" + MSG_SHOULD_EQUAL);
Assert.ok(!update.showNeverForVersion,
"the update showNeverForVersion attribute" + MSG_SHOULD_EQUAL);
Assert.equal(update.promptWaitTime, "691200",
"the update promptWaitTime attribute" + MSG_SHOULD_EQUAL);
// The default and maximum value for backgroundInterval is 600
Assert.equal(update.getProperty("backgroundInterval"), "600",
"the update backgroundInterval attribute" + MSG_SHOULD_EQUAL);
Assert.equal(update.previousAppVersion, null,
"the update previousAppVersion attribute" + MSG_SHOULD_EQUAL);
// Custom attributes
Assert.equal(update.getProperty("custom3_attr"), "custom3 value",
"the update custom3_attr property" + MSG_SHOULD_EQUAL);
Assert.equal(update.getProperty("custom4_attr"), "custom4 value",
"the update custom4_attr property" + MSG_SHOULD_EQUAL);
debugDump("checking the first update patch properties");
patch = update.selectedPatch;
Assert.equal(patch.type, "complete",
"the update patch type attribute" + MSG_SHOULD_EQUAL);
Assert.equal(patch.URL, "http://complete/",
"the update patch URL attribute" + MSG_SHOULD_EQUAL);
Assert.equal(patch.hashFunction, "SHA1",
"the update patch hashFunction attribute" + MSG_SHOULD_EQUAL);
Assert.equal(patch.hashValue, "6232",
"the update patch hashValue attribute" + MSG_SHOULD_EQUAL);
Assert.equal(patch.size, "75",
"the update patch size attribute" + MSG_SHOULD_EQUAL);
Assert.ok(!!patch.selected,
"the update patch selected attribute" + MSG_SHOULD_EQUAL);
Assert.equal(patch.state, STATE_FAILED,
"the update patch state attribute" + MSG_SHOULD_EQUAL);
doTestFinish();
}

View file

@ -0,0 +1,305 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/* General URL Construction Tests */
const URL_PREFIX = URL_HOST + "/";
var gAppInfo;
// Since gUpdateChecker.checkForUpdates uses XMLHttpRequest and XMLHttpRequest
// can be slow it combines the checks whenever possible.
function run_test() {
// This test needs access to omni.ja to read the update.locale file so don't
// use a custom directory for the application directory.
gUseTestAppDir = false;
setupTestCommon();
standardInit();
gAppInfo = Cc["@mozilla.org/xre/app-info;1"].
getService(Ci.nsIXULAppInfo).
QueryInterface(Ci.nsIXULRuntime);
do_execute_soon(run_test_pt1);
}
// url constructed with:
// %PRODUCT%
// %VERSION%
// %BUILD_ID%
// %BUILD_TARGET%
// %LOCALE%
// %CHANNEL%
// %PLATFORM_VERSION%
// %OS_VERSION%
// %SYSTEM_CAPABILITIES%
// %DISTRIBUTION%
// %DISTRIBUTION_VERSION%
function run_test_pt1() {
gCheckFunc = check_test_pt1;
// The code that gets the locale accesses the profile which is only available
// after calling do_get_profile in xpcshell tests. This prevents an error from
// being logged.
do_get_profile();
setUpdateChannel("test_channel");
gDefaultPrefBranch.setCharPref(PREF_DISTRIBUTION_ID, "test_distro");
gDefaultPrefBranch.setCharPref(PREF_DISTRIBUTION_VERSION, "test_distro_version");
let url = URL_PREFIX + "%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/" +
"%LOCALE%/%CHANNEL%/%PLATFORM_VERSION%/%OS_VERSION%/" +
"%SYSTEM_CAPABILITIES%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/" +
"updates.xml";
debugDump("testing url construction - url: " + url);
setUpdateURL(url);
try {
gUpdateChecker.checkForUpdates(updateCheckListener, true);
} catch (e) {
debugDump("The following error is most likely due to a missing " +
"update.locale file");
do_throw(e);
}
}
function check_test_pt1() {
let url = URL_PREFIX + gAppInfo.name + "/" + gAppInfo.version + "/" +
gAppInfo.appBuildID + "/" + gAppInfo.OS + "_" + getABI() + "/" +
INSTALL_LOCALE + "/test_channel/" + gAppInfo.platformVersion + "/" +
getOSVersion() + "/" + getSystemCapabilities() +
"/test_distro/test_distro_version/updates.xml?force=1";
// Log the urls since Assert.equal won't print the entire urls to the log.
if (gRequestURL != url) {
logTestInfo("expected url: " + url);
logTestInfo("returned url: " + gRequestURL);
}
Assert.equal(gRequestURL, url,
"the url" + MSG_SHOULD_EQUAL);
run_test_pt2();
}
// url constructed with:
// %CHANNEL% with distribution partners
// %CUSTOM% parameter
// force param when there already is a param - bug 454357
function run_test_pt2() {
gCheckFunc = check_test_pt2;
let url = URL_PREFIX + "%CHANNEL%/updates.xml?custom=%CUSTOM%";
debugDump("testing url constructed with %CHANNEL% - " + url);
setUpdateURL(url);
gDefaultPrefBranch.setCharPref(PREFBRANCH_APP_PARTNER + "test_partner1",
"test_partner1");
gDefaultPrefBranch.setCharPref(PREFBRANCH_APP_PARTNER + "test_partner2",
"test_partner2");
Services.prefs.setCharPref("app.update.custom", "custom");
gUpdateChecker.checkForUpdates(updateCheckListener, true);
}
function check_test_pt2() {
let url = URL_PREFIX + "test_channel-cck-test_partner1-test_partner2/" +
"updates.xml?custom=custom&force=1";
Assert.equal(gRequestURL, url,
"the url" + MSG_SHOULD_EQUAL);
doTestFinish();
}
function getABI() {
let abi;
try {
abi = gAppInfo.XPCOMABI;
} catch (e) {
do_throw("nsIXULAppInfo:XPCOMABI not defined\n");
}
if (IS_MACOSX) {
// Mac universal build should report a different ABI than either macppc
// or mactel. This is necessary since nsUpdateService.js will set the ABI to
// Universal-gcc3 for Mac universal builds.
let macutils = Cc["@mozilla.org/xpcom/mac-utils;1"].
getService(Ci.nsIMacUtils);
if (macutils.isUniversalBinary) {
abi += "-u-" + macutils.architecturesInBinary;
}
} else if (IS_WIN) {
// Windows build should report the CPU architecture that it's running on.
abi += "-" + getProcArchitecture();
}
return abi;
}
function getOSVersion() {
let sysInfo = Cc["@mozilla.org/system-info;1"].getService(Ci.nsIPropertyBag2);
let osVersion = sysInfo.getProperty("name") + " " + sysInfo.getProperty("version");
if (IS_WIN) {
try {
let servicePack = getServicePack();
osVersion += "." + servicePack;
} catch (e) {
do_throw("Failure obtaining service pack: " + e);
}
if ("5.0" === sysInfo.getProperty("version")) { // Win2K
osVersion += " (unknown)";
} else {
try {
osVersion += " (" + getProcArchitecture() + ")";
} catch (e) {
do_throw("Failed to obtain processor architecture: " + e);
}
}
}
if (osVersion) {
try {
osVersion += " (" + sysInfo.getProperty("secondaryLibrary") + ")";
} catch (e) {
// Not all platforms have a secondary widget library, so an error is
// nothing to worry about.
}
osVersion = encodeURIComponent(osVersion);
}
return osVersion;
}
function getServicePack() {
// NOTE: This function is a helper function and not a test. Thus,
// it uses throw() instead of do_throw(). Any tests that use this function
// should catch exceptions thrown in this function and deal with them
// appropriately (usually by calling do_throw).
const BYTE = ctypes.uint8_t;
const WORD = ctypes.uint16_t;
const DWORD = ctypes.uint32_t;
const WCHAR = ctypes.char16_t;
const BOOL = ctypes.int;
// This structure is described at:
// http://msdn.microsoft.com/en-us/library/ms724833%28v=vs.85%29.aspx
const SZCSDVERSIONLENGTH = 128;
const OSVERSIONINFOEXW = new ctypes.StructType('OSVERSIONINFOEXW',
[
{dwOSVersionInfoSize: DWORD},
{dwMajorVersion: DWORD},
{dwMinorVersion: DWORD},
{dwBuildNumber: DWORD},
{dwPlatformId: DWORD},
{szCSDVersion: ctypes.ArrayType(WCHAR, SZCSDVERSIONLENGTH)},
{wServicePackMajor: WORD},
{wServicePackMinor: WORD},
{wSuiteMask: WORD},
{wProductType: BYTE},
{wReserved: BYTE}
]);
let kernel32 = ctypes.open("kernel32");
try {
let GetVersionEx = kernel32.declare("GetVersionExW",
ctypes.default_abi,
BOOL,
OSVERSIONINFOEXW.ptr);
let winVer = OSVERSIONINFOEXW();
winVer.dwOSVersionInfoSize = OSVERSIONINFOEXW.size;
if (0 === GetVersionEx(winVer.address())) {
// Using "throw" instead of "do_throw" (see NOTE above)
throw ("Failure in GetVersionEx (returned 0)");
}
return winVer.wServicePackMajor + "." + winVer.wServicePackMinor;
} finally {
kernel32.close();
}
}
function getProcArchitecture() {
// NOTE: This function is a helper function and not a test. Thus,
// it uses throw() instead of do_throw(). Any tests that use this function
// should catch exceptions thrown in this function and deal with them
// appropriately (usually by calling do_throw).
const WORD = ctypes.uint16_t;
const DWORD = ctypes.uint32_t;
// This structure is described at:
// http://msdn.microsoft.com/en-us/library/ms724958%28v=vs.85%29.aspx
const SYSTEM_INFO = new ctypes.StructType('SYSTEM_INFO',
[
{wProcessorArchitecture: WORD},
{wReserved: WORD},
{dwPageSize: DWORD},
{lpMinimumApplicationAddress: ctypes.voidptr_t},
{lpMaximumApplicationAddress: ctypes.voidptr_t},
{dwActiveProcessorMask: DWORD.ptr},
{dwNumberOfProcessors: DWORD},
{dwProcessorType: DWORD},
{dwAllocationGranularity: DWORD},
{wProcessorLevel: WORD},
{wProcessorRevision: WORD}
]);
let kernel32 = ctypes.open("kernel32");
try {
let GetNativeSystemInfo = kernel32.declare("GetNativeSystemInfo",
ctypes.default_abi,
ctypes.void_t,
SYSTEM_INFO.ptr);
let sysInfo = SYSTEM_INFO();
// Default to unknown
sysInfo.wProcessorArchitecture = 0xffff;
GetNativeSystemInfo(sysInfo.address());
switch (sysInfo.wProcessorArchitecture) {
case 9:
return "x64";
case 6:
return "IA64";
case 0:
return "x86";
default:
// Using "throw" instead of "do_throw" (see NOTE above)
throw ("Unknown architecture returned from GetNativeSystemInfo: " + sysInfo.wProcessorArchitecture);
}
} finally {
kernel32.close();
}
}
/**
* Provides system capability information for application update though it may
* be used by other consumers.
*/
function getSystemCapabilities() {
if (IS_WIN) {
const PF_MMX_INSTRUCTIONS_AVAILABLE = 3; // MMX
const PF_XMMI_INSTRUCTIONS_AVAILABLE = 6; // SSE
const PF_XMMI64_INSTRUCTIONS_AVAILABLE = 10; // SSE2
const PF_SSE3_INSTRUCTIONS_AVAILABLE = 13; // SSE3
let lib = ctypes.open("kernel32.dll");
let IsProcessorFeaturePresent = lib.declare("IsProcessorFeaturePresent",
ctypes.winapi_abi,
ctypes.int32_t, /* success */
ctypes.uint32_t); /* DWORD */
let instructionSet = "unknown";
try {
if (IsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE)) {
instructionSet = "SSE3";
} else if (IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE)) {
instructionSet = "SSE2";
} else if (IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE)) {
instructionSet = "SSE";
} else if (IsProcessorFeaturePresent(PF_MMX_INSTRUCTIONS_AVAILABLE)) {
instructionSet = "MMX";
}
} catch (e) {
Cu.reportError("Error getting processor instruction set. " +
"Exception: " + e);
}
lib.close();
return instructionSet;
}
return "NA";
}

View file

@ -0,0 +1,27 @@
; This Source Code Form is subject to the terms of the Mozilla Public
; License, v. 2.0. If a copy of the MPL was not distributed with this
; file, You can obtain one at http://mozilla.org/MPL/2.0/.
[DEFAULT]
tags = appupdate
head = head_update.js
tail =
[canCheckForAndCanApplyUpdates.js]
[urlConstruction.js]
[updateManagerXML.js]
[remoteUpdateXML.js]
[downloadAndHashCheckMar.js]
[cleanupDownloadingForOlderAppVersion.js]
[cleanupDownloadingForDifferentChannel.js]
[cleanupDownloadingForSameVersionAndBuildID.js]
[cleanupDownloadingIncorrectStatus.js]
[cleanupPendingVersionFileIncorrectStatus.js]
[cleanupSuccessLogMove.js]
[cleanupSuccessLogsFIFO.js]
[downloadInterruptedRecovery.js]
[downloadResumeForSameAppVersion.js]
[downloadCompleteAfterPartialFailure.js]
[uiSilentPref.js]
[uiUnsupportedAlreadyNotified.js]
[uiAutoPref.js]