summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/test/xpcshell/test_ext_manifest.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /toolkit/components/extensions/test/xpcshell/test_ext_manifest.js
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/extensions/test/xpcshell/test_ext_manifest.js')
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_manifest.js488
1 files changed, 488 insertions, 0 deletions
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_manifest.js b/toolkit/components/extensions/test/xpcshell/test_ext_manifest.js
new file mode 100644
index 0000000000..e627512d9b
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_manifest.js
@@ -0,0 +1,488 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+ChromeUtils.defineESModuleGetters(this, {
+ AddonManager: "resource://gre/modules/AddonManager.sys.mjs",
+});
+
+AddonTestUtils.init(this);
+AddonTestUtils.createAppInfo(
+ "xpcshell@tests.mozilla.org",
+ "XPCShell",
+ "1",
+ "42"
+);
+
+async function testManifest(manifest, expectedError) {
+ ExtensionTestUtils.failOnSchemaWarnings(false);
+ let normalized = await ExtensionTestUtils.normalizeManifest(manifest);
+ ExtensionTestUtils.failOnSchemaWarnings(true);
+
+ if (expectedError) {
+ ok(
+ expectedError.test(normalized.error),
+ `Should have an error for ${JSON.stringify(manifest)}, got ${
+ normalized.error
+ }`
+ );
+ } else {
+ ok(
+ !normalized.error,
+ `Should not have an error ${JSON.stringify(manifest)}, ${
+ normalized.error
+ }`
+ );
+ }
+ return normalized.errors;
+}
+
+async function testIconPaths(icon, manifest, expectedError) {
+ let normalized = await ExtensionTestUtils.normalizeManifest(manifest);
+
+ if (expectedError) {
+ ok(
+ expectedError.test(normalized.error),
+ `Should have an error for ${JSON.stringify(icon)}`
+ );
+ } else {
+ ok(!normalized.error, `Should not have an error ${JSON.stringify(icon)}`);
+ }
+}
+
+add_setup(async () => {
+ await AddonTestUtils.promiseStartupManager();
+});
+
+add_task(async function test_manifest() {
+ let badpaths = ["", " ", "\t", "http://foo.com/icon.png"];
+ for (let path of badpaths) {
+ await testIconPaths(
+ path,
+ {
+ icons: path,
+ },
+ /Error processing icons/
+ );
+
+ await testIconPaths(
+ path,
+ {
+ icons: {
+ 16: path,
+ },
+ },
+ /Error processing icons/
+ );
+ }
+
+ let paths = [
+ "icon.png",
+ "/icon.png",
+ "./icon.png",
+ "path to an icon.png",
+ " icon.png",
+ ];
+ for (let path of paths) {
+ // manifest.icons is an object
+ await testIconPaths(
+ path,
+ {
+ icons: path,
+ },
+ /Error processing icons/
+ );
+
+ await testIconPaths(path, {
+ icons: {
+ 16: path,
+ },
+ });
+ }
+});
+
+add_task(async function test_manifest_warnings_on_unexpected_props() {
+ let extension = await ExtensionTestUtils.loadExtension({
+ manifest: {
+ background: {
+ scripts: ["bg.js"],
+ wrong_prop: true,
+ },
+ },
+ files: {
+ "bg.js": "",
+ },
+ });
+
+ ExtensionTestUtils.failOnSchemaWarnings(false);
+ await extension.startup();
+ ExtensionTestUtils.failOnSchemaWarnings(true);
+
+ // Retrieve the warning message collected by the Extension class
+ // packagingWarning method.
+ const { warnings } = extension.extension;
+ equal(warnings.length, 1, "Got the expected number of manifest warnings");
+
+ const expectedMessage =
+ "Reading manifest: Warning processing background.wrong_prop";
+ ok(
+ warnings[0].startsWith(expectedMessage),
+ "Got the expected warning message format"
+ );
+
+ await extension.unload();
+});
+
+add_task(async function test_mv2_scripting_permission_always_enabled() {
+ let warnings = await testManifest({
+ manifest_version: 2,
+ permissions: ["scripting"],
+ });
+
+ Assert.deepEqual(warnings, [], "Got no warnings");
+});
+
+add_task(
+ {
+ pref_set: [["extensions.manifestV3.enabled", true]],
+ },
+ async function test_mv3_scripting_permission_always_enabled() {
+ let warnings = await testManifest({
+ manifest_version: 3,
+ permissions: ["scripting"],
+ });
+
+ Assert.deepEqual(warnings, [], "Got no warnings");
+ }
+);
+
+add_task(async function test_simpler_version_format() {
+ const TEST_CASES = [
+ // Valid cases
+ { version: "0", expectWarning: false },
+ { version: "0.0", expectWarning: false },
+ { version: "0.0.0", expectWarning: false },
+ { version: "0.0.0.0", expectWarning: false },
+ { version: "0.0.0.1", expectWarning: false },
+ { version: "0.0.0.999999999", expectWarning: false },
+ { version: "0.0.1.0", expectWarning: false },
+ { version: "0.0.999999999", expectWarning: false },
+ { version: "0.1.0.0", expectWarning: false },
+ { version: "0.999999999", expectWarning: false },
+ { version: "1", expectWarning: false },
+ { version: "1.0", expectWarning: false },
+ { version: "1.0.0", expectWarning: false },
+ { version: "1.0.0.0", expectWarning: false },
+ { version: "1.2.3.4", expectWarning: false },
+ { version: "999999999", expectWarning: false },
+ {
+ version: "999999999.999999999.999999999.999999999",
+ expectWarning: false,
+ },
+ // Invalid cases
+ { version: ".", expectWarning: true },
+ { version: ".999999999", expectWarning: true },
+ { version: "0.0.0.0.0", expectWarning: true },
+ { version: "0.0.0.00001", expectWarning: true },
+ { version: "0.0.0.0010", expectWarning: true },
+ { version: "0.0.00001", expectWarning: true },
+ { version: "0.0.001", expectWarning: true },
+ { version: "0.0.01.0", expectWarning: true },
+ { version: "0.01.0", expectWarning: true },
+ { version: "00001", expectWarning: true },
+ { version: "0001", expectWarning: true },
+ { version: "001", expectWarning: true },
+ { version: "01", expectWarning: true },
+ { version: "01.0", expectWarning: true },
+ { version: "099999", expectWarning: true },
+ { version: "0999999999", expectWarning: true },
+ { version: "1.00000", expectWarning: true },
+ { version: "1.1.-1", expectWarning: true },
+ { version: "1.1000000000", expectWarning: true },
+ { version: "1.1pre1aa", expectWarning: true },
+ { version: "1.2.1000000000", expectWarning: true },
+ { version: "1.2.3.4-a", expectWarning: true },
+ { version: "1.2.3.4.5", expectWarning: true },
+ { version: "1000000000", expectWarning: true },
+ { version: "1000000000.0.0.0", expectWarning: true },
+ { version: "999999999.", expectWarning: true },
+ ];
+
+ for (const { version, expectWarning } of TEST_CASES) {
+ const normalized = await ExtensionTestUtils.normalizeManifest({ version });
+
+ if (expectWarning) {
+ Assert.deepEqual(
+ normalized.errors,
+ [
+ `Warning processing version: version must be a version string ` +
+ `consisting of at most 4 integers of at most 9 digits without ` +
+ `leading zeros, and separated with dots`,
+ ],
+ `expected warning for version: ${version}`
+ );
+ } else {
+ Assert.deepEqual(
+ normalized.errors,
+ [],
+ `expected no warning for version: ${version}`
+ );
+ }
+ }
+});
+
+add_task(async function test_applications() {
+ const id = "some@id";
+ const updateURL = "https://example.com/updates/";
+
+ let extension = await ExtensionTestUtils.loadExtension({
+ manifest: {
+ manifest_version: 2,
+ applications: {
+ gecko: { id, update_url: updateURL },
+ },
+ },
+ useAddonManager: "temporary",
+ });
+
+ ExtensionTestUtils.failOnSchemaWarnings(false);
+ await extension.startup();
+ ExtensionTestUtils.failOnSchemaWarnings(true);
+
+ Assert.deepEqual(extension.extension.warnings, [], "expected no warnings");
+
+ const addon = await AddonManager.getAddonByID(extension.id);
+ ok(addon, "got an add-on");
+ equal(addon.id, id, "got expected ID");
+ equal(addon.updateURL, updateURL, "got expected update URL");
+
+ await extension.unload();
+});
+
+add_task(
+ {
+ pref_set: [["extensions.manifestV3.enabled", true]],
+ },
+ async function test_applications_key_mv3() {
+ let warnings = await testManifest({
+ manifest_version: 3,
+ applications: {},
+ });
+
+ Assert.deepEqual(
+ warnings,
+ [`Property "applications" is unsupported in Manifest Version 3`],
+ `Manifest v3 with "applications" key logs an error.`
+ );
+ }
+);
+
+add_task(async function test_bss_gecko_android() {
+ const addonId = "some@id";
+ const isAndroid = AppConstants.platform == "android";
+
+ const TEST_CASES = [
+ {
+ title: "gecko_android overrides gecko",
+ browser_specific_settings: {
+ gecko: {
+ id: addonId,
+ strict_min_version: "2",
+ strict_max_version: "2",
+ },
+ gecko_android: {
+ strict_min_version: "1",
+ strict_max_version: "1",
+ },
+ },
+ expectedError: isAndroid
+ ? `Add-on ${addonId} is not compatible with application version. add-on minVersion: 1. add-on maxVersion: 1.`
+ : `Add-on ${addonId} is not compatible with application version. add-on minVersion: 2. add-on maxVersion: 2.`,
+ },
+ {
+ title:
+ "strict_min_version in gecko_android overrides gecko.strict_min_version",
+ browser_specific_settings: {
+ gecko: {
+ id: addonId,
+ strict_min_version: "2",
+ strict_max_version: "3",
+ },
+ gecko_android: {
+ strict_min_version: "3",
+ },
+ },
+ expectedError: isAndroid
+ ? `Add-on ${addonId} is not compatible with application version. add-on minVersion: 3. add-on maxVersion: 3.`
+ : `Add-on ${addonId} is not compatible with application version. add-on minVersion: 2. add-on maxVersion: 3.`,
+ },
+ {
+ title:
+ "strict_max_version in gecko_android overrides gecko.strict_max_version",
+ browser_specific_settings: {
+ gecko: {
+ id: addonId,
+ strict_min_version: "2",
+ strict_max_version: "2",
+ },
+ gecko_android: {
+ strict_max_version: "3",
+ },
+ },
+ expectedError: isAndroid
+ ? `Add-on ${addonId} is not compatible with application version. add-on minVersion: 2. add-on maxVersion: 3.`
+ : `Add-on ${addonId} is not compatible with application version. add-on minVersion: 2. add-on maxVersion: 2.`,
+ },
+ {
+ title: "no gecko_android",
+ browser_specific_settings: {
+ gecko: {
+ id: addonId,
+ strict_min_version: "2",
+ strict_max_version: "2",
+ },
+ },
+ expectedError: `Add-on ${addonId} is not compatible with application version. add-on minVersion: 2. add-on maxVersion: 2.`,
+ },
+ {
+ title: "empty gecko_android",
+ browser_specific_settings: {
+ gecko: {
+ id: addonId,
+ strict_min_version: "2",
+ strict_max_version: "2",
+ },
+ gecko_android: {},
+ },
+ expectedError: `Add-on ${addonId} is not compatible with application version. add-on minVersion: 2. add-on maxVersion: 2.`,
+ },
+ {
+ title: "empty strict min/max versions in gecko_android",
+ browser_specific_settings: {
+ gecko: {
+ id: addonId,
+ strict_min_version: "2",
+ strict_max_version: "2",
+ },
+ gecko_android: {
+ strict_min_version: "",
+ strict_max_version: "",
+ },
+ },
+ expectedError: `Add-on ${addonId} is not compatible with application version. add-on minVersion: 2. add-on maxVersion: 2.`,
+ },
+ {
+ title: "unsupported prop in gecko_android",
+ browser_specific_settings: {
+ gecko: {
+ id: addonId,
+ strict_min_version: "2",
+ strict_max_version: "2",
+ },
+ gecko_android: {
+ aPropThatIsNotSupported: "aPropThatIsNotSupported",
+ },
+ },
+ expectedError: `Add-on ${addonId} is not compatible with application version. add-on minVersion: 2. add-on maxVersion: 2.`,
+ },
+ {
+ title: "only strict min/max version in gecko_android",
+ browser_specific_settings: {
+ gecko: {
+ id: addonId,
+ },
+ gecko_android: {
+ strict_min_version: "3",
+ strict_max_version: "4",
+ },
+ },
+ expectedError: isAndroid
+ ? `Add-on ${addonId} is not compatible with application version. add-on minVersion: 3. add-on maxVersion: 4.`
+ : null,
+ },
+ {
+ title: "only strict_min_version in gecko_android",
+ browser_specific_settings: {
+ gecko: {
+ id: addonId,
+ },
+ gecko_android: {
+ // The app version is set to `42` at the top of the file.
+ strict_min_version: "100",
+ },
+ },
+ expectedError: isAndroid
+ ? `Add-on ${addonId} is not compatible with application version. add-on minVersion: 100.`
+ : null,
+ },
+ ];
+
+ for (const {
+ title,
+ browser_specific_settings,
+ expectedError,
+ } of TEST_CASES) {
+ info(`verifying: ${title}`);
+
+ // This task is mainly about verifying `bss.gecko_android` and some test
+ // cases require a "valid" compatibility range by default, which would
+ // break the assumption below (that the install is going to fail). This is
+ // why we skip null errors, but only on non-Android builds.
+ if (expectedError === null) {
+ notEqual(
+ AppConstants.platform,
+ "android",
+ `${title} - expected no error on a non-Android build`
+ );
+ continue;
+ }
+
+ const manifest = {
+ manifest_version: 2,
+ version: "1.0",
+ browser_specific_settings,
+ };
+
+ const extension = ExtensionTestUtils.loadExtension({
+ manifest,
+ useAddonManager: "temporary",
+ });
+
+ await Assert.rejects(
+ extension.startup(),
+ new RegExp(expectedError),
+ `${title} - expected error: ${expectedError}`
+ );
+
+ const addon = await AddonManager.getAddonByID(addonId);
+ equal(addon, null, "add-on is not installed");
+ }
+});
+
+add_task(
+ { skip_if: AppConstants.platform !== "android" },
+ async function test_bss_gecko_android_only() {
+ const extension = ExtensionTestUtils.loadExtension({
+ manifest: {
+ manifest_version: 2,
+ version: "1.0",
+ browser_specific_settings: {
+ gecko_android: {
+ strict_min_version: "0",
+ },
+ },
+ },
+ });
+
+ await extension.startup();
+
+ const { manifest } = extension.extension;
+ equal(
+ manifest.browser_specific_settings.gecko_android.strict_min_version,
+ "0",
+ "expected strict min version"
+ );
+
+ await extension.unload();
+ }
+);