michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: * http://creativecommons.org/publicdomain/zero/1.0/ michael@0: */ michael@0: michael@0: // Tests that various operations with file pointers work and do not affect the michael@0: // source files michael@0: michael@0: var addon1 = { michael@0: id: "addon1@tests.mozilla.org", michael@0: version: "1.0", michael@0: name: "Test 1", michael@0: targetApplications: [{ michael@0: id: "xpcshell@tests.mozilla.org", michael@0: minVersion: "1", michael@0: maxVersion: "1" michael@0: }] michael@0: }; michael@0: michael@0: var addon1_2 = { michael@0: id: "addon1@tests.mozilla.org", michael@0: version: "2.0", michael@0: name: "Test 1", michael@0: targetApplications: [{ michael@0: id: "xpcshell@tests.mozilla.org", michael@0: minVersion: "1", michael@0: maxVersion: "1" michael@0: }] michael@0: }; michael@0: michael@0: var addon2 = { michael@0: id: "addon2@tests.mozilla.org", michael@0: version: "1.0", michael@0: name: "Test 2", michael@0: targetApplications: [{ michael@0: id: "xpcshell@tests.mozilla.org", michael@0: minVersion: "1", michael@0: maxVersion: "1" michael@0: }] michael@0: }; michael@0: michael@0: const profileDir = gProfD.clone(); michael@0: profileDir.append("extensions"); michael@0: profileDir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755); michael@0: michael@0: const sourceDir = gProfD.clone(); michael@0: sourceDir.append("source"); michael@0: michael@0: Components.utils.import("resource://testing-common/httpd.js"); michael@0: var testserver; michael@0: michael@0: function writePointer(aId, aName) { michael@0: let file = profileDir.clone(); michael@0: file.append(aName ? aName : aId); michael@0: michael@0: let target = sourceDir.clone(); michael@0: target.append(do_get_expected_addon_name(aId)); michael@0: michael@0: var fos = AM_Cc["@mozilla.org/network/file-output-stream;1"]. michael@0: createInstance(AM_Ci.nsIFileOutputStream); michael@0: fos.init(file, michael@0: FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | FileUtils.MODE_TRUNCATE, michael@0: FileUtils.PERMS_FILE, 0); michael@0: fos.write(target.path, target.path.length); michael@0: fos.close(); michael@0: } michael@0: michael@0: function writeRelativePointer(aId, aName) { michael@0: let file = profileDir.clone(); michael@0: file.append(aName ? aName : aId); michael@0: michael@0: let absTarget = sourceDir.clone(); michael@0: absTarget.append(do_get_expected_addon_name(aId)); michael@0: michael@0: var relTarget = absTarget.getRelativeDescriptor(profileDir); michael@0: michael@0: var fos = AM_Cc["@mozilla.org/network/file-output-stream;1"]. michael@0: createInstance(AM_Ci.nsIFileOutputStream); michael@0: fos.init(file, michael@0: FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | FileUtils.MODE_TRUNCATE, michael@0: FileUtils.PERMS_FILE, 0); michael@0: fos.write(relTarget, relTarget.length); michael@0: fos.close(); michael@0: } michael@0: michael@0: function run_test() { michael@0: // pointer files only work with unpacked directories michael@0: if (Services.prefs.getBoolPref("extensions.alwaysUnpack") == false) michael@0: return; michael@0: michael@0: do_test_pending(); michael@0: createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); michael@0: michael@0: // Create and configure the HTTP server. michael@0: testserver = new HttpServer(); michael@0: testserver.registerDirectory("/data/", do_get_file("data")); michael@0: testserver.registerDirectory("/addons/", do_get_file("addons")); michael@0: testserver.start(-1); michael@0: gPort = testserver.identity.primaryPort; michael@0: michael@0: run_test_1(); michael@0: } michael@0: michael@0: function end_test() { michael@0: testserver.stop(do_test_finished); michael@0: } michael@0: michael@0: // Tests that installing a new add-on by pointer works michael@0: function run_test_1() { michael@0: writeInstallRDFForExtension(addon1, sourceDir); michael@0: writePointer(addon1.id); michael@0: michael@0: startupManager(); michael@0: michael@0: AddonManager.getAddonByID(addon1.id, function(a1) { michael@0: do_check_neq(a1, null); michael@0: do_check_eq(a1.version, "1.0"); michael@0: michael@0: let file = a1.getResourceURI().QueryInterface(AM_Ci.nsIFileURL).file; michael@0: do_check_eq(file.parent.path, sourceDir.path); michael@0: michael@0: let rootUri = do_get_addon_root_uri(sourceDir, addon1.id); michael@0: let uri = a1.getResourceURI("/"); michael@0: do_check_eq(uri.spec, rootUri); michael@0: uri = a1.getResourceURI("install.rdf"); michael@0: do_check_eq(uri.spec, rootUri + "install.rdf"); michael@0: michael@0: // Check that upgrade is disabled for addons installed by file-pointers. michael@0: do_check_eq(a1.permissions & AddonManager.PERM_CAN_UPGRADE, 0); michael@0: run_test_2(); michael@0: }); michael@0: } michael@0: michael@0: // Tests that installing the addon from some other source doesn't clobber michael@0: // the original sources michael@0: function run_test_2() { michael@0: prepare_test({}, [ michael@0: "onNewInstall", michael@0: ]); michael@0: michael@0: let url = "http://localhost:" + gPort + "/addons/test_filepointer.xpi"; michael@0: AddonManager.getInstallForURL(url, function(install) { michael@0: ensure_test_completed(); michael@0: michael@0: prepare_test({ michael@0: "addon1@tests.mozilla.org": [ michael@0: "onInstalling" michael@0: ] michael@0: }, [ michael@0: "onDownloadStarted", michael@0: "onDownloadEnded", michael@0: "onInstallStarted", michael@0: "onInstallEnded" michael@0: ], callback_soon(check_test_2)); michael@0: michael@0: install.install(); michael@0: }, "application/x-xpinstall"); michael@0: } michael@0: michael@0: function check_test_2() { michael@0: restartManager(); michael@0: michael@0: AddonManager.getAddonByID(addon1.id, function(a1) { michael@0: do_check_neq(a1, null); michael@0: do_check_eq(a1.version, "2.0"); michael@0: michael@0: let file = a1.getResourceURI().QueryInterface(AM_Ci.nsIFileURL).file; michael@0: do_check_eq(file.parent.path, profileDir.path); michael@0: michael@0: let rootUri = do_get_addon_root_uri(profileDir, addon1.id); michael@0: let uri = a1.getResourceURI("/"); michael@0: do_check_eq(uri.spec, rootUri); michael@0: uri = a1.getResourceURI("install.rdf"); michael@0: do_check_eq(uri.spec, rootUri + "install.rdf"); michael@0: michael@0: let source = sourceDir.clone(); michael@0: source.append(addon1.id); michael@0: do_check_true(source.exists()); michael@0: michael@0: a1.uninstall(); michael@0: michael@0: do_execute_soon(run_test_3); michael@0: }); michael@0: } michael@0: michael@0: // Tests that uninstalling doesn't clobber the original sources michael@0: function run_test_3() { michael@0: restartManager(); michael@0: michael@0: writePointer(addon1.id); michael@0: michael@0: restartManager(); michael@0: michael@0: AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { michael@0: do_check_neq(a1, null); michael@0: do_check_eq(a1.version, "1.0"); michael@0: michael@0: a1.uninstall(); michael@0: michael@0: restartManager(); michael@0: michael@0: let source = sourceDir.clone(); michael@0: source.append(addon1.id); michael@0: do_check_true(source.exists()); michael@0: michael@0: do_execute_soon(run_test_4); michael@0: })); michael@0: } michael@0: michael@0: // Tests that misnaming a pointer doesn't clobber the sources michael@0: function run_test_4() { michael@0: writePointer("addon2@tests.mozilla.org", addon1.id); michael@0: michael@0: restartManager(); michael@0: michael@0: AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", michael@0: "addon2@tests.mozilla.org"], function([a1, a2]) { michael@0: do_check_eq(a1, null); michael@0: do_check_eq(a2, null); michael@0: michael@0: let source = sourceDir.clone(); michael@0: source.append(addon1.id); michael@0: do_check_true(source.exists()); michael@0: michael@0: let pointer = profileDir.clone(); michael@0: pointer.append("addon2@tests.mozilla.org"); michael@0: do_check_false(pointer.exists()); michael@0: michael@0: do_execute_soon(run_test_5); michael@0: }); michael@0: } michael@0: michael@0: // Tests that changing the ID of an existing add-on doesn't clobber the sources michael@0: function run_test_5() { michael@0: var dest = writeInstallRDFForExtension(addon1, sourceDir); michael@0: // Make sure the modification time changes enough to be detected. michael@0: setExtensionModifiedTime(dest, dest.lastModifiedTime - 5000); michael@0: writePointer(addon1.id); michael@0: michael@0: restartManager(); michael@0: michael@0: AddonManager.getAddonByID(addon1.id, callback_soon(function(a1) { michael@0: do_check_neq(a1, null); michael@0: do_check_eq(a1.version, "1.0"); michael@0: michael@0: writeInstallRDFForExtension(addon2, sourceDir, addon1.id); michael@0: michael@0: restartManager(); michael@0: michael@0: AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", michael@0: "addon2@tests.mozilla.org"], function([a1, a2]) { michael@0: do_check_eq(a1, null); michael@0: do_check_eq(a2, null); michael@0: michael@0: let source = sourceDir.clone(); michael@0: source.append(addon1.id); michael@0: do_check_true(source.exists()); michael@0: michael@0: let pointer = profileDir.clone(); michael@0: pointer.append(addon1.id); michael@0: do_check_false(pointer.exists()); michael@0: michael@0: do_execute_soon(run_test_6); michael@0: }); michael@0: })); michael@0: } michael@0: michael@0: // Removing the pointer file should uninstall the add-on michael@0: function run_test_6() { michael@0: var dest = writeInstallRDFForExtension(addon1, sourceDir); michael@0: // Make sure the modification time changes enough to be detected in run_test_8. michael@0: setExtensionModifiedTime(dest, dest.lastModifiedTime - 5000); michael@0: writePointer(addon1.id); michael@0: michael@0: restartManager(); michael@0: michael@0: AddonManager.getAddonByID(addon1.id, callback_soon(function(a1) { michael@0: do_check_neq(a1, null); michael@0: do_check_eq(a1.version, "1.0"); michael@0: michael@0: let pointer = profileDir.clone(); michael@0: pointer.append(addon1.id); michael@0: pointer.remove(false); michael@0: michael@0: restartManager(); michael@0: michael@0: AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { michael@0: do_check_eq(a1, null); michael@0: michael@0: do_execute_soon(run_test_7); michael@0: }); michael@0: })); michael@0: } michael@0: michael@0: // Removing the pointer file and replacing it with a directory should work michael@0: function run_test_7() { michael@0: writePointer(addon1.id); michael@0: michael@0: restartManager(); michael@0: michael@0: AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { michael@0: do_check_neq(a1, null); michael@0: do_check_eq(a1.version, "1.0"); michael@0: michael@0: let pointer = profileDir.clone(); michael@0: pointer.append(addon1.id); michael@0: pointer.remove(false); michael@0: michael@0: writeInstallRDFForExtension(addon1_2, profileDir); michael@0: michael@0: restartManager(); michael@0: michael@0: AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { michael@0: do_check_neq(a1, null); michael@0: do_check_eq(a1.version, "2.0"); michael@0: michael@0: a1.uninstall(); michael@0: michael@0: do_execute_soon(run_test_8); michael@0: }); michael@0: })); michael@0: } michael@0: michael@0: // Changes to the source files should be detected michael@0: function run_test_8() { michael@0: restartManager(); michael@0: michael@0: writePointer(addon1.id); michael@0: michael@0: restartManager(); michael@0: michael@0: AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { michael@0: do_check_neq(a1, null); michael@0: do_check_eq(a1.version, "1.0"); michael@0: michael@0: writeInstallRDFForExtension(addon1_2, sourceDir); michael@0: michael@0: restartManager(); michael@0: michael@0: AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { michael@0: do_check_neq(a1, null); michael@0: do_check_eq(a1.version, "2.0"); michael@0: michael@0: a1.uninstall(); michael@0: michael@0: do_execute_soon(run_test_9); michael@0: }); michael@0: })); michael@0: } michael@0: michael@0: // Removing the add-on the pointer file points at should uninstall the add-on michael@0: function run_test_9() { michael@0: restartManager(); michael@0: michael@0: var dest = writeInstallRDFForExtension(addon1, sourceDir); michael@0: writePointer(addon1.id); michael@0: michael@0: restartManager(); michael@0: michael@0: AddonManager.getAddonByID(addon1.id, callback_soon(function(a1) { michael@0: do_check_neq(a1, null); michael@0: do_check_eq(a1.version, "1.0"); michael@0: michael@0: dest.remove(true); michael@0: michael@0: restartManager(); michael@0: michael@0: AddonManager.getAddonByID(addon1.id, function(a1) { michael@0: do_check_eq(a1, null); michael@0: michael@0: let pointer = profileDir.clone(); michael@0: pointer.append(addon1.id); michael@0: do_check_false(pointer.exists()); michael@0: michael@0: do_execute_soon(run_test_10); michael@0: }); michael@0: })); michael@0: } michael@0: michael@0: // Tests that installing a new add-on by pointer with a relative path works michael@0: function run_test_10() { michael@0: writeInstallRDFForExtension(addon1, sourceDir); michael@0: writeRelativePointer(addon1.id); michael@0: michael@0: restartManager(); michael@0: michael@0: AddonManager.getAddonByID(addon1.id, function(a1) { michael@0: do_check_neq(a1, null); michael@0: do_check_eq(a1.version, "1.0"); michael@0: michael@0: let file = a1.getResourceURI().QueryInterface(AM_Ci.nsIFileURL).file; michael@0: do_check_eq(file.parent.path, sourceDir.path); michael@0: michael@0: let rootUri = do_get_addon_root_uri(sourceDir, addon1.id); michael@0: let uri = a1.getResourceURI("/"); michael@0: do_check_eq(uri.spec, rootUri); michael@0: uri = a1.getResourceURI("install.rdf"); michael@0: do_check_eq(uri.spec, rootUri + "install.rdf"); michael@0: michael@0: // Check that upgrade is disabled for addons installed by file-pointers. michael@0: do_check_eq(a1.permissions & AddonManager.PERM_CAN_UPGRADE, 0); michael@0: end_test(); michael@0: }); michael@0: }