summaryrefslogtreecommitdiffstats
path: root/toolkit/mozapps/extensions/test/xpcshell/test_filepointer.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/mozapps/extensions/test/xpcshell/test_filepointer.js')
-rw-r--r--toolkit/mozapps/extensions/test/xpcshell/test_filepointer.js327
1 files changed, 327 insertions, 0 deletions
diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_filepointer.js b/toolkit/mozapps/extensions/test/xpcshell/test_filepointer.js
new file mode 100644
index 0000000000..c72737d4fe
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_filepointer.js
@@ -0,0 +1,327 @@
+/* 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);
+});