Loading toolkit/mozapps/extensions/internal/XPIInstall.jsm +9 −8 Original line number Diff line number Diff line Loading @@ -3941,14 +3941,6 @@ var XPIInstall = { let addon = await loadManifestFromFile(source, location); // Ensure a staged addon is compatible with the current running version of // Firefox. If a prior version of the addon is installed, it will remain. if (!addon.isCompatible) { throw new Error( `Add-on ${addon.id} is not compatible with application version.` ); } if ( XPIDatabase.mustSign(addon.type) && addon.signedState <= AddonManager.SIGNEDSTATE_MISSING Loading @@ -3958,8 +3950,17 @@ var XPIInstall = { ); } // Import saved metadata before checking for compatibility. addon.importMetadata(metadata); // Ensure a staged addon is compatible with the current running version of // Firefox. If a prior version of the addon is installed, it will remain. if (!addon.isCompatible) { throw new Error( `Add-on ${addon.id} is not compatible with application version.` ); } logger.debug(`Processing install of ${id} in ${location.name}`); let existingAddon = XPIStates.findAddon(id); // This part of the startup file changes is called from Loading toolkit/mozapps/extensions/test/xpcshell/data/test_delay_updates_staged.json 0 → 100644 +32 −0 Original line number Diff line number Diff line { "addons": { "test_delay_update_staged_webext@tests.mozilla.org": { "updates": [ { "version": "2.0", "update_link": "http://example.com/addons/test_delay_update_staged_webextension_v2.xpi", "applications": { "gecko": { "strict_min_version": "1", "strict_max_version": "43" } } } ] }, "test_delay_update_staged_webext_no_update_url@tests.mozilla.org": { "updates": [ { "version": "2.0", "update_link": "http://example.com/addons/test_delay_update_staged_webextension_no_update_url_v2.xpi", "applications": { "gecko": { "strict_min_version": "1", "strict_max_version": "43" } } } ] } } } toolkit/mozapps/extensions/test/xpcshell/test_delay_update_webextension.js +176 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,9 @@ stageDir.append("staged"); const IGNORE_ID = "test_delay_update_ignore_webext@tests.mozilla.org"; const COMPLETE_ID = "test_delay_update_complete_webext@tests.mozilla.org"; const DEFER_ID = "test_delay_update_defer_webext@tests.mozilla.org"; const STAGED_ID = "test_delay_update_staged_webext@tests.mozilla.org"; const STAGED_NO_UPDATE_URL_ID = "test_delay_update_staged_webext_no_update_url@tests.mozilla.org"; const NOUPDATE_ID = "test_no_update_webext@tests.mozilla.org"; // Create and configure the HTTP server. Loading Loading @@ -58,6 +61,35 @@ const ADDONS = { }, }, }, test_delay_update_staged_webextension_v2: { "manifest.json": { manifest_version: 2, name: "Delay Upgrade", version: "2.0", applications: { gecko: { id: STAGED_ID, update_url: `http://example.com/data/test_delay_updates_staged.json`, strict_min_version: "1", strict_max_version: "41", }, }, }, }, test_delay_update_staged_webextension_no_update_url_v2: { "manifest.json": { manifest_version: 2, name: "Delay Upgrade", version: "2.0", applications: { gecko: { id: STAGED_NO_UPDATE_URL_ID, strict_min_version: "1", strict_max_version: "41", }, }, }, }, test_delay_update_ignore_webextension_v2: { "manifest.json": { manifest_version: 2, Loading Loading @@ -330,6 +362,150 @@ add_task(async function delay_updates_defer() { await promiseShutdownManager(); }); // add-on registers upgrade listener to deny update, completes after restart, // even though the updated XPI is incompatible - the information returned // by the update server defined in its manifest returns a compatible range add_task(async function delay_updates_staged() { await promiseStartupManager(); let extension = ExtensionTestUtils.loadExtension({ useAddonManager: "permanent", manifest: { version: "1.0", applications: { gecko: { id: STAGED_ID, update_url: `http://example.com/data/test_delay_updates_staged.json`, }, }, }, background() { browser.runtime.onUpdateAvailable.addListener(details => { browser.test.sendMessage("denied"); }); browser.test.sendMessage("ready"); }, }); await Promise.all([extension.startup(), extension.awaitMessage("ready")]); let addon = await promiseAddonByID(STAGED_ID); Assert.notEqual(addon, null); Assert.equal(addon.version, "1.0"); Assert.equal(addon.name, "Generated extension"); Assert.ok(addon.isCompatible); Assert.ok(!addon.appDisabled); Assert.ok(addon.isActive); Assert.equal(addon.type, "extension"); let update = await promiseFindAddonUpdates(addon); let install = update.updateAvailable; await promiseCompleteAllInstalls([install]); Assert.equal(install.state, AddonManager.STATE_POSTPONED); // upgrade is initially postponed let addon_postponed = await promiseAddonByID(STAGED_ID); Assert.notEqual(addon_postponed, null); Assert.equal(addon_postponed.version, "1.0"); Assert.equal(addon_postponed.name, "Generated extension"); Assert.ok(addon_postponed.isCompatible); Assert.ok(!addon_postponed.appDisabled); Assert.ok(addon_postponed.isActive); Assert.equal(addon_postponed.type, "extension"); // add-on reports an available upgrade, but denied it till next restart await extension.awaitMessage("denied"); await promiseRestartManager(); await extension.awaitStartup(); // add-on should have been updated during restart let addon_upgraded = await promiseAddonByID(STAGED_ID); Assert.notEqual(addon_upgraded, null); Assert.equal(addon_upgraded.version, "2.0"); Assert.equal(addon_upgraded.name, "Delay Upgrade"); Assert.ok(addon_upgraded.isCompatible); Assert.ok(!addon_upgraded.appDisabled); Assert.ok(addon_upgraded.isActive); Assert.equal(addon_upgraded.type, "extension"); await extension.unload(); await promiseShutdownManager(); }); // add-on registers upgrade listener to deny update, does not complete after // restart, because the updated XPI is incompatible - there is no update server // defined in its manifest, which could return a compatible range add_task(async function delay_updates_staged_no_update_url() { await promiseStartupManager(); let extension = ExtensionTestUtils.loadExtension({ useAddonManager: "permanent", manifest: { version: "1.0", applications: { gecko: { id: STAGED_NO_UPDATE_URL_ID, update_url: `http://example.com/data/test_delay_updates_staged.json`, }, }, }, background() { browser.runtime.onUpdateAvailable.addListener(details => { browser.test.sendMessage("denied"); }); browser.test.sendMessage("ready"); }, }); await Promise.all([extension.startup(), extension.awaitMessage("ready")]); let addon = await promiseAddonByID(STAGED_NO_UPDATE_URL_ID); Assert.notEqual(addon, null); Assert.equal(addon.version, "1.0"); Assert.equal(addon.name, "Generated extension"); Assert.ok(addon.isCompatible); Assert.ok(!addon.appDisabled); Assert.ok(addon.isActive); Assert.equal(addon.type, "extension"); let update = await promiseFindAddonUpdates(addon); let install = update.updateAvailable; await promiseCompleteAllInstalls([install]); Assert.equal(install.state, AddonManager.STATE_POSTPONED); // upgrade is initially postponed let addon_postponed = await promiseAddonByID(STAGED_NO_UPDATE_URL_ID); Assert.notEqual(addon_postponed, null); Assert.equal(addon_postponed.version, "1.0"); Assert.equal(addon_postponed.name, "Generated extension"); Assert.ok(addon_postponed.isCompatible); Assert.ok(!addon_postponed.appDisabled); Assert.ok(addon_postponed.isActive); Assert.equal(addon_postponed.type, "extension"); // add-on reports an available upgrade, but denied it till next restart await extension.awaitMessage("denied"); await promiseRestartManager(); await extension.awaitStartup(); // add-on should not have been updated during restart let addon_upgraded = await promiseAddonByID(STAGED_NO_UPDATE_URL_ID); Assert.notEqual(addon_upgraded, null); Assert.equal(addon_upgraded.version, "1.0"); Assert.equal(addon_upgraded.name, "Generated extension"); Assert.ok(addon_upgraded.isCompatible); Assert.ok(!addon_upgraded.appDisabled); Assert.ok(addon_upgraded.isActive); Assert.equal(addon_upgraded.type, "extension"); await extension.unload(); await promiseShutdownManager(); }); // browser.runtime.reload() without a pending upgrade should just reload. add_task(async function runtime_reload() { await promiseStartupManager(); Loading Loading
toolkit/mozapps/extensions/internal/XPIInstall.jsm +9 −8 Original line number Diff line number Diff line Loading @@ -3941,14 +3941,6 @@ var XPIInstall = { let addon = await loadManifestFromFile(source, location); // Ensure a staged addon is compatible with the current running version of // Firefox. If a prior version of the addon is installed, it will remain. if (!addon.isCompatible) { throw new Error( `Add-on ${addon.id} is not compatible with application version.` ); } if ( XPIDatabase.mustSign(addon.type) && addon.signedState <= AddonManager.SIGNEDSTATE_MISSING Loading @@ -3958,8 +3950,17 @@ var XPIInstall = { ); } // Import saved metadata before checking for compatibility. addon.importMetadata(metadata); // Ensure a staged addon is compatible with the current running version of // Firefox. If a prior version of the addon is installed, it will remain. if (!addon.isCompatible) { throw new Error( `Add-on ${addon.id} is not compatible with application version.` ); } logger.debug(`Processing install of ${id} in ${location.name}`); let existingAddon = XPIStates.findAddon(id); // This part of the startup file changes is called from Loading
toolkit/mozapps/extensions/test/xpcshell/data/test_delay_updates_staged.json 0 → 100644 +32 −0 Original line number Diff line number Diff line { "addons": { "test_delay_update_staged_webext@tests.mozilla.org": { "updates": [ { "version": "2.0", "update_link": "http://example.com/addons/test_delay_update_staged_webextension_v2.xpi", "applications": { "gecko": { "strict_min_version": "1", "strict_max_version": "43" } } } ] }, "test_delay_update_staged_webext_no_update_url@tests.mozilla.org": { "updates": [ { "version": "2.0", "update_link": "http://example.com/addons/test_delay_update_staged_webextension_no_update_url_v2.xpi", "applications": { "gecko": { "strict_min_version": "1", "strict_max_version": "43" } } } ] } } }
toolkit/mozapps/extensions/test/xpcshell/test_delay_update_webextension.js +176 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,9 @@ stageDir.append("staged"); const IGNORE_ID = "test_delay_update_ignore_webext@tests.mozilla.org"; const COMPLETE_ID = "test_delay_update_complete_webext@tests.mozilla.org"; const DEFER_ID = "test_delay_update_defer_webext@tests.mozilla.org"; const STAGED_ID = "test_delay_update_staged_webext@tests.mozilla.org"; const STAGED_NO_UPDATE_URL_ID = "test_delay_update_staged_webext_no_update_url@tests.mozilla.org"; const NOUPDATE_ID = "test_no_update_webext@tests.mozilla.org"; // Create and configure the HTTP server. Loading Loading @@ -58,6 +61,35 @@ const ADDONS = { }, }, }, test_delay_update_staged_webextension_v2: { "manifest.json": { manifest_version: 2, name: "Delay Upgrade", version: "2.0", applications: { gecko: { id: STAGED_ID, update_url: `http://example.com/data/test_delay_updates_staged.json`, strict_min_version: "1", strict_max_version: "41", }, }, }, }, test_delay_update_staged_webextension_no_update_url_v2: { "manifest.json": { manifest_version: 2, name: "Delay Upgrade", version: "2.0", applications: { gecko: { id: STAGED_NO_UPDATE_URL_ID, strict_min_version: "1", strict_max_version: "41", }, }, }, }, test_delay_update_ignore_webextension_v2: { "manifest.json": { manifest_version: 2, Loading Loading @@ -330,6 +362,150 @@ add_task(async function delay_updates_defer() { await promiseShutdownManager(); }); // add-on registers upgrade listener to deny update, completes after restart, // even though the updated XPI is incompatible - the information returned // by the update server defined in its manifest returns a compatible range add_task(async function delay_updates_staged() { await promiseStartupManager(); let extension = ExtensionTestUtils.loadExtension({ useAddonManager: "permanent", manifest: { version: "1.0", applications: { gecko: { id: STAGED_ID, update_url: `http://example.com/data/test_delay_updates_staged.json`, }, }, }, background() { browser.runtime.onUpdateAvailable.addListener(details => { browser.test.sendMessage("denied"); }); browser.test.sendMessage("ready"); }, }); await Promise.all([extension.startup(), extension.awaitMessage("ready")]); let addon = await promiseAddonByID(STAGED_ID); Assert.notEqual(addon, null); Assert.equal(addon.version, "1.0"); Assert.equal(addon.name, "Generated extension"); Assert.ok(addon.isCompatible); Assert.ok(!addon.appDisabled); Assert.ok(addon.isActive); Assert.equal(addon.type, "extension"); let update = await promiseFindAddonUpdates(addon); let install = update.updateAvailable; await promiseCompleteAllInstalls([install]); Assert.equal(install.state, AddonManager.STATE_POSTPONED); // upgrade is initially postponed let addon_postponed = await promiseAddonByID(STAGED_ID); Assert.notEqual(addon_postponed, null); Assert.equal(addon_postponed.version, "1.0"); Assert.equal(addon_postponed.name, "Generated extension"); Assert.ok(addon_postponed.isCompatible); Assert.ok(!addon_postponed.appDisabled); Assert.ok(addon_postponed.isActive); Assert.equal(addon_postponed.type, "extension"); // add-on reports an available upgrade, but denied it till next restart await extension.awaitMessage("denied"); await promiseRestartManager(); await extension.awaitStartup(); // add-on should have been updated during restart let addon_upgraded = await promiseAddonByID(STAGED_ID); Assert.notEqual(addon_upgraded, null); Assert.equal(addon_upgraded.version, "2.0"); Assert.equal(addon_upgraded.name, "Delay Upgrade"); Assert.ok(addon_upgraded.isCompatible); Assert.ok(!addon_upgraded.appDisabled); Assert.ok(addon_upgraded.isActive); Assert.equal(addon_upgraded.type, "extension"); await extension.unload(); await promiseShutdownManager(); }); // add-on registers upgrade listener to deny update, does not complete after // restart, because the updated XPI is incompatible - there is no update server // defined in its manifest, which could return a compatible range add_task(async function delay_updates_staged_no_update_url() { await promiseStartupManager(); let extension = ExtensionTestUtils.loadExtension({ useAddonManager: "permanent", manifest: { version: "1.0", applications: { gecko: { id: STAGED_NO_UPDATE_URL_ID, update_url: `http://example.com/data/test_delay_updates_staged.json`, }, }, }, background() { browser.runtime.onUpdateAvailable.addListener(details => { browser.test.sendMessage("denied"); }); browser.test.sendMessage("ready"); }, }); await Promise.all([extension.startup(), extension.awaitMessage("ready")]); let addon = await promiseAddonByID(STAGED_NO_UPDATE_URL_ID); Assert.notEqual(addon, null); Assert.equal(addon.version, "1.0"); Assert.equal(addon.name, "Generated extension"); Assert.ok(addon.isCompatible); Assert.ok(!addon.appDisabled); Assert.ok(addon.isActive); Assert.equal(addon.type, "extension"); let update = await promiseFindAddonUpdates(addon); let install = update.updateAvailable; await promiseCompleteAllInstalls([install]); Assert.equal(install.state, AddonManager.STATE_POSTPONED); // upgrade is initially postponed let addon_postponed = await promiseAddonByID(STAGED_NO_UPDATE_URL_ID); Assert.notEqual(addon_postponed, null); Assert.equal(addon_postponed.version, "1.0"); Assert.equal(addon_postponed.name, "Generated extension"); Assert.ok(addon_postponed.isCompatible); Assert.ok(!addon_postponed.appDisabled); Assert.ok(addon_postponed.isActive); Assert.equal(addon_postponed.type, "extension"); // add-on reports an available upgrade, but denied it till next restart await extension.awaitMessage("denied"); await promiseRestartManager(); await extension.awaitStartup(); // add-on should not have been updated during restart let addon_upgraded = await promiseAddonByID(STAGED_NO_UPDATE_URL_ID); Assert.notEqual(addon_upgraded, null); Assert.equal(addon_upgraded.version, "1.0"); Assert.equal(addon_upgraded.name, "Generated extension"); Assert.ok(addon_upgraded.isCompatible); Assert.ok(!addon_upgraded.appDisabled); Assert.ok(addon_upgraded.isActive); Assert.equal(addon_upgraded.type, "extension"); await extension.unload(); await promiseShutdownManager(); }); // browser.runtime.reload() without a pending upgrade should just reload. add_task(async function runtime_reload() { await promiseStartupManager(); Loading