From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../extensions/test/xpcshell/test_install.js | 1050 ++++++++++++++++++++ 1 file changed, 1050 insertions(+) create mode 100644 toolkit/mozapps/extensions/test/xpcshell/test_install.js (limited to 'toolkit/mozapps/extensions/test/xpcshell/test_install.js') diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_install.js b/toolkit/mozapps/extensions/test/xpcshell/test_install.js new file mode 100644 index 0000000000..2d2ee3df24 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_install.js @@ -0,0 +1,1050 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +var testserver = createHttpServer({ hosts: ["example.com"] }); +var gInstallDate; + +const ADDONS = { + test_install1: { + manifest: { + name: "Test 1", + version: "1.0", + browser_specific_settings: { gecko: { id: "addon1@tests.mozilla.org" } }, + }, + }, + test_install2_1: { + manifest: { + name: "Test 2", + version: "2.0", + browser_specific_settings: { gecko: { id: "addon2@tests.mozilla.org" } }, + }, + }, + test_install2_2: { + manifest: { + name: "Test 2", + version: "3.0", + browser_specific_settings: { gecko: { id: "addon2@tests.mozilla.org" } }, + }, + }, + test_install3: { + manifest: { + name: "Test 3", + version: "1.0", + browser_specific_settings: { + gecko: { + id: "addon3@tests.mozilla.org", + strict_min_version: "0", + strict_max_version: "0", + update_url: "http://example.com/update.json", + }, + }, + }, + }, +}; + +const XPIS = {}; + +// The test extension uses an insecure update url. +Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); +Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false); + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +const UPDATE_JSON = { + addons: { + "addon3@tests.mozilla.org": { + updates: [ + { + version: "1.0", + applications: { + gecko: { + strict_min_version: "0", + strict_max_version: "2", + }, + }, + }, + ], + }, + }, +}; + +const GETADDONS_JSON = { + page_size: 25, + page_count: 1, + count: 1, + next: null, + previous: null, + results: [ + { + name: "Test 2", + type: "extension", + guid: "addon2@tests.mozilla.org", + current_version: { + version: "1.0", + files: [ + { + size: 2, + url: "http://example.com/test_install2_1.xpi", + }, + ], + }, + authors: [ + { + name: "Test Creator", + url: "http://example.com/creator.html", + }, + ], + summary: "Repository summary", + description: "Repository description", + }, + ], +}; + +function checkInstall(install, expected) { + for (let [key, value] of Object.entries(expected)) { + if (value instanceof Ci.nsIURI) { + equal( + install[key] && install[key].spec, + value.spec, + `Expected value of install.${key}` + ); + } else { + deepEqual(install[key], value, `Expected value of install.${key}`); + } + } +} + +add_task(async function setup() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + for (let [name, data] of Object.entries(ADDONS)) { + XPIS[name] = AddonTestUtils.createTempWebExtensionFile(data); + testserver.registerFile(`/addons/${name}.xpi`, XPIS[name]); + } + + await promiseStartupManager(); + + // Create and configure the HTTP server. + AddonTestUtils.registerJSON(testserver, "/update.json", UPDATE_JSON); + testserver.registerDirectory("/data/", do_get_file("data")); + testserver.registerPathHandler("/redirect", function (aRequest, aResponse) { + aResponse.setStatusLine(null, 301, "Moved Permanently"); + let url = aRequest.host + ":" + aRequest.port + aRequest.queryString; + aResponse.setHeader("Location", "http://" + url); + }); + gPort = testserver.identity.primaryPort; +}); + +// Checks that an install from a local file proceeds as expected +add_task(async function test_install_file() { + let [, install] = await Promise.all([ + AddonTestUtils.promiseInstallEvent("onNewInstall"), + AddonManager.getInstallForFile(XPIS.test_install1), + ]); + + let uri = Services.io.newFileURI(XPIS.test_install1); + checkInstall(install, { + type: "extension", + version: "1.0", + name: "Test 1", + state: AddonManager.STATE_DOWNLOADED, + sourceURI: uri, + }); + + let { addon } = install; + checkAddon("addon1@tests.mozilla.org", addon, { + install, + sourceURI: uri, + }); + notEqual(addon.syncGUID, null); + equal( + addon.getResourceURI("manifest.json").spec, + `jar:${uri.spec}!/manifest.json` + ); + + let activeInstalls = await AddonManager.getAllInstalls(); + equal(activeInstalls.length, 1); + equal(activeInstalls[0], install); + + let fooInstalls = await AddonManager.getInstallsByTypes(["foo"]); + equal(fooInstalls.length, 0); + + let extensionInstalls = await AddonManager.getInstallsByTypes(["extension"]); + equal(extensionInstalls.length, 1); + equal(extensionInstalls[0], install); + + await expectEvents( + { + addonEvents: { + "addon1@tests.mozilla.org": [ + { event: "onInstalling" }, + { event: "onInstalled" }, + ], + }, + }, + () => install.install() + ); + + addon = await AddonManager.getAddonByID("addon1@tests.mozilla.org"); + ok(addon); + + ok(!hasFlag(addon.permissions, AddonManager.PERM_CAN_ENABLE)); + ok(hasFlag(addon.permissions, AddonManager.PERM_CAN_DISABLE)); + + let updateDate = Date.now(); + + await promiseRestartManager(); + + activeInstalls = await AddonManager.getAllInstalls(); + equal(activeInstalls, 0); + + let a1 = await AddonManager.getAddonByID("addon1@tests.mozilla.org"); + let uri2 = do_get_addon_root_uri(profileDir, "addon1@tests.mozilla.org"); + + checkAddon("addon1@tests.mozilla.org", a1, { + type: "extension", + version: "1.0", + name: "Test 1", + foreignInstall: false, + sourceURI: Services.io.newFileURI(XPIS.test_install1), + }); + + notEqual(a1.syncGUID, null); + ok(a1.syncGUID.length >= 9); + + ok(isExtensionInBootstrappedList(profileDir, a1.id)); + ok(XPIS.test_install1.exists()); + do_check_in_crash_annotation(a1.id, a1.version); + + let difference = a1.installDate.getTime() - updateDate; + if (Math.abs(difference) > MAX_TIME_DIFFERENCE) { + do_throw("Add-on install time was out by " + difference + "ms"); + } + + difference = a1.updateDate.getTime() - updateDate; + if (Math.abs(difference) > MAX_TIME_DIFFERENCE) { + do_throw("Add-on update time was out by " + difference + "ms"); + } + + equal(a1.getResourceURI("manifest.json").spec, uri2 + "manifest.json"); + + // Ensure that extension bundle (or icon if unpacked) has updated + // lastModifiedDate. + let testFile = getAddonFile(a1); + ok(testFile.exists()); + difference = testFile.lastModifiedTime - Date.now(); + ok(Math.abs(difference) < MAX_TIME_DIFFERENCE); + + await a1.uninstall(); + let { id, version } = a1; + await promiseRestartManager(); + do_check_not_in_crash_annotation(id, version); +}); + +// Tests that an install from a url downloads. +add_task(async function test_install_url() { + let url = "http://example.com/addons/test_install2_1.xpi"; + let install = await AddonManager.getInstallForURL(url, { + name: "Test 2", + version: "1.0", + }); + checkInstall(install, { + version: "1.0", + name: "Test 2", + state: AddonManager.STATE_AVAILABLE, + sourceURI: Services.io.newURI(url), + }); + + let activeInstalls = await AddonManager.getAllInstalls(); + equal(activeInstalls.length, 1); + equal(activeInstalls[0], install); + + await expectEvents( + { + installEvents: [ + { event: "onDownloadStarted" }, + { event: "onDownloadEnded", returnValue: false }, + ], + }, + () => { + install.install(); + } + ); + + checkInstall(install, { + version: "2.0", + name: "Test 2", + state: AddonManager.STATE_DOWNLOADED, + }); + equal(install.addon.install, install); + + await expectEvents( + { + addonEvents: { + "addon2@tests.mozilla.org": [ + { event: "onInstalling" }, + { event: "onInstalled" }, + ], + }, + installEvents: [ + { event: "onInstallStarted" }, + { event: "onInstallEnded" }, + ], + }, + () => install.install() + ); + + let updateDate = Date.now(); + + await promiseRestartManager(); + + let installs = await AddonManager.getAllInstalls(); + equal(installs, 0); + + let a2 = await AddonManager.getAddonByID("addon2@tests.mozilla.org"); + checkAddon("addon2@tests.mozilla.org", a2, { + type: "extension", + version: "2.0", + name: "Test 2", + sourceURI: Services.io.newURI(url), + }); + notEqual(a2.syncGUID, null); + + ok(isExtensionInBootstrappedList(profileDir, a2.id)); + ok(XPIS.test_install2_1.exists()); + do_check_in_crash_annotation(a2.id, a2.version); + + let difference = a2.installDate.getTime() - updateDate; + Assert.lessOrEqual( + Math.abs(difference), + MAX_TIME_DIFFERENCE, + "Add-on install time was correct" + ); + + difference = a2.updateDate.getTime() - updateDate; + Assert.lessOrEqual( + Math.abs(difference), + MAX_TIME_DIFFERENCE, + "Add-on update time was correct" + ); + + gInstallDate = a2.installDate; +}); + +// Tests that installing a new version of an existing add-on works +add_task(async function test_install_new_version() { + let url = "http://example.com/addons/test_install2_2.xpi"; + let [, install] = await Promise.all([ + AddonTestUtils.promiseInstallEvent("onNewInstall"), + AddonManager.getInstallForURL(url, { + name: "Test 2", + version: "3.0", + }), + ]); + + checkInstall(install, { + version: "3.0", + name: "Test 2", + state: AddonManager.STATE_AVAILABLE, + existingAddon: null, + }); + + let activeInstalls = await AddonManager.getAllInstalls(); + equal(activeInstalls.length, 1); + equal(activeInstalls[0], install); + + await expectEvents( + { + installEvents: [ + { event: "onDownloadStarted" }, + { event: "onDownloadEnded", returnValue: false }, + ], + }, + () => { + install.install(); + } + ); + + checkInstall(install, { + version: "3.0", + name: "Test 2", + state: AddonManager.STATE_DOWNLOADED, + existingAddon: await AddonManager.getAddonByID("addon2@tests.mozilla.org"), + }); + + equal(install.addon.install, install); + + // Installation will continue when there is nothing returned. + await expectEvents( + { + addonEvents: { + "addon2@tests.mozilla.org": [ + { event: "onInstalling" }, + { event: "onInstalled" }, + ], + }, + installEvents: [ + { event: "onInstallStarted" }, + { event: "onInstallEnded" }, + ], + }, + () => install.install() + ); + + await promiseRestartManager(); + + let installs2 = await AddonManager.getInstallsByTypes(null); + equal(installs2.length, 0); + + let a2 = await AddonManager.getAddonByID("addon2@tests.mozilla.org"); + checkAddon("addon2@tests.mozilla.org", a2, { + type: "extension", + version: "3.0", + name: "Test 2", + isActive: true, + foreignInstall: false, + sourceURI: Services.io.newURI(url), + installDate: gInstallDate, + }); + + ok(isExtensionInBootstrappedList(profileDir, a2.id)); + ok(XPIS.test_install2_2.exists()); + do_check_in_crash_annotation(a2.id, a2.version); + + // Update date should be later (or the same if this test is too fast) + ok(a2.installDate <= a2.updateDate); + + await a2.uninstall(); +}); + +// Tests that an install that requires a compatibility update works +add_task(async function test_install_compat_update() { + let url = "http://example.com/addons/test_install3.xpi"; + let [, install] = await Promise.all([ + AddonTestUtils.promiseInstallEvent("onNewInstall"), + await AddonManager.getInstallForURL(url, { + name: "Test 3", + version: "1.0", + }), + ]); + + checkInstall(install, { + version: "1.0", + name: "Test 3", + state: AddonManager.STATE_AVAILABLE, + }); + + let activeInstalls = await AddonManager.getInstallsByTypes(null); + equal(activeInstalls.length, 1); + equal(activeInstalls[0], install); + + await expectEvents( + { + installEvents: [ + { event: "onDownloadStarted" }, + { event: "onDownloadEnded", returnValue: false }, + ], + }, + () => { + install.install(); + } + ); + + checkInstall(install, { + version: "1.0", + name: "Test 3", + state: AddonManager.STATE_DOWNLOADED, + existingAddon: null, + }); + checkAddon("addon3@tests.mozilla.org", install.addon, { + appDisabled: false, + }); + + // Continue the install + await expectEvents( + { + addonEvents: { + "addon3@tests.mozilla.org": [ + { event: "onInstalling" }, + { event: "onInstalled" }, + ], + }, + installEvents: [ + { event: "onInstallStarted" }, + { event: "onInstallEnded" }, + ], + }, + () => install.install() + ); + + await promiseRestartManager(); + + let installs = await AddonManager.getAllInstalls(); + equal(installs, 0); + + let a3 = await AddonManager.getAddonByID("addon3@tests.mozilla.org"); + checkAddon("addon3@tests.mozilla.org", a3, { + type: "extension", + version: "1.0", + name: "Test 3", + isActive: true, + appDisabled: false, + }); + notEqual(a3.syncGUID, null); + + ok(isExtensionInBootstrappedList(profileDir, a3.id)); + + ok(XPIS.test_install3.exists()); + await a3.uninstall(); +}); + +add_task(async function test_compat_update_local() { + let [, install] = await Promise.all([ + AddonTestUtils.promiseInstallEvent("onNewInstall"), + AddonManager.getInstallForFile(XPIS.test_install3), + ]); + ok(install.addon.isCompatible); + + await expectEvents( + { + addonEvents: { + "addon3@tests.mozilla.org": [ + { event: "onInstalling" }, + { event: "onInstalled" }, + ], + }, + installEvents: [ + { event: "onInstallStarted" }, + { event: "onInstallEnded" }, + ], + }, + () => install.install() + ); + + await promiseRestartManager(); + + let a3 = await AddonManager.getAddonByID("addon3@tests.mozilla.org"); + checkAddon("addon3@tests.mozilla.org", a3, { + type: "extension", + version: "1.0", + name: "Test 3", + isActive: true, + appDisabled: false, + }); + notEqual(a3.syncGUID, null); + + ok(isExtensionInBootstrappedList(profileDir, a3.id)); + + ok(XPIS.test_install3.exists()); + await a3.uninstall(); +}); + +// Test that after cancelling a download it is removed from the active installs +add_task(async function test_cancel() { + let url = "http://example.com/addons/test_install3.xpi"; + let [, install] = await Promise.all([ + AddonTestUtils.promiseInstallEvent("onNewInstall"), + AddonManager.getInstallForURL(url, { + name: "Test 3", + version: "1.0", + }), + ]); + + checkInstall(install, { + version: "1.0", + name: "Test 3", + state: AddonManager.STATE_AVAILABLE, + }); + + let activeInstalls = await AddonManager.getInstallsByTypes(null); + equal(activeInstalls.length, 1); + equal(activeInstalls[0], install); + + let promise; + function cancel() { + promise = expectEvents( + { + installEvents: [{ event: "onDownloadCancelled" }], + }, + () => { + install.cancel(); + } + ); + } + + await expectEvents( + { + installEvents: [ + { event: "onDownloadStarted" }, + { event: "onDownloadEnded", callback: cancel }, + ], + }, + () => { + install.install(); + } + ); + + await promise; + + let file = install.file; + + // Allow the file removal to complete + activeInstalls = await AddonManager.getAllInstalls(); + equal(activeInstalls.length, 0); + ok(!file.exists()); +}); + +// Check that cancelling the install from onDownloadStarted actually cancels it +add_task(async function test_cancel_onDownloadStarted() { + let url = "http://example.com/addons/test_install2_1.xpi"; + let [, install] = await Promise.all([ + AddonTestUtils.promiseInstallEvent("onNewInstall"), + AddonManager.getInstallForURL(url), + ]); + + equal(install.file, null); + + install.addListener({ + onDownloadStarted() { + install.removeListener(this); + executeSoon(() => install.cancel()); + }, + }); + + let promise = AddonTestUtils.promiseInstallEvent("onDownloadCancelled"); + install.install(); + await promise; + + // Wait another tick to see if it continues downloading. + // The listener only really tests if we give it time to see progress, the + // file check isn't ideal either + install.addListener({ + onDownloadProgress() { + do_throw("Download should not have continued"); + }, + onDownloadEnded() { + do_throw("Download should not have continued"); + }, + }); + + let file = install.file; + await Promise.resolve(); + ok(!file.exists()); +}); + +// Checks that cancelling the install from onDownloadEnded actually cancels it +add_task(async function test_cancel_onDownloadEnded() { + let url = "http://example.com/addons/test_install2_1.xpi"; + let [, install] = await Promise.all([ + AddonTestUtils.promiseInstallEvent("onNewInstall"), + AddonManager.getInstallForURL(url), + ]); + + equal(install.file, null); + + let promise; + function cancel() { + promise = expectEvents( + { + installEvents: [{ event: "onDownloadCancelled" }], + }, + async () => { + install.cancel(); + } + ); + } + + await expectEvents( + { + installEvents: [ + { event: "onDownloadStarted" }, + { event: "onDownloadEnded", callback: cancel }, + ], + }, + () => { + install.install(); + } + ); + + await promise; + + install.addListener({ + onInstallStarted() { + do_throw("Install should not have continued"); + }, + }); +}); + +// Verify that the userDisabled value carries over to the upgrade by default +add_task(async function test_userDisabled_update() { + let url = "http://example.com/addons/test_install2_1.xpi"; + let [, install] = await Promise.all([ + AddonTestUtils.promiseInstallEvent("onNewInstall"), + AddonManager.getInstallForURL(url), + ]); + + await install.install(); + + ok(!install.addon.userDisabled); + await install.addon.disable(); + + let addon = await AddonManager.getAddonByID("addon2@tests.mozilla.org"); + checkAddon("addon2@tests.mozilla.org", addon, { + userDisabled: true, + isActive: false, + }); + + url = "http://example.com/addons/test_install2_2.xpi"; + install = await AddonManager.getInstallForURL(url); + await install.install(); + + checkAddon("addon2@tests.mozilla.org", install.addon, { + userDisabled: true, + isActive: false, + }); + + await promiseRestartManager(); + + addon = await AddonManager.getAddonByID("addon2@tests.mozilla.org"); + checkAddon("addon2@tests.mozilla.org", addon, { + userDisabled: true, + isActive: false, + }); + + await addon.uninstall(); +}); + +// Verify that changing the userDisabled value before onInstallEnded works +add_task(async function test_userDisabled() { + let url = "http://example.com/addons/test_install2_1.xpi"; + let install = await AddonManager.getInstallForURL(url); + await install.install(); + + ok(!install.addon.userDisabled); + + let addon = await AddonManager.getAddonByID("addon2@tests.mozilla.org"); + checkAddon("addon2@tests.mozilla.org", addon, { + userDisabled: false, + isActive: true, + }); + + url = "http://example.com/addons/test_install2_2.xpi"; + install = await AddonManager.getInstallForURL(url); + + install.addListener({ + onInstallStarted() { + ok(!install.addon.userDisabled); + install.addon.disable(); + }, + }); + + await install.install(); + + addon = await AddonManager.getAddonByID("addon2@tests.mozilla.org"); + checkAddon("addon2@tests.mozilla.org", addon, { + userDisabled: true, + isActive: false, + }); + + await addon.uninstall(); +}); + +// Checks that metadata is not stored if the pref is set to false +add_task(async function test_18_1() { + AddonTestUtils.registerJSON(testserver, "/getaddons.json", GETADDONS_JSON); + Services.prefs.setCharPref( + PREF_GETADDONS_BYIDS, + "http://example.com/getaddons.json" + ); + + Services.prefs.setBoolPref("extensions.getAddons.cache.enabled", true); + Services.prefs.setBoolPref( + "extensions.addon2@tests.mozilla.org.getAddons.cache.enabled", + false + ); + + let url = "http://example.com/addons/test_install2_1.xpi"; + let install = await AddonManager.getInstallForURL(url); + await install.install(); + + notEqual(install.addon.fullDescription, "Repository description"); + + await promiseRestartManager(); + + let addon = await AddonManager.getAddonByID("addon2@tests.mozilla.org"); + notEqual(addon.fullDescription, "Repository description"); + + await addon.uninstall(); +}); + +// Checks that metadata is downloaded for new installs and is visible before and +// after restart +add_task(async function test_metadata() { + Services.prefs.setBoolPref( + "extensions.addon2@tests.mozilla.org.getAddons.cache.enabled", + true + ); + + let url = "http://example.com/addons/test_install2_1.xpi"; + let install = await AddonManager.getInstallForURL(url); + await install.install(); + + equal(install.addon.fullDescription, "Repository description"); + + await promiseRestartManager(); + + let addon = await AddonManager.getAddonByID("addon2@tests.mozilla.org"); + equal(addon.fullDescription, "Repository description"); + + await addon.uninstall(); +}); + +// Do the same again to make sure it works when the data is already in the cache +add_task(async function test_metadata_again() { + let url = "http://example.com/addons/test_install2_1.xpi"; + let install = await AddonManager.getInstallForURL(url); + await install.install(); + + equal(install.addon.fullDescription, "Repository description"); + + await promiseRestartManager(); + + let addon = await AddonManager.getAddonByID("addon2@tests.mozilla.org"); + equal(addon.fullDescription, "Repository description"); + + await addon.uninstall(); +}); + +// Tests that an install can be restarted after being cancelled +add_task(async function test_restart() { + let url = "http://example.com/addons/test_install1.xpi"; + let install = await AddonManager.getInstallForURL(url); + equal(install.state, AddonManager.STATE_AVAILABLE); + + install.addListener({ + onDownloadEnded() { + install.removeListener(this); + install.cancel(); + }, + }); + + try { + await install.install(); + ok(false, "Install should not have succeeded"); + } catch (err) {} + + let promise = expectEvents( + { + addonEvents: { + "addon1@tests.mozilla.org": [ + { event: "onInstalling" }, + { event: "onInstalled" }, + ], + }, + installEvents: [ + { event: "onDownloadStarted" }, + { event: "onDownloadEnded" }, + { event: "onInstallStarted" }, + { event: "onInstallEnded" }, + ], + }, + () => { + install.install(); + } + ); + + await Promise.all([ + promise, + promiseWebExtensionStartup("addon1@tests.mozilla.org"), + ]); + + await install.addon.uninstall(); +}); + +// Tests that an install can be restarted after being cancelled when a hash +// was provided +add_task(async function test_restart_hash() { + let url = "http://example.com/addons/test_install1.xpi"; + let install = await AddonManager.getInstallForURL(url, { + hash: do_get_file_hash(XPIS.test_install1), + }); + equal(install.state, AddonManager.STATE_AVAILABLE); + + install.addListener({ + onDownloadEnded() { + install.removeListener(this); + install.cancel(); + }, + }); + + try { + await install.install(); + ok(false, "Install should not have succeeded"); + } catch (err) {} + + let promise = expectEvents( + { + addonEvents: { + "addon1@tests.mozilla.org": [ + { event: "onInstalling" }, + { event: "onInstalled" }, + ], + }, + installEvents: [ + { event: "onDownloadStarted" }, + { event: "onDownloadEnded" }, + { event: "onInstallStarted" }, + { event: "onInstallEnded" }, + ], + }, + () => { + install.install(); + } + ); + + await Promise.all([ + promise, + promiseWebExtensionStartup("addon1@tests.mozilla.org"), + ]); + + await install.addon.uninstall(); +}); + +// Tests that an install with a bad hash can be restarted after it fails, though +// it will only fail again +add_task(async function test_restart_badhash() { + let url = "http://example.com/addons/test_install1.xpi"; + let install = await AddonManager.getInstallForURL(url, { hash: "sha1:foo" }); + equal(install.state, AddonManager.STATE_AVAILABLE); + + install.addListener({ + onDownloadEnded() { + install.removeListener(this); + install.cancel(); + }, + }); + + try { + await install.install(); + ok(false, "Install should not have succeeded"); + } catch (err) {} + + try { + await install.install(); + ok(false, "Install should not have succeeded"); + } catch (err) { + ok(true, "Resumed install should have failed"); + } +}); + +// Tests that installs with a hash for a local file work +add_task(async function test_local_hash() { + let url = Services.io.newFileURI(XPIS.test_install1).spec; + let install = await AddonManager.getInstallForURL(url, { + hash: do_get_file_hash(XPIS.test_install1), + }); + + checkInstall(install, { + state: AddonManager.STATE_DOWNLOADED, + error: 0, + }); + + install.cancel(); +}); + +// Test that an install cannot be canceled after the install is completed. +add_task(async function test_cancel_completed() { + let url = "http://example.com/addons/test_install1.xpi"; + let install = await AddonManager.getInstallForURL(url); + + let cancelPromise = new Promise((resolve, reject) => { + install.addListener({ + onInstallEnded() { + try { + install.cancel(); + reject("Cancel should fail."); + } catch (e) { + resolve(); + } + }, + }); + }); + + install.install(); + await cancelPromise; + + equal(install.state, AddonManager.STATE_INSTALLED); +}); + +// Test that an install may be canceled after a redirect. +add_task(async function test_cancel_redirect() { + let url = "http://example.com/redirect?/addons/test_install1.xpi"; + let install = await AddonManager.getInstallForURL(url); + + install.addListener({ + onDownloadProgress() { + install.cancel(); + }, + }); + + let promise = AddonTestUtils.promiseInstallEvent("onDownloadCancelled"); + + install.install(); + await promise; + + equal(install.state, AddonManager.STATE_CANCELLED); +}); + +// Tests that an install can be restarted during onDownloadCancelled after being +// cancelled in mid-download +add_task(async function test_restart2() { + let url = "http://example.com/addons/test_install1.xpi"; + let install = await AddonManager.getInstallForURL(url); + + equal(install.state, AddonManager.STATE_AVAILABLE); + + install.addListener({ + onDownloadProgress() { + install.removeListener(this); + install.cancel(); + }, + }); + + let promise = AddonTestUtils.promiseInstallEvent("onDownloadCancelled"); + install.install(); + await promise; + + equal(install.state, AddonManager.STATE_CANCELLED); + + promise = expectEvents( + { + addonEvents: { + "addon1@tests.mozilla.org": [ + { event: "onInstalling" }, + { event: "onInstalled" }, + ], + }, + installEvents: [ + { event: "onDownloadStarted" }, + { event: "onDownloadEnded" }, + { event: "onInstallStarted" }, + { event: "onInstallEnded" }, + ], + }, + () => { + let file = install.file; + install.install(); + notEqual(file.path, install.file.path); + ok(!file.exists()); + } + ); + + await Promise.all([ + promise, + promiseWebExtensionStartup("addon1@tests.mozilla.org"), + ]); + + await install.addon.uninstall(); +}); -- cgit v1.2.3