/* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ // Tests that various operations with file pointers work and do not affect the // source files const ID1 = "addon1@tests.mozilla.org"; const ID2 = "addon2@tests.mozilla.org"; const profileDir = gProfD.clone(); profileDir.append("extensions"); profileDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755); const sourceDir = gProfD.clone(); sourceDir.append("source"); function promiseWriteWebExtension(path, data) { let files = ExtensionTestCommon.generateFiles(data); return AddonTestUtils.promiseWriteFilesToDir(path, files); } function promiseWritePointer(aId, aName) { let path = PathUtils.join(profileDir.path, aName || aId); let target = PathUtils.join(sourceDir.path, do_get_expected_addon_name(aId)); return IOUtils.writeUTF8(path, target); } function promiseWriteRelativePointer(aId, aName) { let path = PathUtils.join(profileDir.path, aName || aId); let absTarget = sourceDir.clone(); absTarget.append(do_get_expected_addon_name(aId)); let relTarget = absTarget.getRelativeDescriptor(profileDir); return IOUtils.writeUTF8(path, relTarget); } add_task(async function setup() { ok(TEST_UNPACKED, "Pointer files only work with unpacked directories"); // Unpacked extensions are never signed, so this can only run with // signature checks disabled. Services.prefs.setBoolPref(PREF_XPI_SIGNATURES_REQUIRED, false); createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); }); // Tests that installing a new add-on by pointer works add_task(async function test_new_pointer_install() { let target = PathUtils.join(sourceDir.path, ID1); await promiseWriteWebExtension(target, { manifest: { version: "1.0", browser_specific_settings: { gecko: { id: ID1 } }, }, }); await promiseWritePointer(ID1); await promiseStartupManager(); let addon = await AddonManager.getAddonByID(ID1); notEqual(addon, null); equal(addon.version, "1.0"); let file = getAddonFile(addon); equal(file.parent.path, sourceDir.path); let rootUri = do_get_addon_root_uri(sourceDir, ID1); let uri = addon.getResourceURI(); equal(uri.spec, rootUri); // Check that upgrade is disabled for addons installed by file-pointers. equal(addon.permissions & AddonManager.PERM_CAN_UPGRADE, 0); }); // Tests that installing the addon from some other source doesn't clobber // the original sources add_task(async function test_addon_over_pointer() { let xpi = AddonTestUtils.createTempWebExtensionFile({ manifest: { version: "2.0", browser_specific_settings: { gecko: { id: ID1 } }, }, }); let install = await AddonManager.getInstallForFile( xpi, "application/x-xpinstall" ); await install.install(); let addon = await AddonManager.getAddonByID(ID1); notEqual(addon, null); equal(addon.version, "2.0"); let url = addon.getResourceURI(); if (url instanceof Ci.nsIJARURI) { url = url.JARFile; } let { file } = url.QueryInterface(Ci.nsIFileURL); equal(file.parent.path, profileDir.path); let rootUri = do_get_addon_root_uri(profileDir, ID1); let uri = addon.getResourceURI(); equal(uri.spec, rootUri); let source = sourceDir.clone(); source.append(ID1); ok(source.exists()); await addon.uninstall(); }); // Tests that uninstalling doesn't clobber the original sources add_task(async function test_uninstall_pointer() { await promiseWritePointer(ID1); await promiseRestartManager(); let addon = await AddonManager.getAddonByID(ID1); notEqual(addon, null); equal(addon.version, "1.0"); await addon.uninstall(); let source = sourceDir.clone(); source.append(ID1); ok(source.exists()); }); // Tests that misnaming a pointer doesn't clobber the sources add_task(async function test_bad_pointer() { await promiseWritePointer(ID2, ID1); let [a1, a2] = await AddonManager.getAddonsByIDs([ID1, ID2]); equal(a1, null); equal(a2, null); let source = sourceDir.clone(); source.append(ID1); ok(source.exists()); let pointer = profileDir.clone(); pointer.append(ID2); ok(!pointer.exists()); }); // Tests that changing the ID of an existing add-on doesn't clobber the sources add_task(async function test_bad_pointer_id() { let dir = sourceDir.clone(); dir.append(ID1); // Make sure the modification time changes enough to be detected. setExtensionModifiedTime(dir, dir.lastModifiedTime - 5000); await promiseWritePointer(ID1); await promiseRestartManager(); let addon = await AddonManager.getAddonByID(ID1); notEqual(addon, null); equal(addon.version, "1.0"); await promiseWriteWebExtension(dir.path, { manifest: { version: "1.0", browser_specific_settings: { gecko: { id: ID2 } }, }, }); setExtensionModifiedTime(dir, dir.lastModifiedTime - 5000); await promiseRestartManager(); let [a1, a2] = await AddonManager.getAddonsByIDs([ID1, ID2]); equal(a1, null); equal(a2, null); let source = sourceDir.clone(); source.append(ID1); ok(source.exists()); let pointer = profileDir.clone(); pointer.append(ID1); ok(!pointer.exists()); }); // Removing the pointer file should uninstall the add-on add_task(async function test_remove_pointer() { let dir = sourceDir.clone(); dir.append(ID1); await promiseWriteWebExtension(dir.path, { manifest: { version: "1.0", browser_specific_settings: { gecko: { id: ID1 } }, }, }); setExtensionModifiedTime(dir, dir.lastModifiedTime - 5000); await promiseWritePointer(ID1); await promiseRestartManager(); let addon = await AddonManager.getAddonByID(ID1); notEqual(addon, null); equal(addon.version, "1.0"); let pointer = profileDir.clone(); pointer.append(ID1); pointer.remove(false); await promiseRestartManager(); addon = await AddonManager.getAddonByID(ID1); equal(addon, null); }); // Removing the pointer file and replacing it with a directory should work add_task(async function test_replace_pointer() { await promiseWritePointer(ID1); await promiseRestartManager(); let addon = await AddonManager.getAddonByID(ID1); notEqual(addon, null); equal(addon.version, "1.0"); let pointer = profileDir.clone(); pointer.append(ID1); pointer.remove(false); await promiseWriteWebExtension(PathUtils.join(profileDir.path, ID1), { manifest: { version: "2.0", browser_specific_settings: { gecko: { id: ID1 } }, }, }); await promiseRestartManager(); addon = await AddonManager.getAddonByID(ID1); notEqual(addon, null); equal(addon.version, "2.0"); await addon.uninstall(); }); // Changes to the source files should be detected add_task(async function test_change_pointer_sources() { await promiseWritePointer(ID1); await promiseRestartManager(); let addon = await AddonManager.getAddonByID(ID1); notEqual(addon, null); equal(addon.version, "1.0"); let dir = sourceDir.clone(); dir.append(ID1); await promiseWriteWebExtension(dir.path, { manifest: { version: "2.0", browser_specific_settings: { gecko: { id: ID1 } }, }, }); setExtensionModifiedTime(dir, dir.lastModifiedTime - 5000); await promiseRestartManager(); addon = await AddonManager.getAddonByID(ID1); notEqual(addon, null); equal(addon.version, "2.0"); await addon.uninstall(); }); // Removing the add-on the pointer file points at should uninstall the add-on add_task(async function test_remove_pointer_target() { let target = PathUtils.join(sourceDir.path, ID1); await promiseWriteWebExtension(target, { manifest: { version: "1.0", browser_specific_settings: { gecko: { id: ID1 } }, }, }); await promiseWritePointer(ID1); await promiseRestartManager(); let addon = await AddonManager.getAddonByID(ID1); notEqual(addon, null); equal(addon.version, "1.0"); await IOUtils.remove(target, { recursive: true }); await promiseRestartManager(); addon = await AddonManager.getAddonByID(ID1); equal(addon, null); let pointer = profileDir.clone(); pointer.append(ID1); ok(!pointer.exists()); }); // Tests that installing a new add-on by pointer with a relative path works add_task(async function test_new_relative_pointer() { let target = PathUtils.join(sourceDir.path, ID1); await promiseWriteWebExtension(target, { manifest: { version: "1.0", browser_specific_settings: { gecko: { id: ID1 } }, }, }); await promiseWriteRelativePointer(ID1); await promiseRestartManager(); let addon = await AddonManager.getAddonByID(ID1); equal(addon.version, "1.0"); let { file } = addon.getResourceURI().QueryInterface(Ci.nsIFileURL); equal(file.parent.path, sourceDir.path); let rootUri = do_get_addon_root_uri(sourceDir, ID1); let uri = addon.getResourceURI(); equal(uri.spec, rootUri); // Check that upgrade is disabled for addons installed by file-pointers. equal(addon.permissions & AddonManager.PERM_CAN_UPGRADE, 0); });