diff options
Diffstat (limited to 'toolkit/mozapps/extensions/test/xpcshell/test_signed_install.js')
-rw-r--r-- | toolkit/mozapps/extensions/test/xpcshell/test_signed_install.js | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_signed_install.js b/toolkit/mozapps/extensions/test/xpcshell/test_signed_install.js new file mode 100644 index 000000000..19b07ac16 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_signed_install.js @@ -0,0 +1,265 @@ +// Enable signature checks for these tests +gUseRealCertChecks = true; +// Disable update security +Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); + +const DATA = "data/signing_checks/"; +const ADDONS = { + bootstrap: { + unsigned: "unsigned_bootstrap_2.xpi", + badid: "signed_bootstrap_badid_2.xpi", + preliminary: "preliminary_bootstrap_2.xpi", + signed: "signed_bootstrap_2.xpi", + }, +}; +const WORKING = "signed_bootstrap_1.xpi"; +const ID = "test@tests.mozilla.org"; + +var gServer = createHttpServer(4444); + +// Creates an add-on with a broken signature by changing an existing file +function createBrokenAddonModify(file) { + let brokenFile = gTmpD.clone(); + brokenFile.append("broken.xpi"); + file.copyTo(brokenFile.parent, brokenFile.leafName); + + var stream = AM_Cc["@mozilla.org/io/string-input-stream;1"]. + createInstance(AM_Ci.nsIStringInputStream); + stream.setData("FOOBAR", -1); + var zipW = AM_Cc["@mozilla.org/zipwriter;1"]. + createInstance(AM_Ci.nsIZipWriter); + zipW.open(brokenFile, FileUtils.MODE_RDWR | FileUtils.MODE_APPEND); + zipW.removeEntry("test.txt", false); + zipW.addEntryStream("test.txt", 0, AM_Ci.nsIZipWriter.COMPRESSION_NONE, + stream, false); + zipW.close(); + + return brokenFile; +} + +// Creates an add-on with a broken signature by adding a new file +function createBrokenAddonAdd(file) { + let brokenFile = gTmpD.clone(); + brokenFile.append("broken.xpi"); + file.copyTo(brokenFile.parent, brokenFile.leafName); + + var stream = AM_Cc["@mozilla.org/io/string-input-stream;1"]. + createInstance(AM_Ci.nsIStringInputStream); + stream.setData("FOOBAR", -1); + var zipW = AM_Cc["@mozilla.org/zipwriter;1"]. + createInstance(AM_Ci.nsIZipWriter); + zipW.open(brokenFile, FileUtils.MODE_RDWR | FileUtils.MODE_APPEND); + zipW.addEntryStream("test2.txt", 0, AM_Ci.nsIZipWriter.COMPRESSION_NONE, + stream, false); + zipW.close(); + + return brokenFile; +} + +// Creates an add-on with a broken signature by removing an existing file +function createBrokenAddonRemove(file) { + let brokenFile = gTmpD.clone(); + brokenFile.append("broken.xpi"); + file.copyTo(brokenFile.parent, brokenFile.leafName); + + var stream = AM_Cc["@mozilla.org/io/string-input-stream;1"]. + createInstance(AM_Ci.nsIStringInputStream); + stream.setData("FOOBAR", -1); + var zipW = AM_Cc["@mozilla.org/zipwriter;1"]. + createInstance(AM_Ci.nsIZipWriter); + zipW.open(brokenFile, FileUtils.MODE_RDWR | FileUtils.MODE_APPEND); + zipW.removeEntry("test.txt", false); + zipW.close(); + + return brokenFile; +} + +function createInstall(url) { + return new Promise(resolve => { + AddonManager.getInstallForURL(url, resolve, "application/x-xpinstall"); + }); +} + +function serveUpdateRDF(leafName) { + gServer.registerPathHandler("/update.rdf", function(request, response) { + let updateData = {}; + updateData[ID] = [{ + version: "2.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "4", + maxVersion: "6", + updateLink: "http://localhost:4444/" + leafName + }] + }]; + + response.setStatusLine(request.httpVersion, 200, "OK"); + response.write(createUpdateRDF(updateData)); + }); +} + + +function* test_install_broken(file, expectedError) { + gServer.registerFile("/" + file.leafName, file); + + let install = yield createInstall("http://localhost:4444/" + file.leafName); + yield promiseCompleteAllInstalls([install]); + + do_check_eq(install.state, AddonManager.STATE_DOWNLOAD_FAILED); + do_check_eq(install.error, expectedError); + do_check_eq(install.addon, null); + + gServer.registerFile("/" + file.leafName, null); +} + +function* test_install_working(file, expectedSignedState) { + gServer.registerFile("/" + file.leafName, file); + + let install = yield createInstall("http://localhost:4444/" + file.leafName); + yield promiseCompleteAllInstalls([install]); + + do_check_eq(install.state, AddonManager.STATE_INSTALLED); + do_check_neq(install.addon, null); + do_check_eq(install.addon.signedState, expectedSignedState); + + gServer.registerFile("/" + file.leafName, null); + + install.addon.uninstall(); +} + +function* test_update_broken(file, expectedError) { + // First install the older version + yield promiseInstallAllFiles([do_get_file(DATA + WORKING)]); + + gServer.registerFile("/" + file.leafName, file); + serveUpdateRDF(file.leafName); + + let addon = yield promiseAddonByID(ID); + let update = yield promiseFindAddonUpdates(addon); + let install = update.updateAvailable; + yield promiseCompleteAllInstalls([install]); + + do_check_eq(install.state, AddonManager.STATE_DOWNLOAD_FAILED); + do_check_eq(install.error, expectedError); + do_check_eq(install.addon, null); + + gServer.registerFile("/" + file.leafName, null); + gServer.registerPathHandler("/update.rdf", null); + + addon.uninstall(); +} + +function* test_update_working(file, expectedSignedState) { + // First install the older version + yield promiseInstallAllFiles([do_get_file(DATA + WORKING)]); + + gServer.registerFile("/" + file.leafName, file); + serveUpdateRDF(file.leafName); + + let addon = yield promiseAddonByID(ID); + let update = yield promiseFindAddonUpdates(addon); + let install = update.updateAvailable; + yield promiseCompleteAllInstalls([install]); + + do_check_eq(install.state, AddonManager.STATE_INSTALLED); + do_check_neq(install.addon, null); + do_check_eq(install.addon.signedState, expectedSignedState); + + gServer.registerFile("/" + file.leafName, null); + gServer.registerPathHandler("/update.rdf", null); + + install.addon.uninstall(); +} + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "4", "4"); + startupManager(); + + run_next_test(); +} + +// Try to install a broken add-on +add_task(function*() { + let file = createBrokenAddonModify(do_get_file(DATA + ADDONS.bootstrap.signed)); + yield test_install_broken(file, AddonManager.ERROR_CORRUPT_FILE); + file.remove(true); +}); + +add_task(function*() { + let file = createBrokenAddonAdd(do_get_file(DATA + ADDONS.bootstrap.signed)); + yield test_install_broken(file, AddonManager.ERROR_CORRUPT_FILE); + file.remove(true); +}); + +add_task(function*() { + let file = createBrokenAddonRemove(do_get_file(DATA + ADDONS.bootstrap.signed)); + yield test_install_broken(file, AddonManager.ERROR_CORRUPT_FILE); + file.remove(true); +}); + +// Try to install an add-on with an incorrect ID +add_task(function*() { + let file = do_get_file(DATA + ADDONS.bootstrap.badid); + yield test_install_broken(file, AddonManager.ERROR_CORRUPT_FILE); +}); + +// Try to install an unsigned add-on +add_task(function*() { + let file = do_get_file(DATA + ADDONS.bootstrap.unsigned); + yield test_install_broken(file, AddonManager.ERROR_SIGNEDSTATE_REQUIRED); +}); + +// Try to install a preliminarily reviewed add-on +add_task(function*() { + let file = do_get_file(DATA + ADDONS.bootstrap.preliminary); + yield test_install_working(file, AddonManager.SIGNEDSTATE_PRELIMINARY); +}); + +// Try to install a signed add-on +add_task(function*() { + let file = do_get_file(DATA + ADDONS.bootstrap.signed); + yield test_install_working(file, AddonManager.SIGNEDSTATE_SIGNED); +}); + +// Try to update to a broken add-on +add_task(function*() { + let file = createBrokenAddonModify(do_get_file(DATA + ADDONS.bootstrap.signed)); + yield test_update_broken(file, AddonManager.ERROR_CORRUPT_FILE); + file.remove(true); +}); + +add_task(function*() { + let file = createBrokenAddonAdd(do_get_file(DATA + ADDONS.bootstrap.signed)); + yield test_update_broken(file, AddonManager.ERROR_CORRUPT_FILE); + file.remove(true); +}); + +add_task(function*() { + let file = createBrokenAddonRemove(do_get_file(DATA + ADDONS.bootstrap.signed)); + yield test_update_broken(file, AddonManager.ERROR_CORRUPT_FILE); + file.remove(true); +}); + +// Try to update to an add-on with an incorrect ID +add_task(function*() { + let file = do_get_file(DATA + ADDONS.bootstrap.badid); + yield test_update_broken(file, AddonManager.ERROR_CORRUPT_FILE); +}); + +// Try to update to an unsigned add-on +add_task(function*() { + let file = do_get_file(DATA + ADDONS.bootstrap.unsigned); + yield test_update_broken(file, AddonManager.ERROR_SIGNEDSTATE_REQUIRED); +}); + +// Try to update to a preliminarily reviewed add-on +add_task(function*() { + let file = do_get_file(DATA + ADDONS.bootstrap.preliminary); + yield test_update_working(file, AddonManager.SIGNEDSTATE_PRELIMINARY); +}); + +// Try to update to a signed add-on +add_task(function*() { + let file = do_get_file(DATA + ADDONS.bootstrap.signed); + yield test_update_working(file, AddonManager.SIGNEDSTATE_SIGNED); +}); |