michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: * http://creativecommons.org/publicdomain/zero/1.0/ michael@0: */ michael@0: michael@0: // This verifies that updating an add-on to a new ID works michael@0: michael@0: // The test extension uses an insecure update url. michael@0: Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); michael@0: michael@0: Components.utils.import("resource://testing-common/httpd.js"); michael@0: var testserver; michael@0: const profileDir = gProfD.clone(); michael@0: profileDir.append("extensions"); michael@0: michael@0: function resetPrefs() { michael@0: Services.prefs.setIntPref("bootstraptest.active_version", -1); michael@0: Services.prefs.setIntPref("bootstraptest.installed_version", -1); michael@0: Services.prefs.setIntPref("bootstraptest.startup_reason", -1); michael@0: Services.prefs.setIntPref("bootstraptest.shutdown_reason", -1); michael@0: Services.prefs.setIntPref("bootstraptest.install_reason", -1); michael@0: Services.prefs.setIntPref("bootstraptest.uninstall_reason", -1); michael@0: } michael@0: michael@0: function getActiveVersion() { michael@0: return Services.prefs.getIntPref("bootstraptest.active_version"); michael@0: } michael@0: michael@0: function getInstalledVersion() { michael@0: return Services.prefs.getIntPref("bootstraptest.installed_version"); michael@0: } michael@0: michael@0: function run_test() { michael@0: createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); michael@0: michael@0: // Create and configure the HTTP server. michael@0: testserver = new HttpServer(); michael@0: testserver.registerDirectory("/data/", do_get_file("data")); michael@0: testserver.registerDirectory("/addons/", do_get_file("addons")); michael@0: testserver.start(4444); michael@0: michael@0: do_test_pending(); michael@0: run_test_1(); michael@0: } michael@0: michael@0: function end_test() { michael@0: testserver.stop(do_test_finished); michael@0: } michael@0: michael@0: function installUpdate(aInstall, aCallback) { michael@0: aInstall.addListener({ michael@0: onInstallEnded: function(aInstall) { michael@0: // give the startup time to run michael@0: do_execute_soon(function() { michael@0: aCallback(aInstall); michael@0: }); michael@0: } michael@0: }); michael@0: michael@0: aInstall.install(); michael@0: } michael@0: michael@0: // Verify that an update to an add-on with a new ID uninstalls the old add-on michael@0: function run_test_1() { michael@0: writeInstallRDFForExtension({ michael@0: id: "addon1@tests.mozilla.org", michael@0: version: "1.0", michael@0: updateURL: "http://localhost:4444/data/test_updateid.rdf", michael@0: targetApplications: [{ michael@0: id: "xpcshell@tests.mozilla.org", michael@0: minVersion: "1", michael@0: maxVersion: "1" michael@0: }], michael@0: name: "Test Addon 1", michael@0: }, profileDir); michael@0: michael@0: startupManager(); michael@0: michael@0: AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { michael@0: do_check_neq(a1, null); michael@0: do_check_eq(a1.version, "1.0"); michael@0: michael@0: a1.findUpdates({ michael@0: onUpdateAvailable: function(addon, install) { michael@0: do_check_eq(install.name, addon.name); michael@0: do_check_eq(install.version, "2.0"); michael@0: do_check_eq(install.state, AddonManager.STATE_AVAILABLE); michael@0: do_check_eq(install.existingAddon, a1); michael@0: michael@0: installUpdate(install, check_test_1); michael@0: } michael@0: }, AddonManager.UPDATE_WHEN_USER_REQUESTED); michael@0: }); michael@0: } michael@0: michael@0: function check_test_1(install) { michael@0: AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { michael@0: // Existing add-on should have a pending upgrade michael@0: do_check_neq(a1.pendingUpgrade, null); michael@0: do_check_eq(a1.pendingUpgrade.id, "addon2@tests.mozilla.org"); michael@0: do_check_eq(a1.pendingUpgrade.install.existingAddon, a1); michael@0: do_check_neq(a1.syncGUID); michael@0: michael@0: let a1SyncGUID = a1.syncGUID; michael@0: michael@0: restartManager(); michael@0: michael@0: AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", michael@0: "addon2@tests.mozilla.org"], function([a1, a2]) { michael@0: // Should have uninstalled the old and installed the new michael@0: do_check_eq(a1, null); michael@0: do_check_neq(a2, null); michael@0: do_check_neq(a2.syncGUID, null); michael@0: michael@0: // The Sync GUID should change when the ID changes michael@0: do_check_neq(a1SyncGUID, a2.syncGUID); michael@0: michael@0: a2.uninstall(); michael@0: michael@0: do_execute_soon(run_test_2); michael@0: }); michael@0: })); michael@0: } michael@0: michael@0: // Test that when the new add-on already exists we just upgrade that michael@0: function run_test_2() { michael@0: restartManager(); michael@0: shutdownManager(); michael@0: michael@0: writeInstallRDFForExtension({ michael@0: id: "addon1@tests.mozilla.org", michael@0: version: "1.0", michael@0: updateURL: "http://localhost:4444/data/test_updateid.rdf", michael@0: targetApplications: [{ michael@0: id: "xpcshell@tests.mozilla.org", michael@0: minVersion: "1", michael@0: maxVersion: "1" michael@0: }], michael@0: name: "Test Addon 1", michael@0: }, profileDir); michael@0: writeInstallRDFForExtension({ michael@0: id: "addon2@tests.mozilla.org", michael@0: version: "1.0", michael@0: targetApplications: [{ michael@0: id: "xpcshell@tests.mozilla.org", michael@0: minVersion: "1", michael@0: maxVersion: "1" michael@0: }], michael@0: name: "Test Addon 2", michael@0: }, profileDir); michael@0: michael@0: startupManager(); michael@0: michael@0: AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { michael@0: do_check_neq(a1, null); michael@0: do_check_eq(a1.version, "1.0"); michael@0: michael@0: a1.findUpdates({ michael@0: onUpdateAvailable: function(addon, install) { michael@0: installUpdate(install, check_test_2); michael@0: } michael@0: }, AddonManager.UPDATE_WHEN_USER_REQUESTED); michael@0: }); michael@0: } michael@0: michael@0: function check_test_2(install) { michael@0: AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", michael@0: "addon2@tests.mozilla.org"], michael@0: callback_soon(function([a1, a2]) { michael@0: do_check_eq(a1.pendingUpgrade, null); michael@0: // Existing add-on should have a pending upgrade michael@0: do_check_neq(a2.pendingUpgrade, null); michael@0: do_check_eq(a2.pendingUpgrade.id, "addon2@tests.mozilla.org"); michael@0: do_check_eq(a2.pendingUpgrade.install.existingAddon, a2); michael@0: michael@0: restartManager(); michael@0: michael@0: AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", michael@0: "addon2@tests.mozilla.org"], function([a1, a2]) { michael@0: // Should have uninstalled the old and installed the new michael@0: do_check_neq(a1, null); michael@0: do_check_neq(a2, null); michael@0: michael@0: a1.uninstall(); michael@0: a2.uninstall(); michael@0: michael@0: do_execute_soon(run_test_3); michael@0: }); michael@0: })); michael@0: } michael@0: michael@0: // Test that we rollback correctly when removing the old add-on fails michael@0: function run_test_3() { michael@0: restartManager(); michael@0: shutdownManager(); michael@0: michael@0: // This test only works on Windows michael@0: if (!("nsIWindowsRegKey" in AM_Ci)) { michael@0: run_test_4(); michael@0: return; michael@0: } michael@0: michael@0: writeInstallRDFForExtension({ michael@0: id: "addon1@tests.mozilla.org", michael@0: version: "1.0", michael@0: updateURL: "http://localhost:4444/data/test_updateid.rdf", michael@0: targetApplications: [{ michael@0: id: "xpcshell@tests.mozilla.org", michael@0: minVersion: "1", michael@0: maxVersion: "1" michael@0: }], michael@0: name: "Test Addon 1", michael@0: }, profileDir); michael@0: michael@0: startupManager(); michael@0: michael@0: AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { michael@0: do_check_neq(a1, null); michael@0: do_check_eq(a1.version, "1.0"); michael@0: michael@0: a1.findUpdates({ michael@0: onUpdateAvailable: function(addon, install) { michael@0: installUpdate(install, check_test_3); michael@0: } michael@0: }, AddonManager.UPDATE_WHEN_USER_REQUESTED); michael@0: }); michael@0: } michael@0: michael@0: function check_test_3(install) { michael@0: AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { michael@0: // Existing add-on should have a pending upgrade michael@0: do_check_neq(a1.pendingUpgrade, null); michael@0: do_check_eq(a1.pendingUpgrade.id, "addon2@tests.mozilla.org"); michael@0: do_check_eq(a1.pendingUpgrade.install.existingAddon, a1); michael@0: michael@0: // Lock the old add-on open so it can't be uninstalled michael@0: var file = profileDir.clone(); michael@0: file.append("addon1@tests.mozilla.org"); michael@0: if (!file.exists()) michael@0: file.leafName += ".xpi"; michael@0: else michael@0: file.append("install.rdf"); michael@0: michael@0: var fstream = AM_Cc["@mozilla.org/network/file-output-stream;1"]. michael@0: createInstance(AM_Ci.nsIFileOutputStream); michael@0: fstream.init(file, FileUtils.MODE_APPEND | FileUtils.MODE_WRONLY, FileUtils.PERMS_FILE, 0); michael@0: michael@0: restartManager(); michael@0: michael@0: fstream.close(); michael@0: michael@0: AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", michael@0: "addon2@tests.mozilla.org"], michael@0: callback_soon(function([a1, a2]) { michael@0: // Should not have installed the new add-on but it should still be michael@0: // pending install michael@0: do_check_neq(a1, null); michael@0: do_check_eq(a2, null); michael@0: michael@0: restartManager(); michael@0: michael@0: AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", michael@0: "addon2@tests.mozilla.org"], function([a1, a2]) { michael@0: // Should have installed the new add-on michael@0: do_check_eq(a1, null); michael@0: do_check_neq(a2, null); michael@0: michael@0: a2.uninstall(); michael@0: michael@0: do_execute_soon(run_test_4); michael@0: }); michael@0: })); michael@0: })); michael@0: } michael@0: michael@0: // Tests that upgrading to a bootstrapped add-on works but requires a restart michael@0: function run_test_4() { michael@0: restartManager(); michael@0: shutdownManager(); michael@0: michael@0: writeInstallRDFForExtension({ michael@0: id: "addon2@tests.mozilla.org", michael@0: version: "2.0", michael@0: updateURL: "http://localhost:4444/data/test_updateid.rdf", michael@0: targetApplications: [{ michael@0: id: "xpcshell@tests.mozilla.org", michael@0: minVersion: "1", michael@0: maxVersion: "1" michael@0: }], michael@0: name: "Test Addon 2", michael@0: }, profileDir); michael@0: michael@0: startupManager(); michael@0: michael@0: resetPrefs(); michael@0: michael@0: AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { michael@0: do_check_neq(a2, null); michael@0: do_check_neq(a2.syncGUID, null); michael@0: do_check_eq(a2.version, "2.0"); michael@0: michael@0: a2.findUpdates({ michael@0: onUpdateAvailable: function(addon, install) { michael@0: installUpdate(install, check_test_4); michael@0: } michael@0: }, AddonManager.UPDATE_WHEN_USER_REQUESTED); michael@0: }); michael@0: } michael@0: michael@0: function check_test_4() { michael@0: AddonManager.getAddonsByIDs(["addon2@tests.mozilla.org", michael@0: "addon3@tests.mozilla.org"], michael@0: callback_soon(function([a2, a3]) { michael@0: // Should still be pending install even though the new add-on is restartless michael@0: do_check_neq(a2, null); michael@0: do_check_eq(a3, null); michael@0: michael@0: do_check_neq(a2.pendingUpgrade, null); michael@0: do_check_eq(a2.pendingUpgrade.id, "addon3@tests.mozilla.org"); michael@0: michael@0: do_check_eq(getInstalledVersion(), -1); michael@0: do_check_eq(getActiveVersion(), -1); michael@0: michael@0: restartManager(); michael@0: michael@0: AddonManager.getAddonsByIDs(["addon2@tests.mozilla.org", michael@0: "addon3@tests.mozilla.org"], function([a2, a3]) { michael@0: // Should have updated michael@0: do_check_eq(a2, null); michael@0: do_check_neq(a3, null); michael@0: michael@0: do_check_eq(getInstalledVersion(), 3); michael@0: do_check_eq(getActiveVersion(), 3); michael@0: michael@0: do_execute_soon(run_test_5); michael@0: }); michael@0: })); michael@0: } michael@0: michael@0: // Tests that upgrading to another bootstrapped add-on works without a restart michael@0: function run_test_5() { michael@0: AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) { michael@0: do_check_neq(a3, null); michael@0: do_check_eq(a3.version, "3.0"); michael@0: michael@0: a3.findUpdates({ michael@0: onUpdateAvailable: function(addon, install) { michael@0: installUpdate(install, check_test_5); michael@0: } michael@0: }, AddonManager.UPDATE_WHEN_USER_REQUESTED); michael@0: }); michael@0: } michael@0: michael@0: function check_test_5() { michael@0: AddonManager.getAddonsByIDs(["addon3@tests.mozilla.org", michael@0: "addon4@tests.mozilla.org"], michael@0: callback_soon(function([a3, a4]) { michael@0: // Should have updated michael@0: do_check_eq(a3, null); michael@0: do_check_neq(a4, null); michael@0: michael@0: do_check_eq(getInstalledVersion(), 4); michael@0: do_check_eq(getActiveVersion(), 4); michael@0: michael@0: restartManager(); michael@0: michael@0: AddonManager.getAddonsByIDs(["addon3@tests.mozilla.org", michael@0: "addon4@tests.mozilla.org"], function([a3, a4]) { michael@0: // Should still be gone michael@0: do_check_eq(a3, null); michael@0: do_check_neq(a4, null); michael@0: michael@0: do_check_eq(getInstalledVersion(), 4); michael@0: do_check_eq(getActiveVersion(), 4); michael@0: michael@0: run_test_6(); michael@0: }); michael@0: })); michael@0: } michael@0: michael@0: // Tests that upgrading to a non-bootstrapped add-on works but requires a restart michael@0: function run_test_6() { michael@0: AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) { michael@0: do_check_neq(a4, null); michael@0: do_check_eq(a4.version, "4.0"); michael@0: michael@0: a4.findUpdates({ michael@0: onUpdateAvailable: function(addon, install) { michael@0: installUpdate(install, check_test_6); michael@0: } michael@0: }, AddonManager.UPDATE_WHEN_USER_REQUESTED); michael@0: }); michael@0: } michael@0: michael@0: function check_test_6() { michael@0: AddonManager.getAddonsByIDs(["addon4@tests.mozilla.org", michael@0: "addon2@tests.mozilla.org"], michael@0: callback_soon(function([a4, a2]) { michael@0: // Should still be pending install even though the old add-on is restartless michael@0: do_check_neq(a4, null); michael@0: do_check_eq(a2, null); michael@0: michael@0: do_check_neq(a4.pendingUpgrade, null); michael@0: do_check_eq(a4.pendingUpgrade.id, "addon2@tests.mozilla.org"); michael@0: michael@0: do_check_eq(getInstalledVersion(), 4); michael@0: do_check_eq(getActiveVersion(), 4); michael@0: michael@0: restartManager(); michael@0: michael@0: AddonManager.getAddonsByIDs(["addon4@tests.mozilla.org", michael@0: "addon2@tests.mozilla.org"], function([a4, a2]) { michael@0: // Should have updated michael@0: do_check_eq(a4, null); michael@0: do_check_neq(a2, null); michael@0: michael@0: do_check_eq(getInstalledVersion(), 0); michael@0: do_check_eq(getActiveVersion(), 0); michael@0: michael@0: end_test(); michael@0: }); michael@0: })); michael@0: }