Loading mobile/android/geckoview/api.txt +1 −0 Original line number Diff line number Diff line Loading @@ -2145,6 +2145,7 @@ package org.mozilla.geckoview { field public static final int ERROR_POSTPONED = -101; field public static final int ERROR_SIGNEDSTATE_REQUIRED = -5; field public static final int ERROR_UNEXPECTED_ADDON_TYPE = -6; field public static final int ERROR_UNEXPECTED_ADDON_VERSION = -9; field public static final int ERROR_USER_CANCELED = -100; } Loading mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtension.java +3 −0 Original line number Diff line number Diff line Loading @@ -1525,6 +1525,8 @@ public class WebExtension { public static final int ERROR_SIGNEDSTATE_REQUIRED = -5; /** The downloaded extension had a different type than expected. */ public static final int ERROR_UNEXPECTED_ADDON_TYPE = -6; /** The downloaded extension had a different version than expected */ public static final int ERROR_UNEXPECTED_ADDON_VERSION = -9; /** The extension did not have the expected ID. */ public static final int ERROR_INCORRECT_ID = -7; /** The extension did not have the expected ID. */ Loading Loading @@ -1572,6 +1574,7 @@ public class WebExtension { ErrorCodes.ERROR_FILE_ACCESS, ErrorCodes.ERROR_SIGNEDSTATE_REQUIRED, ErrorCodes.ERROR_UNEXPECTED_ADDON_TYPE, ErrorCodes.ERROR_UNEXPECTED_ADDON_VERSION, ErrorCodes.ERROR_INCORRECT_ID, ErrorCodes.ERROR_INVALID_DOMAIN, ErrorCodes.ERROR_USER_CANCELED, Loading toolkit/mozapps/extensions/AddonManager.jsm +2 −0 Original line number Diff line number Diff line Loading @@ -3819,6 +3819,8 @@ var AddonManager = { ["ERROR_INCORRECT_ID", -7], // The addon install_origins does not list the 3rd party domain. ["ERROR_INVALID_DOMAIN", -8], // Updates only: The downloaded add-on had a different version than expected. ["ERROR_UNEXPECTED_ADDON_VERSION", -9], ]), // The update check timed out ERROR_TIMEOUT: -1, Loading toolkit/mozapps/extensions/internal/XPIInstall.jsm +11 −2 Original line number Diff line number Diff line Loading @@ -1277,7 +1277,8 @@ class AddonInstall { * @param {object} [options.icons] * Optional icons for the add-on * @param {string} [options.version] * An optional version for the add-on * The expected version for the add-on. * Required for updates, i.e. when existingAddon is set. * @param {Object?} [options.telemetryInfo] * An optional object which provides details about the installation source * included in the addon manager telemetry events. Loading Loading @@ -1613,6 +1614,13 @@ class AddonInstall { `Refusing to change addon type from ${this.existingAddon.type} to ${this.addon.type}`, ]); } if (this.version !== this.addon.version) { return Promise.reject([ AddonManager.ERROR_UNEXPECTED_ADDON_VERSION, `Expected addon version ${this.version} instead of ${this.addon.version}` ]); } } if (XPIDatabase.mustSign(this.addon.type)) { Loading Loading @@ -2210,7 +2218,8 @@ var DownloadAddonInstall = class extends AddonInstall { * @param {Object} [options.icons] * Optional icons for the add-on * @param {string} [options.version] * An optional version for the add-on * The expected version for the add-on. * Required for updates, i.e. when existingAddon is set. * @param {function(string) : Promise<void>} [options.promptHandler] * A callback to prompt the user before installing. * @param {boolean} [options.sendCookies] Loading toolkit/mozapps/extensions/test/xpcshell/test_updateversion.js 0 → 100644 +101 −0 Original line number Diff line number Diff line /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ // The test extension uses an insecure update url. Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); let server = AddonTestUtils.createHttpServer({ hosts: ["example.com"] }); async function serverRegisterUpdate({ id, version, actualVersion }) { let xpi = await createTempWebExtensionFile({ manifest: { version: actualVersion, applications: { gecko: { id } }, }, }); server.registerFile("/addon.xpi", xpi); AddonTestUtils.registerJSON(server, "/update.json", { addons: { [id]: { updates: [{ version, update_link: "http://example.com/addon.xpi" }], }, }, }); } add_task(async function setup() { await ExtensionTestUtils.startAddonManager(); }); add_task(async function test_update_version_mismatch() { const ID = "updateversion@tests.mozilla.org"; await promiseInstallWebExtension({ manifest: { version: "1.0", applications: { gecko: { id: ID, update_url: "http://example.com/update.json", }, }, }, }); await serverRegisterUpdate({ id: ID, version: "2.00", actualVersion: "2.000", }); let addon = await promiseAddonByID(ID); Assert.notEqual(addon, null); Assert.equal(addon.version, "1.0"); let update = await promiseFindAddonUpdates( addon, AddonManager.UPDATE_WHEN_USER_REQUESTED ); let install = update.updateAvailable; Assert.notEqual(install, false, "Found available update"); Assert.equal(install.version, "2.00"); Assert.equal(install.state, AddonManager.STATE_AVAILABLE); Assert.equal(install.existingAddon, addon); await Assert.rejects( install.install(), err => install.error == AddonManager.ERROR_UNEXPECTED_ADDON_VERSION, "Should refuse installation when downloaded version does not match" ); await addon.uninstall(); }); add_task(async function test_update_version_empty() { const ID = "updateversionempty@tests.mozilla.org"; await serverRegisterUpdate({ id: ID, version: "", actualVersion: "1.0" }); await promiseInstallWebExtension({ manifest: { version: "0", applications: { gecko: { id: ID, update_url: "http://example.com/update.json", }, }, }, }); let addon = await promiseAddonByID(ID); Assert.notEqual(addon, null); Assert.equal(addon.version, "0"); let update = await promiseFindAddonUpdates( addon, AddonManager.UPDATE_WHEN_USER_REQUESTED ); // The only item in the updates array has version "" (empty). This should not // be offered as an available update because it is certainly not newer. Assert.equal(update.updateAvailable, false, "No update found"); await addon.uninstall(); }); Loading
mobile/android/geckoview/api.txt +1 −0 Original line number Diff line number Diff line Loading @@ -2145,6 +2145,7 @@ package org.mozilla.geckoview { field public static final int ERROR_POSTPONED = -101; field public static final int ERROR_SIGNEDSTATE_REQUIRED = -5; field public static final int ERROR_UNEXPECTED_ADDON_TYPE = -6; field public static final int ERROR_UNEXPECTED_ADDON_VERSION = -9; field public static final int ERROR_USER_CANCELED = -100; } Loading
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtension.java +3 −0 Original line number Diff line number Diff line Loading @@ -1525,6 +1525,8 @@ public class WebExtension { public static final int ERROR_SIGNEDSTATE_REQUIRED = -5; /** The downloaded extension had a different type than expected. */ public static final int ERROR_UNEXPECTED_ADDON_TYPE = -6; /** The downloaded extension had a different version than expected */ public static final int ERROR_UNEXPECTED_ADDON_VERSION = -9; /** The extension did not have the expected ID. */ public static final int ERROR_INCORRECT_ID = -7; /** The extension did not have the expected ID. */ Loading Loading @@ -1572,6 +1574,7 @@ public class WebExtension { ErrorCodes.ERROR_FILE_ACCESS, ErrorCodes.ERROR_SIGNEDSTATE_REQUIRED, ErrorCodes.ERROR_UNEXPECTED_ADDON_TYPE, ErrorCodes.ERROR_UNEXPECTED_ADDON_VERSION, ErrorCodes.ERROR_INCORRECT_ID, ErrorCodes.ERROR_INVALID_DOMAIN, ErrorCodes.ERROR_USER_CANCELED, Loading
toolkit/mozapps/extensions/AddonManager.jsm +2 −0 Original line number Diff line number Diff line Loading @@ -3819,6 +3819,8 @@ var AddonManager = { ["ERROR_INCORRECT_ID", -7], // The addon install_origins does not list the 3rd party domain. ["ERROR_INVALID_DOMAIN", -8], // Updates only: The downloaded add-on had a different version than expected. ["ERROR_UNEXPECTED_ADDON_VERSION", -9], ]), // The update check timed out ERROR_TIMEOUT: -1, Loading
toolkit/mozapps/extensions/internal/XPIInstall.jsm +11 −2 Original line number Diff line number Diff line Loading @@ -1277,7 +1277,8 @@ class AddonInstall { * @param {object} [options.icons] * Optional icons for the add-on * @param {string} [options.version] * An optional version for the add-on * The expected version for the add-on. * Required for updates, i.e. when existingAddon is set. * @param {Object?} [options.telemetryInfo] * An optional object which provides details about the installation source * included in the addon manager telemetry events. Loading Loading @@ -1613,6 +1614,13 @@ class AddonInstall { `Refusing to change addon type from ${this.existingAddon.type} to ${this.addon.type}`, ]); } if (this.version !== this.addon.version) { return Promise.reject([ AddonManager.ERROR_UNEXPECTED_ADDON_VERSION, `Expected addon version ${this.version} instead of ${this.addon.version}` ]); } } if (XPIDatabase.mustSign(this.addon.type)) { Loading Loading @@ -2210,7 +2218,8 @@ var DownloadAddonInstall = class extends AddonInstall { * @param {Object} [options.icons] * Optional icons for the add-on * @param {string} [options.version] * An optional version for the add-on * The expected version for the add-on. * Required for updates, i.e. when existingAddon is set. * @param {function(string) : Promise<void>} [options.promptHandler] * A callback to prompt the user before installing. * @param {boolean} [options.sendCookies] Loading
toolkit/mozapps/extensions/test/xpcshell/test_updateversion.js 0 → 100644 +101 −0 Original line number Diff line number Diff line /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ // The test extension uses an insecure update url. Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); let server = AddonTestUtils.createHttpServer({ hosts: ["example.com"] }); async function serverRegisterUpdate({ id, version, actualVersion }) { let xpi = await createTempWebExtensionFile({ manifest: { version: actualVersion, applications: { gecko: { id } }, }, }); server.registerFile("/addon.xpi", xpi); AddonTestUtils.registerJSON(server, "/update.json", { addons: { [id]: { updates: [{ version, update_link: "http://example.com/addon.xpi" }], }, }, }); } add_task(async function setup() { await ExtensionTestUtils.startAddonManager(); }); add_task(async function test_update_version_mismatch() { const ID = "updateversion@tests.mozilla.org"; await promiseInstallWebExtension({ manifest: { version: "1.0", applications: { gecko: { id: ID, update_url: "http://example.com/update.json", }, }, }, }); await serverRegisterUpdate({ id: ID, version: "2.00", actualVersion: "2.000", }); let addon = await promiseAddonByID(ID); Assert.notEqual(addon, null); Assert.equal(addon.version, "1.0"); let update = await promiseFindAddonUpdates( addon, AddonManager.UPDATE_WHEN_USER_REQUESTED ); let install = update.updateAvailable; Assert.notEqual(install, false, "Found available update"); Assert.equal(install.version, "2.00"); Assert.equal(install.state, AddonManager.STATE_AVAILABLE); Assert.equal(install.existingAddon, addon); await Assert.rejects( install.install(), err => install.error == AddonManager.ERROR_UNEXPECTED_ADDON_VERSION, "Should refuse installation when downloaded version does not match" ); await addon.uninstall(); }); add_task(async function test_update_version_empty() { const ID = "updateversionempty@tests.mozilla.org"; await serverRegisterUpdate({ id: ID, version: "", actualVersion: "1.0" }); await promiseInstallWebExtension({ manifest: { version: "0", applications: { gecko: { id: ID, update_url: "http://example.com/update.json", }, }, }, }); let addon = await promiseAddonByID(ID); Assert.notEqual(addon, null); Assert.equal(addon.version, "0"); let update = await promiseFindAddonUpdates( addon, AddonManager.UPDATE_WHEN_USER_REQUESTED ); // The only item in the updates array has version "" (empty). This should not // be offered as an available update because it is certainly not newer. Assert.equal(update.updateAvailable, false, "No update found"); await addon.uninstall(); });