diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index 780c869c7ff5..aa9f364d2f82 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -54,6 +54,10 @@ pref("browser.hiddenWindowChromeURL", "chrome://browser/content/hiddenWindow.xul // Enables some extra Extension System Logging (can reduce performance) pref("extensions.logging.enabled", false); +// Enables strict compatibility. To be toggled in bug 698653, to make addons +// compatibile by default. +pref("extensions.strictCompatibility", true); + // Preferences for AMO integration pref("extensions.getAddons.cache.enabled", true); pref("extensions.getAddons.maxResults", 15); diff --git a/browser/base/content/test/browser_bug553455.js b/browser/base/content/test/browser_bug553455.js index 6a8a3ea93705..da43ee1a83cc 100644 --- a/browser/base/content/test/browser_bug553455.js +++ b/browser/base/content/test/browser_bug553455.js @@ -866,6 +866,7 @@ function test() { waitForExplicitFinish(); Services.prefs.setBoolPref("extensions.logging.enabled", true); + Services.prefs.setBoolPref("extensions.strictCompatibility", true); Services.obs.addObserver(XPInstallObserver, "addon-install-started", false); Services.obs.addObserver(XPInstallObserver, "addon-install-blocked", false); @@ -884,6 +885,7 @@ function test() { }); Services.prefs.clearUserPref("extensions.logging.enabled"); + Services.prefs.clearUserPref("extensions.strictCompatibility"); Services.obs.removeObserver(XPInstallObserver, "addon-install-started"); Services.obs.removeObserver(XPInstallObserver, "addon-install-blocked"); diff --git a/toolkit/mozapps/extensions/AddonManager.jsm b/toolkit/mozapps/extensions/AddonManager.jsm index 2c4a290c42ba..f7c5926430a6 100644 --- a/toolkit/mozapps/extensions/AddonManager.jsm +++ b/toolkit/mozapps/extensions/AddonManager.jsm @@ -48,6 +48,9 @@ const PREF_EM_UPDATE_ENABLED = "extensions.update.enabled"; const PREF_EM_LAST_APP_VERSION = "extensions.lastAppVersion"; const PREF_EM_LAST_PLATFORM_VERSION = "extensions.lastPlatformVersion"; const PREF_EM_AUTOUPDATE_DEFAULT = "extensions.update.autoUpdateDefault"; +const PREF_EM_STRICT_COMPATIBILITY = "extensions.strictCompatibility"; + +const STRICT_COMPATIBILITY_DEFAULT = true; const VALID_TYPES_REGEXP = /^[\w\-]+$/; @@ -281,6 +284,7 @@ function AddonType(aId, aLocaleURI, aLocaleKey, aViewType, aUIPriority, aFlags) } var gStarted = false; +var gStrictCompatibility = STRICT_COMPATIBILITY_DEFAULT; /** * This is the real manager, kept here rather than in AddonManager to keep its @@ -374,6 +378,11 @@ var AddonManagerInternal = { (appChanged === undefined ? 0 : -1)); } + try { + gStrictCompatibility = Services.prefs.getBoolPref(PREF_EM_STRICT_COMPATIBILITY); + } catch (e) {} + Services.prefs.addObserver(PREF_EM_STRICT_COMPATIBILITY, this, false); + // Ensure all default providers have had a chance to register themselves DEFAULT_PROVIDERS.forEach(function(url) { try { @@ -495,6 +504,8 @@ var AddonManagerInternal = { * up everything in order for automated tests to fake restarts. */ shutdown: function AMI_shutdown() { + Services.prefs.removeObserver(PREF_EM_STRICT_COMPATIBILITY, this); + this.providers.forEach(function(provider) { callProvider(provider, "shutdown"); }); @@ -507,6 +518,31 @@ var AddonManagerInternal = { gStarted = false; }, + /** + * Notified when a preference we're interested in has changed. + * + * @see nsIObserver + */ + observe: function AMI_observe(aSubject, aTopic, aData) { + switch (aData) { + case PREF_EM_STRICT_COMPATIBILITY: + let oldValue = gStrictCompatibility; + try { + gStrictCompatibility = Services.prefs.getBoolPref(PREF_EM_STRICT_COMPATIBILITY); + } catch(e) { + gStrictCompatibility = STRICT_COMPATIBILITY_DEFAULT; + } + + // XXXunf Currently, this won't notify listeners that an addon's + // compatibility status has changed if the addon's appDisabled state + // doesn't change. + if (gStrictCompatibility != oldValue) + this.updateAddonAppDisabledStates(); + + break; + } + }, + /** * Performs a background update check by starting an update for all add-ons * that can be updated. @@ -1095,6 +1131,10 @@ var AddonManagerInternal = { return Services.prefs.getBoolPref(PREF_EM_AUTOUPDATE_DEFAULT); } catch(e) { } return true; + }, + + get strictCompatibility() { + return gStrictCompatibility; } }; @@ -1415,6 +1455,10 @@ var AddonManager = { if (aAddon.applyBackgroundUpdates == AddonManager.AUTOUPDATE_DISABLE) return false; return this.autoUpdateDefault; + }, + + get strictCompatibility() { + return AddonManagerInternal.strictCompatibility; } }; diff --git a/toolkit/mozapps/extensions/XPIProvider.jsm b/toolkit/mozapps/extensions/XPIProvider.jsm index 16482e1f2f18..cabda6fea8ad 100644 --- a/toolkit/mozapps/extensions/XPIProvider.jsm +++ b/toolkit/mozapps/extensions/XPIProvider.jsm @@ -6908,6 +6908,11 @@ AddonInternal.prototype = { if (!app) return false; + // Only extensions can be compatible by default; themes always use strict + // compatibility checking. + if (this.type == "extension" && !AddonManager.strictCompatibility) + return true; + if (!aAppVersion) aAppVersion = Services.appinfo.version; if (!aPlatformVersion) diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug557956.js b/toolkit/mozapps/extensions/test/browser/browser_bug557956.js index 033ea5cb89fd..4bc68982d2e2 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug557956.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug557956.js @@ -7,6 +7,8 @@ const URI_EXTENSION_UPDATE_DIALOG = "chrome://mozapps/content/extensions/update.xul"; +Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true); + /** * Test add-ons: * diff --git a/toolkit/mozapps/extensions/test/browser/head.js b/toolkit/mozapps/extensions/test/browser/head.js index 47eef60c844c..0ee47d22f19d 100644 --- a/toolkit/mozapps/extensions/test/browser/head.js +++ b/toolkit/mozapps/extensions/test/browser/head.js @@ -26,6 +26,7 @@ const MANAGER_URI = "about:addons"; const INSTALL_URI = "chrome://mozapps/content/xpinstall/xpinstallConfirm.xul"; const PREF_LOGGING_ENABLED = "extensions.logging.enabled"; const PREF_SEARCH_MAXRESULTS = "extensions.getAddons.maxResults"; +const PREF_STRICT_COMPAT = "extensions.strictCompatibility"; var gPendingTests = []; var gTestsRun = 0; @@ -44,9 +45,10 @@ registerCleanupFunction(function() { Services.prefs.clearUserPref(PREF_LOGGING_ENABLED); try { Services.prefs.clearUserPref(PREF_SEARCH_MAXRESULTS); - } - catch (e) { - } + } catch (e) {} + try { + Services.prefs.clearUserPref(PREF_STRICT_COMPAT); + } catch (e) {} Services.prefs.setCharPref(PREF_DISCOVERURL, gDiscoveryURL); Services.prefs.setCharPref(PREF_UPDATEURL, gUpdateURL); diff --git a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js index 16de8d023019..7ebe0f68aab6 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js +++ b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js @@ -8,6 +8,9 @@ const AM_Ci = Components.interfaces; const XULAPPINFO_CONTRACTID = "@mozilla.org/xre/app-info;1"; const XULAPPINFO_CID = Components.ID("{c763b610-9d49-455a-bbd2-ede71682a1ac}"); +const PREF_EM_CHECK_UPDATE_SECURITY = "extensions.checkUpdateSecurity"; +const PREF_EM_STRICT_COMPATIBILITY = "extensions.strictCompatibility"; + Components.utils.import("resource://gre/modules/AddonManager.jsm"); Components.utils.import("resource://gre/modules/AddonRepository.jsm"); Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); @@ -1103,6 +1106,10 @@ Services.prefs.setCharPref("extensions.blocklist.url", "http://127.0.0.1/blockli // By default ignore bundled add-ons Services.prefs.setBoolPref("extensions.installDistroAddons", false); +// By default use strict compatibility +Services.prefs.setBoolPref("extensions.strictCompatibility", true); + + // Register a temporary directory for the tests. const gTmpD = gProfD.clone(); gTmpD.append("temp"); @@ -1146,4 +1153,12 @@ do_register_cleanup(function() { do_check_false(testDir.exists()); shutdownManager(); + + // Clear commonly set prefs. + try { + Services.prefs.clearUserPref(PREF_EM_CHECK_UPDATE_SECURITY); + } catch (e) {} + try { + Services.prefs.clearUserPref(PREF_EM_STRICT_COMPATIBILITY); + } catch (e) {} }); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1.js index a4d3ce9a63b2..7012f8ab0def 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1.js @@ -37,7 +37,8 @@ */ // Disables security checking our updates which haven't been signed -Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); +Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); +Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false); var ADDONS = [ "test_bug470377_1", @@ -70,8 +71,8 @@ function run_test() { "bug470377_5@tests.mozilla.org"], function([a1, a2, a3, a4, a5]) { do_check_eq(a1, null); - do_check_eq(a2, null); - do_check_eq(a3, null); + do_check_neq(a2, null); + do_check_neq(a3, null); do_check_neq(a4, null); do_check_neq(a5, null); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1_strictcompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1_strictcompat.js new file mode 100644 index 000000000000..1e4dd76801aa --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1_strictcompat.js @@ -0,0 +1,82 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Dave Townsend . + * + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL + * + * ***** END LICENSE BLOCK ***** + */ + +// Disables security checking our updates which haven't been signed +Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); +Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, true); + +var ADDONS = [ + "test_bug470377_1", + "test_bug470377_2", + "test_bug470377_3", + "test_bug470377_4", + "test_bug470377_5", +]; + +do_load_httpd_js(); +var server; + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2"); + + server = new nsHttpServer(); + server.registerDirectory("/", do_get_file("data/test_bug470377")); + server.start(4444); + + startupManager(); + + installAllFiles([do_get_addon(a) for each (a in ADDONS)], function() { + restartManager(); + + AddonManager.getAddonsByIDs(["bug470377_1@tests.mozilla.org", + "bug470377_2@tests.mozilla.org", + "bug470377_3@tests.mozilla.org", + "bug470377_4@tests.mozilla.org", + "bug470377_5@tests.mozilla.org"], + function([a1, a2, a3, a4, a5]) { + do_check_eq(a1, null); + do_check_eq(a2, null); + do_check_eq(a3, null); + do_check_neq(a4, null); + do_check_neq(a5, null); + + server.stop(do_test_finished); + }); + }, true); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3.js index 83a0539d2936..3e019db1be8c 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3.js @@ -36,6 +36,8 @@ * ***** END LICENSE BLOCK ***** */ +Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false); + function run_test() { do_test_pending(); createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2.2.3", "2"); @@ -87,9 +89,9 @@ function run_test_1() { do_check_neq(a1, null); do_check_false(a1.isActive); do_check_neq(a2, null); - do_check_false(a2.isActive); + do_check_true(a2.isActive); do_check_neq(a3, null); - do_check_false(a3.isActive); + do_check_true(a3.isActive); do_check_neq(a4, null); do_check_true(a4.isActive); do_check_neq(a5, null); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3_strictcompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3_strictcompat.js new file mode 100644 index 000000000000..f0e8f426606a --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3_strictcompat.js @@ -0,0 +1,140 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Dave Townsend . + * + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL + * + * ***** END LICENSE BLOCK ***** + */ + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2.2.3", "2"); + Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, true); + + // inject the add-ons into the profile + var dest = gProfD.clone(); + dest.append("extensions"); + dest.append("bug470377_1@tests.mozilla.org"); + dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755); + var source = do_get_file("data/test_bug470377/install_1.rdf"); + source.copyTo(dest, "install.rdf"); + dest = gProfD.clone(); + dest.append("extensions"); + dest.append("bug470377_2@tests.mozilla.org"); + dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755); + source = do_get_file("data/test_bug470377/install_2.rdf"); + source.copyTo(dest, "install.rdf"); + dest = gProfD.clone(); + dest.append("extensions"); + dest.append("bug470377_3@tests.mozilla.org"); + dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755); + source = do_get_file("data/test_bug470377/install_3.rdf"); + source.copyTo(dest, "install.rdf"); + dest = gProfD.clone(); + dest.append("extensions"); + dest.append("bug470377_4@tests.mozilla.org"); + dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755); + source = do_get_file("data/test_bug470377/install_4.rdf"); + source.copyTo(dest, "install.rdf"); + dest = gProfD.clone(); + dest.append("extensions"); + dest.append("bug470377_5@tests.mozilla.org"); + dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755); + source = do_get_file("data/test_bug470377/install_5.rdf"); + source.copyTo(dest, "install.rdf"); + + startupManager(); + + run_test_1(); +} + +function run_test_1() { + AddonManager.getAddonsByIDs(["bug470377_1@tests.mozilla.org", + "bug470377_2@tests.mozilla.org", + "bug470377_3@tests.mozilla.org", + "bug470377_4@tests.mozilla.org", + "bug470377_5@tests.mozilla.org"], + function([a1, a2, a3, a4, a5]) { + do_check_neq(a1, null); + do_check_false(a1.isActive); + do_check_neq(a2, null); + do_check_false(a2.isActive); + do_check_neq(a3, null); + do_check_false(a3.isActive); + do_check_neq(a4, null); + do_check_true(a4.isActive); + do_check_neq(a5, null); + do_check_true(a5.isActive); + + run_test_2(); + }); +} + +function run_test_2() { + // Disable compatibility checks + var channel = "default"; + try { + channel = Services.prefs.getCharPref("app.update.channel"); + } + catch (e) { } + + if (channel != "aurora" && + channel != "beta" && + channel != "release") { + Services.prefs.setBoolPref("extensions.checkCompatibility.nightly", false); + } + else { + Services.prefs.setBoolPref("extensions.checkCompatibility.2.2", false); + } + restartManager(); + + AddonManager.getAddonsByIDs(["bug470377_1@tests.mozilla.org", + "bug470377_2@tests.mozilla.org", + "bug470377_3@tests.mozilla.org", + "bug470377_4@tests.mozilla.org", + "bug470377_5@tests.mozilla.org"], + function([a1, a2, a3, a4, a5]) { + do_check_neq(a1, null); + do_check_false(a1.isActive); + do_check_neq(a2, null); + do_check_true(a2.isActive); + do_check_neq(a3, null); + do_check_true(a3.isActive); + do_check_neq(a4, null); + do_check_true(a4.isActive); + do_check_neq(a5, null); + do_check_true(a5.isActive); + + do_test_finished(); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js b/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js index 0930481de664..a16cb87f6020 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js @@ -9,7 +9,8 @@ do_load_httpd_js(); var testserver; // The test extension uses an insecure update url. -Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); +Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); +Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false); // Will be enabled var addon1 = { @@ -35,7 +36,7 @@ var addon2 = { }] }; -// Will get a compatibility update and be enabled +// Will get a compatibility update and stay enabled var addon3 = { id: "addon3@tests.mozilla.org", version: "1.0", @@ -48,7 +49,7 @@ var addon3 = { }] }; -// Will get a compatibility update and be disabled +// Will get a compatibility update and be enabled var addon4 = { id: "addon4@tests.mozilla.org", version: "1.0", @@ -61,7 +62,7 @@ var addon4 = { }] }; -// Stays incompatible +// Would stay incompatible with strict compat var addon5 = { id: "addon5@tests.mozilla.org", version: "1.0", @@ -217,9 +218,9 @@ function run_test_1() { do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE); do_check_neq(a5, null); - do_check_false(a5.isActive); + do_check_true(a5.isActive); do_check_false(a5.userDisabled); - do_check_true(a5.appDisabled); + do_check_false(a5.appDisabled); do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE); do_check_neq(a6, null); @@ -285,21 +286,23 @@ function run_test_1() { do_check_neq(a3, null); do_check_true(a3.isActive); do_check_false(a3.userDisabled); - do_check_true(a3.appDisabled); - do_check_eq(a3.pendingOperations, AddonManager.PENDING_DISABLE); + do_check_false(a3.appDisabled); + do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE); - // The compatibility update won't be recovered and it will not have been - // able to tell that it was previously userDisabled + // The compatibility update won't be recovered and with strict + // compatibility it would not have been able to tell that it was + // previously userDisabled. However, without strict compat, it wasn't + // appDisabled, so it knows it must have been userDisabled. do_check_neq(a4, null); do_check_false(a4.isActive); - do_check_false(a4.userDisabled); - do_check_true(a4.appDisabled); + do_check_true(a4.userDisabled); + do_check_false(a4.appDisabled); do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE); do_check_neq(a5, null); - do_check_false(a5.isActive); + do_check_true(a5.isActive); do_check_false(a5.userDisabled); - do_check_true(a5.appDisabled); + do_check_false(a5.appDisabled); do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE); do_check_neq(a6, null); @@ -354,21 +357,21 @@ function run_test_1() { do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE); do_check_neq(a3, null); - do_check_false(a3.isActive); + do_check_true(a3.isActive); do_check_false(a3.userDisabled); - do_check_true(a3.appDisabled); + do_check_false(a3.appDisabled); do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE); do_check_neq(a4, null); do_check_false(a4.isActive); - do_check_false(a4.userDisabled); - do_check_true(a4.appDisabled); + do_check_true(a4.userDisabled); + do_check_false(a4.appDisabled); do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE); do_check_neq(a5, null); - do_check_false(a5.isActive); + do_check_true(a5.isActive); do_check_false(a5.userDisabled); - do_check_true(a5.appDisabled); + do_check_false(a5.appDisabled); do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE); do_check_neq(a6, null); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_corrupt_strictcompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_corrupt_strictcompat.js new file mode 100644 index 000000000000..4a9766fbe8e4 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_corrupt_strictcompat.js @@ -0,0 +1,403 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Checks that we rebuild something sensible from a corrupt database + + +do_load_httpd_js(); +var testserver; + +// The test extension uses an insecure update url. +Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); +Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, true); + +// Will be enabled +var addon1 = { + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "2", + maxVersion: "2" + }] +}; + +// Will be disabled +var addon2 = { + id: "addon2@tests.mozilla.org", + version: "1.0", + name: "Test 2", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "2", + maxVersion: "2" + }] +}; + +// Will get a compatibility update and be enabled +var addon3 = { + id: "addon3@tests.mozilla.org", + version: "1.0", + name: "Test 3", + updateURL: "http://localhost:4444/data/test_corrupt.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Will get a compatibility update and be disabled +var addon4 = { + id: "addon4@tests.mozilla.org", + version: "1.0", + name: "Test 4", + updateURL: "http://localhost:4444/data/test_corrupt.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Stays incompatible +var addon5 = { + id: "addon5@tests.mozilla.org", + version: "1.0", + name: "Test 5", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Enabled bootstrapped +var addon6 = { + id: "addon6@tests.mozilla.org", + version: "1.0", + name: "Test 6", + bootstrap: "true", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "2", + maxVersion: "2" + }] +}; + +// Disabled bootstrapped +var addon7 = { + id: "addon7@tests.mozilla.org", + version: "1.0", + name: "Test 7", + bootstrap: "true", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "2", + maxVersion: "2" + }] +}; + +// The default theme +var theme1 = { + id: "theme1@tests.mozilla.org", + version: "1.0", + name: "Theme 1", + internalName: "classic/1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "2", + maxVersion: "2" + }] +}; + +// The selected theme +var theme2 = { + id: "theme2@tests.mozilla.org", + version: "1.0", + name: "Theme 2", + internalName: "test/1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "2", + maxVersion: "2" + }] +}; + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2"); + + writeInstallRDFForExtension(addon1, profileDir); + writeInstallRDFForExtension(addon2, profileDir); + writeInstallRDFForExtension(addon3, profileDir); + writeInstallRDFForExtension(addon4, profileDir); + writeInstallRDFForExtension(addon5, profileDir); + writeInstallRDFForExtension(addon6, profileDir); + writeInstallRDFForExtension(addon7, profileDir); + writeInstallRDFForExtension(theme1, profileDir); + writeInstallRDFForExtension(theme2, profileDir); + + // Create and configure the HTTP server. + testserver = new nsHttpServer(); + testserver.registerDirectory("/addons/", do_get_file("addons")); + testserver.registerDirectory("/data/", do_get_file("data")); + testserver.start(4444); + + // Startup the profile and setup the initial state + startupManager(); + + AddonManager.getAddonsByIDs(["addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon7@tests.mozilla.org", + "theme2@tests.mozilla.org"], function([a2, a3, a4, + a7, t2]) { + // Set up the initial state + a2.userDisabled = true; + a4.userDisabled = true; + a7.userDisabled = true; + t2.userDisabled = false; + a3.findUpdates({ + onUpdateFinished: function() { + a4.findUpdates({ + onUpdateFinished: function() { + restartManager(); + + run_test_1(); + } + }, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); + } + }, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); + }); +} + +function end_test() { + testserver.stop(do_test_finished); +} + +function run_test_1() { + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org", + "addon6@tests.mozilla.org", + "addon7@tests.mozilla.org", + "theme1@tests.mozilla.org", + "theme2@tests.mozilla.org"], function([a1, a2, a3, + a4, a5, a6, + a7, t1, t2]) { + do_check_neq(a1, null); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + do_check_false(a1.appDisabled); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a2, null); + do_check_false(a2.isActive); + do_check_true(a2.userDisabled); + do_check_false(a2.appDisabled); + do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a3, null); + do_check_true(a3.isActive); + do_check_false(a3.userDisabled); + do_check_false(a3.appDisabled); + do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a4, null); + do_check_false(a4.isActive); + do_check_true(a4.userDisabled); + do_check_false(a4.appDisabled); + do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a5, null); + do_check_false(a5.isActive); + do_check_false(a5.userDisabled); + do_check_true(a5.appDisabled); + do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a6, null); + do_check_true(a6.isActive); + do_check_false(a6.userDisabled); + do_check_false(a6.appDisabled); + do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a7, null); + do_check_false(a7.isActive); + do_check_true(a7.userDisabled); + do_check_false(a7.appDisabled); + do_check_eq(a7.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(t1, null); + do_check_false(t1.isActive); + do_check_true(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(t2, null); + do_check_true(t2.isActive); + do_check_false(t2.userDisabled); + do_check_false(t2.appDisabled); + do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE); + + // After restarting the database won't be open and so can be replaced with + // a bad file + restartManager(); + var dbfile = gProfD.clone(); + dbfile.append("extensions.sqlite"); + dbfile.remove(true); + dbfile.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755); + + // Accessing the add-ons should open and recover the database + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org", + "addon6@tests.mozilla.org", + "addon7@tests.mozilla.org", + "theme1@tests.mozilla.org", + "theme2@tests.mozilla.org"], function([a1, a2, a3, + a4, a5, a6, + a7, t1, t2]) { + // Should be correctly recovered + do_check_neq(a1, null); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + do_check_false(a1.appDisabled); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + + // Should be correctly recovered + do_check_neq(a2, null); + do_check_false(a2.isActive); + do_check_true(a2.userDisabled); + do_check_false(a2.appDisabled); + do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE); + + // The compatibility update won't be recovered but it should still be + // active for this session + do_check_neq(a3, null); + do_check_true(a3.isActive); + do_check_false(a3.userDisabled); + do_check_true(a3.appDisabled); + do_check_eq(a3.pendingOperations, AddonManager.PENDING_DISABLE); + + // The compatibility update won't be recovered and it will not have been + // able to tell that it was previously userDisabled + do_check_neq(a4, null); + do_check_false(a4.isActive); + do_check_false(a4.userDisabled); + do_check_true(a4.appDisabled); + do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a5, null); + do_check_false(a5.isActive); + do_check_false(a5.userDisabled); + do_check_true(a5.appDisabled); + do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a6, null); + do_check_true(a6.isActive); + do_check_false(a6.userDisabled); + do_check_false(a6.appDisabled); + do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a7, null); + do_check_false(a7.isActive); + do_check_true(a7.userDisabled); + do_check_false(a7.appDisabled); + do_check_eq(a7.pendingOperations, AddonManager.PENDING_NONE); + + // Should be correctly recovered + do_check_neq(t1, null); + do_check_false(t1.isActive); + do_check_true(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE); + + // Should be correctly recovered + do_check_neq(t2, null); + do_check_true(t2.isActive); + do_check_false(t2.userDisabled); + do_check_false(t2.appDisabled); + do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE); + + restartManager(); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org", + "addon6@tests.mozilla.org", + "addon7@tests.mozilla.org", + "theme1@tests.mozilla.org", + "theme2@tests.mozilla.org"], function([a1, a2, a3, + a4, a5, a6, + a7, t1, t2]) { + do_check_neq(a1, null); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + do_check_false(a1.appDisabled); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a2, null); + do_check_false(a2.isActive); + do_check_true(a2.userDisabled); + do_check_false(a2.appDisabled); + do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a3, null); + do_check_false(a3.isActive); + do_check_false(a3.userDisabled); + do_check_true(a3.appDisabled); + do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a4, null); + do_check_false(a4.isActive); + do_check_false(a4.userDisabled); + do_check_true(a4.appDisabled); + do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a5, null); + do_check_false(a5.isActive); + do_check_false(a5.userDisabled); + do_check_true(a5.appDisabled); + do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a6, null); + do_check_true(a6.isActive); + do_check_false(a6.userDisabled); + do_check_false(a6.appDisabled); + do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a7, null); + do_check_false(a7.isActive); + do_check_true(a7.userDisabled); + do_check_false(a7.appDisabled); + do_check_eq(a7.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(t1, null); + do_check_false(t1.isActive); + do_check_true(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(t2, null); + do_check_true(t2.isActive); + do_check_false(t2.userDisabled); + do_check_false(t2.appDisabled); + do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE); + + end_test(); + }); + }); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_install.js b/toolkit/mozapps/extensions/test/xpcshell/test_install.js index 36ee5797a84f..b511f9df2245 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_install.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_install.js @@ -21,7 +21,8 @@ var gInstallDate; var gInstall = null; // The test extension uses an insecure update url. -Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); +Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); +Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false); const profileDir = gProfD.clone(); profileDir.append("extensions"); @@ -671,14 +672,14 @@ function run_test_11() { do_check_true(hasFlag(installs[1].addon.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_INSTALL)); - // Comes from addon6.xpi and is incompatible + // Comes from addon6.xpi and would be incompatible with strict compat enabled do_check_eq(installs[2].sourceURI, install.sourceURI); do_check_eq(installs[2].addon.id, "addon6@tests.mozilla.org"); - do_check_true(installs[2].addon.appDisabled); + do_check_false(installs[2].addon.appDisabled); do_check_eq(installs[2].version, "2.0"); do_check_eq(installs[2].name, "Multi Test 3"); do_check_eq(installs[2].state, AddonManager.STATE_DOWNLOADED); - do_check_false(hasFlag(installs[2].addon.operationsRequiringRestart, + do_check_true(hasFlag(installs[2].addon.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_INSTALL)); // Comes from addon7.jar and is made compatible by an update check @@ -702,8 +703,7 @@ function run_test_11() { "onInstalling" ], "addon6@tests.mozilla.org": [ - ["onInstalling", false], - "onInstalled" + "onInstalling" ], "addon7@tests.mozilla.org": [ "onInstalling" @@ -787,8 +787,7 @@ function run_test_12() { "onInstalling" ], "addon6@tests.mozilla.org": [ - ["onInstalling", false], - "onInstalled" + "onInstalling" ], "addon7@tests.mozilla.org": [ "onInstalling" @@ -851,10 +850,10 @@ function check_test_12() { do_check_eq(installs[1].name, "Multi Test 2"); do_check_eq(installs[1].state, AddonManager.STATE_INSTALLED); - // Comes from addon6.xpi and is incompatible + // Comes from addon6.xpi and would be incompatible with strict compat enabled do_check_eq(installs[2].sourceURI, gInstall.sourceURI); do_check_eq(installs[2].addon.id, "addon6@tests.mozilla.org"); - do_check_true(installs[2].addon.appDisabled); + do_check_false(installs[2].addon.appDisabled); do_check_eq(installs[2].version, "2.0"); do_check_eq(installs[2].name, "Multi Test 3"); do_check_eq(installs[2].state, AddonManager.STATE_INSTALLED); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_install_strictcompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_install_strictcompat.js new file mode 100644 index 000000000000..4c0f7a4bf026 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_install_strictcompat.js @@ -0,0 +1,1623 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that add-ons can be installed from XPI files + +// Maximum error in file modification times. Some file systems don't store +// modification times exactly. As long as we are closer than this then it +// still passes. +const MAX_TIME_DIFFERENCE = 3000; + +Components.utils.import("resource://gre/modules/Services.jsm"); +Components.utils.import("resource://gre/modules/NetUtil.jsm"); + +// install.rdf size, icon.png, icon64.png size +const ADDON1_SIZE = 705 + 16 + 16; + +do_load_httpd_js(); +var testserver; +var gInstallDate; +var gInstall = null; + +// The test extension uses an insecure update url. +Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); +Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, true); + + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + startupManager(); + // Make sure we only register once despite multiple calls + AddonManager.addInstallListener(InstallListener); + AddonManager.addAddonListener(AddonListener); + AddonManager.addInstallListener(InstallListener); + AddonManager.addAddonListener(AddonListener); + + // Create and configure the HTTP server. + testserver = new nsHttpServer(); + testserver.registerDirectory("/addons/", do_get_file("addons")); + 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); + }); + testserver.start(4444); + + do_test_pending(); + run_test_1(); +} + +function end_test() { + testserver.stop(do_test_finished); +} + +// Checks that an install from a local file proceeds as expected +function run_test_1() { + prepare_test({ }, [ + "onNewInstall" + ]); + + AddonManager.getInstallForFile(do_get_addon("test_install1"), function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + do_check_eq(install.linkedInstalls, null); + do_check_eq(install.type, "extension"); + do_check_eq(install.version, "1.0"); + do_check_eq(install.name, "Test 1"); + do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); + do_check_true(install.addon.hasResource("install.rdf")); + do_check_eq(install.addon.install, install); + do_check_eq(install.addon.size, ADDON1_SIZE); + do_check_true(hasFlag(install.addon.operationsRequiringRestart, + AddonManager.OP_NEEDS_RESTART_INSTALL)); + let file = do_get_addon("test_install1"); + let uri = Services.io.newFileURI(file).spec; + do_check_eq(install.addon.getResourceURI("install.rdf").spec, "jar:" + uri + "!/install.rdf"); + do_check_eq(install.addon.iconURL, "jar:" + uri + "!/icon.png"); + do_check_eq(install.addon.icon64URL, "jar:" + uri + "!/icon64.png"); + do_check_eq(install.iconURL, null); + + do_check_eq(install.sourceURI.spec, uri); + do_check_eq(install.addon.sourceURI.spec, uri); + + AddonManager.getAllInstalls(function(activeInstalls) { + do_check_eq(activeInstalls.length, 1); + do_check_eq(activeInstalls[0], install); + + AddonManager.getInstallsByTypes(["foo"], function(fooInstalls) { + do_check_eq(fooInstalls.length, 0); + + AddonManager.getInstallsByTypes(["extension"], function(extensionInstalls) { + do_check_eq(extensionInstalls.length, 1); + do_check_eq(extensionInstalls[0], install); + + prepare_test({ + "addon1@tests.mozilla.org": [ + "onInstalling" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], check_test_1); + install.install(); + }); + }); + }); + }); +} + +function check_test_1() { + ensure_test_completed(); + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(olda1) { + do_check_eq(olda1, null); + + AddonManager.getAddonsWithOperationsByTypes(null, function(pendingAddons) { + do_check_eq(pendingAddons.length, 1); + do_check_eq(pendingAddons[0].id, "addon1@tests.mozilla.org"); + let uri = NetUtil.newURI(pendingAddons[0].iconURL); + if (uri instanceof AM_Ci.nsIJARURI) { + let jarURI = uri.QueryInterface(AM_Ci.nsIJARURI); + let archiveURI = jarURI.JARFile; + let archiveFile = archiveURI.QueryInterface(AM_Ci.nsIFileURL).file; + let zipReader = Cc["@mozilla.org/libjar/zip-reader;1"]. + createInstance(Ci.nsIZipReader); + try { + zipReader.open(archiveFile); + do_check_true(zipReader.hasEntry(jarURI.JAREntry)); + } + finally { + zipReader.close(); + } + } + else { + let iconFile = uri.QueryInterface(AM_Ci.nsIFileURL).file; + do_check_true(iconFile.exists()); + } + + // Make the pending install have a sensible date + let updateDate = Date.now(); + let extURI = pendingAddons[0].getResourceURI(""); + let ext = extURI.QueryInterface(AM_Ci.nsIFileURL).file; + setExtensionModifiedTime(ext, updateDate); + + // The pending add-on cannot be disabled or enabled. + do_check_false(hasFlag(pendingAddons[0].permissions, AddonManager.PERM_CAN_ENABLE)); + do_check_false(hasFlag(pendingAddons[0].permissions, AddonManager.PERM_CAN_DISABLE)); + + restartManager(); + + AddonManager.getAllInstalls(function(activeInstalls) { + do_check_eq(activeInstalls, 0); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.type, "extension"); + do_check_eq(a1.version, "1.0"); + do_check_eq(a1.name, "Test 1"); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); + do_check_true(do_get_addon("test_install1").exists()); + do_check_in_crash_annotation(a1.id, a1.version); + do_check_eq(a1.size, ADDON1_SIZE); + + do_check_eq(a1.sourceURI.spec, + Services.io.newFileURI(do_get_addon("test_install1")).spec); + 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"); + + do_check_true(a1.hasResource("install.rdf")); + do_check_false(a1.hasResource("foo.bar")); + + let uri = do_get_addon_root_uri(profileDir, "addon1@tests.mozilla.org"); + do_check_eq(a1.getResourceURI("install.rdf").spec, uri + "install.rdf"); + do_check_eq(a1.iconURL, uri + "icon.png"); + do_check_eq(a1.icon64URL, uri + "icon64.png"); + + a1.uninstall(); + restartManager(); + do_check_not_in_crash_annotation(a1.id, a1.version); + + run_test_2(); + }); + }); + }); + }); +} + +// Tests that an install from a url downloads. +function run_test_2() { + let url = "http://localhost:4444/addons/test_install2_1.xpi"; + AddonManager.getInstallForURL(url, function(install) { + do_check_neq(install, null); + do_check_eq(install.linkedInstalls, null); + do_check_eq(install.version, "1.0"); + do_check_eq(install.name, "Test 2"); + do_check_eq(install.state, AddonManager.STATE_AVAILABLE); + do_check_eq(install.iconURL, null); + do_check_eq(install.sourceURI.spec, url); + + AddonManager.getAllInstalls(function(activeInstalls) { + do_check_eq(activeInstalls.length, 1); + do_check_eq(activeInstalls[0], install); + + prepare_test({}, [ + "onDownloadStarted", + "onDownloadEnded", + ], check_test_2); + + install.addListener({ + onDownloadProgress: function(install) { + do_execute_soon(function() { + Components.utils.forceGC(); + }); + } + }); + + install.install(); + }); + }, "application/x-xpinstall", null, "Test 2", null, "1.0"); +} + +function check_test_2(install) { + ensure_test_completed(); + do_check_eq(install.version, "2.0"); + do_check_eq(install.name, "Real Test 2"); + do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); + do_check_eq(install.addon.install, install); + do_check_true(hasFlag(install.addon.operationsRequiringRestart, + AddonManager.OP_NEEDS_RESTART_INSTALL)); + do_check_eq(install.iconURL, null); + + // Pause the install here and start it again in run_test_3 + do_execute_soon(function() { run_test_3(install); }); + return false; +} + +// Tests that the downloaded XPI installs ok +function run_test_3(install) { + prepare_test({ + "addon2@tests.mozilla.org": [ + "onInstalling" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], check_test_3); + install.install(); +} + +function check_test_3(aInstall) { + // Make the pending install have a sensible date + let updateDate = Date.now(); + let extURI = aInstall.addon.getResourceURI(""); + let ext = extURI.QueryInterface(AM_Ci.nsIFileURL).file; + setExtensionModifiedTime(ext, updateDate); + + ensure_test_completed(); + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(olda2) { + do_check_eq(olda2, null); + restartManager(); + + AddonManager.getAllInstalls(function(installs) { + do_check_eq(installs, 0); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_neq(a2, null); + do_check_eq(a2.type, "extension"); + do_check_eq(a2.version, "2.0"); + do_check_eq(a2.name, "Real Test 2"); + do_check_true(isExtensionInAddonsList(profileDir, a2.id)); + do_check_true(do_get_addon("test_install2_1").exists()); + do_check_in_crash_annotation(a2.id, a2.version); + do_check_eq(a2.sourceURI.spec, + "http://localhost:4444/addons/test_install2_1.xpi"); + + let difference = a2.installDate.getTime() - updateDate; + if (Math.abs(difference) > MAX_TIME_DIFFERENCE) + do_throw("Add-on install time was out by " + difference + "ms"); + + difference = a2.updateDate.getTime() - updateDate; + if (Math.abs(difference) > MAX_TIME_DIFFERENCE) + do_throw("Add-on update time was out by " + difference + "ms"); + + gInstallDate = a2.installDate.getTime(); + + run_test_4(); + }); + }); + }); +} + +// Tests that installing a new version of an existing add-on works +function run_test_4() { + prepare_test({ }, [ + "onNewInstall" + ]); + + let url = "http://localhost:4444/addons/test_install2_2.xpi"; + AddonManager.getInstallForURL(url, function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + do_check_eq(install.version, "3.0"); + do_check_eq(install.name, "Test 3"); + do_check_eq(install.state, AddonManager.STATE_AVAILABLE); + + AddonManager.getAllInstalls(function(activeInstalls) { + do_check_eq(activeInstalls.length, 1); + do_check_eq(activeInstalls[0], install); + do_check_eq(install.existingAddon, null); + + prepare_test({}, [ + "onDownloadStarted", + "onDownloadEnded", + ], check_test_4); + install.install(); + }); + }, "application/x-xpinstall", null, "Test 3", null, "3.0"); +} + +function check_test_4(install) { + ensure_test_completed(); + + do_check_eq(install.version, "3.0"); + do_check_eq(install.name, "Real Test 3"); + do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); + do_check_neq(install.existingAddon); + do_check_eq(install.existingAddon.id, "addon2@tests.mozilla.org"); + do_check_eq(install.addon.install, install); + do_check_true(hasFlag(install.addon.operationsRequiringRestart, + AddonManager.OP_NEEDS_RESTART_INSTALL)); + + run_test_5(); + // Installation will continue when there is nothing returned. +} + +// Continue installing the new version +function run_test_5() { + prepare_test({ + "addon2@tests.mozilla.org": [ + "onInstalling" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], check_test_5); +} + +function check_test_5(install) { + ensure_test_completed(); + + do_check_eq(install.existingAddon.pendingUpgrade.install, install); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(olda2) { + do_check_neq(olda2, null); + do_check_true(hasFlag(olda2.pendingOperations, AddonManager.PENDING_UPGRADE)); + + AddonManager.getInstallsByTypes(null, function(installs) { + do_check_eq(installs.length, 1); + do_check_eq(installs[0].addon, olda2.pendingUpgrade); + restartManager(); + + AddonManager.getInstallsByTypes(null, function(installs) { + do_check_eq(installs.length, 0); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_neq(a2, null); + do_check_eq(a2.type, "extension"); + do_check_eq(a2.version, "3.0"); + do_check_eq(a2.name, "Real Test 3"); + do_check_true(a2.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a2.id)); + do_check_true(do_get_addon("test_install2_2").exists()); + do_check_in_crash_annotation(a2.id, a2.version); + do_check_eq(a2.sourceURI.spec, + "http://localhost:4444/addons/test_install2_2.xpi"); + + do_check_eq(a2.installDate.getTime(), gInstallDate); + // Update date should be later (or the same if this test is too fast) + do_check_true(a2.installDate <= a2.updateDate); + + a2.uninstall(); + restartManager(); + + run_test_6(); + }); + }); + }); + }); +} + +// Tests that an install that requires a compatibility update works +function run_test_6() { + prepare_test({ }, [ + "onNewInstall" + ]); + + let url = "http://localhost:4444/addons/test_install3.xpi"; + AddonManager.getInstallForURL(url, function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + do_check_eq(install.version, "1.0"); + do_check_eq(install.name, "Real Test 4"); + do_check_eq(install.state, AddonManager.STATE_AVAILABLE); + + AddonManager.getInstallsByTypes(null, function(activeInstalls) { + do_check_eq(activeInstalls.length, 1); + do_check_eq(activeInstalls[0], install); + + prepare_test({}, [ + "onDownloadStarted", + "onDownloadEnded", + ], check_test_6); + install.install(); + }); + }, "application/x-xpinstall", null, "Real Test 4", null, "1.0"); +} + +function check_test_6(install) { + ensure_test_completed(); + do_check_eq(install.version, "1.0"); + do_check_eq(install.name, "Real Test 4"); + do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); + do_check_eq(install.existingAddon, null); + do_check_false(install.addon.appDisabled); + run_test_7(); + return true; +} + +// Continue the install +function run_test_7() { + prepare_test({ + "addon3@tests.mozilla.org": [ + "onInstalling" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], check_test_7); +} + +function check_test_7() { + ensure_test_completed(); + AddonManager.getAddonByID("addon3@tests.mozilla.org", function(olda3) { + do_check_eq(olda3, null); + restartManager(); + + AddonManager.getAllInstalls(function(installs) { + do_check_eq(installs, 0); + + AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) { + do_check_neq(a3, null); + do_check_eq(a3.type, "extension"); + do_check_eq(a3.version, "1.0"); + do_check_eq(a3.name, "Real Test 4"); + do_check_true(a3.isActive); + do_check_false(a3.appDisabled); + do_check_true(isExtensionInAddonsList(profileDir, a3.id)); + do_check_true(do_get_addon("test_install3").exists()); + a3.uninstall(); + restartManager(); + + run_test_8(); + }); + }); + }); +} + +function run_test_8() { + AddonManager.addInstallListener(InstallListener); + AddonManager.addAddonListener(AddonListener); + + prepare_test({ }, [ + "onNewInstall" + ]); + + AddonManager.getInstallForFile(do_get_addon("test_install3"), function(install) { + do_check_true(install.addon.isCompatible); + + prepare_test({ + "addon3@tests.mozilla.org": [ + "onInstalling" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], check_test_8); + install.install(); + }); +} + +function check_test_8() { + restartManager(); + + AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) { + do_check_neq(a3, null); + do_check_eq(a3.type, "extension"); + do_check_eq(a3.version, "1.0"); + do_check_eq(a3.name, "Real Test 4"); + do_check_true(a3.isActive); + do_check_false(a3.appDisabled); + do_check_true(isExtensionInAddonsList(profileDir, a3.id)); + do_check_true(do_get_addon("test_install3").exists()); + a3.uninstall(); + restartManager(); + + run_test_9(); + }); +} + +// Test that after cancelling a download it is removed from the active installs +function run_test_9() { + prepare_test({ }, [ + "onNewInstall" + ]); + + let url = "http://localhost:4444/addons/test_install3.xpi"; + AddonManager.getInstallForURL(url, function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + do_check_eq(install.version, "1.0"); + do_check_eq(install.name, "Real Test 4"); + do_check_eq(install.state, AddonManager.STATE_AVAILABLE); + + AddonManager.getInstallsByTypes(null, function(activeInstalls) { + do_check_eq(activeInstalls.length, 1); + do_check_eq(activeInstalls[0], install); + + prepare_test({}, [ + "onDownloadStarted", + "onDownloadEnded", + ], check_test_9); + install.install(); + }); + }, "application/x-xpinstall", null, "Real Test 4", null, "1.0"); +} + +function check_test_9(install) { + prepare_test({}, [ + "onDownloadCancelled" + ]); + + install.cancel(); + + ensure_test_completed(); + + AddonManager.getAllInstalls(function(activeInstalls) { + do_check_eq(activeInstalls.length, 0); + + run_test_10(); + }); +} + +// Tests that after cancelling a pending install it is removed from the active +// installs +function run_test_10() { + prepare_test({ }, [ + "onNewInstall" + ]); + + let url = "http://localhost:4444/addons/test_install3.xpi"; + AddonManager.getInstallForURL(url, function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + do_check_eq(install.version, "1.0"); + do_check_eq(install.name, "Real Test 4"); + do_check_eq(install.state, AddonManager.STATE_AVAILABLE); + + AddonManager.getInstallsByTypes(null, function(activeInstalls) { + do_check_eq(activeInstalls.length, 1); + do_check_eq(activeInstalls[0], install); + + prepare_test({ + "addon3@tests.mozilla.org": [ + "onInstalling" + ] + }, [ + "onDownloadStarted", + "onDownloadEnded", + "onInstallStarted", + "onInstallEnded" + ], check_test_10); + install.install(); + }); + }, "application/x-xpinstall", null, "Real Test 4", null, "1.0"); +} + +function check_test_10(install) { + prepare_test({ + "addon3@tests.mozilla.org": [ + "onOperationCancelled" + ] + }, [ + "onInstallCancelled" + ]); + + install.cancel(); + + ensure_test_completed(); + + AddonManager.getAllInstalls(function(activeInstalls) { + do_check_eq(activeInstalls.length, 0); + + restartManager(); + + // Check that the install did not complete + AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) { + do_check_eq(a3, null); + + run_test_11(); + }); + }); +} + +// Tests that a multi-package install shows up as multiple installs with the +// correct sourceURI. +function run_test_11() { + prepare_test({ }, [ + "onNewInstall", + "onNewInstall", + "onNewInstall", + "onNewInstall" + ]); + + AddonManager.getInstallForFile(do_get_addon("test_install4"), function(install) { + ensure_test_completed(); + do_check_neq(install, null); + do_check_neq(install.linkedInstalls, null); + do_check_eq(install.linkedInstalls.length, 3); + + // Might be in any order so sort them based on ID + let installs = [install].concat(install.linkedInstalls); + installs.sort(function(a, b) { + if (a.addon.id < b.addon.id) + return -1; + if (a.addon.id > b.addon.id) + return 1; + return 0; + }); + + // Comes from addon4.xpi and is made compatible by an update check + do_check_eq(installs[0].sourceURI, install.sourceURI); + do_check_eq(installs[0].addon.id, "addon4@tests.mozilla.org"); + do_check_false(installs[0].addon.appDisabled); + do_check_eq(installs[0].version, "1.0"); + do_check_eq(installs[0].name, "Multi Test 1"); + do_check_eq(installs[0].state, AddonManager.STATE_DOWNLOADED); + do_check_true(hasFlag(installs[0].addon.operationsRequiringRestart, + AddonManager.OP_NEEDS_RESTART_INSTALL)); + + // Comes from addon5.jar and is compatible by default + do_check_eq(installs[1].sourceURI, install.sourceURI); + do_check_eq(installs[1].addon.id, "addon5@tests.mozilla.org"); + do_check_false(installs[1].addon.appDisabled); + do_check_eq(installs[1].version, "3.0"); + do_check_eq(installs[1].name, "Multi Test 2"); + do_check_eq(installs[1].state, AddonManager.STATE_DOWNLOADED); + do_check_true(hasFlag(installs[1].addon.operationsRequiringRestart, + AddonManager.OP_NEEDS_RESTART_INSTALL)); + + // Comes from addon6.xpi and is incompatible + do_check_eq(installs[2].sourceURI, install.sourceURI); + do_check_eq(installs[2].addon.id, "addon6@tests.mozilla.org"); + do_check_true(installs[2].addon.appDisabled); + do_check_eq(installs[2].version, "2.0"); + do_check_eq(installs[2].name, "Multi Test 3"); + do_check_eq(installs[2].state, AddonManager.STATE_DOWNLOADED); + do_check_false(hasFlag(installs[2].addon.operationsRequiringRestart, + AddonManager.OP_NEEDS_RESTART_INSTALL)); + + // Comes from addon7.jar and is made compatible by an update check + do_check_eq(installs[3].sourceURI, install.sourceURI); + do_check_eq(installs[3].addon.id, "addon7@tests.mozilla.org"); + do_check_false(installs[3].addon.appDisabled); + do_check_eq(installs[3].version, "5.0"); + do_check_eq(installs[3].name, "Multi Test 4"); + do_check_eq(installs[3].state, AddonManager.STATE_DOWNLOADED); + do_check_true(hasFlag(installs[3].addon.operationsRequiringRestart, + AddonManager.OP_NEEDS_RESTART_INSTALL)); + + AddonManager.getAllInstalls(function(aInstalls) { + do_check_eq(aInstalls.length, 4); + + prepare_test({ + "addon4@tests.mozilla.org": [ + "onInstalling" + ], + "addon5@tests.mozilla.org": [ + "onInstalling" + ], + "addon6@tests.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ], + "addon7@tests.mozilla.org": [ + "onInstalling" + ] + }, { + "addon4@tests.mozilla.org": [ + "onInstallStarted", + "onInstallEnded" + ], + "addon5@tests.mozilla.org": [ + "onInstallStarted", + "onInstallEnded" + ], + "addon6@tests.mozilla.org": [ + "onInstallStarted", + "onInstallEnded" + ], + "addon7@tests.mozilla.org": [ + "onInstallStarted", + "onInstallEnded" + ] + }, check_test_11); + + installs[0].install(); + installs[1].install(); + installs[3].install(); + + // Note that we install addon6 last. Since it doesn't need a restart to + // install it completes asynchronously which would otherwise make the + // onInstallStarted/onInstallEnded events go out of sequence unless this + // is the last install operation + installs[2].install(); + }); + }); +} + +function check_test_11() { + restartManager(); + + AddonManager.getAddonsByIDs(["addon4@tests.mozilla.org", + "addon5@tests.mozilla.org", + "addon6@tests.mozilla.org", + "addon7@tests.mozilla.org"], + function([a4, a5, a6, a7]) { + do_check_neq(a4, null); + do_check_neq(a5, null); + do_check_neq(a6, null); + do_check_neq(a7, null); + + a4.uninstall(); + a5.uninstall(); + a6.uninstall(); + a7.uninstall(); + + restartManager(); + + run_test_12(); + }); +} + +// Same as test 11 but for a remote XPI +function run_test_12() { + prepare_test({ }, [ + "onNewInstall", + ]); + + let url = "http://localhost:4444/addons/test_install4.xpi"; + AddonManager.getInstallForURL(url, function(install) { + gInstall = install; + + ensure_test_completed(); + do_check_neq(install, null); + do_check_eq(install.linkedInstalls, null); + do_check_eq(install.state, AddonManager.STATE_AVAILABLE); + + prepare_test({ + "addon4@tests.mozilla.org": [ + "onInstalling" + ], + "addon5@tests.mozilla.org": [ + "onInstalling" + ], + "addon6@tests.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ], + "addon7@tests.mozilla.org": [ + "onInstalling" + ] + }, { + "NO_ID": [ + "onDownloadStarted", + "onNewInstall", + "onNewInstall", + "onNewInstall", + "onDownloadEnded" + ], + "addon4@tests.mozilla.org": [ + "onInstallStarted", + "onInstallEnded" + ], + "addon5@tests.mozilla.org": [ + "onInstallStarted", + "onInstallEnded" + ], + "addon6@tests.mozilla.org": [ + "onInstallStarted", + "onInstallEnded" + ], + "addon7@tests.mozilla.org": [ + "onInstallStarted", + "onInstallEnded" + ] + }, check_test_12); + install.install(); + }, "application/x-xpinstall", null, "Multi Test 4"); +} + +function check_test_12() { + do_check_eq(gInstall.linkedInstalls.length, 3); + + // Might be in any order so sort them based on ID + let installs = [gInstall].concat(gInstall.linkedInstalls); + installs.sort(function(a, b) { + if (a.addon.id < b.addon.id) + return -1; + if (a.addon.id > b.addon.id) + return 1; + return 0; + }); + + // Comes from addon4.xpi and is made compatible by an update check + do_check_eq(installs[0].sourceURI, gInstall.sourceURI); + do_check_eq(installs[0].addon.id, "addon4@tests.mozilla.org"); + do_check_false(installs[0].addon.appDisabled); + do_check_eq(installs[0].version, "1.0"); + do_check_eq(installs[0].name, "Multi Test 1"); + do_check_eq(installs[0].state, AddonManager.STATE_INSTALLED); + + // Comes from addon5.jar and is compatible by default + do_check_eq(installs[1].sourceURI, gInstall.sourceURI); + do_check_eq(installs[1].addon.id, "addon5@tests.mozilla.org"); + do_check_false(installs[1].addon.appDisabled); + do_check_eq(installs[1].version, "3.0"); + do_check_eq(installs[1].name, "Multi Test 2"); + do_check_eq(installs[1].state, AddonManager.STATE_INSTALLED); + + // Comes from addon6.xpi and is incompatible + do_check_eq(installs[2].sourceURI, gInstall.sourceURI); + do_check_eq(installs[2].addon.id, "addon6@tests.mozilla.org"); + do_check_true(installs[2].addon.appDisabled); + do_check_eq(installs[2].version, "2.0"); + do_check_eq(installs[2].name, "Multi Test 3"); + do_check_eq(installs[2].state, AddonManager.STATE_INSTALLED); + + // Comes from addon7.jar and is made compatible by an update check + do_check_eq(installs[3].sourceURI, gInstall.sourceURI); + do_check_eq(installs[3].addon.id, "addon7@tests.mozilla.org"); + do_check_false(installs[3].addon.appDisabled); + do_check_eq(installs[3].version, "5.0"); + do_check_eq(installs[3].name, "Multi Test 4"); + do_check_eq(installs[3].state, AddonManager.STATE_INSTALLED); + + restartManager(); + + AddonManager.getAddonsByIDs(["addon4@tests.mozilla.org", + "addon5@tests.mozilla.org", + "addon6@tests.mozilla.org", + "addon7@tests.mozilla.org"], + function([a4, a5, a6, a7]) { + do_check_neq(a4, null); + do_check_neq(a5, null); + do_check_neq(a6, null); + do_check_neq(a7, null); + + a4.uninstall(); + a5.uninstall(); + a6.uninstall(); + a7.uninstall(); + + restartManager(); + + run_test_13(); + }); +} + + +// Tests that cancelling an upgrade leaves the original add-on's pendingOperations +// correct +function run_test_13() { + installAllFiles([do_get_addon("test_install2_1")], function() { + restartManager(); + + prepare_test({ }, [ + "onNewInstall" + ]); + + let url = "http://localhost:4444/addons/test_install2_2.xpi"; + AddonManager.getInstallForURL(url, function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + do_check_eq(install.version, "3.0"); + do_check_eq(install.name, "Test 3"); + do_check_eq(install.state, AddonManager.STATE_AVAILABLE); + + AddonManager.getAllInstalls(function(activeInstalls) { + do_check_eq(activeInstalls.length, 1); + do_check_eq(activeInstalls[0], install); + do_check_eq(install.existingAddon, null); + + prepare_test({ + "addon2@tests.mozilla.org": [ + "onInstalling" + ] + }, [ + "onDownloadStarted", + "onDownloadEnded", + "onInstallStarted", + "onInstallEnded", + ], check_test_13); + install.install(); + }); + }, "application/x-xpinstall", null, "Test 3", null, "3.0"); + }); +} + +function check_test_13(install) { + ensure_test_completed(); + + do_check_eq(install.version, "3.0"); + do_check_eq(install.name, "Real Test 3"); + do_check_eq(install.state, AddonManager.STATE_INSTALLED); + do_check_neq(install.existingAddon, null); + do_check_eq(install.existingAddon.id, "addon2@tests.mozilla.org"); + do_check_eq(install.addon.install, install); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(olda2) { + do_check_neq(olda2, null); + do_check_true(hasFlag(olda2.pendingOperations, AddonManager.PENDING_UPGRADE)); + do_check_eq(olda2.pendingUpgrade, install.addon); + + do_check_true(hasFlag(install.addon.pendingOperations, + AddonManager.PENDING_INSTALL)); + + prepare_test({ + "addon2@tests.mozilla.org": [ + "onOperationCancelled" + ] + }, [ + "onInstallCancelled", + ]); + + install.cancel(); + + do_check_false(hasFlag(install.addon.pendingOperations, AddonManager.PENDING_INSTALL)); + + do_check_false(hasFlag(olda2.pendingOperations, AddonManager.PENDING_UPGRADE)); + do_check_eq(olda2.pendingUpgrade, null); + + restartManager(); + + // Check that the upgrade did not complete + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_eq(a2.version, "2.0"); + + a2.uninstall(); + + restartManager(); + + run_test_14(); + }); + }); +} + +// Check that cancelling the install from onDownloadStarted actually cancels it +function run_test_14() { + prepare_test({ }, [ + "onNewInstall" + ]); + + let url = "http://localhost:4444/addons/test_install2_1.xpi"; + AddonManager.getInstallForURL(url, function(install) { + ensure_test_completed(); + + do_check_eq(install.file, null); + + prepare_test({ }, [ + "onDownloadStarted" + ], check_test_14); + install.install(); + }, "application/x-xpinstall"); +} + +function check_test_14(install) { + prepare_test({ }, [ + "onDownloadCancelled" + ]); + + install.cancel(); + + ensure_test_completed(); + + install.addListener({ + onDownloadProgress: function() { + do_throw("Download should not have continued"); + }, + onDownloadEnded: function() { + do_throw("Download should not have continued"); + } + }); + + // Allow the listener to return to see if it continues downloading. The + // The listener only really tests if we give it time to see progress, the + // file check isn't ideal either + do_execute_soon(function() { + do_check_eq(install.file, null); + + run_test_15(); + }); +} + +// Checks that cancelling the install from onDownloadEnded actually cancels it +function run_test_15() { + prepare_test({ }, [ + "onNewInstall" + ]); + + let url = "http://localhost:4444/addons/test_install2_1.xpi"; + AddonManager.getInstallForURL(url, function(install) { + ensure_test_completed(); + + do_check_eq(install.file, null); + + prepare_test({ }, [ + "onDownloadStarted", + "onDownloadEnded" + ], check_test_15); + install.install(); + }, "application/x-xpinstall"); +} + +function check_test_15(install) { + prepare_test({ }, [ + "onDownloadCancelled" + ]); + + install.cancel(); + + ensure_test_completed(); + + install.addListener({ + onInstallStarted: function() { + do_throw("Install should not have continued"); + } + }); + + // Allow the listener to return to see if it starts installing + do_execute_soon(run_test_16); +} + +// Verify that the userDisabled value carries over to the upgrade by default +function run_test_16() { + restartManager(); + + let url = "http://localhost:4444/addons/test_install2_1.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ + onInstallStarted: function() { + do_check_false(aInstall.addon.userDisabled); + aInstall.addon.userDisabled = true; + }, + + onInstallEnded: function() { + restartManager(); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_true(a2.userDisabled); + do_check_false(a2.isActive); + + let url = "http://localhost:4444/addons/test_install2_2.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ + onInstallEnded: function() { + do_check_true(aInstall.addon.userDisabled); + + restartManager(); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_true(a2.userDisabled); + do_check_false(a2.isActive); + + a2.uninstall(); + restartManager(); + + run_test_17(); + }); + } + }); + aInstall.install(); + }, "application/x-xpinstall"); + }); + } + }); + aInstall.install(); + }, "application/x-xpinstall"); +} + +// Verify that changing the userDisabled value before onInstallEnded works +function run_test_17() { + let url = "http://localhost:4444/addons/test_install2_1.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ + onInstallEnded: function() { + do_check_false(aInstall.addon.userDisabled); + + restartManager(); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_false(a2.userDisabled); + do_check_true(a2.isActive); + + let url = "http://localhost:4444/addons/test_install2_2.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ + onInstallStarted: function() { + do_check_false(aInstall.addon.userDisabled); + aInstall.addon.userDisabled = true; + }, + + onInstallEnded: function() { + restartManager(); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_true(a2.userDisabled); + do_check_false(a2.isActive); + + a2.uninstall(); + restartManager(); + + run_test_18(); + }); + } + }); + aInstall.install(); + }, "application/x-xpinstall"); + }); + } + }); + aInstall.install(); + }, "application/x-xpinstall"); +} + +// Verify that changing the userDisabled value before onInstallEnded works +function run_test_18() { + let url = "http://localhost:4444/addons/test_install2_1.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ + onInstallStarted: function() { + do_check_false(aInstall.addon.userDisabled); + aInstall.addon.userDisabled = true; + }, + + onInstallEnded: function() { + restartManager(); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_true(a2.userDisabled); + do_check_false(a2.isActive); + + let url = "http://localhost:4444/addons/test_install2_2.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ + onInstallStarted: function() { + do_check_true(aInstall.addon.userDisabled); + aInstall.addon.userDisabled = false; + }, + + onInstallEnded: function() { + restartManager(); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_false(a2.userDisabled); + do_check_true(a2.isActive); + + a2.uninstall(); + restartManager(); + + run_test_18_1(); + }); + } + }); + aInstall.install(); + }, "application/x-xpinstall"); + }); + } + }); + aInstall.install(); + }, "application/x-xpinstall"); +} + + +// Checks that metadata is not stored if the pref is set to false +function run_test_18_1() { + Services.prefs.setBoolPref("extensions.getAddons.cache.enabled", true); + Services.prefs.setCharPref("extensions.getAddons.get.url", + "http://localhost:4444/data/test_install.xml"); + + Services.prefs.setBoolPref("extensions.addon2@tests.mozilla.org.getAddons.cache.enabled", false); + + let url = "http://localhost:4444/addons/test_install2_1.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ + onInstallEnded: function(aInstall, aAddon) { + do_check_neq(aAddon.fullDescription, "Repository description"); + + restartManager(); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_neq(a2.fullDescription, "Repository description"); + + a2.uninstall(); + restartManager(); + + Services.prefs.setBoolPref("extensions.addon2@tests.mozilla.org.getAddons.cache.enabled", true); + run_test_19(); + }); + } + }); + aInstall.install(); + }, "application/x-xpinstall"); +} + +// Checks that metadata is downloaded for new installs and is visible before and +// after restart +function run_test_19() { + let url = "http://localhost:4444/addons/test_install2_1.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ + onInstallEnded: function(aInstall, aAddon) { + do_check_eq(aAddon.fullDescription, "Repository description"); + + restartManager(); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_eq(a2.fullDescription, "Repository description"); + + a2.uninstall(); + restartManager(); + + run_test_20(); + }); + } + }); + aInstall.install(); + }, "application/x-xpinstall"); +} + +// Do the same again to make sure it works when the data is already in the cache +function run_test_20() { + let url = "http://localhost:4444/addons/test_install2_1.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ + onInstallEnded: function(aInstall, aAddon) { + do_check_eq(aAddon.fullDescription, "Repository description"); + + restartManager(); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_eq(a2.fullDescription, "Repository description"); + + a2.uninstall(); + restartManager(); + + Services.prefs.setBoolPref("extensions.getAddons.cache.enabled", false); + run_test_21(); + }); + } + }); + aInstall.install(); + }, "application/x-xpinstall"); +} + +// Verify that installing an add-on that is already pending install cancels the +// first install +function run_test_21() { + installAllFiles([do_get_addon("test_install2_1")], function() { + AddonManager.getAllInstalls(function(aInstalls) { + do_check_eq(aInstalls.length, 1); + + prepare_test({ + "addon2@tests.mozilla.org": [ + "onOperationCancelled", + "onInstalling" + ] + }, [ + "onNewInstall", + "onDownloadStarted", + "onDownloadEnded", + "onInstallStarted", + "onInstallCancelled", + "onInstallEnded", + ], check_test_21); + + let url = "http://localhost:4444/addons/test_install2_1.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.install(); + }, "application/x-xpinstall"); + }); + }); +} + +function check_test_21(aInstall) { + AddonManager.getAllInstalls(function(aInstalls) { + do_check_eq(aInstalls.length, 1); + do_check_eq(aInstalls[0], aInstall); + + prepare_test({ + "addon2@tests.mozilla.org": [ + "onOperationCancelled" + ] + }, [ + "onInstallCancelled", + ]); + + aInstall.cancel(); + + ensure_test_completed(); + + restartManager(); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_eq(a2, null); + + run_test_22(); + }); + }); +} + +// Tests that an install can be restarted after being cancelled +function run_test_22() { + prepare_test({ }, [ + "onNewInstall" + ]); + + let url = "http://localhost:4444/addons/test_install3.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + ensure_test_completed(); + + do_check_neq(aInstall, null); + do_check_eq(aInstall.state, AddonManager.STATE_AVAILABLE); + + prepare_test({}, [ + "onDownloadStarted", + "onDownloadEnded", + ], check_test_22); + aInstall.install(); + }, "application/x-xpinstall"); +} + +function check_test_22(aInstall) { + prepare_test({}, [ + "onDownloadCancelled" + ]); + + aInstall.cancel(); + + ensure_test_completed(); + + prepare_test({ + "addon3@tests.mozilla.org": [ + "onInstalling" + ] + }, [ + "onDownloadStarted", + "onDownloadEnded", + "onInstallStarted", + "onInstallEnded" + ], finish_test_22); + + aInstall.install(); +} + +function finish_test_22(aInstall) { + prepare_test({ + "addon3@tests.mozilla.org": [ + "onOperationCancelled" + ] + }, [ + "onInstallCancelled" + ]); + + aInstall.cancel(); + + ensure_test_completed(); + + run_test_23(); +} + +// Tests that an install can be restarted after being cancelled when a hash +// was provided +function run_test_23() { + prepare_test({ }, [ + "onNewInstall" + ]); + + let url = "http://localhost:4444/addons/test_install3.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + ensure_test_completed(); + + do_check_neq(aInstall, null); + do_check_eq(aInstall.state, AddonManager.STATE_AVAILABLE); + + prepare_test({}, [ + "onDownloadStarted", + "onDownloadEnded", + ], check_test_23); + aInstall.install(); + }, "application/x-xpinstall", do_get_addon_hash("test_install3")); +} + +function check_test_23(aInstall) { + prepare_test({}, [ + "onDownloadCancelled" + ]); + + aInstall.cancel(); + + ensure_test_completed(); + + prepare_test({ + "addon3@tests.mozilla.org": [ + "onInstalling" + ] + }, [ + "onDownloadStarted", + "onDownloadEnded", + "onInstallStarted", + "onInstallEnded" + ], finish_test_23); + + aInstall.install(); +} + +function finish_test_23(aInstall) { + prepare_test({ + "addon3@tests.mozilla.org": [ + "onOperationCancelled" + ] + }, [ + "onInstallCancelled" + ]); + + aInstall.cancel(); + + ensure_test_completed(); + + run_test_24(); +} + +// Tests that an install with a bad hash can be restarted after it fails, though +// it will only fail again +function run_test_24() { + prepare_test({ }, [ + "onNewInstall" + ]); + + let url = "http://localhost:4444/addons/test_install3.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + ensure_test_completed(); + + do_check_neq(aInstall, null); + do_check_eq(aInstall.state, AddonManager.STATE_AVAILABLE); + + prepare_test({}, [ + "onDownloadStarted", + "onDownloadFailed", + ], check_test_24); + aInstall.install(); + }, "application/x-xpinstall", "sha1:foo"); +} + +function check_test_24(aInstall) { + prepare_test({ }, [ + "onDownloadStarted", + "onDownloadFailed" + ], run_test_25); + + aInstall.install(); +} + +// Tests that installs with a hash for a local file work +function run_test_25() { + prepare_test({ }, [ + "onNewInstall" + ]); + + let url = Services.io.newFileURI(do_get_addon("test_install3")).spec; + AddonManager.getInstallForURL(url, function(aInstall) { + ensure_test_completed(); + + do_check_neq(aInstall, null); + do_check_eq(aInstall.state, AddonManager.STATE_DOWNLOADED); + do_check_eq(aInstall.error, 0); + + prepare_test({ }, [ + "onDownloadCancelled" + ]); + + aInstall.cancel(); + + ensure_test_completed(); + + run_test_26(); + }, "application/x-xpinstall", do_get_addon_hash("test_install3")); +} + +function run_test_26() { + prepare_test({ }, [ + "onNewInstall", + "onDownloadStarted", + "onDownloadCancelled" + ]); + + let observerService = AM_Cc["@mozilla.org/network/http-activity-distributor;1"]. + getService(AM_Ci.nsIHttpActivityDistributor); + observerService.addObserver({ + observeActivity: function(aChannel, aType, aSubtype, aTimestamp, aSizeData, + aStringData) { + aChannel.QueryInterface(AM_Ci.nsIChannel); + // Wait for the final event for the redirected URL + if (aChannel.URI.spec != "http://localhost:4444/addons/test_install1.xpi" || + aType != AM_Ci.nsIHttpActivityObserver.ACTIVITY_TYPE_HTTP_TRANSACTION || + aSubtype != AM_Ci.nsIHttpActivityObserver.ACTIVITY_SUBTYPE_TRANSACTION_CLOSE) + return; + + // Request should have been cancelled + do_check_eq(aChannel.status, Components.results.NS_BINDING_ABORTED); + + observerService.removeObserver(this); + + run_test_27(); + } + }); + + let url = "http://localhost:4444/redirect?/addons/test_install1.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ + onDownloadProgress: function(aInstall) { + aInstall.cancel(); + } + }); + + aInstall.install(); + }, "application/x-xpinstall"); +} + + +// Tests that an install can be restarted during onDownloadCancelled after being +// cancelled in mid-download +function run_test_27() { + prepare_test({ }, [ + "onNewInstall" + ]); + + let url = "http://localhost:4444/addons/test_install3.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + ensure_test_completed(); + + do_check_neq(aInstall, null); + do_check_eq(aInstall.state, AddonManager.STATE_AVAILABLE); + + aInstall.addListener({ + onDownloadProgress: function() { + aInstall.removeListener(this); + aInstall.cancel(); + } + }); + + prepare_test({}, [ + "onDownloadStarted", + "onDownloadCancelled", + ], check_test_27); + aInstall.install(); + }, "application/x-xpinstall"); +} + +function check_test_27(aInstall) { + prepare_test({ + "addon3@tests.mozilla.org": [ + "onInstalling" + ] + }, [ + "onDownloadStarted", + "onDownloadEnded", + "onInstallStarted", + "onInstallEnded" + ], finish_test_27); + + aInstall.install(); +} + +function finish_test_27(aInstall) { + prepare_test({ + "addon3@tests.mozilla.org": [ + "onOperationCancelled" + ] + }, [ + "onInstallCancelled" + ]); + + aInstall.cancel(); + + ensure_test_completed(); + + do_test_finished(); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_locked.js b/toolkit/mozapps/extensions/test/xpcshell/test_locked.js index e4bdca8975ab..48e1f79f3df4 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_locked.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_locked.js @@ -9,7 +9,8 @@ do_load_httpd_js(); var testserver; // The test extension uses an insecure update url. -Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); +Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); +Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false); // Will be enabled var addon1 = { @@ -35,7 +36,7 @@ var addon2 = { }] }; -// Will get a compatibility update and be enabled +// Will get a compatibility update and stay enabled var addon3 = { id: "addon3@tests.mozilla.org", version: "1.0", @@ -48,7 +49,7 @@ var addon3 = { }] }; -// Will get a compatibility update and be disabled +// Will get a compatibility update and be enabled var addon4 = { id: "addon4@tests.mozilla.org", version: "1.0", @@ -61,7 +62,7 @@ var addon4 = { }] }; -// Stays incompatible +// Would stay incompatible with strict compat var addon5 = { id: "addon5@tests.mozilla.org", version: "1.0", @@ -217,9 +218,9 @@ function run_test_1() { do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE); do_check_neq(a5, null); - do_check_false(a5.isActive); + do_check_true(a5.isActive); do_check_false(a5.userDisabled); - do_check_true(a5.appDisabled); + do_check_false(a5.appDisabled); do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE); do_check_neq(a6, null); @@ -285,21 +286,23 @@ function run_test_1() { do_check_neq(a3, null); do_check_true(a3.isActive); do_check_false(a3.userDisabled); - do_check_true(a3.appDisabled); - do_check_eq(a3.pendingOperations, AddonManager.PENDING_DISABLE); + do_check_false(a3.appDisabled); + do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE); - // The compatibility update won't be recovered and it will not have been - // able to tell that it was previously userDisabled + // The compatibility update won't be recovered and with strict + // compatibility it would not have been able to tell that it was + // previously userDisabled. However, without strict compat, it wasn't + // appDisabled, so it knows it must have been userDisabled. do_check_neq(a4, null); do_check_false(a4.isActive); - do_check_false(a4.userDisabled); - do_check_true(a4.appDisabled); + do_check_true(a4.userDisabled); + do_check_false(a4.appDisabled); do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE); do_check_neq(a5, null); - do_check_false(a5.isActive); + do_check_true(a5.isActive); do_check_false(a5.userDisabled); - do_check_true(a5.appDisabled); + do_check_false(a5.appDisabled); do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE); do_check_neq(a6, null); @@ -357,21 +360,21 @@ function run_test_1() { do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE); do_check_neq(a3, null); - do_check_false(a3.isActive); + do_check_true(a3.isActive); do_check_false(a3.userDisabled); - do_check_true(a3.appDisabled); + do_check_false(a3.appDisabled); do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE); do_check_neq(a4, null); do_check_false(a4.isActive); - do_check_false(a4.userDisabled); - do_check_true(a4.appDisabled); + do_check_true(a4.userDisabled); + do_check_false(a4.appDisabled); do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE); do_check_neq(a5, null); - do_check_false(a5.isActive); + do_check_true(a5.isActive); do_check_false(a5.userDisabled); - do_check_true(a5.appDisabled); + do_check_false(a5.appDisabled); do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE); do_check_neq(a6, null); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_locked_strictcompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_locked_strictcompat.js new file mode 100644 index 000000000000..42d694ecc753 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_locked_strictcompat.js @@ -0,0 +1,407 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Checks that we rebuild something sensible from a corrupt database + + +do_load_httpd_js(); +var testserver; + +// The test extension uses an insecure update url. +Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); +Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, true); + +// Will be enabled +var addon1 = { + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "2", + maxVersion: "2" + }] +}; + +// Will be disabled +var addon2 = { + id: "addon2@tests.mozilla.org", + version: "1.0", + name: "Test 2", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "2", + maxVersion: "2" + }] +}; + +// Will get a compatibility update and be enabled +var addon3 = { + id: "addon3@tests.mozilla.org", + version: "1.0", + name: "Test 3", + updateURL: "http://localhost:4444/data/test_corrupt.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Will get a compatibility update and be disabled +var addon4 = { + id: "addon4@tests.mozilla.org", + version: "1.0", + name: "Test 4", + updateURL: "http://localhost:4444/data/test_corrupt.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Stays incompatible +var addon5 = { + id: "addon5@tests.mozilla.org", + version: "1.0", + name: "Test 5", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Enabled bootstrapped +var addon6 = { + id: "addon6@tests.mozilla.org", + version: "1.0", + name: "Test 6", + bootstrap: "true", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "2", + maxVersion: "2" + }] +}; + +// Disabled bootstrapped +var addon7 = { + id: "addon7@tests.mozilla.org", + version: "1.0", + name: "Test 7", + bootstrap: "true", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "2", + maxVersion: "2" + }] +}; + +// The default theme +var theme1 = { + id: "theme1@tests.mozilla.org", + version: "1.0", + name: "Theme 1", + internalName: "classic/1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "2", + maxVersion: "2" + }] +}; + +// The selected theme +var theme2 = { + id: "theme2@tests.mozilla.org", + version: "1.0", + name: "Theme 2", + internalName: "test/1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "2", + maxVersion: "2" + }] +}; + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2"); + + writeInstallRDFForExtension(addon1, profileDir); + writeInstallRDFForExtension(addon2, profileDir); + writeInstallRDFForExtension(addon3, profileDir); + writeInstallRDFForExtension(addon4, profileDir); + writeInstallRDFForExtension(addon5, profileDir); + writeInstallRDFForExtension(addon6, profileDir); + writeInstallRDFForExtension(addon7, profileDir); + writeInstallRDFForExtension(theme1, profileDir); + writeInstallRDFForExtension(theme2, profileDir); + + // Create and configure the HTTP server. + testserver = new nsHttpServer(); + testserver.registerDirectory("/addons/", do_get_file("addons")); + testserver.registerDirectory("/data/", do_get_file("data")); + testserver.start(4444); + + // Startup the profile and setup the initial state + startupManager(); + + AddonManager.getAddonsByIDs(["addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon7@tests.mozilla.org", + "theme2@tests.mozilla.org"], function([a2, a3, a4, + a7, t2]) { + // Set up the initial state + a2.userDisabled = true; + a4.userDisabled = true; + a7.userDisabled = true; + t2.userDisabled = false; + a3.findUpdates({ + onUpdateFinished: function() { + a4.findUpdates({ + onUpdateFinished: function() { + restartManager(); + + run_test_1(); + } + }, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); + } + }, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); + }); +} + +function end_test() { + testserver.stop(do_test_finished); +} + +function run_test_1() { + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org", + "addon6@tests.mozilla.org", + "addon7@tests.mozilla.org", + "theme1@tests.mozilla.org", + "theme2@tests.mozilla.org"], function([a1, a2, a3, + a4, a5, a6, + a7, t1, t2]) { + do_check_neq(a1, null); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + do_check_false(a1.appDisabled); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a2, null); + do_check_false(a2.isActive); + do_check_true(a2.userDisabled); + do_check_false(a2.appDisabled); + do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a3, null); + do_check_true(a3.isActive); + do_check_false(a3.userDisabled); + do_check_false(a3.appDisabled); + do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a4, null); + do_check_false(a4.isActive); + do_check_true(a4.userDisabled); + do_check_false(a4.appDisabled); + do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a5, null); + do_check_false(a5.isActive); + do_check_false(a5.userDisabled); + do_check_true(a5.appDisabled); + do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a6, null); + do_check_true(a6.isActive); + do_check_false(a6.userDisabled); + do_check_false(a6.appDisabled); + do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a7, null); + do_check_false(a7.isActive); + do_check_true(a7.userDisabled); + do_check_false(a7.appDisabled); + do_check_eq(a7.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(t1, null); + do_check_false(t1.isActive); + do_check_true(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(t2, null); + do_check_true(t2.isActive); + do_check_false(t2.userDisabled); + do_check_false(t2.appDisabled); + do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE); + + // After restarting the database won't be open so lock the file for writing + restartManager(); + var dbfile = gProfD.clone(); + dbfile.append("extensions.sqlite"); + var fstream = AM_Cc["@mozilla.org/network/file-output-stream;1"]. + createInstance(AM_Ci.nsIFileOutputStream); + fstream.init(dbfile, FileUtils.MODE_TRUNCATE | FileUtils.MODE_WRONLY, FileUtils.PERMS_FILE, 0); + + // Accessing the add-ons should open and recover the database + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org", + "addon6@tests.mozilla.org", + "addon7@tests.mozilla.org", + "theme1@tests.mozilla.org", + "theme2@tests.mozilla.org"], function([a1, a2, a3, + a4, a5, a6, + a7, t1, t2]) { + // Should be correctly recovered + do_check_neq(a1, null); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + do_check_false(a1.appDisabled); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + + // Should be correctly recovered + do_check_neq(a2, null); + do_check_false(a2.isActive); + do_check_true(a2.userDisabled); + do_check_false(a2.appDisabled); + do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE); + + // The compatibility update won't be recovered but it should still be + // active for this session + do_check_neq(a3, null); + do_check_true(a3.isActive); + do_check_false(a3.userDisabled); + do_check_true(a3.appDisabled); + do_check_eq(a3.pendingOperations, AddonManager.PENDING_DISABLE); + + // The compatibility update won't be recovered and it will not have been + // able to tell that it was previously userDisabled + do_check_neq(a4, null); + do_check_false(a4.isActive); + do_check_false(a4.userDisabled); + do_check_true(a4.appDisabled); + do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a5, null); + do_check_false(a5.isActive); + do_check_false(a5.userDisabled); + do_check_true(a5.appDisabled); + do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a6, null); + do_check_true(a6.isActive); + do_check_false(a6.userDisabled); + do_check_false(a6.appDisabled); + do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a7, null); + do_check_false(a7.isActive); + do_check_true(a7.userDisabled); + do_check_false(a7.appDisabled); + do_check_eq(a7.pendingOperations, AddonManager.PENDING_NONE); + + // Should be correctly recovered + do_check_neq(t1, null); + do_check_false(t1.isActive); + do_check_true(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE); + + // Should be correctly recovered + do_check_neq(t2, null); + do_check_true(t2.isActive); + do_check_false(t2.userDisabled); + do_check_false(t2.appDisabled); + do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE); + + // Restarting will actually apply changes to extensions.ini which will + // then be put into the in-memory database when we next fail to load the + // real thing + restartManager(); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org", + "addon6@tests.mozilla.org", + "addon7@tests.mozilla.org", + "theme1@tests.mozilla.org", + "theme2@tests.mozilla.org"], function([a1, a2, a3, + a4, a5, a6, + a7, t1, t2]) { + do_check_neq(a1, null); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + do_check_false(a1.appDisabled); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a2, null); + do_check_false(a2.isActive); + do_check_true(a2.userDisabled); + do_check_false(a2.appDisabled); + do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a3, null); + do_check_false(a3.isActive); + do_check_false(a3.userDisabled); + do_check_true(a3.appDisabled); + do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a4, null); + do_check_false(a4.isActive); + do_check_false(a4.userDisabled); + do_check_true(a4.appDisabled); + do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a5, null); + do_check_false(a5.isActive); + do_check_false(a5.userDisabled); + do_check_true(a5.appDisabled); + do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a6, null); + do_check_true(a6.isActive); + do_check_false(a6.userDisabled); + do_check_false(a6.appDisabled); + do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a7, null); + do_check_false(a7.isActive); + do_check_true(a7.userDisabled); + do_check_false(a7.appDisabled); + do_check_eq(a7.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(t1, null); + do_check_false(t1.isActive); + do_check_true(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(t2, null); + do_check_true(t2.isActive); + do_check_false(t2.userDisabled); + do_check_false(t2.appDisabled); + do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE); + + fstream.close(); + end_test(); + }); + }); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_strictcompatibility.js b/toolkit/mozapps/extensions/test/xpcshell/test_strictcompatibility.js new file mode 100644 index 000000000000..be5d22eb421f --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_strictcompatibility.js @@ -0,0 +1,105 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Tests AddonManager.strictCompatibility and it's related preference, +// extensions.strictCompatibility + + +// Always compatible +var addon1 = { + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Incompatible in strict compatibility mode +var addon2 = { + id: "addon2@tests.mozilla.org", + version: "1.0", + name: "Test 2", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0.1", + maxVersion: "0.2" + }] +}; + +// Theme - always uses strict compatibility, so is always incompatible +var addon3 = { + id: "addon3@tests.mozilla.org", + version: "1.0", + name: "Test 3", + internalName: "test-theme-3", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0.1", + maxVersion: "0.2" + }] +}; + + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + + +function do_check_compat_status(aStrict, aAddonCompat, aCallback) { + do_check_eq(AddonManager.strictCompatibility, aStrict); + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org"], + function([a1, a2, a3]) { + do_check_neq(a1, null); + do_check_eq(a1.isCompatible, aAddonCompat[0]); + do_check_eq(a1.appDisabled, !aAddonCompat[0]); + + do_check_neq(a2, null); + do_check_eq(a2.isCompatible, aAddonCompat[1]); + do_check_eq(a2.appDisabled, !aAddonCompat[1]); + + do_check_neq(a3, null); + do_check_eq(a3.isCompatible, aAddonCompat[2]); + do_check_eq(a3.appDisabled, !aAddonCompat[2]); + + aCallback(); + }); +} + + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + writeInstallRDFForExtension(addon1, profileDir); + writeInstallRDFForExtension(addon2, profileDir); + writeInstallRDFForExtension(addon3, profileDir); + + startupManager(); + + // Should default to enabling strict compat. + do_check_compat_status(true, [true, false, false], run_test_1); +} + +function run_test_1() { + Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false); + do_check_compat_status(false, [true, true, false], run_test_2); +} + +function run_test_2() { + restartManager(); + do_check_compat_status(false, [true, true, false], run_test_3); +} + +function run_test_3() { + Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, true); + do_check_compat_status(true, [true, false, false], run_test_4); +} + +function run_test_4() { + restartManager(); + do_check_compat_status(true, [true, false, false], do_test_finished); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_update.js b/toolkit/mozapps/extensions/test/xpcshell/test_update.js index f39908e06b2a..92e5a41cbfbd 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_update.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_update.js @@ -8,7 +8,8 @@ const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS"; const PREF_SELECTED_LOCALE = "general.useragent.locale"; // The test extension uses an insecure update url. -Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); +Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); +Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false); // This test requires lightweight themes update to be enabled even if the app // doesn't support lightweight themes. Services.prefs.setBoolPref("lightweightThemes.update.enabled", true); @@ -235,16 +236,16 @@ function check_test_2() { function run_test_3() { AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { do_check_neq(a2, null); - do_check_false(a2.isActive); - do_check_false(a2.isCompatible); - do_check_true(a2.appDisabled); + do_check_true(a2.isActive); + do_check_true(a2.isCompatible); + do_check_false(a2.appDisabled); do_check_true(a2.isCompatibleWith("0")); a2.findUpdates({ onCompatibilityUpdateAvailable: function(addon) { do_check_true(a2.isCompatible); do_check_false(a2.appDisabled); - do_check_false(a2.isActive); + do_check_true(a2.isActive); }, onUpdateAvailable: function(addon, install) { @@ -276,11 +277,11 @@ function check_test_3() { function run_test_4() { AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) { do_check_neq(a3, null); - do_check_false(a3.isActive); - do_check_false(a3.isCompatible); - do_check_true(a3.appDisabled); + do_check_true(a3.isActive); + do_check_true(a3.isCompatible); + do_check_false(a3.appDisabled); do_check_true(a3.isCompatibleWith("5")); - do_check_false(a3.isCompatibleWith("2")); + do_check_true(a3.isCompatibleWith("2")); a3.findUpdates({ sawUpdate: false, @@ -309,18 +310,18 @@ function run_test_4() { function run_test_5() { AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) { do_check_neq(a3, null); - do_check_false(a3.isActive); - do_check_false(a3.isCompatible); - do_check_true(a3.appDisabled); + do_check_true(a3.isActive); + do_check_true(a3.isCompatible); + do_check_false(a3.appDisabled); do_check_true(a3.isCompatibleWith("5")); - do_check_false(a3.isCompatibleWith("2")); + do_check_true(a3.isCompatibleWith("2")); a3.findUpdates({ sawUpdate: false, onCompatibilityUpdateAvailable: function(addon) { - do_check_false(a3.isCompatible); - do_check_true(a3.appDisabled); - do_check_false(a3.isActive); + do_check_true(a3.isCompatible); + do_check_false(a3.appDisabled); + do_check_true(a3.isActive); this.sawUpdate = true; }, @@ -344,9 +345,9 @@ function run_test_5() { function check_test_5() { AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) { do_check_neq(a3, null); - do_check_false(a3.isActive); - do_check_false(a3.isCompatible); - do_check_true(a3.appDisabled); + do_check_true(a3.isActive); + do_check_true(a3.isCompatible); + do_check_false(a3.appDisabled); a3.uninstall(); restartManager(); @@ -609,7 +610,7 @@ function run_test_8() { case "addon3@tests.mozilla.org": do_check_eq(item_version, "1.3+"); do_check_eq(item_maxappversion, "0"); - do_check_eq(item_status, "userEnabled,incompatible"); + do_check_eq(item_status, "userEnabled"); do_check_eq(app_version, "1"); do_check_eq(update_type, "112"); break; @@ -741,7 +742,7 @@ function run_test_11() { AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) { a4.findUpdates({ onUpdateFinished: function(addon) { - do_check_false(addon.isCompatible); + do_check_true(addon.isCompatible); run_test_12(); } @@ -754,8 +755,8 @@ function run_test_12() { restartManager(); AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) { - do_check_false(a4.isActive); - do_check_false(a4.isCompatible); + do_check_true(a4.isActive); + do_check_true(a4.isCompatible); a4.uninstall(); restartManager(); @@ -784,9 +785,9 @@ function run_test_13() { AddonManager.getAddonByID("addon7@tests.mozilla.org", function(a7) { do_check_neq(a7, null); - do_check_false(a7.isActive); - do_check_false(a7.isCompatible); - do_check_true(a7.appDisabled); + do_check_true(a7.isActive); + do_check_true(a7.isCompatible); + do_check_false(a7.appDisabled); do_check_true(a7.isCompatibleWith("0")); a7.findUpdates({ diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js new file mode 100644 index 000000000000..01e3c16b4e3d --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js @@ -0,0 +1,1021 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that add-on update checks work + +const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS"; +const PREF_SELECTED_LOCALE = "general.useragent.locale"; + +// The test extension uses an insecure update url. +Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); +// This test requires lightweight themes update to be enabled even if the app +// doesn't support lightweight themes. +Services.prefs.setBoolPref("lightweightThemes.update.enabled", true); + +Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm"); + +const PARAMS = "?%REQ_VERSION%/%ITEM_ID%/%ITEM_VERSION%/%ITEM_MAXAPPVERSION%/" + + "%ITEM_STATUS%/%APP_ID%/%APP_VERSION%/%CURRENT_APP_VERSION%/" + + "%APP_OS%/%APP_ABI%/%APP_LOCALE%/%UPDATE_TYPE%"; + +var gInstallDate; + +do_load_httpd_js(); +var testserver; +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + Services.prefs.setBoolPref(PREF_MATCH_OS_LOCALE, false); + Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "fr-FR"); + Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, true); + + // Create and configure the HTTP server. + testserver = new nsHttpServer(); + testserver.registerDirectory("/data/", do_get_file("data")); + testserver.registerDirectory("/addons/", do_get_file("addons")); + testserver.start(4444); + + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:4444/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 1", + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon2@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:4444/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0", + maxVersion: "0" + }], + name: "Test Addon 2", + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon3@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:4444/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "5", + maxVersion: "5" + }], + name: "Test Addon 3", + }, profileDir); + + startupManager(); + + do_test_pending(); + run_test_1(); +} + +function end_test() { + Services.prefs.clearUserPref(PREF_EM_STRICT_COMPATIBILITY); + + testserver.stop(do_test_finished); +} + +// Verify that an update is available and can be installed. +function run_test_1() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "1.0"); + do_check_eq(a1.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DEFAULT); + do_check_eq(a1.releaseNotesURI, null); + + a1.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DEFAULT; + + prepare_test({ + "addon1@tests.mozilla.org": [ + ["onPropertyChanged", ["applyBackgroundUpdates"]] + ] + }); + a1.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE; + check_test_completed(); + + a1.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE; + + prepare_test({}, [ + "onNewInstall", + ]); + + a1.findUpdates({ + onNoCompatibilityUpdateAvailable: function(addon) { + do_throw("Should not have seen onNoCompatibilityUpdateAvailable notification"); + }, + + onUpdateAvailable: function(addon, install) { + ensure_test_completed(); + + AddonManager.getAllInstalls(function(aInstalls) { + do_check_eq(aInstalls.length, 1); + do_check_eq(aInstalls[0], install); + + do_check_eq(addon, a1); + do_check_eq(install.name, addon.name); + do_check_eq(install.version, "2.0"); + do_check_eq(install.state, AddonManager.STATE_AVAILABLE); + do_check_eq(install.existingAddon, addon); + do_check_eq(install.releaseNotesURI.spec, "http://example.com/updateInfo.xhtml"); + + // Verify that another update check returns the same AddonInstall + a1.findUpdates({ + onNoCompatibilityUpdateAvailable: function(addon) { + do_throw("Should not have seen onNoCompatibilityUpdateAvailable notification"); + }, + + onUpdateAvailable: function(newAddon, newInstall) { + AddonManager.getAllInstalls(function(aInstalls) { + do_check_eq(aInstalls.length, 1); + do_check_eq(aInstalls[0], install); + do_check_eq(newAddon, addon); + do_check_eq(newInstall, install); + + prepare_test({}, [ + "onDownloadStarted", + "onDownloadEnded", + ], check_test_1); + install.install(); + }); + }, + + onNoUpdateAvailable: function(addon) { + do_throw("Should not have seen onNoUpdateAvailable notification"); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); + }, + + onNoUpdateAvailable: function(addon) { + do_throw("Should not have seen onNoUpdateAvailable notification"); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} + +function check_test_1(install) { + ensure_test_completed(); + do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); + run_test_2(install); + return false; +} + +// Continue installing the update. +function run_test_2(install) { + // Verify that another update check returns no new update + install.existingAddon.findUpdates({ + onNoCompatibilityUpdateAvailable: function(addon) { + do_throw("Should not have seen onNoCompatibilityUpdateAvailable notification"); + }, + + onUpdateAvailable: function(addon, install) { + do_throw("Should find no available update when one is already downloading"); + }, + + onNoUpdateAvailable: function(addon) { + AddonManager.getAllInstalls(function(aInstalls) { + do_check_eq(aInstalls.length, 1); + do_check_eq(aInstalls[0], install); + + prepare_test({ + "addon1@tests.mozilla.org": [ + "onInstalling" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], check_test_2); + install.install(); + }); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); +} + +function check_test_2() { + ensure_test_completed(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(olda1) { + do_check_neq(olda1, null); + do_check_eq(olda1.version, "1.0"); + do_check_true(isExtensionInAddonsList(profileDir, olda1.id)); + + shutdownManager(); + + startupManager(); + + do_check_true(isExtensionInAddonsList(profileDir, olda1.id)); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "2.0"); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); + do_check_eq(a1.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DISABLE); + do_check_eq(a1.releaseNotesURI.spec, "http://example.com/updateInfo.xhtml"); + + a1.uninstall(); + restartManager(); + + run_test_3(); + }); + }); +} + + +// Check that an update check finds compatibility updates and applies them +function run_test_3() { + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_neq(a2, null); + do_check_false(a2.isActive); + do_check_false(a2.isCompatible); + do_check_true(a2.appDisabled); + do_check_true(a2.isCompatibleWith("0")); + + a2.findUpdates({ + onCompatibilityUpdateAvailable: function(addon) { + do_check_true(a2.isCompatible); + do_check_false(a2.appDisabled); + do_check_false(a2.isActive); + }, + + onUpdateAvailable: function(addon, install) { + do_throw("Should not have seen an available update"); + }, + + onNoUpdateAvailable: function(addon) { + do_check_eq(addon, a2); + restartManager(); + check_test_3(); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} + +function check_test_3() { + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_neq(a2, null); + do_check_true(a2.isActive); + do_check_true(a2.isCompatible); + do_check_false(a2.appDisabled); + a2.uninstall(); + + run_test_4(); + }); +} + +// Checks that we see no compatibility information when there is none. +function run_test_4() { + AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) { + do_check_neq(a3, null); + do_check_false(a3.isActive); + do_check_false(a3.isCompatible); + do_check_true(a3.appDisabled); + do_check_true(a3.isCompatibleWith("5")); + do_check_false(a3.isCompatibleWith("2")); + + a3.findUpdates({ + sawUpdate: false, + onCompatibilityUpdateAvailable: function(addon) { + do_throw("Should not have seen compatibility information"); + }, + + onNoCompatibilityUpdateAvailable: function(addon) { + this.sawUpdate = true; + }, + + onUpdateAvailable: function(addon, install) { + do_throw("Should not have seen an available update"); + }, + + onNoUpdateAvailable: function(addon) { + do_check_true(this.sawUpdate); + run_test_5(); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} + +// Checks that compatibility info for future apps are detected but don't make +// the item compatibile. +function run_test_5() { + AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) { + do_check_neq(a3, null); + do_check_false(a3.isActive); + do_check_false(a3.isCompatible); + do_check_true(a3.appDisabled); + do_check_true(a3.isCompatibleWith("5")); + do_check_false(a3.isCompatibleWith("2")); + + a3.findUpdates({ + sawUpdate: false, + onCompatibilityUpdateAvailable: function(addon) { + do_check_false(a3.isCompatible); + do_check_true(a3.appDisabled); + do_check_false(a3.isActive); + this.sawUpdate = true; + }, + + onNoCompatibilityUpdateAvailable: function(addon) { + do_throw("Should have seen some compatibility information"); + }, + + onUpdateAvailable: function(addon, install) { + do_throw("Should not have seen an available update"); + }, + + onNoUpdateAvailable: function(addon) { + do_check_true(this.sawUpdate); + restartManager(); + check_test_5(); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED, "3.0"); + }); +} + +function check_test_5() { + AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) { + do_check_neq(a3, null); + do_check_false(a3.isActive); + do_check_false(a3.isCompatible); + do_check_true(a3.appDisabled); + + a3.uninstall(); + restartManager(); + + run_test_6(); + }); +} + +// Test that background update checks work +function run_test_6() { + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:4444/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 1", + }, profileDir); + restartManager(); + + prepare_test({}, [ + "onNewInstall", + "onDownloadStarted", + "onDownloadEnded" + ], continue_test_6); + + // Fake a timer event to cause a background update and wait for the magic to + // happen + gInternalManager.notify(null); +} + +function continue_test_6(install) { + do_check_neq(install.existingAddon, null); + do_check_eq(install.existingAddon.id, "addon1@tests.mozilla.org"); + + prepare_test({ + "addon1@tests.mozilla.org": [ + "onInstalling" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], check_test_6); +} + +function check_test_6(install) { + do_check_eq(install.existingAddon.pendingUpgrade.install, install); + + restartManager(); + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "2.0"); + do_check_eq(a1.releaseNotesURI.spec, "http://example.com/updateInfo.xhtml"); + a1.uninstall(); + restartManager(); + + run_test_7(); + }); +} + +// Test that background update checks work for lightweight themes +function run_test_7() { + LightweightThemeManager.currentTheme = { + id: "1", + version: "1", + name: "Test LW Theme", + description: "A test theme", + author: "Mozilla", + homepageURL: "http://localhost:4444/data/index.html", + headerURL: "http://localhost:4444/data/header.png", + footerURL: "http://localhost:4444/data/footer.png", + previewURL: "http://localhost:4444/data/preview.png", + iconURL: "http://localhost:4444/data/icon.png", + updateURL: "http://localhost:4444/data/lwtheme.js" + }; + + // XXX The lightweight theme manager strips non-https updateURLs so hack it + // back in. + let themes = JSON.parse(Services.prefs.getCharPref("lightweightThemes.usedThemes")); + do_check_eq(themes.length, 1); + themes[0].updateURL = "http://localhost:4444/data/lwtheme.js"; + Services.prefs.setCharPref("lightweightThemes.usedThemes", JSON.stringify(themes)); + + testserver.registerPathHandler("/data/lwtheme.js", function(request, response) { + response.write(JSON.stringify({ + id: "1", + version: "2", + name: "Updated Theme", + description: "A test theme", + author: "Mozilla", + homepageURL: "http://localhost:4444/data/index2.html", + headerURL: "http://localhost:4444/data/header.png", + footerURL: "http://localhost:4444/data/footer.png", + previewURL: "http://localhost:4444/data/preview.png", + iconURL: "http://localhost:4444/data/icon2.png", + updateURL: "http://localhost:4444/data/lwtheme.js" + })); + }); + + AddonManager.getAddonByID("1@personas.mozilla.org", function(p1) { + do_check_neq(p1, null); + do_check_eq(p1.version, "1"); + do_check_eq(p1.name, "Test LW Theme"); + do_check_true(p1.isActive); + do_check_eq(p1.installDate.getTime(), p1.updateDate.getTime()); + + // 5 seconds leeway seems like a lot, but tests can run slow and really if + // this is within 5 seconds it is fine. If it is going to be wrong then it + // is likely to be hours out at least + do_check_true((Date.now() - p1.installDate.getTime()) < 5000); + + gInstallDate = p1.installDate.getTime(); + + prepare_test({ + "1@personas.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ] + }, [ + "onExternalInstall" + ], check_test_7); + + // Fake a timer event to cause a background update and wait for the magic to + // happen + gInternalManager.notify(null); + }); +} + +function check_test_7() { + AddonManager.getAddonByID("1@personas.mozilla.org", function(p1) { + do_check_neq(p1, null); + do_check_eq(p1.version, "2"); + do_check_eq(p1.name, "Updated Theme"); + do_check_eq(p1.installDate.getTime(), gInstallDate); + do_check_true(p1.installDate.getTime() < p1.updateDate.getTime()); + + // 5 seconds leeway seems like a lot, but tests can run slow and really if + // this is within 5 seconds it is fine. If it is going to be wrong then it + // is likely to be hours out at least + do_check_true((Date.now() - p1.updateDate.getTime()) < 5000); + + gInstallDate = p1.installDate.getTime(); + + run_test_8(); + }); +} + +// Verify the parameter escaping in update urls. +function run_test_8() { + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "5.0", + updateURL: "http://localhost:4444/data/param_test.rdf" + PARAMS, + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }], + name: "Test Addon 1", + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon2@tests.mozilla.org", + version: "67.0.5b1", + updateURL: "http://localhost:4444/data/param_test.rdf" + PARAMS, + targetApplications: [{ + id: "toolkit@mozilla.org", + minVersion: "0", + maxVersion: "3" + }], + name: "Test Addon 2", + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon3@tests.mozilla.org", + version: "1.3+", + updateURL: "http://localhost:4444/data/param_test.rdf" + PARAMS, + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0", + maxVersion: "0" + }, { + id: "toolkit@mozilla.org", + minVersion: "0", + maxVersion: "3" + }], + name: "Test Addon 3", + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon4@tests.mozilla.org", + version: "0.5ab6", + updateURL: "http://localhost:4444/data/param_test.rdf" + PARAMS, + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "5" + }], + name: "Test Addon 4", + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon5@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:4444/data/param_test.rdf" + PARAMS, + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 5", + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon6@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:4444/data/param_test.rdf" + PARAMS, + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 6", + }, profileDir); + + restartManager(); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + a2.userDisabled = true; + restartManager(); + + testserver.registerPathHandler("/data/param_test.rdf", function(request, response) { + do_check_neq(request.queryString, ""); + let [req_version, item_id, item_version, + item_maxappversion, item_status, + app_id, app_version, current_app_version, + app_os, app_abi, app_locale, update_type] = + [decodeURIComponent(a) for each (a in request.queryString.split("/"))]; + + do_check_eq(req_version, "2"); + + switch(item_id) { + case "addon1@tests.mozilla.org": + do_check_eq(item_version, "5.0"); + do_check_eq(item_maxappversion, "2"); + do_check_eq(item_status, "userEnabled"); + do_check_eq(app_version, "1"); + do_check_eq(update_type, "97"); + break; + case "addon2@tests.mozilla.org": + do_check_eq(item_version, "67.0.5b1"); + do_check_eq(item_maxappversion, "3"); + do_check_eq(item_status, "userDisabled"); + do_check_eq(app_version, "1"); + do_check_eq(update_type, "49"); + break; + case "addon3@tests.mozilla.org": + do_check_eq(item_version, "1.3+"); + do_check_eq(item_maxappversion, "0"); + do_check_eq(item_status, "userEnabled,incompatible"); + do_check_eq(app_version, "1"); + do_check_eq(update_type, "112"); + break; + case "addon4@tests.mozilla.org": + do_check_eq(item_version, "0.5ab6"); + do_check_eq(item_maxappversion, "5"); + do_check_eq(item_status, "userEnabled"); + do_check_eq(app_version, "2"); + do_check_eq(update_type, "98"); + break; + case "addon5@tests.mozilla.org": + do_check_eq(item_version, "1.0"); + do_check_eq(item_maxappversion, "1"); + do_check_eq(item_status, "userEnabled"); + do_check_eq(app_version, "1"); + do_check_eq(update_type, "35"); + break; + case "addon6@tests.mozilla.org": + do_check_eq(item_version, "1.0"); + do_check_eq(item_maxappversion, "1"); + do_check_eq(item_status, "userEnabled"); + do_check_eq(app_version, "1"); + do_check_eq(update_type, "99"); + break; + default: + do_throw("Update request for unexpected add-on " + item_id); + } + + do_check_eq(app_id, "xpcshell@tests.mozilla.org"); + do_check_eq(current_app_version, "1"); + do_check_eq(app_os, "XPCShell"); + do_check_eq(app_abi, "noarch-spidermonkey"); + do_check_eq(app_locale, "fr-FR"); + + request.setStatusLine(null, 500, "Server Error"); + }); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org", + "addon6@tests.mozilla.org"], + function([a1, a2, a3, a4, a5, a6]) { + let count = 6; + + function run_next_test() { + a1.uninstall(); + a2.uninstall(); + a3.uninstall(); + a4.uninstall(); + a5.uninstall(); + a6.uninstall(); + + restartManager(); + run_test_9(); + } + + let compatListener = { + onUpdateFinished: function(addon, error) { + if (--count == 0) + run_next_test(); + } + }; + + let updateListener = { + onUpdateAvailable: function(addon, update) { + // Dummy so the update checker knows we care about new versions + }, + + onUpdateFinished: function(addon, error) { + if (--count == 0) + run_next_test(); + } + }; + + a1.findUpdates(updateListener, AddonManager.UPDATE_WHEN_USER_REQUESTED); + a2.findUpdates(compatListener, AddonManager.UPDATE_WHEN_ADDON_INSTALLED); + a3.findUpdates(updateListener, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); + a4.findUpdates(updateListener, AddonManager.UPDATE_WHEN_NEW_APP_DETECTED, "2"); + a5.findUpdates(compatListener, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); + a6.findUpdates(updateListener, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); + }); + }); +} + +// Tests that if an install.rdf claims compatibility then the add-on will be +// seen as compatible regardless of what the update.rdf says. +function run_test_9() { + writeInstallRDFForExtension({ + id: "addon4@tests.mozilla.org", + version: "5.0", + updateURL: "http://localhost:4444/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0", + maxVersion: "1" + }], + name: "Test Addon 1", + }, profileDir); + + restartManager(); + + AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) { + do_check_true(a4.isActive); + do_check_true(a4.isCompatible); + + run_test_10(); + }); +} + +// Tests that a normal update check won't decrease a targetApplication's +// maxVersion. +function run_test_10() { + AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) { + a4.findUpdates({ + onUpdateFinished: function(addon) { + do_check_true(addon.isCompatible); + + run_test_11(); + } + }, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); + }); +} + +// Tests that an update check for a new application will decrease a +// targetApplication's maxVersion. +function run_test_11() { + AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) { + a4.findUpdates({ + onUpdateFinished: function(addon) { + do_check_false(addon.isCompatible); + + run_test_12(); + } + }, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); + }); +} + +// Check that the decreased maxVersion applied and disables the add-on +function run_test_12() { + restartManager(); + + AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) { + do_check_false(a4.isActive); + do_check_false(a4.isCompatible); + + a4.uninstall(); + restartManager(); + + run_test_13(); + }); +} + +// Tests that no compatibility update is passed to the listener when there is +// compatibility info for the current version of the app but not for the +// version of the app that the caller requested an update check for. +function run_test_13() { + // Not initially compatible but the update check will make it compatible + writeInstallRDFForExtension({ + id: "addon7@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:4444/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0", + maxVersion: "0" + }], + name: "Test Addon 7", + }, profileDir); + restartManager(); + + AddonManager.getAddonByID("addon7@tests.mozilla.org", function(a7) { + do_check_neq(a7, null); + do_check_false(a7.isActive); + do_check_false(a7.isCompatible); + do_check_true(a7.appDisabled); + do_check_true(a7.isCompatibleWith("0")); + + a7.findUpdates({ + sawUpdate: false, + onCompatibilityUpdateAvailable: function(addon) { + do_throw("Should have not have seen compatibility information"); + }, + + onUpdateAvailable: function(addon, install) { + do_throw("Should not have seen an available update"); + }, + + onUpdateFinished: function(addon) { + do_check_true(addon.isCompatible); + restartManager(); + check_test_13(); + } + }, AddonManager.UPDATE_WHEN_NEW_APP_DETECTED, "3.0"); + }); +} + +function check_test_13() { + AddonManager.getAddonByID("addon7@tests.mozilla.org", function(a7) { + do_check_neq(a7, null); + do_check_true(a7.isActive); + do_check_true(a7.isCompatible); + do_check_false(a7.appDisabled); + + a7.uninstall(); + restartManager(); + + run_test_14(); + }); +} + +// Test that background update checks doesn't update an add-on that isn't +// allowed to update automatically. +function run_test_14() { + // Have an add-on there that will be updated so we see some events from it + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:4444/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 1", + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon8@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:4444/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 8", + }, profileDir); + restartManager(); + + AddonManager.getAddonByID("addon8@tests.mozilla.org", function(a8) { + a8.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE; + + // The background update check will find updates for both add-ons but only + // proceed to install one of them. + AddonManager.addInstallListener({ + onNewInstall: function(aInstall) { + if (aInstall.existingAddon.id != "addon1@tests.mozilla.org" && + aInstall.existingAddon.id != "addon8@tests.mozilla.org") + do_throw("Saw unexpected onNewInstall for " + aInstall.existingAddon.id); + }, + + onDownloadStarted: function(aInstall) { + do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); + }, + + onDownloadEnded: function(aInstall) { + do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); + }, + + onDownloadFailed: function(aInstall) { + do_throw("Should not have seen onDownloadFailed event"); + }, + + onDownloadCancelled: function(aInstall) { + do_throw("Should not have seen onDownloadCancelled event"); + }, + + onInstallStarted: function(aInstall) { + do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); + }, + + onInstallEnded: function(aInstall) { + do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); + check_test_14(aInstall); + }, + + onInstallFailed: function(aInstall) { + do_throw("Should not have seen onInstallFailed event"); + }, + + onInstallCancelled: function(aInstall) { + do_throw("Should not have seen onInstallCancelled event"); + }, + }); + + // Fake a timer event + gInternalManager.notify(null); + }); +} + +function check_test_14(install) { + do_check_eq(install.existingAddon.pendingUpgrade.install, install); + + restartManager(); + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon8@tests.mozilla.org"], function([a1, a8]) { + do_check_neq(a1, null); + do_check_eq(a1.version, "2.0"); + a1.uninstall(); + + do_check_neq(a8, null); + do_check_eq(a8.version, "1.0"); + a8.uninstall(); + + restartManager(); + + run_test_15(); + }); +} + +// Test that background update checks doesn't update an add-on that is +// pending uninstall +function run_test_15() { + // Have an add-on there that will be updated so we see some events from it + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:4444/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 1", + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon8@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:4444/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 8", + }, profileDir); + restartManager(); + + AddonManager.getAddonByID("addon8@tests.mozilla.org", function(a8) { + a8.uninstall(); + do_check_false(hasFlag(a8.permissions, AddonManager.PERM_CAN_UPGRADE)); + + // The background update check will find updates for both add-ons but only + // proceed to install one of them. + AddonManager.addInstallListener({ + onNewInstall: function(aInstall) { + if (aInstall.existingAddon.id != "addon1@tests.mozilla.org" && + aInstall.existingAddon.id != "addon8@tests.mozilla.org") + do_throw("Saw unexpected onNewInstall for " + aInstall.existingAddon.id); + }, + + onDownloadStarted: function(aInstall) { + do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); + }, + + onDownloadEnded: function(aInstall) { + do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); + }, + + onDownloadFailed: function(aInstall) { + do_throw("Should not have seen onDownloadFailed event"); + }, + + onDownloadCancelled: function(aInstall) { + do_throw("Should not have seen onDownloadCancelled event"); + }, + + onInstallStarted: function(aInstall) { + do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); + }, + + onInstallEnded: function(aInstall) { + do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org"); + check_test_15(aInstall); + }, + + onInstallFailed: function(aInstall) { + do_throw("Should not have seen onInstallFailed event"); + }, + + onInstallCancelled: function(aInstall) { + do_throw("Should not have seen onInstallCancelled event"); + }, + }); + + // Fake a timer event + gInternalManager.notify(null); + }); +} + +function check_test_15(aInstall) { + restartManager(); + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon8@tests.mozilla.org"], function([a1, a8]) { + do_check_neq(a1, null); + do_check_eq(a1.version, "2.0"); + a1.uninstall(); + + do_check_eq(a8, null); + + restartManager(); + + end_test(); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_upgrade.js b/toolkit/mozapps/extensions/test/xpcshell/test_upgrade.js index 461d6528b242..0bf8a6cd62cc 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_upgrade.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_upgrade.js @@ -2,7 +2,10 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -// This verifies that app upgrades produce the expected behaviours. +// This verifies that app upgrades produce the expected behaviours, +// with strict compatibility checking disabled. + +Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false); // Enable loading extensions from the application scope Services.prefs.setIntPref("extensions.enabledScopes", @@ -21,7 +24,7 @@ var gInstallTime = Date.now(); function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); - // Will be enabled in the first version and disabled in subsequent versions + // Will be compatible in the first version and incompatible in subsequent versions writeInstallRDFForExtension({ id: "addon1@tests.mozilla.org", version: "1.0", @@ -52,7 +55,7 @@ function run_test() { ] }, profileDir); - // Will be disabled in the first version and enabled in the second. + // Will be incompatible in the first version and enabled in the second. writeInstallRDFForExtension({ id: "addon3@tests.mozilla.org", version: "1.0", @@ -64,7 +67,7 @@ function run_test() { name: "Test Addon 3", }, profileDir); - // Will be enabled in both versions but will change version in between + // Will be compatible in both versions but will change version in between var dest = writeInstallRDFForExtension({ id: "addon4@tests.mozilla.org", version: "1.0", @@ -110,7 +113,7 @@ function run_test_1() { do_check_true(isExtensionInAddonsList(profileDir, a2.id)); do_check_neq(a3, null); - do_check_false(isExtensionInAddonsList(profileDir, a3.id)); + do_check_true(isExtensionInAddonsList(profileDir, a3.id)); do_check_neq(a4, null); do_check_true(isExtensionInAddonsList(globalDir, a4.id)); @@ -120,7 +123,7 @@ function run_test_1() { }); } -// Test that upgrading the application disables now incompatible add-ons +// Test that upgrading the application doesn't disable now incompatible add-ons function run_test_2() { // Upgrade the extension var dest = writeInstallRDFForExtension({ @@ -143,7 +146,7 @@ function run_test_2() { function([a1, a2, a3, a4]) { do_check_neq(a1, null); - do_check_false(isExtensionInAddonsList(profileDir, a1.id)); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); do_check_neq(a2, null); do_check_true(isExtensionInAddonsList(profileDir, a2.id)); @@ -188,7 +191,7 @@ function run_test_3() { function([a1, a2, a3, a4]) { do_check_neq(a1, null); - do_check_false(isExtensionInAddonsList(profileDir, a1.id)); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); do_check_neq(a2, null); do_check_true(isExtensionInAddonsList(profileDir, a2.id)); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_upgrade_strictcompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_upgrade_strictcompat.js new file mode 100644 index 000000000000..0d5ad1c49fff --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_upgrade_strictcompat.js @@ -0,0 +1,211 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that app upgrades produce the expected behaviours, +// with strict compatibility checking enabled. + +// Enable loading extensions from the application scope +Services.prefs.setIntPref("extensions.enabledScopes", + AddonManager.SCOPE_PROFILE + + AddonManager.SCOPE_APPLICATION); + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +const globalDir = Services.dirsvc.get("XCurProcD", AM_Ci.nsILocalFile); +globalDir.append("extensions"); + +var gGlobalExisted = globalDir.exists(); +var gInstallTime = Date.now(); + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + // Will be enabled in the first version and disabled in subsequent versions + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 1", + targetPlatforms: [ + "XPCShell", + "WINNT_x86", + ] + }, profileDir); + + // Works in all tested versions + writeInstallRDFForExtension({ + id: "addon2@tests.mozilla.org", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }], + name: "Test Addon 2", + targetPlatforms: [ + "XPCShell_noarch-spidermonkey" + ] + }, profileDir); + + // Will be disabled in the first version and enabled in the second. + writeInstallRDFForExtension({ + id: "addon3@tests.mozilla.org", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "2", + maxVersion: "2" + }], + name: "Test Addon 3", + }, profileDir); + + // Will be enabled in both versions but will change version in between + var dest = writeInstallRDFForExtension({ + id: "addon4@tests.mozilla.org", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 4", + }, globalDir); + setExtensionModifiedTime(dest, gInstallTime); + + do_test_pending(); + + Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, true); + + run_test_1(); +} + +function end_test() { + if (!gGlobalExisted) { + globalDir.remove(true); + } + else { + globalDir.append(do_get_expected_addon_name("addon4@tests.mozilla.org")); + globalDir.remove(true); + } + + Services.prefs.clearUserPref(PREF_EM_STRICT_COMPATIBILITY); + + do_test_finished(); +} + +// Test that the test extensions are all installed +function run_test_1() { + startupManager(); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org"], + function([a1, a2, a3, a4]) { + + do_check_neq(a1, null); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); + + do_check_neq(a2, null); + do_check_true(isExtensionInAddonsList(profileDir, a2.id)); + + do_check_neq(a3, null); + do_check_false(isExtensionInAddonsList(profileDir, a3.id)); + + do_check_neq(a4, null); + do_check_true(isExtensionInAddonsList(globalDir, a4.id)); + do_check_eq(a4.version, "1.0"); + + run_test_2(); + }); +} + +// Test that upgrading the application disables now incompatible add-ons +function run_test_2() { + // Upgrade the extension + var dest = writeInstallRDFForExtension({ + id: "addon4@tests.mozilla.org", + version: "2.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "2", + maxVersion: "2" + }], + name: "Test Addon 4", + }, globalDir); + setExtensionModifiedTime(dest, gInstallTime); + + restartManager("2"); + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org"], + function([a1, a2, a3, a4]) { + + do_check_neq(a1, null); + do_check_false(isExtensionInAddonsList(profileDir, a1.id)); + + do_check_neq(a2, null); + do_check_true(isExtensionInAddonsList(profileDir, a2.id)); + + do_check_neq(a3, null); + do_check_true(isExtensionInAddonsList(profileDir, a3.id)); + + do_check_neq(a4, null); + do_check_true(isExtensionInAddonsList(globalDir, a4.id)); + do_check_eq(a4.version, "2.0"); + + run_test_3(); + }); +} + +// Test that nothing changes when only the build ID changes. +function run_test_3() { + // Upgrade the extension + var dest = writeInstallRDFForExtension({ + id: "addon4@tests.mozilla.org", + version: "3.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "3", + maxVersion: "3" + }], + name: "Test Addon 4", + }, globalDir); + setExtensionModifiedTime(dest, gInstallTime); + + // Simulates a simple Build ID change, the platform deletes extensions.ini + // whenever the application is changed. + var file = gProfD.clone(); + file.append("extensions.ini"); + file.remove(true); + restartManager(); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org"], + function([a1, a2, a3, a4]) { + + do_check_neq(a1, null); + do_check_false(isExtensionInAddonsList(profileDir, a1.id)); + + do_check_neq(a2, null); + do_check_true(isExtensionInAddonsList(profileDir, a2.id)); + + do_check_neq(a3, null); + do_check_true(isExtensionInAddonsList(profileDir, a3.id)); + + do_check_neq(a4, null); + do_check_true(isExtensionInAddonsList(globalDir, a4.id)); + do_check_eq(a4.version, "2.0"); + + end_test(); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini b/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini index 9266062b5d7c..245c44a6caee 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini +++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini @@ -70,12 +70,18 @@ skip-if = os == "android" [test_bug470377_1.js] # Bug 676992: test consistently hangs on Android skip-if = os == "android" +[test_bug470377_1_strictcompat.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" [test_bug470377_2.js] # Bug 676992: test consistently hangs on Android skip-if = os == "android" [test_bug470377_3.js] # Bug 676992: test consistently hangs on Android skip-if = os == "android" +[test_bug470377_3_strictcompat.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" [test_bug470377_4.js] # Bug 676992: test consistently hangs on Android skip-if = os == "android" @@ -121,6 +127,7 @@ fail-if = os == "android" [test_cacheflush.js] [test_checkcompatibility.js] [test_corrupt.js] +[test_corrupt_strictcompat.js] [test_dictionary.js] [test_disable.js] [test_distribution.js] @@ -153,8 +160,12 @@ skip-if = os == "android" [test_install.js] # Bug 676992: test consistently hangs on Android skip-if = os == "android" +[test_install_strictcompat.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" [test_locale.js] [test_locked.js] +[test_locked_strictcompat.js] [test_manifest.js] [test_migrate1.js] [test_migrate2.js] @@ -170,6 +181,7 @@ fail-if = os == "android" [test_startup.js] # Bug 676992: test consistently fails on Android fail-if = os == "android" +[test_strictcompatibility.js] [test_targetPlatforms.js] [test_theme.js] # Bug 676992: test consistently fails on Android @@ -179,6 +191,9 @@ fail-if = os == "android" [test_update.js] # Bug 676992: test consistently hangs on Android skip-if = os == "android" +[test_update_strictcompat.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" [test_updatecheck.js] # Bug 676992: test consistently hangs on Android skip-if = os == "android" @@ -188,4 +203,6 @@ skip-if = os == "android" [test_upgrade.js] # Bug 676992: test consistently hangs on Android skip-if = os == "android" - +[test_upgrade_strictcompat.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" diff --git a/toolkit/mozapps/update/test/chrome/utils.js b/toolkit/mozapps/update/test/chrome/utils.js index 343d39499719..edbb262c8797 100644 --- a/toolkit/mozapps/update/test/chrome/utils.js +++ b/toolkit/mozapps/update/test/chrome/utils.js @@ -816,6 +816,7 @@ function setupPrefs() { Services.prefs.setIntPref(PREF_APP_UPDATE_IDLETIME, 0); Services.prefs.setIntPref(PREF_APP_UPDATE_PROMPTWAITTIME, 0); + Services.prefs.setBoolPref(PREF_EXTENSIONS_STRICT_COMPAT, true); } /** @@ -913,6 +914,10 @@ function resetPrefs() { } catch(e) { } + + if (Services.prefs.prefHasUserValue(PREF_EXTENSIONS_STRICT_COMPAT)) { + Services.prefs.clearUserPref(PREF_EXTENSIONS_STRICT_COMPAT); + } } /** diff --git a/toolkit/mozapps/update/test/shared.js b/toolkit/mozapps/update/test/shared.js index 88365801cb7f..50b3e8c08b7a 100644 --- a/toolkit/mozapps/update/test/shared.js +++ b/toolkit/mozapps/update/test/shared.js @@ -73,6 +73,7 @@ const PREF_DISTRIBUTION_ID = "distribution.id"; const PREF_DISTRIBUTION_VERSION = "distribution.version"; const PREF_EXTENSIONS_UPDATE_URL = "extensions.update.url"; +const PREF_EXTENSIONS_STRICT_COMPAT = "extensions.strictCompatibility"; const NS_APP_PROFILE_DIR_STARTUP = "ProfDS"; const NS_APP_USER_PROFILE_50_DIR = "ProfD";