michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: * http://creativecommons.org/publicdomain/zero/1.0/ michael@0: */ michael@0: michael@0: // Test the compatibility dialog that displays during startup when the browser michael@0: // version changes. michael@0: michael@0: const URI_EXTENSION_UPDATE_DIALOG = "chrome://mozapps/content/extensions/update.xul"; michael@0: michael@0: const PREF_GETADDONS_BYIDS = "extensions.getAddons.get.url"; michael@0: const PREF_MIN_PLATFORM_COMPAT = "extensions.minCompatiblePlatformVersion"; michael@0: michael@0: Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true); michael@0: // avoid the 'leaked window property' check michael@0: let scope = {}; michael@0: Components.utils.import("resource://gre/modules/TelemetryPing.jsm", scope); michael@0: let TelemetryPing = scope.TelemetryPing; michael@0: michael@0: /** michael@0: * Test add-ons: michael@0: * michael@0: * Addon minVersion maxVersion Notes michael@0: * addon1 0 * michael@0: * addon2 0 0 michael@0: * addon3 0 0 michael@0: * addon4 1 * michael@0: * addon5 0 0 Made compatible by update check michael@0: * addon6 0 0 Made compatible by update check michael@0: * addon7 0 0 Has a broken update available michael@0: * addon8 0 0 Has an update available michael@0: * addon9 0 0 Has an update available michael@0: */ michael@0: michael@0: function test() { michael@0: requestLongerTimeout(2); michael@0: waitForExplicitFinish(); michael@0: michael@0: run_next_test(); michael@0: } michael@0: michael@0: function end_test() { michael@0: // Test generates a lot of available installs so just cancel them all michael@0: AddonManager.getAllInstalls(function(aInstalls) { michael@0: for (let install of aInstalls) michael@0: install.cancel(); michael@0: michael@0: finish(); michael@0: }); michael@0: } michael@0: michael@0: function install_test_addons(aCallback) { michael@0: var installs = []; michael@0: michael@0: // Use a blank update URL michael@0: Services.prefs.setCharPref(PREF_UPDATEURL, TESTROOT + "missing.rdf"); michael@0: michael@0: let names = ["browser_bug557956_1", michael@0: "browser_bug557956_2", michael@0: "browser_bug557956_3", michael@0: "browser_bug557956_4", michael@0: "browser_bug557956_5", michael@0: "browser_bug557956_6", michael@0: "browser_bug557956_7", michael@0: "browser_bug557956_8_1", michael@0: "browser_bug557956_9_1", michael@0: "browser_bug557956_10"]; michael@0: for (let name of names) { michael@0: AddonManager.getInstallForURL(TESTROOT + "addons/" + name + ".xpi", function(aInstall) { michael@0: installs.push(aInstall); michael@0: }, "application/x-xpinstall"); michael@0: } michael@0: michael@0: var listener = { michael@0: installCount: 0, michael@0: michael@0: onInstallEnded: function() { michael@0: this.installCount++; michael@0: if (this.installCount == installs.length) { michael@0: // Switch to the test update URL michael@0: Services.prefs.setCharPref(PREF_UPDATEURL, TESTROOT + "browser_bug557956.rdf"); michael@0: michael@0: aCallback(); michael@0: } michael@0: } michael@0: }; michael@0: michael@0: for (let install of installs) { michael@0: install.addListener(listener); michael@0: install.install(); michael@0: } michael@0: } michael@0: michael@0: function uninstall_test_addons(aCallback) { michael@0: AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", michael@0: "addon2@tests.mozilla.org", michael@0: "addon3@tests.mozilla.org", michael@0: "addon4@tests.mozilla.org", michael@0: "addon5@tests.mozilla.org", michael@0: "addon6@tests.mozilla.org", michael@0: "addon7@tests.mozilla.org", michael@0: "addon8@tests.mozilla.org", michael@0: "addon9@tests.mozilla.org", michael@0: "addon10@tests.mozilla.org"], michael@0: function(aAddons) { michael@0: for (let addon of aAddons) { michael@0: if (addon) michael@0: addon.uninstall(); michael@0: } michael@0: aCallback(); michael@0: }); michael@0: } michael@0: michael@0: function open_compatibility_window(aInactiveAddonIds, aCallback) { michael@0: // This will reset the longer timeout multiplier to 2 which will give each michael@0: // test that calls open_compatibility_window a minimum of 60 seconds to michael@0: // complete. michael@0: requestLongerTimeout(2); michael@0: michael@0: var variant = Cc["@mozilla.org/variant;1"]. michael@0: createInstance(Ci.nsIWritableVariant); michael@0: variant.setFromVariant(aInactiveAddonIds); michael@0: michael@0: // Cannot be modal as we want to interract with it, shouldn't cause problems michael@0: // with testing though. michael@0: var features = "chrome,centerscreen,dialog,titlebar"; michael@0: var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. michael@0: getService(Ci.nsIWindowWatcher); michael@0: var win = ww.openWindow(null, URI_EXTENSION_UPDATE_DIALOG, "", features, variant); michael@0: michael@0: win.addEventListener("load", function() { michael@0: win.removeEventListener("load", arguments.callee, false); michael@0: michael@0: info("Compatibility dialog opened"); michael@0: michael@0: function page_shown(aEvent) { michael@0: if (aEvent.target.pageid) michael@0: info("Page " + aEvent.target.pageid + " shown"); michael@0: } michael@0: michael@0: win.addEventListener("pageshow", page_shown, false); michael@0: win.addEventListener("unload", function() { michael@0: win.removeEventListener("unload", arguments.callee, false); michael@0: win.removeEventListener("pageshow", page_shown, false); michael@0: info("Compatibility dialog closed"); michael@0: }, false); michael@0: michael@0: aCallback(win); michael@0: }, false); michael@0: } michael@0: michael@0: function wait_for_window_close(aWindow, aCallback) { michael@0: aWindow.addEventListener("unload", function() { michael@0: aWindow.removeEventListener("unload", arguments.callee, false); michael@0: aCallback(); michael@0: }, false); michael@0: } michael@0: michael@0: function wait_for_page(aWindow, aPageId, aCallback) { michael@0: var page = aWindow.document.getElementById(aPageId); michael@0: page.addEventListener("pageshow", function() { michael@0: page.removeEventListener("pageshow", arguments.callee, false); michael@0: executeSoon(function() { michael@0: aCallback(aWindow); michael@0: }); michael@0: }, false); michael@0: } michael@0: michael@0: function get_list_names(aList) { michael@0: var items = []; michael@0: for (let listItem of aList.childNodes) michael@0: items.push(listItem.label); michael@0: items.sort(); michael@0: return items; michael@0: } michael@0: michael@0: function check_telemetry({disabled, metaenabled, metadisabled, upgraded, failed, declined}) { michael@0: let ping = TelemetryPing.getPayload(); michael@0: // info(JSON.stringify(ping)); michael@0: let am = ping.simpleMeasurements.addonManager; michael@0: if (disabled !== undefined) michael@0: is(am.appUpdate_disabled, disabled, disabled + " add-ons disabled by version change"); michael@0: if (metaenabled !== undefined) michael@0: is(am.appUpdate_metadata_enabled, metaenabled, metaenabled + " add-ons enabled by metadata"); michael@0: if (metadisabled !== undefined) michael@0: is(am.appUpdate_metadata_disabled, metadisabled, metadisabled + " add-ons disabled by metadata"); michael@0: if (upgraded !== undefined) michael@0: is(am.appUpdate_upgraded, upgraded, upgraded + " add-ons upgraded"); michael@0: if (failed !== undefined) michael@0: is(am.appUpdate_upgradeFailed, failed, failed + " upgrades failed"); michael@0: if (declined !== undefined) michael@0: is(am.appUpdate_upgradeDeclined, declined, declined + " upgrades declined"); michael@0: } michael@0: michael@0: // Tests that the right add-ons show up in the mismatch dialog and updates can michael@0: // be installed michael@0: add_test(function() { michael@0: install_test_addons(function() { michael@0: // These add-ons were inactive in the old application michael@0: var inactiveAddonIds = [ michael@0: "addon2@tests.mozilla.org", michael@0: "addon4@tests.mozilla.org", michael@0: "addon5@tests.mozilla.org", michael@0: "addon10@tests.mozilla.org" michael@0: ]; michael@0: michael@0: AddonManager.getAddonsByIDs(["addon5@tests.mozilla.org", michael@0: "addon6@tests.mozilla.org"], michael@0: function([a5, a6]) { michael@0: // Check starting (pre-update) conditions michael@0: ok(!a5.isCompatible, "addon5 should not be compatible"); michael@0: ok(!a6.isCompatible, "addon6 should not be compatible"); michael@0: michael@0: open_compatibility_window(inactiveAddonIds, function(aWindow) { michael@0: var doc = aWindow.document; michael@0: wait_for_page(aWindow, "mismatch", function(aWindow) { michael@0: var items = get_list_names(doc.getElementById("mismatch.incompatible")); michael@0: // Check that compatibility updates from individual add-on update checks were applied. michael@0: is(items.length, 4, "Should have seen 4 still incompatible items"); michael@0: is(items[0], "Addon3 1.0", "Should have seen addon3 still incompatible"); michael@0: is(items[1], "Addon7 1.0", "Should have seen addon7 still incompatible"); michael@0: is(items[2], "Addon8 1.0", "Should have seen addon8 still incompatible"); michael@0: is(items[3], "Addon9 1.0", "Should have seen addon9 still incompatible"); michael@0: michael@0: ok(a5.isCompatible, "addon5 should be compatible"); michael@0: ok(a6.isCompatible, "addon6 should be compatible"); michael@0: michael@0: var button = doc.documentElement.getButton("next"); michael@0: EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); michael@0: michael@0: wait_for_page(aWindow, "found", function(aWindow) { michael@0: ok(doc.getElementById("xpinstallDisabledAlert").hidden, michael@0: "Install should be allowed"); michael@0: michael@0: var list = doc.getElementById("found.updates"); michael@0: var items = get_list_names(list); michael@0: is(items.length, 3, "Should have seen 3 updates available"); michael@0: is(items[0], "Addon7 2.0", "Should have seen update for addon7"); michael@0: is(items[1], "Addon8 2.0", "Should have seen update for addon8"); michael@0: is(items[2], "Addon9 2.0", "Should have seen update for addon9"); michael@0: michael@0: ok(!doc.documentElement.getButton("next").disabled, michael@0: "Next button should be enabled"); michael@0: michael@0: // Uncheck all michael@0: for (let listItem of list.childNodes) michael@0: EventUtils.synthesizeMouse(listItem, 2, 2, { }, aWindow); michael@0: michael@0: ok(doc.documentElement.getButton("next").disabled, michael@0: "Next button should not be enabled"); michael@0: michael@0: // Check the ones we want to install michael@0: for (let listItem of list.childNodes) { michael@0: if (listItem.label != "Addon7 2.0") michael@0: EventUtils.synthesizeMouse(listItem, 2, 2, { }, aWindow); michael@0: } michael@0: michael@0: var button = doc.documentElement.getButton("next"); michael@0: EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); michael@0: michael@0: wait_for_page(aWindow, "finished", function(aWindow) { michael@0: var button = doc.documentElement.getButton("finish"); michael@0: ok(!button.hidden, "Finish button should not be hidden"); michael@0: ok(!button.disabled, "Finish button should not be disabled"); michael@0: EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); michael@0: michael@0: wait_for_window_close(aWindow, function() { michael@0: AddonManager.getAddonsByIDs(["addon8@tests.mozilla.org", michael@0: "addon9@tests.mozilla.org"], michael@0: function([a8, a9]) { michael@0: is(a8.version, "2.0", "addon8 should have updated"); michael@0: is(a9.version, "2.0", "addon9 should have updated"); michael@0: michael@0: check_telemetry({disabled: 4, metaenabled: 2, metadisabled: 0, michael@0: upgraded: 2, failed: 0, declined: 1}); michael@0: michael@0: uninstall_test_addons(run_next_test); michael@0: }); michael@0: }); michael@0: }); michael@0: }); michael@0: }); michael@0: }); michael@0: }); michael@0: }); michael@0: }); michael@0: michael@0: // Tests that the install failures show the install failed page and disabling michael@0: // xpinstall shows the right UI. michael@0: add_test(function() { michael@0: install_test_addons(function() { michael@0: // These add-ons were inactive in the old application michael@0: var inactiveAddonIds = [ michael@0: "addon2@tests.mozilla.org", michael@0: "addon4@tests.mozilla.org", michael@0: "addon5@tests.mozilla.org", michael@0: "addon10@tests.mozilla.org" michael@0: ]; michael@0: michael@0: Services.prefs.setBoolPref("xpinstall.enabled", false); michael@0: michael@0: open_compatibility_window(inactiveAddonIds, function(aWindow) { michael@0: var doc = aWindow.document; michael@0: wait_for_page(aWindow, "mismatch", function(aWindow) { michael@0: var items = get_list_names(doc.getElementById("mismatch.incompatible")); michael@0: is(items.length, 4, "Should have seen 4 still incompatible items"); michael@0: is(items[0], "Addon3 1.0", "Should have seen addon3 still incompatible"); michael@0: is(items[1], "Addon7 1.0", "Should have seen addon7 still incompatible"); michael@0: is(items[2], "Addon8 1.0", "Should have seen addon8 still incompatible"); michael@0: is(items[3], "Addon9 1.0", "Should have seen addon9 still incompatible"); michael@0: michael@0: // Check that compatibility updates were applied. michael@0: AddonManager.getAddonsByIDs(["addon5@tests.mozilla.org", michael@0: "addon6@tests.mozilla.org"], michael@0: function([a5, a6]) { michael@0: ok(a5.isCompatible, "addon5 should be compatible"); michael@0: ok(a6.isCompatible, "addon6 should be compatible"); michael@0: michael@0: var button = doc.documentElement.getButton("next"); michael@0: EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); michael@0: michael@0: wait_for_page(aWindow, "found", function(aWindow) { michael@0: ok(!doc.getElementById("xpinstallDisabledAlert").hidden, michael@0: "Install should not be allowed"); michael@0: michael@0: ok(doc.documentElement.getButton("next").disabled, michael@0: "Next button should be disabled"); michael@0: michael@0: var checkbox = doc.getElementById("enableXPInstall"); michael@0: EventUtils.synthesizeMouse(checkbox, 2, 2, { }, aWindow); michael@0: michael@0: ok(!doc.documentElement.getButton("next").disabled, michael@0: "Next button should be enabled"); michael@0: michael@0: var list = doc.getElementById("found.updates"); michael@0: var items = get_list_names(list); michael@0: is(items.length, 3, "Should have seen 3 updates available"); michael@0: is(items[0], "Addon7 2.0", "Should have seen update for addon7"); michael@0: is(items[1], "Addon8 2.0", "Should have seen update for addon8"); michael@0: is(items[2], "Addon9 2.0", "Should have seen update for addon9"); michael@0: michael@0: // Unheck the ones we don't want to install michael@0: for (let listItem of list.childNodes) { michael@0: if (listItem.label != "Addon7 2.0") michael@0: EventUtils.synthesizeMouse(listItem, 2, 2, { }, aWindow); michael@0: } michael@0: michael@0: var button = doc.documentElement.getButton("next"); michael@0: EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); michael@0: michael@0: wait_for_page(aWindow, "installerrors", function(aWindow) { michael@0: var button = doc.documentElement.getButton("finish"); michael@0: ok(!button.hidden, "Finish button should not be hidden"); michael@0: ok(!button.disabled, "Finish button should not be disabled"); michael@0: michael@0: wait_for_window_close(aWindow, function() { michael@0: uninstall_test_addons(run_next_test); michael@0: }); michael@0: michael@0: check_telemetry({disabled: 4, metaenabled: 2, metadisabled: 0, michael@0: upgraded: 0, failed: 1, declined: 2}); michael@0: michael@0: EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); michael@0: }); michael@0: }); michael@0: }); michael@0: }); michael@0: }); michael@0: }); michael@0: }); michael@0: michael@0: // Tests that no add-ons show up in the mismatch dialog when they are all disabled michael@0: add_test(function() { michael@0: install_test_addons(function() { michael@0: AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", michael@0: "addon2@tests.mozilla.org", michael@0: "addon3@tests.mozilla.org", michael@0: "addon4@tests.mozilla.org", michael@0: "addon5@tests.mozilla.org", michael@0: "addon6@tests.mozilla.org", michael@0: "addon7@tests.mozilla.org", michael@0: "addon8@tests.mozilla.org", michael@0: "addon9@tests.mozilla.org", michael@0: "addon10@tests.mozilla.org"], michael@0: function(aAddons) { michael@0: for (let addon of aAddons) michael@0: addon.userDisabled = true; michael@0: michael@0: // These add-ons were inactive in the old application michael@0: var inactiveAddonIds = [ michael@0: "addon1@tests.mozilla.org", michael@0: "addon2@tests.mozilla.org", michael@0: "addon3@tests.mozilla.org", michael@0: "addon4@tests.mozilla.org", michael@0: "addon5@tests.mozilla.org", michael@0: "addon6@tests.mozilla.org", michael@0: "addon7@tests.mozilla.org", michael@0: "addon8@tests.mozilla.org", michael@0: "addon9@tests.mozilla.org", michael@0: "addon10@tests.mozilla.org" michael@0: ]; michael@0: michael@0: open_compatibility_window(inactiveAddonIds, function(aWindow) { michael@0: // Should close immediately on its own michael@0: wait_for_window_close(aWindow, function() { michael@0: uninstall_test_addons(run_next_test); michael@0: }); michael@0: }); michael@0: }); michael@0: }); michael@0: }); michael@0: michael@0: // Tests that the right UI shows for when no updates are available michael@0: add_test(function() { michael@0: install_test_addons(function() { michael@0: AddonManager.getAddonsByIDs(["addon7@tests.mozilla.org", michael@0: "addon8@tests.mozilla.org", michael@0: "addon9@tests.mozilla.org", michael@0: "addon10@tests.mozilla.org"], michael@0: function(aAddons) { michael@0: for (let addon of aAddons) michael@0: addon.uninstall(); michael@0: michael@0: // These add-ons were inactive in the old application michael@0: var inactiveAddonIds = [ michael@0: "addon2@tests.mozilla.org", michael@0: "addon4@tests.mozilla.org", michael@0: "addon5@tests.mozilla.org" michael@0: ]; michael@0: michael@0: open_compatibility_window(inactiveAddonIds, function(aWindow) { michael@0: var doc = aWindow.document; michael@0: wait_for_page(aWindow, "mismatch", function(aWindow) { michael@0: var items = get_list_names(doc.getElementById("mismatch.incompatible")); michael@0: is(items.length, 1, "Should have seen 1 still incompatible items"); michael@0: is(items[0], "Addon3 1.0", "Should have seen addon3 still incompatible"); michael@0: michael@0: var button = doc.documentElement.getButton("next"); michael@0: EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); michael@0: michael@0: wait_for_page(aWindow, "noupdates", function(aWindow) { michael@0: var button = doc.documentElement.getButton("finish"); michael@0: ok(!button.hidden, "Finish button should not be hidden"); michael@0: ok(!button.disabled, "Finish button should not be disabled"); michael@0: michael@0: wait_for_window_close(aWindow, function() { michael@0: uninstall_test_addons(run_next_test); michael@0: }); michael@0: michael@0: EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); michael@0: }); michael@0: }); michael@0: }); michael@0: }); michael@0: }); michael@0: }); michael@0: michael@0: // Tests that compatibility overrides are retrieved and affect addon michael@0: // compatibility. michael@0: add_test(function() { michael@0: Services.prefs.setBoolPref(PREF_STRICT_COMPAT, false); michael@0: Services.prefs.setCharPref(PREF_MIN_PLATFORM_COMPAT, "0"); michael@0: is(AddonManager.strictCompatibility, false, "Strict compatibility should be disabled"); michael@0: michael@0: // Use a blank update URL michael@0: Services.prefs.setCharPref(PREF_UPDATEURL, TESTROOT + "missing.rdf"); michael@0: michael@0: install_test_addons(function() { michael@0: michael@0: AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", michael@0: "addon2@tests.mozilla.org", michael@0: "addon3@tests.mozilla.org", michael@0: "addon4@tests.mozilla.org", michael@0: "addon5@tests.mozilla.org", michael@0: "addon6@tests.mozilla.org", michael@0: "addon7@tests.mozilla.org", michael@0: "addon8@tests.mozilla.org", michael@0: "addon9@tests.mozilla.org", michael@0: "addon10@tests.mozilla.org"], michael@0: function(aAddons) { michael@0: michael@0: for (let addon of aAddons) { michael@0: if (addon.id == "addon10@tests.mozilla.org") michael@0: is(addon.isCompatible, true, "Addon10 should be compatible before compat overrides are refreshed"); michael@0: else michael@0: addon.uninstall(); michael@0: } michael@0: michael@0: Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, TESTROOT + "browser_bug557956.xml"); michael@0: Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); michael@0: michael@0: open_compatibility_window([], function(aWindow) { michael@0: var doc = aWindow.document; michael@0: wait_for_page(aWindow, "mismatch", function(aWindow) { michael@0: var items = get_list_names(doc.getElementById("mismatch.incompatible")); michael@0: is(items.length, 1, "Should have seen 1 incompatible item"); michael@0: is(items[0], "Addon10 1.0", "Should have seen addon10 as incompatible"); michael@0: michael@0: var button = doc.documentElement.getButton("next"); michael@0: EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); michael@0: michael@0: wait_for_page(aWindow, "noupdates", function(aWindow) { michael@0: var button = doc.documentElement.getButton("finish"); michael@0: ok(!button.hidden, "Finish button should not be hidden"); michael@0: ok(!button.disabled, "Finish button should not be disabled"); michael@0: michael@0: wait_for_window_close(aWindow, function() { michael@0: uninstall_test_addons(run_next_test); michael@0: }); michael@0: michael@0: check_telemetry({disabled: 0, metaenabled: 0, metadisabled: 1, michael@0: upgraded: 0, failed: 0, declined: 0}); michael@0: michael@0: EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); michael@0: }); michael@0: }); michael@0: }); michael@0: }); michael@0: }); michael@0: });