summaryrefslogtreecommitdiffstats
path: root/toolkit/mozapps/extensions/test/xpcshell/test_webextension.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/mozapps/extensions/test/xpcshell/test_webextension.js')
-rw-r--r--toolkit/mozapps/extensions/test/xpcshell/test_webextension.js513
1 files changed, 513 insertions, 0 deletions
diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_webextension.js b/toolkit/mozapps/extensions/test/xpcshell/test_webextension.js
new file mode 100644
index 0000000000..dd4cbce8a5
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_webextension.js
@@ -0,0 +1,513 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+const ID = "webextension1@tests.mozilla.org";
+
+const profileDir = gProfD.clone();
+profileDir.append("extensions");
+
+const ADDONS = {
+ webextension_1: {
+ "manifest.json": {
+ name: "Web Extension Name",
+ version: "1.0",
+ manifest_version: 2,
+ applications: {
+ gecko: {
+ id: "webextension1@tests.mozilla.org",
+ },
+ },
+ icons: {
+ "48": "icon48.png",
+ "64": "icon64.png",
+ },
+ },
+ "chrome.manifest": "content webex ./\n",
+ },
+ webextension_3: {
+ "manifest.json": {
+ name: "Web Extensiøn __MSG_name__",
+ description: "Descriptïon __MSG_desc__ of add-on",
+ version: "1.0",
+ manifest_version: 2,
+ default_locale: "en",
+ applications: {
+ gecko: {
+ id: "webextension3@tests.mozilla.org",
+ },
+ },
+ },
+ "_locales/en/messages.json": {
+ name: {
+ message: "foo ☹",
+ description: "foo",
+ },
+ desc: {
+ message: "bar ☹",
+ description: "bar",
+ },
+ },
+ "_locales/fr/messages.json": {
+ name: {
+ message: "le foo ☺",
+ description: "foo",
+ },
+ desc: {
+ message: "le bar ☺",
+ description: "bar",
+ },
+ },
+ },
+};
+
+let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(
+ Ci.nsIChromeRegistry
+);
+
+createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42");
+
+const { GlobalManager } = ChromeUtils.import(
+ "resource://gre/modules/Extension.jsm",
+ null
+);
+
+add_task(async function test_1() {
+ await promiseStartupManager();
+
+ equal(GlobalManager.extensionMap.size, 0);
+
+ let { addon } = await AddonTestUtils.promiseInstallXPI(ADDONS.webextension_1);
+
+ equal(GlobalManager.extensionMap.size, 1);
+ ok(GlobalManager.extensionMap.has(ID));
+
+ Assert.throws(
+ () =>
+ chromeReg.convertChromeURL(
+ Services.io.newURI("chrome://webex/content/webex.xul")
+ ),
+ error => error.result == Cr.NS_ERROR_FILE_NOT_FOUND,
+ "Chrome manifest should not have been registered"
+ );
+
+ let uri = do_get_addon_root_uri(profileDir, ID);
+
+ checkAddon(ID, addon, {
+ version: "1.0",
+ name: "Web Extension Name",
+ isCompatible: true,
+ appDisabled: false,
+ isActive: true,
+ isSystem: false,
+ type: "extension",
+ isWebExtension: true,
+ signedState: AddonManager.SIGNEDSTATE_PRIVILEGED,
+ iconURL: `${uri}icon48.png`,
+ });
+
+ // Should persist through a restart
+ await promiseShutdownManager();
+
+ equal(GlobalManager.extensionMap.size, 0);
+
+ await promiseStartupManager();
+
+ equal(GlobalManager.extensionMap.size, 1);
+ ok(GlobalManager.extensionMap.has(ID));
+
+ addon = await promiseAddonByID(ID);
+
+ uri = do_get_addon_root_uri(profileDir, ID);
+
+ checkAddon(ID, addon, {
+ version: "1.0",
+ name: "Web Extension Name",
+ isCompatible: true,
+ appDisabled: false,
+ isActive: true,
+ isSystem: false,
+ type: "extension",
+ signedState: AddonManager.SIGNEDSTATE_PRIVILEGED,
+ iconURL: `${uri}icon48.png`,
+ });
+
+ await addon.disable();
+
+ equal(GlobalManager.extensionMap.size, 0);
+
+ await addon.enable();
+
+ equal(GlobalManager.extensionMap.size, 1);
+ ok(GlobalManager.extensionMap.has(ID));
+
+ await addon.uninstall();
+
+ equal(GlobalManager.extensionMap.size, 0);
+ Assert.ok(!GlobalManager.extensionMap.has(ID));
+
+ await promiseShutdownManager();
+});
+
+// Writing the manifest direct to the profile should work
+add_task(async function test_2() {
+ await promiseWriteWebManifestForExtension(
+ {
+ name: "Web Extension Name",
+ version: "1.0",
+ manifest_version: 2,
+ applications: {
+ gecko: {
+ id: ID,
+ },
+ },
+ },
+ profileDir
+ );
+
+ await promiseStartupManager();
+
+ let addon = await promiseAddonByID(ID);
+ checkAddon(ID, addon, {
+ version: "1.0",
+ name: "Web Extension Name",
+ isCompatible: true,
+ appDisabled: false,
+ isActive: true,
+ isSystem: false,
+ type: "extension",
+ signedState: AddonManager.SIGNEDSTATE_PRIVILEGED,
+ });
+
+ await addon.uninstall();
+
+ await promiseRestartManager();
+});
+
+add_task(async function test_manifest_localization() {
+ const extensionId = "webextension3@tests.mozilla.org";
+
+ let { addon } = await AddonTestUtils.promiseInstallXPI(ADDONS.webextension_3);
+
+ await addon.disable();
+
+ checkAddon(ID, addon, {
+ name: "Web Extensiøn foo ☹",
+ description: "Descriptïon bar ☹ of add-on",
+ });
+
+ await restartWithLocales(["fr-FR"]);
+
+ addon = await promiseAddonByID(extensionId);
+ checkAddon(ID, addon, {
+ name: "Web Extensiøn le foo ☺",
+ description: "Descriptïon le bar ☺ of add-on",
+ });
+
+ await restartWithLocales(["de"]);
+
+ addon = await promiseAddonByID(extensionId);
+ checkAddon(ID, addon, {
+ name: "Web Extensiøn foo ☹",
+ description: "Descriptïon bar ☹ of add-on",
+ });
+
+ await addon.uninstall();
+});
+
+// Missing version should cause a failure
+add_task(async function test_3() {
+ await promiseWriteWebManifestForExtension(
+ {
+ name: "Web Extension Name",
+ manifest_version: 2,
+ applications: {
+ gecko: {
+ id: ID,
+ },
+ },
+ },
+ profileDir
+ );
+
+ await promiseRestartManager();
+
+ let addon = await promiseAddonByID(ID);
+ Assert.equal(addon, null);
+
+ let file = getFileForAddon(profileDir, ID);
+ Assert.ok(!file.exists());
+
+ await promiseRestartManager();
+});
+
+// Incorrect manifest version should cause a failure
+add_task(async function test_4() {
+ await promiseWriteWebManifestForExtension(
+ {
+ name: "Web Extension Name",
+ version: "1.0",
+ manifest_version: 1,
+ applications: {
+ gecko: {
+ id: ID,
+ },
+ },
+ },
+ profileDir
+ );
+
+ await promiseRestartManager();
+
+ let addon = await promiseAddonByID(ID);
+ Assert.equal(addon, null);
+
+ let file = getFileForAddon(profileDir, ID);
+ Assert.ok(!file.exists());
+
+ await promiseRestartManager();
+});
+
+// Test that the "options_ui" manifest section is processed correctly.
+add_task(async function test_options_ui() {
+ let OPTIONS_RE = /^moz-extension:\/\/[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}\/options\.html$/;
+
+ const extensionId = "webextension@tests.mozilla.org";
+ let addon = await promiseInstallWebExtension({
+ manifest: {
+ applications: { gecko: { id: extensionId } },
+ options_ui: {
+ page: "options.html",
+ },
+ },
+ });
+
+ checkAddon(extensionId, addon, {
+ optionsType: AddonManager.OPTIONS_TYPE_INLINE_BROWSER,
+ });
+
+ ok(
+ OPTIONS_RE.test(addon.optionsURL),
+ "Addon should have a moz-extension: options URL for /options.html"
+ );
+
+ await addon.uninstall();
+
+ const ID2 = "webextension2@tests.mozilla.org";
+ addon = await promiseInstallWebExtension({
+ manifest: {
+ applications: { gecko: { id: ID2 } },
+ options_ui: {
+ page: "options.html",
+ open_in_tab: true,
+ },
+ },
+ });
+
+ checkAddon(ID2, addon, {
+ optionsType: AddonManager.OPTIONS_TYPE_TAB,
+ });
+
+ ok(
+ OPTIONS_RE.test(addon.optionsURL),
+ "Addon should have a moz-extension: options URL for /options.html"
+ );
+
+ await addon.uninstall();
+});
+
+// Test that experiments permissions add the appropriate dependencies.
+add_task(async function test_experiments_dependencies() {
+ let addon = await promiseInstallWebExtension({
+ manifest: {
+ applications: { gecko: { id: "meh@experiment" } },
+ permissions: ["experiments.meh"],
+ },
+ });
+
+ checkAddon(addon.id, addon, {
+ dependencies: ["meh@experiments.addons.mozilla.org"],
+ // Add-on should be app disabled due to missing dependencies
+ appDisabled: true,
+ });
+
+ await addon.uninstall();
+});
+
+add_task(async function developerShouldOverride() {
+ let addon = await promiseInstallWebExtension({
+ manifest: {
+ default_locale: "en",
+ developer: {
+ name: "__MSG_name__",
+ url: "__MSG_url__",
+ },
+ author: "Will be overridden by developer",
+ homepage_url: "https://will.be.overridden",
+ },
+ files: {
+ "_locales/en/messages.json": `{
+ "name": {
+ "message": "en name"
+ },
+ "url": {
+ "message": "https://example.net/en"
+ }
+ }`,
+ },
+ });
+
+ checkAddon(ID, addon, {
+ creator: "en name",
+ homepageURL: "https://example.net/en",
+ });
+
+ await addon.uninstall();
+});
+
+add_task(async function developerEmpty() {
+ for (let developer of [{}, null, { name: null, url: null }]) {
+ let addon = await promiseInstallWebExtension({
+ manifest: {
+ author: "Some author",
+ developer,
+ homepage_url: "https://example.net",
+ manifest_version: 2,
+ name: "Web Extension Name",
+ version: "1.0",
+ },
+ });
+
+ checkAddon(ID, addon, {
+ creator: "Some author",
+ homepageURL: "https://example.net",
+ });
+
+ await addon.uninstall();
+ }
+});
+
+add_task(async function authorNotString() {
+ ExtensionTestUtils.failOnSchemaWarnings(false);
+ for (let author of [{}, [], 42]) {
+ let addon = await promiseInstallWebExtension({
+ manifest: {
+ author,
+ manifest_version: 2,
+ name: "Web Extension Name",
+ version: "1.0",
+ },
+ });
+
+ checkAddon(ID, addon, {
+ creator: null,
+ });
+
+ await addon.uninstall();
+ }
+ ExtensionTestUtils.failOnSchemaWarnings(true);
+});
+
+add_task(async function testThemeExtension() {
+ let addon = await promiseInstallWebExtension({
+ manifest: {
+ author: "Some author",
+ manifest_version: 2,
+ name: "Web Extension Name",
+ version: "1.0",
+ theme: { images: { theme_frame: "example.png" } },
+ },
+ });
+
+ checkAddon(ID, addon, {
+ creator: "Some author",
+ version: "1.0",
+ name: "Web Extension Name",
+ isCompatible: true,
+ appDisabled: false,
+ isActive: false,
+ userDisabled: true,
+ isSystem: false,
+ type: "theme",
+ isWebExtension: true,
+ signedState: AddonManager.SIGNEDSTATE_PRIVILEGED,
+ });
+
+ await addon.uninstall();
+
+ // Also test one without a proper 'theme' section.
+ ExtensionTestUtils.failOnSchemaWarnings(false);
+ addon = await promiseInstallWebExtension({
+ manifest: {
+ author: "Some author",
+ manifest_version: 2,
+ name: "Web Extension Name",
+ version: "1.0",
+ theme: null,
+ },
+ });
+ ExtensionTestUtils.failOnSchemaWarnings(true);
+
+ checkAddon(ID, addon, {
+ type: "extension",
+ isWebExtension: true,
+ });
+
+ await addon.uninstall();
+});
+
+// Test that we can update from a webextension to a webextension-theme
+add_task(async function test_theme_upgrade() {
+ // First install a regular webextension
+ let addon = await promiseInstallWebExtension({
+ manifest: {
+ version: "1.0",
+ name: "Test WebExtension 1 (temporary)",
+ applications: {
+ gecko: {
+ id: ID,
+ },
+ },
+ },
+ });
+
+ checkAddon(ID, addon, {
+ version: "1.0",
+ name: "Test WebExtension 1 (temporary)",
+ isCompatible: true,
+ appDisabled: false,
+ isActive: true,
+ type: "extension",
+ signedState: AddonManager.SIGNEDSTATE_PRIVILEGED,
+ });
+
+ // Create a webextension theme with the same ID
+ addon = await promiseInstallWebExtension({
+ manifest: {
+ version: "2.0",
+ name: "Test WebExtension 1 (temporary)",
+ applications: {
+ gecko: {
+ id: ID,
+ },
+ },
+ theme: { images: { theme_frame: "example.png" } },
+ },
+ });
+
+ checkAddon(ID, addon, {
+ version: "2.0",
+ name: "Test WebExtension 1 (temporary)",
+ isCompatible: true,
+ appDisabled: false,
+ isActive: true,
+ // This is what we're really interested in:
+ type: "theme",
+ isWebExtension: true,
+ });
+
+ await addon.uninstall();
+
+ addon = await promiseAddonByID(ID);
+ Assert.equal(addon, null);
+});