michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. michael@0: */ michael@0: michael@0: var gNextRunFunc; michael@0: var gExpectedStatusResult; michael@0: michael@0: function run_test() { michael@0: // This test needs access to omni.ja to read the update.locale file so don't michael@0: // use a custom directory for the application directory. michael@0: gUseTestAppDir = false; michael@0: setupTestCommon(); michael@0: michael@0: logTestInfo("testing mar download and mar hash verification"); michael@0: michael@0: Services.prefs.setBoolPref(PREF_APP_UPDATE_STAGING_ENABLED, false); michael@0: // The HTTP server is only used for the mar file downloads since it is slow michael@0: start_httpserver(); michael@0: setUpdateURLOverride(gURLData + "update.xml"); michael@0: // The mock XMLHttpRequest is MUCH faster michael@0: overrideXHR(callHandleEvent); michael@0: standardInit(); michael@0: do_execute_soon(run_test_pt1); michael@0: } michael@0: michael@0: // The HttpServer must be stopped before calling do_test_finished michael@0: function finish_test() { michael@0: stop_httpserver(doTestFinish); michael@0: } michael@0: michael@0: // Callback function used by the custom XMLHttpRequest implementation to michael@0: // call the nsIDOMEventListener's handleEvent method for onload. michael@0: function callHandleEvent() { michael@0: gXHR.status = 400; michael@0: gXHR.responseText = gResponseBody; michael@0: try { michael@0: var parser = AUS_Cc["@mozilla.org/xmlextras/domparser;1"]. michael@0: createInstance(AUS_Ci.nsIDOMParser); michael@0: gXHR.responseXML = parser.parseFromString(gResponseBody, "application/xml"); michael@0: } catch(e) { michael@0: } michael@0: var e = { target: gXHR }; michael@0: gXHR.onload(e); michael@0: } michael@0: michael@0: // Helper function for testing mar downloads that have the correct size michael@0: // specified in the update xml. michael@0: function run_test_helper_pt1(aMsg, aExpectedStatusResult, aNextRunFunc) { michael@0: gUpdates = null; michael@0: gUpdateCount = null; michael@0: gStatusResult = null; michael@0: gCheckFunc = check_test_helper_pt1_1; michael@0: gNextRunFunc = aNextRunFunc; michael@0: gExpectedStatusResult = aExpectedStatusResult; michael@0: logTestInfo(aMsg, Components.stack.caller); michael@0: gUpdateChecker.checkForUpdates(updateCheckListener, true); michael@0: } michael@0: michael@0: function check_test_helper_pt1_1() { michael@0: do_check_eq(gUpdateCount, 1); michael@0: gCheckFunc = check_test_helper_pt1_2; michael@0: var bestUpdate = gAUS.selectUpdate(gUpdates, gUpdateCount); michael@0: var state = gAUS.downloadUpdate(bestUpdate, false); michael@0: if (state == STATE_NONE || state == STATE_FAILED) michael@0: do_throw("nsIApplicationUpdateService:downloadUpdate returned " + state); michael@0: gAUS.addDownloadListener(downloadListener); michael@0: } michael@0: michael@0: function check_test_helper_pt1_2() { michael@0: do_check_eq(gStatusResult, gExpectedStatusResult); michael@0: gAUS.removeDownloadListener(downloadListener); michael@0: gNextRunFunc(); michael@0: } michael@0: michael@0: // The following 3 functions are a workaround for GONK due to Bug 828858 and michael@0: // can be removed after it is fixed and the callers are changed to use the michael@0: // regular helper functions. michael@0: function run_test_helper_bug828858_pt1(aMsg, aExpectedStatusResult, aNextRunFunc) { michael@0: gUpdates = null; michael@0: gUpdateCount = null; michael@0: gStatusResult = null; michael@0: gCheckFunc = check_test_helper_bug828858_pt1_1; michael@0: gNextRunFunc = aNextRunFunc; michael@0: gExpectedStatusResult = aExpectedStatusResult; michael@0: logTestInfo(aMsg, Components.stack.caller); michael@0: gUpdateChecker.checkForUpdates(updateCheckListener, true); michael@0: } michael@0: michael@0: function check_test_helper_bug828858_pt1_1() { michael@0: do_check_eq(gUpdateCount, 1); michael@0: gCheckFunc = check_test_helper_bug828858_pt1_2; michael@0: var bestUpdate = gAUS.selectUpdate(gUpdates, gUpdateCount); michael@0: var state = gAUS.downloadUpdate(bestUpdate, false); michael@0: if (state == STATE_NONE || state == STATE_FAILED) michael@0: do_throw("nsIApplicationUpdateService:downloadUpdate returned " + state); michael@0: gAUS.addDownloadListener(downloadListener); michael@0: } michael@0: michael@0: function check_test_helper_bug828858_pt1_2() { michael@0: if (gStatusResult == AUS_Cr.NS_ERROR_CONTENT_CORRUPTED) { michael@0: do_check_eq(gStatusResult, AUS_Cr.NS_ERROR_CONTENT_CORRUPTED); michael@0: } else { michael@0: do_check_eq(gStatusResult, gExpectedStatusResult); michael@0: } michael@0: gAUS.removeDownloadListener(downloadListener); michael@0: gNextRunFunc(); michael@0: } michael@0: michael@0: function setResponseBody(aHashFunction, aHashValue, aSize) { michael@0: var patches = getRemotePatchString(null, null, michael@0: aHashFunction, aHashValue, aSize); michael@0: var updates = getRemoteUpdateString(patches); michael@0: gResponseBody = getRemoteUpdatesXMLString(updates); michael@0: } michael@0: michael@0: // mar download with a valid MD5 hash michael@0: function run_test_pt1() { michael@0: setResponseBody("MD5", MD5_HASH_SIMPLE_MAR); michael@0: run_test_helper_pt1("mar download with a valid MD5 hash", michael@0: AUS_Cr.NS_OK, run_test_pt2); michael@0: } michael@0: michael@0: // mar download with an invalid MD5 hash michael@0: function run_test_pt2() { michael@0: setResponseBody("MD5", MD5_HASH_SIMPLE_MAR + "0"); michael@0: run_test_helper_pt1("mar download with an invalid MD5 hash", michael@0: AUS_Cr.NS_ERROR_CORRUPTED_CONTENT, run_test_pt3); michael@0: } michael@0: michael@0: // mar download with a valid SHA1 hash michael@0: function run_test_pt3() { michael@0: setResponseBody("SHA1", SHA1_HASH_SIMPLE_MAR); michael@0: run_test_helper_pt1("mar download with a valid SHA1 hash", michael@0: AUS_Cr.NS_OK, run_test_pt4); michael@0: } michael@0: michael@0: // mar download with an invalid SHA1 hash michael@0: function run_test_pt4() { michael@0: setResponseBody("SHA1", SHA1_HASH_SIMPLE_MAR + "0"); michael@0: run_test_helper_pt1("mar download with an invalid SHA1 hash", michael@0: AUS_Cr.NS_ERROR_CORRUPTED_CONTENT, run_test_pt5); michael@0: } michael@0: michael@0: // mar download with a valid SHA256 hash michael@0: function run_test_pt5() { michael@0: setResponseBody("SHA256", SHA256_HASH_SIMPLE_MAR); michael@0: run_test_helper_pt1("mar download with a valid SHA256 hash", michael@0: AUS_Cr.NS_OK, run_test_pt6); michael@0: } michael@0: michael@0: // mar download with an invalid SHA256 hash michael@0: function run_test_pt6() { michael@0: setResponseBody("SHA256", SHA256_HASH_SIMPLE_MAR + "0"); michael@0: run_test_helper_pt1("mar download with an invalid SHA256 hash", michael@0: AUS_Cr.NS_ERROR_CORRUPTED_CONTENT, run_test_pt7); michael@0: } michael@0: michael@0: // mar download with a valid SHA384 hash michael@0: function run_test_pt7() { michael@0: setResponseBody("SHA384", SHA384_HASH_SIMPLE_MAR); michael@0: run_test_helper_pt1("mar download with a valid SHA384 hash", michael@0: AUS_Cr.NS_OK, run_test_pt8); michael@0: } michael@0: michael@0: // mar download with an invalid SHA384 hash michael@0: function run_test_pt8() { michael@0: setResponseBody("SHA384", SHA384_HASH_SIMPLE_MAR + "0"); michael@0: run_test_helper_pt1("mar download with an invalid SHA384 hash", michael@0: AUS_Cr.NS_ERROR_CORRUPTED_CONTENT, run_test_pt9); michael@0: } michael@0: michael@0: // mar download with a valid SHA512 hash michael@0: function run_test_pt9() { michael@0: setResponseBody("SHA512", SHA512_HASH_SIMPLE_MAR); michael@0: run_test_helper_pt1("mar download with a valid SHA512 hash", michael@0: AUS_Cr.NS_OK, run_test_pt10); michael@0: } michael@0: michael@0: // mar download with an invalid SHA512 hash michael@0: function run_test_pt10() { michael@0: setResponseBody("SHA512", SHA512_HASH_SIMPLE_MAR + "0"); michael@0: run_test_helper_pt1("mar download with an invalid SHA512 hash", michael@0: AUS_Cr.NS_ERROR_CORRUPTED_CONTENT, run_test_pt11); michael@0: } michael@0: michael@0: // mar download with the mar not found michael@0: function run_test_pt11() { michael@0: var patches = getRemotePatchString(null, gURLData + "missing.mar"); michael@0: var updates = getRemoteUpdateString(patches); michael@0: gResponseBody = getRemoteUpdatesXMLString(updates); michael@0: run_test_helper_pt1("mar download with the mar not found", michael@0: AUS_Cr.NS_ERROR_UNEXPECTED, run_test_pt12); michael@0: } michael@0: michael@0: // mar download with a valid MD5 hash but invalid file size michael@0: function run_test_pt12() { michael@0: const arbitraryFileSize = 1024000; michael@0: setResponseBody("MD5", MD5_HASH_SIMPLE_MAR, arbitraryFileSize); michael@0: if (IS_TOOLKIT_GONK) { michael@0: // There seems to be a race on the web server side when the patchFile is michael@0: // stored on the SDCard. Sometimes, the webserver will serve up an error michael@0: // 416 and the contents of the file, and sometimes it will serve up an error michael@0: // 200 and no contents. This can cause either NS_ERROR_UNEXPECTED or michael@0: // NS_ERROR_CONTENT_CORRUPTED. michael@0: // Bug 828858 was filed to follow up on this issue. michael@0: run_test_helper_bug828858_pt1("mar download with a valid MD5 hash but invalid file size", michael@0: AUS_Cr.NS_ERROR_UNEXPECTED, finish_test); michael@0: } else { michael@0: run_test_helper_pt1("mar download with a valid MD5 hash but invalid file size", michael@0: AUS_Cr.NS_ERROR_UNEXPECTED, finish_test); michael@0: } michael@0: }