diff options
Diffstat (limited to 'toolkit/mozapps/webextensions/test/xpcshell/test_proxies.js')
-rw-r--r-- | toolkit/mozapps/webextensions/test/xpcshell/test_proxies.js | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/toolkit/mozapps/webextensions/test/xpcshell/test_proxies.js b/toolkit/mozapps/webextensions/test/xpcshell/test_proxies.js new file mode 100644 index 0000000000..7b28c78f2b --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpcshell/test_proxies.js @@ -0,0 +1,240 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests the semantics of extension proxy files and symlinks + +Components.utils.import("resource://gre/modules/AppConstants.jsm"); +Components.utils.import("resource://gre/modules/osfile.jsm"); + +var ADDONS = [ + { + id: "proxy1@tests.mozilla.org", + dirId: "proxy1@tests.mozilla.com", + type: "proxy" + }, + { + id: "proxy2@tests.mozilla.org", + type: "proxy" + }, + { + id: "symlink1@tests.mozilla.org", + dirId: "symlink1@tests.mozilla.com", + type: "symlink" + }, + { + id: "symlink2@tests.mozilla.org", + type: "symlink" + } +]; + +var METADATA = { + version: "2.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "2", + maxVersion: "2" + }] +} + +const ios = AM_Cc["@mozilla.org/network/io-service;1"].getService(AM_Ci.nsIIOService); + +const LocalFile = Components.Constructor("@mozilla.org/file/local;1", + "nsILocalFile", "initWithPath"); +const Process = Components.Constructor("@mozilla.org/process/util;1", + "nsIProcess", "init"); + +const gHaveSymlinks = AppConstants.platform != "win"; + + +function createSymlink(aSource, aDest) { + if (aSource instanceof AM_Ci.nsIFile) + aSource = aSource.path; + if (aDest instanceof AM_Ci.nsIFile) + aDest = aDest.path; + + return OS.File.unixSymLink(aSource, aDest); +} + +function writeFile(aData, aFile) { + if (!aFile.parent.exists()) + aFile.parent.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0o755); + + var fos = AM_Cc["@mozilla.org/network/file-output-stream;1"]. + createInstance(AM_Ci.nsIFileOutputStream); + fos.init(aFile, + FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | FileUtils.MODE_TRUNCATE, + FileUtils.PERMS_FILE, 0); + fos.write(aData, aData.length); + fos.close(); +} + +function checkAddonsExist() { + for (let addon of ADDONS) { + let file = addon.directory.clone(); + file.append("install.rdf"); + do_check_true(file.exists(), Components.stack.caller); + } +} + + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2"); + + add_task(run_proxy_tests); + + if (gHaveSymlinks) + add_task(run_symlink_tests); + + run_next_test(); +} + +function* run_proxy_tests() { + if (!gHaveSymlinks) { + ADDONS = ADDONS.filter(a => a.type != "symlink"); + } + + for (let addon of ADDONS) { + addon.directory = gTmpD.clone(); + addon.directory.append(addon.id); + + addon.proxyFile = profileDir.clone(); + addon.proxyFile.append(addon.dirId || addon.id); + + METADATA.id = addon.id; + METADATA.name = addon.id; + writeInstallRDFToDir(METADATA, gTmpD); + + if (addon.type == "proxy") { + writeFile(addon.directory.path, addon.proxyFile) + } + else if (addon.type == "symlink") { + yield createSymlink(addon.directory, addon.proxyFile) + } + } + + startupManager(); + + // Check that all add-ons original sources still exist after invalid + // add-ons have been removed at startup. + checkAddonsExist(); + + return new Promise(resolve => { + AddonManager.getAddonsByIDs(ADDONS.map(addon => addon.id), resolve); + }).then(addons => { + try { + for (let [i, addon] of addons.entries()) { + // Ensure that valid proxied add-ons were installed properly on + // platforms that support the installation method. + print(ADDONS[i].id, + ADDONS[i].dirId, + ADDONS[i].dirId != null, + ADDONS[i].type == "symlink"); + do_check_eq(addon == null, + ADDONS[i].dirId != null); + + if (addon != null) { + let fixURL = url => { + if (AppConstants.platform == "macosx") + return url.replace(RegExp(`^file:///private/`), "file:///"); + return url; + }; + + // Check that proxied add-ons do not have upgrade permissions. + do_check_eq(addon.permissions & AddonManager.PERM_CAN_UPGRADE, 0); + + // Check that getResourceURI points to the right place. + do_check_eq(ios.newFileURI(ADDONS[i].directory).spec, + fixURL(addon.getResourceURI().spec), + `Base resource URL resolves as expected`); + + let file = ADDONS[i].directory.clone(); + file.append("install.rdf"); + + do_check_eq(ios.newFileURI(file).spec, + fixURL(addon.getResourceURI("install.rdf").spec), + `Resource URLs resolve as expected`); + + addon.uninstall(); + } + } + + // Check that original sources still exist after explicit uninstall. + restartManager(); + checkAddonsExist(); + + shutdownManager(); + + // Check that all of the proxy files have been removed and remove + // the original targets. + for (let addon of ADDONS) { + equal(addon.proxyFile.exists(), addon.dirId != null, + `Proxy file ${addon.proxyFile.path} should exist?`); + addon.directory.remove(true); + try { + addon.proxyFile.remove(false); + } catch (e) {} + } + } + catch (e) { + do_throw(e); + } + }); +} + +function* run_symlink_tests() { + // Check that symlinks are not followed out of a directory tree + // when deleting an add-on. + + METADATA.id = "unpacked@test.mozilla.org"; + METADATA.name = METADATA.id; + METADATA.unpack = "true"; + + let tempDirectory = gTmpD.clone(); + tempDirectory.append(METADATA.id); + + let tempFile = tempDirectory.clone(); + tempFile.append("test.txt"); + tempFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, 0o644); + + let addonDirectory = profileDir.clone(); + addonDirectory.append(METADATA.id); + + writeInstallRDFToDir(METADATA, profileDir); + + let symlink = addonDirectory.clone(); + symlink.append(tempDirectory.leafName); + yield createSymlink(tempDirectory, symlink); + + // Make sure that the symlink was created properly. + let file = symlink.clone(); + file.append(tempFile.leafName); + file.normalize(); + do_check_eq(file.path.replace(/^\/private\//, "/"), tempFile.path); + + startupManager(); + + return new Promise(resolve => { + AddonManager.getAddonByID(METADATA.id, resolve); + }).then(addon => { + do_check_neq(addon, null); + + addon.uninstall(); + + restartManager(); + shutdownManager(); + + // Check that the install directory is gone. + do_check_false(addonDirectory.exists()); + + // Check that the temp file is not gone. + do_check_true(tempFile.exists()); + + tempDirectory.remove(true); + }); +} + |