/* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu, manager: Cm} = Components; const URL_HOST = "http://localhost"; Cu.import("resource://gre/modules/GMPInstallManager.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/FileUtils.jsm"); Cu.import("resource://testing-common/httpd.js"); Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Preferences.jsm") do_get_profile(); function run_test() {Cu.import("resource://gre/modules/Preferences.jsm") Preferences.set("media.gmp-manager.log", true); run_next_test(); } /** * Tests that the helper used for preferences works correctly */ add_test(function test_prefs() { let addon1 = "addon1", addon2 = "addon2"; GMPPrefs.set(GMPPrefs.KEY_LOG_ENABLED, true); GMPPrefs.set(GMPPrefs.KEY_URL, "http://not-really-used"); GMPPrefs.set(GMPPrefs.KEY_URL_OVERRIDE, "http://not-really-used-2"); GMPPrefs.set(GMPPrefs.KEY_ADDON_LAST_UPDATE, "1", addon1); GMPPrefs.set(GMPPrefs.KEY_ADDON_VERSION, "2", addon1); GMPPrefs.set(GMPPrefs.KEY_ADDON_LAST_UPDATE, "3", addon2); GMPPrefs.set(GMPPrefs.KEY_ADDON_VERSION, "4", addon2); GMPPrefs.set(GMPPrefs.KEY_ADDON_AUTOUPDATE, false, addon2); GMPPrefs.set(GMPPrefs.KEY_CERT_CHECKATTRS, true); do_check_true(GMPPrefs.get(GMPPrefs.KEY_LOG_ENABLED)); do_check_eq(GMPPrefs.get(GMPPrefs.KEY_URL), "http://not-really-used"); do_check_eq(GMPPrefs.get(GMPPrefs.KEY_URL_OVERRIDE), "http://not-really-used-2"); do_check_eq(GMPPrefs.get(GMPPrefs.KEY_ADDON_LAST_UPDATE, addon1), "1"); do_check_eq(GMPPrefs.get(GMPPrefs.KEY_ADDON_VERSION, addon1), "2"); do_check_eq(GMPPrefs.get(GMPPrefs.KEY_ADDON_LAST_UPDATE, addon2), "3"); do_check_eq(GMPPrefs.get(GMPPrefs.KEY_ADDON_VERSION, addon2), "4"); do_check_eq(GMPPrefs.get(GMPPrefs.KEY_ADDON_AUTOUPDATE, addon2), false); do_check_true(GMPPrefs.get(GMPPrefs.KEY_CERT_CHECKATTRS)); GMPPrefs.set(GMPPrefs.KEY_ADDON_AUTOUPDATE, true, addon2); run_next_test(); }); /** * Tests that an uninit without a check works fine */ add_test(function test_checkForAddons_noResponse() { let installManager = new GMPInstallManager(); installManager.uninit(); run_next_test(); }); /** * Tests that an uninit without an install works fine */ add_test(function test_checkForAddons_noResponse() { overrideXHR(200, ""); let installManager = new GMPInstallManager(); let promise = installManager.checkForAddons(); promise.then(function(gmpAddons) { do_throw("no repsonse should reject"); }, function(err) { installManager.uninit(); }); run_next_test(); }); /** * Tests that no response returned rejects */ add_test(function test_checkForAddons_noResponse() { overrideXHR(200, ""); let installManager = new GMPInstallManager(); let promise = installManager.checkForAddons(); promise.then(function(gmpAddons) { do_throw("no repsonse should reject"); }, function(err) { do_check_true(!!err); installManager.uninit(); run_next_test(); }); }); /** * Tests that no addons element returned resolves with no addons */ add_task(function test_checkForAddons_noAddonsElement() { overrideXHR(200, ""); let installManager = new GMPInstallManager(); let gmpAddons = yield installManager.checkForAddons(); do_check_eq(gmpAddons.length, 0); installManager.uninit(); }); /** * Tests that empty addons element returned resolves with no addons */ add_task(function test_checkForAddons_noAddonsElement() { overrideXHR(200, ""); let installManager = new GMPInstallManager(); let gmpAddons = yield installManager.checkForAddons(); do_check_eq(gmpAddons.length, 0); installManager.uninit(); }); /** * Tests that a response with the wrong root element rejects */ add_test(function test_checkForAddons_wrongResponseXML() { overrideXHR(200, "3.141592653589793...."); let installManager = new GMPInstallManager(); let promise = installManager.checkForAddons(); promise.then(function(err, gmpAddons) { do_throw("response with the wrong root element should reject"); }, function(err) { do_check_true(!!err); installManager.uninit(); run_next_test(); }); }); /** * Tests that a 404 error works as expected */ add_test(function test_checkForAddons_404Error() { overrideXHR(404, ""); let installManager = new GMPInstallManager(); let promise = installManager.checkForAddons(); promise.then(function(gmpAddons) { do_throw("404 response should reject"); }, function(err) { do_check_true(!!err); do_check_eq(err.status, 404); installManager.uninit(); run_next_test(); }); }); /** * Tests that a xhr abort() works as expected */ add_test(function test_checkForAddons_abort() { let xhr = overrideXHR(200, "", { dropRequest: true} ); let installManager = new GMPInstallManager(); let promise = installManager.checkForAddons(); xhr.abort(); promise.then(function() { do_throw("abort() should reject"); }, function(err) { do_check_eq(err.status, 0); installManager.uninit(); run_next_test(); }); }); /** * Tests that a defensive timeout works as expected */ add_test(function test_checkForAddons_timeout() { overrideXHR(200, "", { dropRequest: true, timeout: true }); let installManager = new GMPInstallManager(); let promise = installManager.checkForAddons(); promise.then(function() { do_throw("Defensive timeout should reject"); }, function(err) { do_check_eq(err.status, 0); installManager.uninit(); run_next_test(); }); }); /** * Tests that we throw correctly in case of ssl certification error. */ add_test(function test_checkForAddons_bad_ssl() { // // Add random stuff that cause CertUtil to require https. // let PREF_KEY_URL_OVERRIDE_BACKUP = Preferences.get(GMPPrefs.KEY_URL_OVERRIDE, undefined); Preferences.reset(GMPPrefs.KEY_URL_OVERRIDE); let CERTS_BRANCH_DOT_ONE = GMPPrefs.CERTS_BRANCH + ".1"; let PREF_CERTS_BRANCH_DOT_ONE_BACKUP = Preferences.get(CERTS_BRANCH_DOT_ONE, undefined); Services.prefs.setCharPref(CERTS_BRANCH_DOT_ONE, "funky value"); overrideXHR(200, ""); let installManager = new GMPInstallManager(); let promise = installManager.checkForAddons(); promise.then(function() { do_throw("Defensive timeout should reject"); }, function(err) { do_check_true(err.message.contains("SSL is required and URI scheme is not https.")); installManager.uninit(); if (PREF_KEY_URL_OVERRIDE_BACKUP) { Preferences.set(GMPPrefs.KEY_URL_OVERRIDE, PREF_KEY_URL_OVERRIDE_BACKUP); } if (PREF_CERTS_BRANCH_DOT_ONE_BACKUP) { Preferences.set(CERTS_BRANCH_DOT_ONE, PREF_CERTS_BRANCH_DOT_ONE_BACKUP); } run_next_test(); }); }); /** * Tests that gettinga a funky non XML response works as expected */ add_test(function test_checkForAddons_notXML() { overrideXHR(200, "3.141592653589793...."); let installManager = new GMPInstallManager(); let promise = installManager.checkForAddons(); promise.then(function(gmpAddons) { do_throw("non XML response should reject"); }, function(err) { do_check_true(!!err); installManager.uninit(); run_next_test(); }); }); /** * Tests that getting a response with a single addon works as expected */ add_test(function test_checkForAddons_singleAddonNoUpdates() { let responseXML = "" + "" + " " + " " + " " + "" overrideXHR(200, responseXML); let installManager = new GMPInstallManager(); let promise = installManager.checkForAddons(); promise.then(function(gmpAddons) { do_check_eq(gmpAddons.length, 1); let gmpAddon= gmpAddons[0]; do_check_eq(gmpAddon.id, "gmp-gmpopenh264"); do_check_eq(gmpAddon.URL, "http://127.0.0.1:8011/gmp-gmpopenh264-1.1.zip"); do_check_eq(gmpAddon.hashFunction, "sha256"); do_check_eq(gmpAddon.hashValue, "1118b90d6f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee"); do_check_eq(gmpAddon.version, "1.1"); do_check_eq(gmpAddon.size, undefined); do_check_true(gmpAddon.isValid); do_check_true(gmpAddon.isOpenH264); do_check_false(gmpAddon.isInstalled); installManager.uninit(); run_next_test(); }, function(err) { do_throw("1 addon found should not reject"); }); }); /** * Tests that getting a response with a single addon with the optional size * attribute parses as expected. */ add_test(function test_checkForAddons_singleAddonNoUpdates() { let responseXML = "" + "" + " " + " " + " " + "" overrideXHR(200, responseXML); let installManager = new GMPInstallManager(); let promise = installManager.checkForAddons(); promise.then(function(gmpAddons) { do_check_eq(gmpAddons.length, 1); let gmpAddon= gmpAddons[0]; do_check_eq(gmpAddon.id, "openh264-plugin-no-at-symbol"); do_check_eq(gmpAddon.URL, "http://127.0.0.1:8011/gmp-gmpopenh264-1.1.zip"); do_check_eq(gmpAddon.hashFunction, "sha256"); do_check_eq(gmpAddon.hashValue, "1118b90d6f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee"); do_check_eq(gmpAddon.size, 42); do_check_eq(gmpAddon.version, "1.1"); do_check_true(gmpAddon.isValid); do_check_false(gmpAddon.isOpenH264); do_check_false(gmpAddon.isInstalled); installManager.uninit(); run_next_test(); }, function(err) { do_throw("1 addon found should not reject"); }); }); /** * Tests that checking for multiple addons work correctly. * Also tests that invalid addons work correctly. */ add_test(function test_checkForAddons_multipleAddonNoUpdatesSomeInvalid() { let responseXML = "" + "" + " " + // valid openh264 " " + // valid not openh264 " " + // noid " " + // no URL " " + // no hash function " " + // no hash function " " + // not version " " + " " + "" overrideXHR(200, responseXML); let installManager = new GMPInstallManager(); let promise = installManager.checkForAddons(); promise.then(function(gmpAddons) { do_check_eq(gmpAddons.length, 7); let gmpAddon= gmpAddons[0]; do_check_eq(gmpAddon.id, "gmp-gmpopenh264"); do_check_eq(gmpAddon.URL, "http://127.0.0.1:8011/gmp-gmpopenh264-1.1.zip"); do_check_eq(gmpAddon.hashFunction, "sha256"); do_check_eq(gmpAddon.hashValue, "1118b90d6f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee"); do_check_eq(gmpAddon.version, "1.1"); do_check_true(gmpAddon.isValid); do_check_true(gmpAddon.isOpenH264); do_check_false(gmpAddon.isInstalled); gmpAddon= gmpAddons[1]; do_check_eq(gmpAddon.id, "NOT-gmp-gmpopenh264"); do_check_eq(gmpAddon.URL, "http://127.0.0.1:8011/NOT-gmp-gmpopenh264-1.1.zip"); do_check_eq(gmpAddon.hashFunction, "sha512"); do_check_eq(gmpAddon.hashValue, "141592656f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee"); do_check_eq(gmpAddon.version, "9.1"); do_check_true(gmpAddon.isValid); do_check_false(gmpAddon.isOpenH264); do_check_false(gmpAddon.isInstalled); for (let i = 2; i < gmpAddons.length; i++) { do_check_false(gmpAddons[i].isValid); do_check_false(gmpAddons[i].isInstalled); } installManager.uninit(); run_next_test(); }, function(err) { do_throw("multiple addons found should not reject"); }); }); /** * Tests that checking for addons when there are also updates available * works as expected. */ add_test(function test_checkForAddons_updatesWithAddons() { let responseXML = "" + " " + " " + " " + " " + " " + " " + " " + "" overrideXHR(200, responseXML); let installManager = new GMPInstallManager(); let promise = installManager.checkForAddons(); promise.then(function(gmpAddons) { do_check_eq(gmpAddons.length, 1); let gmpAddon= gmpAddons[0]; do_check_eq(gmpAddon.id, "gmp-gmpopenh264"); do_check_eq(gmpAddon.URL, "http://127.0.0.1:8011/gmp-gmpopenh264-1.1.zip"); do_check_eq(gmpAddon.hashFunction, "sha256"); do_check_eq(gmpAddon.hashValue, "1118b90d6f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee"); do_check_eq(gmpAddon.version, "1.1"); do_check_true(gmpAddon.isValid); do_check_true(gmpAddon.isOpenH264); do_check_false(gmpAddon.isInstalled); installManager.uninit(); run_next_test(); }, function(err) { do_throw("updates with addons should not reject"); }); }); /** * Tests that installing found addons works as expected */ function test_checkForAddons_installAddon(id, includeSize,wantInstallReject) { do_print("Running installAddon for includeSize: " + includeSize + " and wantInstallReject: " + wantInstallReject); let httpServer = new HttpServer(); let dir = FileUtils.getDir("TmpD", [], true); httpServer.registerDirectory("/", dir); httpServer.start(-1); let testserverPort = httpServer.identity.primaryPort; let zipFileName = "test_" + id + "_GMP.zip"; let zipURL = URL_HOST + ":" + testserverPort + "/" + zipFileName; do_print("zipURL: " + zipURL); let data = "e~=0.5772156649"; let zipFile = createNewZipFile(zipFileName, data); let hashFunc = "sha256"; let expectedDigest = yield GMPDownloader.computeHash(hashFunc, zipFile); let fileSize = zipFile.size; if (wantInstallReject) { fileSize = 1; } let responseXML = "" + "" + " " + " " + " " + "" overrideXHR(200, responseXML); let installManager = new GMPInstallManager(); let checkPromise = installManager.checkForAddons(); checkPromise.then(function(gmpAddons) { do_check_eq(gmpAddons.length, 1); let gmpAddon = gmpAddons[0]; do_check_false(gmpAddon.isInstalled); GMPInstallManager.overrideLeaveDownloadedZip = true; let installPromise = installManager.installAddon(gmpAddon); installPromise.then(function(extractedPaths) { if (wantInstallReject) { do_throw("install update should reject"); } do_check_eq(extractedPaths.length, 1); let extractedPath = extractedPaths[0]; do_print("Extracted path: " + extractedPath); let extractedFile = Cc["@mozilla.org/file/local;1"]. createInstance(Ci.nsIFile); extractedFile.initWithPath(extractedPath); do_check_true(extractedFile.exists()); let readData = readStringFromFile(extractedFile); do_check_eq(readData, data); // Check that the downloaded zip matches the offered zip exactly let downloadedGMPFile = FileUtils.getFile("TmpD", [gmpAddon.id + ".zip"]); do_check_true(downloadedGMPFile.exists()); let downloadedBytes = getBinaryFileData(downloadedGMPFile); let sourceBytes = getBinaryFileData(zipFile); do_check_true(compareBinaryData(downloadedBytes, sourceBytes)); // Make sure the prefs are set correctly do_check_true(!!GMPPrefs.get(GMPPrefs.KEY_ADDON_LAST_UPDATE, gmpAddon.id, "")); do_check_eq(GMPPrefs.get(GMPPrefs.KEY_ADDON_VERSION, gmpAddon.id, ""), "1.1"); // Make sure it reports as being installed do_check_true(gmpAddon.isInstalled); // Cleanup extractedFile.parent.remove(true); zipFile.remove(false); httpServer.stop(function() {}); do_print("Removing downloaded GMP file: " + downloadedGMPFile.path); downloadedGMPFile.remove(false); installManager.uninit(); }, function(err) { zipFile.remove(false); let downloadedGMPFile = FileUtils.getFile("TmpD", [gmpAddon.id + ".zip"]); do_print("Removing from err downloaded GMP file: " + downloadedGMPFile.path); downloadedGMPFile.remove(false); if (!wantInstallReject) { do_throw("install update should not reject"); } }); }, function(err) { do_throw("checking updates to install them should not reject"); }); } add_task(test_checkForAddons_installAddon.bind(null, "1", true, false)); add_task(test_checkForAddons_installAddon.bind(null, "2", false, false)); add_task(test_checkForAddons_installAddon.bind(null, "3", true, true)); /** * Tests simpleCheckAndInstall autoupdate disabled */ add_task(function test_simpleCheckAndInstall() { GMPPrefs.set(GMPPrefs.KEY_ADDON_AUTOUPDATE, false, OPEN_H264_ID); let installManager = new GMPInstallManager(); let promise = installManager.simpleCheckAndInstall(); promise.then((result) => { do_check_eq(result.status, "check-disabled"); }, () => { do_throw("simple check should not reject"); }); }); /** * Tests simpleCheckAndInstall nothing to install */ add_task(function test_simpleCheckAndInstall() { GMPPrefs.set(GMPPrefs.KEY_ADDON_AUTOUPDATE, true, OPEN_H264_ID); let installManager = new GMPInstallManager(); let promise = installManager.simpleCheckAndInstall(); promise.then((result) => { do_check_eq(result.status, "nothing-new-to-install"); }, () => { do_throw("simple check should not reject"); }); }); /** * Tests simpleCheckAndInstall too frequent */ add_task(function test_simpleCheckAndInstall() { GMPPrefs.set(GMPPrefs.KEY_ADDON_AUTOUPDATE, true, OPEN_H264_ID); let installManager = new GMPInstallManager(); let promise = installManager.simpleCheckAndInstall(); promise.then((result) => { do_check_eq(result.status, "too-frequent-no-check"); }, () => { do_throw("simple check should not reject"); }); }); /** * Tests that installing addons when there is no server works as expected */ add_test(function test_installAddon_noServer() { let dir = FileUtils.getDir("TmpD", [], true); let zipFileName = "test_GMP.zip"; let zipURL = URL_HOST + ":0/" + zipFileName; let data = "e~=0.5772156649"; let zipFile = createNewZipFile(zipFileName, data); let responseXML = "" + "" + " " + " " + " " + "" overrideXHR(200, responseXML); let installManager = new GMPInstallManager(); let checkPromise = installManager.checkForAddons(); checkPromise.then(function(gmpAddons) { do_check_eq(gmpAddons.length, 1); let gmpAddon= gmpAddons[0]; GMPInstallManager.overrideLeaveDownloadedZip = true; let installPromise = installManager.installAddon(gmpAddon); installPromise.then(function(extractedPaths) { do_throw("No server for install should reject"); }, function(err) { do_check_true(!!err); installManager.uninit(); run_next_test(); }); }, function(err) { do_throw("check should not reject for installn o server"); }); }); /** * Returns the read stream into a string */ function readStringFromInputStream(inputStream) { let sis = Cc["@mozilla.org/scriptableinputstream;1"]. createInstance(Ci.nsIScriptableInputStream); sis.init(inputStream); let text = sis.read(sis.available()); sis.close(); return text; } /** * Reads a string of text from a file. * This function only works with ASCII text. */ function readStringFromFile(file) { if (!file.exists()) { do_print("readStringFromFile - file doesn't exist: " + file.path); return null; } let fis = Cc["@mozilla.org/network/file-input-stream;1"]. createInstance(Ci.nsIFileInputStream); fis.init(file, FileUtils.MODE_RDONLY, FileUtils.PERMS_FILE, 0); return readStringFromInputStream(fis); } /** * Bare bones XMLHttpRequest implementation for testing onprogress, onerror, * and onload nsIDomEventListener handleEvent. */ function makeHandler(aVal) { if (typeof aVal == "function") return { handleEvent: aVal }; return aVal; } /** * Constructs a mock xhr which is used for testing different aspects * of responses. */ function xhr(inputStatus, inputResponse, options) { this.inputStatus = inputStatus; this.inputResponse = inputResponse; this.status = 0; this.responseXML = null; this._aborted = false; this._onabort = null; this._onprogress = null; this._onerror = null; this._onload = null; this._onloadend = null; this._ontimeout = null; this._url = null; this._method = null; this._timeout = 0; this._notified = false; this._options = options || {}; } xhr.prototype = { overrideMimeType: function(aMimetype) { }, setRequestHeader: function(aHeader, aValue) { }, status: null, channel: { set notificationCallbacks(aVal) { } }, open: function(aMethod, aUrl) { this.channel.originalURI = Services.io.newURI(aUrl, null, null); this._method = aMethod; this._url = aUrl; }, abort: function() { this._dropRequest = true; this._notify(["abort", "loadend"]); }, responseXML: null, responseText: null, send: function(aBody) { do_execute_soon(function() { try { if (this._options.dropRequest) { if (this._timeout > 0 && this._options.timeout) { this._notify(["timeout", "loadend"]); } return; } this.status = this.inputStatus; this.responseText = this.inputResponse; try { let parser = Cc["@mozilla.org/xmlextras/domparser;1"]. createInstance(Ci.nsIDOMParser); this.responseXML = parser.parseFromString(this.inputResponse, "application/xml"); } catch (e) { this.responseXML = null; } if (this.inputStatus === 200) { this._notify(["load", "loadend"]); } else { this._notify(["error", "loadend"]); } } catch (ex) { do_throw(ex); } }.bind(this)); }, set onabort(aValue) { this._onabort = makeHandler(aValue); }, get onabort() { return this._onabort; }, set onprogress(aValue) { this._onprogress = makeHandler(aValue); }, get onprogress() { return this._onprogress; }, set onerror(aValue) { this._onerror = makeHandler(aValue); }, get onerror() { return this._onerror; }, set onload(aValue) { this._onload = makeHandler(aValue); }, get onload() { return this._onload; }, set onloadend(aValue) { this._onloadend = makeHandler(aValue); }, get onloadend() { return this._onloadend; }, set ontimeout(aValue) { this._ontimeout = makeHandler(aValue); }, get ontimeout() { return this._ontimeout; }, set timeout(aValue) { this._timeout = aValue; }, _notify: function(events) { if (this._notified) { return; } this._notified = true; for (let item of events) { let k = "on" + item; if (this[k]) { do_print("Notifying " + item); let e = { target: this, type: item, }; this[k](e); } else { do_print("Notifying " + item + ", but there are no listeners"); } } }, addEventListener: function(aEvent, aValue, aCapturing) { eval("this._on" + aEvent + " = aValue"); }, flags: Ci.nsIClassInfo.SINGLETON, implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT, getHelperForLanguage: function(aLanguage) null, getInterfaces: function(aCount) { let interfaces = [Ci.nsISupports]; aCount.value = interfaces.length; return interfaces; }, classDescription: "XMLHttpRequest", contractID: "@mozilla.org/xmlextras/xmlhttprequest;1", classID: Components.ID("{c9b37f43-4278-4304-a5e0-600991ab08cb}"), createInstance: function(aOuter, aIID) { if (aOuter == null) return this.QueryInterface(aIID); throw Cr.NS_ERROR_NO_AGGREGATION; }, QueryInterface: function(aIID) { if (aIID.equals(Ci.nsIClassInfo) || aIID.equals(Ci.nsISupports)) return this; throw Cr.NS_ERROR_NO_INTERFACE; }, get wrappedJSObject() { return this; } }; /** * Helper used to overrideXHR requests (no matter to what URL) with the * specified status and response. * @param status The status you want to get back when an XHR request is made * @param response The response you want to get back when an XHR request is made */ function overrideXHR(status, response, options) { let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); if (overrideXHR.myxhr) { registrar.unregisterFactory(overrideXHR.myxhr.classID, overrideXHR.myxhr); } overrideXHR.myxhr = new xhr(status, response, options); registrar.registerFactory(overrideXHR.myxhr.classID, overrideXHR.myxhr.classDescription, overrideXHR.myxhr.contractID, overrideXHR.myxhr); return overrideXHR.myxhr; } /** * Compares binary data of 2 arrays and returns true if they are the same * * @param arr1 The first array to compare * @param arr2 The second array to compare */ function compareBinaryData(arr1, arr2) { do_check_eq(arr1.length, arr2.length); for (let i = 0; i < arr1.length; i++) { if (arr1[i] != arr2[i]) { do_print("Data differs at index " + i + ", arr1: " + arr1[i] + ", arr2: " + arr2[i]); return false; } } return true; } /** * Reads a file's data and returns it * * @param file The file to read the data from * @return array of bytes for the data in the file. */ function getBinaryFileData(file) { let fileStream = Cc["@mozilla.org/network/file-input-stream;1"]. createInstance(Ci.nsIFileInputStream); // Open as RD_ONLY with default permissions. fileStream.init(file, FileUtils.MODE_RDONLY, FileUtils.PERMS_FILE, 0); // Check the returned size versus the expected size. let stream = Cc["@mozilla.org/binaryinputstream;1"]. createInstance(Ci.nsIBinaryInputStream); stream.setInputStream(fileStream); let bytes = stream.readByteArray(stream.available()); fileStream.close(); return bytes; } /** * Creates a new zip file containing a file with the specified data * @param zipName The name of the zip file * @param data The data to go inside the zip for the filename entry1.info */ function createNewZipFile(zipName, data) { // Create a zip file which will be used for extracting let stream = Cc["@mozilla.org/io/string-input-stream;1"]. createInstance(Ci.nsIStringInputStream); stream.setData(data, data.length); let zipWriter = Cc["@mozilla.org/zipwriter;1"]. createInstance(Components.interfaces.nsIZipWriter); let zipFile = FileUtils.getFile("TmpD", [zipName]); if (zipFile.exists()) { zipFile.remove(false); } // From prio.h const PR_RDWR = 0x04; const PR_CREATE_FILE = 0x08; const PR_TRUNCATE = 0x20; zipWriter.open(zipFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE); zipWriter.addEntryStream("entry1.info", Date.now(), Ci.nsIZipWriter.COMPRESSION_BEST, stream, false); zipWriter.close(); stream.close(); do_print("zip file created on disk at: " + zipFile.path); return zipFile; }