diff options
Diffstat (limited to 'toolkit/mozapps/extensions/test')
701 files changed, 74306 insertions, 0 deletions
diff --git a/toolkit/mozapps/extensions/test/AddonManagerTesting.jsm b/toolkit/mozapps/extensions/test/AddonManagerTesting.jsm new file mode 100644 index 000000000..52c954b1a --- /dev/null +++ b/toolkit/mozapps/extensions/test/AddonManagerTesting.jsm @@ -0,0 +1,105 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// This file is a test-only JSM containing utility methods for +// interacting with the add-ons manager. + +"use strict"; + +this.EXPORTED_SYMBOLS = [ + "AddonTestUtils", +]; + +const {utils: Cu} = Components; + +Cu.import("resource://gre/modules/Promise.jsm"); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + +XPCOMUtils.defineLazyModuleGetter(this, "AddonManager", + "resource://gre/modules/AddonManager.jsm"); + +this.AddonTestUtils = { + /** + * Uninstall an add-on that is specified by its ID. + * + * The returned promise resolves on successful uninstall and rejects + * if the add-on is not unknown. + * + * @return Promise<restartRequired> + */ + uninstallAddonByID: function (id) { + let deferred = Promise.defer(); + + AddonManager.getAddonByID(id, (addon) => { + if (!addon) { + deferred.reject(new Error("Add-on is not known: " + id)); + return; + } + + let listener = { + onUninstalling: function (addon, needsRestart) { + if (addon.id != id) { + return; + } + + if (needsRestart) { + AddonManager.removeAddonListener(listener); + deferred.resolve(true); + } + }, + + onUninstalled: function (addon) { + if (addon.id != id) { + return; + } + + AddonManager.removeAddonListener(listener); + deferred.resolve(false); + }, + + onOperationCancelled: function (addon) { + if (addon.id != id) { + return; + } + + AddonManager.removeAddonListener(listener); + deferred.reject(new Error("Uninstall cancelled.")); + }, + }; + + AddonManager.addAddonListener(listener); + addon.uninstall(); + }); + + return deferred.promise; + }, + + /** + * Install an XPI add-on from a URL. + * + * @return Promise<addon> + */ + installXPIFromURL: function (url, hash, name, iconURL, version) { + let deferred = Promise.defer(); + + AddonManager.getInstallForURL(url, (install) => { + let fail = () => { deferred.reject(new Error("Add-on install failed.")) }; + + let listener = { + onDownloadCancelled: fail, + onDownloadFailed: fail, + onInstallCancelled: fail, + onInstallFailed: fail, + onInstallEnded: function (install, addon) { + deferred.resolve(addon); + }, + }; + + install.addListener(listener); + install.install(); + }, "application/x-xpinstall", hash, name, iconURL, version); + + return deferred.promise; + }, +}; diff --git a/toolkit/mozapps/extensions/test/Makefile.in b/toolkit/mozapps/extensions/test/Makefile.in new file mode 100644 index 000000000..6c667ecab --- /dev/null +++ b/toolkit/mozapps/extensions/test/Makefile.in @@ -0,0 +1,20 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +ADDONSRC = $(srcdir)/addons +TESTROOT = $(CURDIR)/$(DEPTH)/_tests/xpcshell/$(relativesrcdir) +TESTXPI = $(TESTROOT)/xpcshell/addons + +include $(topsrcdir)/config/rules.mk + +libs:: + rm -rf $(TESTXPI) + $(NSINSTALL) -D $(TESTXPI) + if [ -d $(ADDONSRC) ]; then \ + $(EXIT_ON_ERROR) \ + for dir in $(ADDONSRC)/*; do \ + base=`basename $$dir` ; \ + (cd $$dir && zip -qr $(TESTXPI)/$$base.xpi *) \ + done \ + fi diff --git a/toolkit/mozapps/extensions/test/addons/blocklist_hard1_1/install.rdf b/toolkit/mozapps/extensions/test/addons/blocklist_hard1_1/install.rdf new file mode 100644 index 000000000..7b1b02a17 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/blocklist_hard1_1/install.rdf @@ -0,0 +1,18 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>hardblock@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:name>Hardblocked add-on</em:name> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/blocklist_hard1_2/install.rdf b/toolkit/mozapps/extensions/test/addons/blocklist_hard1_2/install.rdf new file mode 100644 index 000000000..ae364637e --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/blocklist_hard1_2/install.rdf @@ -0,0 +1,18 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>hardblock@tests.mozilla.org</em:id> + <em:version>2.0</em:version> + <em:name>Hardblocked add-on</em:name> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/blocklist_hard1_3/install.rdf b/toolkit/mozapps/extensions/test/addons/blocklist_hard1_3/install.rdf new file mode 100644 index 000000000..568c41a43 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/blocklist_hard1_3/install.rdf @@ -0,0 +1,18 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>hardblock@tests.mozilla.org</em:id> + <em:version>3.0</em:version> + <em:name>Hardblocked add-on</em:name> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/blocklist_regexp1_1/install.rdf b/toolkit/mozapps/extensions/test/addons/blocklist_regexp1_1/install.rdf new file mode 100644 index 000000000..1281ab53f --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/blocklist_regexp1_1/install.rdf @@ -0,0 +1,18 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>regexpblock@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:name>RegExp-blocked add-on</em:name> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/blocklist_regexp1_2/install.rdf b/toolkit/mozapps/extensions/test/addons/blocklist_regexp1_2/install.rdf new file mode 100644 index 000000000..8b6dd09f5 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/blocklist_regexp1_2/install.rdf @@ -0,0 +1,18 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>regexpblock@tests.mozilla.org</em:id> + <em:version>2.0</em:version> + <em:name>RegExp-blocked add-on</em:name> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/blocklist_regexp1_3/install.rdf b/toolkit/mozapps/extensions/test/addons/blocklist_regexp1_3/install.rdf new file mode 100644 index 000000000..fade395f9 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/blocklist_regexp1_3/install.rdf @@ -0,0 +1,18 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>regexpblock@tests.mozilla.org</em:id> + <em:version>3.0</em:version> + <em:name>RegExp-blocked add-on</em:name> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/blocklist_soft1_1/install.rdf b/toolkit/mozapps/extensions/test/addons/blocklist_soft1_1/install.rdf new file mode 100644 index 000000000..4a18f64e0 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/blocklist_soft1_1/install.rdf @@ -0,0 +1,18 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>softblock1@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:name>Softblocked add-on</em:name> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/blocklist_soft1_2/install.rdf b/toolkit/mozapps/extensions/test/addons/blocklist_soft1_2/install.rdf new file mode 100644 index 000000000..8a2519222 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/blocklist_soft1_2/install.rdf @@ -0,0 +1,18 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>softblock1@tests.mozilla.org</em:id> + <em:version>2.0</em:version> + <em:name>Softblocked add-on</em:name> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/blocklist_soft1_3/install.rdf b/toolkit/mozapps/extensions/test/addons/blocklist_soft1_3/install.rdf new file mode 100644 index 000000000..2c55e5ff7 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/blocklist_soft1_3/install.rdf @@ -0,0 +1,18 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>softblock1@tests.mozilla.org</em:id> + <em:version>3.0</em:version> + <em:name>Softblocked add-on</em:name> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/blocklist_soft2_1/install.rdf b/toolkit/mozapps/extensions/test/addons/blocklist_soft2_1/install.rdf new file mode 100644 index 000000000..eebac4b21 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/blocklist_soft2_1/install.rdf @@ -0,0 +1,18 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>softblock2@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:name>Softblocked add-on</em:name> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/blocklist_soft2_2/install.rdf b/toolkit/mozapps/extensions/test/addons/blocklist_soft2_2/install.rdf new file mode 100644 index 000000000..f37741d04 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/blocklist_soft2_2/install.rdf @@ -0,0 +1,18 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>softblock2@tests.mozilla.org</em:id> + <em:version>2.0</em:version> + <em:name>Softblocked add-on</em:name> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/blocklist_soft2_3/install.rdf b/toolkit/mozapps/extensions/test/addons/blocklist_soft2_3/install.rdf new file mode 100644 index 000000000..e15f99264 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/blocklist_soft2_3/install.rdf @@ -0,0 +1,18 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>softblock2@tests.mozilla.org</em:id> + <em:version>3.0</em:version> + <em:name>Softblocked add-on</em:name> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/blocklist_soft3_1/install.rdf b/toolkit/mozapps/extensions/test/addons/blocklist_soft3_1/install.rdf new file mode 100644 index 000000000..f4b70a24b --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/blocklist_soft3_1/install.rdf @@ -0,0 +1,18 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>softblock3@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:name>Softblocked add-on</em:name> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/blocklist_soft3_2/install.rdf b/toolkit/mozapps/extensions/test/addons/blocklist_soft3_2/install.rdf new file mode 100644 index 000000000..987204fa6 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/blocklist_soft3_2/install.rdf @@ -0,0 +1,18 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>softblock3@tests.mozilla.org</em:id> + <em:version>2.0</em:version> + <em:name>Softblocked add-on</em:name> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/blocklist_soft3_3/install.rdf b/toolkit/mozapps/extensions/test/addons/blocklist_soft3_3/install.rdf new file mode 100644 index 000000000..19ab4b9fe --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/blocklist_soft3_3/install.rdf @@ -0,0 +1,18 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>softblock3@tests.mozilla.org</em:id> + <em:version>3.0</em:version> + <em:name>Softblocked add-on</em:name> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/blocklist_soft4_1/install.rdf b/toolkit/mozapps/extensions/test/addons/blocklist_soft4_1/install.rdf new file mode 100644 index 000000000..a3cd06f5f --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/blocklist_soft4_1/install.rdf @@ -0,0 +1,18 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>softblock4@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:name>Softblocked add-on</em:name> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/blocklist_soft4_2/install.rdf b/toolkit/mozapps/extensions/test/addons/blocklist_soft4_2/install.rdf new file mode 100644 index 000000000..eeff9fb79 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/blocklist_soft4_2/install.rdf @@ -0,0 +1,18 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>softblock4@tests.mozilla.org</em:id> + <em:version>2.0</em:version> + <em:name>Softblocked add-on</em:name> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/blocklist_soft4_3/install.rdf b/toolkit/mozapps/extensions/test/addons/blocklist_soft4_3/install.rdf new file mode 100644 index 000000000..1d2650603 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/blocklist_soft4_3/install.rdf @@ -0,0 +1,18 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>softblock4@tests.mozilla.org</em:id> + <em:version>3.0</em:version> + <em:name>Softblocked add-on</em:name> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/blocklist_soft5_1/install.rdf b/toolkit/mozapps/extensions/test/addons/blocklist_soft5_1/install.rdf new file mode 100644 index 000000000..85d7108d6 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/blocklist_soft5_1/install.rdf @@ -0,0 +1,19 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>softblock5@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:name>Softblocked add-on</em:name> + <em:internalName>test/1.0</em:internalName> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/blocklist_soft5_2/install.rdf b/toolkit/mozapps/extensions/test/addons/blocklist_soft5_2/install.rdf new file mode 100644 index 000000000..394fd909e --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/blocklist_soft5_2/install.rdf @@ -0,0 +1,19 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>softblock5@tests.mozilla.org</em:id> + <em:version>2.0</em:version> + <em:name>Softblocked add-on</em:name> + <em:internalName>test/1.0</em:internalName> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/blocklist_soft5_3/install.rdf b/toolkit/mozapps/extensions/test/addons/blocklist_soft5_3/install.rdf new file mode 100644 index 000000000..2a1fec25a --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/blocklist_soft5_3/install.rdf @@ -0,0 +1,19 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>softblock5@tests.mozilla.org</em:id> + <em:version>3.0</em:version> + <em:name>Softblocked add-on</em:name> + <em:internalName>test/1.0</em:internalName> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/bootstrap_globals/bootstrap.js b/toolkit/mozapps/extensions/test/addons/bootstrap_globals/bootstrap.js new file mode 100644 index 000000000..f8a62bcaa --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/bootstrap_globals/bootstrap.js @@ -0,0 +1,29 @@ +Components.utils.import("resource://gre/modules/Services.jsm"); + +let seenGlobals = new Set(); +let scope = this; +function checkGlobal(name, type) { + if (scope[name] && typeof(scope[name]) == type) + seenGlobals.add(name); +} + +let wrapped = {}; +Services.obs.notifyObservers({ wrappedJSObject: wrapped }, "bootstrap-request-globals", null); +for (let [name, type] of wrapped.expectedGlobals) { + checkGlobal(name, type); +} + +function install(data, reason) { +} + +function startup(data, reason) { + Services.obs.notifyObservers({ + wrappedJSObject: seenGlobals + }, "bootstrap-seen-globals", null); +} + +function shutdown(data, reason) { +} + +function uninstall(data, reason) { +} diff --git a/toolkit/mozapps/extensions/test/addons/bootstrap_globals/install.rdf b/toolkit/mozapps/extensions/test/addons/bootstrap_globals/install.rdf new file mode 100644 index 000000000..f11a626fd --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/bootstrap_globals/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bootstrap_globals@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:bootstrap>true</em:bootstrap> + + <!-- Front End MetaData --> + <em:name>Test Bootstrap Globals</em:name> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/min1max1/install.rdf b/toolkit/mozapps/extensions/test/addons/min1max1/install.rdf new file mode 100644 index 000000000..3a0ace227 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/min1max1/install.rdf @@ -0,0 +1,22 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>min1max1@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Test minVersion 1 maxVersion 1</em:name> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/min1max2/install.rdf b/toolkit/mozapps/extensions/test/addons/min1max2/install.rdf new file mode 100644 index 000000000..0184f1963 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/min1max2/install.rdf @@ -0,0 +1,22 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>min1max2@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Test minVersion 1 maxVersion 2</em:name> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/min1max3/install.rdf b/toolkit/mozapps/extensions/test/addons/min1max3/install.rdf new file mode 100644 index 000000000..dbb1b7318 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/min1max3/install.rdf @@ -0,0 +1,22 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>min1max3@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Test minVersion 1 maxVersion 3</em:name> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/min1max3b/install.rdf b/toolkit/mozapps/extensions/test/addons/min1max3b/install.rdf new file mode 100644 index 000000000..f50c65c6a --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/min1max3b/install.rdf @@ -0,0 +1,22 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>min1max3b@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Another Test minVersion 1 maxVersion 3</em:name> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/override1x2-1x3/install.rdf b/toolkit/mozapps/extensions/test/addons/override1x2-1x3/install.rdf new file mode 100644 index 000000000..92cf3ec96 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/override1x2-1x3/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>override1x2-1x3@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:updateURL>http://localhost:4444/data/test_bug542391.rdf</em:updateURL> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Test override compat from 1..2 to 1..3</em:name> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_AddonRepository_1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_AddonRepository_1/install.rdf new file mode 100644 index 000000000..82cfd0472 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_AddonRepository_1/install.rdf @@ -0,0 +1,33 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>test_AddonRepository_1@tests.mozilla.org</em:id> + <em:version>1.1</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>XPI Add-on 1</em:name> + <em:description>XPI Add-on 1 - Description</em:description> + <em:creator>XPI Add-on 1 - Creator</em:creator> + <em:developer>XPI Add-on 1 - First Developer</em:developer> + <em:developer>XPI Add-on 1 - Second Developer</em:developer> + <em:translator>XPI Add-on 1 - First Translator</em:translator> + <em:translator>XPI Add-on 1 - Second Translator</em:translator> + <em:contributor>XPI Add-on 1 - First Contributor</em:contributor> + <em:contributor>XPI Add-on 1 - Second Contributor</em:contributor> + <em:homepageURL>http://localhost/xpi/1/homepage.html</em:homepageURL> + <em:optionsURL>http://localhost/xpi/1/options.html</em:optionsURL> + <em:aboutURL>http://localhost/xpi/1/about.html</em:aboutURL> + <em:iconURL>http://localhost/xpi/1/icon.png</em:iconURL> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_AddonRepository_2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_AddonRepository_2/install.rdf new file mode 100644 index 000000000..80776e6c3 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_AddonRepository_2/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>test_AddonRepository_2@tests.mozilla.org</em:id> + <em:type>4</em:type> + <em:internalName>test2/1.0</em:internalName> + <em:version>1.2</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>XPI Add-on 2</em:name> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_AddonRepository_3/icon.png b/toolkit/mozapps/extensions/test/addons/test_AddonRepository_3/icon.png new file mode 100644 index 000000000..41409edfe --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_AddonRepository_3/icon.png @@ -0,0 +1 @@ +Fake icon image diff --git a/toolkit/mozapps/extensions/test/addons/test_AddonRepository_3/install.rdf b/toolkit/mozapps/extensions/test/addons/test_AddonRepository_3/install.rdf new file mode 100644 index 000000000..bade9c069 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_AddonRepository_3/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>test_AddonRepository_3@tests.mozilla.org</em:id> + <em:type>4</em:type> + <em:internalName>test3/1.0</em:internalName> + <em:version>1.3</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>XPI Add-on 3</em:name> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_AddonRepository_3/preview.png b/toolkit/mozapps/extensions/test/addons/test_AddonRepository_3/preview.png new file mode 100644 index 000000000..321ce47cf --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_AddonRepository_3/preview.png @@ -0,0 +1 @@ +Fake preview image diff --git a/toolkit/mozapps/extensions/test/addons/test_bootstrap1_1/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_1/bootstrap.js new file mode 100644 index 000000000..eba6762c8 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_1/bootstrap.js @@ -0,0 +1,32 @@ +Components.utils.import("resource://gre/modules/Services.jsm"); + +// Test steps chain from pref observers on *_reason, +// so always set that last +function install(data, reason) { + Components.utils.import(data.resourceURI.spec + "version.jsm"); + Services.prefs.setIntPref("bootstraptest.installed_version", VERSION); + Services.prefs.setIntPref("bootstraptest.install_oldversion", data.oldVersion); + Components.utils.unload(data.resourceURI.spec + "version.jsm"); + Services.prefs.setIntPref("bootstraptest.install_reason", reason); +} + +function startup(data, reason) { + Components.utils.reportError("bootstrap startup"); + Components.utils.import(data.resourceURI.spec + "version.jsm"); + Services.prefs.setIntPref("bootstraptest.active_version", VERSION); + Services.prefs.setIntPref("bootstraptest.startup_oldversion", data.oldVersion); + Components.utils.unload(data.resourceURI.spec + "version.jsm"); + Services.prefs.setIntPref("bootstraptest.startup_reason", reason); +} + +function shutdown(data, reason) { + Services.prefs.setIntPref("bootstraptest.active_version", 0); + Services.prefs.setIntPref("bootstraptest.shutdown_newversion", data.newVersion); + Services.prefs.setIntPref("bootstraptest.shutdown_reason", reason); +} + +function uninstall(data, reason) { + Services.prefs.setIntPref("bootstraptest.installed_version", 0); + Services.prefs.setIntPref("bootstraptest.uninstall_newversion", data.newVersion); + Services.prefs.setIntPref("bootstraptest.uninstall_reason", reason); +} diff --git a/toolkit/mozapps/extensions/test/addons/test_bootstrap1_1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_1/install.rdf new file mode 100644 index 000000000..f02a3869c --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_1/install.rdf @@ -0,0 +1,28 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bootstrap1@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:bootstrap>true</em:bootstrap> + + <!-- Front End MetaData --> + <em:name>Test Bootstrap 1</em:name> + <em:description>Test Description</em:description> + + <em:iconURL>chrome://foo/skin/icon.png</em:iconURL> + <em:aboutURL>chrome://foo/content/about.xul</em:aboutURL> + <em:optionsURL>chrome://foo/content/options.xul</em:optionsURL> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bootstrap1_1/version.jsm b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_1/version.jsm new file mode 100644 index 000000000..7fe60e632 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_1/version.jsm @@ -0,0 +1,3 @@ +this.EXPORTED_SYMBOLS = ["VERSION"]; + +this.VERSION = 1; diff --git a/toolkit/mozapps/extensions/test/addons/test_bootstrap1_2/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_2/bootstrap.js new file mode 100644 index 000000000..8839bfb7d --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_2/bootstrap.js @@ -0,0 +1,31 @@ +Components.utils.import("resource://gre/modules/Services.jsm"); + +// Test steps chain from pref observers on *_reason, +// so always set that last +function install(data, reason) { + Components.utils.import(data.resourceURI.spec + "version.jsm"); + Services.prefs.setIntPref("bootstraptest.installed_version", VERSION); + Services.prefs.setIntPref("bootstraptest.install_oldversion", data.oldVersion); + Components.utils.unload(data.resourceURI.spec + "version.jsm"); + Services.prefs.setIntPref("bootstraptest.install_reason", reason); +} + +function startup(data, reason) { + Components.utils.import(data.resourceURI.spec + "version.jsm"); + Services.prefs.setIntPref("bootstraptest.active_version", VERSION); + Services.prefs.setIntPref("bootstraptest.startup_oldversion", data.oldVersion); + Components.utils.unload(data.resourceURI.spec + "version.jsm"); + Services.prefs.setIntPref("bootstraptest.startup_reason", reason); +} + +function shutdown(data, reason) { + Services.prefs.setIntPref("bootstraptest.active_version", 0); + Services.prefs.setIntPref("bootstraptest.shutdown_newversion", data.newVersion); + Services.prefs.setIntPref("bootstraptest.shutdown_reason", reason); +} + +function uninstall(data, reason) { + Services.prefs.setIntPref("bootstraptest.installed_version", 0); + Services.prefs.setIntPref("bootstraptest.uninstall_newversion", data.newVersion); + Services.prefs.setIntPref("bootstraptest.uninstall_reason", reason); +} diff --git a/toolkit/mozapps/extensions/test/addons/test_bootstrap1_2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_2/install.rdf new file mode 100644 index 000000000..480f03fd1 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_2/install.rdf @@ -0,0 +1,24 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bootstrap1@tests.mozilla.org</em:id> + <em:version>2.0</em:version> + <em:bootstrap>true</em:bootstrap> + + <!-- Front End MetaData --> + <em:name>Test Bootstrap 1</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bootstrap1_2/version.jsm b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_2/version.jsm new file mode 100644 index 000000000..532741e12 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_2/version.jsm @@ -0,0 +1,3 @@ +this.EXPORTED_SYMBOLS = ["VERSION"]; + +this.VERSION = 2; diff --git a/toolkit/mozapps/extensions/test/addons/test_bootstrap1_3/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_3/bootstrap.js new file mode 100644 index 000000000..8839bfb7d --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_3/bootstrap.js @@ -0,0 +1,31 @@ +Components.utils.import("resource://gre/modules/Services.jsm"); + +// Test steps chain from pref observers on *_reason, +// so always set that last +function install(data, reason) { + Components.utils.import(data.resourceURI.spec + "version.jsm"); + Services.prefs.setIntPref("bootstraptest.installed_version", VERSION); + Services.prefs.setIntPref("bootstraptest.install_oldversion", data.oldVersion); + Components.utils.unload(data.resourceURI.spec + "version.jsm"); + Services.prefs.setIntPref("bootstraptest.install_reason", reason); +} + +function startup(data, reason) { + Components.utils.import(data.resourceURI.spec + "version.jsm"); + Services.prefs.setIntPref("bootstraptest.active_version", VERSION); + Services.prefs.setIntPref("bootstraptest.startup_oldversion", data.oldVersion); + Components.utils.unload(data.resourceURI.spec + "version.jsm"); + Services.prefs.setIntPref("bootstraptest.startup_reason", reason); +} + +function shutdown(data, reason) { + Services.prefs.setIntPref("bootstraptest.active_version", 0); + Services.prefs.setIntPref("bootstraptest.shutdown_newversion", data.newVersion); + Services.prefs.setIntPref("bootstraptest.shutdown_reason", reason); +} + +function uninstall(data, reason) { + Services.prefs.setIntPref("bootstraptest.installed_version", 0); + Services.prefs.setIntPref("bootstraptest.uninstall_newversion", data.newVersion); + Services.prefs.setIntPref("bootstraptest.uninstall_reason", reason); +} diff --git a/toolkit/mozapps/extensions/test/addons/test_bootstrap1_3/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_3/install.rdf new file mode 100644 index 000000000..e9385cbb3 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_3/install.rdf @@ -0,0 +1,24 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bootstrap1@tests.mozilla.org</em:id> + <em:version>3.0</em:version> + <em:bootstrap>true</em:bootstrap> + + <!-- Front End MetaData --> + <em:name>Test Bootstrap 1</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>undefined</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bootstrap1_3/version.jsm b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_3/version.jsm new file mode 100644 index 000000000..1b813faaf --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_3/version.jsm @@ -0,0 +1,3 @@ +this.EXPORTED_SYMBOLS = ["VERSION"]; + +this.VERSION = 3; diff --git a/toolkit/mozapps/extensions/test/addons/test_bootstrap1_4/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_4/install.rdf new file mode 100644 index 000000000..2b88e0ad0 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_4/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bootstrap1@tests.mozilla.org</em:id> + <em:version>4.0</em:version> + + <!-- Front End MetaData --> + <em:name>Test Bootstrap 1</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bootstrap2_1/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_bootstrap2_1/bootstrap.js new file mode 100644 index 000000000..476edfeee --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bootstrap2_1/bootstrap.js @@ -0,0 +1,17 @@ +Components.utils.import("resource://gre/modules/Services.jsm"); + +function install(data, reason) { + Services.prefs.setIntPref("bootstraptest2.installed_version", 1); +} + +function startup(data, reason) { + Services.prefs.setIntPref("bootstraptest2.active_version", 1); +} + +function shutdown(data, reason) { + Services.prefs.setIntPref("bootstraptest2.active_version", 0); +} + +function uninstall(data, reason) { + Services.prefs.setIntPref("bootstraptest2.installed_version", 0); +} diff --git a/toolkit/mozapps/extensions/test/addons/test_bootstrap2_1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bootstrap2_1/install.rdf new file mode 100644 index 000000000..e0e8ca978 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bootstrap2_1/install.rdf @@ -0,0 +1,28 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bootstrap2@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:bootstrap>true</em:bootstrap> + + <!-- Front End MetaData --> + <em:name>Test Bootstrap 2</em:name> + <em:description>Test Description</em:description> + + <em:iconURL>chrome://foo/skin/icon.png</em:iconURL> + <em:aboutURL>chrome://foo/content/about.xul</em:aboutURL> + <em:optionsURL>chrome://foo/content/options.xul</em:optionsURL> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug299716_2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug299716_2/install.rdf new file mode 100644 index 000000000..791a6263f --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug299716_2/install.rdf @@ -0,0 +1,30 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>bug299716-2@tests.mozilla.org</em:id> + <em:version>0.1</em:version> + + <!-- XPCShell --> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Toolkit --> + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>1.9</em:minVersion> + <em:maxVersion>1.9</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 299716</em:name> + <em:updateURL>http://localhost:4444/data/test_bug299716_2.rdf</em:updateURL> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug299716_a_1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug299716_a_1/install.rdf new file mode 100644 index 000000000..36d15b8aa --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug299716_a_1/install.rdf @@ -0,0 +1,21 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug299716-a@tests.mozilla.org</em:id> + <em:version>0.1</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>5</em:minVersion> + <em:maxVersion>5</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 299716 test A</em:name> + <em:updateURL>http://localhost:4444/data/test_bug299716.rdf</em:updateURL> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug299716_a_2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug299716_a_2/install.rdf new file mode 100644 index 000000000..3521a503c --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug299716_a_2/install.rdf @@ -0,0 +1,21 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug299716-a@tests.mozilla.org</em:id> + <em:version>0.2</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>5</em:minVersion> + <em:maxVersion>5</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 299716 test A</em:name> + <em:updateURL>http://localhost:4444/data/test_bug299716.rdf</em:updateURL> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug299716_b_1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug299716_b_1/install.rdf new file mode 100644 index 000000000..d92a4ec41 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug299716_b_1/install.rdf @@ -0,0 +1,20 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>bug299716-b@tests.mozilla.org</em:id> + <em:version>0.1</em:version> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>1.9</em:minVersion> + <em:maxVersion>1.9</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 299716 test B</em:name> + <em:updateURL>http://localhost:4444/data/test_bug299716.rdf</em:updateURL> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug299716_b_2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug299716_b_2/install.rdf new file mode 100644 index 000000000..c3ad76b84 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug299716_b_2/install.rdf @@ -0,0 +1,20 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>bug299716-b@tests.mozilla.org</em:id> + <em:version>0.2</em:version> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>1.9</em:minVersion> + <em:maxVersion>1.9</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 299716 test B</em:name> + <em:updateURL>http://localhost:4444/data/test_bug299716.rdf</em:updateURL> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug299716_c_1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug299716_c_1/install.rdf new file mode 100644 index 000000000..a937b6e76 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug299716_c_1/install.rdf @@ -0,0 +1,30 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>bug299716-c@tests.mozilla.org</em:id> + <em:version>0.1</em:version> + + <!-- XPCShell --> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>5</em:minVersion> + <em:maxVersion>5</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Toolkit --> + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>1.9</em:minVersion> + <em:maxVersion>1.9</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 299716 test C</em:name> + <em:updateURL>http://localhost:4444/data/test_bug299716.rdf</em:updateURL> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug299716_c_2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug299716_c_2/install.rdf new file mode 100644 index 000000000..8afca3ff9 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug299716_c_2/install.rdf @@ -0,0 +1,30 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>bug299716-c@tests.mozilla.org</em:id> + <em:version>0.2</em:version> + + <!-- XPCShell --> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>5</em:minVersion> + <em:maxVersion>5</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Toolkit --> + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>1.9</em:minVersion> + <em:maxVersion>1.9</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 299716 test C</em:name> + <em:updateURL>http://localhost:4444/data/test_bug299716.rdf</em:updateURL> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug299716_d_1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug299716_d_1/install.rdf new file mode 100644 index 000000000..4c0dcc2ef --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug299716_d_1/install.rdf @@ -0,0 +1,30 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>bug299716-d@tests.mozilla.org</em:id> + <em:version>0.1</em:version> + + <!-- XPCShell --> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>5</em:minVersion> + <em:maxVersion>5</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Toolkit, invalid --> + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>30</em:minVersion> + <em:maxVersion>30</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 299716 test D</em:name> + <em:updateURL>http://localhost:4444/data/test_bug299716.rdf</em:updateURL> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug299716_d_2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug299716_d_2/install.rdf new file mode 100644 index 000000000..2b113809a --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug299716_d_2/install.rdf @@ -0,0 +1,30 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>bug299716-d@tests.mozilla.org</em:id> + <em:version>0.2</em:version> + + <!-- XPCShell --> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>5</em:minVersion> + <em:maxVersion>5</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Toolkit, invalid --> + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>30</em:minVersion> + <em:maxVersion>30</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 299716 test D</em:name> + <em:updateURL>http://localhost:4444/data/test_bug299716.rdf</em:updateURL> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug299716_e_1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug299716_e_1/install.rdf new file mode 100644 index 000000000..03eb7180e --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug299716_e_1/install.rdf @@ -0,0 +1,30 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>bug299716-e@tests.mozilla.org</em:id> + <em:version>0.1</em:version> + + <!-- Toolkit --> + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>1.9</em:minVersion> + <em:maxVersion>1.9</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- XPCShell, invalid --> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>30</em:minVersion> + <em:maxVersion>30</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 299716 test E</em:name> + <em:updateURL>http://localhost:4444/data/test_bug299716.rdf</em:updateURL> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug299716_e_2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug299716_e_2/install.rdf new file mode 100644 index 000000000..3ed7cd932 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug299716_e_2/install.rdf @@ -0,0 +1,30 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>bug299716-e@tests.mozilla.org</em:id> + <em:version>0.2</em:version> + + <!-- Toolkit --> + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>1.9</em:minVersion> + <em:maxVersion>1.9</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- XPCShell, invalid --> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>30</em:minVersion> + <em:maxVersion>30</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 299716 test E</em:name> + <em:updateURL>http://localhost:4444/data/test_bug299716.rdf</em:updateURL> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug299716_f_1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug299716_f_1/install.rdf new file mode 100644 index 000000000..cacf824c1 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug299716_f_1/install.rdf @@ -0,0 +1,30 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>bug299716-f@tests.mozilla.org</em:id> + <em:version>0.1</em:version> + + <!-- Toolkit, invalid --> + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>30</em:minVersion> + <em:maxVersion>30</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- XPCShell, invalid --> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>30</em:minVersion> + <em:maxVersion>30</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 299716 test F</em:name> + <em:updateURL>http://localhost:4444/data/test_bug299716.rdf</em:updateURL> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug299716_f_2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug299716_f_2/install.rdf new file mode 100644 index 000000000..09954ec36 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug299716_f_2/install.rdf @@ -0,0 +1,30 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>bug299716-f@tests.mozilla.org</em:id> + <em:version>0.2</em:version> + + <!-- Toolkit, invalid --> + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>30</em:minVersion> + <em:maxVersion>30</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- XPCShell, invalid --> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>30</em:minVersion> + <em:maxVersion>30</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 299716 test F</em:name> + <em:updateURL>http://localhost:4444/data/test_bug299716.rdf</em:updateURL> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug299716_g_1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug299716_g_1/install.rdf new file mode 100644 index 000000000..5e4a6f6a2 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug299716_g_1/install.rdf @@ -0,0 +1,21 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>bug299716-g@tests.mozilla.org</em:id> + <em:version>0.1</em:version> + + <!-- Toolkit, invalid --> + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>30</em:minVersion> + <em:maxVersion>30</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 299716 test G</em:name> + <em:updateURL>http://localhost:4444/data/test_bug299716.rdf</em:updateURL> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug299716_g_2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug299716_g_2/install.rdf new file mode 100644 index 000000000..913233cec --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug299716_g_2/install.rdf @@ -0,0 +1,21 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>bug299716-g@tests.mozilla.org</em:id> + <em:version>0.2</em:version> + + <!-- Toolkit, invalid --> + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>30</em:minVersion> + <em:maxVersion>30</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 299716 test G</em:name> + <em:updateURL>http://localhost:4444/data/test_bug299716.rdf</em:updateURL> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug324121_1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug324121_1/install.rdf new file mode 100644 index 000000000..fd0dd50b7 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug324121_1/install.rdf @@ -0,0 +1,25 @@ +<?xml version="1.0"?> + +<!-- Compatible to install --> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug324121_1@tests.mozilla.org</em:id> + <em:version>1</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 324121 Test 1</em:name> + <em:updateURL>http://localhost:4444/data/test_bug324121_1.rdf</em:updateURL> + + </Description> +</RDF> + diff --git a/toolkit/mozapps/extensions/test/addons/test_bug324121_2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug324121_2/install.rdf new file mode 100644 index 000000000..607b68357 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug324121_2/install.rdf @@ -0,0 +1,25 @@ +<?xml version="1.0"?> + +<!-- Compatible to install --> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug324121_2@tests.mozilla.org</em:id> + <em:version>1</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 324121 Test 2</em:name> + <em:updateURL>http://localhost:4444/data/test_bug324121.rdf</em:updateURL> + + </Description> +</RDF> + diff --git a/toolkit/mozapps/extensions/test/addons/test_bug324121_3/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug324121_3/install.rdf new file mode 100644 index 000000000..3a4c7eafc --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug324121_3/install.rdf @@ -0,0 +1,25 @@ +<?xml version="1.0"?> + +<!-- Compatible to install --> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug324121_3@tests.mozilla.org</em:id> + <em:version>1</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 324121 Test 5</em:name> + <em:updateURL>http://localhost:4444/data/test_bug324121.rdf</em:updateURL> + + </Description> +</RDF> + diff --git a/toolkit/mozapps/extensions/test/addons/test_bug324121_4/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug324121_4/install.rdf new file mode 100644 index 000000000..8557df116 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug324121_4/install.rdf @@ -0,0 +1,25 @@ +<?xml version="1.0"?> + +<!-- Compatible to install --> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug324121_4@tests.mozilla.org</em:id> + <em:version>1</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 324121 Test 4</em:name> + <em:updateURL>http://localhost:4444/data/test_bug324121_4.rdf</em:updateURL> + + </Description> +</RDF> + diff --git a/toolkit/mozapps/extensions/test/addons/test_bug324121_5/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug324121_5/install.rdf new file mode 100644 index 000000000..343a9d44c --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug324121_5/install.rdf @@ -0,0 +1,25 @@ +<?xml version="1.0"?> + +<!-- Compatible to install --> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug324121_5@tests.mozilla.org</em:id> + <em:version>1</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 324121 Test 5</em:name> + <em:updateURL>http://localhost:4444/data/test_bug324121_5.rdf</em:updateURL> + + </Description> +</RDF> + diff --git a/toolkit/mozapps/extensions/test/addons/test_bug324121_6/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug324121_6/install.rdf new file mode 100644 index 000000000..5a724cc99 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug324121_6/install.rdf @@ -0,0 +1,25 @@ +<?xml version="1.0"?> + +<!-- Compatible to install --> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug324121_6@tests.mozilla.org</em:id> + <em:version>1</em:version> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 324121 Test 6</em:name> + <em:updateURL>http://localhost:4444/data/test_bug324121.rdf</em:updateURL> + + </Description> +</RDF> + diff --git a/toolkit/mozapps/extensions/test/addons/test_bug324121_7/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug324121_7/install.rdf new file mode 100644 index 000000000..70fe81168 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug324121_7/install.rdf @@ -0,0 +1,25 @@ +<?xml version="1.0"?> + +<!-- Compatible to install --> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug324121_7@tests.mozilla.org</em:id> + <em:version>1</em:version> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 324121 Test 7</em:name> + <em:updateURL>http://localhost:4444/data/test_bug324121.rdf</em:updateURL> + + </Description> +</RDF> + diff --git a/toolkit/mozapps/extensions/test/addons/test_bug324121_8/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug324121_8/install.rdf new file mode 100644 index 000000000..2aface3b4 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug324121_8/install.rdf @@ -0,0 +1,25 @@ +<?xml version="1.0"?> + +<!-- Compatible to install --> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug324121_8@tests.mozilla.org</em:id> + <em:version>1</em:version> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 324121 Test 8</em:name> + <em:updateURL>http://localhost:4444/data/test_bug324121_8.rdf</em:updateURL> + + </Description> +</RDF> + diff --git a/toolkit/mozapps/extensions/test/addons/test_bug324121_9/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug324121_9/install.rdf new file mode 100644 index 000000000..7804e833c --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug324121_9/install.rdf @@ -0,0 +1,25 @@ +<?xml version="1.0"?> + +<!-- Compatible to install --> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug324121_9@tests.mozilla.org</em:id> + <em:version>1</em:version> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 324121 Test 9</em:name> + <em:updateURL>http://localhost:4444/data/test_bug324121_9.rdf</em:updateURL> + + </Description> +</RDF> + diff --git a/toolkit/mozapps/extensions/test/addons/test_bug335238_1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug335238_1/install.rdf new file mode 100644 index 000000000..c60b5711b --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug335238_1/install.rdf @@ -0,0 +1,22 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug335238_1@tests.mozilla.org</em:id> + <em:version>1.3.4</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>5</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 335238</em:name> + <em:updateURL>http://localhost:4444/0?id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appId=%APP_ID%&appVersion=%APP_VERSION%&appOs=%APP_OS%&appAbi=%APP_ABI%&locale=%APP_LOCALE%&reqVersion=%REQ_VERSION%</em:updateURL> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug335238_2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug335238_2/install.rdf new file mode 100644 index 000000000..23faf5a34 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug335238_2/install.rdf @@ -0,0 +1,30 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug335238_2@tests.mozilla.org</em:id> + <em:version>28at</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>7</em:maxVersion> + </Description> + </em:targetApplication> + + <em:requires> + <Description> + <em:id>unknown@tests.mozilla.org</em:id> + <em:minVersion>2</em:minVersion> + <em:maxVersion>72</em:maxVersion> + </Description> + </em:requires> + + <em:name>Bug 335238</em:name> + <em:updateURL>http://localhost:4444/1?id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appId=%APP_ID%&appVersion=%APP_VERSION%&appOs=%APP_OS%&appAbi=%APP_ABI%&locale=%APP_LOCALE%&reqVersion=%REQ_VERSION%</em:updateURL> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug335238_3/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug335238_3/install.rdf new file mode 100644 index 000000000..d44448208 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug335238_3/install.rdf @@ -0,0 +1,30 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug335238_3@tests.mozilla.org</em:id> + <em:version>58</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </Description> + </em:targetApplication> + + <em:requires> + <Description> + <em:id>unknown@tests.mozilla.org</em:id> + <em:minVersion>2</em:minVersion> + <em:maxVersion>72</em:maxVersion> + </Description> + </em:requires> + + <em:name>Bug 335238</em:name> + <em:updateURL>http://localhost:4444/2?id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appId=%APP_ID%&appVersion=%APP_VERSION%&appOs=%APP_OS%&appAbi=%APP_ABI%&locale=%APP_LOCALE%&reqVersion=%REQ_VERSION%</em:updateURL> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug335238_4/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug335238_4/install.rdf new file mode 100644 index 000000000..6ec052d36 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug335238_4/install.rdf @@ -0,0 +1,30 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug335238_4@tests.mozilla.org</em:id> + <em:version>4</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2+</em:maxVersion> + </Description> + </em:targetApplication> + + <em:requires> + <Description> + <em:id>unknown@tests.mozilla.org</em:id> + <em:minVersion>2</em:minVersion> + <em:maxVersion>72</em:maxVersion> + </Description> + </em:requires> + + <em:name>Bug 335238</em:name> + <em:updateURL>http://localhost:4444/3?id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appId=%APP_ID%&appVersion=%APP_VERSION%&appOs=%APP_OS%&appAbi=%APP_ABI%&locale=%APP_LOCALE%&reqVersion=%REQ_VERSION%</em:updateURL> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug371495/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug371495/install.rdf new file mode 100644 index 000000000..c60caf594 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug371495/install.rdf @@ -0,0 +1,26 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug371495@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Test theme</em:name> + <em:type>4</em:type> + <em:internalName>test/1.0</em:internalName> + <em:optionsURL>chrome://foo/content/bar.xul</em:optionsURL> + <em:aboutURL>chrome://foo/content/bar.xul</em:aboutURL> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug394300_1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug394300_1/install.rdf new file mode 100644 index 000000000..2e5ace760 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug394300_1/install.rdf @@ -0,0 +1,22 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug394300_1@tests.mozilla.org</em:id> + <em:version>5</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 394300 Test 1</em:name> + <em:updateURL>http://localhost:4444/test_bug394300.rdf</em:updateURL> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug394300_2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug394300_2/install.rdf new file mode 100644 index 000000000..ae54424d1 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug394300_2/install.rdf @@ -0,0 +1,22 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug394300_2@tests.mozilla.org</em:id> + <em:version>5</em:version> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>1.9</em:minVersion> + <em:maxVersion>1.9</em:maxVersion> + </Description> + </em:targetApplication> + + <em:name>Bug 394300 Test 2</em:name> + <em:updateURL>http://localhost:4444/test_bug394300.rdf</em:updateURL> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug397778/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug397778/install.rdf new file mode 100644 index 000000000..cfcfd406f --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug397778/install.rdf @@ -0,0 +1,78 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug397778@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + <em:localized> + <Description em:locale="fr"> + <em:name>fr Name</em:name> + <em:description>fr Description</em:description> + </Description> + </em:localized> + + <em:localized> + <Description em:locale="de-DE"> + <em:name>de-DE Name</em:name> + </Description> + </em:localized> + + <em:localized> + <Description em:locale="ES-es"> + <em:name>es-ES Name</em:name> + <em:description>es-ES Description</em:description> + </Description> + </em:localized> + + <em:localized> + <Description em:locale="zh-TW"> + <em:name>zh-TW Name</em:name> + <em:description>zh-TW Description</em:description> + </Description> + </em:localized> + + <em:localized> + <Description em:locale="zh-CN"> + <em:name>zh-CN Name</em:name> + <em:description>zh-CN Description</em:description> + </Description> + </em:localized> + + <em:localized> + <Description em:locale="en-GB"> + <em:name>en-GB Name</em:name> + <em:description>en-GB Description</em:description> + </Description> + </em:localized> + + <em:localized> + <Description em:locale="en"> + <em:name>en Name</em:name> + <em:description>en Description</em:description> + </Description> + </em:localized> + + <em:localized> + <Description em:locale="en-CA"> + <em:name>en-CA Name</em:name> + <em:description>en-CA Description</em:description> + </Description> + </em:localized> + + <!-- Front End MetaData --> + <em:name>Fallback Name</em:name> + <em:description>Fallback Description</em:description> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug425657/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug425657/install.rdf new file mode 100644 index 000000000..e4e1b339b --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug425657/install.rdf @@ -0,0 +1,17 @@ +<?xml version="1.0"?>
+
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+ <Description about="urn:mozilla:install-manifest">
+ <em:id>bug425657@tests.mozilla.org</em:id>
+ <em:version>1</em:version>
+ <em:targetApplication>
+ <Description>
+ <em:id>xpcshell@tests.mozilla.org</em:id>
+ <em:minVersion>1</em:minVersion>
+ <em:maxVersion>1</em:maxVersion>
+ </Description>
+ </em:targetApplication>
+ <em:name>Deutsches Wörterbuch</em:name>
+ </Description>
+</RDF>
diff --git a/toolkit/mozapps/extensions/test/addons/test_bug470377_1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug470377_1/install.rdf new file mode 100644 index 000000000..5397e8a87 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug470377_1/install.rdf @@ -0,0 +1,17 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>bug470377_1@tests.mozilla.org</em:id> + <em:version>1</em:version> + <em:targetApplication> + <Description> + <em:id>unknown@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + <em:name>Test for Bug 470377</em:name> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug470377_2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug470377_2/install.rdf new file mode 100644 index 000000000..b1dde7f7a --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug470377_2/install.rdf @@ -0,0 +1,17 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>bug470377_2@tests.mozilla.org</em:id> + <em:version>1</em:version> + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + <em:name>Test for Bug 470377</em:name> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug470377_3/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug470377_3/install.rdf new file mode 100644 index 000000000..ae483434a --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug470377_3/install.rdf @@ -0,0 +1,17 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>bug470377_3@tests.mozilla.org</em:id> + <em:version>1</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + <em:name>Test for Bug 470377</em:name> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug470377_4/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug470377_4/install.rdf new file mode 100644 index 000000000..97abacc5e --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug470377_4/install.rdf @@ -0,0 +1,17 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>bug470377_4@tests.mozilla.org</em:id> + <em:version>1</em:version> + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + <em:name>Test for Bug 470377</em:name> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug470377_5/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug470377_5/install.rdf new file mode 100644 index 000000000..bff1104a7 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug470377_5/install.rdf @@ -0,0 +1,17 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>bug470377_5@tests.mozilla.org</em:id> + <em:version>1</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + <em:name>Test for Bug 470377</em:name> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug521905/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug521905/install.rdf new file mode 100644 index 000000000..444bdc556 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug521905/install.rdf @@ -0,0 +1,22 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug521905@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Bug 521905</em:name> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug567173/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug567173/install.rdf new file mode 100644 index 000000000..f97bd1302 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug567173/install.rdf @@ -0,0 +1,22 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug567173</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Test Bug 567173</em:name> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug567184/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_bug567184/bootstrap.js new file mode 100644 index 000000000..09c083532 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug567184/bootstrap.js @@ -0,0 +1,7 @@ +function install(data, reason) { } + +function startup(data, reason) { } + +function shutdown(data, reason) { } + +function uninstall(data, reason) {} diff --git a/toolkit/mozapps/extensions/test/addons/test_bug567184/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug567184/install.rdf new file mode 100644 index 000000000..1e13ceb87 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug567184/install.rdf @@ -0,0 +1,24 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug567184@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:bootstrap>true</em:bootstrap> + + <!-- Front End MetaData --> + <em:name>Bug 567184 Test</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>undefined</em:minVersion> + <em:maxVersion>undefined</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug587088_1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug587088_1/install.rdf new file mode 100644 index 000000000..83220ce06 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug587088_1/install.rdf @@ -0,0 +1,22 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon1@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <!-- Front End MetaData --> + <em:name>Bug 587088 Test</em:name> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug587088_1/testfile b/toolkit/mozapps/extensions/test/addons/test_bug587088_1/testfile new file mode 100644 index 000000000..d2277257f --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug587088_1/testfile @@ -0,0 +1 @@ +Contents of add-on version 1 diff --git a/toolkit/mozapps/extensions/test/addons/test_bug587088_1/testfile1 b/toolkit/mozapps/extensions/test/addons/test_bug587088_1/testfile1 new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug587088_1/testfile1 diff --git a/toolkit/mozapps/extensions/test/addons/test_bug587088_2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug587088_2/install.rdf new file mode 100644 index 000000000..ba23ab802 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug587088_2/install.rdf @@ -0,0 +1,22 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon1@tests.mozilla.org</em:id> + <em:version>2.0</em:version> + + <!-- Front End MetaData --> + <em:name>Bug 587088 Test</em:name> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug587088_2/testfile b/toolkit/mozapps/extensions/test/addons/test_bug587088_2/testfile new file mode 100644 index 000000000..07afddfa7 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug587088_2/testfile @@ -0,0 +1 @@ +Contents of add-on version 2 diff --git a/toolkit/mozapps/extensions/test/addons/test_bug587088_2/testfile2 b/toolkit/mozapps/extensions/test/addons/test_bug587088_2/testfile2 new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug587088_2/testfile2 diff --git a/toolkit/mozapps/extensions/test/addons/test_bug594058/directory/file1 b/toolkit/mozapps/extensions/test/addons/test_bug594058/directory/file1 new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug594058/directory/file1 diff --git a/toolkit/mozapps/extensions/test/addons/test_bug594058/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug594058/install.rdf new file mode 100644 index 000000000..682831949 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug594058/install.rdf @@ -0,0 +1,21 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug594058@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + <em:name>bug 594058</em:name> + <em:description>stat-based invalidation</em:description> + <em:unpack>true</em:unpack> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug595573/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug595573/install.rdf new file mode 100644 index 000000000..36c03fd00 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug595573/install.rdf @@ -0,0 +1,24 @@ +<?xml version="1.0"?> + +<!-- An extension that is compatible with the XPCShell test suite --> +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>{2f69dacd-03df-4150-a9f1-e8a7b2748829}</em:id> + <em:version>1.0</em:version> + + <!-- Front End MetaData --> + <em:name>Test 1</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug655254/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug655254/install.rdf new file mode 100644 index 000000000..a3fa0d707 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug655254/install.rdf @@ -0,0 +1,18 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon1@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:name>Test 1</em:name> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug655254_2/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_bug655254_2/bootstrap.js new file mode 100644 index 000000000..b79648e89 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug655254_2/bootstrap.js @@ -0,0 +1,9 @@ +Components.utils.import("resource://gre/modules/Services.jsm"); + +function startup(data, reason) { + Services.prefs.setIntPref("bootstraptest.active_version", 1); +} + +function shutdown(data, reason) { + Services.prefs.setIntPref("bootstraptest.active_version", 0); +} diff --git a/toolkit/mozapps/extensions/test/addons/test_bug655254_2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug655254_2/install.rdf new file mode 100644 index 000000000..71827885f --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug655254_2/install.rdf @@ -0,0 +1,19 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon2@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:name>Test 2</em:name> + <em:bootstrap>true</em:bootstrap> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>2</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug659772/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug659772/install.rdf new file mode 100644 index 000000000..3b34c63d3 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug659772/install.rdf @@ -0,0 +1,24 @@ +<?xml version="1.0"?> + +<!-- An extension that is compatible with the XPCShell test suite --> +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon3@tests.mozilla.org</em:id> + <em:version>2.0</em:version> + + <!-- Front End MetaData --> + <em:name>Test 1</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>2</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug675371/chrome.manifest b/toolkit/mozapps/extensions/test/addons/test_bug675371/chrome.manifest new file mode 100644 index 000000000..17d5c99ec --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug675371/chrome.manifest @@ -0,0 +1 @@ +content bug675371 .
diff --git a/toolkit/mozapps/extensions/test/addons/test_bug675371/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug675371/install.rdf new file mode 100644 index 000000000..ca2881e5a --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug675371/install.rdf @@ -0,0 +1,24 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug675371@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:bootstrap>true</em:bootstrap> + + <!-- Front End MetaData --> + <em:name>Bug 675371 Test</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug675371/test.js b/toolkit/mozapps/extensions/test/addons/test_bug675371/test.js new file mode 100644 index 000000000..ae74c174d --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug675371/test.js @@ -0,0 +1 @@ +active = true; diff --git a/toolkit/mozapps/extensions/test/addons/test_bug740612_1/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_bug740612_1/bootstrap.js new file mode 100644 index 000000000..6703e7f7d --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug740612_1/bootstrap.js @@ -0,0 +1 @@ +const APP_STARTUP = 1; diff --git a/toolkit/mozapps/extensions/test/addons/test_bug740612_1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug740612_1/install.rdf new file mode 100644 index 000000000..b2316273f --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug740612_1/install.rdf @@ -0,0 +1,24 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug740612_1@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:bootstrap>true</em:bootstrap> + + <!-- Front End MetaData --> + <em:name>Test Bootstrap 1</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug740612_2/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_bug740612_2/bootstrap.js new file mode 100644 index 000000000..2ad481453 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug740612_2/bootstrap.js @@ -0,0 +1,23 @@ +Components.utils.import("resource://gre/modules/Services.jsm"); + +const VERSION = "1.0"; + +function install(data, reason) { + Services.prefs.setIntPref("bootstraptest.installed_version", VERSION); + Services.prefs.setIntPref("bootstraptest.install_reason", reason); +} + +function startup(data, reason) { + Services.prefs.setIntPref("bootstraptest.active_version", VERSION); + Services.prefs.setIntPref("bootstraptest.startup_reason", reason); +} + +function shutdown(data, reason) { + Services.prefs.setIntPref("bootstraptest.active_version", 0); + Services.prefs.setIntPref("bootstraptest.shutdown_reason", reason); +} + +function uninstall(data, reason) { + Services.prefs.setIntPref("bootstraptest.installed_version", 0); + Services.prefs.setIntPref("bootstraptest.uninstall_reason", reason); +} diff --git a/toolkit/mozapps/extensions/test/addons/test_bug740612_2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug740612_2/install.rdf new file mode 100644 index 000000000..ff4d613ef --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug740612_2/install.rdf @@ -0,0 +1,24 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug740612_2@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:bootstrap>true</em:bootstrap> + + <!-- Front End MetaData --> + <em:name>Test Bootstrap 2</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_bug757663/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug757663/install.rdf new file mode 100644 index 000000000..be8d85b1b --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug757663/install.rdf @@ -0,0 +1,24 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug757663@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:bootstrap>true</em:bootstrap> + + <!-- Front End MetaData --> + <em:name>Test Bootstrap 1</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_cacheflush1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_cacheflush1/install.rdf new file mode 100644 index 000000000..5e64b65c1 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_cacheflush1/install.rdf @@ -0,0 +1,22 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon1@tests.mozilla.org</em:id> + <em:version>2.0</em:version> + + <!-- Front End MetaData --> + <em:name>File Pointer Test</em:name> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_cacheflush2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_cacheflush2/install.rdf new file mode 100644 index 000000000..7728002ea --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_cacheflush2/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon2@tests.mozilla.org</em:id> + <em:version>2.0</em:version> + + <!-- Front End MetaData --> + <em:name>File Pointer Test</em:name> + <em:bootstrap>true</em:bootstrap> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_chromemanifest_1/chrome.manifest b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_1/chrome.manifest new file mode 100644 index 000000000..4d63b6b06 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_1/chrome.manifest @@ -0,0 +1,6 @@ +content test-addon-1 chrome/content +# comment! + locale test-addon-1 en-US locale/en-US + # commentaire! + locale test-addon-1 fr-FR locale/fr-FR +overlay chrome://browser/content/browser.xul chrome://test-addon-1/content/overlay.xul diff --git a/toolkit/mozapps/extensions/test/addons/test_chromemanifest_1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_1/install.rdf new file mode 100644 index 000000000..486be8670 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_1/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon1@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <!-- Front End MetaData --> + <em:name>Test 1</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_chromemanifest_2/chrome.manifest b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_2/chrome.manifest new file mode 100644 index 000000000..3b0195077 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_2/chrome.manifest @@ -0,0 +1,7 @@ +content test-addon-1 chrome/content + + locale test-addon-1 en-US locale/en-US + locale test-addon-1 fr-FR locale/fr-FR +overlay chrome://browser/content/browser.xul chrome://test-addon-1/content/overlay.xul +binary-component components/something.so +manifest thisdoesntexist.manifest diff --git a/toolkit/mozapps/extensions/test/addons/test_chromemanifest_2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_2/install.rdf new file mode 100644 index 000000000..9a9ee4823 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_2/install.rdf @@ -0,0 +1,24 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon2@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <!-- Front End MetaData --> + <em:name>Test 2</em:name> + <em:description>Test Description</em:description> + <em:unpack>true</em:unpack> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_chromemanifest_3/chrome.manifest b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_3/chrome.manifest new file mode 100644 index 000000000..73190ed8f --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_3/chrome.manifest @@ -0,0 +1,9 @@ +content test-addon-1 chrome/content + + locale test-addon-1 en-US locale/en-US + locale test-addon-1 fr-FR locale/fr-FR +overlay chrome://browser/content/browser.xul chrome://test-addon-1/content/overlay.xul + + binary-component components/something.so + + manifest jar:inner.jar!/nested.manifest diff --git a/toolkit/mozapps/extensions/test/addons/test_chromemanifest_3/inner.jar b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_3/inner.jar Binary files differnew file mode 100644 index 000000000..b4a40052f --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_3/inner.jar diff --git a/toolkit/mozapps/extensions/test/addons/test_chromemanifest_3/install.rdf b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_3/install.rdf new file mode 100644 index 000000000..3a4a709e0 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_3/install.rdf @@ -0,0 +1,24 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon3@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <!-- Front End MetaData --> + <em:name>Test 3</em:name> + <em:description>Test Description</em:description> + <em:unpack>true</em:unpack> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_chromemanifest_4/chrome.manifest b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_4/chrome.manifest new file mode 100644 index 000000000..60d4f01f0 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_4/chrome.manifest @@ -0,0 +1,6 @@ +content test-addon-1 chrome/content + + locale test-addon-1 en-US locale/en-US + locale test-addon-1 fr-FR locale/fr-FR +overlay chrome://browser/content/browser.xul chrome://test-addon-1/content/overlay.xul + manifest components/components.manifest diff --git a/toolkit/mozapps/extensions/test/addons/test_chromemanifest_4/components/components.manifest b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_4/components/components.manifest new file mode 100644 index 000000000..1e0aea440 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_4/components/components.manifest @@ -0,0 +1,2 @@ +binary-component mycomponent.dll +manifest other/something.manifest diff --git a/toolkit/mozapps/extensions/test/addons/test_chromemanifest_4/components/other/something.manifest b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_4/components/other/something.manifest new file mode 100644 index 000000000..73d58dd66 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_4/components/other/something.manifest @@ -0,0 +1 @@ +binary-component thermalnuclearwar.dll
diff --git a/toolkit/mozapps/extensions/test/addons/test_chromemanifest_4/install.rdf b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_4/install.rdf new file mode 100644 index 000000000..463e3f27e --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_4/install.rdf @@ -0,0 +1,24 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon4@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <!-- Front End MetaData --> + <em:name>Test 4</em:name> + <em:description>Test Description</em:description> + <em:unpack>true</em:unpack> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_chromemanifest_5/chrome.manifest b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_5/chrome.manifest new file mode 100644 index 000000000..b0aa32adc --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_5/chrome.manifest @@ -0,0 +1,7 @@ +content test-addon-1 chrome/content + + locale test-addon-1 en-US locale/en-US + locale test-addon-1 fr-FR locale/fr-FR +overlay chrome://browser/content/browser.xul chrome://test-addon-1/content/overlay.xul + + binary-component components/something.so diff --git a/toolkit/mozapps/extensions/test/addons/test_chromemanifest_5/install.rdf b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_5/install.rdf new file mode 100644 index 000000000..7836bced8 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_5/install.rdf @@ -0,0 +1,24 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon5@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <!-- Front End MetaData --> + <em:name>Test 5</em:name> + <em:description>Test Description</em:description> + <em:unpack>false</em:unpack> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_chromemanifest_6/chrome.manifest b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_6/chrome.manifest new file mode 100644 index 000000000..4ebb75c30 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_6/chrome.manifest @@ -0,0 +1 @@ +resource test-addon-1 . diff --git a/toolkit/mozapps/extensions/test/addons/test_chromemanifest_6/install.rdf b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_6/install.rdf new file mode 100644 index 000000000..5d94de0ea --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_chromemanifest_6/install.rdf @@ -0,0 +1,24 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon6@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <!-- Front End MetaData --> + <em:name>Test 6</em:name> + <em:description>Test Description</em:description> + <em:bootstrap>true</em:bootstrap> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_data_directory/install.rdf b/toolkit/mozapps/extensions/test/addons/test_data_directory/install.rdf new file mode 100644 index 000000000..aebfe3b68 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_data_directory/install.rdf @@ -0,0 +1,22 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>datadirectory1@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <!-- Front End MetaData --> + <em:name>Test Data Directory 1</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_db_sanity_1_1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_db_sanity_1_1/install.rdf new file mode 100644 index 000000000..e1f2b5173 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_db_sanity_1_1/install.rdf @@ -0,0 +1,58 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>test_db_sanity_1@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:bootstrap>true</em:bootstrap> + + <em:name>Test 1</em:name> + <em:description>Test Description</em:description> + <em:creator>Keyboard Cat</em:creator> + <em:homepageURL>http://mozilla.org/</em:homepageURL> + + <em:contributor>Keyboard Cat 2</em:contributor> + <em:translator>Keyboard Cat 3</em:translator> + + <em:localized> + <Description> + <em:locale>en-1</em:locale> + <em:name>Test 1 (en-1)</em:name> + <em:description>Test Description (en-1)</em:description> + <em:creator>Keyboard Cat (en-1)</em:creator> + <em:homepageURL>http://mozilla.org/en-1/</em:homepageURL> + </Description> + </em:localized> + + <em:localized> + <Description> + <em:locale>en-2</em:locale> + <em:name>Test 1 (en-2)</em:name> + <em:description>Test Description (en-2)</em:description> + <em:creator>Keyboard Cat (en-2)</em:creator> + <em:homepageURL>http://mozilla.org/en-2/</em:homepageURL> + </Description> + </em:localized> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + <em:targetApplication> + <Description> + <em:id>keyboard-cats-awesome-browser@keyboard.cat</em:id> + <em:minVersion>3.1415</em:minVersion> + <em:maxVersion>3.1415</em:maxVersion> + </Description> + </em:targetApplication> + + <em:targetPlatform>XPCShell_noarch-spidermonkey</em:targetPlatform> + <em:targetPlatform>WINNT_x86</em:targetPlatform> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_db_sanity_1_2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_db_sanity_1_2/install.rdf new file mode 100644 index 000000000..da9b067ab --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_db_sanity_1_2/install.rdf @@ -0,0 +1,59 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>test_db_sanity_1@tests.mozilla.org</em:id> + <em:version>2.0</em:version> + <em:bootstrap>true</em:bootstrap> + + <em:name>Test 1</em:name> + <em:description>Test Description!!!</em:description> + <em:creator>Keyboard Cat</em:creator> + <em:homepageURL>http://mozilla.org/</em:homepageURL> + + <em:contributor>Keyboard Cat 2</em:contributor> + <em:translator>Keyboard Cat 3</em:translator> + <em:translator>Keyboard Cat 4</em:translator> + + <em:localized> + <Description> + <em:locale>en-1</em:locale> + <em:name>Test 1 (en-1)</em:name> + <em:description>Test Description (en-1)</em:description> + <em:creator>Keyboard Cat (en-1)</em:creator> + <em:homepageURL>http://mozilla.org/en-1/</em:homepageURL> + </Description> + </em:localized> + + <em:localized> + <Description> + <em:locale>en-3</em:locale> + <em:name>Test 1 (en-3)</em:name> + <em:description>Test Description (en-3)</em:description> + <em:creator>Keyboard Cat (en-3)</em:creator> + <em:homepageURL>http://mozilla.org/en-3/</em:homepageURL> + </Description> + </em:localized> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + <em:targetApplication> + <Description> + <em:id>keyboard-cats-awesome-browser-3000@keyboard.cat</em:id> + <em:minVersion>3.1415</em:minVersion> + <em:maxVersion>3.1415</em:maxVersion> + </Description> + </em:targetApplication> + + <em:targetPlatform>XPCShell_noarch-spidermonkey</em:targetPlatform> + <em:targetPlatform>WINNT_i386</em:targetPlatform> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_dictionary/dictionaries/ab-CD.dic b/toolkit/mozapps/extensions/test/addons/test_dictionary/dictionaries/ab-CD.dic new file mode 100644 index 000000000..3feac546d --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_dictionary/dictionaries/ab-CD.dic @@ -0,0 +1,2 @@ +1 +test1 diff --git a/toolkit/mozapps/extensions/test/addons/test_dictionary/install.rdf b/toolkit/mozapps/extensions/test/addons/test_dictionary/install.rdf new file mode 100644 index 000000000..9e66ab237 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_dictionary/install.rdf @@ -0,0 +1,25 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>ab-CD@dictionaries.addons.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:type>64</em:type> + <em:unpack>true</em:unpack> + + <!-- Front End MetaData --> + <em:name>Test Dictionary</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_dictionary_2/dictionaries/ab-CD.dic b/toolkit/mozapps/extensions/test/addons/test_dictionary_2/dictionaries/ab-CD.dic new file mode 100644 index 000000000..b35b9c1a6 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_dictionary_2/dictionaries/ab-CD.dic @@ -0,0 +1,2 @@ +1 +test2 diff --git a/toolkit/mozapps/extensions/test/addons/test_dictionary_2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_dictionary_2/install.rdf new file mode 100644 index 000000000..a74a114fd --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_dictionary_2/install.rdf @@ -0,0 +1,24 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>ab-CD@dictionaries.addons.mozilla.org</em:id> + <em:version>2.0</em:version> + <em:unpack>true</em:unpack> + + <!-- Front End MetaData --> + <em:name>Test Dictionary</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_dictionary_3/install.rdf b/toolkit/mozapps/extensions/test/addons/test_dictionary_3/install.rdf new file mode 100644 index 000000000..c056e87ff --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_dictionary_3/install.rdf @@ -0,0 +1,25 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>ab-CD@dictionaries.addons.mozilla.org</em:id> + <em:version>2.0</em:version> + <em:type>64</em:type> + <em:unpack>true</em:unpack> + + <!-- Front End MetaData --> + <em:name>Test Dictionary</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_dictionary_4/install.rdf b/toolkit/mozapps/extensions/test/addons/test_dictionary_4/install.rdf new file mode 100644 index 000000000..7470284ba --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_dictionary_4/install.rdf @@ -0,0 +1,24 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>ef@dictionaries.addons.mozilla.org</em:id> + <em:version>2.0</em:version> + <em:unpack>true</em:unpack> + + <!-- Front End MetaData --> + <em:name>Test Dictionary ef</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_dictionary_5/install.rdf b/toolkit/mozapps/extensions/test/addons/test_dictionary_5/install.rdf new file mode 100644 index 000000000..11eba90d7 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_dictionary_5/install.rdf @@ -0,0 +1,25 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>gh@dictionaries.addons.mozilla.org</em:id> + <em:version>2.0</em:version> + <em:type>64</em:type> + <em:unpack>true</em:unpack> + + <!-- Front End MetaData --> + <em:name>Test Dictionary gh</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_distribution1_2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_distribution1_2/install.rdf new file mode 100644 index 000000000..8bd5966c9 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_distribution1_2/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon1@tests.mozilla.org</em:id> + <em:version>2.0</em:version> + + <!-- Front End MetaData --> + <em:name>Distributed add-ons test</em:name> + <em:bootstrap>true</em:bootstrap> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>5</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_experiment1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_experiment1/install.rdf new file mode 100644 index 000000000..414a36b30 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_experiment1/install.rdf @@ -0,0 +1,16 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>experiment1@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:type>128</em:type> + + <!-- Front End MetaData --> + <em:name>Test Experiment 1</em:name> + <em:description>Test Description</em:description> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_filepointer/install.rdf b/toolkit/mozapps/extensions/test/addons/test_filepointer/install.rdf new file mode 100644 index 000000000..5e64b65c1 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_filepointer/install.rdf @@ -0,0 +1,22 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon1@tests.mozilla.org</em:id> + <em:version>2.0</em:version> + + <!-- Front End MetaData --> + <em:name>File Pointer Test</em:name> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_getresource/icon.png b/toolkit/mozapps/extensions/test/addons/test_getresource/icon.png new file mode 100644 index 000000000..40765b0e2 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_getresource/icon.png @@ -0,0 +1 @@ +Dummy icon file
\ No newline at end of file diff --git a/toolkit/mozapps/extensions/test/addons/test_getresource/install.rdf b/toolkit/mozapps/extensions/test/addons/test_getresource/install.rdf new file mode 100644 index 000000000..8d2740dbb --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_getresource/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon1@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <!-- Front End MetaData --> + <em:name>Test 1</em:name> + <em:description>Test Description</em:description> + <em:bootstrap>true</em:bootstrap> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_getresource/subdir/subfile.txt b/toolkit/mozapps/extensions/test/addons/test_getresource/subdir/subfile.txt new file mode 100644 index 000000000..a28d18162 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_getresource/subdir/subfile.txt @@ -0,0 +1 @@ +Dummy file in subdirectory
\ No newline at end of file diff --git a/toolkit/mozapps/extensions/test/addons/test_install1/icon.png b/toolkit/mozapps/extensions/test/addons/test_install1/icon.png new file mode 100644 index 000000000..41409edfe --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_install1/icon.png @@ -0,0 +1 @@ +Fake icon image diff --git a/toolkit/mozapps/extensions/test/addons/test_install1/icon64.png b/toolkit/mozapps/extensions/test/addons/test_install1/icon64.png new file mode 100644 index 000000000..41409edfe --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_install1/icon64.png @@ -0,0 +1 @@ +Fake icon image diff --git a/toolkit/mozapps/extensions/test/addons/test_install1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_install1/install.rdf new file mode 100644 index 000000000..efe3f18ae --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_install1/install.rdf @@ -0,0 +1,24 @@ +<?xml version="1.0"?> + +<!-- An extension that is compatible with the XPCShell test suite --> +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon1@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <!-- Front End MetaData --> + <em:name>Test 1</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_install2_1/icon.png b/toolkit/mozapps/extensions/test/addons/test_install2_1/icon.png new file mode 100644 index 000000000..41409edfe --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_install2_1/icon.png @@ -0,0 +1 @@ +Fake icon image diff --git a/toolkit/mozapps/extensions/test/addons/test_install2_1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_install2_1/install.rdf new file mode 100644 index 000000000..116eb7069 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_install2_1/install.rdf @@ -0,0 +1,24 @@ +<?xml version="1.0"?> + +<!-- An extension that is compatible with the XPCShell test suite --> +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon2@tests.mozilla.org</em:id> + <em:version>2.0</em:version> + + <!-- Front End MetaData --> + <em:name>Real Test 2</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_install2_2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_install2_2/install.rdf new file mode 100644 index 000000000..7197ea1fb --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_install2_2/install.rdf @@ -0,0 +1,24 @@ +<?xml version="1.0"?> + +<!-- An extension that is compatible with the XPCShell test suite --> +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon2@tests.mozilla.org</em:id> + <em:version>3.0</em:version> + + <!-- Front End MetaData --> + <em:name>Real Test 3</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_install3/install.rdf b/toolkit/mozapps/extensions/test/addons/test_install3/install.rdf new file mode 100644 index 000000000..8e72017ad --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_install3/install.rdf @@ -0,0 +1,27 @@ +<?xml version="1.0"?> + +<!-- An extension that is incompatible with the XPCShell test suite until + a compatibility update check is performed --> +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon3@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <!-- Front End MetaData --> + <em:name>Real Test 4</em:name> + <em:description>Test Description</em:description> + + <em:updateURL>http://localhost:4444/data/test_install.rdf</em:updateURL> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>0</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_install4/addon4.xpi b/toolkit/mozapps/extensions/test/addons/test_install4/addon4.xpi Binary files differnew file mode 100644 index 000000000..e57a4f5b6 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_install4/addon4.xpi diff --git a/toolkit/mozapps/extensions/test/addons/test_install4/addon5.jar b/toolkit/mozapps/extensions/test/addons/test_install4/addon5.jar Binary files differnew file mode 100644 index 000000000..93fbfbe6e --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_install4/addon5.jar diff --git a/toolkit/mozapps/extensions/test/addons/test_install4/addon6.xpi b/toolkit/mozapps/extensions/test/addons/test_install4/addon6.xpi Binary files differnew file mode 100644 index 000000000..3613dab04 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_install4/addon6.xpi diff --git a/toolkit/mozapps/extensions/test/addons/test_install4/addon7.jar b/toolkit/mozapps/extensions/test/addons/test_install4/addon7.jar Binary files differnew file mode 100644 index 000000000..1af178887 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_install4/addon7.jar diff --git a/toolkit/mozapps/extensions/test/addons/test_install4/badaddon.jar b/toolkit/mozapps/extensions/test/addons/test_install4/badaddon.jar new file mode 100644 index 000000000..33695b99f --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_install4/badaddon.jar @@ -0,0 +1 @@ +This is corrupt diff --git a/toolkit/mozapps/extensions/test/addons/test_install4/badaddon.xpi b/toolkit/mozapps/extensions/test/addons/test_install4/badaddon.xpi new file mode 100644 index 000000000..33695b99f --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_install4/badaddon.xpi @@ -0,0 +1 @@ +This is corrupt diff --git a/toolkit/mozapps/extensions/test/addons/test_install4/icon.png b/toolkit/mozapps/extensions/test/addons/test_install4/icon.png new file mode 100644 index 000000000..57f2c2eb6 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_install4/icon.png @@ -0,0 +1 @@ +This is ignored diff --git a/toolkit/mozapps/extensions/test/addons/test_install4/install.rdf b/toolkit/mozapps/extensions/test/addons/test_install4/install.rdf new file mode 100644 index 000000000..5e99ae29a --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_install4/install.rdf @@ -0,0 +1,10 @@ +<?xml version="1.0"?> + +<!-- A multi-package XPI --> +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:type>32</em:type> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_install5/chrome.manifest b/toolkit/mozapps/extensions/test/addons/test_install5/chrome.manifest new file mode 100644 index 000000000..703adf2a7 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_install5/chrome.manifest @@ -0,0 +1 @@ +binary-component components/mycomponent.so
diff --git a/toolkit/mozapps/extensions/test/addons/test_install5/install.rdf b/toolkit/mozapps/extensions/test/addons/test_install5/install.rdf new file mode 100644 index 000000000..1f96e4b49 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_install5/install.rdf @@ -0,0 +1,26 @@ +<?xml version="1.0"?> + +<!-- An extension that is incompatible with the XPCShell test suite and + has binary components, so won't be compatible-by-default. --> +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon5@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <!-- Front End MetaData --> + <em:name>Real Test 5</em:name> + <em:description>Test Description</em:description> + <em:unpack>true</em:unpack> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>0</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_install6/install.rdf b/toolkit/mozapps/extensions/test/addons/test_install6/install.rdf new file mode 100644 index 000000000..b1f97c1fd --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_install6/install.rdf @@ -0,0 +1,24 @@ +<?xml version="1.0"?> + +<!-- An extension that has a compatibility override making it incompatible. --> +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon6@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <!-- Front End MetaData --> + <em:name>Addon Test 6</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_jetpack/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_jetpack/bootstrap.js new file mode 100644 index 000000000..2449baeb8 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_jetpack/bootstrap.js @@ -0,0 +1,17 @@ +Components.utils.import("resource://gre/modules/Services.jsm"); + +function install(data, reason) { + Services.prefs.setIntPref("jetpacktest.installed_version", 1); +} + +function startup(data, reason) { + Services.prefs.setIntPref("jetpacktest.active_version", 1); +} + +function shutdown(data, reason) { + Services.prefs.setIntPref("jetpacktest.active_version", 0); +} + +function uninstall(data, reason) { + Services.prefs.setIntPref("jetpacktest.installed_version", 0); +} diff --git a/toolkit/mozapps/extensions/test/addons/test_jetpack/harness-options.json b/toolkit/mozapps/extensions/test/addons/test_jetpack/harness-options.json new file mode 100644 index 000000000..9e26dfeeb --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_jetpack/harness-options.json @@ -0,0 +1 @@ +{}
\ No newline at end of file diff --git a/toolkit/mozapps/extensions/test/addons/test_jetpack/install.rdf b/toolkit/mozapps/extensions/test/addons/test_jetpack/install.rdf new file mode 100644 index 000000000..e88794a60 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_jetpack/install.rdf @@ -0,0 +1,28 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>jetpack@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:bootstrap>true</em:bootstrap> + + <!-- Front End MetaData --> + <em:name>Test jetpack</em:name> + <em:description>Test Description</em:description> + + <em:iconURL>chrome://foo/skin/icon.png</em:iconURL> + <em:aboutURL>chrome://foo/content/about.xul</em:aboutURL> + <em:optionsURL>chrome://foo/content/options.xul</em:optionsURL> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_langpack/chrome.manifest b/toolkit/mozapps/extensions/test/addons/test_langpack/chrome.manifest new file mode 100644 index 000000000..16fe819a2 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_langpack/chrome.manifest @@ -0,0 +1 @@ +locale test-langpack x-testing locale/x-testing diff --git a/toolkit/mozapps/extensions/test/addons/test_langpack/install.rdf b/toolkit/mozapps/extensions/test/addons/test_langpack/install.rdf new file mode 100644 index 000000000..056f6dff5 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_langpack/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>langpack-x-testing@tests.mozilla.org</em:id> + <em:type>8</em:type> + <em:version>1.0</em:version> + + <!-- Front End MetaData --> + <em:name>Language Pack x-testing</em:name> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_locale/install.rdf b/toolkit/mozapps/extensions/test/addons/test_locale/install.rdf new file mode 100644 index 000000000..d8d027b93 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_locale/install.rdf @@ -0,0 +1,61 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon1@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + <em:localized> + <Description em:locale="fr-FR"> + <em:locale/> <!-- Should be ignored and not fail --> + <em:name>fr-FR Name</em:name> + <em:description>fr-FR Description</em:description> + <em:contributor>Fr Contributor 1</em:contributor> + <em:contributor>Fr Contributor 2</em:contributor> + <em:contributor>Fr Contributor 3</em:contributor> + </Description> + </em:localized> + + <em:localized> + <Description em:locale="de-DE"> + <em:name>de-DE Name</em:name> + </Description> + </em:localized> + + <em:localized> + <Description em:locale="es-ES"> + <em:name>es-ES Name</em:name> + <em:description>es-ES Description</em:description> + </Description> + </em:localized> + + <!-- Subsequent definitions for the same locale should be ignored --> + <em:localized> + <Description em:locale="fr-FR"> + <em:name>Repeated locale</em:name> + </Description> + </em:localized> + + <!-- Properties with no listed locale should be ignored --> + <em:localized> + <Description> + <em:name>Missing locale</em:name> + </Description> + </em:localized> + + <!-- Front End MetaData --> + <em:name>Fallback Name</em:name> + <em:description>Fallback Description</em:description> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_locked2_5/install.rdf b/toolkit/mozapps/extensions/test/addons/test_locked2_5/install.rdf new file mode 100644 index 000000000..09655c2a6 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_locked2_5/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon5@tests.mozilla.org</em:id> + <em:version>2.0</em:version> + + <!-- Front End MetaData --> + <em:name>Test 5</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>2</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_locked2_6/install.rdf b/toolkit/mozapps/extensions/test/addons/test_locked2_6/install.rdf new file mode 100644 index 000000000..75f110d2a --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_locked2_6/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon6@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <!-- Front End MetaData --> + <em:name>Test 6</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>2</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_migrate4_6/install.rdf b/toolkit/mozapps/extensions/test/addons/test_migrate4_6/install.rdf new file mode 100644 index 000000000..5924982f7 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_migrate4_6/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon6@tests.mozilla.org</em:id> + <em:version>2.0</em:version> + + <!-- Front End MetaData --> + <em:name>Test 6</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_migrate4_7/install.rdf b/toolkit/mozapps/extensions/test/addons/test_migrate4_7/install.rdf new file mode 100644 index 000000000..072751cf2 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_migrate4_7/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon7@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <!-- Front End MetaData --> + <em:name>Test 7</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_migrate6/install.rdf b/toolkit/mozapps/extensions/test/addons/test_migrate6/install.rdf new file mode 100644 index 000000000..ff8280ae3 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_migrate6/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon6@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <!-- Front End MetaData --> + <em:name>Test 6</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_migrate7/install.rdf b/toolkit/mozapps/extensions/test/addons/test_migrate7/install.rdf new file mode 100644 index 000000000..fd1df0e08 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_migrate7/install.rdf @@ -0,0 +1,24 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon7@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <!-- Front End MetaData --> + <em:name>Test 7</em:name> + <em:description>Test Description</em:description> + <em:unpack>true</em:unpack> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_migrate8/chrome.manifest b/toolkit/mozapps/extensions/test/addons/test_migrate8/chrome.manifest new file mode 100644 index 000000000..8570bae82 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_migrate8/chrome.manifest @@ -0,0 +1,6 @@ +content test-addon-1 chrome/content + + locale test-addon-1 en-US locale/en-US + locale test-addon-1 fr-FR locale/fr-FR +overlay chrome://browser/content/browser.xul chrome://test-addon-1/content/overlay.xul +binary-component components/something.so diff --git a/toolkit/mozapps/extensions/test/addons/test_migrate8/install.rdf b/toolkit/mozapps/extensions/test/addons/test_migrate8/install.rdf new file mode 100644 index 000000000..61ed24763 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_migrate8/install.rdf @@ -0,0 +1,24 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon8@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <!-- Front End MetaData --> + <em:name>Test 8</em:name> + <em:description>Test Description</em:description> + <em:unpack>true</em:unpack> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_migrate9/install.rdf b/toolkit/mozapps/extensions/test/addons/test_migrate9/install.rdf new file mode 100644 index 000000000..116dd0176 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_migrate9/install.rdf @@ -0,0 +1,26 @@ +<?xml version="1.0"?>
+
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+
+ <Description about="urn:mozilla:install-manifest">
+ <em:id>addon9@tests.mozilla.org</em:id>
+ <em:version>1.0</em:version>
+ <em:internalName>theme1/1.0</em:internalName>
+
+ <!-- Front End MetaData -->
+ <em:name>Test Theme 1</em:name>
+ <em:description>Test Description</em:description>
+
+ <em:targetApplication>
+ <Description>
+ <em:id>xpcshell@tests.mozilla.org</em:id>
+ <em:minVersion>1</em:minVersion>
+ <em:maxVersion>2</em:maxVersion>
+ </Description>
+ </em:targetApplication>
+
+ <em:skinnable>true</em:skinnable>
+
+ </Description>
+</RDF>
diff --git a/toolkit/mozapps/extensions/test/addons/test_theme/install.rdf b/toolkit/mozapps/extensions/test/addons/test_theme/install.rdf new file mode 100644 index 000000000..e1a37d0a4 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_theme/install.rdf @@ -0,0 +1,26 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>theme1@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:internalName>theme1/1.0</em:internalName> + + <!-- Front End MetaData --> + <em:name>Test Theme 1</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + + <em:skinnable>true</em:skinnable> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_theme/preview.png b/toolkit/mozapps/extensions/test/addons/test_theme/preview.png new file mode 100644 index 000000000..321ce47cf --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_theme/preview.png @@ -0,0 +1 @@ +Fake preview image diff --git a/toolkit/mozapps/extensions/test/addons/test_undoincompatible/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_undoincompatible/bootstrap.js new file mode 100644 index 000000000..1666f2972 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_undoincompatible/bootstrap.js @@ -0,0 +1 @@ +Components.utils.import("resource://xpcshell-data/BootstrapMonitor.jsm").monitor(this); diff --git a/toolkit/mozapps/extensions/test/addons/test_undoincompatible/install.rdf b/toolkit/mozapps/extensions/test/addons/test_undoincompatible/install.rdf new file mode 100644 index 000000000..b038ebc51 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_undoincompatible/install.rdf @@ -0,0 +1,28 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>incompatible@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:bootstrap>true</em:bootstrap> + + <!-- Front End MetaData --> + <em:name>Incompatible Addon</em:name> + <em:description>I am incompatible</em:description> + + <em:iconURL>chrome://foo/skin/icon.png</em:iconURL> + <em:aboutURL>chrome://foo/content/about.xul</em:aboutURL> + <em:optionsURL>chrome://foo/content/options.xul</em:optionsURL> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>2</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_undouninstall1/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_undouninstall1/bootstrap.js new file mode 100644 index 000000000..1666f2972 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_undouninstall1/bootstrap.js @@ -0,0 +1 @@ +Components.utils.import("resource://xpcshell-data/BootstrapMonitor.jsm").monitor(this); diff --git a/toolkit/mozapps/extensions/test/addons/test_undouninstall1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_undouninstall1/install.rdf new file mode 100644 index 000000000..4178fe929 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_undouninstall1/install.rdf @@ -0,0 +1,28 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>undouninstall1@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:bootstrap>true</em:bootstrap> + + <!-- Front End MetaData --> + <em:name>Test Bootstrap 1</em:name> + <em:description>Test Description</em:description> + + <em:iconURL>chrome://foo/skin/icon.png</em:iconURL> + <em:aboutURL>chrome://foo/content/about.xul</em:aboutURL> + <em:optionsURL>chrome://foo/content/options.xul</em:optionsURL> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_update/install.rdf b/toolkit/mozapps/extensions/test/addons/test_update/install.rdf new file mode 100644 index 000000000..801a35a8f --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_update/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon1@tests.mozilla.org</em:id> + <em:version>2.0</em:version> + + <!-- Front End MetaData --> + <em:name>Test 1</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_update12/install.rdf b/toolkit/mozapps/extensions/test/addons/test_update12/install.rdf new file mode 100644 index 000000000..3589cb55c --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_update12/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon12@tests.mozilla.org</em:id> + <em:version>2.0</em:version> + + <!-- Front End MetaData --> + <em:name>Test 12</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_update8/install.rdf b/toolkit/mozapps/extensions/test/addons/test_update8/install.rdf new file mode 100644 index 000000000..43e31af42 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_update8/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon8@tests.mozilla.org</em:id> + <em:version>2.0</em:version> + + <!-- Front End MetaData --> + <em:name>Test 8</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_updateid2_2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_updateid2_2/install.rdf new file mode 100644 index 000000000..5982b9868 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_updateid2_2/install.rdf @@ -0,0 +1,24 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon2@tests.mozilla.org</em:id> + <em:version>2.0</em:version> + <em:updateURL>http://localhost:4444/data/test_updateid.rdf</em:updateURL> + + <!-- Front End MetaData --> + <em:name>Test 2</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_updateid2_5/install.rdf b/toolkit/mozapps/extensions/test/addons/test_updateid2_5/install.rdf new file mode 100644 index 000000000..e923a5289 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_updateid2_5/install.rdf @@ -0,0 +1,24 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon2@tests.mozilla.org</em:id> + <em:version>5.0</em:version> + <em:updateURL>http://localhost:4444/data/test_updateid.rdf</em:updateURL> + + <!-- Front End MetaData --> + <em:name>Test 2</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_updateid3_3/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_updateid3_3/bootstrap.js new file mode 100644 index 000000000..c28d75925 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_updateid3_3/bootstrap.js @@ -0,0 +1,21 @@ +Components.utils.import("resource://gre/modules/Services.jsm"); + +function install(data, reason) { + Services.prefs.setIntPref("bootstraptest.installed_version", 3); + Services.prefs.setIntPref("bootstraptest.install_reason", reason); +} + +function startup(data, reason) { + Services.prefs.setIntPref("bootstraptest.active_version", 3); + Services.prefs.setIntPref("bootstraptest.startup_reason", reason); +} + +function shutdown(data, reason) { + Services.prefs.setIntPref("bootstraptest.active_version", 0); + Services.prefs.setIntPref("bootstraptest.shutdown_reason", reason); +} + +function uninstall(data, reason) { + Services.prefs.setIntPref("bootstraptest.installed_version", 0); + Services.prefs.setIntPref("bootstraptest.uninstall_reason", reason); +} diff --git a/toolkit/mozapps/extensions/test/addons/test_updateid3_3/install.rdf b/toolkit/mozapps/extensions/test/addons/test_updateid3_3/install.rdf new file mode 100644 index 000000000..ffed064cf --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_updateid3_3/install.rdf @@ -0,0 +1,25 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon3@tests.mozilla.org</em:id> + <em:version>3.0</em:version> + <em:updateURL>http://localhost:4444/data/test_updateid.rdf</em:updateURL> + <em:bootstrap>true</em:bootstrap> + + <!-- Front End MetaData --> + <em:name>Test 3</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/test_updateid4_4/bootstrap.js b/toolkit/mozapps/extensions/test/addons/test_updateid4_4/bootstrap.js new file mode 100644 index 000000000..6b1753cb2 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_updateid4_4/bootstrap.js @@ -0,0 +1,21 @@ +Components.utils.import("resource://gre/modules/Services.jsm"); + +function install(data, reason) { + Services.prefs.setIntPref("bootstraptest.installed_version", 4); + Services.prefs.setIntPref("bootstraptest.install_reason", reason); +} + +function startup(data, reason) { + Services.prefs.setIntPref("bootstraptest.active_version", 4); + Services.prefs.setIntPref("bootstraptest.startup_reason", reason); +} + +function shutdown(data, reason) { + Services.prefs.setIntPref("bootstraptest.active_version", 0); + Services.prefs.setIntPref("bootstraptest.shutdown_reason", reason); +} + +function uninstall(data, reason) { + Services.prefs.setIntPref("bootstraptest.installed_version", 0); + Services.prefs.setIntPref("bootstraptest.uninstall_reason", reason); +} diff --git a/toolkit/mozapps/extensions/test/addons/test_updateid4_4/install.rdf b/toolkit/mozapps/extensions/test/addons/test_updateid4_4/install.rdf new file mode 100644 index 000000000..b354ac5c1 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_updateid4_4/install.rdf @@ -0,0 +1,25 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon4@tests.mozilla.org</em:id> + <em:version>4.0</em:version> + <em:updateURL>http://localhost:4444/data/test_updateid.rdf</em:updateURL> + <em:bootstrap>true</em:bootstrap> + + <!-- Front End MetaData --> + <em:name>Test 4</em:name> + <em:description>Test Description</em:description> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/upgradeable1x2-3_1/install.rdf b/toolkit/mozapps/extensions/test/addons/upgradeable1x2-3_1/install.rdf new file mode 100644 index 000000000..76e662977 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/upgradeable1x2-3_1/install.rdf @@ -0,0 +1,22 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>upgradeable1x2-3@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Test min 1 max 2 upgrade to 3</em:name> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/addons/upgradeable1x2-3_2/install.rdf b/toolkit/mozapps/extensions/test/addons/upgradeable1x2-3_2/install.rdf new file mode 100644 index 000000000..e57672c42 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/upgradeable1x2-3_2/install.rdf @@ -0,0 +1,22 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>upgradeable1x2-3@tests.mozilla.org</em:id> + <em:version>2.0</em:version> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>3</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Test min 1 max 2 upgrade to 3</em:name> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/Makefile.in b/toolkit/mozapps/extensions/test/browser/Makefile.in new file mode 100644 index 000000000..6bd692d9b --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/Makefile.in @@ -0,0 +1,19 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +ADDONSRC = $(srcdir)/addons +TESTXPI = $(CURDIR)/$(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)/addons + +include $(topsrcdir)/config/rules.mk + +libs:: + rm -rf $(TESTXPI) + $(NSINSTALL) -D $(TESTXPI) + if [ -d $(ADDONSRC) ]; then \ + $(EXIT_ON_ERROR) \ + for dir in $(ADDONSRC)/*; do \ + base=`basename $$dir` ; \ + (cd $$dir && zip -q $(TESTXPI)/$$base.xpi *) \ + done \ + fi diff --git a/toolkit/mozapps/extensions/test/browser/addon_about.xul b/toolkit/mozapps/extensions/test/browser/addon_about.xul new file mode 100644 index 000000000..c2b8b935e --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addon_about.xul @@ -0,0 +1,6 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> +<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + id="addon-test-about-window"> + <label value="Oh hai!"/> +</window> diff --git a/toolkit/mozapps/extensions/test/browser/addon_prefs.xul b/toolkit/mozapps/extensions/test/browser/addon_prefs.xul new file mode 100644 index 000000000..85cfe6b2d --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addon_prefs.xul @@ -0,0 +1,6 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> +<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + id="addon-test-pref-window"> + <label value="Oh hai!"/> +</window> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_1/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_1/install.rdf new file mode 100644 index 000000000..5c164ec07 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_1/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon1@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Addon1</em:name> + <em:bootstrap>true</em:bootstrap> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_10/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_10/install.rdf new file mode 100644 index 000000000..95b6488dd --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_10/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon10@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>0</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Addon10</em:name> + <em:bootstrap>true</em:bootstrap> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_2/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_2/install.rdf new file mode 100644 index 000000000..d02cefac2 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_2/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon2@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>0</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Addon2</em:name> + <em:bootstrap>true</em:bootstrap> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_3/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_3/install.rdf new file mode 100644 index 000000000..23b4813c6 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_3/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon3@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>0</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Addon3</em:name> + <em:bootstrap>true</em:bootstrap> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_4/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_4/install.rdf new file mode 100644 index 000000000..0150fc3c0 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_4/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon4@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Addon4</em:name> + <em:bootstrap>true</em:bootstrap> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_5/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_5/install.rdf new file mode 100644 index 000000000..dfcbf0384 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_5/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon5@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>0</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Addon5</em:name> + <em:bootstrap>true</em:bootstrap> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_6/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_6/install.rdf new file mode 100644 index 000000000..8e1027923 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_6/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon6@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>0</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Addon6</em:name> + <em:bootstrap>true</em:bootstrap> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_7/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_7/install.rdf new file mode 100644 index 000000000..023f9f05f --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_7/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon7@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>0</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Addon7</em:name> + <em:bootstrap>true</em:bootstrap> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_8_1/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_8_1/install.rdf new file mode 100644 index 000000000..57855e094 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_8_1/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon8@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>0</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Addon8</em:name> + <em:bootstrap>true</em:bootstrap> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_9_1/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_9_1/install.rdf new file mode 100644 index 000000000..e1d6554f3 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug557956_9_1/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon9@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>0</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Addon9</em:name> + <em:bootstrap>true</em:bootstrap> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug567127_1/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug567127_1/install.rdf new file mode 100644 index 000000000..f5780d5d3 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug567127_1/install.rdf @@ -0,0 +1,22 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug567127_1@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>browser_bug567127 #1</em:name> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug567127_2/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug567127_2/install.rdf new file mode 100644 index 000000000..84c542cf9 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug567127_2/install.rdf @@ -0,0 +1,22 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>bug567127_2@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>browser_bug567127 #2</em:name> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug596336_1/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug596336_1/install.rdf new file mode 100644 index 000000000..726ffee8b --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug596336_1/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon1@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:bootstrap>true</em:bootstrap> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Bootstrap upgrade test</em:name> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_bug596336_2/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_bug596336_2/install.rdf new file mode 100644 index 000000000..16e4fd0cd --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_bug596336_2/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon1@tests.mozilla.org</em:id> + <em:version>2.0</em:version> + <em:bootstrap>true</em:bootstrap> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Bootstrap upgrade test</em:name> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_dragdrop1/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_dragdrop1/install.rdf new file mode 100644 index 000000000..0a845ed31 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_dragdrop1/install.rdf @@ -0,0 +1,22 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>dragdrop1@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Drag Drop test 1</em:name> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_dragdrop2/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_dragdrop2/install.rdf new file mode 100644 index 000000000..03072fdf4 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_dragdrop2/install.rdf @@ -0,0 +1,22 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>dragdrop2@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Drag Drop test 2</em:name> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_experiment1/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_experiment1/install.rdf new file mode 100644 index 000000000..92f20a4ef --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_experiment1/install.rdf @@ -0,0 +1,16 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>test-experiment1@experiments.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:type>128</em:type> + + <!-- Front End MetaData --> + <em:name>Test Experiment 1</em:name> + <em:description>Test Description</em:description> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1/bootstrap.js b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1/bootstrap.js new file mode 100644 index 000000000..7871af738 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1/bootstrap.js @@ -0,0 +1,8 @@ +function install (params, aReason) { +} +function uninstall (params, aReason) { +} +function startup (params, aReason) { +} +function shutdown (params, aReason) { +} diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1/install.rdf new file mode 100644 index 000000000..2bf7c6e2e --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1/install.rdf @@ -0,0 +1,19 @@ +<?xml version="1.0" ?> +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>inlinesettings1@tests.mozilla.org</em:id> + <em:name>Inline Settings (Bootstrap)</em:name> + <em:version>1</em:version> + <em:bootstrap>true</em:bootstrap> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </Description> + </em:targetApplication> + </Description> + +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1/options.xul b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1/options.xul new file mode 100644 index 000000000..c271c35da --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1/options.xul @@ -0,0 +1,20 @@ +<?xml version="1.0" ?> +<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <setting pref="extensions.inlinesettings1.bool" type="bool" title="Bool" checkboxlabel="Check box label"/> + <setting pref="extensions.inlinesettings1.boolint" type="boolint" on="1" off="2" title="BoolInt"/> + <setting pref="extensions.inlinesettings1.integer" type="integer" title="Integer"/> + <setting pref="extensions.inlinesettings1.string" type="string" title="String"/> + <setting type="control" title="Menulist"> + <menulist sizetopopup="always" oncommand="window._testValue = this.value;"> + <menupopup> + <menuitem label="Alpha" value="1" /> + <menuitem label="Bravo" value="2" /> + <menuitem label="Charlie" value="3" /> + </menupopup> + </menulist> + </setting> + <setting pref="extensions.inlinesettings1.color" type="color" title="Color"/> + <setting pref="extensions.inlinesettings1.file" type="file" title="File"/> + <setting pref="extensions.inlinesettings1.directory" type="directory" title="Directory"/> + <setting pref="extensions.inlinesettings1.integer-size" type="integer" title="Integer with size" size="1" /> +</vbox> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom/binding.xml b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom/binding.xml new file mode 100644 index 000000000..6ac72a03c --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom/binding.xml @@ -0,0 +1,19 @@ +<?xml version="1.0"?> +<bindings xmlns="http://www.mozilla.org/xbl" + xmlns:xbl="http://www.mozilla.org/xbl" + xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <binding id="custom" + extends="chrome://mozapps/content/extensions/setting.xml#setting-base"> + <content> + <xul:vbox> + <xul:hbox class="preferences-alignment"> + <xul:label anonid="label" class="preferences-title" flex="1" xbl:inherits="xbl:text=title"/> + </xul:hbox> + <xul:description class="preferences-description" flex="1" xbl:inherits="xbl:text=desc"/> + </xul:vbox> + <xul:hbox class="preferences-alignment"> + <xul:label anonid="input" value="Woah!"/> + </xul:hbox> + </content> + </binding> +</bindings> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom/bootstrap.js b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom/bootstrap.js new file mode 100644 index 000000000..7871af738 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom/bootstrap.js @@ -0,0 +1,8 @@ +function install (params, aReason) { +} +function uninstall (params, aReason) { +} +function startup (params, aReason) { +} +function shutdown (params, aReason) { +} diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom/chrome.manifest b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom/chrome.manifest new file mode 100644 index 000000000..f7132fc46 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom/chrome.manifest @@ -0,0 +1,2 @@ +content inlinesettings ./ +locale inlinesettings en-US ./ diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom/install.rdf new file mode 100644 index 000000000..2bf7c6e2e --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom/install.rdf @@ -0,0 +1,19 @@ +<?xml version="1.0" ?> +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>inlinesettings1@tests.mozilla.org</em:id> + <em:name>Inline Settings (Bootstrap)</em:name> + <em:version>1</em:version> + <em:bootstrap>true</em:bootstrap> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </Description> + </em:targetApplication> + </Description> + +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom/options.xul b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom/options.xul new file mode 100644 index 000000000..148fb9856 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom/options.xul @@ -0,0 +1,5 @@ +<?xml version="1.0" ?> +<!DOCTYPE vbox SYSTEM "chrome://inlinesettings/locale/string.dtd"> +<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <setting type="custom" title="&custom.title;" style="background-color: blue; display: -moz-grid-line; -moz-binding: url('chrome://inlinesettings/content/binding.xml#custom');"/> +</vbox> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom/string.dtd b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom/string.dtd new file mode 100644 index 000000000..0b2dcc8fe --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_custom/string.dtd @@ -0,0 +1 @@ +<!ENTITY custom.title "Custom"> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_info/bootstrap.js b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_info/bootstrap.js new file mode 100644 index 000000000..7871af738 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_info/bootstrap.js @@ -0,0 +1,8 @@ +function install (params, aReason) { +} +function uninstall (params, aReason) { +} +function startup (params, aReason) { +} +function shutdown (params, aReason) { +} diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_info/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_info/install.rdf new file mode 100644 index 000000000..e3a054890 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_info/install.rdf @@ -0,0 +1,20 @@ +<?xml version="1.0" ?> +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>inlinesettings1@tests.mozilla.org</em:id> + <em:name>Inline Settings (Bootstrap)</em:name> + <em:version>1</em:version> + <em:bootstrap>true</em:bootstrap> + <em:optionsType>4</em:optionsType> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </Description> + </em:targetApplication> + </Description> + +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_info/options.xul b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_info/options.xul new file mode 100644 index 000000000..095d3bcef --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_info/options.xul @@ -0,0 +1,19 @@ +<?xml version="1.0" ?> +<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <setting pref="extensions.inlinesettings1.bool" type="bool" title="Bool" checkboxlabel="Check box label"/> + <setting pref="extensions.inlinesettings1.boolint" type="boolint" on="1" off="2" title="BoolInt"/> + <setting pref="extensions.inlinesettings1.integer" type="integer" title="Integer"/> + <setting pref="extensions.inlinesettings1.string" type="string" title="String"/> + <setting type="control" title="Menulist"> + <menulist sizetopopup="always" oncommand="window._testValue = this.value;"> + <menupopup> + <menuitem label="Alpha" value="1" /> + <menuitem label="Bravo" value="2" /> + <menuitem label="Charlie" value="3" /> + </menupopup> + </menulist> + </setting> + <setting pref="extensions.inlinesettings1.color" type="color" title="Color"/> + <setting pref="extensions.inlinesettings1.file" type="file" title="File"/> + <setting pref="extensions.inlinesettings1.directory" type="directory" title="Directory"/> +</vbox> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_install1_1/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_install1_1/install.rdf new file mode 100644 index 000000000..ba71f4c95 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_install1_1/install.rdf @@ -0,0 +1,24 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon1@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:bootstrap>true</em:bootstrap> + <em:updateURL>http://example.com/browser/toolkit/mozapps/extensions/test/browser/browser_install.rdf</em:updateURL> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Install Tests</em:name> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_install1_2/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_install1_2/install.rdf new file mode 100644 index 000000000..4497c31e2 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_install1_2/install.rdf @@ -0,0 +1,22 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon1@tests.mozilla.org</em:id> + <em:version>2.0</em:version> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Install Tests</em:name> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_installssl/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_installssl/install.rdf new file mode 100644 index 000000000..0906bbe91 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_installssl/install.rdf @@ -0,0 +1,22 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>sslinstall@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>SSL Install Tests</em:name> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_searching/bootstrap.js b/toolkit/mozapps/extensions/test/browser/addons/browser_searching/bootstrap.js new file mode 100644 index 000000000..7b86e419a --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_searching/bootstrap.js @@ -0,0 +1,9 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +function install(data, reason) {} +function startup(data, reason) {} +function shutdown(data, reason) {} +function uninstall(data, reason) {} + diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_searching/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_searching/install.rdf new file mode 100644 index 000000000..f26f9ad80 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_searching/install.rdf @@ -0,0 +1,25 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>remote1@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + <em:type>2</em:type> + <em:bootstrap>true</em:bootstrap> + + <em:targetApplication> + <Description> + <em:id>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>PASS - b - installed</em:name> + <em:description>Test sumary - SEARCH SEARCH</em:description> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/addons/browser_select_compatoverrides_1/install.rdf b/toolkit/mozapps/extensions/test/browser/addons/browser_select_compatoverrides_1/install.rdf new file mode 100644 index 000000000..47a0e373a --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/addons/browser_select_compatoverrides_1/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon1@tests.mozilla.org</em:id> + <em:version>1.0</em:version> + + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>0.1</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Addon1</em:name> + <em:bootstrap>true</em:bootstrap> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/blockNoPlugins.xml b/toolkit/mozapps/extensions/test/browser/blockNoPlugins.xml new file mode 100644 index 000000000..e4e191b37 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/blockNoPlugins.xml @@ -0,0 +1,7 @@ +<?xml version="1.0"?> +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1336406310001"> + <emItems> + </emItems> + <pluginItems> + </pluginItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/browser/blockPluginHard.xml b/toolkit/mozapps/extensions/test/browser/blockPluginHard.xml new file mode 100644 index 000000000..24eb5bc6f --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/blockPluginHard.xml @@ -0,0 +1,11 @@ +<?xml version="1.0"?> +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1336406310000"> + <emItems> + </emItems> + <pluginItems> + <pluginItem blockID="p9999"> + <match name="filename" exp="libnptest\.so|nptest\.dll|Test\.plugin" /> + <versionRange severity="2"></versionRange> + </pluginItem> + </pluginItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/browser/browser-common.ini b/toolkit/mozapps/extensions/test/browser/browser-common.ini new file mode 100644 index 000000000..eaab29f75 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser-common.ini @@ -0,0 +1,78 @@ +[DEFAULT] +support-files = + head.js + +[browser_about.js] +skip-if = os == 'linux' || os == 'win' # bug 632290 +[browser_bug523784.js] +[browser_bug557943.js] +[browser_bug562797.js] +skip-if = e10s # Bug 933103 - mochitest's EventUtils.synthesizeMouse functions not e10s friendly +[browser_bug562854.js] +[browser_bug562890.js] +[browser_bug562899.js] +skip-if = buildapp == 'mulet' +[browser_bug562992.js] +[browser_bug567127.js] +[browser_bug567137.js] +[browser_bug570760.js] +skip-if = e10s # Bug ?????? - EventUtils.synthesizeKey not e10s friendly +[browser_bug572561.js] +[browser_bug577990.js] +[browser_bug580298.js] +[browser_bug581076.js] +[browser_bug586574.js] +[browser_bug587970.js] +[browser_bug591465.js] +[browser_bug591663.js] +[browser_bug593535.js] +skip-if = true # Bug 1093190 - Disabled due to leak +[browser_bug596336.js] +[browser_bug608316.js] +[browser_bug610764.js] +[browser_bug618502.js] +[browser_bug679604.js] +[browser_bug714593.js] +[browser_bug590347.js] +[browser_debug_button.js] +[browser_details.js] +[browser_discovery.js] +skip-if = e10s # Bug ?????? - test times out on try on all platforms, but works locally for markh! +[browser_dragdrop.js] +skip-if = buildapp == 'mulet' +[browser_experiments.js] +skip-if = e10s +[browser_list.js] +[browser_metadataTimeout.js] +[browser_searching.js] +[browser_sorting.js] +[browser_sorting_plugins.js] +[browser_plugin_enabled_state_locked.js] +skip-if = e10s # Bug ?????? - leaked until shutdown [nsGlobalWindow #1760 about:blank] +[browser_uninstalling.js] +skip-if = e10s # Bug ?????? - leaked until shutdown [nsGlobalWindow #1760 about:blank] +[browser_install.js] +[browser_recentupdates.js] +[browser_manualupdates.js] +[browser_globalwarnings.js] +[browser_globalinformations.js] +skip-if = e10s # Bug 933103 - mochitest's EventUtils.synthesizeMouse functions not e10s friendly +[browser_eula.js] +skip-if = buildapp == 'mulet' +[browser_updateid.js] +skip-if = e10s # Bug ?????? - window leak reported at end of test run. +[browser_purchase.js] +skip-if = e10s # Bug 933103 - mochitest's EventUtils.synthesizeMouse functions not e10s friendly +[browser_openDialog.js] +skip-if = e10s +[browser_types.js] +skip-if = e10s # Bug ?????? - leaked until shutdown [nsGlobalWindow #1760 about:blank] +[browser_inlinesettings.js] +[browser_inlinesettings_custom.js] +[browser_inlinesettings_info.js] +[browser_tabsettings.js] +skip-if = e10s # Bug ?????? - leaked until shutdown [nsGlobalWindow #1760 about:blank] +[browser_pluginprefs.js] +skip-if = buildapp == 'mulet' +[browser_CTP_plugins.js] +skip-if = buildapp == 'mulet' || e10s # Bug 899347 - no e10s click-to-play support diff --git a/toolkit/mozapps/extensions/test/browser/browser-window.ini b/toolkit/mozapps/extensions/test/browser/browser-window.ini new file mode 100644 index 000000000..95494eb3e --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser-window.ini @@ -0,0 +1,4 @@ +[DEFAULT] +install-to-subdir = test-window + +[include:browser-common.ini] diff --git a/toolkit/mozapps/extensions/test/browser/browser.ini b/toolkit/mozapps/extensions/test/browser/browser.ini new file mode 100644 index 000000000..dc6f86bd6 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser.ini @@ -0,0 +1,53 @@ +[DEFAULT] +skip-if = buildapp == 'mulet' +support-files = + addon_about.xul + addon_prefs.xul + cancelCompatCheck.sjs + discovery.html + discovery_frame.html + discovery_install.html + more_options.xul + options.xul + plugin_test.html + redirect.sjs + releaseNotes.xhtml + blockNoPlugins.xml + blockPluginHard.xml + browser_bug557956.rdf + browser_bug557956_8_2.xpi + browser_bug557956_9_2.xpi + browser_bug557956.xml + browser_bug591465.xml + browser_bug593535.xml + browser_searching.xml + browser_searching_empty.xml + browser_select_compatoverrides.xml + browser_updatessl.rdf + browser_updatessl.rdf^headers^ + browser_install.rdf + browser_install.rdf^headers^ + browser_install.xml + browser_install1_3.xpi + browser_eula.xml + browser_purchase.xml + +[browser_addonrepository_performance.js] +[browser_bug557956.js] +skip-if = e10s +[browser_bug616841.js] +[browser_cancelCompatCheck.js] +[browser_checkAddonCompatibility.js] +[browser_gmpProvider.js] +[browser_installssl.js] +[browser_newaddon.js] +skip-if = e10s +[browser_select_compatoverrides.js] +[browser_select_confirm.js] +[browser_select_selection.js] +[browser_select_update.js] +[browser_updatessl.js] +[browser_task_next_test.js] +[browser_discovery_install.js] + +[include:browser-common.ini] diff --git a/toolkit/mozapps/extensions/test/browser/browser_CTP_plugins.js b/toolkit/mozapps/extensions/test/browser/browser_CTP_plugins.js new file mode 100644 index 000000000..1b119ca5b --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_CTP_plugins.js @@ -0,0 +1,234 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const gHttpTestRoot = "http://127.0.0.1:8888/" + RELATIVE_DIR + "/"; +let gManagerWindow; +let gTestPluginId; +let gPluginBrowser; + +function updateBlocklist(aCallback) { + var blocklistNotifier = Cc["@mozilla.org/extensions/blocklist;1"] + .getService(Ci.nsITimerCallback); + var observer = function() { + Services.obs.removeObserver(observer, "blocklist-updated"); + SimpleTest.executeSoon(aCallback); + }; + Services.obs.addObserver(observer, "blocklist-updated", false); + blocklistNotifier.notify(null); +} + +var _originalBlocklistURL = null; +function setAndUpdateBlocklist(aURL, aCallback) { + if (!_originalBlocklistURL) { + _originalBlocklistURL = Services.prefs.getCharPref("extensions.blocklist.url"); + } + Services.prefs.setCharPref("extensions.blocklist.url", aURL); + updateBlocklist(aCallback); +} + +function resetBlocklist(aCallback) { + Services.prefs.setCharPref("extensions.blocklist.url", _originalBlocklistURL); +} + +function test() { + waitForExplicitFinish(); + Services.prefs.setBoolPref("plugins.click_to_play", true); + Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true); + let pluginTag = getTestPluginTag(); + pluginTag.enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY; + open_manager("addons://list/plugin", part1); +} + +function part1(aWindow) { + gManagerWindow = aWindow; + AddonManager.getAddonsByTypes(["plugin"], part2); +} + +function part2(aPlugins) { + for (let plugin of aPlugins) { + if (plugin.name == "Test Plug-in") { + gTestPluginId = plugin.id; + break; + } + } + ok(gTestPluginId, "part2: Test Plug-in should exist"); + AddonManager.getAddonByID(gTestPluginId, part3); +} + +function part3(aTestPlugin) { + let pluginEl = get_addon_element(gManagerWindow, gTestPluginId); + pluginEl.parentNode.ensureElementIsVisible(pluginEl); + let enableButton = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "enable-btn"); + is_element_hidden(enableButton, "part3: enable button should not be visible"); + let disableButton = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "enable-btn"); + is_element_hidden(disableButton, "part3: disable button should not be visible"); + let menu = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "state-menulist"); + is_element_visible(menu, "part3: state menu should be visible"); + let askToActivateItem = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "ask-to-activate-menuitem"); + is(menu.selectedItem, askToActivateItem, "part3: state menu should have 'Ask To Activate' selected"); + + gBrowser.selectedTab = gBrowser.addTab(); + gPluginBrowser = gBrowser.selectedBrowser; + gPluginBrowser.addEventListener("PluginBindingAttached", part4, true, true); + gPluginBrowser.contentWindow.location = gHttpTestRoot + "plugin_test.html"; +} + +function part4() { + let condition = () => PopupNotifications.getNotification("click-to-play-plugins", gPluginBrowser); + waitForCondition(condition, () => { + gPluginBrowser.removeEventListener("PluginBindingAttached", part4); + gBrowser.removeCurrentTab(); + + let pluginEl = get_addon_element(gManagerWindow, gTestPluginId); + let menu = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "state-menulist"); + let alwaysActivateItem = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "always-activate-menuitem"); + menu.selectedItem = alwaysActivateItem; + alwaysActivateItem.doCommand(); + gBrowser.selectedTab = gBrowser.addTab(); + gPluginBrowser = gBrowser.selectedBrowser; + gPluginBrowser.addEventListener("load", part5, true); + gPluginBrowser.contentWindow.location = gHttpTestRoot + "plugin_test.html"; + }, "part4: should have a click-to-play notification"); +} + +function part5() { + let testPlugin = gPluginBrowser.contentDocument.getElementById("test"); + ok(testPlugin, "part5: should have a plugin element in the page"); + let objLoadingContent = testPlugin.QueryInterface(Ci.nsIObjectLoadingContent); + let condition = function() objLoadingContent.activated; + waitForCondition(condition, part6, "part5: waited too long for plugin to activate"); +} + +function part6() { + let testPlugin = gPluginBrowser.contentDocument.getElementById("test"); + ok(testPlugin, "part6: should have a plugin element in the page"); + let objLoadingContent = testPlugin.QueryInterface(Ci.nsIObjectLoadingContent); + ok(objLoadingContent.activated, "part6: plugin should be activated"); + gPluginBrowser.removeEventListener("load", part5); + gBrowser.removeCurrentTab(); + + let pluginEl = get_addon_element(gManagerWindow, gTestPluginId); + let menu = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "state-menulist"); + let neverActivateItem = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "never-activate-menuitem"); + menu.selectedItem = neverActivateItem; + neverActivateItem.doCommand(); + gBrowser.selectedTab = gBrowser.addTab(); + gPluginBrowser = gBrowser.selectedBrowser; + gPluginBrowser.addEventListener("PluginBindingAttached", part7, true, true); + gPluginBrowser.contentWindow.location = gHttpTestRoot + "plugin_test.html"; +} + +function part7() { + let condition = () => PopupNotifications.getNotification("click-to-play-plugins", gPluginBrowser); + waitForCondition(condition, () => { + let testPlugin = gPluginBrowser.contentDocument.getElementById("test"); + ok(testPlugin, "part7: should have a plugin element in the page"); + let objLoadingContent = testPlugin.QueryInterface(Ci.nsIObjectLoadingContent); + ok(!objLoadingContent.activated, "part7: plugin should not be activated"); + + gPluginBrowser.removeEventListener("PluginBindingAttached", part7); + gBrowser.removeCurrentTab(); + + let pluginEl = get_addon_element(gManagerWindow, gTestPluginId); + let details = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "details-btn"); + is_element_visible(details, "part7: details link should be visible"); + EventUtils.synthesizeMouseAtCenter(details, {}, gManagerWindow); + wait_for_view_load(gManagerWindow, part8); + }, "part7: disabled plugins still show a notification"); +} + +function part8() { + let enableButton = gManagerWindow.document.getElementById("detail-enable-btn"); + is_element_hidden(enableButton, "part8: detail enable button should be hidden"); + let disableButton = gManagerWindow.document.getElementById("detail-disable-btn"); + is_element_hidden(disableButton, "part8: detail disable button should be hidden"); + let menu = gManagerWindow.document.getElementById("detail-state-menulist"); + is_element_visible(menu, "part8: detail state menu should be visible"); + let neverActivateItem = gManagerWindow.document.getElementById("detail-never-activate-menuitem"); + is(menu.selectedItem, neverActivateItem, "part8: state menu should have 'Never Activate' selected"); + + let alwaysActivateItem = gManagerWindow.document.getElementById("detail-always-activate-menuitem"); + menu.selectedItem = alwaysActivateItem; + alwaysActivateItem.doCommand(); + gBrowser.selectedTab = gBrowser.addTab(); + gPluginBrowser = gBrowser.selectedBrowser; + gPluginBrowser.addEventListener("load", part9, true); + gPluginBrowser.contentWindow.location = gHttpTestRoot + "plugin_test.html"; +} + +function part9() { + let testPlugin = gPluginBrowser.contentDocument.getElementById("test"); + ok(testPlugin, "part9: should have a plugin element in the page"); + let objLoadingContent = testPlugin.QueryInterface(Ci.nsIObjectLoadingContent); + let condition = function() objLoadingContent.activated; + waitForCondition(condition, part10, "part9: waited too long for plugin to activate"); +} + +function part10() { + let testPlugin = gPluginBrowser.contentDocument.getElementById("test"); + ok(testPlugin, "part10: should have a plugin element in the page"); + let objLoadingContent = testPlugin.QueryInterface(Ci.nsIObjectLoadingContent); + ok(objLoadingContent.activated, "part10: plugin should be activated"); + gPluginBrowser.removeEventListener("load", part9); + gBrowser.removeCurrentTab(); + + let menu = gManagerWindow.document.getElementById("detail-state-menulist"); + let askToActivateItem = gManagerWindow.document.getElementById("detail-ask-to-activate-menuitem"); + menu.selectedItem = askToActivateItem; + askToActivateItem.doCommand(); + gBrowser.selectedTab = gBrowser.addTab(); + gPluginBrowser = gBrowser.selectedBrowser; + gPluginBrowser.addEventListener("PluginBindingAttached", part11, true, true); + gPluginBrowser.contentWindow.location = gHttpTestRoot + "plugin_test.html"; +} + +function part11() { + let condition = () => PopupNotifications.getNotification("click-to-play-plugins", gPluginBrowser); + waitForCondition(condition, () => { + gPluginBrowser.removeEventListener("PluginBindingAttached", part11); + gBrowser.removeCurrentTab(); + + let pluginTag = getTestPluginTag(); + + // causes appDisabled to be set + setAndUpdateBlocklist(gHttpTestRoot + "blockPluginHard.xml", + function() { + close_manager(gManagerWindow, function() { + open_manager("addons://list/plugin", part12); + }); + }); + }, "part11: should have a click-to-play notification"); +} + +function part12(aWindow) { + gManagerWindow = aWindow; + let pluginEl = get_addon_element(gManagerWindow, gTestPluginId); + pluginEl.parentNode.ensureElementIsVisible(pluginEl); + let menu = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "state-menulist"); + is(menu.disabled, true, "part12: state menu should be disabled"); + + let details = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "details-btn"); + EventUtils.synthesizeMouseAtCenter(details, {}, gManagerWindow); + wait_for_view_load(gManagerWindow, part13); +} + +function part13() { + let menu = gManagerWindow.document.getElementById("detail-state-menulist"); + is(menu.disabled, true, "part13: detail state menu should be disabled"); + + setAndUpdateBlocklist(gHttpTestRoot + "blockNoPlugins.xml", function() { + run_next_test(); + }); +} + +function end_test() { + Services.prefs.clearUserPref("plugins.click_to_play"); + Services.prefs.clearUserPref("extensions.blocklist.suppressUI"); + let pluginTag = getTestPluginTag(); + pluginTag.enabledState = Ci.nsIPluginTag.STATE_ENABLED; + resetBlocklist(); + close_manager(gManagerWindow, function() { + finish(); + }); +} diff --git a/toolkit/mozapps/extensions/test/browser/browser_about.js b/toolkit/mozapps/extensions/test/browser/browser_about.js new file mode 100644 index 000000000..f781cf146 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_about.js @@ -0,0 +1,84 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +/** + * Tests the default and custom "about" dialogs of add-ons. + * + * Test for bug 610661 <https://bugzilla.mozilla.org/show_bug.cgi?id=610661>: + * Addon object not passed to custom about dialogs. + */ + +var gManagerWindow; + +const URI_ABOUT_DEFAULT = "chrome://mozapps/content/extensions/about.xul"; +const URI_ABOUT_CUSTOM = CHROMEROOT + "addon_about.xul"; + +function test() { + requestLongerTimeout(2); + + waitForExplicitFinish(); + + var gProvider = new MockProvider(); + gProvider.createAddons([{ + id: "test1@tests.mozilla.org", + name: "Test add-on 1", + description: "foo" + }, + { + id: "test2@tests.mozilla.org", + name: "Test add-on 2", + description: "bar", + aboutURL: URI_ABOUT_CUSTOM + }]); + + open_manager("addons://list/extension", function(aManager) { + gManagerWindow = aManager; + + test_about_window("Test add-on 1", URI_ABOUT_DEFAULT, function() { + test_about_window("Test add-on 2", URI_ABOUT_CUSTOM, function() { + close_manager(gManagerWindow, finish); + }); + }); + }); +} + +function test_about_window(aAddonItemName, aExpectedAboutUri, aCallback) { + var addonList = gManagerWindow.document.getElementById("addon-list"); + for (var addonItem of addonList.childNodes) { + if (addonItem.hasAttribute("name") && + addonItem.getAttribute("name") === aAddonItemName) + break; + } + + info("Waiting for about dialog"); + Services.ww.registerNotification(function TEST_ww_observer(aSubject, aTopic, + aData) { + if (aTopic == "domwindowclosed") { + Services.ww.unregisterNotification(TEST_ww_observer); + + info("About dialog closed, waiting for focus on browser window"); + waitForFocus(() => executeSoon(aCallback)); + } else if (aTopic == "domwindowopened") { + info("About dialog opened, waiting for focus"); + + let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget); + waitForFocus(function() { + info("Saw about dialog"); + + is(win.location, + aExpectedAboutUri, + "The correct add-on about window should have opened"); + + is(win.arguments && win.arguments[0] && win.arguments[0].name, + aAddonItemName, + "window.arguments[0] should refer to the add-on object"); + + executeSoon(() => win.close()); + }, win); + } + }); + + gManagerWindow.gViewController.doCommand("cmd_showItemAbout", + addonItem.mAddon); +} diff --git a/toolkit/mozapps/extensions/test/browser/browser_addonrepository_performance.js b/toolkit/mozapps/extensions/test/browser/browser_addonrepository_performance.js new file mode 100644 index 000000000..0ba3127cd --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_addonrepository_performance.js @@ -0,0 +1,99 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that the metadata request includes startup time measurements + +let tmp = {}; +Components.utils.import("resource://gre/modules/addons/AddonRepository.jsm", tmp); +let AddonRepository = tmp.AddonRepository; + +var gTelemetry = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry); +var gManagerWindow; +var gProvider; + +function parseParams(aQuery) { + let params = {}; + + for (let param of aQuery.split("&")) { + let [key, value] = param.split("="); + params[key] = value; + } + + return params; +} + +function test() { + waitForExplicitFinish(); + + var gSeenRequest = false; + + gProvider = new MockProvider(); + gProvider.createAddons([{ + id: "test1@tests.mozilla.org", + name: "Test add-on" + }]); + + function observe(aSubject, aTopic, aData) { + aSubject.QueryInterface(Ci.nsIChannel); + let url = aSubject.URI.QueryInterface(Ci.nsIURL); + if (url.filePath != "/extensions-dummy/metadata") { + return; + } + info(url.query); + + // Check if we encountered telemetry errors and turn the tests for which + // we don't have valid data into known failures. + let snapshot = gTelemetry.getHistogramById("STARTUP_MEASUREMENT_ERRORS") + .snapshot(); + + let tProcessValid = (snapshot.counts[0] == 0); + let tMainValid = tProcessValid && (snapshot.counts[2] == 0); + let tFirstPaintValid = tProcessValid && (snapshot.counts[5] == 0); + let tSessionRestoredValid = tProcessValid && (snapshot.counts[6] == 0); + + let params = parseParams(url.query); + + is(params.appOS, Services.appinfo.OS, "OS should be correct"); + is(params.appVersion, Services.appinfo.version, "Version should be correct"); + + if (tMainValid) { + ok(params.tMain >= 0, "Should be a sensible tMain"); + } else { + todo(false, "An error occurred while recording the startup timestamps, skipping this test"); + } + + if (tFirstPaintValid) { + ok(params.tFirstPaint >= 0, "Should be a sensible tFirstPaint"); + } else { + todo(false, "An error occurred while recording the startup timestamps, skipping this test"); + } + + if (tSessionRestoredValid) { + ok(params.tSessionRestored >= 0, "Should be a sensible tSessionRestored"); + } else { + todo(false, "An error occurred while recording the startup timestamps, skipping this test"); + } + + gSeenRequest = true; + } + + const PREF = "extensions.getAddons.getWithPerformance.url"; + + // Watch HTTP requests + Services.obs.addObserver(observe, "http-on-modify-request", false); + Services.prefs.setCharPref(PREF, + "http://127.0.0.1:8888/extensions-dummy/metadata?appOS=%OS%&appVersion=%VERSION%&tMain=%TIME_MAIN%&tFirstPaint=%TIME_FIRST_PAINT%&tSessionRestored=%TIME_SESSION_RESTORED%"); + + registerCleanupFunction(function() { + Services.obs.removeObserver(observe, "http-on-modify-request"); + }); + + AddonRepository._beginGetAddons(["test1@tests.mozilla.org"], { + searchFailed: function() { + ok(gSeenRequest, "Should have seen metadata request"); + finish(); + } + }, true); +} + diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug523784.js b/toolkit/mozapps/extensions/test/browser/browser_bug523784.js new file mode 100644 index 000000000..c467e5cc0 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug523784.js @@ -0,0 +1,120 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const URI_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul"; + +// This tests that the blocklist dialog still affects soft-blocked add-ons +// if the user clicks the "Restart Later" button. It also ensures that the +// "Cancel" button is correctly renamed (to "Restart Later"). +let args = { + restart: false, + list: [{ + name: "Bug 523784 softblocked addon", + version: "1", + icon: "chrome://mozapps/skin/plugins/pluginGeneric.png", + disable: false, + blocked: false, + url: 'http://example.com/bug523784_1', + }], +}; + +function test() { + waitForExplicitFinish(); + + let windowObserver = function(aSubject, aTopic, aData) { + if (aTopic != "domwindowopened") + return; + + Services.ww.unregisterNotification(windowObserver); + + let win = aSubject.QueryInterface(Ci.nsIDOMWindow); + win.addEventListener("load", function() { + win.removeEventListener("load", arguments.callee, false); + + executeSoon(function() bug523784_test1(win)); + }, false); + }; + Services.ww.registerNotification(windowObserver); + + args.wrappedJSObject = args; + Services.ww.openWindow(null, URI_BLOCKLIST_DIALOG, "", + "chrome,centerscreen,dialog,titlebar", args); +} + +function bug523784_test1(win) { + let bundle = Services.strings. + createBundle("chrome://mozapps/locale/update/updates.properties"); + let cancelButton = win.document.documentElement.getButton("cancel"); + let moreInfoLink = win.document.getElementById("moreInfo"); + + is(cancelButton.getAttribute("label"), + bundle.GetStringFromName("restartLaterButton"), + "Text should be changed on Cancel button"); + is(cancelButton.getAttribute("accesskey"), + bundle.GetStringFromName("restartLaterButton.accesskey"), + "Accesskey should also be changed on Cancel button"); + is(moreInfoLink.getAttribute("href"), + 'http://example.com/bug523784_1', + "More Info link should link to a detailed blocklist page."); + let windowObserver = function(aSubject, aTopic, aData) { + if (aTopic != "domwindowclosed") + return; + + Services.ww.unregisterNotification(windowObserver); + + ok(args.list[0].disable, "Should be blocking add-on"); + ok(!args.restart, "Should not restart browser immediately"); + + executeSoon(bug523784_test2); + }; + Services.ww.registerNotification(windowObserver); + + cancelButton.doCommand(); +} + +function bug523784_test2(win) { + let windowObserver = function(aSubject, aTopic, aData) { + if (aTopic != "domwindowopened") + return; + + Services.ww.unregisterNotification(windowObserver); + let win = aSubject.QueryInterface(Ci.nsIDOMWindow); + win.addEventListener("load", function() { + win.removeEventListener("load", arguments.callee, false); + + executeSoon(function(){ + let moreInfoLink = win.document.getElementById("moreInfo"); + let cancelButton = win.document.documentElement.getButton("cancel"); + is(moreInfoLink.getAttribute("href"), + Services.urlFormatter.formatURLPref("extensions.blocklist.detailsURL"), + "More Info link should link to the general blocklist page."); + cancelButton.doCommand(); + executeSoon(finish); + }) + }, false); + }; + Services.ww.registerNotification(windowObserver); + + // Add 2 more addons to the blocked list to check that the more info link + // points to the general blocked list page. + args.list.push({ + name: "Bug 523784 softblocked addon 2", + version: "2", + icon: "chrome://mozapps/skin/plugins/pluginGeneric.png", + disable: false, + blocked: false, + url: 'http://example.com/bug523784_2' + }); + args.list.push({ + name: "Bug 523784 softblocked addon 3", + version: "4", + icon: "chrome://mozapps/skin/plugins/pluginGeneric.png", + disable: false, + blocked: false, + url: 'http://example.com/bug523784_3' + }); + + args.wrappedJSObject = args; + Services.ww.openWindow(null, URI_BLOCKLIST_DIALOG, "", + "chrome,centerscreen,dialog,titlebar", args); +} diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug557943.js b/toolkit/mozapps/extensions/test/browser/browser_bug557943.js new file mode 100644 index 000000000..94a8b6f49 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug557943.js @@ -0,0 +1,80 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Bug 557943 - Searching for addons can result in wrong results + +var gManagerWindow; +var gProvider; + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + gProvider.createAddons([{ + id: "addon1@tests.mozilla.org", + name: "Microsoft .NET Framework Assistant", + description: "", + version: "6.66" + }, { + id: "addon2@tests.mozilla.org", + name: "AwesomeNet Addon", + description: "" + }, { + id: "addon3@tests.mozilla.org", + name: "Dictionnaire MySpell en Francais (réforme 1990)", + description: "" + }]); + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, function() { + finish(); + }); +} + + +function perform_search(aQuery, aCallback) { + waitForFocus(function() { + var searchBox = gManagerWindow.document.getElementById("header-search"); + searchBox.value = aQuery; + + EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow); + EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); + wait_for_view_load(gManagerWindow, function() { + var list = gManagerWindow.document.getElementById("search-list"); + var rows = list.getElementsByTagName("richlistitem"); + aCallback(rows); + }); + }, gManagerWindow); +} + + +add_test(function() { + perform_search(".net", function(aRows) { + is(aRows.length, 1, "Should only get one result"); + is(aRows[0].mAddon.id, "addon1@tests.mozilla.org", "Should get expected addon as only result"); + run_next_test(); + }); +}); + +add_test(function() { + perform_search("réf", function(aRows) { + is(aRows.length, 1, "Should only get one result"); + is(aRows[0].mAddon.id, "addon3@tests.mozilla.org", "Should get expected addon as only result"); + run_next_test(); + }); +}); + +add_test(function() { + perform_search("javascript:void()", function(aRows) { + is(aRows.length, 0, "Should not get any results"); + run_next_test(); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug557956.js b/toolkit/mozapps/extensions/test/browser/browser_bug557956.js new file mode 100644 index 000000000..919564b45 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug557956.js @@ -0,0 +1,518 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test the compatibility dialog that displays during startup when the browser +// version changes. + +const URI_EXTENSION_UPDATE_DIALOG = "chrome://mozapps/content/extensions/update.xul"; + +const PREF_GETADDONS_BYIDS = "extensions.getAddons.get.url"; +const PREF_MIN_PLATFORM_COMPAT = "extensions.minCompatiblePlatformVersion"; + +Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true); +// avoid the 'leaked window property' check +let scope = {}; +Components.utils.import("resource://gre/modules/TelemetrySession.jsm", scope); +let TelemetrySession = scope.TelemetrySession; + +/** + * Test add-ons: + * + * Addon minVersion maxVersion Notes + * addon1 0 * + * addon2 0 0 + * addon3 0 0 + * addon4 1 * + * addon5 0 0 Made compatible by update check + * addon6 0 0 Made compatible by update check + * addon7 0 0 Has a broken update available + * addon8 0 0 Has an update available + * addon9 0 0 Has an update available + */ + +function test() { + requestLongerTimeout(2); + waitForExplicitFinish(); + + run_next_test(); +} + +function end_test() { + // Test generates a lot of available installs so just cancel them all + AddonManager.getAllInstalls(function(aInstalls) { + for (let install of aInstalls) + install.cancel(); + + finish(); + }); +} + +function install_test_addons(aCallback) { + var installs = []; + + // Use a blank update URL + Services.prefs.setCharPref(PREF_UPDATEURL, TESTROOT + "missing.rdf"); + + let names = ["browser_bug557956_1", + "browser_bug557956_2", + "browser_bug557956_3", + "browser_bug557956_4", + "browser_bug557956_5", + "browser_bug557956_6", + "browser_bug557956_7", + "browser_bug557956_8_1", + "browser_bug557956_9_1", + "browser_bug557956_10"]; + for (let name of names) { + AddonManager.getInstallForURL(TESTROOT + "addons/" + name + ".xpi", function(aInstall) { + installs.push(aInstall); + }, "application/x-xpinstall"); + } + + var listener = { + installCount: 0, + + onInstallEnded: function() { + this.installCount++; + if (this.installCount == installs.length) { + // Switch to the test update URL + Services.prefs.setCharPref(PREF_UPDATEURL, TESTROOT + "browser_bug557956.rdf"); + + executeSoon(aCallback); + } + } + }; + + for (let install of installs) { + install.addListener(listener); + install.install(); + } +} + +function uninstall_test_addons(aCallback) { + 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", + "addon8@tests.mozilla.org", + "addon9@tests.mozilla.org", + "addon10@tests.mozilla.org"], + function(aAddons) { + for (let addon of aAddons) { + if (addon) + addon.uninstall(); + } + aCallback(); + }); +} + +// Open the compatibility dialog, with the list of addon IDs +// that were disabled by this "update" +function open_compatibility_window(aDisabledAddons, aCallback) { + // This will reset the longer timeout multiplier to 2 which will give each + // test that calls open_compatibility_window a minimum of 60 seconds to + // complete. + requestLongerTimeout(2); + + var variant = Cc["@mozilla.org/variant;1"]. + createInstance(Ci.nsIWritableVariant); + variant.setFromVariant(aDisabledAddons); + + // Cannot be modal as we want to interact with it, shouldn't cause problems + // with testing though. + var features = "chrome,centerscreen,dialog,titlebar"; + var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. + getService(Ci.nsIWindowWatcher); + var win = ww.openWindow(null, URI_EXTENSION_UPDATE_DIALOG, "", features, variant); + + win.addEventListener("load", function() { + win.removeEventListener("load", arguments.callee, false); + + info("Compatibility dialog opened"); + + function page_shown(aEvent) { + if (aEvent.target.pageid) + info("Page " + aEvent.target.pageid + " shown"); + } + + win.addEventListener("pageshow", page_shown, false); + win.addEventListener("unload", function() { + win.removeEventListener("unload", arguments.callee, false); + win.removeEventListener("pageshow", page_shown, false); + info("Compatibility dialog closed"); + }, false); + + aCallback(win); + }, false); +} + +function wait_for_window_close(aWindow, aCallback) { + aWindow.addEventListener("unload", function() { + aWindow.removeEventListener("unload", arguments.callee, false); + aCallback(); + }, false); +} + +function wait_for_page(aWindow, aPageId, aCallback) { + var page = aWindow.document.getElementById(aPageId); + page.addEventListener("pageshow", function() { + page.removeEventListener("pageshow", arguments.callee, false); + executeSoon(function() { + aCallback(aWindow); + }); + }, false); +} + +function get_list_names(aList) { + var items = []; + for (let listItem of aList.childNodes) + items.push(listItem.label); + items.sort(); + return items; +} + +function check_telemetry({disabled, metaenabled, metadisabled, upgraded, failed, declined}) { + let ping = TelemetrySession.getPayload(); + // info(JSON.stringify(ping)); + let am = ping.simpleMeasurements.addonManager; + if (disabled !== undefined) + is(am.appUpdate_disabled, disabled, disabled + " add-ons disabled by version change"); + if (metaenabled !== undefined) + is(am.appUpdate_metadata_enabled, metaenabled, metaenabled + " add-ons enabled by metadata"); + if (metadisabled !== undefined) + is(am.appUpdate_metadata_disabled, metadisabled, metadisabled + " add-ons disabled by metadata"); + if (upgraded !== undefined) + is(am.appUpdate_upgraded, upgraded, upgraded + " add-ons upgraded"); + if (failed !== undefined) + is(am.appUpdate_upgradeFailed, failed, failed + " upgrades failed"); + if (declined !== undefined) + is(am.appUpdate_upgradeDeclined, declined, declined + " upgrades declined"); +} + +add_test(function test_setup() { + TelemetrySession.setup().then(run_next_test); +}); + +// Tests that the right add-ons show up in the mismatch dialog and updates can +// be installed +add_test(function basic_mismatch() { + install_test_addons(function() { + // These add-ons become disabled + var disabledAddonIds = [ + "addon3@tests.mozilla.org", + "addon6@tests.mozilla.org", + "addon7@tests.mozilla.org", + "addon8@tests.mozilla.org", + "addon9@tests.mozilla.org" + ]; + + AddonManager.getAddonsByIDs(["addon5@tests.mozilla.org", + "addon6@tests.mozilla.org"], + function([a5, a6]) { + // Check starting (pre-update) conditions + ok(!a5.isCompatible, "addon5 should not be compatible"); + ok(!a6.isCompatible, "addon6 should not be compatible"); + + open_compatibility_window(disabledAddonIds, function(aWindow) { + var doc = aWindow.document; + wait_for_page(aWindow, "mismatch", function(aWindow) { + var items = get_list_names(doc.getElementById("mismatch.incompatible")); + // Check that compatibility updates from individual add-on update checks were applied. + is(items.length, 4, "Should have seen 4 still incompatible items"); + is(items[0], "Addon3 1.0", "Should have seen addon3 still incompatible"); + is(items[1], "Addon7 1.0", "Should have seen addon7 still incompatible"); + is(items[2], "Addon8 1.0", "Should have seen addon8 still incompatible"); + is(items[3], "Addon9 1.0", "Should have seen addon9 still incompatible"); + + // If it wasn't disabled by this run, we don't try to enable it + ok(!a5.isCompatible, "addon5 should not be compatible"); + ok(a6.isCompatible, "addon6 should be compatible"); + + var button = doc.documentElement.getButton("next"); + EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); + + wait_for_page(aWindow, "found", function(aWindow) { + ok(doc.getElementById("xpinstallDisabledAlert").hidden, + "Install should be allowed"); + + var list = doc.getElementById("found.updates"); + var items = get_list_names(list); + is(items.length, 3, "Should have seen 3 updates available"); + is(items[0], "Addon7 2.0", "Should have seen update for addon7"); + is(items[1], "Addon8 2.0", "Should have seen update for addon8"); + is(items[2], "Addon9 2.0", "Should have seen update for addon9"); + + ok(!doc.documentElement.getButton("next").disabled, + "Next button should be enabled"); + + // Uncheck all + for (let listItem of list.childNodes) + EventUtils.synthesizeMouse(listItem, 2, 2, { }, aWindow); + + ok(doc.documentElement.getButton("next").disabled, + "Next button should not be enabled"); + + // Check the ones we want to install + for (let listItem of list.childNodes) { + if (listItem.label != "Addon7 2.0") + EventUtils.synthesizeMouse(listItem, 2, 2, { }, aWindow); + } + + var button = doc.documentElement.getButton("next"); + EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); + + wait_for_page(aWindow, "finished", function(aWindow) { + var button = doc.documentElement.getButton("finish"); + ok(!button.hidden, "Finish button should not be hidden"); + ok(!button.disabled, "Finish button should not be disabled"); + EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); + + wait_for_window_close(aWindow, function() { + AddonManager.getAddonsByIDs(["addon8@tests.mozilla.org", + "addon9@tests.mozilla.org"], + function([a8, a9]) { + is(a8.version, "2.0", "addon8 should have updated"); + is(a9.version, "2.0", "addon9 should have updated"); + + check_telemetry({disabled: 5, metaenabled: 1, metadisabled: 0, + upgraded: 2, failed: 0, declined: 1}); + + uninstall_test_addons(run_next_test); + }); + }); + }); + }); + }); + }); + }); + }); +}); + +// Tests that the install failures show the install failed page and disabling +// xpinstall shows the right UI. +add_test(function failure_page() { + install_test_addons(function() { + // These add-ons become disabled + var disabledAddonIds = [ + "addon3@tests.mozilla.org", + "addon6@tests.mozilla.org", + "addon7@tests.mozilla.org", + "addon8@tests.mozilla.org", + "addon9@tests.mozilla.org" + ]; + + Services.prefs.setBoolPref("xpinstall.enabled", false); + + open_compatibility_window(disabledAddonIds, function(aWindow) { + var doc = aWindow.document; + wait_for_page(aWindow, "mismatch", function(aWindow) { + var items = get_list_names(doc.getElementById("mismatch.incompatible")); + is(items.length, 4, "Should have seen 4 still incompatible items"); + is(items[0], "Addon3 1.0", "Should have seen addon3 still incompatible"); + is(items[1], "Addon7 1.0", "Should have seen addon7 still incompatible"); + is(items[2], "Addon8 1.0", "Should have seen addon8 still incompatible"); + is(items[3], "Addon9 1.0", "Should have seen addon9 still incompatible"); + + // Check that compatibility updates were applied. + AddonManager.getAddonsByIDs(["addon5@tests.mozilla.org", + "addon6@tests.mozilla.org"], + function([a5, a6]) { + ok(!a5.isCompatible, "addon5 should not be compatible"); + ok(a6.isCompatible, "addon6 should be compatible"); + + var button = doc.documentElement.getButton("next"); + EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); + + wait_for_page(aWindow, "found", function(aWindow) { + ok(!doc.getElementById("xpinstallDisabledAlert").hidden, + "Install should not be allowed"); + + ok(doc.documentElement.getButton("next").disabled, + "Next button should be disabled"); + + var checkbox = doc.getElementById("enableXPInstall"); + EventUtils.synthesizeMouse(checkbox, 2, 2, { }, aWindow); + + ok(!doc.documentElement.getButton("next").disabled, + "Next button should be enabled"); + + var list = doc.getElementById("found.updates"); + var items = get_list_names(list); + is(items.length, 3, "Should have seen 3 updates available"); + is(items[0], "Addon7 2.0", "Should have seen update for addon7"); + is(items[1], "Addon8 2.0", "Should have seen update for addon8"); + is(items[2], "Addon9 2.0", "Should have seen update for addon9"); + + // Unheck the ones we don't want to install + for (let listItem of list.childNodes) { + if (listItem.label != "Addon7 2.0") + EventUtils.synthesizeMouse(listItem, 2, 2, { }, aWindow); + } + + var button = doc.documentElement.getButton("next"); + EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); + + wait_for_page(aWindow, "installerrors", function(aWindow) { + var button = doc.documentElement.getButton("finish"); + ok(!button.hidden, "Finish button should not be hidden"); + ok(!button.disabled, "Finish button should not be disabled"); + + wait_for_window_close(aWindow, function() { + uninstall_test_addons(run_next_test); + }); + + check_telemetry({disabled: 5, metaenabled: 1, metadisabled: 0, + upgraded: 0, failed: 1, declined: 2}); + + EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); + }); + }); + }); + }); + }); + }); +}); + +// Tests that no add-ons show up in the mismatch dialog when they are all disabled +add_test(function all_disabled() { + install_test_addons(function() { + 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", + "addon8@tests.mozilla.org", + "addon9@tests.mozilla.org", + "addon10@tests.mozilla.org"], + function(aAddons) { + for (let addon of aAddons) + addon.userDisabled = true; + + open_compatibility_window([], function(aWindow) { + // Should close immediately on its own + wait_for_window_close(aWindow, function() { + uninstall_test_addons(run_next_test); + }); + }); + }); + }); +}); + +// Tests that the right UI shows for when no updates are available +add_test(function no_updates() { + install_test_addons(function() { + AddonManager.getAddonsByIDs(["addon7@tests.mozilla.org", + "addon8@tests.mozilla.org", + "addon9@tests.mozilla.org", + "addon10@tests.mozilla.org"], + function(aAddons) { + for (let addon of aAddons) + addon.uninstall(); + + // These add-ons were disabled by the upgrade + var inactiveAddonIds = [ + "addon3@tests.mozilla.org", + "addon5@tests.mozilla.org", + "addon6@tests.mozilla.org" + ]; + + open_compatibility_window(inactiveAddonIds, function(aWindow) { + var doc = aWindow.document; + wait_for_page(aWindow, "mismatch", function(aWindow) { + var items = get_list_names(doc.getElementById("mismatch.incompatible")); + is(items.length, 1, "Should have seen 1 still incompatible items"); + is(items[0], "Addon3 1.0", "Should have seen addon3 still incompatible"); + + var button = doc.documentElement.getButton("next"); + EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); + + wait_for_page(aWindow, "noupdates", function(aWindow) { + var button = doc.documentElement.getButton("finish"); + ok(!button.hidden, "Finish button should not be hidden"); + ok(!button.disabled, "Finish button should not be disabled"); + + wait_for_window_close(aWindow, function() { + uninstall_test_addons(run_next_test); + }); + + EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); + }); + }); + }); + }); + }); +}); + +// Tests that compatibility overrides are retrieved and affect addon +// compatibility. +add_test(function overrides_retrieved() { + Services.prefs.setBoolPref(PREF_STRICT_COMPAT, false); + Services.prefs.setCharPref(PREF_MIN_PLATFORM_COMPAT, "0"); + is(AddonManager.strictCompatibility, false, "Strict compatibility should be disabled"); + + // Use a blank update URL + Services.prefs.setCharPref(PREF_UPDATEURL, TESTROOT + "missing.rdf"); + + install_test_addons(function() { + + 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", + "addon8@tests.mozilla.org", + "addon9@tests.mozilla.org", + "addon10@tests.mozilla.org"], + function(aAddons) { + + for (let addon of aAddons) { + if (addon.id == "addon10@tests.mozilla.org") + is(addon.isCompatible, true, "Addon10 should be compatible before compat overrides are refreshed"); + else + addon.uninstall(); + } + + Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, TESTROOT + "browser_bug557956.xml"); + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); + + open_compatibility_window([], function(aWindow) { + var doc = aWindow.document; + wait_for_page(aWindow, "mismatch", function(aWindow) { + var items = get_list_names(doc.getElementById("mismatch.incompatible")); + is(items.length, 1, "Should have seen 1 incompatible item"); + is(items[0], "Addon10 1.0", "Should have seen addon10 as incompatible"); + + var button = doc.documentElement.getButton("next"); + EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); + + wait_for_page(aWindow, "noupdates", function(aWindow) { + var button = doc.documentElement.getButton("finish"); + ok(!button.hidden, "Finish button should not be hidden"); + ok(!button.disabled, "Finish button should not be disabled"); + + wait_for_window_close(aWindow, function() { + uninstall_test_addons(run_next_test); + }); + + check_telemetry({disabled: 0, metaenabled: 0, metadisabled: 1, + upgraded: 0, failed: 0, declined: 0}); + + EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); + }); + }); + }); + }); + }); +}); + +add_test(function test_shutdown() { + TelemetrySession.shutdown().then(run_next_test); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug557956.rdf b/toolkit/mozapps/extensions/test/browser/browser_bug557956.rdf new file mode 100644 index 000000000..eebf6c0f9 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug557956.rdf @@ -0,0 +1,220 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <RDF:Description about="urn:mozilla:extension:addon1@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>1.0</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:addon2@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>1.0</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>0</em:maxVersion> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:addon3@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>1.0</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>0</em:maxVersion> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:addon4@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>1.0</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:addon5@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>1.0</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:addon6@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>1.0</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:addon7@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>1.0</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>0</em:maxVersion> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + <RDF:li> + <RDF:Description> + <em:version>2.0</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + <em:updateLink>http://example.com/browser/toolkit/mozapps/extensions/test/browser/browser_bug557956_7_2.xpi</em:updateLink> + <em:updateHash>sha1:18674cf7ad76664e0ead6280a43cc0c681180505</em:updateHash> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:addon8@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>1.0</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>0</em:maxVersion> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + <RDF:li> + <RDF:Description> + <em:version>2.0</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + <em:updateLink>http://example.com/browser/toolkit/mozapps/extensions/test/browser/browser_bug557956_8_2.xpi</em:updateLink> + <em:updateHash>sha1:d6240607c4f202226fa291d9b7e537ff2a309616</em:updateHash> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:addon9@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>1.0</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>0</em:maxVersion> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + <RDF:li> + <RDF:Description> + <em:version>2.0</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + <em:updateLink>http://example.com/browser/toolkit/mozapps/extensions/test/browser/browser_bug557956_9_2.xpi</em:updateLink> + <em:updateHash>sha1:b25d1ee94acc734a4a039d31c1620051bbbd5633</em:updateHash> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + +</RDF:RDF> + diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug557956.xml b/toolkit/mozapps/extensions/test/browser/browser_bug557956.xml new file mode 100644 index 000000000..6184e5214 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug557956.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8" ?> +<searchresults total_results="1"> + <addon_compatibility hosted="false"> + <guid>addon10@tests.mozilla.org</guid> + <name>Addon10</name> + <version_ranges> + <version_range type="incompatible"> + <min_version>1.0</min_version> + <max_version>2.0</max_version> + <compatible_applications> + <application> + <min_version>0.1</min_version> + <max_version>999.0</max_version> + <appID>toolkit@mozilla.org</appID> + </application> + </compatible_applications> + </version_range> + </version_ranges> + </addon_compatibility> +</searchresults> diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug557956_8_2.xpi b/toolkit/mozapps/extensions/test/browser/browser_bug557956_8_2.xpi Binary files differnew file mode 100644 index 000000000..9476a8907 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug557956_8_2.xpi diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug557956_9_2.xpi b/toolkit/mozapps/extensions/test/browser/browser_bug557956_9_2.xpi Binary files differnew file mode 100644 index 000000000..df7673672 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug557956_9_2.xpi diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug562797.js b/toolkit/mozapps/extensions/test/browser/browser_bug562797.js new file mode 100644 index 000000000..6560e9a2c --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug562797.js @@ -0,0 +1,965 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +/** + * Tests that history navigation works for the add-ons manager. + */ + +const MAIN_URL = "https://example.com/" + RELATIVE_DIR + "discovery.html"; +const SECOND_URL = "https://example.com/" + RELATIVE_DIR + "releaseNotes.xhtml"; + +var gLoadCompleteCallback = null; + +var gProgressListener = { + onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) { + // Only care about the network stop status events + if (!(aStateFlags & (Ci.nsIWebProgressListener.STATE_IS_NETWORK)) || + !(aStateFlags & (Ci.nsIWebProgressListener.STATE_STOP))) + return; + + if (gLoadCompleteCallback) + executeSoon(gLoadCompleteCallback); + gLoadCompleteCallback = null; + }, + + onLocationChange: function() { }, + onSecurityChange: function() { }, + onProgressChange: function() { }, + onStatusChange: function() { }, + + QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener, + Ci.nsISupportsWeakReference]), +}; + +function waitForLoad(aManager, aCallback) { + var browser = aManager.document.getElementById("discover-browser"); + browser.addProgressListener(gProgressListener); + + gLoadCompleteCallback = function() { + browser.removeProgressListener(gProgressListener); + aCallback(); + }; +} + +function clickLink(aManager, aId, aCallback) { + waitForLoad(aManager, aCallback); + + var browser = aManager.document.getElementById("discover-browser"); + + var link = browser.contentDocument.getElementById(aId); + EventUtils.sendMouseEvent({type: "click"}, link); +} + +function test() { + requestLongerTimeout(2); + + waitForExplicitFinish(); + + Services.prefs.setCharPref(PREF_DISCOVERURL, MAIN_URL); + + var gProvider = new MockProvider(); + gProvider.createAddons([{ + id: "test1@tests.mozilla.org", + name: "Test add-on 1", + description: "foo" + }, + { + id: "test2@tests.mozilla.org", + name: "Test add-on 2", + description: "bar" + }, + { + id: "test3@tests.mozilla.org", + name: "Test add-on 3", + type: "theme", + description: "bar" + }]); + + run_next_test(); +} + +function end_test() { + finish(); +} + +function go_back(aManager) { + if (gUseInContentUI) { + gBrowser.goBack(); + } else { + EventUtils.synthesizeMouseAtCenter(aManager.document.getElementById("back-btn"), + { }, aManager); + } +} + +function go_back_backspace(aManager) { + EventUtils.synthesizeKey("VK_BACK_SPACE",{}); +} + +function go_forward_backspace(aManager) { + EventUtils.synthesizeKey("VK_BACK_SPACE",{shiftKey: true}); +} + +function go_forward(aManager) { + if (gUseInContentUI) { + gBrowser.goForward(); + } else { + EventUtils.synthesizeMouseAtCenter(aManager.document.getElementById("forward-btn"), + { }, aManager); + } +} + +function check_state(aManager, canGoBack, canGoForward) { + var doc = aManager.document; + + if (gUseInContentUI) { + is(gBrowser.canGoBack, canGoBack, "canGoBack should be correct"); + is(gBrowser.canGoForward, canGoForward, "canGoForward should be correct"); + } + + if (!is_hidden(doc.getElementById("back-btn"))) { + is(!doc.getElementById("back-btn").disabled, canGoBack, "Back button should have the right state"); + is(!doc.getElementById("forward-btn").disabled, canGoForward, "Forward button should have the right state"); + } +} + +function is_in_list(aManager, view, canGoBack, canGoForward) { + var doc = aManager.document; + + is(doc.getElementById("categories").selectedItem.value, view, "Should be on the right category"); + is(doc.getElementById("view-port").selectedPanel.id, "list-view", "Should be on the right view"); + + check_state(aManager, canGoBack, canGoForward); +} + +function is_in_search(aManager, query, canGoBack, canGoForward) { + var doc = aManager.document; + + is(doc.getElementById("categories").selectedItem.value, "addons://search/", "Should be on the right category"); + is(doc.getElementById("view-port").selectedPanel.id, "search-view", "Should be on the right view"); + is(doc.getElementById("header-search").value, query, "Should have used the right query"); + + check_state(aManager, canGoBack, canGoForward); +} + +function is_in_detail(aManager, view, canGoBack, canGoForward) { + var doc = aManager.document; + + is(doc.getElementById("categories").selectedItem.value, view, "Should be on the right category"); + is(doc.getElementById("view-port").selectedPanel.id, "detail-view", "Should be on the right view"); + + check_state(aManager, canGoBack, canGoForward); +} + +function is_in_discovery(aManager, url, canGoBack, canGoForward) { + var browser = aManager.document.getElementById("discover-browser"); + + is(aManager.document.getElementById("discover-view").selectedPanel, browser, + "Browser should be visible"); + + var spec = browser.currentURI.spec; + var pos = spec.indexOf("#"); + if (pos != -1) + spec = spec.substring(0, pos); + + is(spec, url, "Should have loaded the right url"); + + check_state(aManager, canGoBack, canGoForward); +} + +function double_click_addon_element(aManager, aId) { + var addon = get_addon_element(aManager, aId); + addon.parentNode.ensureElementIsVisible(addon); + EventUtils.synthesizeMouseAtCenter(addon, { clickCount: 1 }, aManager); + EventUtils.synthesizeMouseAtCenter(addon, { clickCount: 2 }, aManager); +} + +// Tests simple forward and back navigation and that the right heading and +// category is selected +add_test(function() { + open_manager("addons://list/extension", function(aManager) { + info("Part 1"); + is_in_list(aManager, "addons://list/extension", false, false); + + EventUtils.synthesizeMouseAtCenter(aManager.document.getElementById("category-plugin"), { }, aManager); + + wait_for_view_load(aManager, function(aManager) { + info("Part 2"); + is_in_list(aManager, "addons://list/plugin", true, false); + + go_back(aManager); + + wait_for_view_load(aManager, function(aManager) { + info("Part 3"); + is_in_list(aManager, "addons://list/extension", false, true); + + go_forward(aManager); + + wait_for_view_load(aManager, function(aManager) { + info("Part 4"); + is_in_list(aManager, "addons://list/plugin", true, false); + + go_back(aManager); + + wait_for_view_load(aManager, function(aManager) { + info("Part 5"); + is_in_list(aManager, "addons://list/extension", false, true); + + double_click_addon_element(aManager, "test1@tests.mozilla.org"); + + wait_for_view_load(aManager, function(aManager) { + info("Part 6"); + is_in_detail(aManager, "addons://list/extension", true, false); + + go_back(aManager); + + wait_for_view_load(aManager, function(aManager) { + info("Part 7"); + is_in_list(aManager, "addons://list/extension", false, true); + + close_manager(aManager, run_next_test); + }); + }); + }); + }); + }); + }); + }); +}); + +// Tests that browsing to the add-ons manager from a website and going back works +// Only relevant for in-content UI +add_test(function() { + if (!gUseInContentUI) { + run_next_test(); + return; + } + + info("Part 1"); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI("http://example.com/"); + gBrowser.addEventListener("pageshow", function(event) { + if (event.target.location != "http://example.com/") + return; + gBrowser.removeEventListener("pageshow", arguments.callee, false); + + //Must let the load complete for it to go into the session history + executeSoon(function() { + info("Part 2"); + ok(!gBrowser.canGoBack, "Should not be able to go back"); + ok(!gBrowser.canGoForward, "Should not be able to go forward"); + + gBrowser.loadURI("about:addons"); + gBrowser.addEventListener("pageshow", function(event) { + if (event.target.location != "about:addons") + return; + gBrowser.removeEventListener("pageshow", arguments.callee, true); + + wait_for_view_load(gBrowser.contentWindow.wrappedJSObject, function(aManager) { + info("Part 3"); + is_in_list(aManager, "addons://list/extension", true, false); + + executeSoon(() => go_back(aManager)); + gBrowser.addEventListener("pageshow", function() { + gBrowser.removeEventListener("pageshow", arguments.callee, false); + info("Part 4"); + executeSoon(() => executeSoon(function () { + is(gBrowser.currentURI.spec, "http://example.com/", "Should be showing the webpage"); + ok(!gBrowser.canGoBack, "Should not be able to go back"); + ok(gBrowser.canGoForward, "Should be able to go forward"); + + go_forward(aManager); + gBrowser.addEventListener("pageshow", function() { + gBrowser.removeEventListener("pageshow", arguments.callee, false); + wait_for_view_load(gBrowser.contentWindow.wrappedJSObject, function(aManager) { + info("Part 5"); + is_in_list(aManager, "addons://list/extension", true, false); + + close_manager(aManager, run_next_test); + }); + }, false); + })); + }, false); + }); + }, true); + }); + }, false); +}); + +// Tests simple forward and back navigation and that the right heading and +// category is selected -- Keyboard navigation [Bug 565359] +// Only add the test if the backspace key navigates back and addon-manager +// loaded in a tab +add_test(function() { + + if (!gUseInContentUI || (Services.prefs.getIntPref("browser.backspace_action") != 0)) { + run_next_test(); + return; + } + + open_manager("addons://list/extension", function(aManager) { + info("Part 1"); + is_in_list(aManager, "addons://list/extension", false, false); + + EventUtils.synthesizeMouseAtCenter(aManager.document.getElementById("category-plugin"), { }, aManager); + + wait_for_view_load(aManager, function(aManager) { + info("Part 2"); + is_in_list(aManager, "addons://list/plugin", true, false); + + go_back_backspace(aManager); + + wait_for_view_load(aManager, function(aManager) { + info("Part 3"); + is_in_list(aManager, "addons://list/extension", false, true); + + go_forward_backspace(aManager); + + wait_for_view_load(aManager, function(aManager) { + info("Part 4"); + is_in_list(aManager, "addons://list/plugin", true, false); + + go_back_backspace(aManager); + + wait_for_view_load(aManager, function(aManager) { + info("Part 5"); + is_in_list(aManager, "addons://list/extension", false, true); + + double_click_addon_element(aManager, "test1@tests.mozilla.org"); + + wait_for_view_load(aManager, function(aManager) { + info("Part 6"); + is_in_detail(aManager, "addons://list/extension", true, false); + + go_back_backspace(aManager); + + wait_for_view_load(aManager, function(aManager) { + info("Part 7"); + is_in_list(aManager, "addons://list/extension", false, true); + + close_manager(aManager, run_next_test); + }); + }); + }); + }); + }); + }); + }); +}); + + +// Tests that opening a custom first view only stores a single history entry +add_test(function() { + open_manager("addons://list/plugin", function(aManager) { + info("Part 1"); + is_in_list(aManager, "addons://list/plugin", false, false); + + EventUtils.synthesizeMouseAtCenter(aManager.document.getElementById("category-extension"), { }, aManager); + + wait_for_view_load(aManager, function(aManager) { + info("Part 2"); + is_in_list(aManager, "addons://list/extension", true, false); + + go_back(aManager); + + wait_for_view_load(aManager, function(aManager) { + info("Part 3"); + is_in_list(aManager, "addons://list/plugin", false, true); + + close_manager(aManager, run_next_test); + }); + }); + }); +}); + + +// Tests that opening a view while the manager is already open adds a new +// history entry +add_test(function() { + open_manager("addons://list/extension", function(aManager) { + info("Part 1"); + is_in_list(aManager, "addons://list/extension", false, false); + + aManager.loadView("addons://list/plugin"); + + wait_for_view_load(aManager, function(aManager) { + info("Part 2"); + is_in_list(aManager, "addons://list/plugin", true, false); + + go_back(aManager); + + wait_for_view_load(aManager, function(aManager) { + info("Part 3"); + is_in_list(aManager, "addons://list/extension", false, true); + + go_forward(aManager); + + wait_for_view_load(aManager, function(aManager) { + info("Part 4"); + is_in_list(aManager, "addons://list/plugin", true, false); + + close_manager(aManager, run_next_test); + }); + }); + }); + }); +}); + +// Tests than navigating to a website and then going back returns to the +// previous view +// Only relevant for in-content UI +add_test(function() { + if (!gUseInContentUI) { + run_next_test(); + return; + } + + open_manager("addons://list/plugin", function(aManager) { + info("Part 1"); + is_in_list(aManager, "addons://list/plugin", false, false); + + gBrowser.loadURI("http://example.com/"); + gBrowser.addEventListener("pageshow", function(event) { + if (event.target.location != "http://example.com/") + return; + gBrowser.removeEventListener("pageshow", arguments.callee, false); + info("Part 2"); + + executeSoon(function() { + ok(gBrowser.canGoBack, "Should be able to go back"); + ok(!gBrowser.canGoForward, "Should not be able to go forward"); + + go_back(aManager); + + gBrowser.addEventListener("pageshow", function(event) { + if (event.target.location != "about:addons") + return; + gBrowser.removeEventListener("pageshow", arguments.callee, false); + + wait_for_view_load(gBrowser.contentWindow.wrappedJSObject, function(aManager) { + info("Part 3"); + is_in_list(aManager, "addons://list/plugin", false, true); + + executeSoon(() => go_forward(aManager)); + gBrowser.addEventListener("pageshow", function(event) { + if (event.target.location != "http://example.com/") + return; + gBrowser.removeEventListener("pageshow", arguments.callee, false); + info("Part 4"); + + executeSoon(function() { + ok(gBrowser.canGoBack, "Should be able to go back"); + ok(!gBrowser.canGoForward, "Should not be able to go forward"); + + go_back(aManager); + + gBrowser.addEventListener("pageshow", function(event) { + if (event.target.location != "about:addons") + return; + gBrowser.removeEventListener("pageshow", arguments.callee, false); + wait_for_view_load(gBrowser.contentWindow.wrappedJSObject, function(aManager) { + info("Part 5"); + is_in_list(aManager, "addons://list/plugin", false, true); + + close_manager(aManager, run_next_test); + }); + }, false); + }); + }, false); + }); + }, false); + }); + }, false); + }); +}); + +// Tests that going back to search results works +add_test(function() { + // Before we open the add-ons manager, we should make sure that no filter + // has been set. If one is set, we remove it. + // This is for the check below, from bug 611459. + let store = Cc["@mozilla.org/xul/xulstore;1"].getService(Ci.nsIXULStore); + store.removeValue("about:addons", "search-filter-radiogroup", "value"); + + open_manager("addons://list/extension", function(aManager) { + info("Part 1"); + is_in_list(aManager, "addons://list/extension", false, false); + + var search = aManager.document.getElementById("header-search"); + search.focus(); + search.value = "bar"; + EventUtils.synthesizeKey("VK_RETURN", {}, aManager); + + wait_for_view_load(aManager, function(aManager) { + // Remote search is meant to be checked by default (bug 611459), so we + // confirm that and then switch to a local search. + var localFilter = aManager.document.getElementById("search-filter-local"); + var remoteFilter = aManager.document.getElementById("search-filter-remote"); + + is(remoteFilter.selected, true, "Remote filter should be set by default"); + + var list = aManager.document.getElementById("search-list"); + list.ensureElementIsVisible(localFilter); + EventUtils.synthesizeMouseAtCenter(localFilter, { }, aManager); + + is(localFilter.selected, true, "Should have changed to local filter"); + + // Now we continue with the normal test. + + info("Part 2"); + is_in_search(aManager, "bar", true, false); + check_all_in_list(aManager, ["test2@tests.mozilla.org", "test3@tests.mozilla.org"]); + + double_click_addon_element(aManager, "test2@tests.mozilla.org"); + + wait_for_view_load(aManager, function(aManager) { + info("Part 3"); + is_in_detail(aManager, "addons://search/", true, false); + + go_back(aManager); + wait_for_view_load(aManager, function(aManager) { + info("Part 4"); + is_in_search(aManager, "bar", true, true); + check_all_in_list(aManager, ["test2@tests.mozilla.org", "test3@tests.mozilla.org"]); + + go_forward(aManager); + wait_for_view_load(aManager, function(aManager) { + info("Part 5"); + is_in_detail(aManager, "addons://search/", true, false); + + close_manager(aManager, run_next_test); + }); + }); + }); + }); + }); +}); + +// Tests that going back from a webpage to a detail view loaded from a search +// result works +// Only relevant for in-content UI +add_test(function() { + if (!gUseInContentUI) { + run_next_test(); + return; + } + + open_manager("addons://list/extension", function(aManager) { + info("Part 1"); + is_in_list(aManager, "addons://list/extension", false, false); + + var search = aManager.document.getElementById("header-search"); + search.focus(); + search.value = "bar"; + EventUtils.synthesizeKey("VK_RETURN", {}); + + wait_for_view_load(aManager, function(aManager) { + info("Part 2"); + is_in_search(aManager, "bar", true, false); + check_all_in_list(aManager, ["test2@tests.mozilla.org", "test3@tests.mozilla.org"]); + + double_click_addon_element(aManager, "test2@tests.mozilla.org"); + + wait_for_view_load(aManager, function(aManager) { + info("Part 3"); + is_in_detail(aManager, "addons://search/", true, false); + + gBrowser.loadURI("http://example.com/"); + gBrowser.addEventListener("pageshow", function(event) { + if (event.target.location != "http://example.com/") + return; + gBrowser.removeEventListener("pageshow", arguments.callee, false); + + info("Part 4"); + executeSoon(function() { + ok(gBrowser.canGoBack, "Should be able to go back"); + ok(!gBrowser.canGoForward, "Should not be able to go forward"); + + go_back(aManager); + gBrowser.addEventListener("pageshow", function(event) { + if (event.target.location != "about:addons") + return; + gBrowser.removeEventListener("pageshow", arguments.callee, false); + + wait_for_view_load(gBrowser.contentWindow.wrappedJSObject, function(aManager) { + info("Part 5"); + is_in_detail(aManager, "addons://search/", true, true); + + go_back(aManager); + wait_for_view_load(aManager, function(aManager) { + info("Part 6"); + is_in_search(aManager, "bar", true, true); + check_all_in_list(aManager, ["test2@tests.mozilla.org", "test3@tests.mozilla.org"]); + + close_manager(aManager, run_next_test); + }); + }); + }, false); + }); + }, false); + }); + }); + }); +}); + +// Tests that refreshing a list view does not affect the history +// Only relevant for in-content UI +add_test(function() { + if (!gUseInContentUI) { + run_next_test(); + return; + } + + open_manager("addons://list/extension", function(aManager) { + info("Part 1"); + is_in_list(aManager, "addons://list/extension", false, false); + + EventUtils.synthesizeMouseAtCenter(aManager.document.getElementById("category-plugin"), { }, aManager); + + wait_for_view_load(aManager, function(aManager) { + info("Part 2"); + is_in_list(aManager, "addons://list/plugin", true, false); + + gBrowser.reload(); + gBrowser.addEventListener("pageshow", function(event) { + if (event.target.location != "about:addons") + return; + gBrowser.removeEventListener("pageshow", arguments.callee, false); + + wait_for_view_load(gBrowser.contentWindow.wrappedJSObject, function(aManager) { + info("Part 3"); + is_in_list(aManager, "addons://list/plugin", true, false); + + go_back(aManager); + wait_for_view_load(aManager, function(aManager) { + info("Part 4"); + is_in_list(aManager, "addons://list/extension", false, true); + + close_manager(aManager, run_next_test); + }); + }); + }, false); + }); + }); +}); + +// Tests that refreshing a detail view does not affect the history +// Only relevant for in-content UI +add_test(function() { + if (!gUseInContentUI) { + run_next_test(); + return; + } + + open_manager(null, function(aManager) { + info("Part 1"); + is_in_list(aManager, "addons://list/extension", false, false); + + double_click_addon_element(aManager, "test1@tests.mozilla.org"); + + wait_for_view_load(aManager, function(aManager) { + info("Part 2"); + is_in_detail(aManager, "addons://list/extension", true, false); + + gBrowser.reload(); + gBrowser.addEventListener("pageshow", function(event) { + if (event.target.location != "about:addons") + return; + gBrowser.removeEventListener("pageshow", arguments.callee, false); + + wait_for_view_load(gBrowser.contentWindow.wrappedJSObject, function(aManager) { + info("Part 3"); + is_in_detail(aManager, "addons://list/extension", true, false); + + go_back(aManager); + wait_for_view_load(aManager, function(aManager) { + info("Part 4"); + is_in_list(aManager, "addons://list/extension", false, true); + + close_manager(aManager, run_next_test); + }); + }); + }, false); + }); + }); +}); + +// Tests that removing an extension from the detail view goes back and doesn't +// allow you to go forward again. +add_test(function() { + open_manager("addons://list/extension", function(aManager) { + info("Part 1"); + is_in_list(aManager, "addons://list/extension", false, false); + + double_click_addon_element(aManager, "test1@tests.mozilla.org"); + + wait_for_view_load(aManager, function(aManager) { + info("Part 2"); + is_in_detail(aManager, "addons://list/extension", true, false); + + EventUtils.synthesizeMouseAtCenter(aManager.document.getElementById("detail-uninstall-btn"), + { }, aManager); + + wait_for_view_load(aManager, function() { + if (gUseInContentUI) { + // TODO until bug 590661 is fixed the back button will be enabled + // when displaying in content + is_in_list(aManager, "addons://list/extension", true, false); + } else { + is_in_list(aManager, "addons://list/extension", false, false); + } + + close_manager(aManager, run_next_test); + }); + }); + }); +}); + +// Tests that the back and forward buttons only show up for windowed mode +add_test(function() { + open_manager(null, function(aManager) { + var doc = aManager.document; + + if (gUseInContentUI) { + var btn = document.getElementById("back-button"); + if (!btn || is_hidden(btn)) { + is_element_visible(doc.getElementById("back-btn"), "Back button should not be hidden"); + is_element_visible(doc.getElementById("forward-btn"), "Forward button should not be hidden"); + } else { + is_element_hidden(doc.getElementById("back-btn"), "Back button should be hidden"); + is_element_hidden(doc.getElementById("forward-btn"), "Forward button should be hidden"); + } + } else { + is_element_visible(doc.getElementById("back-btn"), "Back button should not be hidden"); + is_element_visible(doc.getElementById("forward-btn"), "Forward button should not be hidden"); + } + + close_manager(aManager, run_next_test); + }); +}); + +// Tests that opening the manager opens the last view +add_test(function() { + open_manager("addons://list/plugin", function(aManager) { + info("Part 1"); + is_in_list(aManager, "addons://list/plugin", false, false); + + close_manager(aManager, function() { + open_manager(null, function(aManager) { + info("Part 2"); + is_in_list(aManager, "addons://list/plugin", false, false); + + close_manager(aManager, run_next_test); + }); + }); + }); +}); + +// Tests that navigating the discovery page works when that was the first view +add_test(function() { + open_manager("addons://discover/", function(aManager) { + info("1"); + is_in_discovery(aManager, MAIN_URL, false, false); + + clickLink(aManager, "link-good", function() { + info("2"); + is_in_discovery(aManager, SECOND_URL, true, false); + + waitForLoad(aManager, function() { + info("3"); + is_in_discovery(aManager, MAIN_URL, false, true); + + waitForLoad(aManager, function() { + is_in_discovery(aManager, SECOND_URL, true, false); + + EventUtils.synthesizeMouseAtCenter(aManager.document.getElementById("category-plugin"), { }, aManager); + + wait_for_view_load(aManager, function(aManager) { + is_in_list(aManager, "addons://list/plugin", true, false); + + go_back(aManager); + + wait_for_view_load(aManager, function(aManager) { + is_in_discovery(aManager, SECOND_URL, true, true); + + go_back(aManager); + + waitForLoad(aManager, function() { + is_in_discovery(aManager, MAIN_URL, false, true); + + close_manager(aManager, run_next_test); + }); + }); + }); + }); + + go_forward(aManager); + }); + + go_back(aManager); + }); + }); +}); + +// Tests that navigating the discovery page works when that was the second view +add_test(function() { + open_manager("addons://list/plugin", function(aManager) { + is_in_list(aManager, "addons://list/plugin", false, false); + + EventUtils.synthesizeMouseAtCenter(aManager.document.getElementById("category-discover"), { }, aManager); + + wait_for_view_load(aManager, function(aManager) { + is_in_discovery(aManager, MAIN_URL, true, false); + + clickLink(aManager, "link-good", function() { + is_in_discovery(aManager, SECOND_URL, true, false); + + waitForLoad(aManager, function() { + is_in_discovery(aManager, MAIN_URL, true, true); + + waitForLoad(aManager, function() { + is_in_discovery(aManager, SECOND_URL, true, false); + + EventUtils.synthesizeMouseAtCenter(aManager.document.getElementById("category-plugin"), { }, aManager); + + wait_for_view_load(aManager, function(aManager) { + is_in_list(aManager, "addons://list/plugin", true, false); + + go_back(aManager); + + wait_for_view_load(aManager, function(aManager) { + is_in_discovery(aManager, SECOND_URL, true, true); + + go_back(aManager); + + waitForLoad(aManager, function() { + is_in_discovery(aManager, MAIN_URL, true, true); + + go_back(aManager); + + wait_for_view_load(aManager, function(aManager) { + is_in_list(aManager, "addons://list/plugin", false, true); + + go_forward(aManager); + + wait_for_view_load(aManager, function(aManager) { + is_in_discovery(aManager, MAIN_URL, true, true); + + waitForLoad(aManager, function() { + is_in_discovery(aManager, SECOND_URL, true, true); + + close_manager(aManager, run_next_test); + }); + + go_forward(aManager); + }); + }); + }); + }); + }); + }); + + go_forward(aManager); + }); + + go_back(aManager); + }); + }); + }); +}); + +// Tests that when displaying in-content and opened in the background the back +// and forward buttons still appear when switching tabs +add_test(function() { + if (!gUseInContentUI) { + run_next_test(); + return; + } + + var tab = gBrowser.addTab("about:addons"); + var browser = gBrowser.getBrowserForTab(tab); + + browser.addEventListener("pageshow", function(event) { + if (event.target.location.href != "about:addons") + return; + browser.removeEventListener("pageshow", arguments.callee, true); + + wait_for_manager_load(browser.contentWindow.wrappedJSObject, function() { + wait_for_view_load(browser.contentWindow.wrappedJSObject, function(aManager) { + gBrowser.selectedTab = tab; + + var doc = aManager.document; + var btn = document.getElementById("back-button"); + if (!btn || is_hidden(btn)) { + is_element_visible(doc.getElementById("back-btn"), "Back button should not be hidden"); + is_element_visible(doc.getElementById("forward-btn"), "Forward button should not be hidden"); + } else { + is_element_hidden(doc.getElementById("back-btn"), "Back button should be hidden"); + is_element_hidden(doc.getElementById("forward-btn"), "Forward button should be hidden"); + } + + close_manager(aManager, run_next_test); + }); + }); + }, true); +}); + +// Tests that refreshing the disicovery pane integrates properly with history +add_test(function() { + open_manager("addons://list/plugin", function(aManager) { + is_in_list(aManager, "addons://list/plugin", false, false); + + EventUtils.synthesizeMouseAtCenter(aManager.document.getElementById("category-discover"), { }, aManager); + + wait_for_view_load(aManager, function(aManager) { + is_in_discovery(aManager, MAIN_URL, true, false); + + clickLink(aManager, "link-good", function() { + is_in_discovery(aManager, SECOND_URL, true, false); + + EventUtils.synthesizeMouseAtCenter(aManager.document.getElementById("category-discover"), { }, aManager); + + waitForLoad(aManager, function() { + is_in_discovery(aManager, MAIN_URL, true, false); + + go_back(aManager); + + waitForLoad(aManager, function() { + is_in_discovery(aManager, SECOND_URL, true, true); + + go_back(aManager); + + waitForLoad(aManager, function() { + is_in_discovery(aManager, MAIN_URL, true, true); + + go_back(aManager); + + wait_for_view_load(aManager, function(aManager) { + is_in_list(aManager, "addons://list/plugin", false, true); + + go_forward(aManager); + + wait_for_view_load(aManager, function(aManager) { + is_in_discovery(aManager, MAIN_URL, true, true); + + waitForLoad(aManager, function() { + is_in_discovery(aManager, SECOND_URL, true, true); + + waitForLoad(aManager, function() { + is_in_discovery(aManager, MAIN_URL, true, false); + + close_manager(aManager, run_next_test); + }); + go_forward(aManager); + }); + + go_forward(aManager); + }); + }); + }); + }); + }); + }); + }); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug562854.js b/toolkit/mozapps/extensions/test/browser/browser_bug562854.js new file mode 100644 index 000000000..4c06cebb7 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug562854.js @@ -0,0 +1,129 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +/** + * Tests that double-click does not go to detail view if the target is a link or button. + */ + +function test() { + requestLongerTimeout(2); + + waitForExplicitFinish(); + + var gProvider = new MockProvider(); + gProvider.createAddons([{ + id: "test1@tests.mozilla.org", + name: "Test add-on 1", + description: "foo", + operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE + }]); + + run_next_test(); +} + +function end_test() { + finish(); +} + +function is_in_list(aManager, view) { + var doc = aManager.document; + + is(doc.getElementById("categories").selectedItem.value, view, "Should be on the right category"); + is(doc.getElementById("view-port").selectedPanel.id, "list-view", "Should be on the right view"); +} + +function is_in_detail(aManager, view) { + var doc = aManager.document; + + is(doc.getElementById("categories").selectedItem.value, view, "Should be on the right category"); + is(doc.getElementById("view-port").selectedPanel.id, "detail-view", "Should be on the right view"); +} + +// Check that double-click does something. +add_test(function() { + open_manager("addons://list/extension", function(aManager) { + info("Part 1"); + is_in_list(aManager, "addons://list/extension"); + + var addon = get_addon_element(aManager, "test1@tests.mozilla.org"); + addon.parentNode.ensureElementIsVisible(addon); + EventUtils.synthesizeMouseAtCenter(addon, { clickCount: 1 }, aManager); + EventUtils.synthesizeMouseAtCenter(addon, { clickCount: 2 }, aManager); + + wait_for_view_load(aManager, function(aManager) { + info("Part 2"); + is_in_detail(aManager, "addons://list/extension"); + + close_manager(aManager, run_next_test); + }); + }); +}); + +// Check that double-click does nothing when over the disable button. +add_test(function() { + open_manager("addons://list/extension", function(aManager) { + info("Part 1"); + is_in_list(aManager, "addons://list/extension"); + + var addon = get_addon_element(aManager, "test1@tests.mozilla.org"); + addon.parentNode.ensureElementIsVisible(addon); + EventUtils.synthesizeMouseAtCenter( + aManager.document.getAnonymousElementByAttribute(addon, "anonid", "disable-btn"), + { clickCount: 1 }, + aManager + ); + // The disable button is replaced by the enable button when clicked on. + EventUtils.synthesizeMouseAtCenter( + aManager.document.getAnonymousElementByAttribute(addon, "anonid", "enable-btn"), + { clickCount: 2 }, + aManager + ); + + wait_for_view_load(aManager, function(aManager) { + info("Part 2"); + is_in_list(aManager, "addons://list/extension"); + + close_manager(aManager, run_next_test); + }); + }); +}); + +// Check that double-click does nothing when over the undo button. +add_test(function() { + open_manager("addons://list/extension", function(aManager) { + info("Part 1"); + is_in_list(aManager, "addons://list/extension"); + + var addon = get_addon_element(aManager, "test1@tests.mozilla.org"); + addon.parentNode.ensureElementIsVisible(addon); + EventUtils.synthesizeMouseAtCenter( + aManager.document.getAnonymousElementByAttribute(addon, "anonid", "remove-btn"), + { clickCount: 1 }, + aManager + ); + + // The undo button is removed when clicked on. + // We need to wait for the UI to catch up. + setTimeout(function() { + var target = aManager.document.getAnonymousElementByAttribute(addon, "anonid", "undo-btn"); + var rect = target.getBoundingClientRect(); + var addonRect = addon.getBoundingClientRect(); + + EventUtils.synthesizeMouse(target, rect.width / 2, rect.height / 2, { clickCount: 1 }, aManager); + EventUtils.synthesizeMouse(addon, + rect.left - addonRect.left + rect.width / 2, + rect.top - addonRect.top + rect.height / 2, + { clickCount: 2 }, + aManager + ); + + wait_for_view_load(aManager, function(aManager) { + info("Part 2"); + is_in_list(aManager, "addons://list/extension"); + + close_manager(aManager, run_next_test); + }); + }, 0); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug562890.js b/toolkit/mozapps/extensions/test/browser/browser_bug562890.js new file mode 100644 index 000000000..375cb9ef0 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug562890.js @@ -0,0 +1,78 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +/** + * Tests the Preferences button for addons in list view + */ + +function test() { + requestLongerTimeout(2); + + waitForExplicitFinish(); + + var addonPrefsURI = CHROMEROOT + "addon_prefs.xul"; + + var gProvider = new MockProvider(); + gProvider.createAddons([{ + id: "test1@tests.mozilla.org", + name: "Test add-on 1", + description: "foo" + }, + { + id: "test2@tests.mozilla.org", + name: "Test add-on 2", + description: "bar", + optionsURL: addonPrefsURI + }]); + + open_manager("addons://list/extension", function(aManager) { + var addonList = aManager.document.getElementById("addon-list"); + for (var addonItem of addonList.childNodes) { + if (addonItem.hasAttribute("name") && + addonItem.getAttribute("name") == "Test add-on 1") + break; + } + var prefsBtn = aManager.document.getAnonymousElementByAttribute(addonItem, + "anonid", + "preferences-btn"); + is(prefsBtn.hidden, true, "Prefs button should be hidden for addon with no optionsURL set") + + for (addonItem of addonList.childNodes) { + if (addonItem.hasAttribute("name") && + addonItem.getAttribute("name") == "Test add-on 2") + break; + } + prefsBtn = aManager.document.getAnonymousElementByAttribute(addonItem, + "anonid", + "preferences-btn"); + is(prefsBtn.hidden, false, "Prefs button should be shown for addon with a optionsURL set") + + Services.ww.registerNotification(function TEST_ww_observer(aSubject, aTopic, aData) { + if (aTopic == "domwindowclosed") { + Services.ww.unregisterNotification(TEST_ww_observer); + // Give the preference window a chance to finish closing before closing + // the add-ons manager. + executeSoon(function() { + close_manager(aManager, finish); + }); + } else if (aTopic == "domwindowopened") { + let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget); + win = aSubject.QueryInterface(Ci.nsIDOMEventTarget); + win.addEventListener("load", function TEST_ww_onLoad() { + if (win.location != addonPrefsURI) + return; + + win.removeEventListener("load", TEST_ww_onLoad, false); + is(win.location, addonPrefsURI, + "The correct addon pref window should have opened"); + win.close(); + }, false); + } + }); + + addonList.ensureElementIsVisible(addonItem); + EventUtils.synthesizeMouseAtCenter(prefsBtn, { }, aManager); + }); + +} diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug562899.js b/toolkit/mozapps/extensions/test/browser/browser_bug562899.js new file mode 100644 index 000000000..8bfabf004 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug562899.js @@ -0,0 +1,88 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Simulates quickly switching between different list views to verify that only +// the last selected is displayed + +let tempScope = {}; +Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", tempScope); +let LightweightThemeManager = tempScope.LightweightThemeManager; + +const xpi = "browser/toolkit/mozapps/extensions/test/browser/browser_installssl.xpi"; + +var gManagerWindow; +var gCategoryUtilities; + +function test() { + waitForExplicitFinish(); + + // Add a lightweight theme so at least one theme exists + LightweightThemeManager.currentTheme = { + id: "test", + name: "Test lightweight theme", + headerURL: "http://example.com/header.png" + }; + + open_manager(null, function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, function() { + LightweightThemeManager.forgetUsedTheme("test"); + finish(); + }); +} + +// Tests that loading a second view before the first has not finished loading +// does not merge the results +add_test(function() { + var themeCount = null; + var pluginCount = null; + var themeItem = gCategoryUtilities.get("theme"); + var pluginItem = gCategoryUtilities.get("plugin"); + var list = gManagerWindow.document.getElementById("addon-list"); + + gCategoryUtilities.open(themeItem, function() { + themeCount = list.childNodes.length; + ok(themeCount > 0, "Test is useless if there are no themes"); + + gCategoryUtilities.open(pluginItem, function() { + pluginCount = list.childNodes.length; + ok(pluginCount > 0, "Test is useless if there are no plugins"); + + gCategoryUtilities.open(themeItem); + + gCategoryUtilities.open(pluginItem, function() { + is(list.childNodes.length, pluginCount, "Should only see the plugins"); + + var item = list.firstChild; + while (item) { + is(item.getAttribute("type"), "plugin", "All items should be plugins"); + item = item.nextSibling; + } + + // Tests that switching to, from, to the same pane in quick succession + // still only shows the right number of results + + gCategoryUtilities.open(themeItem); + gCategoryUtilities.open(pluginItem); + gCategoryUtilities.open(themeItem, function() { + is(list.childNodes.length, themeCount, "Should only see the theme"); + + var item = list.firstChild; + while (item) { + is(item.getAttribute("type"), "theme", "All items should be theme"); + item = item.nextSibling; + } + + run_next_test(); + }); + }); + }); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug562992.js b/toolkit/mozapps/extensions/test/browser/browser_bug562992.js new file mode 100644 index 000000000..1cd4d90cd --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug562992.js @@ -0,0 +1,70 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * This test ensures that when the extension manager UI is open and a + * restartless extension is installed from the web, its correct name appears + * when the download and installation complete. See bug 562992. + */ + +var gManagerWindow; +var gProvider; +var gInstall; + +const EXTENSION_NAME = "Wunderbar"; + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + open_manager("addons://list/extension", function (aWindow) { + gManagerWindow = aWindow; + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, function () { + finish(); + }); +} + +// Create a MockInstall with a MockAddon payload and add it to the provider, +// causing the onNewInstall event to fire, which in turn will cause a new +// "installing" item to appear in the list of extensions. +add_test(function () { + let addon = new MockAddon(undefined, EXTENSION_NAME, "extension", true); + gInstall = new MockInstall(undefined, undefined, addon); + gInstall.addTestListener({ + onNewInstall: run_next_test + }); + gProvider.addInstall(gInstall); +}); + +// Finish the install, which will cause the "installing" item to be converted +// to an "installed" item, which should have the correct add-on name. +add_test(function () { + gInstall.addTestListener({ + onInstallEnded: function () { + let list = gManagerWindow.document.getElementById("addon-list"); + + // To help prevent future breakage, don't assume the item is the only one + // in the list, or that it's first in the list. Find it by name. + for (let i = 0; i < list.itemCount; i++) { + let item = list.getItemAtIndex(i); + if (item.getAttribute("name") === EXTENSION_NAME) { + ok(true, "Item with correct name found"); + run_next_test(); + return; + } + } + ok(false, "Item with correct name was not found"); + run_next_test(); + } + }); + gInstall.install(); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug567127.js b/toolkit/mozapps/extensions/test/browser/browser_bug567127.js new file mode 100644 index 000000000..5c5dce069 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug567127.js @@ -0,0 +1,137 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests bug 567127 - Add install button to the add-ons manager + +var MockFilePicker = SpecialPowers.MockFilePicker; +MockFilePicker.init(window); + +var gManagerWindow; +var gSawInstallNotification = false; + +// This listens for the next opened window and checks it is of the right url. +// opencallback is called when the new window is fully loaded +// closecallback is called when the window is closed +function WindowOpenListener(url, opencallback, closecallback) { + this.url = url; + this.opencallback = opencallback; + this.closecallback = closecallback; + + var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] + .getService(Components.interfaces.nsIWindowMediator); + wm.addListener(this); +} + +WindowOpenListener.prototype = { + url: null, + opencallback: null, + closecallback: null, + window: null, + domwindow: null, + + handleEvent: function(event) { + is(this.domwindow.document.location.href, this.url, "Should have opened the correct window"); + + this.domwindow.removeEventListener("load", this, false); + // Allow any other load handlers to execute + var self = this; + executeSoon(function() { self.opencallback(self.domwindow); } ); + }, + + onWindowTitleChange: function(window, title) { + }, + + onOpenWindow: function(window) { + if (this.window) + return; + + this.window = window; + this.domwindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIDOMWindow); + this.domwindow.addEventListener("load", this, false); + }, + + onCloseWindow: function(window) { + if (this.window != window) + return; + + var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] + .getService(Components.interfaces.nsIWindowMediator); + wm.removeListener(this); + this.opencallback = null; + this.window = null; + this.domwindow = null; + + // Let the window close complete + executeSoon(this.closecallback); + this.closecallback = null; + } +}; + + +var gInstallNotificationObserver = { + observe: function(aSubject, aTopic, aData) { + var installInfo = aSubject.QueryInterface(Ci.amIWebInstallInfo); + is(installInfo.installs.length, 2, "Should be installing 2 files.") + if (gTestInWindow) + is(installInfo.browser, null, "Notification should have a null browser"); + else + isnot(installInfo.browser, null, "Notification should have non-null browser"); + gSawInstallNotification = true; + Services.obs.removeObserver(this, "addon-install-started"); + } +}; + + +function test_confirmation(aWindow, aExpectedURLs) { + var list = aWindow.document.getElementById("itemList"); + is(list.childNodes.length, aExpectedURLs.length, "Should be the right number of installs"); + + for (let url of aExpectedURLs) { + let found = false; + for (let node of list.children) { + if (node.url == url) { + found = true; + break; + } + } + ok(found, "Should have seen " + url + " in the list"); + } + + aWindow.document.documentElement.cancelDialog(); +} + +add_task(function* test_install_from_file() { + gManagerWindow = yield open_manager("addons://list/extension"); + + var filePaths = [ + get_addon_file_url("browser_bug567127_1.xpi"), + get_addon_file_url("browser_bug567127_2.xpi") + ]; + MockFilePicker.returnFiles = filePaths.map(function(aPath) aPath.file); + + Services.obs.addObserver(gInstallNotificationObserver, + "addon-install-started", false); + + // Set handler that executes the core test after the window opens, + // and resolves the promise when the window closes + let pInstallURIClosed = new Promise((resolve, reject) => { + new WindowOpenListener(INSTALL_URI, function(aWindow) { + try { + test_confirmation(aWindow, filePaths.map(function(aPath) aPath.spec)); + } catch(e) { + reject(e); + } + }, resolve); + }); + + gManagerWindow.gViewController.doCommand("cmd_installFromFile"); + + yield pInstallURIClosed; + + is(gSawInstallNotification, true, "Should have seen addon-install-started notification."); + + MockFilePicker.cleanup(); + yield close_manager(gManagerWindow); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug567137.js b/toolkit/mozapps/extensions/test/browser/browser_bug567137.js new file mode 100644 index 000000000..bb9b9a894 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug567137.js @@ -0,0 +1,40 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test that the selected category is persisted across loads of the manager + +function test() { + waitForExplicitFinish(); + + open_manager(null, function(aWindow) { + let utils = new CategoryUtilities(aWindow); + + // Open the plugins category + utils.openType("plugin", function() { + + // Re-open the manager + close_manager(aWindow, function() { + open_manager(null, function(aWindow) { + utils = new CategoryUtilities(aWindow); + + is(utils.selectedCategory, "plugin", "Should have shown the plugins category"); + + // Open the extensions category + utils.openType("extension", function() { + + // Re-open the manager + close_manager(aWindow, function() { + open_manager(null, function(aWindow) { + utils = new CategoryUtilities(aWindow); + + is(utils.selectedCategory, "extension", "Should have shown the extensions category"); + close_manager(aWindow, finish); + }); + }); + }); + }); + }); + }); + }); +} diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug570760.js b/toolkit/mozapps/extensions/test/browser/browser_bug570760.js new file mode 100644 index 000000000..765665e8c --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug570760.js @@ -0,0 +1,44 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// As part of bug 1077403, the leaking uncaught rejection should be fixed. +thisTestLeaksUncaughtRejectionsAndShouldBeFixed(""); + +// Bug 570760 - Make ctrl-f and / focus the search box in the add-ons manager + +var gManagerWindow; +var focusCount = 0; + +function test() { + waitForExplicitFinish(); + + open_manager(null, function(aWindow) { + gManagerWindow = aWindow; + + var searchBox = gManagerWindow.document.getElementById("header-search"); + function focusHandler() { + searchBox.blur(); + focusCount++; + } + searchBox.addEventListener("focus", focusHandler); + f_key_test(); + slash_key_test(); + searchBox.removeEventListener("focus", focusHandler); + end_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, finish); +} + +function f_key_test() { + EventUtils.synthesizeKey("f", { accelKey: true }, gManagerWindow); + is(focusCount, 1, "Search box should have been focused due to the f key"); +} + +function slash_key_test() { + EventUtils.synthesizeKey("/", { }, gManagerWindow); + is(focusCount, 2, "Search box should have been focused due to the / key"); +} diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug572561.js b/toolkit/mozapps/extensions/test/browser/browser_bug572561.js new file mode 100644 index 000000000..69102060e --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug572561.js @@ -0,0 +1,99 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that the locale category is shown if there are no locale packs +// installed but some are pending install + +var gManagerWindow; +var gCategoryUtilities; +var gProvider; +var gInstallProperties = [{ + name: "Locale Category Test", + type: "locale" +}]; +var gInstall; +var gExpectedCancel = false; +var gTestInstallListener = { + onInstallStarted: function(aInstall) { + check_hidden(false); + }, + + onInstallEnded: function(aInstall) { + check_hidden(false); + run_next_test(); + }, + + onInstallCancelled: function(aInstall) { + ok(gExpectedCancel, "Should expect install cancel"); + check_hidden(false); + run_next_test(); + }, + + onInstallFailed: function(aInstall) { + ok(false, "Did not expect onInstallFailed"); + run_next_test(); + } +}; + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, function() { + finish(); + }); +} + +function check_hidden(aExpectedHidden) { + var hidden = !gCategoryUtilities.isTypeVisible("locale"); + is(hidden, aExpectedHidden, "Should have correct hidden state"); +} + +// Tests that a non-active install does not make the locale category show +add_test(function() { + check_hidden(true); + gInstall = gProvider.createInstalls(gInstallProperties)[0]; + gInstall.addTestListener(gTestInstallListener); + check_hidden(true); + run_next_test(); +}); + +// Test that restarting the add-on manager with a non-active install +// does not cause the locale category to show +add_test(function() { + restart_manager(gManagerWindow, null, function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + check_hidden(true); + run_next_test(); + }); +}); + +// Test that installing the install shows the locale category +add_test(function() { + gInstall.install(); +}); + +// Test that restarting the add-on manager does not cause the locale category +// to become hidden +add_test(function() { + restart_manager(gManagerWindow, null, function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + check_hidden(false); + + gExpectedCancel = true; + gInstall.cancel(); + }); +}); + diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug573062.js b/toolkit/mozapps/extensions/test/browser/browser_bug573062.js new file mode 100644 index 000000000..c61131f03 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug573062.js @@ -0,0 +1,116 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +function test() { + waitForExplicitFinish(); + + var gProvider = new MockProvider(); + let perms = AddonManager.PERM_CAN_UNINSTALL | + AddonManager.PERM_CAN_ENABLE | AddonManager.PERM_CAN_DISABLE; + + gProvider.createAddons([{ + id: "restart-enable-disable@tests.mozilla.org", + name: "restart-enable-disable", + description: "foo", + permissions: perms, + operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_ENABLE | + AddonManager.OP_NEEDS_RESTART_DISABLE + }, + { + id: "restart-uninstall@tests.mozilla.org", + name: "restart-uninstall", + description: "foo", + permissions: perms, + operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_UNINSTALL + }, + { + id: "no-restart-required@tests.mozilla.org", + name: "no-restart-required", + description: "bar", + permissions: perms, + operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE + }]); + + open_manager("addons://list/extension", function(aWindow) { + let addonList = aWindow.document.getElementById("addon-list"); + let ed_r_Item, un_r_Item, no_r_Item; + for (let addonItem of addonList.childNodes) { + let name = addonItem.getAttribute("name"); + switch (name) { + case "restart-enable-disable": + ed_r_Item = addonItem; + break; + case "restart-uninstall": + un_r_Item = addonItem; + break; + case "no-restart-required": + no_r_Item = addonItem; + break; + } + } + + // Check the buttons in the list view. + function checkTooltips(aItem, aEnable, aDisable, aRemove) { + ok(aItem._enableBtn.getAttribute("tooltiptext") == aEnable); + ok(aItem._disableBtn.getAttribute("tooltiptext") == aDisable); + ok(aItem._removeBtn.getAttribute("tooltiptext") == aRemove); + } + + let strs = aWindow.gStrings.ext; + addonList.selectedItem = ed_r_Item; + let ed_args = [ed_r_Item, + strs.GetStringFromName("enableAddonRestartRequiredTooltip"), + strs.GetStringFromName("disableAddonRestartRequiredTooltip"), + strs.GetStringFromName("uninstallAddonTooltip")]; + checkTooltips.apply(null, ed_args); + + addonList.selectedItem = un_r_Item; + let un_args = [un_r_Item, + strs.GetStringFromName("enableAddonTooltip"), + strs.GetStringFromName("disableAddonTooltip"), + strs.GetStringFromName("uninstallAddonRestartRequiredTooltip")]; + checkTooltips.apply(null, un_args); + + addonList.selectedItem = no_r_Item; + let no_args = [no_r_Item, + strs.GetStringFromName("enableAddonTooltip"), + strs.GetStringFromName("disableAddonTooltip"), + strs.GetStringFromName("uninstallAddonTooltip")]; + checkTooltips.apply(null, no_args) + + // Check the buttons in the details view. + function checkTooltips2(aItem, aEnable, aDisable, aRemove) { + let detailEnable = aWindow.document.getElementById("detail-enable-btn"); + let detailDisable = aWindow.document.getElementById("detail-disable-btn"); + let detailUninstall = aWindow.document.getElementById("detail-uninstall-btn"); + ok(detailEnable.getAttribute("tooltiptext") == aEnable); + ok(detailDisable.getAttribute("tooltiptext") == aDisable); + ok(detailUninstall.getAttribute("tooltiptext") == aRemove); + } + + function showInDetailView(aAddonId) { + aWindow.gViewController.loadView("addons://detail/" + + aWindow.encodeURIComponent(aAddonId)); + } + + // enable-disable: + showInDetailView("restart-enable-disable@tests.mozilla.org"); + wait_for_view_load(aWindow, function() { + checkTooltips2.apply(null, ed_args); + // uninstall: + showInDetailView("restart-uninstall@tests.mozilla.org"); + wait_for_view_load(aWindow, function() { + checkTooltips2.apply(null, un_args); + // no restart: + showInDetailView("no-restart-required@tests.mozilla.org"); + wait_for_view_load(aWindow, function() { + checkTooltips2.apply(null, no_args); + aWindow.close(); + finish(); + }); + }); + }); + + }); +} diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug577990.js b/toolkit/mozapps/extensions/test/browser/browser_bug577990.js new file mode 100644 index 000000000..2c3c7ba5a --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug577990.js @@ -0,0 +1,132 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that the visible delay in showing the "Language" category occurs +// very minimally + +var gManagerWindow; +var gCategoryUtilities; +var gProvider; +var gInstall; +var gInstallProperties = [{ + name: "Locale Category Test", + type: "locale" +}]; + +function test() { + try { + if (Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).D2DEnabled) { + requestLongerTimeout(2); + } + } catch(e) {} + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, finish); +} + +function install_locale(aCallback) { + gInstall = gProvider.createInstalls(gInstallProperties)[0]; + gInstall.addTestListener({ + onInstallEnded: function(aInstall) { + gInstall.removeTestListener(this); + executeSoon(aCallback); + } + }); + gInstall.install(); +} + +function check_hidden(aExpectedHidden) { + var hidden = !gCategoryUtilities.isTypeVisible("locale"); + is(hidden, !!aExpectedHidden, "Should have correct hidden state"); +} + +function run_open_test(aTestSetup, aLoadHidden, aInitializedHidden, aSelected) { + function loadCallback(aManagerWindow) { + gManagerWindow = aManagerWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + check_hidden(aLoadHidden); + } + + function run() { + open_manager(null, function() { + check_hidden(aInitializedHidden); + var selected = (gCategoryUtilities.selectedCategory == "locale"); + is(selected, !!aSelected, "Should have correct selected state"); + + run_next_test(); + }, loadCallback); + } + + close_manager(gManagerWindow, function() { + // Allow for asynchronous functions to run before the manager opens + aTestSetup ? aTestSetup(run) : run(); + }); +} + + +// Tests that the locale category is hidden when there are no locales installed +add_test(function() { + run_open_test(null, true, true); +}); + +// Tests that installing a locale while the Add-on Manager is open shows the +// locale category +add_test(function() { + check_hidden(true); + install_locale(function() { + check_hidden(false); + run_next_test(); + }); +}); + +// Tests that the locale category is shown with no delay when restarting +// Add-on Manager +add_test(function() { + run_open_test(null, false, false); +}); + +// Tests that cancelling the locale install and restarting the Add-on Manager +// causes the locale category to be hidden with an acceptable delay +add_test(function() { + gInstall.cancel(); + run_open_test(null, false, true) +}); + +// Tests that the locale category is hidden with no delay when restarting +// Add-on Manager +add_test(function() { + run_open_test(null, true, true); +}); + +// Tests that installing a locale when the Add-on Manager is closed, and then +// opening the Add-on Manager causes the locale category to be shown with an +// acceptable delay +add_test(function() { + run_open_test(install_locale, true, false); +}); + +// Tests that selection of the locale category persists +add_test(function() { + gCategoryUtilities.openType("locale", function() { + run_open_test(null, false, false, true); + }); +}); + +// Tests that cancelling the locale install and restarting the Add-on Manager +// causes the locale category to be hidden and not selected +add_test(function() { + gInstall.cancel(); + run_open_test(null, false, true); +}); + diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug580298.js b/toolkit/mozapps/extensions/test/browser/browser_bug580298.js new file mode 100644 index 000000000..8456cc433 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug580298.js @@ -0,0 +1,111 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that certain types of addons do not have their version number +// displayed. This currently only includes lightweight themes. + +var gManagerWindow; +var gCategoryUtilities; +var gProvider; + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + gProvider.createAddons([{ + id: "extension@tests.mozilla.org", + name: "Extension 1", + type: "extension", + version: "123" + }, { + id: "theme@tests.mozilla.org", + name: "Theme 2", + type: "theme", + version: "456" + }, { + id: "lwtheme@personas.mozilla.org", + name: "Persona 3", + type: "theme", + version: "789" + }]); + + open_manager(null, function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, finish); +} + +function get(aId) { + return gManagerWindow.document.getElementById(aId); +} + +function get_node(parent, anonid) { + return parent.ownerDocument.getAnonymousElementByAttribute(parent, "anonid", anonid); +} + +function open_details(aList, aItem, aCallback) { + aList.ensureElementIsVisible(aItem); + EventUtils.synthesizeMouseAtCenter(aItem, { clickCount: 1 }, gManagerWindow); + EventUtils.synthesizeMouseAtCenter(aItem, { clickCount: 2 }, gManagerWindow); + wait_for_view_load(gManagerWindow, aCallback); +} + +function check_addon_has_version(aList, aName, aVersion) { + for (let i = 0; i < aList.itemCount; i++) { + let item = aList.getItemAtIndex(i); + if (get_node(item, "name").value === aName) { + ok(true, "Item with correct name found"); + is(get_node(item, "version").value, aVersion, "Item has correct version"); + return item; + } + } + ok(false, "Item with correct name was not found"); + return null; +} + +add_test(function() { + gCategoryUtilities.openType("extension", function() { + info("Extension"); + let list = gManagerWindow.document.getElementById("addon-list"); + let item = check_addon_has_version(list, "Extension 1", "123"); + open_details(list, item, function() { + is_element_visible(get("detail-version"), "Details view has version visible"); + is(get("detail-version").value, "123", "Details view has correct version"); + run_next_test(); + }); + }); +}); + +add_test(function() { + gCategoryUtilities.openType("theme", function() { + info("Normal theme"); + let list = gManagerWindow.document.getElementById("addon-list"); + let item = check_addon_has_version(list, "Theme 2", "456"); + open_details(list, item, function() { + is_element_visible(get("detail-version"), "Details view has version visible"); + is(get("detail-version").value, "456", "Details view has correct version"); + run_next_test(); + }); + }); +}); + +add_test(function() { + gCategoryUtilities.openType("theme", function() { + info("Lightweight theme"); + let list = gManagerWindow.document.getElementById("addon-list"); + // See that the version isn't displayed + let item = check_addon_has_version(list, "Persona 3", ""); + open_details(list, item, function() { + is_element_hidden(get("detail-version"), "Details view has version hidden"); + // If the version element is hidden then we don't care about its value + run_next_test(); + }); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug581076.js b/toolkit/mozapps/extensions/test/browser/browser_bug581076.js new file mode 100644 index 000000000..4c25c409d --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug581076.js @@ -0,0 +1,128 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Bug 581076 - No "See all results" link present when searching for add-ons and not all are displayed (extensions.getAddons.maxResults) + +const PREF_GETADDONS_BROWSESEARCHRESULTS = "extensions.getAddons.search.browseURL"; +const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url"; +const PREF_GETADDONS_MAXRESULTS = "extensions.getAddons.maxResults"; +const SEARCH_URL = TESTROOT + "browser_searching.xml"; +const SEARCH_EXPECTED_TOTAL = 100; +const SEARCH_QUERY = "search"; + +var gManagerWindow; + + +function test() { + Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, SEARCH_URL); + Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15); + + waitForExplicitFinish(); + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + run_next_test(); + }); +} + +function end_test() { + // Test generates a lot of available installs so just cancel them all + AddonManager.getAllInstalls(function(aInstalls) { + for (let install of aInstalls) + install.cancel(); + + close_manager(gManagerWindow, finish); + }); +} + +function search(aRemoteSearch, aCallback) { + waitForFocus(function() { + var searchBox = gManagerWindow.document.getElementById("header-search"); + searchBox.value = SEARCH_QUERY; + + EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow); + EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + if (aRemoteSearch) + var filter = gManagerWindow.document.getElementById("search-filter-remote"); + else + var filter = gManagerWindow.document.getElementById("search-filter-local"); + EventUtils.synthesizeMouseAtCenter(filter, { }, gManagerWindow); + + executeSoon(aCallback); + }); + }, gManagerWindow); +} + +function check_allresultslink(aShouldShow) { + var list = gManagerWindow.document.getElementById("search-list"); + var link = gManagerWindow.document.getElementById("search-allresults-link"); + is(link.parentNode, list.lastChild, "Footer should be at the end of the richlistbox"); + if (aShouldShow) { + is_element_visible(link, "All Results link should be visible"); + is(link.value, "See all " + SEARCH_EXPECTED_TOTAL + " results", "All Results link should show the correct message"); + var scope = {}; + Components.utils.import("resource://gre/modules/addons/AddonRepository.jsm", scope); + is(link.href, scope.AddonRepository.getSearchURL(SEARCH_QUERY), "All Results link should have the correct href"); + } else { + is_element_hidden(link, "All Results link should be hidden"); + } +} + +add_test(function() { + info("Searching locally"); + search(false, function() { + check_allresultslink(false); + restart_manager(gManagerWindow, null, function(aManager) { + gManagerWindow = aManager; + run_next_test(); + }); + }); +}); + +add_test(function() { + info("Searching remotely - more results than cap"); + Services.prefs.setIntPref(PREF_GETADDONS_MAXRESULTS, 3); + search(true, function() { + check_allresultslink(true); + restart_manager(gManagerWindow, null, function(aManager) { + gManagerWindow = aManager; + run_next_test(); + }); + }); +}); + +add_test(function() { + info("Searching remotely - less results than cap"); + Services.prefs.setIntPref(PREF_GETADDONS_MAXRESULTS, 200); + search(true, function() { + check_allresultslink(false); + restart_manager(gManagerWindow, null, function(aManager) { + gManagerWindow = aManager; + run_next_test(); + }); + }); +}); + +add_test(function() { + info("Searching remotely - more results than cap"); + Services.prefs.setIntPref(PREF_GETADDONS_MAXRESULTS, 3); + search(true, function() { + check_allresultslink(true); + run_next_test(); + }); +}); + +add_test(function() { + info("Switching views"); + gManagerWindow.loadView("addons://list/extension"); + wait_for_view_load(gManagerWindow, function() { + info("Re-loading previous search"); + search(true, function() { + check_allresultslink(true); + run_next_test(); + }); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug586574.js b/toolkit/mozapps/extensions/test/browser/browser_bug586574.js new file mode 100644 index 000000000..fb5ebf01b --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug586574.js @@ -0,0 +1,286 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Bug 586574 - Provide way to set a default for automatic updates +// Bug 710064 - Make the "Update Add-ons Automatically" checkbox state +// also depend on the extensions.update.enabled pref + +// TEST_PATH=toolkit/mozapps/extensions/test/browser/browser_bug586574.js make -C obj-ff mochitest-browser-chrome + +const PREF_UPDATE_ENABLED = "extensions.update.enabled"; +const PREF_AUTOUPDATE_DEFAULT = "extensions.update.autoUpdateDefault"; + +var gManagerWindow; +var gProvider; + +var gUtilsBtn; +var gUtilsMenu; +var gDropdownMenu; +var gSetDefault; +var gResetToAutomatic; +var gResetToManual; + +// Make sure we don't accidentally start a background update while the prefs +// are enabled. +disableBackgroundUpdateTimer(); +registerCleanupFunction(() => { + enableBackgroundUpdateTimer(); +}); + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + gProvider.createAddons([{ + id: "addon1@tests.mozilla.org", + name: "addon 1", + version: "1.0", + applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE + }]); + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + + gUtilsBtn = gManagerWindow.document.getElementById("header-utils-btn"); + gUtilsMenu = gManagerWindow.document.getElementById("utils-menu"); + + run_next_test(); + }); +} + + +function end_test() { + close_manager(gManagerWindow, finish); +} + + +function wait_for_popup(aCallback) { + if (gUtilsMenu.state == "open") { + aCallback(); + return; + } + + gUtilsMenu.addEventListener("popupshown", function() { + gUtilsMenu.removeEventListener("popupshown", arguments.callee, false); + info("Utilities menu shown"); + aCallback(); + }, false); +} + +function wait_for_hide(aCallback) { + if (gUtilsMenu.state == "closed") { + aCallback(); + return; + } + + gUtilsMenu.addEventListener("popuphidden", function() { + gUtilsMenu.removeEventListener("popuphidden", arguments.callee, false); + info("Utilities menu hidden"); + aCallback(); + }, false); +} + +add_test(function() { + gSetDefault = gManagerWindow.document.getElementById("utils-autoUpdateDefault"); + gResetToAutomatic = gManagerWindow.document.getElementById("utils-resetAddonUpdatesToAutomatic"); + gResetToManual = gManagerWindow.document.getElementById("utils-resetAddonUpdatesToManual"); + + info("Ensuring default prefs are set to true"); + Services.prefs.setBoolPref(PREF_UPDATE_ENABLED, true); + Services.prefs.setBoolPref(PREF_AUTOUPDATE_DEFAULT, true); + + wait_for_popup(function() { + is(gSetDefault.getAttribute("checked"), "true", + "#1 Set Default menuitem should be checked"); + is_element_visible(gResetToAutomatic, + "#1 Reset to Automatic menuitem should be visible"); + is_element_hidden(gResetToManual, + "#1 Reset to Manual menuitem should be hidden"); + + var listener = { + onPropertyChanged: function(aAddon, aProperties) { + AddonManager.removeAddonListener(listener); + is(aAddon.id, gProvider.addons[0].id, + "Should get onPropertyChanged event for correct addon"); + ok(!("applyBackgroundUpdates" in aProperties), + "Should have gotten applyBackgroundUpdates in properties array"); + is(aAddon.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DEFAULT, + "Addon.applyBackgroundUpdates should have been reset to default"); + + info("Setting Addon.applyBackgroundUpdates back to disabled"); + aAddon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE; + + wait_for_hide(run_next_test); + } + }; + AddonManager.addAddonListener(listener); + + info("Clicking Reset to Automatic menuitem"); + EventUtils.synthesizeMouseAtCenter(gResetToAutomatic, { }, gManagerWindow); + }); + + info("Opening utilities menu"); + EventUtils.synthesizeMouseAtCenter(gUtilsBtn, { }, gManagerWindow); +}); + + +add_test(function() { + info("Disabling extensions.update.enabled"); + Services.prefs.setBoolPref(PREF_UPDATE_ENABLED, false); + + wait_for_popup(function() { + isnot(gSetDefault.getAttribute("checked"), "true", + "#2 Set Default menuitem should not be checked"); + is_element_visible(gResetToAutomatic, + "#2 Reset to Automatic menuitem should be visible"); + is_element_hidden(gResetToManual, + "#2 Reset to Manual menuitem should be hidden"); + + wait_for_hide(run_next_test); + + info("Clicking Set Default menuitem to reenable"); + EventUtils.synthesizeMouseAtCenter(gSetDefault, { }, gManagerWindow); + }); + + info("Opening utilities menu"); + EventUtils.synthesizeMouseAtCenter(gUtilsBtn, { }, gManagerWindow); +}); + + +add_test(function() { + ok(Services.prefs.getBoolPref(PREF_UPDATE_ENABLED), + "extensions.update.enabled should be true after the previous test"); + ok(Services.prefs.getBoolPref(PREF_AUTOUPDATE_DEFAULT), + "extensions.update.autoUpdateDefault should be true after the previous test"); + + info("Disabling both extensions.update.enabled and extensions.update.autoUpdateDefault"); + Services.prefs.setBoolPref(PREF_UPDATE_ENABLED, false); + Services.prefs.setBoolPref(PREF_AUTOUPDATE_DEFAULT, false); + + wait_for_popup(function() { + isnot(gSetDefault.getAttribute("checked"), "true", + "#3 Set Default menuitem should not be checked"); + is_element_hidden(gResetToAutomatic, + "#3 Reset to automatic menuitem should be hidden"); + is_element_visible(gResetToManual, + "#3 Reset to manual menuitem should be visible"); + + wait_for_hide(run_next_test); + + info("Clicking Set Default menuitem to reenable"); + EventUtils.synthesizeMouseAtCenter(gSetDefault, { }, gManagerWindow); + }); + + info("Opening utilities menu"); + EventUtils.synthesizeMouseAtCenter(gUtilsBtn, { }, gManagerWindow); +}); + + +add_test(function() { + ok(Services.prefs.getBoolPref(PREF_UPDATE_ENABLED), + "extensions.update.enabled should be true after the previous test"); + ok(Services.prefs.getBoolPref(PREF_AUTOUPDATE_DEFAULT), + "extensions.update.autoUpdateDefault should be true after the previous test"); + + info("clicking the button to disable extensions.update.autoUpdateDefault"); + wait_for_popup(function() { + is(gSetDefault.getAttribute("checked"), "true", + "#4 Set Default menuitem should be checked"); + is_element_visible(gResetToAutomatic, + "#4 Reset to Automatic menuitem should be visible"); + is_element_hidden(gResetToManual, + "#4 Reset to Manual menuitem should be hidden"); + + wait_for_hide(run_next_test); + + info("Clicking Set Default menuitem to disable"); + EventUtils.synthesizeMouseAtCenter(gSetDefault, { }, gManagerWindow); + }); + + info("Opening utilities menu"); + EventUtils.synthesizeMouseAtCenter(gUtilsBtn, { }, gManagerWindow); +}); + + +add_test(function() { + ok(Services.prefs.getBoolPref(PREF_UPDATE_ENABLED), + "extensions.update.enabled should be true after the previous test"); + is(Services.prefs.getBoolPref(PREF_AUTOUPDATE_DEFAULT), false, + "extensions.update.autoUpdateDefault should be false after the previous test"); + + wait_for_popup(function() { + isnot(gSetDefault.getAttribute("checked"), "true", + "#5 Set Default menuitem should not be checked"); + is_element_hidden(gResetToAutomatic, + "#5 Reset to automatic menuitem should be hidden"); + is_element_visible(gResetToManual, + "#5 Reset to manual menuitem should be visible"); + + var listener = { + onPropertyChanged: function(aAddon, aProperties) { + AddonManager.removeAddonListener(listener); + is(aAddon.id, gProvider.addons[0].id, + "Should get onPropertyChanged event for correct addon"); + ok(!("applyBackgroundUpdates" in aProperties), + "Should have gotten applyBackgroundUpdates in properties array"); + is(aAddon.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DEFAULT, + "Addon.applyBackgroundUpdates should have been reset to default"); + + info("Setting Addon.applyBackgroundUpdates back to disabled"); + aAddon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE; + + wait_for_hide(run_next_test); + } + }; + AddonManager.addAddonListener(listener); + + info("Clicking Reset to Manual menuitem"); + EventUtils.synthesizeMouseAtCenter(gResetToManual, { }, gManagerWindow); + + }); + + info("Opening utilities menu"); + EventUtils.synthesizeMouseAtCenter(gUtilsBtn, { }, gManagerWindow); +}); + + +add_test(function() { + wait_for_popup(function() { + isnot(gSetDefault.getAttribute("checked"), "true", + "#6 Set Default menuitem should not be checked"); + is_element_hidden(gResetToAutomatic, + "#6 Reset to automatic menuitem should be hidden"); + is_element_visible(gResetToManual, + "#6 Reset to manual menuitem should be visible"); + + wait_for_hide(run_next_test); + + info("Clicking Set Default menuitem"); + EventUtils.synthesizeMouseAtCenter(gSetDefault, { }, gManagerWindow); + }); + + info("Opening utilities menu"); + EventUtils.synthesizeMouseAtCenter(gUtilsBtn, { }, gManagerWindow); +}); + + +add_test(function() { + wait_for_popup(function() { + is(gSetDefault.getAttribute("checked"), "true", + "#7 Set Default menuitem should be checked"); + is_element_visible(gResetToAutomatic, + "#7 Reset to Automatic menuitem should be visible"); + is_element_hidden(gResetToManual, + "#7 Reset to Manual menuitem should be hidden"); + + wait_for_hide(run_next_test); + + gUtilsMenu.hidePopup(); + }); + + info("Opening utilities menu"); + EventUtils.synthesizeMouseAtCenter(gUtilsBtn, { }, gManagerWindow); +}); + diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug587970.js b/toolkit/mozapps/extensions/test/browser/browser_bug587970.js new file mode 100644 index 000000000..0ff6d1b59 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug587970.js @@ -0,0 +1,180 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Bug 587970 - Provide ability "Update all now" within 'Available Updates' screen + +var gManagerWindow; +var gProvider; + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + gProvider.createAddons([{ + id: "addon1@tests.mozilla.org", + name: "addon 1", + version: "1.0", + applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE + }, { + id: "addon2@tests.mozilla.org", + name: "addon 2", + version: "2.0", + applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE + }, { + id: "addon3@tests.mozilla.org", + name: "addon 3", + version: "3.0", + applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE + }]); + + + open_manager("addons://updates/available", function(aWindow) { + gManagerWindow = aWindow; + run_next_test(); + }); +} + + +function end_test() { + close_manager(gManagerWindow, finish); +} + + +add_test(function() { + var list = gManagerWindow.document.getElementById("updates-list"); + is(list.childNodes.length, 0, "Available updates list should be empty"); + + var emptyNotice = gManagerWindow.document.getElementById("empty-availableUpdates-msg"); + is_element_visible(emptyNotice, "Empty notice should be visible"); + + var updateSelected = gManagerWindow.document.getElementById("update-selected-btn"); + is_element_hidden(updateSelected, "Update Selected button should be hidden"); + + info("Adding updates"); + gProvider.createInstalls([{ + name: "addon 1", + version: "1.1", + existingAddon: gProvider.addons[0] + }, { + name: "addon 2", + version: "2.1", + existingAddon: gProvider.addons[1] + }, { + name: "addon 3", + version: "3.1", + existingAddon: gProvider.addons[2] + }]); + + function wait_for_refresh() { + if (list.childNodes.length == 3 && + list.childNodes[0].mManualUpdate && + list.childNodes[1].mManualUpdate && + list.childNodes[2].mManualUpdate) { + run_next_test(); + } else { + info("Waiting for pane to refresh"); + setTimeout(wait_for_refresh, 10); + } + } + info("Waiting for pane to refresh"); + setTimeout(wait_for_refresh, 10); +}); + + +add_test(function() { + var list = gManagerWindow.document.getElementById("updates-list"); + is(list.childNodes.length, 3, "Available updates list should have 2 items"); + + var item1 = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); + isnot(item1, null, "Item for addon1@tests.mozilla.org should be in list"); + var item2 = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org"); + isnot(item2, null, "Item for addon2@tests.mozilla.org should be in list"); + var item3 = get_addon_element(gManagerWindow, "addon3@tests.mozilla.org"); + isnot(item3, null, "Item for addon3@tests.mozilla.org should be in list"); + + var emptyNotice = gManagerWindow.document.getElementById("empty-availableUpdates-msg"); + is_element_hidden(emptyNotice, "Empty notice should be hidden"); + + var updateSelected = gManagerWindow.document.getElementById("update-selected-btn"); + is_element_visible(updateSelected, "Update Selected button should be visible"); + is(updateSelected.disabled, false, "Update Selected button should be enabled by default"); + + is(item1._includeUpdate.checked, true, "Include Update checkbox should be checked by default for addon1"); + is(item2._includeUpdate.checked, true, "Include Update checkbox should be checked by default for addon2"); + is(item3._includeUpdate.checked, true, "Include Update checkbox should be checked by default for addon3"); + + info("Unchecking Include Update checkbox for addon1"); + EventUtils.synthesizeMouse(item1._includeUpdate, 2, 2, { }, gManagerWindow); + is(item1._includeUpdate.checked, false, "Include Update checkbox should now be be unchecked for addon1"); + is(updateSelected.disabled, false, "Update Selected button should still be enabled"); + + info("Unchecking Include Update checkbox for addon2"); + EventUtils.synthesizeMouse(item2._includeUpdate, 2, 2, { }, gManagerWindow); + is(item2._includeUpdate.checked, false, "Include Update checkbox should now be be unchecked for addon2"); + is(updateSelected.disabled, false, "Update Selected button should still be enabled"); + + info("Unchecking Include Update checkbox for addon3"); + EventUtils.synthesizeMouse(item3._includeUpdate, 2, 2, { }, gManagerWindow); + is(item3._includeUpdate.checked, false, "Include Update checkbox should now be be unchecked for addon3"); + is(updateSelected.disabled, true, "Update Selected button should now be disabled"); + + info("Checking Include Update checkbox for addon2"); + EventUtils.synthesizeMouse(item2._includeUpdate, 2, 2, { }, gManagerWindow); + is(item2._includeUpdate.checked, true, "Include Update checkbox should now be be checked for addon2"); + is(updateSelected.disabled, false, "Update Selected button should now be enabled"); + + info("Checking Include Update checkbox for addon3"); + EventUtils.synthesizeMouse(item3._includeUpdate, 2, 2, { }, gManagerWindow); + is(item3._includeUpdate.checked, true, "Include Update checkbox should now be be checked for addon3"); + is(updateSelected.disabled, false, "Update Selected button should now be enabled"); + + var installCount = 0; + var listener = { + onDownloadStarted: function(aInstall) { + isnot(aInstall.existingAddon.id, "addon1@tests.mozilla.org", "Should not have seen a download start for addon1"); + }, + + onInstallEnded: function(aInstall) { + if (++installCount < 2) + return; + + gProvider.installs[0].removeTestListener(listener); + gProvider.installs[1].removeTestListener(listener); + gProvider.installs[2].removeTestListener(listener); + + // Installs are started synchronously so by the time an executeSoon is + // executed all installs that are going to start will have started + executeSoon(function() { + is(gProvider.installs[0].state, AddonManager.STATE_AVAILABLE, "addon1 should not have been upgraded"); + is(gProvider.installs[1].state, AddonManager.STATE_INSTALLED, "addon2 should have been upgraded"); + is(gProvider.installs[2].state, AddonManager.STATE_INSTALLED, "addon3 should have been upgraded"); + + run_next_test(); + }); + } + } + gProvider.installs[0].addTestListener(listener); + gProvider.installs[1].addTestListener(listener); + gProvider.installs[2].addTestListener(listener); + info("Clicking Update Selected button"); + EventUtils.synthesizeMouseAtCenter(updateSelected, { }, gManagerWindow); +}); + + +add_test(function() { + var updateSelected = gManagerWindow.document.getElementById("update-selected-btn"); + is(updateSelected.disabled, true, "Update Selected button should be disabled"); + + var item1 = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); + isnot(item1, null, "Item for addon1@tests.mozilla.org should be in list"); + is(item1._includeUpdate.checked, false, "Include Update checkbox should not have changed"); + + info("Checking Include Update checkbox for addon1"); + EventUtils.synthesizeMouse(item1._includeUpdate, 2, 2, { }, gManagerWindow); + is(item1._includeUpdate.checked, true, "Include Update checkbox should now be be checked for addon1"); + is(updateSelected.disabled, false, "Update Selected button should now not be disabled"); + + run_next_test(); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug590347.js b/toolkit/mozapps/extensions/test/browser/browser_bug590347.js new file mode 100644 index 000000000..8fe9c715e --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug590347.js @@ -0,0 +1,120 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Bug 590347 +// Tests if softblock notifications are exposed in preference to incompatible +// notifications when compatibility checking is disabled + +var gProvider; +var gManagerWindow; +var gCategoryUtilities; + +var gApp = document.getElementById("bundle_brand").getString("brandShortName"); +var gVersion = Services.appinfo.version; + +// Opens the details view of an add-on +function open_details(aId, aType, aCallback) { + requestLongerTimeout(2); + + gCategoryUtilities.openType(aType, function() { + var list = gManagerWindow.document.getElementById("addon-list"); + var item = list.firstChild; + while (item) { + if ("mAddon" in item && item.mAddon.id == aId) { + list.ensureElementIsVisible(item); + EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow); + EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow); + wait_for_view_load(gManagerWindow, aCallback); + return; + } + item = item.nextSibling; + } + ok(false, "Should have found the add-on in the list"); + }); +} + +function get_list_view_warning_node() { + let item = gManagerWindow.document.getElementById("addon-list").firstChild; + let found = false; + while (item) { + if (item.mAddon.name == "Test add-on") { + found = true; + break; + } + item = item.nextSibling; + } + ok(found, "Test add-on node should have been found."); + return item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "warning"); +} + +function get_detail_view_warning_node(aManagerWindow) { + if(aManagerWindow) + return aManagerWindow.document.getElementById("detail-warning"); +} + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + gProvider.createAddons([{ + id: "addon1@tests.mozilla.org", + name: "Test add-on", + description: "A test add-on", + isCompatible: false, + blocklistState: Ci.nsIBlocklistService.STATE_SOFTBLOCKED, + }]); + + open_manager(null, function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, function() { + finish(); + }); +} + +// Check with compatibility checking enabled +add_test(function() { + gCategoryUtilities.openType("extension", function() { + Services.prefs.setBoolPref(PREF_CHECK_COMPATIBILITY, true); + let warning_node = get_list_view_warning_node(); + is_element_visible(warning_node, "Warning message should be visible"); + is(warning_node.textContent, "Test add-on is incompatible with " + gApp + " " + gVersion + ".", "Warning message should be correct"); + run_next_test(); + }); +}); + +add_test(function() { + open_details("addon1@tests.mozilla.org", "extension", function() { + let warning_node = get_detail_view_warning_node(gManagerWindow); + is_element_visible(warning_node, "Warning message should be visible"); + is(warning_node.textContent, "Test add-on is incompatible with " + gApp + " " + gVersion + ".", "Warning message should be correct"); + Services.prefs.setBoolPref(PREF_CHECK_COMPATIBILITY, false); + run_next_test(); + }); +}); + +// Check with compatibility checking disabled +add_test(function() { + gCategoryUtilities.openType("extension", function() { + let warning_node = get_list_view_warning_node(); + is_element_visible(warning_node, "Warning message should be visible"); + is(warning_node.textContent, "Test add-on is known to cause security or stability issues.", "Warning message should be correct"); + run_next_test(); + }); +}); + +add_test(function() { + open_details("addon1@tests.mozilla.org", "extension", function() { + let warning_node = get_detail_view_warning_node(gManagerWindow); + is_element_visible(warning_node, "Warning message should be visible"); + is(warning_node.textContent, "Test add-on is known to cause security or stability issues.", "Warning message should be correct"); + run_next_test(); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug591465.js b/toolkit/mozapps/extensions/test/browser/browser_bug591465.js new file mode 100644 index 000000000..2380deee1 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug591465.js @@ -0,0 +1,512 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Bug 591465 - Context menu of add-ons miss context related state change entries + + +let tempScope = {}; +Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", tempScope); +let LightweightThemeManager = tempScope.LightweightThemeManager; + + +const PREF_GETADDONS_MAXRESULTS = "extensions.getAddons.maxResults"; +const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url"; +const SEARCH_URL = TESTROOT + "browser_bug591465.xml"; +const SEARCH_QUERY = "SEARCH"; + +var gManagerWindow; +var gProvider; +var gContextMenu; +var gLWTheme = { + id: "4", + version: "1", + name: "Bling", + description: "SO MUCH BLING!", + author: "Pixel Pusher", + homepageURL: "http://mochi.test:8888/data/index.html", + headerURL: "http://mochi.test:8888/data/header.png", + footerURL: "http://mochi.test:8888/data/footer.png", + previewURL: "http://mochi.test:8888/data/preview.png", + iconURL: "http://mochi.test:8888/data/icon.png" + }; + + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + gProvider.createAddons([{ + id: "addon1@tests.mozilla.org", + name: "addon 1", + version: "1.0" + }, { + id: "addon2@tests.mozilla.org", + name: "addon 2", + version: "1.0", + _userDisabled: true + }, { + id: "theme1@tests.mozilla.org", + name: "theme 1", + version: "1.0", + type: "theme" + }, { + id: "theme2@tests.mozilla.org", + name: "theme 2", + version: "1.0", + type: "theme", + _userDisabled: true + }, { + id: "theme3@tests.mozilla.org", + name: "theme 3", + version: "1.0", + type: "theme", + permissions: 0 + }]); + + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gContextMenu = aWindow.document.getElementById("addonitem-popup"); + run_next_test(); + }); +} + + +function end_test() { + close_manager(gManagerWindow, finish); +} + + +function check_contextmenu(aIsTheme, aIsEnabled, aIsRemote, aIsDetails, aIsSingleItemCase) { + if (aIsTheme || aIsEnabled || aIsRemote) + is_element_hidden(gManagerWindow.document.getElementById("menuitem_enableItem"), + "'Enable' should be hidden"); + else + is_element_visible(gManagerWindow.document.getElementById("menuitem_enableItem"), + "'Enable' should be visible"); + + if (aIsTheme || !aIsEnabled || aIsRemote) + is_element_hidden(gManagerWindow.document.getElementById("menuitem_disableItem"), + "'Disable' should be hidden"); + else + is_element_visible(gManagerWindow.document.getElementById("menuitem_disableItem"), + "'Disable' should be visible"); + + if (!aIsTheme || aIsEnabled || aIsRemote || aIsSingleItemCase) + is_element_hidden(gManagerWindow.document.getElementById("menuitem_enableTheme"), + "'Wear Theme' should be hidden"); + else + is_element_visible(gManagerWindow.document.getElementById("menuitem_enableTheme"), + "'Wear Theme' should be visible"); + + if (!aIsTheme || !aIsEnabled || aIsRemote || aIsSingleItemCase) + is_element_hidden(gManagerWindow.document.getElementById("menuitem_disableTheme"), + "'Stop Wearing Theme' should be hidden"); + else + is_element_visible(gManagerWindow.document.getElementById("menuitem_disableTheme"), + "'Stop Wearing Theme' should be visible"); + + if (aIsRemote) + is_element_visible(gManagerWindow.document.getElementById("menuitem_installItem"), + "'Install' should be visible"); + else + is_element_hidden(gManagerWindow.document.getElementById("menuitem_installItem"), + "'Install' should be hidden"); + + if (aIsDetails) + is_element_hidden(gManagerWindow.document.getElementById("menuitem_showDetails"), + "'Show More Information' should be hidden in details view"); + else + is_element_visible(gManagerWindow.document.getElementById("menuitem_showDetails"), + "'Show More Information' should be visible in list view"); + + if (aIsSingleItemCase) + is_element_hidden(gManagerWindow.document.getElementById("addonitem-menuseparator"), + "Menu separator should be hidden with only one menu item"); + else + is_element_visible(gManagerWindow.document.getElementById("addonitem-menuseparator"), + "Menu separator should be visible with multiple menu items"); + +} + + +add_test(function() { + var el = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); + isnot(el, null, "Should have found addon element"); + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(false, true, false, false, false); + + gContextMenu.hidePopup(); + run_next_test(); + }, false); + + info("Opening context menu on enabled extension item"); + el.parentNode.ensureElementIsVisible(el); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); +}); + +add_test(function() { + var el = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); + isnot(el, null, "Should have found addon element"); + el.mAddon.userDisabled = true; + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(false, false, false, false, false); + + gContextMenu.hidePopup(); + run_next_test(); + }, false); + + info("Opening context menu on newly disabled extension item"); + el.parentNode.ensureElementIsVisible(el); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); +}); + +add_test(function() { + var el = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); + isnot(el, null, "Should have found addon element"); + el.mAddon.userDisabled = false; + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(false, true, false, false, false); + + gContextMenu.hidePopup(); + run_next_test(); + }, false); + + info("Opening context menu on newly enabled extension item"); + el.parentNode.ensureElementIsVisible(el); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); +}); + +add_test(function() { + var el = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org"); + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(false, false, false, false, false); + + gContextMenu.hidePopup(); + run_next_test(); + }, false); + + info("Opening context menu on disabled extension item"); + el.parentNode.ensureElementIsVisible(el); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); +}); + + +add_test(function() { + gManagerWindow.loadView("addons://list/theme"); + wait_for_view_load(gManagerWindow, function() { + var el = get_addon_element(gManagerWindow, "theme1@tests.mozilla.org"); + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(true, true, false, false, false); + + gContextMenu.hidePopup(); + run_next_test(); + }, false); + + info("Opening context menu on enabled theme item"); + el.parentNode.ensureElementIsVisible(el); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); + }); +}); + + +add_test(function() { + var el = get_addon_element(gManagerWindow, "theme2@tests.mozilla.org"); + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(true, false, false, false, false); + + gContextMenu.hidePopup(); + run_next_test(); + }, false); + + info("Opening context menu on disabled theme item"); + el.parentNode.ensureElementIsVisible(el); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); +}); + + +add_test(function() { + LightweightThemeManager.currentTheme = gLWTheme; + + var el = get_addon_element(gManagerWindow, "4@personas.mozilla.org"); + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(true, true, false, false, false); + + gContextMenu.hidePopup(); + run_next_test(); + }, false); + + info("Opening context menu on enabled LW theme item"); + el.parentNode.ensureElementIsVisible(el); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); +}); + + +add_test(function() { + LightweightThemeManager.currentTheme = null; + + var el = get_addon_element(gManagerWindow, "4@personas.mozilla.org"); + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(true, false, false, false, false); + + gContextMenu.hidePopup(); + run_next_test(); + }, false); + + info("Opening context menu on disabled LW theme item"); + el.parentNode.ensureElementIsVisible(el); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); +}); + + +add_test(function() { + LightweightThemeManager.currentTheme = gLWTheme; + + gManagerWindow.loadView("addons://detail/4@personas.mozilla.org"); + wait_for_view_load(gManagerWindow, function() { + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(true, true, false, true, false); + + gContextMenu.hidePopup(); + run_next_test(); + }, false); + + info("Opening context menu on enabled LW theme, in detail view"); + var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container"); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); + }); +}); + + +add_test(function() { + LightweightThemeManager.currentTheme = null; + + gManagerWindow.loadView("addons://detail/4@personas.mozilla.org"); + wait_for_view_load(gManagerWindow, function() { + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(true, false, false, true, false); + + gContextMenu.hidePopup(); + + AddonManager.getAddonByID("4@personas.mozilla.org", function(aAddon) { + aAddon.uninstall(); + run_next_test(); + }); + }, false); + + info("Opening context menu on disabled LW theme, in detail view"); + var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container"); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); + }); +}); + + +add_test(function() { + gManagerWindow.loadView("addons://detail/addon1@tests.mozilla.org"); + wait_for_view_load(gManagerWindow, function() { + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(false, true, false, true, false); + + gContextMenu.hidePopup(); + run_next_test(); + }, false); + + info("Opening context menu on enabled extension, in detail view"); + var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container"); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); + }); +}); + + +add_test(function() { + gManagerWindow.loadView("addons://detail/addon2@tests.mozilla.org"); + wait_for_view_load(gManagerWindow, function() { + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(false, false, false, true, false); + + gContextMenu.hidePopup(); + run_next_test(); + }, false); + + info("Opening context menu on disabled extension, in detail view"); + var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container"); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); + }); +}); + + +add_test(function() { + gManagerWindow.loadView("addons://detail/theme1@tests.mozilla.org"); + wait_for_view_load(gManagerWindow, function() { + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(true, true, false, true, false); + + gContextMenu.hidePopup(); + run_next_test(); + }, false); + + info("Opening context menu on enabled theme, in detail view"); + var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container"); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); + }); +}); + + +add_test(function() { + gManagerWindow.loadView("addons://detail/theme2@tests.mozilla.org"); + wait_for_view_load(gManagerWindow, function() { + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(true, false, false, true, false); + + gContextMenu.hidePopup(); + run_next_test(); + }, false); + + info("Opening context menu on disabled theme, in detail view"); + var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container"); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); + }); +}); + +add_test(function() { + gManagerWindow.loadView("addons://detail/theme3@tests.mozilla.org"); + wait_for_view_load(gManagerWindow, function() { + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(true, true, false, true, true); + + gContextMenu.hidePopup(); + run_next_test(); + }, false); + + info("Opening context menu with single menu item on enabled theme, in detail view"); + var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container"); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); + }); +}); + +add_test(function() { + info("Searching for remote addons"); + + Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, SEARCH_URL); + Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15); + + var searchBox = gManagerWindow.document.getElementById("header-search"); + searchBox.value = SEARCH_QUERY; + + EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow); + EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + var filter = gManagerWindow.document.getElementById("search-filter-remote"); + EventUtils.synthesizeMouseAtCenter(filter, { }, gManagerWindow); + executeSoon(function() { + + var el = get_addon_element(gManagerWindow, "remote1@tests.mozilla.org"); + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(false, false, true, false, false); + + gContextMenu.hidePopup(); + run_next_test(); + }, false); + + info("Opening context menu on remote extension item"); + el.parentNode.ensureElementIsVisible(el); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); + + }); + }); +}); + + +add_test(function() { + gManagerWindow.loadView("addons://detail/remote1@tests.mozilla.org"); + wait_for_view_load(gManagerWindow, function() { + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(false, false, true, true, false); + + gContextMenu.hidePopup(); + + // Delete the created install + AddonManager.getAllInstalls(function(aInstalls) { + is(aInstalls.length, 1, "Should be one available install"); + aInstalls[0].cancel(); + + run_next_test(); + }); + }, false); + + info("Opening context menu on remote extension, in detail view"); + var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container"); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug591465.xml b/toolkit/mozapps/extensions/test/browser/browser_bug591465.xml new file mode 100644 index 000000000..bd648cf0f --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug591465.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8" ?> +<searchresults total_results="100"> + <addon> + <name>MAGICAL SEARCH RESULT</name> + <type id='1'>Extension</type> + <guid>remote1@tests.mozilla.org</guid> + <version>3.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://example.com/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <summary>Test summary - SEARCH SEARCH</summary> + <description>Test description</description> + <compatible_applications> + <application> + <name>Firefox</name> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + <application> + <name>SeaMonkey</name> + <appID>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + </compatible_applications> + <compatible_os>ALL</compatible_os> + <install size="2">http://example.com/browser/toolkit/mozapps/extensions/test/browser/addons/browser_searching.xpi</install> + </addon> +</searchresults> + diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug591663.js b/toolkit/mozapps/extensions/test/browser/browser_bug591663.js new file mode 100644 index 000000000..0736aa391 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug591663.js @@ -0,0 +1,161 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test that the empty notice in the list view disappears as it should + +// Don't use a standard list view (e.g. "extension") to ensure that the list is +// initially empty. Don't need to worry about the list of categories displayed +// since only the list view itself is tested. +let VIEW_ID = "addons://list/mock-addon"; + +let LIST_ID = "addon-list"; +let EMPTY_ID = "addon-list-empty"; + +let gManagerWindow; +let gProvider; +let gItem; + +let gInstallProperties = { + name: "Bug 591663 Mock Install", + type: "mock-addon" +}; +let gAddonProperties = { + id: "test1@tests.mozilla.org", + name: "Bug 591663 Mock Add-on", + type: "mock-addon" +}; +let gExtensionProperties = { + name: "Bug 591663 Extension Install", + type: "extension" +}; + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(true, [{ + id: "mock-addon", + name: "Mock Add-ons", + uiPriority: 4500, + flags: AddonManager.TYPE_UI_VIEW_LIST + }]); + + open_manager(VIEW_ID, function(aWindow) { + gManagerWindow = aWindow; + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, finish); +} + +/** + * Check that the list view is as expected + * + * @param aItem + * The expected item in the list, or null if list should be empty + */ +function check_list(aItem) { + // Check state of the empty notice + let emptyNotice = gManagerWindow.document.getElementById(EMPTY_ID); + ok(emptyNotice != null, "Should have found the empty notice"); + is(!emptyNotice.hidden, (aItem == null), "Empty notice should be showing if list empty"); + + // Check the children of the list + let list = gManagerWindow.document.getElementById(LIST_ID); + is(list.itemCount, aItem ? 1 : 0, "Should get expected number of items in list"); + if (aItem != null) { + let itemName = list.firstChild.getAttribute("name"); + is(itemName, aItem.name, "List item should have correct name"); + } +} + + +// Test that the empty notice is showing and no items are showing in list +add_test(function() { + check_list(null); + run_next_test(); +}); + +// Test that a new, non-active, install does not affect the list view +add_test(function() { + gItem = gProvider.createInstalls([gInstallProperties])[0]; + check_list(null); + run_next_test(); +}); + +// Test that onInstallStarted properly hides empty notice and adds install to list +add_test(function() { + gItem.addTestListener({ + onDownloadStarted: function() { + // Install type unknown until download complete + check_list(null); + }, + onInstallStarted: function() { + check_list(gItem); + }, + onInstallEnded: function() { + check_list(gItem); + run_next_test(); + } + }); + + gItem.install(); +}); + +// Test that restarting the manager does not change list +add_test(function() { + restart_manager(gManagerWindow, VIEW_ID, function(aManagerWindow) { + gManagerWindow = aManagerWindow; + check_list(gItem); + run_next_test(); + }); +}); + +// Test that onInstallCancelled removes install and shows empty notice +add_test(function() { + gItem.cancel(); + gItem = null; + check_list(null); + run_next_test(); +}); + +// Test that add-ons of a different type do not show up in the list view +add_test(function() { + let extension = gProvider.createInstalls([gExtensionProperties])[0]; + check_list(null); + + extension.addTestListener({ + onDownloadStarted: function() { + check_list(null); + }, + onInstallStarted: function() { + check_list(null); + }, + onInstallEnded: function() { + check_list(null); + extension.cancel(); + run_next_test(); + } + }); + + extension.install(); +}); + +// Test that onExternalInstall properly hides empty notice and adds install to list +add_test(function() { + gItem = gProvider.createAddons([gAddonProperties])[0]; + check_list(gItem); + run_next_test(); +}); + +// Test that restarting the manager does not change list +add_test(function() { + restart_manager(gManagerWindow, VIEW_ID, function(aManagerWindow) { + gManagerWindow = aManagerWindow; + check_list(gItem); + run_next_test(); + }); +}); + diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug593535.js b/toolkit/mozapps/extensions/test/browser/browser_bug593535.js new file mode 100644 index 000000000..a78ef9a23 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug593535.js @@ -0,0 +1,118 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Bug 593535 - Failure to download extension causes about:addons to list the +// addon with no way to restart the download + +const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url"; +const SEARCH_URL = TESTROOT + "browser_bug593535.xml"; +const QUERY = "NOTFOUND"; + +var gProvider; + +function test() { + waitForExplicitFinish(); + + // Turn on searching for this test + Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15); + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, function() { + AddonManager.getAllInstalls(function(aInstallsList) { + for (var install of aInstallsList) { + var sourceURI = install.sourceURI.spec; + if (sourceURI.match(/^http:\/\/example\.com\/(.+)\.xpi$/) != null) + install.cancel(); + } + + finish(); + }); + }); +} + +function search(aQuery, aCallback) { + // Point search to the correct xml test file + Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, SEARCH_URL); + + var searchBox = gManagerWindow.document.getElementById("header-search"); + searchBox.value = aQuery; + + EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow); + EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + var remoteFilter = gManagerWindow.document.getElementById("search-filter-remote"); + EventUtils.synthesizeMouseAtCenter(remoteFilter, { }, gManagerWindow); + + aCallback(); + }); +} + +function get_addon_item(aName) { + var id = aName + "@tests.mozilla.org"; + var list = gManagerWindow.document.getElementById("search-list"); + var rows = list.getElementsByTagName("richlistitem"); + for (let row of rows) { + if (row.mAddon && row.mAddon.id == id) + return row; + } + + return null; +} + +function get_install_button(aItem) { + isnot(aItem, null, "Item should not be null when checking state of install button"); + var installStatus = getAnonymousElementByAttribute(aItem, "anonid", "install-status"); + return getAnonymousElementByAttribute(installStatus, "anonid", "install-remote-btn"); +} + + +function getAnonymousElementByAttribute(aElement, aName, aValue) { + return gManagerWindow.document.getAnonymousElementByAttribute(aElement, + aName, + aValue); +} + + + +// Tests that a failed install for a remote add-on will ask to retry the install +add_test(function() { + var remoteItem; + + var listener = { + onDownloadFailed: function(aInstall) { + aInstall.removeListener(this); + ok(true, "Install failed as expected"); + + executeSoon(function() { + is(remoteItem.getAttribute("notification"), "warning", "Item should have notification attribute set to 'warning'"); + is_element_visible(remoteItem._warning, "Warning text should be visible"); + is(remoteItem._warning.textContent, "There was an error downloading NOTFOUND.", "Warning should show correct message"); + is_element_visible(remoteItem._warningLink, "Retry button should be visible"); + run_next_test(); + }); + }, + + onInstallEnded: function() { + ok(false, "Install should have failed"); + } + } + + search(QUERY, function() { + var list = gManagerWindow.document.getElementById("search-list"); + remoteItem = get_addon_item("notfound1"); + list.ensureElementIsVisible(remoteItem); + + remoteItem.mAddon.install.addListener(listener); + + var installBtn = get_install_button(remoteItem); + EventUtils.synthesizeMouseAtCenter(installBtn, { }, gManagerWindow); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug593535.xml b/toolkit/mozapps/extensions/test/browser/browser_bug593535.xml new file mode 100644 index 000000000..847c2854d --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug593535.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8" ?> +<searchresults total_results="100"> + <addon> + <name>NOTFOUND</name> + <type id='1'>Extension</type> + <guid>notfound1@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://example.com/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <summary>Install file not found - NOTFOUND</summary> + <description>Test description</description> + <compatible_applications> + <application> + <name>Firefox</name> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + <application> + <name>SeaMonkey</name> + <appID>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + </compatible_applications> + <compatible_os>ALL</compatible_os> + <install size="1">http://example.com/file_not_found.xpi</install> + </addon> +</searchresults> diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug596336.js b/toolkit/mozapps/extensions/test/browser/browser_bug596336.js new file mode 100644 index 000000000..935820613 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug596336.js @@ -0,0 +1,180 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that upgrading bootstrapped add-ons behaves correctly while the +// manager is open + +var gManagerWindow; +var gCategoryUtilities; + +function test() { + waitForExplicitFinish(); + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, finish); +} + +function get_list_item_count() { + return get_test_items_in_list(gManagerWindow).length; +} + +function get_node(parent, anonid) { + return parent.ownerDocument.getAnonymousElementByAttribute(parent, "anonid", anonid); +} + +function get_class_node(parent, cls) { + return parent.ownerDocument.getAnonymousElementByAttribute(parent, "class", cls); +} + +function install_addon(aXpi, aCallback) { + AddonManager.getInstallForURL(TESTROOT + "addons/" + aXpi + ".xpi", + function(aInstall) { + aInstall.addListener({ + onInstallEnded: function(aInstall) { + executeSoon(aCallback); + } + }); + aInstall.install(); + }, "application/x-xpinstall"); +} + +function check_addon(aAddon, version) { + is(get_list_item_count(), 1, "Should be one item in the list"); + is(aAddon.version, version, "Add-on should have the right version"); + + let item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); + ok(!!item, "Should see the add-on in the list"); + + // Force XBL to apply + item.clientTop; + + is(get_node(item, "version").value, version, "Version should be correct"); + + if (aAddon.userDisabled) + is_element_visible(get_class_node(item, "disabled-postfix"), "Disabled postfix should be hidden"); + else + is_element_hidden(get_class_node(item, "disabled-postfix"), "Disabled postfix should be hidden"); +} + +// Install version 1 then upgrade to version 2 with the manager open +add_test(function() { + install_addon("browser_bug596336_1", function() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { + check_addon(aAddon, "1.0"); + ok(!aAddon.userDisabled, "Add-on should not be disabled"); + + install_addon("browser_bug596336_2", function() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { + check_addon(aAddon, "2.0"); + ok(!aAddon.userDisabled, "Add-on should not be disabled"); + + aAddon.uninstall(); + + is(get_list_item_count(), 0, "Should be no items in the list"); + + run_next_test(); + }); + }); + }); + }); +}); + +// Install version 1 mark it as disabled then upgrade to version 2 with the +// manager open +add_test(function() { + install_addon("browser_bug596336_1", function() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { + aAddon.userDisabled = true; + check_addon(aAddon, "1.0"); + ok(aAddon.userDisabled, "Add-on should be disabled"); + + install_addon("browser_bug596336_2", function() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { + check_addon(aAddon, "2.0"); + ok(aAddon.userDisabled, "Add-on should be disabled"); + + aAddon.uninstall(); + + is(get_list_item_count(), 0, "Should be no items in the list"); + + run_next_test(); + }); + }); + }); + }); +}); + +// Install version 1 click the remove button and then upgrade to version 2 with +// the manager open +add_test(function() { + install_addon("browser_bug596336_1", function() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { + check_addon(aAddon, "1.0"); + ok(!aAddon.userDisabled, "Add-on should not be disabled"); + + let item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); + EventUtils.synthesizeMouseAtCenter(get_node(item, "remove-btn"), { }, gManagerWindow); + + // Force XBL to apply + item.clientTop; + + ok(!!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should be pending uninstall"); + is_element_visible(get_class_node(item, "pending"), "Pending message should be visible"); + + install_addon("browser_bug596336_2", function() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { + check_addon(aAddon, "2.0"); + ok(!aAddon.userDisabled, "Add-on should not be disabled"); + + aAddon.uninstall(); + + is(get_list_item_count(), 0, "Should be no items in the list"); + + run_next_test(); + }); + }); + }); + }); +}); + +// Install version 1, disable it, click the remove button and then upgrade to +// version 2 with the manager open +add_test(function() { + install_addon("browser_bug596336_1", function() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { + aAddon.userDisabled = true; + check_addon(aAddon, "1.0"); + ok(aAddon.userDisabled, "Add-on should be disabled"); + + let item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); + EventUtils.synthesizeMouseAtCenter(get_node(item, "remove-btn"), { }, gManagerWindow); + + // Force XBL to apply + item.clientTop; + + ok(!!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should be pending uninstall"); + is_element_visible(get_class_node(item, "pending"), "Pending message should be visible"); + + install_addon("browser_bug596336_2", function() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { + check_addon(aAddon, "2.0"); + ok(aAddon.userDisabled, "Add-on should be disabled"); + + aAddon.uninstall(); + + is(get_list_item_count(), 0, "Should be no items in the list"); + + run_next_test(); + }); + }); + }); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug608316.js b/toolkit/mozapps/extensions/test/browser/browser_bug608316.js new file mode 100644 index 000000000..39986c23b --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug608316.js @@ -0,0 +1,65 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Bug 608316 - Test that cancelling an uninstall during the onUninstalling +// event doesn't confuse the UI + +var gProvider; + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + gProvider.createAddons([{ + id: "addon1@tests.mozilla.org", + name: "addon 1", + version: "1.0" + }]); + + run_next_test(); +} + + +function end_test() { + finish(); +} + + +add_test(function() { + var sawUninstall = false; + var listener = { + onUninstalling: function(aAddon, aRestartRequired) { + if (aAddon.id != "addon1@tests.mozilla.org") + return; + sawUninstall = true; + aAddon.cancelUninstall(); + } + } + + // Important to add this before opening the UI so it gets its events first + AddonManager.addAddonListener(listener); + registerCleanupFunction(function() { + AddonManager.removeAddonListener(listener); + }); + + open_manager("addons://list/extension", function(aManager) { + var addon = get_addon_element(aManager, "addon1@tests.mozilla.org"); + isnot(addon, null, "Should see the add-on in the list"); + + var removeBtn = aManager.document.getAnonymousElementByAttribute(addon, "anonid", "remove-btn"); + EventUtils.synthesizeMouseAtCenter(removeBtn, { }, aManager); + + ok(sawUninstall, "Should have seen the uninstall event"); + sawUninstall = false; + + is(addon.getAttribute("pending"), "", "Add-on should not be uninstalling"); + + close_manager(aManager, function() { + ok(!sawUninstall, "Should not have seen another uninstall event"); + + run_next_test(); + }); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug610764.js b/toolkit/mozapps/extensions/test/browser/browser_bug610764.js new file mode 100644 index 000000000..58de88130 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug610764.js @@ -0,0 +1,34 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that the discovery view is the default + +var gCategoryUtilities; + +function test() { + waitForExplicitFinish(); + + open_manager(null, function(aWindow) { + waitForFocus(function() { + // The last view is cached except when it is the search view so switch to + // that and reopen to ensure we see the default view + var searchBox = aWindow.document.getElementById("header-search"); + searchBox.value = "bar"; + + EventUtils.synthesizeMouseAtCenter(searchBox, { }, aWindow); + EventUtils.synthesizeKey("VK_RETURN", { }, aWindow); + + wait_for_view_load(aWindow, function() { + close_manager(aWindow, function() { + open_manager(null, function(aWindow) { + gCategoryUtilities = new CategoryUtilities(aWindow); + is(gCategoryUtilities.selectedCategory, "discover", "Should show the discovery pane by default"); + + close_manager(aWindow, finish); + }); + }); + }); + }, aWindow); + }); +} diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug616841.js b/toolkit/mozapps/extensions/test/browser/browser_bug616841.js new file mode 100644 index 000000000..3cf6f5346 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug616841.js @@ -0,0 +1,21 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +function test_string_compare() { + ok("C".localeCompare("D") < 0, "C < D"); + ok("D".localeCompare("C") > 0, "D > C"); + ok("\u010C".localeCompare("D") < 0, "\u010C < D"); + ok("D".localeCompare("\u010C") > 0, "D > \u010C"); +} + +function test() { + waitForExplicitFinish(); + + test_string_compare(); + + AddonManager.getAddonByID("foo", function(aAddon) { + test_string_compare(); + finish(); + }); +} diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug618502.js b/toolkit/mozapps/extensions/test/browser/browser_bug618502.js new file mode 100644 index 000000000..36ba8fb69 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug618502.js @@ -0,0 +1,44 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Bug 608316 - Test that opening the manager to an add-on that doesn't exist +// just loads the default view + +var gCategoryUtilities; + +function test() { + waitForExplicitFinish(); + + run_next_test(); +} + +function end_test() { + finish(); +} + +add_test(function() { + open_manager("addons://detail/foo", function(aManager) { + gCategoryUtilities = new CategoryUtilities(aManager); + is(gCategoryUtilities.selectedCategory, "discover", "Should fall back to the discovery pane"); + + close_manager(aManager, run_next_test); + }); +}); + +// Also test that opening directly to an add-on that does exist doesn't break +// and selects the right category +add_test(function() { + new MockProvider().createAddons([{ + id: "addon1@tests.mozilla.org", + name: "addon 1", + version: "1.0" + }]); + + open_manager("addons://detail/addon1@tests.mozilla.org", function(aManager) { + gCategoryUtilities = new CategoryUtilities(aManager); + is(gCategoryUtilities.selectedCategory, "extension", "Should have selected the right category"); + + close_manager(aManager, run_next_test); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug679604.js b/toolkit/mozapps/extensions/test/browser/browser_bug679604.js new file mode 100644 index 000000000..e1ec605c2 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug679604.js @@ -0,0 +1,29 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Bug 679604 - Test that a XUL persisted category from an older version of +// Firefox doesn't break the add-ons manager when that category doesn't exist + +var gManagerWindow; + +function test() { + waitForExplicitFinish(); + + open_manager(null, function(aWindow) { + var categories = aWindow.document.getElementById("categories"); + categories.setAttribute("last-selected", "foo"); + aWindow.document.persist("categories", "last-selected"); + + close_manager(aWindow, function() { + Services.prefs.clearUserPref(PREF_UI_LASTCATEGORY); + + open_manager(null, function(aWindow) { + is(new CategoryUtilities(aWindow).selectedCategory, "discover", + "Should have loaded the right view"); + + close_manager(aWindow, finish); + }); + }); + }); +} diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug714593.js b/toolkit/mozapps/extensions/test/browser/browser_bug714593.js new file mode 100644 index 000000000..b9a7faa5e --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug714593.js @@ -0,0 +1,140 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that installed addons in the search view load inline prefs properly + +const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url"; +const NO_MATCH_URL = TESTROOT + "browser_searching_empty.xml"; + +var gManagerWindow; +var gCategoryUtilities; +var gProvider; + +function test() { + // Turn on searching for this test + Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15); + + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + gProvider.createAddons([{ + id: "inlinesettings2@tests.mozilla.org", + name: "Inline Settings (Regular)", + version: "1", + optionsURL: CHROMEROOT + "options.xul", + optionsType: AddonManager.OPTIONS_TYPE_INLINE + }]); + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, finish); +} + +/* + * Checks whether or not the Add-ons Manager is currently searching + * + * @param aExpectedSearching + * The expected isSearching state + */ +function check_is_searching(aExpectedSearching) { + var loading = gManagerWindow.document.getElementById("search-loading"); + is(!is_hidden(loading), aExpectedSearching, + "Search throbber should be showing iff currently searching"); +} + +/* + * Completes a search + * + * @param aQuery + * The query to search for + * @param aFinishImmediately + * Boolean representing whether or not the search is expected to + * finish immediately + * @param aCallback + * The callback to call when the search is done + * @param aCategoryType + * The expected selected category after the search is done. + * Optional and defaults to "search" + */ +function search(aQuery, aFinishImmediately, aCallback, aCategoryType) { + // Point search to the correct xml test file + Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, NO_MATCH_URL); + + aCategoryType = aCategoryType ? aCategoryType : "search"; + + var searchBox = gManagerWindow.document.getElementById("header-search"); + searchBox.value = aQuery; + + EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow); + EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); + + var finishImmediately = true; + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, aCategoryType, "Expected category view should be selected"); + is(gCategoryUtilities.isTypeVisible("search"), aCategoryType == "search", + "Search category should only be visible if it is the current view"); + is(finishImmediately, aFinishImmediately, "Search should finish immediately only if expected"); + + aCallback(); + }); + + finishImmediately = false + if (!aFinishImmediately) + check_is_searching(true); +} + +/* + * Get item for a specific add-on by name + * + * @param aName + * The name of the add-on to search for + * @return Row of add-on if found, null otherwise + */ +function get_addon_item(aName) { + var id = aName + "@tests.mozilla.org"; + var list = gManagerWindow.document.getElementById("search-list"); + var rows = list.getElementsByTagName("richlistitem"); + for (let row of rows) { + if (row.mAddon && row.mAddon.id == id) + return row; + } + + return null; +} + +add_test(function() { + search("settings", false, function() { + var localFilter = gManagerWindow.document.getElementById("search-filter-local"); + EventUtils.synthesizeMouseAtCenter(localFilter, { }, gManagerWindow); + + var item = get_addon_item("inlinesettings2"); + // Force the XBL binding to apply. + item.clientTop; + var button = gManagerWindow.document.getAnonymousElementByAttribute(item, "anonid", "preferences-btn"); + is_element_visible(button, "Preferences button should be visible"); + + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + wait_for_view_load(gManagerWindow, function() { + is(gManagerWindow.gViewController.currentViewObj, gManagerWindow.gDetailView, "View should have changed to detail"); + + var searchCategory = gManagerWindow.document.getElementById("category-search"); + EventUtils.synthesizeMouseAtCenter(searchCategory, { }, gManagerWindow); + wait_for_view_load(gManagerWindow, function() { + is(gManagerWindow.gViewController.currentViewObj, gManagerWindow.gSearchView, "View should have changed back to search"); + + // Reset filter to remote to avoid breaking later tests. + var remoteFilter = gManagerWindow.document.getElementById("search-filter-remote"); + EventUtils.synthesizeMouseAtCenter(remoteFilter, { }, gManagerWindow); + run_next_test(); + }); + }); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_cancelCompatCheck.js b/toolkit/mozapps/extensions/test/browser/browser_cancelCompatCheck.js new file mode 100644 index 000000000..1799adcdd --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_cancelCompatCheck.js @@ -0,0 +1,462 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test that we can cancel the add-on compatibility check while it is +// in progress (bug 772484). +// Test framework copied from browser_bug557956.js + +const URI_EXTENSION_UPDATE_DIALOG = "chrome://mozapps/content/extensions/update.xul"; + +const PREF_GETADDONS_BYIDS = "extensions.getAddons.get.url"; +const PREF_MIN_PLATFORM_COMPAT = "extensions.minCompatiblePlatformVersion"; +const PREF_METADATA_LASTUPDATE = "extensions.getAddons.cache.lastUpdate"; + +let repo = {}; +Components.utils.import("resource://gre/modules/addons/AddonRepository.jsm", repo); +Components.utils.import("resource://gre/modules/Promise.jsm", this); + +/** + * Test add-ons: + * + * Addon minVersion maxVersion Notes + * addon1 0 * + * addon2 0 0 + * addon3 0 0 + * addon4 1 * + * addon5 0 0 Made compatible by update check + * addon6 0 0 Made compatible by update check + * addon7 0 0 Has a broken update available + * addon8 0 0 Has an update available + * addon9 0 0 Has an update available + * addon10 0 0 Made incompatible by override check + */ + +// describe the addons +let ao1 = { file: "browser_bug557956_1", id: "addon1@tests.mozilla.org"}; +let ao2 = { file: "browser_bug557956_2", id: "addon2@tests.mozilla.org"}; +let ao3 = { file: "browser_bug557956_3", id: "addon3@tests.mozilla.org"}; +let ao4 = { file: "browser_bug557956_4", id: "addon4@tests.mozilla.org"}; +let ao5 = { file: "browser_bug557956_5", id: "addon5@tests.mozilla.org"}; +let ao6 = { file: "browser_bug557956_6", id: "addon6@tests.mozilla.org"}; +let ao7 = { file: "browser_bug557956_7", id: "addon7@tests.mozilla.org"}; +let ao8 = { file: "browser_bug557956_8_1", id: "addon8@tests.mozilla.org"}; +let ao9 = { file: "browser_bug557956_9_1", id: "addon9@tests.mozilla.org"}; +let ao10 = { file: "browser_bug557956_10", id: "addon10@tests.mozilla.org"}; + +// Return a promise that resolves after the specified delay in MS +function delayMS(aDelay) { + let deferred = Promise.defer(); + setTimeout(deferred.resolve, aDelay); + return deferred.promise; +} + +// Return a promise that resolves when the specified observer topic is notified +function promise_observer(aTopic) { + let deferred = Promise.defer(); + Services.obs.addObserver(function observe(aSubject, aObsTopic, aData) { + Services.obs.removeObserver(arguments.callee, aObsTopic); + deferred.resolve([aSubject, aData]); + }, aTopic, false); + return deferred.promise; +} + +// Install a set of addons using a bogus update URL so that we can force +// the compatibility update to happen later +// @param aUpdateURL The real update URL to use after the add-ons are installed +function promise_install_test_addons(aAddonList, aUpdateURL) { + info("Starting add-on installs"); + var installs = []; + let deferred = Promise.defer(); + + // Use a blank update URL + Services.prefs.setCharPref(PREF_UPDATEURL, TESTROOT + "missing.rdf"); + + for (let addon of aAddonList) { + AddonManager.getInstallForURL(TESTROOT + "addons/" + addon.file + ".xpi", function(aInstall) { + installs.push(aInstall); + }, "application/x-xpinstall"); + } + + var listener = { + installCount: 0, + + onInstallEnded: function() { + this.installCount++; + if (this.installCount == installs.length) { + info("Done add-on installs"); + // Switch to the test update URL + Services.prefs.setCharPref(PREF_UPDATEURL, aUpdateURL); + deferred.resolve(); + } + } + }; + + for (let install of installs) { + install.addListener(listener); + install.install(); + } + + return deferred.promise; +} + +function promise_addons_by_ids(aAddonIDs) { + info("promise_addons_by_ids " + aAddonIDs.toSource()); + let deferred = Promise.defer(); + AddonManager.getAddonsByIDs(aAddonIDs, deferred.resolve); + return deferred.promise; +} + +function* promise_uninstall_test_addons() { + info("Starting add-on uninstalls"); + let addons = yield promise_addons_by_ids([ao1.id, ao2.id, ao3.id, ao4.id, ao5.id, + ao6.id, ao7.id, ao8.id, ao9.id, ao10.id]); + let deferred = Promise.defer(); + let uninstallCount = addons.length; + let listener = { + onUninstalled: function(aAddon) { + if (aAddon) { + info("Finished uninstalling " + aAddon.id); + } + if (--uninstallCount == 0) { + info("Done add-on uninstalls"); + AddonManager.removeAddonListener(listener); + deferred.resolve(); + } + }}; + AddonManager.addAddonListener(listener); + for (let addon of addons) { + if (addon) + addon.uninstall(); + else + listener.onUninstalled(null); + } + yield deferred.promise; +} + +// Returns promise{window}, resolves with a handle to the compatibility +// check window +function promise_open_compatibility_window(aInactiveAddonIds) { + let deferred = Promise.defer(); + // This will reset the longer timeout multiplier to 2 which will give each + // test that calls open_compatibility_window a minimum of 60 seconds to + // complete. + requestLongerTimeout(2); + + var variant = Cc["@mozilla.org/variant;1"]. + createInstance(Ci.nsIWritableVariant); + variant.setFromVariant(aInactiveAddonIds); + + // Cannot be modal as we want to interract with it, shouldn't cause problems + // with testing though. + var features = "chrome,centerscreen,dialog,titlebar"; + var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. + getService(Ci.nsIWindowWatcher); + var win = ww.openWindow(null, URI_EXTENSION_UPDATE_DIALOG, "", features, variant); + + win.addEventListener("load", function() { + function page_shown(aEvent) { + if (aEvent.target.pageid) + info("Page " + aEvent.target.pageid + " shown"); + } + + win.removeEventListener("load", arguments.callee, false); + + info("Compatibility dialog opened"); + + win.addEventListener("pageshow", page_shown, false); + win.addEventListener("unload", function() { + win.removeEventListener("unload", arguments.callee, false); + win.removeEventListener("pageshow", page_shown, false); + dump("Compatibility dialog closed\n"); + }, false); + + deferred.resolve(win); + }, false); + return deferred.promise; +} + +function promise_window_close(aWindow) { + let deferred = Promise.defer(); + aWindow.addEventListener("unload", function() { + aWindow.removeEventListener("unload", arguments.callee, false); + deferred.resolve(aWindow); + }, false); + return deferred.promise; +} + +function promise_page(aWindow, aPageId) { + let deferred = Promise.defer(); + var page = aWindow.document.getElementById(aPageId); + if (aWindow.document.getElementById("updateWizard").currentPage === page) { + deferred.resolve(aWindow); + } else { + page.addEventListener("pageshow", function() { + page.removeEventListener("pageshow", arguments.callee, false); + executeSoon(function() { + deferred.resolve(aWindow); + }); + }, false); + } + return deferred.promise; +} + +function get_list_names(aList) { + var items = []; + for (let listItem of aList.childNodes) + items.push(listItem.label); + items.sort(); + return items; +} + +// These add-ons became inactive during the upgrade +let inactiveAddonIds = [ + ao5.id, + ao6.id, + ao7.id, + ao8.id, + ao9.id +]; + +// Make sure the addons in the list are not installed +function* check_addons_uninstalled(aAddonList) { + let foundList = yield promise_addons_by_ids([addon.id for (addon of aAddonList)]); + for (let i = 0; i < aAddonList.length; i++) { + ok(!foundList[i], "Addon " + aAddonList[i].id + " is not installed"); + } + info("Add-on uninstall check complete"); + yield true; +} + +// Test what happens when the user cancels during AddonRepository.repopulateCache() +// Add-ons that have updates available should not update if they were disabled before +// For this test, addon8 became disabled during update and addon9 was previously disabled, +// so addon8 should update and addon9 should not +add_task(function cancel_during_repopulate() { + let a5, a8, a9, a10; + + Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true); + Services.prefs.setCharPref(PREF_MIN_PLATFORM_COMPAT, "0"); + Services.prefs.setCharPref(PREF_UPDATEURL, TESTROOT + "missing.rdf"); + + let installsDone = promise_observer("TEST:all-updates-done"); + + // Don't pull compatibility data during add-on install + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, false); + // Set up our test addons so that the server-side JS has a 500ms delay to make + // sure we cancel the dialog before we get the data we want to refill our + // AddonRepository cache + let addonList = [ao5, ao8, ao9, ao10]; + yield promise_install_test_addons(addonList, + TESTROOT + "cancelCompatCheck.sjs?500"); + + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); + Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, TESTROOT + "browser_bug557956.xml"); + + [a5, a8, a9] = yield promise_addons_by_ids([ao5.id, ao8.id, ao9.id]); + ok(!a5.isCompatible, "addon5 should not be compatible"); + ok(!a8.isCompatible, "addon8 should not be compatible"); + ok(!a9.isCompatible, "addon9 should not be compatible"); + + let compatWindow = yield promise_open_compatibility_window([ao5.id, ao8.id]); + var doc = compatWindow.document; + yield promise_page(compatWindow, "versioninfo"); + + // Brief delay to let the update window finish requesting all add-ons and start + // reloading the addon repository + yield delayMS(50); + + info("Cancel the compatibility check dialog"); + var button = doc.documentElement.getButton("cancel"); + EventUtils.synthesizeMouse(button, 2, 2, { }, compatWindow); + + info("Waiting for installs to complete"); + yield installsDone; + ok(!repo.AddonRepository.isSearching, "Background installs are done"); + + // There should be no active updates + let getInstalls = Promise.defer(); + AddonManager.getAllInstalls(getInstalls.resolve); + let installs = yield getInstalls.promise; + is (installs.length, 0, "There should be no active installs after background installs are done"); + + // addon8 should have updated in the background, + // addon9 was listed as previously disabled so it should not have updated + [a5, a8, a9, a10] = yield promise_addons_by_ids([ao5.id, ao8.id, ao9.id, ao10.id]); + ok(a5.isCompatible, "addon5 should be compatible"); + ok(a8.isCompatible, "addon8 should have been upgraded"); + ok(!a9.isCompatible, "addon9 should not have been upgraded"); + ok(!a10.isCompatible, "addon10 should not be compatible"); + + info("Updates done"); + yield promise_uninstall_test_addons(); + info("done uninstalling add-ons"); +}); + +// User cancels after repopulateCache, while we're waiting for the addon.findUpdates() +// calls in gVersionInfoPage_onPageShow() to complete +// For this test, both addon8 and addon9 were disabled by this update, but addon8 +// is set to not auto-update, so only addon9 should update in the background +add_task(function cancel_during_findUpdates() { + let a5, a8, a9; + + Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true); + Services.prefs.setCharPref(PREF_MIN_PLATFORM_COMPAT, "0"); + + // Clear the AddonRepository-last-updated preference to ensure that it reloads + Services.prefs.clearUserPref(PREF_METADATA_LASTUPDATE); + let observeUpdateDone = promise_observer("TEST:addon-repository-data-updated"); + let installsDone = promise_observer("TEST:all-updates-done"); + + // Don't pull compatibility data during add-on install + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, false); + // No delay on the .sjs this time because we want the cache to repopulate + let addonList = [ao3, ao5, ao6, ao7, ao8, ao9]; + yield promise_install_test_addons(addonList, + TESTROOT + "cancelCompatCheck.sjs"); + + [a8] = yield promise_addons_by_ids([ao8.id]); + a8.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE; + + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); + let compatWindow = yield promise_open_compatibility_window(inactiveAddonIds); + var doc = compatWindow.document; + yield promise_page(compatWindow, "versioninfo"); + + info("Waiting for repository-data-updated"); + yield observeUpdateDone; + + // Quick wait to make sure the findUpdates calls get queued + yield delayMS(5); + + info("Cancel the compatibility check dialog"); + var button = doc.documentElement.getButton("cancel"); + EventUtils.synthesizeMouse(button, 2, 2, { }, compatWindow); + + info("Waiting for installs to complete 2"); + yield installsDone; + ok(!repo.AddonRepository.isSearching, "Background installs are done 2"); + + // addon8 should have updated in the background, + // addon9 was listed as previously disabled so it should not have updated + [a5, a8, a9] = yield promise_addons_by_ids([ao5.id, ao8.id, ao9.id]); + ok(a5.isCompatible, "addon5 should be compatible"); + ok(!a8.isCompatible, "addon8 should not have been upgraded"); + ok(a9.isCompatible, "addon9 should have been upgraded"); + + let getInstalls = Promise.defer(); + AddonManager.getAllInstalls(getInstalls.resolve); + let installs = yield getInstalls.promise; + is (installs.length, 0, "There should be no active installs after the dialog is cancelled 2"); + + info("findUpdates done"); + yield promise_uninstall_test_addons(); +}); + +// Cancelling during the 'mismatch' screen allows add-ons that can auto-update +// to continue updating in the background and cancels any other updates +// Same conditions as the previous test - addon8 and addon9 have updates available, +// addon8 is set to not auto-update so only addon9 should become compatible +add_task(function cancel_mismatch() { + let a3, a5, a7, a8, a9; + + Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true); + Services.prefs.setCharPref(PREF_MIN_PLATFORM_COMPAT, "0"); + + // Clear the AddonRepository-last-updated preference to ensure that it reloads + Services.prefs.clearUserPref(PREF_METADATA_LASTUPDATE); + let installsDone = promise_observer("TEST:all-updates-done"); + + // Don't pull compatibility data during add-on install + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, false); + // No delay on the .sjs this time because we want the cache to repopulate + let addonList = [ao3, ao5, ao6, ao7, ao8, ao9]; + yield promise_install_test_addons(addonList, + TESTROOT + "cancelCompatCheck.sjs"); + + [a8] = yield promise_addons_by_ids([ao8.id]); + a8.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE; + + // Check that the addons start out not compatible. + [a3, a7, a8, a9] = yield promise_addons_by_ids([ao3.id, ao7.id, ao8.id, ao9.id]); + ok(!a3.isCompatible, "addon3 should not be compatible"); + ok(!a7.isCompatible, "addon7 should not be compatible"); + ok(!a8.isCompatible, "addon8 should not be compatible"); + ok(!a9.isCompatible, "addon9 should not be compatible"); + + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); + let compatWindow = yield promise_open_compatibility_window(inactiveAddonIds); + var doc = compatWindow.document; + info("Wait for mismatch page"); + yield promise_page(compatWindow, "mismatch"); + info("Click the Don't Check button"); + var button = doc.documentElement.getButton("cancel"); + EventUtils.synthesizeMouse(button, 2, 2, { }, compatWindow); + + yield promise_window_close(compatWindow); + info("Waiting for installs to complete in cancel_mismatch"); + yield installsDone; + + // addon8 should not have updated in the background, + // addon9 was listed as previously disabled so it should not have updated + [a5, a8, a9] = yield promise_addons_by_ids([ao5.id, ao8.id, ao9.id]); + ok(a5.isCompatible, "addon5 should be compatible"); + ok(!a8.isCompatible, "addon8 should not have been upgraded"); + ok(a9.isCompatible, "addon9 should have been upgraded"); + + // Make sure there are no pending addon installs + let pInstalls = Promise.defer(); + AddonManager.getAllInstalls(pInstalls.resolve); + let installs = yield pInstalls.promise; + ok(installs.length == 0, "No remaining add-on installs (" + installs.toSource() + ")"); + + yield promise_uninstall_test_addons(); + yield check_addons_uninstalled(addonList); +}); + +// Cancelling during the 'mismatch' screen with only add-ons that have +// no updates available +add_task(function cancel_mismatch_no_updates() { + let a3, a5, a6 + + Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true); + Services.prefs.setCharPref(PREF_MIN_PLATFORM_COMPAT, "0"); + + // Don't pull compatibility data during add-on install + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, false); + // No delay on the .sjs this time because we want the cache to repopulate + let addonList = [ao3, ao5, ao6]; + yield promise_install_test_addons(addonList, + TESTROOT + "cancelCompatCheck.sjs"); + + // Check that the addons start out not compatible. + [a3, a5, a6] = yield promise_addons_by_ids([ao3.id, ao5.id, ao6.id]); + ok(!a3.isCompatible, "addon3 should not be compatible"); + ok(!a5.isCompatible, "addon5 should not be compatible"); + ok(!a6.isCompatible, "addon6 should not be compatible"); + + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); + let compatWindow = yield promise_open_compatibility_window([ao3.id, ao5.id, ao6.id]); + var doc = compatWindow.document; + info("Wait for mismatch page"); + yield promise_page(compatWindow, "mismatch"); + info("Click the Don't Check button"); + var button = doc.documentElement.getButton("cancel"); + EventUtils.synthesizeMouse(button, 2, 2, { }, compatWindow); + + yield promise_window_close(compatWindow); + + [a3, a5, a6] = yield promise_addons_by_ids([ao3.id, ao5.id, ao6.id]); + ok(!a3.isCompatible, "addon3 should not be compatible"); + ok(a5.isCompatible, "addon5 should have become compatible"); + ok(a6.isCompatible, "addon6 should have become compatible"); + + // Make sure there are no pending addon installs + let pInstalls = Promise.defer(); + AddonManager.getAllInstalls(pInstalls.resolve); + let installs = yield pInstalls.promise; + ok(installs.length == 0, "No remaining add-on installs (" + installs.toSource() + ")"); + + yield promise_uninstall_test_addons(); + yield check_addons_uninstalled(addonList); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_checkAddonCompatibility.js b/toolkit/mozapps/extensions/test/browser/browser_checkAddonCompatibility.js new file mode 100644 index 000000000..6c42e0126 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_checkAddonCompatibility.js @@ -0,0 +1,34 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test that all bundled add-ons are compatible. + +function test() { + waitForExplicitFinish(); + + Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true); + ok(AddonManager.strictCompatibility, "Strict compatibility should be enabled"); + + AddonManager.getAllAddons(function gAACallback(aAddons) { + // Sort add-ons (by type and name) to improve output. + aAddons.sort(function compareTypeName(a, b) { + return a.type.localeCompare(b.type) || a.name.localeCompare(b.name); + }); + + let allCompatible = true; + for (let a of aAddons) { + // Ignore plugins. + if (a.type == "plugin") + continue; + + ok(a.isCompatible, a.type + " " + a.name + " " + a.version + " should be compatible"); + allCompatible = allCompatible && a.isCompatible; + } + // Add a reminder. + if (!allCompatible) + ok(false, "As this test failed, test browser_bug557956.js should have failed, too."); + + finish(); + }); +} diff --git a/toolkit/mozapps/extensions/test/browser/browser_debug_button.js b/toolkit/mozapps/extensions/test/browser/browser_debug_button.js new file mode 100644 index 000000000..3f371e906 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_debug_button.js @@ -0,0 +1,112 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +/** + * Tests debug button for addons in list view + */ + +let { Promise } = Components.utils.import("resource://gre/modules/Promise.jsm", {}); +let { Task } = Components.utils.import("resource://gre/modules/Task.jsm", {}); + +const getDebugButton = node => + node.ownerDocument.getAnonymousElementByAttribute(node, "anonid", "debug-btn"); +const addonDebuggingEnabled = bool => + Services.prefs.setBoolPref("devtools.chrome.enabled", !!bool); +const remoteDebuggingEnabled = bool => + Services.prefs.setBoolPref("devtools.debugger.remote-enabled", !!bool); + +function test() { + requestLongerTimeout(2); + + waitForExplicitFinish(); + + + var gProvider = new MockProvider(); + gProvider.createAddons([{ + id: "non-debuggable@tests.mozilla.org", + name: "No debug", + description: "foo" + }, + { + id: "debuggable@tests.mozilla.org", + name: "Debuggable", + description: "bar", + isDebuggable: true + }]); + + Task.spawn(function* () { + addonDebuggingEnabled(false); + remoteDebuggingEnabled(false); + + yield testDOM((nondebug, debuggable) => { + is(nondebug.disabled, true, + "addon:disabled::remote:disabled button is disabled for legacy addons"); + is(nondebug.hidden, true, + "addon:disabled::remote:disabled button is hidden for legacy addons"); + is(debuggable.disabled, true, + "addon:disabled::remote:disabled button is disabled for debuggable addons"); + is(debuggable.hidden, true, + "addon:disabled::remote:disabled button is hidden for debuggable addons"); + }); + + addonDebuggingEnabled(true); + remoteDebuggingEnabled(false); + + yield testDOM((nondebug, debuggable) => { + is(nondebug.disabled, true, + "addon:enabled::remote:disabled button is disabled for legacy addons"); + is(nondebug.disabled, true, + "addon:enabled::remote:disabled button is hidden for legacy addons"); + is(debuggable.disabled, true, + "addon:enabled::remote:disabled button is disabled for debuggable addons"); + is(debuggable.disabled, true, + "addon:enabled::remote:disabled button is hidden for debuggable addons"); + }); + + addonDebuggingEnabled(false); + remoteDebuggingEnabled(true); + + yield testDOM((nondebug, debuggable) => { + is(nondebug.disabled, true, + "addon:disabled::remote:enabled button is disabled for legacy addons"); + is(nondebug.disabled, true, + "addon:disabled::remote:enabled button is hidden for legacy addons"); + is(debuggable.disabled, true, + "addon:disabled::remote:enabled button is disabled for debuggable addons"); + is(debuggable.disabled, true, + "addon:disabled::remote:enabled button is hidden for debuggable addons"); + }); + + addonDebuggingEnabled(true); + remoteDebuggingEnabled(true); + + yield testDOM((nondebug, debuggable) => { + is(nondebug.disabled, true, + "addon:enabled::remote:enabled button is disabled for legacy addons"); + is(nondebug.disabled, true, + "addon:enabled::remote:enabled button is hidden for legacy addons"); + is(debuggable.disabled, false, + "addon:enabled::remote:enabled button is enabled for debuggable addons"); + is(debuggable.hidden, false, + "addon:enabled::remote:enabled button is visible for debuggable addons"); + }); + + finish(); + }); + + function testDOM (testCallback) { + let deferred = Promise.defer(); + open_manager("addons://list/extension", function(aManager) { + const {document} = aManager; + const addonList = document.getElementById("addon-list"); + const nondebug = addonList.querySelector("[name='No debug']"); + const debuggable = addonList.querySelector("[name='Debuggable']"); + + testCallback.apply(null, [nondebug, debuggable].map(getDebugButton)); + + close_manager(aManager, deferred.resolve); + }); + return deferred.promise; + } +} diff --git a/toolkit/mozapps/extensions/test/browser/browser_details.js b/toolkit/mozapps/extensions/test/browser/browser_details.js new file mode 100644 index 000000000..7394c87da --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_details.js @@ -0,0 +1,764 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests various aspects of the details view + +const PREF_AUTOUPDATE_DEFAULT = "extensions.update.autoUpdateDefault" +const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url"; +const SEARCH_URL = TESTROOT + "browser_details.xml"; + +var gManagerWindow; +var gCategoryUtilities; +var gProvider; + +var gApp = document.getElementById("bundle_brand").getString("brandShortName"); +var gVersion = Services.appinfo.version; +var gBlocklistURL = Services.urlFormatter.formatURLPref("extensions.blocklist.detailsURL"); +var gPluginURL = Services.urlFormatter.formatURLPref("plugins.update.url"); +var gDate = new Date(2010, 7, 1); + +function open_details(aId, aType, aCallback) { + requestLongerTimeout(2); + + gCategoryUtilities.openType(aType, function() { + var list = gManagerWindow.document.getElementById("addon-list"); + var item = list.firstChild; + while (item) { + if ("mAddon" in item && item.mAddon.id == aId) { + list.ensureElementIsVisible(item); + EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow); + EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow); + wait_for_view_load(gManagerWindow, aCallback); + return; + } + item = item.nextSibling; + } + ok(false, "Should have found the add-on in the list"); + }); +} + +function get(aId) { + return gManagerWindow.document.getElementById(aId); +} + +function test() { + requestLongerTimeout(2); + // Turn on searching for this test + Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15); + Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, SEARCH_URL); + + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + gProvider.createAddons([{ + id: "addon1@tests.mozilla.org", + name: "Test add-on 1", + version: "2.1", + description: "Short description", + fullDescription: "Longer description", + type: "extension", + iconURL: "chrome://foo/skin/icon.png", + icon64URL: "chrome://foo/skin/icon64.png", + contributionURL: "http://foo.com", + contributionAmount: "$0.99", + sourceURI: Services.io.newURI("http://example.com/foo", null, null), + averageRating: 4, + reviewCount: 5, + reviewURL: "http://example.com/reviews", + homepageURL: "http://example.com/addon1", + applyBackgroundUpdates: AddonManager.AUTOUPDATE_ENABLE + }, { + id: "addon2@tests.mozilla.org", + name: "Test add-on 2", + version: "2.2", + description: "Short description", + creator: { name: "Mozilla", url: null }, + type: "extension", + iconURL: "chrome://foo/skin/icon.png", + contributionURL: "http://foo.com", + contributionAmount: null, + updateDate: gDate, + permissions: 0, + screenshots: [{ + url: "chrome://branding/content/about.png", + width: 200, + height: 150 + }], + }, { + id: "addon3@tests.mozilla.org", + name: "Test add-on 3", + description: "Short description", + creator: { name: "Mozilla", url: "http://www.mozilla.org" }, + type: "extension", + sourceURI: Services.io.newURI("http://example.com/foo", null, null), + updateDate: gDate, + reviewCount: 1, + reviewURL: "http://example.com/reviews", + applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE, + isActive: false, + isCompatible: false, + appDisabled: true, + permissions: AddonManager.PERM_CAN_ENABLE | + AddonManager.PERM_CAN_DISABLE | + AddonManager.PERM_CAN_UPGRADE, + screenshots: [{ + url: "http://example.com/screenshot", + width: 400, + height: 300, + thumbnailURL: "chrome://branding/content/icon64.png", + thumbnailWidth: 160, + thumbnailHeight: 120 + }], + }, { + id: "addon4@tests.mozilla.org", + blocklistURL: "http://example.com/addon4@tests.mozilla.org", + name: "Test add-on 4", + _userDisabled: true, + isActive: false, + blocklistState: Ci.nsIBlocklistService.STATE_SOFTBLOCKED + }, { + id: "addon5@tests.mozilla.org", + blocklistURL: "http://example.com/addon5@tests.mozilla.org", + name: "Test add-on 5", + isActive: false, + blocklistState: Ci.nsIBlocklistService.STATE_BLOCKED, + appDisabled: true + }, { + id: "addon6@tests.mozilla.org", + blocklistURL: "http://example.com/addon6@tests.mozilla.org", + name: "Test add-on 6", + operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE + }, { + id: "addon7@tests.mozilla.org", + blocklistURL: "http://example.com/addon7@tests.mozilla.org", + name: "Test add-on 7", + _userDisabled: true, + isActive: false + }, { + id: "addon8@tests.mozilla.org", + blocklistURL: "http://example.com/addon8@tests.mozilla.org", + name: "Test add-on 8", + blocklistState: Ci.nsIBlocklistService.STATE_OUTDATED + }]); + + open_manager(null, function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, function() { + finish(); + }); +} + +// Opens and tests the details view for add-on 1 +add_test(function() { + open_details("addon1@tests.mozilla.org", "extension", function() { + is(get("detail-name").textContent, "Test add-on 1", "Name should be correct"); + is_element_visible(get("detail-version"), "Version should not be hidden"); + is(get("detail-version").value, "2.1", "Version should be correct"); + is(get("detail-icon").src, "chrome://foo/skin/icon64.png", "Icon should be correct"); + is_element_hidden(get("detail-creator"), "Creator should be hidden"); + is_element_hidden(get("detail-screenshot"), "Screenshot should be hidden"); + is(get("detail-screenshot").width, "", "Screenshot dimensions should not be set"); + is(get("detail-screenshot").height, "", "Screenshot dimensions should not be set"); + is(get("detail-desc").textContent, "Short description", "Description should be correct"); + is(get("detail-fulldesc").textContent, "Longer description", "Full description should be correct"); + + is_element_visible(get("detail-contributions"), "Contributions section should be visible"); + is_element_visible(get("detail-contrib-suggested"), "Contributions amount should be visible"); + ok(get("detail-contrib-suggested").value, "$0.99"); + + is_element_visible(get("detail-updates-row"), "Updates should not be hidden"); + is_element_hidden(get("detail-dateUpdated"), "Update date should be hidden"); + + is_element_visible(get("detail-rating-row"), "Rating row should not be hidden"); + is_element_visible(get("detail-rating"), "Rating should not be hidden"); + is(get("detail-rating").averageRating, 4, "Rating should be correct"); + is_element_visible(get("detail-reviews"), "Reviews should not be hidden"); + is(get("detail-reviews").href, "http://example.com/reviews", "Review URL should be correct"); + is(get("detail-reviews").value, "5 reviews", "Review text should be correct"); + + is_element_visible(get("detail-homepage-row"), "Homepage should be visible"); + ok(get("detail-homepage").href, "http://example.com/addon1"); + is_element_hidden(get("detail-repository-row"), "Repository profile should not be visible"); + + is_element_hidden(get("detail-size"), "Size should be hidden"); + + is_element_hidden(get("detail-downloads"), "Downloads should be hidden"); + + is_element_visible(get("detail-autoUpdate"), "Updates should not be hidden"); + ok(get("detail-autoUpdate").childNodes[1].selected, "Updates ahould be automatic"); + is_element_hidden(get("detail-findUpdates-btn"), "Check for updates should be hidden"); + EventUtils.synthesizeMouseAtCenter(get("detail-autoUpdate").lastChild, {}, gManagerWindow); + ok(get("detail-autoUpdate").lastChild.selected, "Updates should be manual"); + is_element_visible(get("detail-findUpdates-btn"), "Check for updates should be visible"); + EventUtils.synthesizeMouseAtCenter(get("detail-autoUpdate").firstChild, {}, gManagerWindow); + ok(get("detail-autoUpdate").firstChild.selected, "Updates should be automatic"); + is_element_hidden(get("detail-findUpdates-btn"), "Check for updates should be hidden"); + + is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); + is_element_hidden(get("detail-enable-btn"), "Enable button should be hidden"); + is_element_visible(get("detail-disable-btn"), "Disable button should be visible"); + is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); + + is_element_hidden(get("detail-warning"), "Warning message should be hidden"); + is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); + is_element_hidden(get("detail-error"), "Error message should be hidden"); + is_element_hidden(get("detail-pending"), "Pending message should be hidden"); + + // Disable it + EventUtils.synthesizeMouseAtCenter(get("detail-disable-btn"), {}, gManagerWindow); + is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); + is_element_visible(get("detail-enable-btn"), "Enable button should be visible"); + is_element_hidden(get("detail-disable-btn"), "Disable button should be hidden"); + is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); + + is_element_hidden(get("detail-warning"), "Warning message should be hidden"); + is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); + is_element_hidden(get("detail-error"), "Error message should be hidden"); + is_element_hidden(get("detail-error-link"), "Error link should be hidden"); + is_element_visible(get("detail-pending"), "Pending message should be visible"); + is(get("detail-pending").textContent, "Test add-on 1 will be disabled after you restart " + gApp + ".", "Pending message should be correct"); + + // Reopen it + open_details("addon1@tests.mozilla.org", "extension", function() { + is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); + is_element_visible(get("detail-enable-btn"), "Enable button should be visible"); + is_element_hidden(get("detail-disable-btn"), "Disable button should be hidden"); + is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); + + is_element_hidden(get("detail-warning"), "Warning message should be hidden"); + is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); + is_element_hidden(get("detail-error"), "Error message should be hidden"); + is_element_hidden(get("detail-error-link"), "Error link should be hidden"); + is_element_visible(get("detail-pending"), "Pending message should be visible"); + is(get("detail-pending").textContent, "Test add-on 1 will be disabled after you restart " + gApp + ".", "Pending message should be correct"); + + // Undo disabling + EventUtils.synthesizeMouseAtCenter(get("detail-undo-btn"), {}, gManagerWindow); + is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); + is_element_hidden(get("detail-enable-btn"), "Enable button should be hidden"); + is_element_visible(get("detail-disable-btn"), "Disable button should be visible"); + is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); + + is_element_hidden(get("detail-warning"), "Warning message should be hidden"); + is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); + is_element_hidden(get("detail-error"), "Error message should be hidden"); + is_element_hidden(get("detail-error-link"), "Error link should be hidden"); + is_element_hidden(get("detail-pending"), "Pending message should be hidden"); + + run_next_test(); + }); + }); +}); + +// Opens and tests the details view for add-on 2 +add_test(function() { + open_details("addon2@tests.mozilla.org", "extension", function() { + is(get("detail-name").textContent, "Test add-on 2", "Name should be correct"); + is_element_visible(get("detail-version"), "Version should not be hidden"); + is(get("detail-version").value, "2.2", "Version should be correct"); + is(get("detail-icon").src, "chrome://foo/skin/icon.png", "Icon should be correct"); + + is_element_visible(get("detail-creator"), "Creator should not be hidden"); + is_element_visible(get("detail-creator")._creatorName, "Creator name should not be hidden"); + is(get("detail-creator")._creatorName.value, "Mozilla", "Creator should be correct"); + is_element_hidden(get("detail-creator")._creatorLink, "Creator link should be hidden"); + + is_element_visible(get("detail-screenshot"), "Screenshot should be visible"); + is(get("detail-screenshot").src, "chrome://branding/content/about.png", "Should be showing the full sized screenshot"); + is(get("detail-screenshot").width, 200, "Screenshot dimensions should be set"); + is(get("detail-screenshot").height, 150, "Screenshot dimensions should be set"); + is(get("detail-screenshot").hasAttribute("loading"), true, "Screenshot should have loading attribute"); + is(get("detail-desc").textContent, "Short description", "Description should be correct"); + is_element_hidden(get("detail-fulldesc"), "Full description should be hidden"); + + is_element_visible(get("detail-contributions"), "Contributions section should be visible"); + is_element_hidden(get("detail-contrib-suggested"), "Contributions amount should be hidden"); + + is_element_visible(get("detail-dateUpdated"), "Update date should not be hidden"); + is(get("detail-dateUpdated").value, formatDate(gDate), "Update date should be correct"); + + is_element_hidden(get("detail-rating-row"), "Rating should be hidden"); + + is_element_hidden(get("detail-homepage-row"), "Homepage should not be visible"); + is_element_hidden(get("detail-repository-row"), "Repository profile should not be visible"); + + is_element_hidden(get("detail-size"), "Size should be hidden"); + + is_element_hidden(get("detail-downloads"), "Downloads should be hidden"); + + is_element_hidden(get("detail-updates-row"), "Updates should be hidden"); + + is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); + is_element_hidden(get("detail-enable-btn"), "Enable button should be hidden"); + is_element_hidden(get("detail-disable-btn"), "Disable button should be hidden"); + is_element_hidden(get("detail-uninstall-btn"), "Remove button should be hidden"); + + is_element_hidden(get("detail-warning"), "Warning message should be hidden"); + is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); + is_element_hidden(get("detail-error"), "Error message should be hidden"); + is_element_hidden(get("detail-error-link"), "Error link should be hidden"); + is_element_hidden(get("detail-pending"), "Pending message should be hidden"); + + get("detail-screenshot").addEventListener("load", function() { + this.removeEventListener("load", arguments.callee, false); + is(this.hasAttribute("loading"), false, "Screenshot should not have loading attribute"); + run_next_test(); + }, false); + }); +}); + +// Opens and tests the details view for add-on 3 +add_test(function() { + open_details("addon3@tests.mozilla.org", "extension", function() { + is(get("detail-name").textContent, "Test add-on 3", "Name should be correct"); + is_element_hidden(get("detail-version"), "Version should be hidden"); + is(get("detail-icon").src, "", "Icon should be correct"); + + is_element_visible(get("detail-creator"), "Creator should not be hidden"); + is_element_hidden(get("detail-creator")._creatorName, "Creator name should be hidden"); + is_element_visible(get("detail-creator")._creatorLink, "Creator link should not be hidden"); + is(get("detail-creator")._creatorLink.value, "Mozilla", "Creator link should be correct"); + is(get("detail-creator")._creatorLink.href, "http://www.mozilla.org", "Creator link href should be correct"); + + is_element_visible(get("detail-screenshot"), "Screenshot should be visible"); + is(get("detail-screenshot").src, "chrome://branding/content/icon64.png", "Should be showing the thumbnail"); + is(get("detail-screenshot").width, 160, "Screenshot dimensions should be set"); + is(get("detail-screenshot").height, 120, "Screenshot dimensions should be set"); + is(get("detail-screenshot").hasAttribute("loading"), true, "Screenshot should have loading attribute"); + + is_element_hidden(get("detail-contributions"), "Contributions section should be hidden"); + + is_element_visible(get("detail-updates-row"), "Updates should not be hidden"); + is_element_visible(get("detail-dateUpdated"), "Update date should not be hidden"); + is(get("detail-dateUpdated").value, formatDate(gDate), "Update date should be correct"); + + is_element_visible(get("detail-rating-row"), "Rating row should not be hidden"); + is_element_hidden(get("detail-rating"), "Rating should be hidden"); + is_element_visible(get("detail-reviews"), "Reviews should not be hidden"); + is(get("detail-reviews").href, "http://example.com/reviews", "Review URL should be correct"); + is(get("detail-reviews").value, "1 review", "Review text should be correct"); + + is_element_hidden(get("detail-size"), "Size should be hidden"); + + is_element_hidden(get("detail-downloads"), "Downloads should be hidden"); + + is_element_visible(get("detail-autoUpdate"), "Updates should not be hidden"); + ok(get("detail-autoUpdate").lastChild.selected, "Updates should be manual"); + is_element_visible(get("detail-findUpdates-btn"), "Check for updates should be visible"); + EventUtils.synthesizeMouseAtCenter(get("detail-autoUpdate").childNodes[1], {}, gManagerWindow); + ok(get("detail-autoUpdate").childNodes[1].selected, "Updates should be automatic"); + is_element_hidden(get("detail-findUpdates-btn"), "Check for updates should be hidden"); + EventUtils.synthesizeMouseAtCenter(get("detail-autoUpdate").lastChild, {}, gManagerWindow); + ok(get("detail-autoUpdate").lastChild.selected, "Updates should be manual"); + is_element_visible(get("detail-findUpdates-btn"), "Check for updates should be visible"); + + info("Setting " + PREF_AUTOUPDATE_DEFAULT + " to true"); + Services.prefs.setBoolPref(PREF_AUTOUPDATE_DEFAULT, true); + EventUtils.synthesizeMouseAtCenter(get("detail-autoUpdate").firstChild, {}, gManagerWindow); + ok(get("detail-autoUpdate").firstChild.selected, "Updates should be default"); + is_element_hidden(get("detail-findUpdates-btn"), "Check for updates should be hidden"); + + info("Setting " + PREF_AUTOUPDATE_DEFAULT + " to false"); + Services.prefs.setBoolPref(PREF_AUTOUPDATE_DEFAULT, false); + ok(get("detail-autoUpdate").firstChild.selected, "Updates should be default"); + is_element_visible(get("detail-findUpdates-btn"), "Check for updates should be visible"); + EventUtils.synthesizeMouseAtCenter(get("detail-autoUpdate").childNodes[1], {}, gManagerWindow); + ok(get("detail-autoUpdate").childNodes[1].selected, "Updates should be automatic"); + is_element_hidden(get("detail-findUpdates-btn"), "Check for updates should be hidden"); + EventUtils.synthesizeMouseAtCenter(get("detail-autoUpdate").firstChild, {}, gManagerWindow); + ok(get("detail-autoUpdate").firstChild.selected, "Updates should be default"); + is_element_visible(get("detail-findUpdates-btn"), "Check for updates should be visible"); + Services.prefs.clearUserPref(PREF_AUTOUPDATE_DEFAULT); + + is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); + is_element_hidden(get("detail-enable-btn"), "Enable button should be hidden"); + is_element_hidden(get("detail-disable-btn"), "Disable button should be hidden"); + is_element_hidden(get("detail-uninstall-btn"), "Remove button should be hidden"); + + is_element_visible(get("detail-warning"), "Warning message should be visible"); + is(get("detail-warning").textContent, "Test add-on 3 is incompatible with " + gApp + " " + gVersion + ".", "Warning message should be correct"); + is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); + is_element_hidden(get("detail-error"), "Error message should be hidden"); + is_element_hidden(get("detail-error-link"), "Error link should be hidden"); + is_element_hidden(get("detail-pending"), "Pending message should be hidden"); + + get("detail-screenshot").addEventListener("load", function() { + this.removeEventListener("load", arguments.callee, false); + is(this.hasAttribute("loading"), false, "Screenshot should not have loading attribute"); + run_next_test(); + }, false); + }); +}); + +// Opens and tests the details view for add-on 4 +add_test(function() { + open_details("addon4@tests.mozilla.org", "extension", function() { + is(get("detail-name").textContent, "Test add-on 4", "Name should be correct"); + + is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); + is_element_visible(get("detail-enable-btn"), "Enable button should be visible"); + is_element_hidden(get("detail-disable-btn"), "Disable button should be hidden"); + is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); + + is_element_visible(get("detail-warning"), "Warning message should be visible"); + is(get("detail-warning").textContent, "Test add-on 4 is known to cause security or stability issues.", "Warning message should be correct"); + is_element_visible(get("detail-warning-link"), "Warning link should be visible"); + is(get("detail-warning-link").value, "More Information", "Warning link text should be correct"); + is(get("detail-warning-link").href, "http://example.com/addon4@tests.mozilla.org", "Warning link should be correct"); + is_element_hidden(get("detail-error"), "Error message should be hidden"); + is_element_hidden(get("detail-error-link"), "Error link should be hidden"); + is_element_hidden(get("detail-pending"), "Pending message should be hidden"); + + // Enable it + EventUtils.synthesizeMouseAtCenter(get("detail-enable-btn"), {}, gManagerWindow); + is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); + is_element_hidden(get("detail-enable-btn"), "Enable button should be hidden"); + is_element_visible(get("detail-disable-btn"), "Disable button should be visible"); + is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); + + is_element_hidden(get("detail-warning"), "Warning message should be hidden"); + is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); + is_element_hidden(get("detail-error"), "Error message should be hidden"); + is_element_hidden(get("detail-error-link"), "Error link should be hidden"); + is_element_visible(get("detail-pending"), "Pending message should be visible"); + is(get("detail-pending").textContent, "Test add-on 4 will be enabled after you restart " + gApp + ".", "Pending message should be correct"); + + // Reopen it + open_details("addon4@tests.mozilla.org", "extension", function() { + is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); + is_element_hidden(get("detail-enable-btn"), "Enable button should be hidden"); + is_element_visible(get("detail-disable-btn"), "Disable button should be visible"); + is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); + + is_element_hidden(get("detail-warning"), "Warning message should be hidden"); + is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); + is_element_hidden(get("detail-error"), "Error message should be hidden"); + is_element_hidden(get("detail-error-link"), "Error link should be hidden"); + is_element_visible(get("detail-pending"), "Pending message should be visible"); + is(get("detail-pending").textContent, "Test add-on 4 will be enabled after you restart " + gApp + ".", "Pending message should be correct"); + + // Undo enabling + EventUtils.synthesizeMouseAtCenter(get("detail-undo-btn"), {}, gManagerWindow); + is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); + is_element_visible(get("detail-enable-btn"), "Enable button should be visible"); + is_element_hidden(get("detail-disable-btn"), "Disable button should be hidden"); + is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); + + is_element_visible(get("detail-warning"), "Warning message should be visible"); + is(get("detail-warning").textContent, "Test add-on 4 is known to cause security or stability issues.", "Warning message should be correct"); + is_element_visible(get("detail-warning-link"), "Warning link should be visible"); + is(get("detail-warning-link").value, "More Information", "Warning link text should be correct"); + is(get("detail-warning-link").href, "http://example.com/addon4@tests.mozilla.org", "Warning link should be correct"); + is_element_hidden(get("detail-error"), "Error message should be hidden"); + is_element_hidden(get("detail-error-link"), "Error link should be hidden"); + is_element_hidden(get("detail-pending"), "Pending message should be hidden"); + + run_next_test(); + }); + }); +}); + +// Opens and tests the details view for add-on 5 +add_test(function() { + open_details("addon5@tests.mozilla.org", "extension", function() { + is(get("detail-name").textContent, "Test add-on 5", "Name should be correct"); + + is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); + is_element_hidden(get("detail-enable-btn"), "Enable button should be hidden"); + is_element_hidden(get("detail-disable-btn"), "Disable button should be hidden"); + is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); + + is_element_hidden(get("detail-warning"), "Warning message should be hidden"); + is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); + is_element_visible(get("detail-error"), "Error message should be visible"); + is(get("detail-error").textContent, "Test add-on 5 has been disabled due to security or stability issues.", "Error message should be correct"); + is_element_visible(get("detail-error-link"), "Error link should be visible"); + is(get("detail-error-link").value, "More Information", "Error link text should be correct"); + is(get("detail-error-link").href, "http://example.com/addon5@tests.mozilla.org", "Error link should be correct"); + is_element_hidden(get("detail-pending"), "Pending message should be hidden"); + + run_next_test(); + }); +}); + +// Opens and tests the details view for add-on 6 +add_test(function() { + open_details("addon6@tests.mozilla.org", "extension", function() { + is(get("detail-name").textContent, "Test add-on 6", "Name should be correct"); + + is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); + is_element_hidden(get("detail-enable-btn"), "Enable button should be hidden"); + is_element_visible(get("detail-disable-btn"), "Disable button should be visible"); + is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); + + is_element_hidden(get("detail-warning"), "Warning message should be hidden"); + is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); + is_element_hidden(get("detail-error"), "Error message should be hidden"); + is_element_hidden(get("detail-error-link"), "Error link should be hidden"); + is_element_hidden(get("detail-pending"), "Pending message should be hidden"); + + // Disable it + EventUtils.synthesizeMouseAtCenter(get("detail-disable-btn"), {}, gManagerWindow); + is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); + is_element_visible(get("detail-enable-btn"), "Enable button should be visible"); + is_element_hidden(get("detail-disable-btn"), "Disable button should be hidden"); + is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); + + is_element_hidden(get("detail-warning"), "Warning message should be hidden"); + is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); + is_element_hidden(get("detail-error"), "Error message should be hidden"); + is_element_hidden(get("detail-error-link"), "Error link should be hidden"); + is_element_hidden(get("detail-pending"), "Pending message should be hidden"); + + // Reopen it + open_details("addon6@tests.mozilla.org", "extension", function() { + is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); + is_element_visible(get("detail-enable-btn"), "Enable button should be visible"); + is_element_hidden(get("detail-disable-btn"), "Disable button should be hidden"); + is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); + + is_element_hidden(get("detail-warning"), "Warning message should be hidden"); + is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); + is_element_hidden(get("detail-error"), "Error message should be hidden"); + is_element_hidden(get("detail-error-link"), "Error link should be hidden"); + is_element_hidden(get("detail-pending"), "Pending message should be visible"); + + // Enable it + EventUtils.synthesizeMouseAtCenter(get("detail-enable-btn"), {}, gManagerWindow); + is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); + is_element_hidden(get("detail-enable-btn"), "Enable button should be hidden"); + is_element_visible(get("detail-disable-btn"), "Disable button should be visible"); + is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); + + is_element_hidden(get("detail-warning"), "Warning message should be hidden"); + is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); + is_element_hidden(get("detail-error"), "Error message should be hidden"); + is_element_hidden(get("detail-error-link"), "Error link should be hidden"); + is_element_hidden(get("detail-pending"), "Pending message should be hidden"); + + run_next_test(); + }); + }); +}); + +// Opens and tests the details view for add-on 7 +add_test(function() { + open_details("addon7@tests.mozilla.org", "extension", function() { + is(get("detail-name").textContent, "Test add-on 7", "Name should be correct"); + + is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); + is_element_visible(get("detail-enable-btn"), "Enable button should be visible"); + is_element_hidden(get("detail-disable-btn"), "Disable button should be hidden"); + is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); + + is_element_hidden(get("detail-warning"), "Warning message should be hidden"); + is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); + is_element_hidden(get("detail-error"), "Error message should be hidden"); + is_element_hidden(get("detail-error-link"), "Error link should be hidden"); + is_element_hidden(get("detail-pending"), "Pending message should be hidden"); + + // Enable it + EventUtils.synthesizeMouseAtCenter(get("detail-enable-btn"), {}, gManagerWindow); + is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); + is_element_hidden(get("detail-enable-btn"), "Enable button should be hidden"); + is_element_visible(get("detail-disable-btn"), "Disable button should be visible"); + is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); + + is_element_hidden(get("detail-warning"), "Warning message should be hidden"); + is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); + is_element_hidden(get("detail-error"), "Error message should be hidden"); + is_element_hidden(get("detail-error-link"), "Error link should be hidden"); + is_element_visible(get("detail-pending"), "Pending message should be visible"); + is(get("detail-pending").textContent, "Test add-on 7 will be enabled after you restart " + gApp + ".", "Pending message should be correct"); + + // Reopen it + open_details("addon7@tests.mozilla.org", "extension", function() { + is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); + is_element_hidden(get("detail-enable-btn"), "Enable button should be hidden"); + is_element_visible(get("detail-disable-btn"), "Disable button should be visible"); + is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); + + is_element_hidden(get("detail-warning"), "Warning message should be hidden"); + is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); + is_element_hidden(get("detail-error"), "Error message should be hidden"); + is_element_hidden(get("detail-error-link"), "Error link should be hidden"); + is_element_visible(get("detail-pending"), "Pending message should be visible"); + is(get("detail-pending").textContent, "Test add-on 7 will be enabled after you restart " + gApp + ".", "Pending message should be correct"); + + // Undo enabling + EventUtils.synthesizeMouseAtCenter(get("detail-undo-btn"), {}, gManagerWindow); + is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); + is_element_visible(get("detail-enable-btn"), "Enable button should be visible"); + is_element_hidden(get("detail-disable-btn"), "Disable button should be hidden"); + is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); + + is_element_hidden(get("detail-warning"), "Warning message should be hidden"); + is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); + is_element_hidden(get("detail-error"), "Error message should be hidden"); + is_element_hidden(get("detail-error-link"), "Error link should be hidden"); + is_element_hidden(get("detail-pending"), "Pending message should be hidden"); + + run_next_test(); + }); + }); +}); + +// Opens and tests the details view for add-on 8 +add_test(function() { + open_details("addon8@tests.mozilla.org", "extension", function() { + is(get("detail-name").textContent, "Test add-on 8", "Name should be correct"); + + is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); + is_element_hidden(get("detail-enable-btn"), "Enable button should be hidden"); + is_element_visible(get("detail-disable-btn"), "Disable button should be visible"); + is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); + + is_element_visible(get("detail-warning"), "Warning message should be visible"); + is(get("detail-warning").textContent, "An important update is available for Test add-on 8.", "Warning message should be correct"); + is_element_visible(get("detail-warning-link"), "Warning link should be visible"); + is(get("detail-warning-link").value, "Update Now", "Warning link text should be correct"); + is(get("detail-warning-link").href, gPluginURL, "Warning link should be correct"); + is_element_hidden(get("detail-error"), "Error message should be hidden"); + is_element_hidden(get("detail-error-link"), "Error link should be hidden"); + is_element_hidden(get("detail-pending"), "Pending message should be hidden"); + + // Disable it + EventUtils.synthesizeMouseAtCenter(get("detail-disable-btn"), {}, gManagerWindow); + is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); + is_element_visible(get("detail-enable-btn"), "Enable button should be visible"); + is_element_hidden(get("detail-disable-btn"), "Disable button should be hidden"); + is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); + + is_element_hidden(get("detail-warning"), "Warning message should be hidden"); + is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); + is_element_hidden(get("detail-error"), "Error message should be hidden"); + is_element_hidden(get("detail-error-link"), "Error link should be hidden"); + is_element_visible(get("detail-pending"), "Pending message should be visible"); + is(get("detail-pending").textContent, "Test add-on 8 will be disabled after you restart " + gApp + ".", "Pending message should be correct"); + + // Reopen it + open_details("addon8@tests.mozilla.org", "extension", function() { + is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); + is_element_visible(get("detail-enable-btn"), "Enable button should be visible"); + is_element_hidden(get("detail-disable-btn"), "Disable button should be hidden"); + is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); + + is_element_hidden(get("detail-warning"), "Warning message should be hidden"); + is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); + is_element_hidden(get("detail-error"), "Error message should be hidden"); + is_element_hidden(get("detail-error-link"), "Error link should be hidden"); + is_element_visible(get("detail-pending"), "Pending message should be visible"); + is(get("detail-pending").textContent, "Test add-on 8 will be disabled after you restart " + gApp + ".", "Pending message should be correct"); + + // Undo disabling + EventUtils.synthesizeMouseAtCenter(get("detail-undo-btn"), {}, gManagerWindow); + is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden"); + is_element_hidden(get("detail-enable-btn"), "Enable button should be hidden"); + is_element_visible(get("detail-disable-btn"), "Disable button should be visible"); + is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); + + is_element_visible(get("detail-warning"), "Warning message should be visible"); + is(get("detail-warning").textContent, "An important update is available for Test add-on 8.", "Warning message should be correct"); + is_element_visible(get("detail-warning-link"), "Warning link should be visible"); + is(get("detail-warning-link").value, "Update Now", "Warning link text should be correct"); + is(get("detail-warning-link").href, gPluginURL, "Warning link should be correct"); + is_element_hidden(get("detail-error"), "Error message should be hidden"); + is_element_hidden(get("detail-error-link"), "Error link should be hidden"); + is_element_hidden(get("detail-pending"), "Pending message should be hidden"); + + run_next_test(); + }); + }); +}); + +// Tests that upgrades with onExternalInstall apply immediately +add_test(function() { + open_details("addon1@tests.mozilla.org", "extension", function() { + gProvider.createAddons([{ + id: "addon1@tests.mozilla.org", + name: "Test add-on replacement", + version: "2.5", + description: "Short description replacement", + fullDescription: "Longer description replacement", + type: "extension", + iconURL: "chrome://foo/skin/icon.png", + icon64URL: "chrome://foo/skin/icon264.png", + sourceURI: Services.io.newURI("http://example.com/foo", null, null), + averageRating: 2, + optionsURL: "chrome://foo/content/options.xul", + applyBackgroundUpdates: AddonManager.AUTOUPDATE_ENABLE, + operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE + }]); + + is(get("detail-name").textContent, "Test add-on replacement", "Name should be correct"); + is_element_visible(get("detail-version"), "Version should not be hidden"); + is(get("detail-version").value, "2.5", "Version should be correct"); + is(get("detail-icon").src, "chrome://foo/skin/icon264.png", "Icon should be correct"); + is_element_hidden(get("detail-creator"), "Creator should be hidden"); + is_element_hidden(get("detail-screenshot"), "Screenshot should be hidden"); + is(get("detail-desc").textContent, "Short description replacement", "Description should be correct"); + is(get("detail-fulldesc").textContent, "Longer description replacement", "Full description should be correct"); + + is_element_hidden(get("detail-contributions"), "Contributions section should be hidden"); + + is_element_hidden(get("detail-dateUpdated"), "Update date should be hidden"); + + is_element_visible(get("detail-rating-row"), "Rating row should not be hidden"); + is_element_visible(get("detail-rating"), "Rating should not be hidden"); + is(get("detail-rating").averageRating, 2, "Rating should be correct"); + is_element_hidden(get("detail-reviews"), "Reviews should be hidden"); + + is_element_hidden(get("detail-homepage-row"), "Homepage should be hidden"); + + is_element_hidden(get("detail-size"), "Size should be hidden"); + + is_element_hidden(get("detail-downloads"), "Downloads should be hidden"); + + is_element_visible(get("detail-prefs-btn"), "Preferences button should be visible"); + is_element_hidden(get("detail-enable-btn"), "Enable button should be hidden"); + is_element_visible(get("detail-disable-btn"), "Disable button should be visible"); + is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible"); + + is_element_hidden(get("detail-warning"), "Warning message should be hidden"); + is_element_hidden(get("detail-warning-link"), "Warning link should be hidden"); + is_element_hidden(get("detail-error"), "Error message should be hidden"); + is_element_hidden(get("detail-pending"), "Pending message should be hidden"); + + run_next_test(); + }); +}); + +// Check that onPropertyChanges for appDisabled updates the UI +add_test(function() { + info("Checking that onPropertyChanges for appDisabled updates the UI"); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { + aAddon.userDisabled = true; + aAddon.isCompatible = true; + aAddon.appDisabled = false; + + open_details("addon1@tests.mozilla.org", "extension", function() { + is(get("detail-view").getAttribute("active"), "false", "Addon should not be marked as active"); + is_element_hidden(get("detail-warning"), "Warning message should not be visible"); + + info("Making addon incompatible and appDisabled"); + aAddon.isCompatible = false; + aAddon.appDisabled = true; + + is(get("detail-view").getAttribute("active"), "false", "Addon should not be marked as active"); + is_element_visible(get("detail-warning"), "Warning message should be visible"); + is(get("detail-warning").textContent, "Test add-on replacement is incompatible with " + gApp + " " + gVersion + ".", "Warning message should be correct"); + + run_next_test(); + }); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_discovery.js b/toolkit/mozapps/extensions/test/browser/browser_discovery.js new file mode 100644 index 000000000..708ba311b --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_discovery.js @@ -0,0 +1,637 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that the discovery view loads properly + +const MAIN_URL = "https://example.com/" + RELATIVE_DIR + "discovery.html"; + +var gManagerWindow; +var gCategoryUtilities; +var gProvider; + +var gLoadCompleteCallback = null; + +var gProgressListener = { + onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) { + // Only care about the network stop status events + if (!(aStateFlags & (Ci.nsIWebProgressListener.STATE_IS_NETWORK)) || + !(aStateFlags & (Ci.nsIWebProgressListener.STATE_STOP))) + return; + + if (gLoadCompleteCallback) + executeSoon(gLoadCompleteCallback); + gLoadCompleteCallback = null; + }, + + onLocationChange: function() { }, + onSecurityChange: function() { }, + onProgressChange: function() { }, + onStatusChange: function() { }, + + QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener, + Ci.nsISupportsWeakReference]), +}; + +function test() { + // Switch to a known url + Services.prefs.setCharPref(PREF_DISCOVERURL, MAIN_URL); + // Temporarily enable caching + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); + + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + gProvider.createAddons([{ + id: "addon1@tests.mozilla.org", + name: "Test add-on 1", + type: "extension", + version: "2.2", + isCompatible: false, + blocklistState: Ci.nsIBlocklistService.STATE_SOFTBLOCKED, + userDisabled: false + }, { + id: "addon2@tests.mozilla.org", + name: "Test add-on 2", + type: "plugin", + version: "3.1.5", + isCompatible: true, + blocklistState: Ci.nsIBlocklistService.STATE_NOT_BLOCKED, + userDisabled: false + }, { + id: "addon3@tests.mozilla.org", + name: "Test add-on 3", + type: "theme", + version: "1.2b1", + isCompatible: false, + blocklistState: Ci.nsIBlocklistService.STATE_BLOCKED, + userDisabled: true + }]); + + run_next_test(); +} + +function end_test() { + finish(); +} + +function getURL(aBrowser) { + if (gManagerWindow.document.getElementById("discover-view").selectedPanel != + aBrowser) + return null; + + var url = aBrowser.currentURI.spec; + var pos = url.indexOf("#"); + if (pos != -1) + return url.substring(0, pos); + return url; +} + +function getHash(aBrowser) { + if (gManagerWindow.document.getElementById("discover-view").selectedPanel != + aBrowser) + return null; + + var url = aBrowser.currentURI.spec; + var pos = url.indexOf("#"); + if (pos != -1) + return decodeURIComponent(url.substring(pos + 1)); + return null; +} + +function testHash(aBrowser, aTestAddonVisible, aCallback) { + var hash = getHash(aBrowser); + isnot(hash, null, "There should be a hash"); + try { + var data = JSON.parse(hash); + } + catch (e) { + ok(false, "Hash should have been valid JSON: " + e); + aCallback(); + return; + } + is(typeof data, "object", "Hash should be a JS object"); + + // Ensure that at least the test add-ons are present + if (aTestAddonVisible[0]) + ok("addon1@tests.mozilla.org" in data, "Test add-on 1 should be listed"); + else + ok(!("addon1@tests.mozilla.org" in data), "Test add-on 1 should not be listed"); + if (aTestAddonVisible[1]) + ok("addon2@tests.mozilla.org" in data, "Test add-on 2 should be listed"); + else + ok(!("addon2@tests.mozilla.org" in data), "Test add-on 2 should not be listed"); + if (aTestAddonVisible[2]) + ok("addon3@tests.mozilla.org" in data, "Test add-on 3 should be listed"); + else + ok(!("addon3@tests.mozilla.org" in data), "Test add-on 3 should not be listed"); + + // Test against all the add-ons the manager knows about since plugins and + // app extensions may exist + AddonManager.getAllAddons(function(aAddons) { + for (let addon of aAddons) { + if (!(addon.id in data)) { + // Test add-ons will have shown an error if necessary above + if (addon.id.substring(6) != "@tests.mozilla.org") + ok(false, "Add-on " + addon.id + " was not included in the data"); + continue; + } + + info("Testing data for add-on " + addon.id); + var addonData = data[addon.id]; + is(addonData.name, addon.name, "Name should be correct"); + is(addonData.version, addon.version, "Version should be correct"); + is(addonData.type, addon.type, "Type should be correct"); + is(addonData.userDisabled, addon.userDisabled, "userDisabled should be correct"); + is(addonData.isBlocklisted, addon.blocklistState == Ci.nsIBlocklistService.STATE_BLOCKED, "blocklisted should be correct"); + is(addonData.isCompatible, addon.isCompatible, "isCompatible should be correct"); + } + aCallback(); + }); +} + +function isLoading() { + var loading = gManagerWindow.document.getElementById("discover-view").selectedPanel == + gManagerWindow.document.getElementById("discover-loading"); + if (loading) { + is_element_visible(gManagerWindow.document.querySelector("#discover-loading .loading"), + "Loading message should be visible when its panel is the selected panel"); + } + return loading; +} + +function isError() { + return gManagerWindow.document.getElementById("discover-view").selectedPanel == + gManagerWindow.document.getElementById("discover-error"); +} + +function clickLink(aId, aCallback) { + var browser = gManagerWindow.document.getElementById("discover-browser"); + browser.addProgressListener(gProgressListener); + + gLoadCompleteCallback = function() { + browser.removeProgressListener(gProgressListener); + aCallback(); + }; + + var link = browser.contentDocument.getElementById(aId); + EventUtils.sendMouseEvent({type: "click"}, link); + + executeSoon(function() { + ok(isLoading(), "Clicking a link should show the loading pane"); + }); +} + +// Tests that switching to the discovery view displays the right url +add_test(function() { + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + gCategoryUtilities.openType("discover", function() { + var browser = gManagerWindow.document.getElementById("discover-browser"); + is(getURL(browser), MAIN_URL, "Should have loaded the right url"); + + testHash(browser, [true, true, true], function() { + close_manager(gManagerWindow, run_next_test); + }); + }); + + ok(isLoading(), "Should be loading at first"); + }); +}); + +// Tests that loading the add-ons manager with the discovery view as the last +// selected view displays the right url +add_test(function() { + // Hide one of the test add-ons + Services.prefs.setBoolPref("extensions.addon2@tests.mozilla.org.getAddons.cache.enabled", false); + Services.prefs.setBoolPref("extensions.addon3@tests.mozilla.org.getAddons.cache.enabled", true); + + open_manager(null, function(aWindow) { + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + is(gCategoryUtilities.selectedCategory, "discover", "Should have loaded the right view"); + + var browser = gManagerWindow.document.getElementById("discover-browser"); + is(getURL(browser), MAIN_URL, "Should have loaded the right url"); + + testHash(browser, [true, false, true], function() { + close_manager(gManagerWindow, run_next_test); + }); + }, function(aWindow) { + gManagerWindow = aWindow; + ok(isLoading(), "Should be loading at first"); + }); +}); + +// Tests that loading the add-ons manager with the discovery view as the initial +// view displays the right url +add_test(function() { + Services.prefs.clearUserPref("extensions.addon2@tests.mozilla.org.getAddons.cache.enabled"); + Services.prefs.setBoolPref("extensions.addon3@tests.mozilla.org.getAddons.cache.enabled", false); + + open_manager(null, function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + gCategoryUtilities.openType("extension", function() { + close_manager(gManagerWindow, function() { + open_manager("addons://discover/", function(aWindow) { + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + is(gCategoryUtilities.selectedCategory, "discover", "Should have loaded the right view"); + + var browser = gManagerWindow.document.getElementById("discover-browser"); + is(getURL(browser), MAIN_URL, "Should have loaded the right url"); + + testHash(browser, [true, true, false], function() { + Services.prefs.clearUserPref("extensions.addon3@tests.mozilla.org.getAddons.cache.enabled"); + close_manager(gManagerWindow, run_next_test); + }); + }, function(aWindow) { + gManagerWindow = aWindow; + ok(isLoading(), "Should be loading at first"); + }); + }); + }); + }); +}); + +// Tests that switching to the discovery view displays the right url +add_test(function() { + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, false); + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + gCategoryUtilities.openType("discover", function() { + var browser = gManagerWindow.document.getElementById("discover-browser"); + is(getURL(browser), MAIN_URL, "Should have loaded the right url"); + + is(getHash(browser), null, "Hash should not have been passed"); + close_manager(gManagerWindow, run_next_test); + }); + }); +}); + +// Tests that loading the add-ons manager with the discovery view as the last +// selected view displays the right url +add_test(function() { + open_manager(null, function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + is(gCategoryUtilities.selectedCategory, "discover", "Should have loaded the right view"); + + var browser = gManagerWindow.document.getElementById("discover-browser"); + is(getURL(browser), MAIN_URL, "Should have loaded the right url"); + + is(getHash(browser), null, "Hash should not have been passed"); + close_manager(gManagerWindow, run_next_test); + }); +}); + +// Tests that loading the add-ons manager with the discovery view as the initial +// view displays the right url +add_test(function() { + open_manager(null, function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + gCategoryUtilities.openType("extension", function() { + close_manager(gManagerWindow, function() { + open_manager("addons://discover/", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + is(gCategoryUtilities.selectedCategory, "discover", "Should have loaded the right view"); + + var browser = gManagerWindow.document.getElementById("discover-browser"); + is(getURL(browser), MAIN_URL, "Should have loaded the right url"); + + is(getHash(browser), null, "Hash should not have been passed"); + close_manager(gManagerWindow, run_next_test); + }); + }); + }); + }); +}); + +// Tests that navigating to an insecure page fails +add_test(function() { + open_manager("addons://discover/", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + var browser = gManagerWindow.document.getElementById("discover-browser"); + is(getURL(browser), MAIN_URL, "Should have loaded the right url"); + + clickLink("link-http", function() { + ok(isError(), "Should have shown the error page"); + + gCategoryUtilities.openType("extension", function() { + gCategoryUtilities.openType("discover", function() { + is(getURL(browser), MAIN_URL, "Should have loaded the right url"); + + close_manager(gManagerWindow, run_next_test); + }); + ok(isLoading(), "Should start loading again"); + }); + }); + }); +}); + +// Tests that navigating to a different domain fails +add_test(function() { + open_manager("addons://discover/", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + var browser = gManagerWindow.document.getElementById("discover-browser"); + is(getURL(browser), MAIN_URL, "Should have loaded the right url"); + + clickLink("link-domain", function() { + ok(isError(), "Should have shown the error page"); + + gCategoryUtilities.openType("extension", function() { + gCategoryUtilities.openType("discover", function() { + is(getURL(browser), MAIN_URL, "Should have loaded the right url"); + + close_manager(gManagerWindow, run_next_test); + }); + ok(isLoading(), "Should start loading again"); + }); + }); + }); +}); + +// Tests that navigating to a missing page fails +add_test(function() { + open_manager("addons://discover/", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + var browser = gManagerWindow.document.getElementById("discover-browser"); + is(getURL(browser), MAIN_URL, "Should have loaded the right url"); + + clickLink("link-bad", function() { + ok(isError(), "Should have shown the error page"); + + gCategoryUtilities.openType("extension", function() { + gCategoryUtilities.openType("discover", function() { + is(getURL(browser), MAIN_URL, "Should have loaded the right url"); + + close_manager(gManagerWindow, run_next_test); + }); + ok(isLoading(), "Should start loading again"); + }); + }); + }); +}); + +// Tests that navigating to a page on the same domain works +add_test(function() { + open_manager("addons://discover/", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + var browser = gManagerWindow.document.getElementById("discover-browser"); + is(getURL(browser), MAIN_URL, "Should have loaded the right url"); + + clickLink("link-good", function() { + is(getURL(browser), "https://example.com/" + RELATIVE_DIR + "releaseNotes.xhtml", "Should have loaded the right url"); + + gCategoryUtilities.openType("extension", function() { + gCategoryUtilities.openType("discover", function() { + is(getURL(browser), MAIN_URL, "Should have loaded the right url"); + + close_manager(gManagerWindow, run_next_test); + }); + }); + }); + }); +}); + +// Tests repeated navigation to the same page followed by a navigation to a +// different domain +add_test(function() { + open_manager("addons://discover/", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + var browser = gManagerWindow.document.getElementById("discover-browser"); + is(getURL(browser), MAIN_URL, "Should have loaded the right url"); + + var count = 10; + function clickAgain(aCallback) { + if (count-- == 0) + aCallback(); + else + clickLink("link-normal", clickAgain.bind(null, aCallback)); + } + + clickAgain(function() { + is(getURL(browser), MAIN_URL, "Should have loaded the right url"); + + clickLink("link-domain", function() { + ok(isError(), "Should have shown the error page"); + + gCategoryUtilities.openType("extension", function() { + gCategoryUtilities.openType("discover", function() { + is(getURL(browser), MAIN_URL, "Should have loaded the right url"); + + close_manager(gManagerWindow, run_next_test); + }); + ok(isLoading(), "Should start loading again"); + }); + }); + }); + }); +}); + +// Loading an insecure main page should work if that is what the prefs say, should +// also be able to navigate to a https page and back again +add_test(function() { + Services.prefs.setCharPref(PREF_DISCOVERURL, TESTROOT + "discovery.html"); + + open_manager("addons://discover/", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + var browser = gManagerWindow.document.getElementById("discover-browser"); + is(getURL(browser), TESTROOT + "discovery.html", "Should have loaded the right url"); + + clickLink("link-normal", function() { + is(getURL(browser), MAIN_URL, "Should have loaded the right url"); + + clickLink("link-http", function() { + is(getURL(browser), TESTROOT + "discovery.html", "Should have loaded the right url"); + + close_manager(gManagerWindow, run_next_test); + }); + }); + }); +}); + +// Stopping the initial load should display the error page and then correctly +// reload when switching away and back again +add_test(function() { + Services.prefs.setCharPref(PREF_DISCOVERURL, MAIN_URL); + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + var browser = gManagerWindow.document.getElementById("discover-browser"); + + EventUtils.synthesizeMouse(gCategoryUtilities.get("discover"), 2, 2, { }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + ok(isError(), "Should have shown the error page"); + + gCategoryUtilities.openType("extension", function() { + EventUtils.synthesizeMouse(gCategoryUtilities.get("discover"), 2, 2, { }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + ok(isError(), "Should have shown the error page"); + + gCategoryUtilities.openType("extension", function() { + gCategoryUtilities.openType("discover", function() { + is(getURL(browser), MAIN_URL, "Should have loaded the right url"); + + close_manager(gManagerWindow, run_next_test); + }); + }); + }); + + ok(isLoading(), "Should be loading"); + // This will stop the real page load + browser.stop(); + }); + }); + + ok(isLoading(), "Should be loading"); + // This will actually stop the about:blank load + browser.stop(); + }); +}); + +// Test for Bug 703929 - Loading the discover view from a chrome XUL file fails when +// the add-on manager is reopened. +add_test(function() { + const url = "chrome://mochitests/content/" + RELATIVE_DIR + "addon_about.xul"; + Services.prefs.setCharPref(PREF_DISCOVERURL, url); + + open_manager("addons://discover/", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + var browser = gManagerWindow.document.getElementById("discover-browser"); + is(getURL(browser), url, "Loading a chrome XUL file should work"); + + restart_manager(gManagerWindow, "addons://discover/", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + var browser = gManagerWindow.document.getElementById("discover-browser"); + is(getURL(browser), url, "Should be able to load the chrome XUL file a second time"); + + close_manager(gManagerWindow, run_next_test); + }); + }); +}); + +// Bug 711693 - Send the compatibility mode when loading the Discovery pane +add_test(function() { + info("Test '%COMPATIBILITY_MODE%' in the URL is correctly replaced by 'normal'"); + Services.prefs.setCharPref(PREF_DISCOVERURL, MAIN_URL + "?mode=%COMPATIBILITY_MODE%"); + Services.prefs.setBoolPref(PREF_STRICT_COMPAT, false); + + open_manager("addons://discover/", function(aWindow) { + gManagerWindow = aWindow; + var browser = gManagerWindow.document.getElementById("discover-browser"); + is(getURL(browser), MAIN_URL + "?mode=normal", "Should have loaded the right url"); + close_manager(gManagerWindow, run_next_test); + }); +}); + +add_test(function() { + info("Test '%COMPATIBILITY_MODE%' in the URL is correctly replaced by 'strict'"); + Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true); + + open_manager("addons://discover/", function(aWindow) { + gManagerWindow = aWindow; + var browser = gManagerWindow.document.getElementById("discover-browser"); + is(getURL(browser), MAIN_URL + "?mode=strict", "Should have loaded the right url"); + close_manager(gManagerWindow, run_next_test); + }); +}); + +add_test(function() { + info("Test '%COMPATIBILITY_MODE%' in the URL is correctly replaced by 'ignore'"); + Services.prefs.setBoolPref(PREF_CHECK_COMPATIBILITY, false); + + open_manager("addons://discover/", function(aWindow) { + gManagerWindow = aWindow; + var browser = gManagerWindow.document.getElementById("discover-browser"); + is(getURL(browser), MAIN_URL + "?mode=ignore", "Should have loaded the right url"); + close_manager(gManagerWindow, run_next_test); + }); +}); + +// Test for Bug 601442 - extensions.getAddons.showPane need to be update +// for the new addon manager. +function bug_601442_test_elements(visible) { + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + if(visible) + ok(gCategoryUtilities.isTypeVisible("discover"), "Discover category should be visible"); + else + ok(!gCategoryUtilities.isTypeVisible("discover"), "Discover category should not be visible"); + + gManagerWindow.loadView("addons://list/dictionary"); + wait_for_view_load(gManagerWindow, function(aManager) { + var button = aManager.document.getElementById("discover-button-install"); + if(visible) + ok(!is_hidden(button), "Discover button should be visible!"); + else + ok(is_hidden(button), "Discover button should not be visible!"); + + close_manager(gManagerWindow, run_next_test); + }); + }); +} + +add_test(function() { + Services.prefs.setBoolPref(PREF_DISCOVER_ENABLED, false); + Services.prefs.setBoolPref(PREF_XPI_ENABLED, true); + bug_601442_test_elements(false); +}); +add_test(function() { + Services.prefs.setBoolPref(PREF_DISCOVER_ENABLED, true); + Services.prefs.setBoolPref(PREF_XPI_ENABLED, false); + bug_601442_test_elements(false); +}); +add_test(function() { + Services.prefs.setBoolPref(PREF_DISCOVER_ENABLED, false); + Services.prefs.setBoolPref(PREF_XPI_ENABLED, false); + bug_601442_test_elements(false); +}); +add_test(function() { + Services.prefs.setBoolPref(PREF_DISCOVER_ENABLED, true); + Services.prefs.setBoolPref(PREF_XPI_ENABLED, true); + bug_601442_test_elements(true); +}); + +// Test for Bug 1132971 - if extensions.getAddons.showPane is false, +// the extensions pane should show by default +add_test(function() { + Services.prefs.clearUserPref(PREF_UI_LASTCATEGORY); + Services.prefs.setBoolPref(PREF_DISCOVER_ENABLED, false); + + open_manager(null, function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + is(gCategoryUtilities.selectedCategory, "extension", "Should be showing the extension view"); + close_manager(gManagerWindow, run_next_test); + Services.prefs.clearUserPref(PREF_DISCOVER_ENABLED); + }); +});
\ No newline at end of file diff --git a/toolkit/mozapps/extensions/test/browser/browser_discovery_install.js b/toolkit/mozapps/extensions/test/browser/browser_discovery_install.js new file mode 100644 index 000000000..bd7d194f2 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_discovery_install.js @@ -0,0 +1,130 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that the discovery view can install add-ons correctly + +const MAIN_URL = "https://test1.example.com/" + RELATIVE_DIR + "discovery_install.html"; +const GOOD_FRAMED_URL = "https://test1.example.com/" + RELATIVE_DIR + "discovery_frame.html"; +const BAD_FRAMED_URL = "https://test2.example.com/" + RELATIVE_DIR + "discovery_frame.html"; + +// Temporarily enable caching +Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); +// Allow SSL from non-built-in certs +Services.prefs.setBoolPref("extensions.install.requireBuiltInCerts", false); +// Allow installs from the test site +Services.perms.add(NetUtil.newURI("https://test1.example.com/"), "install", + Ci.nsIPermissionManager.ALLOW_ACTION); +Services.perms.add(NetUtil.newURI("https://test2.example.com/"), "install", + Ci.nsIPermissionManager.ALLOW_ACTION); + +registerCleanupFunction(() => { + Services.perms.remove("test1.example.com", "install"); + Services.perms.remove("test2.example.com", "install"); +}); + +function clickLink(frameLoader, id) { + let link = frameLoader.contentDocument.getElementById(id); + EventUtils.sendMouseEvent({type: "click"}, link); +} + +function waitForInstall() { + return new Promise(resolve => { + wait_for_window_open((window) => { + is(window.location, "chrome://mozapps/content/xpinstall/xpinstallConfirm.xul", + "Should have seen the install window"); + window.document.documentElement.cancelDialog(); + resolve(); + }); + }); +} + +function waitForFail() { + return new Promise(resolve => { + let listener = (subject, topic, data) => { + Services.obs.removeObserver(listener, topic); + resolve(); + } + Services.obs.addObserver(listener, "addon-install-origin-blocked", false); + }); +} + +// Tests that navigating to an XPI attempts to install correctly +add_task(function* test_install_direct() { + Services.prefs.setCharPref(PREF_DISCOVERURL, MAIN_URL); + + let managerWindow = yield open_manager("addons://discover/"); + let browser = managerWindow.document.getElementById("discover-browser"); + + clickLink(browser, "install-direct"); + yield waitForInstall(); + + yield close_manager(managerWindow); +}); + +// Tests that installing via JS works correctly +add_task(function* test_install_js() { + Services.prefs.setCharPref(PREF_DISCOVERURL, MAIN_URL); + + let managerWindow = yield open_manager("addons://discover/"); + let browser = managerWindow.document.getElementById("discover-browser"); + + clickLink(browser, "install-js"); + yield waitForInstall(); + + yield close_manager(managerWindow); +}); + +// Installing from an inner-frame of the same origin should work +add_task(function* test_install_inner_direct() { + Services.prefs.setCharPref(PREF_DISCOVERURL, GOOD_FRAMED_URL); + + let managerWindow = yield open_manager("addons://discover/"); + let browser = managerWindow.document.getElementById("discover-browser"); + let frame = browser.contentDocument.getElementById("frame"); + + clickLink(frame, "install-direct"); + yield waitForInstall(); + + yield close_manager(managerWindow); +}); + +add_task(function* test_install_inner_js() { + Services.prefs.setCharPref(PREF_DISCOVERURL, GOOD_FRAMED_URL); + + let managerWindow = yield open_manager("addons://discover/"); + let browser = managerWindow.document.getElementById("discover-browser"); + let frame = browser.contentDocument.getElementById("frame"); + + clickLink(frame, "install-js"); + yield waitForInstall(); + + yield close_manager(managerWindow); +}); + +// Installing from an inner-frame of a different origin should fail +add_task(function* test_install_xorigin_direct() { + Services.prefs.setCharPref(PREF_DISCOVERURL, BAD_FRAMED_URL); + + let managerWindow = yield open_manager("addons://discover/"); + let browser = managerWindow.document.getElementById("discover-browser"); + let frame = browser.contentDocument.getElementById("frame"); + + clickLink(frame, "install-direct"); + yield waitForFail(); + + yield close_manager(managerWindow); +}); + +add_task(function* test_install_xorigin_js() { + Services.prefs.setCharPref(PREF_DISCOVERURL, BAD_FRAMED_URL); + + let managerWindow = yield open_manager("addons://discover/"); + let browser = managerWindow.document.getElementById("discover-browser"); + let frame = browser.contentDocument.getElementById("frame"); + + clickLink(frame, "install-js"); + yield waitForFail(); + + yield close_manager(managerWindow); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_dragdrop.js b/toolkit/mozapps/extensions/test/browser/browser_dragdrop.js new file mode 100644 index 000000000..1df288323 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_dragdrop.js @@ -0,0 +1,234 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This tests simulated drag and drop of files into the add-ons manager. +// We test with the add-ons manager in its own tab if in Firefox otherwise +// in its own window. +// Tests are only simulations of the drag and drop events, we cannot really do +// this automatically. + +// Instead of loading ChromeUtils.js into the test scope in browser-test.js for all tests, +// we only need ChromeUtils.js for a few files which is why we are using loadSubScript. +var gManagerWindow; +var ChromeUtils = {}; +this._scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"]. + getService(Ci.mozIJSSubScriptLoader); +this._scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/ChromeUtils.js", ChromeUtils); + +// This listens for the next opened window and checks it is of the right url. +// opencallback is called when the new window is fully loaded +// closecallback is called when the window is closed +function WindowOpenListener(url, opencallback, closecallback) { + this.url = url; + this.opencallback = opencallback; + this.closecallback = closecallback; + + var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] + .getService(Components.interfaces.nsIWindowMediator); + wm.addListener(this); +} + +WindowOpenListener.prototype = { + url: null, + opencallback: null, + closecallback: null, + window: null, + domwindow: null, + + handleEvent: function(event) { + is(this.domwindow.document.location.href, this.url, "Should have opened the correct window"); + + this.domwindow.removeEventListener("load", this, false); + // Allow any other load handlers to execute + var self = this; + executeSoon(function() { self.opencallback(self.domwindow); } ); + }, + + onWindowTitleChange: function(window, title) { + }, + + onOpenWindow: function(window) { + if (this.window) + return; + + this.window = window; + this.domwindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIDOMWindow); + this.domwindow.addEventListener("load", this, false); + }, + + onCloseWindow: function(window) { + if (this.window != window) + return; + + var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] + .getService(Components.interfaces.nsIWindowMediator); + wm.removeListener(this); + this.opencallback = null; + this.window = null; + this.domwindow = null; + + // Let the window close complete + executeSoon(this.closecallback); + this.closecallback = null; + } +}; + +var gSawInstallNotification = false; +var gInstallNotificationObserver = { + observe: function(aSubject, aTopic, aData) { + var installInfo = aSubject.QueryInterface(Ci.amIWebInstallInfo); + if (gTestInWindow) + is(installInfo.browser, null, "Notification should have a null browser"); + else + isnot(installInfo.browser, null, "Notification should have non-null browser"); + gSawInstallNotification = true; + Services.obs.removeObserver(this, "addon-install-started"); + } +}; + + +function test() { + waitForExplicitFinish(); + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, function() { + finish(); + }); +} + +function test_confirmation(aWindow, aExpectedURLs) { + var list = aWindow.document.getElementById("itemList"); + is(list.childNodes.length, aExpectedURLs.length, "Should be the right number of installs"); + + for (let url of aExpectedURLs) { + let found = false; + for (let node of list.children) { + if (node.url == url) { + found = true; + break; + } + } + ok(found, "Should have seen " + url + " in the list"); + } + + aWindow.document.documentElement.cancelDialog(); +} + +// Simulates dropping a URL onto the manager +add_test(function() { + var url = TESTROOT + "addons/browser_dragdrop1.xpi"; + + Services.obs.addObserver(gInstallNotificationObserver, + "addon-install-started", false); + + new WindowOpenListener(INSTALL_URI, function(aWindow) { + test_confirmation(aWindow, [url]); + }, function() { + is(gSawInstallNotification, true, "Should have seen addon-install-started notification."); + run_next_test(); + }); + + var viewContainer = gManagerWindow.document.getElementById("view-port"); + var effect = ChromeUtils.synthesizeDrop(viewContainer, viewContainer, + [[{type: "text/x-moz-url", data: url}]], + "copy", gManagerWindow); + is(effect, "copy", "Drag should be accepted"); +}); + +// Simulates dropping a file onto the manager +add_test(function() { + var fileurl = get_addon_file_url("browser_dragdrop1.xpi"); + + Services.obs.addObserver(gInstallNotificationObserver, + "addon-install-started", false); + + new WindowOpenListener(INSTALL_URI, function(aWindow) { + test_confirmation(aWindow, [fileurl.spec]); + }, function() { + is(gSawInstallNotification, true, "Should have seen addon-install-started notification."); + run_next_test(); + }); + + var viewContainer = gManagerWindow.document.getElementById("view-port"); + var effect = ChromeUtils.synthesizeDrop(viewContainer, viewContainer, + [[{type: "application/x-moz-file", data: fileurl.file}]], + "copy", gManagerWindow); + is(effect, "copy", "Drag should be accepted"); +}); + +// Simulates dropping two urls onto the manager +add_test(function() { + var url1 = TESTROOT + "addons/browser_dragdrop1.xpi"; + var url2 = TESTROOT2 + "addons/browser_dragdrop2.xpi"; + + Services.obs.addObserver(gInstallNotificationObserver, + "addon-install-started", false); + + new WindowOpenListener(INSTALL_URI, function(aWindow) { + test_confirmation(aWindow, [url1, url2]); + }, function() { + is(gSawInstallNotification, true, "Should have seen addon-install-started notification."); + run_next_test(); + }); + + var viewContainer = gManagerWindow.document.getElementById("view-port"); + var effect = ChromeUtils.synthesizeDrop(viewContainer, viewContainer, + [[{type: "text/x-moz-url", data: url1}], + [{type: "text/x-moz-url", data: url2}]], + "copy", gManagerWindow); + is(effect, "copy", "Drag should be accepted"); +}); + +// Simulates dropping two files onto the manager +add_test(function() { + var fileurl1 = get_addon_file_url("browser_dragdrop1.xpi"); + var fileurl2 = get_addon_file_url("browser_dragdrop2.xpi"); + + Services.obs.addObserver(gInstallNotificationObserver, + "addon-install-started", false); + + new WindowOpenListener(INSTALL_URI, function(aWindow) { + test_confirmation(aWindow, [fileurl1.spec, fileurl2.spec]); + }, function() { + is(gSawInstallNotification, true, "Should have seen addon-install-started notification."); + run_next_test(); + }); + + var viewContainer = gManagerWindow.document.getElementById("view-port"); + var effect = ChromeUtils.synthesizeDrop(viewContainer, viewContainer, + [[{type: "application/x-moz-file", data: fileurl1.file}], + [{type: "application/x-moz-file", data: fileurl2.file}]], + "copy", gManagerWindow); + is(effect, "copy", "Drag should be accepted"); +}); + +// Simulates dropping a file and a url onto the manager (weird, but should still work) +add_test(function() { + var url = TESTROOT + "addons/browser_dragdrop1.xpi"; + var fileurl = get_addon_file_url("browser_dragdrop2.xpi"); + + Services.obs.addObserver(gInstallNotificationObserver, + "addon-install-started", false); + + new WindowOpenListener(INSTALL_URI, function(aWindow) { + test_confirmation(aWindow, [url, fileurl.spec]); + }, function() { + is(gSawInstallNotification, true, "Should have seen addon-install-started notification."); + run_next_test(); + }); + + var viewContainer = gManagerWindow.document.getElementById("view-port"); + var effect = ChromeUtils.synthesizeDrop(viewContainer, viewContainer, + [[{type: "text/x-moz-url", data: url}], + [{type: "application/x-moz-file", data: fileurl.file}]], + "copy", gManagerWindow); + is(effect, "copy", "Drag should be accepted"); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_eula.js b/toolkit/mozapps/extensions/test/browser/browser_eula.js new file mode 100644 index 000000000..befe9f1f2 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_eula.js @@ -0,0 +1,85 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that the eula is shown correctly for search results + +var gManagerWindow; +var gCategoryUtilities; + +var gApp = document.getElementById("bundle_brand").getString("brandShortName"); +var gSearchCount = 0; + +function test() { + requestLongerTimeout(2); + waitForExplicitFinish(); + + // Turn on searching for this test + Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15); + Services.prefs.setCharPref("extensions.getAddons.search.url", TESTROOT + "browser_eula.xml"); + + open_manager(null, function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, finish); +} + +function get_node(parent, anonid) { + return parent.ownerDocument.getAnonymousElementByAttribute(parent, "anonid", anonid); +} + +function installSearchResult(aCallback) { + var searchBox = gManagerWindow.document.getElementById("header-search"); + // Search for something different each time + searchBox.value = "foo" + gSearchCount; + gSearchCount++; + + EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow); + EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + let remote = gManagerWindow.document.getElementById("search-filter-remote") + EventUtils.synthesizeMouseAtCenter(remote, { }, gManagerWindow); + + let item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); + ok(!!item, "Should see the search result in the list"); + + let status = get_node(item, "install-status"); + EventUtils.synthesizeMouseAtCenter(get_node(status, "install-remote-btn"), {}, gManagerWindow); + + item.mInstall.addListener({ + onInstallEnded: function() { + executeSoon(aCallback); + } + }); + }); +} + +// Install an add-on through the search page, accept the EULA and then undo it +add_test(function() { + // Accept the EULA when it appears + let sawEULA = false; + wait_for_window_open(function(aWindow) { + sawEULA = true; + is(aWindow.location.href, "chrome://mozapps/content/extensions/eula.xul", "Window opened should be correct"); + is(aWindow.document.getElementById("eula").value, "This is the EULA for this add-on", "EULA should be correct"); + + aWindow.document.documentElement.acceptDialog(); + }); + + installSearchResult(function() { + ok(sawEULA, "Should have seen the EULA"); + + AddonManager.getAllInstalls(function(aInstalls) { + is(aInstalls.length, 1, "Should be one pending install"); + aInstalls[0].cancel(); + + run_next_test(); + }); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_eula.xml b/toolkit/mozapps/extensions/test/browser/browser_eula.xml new file mode 100644 index 000000000..87b5997cf --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_eula.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8" ?> +<searchresults total_results="1"> + <addon> + <name>Install Tests</name> + <type id='1'>Extension</type> + <guid>addon1@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://example.com/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <summary>Test add-on</summary> + <description>Test add-on</description> + <eula>This is the EULA for this add-on</eula> + <compatible_applications> + <application> + <name>Firefox</name> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + <application> + <name>SeaMonkey</name> + <appID>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + </compatible_applications> + <compatible_os>ALL</compatible_os> + <install size="2">http://example.com/browser/toolkit/mozapps/extensions/test/browser/addons/browser_install1_2.xpi</install> + </addon> +</searchresults> diff --git a/toolkit/mozapps/extensions/test/browser/browser_experiments.js b/toolkit/mozapps/extensions/test/browser/browser_experiments.js new file mode 100644 index 000000000..72d0ca83e --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_experiments.js @@ -0,0 +1,645 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +Components.utils.import("resource://gre/modules/Promise.jsm", this); + +let {AddonTestUtils} = Components.utils.import("resource://testing-common/AddonManagerTesting.jsm", {}); +let {HttpServer} = Components.utils.import("resource://testing-common/httpd.js", {}); + +let gManagerWindow; +let gCategoryUtilities; +let gExperiments; +let gHttpServer; + +let gSavedManifestURI; +let gIsEnUsLocale; + +const SEC_IN_ONE_DAY = 24 * 60 * 60; +const MS_IN_ONE_DAY = SEC_IN_ONE_DAY * 1000; + +function getExperimentAddons() { + let deferred = Promise.defer(); + AddonManager.getAddonsByTypes(["experiment"], (addons) => { + deferred.resolve(addons); + }); + return deferred.promise; +} + +function getInstallItem() { + let doc = gManagerWindow.document; + let view = doc.getElementById("view-port").selectedPanel; + let list = doc.getElementById("addon-list"); + + let node = list.firstChild; + while (node) { + if (node.getAttribute("status") == "installing") { + return node; + } + node = node.nextSibling; + } + + return null; +} + +function patchPolicy(policy, data) { + for (let key of Object.keys(data)) { + Object.defineProperty(policy, key, { + value: data[key], + writable: true, + }); + } +} + +function defineNow(policy, time) { + patchPolicy(policy, { now: () => new Date(time) }); +} + +function openDetailsView(aId) { + let item = get_addon_element(gManagerWindow, aId); + Assert.ok(item, "Should have got add-on element."); + is_element_visible(item, "Add-on element should be visible."); + + EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow); + EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow); + + let deferred = Promise.defer(); + wait_for_view_load(gManagerWindow, deferred.resolve); + return deferred.promise; +} + +function clickRemoveButton(addonElement) { + let btn = gManagerWindow.document.getAnonymousElementByAttribute(addonElement, "anonid", "remove-btn"); + if (!btn) { + return Promise.reject(); + } + + EventUtils.synthesizeMouseAtCenter(btn, { clickCount: 1 }, gManagerWindow); + let deferred = Promise.defer(); + setTimeout(deferred.resolve, 0); + return deferred; +} + +function clickUndoButton(addonElement) { + let btn = gManagerWindow.document.getAnonymousElementByAttribute(addonElement, "anonid", "undo-btn"); + if (!btn) { + return Promise.reject(); + } + + EventUtils.synthesizeMouseAtCenter(btn, { clickCount: 1 }, gManagerWindow); + let deferred = Promise.defer(); + setTimeout(deferred.resolve, 0); + return deferred; +} + +add_task(function* initializeState() { + gManagerWindow = yield open_manager(); + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + registerCleanupFunction(() => { + Services.prefs.clearUserPref("experiments.enabled"); + if (gHttpServer) { + gHttpServer.stop(() => {}); + if (gSavedManifestURI !== undefined) { + Services.prefs.setCharPref("experments.manifest.uri", gSavedManifestURI); + } + } + if (gExperiments) { + let tmp = {}; + Cu.import("resource:///modules/experiments/Experiments.jsm", tmp); + gExperiments._policy = new tmp.Experiments.Policy(); + } + }); + + let chrome = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIXULChromeRegistry); + gIsEnUsLocale = chrome.getSelectedLocale("global") == "en-US"; + + // The Experiments Manager will interfere with us by preventing installs + // of experiments it doesn't know about. We remove it from the equation + // because here we are only concerned with core Addon Manager operation, + // not the superset Experiments Manager has imposed. + if ("@mozilla.org/browser/experiments-service;1" in Components.classes) { + let tmp = {}; + Cu.import("resource:///modules/experiments/Experiments.jsm", tmp); + // There is a race condition between XPCOM service initialization and + // this test running. We have to initialize the instance first, then + // uninitialize it to prevent this. + gExperiments = tmp.Experiments.instance(); + yield gExperiments._mainTask; + yield gExperiments.uninit(); + } +}); + +// On an empty profile with no experiments, the experiment category +// should be hidden. +add_task(function* testInitialState() { + Assert.ok(gCategoryUtilities.get("experiment", false), "Experiment tab is defined."); + Assert.ok(!gCategoryUtilities.isTypeVisible("experiment"), "Experiment tab hidden by default."); +}); + +add_task(function* testExperimentInfoNotVisible() { + yield gCategoryUtilities.openType("extension"); + let el = gManagerWindow.document.getElementsByClassName("experiment-info-container")[0]; + is_element_hidden(el, "Experiment info not visible on other types."); +}); + +// If we have an active experiment, we should see the experiments tab +// and that tab should have some messages. +add_task(function* testActiveExperiment() { + let addon = yield install_addon("addons/browser_experiment1.xpi"); + + Assert.ok(addon.userDisabled, "Add-on is disabled upon initial install."); + Assert.equal(addon.isActive, false, "Add-on is not active."); + + Assert.ok(gCategoryUtilities.isTypeVisible("experiment"), "Experiment tab visible."); + + yield gCategoryUtilities.openType("experiment"); + let el = gManagerWindow.document.getElementsByClassName("experiment-info-container")[0]; + is_element_visible(el, "Experiment info is visible on experiment tab."); +}); + +add_task(function* testExperimentLearnMore() { + // Actual URL is irrelevant. + Services.prefs.setCharPref("toolkit.telemetry.infoURL", + "http://mochi.test:8888/server.js"); + + yield gCategoryUtilities.openType("experiment"); + let btn = gManagerWindow.document.getElementById("experiments-learn-more"); + + if (!gUseInContentUI) { + is_element_hidden(btn, "Learn more button hidden if not using in-content UI."); + Services.prefs.clearUserPref("toolkit.telemetry.infoURL"); + + return; + } + + is_element_visible(btn, "Learn more button visible."); + + let deferred = Promise.defer(); + window.addEventListener("DOMContentLoaded", function onLoad(event) { + info("Telemetry privacy policy window opened."); + window.removeEventListener("DOMContentLoaded", onLoad, false); + + let browser = gBrowser.selectedBrowser; + let expected = Services.prefs.getCharPref("toolkit.telemetry.infoURL"); + Assert.equal(browser.currentURI.spec, expected, "New tab should have loaded privacy policy."); + browser.contentWindow.close(); + + Services.prefs.clearUserPref("toolkit.telemetry.infoURL"); + + deferred.resolve(); + }, false); + + info("Opening telemetry privacy policy."); + EventUtils.synthesizeMouseAtCenter(btn, {}, gManagerWindow); + + yield deferred.promise; +}); + +add_task(function* testOpenPreferences() { + yield gCategoryUtilities.openType("experiment"); + let btn = gManagerWindow.document.getElementById("experiments-change-telemetry"); + if (!gUseInContentUI) { + is_element_hidden(btn, "Change telemetry button not enabled in out of window UI."); + info("Skipping preferences open test because not using in-content UI."); + return; + } + + is_element_visible(btn, "Change telemetry button visible in in-content UI."); + + let deferred = Promise.defer(); + Services.obs.addObserver(function observer(prefWin, topic, data) { + Services.obs.removeObserver(observer, "advanced-pane-loaded"); + info("Advanced preference pane opened."); + executeSoon(function() { + // We want this test to fail if the preferences pane changes. + let el = prefWin.document.getElementById("dataChoicesPanel"); + is_element_visible(el); + + prefWin.close(); + info("Closed preferences pane."); + + deferred.resolve(); + }); + }, "advanced-pane-loaded", false); + + info("Loading preferences pane."); + EventUtils.synthesizeMouseAtCenter(btn, {}, gManagerWindow); + + yield deferred.promise; +}); + +add_task(function* testButtonPresence() { + yield gCategoryUtilities.openType("experiment"); + let item = get_addon_element(gManagerWindow, "test-experiment1@experiments.mozilla.org"); + Assert.ok(item, "Got add-on element."); + item.parentNode.ensureElementIsVisible(item); + + let el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + // Corresponds to the uninstall permission. + is_element_visible(el, "Remove button is visible."); + // Corresponds to lack of disable permission. + el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "disable-btn"); + is_element_hidden(el, "Disable button not visible."); + // Corresponds to lack of enable permission. + el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "enable-btn"); + is_element_hidden(el, "Enable button not visible."); +}); + +// Remove the add-on we've been testing with. +add_task(function* testCleanup() { + yield AddonTestUtils.uninstallAddonByID("test-experiment1@experiments.mozilla.org"); + // Verify some conditions, just in case. + let addons = yield getExperimentAddons(); + Assert.equal(addons.length, 0, "No experiment add-ons are installed."); +}); + +// The following tests should ideally live in browser/experiments/. However, +// they rely on some of the helper functions from head.js, which can't easily +// be consumed from other directories. So, they live here. + +add_task(function* testActivateExperiment() { + if (!gExperiments) { + info("Skipping experiments test because that feature isn't available."); + return; + } + + gHttpServer = new HttpServer(); + gHttpServer.start(-1); + let root = "http://localhost:" + gHttpServer.identity.primaryPort + "/"; + gHttpServer.registerPathHandler("/manifest", (request, response) => { + response.setStatusLine(null, 200, "OK"); + response.write(JSON.stringify({ + "version": 1, + "experiments": [ + { + id: "experiment-1", + xpiURL: TESTROOT + "addons/browser_experiment1.xpi", + xpiHash: "IRRELEVANT", + startTime: Date.now() / 1000 - 3600, + endTime: Date.now() / 1000 + 3600, + maxActiveSeconds: 600, + appName: [Services.appinfo.name], + channel: [gExperiments._policy.updatechannel()], + }, + ], + })); + response.processAsync(); + response.finish(); + }); + + gSavedManifestURI = Services.prefs.getCharPref("experiments.manifest.uri"); + Services.prefs.setCharPref("experiments.manifest.uri", root + "manifest"); + + // We need to remove the cache file to help ensure consistent state. + yield OS.File.remove(gExperiments._cacheFilePath); + + Services.prefs.setBoolPref("experiments.enabled", true); + + info("Initializing experiments service."); + yield gExperiments.init(); + info("Experiments service finished first run."); + + // Check conditions, just to be sure. + let experiments = yield gExperiments.getExperiments(); + Assert.equal(experiments.length, 0, "No experiments known to the service."); + + // This makes testing easier. + gExperiments._policy.ignoreHashes = true; + + info("Manually updating experiments manifest."); + yield gExperiments.updateManifest(); + info("Experiments update complete."); + + let deferred = Promise.defer(); + gHttpServer.stop(() => { + gHttpServer = null; + + info("getting experiment by ID"); + AddonManager.getAddonByID("test-experiment1@experiments.mozilla.org", (addon) => { + Assert.ok(addon, "Add-on installed via Experiments manager."); + + deferred.resolve(); + }); + }); + + yield deferred.promise; + + Assert.ok(gCategoryUtilities.isTypeVisible, "experiment", "Experiment tab visible."); + yield gCategoryUtilities.openType("experiment"); + let el = gManagerWindow.document.getElementsByClassName("experiment-info-container")[0]; + is_element_visible(el, "Experiment info is visible on experiment tab."); +}); + +add_task(function testDeactivateExperiment() { + if (!gExperiments) { + return; + } + + // Fake an empty manifest to purge data from previous manifest. + yield gExperiments._updateExperiments({ + "version": 1, + "experiments": [], + }); + + yield gExperiments.disableExperiment("testing"); + + // We should have a record of the previously-active experiment. + let experiments = yield gExperiments.getExperiments(); + Assert.equal(experiments.length, 1, "1 experiment is known."); + Assert.equal(experiments[0].active, false, "Experiment is not active."); + + // We should have a previous experiment in the add-ons manager. + let deferred = Promise.defer(); + AddonManager.getAddonsByTypes(["experiment"], (addons) => { + deferred.resolve(addons); + }); + let addons = yield deferred.promise; + Assert.equal(addons.length, 1, "1 experiment add-on known."); + Assert.ok(addons[0].appDisabled, "It is a previous experiment."); + Assert.equal(addons[0].id, "experiment-1", "Add-on ID matches expected."); + + // Verify the UI looks sane. + + Assert.ok(gCategoryUtilities.isTypeVisible("experiment"), "Experiment tab visible."); + let item = get_addon_element(gManagerWindow, "experiment-1"); + Assert.ok(item, "Got add-on element."); + Assert.ok(!item.active, "Element should not be active."); + item.parentNode.ensureElementIsVisible(item); + + // User control buttons should not be present because previous experiments + // should have no permissions. + let el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + is_element_hidden(el, "Remove button is not visible."); + el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "disable-btn"); + is_element_hidden(el, "Disable button is not visible."); + el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "enable-btn"); + is_element_hidden(el, "Enable button is not visible."); + el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "preferences-btn"); + is_element_hidden(el, "Preferences button is not visible."); +}); + +add_task(function testActivateRealExperiments() { + if (!gExperiments) { + info("Skipping experiments test because that feature isn't available."); + return; + } + + yield gExperiments._updateExperiments({ + "version": 1, + "experiments": [ + { + id: "experiment-2", + xpiURL: TESTROOT + "addons/browser_experiment1.xpi", + xpiHash: "IRRELEVANT", + startTime: Date.now() / 1000 - 3600, + endTime: Date.now() / 1000 + 3600, + maxActiveSeconds: 600, + appName: [Services.appinfo.name], + channel: [gExperiments._policy.updatechannel()], + }, + ], + }); + yield gExperiments._run(); + + // Check the active experiment. + + let item = get_addon_element(gManagerWindow, "test-experiment1@experiments.mozilla.org"); + Assert.ok(item, "Got add-on element."); + item.parentNode.ensureElementIsVisible(item); + + let el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "experiment-state"); + is_element_visible(el, "Experiment state label should be visible."); + if (gIsEnUsLocale) { + Assert.equal(el.value, "Active"); + } + + el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "experiment-time"); + is_element_visible(el, "Experiment time label should be visible."); + if (gIsEnUsLocale) { + Assert.equal(el.value, "Less than a day remaining"); + } + + el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "error-container"); + is_element_hidden(el, "error-container should be hidden."); + el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "warning-container"); + is_element_hidden(el, "warning-container should be hidden."); + el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "pending-container"); + is_element_hidden(el, "pending-container should be hidden."); + el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "version"); + is_element_hidden(el, "version should be hidden."); + el = item.ownerDocument.getAnonymousElementByAttribute(item, "class", "disabled-postfix"); + is_element_hidden(el, "disabled-postfix should be hidden."); + el = item.ownerDocument.getAnonymousElementByAttribute(item, "class", "update-postfix"); + is_element_hidden(el, "update-postfix should be hidden."); + el = item.ownerDocument.getAnonymousElementByAttribute(item, "class", "experiment-bullet"); + is_element_visible(el, "experiment-bullet should be visible."); + + // Check the previous experiment. + + item = get_addon_element(gManagerWindow, "experiment-1"); + Assert.ok(item, "Got add-on element."); + item.parentNode.ensureElementIsVisible(item); + + el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "experiment-state"); + is_element_visible(el, "Experiment state label should be visible."); + if (gIsEnUsLocale) { + Assert.equal(el.value, "Complete"); + } + + el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "experiment-time"); + is_element_visible(el, "Experiment time label should be visible."); + if (gIsEnUsLocale) { + Assert.equal(el.value, "Less than a day ago"); + } + + el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "error-container"); + is_element_hidden(el, "error-container should be hidden."); + el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "warning-container"); + is_element_hidden(el, "warning-container should be hidden."); + el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "pending-container"); + is_element_hidden(el, "pending-container should be hidden."); + el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "version"); + is_element_hidden(el, "version should be hidden."); + el = item.ownerDocument.getAnonymousElementByAttribute(item, "class", "disabled-postfix"); + is_element_hidden(el, "disabled-postfix should be hidden."); + el = item.ownerDocument.getAnonymousElementByAttribute(item, "class", "update-postfix"); + is_element_hidden(el, "update-postfix should be hidden."); + el = item.ownerDocument.getAnonymousElementByAttribute(item, "class", "experiment-bullet"); + is_element_visible(el, "experiment-bullet should be visible."); + + // Install an "older" experiment. + + yield gExperiments.disableExperiment("experiment-2"); + + let now = Date.now(); + let fakeNow = now - 5 * MS_IN_ONE_DAY; + defineNow(gExperiments._policy, fakeNow); + + yield gExperiments._updateExperiments({ + "version": 1, + "experiments": [ + { + id: "experiment-3", + xpiURL: TESTROOT + "addons/browser_experiment1.xpi", + xpiHash: "IRRELEVANT", + startTime: fakeNow / 1000 - SEC_IN_ONE_DAY, + endTime: now / 1000 + 10 * SEC_IN_ONE_DAY, + maxActiveSeconds: 100 * SEC_IN_ONE_DAY, + appName: [Services.appinfo.name], + channel: [gExperiments._policy.updatechannel()], + }, + ], + }); + yield gExperiments._run(); + + // Check the active experiment. + + item = get_addon_element(gManagerWindow, "test-experiment1@experiments.mozilla.org"); + Assert.ok(item, "Got add-on element."); + item.parentNode.ensureElementIsVisible(item); + + el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "experiment-state"); + is_element_visible(el, "Experiment state label should be visible."); + if (gIsEnUsLocale) { + Assert.equal(el.value, "Active"); + } + + el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "experiment-time"); + is_element_visible(el, "Experiment time label should be visible."); + if (gIsEnUsLocale) { + Assert.equal(el.value, "10 days remaining"); + } + + // Disable it and check it's previous experiment entry. + + yield gExperiments.disableExperiment("experiment-3"); + + item = get_addon_element(gManagerWindow, "experiment-3"); + Assert.ok(item, "Got add-on element."); + item.parentNode.ensureElementIsVisible(item); + + el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "experiment-state"); + is_element_visible(el, "Experiment state label should be visible."); + if (gIsEnUsLocale) { + Assert.equal(el.value, "Complete"); + } + + el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "experiment-time"); + is_element_visible(el, "Experiment time label should be visible."); + if (gIsEnUsLocale) { + Assert.equal(el.value, "5 days ago"); + } +}); + +add_task(function testDetailView() { + if (!gExperiments) { + info("Skipping experiments test because that feature isn't available."); + return; + } + + defineNow(gExperiments._policy, Date.now()); + yield gExperiments._updateExperiments({ + "version": 1, + "experiments": [ + { + id: "experiment-4", + xpiURL: TESTROOT + "addons/browser_experiment1.xpi", + xpiHash: "IRRELEVANT", + startTime: Date.now() / 1000 - 3600, + endTime: Date.now() / 1000 + 3600, + maxActiveSeconds: 600, + appName: [Services.appinfo.name], + channel: [gExperiments._policy.updatechannel()], + }, + ], + }); + yield gExperiments._run(); + + // Check active experiment. + + yield openDetailsView("test-experiment1@experiments.mozilla.org"); + + let el = gManagerWindow.document.getElementById("detail-experiment-state"); + is_element_visible(el, "Experiment state label should be visible."); + if (gIsEnUsLocale) { + Assert.equal(el.value, "Active"); + } + + el = gManagerWindow.document.getElementById("detail-experiment-time"); + is_element_visible(el, "Experiment time label should be visible."); + if (gIsEnUsLocale) { + Assert.equal(el.value, "Less than a day remaining"); + } + + el = gManagerWindow.document.getElementById("detail-version"); + is_element_hidden(el, "detail-version should be hidden."); + el = gManagerWindow.document.getElementById("detail-creator"); + is_element_hidden(el, "detail-creator should be hidden."); + el = gManagerWindow.document.getElementById("detail-experiment-bullet"); + is_element_visible(el, "experiment-bullet should be visible."); + + // Check previous experiment. + + yield gCategoryUtilities.openType("experiment"); + yield openDetailsView("experiment-3"); + + el = gManagerWindow.document.getElementById("detail-experiment-state"); + is_element_visible(el, "Experiment state label should be visible."); + if (gIsEnUsLocale) { + Assert.equal(el.value, "Complete"); + } + + el = gManagerWindow.document.getElementById("detail-experiment-time"); + is_element_visible(el, "Experiment time label should be visible."); + if (gIsEnUsLocale) { + Assert.equal(el.value, "5 days ago"); + } + + el = gManagerWindow.document.getElementById("detail-version"); + is_element_hidden(el, "detail-version should be hidden."); + el = gManagerWindow.document.getElementById("detail-creator"); + is_element_hidden(el, "detail-creator should be hidden."); + el = gManagerWindow.document.getElementById("detail-experiment-bullet"); + is_element_visible(el, "experiment-bullet should be visible."); +}); + +add_task(function* testRemoveAndUndo() { + if (!gExperiments) { + info("Skipping experiments test because that feature isn't available."); + return; + } + + yield gCategoryUtilities.openType("experiment"); + + let addon = get_addon_element(gManagerWindow, "test-experiment1@experiments.mozilla.org"); + Assert.ok(addon, "Got add-on element."); + + yield clickRemoveButton(addon); + addon.parentNode.ensureElementIsVisible(addon); + + let el = gManagerWindow.document.getAnonymousElementByAttribute(addon, "class", "pending"); + is_element_visible(el, "Uninstall undo information should be visible."); + + yield clickUndoButton(addon); + addon = get_addon_element(gManagerWindow, "test-experiment1@experiments.mozilla.org"); + Assert.ok(addon, "Got add-on element."); +}); + +add_task(function* testCleanup() { + if (gExperiments) { + Services.prefs.clearUserPref("experiments.enabled"); + Services.prefs.setCharPref("experiments.manifest.uri", gSavedManifestURI); + + // We perform the uninit/init cycle to purge any leftover state. + yield OS.File.remove(gExperiments._cacheFilePath); + yield gExperiments.uninit(); + yield gExperiments.init(); + } + + // Check post-conditions. + let addons = yield getExperimentAddons(); + Assert.equal(addons.length, 0, "No experiment add-ons are installed."); + + yield close_manager(gManagerWindow); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_globalinformations.js b/toolkit/mozapps/extensions/test/browser/browser_globalinformations.js new file mode 100644 index 000000000..33890d8f5 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_globalinformations.js @@ -0,0 +1,55 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Bug 656269 - Add link to Mozilla plugin check from Add-ons Manager + +const MAIN_URL = "https://example.com/" + RELATIVE_DIR + "discovery.html"; +const PREF_PLUGINCHECKURL = "plugins.update.url"; + +function test() { + waitForExplicitFinish(); + + Services.prefs.setCharPref(PREF_PLUGINCHECKURL, MAIN_URL); + registerCleanupFunction(function() { + Services.prefs.clearUserPref(PREF_PLUGINCHECKURL); + }); + + run_next_test(); +} + +function end_test() { + finish(); +} + +add_test(function() { + open_manager("addons://list/extension", function(aManager) { + info("Testing plugin check information"); + var button = aManager.document.querySelector("#list-view button.global-info-plugincheck"); + is_element_hidden(button, "Plugin Check message button should be hidden"); + + info("Changing view to plugins") + EventUtils.synthesizeMouseAtCenter(aManager.document.getElementById("category-plugin"), { }, aManager); + + wait_for_view_load(aManager, function(aManager) { + var button = aManager.document.querySelector("#list-view button.global-info-plugincheck"); + is_element_visible(button, "Plugin Check message button should be visible"); + + info("Clicking 'Plugin Check' button"); + EventUtils.synthesizeMouseAtCenter(button, { }, aManager); + gBrowser.addEventListener("load", function(event) { + if (!(event.target instanceof Document) || + event.target.location.href == "about:blank") + return; + gBrowser.removeEventListener("load", arguments.callee, true); + + is(gBrowser.currentURI.spec, Services.urlFormatter.formatURLPref("plugins.update.url"), "Plugin Check URL should match"); + + gBrowser.removeCurrentTab(); + close_manager(aManager, function() { + run_next_test(); + }); + }, true); + }); + }); +});
\ No newline at end of file diff --git a/toolkit/mozapps/extensions/test/browser/browser_globalwarnings.js b/toolkit/mozapps/extensions/test/browser/browser_globalwarnings.js new file mode 100644 index 000000000..663905a90 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_globalwarnings.js @@ -0,0 +1,63 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Bug 566194 - safe mode / security & compatibility check status are not exposed in new addon manager UI + +function test() { + waitForExplicitFinish(); + run_next_test(); +} + +function end_test() { + finish(); +} + +add_test(function() { + info("Testing compatibility checking warning"); + + info("Setting checkCompatibility to false"); + AddonManager.checkCompatibility = false; + + open_manager("addons://list/extension", function(aWindow) { + var hbox = aWindow.document.querySelector("#list-view hbox.global-warning-checkcompatibility"); + is_element_visible(hbox, "Check Compatibility warning hbox should be visible"); + var button = aWindow.document.querySelector("#list-view button.global-warning-checkcompatibility"); + is_element_visible(button, "Check Compatibility warning button should be visible"); + + info("Clicking 'Enable' button"); + EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); + is(AddonManager.checkCompatibility, true, "Check Compatibility pref should be cleared"); + is_element_hidden(hbox, "Check Compatibility warning hbox should be hidden"); + is_element_hidden(button, "Check Compatibility warning button should be hidden"); + + close_manager(aWindow, function() { + run_next_test(); + }); + }); +}); + +add_test(function() { + info("Testing update security checking warning"); + + var pref = "extensions.checkUpdateSecurity"; + info("Setting " + pref + " pref to false") + Services.prefs.setBoolPref(pref, false); + + open_manager(null, function(aWindow) { + var hbox = aWindow.document.querySelector("#list-view hbox.global-warning-updatesecurity"); + is_element_visible(hbox, "Check Update Security warning hbox should be visible"); + var button = aWindow.document.querySelector("#list-view button.global-warning-updatesecurity"); + is_element_visible(button, "Check Update Security warning button should be visible"); + + info("Clicking 'Enable' button"); + EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); + is(Services.prefs.prefHasUserValue(pref), false, "Check Update Security pref should be cleared"); + is_element_hidden(hbox, "Check Update Security warning hbox should be hidden"); + is_element_hidden(button, "Check Update Security warning button should be hidden"); + + close_manager(aWindow, function() { + run_next_test(); + }); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_gmpProvider.js b/toolkit/mozapps/extensions/test/browser/browser_gmpProvider.js new file mode 100644 index 000000000..1813df78c --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_gmpProvider.js @@ -0,0 +1,401 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +"use strict"; + +Cu.import("resource://gre/modules/Promise.jsm"); +let {AddonTestUtils} = Cu.import("resource://testing-common/AddonManagerTesting.jsm", {}); +let GMPScope = Cu.import("resource://gre/modules/addons/GMPProvider.jsm"); + +const TEST_DATE = new Date(2013, 0, 1, 12); + +let gManagerWindow; +let gCategoryUtilities; +let gIsEnUsLocale; + +let gMockAddons = []; + +for (let plugin of GMPScope.GMP_PLUGINS) { + let mockAddon = Object.freeze({ + id: plugin.id, + isValid: true, + isInstalled: false, + isEME: plugin.id.indexOf("gmp-eme-") == 0 ? true : false, + }); + gMockAddons.push(mockAddon); +} + +let gInstalledAddonId = ""; +let gInstallDeferred = null; +let gPrefs = Services.prefs; +let getKey = GMPScope.GMPPrefs.getPrefKey; + +function MockGMPInstallManager() { +} + +MockGMPInstallManager.prototype = { + checkForAddons: () => Promise.resolve(gMockAddons), + + installAddon: addon => { + gInstalledAddonId = addon.id; + gInstallDeferred.resolve(); + return Promise.resolve(); + }, +}; + +let gOptionsObserver = { + lastDisplayed: null, + observe: function(aSubject, aTopic, aData) { + if (aTopic == AddonManager.OPTIONS_NOTIFICATION_DISPLAYED) { + this.lastDisplayed = aData; + } + } +}; + +function getInstallItem() { + let doc = gManagerWindow.document; + let list = doc.getElementById("addon-list"); + + let node = list.firstChild; + while (node) { + if (node.getAttribute("status") == "installing") { + return node; + } + node = node.nextSibling; + } + + return null; +} + +function openDetailsView(aId) { + let item = get_addon_element(gManagerWindow, aId); + Assert.ok(item, "Should have got add-on element."); + is_element_visible(item, "Add-on element should be visible."); + + EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow); + EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow); + + let deferred = Promise.defer(); + wait_for_view_load(gManagerWindow, deferred.resolve); + return deferred.promise; +} + +add_task(function* initializeState() { + gPrefs.setBoolPref(GMPScope.GMPPrefs.KEY_LOGGING_DUMP, true); + gPrefs.setIntPref(GMPScope.GMPPrefs.KEY_LOGGING_LEVEL, 0); + + gManagerWindow = yield open_manager(); + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + registerCleanupFunction(Task.async(function*() { + Services.obs.removeObserver(gOptionsObserver, AddonManager.OPTIONS_NOTIFICATION_DISPLAYED); + + for (let addon of gMockAddons) { + gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_ENABLED, addon.id)); + gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_LAST_UPDATE, addon.id)); + gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_AUTOUPDATE, addon.id)); + gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, addon.id)); + gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCEVISIBLE, addon.id)); + } + gPrefs.clearUserPref(GMPScope.GMPPrefs.KEY_LOGGING_DUMP); + gPrefs.clearUserPref(GMPScope.GMPPrefs.KEY_LOGGING_LEVEL); + gPrefs.clearUserPref(GMPScope.GMPPrefs.KEY_UPDATE_LAST_CHECK); + gPrefs.clearUserPref(GMPScope.GMPPrefs.KEY_EME_ENABLED); + yield GMPScope.GMPProvider.shutdown(); + GMPScope.GMPProvider.startup(); + })); + + let chrome = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIXULChromeRegistry); + gIsEnUsLocale = chrome.getSelectedLocale("global") == "en-US"; + + Services.obs.addObserver(gOptionsObserver, AddonManager.OPTIONS_NOTIFICATION_DISPLAYED, false); + + // Start out with plugins not being installed, disabled and automatic updates + // disabled. + gPrefs.setBoolPref(GMPScope.GMPPrefs.KEY_EME_ENABLED, true); + for (let addon of gMockAddons) { + gPrefs.setBoolPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_ENABLED, addon.id), false); + gPrefs.setIntPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_LAST_UPDATE, addon.id), 0); + gPrefs.setBoolPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_AUTOUPDATE, addon.id), false); + gPrefs.setCharPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, addon.id), ""); + gPrefs.setBoolPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCEVISIBLE, addon.id), + true); + } + yield GMPScope.GMPProvider.shutdown(); + GMPScope.GMPProvider.startup(); +}); + +add_task(function* testNotInstalledDisabled() { + Assert.ok(gCategoryUtilities.isTypeVisible("plugin"), "Plugin tab visible."); + yield gCategoryUtilities.openType("plugin"); + + for (let addon of gMockAddons) { + let item = get_addon_element(gManagerWindow, addon.id); + Assert.ok(item, "Got add-on element:" + addon.id); + item.parentNode.ensureElementIsVisible(item); + is(item.getAttribute("active"), "false"); + + let el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "warning"); + is_element_hidden(el, "Warning notification is hidden."); + el = item.ownerDocument.getAnonymousElementByAttribute(item, "class", "disabled-postfix"); + is_element_visible(el, "disabled-postfix is visible."); + el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "disable-btn"); + is_element_hidden(el, "Disable button not visible."); + el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "enable-btn"); + is_element_hidden(el, "Enable button not visible."); + + let menu = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "state-menulist"); + is_element_visible(menu, "State menu should be visible."); + + let neverActivate = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "never-activate-menuitem"); + is(menu.selectedItem, neverActivate, "Plugin state should be never-activate."); + } +}); + +add_task(function* testNotInstalledDisabledDetails() { + for (let addon of gMockAddons) { + yield openDetailsView(addon.id); + let doc = gManagerWindow.document; + + let el = doc.getElementsByClassName("disabled-postfix")[0]; + is_element_visible(el, "disabled-postfix is visible."); + el = doc.getElementById("detail-findUpdates-btn"); + is_element_visible(el, "Find updates link is visible."); + el = doc.getElementById("detail-warning"); + is_element_hidden(el, "Warning notification is hidden."); + el = doc.getElementsByTagName("setting")[0]; + } +}); + +add_task(function* testNotInstalled() { + Assert.ok(gCategoryUtilities.isTypeVisible("plugin"), "Plugin tab visible."); + yield gCategoryUtilities.openType("plugin"); + + for (let addon of gMockAddons) { + gPrefs.setBoolPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_ENABLED, addon.id), true); + let item = get_addon_element(gManagerWindow, addon.id); + Assert.ok(item, "Got add-on element:" + addon.id); + item.parentNode.ensureElementIsVisible(item); + is(item.getAttribute("active"), "true"); + + let el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "warning"); + is_element_visible(el, "Warning notification is visible."); + el = item.ownerDocument.getAnonymousElementByAttribute(item, "class", "disabled-postfix"); + is_element_hidden(el, "disabled-postfix is hidden."); + el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "disable-btn"); + is_element_hidden(el, "Disable button not visible."); + el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "enable-btn"); + is_element_hidden(el, "Enable button not visible."); + + let menu = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "state-menulist"); + is_element_visible(menu, "State menu should be visible."); + + let alwaysActivate = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "always-activate-menuitem"); + is(menu.selectedItem, alwaysActivate, "Plugin state should be always-activate."); + } +}); + +add_task(function* testNotInstalledDetails() { + for (let addon of gMockAddons) { + yield openDetailsView(addon.id); + let doc = gManagerWindow.document; + + let el = doc.getElementsByClassName("disabled-postfix")[0]; + is_element_hidden(el, "disabled-postfix is hidden."); + el = doc.getElementById("detail-findUpdates-btn"); + is_element_visible(el, "Find updates link is visible."); + el = doc.getElementById("detail-warning"); + is_element_visible(el, "Warning notification is visible."); + el = doc.getElementsByTagName("setting")[0]; + } +}); + +add_task(function* testInstalled() { + for (let addon of gMockAddons) { + gPrefs.setIntPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_LAST_UPDATE, addon.id), + TEST_DATE.getTime()); + gPrefs.setBoolPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_AUTOUPDATE, addon.id), false); + gPrefs.setCharPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, addon.id), "1.2.3.4"); + + yield gCategoryUtilities.openType("plugin"); + + let item = get_addon_element(gManagerWindow, addon.id); + Assert.ok(item, "Got add-on element."); + item.parentNode.ensureElementIsVisible(item); + is(item.getAttribute("active"), "true"); + + let el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "warning"); + is_element_hidden(el, "Warning notification is hidden."); + el = item.ownerDocument.getAnonymousElementByAttribute(item, "class", "disabled-postfix"); + is_element_hidden(el, "disabled-postfix is hidden."); + el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "disable-btn"); + is_element_hidden(el, "Disable button not visible."); + el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "enable-btn"); + is_element_hidden(el, "Enable button not visible."); + + let menu = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "state-menulist"); + is_element_visible(menu, "State menu should be visible."); + + let alwaysActivate = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "always-activate-menuitem"); + is(menu.selectedItem, alwaysActivate, "Plugin state should be always-activate."); + } +}); + +add_task(function* testInstalledDetails() { + for (let addon of gMockAddons) { + yield openDetailsView(addon.id); + let doc = gManagerWindow.document; + + let el = doc.getElementsByClassName("disabled-postfix")[0]; + is_element_hidden(el, "disabled-postfix is hidden."); + el = doc.getElementById("detail-findUpdates-btn"); + is_element_visible(el, "Find updates link is visible."); + el = doc.getElementById("detail-warning"); + is_element_hidden(el, "Warning notification is hidden."); + el = doc.getElementsByTagName("setting")[0]; + + let contextMenu = doc.getElementById("addonitem-popup"); + let deferred = Promise.defer(); + let listener = () => { + contextMenu.removeEventListener("popupshown", listener, false); + deferred.resolve(); + }; + contextMenu.addEventListener("popupshown", listener, false); + el = doc.getElementsByClassName("detail-view-container")[0]; + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); + yield deferred.promise; + let menuSep = doc.getElementById("addonitem-menuseparator"); + is_element_hidden(menuSep, "Menu separator is hidden."); + contextMenu.hidePopup(); + } +}); + +add_task(function* testInstalledGlobalEmeDisabled() { + gPrefs.setBoolPref(GMPScope.GMPPrefs.KEY_EME_ENABLED, false); + for (let addon of gMockAddons) { + yield gCategoryUtilities.openType("plugin"); + + let item = get_addon_element(gManagerWindow, addon.id); + if (addon.isEME) { + Assert.ok(!item, "Couldn't get add-on element."); + } else { + Assert.ok(item, "Got add-on element."); + } + } + gPrefs.setBoolPref(GMPScope.GMPPrefs.KEY_EME_ENABLED, true); +}); + +add_task(function* testPreferencesButton() { + + let prefValues = [ + { enabled: false, version: "" }, + { enabled: false, version: "1.2.3.4" }, + { enabled: true, version: "" }, + { enabled: true, version: "1.2.3.4" }, + ]; + + for (let preferences of prefValues) { + dump("Testing preferences button with pref settings: " + + JSON.stringify(preferences) + "\n"); + for (let addon of gMockAddons) { + yield close_manager(gManagerWindow); + gManagerWindow = yield open_manager(); + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + gPrefs.setCharPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, addon.id), + preferences.version); + gPrefs.setBoolPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_ENABLED, addon.id), + preferences.enabled); + + yield gCategoryUtilities.openType("plugin"); + let doc = gManagerWindow.document; + let item = get_addon_element(gManagerWindow, addon.id); + + let button = doc.getAnonymousElementByAttribute(item, "anonid", "preferences-btn"); + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + let deferred = Promise.defer(); + wait_for_view_load(gManagerWindow, deferred.resolve); + yield deferred.promise; + + is(gOptionsObserver.lastDisplayed, addon.id); + } + } +}); + +add_task(function* testUpdateButton() { + gPrefs.clearUserPref(GMPScope.GMPPrefs.KEY_UPDATE_LAST_CHECK); + + let originalInstallManager = GMPScope.GMPInstallManager; + Object.defineProperty(GMPScope, "GMPInstallManager", { + value: MockGMPInstallManager, + writable: true, + enumerable: true, + configurable: true + }); + + for (let addon of gMockAddons) { + yield gCategoryUtilities.openType("plugin"); + let doc = gManagerWindow.document; + let item = get_addon_element(gManagerWindow, addon.id); + + gInstalledAddonId = ""; + gInstallDeferred = Promise.defer(); + + let button = doc.getAnonymousElementByAttribute(item, "anonid", "preferences-btn"); + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + let deferred = Promise.defer(); + wait_for_view_load(gManagerWindow, deferred.resolve); + yield deferred.promise; + + button = doc.getElementById("detail-findUpdates-btn"); + Assert.ok(button != null, "Got detail-findUpdates-btn"); + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + yield gInstallDeferred.promise; + + Assert.equal(gInstalledAddonId, addon.id); + } + Object.defineProperty(GMPScope, "GMPInstallManager", { + value: originalInstallManager, + writable: true, + enumerable: true, + configurable: true + }); +}); + +add_task(function* testEmeSupport() { + for (let addon of gMockAddons) { + gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCEVISIBLE, addon.id)); + } + yield GMPScope.GMPProvider.shutdown(); + GMPScope.GMPProvider.startup(); + + for (let addon of gMockAddons) { + yield gCategoryUtilities.openType("plugin"); + let doc = gManagerWindow.document; + let item = get_addon_element(gManagerWindow, addon.id); + if (addon.id == GMPScope.EME_ADOBE_ID) { + if (Services.appinfo.OS == "WINNT" && + Services.sysinfo.getPropertyAsInt32("version") >= 6) { + Assert.ok(item, "Adobe EME supported, found add-on element."); + } else { + Assert.ok(!item, + "Adobe EME not supported, couldn't find add-on element."); + } + } else { + Assert.ok(item, "Found add-on element."); + } + } + + for (let addon of gMockAddons) { + gPrefs.setBoolPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCEVISIBLE, addon.id), + true); + } + yield GMPScope.GMPProvider.shutdown(); + GMPScope.GMPProvider.startup(); + +}); + +add_task(function* test_cleanup() { + yield close_manager(gManagerWindow); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js b/toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js new file mode 100644 index 000000000..c1dd7f762 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js @@ -0,0 +1,677 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests various aspects of the details view + +var gManagerWindow; +var gCategoryUtilities; +var gProvider; + +const SETTINGS_ROWS = 9; + +var MockFilePicker = SpecialPowers.MockFilePicker; +MockFilePicker.init(window); + +var observer = { + lastDisplayed: null, + callback: null, + checkDisplayed: function(aExpected) { + is(this.lastDisplayed, aExpected, "'addon-options-displayed' notification should have fired"); + this.lastDisplayed = null; + }, + checkNotDisplayed: function() { + is(this.lastDisplayed, null, "'addon-options-displayed' notification should not have fired"); + }, + lastHidden: null, + checkHidden: function(aExpected) { + is(this.lastHidden, aExpected, "'addon-options-hidden' notification should have fired"); + this.lastHidden = null; + }, + checkNotHidden: function() { + is(this.lastHidden, null, "'addon-options-hidden' notification should not have fired"); + }, + observe: function(aSubject, aTopic, aData) { + if (aTopic == AddonManager.OPTIONS_NOTIFICATION_DISPLAYED) { + this.lastDisplayed = aData; + // Test if the binding has applied before the observers are notified. We test the second setting here, + // because the code operates on the first setting and we want to check it applies to all. + var setting = aSubject.querySelector("rows > setting[first-row] ~ setting"); + var input = gManagerWindow.document.getAnonymousElementByAttribute(setting, "class", "preferences-title"); + isnot(input, null, "XBL binding should be applied"); + + // Add some extra height to the scrolling pane to ensure that it needs to scroll when appropriate. + gManagerWindow.document.getElementById("detail-controls").style.marginBottom = "1000px"; + + if (this.callback) { + var tempCallback = this.callback; + this.callback = null; + tempCallback(); + } + } else if (aTopic == AddonManager.OPTIONS_NOTIFICATION_HIDDEN) { + this.lastHidden = aData; + } + } +}; + +function installAddon(aCallback) { + AddonManager.getInstallForURL(TESTROOT + "addons/browser_inlinesettings1.xpi", + function(aInstall) { + aInstall.addListener({ + onInstallEnded: function() { + executeSoon(aCallback); + } + }); + aInstall.install(); + }, "application/x-xpinstall"); +} + +function checkScrolling(aShouldHaveScrolled) { + var detailView = gManagerWindow.document.getElementById("detail-view"); + var boxObject = detailView.boxObject; + ok(detailView.scrollHeight > boxObject.height, "Page should require scrolling"); + if (aShouldHaveScrolled) + isnot(detailView.scrollTop, 0, "Page should have scrolled"); + else + is(detailView.scrollTop, 0, "Page should not have scrolled"); +} + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + gProvider.createAddons([{ + id: "inlinesettings2@tests.mozilla.org", + name: "Inline Settings (Regular)", + version: "1", + optionsURL: CHROMEROOT + "options.xul", + optionsType: AddonManager.OPTIONS_TYPE_INLINE, + operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_DISABLE, + },{ + id: "inlinesettings3@tests.mozilla.org", + name: "Inline Settings (More Options)", + description: "Tests for option types introduced after Mozilla 7.0", + version: "1", + optionsURL: CHROMEROOT + "more_options.xul", + optionsType: AddonManager.OPTIONS_TYPE_INLINE + },{ + id: "noninlinesettings@tests.mozilla.org", + name: "Non-Inline Settings", + version: "1", + optionsURL: CHROMEROOT + "addon_prefs.xul" + }]); + + installAddon(function () { + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + Services.obs.addObserver(observer, + AddonManager.OPTIONS_NOTIFICATION_DISPLAYED, + false); + Services.obs.addObserver(observer, + AddonManager.OPTIONS_NOTIFICATION_HIDDEN, + false); + + run_next_test(); + }); + }); +} + +function end_test() { + Services.obs.removeObserver(observer, + AddonManager.OPTIONS_NOTIFICATION_DISPLAYED); + + Services.prefs.clearUserPref("extensions.inlinesettings1.bool"); + Services.prefs.clearUserPref("extensions.inlinesettings1.boolint"); + Services.prefs.clearUserPref("extensions.inlinesettings1.integer"); + Services.prefs.clearUserPref("extensions.inlinesettings1.string"); + Services.prefs.clearUserPref("extensions.inlinesettings1.color"); + Services.prefs.clearUserPref("extensions.inlinesettings1.file"); + Services.prefs.clearUserPref("extensions.inlinesettings1.directory"); + Services.prefs.clearUserPref("extensions.inlinesettings3.radioBool"); + Services.prefs.clearUserPref("extensions.inlinesettings3.radioInt"); + Services.prefs.clearUserPref("extensions.inlinesettings3.radioString"); + Services.prefs.clearUserPref("extensions.inlinesettings3.menulist"); + + MockFilePicker.cleanup(); + + close_manager(gManagerWindow, function() { + observer.checkHidden("inlinesettings3@tests.mozilla.org"); + Services.obs.removeObserver(observer, + AddonManager.OPTIONS_NOTIFICATION_HIDDEN); + + AddonManager.getAddonByID("inlinesettings1@tests.mozilla.org", function(aAddon) { + aAddon.uninstall(); + finish(); + }); + }); +} + +// Addon with options.xul +add_test(function() { + var addon = get_addon_element(gManagerWindow, "inlinesettings1@tests.mozilla.org"); + is(addon.mAddon.optionsType, AddonManager.OPTIONS_TYPE_INLINE, "Options should be inline type"); + addon.parentNode.ensureElementIsVisible(addon); + + var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "preferences-btn"); + is_element_visible(button, "Preferences button should be visible"); + + run_next_test(); +}); + +// Addon with inline preferences as optionsURL +add_test(function() { + var addon = get_addon_element(gManagerWindow, "inlinesettings2@tests.mozilla.org"); + is(addon.mAddon.optionsType, AddonManager.OPTIONS_TYPE_INLINE, "Options should be inline type"); + addon.parentNode.ensureElementIsVisible(addon); + + var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "preferences-btn"); + is_element_visible(button, "Preferences button should be visible"); + + run_next_test(); +}); + +// Addon with non-inline preferences as optionsURL +add_test(function() { + var addon = get_addon_element(gManagerWindow, "noninlinesettings@tests.mozilla.org"); + is(addon.mAddon.optionsType, AddonManager.OPTIONS_TYPE_DIALOG, "Options should be dialog type"); + addon.parentNode.ensureElementIsVisible(addon); + + var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "preferences-btn"); + is_element_visible(button, "Preferences button should be visible"); + + run_next_test(); +}); + +// Addon with options.xul, also a test for the setting.xml bindings +add_test(function() { + var addon = get_addon_element(gManagerWindow, "inlinesettings1@tests.mozilla.org"); + addon.parentNode.ensureElementIsVisible(addon); + + var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "preferences-btn"); + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + observer.checkDisplayed("inlinesettings1@tests.mozilla.org"); + is(gManagerWindow.gViewController.currentViewId, + "addons://detail/inlinesettings1%40tests.mozilla.org/preferences", + "Current view should scroll to preferences"); + checkScrolling(true); + + var grid = gManagerWindow.document.getElementById("detail-grid"); + var settings = grid.querySelectorAll("rows > setting"); + is(settings.length, SETTINGS_ROWS, "Grid should have settings children"); + + ok(settings[0].hasAttribute("first-row"), "First visible row should have first-row attribute"); + Services.prefs.setBoolPref("extensions.inlinesettings1.bool", false); + var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[0], "anonid", "input"); + isnot(input.checked, true, "Checkbox should have initial value"); + is(input.label, "Check box label", "Checkbox should be labelled"); + EventUtils.synthesizeMouseAtCenter(input, { clickCount: 1 }, gManagerWindow); + is(input.checked, true, "Checkbox should have updated value"); + is(Services.prefs.getBoolPref("extensions.inlinesettings1.bool"), true, "Bool pref should have been updated"); + EventUtils.synthesizeMouseAtCenter(input, { clickCount: 1 }, gManagerWindow); + isnot(input.checked, true, "Checkbox should have updated value"); + is(Services.prefs.getBoolPref("extensions.inlinesettings1.bool"), false, "Bool pref should have been updated"); + + ok(!settings[1].hasAttribute("first-row"), "Not the first row"); + Services.prefs.setIntPref("extensions.inlinesettings1.boolint", 0); + var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[1], "anonid", "input"); + isnot(input.checked, true, "Checkbox should have initial value"); + EventUtils.synthesizeMouseAtCenter(input, { clickCount: 1 }, gManagerWindow); + is(input.checked, true, "Checkbox should have updated value"); + is(Services.prefs.getIntPref("extensions.inlinesettings1.boolint"), 1, "BoolInt pref should have been updated"); + EventUtils.synthesizeMouseAtCenter(input, { clickCount: 1 }, gManagerWindow); + isnot(input.checked, true, "Checkbox should have updated value"); + is(Services.prefs.getIntPref("extensions.inlinesettings1.boolint"), 2, "BoolInt pref should have been updated"); + + ok(!settings[2].hasAttribute("first-row"), "Not the first row"); + Services.prefs.setIntPref("extensions.inlinesettings1.integer", 0); + var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[2], "anonid", "input"); + is(input.value, "0", "Number box should have initial value"); + input.select(); + EventUtils.synthesizeKey("1", {}, gManagerWindow); + EventUtils.synthesizeKey("3", {}, gManagerWindow); + is(input.value, "13", "Number box should have updated value"); + is(Services.prefs.getIntPref("extensions.inlinesettings1.integer"), 13, "Integer pref should have been updated"); + EventUtils.synthesizeKey("VK_DOWN", {}, gManagerWindow); + is(input.value, "12", "Number box should have updated value"); + is(Services.prefs.getIntPref("extensions.inlinesettings1.integer"), 12, "Integer pref should have been updated"); + + ok(!settings[3].hasAttribute("first-row"), "Not the first row"); + Services.prefs.setCharPref("extensions.inlinesettings1.string", "foo"); + var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[3], "anonid", "input"); + is(input.value, "foo", "Text box should have initial value"); + input.select(); + EventUtils.synthesizeKey("b", {}, gManagerWindow); + EventUtils.synthesizeKey("a", {}, gManagerWindow); + EventUtils.synthesizeKey("r", {}, gManagerWindow); + is(input.value, "bar", "Text box should have updated value"); + EventUtils.synthesizeKey("/", {}, gManagerWindow); + is(input.value, "bar/", "Text box should have updated value"); + is(gManagerWindow.document.getBindingParent(gManagerWindow.document.activeElement), input, "Search box should not have focus"); + is(Services.prefs.getCharPref("extensions.inlinesettings1.string"), "bar/", "String pref should have been updated"); + + ok(!settings[4].hasAttribute("first-row"), "Not the first row"); + var input = settings[4].firstElementChild; + is(input.value, "1", "Menulist should have initial value"); + input.focus(); + EventUtils.synthesizeKey("b", {}, gManagerWindow); + is(input.value, "2", "Menulist should have updated value"); + is(gManagerWindow._testValue, "2", "Menulist oncommand handler should've updated the test value"); + delete gManagerWindow._testValue; + + ok(!settings[5].hasAttribute("first-row"), "Not the first row"); + Services.prefs.setCharPref("extensions.inlinesettings1.color", "#FF0000"); + input = gManagerWindow.document.getAnonymousElementByAttribute(settings[5], "anonid", "input"); + is(input.color, "#FF0000", "Color picker should have initial value"); + input.focus(); + EventUtils.synthesizeKey("VK_RIGHT", {}, gManagerWindow); + EventUtils.synthesizeKey("VK_RIGHT", {}, gManagerWindow); + EventUtils.synthesizeKey("VK_RETURN", {}, gManagerWindow); + input.hidePopup(); + is(input.color, "#FF9900", "Color picker should have updated value"); + is(Services.prefs.getCharPref("extensions.inlinesettings1.color"), "#FF9900", "Color pref should have been updated"); + + try { + ok(!settings[6].hasAttribute("first-row"), "Not the first row"); + var button = gManagerWindow.document.getAnonymousElementByAttribute(settings[6], "anonid", "button"); + input = gManagerWindow.document.getAnonymousElementByAttribute(settings[6], "anonid", "input"); + is(input.value, "", "Label value should be empty"); + is(input.tooltipText, "", "Label tooltip should be empty"); + + var profD = Services.dirsvc.get("ProfD", Ci.nsIFile); + var curProcD = Services.dirsvc.get("CurProcD", Ci.nsIFile); + + MockFilePicker.returnFiles = [profD]; + MockFilePicker.returnValue = Ci.nsIFilePicker.returnOK; + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + is(MockFilePicker.mode, Ci.nsIFilePicker.modeOpen, "File picker mode should be open file"); + is(input.value, profD.path, "Label value should match file chosen"); + is(input.tooltipText, profD.path, "Label tooltip should match file chosen"); + is(Services.prefs.getCharPref("extensions.inlinesettings1.file"), profD.path, "File pref should match file chosen"); + + MockFilePicker.returnFiles = [curProcD]; + MockFilePicker.returnValue = Ci.nsIFilePicker.returnCancel; + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + is(MockFilePicker.mode, Ci.nsIFilePicker.modeOpen, "File picker mode should be open file"); + is(input.value, profD.path, "Label value should not have changed"); + is(input.tooltipText, profD.path, "Label tooltip should not have changed"); + is(Services.prefs.getCharPref("extensions.inlinesettings1.file"), profD.path, "File pref should not have changed"); + + ok(!settings[7].hasAttribute("first-row"), "Not the first row"); + button = gManagerWindow.document.getAnonymousElementByAttribute(settings[7], "anonid", "button"); + input = gManagerWindow.document.getAnonymousElementByAttribute(settings[7], "anonid", "input"); + is(input.value, "", "Label value should be empty"); + is(input.tooltipText, "", "Label tooltip should be empty"); + + MockFilePicker.returnFiles = [profD]; + MockFilePicker.returnValue = Ci.nsIFilePicker.returnOK; + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + is(MockFilePicker.mode, Ci.nsIFilePicker.modeGetFolder, "File picker mode should be directory"); + is(input.value, profD.path, "Label value should match file chosen"); + is(input.tooltipText, profD.path, "Label tooltip should match file chosen"); + is(Services.prefs.getCharPref("extensions.inlinesettings1.directory"), profD.path, "Directory pref should match file chosen"); + + MockFilePicker.returnFiles = [curProcD]; + MockFilePicker.returnValue = Ci.nsIFilePicker.returnCancel; + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + is(MockFilePicker.mode, Ci.nsIFilePicker.modeGetFolder, "File picker mode should be directory"); + is(input.value, profD.path, "Label value should not have changed"); + is(input.tooltipText, profD.path, "Label tooltip should not have changed"); + is(Services.prefs.getCharPref("extensions.inlinesettings1.directory"), profD.path, "Directory pref should not have changed"); + + var unsizedInput = gManagerWindow.document.getAnonymousElementByAttribute(settings[2], "anonid", "input"); + var sizedInput = gManagerWindow.document.getAnonymousElementByAttribute(settings[8], "anonid", "input"); + is(unsizedInput.clientWidth > sizedInput.clientWidth, true, "Input with size attribute should be smaller than input without"); + } finally { + button = gManagerWindow.document.getElementById("detail-prefs-btn"); + is_element_hidden(button, "Preferences button should not be visible"); + + gCategoryUtilities.openType("extension", run_next_test); + } + }); +}); + +// Tests for the setting.xml bindings introduced after Mozilla 7 +add_test(function() { + observer.checkHidden("inlinesettings1@tests.mozilla.org"); + + var addon = get_addon_element(gManagerWindow, "inlinesettings3@tests.mozilla.org"); + addon.parentNode.ensureElementIsVisible(addon); + + var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "preferences-btn"); + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + observer.checkDisplayed("inlinesettings3@tests.mozilla.org"); + + var grid = gManagerWindow.document.getElementById("detail-grid"); + var settings = grid.querySelectorAll("rows > setting"); + is(settings.length, 4, "Grid should have settings children"); + + ok(settings[0].hasAttribute("first-row"), "First visible row should have first-row attribute"); + Services.prefs.setBoolPref("extensions.inlinesettings3.radioBool", false); + var radios = settings[0].getElementsByTagName("radio"); + isnot(radios[0].selected, true, "Correct radio button should be selected"); + is(radios[1].selected, true, "Correct radio button should be selected"); + EventUtils.synthesizeMouseAtCenter(radios[0], { clickCount: 1 }, gManagerWindow); + is(Services.prefs.getBoolPref("extensions.inlinesettings3.radioBool"), true, "Radio pref should have been updated"); + EventUtils.synthesizeMouseAtCenter(radios[1], { clickCount: 1 }, gManagerWindow); + is(Services.prefs.getBoolPref("extensions.inlinesettings3.radioBool"), false, "Radio pref should have been updated"); + + ok(!settings[1].hasAttribute("first-row"), "Not the first row"); + Services.prefs.setIntPref("extensions.inlinesettings3.radioInt", 5); + var radios = settings[1].getElementsByTagName("radio"); + isnot(radios[0].selected, true, "Correct radio button should be selected"); + is(radios[1].selected, true, "Correct radio button should be selected"); + isnot(radios[2].selected, true, "Correct radio button should be selected"); + EventUtils.synthesizeMouseAtCenter(radios[0], { clickCount: 1 }, gManagerWindow); + is(Services.prefs.getIntPref("extensions.inlinesettings3.radioInt"), 4, "Radio pref should have been updated"); + EventUtils.synthesizeMouseAtCenter(radios[2], { clickCount: 1 }, gManagerWindow); + is(Services.prefs.getIntPref("extensions.inlinesettings3.radioInt"), 6, "Radio pref should have been updated"); + + ok(!settings[2].hasAttribute("first-row"), "Not the first row"); + Services.prefs.setCharPref("extensions.inlinesettings3.radioString", "juliet"); + var radios = settings[2].getElementsByTagName("radio"); + isnot(radios[0].selected, true, "Correct radio button should be selected"); + is(radios[1].selected, true, "Correct radio button should be selected"); + isnot(radios[2].selected, true, "Correct radio button should be selected"); + EventUtils.synthesizeMouseAtCenter(radios[0], { clickCount: 1 }, gManagerWindow); + is(Services.prefs.getCharPref("extensions.inlinesettings3.radioString"), "india", "Radio pref should have been updated"); + EventUtils.synthesizeMouseAtCenter(radios[2], { clickCount: 1 }, gManagerWindow); + is(Services.prefs.getCharPref("extensions.inlinesettings3.radioString"), "kilo", "Radio pref should have been updated"); + + ok(!settings[3].hasAttribute("first-row"), "Not the first row"); + Services.prefs.setIntPref("extensions.inlinesettings3.menulist", 8); + var input = settings[3].firstElementChild; + is(input.value, "8", "Menulist should have initial value"); + input.focus(); + EventUtils.synthesizeKey("n", {}, gManagerWindow); + is(input.value, "9", "Menulist should have updated value"); + is(Services.prefs.getIntPref("extensions.inlinesettings3.menulist"), 9, "Menulist pref should have been updated"); + + button = gManagerWindow.document.getElementById("detail-prefs-btn"); + is_element_hidden(button, "Preferences button should not be visible"); + + gCategoryUtilities.openType("extension", run_next_test); + }); +}); + +// Addon with inline preferences as optionsURL +add_test(function() { + observer.checkHidden("inlinesettings3@tests.mozilla.org"); + + var addon = get_addon_element(gManagerWindow, "inlinesettings2@tests.mozilla.org"); + addon.parentNode.ensureElementIsVisible(addon); + + var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "preferences-btn"); + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + observer.checkDisplayed("inlinesettings2@tests.mozilla.org"); + + var grid = gManagerWindow.document.getElementById("detail-grid"); + var settings = grid.querySelectorAll("rows > setting"); + is(settings.length, 5, "Grid should have settings children"); + + var node = settings[0]; + node = settings[0]; + is_element_hidden(node, "Unsupported settings should not be visible"); + ok(!node.hasAttribute("first-row"), "Hidden row is not the first row"); + + node = settings[1]; + is(node.nodeName, "setting", "Should be a setting node"); + ok(node.hasAttribute("first-row"), "First visible row should have first-row attribute"); + var description = gManagerWindow.document.getAnonymousElementByAttribute(node, "class", "preferences-description"); + is(description.textContent, "Description Attribute", "Description node should contain description"); + + node = settings[2]; + is(node.nodeName, "setting", "Should be a setting node"); + ok(!node.hasAttribute("first-row"), "Not the first row"); + description = gManagerWindow.document.getAnonymousElementByAttribute(node, "class", "preferences-description"); + is(description.textContent, "Description Text Node", "Description node should contain description"); + + node = settings[3]; + is(node.nodeName, "setting", "Should be a setting node"); + ok(!node.hasAttribute("first-row"), "Not the first row"); + description = gManagerWindow.document.getAnonymousElementByAttribute(node, "class", "preferences-description"); + is(description.textContent, "This is a test, all this text should be visible", "Description node should contain description"); + var button = node.firstElementChild; + isnot(button, null, "There should be a button"); + + node = settings[4]; + is_element_hidden(node, "Unsupported settings should not be visible"); + ok(!node.hasAttribute("first-row"), "Hidden row is not the first row"); + + var button = gManagerWindow.document.getElementById("detail-prefs-btn"); + is_element_hidden(button, "Preferences button should not be visible"); + + gCategoryUtilities.openType("extension", run_next_test); + }); +}); + +// Addon with non-inline preferences as optionsURL +add_test(function() { + observer.checkHidden("inlinesettings2@tests.mozilla.org"); + + var addon = get_addon_element(gManagerWindow, "noninlinesettings@tests.mozilla.org"); + addon.parentNode.ensureElementIsVisible(addon); + + var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "details-btn"); + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + observer.checkNotDisplayed(); + + var grid = gManagerWindow.document.getElementById("detail-grid"); + var settings = grid.querySelectorAll("rows > setting"); + is(settings.length, 0, "Grid should not have settings children"); + + var button = gManagerWindow.document.getElementById("detail-prefs-btn"); + is_element_visible(button, "Preferences button should be visible"); + + gCategoryUtilities.openType("extension", run_next_test); + }); +}); + +// Addon with options.xul, disabling and enabling should hide and show settings UI +add_test(function() { + observer.checkNotHidden(); + + var addon = get_addon_element(gManagerWindow, "inlinesettings1@tests.mozilla.org"); + addon.parentNode.ensureElementIsVisible(addon); + + var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "details-btn"); + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + observer.checkDisplayed("inlinesettings1@tests.mozilla.org"); + is(gManagerWindow.gViewController.currentViewId, + "addons://detail/inlinesettings1%40tests.mozilla.org", + "Current view should not scroll to preferences"); + checkScrolling(false); + + var grid = gManagerWindow.document.getElementById("detail-grid"); + var settings = grid.querySelectorAll("rows > setting"); + is(settings.length, SETTINGS_ROWS, "Grid should have settings children"); + + // disable + var button = gManagerWindow.document.getElementById("detail-disable-btn"); + button.focus(); // make sure it's in view + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + + observer.checkHidden("inlinesettings1@tests.mozilla.org"); + + settings = grid.querySelectorAll("rows > setting"); + is(settings.length, 0, "Grid should not have settings children"); + + gCategoryUtilities.openType("extension", function() { + var addon = get_addon_element(gManagerWindow, "inlinesettings1@tests.mozilla.org"); + addon.parentNode.ensureElementIsVisible(addon); + + var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "preferences-btn"); + is_element_hidden(button, "Preferences button should not be visible"); + + button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "details-btn"); + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + var grid = gManagerWindow.document.getElementById("detail-grid"); + var settings = grid.querySelectorAll("rows > setting"); + is(settings.length, 0, "Grid should not have settings children"); + + // enable + var button = gManagerWindow.document.getElementById("detail-enable-btn"); + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + + observer.callback = function() { + observer.checkDisplayed("inlinesettings1@tests.mozilla.org"); + + settings = grid.querySelectorAll("rows > setting"); + is(settings.length, SETTINGS_ROWS, "Grid should have settings children"); + + gCategoryUtilities.openType("extension", run_next_test); + }; + }); + }); + }); +}); + + +// Addon with options.xul that requires a restart to disable, +// disabling and enabling should not hide and show settings UI. +add_test(function() { + observer.checkHidden("inlinesettings1@tests.mozilla.org"); + + var addon = get_addon_element(gManagerWindow, "inlinesettings2@tests.mozilla.org"); + addon.parentNode.ensureElementIsVisible(addon); + + var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "details-btn"); + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + observer.checkDisplayed("inlinesettings2@tests.mozilla.org"); + + var grid = gManagerWindow.document.getElementById("detail-grid"); + var settings = grid.querySelectorAll("rows > setting"); + ok(settings.length > 0, "Grid should have settings children"); + + // disable + var button = gManagerWindow.document.getElementById("detail-disable-btn"); + button.focus(); // make sure it's in view + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + observer.checkNotHidden(); + + settings = grid.querySelectorAll("rows > setting"); + ok(settings.length > 0, "Grid should still have settings children"); + + // cancel pending disable + button = gManagerWindow.document.getElementById("detail-enable-btn"); + button.focus(); // make sure it's in view + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + observer.checkNotDisplayed(); + + gCategoryUtilities.openType("extension", run_next_test); + }); +}); + +// Tests bindings with existing prefs. +add_test(function() { + observer.checkHidden("inlinesettings2@tests.mozilla.org"); + + // Ensure these prefs are set. They should be set above, but somebody might + // change the tests above. + var profD = Services.dirsvc.get("ProfD", Ci.nsIFile); + Services.prefs.setBoolPref("extensions.inlinesettings1.bool", false); + Services.prefs.setIntPref("extensions.inlinesettings1.boolint", 1); + Services.prefs.setIntPref("extensions.inlinesettings1.integer", 12); + Services.prefs.setCharPref("extensions.inlinesettings1.string", "bar/"); + Services.prefs.setCharPref("extensions.inlinesettings1.color", "#FF9900"); + Services.prefs.setCharPref("extensions.inlinesettings1.file", profD.path); + Services.prefs.setCharPref("extensions.inlinesettings1.directory", profD.path); + + var addon = get_addon_element(gManagerWindow, "inlinesettings1@tests.mozilla.org"); + addon.parentNode.ensureElementIsVisible(addon); + + var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "preferences-btn"); + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + observer.checkDisplayed("inlinesettings1@tests.mozilla.org"); + + var grid = gManagerWindow.document.getElementById("detail-grid"); + var settings = grid.querySelectorAll("rows > setting"); + + var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[0], "anonid", "input"); + is(input.checked, false, "Checkbox should have initial value"); + + var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[1], "anonid", "input"); + is(input.checked, true, "Checkbox should have initial value"); + + var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[2], "anonid", "input"); + is(input.value, "12", "Number box should have initial value"); + + var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[3], "anonid", "input"); + is(input.value, "bar/", "Text box should have initial value"); + + input = gManagerWindow.document.getAnonymousElementByAttribute(settings[5], "anonid", "input"); + is(input.color, "#FF9900", "Color picker should have initial value"); + + input = gManagerWindow.document.getAnonymousElementByAttribute(settings[6], "anonid", "input"); + is(input.value, profD.path, "Label should have initial value"); + is(input.tooltipText, profD.path, "Label tooltip should have initial value"); + + input = gManagerWindow.document.getAnonymousElementByAttribute(settings[7], "anonid", "input"); + is(input.value, profD.path, "Label value should have initial value"); + is(input.tooltipText, profD.path, "Label tooltip should have initial value"); + + gCategoryUtilities.openType("extension", run_next_test); + }); +}); + +// Tests bindings with existing prefs. +add_test(function() { + observer.checkHidden("inlinesettings1@tests.mozilla.org"); + + // Ensure these prefs are set. They should be set above, but somebody might + // change the tests above. + Services.prefs.setBoolPref("extensions.inlinesettings3.radioBool", false); + Services.prefs.setIntPref("extensions.inlinesettings3.radioInt", 6); + Services.prefs.setCharPref("extensions.inlinesettings3.radioString", "kilo"); + Services.prefs.setIntPref("extensions.inlinesettings3.menulist", 9); + + var addon = get_addon_element(gManagerWindow, "inlinesettings3@tests.mozilla.org"); + addon.parentNode.ensureElementIsVisible(addon); + + var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "preferences-btn"); + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + observer.checkDisplayed("inlinesettings3@tests.mozilla.org"); + + var grid = gManagerWindow.document.getElementById("detail-grid"); + var settings = grid.querySelectorAll("rows > setting"); + + var radios = settings[0].getElementsByTagName("radio"); + isnot(radios[0].selected, true, "Correct radio button should be selected"); + is(radios[1].selected, true, "Correct radio button should be selected"); + + var radios = settings[1].getElementsByTagName("radio"); + isnot(radios[0].selected, true, "Correct radio button should be selected"); + isnot(radios[1].selected, true, "Correct radio button should be selected"); + is(radios[2].selected, true, "Correct radio button should be selected"); + + var radios = settings[2].getElementsByTagName("radio"); + isnot(radios[0].selected, true, "Correct radio button should be selected"); + isnot(radios[1].selected, true, "Correct radio button should be selected"); + is(radios[2].selected, true, "Correct radio button should be selected"); + + var input = settings[3].firstElementChild; + is(input.value, "9", "Menulist should have initial value"); + + gCategoryUtilities.openType("extension", run_next_test); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_inlinesettings_custom.js b/toolkit/mozapps/extensions/test/browser/browser_inlinesettings_custom.js new file mode 100644 index 000000000..ecd10852d --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_inlinesettings_custom.js @@ -0,0 +1,92 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests various aspects of the details view + +var gManagerWindow; +var gCategoryUtilities; + +function installAddon(aCallback) { + AddonManager.getInstallForURL(TESTROOT + "addons/browser_inlinesettings1_custom.xpi", + function(aInstall) { + aInstall.addListener({ + onInstallEnded: function() { + executeSoon(aCallback); + } + }); + aInstall.install(); + }, "application/x-xpinstall"); +} + +function test() { + waitForExplicitFinish(); + + installAddon(function () { + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + run_next_test(); + }); + }); +} + +function end_test() { + close_manager(gManagerWindow, function() { + AddonManager.getAddonByID("inlinesettings1@tests.mozilla.org", function(aAddon) { + aAddon.uninstall(); + finish(); + }); + }); +} + +// Addon with options.xul, with custom <setting> binding +add_test(function() { + var addon = get_addon_element(gManagerWindow, "inlinesettings1@tests.mozilla.org"); + is(addon.mAddon.optionsType, AddonManager.OPTIONS_TYPE_INLINE, "Options should be inline type"); + addon.parentNode.ensureElementIsVisible(addon); + + var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "preferences-btn"); + is_element_visible(button, "Preferences button should be visible"); + + run_next_test(); +}); + +// Addon with options.xul, also a test for the setting.xml bindings +add_test(function() { + var addon = get_addon_element(gManagerWindow, "inlinesettings1@tests.mozilla.org"); + addon.parentNode.ensureElementIsVisible(addon); + + var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "preferences-btn"); + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + is(gManagerWindow.gViewController.currentViewId, + "addons://detail/inlinesettings1%40tests.mozilla.org/preferences", + "Current view should scroll to preferences"); + + var grid = gManagerWindow.document.getElementById("detail-grid"); + var settings = grid.querySelectorAll("rows > setting"); + is(settings.length, 1, "Grid should have settings children"); + + ok(settings[0].hasAttribute("first-row"), "First visible row should have first-row attribute"); + + var style = window.getComputedStyle(settings[0], null); + is(style.getPropertyValue("background-color"), "rgb(0, 0, 255)", "Background color should be set"); + is(style.getPropertyValue("display"), "-moz-grid-line", "Display should be set"); + is(style.getPropertyValue("-moz-binding"), 'url("chrome://inlinesettings/content/binding.xml#custom")', "Binding should be set"); + + var label = gManagerWindow.document.getAnonymousElementByAttribute(settings[0], "anonid", "label"); + is(label.textContent, "Custom", "Localized string should be shown"); + + var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[0], "anonid", "input"); + isnot(input, null, "Binding should be applied"); + is(input.value, "Woah!", "Binding should be applied"); + + button = gManagerWindow.document.getElementById("detail-prefs-btn"); + is_element_hidden(button, "Preferences button should not be visible"); + + gCategoryUtilities.openType("extension", run_next_test); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_inlinesettings_info.js b/toolkit/mozapps/extensions/test/browser/browser_inlinesettings_info.js new file mode 100644 index 000000000..05b43a238 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_inlinesettings_info.js @@ -0,0 +1,569 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests various aspects of the details view + +var gManagerWindow; +var gCategoryUtilities; +var gProvider; + +const SETTINGS_ROWS = 8; + +var MockFilePicker = SpecialPowers.MockFilePicker; +MockFilePicker.init(window); + +var observer = { + lastDisplayed: null, + callback: null, + checkDisplayed: function(aExpected) { + is(this.lastDisplayed, aExpected, "'addon-options-displayed' notification should have fired"); + this.lastDisplayed = null; + }, + checkNotDisplayed: function() { + is(this.lastDisplayed, null, "'addon-options-displayed' notification should not have fired"); + }, + lastHidden: null, + checkHidden: function(aExpected) { + is(this.lastHidden, aExpected, "'addon-options-hidden' notification should have fired"); + this.lastHidden = null; + }, + checkNotHidden: function() { + is(this.lastHidden, null, "'addon-options-hidden' notification should not have fired"); + }, + observe: function(aSubject, aTopic, aData) { + if (aTopic == AddonManager.OPTIONS_NOTIFICATION_DISPLAYED) { + this.lastDisplayed = aData; + // Test if the binding has applied before the observers are notified. We test the second setting here, + // because the code operates on the first setting and we want to check it applies to all. + var setting = aSubject.querySelector("rows > setting[first-row] ~ setting"); + var input = gManagerWindow.document.getAnonymousElementByAttribute(setting, "class", "preferences-title"); + isnot(input, null, "XBL binding should be applied"); + + // Add some extra height to the scrolling pane to ensure that it needs to scroll when appropriate. + gManagerWindow.document.getElementById("detail-controls").style.marginBottom = "1000px"; + + if (this.callback) { + var tempCallback = this.callback; + this.callback = null; + tempCallback(); + } + } else if (aTopic == AddonManager.OPTIONS_NOTIFICATION_HIDDEN) { + this.lastHidden = aData; + } + } +}; + +function installAddon(aCallback) { + AddonManager.getInstallForURL(TESTROOT + "addons/browser_inlinesettings1_info.xpi", + function(aInstall) { + aInstall.addListener({ + onInstallEnded: function() { + executeSoon(aCallback); + } + }); + aInstall.install(); + }, "application/x-xpinstall"); +} + +function checkScrolling(aShouldHaveScrolled) { + var detailView = gManagerWindow.document.getElementById("detail-view"); + var boxObject = detailView.boxObject; + ok(detailView.scrollHeight > boxObject.height, "Page should require scrolling"); + if (aShouldHaveScrolled) + isnot(detailView.scrollTop, 0, "Page should have scrolled"); + else + is(detailView.scrollTop, 0, "Page should not have scrolled"); +} + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + gProvider.createAddons([{ + id: "inlinesettings2@tests.mozilla.org", + name: "Inline Settings (Regular)", + version: "1", + optionsURL: CHROMEROOT + "options.xul", + optionsType: AddonManager.OPTIONS_TYPE_INLINE_INFO, + operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_DISABLE, + },{ + id: "inlinesettings3@tests.mozilla.org", + name: "Inline Settings (More Options)", + description: "Tests for option types introduced after Mozilla 7.0", + version: "1", + optionsURL: CHROMEROOT + "more_options.xul", + optionsType: AddonManager.OPTIONS_TYPE_INLINE_INFO + },{ + id: "noninlinesettings@tests.mozilla.org", + name: "Non-Inline Settings", + version: "1", + optionsURL: CHROMEROOT + "addon_prefs.xul" + }]); + + installAddon(function () { + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + Services.obs.addObserver(observer, + AddonManager.OPTIONS_NOTIFICATION_DISPLAYED, + false); + Services.obs.addObserver(observer, + AddonManager.OPTIONS_NOTIFICATION_HIDDEN, + false); + + run_next_test(); + }); + }); +} + +function end_test() { + Services.obs.removeObserver(observer, + AddonManager.OPTIONS_NOTIFICATION_DISPLAYED); + + Services.prefs.clearUserPref("extensions.inlinesettings1.bool"); + Services.prefs.clearUserPref("extensions.inlinesettings1.boolint"); + Services.prefs.clearUserPref("extensions.inlinesettings1.integer"); + Services.prefs.clearUserPref("extensions.inlinesettings1.string"); + Services.prefs.clearUserPref("extensions.inlinesettings1.color"); + Services.prefs.clearUserPref("extensions.inlinesettings1.file"); + Services.prefs.clearUserPref("extensions.inlinesettings1.directory"); + Services.prefs.clearUserPref("extensions.inlinesettings3.radioBool"); + Services.prefs.clearUserPref("extensions.inlinesettings3.radioInt"); + Services.prefs.clearUserPref("extensions.inlinesettings3.radioString"); + Services.prefs.clearUserPref("extensions.inlinesettings3.menulist"); + + MockFilePicker.cleanup(); + + close_manager(gManagerWindow, function() { + observer.checkHidden("inlinesettings2@tests.mozilla.org"); + Services.obs.removeObserver(observer, + AddonManager.OPTIONS_NOTIFICATION_HIDDEN); + + AddonManager.getAddonByID("inlinesettings1@tests.mozilla.org", function(aAddon) { + aAddon.uninstall(); + finish(); + }); + }); +} + +// Addon with options.xul +add_test(function() { + var addon = get_addon_element(gManagerWindow, "inlinesettings1@tests.mozilla.org"); + is(addon.mAddon.optionsType, AddonManager.OPTIONS_TYPE_INLINE_INFO, "Options should be inline info type"); + addon.parentNode.ensureElementIsVisible(addon); + + var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "preferences-btn"); + is_element_hidden(button, "Preferences button should be hidden"); + + run_next_test(); +}); + +// Addon with inline preferences as optionsURL +add_test(function() { + var addon = get_addon_element(gManagerWindow, "inlinesettings2@tests.mozilla.org"); + is(addon.mAddon.optionsType, AddonManager.OPTIONS_TYPE_INLINE_INFO, "Options should be inline info type"); + addon.parentNode.ensureElementIsVisible(addon); + + var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "preferences-btn"); + is_element_hidden(button, "Preferences button should be hidden"); + + run_next_test(); +}); + +// Addon with non-inline preferences as optionsURL +add_test(function() { + var addon = get_addon_element(gManagerWindow, "noninlinesettings@tests.mozilla.org"); + is(addon.mAddon.optionsType, AddonManager.OPTIONS_TYPE_DIALOG, "Options should be dialog type"); + addon.parentNode.ensureElementIsVisible(addon); + + var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "preferences-btn"); + is_element_visible(button, "Preferences button should be visible"); + + run_next_test(); +}); + +// Addon with options.xul, also a test for the setting.xml bindings +add_test(function() { + var addon = get_addon_element(gManagerWindow, "inlinesettings1@tests.mozilla.org"); + addon.parentNode.ensureElementIsVisible(addon); + + var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "details-btn"); + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + observer.checkDisplayed("inlinesettings1@tests.mozilla.org"); + + var grid = gManagerWindow.document.getElementById("detail-grid"); + var settings = grid.querySelectorAll("rows > setting"); + is(settings.length, SETTINGS_ROWS, "Grid should have settings children"); + + ok(settings[0].hasAttribute("first-row"), "First visible row should have first-row attribute"); + Services.prefs.setBoolPref("extensions.inlinesettings1.bool", false); + var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[0], "anonid", "input"); + isnot(input.checked, true, "Checkbox should have initial value"); + is(input.label, "Check box label", "Checkbox should be labelled"); + EventUtils.synthesizeMouseAtCenter(input, { clickCount: 1 }, gManagerWindow); + is(input.checked, true, "Checkbox should have updated value"); + is(Services.prefs.getBoolPref("extensions.inlinesettings1.bool"), true, "Bool pref should have been updated"); + EventUtils.synthesizeMouseAtCenter(input, { clickCount: 1 }, gManagerWindow); + isnot(input.checked, true, "Checkbox should have updated value"); + is(Services.prefs.getBoolPref("extensions.inlinesettings1.bool"), false, "Bool pref should have been updated"); + + ok(!settings[1].hasAttribute("first-row"), "Not the first row"); + Services.prefs.setIntPref("extensions.inlinesettings1.boolint", 0); + var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[1], "anonid", "input"); + isnot(input.checked, true, "Checkbox should have initial value"); + EventUtils.synthesizeMouseAtCenter(input, { clickCount: 1 }, gManagerWindow); + is(input.checked, true, "Checkbox should have updated value"); + is(Services.prefs.getIntPref("extensions.inlinesettings1.boolint"), 1, "BoolInt pref should have been updated"); + EventUtils.synthesizeMouseAtCenter(input, { clickCount: 1 }, gManagerWindow); + isnot(input.checked, true, "Checkbox should have updated value"); + is(Services.prefs.getIntPref("extensions.inlinesettings1.boolint"), 2, "BoolInt pref should have been updated"); + + ok(!settings[2].hasAttribute("first-row"), "Not the first row"); + Services.prefs.setIntPref("extensions.inlinesettings1.integer", 0); + var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[2], "anonid", "input"); + is(input.value, "0", "Number box should have initial value"); + input.select(); + EventUtils.synthesizeKey("1", {}, gManagerWindow); + EventUtils.synthesizeKey("3", {}, gManagerWindow); + is(input.value, "13", "Number box should have updated value"); + is(Services.prefs.getIntPref("extensions.inlinesettings1.integer"), 13, "Integer pref should have been updated"); + EventUtils.synthesizeKey("VK_DOWN", {}, gManagerWindow); + is(input.value, "12", "Number box should have updated value"); + is(Services.prefs.getIntPref("extensions.inlinesettings1.integer"), 12, "Integer pref should have been updated"); + + ok(!settings[3].hasAttribute("first-row"), "Not the first row"); + Services.prefs.setCharPref("extensions.inlinesettings1.string", "foo"); + var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[3], "anonid", "input"); + is(input.value, "foo", "Text box should have initial value"); + input.select(); + EventUtils.synthesizeKey("b", {}, gManagerWindow); + EventUtils.synthesizeKey("a", {}, gManagerWindow); + EventUtils.synthesizeKey("r", {}, gManagerWindow); + is(input.value, "bar", "Text box should have updated value"); + is(Services.prefs.getCharPref("extensions.inlinesettings1.string"), "bar", "String pref should have been updated"); + + ok(!settings[4].hasAttribute("first-row"), "Not the first row"); + var input = settings[4].firstElementChild; + is(input.value, "1", "Menulist should have initial value"); + input.focus(); + EventUtils.synthesizeKey("b", {}, gManagerWindow); + is(input.value, "2", "Menulist should have updated value"); + is(gManagerWindow._testValue, "2", "Menulist oncommand handler should've updated the test value"); + delete gManagerWindow._testValue; + + ok(!settings[5].hasAttribute("first-row"), "Not the first row"); + Services.prefs.setCharPref("extensions.inlinesettings1.color", "#FF0000"); + input = gManagerWindow.document.getAnonymousElementByAttribute(settings[5], "anonid", "input"); + is(input.color, "#FF0000", "Color picker should have initial value"); + input.focus(); + EventUtils.synthesizeKey("VK_RIGHT", {}, gManagerWindow); + EventUtils.synthesizeKey("VK_RIGHT", {}, gManagerWindow); + EventUtils.synthesizeKey("VK_RETURN", {}, gManagerWindow); + input.hidePopup(); + is(input.color, "#FF9900", "Color picker should have updated value"); + is(Services.prefs.getCharPref("extensions.inlinesettings1.color"), "#FF9900", "Color pref should have been updated"); + + try { + ok(!settings[6].hasAttribute("first-row"), "Not the first row"); + var button = gManagerWindow.document.getAnonymousElementByAttribute(settings[6], "anonid", "button"); + input = gManagerWindow.document.getAnonymousElementByAttribute(settings[6], "anonid", "input"); + is(input.value, "", "Label value should be empty"); + is(input.tooltipText, "", "Label tooltip should be empty"); + + var profD = Services.dirsvc.get("ProfD", Ci.nsIFile); + var curProcD = Services.dirsvc.get("CurProcD", Ci.nsIFile); + + MockFilePicker.returnFiles = [profD]; + MockFilePicker.returnValue = Ci.nsIFilePicker.returnOK; + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + is(MockFilePicker.mode, Ci.nsIFilePicker.modeOpen, "File picker mode should be open file"); + is(input.value, profD.path, "Label value should match file chosen"); + is(input.tooltipText, profD.path, "Label tooltip should match file chosen"); + is(Services.prefs.getCharPref("extensions.inlinesettings1.file"), profD.path, "File pref should match file chosen"); + + MockFilePicker.returnFiles = [curProcD]; + MockFilePicker.returnValue = Ci.nsIFilePicker.returnCancel; + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + is(MockFilePicker.mode, Ci.nsIFilePicker.modeOpen, "File picker mode should be open file"); + is(input.value, profD.path, "Label value should not have changed"); + is(input.tooltipText, profD.path, "Label tooltip should not have changed"); + is(Services.prefs.getCharPref("extensions.inlinesettings1.file"), profD.path, "File pref should not have changed"); + + ok(!settings[7].hasAttribute("first-row"), "Not the first row"); + button = gManagerWindow.document.getAnonymousElementByAttribute(settings[7], "anonid", "button"); + input = gManagerWindow.document.getAnonymousElementByAttribute(settings[7], "anonid", "input"); + is(input.value, "", "Label value should be empty"); + is(input.tooltipText, "", "Label tooltip should be empty"); + + MockFilePicker.returnFiles = [profD]; + MockFilePicker.returnValue = Ci.nsIFilePicker.returnOK; + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + is(MockFilePicker.mode, Ci.nsIFilePicker.modeGetFolder, "File picker mode should be directory"); + is(input.value, profD.path, "Label value should match file chosen"); + is(input.tooltipText, profD.path, "Label tooltip should match file chosen"); + is(Services.prefs.getCharPref("extensions.inlinesettings1.directory"), profD.path, "Directory pref should match file chosen"); + + MockFilePicker.returnFiles = [curProcD]; + MockFilePicker.returnValue = Ci.nsIFilePicker.returnCancel; + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + is(MockFilePicker.mode, Ci.nsIFilePicker.modeGetFolder, "File picker mode should be directory"); + is(input.value, profD.path, "Label value should not have changed"); + is(input.tooltipText, profD.path, "Label tooltip should not have changed"); + is(Services.prefs.getCharPref("extensions.inlinesettings1.directory"), profD.path, "Directory pref should not have changed"); + + } finally { + button = gManagerWindow.document.getElementById("detail-prefs-btn"); + is_element_hidden(button, "Preferences button should not be visible"); + + gCategoryUtilities.openType("extension", run_next_test); + } + }); +}); + +// Tests for the setting.xml bindings introduced after Mozilla 7 +add_test(function() { + observer.checkHidden("inlinesettings1@tests.mozilla.org"); + + var addon = get_addon_element(gManagerWindow, "inlinesettings3@tests.mozilla.org"); + addon.parentNode.ensureElementIsVisible(addon); + + var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "details-btn"); + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + observer.checkDisplayed("inlinesettings3@tests.mozilla.org"); + + var grid = gManagerWindow.document.getElementById("detail-grid"); + var settings = grid.querySelectorAll("rows > setting"); + is(settings.length, 4, "Grid should have settings children"); + + ok(settings[0].hasAttribute("first-row"), "First visible row should have first-row attribute"); + Services.prefs.setBoolPref("extensions.inlinesettings3.radioBool", false); + var radios = settings[0].getElementsByTagName("radio"); + isnot(radios[0].selected, true, "Correct radio button should be selected"); + is(radios[1].selected, true, "Correct radio button should be selected"); + EventUtils.synthesizeMouseAtCenter(radios[0], { clickCount: 1 }, gManagerWindow); + is(Services.prefs.getBoolPref("extensions.inlinesettings3.radioBool"), true, "Radio pref should have been updated"); + EventUtils.synthesizeMouseAtCenter(radios[1], { clickCount: 1 }, gManagerWindow); + is(Services.prefs.getBoolPref("extensions.inlinesettings3.radioBool"), false, "Radio pref should have been updated"); + + ok(!settings[1].hasAttribute("first-row"), "Not the first row"); + Services.prefs.setIntPref("extensions.inlinesettings3.radioInt", 5); + var radios = settings[1].getElementsByTagName("radio"); + isnot(radios[0].selected, true, "Correct radio button should be selected"); + is(radios[1].selected, true, "Correct radio button should be selected"); + isnot(radios[2].selected, true, "Correct radio button should be selected"); + EventUtils.synthesizeMouseAtCenter(radios[0], { clickCount: 1 }, gManagerWindow); + is(Services.prefs.getIntPref("extensions.inlinesettings3.radioInt"), 4, "Radio pref should have been updated"); + EventUtils.synthesizeMouseAtCenter(radios[2], { clickCount: 1 }, gManagerWindow); + is(Services.prefs.getIntPref("extensions.inlinesettings3.radioInt"), 6, "Radio pref should have been updated"); + + ok(!settings[2].hasAttribute("first-row"), "Not the first row"); + Services.prefs.setCharPref("extensions.inlinesettings3.radioString", "juliet"); + var radios = settings[2].getElementsByTagName("radio"); + isnot(radios[0].selected, true, "Correct radio button should be selected"); + is(radios[1].selected, true, "Correct radio button should be selected"); + isnot(radios[2].selected, true, "Correct radio button should be selected"); + EventUtils.synthesizeMouseAtCenter(radios[0], { clickCount: 1 }, gManagerWindow); + is(Services.prefs.getCharPref("extensions.inlinesettings3.radioString"), "india", "Radio pref should have been updated"); + EventUtils.synthesizeMouseAtCenter(radios[2], { clickCount: 1 }, gManagerWindow); + is(Services.prefs.getCharPref("extensions.inlinesettings3.radioString"), "kilo", "Radio pref should have been updated"); + + ok(!settings[3].hasAttribute("first-row"), "Not the first row"); + Services.prefs.setIntPref("extensions.inlinesettings3.menulist", 8); + var input = settings[3].firstElementChild; + is(input.value, "8", "Menulist should have initial value"); + input.focus(); + EventUtils.synthesizeKey("n", {}, gManagerWindow); + is(input.value, "9", "Menulist should have updated value"); + is(Services.prefs.getIntPref("extensions.inlinesettings3.menulist"), 9, "Menulist pref should have been updated"); + + button = gManagerWindow.document.getElementById("detail-prefs-btn"); + is_element_hidden(button, "Preferences button should not be visible"); + + gCategoryUtilities.openType("extension", run_next_test); + }); +}); + +// Addon with inline preferences as optionsURL +add_test(function() { + observer.checkHidden("inlinesettings3@tests.mozilla.org"); + + var addon = get_addon_element(gManagerWindow, "inlinesettings2@tests.mozilla.org"); + addon.parentNode.ensureElementIsVisible(addon); + + var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "details-btn"); + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + observer.checkDisplayed("inlinesettings2@tests.mozilla.org"); + + var grid = gManagerWindow.document.getElementById("detail-grid"); + var settings = grid.querySelectorAll("rows > setting"); + is(settings.length, 5, "Grid should have settings children"); + + var node = settings[0]; + node = settings[0]; + is_element_hidden(node, "Unsupported settings should not be visible"); + ok(!node.hasAttribute("first-row"), "Hidden row is not the first row"); + + node = settings[1]; + is(node.nodeName, "setting", "Should be a setting node"); + ok(node.hasAttribute("first-row"), "First visible row should have first-row attribute"); + var description = gManagerWindow.document.getAnonymousElementByAttribute(node, "class", "preferences-description"); + is(description.textContent, "Description Attribute", "Description node should contain description"); + + node = settings[2]; + is(node.nodeName, "setting", "Should be a setting node"); + ok(!node.hasAttribute("first-row"), "Not the first row"); + description = gManagerWindow.document.getAnonymousElementByAttribute(node, "class", "preferences-description"); + is(description.textContent, "Description Text Node", "Description node should contain description"); + + node = settings[3]; + is(node.nodeName, "setting", "Should be a setting node"); + ok(!node.hasAttribute("first-row"), "Not the first row"); + description = gManagerWindow.document.getAnonymousElementByAttribute(node, "class", "preferences-description"); + is(description.textContent, "This is a test, all this text should be visible", "Description node should contain description"); + var button = node.firstElementChild; + isnot(button, null, "There should be a button"); + + node = settings[4]; + is_element_hidden(node, "Unsupported settings should not be visible"); + ok(!node.hasAttribute("first-row"), "Hidden row is not the first row"); + + var button = gManagerWindow.document.getElementById("detail-prefs-btn"); + is_element_hidden(button, "Preferences button should not be visible"); + + gCategoryUtilities.openType("extension", run_next_test); + }); +}); + +// Addon with non-inline preferences as optionsURL +add_test(function() { + observer.checkHidden("inlinesettings2@tests.mozilla.org"); + + var addon = get_addon_element(gManagerWindow, "noninlinesettings@tests.mozilla.org"); + addon.parentNode.ensureElementIsVisible(addon); + + var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "details-btn"); + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + observer.checkNotDisplayed(); + + var grid = gManagerWindow.document.getElementById("detail-grid"); + var settings = grid.querySelectorAll("rows > setting"); + is(settings.length, 0, "Grid should not have settings children"); + + var button = gManagerWindow.document.getElementById("detail-prefs-btn"); + is_element_visible(button, "Preferences button should be visible"); + + gCategoryUtilities.openType("extension", run_next_test); + }); +}); + +// Addon with options.xul, disabling and enabling should hide and show settings UI +add_test(function() { + observer.checkNotHidden(); + + var addon = get_addon_element(gManagerWindow, "inlinesettings1@tests.mozilla.org"); + addon.parentNode.ensureElementIsVisible(addon); + + var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "details-btn"); + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + observer.checkDisplayed("inlinesettings1@tests.mozilla.org"); + is(gManagerWindow.gViewController.currentViewId, + "addons://detail/inlinesettings1%40tests.mozilla.org", + "Current view should not scroll to preferences"); + checkScrolling(false); + + var grid = gManagerWindow.document.getElementById("detail-grid"); + var settings = grid.querySelectorAll("rows > setting"); + is(settings.length, SETTINGS_ROWS, "Grid should have settings children"); + + // disable + var button = gManagerWindow.document.getElementById("detail-disable-btn"); + button.focus(); // make sure it's in view + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + + observer.checkHidden("inlinesettings1@tests.mozilla.org"); + + settings = grid.querySelectorAll("rows > setting"); + is(settings.length, 0, "Grid should not have settings children"); + + gCategoryUtilities.openType("extension", function() { + var addon = get_addon_element(gManagerWindow, "inlinesettings1@tests.mozilla.org"); + addon.parentNode.ensureElementIsVisible(addon); + + var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "preferences-btn"); + is_element_hidden(button, "Preferences button should not be visible"); + + button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "details-btn"); + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + var grid = gManagerWindow.document.getElementById("detail-grid"); + var settings = grid.querySelectorAll("rows > setting"); + is(settings.length, 0, "Grid should not have settings children"); + + // enable + var button = gManagerWindow.document.getElementById("detail-enable-btn"); + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + + observer.callback = function() { + observer.checkDisplayed("inlinesettings1@tests.mozilla.org"); + + settings = grid.querySelectorAll("rows > setting"); + is(settings.length, SETTINGS_ROWS, "Grid should have settings children"); + + gCategoryUtilities.openType("extension", run_next_test); + }; + }); + }); + }); +}); + + +// Addon with options.xul that requires a restart to disable, +// disabling and enabling should not hide and show settings UI. +add_test(function() { + observer.checkHidden("inlinesettings1@tests.mozilla.org"); + + var addon = get_addon_element(gManagerWindow, "inlinesettings2@tests.mozilla.org"); + addon.parentNode.ensureElementIsVisible(addon); + + var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "details-btn"); + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + observer.checkDisplayed("inlinesettings2@tests.mozilla.org"); + + var grid = gManagerWindow.document.getElementById("detail-grid"); + var settings = grid.querySelectorAll("rows > setting"); + ok(settings.length > 0, "Grid should have settings children"); + + // disable + var button = gManagerWindow.document.getElementById("detail-disable-btn"); + button.focus(); // make sure it's in view + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + observer.checkNotHidden(); + + settings = grid.querySelectorAll("rows > setting"); + ok(settings.length > 0, "Grid should still have settings children"); + + // cancel pending disable + button = gManagerWindow.document.getElementById("detail-enable-btn"); + button.focus(); // make sure it's in view + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + observer.checkNotDisplayed(); + + gCategoryUtilities.openType("extension", run_next_test); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_install.js b/toolkit/mozapps/extensions/test/browser/browser_install.js new file mode 100644 index 000000000..3f7d17d37 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_install.js @@ -0,0 +1,312 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests tha installs and undoing installs show up correctly + +var gManagerWindow; +var gCategoryUtilities; + +var gApp = document.getElementById("bundle_brand").getString("brandShortName"); +var gSearchCount = 0; + +function test() { + requestLongerTimeout(2); + waitForExplicitFinish(); + + // Turn on searching for this test + Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15); + Services.prefs.setCharPref("extensions.getAddons.search.url", TESTROOT + "browser_install.xml"); + // Allow http update checks + Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); + + open_manager(null, function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, function() { + Services.prefs.clearUserPref("extensions.checkUpdateSecurity"); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { + aAddon.uninstall(); + finish(); + }); + }); +} + +function get_node(parent, anonid) { + return parent.ownerDocument.getAnonymousElementByAttribute(parent, "anonid", anonid); +} + +function installAddon(aCallback) { + AddonManager.getInstallForURL(TESTROOT + "addons/browser_install1_2.xpi", + function(aInstall) { + aInstall.addListener({ + onInstallEnded: function() { + executeSoon(aCallback); + } + }); + aInstall.install(); + }, "application/x-xpinstall"); +} + +function installUpgrade(aCallback) { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { + aAddon.findUpdates({ + onUpdateAvailable: function(aAddon, aInstall) { + is(get_list_item_count(), 1, "Should be only one item in the list"); + + aInstall.addListener({ + onDownloadEnded: function() { + is(get_list_item_count(), 1, "Should be only one item in the list once the update has started"); + }, + onInstallEnded: function() { + executeSoon(aCallback); + } + }); + aInstall.install(); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} + +function cancelInstall(aCallback) { + AddonManager.getInstallForURL(TESTROOT + "addons/browser_install1_2.xpi", + function(aInstall) { + aInstall.addListener({ + onDownloadEnded: function(aInstall) { + executeSoon(function() { + aInstall.cancel(); + aCallback(); + }); + return false; + } + }); + aInstall.install(); + }, "application/x-xpinstall"); +} + +function installSearchResult(aCallback) { + var searchBox = gManagerWindow.document.getElementById("header-search"); + // Search for something different each time + searchBox.value = "foo" + gSearchCount; + gSearchCount++; + + EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow); + EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + let remote = gManagerWindow.document.getElementById("search-filter-remote") + EventUtils.synthesizeMouseAtCenter(remote, { }, gManagerWindow); + + let item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); + ok(!!item, "Should see the search result in the list"); + + let status = get_node(item, "install-status"); + EventUtils.synthesizeMouseAtCenter(get_node(status, "install-remote-btn"), {}, gManagerWindow); + + item.mInstall.addListener({ + onInstallEnded: function() { + executeSoon(aCallback); + } + }); + }); +} + +function get_list_item_count() { + return get_test_items_in_list(gManagerWindow).length; +} + +function check_undo_install() { + is(get_list_item_count(), 1, "Should be only one item in the list"); + + let item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); + ok(!!item, "Should see the pending install in the list"); + // Force XBL to apply + item.clientTop; + is_element_visible(get_node(item, "pending"), "Pending message should be visible"); + is(get_node(item, "pending").textContent, "Install Tests will be installed after you restart " + gApp + ".", "Pending message should be correct"); + + EventUtils.synthesizeMouseAtCenter(get_node(item, "undo-btn"), {}, gManagerWindow); + + is(get_list_item_count(), 0, "Should be no items in the list"); + + item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); + ok(!item, "Should no longer see the pending install"); +} + +function check_undo_upgrade() { + is(get_list_item_count(), 1, "Should be only one item in the list"); + + let item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); + ok(!!item, "Should see the pending upgrade in the list"); + // Force XBL to apply + item.clientTop; + is_element_visible(get_node(item, "pending"), "Pending message should be visible"); + is(get_node(item, "pending").textContent, "Install Tests will be updated after you restart " + gApp + ".", "Pending message should be correct"); + + EventUtils.synthesizeMouseAtCenter(get_node(item, "undo-btn"), {}, gManagerWindow); + + is(get_list_item_count(), 1, "Should be only one item in the list"); + + item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); + ok(!!item, "Should still see installed item in the list"); + is_element_hidden(get_node(item, "pending"), "Pending message should be hidden"); +} + +// Install an add-on through the API with the manager open +add_test(function() { + gCategoryUtilities.openType("extension", function() { + installAddon(function() { + check_undo_install(); + run_next_test(); + }); + }); +}); + +// Install an add-on with the manager closed then open it +add_test(function() { + close_manager(gManagerWindow, function() { + installAddon(function() { + open_manager(null, function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + check_undo_install(); + run_next_test(); + }); + }); + }); +}); + +// Install an add-on through the search page and then undo it +add_test(function() { + installSearchResult(function() { + check_undo_install(); + run_next_test(); + }); +}); + +// Install an add-on through the search page then switch to the extensions page +// and then undo it +add_test(function() { + installSearchResult(function() { + gCategoryUtilities.openType("extension", function() { + check_undo_install(); + run_next_test(); + }); + }); +}); + +// Install an add-on through the search page then re-open the manager and then +// undo it +add_test(function() { + installSearchResult(function() { + close_manager(gManagerWindow, function() { + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + check_undo_install(); + run_next_test(); + }); + }); + }); +}); + +// Cancel an install after download with the manager open +add_test(function() { + cancelInstall(function() { + is(get_list_item_count(), 0, "Should be no items in the list"); + + run_next_test(); + }); +}); + +// Cancel an install after download with the manager closed +add_test(function() { + close_manager(gManagerWindow, function() { + cancelInstall(function() { + open_manager(null, function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + is(get_list_item_count(), 0, "Should be no items in the list"); + + run_next_test(); + }); + }); + }); +}); + +// Install an existing add-on for the subsequent tests +add_test(function() { + AddonManager.getInstallForURL(TESTROOT + "addons/browser_install1_1.xpi", + function(aInstall) { + aInstall.addListener({ + onInstallEnded: run_next_test + }); + aInstall.install(); + }, "application/x-xpinstall"); +}); + +// Install an upgrade through the API with the manager open +add_test(function() { + installAddon(function() { + check_undo_upgrade(); + run_next_test(); + }); +}); + +// Install an upgrade through the API with the manager open +add_test(function() { + installUpgrade(function() { + check_undo_upgrade(); + run_next_test(); + }); +}); + +// Install an upgrade through the API with the manager closed +add_test(function() { + close_manager(gManagerWindow, function() { + installAddon(function() { + open_manager(null, function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + check_undo_upgrade(); + run_next_test(); + }); + }); + }); +}); + +// Cancel an upgrade after download with the manager open +add_test(function() { + cancelInstall(function() { + is(get_list_item_count(), 1, "Should be no items in the list"); + let item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); + ok(!!item, "Should still see installed item in the list"); + is_element_hidden(get_node(item, "pending"), "Pending message should be hidden"); + + run_next_test(); + }); +}); + +// Cancel an upgrade after download with the manager closed +add_test(function() { + close_manager(gManagerWindow, function() { + cancelInstall(function() { + open_manager(null, function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + is(get_list_item_count(), 1, "Should be no items in the list"); + let item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); + ok(!!item, "Should still see installed item in the list"); + is_element_hidden(get_node(item, "pending"), "Pending message should be hidden"); + + run_next_test(); + }); + }); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_install.rdf b/toolkit/mozapps/extensions/test/browser/browser_install.rdf new file mode 100644 index 000000000..7dc0477f0 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_install.rdf @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:extension:addon1@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>2.0</em:version> + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + <em:updateLink>https://example.com/browser/toolkit/mozapps/extensions/test/browser/browser_install1_3.xpi</em:updateLink> + <em:updateHash>sha1:6760e51269941245105a17076afeb5f45621de0e</em:updateHash> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/browser_install.rdf^headers^ b/toolkit/mozapps/extensions/test/browser/browser_install.rdf^headers^ new file mode 100644 index 000000000..2e4f8163b --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_install.rdf^headers^ @@ -0,0 +1 @@ +Connection: close diff --git a/toolkit/mozapps/extensions/test/browser/browser_install.xml b/toolkit/mozapps/extensions/test/browser/browser_install.xml new file mode 100644 index 000000000..84067a6a3 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_install.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8" ?> +<searchresults total_results="1"> + <addon> + <name>Install Tests</name> + <type id='1'>Extension</type> + <guid>addon1@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://example.com/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <summary>Test add-on</summary> + <description>Test add-on</description> + <compatible_applications> + <application> + <name>Firefox</name> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + <application> + <name>SeaMonkey</name> + <appID>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + </compatible_applications> + <compatible_os>ALL</compatible_os> + <install size="2">http://example.com/browser/toolkit/mozapps/extensions/test/browser/addons/browser_install1_2.xpi</install> + </addon> +</searchresults> diff --git a/toolkit/mozapps/extensions/test/browser/browser_install1_3.xpi b/toolkit/mozapps/extensions/test/browser/browser_install1_3.xpi Binary files differnew file mode 100644 index 000000000..31bb4b2a6 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_install1_3.xpi diff --git a/toolkit/mozapps/extensions/test/browser/browser_installssl.js b/toolkit/mozapps/extensions/test/browser/browser_installssl.js new file mode 100644 index 000000000..b0726ef9e --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_installssl.js @@ -0,0 +1,374 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +const xpi = RELATIVE_DIR + "addons/browser_installssl.xpi"; +const redirect = RELATIVE_DIR + "redirect.sjs?"; +const SUCCESS = 0; +const NETWORK_FAILURE = AddonManager.ERROR_NETWORK_FAILURE; + +const HTTP = "http://example.com/"; +const HTTPS = "https://example.com/"; +const NOCERT = "https://nocert.example.com/"; +const SELFSIGNED = "https://self-signed.example.com/"; +const UNTRUSTED = "https://untrusted.example.com/"; +const EXPIRED = "https://expired.example.com/"; + +const PREF_INSTALL_REQUIREBUILTINCERTS = "extensions.install.requireBuiltInCerts"; + +var gTests = []; +var gStart = 0; +var gLast = 0; +var gPendingInstall = null; + +function test() { + gStart = Date.now(); + requestLongerTimeout(4); + waitForExplicitFinish(); + + registerCleanupFunction(function() { + var cos = Cc["@mozilla.org/security/certoverride;1"]. + getService(Ci.nsICertOverrideService); + cos.clearValidityOverride("nocert.example.com", -1); + cos.clearValidityOverride("self-signed.example.com", -1); + cos.clearValidityOverride("untrusted.example.com", -1); + cos.clearValidityOverride("expired.example.com", -1); + + try { + Services.prefs.clearUserPref(PREF_INSTALL_REQUIREBUILTINCERTS); + } + catch (e) { + } + + if (gPendingInstall) { + gTests = []; + ok(false, "Timed out in the middle of downloading " + gPendingInstall.sourceURI.spec); + try { + gPendingInstall.cancel(); + } + catch (e) { + } + } + }); + + run_next_test(); +} + +function end_test() { + info("All tests completed in " + (Date.now() - gStart) + "ms"); + finish(); +} + +function add_install_test(mainURL, redirectURL, expectedStatus) { + gTests.push([mainURL, redirectURL, expectedStatus]); +} + +function run_install_tests(callback) { + function run_next_install_test() { + if (gTests.length == 0) { + callback(); + return; + } + gLast = Date.now(); + + let [mainURL, redirectURL, expectedStatus] = gTests.shift(); + if (redirectURL) { + var url = mainURL + redirect + redirectURL + xpi; + var message = "Should have seen the right result for an install redirected from " + + mainURL + " to " + redirectURL; + } + else { + url = mainURL + xpi; + message = "Should have seen the right result for an install from " + + mainURL; + } + + AddonManager.getInstallForURL(url, function(install) { + gPendingInstall = install; + install.addListener({ + onDownloadEnded: function(install) { + is(SUCCESS, expectedStatus, message); + info("Install test ran in " + (Date.now() - gLast) + "ms"); + // Don't proceed with the install + install.cancel(); + gPendingInstall = null; + run_next_install_test(); + return false; + }, + + onDownloadFailed: function(install) { + is(install.error, expectedStatus, message); + info("Install test ran in " + (Date.now() - gLast) + "ms"); + gPendingInstall = null; + run_next_install_test(); + } + }); + install.install(); + }, "application/x-xpinstall"); + } + + run_next_install_test(); +} + +// Add overrides for the bad certificates +function addCertOverrides() { + addCertOverride("nocert.example.com", Ci.nsICertOverrideService.ERROR_MISMATCH); + addCertOverride("self-signed.example.com", Ci.nsICertOverrideService.ERROR_UNTRUSTED); + addCertOverride("untrusted.example.com", Ci.nsICertOverrideService.ERROR_UNTRUSTED); + addCertOverride("expired.example.com", Ci.nsICertOverrideService.ERROR_TIME); +} + +// Runs tests with built-in certificates required, no certificate exceptions +// and no hashes +add_test(function() { + // Tests that a simple install works as expected. + add_install_test(HTTP, null, SUCCESS); + add_install_test(HTTPS, null, NETWORK_FAILURE); + add_install_test(NOCERT, null, NETWORK_FAILURE); + add_install_test(SELFSIGNED, null, NETWORK_FAILURE); + add_install_test(UNTRUSTED, null, NETWORK_FAILURE); + add_install_test(EXPIRED, null, NETWORK_FAILURE); + + // Tests that redirecting from http to other servers works as expected + add_install_test(HTTP, HTTP, SUCCESS); + add_install_test(HTTP, HTTPS, SUCCESS); + add_install_test(HTTP, NOCERT, NETWORK_FAILURE); + add_install_test(HTTP, SELFSIGNED, NETWORK_FAILURE); + add_install_test(HTTP, UNTRUSTED, NETWORK_FAILURE); + add_install_test(HTTP, EXPIRED, NETWORK_FAILURE); + + // Tests that redirecting from valid https to other servers works as expected + add_install_test(HTTPS, HTTP, NETWORK_FAILURE); + add_install_test(HTTPS, HTTPS, NETWORK_FAILURE); + add_install_test(HTTPS, NOCERT, NETWORK_FAILURE); + add_install_test(HTTPS, SELFSIGNED, NETWORK_FAILURE); + add_install_test(HTTPS, UNTRUSTED, NETWORK_FAILURE); + add_install_test(HTTPS, EXPIRED, NETWORK_FAILURE); + + // Tests that redirecting from nocert https to other servers works as expected + add_install_test(NOCERT, HTTP, NETWORK_FAILURE); + add_install_test(NOCERT, HTTPS, NETWORK_FAILURE); + add_install_test(NOCERT, NOCERT, NETWORK_FAILURE); + add_install_test(NOCERT, SELFSIGNED, NETWORK_FAILURE); + add_install_test(NOCERT, UNTRUSTED, NETWORK_FAILURE); + add_install_test(NOCERT, EXPIRED, NETWORK_FAILURE); + + // Tests that redirecting from self-signed https to other servers works as expected + add_install_test(SELFSIGNED, HTTP, NETWORK_FAILURE); + add_install_test(SELFSIGNED, HTTPS, NETWORK_FAILURE); + add_install_test(SELFSIGNED, NOCERT, NETWORK_FAILURE); + add_install_test(SELFSIGNED, SELFSIGNED, NETWORK_FAILURE); + add_install_test(SELFSIGNED, UNTRUSTED, NETWORK_FAILURE); + add_install_test(SELFSIGNED, EXPIRED, NETWORK_FAILURE); + + // Tests that redirecting from untrusted https to other servers works as expected + add_install_test(UNTRUSTED, HTTP, NETWORK_FAILURE); + add_install_test(UNTRUSTED, HTTPS, NETWORK_FAILURE); + add_install_test(UNTRUSTED, NOCERT, NETWORK_FAILURE); + add_install_test(UNTRUSTED, SELFSIGNED, NETWORK_FAILURE); + add_install_test(UNTRUSTED, UNTRUSTED, NETWORK_FAILURE); + add_install_test(UNTRUSTED, EXPIRED, NETWORK_FAILURE); + + // Tests that redirecting from expired https to other servers works as expected + add_install_test(EXPIRED, HTTP, NETWORK_FAILURE); + add_install_test(EXPIRED, HTTPS, NETWORK_FAILURE); + add_install_test(EXPIRED, NOCERT, NETWORK_FAILURE); + add_install_test(EXPIRED, SELFSIGNED, NETWORK_FAILURE); + add_install_test(EXPIRED, UNTRUSTED, NETWORK_FAILURE); + add_install_test(EXPIRED, EXPIRED, NETWORK_FAILURE); + + run_install_tests(run_next_test); +}); + +// Runs tests without requiring built-in certificates, no certificate +// exceptions and no hashes +add_test(function() { + Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false); + + // Tests that a simple install works as expected. + add_install_test(HTTP, null, SUCCESS); + add_install_test(HTTPS, null, SUCCESS); + add_install_test(NOCERT, null, NETWORK_FAILURE); + add_install_test(SELFSIGNED, null, NETWORK_FAILURE); + add_install_test(UNTRUSTED, null, NETWORK_FAILURE); + add_install_test(EXPIRED, null, NETWORK_FAILURE); + + // Tests that redirecting from http to other servers works as expected + add_install_test(HTTP, HTTP, SUCCESS); + add_install_test(HTTP, HTTPS, SUCCESS); + add_install_test(HTTP, NOCERT, NETWORK_FAILURE); + add_install_test(HTTP, SELFSIGNED, NETWORK_FAILURE); + add_install_test(HTTP, UNTRUSTED, NETWORK_FAILURE); + add_install_test(HTTP, EXPIRED, NETWORK_FAILURE); + + // Tests that redirecting from valid https to other servers works as expected + add_install_test(HTTPS, HTTP, NETWORK_FAILURE); + add_install_test(HTTPS, HTTPS, SUCCESS); + add_install_test(HTTPS, NOCERT, NETWORK_FAILURE); + add_install_test(HTTPS, SELFSIGNED, NETWORK_FAILURE); + add_install_test(HTTPS, UNTRUSTED, NETWORK_FAILURE); + add_install_test(HTTPS, EXPIRED, NETWORK_FAILURE); + + // Tests that redirecting from nocert https to other servers works as expected + add_install_test(NOCERT, HTTP, NETWORK_FAILURE); + add_install_test(NOCERT, HTTPS, NETWORK_FAILURE); + add_install_test(NOCERT, NOCERT, NETWORK_FAILURE); + add_install_test(NOCERT, SELFSIGNED, NETWORK_FAILURE); + add_install_test(NOCERT, UNTRUSTED, NETWORK_FAILURE); + add_install_test(NOCERT, EXPIRED, NETWORK_FAILURE); + + // Tests that redirecting from self-signed https to other servers works as expected + add_install_test(SELFSIGNED, HTTP, NETWORK_FAILURE); + add_install_test(SELFSIGNED, HTTPS, NETWORK_FAILURE); + add_install_test(SELFSIGNED, NOCERT, NETWORK_FAILURE); + add_install_test(SELFSIGNED, SELFSIGNED, NETWORK_FAILURE); + add_install_test(SELFSIGNED, UNTRUSTED, NETWORK_FAILURE); + add_install_test(SELFSIGNED, EXPIRED, NETWORK_FAILURE); + + // Tests that redirecting from untrusted https to other servers works as expected + add_install_test(UNTRUSTED, HTTP, NETWORK_FAILURE); + add_install_test(UNTRUSTED, HTTPS, NETWORK_FAILURE); + add_install_test(UNTRUSTED, NOCERT, NETWORK_FAILURE); + add_install_test(UNTRUSTED, SELFSIGNED, NETWORK_FAILURE); + add_install_test(UNTRUSTED, UNTRUSTED, NETWORK_FAILURE); + add_install_test(UNTRUSTED, EXPIRED, NETWORK_FAILURE); + + // Tests that redirecting from expired https to other servers works as expected + add_install_test(EXPIRED, HTTP, NETWORK_FAILURE); + add_install_test(EXPIRED, HTTPS, NETWORK_FAILURE); + add_install_test(EXPIRED, NOCERT, NETWORK_FAILURE); + add_install_test(EXPIRED, SELFSIGNED, NETWORK_FAILURE); + add_install_test(EXPIRED, UNTRUSTED, NETWORK_FAILURE); + add_install_test(EXPIRED, EXPIRED, NETWORK_FAILURE); + + run_install_tests(run_next_test); +}); + +// Runs tests with built-in certificates required, all certificate exceptions +// and no hashes +add_test(function() { + Services.prefs.clearUserPref(PREF_INSTALL_REQUIREBUILTINCERTS); + addCertOverrides(); + + // Tests that a simple install works as expected. + add_install_test(HTTP, null, SUCCESS); + add_install_test(HTTPS, null, NETWORK_FAILURE); + add_install_test(NOCERT, null, NETWORK_FAILURE); + add_install_test(SELFSIGNED, null, NETWORK_FAILURE); + add_install_test(UNTRUSTED, null, NETWORK_FAILURE); + add_install_test(EXPIRED, null, NETWORK_FAILURE); + + // Tests that redirecting from http to other servers works as expected + add_install_test(HTTP, HTTP, SUCCESS); + add_install_test(HTTP, HTTPS, SUCCESS); + add_install_test(HTTP, NOCERT, SUCCESS); + add_install_test(HTTP, SELFSIGNED, SUCCESS); + add_install_test(HTTP, UNTRUSTED, SUCCESS); + add_install_test(HTTP, EXPIRED, SUCCESS); + + // Tests that redirecting from valid https to other servers works as expected + add_install_test(HTTPS, HTTP, NETWORK_FAILURE); + add_install_test(HTTPS, HTTPS, NETWORK_FAILURE); + add_install_test(HTTPS, NOCERT, NETWORK_FAILURE); + add_install_test(HTTPS, SELFSIGNED, NETWORK_FAILURE); + add_install_test(HTTPS, UNTRUSTED, NETWORK_FAILURE); + add_install_test(HTTPS, EXPIRED, NETWORK_FAILURE); + + // Tests that redirecting from nocert https to other servers works as expected + add_install_test(NOCERT, HTTP, NETWORK_FAILURE); + add_install_test(NOCERT, HTTPS, NETWORK_FAILURE); + add_install_test(NOCERT, NOCERT, NETWORK_FAILURE); + add_install_test(NOCERT, SELFSIGNED, NETWORK_FAILURE); + add_install_test(NOCERT, UNTRUSTED, NETWORK_FAILURE); + add_install_test(NOCERT, EXPIRED, NETWORK_FAILURE); + + // Tests that redirecting from self-signed https to other servers works as expected + add_install_test(SELFSIGNED, HTTP, NETWORK_FAILURE); + add_install_test(SELFSIGNED, HTTPS, NETWORK_FAILURE); + add_install_test(SELFSIGNED, NOCERT, NETWORK_FAILURE); + add_install_test(SELFSIGNED, SELFSIGNED, NETWORK_FAILURE); + add_install_test(SELFSIGNED, UNTRUSTED, NETWORK_FAILURE); + add_install_test(SELFSIGNED, EXPIRED, NETWORK_FAILURE); + + // Tests that redirecting from untrusted https to other servers works as expected + add_install_test(UNTRUSTED, HTTP, NETWORK_FAILURE); + add_install_test(UNTRUSTED, HTTPS, NETWORK_FAILURE); + add_install_test(UNTRUSTED, NOCERT, NETWORK_FAILURE); + add_install_test(UNTRUSTED, SELFSIGNED, NETWORK_FAILURE); + add_install_test(UNTRUSTED, UNTRUSTED, NETWORK_FAILURE); + add_install_test(UNTRUSTED, EXPIRED, NETWORK_FAILURE); + + // Tests that redirecting from expired https to other servers works as expected + add_install_test(EXPIRED, HTTP, NETWORK_FAILURE); + add_install_test(EXPIRED, HTTPS, NETWORK_FAILURE); + add_install_test(EXPIRED, NOCERT, NETWORK_FAILURE); + add_install_test(EXPIRED, SELFSIGNED, NETWORK_FAILURE); + add_install_test(EXPIRED, UNTRUSTED, NETWORK_FAILURE); + add_install_test(EXPIRED, EXPIRED, NETWORK_FAILURE); + + run_install_tests(run_next_test); +}); + +// Runs tests without requiring built-in certificates, all certificate +// exceptions and no hashes +add_test(function() { + Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false); + + // Tests that a simple install works as expected. + add_install_test(HTTP, null, SUCCESS); + add_install_test(HTTPS, null, SUCCESS); + add_install_test(NOCERT, null, SUCCESS); + add_install_test(SELFSIGNED, null, SUCCESS); + add_install_test(UNTRUSTED, null, SUCCESS); + add_install_test(EXPIRED, null, SUCCESS); + + // Tests that redirecting from http to other servers works as expected + add_install_test(HTTP, HTTP, SUCCESS); + add_install_test(HTTP, HTTPS, SUCCESS); + add_install_test(HTTP, NOCERT, SUCCESS); + add_install_test(HTTP, SELFSIGNED, SUCCESS); + add_install_test(HTTP, UNTRUSTED, SUCCESS); + add_install_test(HTTP, EXPIRED, SUCCESS); + + // Tests that redirecting from valid https to other servers works as expected + add_install_test(HTTPS, HTTP, NETWORK_FAILURE); + add_install_test(HTTPS, HTTPS, SUCCESS); + add_install_test(HTTPS, NOCERT, SUCCESS); + add_install_test(HTTPS, SELFSIGNED, SUCCESS); + add_install_test(HTTPS, UNTRUSTED, SUCCESS); + add_install_test(HTTPS, EXPIRED, SUCCESS); + + // Tests that redirecting from nocert https to other servers works as expected + add_install_test(NOCERT, HTTP, NETWORK_FAILURE); + add_install_test(NOCERT, HTTPS, SUCCESS); + add_install_test(NOCERT, NOCERT, SUCCESS); + add_install_test(NOCERT, SELFSIGNED, SUCCESS); + add_install_test(NOCERT, UNTRUSTED, SUCCESS); + add_install_test(NOCERT, EXPIRED, SUCCESS); + + // Tests that redirecting from self-signed https to other servers works as expected + add_install_test(SELFSIGNED, HTTP, NETWORK_FAILURE); + add_install_test(SELFSIGNED, HTTPS, SUCCESS); + add_install_test(SELFSIGNED, NOCERT, SUCCESS); + add_install_test(SELFSIGNED, SELFSIGNED, SUCCESS); + add_install_test(SELFSIGNED, UNTRUSTED, SUCCESS); + add_install_test(SELFSIGNED, EXPIRED, SUCCESS); + + // Tests that redirecting from untrusted https to other servers works as expected + add_install_test(UNTRUSTED, HTTP, NETWORK_FAILURE); + add_install_test(UNTRUSTED, HTTPS, SUCCESS); + add_install_test(UNTRUSTED, NOCERT, SUCCESS); + add_install_test(UNTRUSTED, SELFSIGNED, SUCCESS); + add_install_test(UNTRUSTED, UNTRUSTED, SUCCESS); + add_install_test(UNTRUSTED, EXPIRED, SUCCESS); + + // Tests that redirecting from expired https to other servers works as expected + add_install_test(EXPIRED, HTTP, NETWORK_FAILURE); + add_install_test(EXPIRED, HTTPS, SUCCESS); + add_install_test(EXPIRED, NOCERT, SUCCESS); + add_install_test(EXPIRED, SELFSIGNED, SUCCESS); + add_install_test(EXPIRED, UNTRUSTED, SUCCESS); + add_install_test(EXPIRED, EXPIRED, SUCCESS); + + run_install_tests(run_next_test); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_list.js b/toolkit/mozapps/extensions/test/browser/browser_list.js new file mode 100644 index 000000000..fd6cfed7e --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_list.js @@ -0,0 +1,760 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests the list view + +let tempScope = {}; +Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", tempScope); +let LightweightThemeManager = tempScope.LightweightThemeManager; + + +var gProvider; +var gManagerWindow; +var gCategoryUtilities; + +var gApp = document.getElementById("bundle_brand").getString("brandShortName"); +var gVersion = Services.appinfo.version; +var gBlocklistURL = Services.urlFormatter.formatURLPref("extensions.blocklist.detailsURL"); +var gPluginURL = Services.urlFormatter.formatURLPref("plugins.update.url"); +var gDate = new Date(2010, 7, 16); + +var gLWTheme = { + id: "4", + version: "1", + name: "Bling", + description: "SO MUCH BLING!", + author: "Pixel Pusher", + homepageURL: "http://mochi.test:8888/data/index.html", + headerURL: "http://mochi.test:8888/data/header.png", + footerURL: "http://mochi.test:8888/data/footer.png", + previewURL: "http://mochi.test:8888/data/preview.png", + iconURL: "http://mochi.test:8888/data/icon.png" + }; + + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + gProvider.createAddons([{ + id: "addon1@tests.mozilla.org", + name: "Test add-on", + version: "1.0", + description: "A test add-on", + longDescription: " A longer description", + updateDate: gDate + }, { + id: "addon2@tests.mozilla.org", + name: "Test add-on 2", + version: "2.0", + longDescription: " A longer description", + _userDisabled: true, + isActive: false, + }, { + id: "addon3@tests.mozilla.org", + name: "Test add-on 3", + longDescription: " A longer description", + isActive: false, + isCompatible: false, + appDisabled: true, + permissions: AddonManager.PERM_CAN_ENABLE | + AddonManager.PERM_CAN_DISABLE | + AddonManager.PERM_CAN_UPGRADE + }, { + id: "addon4@tests.mozilla.org", + blocklistURL: "http://example.com/addon4@tests.mozilla.org", + name: "Test add-on 4", + _userDisabled: true, + isActive: false, + blocklistState: Ci.nsIBlocklistService.STATE_SOFTBLOCKED + }, { + id: "addon5@tests.mozilla.org", + blocklistURL: "http://example.com/addon5@tests.mozilla.org", + name: "Test add-on 5", + isActive: false, + blocklistState: Ci.nsIBlocklistService.STATE_BLOCKED, + appDisabled: true + }, { + id: "addon6@tests.mozilla.org", + blocklistURL: "http://example.com/addon6@tests.mozilla.org", + name: "Test add-on 6", + operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE + }, { + id: "addon7@tests.mozilla.org", + blocklistURL: "http://example.com/addon7@tests.mozilla.org", + name: "Test add-on 7", + blocklistState: Ci.nsIBlocklistService.STATE_OUTDATED, + }, { + id: "addon8@tests.mozilla.org", + blocklistURL: "http://example.com/addon8@tests.mozilla.org", + name: "Test add-on 8", + blocklistState: Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE, + }, { + id: "addon9@tests.mozilla.org", + blocklistURL: "http://example.com/addon9@tests.mozilla.org", + name: "Test add-on 9", + blocklistState: Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE, + }]); + + open_manager(null, function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, function() { + finish(); + }); +} + +function get_test_items() { + var tests = "@tests.mozilla.org"; + + var items = {}; + var item = gManagerWindow.document.getElementById("addon-list").firstChild; + + while (item) { + if (item.mAddon.id.substring(item.mAddon.id.length - tests.length) == tests) + items[item.mAddon.name] = item; + item = item.nextSibling; + } + + return items; +} + +function get_node(parent, anonid) { + return parent.ownerDocument.getAnonymousElementByAttribute(parent, "anonid", anonid); +} + +function get_class_node(parent, cls) { + return parent.ownerDocument.getAnonymousElementByAttribute(parent, "class", cls); +} + +// Check that the list appears to have displayed correctly and trigger some +// changes +add_test(function() { + gCategoryUtilities.openType("extension", function() { + let items = get_test_items(); + is(Object.keys(items).length, 9, "Should be nine add-ons installed"); + + info("Addon 1"); + let addon = items["Test add-on"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on", "Name should be correct"); + is_element_visible(get_node(addon, "version"), "Version should be visible"); + is(get_node(addon, "version").value, "1.0", "Version should be correct"); + is_element_visible(get_node(addon, "description"), "Description should be visible"); + is(get_node(addon, "description").value, "A test add-on", "Description should be correct"); + is_element_hidden(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be hidden"); + is_element_hidden(get_class_node(addon, "update-postfix"), "Update postfix should be hidden"); + is(get_node(addon, "date-updated").value, formatDate(gDate), "Update date should be correct"); + + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + + info("Disabling"); + EventUtils.synthesizeMouseAtCenter(get_node(addon, "disable-btn"), {}, gManagerWindow); + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); + is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be visible"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_visible(get_node(addon, "pending"), "Pending message should be visible"); + is(get_node(addon, "pending").textContent, "Test add-on will be disabled after you restart " + gApp + ".", "Pending message should be correct"); + + info("Addon 2"); + addon = items["Test add-on 2"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on 2", "Name should be correct"); + is_element_visible(get_node(addon, "version"), "Version should be visible"); + is(get_node(addon, "version").value, "2.0", "Version should be correct"); + is_element_hidden(get_node(addon, "description"), "Description should be hidden"); + is_element_visible(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be visible"); + is_element_hidden(get_class_node(addon, "update-postfix"), "Update postfix should be hidden"); + is(get_node(addon, "date-updated").value, "Unknown", "Date should be correct"); + + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); + is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + + info("Enabling"); + EventUtils.synthesizeMouseAtCenter(get_node(addon, "enable-btn"), {}, gManagerWindow); + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_visible(get_node(addon, "pending"), "Pending message should be visible"); + is(get_node(addon, "pending").textContent, "Test add-on 2 will be enabled after you restart " + gApp + ".", "Pending message should be correct"); + + info("Addon 3"); + addon = items["Test add-on 3"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on 3", "Name should be correct"); + is_element_hidden(get_node(addon, "version"), "Version should be hidden"); + + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); + is_element_hidden(get_node(addon, "remove-btn"), "Remove button should be hidden"); + + is_element_visible(get_node(addon, "warning"), "Warning message should be visible"); + is(get_node(addon, "warning").textContent, "Test add-on 3 is incompatible with " + gApp + " " + gVersion + ".", "Warning message should be correct"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + + info("Addon 4"); + addon = items["Test add-on 4"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on 4", "Name should be correct"); + + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); + is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_visible(get_node(addon, "warning"), "Warning message should be visible"); + is(get_node(addon, "warning").textContent, "Test add-on 4 is known to cause security or stability issues.", "Warning message should be correct"); + is_element_visible(get_node(addon, "warning-link"), "Warning link should be visible"); + is(get_node(addon, "warning-link").value, "More Information", "Warning link text should be correct"); + is(get_node(addon, "warning-link").href, "http://example.com/addon4@tests.mozilla.org", "Warning link should be correct"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + + info("Enabling"); + EventUtils.synthesizeMouseAtCenter(get_node(addon, "enable-btn"), {}, gManagerWindow); + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_visible(get_node(addon, "pending"), "Pending message should be visible"); + is(get_node(addon, "pending").textContent, "Test add-on 4 will be enabled after you restart " + gApp + ".", "Pending message should be correct"); + + info("Addon 5"); + addon = items["Test add-on 5"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on 5", "Name should be correct"); + + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_visible(get_node(addon, "error"), "Error message should be visible"); + is(get_node(addon, "error").textContent, "Test add-on 5 has been disabled due to security or stability issues.", "Error message should be correct"); + is_element_visible(get_node(addon, "error-link"), "Error link should be visible"); + is(get_node(addon, "error-link").value, "More Information", "Error link text should be correct"); + is(get_node(addon, "error-link").href, "http://example.com/addon5@tests.mozilla.org", "Error link should be correct"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + + info("Addon 6"); + addon = items["Test add-on 6"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on 6", "Name should be correct"); + is_element_hidden(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be hidden"); + + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be visible"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + + info("Disabling"); + EventUtils.synthesizeMouseAtCenter(get_node(addon, "disable-btn"), {}, gManagerWindow); + is_element_visible(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be visible"); + + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); + is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be visible"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + + info("Addon 7"); + addon = items["Test add-on 7"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on 7", "Name should be correct"); + + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_visible(get_node(addon, "warning"), "Warning message should be hidden"); + is(get_node(addon, "warning").textContent, "An important update is available for Test add-on 7.", "Warning message should be correct"); + is_element_visible(get_node(addon, "warning-link"), "Warning link should be visible"); + is(get_node(addon, "warning-link").value, "Update Now", "Warning link text should be correct"); + is(get_node(addon, "warning-link").href, gPluginURL, "Warning link should be correct"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + + info("Disabling"); + EventUtils.synthesizeMouseAtCenter(get_node(addon, "disable-btn"), {}, gManagerWindow); + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); + is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be visible"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_visible(get_node(addon, "pending"), "Pending message should be visible"); + is(get_node(addon, "pending").textContent, "Test add-on 7 will be disabled after you restart " + gApp + ".", "Pending message should be correct"); + + info("Addon 8"); + addon = items["Test add-on 8"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on 8", "Name should be correct"); + + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_visible(get_node(addon, "error"), "Error message should be visible"); + is(get_node(addon, "error").textContent, "Test add-on 8 is known to be vulnerable and should be updated.", "Error message should be correct"); + is_element_visible(get_node(addon, "error-link"), "Error link should be visible"); + is(get_node(addon, "error-link").value, "Update Now", "Error link text should be correct"); + is(get_node(addon, "error-link").href, "http://example.com/addon8@tests.mozilla.org", "Error link should be correct"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + + info("Addon 9"); + addon = items["Test add-on 9"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on 9", "Name should be correct"); + + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_visible(get_node(addon, "error"), "Error message should be visible"); + is(get_node(addon, "error").textContent, "Test add-on 9 is known to be vulnerable. Use with caution.", "Error message should be correct"); + is_element_visible(get_node(addon, "error-link"), "Error link should be visible"); + is(get_node(addon, "error-link").value, "More Information", "Error link text should be correct"); + is(get_node(addon, "error-link").href, "http://example.com/addon9@tests.mozilla.org", "Error link should be correct"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + + run_next_test(); + }); +}); + +// Check the add-ons are now in the right state +add_test(function() { + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon6@tests.mozilla.org"], + function([a1, a2, a4, a6]) { + is(a1.pendingOperations, AddonManager.PENDING_DISABLE, "Add-on 1 should be pending disable"); + is(a2.pendingOperations, AddonManager.PENDING_ENABLE, "Add-on 2 should be pending enable"); + is(a4.pendingOperations, AddonManager.PENDING_ENABLE, "Add-on 4 should be pending enable"); + + run_next_test(); + }); +}); + +// Reload the list to make sure the changes are still pending and that undoing +// works +add_test(function() { + gCategoryUtilities.openType("plugin", function() { + gCategoryUtilities.openType("extension", function() { + let items = get_test_items(); + is(Object.keys(items).length, 9, "Should be nine add-ons installed"); + + info("Addon 1"); + let addon = items["Test add-on"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on", "Name should be correct"); + is_element_visible(get_node(addon, "version"), "Version should be visible"); + is(get_node(addon, "version").value, "1.0", "Version should be correct"); + is_element_visible(get_node(addon, "description"), "Description should be visible"); + is(get_node(addon, "description").value, "A test add-on", "Description should be correct"); + is_element_hidden(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be hidden"); + is_element_hidden(get_class_node(addon, "update-postfix"), "Update postfix should be hidden"); + is(get_node(addon, "date-updated").value, formatDate(gDate), "Update date should be correct"); + + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); + is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_visible(get_node(addon, "pending"), "Pending message should be visible"); + is(get_node(addon, "pending").textContent, "Test add-on will be disabled after you restart " + gApp + ".", "Pending message should be correct"); + + info("Undoing"); + EventUtils.synthesizeMouseAtCenter(get_node(addon, "undo-btn"), {}, gManagerWindow); + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + + info("Addon 2"); + addon = items["Test add-on 2"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on 2", "Name should be correct"); + is_element_visible(get_node(addon, "version"), "Version should be visible"); + is(get_node(addon, "version").value, "2.0", "Version should be correct"); + is_element_hidden(get_node(addon, "description"), "Description should be hidden"); + is_element_visible(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be visible"); + is_element_hidden(get_class_node(addon, "update-postfix"), "Update postfix should be hidden"); + is(get_node(addon, "date-updated").value, "Unknown", "Date should be correct"); + + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_visible(get_node(addon, "pending"), "Pending message should be visible"); + is(get_node(addon, "pending").textContent, "Test add-on 2 will be enabled after you restart " + gApp + ".", "Pending message should be correct"); + + info("Undoing"); + EventUtils.synthesizeMouseAtCenter(get_node(addon, "undo-btn"), {}, gManagerWindow); + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); + is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + + info("Addon 4"); + addon = items["Test add-on 4"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on 4", "Name should be correct"); + + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_visible(get_node(addon, "pending"), "Pending message should be visible"); + is(get_node(addon, "pending").textContent, "Test add-on 4 will be enabled after you restart " + gApp + ".", "Pending message should be correct"); + + info("Undoing"); + EventUtils.synthesizeMouseAtCenter(get_node(addon, "undo-btn"), {}, gManagerWindow); + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); + is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_visible(get_node(addon, "warning"), "Warning message should be visible"); + is(get_node(addon, "warning").textContent, "Test add-on 4 is known to cause security or stability issues.", "Warning message should be correct"); + is_element_visible(get_node(addon, "warning-link"), "Warning link should be visible"); + is(get_node(addon, "warning-link").value, "More Information", "Warning link text should be correct"); + is(get_node(addon, "warning-link").href, "http://example.com/addon4@tests.mozilla.org", "Warning link should be correct"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + + info("Addon 6"); + addon = items["Test add-on 6"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on 6", "Name should be correct"); + is_element_visible(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be visible"); + + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); + is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be visible"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + + info("Enabling"); + EventUtils.synthesizeMouseAtCenter(get_node(addon, "enable-btn"), {}, gManagerWindow); + is_element_hidden(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be hidden"); + + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be visible"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + + info("Addon 7"); + addon = items["Test add-on 7"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on 7", "Name should be correct"); + + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible"); + is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be visible"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_visible(get_node(addon, "pending"), "Pending message should be visible"); + is(get_node(addon, "pending").textContent, "Test add-on 7 will be disabled after you restart " + gApp + ".", "Pending message should be correct"); + + info("Undoing"); + EventUtils.synthesizeMouseAtCenter(get_node(addon, "undo-btn"), {}, gManagerWindow); + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_visible(get_node(addon, "warning"), "Warning message should be hidden"); + is(get_node(addon, "warning").textContent, "An important update is available for Test add-on 7.", "Warning message should be correct"); + is_element_visible(get_node(addon, "warning-link"), "Warning link should be visible"); + is(get_node(addon, "warning-link").value, "Update Now", "Warning link text should be correct"); + is(get_node(addon, "warning-link").href, gPluginURL, "Warning link should be correct"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + + run_next_test(); + }); + }); +}); + +// Check the add-ons are now in the right state +add_test(function() { + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon4@tests.mozilla.org"], + function([a1, a2, a4]) { + is(a1.pendingOperations, 0, "Add-on 1 should not have any pending operations"); + is(a2.pendingOperations, 0, "Add-on 1 should not have any pending operations"); + is(a4.pendingOperations, 0, "Add-on 1 should not have any pending operations"); + + run_next_test(); + }); +}); + +// Check that upgrades with onExternalInstall take effect immediately +add_test(function() { + gProvider.createAddons([{ + id: "addon1@tests.mozilla.org", + name: "Test add-on replacement", + version: "2.0", + description: "A test add-on with a new description", + updateDate: gDate, + operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE + }]); + + let items = get_test_items(); + is(Object.keys(items).length, 9, "Should be nine add-ons installed"); + + let addon = items["Test add-on replacement"]; + addon.parentNode.ensureElementIsVisible(addon); + is(get_node(addon, "name").value, "Test add-on replacement", "Name should be correct"); + is_element_visible(get_node(addon, "version"), "Version should be visible"); + is(get_node(addon, "version").value, "2.0", "Version should be correct"); + is_element_visible(get_node(addon, "description"), "Description should be visible"); + is(get_node(addon, "description").value, "A test add-on with a new description", "Description should be correct"); + is_element_hidden(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be hidden"); + is_element_hidden(get_class_node(addon, "update-postfix"), "Update postfix should be hidden"); + is(get_node(addon, "date-updated").value, formatDate(gDate), "Update date should be correct"); + + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden"); + is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden"); + is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); + is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); + is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); + + run_next_test(); +}); + +// Check that focus changes correctly move around the selected list item +add_test(function() { + function is_node_in_list(aNode) { + var list = gManagerWindow.document.getElementById("addon-list"); + + while (aNode && aNode != list) + aNode = aNode.parentNode; + + if (aNode) + return true; + return false; + } + + // Ignore the OSX full keyboard access setting + Services.prefs.setBoolPref("accessibility.tabfocus_applies_to_xul", false); + + let items = get_test_items(); + + var fm = Cc["@mozilla.org/focus-manager;1"]. + getService(Ci.nsIFocusManager); + + let addon = items["Test add-on 6"]; + EventUtils.synthesizeMouseAtCenter(addon, { }, gManagerWindow); + is(fm.focusedElement, addon.parentNode, "Focus should have moved to the list"); + + EventUtils.synthesizeKey("VK_TAB", { }, gManagerWindow); + is(fm.focusedElement, get_node(addon, "details-btn"), "Focus should have moved to the more button"); + + EventUtils.synthesizeKey("VK_TAB", { }, gManagerWindow); + is(fm.focusedElement, get_node(addon, "disable-btn"), "Focus should have moved to the disable button"); + + EventUtils.synthesizeKey("VK_TAB", { }, gManagerWindow); + is(fm.focusedElement, get_node(addon, "remove-btn"), "Focus should have moved to the remove button"); + + EventUtils.synthesizeKey("VK_TAB", { }, gManagerWindow); + ok(!is_node_in_list(fm.focusedElement), "Focus should be outside the list"); + + EventUtils.synthesizeKey("VK_TAB", { shiftKey: true }, gManagerWindow); + is(fm.focusedElement, get_node(addon, "remove-btn"), "Focus should have moved to the remove button"); + + EventUtils.synthesizeKey("VK_TAB", { shiftKey: true }, gManagerWindow); + EventUtils.synthesizeKey("VK_TAB", { shiftKey: true }, gManagerWindow); + is(fm.focusedElement, get_node(addon, "details-btn"), "Focus should have moved to the more button"); + + EventUtils.synthesizeKey("VK_TAB", { shiftKey: true }, gManagerWindow); + is(fm.focusedElement, addon.parentNode, "Focus should have moved to the list"); + + EventUtils.synthesizeKey("VK_TAB", { shiftKey: true }, gManagerWindow); + ok(!is_node_in_list(fm.focusedElement), "Focus should be outside the list"); + + try { + Services.prefs.clearUserPref("accessibility.tabfocus_applies_to_xul"); + } + catch (e) { } + + run_next_test(); +}); + + +add_test(function() { + info("Enabling lightweight theme"); + LightweightThemeManager.currentTheme = gLWTheme; + + gManagerWindow.loadView("addons://list/theme"); + wait_for_view_load(gManagerWindow, function() { + var addon = get_addon_element(gManagerWindow, "4@personas.mozilla.org"); + + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + info("Disabling lightweight theme"); + LightweightThemeManager.currentTheme = null; + + is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden"); + is_element_visible(get_node(addon, "enable-btn"), "Enable button should be hidden"); + is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be visible"); + is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible"); + + AddonManager.getAddonByID("4@personas.mozilla.org", function(aAddon) { + aAddon.uninstall(); + run_next_test(); + }); + }); +}); + +// Check that onPropertyChanges for appDisabled updates the UI +add_test(function() { + info("Checking that onPropertyChanges for appDisabled updates the UI"); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(aAddon) { + aAddon.userDisabled = true; + aAddon.isCompatible = true; + aAddon.appDisabled = false; + + gManagerWindow.loadView("addons://list/extension"); + wait_for_view_load(gManagerWindow, function() { + var el = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org"); + + is(el.getAttribute("active"), "false", "Addon should not be marked as active"); + is_element_hidden(get_node(el, "warning"), "Warning message should not be visible"); + + info("Making addon incompatible and appDisabled"); + aAddon.isCompatible = false; + aAddon.appDisabled = true; + + is(el.getAttribute("active"), "false", "Addon should not be marked as active"); + is_element_visible(get_node(el, "warning"), "Warning message should be visible"); + is(get_node(el, "warning").textContent, "Test add-on 2 is incompatible with " + gApp + " " + gVersion + ".", "Warning message should be correct"); + + run_next_test(); + }); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_manualupdates.js b/toolkit/mozapps/extensions/test/browser/browser_manualupdates.js new file mode 100644 index 000000000..27a4a6cd8 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_manualupdates.js @@ -0,0 +1,242 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests manual updates, including the Available Updates pane + +var gProvider; +var gManagerWindow; +var gCategoryUtilities; +var gAvailableCategory; + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + gProvider.createAddons([{ + id: "addon1@tests.mozilla.org", + name: "auto updating addon", + version: "1.0", + applyBackgroundUpdates: AddonManager.AUTOUPDATE_ENABLE + }]); + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, function() { + finish(); + }); +} + + +add_test(function() { + gAvailableCategory = gManagerWindow.gCategories.get("addons://updates/available"); + is(gCategoryUtilities.isVisible(gAvailableCategory), false, "Available Updates category should initially be hidden"); + + gProvider.createAddons([{ + id: "addon2@tests.mozilla.org", + name: "manually updating addon", + version: "1.0", + isCompatible: false, + blocklistState: Ci.nsIBlocklistService.STATE_BLOCKED, + applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE + }]); + + is(gCategoryUtilities.isVisible(gAvailableCategory), false, "Available Updates category should still be hidden"); + + run_next_test(); +}); + + +add_test(function() { + gAvailableCategory.addEventListener("CategoryBadgeUpdated", function() { + gAvailableCategory.removeEventListener("CategoryBadgeUpdated", arguments.callee, false); + is(gCategoryUtilities.isVisible(gAvailableCategory), true, "Available Updates category should now be visible"); + is(gAvailableCategory.badgeCount, 1, "Badge for Available Updates should now be 1"); + run_next_test(); + }, false); + + gCategoryUtilities.openType("extension", function() { + gProvider.createInstalls([{ + name: "manually updating addon (new and improved!)", + existingAddon: gProvider.addons[1], + version: "1.1", + releaseNotesURI: Services.io.newURI(TESTROOT + "thereIsNoFileHere.xhtml", null, null) + }]); + + var item = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org"); + is(item._version.value, "1.0", "Should still show the old version in the normal list"); + }); +}); + + +add_test(function() { + wait_for_view_load(gManagerWindow, function() { + is(gManagerWindow.document.getElementById("categories").selectedItem.value, "addons://updates/available", "Available Updates category should now be selected"); + is(gManagerWindow.gViewController.currentViewId, "addons://updates/available", "Available Updates view should be the current view"); + run_next_test(); + }, true); + EventUtils.synthesizeMouseAtCenter(gAvailableCategory, { }, gManagerWindow); +}); + + +add_test(function() { + var list = gManagerWindow.document.getElementById("updates-list"); + is(list.itemCount, 1, "Should be 1 available update listed"); + var item = list.firstChild; + is(item.mAddon.id, "addon2@tests.mozilla.org", "Update item should be for the manually updating addon"); + + // for manual update items, update-related properties are updated asynchronously, + // so we poll for one of the expected changes to know when its done + function waitForAsyncInit() { + if (item._version.value == "1.1") { + run_next_test(); + return; + } + info("Update item not initialized yet, checking again in 100ms"); + setTimeout(waitForAsyncInit, 100); + } + waitForAsyncInit(); +}); + +add_test(function() { + var list = gManagerWindow.document.getElementById("updates-list"); + var item = list.firstChild; + is(item._version.value, "1.1", "Update item should have version number of the update"); + var postfix = gManagerWindow.document.getAnonymousElementByAttribute(item, "class", "update-postfix"); + is_element_visible(postfix, "'Update' postfix should be visible"); + is_element_visible(item._updateAvailable, ""); + is_element_visible(item._relNotesToggle, "Release notes toggle should be visible"); + is_element_hidden(item._warning, "Incompatible warning should be hidden"); + is_element_hidden(item._error, "Blocklist error should be hidden"); + + info("Opening release notes"); + item.addEventListener("RelNotesToggle", function() { + item.removeEventListener("RelNotesToggle", arguments.callee, false); + info("Release notes now open"); + + is_element_hidden(item._relNotesLoading, "Release notes loading message should be hidden"); + is_element_visible(item._relNotesError, "Release notes error message should be visible"); + is(item._relNotes.childElementCount, 0, "Release notes should be empty"); + + info("Closing release notes"); + item.addEventListener("RelNotesToggle", function() { + item.removeEventListener("RelNotesToggle", arguments.callee, false); + info("Release notes now closed"); + info("Setting Release notes URI to something that should load"); + gProvider.installs[0].releaseNotesURI = Services.io.newURI(TESTROOT + "releaseNotes.xhtml", null, null) + + info("Re-opening release notes"); + item.addEventListener("RelNotesToggle", function() { + item.removeEventListener("RelNotesToggle", arguments.callee, false); + info("Release notes now open"); + + is_element_hidden(item._relNotesLoading, "Release notes loading message should be hidden"); + is_element_hidden(item._relNotesError, "Release notes error message should be hidden"); + isnot(item._relNotes.childElementCount, 0, "Release notes should have been inserted into container"); + run_next_test(); + + }, false); + EventUtils.synthesizeMouseAtCenter(item._relNotesToggle, { }, gManagerWindow); + is_element_visible(item._relNotesLoading, "Release notes loading message should be visible"); + + }, false); + EventUtils.synthesizeMouseAtCenter(item._relNotesToggle, { }, gManagerWindow); + + }, false); + EventUtils.synthesizeMouseAtCenter(item._relNotesToggle, { }, gManagerWindow); + is_element_visible(item._relNotesLoading, "Release notes loading message should be visible"); +}); + + +add_test(function() { + var badgeUpdated = false; + var installCompleted = false; + + gAvailableCategory.addEventListener("CategoryBadgeUpdated", function() { + gAvailableCategory.removeEventListener("CategoryBadgeUpdated", arguments.callee, false); + if (installCompleted) + run_next_test(); + else + badgeUpdated = true; + }, false); + + var list = gManagerWindow.document.getElementById("updates-list"); + var item = list.firstChild; + var updateBtn = item._updateBtn; + is_element_visible(updateBtn, "Update button should be visible"); + + var install = gProvider.installs[0]; + var listener = { + onInstallStarted: function() { + info("Install started"); + is_element_visible(item._installStatus, "Install progress widget should be visible"); + }, + onInstallEnded: function() { + install.removeTestListener(this); + info("Install ended"); + is_element_hidden(item._installStatus, "Install progress widget should be hidden"); + + if (badgeUpdated) + run_next_test(); + else + installCompleted = true; + } + }; + install.addTestListener(listener); + EventUtils.synthesizeMouseAtCenter(updateBtn, { }, gManagerWindow); +}); + + +add_test(function() { + is(gCategoryUtilities.isVisible(gAvailableCategory), true, "Available Updates category should still be visible"); + is(gAvailableCategory.badgeCount, 0, "Badge for Available Updates should now be 0"); + + gCategoryUtilities.openType("extension", function() { + is(gCategoryUtilities.isVisible(gAvailableCategory), false, "Available Updates category should be hidden"); + + close_manager(gManagerWindow, function() { + open_manager(null, function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + gAvailableCategory = gManagerWindow.gCategories.get("addons://updates/available"); + + is(gCategoryUtilities.isVisible(gAvailableCategory), false, "Available Updates category should be hidden"); + + run_next_test(); + }); + }); + }); +}); + +add_test(function() { + gAvailableCategory.addEventListener("CategoryBadgeUpdated", function() { + gAvailableCategory.removeEventListener("CategoryBadgeUpdated", arguments.callee, false); + is(gCategoryUtilities.isVisible(gAvailableCategory), true, "Available Updates category should now be visible"); + is(gAvailableCategory.badgeCount, 1, "Badge for Available Updates should now be 1"); + + gAvailableCategory.addEventListener("CategoryBadgeUpdated", function() { + gAvailableCategory.removeEventListener("CategoryBadgeUpdated", arguments.callee, false); + is(gCategoryUtilities.isVisible(gAvailableCategory), false, "Available Updates category should now be hidden"); + + run_next_test(); + }, false); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(aAddon) { + aAddon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_ENABLE; + }); + }, false); + + gProvider.createInstalls([{ + name: "manually updating addon (new and even more improved!)", + existingAddon: gProvider.addons[1], + version: "1.2", + releaseNotesURI: Services.io.newURI(TESTROOT + "thereIsNoFileHere.xhtml", null, null) + }]); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_metadataTimeout.js b/toolkit/mozapps/extensions/test/browser/browser_metadataTimeout.js new file mode 100644 index 000000000..e2aae6c13 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_metadataTimeout.js @@ -0,0 +1,114 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test how update window behaves when metadata ping times out +// bug 965788 + +const URI_EXTENSION_UPDATE_DIALOG = "chrome://mozapps/content/extensions/update.xul"; + +const PREF_GETADDONS_BYIDS = "extensions.getAddons.get.url"; +const PREF_MIN_PLATFORM_COMPAT = "extensions.minCompatiblePlatformVersion"; +const PREF_METADATA_LASTUPDATE = "extensions.getAddons.cache.lastUpdate"; + +Components.utils.import("resource://gre/modules/Promise.jsm"); + +let repo = {}; +let ARContext = Components.utils.import("resource://gre/modules/addons/AddonRepository.jsm", repo); + +// Mock out the XMLHttpRequest factory for AddonRepository so +// we can reply with a timeout +let pXHRStarted = Promise.defer(); +let oldXHRConstructor = ARContext.XHRequest; +ARContext.XHRequest = function() { + this._handlers = new Map(); + this.mozBackgroundRequest = false; + this.timeout = undefined; + this.open = function(aMethod, aURI, aAsync) { + this.method = aMethod; + this.uri = aURI; + this.async = aAsync; + info("Opened XHR for " + aMethod + " " + aURI); + }; + this.overrideMimeType = function(aMimeType) { + this.mimeType = aMimeType; + }; + this.addEventListener = function(aEvent, aHandler, aCapture) { + this._handlers.set(aEvent, aHandler); + }; + this.send = function(aBody) { + info("Send XHR for " + this.method + " " + this.uri + " handlers: " + [this._handlers.keys()].join(", ")); + pXHRStarted.resolve(this); + } +}; + + +// Returns promise{window}, resolves with a handle to the compatibility +// check window +function promise_open_compatibility_window(aInactiveAddonIds) { + let deferred = Promise.defer(); + // This will reset the longer timeout multiplier to 2 which will give each + // test that calls open_compatibility_window a minimum of 60 seconds to + // complete. + requestLongerTimeout(2); + + var variant = Cc["@mozilla.org/variant;1"]. + createInstance(Ci.nsIWritableVariant); + variant.setFromVariant(aInactiveAddonIds); + + // Cannot be modal as we want to interract with it, shouldn't cause problems + // with testing though. + var features = "chrome,centerscreen,dialog,titlebar"; + var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. + getService(Ci.nsIWindowWatcher); + var win = ww.openWindow(null, URI_EXTENSION_UPDATE_DIALOG, "", features, variant); + + win.addEventListener("load", function() { + function page_shown(aEvent) { + if (aEvent.target.pageid) + info("Page " + aEvent.target.pageid + " shown"); + } + + win.removeEventListener("load", arguments.callee, false); + + info("Compatibility dialog opened"); + + win.addEventListener("pageshow", page_shown, false); + win.addEventListener("unload", function() { + win.removeEventListener("unload", arguments.callee, false); + win.removeEventListener("pageshow", page_shown, false); + dump("Compatibility dialog closed\n"); + }, false); + + deferred.resolve(win); + }, false); + return deferred.promise; +} + +function promise_window_close(aWindow) { + let deferred = Promise.defer(); + aWindow.addEventListener("unload", function() { + aWindow.removeEventListener("unload", arguments.callee, false); + deferred.resolve(aWindow); + }, false); + return deferred.promise; +} + +// Start the compatibility update dialog, but use the mock XHR to respond with +// a timeout +add_task(function* amo_ping_timeout() { + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); + Services.prefs.clearUserPref(PREF_METADATA_LASTUPDATE); + let compatWindow = yield promise_open_compatibility_window([]); + + let xhr = yield pXHRStarted.promise; + is(xhr.timeout, 30000, "XHR request should have 30 second timeout"); + ok(xhr._handlers.has("timeout"), "Timeout handler set on XHR"); + // call back the timeout handler + xhr._handlers.get("timeout")(); + + // Put the old XHR constructor back + ARContext.XHRequest = oldXHRConstructor; + // The window should close without further interaction + yield promise_window_close(compatWindow); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_newaddon.js b/toolkit/mozapps/extensions/test/browser/browser_newaddon.js new file mode 100644 index 000000000..a460d79d8 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_newaddon.js @@ -0,0 +1,186 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests the new add-on tab + +var gProvider; + +function loadPage(aURL, aCallback) { + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(aURL); + gBrowser.addEventListener("AddonDisplayed", function(event) { + gBrowser.removeEventListener("AddonDisplayed", arguments.callee, false); + + aCallback(gBrowser.selectedTab); + }); +} + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + gProvider.createAddons([{ + id: "addon1@tests.mozilla.org", + name: "Test 1", + version: "5.3", + userDisabled: true, + operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE + }, { + id: "addon2@tests.mozilla.org", + name: "Test 2", + version: "7.1", + creator: "Dave Townsend", + userDisabled: true + }]); + + run_next_test(); +} + +function end_test() { + finish(); +} + +// Tests that ignoring a restartless add-on works +add_test(function() { + loadPage("about:newaddon?id=addon1@tests.mozilla.org", function(aTab) { + var doc = aTab.linkedBrowser.contentDocument; + is(doc.getElementById("name").value, "Test 1 5.3", "Should say the right name"); + + is_element_hidden(doc.getElementById("author"), "Should be no author displayed"); + is_element_hidden(doc.getElementById("location"), "Should be no location displayed"); + + is(doc.getElementById("buttonDeck").selectedPanel, doc.getElementById("continuePanel"), + "Should be showing the right buttons"); + + EventUtils.synthesizeMouseAtCenter(doc.getElementById("continue-button"), + {}, aTab.linkedBrowser.contentWindow); + + is(gBrowser.tabs.length, 1, "Page should have been closed"); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { + ok(aAddon.userDisabled, "Add-on should not have been enabled"); + + ok(!aAddon.isActive, "Add-on should not be running"); + + run_next_test(); + }); + }); +}); + +// Tests that enabling a restartless add-on works +add_test(function() { + loadPage("about:newaddon?id=addon1@tests.mozilla.org", function(aTab) { + var doc = aTab.linkedBrowser.contentDocument; + is(doc.getElementById("name").value, "Test 1 5.3", "Should say the right name"); + + is_element_hidden(doc.getElementById("author"), "Should be no author displayed"); + is_element_hidden(doc.getElementById("location"), "Should be no location displayed"); + + is(doc.getElementById("buttonDeck").selectedPanel, doc.getElementById("continuePanel"), + "Should be showing the right buttons"); + + EventUtils.synthesizeMouseAtCenter(doc.getElementById("allow"), + {}, aTab.linkedBrowser.contentWindow); + + EventUtils.synthesizeMouseAtCenter(doc.getElementById("continue-button"), + {}, aTab.linkedBrowser.contentWindow); + + is(gBrowser.tabs.length, 1, "Page should have been closed"); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { + ok(!aAddon.userDisabled, "Add-on should now have been enabled"); + + ok(aAddon.isActive, "Add-on should now be running"); + + run_next_test(); + }); + }); +}); + +// Tests that ignoring a non-restartless add-on works +add_test(function() { + loadPage("about:newaddon?id=addon2@tests.mozilla.org", function(aTab) { + var doc = aTab.linkedBrowser.contentDocument; + is(doc.getElementById("name").value, "Test 2 7.1", "Should say the right name"); + + is_element_visible(doc.getElementById("author"), "Should be an author displayed"); + is(doc.getElementById("author").value, "By Dave Townsend", "Should have the right author"); + is_element_hidden(doc.getElementById("location"), "Should be no location displayed"); + + is(doc.getElementById("buttonDeck").selectedPanel, doc.getElementById("continuePanel"), + "Should be showing the right buttons"); + + EventUtils.synthesizeMouseAtCenter(doc.getElementById("continue-button"), + {}, aTab.linkedBrowser.contentWindow); + + is(gBrowser.tabs.length, 1, "Page should have been closed"); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(aAddon) { + ok(aAddon.userDisabled, "Add-on should not have been enabled"); + + ok(!aAddon.isActive, "Add-on should not be running"); + + run_next_test(); + }); + }); +}); + +// Tests that enabling a non-restartless add-on works +add_test(function() { + loadPage("about:newaddon?id=addon2@tests.mozilla.org", function(aTab) { + var doc = aTab.linkedBrowser.contentDocument; + is(doc.getElementById("name").value, "Test 2 7.1", "Should say the right name"); + + is_element_visible(doc.getElementById("author"), "Should be an author displayed"); + is(doc.getElementById("author").value, "By Dave Townsend", "Should have the right author"); + is_element_hidden(doc.getElementById("location"), "Should be no location displayed"); + + is(doc.getElementById("buttonDeck").selectedPanel, doc.getElementById("continuePanel"), + "Should be showing the right buttons"); + + EventUtils.synthesizeMouseAtCenter(doc.getElementById("allow"), + {}, aTab.linkedBrowser.contentWindow); + + EventUtils.synthesizeMouseAtCenter(doc.getElementById("continue-button"), + {}, aTab.linkedBrowser.contentWindow); + + is(doc.getElementById("buttonDeck").selectedPanel, doc.getElementById("restartPanel"), + "Should be showing the right buttons"); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(aAddon) { + ok(!aAddon.userDisabled, "Add-on should now have been enabled"); + + ok(!aAddon.isActive, "Add-on should not be running"); + + ok(doc.getElementById("allow").disabled, "Should have disabled checkbox"); + + EventUtils.synthesizeMouseAtCenter(doc.getElementById("cancel-button"), + {}, aTab.linkedBrowser.contentWindow); + + is(doc.getElementById("buttonDeck").selectedPanel, doc.getElementById("continuePanel"), + "Should be showing the right buttons"); + + ok(!doc.getElementById("allow").disabled, "Should have enabled checkbox"); + + ok(aAddon.userDisabled, "Add-on should not have been enabled"); + + ok(!aAddon.isActive, "Add-on should not be running"); + + EventUtils.synthesizeMouseAtCenter(doc.getElementById("allow"), + {}, aTab.linkedBrowser.contentWindow); + + EventUtils.synthesizeMouseAtCenter(doc.getElementById("continue-button"), + {}, aTab.linkedBrowser.contentWindow); + + ok(aAddon.userDisabled, "Add-on should not have been enabled"); + + ok(!aAddon.isActive, "Add-on should not be running"); + + is(gBrowser.tabs.length, 1, "Page should have been closed"); + + run_next_test(); + }); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_openDialog.js b/toolkit/mozapps/extensions/test/browser/browser_openDialog.js new file mode 100644 index 000000000..bdbe9caee --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_openDialog.js @@ -0,0 +1,176 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests the dialog open by the Options button for addons that provide a +// custom chrome-like protocol for optionsURL. + +let CustomChromeProtocol = { + scheme: "khrome", + defaultPort: -1, + protocolFlags: Ci.nsIProtocolHandler.URI_DANGEROUS_TO_LOAD | + Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE | + Ci.nsIProtocolHandler.URI_NORELATIVE | + Ci.nsIProtocolHandler.URI_NOAUTH, + + newURI: function CCP_newURI(aSpec, aOriginCharset, aBaseUri) { + let uri = Cc["@mozilla.org/network/simple-uri;1"]. + createInstance(Ci.nsIURI); + uri.spec = aSpec; + return uri; + }, + + newChannel: function CCP_newChannel(aURI) { + let url = "chrome:" + aURI.path; + let ch = NetUtil.newChannel2(url, + null, + null, + null, // aLoadingNode + Services.scriptSecurityManager.getSystemPrincipal(), + null, // aTriggeringPrincipal + Ci.nsILoadInfo.SEC_NORMAL, + Ci.nsIContentPolicy.TYPE_OTHER); + ch.originalURI = aURI; + return ch; + }, + + allowPort: function CCP_allowPort(aPort, aScheme) { + return false; + }, + + QueryInterface: XPCOMUtils.generateQI([ + Ci.nsIProtocolHandler + ]), + + classID: Components.ID("{399cb2d1-05dd-4363-896f-63b78e008cf8}"), + + factory: { + registrar: Components.manager.QueryInterface(Ci.nsIComponentRegistrar), + + register: function CCP_register() { + this.registrar.registerFactory( + CustomChromeProtocol.classID, + "CustomChromeProtocol", + "@mozilla.org/network/protocol;1?name=khrome", + this + ); + }, + + unregister: function CCP_register() { + this.registrar.unregisterFactory(CustomChromeProtocol.classID, this); + }, + + // nsIFactory + createInstance: function BNPH_createInstance(aOuter, aIID) { + if (aOuter) { + throw Components.Exception("Class does not allow aggregation", + Components.results.NS_ERROR_NO_AGGREGATION); + } + return CustomChromeProtocol.QueryInterface(aIID); + }, + + lockFactory: function BNPH_lockFactory(aLock) { + throw Components.Exception("Function lockFactory is not implemented", + Components.results.NS_ERROR_NOT_IMPLEMENTED); + }, + + QueryInterface: XPCOMUtils.generateQI([ + Ci.nsIFactory + ]) + } +} + +function test() { + waitForExplicitFinish(); + requestLongerTimeout(2); + + info("Registering custom chrome-like protocol."); + CustomChromeProtocol.factory.register(); + registerCleanupFunction(function () CustomChromeProtocol.factory.unregister()); + + const ADDONS_LIST = [ + { id: "test1@tests.mozilla.org", + name: "Test add-on 1", + optionsURL: CHROMEROOT + "addon_prefs.xul" }, + { id: "test2@tests.mozilla.org", + name: "Test add-on 2", + optionsURL: (CHROMEROOT + "addon_prefs.xul").replace("chrome:", "khrome:") }, + ]; + + var gProvider = new MockProvider(); + gProvider.createAddons(ADDONS_LIST); + + open_manager("addons://list/extension", function(aManager) { + let addonList = aManager.document.getElementById("addon-list"); + let currentAddon; + let instantApply = Services.prefs.getBoolPref("browser.preferences.instantApply"); + + function getAddonByName(aName) { + for (let addonItem of addonList.childNodes) { + if (addonItem.hasAttribute("name") && + addonItem.getAttribute("name") == aName) + return addonItem; + } + return null; + } + + function observer(aSubject, aTopic, aData) { + switch (aTopic) { + case "domwindowclosed": + // Give the preference window a chance to finish closing before + // closing the add-ons manager. + waitForFocus(function () { + test_next_addon(); + }); + break; + case "domwindowopened": + let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget); + waitForFocus(function () { + // If the openDialog privileges are wrong a new browser window + // will open, let the test proceed (and fail) rather than timeout. + if (win.location != currentAddon.optionsURL && + win.location != "chrome://browser/content/browser.xul") + return; + + is(win.location, currentAddon.optionsURL, + "The correct addon pref window should have opened"); + + let chromeFlags = win.QueryInterface(Ci.nsIInterfaceRequestor). + getInterface(Ci.nsIWebNavigation). + QueryInterface(Ci.nsIDocShellTreeItem).treeOwner. + QueryInterface(Ci.nsIInterfaceRequestor). + getInterface(Ci.nsIXULWindow).chromeFlags; + ok(chromeFlags & Ci.nsIWebBrowserChrome.CHROME_OPENAS_CHROME && + (instantApply || chromeFlags & Ci.nsIWebBrowserChrome.CHROME_OPENAS_DIALOG), + "Window was open as a chrome dialog."); + + win.close(); + }, win); + break; + } + } + + function test_next_addon() { + currentAddon = ADDONS_LIST.shift(); + if (!currentAddon) { + Services.ww.unregisterNotification(observer); + close_manager(aManager, finish); + return; + } + + info("Testing " + currentAddon.name); + let addonItem = getAddonByName(currentAddon.name, addonList); + let optionsBtn = + aManager.document.getAnonymousElementByAttribute(addonItem, "anonid", + "preferences-btn"); + is(optionsBtn.hidden, false, "Prefs button should be visible.") + + addonList.ensureElementIsVisible(addonItem); + EventUtils.synthesizeMouseAtCenter(optionsBtn, { }, aManager); + } + + Services.ww.registerNotification(observer); + test_next_addon(); + }); + +} diff --git a/toolkit/mozapps/extensions/test/browser/browser_plugin_enabled_state_locked.js b/toolkit/mozapps/extensions/test/browser/browser_plugin_enabled_state_locked.js new file mode 100644 index 000000000..b32d74336 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_plugin_enabled_state_locked.js @@ -0,0 +1,125 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that state menu is displayed correctly (enabled or disabled) in the add-on manager +// when the preference is unlocked / locked +const {classes: Cc, interfaces: Ci} = Components; +const gIsWindows = ("@mozilla.org/windows-registry-key;1" in Cc); +const gIsOSX = ("nsILocalFileMac" in Ci); +const gIsLinux = ("@mozilla.org/gnome-gconf-service;1" in Cc) || + ("@mozilla.org/gio-service;1" in Cc); + +let gManagerWindow; +let gCategoryUtilities; +let gPluginElement; + +function getTestPluginPref() { + let prefix = "plugin.state."; + if (gIsWindows) + return prefix + "nptest"; + else if (gIsLinux) + return prefix + "libnptest"; + else + return prefix + "test"; +} + +registerCleanupFunction(() => { + Services.prefs.unlockPref(getTestPluginPref()); + Services.prefs.clearUserPref(getTestPluginPref()); +}); + +function getPlugins() { + let deferred = Promise.defer(); + AddonManager.getAddonsByTypes(["plugin"], plugins => deferred.resolve(plugins)); + return deferred.promise; +} + +function getTestPlugin(aPlugins) { + let testPluginId; + + for (let plugin of aPlugins) { + if (plugin.name == "Test Plug-in") { + testPluginId = plugin.id; + break; + } + } + + Assert.ok(testPluginId, "Test Plug-in should exist"); + + let pluginElement = get_addon_element(gManagerWindow, testPluginId); + pluginElement.parentNode.ensureElementIsVisible(pluginElement); + + return pluginElement; +} + +function checkStateMenu(locked) { + Assert.equal(Services.prefs.prefIsLocked(getTestPluginPref()), locked, + "Preference lock state should be correct."); + let menuList = gManagerWindow.document.getAnonymousElementByAttribute(gPluginElement, "anonid", "state-menulist"); + // State menu should always have a selected item which must be visible + let selectedMenuItem = menuList.querySelector(".addon-control[selected=\"true\"]"); + + is_element_visible(menuList, "State menu should be visible."); + Assert.equal(menuList.disabled, locked, + "State menu should" + (locked === true ? "" : " not") + " be disabled."); + + is_element_visible(selectedMenuItem, "State menu's selected item should be visible."); +} + +function checkStateMenuDetail(locked) { + Assert.equal(Services.prefs.prefIsLocked(getTestPluginPref()), locked, + "Preference should be " + (locked === true ? "" : "un") + "locked."); + + // open details menu + let details = gManagerWindow.document.getAnonymousElementByAttribute(gPluginElement, "anonid", "details-btn"); + is_element_visible(details, "Details link should be visible."); + EventUtils.synthesizeMouseAtCenter(details, {}, gManagerWindow); + + let deferred = Promise.defer(); + wait_for_view_load(gManagerWindow, function() { + let menuList = gManagerWindow.document.getElementById("detail-state-menulist"); + is_element_visible(menuList, "Details state menu should be visible."); + Assert.equal(menuList.disabled, locked, + "Details state menu enabled state should be correct."); + deferred.resolve(); + }); + return deferred.promise; +} + +add_task(function* initializeState() { + Services.prefs.setIntPref(getTestPluginPref(), Ci.nsIPluginTag.STATE_ENABLED); + Services.prefs.unlockPref(getTestPluginPref()); + gManagerWindow = yield open_manager(); + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + yield gCategoryUtilities.openType("plugin"); + + let plugins = yield getPlugins(); + gPluginElement = getTestPlugin(plugins); +}); + +// Tests that plugin state menu is enabled if the preference is unlocked +add_task(function* taskCheckStateMenuIsEnabled() { + checkStateMenu(false); + yield checkStateMenuDetail(false); +}); + +// Lock the preference and then reload the plugin category +add_task(function* reinitializeState() { + // lock the preference + Services.prefs.lockPref(getTestPluginPref()); + yield gCategoryUtilities.openType("plugin"); + // Retrieve the test plugin element + let plugins = yield getPlugins(); + gPluginElement = getTestPlugin(plugins); +}); + +// Tests that plugin state menu is disabled if the preference is locked +add_task(function* taskCheckStateMenuIsDisabled() { + checkStateMenu(true); + yield checkStateMenuDetail(true); +}); + +add_task(function* testCleanup() { + yield close_manager(gManagerWindow); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_pluginprefs.js b/toolkit/mozapps/extensions/test/browser/browser_pluginprefs.js new file mode 100644 index 000000000..458e8e334 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_pluginprefs.js @@ -0,0 +1,61 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests the detail view of plugins + +var gManagerWindow; + +function test() { + waitForExplicitFinish(); + + open_manager("addons://list/plugin", function(aWindow) { + gManagerWindow = aWindow; + + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, function() { + finish(); + }); +} + +add_test(function() { + AddonManager.getAddonsByTypes(["plugin"], function(plugins) { + let testPluginId; + for (let plugin of plugins) { + if (plugin.name == "Test Plug-in") { + testPluginId = plugin.id; + break; + } + } + ok(testPluginId, "Test Plug-in should exist") + + AddonManager.getAddonByID(testPluginId, function(testPlugin) { + let pluginEl = get_addon_element(gManagerWindow, testPluginId); + is(pluginEl.mAddon.optionsType, AddonManager.OPTIONS_TYPE_INLINE_INFO, "Options should be inline info type"); + pluginEl.parentNode.ensureElementIsVisible(pluginEl); + + let button = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "preferences-btn"); + is_element_hidden(button, "Preferences button should be hidden"); + + button = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "details-btn"); + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + let pluginLibraries = gManagerWindow.document.getElementById("pluginLibraries"); + ok(pluginLibraries, "Plugin file name row should be displayed"); + // the file name depends on the platform + ok(pluginLibraries.textContent, testPlugin.pluginLibraries, "Plugin file name should be displayed"); + + let pluginMimeTypes = gManagerWindow.document.getElementById("pluginMimeTypes"); + ok(pluginMimeTypes, "Plugin mime type row should be displayed"); + ok(pluginMimeTypes.textContent, "application/x-test (tst)", "Plugin mime type should be displayed"); + + run_next_test(); + }); + }); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_purchase.js b/toolkit/mozapps/extensions/test/browser/browser_purchase.js new file mode 100644 index 000000000..bb30a1eb4 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_purchase.js @@ -0,0 +1,195 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that marketplace results show up in searches, are sorted right and +// attempting to buy links through to the right webpage + +const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url"; +const SEARCH_URL = TESTROOT + "browser_purchase.xml"; + +var gManagerWindow; + +function test() { + // Turn on searching for this test + Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15); + Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, SEARCH_URL); + + waitForExplicitFinish(); + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + + waitForFocus(function() { + var searchBox = gManagerWindow.document.getElementById("header-search"); + searchBox.value = "foo"; + + EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow); + EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + var remoteFilter = gManagerWindow.document.getElementById("search-filter-remote"); + EventUtils.synthesizeMouseAtCenter(remoteFilter, { }, gManagerWindow); + + run_next_test(); + }); + }, aWindow); + }); +} + +function end_test() { + close_manager(gManagerWindow, function() { + // Will have created an install so cancel it + AddonManager.getAllInstalls(function(aInstalls) { + is(aInstalls.length, 1, "Should have been one install created"); + aInstalls[0].cancel(); + + finish(); + }); + }); +} + +function get_node(parent, anonid) { + return parent.ownerDocument.getAnonymousElementByAttribute(parent, "anonid", anonid); +} + +function get_install_btn(parent) { + var installStatus = get_node(parent, "install-status"); + return get_node(installStatus, "install-remote-btn"); +} + +function get_purchase_btn(parent) { + var installStatus = get_node(parent, "install-status"); + return get_node(installStatus, "purchase-remote-btn"); +} + +// Tests that the expected results appeared +add_test(function() { + var list = gManagerWindow.document.getElementById("search-list"); + var items = Array.filter(list.childNodes, function(e) { + return e.tagName == "richlistitem"; + }); + + is(items.length, 5, "Should be 5 results"); + + is(get_node(items[0], "name").value, "Ludicrously Expensive Add-on", "Add-on 0 should be in expected position"); + is_element_hidden(get_install_btn(items[0]), "Add-on 0 install button should be hidden"); + is_element_visible(get_purchase_btn(items[0]), "Add-on 0 purchase button should be visible"); + is(get_purchase_btn(items[0]).label, "Purchase for $101\u2026", "Add-on 0 should have the right price"); + + is(get_node(items[1], "name").value, "Cheap Add-on", "Add-on 1 should be in expected position"); + is_element_hidden(get_install_btn(items[1]), "Add-on 1 install button should be hidden"); + is_element_visible(get_purchase_btn(items[1]), "Add-on 1 purchase button should be visible"); + is(get_purchase_btn(items[1]).label, "Purchase for $0.99\u2026", "Add-on 2 should have the right price"); + + is(get_node(items[2], "name").value, "Reasonable Add-on", "Add-on 2 should be in expected position"); + is_element_hidden(get_install_btn(items[2]), "Add-on 2 install button should be hidden"); + is_element_visible(get_purchase_btn(items[2]), "Add-on 2 purchase button should be visible"); + is(get_purchase_btn(items[2]).label, "Purchase for $1\u2026", "Add-on 3 should have the right price"); + + is(get_node(items[3], "name").value, "Free Add-on", "Add-on 3 should be in expected position"); + is_element_visible(get_install_btn(items[3]), "Add-on 3 install button should be visible"); + is_element_hidden(get_purchase_btn(items[3]), "Add-on 3 purchase button should be hidden"); + + is(get_node(items[4], "name").value, "More Expensive Add-on", "Add-on 4 should be in expected position"); + is_element_hidden(get_install_btn(items[4]), "Add-on 4 install button should be hidden"); + is_element_visible(get_purchase_btn(items[4]), "Add-on 4 purchase button should be visible"); + is(get_purchase_btn(items[4]).label, "Purchase for $1.01\u2026", "Add-on 4 should have the right price"); + + run_next_test(); +}); + +// Tests that sorting by price works +add_test(function() { + var list = gManagerWindow.document.getElementById("search-list"); + + var sorters = gManagerWindow.document.getElementById("search-sorters"); + var priceSorter = get_node(sorters, "price-btn"); + info("Changing sort order"); + EventUtils.synthesizeMouseAtCenter(priceSorter, { }, gManagerWindow); + + var items = Array.filter(list.childNodes, function(e) { + return e.tagName == "richlistitem"; + }); + + is(get_node(items[0], "name").value, "Free Add-on", "Add-on 0 should be in expected position"); + is(get_node(items[1], "name").value, "Cheap Add-on", "Add-on 1 should be in expected position"); + is(get_node(items[2], "name").value, "Reasonable Add-on", "Add-on 2 should be in expected position"); + is(get_node(items[3], "name").value, "More Expensive Add-on", "Add-on 3 should be in expected position"); + is(get_node(items[4], "name").value, "Ludicrously Expensive Add-on", "Add-on 4 should be in expected position"); + + info("Changing sort order"); + EventUtils.synthesizeMouseAtCenter(priceSorter, { }, gManagerWindow); + + var items = Array.filter(list.childNodes, function(e) { + return e.tagName == "richlistitem"; + }); + + is(get_node(items[0], "name").value, "Ludicrously Expensive Add-on", "Add-on 0 should be in expected position"); + is(get_node(items[1], "name").value, "More Expensive Add-on", "Add-on 1 should be in expected position"); + is(get_node(items[2], "name").value, "Reasonable Add-on", "Add-on 2 should be in expected position"); + is(get_node(items[3], "name").value, "Cheap Add-on", "Add-on 3 should be in expected position"); + is(get_node(items[4], "name").value, "Free Add-on", "Add-on 4 should be in expected position"); + + run_next_test(); +}); + +// Tests that clicking the buy button works from the list +add_test(function() { + gBrowser.addEventListener("load", function(event) { + if (!(event.target instanceof Document) || + event.target.location.href == "about:blank") + return; + gBrowser.removeEventListener("load", arguments.callee, true); + + is(gBrowser.currentURI.spec, TESTROOT + "releaseNotes.xhtml?addon5", "Should have loaded the right page"); + + gBrowser.removeCurrentTab(); + + if (gUseInContentUI) { + is(gBrowser.currentURI.spec, "about:addons", "Should be back to the add-ons manager"); + run_next_test(); + } + else { + waitForFocus(run_next_test, gManagerWindow); + } + }, true); + + var list = gManagerWindow.document.getElementById("search-list"); + EventUtils.synthesizeMouseAtCenter(get_purchase_btn(list.firstChild), { }, gManagerWindow); +}); + +// Tests that clicking the buy button from the details view works +add_test(function() { + gBrowser.addEventListener("load", function(event) { + if (!(event.target instanceof Document) || + event.target.location.href == "about:blank") + return; + gBrowser.removeEventListener("load", arguments.callee, true); + + is(gBrowser.currentURI.spec, TESTROOT + "releaseNotes.xhtml?addon4", "Should have loaded the right page"); + + gBrowser.removeCurrentTab(); + + if (gUseInContentUI) { + is(gBrowser.currentURI.spec, "about:addons", "Should be back to the add-ons manager"); + run_next_test(); + } + else { + waitForFocus(run_next_test, gManagerWindow); + } + }, true); + + var list = gManagerWindow.document.getElementById("search-list"); + var item = list.firstChild.nextSibling; + list.ensureElementIsVisible(item); + EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow); + EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + var btn = gManagerWindow.document.getElementById("detail-purchase-btn"); + is_element_visible(btn, "Purchase button should be visible"); + + EventUtils.synthesizeMouseAtCenter(btn, { }, gManagerWindow); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_purchase.xml b/toolkit/mozapps/extensions/test/browser/browser_purchase.xml new file mode 100644 index 000000000..470f47d28 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_purchase.xml @@ -0,0 +1,180 @@ +<?xml version="1.0" encoding="utf-8" ?> +<searchresults total_results="100"> + <addon> + <name>Ludicrously Expensive Add-on</name> + <type id='1'>Extension</type> + <guid>addon5@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://example.com/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <summary>Test summary</summary> + <description>Test description</description> + <compatible_applications> + <application> + <name>Firefox</name> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + <application> + <name>SeaMonkey</name> + <appID>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + </compatible_applications> + <all_compatible_os> + <os>ALL</os> + </all_compatible_os> + <payment_data> + <link>http://example.com/browser/toolkit/mozapps/extensions/test/browser/releaseNotes.xhtml?addon5</link> + <amount amount="101">$101</amount> + </payment_data> + </addon> + <addon> + <name>Cheap Add-on</name> + <type id='1'>Extension</type> + <guid>addon2@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://example.com/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <summary>Test summary</summary> + <description>Test description</description> + <compatible_applications> + <application> + <name>Firefox</name> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + <application> + <name>SeaMonkey</name> + <appID>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + </compatible_applications> + <all_compatible_os> + <os>ALL</os> + </all_compatible_os> + <payment_data> + <link>http://example.com/browser/toolkit/mozapps/extensions/test/browser/releaseNotes.xhtml?addon2</link> + <amount amount="0.99">$0.99</amount> + </payment_data> + </addon> + <addon> + <name>Reasonable Add-on</name> + <type id='1'>Extension</type> + <guid>addon3@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://example.com/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <summary>Test summary</summary> + <description>Test description</description> + <compatible_applications> + <application> + <name>Firefox</name> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + <application> + <name>SeaMonkey</name> + <appID>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + </compatible_applications> + <all_compatible_os> + <os>ALL</os> + </all_compatible_os> + <payment_data> + <link>http://example.com/browser/toolkit/mozapps/extensions/test/browser/releaseNotes.xhtml?addon3</link> + <amount amount="1">$1</amount> + </payment_data> + </addon> + <addon> + <name>Free Add-on</name> + <type id='1'>Extension</type> + <guid>addon1@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://example.com/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <summary>Test summary</summary> + <description>Test description</description> + <compatible_applications> + <application> + <name>Firefox</name> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + <application> + <name>SeaMonkey</name> + <appID>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + </compatible_applications> + <all_compatible_os> + <os>ALL</os> + </all_compatible_os> + <install size="1">http://example.com/addon1.xpi</install> + </addon> + <addon> + <name>More Expensive Add-on</name> + <type id='1'>Extension</type> + <guid>addon4@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://example.com/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <summary>Test summary</summary> + <description>Test description</description> + <compatible_applications> + <application> + <name>Firefox</name> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + <application> + <name>SeaMonkey</name> + <appID>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + </compatible_applications> + <all_compatible_os> + <os>ALL</os> + </all_compatible_os> + <payment_data> + <link>http://example.com/browser/toolkit/mozapps/extensions/test/browser/releaseNotes.xhtml?addon4</link> + <amount amount="1.01">$1.01</amount> + </payment_data> + </addon> +</searchresults> diff --git a/toolkit/mozapps/extensions/test/browser/browser_recentupdates.js b/toolkit/mozapps/extensions/test/browser/browser_recentupdates.js new file mode 100644 index 000000000..1427d5eba --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_recentupdates.js @@ -0,0 +1,125 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests the recent updates pane + +var gProvider; +var gManagerWindow; +var gCategoryUtilities; + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + gProvider.createAddons([{ + id: "addon1@tests.mozilla.org", + name: "updated 6 hours ago", + version: "1.0", + updateDate: new Date(Date.now() - (1000 * 60 * 60 * 6)), + releaseNotesURI: Services.io.newURI(TESTROOT + "releaseNotes.xhtml", null, null) + }, { + id: "addon2@tests.mozilla.org", + name: "updated 5 seconds ago", + version: "1.0", + updateDate: new Date(Date.now() - (1000 * 5)) + }, { + id: "addon3@tests.mozilla.org", + name: "updated 1 month ago", + version: "1.0", + updateDate: new Date(Date.now() - (1000 * 60 * 60 * 25 * 30)) + }]); + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, function() { + finish(); + }); +} + + +add_test(function() { + info("Checking menuitem for Recent Updates opens that pane"); + var recentCat = gManagerWindow.gCategories.get("addons://updates/recent"); + is(gCategoryUtilities.isVisible(recentCat), false, "Recent Updates category should initially be hidden"); + + var utilsBtn = gManagerWindow.document.getElementById("header-utils-btn"); + utilsBtn.addEventListener("popupshown", function() { + utilsBtn.removeEventListener("popupshown", arguments.callee, false); + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.isVisible(recentCat), true, "Recent Updates category should now be visible"); + is(gManagerWindow.document.getElementById("categories").selectedItem.value, "addons://updates/recent", "Recent Updates category should now be selected"); + is(gManagerWindow.gViewController.currentViewId, "addons://updates/recent", "Recent Updates view should be the current view"); + run_next_test(); + }, true); + var menuitem = gManagerWindow.document.getElementById("utils-viewUpdates"); + EventUtils.synthesizeMouse(menuitem, 2, 2, { }, gManagerWindow); + }, false); + EventUtils.synthesizeMouse(utilsBtn, 2, 2, { }, gManagerWindow); +}); + + +add_test(function() { + var updatesList = gManagerWindow.document.getElementById("updates-list"); + var sorters = gManagerWindow.document.getElementById("updates-sorters"); + var dateSorter = gManagerWindow.document.getAnonymousElementByAttribute(sorters, "anonid", "date-btn"); + var nameSorter = gManagerWindow.document.getAnonymousElementByAttribute(sorters, "anonid", "name-btn"); + + function check_order(expected) { + var items = updatesList.getElementsByTagName("richlistitem"); + var possible = ["addon1@tests.mozilla.org", "addon2@tests.mozilla.org", "addon3@tests.mozilla.org"]; + for (let item of items) { + let itemId = item.mAddon.id; + if (possible.indexOf(itemId) == -1) + continue; // skip over any other addons, such as shipped addons that would update on every build + isnot(expected.length, 0, "Should be expecting more items"); + is(itemId, expected.shift(), "Should get expected item based on sort order"); + if (itemId == "addon1@tests.mozilla.org") + is_element_visible(item._relNotesToggle, "Release notes toggle should be visible for addon with release notes"); + else + is_element_hidden(item._relNotesToggle, "Release notes toggle should be hidden for addon with no release notes"); + } + } + + is_element_visible(dateSorter); + is_element_visible(nameSorter); + + // sorted by date, descending + check_order(["addon2@tests.mozilla.org", "addon1@tests.mozilla.org"]); + + // sorted by date, ascending + EventUtils.synthesizeMouseAtCenter(dateSorter, { }, gManagerWindow); + check_order(["addon1@tests.mozilla.org", "addon2@tests.mozilla.org"]); + + // sorted by name, ascending + EventUtils.synthesizeMouseAtCenter(nameSorter, { }, gManagerWindow); + check_order(["addon2@tests.mozilla.org", "addon1@tests.mozilla.org"]); + + // sorted by name, descending + EventUtils.synthesizeMouseAtCenter(nameSorter, { }, gManagerWindow); + check_order(["addon1@tests.mozilla.org", "addon2@tests.mozilla.org"]); + + run_next_test(); +}); + + +add_test(function() { + close_manager(gManagerWindow, function() { + open_manager(null, function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + var recentCat = gManagerWindow.gCategories.get("addons://updates/recent"); + is(gCategoryUtilities.isVisible(recentCat), true, "Recent Updates category should still be visible"); + + run_next_test(); + }); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_searching.js b/toolkit/mozapps/extensions/test/browser/browser_searching.js new file mode 100644 index 000000000..9e03e8297 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_searching.js @@ -0,0 +1,695 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that searching for add-ons works correctly + +const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url"; +const SEARCH_URL = TESTROOT + "browser_searching.xml"; +const NO_MATCH_URL = TESTROOT + "browser_searching_empty.xml"; + +const QUERY = "SEARCH"; +const NO_MATCH_QUERY = "NOMATCHQUERY"; +const REMOTE_TO_INSTALL = "remote1"; +const REMOTE_INSTALL_URL = TESTROOT + "addons/browser_searching.xpi"; + +var gManagerWindow; +var gCategoryUtilities; +var gProvider; +var gServer; +var gAddonInstalled = false; + +function test() { + requestLongerTimeout(2); + // Turn on searching for this test + Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15); + Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true); + + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + gProvider.createAddons([{ + id: "addon1@tests.mozilla.org", + name: "PASS - f", + description: "Test description - SEARCH", + size: 3, + version: "1.0", + updateDate: new Date(2010, 4, 2, 0, 0, 1) + }, { + id: "fail-addon1@tests.mozilla.org", + name: "FAIL", + description: "Does not match query" + }, { + id: "addon2@tests.mozilla.org", + name: "PASS - c", + description: "Test description - reSEARCHing SEARCH SEARCH", + size: 6, + version: "2.0", + updateDate: new Date(2010, 4, 2, 0, 0, 0) + }]); + + var installs = gProvider.createInstalls([{ + name: "PASS - a - SEARCHing", + sourceURI: "http://example.com/install1.xpi" + }, { + name: "PASS - g - reSEARCHing SEARCH", + sourceURI: "http://example.com/install2.xpi" + }, { + // Does not match query + name: "FAIL", + sourceURI: "http://example.com/fail-install1.xpi" + }]); + + for (let install of installs ) + install.install(); + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, function() { + var installedAddon = get_addon_item(REMOTE_TO_INSTALL).mAddon; + installedAddon.uninstall(); + + AddonManager.getAllInstalls(function(aInstallsList) { + for (var install of aInstallsList) { + var sourceURI = install.sourceURI.spec; + if (sourceURI == REMOTE_INSTALL_URL || + sourceURI.match(/^http:\/\/example\.com\/(.+)\.xpi$/) != null) + install.cancel(); + } + + finish(); + }); + }); +} + +function getAnonymousElementByAttribute(aElement, aName, aValue) { + return gManagerWindow.document.getAnonymousElementByAttribute(aElement, + aName, + aValue); +} + +/* + * Checks whether or not the Add-ons Manager is currently searching + * + * @param aExpectedSearching + * The expected isSearching state + */ +function check_is_searching(aExpectedSearching) { + var loading = gManagerWindow.document.getElementById("search-loading"); + is(!is_hidden(loading), aExpectedSearching, + "Search throbber should be showing iff currently searching"); +} + +/* + * Completes a search + * + * @param aQuery + * The query to search for + * @param aFinishImmediately + * Boolean representing whether or not the search is expected to + * finish immediately + * @param aCallback + * The callback to call when the search is done + * @param aCategoryType + * The expected selected category after the search is done. + * Optional and defaults to "search" + */ +function search(aQuery, aFinishImmediately, aCallback, aCategoryType) { + // Point search to the correct xml test file + var url = (aQuery == NO_MATCH_QUERY) ? NO_MATCH_URL : SEARCH_URL; + Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, url); + + aCategoryType = aCategoryType ? aCategoryType : "search"; + + var searchBox = gManagerWindow.document.getElementById("header-search"); + searchBox.value = aQuery; + + EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow); + EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); + + var finishImmediately = true; + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, aCategoryType, "Expected category view should be selected"); + is(gCategoryUtilities.isTypeVisible("search"), aCategoryType == "search", + "Search category should only be visible if it is the current view"); + check_is_searching(false); + is(finishImmediately, aFinishImmediately, "Search should finish immediately only if expected"); + + aCallback(); + }); + + finishImmediately = false + if (!aFinishImmediately) + check_is_searching(true); +} + +/* + * Return results of a search + * + * @return Array of objects, each containing the name and item of a specific + * result + */ +function get_actual_results() { + var list = gManagerWindow.document.getElementById("search-list"); + var rows = list.getElementsByTagName("richlistitem"); + + var results = []; + for (var item of rows) { + + // Only consider items that are currently showing + var style = gManagerWindow.document.defaultView.getComputedStyle(item, ""); + if (style.display == "none" || style.visibility != "visible") + continue; + + if (item.mInstall || item.isPending("install")) { + var sourceURI = item.mInstall.sourceURI.spec; + if (sourceURI == REMOTE_INSTALL_URL) { + results.push({name: REMOTE_TO_INSTALL, item: item}); + continue; + } + + var result = sourceURI.match(/^http:\/\/example\.com\/(.+)\.xpi$/); + if (result != null) { + is(item.mInstall.name.indexOf("PASS"), 0, "Install name should start with PASS"); + results.push({name: result[1], item: item}); + continue; + } + } + else if (item.mAddon) { + var result = item.mAddon.id.match(/^(.+)@tests\.mozilla\.org$/); + if (result != null) { + is(item.mAddon.name.indexOf("PASS"), 0, "Addon name should start with PASS"); + results.push({name: result[1], item: item}); + continue; + } + } + else { + ok(false, "Found an item in the list that was neither installing or installed"); + } + } + + return results; +} + +/* + * Returns expected results when searching for QUERY with default ordering + * + * @param aSortBy + * How the results are sorted (e.g. "name") + * @param aLocalExpected + * Boolean representing if local results are expected + * @return A pair: [array of results with an expected order, + * array of results with unknown order] + */ +function get_expected_results(aSortBy, aLocalExpected) { + var expectedOrder = null, unknownOrder = null; + switch (aSortBy) { + case "relevancescore": + expectedOrder = [ "addon2" , "remote1", "install2", "addon1", + "install1", "remote2", "remote3" , "remote4" ]; + unknownOrder = []; + break; + case "name": + // Defaults to ascending order + expectedOrder = [ "install1", "remote1", "addon2" , "remote2", + "remote3" , "addon1" , "install2", "remote4" ]; + unknownOrder = []; + break; + case "dateUpdated": + expectedOrder = [ "addon1", "addon2" ]; + // Updated date not available for installs and remote add-ons + unknownOrder = [ "install1", "install2", "remote1", + "remote2" , "remote3" , "remote4" ]; + break; + default: + ok(false, "Should recognize sortBy when checking the order of items"); + } + + // Only keep expected results + function filterResults(aId) { + // Include REMOTE_TO_INSTALL as a local add-on if it has been installed + if (gAddonInstalled && aId == REMOTE_TO_INSTALL) + return aLocalExpected; + + if (aId.indexOf("addon") == 0 || aId.indexOf("install") == 0) + return aLocalExpected; + if (aId.indexOf("remote") == 0) + return !aLocalExpected; + + return false; + } + + + return [expectedOrder.filter(filterResults), + unknownOrder.filter(filterResults)] +} + +/* + * Check that the actual and expected results are the same + * + * @param aQuery + * The search query used + * @param aSortBy + * How the results are sorted (e.g. "name") + * @param aReverseOrder + * Boolean representing if the results are in reverse default order + * @param aShowLocal + * Boolean representing if local results are being shown + */ +function check_results(aQuery, aSortBy, aReverseOrder, aShowLocal) { + + var xpinstall_enabled = true; + try { + xpinstall_enabled = Services.prefs.getBoolPref(PREF_XPI_ENABLED); + } + catch (e) {}; + + // When XPI Instalation is disabled, those buttons are hidden and unused + if (xpinstall_enabled) { + var localFilterSelected = gManagerWindow.document.getElementById("search-filter-local").selected; + var remoteFilterSelected = gManagerWindow.document.getElementById("search-filter-remote").selected; + is(localFilterSelected, aShowLocal, "Local filter should be selected if showing local items"); + is(remoteFilterSelected, !aShowLocal, "Remote filter should be selected if showing remote items"); + } + + // Get expected order assuming default order + var expectedOrder = [], unknownOrder = []; + if (aQuery == QUERY) + [expectedOrder, unknownOrder] = get_expected_results(aSortBy, aShowLocal); + + // Get actual order of results + var actualResults = get_actual_results(); + var actualOrder = [result.name for each(result in actualResults)]; + + // Reverse array of actual results if supposed to be in reverse order. + // Reverse actualOrder instead of expectedOrder so can always check + // expectedOrder before unknownOrder + if (aReverseOrder) + actualOrder.reverse(); + + // Check actual vs. expected list of results + var totalExpectedResults = expectedOrder.length + unknownOrder.length; + is(actualOrder.length, totalExpectedResults, "Should get correct number of results"); + + // Check the "first" and "last" attributes are set correctly + for (let i = 0; i < actualResults.length; i++) { + if (i == 0) { + is(actualResults[0].item.hasAttribute("first"), true, + "First item should have 'first' attribute set"); + is(actualResults[0].item.hasAttribute("last"), false, + "First item should not have 'last' attribute set"); + } else if (i == (actualResults.length - 1)) { + is(actualResults[actualResults.length - 1].item.hasAttribute("first"), false, + "Last item should not have 'first' attribute set"); + is(actualResults[actualResults.length - 1].item.hasAttribute("last"), true, + "Last item should have 'last' attribute set"); + } else { + is(actualResults[i].item.hasAttribute("first"), false, + "Item " + i + " should not have 'first' attribute set"); + is(actualResults[i].item.hasAttribute("last"), false, + "Item " + i + " should not have 'last' attribute set"); + } + } + + var i = 0; + for (; i < expectedOrder.length; i++) + is(actualOrder[i], expectedOrder[i], "Should have seen expected item"); + + // Items with data that is unknown can appear in any order among themselves, + // so just check that these items exist + for (; i < actualOrder.length; i++) { + var unknownOrderIndex = unknownOrder.indexOf(actualOrder[i]); + ok(unknownOrderIndex >= 0, "Should expect to see item with data that is unknown"); + unknownOrder[unknownOrderIndex] = null; + } + + // Check status of empty notice + var emptyNotice = gManagerWindow.document.getElementById("search-list-empty"); + is(emptyNotice.hidden, totalExpectedResults > 0, + "Empty notice should be hidden only if expecting shown items"); +} + +/* + * Check results of a search with different filterings + * + * @param aQuery + * The search query used + * @param aSortBy + * How the results are sorted (e.g. "name") + * @param aReverseOrder + * Boolean representing if the results are in reverse default order + * @param aLocalOnly + * Boolean representing if the results are local only, can be undefined + */ +function check_filtered_results(aQuery, aSortBy, aReverseOrder, aLocalOnly) { + var localFilter = gManagerWindow.document.getElementById("search-filter-local"); + var remoteFilter = gManagerWindow.document.getElementById("search-filter-remote"); + + var list = gManagerWindow.document.getElementById("search-list"); + list.ensureElementIsVisible(localFilter); + + // Check with showing local add-ons + EventUtils.synthesizeMouseAtCenter(localFilter, { }, gManagerWindow); + check_results(aQuery, aSortBy, aReverseOrder, true); + + // Check with showing remote add-ons + aLocalOnly = aLocalOnly || false; + EventUtils.synthesizeMouseAtCenter(remoteFilter, { }, gManagerWindow); + check_results(aQuery, aSortBy, aReverseOrder, aLocalOnly); +} + +/* + * Get item for a specific add-on by name + * + * @param aName + * The name of the add-on to search for + * @return Row of add-on if found, null otherwise + */ +function get_addon_item(aName) { + var id = aName + "@tests.mozilla.org"; + var list = gManagerWindow.document.getElementById("search-list"); + var rows = list.getElementsByTagName("richlistitem"); + for (var row of rows) { + if (row.mAddon && row.mAddon.id == id) + return row; + } + + return null; +} + +/* + * Get item for a specific install by name + * + * @param aName + * The name of the install to search for + * @return Row of install if found, null otherwise + */ +function get_install_item(aName) { + var sourceURI = "http://example.com/" + aName + ".xpi"; + var list = gManagerWindow.document.getElementById("search-list"); + var rows = list.getElementsByTagName("richlistitem"); + for (var row of rows) { + if (row.mInstall && row.mInstall.sourceURI.spec == sourceURI) + return row; + } + + return null; +} + +/* + * Gets the install button for a specific item + * + * @param aItem + * The item to get the install button for + * @return The install button for aItem + */ +function get_install_button(aItem) { + isnot(aItem, null, "Item should not be null when checking state of install button"); + var installStatus = getAnonymousElementByAttribute(aItem, "anonid", "install-status"); + return getAnonymousElementByAttribute(installStatus, "anonid", "install-remote-btn"); +} + + +// Tests that searching for the empty string does nothing when not in the search view +add_test(function() { + is(gCategoryUtilities.isTypeVisible("search"), false, "Search category should initially be hidden"); + + var selectedCategory = gCategoryUtilities.selectedCategory; + isnot(selectedCategory, "search", "Selected type should not initially be the search view"); + search("", true, run_next_test, selectedCategory); +}); + +// Tests that the results from a query are sorted by relevancescore in descending order. +// Also test that double clicking non-install items goes to the detail view, and that +// only remote items have install buttons showing +add_test(function() { + search(QUERY, false, function() { + check_filtered_results(QUERY, "relevancescore", false); + + var list = gManagerWindow.document.getElementById("search-list"); + var results = get_actual_results(); + for (var result of results) { + var installBtn = get_install_button(result.item); + is(installBtn.hidden, result.name.indexOf("remote") != 0, + "Install button should only be showing for remote items"); + } + + var currentIndex = -1; + function run_next_double_click_test() { + currentIndex++; + if (currentIndex >= results.length) { + run_next_test(); + return; + } + + var result = results[currentIndex]; + if (result.name.indexOf("install") == 0) { + run_next_double_click_test(); + return; + } + + var item = result.item; + list.ensureElementIsVisible(item); + EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow); + EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow); + wait_for_view_load(gManagerWindow, function() { + var name = gManagerWindow.document.getElementById("detail-name").textContent; + is(name, item.mAddon.name, "Name in detail view should be correct"); + var version = gManagerWindow.document.getElementById("detail-version").value; + is(version, item.mAddon.version, "Version in detail view should be correct"); + + EventUtils.synthesizeMouseAtCenter(gManagerWindow.document.getElementById("category-search"), + { }, gManagerWindow); + wait_for_view_load(gManagerWindow, run_next_double_click_test); + }); + } + + run_next_double_click_test(); + }); +}); + +// Tests that the sorters and filters correctly manipulate the results +add_test(function() { + var sorters = gManagerWindow.document.getElementById("search-sorters"); + var originalHandler = sorters.handler; + + var sorterNames = ["name", "dateUpdated"]; + var buttonIds = ["name-btn", "date-btn"]; + var currentIndex = 0; + var currentReversed = false; + + function run_sort_test() { + if (currentIndex >= sorterNames.length) { + sorters.handler = originalHandler; + run_next_test(); + return; + } + + // Simulate clicking on a specific sorter + var buttonId = buttonIds[currentIndex]; + var sorter = getAnonymousElementByAttribute(sorters, "anonid", buttonId); + is_element_visible(sorter); + EventUtils.synthesizeMouseAtCenter(sorter, { }, gManagerWindow); + } + + sorters.handler = { + onSortChanged: function(aSortBy, aAscending) { + if (originalHandler && "onSortChanged" in originalHandler) + originalHandler.onSortChanged(aSortBy, aAscending); + + check_filtered_results(QUERY, sorterNames[currentIndex], currentReversed); + + if (currentReversed) + currentIndex++; + currentReversed = !currentReversed; + + run_sort_test(); + } + }; + + check_filtered_results(QUERY, "relevancescore", false); + run_sort_test(); +}); + +// Tests that searching for the empty string does nothing when in search view +add_test(function() { + search("", true, function() { + check_filtered_results(QUERY, "dateUpdated", true); + run_next_test(); + }); +}); + +// Tests that clicking a different category hides the search query +add_test(function() { + gCategoryUtilities.openType("extension", function() { + is(gCategoryUtilities.isTypeVisible("search"), false, "Search category should be hidden"); + is(gCategoryUtilities.selectedCategory, "extension", "View should have changed to extension"); + run_next_test(); + }); +}); + +// Tests that re-searching for query doesn't actually complete a new search, +// and the last sort is still used +add_test(function() { + search(QUERY, true, function() { + check_filtered_results(QUERY, "dateUpdated", true); + run_next_test(); + }); +}); + +// Tests that getting zero results works correctly +add_test(function() { + search(NO_MATCH_QUERY, false, function() { + check_filtered_results(NO_MATCH_QUERY, "relevancescore", false); + run_next_test(); + }); +}); + +// Tests that installing a remote add-on works +add_test(function() { + var installBtn = null; + + var listener = { + onInstallEnded: function(aInstall, aAddon) { + // Don't immediately consider the installed add-on as local because + // if the user was filtering out local add-ons, the installed add-on + // would vanish. Only consider add-on as local on new searches. + + aInstall.removeListener(this); + + is(installBtn.hidden, true, "Install button should be hidden after install ended"); + check_filtered_results(QUERY, "relevancescore", false); + run_next_test(); + } + } + + search(QUERY, false, function() { + var list = gManagerWindow.document.getElementById("search-list"); + var remoteItem = get_addon_item(REMOTE_TO_INSTALL); + list.ensureElementIsVisible(remoteItem); + + installBtn = get_install_button(remoteItem); + is(installBtn.hidden, false, "Install button should be showing before install"); + remoteItem.mAddon.install.addListener(listener); + EventUtils.synthesizeMouseAtCenter(installBtn, { }, gManagerWindow); + }); +}); + +// Tests that re-searching for query results in correct results +add_test(function() { + // Select a different category + gCategoryUtilities.openType("extension", function() { + is(gCategoryUtilities.isTypeVisible("search"), false, "Search category should be hidden"); + is(gCategoryUtilities.selectedCategory, "extension", "View should have changed to extension"); + + var installBtn = get_install_button(get_addon_item(REMOTE_TO_INSTALL)); + is(installBtn.hidden, true, "Install button should be hidden for installed item"); + + search(QUERY, true, function() { + check_filtered_results(QUERY, "relevancescore", false); + run_next_test(); + }); + }); +}); + +// Tests that incompatible add-ons are shown with a warning if compatibility checking is disabled +add_test(function() { + AddonManager.checkCompatibility = false; + search("incompatible", false, function() { + var item = get_addon_item("remote5"); + is_element_visible(item, "Incompatible addon should be visible"); + is(item.getAttribute("notification"), "warning", "Compatibility warning should be shown"); + + item = get_addon_item("remote6"); + is(item, null, "Addon incompatible with the product should not be visible"); + + AddonManager.checkCompatibility = true; + run_next_test(); + }); +}); + +// Tests that compatible-by-default addons are shown if strict compatibility checking is disabled +add_test(function() { + restart_manager(gManagerWindow, null, function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + Services.prefs.setBoolPref(PREF_STRICT_COMPAT, false); + search("incompatible", false, function() { + var item = get_addon_item("remote5"); + is_element_visible(item, "Incompatible addon should be visible"); + isnot(item.getAttribute("notification"), "warning", "Compatibility warning should not be shown"); + + var item = get_addon_item("remote6"); + is(item, null, "Addon incompatible with the product should not be visible"); + + Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true); + run_next_test(); + }); + }); +}); + + +// Tests that restarting the manager doesn't change search results +add_test(function() { + restart_manager(gManagerWindow, null, function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + // We never restore to the search pane + is(gCategoryUtilities.selectedCategory, "discover", "View should have changed to discover"); + + // Installed add-on is considered local on new search + gAddonInstalled = true; + + search(QUERY, false, function() { + check_filtered_results(QUERY, "relevancescore", false); + + var installBtn = get_install_button(get_addon_item(REMOTE_TO_INSTALL)); + is(installBtn.hidden, true, "Install button should be hidden for installed item"); + + run_next_test(); + }); + }); +}); + +function bug_815120_test_search(aLocalOnly) { + restart_manager(gManagerWindow, "addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + // Installed add-on is considered local on new search + gAddonInstalled = true; + + // The search buttons should be hidden in the LocalOnly setup + var localFilterButton = aWindow.document.getElementById("search-filter-local"); + is(aLocalOnly, is_hidden(localFilterButton), "Local filter button visibility does not match, aLocalOnly = " + aLocalOnly); + + var remoteFilterButton = aWindow.document.getElementById("search-filter-remote"); + is(aLocalOnly, is_hidden(remoteFilterButton), "Remote filter button visibility does not match, aLocalOnly = " + aLocalOnly); + + search(QUERY, false, function() { + check_filtered_results(QUERY, "relevancescore", false, aLocalOnly); + run_next_test(); + }); + }); +} + +// Tests for Bug 815120 +add_test(function() { + Services.prefs.setBoolPref(PREF_XPI_ENABLED, false); + bug_815120_test_search(true); +}); + +add_test(function() { + Services.prefs.setBoolPref(PREF_XPI_ENABLED, true); + bug_815120_test_search(false); +}); + diff --git a/toolkit/mozapps/extensions/test/browser/browser_searching.xml b/toolkit/mozapps/extensions/test/browser/browser_searching.xml new file mode 100644 index 000000000..e88db289e --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_searching.xml @@ -0,0 +1,277 @@ +<?xml version="1.0" encoding="utf-8" ?> +<searchresults total_results="100"> + <addon> + <name>FAIL</name> + <type id='1'>Extension</type> + <guid>addon1@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://example.com/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <summary>Addon already installed - SEARCH</summary> + <description>Test description</description> + <compatible_applications> + <application> + <name>Firefox</name> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + <application> + <name>SeaMonkey</name> + <appID>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + </compatible_applications> + <compatible_os>ALL</compatible_os> + <install size="1">http://example.com/addon1.xpi</install> + </addon> + <addon> + <name>FAIL</name> + <type id='9'>lightweight theme</type> + <guid>addon12345@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://example.com/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <summary>Addon with uninstallable type shouldn't be visible in search</summary> + <description>Test description</description> + <compatible_applications> + <application> + <name>Firefox</name> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + <application> + <name>SeaMonkey</name> + <appID>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + </compatible_applications> + <compatible_os>ALL</compatible_os> + <install size="1">http://example.com/addon1.xpi</install> + </addon> + <addon> + <name>FAIL</name> + <type id='1'>Extension</type> + <guid>install1@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://example.com/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <summary>Install already exists - SEARCH</summary> + <description>Test description</description> + <compatible_applications> + <application> + <name>Firefox</name> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + <application> + <name>SeaMonkey</name> + <appID>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + </compatible_applications> + <compatible_os>ALL</compatible_os> + <install size="1">http://example.com/install1.xpi</install> + </addon> + <addon> + <name>PASS - b</name> + <type id='1'>Extension</type> + <guid>remote1@tests.mozilla.org</guid> + <version>3.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://example.com/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <summary>Test summary - SEARCH SEARCH</summary> + <description>Test description</description> + <compatible_applications> + <application> + <name>Firefox</name> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + <application> + <name>SeaMonkey</name> + <appID>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + </compatible_applications> + <compatible_os>ALL</compatible_os> + <install size="2">http://example.com/browser/toolkit/mozapps/extensions/test/browser/addons/browser_searching.xpi</install> + </addon> + <addon> + <name>PASS - d</name> + <type id='1'>Extension</type> + <guid>remote2@tests.mozilla.org</guid> + <version>4.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://example.com/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <summary>Test summary - SEARCHing SEARCH</summary> + <description>Test description</description> + <compatible_applications> + <application> + <name>Firefox</name> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + <application> + <name>SeaMonkey</name> + <appID>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + </compatible_applications> + <compatible_os>ALL</compatible_os> + <install size="5">http://example.com/remote2.xpi</install> + </addon> + <addon> + <name>PASS - e</name> + <type id='1'>Extension</type> + <guid>remote3@tests.mozilla.org</guid> + <version>5.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://example.com/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <summary>Test summary - Does not match query</summary> + <description>Test description</description> + <compatible_applications> + <application> + <name>Firefox</name> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + <application> + <name>SeaMonkey</name> + <appID>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + </compatible_applications> + <compatible_os>ALL</compatible_os> + <install size="1">http://example.com/remote3.xpi</install> + </addon> + <addon> + <name>PASS - h</name> + <type id='1'>Extension</type> + <guid>remote4@tests.mozilla.org</guid> + <version>6.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://example.com/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <summary>Test summary - SEARCHing SEARCH SEARCH</summary> + <description>Test description</description> + <compatible_applications> + <application> + <name>Firefox</name> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + <application> + <name>SeaMonkey</name> + <appID>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + </compatible_applications> + <compatible_os>ALL</compatible_os> + <install size="4">http://example.com/remote4.xpi</install> + </addon> + <addon> + <name>PASS - i</name> + <type id='1'>Extension</type> + <guid>remote5@tests.mozilla.org</guid> + <version>6.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://example.com/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <summary>Incompatible test</summary> + <description>Test description</description> + <compatible_applications> + <application> + <name>Firefox</name> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> + <min_version>0</min_version> + <max_version>1</max_version> + </application> + <application> + <name>SeaMonkey</name> + <appID>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</appID> + <min_version>0</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <compatible_os>ALL</compatible_os> + <install size="1">http://example.com/addon1.xpi</install> + </addon> + <addon> + <name>FAIL - j</name> + <type id='1'>Extension</type> + <guid>remote6@tests.mozilla.org</guid> + <version>6.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://example.com/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <summary>Incompatible test</summary> + <description>Test description</description> + <compatible_applications> + <application> + <name>Fake Product</name> + <appID>fakeproduct@mozilla.org</appID> + <min_version>0</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <compatible_os>ALL</compatible_os> + <install size="1">http://example.com/addon1.xpi</install> + </addon> +</searchresults> + diff --git a/toolkit/mozapps/extensions/test/browser/browser_searching_empty.xml b/toolkit/mozapps/extensions/test/browser/browser_searching_empty.xml new file mode 100644 index 000000000..24f6cb89f --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_searching_empty.xml @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="utf-8" ?> +<searchresults total_results="100" /> + diff --git a/toolkit/mozapps/extensions/test/browser/browser_select_compatoverrides.js b/toolkit/mozapps/extensions/test/browser/browser_select_compatoverrides.js new file mode 100644 index 000000000..747811e63 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_select_compatoverrides.js @@ -0,0 +1,116 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that compatibility overrides are refreshed when showing the addon +// selection UI. + +const PREF_GETADDONS_BYIDS = "extensions.getAddons.get.url"; +const PREF_MIN_PLATFORM_COMPAT = "extensions.minCompatiblePlatformVersion"; + +var gTestAddon = null; +var gWin; + +function waitForView(aView, aCallback) { + var view = gWin.document.getElementById(aView); + if (view.parentNode.selectedPanel == view) { + aCallback(); + return; + } + + view.addEventListener("ViewChanged", function() { + view.removeEventListener("ViewChanged", arguments.callee, false); + aCallback(); + }, false); +} + +function install_test_addon(aCallback) { + AddonManager.getInstallForURL(TESTROOT + "addons/browser_select_compatoverrides_1.xpi", function(aInstall) { + var listener = { + onInstallEnded: function() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(addon) { + gTestAddon = addon; + executeSoon(aCallback); + }); + } + }; + aInstall.addListener(listener); + aInstall.install(); + }, "application/x-xpinstall"); +} + +registerCleanupFunction(function() { + if (gWin) + gWin.close(); + if (gTestAddon) + gTestAddon.uninstall(); + + Services.prefs.clearUserPref(PREF_MIN_PLATFORM_COMPAT); +}); + +function end_test() { + finish(); +} + + +function test() { + waitForExplicitFinish(); + Services.prefs.setCharPref(PREF_UPDATEURL, TESTROOT + "missing.rdf"); + Services.prefs.setBoolPref(PREF_STRICT_COMPAT, false); + Services.prefs.setCharPref(PREF_MIN_PLATFORM_COMPAT, "0"); + + install_test_addon(run_next_test); +} + +add_test(function() { + gWin = Services.ww.openWindow(null, + "chrome://mozapps/content/extensions/selectAddons.xul", + "", + "chrome,centerscreen,dialog,titlebar", + null); + waitForFocus(function() { + waitForView("select", run_next_test); + }, gWin); +}); + +add_test(function() { + for (var row = gWin.document.getElementById("select-rows").firstChild; row; row = row.nextSibling) { + if (row.localName == "separator") + continue; + if (row.id.substr(-18) != "@tests.mozilla.org") + continue; + + is(row.id, "addon1@tests.mozilla.org", "Should get expected addon"); + isnot(row.action, "incompatible", "Addon should not be incompatible"); + + gWin.close(); + gWin = null; + run_next_test(); + } +}); + +add_test(function() { + Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, TESTROOT + "browser_select_compatoverrides.xml"); + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); + + gWin = Services.ww.openWindow(null, + "chrome://mozapps/content/extensions/selectAddons.xul", + "", + "chrome,centerscreen,dialog,titlebar", + null); + waitForFocus(function() { + waitForView("select", run_next_test); + }, gWin); +}); + +add_test(function() { + for (var row = gWin.document.getElementById("select-rows").firstChild; row; row = row.nextSibling) { + if (row.localName == "separator") + continue; + if (row.id.substr(-18) != "@tests.mozilla.org") + continue; + is(row.id, "addon1@tests.mozilla.org", "Should get expected addon"); + is(row.action, "incompatible", "Addon should be incompatible"); + run_next_test(); + } +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_select_compatoverrides.xml b/toolkit/mozapps/extensions/test/browser/browser_select_compatoverrides.xml new file mode 100644 index 000000000..76d00aa2c --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_select_compatoverrides.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8" ?> +<searchresults total_results="1"> + <addon_compatibility hosted="false"> + <guid>addon1@tests.mozilla.org</guid> + <name>Addon1</name> + <version_ranges> + <version_range type="incompatible"> + <min_version>1.0</min_version> + <max_version>2.0</max_version> + <compatible_applications> + <application> + <min_version>0.1</min_version> + <max_version>999.0</max_version> + <appID>toolkit@mozilla.org</appID> + </application> + </compatible_applications> + </version_range> + </version_ranges> + </addon_compatibility> +</searchresults> diff --git a/toolkit/mozapps/extensions/test/browser/browser_select_confirm.js b/toolkit/mozapps/extensions/test/browser/browser_select_confirm.js new file mode 100644 index 000000000..1204777ce --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_select_confirm.js @@ -0,0 +1,181 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests the confirmation part of the post-app-update dialog + +var gProvider; +var gWin; + +function waitForView(aView, aCallback) { + var view = gWin.document.getElementById(aView); + if (view.parentNode.selectedPanel == view) { + aCallback(); + return; + } + + view.addEventListener("ViewChanged", function() { + view.removeEventListener("ViewChanged", arguments.callee, false); + try { + aCallback(); + } + catch (e) { + ok(false, e); + } + }, false); +} + +/** + * Creates 4 test add-ons. Two are disabled and two enabled. + * + * @param aAppDisabled + * The appDisabled property for the test add-ons + * @param aUpdateAvailable + * True if the test add-ons should claim to have an update available + */ +function setupUI(aAppDisabled, aUpdateAvailable, aCallback) { + if (gProvider) + gProvider.unregister(); + + gProvider = new MockProvider(); + + for (var i = 1; i < 5; i++) { + var addon = new MockAddon("test" + i + "@tests.mozilla.org", + "Test Add-on " + i, "extension"); + addon.version = "1.0"; + addon.userDisabled = (i > 2); + addon.appDisabled = aAppDisabled; + addon.isActive = !addon.userDisabled && !addon.appDisabled; + + addon.findUpdates = function(aListener, aReason, aAppVersion, aPlatformVersion) { + if (aUpdateAvailable) { + var newAddon = new MockAddon(this.id, this.name, "extension"); + newAddon.version = "2.0"; + var install = new MockInstall(this.name, this.type, newAddon); + install.existingAddon = this; + aListener.onUpdateAvailable(this, install); + } + + aListener.onUpdateFinished(this, AddonManager.UPDATE_STATUS_NO_ERROR); + }; + + gProvider.addAddon(addon); + } + + gWin = Services.ww.openWindow(null, + "chrome://mozapps/content/extensions/selectAddons.xul", + "", + "chrome,centerscreen,dialog,titlebar", + null); + waitForFocus(function() { + waitForView("select", function() { + var row = gWin.document.getElementById("select-rows").firstChild.nextSibling; + while (row) { + if (!row.id || row.id.indexOf("@tests.mozilla.org") < 0) { + // not a test add-on + row = row.nextSibling; + continue; + } + + if (row.id == "test2@tests.mozilla.org" || + row.id == "test4@tests.mozilla.org") { + row.disable(); + } + else { + row.keep(); + } + row = row.nextSibling; + } + + waitForView("confirm", aCallback); + EventUtils.synthesizeMouseAtCenter(gWin.document.getElementById("next"), {}, gWin); + }); + }, gWin); +} + +function test() { + waitForExplicitFinish(); + + run_next_test(); +} + +function end_test() { + finish(); +} + +// Test for disabling +add_test(function disabling_test() { + setupUI(false, false, function() { + ok(gWin.document.getElementById("incompatible-list").hidden, "Incompatible list should be hidden"); + ok(gWin.document.getElementById("update-list").hidden, "Update list should be hidden"); + + var list = gWin.document.getElementById("disable-list"); + ok(!list.hidden, "Disable list should be visible"); + is(list.childNodes.length, 2, "Should be one add-on getting disabled (plus the header)"); + is(list.childNodes[1].id, "test2@tests.mozilla.org", "Should be the right add-on ID"); + is(list.childNodes[1].getAttribute("name"), "Test Add-on 2", "Should be the right add-on name"); + + var list = gWin.document.getElementById("enable-list"); + ok(!list.hidden, "Enable list should be visible"); + is(list.childNodes.length, 2, "Should be one add-on getting disabled (plus the header)"); + is(list.childNodes[1].id, "test3@tests.mozilla.org", "Should be the right add-on ID"); + is(list.childNodes[1].getAttribute("name"), "Test Add-on 3", "Should be the right add-on name"); + + ok(gWin.document.getElementById("next").hidden, "Next button should be hidden"); + ok(!gWin.document.getElementById("done").hidden, "Done button should be visible"); + gWin.close(); + + run_next_test(); + }); +}); + +// Test for incompatible +add_test(function incompatible_test() { + setupUI(true, false, function() { + ok(gWin.document.getElementById("update-list").hidden, "Update list should be hidden"); + ok(gWin.document.getElementById("disable-list").hidden, "Disable list should be hidden"); + ok(gWin.document.getElementById("enable-list").hidden, "Enable list should be hidden"); + + var list = gWin.document.getElementById("incompatible-list"); + ok(!list.hidden, "Incompatible list should be visible"); + is(list.childNodes.length, 3, "Should be two add-ons waiting to be compatible (plus the header)"); + is(list.childNodes[1].id, "test1@tests.mozilla.org", "Should be the right add-on ID"); + is(list.childNodes[1].getAttribute("name"), "Test Add-on 1", "Should be the right add-on name"); + is(list.childNodes[2].id, "test3@tests.mozilla.org", "Should be the right add-on ID"); + is(list.childNodes[2].getAttribute("name"), "Test Add-on 3", "Should be the right add-on name"); + + ok(gWin.document.getElementById("next").hidden, "Next button should be hidden"); + ok(!gWin.document.getElementById("done").hidden, "Done button should be visible"); + gWin.close(); + + run_next_test(); + }); +}); + +// Test for updates +add_test(function update_test() { + setupUI(false, true, function() { + ok(gWin.document.getElementById("incompatible-list").hidden, "Incompatible list should be hidden"); + ok(gWin.document.getElementById("enable-list").hidden, "Enable list should be hidden"); + + var list = gWin.document.getElementById("update-list"); + ok(!list.hidden, "Update list should be visible"); + is(list.childNodes.length, 3, "Should be two add-ons waiting to be updated (plus the header)"); + is(list.childNodes[1].id, "test1@tests.mozilla.org", "Should be the right add-on ID"); + is(list.childNodes[1].getAttribute("name"), "Test Add-on 1", "Should be the right add-on name"); + is(list.childNodes[2].id, "test3@tests.mozilla.org", "Should be the right add-on ID"); + is(list.childNodes[2].getAttribute("name"), "Test Add-on 3", "Should be the right add-on name"); + + list = gWin.document.getElementById("disable-list"); + ok(!list.hidden, "Disable list should be visible"); + is(list.childNodes.length, 2, "Should be one add-on getting disabled (plus the header)"); + is(list.childNodes[1].id, "test2@tests.mozilla.org", "Should be the right add-on ID"); + is(list.childNodes[1].getAttribute("name"), "Test Add-on 2", "Should be the right add-on name"); + + ok(!gWin.document.getElementById("next").hidden, "Next button should be visible"); + ok(gWin.document.getElementById("done").hidden, "Done button should be hidden"); + gWin.close(); + + run_next_test(); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_select_selection.js b/toolkit/mozapps/extensions/test/browser/browser_select_selection.js new file mode 100644 index 000000000..cf83e7c1e --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_select_selection.js @@ -0,0 +1,268 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests the selection part of the post-app-update dialog + +var gProvider; +var gWin; + +const PROFILE = AddonManager.SCOPE_PROFILE; +const USER = AddonManager.SCOPE_USER; +const APP = AddonManager.SCOPE_APPLICATION; +const SYSTEM = AddonManager.SCOPE_SYSTEM; +const DIST = -1; + +// The matrix of testcases for the selection part of the UI +// Note that the isActive flag has the value it had when the previous version +// of the application ran with this add-on. +var ADDONS = [ + //userDisabled wasAppDisabled isAppDisabled isActive hasUpdate autoUpdate scope defaultKeep position keepString disableString + [false, true, false, false, false, true, PROFILE, true, 42, "enabled", ""], // 0 + [false, true, false, false, true, true, PROFILE, true, 43, "enabled", ""], // 1 + [false, true, false, false, true, false, PROFILE, true, 52, "unneededupdate", ""], // 2 + [false, false, false, true, false, true, PROFILE, true, 53, "", "disabled"], // 3 + [false, false, false, true, true, true, PROFILE, true, 54, "", "disabled"], // 4 + [false, false, false, true, true, false, PROFILE, true, 55, "unneededupdate", "disabled"], // 5 + [false, true, true, false, false, true, PROFILE, true, 56, "incompatible", ""], // 6 + [false, true, true, false, true, true, PROFILE, true, 57, "autoupdate", ""], // 7 + [false, true, true, false, true, false, PROFILE, true, 58, "neededupdate", ""], // 8 + [false, false, true, true, false, true, PROFILE, true, 59, "incompatible", "disabled"], // 9 + [false, true, true, true, true, true, PROFILE, true, 44, "autoupdate", "disabled"], // 10 + [false, true, true, true, true, false, PROFILE, true, 45, "neededupdate", "disabled"], // 11 + [true, false, false, false, false, true, PROFILE, false, 46, "enabled", ""], // 12 + [true, false, false, false, true, true, PROFILE, false, 47, "enabled", ""], // 13 + [true, false, false, false, true, false, PROFILE, false, 48, "unneededupdate", ""], // 14 + + // userDisabled and isActive cannot be true on startup + + [true, true, true, false, false, true, PROFILE, false, 49, "incompatible", ""], // 15 + [true, true, true, false, true, true, PROFILE, false, 50, "autoupdate", ""], // 16 + [true, true, true, false, true, false, PROFILE, false, 51, "neededupdate", ""], // 17 + + // userDisabled and isActive cannot be true on startup + + // Being in a different scope should make little difference except no updates are possible so don't exhaustively test each + [false, false, false, true, true, false, USER, false, 0, "", "disabled"], // 18 + [true, true, false, false, true, false, USER, false, 1, "enabled", ""], // 19 + [false, true, true, true, true, false, USER, false, 2, "incompatible", "disabled"], // 20 + [true, true, true, false, true, false, USER, false, 3, "incompatible", ""], // 21 + [false, false, false, true, true, false, SYSTEM, false, 4, "", "disabled"], // 22 + [true, true, false, false, true, false, SYSTEM, false, 5, "enabled", ""], // 23 + [false, true, true, true, true, false, SYSTEM, false, 6, "incompatible", "disabled"], // 24 + [true, true, true, false, true, false, SYSTEM, false, 7, "incompatible", ""], // 25 + [false, false, false, true, true, false, APP, false, 8, "", "disabled"], // 26 + [true, true, false, false, true, false, APP, false, 9, "enabled", ""], // 27 + [false, true, true, true, true, false, APP, false, 10, "incompatible", "disabled"], // 28 + [true, true, true, false, true, false, APP, false, 11, "incompatible", ""], // 29 +]; + +function waitForView(aView, aCallback) { + var view = gWin.document.getElementById(aView); + if (view.parentNode.selectedPanel == view) { + aCallback(); + return; + } + + view.addEventListener("ViewChanged", function() { + view.removeEventListener("ViewChanged", arguments.callee, false); + aCallback(); + }, false); +} + +function getString(aName) { + if (!aName) + return ""; + + var strings = Services.strings.createBundle("chrome://mozapps/locale/extensions/selectAddons.properties"); + return strings.GetStringFromName("action." + aName); +} + +function getSourceString(aSource) { + if (!aSource) + return ""; + + var strings = Services.strings.createBundle("chrome://mozapps/locale/extensions/selectAddons.properties"); + switch (aSource) { + case PROFILE: + return strings.GetStringFromName("source.profile"); + case DIST: + return strings.GetStringFromName("source.bundled"); + default: + return strings.GetStringFromName("source.other"); + } +} + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + // Set prefs for Distributed Extension Source tests. + Services.prefs.setBoolPref("extensions.installedDistroAddon.test3@tests.mozilla.org", true); + Services.prefs.setBoolPref("extensions.installedDistroAddon.test12@tests.mozilla.org", true); + Services.prefs.setBoolPref("extensions.installedDistroAddon.test15@tests.mozilla.org", true); + + for (let pos in ADDONS) { + let addonItem = ADDONS[pos]; + let addon = new MockAddon("test" + pos + "@tests.mozilla.org", + "Test Add-on " + pos, "extension"); + addon.version = "1.0"; + addon.userDisabled = addonItem[0]; + addon.appDisabled = addonItem[1]; + addon.isActive = addonItem[3]; + addon.applyBackgroundUpdates = addonItem[5] ? AddonManager.AUTOUPDATE_ENABLE + : AddonManager.AUTOUPDATE_DISABLE; + addon.scope = addonItem[6]; + + // Remove the upgrade permission from non-profile add-ons + if (addon.scope != AddonManager.SCOPE_PROFILE) + addon._permissions -= AddonManager.PERM_CAN_UPGRADE; + + addon.findUpdates = function(aListener, aReason, aAppVersion, aPlatformVersion) { + addon.appDisabled = addonItem[2]; + addon.isActive = addon.shouldBeActive; + + if (addonItem[4]) { + var newAddon = new MockAddon(this.id, this.name, "extension"); + newAddon.version = "2.0"; + var install = new MockInstall(this.name, this.type, newAddon); + install.existingAddon = this; + aListener.onUpdateAvailable(this, install); + } + + aListener.onUpdateFinished(this, AddonManager.UPDATE_STATUS_NO_ERROR); + }; + + gProvider.addAddon(addon); + } + + gWin = Services.ww.openWindow(null, + "chrome://mozapps/content/extensions/selectAddons.xul", + "", + "chrome,centerscreen,dialog,titlebar", + null); + waitForFocus(function() { + waitForView("select", run_next_test); + }, gWin); +} + +function end_test() { + gWin.close(); + finish(); +} + +// Minimal test for the checking UI +add_test(function checking_test() { + // By the time we're here the progress bar should be full + var progress = gWin.document.getElementById("checking-progress"); + is(progress.mode, "determined", "Should be a determined progress bar"); + is(progress.value, progress.max, "Should be at full progress"); + + run_next_test(); +}); + +// Tests that the selection UI behaves correctly +add_test(function selection_test() { + function check_state() { + var str = addon[keep.checked ? 9 : 10]; + var expected = getString(str); + var showCheckbox = str == "neededupdate" || str == "unneededupdate"; + is(action.textContent, expected, "Action message should have the right text"); + is(!is_hidden(update), showCheckbox, "Checkbox should have the right visibility"); + is(is_hidden(action), showCheckbox, "Message should have the right visibility"); + if (showCheckbox) + ok(update.checked, "Optional update checkbox should be checked"); + + if (keep.checked) { + is(row.hasAttribute("active"), !addon[2] || hasUpdate, + "Add-on will be active if it isn't appDisabled or an update is available"); + + if (showCheckbox) { + info("Flipping update checkbox"); + EventUtils.synthesizeMouseAtCenter(update, { }, gWin); + is(row.hasAttribute("active"), str == "unneededupdate", + "If the optional update isn't needed then the add-on will still be active"); + + info("Flipping update checkbox"); + EventUtils.synthesizeMouseAtCenter(update, { }, gWin); + is(row.hasAttribute("active"), !addon[2] || hasUpdate, + "Add-on will be active if it isn't appDisabled or an update is available"); + } + } + else { + ok(!row.hasAttribute("active"), "Add-on won't be active when not keeping"); + + if (showCheckbox) { + info("Flipping update checkbox"); + EventUtils.synthesizeMouseAtCenter(update, { }, gWin); + ok(!row.hasAttribute("active"), + "Unchecking the update checkbox shouldn't make the add-on active"); + + info("Flipping update checkbox"); + EventUtils.synthesizeMouseAtCenter(update, { }, gWin); + ok(!row.hasAttribute("active"), + "Re-checking the update checkbox shouldn't make the add-on active"); + } + } + } + + is(gWin.document.getElementById("view-deck").selectedPanel.id, "select", + "Should be on the right view"); + + var pos = 0; + var scrollbox = gWin.document.getElementById("select-scrollbox"); + var scrollBoxObject = scrollbox.boxObject; + for (var row = gWin.document.getElementById("select-rows").firstChild; row; row = row.nextSibling) { + // Ignore separators but increase the position by a large amount so we + // can verify they were in the right place + if (row.localName == "separator") { + pos += 30; + continue; + } + + is(row._addon.type, "extension", "Should only be listing extensions"); + + // Ignore non-test add-ons that may be present + if (row.id.substr(-18) != "@tests.mozilla.org") + continue; + + var id = parseInt(row.id.substring(4, row.id.length - 18)); + var addon = ADDONS[id]; + + info("Testing add-on " + id); + scrollBoxObject.ensureElementIsVisible(row); + var keep = gWin.document.getAnonymousElementByAttribute(row, "anonid", "keep"); + var action = gWin.document.getAnonymousElementByAttribute(row, "class", "addon-action-message"); + var update = gWin.document.getAnonymousElementByAttribute(row, "anonid", "update"); + var source = gWin.document.getAnonymousElementByAttribute(row, "class", "addon-source"); + + if (id == 3 || id == 12 || id == 15) { + // Distro Installed To Profile + is(source.textContent, getSourceString(DIST), "Source message should have the right text for Distributed Addons"); + } else { + is(source.textContent, getSourceString(addon[6]), "Source message should have the right text"); + } + + // Non-profile add-ons don't appear to have updates since we won't install + // them + var hasUpdate = addon[4] && addon[6] == PROFILE; + + is(pos, addon[8], "Should have been in the right position"); + is(keep.checked, addon[7], "Keep checkbox should be in the right state"); + + check_state(); + + info("Flipping keep"); + EventUtils.synthesizeMouseAtCenter(keep, { }, gWin); + is(keep.checked, !addon[7], "Keep checkbox should be in the right state"); + + check_state(); + + pos++; + } + + is(pos, 60, "Should have seen the right number of add-ons"); + + run_next_test(); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_select_update.js b/toolkit/mozapps/extensions/test/browser/browser_select_update.js new file mode 100644 index 000000000..58f1de687 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_select_update.js @@ -0,0 +1,181 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests the update part of the post-app-update dialog + +var gProvider; +var gWin; + +function waitForView(aView, aCallback) { + var view = gWin.document.getElementById(aView); + if (view.parentNode.selectedPanel == view) { + aCallback(); + return; + } + + view.addEventListener("ViewChanged", function() { + view.removeEventListener("ViewChanged", arguments.callee, false); + aCallback(); + }, false); +} + +function waitForClose(aCallback) { + gWin.addEventListener("unload", function() { + gWin.removeEventListener("unload", arguments.callee, false); + + aCallback(); + }, false); +} + +/** + * Creates 4 test add-ons. Two are disabled and two enabled. + */ +function setupUI(aFailDownloads, aFailInstalls, aCallback) { + if (gProvider) + gProvider.unregister(); + + gProvider = new MockProvider(); + + for (var i = 1; i < 5; i++) { + var addon = new MockAddon("test" + i + "@tests.mozilla.org", + "Test Add-on " + i, "extension"); + addon.version = "1.0"; + addon.userDisabled = (i > 2); + addon.appDisabled = false; + addon.isActive = !addon.userDisabled && !addon.appDisabled; + + addon.findUpdates = function(aListener, aReason, aAppVersion, aPlatformVersion) { + var newAddon = new MockAddon(this.id, this.name, "extension"); + newAddon.version = "2.0"; + var install = new MockInstall(this.name, this.type, newAddon); + install.existingAddon = this; + + install.install = function() { + this.state = AddonManager.STATE_DOWNLOADING; + this.callListeners("onDownloadStarted"); + + var self = this; + executeSoon(function() { + if (aFailDownloads) { + self.state = AddonManager.STATE_DOWNLOAD_FAILED; + self.callListeners("onDownloadFailed"); + return; + } + + self.type = self._type; + self.addon = new MockAddon(self.existingAddon.id, self.name, self.type); + self.addon.version = self.version; + self.addon.pendingOperations = AddonManager.PENDING_INSTALL; + self.addon.install = self; + + self.existingAddon.pendingUpgrade = self.addon; + self.existingAddon.pendingOperations |= AddonManager.PENDING_UPGRADE; + + self.state = AddonManager.STATE_DOWNLOADED; + self.callListeners("onDownloadEnded"); + + self.state = AddonManager.STATE_INSTALLING; + self.callListeners("onInstallStarted"); + + if (aFailInstalls) { + self.state = AddonManager.STATE_INSTALL_FAILED; + self.callListeners("onInstallFailed"); + return; + } + + self.state = AddonManager.STATE_INSTALLED; + self.callListeners("onInstallEnded"); + }); + } + + aListener.onUpdateAvailable(this, install); + + aListener.onUpdateFinished(this, AddonManager.UPDATE_STATUS_NO_ERROR); + }; + + gProvider.addAddon(addon); + } + + gWin = Services.ww.openWindow(null, + "chrome://mozapps/content/extensions/selectAddons.xul", + "", + "chrome,centerscreen,dialog,titlebar", + null); + waitForFocus(function() { + waitForView("select", function() { + var row = gWin.document.getElementById("select-rows").firstChild.nextSibling; + while (row) { + if (!row.id || row.id.indexOf("@tests.mozilla.org") < 0) { + // not a test add-on + row = row.nextSibling; + continue; + } + + if (row.id == "test2@tests.mozilla.org" || + row.id == "test4@tests.mozilla.org") { + row.disable(); + } + else { + row.keep(); + } + row = row.nextSibling; + } + + waitForView("confirm", function() { + waitForView("update", aCallback); + EventUtils.synthesizeMouseAtCenter(gWin.document.getElementById("next"), {}, gWin); + }); + EventUtils.synthesizeMouseAtCenter(gWin.document.getElementById("next"), {}, gWin); + }); + }, gWin); +} + +function test() { + waitForExplicitFinish(); + run_next_test(); +} + +function end_test() { + finish(); +} + +// Test for working updates +add_test(function working_test() { + setupUI(false, false, function() { + waitForClose(function() { + is(gWin.document.getElementById("update-progress").value, 2, "Should have finished 2 downloads"); + run_next_test(); + }); + + EventUtils.synthesizeMouseAtCenter(gWin.document.getElementById("next"), {}, gWin); + }); +}); + +// Test for failed updates +add_test(function working_test() { + setupUI(true, false, function() { + waitForView("errors", function() { + is(gWin.document.getElementById("update-progress").value, 2, "Should have finished 2 downloads"); + gWin.close(); + + run_next_test(); + }); + + EventUtils.synthesizeMouseAtCenter(gWin.document.getElementById("next"), {}, gWin); + }); +}); + +// Test for failed updates +add_test(function working_test() { + setupUI(false, true, function() { + waitForView("errors", function() { + is(gWin.document.getElementById("update-progress").value, 2, "Should have finished 2 downloads"); + gWin.close(); + + run_next_test(); + }); + + EventUtils.synthesizeMouseAtCenter(gWin.document.getElementById("next"), {}, gWin); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_sorting.js b/toolkit/mozapps/extensions/test/browser/browser_sorting.js new file mode 100644 index 000000000..7bf697b36 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_sorting.js @@ -0,0 +1,372 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that sorting of add-ons works correctly +// (this test uses the list view, even though it no longer has sort buttons - see bug 623207) + +var gManagerWindow; +var gProvider; + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(); + gProvider.createAddons([{ + // enabledInstalled group + // * Enabled + // * Incompatible but enabled because compatibility checking is off + // * Waiting to be installed + // * Waiting to be enabled + id: "test1@tests.mozilla.org", + name: "Test add-on", + description: "foo", + updateDate: new Date(2010, 04, 02, 00, 00, 00), + size: 1, + pendingOperations: AddonManager.PENDING_NONE, + }, { + id: "test2@tests.mozilla.org", + name: "a first add-on", + description: "foo", + updateDate: new Date(2010, 04, 01, 23, 59, 59), + size: 0265, + pendingOperations: AddonManager.PENDING_UPGRADE, + isActive: true, + isCompatible: false, + }, { + id: "test3@tests.mozilla.org", + name: "\u010Cesk\u00FD slovn\u00EDk", // Český slovník + description: "foo", + updateDate: new Date(2010, 04, 02, 00, 00, 01), + size: 12, + pendingOperations: AddonManager.PENDING_INSTALL, + isActive: false, + }, { + id: "test4@tests.mozilla.org", + name: "canadian dictionary", + updateDate: new Date(1970, 0, 01, 00, 00, 00), + description: "foo", + isActive: true, + }, { + id: "test5@tests.mozilla.org", + name: "croatian dictionary", + description: "foo", + updateDate: new Date(2012, 12, 12, 00, 00, 00), + size: 5, + pendingOperations: AddonManager.PENDING_ENABLE, + isActive: false, + }, { + // pendingDisable group + // * Waiting to be disabled + id: "test6@tests.mozilla.org", + name: "orange Add-on", + description: "foo", + updateDate: new Date(2010, 04, 02, 00, 00, 00), + size: 142, + isCompatible: false, + isActive: true, + pendingOperations: AddonManager.PENDING_DISABLE, + }, { + id: "test7@tests.mozilla.org", + name: "Blue Add-on", + description: "foo", + updateDate: new Date(2010, 04, 01, 23, 59, 59), + size: 65, + isActive: true, + pendingOperations: AddonManager.PENDING_DISABLE, + }, { + id: "test8@tests.mozilla.org", + name: "Green Add-on", + description: "foo", + updateDate: new Date(2010, 04, 03, 00, 00, 01), + size: 125, + pendingOperations: AddonManager.PENDING_DISABLE, + }, { + id: "test9@tests.mozilla.org", + name: "red Add-on", + updateDate: new Date(2011, 04, 01, 00, 00, 00), + description: "foo", + isCompatible: false, + pendingOperations: AddonManager.PENDING_DISABLE, + }, { + id: "test10@tests.mozilla.org", + name: "Purple Add-on", + description: "foo", + updateDate: new Date(2012, 12, 12, 00, 00, 00), + size: 56, + isCompatible: false, + pendingOperations: AddonManager.PENDING_DISABLE, + }, { + // pendingUninstall group + // * Waiting to be removed + id: "test11@tests.mozilla.org", + name: "amber Add-on", + description: "foo", + updateDate: new Date(1978, 04, 02, 00, 00, 00), + size: 142, + isActive: false, + appDisabled: true, + pendingOperations: AddonManager.PENDING_UNINSTALL, + }, { + id: "test12@tests.mozilla.org", + name: "Salmon Add-on - pending disable", + description: "foo", + updateDate: new Date(2054, 04, 01, 23, 59, 59), + size: 65, + isActive: true, + pendingOperations: AddonManager.PENDING_UNINSTALL, + }, { + id: "test13@tests.mozilla.org", + name: "rose Add-on", + description: "foo", + updateDate: new Date(2010, 04, 02, 00, 00, 01), + size: 125, + isActive: false, + userDisabled: true, + pendingOperations: AddonManager.PENDING_UNINSTALL, + }, { + id: "test14@tests.mozilla.org", + name: "Violet Add-on", + updateDate: new Date(2010, 05, 01, 00, 00, 00), + description: "foo", + isActive: false, + appDisabled: true, + pendingOperations: AddonManager.PENDING_UNINSTALL, + }, { + id: "test15@tests.mozilla.org", + name: "white Add-on", + description: "foo", + updateDate: new Date(2010, 04, 12, 00, 00, 00), + size: 56, + isActive: false, + userDisabled: true, + pendingOperations: AddonManager.PENDING_UNINSTALL, + }, { + // disabledIncompatibleBlocked group + // * Disabled + // * Incompatible + // * Blocklisted + id: "test16@tests.mozilla.org", + name: "grimsby Add-on", + description: "foo", + updateDate: new Date(2010, 04, 01, 00, 00, 00), + size: 142, + isActive: false, + appDisabled: true, + }, { + id: "test17@tests.mozilla.org", + name: "beamsville Add-on", + description: "foo", + updateDate: new Date(2010, 04, 8, 23, 59, 59), + size: 65, + isActive: false, + userDisabled: true, + }, { + id: "test18@tests.mozilla.org", + name: "smithville Add-on", + description: "foo", + updateDate: new Date(2010, 04, 03, 00, 00, 01), + size: 125, + isActive: false, + userDisabled: true, + blocklistState: Ci.nsIBlocklistService.STATE_OUTDATED, + }, { + id: "test19@tests.mozilla.org", + name: "dunnville Add-on", + updateDate: new Date(2010, 04, 02, 00, 00, 00), + description: "foo", + isActive: false, + appDisabled: true, + isCompatible: false, + blocklistState: Ci.nsIBlocklistService.STATE_NOT_BLOCKED, + }, { + id: "test20@tests.mozilla.org", + name: "silverdale Add-on", + description: "foo", + updateDate: new Date(2010, 04, 12, 00, 00, 00), + size: 56, + isActive: false, + appDisabled: true, + blocklistState: Ci.nsIBlocklistService.STATE_BLOCKED, + }]); + + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, function() { + finish(); + }); +} + +function set_order(aSortBy, aAscending) { + var list = gManagerWindow.document.getElementById("addon-list"); + var elements = []; + var node = list.firstChild; + while (node) { + elements.push(node); + node = node.nextSibling; + } + gManagerWindow.sortElements(elements, ["uiState", aSortBy], aAscending); + for (let element of elements) + list.appendChild(element); +} + +function check_order(aExpectedOrder) { + var order = []; + var list = gManagerWindow.document.getElementById("addon-list"); + var node = list.firstChild; + while (node) { + var id = node.getAttribute("value"); + if (id && id.endsWith("@tests.mozilla.org")) + order.push(node.getAttribute("value")); + node = node.nextSibling; + } + + is(order.toSource(), aExpectedOrder.toSource(), "Should have seen the right order"); +} + +// Tests that ascending name ordering was the default +add_test(function() { + + check_order([ + "test2@tests.mozilla.org", + "test4@tests.mozilla.org", + "test3@tests.mozilla.org", + "test5@tests.mozilla.org", + "test1@tests.mozilla.org", + "test7@tests.mozilla.org", + "test8@tests.mozilla.org", + "test6@tests.mozilla.org", + "test10@tests.mozilla.org", + "test9@tests.mozilla.org", + "test11@tests.mozilla.org", + "test13@tests.mozilla.org", + "test12@tests.mozilla.org", + "test14@tests.mozilla.org", + "test15@tests.mozilla.org", + "test17@tests.mozilla.org", + "test19@tests.mozilla.org", + "test16@tests.mozilla.org", + "test20@tests.mozilla.org", + "test18@tests.mozilla.org", + ]); + run_next_test(); +}); + +// Tests that switching to date ordering works +add_test(function() { + set_order("updateDate", false); + + // When we're ascending with updateDate, it's from newest + // to oldest. + + check_order([ + "test5@tests.mozilla.org", + "test3@tests.mozilla.org", + "test1@tests.mozilla.org", + "test2@tests.mozilla.org", + "test4@tests.mozilla.org", + "test10@tests.mozilla.org", + "test9@tests.mozilla.org", + "test8@tests.mozilla.org", + "test6@tests.mozilla.org", + "test7@tests.mozilla.org", + "test12@tests.mozilla.org", + "test14@tests.mozilla.org", + "test15@tests.mozilla.org", + "test13@tests.mozilla.org", + "test11@tests.mozilla.org", + "test20@tests.mozilla.org", + "test17@tests.mozilla.org", + "test18@tests.mozilla.org", + "test19@tests.mozilla.org", + "test16@tests.mozilla.org", + ]); + + set_order("updateDate", true); + + check_order([ + "test4@tests.mozilla.org", + "test2@tests.mozilla.org", + "test1@tests.mozilla.org", + "test3@tests.mozilla.org", + "test5@tests.mozilla.org", + "test7@tests.mozilla.org", + "test6@tests.mozilla.org", + "test8@tests.mozilla.org", + "test9@tests.mozilla.org", + "test10@tests.mozilla.org", + "test11@tests.mozilla.org", + "test13@tests.mozilla.org", + "test15@tests.mozilla.org", + "test14@tests.mozilla.org", + "test12@tests.mozilla.org", + "test16@tests.mozilla.org", + "test19@tests.mozilla.org", + "test18@tests.mozilla.org", + "test17@tests.mozilla.org", + "test20@tests.mozilla.org", + ]); + + run_next_test(); +}); + +// Tests that switching to name ordering works +add_test(function() { + set_order("name", true); + + check_order([ + "test2@tests.mozilla.org", + "test4@tests.mozilla.org", + "test3@tests.mozilla.org", + "test5@tests.mozilla.org", + "test1@tests.mozilla.org", + "test7@tests.mozilla.org", + "test8@tests.mozilla.org", + "test6@tests.mozilla.org", + "test10@tests.mozilla.org", + "test9@tests.mozilla.org", + "test11@tests.mozilla.org", + "test13@tests.mozilla.org", + "test12@tests.mozilla.org", + "test14@tests.mozilla.org", + "test15@tests.mozilla.org", + "test17@tests.mozilla.org", + "test19@tests.mozilla.org", + "test16@tests.mozilla.org", + "test20@tests.mozilla.org", + "test18@tests.mozilla.org", + ]); + + set_order("name", false); + + check_order([ + "test1@tests.mozilla.org", + "test5@tests.mozilla.org", + "test3@tests.mozilla.org", + "test4@tests.mozilla.org", + "test2@tests.mozilla.org", + "test9@tests.mozilla.org", + "test10@tests.mozilla.org", + "test6@tests.mozilla.org", + "test8@tests.mozilla.org", + "test7@tests.mozilla.org", + "test15@tests.mozilla.org", + "test14@tests.mozilla.org", + "test12@tests.mozilla.org", + "test13@tests.mozilla.org", + "test11@tests.mozilla.org", + "test18@tests.mozilla.org", + "test20@tests.mozilla.org", + "test16@tests.mozilla.org", + "test19@tests.mozilla.org", + "test17@tests.mozilla.org", + ]); + + run_next_test(); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_sorting_plugins.js b/toolkit/mozapps/extensions/test/browser/browser_sorting_plugins.js new file mode 100644 index 000000000..2bb6b4ba4 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_sorting_plugins.js @@ -0,0 +1,95 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that sorting of plugins works correctly +// (this test checks that plugins with "ask to activate" state appear after those with +// "always activate" and before those with "never activate") + +var gManagerWindow; +var gProvider; + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(); + gProvider.createAddons([{ + // enabledInstalled group + // * Always activate + // * Ask to activate + // * Never activate + id: "test1@tests.mozilla.org", + name: "Java Applet Plug-in Java 7 Update 51", + description: "foo", + type: "plugin", + isActive: true, + userDisabled: AddonManager.STATE_ASK_TO_ACTIVATE + }, { + id: "test2@tests.mozilla.org", + name: "Quick Time Plug-in", + description: "foo", + type: "plugin", + isActive: true, + userDisabled: false + }, { + id: "test3@tests.mozilla.org", + name: "Shockwave Flash", + description: "foo", + type: "plugin", + isActive: false, + userDisabled: true + }, { + id: "test4@tests.mozilla.org", + name: "Adobe Reader Plug-in", + description: "foo", + type: "plugin", + isActive: true, + userDisabled: AddonManager.STATE_ASK_TO_ACTIVATE + }, { + id: "test5@tests.mozilla.org", + name: "3rd Party Plug-in", + description: "foo", + type: "plugin", + isActive: true, + userDisabled: false + }]); + + open_manager("addons://list/plugin", function(aWindow) { + gManagerWindow = aWindow; + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, function() { + finish(); + }); +} + +function check_order(aExpectedOrder) { + var order = []; + var list = gManagerWindow.document.getElementById("addon-list"); + var node = list.firstChild; + while (node) { + var id = node.getAttribute("value"); + if (id && id.endsWith("@tests.mozilla.org")) + order.push(node.getAttribute("value")); + node = node.nextSibling; + } + + is(order.toSource(), aExpectedOrder.toSource(), "Should have seen the right order"); +} + +// Tests that ascending name ordering was the default +add_test(function() { + + check_order([ + "test5@tests.mozilla.org", + "test2@tests.mozilla.org", + "test4@tests.mozilla.org", + "test1@tests.mozilla.org", + "test3@tests.mozilla.org" + ]); + + run_next_test(); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_tabsettings.js b/toolkit/mozapps/extensions/test/browser/browser_tabsettings.js new file mode 100644 index 000000000..2838698c7 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_tabsettings.js @@ -0,0 +1,100 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests various aspects of the details view + +var gManagerWindow; +var gCategoryUtilities; +var gProvider; + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + gProvider.createAddons([{ + id: "tabsettings@tests.mozilla.org", + name: "Tab Settings", + version: "1", + optionsURL: CHROMEROOT + "addon_prefs.xul", + optionsType: AddonManager.OPTIONS_TYPE_TAB + }]); + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, function() { + finish(); + }); +} + +add_test(function() { + var addon = get_addon_element(gManagerWindow, "tabsettings@tests.mozilla.org"); + is(addon.mAddon.optionsType, AddonManager.OPTIONS_TYPE_TAB, "Options should be inline type"); + addon.parentNode.ensureElementIsVisible(addon); + + var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "preferences-btn"); + is_element_visible(button, "Preferences button should be visible"); + + if (gUseInContentUI) { + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + + var browser = gBrowser.selectedBrowser; + browser.addEventListener("DOMContentLoaded", function() { + browser.removeEventListener("DOMContentLoaded", arguments.callee, false); + is(browser.currentURI.spec, addon.mAddon.optionsURL, "New tab should have loaded the options URL"); + browser.contentWindow.close(); + run_next_test(); + }, false); + return; + } + + let instantApply = Services.prefs.getBoolPref("browser.preferences.instantApply"); + + function observer(aSubject, aTopic, aData) { + switch (aTopic) { + case "domwindowclosed": + // Give the preference window a chance to finish closing before + // closing the add-ons manager. + waitForFocus(function () { + Services.ww.unregisterNotification(observer); + run_next_test(); + }); + break; + case "domwindowopened": + let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget); + waitForFocus(function () { + // If the openDialog privileges are wrong a new browser window + // will open, let the test proceed (and fail) rather than timeout. + if (win.location != addon.mAddon.optionsURL && + win.location != "chrome://browser/content/browser.xul") + return; + + is(win.location, addon.mAddon.optionsURL, + "The correct addon pref window should have opened"); + + let chromeFlags = win.QueryInterface(Ci.nsIInterfaceRequestor). + getInterface(Ci.nsIWebNavigation). + QueryInterface(Ci.nsIDocShellTreeItem).treeOwner. + QueryInterface(Ci.nsIInterfaceRequestor). + getInterface(Ci.nsIXULWindow).chromeFlags; + ok(chromeFlags & Ci.nsIWebBrowserChrome.CHROME_OPENAS_CHROME && + (instantApply || chromeFlags & Ci.nsIWebBrowserChrome.CHROME_OPENAS_DIALOG), + "Window was open as a chrome dialog."); + + win.close(); + }, win); + break; + } + } + + Services.ww.registerNotification(observer); + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_task_next_test.js b/toolkit/mozapps/extensions/test/browser/browser_task_next_test.js new file mode 100644 index 000000000..5ff2aff78 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_task_next_test.js @@ -0,0 +1,17 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test that we throw if a test created with add_task() +// calls run_next_test + +add_task(function* run_next_throws() { + let err = null; + try { + run_next_test(); + } catch (e) { + err = e; + info("run_next_test threw " + err); + } + ok(err, "run_next_test() should throw an error inside an add_task test"); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_types.js b/toolkit/mozapps/extensions/test/browser/browser_types.js new file mode 100644 index 000000000..8abb0ff73 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_types.js @@ -0,0 +1,473 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that registering new types works + +var gManagerWindow; +var gCategoryUtilities; + +var gProvider = { +}; + +var gTypes = [ + new AddonManagerPrivate.AddonType("type1", null, "Type 1", + AddonManager.VIEW_TYPE_LIST, 4500), + new AddonManagerPrivate.AddonType("missing1", null, "Missing 1"), + new AddonManagerPrivate.AddonType("type2", null, "Type 1", + AddonManager.VIEW_TYPE_LIST, 5100, + AddonManager.TYPE_UI_HIDE_EMPTY), + { + id: "type3", + name: "Type 3", + uiPriority: 5200, + viewType: AddonManager.VIEW_TYPE_LIST + } +]; + +function go_back(aManager) { + if (gUseInContentUI) { + gBrowser.goBack(); + } else { + EventUtils.synthesizeMouseAtCenter(aManager.document.getElementById("back-btn"), + { }, aManager); + } +} + +function go_forward(aManager) { + if (gUseInContentUI) { + gBrowser.goForward(); + } else { + EventUtils.synthesizeMouseAtCenter(aManager.document.getElementById("forward-btn"), + { }, aManager); + } +} + +function check_state(aManager, canGoBack, canGoForward) { + var doc = aManager.document; + + if (gUseInContentUI) { + is(gBrowser.canGoBack, canGoBack, "canGoBack should be correct"); + is(gBrowser.canGoForward, canGoForward, "canGoForward should be correct"); + } + + if (!is_hidden(doc.getElementById("back-btn"))) { + is(!doc.getElementById("back-btn").disabled, canGoBack, "Back button should have the right state"); + is(!doc.getElementById("forward-btn").disabled, canGoForward, "Forward button should have the right state"); + } +} + +function test() { + waitForExplicitFinish(); + + run_next_test(); +} + +function end_test() { + finish(); +} + +// Add a new type, open the manager and make sure it is in the right place +add_test(function() { + AddonManagerPrivate.registerProvider(gProvider, gTypes); + + open_manager(null, function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + ok(gCategoryUtilities.get("type1"), "Type 1 should be present"); + ok(gCategoryUtilities.get("type2"), "Type 2 should be present"); + ok(!gCategoryUtilities.get("missing1", true), "Missing 1 should be absent"); + + is(gCategoryUtilities.get("type1").previousSibling.getAttribute("value"), + "addons://list/extension", "Type 1 should be in the right place"); + is(gCategoryUtilities.get("type2").previousSibling.getAttribute("value"), + "addons://list/theme", "Type 2 should be in the right place"); + + ok(gCategoryUtilities.isTypeVisible("type1"), "Type 1 should be visible"); + ok(!gCategoryUtilities.isTypeVisible("type2"), "Type 2 should be hidden"); + + run_next_test(); + }); +}); + +// Select the type, close the manager and remove it then open the manager and +// check we're back to the default view +add_test(function() { + gCategoryUtilities.openType("type1", function() { + close_manager(gManagerWindow, function() { + AddonManagerPrivate.unregisterProvider(gProvider); + + open_manager(null, function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + ok(!gCategoryUtilities.get("type1", true), "Type 1 should be absent"); + ok(!gCategoryUtilities.get("type2", true), "Type 2 should be absent"); + ok(!gCategoryUtilities.get("missing1", true), "Missing 1 should be absent"); + + is(gCategoryUtilities.selectedCategory, "discover", "Should be back to the default view"); + + close_manager(gManagerWindow, run_next_test); + }); + }); + }); +}); + +// Add a type while the manager is still open and check it appears +add_test(function() { + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + ok(!gCategoryUtilities.get("type1", true), "Type 1 should be absent"); + ok(!gCategoryUtilities.get("type2", true), "Type 2 should be absent"); + ok(!gCategoryUtilities.get("missing1", true), "Missing 1 should be absent"); + + AddonManagerPrivate.registerProvider(gProvider, gTypes); + + ok(gCategoryUtilities.get("type1"), "Type 1 should be present"); + ok(gCategoryUtilities.get("type2"), "Type 2 should be present"); + ok(!gCategoryUtilities.get("missing1", true), "Missing 1 should be absent"); + + is(gCategoryUtilities.get("type1").previousSibling.getAttribute("value"), + "addons://list/extension", "Type 1 should be in the right place"); + is(gCategoryUtilities.get("type2").previousSibling.getAttribute("value"), + "addons://list/theme", "Type 2 should be in the right place"); + + ok(gCategoryUtilities.isTypeVisible("type1"), "Type 1 should be visible"); + ok(!gCategoryUtilities.isTypeVisible("type2"), "Type 2 should be hidden"); + + run_next_test(); + }); +}); + +// Remove the type while it is beng viewed and check it is replaced with the +// default view +add_test(function() { + gCategoryUtilities.openType("type1", function() { + gCategoryUtilities.openType("plugin", function() { + go_back(gManagerWindow); + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "type1", "Should be showing the custom view"); + check_state(gManagerWindow, true, true); + + AddonManagerPrivate.unregisterProvider(gProvider); + + ok(!gCategoryUtilities.get("type1", true), "Type 1 should be absent"); + ok(!gCategoryUtilities.get("type2", true), "Type 2 should be absent"); + ok(!gCategoryUtilities.get("missing1", true), "Missing 1 should be absent"); + + is(gCategoryUtilities.selectedCategory, "discover", "Should be back to the default view"); + check_state(gManagerWindow, true, true); + + go_back(gManagerWindow); + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "extension", "Should be showing the extension view"); + check_state(gManagerWindow, false, true); + + go_forward(gManagerWindow); + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "discover", "Should be back to the default view"); + check_state(gManagerWindow, true, true); + + go_forward(gManagerWindow); + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "plugin", "Should be back to the plugins view"); + check_state(gManagerWindow, true, false); + + go_back(gManagerWindow); + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "discover", "Should be back to the default view"); + check_state(gManagerWindow, true, true); + + close_manager(gManagerWindow, run_next_test); + }); + }); + }); + }); + }); + }); + }); +}); + +// Test that when going back to a now missing category we skip it +add_test(function() { + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + AddonManagerPrivate.registerProvider(gProvider, gTypes); + + ok(gCategoryUtilities.get("type1"), "Type 1 should be present"); + ok(gCategoryUtilities.isTypeVisible("type1"), "Type 1 should be visible"); + + gCategoryUtilities.openType("type1", function() { + gCategoryUtilities.openType("plugin", function() { + AddonManagerPrivate.unregisterProvider(gProvider); + + ok(!gCategoryUtilities.get("type1", true), "Type 1 should not be present"); + + go_back(gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "extension", "Should be back to the first view"); + check_state(gManagerWindow, false, true); + + close_manager(gManagerWindow, run_next_test); + }); + }); + }); + }); +}); + +// Test that when going forward to a now missing category we skip it +add_test(function() { + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + AddonManagerPrivate.registerProvider(gProvider, gTypes); + + ok(gCategoryUtilities.get("type1"), "Type 1 should be present"); + ok(gCategoryUtilities.isTypeVisible("type1"), "Type 1 should be visible"); + + gCategoryUtilities.openType("type1", function() { + gCategoryUtilities.openType("plugin", function() { + go_back(gManagerWindow); + wait_for_view_load(gManagerWindow, function() { + go_back(gManagerWindow); + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "extension", "Should be back to the extension view"); + + AddonManagerPrivate.unregisterProvider(gProvider); + + ok(!gCategoryUtilities.get("type1", true), "Type 1 should not be present"); + + go_forward(gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "plugin", "Should be back to the plugin view"); + check_state(gManagerWindow, true, false); + + close_manager(gManagerWindow, run_next_test); + }); + }); + }); + }); + }); + }); +}); + +// Test that when going back to a now missing category and we can't go back any +// any further then we just display the default view +add_test(function() { + AddonManagerPrivate.registerProvider(gProvider, gTypes); + + open_manager("addons://list/type1", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + is(gCategoryUtilities.selectedCategory, "type1", "Should be at the custom view"); + + ok(gCategoryUtilities.get("type1"), "Type 1 should be present"); + ok(gCategoryUtilities.isTypeVisible("type1"), "Type 1 should be visible"); + + gCategoryUtilities.openType("extension", function() { + AddonManagerPrivate.unregisterProvider(gProvider); + + ok(!gCategoryUtilities.get("type1", true), "Type 1 should not be present"); + + go_back(gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "discover", "Should be at the default view"); + check_state(gManagerWindow, false, true); + + close_manager(gManagerWindow, run_next_test); + }); + }); + }); +}); + +// Test that when going forward to a now missing category and we can't go +// forward any further then we just display the default view +add_test(function() { + AddonManagerPrivate.registerProvider(gProvider, gTypes); + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + ok(gCategoryUtilities.get("type1"), "Type 1 should be present"); + ok(gCategoryUtilities.isTypeVisible("type1"), "Type 1 should be visible"); + + gCategoryUtilities.openType("type1", function() { + go_back(gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "extension", "Should be at the extension view"); + + AddonManagerPrivate.unregisterProvider(gProvider); + + ok(!gCategoryUtilities.get("type1", true), "Type 1 should not be present"); + + go_forward(gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "discover", "Should be at the default view"); + check_state(gManagerWindow, true, false); + + close_manager(gManagerWindow, run_next_test); + }); + }); + }); + }); +}); + +// Test that when going back we skip multiple missing categories +add_test(function() { + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + AddonManagerPrivate.registerProvider(gProvider, gTypes); + + ok(gCategoryUtilities.get("type1"), "Type 1 should be present"); + ok(gCategoryUtilities.isTypeVisible("type1"), "Type 1 should be visible"); + + gCategoryUtilities.openType("type1", function() { + gCategoryUtilities.openType("type3", function() { + gCategoryUtilities.openType("plugin", function() { + AddonManagerPrivate.unregisterProvider(gProvider); + + ok(!gCategoryUtilities.get("type1", true), "Type 1 should not be present"); + + go_back(gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "extension", "Should be back to the first view"); + check_state(gManagerWindow, false, true); + + close_manager(gManagerWindow, run_next_test); + }); + }); + }); + }); + }); +}); + +// Test that when going forward we skip multiple missing categories +add_test(function() { + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + AddonManagerPrivate.registerProvider(gProvider, gTypes); + + ok(gCategoryUtilities.get("type1"), "Type 1 should be present"); + ok(gCategoryUtilities.isTypeVisible("type1"), "Type 1 should be visible"); + + gCategoryUtilities.openType("type1", function() { + gCategoryUtilities.openType("type3", function() { + gCategoryUtilities.openType("plugin", function() { + go_back(gManagerWindow); + wait_for_view_load(gManagerWindow, function() { + go_back(gManagerWindow); + wait_for_view_load(gManagerWindow, function() { + go_back(gManagerWindow); + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "extension", "Should be back to the extension view"); + + AddonManagerPrivate.unregisterProvider(gProvider); + + ok(!gCategoryUtilities.get("type1", true), "Type 1 should not be present"); + + go_forward(gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "plugin", "Should be back to the plugin view"); + check_state(gManagerWindow, true, false); + + close_manager(gManagerWindow, run_next_test); + }); + }); + }); + }); + }); + }); + }); + }); +}); + +// Test that when going back we skip all missing categories and when we can't go +// back any any further then we just display the default view +add_test(function() { + AddonManagerPrivate.registerProvider(gProvider, gTypes); + + open_manager("addons://list/type1", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + is(gCategoryUtilities.selectedCategory, "type1", "Should be at the custom view"); + + ok(gCategoryUtilities.get("type1"), "Type 1 should be present"); + ok(gCategoryUtilities.isTypeVisible("type1"), "Type 1 should be visible"); + + gCategoryUtilities.openType("type3", function() { + gCategoryUtilities.openType("extension", function() { + AddonManagerPrivate.unregisterProvider(gProvider); + + ok(!gCategoryUtilities.get("type1", true), "Type 1 should not be present"); + + go_back(gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "discover", "Should be at the default view"); + check_state(gManagerWindow, false, true); + + close_manager(gManagerWindow, run_next_test); + }); + }); + }); + }); +}); + +// Test that when going forward we skip all missing categories and when we can't +// go back any any further then we just display the default view +add_test(function() { + AddonManagerPrivate.registerProvider(gProvider, gTypes); + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + + ok(gCategoryUtilities.get("type1"), "Type 1 should be present"); + ok(gCategoryUtilities.isTypeVisible("type1"), "Type 1 should be visible"); + + gCategoryUtilities.openType("type1", function() { + gCategoryUtilities.openType("type3", function() { + go_back(gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + go_back(gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "extension", "Should be at the extension view"); + + AddonManagerPrivate.unregisterProvider(gProvider); + + ok(!gCategoryUtilities.get("type1", true), "Type 1 should not be present"); + + go_forward(gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "discover", "Should be at the default view"); + check_state(gManagerWindow, true, false); + + close_manager(gManagerWindow, run_next_test); + }); + }); + }); + }); + }); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_uninstalling.js b/toolkit/mozapps/extensions/test/browser/browser_uninstalling.js new file mode 100644 index 000000000..9fcb9de66 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_uninstalling.js @@ -0,0 +1,1099 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that searching for add-ons works correctly + +var gManagerWindow; +var gDocument; +var gCategoryUtilities; +var gProvider; + +function test() { + requestLongerTimeout(2); + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + gProvider.createAddons([{ + id: "addon1@tests.mozilla.org", + name: "Uninstall needs restart", + type: "extension", + operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_UNINSTALL + }, { + id: "addon2@tests.mozilla.org", + name: "Uninstall doesn't need restart 1", + type: "extension", + operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE + }, { + id: "addon3@tests.mozilla.org", + name: "Uninstall doesn't need restart 2", + type: "extension", + operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE + }, { + id: "addon4@tests.mozilla.org", + name: "Uninstall doesn't need restart 3", + type: "extension", + operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE + }, { + id: "addon5@tests.mozilla.org", + name: "Uninstall doesn't need restart 4", + type: "extension", + operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE + }, { + id: "addon6@tests.mozilla.org", + name: "Uninstall doesn't need restart 5", + type: "extension", + operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE + }, { + id: "addon7@tests.mozilla.org", + name: "Uninstall doesn't need restart 6", + type: "extension", + operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE + }, { + id: "addon8@tests.mozilla.org", + name: "Uninstall doesn't need restart 7", + type: "extension", + operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE + }, { + id: "addon9@tests.mozilla.org", + name: "Uninstall doesn't need restart 8", + type: "extension", + operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE + }]); + + open_manager(null, function(aWindow) { + gManagerWindow = aWindow; + gDocument = gManagerWindow.document; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, function() { + finish(); + }); +} + +function get_item_in_list(aId, aList) { + var item = aList.firstChild; + while (item) { + if ("mAddon" in item && item.mAddon.id == aId) { + aList.ensureElementIsVisible(item); + return item; + } + item = item.nextSibling; + } + return null; +} + +// Tests that uninstalling a normal add-on from the list view can be undone +add_test(function() { + var ID = "addon1@tests.mozilla.org"; + var list = gDocument.getElementById("addon-list"); + + // Select the extensions category + gCategoryUtilities.openType("extension", function() { + is(gCategoryUtilities.selectedCategory, "extension", "View should have changed to extension"); + + AddonManager.getAddonByID(ID, function(aAddon) { + ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall"); + ok(aAddon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_UNINSTALL, "Add-on should require a restart to uninstall"); + + var item = get_item_in_list(ID, list); + isnot(item, null, "Should have found the add-on in the list"); + + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + // Force XBL to apply + item.clientTop; + + is(item.getAttribute("pending"), "uninstall", "Add-on should be uninstalling"); + + ok(!!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should be pending uninstall"); + + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); + isnot(button, null, "Should have a restart button"); + ok(!button.hidden, "Restart button should not be hidden"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "undo-btn"); + isnot(button, null, "Should have an undo button"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + // Force XBL to apply + item.clientTop; + + ok(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL, "Add-on should be pending uninstall"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + run_next_test(); + }); + }); +}); + +// Tests that uninstalling a restartless add-on from the list view can be undone +add_test(function() { + var ID = "addon2@tests.mozilla.org"; + var list = gDocument.getElementById("addon-list"); + + // Select the extensions category + gCategoryUtilities.openType("extension", function() { + is(gCategoryUtilities.selectedCategory, "extension", "View should have changed to extension"); + + AddonManager.getAddonByID(ID, function(aAddon) { + ok(aAddon.isActive, "Add-on should be active"); + ok(!(aAddon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_UNINSTALL), "Add-on should not require a restart to uninstall"); + ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall"); + + var item = get_item_in_list(ID, list); + isnot(item, null, "Should have found the add-on in the list"); + + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + // Force XBL to apply + item.clientTop; + + is(item.getAttribute("pending"), "uninstall", "Add-on should be uninstalling"); + + ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall"); + ok(!aAddon.isActive, "Add-on should be inactive"); + + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); + isnot(button, null, "Should have a restart button"); + ok(button.hidden, "Restart button should be hidden"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "undo-btn"); + isnot(button, null, "Should have an undo button"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + // Force XBL to apply + item.clientTop; + + ok(aAddon.isActive, "Add-on should be active"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + run_next_test(); + }); + }); +}); + +// Tests that uninstalling a disabled restartless add-on from the list view can +// be undone and doesn't re-enable +add_test(function() { + var ID = "addon2@tests.mozilla.org"; + var list = gDocument.getElementById("addon-list"); + + // Select the extensions category + gCategoryUtilities.openType("extension", function() { + is(gCategoryUtilities.selectedCategory, "extension", "View should have changed to extension"); + + AddonManager.getAddonByID(ID, function(aAddon) { + aAddon.userDisabled = true; + + ok(!aAddon.isActive, "Add-on should be inactive"); + ok(!(aAddon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_UNINSTALL), "Add-on should not require a restart to uninstall"); + ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall"); + + var item = get_item_in_list(ID, list); + isnot(item, null, "Should have found the add-on in the list"); + + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + // Force XBL to apply + item.clientTop; + + is(item.getAttribute("pending"), "uninstall", "Add-on should be uninstalling"); + + ok(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL, "Add-on should be pending uninstall"); + ok(!aAddon.isActive, "Add-on should be inactive"); + + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); + isnot(button, null, "Should have a restart button"); + ok(button.hidden, "Restart button should be hidden"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "undo-btn"); + isnot(button, null, "Should have an undo button"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + // Force XBL to apply + item.clientTop; + + ok(!aAddon.isActive, "Add-on should be inactive"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + aAddon.userDisabled = false; + ok(aAddon.isActive, "Add-on should be active"); + + run_next_test(); + }); + }); +}); + +// Tests that uninstalling a normal add-on from the search view can be undone +add_test(function() { + var ID = "addon1@tests.mozilla.org"; + var list = gDocument.getElementById("search-list"); + + var searchBox = gManagerWindow.document.getElementById("header-search"); + searchBox.value = "Uninstall"; + + EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow); + EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "search", "View should have changed to search"); + + // Make sure to show local add-ons + EventUtils.synthesizeMouseAtCenter(gDocument.getElementById("search-filter-local"), { }, gManagerWindow); + + AddonManager.getAddonByID(ID, function(aAddon) { + ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall"); + ok(aAddon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_UNINSTALL, "Add-on should require a restart to uninstall"); + + var item = get_item_in_list(ID, list); + isnot(item, null, "Should have found the add-on in the list"); + + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + // Force XBL to apply + item.clientTop; + + is(item.getAttribute("pending"), "uninstall", "Add-on should be uninstalling"); + + ok(!!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should be pending uninstall"); + + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); + isnot(button, null, "Should have a restart button"); + ok(!button.hidden, "Restart button should not be hidden"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "undo-btn"); + isnot(button, null, "Should have an undo button"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + // Force XBL to apply + item.clientTop; + + ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + run_next_test(); + }); + }); +}); + +// Tests that uninstalling a restartless add-on from the search view can be undone +add_test(function() { + var ID = "addon2@tests.mozilla.org"; + var list = gDocument.getElementById("search-list"); + + var searchBox = gManagerWindow.document.getElementById("header-search"); + searchBox.value = "Uninstall"; + + EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow); + EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "search", "View should have changed to search"); + + // Make sure to show local add-ons + EventUtils.synthesizeMouseAtCenter(gDocument.getElementById("search-filter-local"), { }, gManagerWindow); + + AddonManager.getAddonByID(ID, function(aAddon) { + ok(aAddon.isActive, "Add-on should be active"); + ok(!(aAddon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_UNINSTALL), "Add-on should not require a restart to uninstall"); + ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall"); + + var item = get_item_in_list(ID, list); + isnot(item, null, "Should have found the add-on in the list"); + + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + // Force XBL to apply + item.clientTop; + + is(item.getAttribute("pending"), "uninstall", "Add-on should be uninstalling"); + + ok(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL, "Add-on should be pending uninstall"); + ok(!aAddon.isActive, "Add-on should be inactive"); + + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); + isnot(button, null, "Should have a restart button"); + ok(button.hidden, "Restart button should be hidden"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "undo-btn"); + isnot(button, null, "Should have an undo button"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + // Force XBL to apply + item.clientTop; + + ok(aAddon.isActive, "Add-on should be active"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + run_next_test(); + }); + }); +}); + +// Tests that uninstalling a disabled restartless add-on from the search view can +// be undone and doesn't re-enable +add_test(function() { + var ID = "addon2@tests.mozilla.org"; + var list = gDocument.getElementById("search-list"); + + var searchBox = gManagerWindow.document.getElementById("header-search"); + searchBox.value = "Uninstall"; + + EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow); + EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "search", "View should have changed to search"); + + // Make sure to show local add-ons + EventUtils.synthesizeMouseAtCenter(gDocument.getElementById("search-filter-local"), { }, gManagerWindow); + + AddonManager.getAddonByID(ID, function(aAddon) { + aAddon.userDisabled = true; + + ok(!aAddon.isActive, "Add-on should be inactive"); + ok(!(aAddon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_UNINSTALL), "Add-on should not require a restart to uninstall"); + ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall"); + + var item = get_item_in_list(ID, list); + isnot(item, null, "Should have found the add-on in the list"); + + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + // Force XBL to apply + item.clientTop; + + is(item.getAttribute("pending"), "uninstall", "Add-on should be uninstalling"); + + ok(!!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should be pending uninstall"); + ok(!aAddon.isActive, "Add-on should be inactive"); + + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); + isnot(button, null, "Should have a restart button"); + ok(button.hidden, "Restart button should be hidden"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "undo-btn"); + isnot(button, null, "Should have an undo button"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + // Force XBL to apply + item.clientTop; + + ok(!aAddon.isActive, "Add-on should be inactive"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + aAddon.userDisabled = false; + ok(aAddon.isActive, "Add-on should be active"); + + run_next_test(); + }); + }); +}); + +// Tests that uninstalling a normal add-on from the details view switches back +// to the list view and can be undone +add_test(function() { + var ID = "addon1@tests.mozilla.org"; + var list = gDocument.getElementById("addon-list"); + + // Select the extensions category + gCategoryUtilities.openType("extension", function() { + is(gCategoryUtilities.selectedCategory, "extension", "View should have changed to extension"); + + AddonManager.getAddonByID(ID, function(aAddon) { + ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall"); + ok(aAddon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_UNINSTALL, "Add-on should require a restart to uninstall"); + + var item = get_item_in_list(ID, list); + isnot(item, null, "Should have found the add-on in the list"); + + EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow); + EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow); + wait_for_view_load(gManagerWindow, function() { + is(gDocument.getElementById("view-port").selectedPanel.id, "detail-view", "Should be in the detail view"); + + var button = gDocument.getElementById("detail-uninstall-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "extension", "View should have changed to extension"); + + var item = get_item_in_list(ID, list); + isnot(item, null, "Should have found the add-on in the list"); + is(item.getAttribute("pending"), "uninstall", "Add-on should be uninstalling"); + + ok(!!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should be pending uninstall"); + + // Force XBL to apply + item.clientTop; + + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); + isnot(button, null, "Should have a restart button"); + ok(!button.hidden, "Restart button should not be hidden"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "undo-btn"); + isnot(button, null, "Should have an undo button"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + // Force XBL to apply + item.clientTop; + + ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + run_next_test(); + }); + }); + }); + }); +}); + +// Tests that uninstalling a restartless add-on from the details view switches +// back to the list view and can be undone +add_test(function() { + var ID = "addon2@tests.mozilla.org"; + var list = gDocument.getElementById("addon-list"); + + // Select the extensions category + gCategoryUtilities.openType("extension", function() { + is(gCategoryUtilities.selectedCategory, "extension", "View should have changed to extension"); + + AddonManager.getAddonByID(ID, function(aAddon) { + ok(aAddon.isActive, "Add-on should be active"); + ok(!(aAddon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_UNINSTALL), "Add-on should not require a restart to uninstall"); + ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall"); + + var item = get_item_in_list(ID, list); + isnot(item, null, "Should have found the add-on in the list"); + + EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow); + EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow); + wait_for_view_load(gManagerWindow, function() { + is(gDocument.getElementById("view-port").selectedPanel.id, "detail-view", "Should be in the detail view"); + + var button = gDocument.getElementById("detail-uninstall-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "extension", "View should have changed to extension"); + + var item = get_item_in_list(ID, list); + isnot(item, null, "Should have found the add-on in the list"); + is(item.getAttribute("pending"), "uninstall", "Add-on should be uninstalling"); + + ok(!!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should be pending uninstall"); + ok(!aAddon.isActive, "Add-on should be inactive"); + + // Force XBL to apply + item.clientTop; + + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); + isnot(button, null, "Should have a restart button"); + ok(button.hidden, "Restart button should be hidden"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "undo-btn"); + isnot(button, null, "Should have an undo button"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + // Force XBL to apply + item.clientTop; + + ok(aAddon.isActive, "Add-on should be active"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + run_next_test(); + }); + }); + }); + }); +}); + +// Tests that uninstalling a restartless add-on from the details view switches +// back to the list view and can be undone and doesn't re-enable +add_test(function() { + var ID = "addon2@tests.mozilla.org"; + var list = gDocument.getElementById("addon-list"); + + // Select the extensions category + gCategoryUtilities.openType("extension", function() { + is(gCategoryUtilities.selectedCategory, "extension", "View should have changed to extension"); + + AddonManager.getAddonByID(ID, function(aAddon) { + aAddon.userDisabled = true; + + ok(!aAddon.isActive, "Add-on should be inactive"); + ok(!(aAddon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_UNINSTALL), "Add-on should not require a restart to uninstall"); + ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall"); + + var item = get_item_in_list(ID, list); + isnot(item, null, "Should have found the add-on in the list"); + + EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow); + EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow); + wait_for_view_load(gManagerWindow, function() { + is(gDocument.getElementById("view-port").selectedPanel.id, "detail-view", "Should be in the detail view"); + + var button = gDocument.getElementById("detail-uninstall-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "extension", "View should have changed to extension"); + + var item = get_item_in_list(ID, list); + isnot(item, null, "Should have found the add-on in the list"); + is(item.getAttribute("pending"), "uninstall", "Add-on should be uninstalling"); + + ok(!!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should be pending uninstall"); + ok(!aAddon.isActive, "Add-on should be inactive"); + + // Force XBL to apply + item.clientTop; + + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); + isnot(button, null, "Should have a restart button"); + ok(button.hidden, "Restart button should be hidden"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "undo-btn"); + isnot(button, null, "Should have an undo button"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + // Force XBL to apply + item.clientTop; + + ok(!aAddon.isActive, "Add-on should be inactive"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + aAddon.userDisabled = false; + ok(aAddon.isActive, "Add-on should be active"); + + run_next_test(); + }); + }); + }); + }); +}); + +// Tests that a normal add-on pending uninstall shows up in the list view +add_test(function() { + var ID = "addon1@tests.mozilla.org"; + var list = gDocument.getElementById("addon-list"); + + // Select the extensions category + gCategoryUtilities.openType("extension", function() { + is(gCategoryUtilities.selectedCategory, "extension", "View should have changed to extension"); + + AddonManager.getAddonByID(ID, function(aAddon) { + ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall"); + ok(aAddon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_UNINSTALL, "Add-on should require a restart to uninstall"); + + var item = get_item_in_list(ID, list); + isnot(item, null, "Should have found the add-on in the list"); + + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + // Force XBL to apply + item.clientTop; + + is(item.getAttribute("pending"), "uninstall", "Add-on should be uninstalling"); + + ok(!!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should be pending uninstall"); + + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); + isnot(button, null, "Should have a restart button"); + ok(!button.hidden, "Restart button should not be hidden"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "undo-btn"); + isnot(button, null, "Should have an undo button"); + + gCategoryUtilities.openType("plugin", function() { + is(gCategoryUtilities.selectedCategory, "plugin", "View should have changed to plugin"); + gCategoryUtilities.openType("extension", function() { + is(gCategoryUtilities.selectedCategory, "extension", "View should have changed to extension"); + + var item = get_item_in_list(ID, list); + isnot(item, null, "Should have found the add-on in the list"); + is(item.getAttribute("pending"), "uninstall", "Add-on should be uninstalling"); + + ok(!!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should be pending uninstall"); + + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); + isnot(button, null, "Should have a restart button"); + ok(!button.hidden, "Restart button should not be hidden"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "undo-btn"); + isnot(button, null, "Should have an undo button"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + // Force XBL to apply + item.clientTop; + ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + run_next_test(); + }); + }); + }); + }); +}); + +// Tests that a normal add-on pending uninstall shows up in the search view +add_test(function() { + var ID = "addon1@tests.mozilla.org"; + var list = gDocument.getElementById("search-list"); + + var searchBox = gManagerWindow.document.getElementById("header-search"); + searchBox.value = "Uninstall"; + + EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow); + EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "search", "View should have changed to search"); + + // Make sure to show local add-ons + EventUtils.synthesizeMouseAtCenter(gDocument.getElementById("search-filter-local"), { }, gManagerWindow); + + AddonManager.getAddonByID(ID, function(aAddon) { + ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall"); + ok(aAddon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_UNINSTALL, "Add-on should require a restart to uninstall"); + + var item = get_item_in_list(ID, list); + isnot(item, null, "Should have found the add-on in the list"); + + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + // Force XBL to apply + item.clientTop; + + is(item.getAttribute("pending"), "uninstall", "Add-on should be uninstalling"); + + ok(!!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should be pending uninstall"); + + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); + isnot(button, null, "Should have a restart button"); + ok(!button.hidden, "Restart button should not be hidden"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "undo-btn"); + isnot(button, null, "Should have an undo button"); + + gCategoryUtilities.openType("plugin", function() { + is(gCategoryUtilities.selectedCategory, "plugin", "View should have changed to plugin"); + searchBox.value = "Uninstall"; + + EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow); + EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "search", "View should have changed to search"); + + var item = get_item_in_list(ID, list); + isnot(item, null, "Should have found the add-on in the list"); + is(item.getAttribute("pending"), "uninstall", "Add-on should be uninstalling"); + + ok(!!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should be pending uninstall"); + + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); + isnot(button, null, "Should have a restart button"); + ok(!button.hidden, "Restart button should not be hidden"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "undo-btn"); + isnot(button, null, "Should have an undo button"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + // Force XBL to apply + item.clientTop; + ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + run_next_test(); + }); + }); + }); + }); +}); + +// Tests that switching away from the list view finalises the uninstall of +// multiple restartless add-ons +add_test(function() { + var ID = "addon2@tests.mozilla.org"; + var ID2 = "addon6@tests.mozilla.org"; + var list = gDocument.getElementById("addon-list"); + + // Select the extensions category + gCategoryUtilities.openType("extension", function() { + is(gCategoryUtilities.selectedCategory, "extension", "View should have changed to extension"); + + AddonManager.getAddonByID(ID, function(aAddon) { + ok(aAddon.isActive, "Add-on should be active"); + ok(!(aAddon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_UNINSTALL), "Add-on should not require a restart to uninstall"); + ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall"); + + var item = get_item_in_list(ID, list); + isnot(item, null, "Should have found the add-on in the list"); + + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + // Force XBL to apply + item.clientTop; + + is(item.getAttribute("pending"), "uninstall", "Add-on should be uninstalling"); + + ok(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL, "Add-on should be pending uninstall"); + ok(!aAddon.isActive, "Add-on should be inactive"); + + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); + isnot(button, null, "Should have a restart button"); + ok(button.hidden, "Restart button should be hidden"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "undo-btn"); + isnot(button, null, "Should have an undo button"); + + item = get_item_in_list(ID2, list); + isnot(item, null, "Should have found the add-on in the list"); + + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + gCategoryUtilities.openType("plugin", function() { + is(gCategoryUtilities.selectedCategory, "plugin", "View should have changed to extension"); + + AddonManager.getAddonsByIDs([ID, ID2], function([aAddon, aAddon2]) { + is(aAddon, null, "Add-on should no longer be installed"); + is(aAddon2, null, "Second add-on should no longer be installed"); + + gCategoryUtilities.openType("extension", function() { + is(gCategoryUtilities.selectedCategory, "extension", "View should have changed to extension"); + + var item = get_item_in_list(ID, list); + is(item, null, "Should not have found the add-on in the list"); + item = get_item_in_list(ID2, list); + is(item, null, "Should not have found the second add-on in the list"); + + run_next_test(); + }); + }); + }); + }); + }); +}); + +// Tests that switching away from the search view finalises the uninstall of +// multiple restartless add-ons +add_test(function() { + var ID = "addon3@tests.mozilla.org"; + var ID2 = "addon7@tests.mozilla.org"; + var list = gDocument.getElementById("search-list"); + + var searchBox = gManagerWindow.document.getElementById("header-search"); + searchBox.value = "Uninstall"; + + EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow); + EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "search", "View should have changed to search"); + + // Make sure to show local add-ons + EventUtils.synthesizeMouseAtCenter(gDocument.getElementById("search-filter-local"), { }, gManagerWindow); + + AddonManager.getAddonByID(ID, function(aAddon) { + ok(aAddon.isActive, "Add-on should be active"); + ok(!(aAddon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_UNINSTALL), "Add-on should not require a restart to uninstall"); + ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall"); + + var item = get_item_in_list(ID, list); + isnot(item, null, "Should have found the add-on in the list"); + + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + // Force XBL to apply + item.clientTop; + + is(item.getAttribute("pending"), "uninstall", "Add-on should be uninstalling"); + + ok(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL, "Add-on should be pending uninstall"); + ok(!aAddon.isActive, "Add-on should be inactive"); + + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); + isnot(button, null, "Should have a restart button"); + ok(button.hidden, "Restart button should be hidden"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "undo-btn"); + isnot(button, null, "Should have an undo button"); + + item = get_item_in_list(ID2, list); + isnot(item, null, "Should have found the add-on in the list"); + + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + gCategoryUtilities.openType("plugin", function() { + is(gCategoryUtilities.selectedCategory, "plugin", "View should have changed to extension"); + + AddonManager.getAddonsByIDs([ID, ID2], function([aAddon, aAddon2]) { + is(aAddon, null, "Add-on should no longer be installed"); + is(aAddon2, null, "Second add-on should no longer be installed"); + + searchBox.value = "Uninstall"; + + EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow); + EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "search", "View should have changed to search"); + + var item = get_item_in_list(ID, list); + is(item, null, "Should not have found the add-on in the list"); + item = get_item_in_list(ID2, list); + is(item, null, "Should not have found the second add-on in the list"); + + run_next_test(); + }); + }); + }); + }); + }); +}); + +// Tests that closing the manager from the list view finalises the uninstall of +// multiple restartless add-ons +add_test(function() { + var ID = "addon4@tests.mozilla.org"; + var ID2 = "addon8@tests.mozilla.org"; + var list = gDocument.getElementById("addon-list"); + + // Select the extensions category + gCategoryUtilities.openType("extension", function() { + is(gCategoryUtilities.selectedCategory, "extension", "View should have changed to extension"); + + AddonManager.getAddonByID(ID, function(aAddon) { + ok(aAddon.isActive, "Add-on should be active"); + ok(!(aAddon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_UNINSTALL), "Add-on should not require a restart to uninstall"); + ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall"); + + var item = get_item_in_list(ID, list); + isnot(item, null, "Should have found the add-on in the list"); + + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + // Force XBL to apply + item.clientTop; + + is(item.getAttribute("pending"), "uninstall", "Add-on should be uninstalling"); + + ok(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL, "Add-on should be pending uninstall"); + ok(!aAddon.isActive, "Add-on should be inactive"); + + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); + isnot(button, null, "Should have a restart button"); + ok(button.hidden, "Restart button should be hidden"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "undo-btn"); + isnot(button, null, "Should have an undo button"); + + item = get_item_in_list(ID2, list); + isnot(item, null, "Should have found the add-on in the list"); + + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + close_manager(gManagerWindow, function() { + AddonManager.getAddonsByIDs([ID, ID2], function([aAddon, aAddon2]) { + is(aAddon, null, "Add-on should no longer be installed"); + is(aAddon2, null, "Second add-on should no longer be installed"); + + open_manager(null, function(aWindow) { + gManagerWindow = aWindow; + gDocument = gManagerWindow.document; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + var list = gDocument.getElementById("addon-list"); + + is(gCategoryUtilities.selectedCategory, "extension", "View should have changed to extension"); + + var item = get_item_in_list(ID, list); + is(item, null, "Should not have found the add-on in the list"); + item = get_item_in_list(ID2, list); + is(item, null, "Should not have found the second add-on in the list"); + + run_next_test(); + }); + }); + }); + }); + }); +}); + +// Tests that closing the manager from the search view finalises the uninstall +// of multiple restartless add-ons +add_test(function() { + var ID = "addon5@tests.mozilla.org"; + var ID2 = "addon9@tests.mozilla.org"; + var list = gDocument.getElementById("search-list"); + + var searchBox = gManagerWindow.document.getElementById("header-search"); + searchBox.value = "Uninstall"; + + EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow); + EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "search", "View should have changed to search"); + + // Make sure to show local add-ons + EventUtils.synthesizeMouseAtCenter(gDocument.getElementById("search-filter-local"), { }, gManagerWindow); + + AddonManager.getAddonByID(ID, function(aAddon) { + ok(aAddon.isActive, "Add-on should be active"); + ok(!(aAddon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_UNINSTALL), "Add-on should not require a restart to uninstall"); + ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall"); + + var item = get_item_in_list(ID, list); + isnot(item, null, "Should have found the add-on in the list"); + + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + // Force XBL to apply + item.clientTop; + + is(item.getAttribute("pending"), "uninstall", "Add-on should be uninstalling"); + + ok(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL, "Add-on should be pending uninstall"); + ok(!aAddon.isActive, "Add-on should be inactive"); + + var button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn"); + isnot(button, null, "Should have a restart button"); + ok(button.hidden, "Restart button should be hidden"); + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "undo-btn"); + isnot(button, null, "Should have an undo button"); + + item = get_item_in_list(ID2, list); + isnot(item, null, "Should have found the add-on in the list"); + + button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn"); + isnot(button, null, "Should have a remove button"); + ok(!button.disabled, "Button should not be disabled"); + + EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow); + + close_manager(gManagerWindow, function() { + AddonManager.getAddonsByIDs([ID, ID2], function([aAddon, aAddon2]) { + is(aAddon, null, "Add-on should no longer be installed"); + is(aAddon2, null, "Second add-on should no longer be installed"); + + open_manager(null, function(aWindow) { + gManagerWindow = aWindow; + gDocument = gManagerWindow.document; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + var list = gDocument.getElementById("search-list"); + var searchBox = gManagerWindow.document.getElementById("header-search"); + + searchBox.value = "Uninstall"; + + EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow); + EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, "search", "View should have changed to search"); + + var item = get_item_in_list(ID, list); + is(item, null, "Should not have found the add-on in the list"); + item = get_item_in_list(ID2, list); + is(item, null, "Should not have found the second add-on in the list"); + + run_next_test(); + }); + }); + }); + }); + }); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_updateid.js b/toolkit/mozapps/extensions/test/browser/browser_updateid.js new file mode 100644 index 000000000..a6672e825 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_updateid.js @@ -0,0 +1,80 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that updates that change an add-on's ID show up correctly in the UI + +var gProvider; +var gManagerWindow; +var gCategoryUtilities; + +var gApp = document.getElementById("bundle_brand").getString("brandShortName"); + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + gProvider.createAddons([{ + id: "addon1@tests.mozilla.org", + name: "manually updating addon", + version: "1.0", + applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE + }]); + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, function() { + finish(); + }); +} + +add_test(function() { + gCategoryUtilities.openType("extension", function() { + gProvider.createInstalls([{ + name: "updated add-on", + existingAddon: gProvider.addons[0], + version: "2.0" + }]); + var newAddon = new MockAddon("addon2@tests.mozilla.org"); + newAddon.name = "updated add-on"; + newAddon.version = "2.0"; + newAddon.pendingOperations = AddonManager.PENDING_INSTALL; + gProvider.installs[0]._addonToInstall = newAddon; + + var item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); + is(item._version.value, "1.0", "Should still show the old version in the normal list"); + var name = gManagerWindow.document.getAnonymousElementByAttribute(item, "anonid", "name"); + is(name.value, "manually updating addon", "Should show the old name in the list"); + var update = gManagerWindow.document.getAnonymousElementByAttribute(item, "anonid", "update-btn"); + is_element_visible(update, "Update button should be visible"); + + item = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org"); + is(item, null, "Should not show the new version in the list"); + + run_next_test(); + }); +}); + +add_test(function() { + var item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); + var update = gManagerWindow.document.getAnonymousElementByAttribute(item, "anonid", "update-btn"); + EventUtils.synthesizeMouseAtCenter(update, { }, gManagerWindow); + + var pending = gManagerWindow.document.getAnonymousElementByAttribute(item, "anonid", "pending"); + is_element_visible(pending, "Pending message should be visible"); + is(pending.textContent, + get_string("notification.upgrade", "manually updating addon", gApp), + "Pending message should be correct"); + + item = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org"); + is(item, null, "Should not show the new version in the list"); + + run_next_test(); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_updatessl.js b/toolkit/mozapps/extensions/test/browser/browser_updatessl.js new file mode 100644 index 000000000..7a9149aa5 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_updatessl.js @@ -0,0 +1,370 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +let tempScope = {}; +Components.utils.import("resource://gre/modules/addons/AddonUpdateChecker.jsm", tempScope); +let AddonUpdateChecker = tempScope.AddonUpdateChecker; + +const updaterdf = RELATIVE_DIR + "browser_updatessl.rdf"; +const redirect = RELATIVE_DIR + "redirect.sjs?"; +const SUCCESS = 0; +const DOWNLOAD_ERROR = AddonUpdateChecker.ERROR_DOWNLOAD_ERROR; + +const HTTP = "http://example.com/"; +const HTTPS = "https://example.com/"; +const NOCERT = "https://nocert.example.com/"; +const SELFSIGNED = "https://self-signed.example.com/"; +const UNTRUSTED = "https://untrusted.example.com/"; +const EXPIRED = "https://expired.example.com/"; + +const PREF_UPDATE_REQUIREBUILTINCERTS = "extensions.update.requireBuiltInCerts"; + +var gTests = []; +var gStart = 0; +var gLast = 0; + +var HTTPObserver = { + observeActivity: function(aChannel, aType, aSubtype, aTimestamp, aSizeData, + aStringData) { + aChannel.QueryInterface(Ci.nsIChannel); + + dump("*** HTTP Activity 0x" + aType.toString(16) + " 0x" + aSubtype.toString(16) + + " " + aChannel.URI.spec + "\n"); + } +}; + +function test() { + gStart = Date.now(); + requestLongerTimeout(4); + waitForExplicitFinish(); + + let observerService = Cc["@mozilla.org/network/http-activity-distributor;1"]. + getService(Ci.nsIHttpActivityDistributor); + observerService.addObserver(HTTPObserver); + + registerCleanupFunction(function() { + observerService.removeObserver(HTTPObserver); + }); + + run_next_test(); +} + +function end_test() { + Services.prefs.clearUserPref(PREF_UPDATE_REQUIREBUILTINCERTS); + + var cos = Cc["@mozilla.org/security/certoverride;1"]. + getService(Ci.nsICertOverrideService); + cos.clearValidityOverride("nocert.example.com", -1); + cos.clearValidityOverride("self-signed.example.com", -1); + cos.clearValidityOverride("untrusted.example.com", -1); + cos.clearValidityOverride("expired.example.com", -1); + + info("All tests completed in " + (Date.now() - gStart) + "ms"); + finish(); +} + +function add_update_test(mainURL, redirectURL, expectedStatus) { + gTests.push([mainURL, redirectURL, expectedStatus]); +} + +function run_update_tests(callback) { + function run_next_update_test() { + if (gTests.length == 0) { + callback(); + return; + } + gLast = Date.now(); + + let [mainURL, redirectURL, expectedStatus] = gTests.shift(); + if (redirectURL) { + var url = mainURL + redirect + redirectURL + updaterdf; + var message = "Should have seen the right result for an update check redirected from " + + mainURL + " to " + redirectURL; + } + else { + url = mainURL + updaterdf; + message = "Should have seen the right result for an update check from " + + mainURL; + } + + AddonUpdateChecker.checkForUpdates("addon1@tests.mozilla.org", + null, url, { + onUpdateCheckComplete: function(updates) { + is(updates.length, 1, "Should be the right number of results"); + is(SUCCESS, expectedStatus, message); + info("Update test ran in " + (Date.now() - gLast) + "ms"); + run_next_update_test(); + }, + + onUpdateCheckError: function(status) { + is(status, expectedStatus, message); + info("Update test ran in " + (Date.now() - gLast) + "ms"); + run_next_update_test(); + } + }); + } + + run_next_update_test(); +} + +// Add overrides for the bad certificates +function addCertOverrides() { + addCertOverride("nocert.example.com", Ci.nsICertOverrideService.ERROR_MISMATCH); + addCertOverride("self-signed.example.com", Ci.nsICertOverrideService.ERROR_UNTRUSTED); + addCertOverride("untrusted.example.com", Ci.nsICertOverrideService.ERROR_UNTRUSTED); + addCertOverride("expired.example.com", Ci.nsICertOverrideService.ERROR_TIME); +} + +// Runs tests with built-in certificates required and no certificate exceptions. +add_test(function() { + // Tests that a simple update.rdf retrieval works as expected. + add_update_test(HTTP, null, SUCCESS); + add_update_test(HTTPS, null, DOWNLOAD_ERROR); + add_update_test(NOCERT, null, DOWNLOAD_ERROR); + add_update_test(SELFSIGNED, null, DOWNLOAD_ERROR); + add_update_test(UNTRUSTED, null, DOWNLOAD_ERROR); + add_update_test(EXPIRED, null, DOWNLOAD_ERROR); + + // Tests that redirecting from http to other servers works as expected + add_update_test(HTTP, HTTP, SUCCESS); + add_update_test(HTTP, HTTPS, SUCCESS); + add_update_test(HTTP, NOCERT, DOWNLOAD_ERROR); + add_update_test(HTTP, SELFSIGNED, DOWNLOAD_ERROR); + add_update_test(HTTP, UNTRUSTED, DOWNLOAD_ERROR); + add_update_test(HTTP, EXPIRED, DOWNLOAD_ERROR); + + // Tests that redirecting from valid https to other servers works as expected + add_update_test(HTTPS, HTTP, DOWNLOAD_ERROR); + add_update_test(HTTPS, HTTPS, DOWNLOAD_ERROR); + add_update_test(HTTPS, NOCERT, DOWNLOAD_ERROR); + add_update_test(HTTPS, SELFSIGNED, DOWNLOAD_ERROR); + add_update_test(HTTPS, UNTRUSTED, DOWNLOAD_ERROR); + add_update_test(HTTPS, EXPIRED, DOWNLOAD_ERROR); + + // Tests that redirecting from nocert https to other servers works as expected + add_update_test(NOCERT, HTTP, DOWNLOAD_ERROR); + add_update_test(NOCERT, HTTPS, DOWNLOAD_ERROR); + add_update_test(NOCERT, NOCERT, DOWNLOAD_ERROR); + add_update_test(NOCERT, SELFSIGNED, DOWNLOAD_ERROR); + add_update_test(NOCERT, UNTRUSTED, DOWNLOAD_ERROR); + add_update_test(NOCERT, EXPIRED, DOWNLOAD_ERROR); + + // Tests that redirecting from self-signed https to other servers works as expected + add_update_test(SELFSIGNED, HTTP, DOWNLOAD_ERROR); + add_update_test(SELFSIGNED, HTTPS, DOWNLOAD_ERROR); + add_update_test(SELFSIGNED, NOCERT, DOWNLOAD_ERROR); + add_update_test(SELFSIGNED, SELFSIGNED, DOWNLOAD_ERROR); + add_update_test(SELFSIGNED, UNTRUSTED, DOWNLOAD_ERROR); + add_update_test(SELFSIGNED, EXPIRED, DOWNLOAD_ERROR); + + // Tests that redirecting from untrusted https to other servers works as expected + add_update_test(UNTRUSTED, HTTP, DOWNLOAD_ERROR); + add_update_test(UNTRUSTED, HTTPS, DOWNLOAD_ERROR); + add_update_test(UNTRUSTED, NOCERT, DOWNLOAD_ERROR); + add_update_test(UNTRUSTED, SELFSIGNED, DOWNLOAD_ERROR); + add_update_test(UNTRUSTED, UNTRUSTED, DOWNLOAD_ERROR); + add_update_test(UNTRUSTED, EXPIRED, DOWNLOAD_ERROR); + + // Tests that redirecting from expired https to other servers works as expected + add_update_test(EXPIRED, HTTP, DOWNLOAD_ERROR); + add_update_test(EXPIRED, HTTPS, DOWNLOAD_ERROR); + add_update_test(EXPIRED, NOCERT, DOWNLOAD_ERROR); + add_update_test(EXPIRED, SELFSIGNED, DOWNLOAD_ERROR); + add_update_test(EXPIRED, UNTRUSTED, DOWNLOAD_ERROR); + add_update_test(EXPIRED, EXPIRED, DOWNLOAD_ERROR); + + run_update_tests(run_next_test); +}); + +// Runs tests without requiring built-in certificates and no certificate +// exceptions. +add_test(function() { + Services.prefs.setBoolPref(PREF_UPDATE_REQUIREBUILTINCERTS, false); + + // Tests that a simple update.rdf retrieval works as expected. + add_update_test(HTTP, null, SUCCESS); + add_update_test(HTTPS, null, SUCCESS); + add_update_test(NOCERT, null, DOWNLOAD_ERROR); + add_update_test(SELFSIGNED, null, DOWNLOAD_ERROR); + add_update_test(UNTRUSTED, null, DOWNLOAD_ERROR); + add_update_test(EXPIRED, null, DOWNLOAD_ERROR); + + // Tests that redirecting from http to other servers works as expected + add_update_test(HTTP, HTTP, SUCCESS); + add_update_test(HTTP, HTTPS, SUCCESS); + add_update_test(HTTP, NOCERT, DOWNLOAD_ERROR); + add_update_test(HTTP, SELFSIGNED, DOWNLOAD_ERROR); + add_update_test(HTTP, UNTRUSTED, DOWNLOAD_ERROR); + add_update_test(HTTP, EXPIRED, DOWNLOAD_ERROR); + + // Tests that redirecting from valid https to other servers works as expected + add_update_test(HTTPS, HTTP, DOWNLOAD_ERROR); + add_update_test(HTTPS, HTTPS, SUCCESS); + add_update_test(HTTPS, NOCERT, DOWNLOAD_ERROR); + add_update_test(HTTPS, SELFSIGNED, DOWNLOAD_ERROR); + add_update_test(HTTPS, UNTRUSTED, DOWNLOAD_ERROR); + add_update_test(HTTPS, EXPIRED, DOWNLOAD_ERROR); + + // Tests that redirecting from nocert https to other servers works as expected + add_update_test(NOCERT, HTTP, DOWNLOAD_ERROR); + add_update_test(NOCERT, HTTPS, DOWNLOAD_ERROR); + add_update_test(NOCERT, NOCERT, DOWNLOAD_ERROR); + add_update_test(NOCERT, SELFSIGNED, DOWNLOAD_ERROR); + add_update_test(NOCERT, UNTRUSTED, DOWNLOAD_ERROR); + add_update_test(NOCERT, EXPIRED, DOWNLOAD_ERROR); + + // Tests that redirecting from self-signed https to other servers works as expected + add_update_test(SELFSIGNED, HTTP, DOWNLOAD_ERROR); + add_update_test(SELFSIGNED, HTTPS, DOWNLOAD_ERROR); + add_update_test(SELFSIGNED, NOCERT, DOWNLOAD_ERROR); + add_update_test(SELFSIGNED, SELFSIGNED, DOWNLOAD_ERROR); + add_update_test(SELFSIGNED, UNTRUSTED, DOWNLOAD_ERROR); + add_update_test(SELFSIGNED, EXPIRED, DOWNLOAD_ERROR); + + // Tests that redirecting from untrusted https to other servers works as expected + add_update_test(UNTRUSTED, HTTP, DOWNLOAD_ERROR); + add_update_test(UNTRUSTED, HTTPS, DOWNLOAD_ERROR); + add_update_test(UNTRUSTED, NOCERT, DOWNLOAD_ERROR); + add_update_test(UNTRUSTED, SELFSIGNED, DOWNLOAD_ERROR); + add_update_test(UNTRUSTED, UNTRUSTED, DOWNLOAD_ERROR); + add_update_test(UNTRUSTED, EXPIRED, DOWNLOAD_ERROR); + + // Tests that redirecting from expired https to other servers works as expected + add_update_test(EXPIRED, HTTP, DOWNLOAD_ERROR); + add_update_test(EXPIRED, HTTPS, DOWNLOAD_ERROR); + add_update_test(EXPIRED, NOCERT, DOWNLOAD_ERROR); + add_update_test(EXPIRED, SELFSIGNED, DOWNLOAD_ERROR); + add_update_test(EXPIRED, UNTRUSTED, DOWNLOAD_ERROR); + add_update_test(EXPIRED, EXPIRED, DOWNLOAD_ERROR); + + run_update_tests(run_next_test); +}); + +// Runs tests with built-in certificates required and all certificate exceptions. +add_test(function() { + Services.prefs.clearUserPref(PREF_UPDATE_REQUIREBUILTINCERTS); + addCertOverrides(); + + // Tests that a simple update.rdf retrieval works as expected. + add_update_test(HTTP, null, SUCCESS); + add_update_test(HTTPS, null, DOWNLOAD_ERROR); + add_update_test(NOCERT, null, DOWNLOAD_ERROR); + add_update_test(SELFSIGNED, null, DOWNLOAD_ERROR); + add_update_test(UNTRUSTED, null, DOWNLOAD_ERROR); + add_update_test(EXPIRED, null, DOWNLOAD_ERROR); + + // Tests that redirecting from http to other servers works as expected + add_update_test(HTTP, HTTP, SUCCESS); + add_update_test(HTTP, HTTPS, SUCCESS); + add_update_test(HTTP, NOCERT, SUCCESS); + add_update_test(HTTP, SELFSIGNED, SUCCESS); + add_update_test(HTTP, UNTRUSTED, SUCCESS); + add_update_test(HTTP, EXPIRED, SUCCESS); + + // Tests that redirecting from valid https to other servers works as expected + add_update_test(HTTPS, HTTP, DOWNLOAD_ERROR); + add_update_test(HTTPS, HTTPS, DOWNLOAD_ERROR); + add_update_test(HTTPS, NOCERT, DOWNLOAD_ERROR); + add_update_test(HTTPS, SELFSIGNED, DOWNLOAD_ERROR); + add_update_test(HTTPS, UNTRUSTED, DOWNLOAD_ERROR); + add_update_test(HTTPS, EXPIRED, DOWNLOAD_ERROR); + + // Tests that redirecting from nocert https to other servers works as expected + add_update_test(NOCERT, HTTP, DOWNLOAD_ERROR); + add_update_test(NOCERT, HTTPS, DOWNLOAD_ERROR); + add_update_test(NOCERT, NOCERT, DOWNLOAD_ERROR); + add_update_test(NOCERT, SELFSIGNED, DOWNLOAD_ERROR); + add_update_test(NOCERT, UNTRUSTED, DOWNLOAD_ERROR); + add_update_test(NOCERT, EXPIRED, DOWNLOAD_ERROR); + + // Tests that redirecting from self-signed https to other servers works as expected + add_update_test(SELFSIGNED, HTTP, DOWNLOAD_ERROR); + add_update_test(SELFSIGNED, HTTPS, DOWNLOAD_ERROR); + add_update_test(SELFSIGNED, NOCERT, DOWNLOAD_ERROR); + add_update_test(SELFSIGNED, SELFSIGNED, DOWNLOAD_ERROR); + add_update_test(SELFSIGNED, UNTRUSTED, DOWNLOAD_ERROR); + add_update_test(SELFSIGNED, EXPIRED, DOWNLOAD_ERROR); + + // Tests that redirecting from untrusted https to other servers works as expected + add_update_test(UNTRUSTED, HTTP, DOWNLOAD_ERROR); + add_update_test(UNTRUSTED, HTTPS, DOWNLOAD_ERROR); + add_update_test(UNTRUSTED, NOCERT, DOWNLOAD_ERROR); + add_update_test(UNTRUSTED, SELFSIGNED, DOWNLOAD_ERROR); + add_update_test(UNTRUSTED, UNTRUSTED, DOWNLOAD_ERROR); + add_update_test(UNTRUSTED, EXPIRED, DOWNLOAD_ERROR); + + // Tests that redirecting from expired https to other servers works as expected + add_update_test(EXPIRED, HTTP, DOWNLOAD_ERROR); + add_update_test(EXPIRED, HTTPS, DOWNLOAD_ERROR); + add_update_test(EXPIRED, NOCERT, DOWNLOAD_ERROR); + add_update_test(EXPIRED, SELFSIGNED, DOWNLOAD_ERROR); + add_update_test(EXPIRED, UNTRUSTED, DOWNLOAD_ERROR); + add_update_test(EXPIRED, EXPIRED, DOWNLOAD_ERROR); + + run_update_tests(run_next_test); +}); + +// Runs tests without requiring built-in certificates and all certificate +// exceptions. +add_test(function() { + Services.prefs.setBoolPref(PREF_UPDATE_REQUIREBUILTINCERTS, false); + + // Tests that a simple update.rdf retrieval works as expected. + add_update_test(HTTP, null, SUCCESS); + add_update_test(HTTPS, null, SUCCESS); + add_update_test(NOCERT, null, SUCCESS); + add_update_test(SELFSIGNED, null, SUCCESS); + add_update_test(UNTRUSTED, null, SUCCESS); + add_update_test(EXPIRED, null, SUCCESS); + + // Tests that redirecting from http to other servers works as expected + add_update_test(HTTP, HTTP, SUCCESS); + add_update_test(HTTP, HTTPS, SUCCESS); + add_update_test(HTTP, NOCERT, SUCCESS); + add_update_test(HTTP, SELFSIGNED, SUCCESS); + add_update_test(HTTP, UNTRUSTED, SUCCESS); + add_update_test(HTTP, EXPIRED, SUCCESS); + + // Tests that redirecting from valid https to other servers works as expected + add_update_test(HTTPS, HTTP, DOWNLOAD_ERROR); + add_update_test(HTTPS, HTTPS, SUCCESS); + add_update_test(HTTPS, NOCERT, SUCCESS); + add_update_test(HTTPS, SELFSIGNED, SUCCESS); + add_update_test(HTTPS, UNTRUSTED, SUCCESS); + add_update_test(HTTPS, EXPIRED, SUCCESS); + + // Tests that redirecting from nocert https to other servers works as expected + add_update_test(NOCERT, HTTP, DOWNLOAD_ERROR); + add_update_test(NOCERT, HTTPS, SUCCESS); + add_update_test(NOCERT, NOCERT, SUCCESS); + add_update_test(NOCERT, SELFSIGNED, SUCCESS); + add_update_test(NOCERT, UNTRUSTED, SUCCESS); + add_update_test(NOCERT, EXPIRED, SUCCESS); + + // Tests that redirecting from self-signed https to other servers works as expected + add_update_test(SELFSIGNED, HTTP, DOWNLOAD_ERROR); + add_update_test(SELFSIGNED, HTTPS, SUCCESS); + add_update_test(SELFSIGNED, NOCERT, SUCCESS); + add_update_test(SELFSIGNED, SELFSIGNED, SUCCESS); + add_update_test(SELFSIGNED, UNTRUSTED, SUCCESS); + add_update_test(SELFSIGNED, EXPIRED, SUCCESS); + + // Tests that redirecting from untrusted https to other servers works as expected + add_update_test(UNTRUSTED, HTTP, DOWNLOAD_ERROR); + add_update_test(UNTRUSTED, HTTPS, SUCCESS); + add_update_test(UNTRUSTED, NOCERT, SUCCESS); + add_update_test(UNTRUSTED, SELFSIGNED, SUCCESS); + add_update_test(UNTRUSTED, UNTRUSTED, SUCCESS); + add_update_test(UNTRUSTED, EXPIRED, SUCCESS); + + // Tests that redirecting from expired https to other servers works as expected + add_update_test(EXPIRED, HTTP, DOWNLOAD_ERROR); + add_update_test(EXPIRED, HTTPS, SUCCESS); + add_update_test(EXPIRED, NOCERT, SUCCESS); + add_update_test(EXPIRED, SELFSIGNED, SUCCESS); + add_update_test(EXPIRED, UNTRUSTED, SUCCESS); + add_update_test(EXPIRED, EXPIRED, SUCCESS); + + run_update_tests(run_next_test); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_updatessl.rdf b/toolkit/mozapps/extensions/test/browser/browser_updatessl.rdf new file mode 100644 index 000000000..f24573847 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_updatessl.rdf @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:extension:addon1@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>2.0</em:version> + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>20</em:maxVersion> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + +</RDF> diff --git a/toolkit/mozapps/extensions/test/browser/browser_updatessl.rdf^headers^ b/toolkit/mozapps/extensions/test/browser/browser_updatessl.rdf^headers^ new file mode 100644 index 000000000..2e4f8163b --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_updatessl.rdf^headers^ @@ -0,0 +1 @@ +Connection: close diff --git a/toolkit/mozapps/extensions/test/browser/cancelCompatCheck.sjs b/toolkit/mozapps/extensions/test/browser/cancelCompatCheck.sjs new file mode 100644 index 000000000..38bc25d08 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/cancelCompatCheck.sjs @@ -0,0 +1,43 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Delay before responding to an HTTP call attempting to read +// an addon update RDF file + +function handleRequest(req, resp) { + resp.processAsync(); + resp.setHeader("Cache-Control", "no-cache, no-store", false); + resp.setHeader("Content-Type", "text/xml;charset=utf-8", false); + + let file = null; + getObjectState("SERVER_ROOT", function(serverRoot) + { + file = serverRoot.getFile("browser/toolkit/mozapps/extensions/test/browser/browser_bug557956.rdf"); + }); + dump("*** cancelCompatCheck.sjs: " + file.path + "\n"); + let fstream = Components.classes["@mozilla.org/network/file-input-stream;1"]. + createInstance(Components.interfaces.nsIFileInputStream); + fstream.init(file, -1, 0, 0); + let cstream = null; + cstream = Components.classes["@mozilla.org/intl/converter-input-stream;1"]. + createInstance(Components.interfaces.nsIConverterInputStream); + cstream.init(fstream, "UTF-8", 0, 0); + + // The delay can be passed on the query string + let delay = req.queryString + 0; + + timer = Components.classes["@mozilla.org/timer;1"]. + createInstance(Components.interfaces.nsITimer); + timer.init(function sendFile() { + dump("cancelCompatCheck: starting to send file\n"); + let str = {}; + let read = 0; + do { + // read as much as we can and put it in str.value + read = cstream.readString(0xffffffff, str); + resp.write(str.value); + } while (read != 0); + cstream.close(); + resp.finish(); + }, delay, Components.interfaces.nsITimer.TYPE_ONE_SHOT); +} diff --git a/toolkit/mozapps/extensions/test/browser/discovery.html b/toolkit/mozapps/extensions/test/browser/discovery.html new file mode 100644 index 000000000..72f4fe374 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/discovery.html @@ -0,0 +1,10 @@ +<html> +<body> + <h1>Test page for the discovery pane</h1> + <p><a id="link-normal" href="https://example.com/browser/toolkit/mozapps/extensions/test/browser/discovery.html">Load normal</a></p> + <p><a id="link-http" href="http://example.com/browser/toolkit/mozapps/extensions/test/browser/discovery.html">Load insecure</a></p> + <p><a id="link-domain" href="https://test1.example.com/browser/toolkit/mozapps/extensions/test/browser/discovery.html">Load other domain</a></p> + <p><a id="link-bad" href="https://example.com/browser/toolkit/mozapps/extensions/test/browser/foo.html">Load missing page</a></p> + <p><a id="link-good" href="https://example.com/browser/toolkit/mozapps/extensions/test/browser/releaseNotes.xhtml">Load other page</a></p> +</body> +</html> diff --git a/toolkit/mozapps/extensions/test/browser/discovery_frame.html b/toolkit/mozapps/extensions/test/browser/discovery_frame.html new file mode 100644 index 000000000..ca0223a9c --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/discovery_frame.html @@ -0,0 +1,6 @@ +<!DOCTYPE html> + +<html> +<body> +<iframe id="frame" width="100%" height="100%" src="https://test1.example.com/browser/toolkit/mozapps/extensions/test/browser/discovery_install.html"></iframe> +</body> diff --git a/toolkit/mozapps/extensions/test/browser/discovery_install.html b/toolkit/mozapps/extensions/test/browser/discovery_install.html new file mode 100644 index 000000000..3832adff6 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/discovery_install.html @@ -0,0 +1,18 @@ +<html> +<head> +<script type="text/javascript"> +function install() { + InstallTrigger.install({ + "Test Add-on": { + URL: "https://example.com/browser/toolkit/mozapps/extensions/test/xpinstall/unsigned.xpi" + } + }); +} +</script> +</head> +<body> + <h1>Test page for the discovery pane</h1> + <p><a id="install-direct" href="https://example.com/browser/toolkit/mozapps/extensions/test/xpinstall/unsigned.xpi">Direct install</a></p> + <p><a id="install-js" href="javascript:install()">JS install</a></p> +</body> +</html> diff --git a/toolkit/mozapps/extensions/test/browser/head.js b/toolkit/mozapps/extensions/test/browser/head.js new file mode 100644 index 000000000..8e96b9b3f --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/head.js @@ -0,0 +1,1393 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +Components.utils.import("resource://gre/modules/NetUtil.jsm"); + +let tmp = {}; +Components.utils.import("resource://gre/modules/AddonManager.jsm", tmp); +Components.utils.import("resource://gre/modules/Log.jsm", tmp); +let AddonManager = tmp.AddonManager; +let AddonManagerPrivate = tmp.AddonManagerPrivate; +let Log = tmp.Log; + +var pathParts = gTestPath.split("/"); +// Drop the test filename +pathParts.splice(pathParts.length - 1, pathParts.length); + +var gTestInWindow = /-window$/.test(pathParts[pathParts.length - 1]); + +// Drop the UI type +if (gTestInWindow) { + pathParts.splice(pathParts.length - 1, pathParts.length); +} + +const RELATIVE_DIR = pathParts.slice(4).join("/") + "/"; + +const TESTROOT = "http://example.com/" + RELATIVE_DIR; +const TESTROOT2 = "http://example.org/" + RELATIVE_DIR; +const CHROMEROOT = pathParts.join("/") + "/"; +const PREF_DISCOVERURL = "extensions.webservice.discoverURL"; +const PREF_DISCOVER_ENABLED = "extensions.getAddons.showPane"; +const PREF_XPI_ENABLED = "xpinstall.enabled"; +const PREF_UPDATEURL = "extensions.update.url"; +const PREF_GETADDONS_CACHE_ENABLED = "extensions.getAddons.cache.enabled"; +const PREF_UI_LASTCATEGORY = "extensions.ui.lastCategory"; + +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 PREF_CHECK_COMPATIBILITY; +(function() { + var channel = "default"; + try { + channel = Services.prefs.getCharPref("app.update.channel"); + } catch (e) { } + if (channel != "aurora" && + channel != "beta" && + channel != "release") { + var version = "nightly"; + } else { + version = Services.appinfo.version.replace(/^([^\.]+\.[0-9]+[a-z]*).*/gi, "$1"); + } + PREF_CHECK_COMPATIBILITY = "extensions.checkCompatibility." + version; +})(); + +var gPendingTests = []; +var gTestsRun = 0; +var gTestStart = null; + +var gUseInContentUI = !gTestInWindow && ("switchToTabHavingURI" in window); + +var gRestorePrefs = [{name: PREF_LOGGING_ENABLED}, + {name: "extensions.webservice.discoverURL"}, + {name: "extensions.update.url"}, + {name: "extensions.update.background.url"}, + {name: "extensions.update.enabled"}, + {name: "extensions.update.autoUpdateDefault"}, + {name: "extensions.getAddons.get.url"}, + {name: "extensions.getAddons.getWithPerformance.url"}, + {name: "extensions.getAddons.search.browseURL"}, + {name: "extensions.getAddons.search.url"}, + {name: "extensions.getAddons.cache.enabled"}, + {name: "devtools.chrome.enabled"}, + {name: "devtools.debugger.remote-enabled"}, + {name: PREF_SEARCH_MAXRESULTS}, + {name: PREF_STRICT_COMPAT}, + {name: PREF_CHECK_COMPATIBILITY}]; + +for (let pref of gRestorePrefs) { + if (!Services.prefs.prefHasUserValue(pref.name)) { + pref.type = "clear"; + continue; + } + pref.type = Services.prefs.getPrefType(pref.name); + if (pref.type == Services.prefs.PREF_BOOL) + pref.value = Services.prefs.getBoolPref(pref.name); + else if (pref.type == Services.prefs.PREF_INT) + pref.value = Services.prefs.getIntPref(pref.name); + else if (pref.type == Services.prefs.PREF_STRING) + pref.value = Services.prefs.getCharPref(pref.name); +} + +// Turn logging on for all tests +Services.prefs.setBoolPref(PREF_LOGGING_ENABLED, true); + +// Helper to register test failures and close windows if any are left open +function checkOpenWindows(aWindowID) { + let windows = Services.wm.getEnumerator(aWindowID); + let found = false; + while (windows.hasMoreElements()) { + let win = windows.getNext().QueryInterface(Ci.nsIDOMWindow); + if (!win.closed) { + found = true; + win.close(); + } + } + if (found) + ok(false, "Found unexpected " + aWindowID + " window still open"); +} + +// Tools to disable and re-enable the background update and blocklist timers +// so that tests can protect themselves from unwanted timer events. +let gCatMan = Components.classes["@mozilla.org/categorymanager;1"] + .getService(Components.interfaces.nsICategoryManager); +// Default values from toolkit/mozapps/extensions/extensions.manifest, but disable*UpdateTimer() +// records the actual value so we can put it back in enable*UpdateTimer() +let backgroundUpdateConfig = "@mozilla.org/addons/integration;1,getService,addon-background-update-timer,extensions.update.interval,86400"; +let blocklistUpdateConfig = "@mozilla.org/extensions/blocklist;1,getService,blocklist-background-update-timer,extensions.blocklist.interval,86400"; + +let UTIMER = "update-timer"; +let AMANAGER = "addonManager"; +let BLOCKLIST = "nsBlocklistService"; + +function disableBackgroundUpdateTimer() { + info("Disabling " + UTIMER + " " + AMANAGER); + backgroundUpdateConfig = gCatMan.getCategoryEntry(UTIMER, AMANAGER); + gCatMan.deleteCategoryEntry(UTIMER, AMANAGER, true); +} + +function enableBackgroundUpdateTimer() { + info("Enabling " + UTIMER + " " + AMANAGER); + gCatMan.addCategoryEntry(UTIMER, AMANAGER, backgroundUpdateConfig, false, true); +} + +function disableBlocklistUpdateTimer() { + info("Disabling " + UTIMER + " " + BLOCKLIST); + blocklistUpdateConfig = gCatMan.getCategoryEntry(UTIMER, BLOCKLIST); + gCatMan.deleteCategoryEntry(UTIMER, BLOCKLIST, true); +} + +function enableBlocklistUpdateTimer() { + info("Enabling " + UTIMER + " " + BLOCKLIST); + gCatMan.addCategoryEntry(UTIMER, BLOCKLIST, blocklistUpdateConfig, false, true); +} + +registerCleanupFunction(function() { + // Restore prefs + for (let pref of gRestorePrefs) { + if (pref.type == "clear") + Services.prefs.clearUserPref(pref.name); + else if (pref.type == Services.prefs.PREF_BOOL) + Services.prefs.setBoolPref(pref.name, pref.value); + else if (pref.type == Services.prefs.PREF_INT) + Services.prefs.setIntPref(pref.name, pref.value); + else if (pref.type == Services.prefs.PREF_STRING) + Services.prefs.setCharPref(pref.name, pref.value); + } + + // Throw an error if the add-ons manager window is open anywhere + checkOpenWindows("Addons:Manager"); + checkOpenWindows("Addons:Compatibility"); + checkOpenWindows("Addons:Install"); + + return new Promise((resolve, reject) => AddonManager.getAllInstalls(resolve)) + .then(aInstalls => { + for (let install of aInstalls) { + if (install instanceof MockInstall) + continue; + + ok(false, "Should not have seen an install of " + install.sourceURI.spec + " in state " + install.state); + install.cancel(); + } + }); +}); + +function log_exceptions(aCallback, ...aArgs) { + try { + return aCallback.apply(null, aArgs); + } + catch (e) { + info("Exception thrown: " + e); + throw e; + } +} + +function log_callback(aPromise, aCallback) { + aPromise.then(aCallback) + .then(null, e => info("Exception thrown: " + e)); + return aPromise; +} + +function add_test(test) { + gPendingTests.push(test); +} + +function run_next_test() { + // Make sure we're not calling run_next_test from inside an add_task() test + // We're inside the browser_test.js 'testScope' here + if (this.__tasks) { + throw new Error("run_next_test() called from an add_task() test function. " + + "run_next_test() should not be called from inside add_task() " + + "under any circumstances!"); + } + if (gTestsRun > 0) + info("Test " + gTestsRun + " took " + (Date.now() - gTestStart) + "ms"); + + if (gPendingTests.length == 0) { + executeSoon(end_test); + return; + } + + gTestsRun++; + var test = gPendingTests.shift(); + if (test.name) + info("Running test " + gTestsRun + " (" + test.name + ")"); + else + info("Running test " + gTestsRun); + + gTestStart = Date.now(); + executeSoon(() => log_exceptions(test)); +} + +function get_addon_file_url(aFilename) { + try { + var cr = Cc["@mozilla.org/chrome/chrome-registry;1"]. + getService(Ci.nsIChromeRegistry); + var fileurl = cr.convertChromeURL(makeURI(CHROMEROOT + "addons/" + aFilename)); + return fileurl.QueryInterface(Ci.nsIFileURL); + } catch(ex) { + var jar = getJar(CHROMEROOT + "addons/" + aFilename); + var tmpDir = extractJarToTmp(jar); + tmpDir.append(aFilename); + + return Services.io.newFileURI(tmpDir).QueryInterface(Ci.nsIFileURL); + } +} + +function get_test_items_in_list(aManager) { + var tests = "@tests.mozilla.org"; + + let view = aManager.document.getElementById("view-port").selectedPanel; + let listid = view.id == "search-view" ? "search-list" : "addon-list"; + let item = aManager.document.getElementById(listid).firstChild; + let items = []; + + while (item) { + if (item.localName != "richlistitem") { + item = item.nextSibling; + continue; + } + + if (!item.mAddon || item.mAddon.id.substring(item.mAddon.id.length - tests.length) == tests) + items.push(item); + item = item.nextSibling; + } + + return items; +} + +function check_all_in_list(aManager, aIds, aIgnoreExtras) { + var doc = aManager.document; + var view = doc.getElementById("view-port").selectedPanel; + var listid = view.id == "search-view" ? "search-list" : "addon-list"; + var list = doc.getElementById(listid); + + var inlist = []; + var node = list.firstChild; + while (node) { + if (node.value) + inlist.push(node.value); + node = node.nextSibling; + } + + for (let id of aIds) { + if (inlist.indexOf(id) == -1) + ok(false, "Should find " + id + " in the list"); + } + + if (aIgnoreExtras) + return; + + for (let inlistItem of inlist) { + if (aIds.indexOf(inlistItem) == -1) + ok(false, "Shouldn't have seen " + inlistItem + " in the list"); + } +} + +function get_addon_element(aManager, aId) { + var doc = aManager.document; + var view = doc.getElementById("view-port").selectedPanel; + var listid = "addon-list"; + if (view.id == "search-view") + listid = "search-list"; + else if (view.id == "updates-view") + listid = "updates-list"; + var list = doc.getElementById(listid); + + var node = list.firstChild; + while (node) { + if (node.value == aId) + return node; + node = node.nextSibling; + } + return null; +} + +function wait_for_view_load(aManagerWindow, aCallback, aForceWait, aLongerTimeout) { + requestLongerTimeout(aLongerTimeout ? aLongerTimeout : 2); + + if (!aForceWait && !aManagerWindow.gViewController.isLoading) { + log_exceptions(aCallback, aManagerWindow); + return; + } + + aManagerWindow.document.addEventListener("ViewChanged", function() { + aManagerWindow.document.removeEventListener("ViewChanged", arguments.callee, false); + log_exceptions(aCallback, aManagerWindow); + }, false); +} + +function wait_for_manager_load(aManagerWindow, aCallback) { + if (!aManagerWindow.gIsInitializing) { + log_exceptions(aCallback, aManagerWindow); + return; + } + + info("Waiting for initialization"); + aManagerWindow.document.addEventListener("Initialized", function() { + aManagerWindow.document.removeEventListener("Initialized", arguments.callee, false); + log_exceptions(aCallback, aManagerWindow); + }, false); +} + +function open_manager(aView, aCallback, aLoadCallback, aLongerTimeout) { + let p = new Promise((resolve, reject) => { + + function setup_manager(aManagerWindow) { + if (aLoadCallback) + log_exceptions(aLoadCallback, aManagerWindow); + + if (aView) + aManagerWindow.loadView(aView); + + ok(aManagerWindow != null, "Should have an add-ons manager window"); + is(aManagerWindow.location, MANAGER_URI, "Should be displaying the correct UI"); + + waitForFocus(function() { + info("window has focus, waiting for manager load"); + wait_for_manager_load(aManagerWindow, function() { + info("Manager waiting for view load"); + wait_for_view_load(aManagerWindow, function() { + resolve(aManagerWindow); + }, null, aLongerTimeout); + }); + }, aManagerWindow); + } + + if (gUseInContentUI) { + info("Loading manager window in tab"); + Services.obs.addObserver(function (aSubject, aTopic, aData) { + Services.obs.removeObserver(arguments.callee, aTopic); + if (aSubject.location.href != MANAGER_URI) { + info("Ignoring load event for " + aSubject.location.href); + return; + } + setup_manager(aSubject); + }, "EM-loaded", false); + + gBrowser.selectedTab = gBrowser.addTab(); + switchToTabHavingURI(MANAGER_URI, true); + } else { + info("Loading manager window in dialog"); + Services.obs.addObserver(function (aSubject, aTopic, aData) { + Services.obs.removeObserver(arguments.callee, aTopic); + setup_manager(aSubject); + }, "EM-loaded", false); + + openDialog(MANAGER_URI); + } + }); + + // The promise resolves with the manager window, so it is passed to the callback + return log_callback(p, aCallback); +} + +function close_manager(aManagerWindow, aCallback, aLongerTimeout) { + let p = new Promise((resolve, reject) => { + requestLongerTimeout(aLongerTimeout ? aLongerTimeout : 2); + + ok(aManagerWindow != null, "Should have an add-ons manager window to close"); + is(aManagerWindow.location, MANAGER_URI, "Should be closing window with correct URI"); + + aManagerWindow.addEventListener("unload", function() { + try { + dump("Manager window unload handler\n"); + this.removeEventListener("unload", arguments.callee, false); + resolve(); + } catch(e) { + reject(e); + } + }, false); + }); + + info("Telling manager window to close"); + aManagerWindow.close(); + info("Manager window close() call returned"); + + return log_callback(p, aCallback); +} + +function restart_manager(aManagerWindow, aView, aCallback, aLoadCallback) { + if (!aManagerWindow) { + return open_manager(aView, aCallback, aLoadCallback); + } + + return close_manager(aManagerWindow) + .then(() => open_manager(aView, aCallback, aLoadCallback)); +} + +function wait_for_window_open(aCallback) { + Services.wm.addListener({ + onOpenWindow: function(aWindow) { + Services.wm.removeListener(this); + + let domwindow = aWindow.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindow); + domwindow.addEventListener("load", function() { + domwindow.removeEventListener("load", arguments.callee, false); + executeSoon(function() { + aCallback(domwindow); + }); + }, false); + }, + + onCloseWindow: function(aWindow) { + }, + + onWindowTitleChange: function(aWindow, aTitle) { + } + }); +} + +function get_string(aName, ...aArgs) { + var bundle = Services.strings.createBundle("chrome://mozapps/locale/extensions/extensions.properties"); + if (aArgs.length == 0) + return bundle.GetStringFromName(aName); + return bundle.formatStringFromName(aName, aArgs, aArgs.length); +} + +function formatDate(aDate) { + return Cc["@mozilla.org/intl/scriptabledateformat;1"] + .getService(Ci.nsIScriptableDateFormat) + .FormatDate("", + Ci.nsIScriptableDateFormat.dateFormatLong, + aDate.getFullYear(), + aDate.getMonth() + 1, + aDate.getDate() + ); +} + +function is_hidden(aElement) { + var style = aElement.ownerDocument.defaultView.getComputedStyle(aElement, ""); + if (style.display == "none") + return true; + if (style.visibility != "visible") + return true; + + // Hiding a parent element will hide all its children + if (aElement.parentNode != aElement.ownerDocument) + return is_hidden(aElement.parentNode); + + return false; +} + +function is_element_visible(aElement, aMsg) { + isnot(aElement, null, "Element should not be null, when checking visibility"); + ok(!is_hidden(aElement), aMsg || (aElement + " should be visible")); +} + +function is_element_hidden(aElement, aMsg) { + isnot(aElement, null, "Element should not be null, when checking visibility"); + ok(is_hidden(aElement), aMsg || (aElement + " should be hidden")); +} + +/** + * Install an add-on and call a callback when complete. + * + * The callback will receive the Addon for the installed add-on. + */ +function install_addon(path, cb, pathPrefix=TESTROOT) { + let p = new Promise((resolve, reject) => { + AddonManager.getInstallForURL(pathPrefix + path, (install) => { + install.addListener({ + onInstallEnded: () => resolve(install.addon), + }); + + install.install(); + }, "application/x-xpinstall"); + }); + + return log_callback(p, cb); +} + +function CategoryUtilities(aManagerWindow) { + this.window = aManagerWindow; + + var self = this; + this.window.addEventListener("unload", function() { + self.window.removeEventListener("unload", arguments.callee, false); + self.window = null; + }, false); +} + +CategoryUtilities.prototype = { + window: null, + + get selectedCategory() { + isnot(this.window, null, "Should not get selected category when manager window is not loaded"); + var selectedItem = this.window.document.getElementById("categories").selectedItem; + isnot(selectedItem, null, "A category should be selected"); + var view = this.window.gViewController.parseViewId(selectedItem.value); + return (view.type == "list") ? view.param : view.type; + }, + + get: function(aCategoryType, aAllowMissing) { + isnot(this.window, null, "Should not get category when manager window is not loaded"); + var categories = this.window.document.getElementById("categories"); + + var viewId = "addons://list/" + aCategoryType; + var items = categories.getElementsByAttribute("value", viewId); + if (items.length) + return items[0]; + + viewId = "addons://" + aCategoryType + "/"; + items = categories.getElementsByAttribute("value", viewId); + if (items.length) + return items[0]; + + if (!aAllowMissing) + ok(false, "Should have found a category with type " + aCategoryType); + return null; + }, + + getViewId: function(aCategoryType) { + isnot(this.window, null, "Should not get view id when manager window is not loaded"); + return this.get(aCategoryType).value; + }, + + isVisible: function(aCategory) { + isnot(this.window, null, "Should not check visible state when manager window is not loaded"); + if (aCategory.hasAttribute("disabled") && + aCategory.getAttribute("disabled") == "true") + return false; + + return !is_hidden(aCategory); + }, + + isTypeVisible: function(aCategoryType) { + return this.isVisible(this.get(aCategoryType)); + }, + + open: function(aCategory, aCallback) { + + isnot(this.window, null, "Should not open category when manager window is not loaded"); + ok(this.isVisible(aCategory), "Category should be visible if attempting to open it"); + + EventUtils.synthesizeMouse(aCategory, 2, 2, { }, this.window); + let p = new Promise((resolve, reject) => wait_for_view_load(this.window, resolve)); + + return log_callback(p, aCallback); + }, + + openType: function(aCategoryType, aCallback) { + return this.open(this.get(aCategoryType), aCallback); + } +} + +function CertOverrideListener(host, bits) { + this.host = host; + this.bits = bits; +} + +CertOverrideListener.prototype = { + host: null, + bits: null, + + getInterface: function (aIID) { + return this.QueryInterface(aIID); + }, + + QueryInterface: function(aIID) { + if (aIID.equals(Ci.nsIBadCertListener2) || + aIID.equals(Ci.nsIInterfaceRequestor) || + aIID.equals(Ci.nsISupports)) + return this; + + throw Components.Exception("No interface", Components.results.NS_ERROR_NO_INTERFACE); + }, + + notifyCertProblem: function (socketInfo, sslStatus, targetHost) { + var cert = sslStatus.QueryInterface(Components.interfaces.nsISSLStatus) + .serverCert; + var cos = Cc["@mozilla.org/security/certoverride;1"]. + getService(Ci.nsICertOverrideService); + cos.rememberValidityOverride(this.host, -1, cert, this.bits, false); + return true; + } +} + +// Add overrides for the bad certificates +function addCertOverride(host, bits) { + var req = new XMLHttpRequest(); + try { + req.open("GET", "https://" + host + "/", false); + req.channel.notificationCallbacks = new CertOverrideListener(host, bits); + req.send(null); + } + catch (e) { + // This request will fail since the SSL server is not trusted yet + } +} + +/***** Mock Provider *****/ + +function MockProvider(aUseAsyncCallbacks, aTypes) { + this.addons = []; + this.installs = []; + this.callbackTimers = []; + this.timerLocations = new Map(); + this.useAsyncCallbacks = (aUseAsyncCallbacks === undefined) ? true : aUseAsyncCallbacks; + this.types = (aTypes === undefined) ? [{ + id: "extension", + name: "Extensions", + uiPriority: 4000, + flags: AddonManager.TYPE_UI_VIEW_LIST | + AddonManager.TYPE_SUPPORTS_UNDO_RESTARTLESS_UNINSTALL, + }] : aTypes; + + var self = this; + registerCleanupFunction(function() { + if (self.started) + self.unregister(); + }); + + this.register(); +} + +MockProvider.prototype = { + addons: null, + installs: null, + started: null, + apiDelay: 10, + callbackTimers: null, + timerLocations: null, + useAsyncCallbacks: null, + types: null, + + /***** Utility functions *****/ + + /** + * Register this provider with the AddonManager + */ + register: function MP_register() { + info("Registering mock add-on provider"); + AddonManagerPrivate.registerProvider(this, this.types); + }, + + /** + * Unregister this provider with the AddonManager + */ + unregister: function MP_unregister() { + info("Unregistering mock add-on provider"); + AddonManagerPrivate.unregisterProvider(this); + }, + + /** + * Adds an add-on to the list of add-ons that this provider exposes to the + * AddonManager, dispatching appropriate events in the process. + * + * @param aAddon + * The add-on to add + */ + addAddon: function MP_addAddon(aAddon) { + var oldAddons = this.addons.filter(function(aOldAddon) aOldAddon.id == aAddon.id); + var oldAddon = oldAddons.length > 0 ? oldAddons[0] : null; + + this.addons = this.addons.filter(function(aOldAddon) aOldAddon.id != aAddon.id); + + this.addons.push(aAddon); + aAddon._provider = this; + + if (!this.started) + return; + + let requiresRestart = (aAddon.operationsRequiringRestart & + AddonManager.OP_NEEDS_RESTART_INSTALL) != 0; + AddonManagerPrivate.callInstallListeners("onExternalInstall", null, aAddon, + oldAddon, requiresRestart) + }, + + /** + * Removes an add-on from the list of add-ons that this provider exposes to + * the AddonManager, dispatching the onUninstalled event in the process. + * + * @param aAddon + * The add-on to add + */ + removeAddon: function MP_removeAddon(aAddon) { + var pos = this.addons.indexOf(aAddon); + if (pos == -1) { + ok(false, "Tried to remove an add-on that wasn't registered with the mock provider"); + return; + } + + this.addons.splice(pos, 1); + + if (!this.started) + return; + + AddonManagerPrivate.callAddonListeners("onUninstalled", aAddon); + }, + + /** + * Adds an add-on install to the list of installs that this provider exposes + * to the AddonManager, dispatching appropriate events in the process. + * + * @param aInstall + * The add-on install to add + */ + addInstall: function MP_addInstall(aInstall) { + this.installs.push(aInstall); + aInstall._provider = this; + + if (!this.started) + return; + + aInstall.callListeners("onNewInstall"); + }, + + removeInstall: function MP_removeInstall(aInstall) { + var pos = this.installs.indexOf(aInstall); + if (pos == -1) { + ok(false, "Tried to remove an install that wasn't registered with the mock provider"); + return; + } + + this.installs.splice(pos, 1); + }, + + /** + * Creates a set of mock add-on objects and adds them to the list of add-ons + * managed by this provider. + * + * @param aAddonProperties + * An array of objects containing properties describing the add-ons + * @return Array of the new MockAddons + */ + createAddons: function MP_createAddons(aAddonProperties) { + var newAddons = []; + for (let addonProp of aAddonProperties) { + let addon = new MockAddon(addonProp.id); + for (let prop in addonProp) { + if (prop == "id") + continue; + if (prop == "applyBackgroundUpdates") { + addon._applyBackgroundUpdates = addonProp[prop]; + continue; + } + if (prop == "appDisabled") { + addon._appDisabled = addonProp[prop]; + continue; + } + addon[prop] = addonProp[prop]; + } + if (!addon.optionsType && !!addon.optionsURL) + addon.optionsType = AddonManager.OPTIONS_TYPE_DIALOG; + + // Make sure the active state matches the passed in properties + addon.isActive = addon.shouldBeActive; + + this.addAddon(addon); + newAddons.push(addon); + } + + return newAddons; + }, + + /** + * Creates a set of mock add-on install objects and adds them to the list + * of installs managed by this provider. + * + * @param aInstallProperties + * An array of objects containing properties describing the installs + * @return Array of the new MockInstalls + */ + createInstalls: function MP_createInstalls(aInstallProperties) { + var newInstalls = []; + for (let installProp of aInstallProperties) { + let install = new MockInstall(installProp.name || null, + installProp.type || null, + null); + for (let prop in installProp) { + switch (prop) { + case "name": + case "type": + break; + case "sourceURI": + install[prop] = NetUtil.newURI(installProp[prop]); + break; + default: + install[prop] = installProp[prop]; + } + } + this.addInstall(install); + newInstalls.push(install); + } + + return newInstalls; + }, + + /***** AddonProvider implementation *****/ + + /** + * Called to initialize the provider. + */ + startup: function MP_startup() { + this.started = true; + }, + + /** + * Called when the provider should shutdown. + */ + shutdown: function MP_shutdown() { + if (this.callbackTimers.length) { + info("MockProvider: pending callbacks at shutdown(): calling immediately"); + } + while (this.callbackTimers.length > 0) { + // When we notify the callback timer, it removes itself from our array + let timer = this.callbackTimers[0]; + try { + let setAt = this.timerLocations.get(timer); + info("Notifying timer set at " + (setAt || "unknown location")); + timer.callback.notify(timer); + timer.cancel(); + } catch(e) { + info("Timer notify failed: " + e); + } + } + this.callbackTimers = []; + this.timerLocations = null; + + this.started = false; + }, + + /** + * Called to get an Addon with a particular ID. + * + * @param aId + * The ID of the add-on to retrieve + * @param aCallback + * A callback to pass the Addon to + */ + getAddonByID: function MP_getAddon(aId, aCallback) { + for (let addon of this.addons) { + if (addon.id == aId) { + this._delayCallback(aCallback, addon); + return; + } + } + + aCallback(null); + }, + + /** + * Called to get Addons of a particular type. + * + * @param aTypes + * An array of types to fetch. Can be null to get all types. + * @param callback + * A callback to pass an array of Addons to + */ + getAddonsByTypes: function MP_getAddonsByTypes(aTypes, aCallback) { + var addons = this.addons.filter(function(aAddon) { + if (aTypes && aTypes.length > 0 && aTypes.indexOf(aAddon.type) == -1) + return false; + return true; + }); + this._delayCallback(aCallback, addons); + }, + + /** + * Called to get Addons that have pending operations. + * + * @param aTypes + * An array of types to fetch. Can be null to get all types + * @param aCallback + * A callback to pass an array of Addons to + */ + getAddonsWithOperationsByTypes: function MP_getAddonsWithOperationsByTypes(aTypes, aCallback) { + var addons = this.addons.filter(function(aAddon) { + if (aTypes && aTypes.length > 0 && aTypes.indexOf(aAddon.type) == -1) + return false; + return aAddon.pendingOperations != 0; + }); + this._delayCallback(aCallback, addons); + }, + + /** + * Called to get the current AddonInstalls, optionally restricting by type. + * + * @param aTypes + * An array of types or null to get all types + * @param aCallback + * A callback to pass the array of AddonInstalls to + */ + getInstallsByTypes: function MP_getInstallsByTypes(aTypes, aCallback) { + var installs = this.installs.filter(function(aInstall) { + // Appear to have actually removed cancelled installs from the provider + if (aInstall.state == AddonManager.STATE_CANCELLED) + return false; + + if (aTypes && aTypes.length > 0 && aTypes.indexOf(aInstall.type) == -1) + return false; + + return true; + }); + this._delayCallback(aCallback, installs); + }, + + /** + * Called when a new add-on has been enabled when only one add-on of that type + * can be enabled. + * + * @param aId + * The ID of the newly enabled add-on + * @param aType + * The type of the newly enabled add-on + * @param aPendingRestart + * true if the newly enabled add-on will only become enabled after a + * restart + */ + addonChanged: function MP_addonChanged(aId, aType, aPendingRestart) { + // Not implemented + }, + + /** + * Update the appDisabled property for all add-ons. + */ + updateAddonAppDisabledStates: function MP_updateAddonAppDisabledStates() { + // Not needed + }, + + /** + * Called to get an AddonInstall to download and install an add-on from a URL. + * + * @param aUrl + * The URL to be installed + * @param aHash + * A hash for the install + * @param aName + * A name for the install + * @param aIconURL + * An icon URL for the install + * @param aVersion + * A version for the install + * @param aLoadGroup + * An nsILoadGroup to associate requests with + * @param aCallback + * A callback to pass the AddonInstall to + */ + getInstallForURL: function MP_getInstallForURL(aUrl, aHash, aName, aIconURL, + aVersion, aLoadGroup, aCallback) { + // Not yet implemented + }, + + /** + * Called to get an AddonInstall to install an add-on from a local file. + * + * @param aFile + * The file to be installed + * @param aCallback + * A callback to pass the AddonInstall to + */ + getInstallForFile: function MP_getInstallForFile(aFile, aCallback) { + // Not yet implemented + }, + + /** + * Called to test whether installing add-ons is enabled. + * + * @return true if installing is enabled + */ + isInstallEnabled: function MP_isInstallEnabled() { + return false; + }, + + /** + * Called to test whether this provider supports installing a particular + * mimetype. + * + * @param aMimetype + * The mimetype to check for + * @return true if the mimetype is supported + */ + supportsMimetype: function MP_supportsMimetype(aMimetype) { + return false; + }, + + /** + * Called to test whether installing add-ons from a URI is allowed. + * + * @param aUri + * The URI being installed from + * @return true if installing is allowed + */ + isInstallAllowed: function MP_isInstallAllowed(aUri) { + return false; + }, + + + /***** Internal functions *****/ + + /** + * Delay calling a callback to fake a time-consuming async operation. + * The delay is specified by the apiDelay property, in milliseconds. + * Parameters to send to the callback should be specified as arguments after + * the aCallback argument. + * + * @param aCallback Callback to eventually call + */ + _delayCallback: function MP_delayCallback(aCallback, ...aArgs) { + if (!this.useAsyncCallbacks) { + aCallback(...aArgs); + return; + } + + let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + // Need to keep a reference to the timer, so it doesn't get GC'ed + this.callbackTimers.push(timer); + // Capture a stack trace where the timer was set + // needs the 'new Error' hack until bug 1007656 + this.timerLocations.set(timer, Log.stackTrace(new Error("dummy"))); + timer.initWithCallback(() => { + let idx = this.callbackTimers.indexOf(timer); + if (idx == -1) { + dump("MockProvider._delayCallback lost track of timer set at " + + (this.timerLocations.get(timer) || "unknown location") + "\n"); + } else { + this.callbackTimers.splice(idx, 1); + } + this.timerLocations.delete(timer); + aCallback(...aArgs); + }, this.apiDelay, timer.TYPE_ONE_SHOT); + } +}; + +/***** Mock Addon object for the Mock Provider *****/ + +function MockAddon(aId, aName, aType, aOperationsRequiringRestart) { + // Only set required attributes. + this.id = aId || ""; + this.name = aName || ""; + this.type = aType || "extension"; + this.version = ""; + this.isCompatible = true; + this.isDebuggable = false; + this.providesUpdatesSecurely = true; + this.blocklistState = 0; + this._appDisabled = false; + this._userDisabled = false; + this._applyBackgroundUpdates = AddonManager.AUTOUPDATE_ENABLE; + this.scope = AddonManager.SCOPE_PROFILE; + this.isActive = true; + this.creator = ""; + this.pendingOperations = 0; + this._permissions = AddonManager.PERM_CAN_UNINSTALL | + AddonManager.PERM_CAN_ENABLE | + AddonManager.PERM_CAN_DISABLE | + AddonManager.PERM_CAN_UPGRADE; + this.operationsRequiringRestart = aOperationsRequiringRestart || + (AddonManager.OP_NEEDS_RESTART_INSTALL | + AddonManager.OP_NEEDS_RESTART_UNINSTALL | + AddonManager.OP_NEEDS_RESTART_ENABLE | + AddonManager.OP_NEEDS_RESTART_DISABLE); +} + +MockAddon.prototype = { + get shouldBeActive() { + return !this.appDisabled && !this._userDisabled && + !(this.pendingOperations & AddonManager.PENDING_UNINSTALL); + }, + + get appDisabled() { + return this._appDisabled; + }, + + set appDisabled(val) { + if (val == this._appDisabled) + return val; + + AddonManagerPrivate.callAddonListeners("onPropertyChanged", this, ["appDisabled"]); + + var currentActive = this.shouldBeActive; + this._appDisabled = val; + var newActive = this.shouldBeActive; + this._updateActiveState(currentActive, newActive); + + return val; + }, + + get userDisabled() { + return this._userDisabled; + }, + + set userDisabled(val) { + if (val == this._userDisabled) + return val; + + var currentActive = this.shouldBeActive; + this._userDisabled = val; + var newActive = this.shouldBeActive; + this._updateActiveState(currentActive, newActive); + + return val; + }, + + get permissions() { + let permissions = this._permissions; + if (this.appDisabled || !this._userDisabled) + permissions &= ~AddonManager.PERM_CAN_ENABLE; + if (this.appDisabled || this._userDisabled) + permissions &= ~AddonManager.PERM_CAN_DISABLE; + return permissions; + }, + + set permissions(val) { + return this._permissions = val; + }, + + get applyBackgroundUpdates() { + return this._applyBackgroundUpdates; + }, + + set applyBackgroundUpdates(val) { + if (val != AddonManager.AUTOUPDATE_DEFAULT && + val != AddonManager.AUTOUPDATE_DISABLE && + val != AddonManager.AUTOUPDATE_ENABLE) { + ok(false, "addon.applyBackgroundUpdates set to an invalid value: " + val); + } + this._applyBackgroundUpdates = val; + AddonManagerPrivate.callAddonListeners("onPropertyChanged", this, ["applyBackgroundUpdates"]); + }, + + isCompatibleWith: function(aAppVersion, aPlatformVersion) { + return true; + }, + + findUpdates: function(aListener, aReason, aAppVersion, aPlatformVersion) { + // Tests can implement this if they need to + }, + + uninstall: function(aAlwaysAllowUndo = false) { + if ((this.operationsRequiringRestart & AddonManager.OP_NEED_RESTART_UNINSTALL) + && this.pendingOperations & AddonManager.PENDING_UNINSTALL) + throw Components.Exception("Add-on is already pending uninstall"); + + var needsRestart = aAlwaysAllowUndo || !!(this.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_UNINSTALL); + this.pendingOperations |= AddonManager.PENDING_UNINSTALL; + AddonManagerPrivate.callAddonListeners("onUninstalling", this, needsRestart); + if (!needsRestart) { + this.pendingOperations -= AddonManager.PENDING_UNINSTALL; + this._provider.removeAddon(this); + } else if (!(this.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_DISABLE)) { + this.isActive = false; + } + }, + + cancelUninstall: function() { + if (!(this.pendingOperations & AddonManager.PENDING_UNINSTALL)) + throw Components.Exception("Add-on is not pending uninstall"); + + this.pendingOperations -= AddonManager.PENDING_UNINSTALL; + this.isActive = this.shouldBeActive; + AddonManagerPrivate.callAddonListeners("onOperationCancelled", this); + }, + + _updateActiveState: function(currentActive, newActive) { + if (currentActive == newActive) + return; + + if (newActive == this.isActive) { + this.pendingOperations -= (newActive ? AddonManager.PENDING_DISABLE : AddonManager.PENDING_ENABLE); + AddonManagerPrivate.callAddonListeners("onOperationCancelled", this); + } + else if (newActive) { + var needsRestart = !!(this.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_ENABLE); + this.pendingOperations |= AddonManager.PENDING_ENABLE; + AddonManagerPrivate.callAddonListeners("onEnabling", this, needsRestart); + if (!needsRestart) { + this.isActive = newActive; + this.pendingOperations -= AddonManager.PENDING_ENABLE; + AddonManagerPrivate.callAddonListeners("onEnabled", this); + } + } + else { + var needsRestart = !!(this.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_DISABLE); + this.pendingOperations |= AddonManager.PENDING_DISABLE; + AddonManagerPrivate.callAddonListeners("onDisabling", this, needsRestart); + if (!needsRestart) { + this.isActive = newActive; + this.pendingOperations -= AddonManager.PENDING_DISABLE; + AddonManagerPrivate.callAddonListeners("onDisabled", this); + } + } + } +}; + +/***** Mock AddonInstall object for the Mock Provider *****/ + +function MockInstall(aName, aType, aAddonToInstall) { + this.name = aName || ""; + // Don't expose type until download completed + this._type = aType || "extension"; + this.type = null; + this.version = "1.0"; + this.iconURL = ""; + this.infoURL = ""; + this.state = AddonManager.STATE_AVAILABLE; + this.error = 0; + this.sourceURI = null; + this.file = null; + this.progress = 0; + this.maxProgress = -1; + this.certificate = null; + this.certName = ""; + this.existingAddon = null; + this.addon = null; + this._addonToInstall = aAddonToInstall; + this.listeners = []; + + // Another type of install listener for tests that want to check the results + // of code run from standard install listeners + this.testListeners = []; +} + +MockInstall.prototype = { + install: function() { + switch (this.state) { + case AddonManager.STATE_AVAILABLE: + this.state = AddonManager.STATE_DOWNLOADING; + if (!this.callListeners("onDownloadStarted")) { + this.state = AddonManager.STATE_CANCELLED; + this.callListeners("onDownloadCancelled"); + return; + } + + this.type = this._type; + + // Adding addon to MockProvider to be implemented when needed + if (this._addonToInstall) + this.addon = this._addonToInstall; + else { + this.addon = new MockAddon("", this.name, this.type); + this.addon.version = this.version; + this.addon.pendingOperations = AddonManager.PENDING_INSTALL; + } + this.addon.install = this; + if (this.existingAddon) { + if (!this.addon.id) + this.addon.id = this.existingAddon.id; + this.existingAddon.pendingUpgrade = this.addon; + this.existingAddon.pendingOperations |= AddonManager.PENDING_UPGRADE; + } + + this.state = AddonManager.STATE_DOWNLOADED; + this.callListeners("onDownloadEnded"); + + case AddonManager.STATE_DOWNLOADED: + this.state = AddonManager.STATE_INSTALLING; + if (!this.callListeners("onInstallStarted")) { + this.state = AddonManager.STATE_CANCELLED; + this.callListeners("onInstallCancelled"); + return; + } + + AddonManagerPrivate.callAddonListeners("onInstalling", this.addon); + + this.state = AddonManager.STATE_INSTALLED; + this.callListeners("onInstallEnded"); + break; + case AddonManager.STATE_DOWNLOADING: + case AddonManager.STATE_CHECKING: + case AddonManger.STATE_INSTALLING: + // Installation is already running + return; + default: + ok(false, "Cannot start installing when state = " + this.state); + } + }, + + cancel: function() { + switch (this.state) { + case AddonManager.STATE_AVAILABLE: + this.state = AddonManager.STATE_CANCELLED; + break; + case AddonManager.STATE_INSTALLED: + this.state = AddonManager.STATE_CANCELLED; + this._provider.removeInstall(this); + this.callListeners("onInstallCancelled"); + break; + default: + // Handling cancelling when downloading to be implemented when needed + ok(false, "Cannot cancel when state = " + this.state); + } + }, + + + addListener: function(aListener) { + if (!this.listeners.some(function(i) i == aListener)) + this.listeners.push(aListener); + }, + + removeListener: function(aListener) { + this.listeners = this.listeners.filter(function(i) i != aListener); + }, + + addTestListener: function(aListener) { + if (!this.testListeners.some(function(i) i == aListener)) + this.testListeners.push(aListener); + }, + + removeTestListener: function(aListener) { + this.testListeners = this.testListeners.filter(function(i) i != aListener); + }, + + callListeners: function(aMethod) { + var result = AddonManagerPrivate.callInstallListeners(aMethod, this.listeners, + this, this.addon); + + // Call test listeners after standard listeners to remove race condition + // between standard and test listeners + for (let listener of this.testListeners) { + try { + if (aMethod in listener) + if (listener[aMethod].call(listener, this, this.addon) === false) + result = false; + } + catch (e) { + ok(false, "Test listener threw exception: " + e); + } + } + + return result; + } +}; + +function waitForCondition(condition, nextTest, errorMsg) { + let tries = 0; + let interval = setInterval(function() { + if (tries >= 30) { + ok(false, errorMsg); + moveOn(); + } + var conditionPassed; + try { + conditionPassed = condition(); + } catch (e) { + ok(false, e + "\n" + e.stack); + conditionPassed = false; + } + if (conditionPassed) { + moveOn(); + } + tries++; + }, 100); + let moveOn = function() { clearInterval(interval); nextTest(); }; +} + +function getTestPluginTag() { + let ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost); + let tags = ph.getPluginTags(); + + // Find the test plugin + for (let i = 0; i < tags.length; i++) { + if (tags[i].name == "Test Plug-in") + return tags[i]; + } + ok(false, "Unable to find plugin"); + return null; +} diff --git a/toolkit/mozapps/extensions/test/browser/more_options.xul b/toolkit/mozapps/extensions/test/browser/more_options.xul new file mode 100644 index 000000000..4c8474a79 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/more_options.xul @@ -0,0 +1,32 @@ +<?xml version="1.0" ?> +<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <setting pref="extensions.inlinesettings3.radioBool" type="radio" title="Radio"> + <radiogroup> + <radio label="Delta" value="true" /> + <radio label="Echo" value="false" /> + </radiogroup> + </setting> + <setting pref="extensions.inlinesettings3.radioInt" type="radio" title="Radio"> + <radiogroup> + <radio label="Foxtrot" value="4" /> + <radio label="Golf" value="5" /> + <radio label="Hotel" value="6" /> + </radiogroup> + </setting> + <setting pref="extensions.inlinesettings3.radioString" type="radio" title="Radio"> + <radiogroup> + <radio label="India" value="india" /> + <radio label="Juliet" value="juliet" /> + <radio label="Kilo" value="kilo" /> + </radiogroup> + </setting> + <setting pref="extensions.inlinesettings3.menulist" type="menulist" title="Menulist"> + <menulist sizetopopup="always"> + <menupopup> + <menuitem label="Lima" value="7" /> + <menuitem label="Mike" value="8" /> + <menuitem label="November" value="9" /> + </menupopup> + </menulist> + </setting> +</vbox> diff --git a/toolkit/mozapps/extensions/test/browser/moz.build b/toolkit/mozapps/extensions/test/browser/moz.build new file mode 100644 index 000000000..9acb42133 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/moz.build @@ -0,0 +1,10 @@ +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +BROWSER_CHROME_MANIFESTS += [ + 'browser-window.ini', + 'browser.ini', +] diff --git a/toolkit/mozapps/extensions/test/browser/options.xul b/toolkit/mozapps/extensions/test/browser/options.xul new file mode 100644 index 000000000..1b6827915 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/options.xul @@ -0,0 +1,12 @@ +<?xml version="1.0" ?> +<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <setting /> + <setting pref="extensions.inlinesettings2.bool1" type="bool" title="Bool 1" desc="Description Attribute"/> + <setting pref="extensions.inlinesettings2.bool2" type="bool" title="Bool 2">Description Text Node</setting> + <setting type="control" title="Button"> + This is a test, <button label="button" />all this text should be visible + </setting> + <setting type="unsupported"> + This setting should never appear + </setting> +</vbox> diff --git a/toolkit/mozapps/extensions/test/browser/plugin_test.html b/toolkit/mozapps/extensions/test/browser/plugin_test.html new file mode 100644 index 000000000..0709eda06 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/plugin_test.html @@ -0,0 +1,7 @@ +<!DOCTYPE html> +<html> +<head><meta charset="utf-8"></head> +<body> +<object id="test" width=200 height=200 type="application/x-test"></object> +</body> +</html> diff --git a/toolkit/mozapps/extensions/test/browser/redirect.sjs b/toolkit/mozapps/extensions/test/browser/redirect.sjs new file mode 100644 index 000000000..8f9d1c08a --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/redirect.sjs @@ -0,0 +1,5 @@ +function handleRequest(request, response) { + dump("*** Received redirect for " + request.queryString + "\n"); + response.setStatusLine(request.httpVersion, 301, "Moved Permanently"); + response.setHeader("Location", request.queryString, false); +} diff --git a/toolkit/mozapps/extensions/test/browser/releaseNotes.xhtml b/toolkit/mozapps/extensions/test/browser/releaseNotes.xhtml new file mode 100644 index 000000000..63ae07901 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/releaseNotes.xhtml @@ -0,0 +1,15 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html lang="en-US" dir="ltr" xmlns="http://www.w3.org/1999/xhtml"> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> + <title></title> +</head> + +<body> + <h1>OMG, an update!!!!</h1> + <ul> + <li>Made everything more awesome</li> + <li>Added hot sauce</li> + </ul> +</body> +</html> diff --git a/toolkit/mozapps/extensions/test/mochitest/file_bug687194.xpi b/toolkit/mozapps/extensions/test/mochitest/file_bug687194.xpi Binary files differnew file mode 100644 index 000000000..dfc035053 --- /dev/null +++ b/toolkit/mozapps/extensions/test/mochitest/file_bug687194.xpi diff --git a/toolkit/mozapps/extensions/test/mochitest/file_empty.html b/toolkit/mozapps/extensions/test/mochitest/file_empty.html new file mode 100644 index 000000000..b6c8a53b4 --- /dev/null +++ b/toolkit/mozapps/extensions/test/mochitest/file_empty.html @@ -0,0 +1,2 @@ +<!DOCTYPE html> +<html><head></head><body><span id="text">Nothing to see here</span></body></html> diff --git a/toolkit/mozapps/extensions/test/mochitest/mochitest.ini b/toolkit/mozapps/extensions/test/mochitest/mochitest.ini new file mode 100644 index 000000000..375f619b4 --- /dev/null +++ b/toolkit/mozapps/extensions/test/mochitest/mochitest.ini @@ -0,0 +1,10 @@ +[DEFAULT] +skip-if = buildapp == 'b2g' +support-files = + file_empty.html + file_bug687194.xpi + +[test_bug609794.html] +[test_bug687194.html] +skip-if = e10s || os == "android" # this test creates its own child process, no need to run it in e10s +[test_bug887098.html] diff --git a/toolkit/mozapps/extensions/test/mochitest/test_bug609794.html b/toolkit/mozapps/extensions/test/mochitest/test_bug609794.html new file mode 100644 index 000000000..d13e6ef2f --- /dev/null +++ b/toolkit/mozapps/extensions/test/mochitest/test_bug609794.html @@ -0,0 +1,27 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=609794 +--> +<head> + <title>Test for Bug 609794</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=609794">Mozilla Bug 609794</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 609794 **/ +var obj = Object.create(window); +is(Object.prototype.toString.call(obj.InstallTrigger), "[object InstallTriggerImpl]", "can get InstallTrigger through the prototype"); + +</script> +</pre> +</body> +</html> diff --git a/toolkit/mozapps/extensions/test/mochitest/test_bug687194.html b/toolkit/mozapps/extensions/test/mochitest/test_bug687194.html new file mode 100644 index 000000000..8f99ea73a --- /dev/null +++ b/toolkit/mozapps/extensions/test/mochitest/test_bug687194.html @@ -0,0 +1,133 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for registering/unregistering chrome OOP</title> + <script type="application/javascript" + src="/tests/SimpleTest/SimpleTest.js"> + </script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> + + <script type="application/javascript;version=1.8"> + "use strict"; + + SimpleTest.waitForExplicitFinish(); + + const childFrameURL = + "data:text/html,<!DOCTYPE HTML><html><body></body></html>"; + + function childFrameScript() { + "use strict"; + + var ios = + Components.classes["@mozilla.org/network/io-service;1"] + .getService(Components.interfaces.nsIIOService); + let cr = + Components.classes["@mozilla.org/chrome/chrome-registry;1"] + .getService(Ci.nsIXULChromeRegistry); + addMessageListener("test687194:resolveChromeURI", function(message) { + let result; + let threw = false; + try { + let uri = ios.newURI(message.data.URI, null, null); + result = cr.convertChromeURL(uri).spec; + } catch (e) { + threw = true; + result = "EXCEPTION: " + e; + } + + message.target.sendAsyncMessage("test687194:resolveChromeURI:Answer", + { threw: threw, result: result }); + }); + } + + let test; + function* testStructure(mm) { + let lastResult; + + mm.addMessageListener("test687194:resolveChromeURI:Answer", function(msg) { + test.next(msg.data); + }); + + mm.sendAsyncMessage("test687194:resolveChromeURI", + { URI: "chrome://bug687194/content/e10sbug.js" }); + lastResult = yield; + is(lastResult.threw, true, "URI shouldn't resolve to begin with"); + + let { AddonManager } = SpecialPowers.Cu.import("resource://gre/modules/AddonManager.jsm", {}); + const INSTALL_URI = + "http://mochi.test:8888/tests/toolkit/mozapps/extensions/test/mochitest/file_bug687194.xpi" + AddonManager.getInstallForURL(INSTALL_URI, (install) => { + install = SpecialPowers.wrap(install); + install.addListener(SpecialPowers.wrapCallbackObject({ + onInstallEnded: function(install, addon) { + SimpleTest.executeSoon(() => test.next(addon)); + } + })); + install.install(); + }, "application/x-xpinstall"); + + let addon = SpecialPowers.wrap(yield); + + mm.sendAsyncMessage("test687194:resolveChromeURI", + { URI: "chrome://bug687194/content/e10sbug.js" }); + lastResult = yield; + is(lastResult.threw, false, "able to resolve after the installation"); + + let listener = SpecialPowers.wrapCallbackObject({ + onUninstalled: function(removedAddon) { + if (removedAddon.id === addon.id) { + AddonManager.removeAddonListener(listener); + SimpleTest.executeSoon(() => test.next()); + } + } + }); + AddonManager.addAddonListener(listener); + addon.uninstall(); + + yield; + + mm.sendAsyncMessage("test687194:resolveChromeURI", + { URI: "chrome://bug687194/content/e10sbug.js" }); + lastResult = yield; + is(lastResult.threw, true, "should have unregistered the URI"); + SimpleTest.finish(); + } + + function runTests() { + info("Browser prefs set."); + + let iframe = document.createElement("iframe"); + SpecialPowers.wrap(iframe).mozbrowser = true; + iframe.id = "iframe"; + iframe.src = childFrameURL; + + iframe.addEventListener("mozbrowserloadend", function() { + info("Got iframe load event."); + let mm = SpecialPowers.getBrowserFrameMessageManager(iframe); + mm.loadFrameScript("data:,(" + childFrameScript.toString() + ")();", + false); + + test = testStructure(mm); + test.next(); + }); + + document.body.appendChild(iframe); + } + + addEventListener("load", function() { + info("Got load event."); + + SpecialPowers.addPermission("browser", true, document); + SpecialPowers.pushPrefEnv({ + "set": [ + ["dom.ipc.browser_frames.oop_by_default", true], + ["dom.mozBrowserFramesEnabled", true], + ["browser.pagethumbnails.capturing_disabled", true] + ] + }, runTests); + }); + </script> +</body> +</html> diff --git a/toolkit/mozapps/extensions/test/mochitest/test_bug887098.html b/toolkit/mozapps/extensions/test/mochitest/test_bug887098.html new file mode 100644 index 000000000..2b2033a37 --- /dev/null +++ b/toolkit/mozapps/extensions/test/mochitest/test_bug887098.html @@ -0,0 +1,51 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=887098 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 887098</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 887098 **/ + SimpleTest.waitForExplicitFinish(); + + function loaded() { + var iwin = $('ifr').contentWindow; + var href = SpecialPowers.wrap(iwin).location.href; + if (/file_empty/.test(href)) { + window.evalRef = iwin.eval; + window.installTriggerRef = iwin.InstallTrigger; // Force lazy instantiation. + // about: is privileged, so we need to be privileged to load it. + SpecialPowers.wrap(iwin).location.href = 'about:'; + } else { + is(href, 'about:', "Successfully navigated to about:"); + try { + evalRef('InstallTrigger.install({URL: "chrome://global/skin/global.css"});'); + ok(false, "Should have thrown when trying to install restricted URI from InstallTrigger"); + } catch (e) { + //XXXgijs this test broke because of the switch to webidl. I'm told + // it has to do with compartments and the fact that we eval in "about:". + // Tracking in bug 1007671 + todo(/permission/.test(e), "We should throw a security exception. Got: " + e); + } + SimpleTest.finish(); + } + } + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=887098">Mozilla Bug 887098</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<iframe onload="loaded();" id="ifr" src="file_empty.html"></iframe> +<pre id="test"> +</pre> +</body> +</html> diff --git a/toolkit/mozapps/extensions/test/moz.build b/toolkit/mozapps/extensions/test/moz.build new file mode 100644 index 000000000..d74976bda --- /dev/null +++ b/toolkit/mozapps/extensions/test/moz.build @@ -0,0 +1,20 @@ +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +if CONFIG['MOZ_BUILD_APP'] != 'mobile': + DIRS += ['browser'] + + BROWSER_CHROME_MANIFESTS += ['xpinstall/browser.ini'] + MOCHITEST_MANIFESTS += ['mochitest/mochitest.ini'] + +TESTING_JS_MODULES += [ + 'AddonManagerTesting.jsm', +] + +XPCSHELL_TESTS_MANIFESTS += [ + 'xpcshell/xpcshell-unpack.ini', + 'xpcshell/xpcshell.ini', +] diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/blocklistchange/addon_change.xml b/toolkit/mozapps/extensions/test/xpcshell/data/blocklistchange/addon_change.xml new file mode 100644 index 000000000..a229a653a --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/blocklistchange/addon_change.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <emItems> + <emItem id="softblock1@tests.mozilla.org"> + <versionRange severity="1" minVersion="2" maxVersion="3"/> + </emItem> + <emItem id="softblock2@tests.mozilla.org"> + <versionRange severity="1" minVersion="2" maxVersion="3"/> + </emItem> + <emItem id="softblock3@tests.mozilla.org"> + <versionRange severity="1" minVersion="2" maxVersion="3"/> + </emItem> + <emItem id="softblock4@tests.mozilla.org"> + <versionRange severity="1" minVersion="2" maxVersion="3"/> + </emItem> + <emItem id="softblock5@tests.mozilla.org"> + <versionRange severity="1" minVersion="2" maxVersion="3"/> + </emItem> + <emItem id="hardblock@tests.mozilla.org"> + <versionRange minVersion="2" maxVersion="3"/> + </emItem> + <!-- Two RegExp matches, so test flags work - first shouldn't match. --> + <emItem id="/^RegExp/"> + <versionRange severity="1" minVersion="2" maxVersion="3"/> + </emItem> + <emItem id="/^RegExp/i"> + <versionRange severity="2" minVersion="2" maxVersion="3"/> + </emItem> + </emItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/blocklistchange/addon_update1.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/blocklistchange/addon_update1.rdf new file mode 100644 index 000000000..588290968 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/blocklistchange/addon_update1.rdf @@ -0,0 +1,144 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <RDF:Description about="urn:mozilla:extension:softblock1@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>2</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/blocklist_soft1_2.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:softblock2@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>2</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/blocklist_soft2_2.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:softblock3@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>2</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/blocklist_soft3_2.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:softblock4@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>2</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/blocklist_soft4_2.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:theme:softblock5@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>2</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/blocklist_soft5_2.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:hardblock@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>2</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/blocklist_hard1_2.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:regexpblock@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>2</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/blocklist_regexp1_2.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> +</RDF:RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/blocklistchange/addon_update2.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/blocklistchange/addon_update2.rdf new file mode 100644 index 000000000..5c3747f5f --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/blocklistchange/addon_update2.rdf @@ -0,0 +1,144 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <RDF:Description about="urn:mozilla:extension:softblock1@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>3</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/blocklist_soft1_3.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:softblock2@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>3</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/blocklist_soft2_3.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:softblock3@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>3</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/blocklist_soft3_3.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:softblock4@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>3</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/blocklist_soft4_3.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:theme:softblock5@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>3</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/blocklist_soft5_3.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:hardblock@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>3</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/blocklist_hard1_3.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:regexpblock@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>3</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/blocklist_regexp1_3.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> +</RDF:RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/blocklistchange/addon_update3.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/blocklistchange/addon_update3.rdf new file mode 100644 index 000000000..d60708414 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/blocklistchange/addon_update3.rdf @@ -0,0 +1,144 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <RDF:Description about="urn:mozilla:extension:softblock1@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>4</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/blocklist_soft1_1.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:softblock2@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>4</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/blocklist_soft2_1.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:softblock3@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>4</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/blocklist_soft3_1.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:softblock4@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>4</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/blocklist_soft4_1.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:theme:softblock5@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>4</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/blocklist_soft5_1.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:hardblock@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>4</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/blocklist_hard1_1.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:regexpblock@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>4</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>*</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/blocklist_regexp1_1.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> +</RDF:RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/blocklistchange/app_update.xml b/toolkit/mozapps/extensions/test/xpcshell/data/blocklistchange/app_update.xml new file mode 100644 index 000000000..85a66fe55 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/blocklistchange/app_update.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <emItems> + <emItem id="softblock1@tests.mozilla.org"> + <versionRange severity="1"> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange minVersion="2" maxVersion="2.*"/> + </targetApplication> + </versionRange> + </emItem> + <emItem id="softblock2@tests.mozilla.org"> + <versionRange severity="1"> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange minVersion="2" maxVersion="2.*"/> + </targetApplication> + </versionRange> + </emItem> + <emItem id="softblock3@tests.mozilla.org"> + <versionRange severity="1"> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange minVersion="2" maxVersion="2.*"/> + </targetApplication> + </versionRange> + </emItem> + <emItem id="softblock4@tests.mozilla.org"> + <versionRange severity="1"> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange minVersion="2" maxVersion="2.*"/> + </targetApplication> + </versionRange> + </emItem> + <emItem id="softblock5@tests.mozilla.org"> + <versionRange severity="1"> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange minVersion="2" maxVersion="2.*"/> + </targetApplication> + </versionRange> + </emItem> + <emItem id="hardblock@tests.mozilla.org"> + <versionRange> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange minVersion="2" maxVersion="2.*"/> + </targetApplication> + </versionRange> + </emItem> + <emItem id="/^RegExp/"> + <versionRange severity="1"> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange minVersion="2" maxVersion="2.*"/> + </targetApplication> + </versionRange> + </emItem> + <emItem id="/^RegExp/i"> + <versionRange> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange minVersion="2" maxVersion="2.*"/> + </targetApplication> + </versionRange> + </emItem> + </emItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/blocklistchange/blocklist_update1.xml b/toolkit/mozapps/extensions/test/xpcshell/data/blocklistchange/blocklist_update1.xml new file mode 100644 index 000000000..87011cd39 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/blocklistchange/blocklist_update1.xml @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"/> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/blocklistchange/blocklist_update2.xml b/toolkit/mozapps/extensions/test/xpcshell/data/blocklistchange/blocklist_update2.xml new file mode 100644 index 000000000..867a34255 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/blocklistchange/blocklist_update2.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <emItems> + <emItem id="softblock1@tests.mozilla.org"> + <versionRange severity="1"/> + </emItem> + <emItem id="softblock2@tests.mozilla.org"> + <versionRange severity="1"/> + </emItem> + <emItem id="softblock3@tests.mozilla.org"> + <versionRange severity="1"/> + </emItem> + <emItem id="softblock4@tests.mozilla.org"> + <versionRange severity="1"/> + </emItem> + <emItem id="softblock5@tests.mozilla.org"> + <versionRange severity="1"/> + </emItem> + <emItem id="hardblock@tests.mozilla.org"/> + <emItem id="/^RegExp/"> + <versionRange severity="1"/> + </emItem> + <emItem id="/^RegExp/i"/> + </emItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/blocklistchange/manual_update.xml b/toolkit/mozapps/extensions/test/xpcshell/data/blocklistchange/manual_update.xml new file mode 100644 index 000000000..df9276525 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/blocklistchange/manual_update.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <emItems> + <emItem id="softblock1@tests.mozilla.org"> + <versionRange severity="1" minVersion="1" maxVersion="2"/> + </emItem> + <emItem id="softblock2@tests.mozilla.org"> + <versionRange severity="1" minVersion="1" maxVersion="2"/> + </emItem> + <emItem id="softblock3@tests.mozilla.org"> + <versionRange severity="1" minVersion="1" maxVersion="2"/> + </emItem> + <emItem id="softblock4@tests.mozilla.org"> + <versionRange severity="1" minVersion="1" maxVersion="2"/> + </emItem> + <emItem id="softblock5@tests.mozilla.org"> + <versionRange severity="1" minVersion="1" maxVersion="2"/> + </emItem> + <emItem id="hardblock@tests.mozilla.org"> + <versionRange minVersion="1" maxVersion="2"/> + </emItem> + <emItem id="/^RegExp/i"> + <versionRange minVersion="1" maxVersion="2"/> + </emItem> + </emItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/bug455906_block.xml b/toolkit/mozapps/extensions/test/xpcshell/data/bug455906_block.xml new file mode 100644 index 000000000..1f673ef2f --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/bug455906_block.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <emItems> + <emItem id="test_bug455906_1@tests.mozilla.org" blockID="test_bug455906_1@tests.mozilla.org"/> + <emItem id="test_bug455906_2@tests.mozilla.org" blockID="test_bug455906_2@tests.mozilla.org"/> + <emItem id="test_bug455906_3@tests.mozilla.org" blockID="test_bug455906_3@tests.mozilla.org"/> + <emItem id="test_bug455906_4@tests.mozilla.org" blockID="test_bug455906_4@tests.mozilla.org"/> + <emItem id="test_bug455906_5@tests.mozilla.org" blockID="test_bug455906_5@tests.mozilla.org"/> + <emItem id="test_bug455906_6@tests.mozilla.org" blockID="test_bug455906_6@tests.mozilla.org"/> + <emItem id="test_bug455906_7@tests.mozilla.org" blockID="test_bug455906_7@tests.mozilla.org"/> + </emItems> + <pluginItems> + <pluginItem blockID="test_bug455906_plugin"> + <match name="name" exp="^test_bug455906"/> + </pluginItem> + </pluginItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/bug455906_empty.xml b/toolkit/mozapps/extensions/test/xpcshell/data/bug455906_empty.xml new file mode 100644 index 000000000..88d22f281 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/bug455906_empty.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <emItems> + <emItem id="dummy_bug455906_2@tests.mozilla.org"/> + </emItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/bug455906_start.xml b/toolkit/mozapps/extensions/test/xpcshell/data/bug455906_start.xml new file mode 100644 index 000000000..daba6f4c1 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/bug455906_start.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <emItems> + <emItem id="test_bug455906_4@tests.mozilla.org"> + <versionRange severity="-1"/> + </emItem> + <emItem id="test_bug455906_5@tests.mozilla.org"> + <versionRange severity="1"/> + </emItem> + <emItem id="test_bug455906_6@tests.mozilla.org"> + <versionRange severity="2"/> + </emItem> + <emItem id="dummy_bug455906_1@tests.mozilla.org"/> + </emItems> + <pluginItems> + <pluginItem> + <match name="name" exp="^test_bug455906_4$"/> + <versionRange severity="0"/> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_bug455906_5$"/> + <versionRange severity="1"/> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_bug455906_6$"/> + <versionRange severity="2"/> + </pluginItem> + </pluginItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/bug455906_warn.xml b/toolkit/mozapps/extensions/test/xpcshell/data/bug455906_warn.xml new file mode 100644 index 000000000..232fd0d07 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/bug455906_warn.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <emItems> + <emItem id="test_bug455906_1@tests.mozilla.org"> + <versionRange severity="-1"/> + </emItem> + <emItem id="test_bug455906_2@tests.mozilla.org"> + <versionRange severity="-1"/> + </emItem> + <emItem id="test_bug455906_3@tests.mozilla.org"> + <versionRange severity="-1"/> + </emItem> + <emItem id="test_bug455906_4@tests.mozilla.org"> + <versionRange severity="-1"/> + </emItem> + <emItem id="test_bug455906_5@tests.mozilla.org"> + <versionRange severity="-1"/> + </emItem> + <emItem id="test_bug455906_6@tests.mozilla.org"> + <versionRange severity="-1"/> + </emItem> + <emItem id="test_bug455906_7@tests.mozilla.org"> + <versionRange severity="-1"/> + </emItem> + </emItems> + <pluginItems> + <pluginItem> + <match name="name" exp="^test_bug455906"/> + <versionRange severity="-1"/> + </pluginItem> + </pluginItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/corrupt.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/corrupt.xpi new file mode 100644 index 000000000..35d7bd5e5 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/corrupt.xpi @@ -0,0 +1 @@ +This is a corrupt zip file diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/corruptfile.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/corruptfile.xpi Binary files differnew file mode 100644 index 000000000..0c30989aa --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/corruptfile.xpi diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/empty.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/empty.xpi Binary files differnew file mode 100644 index 000000000..74ed2b817 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/empty.xpi diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/pluginInfoURL_block.xml b/toolkit/mozapps/extensions/test/xpcshell/data/pluginInfoURL_block.xml new file mode 100644 index 000000000..6c6ce90ef --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/pluginInfoURL_block.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <emItems> + </emItems> + <pluginItems> + <pluginItem blockID="test_plugin_wInfoURL"> + <match name="name" exp="^test_with_infoURL"/> + <match name="version" exp="^5"/> + <infoURL>http://test.url.com/</infoURL> + </pluginItem> + <pluginItem blockID="test_plugin_wAltInfoURL"> + <match name="name" exp="^test_with_altInfoURL"/> + <match name="version" exp="^5"/> + <infoURL>http://alt.test.url.com/</infoURL> + </pluginItem> + <pluginItem blockID="test_plugin_noInfoURL"> + <match name="name" exp="^test_no_infoURL"/> + </pluginItem> + </pluginItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository.xml new file mode 100644 index 000000000..0bebca2c1 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository.xml @@ -0,0 +1,820 @@ +<?xml version="1.0" encoding="utf-8" ?> +<searchresults total_results="1111"> + <!-- Passes all requirements --> + <addon> + <name>PASS</name> + <type id="1">Extension</type> + <guid>test1@tests.mozilla.org</guid> + <version>1.1</version> + <authors> + <author> + <name>Test Creator 1</name> + <link>http://localhost:%PORT%/creator1.html</link> + </author> + </authors> + <status id="8">Preliminarily Reviewed</status> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <!-- Test that a negative rating is ignored --> + <rating>-2</rating> + <!-- Test that a <reviews> with a blank review URL is ignored --> + <reviews num=" 1111 "> </reviews> + <!-- Test that a negative total_downloads is ignored --> + <total_downloads>-2</total_downloads> + <install>http://localhost:%PORT%/test1.xpi</install> + </addon> + + <!-- Passes requirements. Tests optional attributes. Also tests that + integer properties that are NaN in the XML are ignored --> + <addon> + <name>PASS</name> + <!-- Test that extensions pass --> + <type id="1">Extension</type> + <guid>test2@tests.mozilla.org</guid> + <version>1.2</version> + <authors> + <!-- Test that the first author becomes the creator, + and the second one is a developer --> + <author> + <name>Test Creator 2</name> + <link>http://localhost:%PORT%/creator2.html</link> + </author> + <author> + <name>Test Developer 2</name> + <link>http://localhost:%PORT%/developer2.html</link> + </author> + </authors> + <summary><h1>Test Summary 2</h1><p>paragraph</p></summary> + <description>Test Description 2<br>newline</description> + <developer_comments>Test Developer + Comments 2</developer_comments> + <eula>Test EULA 2</eula> + <icon size="64">http://localhost:%PORT%/icon2-64.png</icon> + <icon size="48">http://localhost:%PORT%/icon2-48.png</icon> + <icon size="32">http://localhost:%PORT%/icon2-32.png</icon> + <status id="4">Public</status> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <!-- Test that multiple preview images are correctly parsed --> + <previews> + <preview primary="0"> + <full type="image/png">http://localhost:%PORT%/full1-2.png</full> + <thumbnail type="image/png">http://localhost:%PORT%/thumbnail1-2.png</thumbnail> + </preview> + <preview primary="0"> + <full type="image/png">http://localhost:%PORT%/full2-2.png</full> + <thumbnail type="image/png">http://localhost:%PORT%/thumbnail2-2.png</thumbnail> + <caption>Caption 2</caption> + </preview> + </previews> + <rating>NaN</rating> + <!-- Test that learnmore is used as the add-on's homepageURL + if there is no homepage defined --> + <learnmore>http://localhost:%PORT%/learnmore2.html</learnmore> + <homepage/> + <support>http://localhost:%PORT%/support2.html</support> + <contribution_data> + <link>http://localhost:%PORT%/contribution2.html</link> + <meet_developers>http://localhost:%PORT%/meetDevelopers2.html</meet_developers> + </contribution_data> + <reviews num="NaN">http://localhost:%PORT%/review2.html</reviews> + <total_downloads>NaN</total_downloads> + <weekly_downloads>NaN</weekly_downloads> + <daily_users>NaN</daily_users> + <last_updated epoch="NaN">Not an acual date</last_updated> + <install size="NaN" os="ALL">http://localhost:%PORT%/test2.xpi</install> + </addon> + + <!-- Passes requirements. Tests optional attributes with extra whitespace. --> + <addon> + <name> PASS </name> + <!-- Test that themes pass --> + <type id=" 2 ">Theme</type> + <guid> test3@tests.mozilla.org </guid> + <version> 1.3 </version> + <authors> + <!-- Test that authors with blank names are ignored --> + <author> + <name> </name> + <link> http://localhost:%PORT%/ignore3.html </link> + </author> + <!-- Test that authors with blank links are ignored --> + <author> + <name> Test Creator Ignore </name> + <link> </link> + </author> + <author> + <name> Test Creator 3 </name> + <link> http://localhost:%PORT%/creator3.html </link> + </author> + <author> + <name> First Test Developer 3 </name> + <link> http://localhost:%PORT%/developer1-3.html </link> + </author> + <author> + <name> </name> + <link> </link> + </author> + <author> + <name> Second Test Developer 3 </name> + <link> http://localhost:%PORT%/developer2-3.html </link> + </author> + </authors> + <summary> Test Summary 3 </summary> + <description> Test Description 3<br><ul><li>List item 1<li>List item 2</ul> </description> + <developer_comments> Test Developer Comments 3 </developer_comments> + <eula> Test EULA 3 </eula> + <icon size="32"> http://localhost:%PORT%/icon3.png </icon> + <status id=" 8 ">Preliminarily Reviewed</status> + <!-- Test that an incompatible + compatible application list passes --> + <compatible_applications> + <application> + <appID> unknown@tests.mozilla.org </appID> + <min_version> 1 </min_version> + <max_version> 1 </max_version> + </application> + <application> + <appID> xpcshell@tests.mozilla.org </appID> + <min_version> 1 </min_version> + <max_version> 1 </max_version> + </application> + </compatible_applications> + <!-- Test that primary images appear first in the add-on's screenshots array --> + <previews> + <preview primary=" 0 "> + <full type=" image/png "> http://localhost:%PORT%/full2-3.png </full> + <caption> Caption 2 - 3 </caption> + </preview> + <!-- Test that a preview without a <full> element is ignored --> + <preview primary=" 0 "> + <caption> Caption ignore - 3 </caption> + </preview> + <!-- Test that a preview with an empty <full> element is ignored --> + <preview primary=" 0 "> + <full type=" image/png "> </full> + <caption> Caption ignore - 3 </caption> + <preview primary=" 1 "> + <full type=" image/png "> http://localhost:%PORT%/full1-3.png </full> + <thumbnail type=" image/png "> http://localhost:%PORT%/thumbnail1-3.png </thumbnail> + <caption> Caption 1 - 3 </caption> + </preview> + <preview primary=" 0 "> + <full type=" image/png "> http://localhost:%PORT%/full3-3.png </full> + <thumbnail type=" image/png "> http://localhost:%PORT%/thumbnail3-3.png </thumbnail> + <caption> Caption 3 - 3 </caption> + </preview> + </preview> + </previews> + <!-- Test that a rating between 1 and 5 is correctly parsed --> + <rating> 2 </rating> + <!-- Test that hompage is used as the add-on's homepageURL + even if learnmore is defined --> + <learnmore> http://localhost:%PORT%/learnmore3.html </learnmore> + <homepage> http://localhost:%PORT%/homepage3.html </homepage> + <support> http://localhost:%PORT%/support3.html </support> + <contribution_data> + <link> http://localhost:%PORT%/contribution3.html </link> + <suggested_amount currency="USD"> $11.11 </suggested_amount> + <meet_developers> http://localhost:%PORT%/meetDevelopers3.html </meet_developers> + </contribution_data> + <reviews num=" 1111 "> http://localhost:%PORT%/review3.html </reviews> + <total_downloads> 2222 </total_downloads> + <weekly_downloads> 3333 </weekly_downloads> + <daily_users> 4444 </daily_users> + <last_updated epoch=" 1265033045 "> 2010-02-01T14:04:05Z </last_updated> + <!-- Test that an incompatible install is ignored --> + <install size=" 9999 " os=" UNKNOWN "> http://localhost:%PORT%/fail3.xpi </install> + <!-- Test that OS matching is case-insensitive --> + <install size=" 5555 " os=" xpCShell " hash=" sha1:c26f0b0d62e5dcddcda95074d3f3fedb9bbc26e3 "> http://localhost:%PORT%/test3.xpi </install> + </addon> + + <!-- Fails because name is undefined --> + <addon> + <type id="1">Extension</type> + <guid>test4@tests.mozilla.org</guid> + <version>1.4</version> + <authors><author><name>Test Creator 4</name></author></authors> + <status id="4">Public</status> + <summary>Add-on with undefined name should be ignored.</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test4.xpi</install> + </addon> + + <!-- Fails because name is empty--> + <addon> + <name> </name> + <type id="1">Extension</type> + <guid>test5@tests.mozilla.org</guid> + <version>1.5</version> + <authors><author><name>Test Creator 5</name></author></authors> + <status id="4">Public</status> + <summary>Add-on with empty name should be ignored.</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test5.xpi</install> + </addon> + + <!-- Fails because type is undefined --> + <addon> + <name>FAIL</name> + <guid>test6@tests.mozilla.org</guid> + <version>1.6</version> + <authors><author><name>Test Creator 6</name></author></authors> + <status id="4">Public</status> + <summary>Add-on with undefined type should be ignored</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test6.xpi</install> + </addon> + + <!-- Fails because type is empty --> + <addon> + <name>FAIL</name> + <type id="">Empty id attribute</type> + <guid>test7@tests.mozilla.org</guid> + <version>1.7</version> + <authors><author><name>Test Creator 7</name></author></authors> + <status id="4">Public</status> + <summary>Add-on with empty type should be ignored</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test7.xpi</install> + </addon> + + <!-- Fails because type is unknown --> + <addon> + <name>FAIL</name> + <type id="9999">Unknown</type> + <guid>test8@tests.mozilla.org</guid> + <version>1.8</version> + <authors><author><name>Test Creator 8</name></author></authors> + <status id="4">Public</status> + <summary>Add-on with unknown type should be ignored</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test8.xpi</install> + </addon> + + <!-- Fails because guid is undefined --> + <addon> + <name>FAIL</name> + <type id="1">Extension</type> + <version>1.9</version> + <authors><author><name>Test Creator 9</name></author></authors> + <status id="4">Public</status> + <summary>Add-on with undefined guid should be ignored.</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test9.xpi</install> + </addon> + + <!-- Fails because guid is empty --> + <addon> + <name>FAIL</name> + <type id="1">Extension</type> + <guid> </guid> + <version>1.10</version> + <authors><author><name>Test Creator 10</name></author></authors> + <status id="4">Public</status> + <summary>Add-on with empty guid should be ignored.</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test10.xpi</install> + </addon> + + <!-- Fails because guid matches previously successful result --> + <addon> + <name>FAIL</name> + <type id="1">Extension</type> + <guid>test1@tests.mozilla.org</guid> + <version>1.11</version> + <authors><author><name>Test Creator 11</name></author></authors> + <status id="4">Public</status> + <summary>Add-on with a guid that matches a previously successful result should be ignored.</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test11.xpi</install> + </addon> + + <!-- Fails because guid matches already installed add-on --> + <addon> + <name>FAIL</name> + <type id="1">Extension</type> + <guid>test_AddonRepository_1@tests.mozilla.org</guid> + <version>1.12</version> + <authors><author><name>Test Creator 12</name></author></authors> + <status id="4">Public</status> + <summary>Add-on with a guid that matches an installed Addon should be ignored.</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test12.xpi</install> + </addon> + + <!-- Fails because version is undefined --> + <addon> + <name>FAIL</name> + <type id="1">Extension</type> + <guid>test13@tests.mozilla.org</guid> + <authors><author><name>Test Creator 13</name></author></authors> + <status id="4">Public</status> + <summary>Add-on with undefined version should be ignored.</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test13.xpi</install> + </addon> + + <!-- Fails because version is empty --> + <addon> + <name>FAIL</name> + <type id="1">Extension</type> + <guid>test14@tests.mozilla.org</guid> + <version> </version> + <authors><author><name>Test Creator 14</name></author></authors> + <status id="4">Public</status> + <summary>Add-on with empty version should be ignored.</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test14.xpi</install> + </addon> + + <!-- Fails because authors undefined --> + <addon> + <name>FAIL</name> + <type id="1">Extension</type> + <guid>test15@tests.mozilla.org</guid> + <version>1.15</version> + <status id="4">Public</status> + <summary>Add-on with undefined authors should be ignored.</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test15.xpi</install> + </addon> + + <!-- Fails because it has no defined author elements --> + <addon> + <name>FAIL</name> + <type id="1">Extension</type> + <guid>test16@tests.mozilla.org</guid> + <version>1.16</version> + <authors></authors> + <status id="4">Public</status> + <summary>Add-on with no defined author elements should be ignored.</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test16.xpi</install> + </addon> + + <!-- Fails because no non-empty author elements --> + <addon> + <name>FAIL</name> + <type id="1">Extension</type> + <guid>test17@tests.mozilla.org</guid> + <version>1.17</version> + <authors> + <author><name></name></author> + <author><name></name> </author> + </authors> + <status id="4">Public</status> + <summary>Add-on with no non-empty author elements should be ignored.</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test17.xpi</install> + </addon> + + <!-- Fails because status is undefined --> + <addon> + <name>FAIL</name> + <type id="1">Extension</type> + <guid>test18@tests.mozilla.org</guid> + <version>1.18</version> + <authors><author><name>Test Creator 18</name></author></authors> + <summary>Add-on with undefined status should be ignored.</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test18.xpi</install> + </addon> + + <!-- Fails because status is not Public --> + <addon> + <name>FAIL</name> + <type id="1">Extension</type> + <guid>test19@tests.mozilla.org</guid> + <version>1.19</version> + <authors><author><name>Test Creator 19</name></author></authors> + <status id="9999">Unknown</status> + <summary>Add-on with non-Public status should be ignored.</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test19.xpi</install> + </addon> + + <!-- Fails because compatible_applications is undefined --> + <addon> + <name>FAIL</name> + <type id="1">Extension</type> + <guid>test20@tests.mozilla.org</guid> + <version>1.20</version> + <authors><author><name>Test Creator 20</name></author></authors> + <status id="4">Public</status> + <summary>Add-on with undefined compatible_applications should be ignored.</summary> + <install>http://localhost:%PORT%/test20.xpi</install> + </addon> + + <!-- Fails because no compatible applications matched --> + <addon> + <name>FAIL</name> + <type id="1">Extension</type> + <guid>test21@tests.mozilla.org</guid> + <version>1.21</version> + <authors><author><name>Test Creator 21</name></author></authors> + <status id="4">Public</status> + <summary>Add-on with no compatible applications should be ignored.</summary> + <compatible_applications> + <application> + <appID>unknown@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test21.xpi</install> + </addon> + + <!-- Fails because compatible application's min version is undefined --> + <addon> + <name>FAIL</name> + <type id="1">Extension</type> + <guid>test22@tests.mozilla.org</guid> + <version>1.22</version> + <authors><author><name>Test Creator 22</name></author></authors> + <status id="4">Public</status> + <summary>Add-on with too high of a compatible application min version should be ignored.</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <max_version>2.0</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test22.xpi</install> + </addon> + + <!-- Fails because compatible application's min version too high --> + <addon> + <name>FAIL</name> + <type id="1">Extension</type> + <guid>test23@tests.mozilla.org</guid> + <version>1.23</version> + <authors><author><name>Test Creator 23</name></author></authors> + <status id="4">Public</status> + <summary>Add-on with too high of a compatible application min version should be ignored.</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1.1</min_version> + <max_version>2.0</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test23.xpi</install> + </addon> + + <!-- Fails because compatible application's max version is undefined --> + <addon> + <name>FAIL</name> + <type id="1">Extension</type> + <guid>test24@tests.mozilla.org</guid> + <version>1.24</version> + <authors><author><name>Test Creator 24</name></author></authors> + <status id="4">Public</status> + <summary>Add-on with too low of a compatible application max version should be ignored.</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>0.9</min_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test24.xpi</install> + </addon> + + <!-- Fails because compatible application's max version is too low --> + <addon> + <name>FAIL</name> + <type id="1">Extension</type> + <guid>test25@tests.mozilla.org</guid> + <version>1.25</version> + <authors><author><name>Test Creator 25</name></author></authors> + <status id="4">Public</status> + <summary>Add-on with too low of a compatible application max version should be ignored.</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>0.9</min_version> + <max_version>0.9.9</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test25.xpi</install> + </addon> + + <!-- Fails because XPI URL is undefined --> + <addon> + <name>FAIL</name> + <type id="1">Extension</type> + <guid>test26@tests.mozilla.org</guid> + <version>1.26</version> + <authors><author><name>Test Creator 26</name></author></authors> + <status id="4">Public</status> + <summary>Add-on with undefined XPI URL should be ignored.</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + </addon> + + <!-- Fails because XPI URL is empty --> + <addon> + <name>FAIL</name> + <type id="1">Extension</type> + <guid>test27@tests.mozilla.org</guid> + <version>1.27</version> + <authors><author><name>Test Creator 27</name></author></authors> + <status id="4">Public</status> + <summary>Add-on with an empty XPI URL should be ignored.</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install> </install> + </addon> + + <!-- Fails because install not compatible with OS --> + <addon> + <name>FAIL</name> + <type id="1">Extension</type> + <guid>test28@tests.mozilla.org</guid> + <version>1.28</version> + <authors><author><name>Test Creator 28</name></author></authors> + <status id="4">Public</status> + <summary>Add-on with no installs with compatible OS should be ignored.</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install os="UNKNOWN1">http://localhost:%PORT%/test28.xpi</install> + <install os="UNKNOWN2">http://localhost:%PORT%/test28.xpi</install> + </addon> + + <!-- Fails because XPI URL matches an installing AddonInstall --> + <addon> + <name>FAIL</name> + <type id="1">Extension</type> + <guid>test29@tests.mozilla.org</guid> + <version>1.29</version> + <authors><author><name>Test Creator 29</name></author></authors> + <status id="4">Public</status> + <summary>Add-on with an XPI URL that matches an installing AddonInstall should be ignored.</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/addons/test_AddonRepository_2.xpi</install> + </addon> + + <!-- Passes because the add-on has the right payment info --> + <addon> + <name>PASS</name> + <type id="1">Extension</type> + <guid>purchase1@tests.mozilla.org</guid> + <version>2.0</version> + <authors> + <author> + <name>Test Creator - Last Passing</name> + <link>http://localhost:%PORT%/creatorLastPassing.html</link> + </author> + </authors> + <status id="4">Public</status> + <all_compatible_os> + <os>ALL</os> + </all_compatible_os> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <rating>5</rating> + <payment_data> + <link>http://localhost:%PORT%/purchaseURL1</link> + <amount amount="5">$5</amount> + </payment_data> + </addon> + + <!-- Passes because the add-on has the right payment info --> + <addon> + <name>PASS</name> + <type id="1">Extension</type> + <guid>purchase2@tests.mozilla.org</guid> + <version>2.0</version> + <authors> + <author> + <name>Test Creator - Last Passing</name> + <link>http://localhost:%PORT%/creatorLastPassing.html</link> + </author> + </authors> + <status id="4">Public</status> + <all_compatible_os> + <os>XPCShell</os> + </all_compatible_os> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <rating>5</rating> + <payment_data> + <link>http://localhost:%PORT%/purchaseURL2</link> + <amount amount="10.0">$10</amount> + </payment_data> + </addon> + + <!-- Fails because the add-on doesn't match the platform --> + <addon> + <name>FAIL</name> + <type id="1">Extension</type> + <guid>purchase3@tests.mozilla.org</guid> + <version>2.0</version> + <authors> + <author> + <name>Test Creator - Last Passing</name> + <link>http://localhost:%PORT%/creatorLastPassing.html</link> + </author> + </authors> + <status id="4">Public</status> + <all_compatible_os> + <os>FOO</os> + </all_compatible_os> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <rating>5</rating> + <payment_data> + <link>http://localhost:%PORT%/purchaseURL3</link> + <amount amount="10">$10</amount> + </payment_data> + </addon> + + <!-- Passes because the Addon that has a matching XPI URL + has a state = STATE_AVAILABLE (non-active install). This is the + last passing add-on. --> + <addon> + <name>PASS</name> + <type id="1">Extension</type> + <guid>test-lastPassing@tests.mozilla.org</guid> + <version>2.0</version> + <authors> + <author> + <name>Test Creator - Last Passing</name> + <link>http://localhost:%PORT%/creatorLastPassing.html</link> + </author> + </authors> + <status id="4">Public</status> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <!-- Test that a rating > 5 becomes a rating = 5 --> + <rating>10</rating> + <install>http://localhost:%PORT%/addons/test_AddonRepository_3.xpi</install> + </addon> + + <!-- Fails because of MAX_RESULTS limit. The previous <addon> should + be the last passing add-on in order to correctly test the limit. --> + <addon> + <name>FAIL</name> + <type id="1">Extension</type> + <guid>test-surpassesLimit@tests.mozilla.org</guid> + <version>9.9</version> + <authors><author><name>Test Creator - Surpasses Limit</name></author></authors> + <status id="4">Public</status> + <summary>Add-on should not be added because doing so would surpass MAX_RESULTS limit</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test-surpassesLimit.xpi</install> + </addon> +</searchresults> + diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_cache.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_cache.xml new file mode 100644 index 000000000..f707f1217 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_cache.xml @@ -0,0 +1,182 @@ +<?xml version="1.0" encoding="utf-8" ?> +<searchresults total_results="1111"> + <addon> + <name>Repo Add-on 1</name> + <type id="1">Extension</type> + <guid>test_AddonRepository_1@tests.mozilla.org</guid> + <version>2.1</version> + <authors> + <author> + <name>Repo Add-on 1 - Creator</name> + <link>http://localhost:4444/repo/1/creator.html</link> + </author> + <author> + <name>Repo Add-on 1 - First Developer</name> + <link>http://localhost:4444/repo/1/firstDeveloper.html</link> + </author> + <author> + <name>Repo Add-on 1 - Second Developer</name> + <link>http://localhost:4444/repo/1/secondDeveloper.html</link> + </author> + </authors> + <summary>Repo Add-on 1 - Description<br>Second line</summary> + <description><p>Repo Add-on 1 - Full Description &amp; some extra</p></description> + <eula>Repo Add-on 1 - EULA</eula> + <developer_comments>Repo Add-on 1 + Developer Comments</developer_comments> + <icon size="32">http://localhost/repo/1/icon.png</icon> + <status id="4">Public</status> + <rating>1</rating> + <learnmore>http://localhost/repo/1/learnmore.html</learnmore> + <homepage>http://localhost/repo/1/homepage.html</homepage> + <support>http://localhost/repo/1/support.html</support> + <contribution_data> + <link>http://localhost/repo/1/contribution.html</link> + <suggested_amount currency="USD">$11.11</suggested_amount> + <meet_developers>http://localhost/repo/1/meetDevelopers.html</meet_developers> + </contribution_data> + <reviews num="1111">http://localhost/repo/1/review.html</reviews> + <total_downloads>2221</total_downloads> + <weekly_downloads>3331</weekly_downloads> + <daily_users>4441</daily_users> + <last_updated epoch="9">1970-01-01T00:00:09Z</last_updated> + <install size="9">http://localhost:4444/repo/1/install.xpi</install> + </addon> + + <addon> + <name>Repo Add-on 2</name> + <type id="2">Theme</type> + <guid>test_AddonRepository_2@tests.mozilla.org</guid> + <version>2.2</version> + <authors> + <author> + <name>Repo Add-on 2 - Creator</name> + <link>http://localhost:4444/repo/2/creator.html</link> + </author> + <author> + <name>Repo Add-on 2 - First Developer</name> + <link>http://localhost:4444/repo/2/firstDeveloper.html</link> + </author> + <author> + <name>Repo Add-on 2 - Second Developer</name> + <link>http://localhost:4444/repo/2/secondDeveloper.html</link> + </author> + </authors> + <summary>Repo Add-on 2 - Description</summary> + <description>Repo Add-on 2 - Full Description</description> + <eula>Repo Add-on 2 - EULA</eula> + <developer_comments>Repo Add-on 2 - Developer Comments</developer_comments> + <icon size="32">http://localhost/repo/2/icon.png</icon> + <status id="9">Unknown</status> + <previews> + <preview primary="1"> + <full type="image/png">http://localhost:4444/repo/2/firstFull.png</full> + <thumbnail type="image/png">http://localhost:4444/repo/2/firstThumbnail.png</thumbnail> + <caption>Repo Add-on 2 - First Caption</caption> + </preview> + <preview primary="0"> + <full type="image/png">http://localhost:4444/repo/2/secondFull.png</full> + <thumbnail type="image/png">http://localhost:4444/repo/2/secondThumbnail.png</thumbnail> + <caption>Repo Add-on 2 - Second Caption</caption> + </preview> + </previews> + <rating>2</rating> + <learnmore>http://localhost/repo/2/learnmore.html</learnmore> + <homepage>http://localhost/repo/2/homepage.html</homepage> + <support>http://localhost/repo/2/support.html</support> + <contribution_data> + <link>http://localhost/repo/2/contribution.html</link> + <meet_developers>http://localhost/repo/2/meetDevelopers.html</meet_developers> + </contribution_data> + <reviews num="1112">http://localhost/repo/2/review.html</reviews> + <total_downloads>2222</total_downloads> + <weekly_downloads>3332</weekly_downloads> + <daily_users>4442</daily_users> + <last_updated epoch="9">1970-01-01T00:00:09Z</last_updated> + <install size="9">http://localhost:4444/repo/2/install.xpi</install> + </addon> + + <addon> + <name>Repo Add-on 3</name> + <type id="2">Theme</type> + <guid>test_AddonRepository_3@tests.mozilla.org</guid> + <version>2.3</version> + <icon size="32">http://localhost/repo/3/icon.png</icon> + <previews> + <preview primary="1"> + <full type="image/png">http://localhost:4444/repo/3/firstFull.png</full> + <thumbnail type="image/png">http://localhost:4444/repo/3/firstThumbnail.png</thumbnail> + <caption>Repo Add-on 3 - First Caption</caption> + </preview> + <preview primary="0"> + <full type="image/png">http://localhost:4444/repo/3/secondFull.png</full> + <thumbnail type="image/png">http://localhost:4444/repo/3/secondThumbnail.png</thumbnail> + <caption>Repo Add-on 3 - Second Caption</caption> + </preview> + </previews> + </addon> + + <addon_compatibility hosted="true" id="123"> + <guid>test_AddonRepository_1@tests.mozilla.org</guid> + <name>PASS</name> + <version_ranges> + <!-- Will be included --> + <version_range type="incompatible"> + <min_version>0.1</min_version> + <max_version>0.2</max_version> + <compatible_applications> + <application> + <name>XPCShell</name> + <application_id>666</application_id> + <min_version>3.0</min_version> + <max_version>4.0</max_version> + <appID>xpcshell@tests.mozilla.org</appID> + </application> + </compatible_applications> + </version_range> + <!-- Will be included --> + <version_range type="incompatible"> + <min_version>0.2</min_version> + <max_version>0.3</max_version> + <compatible_applications> + <application> + <name>XPCShell</name> + <application_id>666</application_id> + <min_version>5.0</min_version> + <max_version>6.0</max_version> + <appID>xpcshell@tests.mozilla.org</appID> + </application> + </compatible_applications> + </version_range> + <!-- Won't be included - invalid type attribute --> + <version_range type="unknown"> + <min_version>9</min_version> + <max_version>10</max_version> + <compatible_applications> + <application> + <name>XPCShell</name> + <application_id>666</application_id> + <min_version>10.0</min_version> + <max_version>11.0</max_version> + <appID>xpcshell@tests.mozilla.org</appID> + </application> + </compatible_applications> + </version_range> + <!-- Won't be included - no matching appID --> + <version_range type="incompatible"> + <min_version>0.2</min_version> + <max_version>0.3</max_version> + <compatible_applications> + <application> + <name>Unknown App</name> + <application_id>123</application_id> + <min_version>1.0</min_version> + <max_version>999.0</max_version> + <appID>unknown-app@tests.mozilla.org</appID> + </application> + </compatible_applications> + </version_range> + </version_ranges> + </addon_compatibility> +</searchresults> + diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_compatmode_ignore.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_compatmode_ignore.xml new file mode 100644 index 000000000..003095727 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_compatmode_ignore.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8" ?> +<searchresults total_results="123"> + <addon> + <name>Test Repo Add-on - ignore</name> + <type id="1">Extension</type> + <guid>compatmode-ignore@tests.mozilla.org</guid> + <version>1.1</version> + <authors> + <author> + <name>Test Creator 1</name> + <link>http://localhost:%PORT%/creator1.html</link> + </author> + </authors> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test1.xpi</install> + </addon> +</searchresults> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_compatmode_normal.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_compatmode_normal.xml new file mode 100644 index 000000000..fec8b09ca --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_compatmode_normal.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8" ?> +<searchresults total_results="123"> + <addon> + <name>Test Repo Add-on - normal</name> + <type id="1">Extension</type> + <guid>compatmode-normal@tests.mozilla.org</guid> + <version>1.1</version> + <authors> + <author> + <name>Test Creator 1</name> + <link>http://localhost:%PORT%/creator1.html</link> + </author> + </authors> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test1.xpi</install> + </addon> +</searchresults> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_compatmode_strict.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_compatmode_strict.xml new file mode 100644 index 000000000..f99256b87 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_compatmode_strict.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8" ?> +<searchresults total_results="123"> + <addon> + <name>Test Repo Add-on - strict</name> + <type id="1">Extension</type> + <guid>compatmode-strict@tests.mozilla.org</guid> + <version>1.1</version> + <authors> + <author> + <name>Test Creator 1</name> + <link>http://localhost:%PORT%/creator1.html</link> + </author> + </authors> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test1.xpi</install> + </addon> +</searchresults> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_empty.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_empty.xml new file mode 100644 index 000000000..4cd5c1443 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_empty.xml @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="utf-8" ?> +<searchresults total_results="9999" /> + diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_failed.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_failed.xml new file mode 100644 index 000000000..d02fa0249 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_failed.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8" ?> +<searchresults total_results="9999"> +<!-- Cause XML parse error so that the search fails --> +<!-- <addon> --> + <name>PASS</name> + <type id="1">Extension</type> + <guid>test1@tests.mozilla.org</guid> + <version>1.1</version> + <authors><author><name>Test Creator 1</name></author></authors> + <status id="4">Public</status> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test1.xpi</install> + </addon> +</searchresults> + diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_getAddonsByIDs.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_getAddonsByIDs.xml new file mode 100644 index 000000000..8a6167969 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_getAddonsByIDs.xml @@ -0,0 +1,187 @@ +<?xml version="1.0" encoding="utf-8" ?> +<searchresults total_results="1111"> + <!-- Passes even though XPI URL matches an installing AddonInstall. + Tests optional attributes. --> + <addon> + <name>PASS</name> + <type id="1">Extension</type> + <guid>test1@tests.mozilla.org</guid> + <version>1.1</version> + <authors> + <author> + <name>Test Creator 1</name> + <link>http://localhost:%PORT%/creator1.html</link> + </author> + <author> + <name>Test Developer 1</name> + <link>http://localhost:%PORT%/developer1.html</link> + </author> + </authors> + <summary>Test Summary 1</summary> + <description>Test Description 1</description> + <eula>Test EULA 1</eula> + <developer_comments>Test Developer Comments 1</developer_comments> + <icon size="32">http://localhost:%PORT%/icon1.png</icon> + <status id="8">Preliminarily Reviewed</status> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <previews> + <preview primary="1"> + <full type="image/png" width="400" height="300"> + http://localhost:%PORT%/full1-1.png + </full> + <thumbnail type="image/png" width="200" height="150"> + http://localhost:%PORT%/thumbnail1-1.png + </thumbnail> + <caption>Caption 1 - 1</caption> + </preview> + <preview primary="0"> + <full type="image/png">http://localhost:%PORT%/full2-1.png</full> + <thumbnail type="image/png">http://localhost:%PORT%/thumbnail2-1.png</thumbnail> + <caption>Caption 2 - 1</caption> + </preview> + </previews> + <rating>4</rating> + <learnmore>http://localhost:%PORT%/learnmore1.html</learnmore> + <support>http://localhost:%PORT%/support1.html</support> + <contribution_data> + <link>http://localhost:%PORT%/contribution1.html</link> + <suggested_amount currency="USD">$11.11</suggested_amount> + <meet_developers>http://localhost:%PORT%/meetDevelopers1.html</meet_developers> + </contribution_data> + <reviews num="1111">http://localhost:%PORT%/review1.html</reviews> + <total_downloads>2222</total_downloads> + <weekly_downloads>3333</weekly_downloads> + <daily_users>4444</daily_users> + <last_updated epoch="1265033045">2010-02-01T14:04:05Z</last_updated> + <install size="5555">http://localhost:%PORT%/addons/test_AddonRepository_2.xpi</install> + </addon> + + <addon_compatibility hosted="true" id="123"> + <guid>test1@tests.mozilla.org</guid> + <name>PASS</name> + <version_ranges> + <!-- Will be included --> + <version_range type="incompatible"> + <min_version>0.1</min_version> + <max_version>0.2</max_version> + <compatible_applications> + <application> + <name>XPCShell</name> + <application_id>666</application_id> + <min_version>3.0</min_version> + <max_version>4.0</max_version> + <appID>xpcshell@tests.mozilla.org</appID> + </application> + </compatible_applications> + </version_range> + <!-- Will be included --> + <version_range type="incompatible"> + <min_version>0.2</min_version> + <max_version>0.3</max_version> + <compatible_applications> + <application> + <name>XPCShell</name> + <application_id>666</application_id> + <min_version>5.0</min_version> + <max_version>6.0</max_version> + <appID>xpcshell@tests.mozilla.org</appID> + </application> + </compatible_applications> + </version_range> + <!-- Won't be included - invalid type attribute --> + <version_range type="unknown"> + <min_version>9</min_version> + <max_version>10</max_version> + <compatible_applications> + <application> + <name>XPCShell</name> + <application_id>666</application_id> + <min_version>10.0</min_version> + <max_version>11.0</max_version> + <appID>xpcshell@tests.mozilla.org</appID> + </application> + </compatible_applications> + </version_range> + <!-- Won't be included - no matching appID --> + <version_range type="incompatible"> + <min_version>0.2</min_version> + <max_version>0.3</max_version> + <compatible_applications> + <application> + <name>Unknown App</name> + <application_id>123</application_id> + <min_version>1.0</min_version> + <max_version>999.0</max_version> + <appID>unknown-app@tests.mozilla.org</appID> + </application> + </compatible_applications> + </version_range> + </version_ranges> + </addon_compatibility> + + <!-- Fails because guid matches previously successful result --> + <addon> + <name>FAIL</name> + <type id="1">Extension</type> + <guid>test1@tests.mozilla.org</guid> + <version>1.2</version> + <authors><author><name>Test Creator 2</name></author></authors> + <status id="4">Public</status> + <summary>Add-on with a guid that matches a previously successful result should be ignored.</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test2.xpi</install> + </addon> + + <!-- Fails because guid was not requested --> + <addon> + <name>FAIL</name> + <type id="1">Extension</type> + <guid>notRequested@tests.mozilla.org</guid> + <version>1.3</version> + <authors><author><name>Test Creator 3</name></author></authors> + <status id="4">Public</status> + <summary>Add-on with a guid that wasn't requested should be ignored.</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test3.xpi</install> + </addon> + + <!-- Passes even though guid matches already installed add-on, + type is unknown, no defined author elements, status is not Public, + no compatible applications matched, no installs compatible with OS + --> + <addon> + <name>PASS</name> + <type id="2">Theme</type> + <guid>test_AddonRepository_1@tests.mozilla.org</guid> + <version>1.4</version> + <status id="9999">Unknown</status> + <compatible_applications> + <application> + <appID>unknown@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install os="UNKNOWN1">http://localhost:%PORT%/test4.xpi</install> + <install os="UNKNOWN2">http://localhost:%PORT%/test4.xpi</install> + </addon> +</searchresults> + diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_backgroundupdate.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_backgroundupdate.rdf new file mode 100644 index 000000000..ab7cdef34 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_backgroundupdate.rdf @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <RDF:Description about="urn:mozilla:extension:addon1@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <!-- app id compatible update available --> + <RDF:li> + <RDF:Description> + <em:version>2</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/broken.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:addon2@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <!-- app id compatible update available --> + <RDF:li> + <RDF:Description> + <em:version>2</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/broken.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:addon3@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <!-- app id compatible update available --> + <RDF:li> + <RDF:Description> + <em:version>2</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/broken.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + +</RDF:RDF> + diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_blocklist_metadata_filters_1.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_blocklist_metadata_filters_1.xml new file mode 100644 index 000000000..368a6ed53 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_blocklist_metadata_filters_1.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <emItems> + <emItem name="/^Mozilla Corp\.$/"> + <versionRange severity="1"> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange minVersion="1" maxVersion="2.*"/> + </targetApplication> + </versionRange> + </emItem> + <emItem id="/block2/" name="/^Moz/" creator="Dangerous" + homepageURL="/\.dangerous\.com/" updateURL="/\.dangerous\.com/"> + <versionRange severity="3"> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange minVersion="1" maxVersion="2.*"/> + </targetApplication> + </versionRange> + </emItem> + </emItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_blocklist_prefs_1.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_blocklist_prefs_1.xml new file mode 100644 index 000000000..41df457b0 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_blocklist_prefs_1.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <emItems> + <emItem id="block1@tests.mozilla.org"> + <prefs> + <pref>test.blocklist.pref1</pref> + <pref>test.blocklist.pref2</pref> + </prefs> + <versionRange severity="1"> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange minVersion="1" maxVersion="2.*"/> + </targetApplication> + </versionRange> + </emItem> + <emItem id="block2@tests.mozilla.org"> + <prefs> + <pref>test.blocklist.pref3</pref> + <pref>test.blocklist.pref4</pref> + </prefs> + <versionRange severity="3"> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange minVersion="1" maxVersion="2.*"/> + </targetApplication> + </versionRange> + </emItem> + </emItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_blocklist_regexp_1.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_blocklist_regexp_1.xml new file mode 100644 index 000000000..20035c6a2 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_blocklist_regexp_1.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?>
+
+<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist">
+ <emItems>
+ <emItem id="/block1/">
+ <versionRange severity="1">
+ <targetApplication id="xpcshell@tests.mozilla.org">
+ <versionRange minVersion="1" maxVersion="2.*"/>
+ </targetApplication>
+ </versionRange>
+ </emItem>
+ <emItem id="/block1/">
+ <versionRange severity="2">
+ <targetApplication id="xpcshell@tests.mozilla.org">
+ <versionRange minVersion="1" maxVersion="2.*"/>
+ </targetApplication>
+ </versionRange>
+ </emItem>
+ </emItems>
+</blocklist>
diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug299716.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug299716.rdf new file mode 100644 index 000000000..d60d8ca3f --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug299716.rdf @@ -0,0 +1,181 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE RDF:RDF [ + <!ENTITY bug299716 "urn:mozilla:extension:bug299716"> + <!ENTITY addons_prefix "http://localhost:4444/addons/test_bug299716"> + <!ENTITY v0.2 "<em:version>0.2</em:version>"> + + <!ENTITY xpcshell.app " + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>5</em:minVersion> + <em:maxVersion>5</em:maxVersion> + "> + + <!ENTITY toolkit.app " + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>1.9</em:minVersion> + <em:maxVersion>1.9</em:maxVersion> + "> + + <!ENTITY invalidRange " + <em:minVersion>30</em:minVersion> + <em:maxVersion>30</em:maxVersion> + "> + + <!ENTITY xpcshell.invalid " + <em:id>xpcshell@tests.mozilla.org</em:id> + &invalidRange; + "> + + <!ENTITY toolkit.invalid " + <em:id>toolkit@mozilla.org</em:id> + &invalidRange; + "> +]> +<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <!-- XPCShell --> + <RDF:Description about="&bug299716;-a@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li RDF:resource="&bug299716;-a@tests.mozilla.org:0.2"/> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="&bug299716;-a@tests.mozilla.org:0.2"> + &v0.2; + <em:targetApplication> + <RDF:Description em:updateLink="&addons_prefix;_a_2.xpi"> + &xpcshell.app; + </RDF:Description> + </em:targetApplication> + </RDF:Description> + + <!-- Toolkit --> + <RDF:Description about="&bug299716;-b@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li RDF:resource="&bug299716;-b@tests.mozilla.org:0.2"/> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="&bug299716;-b@tests.mozilla.org:0.2"> + &v0.2; + <em:targetApplication> + <RDF:Description em:updateLink="&addons_prefix;_b_2.xpi"> + &toolkit.app; + </RDF:Description> + </em:targetApplication> + </RDF:Description> + + <!-- XPCShell + Toolkit --> + <RDF:Description about="&bug299716;-c@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li RDF:resource="&bug299716;-c@tests.mozilla.org:0.2"/> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="&bug299716;-c@tests.mozilla.org:0.2"> + &v0.2; + <em:targetApplication> + <RDF:Description em:updateLink="&addons_prefix;_c_2.xpi"> + &xpcshell.app; + </RDF:Description> + </em:targetApplication> + <em:targetApplication> + <RDF:Description em:updateLink="&addons_prefix;_c_2.xpi"> + &toolkit.app; + </RDF:Description> + </em:targetApplication> + </RDF:Description> + + <!-- XPCShell (Toolkit invalid) --> + <RDF:Description about="&bug299716;-d@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li RDF:resource="&bug299716;-d@tests.mozilla.org:0.2"/> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="&bug299716;-d@tests.mozilla.org:0.2"> + &v0.2; + <em:targetApplication> + <RDF:Description em:updateLink="&addons_prefix;_d_2.xpi"> + &xpcshell.app; + </RDF:Description> + </em:targetApplication> + <em:targetApplication> + <RDF:Description em:updateLink="&addons_prefix;_d_2.xpi"> + &toolkit.invalid; + </RDF:Description> + </em:targetApplication> + </RDF:Description> + + <!-- Toolkit (XPCShell invalid), should not install --> + <RDF:Description about="&bug299716;-e@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li RDF:resource="&bug299716;-e@tests.mozilla.org:0.2"/> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="&bug299716;-e@tests.mozilla.org:0.2"> + &v0.2; + <em:targetApplication> + <RDF:Description em:updateLink="&addons_prefix;_e_2.xpi"> + &xpcshell.invalid; + </RDF:Description> + </em:targetApplication> + <em:targetApplication> + <RDF:Description em:updateLink="&addons_prefix;_e_2.xpi"> + &toolkit.app; + </RDF:Description> + </em:targetApplication> + </RDF:Description> + + <!-- None (XPCShell, Toolkit invalid), should not install --> + <RDF:Description about="&bug299716;-f@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li RDF:resource="&bug299716;-f@tests.mozilla.org:0.2"/> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="&bug299716;-f@tests.mozilla.org:0.2"> + &v0.2; + <em:targetApplication> + <RDF:Description em:updateLink="&addons_prefix;_f_2.xpi"> + &xpcshell.invalid; + </RDF:Description> + </em:targetApplication> + <em:targetApplication> + <RDF:Description em:updateLink="&addons_prefix;_f_2.xpi"> + &toolkit.invalid; + </RDF:Description> + </em:targetApplication> + </RDF:Description> + + <!-- Toolkit (invalid), should not install --> + <RDF:Description about="&bug299716;-g@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li RDF:resource="&bug299716;-g@tests.mozilla.org:0.2"/> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="&bug299716;-g@tests.mozilla.org:0.2"> + &v0.2; + <em:targetApplication> + <RDF:Description em:updateLink="&addons_prefix;_g_2.xpi"> + &toolkit.invalid; + </RDF:Description> + </em:targetApplication> + </RDF:Description> +</RDF:RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug299716_2.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug299716_2.rdf new file mode 100644 index 000000000..94a4ea450 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug299716_2.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <RDF:Description about="urn:mozilla:extension:bug299716-2@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>0.1</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>1.9</em:minVersion> + <em:maxVersion>2.0.*</em:maxVersion> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> +</RDF:RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug324121.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug324121.rdf new file mode 100644 index 000000000..2c453f756 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug324121.rdf @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <RDF:Description about="urn:mozilla:extension:bug324121_2@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <!-- app id compatible update available --> + <RDF:li> + <RDF:Description> + <em:version>2</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>3</em:minVersion> + <em:maxVersion>3</em:maxVersion> + <em:updateLink>http://localhost:4444/broken.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:bug324121_3@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <!-- app id incompatible update available --> + <RDF:li> + <RDF:Description> + <em:version>2</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>2</em:minVersion> + <em:maxVersion>2</em:maxVersion> + <em:updateLink>http://localhost:4444/broken.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:bug324121_6@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <!-- toolkit id compatible update available --> + <RDF:li> + <RDF:Description> + <em:version>2</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>3</em:minVersion> + <em:maxVersion>3</em:maxVersion> + <em:updateLink>http://localhost:4444/broken.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:bug324121_7@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <!-- toolkit id incompatible update available --> + <RDF:li> + <RDF:Description> + <em:version>2</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>2</em:minVersion> + <em:maxVersion>2</em:maxVersion> + <em:updateLink>http://localhost:4444/broken.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + +</RDF:RDF> + diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug393285.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug393285.xml new file mode 100644 index 000000000..1767b4332 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug393285.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <emItems> + <emItem id="test_bug393285_2@tests.mozilla.org"/> + <emItem id="test_bug393285_3a@tests.mozilla.org"> + <versionRange minVersion="1.0" maxVersion="1.0"/> + </emItem> + <emItem id="test_bug393285_3b@tests.mozilla.org"> + <versionRange minVersion="1.0" maxVersion="1.0"/> + </emItem> + <emItem id="test_bug393285_4@tests.mozilla.org"> + <versionRange minVersion="1.0" maxVersion="1.0"> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange minVersion="1.0" maxVersion="1.0"/> + </targetApplication> + </versionRange> + </emItem> + <emItem id="test_bug393285_5@tests.mozilla.org" os="Darwin"/> + <emItem id="test_bug393285_6@tests.mozilla.org" os="XPCShell"/> + <emItem id="test_bug393285_7@tests.mozilla.org" os="Darwin,XPCShell,WINNT"/> + <emItem id="test_bug393285_8@tests.mozilla.org" xpcomabi="x86-msvc"/> + <emItem id="test_bug393285_9@tests.mozilla.org" xpcomabi="noarch-spidermonkey"/> + <emItem id="test_bug393285_10@tests.mozilla.org" xpcomabi="ppc-gcc3,noarch-spidermonkey,x86-msvc"/> + <emItem id="test_bug393285_11@tests.mozilla.org" os="Darwin" xpcomabi="ppc-gcc3,x86-msvc"/> + <emItem id="test_bug393285_12@tests.mozilla.org" os="Darwin" xpcomabi="ppc-gcc3,noarch-spidermonkey,x86-msvc"/> + <emItem id="test_bug393285_13@tests.mozilla.org" os="XPCShell" xpcomabi="ppc-gcc3,x86-msvc"/> + <emItem id="test_bug393285_14@tests.mozilla.org" os="XPCShell,WINNT" xpcomabi="ppc-gcc3,x86-msvc,noarch-spidermonkey"/> + </emItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug394300.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug394300.rdf new file mode 100644 index 000000000..94e12527f --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug394300.rdf @@ -0,0 +1,159 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <RDF:Description about="urn:mozilla:extension:bug394300_1@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <!-- Not a valid install - incompatible app versions --> + <RDF:li> + <RDF:Description> + <em:version>20</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>2</em:minVersion> + <em:maxVersion>2</em:maxVersion> + <em:updateLink>http://localhost:4444/broken.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + <!-- Valid install should be the version detected --> + <RDF:li> + <RDF:Description> + <em:version>10</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>http://localhost:4444/broken.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + <!-- Valid install. Detecting this would indicate that the order + of entries is playing a part in the update detection. --> + <RDF:li> + <RDF:Description> + <em:version>6</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>http://localhost:4444/broken.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + <!-- Not a valid install - no minVersion or maxVersion specified --> + <RDF:li> + <RDF:Description> + <em:version>40</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:updateLink>http://localhost:4444/broken.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + <!-- Not a valid install - incompatible app versions --> + <RDF:li> + <RDF:Description> + <em:version>30</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>2</em:minVersion> + <em:maxVersion>2</em:maxVersion> + <em:updateLink>http://localhost:4444/broken.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <RDF:Description about="urn:mozilla:extension:bug394300_2@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <!-- Not a valid install - incompatible app versions --> + <RDF:li> + <RDF:Description> + <em:version>20</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>2</em:minVersion> + <em:maxVersion>2</em:maxVersion> + <em:updateLink>http://localhost:4444/broken.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + <!-- Valid install should be the version detected --> + <RDF:li> + <RDF:Description> + <em:version>10</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>1.9</em:minVersion> + <em:maxVersion>1.9</em:maxVersion> + <em:updateLink>http://localhost:4444/broken.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + <!-- Valid install. Detecting this would indicate that the order + of entries is playing a part in the update detection. --> + <RDF:li> + <RDF:Description> + <em:version>6</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>1.9</em:minVersion> + <em:maxVersion>1.9</em:maxVersion> + <em:updateLink>http://localhost:4444/broken.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + <!-- Not a valid install - no minVersion or maxVersion specified --> + <RDF:li> + <RDF:Description> + <em:version>40</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:updateLink>http://localhost:4444/broken.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + <!-- Not a valid install - incompatible app versions --> + <RDF:li> + <RDF:Description> + <em:version>30</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>2</em:minVersion> + <em:maxVersion>2</em:maxVersion> + <em:updateLink>http://localhost:4444/broken.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + +</RDF:RDF> + diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug424262.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug424262.xml new file mode 100644 index 000000000..d797debbb --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug424262.xml @@ -0,0 +1,185 @@ +<?xml version="1.0" encoding="utf-8" ?> +<searchresults total_results="100"> + <addon> + <name>TEST</name> + <type id='1'>Extension</type> + <guid>test1@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://localhost:%PORT%/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test.xpi</install> + </addon> + + <addon> + <name>TEST</name> + <rating>-5</rating> + <type id='1'>Extension</type> + <guid>test2@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://localhost:%PORT%/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test.xpi</install> + </addon> + + <addon> + <name>TEST</name> + <rating>0</rating> + <type id='1'>Extension</type> + <guid>test3@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://localhost:%PORT%/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test.xpi</install> + </addon> + + <addon> + <name>TEST</name> + <rating>2</rating> + <type id='1'>Extension</type> + <guid>test4@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://localhost:%PORT%/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test.xpi</install> + </addon> + + <addon> + <name>TEST</name> + <rating>4</rating> + <type id='1'>Extension</type> + <guid>test5@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://localhost:%PORT%/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test.xpi</install> + </addon> + + <addon> + <name>TEST</name> + <rating>5</rating> + <type id='1'>Extension</type> + <guid>test6@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://localhost:%PORT%/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test.xpi</install> + </addon> + + <addon> + <name>TEST</name> + <rating>10</rating> + <type id='1'>Extension</type> + <guid>test7@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://localhost:%PORT%/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test.xpi</install> + </addon> + + <addon> + <name>TEST</name> + <rating>100</rating> + <type id='1'>Extension</type> + <guid>test8@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://localhost:%PORT%/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test.xpi</install> + </addon> +</searchresults> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug449027_app.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug449027_app.xml new file mode 100644 index 000000000..f12ca1fa6 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug449027_app.xml @@ -0,0 +1,333 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <emItems> + <!-- All extensions are version 5 and tests run against appVersion 3 --> + + <!-- Test 1 not listed, should never get blocked --> + <!-- Always blocked --> + <emItem id="test_bug449027_2@tests.mozilla.org"/> + <!-- Always blocked --> + <emItem id="test_bug449027_3@tests.mozilla.org"> + <versionRange/> + </emItem> + <!-- Not blocked since neither version range matches --> + <emItem id="test_bug449027_4@tests.mozilla.org"> + <versionRange minVersion="6"/> + <versionRange maxVersion="4"/> + </emItem> + <!-- Invalid version range, should not block --> + <emItem id="test_bug449027_5@tests.mozilla.org"> + <versionRange minVersion="6" maxVersion="4"/> + </emItem> + <!-- Should block all of these --> + <emItem id="test_bug449027_6@tests.mozilla.org"> + <versionRange minVersion="7" maxVersion="8"/> + <versionRange minVersion="5" maxVersion="6"/> + <versionRange maxVersion="4"/> + </emItem> + <emItem id="test_bug449027_7@tests.mozilla.org"> + <versionRange maxVersion="4"/> + <versionRange minVersion="4" maxVersion="5"/> + <versionRange minVersion="6" maxVersion="7"/> + </emItem> + <emItem id="test_bug449027_8@tests.mozilla.org"> + <versionRange minVersion="2" maxVersion="2"/> + <versionRange minVersion="4" maxVersion="6"/> + <versionRange minVersion="7" maxVersion="8"/> + </emItem> + <emItem id="test_bug449027_9@tests.mozilla.org"> + <versionRange minVersion="4"/> + </emItem> + <emItem id="test_bug449027_10@tests.mozilla.org"> + <versionRange minVersion="5"/> + </emItem> + <emItem id="test_bug449027_11@tests.mozilla.org"> + <versionRange maxVersion="6"/> + </emItem> + <emItem id="test_bug449027_12@tests.mozilla.org"> + <versionRange maxVersion="5"/> + </emItem> + + <!-- This should block all versions for any application --> + <emItem id="test_bug449027_13@tests.mozilla.org"> + <versionRange> + <targetApplication/> + </versionRange> + </emItem> + <!-- Shouldn't block --> + <emItem id="test_bug449027_14@tests.mozilla.org"> + <versionRange> + <targetApplication id="foo@bar.com"/> + </versionRange> + </emItem> + <!-- Should block for any version of the app --> + <emItem id="test_bug449027_15@tests.mozilla.org"> + <versionRange> + <targetApplication id="xpcshell@tests.mozilla.org"/> + </versionRange> + </emItem> + <!-- Should still block --> + <emItem id="test_bug449027_16@tests.mozilla.org"> + <versionRange> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange/> + </targetApplication> + </versionRange> + </emItem> + <!-- Not blocked since neither version range matches --> + <emItem id="test_bug449027_17@tests.mozilla.org"> + <versionRange> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange minVersion="4"/> + <versionRange maxVersion="2"/> + </targetApplication> + </versionRange> + </emItem> + <!-- Invalid version range, should not block --> + <emItem id="test_bug449027_18@tests.mozilla.org"> + <versionRange> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange minVersion="6" maxVersion="4"/> + </targetApplication> + </versionRange> + </emItem> + <!-- Should block all of these --> + <emItem id="test_bug449027_19@tests.mozilla.org"> + <versionRange> + <targetApplication id="foo@bar.com"/> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange minVersion="5" maxVersion="6"/> + <versionRange minVersion="3" maxVersion="4"/> + <versionRange maxVersion="2"/> + </targetApplication> + </versionRange> + </emItem> + <emItem id="test_bug449027_20@tests.mozilla.org"> + <versionRange> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange maxVersion="2"/> + <versionRange minVersion="2" maxVersion="3"/> + <versionRange minVersion="4" maxVersion="5"/> + </targetApplication> + <targetApplication id="foo@bar.com"/> + </versionRange> + </emItem> + <emItem id="test_bug449027_21@tests.mozilla.org"> + <versionRange> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange minVersion="1" maxVersion="1"/> + <versionRange minVersion="2" maxVersion="4"/> + <versionRange minVersion="5" maxVersion="6"/> + </targetApplication> + </versionRange> + </emItem> + <emItem id="test_bug449027_22@tests.mozilla.org"> + <versionRange> + <targetApplication id="foo@bar.com"/> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange minVersion="3"/> + </targetApplication> + </versionRange> + </emItem> + <emItem id="test_bug449027_23@tests.mozilla.org"> + <versionRange> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange minVersion="2"/> + </targetApplication> + <targetApplication id="foo@bar.com"/> + </versionRange> + </emItem> + <emItem id="test_bug449027_24@tests.mozilla.org"> + <versionRange> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange maxVersion="3"/> + </targetApplication> + </versionRange> + </emItem> + <emItem id="test_bug449027_25@tests.mozilla.org"> + <versionRange> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange maxVersion="4"/> + </targetApplication> + </versionRange> + </emItem> + </emItems> + <pluginItems> + <!-- All plugins are version 5 and tests run against appVersion 3 --> + + <!-- Test 1 not listed, should never get blocked --> + <!-- Always blocked --> + <pluginItem> + <match name="name" exp="^test_bug449027_2$"/> + </pluginItem> + <!-- Always blocked --> + <pluginItem> + <match name="name" exp="^test_bug449027_3$"/> + <versionRange/> + </pluginItem> + <!-- Not blocked since neither version range matches --> + <pluginItem> + <match name="name" exp="^test_bug449027_4$"/> + <versionRange minVersion="6"/> + <versionRange maxVersion="4"/> + </pluginItem> + <!-- Invalid version range, should not block --> + <pluginItem> + <match name="name" exp="^test_bug449027_5$"/> + <versionRange minVersion="6" maxVersion="4"/> + </pluginItem> + <!-- Should block all of these --> + <pluginItem> + <match name="name" exp="^test_bug449027_6$"/> + <versionRange minVersion="7" maxVersion="8"/> + <versionRange minVersion="5" maxVersion="6"/> + <versionRange maxVersion="4"/> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_bug449027_7$"/> + <versionRange maxVersion="4"/> + <versionRange minVersion="4" maxVersion="5"/> + <versionRange minVersion="6" maxVersion="7"/> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_bug449027_8$"/> + <versionRange minVersion="2" maxVersion="2"/> + <versionRange minVersion="4" maxVersion="6"/> + <versionRange minVersion="7" maxVersion="8"/> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_bug449027_9$"/> + <versionRange minVersion="4"/> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_bug449027_10$"/> + <versionRange minVersion="5"/> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_bug449027_11$"/> + <versionRange maxVersion="6"/> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_bug449027_12$"/> + <versionRange maxVersion="5"/> + </pluginItem> + + <!-- This should block all versions for any application --> + <pluginItem> + <match name="name" exp="^test_bug449027_13$"/> + <versionRange> + <targetApplication/> + </versionRange> + </pluginItem> + <!-- Shouldn't block --> + <pluginItem> + <match name="name" exp="^test_bug449027_14$"/> + <versionRange> + <targetApplication id="foo@bar.com"/> + </versionRange> + </pluginItem> + <!-- Should block for any version of the app --> + <pluginItem> + <match name="name" exp="^test_bug449027_15$"/> + <versionRange> + <targetApplication id="xpcshell@tests.mozilla.org"/> + </versionRange> + </pluginItem> + <!-- Should still block --> + <pluginItem> + <match name="name" exp="^test_bug449027_16$"/> + <versionRange> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange/> + </targetApplication> + </versionRange> + </pluginItem> + <!-- Not blocked since neither version range matches --> + <pluginItem> + <match name="name" exp="^test_bug449027_17$"/> + <versionRange> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange minVersion="4"/> + <versionRange maxVersion="2"/> + </targetApplication> + </versionRange> + </pluginItem> + <!-- Invalid version range, should not block --> + <pluginItem> + <match name="name" exp="^test_bug449027_18$"/> + <versionRange> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange minVersion="6" maxVersion="4"/> + </targetApplication> + </versionRange> + </pluginItem> + <!-- Should block all of these --> + <pluginItem> + <match name="name" exp="^test_bug449027_19$"/> + <versionRange> + <targetApplication id="foo@bar.com"/> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange minVersion="5" maxVersion="6"/> + <versionRange minVersion="3" maxVersion="4"/> + <versionRange maxVersion="2"/> + </targetApplication> + </versionRange> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_bug449027_20$"/> + <versionRange> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange maxVersion="2"/> + <versionRange minVersion="2" maxVersion="3"/> + <versionRange minVersion="4" maxVersion="5"/> + </targetApplication> + <targetApplication id="foo@bar.com"/> + </versionRange> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_bug449027_21$"/> + <versionRange> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange minVersion="1" maxVersion="1"/> + <versionRange minVersion="2" maxVersion="4"/> + <versionRange minVersion="5" maxVersion="6"/> + </targetApplication> + </versionRange> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_bug449027_22$"/> + <versionRange> + <targetApplication id="foo@bar.com"/> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange minVersion="3"/> + </targetApplication> + </versionRange> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_bug449027_23$"/> + <versionRange> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange minVersion="2"/> + </targetApplication> + <targetApplication id="foo@bar.com"/> + </versionRange> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_bug449027_24$"/> + <versionRange> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange maxVersion="3"/> + </targetApplication> + </versionRange> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_bug449027_25$"/> + <versionRange> + <targetApplication id="xpcshell@tests.mozilla.org"> + <versionRange maxVersion="4"/> + </targetApplication> + </versionRange> + </pluginItem> + </pluginItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug449027_toolkit.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug449027_toolkit.xml new file mode 100644 index 000000000..ad8ec5ed9 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug449027_toolkit.xml @@ -0,0 +1,208 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <emItems> + <!-- All extensions are version 5 and tests run against toolkitVersion 8 --> + + <!-- Test 1-14 not listed, should never get blocked --> + + <!-- Should block for any version of the app --> + <emItem id="test_bug449027_15@tests.mozilla.org"> + <versionRange> + <targetApplication id="toolkit@mozilla.org"/> + </versionRange> + </emItem> + <!-- Should still block --> + <emItem id="test_bug449027_16@tests.mozilla.org"> + <versionRange> + <targetApplication id="toolkit@mozilla.org"> + <versionRange/> + </targetApplication> + </versionRange> + </emItem> + <!-- Not blocked since neither version range matches --> + <emItem id="test_bug449027_17@tests.mozilla.org"> + <versionRange> + <targetApplication id="toolkit@mozilla.org"> + <versionRange minVersion="9"/> + <versionRange maxVersion="7"/> + </targetApplication> + </versionRange> + </emItem> + <!-- Invalid version range, should not block --> + <emItem id="test_bug449027_18@tests.mozilla.org"> + <versionRange> + <targetApplication id="toolkit@mozilla.org"> + <versionRange minVersion="11" maxVersion="9"/> + </targetApplication> + </versionRange> + </emItem> + <!-- Should block all of these --> + <emItem id="test_bug449027_19@tests.mozilla.org"> + <versionRange> + <targetApplication id="foo@bar.com"/> + <targetApplication id="toolkit@mozilla.org"> + <versionRange minVersion="10" maxVersion="11"/> + <versionRange minVersion="8" maxVersion="9"/> + <versionRange maxVersion="7"/> + </targetApplication> + </versionRange> + </emItem> + <emItem id="test_bug449027_20@tests.mozilla.org"> + <versionRange> + <targetApplication id="toolkit@mozilla.org"> + <versionRange maxVersion="7"/> + <versionRange minVersion="7" maxVersion="8"/> + <versionRange minVersion="9" maxVersion="10"/> + </targetApplication> + <targetApplication id="foo@bar.com"/> + </versionRange> + </emItem> + <emItem id="test_bug449027_21@tests.mozilla.org"> + <versionRange> + <targetApplication id="toolkit@mozilla.org"> + <versionRange minVersion="6" maxVersion="6"/> + <versionRange minVersion="7" maxVersion="9"/> + <versionRange minVersion="10" maxVersion="11"/> + </targetApplication> + </versionRange> + </emItem> + <emItem id="test_bug449027_22@tests.mozilla.org"> + <versionRange> + <targetApplication id="foo@bar.com"/> + <targetApplication id="toolkit@mozilla.org"> + <versionRange minVersion="8"/> + </targetApplication> + </versionRange> + </emItem> + <emItem id="test_bug449027_23@tests.mozilla.org"> + <versionRange> + <targetApplication id="toolkit@mozilla.org"> + <versionRange minVersion="7"/> + </targetApplication> + <targetApplication id="foo@bar.com"/> + </versionRange> + </emItem> + <emItem id="test_bug449027_24@tests.mozilla.org"> + <versionRange> + <targetApplication id="toolkit@mozilla.org"> + <versionRange maxVersion="8"/> + </targetApplication> + </versionRange> + </emItem> + <emItem id="test_bug449027_25@tests.mozilla.org"> + <versionRange> + <targetApplication id="toolkit@mozilla.org"> + <versionRange maxVersion="9"/> + </targetApplication> + </versionRange> + </emItem> + </emItems> + <pluginItems> + <!-- All plugins are version 5 and tests run against appVersion 3 --> + + <!-- Test 1-14 not listed, should never get blocked --> + <!-- Should block for any version of the app --> + <pluginItem> + <match name="name" exp="^test_bug449027_15$"/> + <versionRange> + <targetApplication id="toolkit@mozilla.org"/> + </versionRange> + </pluginItem> + <!-- Should still block --> + <pluginItem> + <match name="name" exp="^test_bug449027_16$"/> + <versionRange> + <targetApplication id="toolkit@mozilla.org"> + <versionRange/> + </targetApplication> + </versionRange> + </pluginItem> + <!-- Not blocked since neither version range matches --> + <pluginItem> + <match name="name" exp="^test_bug449027_17$"/> + <versionRange> + <targetApplication id="toolkit@mozilla.org"> + <versionRange minVersion="9"/> + <versionRange maxVersion="7"/> + </targetApplication> + </versionRange> + </pluginItem> + <!-- Invalid version range, should not block --> + <pluginItem> + <match name="name" exp="^test_bug449027_18$"/> + <versionRange> + <targetApplication id="toolkit@mozilla.org"> + <versionRange minVersion="11" maxVersion="9"/> + </targetApplication> + </versionRange> + </pluginItem> + <!-- Should block all of these --> + <pluginItem> + <match name="name" exp="^test_bug449027_19$"/> + <versionRange> + <targetApplication id="foo@bar.com"/> + <targetApplication id="toolkit@mozilla.org"> + <versionRange minVersion="10" maxVersion="11"/> + <versionRange minVersion="8" maxVersion="9"/> + <versionRange maxVersion="7"/> + </targetApplication> + </versionRange> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_bug449027_20$"/> + <versionRange> + <targetApplication id="toolkit@mozilla.org"> + <versionRange maxVersion="7"/> + <versionRange minVersion="7" maxVersion="8"/> + <versionRange minVersion="9" maxVersion="10"/> + </targetApplication> + <targetApplication id="foo@bar.com"/> + </versionRange> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_bug449027_21$"/> + <versionRange> + <targetApplication id="toolkit@mozilla.org"> + <versionRange minVersion="6" maxVersion="6"/> + <versionRange minVersion="7" maxVersion="9"/> + <versionRange minVersion="10" maxVersion="11"/> + </targetApplication> + </versionRange> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_bug449027_22$"/> + <versionRange> + <targetApplication id="foo@bar.com"/> + <targetApplication id="toolkit@mozilla.org"> + <versionRange minVersion="8"/> + </targetApplication> + </versionRange> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_bug449027_23$"/> + <versionRange> + <targetApplication id="toolkit@mozilla.org"> + <versionRange minVersion="7"/> + </targetApplication> + <targetApplication id="foo@bar.com"/> + </versionRange> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_bug449027_24$"/> + <versionRange> + <targetApplication id="toolkit@mozilla.org"> + <versionRange maxVersion="8"/> + </targetApplication> + </versionRange> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_bug449027_25$"/> + <versionRange> + <targetApplication id="toolkit@mozilla.org"> + <versionRange maxVersion="9"/> + </targetApplication> + </versionRange> + </pluginItem> + </pluginItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug468528.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug468528.xml new file mode 100644 index 000000000..85f0da57c --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug468528.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <pluginItems> + <pluginItem> + <match name="name" exp="^test_bug468528_1"/> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_bug468528_2["/> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_bug468528_3"/> + </pluginItem> + </pluginItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/install_1.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/install_1.rdf new file mode 100644 index 000000000..5397e8a87 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/install_1.rdf @@ -0,0 +1,17 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>bug470377_1@tests.mozilla.org</em:id> + <em:version>1</em:version> + <em:targetApplication> + <Description> + <em:id>unknown@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + <em:name>Test for Bug 470377</em:name> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/install_2.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/install_2.rdf new file mode 100644 index 000000000..b1dde7f7a --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/install_2.rdf @@ -0,0 +1,17 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>bug470377_2@tests.mozilla.org</em:id> + <em:version>1</em:version> + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + <em:name>Test for Bug 470377</em:name> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/install_3.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/install_3.rdf new file mode 100644 index 000000000..ae483434a --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/install_3.rdf @@ -0,0 +1,17 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>bug470377_3@tests.mozilla.org</em:id> + <em:version>1</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + <em:name>Test for Bug 470377</em:name> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/install_4.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/install_4.rdf new file mode 100644 index 000000000..97abacc5e --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/install_4.rdf @@ -0,0 +1,17 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>bug470377_4@tests.mozilla.org</em:id> + <em:version>1</em:version> + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + <em:name>Test for Bug 470377</em:name> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/install_5.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/install_5.rdf new file mode 100644 index 000000000..bff1104a7 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/install_5.rdf @@ -0,0 +1,17 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>bug470377_5@tests.mozilla.org</em:id> + <em:version>1</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + <em:name>Test for Bug 470377</em:name> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/update_1.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/update_1.rdf new file mode 100644 index 000000000..e4ad91ae9 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/update_1.rdf @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <RDF:Description about="urn:mozilla:extension:test_bug470377_1@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>1</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>unknown@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/broken.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + +</RDF:RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/update_2.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/update_2.rdf new file mode 100644 index 000000000..10fcafd39 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/update_2.rdf @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <RDF:Description about="urn:mozilla:extension:test_bug470377_2@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>1</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/broken.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + +</RDF:RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/update_3.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/update_3.rdf new file mode 100644 index 000000000..684002462 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/update_3.rdf @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <RDF:Description about="urn:mozilla:extension:test_bug470377_3@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>1</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/broken.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + +</RDF:RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/update_4.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/update_4.rdf new file mode 100644 index 000000000..6e7116239 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/update_4.rdf @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <RDF:Description about="urn:mozilla:extension:test_bug470377_4@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>1</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/broken.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + +</RDF:RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/update_5.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/update_5.rdf new file mode 100644 index 000000000..c926af934 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug470377/update_5.rdf @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <RDF:Description about="urn:mozilla:extension:test_bug470377_5@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>1</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/broken.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + +</RDF:RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug514327_1.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug514327_1.xml new file mode 100644 index 000000000..c4cc2fe37 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug514327_1.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <pluginItems> + <pluginItem> + <match name="name" exp="^test_bug514327_1"/> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_bug514327_2"/> + <versionRange severity="0"/> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_bug514327_3"/> + <versionRange severity="0"/> + </pluginItem> + </pluginItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug514327_2.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug514327_2.xml new file mode 100644 index 000000000..cc0a0c69d --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug514327_2.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <pluginItems> + <pluginItem> + <match name="name" exp="Test Plug-in"/> + <versionRange severity="0"/> + </pluginItem> + </pluginItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug514327_3_empty.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug514327_3_empty.xml new file mode 100644 index 000000000..0261794f8 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug514327_3_empty.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug514327_3_outdated_1.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug514327_3_outdated_1.xml new file mode 100644 index 000000000..d651f8799 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug514327_3_outdated_1.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <pluginItems> + <pluginItem> + <match name="name" exp="test_bug514327_1"/> + </pluginItem> + <pluginItem> + <match name="name" exp="test_bug514327_outdated"/> + <versionRange severity="0"/> + </pluginItem> + </pluginItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug514327_3_outdated_2.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug514327_3_outdated_2.xml new file mode 100644 index 000000000..208444681 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug514327_3_outdated_2.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <pluginItems> + <pluginItem> + <match name="name" exp="test_bug514327_2"/> + </pluginItem> + <pluginItem> + <match name="name" exp="test_bug514327_outdated"/> + <versionRange severity="0"/> + </pluginItem> + </pluginItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug526598_1.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug526598_1.xpi Binary files differnew file mode 100644 index 000000000..2dbcc0b50 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug526598_1.xpi diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug526598_2.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug526598_2.xpi Binary files differnew file mode 100644 index 000000000..86fc6baaa --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug526598_2.xpi diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug541420.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug541420.xpi Binary files differnew file mode 100644 index 000000000..adb7be9ad --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug541420.xpi diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug542391.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug542391.rdf new file mode 100644 index 000000000..db82cf675 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug542391.rdf @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:extension:override1x2-1x3@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>1.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + +</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug554133.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug554133.xml new file mode 100644 index 000000000..736c10514 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug554133.xml @@ -0,0 +1,292 @@ +<?xml version="1.0" encoding="utf-8" ?> +<searchresults total_results="100"> + <addon> + <name>PASS</name> + <type id='1'>Extension</type> + <guid>test1@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://localhost:%PORT%/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test.xpi</install> + </addon> + + <addon> + <name>FAIL</name> + <type id='1'>Extension</type> + <guid>test2@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://localhost:%PORT%/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <summary>Should not return an incompatible add-on</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>2</min_version> + <max_version>2</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test.xpi</install> + </addon> + + <addon> + <name>PASS</name> + <type id='1'>Extension</type> + <guid>test3@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://localhost:%PORT%/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test.xpi</install> + </addon> + + <addon> + <name>FAIL</name> + <type id='1'>Extension</type> + <guid>test4@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://localhost:%PORT%/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <summary>Should not return an add-on for a different OS</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install os="UNKNOWN">http://localhost:%PORT%/test.xpi</install> + </addon> + + <addon> + <name>PASS</name> + <type id='1'>Extension</type> + <guid>test5@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://localhost:%PORT%/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test.xpi</install> + </addon> + + <addon> + <name>FAIL</name> + <type id='1'>Extension</type> + <guid>test5@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://localhost:%PORT%/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <summary>Should not include the same result twice</summary> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test.xpi</install> + </addon> + + <addon> + <name>PASS</name> + <type id='1'>Extension</type> + <guid>test6@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://localhost:%PORT%/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test.xpi</install> + </addon> + + <addon> + <name>PASS</name> + <type id='1'>Extension</type> + <guid>test7@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://localhost:%PORT%/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test.xpi</install> + </addon> + + <addon> + <name>PASS</name> + <type id='1'>Extension</type> + <guid>test8@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://localhost:%PORT%/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test.xpi</install> + </addon> + + <addon> + <name>PASS</name> + <type id='1'>Extension</type> + <guid>test9@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://localhost:%PORT%/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test.xpi</install> + </addon> + + <addon> + <name>PASS</name> + <type id='1'>Extension</type> + <guid>test10@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://localhost:%PORT%/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test.xpi</install> + </addon> + + <addon> + <name>PASS</name> + <type id='1'>Extension</type> + <guid>test11@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://localhost:%PORT%/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test.xpi</install> + </addon> + + <addon> + <name>PASS</name> + <type id='1'>Extension</type> + <guid>test12@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://localhost:%PORT%/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://localhost:%PORT%/test.xpi</install> + </addon> +</searchresults> + diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug619730.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug619730.xml new file mode 100644 index 000000000..f2511c0de --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug619730.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <gfxItems testattr="GFX"><gfxItem/><gfxItem/></gfxItems> + <testItems testattr="FOO"><testItem/><testItem/><testItem/></testItems> + <fooItems/> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug655254.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug655254.rdf new file mode 100644 index 000000000..9857dcb55 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug655254.rdf @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <RDF:Description about="urn:mozilla:extension:addon1@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>1</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + +</RDF:RDF> + diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_compatoverrides.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_compatoverrides.xml new file mode 100644 index 000000000..c0d67d033 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_compatoverrides.xml @@ -0,0 +1,228 @@ +<?xml version="1.0" encoding="utf-8" ?> +<searchresults total_results="9"> + <addon> + <name>Test addon 2</name> + <type id="1">Extension</type> + <guid>addon2@tests.mozilla.org</guid> + <version>1.0</version> + </addon> + + <addon> + <name>Test addon 3</name> + <type id="1">Extension</type> + <guid>addon3@tests.mozilla.org</guid> + <version>1.0</version> + </addon> + <addon_compatibility hosted="true"> + <name>Test addon 3</name> + <guid>addon3@tests.mozilla.org</guid> + <version_ranges> + <version_range type="incompatible"> + <min_version>0.9</min_version> + <max_version>1.0</max_version> + <compatible_applications> + <application> + <name>XPCShell</name> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>2</max_version> + </application> + </compatible_applications> + </version_range> + </version_ranges> + </addon_compatibility> + + <addon> + <name>Test addon 4</name> + <type id="1">Extension</type> + <guid>addon4@tests.mozilla.org</guid> + <version>1.0</version> + </addon> + <addon_compatibility hosted="true"> + <name>Test addon 4</name> + <guid>addon4@tests.mozilla.org</guid> + <version_ranges> + <version_range type="incompatible"> + <min_version>0.9</min_version> + <max_version>1.0</max_version> + <compatible_applications> + <application> + <name>XPCShell</name> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>2</max_version> + </application> + </compatible_applications> + </version_range> + </version_ranges> + </addon_compatibility> + + <addon> + <name>Test addon 5</name> + <type id="1">Extension</type> + <guid>addon5@tests.mozilla.org</guid> + <version>1.0</version> + </addon> + <addon_compatibility hosted="true"> + <name>Test addon 5</name> + <guid>addon5@tests.mozilla.org</guid> + <version_ranges> + <version_range type="incompatible"> + <min_version>0.9</min_version> + <max_version>1.0</max_version> + <compatible_applications> + <application> + <name>Unknown App</name> + <appID>unknown-app@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>2</max_version> + </application> + </compatible_applications> + </version_range> + </version_ranges> + </addon_compatibility> + + <addon> + <name>Test addon 6</name> + <type id="1">Extension</type> + <guid>addon6@tests.mozilla.org</guid> + <version>1.0</version> + </addon> + <addon_compatibility hosted="true"> + <name>Test addon 6</name> + <guid>addon6@tests.mozilla.org</guid> + <version_ranges> + <version_range type="incompatible"> + <min_version>0.5</min_version> + <max_version>0.9</max_version> + <compatible_applications> + <application> + <name>XPCShell</name> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>2</max_version> + </application> + </compatible_applications> + </version_range> + </version_ranges> + </addon_compatibility> + + <addon> + <name>Test addon 7</name> + <type id="1">Extension</type> + <guid>addon7@tests.mozilla.org</guid> + <version>1.0</version> + </addon> + <addon_compatibility hosted="true"> + <name>Test addon 7</name> + <guid>addon7@tests.mozilla.org</guid> + <version_ranges> + <version_range type="incompatible"> + <min_version>0.5</min_version> + <max_version>1.0</max_version> + <compatible_applications> + <application> + <name>XPCShell</name> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>0.1</min_version> + <max_version>0.9</max_version> + </application> + </compatible_applications> + </version_range> + </version_ranges> + </addon_compatibility> + + <addon> + <name>Test addon 8</name> + <type id="1">Extension</type> + <guid>addon8@tests.mozilla.org</guid> + <version>1.0</version> + </addon> + <addon_compatibility hosted="true"> + <name>Test addon 8</name> + <guid>addon8@tests.mozilla.org</guid> + <version_ranges> + <version_range type="incompatible"> + <min_version>6</min_version> + <max_version>6.2</max_version> + <compatible_applications> + <application> + <name>XPCShell</name> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>0.9</min_version> + <max_version>9</max_version> + </application> + </compatible_applications> + </version_range> + <version_range type="incompatible"> + <min_version>0.5</min_version> + <max_version>1.0</max_version> + <compatible_applications> + <application> + <name>XPCShell</name> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>0.1</min_version> + <max_version>9</max_version> + </application> + <application> + <name>Unknown app</name> + <appID>unknown-app@tests.mozilla.org</appID> + <min_version>0.1</min_version> + <max_version>9</max_version> + </application> + </compatible_applications> + </version_range> + <version_range type="incompatible"> + <min_version>0.1</min_version> + <max_version>0.2</max_version> + <compatible_applications> + <application> + <name>XPCShell</name> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>0.1</min_version> + <max_version>0.9</max_version> + </application> + </compatible_applications> + </version_range> + </version_ranges> + </addon_compatibility> + + <addon_compatibility hosted="false"> + <name>Test addon 9</name> + <guid>addon9@tests.mozilla.org</guid> + <version_ranges> + <version_range type="incompatible"> + <min_version>0.5</min_version> + <max_version>1.0</max_version> + <compatible_applications> + <application> + <name>XPCShell</name> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>2</max_version> + </application> + </compatible_applications> + </version_range> + </version_ranges> + </addon_compatibility> + + <addon_compatibility hosted="false"> + <name>Test addon 10</name> + <guid>addon10@tests.mozilla.org</guid> + <version_ranges> + <version_range type="compatible"> + <min_version>0.5</min_version> + <max_version>1.0</max_version> + <compatible_applications> + <application> + <name>XPCShell</name> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>2</max_version> + </application> + </compatible_applications> + </version_range> + </version_ranges> + </addon_compatibility> + +</searchresults> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_corrupt.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_corrupt.rdf new file mode 100644 index 000000000..f3341bdcf --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_corrupt.rdf @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:extension:addon3@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>1.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + + <Description about="urn:mozilla:extension:addon4@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>1.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + +</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_dictionary.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_dictionary.rdf new file mode 100644 index 000000000..364b3bba1 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_dictionary.rdf @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:extension:ab-CD@dictionaries.addons.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>2.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/test_dictionary_3.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + + <Description about="urn:mozilla:extension:ef@dictionaries.addons.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>2.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/test_dictionary_4.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + + <Description about="urn:mozilla:extension:gh@dictionaries.addons.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>2.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/test_dictionary_5.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_distribution2_2/bootstrap.js b/toolkit/mozapps/extensions/test/xpcshell/data/test_distribution2_2/bootstrap.js new file mode 100644 index 000000000..01682d3b7 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_distribution2_2/bootstrap.js @@ -0,0 +1,21 @@ +Components.utils.import("resource://gre/modules/Services.jsm"); + +function install(data, reason) { + Services.prefs.setIntPref("bootstraptest.installed_version", 2); + Services.prefs.setIntPref("bootstraptest.install_reason", reason); +} + +function startup(data, reason) { + Services.prefs.setIntPref("bootstraptest.active_version", 2); + Services.prefs.setIntPref("bootstraptest.startup_reason", reason); +} + +function shutdown(data, reason) { + Services.prefs.setIntPref("bootstraptest.active_version", 0); + Services.prefs.setIntPref("bootstraptest.shutdown_reason", reason); +} + +function uninstall(data, reason) { + Services.prefs.setIntPref("bootstraptest.installed_version", 0); + Services.prefs.setIntPref("bootstraptest.uninstall_reason", reason); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_distribution2_2/install.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_distribution2_2/install.rdf new file mode 100644 index 000000000..ebe547ccc --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_distribution2_2/install.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>addon2@tests.mozilla.org</em:id> + <em:version>2.0</em:version> + + <!-- Front End MetaData --> + <em:name>Distributed add-ons test</em:name> + <em:bootstrap>true</em:bootstrap> + + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>5</em:maxVersion> + </Description> + </em:targetApplication> + + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_distribution2_2/subdir/dummy.txt b/toolkit/mozapps/extensions/test/xpcshell/data/test_distribution2_2/subdir/dummy.txt new file mode 100644 index 000000000..051aef85a --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_distribution2_2/subdir/dummy.txt @@ -0,0 +1 @@ +Test of a file in a sub directory
\ No newline at end of file diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_distribution2_2/subdir/subdir2/dummy2.txt b/toolkit/mozapps/extensions/test/xpcshell/data/test_distribution2_2/subdir/subdir2/dummy2.txt new file mode 100644 index 000000000..9eddc4493 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_distribution2_2/subdir/subdir2/dummy2.txt @@ -0,0 +1 @@ +Nested dummy file
\ No newline at end of file diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist.xml new file mode 100644 index 000000000..639f2d20f --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist.xml @@ -0,0 +1,154 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <gfxItems> + <gfxBlacklistEntry> + <os>WINNT 6.1</os> + <vendor>0xabcd</vendor> + <devices> + <device>0x2783</device> + <device>0x1234</device> + <device>0x2782</device> + </devices> + <feature> DIRECT2D </feature> + <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> + <driverVersion> 8.52.322.2202 </driverVersion> + <driverVersionComparator> LESS_THAN </driverVersionComparator> + </gfxBlacklistEntry> + <gfxBlacklistEntry> + <os>WINNT 6.0</os> + <vendor>0xdcba</vendor> + <devices> + <device>0x2783</device> + <device>0x1234</device> + <device>0x2782</device> + </devices> + <feature> DIRECT3D_9_LAYERS </feature> + <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> + <driverVersion> 8.52.322.2202 </driverVersion> + <driverVersionComparator> LESS_THAN </driverVersionComparator> + </gfxBlacklistEntry> + <gfxBlacklistEntry> + <os>WINNT 6.1</os> + <vendor>0xabab</vendor> + <devices> + <device>0x2783</device> + <device>0x1234</device> + <device>0x2782</device> + </devices> + <feature> DIRECT2D </feature> + <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> + <driverVersion> 8.52.322.2202 </driverVersion> + <driverVersionComparator> GREATER_THAN_OR_EQUAL </driverVersionComparator> + </gfxBlacklistEntry> + <gfxBlacklistEntry> + <os>WINNT 6.1</os> + <vendor>0xdcdc</vendor> + <devices> + <device>0x2783</device> + <device>0x1234</device> + <device>0x2782</device> + </devices> + <feature> DIRECT2D </feature> + <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> + <driverVersion> 8.52.322.1111 </driverVersion> + <driverVersionComparator> EQUAL </driverVersionComparator> + </gfxBlacklistEntry> + <gfxBlacklistEntry> + <os>Darwin 9</os> + <vendor>0xabcd</vendor> + <devices> + <device>0x2783</device> + <device>0x1234</device> + <device>0x2782</device> + </devices> + <feature> DIRECT2D </feature> + <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> + </gfxBlacklistEntry> + <gfxBlacklistEntry> + <os>Linux</os> + <vendor>0xabcd</vendor> + <devices> + <device>0x2783</device> + <device>0x1234</device> + <device>0x2782</device> + </devices> + <feature> DIRECT2D </feature> + <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> + </gfxBlacklistEntry> + <gfxBlacklistEntry> + <os>Android</os> + <vendor>abcd</vendor> + <devices> + <device>wxyz</device> + <device>asdf</device> + <device>erty</device> + </devices> + <feature> DIRECT2D </feature> + <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> + <driverVersion> 5 </driverVersion> + <driverVersionComparator> LESS_THAN_OR_EQUAL </driverVersionComparator> + </gfxBlacklistEntry> + <gfxBlacklistEntry> + <os>Android</os> + <vendor>dcdc</vendor> + <devices> + <device>uiop</device> + <device>vbnm</device> + <device>hjkl</device> + </devices> + <feature> DIRECT2D </feature> + <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> + <driverVersion> 5 </driverVersion> + <driverVersionComparator> EQUAL </driverVersionComparator> + </gfxBlacklistEntry> + <gfxBlacklistEntry> + <os>Android</os> + <vendor>abab</vendor> + <devices> + <device>ghjk</device> + <device>cvbn</device> + </devices> + <feature> DIRECT2D </feature> + <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> + <driverVersion> 7 </driverVersion> + <driverVersionComparator> GREATER_THAN_OR_EQUAL </driverVersionComparator> + </gfxBlacklistEntry> + <gfxBlacklistEntry> + <os>WINNT 6.1</os> + <vendor>0xabcd</vendor> + <devices> + <device>0x6666</device> + </devices> + <feature> DIRECT2D </feature> + <featureStatus> BLOCKED_DEVICE </featureStatus> + </gfxBlacklistEntry> + <gfxBlacklistEntry> + <os>Darwin 9</os> + <vendor>0xabcd</vendor> + <devices> + <device>0x6666</device> + </devices> + <feature> DIRECT2D </feature> + <featureStatus> BLOCKED_DEVICE </featureStatus> + </gfxBlacklistEntry> + <gfxBlacklistEntry> + <os>Linux</os> + <vendor>0xabcd</vendor> + <devices> + <device>0x6666</device> + </devices> + <feature> DIRECT2D </feature> + <featureStatus> BLOCKED_DEVICE </featureStatus> + </gfxBlacklistEntry> + <gfxBlacklistEntry> + <os>Android</os> + <vendor>0xabcd</vendor> + <devices> + <device>0x6666</device> + </devices> + <feature> DIRECT2D </feature> + <featureStatus> BLOCKED_DEVICE </featureStatus> + </gfxBlacklistEntry> + </gfxItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist2.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist2.xml new file mode 100644 index 000000000..0ad8f6819 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist2.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <gfxItems> + <gfxBlacklistEntry> + <os>WINNT 6.1</os> + <vendor>0xabcd</vendor> + <devices> + <device>0x2783</device> + <device>0x2782</device> + </devices> + <feature> DIRECT2D </feature> + <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> + <driverVersion> 8.52.322.2202 </driverVersion> + <driverVersionComparator> LESS_THAN </driverVersionComparator> + </gfxBlacklistEntry> + <gfxBlacklistEntry> + <os>WINNT 6.0</os> + <vendor>0xdcba</vendor> + <devices> + <device>0x2783</device> + <device>0x1234</device> + <device>0x2782</device> + </devices> + <feature> DIRECT3D_9_LAYERS </feature> + <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> + <driverVersion> 8.52.322.2202 </driverVersion> + <driverVersionComparator> LESS_THAN </driverVersionComparator> + </gfxBlacklistEntry> + </gfxItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist_AllOS.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist_AllOS.xml new file mode 100644 index 000000000..22af6f712 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist_AllOS.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <gfxItems> + <gfxBlacklistEntry> + <os>All</os> + <vendor>0xabcd</vendor> + <devices> + <device>0x2783</device> + <device>0x1234</device> + <device>0x2782</device> + </devices> + <feature> DIRECT2D </feature> + <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> + <driverVersion> 8.52.322.2202 </driverVersion> + <driverVersionComparator> LESS_THAN </driverVersionComparator> + </gfxBlacklistEntry> + <gfxBlacklistEntry> + <os>WINNT 6.0</os> + <vendor>0xdcba</vendor> + <devices> + <device>0x2783</device> + <device>0x1234</device> + <device>0x2782</device> + </devices> + <feature> DIRECT3D_9_LAYERS </feature> + <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> + <driverVersion> 8.52.322.2202 </driverVersion> + <driverVersionComparator> LESS_THAN </driverVersionComparator> + </gfxBlacklistEntry> + </gfxItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist_OSVersion.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist_OSVersion.xml new file mode 100644 index 000000000..463207d14 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist_OSVersion.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <gfxItems> + <gfxBlacklistEntry> + <os>WINNT 6.2</os> + <vendor>0xabcd</vendor> + <devices> + <device>0x2783</device> + <device>0x1234</device> + <device>0x2782</device> + </devices> + <feature> DIRECT2D </feature> + <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> + <driverVersion> 8.52.322.2202 </driverVersion> + <driverVersionComparator> LESS_THAN </driverVersionComparator> + </gfxBlacklistEntry> + <gfxBlacklistEntry> + <os>Darwin 12</os> + <vendor>0xabcd</vendor> + <devices> + <device>0x2783</device> + <device>0x1234</device> + <device>0x2782</device> + </devices> + <feature> OPENGL_LAYERS </feature> + <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus> + <driverVersion> 8.52.322.2202 </driverVersion> + <driverVersionComparator> LESS_THAN </driverVersionComparator> + </gfxBlacklistEntry> + </gfxItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_install.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_install.rdf new file mode 100644 index 000000000..fe82334fa --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_install.rdf @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:extension:addon3@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>1.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + + <Description about="urn:mozilla:extension:addon4@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>1.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + + <Description about="urn:mozilla:extension:addon7@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>5.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + +</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_install.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_install.xml new file mode 100644 index 000000000..5f0aab75f --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_install.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="utf-8" ?> +<searchresults total_results="1"> + <addon> + <name>Real Test 2</name> + <type id='1'>Extension</type> + <guid>addon2@tests.mozilla.org</guid> + <version>1.0</version> + <authors> + <author> + <name>Test Creator</name> + <link>http://example.com/creator.html</link> + </author> + </authors> + <status id='4'>Public</status> + <summary>Repository summary</summary> + <description>Repository description</description> + <compatible_applications> + <application> + <name>Firefox</name> + <appID>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + <application> + <name>SeaMonkey</name> + <appID>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</appID> + <min_version>0</min_version> + <max_version>*</max_version> + </application> + </compatible_applications> + <compatible_os>ALL</compatible_os> + <install size="2">http://example.com/browser/toolkit/mozapps/extensions/test/browser/addons/browser_install1_2.xpi</install> + </addon> + + <addon_compatibility hosted="false"> + <guid>addon6@tests.mozilla.org</guid> + <name>Addon Test 6</name> + <version_ranges> + <version_range type="incompatible"> + <min_version>1.0</min_version> + <max_version>1.0</max_version> + <compatible_applications> + <application> + <name>XPCShell</name> + <min_version>1.0</min_version> + <max_version>1.0</max_version> + <appID>xpcshell@tests.mozilla.org</appID> + </application> + </compatible_applications> + </version_range> + </version_ranges> + </addon_compatibility> +</searchresults> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_migrate.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_migrate.rdf new file mode 100644 index 000000000..d1dc992d5 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_migrate.rdf @@ -0,0 +1,125 @@ +<?xml version="1.0"?> + +<!-- This is a copy of extensions.rdf from Firefox 3.5 including four + test extensions. Addon1 was user enabled, addon2 was user disabled, addon3 + was pending user disable at the next restart and addon4 was pending user + enable at the next restart. Additionally addon1 and 2 have had + compatibility updates applies to make them compatible with the app and + toolkit respectively, addon3 and 4 have not. addon5 is disabled however + at the same time as the migration a new version should be detected. addon6 + is pending install and needs a compatibility update to be compatible. + It also contains two themes in the profile --> + +<RDF:RDF xmlns:NS1="http://www.mozilla.org/2004/em-rdf#" + xmlns:NC="http://home.netscape.com/NC-rdf#" + xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> + <RDF:Description RDF:about="rdf:#$w8dNC3" + NS1:id="xpcshell@tests.mozilla.org" + NS1:minVersion="1" + NS1:maxVersion="1" /> + <RDF:Description RDF:about="rdf:#$w8dNC4" + NS1:id="xpcshell@tests.mozilla.org" + NS1:minVersion="1" + NS1:maxVersion="2" /> + <RDF:Description RDF:about="rdf:#$w8dNC5" + NS1:id="xpcshell@tests.mozilla.org" + NS1:minVersion="1" + NS1:maxVersion="2" /> + <RDF:Description RDF:about="rdf:#$w8dNC6" + NS1:id="xpcshell@tests.mozilla.org" + NS1:minVersion="1" + NS1:maxVersion="2" /> + <RDF:Description RDF:about="rdf:#$w8dNC2" + NS1:id="toolkit@mozilla.org" + NS1:minVersion="1" + NS1:maxVersion="1" /> + <RDF:Description RDF:about="rdf:#$w8dNC1" + NS1:id="toolkit@mozilla.org" + NS1:minVersion="1" + NS1:maxVersion="2" /> + <RDF:Description RDF:about="rdf:#$w8dNC7" + NS1:id="toolkit@mozilla.org" + NS1:minVersion="1" + NS1:maxVersion="2" /> + <RDF:Description RDF:about="rdf:#$oadNC1" + NS1:id="xpcshell@tests.mozilla.org" + NS1:minVersion="1" + NS1:maxVersion="2" /> + <RDF:Description RDF:about="rdf:#$TpnM4" + NS1:id="xpcshell@tests.mozilla.org" + NS1:updatedMinVersion="1" + NS1:updatedMaxVersion="2" /> + <RDF:Description RDF:about="urn:mozilla:item:addon1@tests.mozilla.org" + NS1:installLocation="app-profile" + NS1:version="1.0" + NS1:name="Test 1"> + <NS1:type NC:parseType="Integer">2</NS1:type> + <NS1:targetApplication RDF:resource="rdf:#$oadNC1"/> + </RDF:Description> + <RDF:Description RDF:about="urn:mozilla:item:addon2@tests.mozilla.org" + NS1:installLocation="app-profile" + NS1:version="2.0" + NS1:name="Test 2" + NS1:userDisabled="true"> + <NS1:type NC:parseType="Integer">2</NS1:type> + <NS1:targetApplication RDF:resource="rdf:#$w8dNC1"/> + </RDF:Description> + <RDF:Description RDF:about="urn:mozilla:item:addon3@tests.mozilla.org" + NS1:installLocation="app-profile" + NS1:version="2.0" + NS1:name="Test 3" + NS1:userDisabled="needs-disable"> + <NS1:type NC:parseType="Integer">2</NS1:type> + <NS1:targetApplication RDF:resource="rdf:#$w8dNC3"/> + </RDF:Description> + <RDF:Description RDF:about="urn:mozilla:item:addon4@tests.mozilla.org" + NS1:installLocation="app-profile" + NS1:version="2.0" + NS1:name="Test 4" + NS1:userDisabled="needs-enable"> + <NS1:type NC:parseType="Integer">2</NS1:type> + <NS1:targetApplication RDF:resource="rdf:#$w8dNC2"/> + </RDF:Description> + <RDF:Description RDF:about="urn:mozilla:item:addon5@tests.mozilla.org" + NS1:installLocation="app-profile" + NS1:version="1.0" + NS1:name="Test 5" + NS1:userDisabled="true"> + <NS1:type NC:parseType="Integer">2</NS1:type> + <NS1:targetApplication RDF:resource="rdf:#$w8dNC7"/> + </RDF:Description> + <RDF:Description RDF:about="urn:mozilla:item:addon6@tests.mozilla.org" + NS1:name="Test 6" + NS1:version="1.0" + NS1:newVersion="1.0" + NS1:installLocation="app-profile"> + <NS1:type NC:parseType="Integer">2</NS1:type> + <NS1:targetApplication RDF:resource="rdf:#$TpnM4"/> + </RDF:Description> + <RDF:Description RDF:about="urn:mozilla:item:theme1@tests.mozilla.org" + NS1:installLocation="app-profile" + NS1:version="1.0" + NS1:name="Theme 2" + NS1:internalName="theme1/1.0"> + <NS1:type NC:parseType="Integer">4</NS1:type> + <NS1:targetApplication RDF:resource="rdf:#$w8dNC5"/> + </RDF:Description> + <RDF:Description RDF:about="urn:mozilla:item:theme2@tests.mozilla.org" + NS1:installLocation="app-profile" + NS1:version="2.0" + NS1:name="Theme 2" + NS1:internalName="theme2/1.0"> + <NS1:type NC:parseType="Integer">4</NS1:type> + <NS1:targetApplication RDF:resource="rdf:#$w8dNC6"/> + </RDF:Description> + <RDF:Seq RDF:about="urn:mozilla:item:root"> + <RDF:li RDF:resource="urn:mozilla:item:addon1@tests.mozilla.org"/> + <RDF:li RDF:resource="urn:mozilla:item:addon2@tests.mozilla.org"/> + <RDF:li RDF:resource="urn:mozilla:item:addon3@tests.mozilla.org"/> + <RDF:li RDF:resource="urn:mozilla:item:addon4@tests.mozilla.org"/> + <RDF:li RDF:resource="urn:mozilla:item:addon5@tests.mozilla.org"/> + <RDF:li RDF:resource="urn:mozilla:item:addon6@tests.mozilla.org"/> + <RDF:li RDF:resource="urn:mozilla:item:theme1@tests.mozilla.org"/> + <RDF:li RDF:resource="urn:mozilla:item:theme2@tests.mozilla.org"/> + </RDF:Seq> +</RDF:RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_migrate4.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_migrate4.rdf new file mode 100644 index 000000000..a3bf4f8ae --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_migrate4.rdf @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:extension:addon5@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>2.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + + <Description about="urn:mozilla:extension:addon6@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>2.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>2</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/test_migrate4_6.xpi</em:updateLink> + <em:updateInfoURL>http://example.com/updateInfo.xhtml</em:updateInfoURL> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + +</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_overrideblocklist/ancient.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_overrideblocklist/ancient.xml new file mode 100644 index 000000000..699257f87 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_overrideblocklist/ancient.xml @@ -0,0 +1,8 @@ +<?xml version="1.0"?> +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <emItems> + <emItem blockID="i454" id="ancient@tests.mozilla.org"> + <versionRange minVersion="0" maxVersion="*" severity="3"/> + </emItem> + </emItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_overrideblocklist/new.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_overrideblocklist/new.xml new file mode 100644 index 000000000..8cbfb5d6a --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_overrideblocklist/new.xml @@ -0,0 +1,8 @@ +<?xml version="1.0"?> +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1396046918000"> + <emItems> + <emItem blockID="i454" id="new@tests.mozilla.org"> + <versionRange minVersion="0" maxVersion="*" severity="3"/> + </emItem> + </emItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_overrideblocklist/old.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_overrideblocklist/old.xml new file mode 100644 index 000000000..75bd6e934 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_overrideblocklist/old.xml @@ -0,0 +1,8 @@ +<?xml version="1.0"?> +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1296046918000"> + <emItems> + <emItem blockID="i454" id="old@tests.mozilla.org"> + <versionRange minVersion="0" maxVersion="*" severity="3"/> + </emItem> + </emItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_pluginBlocklistCtp.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_pluginBlocklistCtp.xml new file mode 100644 index 000000000..d3564aebd --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_pluginBlocklistCtp.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <pluginItems> + <pluginItem> + <match name="name" exp="^test_plugin_0"/> + <versionRange minVersion="0" maxVersion="*" severity="0" vulnerabilitystatus="0"/> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_plugin_1"/> + <versionRange minVersion="0" maxVersion="*" severity="0" vulnerabilitystatus="1"/> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_plugin_2"/> + <versionRange minVersion="0" maxVersion="*" severity="0" vulnerabilitystatus="2"/> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_plugin_3"/> + <versionRange minVersion="0" maxVersion="*" vulnerabilitystatus="2"/> + </pluginItem> + <pluginItem> + <match name="name" exp="^test_plugin_4"/> + <versionRange minVersion="0" maxVersion="*" severity="1" vulnerabilitystatus="2"/> + </pluginItem> + </pluginItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_pluginBlocklistCtpUndo.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_pluginBlocklistCtpUndo.xml new file mode 100644 index 000000000..7cd8496b3 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_pluginBlocklistCtpUndo.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist"> + <pluginItems> + <pluginItem> + <match name="name" exp="^Test Plug-in"/> + <versionRange minVersion="0" maxVersion="*" severity="0" vulnerabilitystatus="2"/> + </pluginItem> + </pluginItems> +</blocklist> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_sourceURI.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_sourceURI.xml new file mode 100644 index 000000000..949288e3f --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_sourceURI.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8" ?> +<searchresults total_results="1"> + <!-- Passes all requirements --> + <addon> + <name>Test</name> + <type id="1">Extension</type> + <guid>addon@tests.mozilla.org</guid> + <version>1</version> + <compatible_applications> + <application> + <appID>xpcshell@tests.mozilla.org</appID> + <min_version>1</min_version> + <max_version>1</max_version> + </application> + </compatible_applications> + <install>http://www.example.com/testaddon.xpi</install> + </addon> +</searchresults> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_update.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_update.rdf new file mode 100644 index 000000000..4d4640f60 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_update.rdf @@ -0,0 +1,270 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:extension:addon1@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>1.0</em:version> + <!-- Shouldn't fire onCompatibilityUpdateAvailable since this + information is already in the install.rdf --> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Should be ignored as it is not for the present version of the + application --> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>2</em:minVersion> + <em:maxVersion>2</em:maxVersion> + </Description> + </em:targetApplication> + </Description> + </li> + + <li> + <Description> + <em:version>2.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/test_update.xpi</em:updateLink> + <em:updateInfoURL>http://example.com/updateInfo.xhtml</em:updateInfoURL> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + + <Description about="urn:mozilla:extension:addon2@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>1.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + + <Description about="urn:mozilla:extension:addon3@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>1.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>3</em:minVersion> + <em:maxVersion>3</em:maxVersion> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + + <Description about="urn:mozilla:extension:addon4@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>5.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>0</em:maxVersion> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + + <Description about="urn:mozilla:extension:addon7@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>1.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>0</em:minVersion> + <em:maxVersion>1</em:maxVersion> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + + <Description about="urn:mozilla:extension:addon8@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>2.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/test_update8.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + + <Description about="urn:mozilla:extension:addon9@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>2.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/test_update9_2.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + <!-- Incompatible when strict compatibility is enabled --> + <li> + <Description> + <em:version>3.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>0.9</em:minVersion> + <em:maxVersion>0.9</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/test_update9_3.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + <!-- Incompatible due to compatibility override --> + <li> + <Description> + <em:version>4.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>0.9</em:minVersion> + <em:maxVersion>0.9</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/test_update9_4.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + <!-- Addon for future version of app --> + <li> + <Description> + <em:version>5.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>5</em:minVersion> + <em:maxVersion>6</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/test_update9_5.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + + <Description about="urn:mozilla:extension:addon10@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>1.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>0.1</em:minVersion> + <em:maxVersion>0.4</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/test_update10.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + + <Description about="urn:mozilla:extension:addon11@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>2.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>0.1</em:minVersion> + <em:maxVersion>0.2</em:maxVersion> + <em:strictCompatibility>true</em:strictCompatibility> + <em:updateLink>http://localhost:%PORT%/addons/test_update11.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + + <Description about="urn:mozilla:item:addon12@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>2.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>http://localhost:%PORT%/addons/test_update12.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_update.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_update.xml new file mode 100644 index 000000000..62928815b --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_update.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8" ?> +<searchresults total_results="11"> + <addon> + <name>Test Addon 9</name> + <type id="1">Extension</type> + <guid>addon9@tests.mozilla.org</guid> + </addon> + <addon_compatibility hosted="true"> + <guid>addon9@tests.mozilla.org</guid> + <name>Test Addon 9</name> + <version_ranges> + <version_range type="incompatible"> + <min_version>4</min_version> + <max_version>4</max_version> + <compatible_applications> + <application> + <name>XPCShell</name> + <min_version>1</min_version> + <max_version>1</max_version> + <appID>xpcshell@tests.mozilla.org</appID> + </application> + </compatible_applications> + </version_range> + </version_ranges> + </addon_compatibility> +</searchresults> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_updatecheck.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_updatecheck.rdf new file mode 100644 index 000000000..93c82886a --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_updatecheck.rdf @@ -0,0 +1,419 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:extension:updatecheck1@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>1.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>https://localhost:4444/addons/test1.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + <!-- This update is incompatible and so should not be considered a valid + update --> + <li> + <Description> + <em:version>2.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>2</em:minVersion> + <em:maxVersion>2</em:maxVersion> + <em:updateLink>https://localhost:4444/addons/test2.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + <li> + <Description> + <em:version>3.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>https://localhost:4444/addons/test3.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + <li> + <Description> + <em:version>2.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + <em:updateLink>https://localhost:4444/addons/test2.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + <!-- This update is incompatible and so should not be considered a valid + update --> + <li> + <Description> + <em:version>4.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>2</em:minVersion> + <em:maxVersion>2</em:maxVersion> + <em:updateLink>https://localhost:4444/addons/test4.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + + <!-- An update with no signature which will fail if retrieved with an update + key. The updateLink will also be ignored since it is not secure and there + is no updateHash. --> + <RDF:Description about="urn:mozilla:extension:test_bug378216_5@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>2.0</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>http://localhost:4444/broken.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + </RDF:Description> + + <!-- An update with a broken signature which will fail if retrieved with an + update key. The updateLink will also be ignored since it is not secure + and there is no updateHash. --> + <RDF:Description about="urn:mozilla:extension:test_bug378216_7@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>2.0</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + <em:updateLink>http://localhost:4444/broken.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + <em:signature>MIGTMA0GCSqGSIb3DQEBBQUAA4GBAMO1O2gwSCCth1GwYMgscfaNakpN40PJfOWt + ub2HVdg8+OXMciF8d/9eVWm8eH/IxuxyZlmRZTs3O5tv9eWAY5uBCtqDf1WgTsGk + jrgZow1fITkZI7w0//C8eKdMLAtGueGfNs2IlTd5P/0KH/hf1rPc1wUqEqKCd4+L + BcVq13ad</em:signature> + </RDF:Description> + + <!-- An update with a valid signature. The updateLink will be ignored since it + is not secure and there is no updateHash. --> + <RDF:Description about="urn:mozilla:extension:test_bug378216_8@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>2.0</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>http://localhost:4444/broken.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + <em:signature>MIGTMA0GCSqGSIb3DQEBBQUAA4GBAMH/33P/bn148mVkAB8i5X8c4LhY52E+MPUT + yKHGpowZnRLgL2O0dfpm+rljOBfKi51322PFrsc6VIFml6x4Lrb5foxSyB0Vs9pb + SEDFWUKquOQvceQ9iEx5Pe0VzrmUZgcQxd8ksSunWL4wJaBZ/evE5amFC6sw3pv/ + fjt8p3GN</em:signature> + </RDF:Description> + + <!-- An update with a valid signature. The updateLink will used since there is + an updateHash to verify it. --> + <RDF:Description about="urn:mozilla:extension:test_bug378216_9@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>2.0</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>http://localhost:4444/broken.xpi</em:updateLink> + <em:updateHash>sha1:78fc1d2887eda35b4ad2e3a0b60120ca271ce6e6</em:updateHash> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + <em:signature>MIGTMA0GCSqGSIb3DQEBBQUAA4GBAJ5Dv3Zd7/j5dLchCw9iO/cxPq8oOhOYD2M+ + jUKvmHCyTBRIEaJrE4N7yVbRYk++ERIfyVepLivsVi4pBmF7JTdw0NaKUA0LiOoT + mRL8I7s5NPjCiiNcdqbncWyiZwIj1w1nkbWGTlH/gEjRW/LbvT4JAuec8yNFDa4S + X8mOMf7k</em:signature> + </RDF:Description> + + <!-- An update with a valid signature. The updateLink will used since it is + a secure URL. --> + <RDF:Description about="urn:mozilla:extension:test_bug378216_10@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>2.0</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>https://localhost:4444/broken.xpi</em:updateLink> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + <em:signature>MIGTMA0GCSqGSIb3DQEBBQUAA4GBAGvf7XqqoTl5WofrNq55E7W+UttOEDXLB3Oi + XDiXe0i6njlozilseaUo1hgfQhhzN9gkyetP5tGBVcLRrVyliKpJmD6ABCVGW1lS + qS+SEw7gDHyHkvwKMyWKedpRGChqLYnnf+Y+CX3MWLZLkwPXMKdTYgN3Rx0lEnJk + 37LSEMKE</em:signature> + </RDF:Description> + + <!-- An update with a valid signature. The updateLink will used since it is + a secure URL. --> + <RDF:Description about="urn:mozilla:extension:test_bug378216_11@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>2.0</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>https://localhost:4444/broken.xpi</em:updateLink> + <em:updateHash>sha1:78fc1d2887eda35b4ad2e3a0b60120ca271ce6e6</em:updateHash> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + <em:signature>MIGTMA0GCSqGSIb3DQEBBQUAA4GBACMX/KReOGSJ8CMGRroH1v3Gjv/Qs/pqH+Ow + o+hCKWLUKx7hpJgVJkXXdAHW0U88NXlp1S2H0WqA7I/CdmNXJSPzzV/J4z1dZgXh + JbW6mqNb0pj6nIe7g8OLzSxDgBmO4DUP5DAmnmqciJLWQzN7OdbcwrWz6xPN5kZF + A90eF5zy</em:signature> + </RDF:Description> + + <!-- An update with a valid signature. The updateLink will used since the + updateHash verifying it is not strong enough. --> + <RDF:Description about="urn:mozilla:extension:test_bug378216_12@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>2.0</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>http://localhost:4444/broken.xpi</em:updateLink> + <em:updateHash>md2:78fc1d2887eda35b4ad2e3a0b60120ca271ce6e6</em:updateHash> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + <em:signature>MIGTMA0GCSqGSIb3DQEBBQUAA4GBAJRfcFvHIWxVyycCw8IjNmEhabc2uqA1zQwp + 5oKh3Y23hwIsQ6xy68Wtjte1NEYFRt5fWkbMXj9YQj6LpVbzBKiGATcrq6MycZKK + o5N22cWbrKKRweJezTyN4eLfQg21pG7r8mdfS0bIA28ZVFtQOmORejoUesEouCGy + eKYk9nS2</em:signature> + </RDF:Description> + + <!-- An update with a valid signature. The updateLink will used since it is + a secure URL. --> + <RDF:Description about="urn:mozilla:extension:test_bug378216_13@tests.mozilla.org"> + <em:updates> + <RDF:Seq> + <RDF:li> + <RDF:Description> + <em:version>2.0</em:version> + <em:targetApplication> + <RDF:Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>https://localhost:4444/broken.xpi</em:updateLink> + <em:updateHash>md2:78fc1d2887eda35b4ad2e3a0b60120ca271ce6e6</em:updateHash> + </RDF:Description> + </em:targetApplication> + </RDF:Description> + </RDF:li> + </RDF:Seq> + </em:updates> + <em:signature>MIGTMA0GCSqGSIb3DQEBBQUAA4GBALQKwzLFr/VOw3gJvv/LCh3/PWDd9FqmFnX+ + hJjBmCaUDtG7CXn1i0h8ed8IeRHpLLT7FCzVwU3bH9BUjdm8wc3ObtlNbd8go01a + CoXz50r3rYPcYz4WS+7/+lvrUqsuWd9Wj+q0NeCPiNaaro6/AolE2Qf5JFRL3lxY + lsKWAnVO</em:signature> + </RDF:Description> + + <!-- There should be no information present for test_bug378216_14 --> + + <!-- Invalid update RDF --> + <RDF:Description about="urn:mozilla:extension:test_bug378216_15@tests.mozilla.org"> + <em:updates>Foo</em:updates> + </RDF:Description> + + <!-- Various updates available - one is not compatible, but compatibility checking is disabled --> + <Description about="urn:mozilla:extension:ignore-compat@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>1.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>0.1</em:minVersion> + <em:maxVersion>0.2</em:maxVersion> + <em:updateLink>https://localhost:4444/addons/test1.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + <li> + <Description> + <em:version>2.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>0.5</em:minVersion> + <em:maxVersion>0.6</em:maxVersion> + <em:updateLink>https://localhost:4444/addons/test2.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + <!-- Update for future app versions - should never be compatible --> + <li> + <Description> + <em:version>3.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>2</em:minVersion> + <em:maxVersion>3</em:maxVersion> + <em:updateLink>https://localhost:4444/addons/test3.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + + <!-- Various updates available - one is not compatible, but compatibility checking is disabled --> + <Description about="urn:mozilla:extension:compat-override@tests.mozilla.org"> + <em:updates> + <Seq> + <!-- Has compatibility override, but it doesn't match this app version --> + <li> + <Description> + <em:version>1.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>0.1</em:minVersion> + <em:maxVersion>0.2</em:maxVersion> + <em:updateLink>https://localhost:4444/addons/test1.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + <!-- Has compatibility override, so is incompaible --> + <li> + <Description> + <em:version>2.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>0.5</em:minVersion> + <em:maxVersion>0.6</em:maxVersion> + <em:updateLink>https://localhost:4444/addons/test2.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + <!-- Update for future app versions - should never be compatible --> + <li> + <Description> + <em:version>3.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>2</em:minVersion> + <em:maxVersion>3</em:maxVersion> + <em:updateLink>https://localhost:4444/addons/test3.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + + <!-- Opt-in to strict compatibility checking --> + <Description about="urn:mozilla:extension:compat-strict-optin@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>1.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>0.1</em:minVersion> + <em:maxVersion>0.2</em:maxVersion> + <em:strictCompatibility>true</em:strictCompatibility> + <em:updateLink>https://localhost:4444/addons/test1.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_updatecompatmode_ignore.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_updatecompatmode_ignore.rdf new file mode 100644 index 000000000..ec6e88ec4 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_updatecompatmode_ignore.rdf @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:extension:compatmode-ignore@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>2.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + <em:updateLink>https://localhost:%PORT%/addons/test1.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_updatecompatmode_normal.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_updatecompatmode_normal.rdf new file mode 100644 index 000000000..2ef88860e --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_updatecompatmode_normal.rdf @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:extension:compatmode-normal@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>2.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + <em:updateLink>https://localhost:%PORT%/addons/test1.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_updatecompatmode_strict.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_updatecompatmode_strict.rdf new file mode 100644 index 000000000..2f72c181d --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_updatecompatmode_strict.rdf @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:extension:compatmode-strict@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>2.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>2</em:maxVersion> + <em:updateLink>https://localhost:%PORT%/addons/test1.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> +</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_updateid.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_updateid.rdf new file mode 100644 index 000000000..d59df9736 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_updateid.rdf @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:extension:addon1@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>2.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>http://localhost:4444/addons/test_updateid2_2.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + + <Description about="urn:mozilla:extension:addon2@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>3.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>http://localhost:4444/addons/test_updateid3_3.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + + <Description about="urn:mozilla:extension:addon3@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>4.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>http://localhost:4444/addons/test_updateid4_4.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + + <Description about="urn:mozilla:extension:addon4@tests.mozilla.org"> + <em:updates> + <Seq> + <li> + <Description> + <em:version>5.0</em:version> + <em:targetApplication> + <Description> + <em:id>xpcshell@tests.mozilla.org</em:id> + <em:minVersion>1</em:minVersion> + <em:maxVersion>1</em:maxVersion> + <em:updateLink>http://localhost:4444/addons/test_updateid2_5.xpi</em:updateLink> + </Description> + </em:targetApplication> + </Description> + </li> + </Seq> + </em:updates> + </Description> + +</RDF> diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/unsigned.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/unsigned.xpi Binary files differnew file mode 100644 index 000000000..51b00475a --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/unsigned.xpi diff --git a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js new file mode 100644 index 000000000..60259944e --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js @@ -0,0 +1,1759 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +const AM_Cc = Components.classes; +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"; +const PREF_EM_MIN_COMPAT_APP_VERSION = "extensions.minCompatibleAppVersion"; +const PREF_EM_MIN_COMPAT_PLATFORM_VERSION = "extensions.minCompatiblePlatformVersion"; +const PREF_GETADDONS_BYIDS = "extensions.getAddons.get.url"; +const PREF_GETADDONS_BYIDS_PERFORMANCE = "extensions.getAddons.getWithPerformance.url"; + +// Forcibly end the test if it runs longer than 15 minutes +const TIMEOUT_MS = 900000; + +Components.utils.import("resource://gre/modules/addons/AddonRepository.jsm"); +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); +Components.utils.import("resource://gre/modules/FileUtils.jsm"); +Components.utils.import("resource://gre/modules/Services.jsm"); +Components.utils.import("resource://gre/modules/NetUtil.jsm"); +Components.utils.import("resource://gre/modules/Promise.jsm"); +Components.utils.import("resource://gre/modules/Task.jsm"); +Components.utils.import("resource://gre/modules/osfile.jsm"); +Components.utils.import("resource://gre/modules/AsyncShutdown.jsm"); + +Services.prefs.setBoolPref("toolkit.osfile.log", true); + +// We need some internal bits of AddonManager +let AMscope = Components.utils.import("resource://gre/modules/AddonManager.jsm"); +let AddonManager = AMscope.AddonManager; +let AddonManagerInternal = AMscope.AddonManagerInternal; +// Mock out AddonManager's reference to the AsyncShutdown module so we can shut +// down AddonManager from the test +let MockAsyncShutdown = { + hook: null, + status: null, + profileBeforeChange: { + addBlocker: function(aName, aBlocker, aOptions) { + do_print("Mock profileBeforeChange blocker for '" + aName + "'"); + MockAsyncShutdown.hook = aBlocker; + MockAsyncShutdown.status = aOptions.fetchState; + } + }, + // We can use the real Barrier + Barrier: AsyncShutdown.Barrier +}; + +AMscope.AsyncShutdown = MockAsyncShutdown; + +var gInternalManager = null; +var gAppInfo = null; +var gAddonsList; + +var gPort = null; +var gUrlToFileMap = {}; + +var TEST_UNPACKED = false; + +function isNightlyChannel() { + var channel = "default"; + try { + channel = Services.prefs.getCharPref("app.update.channel"); + } + catch (e) { } + + return channel != "aurora" && channel != "beta" && channel != "release" && channel != "esr"; +} + +function createAppInfo(id, name, version, platformVersion) { + gAppInfo = { + // nsIXULAppInfo + vendor: "Mozilla", + name: name, + ID: id, + version: version, + appBuildID: "2007010101", + platformVersion: platformVersion ? platformVersion : "1.0", + platformBuildID: "2007010101", + + // nsIXULRuntime + inSafeMode: false, + logConsoleErrors: true, + OS: "XPCShell", + XPCOMABI: "noarch-spidermonkey", + invalidateCachesOnRestart: function invalidateCachesOnRestart() { + // Do nothing + }, + + // nsICrashReporter + annotations: {}, + + annotateCrashReport: function(key, data) { + this.annotations[key] = data; + }, + + QueryInterface: XPCOMUtils.generateQI([AM_Ci.nsIXULAppInfo, + AM_Ci.nsIXULRuntime, + AM_Ci.nsICrashReporter, + AM_Ci.nsISupports]) + }; + + var XULAppInfoFactory = { + createInstance: function (outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return gAppInfo.QueryInterface(iid); + } + }; + var registrar = Components.manager.QueryInterface(AM_Ci.nsIComponentRegistrar); + registrar.registerFactory(XULAPPINFO_CID, "XULAppInfo", + XULAPPINFO_CONTRACTID, XULAppInfoFactory); +} + +/** + * Tests that an add-on does appear in the crash report annotations, if + * crash reporting is enabled. The test will fail if the add-on is not in the + * annotation. + * @param aId + * The ID of the add-on + * @param aVersion + * The version of the add-on + */ +function do_check_in_crash_annotation(aId, aVersion) { + if (!("nsICrashReporter" in AM_Ci)) + return; + + if (!("Add-ons" in gAppInfo.annotations)) { + do_check_false(true); + return; + } + + let addons = gAppInfo.annotations["Add-ons"].split(","); + do_check_false(addons.indexOf(encodeURIComponent(aId) + ":" + + encodeURIComponent(aVersion)) < 0); +} + +/** + * Tests that an add-on does not appear in the crash report annotations, if + * crash reporting is enabled. The test will fail if the add-on is in the + * annotation. + * @param aId + * The ID of the add-on + * @param aVersion + * The version of the add-on + */ +function do_check_not_in_crash_annotation(aId, aVersion) { + if (!("nsICrashReporter" in AM_Ci)) + return; + + if (!("Add-ons" in gAppInfo.annotations)) { + do_check_true(true); + return; + } + + let addons = gAppInfo.annotations["Add-ons"].split(","); + do_check_true(addons.indexOf(encodeURIComponent(aId) + ":" + + encodeURIComponent(aVersion)) < 0); +} + +/** + * Returns a testcase xpi + * + * @param aName + * The name of the testcase (without extension) + * @return an nsIFile pointing to the testcase xpi + */ +function do_get_addon(aName) { + return do_get_file("addons/" + aName + ".xpi"); +} + +function do_get_addon_hash(aName, aAlgorithm) { + let file = do_get_addon(aName); + return do_get_file_hash(file); +} + +function do_get_file_hash(aFile, aAlgorithm) { + if (!aAlgorithm) + aAlgorithm = "sha1"; + + let crypto = AM_Cc["@mozilla.org/security/hash;1"]. + createInstance(AM_Ci.nsICryptoHash); + crypto.initWithString(aAlgorithm); + let fis = AM_Cc["@mozilla.org/network/file-input-stream;1"]. + createInstance(AM_Ci.nsIFileInputStream); + fis.init(aFile, -1, -1, false); + crypto.updateFromStream(fis, aFile.fileSize); + + // return the two-digit hexadecimal code for a byte + function toHexString(charCode) + ("0" + charCode.toString(16)).slice(-2); + + let binary = crypto.finish(false); + return aAlgorithm + ":" + [toHexString(binary.charCodeAt(i)) for (i in binary)].join("") +} + +/** + * Returns an extension uri spec + * + * @param aProfileDir + * The extension install directory + * @return a uri spec pointing to the root of the extension + */ +function do_get_addon_root_uri(aProfileDir, aId) { + let path = aProfileDir.clone(); + path.append(aId); + if (!path.exists()) { + path.leafName += ".xpi"; + return "jar:" + Services.io.newFileURI(path).spec + "!/"; + } + else { + return Services.io.newFileURI(path).spec; + } +} + +function do_get_expected_addon_name(aId) { + if (TEST_UNPACKED) + return aId; + return aId + ".xpi"; +} + +/** + * Check that an array of actual add-ons is the same as an array of + * expected add-ons. + * + * @param aActualAddons + * The array of actual add-ons to check. + * @param aExpectedAddons + * The array of expected add-ons to check against. + * @param aProperties + * An array of properties to check. + */ +function do_check_addons(aActualAddons, aExpectedAddons, aProperties) { + do_check_neq(aActualAddons, null); + do_check_eq(aActualAddons.length, aExpectedAddons.length); + for (let i = 0; i < aActualAddons.length; i++) + do_check_addon(aActualAddons[i], aExpectedAddons[i], aProperties); +} + +/** + * Check that the actual add-on is the same as the expected add-on. + * + * @param aActualAddon + * The actual add-on to check. + * @param aExpectedAddon + * The expected add-on to check against. + * @param aProperties + * An array of properties to check. + */ +function do_check_addon(aActualAddon, aExpectedAddon, aProperties) { + do_check_neq(aActualAddon, null); + + aProperties.forEach(function(aProperty) { + let actualValue = aActualAddon[aProperty]; + let expectedValue = aExpectedAddon[aProperty]; + + // Check that all undefined expected properties are null on actual add-on + if (!(aProperty in aExpectedAddon)) { + if (actualValue !== undefined && actualValue !== null) { + do_throw("Unexpected defined/non-null property for add-on " + + aExpectedAddon.id + " (addon[" + aProperty + "] = " + + actualValue.toSource() + ")"); + } + + return; + } + else if (expectedValue && !actualValue) { + do_throw("Missing property for add-on " + aExpectedAddon.id + + ": expected addon[" + aProperty + "] = " + expectedValue); + return; + } + + switch (aProperty) { + case "creator": + do_check_author(actualValue, expectedValue); + break; + + case "developers": + case "translators": + case "contributors": + do_check_eq(actualValue.length, expectedValue.length); + for (let i = 0; i < actualValue.length; i++) + do_check_author(actualValue[i], expectedValue[i]); + break; + + case "screenshots": + do_check_eq(actualValue.length, expectedValue.length); + for (let i = 0; i < actualValue.length; i++) + do_check_screenshot(actualValue[i], expectedValue[i]); + break; + + case "sourceURI": + do_check_eq(actualValue.spec, expectedValue); + break; + + case "updateDate": + do_check_eq(actualValue.getTime(), expectedValue.getTime()); + break; + + case "compatibilityOverrides": + do_check_eq(actualValue.length, expectedValue.length); + for (let i = 0; i < actualValue.length; i++) + do_check_compatibilityoverride(actualValue[i], expectedValue[i]); + break; + + case "icons": + do_check_icons(actualValue, expectedValue); + break; + + default: + if (remove_port(actualValue) !== remove_port(expectedValue)) + do_throw("Failed for " + aProperty + " for add-on " + aExpectedAddon.id + + " (" + actualValue + " === " + expectedValue + ")"); + } + }); +} + +/** + * Check that the actual author is the same as the expected author. + * + * @param aActual + * The actual author to check. + * @param aExpected + * The expected author to check against. + */ +function do_check_author(aActual, aExpected) { + do_check_eq(aActual.toString(), aExpected.name); + do_check_eq(aActual.name, aExpected.name); + do_check_eq(aActual.url, aExpected.url); +} + +/** + * Check that the actual screenshot is the same as the expected screenshot. + * + * @param aActual + * The actual screenshot to check. + * @param aExpected + * The expected screenshot to check against. + */ +function do_check_screenshot(aActual, aExpected) { + do_check_eq(aActual.toString(), aExpected.url); + do_check_eq(aActual.url, aExpected.url); + do_check_eq(aActual.width, aExpected.width); + do_check_eq(aActual.height, aExpected.height); + do_check_eq(aActual.thumbnailURL, aExpected.thumbnailURL); + do_check_eq(aActual.thumbnailWidth, aExpected.thumbnailWidth); + do_check_eq(aActual.thumbnailHeight, aExpected.thumbnailHeight); + do_check_eq(aActual.caption, aExpected.caption); +} + +/** + * Check that the actual compatibility override is the same as the expected + * compatibility override. + * + * @param aAction + * The actual compatibility override to check. + * @param aExpected + * The expected compatibility override to check against. + */ +function do_check_compatibilityoverride(aActual, aExpected) { + do_check_eq(aActual.type, aExpected.type); + do_check_eq(aActual.minVersion, aExpected.minVersion); + do_check_eq(aActual.maxVersion, aExpected.maxVersion); + do_check_eq(aActual.appID, aExpected.appID); + do_check_eq(aActual.appMinVersion, aExpected.appMinVersion); + do_check_eq(aActual.appMaxVersion, aExpected.appMaxVersion); +} + +function do_check_icons(aActual, aExpected) { + for (var size in aExpected) { + do_check_eq(remove_port(aActual[size]), remove_port(aExpected[size])); + } +} + +// Record the error (if any) from trying to save the XPI +// database at shutdown time +let gXPISaveError = null; + +/** + * Starts up the add-on manager as if it was started by the application. + * + * @param aAppChanged + * An optional boolean parameter to simulate the case where the + * application has changed version since the last run. If not passed it + * defaults to true + */ +function startupManager(aAppChanged) { + if (gInternalManager) + do_throw("Test attempt to startup manager that was already started."); + + if (aAppChanged || aAppChanged === undefined) { + if (gExtensionsINI.exists()) + gExtensionsINI.remove(true); + } + + gInternalManager = AM_Cc["@mozilla.org/addons/integration;1"]. + getService(AM_Ci.nsIObserver). + QueryInterface(AM_Ci.nsITimerCallback); + + gInternalManager.observe(null, "addons-startup", null); + + // Load the add-ons list as it was after extension registration + loadAddonsList(); +} + +/** + * Helper to spin the event loop until a promise resolves or rejects + */ +function loopUntilPromise(aPromise) { + let done = false; + aPromise.then( + () => done = true, + err => { + do_report_unexpected_exception(err); + done = true; + }); + + let thr = Services.tm.mainThread; + + while (!done) { + thr.processNextEvent(true); + } +} + +/** + * Restarts the add-on manager as if the host application was restarted. + * + * @param aNewVersion + * An optional new version to use for the application. Passing this + * will change nsIXULAppInfo.version and make the startup appear as if + * the application version has changed. + */ +function restartManager(aNewVersion) { + loopUntilPromise(promiseRestartManager(aNewVersion)); +} + +function promiseRestartManager(aNewVersion) { + return promiseShutdownManager() + .then(null, err => do_report_unexpected_exception(err)) + .then(() => { + if (aNewVersion) { + gAppInfo.version = aNewVersion; + startupManager(true); + } + else { + startupManager(false); + } + }); +} + +function shutdownManager() { + loopUntilPromise(promiseShutdownManager()); +} + +function promiseShutdownManager() { + if (!gInternalManager) { + return Promise.resolve(false); + } + + let hookErr = null; + Services.obs.notifyObservers(null, "quit-application-granted", null); + return MockAsyncShutdown.hook() + .then(null, err => hookErr = err) + .then( () => { + gInternalManager = null; + + // Load the add-ons list as it was after application shutdown + loadAddonsList(); + + // Clear any crash report annotations + gAppInfo.annotations = {}; + + // Force the XPIProvider provider to reload to better + // simulate real-world usage. + let XPIscope = Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm"); + // This would be cleaner if I could get it as the rejection reason from + // the AddonManagerInternal.shutdown() promise + gXPISaveError = XPIscope.XPIProvider._shutdownError; + do_print("gXPISaveError set to: " + gXPISaveError); + AddonManagerPrivate.unregisterProvider(XPIscope.XPIProvider); + Components.utils.unload("resource://gre/modules/addons/XPIProvider.jsm"); + if (hookErr) { + throw hookErr; + } + }); +} + +function loadAddonsList() { + function readDirectories(aSection) { + var dirs = []; + var keys = parser.getKeys(aSection); + while (keys.hasMore()) { + let descriptor = parser.getString(aSection, keys.getNext()); + try { + let file = AM_Cc["@mozilla.org/file/local;1"]. + createInstance(AM_Ci.nsIFile); + file.persistentDescriptor = descriptor; + dirs.push(file); + } + catch (e) { + // Throws if the directory doesn't exist, we can ignore this since the + // platform will too. + } + } + return dirs; + } + + gAddonsList = { + extensions: [], + themes: [], + mpIncompatible: new Set() + }; + + if (!gExtensionsINI.exists()) + return; + + var factory = AM_Cc["@mozilla.org/xpcom/ini-parser-factory;1"]. + getService(AM_Ci.nsIINIParserFactory); + var parser = factory.createINIParser(gExtensionsINI); + gAddonsList.extensions = readDirectories("ExtensionDirs"); + gAddonsList.themes = readDirectories("ThemeDirs"); + var keys = parser.getKeys("MultiprocessIncompatibleExtensions"); + while (keys.hasMore()) { + let id = parser.getString("MultiprocessIncompatibleExtensions", keys.getNext()); + gAddonsList.mpIncompatible.add(id); + } +} + +function isItemInAddonsList(aType, aDir, aId) { + var path = aDir.clone(); + path.append(aId); + var xpiPath = aDir.clone(); + xpiPath.append(aId + ".xpi"); + for (var i = 0; i < gAddonsList[aType].length; i++) { + let file = gAddonsList[aType][i]; + if (!file.exists()) + do_throw("Non-existant path found in extensions.ini: " + file.path) + if (file.isDirectory() && file.equals(path)) + return true; + if (file.isFile() && file.equals(xpiPath)) + return true; + } + return false; +} + +function isItemMarkedMPIncompatible(aId) { + return gAddonsList.mpIncompatible.has(aId); +} + +function isThemeInAddonsList(aDir, aId) { + return isItemInAddonsList("themes", aDir, aId); +} + +function isExtensionInAddonsList(aDir, aId) { + return isItemInAddonsList("extensions", aDir, aId); +} + +function check_startup_changes(aType, aIds) { + var ids = aIds.slice(0); + ids.sort(); + var changes = AddonManager.getStartupChanges(aType); + changes = changes.filter(function(aEl) /@tests.mozilla.org$/.test(aEl)); + changes.sort(); + + do_check_eq(JSON.stringify(ids), JSON.stringify(changes)); +} + +/** + * Escapes any occurances of &, ", < or > with XML entities. + * + * @param str + * The string to escape + * @return The escaped string + */ +function escapeXML(aStr) { + return aStr.toString() + .replace(/&/g, "&") + .replace(/"/g, """) + .replace(/</g, "<") + .replace(/>/g, ">"); +} + +function writeLocaleStrings(aData) { + let rdf = ""; + ["name", "description", "creator", "homepageURL"].forEach(function(aProp) { + if (aProp in aData) + rdf += "<em:" + aProp + ">" + escapeXML(aData[aProp]) + "</em:" + aProp + ">\n"; + }); + + ["developer", "translator", "contributor"].forEach(function(aProp) { + if (aProp in aData) { + aData[aProp].forEach(function(aValue) { + rdf += "<em:" + aProp + ">" + escapeXML(aValue) + "</em:" + aProp + ">\n"; + }); + } + }); + return rdf; +} + +/** + * Creates an update.rdf structure as a string using for the update data passed. + * + * @param aData + * The update data as a JS object. Each property name is an add-on ID, + * the property value is an array of each version of the add-on. Each + * array value is a JS object containing the data for the version, at + * minimum a "version" and "targetApplications" property should be + * included to create a functional update manifest. + * @return the update.rdf structure as a string. + */ +function createUpdateRDF(aData) { + var rdf = '<?xml version="1.0"?>\n'; + rdf += '<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"\n' + + ' xmlns:em="http://www.mozilla.org/2004/em-rdf#">\n'; + + for (let addon in aData) { + rdf += ' <Description about="urn:mozilla:extension:' + escapeXML(addon) + '"><em:updates><Seq>\n'; + + for (let versionData of aData[addon]) { + rdf += ' <li><Description>\n'; + + for (let prop of ["version", "multiprocessCompatible"]) { + if (prop in versionData) + rdf += " <em:" + prop + ">" + escapeXML(versionData[prop]) + "</em:" + prop + ">\n"; + } + + if ("targetApplications" in versionData) { + for (let app of versionData.targetApplications) { + rdf += " <em:targetApplication><Description>\n"; + for (let prop of ["id", "minVersion", "maxVersion", "updateLink", "updateHash"]) { + if (prop in app) + rdf += " <em:" + prop + ">" + escapeXML(app[prop]) + "</em:" + prop + ">\n"; + } + rdf += " </Description></em:targetApplication>\n"; + } + } + + rdf += ' </Description></li>\n'; + } + + rdf += ' </Seq></em:updates></Description>\n' + } + rdf += "</RDF>\n"; + + return rdf; +} + +function createInstallRDF(aData) { + var rdf = '<?xml version="1.0"?>\n'; + rdf += '<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"\n' + + ' xmlns:em="http://www.mozilla.org/2004/em-rdf#">\n'; + rdf += '<Description about="urn:mozilla:install-manifest">\n'; + + ["id", "version", "type", "internalName", "updateURL", "updateKey", + "optionsURL", "optionsType", "aboutURL", "iconURL", "icon64URL", + "skinnable", "bootstrap", "strictCompatibility", "multiprocessCompatible"].forEach(function(aProp) { + if (aProp in aData) + rdf += "<em:" + aProp + ">" + escapeXML(aData[aProp]) + "</em:" + aProp + ">\n"; + }); + + rdf += writeLocaleStrings(aData); + + if ("targetPlatforms" in aData) { + aData.targetPlatforms.forEach(function(aPlatform) { + rdf += "<em:targetPlatform>" + escapeXML(aPlatform) + "</em:targetPlatform>\n"; + }); + } + + if ("targetApplications" in aData) { + aData.targetApplications.forEach(function(aApp) { + rdf += "<em:targetApplication><Description>\n"; + ["id", "minVersion", "maxVersion"].forEach(function(aProp) { + if (aProp in aApp) + rdf += "<em:" + aProp + ">" + escapeXML(aApp[aProp]) + "</em:" + aProp + ">\n"; + }); + rdf += "</Description></em:targetApplication>\n"; + }); + } + + if ("localized" in aData) { + aData.localized.forEach(function(aLocalized) { + rdf += "<em:localized><Description>\n"; + if ("locale" in aLocalized) { + aLocalized.locale.forEach(function(aLocaleName) { + rdf += "<em:locale>" + escapeXML(aLocaleName) + "</em:locale>\n"; + }); + } + rdf += writeLocaleStrings(aLocalized); + rdf += "</Description></em:localized>\n"; + }); + } + + rdf += "</Description>\n</RDF>\n"; + return rdf; +} + +/** + * Writes an install.rdf manifest into a directory using the properties passed + * in a JS object. The objects should contain a property for each property to + * appear in the RDF. The object may contain an array of objects with id, + * minVersion and maxVersion in the targetApplications property to give target + * application compatibility. + * + * @param aData + * The object holding data about the add-on + * @param aDir + * The directory to add the install.rdf to + * @param aId + * An optional string to override the default installation aId + * @param aExtraFile + * An optional dummy file to create in the directory + * @return An nsIFile for the directory in which the add-on is installed. + */ +function writeInstallRDFToDir(aData, aDir, aId, aExtraFile) { + var id = aId ? aId : aData.id + + var dir = aDir.clone(); + dir.append(id); + + var rdf = createInstallRDF(aData); + if (!dir.exists()) + dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); + var file = dir.clone(); + file.append("install.rdf"); + if (file.exists()) + file.remove(true); + var fos = AM_Cc["@mozilla.org/network/file-output-stream;1"]. + createInstance(AM_Ci.nsIFileOutputStream); + fos.init(file, + FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | FileUtils.MODE_TRUNCATE, + FileUtils.PERMS_FILE, 0); + fos.write(rdf, rdf.length); + fos.close(); + + if (!aExtraFile) + return dir; + + file = dir.clone(); + file.append(aExtraFile); + file.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); + return dir; +} + +/** + * Writes an install.rdf manifest into an extension using the properties passed + * in a JS object. The objects should contain a property for each property to + * appear in the RDF. The object may contain an array of objects with id, + * minVersion and maxVersion in the targetApplications property to give target + * application compatibility. + * + * @param aData + * The object holding data about the add-on + * @param aDir + * The install directory to add the extension to + * @param aId + * An optional string to override the default installation aId + * @param aExtraFile + * An optional dummy file to create in the extension + * @return A file pointing to where the extension was installed + */ +function writeInstallRDFForExtension(aData, aDir, aId, aExtraFile) { + if (TEST_UNPACKED) { + return writeInstallRDFToDir(aData, aDir, aId, aExtraFile); + } + return writeInstallRDFToXPI(aData, aDir, aId, aExtraFile); +} + +/** + * Writes an install.rdf manifest into a packed extension using the properties passed + * in a JS object. The objects should contain a property for each property to + * appear in the RDF. The object may contain an array of objects with id, + * minVersion and maxVersion in the targetApplications property to give target + * application compatibility. + * + * @param aData + * The object holding data about the add-on + * @param aDir + * The install directory to add the extension to + * @param aId + * An optional string to override the default installation aId + * @param aExtraFile + * An optional dummy file to create in the extension + * @return A file pointing to where the extension was installed + */ +function writeInstallRDFToXPI(aData, aDir, aId, aExtraFile) { + var id = aId ? aId : aData.id + + if (!aDir.exists()) + aDir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); + + var file = aDir.clone(); + file.append(id + ".xpi"); + writeInstallRDFToXPIFile(aData, file, aExtraFile); + + return file; +} + +/** + * Writes an install.rdf manifest into an XPI file using the properties passed + * in a JS object. The objects should contain a property for each property to + * appear in the RDF. The object may contain an array of objects with id, + * minVersion and maxVersion in the targetApplications property to give target + * application compatibility. + * + * @param aData + * The object holding data about the add-on + * @param aFile + * The XPI file to write to. Any existing file will be overwritten + * @param aExtraFile + * An optional dummy file to create in the extension + */ +function writeInstallRDFToXPIFile(aData, aFile, aExtraFile) { + var rdf = createInstallRDF(aData); + var stream = AM_Cc["@mozilla.org/io/string-input-stream;1"]. + createInstance(AM_Ci.nsIStringInputStream); + stream.setData(rdf, -1); + var zipW = AM_Cc["@mozilla.org/zipwriter;1"]. + createInstance(AM_Ci.nsIZipWriter); + zipW.open(aFile, FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | FileUtils.MODE_TRUNCATE); + zipW.addEntryStream("install.rdf", 0, AM_Ci.nsIZipWriter.COMPRESSION_NONE, + stream, false); + if (aExtraFile) + zipW.addEntryStream(aExtraFile, 0, AM_Ci.nsIZipWriter.COMPRESSION_NONE, + stream, false); + zipW.close(); +} + +let temp_xpis = []; +/** + * Creates an XPI file for some manifest data in the temporary directory and + * returns the nsIFile for it. The file will be deleted when the test completes. + * + * @param aData + * The object holding data about the add-on + * @return A file pointing to the created XPI file + */ +function createTempXPIFile(aData) { + var file = gTmpD.clone(); + file.append("foo.xpi"); + do { + file.leafName = Math.floor(Math.random() * 1000000) + ".xpi"; + } while (file.exists()); + + temp_xpis.push(file); + writeInstallRDFToXPIFile(aData, file); + return file; +} + +/** + * Sets the last modified time of the extension, usually to trigger an update + * of its metadata. If the extension is unpacked, this function assumes that + * the extension contains only the install.rdf file. + * + * @param aExt a file pointing to either the packed extension or its unpacked directory. + * @param aTime the time to which we set the lastModifiedTime of the extension + * + * @deprecated Please use promiseSetExtensionModifiedTime instead + */ +function setExtensionModifiedTime(aExt, aTime) { + aExt.lastModifiedTime = aTime; + if (aExt.isDirectory()) { + let entries = aExt.directoryEntries + .QueryInterface(AM_Ci.nsIDirectoryEnumerator); + while (entries.hasMoreElements()) + setExtensionModifiedTime(entries.nextFile, aTime); + entries.close(); + } +} +function promiseSetExtensionModifiedTime(aPath, aTime) { + return Task.spawn(function* () { + yield OS.File.setDates(aPath, aTime, aTime); + let entries, iterator; + try { + let iterator = new OS.File.DirectoryIterator(aPath); + entries = yield iterator.nextBatch(); + } catch (ex if ex instanceof OS.File.Error) { + return; + } finally { + if (iterator) { + iterator.close(); + } + } + for (let entry of entries) { + yield promiseSetExtensionModifiedTime(entry.path, aTime); + } + }); +} + +/** + * Manually installs an XPI file into an install location by either copying the + * XPI there or extracting it depending on whether unpacking is being tested + * or not. + * + * @param aXPIFile + * The XPI file to install. + * @param aInstallLocation + * The install location (an nsIFile) to install into. + * @param aID + * The ID to install as. + */ +function manuallyInstall(aXPIFile, aInstallLocation, aID) { + if (TEST_UNPACKED) { + let dir = aInstallLocation.clone(); + dir.append(aID); + dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); + let zip = AM_Cc["@mozilla.org/libjar/zip-reader;1"]. + createInstance(AM_Ci.nsIZipReader); + zip.open(aXPIFile); + let entries = zip.findEntries(null); + while (entries.hasMore()) { + let entry = entries.getNext(); + let target = dir.clone(); + entry.split("/").forEach(function(aPart) { + target.append(aPart); + }); + zip.extract(entry, target); + } + zip.close(); + + return dir; + } + else { + let target = aInstallLocation.clone(); + target.append(aID + ".xpi"); + aXPIFile.copyTo(target.parent, target.leafName); + return target; + } +} + +/** + * Manually uninstalls an add-on by removing its files from the install + * location. + * + * @param aInstallLocation + * The nsIFile of the install location to remove from. + * @param aID + * The ID of the add-on to remove. + */ +function manuallyUninstall(aInstallLocation, aID) { + let file = getFileForAddon(aInstallLocation, aID); + + // In reality because the app is restarted a flush isn't necessary for XPIs + // removed outside the app, but for testing we must flush manually. + if (file.isFile()) + Services.obs.notifyObservers(file, "flush-cache-entry", null); + + file.remove(true); +} + +/** + * Gets the nsIFile for where an add-on is installed. It may point to a file or + * a directory depending on whether add-ons are being installed unpacked or not. + * + * @param aDir + * The nsIFile for the install location + * @param aId + * The ID of the add-on + * @return an nsIFile + */ +function getFileForAddon(aDir, aId) { + var dir = aDir.clone(); + dir.append(do_get_expected_addon_name(aId)); + return dir; +} + +function registerDirectory(aKey, aDir) { + var dirProvider = { + getFile: function(aProp, aPersistent) { + aPersistent.value = true; + if (aProp == aKey) + return aDir.clone(); + return null; + }, + + QueryInterface: XPCOMUtils.generateQI([AM_Ci.nsIDirectoryServiceProvider, + AM_Ci.nsISupports]) + }; + Services.dirsvc.registerProvider(dirProvider); +} + +var gExpectedEvents = {}; +var gExpectedInstalls = []; +var gNext = null; + +function getExpectedEvent(aId) { + if (!(aId in gExpectedEvents)) + do_throw("Wasn't expecting events for " + aId); + if (gExpectedEvents[aId].length == 0) + do_throw("Too many events for " + aId); + let event = gExpectedEvents[aId].shift(); + if (event instanceof Array) + return event; + return [event, true]; +} + +function getExpectedInstall(aAddon) { + if (gExpectedInstalls instanceof Array) + return gExpectedInstalls.shift(); + if (!aAddon || !aAddon.id) + return gExpectedInstalls["NO_ID"].shift(); + let id = aAddon.id; + if (!(id in gExpectedInstalls) || !(gExpectedInstalls[id] instanceof Array)) + do_throw("Wasn't expecting events for " + id); + if (gExpectedInstalls[id].length == 0) + do_throw("Too many events for " + id); + return gExpectedInstalls[id].shift(); +} + +const AddonListener = { + onPropertyChanged: function(aAddon, aProperties) { + do_print(`Got onPropertyChanged event for ${aAddon.id}`); + let [event, properties] = getExpectedEvent(aAddon.id); + do_check_eq("onPropertyChanged", event); + do_check_eq(aProperties.length, properties.length); + properties.forEach(function(aProperty) { + // Only test that the expected properties are listed, having additional + // properties listed is not necessary a problem + if (aProperties.indexOf(aProperty) == -1) + do_throw("Did not see property change for " + aProperty); + }); + return check_test_completed(arguments); + }, + + onEnabling: function(aAddon, aRequiresRestart) { + do_print(`Got onEnabling event for ${aAddon.id}`); + let [event, expectedRestart] = getExpectedEvent(aAddon.id); + do_check_eq("onEnabling", event); + do_check_eq(aRequiresRestart, expectedRestart); + if (expectedRestart) + do_check_true(hasFlag(aAddon.pendingOperations, AddonManager.PENDING_ENABLE)); + do_check_false(hasFlag(aAddon.permissions, AddonManager.PERM_CAN_ENABLE)); + return check_test_completed(arguments); + }, + + onEnabled: function(aAddon) { + do_print(`Got onEnabled event for ${aAddon.id}`); + let [event, expectedRestart] = getExpectedEvent(aAddon.id); + do_check_eq("onEnabled", event); + do_check_false(hasFlag(aAddon.permissions, AddonManager.PERM_CAN_ENABLE)); + return check_test_completed(arguments); + }, + + onDisabling: function(aAddon, aRequiresRestart) { + do_print(`Got onDisabling event for ${aAddon.id}`); + let [event, expectedRestart] = getExpectedEvent(aAddon.id); + do_check_eq("onDisabling", event); + do_check_eq(aRequiresRestart, expectedRestart); + if (expectedRestart) + do_check_true(hasFlag(aAddon.pendingOperations, AddonManager.PENDING_DISABLE)); + do_check_false(hasFlag(aAddon.permissions, AddonManager.PERM_CAN_DISABLE)); + return check_test_completed(arguments); + }, + + onDisabled: function(aAddon) { + do_print(`Got onDisabled event for ${aAddon.id}`); + let [event, expectedRestart] = getExpectedEvent(aAddon.id); + do_check_eq("onDisabled", event); + do_check_false(hasFlag(aAddon.permissions, AddonManager.PERM_CAN_DISABLE)); + return check_test_completed(arguments); + }, + + onInstalling: function(aAddon, aRequiresRestart) { + do_print(`Got onInstalling event for ${aAddon.id}`); + let [event, expectedRestart] = getExpectedEvent(aAddon.id); + do_check_eq("onInstalling", event); + do_check_eq(aRequiresRestart, expectedRestart); + if (expectedRestart) + do_check_true(hasFlag(aAddon.pendingOperations, AddonManager.PENDING_INSTALL)); + return check_test_completed(arguments); + }, + + onInstalled: function(aAddon) { + do_print(`Got onInstalled event for ${aAddon.id}`); + let [event, expectedRestart] = getExpectedEvent(aAddon.id); + do_check_eq("onInstalled", event); + return check_test_completed(arguments); + }, + + onUninstalling: function(aAddon, aRequiresRestart) { + do_print(`Got onUninstalling event for ${aAddon.id}`); + let [event, expectedRestart] = getExpectedEvent(aAddon.id); + do_check_eq("onUninstalling", event); + do_check_eq(aRequiresRestart, expectedRestart); + if (expectedRestart) + do_check_true(hasFlag(aAddon.pendingOperations, AddonManager.PENDING_UNINSTALL)); + return check_test_completed(arguments); + }, + + onUninstalled: function(aAddon) { + do_print(`Got onUninstalled event for ${aAddon.id}`); + let [event, expectedRestart] = getExpectedEvent(aAddon.id); + do_check_eq("onUninstalled", event); + return check_test_completed(arguments); + }, + + onOperationCancelled: function(aAddon) { + do_print(`Got onOperationCancelled event for ${aAddon.id}`); + let [event, expectedRestart] = getExpectedEvent(aAddon.id); + do_check_eq("onOperationCancelled", event); + return check_test_completed(arguments); + } +}; + +const InstallListener = { + onNewInstall: function(install) { + if (install.state != AddonManager.STATE_DOWNLOADED && + install.state != AddonManager.STATE_AVAILABLE) + do_throw("Bad install state " + install.state); + do_check_eq(install.error, 0); + do_check_eq("onNewInstall", getExpectedInstall()); + return check_test_completed(arguments); + }, + + onDownloadStarted: function(install) { + do_check_eq(install.state, AddonManager.STATE_DOWNLOADING); + do_check_eq(install.error, 0); + do_check_eq("onDownloadStarted", getExpectedInstall()); + return check_test_completed(arguments); + }, + + onDownloadEnded: function(install) { + do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); + do_check_eq(install.error, 0); + do_check_eq("onDownloadEnded", getExpectedInstall()); + return check_test_completed(arguments); + }, + + onDownloadFailed: function(install) { + do_check_eq(install.state, AddonManager.STATE_DOWNLOAD_FAILED); + do_check_eq("onDownloadFailed", getExpectedInstall()); + return check_test_completed(arguments); + }, + + onDownloadCancelled: function(install) { + do_check_eq(install.state, AddonManager.STATE_CANCELLED); + do_check_eq(install.error, 0); + do_check_eq("onDownloadCancelled", getExpectedInstall()); + return check_test_completed(arguments); + }, + + onInstallStarted: function(install) { + do_check_eq(install.state, AddonManager.STATE_INSTALLING); + do_check_eq(install.error, 0); + do_check_eq("onInstallStarted", getExpectedInstall(install.addon)); + return check_test_completed(arguments); + }, + + onInstallEnded: function(install, newAddon) { + do_check_eq(install.state, AddonManager.STATE_INSTALLED); + do_check_eq(install.error, 0); + do_check_eq("onInstallEnded", getExpectedInstall(install.addon)); + return check_test_completed(arguments); + }, + + onInstallFailed: function(install) { + do_check_eq(install.state, AddonManager.STATE_INSTALL_FAILED); + do_check_eq("onInstallFailed", getExpectedInstall(install.addon)); + return check_test_completed(arguments); + }, + + onInstallCancelled: function(install) { + // If the install was cancelled by a listener returning false from + // onInstallStarted, then the state will revert to STATE_DOWNLOADED. + let possibleStates = [AddonManager.STATE_CANCELLED, + AddonManager.STATE_DOWNLOADED]; + do_check_true(possibleStates.indexOf(install.state) != -1); + do_check_eq(install.error, 0); + do_check_eq("onInstallCancelled", getExpectedInstall(install.addon)); + return check_test_completed(arguments); + }, + + onExternalInstall: function(aAddon, existingAddon, aRequiresRestart) { + do_check_eq("onExternalInstall", getExpectedInstall(aAddon)); + do_check_false(aRequiresRestart); + return check_test_completed(arguments); + } +}; + +function hasFlag(aBits, aFlag) { + return (aBits & aFlag) != 0; +} + +// Just a wrapper around setting the expected events +function prepare_test(aExpectedEvents, aExpectedInstalls, aNext) { + AddonManager.addAddonListener(AddonListener); + AddonManager.addInstallListener(InstallListener); + + gExpectedInstalls = aExpectedInstalls; + gExpectedEvents = aExpectedEvents; + gNext = aNext; +} + +// Checks if all expected events have been seen and if so calls the callback +function check_test_completed(aArgs) { + if (!gNext) + return undefined; + + if (gExpectedInstalls instanceof Array && + gExpectedInstalls.length > 0) + return undefined; + else for each (let installList in gExpectedInstalls) { + if (installList.length > 0) + return undefined; + } + + for (let id in gExpectedEvents) { + if (gExpectedEvents[id].length > 0) + return undefined; + } + + return gNext.apply(null, aArgs); +} + +// Verifies that all the expected events for all add-ons were seen +function ensure_test_completed() { + for (let i in gExpectedEvents) { + if (gExpectedEvents[i].length > 0) + do_throw("Didn't see all the expected events for " + i); + } + gExpectedEvents = {}; + if (gExpectedInstalls) + do_check_eq(gExpectedInstalls.length, 0); +} + +/** + * A helper method to install an array of AddonInstall to completion and then + * call a provided callback. + * + * @param aInstalls + * The array of AddonInstalls to install + * @param aCallback + * The callback to call when all installs have finished + */ +function completeAllInstalls(aInstalls, aCallback) { + let count = aInstalls.length; + + if (count == 0) { + aCallback(); + return; + } + + function installCompleted(aInstall) { + aInstall.removeListener(listener); + + if (--count == 0) + do_execute_soon(aCallback); + } + + let listener = { + onDownloadFailed: installCompleted, + onDownloadCancelled: installCompleted, + onInstallFailed: installCompleted, + onInstallCancelled: installCompleted, + onInstallEnded: installCompleted + }; + + aInstalls.forEach(function(aInstall) { + aInstall.addListener(listener); + aInstall.install(); + }); +} + +function promiseCompleteAllInstalls(aInstalls) { + return new Promise(resolve => { + completeAllInstalls(aInstalls, resolve); + }); +} + +/** + * A helper method to install an array of files and call a callback after the + * installs are completed. + * + * @param aFiles + * The array of files to install + * @param aCallback + * The callback to call when all installs have finished + * @param aIgnoreIncompatible + * Optional parameter to ignore add-ons that are incompatible in + * aome way with the application + */ +function installAllFiles(aFiles, aCallback, aIgnoreIncompatible) { + let count = aFiles.length; + let installs = []; + function callback() { + if (aCallback) { + aCallback(); + } + } + aFiles.forEach(function(aFile) { + AddonManager.getInstallForFile(aFile, function(aInstall) { + if (!aInstall) + do_throw("No AddonInstall created for " + aFile.path); + do_check_eq(aInstall.state, AddonManager.STATE_DOWNLOADED); + + if (!aIgnoreIncompatible || !aInstall.addon.appDisabled) + installs.push(aInstall); + + if (--count == 0) + completeAllInstalls(installs, callback); + }); + }); +} + +function promiseInstallAllFiles(aFiles, aIgnoreIncompatible) { + let deferred = Promise.defer(); + installAllFiles(aFiles, deferred.resolve, aIgnoreIncompatible); + return deferred.promise; + +} + +if ("nsIWindowsRegKey" in AM_Ci) { + var MockRegistry = { + LOCAL_MACHINE: {}, + CURRENT_USER: {}, + CLASSES_ROOT: {}, + + getRoot: function(aRoot) { + switch (aRoot) { + case AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE: + return MockRegistry.LOCAL_MACHINE; + case AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER: + return MockRegistry.CURRENT_USER; + case AM_Ci.nsIWindowsRegKey.ROOT_KEY_CLASSES_ROOT: + return MockRegistry.CLASSES_ROOT; + default: + do_throw("Unknown root " + aRootKey); + return null; + } + }, + + setValue: function(aRoot, aPath, aName, aValue) { + let rootKey = MockRegistry.getRoot(aRoot); + + if (!(aPath in rootKey)) { + rootKey[aPath] = []; + } + else { + for (let i = 0; i < rootKey[aPath].length; i++) { + if (rootKey[aPath][i].name == aName) { + if (aValue === null) + rootKey[aPath].splice(i, 1); + else + rootKey[aPath][i].value = aValue; + return; + } + } + } + + if (aValue === null) + return; + + rootKey[aPath].push({ + name: aName, + value: aValue + }); + } + }; + + /** + * This is a mock nsIWindowsRegistry implementation. It only implements the + * methods that the extension manager requires. + */ + function MockWindowsRegKey() { + } + + MockWindowsRegKey.prototype = { + values: null, + + // --- Overridden nsISupports interface functions --- + QueryInterface: XPCOMUtils.generateQI([AM_Ci.nsIWindowsRegKey]), + + // --- Overridden nsIWindowsRegKey interface functions --- + open: function(aRootKey, aRelPath, aMode) { + let rootKey = MockRegistry.getRoot(aRootKey); + + if (!(aRelPath in rootKey)) + rootKey[aRelPath] = []; + this.values = rootKey[aRelPath]; + }, + + close: function() { + this.values = null; + }, + + get valueCount() { + if (!this.values) + throw Components.results.NS_ERROR_FAILURE; + return this.values.length; + }, + + getValueName: function(aIndex) { + if (!this.values || aIndex >= this.values.length) + throw Components.results.NS_ERROR_FAILURE; + return this.values[aIndex].name; + }, + + readStringValue: function(aName) { + for (let value of this.values) { + if (value.name == aName) + return value.value; + } + return null; + } + }; + + var WinRegFactory = { + createInstance: function(aOuter, aIid) { + if (aOuter != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + + var key = new MockWindowsRegKey(); + return key.QueryInterface(aIid); + } + }; + + var registrar = Components.manager.QueryInterface(AM_Ci.nsIComponentRegistrar); + registrar.registerFactory(Components.ID("{0478de5b-0f38-4edb-851d-4c99f1ed8eba}"), + "Mock Windows Registry Implementation", + "@mozilla.org/windows-registry-key;1", WinRegFactory); +} + +// Get the profile directory for tests to use. +const gProfD = do_get_profile(); + +const EXTENSIONS_DB = "extensions.json"; +let gExtensionsJSON = gProfD.clone(); +gExtensionsJSON.append(EXTENSIONS_DB); + +const EXTENSIONS_INI = "extensions.ini"; +let gExtensionsINI = gProfD.clone(); +gExtensionsINI.append(EXTENSIONS_INI); + +// Enable more extensive EM logging +Services.prefs.setBoolPref("extensions.logging.enabled", true); + +// By default only load extensions from the profile install location +Services.prefs.setIntPref("extensions.enabledScopes", AddonManager.SCOPE_PROFILE); + +// By default don't disable add-ons from any scope +Services.prefs.setIntPref("extensions.autoDisableScopes", 0); + +// By default, don't cache add-ons in AddonRepository.jsm +Services.prefs.setBoolPref("extensions.getAddons.cache.enabled", false); + +// Disable the compatibility updates window by default +Services.prefs.setBoolPref("extensions.showMismatchUI", false); + +// Point update checks to the local machine for fast failures +Services.prefs.setCharPref("extensions.update.url", "http://127.0.0.1/updateURL"); +Services.prefs.setCharPref("extensions.update.background.url", "http://127.0.0.1/updateBackgroundURL"); +Services.prefs.setCharPref("extensions.blocklist.url", "http://127.0.0.1/blocklistURL"); + +// By default ignore bundled add-ons +Services.prefs.setBoolPref("extensions.installDistroAddons", false); + +// By default use strict compatibility +Services.prefs.setBoolPref("extensions.strictCompatibility", true); + +// By default, set min compatible versions to 0 +Services.prefs.setCharPref(PREF_EM_MIN_COMPAT_APP_VERSION, "0"); +Services.prefs.setCharPref(PREF_EM_MIN_COMPAT_PLATFORM_VERSION, "0"); + +// Register a temporary directory for the tests. +const gTmpD = gProfD.clone(); +gTmpD.append("temp"); +gTmpD.create(AM_Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); +registerDirectory("TmpD", gTmpD); + +// Write out an empty blocklist.xml file to the profile to ensure nothing +// is blocklisted by default +var blockFile = gProfD.clone(); +blockFile.append("blocklist.xml"); +var stream = AM_Cc["@mozilla.org/network/file-output-stream;1"]. + createInstance(AM_Ci.nsIFileOutputStream); +stream.init(blockFile, FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | FileUtils.MODE_TRUNCATE, + FileUtils.PERMS_FILE, 0); + +var data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + + "<blocklist xmlns=\"http://www.mozilla.org/2006/addons-blocklist\">\n" + + "</blocklist>\n"; +stream.write(data, data.length); +stream.close(); + +// Copies blocklistFile (an nsIFile) to gProfD/blocklist.xml. +function copyBlocklistToProfile(blocklistFile) { + var dest = gProfD.clone(); + dest.append("blocklist.xml"); + if (dest.exists()) + dest.remove(false); + blocklistFile.copyTo(gProfD, "blocklist.xml"); + dest.lastModifiedTime = Date.now(); +} + +// Throw a failure and attempt to abandon the test if it looks like it is going +// to timeout +function timeout() { + timer = null; + do_throw("Test ran longer than " + TIMEOUT_MS + "ms"); + + // Attempt to bail out of the test + do_test_finished(); +} + +var timer = AM_Cc["@mozilla.org/timer;1"].createInstance(AM_Ci.nsITimer); +timer.init(timeout, TIMEOUT_MS, AM_Ci.nsITimer.TYPE_ONE_SHOT); + +// Make sure that a given path does not exist +function pathShouldntExist(aPath) { + if (aPath.exists()) { + do_throw("Test cleanup: path " + aPath.path + " exists when it should not"); + } +} + +do_register_cleanup(function addon_cleanup() { + if (timer) + timer.cancel(); + + for (let file of temp_xpis) { + if (file.exists()) + file.remove(false); + } + + // Check that the temporary directory is empty + var dirEntries = gTmpD.directoryEntries + .QueryInterface(AM_Ci.nsIDirectoryEnumerator); + var entry; + while ((entry = dirEntries.nextFile)) { + do_throw("Found unexpected file in temporary directory: " + entry.leafName); + } + dirEntries.close(); + + var testDir = gProfD.clone(); + testDir.append("extensions"); + testDir.append("trash"); + pathShouldntExist(testDir); + + testDir.leafName = "staged"; + pathShouldntExist(testDir); + + testDir.leafName = "staged-xpis"; + pathShouldntExist(testDir); + + 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) {} +}); + +/** + * Handler function that responds with the interpolated + * static file associated to the URL specified by request.path. + * This replaces the %PORT% entries in the file with the actual + * value of the running server's port (stored in gPort). + */ +function interpolateAndServeFile(request, response) { + try { + let file = gUrlToFileMap[request.path]; + var data = ""; + var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"]. + createInstance(Components.interfaces.nsIFileInputStream); + var cstream = Components.classes["@mozilla.org/intl/converter-input-stream;1"]. + createInstance(Components.interfaces.nsIConverterInputStream); + fstream.init(file, -1, 0, 0); + cstream.init(fstream, "UTF-8", 0, 0); + + let str = {}; + let read = 0; + do { + // read as much as we can and put it in str.value + read = cstream.readString(0xffffffff, str); + data += str.value; + } while (read != 0); + data = data.replace(/%PORT%/g, gPort); + + response.write(data); + } catch (e) { + do_throw("Exception while serving interpolated file."); + } finally { + cstream.close(); // this closes fstream as well + } +} + +/** + * Sets up a path handler for the given URL and saves the + * corresponding file in the global url -> file map. + * + * @param url + * the actual URL + * @param file + * nsILocalFile representing a static file + */ +function mapUrlToFile(url, file, server) { + server.registerPathHandler(url, interpolateAndServeFile); + gUrlToFileMap[url] = file; +} + +function mapFile(path, server) { + mapUrlToFile(path, do_get_file(path), server); +} + +/** + * Take out the port number in an URL + * + * @param url + * String that represents an URL with a port number in it + */ +function remove_port(url) { + if (typeof url === "string") + return url.replace(/:\d+/, ""); + return url; +} +// Wrap a function (typically a callback) to catch and report exceptions +function do_exception_wrap(func) { + return function() { + try { + func.apply(null, arguments); + } + catch(e) { + do_report_unexpected_exception(e); + } + }; +} + +/** + * Change the schema version of the JSON extensions database + */ +function changeXPIDBVersion(aNewVersion) { + let jData = loadJSON(gExtensionsJSON); + jData.schemaVersion = aNewVersion; + saveJSON(jData, gExtensionsJSON); +} + +/** + * Load a file into a string + */ +function loadFile(aFile) { + let data = ""; + let fstream = Components.classes["@mozilla.org/network/file-input-stream;1"]. + createInstance(Components.interfaces.nsIFileInputStream); + let cstream = Components.classes["@mozilla.org/intl/converter-input-stream;1"]. + createInstance(Components.interfaces.nsIConverterInputStream); + fstream.init(aFile, -1, 0, 0); + cstream.init(fstream, "UTF-8", 0, 0); + let str = {}; + let read = 0; + do { + read = cstream.readString(0xffffffff, str); // read as much as we can and put it in str.value + data += str.value; + } while (read != 0); + cstream.close(); + return data; +} + +/** + * Raw load of a JSON file + */ +function loadJSON(aFile) { + let data = loadFile(aFile); + do_print("Loaded JSON file " + aFile.path); + return(JSON.parse(data)); +} + +/** + * Raw save of a JSON blob to file + */ +function saveJSON(aData, aFile) { + do_print("Starting to save JSON file " + aFile.path); + let stream = FileUtils.openSafeFileOutputStream(aFile); + let converter = AM_Cc["@mozilla.org/intl/converter-output-stream;1"]. + createInstance(AM_Ci.nsIConverterOutputStream); + converter.init(stream, "UTF-8", 0, 0x0000); + // XXX pretty print the JSON while debugging + converter.writeString(JSON.stringify(aData, null, 2)); + converter.flush(); + // nsConverterOutputStream doesn't finish() safe output streams on close() + FileUtils.closeSafeFileOutputStream(stream); + converter.close(); + do_print("Done saving JSON file " + aFile.path); +} + +/** + * Create a callback function that calls do_execute_soon on an actual callback and arguments + */ +function callback_soon(aFunction) { + return function(...args) { + do_execute_soon(function() { + aFunction.apply(null, args); + }, aFunction.name ? "delayed callback " + aFunction.name : "delayed callback"); + } +} + +/** + * A promise-based variant of AddonManager.getAddonsByIDs. + * + * @param {array} list As the first argument of AddonManager.getAddonsByIDs + * @return {promise} + * @resolve {array} The list of add-ons sent by AddonManaget.getAddonsByIDs to + * its callback. + */ +function promiseAddonsByIDs(list) { + return new Promise(resolve => AddonManager.getAddonsByIDs(list, resolve)); +} + +/** + * A promise-based variant of AddonManager.getAddonByID. + * + * @param {string} aId The ID of the add-on. + * @return {promise} + * @resolve {AddonWrapper} The corresponding add-on, or null. + */ +function promiseAddonByID(aId) { + return new Promise(resolve => AddonManager.getAddonByID(aId, resolve)); +} + +/** + * A promise-based variant of AddonManager.getAddonsWithOperationsByTypes + * + * @param {array} aTypes The first argument to + * AddonManager.getAddonsWithOperationsByTypes + * @return {promise} + * @resolve {array} The list of add-ons sent by + * AddonManaget.getAddonsWithOperationsByTypes to its callback. + */ +function promiseAddonsWithOperationsByTypes(aTypes) { + return new Promise(resolve => AddonManager.getAddonsWithOperationsByTypes(aTypes, resolve)); +} + +/** + * Returns a promise that will be resolved when an add-on update check is + * complete. The value resolved will be an AddonInstall if a new version was + * found. + */ +function promiseFindAddonUpdates(addon, reason = AddonManager.UPDATE_WHEN_PERIODIC_UPDATE) { + return new Promise((resolve, reject) => { + addon.findUpdates({ + install: null, + + onUpdateAvailable: function(addon, install) { + this.install = install; + }, + + onUpdateFinished: function(addon, error) { + if (error == AddonManager.UPDATE_STATUS_NO_ERROR) + resolve(this.install); + else + reject(error); + } + }, reason); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/head_unpack.js b/toolkit/mozapps/extensions/test/xpcshell/head_unpack.js new file mode 100644 index 000000000..088898b41 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/head_unpack.js @@ -0,0 +1,2 @@ +Services.prefs.setBoolPref("extensions.alwaysUnpack", true); +TEST_UNPACKED = true; diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository.js b/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository.js new file mode 100644 index 000000000..3f51d7226 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository.js @@ -0,0 +1,625 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests AddonRepository.jsm + +Components.utils.import("resource://gre/modules/addons/AddonRepository.jsm"); + +Components.utils.import("resource://testing-common/httpd.js"); +var gServer = new HttpServer(); +gServer.start(-1); + +const PREF_GETADDONS_BROWSEADDONS = "extensions.getAddons.browseAddons"; +const PREF_GETADDONS_BROWSERECOMMENDED = "extensions.getAddons.recommended.browseURL"; +const PREF_GETADDONS_GETRECOMMENDED = "extensions.getAddons.recommended.url"; +const PREF_GETADDONS_BROWSESEARCHRESULTS = "extensions.getAddons.search.browseURL"; +const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url"; + +const PORT = gServer.identity.primaryPort; +const BASE_URL = "http://localhost:" + PORT; +const DEFAULT_URL = "about:blank"; + +gPort = PORT; + +// Path to source URI of installed add-on +const INSTALL_URL1 = "/addons/test_AddonRepository_1.xpi"; +// Path to source URI of installing add-on +const INSTALL_URL2 = "/addons/test_AddonRepository_2.xpi"; +// Path to source URI of non-active add-on (state = STATE_AVAILABLE) +const INSTALL_URL3 = "/addons/test_AddonRepository_3.xpi"; + +// Properties of an individual add-on that should be checked +// Note: name is checked separately +var ADDON_PROPERTIES = ["id", "type", "version", "creator", "developers", + "description", "fullDescription", "developerComments", + "eula", "iconURL", "icons", "screenshots", "homepageURL", + "supportURL", "contributionURL", "contributionAmount", + "averageRating", "reviewCount", "reviewURL", + "totalDownloads", "weeklyDownloads", "dailyUsers", + "sourceURI", "repositoryStatus", "size", "updateDate", + "purchaseURL", "purchaseAmount", "purchaseDisplayAmount", + "compatibilityOverrides"]; + +// Results of getAddonsByIDs +var GET_RESULTS = [{ + id: "test1@tests.mozilla.org", + type: "extension", + version: "1.1", + creator: { + name: "Test Creator 1", + url: BASE_URL + "/creator1.html" + }, + developers: [{ + name: "Test Developer 1", + url: BASE_URL + "/developer1.html" + }], + description: "Test Summary 1", + fullDescription: "Test Description 1", + developerComments: "Test Developer Comments 1", + eula: "Test EULA 1", + iconURL: BASE_URL + "/icon1.png", + icons: { "32": BASE_URL + "/icon1.png" }, + screenshots: [{ + url: BASE_URL + "/full1-1.png", + width: 400, + height: 300, + thumbnailURL: BASE_URL + "/thumbnail1-1.png", + thumbnailWidth: 200, + thumbnailHeight: 150, + caption: "Caption 1 - 1" + }, { + url: BASE_URL + "/full2-1.png", + thumbnailURL: BASE_URL + "/thumbnail2-1.png", + caption: "Caption 2 - 1" + }], + homepageURL: BASE_URL + "/learnmore1.html", + learnmoreURL: BASE_URL + "/learnmore1.html", + supportURL: BASE_URL + "/support1.html", + contributionURL: BASE_URL + "/meetDevelopers1.html", + contributionAmount: "$11.11", + averageRating: 4, + reviewCount: 1111, + reviewURL: BASE_URL + "/review1.html", + totalDownloads: 2222, + weeklyDownloads: 3333, + dailyUsers: 4444, + sourceURI: BASE_URL + INSTALL_URL2, + repositoryStatus: 8, + size: 5555, + updateDate: new Date(1265033045000), + compatibilityOverrides: [{ + type: "incompatible", + minVersion: 0.1, + maxVersion: 0.2, + appID: "xpcshell@tests.mozilla.org", + appMinVersion: 3.0, + appMaxVersion: 4.0 + }, { + type: "incompatible", + minVersion: 0.2, + maxVersion: 0.3, + appID: "xpcshell@tests.mozilla.org", + appMinVersion: 5.0, + appMaxVersion: 6.0 + }] +}, { + id: "test_AddonRepository_1@tests.mozilla.org", + type: "theme", + version: "1.4", + repositoryStatus: 9999, + icons: {} +}]; + +// Results of retrieveRecommendedAddons and searchAddons +var SEARCH_RESULTS = [{ + id: "test1@tests.mozilla.org", + type: "extension", + version: "1.1", + creator: { + name: "Test Creator 1", + url: BASE_URL + "/creator1.html" + }, + repositoryStatus: 8, + sourceURI: BASE_URL + "/test1.xpi", + icons: {} +}, { + id: "test2@tests.mozilla.org", + type: "extension", + version: "1.2", + creator: { + name: "Test Creator 2", + url: BASE_URL + "/creator2.html" + }, + developers: [{ + name: "Test Developer 2", + url: BASE_URL + "/developer2.html" + }], + description: "Test Summary 2\n\nparagraph", + fullDescription: "Test Description 2\nnewline", + developerComments: "Test Developer\nComments 2", + eula: "Test EULA 2", + iconURL: BASE_URL + "/icon2-32.png", + icons: { + "32": BASE_URL + "/icon2-32.png", + "48": BASE_URL + "/icon2-48.png", + "64": BASE_URL + "/icon2-64.png" + }, + screenshots: [{ + url: BASE_URL + "/full1-2.png", + thumbnailURL: BASE_URL + "/thumbnail1-2.png" + }, { + url: BASE_URL + "/full2-2.png", + thumbnailURL: BASE_URL + "/thumbnail2-2.png", + caption: "Caption 2" + }], + homepageURL: BASE_URL + "/learnmore2.html", + supportURL: BASE_URL + "/support2.html", + learnmoreURL: BASE_URL + "/learnmore2.html", + contributionURL: BASE_URL + "/meetDevelopers2.html", + contributionAmount: null, + repositoryStatus: 4, + sourceURI: BASE_URL + "/test2.xpi" +}, { + id: "test3@tests.mozilla.org", + type: "theme", + version: "1.3", + creator: { + name: "Test Creator 3", + url: BASE_URL + "/creator3.html" + }, + developers: [{ + name: "First Test Developer 3", + url: BASE_URL + "/developer1-3.html" + }, { + name: "Second Test Developer 3", + url: BASE_URL + "/developer2-3.html" + }], + description: "Test Summary 3", + fullDescription: "Test Description 3\n\n List item 1\n List item 2", + developerComments: "Test Developer Comments 3", + eula: "Test EULA 3", + iconURL: BASE_URL + "/icon3.png", + icons: { "32": BASE_URL + "/icon3.png" }, + screenshots: [{ + url: BASE_URL + "/full1-3.png", + thumbnailURL: BASE_URL + "/thumbnail1-3.png", + caption: "Caption 1 - 3" + }, { + url: BASE_URL + "/full2-3.png", + caption: "Caption 2 - 3" + }, { + url: BASE_URL + "/full3-3.png", + thumbnailURL: BASE_URL + "/thumbnail3-3.png", + caption: "Caption 3 - 3" + }], + homepageURL: BASE_URL + "/homepage3.html", + supportURL: BASE_URL + "/support3.html", + learnmoreURL: BASE_URL + "/learnmore3.html", + contributionURL: BASE_URL + "/meetDevelopers3.html", + contributionAmount: "$11.11", + averageRating: 2, + reviewCount: 1111, + reviewURL: BASE_URL + "/review3.html", + totalDownloads: 2222, + weeklyDownloads: 3333, + dailyUsers: 4444, + sourceURI: BASE_URL + "/test3.xpi", + repositoryStatus: 8, + size: 5555, + updateDate: new Date(1265033045000), + +}, { + id: "purchase1@tests.mozilla.org", + type: "extension", + version: "2.0", + creator: { + name: "Test Creator - Last Passing", + url: BASE_URL + "/creatorLastPassing.html" + }, + averageRating: 5, + repositoryStatus: 4, + purchaseURL: "http://localhost:" + PORT + "/purchaseURL1", + purchaseAmount: 5, + purchaseDisplayAmount: "$5", + icons: {} +}, { + id: "purchase2@tests.mozilla.org", + type: "extension", + version: "2.0", + creator: { + name: "Test Creator - Last Passing", + url: BASE_URL + "/creatorLastPassing.html" + }, + averageRating: 5, + repositoryStatus: 4, + purchaseURL: "http://localhost:" + PORT + "/purchaseURL2", + purchaseAmount: 10, + purchaseDisplayAmount: "$10", + icons: {} +}, { + id: "test-lastPassing@tests.mozilla.org", + type: "extension", + version: "2.0", + creator: { + name: "Test Creator - Last Passing", + url: BASE_URL + "/creatorLastPassing.html" + }, + averageRating: 5, + repositoryStatus: 4, + sourceURI: BASE_URL + "/addons/test_AddonRepository_3.xpi", + icons: {} +}]; + +const TOTAL_RESULTS = 1111; +const MAX_RESULTS = SEARCH_RESULTS.length; + +// Used to differentiate between testing that a search success +// or a search failure for retrieveRecommendedAddons and searchAddons +const FAILED_MAX_RESULTS = 9999; + +// Values for testing AddonRepository.getAddonsByIDs() +var GET_TEST = { + preference: PREF_GETADDONS_BYIDS, + preferenceValue: BASE_URL + "/%OS%/%VERSION%/%API_VERSION%/" + + "%API_VERSION%/%IDS%", + failedIDs: ["test1@tests.mozilla.org"], + failedURL: "/XPCShell/1/1.5/1.5/test1%40tests.mozilla.org", + successfulIDs: ["test1@tests.mozilla.org", + "{00000000-1111-2222-3333-444444444444}", + "test_AddonRepository_1@tests.mozilla.org"], + successfulURL: "/XPCShell/1/1.5/1.5/test1%40tests.mozilla.org," + + "%7B00000000-1111-2222-3333-444444444444%7D," + + "test_AddonRepository_1%40tests.mozilla.org" +}; + +// Values for testing AddonRepository.retrieveRecommendedAddons() +var RECOMMENDED_TEST = { + preference: PREF_GETADDONS_GETRECOMMENDED, + preferenceValue: BASE_URL + "/%OS%/%VERSION%/%API_VERSION%/" + + "%API_VERSION%/%MAX_RESULTS%", + failedURL: "/XPCShell/1/1.5/1.5/" + (2 * FAILED_MAX_RESULTS), + successfulURL: "/XPCShell/1/1.5/1.5/" + (2 * MAX_RESULTS) +}; + +// Values for testing AddonRepository.searchAddons() +var SEARCH_TEST = { + searchTerms: "odd=search:with&weird\"characters", + preference: PREF_GETADDONS_GETSEARCHRESULTS, + preferenceValue: BASE_URL + "/%OS%/%VERSION%/%API_VERSION%/" + + "%API_VERSION%/%MAX_RESULTS%/%TERMS%", + failedURL: "/XPCShell/1/1.5/1.5/" + (2 * FAILED_MAX_RESULTS) + + "/odd%3Dsearch%3Awith%26weird%22characters", + successfulURL: "/XPCShell/1/1.5/1.5/" + (2 * MAX_RESULTS) + + "/odd%3Dsearch%3Awith%26weird%22characters" +}; + +// Test that actual results and expected results are equal +function check_results(aActualAddons, aExpectedAddons, aAddonCount, aInstallNull) { + do_check_false(AddonRepository.isSearching); + + do_check_eq(aActualAddons.length, aAddonCount); + do_check_addons(aActualAddons, aExpectedAddons, ADDON_PROPERTIES); + + // Additional tests + aActualAddons.forEach(function check_each_addon(aActualAddon) { + // Separately check name so better messages are output when test fails + if (aActualAddon.name == "FAIL") + do_throw(aActualAddon.id + " - " + aActualAddon.description); + if (aActualAddon.name != "PASS") + do_throw(aActualAddon.id + " - " + "invalid add-on name " + aActualAddon.name); + + do_check_eq(aActualAddon.install == null, !!aInstallNull || !aActualAddon.sourceURI); + + // Check that sourceURI property consistent within actual addon + if (aActualAddon.install) + do_check_eq(aActualAddon.install.sourceURI.spec, aActualAddon.sourceURI.spec); + }); +} + +// Complete a search, also testing cancelSearch() and isSearching +function complete_search(aSearch, aSearchCallback) { + var failCallback = { + searchSucceeded: function(addons, length, total) { + do_throw("failCallback.searchSucceeded should not be called"); + end_test(); + }, + + searchFailed: function() { + do_throw("failCallback.searchFailed should not be called"); + end_test(); + } + }; + + var callbackCalled = false; + var testCallback = { + searchSucceeded: function(addons, length, total) { + do_throw("testCallback.searchSucceeded should not be called"); + end_test(); + }, + + searchFailed: function() { + callbackCalled = true; + } + }; + + // Should fail because cancelled it immediately + aSearch(failCallback); + do_check_true(AddonRepository.isSearching); + AddonRepository.cancelSearch(); + do_check_false(AddonRepository.isSearching); + + aSearch(aSearchCallback); + do_check_true(AddonRepository.isSearching); + + // searchFailed should be called immediately because already searching + aSearch(testCallback); + do_check_true(callbackCalled); + do_check_true(AddonRepository.isSearching); +} + + +function run_test() { + // Setup for test + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); + + startupManager(); + + // Install an add-on so can check that it isn't returned in the results + installAllFiles([do_get_addon("test_AddonRepository_1")], function addon_1_install_callback() { + restartManager(); + + // Register other add-on XPI files + gServer.registerFile(INSTALL_URL2, + do_get_addon("test_AddonRepository_2")); + gServer.registerFile(INSTALL_URL3, + do_get_addon("test_AddonRepository_3")); + + // Register files used to test search failure + mapUrlToFile(GET_TEST.failedURL, + do_get_file("data/test_AddonRepository_failed.xml"), + gServer); + mapUrlToFile(RECOMMENDED_TEST.failedURL, + do_get_file("data/test_AddonRepository_failed.xml"), + gServer); + mapUrlToFile(SEARCH_TEST.failedURL, + do_get_file("data/test_AddonRepository_failed.xml"), + gServer); + + // Register files used to test search success + mapUrlToFile(GET_TEST.successfulURL, + do_get_file("data/test_AddonRepository_getAddonsByIDs.xml"), + gServer); + mapUrlToFile(RECOMMENDED_TEST.successfulURL, + do_get_file("data/test_AddonRepository.xml"), + gServer); + mapUrlToFile(SEARCH_TEST.successfulURL, + do_get_file("data/test_AddonRepository.xml"), + gServer); + + // Create an active AddonInstall so can check that it isn't returned in the results + AddonManager.getInstallForURL(BASE_URL + INSTALL_URL2, function addon_2_get(aInstall) { + try { + aInstall.install(); + } + catch(e) { + do_print("Failed to install add-on " + aInstall.sourceURI.spec); + do_report_unexpected_exception(e); + } + + // Create a non-active AddonInstall so can check that it is returned in the results + AddonManager.getInstallForURL(BASE_URL + INSTALL_URL3, + run_test_1, "application/x-xpinstall"); + }, "application/x-xpinstall"); + }); +} + +function end_test() { + let testDir = gProfD.clone(); + testDir.append("extensions"); + testDir.append("staged"); + gServer.stop(function() { + function loop() { + if (!testDir.exists()) { + do_print("Staged directory has been cleaned up"); + do_test_finished(); + } + do_print("Waiting 1 second until cleanup is complete"); + do_timeout(1000, loop); + } + loop(); + }); +} + +// Tests homepageURL, getRecommendedURL() and getSearchURL() +function run_test_1() { + function check_urls(aPreference, aGetURL, aTests) { + aTests.forEach(function(aTest) { + Services.prefs.setCharPref(aPreference, aTest.preferenceValue); + do_check_eq(aGetURL(aTest), aTest.expectedURL); + }); + } + + var urlTests = [{ + preferenceValue: BASE_URL, + expectedURL: BASE_URL + }, { + preferenceValue: BASE_URL + "/%OS%/%VERSION%", + expectedURL: BASE_URL + "/XPCShell/1" + }]; + + // Extra tests for AddonRepository.getSearchURL(); + var searchURLTests = [{ + searchTerms: "test", + preferenceValue: BASE_URL + "/search?q=%TERMS%", + expectedURL: BASE_URL + "/search?q=test" + }, { + searchTerms: "test search", + preferenceValue: BASE_URL + "/%TERMS%", + expectedURL: BASE_URL + "/test%20search" + }, { + searchTerms: "odd=search:with&weird\"characters", + preferenceValue: BASE_URL + "/%TERMS%", + expectedURL: BASE_URL + "/odd%3Dsearch%3Awith%26weird%22characters" + }]; + + // Setup tests for homepageURL, getRecommendedURL() and getSearchURL() + var tests = [{ + initiallyUndefined: true, + preference: PREF_GETADDONS_BROWSEADDONS, + urlTests: urlTests, + getURL: function() AddonRepository.homepageURL + }, { + initiallyUndefined: true, + preference: PREF_GETADDONS_BROWSERECOMMENDED, + urlTests: urlTests, + getURL: function() AddonRepository.getRecommendedURL() + }, { + initiallyUndefined: false, + preference: PREF_GETADDONS_BROWSESEARCHRESULTS, + urlTests: urlTests.concat(searchURLTests), + getURL: function getSearchURL(aTest) { + var searchTerms = aTest && aTest.searchTerms ? aTest.searchTerms + : "unused terms"; + return AddonRepository.getSearchURL(searchTerms); + } + }]; + + tests.forEach(function url_test(aTest) { + if (aTest.initiallyUndefined) { + // Preference is not defined by default + do_check_eq(Services.prefs.getPrefType(aTest.preference), + Services.prefs.PREF_INVALID); + do_check_eq(aTest.getURL(), DEFAULT_URL); + } + + check_urls(aTest.preference, aTest.getURL, aTest.urlTests); + }); + + run_test_getAddonsByID_fails(); +} + +// Tests failure of AddonRepository.getAddonsByIDs() +function run_test_getAddonsByID_fails() { + Services.prefs.setCharPref(GET_TEST.preference, GET_TEST.preferenceValue); + var callback = { + searchSucceeded: function(aAddonsList, aAddonCount, aTotalResults) { + do_throw("searchAddons should not have succeeded"); + end_test(); + }, + + searchFailed: function() { + do_check_false(AddonRepository.isSearching); + run_test_getAddonsByID_succeeds(); + } + }; + + complete_search(function complete_search_fail_callback(aCallback) { + AddonRepository.getAddonsByIDs(GET_TEST.failedIDs, aCallback); + }, callback); +} + +// Tests success of AddonRepository.getAddonsByIDs() +function run_test_getAddonsByID_succeeds() { + var callback = { + searchSucceeded: function(aAddonsList, aAddonCount, aTotalResults) { + do_check_eq(aTotalResults, -1); + check_results(aAddonsList, GET_RESULTS, aAddonCount, true); + run_test_retrieveRecommended_fails(); + }, + + searchFailed: function() { + do_throw("searchAddons should not have failed"); + end_test(); + } + }; + + complete_search(function complete_search_succeed_callback(aCallback) { + AddonRepository.getAddonsByIDs(GET_TEST.successfulIDs, aCallback); + }, callback); +} + +// Tests failure of AddonRepository.retrieveRecommendedAddons() +function run_test_retrieveRecommended_fails() { + Services.prefs.setCharPref(RECOMMENDED_TEST.preference, + RECOMMENDED_TEST.preferenceValue); + var callback = { + searchSucceeded: function(aAddonsList, aAddonCount, aTotalResults) { + do_throw("retrieveRecommendedAddons should not have succeeded"); + end_test(); + }, + + searchFailed: function() { + do_check_false(AddonRepository.isSearching); + run_test_retrieveRecommended_succeed(); + } + }; + + complete_search(function retrieveRecommended_failing_callback(aCallback) { + AddonRepository.retrieveRecommendedAddons(FAILED_MAX_RESULTS, aCallback); + }, callback); +} + +// Tests success of AddonRepository.retrieveRecommendedAddons() +function run_test_retrieveRecommended_succeed() { + var callback = { + searchSucceeded: function(aAddonsList, aAddonCount, aTotalResults) { + do_check_eq(aTotalResults, -1); + check_results(aAddonsList, SEARCH_RESULTS, aAddonCount); + run_test_searchAddons_fails(); + }, + + searchFailed: function() { + do_throw("retrieveRecommendedAddons should not have failed"); + end_test(); + } + }; + + complete_search(function retrieveRecommended_succeed_callback(aCallback) { + AddonRepository.retrieveRecommendedAddons(MAX_RESULTS, aCallback); + }, callback); +} + +// Tests failure of AddonRepository.searchAddons() +function run_test_searchAddons_fails() { + Services.prefs.setCharPref(SEARCH_TEST.preference, SEARCH_TEST.preferenceValue); + var callback = { + searchSucceeded: function(aAddonsList, aAddonCount, aTotalResults) { + do_throw("searchAddons should not have succeeded"); + end_test(); + }, + + searchFailed: function() { + do_check_false(AddonRepository.isSearching); + run_test_searchAddons_succeeds(); + } + }; + + complete_search(function(aCallback) { + var searchTerms = SEARCH_TEST.searchTerms; + AddonRepository.searchAddons(searchTerms, FAILED_MAX_RESULTS, aCallback); + }, callback); +} + +// Tests success of AddonRepository.searchAddons() +function run_test_searchAddons_succeeds() { + var callback = { + searchSucceeded: function(aAddonsList, aAddonCount, aTotalResults) { + do_check_eq(aTotalResults, TOTAL_RESULTS); + check_results(aAddonsList, SEARCH_RESULTS, aAddonCount); + end_test(); + }, + + searchFailed: function() { + do_throw("searchAddons should not have failed"); + end_test(); + } + }; + + complete_search(function(aCallback) { + var searchTerms = SEARCH_TEST.searchTerms; + AddonRepository.searchAddons(searchTerms, MAX_RESULTS, aCallback); + }, callback); +} + diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_cache.js b/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_cache.js new file mode 100644 index 000000000..0327ab6d0 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_cache.js @@ -0,0 +1,710 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests caching in AddonRepository.jsm + +Components.utils.import("resource://gre/modules/addons/AddonRepository.jsm"); + +Components.utils.import("resource://testing-common/httpd.js"); +let gServer; + +const PORT = 4444; +const BASE_URL = "http://localhost:" + PORT; + +const PREF_GETADDONS_CACHE_ENABLED = "extensions.getAddons.cache.enabled"; +const PREF_GETADDONS_CACHE_TYPES = "extensions.getAddons.cache.types"; +const GETADDONS_RESULTS = BASE_URL + "/data/test_AddonRepository_cache.xml"; +const GETADDONS_EMPTY = BASE_URL + "/data/test_AddonRepository_empty.xml"; +const GETADDONS_FAILED = BASE_URL + "/data/test_AddonRepository_failed.xml"; + +const FILE_DATABASE = "addons.json"; +const ADDON_NAMES = ["test_AddonRepository_1", + "test_AddonRepository_2", + "test_AddonRepository_3"]; +const ADDON_IDS = ADDON_NAMES.map(function(aName) aName + "@tests.mozilla.org"); +const ADDON_FILES = ADDON_NAMES.map(do_get_addon); + +const PREF_ADDON0_CACHE_ENABLED = "extensions." + ADDON_IDS[0] + ".getAddons.cache.enabled"; +const PREF_ADDON1_CACHE_ENABLED = "extensions." + ADDON_IDS[1] + ".getAddons.cache.enabled"; + +// Properties of an individual add-on that should be checked +// Note: size and updateDate are checked separately +const ADDON_PROPERTIES = ["id", "type", "name", "version", "creator", + "developers", "translators", "contributors", + "description", "fullDescription", + "developerComments", "eula", "iconURL", "icons", + "screenshots", "homepageURL", "supportURL", + "optionsURL", "aboutURL", "contributionURL", + "contributionAmount", "averageRating", "reviewCount", + "reviewURL", "totalDownloads", "weeklyDownloads", + "dailyUsers", "sourceURI", "repositoryStatus", + "compatibilityOverrides"]; + +// The size and updateDate properties are annoying to test for XPI add-ons. +// However, since we only care about whether the repository value vs. the +// XPI value is used, we can just test if the property value matches +// the repository value +const REPOSITORY_SIZE = 9; +const REPOSITORY_UPDATEDATE = 9; + +// Get the URI of a subfile locating directly in the folder of +// the add-on corresponding to the specified id +function get_subfile_uri(aId, aFilename) { + let file = gProfD.clone(); + file.append("extensions"); + return do_get_addon_root_uri(file, aId) + aFilename; +} + + +// Expected repository add-ons +const REPOSITORY_ADDONS = [{ + id: ADDON_IDS[0], + type: "extension", + name: "Repo Add-on 1", + version: "2.1", + creator: { + name: "Repo Add-on 1 - Creator", + url: BASE_URL + "/repo/1/creator.html" + }, + developers: [{ + name: "Repo Add-on 1 - First Developer", + url: BASE_URL + "/repo/1/firstDeveloper.html" + }, { + name: "Repo Add-on 1 - Second Developer", + url: BASE_URL + "/repo/1/secondDeveloper.html" + }], + description: "Repo Add-on 1 - Description\nSecond line", + fullDescription: "Repo Add-on 1 - Full Description & some extra", + developerComments: "Repo Add-on 1\nDeveloper Comments", + eula: "Repo Add-on 1 - EULA", + iconURL: BASE_URL + "/repo/1/icon.png", + icons: { "32": BASE_URL + "/repo/1/icon.png" }, + homepageURL: BASE_URL + "/repo/1/homepage.html", + supportURL: BASE_URL + "/repo/1/support.html", + contributionURL: BASE_URL + "/repo/1/meetDevelopers.html", + contributionAmount: "$11.11", + averageRating: 1, + reviewCount: 1111, + reviewURL: BASE_URL + "/repo/1/review.html", + totalDownloads: 2221, + weeklyDownloads: 3331, + dailyUsers: 4441, + sourceURI: BASE_URL + "/repo/1/install.xpi", + repositoryStatus: 4, + compatibilityOverrides: [{ + type: "incompatible", + minVersion: 0.1, + maxVersion: 0.2, + appID: "xpcshell@tests.mozilla.org", + appMinVersion: 3.0, + appMaxVersion: 4.0 + }, { + type: "incompatible", + minVersion: 0.2, + maxVersion: 0.3, + appID: "xpcshell@tests.mozilla.org", + appMinVersion: 5.0, + appMaxVersion: 6.0 + }] +}, { + id: ADDON_IDS[1], + type: "theme", + name: "Repo Add-on 2", + version: "2.2", + creator: { + name: "Repo Add-on 2 - Creator", + url: BASE_URL + "/repo/2/creator.html" + }, + developers: [{ + name: "Repo Add-on 2 - First Developer", + url: BASE_URL + "/repo/2/firstDeveloper.html" + }, { + name: "Repo Add-on 2 - Second Developer", + url: BASE_URL + "/repo/2/secondDeveloper.html" + }], + description: "Repo Add-on 2 - Description", + fullDescription: "Repo Add-on 2 - Full Description", + developerComments: "Repo Add-on 2 - Developer Comments", + eula: "Repo Add-on 2 - EULA", + iconURL: BASE_URL + "/repo/2/icon.png", + icons: { "32": BASE_URL + "/repo/2/icon.png" }, + screenshots: [{ + url: BASE_URL + "/repo/2/firstFull.png", + thumbnailURL: BASE_URL + "/repo/2/firstThumbnail.png", + caption: "Repo Add-on 2 - First Caption" + } , { + url: BASE_URL + "/repo/2/secondFull.png", + thumbnailURL: BASE_URL + "/repo/2/secondThumbnail.png", + caption: "Repo Add-on 2 - Second Caption" + }], + homepageURL: BASE_URL + "/repo/2/homepage.html", + supportURL: BASE_URL + "/repo/2/support.html", + contributionURL: BASE_URL + "/repo/2/meetDevelopers.html", + contributionAmount: null, + averageRating: 2, + reviewCount: 1112, + reviewURL: BASE_URL + "/repo/2/review.html", + totalDownloads: 2222, + weeklyDownloads: 3332, + dailyUsers: 4442, + sourceURI: BASE_URL + "/repo/2/install.xpi", + repositoryStatus: 9 +}, { + id: ADDON_IDS[2], + type: "theme", + name: "Repo Add-on 3", + version: "2.3", + iconURL: BASE_URL + "/repo/3/icon.png", + icons: { "32": BASE_URL + "/repo/3/icon.png" }, + screenshots: [{ + url: BASE_URL + "/repo/3/firstFull.png", + thumbnailURL: BASE_URL + "/repo/3/firstThumbnail.png", + caption: "Repo Add-on 3 - First Caption" + } , { + url: BASE_URL + "/repo/3/secondFull.png", + thumbnailURL: BASE_URL + "/repo/3/secondThumbnail.png", + caption: "Repo Add-on 3 - Second Caption" + }] +}]; + + +// Expected add-ons when not using cache +const WITHOUT_CACHE = [{ + id: ADDON_IDS[0], + type: "extension", + name: "XPI Add-on 1", + version: "1.1", + creator: { name: "XPI Add-on 1 - Creator" }, + developers: [{ name: "XPI Add-on 1 - First Developer" }, + { name: "XPI Add-on 1 - Second Developer" }], + translators: [{ name: "XPI Add-on 1 - First Translator" }, + { name: "XPI Add-on 1 - Second Translator" }], + contributors: [{ name: "XPI Add-on 1 - First Contributor" }, + { name: "XPI Add-on 1 - Second Contributor" }], + description: "XPI Add-on 1 - Description", + iconURL: BASE_URL + "/xpi/1/icon.png", + icons: { "32": BASE_URL + "/xpi/1/icon.png" }, + homepageURL: BASE_URL + "/xpi/1/homepage.html", + optionsURL: BASE_URL + "/xpi/1/options.html", + aboutURL: BASE_URL + "/xpi/1/about.html", + sourceURI: NetUtil.newURI(ADDON_FILES[0]).spec +}, { + id: ADDON_IDS[1], + type: "theme", + name: "XPI Add-on 2", + version: "1.2", + sourceURI: NetUtil.newURI(ADDON_FILES[1]).spec, + icons: {} +}, { + id: ADDON_IDS[2], + type: "theme", + name: "XPI Add-on 3", + version: "1.3", + get iconURL () { + return get_subfile_uri(ADDON_IDS[2], "icon.png"); + }, + get icons () { + return { "32": get_subfile_uri(ADDON_IDS[2], "icon.png") }; + }, + screenshots: [{ get url () { return get_subfile_uri(ADDON_IDS[2], "preview.png"); } }], + sourceURI: NetUtil.newURI(ADDON_FILES[2]).spec +}]; + + +// Expected add-ons when using cache +const WITH_CACHE = [{ + id: ADDON_IDS[0], + type: "extension", + name: "XPI Add-on 1", + version: "1.1", + creator: { + name: "Repo Add-on 1 - Creator", + url: BASE_URL + "/repo/1/creator.html" + }, + developers: [{ name: "XPI Add-on 1 - First Developer" }, + { name: "XPI Add-on 1 - Second Developer" }], + translators: [{ name: "XPI Add-on 1 - First Translator" }, + { name: "XPI Add-on 1 - Second Translator" }], + contributors: [{ name: "XPI Add-on 1 - First Contributor" }, + { name: "XPI Add-on 1 - Second Contributor" }], + description: "XPI Add-on 1 - Description", + fullDescription: "Repo Add-on 1 - Full Description & some extra", + developerComments: "Repo Add-on 1\nDeveloper Comments", + eula: "Repo Add-on 1 - EULA", + iconURL: BASE_URL + "/xpi/1/icon.png", + icons: { "32": BASE_URL + "/xpi/1/icon.png" }, + homepageURL: BASE_URL + "/xpi/1/homepage.html", + supportURL: BASE_URL + "/repo/1/support.html", + optionsURL: BASE_URL + "/xpi/1/options.html", + aboutURL: BASE_URL + "/xpi/1/about.html", + contributionURL: BASE_URL + "/repo/1/meetDevelopers.html", + contributionAmount: "$11.11", + averageRating: 1, + reviewCount: 1111, + reviewURL: BASE_URL + "/repo/1/review.html", + totalDownloads: 2221, + weeklyDownloads: 3331, + dailyUsers: 4441, + sourceURI: NetUtil.newURI(ADDON_FILES[0]).spec, + repositoryStatus: 4, + compatibilityOverrides: [{ + type: "incompatible", + minVersion: 0.1, + maxVersion: 0.2, + appID: "xpcshell@tests.mozilla.org", + appMinVersion: 3.0, + appMaxVersion: 4.0 + }, { + type: "incompatible", + minVersion: 0.2, + maxVersion: 0.3, + appID: "xpcshell@tests.mozilla.org", + appMinVersion: 5.0, + appMaxVersion: 6.0 + }] +}, { + id: ADDON_IDS[1], + type: "theme", + name: "XPI Add-on 2", + version: "1.2", + creator: { + name: "Repo Add-on 2 - Creator", + url: BASE_URL + "/repo/2/creator.html" + }, + developers: [{ + name: "Repo Add-on 2 - First Developer", + url: BASE_URL + "/repo/2/firstDeveloper.html" + }, { + name: "Repo Add-on 2 - Second Developer", + url: BASE_URL + "/repo/2/secondDeveloper.html" + }], + description: "Repo Add-on 2 - Description", + fullDescription: "Repo Add-on 2 - Full Description", + developerComments: "Repo Add-on 2 - Developer Comments", + eula: "Repo Add-on 2 - EULA", + iconURL: BASE_URL + "/repo/2/icon.png", + icons: { "32": BASE_URL + "/repo/2/icon.png" }, + screenshots: [{ + url: BASE_URL + "/repo/2/firstFull.png", + thumbnailURL: BASE_URL + "/repo/2/firstThumbnail.png", + caption: "Repo Add-on 2 - First Caption" + } , { + url: BASE_URL + "/repo/2/secondFull.png", + thumbnailURL: BASE_URL + "/repo/2/secondThumbnail.png", + caption: "Repo Add-on 2 - Second Caption" + }], + homepageURL: BASE_URL + "/repo/2/homepage.html", + supportURL: BASE_URL + "/repo/2/support.html", + contributionURL: BASE_URL + "/repo/2/meetDevelopers.html", + contributionAmount: null, + averageRating: 2, + reviewCount: 1112, + reviewURL: BASE_URL + "/repo/2/review.html", + totalDownloads: 2222, + weeklyDownloads: 3332, + dailyUsers: 4442, + sourceURI: NetUtil.newURI(ADDON_FILES[1]).spec, + repositoryStatus: 9 +}, { + id: ADDON_IDS[2], + type: "theme", + name: "XPI Add-on 3", + version: "1.3", + get iconURL () { + return get_subfile_uri(ADDON_IDS[2], "icon.png"); + }, + get icons () { + return { "32": get_subfile_uri(ADDON_IDS[2], "icon.png") }; + }, + screenshots: [{ + url: BASE_URL + "/repo/3/firstFull.png", + thumbnailURL: BASE_URL + "/repo/3/firstThumbnail.png", + caption: "Repo Add-on 3 - First Caption" + } , { + url: BASE_URL + "/repo/3/secondFull.png", + thumbnailURL: BASE_URL + "/repo/3/secondThumbnail.png", + caption: "Repo Add-on 3 - Second Caption" + }], + sourceURI: NetUtil.newURI(ADDON_FILES[2]).spec +}]; + +// Expected add-ons when using cache +const WITH_EXTENSION_CACHE = [{ + id: ADDON_IDS[0], + type: "extension", + name: "XPI Add-on 1", + version: "1.1", + creator: { + name: "Repo Add-on 1 - Creator", + url: BASE_URL + "/repo/1/creator.html" + }, + developers: [{ name: "XPI Add-on 1 - First Developer" }, + { name: "XPI Add-on 1 - Second Developer" }], + translators: [{ name: "XPI Add-on 1 - First Translator" }, + { name: "XPI Add-on 1 - Second Translator" }], + contributors: [{ name: "XPI Add-on 1 - First Contributor" }, + { name: "XPI Add-on 1 - Second Contributor" }], + description: "XPI Add-on 1 - Description", + fullDescription: "Repo Add-on 1 - Full Description & some extra", + developerComments: "Repo Add-on 1\nDeveloper Comments", + eula: "Repo Add-on 1 - EULA", + iconURL: BASE_URL + "/xpi/1/icon.png", + icons: { "32": BASE_URL + "/xpi/1/icon.png" }, + homepageURL: BASE_URL + "/xpi/1/homepage.html", + supportURL: BASE_URL + "/repo/1/support.html", + optionsURL: BASE_URL + "/xpi/1/options.html", + aboutURL: BASE_URL + "/xpi/1/about.html", + contributionURL: BASE_URL + "/repo/1/meetDevelopers.html", + contributionAmount: "$11.11", + averageRating: 1, + reviewCount: 1111, + reviewURL: BASE_URL + "/repo/1/review.html", + totalDownloads: 2221, + weeklyDownloads: 3331, + dailyUsers: 4441, + sourceURI: NetUtil.newURI(ADDON_FILES[0]).spec, + repositoryStatus: 4, + compatibilityOverrides: [{ + type: "incompatible", + minVersion: 0.1, + maxVersion: 0.2, + appID: "xpcshell@tests.mozilla.org", + appMinVersion: 3.0, + appMaxVersion: 4.0 + }, { + type: "incompatible", + minVersion: 0.2, + maxVersion: 0.3, + appID: "xpcshell@tests.mozilla.org", + appMinVersion: 5.0, + appMaxVersion: 6.0 + }] +}, { + id: ADDON_IDS[1], + type: "theme", + name: "XPI Add-on 2", + version: "1.2", + sourceURI: NetUtil.newURI(ADDON_FILES[1]).spec, + icons: {} +}, { + id: ADDON_IDS[2], + type: "theme", + name: "XPI Add-on 3", + version: "1.3", + get iconURL () { + return get_subfile_uri(ADDON_IDS[2], "icon.png"); + }, + get icons () { + return { "32": get_subfile_uri(ADDON_IDS[2], "icon.png") }; + }, + screenshots: [{ get url () { return get_subfile_uri(ADDON_IDS[2], "preview.png"); } }], + sourceURI: NetUtil.newURI(ADDON_FILES[2]).spec +}]; + +let gDBFile = gProfD.clone(); +gDBFile.append(FILE_DATABASE); + +/* + * Check the actual add-on results against the expected add-on results + * + * @param aActualAddons + * The array of actual add-ons to check + * @param aExpectedAddons + * The array of expected add-ons to check against + * @param aFromRepository + * An optional boolean representing if the add-ons are from + * the repository + */ +function check_results(aActualAddons, aExpectedAddons, aFromRepository) { + aFromRepository = !!aFromRepository; + + do_check_addons(aActualAddons, aExpectedAddons, ADDON_PROPERTIES); + + // Separately test size and updateDate (they should only be equal to the + // REPOSITORY values if they are from the repository) + aActualAddons.forEach(function(aActualAddon) { + if (aActualAddon.size) + do_check_eq(aActualAddon.size === REPOSITORY_SIZE, aFromRepository); + + if (aActualAddon.updateDate) { + let time = aActualAddon.updateDate.getTime(); + do_check_eq(time === 1000 * REPOSITORY_UPDATEDATE, aFromRepository); + } + }); +} + +/* + * Check the add-ons in the cache. This function also tests + * AddonRepository.getCachedAddonByID() + * + * @param aExpectedToFind + * An array of booleans representing which REPOSITORY_ADDONS are + * expected to be found in the cache + * @param aExpectedImmediately + * A boolean representing if results from the cache are expected + * immediately. Results are not immediate if the cache has not been + * initialized yet. + * @return Promise{null} + * Resolves once the checks are complete + */ +function check_cache(aExpectedToFind, aExpectedImmediately) { + do_check_eq(aExpectedToFind.length, REPOSITORY_ADDONS.length); + + let lookups = []; + + for (let i = 0 ; i < REPOSITORY_ADDONS.length ; i++) { + lookups.push(new Promise((resolve, reject) => { + let immediatelyFound = true; + let expected = aExpectedToFind[i] ? REPOSITORY_ADDONS[i] : null; + // can't Promise-wrap this because we're also testing whether the callback is + // sync or async + AddonRepository.getCachedAddonByID(REPOSITORY_ADDONS[i].id, function(aAddon) { + do_check_eq(immediatelyFound, aExpectedImmediately); + if (expected == null) + do_check_eq(aAddon, null); + else + check_results([aAddon], [expected], true); + resolve(); + }); + immediatelyFound = false; + })); + } + return Promise.all(lookups); +} + +/* + * Task to check an initialized cache by checking the cache, then restarting the + * manager, and checking the cache. This checks that the cache is consistent + * across manager restarts. + * + * @param aExpectedToFind + * An array of booleans representing which REPOSITORY_ADDONS are + * expected to be found in the cache + */ +function* check_initialized_cache(aExpectedToFind) { + yield check_cache(aExpectedToFind, true); + yield promiseRestartManager(); + + // If cache is disabled, then expect results immediately + let cacheEnabled = Services.prefs.getBoolPref(PREF_GETADDONS_CACHE_ENABLED); + yield check_cache(aExpectedToFind, !cacheEnabled); +} + +function run_test() { + run_next_test(); +} + +add_task(function* setup() { + // Setup for test + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); + + startupManager(); + + // Install XPI add-ons + yield promiseInstallAllFiles(ADDON_FILES); + yield promiseRestartManager(); + + gServer = new HttpServer(); + gServer.registerDirectory("/data/", do_get_file("data")); + gServer.start(PORT); +}); + +// Tests AddonRepository.cacheEnabled +add_task(function* run_test_1() { + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, false); + do_check_false(AddonRepository.cacheEnabled); + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); + do_check_true(AddonRepository.cacheEnabled); +}); + +// Tests that the cache and database begin as empty +add_task(function* run_test_2() { + do_check_false(gDBFile.exists()); + yield check_cache([false, false, false], false); + yield AddonRepository.flush(); +}); + +// Tests repopulateCache when the search fails +add_task(function* run_test_3() { + do_check_true(gDBFile.exists()); + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); + Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, GETADDONS_FAILED); + + yield AddonRepository.repopulateCache(); + yield check_initialized_cache([false, false, false]); +}); + +// Tests repopulateCache when search returns no results +add_task(function* run_test_4() { + Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, GETADDONS_EMPTY); + + yield AddonRepository.repopulateCache(); + yield check_initialized_cache([false, false, false]); +}); + +// Tests repopulateCache when search returns results +add_task(function* run_test_5() { + Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, GETADDONS_RESULTS); + + yield AddonRepository.repopulateCache(); + yield check_initialized_cache([true, true, true]); +}); + +// Tests repopulateCache when caching is disabled for a single add-on +add_task(function* run_test_5_1() { + Services.prefs.setBoolPref(PREF_ADDON0_CACHE_ENABLED, false); + + yield AddonRepository.repopulateCache(); + + // Reset pref for next test + Services.prefs.setBoolPref(PREF_ADDON0_CACHE_ENABLED, true); + + yield check_initialized_cache([false, true, true]); +}); + +// Tests repopulateCache when caching is disabled +add_task(function* run_test_6() { + do_check_true(gDBFile.exists()); + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, false); + + yield AddonRepository.repopulateCache(); + // Database should have been deleted + do_check_false(gDBFile.exists()); + + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); + yield check_cache([false, false, false], false); + yield AddonRepository.flush(); +}); + +// Tests cacheAddons when the search fails +add_task(function* run_test_7() { + do_check_true(gDBFile.exists()); + Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, GETADDONS_FAILED); + + yield new Promise((resolve, reject) => + AddonRepository.cacheAddons(ADDON_IDS, resolve)); + yield check_initialized_cache([false, false, false]); +}); + +// Tests cacheAddons when the search returns no results +add_task(function* run_test_8() { + Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, GETADDONS_EMPTY); + + yield new Promise((resolve, reject) => + AddonRepository.cacheAddons(ADDON_IDS, resolve)); + yield check_initialized_cache([false, false, false]); +}); + +// Tests cacheAddons for a single add-on when search returns results +add_task(function* run_test_9() { + Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, GETADDONS_RESULTS); + + yield new Promise((resolve, reject) => + AddonRepository.cacheAddons([ADDON_IDS[0]], resolve)); + yield check_initialized_cache([true, false, false]); +}); + +// Tests cacheAddons when caching is disabled for a single add-on +add_task(function* run_test_9_1() { + Services.prefs.setBoolPref(PREF_ADDON1_CACHE_ENABLED, false); + + yield new Promise((resolve, reject) => + AddonRepository.cacheAddons(ADDON_IDS, resolve)); + + // Reset pref for next test + Services.prefs.setBoolPref(PREF_ADDON1_CACHE_ENABLED, true); + + yield check_initialized_cache([true, false, true]); +}); + +// Tests cacheAddons for multiple add-ons, some already in the cache, +add_task(function* run_test_10() { + yield new Promise((resolve, reject) => + AddonRepository.cacheAddons(ADDON_IDS, resolve)); + yield check_initialized_cache([true, true, true]); +}); + +// Tests cacheAddons when caching is disabled +add_task(function* run_test_11() { + do_check_true(gDBFile.exists()); + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, false); + + yield new Promise((resolve, reject) => + AddonRepository.cacheAddons(ADDON_IDS, resolve)); + do_check_true(gDBFile.exists()); + + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); + yield check_initialized_cache([true, true, true]); +}); + +// Tests that XPI add-ons do not use any of the repository properties if +// caching is disabled, even if there are repository properties available +add_task(function* run_test_12() { + do_check_true(gDBFile.exists()); + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, false); + Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, GETADDONS_RESULTS); + + let aAddons = yield promiseAddonsByIDs(ADDON_IDS); + check_results(aAddons, WITHOUT_CACHE); +}); + +// Tests that a background update with caching disabled deletes the add-ons +// database, and that XPI add-ons still do not use any of repository properties +add_task(function* run_test_13() { + do_check_true(gDBFile.exists()); + Services.prefs.setCharPref(PREF_GETADDONS_BYIDS_PERFORMANCE, GETADDONS_EMPTY); + + yield AddonManagerInternal.backgroundUpdateCheck(); + // Database should have been deleted + do_check_false(gDBFile.exists()); + + let aAddons = yield promiseAddonsByIDs(ADDON_IDS); + check_results(aAddons, WITHOUT_CACHE); +}); + +// Tests that the XPI add-ons have the correct properties if caching is +// enabled but has no information +add_task(function* run_test_14() { + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); + + yield AddonManagerInternal.backgroundUpdateCheck(); + yield AddonRepository.flush(); + do_check_true(gDBFile.exists()); + + let aAddons = yield promiseAddonsByIDs(ADDON_IDS); + check_results(aAddons, WITHOUT_CACHE); +}); + +// Tests that the XPI add-ons correctly use the repository properties when +// caching is enabled and the repository information is available +add_task(function* run_test_15() { + Services.prefs.setCharPref(PREF_GETADDONS_BYIDS_PERFORMANCE, GETADDONS_RESULTS); + + yield AddonManagerInternal.backgroundUpdateCheck(); + let aAddons = yield promiseAddonsByIDs(ADDON_IDS); + check_results(aAddons, WITH_CACHE); +}); + +// Tests that restarting the manager does not change the checked properties +// on the XPI add-ons (repository properties still exist and are still properly +// used) +add_task(function* run_test_16() { + yield promiseRestartManager(); + + let aAddons = yield promiseAddonsByIDs(ADDON_IDS); + check_results(aAddons, WITH_CACHE); +}); + +// Tests that setting a list of types to cache works +add_task(function* run_test_17() { + Services.prefs.setCharPref(PREF_GETADDONS_CACHE_TYPES, "foo,bar,extension,baz"); + + yield AddonManagerInternal.backgroundUpdateCheck(); + let aAddons = yield promiseAddonsByIDs(ADDON_IDS); + check_results(aAddons, WITH_EXTENSION_CACHE); +}); + +add_task(function* end_test() { + yield new Promise((resolve, reject) => gServer.stop(resolve)); +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_compatmode.js b/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_compatmode.js new file mode 100644 index 000000000..6aec96ea1 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_compatmode.js @@ -0,0 +1,90 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that AddonRepository correctly fills in the +// %COMPATIBILITY_MODE% token in the Search API URL. + +const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url"; + +Components.utils.import("resource://testing-common/httpd.js"); +var gServer = new HttpServer(); +gServer.start(-1); +gPort = gServer.identity.primaryPort; +var COMPATIBILITY_PREF; + +// register static files with server and interpolate port numbers in them +mapFile("/data/test_AddonRepository_compatmode_ignore.xml", gServer); +mapFile("/data/test_AddonRepository_compatmode_normal.xml", gServer); +mapFile("/data/test_AddonRepository_compatmode_strict.xml", gServer); + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, + "http://localhost:" + gPort + "/data/test_AddonRepository_compatmode_%COMPATIBILITY_MODE%.xml"); + startupManager(); + run_test_1(); +} + +function end_test() { + gServer.stop(do_test_finished); +} + +// Strict compatibility checking disabled. +function run_test_1() { + do_print("Testing with strict compatibility checking disabled"); + Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false); + + AddonRepository.searchAddons("test", 6, { + searchSucceeded: function(aAddons) { + do_check_neq(aAddons, null); + do_check_eq(aAddons.length, 1); + do_check_eq(aAddons[0].id, "compatmode-normal@tests.mozilla.org"); + + run_test_2(); + }, + searchFailed: function() { + do_throw("Search should not have failed"); + } + }); +} + +// Strict compatibility checking enabled. +function run_test_2() { + do_print("Testing with strict compatibility checking enabled"); + Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, true); + + AddonRepository.searchAddons("test", 6, { + searchSucceeded: function(aAddons) { + do_check_neq(aAddons, null); + do_check_eq(aAddons.length, 1); + do_check_eq(aAddons[0].id, "compatmode-strict@tests.mozilla.org"); + + run_test_3(); + }, + searchFailed: function() { + do_throw("Search should not have failed"); + } + }); +} + +// Compatibility checking disabled. +function run_test_3() { + do_print("Testing with all compatibility checking disabled"); + AddonManager.checkCompatibility = false; + + AddonRepository.searchAddons("test", 6, { + searchSucceeded: function(aAddons) { + do_check_neq(aAddons, null); + do_check_eq(aAddons.length, 1); + do_check_eq(aAddons[0].id, "compatmode-ignore@tests.mozilla.org"); + + end_test(); + }, + searchFailed: function() { + do_throw("Search should not have failed"); + } + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_ChromeManifestParser.js b/toolkit/mozapps/extensions/test/xpcshell/test_ChromeManifestParser.js new file mode 100644 index 000000000..2e4adbe0f --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_ChromeManifestParser.js @@ -0,0 +1,108 @@ +/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Tests ChromeManifestParser.js
+
+Components.utils.import("resource://gre/modules/ChromeManifestParser.jsm");
+
+
+function run_test() {
+ do_test_pending();
+ createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2");
+
+ startupManager();
+
+ installAllFiles([do_get_addon("test_chromemanifest_1"),
+ do_get_addon("test_chromemanifest_2"),
+ do_get_addon("test_chromemanifest_3"),
+ do_get_addon("test_chromemanifest_4")],
+ function() {
+
+ restartManager();
+ run_test_1();
+ });
+}
+
+function run_test_1() {
+ AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
+ "addon2@tests.mozilla.org",
+ "addon3@tests.mozilla.org",
+ "addon4@tests.mozilla.org"],
+ function([a1, a2, a3, a4]) {
+ // addon1
+ let a1Uri = a1.getResourceURI("/").spec;
+ let expected = [
+ {type: "content", baseURI: a1Uri, args: ["test-addon-1", "chrome/content"]},
+ {type: "locale", baseURI: a1Uri, args: ["test-addon-1", "en-US", "locale/en-US"]},
+ {type: "locale", baseURI: a1Uri, args: ["test-addon-1", "fr-FR", "locale/fr-FR"]},
+ {type: "overlay", baseURI: a1Uri, args: ["chrome://browser/content/browser.xul", "chrome://test-addon-1/content/overlay.xul"]}
+ ];
+ let manifestURI = a1.getResourceURI("chrome.manifest");
+ let manifest = ChromeManifestParser.parseSync(manifestURI);
+
+ do_check_true(Array.isArray(manifest));
+ do_check_eq(manifest.length, expected.length);
+ for (let i = 0; i < manifest.length; i++) {
+ do_check_eq(JSON.stringify(manifest[i]), JSON.stringify(expected[i]));
+ }
+
+ // addon2
+ let a2Uri = a2.getResourceURI("/").spec;
+ expected = [
+ {type: "content", baseURI: a2Uri, args: ["test-addon-1", "chrome/content"]},
+ {type: "locale", baseURI: a2Uri, args: ["test-addon-1", "en-US", "locale/en-US"]},
+ {type: "locale", baseURI: a2Uri, args: ["test-addon-1", "fr-FR", "locale/fr-FR"]},
+ {type: "overlay", baseURI: a2Uri, args: ["chrome://browser/content/browser.xul", "chrome://test-addon-1/content/overlay.xul"]},
+ {type: "binary-component", baseURI: a2Uri, args: ["components/something.so"]}
+ ];
+ manifestURI = a2.getResourceURI("chrome.manifest");
+ manifest = ChromeManifestParser.parseSync(manifestURI);
+
+ do_check_true(Array.isArray(manifest));
+ do_check_eq(manifest.length, expected.length);
+ for (let i = 0; i < manifest.length; i++) {
+ do_check_eq(JSON.stringify(manifest[i]), JSON.stringify(expected[i]));
+ }
+
+ // addon3
+ let a3Uri = a3.getResourceURI("/").spec;
+ expected = [
+ {type: "content", baseURI: a3Uri, args: ["test-addon-1", "chrome/content"]},
+ {type: "locale", baseURI: a3Uri, args: ["test-addon-1", "en-US", "locale/en-US"]},
+ {type: "locale", baseURI: a3Uri, args: ["test-addon-1", "fr-FR", "locale/fr-FR"]},
+ {type: "overlay", baseURI: a3Uri, args: ["chrome://browser/content/browser.xul", "chrome://test-addon-1/content/overlay.xul"]},
+ {type: "binary-component", baseURI: a3Uri, args: ["components/something.so"]},
+ {type: "locale", baseURI: "jar:" + a3.getResourceURI("/inner.jar").spec + "!/", args: ["test-addon-1", "en-NZ", "locale/en-NZ"]},
+ ];
+ manifestURI = a3.getResourceURI("chrome.manifest");
+ manifest = ChromeManifestParser.parseSync(manifestURI);
+
+ do_check_true(Array.isArray(manifest));
+ do_check_eq(manifest.length, expected.length);
+ for (let i = 0; i < manifest.length; i++) {
+ do_check_eq(JSON.stringify(manifest[i]), JSON.stringify(expected[i]));
+ }
+
+ // addon4
+ let a4Uri = a4.getResourceURI("/").spec;
+ expected = [
+ {type: "content", baseURI: a4Uri, args: ["test-addon-1", "chrome/content"]},
+ {type: "locale", baseURI: a4Uri, args: ["test-addon-1", "en-US", "locale/en-US"]},
+ {type: "locale", baseURI: a4Uri, args: ["test-addon-1", "fr-FR", "locale/fr-FR"]},
+ {type: "overlay", baseURI: a4Uri, args: ["chrome://browser/content/browser.xul", "chrome://test-addon-1/content/overlay.xul"]},
+ {type: "binary-component", baseURI: a4.getResourceURI("components/").spec, args: ["mycomponent.dll"]},
+ {type: "binary-component", baseURI: a4.getResourceURI("components/other/").spec, args: ["thermalnuclearwar.dll"]}
+ ];
+ manifestURI = a4.getResourceURI("chrome.manifest");
+ manifest = ChromeManifestParser.parseSync(manifestURI);
+
+ do_check_true(Array.isArray(manifest));
+ do_check_eq(manifest.length, expected.length);
+ for (let i = 0; i < manifest.length; i++) {
+ do_check_eq(JSON.stringify(manifest[i]), JSON.stringify(expected[i]));
+ }
+
+ do_execute_soon(do_test_finished);
+ });
+}
diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_DeferredSave.js b/toolkit/mozapps/extensions/test/xpcshell/test_DeferredSave.js new file mode 100644 index 000000000..7599c8b80 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_DeferredSave.js @@ -0,0 +1,550 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test behaviour of module to perform deferred save of data +// files to disk + +"use strict"; + +const testFile = gProfD.clone(); +testFile.append("DeferredSaveTest"); + +Components.utils.import("resource://gre/modules/Promise.jsm"); + +let DSContext = Components.utils.import("resource://gre/modules/DeferredSave.jsm", {}); +let DeferredSave = DSContext.DeferredSave; + +// Test wrapper to let us do promise/task based testing of DeferredSave +function DeferredSaveTester(aDataProvider) { + let tester = { + // Deferred for the promise returned by the mock writeAtomic + waDeferred: null, + + // The most recent data "written" by the mock OS.File.writeAtomic + writtenData: undefined, + + dataToSave: "Data to save", + + save: (aData, aWriteHandler) => { + tester.writeHandler = aWriteHandler || writer; + tester.dataToSave = aData; + return tester.saver.saveChanges(); + }, + + flush: (aWriteHandler) => { + tester.writeHandler = aWriteHandler || writer; + return tester.saver.flush(); + }, + + get lastError() { + return tester.saver.lastError; + } + }; + + // Default write handler for most cases where the test case doesn't need + // to do anything while the write is in progress; just completes the write + // on the next event loop + function writer(aTester) { + do_print("default write callback"); + let length = aTester.writtenData.length; + do_execute_soon(() => aTester.waDeferred.resolve(length)); + } + + if (!aDataProvider) + aDataProvider = () => tester.dataToSave; + + tester.saver = new DeferredSave(testFile.path, aDataProvider); + + // Install a mock for OS.File.writeAtomic to let us control the async + // behaviour of the promise + DSContext.OS.File.writeAtomic = function mock_writeAtomic(aFile, aData, aOptions) { + do_print("writeAtomic: " + aFile + " data: '" + aData + "', " + aOptions.toSource()); + tester.writtenData = aData; + tester.waDeferred = Promise.defer(); + tester.writeHandler(tester); + return tester.waDeferred.promise; + }; + + return tester; +}; + +/** + * Install a mock nsITimer factory that triggers on the next spin of + * the event loop after it is scheduled + */ +function setQuickMockTimer() { + let quickTimer = { + initWithCallback: function(aFunction, aDelay, aType) { + do_print("Starting quick timer, delay = " + aDelay); + do_execute_soon(aFunction); + }, + cancel: function() { + do_throw("Attempted to cancel a quickMockTimer"); + } + }; + DSContext.MakeTimer = () => { + do_print("Creating quick timer"); + return quickTimer; + }; +} + +/** + * Install a mock nsITimer factory in DeferredSave.jsm, returning a promise that resolves + * when the client code sets the timer. Test cases can use this to wait for client code to + * be ready for a timer event, and then signal the event by calling mockTimer.callback(). + * This could use some enhancement; clients can re-use the returned timer, + * but with this implementation it's not possible for the test to wait for + * a second call to initWithCallback() on the re-used timer. + * @return Promise{mockTimer} that resolves when initWithCallback() + * is called + */ +function setPromiseMockTimer() { + let waiter = Promise.defer(); + let mockTimer = { + callback: null, + delay: null, + type: null, + isCancelled: false, + + initWithCallback: function(aFunction, aDelay, aType) { + do_print("Starting timer, delay = " + aDelay); + this.callback = aFunction; + this.delay = aDelay; + this.type = aType; + // cancelled timers can be re-used + this.isCancelled = false; + waiter.resolve(this); + }, + cancel: function() { + do_print("Cancelled mock timer"); + this.callback = null; + this.delay = null; + this.type = null; + this.isCancelled = true; + // If initWithCallback was never called, resolve to let tests check for cancel + waiter.resolve(this); + } + }; + DSContext.MakeTimer = () => { + do_print("Creating mock timer"); + return mockTimer; + }; + return waiter.promise; +} + +/** + * Return a Promise<null> that resolves after the specified number of milliseconds + */ +function delay(aDelayMS) { + let deferred = Promise.defer(); + do_timeout(aDelayMS, () => deferred.resolve(null)); + return deferred.promise; +} + +function run_test() { + run_next_test(); +} + +// Modify set data once, ask for save, make sure it saves cleanly +add_task(function test_basic_save_succeeds() { + setQuickMockTimer(); + let tester = DeferredSaveTester(); + let data = "Test 1 Data"; + + yield tester.save(data); + do_check_eq(tester.writtenData, data); + do_check_eq(1, tester.saver.totalSaves); +}); + +// Two saves called during the same event loop, both with callbacks +// Make sure we save only the second version of the data +add_task(function test_two_saves() { + setQuickMockTimer(); + let tester = DeferredSaveTester(); + let firstCallback_happened = false; + let firstData = "Test first save"; + let secondData = "Test second save"; + + // first save should not resolve until after the second one is called, + // so we can't just yield this promise + tester.save(firstData).then(count => { + do_check_eq(secondData, tester.writtenData); + do_check_false(firstCallback_happened); + firstCallback_happened = true; + }, do_report_unexpected_exception); + + yield tester.save(secondData); + do_check_true(firstCallback_happened); + do_check_eq(secondData, tester.writtenData); + do_check_eq(1, tester.saver.totalSaves); +}); + +// Two saves called with a delay in between, both with callbacks +// Make sure we save the second version of the data +add_task(function test_two_saves_delay() { + let timerPromise = setPromiseMockTimer(); + let tester = DeferredSaveTester(); + let firstCallback_happened = false; + let delayDone = false; + + let firstData = "First data to save with delay"; + let secondData = "Modified data to save with delay"; + + tester.save(firstData).then(count => { + do_check_false(firstCallback_happened); + do_check_true(delayDone); + do_check_eq(secondData, tester.writtenData); + firstCallback_happened = true; + }, do_report_unexpected_exception); + + // Wait a short time to let async events possibly spawned by the + // first tester.save() to run + yield delay(2); + delayDone = true; + // request to save modified data + let saving = tester.save(secondData); + // Yield to wait for client code to set the timer + let activeTimer = yield timerPromise; + // and then trigger it + activeTimer.callback(); + // now wait for the DeferredSave to finish saving + yield saving; + do_check_true(firstCallback_happened); + do_check_eq(secondData, tester.writtenData); + do_check_eq(1, tester.saver.totalSaves); + do_check_eq(0, tester.saver.overlappedSaves); +}); + +// Test case where OS.File immediately reports an error when the write begins +// Also check that the "error" getter correctly returns the error +// Then do a write that succeeds, and make sure the error is cleared +add_task(function test_error_immediate() { + let tester = DeferredSaveTester(); + let testError = new Error("Forced failure"); + function writeFail(aTester) { + aTester.waDeferred.reject(testError); + } + + setQuickMockTimer(); + yield tester.save("test_error_immediate", writeFail).then( + count => do_throw("Did not get expected error"), + error => do_check_eq(testError.message, error.message) + ); + do_check_eq(testError, tester.lastError); + + // This write should succeed and clear the error + yield tester.save("test_error_immediate succeeds"); + do_check_eq(null, tester.lastError); + // The failed save attempt counts in our total + do_check_eq(2, tester.saver.totalSaves); +}); + +// Save one set of changes, then while the write is in progress, modify the +// data two more times. Test that we re-write the dirty data exactly once +// after the first write succeeds +add_task(function dirty_while_writing() { + let tester = DeferredSaveTester(); + let firstData = "First data"; + let secondData = "Second data"; + let thirdData = "Third data"; + let firstCallback_happened = false; + let secondCallback_happened = false; + let writeStarted = Promise.defer(); + + function writeCallback(aTester) { + writeStarted.resolve(aTester.waDeferred); + } + + setQuickMockTimer(); + do_print("First save"); + tester.save(firstData, writeCallback).then( + count => { + do_check_false(firstCallback_happened); + do_check_false(secondCallback_happened); + do_check_eq(tester.writtenData, firstData); + firstCallback_happened = true; + }, do_report_unexpected_exception); + + do_print("waiting for writer"); + let writer = yield writeStarted.promise; + do_print("Write started"); + + // Delay a bit, modify the data and call saveChanges, delay a bit more, + // modify the data and call saveChanges again, another delay, + // then complete the in-progress write + yield delay(1); + + tester.save(secondData).then( + count => { + do_check_true(firstCallback_happened); + do_check_false(secondCallback_happened); + do_check_eq(tester.writtenData, thirdData); + secondCallback_happened = true; + }, do_report_unexpected_exception); + + // wait and then do the third change + yield delay(1); + let thirdWrite = tester.save(thirdData); + + // wait a bit more and then finally finish the first write + yield delay(1); + writer.resolve(firstData.length); + + // Now let everything else finish + yield thirdWrite; + do_check_true(firstCallback_happened); + do_check_true(secondCallback_happened); + do_check_eq(tester.writtenData, thirdData); + do_check_eq(2, tester.saver.totalSaves); + do_check_eq(1, tester.saver.overlappedSaves); +}); + +// A write callback for the OS.File.writeAtomic mock that rejects write attempts +function disabled_write_callback(aTester) { + do_throw("Should not have written during clean flush"); + deferred.reject(new Error("Write during supposedly clean flush")); +} + +// special write callback that disables itself to make sure +// we don't try to write twice +function write_then_disable(aTester) { + do_print("write_then_disable"); + let length = aTester.writtenData.length; + aTester.writeHandler = disabled_write_callback; + do_execute_soon(() => aTester.waDeferred.resolve(length)); +} + +// Flush tests. First, do an ordinary clean save and then call flush; +// there should not be another save +add_task(function flush_after_save() { + setQuickMockTimer(); + let tester = DeferredSaveTester(); + let dataToSave = "Flush after save"; + + yield tester.save(dataToSave); + yield tester.flush(disabled_write_callback); + do_check_eq(1, tester.saver.totalSaves); +}); + +// Flush while a write is in progress, but the in-memory data is clean +add_task(function flush_during_write() { + let tester = DeferredSaveTester(); + let dataToSave = "Flush during write"; + let firstCallback_happened = false; + let writeStarted = Promise.defer(); + + function writeCallback(aTester) { + writeStarted.resolve(aTester.waDeferred); + } + + setQuickMockTimer(); + tester.save(dataToSave, writeCallback).then( + count => { + do_check_false(firstCallback_happened); + firstCallback_happened = true; + }, do_report_unexpected_exception); + + let writer = yield writeStarted.promise; + + // call flush with the write callback disabled, delay a bit more, complete in-progress write + let flushing = tester.flush(disabled_write_callback); + yield delay(2); + writer.resolve(dataToSave.length); + + // now wait for the flush to finish + yield flushing; + do_check_true(firstCallback_happened); + do_check_eq(1, tester.saver.totalSaves); +}); + +// Flush while dirty but write not in progress +// The data written should be the value at the time +// flush() is called, even if it is changed later +add_task(function flush_while_dirty() { + let timerPromise = setPromiseMockTimer(); + let tester = DeferredSaveTester(); + let firstData = "Flush while dirty, valid data"; + let firstCallback_happened = false; + + tester.save(firstData, write_then_disable).then( + count => { + do_check_false(firstCallback_happened); + firstCallback_happened = true; + do_check_eq(tester.writtenData, firstData); + }, do_report_unexpected_exception); + + // Wait for the timer to be set, but don't trigger it so the write won't start + let activeTimer = yield timerPromise; + + let flushing = tester.flush(); + + // Make sure the timer was cancelled + do_check_true(activeTimer.isCancelled); + + // Also make sure that data changed after the flush call + // (even without a saveChanges() call) doesn't get written + tester.dataToSave = "Flush while dirty, invalid data"; + + yield flushing; + do_check_true(firstCallback_happened); + do_check_eq(tester.writtenData, firstData); + do_check_eq(1, tester.saver.totalSaves); +}); + +// And the grand finale - modify the data, start writing, +// modify the data again so we're in progress and dirty, +// then flush, then modify the data again +// Data for the second write should be taken at the time +// flush() is called, even if it is modified later +add_task(function flush_writing_dirty() { + let timerPromise = setPromiseMockTimer(); + let tester = DeferredSaveTester(); + let firstData = "Flush first pass data"; + let secondData = "Flush second pass data"; + let firstCallback_happened = false; + let secondCallback_happened = false; + let writeStarted = Promise.defer(); + + function writeCallback(aTester) { + writeStarted.resolve(aTester.waDeferred); + } + + tester.save(firstData, writeCallback).then( + count => { + do_check_false(firstCallback_happened); + do_check_eq(tester.writtenData, firstData); + firstCallback_happened = true; + }, do_report_unexpected_exception); + + // Trigger the timer callback as soon as the DeferredSave sets it + let activeTimer = yield timerPromise; + activeTimer.callback(); + let writer = yield writeStarted.promise; + // the first write has started + + // dirty the data and request another save + // after the second save completes, there should not be another write + tester.save(secondData, write_then_disable).then( + count => { + do_check_true(firstCallback_happened); + do_check_false(secondCallback_happened); + do_check_eq(tester.writtenData, secondData); + secondCallback_happened = true; + }, do_report_unexpected_exception); + + let flushing = tester.flush(write_then_disable); + // Flush should have cancelled our timer + do_check_true(activeTimer.isCancelled); + tester.dataToSave = "Flush, invalid data: changed late"; + // complete the first write + writer.resolve(firstData.length); + // now wait for the second write / flush to complete + yield flushing; + do_check_true(firstCallback_happened); + do_check_true(secondCallback_happened); + do_check_eq(tester.writtenData, secondData); + do_check_eq(2, tester.saver.totalSaves); + do_check_eq(1, tester.saver.overlappedSaves); +}); + +// A data provider callback that throws an error the first +// time it is called, and a different error the second time +// so that tests can (a) make sure the promise is rejected +// with the error and (b) make sure the provider is only +// called once in case of error +const expectedDataError = "Failed to serialize data"; +let badDataError = null; +function badDataProvider() { + let err = new Error(badDataError); + badDataError = "badDataProvider called twice"; + throw err; +} + +// Handle cases where data provider throws +// First, throws during a normal save +add_task(function data_throw() { + setQuickMockTimer(); + badDataError = expectedDataError; + let tester = DeferredSaveTester(badDataProvider); + yield tester.save("data_throw").then( + count => do_throw("Expected serialization failure"), + error => do_check_eq(error.message, expectedDataError)); +}); + +// Now, throws during flush +add_task(function data_throw_during_flush() { + badDataError = expectedDataError; + let tester = DeferredSaveTester(badDataProvider); + let firstCallback_happened = false; + + setPromiseMockTimer(); + // Write callback should never be called + tester.save("data_throw_during_flush", disabled_write_callback).then( + count => do_throw("Expected serialization failure"), + error => { + do_check_false(firstCallback_happened); + do_check_eq(error.message, expectedDataError); + firstCallback_happened = true; + }); + + // flush() will cancel the timer + yield tester.flush(disabled_write_callback).then( + count => do_throw("Expected serialization failure"), + error => do_check_eq(error.message, expectedDataError) + ); + + do_check_true(firstCallback_happened); +}); + +// Try to reproduce race condition. The observed sequence of events: +// saveChanges +// start writing +// saveChanges +// finish writing (need to restart delayed timer) +// saveChanges +// flush +// write starts +// actually restart timer for delayed write +// write completes +// delayed timer goes off, throws error because DeferredSave has been torn down +add_task(function delay_flush_race() { + let timerPromise = setPromiseMockTimer(); + let tester = DeferredSaveTester(); + let firstData = "First save"; + let secondData = "Second save"; + let thirdData = "Third save"; + let writeStarted = Promise.defer(); + + function writeCallback(aTester) { + writeStarted.resolve(aTester.waDeferred); + } + + // This promise won't resolve until after writeStarted + let firstSave = tester.save(firstData, writeCallback); + (yield timerPromise).callback(); + + let writer = yield writeStarted.promise; + // the first write has started + + // dirty the data and request another save + let secondSave = tester.save(secondData); + + // complete the first write + writer.resolve(firstData.length); + yield firstSave; + do_check_eq(tester.writtenData, firstData); + + tester.save(thirdData); + let flushing = tester.flush(); + + yield secondSave; + do_check_eq(tester.writtenData, thirdData); + + yield flushing; + do_check_eq(tester.writtenData, thirdData); + + // Our DeferredSave should not have a _timer here; if it + // does, the bug caused a reschedule + do_check_eq(null, tester.saver._timer); +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_LightweightThemeManager.js b/toolkit/mozapps/extensions/test/xpcshell/test_LightweightThemeManager.js new file mode 100644 index 000000000..c0cf78a89 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_LightweightThemeManager.js @@ -0,0 +1,514 @@ +const Cc = Components.classes; +const Ci = Components.interfaces; + +const MANDATORY = ["id", "name", "headerURL"]; +const OPTIONAL = ["footerURL", "textcolor", "accentcolor", "iconURL", + "previewURL", "author", "description", "homepageURL", + "updateURL", "version"]; + +Components.utils.import("resource://gre/modules/Services.jsm"); + +function dummy(id) { + return { + id: id || Math.random().toString(), + name: Math.random().toString(), + headerURL: "http://lwttest.invalid/a.png", + footerURL: "http://lwttest.invalid/b.png", + textcolor: Math.random().toString(), + accentcolor: Math.random().toString() + }; +} + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); + startupManager(); + + Services.prefs.setIntPref("lightweightThemes.maxUsedThemes", 8); + + var temp = {}; + Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", temp); + do_check_eq(typeof temp.LightweightThemeManager, "object"); + + var ltm = temp.LightweightThemeManager; + + do_check_eq(typeof ltm.usedThemes, "object"); + do_check_eq(ltm.usedThemes.length, 0); + do_check_eq(ltm.currentTheme, null); + + ltm.previewTheme(dummy("preview0")); + do_check_eq(ltm.usedThemes.length, 0); + do_check_eq(ltm.currentTheme, null); + + ltm.previewTheme(dummy("preview1")); + do_check_eq(ltm.usedThemes.length, 0); + do_check_eq(ltm.currentTheme, null); + ltm.resetPreview(); + + ltm.currentTheme = dummy("x0"); + do_check_eq(ltm.usedThemes.length, 1); + do_check_eq(ltm.currentTheme.id, "x0"); + do_check_eq(ltm.usedThemes[0].id, "x0"); + do_check_eq(ltm.getUsedTheme("x0").id, "x0"); + + ltm.previewTheme(dummy("preview0")); + do_check_eq(ltm.usedThemes.length, 1); + do_check_eq(ltm.currentTheme.id, "x0"); + + ltm.resetPreview(); + do_check_eq(ltm.usedThemes.length, 1); + do_check_eq(ltm.currentTheme.id, "x0"); + + ltm.currentTheme = dummy("x1"); + do_check_eq(ltm.usedThemes.length, 2); + do_check_eq(ltm.currentTheme.id, "x1"); + do_check_eq(ltm.usedThemes[1].id, "x0"); + + ltm.currentTheme = dummy("x2"); + do_check_eq(ltm.usedThemes.length, 3); + do_check_eq(ltm.currentTheme.id, "x2"); + do_check_eq(ltm.usedThemes[1].id, "x1"); + do_check_eq(ltm.usedThemes[2].id, "x0"); + + ltm.currentTheme = dummy("x3"); + ltm.currentTheme = dummy("x4"); + ltm.currentTheme = dummy("x5"); + ltm.currentTheme = dummy("x6"); + ltm.currentTheme = dummy("x7"); + do_check_eq(ltm.usedThemes.length, 8); + do_check_eq(ltm.currentTheme.id, "x7"); + do_check_eq(ltm.usedThemes[1].id, "x6"); + do_check_eq(ltm.usedThemes[7].id, "x0"); + + ltm.currentTheme = dummy("x8"); + do_check_eq(ltm.usedThemes.length, 8); + do_check_eq(ltm.currentTheme.id, "x8"); + do_check_eq(ltm.usedThemes[1].id, "x7"); + do_check_eq(ltm.usedThemes[7].id, "x1"); + do_check_eq(ltm.getUsedTheme("x0"), null); + + ltm.forgetUsedTheme("nonexistent"); + do_check_eq(ltm.usedThemes.length, 8); + do_check_neq(ltm.currentTheme, null); + + ltm.forgetUsedTheme("x8"); + do_check_eq(ltm.usedThemes.length, 7); + do_check_eq(ltm.currentTheme, null); + do_check_eq(ltm.usedThemes[0].id, "x7"); + do_check_eq(ltm.usedThemes[6].id, "x1"); + + ltm.forgetUsedTheme("x7"); + ltm.forgetUsedTheme("x6"); + ltm.forgetUsedTheme("x5"); + ltm.forgetUsedTheme("x4"); + ltm.forgetUsedTheme("x3"); + do_check_eq(ltm.usedThemes.length, 2); + do_check_eq(ltm.currentTheme, null); + do_check_eq(ltm.usedThemes[0].id, "x2"); + do_check_eq(ltm.usedThemes[1].id, "x1"); + + ltm.currentTheme = dummy("x1"); + do_check_eq(ltm.usedThemes.length, 2); + do_check_eq(ltm.currentTheme.id, "x1"); + do_check_eq(ltm.usedThemes[0].id, "x1"); + do_check_eq(ltm.usedThemes[1].id, "x2"); + + ltm.currentTheme = dummy("x2"); + do_check_eq(ltm.usedThemes.length, 2); + do_check_eq(ltm.currentTheme.id, "x2"); + do_check_eq(ltm.usedThemes[0].id, "x2"); + do_check_eq(ltm.usedThemes[1].id, "x1"); + + ltm.currentTheme = ltm.getUsedTheme("x1"); + do_check_eq(ltm.usedThemes.length, 2); + do_check_eq(ltm.currentTheme.id, "x1"); + do_check_eq(ltm.usedThemes[0].id, "x1"); + do_check_eq(ltm.usedThemes[1].id, "x2"); + + ltm.forgetUsedTheme("x1"); + ltm.forgetUsedTheme("x2"); + do_check_eq(ltm.usedThemes.length, 0); + do_check_eq(ltm.currentTheme, null); + + // Use chinese name to test utf-8, for bug #541943 + var chineseTheme = dummy("chinese0"); + chineseTheme.name = "笢恅0"; + chineseTheme.description = "笢恅1"; + ltm.currentTheme = chineseTheme; + do_check_eq(ltm.usedThemes.length, 1); + do_check_eq(ltm.currentTheme.name, "笢恅0"); + do_check_eq(ltm.currentTheme.description, "笢恅1"); + do_check_eq(ltm.usedThemes[0].name, "笢恅0"); + do_check_eq(ltm.usedThemes[0].description, "笢恅1"); + do_check_eq(ltm.getUsedTheme("chinese0").name, "笢恅0"); + do_check_eq(ltm.getUsedTheme("chinese0").description, "笢恅1"); + + // This name used to break the usedTheme JSON causing all LWTs to be lost + var chineseTheme1 = dummy("chinese1"); + chineseTheme1.name = "眵昜湮桵蔗坌~郔乾"; + chineseTheme1.description = "眵昜湮桵蔗坌~郔乾"; + ltm.currentTheme = chineseTheme1; + do_check_neq(ltm.currentTheme, null); + do_check_eq(ltm.usedThemes.length, 2); + do_check_eq(ltm.currentTheme.name, "眵昜湮桵蔗坌~郔乾"); + do_check_eq(ltm.currentTheme.description, "眵昜湮桵蔗坌~郔乾"); + do_check_eq(ltm.usedThemes[1].name, "笢恅0"); + do_check_eq(ltm.usedThemes[1].description, "笢恅1"); + do_check_eq(ltm.usedThemes[0].name, "眵昜湮桵蔗坌~郔乾"); + do_check_eq(ltm.usedThemes[0].description, "眵昜湮桵蔗坌~郔乾"); + + ltm.forgetUsedTheme("chinese0"); + do_check_eq(ltm.usedThemes.length, 1); + do_check_neq(ltm.currentTheme, null); + + ltm.forgetUsedTheme("chinese1"); + do_check_eq(ltm.usedThemes.length, 0); + do_check_eq(ltm.currentTheme, null); + + do_check_eq(ltm.parseTheme("invalid json"), null); + do_check_eq(ltm.parseTheme('"json string"'), null); + + function roundtrip(data, secure) { + return ltm.parseTheme(JSON.stringify(data), + "http" + (secure ? "s" : "") + "://lwttest.invalid/"); + } + + var data = dummy(); + do_check_neq(roundtrip(data), null); + data.id = null; + do_check_eq(roundtrip(data), null); + data.id = 1; + do_check_eq(roundtrip(data), null); + data.id = 1.5; + do_check_eq(roundtrip(data), null); + data.id = true; + do_check_eq(roundtrip(data), null); + data.id = {}; + do_check_eq(roundtrip(data), null); + data.id = []; + do_check_eq(roundtrip(data), null); + + // Check whether parseTheme handles international characters right + var chineseTheme2 = dummy(); + chineseTheme2.name = "眵昜湮桵蔗坌~郔乾"; + chineseTheme2.description = "眵昜湮桵蔗坌~郔乾"; + do_check_neq(roundtrip(chineseTheme2), null); + do_check_eq(roundtrip(chineseTheme2).name, "眵昜湮桵蔗坌~郔乾"); + do_check_eq(roundtrip(chineseTheme2).description, "眵昜湮桵蔗坌~郔乾"); + + data = dummy(); + data.unknownProperty = "Foo"; + do_check_eq(typeof roundtrip(data).unknownProperty, "undefined"); + + data = dummy(); + data.unknownURL = "http://lwttest.invalid/"; + do_check_eq(typeof roundtrip(data).unknownURL, "undefined"); + + function roundtripSet(props, modify, test, secure) { + props.forEach(function (prop) { + var data = dummy(); + modify(data, prop); + test(roundtrip(data, secure), prop, data); + }); + } + + roundtripSet(MANDATORY, function (data, prop) { + delete data[prop]; + }, function (after) { + do_check_eq(after, null); + }); + + roundtripSet(OPTIONAL, function (data, prop) { + delete data[prop]; + }, function (after) { + do_check_neq(after, null); + }); + + roundtripSet(MANDATORY, function (data, prop) { + data[prop] = ""; + }, function (after) { + do_check_eq(after, null); + }); + + roundtripSet(OPTIONAL, function (data, prop) { + data[prop] = ""; + }, function (after, prop) { + do_check_eq(typeof after[prop], "undefined"); + }); + + roundtripSet(MANDATORY, function (data, prop) { + data[prop] = " "; + }, function (after) { + do_check_eq(after, null); + }); + + roundtripSet(OPTIONAL, function (data, prop) { + data[prop] = " "; + }, function (after, prop) { + do_check_neq(after, null); + do_check_eq(typeof after[prop], "undefined"); + }); + + function non_urls(props) { + return props.filter(function (prop) !/URL$/.test(prop)); + } + + function urls(props) { + return props.filter(function (prop) /URL$/.test(prop)); + } + + roundtripSet(non_urls(MANDATORY.concat(OPTIONAL)), function (data, prop) { + data[prop] = prop; + }, function (after, prop, before) { + do_check_eq(after[prop], before[prop]); + }); + + roundtripSet(non_urls(MANDATORY.concat(OPTIONAL)), function (data, prop) { + data[prop] = " " + prop + " "; + }, function (after, prop, before) { + do_check_eq(after[prop], before[prop].trim()); + }); + + roundtripSet(urls(MANDATORY.concat(OPTIONAL)), function (data, prop) { + data[prop] = Math.random().toString(); + }, function (after, prop, before) { + if (prop == "updateURL") + do_check_eq(typeof after[prop], "undefined"); + else + do_check_eq(after[prop], "http://lwttest.invalid/" + before[prop]); + }); + + roundtripSet(urls(MANDATORY.concat(OPTIONAL)), function (data, prop) { + data[prop] = Math.random().toString(); + }, function (after, prop, before) { + do_check_eq(after[prop], "https://lwttest.invalid/" + before[prop]); + }, true); + + roundtripSet(urls(MANDATORY.concat(OPTIONAL)), function (data, prop) { + data[prop] = "https://sub.lwttest.invalid/" + Math.random().toString(); + }, function (after, prop, before) { + do_check_eq(after[prop], before[prop]); + }); + + roundtripSet(urls(MANDATORY), function (data, prop) { + data[prop] = "ftp://lwttest.invalid/" + Math.random().toString(); + }, function (after) { + do_check_eq(after, null); + }); + + roundtripSet(urls(OPTIONAL), function (data, prop) { + data[prop] = "ftp://lwttest.invalid/" + Math.random().toString(); + }, function (after, prop) { + do_check_eq(typeof after[prop], "undefined"); + }); + + do_check_eq(ltm.usedThemes.length, 0); + do_check_eq(ltm.currentTheme, null); + + data = dummy(); + delete data.name; + try { + ltm.currentTheme = data; + do_throw("Should have rejected a theme with no name"); + } + catch (e) { + // Expected exception + } + + data = dummy(); + data.headerURL = "foo"; + try { + ltm.currentTheme = data; + do_throw("Should have rejected a theme with a bad headerURL"); + } + catch (e) { + // Expected exception + } + + data = dummy(); + data.headerURL = "ftp://lwtest.invalid/test.png"; + try { + ltm.currentTheme = data; + do_throw("Should have rejected a theme with a non-http(s) headerURL"); + } + catch (e) { + // Expected exception + } + + data = dummy(); + data.headerURL = "file:///test.png"; + try { + ltm.currentTheme = data; + do_throw("Should have rejected a theme with a non-http(s) headerURL"); + } + catch (e) { + // Expected exception + } + + data = dummy(); + data.updateURL = "file:///test.json"; + ltm.setLocalTheme(data); + do_check_eq(ltm.usedThemes.length, 1); + do_check_eq(ltm.currentTheme.updateURL, undefined); + ltm.forgetUsedTheme(ltm.currentTheme.id); + do_check_eq(ltm.usedThemes.length, 0); + + data = dummy(); + data.headerURL = "file:///test.png"; + ltm.setLocalTheme(data); + do_check_eq(ltm.usedThemes.length, 1); + do_check_eq(ltm.currentTheme.headerURL, "file:///test.png"); + ltm.forgetUsedTheme(ltm.currentTheme.id); + do_check_eq(ltm.usedThemes.length, 0); + + data = dummy(); + data.headerURL = "ftp://lwtest.invalid/test.png"; + try { + ltm.setLocalTheme(data); + do_throw("Should have rejected a theme with a non-http(s), non-file headerURL"); + } + catch (e) { + // Expected exception + } + + data = dummy(); + delete data.id; + try { + ltm.currentTheme = data; + do_throw("Should have rejected a theme with no ID"); + } + catch (e) { + // Expected exception + } + + do_check_eq(ltm.usedThemes.length, 0); + do_check_eq(ltm.currentTheme, null); + + // Force the theme into the prefs anyway + let prefs = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefBranch); + let themes = [data]; + prefs.setCharPref("lightweightThemes.usedThemes", JSON.stringify(themes)); + do_check_eq(ltm.usedThemes.length, 1); + + // This should silently drop the bad theme. + ltm.currentTheme = dummy(); + do_check_eq(ltm.usedThemes.length, 1); + ltm.forgetUsedTheme(ltm.currentTheme.id); + do_check_eq(ltm.usedThemes.length, 0); + do_check_eq(ltm.currentTheme, null); + + // Add one broken and some working. + themes = [data, dummy("x1"), dummy("x2")]; + prefs.setCharPref("lightweightThemes.usedThemes", JSON.stringify(themes)); + do_check_eq(ltm.usedThemes.length, 3); + + // Switching to an existing theme should drop the bad theme. + ltm.currentTheme = ltm.getUsedTheme("x1"); + do_check_eq(ltm.usedThemes.length, 2); + ltm.forgetUsedTheme("x1"); + ltm.forgetUsedTheme("x2"); + do_check_eq(ltm.usedThemes.length, 0); + do_check_eq(ltm.currentTheme, null); + + prefs.setCharPref("lightweightThemes.usedThemes", JSON.stringify(themes)); + do_check_eq(ltm.usedThemes.length, 3); + + // Forgetting an existing theme should drop the bad theme. + ltm.forgetUsedTheme("x1"); + do_check_eq(ltm.usedThemes.length, 1); + ltm.forgetUsedTheme("x2"); + do_check_eq(ltm.usedThemes.length, 0); + do_check_eq(ltm.currentTheme, null); + + // Test whether a JSON set with setCharPref can be retrieved with usedThemes + ltm.currentTheme = dummy("x0"); + ltm.currentTheme = dummy("x1"); + prefs.setCharPref("lightweightThemes.usedThemes", JSON.stringify(ltm.usedThemes)); + do_check_eq(ltm.usedThemes.length, 2); + do_check_eq(ltm.currentTheme.id, "x1"); + do_check_eq(ltm.usedThemes[1].id, "x0"); + do_check_eq(ltm.usedThemes[0].id, "x1"); + + ltm.forgetUsedTheme("x0"); + do_check_eq(ltm.usedThemes.length, 1); + do_check_neq(ltm.currentTheme, null); + + ltm.forgetUsedTheme("x1"); + do_check_eq(ltm.usedThemes.length, 0); + do_check_eq(ltm.currentTheme, null); + + Services.prefs.clearUserPref("lightweightThemes.maxUsedThemes"); + + ltm.currentTheme = dummy("x1"); + ltm.currentTheme = dummy("x2"); + ltm.currentTheme = dummy("x3"); + ltm.currentTheme = dummy("x4"); + ltm.currentTheme = dummy("x5"); + ltm.currentTheme = dummy("x6"); + ltm.currentTheme = dummy("x7"); + ltm.currentTheme = dummy("x8"); + ltm.currentTheme = dummy("x9"); + ltm.currentTheme = dummy("x10"); + ltm.currentTheme = dummy("x11"); + ltm.currentTheme = dummy("x12"); + ltm.currentTheme = dummy("x13"); + ltm.currentTheme = dummy("x14"); + ltm.currentTheme = dummy("x15"); + ltm.currentTheme = dummy("x16"); + ltm.currentTheme = dummy("x17"); + ltm.currentTheme = dummy("x18"); + ltm.currentTheme = dummy("x19"); + ltm.currentTheme = dummy("x20"); + ltm.currentTheme = dummy("x21"); + ltm.currentTheme = dummy("x22"); + ltm.currentTheme = dummy("x23"); + ltm.currentTheme = dummy("x24"); + ltm.currentTheme = dummy("x25"); + ltm.currentTheme = dummy("x26"); + ltm.currentTheme = dummy("x27"); + ltm.currentTheme = dummy("x28"); + ltm.currentTheme = dummy("x29"); + ltm.currentTheme = dummy("x30"); + + do_check_eq(ltm.usedThemes.length, 30); + + ltm.currentTheme = dummy("x31"); + + do_check_eq(ltm.usedThemes.length, 30); + do_check_eq(ltm.getUsedTheme("x1"), null); + + Services.prefs.setIntPref("lightweightThemes.maxUsedThemes", 15); + + do_check_eq(ltm.usedThemes.length, 15); + + Services.prefs.setIntPref("lightweightThemes.maxUsedThemes", 32); + + ltm.currentTheme = dummy("x1"); + ltm.currentTheme = dummy("x2"); + ltm.currentTheme = dummy("x3"); + ltm.currentTheme = dummy("x4"); + ltm.currentTheme = dummy("x5"); + ltm.currentTheme = dummy("x6"); + ltm.currentTheme = dummy("x7"); + ltm.currentTheme = dummy("x8"); + ltm.currentTheme = dummy("x9"); + ltm.currentTheme = dummy("x10"); + ltm.currentTheme = dummy("x11"); + ltm.currentTheme = dummy("x12"); + ltm.currentTheme = dummy("x13"); + ltm.currentTheme = dummy("x14"); + ltm.currentTheme = dummy("x15"); + ltm.currentTheme = dummy("x16"); + + ltm.currentTheme = dummy("x32"); + + do_check_eq(ltm.usedThemes.length, 32); + + ltm.currentTheme = dummy("x33"); + + do_check_eq(ltm.usedThemes.length, 32); + + Services.prefs.clearUserPref("lightweightThemes.maxUsedThemes"); + + do_check_eq(ltm.usedThemes.length, 30); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_XPIStates.js b/toolkit/mozapps/extensions/test/xpcshell/test_XPIStates.js new file mode 100644 index 000000000..37ac161ca --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_XPIStates.js @@ -0,0 +1,299 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test that we only check manifest age for disabled extensions + +Components.utils.import("resource://gre/modules/Promise.jsm"); + +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +/* We want one add-on installed packed, and one installed unpacked + */ + +function run_test() { + // Shut down the add-on manager after all tests run. + do_register_cleanup(promiseShutdownManager); + // Kick off the task-based tests... + run_next_test(); +} + +// Use bootstrap extensions so the changes will be immediate. +// A packed extension, to be enabled +writeInstallRDFToXPI({ + id: "packed-enabled@tests.mozilla.org", + version: "1.0", + bootstrap: true, + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Packed, Enabled", +}, profileDir); + +// Packed, will be disabled +writeInstallRDFToXPI({ + id: "packed-disabled@tests.mozilla.org", + version: "1.0", + bootstrap: true, + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Packed, Disabled", +}, profileDir); + +// Unpacked, enabled +writeInstallRDFToDir({ + id: "unpacked-enabled@tests.mozilla.org", + version: "1.0", + bootstrap: true, + unpack: true, + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Unpacked, Enabled", +}, profileDir, null, "extraFile.js"); + + +// Unpacked, disabled +writeInstallRDFToDir({ + id: "unpacked-disabled@tests.mozilla.org", + version: "1.0", + bootstrap: true, + unpack: true, + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Unpacked, disabled", +}, profileDir, null, "extraFile.js"); + +// Keep track of the last time stamp we've used, so that we can keep moving +// it forward (if we touch two different files in the same add-on with the same +// timestamp we may not consider the change significant) +let lastTimestamp = Date.now(); + +/* + * Helper function to touch a file and then test whether we detect the change. + * @param XS The XPIState object. + * @param aPath File path to touch. + * @param aChange True if we should notice the change, False if we shouldn't. + */ +function checkChange(XS, aPath, aChange) { + do_check_true(aPath.exists()); + lastTimestamp += 10000; + do_print("Touching file " + aPath.path + " with " + lastTimestamp); + aPath.lastModifiedTime = lastTimestamp; + do_check_eq(XS.getInstallState(), aChange); + // Save the pref so we don't detect this change again + XS.save(); +} + +// Get a reference to the XPIState (loaded by startupManager) so we can unit test it. +function getXS() { + let XPI = Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm"); + return XPI.XPIStates; +} + +add_task(function* detect_touches() { + startupManager(); + let [pe, pd, ue, ud] = yield promiseAddonsByIDs([ + "packed-enabled@tests.mozilla.org", + "packed-disabled@tests.mozilla.org", + "unpacked-enabled@tests.mozilla.org", + "unpacked-disabled@tests.mozilla.org" + ]); + + do_print("Disable test add-ons"); + pd.userDisabled = true; + ud.userDisabled = true; + + let XS = getXS(); + + // Should be no changes detected here, because everything should start out up-to-date. + do_check_false(XS.getInstallState()); + + let states = XS.getLocation("app-profile"); + + // State should correctly reflect enabled/disabled + do_check_true(states.get("packed-enabled@tests.mozilla.org").enabled); + do_check_false(states.get("packed-disabled@tests.mozilla.org").enabled); + do_check_true(states.get("unpacked-enabled@tests.mozilla.org").enabled); + do_check_false(states.get("unpacked-disabled@tests.mozilla.org").enabled); + + // Touch various files and make sure the change is detected. + + // We notice that a packed XPI is touched for an enabled add-on. + let peFile = profileDir.clone(); + peFile.append("packed-enabled@tests.mozilla.org.xpi"); + checkChange(XS, peFile, true); + + // We should notice the packed XPI change for a disabled add-on too. + let pdFile = profileDir.clone(); + pdFile.append("packed-disabled@tests.mozilla.org.xpi"); + checkChange(XS, pdFile, true); + + // We notice changing install.rdf for an enabled unpacked add-on. + let ueDir = profileDir.clone(); + ueDir.append("unpacked-enabled@tests.mozilla.org"); + let manifest = ueDir.clone(); + manifest.append("install.rdf"); + checkChange(XS, manifest, true); + // We also notice changing another file for enabled unpacked add-on. + let otherFile = ueDir.clone(); + otherFile.append("extraFile.js"); + checkChange(XS, otherFile, true); + + // We notice changing install.rdf for a *disabled* unpacked add-on. + let udDir = profileDir.clone(); + udDir.append("unpacked-disabled@tests.mozilla.org"); + manifest = udDir.clone(); + manifest.append("install.rdf"); + checkChange(XS, manifest, true); + // Finally, the case we actually care about... + // We *don't* notice changing another file for disabled unpacked add-on. + otherFile = udDir.clone(); + otherFile.append("extraFile.js"); + checkChange(XS, otherFile, false); + + /* + * When we enable an unpacked add-on that was modified while it was + * disabled, we reflect the new timestamp in the add-on DB (otherwise, we'll + * think it changed on next restart). + */ + ud.userDisabled = false; + let xState = XS.getAddon("app-profile", ud.id); + do_check_true(xState.enabled); + do_check_eq(xState.scanTime, ud.updateDate.getTime()); +}); + +/* + * Uninstalling bootstrap add-ons should immediately remove them from the + * extensions.xpiState preference. + */ +add_task(function* uninstall_bootstrap() { + let [pe, pd, ue, ud] = yield promiseAddonsByIDs([ + "packed-enabled@tests.mozilla.org", + "packed-disabled@tests.mozilla.org", + "unpacked-enabled@tests.mozilla.org", + "unpacked-disabled@tests.mozilla.org" + ]); + pe.uninstall(); + let xpiState = Services.prefs.getCharPref("extensions.xpiState"); + do_check_false(xpiState.includes("\"packed-enabled@tests.mozilla.org\"")); +}); + +/* + * Installing a restartless add-on should immediately add it to XPIState + */ +add_task(function* install_bootstrap() { + let XS = getXS(); + + let installer = yield new Promise((resolve, reject) => + AddonManager.getInstallForFile(do_get_addon("test_bootstrap1_1"), resolve)); + + let promiseInstalled = new Promise((resolve, reject) => { + AddonManager.addInstallListener({ + onInstallFailed: reject, + onInstallEnded: (install, newAddon) => resolve(newAddon) + }); + }); + + installer.install(); + + let newAddon = yield promiseInstalled; + let xState = XS.getAddon("app-profile", newAddon.id); + do_check_true(!!xState); + do_check_true(xState.enabled); + do_check_eq(xState.scanTime, newAddon.updateDate.getTime()); + newAddon.uninstall(); +}); + +/* + * Installing an add-on that requires restart doesn't add to XPIState + * until after the restart; disable and enable happen immediately so that + * the next restart won't / will scan as necessary on the next restart, + * uninstalling it marks XPIState as disabled immediately + * and removes XPIState after restart. + */ +add_task(function* install_restart() { + let XS = getXS(); + + let installer = yield new Promise((resolve, reject) => + AddonManager.getInstallForFile(do_get_addon("test_bootstrap1_4"), resolve)); + + let promiseInstalled = new Promise((resolve, reject) => { + AddonManager.addInstallListener({ + onInstallFailed: reject, + onInstallEnded: (install, newAddon) => resolve(newAddon) + }); + }); + + installer.install(); + + let newAddon = yield promiseInstalled; + let newID = newAddon.id; + let xState = XS.getAddon("app-profile", newID); + do_check_false(xState); + + // Now we restart the add-on manager, and we need to get the XPIState again + // because the add-on manager reloads it. + XS = null; + newAddon = null; + yield promiseRestartManager(); + XS = getXS(); + + newAddon = yield promiseAddonByID(newID); + xState = XS.getAddon("app-profile", newID); + do_check_true(xState); + do_check_true(xState.enabled); + do_check_eq(xState.scanTime, newAddon.updateDate.getTime()); + + // Check that XPIState enabled flag is updated immediately, + // and doesn't change over restart. + newAddon.userDisabled = true; + do_check_false(xState.enabled); + XS = null; + newAddon = null; + yield promiseRestartManager(); + XS = getXS(); + xState = XS.getAddon("app-profile", newID); + do_check_true(xState); + do_check_false(xState.enabled); + + newAddon = yield promiseAddonByID(newID); + newAddon.userDisabled = false; + do_check_true(xState.enabled); + XS = null; + newAddon = null; + yield promiseRestartManager(); + XS = getXS(); + xState = XS.getAddon("app-profile", newID); + do_check_true(xState); + do_check_true(xState.enabled); + + // Uninstalling immediately marks XPIState disabled, + // removes state after restart. + newAddon = yield promiseAddonByID(newID); + newAddon.uninstall(); + xState = XS.getAddon("app-profile", newID); + do_check_true(xState); + do_check_false(xState.enabled); + + // Restart to finish uninstall. + XS = null; + newAddon = null; + yield promiseRestartManager(); + XS = getXS(); + xState = XS.getAddon("app-profile", newID); + do_check_false(xState); +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_XPIcancel.js b/toolkit/mozapps/extensions/test/xpcshell/test_XPIcancel.js new file mode 100644 index 000000000..7d8778301 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_XPIcancel.js @@ -0,0 +1,66 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test the cancellable doing/done/cancelAll API in XPIProvider + +let scope = Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm"); +let XPIProvider = scope.XPIProvider; + +function run_test() { + // Check that cancelling with nothing in progress doesn't blow up + XPIProvider.cancelAll(); + + // Check that a basic object gets cancelled + let getsCancelled = { + isCancelled: false, + cancel: function () { + if (this.isCancelled) + do_throw("Already cancelled"); + this.isCancelled = true; + } + }; + XPIProvider.doing(getsCancelled); + XPIProvider.cancelAll(); + do_check_true(getsCancelled.isCancelled); + + // Check that if we complete a cancellable, it doesn't get cancelled + let doesntGetCancelled = { + cancel: () => do_throw("This should not have been cancelled") + }; + XPIProvider.doing(doesntGetCancelled); + do_check_true(XPIProvider.done(doesntGetCancelled)); + XPIProvider.cancelAll(); + + // A cancellable that adds a cancellable + getsCancelled.isCancelled = false; + let addsAnother = { + isCancelled: false, + cancel: function () { + if (this.isCancelled) + do_throw("Already cancelled"); + this.isCancelled = true; + XPIProvider.doing(getsCancelled); + } + } + XPIProvider.doing(addsAnother); + XPIProvider.cancelAll(); + do_check_true(addsAnother.isCancelled); + do_check_true(getsCancelled.isCancelled); + + // A cancellable that removes another. This assumes that Set() iterates in the + // order that members were added + let removesAnother = { + isCancelled: false, + cancel: function () { + if (this.isCancelled) + do_throw("Already cancelled"); + this.isCancelled = true; + XPIProvider.done(doesntGetCancelled); + } + } + XPIProvider.doing(removesAnother); + XPIProvider.doing(doesntGetCancelled); + XPIProvider.cancelAll(); + do_check_true(removesAnother.isCancelled); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_addon_path_service.js b/toolkit/mozapps/extensions/test/xpcshell/test_addon_path_service.js new file mode 100644 index 000000000..30bb577a1 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_addon_path_service.js @@ -0,0 +1,38 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +let service = Components.classes["@mozilla.org/addon-path-service;1"].getService(Components.interfaces.amIAddonPathService); + +function insert(path, value) +{ + service.insertPath("/test/" + path, value); +} + +function find(path) +{ + return service.findAddonId("/test/" + path); +} + +function run_test() +{ + insert("abc", "10"); + insert("def", "11"); + insert("axy", "12"); + insert("defghij", "13"); + insert("defghi", "14"); + + do_check_eq(find("abc"), "10"); + do_check_eq(find("abc123"), "10"); + do_check_eq(find("def"), "11"); + do_check_eq(find("axy"), "12"); + do_check_eq(find("axy1"), "12"); + do_check_eq(find("defghij"), "13"); + do_check_eq(find("abd"), ""); + do_check_eq(find("x"), ""); + + insert("file:///home/billm/mozilla/in4/objdir-ff-dbg/dist/bin/browser/extensions/%7B972ce4c6-7e08-4474-a285-3208198ce6fd%7D/", "{972ce4c6-7e08-4474-a285-3208198ce6fd}"); + insert("file:///home/billm/mozilla/addons/dl-helper-workspace/addon/", "{b9db16a4-6edc-47ec-a1f4-b86292ed211d}"); + + do_check_eq(find("file:///home/billm/mozilla/addons/dl-helper-workspace/addon/local/modules/medialist-manager.jsm"), "{b9db16a4-6edc-47ec-a1f4-b86292ed211d}"); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_asyncBlocklistLoad.js b/toolkit/mozapps/extensions/test/xpcshell/test_asyncBlocklistLoad.js new file mode 100644 index 000000000..11d9f2943 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_asyncBlocklistLoad.js @@ -0,0 +1,44 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +function run_test() { + run_next_test(); +} + +add_task(function () { + let blocklist = AM_Cc["@mozilla.org/extensions/blocklist;1"]. + getService().wrappedJSObject; + let scope = Components.utils.import("resource://gre/modules/osfile.jsm"); + + // sync -> async + blocklist._loadBlocklist(); + do_check_true(blocklist._isBlocklistLoaded()); + yield blocklist._preloadBlocklist(); + do_check_false(blocklist._isBlocklistPreloaded()); + blocklist._clear(); + + // async -> sync + yield blocklist._preloadBlocklist(); + do_check_false(blocklist._isBlocklistLoaded()); + do_check_true(blocklist._isBlocklistPreloaded()); + blocklist._loadBlocklist(); + do_check_true(blocklist._isBlocklistLoaded()); + do_check_false(blocklist._isBlocklistPreloaded()); + blocklist._clear(); + + // async -> sync -> async + let read = scope.OS.File.read; + scope.OS.File.read = function(...args) { + return new Promise((resolve, reject) => { + do_execute_soon(() => { + blocklist._loadBlocklist(); + resolve(read(...args)); + }); + }); + } + + yield blocklist._preloadBlocklist(); + do_check_true(blocklist._isBlocklistLoaded()); + do_check_false(blocklist._isBlocklistPreloaded()); +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_backgroundupdate.js b/toolkit/mozapps/extensions/test/xpcshell/test_backgroundupdate.js new file mode 100644 index 000000000..d69c33e33 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_backgroundupdate.js @@ -0,0 +1,122 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that background updates & notifications work as expected + +// The test extension uses an insecure update url. +Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); + +Components.utils.import("resource://testing-common/httpd.js"); +var testserver = new HttpServer(); +testserver.start(-1); +gPort = testserver.identity.primaryPort; +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +// register static files with server and interpolate port numbers in them +mapFile("/data/test_backgroundupdate.rdf", testserver); + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + testserver.registerDirectory("/addons/", do_get_file("addons")); + + startupManager(); + + do_test_pending(); + run_test_1(); +} + +function end_test() { + testserver.stop(do_test_finished); +} + +// Verify that with no add-ons installed the background update notifications get +// called +function run_test_1() { + AddonManager.getAddonsByTypes(["extension", "theme", "locale"], function(aAddons) { + do_check_eq(aAddons.length, 0); + + Services.obs.addObserver(function() { + Services.obs.removeObserver(arguments.callee, "addons-background-update-complete"); + + do_execute_soon(run_test_2); + }, "addons-background-update-complete", false); + + // Trigger the background update timer handler + gInternalManager.notify(null); + }); +} + +// Verify that with two add-ons installed both of which claim to have updates +// available we get the notification after both updates attempted to start +function run_test_2() { + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_backgroundupdate.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:" + gPort + "/data/test_backgroundupdate.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 2", + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon3@tests.mozilla.org", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 3", + }, profileDir); + + // Background update uses a different pref, if set + Services.prefs.setCharPref("extensions.update.background.url", + "http://localhost:" + gPort +"/data/test_backgroundupdate.rdf"); + restartManager(); + + let installCount = 0; + let completeCount = 0; + let sawCompleteNotification = false; + + Services.obs.addObserver(function() { + Services.obs.removeObserver(arguments.callee, "addons-background-update-complete"); + + do_check_eq(installCount, 3); + sawCompleteNotification = true; + }, "addons-background-update-complete", false); + + AddonManager.addInstallListener({ + onNewInstall: function(aInstall) { + installCount++; + }, + + onDownloadFailed: function(aInstall) { + completeCount++; + if (completeCount == 3) { + do_check_true(sawCompleteNotification); + end_test(); + } + } + }); + + // Trigger the background update timer handler + gInternalManager.notify(null); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bad_json.js b/toolkit/mozapps/extensions/test/xpcshell/test_bad_json.js new file mode 100644 index 000000000..d3ccf68f3 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bad_json.js @@ -0,0 +1,54 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that we rebuild the database correctly if it contains +// JSON data that parses correctly but doesn't contain required fields + +var addon1 = { + id: "addon1@tests.mozilla.org", + version: "2.0", + name: "Test 1", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +function run_test() { + do_test_pending("Bad JSON"); + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + // This addon will be auto-installed at startup + writeInstallRDFForExtension(addon1, profileDir); + + startupManager(); + + shutdownManager(); + + // First startup/shutdown finished + // Replace the JSON store with something bogus + saveJSON({not: "what we expect to find"}, gExtensionsJSON); + + startupManager(false); + // Retrieve an addon to force the database to rebuild + AddonManager.getAddonsByIDs([addon1.id], callback_soon(after_db_rebuild)); +} + +function after_db_rebuild([a1]) { + do_check_eq(a1.id, addon1.id); + + shutdownManager(); + + // Make sure our JSON database has schemaVersion and our installed extension + let data = loadJSON(gExtensionsJSON); + do_check_true("schemaVersion" in data); + do_check_eq(data.addons[0].id, addon1.id); + + do_test_finished("Bad JSON"); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_badschema.js b/toolkit/mozapps/extensions/test/xpcshell/test_badschema.js new file mode 100644 index 000000000..6ebf088d6 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_badschema.js @@ -0,0 +1,404 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Checks that we rebuild something sensible from a database with a bad schema + + +Components.utils.import("resource://testing-common/httpd.js"); +var testserver = new HttpServer(); +testserver.start(-1); +gPort = testserver.identity.primaryPort; + +// register static files with server and interpolate port numbers in them +mapFile("/data/test_corrupt.rdf", testserver); + +// The test extension uses an insecure update url. +Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); + +// 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:" + gPort + "/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:" + gPort + "/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.registerDirectory("/addons/", do_get_file("addons")); + + // 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() { + do_execute_soon(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() { + 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_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); + + do_execute_soon(run_test_1_modified_db); + }); +} + + +function run_test_1_modified_db() { + // After restarting the database won't be open so we can alter + // the schema + shutdownManager(); + changeXPIDBVersion(100); + startupManager(); + + // Accessing the add-ons should open and recover the database. Since + // migration occurs everything should be recovered correctly + 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); + + do_execute_soon(run_test_1_after_rebuild); + }); +} + +function run_test_1_after_rebuild() { + 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_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); + + end_test(); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_metadata_filters.js b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_metadata_filters.js new file mode 100644 index 000000000..15e951bce --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_metadata_filters.js @@ -0,0 +1,159 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests blocking of extensions by ID, name, creator, homepageURL, updateURL +// and RegExps for each. See bug 897735. + +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; + +const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul"; + +Cu.import("resource://testing-common/httpd.js"); +var testserver = new HttpServer(); +testserver.start(-1); +gPort = testserver.identity.primaryPort; + +// register static files with server and interpolate port numbers in them +mapFile("/data/test_blocklist_metadata_filters_1.xml", testserver); + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +// Don't need the full interface, attempts to call other methods will just +// throw which is just fine +var WindowWatcher = { + openWindow: function(parent, url, name, features, arguments) { + // Should be called to list the newly blocklisted items + do_check_eq(url, URI_EXTENSION_BLOCKLIST_DIALOG); + + // Simulate auto-disabling any softblocks + var list = arguments.wrappedJSObject.list; + list.forEach(function(aItem) { + if (!aItem.blocked) + aItem.disable = true; + }); + + //run the code after the blocklist is closed + Services.obs.notifyObservers(null, "addon-blocklist-closed", null); + + }, + + QueryInterface: function(iid) { + if (iid.equals(Ci.nsIWindowWatcher) + || iid.equals(Ci.nsISupports)) + return this; + + throw Cr.NS_ERROR_NO_INTERFACE; + } +}; + +var WindowWatcherFactory = { + createInstance: function createInstance(outer, iid) { + if (outer != null) + throw Cr.NS_ERROR_NO_AGGREGATION; + return WindowWatcher.QueryInterface(iid); + } +}; + +var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"), + "Fake Window Watcher", + "@mozilla.org/embedcomp/window-watcher;1", + WindowWatcherFactory); + + +function load_blocklist(aFile, aCallback) { + Services.obs.addObserver(function() { + Services.obs.removeObserver(arguments.callee, "blocklist-updated"); + + do_execute_soon(aCallback); + }, "blocklist-updated", false); + + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + + gPort + "/data/" + aFile); + var blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. + getService(Ci.nsITimerCallback); + blocklist.notify(null); +} + + +function end_test() { + testserver.stop(do_test_finished); +} + +function run_test() { + do_test_pending(); + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); + + // Should get blocked by name + writeInstallRDFForExtension({ + id: "block1@tests.mozilla.org", + version: "1.0", + name: "Mozilla Corp.", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] + }, profileDir); + + // Should get blocked by all the attributes. + writeInstallRDFForExtension({ + id: "block2@tests.mozilla.org", + version: "1.0", + name: "Moz-addon", + creator: "Dangerous", + homepageURL: "www.extension.dangerous.com", + updateURL: "www.extension.dangerous.com/update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] + }, profileDir); + + // Fails to get blocked because of a different ID even though other + // attributes match against a blocklist entry. + writeInstallRDFForExtension({ + id: "block3@tests.mozilla.org", + version: "1.0", + name: "Moz-addon", + creator: "Dangerous", + homepageURL: "www.extensions.dangerous.com", + updateURL: "www.extension.dangerous.com/update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] + }, profileDir); + + startupManager(); + + AddonManager.getAddonsByIDs(["block1@tests.mozilla.org", + "block2@tests.mozilla.org", + "block3@tests.mozilla.org"], function([a1, a2, a3]) { + do_check_eq(a1.blocklistState, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + do_check_eq(a2.blocklistState, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + do_check_eq(a3.blocklistState, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + + run_test_1(); + }); +} + +function run_test_1() { + load_blocklist("test_blocklist_metadata_filters_1.xml", function() { + restartManager(); + + AddonManager.getAddonsByIDs(["block1@tests.mozilla.org", + "block2@tests.mozilla.org", + "block3@tests.mozilla.org"], function([a1, a2, a3]) { + do_check_eq(a1.blocklistState, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + do_check_eq(a2.blocklistState, Ci.nsIBlocklistService.STATE_BLOCKED); + do_check_eq(a3.blocklistState, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + end_test(); + }); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_prefs.js b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_prefs.js new file mode 100644 index 000000000..71112387b --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_prefs.js @@ -0,0 +1,159 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests resetting of preferences in blocklist entry when an add-on is blocked. +// See bug 802434. + +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; + +const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul"; + +XPCOMUtils.defineLazyGetter(this, "gPref", function bls_gPref() { + return Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService). + QueryInterface(Ci.nsIPrefBranch); +}); + +Cu.import("resource://testing-common/httpd.js"); +var testserver = new HttpServer(); +testserver.start(-1); +gPort = testserver.identity.primaryPort; + +// register static files with server and interpolate port numbers in them +mapFile("/data/test_blocklist_prefs_1.xml", testserver); + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +// A window watcher to handle the blocklist UI. +// Don't need the full interface, attempts to call other methods will just +// throw which is just fine +var WindowWatcher = { + openWindow: function(parent, url, name, features, arguments) { + // Should be called to list the newly blocklisted items + do_check_eq(url, URI_EXTENSION_BLOCKLIST_DIALOG); + + // Simulate auto-disabling any softblocks + var list = arguments.wrappedJSObject.list; + list.forEach(function(aItem) { + if (!aItem.blocked) + aItem.disable = true; + }); + + //run the code after the blocklist is closed + Services.obs.notifyObservers(null, "addon-blocklist-closed", null); + + }, + + QueryInterface: function(iid) { + if (iid.equals(Ci.nsIWindowWatcher) + || iid.equals(Ci.nsISupports)) + return this; + + throw Cr.NS_ERROR_NO_INTERFACE; + } +}; + +var WindowWatcherFactory = { + createInstance: function createInstance(outer, iid) { + if (outer != null) + throw Cr.NS_ERROR_NO_AGGREGATION; + return WindowWatcher.QueryInterface(iid); + } +}; + +var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"), + "Fake Window Watcher", + "@mozilla.org/embedcomp/window-watcher;1", + WindowWatcherFactory); + +function load_blocklist(aFile, aCallback) { + Services.obs.addObserver(function() { + Services.obs.removeObserver(arguments.callee, "blocklist-updated"); + + do_execute_soon(aCallback); + }, "blocklist-updated", false); + + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + + gPort + "/data/" + aFile); + var blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. + getService(Ci.nsITimerCallback); + blocklist.notify(null); +} + +function end_test() { + testserver.stop(do_test_finished); +} + +function run_test() { + do_test_pending(); + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); + + // Add 2 extensions + writeInstallRDFForExtension({ + id: "block1@tests.mozilla.org", + version: "1.0", + name: "Blocked add-on-1 with to-be-reset prefs", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] + }, profileDir); + + writeInstallRDFForExtension({ + id: "block2@tests.mozilla.org", + version: "1.0", + name: "Blocked add-on-2 with to-be-reset prefs", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] + }, profileDir); + + // Pre-set the preferences that we expect to get reset. + gPref.setIntPref("test.blocklist.pref1", 15); + gPref.setIntPref("test.blocklist.pref2", 15); + gPref.setBoolPref("test.blocklist.pref3", true); + gPref.setBoolPref("test.blocklist.pref4", true); + + startupManager(); + + // Before blocklist is loaded. + AddonManager.getAddonsByIDs(["block1@tests.mozilla.org", + "block2@tests.mozilla.org"], function([a1, a2]) { + do_check_eq(a1.blocklistState, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + do_check_eq(a2.blocklistState, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + + do_check_eq(gPref.getIntPref("test.blocklist.pref1"), 15); + do_check_eq(gPref.getIntPref("test.blocklist.pref2"), 15); + do_check_eq(gPref.getBoolPref("test.blocklist.pref3"), true); + do_check_eq(gPref.getBoolPref("test.blocklist.pref4"), true); + run_test_1(); + }); +} + +function run_test_1() { + load_blocklist("test_blocklist_prefs_1.xml", function() { + restartManager(); + + // Blocklist changes should have applied and the prefs must be reset. + AddonManager.getAddonsByIDs(["block1@tests.mozilla.org", + "block2@tests.mozilla.org"], function([a1, a2]) { + do_check_neq(a1, null); + do_check_eq(a1.blocklistState, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + do_check_neq(a2, null); + do_check_eq(a2.blocklistState, Ci.nsIBlocklistService.STATE_BLOCKED); + + // All these prefs must be reset to defaults. + do_check_eq(gPref.prefHasUserValue("test.blocklist.pref1"), false); + do_check_eq(gPref.prefHasUserValue("test.blocklist.pref2"), false); + do_check_eq(gPref.prefHasUserValue("test.blocklist.pref3"), false); + do_check_eq(gPref.prefHasUserValue("test.blocklist.pref4"), false); + end_test(); + }); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_regexp.js b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_regexp.js new file mode 100644 index 000000000..d9acf7170 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_regexp.js @@ -0,0 +1,125 @@ +/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Checks that blocklist entries using RegExp work as expected. This only covers
+// behavior specific to RegExp entries - general behavior is already tested
+// in test_blocklistchange.js.
+
+const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
+
+const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul";
+
+Cu.import("resource://testing-common/httpd.js");
+var testserver = new HttpServer();
+testserver.start(-1);
+gPort = testserver.identity.primaryPort;
+
+// register static files with server and interpolate port numbers in them
+mapFile("/data/test_blocklist_regexp_1.xml", testserver);
+
+const profileDir = gProfD.clone();
+profileDir.append("extensions");
+
+// Don't need the full interface, attempts to call other methods will just
+// throw which is just fine
+var WindowWatcher = {
+ openWindow: function(parent, url, name, features, arguments) {
+ // Should be called to list the newly blocklisted items
+ do_check_eq(url, URI_EXTENSION_BLOCKLIST_DIALOG);
+
+ // Simulate auto-disabling any softblocks
+ var list = arguments.wrappedJSObject.list;
+ list.forEach(function(aItem) {
+ if (!aItem.blocked)
+ aItem.disable = true;
+ });
+
+ //run the code after the blocklist is closed
+ Services.obs.notifyObservers(null, "addon-blocklist-closed", null);
+
+ },
+
+ QueryInterface: function(iid) {
+ if (iid.equals(Ci.nsIWindowWatcher)
+ || iid.equals(Ci.nsISupports))
+ return this;
+
+ throw Cr.NS_ERROR_NO_INTERFACE;
+ }
+};
+
+var WindowWatcherFactory = {
+ createInstance: function createInstance(outer, iid) {
+ if (outer != null)
+ throw Cr.NS_ERROR_NO_AGGREGATION;
+ return WindowWatcher.QueryInterface(iid);
+ }
+};
+
+var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
+registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"),
+ "Fake Window Watcher",
+ "@mozilla.org/embedcomp/window-watcher;1",
+ WindowWatcherFactory);
+
+
+function load_blocklist(aFile, aCallback) {
+ Services.obs.addObserver(function() {
+ Services.obs.removeObserver(arguments.callee, "blocklist-updated");
+
+ do_execute_soon(aCallback);
+ }, "blocklist-updated", false);
+
+ Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" +
+ gPort + "/data/" + aFile);
+ var blocklist = Cc["@mozilla.org/extensions/blocklist;1"].
+ getService(Ci.nsITimerCallback);
+ blocklist.notify(null);
+}
+
+
+function end_test() {
+ testserver.stop(do_test_finished);
+}
+
+
+function run_test() {
+ do_test_pending();
+
+ createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1");
+
+ writeInstallRDFForExtension({
+ id: "block1@tests.mozilla.org",
+ version: "1.0",
+ name: "RegExp blocked add-on",
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "1",
+ maxVersion: "3"
+ }]
+ }, profileDir);
+
+ startupManager();
+
+ AddonManager.getAddonsByIDs(["block1@tests.mozilla.org"], function([a1]) {
+ do_check_eq(a1.blocklistState, Ci.nsIBlocklistService.STATE_NOT_BLOCKED);
+
+ run_test_1();
+ });
+}
+
+function run_test_1() {
+ load_blocklist("test_blocklist_regexp_1.xml", function() {
+ restartManager();
+
+ AddonManager.getAddonsByIDs(["block1@tests.mozilla.org"], function([a1]) {
+ // Blocklist contains two entries that will match this addon - ensure
+ // that the first one is applied.
+ do_check_neq(a1, null);
+ do_check_eq(a1.blocklistState, Ci.nsIBlocklistService.STATE_SOFTBLOCKED);
+
+ end_test();
+ });
+ });
+}
diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_blocklistchange.js b/toolkit/mozapps/extensions/test/xpcshell/test_blocklistchange.js new file mode 100644 index 000000000..46f939943 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_blocklistchange.js @@ -0,0 +1,1321 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Checks that changes that cause an add-on to become unblocked or blocked have +// the right effect + +// The tests follow a mostly common pattern. First they start with the add-ons +// unblocked, then they make a change that causes the add-ons to become blocked +// then they make a similar change that keeps the add-ons blocked then they make +// a change that unblocks the add-ons. Some tests skip the initial part and +// start with add-ons detected as blocked. + +// softblock1 is enabled/disabled by the blocklist changes so its softDisabled +// property should always match its userDisabled property + +// softblock2 gets manually enabled then disabled after it becomes blocked so +// its softDisabled property should never become true after that + +// softblock3 does the same as softblock2 however it remains disabled + +// softblock4 is disabled while unblocked and so should never have softDisabled +// set to true and stay userDisabled. This add-on is not used in tests that +// start with add-ons blocked as it would be identical to softblock3 + +// softblock5 is a theme. Currently themes just get disabled when they become +// softblocked and have to be manually re-enabled if they become completely +// unblocked (bug 657520) + +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; +const Cr = Components.results; + +const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul"; + +Cu.import("resource://gre/modules/NetUtil.jsm"); + +// Allow insecure updates +Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false) + +Cu.import("resource://testing-common/httpd.js"); +var testserver = new HttpServer(); +testserver.start(-1); +gPort = testserver.identity.primaryPort; + +// register static files with server and interpolate port numbers in them +mapFile("/data/blocklistchange/addon_update1.rdf", testserver); +mapFile("/data/blocklistchange/addon_update2.rdf", testserver); +mapFile("/data/blocklistchange/addon_update3.rdf", testserver); +mapFile("/data/blocklistchange/addon_change.xml", testserver); +mapFile("/data/blocklistchange/app_update.xml", testserver); +mapFile("/data/blocklistchange/blocklist_update1.xml", testserver); +mapFile("/data/blocklistchange/blocklist_update2.xml", testserver); +mapFile("/data/blocklistchange/manual_update.xml", testserver); + +testserver.registerDirectory("/addons/", do_get_file("addons")); + + +var default_theme = { + id: "default@tests.mozilla.org", + version: "1.0", + name: "Softblocked add-on", + internalName: "classic/1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] +}; + +var softblock1_1 = { + id: "softblock1@tests.mozilla.org", + version: "1.0", + name: "Softblocked add-on", + updateURL: "http://localhost:" + gPort + "/data/blocklistchange/addon_update1.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] +}; + +var softblock1_2 = { + id: "softblock1@tests.mozilla.org", + version: "2.0", + name: "Softblocked add-on", + updateURL: "http://localhost:" + gPort + "/data/blocklistchange/addon_update2.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] +}; + +var softblock1_3 = { + id: "softblock1@tests.mozilla.org", + version: "3.0", + name: "Softblocked add-on", + updateURL: "http://localhost:" + gPort + "/data/blocklistchange/addon_update3.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] +}; + +var softblock2_1 = { + id: "softblock2@tests.mozilla.org", + version: "1.0", + name: "Softblocked add-on", + updateURL: "http://localhost:" + gPort + "/data/blocklistchange/addon_update1.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] +}; + +var softblock2_2 = { + id: "softblock2@tests.mozilla.org", + version: "2.0", + name: "Softblocked add-on", + updateURL: "http://localhost:" + gPort + "/data/blocklistchange/addon_update2.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] +}; + +var softblock2_3 = { + id: "softblock2@tests.mozilla.org", + version: "3.0", + name: "Softblocked add-on", + updateURL: "http://localhost:" + gPort + "/data/blocklistchange/addon_update3.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] +}; + +var softblock3_1 = { + id: "softblock3@tests.mozilla.org", + version: "1.0", + name: "Softblocked add-on", + updateURL: "http://localhost:" + gPort + "/data/blocklistchange/addon_update1.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] +}; + +var softblock3_2 = { + id: "softblock3@tests.mozilla.org", + version: "2.0", + name: "Softblocked add-on", + updateURL: "http://localhost:" + gPort + "/data/blocklistchange/addon_update2.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] +}; + +var softblock3_3 = { + id: "softblock3@tests.mozilla.org", + version: "3.0", + name: "Softblocked add-on", + updateURL: "http://localhost:" + gPort + "/data/blocklistchange/addon_update3.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] +}; + +var softblock4_1 = { + id: "softblock4@tests.mozilla.org", + version: "1.0", + name: "Softblocked add-on", + updateURL: "http://localhost:" + gPort + "/data/blocklistchange/addon_update1.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] +}; + +var softblock4_2 = { + id: "softblock4@tests.mozilla.org", + version: "2.0", + name: "Softblocked add-on", + updateURL: "http://localhost:" + gPort + "/data/blocklistchange/addon_update2.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] +}; + +var softblock4_3 = { + id: "softblock4@tests.mozilla.org", + version: "3.0", + name: "Softblocked add-on", + updateURL: "http://localhost:" + gPort + "/data/blocklistchange/addon_update3.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] +}; + +var softblock5_1 = { + id: "softblock5@tests.mozilla.org", + version: "1.0", + name: "Softblocked add-on", + updateURL: "http://localhost:" + gPort + "/data/blocklistchange/addon_update1.rdf", + internalName: "test/1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] +}; + +var softblock5_2 = { + id: "softblock5@tests.mozilla.org", + version: "2.0", + name: "Softblocked add-on", + updateURL: "http://localhost:" + gPort + "/data/blocklistchange/addon_update2.rdf", + internalName: "test/1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] +}; + +var softblock5_3 = { + id: "softblock5@tests.mozilla.org", + version: "3.0", + name: "Softblocked add-on", + updateURL: "http://localhost:" + gPort + "/data/blocklistchange/addon_update3.rdf", + internalName: "test/1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] +}; + +var hardblock_1 = { + id: "hardblock@tests.mozilla.org", + version: "1.0", + name: "Hardblocked add-on", + updateURL: "http://localhost:" + gPort + "/data/blocklistchange/addon_update1.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] +}; + +var hardblock_2 = { + id: "hardblock@tests.mozilla.org", + version: "2.0", + name: "Hardblocked add-on", + updateURL: "http://localhost:" + gPort + "/data/blocklistchange/addon_update2.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] +}; + +var hardblock_3 = { + id: "hardblock@tests.mozilla.org", + version: "3.0", + name: "Hardblocked add-on", + updateURL: "http://localhost:" + gPort + "/data/blocklistchange/addon_update3.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] +}; + +var regexpblock_1 = { + id: "regexpblock@tests.mozilla.org", + version: "1.0", + name: "RegExp-blocked add-on", + updateURL: "http://localhost:" + gPort + "/data/blocklistchange/addon_update1.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] +}; + +var regexpblock_2 = { + id: "regexpblock@tests.mozilla.org", + version: "2.0", + name: "RegExp-blocked add-on", + updateURL: "http://localhost:" + gPort + "/data/blocklistchange/addon_update2.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] +}; + +var regexpblock_3 = { + id: "regexpblock@tests.mozilla.org", + version: "3.0", + name: "RegExp-blocked add-on", + updateURL: "http://localhost:" + gPort + "/data/blocklistchange/addon_update3.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] +}; + +const ADDON_IDS = ["softblock1@tests.mozilla.org", + "softblock2@tests.mozilla.org", + "softblock3@tests.mozilla.org", + "softblock4@tests.mozilla.org", + "softblock5@tests.mozilla.org", + "hardblock@tests.mozilla.org", + "regexpblock@tests.mozilla.org"]; + +// Don't need the full interface, attempts to call other methods will just +// throw which is just fine +var WindowWatcher = { + openWindow: function(parent, url, name, features, openArgs) { + // Should be called to list the newly blocklisted items + do_check_eq(url, URI_EXTENSION_BLOCKLIST_DIALOG); + + // Simulate auto-disabling any softblocks + var list = openArgs.wrappedJSObject.list; + list.forEach(function(aItem) { + if (!aItem.blocked) + aItem.disable = true; + }); + + //run the code after the blocklist is closed + Services.obs.notifyObservers(null, "addon-blocklist-closed", null); + + }, + + QueryInterface: function(iid) { + if (iid.equals(Ci.nsIWindowWatcher) + || iid.equals(Ci.nsISupports)) + return this; + + throw Cr.NS_ERROR_NO_INTERFACE; + } +}; + +var WindowWatcherFactory = { + createInstance: function createInstance(outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return WindowWatcher.QueryInterface(iid); + } +}; + +var InstallConfirm = { + confirm: function(aWindow, aUrl, aInstalls, aInstallCount) { + aInstalls.forEach(function(aInstall) { + aInstall.install(); + }); + }, + + QueryInterface: function(iid) { + if (iid.equals(Ci.amIWebInstallPrompt) + || iid.equals(Ci.nsISupports)) + return this; + + throw Cr.NS_ERROR_NO_INTERFACE; + } +}; + +var InstallConfirmFactory = { + createInstance: function createInstance(outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return InstallConfirm.QueryInterface(iid); + } +}; + +var registrar = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"), + "Fake Window Watcher", + "@mozilla.org/embedcomp/window-watcher;1", WindowWatcherFactory); +registrar.registerFactory(Components.ID("{f0863905-4dde-42e2-991c-2dc8209bc9ca}"), + "Fake Install Prompt", + "@mozilla.org/addons/web-install-prompt;1", InstallConfirmFactory); + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +function Pload_blocklist(aFile) { + let blocklist_updated = new Promise((resolve, reject) => { + Services.obs.addObserver(function() { + Services.obs.removeObserver(arguments.callee, "blocklist-updated"); + + resolve(); + }, "blocklist-updated", false); + }); + + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + gPort + "/data/blocklistchange/" + aFile); + var blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. + getService(Ci.nsITimerCallback); + blocklist.notify(null); + return blocklist_updated; +} + +// Does a background update check for add-ons and returns a promise that +// resolves when any started installs complete +function Pbackground_update() { + var installCount = 0; + var backgroundCheckCompleted = false; + + let updated = new Promise((resolve, reject) => { + AddonManager.addInstallListener({ + onNewInstall: function(aInstall) { + installCount++; + }, + + onInstallEnded: function(aInstall) { + installCount--; + // Wait until all started installs have completed + if (installCount) + return; + + AddonManager.removeInstallListener(this); + + // If the background check hasn't yet completed then let that call the + // callback when it is done + if (!backgroundCheckCompleted) + return; + + resolve(); + } + }) + + Services.obs.addObserver(function() { + Services.obs.removeObserver(arguments.callee, "addons-background-update-complete"); + backgroundCheckCompleted = true; + + // If any new installs have started then we'll call the callback once they + // are completed + if (installCount) + return; + + resolve(); + }, "addons-background-update-complete", false); + }); + + AddonManagerPrivate.backgroundUpdateCheck(); + return updated; +} + +// Manually updates the test add-ons to the given version +function Pmanual_update(aVersion) { + let Pinstalls = []; + for (let name of ["soft1", "soft2", "soft3", "soft4", "soft5", "hard1", "regexp1"]) { + Pinstalls.push(new Promise((resolve, reject) => { + AddonManager.getInstallForURL("http://localhost:" + gPort + "/addons/blocklist_" + + name + "_" + aVersion + ".xpi", + resolve, "application/x-xpinstall"); + })); + } + + return Promise.all(Pinstalls).then(installs => { + let completePromises = []; + for (let install of installs) { + completePromises.push(new Promise(resolve => { + install.addListener({ + onDownloadCancelled: resolve, + onInstallEnded: resolve + }) + })); + } + + // Use the default web installer to cancel/allow installs based on whether + // the add-on is valid or not. + let webInstaller = Cc["@mozilla.org/addons/web-install-listener;1"] + .getService(Ci.amIWebInstallListener); + webInstaller.onWebInstallRequested(null, null, installs, installs.length); + + return Promise.all(completePromises); + }); +} + +// Checks that an add-ons properties match expected values +function check_addon(aAddon, aExpectedVersion, aExpectedUserDisabled, + aExpectedSoftDisabled, aExpectedState) { + do_check_neq(aAddon, null); + do_print("Testing " + aAddon.id + " version " + aAddon.version + " user " + + aAddon.userDisabled + " soft " + aAddon.softDisabled + + " perms " + aAddon.permissions); + + do_check_eq(aAddon.version, aExpectedVersion); + do_check_eq(aAddon.blocklistState, aExpectedState); + do_check_eq(aAddon.userDisabled, aExpectedUserDisabled); + do_check_eq(aAddon.softDisabled, aExpectedSoftDisabled); + if (aAddon.softDisabled) + do_check_true(aAddon.userDisabled); + + if (aExpectedState == Ci.nsIBlocklistService.STATE_BLOCKED) { + do_print("blocked, PERM_CAN_ENABLE " + aAddon.id); + do_check_false(hasFlag(aAddon.permissions, AddonManager.PERM_CAN_ENABLE)); + do_print("blocked, PERM_CAN_DISABLE " + aAddon.id); + do_check_false(hasFlag(aAddon.permissions, AddonManager.PERM_CAN_DISABLE)); + } + else if (aAddon.userDisabled) { + do_print("userDisabled, PERM_CAN_ENABLE " + aAddon.id); + do_check_true(hasFlag(aAddon.permissions, AddonManager.PERM_CAN_ENABLE)); + do_print("userDisabled, PERM_CAN_DISABLE " + aAddon.id); + do_check_false(hasFlag(aAddon.permissions, AddonManager.PERM_CAN_DISABLE)); + } + else { + do_print("other, PERM_CAN_ENABLE " + aAddon.id); + do_check_false(hasFlag(aAddon.permissions, AddonManager.PERM_CAN_ENABLE)); + if (aAddon.type != "theme") { + do_print("other, PERM_CAN_DISABLE " + aAddon.id); + do_check_true(hasFlag(aAddon.permissions, AddonManager.PERM_CAN_DISABLE)); + } + } + do_check_eq(aAddon.appDisabled, aExpectedState == Ci.nsIBlocklistService.STATE_BLOCKED); + + let willBeActive = aAddon.isActive; + if (hasFlag(aAddon.pendingOperations, AddonManager.PENDING_DISABLE)) + willBeActive = false; + else if (hasFlag(aAddon.pendingOperations, AddonManager.PENDING_ENABLE)) + willBeActive = true; + + if (aExpectedUserDisabled || aExpectedState == Ci.nsIBlocklistService.STATE_BLOCKED) { + do_check_false(willBeActive); + } + else { + do_check_true(willBeActive); + } +} + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); + run_next_test(); +} + +add_task(function* init() { + writeInstallRDFForExtension(default_theme, profileDir); + writeInstallRDFForExtension(softblock1_1, profileDir); + writeInstallRDFForExtension(softblock2_1, profileDir); + writeInstallRDFForExtension(softblock3_1, profileDir); + writeInstallRDFForExtension(softblock4_1, profileDir); + writeInstallRDFForExtension(softblock5_1, profileDir); + writeInstallRDFForExtension(hardblock_1, profileDir); + writeInstallRDFForExtension(regexpblock_1, profileDir); + startupManager(); + + let [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + s4.userDisabled = true; + s5.userDisabled = false; +}); + +// Starts with add-ons unblocked and then switches application versions to +// change add-ons to blocked and back +add_task(function* run_app_update_test() { + do_print("Test: " + arguments.callee.name); + yield promiseRestartManager(); + yield Pload_blocklist("app_update.xml"); + yield promiseRestartManager(); + + let [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s2, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s3, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s4, "1.0", true, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s5, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + do_check_eq(Services.prefs.getCharPref("general.skins.selectedSkin"), "test/1.0"); +}); + +add_task(function* app_update_step_2() { + yield promiseRestartManager("2"); + + let [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s2, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s3, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s4, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s5, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + do_check_eq(Services.prefs.getCharPref("general.skins.selectedSkin"), "classic/1.0"); + + s2.userDisabled = false; + s2.userDisabled = true; + check_addon(s2, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + s3.userDisabled = false; + check_addon(s3, "1.0", false, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); +}); + +add_task(function* app_update_step_3() { + yield promiseRestartManager(); + + yield promiseRestartManager("2.5"); + + let [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s2, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s3, "1.0", false, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s4, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s5, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + do_check_eq(Services.prefs.getCharPref("general.skins.selectedSkin"), "classic/1.0"); +}); + +add_task(function* app_update_step_4() { + yield promiseRestartManager("1"); + + let [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s2, "1.0", true, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s3, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s4, "1.0", true, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s5, "1.0", true, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + do_check_eq(Services.prefs.getCharPref("general.skins.selectedSkin"), "classic/1.0"); + + s1.userDisabled = false; + s2.userDisabled = false; + s5.userDisabled = false; +}); + +// Starts with add-ons unblocked and then switches application versions to +// change add-ons to blocked and back. A DB schema change is faked to force a +// rebuild when the application version changes +add_task(function* run_app_update_schema_test() { + do_print("Test: " + arguments.callee.name); + yield promiseRestartManager(); + + let [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s2, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s3, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s4, "1.0", true, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s5, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + do_check_eq(Services.prefs.getCharPref("general.skins.selectedSkin"), "test/1.0"); +}); + +add_task(function* update_schema_2() { + yield promiseShutdownManager(); + + changeXPIDBVersion(100); + gAppInfo.version = "2"; + startupManager(true); + + let [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s2, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s3, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s4, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s5, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + do_check_eq(Services.prefs.getCharPref("general.skins.selectedSkin"), "classic/1.0"); + + s2.userDisabled = false; + s2.userDisabled = true; + check_addon(s2, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + s3.userDisabled = false; + check_addon(s3, "1.0", false, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); +}); + +add_task(function* update_schema_3() { + yield promiseRestartManager(); + + yield promiseShutdownManager(); + changeXPIDBVersion(100); + gAppInfo.version = "2.5"; + startupManager(true); + + let [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s2, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s3, "1.0", false, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s4, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s5, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + do_check_eq(Services.prefs.getCharPref("general.skins.selectedSkin"), "classic/1.0"); +}); + +add_task(function* update_schema_4() { + yield promiseShutdownManager(); + + changeXPIDBVersion(100); + startupManager(false); + + let [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s2, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s3, "1.0", false, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s4, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s5, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + do_check_eq(Services.prefs.getCharPref("general.skins.selectedSkin"), "classic/1.0"); +}); + +add_task(function* update_schema_5() { + yield promiseShutdownManager(); + + changeXPIDBVersion(100); + gAppInfo.version = "1"; + startupManager(true); + + let [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s2, "1.0", true, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s3, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s4, "1.0", true, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s5, "1.0", true, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + do_check_eq(Services.prefs.getCharPref("general.skins.selectedSkin"), "classic/1.0"); + + s1.userDisabled = false; + s2.userDisabled = false; + s5.userDisabled = false; +}); + +// Starts with add-ons unblocked and then loads new blocklists to change add-ons +// to blocked and back again. +add_task(function* run_blocklist_update_test() { + do_print("Test: " + arguments.callee.name + "\n"); + yield Pload_blocklist("blocklist_update1.xml"); + yield promiseRestartManager(); + + let [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s2, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s3, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s4, "1.0", true, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s5, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + do_check_eq(Services.prefs.getCharPref("general.skins.selectedSkin"), "test/1.0"); + + yield Pload_blocklist("blocklist_update2.xml"); + yield promiseRestartManager(); + + [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s2, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s3, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s4, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s5, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + do_check_eq(Services.prefs.getCharPref("general.skins.selectedSkin"), "classic/1.0"); + + s2.userDisabled = false; + s2.userDisabled = true; + check_addon(s2, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + s3.userDisabled = false; + check_addon(s3, "1.0", false, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + + yield promiseRestartManager(); + + yield Pload_blocklist("blocklist_update2.xml"); + yield promiseRestartManager(); + + [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s2, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s3, "1.0", false, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s4, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s5, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + do_check_eq(Services.prefs.getCharPref("general.skins.selectedSkin"), "classic/1.0"); + + yield Pload_blocklist("blocklist_update1.xml"); + yield promiseRestartManager(); + + [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s2, "1.0", true, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s3, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s4, "1.0", true, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s5, "1.0", true, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + do_check_eq(Services.prefs.getCharPref("general.skins.selectedSkin"), "classic/1.0"); + + s1.userDisabled = false; + s2.userDisabled = false; + s5.userDisabled = false; +}); + +// Starts with add-ons unblocked and then new versions are installed outside of +// the app to change them to blocked and back again. +add_task(function* run_addon_change_test() { + do_print("Test: " + arguments.callee.name + "\n"); + yield Pload_blocklist("addon_change.xml"); + yield promiseRestartManager(); + + let [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s2, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s3, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s4, "1.0", true, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s5, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + do_check_eq(Services.prefs.getCharPref("general.skins.selectedSkin"), "test/1.0"); +}); + +add_task(function* run_addon_change_2() { + yield promiseShutdownManager(); + + writeInstallRDFForExtension(softblock1_2, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, softblock1_2.id), Date.now() + 10000); + writeInstallRDFForExtension(softblock2_2, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, softblock2_2.id), Date.now() + 10000); + writeInstallRDFForExtension(softblock3_2, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, softblock3_2.id), Date.now() + 10000); + writeInstallRDFForExtension(softblock4_2, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, softblock4_2.id), Date.now() + 10000); + writeInstallRDFForExtension(softblock5_2, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, softblock5_2.id), Date.now() + 10000); + writeInstallRDFForExtension(hardblock_2, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, hardblock_2.id), Date.now() + 10000); + writeInstallRDFForExtension(regexpblock_2, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, regexpblock_2.id), Date.now() + 10000); + + startupManager(false); + + let [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "2.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s2, "2.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s3, "2.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s4, "2.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s5, "2.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(h, "2.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + check_addon(r, "2.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + do_check_eq(Services.prefs.getCharPref("general.skins.selectedSkin"), "classic/1.0"); + + s2.userDisabled = false; + s2.userDisabled = true; + check_addon(s2, "2.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + s3.userDisabled = false; + check_addon(s3, "2.0", false, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); +}); + +add_task(function* run_addon_change_3() { + yield promiseRestartManager(); + + yield promiseShutdownManager(); + + writeInstallRDFForExtension(softblock1_3, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, softblock1_3.id), Date.now() + 20000); + writeInstallRDFForExtension(softblock2_3, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, softblock2_3.id), Date.now() + 20000); + writeInstallRDFForExtension(softblock3_3, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, softblock3_3.id), Date.now() + 20000); + writeInstallRDFForExtension(softblock4_3, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, softblock4_3.id), Date.now() + 20000); + writeInstallRDFForExtension(softblock5_3, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, softblock5_3.id), Date.now() + 20000); + writeInstallRDFForExtension(hardblock_3, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, hardblock_3.id), Date.now() + 20000); + writeInstallRDFForExtension(regexpblock_3, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, regexpblock_3.id), Date.now() + 20000); + + startupManager(false); + + let [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "3.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s2, "3.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s3, "3.0", false, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s4, "3.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s5, "3.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(h, "3.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + check_addon(r, "3.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + do_check_eq(Services.prefs.getCharPref("general.skins.selectedSkin"), "classic/1.0"); +}); + +add_task(function* run_addon_change_4() { + yield promiseShutdownManager(); + + writeInstallRDFForExtension(softblock1_1, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, softblock1_1.id), Date.now() + 30000); + writeInstallRDFForExtension(softblock2_1, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, softblock2_1.id), Date.now() + 30000); + writeInstallRDFForExtension(softblock3_1, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, softblock3_1.id), Date.now() + 30000); + writeInstallRDFForExtension(softblock4_1, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, softblock4_1.id), Date.now() + 30000); + writeInstallRDFForExtension(softblock5_1, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, softblock5_1.id), Date.now() + 30000); + writeInstallRDFForExtension(hardblock_1, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, hardblock_1.id), Date.now() + 30000); + writeInstallRDFForExtension(regexpblock_1, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, regexpblock_1.id), Date.now() + 30000); + + startupManager(false); + + let [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s2, "1.0", true, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s3, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s4, "1.0", true, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s5, "1.0", true, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + do_check_eq(Services.prefs.getCharPref("general.skins.selectedSkin"), "classic/1.0"); + + s1.userDisabled = false; + s2.userDisabled = false; + s5.userDisabled = false; +}); + +// Starts with add-ons blocked and then new versions are installed outside of +// the app to change them to unblocked. +add_task(function* run_addon_change_2_test() { + do_print("Test: " + arguments.callee.name + "\n"); + yield promiseShutdownManager(); + + getFileForAddon(profileDir, softblock1_1.id).remove(true); + getFileForAddon(profileDir, softblock2_1.id).remove(true); + getFileForAddon(profileDir, softblock3_1.id).remove(true); + getFileForAddon(profileDir, softblock4_1.id).remove(true); + getFileForAddon(profileDir, softblock5_1.id).remove(true); + getFileForAddon(profileDir, hardblock_1.id).remove(true); + getFileForAddon(profileDir, regexpblock_1.id).remove(true); + + startupManager(false); + yield promiseShutdownManager(); + + writeInstallRDFForExtension(softblock1_2, profileDir); + writeInstallRDFForExtension(softblock2_2, profileDir); + writeInstallRDFForExtension(softblock3_2, profileDir); + writeInstallRDFForExtension(softblock4_2, profileDir); + writeInstallRDFForExtension(softblock5_2, profileDir); + writeInstallRDFForExtension(hardblock_2, profileDir); + writeInstallRDFForExtension(regexpblock_2, profileDir); + + startupManager(false); + + let [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "2.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s2, "2.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s3, "2.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(h, "2.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + check_addon(r, "2.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + + s2.userDisabled = false; + s2.userDisabled = true; + check_addon(s2, "2.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + s3.userDisabled = false; + check_addon(s3, "2.0", false, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); +}); + +add_task(function* addon_change_2_test_2() { + yield promiseRestartManager(); + + yield promiseShutdownManager(); + + writeInstallRDFForExtension(softblock1_3, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, softblock1_3.id), Date.now() + 10000); + writeInstallRDFForExtension(softblock2_3, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, softblock2_3.id), Date.now() + 10000); + writeInstallRDFForExtension(softblock3_3, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, softblock3_3.id), Date.now() + 10000); + writeInstallRDFForExtension(softblock4_3, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, softblock4_3.id), Date.now() + 10000); + writeInstallRDFForExtension(softblock5_3, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, softblock5_3.id), Date.now() + 10000); + writeInstallRDFForExtension(hardblock_3, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, hardblock_3.id), Date.now() + 10000); + writeInstallRDFForExtension(regexpblock_3, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, regexpblock_3.id), Date.now() + 10000); + + startupManager(false); + + let [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "3.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s2, "3.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s3, "3.0", false, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(h, "3.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + check_addon(r, "3.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); +}); + +add_task(function* addon_change_2_test_3() { + yield promiseShutdownManager(); + + writeInstallRDFForExtension(softblock1_1, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, softblock1_1.id), Date.now() + 20000); + writeInstallRDFForExtension(softblock2_1, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, softblock2_1.id), Date.now() + 20000); + writeInstallRDFForExtension(softblock3_1, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, softblock3_1.id), Date.now() + 20000); + writeInstallRDFForExtension(softblock4_1, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, softblock4_1.id), Date.now() + 20000); + writeInstallRDFForExtension(softblock5_1, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, softblock5_1.id), Date.now() + 20000); + writeInstallRDFForExtension(hardblock_1, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, hardblock_1.id), Date.now() + 20000); + writeInstallRDFForExtension(regexpblock_1, profileDir); + setExtensionModifiedTime(getFileForAddon(profileDir, regexpblock_1.id), Date.now() + 20000); + + startupManager(false); + + let [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s2, "1.0", true, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s3, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + + s1.userDisabled = false; + s2.userDisabled = false; + s4.userDisabled = true; + s5.userDisabled = false; +}); + +// Add-ons are initially unblocked then attempts to upgrade to blocked versions +// in the background which should fail +add_task(function* run_background_update_test() { + do_print("Test: " + arguments.callee.name + "\n"); + yield promiseRestartManager(); + + let [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s2, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s3, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s4, "1.0", true, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s5, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + + yield Pbackground_update(); + yield promiseRestartManager(); + + [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s2, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s3, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s4, "1.0", true, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s5, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); +}); + +// Starts with add-ons blocked and then new versions are detected and installed +// automatically for unblocked versions. +add_task(function* run_background_update_2_test() { + do_print("Test: " + arguments.callee.name + "\n"); + yield promiseShutdownManager(); + + getFileForAddon(profileDir, softblock1_1.id).remove(true); + getFileForAddon(profileDir, softblock2_1.id).remove(true); + getFileForAddon(profileDir, softblock3_1.id).remove(true); + getFileForAddon(profileDir, softblock4_1.id).remove(true); + getFileForAddon(profileDir, softblock5_1.id).remove(true); + getFileForAddon(profileDir, hardblock_1.id).remove(true); + getFileForAddon(profileDir, regexpblock_1.id).remove(true); + + startupManager(false); + yield promiseShutdownManager(); + + writeInstallRDFForExtension(softblock1_3, profileDir); + writeInstallRDFForExtension(softblock2_3, profileDir); + writeInstallRDFForExtension(softblock3_3, profileDir); + writeInstallRDFForExtension(softblock4_3, profileDir); + writeInstallRDFForExtension(softblock5_3, profileDir); + writeInstallRDFForExtension(hardblock_3, profileDir); + writeInstallRDFForExtension(regexpblock_3, profileDir); + + startupManager(false); + + let [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "3.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s2, "3.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s3, "3.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(h, "3.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + check_addon(r, "3.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + + s2.userDisabled = false; + s2.userDisabled = true; + check_addon(s2, "3.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + s3.userDisabled = false; + check_addon(s3, "3.0", false, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + + yield promiseRestartManager(); + + yield Pbackground_update(); + yield promiseRestartManager(); + + [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s2, "1.0", true, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s3, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + + s1.userDisabled = false; + s2.userDisabled = false; + s4.userDisabled = true; + s5.userDisabled = true; +}); + +// Starts with add-ons blocked and then simulates the user upgrading them to +// unblocked versions. +add_task(function* run_manual_update_test() { + do_print("Test: " + arguments.callee.name + "\n"); + yield promiseRestartManager(); + yield Pload_blocklist("manual_update.xml"); + yield promiseRestartManager(); + + let [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s2, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s3, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s4, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s5, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + + s2.userDisabled = false; + s2.userDisabled = true; + check_addon(s2, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + s3.userDisabled = false; + check_addon(s3, "1.0", false, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + + yield promiseRestartManager(); + + yield Pmanual_update("2"); + yield promiseRestartManager(); + + [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "2.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s2, "2.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s3, "2.0", false, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s4, "2.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s5, "2.0", false, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + // Can't manually update to a hardblocked add-on + check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + + yield Pmanual_update("3"); + yield promiseRestartManager(); + + [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "3.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s2, "3.0", true, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s3, "3.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s4, "3.0", true, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s5, "3.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(h, "3.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(r, "3.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); +}); + +// Starts with add-ons blocked and then new versions are installed outside of +// the app to change them to unblocked. +add_task(function* run_manual_update_2_test() { + do_print("Test: " + arguments.callee.name + "\n"); + yield promiseShutdownManager(); + + getFileForAddon(profileDir, softblock1_1.id).remove(true); + getFileForAddon(profileDir, softblock2_1.id).remove(true); + getFileForAddon(profileDir, softblock3_1.id).remove(true); + getFileForAddon(profileDir, softblock4_1.id).remove(true); + getFileForAddon(profileDir, softblock5_1.id).remove(true); + getFileForAddon(profileDir, hardblock_1.id).remove(true); + getFileForAddon(profileDir, regexpblock_1.id).remove(true); + + startupManager(false); + yield promiseShutdownManager(); + + writeInstallRDFForExtension(softblock1_1, profileDir); + writeInstallRDFForExtension(softblock2_1, profileDir); + writeInstallRDFForExtension(softblock3_1, profileDir); + writeInstallRDFForExtension(softblock4_1, profileDir); + writeInstallRDFForExtension(softblock5_1, profileDir); + writeInstallRDFForExtension(hardblock_1, profileDir); + writeInstallRDFForExtension(regexpblock_1, profileDir); + + startupManager(false); + + let [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s2, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s3, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + + s2.userDisabled = false; + s2.userDisabled = true; + check_addon(s2, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + s3.userDisabled = false; + check_addon(s3, "1.0", false, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + yield promiseRestartManager(); + + yield Pmanual_update("2"); + yield promiseRestartManager(); + + [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "2.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s2, "2.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s3, "2.0", false, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + // Can't manually update to a hardblocked add-on + check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + + yield promiseRestartManager(); + + yield Pmanual_update("3"); + yield promiseRestartManager(); + + [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "3.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s2, "3.0", true, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(s3, "3.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(h, "3.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + check_addon(r, "3.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + + s1.userDisabled = false; + s2.userDisabled = false; + s4.userDisabled = true; +}); + +// Uses the API to install blocked add-ons from the local filesystem +add_task(function* run_local_install_test() { + do_print("Test: " + arguments.callee.name + "\n"); + yield promiseShutdownManager(); + + getFileForAddon(profileDir, softblock1_1.id).remove(true); + getFileForAddon(profileDir, softblock2_1.id).remove(true); + getFileForAddon(profileDir, softblock3_1.id).remove(true); + getFileForAddon(profileDir, softblock4_1.id).remove(true); + getFileForAddon(profileDir, softblock5_1.id).remove(true); + getFileForAddon(profileDir, hardblock_1.id).remove(true); + getFileForAddon(profileDir, regexpblock_1.id).remove(true); + + startupManager(false); + + yield promiseInstallAllFiles([ + do_get_file("addons/blocklist_soft1_1.xpi"), + do_get_file("addons/blocklist_soft2_1.xpi"), + do_get_file("addons/blocklist_soft3_1.xpi"), + do_get_file("addons/blocklist_soft4_1.xpi"), + do_get_file("addons/blocklist_soft5_1.xpi"), + do_get_file("addons/blocklist_hard1_1.xpi"), + do_get_file("addons/blocklist_regexp1_1.xpi") + ]); + + let aInstalls = yield new Promise((resolve, reject) => { + AddonManager.getAllInstalls(resolve) + }); + // Should have finished all installs without needing to restart + do_check_eq(aInstalls.length, 0); + + let [s1, s2, s3, s4, s5, h, r] = yield promiseAddonsByIDs(ADDON_IDS); + + check_addon(s1, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s2, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(s3, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED); + check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); + check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED); +}); + +add_task(function* shutdown_httpserver() { + yield new Promise((resolve, reject) => { + testserver.stop(resolve); + }); +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap.js b/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap.js new file mode 100644 index 000000000..e8d12c1fa --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap.js @@ -0,0 +1,1434 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +const APP_STARTUP = 1; +const APP_SHUTDOWN = 2; +const ADDON_ENABLE = 3; +const ADDON_DISABLE = 4; +const ADDON_INSTALL = 5; +const ADDON_UNINSTALL = 6; +const ADDON_UPGRADE = 7; +const ADDON_DOWNGRADE = 8; + +// This verifies that bootstrappable add-ons can be used without restarts. +Components.utils.import("resource://gre/modules/Services.jsm"); +Components.utils.import("resource://gre/modules/Promise.jsm"); + +// Enable loading extensions from the user scopes +Services.prefs.setIntPref("extensions.enabledScopes", + AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_USER); + +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); +const userExtDir = gProfD.clone(); +userExtDir.append("extensions2"); +userExtDir.append(gAppInfo.ID); +registerDirectory("XREUSysExt", userExtDir.parent); + +Components.utils.import("resource://testing-common/httpd.js"); +var testserver = new HttpServer(); +testserver.start(-1); +gPort = testserver.identity.primaryPort; + +testserver.registerDirectory("/addons/", do_get_file("addons")); + +function resetPrefs() { + Services.prefs.setIntPref("bootstraptest.active_version", -1); + Services.prefs.setIntPref("bootstraptest.installed_version", -1); + Services.prefs.setIntPref("bootstraptest2.active_version", -1); + Services.prefs.setIntPref("bootstraptest2.installed_version", -1); + Services.prefs.setIntPref("bootstraptest.startup_reason", -1); + Services.prefs.setIntPref("bootstraptest.shutdown_reason", -1); + Services.prefs.setIntPref("bootstraptest.install_reason", -1); + Services.prefs.setIntPref("bootstraptest.uninstall_reason", -1); + Services.prefs.setIntPref("bootstraptest.startup_oldversion", -1); + Services.prefs.setIntPref("bootstraptest.shutdown_newversion", -1); + Services.prefs.setIntPref("bootstraptest.install_oldversion", -1); + Services.prefs.setIntPref("bootstraptest.uninstall_newversion", -1); +} + +function waitForPref(aPref, aCallback) { + function prefChanged() { + Services.prefs.removeObserver(aPref, prefChanged); + // Always let whoever set the preference keep running + do_execute_soon(aCallback); + } + Services.prefs.addObserver(aPref, prefChanged, false); +} + +function promisePref(aPref) { + let deferred = Promise.defer(); + + waitForPref(aPref, deferred.resolve.bind(deferred)); + + return deferred.promise; +} + +function promiseInstall(aFiles) { + let deferred = Promise.defer(); + + installAllFiles(aFiles, function() { + deferred.resolve(); + }); + + return deferred.promise; +} + +function getActiveVersion() { + return Services.prefs.getIntPref("bootstraptest.active_version"); +} + +function getInstalledVersion() { + return Services.prefs.getIntPref("bootstraptest.installed_version"); +} + +function getActiveVersion2() { + return Services.prefs.getIntPref("bootstraptest2.active_version"); +} + +function getInstalledVersion2() { + return Services.prefs.getIntPref("bootstraptest2.installed_version"); +} + +function getStartupReason() { + return Services.prefs.getIntPref("bootstraptest.startup_reason"); +} + +function getShutdownReason() { + return Services.prefs.getIntPref("bootstraptest.shutdown_reason"); +} + +function getInstallReason() { + return Services.prefs.getIntPref("bootstraptest.install_reason"); +} + +function getUninstallReason() { + return Services.prefs.getIntPref("bootstraptest.uninstall_reason"); +} + +function getStartupOldVersion() { + return Services.prefs.getIntPref("bootstraptest.startup_oldversion"); +} + +function getShutdownNewVersion() { + return Services.prefs.getIntPref("bootstraptest.shutdown_newversion"); +} + +function getInstallOldVersion() { + return Services.prefs.getIntPref("bootstraptest.install_oldversion"); +} + +function getUninstallNewVersion() { + return Services.prefs.getIntPref("bootstraptest.uninstall_newversion"); +} + +function do_check_bootstrappedPref(aCallback) { + let data = Services.prefs.getCharPref("extensions.bootstrappedAddons"); + data = JSON.parse(data); + + AddonManager.getAddonsByTypes(["extension"], function(aAddons) { + for (let addon of aAddons) { + if (!addon.id.endsWith("@tests.mozilla.org")) + continue; + if (!addon.isActive) + continue; + if (addon.operationsRequiringRestart != AddonManager.OP_NEEDS_RESTART_NONE) + continue; + + do_check_true(addon.id in data); + let addonData = data[addon.id]; + delete data[addon.id]; + + do_check_eq(addonData.version, addon.version); + do_check_eq(addonData.type, addon.type); + let file = addon.getResourceURI().QueryInterface(Components.interfaces.nsIFileURL).file; + do_check_eq(addonData.descriptor, file.persistentDescriptor); + } + do_check_eq(Object.keys(data).length, 0); + + do_execute_soon(aCallback); + }); +} + + +function run_test() { + do_test_pending(); + + resetPrefs(); + + startupManager(); + + do_check_false(gExtensionsJSON.exists()); + + do_check_false(gExtensionsINI.exists()); + + run_test_1(); +} + +// Tests that installing doesn't require a restart +function run_test_1() { + prepare_test({ }, [ + "onNewInstall" + ]); + + AddonManager.getInstallForFile(do_get_addon("test_bootstrap1_1"), function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + do_check_eq(install.type, "extension"); + do_check_eq(install.version, "1.0"); + do_check_eq(install.name, "Test Bootstrap 1"); + do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); + do_check_neq(install.addon.syncGUID, null); + do_check_true(install.addon.hasResource("install.rdf")); + do_check_true(install.addon.hasResource("bootstrap.js")); + do_check_false(install.addon.hasResource("foo.bar")); + do_check_eq(install.addon.operationsRequiringRestart & + AddonManager.OP_NEEDS_RESTART_INSTALL, 0); + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); + + let addon = install.addon; + + waitForPref("bootstraptest.startup_reason", function() { + do_check_bootstrappedPref(function() { + check_test_1(addon.syncGUID); + }); + }); + + prepare_test({ + "bootstrap1@tests.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], function() { + do_check_true(addon.hasResource("install.rdf")); + + // startup should not have been called yet. + do_check_eq(getActiveVersion(), -1); + }); + install.install(); + }); +} + +function check_test_1(installSyncGUID) { + do_check_false(gExtensionsINI.exists()); + + AddonManager.getAllInstalls(function(installs) { + // There should be no active installs now since the install completed and + // doesn't require a restart. + do_check_eq(installs.length, 0); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_neq(b1.syncGUID, null); + do_check_eq(b1.syncGUID, installSyncGUID); + do_check_false(b1.appDisabled); + do_check_false(b1.userDisabled); + do_check_true(b1.isActive); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); + do_check_eq(getStartupReason(), ADDON_INSTALL); + do_check_eq(getStartupOldVersion(), 0); + do_check_true(b1.hasResource("install.rdf")); + do_check_true(b1.hasResource("bootstrap.js")); + do_check_false(b1.hasResource("foo.bar")); + do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); + + let dir = do_get_addon_root_uri(profileDir, "bootstrap1@tests.mozilla.org"); + do_check_eq(b1.getResourceURI("bootstrap.js").spec, dir + "bootstrap.js"); + + AddonManager.getAddonsWithOperationsByTypes(null, function(list) { + do_check_eq(list.length, 0); + + do_execute_soon(run_test_2); + }); + }); + }); +} + +// Tests that disabling doesn't require a restart +function run_test_2() { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + prepare_test({ + "bootstrap1@tests.mozilla.org": [ + ["onDisabling", false], + "onDisabled" + ] + }); + + do_check_eq(b1.operationsRequiringRestart & + AddonManager.OP_NEEDS_RESTART_DISABLE, 0); + b1.userDisabled = true; + ensure_test_completed(); + + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_false(b1.appDisabled); + do_check_true(b1.userDisabled); + do_check_false(b1.isActive); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 0); + do_check_eq(getShutdownReason(), ADDON_DISABLE); + do_check_eq(getShutdownNewVersion(), 0); + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(newb1) { + do_check_neq(newb1, null); + do_check_eq(newb1.version, "1.0"); + do_check_false(newb1.appDisabled); + do_check_true(newb1.userDisabled); + do_check_false(newb1.isActive); + + do_check_bootstrappedPref(run_test_3); + }); + }); +} + +// Test that restarting doesn't accidentally re-enable +function run_test_3() { + shutdownManager(); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 0); + do_check_eq(getShutdownReason(), ADDON_DISABLE); + do_check_eq(getShutdownNewVersion(), 0); + startupManager(false); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 0); + do_check_eq(getShutdownReason(), ADDON_DISABLE); + do_check_eq(getShutdownNewVersion(), 0); + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); + + do_check_false(gExtensionsINI.exists()); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_false(b1.appDisabled); + do_check_true(b1.userDisabled); + do_check_false(b1.isActive); + + do_check_bootstrappedPref(run_test_4); + }); +} + +// Tests that enabling doesn't require a restart +function run_test_4() { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + prepare_test({ + "bootstrap1@tests.mozilla.org": [ + ["onEnabling", false], + "onEnabled" + ] + }); + + do_check_eq(b1.operationsRequiringRestart & + AddonManager.OP_NEEDS_RESTART_ENABLE, 0); + b1.userDisabled = false; + ensure_test_completed(); + + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_false(b1.appDisabled); + do_check_false(b1.userDisabled); + do_check_true(b1.isActive); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); + do_check_eq(getStartupReason(), ADDON_ENABLE); + do_check_eq(getStartupOldVersion(), 0); + do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(newb1) { + do_check_neq(newb1, null); + do_check_eq(newb1.version, "1.0"); + do_check_false(newb1.appDisabled); + do_check_false(newb1.userDisabled); + do_check_true(newb1.isActive); + + do_check_bootstrappedPref(run_test_5); + }); + }); +} + +// Tests that a restart shuts down and restarts the add-on +function run_test_5() { + shutdownManager(); + // By the time we've shut down, the database must have been written + do_check_true(gExtensionsJSON.exists()); + + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 0); + do_check_eq(getShutdownReason(), APP_SHUTDOWN); + do_check_eq(getShutdownNewVersion(), 0); + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); + startupManager(false); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); + do_check_eq(getStartupReason(), APP_STARTUP); + do_check_eq(getStartupOldVersion(), 0); + do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_false(b1.appDisabled); + do_check_false(b1.userDisabled); + do_check_true(b1.isActive); + do_check_false(isExtensionInAddonsList(profileDir, b1.id)); + + do_check_bootstrappedPref(run_test_6); + }); +} + +// Tests that installing an upgrade doesn't require a restart +function run_test_6() { + prepare_test({ }, [ + "onNewInstall" + ]); + + AddonManager.getInstallForFile(do_get_addon("test_bootstrap1_2"), function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + do_check_eq(install.type, "extension"); + do_check_eq(install.version, "2.0"); + do_check_eq(install.name, "Test Bootstrap 1"); + do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); + + waitForPref("bootstraptest.startup_reason", check_test_6); + prepare_test({ + "bootstrap1@tests.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], function() { + }); + install.install(); + }); +} + +function check_test_6() { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "2.0"); + do_check_false(b1.appDisabled); + do_check_false(b1.userDisabled); + do_check_true(b1.isActive); + do_check_eq(getInstalledVersion(), 2); + do_check_eq(getActiveVersion(), 2); + do_check_eq(getStartupReason(), ADDON_UPGRADE); + do_check_eq(getInstallOldVersion(), 1); + do_check_eq(getStartupOldVersion(), 1); + do_check_eq(getShutdownReason(), ADDON_UPGRADE); + do_check_eq(getShutdownNewVersion(), 2); + do_check_eq(getUninstallNewVersion(), 2); + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); + do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "2.0"); + + do_check_bootstrappedPref(run_test_7); + }); +} + +// Tests that uninstalling doesn't require a restart +function run_test_7() { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + prepare_test({ + "bootstrap1@tests.mozilla.org": [ + ["onUninstalling", false], + "onUninstalled" + ] + }); + + do_check_eq(b1.operationsRequiringRestart & + AddonManager.OP_NEEDS_RESTART_UNINSTALL, 0); + b1.uninstall(); + + do_check_bootstrappedPref(check_test_7); + }); +} + +function check_test_7() { + ensure_test_completed(); + do_check_eq(getInstalledVersion(), 0); + do_check_eq(getActiveVersion(), 0); + do_check_eq(getShutdownReason(), ADDON_UNINSTALL); + do_check_eq(getShutdownNewVersion(), 0); + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "2.0"); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) { + do_check_eq(b1, null); + + restartManager(); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(newb1) { + do_check_eq(newb1, null); + + do_check_bootstrappedPref(run_test_8); + }); + })); +} + +// Test that a bootstrapped extension dropped into the profile loads properly +// on startup and doesn't cause an EM restart +function run_test_8() { + shutdownManager(); + + manuallyInstall(do_get_addon("test_bootstrap1_1"), profileDir, + "bootstrap1@tests.mozilla.org"); + + startupManager(false); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_false(b1.appDisabled); + do_check_false(b1.userDisabled); + do_check_true(b1.isActive); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); + do_check_eq(getStartupReason(), ADDON_INSTALL); + do_check_eq(getStartupOldVersion(), 0); + do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); + + do_check_bootstrappedPref(run_test_9); + }); +} + +// Test that items detected as removed during startup get removed properly +function run_test_9() { + shutdownManager(); + + manuallyUninstall(profileDir, "bootstrap1@tests.mozilla.org"); + + startupManager(false); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + do_check_eq(b1, null); + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); + + do_check_bootstrappedPref(run_test_10); + }); +} + + +// Tests that installing a downgrade sends the right reason +function run_test_10() { + resetPrefs(); + prepare_test({ }, [ + "onNewInstall" + ]); + + AddonManager.getInstallForFile(do_get_addon("test_bootstrap1_2"), function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + do_check_eq(install.type, "extension"); + do_check_eq(install.version, "2.0"); + do_check_eq(install.name, "Test Bootstrap 1"); + do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); + do_check_true(install.addon.hasResource("install.rdf")); + do_check_true(install.addon.hasResource("bootstrap.js")); + do_check_false(install.addon.hasResource("foo.bar")); + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "2.0"); + + waitForPref("bootstraptest.startup_reason", check_test_10_pt1); + prepare_test({ + "bootstrap1@tests.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], function() { + do_print("Waiting for startup of bootstrap1_2"); + }); + install.install(); + }); +} + +function check_test_10_pt1() { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "2.0"); + do_check_false(b1.appDisabled); + do_check_false(b1.userDisabled); + do_check_true(b1.isActive); + do_check_eq(getInstalledVersion(), 2); + do_check_eq(getActiveVersion(), 2); + do_check_eq(getStartupReason(), ADDON_INSTALL); + do_check_eq(getStartupOldVersion(), 0); + do_check_true(b1.hasResource("install.rdf")); + do_check_true(b1.hasResource("bootstrap.js")); + do_check_false(b1.hasResource("foo.bar")); + do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "2.0"); + + prepare_test({ }, [ + "onNewInstall" + ]); + + AddonManager.getInstallForFile(do_get_addon("test_bootstrap1_1"), function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + do_check_eq(install.type, "extension"); + do_check_eq(install.version, "1.0"); + do_check_eq(install.name, "Test Bootstrap 1"); + do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); + + waitForPref("bootstraptest.startup_reason", check_test_10_pt2); + prepare_test({ + "bootstrap1@tests.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], function() { }); + install.install(); + }); + }); +} + +function check_test_10_pt2() { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_false(b1.appDisabled); + do_check_false(b1.userDisabled); + do_check_true(b1.isActive); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); + do_check_eq(getStartupReason(), ADDON_DOWNGRADE); + do_check_eq(getInstallOldVersion(), 2); + do_check_eq(getStartupOldVersion(), 2); + do_check_eq(getShutdownReason(), ADDON_DOWNGRADE); + do_check_eq(getShutdownNewVersion(), 1); + do_check_eq(getUninstallNewVersion(), 1); + do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "2.0"); + + do_check_bootstrappedPref(run_test_11); + }); +} + +// Tests that uninstalling a disabled add-on still calls the uninstall method +function run_test_11() { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + prepare_test({ + "bootstrap1@tests.mozilla.org": [ + ["onDisabling", false], + "onDisabled", + ["onUninstalling", false], + "onUninstalled" + ] + }); + + b1.userDisabled = true; + + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 0); + do_check_eq(getShutdownReason(), ADDON_DISABLE); + do_check_eq(getShutdownNewVersion(), 0); + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); + + b1.uninstall(); + + check_test_11(); + }); +} + +function check_test_11() { + ensure_test_completed(); + do_check_eq(getInstalledVersion(), 0); + do_check_eq(getActiveVersion(), 0); + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); + + do_check_bootstrappedPref(run_test_12); +} + +// Tests that bootstrapped extensions are correctly loaded even if the app is +// upgraded at the same time +function run_test_12() { + shutdownManager(); + + manuallyInstall(do_get_addon("test_bootstrap1_1"), profileDir, + "bootstrap1@tests.mozilla.org"); + + startupManager(true); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_false(b1.appDisabled); + do_check_false(b1.userDisabled); + do_check_true(b1.isActive); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); + do_check_eq(getStartupReason(), ADDON_INSTALL); + do_check_eq(getStartupOldVersion(), 0); + do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); + + b1.uninstall(); + do_execute_soon(test_12_restart); + }); +} + +function test_12_restart() { + restartManager(); + do_check_bootstrappedPref(run_test_13); +} + + +// Tests that installing a bootstrapped extension with an invalid application +// entry doesn't call it's startup method +function run_test_13() { + prepare_test({ }, [ + "onNewInstall" + ]); + + AddonManager.getInstallForFile(do_get_addon("test_bootstrap1_3"), function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + do_check_eq(install.type, "extension"); + do_check_eq(install.version, "3.0"); + do_check_eq(install.name, "Test Bootstrap 1"); + do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "3.0"); + + prepare_test({ + "bootstrap1@tests.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], callback_soon(check_test_13)); + install.install(); + }); +} + +function check_test_13() { + AddonManager.getAllInstalls(function(installs) { + // There should be no active installs now since the install completed and + // doesn't require a restart. + do_check_eq(installs.length, 0); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "3.0"); + do_check_true(b1.appDisabled); + do_check_false(b1.userDisabled); + do_check_false(b1.isActive); + do_check_eq(getInstalledVersion(), 3); // We call install even for disabled add-ons + do_check_eq(getActiveVersion(), 0); // Should not have called startup though + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "3.0"); + + do_execute_soon(test_13_restart); + }); + }); +} + +function test_13_restart() { + restartManager(); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "3.0"); + do_check_true(b1.appDisabled); + do_check_false(b1.userDisabled); + do_check_false(b1.isActive); + do_check_eq(getInstalledVersion(), 3); // We call install even for disabled add-ons + do_check_eq(getActiveVersion(), 0); // Should not have called startup though + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "3.0"); + + do_check_bootstrappedPref(function() { + b1.uninstall(); + do_execute_soon(run_test_14); + }); + }); +} + +// Tests that a bootstrapped extension with an invalid target application entry +// does not get loaded when detected during startup +function run_test_14() { + restartManager(); + + shutdownManager(); + + manuallyInstall(do_get_addon("test_bootstrap1_3"), profileDir, + "bootstrap1@tests.mozilla.org"); + + startupManager(false); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "3.0"); + do_check_true(b1.appDisabled); + do_check_false(b1.userDisabled); + do_check_false(b1.isActive); + do_check_eq(getInstalledVersion(), 3); // We call install even for disabled add-ons + do_check_eq(getActiveVersion(), 0); // Should not have called startup though + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "3.0"); + + do_check_bootstrappedPref(function() { + b1.uninstall(); + + run_test_15(); + }); + }); +} + +// Tests that upgrading a disabled bootstrapped extension still calls uninstall +// and install but doesn't startup the new version +function run_test_15() { + resetPrefs(); + waitForPref("bootstraptest.startup_reason", function test_15_after_startup() { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_false(b1.appDisabled); + do_check_false(b1.userDisabled); + do_check_true(b1.isActive); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); + + b1.userDisabled = true; + do_check_false(b1.isActive); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 0); + + prepare_test({ }, [ + "onNewInstall" + ]); + + AddonManager.getInstallForFile(do_get_addon("test_bootstrap1_2"), function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + do_check_true(install.addon.userDisabled); + + prepare_test({ + "bootstrap1@tests.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], callback_soon(check_test_15)); + install.install(); + }); + }); + }); + installAllFiles([do_get_addon("test_bootstrap1_1")], function test_15_addon_installed() { }); +} + +function check_test_15() { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "2.0"); + do_check_false(b1.appDisabled); + do_check_true(b1.userDisabled); + do_check_false(b1.isActive); + do_check_eq(getInstalledVersion(), 2); + do_check_eq(getActiveVersion(), 0); + + do_check_bootstrappedPref(function() { + restartManager(); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "2.0"); + do_check_false(b1.appDisabled); + do_check_true(b1.userDisabled); + do_check_false(b1.isActive); + do_check_eq(getInstalledVersion(), 2); + do_check_eq(getActiveVersion(), 0); + + b1.uninstall(); + + run_test_16(); + })); + }); + }); +} + +// Tests that bootstrapped extensions don't get loaded when in safe mode +function run_test_16() { + resetPrefs(); + waitForPref("bootstraptest.startup_reason", function test_16_after_startup() { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) { + // Should have installed and started + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); + do_check_true(b1.isActive); + do_check_eq(b1.iconURL, "chrome://foo/skin/icon.png"); + do_check_eq(b1.aboutURL, "chrome://foo/content/about.xul"); + do_check_eq(b1.optionsURL, "chrome://foo/content/options.xul"); + + shutdownManager(); + + // Should have stopped + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 0); + + gAppInfo.inSafeMode = true; + startupManager(false); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) { + // Should still be stopped + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 0); + do_check_false(b1.isActive); + do_check_eq(b1.iconURL, null); + do_check_eq(b1.aboutURL, null); + do_check_eq(b1.optionsURL, null); + + shutdownManager(); + gAppInfo.inSafeMode = false; + startupManager(false); + + // Should have started + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + b1.uninstall(); + + do_execute_soon(run_test_17); + }); + })); + })); + }); + installAllFiles([do_get_addon("test_bootstrap1_1")], function() { }); +} + +// Check that a bootstrapped extension in a non-profile location is loaded +function run_test_17() { + shutdownManager(); + + manuallyInstall(do_get_addon("test_bootstrap1_1"), userExtDir, + "bootstrap1@tests.mozilla.org"); + + resetPrefs(); + startupManager(); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + // Should have installed and started + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_true(b1.isActive); + + do_check_bootstrappedPref(run_test_18); + }); +} + +// Check that installing a new bootstrapped extension in the profile replaces +// the existing one +function run_test_18() { + resetPrefs(); + waitForPref("bootstraptest.startup_reason", function test_18_after_startup() { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + // Should have installed and started + do_check_eq(getInstalledVersion(), 2); + do_check_eq(getActiveVersion(), 2); + do_check_neq(b1, null); + do_check_eq(b1.version, "2.0"); + do_check_true(b1.isActive); + + do_check_eq(getShutdownReason(), ADDON_UPGRADE); + do_check_eq(getUninstallReason(), ADDON_UPGRADE); + do_check_eq(getInstallReason(), ADDON_UPGRADE); + do_check_eq(getStartupReason(), ADDON_UPGRADE); + + do_check_eq(getShutdownNewVersion(), 2); + do_check_eq(getUninstallNewVersion(), 2); + do_check_eq(getInstallOldVersion(), 1); + do_check_eq(getStartupOldVersion(), 1); + + do_check_bootstrappedPref(run_test_19); + }); + }); + installAllFiles([do_get_addon("test_bootstrap1_2")], function() { }); +} + +// Check that uninstalling the profile version reveals the non-profile one +function run_test_19() { + resetPrefs(); + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + // The revealed add-on gets activated asynchronously + prepare_test({ + "bootstrap1@tests.mozilla.org": [ + ["onUninstalling", false], + "onUninstalled", + ["onInstalling", false], + "onInstalled" + ] + }, [], check_test_19); + + b1.uninstall(); + }); +} + +function check_test_19() { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + // Should have reverted to the older version + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_true(b1.isActive); + + // TODO these reasons really should be ADDON_DOWNGRADE (bug 607818) + do_check_eq(getShutdownReason(), ADDON_UNINSTALL); + do_check_eq(getUninstallReason(), ADDON_UNINSTALL); + do_check_eq(getInstallReason(), ADDON_INSTALL); + do_check_eq(getStartupReason(), ADDON_INSTALL); + + do_check_eq(getShutdownNewVersion(), 0); + do_check_eq(getUninstallNewVersion(), 0); + do_check_eq(getInstallOldVersion(), 0); + do_check_eq(getStartupOldVersion(), 0); + + do_check_bootstrappedPref(run_test_20); + }); +} + +// Check that a new profile extension detected at startup replaces the non-profile +// one +function run_test_20() { + resetPrefs(); + shutdownManager(); + + manuallyInstall(do_get_addon("test_bootstrap1_2"), profileDir, + "bootstrap1@tests.mozilla.org"); + + startupManager(); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + // Should have installed and started + do_check_eq(getInstalledVersion(), 2); + do_check_eq(getActiveVersion(), 2); + do_check_neq(b1, null); + do_check_eq(b1.version, "2.0"); + do_check_true(b1.isActive); + + do_check_eq(getShutdownReason(), APP_SHUTDOWN); + do_check_eq(getUninstallReason(), ADDON_UPGRADE); + do_check_eq(getInstallReason(), ADDON_UPGRADE); + do_check_eq(getStartupReason(), APP_STARTUP); + + do_check_eq(getShutdownNewVersion(), 0); + do_check_eq(getUninstallNewVersion(), 2); + do_check_eq(getInstallOldVersion(), 1); + do_check_eq(getStartupOldVersion(), 0); + + do_execute_soon(run_test_21); + }); +} + +// Check that a detected removal reveals the non-profile one +function run_test_21() { + resetPrefs(); + shutdownManager(); + + manuallyUninstall(profileDir, "bootstrap1@tests.mozilla.org"); + + startupManager(); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + // Should have installed and started + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_true(b1.isActive); + + do_check_eq(getShutdownReason(), APP_SHUTDOWN); + do_check_eq(getShutdownNewVersion(), 0); + + // This won't be set as the bootstrap script was gone so we couldn't + // uninstall it properly + do_check_eq(getUninstallReason(), -1); + do_check_eq(getUninstallNewVersion(), -1); + + // TODO this reason should probably be ADDON_DOWNGRADE (bug 607818) + do_check_eq(getInstallReason(), ADDON_INSTALL); + do_check_eq(getInstallOldVersion(), 0); + + do_check_eq(getStartupReason(), APP_STARTUP); + do_check_eq(getStartupOldVersion(), 0); + + do_check_bootstrappedPref(function() { + manuallyUninstall(userExtDir, "bootstrap1@tests.mozilla.org"); + + restartManager(); + run_test_22(); + }); + }); +} + +// Check that an upgrade from the filesystem is detected and applied correctly +function run_test_22() { + shutdownManager(); + + let file = manuallyInstall(do_get_addon("test_bootstrap1_1"), profileDir, + "bootstrap1@tests.mozilla.org"); + + // Make it look old so changes are detected + setExtensionModifiedTime(file, file.lastModifiedTime - 5000); + + startupManager(); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) { + // Should have installed and started + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_true(b1.isActive); + + resetPrefs(); + shutdownManager(); + + manuallyUninstall(profileDir, "bootstrap1@tests.mozilla.org"); + manuallyInstall(do_get_addon("test_bootstrap1_2"), profileDir, + "bootstrap1@tests.mozilla.org"); + + startupManager(); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + // Should have installed and started + do_check_eq(getInstalledVersion(), 2); + do_check_eq(getActiveVersion(), 2); + do_check_neq(b1, null); + do_check_eq(b1.version, "2.0"); + do_check_true(b1.isActive); + + do_check_eq(getShutdownReason(), APP_SHUTDOWN); + do_check_eq(getShutdownNewVersion(), 0); + + // This won't be set as the bootstrap script was gone so we couldn't + // uninstall it properly + do_check_eq(getUninstallReason(), -1); + do_check_eq(getUninstallNewVersion(), -1); + + do_check_eq(getInstallReason(), ADDON_UPGRADE); + do_check_eq(getInstallOldVersion(), 1); + do_check_eq(getStartupReason(), APP_STARTUP); + do_check_eq(getStartupOldVersion(), 0); + + do_check_bootstrappedPref(function() { + b1.uninstall(); + + run_test_23(); + }); + }); + })); +} + + +// Tests that installing from a URL doesn't require a restart +function run_test_23() { + prepare_test({ }, [ + "onNewInstall" + ]); + + let url = "http://localhost:" + gPort + "/addons/test_bootstrap1_1.xpi"; + AddonManager.getInstallForURL(url, function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + + prepare_test({ }, [ + "onDownloadStarted", + "onDownloadEnded" + ], function() { + do_check_eq(install.type, "extension"); + do_check_eq(install.version, "1.0"); + do_check_eq(install.name, "Test Bootstrap 1"); + do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); + do_check_true(install.addon.hasResource("install.rdf")); + do_check_true(install.addon.hasResource("bootstrap.js")); + do_check_false(install.addon.hasResource("foo.bar")); + do_check_eq(install.addon.operationsRequiringRestart & + AddonManager.OP_NEEDS_RESTART_INSTALL, 0); + do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); + + let addon = install.addon; + prepare_test({ + "bootstrap1@tests.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], function() { + do_check_true(addon.hasResource("install.rdf")); + do_check_bootstrappedPref(check_test_23); + }); + }); + install.install(); + }, "application/x-xpinstall"); +} + +function check_test_23() { + AddonManager.getAllInstalls(function(installs) { + // There should be no active installs now since the install completed and + // doesn't require a restart. + do_check_eq(installs.length, 0); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + do_execute_soon(function test_23_after_startup() { + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_false(b1.appDisabled); + do_check_false(b1.userDisabled); + do_check_true(b1.isActive); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); + do_check_eq(getStartupReason(), ADDON_INSTALL); + do_check_eq(getStartupOldVersion(), 0); + do_check_true(b1.hasResource("install.rdf")); + do_check_true(b1.hasResource("bootstrap.js")); + do_check_false(b1.hasResource("foo.bar")); + do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0"); + + let dir = do_get_addon_root_uri(profileDir, "bootstrap1@tests.mozilla.org"); + do_check_eq(b1.getResourceURI("bootstrap.js").spec, dir + "bootstrap.js"); + + AddonManager.getAddonsWithOperationsByTypes(null, callback_soon(function(list) { + do_check_eq(list.length, 0); + + restartManager(); + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) { + b1.uninstall(); + restartManager(); + + testserver.stop(run_test_24); + })); + })); + }); + }); + }); +} + +// Tests that we recover from a broken preference +function run_test_24() { + resetPrefs(); + do_print("starting 24"); + + Promise.all([promisePref("bootstraptest2.active_version"), + promiseInstall([do_get_addon("test_bootstrap1_1"), do_get_addon("test_bootstrap2_1")])]) + .then(function test_24_pref() { + do_print("test 24 got prefs"); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); + do_check_eq(getInstalledVersion2(), 1); + do_check_eq(getActiveVersion2(), 1); + + resetPrefs(); + + restartManager(); + + do_check_eq(getInstalledVersion(), -1); + do_check_eq(getActiveVersion(), 1); + do_check_eq(getInstalledVersion2(), -1); + do_check_eq(getActiveVersion2(), 1); + + shutdownManager(); + + do_check_eq(getInstalledVersion(), -1); + do_check_eq(getActiveVersion(), 0); + do_check_eq(getInstalledVersion2(), -1); + do_check_eq(getActiveVersion2(), 0); + + // Break the preferece + let bootstrappedAddons = JSON.parse(Services.prefs.getCharPref("extensions.bootstrappedAddons")); + bootstrappedAddons["bootstrap1@tests.mozilla.org"].descriptor += "foo"; + Services.prefs.setCharPref("extensions.bootstrappedAddons", JSON.stringify(bootstrappedAddons)); + + startupManager(false); + + do_check_eq(getInstalledVersion(), -1); + do_check_eq(getActiveVersion(), 1); + do_check_eq(getInstalledVersion2(), -1); + do_check_eq(getActiveVersion2(), 1); + + run_test_25(); + }); +} + +// Tests that updating from a bootstrappable add-on to a normal add-on calls +// the uninstall method +function run_test_25() { + waitForPref("bootstraptest.startup_reason", function test_25_after_pref() { + do_print("test 25 pref change detected"); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); + + installAllFiles([do_get_addon("test_bootstrap1_4")], function() { + // Needs a restart to complete this so the old version stays running + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_true(b1.isActive); + do_check_true(hasFlag(b1.pendingOperations, AddonManager.PENDING_UPGRADE)); + + restartManager(); + + do_check_eq(getInstalledVersion(), 0); + do_check_eq(getUninstallReason(), ADDON_UPGRADE); + do_check_eq(getUninstallNewVersion(), 4); + do_check_eq(getActiveVersion(), 0); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "4.0"); + do_check_true(b1.isActive); + do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE); + + do_check_bootstrappedPref(run_test_26); + }); + })); + }); + }); + installAllFiles([do_get_addon("test_bootstrap1_1")], function test_25_installed() { + do_print("test 25 install done"); + }); +} + +// Tests that updating from a normal add-on to a bootstrappable add-on calls +// the install method +function run_test_26() { + installAllFiles([do_get_addon("test_bootstrap1_1")], function() { + // Needs a restart to complete this + do_check_eq(getInstalledVersion(), 0); + do_check_eq(getActiveVersion(), 0); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "4.0"); + do_check_true(b1.isActive); + do_check_true(hasFlag(b1.pendingOperations, AddonManager.PENDING_UPGRADE)); + + restartManager(); + + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getInstallReason(), ADDON_DOWNGRADE); + do_check_eq(getInstallOldVersion(), 4); + do_check_eq(getActiveVersion(), 1); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_true(b1.isActive); + do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE); + + do_check_bootstrappedPref(run_test_27); + }); + })); + }); +} + +// Tests that updating from a bootstrappable add-on to a normal add-on while +// disabled calls the uninstall method +function run_test_27() { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + do_check_neq(b1, null); + b1.userDisabled = true; + do_check_eq(b1.version, "1.0"); + do_check_false(b1.isActive); + do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 0); + + installAllFiles([do_get_addon("test_bootstrap1_4")], function() { + // Updating disabled things happens immediately + do_check_eq(getInstalledVersion(), 0); + do_check_eq(getUninstallReason(), ADDON_UPGRADE); + do_check_eq(getUninstallNewVersion(), 4); + do_check_eq(getActiveVersion(), 0); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "4.0"); + do_check_false(b1.isActive); + do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE); + + restartManager(); + + do_check_eq(getInstalledVersion(), 0); + do_check_eq(getActiveVersion(), 0); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "4.0"); + do_check_false(b1.isActive); + do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE); + + do_check_bootstrappedPref(run_test_28); + }); + })); + }); + }); +} + +// Tests that updating from a normal add-on to a bootstrappable add-on when +// disabled calls the install method but not the startup method +function run_test_28() { + installAllFiles([do_get_addon("test_bootstrap1_1")], function() { + do_execute_soon(function bootstrap_disabled_downgrade_check() { + // Doesn't need a restart to complete this + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getInstallReason(), ADDON_DOWNGRADE); + do_check_eq(getInstallOldVersion(), 4); + do_check_eq(getActiveVersion(), 0); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_false(b1.isActive); + do_check_true(b1.userDisabled); + do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE); + + restartManager(); + + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 0); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_true(b1.userDisabled); + b1.userDisabled = false; + do_check_eq(b1.version, "1.0"); + do_check_true(b1.isActive); + do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE); + do_check_eq(getInstalledVersion(), 1); + do_check_eq(getActiveVersion(), 1); + + do_check_bootstrappedPref(do_test_finished); + }); + })); + }); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap_globals.js b/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap_globals.js new file mode 100644 index 000000000..2243a21a2 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap_globals.js @@ -0,0 +1,37 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that bootstrap.js has the expected globals defined +Components.utils.import("resource://gre/modules/Services.jsm"); + +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); + +const EXPECTED_GLOBALS = [ + ["Worker", "function"], + ["ChromeWorker", "function"], + ["console", "object"] +]; + +function run_test() { + do_test_pending(); + startupManager(); + let sawGlobals = false; + + Services.obs.addObserver(function(subject) { + subject.wrappedJSObject.expectedGlobals = EXPECTED_GLOBALS; + }, "bootstrap-request-globals", false); + + Services.obs.addObserver(function({ wrappedJSObject: seenGlobals }) { + for (let [name,] of EXPECTED_GLOBALS) + do_check_true(seenGlobals.has(name)); + + sawGlobals = true; + }, "bootstrap-seen-globals", false); + + installAllFiles([do_get_addon("bootstrap_globals")], function() { + do_check_true(sawGlobals); + shutdownManager(); + do_test_finished(); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap_resource.js b/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap_resource.js new file mode 100644 index 000000000..7b7883225 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap_resource.js @@ -0,0 +1,56 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that resource protocol substitutions are set and unset for bootstrapped add-ons. + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2"); + + let resourceProtocol = Services.io.getProtocolHandler("resource") + .QueryInterface(Components.interfaces.nsIResProtocolHandler); + startupManager(); + + installAllFiles([do_get_addon("test_chromemanifest_6")], + function() { + + AddonManager.getAddonByID("addon6@tests.mozilla.org", function(addon) { + do_check_neq(addon, null); + do_check_true(addon.isActive); + do_check_true(resourceProtocol.hasSubstitution("test-addon-1")); + + prepare_test({ + "addon6@tests.mozilla.org": [ + ["onDisabling", false], + "onDisabled" + ] + }); + + do_check_eq(addon.operationsRequiringRestart & + AddonManager.OP_NEEDS_RESTART_DISABLE, 0); + addon.userDisabled = true; + ensure_test_completed(); + do_check_false(resourceProtocol.hasSubstitution("test-addon-1")) + + prepare_test({ + "addon6@tests.mozilla.org": [ + ["onEnabling", false], + "onEnabled" + ] + }); + + do_check_eq(addon.operationsRequiringRestart & + AddonManager.OP_NEEDS_RESTART_ENABLE, 0); + addon.userDisabled = false; + ensure_test_completed(); + do_check_true(resourceProtocol.hasSubstitution("test-addon-1")); + + do_execute_soon(do_test_finished); + }); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug299716.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug299716.js new file mode 100644 index 000000000..5de941f32 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug299716.js @@ -0,0 +1,209 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// Disables security checking our updates which haven't been signed +Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); + +// Update check listener. +const checkListener = { + pendingCount: 0, + + onUpdateAvailable: function onUpdateAvailable(aAddon, aInstall) { + for (let currentAddon of ADDONS) { + if (currentAddon.id == aAddon.id) { + currentAddon.newInstall = aInstall; + return; + } + } + }, + + onUpdateFinished: function onUpdateFinished() { + if (--this.pendingCount == 0) + next_test(); + } +} + +// Get the HTTP server. +Components.utils.import("resource://testing-common/httpd.js"); +var testserver; + +var ADDONS = [ + // XPCShell + { + id: "bug299716-a@tests.mozilla.org", + addon: "test_bug299716_a_1", + installed: true, + item: null, + newInstall: null + }, + + // Toolkit + { + id: "bug299716-b@tests.mozilla.org", + addon: "test_bug299716_b_1", + installed: true, + item: null, + newInstall: null + }, + + // XPCShell + Toolkit + { + id: "bug299716-c@tests.mozilla.org", + addon: "test_bug299716_c_1", + installed: true, + item: null, + newInstall: null + }, + + // XPCShell (Toolkit invalid) + { + id: "bug299716-d@tests.mozilla.org", + addon: "test_bug299716_d_1", + installed: true, + item: null, + newInstall: null + }, + + // Toolkit (XPCShell invalid) + { + id: "bug299716-e@tests.mozilla.org", + addon: "test_bug299716_e_1", + installed: false, + item: null, + newInstall: null, + failedAppName: "XPCShell" + }, + + // None (XPCShell, Toolkit invalid) + { + id: "bug299716-f@tests.mozilla.org", + addon: "test_bug299716_f_1", + installed: false, + item: null, + newInstall: null, + failedAppName: "XPCShell" + }, + + // None (Toolkit invalid) + { + id: "bug299716-g@tests.mozilla.org", + addon: "test_bug299716_g_1", + installed: false, + item: null, + newInstall: null, + failedAppName: "Toolkit" + }, +]; + +var next_test = function() {}; + +function do_check_item(aItem, aVersion, aAddonsEntry) { + if (aAddonsEntry.installed) { + if (aItem == null) + do_throw("Addon " + aAddonsEntry.id + " wasn't detected"); + if (aItem.version != aVersion) + do_throw("Addon " + aAddonsEntry.id + " was version " + aItem.version + " instead of " + aVersion); + } else { + if (aItem != null) + do_throw("Addon " + aAddonsEntry.id + " was detected"); + } +} + +/** + * Start the test by installing extensions. + */ +function run_test() { + do_test_pending(); + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "5", "1.9"); + + const dataDir = do_get_file("data"); + const addonsDir = do_get_addon(ADDONS[0].addon).parent; + + // Make sure we can actually get our data files. + const xpiFile = addonsDir.clone(); + xpiFile.append("test_bug299716_a_2.xpi"); + do_check_true(xpiFile.exists()); + + // Create and configure the HTTP server. + testserver = new HttpServer(); + testserver.registerDirectory("/addons/", addonsDir); + testserver.registerDirectory("/data/", dataDir); + testserver.start(4444); + + // Make sure we can fetch the files over HTTP. + const Ci = Components.interfaces; + const xhr = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"] + .createInstance(Ci.nsIXMLHttpRequest) + xhr.open("GET", "http://localhost:4444/addons/test_bug299716_a_2.xpi", false); + xhr.send(null); + do_check_true(xhr.status == 200); + + xhr.open("GET", "http://localhost:4444/data/test_bug299716.rdf", false); + xhr.send(null); + do_check_true(xhr.status == 200); + + // Start the real test. + startupManager(); + dump("\n\n*** INSTALLING NEW ITEMS\n\n"); + + installAllFiles([do_get_addon(a.addon) for each (a in ADDONS)], run_test_pt2, + true); +} + +/** + * Check the versions of all items, and ask the extension manager to find updates. + */ +function run_test_pt2() { + dump("\n\n*** DONE INSTALLING NEW ITEMS\n\n"); + dump("\n\n*** RESTARTING EXTENSION MANAGER\n\n"); + restartManager(); + + AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], function(items) { + dump("\n\n*** REQUESTING UPDATE\n\n"); + // checkListener will call run_test_pt3(). + next_test = run_test_pt3; + + // Try to update the items. + for (var i = 0; i < ADDONS.length; i++) { + var item = items[i]; + do_check_item(item, "0.1", ADDONS[i]); + + if (item) { + checkListener.pendingCount++; + ADDONS[i].item = item; + item.findUpdates(checkListener, AddonManager.UPDATE_WHEN_USER_REQUESTED); + } + } + }); +} + +/** + * Install new items for each enabled extension. + */ +function run_test_pt3() { + // Install the new items. + dump("\n\n*** UPDATING ITEMS\n\n"); + completeAllInstalls([a.newInstall for each(a in ADDONS) if (a.newInstall)], + run_test_pt4); +} + +/** + * Check the final version of each extension. + */ +function run_test_pt4() { + dump("\n\n*** RESTARTING EXTENSION MANAGER\n\n"); + restartManager(); + + dump("\n\n*** FINAL CHECKS\n\n"); + AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], function(items) { + for (var i = 0; i < ADDONS.length; i++) { + var item = items[i]; + do_check_item(item, "0.2", ADDONS[i]); + } + + testserver.stop(do_test_finished); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug299716_2.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug299716_2.js new file mode 100644 index 000000000..c183edad4 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug299716_2.js @@ -0,0 +1,50 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// Disables security checking our updates which haven't been signed +Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); + +// Get the HTTP server. +Components.utils.import("resource://testing-common/httpd.js"); +var testserver; + +var ADDON = { + id: "bug299716-2@tests.mozilla.org", + addon: "test_bug299716_2" +}; + +function run_test() { + do_test_pending(); + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "1.9"); + + const dataDir = do_get_file("data"); + const addonsDir = do_get_addon(ADDON.addon).parent; + + // Create and configure the HTTP server. + testserver = new HttpServer(); + testserver.registerDirectory("/addons/", addonsDir); + testserver.registerDirectory("/data/", dataDir); + testserver.start(4444); + + startupManager(); + + installAllFiles([do_get_addon(ADDON.addon)], function() { + restartManager(); + + AddonManager.getAddonByID(ADDON.id, function(item) { + do_check_eq(item.version, 0.1); + do_check_false(item.isCompatible); + + item.findUpdates({ + onUpdateFinished: function(addon) { + do_check_false(item.isCompatible); + + testserver.stop(do_test_finished); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug324121.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug324121.js new file mode 100644 index 000000000..b88c07b23 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug324121.js @@ -0,0 +1,178 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// Disables security checking our updates which haven't been signed +Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); + +// Get the HTTP server. +Components.utils.import("resource://testing-common/httpd.js"); +var testserver; + +var next_test = null; +var gItemsNotChecked =[]; + +var ADDONS = [ {id: "bug324121_1@tests.mozilla.org", + addon: "test_bug324121_1", + shouldCheck: false }, + {id: "bug324121_2@tests.mozilla.org", + addon: "test_bug324121_2", + shouldCheck: true }, + {id: "bug324121_3@tests.mozilla.org", + addon: "test_bug324121_3", + shouldCheck: true }, + {id: "bug324121_4@tests.mozilla.org", + addon: "test_bug324121_4", + shouldCheck: true }, + {id: "bug324121_5@tests.mozilla.org", + addon: "test_bug324121_5", + shouldCheck: false }, + {id: "bug324121_6@tests.mozilla.org", + addon: "test_bug324121_6", + shouldCheck: true }, + {id: "bug324121_7@tests.mozilla.org", + addon: "test_bug324121_7", + shouldCheck: true }, + {id: "bug324121_8@tests.mozilla.org", + addon: "test_bug324121_8", + shouldCheck: true }, + {id: "bug324121_9@tests.mozilla.org", + addon: "test_bug324121_9", + shouldCheck: false } ]; + +// nsIAddonUpdateCheckListener +var updateListener = { + pendingCount: 0, + + onUpdateAvailable: function onAddonUpdateEnded(aAddon) { + switch (aAddon.id) { + // add-on disabled - should not happen + case "bug324121_1@tests.mozilla.org": + // app id already compatible - should not happen + case "bug324121_5@tests.mozilla.org": + // toolkit id already compatible - should not happen + case "bug324121_9@tests.mozilla.org": + do_throw("Should not have seen an update check for " + aAddon.id); + break; + + // app id incompatible update available + case "bug324121_3@tests.mozilla.org": + // update rdf not found + case "bug324121_4@tests.mozilla.org": + // toolkit id incompatible update available + case "bug324121_7@tests.mozilla.org": + // update rdf not found + case "bug324121_8@tests.mozilla.org": + do_throw("Should be no update available for " + aAddon.id); + break; + + // Updates available + case "bug324121_2@tests.mozilla.org": + case "bug324121_6@tests.mozilla.org": + break; + + default: + do_throw("Update check for unknown " + aAddon.id); + } + + // pos should always be >= 0 so just let this throw if this fails + var pos = gItemsNotChecked.indexOf(aAddon.id); + gItemsNotChecked.splice(pos, 1); + }, + + onNoUpdateAvailable: function onNoUpdateAvailable(aAddon) { + switch (aAddon.id) { + // add-on disabled - should not happen + case "bug324121_1@tests.mozilla.org": + // app id already compatible - should not happen + case "bug324121_5@tests.mozilla.org": + // toolkit id already compatible - should not happen + case "bug324121_9@tests.mozilla.org": + do_throw("Should not have seen an update check for " + aAddon.id); + break; + + // app id incompatible update available + case "bug324121_3@tests.mozilla.org": + // update rdf not found + case "bug324121_4@tests.mozilla.org": + // toolkit id incompatible update available + case "bug324121_7@tests.mozilla.org": + // update rdf not found + case "bug324121_8@tests.mozilla.org": + break; + + // Updates available + case "bug324121_2@tests.mozilla.org": + case "bug324121_6@tests.mozilla.org": + do_throw("Should be an update available for " + aAddon.id); + break; + + default: + do_throw("Update check for unknown " + aAddon.id); + } + + // pos should always be >= 0 so just let this throw if this fails + var pos = gItemsNotChecked.indexOf(aAddon.id); + gItemsNotChecked.splice(pos, 1); + }, + + onUpdateFinished: function onUpdateFinished(aAddon) { + if (--this.pendingCount == 0) + test_complete(); + } +}; + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2"); + + const dataDir = do_get_file("data"); + + // Create and configure the HTTP server. + testserver = new HttpServer(); + testserver.registerDirectory("/data/", dataDir); + testserver.start(4444); + + startupManager(); + + installAllFiles([do_get_addon(a.addon) for each (a in ADDONS)], function() { + restartManager(); + AddonManager.getAddonByID(ADDONS[0].id, callback_soon(function(addon) { + do_check_true(!(!addon)); + addon.userDisabled = true; + restartManager(); + + AddonManager.getAddonsByTypes(["extension"], function(installedItems) { + var items = []; + + for (let addon of ADDONS) { + for (let installedItem of installedItems) { + if (addon.id != installedItem.id) + continue; + if (installedItem.userDisabled) + continue; + + if (addon.shouldCheck == installedItem.isCompatibleWith("3", "3")) { + do_throw(installedItem.id + " had the wrong compatibility: " + + installedItem.isCompatibleWith("3", "3")); + } + + if (addon.shouldCheck) { + gItemsNotChecked.push(addon.id); + updateListener.pendingCount++; + installedItem.findUpdates(updateListener, + AddonManager.UPDATE_WHEN_USER_REQUESTED, + "3", "3"); + } + } + } + }); + })); + }); +} + +function test_complete() { + do_check_eq(gItemsNotChecked.length, 0); + testserver.stop(do_test_finished); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug335238.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug335238.js new file mode 100644 index 000000000..e691bb570 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug335238.js @@ -0,0 +1,181 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS"; +const PREF_SELECTED_LOCALE = "general.useragent.locale"; + +// Disables security checking our updates which haven't been signed +Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); + +const Ci = Components.interfaces; +const Cu = Components.utils; + +Cu.import("resource://testing-common/httpd.js"); + +// This is the data we expect to see sent as part of the update url. +var EXPECTED = [ + { + id: "bug335238_1@tests.mozilla.org", + version: "1.3.4", + maxAppVersion: "5", + status: "userEnabled", + appId: "xpcshell@tests.mozilla.org", + appVersion: "1", + appOs: "XPCShell", + appAbi: "noarch-spidermonkey", + locale: "en-US", + reqVersion: "2" + }, + { + id: "bug335238_2@tests.mozilla.org", + version: "28at", + maxAppVersion: "7", + status: "userDisabled", + appId: "xpcshell@tests.mozilla.org", + appVersion: "1", + appOs: "XPCShell", + appAbi: "noarch-spidermonkey", + locale: "en-US", + reqVersion: "2" + }, + { + id: "bug335238_3@tests.mozilla.org", + version: "58", + maxAppVersion: "*", + status: "userDisabled,softblocked", + appId: "xpcshell@tests.mozilla.org", + appVersion: "1", + appOs: "XPCShell", + appAbi: "noarch-spidermonkey", + locale: "en-US", + reqVersion: "2" + }, + { + id: "bug335238_4@tests.mozilla.org", + version: "4", + maxAppVersion: "2+", + status: "userEnabled,blocklisted", + appId: "xpcshell@tests.mozilla.org", + appVersion: "1", + appOs: "XPCShell", + appAbi: "noarch-spidermonkey", + locale: "en-US", + reqVersion: "2" + } +]; + +var ADDONS = [ + {id: "bug335238_1@tests.mozilla.org", + addon: "test_bug335238_1"}, + {id: "bug335238_2@tests.mozilla.org", + addon: "test_bug335238_2"}, + {id: "bug335238_3@tests.mozilla.org", + addon: "test_bug335238_3"}, + {id: "bug335238_4@tests.mozilla.org", + addon: "test_bug335238_4"} +]; + +// This is a replacement for the blocklist service +var BlocklistService = { + getAddonBlocklistState: function(aAddon, aAppVersion, aToolkitVersion) { + if (aAddon.id == "bug335238_3@tests.mozilla.org") + return Ci.nsIBlocklistService.STATE_SOFTBLOCKED; + if (aAddon.id == "bug335238_4@tests.mozilla.org") + return Ci.nsIBlocklistService.STATE_BLOCKED; + return Ci.nsIBlocklistService.STATE_NOT_BLOCKED; + }, + + getPluginBlocklistState: function(aPlugin, aVersion, aAppVersion, aToolkitVersion) { + return Ci.nsIBlocklistService.STATE_NOT_BLOCKED; + }, + + isAddonBlocklisted: function(aAddon, aAppVersion, aToolkitVersion) { + return this.getAddonBlocklistState(aAddon, aAppVersion, aToolkitVersion) == + Ci.nsIBlocklistService.STATE_BLOCKED; + }, + + QueryInterface: function(iid) { + if (iid.equals(Ci.nsIBlocklistService) + || iid.equals(Ci.nsISupports)) + return this; + + throw Components.results.NS_ERROR_NO_INTERFACE; + } +}; + +var BlocklistServiceFactory = { + createInstance: function (outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return BlocklistService.QueryInterface(iid); + } +}; +var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{61189e7a-6b1b-44b8-ac81-f180a6105085}"), "BlocklistService", + "@mozilla.org/extensions/blocklist;1", BlocklistServiceFactory); + +var server; + +var updateListener = { + pendingCount: 0, + + onUpdateAvailable: function(aAddon) { + do_throw("Should not have seen an update for " + aAddon.id); + }, + + onUpdateFinished: function() { + if (--this.pendingCount == 0) + server.stop(do_test_finished); + } +} + +var requestHandler = { + handle: function(metadata, response) + { + var expected = EXPECTED[metadata.path.substring(1)]; + var params = metadata.queryString.split("&"); + do_check_eq(params.length, 10); + for (var k in params) { + var pair = params[k].split("="); + var name = decodeURIComponent(pair[0]); + var value = decodeURIComponent(pair[1]); + do_check_eq(expected[name], value); + } + response.setStatusLine(metadata.httpVersion, 404, "Not Found"); + } +} + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); + + server = new HttpServer(); + server.registerPathHandler("/0", requestHandler); + server.registerPathHandler("/1", requestHandler); + server.registerPathHandler("/2", requestHandler); + server.registerPathHandler("/3", requestHandler); + server.start(4444); + + Services.prefs.setBoolPref(PREF_MATCH_OS_LOCALE, false); + Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "en-US"); + + startupManager(); + installAllFiles([do_get_addon(a.addon) for each (a in ADDONS)], function() { + + restartManager(); + AddonManager.getAddonByID(ADDONS[1].id, callback_soon(function(addon) { + do_check_true(!(!addon)); + addon.userDisabled = true; + restartManager(); + + AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], function(installedItems) { + installedItems.forEach(function(item) { + updateListener.pendingCount++; + item.findUpdates(updateListener, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); + }); + })); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug371495.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug371495.js new file mode 100644 index 000000000..3a80c1945 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug371495.js @@ -0,0 +1,35 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS"; +const PREF_SELECTED_LOCALE = "general.useragent.locale"; + +const ADDON = "test_bug371495"; +const ID = "bug371495@tests.mozilla.org"; + +function run_test() +{ + // Setup for test + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1"); + + // Install test add-on + startupManager(); + installAllFiles([do_get_addon(ADDON)], function() { + AddonManager.getAddonByID(ID, callback_soon(function(addon) { + do_check_neq(addon, null); + do_check_eq(addon.name, "Test theme"); + restartManager(); + + AddonManager.getAddonByID(ID, callback_soon(function(addon) { + do_check_neq(addon, null); + do_check_eq(addon.optionsURL, null); + do_check_eq(addon.aboutURL, null); + + do_execute_soon(do_test_finished); + })); + })); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug384052.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug384052.js new file mode 100644 index 000000000..aeaaf3d8f --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug384052.js @@ -0,0 +1,103 @@ +const CLASS_ID = Components.ID("{12345678-1234-1234-1234-123456789abc}"); +const CONTRACT_ID = "@mozilla.org/test-parameter-source;1"; + +// Get and create the HTTP server. +Components.utils.import("resource://testing-common/httpd.js"); +var testserver = new HttpServer(); +testserver.start(-1); +gPort = testserver.identity.primaryPort; + +var gTestURL = "http://127.0.0.1:" + gPort + "/update.rdf?itemID=%ITEM_ID%&custom1=%CUSTOM1%&custom2=%CUSTOM2%"; +var gExpectedQuery = "itemID=test@mozilla.org&custom1=custom_parameter_1&custom2=custom_parameter_2"; +var gSeenExpectedURL = false; + +var gComponentRegistrar = Components.manager.QueryInterface(AM_Ci.nsIComponentRegistrar); +var gCategoryManager = AM_Cc["@mozilla.org/categorymanager;1"].getService(AM_Ci.nsICategoryManager); + +// Factory for our parameter handler +var paramHandlerFactory = { + QueryInterface: function(iid) { + if (iid.equals(AM_Ci.nsIFactory) || iid.equals(AM_Ci.nsISupports)) + return this; + + throw Components.results.NS_ERROR_NO_INTERFACE; + }, + + createInstance: function(outer, iid) { + var bag = AM_Cc["@mozilla.org/hash-property-bag;1"]. + createInstance(AM_Ci.nsIWritablePropertyBag); + bag.setProperty("CUSTOM1", "custom_parameter_1"); + bag.setProperty("CUSTOM2", "custom_parameter_2"); + return bag.QueryInterface(iid); + } +}; + +function initTest() +{ + do_test_pending(); + // Setup extension manager + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); + + // Configure the HTTP server. + testserver.registerPathHandler("/update.rdf", function(aRequest, aResponse) { + gSeenExpectedURL = aRequest.queryString == gExpectedQuery; + aResponse.setStatusLine(null, 404, "Not Found"); + }); + + // Register our parameter handlers + gComponentRegistrar.registerFactory(CLASS_ID, "Test component", CONTRACT_ID, paramHandlerFactory); + gCategoryManager.addCategoryEntry("extension-update-params", "CUSTOM1", CONTRACT_ID, false, false); + gCategoryManager.addCategoryEntry("extension-update-params", "CUSTOM2", CONTRACT_ID, false, false); + + // Install a test extension into the profile + let dir = gProfD.clone(); + dir.append("extensions"); + writeInstallRDFForExtension({ + id: "test@mozilla.org", + version: "1.0", + name: "Test extension", + updateURL: gTestURL, + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + }, dir); + + startupManager(); +} + +function shutdownTest() +{ + shutdownManager(); + + gComponentRegistrar.unregisterFactory(CLASS_ID, paramHandlerFactory); + gCategoryManager.deleteCategoryEntry("extension-update-params", "CUSTOM1", false); + gCategoryManager.deleteCategoryEntry("extension-update-params", "CUSTOM2", false); + + do_test_finished(); +} + +function run_test() +{ + initTest(); + + AddonManager.getAddonByID("test@mozilla.org", function(item) { + // Initiate update + item.findUpdates({ + onCompatibilityUpdateAvailable: function(addon) { + do_throw("Should not have seen a compatibility update"); + }, + + onUpdateAvailable: function(addon, install) { + do_throw("Should not have seen an available update"); + }, + + onUpdateFinished: function(addon, error) { + do_check_eq(error, AddonManager.UPDATE_STATUS_DOWNLOAD_ERROR); + do_check_true(gSeenExpectedURL); + do_execute_soon(shutdownTest); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug393285.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug393285.js new file mode 100644 index 000000000..90cf29753 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug393285.js @@ -0,0 +1,327 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; + +const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul"; + +Cu.import("resource://testing-common/httpd.js"); +var testserver = new HttpServer(); +testserver.start(-1); +gPort = testserver.identity.primaryPort; + +// register static files with server and interpolate port numbers in them +mapFile("/data/test_bug393285.xml", testserver); + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +let addonIDs = ["test_bug393285_1@tests.mozilla.org", + "test_bug393285_2@tests.mozilla.org", + "test_bug393285_3a@tests.mozilla.org", + "test_bug393285_3b@tests.mozilla.org", + "test_bug393285_4@tests.mozilla.org", + "test_bug393285_5@tests.mozilla.org", + "test_bug393285_6@tests.mozilla.org", + "test_bug393285_7@tests.mozilla.org", + "test_bug393285_8@tests.mozilla.org", + "test_bug393285_9@tests.mozilla.org", + "test_bug393285_10@tests.mozilla.org", + "test_bug393285_11@tests.mozilla.org", + "test_bug393285_12@tests.mozilla.org", + "test_bug393285_13@tests.mozilla.org", + "test_bug393285_14@tests.mozilla.org"]; + +// A window watcher to deal with the blocklist UI dialog. +var WindowWatcher = { + openWindow: function(parent, url, name, features, arguments) { + // Should be called to list the newly blocklisted items + do_check_eq(url, URI_EXTENSION_BLOCKLIST_DIALOG); + + // Simulate auto-disabling any softblocks + var list = arguments.wrappedJSObject.list; + list.forEach(function(aItem) { + if (!aItem.blocked) + aItem.disable = true; + }); + + //run the code after the blocklist is closed + Services.obs.notifyObservers(null, "addon-blocklist-closed", null); + + }, + + QueryInterface: function(iid) { + if (iid.equals(Ci.nsIWindowWatcher) + || iid.equals(Ci.nsISupports)) + return this; + + throw Cr.NS_ERROR_NO_INTERFACE; + } +}; + +var WindowWatcherFactory = { + createInstance: function createInstance(outer, iid) { + if (outer != null) + throw Cr.NS_ERROR_NO_AGGREGATION; + return WindowWatcher.QueryInterface(iid); + } +}; + +var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"), + "Fake Window Watcher", + "@mozilla.org/embedcomp/window-watcher;1", + WindowWatcherFactory); + + +function load_blocklist(aFile, aCallback) { + Services.obs.addObserver(function() { + Services.obs.removeObserver(arguments.callee, "blocklist-updated"); + + do_execute_soon(aCallback); + }, "blocklist-updated", false); + + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + + gPort + "/data/" + aFile); + var blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. + getService(Ci.nsITimerCallback); + blocklist.notify(null); +} + + +function end_test() { + testserver.stop(do_test_finished); +} + +function run_test() { + do_test_pending(); + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); + + writeInstallRDFForExtension({ + id: "test_bug393285_1@tests.mozilla.org", + name: "extension 1", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] + }, profileDir); + + + writeInstallRDFForExtension({ + id: "test_bug393285_2@tests.mozilla.org", + name: "extension 2", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] + }, profileDir); + + writeInstallRDFForExtension({ + id: "test_bug393285_3a@tests.mozilla.org", + name: "extension 3a", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] + }, profileDir); + + writeInstallRDFForExtension({ + id: "test_bug393285_3b@tests.mozilla.org", + name: "extension 3b", + version: "2.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] + }, profileDir); + + writeInstallRDFForExtension({ + id: "test_bug393285_4@tests.mozilla.org", + name: "extension 4", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] + }, profileDir); + + writeInstallRDFForExtension({ + id: "test_bug393285_5@tests.mozilla.org", + name: "extension 5", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] + }, profileDir); + + writeInstallRDFForExtension({ + id: "test_bug393285_6@tests.mozilla.org", + name: "extension 6", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] + }, profileDir); + + writeInstallRDFForExtension({ + id: "test_bug393285_7@tests.mozilla.org", + name: "extension 7", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] + }, profileDir); + + writeInstallRDFForExtension({ + id: "test_bug393285_8@tests.mozilla.org", + name: "extension 8", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] + }, profileDir); + + writeInstallRDFForExtension({ + id: "test_bug393285_9@tests.mozilla.org", + name: "extension 9", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] + }, profileDir); + + writeInstallRDFForExtension({ + id: "test_bug393285_10@tests.mozilla.org", + name: "extension 10", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] + }, profileDir); + + writeInstallRDFForExtension({ + id: "test_bug393285_11@tests.mozilla.org", + name: "extension 11", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] + }, profileDir); + + writeInstallRDFForExtension({ + id: "test_bug393285_12@tests.mozilla.org", + name: "extension 12", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] + }, profileDir); + + writeInstallRDFForExtension({ + id: "test_bug393285_13@tests.mozilla.org", + name: "extension 13", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] + }, profileDir); + + writeInstallRDFForExtension({ + id: "test_bug393285_14@tests.mozilla.org", + name: "extension 14", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] + }, profileDir); + + startupManager(); + + AddonManager.getAddonsByIDs(addonIDs, function(addons) { + for (addon of addons) { + do_check_eq(addon.blocklistState, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + } + run_test_1(); + }); +} + +function run_test_1() { + load_blocklist("test_bug393285.xml", function() { + restartManager(); + + var blocklist = Cc["@mozilla.org/extensions/blocklist;1"] + .getService(Ci.nsIBlocklistService); + + AddonManager.getAddonsByIDs(addonIDs, + function([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15]) { + // No info in blocklist, shouldn't be blocked + do_check_false(blocklist.isAddonBlocklisted(a1, "1", "1.9")); + + // Should always be blocked + do_check_true(blocklist.isAddonBlocklisted(a2, "1", "1.9")); + + // Only version 1 should be blocked + do_check_true(blocklist.isAddonBlocklisted(a3, "1", "1.9")); + do_check_false(blocklist.isAddonBlocklisted(a4, "1", "1.9")); + + // Should be blocked for app version 1 + do_check_true(blocklist.isAddonBlocklisted(a5, "1", "1.9")); + do_check_false(blocklist.isAddonBlocklisted(a5, "2", "1.9")); + + // Not blocklisted because we are a different OS + do_check_false(blocklist.isAddonBlocklisted(a6, "2", "1.9")); + + // Blocklisted based on OS + do_check_true(blocklist.isAddonBlocklisted(a7, "2", "1.9")); + do_check_true(blocklist.isAddonBlocklisted(a8, "2", "1.9")); + + // Not blocklisted because we are a different ABI + do_check_false(blocklist.isAddonBlocklisted(a9, "2", "1.9")); + + // Blocklisted based on ABI + do_check_true(blocklist.isAddonBlocklisted(a10, "2", "1.9")); + do_check_true(blocklist.isAddonBlocklisted(a11, "2", "1.9")); + + // Doesnt match both os and abi so not blocked + do_check_false(blocklist.isAddonBlocklisted(a12, "2", "1.9")); + do_check_false(blocklist.isAddonBlocklisted(a13, "2", "1.9")); + do_check_false(blocklist.isAddonBlocklisted(a14, "2", "1.9")); + + // Matches both os and abi so blocked + do_check_true(blocklist.isAddonBlocklisted(a15, "2", "1.9")); + end_test(); + }); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug394300.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug394300.js new file mode 100644 index 000000000..bd393b91c --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug394300.js @@ -0,0 +1,56 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// Disables security checking our updates which haven't been signed +Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); + +Components.utils.import("resource://testing-common/httpd.js"); +var server; + +// nsIAddonUpdateCheckListener implementation +var updateListener = { + _count: 0, + + onUpdateAvailable: function onAddonUpdateEnded(aAddon, aInstall) { + do_check_eq(aInstall.version, 10); + }, + + onNoUpdateAvailable: function onNoUpdateAvailable(aAddon) { + do_throw("Expected an available update for " + aAddon.id); + }, + + onUpdateFinished: function onUpdateFinished() { + if (++this._count == 2) + server.stop(do_test_finished); + }, +} + +function run_test() +{ + // Setup for test + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); + startupManager(); + + installAllFiles([do_get_addon("test_bug394300_1"), + do_get_addon("test_bug394300_2")], function() { + + restartManager(); + + AddonManager.getAddonsByIDs(["bug394300_1@tests.mozilla.org", + "bug394300_2@tests.mozilla.org"], function(updates) { + + do_check_neq(updates[0], null); + do_check_neq(updates[1], null); + + server = new HttpServer(); + server.registerDirectory("/", do_get_file("data")); + server.start(4444); + + updates[0].findUpdates(updateListener, AddonManager.UPDATE_WHEN_USER_REQUESTED); + updates[1].findUpdates(updateListener, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug397778.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug397778.js new file mode 100644 index 000000000..aa18a6946 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug397778.js @@ -0,0 +1,117 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS"; +const PREF_SELECTED_LOCALE = "general.useragent.locale"; + +const ADDON = "test_bug397778"; +const ID = "bug397778@tests.mozilla.org"; + +function run_test() +{ + // Setup for test + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1"); + Services.prefs.setBoolPref(PREF_MATCH_OS_LOCALE, false); + Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "fr-FR"); + + // Install test add-on + startupManager(); + installAllFiles([do_get_addon(ADDON)], function() { + restartManager(); + + run_test_1(); + }); +} + +function run_test_1() { + AddonManager.getAddonByID(ID, callback_soon(function(addon) { + do_check_neq(addon, null); + do_check_eq(addon.name, "fr Name"); + do_check_eq(addon.description, "fr Description"); + + // Disable item + addon.userDisabled = true; + restartManager(); + + AddonManager.getAddonByID(ID, function(newAddon) { + do_check_neq(newAddon, null); + do_check_eq(newAddon.name, "fr Name"); + + do_execute_soon(run_test_2); + }); + })); +} + +function run_test_2() { + // Change locale. The more specific de-DE is the best match + Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "de"); + restartManager(); + + AddonManager.getAddonByID(ID, function(addon) { + do_check_neq(addon, null); + do_check_eq(addon.name, "de-DE Name"); + do_check_eq(addon.description, null); + + do_execute_soon(run_test_3); + }); +} + +function run_test_3() { + // Change locale. Locale case should have no effect + Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "DE-de"); + restartManager(); + + AddonManager.getAddonByID(ID, function(addon) { + do_check_neq(addon, null); + do_check_eq(addon.name, "de-DE Name"); + do_check_eq(addon.description, null); + + do_execute_soon(run_test_4); + }); +} + +function run_test_4() { + // Change locale. es-ES should closely match + Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "es-AR"); + restartManager(); + + AddonManager.getAddonByID(ID, function(addon) { + do_check_neq(addon, null); + do_check_eq(addon.name, "es-ES Name"); + do_check_eq(addon.description, "es-ES Description"); + + do_execute_soon(run_test_5); + }); +} + +function run_test_5() { + // Change locale. Either zh-CN or zh-TW could match + Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "zh"); + restartManager(); + + AddonManager.getAddonByID(ID, function(addon) { + do_check_neq(addon, null); + if (addon.name != "zh-TW Name" && addon.name != "zh-CN Name") + do_throw("zh matched to " + addon.name); + + do_execute_soon(run_test_6); + }); +} + +function run_test_6() { + // Unknown locale should try to match against en-US as well. Of en,en-GB + // en should match as being less specific + Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "nl-NL"); + restartManager(); + + AddonManager.getAddonByID(ID, function(addon) { + do_check_neq(addon, null); + do_check_eq(addon.name, "en Name"); + do_check_eq(addon.description, "en Description"); + + do_execute_soon(do_test_finished); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug406118.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug406118.js new file mode 100644 index 000000000..724b48dd5 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug406118.js @@ -0,0 +1,167 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +let addonIDs = ["test_bug393285_1@tests.mozilla.org", + "test_bug393285_2@tests.mozilla.org", + "test_bug393285_3a@tests.mozilla.org", + "test_bug393285_4@tests.mozilla.org"]; + +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; + +const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul"; + +Cu.import("resource://testing-common/httpd.js"); +var testserver = new HttpServer(); +testserver.start(-1); +gPort = testserver.identity.primaryPort; + +// register static files with server and interpolate port numbers in them +mapFile("/data/test_bug393285.xml", testserver); + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +// A window watcher to deal with the blocklist UI dialog. +var WindowWatcher = { + openWindow: function(parent, url, name, features, arguments) { + // Should be called to list the newly blocklisted items + do_check_eq(url, URI_EXTENSION_BLOCKLIST_DIALOG); + + // Simulate auto-disabling any softblocks + var list = arguments.wrappedJSObject.list; + list.forEach(function(aItem) { + if (!aItem.blocked) + aItem.disable = true; + }); + + //run the code after the blocklist is closed + Services.obs.notifyObservers(null, "addon-blocklist-closed", null); + + }, + + QueryInterface: function(iid) { + if (iid.equals(Ci.nsIWindowWatcher) + || iid.equals(Ci.nsISupports)) + return this; + + throw Cr.NS_ERROR_NO_INTERFACE; + } +}; + +var WindowWatcherFactory = { + createInstance: function createInstance(outer, iid) { + if (outer != null) + throw Cr.NS_ERROR_NO_AGGREGATION; + return WindowWatcher.QueryInterface(iid); + } +}; + +var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"), + "Fake Window Watcher", + "@mozilla.org/embedcomp/window-watcher;1", + WindowWatcherFactory); + + +function load_blocklist(aFile, aCallback) { + Services.obs.addObserver(function() { + Services.obs.removeObserver(arguments.callee, "blocklist-updated"); + + do_execute_soon(aCallback); + }, "blocklist-updated", false); + + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + + gPort + "/data/" + aFile); + var blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. + getService(Ci.nsITimerCallback); + blocklist.notify(null); +} + + +function end_test() { + testserver.stop(do_test_finished); +} + +function run_test() { + do_test_pending(); + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); + + writeInstallRDFForExtension({ + id: "test_bug393285_1@tests.mozilla.org", + name: "extension 1", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] + }, profileDir); + + + writeInstallRDFForExtension({ + id: "test_bug393285_2@tests.mozilla.org", + name: "extension 2", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] + }, profileDir); + + writeInstallRDFForExtension({ + id: "test_bug393285_3a@tests.mozilla.org", + name: "extension 3a", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] + }, profileDir); + + writeInstallRDFForExtension({ + id: "test_bug393285_4@tests.mozilla.org", + name: "extension 4", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] + }, profileDir); + + startupManager(); + + AddonManager.getAddonsByIDs(addonIDs, function(addons) { + for (addon of addons) { + do_check_eq(addon.blocklistState, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + } + run_test_1(); + }); +} + +function run_test_1() { + load_blocklist("test_bug393285.xml", function() { + restartManager(); + + var blocklist = Cc["@mozilla.org/extensions/blocklist;1"] + .getService(Ci.nsIBlocklistService); + + AddonManager.getAddonsByIDs(addonIDs, + function([a1, a2, a3, a4]) { + // No info in blocklist, shouldn't be blocked + do_check_false(blocklist.isAddonBlocklisted(a1, null, null)); + + // All these should be blocklisted for the current app. + do_check_true(blocklist.isAddonBlocklisted(a2, null, null)); + do_check_true(blocklist.isAddonBlocklisted(a3, null, null)); + do_check_true(blocklist.isAddonBlocklisted(a4, null, null)); + + end_test(); + }); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug424262.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug424262.js new file mode 100644 index 000000000..8b29e15a5 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug424262.js @@ -0,0 +1,62 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Components.utils.import("resource://gre/modules/addons/AddonRepository.jsm"); + +const PREF_GETADDONS_GETRECOMMENDED = "extensions.getAddons.recommended.url"; + +Components.utils.import("resource://testing-common/httpd.js"); +var server; +var RESULTS = [ + null, + null, + 0, + 2, + 4, + 5, + 5, + 5 +]; + +var RecommendedCallback = { + searchSucceeded: function(addons, length, total) { + dump("loaded"); + // Search is complete + do_check_eq(length, RESULTS.length); + + for (var i = 0; i < length; i++) { + if (addons[i].averageRating != RESULTS[i]) + do_throw("Rating for " + addons[i].id + " was " + addons[i].averageRating + ", should have been " + RESULTS[i]); + } + server.stop(do_test_finished); + }, + + searchFailed: function() { + server.stop(do_test_finished); + do_throw("Recommended results failed"); + } +}; + +function run_test() +{ + // EM needs to be running. + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); + startupManager(); + + server = new HttpServer(); + server.start(-1); + gPort = server.identity.primaryPort; + mapFile("/data/test_bug424262.xml", server); + + // Point the addons repository to the test server + Services.prefs.setCharPref(PREF_GETADDONS_GETRECOMMENDED, "http://localhost:" + + gPort + "/data/test_bug424262.xml"); + + do_check_neq(AddonRepository, null); + + do_test_pending(); + // Pull some results. + AddonRepository.retrieveRecommendedAddons(RESULTS.length, RecommendedCallback); +} + diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug425657.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug425657.js new file mode 100644 index 000000000..f11a942fb --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug425657.js @@ -0,0 +1,27 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +const ADDON = "test_bug425657"; +const ID = "bug425657@tests.mozilla.org"; + +function run_test() +{ + // Setup for test + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1"); + + // Install test add-on + startupManager(); + installAllFiles([do_get_addon(ADDON)], function() { + restartManager(); + AddonManager.getAddonByID(ID, function(addon) { + do_check_neq(addon, null); + do_check_eq(addon.name, "Deutsches W\u00f6rterbuch"); + do_check_eq(addon.name.length, 20); + + do_execute_soon(do_test_finished); + }); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug430120.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug430120.js new file mode 100644 index 000000000..74080dba9 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug430120.js @@ -0,0 +1,142 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +const BLOCKLIST_TIMER = "blocklist-background-update-timer"; +const PREF_BLOCKLIST_URL = "extensions.blocklist.url"; +const PREF_BLOCKLIST_ENABLED = "extensions.blocklist.enabled"; +const PREF_APP_DISTRIBUTION = "distribution.id"; +const PREF_APP_DISTRIBUTION_VERSION = "distribution.version"; +const PREF_APP_UPDATE_CHANNEL = "app.update.channel"; +const PREF_GENERAL_USERAGENT_LOCALE = "general.useragent.locale"; +const CATEGORY_UPDATE_TIMER = "update-timer"; + +// Get the HTTP server. +Components.utils.import("resource://testing-common/httpd.js"); +var testserver; +var gOSVersion; +var gBlocklist; + +// This is a replacement for the timer service so we can trigger timers +var timerService = { + + hasTimer: function(id) { + var catMan = Components.classes["@mozilla.org/categorymanager;1"] + .getService(Components.interfaces.nsICategoryManager); + var entries = catMan.enumerateCategory(CATEGORY_UPDATE_TIMER); + while (entries.hasMoreElements()) { + var entry = entries.getNext().QueryInterface(Components.interfaces.nsISupportsCString).data; + var value = catMan.getCategoryEntry(CATEGORY_UPDATE_TIMER, entry); + var timerID = value.split(",")[2]; + if (id == timerID) { + return true; + } + } + return false; + }, + + fireTimer: function(id) { + gBlocklist.QueryInterface(Components.interfaces.nsITimerCallback).notify(null); + }, + + QueryInterface: function(iid) { + if (iid.equals(Components.interfaces.nsIUpdateTimerManager) + || iid.equals(Components.interfaces.nsISupports)) + return this; + + throw Components.results.NS_ERROR_NO_INTERFACE; + } +}; + +var TimerServiceFactory = { + createInstance: function (outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return timerService.QueryInterface(iid); + } +}; +var registrar = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{61189e7a-6b1b-44b8-ac81-f180a6105085}"), "TimerService", + "@mozilla.org/updates/timer-manager;1", TimerServiceFactory); + +function failHandler(metadata, response) { + do_throw("Should not have attempted to retrieve the blocklist when it is disabled"); +} + +function pathHandler(metadata, response) { + var ABI = "noarch-spidermonkey"; + // the blacklist service special-cases ABI for Universal binaries, + // so do the same here. + if ("@mozilla.org/xpcom/mac-utils;1" in Components.classes) { + var macutils = Components.classes["@mozilla.org/xpcom/mac-utils;1"] + .getService(Components.interfaces.nsIMacUtils); + if (macutils.isUniversalBinary) + ABI += "-u-" + macutils.architecturesInBinary; + } + do_check_eq(metadata.queryString, + "xpcshell@tests.mozilla.org&1&XPCShell&1&2007010101&" + + "XPCShell_" + ABI + "&locale&updatechannel&" + + gOSVersion + "&1.9&distribution&distribution-version"); + gBlocklist.observe(null, "quit-application", ""); + gBlocklist.observe(null, "xpcom-shutdown", ""); + testserver.stop(do_test_finished); +} + +function run_test() { + var osVersion; + var sysInfo = Components.classes["@mozilla.org/system-info;1"] + .getService(Components.interfaces.nsIPropertyBag2); + try { + osVersion = sysInfo.getProperty("name") + " " + sysInfo.getProperty("version"); + if (osVersion) { + try { + osVersion += " (" + sysInfo.getProperty("secondaryLibrary") + ")"; + } + catch (e) { + } + gOSVersion = encodeURIComponent(osVersion); + } + } + catch (e) { + } + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); + + testserver = new HttpServer(); + testserver.registerPathHandler("/1", failHandler); + testserver.registerPathHandler("/2", pathHandler); + testserver.start(-1); + gPort = testserver.identity.primaryPort; + + // Initialise the blocklist service + gBlocklist = Components.classes["@mozilla.org/extensions/blocklist;1"] + .getService(Components.interfaces.nsIBlocklistService) + .QueryInterface(Components.interfaces.nsIObserver); + gBlocklist.observe(null, "profile-after-change", ""); + + do_check_true(timerService.hasTimer(BLOCKLIST_TIMER)); + + do_test_pending(); + + // This should have no effect as the blocklist is disabled + Services.prefs.setCharPref(PREF_BLOCKLIST_URL, "http://localhost:" + gPort + "/1"); + Services.prefs.setBoolPref(PREF_BLOCKLIST_ENABLED, false); + timerService.fireTimer(BLOCKLIST_TIMER); + + // Some values have to be on the default branch to work + var defaults = Services.prefs.QueryInterface(Components.interfaces.nsIPrefService) + .getDefaultBranch(null); + defaults.setCharPref(PREF_APP_UPDATE_CHANNEL, "updatechannel"); + defaults.setCharPref(PREF_APP_DISTRIBUTION, "distribution"); + defaults.setCharPref(PREF_APP_DISTRIBUTION_VERSION, "distribution-version"); + defaults.setCharPref(PREF_GENERAL_USERAGENT_LOCALE, "locale"); + + // This should correctly escape everything + Services.prefs.setCharPref(PREF_BLOCKLIST_URL, "http://localhost:" + gPort + "/2?" + + "%APP_ID%&%APP_VERSION%&%PRODUCT%&%VERSION%&%BUILD_ID%&" + + "%BUILD_TARGET%&%LOCALE%&%CHANNEL%&" + + "%OS_VERSION%&%PLATFORM_VERSION%&%DISTRIBUTION%&%DISTRIBUTION_VERSION%"); + Services.prefs.setBoolPref(PREF_BLOCKLIST_ENABLED, true); + timerService.fireTimer(BLOCKLIST_TIMER); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug449027.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug449027.js new file mode 100644 index 000000000..623a6a14a --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug449027.js @@ -0,0 +1,448 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul"; + +const Ci = Components.interfaces; +const Cu = Components.utils; + +Cu.import("resource://testing-common/httpd.js"); + +var ADDONS = [{ + id: "test_bug449027_1@tests.mozilla.org", + name: "Bug 449027 Addon Test 1", + version: "5", + start: false, + appBlocks: false, + toolkitBlocks: false +}, { + id: "test_bug449027_2@tests.mozilla.org", + name: "Bug 449027 Addon Test 2", + version: "5", + start: false, + appBlocks: true, + toolkitBlocks: false +}, { + id: "test_bug449027_3@tests.mozilla.org", + name: "Bug 449027 Addon Test 3", + version: "5", + start: false, + appBlocks: true, + toolkitBlocks: false +}, { + id: "test_bug449027_4@tests.mozilla.org", + name: "Bug 449027 Addon Test 4", + version: "5", + start: false, + appBlocks: false, + toolkitBlocks: false +}, { + id: "test_bug449027_5@tests.mozilla.org", + name: "Bug 449027 Addon Test 5", + version: "5", + start: false, + appBlocks: false, + toolkitBlocks: false +}, { + id: "test_bug449027_6@tests.mozilla.org", + name: "Bug 449027 Addon Test 6", + version: "5", + start: false, + appBlocks: true, + toolkitBlocks: false +}, { + id: "test_bug449027_7@tests.mozilla.org", + name: "Bug 449027 Addon Test 7", + version: "5", + start: false, + appBlocks: true, + toolkitBlocks: false +}, { + id: "test_bug449027_8@tests.mozilla.org", + name: "Bug 449027 Addon Test 8", + version: "5", + start: false, + appBlocks: true, + toolkitBlocks: false +}, { + id: "test_bug449027_9@tests.mozilla.org", + name: "Bug 449027 Addon Test 9", + version: "5", + start: false, + appBlocks: true, + toolkitBlocks: false +}, { + id: "test_bug449027_10@tests.mozilla.org", + name: "Bug 449027 Addon Test 10", + version: "5", + start: false, + appBlocks: true, + toolkitBlocks: false +}, { + id: "test_bug449027_11@tests.mozilla.org", + name: "Bug 449027 Addon Test 11", + version: "5", + start: false, + appBlocks: true, + toolkitBlocks: false +}, { + id: "test_bug449027_12@tests.mozilla.org", + name: "Bug 449027 Addon Test 12", + version: "5", + start: false, + appBlocks: true, + toolkitBlocks: false +}, { + id: "test_bug449027_13@tests.mozilla.org", + name: "Bug 449027 Addon Test 13", + version: "5", + start: false, + appBlocks: true, + toolkitBlocks: false +}, { + id: "test_bug449027_14@tests.mozilla.org", + name: "Bug 449027 Addon Test 14", + version: "5", + start: false, + appBlocks: false, + toolkitBlocks: false +}, { + id: "test_bug449027_15@tests.mozilla.org", + name: "Bug 449027 Addon Test 15", + version: "5", + start: false, + appBlocks: true, + toolkitBlocks: true +}, { + id: "test_bug449027_16@tests.mozilla.org", + name: "Bug 449027 Addon Test 16", + version: "5", + start: false, + appBlocks: true, + toolkitBlocks: true +}, { + id: "test_bug449027_17@tests.mozilla.org", + name: "Bug 449027 Addon Test 17", + version: "5", + start: false, + appBlocks: false, + toolkitBlocks: false +}, { + id: "test_bug449027_18@tests.mozilla.org", + name: "Bug 449027 Addon Test 18", + version: "5", + start: false, + appBlocks: false, + toolkitBlocks: false +}, { + id: "test_bug449027_19@tests.mozilla.org", + name: "Bug 449027 Addon Test 19", + version: "5", + start: false, + appBlocks: true, + toolkitBlocks: true +}, { + id: "test_bug449027_20@tests.mozilla.org", + name: "Bug 449027 Addon Test 20", + version: "5", + start: false, + appBlocks: true, + toolkitBlocks: true +}, { + id: "test_bug449027_21@tests.mozilla.org", + name: "Bug 449027 Addon Test 21", + version: "5", + start: false, + appBlocks: true, + toolkitBlocks: true +}, { + id: "test_bug449027_22@tests.mozilla.org", + name: "Bug 449027 Addon Test 22", + version: "5", + start: false, + appBlocks: true, + toolkitBlocks: true +}, { + id: "test_bug449027_23@tests.mozilla.org", + name: "Bug 449027 Addon Test 23", + version: "5", + start: false, + appBlocks: true, + toolkitBlocks: true +}, { + id: "test_bug449027_24@tests.mozilla.org", + name: "Bug 449027 Addon Test 24", + version: "5", + start: false, + appBlocks: true, + toolkitBlocks: true +}, { + id: "test_bug449027_25@tests.mozilla.org", + name: "Bug 449027 Addon Test 25", + version: "5", + start: false, + appBlocks: true, + toolkitBlocks: true +}]; + +function MockPluginTag(name, version, start, appBlocks, toolkitBlocks) +{ + this.name = name; + this.version = version; + this.start = start; + this.appBlocks = appBlocks; + this.toolkitBlocks = toolkitBlocks; +} +Object.defineProperty(MockPluginTag.prototype, "blocklisted", { + get: function MockPluginTag_getBlocklisted() { + let bls = AM_Cc["@mozilla.org/extensions/blocklist;1"].getService(Ci.nsIBlocklistService); + return bls.getPluginBlocklistState(this) == bls.STATE_BLOCKED; + } +}); + +var PLUGINS = [ + new MockPluginTag("test_bug449027_1", "5", false, false, false), + new MockPluginTag("test_bug449027_2", "5", false, true, false), + new MockPluginTag("test_bug449027_3", "5", false, true, false), + new MockPluginTag("test_bug449027_4", "5", false, false, false), + new MockPluginTag("test_bug449027_5", "5", false, false, false), + new MockPluginTag("test_bug449027_6", "5", false, true, false), + new MockPluginTag("test_bug449027_7", "5", false, true, false), + new MockPluginTag("test_bug449027_8", "5", false, true, false), + new MockPluginTag("test_bug449027_9", "5", false, true, false), + new MockPluginTag("test_bug449027_10", "5", false, true, false), + new MockPluginTag("test_bug449027_11", "5", false, true, false), + new MockPluginTag("test_bug449027_12", "5", false, true, false), + new MockPluginTag("test_bug449027_13", "5", false, true, false), + new MockPluginTag("test_bug449027_14", "5", false, false, false), + new MockPluginTag("test_bug449027_15", "5", false, true, true), + new MockPluginTag("test_bug449027_16", "5", false, true, true), + new MockPluginTag("test_bug449027_17", "5", false, false, false), + new MockPluginTag("test_bug449027_18", "5", false, false, false), + new MockPluginTag("test_bug449027_19", "5", false, true, true), + new MockPluginTag("test_bug449027_20", "5", false, true, true), + new MockPluginTag("test_bug449027_21", "5", false, true, true), + new MockPluginTag("test_bug449027_22", "5", false, true, true), + new MockPluginTag("test_bug449027_23", "5", false, true, true), + new MockPluginTag("test_bug449027_24", "5", false, true, true), + new MockPluginTag("test_bug449027_25", "5", false, true, true) +]; + +var gCallback = null; +var gTestserver = null; +var gNewBlocks = []; + +// A fake plugin host for the blocklist service to use +var PluginHost = { + getPluginTags: function(countRef) { + countRef.value = PLUGINS.length; + return PLUGINS; + }, + + QueryInterface: function(iid) { + if (iid.equals(Ci.nsIPluginHost) + || iid.equals(Ci.nsISupports)) + return this; + + throw Components.results.NS_ERROR_NO_INTERFACE; + } +} + +var PluginHostFactory = { + createInstance: function (outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return PluginHost.QueryInterface(iid); + } +}; + +// Don't need the full interface, attempts to call other methods will just +// throw which is just fine +var WindowWatcher = { + openWindow: function(parent, url, name, features, arguments) { + // Should be called to list the newly blocklisted items + do_check_eq(url, URI_EXTENSION_BLOCKLIST_DIALOG); + do_check_neq(gCallback, null); + + var args = arguments.wrappedJSObject; + + gNewBlocks = []; + var list = args.list; + for (let listItem of list) + gNewBlocks.push(listItem.name + " " + listItem.version); + + // Call the callback after the blocklist has finished up + do_timeout(0, gCallback); + }, + + QueryInterface: function(iid) { + if (iid.equals(Ci.nsIWindowWatcher) + || iid.equals(Ci.nsISupports)) + return this; + + throw Components.results.NS_ERROR_NO_INTERFACE; + } +} + +var WindowWatcherFactory = { + createInstance: function createInstance(outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return WindowWatcher.QueryInterface(iid); + } +}; +var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{721c3e73-969e-474b-a6dc-059fd288c428}"), + "Fake Plugin Host", + "@mozilla.org/plugin/host;1", PluginHostFactory); +registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"), + "Fake Window Watcher", + "@mozilla.org/embedcomp/window-watcher;1", WindowWatcherFactory); + +function create_addon(addon) { + var installrdf = "<?xml version=\"1.0\"?>\n" + + "\n" + + "<RDF xmlns=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n" + + " xmlns:em=\"http://www.mozilla.org/2004/em-rdf#\">\n" + + " <Description about=\"urn:mozilla:install-manifest\">\n" + + " <em:id>" + addon.id + "</em:id>\n" + + " <em:version>" + addon.version + "</em:version>\n" + + " <em:targetApplication>\n" + + " <Description>\n" + + " <em:id>xpcshell@tests.mozilla.org</em:id>\n" + + " <em:minVersion>3</em:minVersion>\n" + + " <em:maxVersion>3</em:maxVersion>\n" + + " </Description>\n" + + " </em:targetApplication>\n" + + " <em:name>" + addon.name + "</em:name>\n" + + " </Description>\n" + + "</RDF>\n"; + var target = gProfD.clone(); + target.append("extensions"); + target.append(addon.id); + target.append("install.rdf"); + target.create(target.NORMAL_FILE_TYPE, 0644); + var stream = Components.classes["@mozilla.org/network/file-output-stream;1"] + .createInstance(Ci.nsIFileOutputStream); + stream.init(target, 0x04 | 0x08 | 0x20, 0664, 0); // write, create, truncate + stream.write(installrdf, installrdf.length); + stream.close(); +} + +/** + * Checks that items are blocklisted correctly according to the current test. + * If a lastTest is provided checks that the notification dialog got passed + * the newly blocked items compared to the previous test. + */ +function check_state(test, lastTest, callback) { + AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], function(addons) { + for (var i = 0; i < ADDONS.length; i++) { + var blocked = addons[i].blocklistState == Ci.nsIBlocklistService.STATE_BLOCKED; + if (blocked != ADDONS[i][test]) + do_throw("Blocklist state did not match expected for extension " + (i + 1) + ", test " + test); + } + + for (i = 0; i < PLUGINS.length; i++) { + if (PLUGINS[i].blocklisted != PLUGINS[i][test]) + do_throw("Blocklist state did not match expected for plugin " + (i + 1) + ", test " + test); + } + + if (lastTest) { + var expected = 0; + for (i = 0; i < ADDONS.length; i++) { + if (ADDONS[i][test] && !ADDONS[i][lastTest]) { + if (gNewBlocks.indexOf(ADDONS[i].name + " " + ADDONS[i].version) < 0) + do_throw("Addon " + (i + 1) + " should have been listed in the blocklist notification for test " + test); + expected++; + } + } + + for (i = 0; i < PLUGINS.length; i++) { + if (PLUGINS[i][test] && !PLUGINS[i][lastTest]) { + if (gNewBlocks.indexOf(PLUGINS[i].name + " " + PLUGINS[i].version) < 0) + do_throw("Plugin " + (i + 1) + " should have been listed in the blocklist notification for test " + test); + expected++; + } + } + + do_check_eq(expected, gNewBlocks.length); + } + do_execute_soon(callback); + }); +} + +function load_blocklist(file) { + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + gPort + "/data/" + file); + var blocklist = Components.classes["@mozilla.org/extensions/blocklist;1"] + .getService(Ci.nsITimerCallback); + blocklist.notify(null); +} + +function run_test() { + // Setup for test + dump("Setting up tests\n"); + // Rather than keeping lots of identical add-ons in version control, just + // write them into the profile. + for (let addon of ADDONS) + create_addon(addon); + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); + startupManager(); + + gTestserver = new HttpServer(); + gTestserver.registerDirectory("/data/", do_get_file("data")); + gTestserver.start(-1); + gPort = gTestserver.identity.primaryPort; + + do_test_pending(); + check_test_pt1(); +} + +/** + * Checks the initial state is correct + */ +function check_test_pt1() { + dump("Checking pt 1\n"); + + AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], function(addons) { + for (var i = 0; i < ADDONS.length; i++) { + if (!addons[i]) + do_throw("Addon " + (i + 1) + " did not get installed correctly"); + } + + do_execute_soon(function checkstate1() {check_state("start", null, run_test_pt2);}); + }); +} + +/** + * Load the toolkit based blocks + */ +function run_test_pt2() { + dump("Running test pt 2\n"); + gCallback = check_test_pt2; + load_blocklist("test_bug449027_toolkit.xml"); +} + +function check_test_pt2() { + dump("Checking pt 2\n"); + check_state("toolkitBlocks", "start", run_test_pt3); +} + +/** + * Load the application based blocks + */ +function run_test_pt3() { + dump("Running test pt 3\n"); + gCallback = check_test_pt3; + load_blocklist("test_bug449027_app.xml"); +} + +function check_test_pt3() { + dump("Checking pt 3\n"); + check_state("appBlocks", "toolkitBlocks", end_test); +} + +function end_test() { + gTestserver.stop(do_test_finished); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug455906.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug455906.js new file mode 100644 index 000000000..9a41e827c --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug455906.js @@ -0,0 +1,536 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; +const Cr = Components.results; + +const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul"; + +Cu.import("resource://testing-common/httpd.js"); +var gTestserver = new HttpServer(); +gTestserver.start(-1); +gPort = gTestserver.identity.primaryPort; + +// register static files with server and interpolate port numbers in them +mapFile("/data/bug455906_warn.xml", gTestserver); +mapFile("/data/bug455906_start.xml", gTestserver); +mapFile("/data/bug455906_block.xml", gTestserver); +mapFile("/data/bug455906_empty.xml", gTestserver); + +// Workaround for Bug 658720 - URL formatter can leak during xpcshell tests +const PREF_BLOCKLIST_ITEM_URL = "extensions.blocklist.itemURL"; +Services.prefs.setCharPref(PREF_BLOCKLIST_ITEM_URL, "http://localhost:" + gPort + "/blocklist/%blockID%"); + +var ADDONS = [{ + // Tests how the blocklist affects a disabled add-on + id: "test_bug455906_1@tests.mozilla.org", + name: "Bug 455906 Addon Test 1", + version: "5", + appVersion: "3" +}, { + // Tests how the blocklist affects an enabled add-on + id: "test_bug455906_2@tests.mozilla.org", + name: "Bug 455906 Addon Test 2", + version: "5", + appVersion: "3" +}, { + // Tests how the blocklist affects an enabled add-on, to be disabled by the notification + id: "test_bug455906_3@tests.mozilla.org", + name: "Bug 455906 Addon Test 3", + version: "5", + appVersion: "3" +}, { + // Tests how the blocklist affects a disabled add-on that was already warned about + id: "test_bug455906_4@tests.mozilla.org", + name: "Bug 455906 Addon Test 4", + version: "5", + appVersion: "3" +}, { + // Tests how the blocklist affects an enabled add-on that was already warned about + id: "test_bug455906_5@tests.mozilla.org", + name: "Bug 455906 Addon Test 5", + version: "5", + appVersion: "3" +}, { + // Tests how the blocklist affects an already blocked add-on + id: "test_bug455906_6@tests.mozilla.org", + name: "Bug 455906 Addon Test 6", + version: "5", + appVersion: "3" +}, { + // Tests how the blocklist affects an incompatible add-on + id: "test_bug455906_7@tests.mozilla.org", + name: "Bug 455906 Addon Test 7", + version: "5", + appVersion: "2" +}, { + // Spare add-on used to ensure we get a notification when switching lists + id: "dummy_bug455906_1@tests.mozilla.org", + name: "Dummy Addon 1", + version: "5", + appVersion: "3" +}, { + // Spare add-on used to ensure we get a notification when switching lists + id: "dummy_bug455906_2@tests.mozilla.org", + name: "Dummy Addon 2", + version: "5", + appVersion: "3" +}]; + +function MockPlugin(name, version, enabledState) { + this.name = name; + this.version = version; + this.enabledState = enabledState; +} +Object.defineProperty(MockPlugin.prototype, "blocklisted", { + get: function MockPlugin_getBlocklisted() { + let bls = Cc["@mozilla.org/extensions/blocklist;1"].getService(Ci.nsIBlocklistService); + return bls.getPluginBlocklistState(this) == bls.STATE_BLOCKED; + } +}); +Object.defineProperty(MockPlugin.prototype, "disabled", { + get: function MockPlugin_getDisabled() { + return this.enabledState == Ci.nsIPluginTag.STATE_DISABLED; + } +}); + +var PLUGINS = [ + // Tests how the blocklist affects a disabled plugin + new MockPlugin("test_bug455906_1", "5", Ci.nsIPluginTag.STATE_DISABLED), + // Tests how the blocklist affects an enabled plugin + new MockPlugin("test_bug455906_2", "5", Ci.nsIPluginTag.STATE_ENABLED), + // Tests how the blocklist affects an enabled plugin, to be disabled by the notification + new MockPlugin("test_bug455906_3", "5", Ci.nsIPluginTag.STATE_ENABLED), + // Tests how the blocklist affects a disabled plugin that was already warned about + new MockPlugin("test_bug455906_4", "5", Ci.nsIPluginTag.STATE_DISABLED), + // Tests how the blocklist affects an enabled plugin that was already warned about + new MockPlugin("test_bug455906_5", "5", Ci.nsIPluginTag.STATE_ENABLED), + // Tests how the blocklist affects an already blocked plugin + new MockPlugin("test_bug455906_6", "5", Ci.nsIPluginTag.STATE_ENABLED) +]; + +var gNotificationCheck = null; +var gTestCheck = null; + +// A fake plugin host for the blocklist service to use +var PluginHost = { + getPluginTags: function(countRef) { + countRef.value = PLUGINS.length; + return PLUGINS; + }, + + QueryInterface: function(iid) { + if (iid.equals(Ci.nsIPluginHost) + || iid.equals(Ci.nsISupports)) + return this; + + throw Components.results.NS_ERROR_NO_INTERFACE; + } +} + +var PluginHostFactory = { + createInstance: function (outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return PluginHost.QueryInterface(iid); + } +}; + +// Don't need the full interface, attempts to call other methods will just +// throw which is just fine +var WindowWatcher = { + openWindow: function(parent, url, name, features, windowArguments) { + // Should be called to list the newly blocklisted items + do_check_eq(url, URI_EXTENSION_BLOCKLIST_DIALOG); + + if (gNotificationCheck) { + var args = windowArguments.wrappedJSObject; + gNotificationCheck(args); + } + + //run the code after the blocklist is closed + Services.obs.notifyObservers(null, "addon-blocklist-closed", null); + + // Call the next test after the blocklist has finished up + do_timeout(0, gTestCheck); + }, + + QueryInterface: function(iid) { + if (iid.equals(Ci.nsIWindowWatcher) + || iid.equals(Ci.nsISupports)) + return this; + + throw Cr.NS_ERROR_NO_INTERFACE; + } +} + +var WindowWatcherFactory = { + createInstance: function createInstance(outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return WindowWatcher.QueryInterface(iid); + } +}; +var registrar = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{721c3e73-969e-474b-a6dc-059fd288c428}"), + "Fake Plugin Host", + "@mozilla.org/plugin/host;1", PluginHostFactory); +registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"), + "Fake Window Watcher", + "@mozilla.org/embedcomp/window-watcher;1", WindowWatcherFactory); + +function create_addon(addon) { + var installrdf = "<?xml version=\"1.0\"?>\n" + + "\n" + + "<RDF xmlns=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n" + + " xmlns:em=\"http://www.mozilla.org/2004/em-rdf#\">\n" + + " <Description about=\"urn:mozilla:install-manifest\">\n" + + " <em:id>" + addon.id + "</em:id>\n" + + " <em:version>" + addon.version + "</em:version>\n" + + " <em:targetApplication>\n" + + " <Description>\n" + + " <em:id>xpcshell@tests.mozilla.org</em:id>\n" + + " <em:minVersion>" + addon.appVersion + "</em:minVersion>\n" + + " <em:maxVersion>" + addon.appVersion + "</em:maxVersion>\n" + + " </Description>\n" + + " </em:targetApplication>\n" + + " <em:name>" + addon.name + "</em:name>\n" + + " </Description>\n" + + "</RDF>\n"; + var target = gProfD.clone(); + target.append("extensions"); + target.append(addon.id); + target.append("install.rdf"); + target.create(target.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); + var stream = Cc["@mozilla.org/network/file-output-stream;1"]. + createInstance(Ci.nsIFileOutputStream); + stream.init(target, + FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | FileUtils.MODE_TRUNCATE, + FileUtils.PERMS_FILE, 0); + stream.write(installrdf, installrdf.length); + stream.close(); +} + +function load_blocklist(file) { + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + gPort + "/data/" + file); + var blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. + getService(Ci.nsITimerCallback); + blocklist.notify(null); +} + +function check_addon_state(addon) { + return addon.userDisabled + "," + addon.softDisabled + "," + addon.appDisabled; +} + +function check_plugin_state(plugin) { + return plugin.disabled + "," + plugin.blocklisted; +} + +function create_blocklistURL(blockID){ + let url = Services.urlFormatter.formatURLPref(PREF_BLOCKLIST_ITEM_URL); + url = url.replace(/%blockID%/g, blockID); + return url; +} + +// Performs the initial setup +function run_test() { + // Setup for test + dump("Setting up tests\n"); + // Rather than keeping lots of identical add-ons in version control, just + // write them into the profile. + for (let addon of ADDONS) + create_addon(addon); + + // Copy the initial blocklist into the profile to check add-ons start in the + // right state. + copyBlocklistToProfile(do_get_file("data/bug455906_start.xml")); + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); + startupManager(); + + do_test_pending(); + check_test_pt1(); +} + +// Before every main test this is the state the add-ons are meant to be in +function check_initial_state(callback) { + AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], function(addons) { + do_check_eq(check_addon_state(addons[0]), "true,false,false"); + do_check_eq(check_addon_state(addons[1]), "false,false,false"); + do_check_eq(check_addon_state(addons[2]), "false,false,false"); + do_check_eq(check_addon_state(addons[3]), "true,true,false"); + do_check_eq(check_addon_state(addons[4]), "false,false,false"); + do_check_eq(check_addon_state(addons[5]), "false,false,true"); + do_check_eq(check_addon_state(addons[6]), "false,false,true"); + + do_check_eq(check_plugin_state(PLUGINS[0]), "true,false"); + do_check_eq(check_plugin_state(PLUGINS[1]), "false,false"); + do_check_eq(check_plugin_state(PLUGINS[2]), "false,false"); + do_check_eq(check_plugin_state(PLUGINS[3]), "true,false"); + do_check_eq(check_plugin_state(PLUGINS[4]), "false,false"); + do_check_eq(check_plugin_state(PLUGINS[5]), "false,true"); + + callback(); + }); +} + +// Tests the add-ons were installed and the initial blocklist applied as expected +function check_test_pt1() { + dump("Checking pt 1\n"); + + AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], callback_soon(function(addons) { + for (var i = 0; i < ADDONS.length; i++) { + if (!addons[i]) + do_throw("Addon " + (i + 1) + " did not get installed correctly"); + } + + do_check_eq(check_addon_state(addons[0]), "false,false,false"); + do_check_eq(check_addon_state(addons[1]), "false,false,false"); + do_check_eq(check_addon_state(addons[2]), "false,false,false"); + + // Warn add-ons should be soft disabled automatically + do_check_eq(check_addon_state(addons[3]), "true,true,false"); + do_check_eq(check_addon_state(addons[4]), "true,true,false"); + + // Blocked and incompatible should be app disabled only + do_check_eq(check_addon_state(addons[5]), "false,false,true"); + do_check_eq(check_addon_state(addons[6]), "false,false,true"); + + // We've overridden the plugin host so we cannot tell what that would have + // initialised the plugins as + + // Put the add-ons into the base state + addons[0].userDisabled = true; + addons[4].userDisabled = false; + + restartManager(); + check_initial_state(function() { + gNotificationCheck = check_notification_pt2; + gTestCheck = check_test_pt2; + load_blocklist("bug455906_warn.xml"); + }); + })); +} + +function check_notification_pt2(args) { + dump("Checking notification pt 2\n"); + do_check_eq(args.list.length, 4); + + for (let addon of args.list) { + if (addon.item instanceof Ci.nsIPluginTag) { + switch (addon.item.name) { + case "test_bug455906_2": + do_check_false(addon.blocked); + break; + case "test_bug455906_3": + do_check_false(addon.blocked); + addon.disable = true; + break; + default: + do_throw("Unknown addon: " + addon.item.name); + } + } + else { + switch (addon.item.id) { + case "test_bug455906_2@tests.mozilla.org": + do_check_false(addon.blocked); + break; + case "test_bug455906_3@tests.mozilla.org": + do_check_false(addon.blocked); + addon.disable = true; + break; + default: + do_throw("Unknown addon: " + addon.item.id); + } + } + } +} + +function check_test_pt2() { + restartManager(); + dump("Checking results pt 2\n"); + + AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], callback_soon(function(addons) { + // Should have disabled this add-on as requested + do_check_eq(check_addon_state(addons[2]), "true,true,false"); + do_check_eq(check_plugin_state(PLUGINS[2]), "true,false"); + + // The blocked add-on should have changed to soft disabled + do_check_eq(check_addon_state(addons[5]), "true,true,false"); + do_check_eq(check_plugin_state(PLUGINS[5]), "true,false"); + + // These should have been unchanged + do_check_eq(check_addon_state(addons[0]), "true,false,false"); + do_check_eq(check_addon_state(addons[1]), "false,false,false"); + do_check_eq(check_addon_state(addons[3]), "true,true,false"); + do_check_eq(check_addon_state(addons[4]), "false,false,false"); + do_check_eq(check_addon_state(addons[6]), "false,false,true"); + do_check_eq(check_plugin_state(PLUGINS[0]), "true,false"); + do_check_eq(check_plugin_state(PLUGINS[1]), "false,false"); + do_check_eq(check_plugin_state(PLUGINS[3]), "true,false"); + do_check_eq(check_plugin_state(PLUGINS[4]), "false,false"); + + // Back to starting state + addons[2].userDisabled = false; + addons[5].userDisabled = false; + PLUGINS[2].enabledState = Ci.nsIPluginTag.STATE_ENABLED; + PLUGINS[5].enabledState = Ci.nsIPluginTag.STATE_ENABLED; + restartManager(); + gNotificationCheck = null; + gTestCheck = run_test_pt3; + load_blocklist("bug455906_start.xml"); + })); +} + +function run_test_pt3() { + restartManager(); + check_initial_state(function() { + gNotificationCheck = check_notification_pt3; + gTestCheck = check_test_pt3; + load_blocklist("bug455906_block.xml"); + }); +} + +function check_notification_pt3(args) { + dump("Checking notification pt 3\n"); + do_check_eq(args.list.length, 6); + + for (let addon of args.list) { + if (addon.item instanceof Ci.nsIPluginTag) { + switch (addon.item.name) { + case "test_bug455906_2": + do_check_true(addon.blocked); + break; + case "test_bug455906_3": + do_check_true(addon.blocked); + break; + case "test_bug455906_5": + do_check_true(addon.blocked); + break; + default: + do_throw("Unknown addon: " + addon.item.name); + } + } + else { + switch (addon.item.id) { + case "test_bug455906_2@tests.mozilla.org": + do_check_true(addon.blocked); + break; + case "test_bug455906_3@tests.mozilla.org": + do_check_true(addon.blocked); + break; + case "test_bug455906_5@tests.mozilla.org": + do_check_true(addon.blocked); + break; + default: + do_throw("Unknown addon: " + addon.item.id); + } + } + } +} + +function check_test_pt3() { + restartManager(); + dump("Checking results pt 3\n"); + + let blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. + getService(Ci.nsIBlocklistService); + + AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], function(addons) { + // All should have gained the blocklist state, user disabled as previously + do_check_eq(check_addon_state(addons[0]), "true,false,true"); + do_check_eq(check_addon_state(addons[1]), "false,false,true"); + do_check_eq(check_addon_state(addons[2]), "false,false,true"); + do_check_eq(check_addon_state(addons[4]), "false,false,true"); + do_check_eq(check_plugin_state(PLUGINS[0]), "true,true"); + do_check_eq(check_plugin_state(PLUGINS[1]), "false,true"); + do_check_eq(check_plugin_state(PLUGINS[2]), "false,true"); + do_check_eq(check_plugin_state(PLUGINS[3]), "true,true"); + do_check_eq(check_plugin_state(PLUGINS[4]), "false,true"); + + // Should have gained the blocklist state but no longer be soft disabled + do_check_eq(check_addon_state(addons[3]), "false,false,true"); + + // Check blockIDs are correct + do_check_eq(blocklist.getAddonBlocklistURL(addons[0]),create_blocklistURL(addons[0].id)); + do_check_eq(blocklist.getAddonBlocklistURL(addons[1]),create_blocklistURL(addons[1].id)); + do_check_eq(blocklist.getAddonBlocklistURL(addons[2]),create_blocklistURL(addons[2].id)); + do_check_eq(blocklist.getAddonBlocklistURL(addons[3]),create_blocklistURL(addons[3].id)); + do_check_eq(blocklist.getAddonBlocklistURL(addons[4]),create_blocklistURL(addons[4].id)); + + // All plugins have the same blockID on the test + do_check_eq(blocklist.getPluginBlocklistURL(PLUGINS[0]), create_blocklistURL('test_bug455906_plugin')); + do_check_eq(blocklist.getPluginBlocklistURL(PLUGINS[1]), create_blocklistURL('test_bug455906_plugin')); + do_check_eq(blocklist.getPluginBlocklistURL(PLUGINS[2]), create_blocklistURL('test_bug455906_plugin')); + do_check_eq(blocklist.getPluginBlocklistURL(PLUGINS[3]), create_blocklistURL('test_bug455906_plugin')); + do_check_eq(blocklist.getPluginBlocklistURL(PLUGINS[4]), create_blocklistURL('test_bug455906_plugin')); + + // Shouldn't be changed + do_check_eq(check_addon_state(addons[5]), "false,false,true"); + do_check_eq(check_addon_state(addons[6]), "false,false,true"); + do_check_eq(check_plugin_state(PLUGINS[5]), "false,true"); + + // Back to starting state + gNotificationCheck = null; + gTestCheck = run_test_pt4; + load_blocklist("bug455906_start.xml"); + }); +} + +function run_test_pt4() { + AddonManager.getAddonByID(ADDONS[4].id, callback_soon(function(addon) { + addon.userDisabled = false; + PLUGINS[4].enabledState = Ci.nsIPluginTag.STATE_ENABLED; + restartManager(); + check_initial_state(function() { + gNotificationCheck = check_notification_pt4; + gTestCheck = check_test_pt4; + load_blocklist("bug455906_empty.xml"); + }); + })); +} + +function check_notification_pt4(args) { + dump("Checking notification pt 4\n"); + + // Should be just the dummy add-on to force this notification + do_check_eq(args.list.length, 1); + do_check_false(args.list[0].item instanceof Ci.nsIPluginTag); + do_check_eq(args.list[0].item.id, "dummy_bug455906_2@tests.mozilla.org"); +} + +function check_test_pt4() { + restartManager(); + dump("Checking results pt 4\n"); + + AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], function(addons) { + // This should have become unblocked + do_check_eq(check_addon_state(addons[5]), "false,false,false"); + do_check_eq(check_plugin_state(PLUGINS[5]), "false,false"); + + // Should get re-enabled + do_check_eq(check_addon_state(addons[3]), "false,false,false"); + + // No change for anything else + do_check_eq(check_addon_state(addons[0]), "true,false,false"); + do_check_eq(check_addon_state(addons[1]), "false,false,false"); + do_check_eq(check_addon_state(addons[2]), "false,false,false"); + do_check_eq(check_addon_state(addons[4]), "false,false,false"); + do_check_eq(check_addon_state(addons[6]), "false,false,true"); + do_check_eq(check_plugin_state(PLUGINS[0]), "true,false"); + do_check_eq(check_plugin_state(PLUGINS[1]), "false,false"); + do_check_eq(check_plugin_state(PLUGINS[2]), "false,false"); + do_check_eq(check_plugin_state(PLUGINS[3]), "true,false"); + do_check_eq(check_plugin_state(PLUGINS[4]), "false,false"); + + finish(); + }); +} + +function finish() { + gTestserver.stop(do_test_finished); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug465190.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug465190.js new file mode 100644 index 000000000..fc8c772c9 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug465190.js @@ -0,0 +1,39 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +var installLocation = gProfD.clone(); +installLocation.append("baddir"); +installLocation.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0664); + +var dirProvider2 = { + getFile: function(prop, persistent) { + persistent.value = true; + if (prop == "XREUSysExt") + return installLocation.clone(); + return null; + }, + QueryInterface: function(iid) { + if (iid.equals(Components.interfaces.nsIDirectoryServiceProvider) || + iid.equals(Components.interfaces.nsISupports)) { + return this; + } + throw Components.results.NS_ERROR_NO_INTERFACE; + } +}; +Services.dirsvc.QueryInterface(Components.interfaces.nsIDirectoryService) + .registerProvider(dirProvider2); + +function run_test() +{ + var log = gProfD.clone(); + log.append("extensions.log"); + do_check_false(log.exists()); + + // Setup for test + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1"); + + startupManager(); + do_check_false(log.exists()); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug468528.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug468528.js new file mode 100644 index 000000000..5e8702eb7 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug468528.js @@ -0,0 +1,58 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const nsIBLS = Components.interfaces.nsIBlocklistService; + +var PLUGINS = [{ + // Normal blacklisted plugin, before an invalid regexp + name: "test_bug468528_1", + version: "5", + disabled: false, + blocklisted: false +}, +{ + // Normal blacklisted plugin, with an invalid regexp + name: "test_bug468528_2", + version: "5", + disabled: false, + blocklisted: false +}, +{ + // Normal blacklisted plugin, after an invalid regexp + name: "test_bug468528_3", + version: "5", + disabled: false, + blocklisted: false +}, +{ + // Non-blocklisted plugin + name: "test_bug468528_4", + version: "5", + disabled: false, + blocklisted: false +}]; + + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); + + // We cannot force the blocklist to update so just copy our test list to the profile + copyBlocklistToProfile(do_get_file("data/test_bug468528.xml")); + + var blocklist = Components.classes["@mozilla.org/extensions/blocklist;1"] + .getService(nsIBLS); + + // blocked (sanity check) + do_check_true(blocklist.getPluginBlocklistState(PLUGINS[0], "1", "1.9") == nsIBLS.STATE_BLOCKED); + + // not blocked - won't match due to invalid regexp + do_check_true(blocklist.getPluginBlocklistState(PLUGINS[1], "1", "1.9") == nsIBLS.STATE_NOT_BLOCKED); + + // blocked - the invalid regexp for the previous item shouldn't affect this one + do_check_true(blocklist.getPluginBlocklistState(PLUGINS[2], "1", "1.9") == nsIBLS.STATE_BLOCKED); + + // not blocked - the previous invalid regexp shouldn't act as a wildcard + do_check_true(blocklist.getPluginBlocklistState(PLUGINS[3], "1", "1.9") == nsIBLS.STATE_NOT_BLOCKED); + +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1.js new file mode 100644 index 000000000..c456506ce --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1.js @@ -0,0 +1,49 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// 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, false); + +var ADDONS = [ + "test_bug470377_1", + "test_bug470377_2", + "test_bug470377_3", + "test_bug470377_4", + "test_bug470377_5", +]; + +Components.utils.import("resource://testing-common/httpd.js"); +var server; + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2"); + + server = new HttpServer(); + server.registerDirectory("/", do_get_file("data/test_bug470377")); + server.start(-1); + + 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_neq(a2, null); + do_check_neq(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_1_strictcompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1_strictcompat.js new file mode 100644 index 000000000..1e542dff8 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1_strictcompat.js @@ -0,0 +1,49 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// 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", +]; + +Components.utils.import("resource://testing-common/httpd.js"); +var server; + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2"); + + server = new HttpServer(); + server.registerDirectory("/", do_get_file("data/test_bug470377")); + server.start(-1); + + 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_2.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_2.js new file mode 100644 index 000000000..15e8d54c4 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_2.js @@ -0,0 +1,49 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// Disables security checking our updates which haven't been signed +Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); + +var ADDONS = [ + "test_bug470377_1", + "test_bug470377_2", + "test_bug470377_3", + "test_bug470377_4", + "test_bug470377_5", +]; + +Components.utils.import("resource://testing-common/httpd.js"); +var server; + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2"); + + server = new HttpServer(); + server.registerDirectory("/", do_get_file("data/test_bug470377")); + server.start(-1); + + startupManager(); + AddonManager.checkCompatibility = false; + + 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_neq(a2, null); + do_check_neq(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 new file mode 100644 index 000000000..fcac471ee --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3.js @@ -0,0 +1,95 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false); + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2.2.3", "2"); + + // 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_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_execute_soon(run_test_2); + }); +} + +function run_test_2() { + AddonManager.checkCompatibility = 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_execute_soon(do_test_finished); + }); +} 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 000000000..7a3347320 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3_strictcompat.js @@ -0,0 +1,94 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +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); + + do_execute_soon(run_test_2); + }); +} + +function run_test_2() { + AddonManager.checkCompatibility = 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_execute_soon(do_test_finished); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_4.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_4.js new file mode 100644 index 000000000..701cbe448 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_4.js @@ -0,0 +1,92 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2.1a4", "2"); + + // inject the add-ons into the profile + var profileDir = gProfD.clone(); + profileDir.append("extensions"); + var dest = profileDir.clone(); + 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 = profileDir.clone(); + 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 = profileDir.clone(); + 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 = profileDir.clone(); + 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 = profileDir.clone(); + 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"); + + run_test_1(); +} + +function run_test_1() { + startupManager(); + AddonManager.checkCompatibility = 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_execute_soon(run_test_2); + }); +} + +function run_test_2() { + AddonManager.checkCompatibility = true; + + 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_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); + + do_execute_soon(do_test_finished); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug514327_1.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug514327_1.js new file mode 100644 index 000000000..c684e0ca2 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug514327_1.js @@ -0,0 +1,59 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const Cc = Components.classes; +const Ci = Components.interfaces; + +const nsIBLS = Ci.nsIBlocklistService; + +var PLUGINS = [{ + // blocklisted - default severity + name: "test_bug514327_1", + version: "5", + disabled: false, + blocklisted: false +}, +{ + // outdated - severity of "0" + name: "test_bug514327_2", + version: "5", + disabled: false, + blocklisted: false +}, +{ + // outdated - severity of "0" + name: "test_bug514327_3", + version: "5", + disabled: false, + blocklisted: false +}, +{ + // not blocklisted, not outdated + name: "test_bug514327_4", + version: "5", + disabled: false, + blocklisted: false, + outdated: false +}]; + + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); + + copyBlocklistToProfile(do_get_file("data/test_bug514327_1.xml")); + + var blocklist = Cc["@mozilla.org/extensions/blocklist;1"].getService(nsIBLS); + + // blocked (sanity check) + do_check_true(blocklist.getPluginBlocklistState(PLUGINS[0], "1", "1.9") == nsIBLS.STATE_BLOCKED); + + // outdated + do_check_true(blocklist.getPluginBlocklistState(PLUGINS[1], "1", "1.9") == nsIBLS.STATE_OUTDATED); + + // outdated + do_check_true(blocklist.getPluginBlocklistState(PLUGINS[2], "1", "1.9") == nsIBLS.STATE_OUTDATED); + + // not blocked + do_check_true(blocklist.getPluginBlocklistState(PLUGINS[3], "1", "1.9") == nsIBLS.STATE_NOT_BLOCKED); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug514327_2.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug514327_2.js new file mode 100644 index 000000000..a8c369f1b --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug514327_2.js @@ -0,0 +1,42 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const Cc = Components.classes; +const Ci = Components.interfaces; + +const nsIBLS = Ci.nsIBlocklistService; + +// Finds the test nsIPluginTag +function get_test_plugintag() { + var host = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost); + var tags = host.getPluginTags(); + for (let tag of tags) { + if (tag.name == "Test Plug-in") + return tag; + } + return null; +} + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); + + copyBlocklistToProfile(do_get_file("data/test_bug514327_2.xml")); + + var blocklist = Cc["@mozilla.org/extensions/blocklist;1"].getService(nsIBLS); + var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch); + + var plugin = get_test_plugintag(); + if (!plugin) + do_throw("Plugin tag not found"); + + //run the code after the blocklist is closed + Services.obs.notifyObservers(null, "addon-blocklist-closed", null); + do_execute_soon(function() { + // should be marked as outdated by the blocklist + do_check_true(blocklist.getPluginBlocklistState(plugin, "1", "1.9") == nsIBLS.STATE_OUTDATED); + + // should indicate that a warning should be shown + do_check_true(prefs.getBoolPref("plugins.update.notifyUser")); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug514327_3.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug514327_3.js new file mode 100644 index 000000000..1267a8772 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug514327_3.js @@ -0,0 +1,166 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; +const Cr = Components.results; + +Cu.import("resource://testing-common/httpd.js"); + +const nsIBLS = Ci.nsIBlocklistService; +const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul"; + +var gBlocklist = null; +var gPrefs = null; +var gTestserver = null; + +var gNextTestPart = null; + + +var PLUGINS = [{ + // Tests a plugin whose state goes from not-blocked, to outdated + name: "test_bug514327_outdated", + version: "5", + disabled: false, + blocklisted: false +}, { + // Used to trigger the blocklist dialog, which indicates the blocklist has updated + name: "test_bug514327_1", + version: "5", + disabled: false, + blocklisted: false +}, { + // Used to trigger the blocklist dialog, which indicates the blocklist has updated + name: "test_bug514327_2", + version: "5", + disabled: false, + blocklisted: false +} ]; + + +// A fake plugin host for the blocklist service to use +var PluginHost = { + getPluginTags: function(countRef) { + countRef.value = PLUGINS.length; + return PLUGINS; + }, + + QueryInterface: function(iid) { + if (iid.equals(Ci.nsIPluginHost) + || iid.equals(Ci.nsISupports)) + return this; + + throw Components.results.NS_ERROR_NO_INTERFACE; + } +} + +var PluginHostFactory = { + createInstance: function (outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return PluginHost.QueryInterface(iid); + } +}; + +// Don't need the full interface, attempts to call other methods will just +// throw which is just fine +var WindowWatcher = { + openWindow: function(parent, url, name, features, arguments) { + // Should be called to list the newly blocklisted items + do_check_eq(url, URI_EXTENSION_BLOCKLIST_DIALOG); + // Should only include one item + do_check_eq(arguments.wrappedJSObject.list.length, 1); + // And that item should be the blocked plugin, not the outdated one + var item = arguments.wrappedJSObject.list[0]; + do_check_true(item.item instanceof Ci.nsIPluginTag); + do_check_neq(item.name, "test_bug514327_outdated"); + + // Call the next test after the blocklist has finished up + do_timeout(0, gNextTestPart); + }, + + QueryInterface: function(iid) { + if (iid.equals(Ci.nsIWindowWatcher) + || iid.equals(Ci.nsISupports)) + return this; + + throw Cr.NS_ERROR_NO_INTERFACE; + } +} + +var WindowWatcherFactory = { + createInstance: function createInstance(outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return WindowWatcher.QueryInterface(iid); + } +}; + +var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{721c3e73-969e-474b-a6dc-059fd288c428}"), + "Fake Plugin Host", + "@mozilla.org/plugin/host;1", PluginHostFactory); +registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"), + "Fake Window Watcher", + "@mozilla.org/embedcomp/window-watcher;1", WindowWatcherFactory); + + +function do_update_blocklist(aDatafile, aNextPart) { + gNextTestPart = aNextPart; + + gPrefs.setCharPref("extensions.blocklist.url", "http://localhost:" + gPort + "/data/" + aDatafile); + gBlocklist.QueryInterface(Ci.nsITimerCallback).notify(null); +} + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); + + gTestserver = new HttpServer(); + gTestserver.registerDirectory("/data/", do_get_file("data")); + gTestserver.start(-1); + gPort = gTestserver.identity.primaryPort; + + startupManager(); + + // initialize the blocklist with no entries + copyBlocklistToProfile(do_get_file("data/test_bug514327_3_empty.xml")); + + gPrefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch); + gBlocklist = Cc["@mozilla.org/extensions/blocklist;1"].getService(nsIBLS); + + // should NOT be marked as outdated by the blocklist + do_check_true(gBlocklist.getPluginBlocklistState(PLUGINS[0], "1", "1.9") == nsIBLS.STATE_NOT_BLOCKED); + + do_test_pending(); + + // update blocklist with data that marks the plugin as outdated + do_update_blocklist("test_bug514327_3_outdated_1.xml", test_part_1); +} + +function test_part_1() { + // plugin should now be marked as outdated + do_check_true(gBlocklist.getPluginBlocklistState(PLUGINS[0], "1", "1.9") == nsIBLS.STATE_OUTDATED); + // and the notifyUser pref should be set to true + do_check_true(gPrefs.getBoolPref("plugins.update.notifyUser")); + + // preternd the user has been notified, reset the pref + gPrefs.setBoolPref("plugins.update.notifyUser", false); + + // update blocklist with data that marks the plugin as outdated + do_update_blocklist("test_bug514327_3_outdated_2.xml", test_part_2); +} + +function test_part_2() { + // plugin should still be marked as outdated + do_check_true(gBlocklist.getPluginBlocklistState(PLUGINS[0], "1", "1.9") == nsIBLS.STATE_OUTDATED); + // and the notifyUser pref should NOT be set to true, as the plugin was already outdated + do_check_false(gPrefs.getBoolPref("plugins.update.notifyUser")); + + finish(); +} + +function finish() { + gTestserver.stop(do_test_finished); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug521905.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug521905.js new file mode 100644 index 000000000..b507fc100 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug521905.js @@ -0,0 +1,59 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +const ADDON = "test_bug521905"; +const ID = "bug521905@tests.mozilla.org"; + +// Disables security checking our updates which haven't been signed +Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); + +function run_test() { + // This test is only relevant on builds where the version is included in the + // checkCompatibility preference name + if (isNightlyChannel()) { + return; + } + + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2.0pre", "2"); + + startupManager(); + AddonManager.checkCompatibility = false; + + installAllFiles([do_get_addon(ADDON)], function() { + restartManager(); + + AddonManager.getAddonByID(ID, function(addon) { + do_check_neq(addon, null); + do_check_true(addon.isActive); + + do_execute_soon(run_test_1); + }); + }); +} + +function run_test_1() { + Services.prefs.setBoolPref("extensions.checkCompatibility.2.0pre", true); + + restartManager(); + AddonManager.getAddonByID(ID, function(addon) { + do_check_neq(addon, null); + do_check_false(addon.isActive); + + do_execute_soon(run_test_2); + }); +} + +function run_test_2() { + Services.prefs.setBoolPref("extensions.checkCompatibility.2.0p", false); + + restartManager(); + AddonManager.getAddonByID(ID, function(addon) { + do_check_neq(addon, null); + do_check_false(addon.isActive); + + do_execute_soon(do_test_finished); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug526598.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug526598.js new file mode 100644 index 000000000..debf59172 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug526598.js @@ -0,0 +1,54 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); + + startupManager(); + + installAllFiles([do_get_file("data/test_bug526598_1.xpi"), + do_get_file("data/test_bug526598_2.xpi")], function() { + + restartManager(); + + AddonManager.getAddonsByIDs(["bug526598_1@tests.mozilla.org", + "bug526598_2@tests.mozilla.org"], + callback_soon(function([a1, a2]) { + + do_check_neq(a1, null); + do_check_true(a1.hasResource("install.rdf")); + let uri = a1.getResourceURI("install.rdf"); + do_check_true(uri instanceof AM_Ci.nsIFileURL); + let file = uri.file; + do_check_true(file.exists()); + do_check_true(file.isReadable()); + do_check_true(file.isWritable()); + + do_check_neq(a2, null); + do_check_true(a2.hasResource("install.rdf")); + uri = a2.getResourceURI("install.rdf"); + do_check_true(uri instanceof AM_Ci.nsIFileURL); + file = uri.file; + do_check_true(file.exists()); + do_check_true(file.isReadable()); + do_check_true(file.isWritable()); + + a1.uninstall(); + a2.uninstall(); + + restartManager(); + + AddonManager.getAddonsByIDs(["bug526598_1@tests.mozilla.org", + "bug526598_2@tests.mozilla.org"], + function([newa1, newa2]) { + do_check_eq(newa1, null); + do_check_eq(newa2, null); + + do_execute_soon(do_test_finished); + }); + })); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug541420.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug541420.js new file mode 100644 index 000000000..1f70b42d5 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug541420.js @@ -0,0 +1,37 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); + + startupManager(); + + installAllFiles([do_get_file("data/test_bug541420.xpi")], function() { + + restartManager(); + + AddonManager.getAddonByID("bug541420@tests.mozilla.org", function(addon) { + + do_check_neq(addon, null); + do_check_true(addon.hasResource("binary")); + let uri = addon.getResourceURI("binary"); + do_check_true(uri instanceof AM_Ci.nsIFileURL); + let file = uri.file; + do_check_true(file.exists()); + do_check_true(file.isReadable()); + do_check_true(file.isWritable()); + + // We don't understand executable permissions on Windows since we don't + // support NTFS permissions so we don't need to test there. OSX's isExecutable + // only tests if the file is an application so it is better to just check the + // raw permission bits + if (!("nsIWindowsRegKey" in Components.interfaces)) + do_check_true((file.permissions & 0100) == 0100); + + do_execute_soon(do_test_finished); + }); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug542391.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug542391.js new file mode 100644 index 000000000..ceb472f98 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug542391.js @@ -0,0 +1,486 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +const URI_EXTENSION_UPDATE_DIALOG = "chrome://mozapps/content/extensions/update.xul"; +const PREF_EM_SHOW_MISMATCH_UI = "extensions.showMismatchUI"; + +// The test extension uses an insecure update url. +Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); + +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; +const Cr = Components.results; + +Cu.import("resource://testing-common/httpd.js"); +var testserver; + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +var gInstallUpdate = false; +var gCheckUpdates = false; + +// This will be called to show the compatibility update dialog. +var WindowWatcher = { + expected: false, + arguments: null, + + openWindow: function(parent, url, name, features, args) { + do_check_true(Services.startup.interrupted); + do_check_eq(url, URI_EXTENSION_UPDATE_DIALOG); + do_check_true(this.expected); + this.expected = false; + this.arguments = args.QueryInterface(AM_Ci.nsIVariant); + + var updated = !gCheckUpdates; + if (gCheckUpdates) { + AddonManager.getAddonByID("override1x2-1x3@tests.mozilla.org", function(a6) { + a6.findUpdates({ + onUpdateFinished: function() { + AddonManagerPrivate.removeStartupChange("disabled", "override1x2-1x3@tests.mozilla.org"); + updated = true; + } + }, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); + }); + } + + var installed = !gInstallUpdate; + if (gInstallUpdate) { + // Simulate installing an update while in the dialog + installAllFiles([do_get_addon("upgradeable1x2-3_2")], function() { + AddonManagerPrivate.removeStartupChange("disabled", "upgradeable1x2-3@tests.mozilla.org"); + AddonManagerPrivate.addStartupChange("updated", "upgradeable1x2-3@tests.mozilla.org"); + installed = true; + }); + } + + // The dialog is meant to be opened modally and the install operation can be + // asynchronous, so we must spin an event loop (like the modal window does) + // until the install is complete + let thr = AM_Cc["@mozilla.org/thread-manager;1"]. + getService(AM_Ci.nsIThreadManager). + mainThread; + + while (!installed || !updated) + thr.processNextEvent(false); + }, + + QueryInterface: function(iid) { + if (iid.equals(Ci.nsIWindowWatcher) + || iid.equals(Ci.nsISupports)) + return this; + + throw Cr.NS_ERROR_NO_INTERFACE; + } +} + +var WindowWatcherFactory = { + createInstance: function createInstance(outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return WindowWatcher.QueryInterface(iid); + } +}; + +var registrar = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"), + "Fake Window Watcher", + "@mozilla.org/embedcomp/window-watcher;1", WindowWatcherFactory); + +function check_state_v1([a1, a2, a3, a4, a5, a6]) { + do_check_neq(a1, null); + do_check_false(a1.appDisabled); + do_check_false(a1.userDisabled); + do_check_true(a1.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); + + do_check_neq(a2, null); + do_check_false(a2.appDisabled); + do_check_true(a2.userDisabled); + do_check_false(a2.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a2.id)); + + do_check_neq(a3, null); + do_check_false(a3.appDisabled); + do_check_false(a3.userDisabled); + do_check_true(a3.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a3.id)); + do_check_eq(a3.version, "1.0"); + + do_check_neq(a4, null); + do_check_false(a4.appDisabled); + do_check_true(a4.userDisabled); + do_check_false(a4.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a4.id)); + + do_check_neq(a5, null); + do_check_false(a5.appDisabled); + do_check_false(a5.userDisabled); + do_check_true(a5.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a5.id)); + + do_check_neq(a6, null); + do_check_false(a6.appDisabled); + do_check_false(a6.userDisabled); + do_check_true(a6.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a6.id)); +} + +function check_state_v1_2([a1, a2, a3, a4, a5, a6]) { + do_check_neq(a1, null); + do_check_false(a1.appDisabled); + do_check_false(a1.userDisabled); + do_check_true(a1.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); + + do_check_neq(a2, null); + do_check_false(a2.appDisabled); + do_check_true(a2.userDisabled); + do_check_false(a2.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a2.id)); + + do_check_neq(a3, null); + do_check_true(a3.appDisabled); + do_check_false(a3.userDisabled); + do_check_false(a3.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a3.id)); + do_check_eq(a3.version, "2.0"); + + do_check_neq(a4, null); + do_check_false(a4.appDisabled); + do_check_true(a4.userDisabled); + do_check_false(a4.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a4.id)); + + do_check_neq(a5, null); + do_check_false(a5.appDisabled); + do_check_false(a5.userDisabled); + do_check_true(a5.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a5.id)); + + do_check_neq(a6, null); + do_check_false(a6.appDisabled); + do_check_false(a6.userDisabled); + do_check_true(a6.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a6.id)); +} + +function check_state_v2([a1, a2, a3, a4, a5, a6]) { + do_check_neq(a1, null); + do_check_true(a1.appDisabled); + do_check_false(a1.userDisabled); + do_check_false(a1.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a1.id)); + + do_check_neq(a2, null); + do_check_false(a2.appDisabled); + do_check_true(a2.userDisabled); + do_check_false(a2.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a2.id)); + + do_check_neq(a3, null); + do_check_false(a3.appDisabled); + do_check_false(a3.userDisabled); + do_check_true(a3.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a3.id)); + do_check_eq(a3.version, "1.0"); + + do_check_neq(a4, null); + do_check_false(a4.appDisabled); + do_check_true(a4.userDisabled); + do_check_false(a4.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a4.id)); + + do_check_neq(a5, null); + do_check_false(a5.appDisabled); + do_check_false(a5.userDisabled); + do_check_true(a5.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a5.id)); + + do_check_neq(a6, null); + do_check_false(a6.appDisabled); + do_check_false(a6.userDisabled); + do_check_true(a6.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a6.id)); +} + +function check_state_v3([a1, a2, a3, a4, a5, a6]) { + do_check_neq(a1, null); + do_check_true(a1.appDisabled); + do_check_false(a1.userDisabled); + do_check_false(a1.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a1.id)); + + do_check_neq(a2, null); + do_check_true(a2.appDisabled); + do_check_true(a2.userDisabled); + do_check_false(a2.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a2.id)); + + do_check_neq(a3, null); + do_check_true(a3.appDisabled); + do_check_false(a3.userDisabled); + do_check_false(a3.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a3.id)); + do_check_eq(a3.version, "1.0"); + + do_check_neq(a4, null); + do_check_false(a4.appDisabled); + do_check_true(a4.userDisabled); + do_check_false(a4.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a4.id)); + + do_check_neq(a5, null); + do_check_false(a5.appDisabled); + do_check_false(a5.userDisabled); + do_check_true(a5.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a5.id)); + + do_check_neq(a6, null); + do_check_false(a6.appDisabled); + do_check_false(a6.userDisabled); + do_check_true(a6.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a6.id)); +} + +function check_state_v3_2([a1, a2, a3, a4, a5, a6]) { + do_check_neq(a1, null); + do_check_true(a1.appDisabled); + do_check_false(a1.userDisabled); + do_check_false(a1.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a1.id)); + + do_check_neq(a2, null); + do_check_true(a2.appDisabled); + do_check_true(a2.userDisabled); + do_check_false(a2.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a2.id)); + + do_check_neq(a3, null); + do_check_false(a3.appDisabled); + do_check_false(a3.userDisabled); + do_check_true(a3.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a3.id)); + do_check_eq(a3.version, "2.0"); + + do_check_neq(a4, null); + do_check_false(a4.appDisabled); + do_check_true(a4.userDisabled); + do_check_false(a4.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a4.id)); + + do_check_neq(a5, null); + do_check_false(a5.appDisabled); + do_check_false(a5.userDisabled); + do_check_true(a5.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a5.id)); + + do_check_neq(a6, null); + do_check_false(a6.appDisabled); + do_check_false(a6.userDisabled); + do_check_true(a6.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a6.id)); +} + +// Install all the test add-ons, disable two of them and "upgrade" the app to +// version 2 which will appDisable one. +add_task(function* init() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); + + Services.prefs.setBoolPref(PREF_EM_SHOW_MISMATCH_UI, true); + + // Add an extension to the profile to make sure the dialog doesn't show up + // on new profiles + var dest = writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 1", + }, profileDir); + + // Create and configure the HTTP server. + testserver = new HttpServer(); + testserver.registerDirectory("/data/", do_get_file("data")); + testserver.registerDirectory("/addons/", do_get_file("addons")); + testserver.start(4444); + + startupManager(); + + // Remove the add-on we installed directly in the profile directory; + // this should show as uninstalled on next restart + dest.remove(true); + + // Load up an initial set of add-ons + yield promiseInstallAllFiles([do_get_addon("min1max1"), + do_get_addon("min1max2"), + do_get_addon("upgradeable1x2-3_1"), + do_get_addon("min1max3"), + do_get_addon("min1max3b"), + do_get_addon("override1x2-1x3")]); + yield promiseRestartManager(); + + check_startup_changes("installed", []); + check_startup_changes("updated", []); + check_startup_changes("uninstalled", ["addon1@tests.mozilla.org"]); + check_startup_changes("disabled", []); + check_startup_changes("enabled", []); + + // user-disable two add-ons + let [a2, a4] = yield promiseAddonsByIDs(["min1max2@tests.mozilla.org", + "min1max3@tests.mozilla.org"]); + do_check_true(a2 != null && a4 != null); + a2.userDisabled = true; + a4.userDisabled = true; + yield promiseRestartManager(); + check_startup_changes("installed", []); + check_startup_changes("updated", []); + check_startup_changes("uninstalled", []); + check_startup_changes("disabled", []); + check_startup_changes("enabled", []); + + let addons = yield promiseAddonsByIDs(["min1max1@tests.mozilla.org", + "min1max2@tests.mozilla.org", + "upgradeable1x2-3@tests.mozilla.org", + "min1max3@tests.mozilla.org", + "min1max3b@tests.mozilla.org", + "override1x2-1x3@tests.mozilla.org"]); + check_state_v1(addons); + + // Restart as version 2, add-on _1 should become app-disabled + WindowWatcher.expected = true; + yield promiseRestartManager("2"); + check_startup_changes("installed", []); + check_startup_changes("updated", []); + check_startup_changes("uninstalled", []); + check_startup_changes("disabled", ["min1max1@tests.mozilla.org"]); + check_startup_changes("enabled", []); + do_check_false(WindowWatcher.expected); + + addons = yield promiseAddonsByIDs(["min1max1@tests.mozilla.org", + "min1max2@tests.mozilla.org", + "upgradeable1x2-3@tests.mozilla.org", + "min1max3@tests.mozilla.org", + "min1max3b@tests.mozilla.org", + "override1x2-1x3@tests.mozilla.org"]); + check_state_v2(addons); +}); + +// Upgrade to version 3 which will appDisable addons +// upgradeable1x2-3 and override1x2-1x3 +// Only the newly disabled add-ons should be passed to the +// upgrade window +add_task(function* run_test_1() { + gCheckUpdates = true; + WindowWatcher.expected = true; + + yield promiseRestartManager("3"); + check_startup_changes("installed", []); + check_startup_changes("updated", []); + check_startup_changes("uninstalled", []); + check_startup_changes("disabled", ["upgradeable1x2-3@tests.mozilla.org"]); + check_startup_changes("enabled", []); + do_check_false(WindowWatcher.expected); + gCheckUpdates = false; + + let addons = yield promiseAddonsByIDs(["min1max1@tests.mozilla.org", + "min1max2@tests.mozilla.org", + "upgradeable1x2-3@tests.mozilla.org", + "min1max3@tests.mozilla.org", + "min1max3b@tests.mozilla.org", + "override1x2-1x3@tests.mozilla.org"]); + check_state_v3(addons); + + do_check_eq(WindowWatcher.arguments.length, 2); + do_check_true(WindowWatcher.arguments.indexOf("upgradeable1x2-3@tests.mozilla.org") >= 0); + do_check_true(WindowWatcher.arguments.indexOf("override1x2-1x3@tests.mozilla.org") >= 0); +}); + +// Downgrade to version 2 which will remove appDisable from two add-ons +// Still displays the compat window, because metadata is not recently updated +add_task(function* run_test_2() { + WindowWatcher.expected = true; + yield promiseRestartManager("2"); + check_startup_changes("installed", []); + check_startup_changes("updated", []); + check_startup_changes("uninstalled", []); + check_startup_changes("disabled", []); + check_startup_changes("enabled", ["upgradeable1x2-3@tests.mozilla.org"]); + do_check_false(WindowWatcher.expected); + + let addons = yield promiseAddonsByIDs(["min1max1@tests.mozilla.org", + "min1max2@tests.mozilla.org", + "upgradeable1x2-3@tests.mozilla.org", + "min1max3@tests.mozilla.org", + "min1max3b@tests.mozilla.org", + "override1x2-1x3@tests.mozilla.org"]); + check_state_v2(addons); +}); + +// Upgrade back to version 3 which should only appDisable +// upgradeable1x2-3, because we already have the override +// stored in our DB for override1x2-1x3. Ensure that when +// the upgrade dialog updates an add-on no restart is necessary +add_task(function* run_test_5() { + Services.prefs.setBoolPref(PREF_EM_SHOW_MISMATCH_UI, true); + // tell the mock compatibility window to install the available upgrade + gInstallUpdate = true; + + WindowWatcher.expected = true; + yield promiseRestartManager("3"); + check_startup_changes("installed", []); + check_startup_changes("updated", ["upgradeable1x2-3@tests.mozilla.org"]); + check_startup_changes("uninstalled", []); + check_startup_changes("disabled", []); + check_startup_changes("enabled", []); + do_check_false(WindowWatcher.expected); + gInstallUpdate = false; + + let addons = yield promiseAddonsByIDs(["min1max1@tests.mozilla.org", + "min1max2@tests.mozilla.org", + "upgradeable1x2-3@tests.mozilla.org", + "min1max3@tests.mozilla.org", + "min1max3b@tests.mozilla.org", + "override1x2-1x3@tests.mozilla.org"]); + check_state_v3_2(addons); + + do_check_eq(WindowWatcher.arguments.length, 1); + do_check_true(WindowWatcher.arguments.indexOf("upgradeable1x2-3@tests.mozilla.org") >= 0); +}); + +// Downgrade to version 1 which will appEnable all the add-ons +// except upgradeable1x2-3; the update we installed isn't compatible with 1 +add_task(function* run_test_6() { + WindowWatcher.expected = true; + yield promiseRestartManager("1"); + check_startup_changes("installed", []); + check_startup_changes("updated", []); + check_startup_changes("uninstalled", []); + check_startup_changes("disabled", ["upgradeable1x2-3@tests.mozilla.org"]); + check_startup_changes("enabled", ["min1max1@tests.mozilla.org"]); + do_check_false(WindowWatcher.expected); + + let addons = yield promiseAddonsByIDs(["min1max1@tests.mozilla.org", + "min1max2@tests.mozilla.org", + "upgradeable1x2-3@tests.mozilla.org", + "min1max3@tests.mozilla.org", + "min1max3b@tests.mozilla.org", + "override1x2-1x3@tests.mozilla.org"]); + check_state_v1_2(addons); +}); + +add_task(function* cleanup() { + return new Promise((resolve, reject) => { + testserver.stop(resolve); + }); +}); + +function run_test() { + run_next_test(); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug554133.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug554133.js new file mode 100644 index 000000000..c252e1ced --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug554133.js @@ -0,0 +1,86 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that if the AMO response provides total_results, +// searchSucceeded is called with the correct number of total results + +Components.utils.import("resource://gre/modules/addons/AddonRepository.jsm"); + +const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url"; + +Components.utils.import("resource://testing-common/httpd.js"); +var server; + +var TESTS = [ +{ + query: "bug554133", + maxResults: 2, + length: 2, + total: 100 +}, +{ + query: "bug554133", + maxResults: 10, + length: 10, + total: 100 +}, +{ + query: "bug554133", + maxResults: 100, + length: 10, + total: 100 +} +]; + +var gCurrentTest = 0; +var SearchCallback = { + searchSucceeded: function(addons, length, total) { + do_check_false(AddonRepository.isSearching); + do_check_eq(addons.length, length); + do_check_eq(length, TESTS[gCurrentTest].length); + do_check_eq(total, TESTS[gCurrentTest].total); + + gCurrentTest++; + run_current_test(); + }, + + searchFailed: function() { + server.stop(do_test_finished); + do_throw("Search results failed"); + } +}; + +function run_current_test() { + if (gCurrentTest < TESTS.length) { + var query = TESTS[gCurrentTest].query; + var maxResults = TESTS[gCurrentTest].maxResults; + AddonRepository.searchAddons(query, maxResults, SearchCallback); + } + else + server.stop(do_test_finished); +} + +function run_test() +{ + // Setup for test + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); + + startupManager(); + + server = new HttpServer(); + server.registerDirectory("/", do_get_file("data")); + mapFile("/data/test_bug554133.xml", server); + server.start(-1); + gPort = server.identity.primaryPort; + + // Point search to the test server + Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, + "http://localhost:" + gPort + "/data/test_%TERMS%.xml"); + + do_check_neq(AddonRepository, null); + gCurrentTest = 0; + run_current_test(); +} + diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug559800.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug559800.js new file mode 100644 index 000000000..41057cd76 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug559800.js @@ -0,0 +1,71 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that deleting the database from the profile doesn't break +// anything + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +// getting an unused port +Components.utils.import("resource://testing-common/httpd.js"); +let gServer = new HttpServer(); +gServer.start(-1); +gPort = gServer.identity.primaryPort; + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 1", + }, profileDir); + + startupManager(); + + do_test_pending(); + + run_test_1(); +} + +function end_test() { + gServer.stop(do_test_finished); +} + +function run_test_1() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "1.0"); + + shutdownManager(); + + gExtensionsJSON.remove(true); + + do_execute_soon(check_test_1); + })); +} + +function check_test_1() { + startupManager(false); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "1.0"); + + // due to delayed write, the file may not exist until + // after shutdown + shutdownManager(); + do_check_true(gExtensionsJSON.exists()); + do_check_true(gExtensionsJSON.fileSize > 0); + + end_test(); + })); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug563256.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug563256.js new file mode 100644 index 000000000..2437cf748 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug563256.js @@ -0,0 +1,259 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that the themes switch as expected + +const PREF_GENERAL_SKINS_SELECTEDSKIN = "general.skins.selectedSkin"; + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + writeInstallRDFForExtension({ + id: "default@tests.mozilla.org", + version: "1.0", + name: "Default", + internalName: "classic/1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }] + }, profileDir); + + writeInstallRDFForExtension({ + id: "alternate@tests.mozilla.org", + version: "1.0", + name: "Test 1", + type: 4, + internalName: "alternate/1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }] + }, profileDir); + + startupManager(); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); + + AddonManager.getAddonsByIDs(["default@tests.mozilla.org", + "alternate@tests.mozilla.org"], function([d, a]) { + do_check_neq(d, null); + do_check_false(d.userDisabled); + do_check_false(d.appDisabled); + do_check_true(d.isActive); + do_check_true(isThemeInAddonsList(profileDir, d.id)); + do_check_false(hasFlag(d.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_false(hasFlag(d.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_check_neq(a, null); + do_check_true(a.userDisabled); + do_check_false(a.appDisabled); + do_check_false(a.isActive); + do_check_false(isThemeInAddonsList(profileDir, a.id)); + do_check_false(hasFlag(a.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_true(hasFlag(a.permissions, AddonManager.PERM_CAN_ENABLE)); + + run_test_1(d, a); + }); +} + +function end_test() { + do_execute_soon(do_test_finished); +} + +// Checks switching to a different theme and back again leaves everything the +// same +function run_test_1(d, a) { + a.userDisabled = false; + + do_check_true(d.userDisabled); + do_check_false(d.appDisabled); + do_check_true(d.isActive); + do_check_true(isThemeInAddonsList(profileDir, d.id)); + do_check_false(hasFlag(d.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_true(hasFlag(d.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_check_false(a.userDisabled); + do_check_false(a.appDisabled); + do_check_false(a.isActive); + do_check_false(isThemeInAddonsList(profileDir, a.id)); + do_check_false(hasFlag(a.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_false(hasFlag(a.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); + + d.userDisabled = false; + + do_check_false(d.userDisabled); + do_check_false(d.appDisabled); + do_check_true(d.isActive); + do_check_true(isThemeInAddonsList(profileDir, d.id)); + do_check_false(hasFlag(d.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_false(hasFlag(d.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_check_true(a.userDisabled); + do_check_false(a.appDisabled); + do_check_false(a.isActive); + do_check_false(isThemeInAddonsList(profileDir, a.id)); + do_check_false(hasFlag(a.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_true(hasFlag(a.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); + + do_execute_soon(run_test_2); +} + +// Tests that after the restart themes can be changed as expected +function run_test_2() { + restartManager(); + AddonManager.getAddonsByIDs(["default@tests.mozilla.org", + "alternate@tests.mozilla.org"], function([d, a]) { + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); + + do_check_neq(d, null); + do_check_false(d.userDisabled); + do_check_false(d.appDisabled); + do_check_true(d.isActive); + do_check_true(isThemeInAddonsList(profileDir, d.id)); + do_check_false(hasFlag(d.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_false(hasFlag(d.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_check_neq(a, null); + do_check_true(a.userDisabled); + do_check_false(a.appDisabled); + do_check_false(a.isActive); + do_check_false(isThemeInAddonsList(profileDir, a.id)); + do_check_false(hasFlag(a.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_true(hasFlag(a.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); + + a.userDisabled = false; + + do_check_true(d.userDisabled); + do_check_false(d.appDisabled); + do_check_true(d.isActive); + do_check_true(isThemeInAddonsList(profileDir, d.id)); + do_check_false(hasFlag(d.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_true(hasFlag(d.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_check_false(a.userDisabled); + do_check_false(a.appDisabled); + do_check_false(a.isActive); + do_check_false(isThemeInAddonsList(profileDir, a.id)); + do_check_false(hasFlag(a.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_false(hasFlag(a.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); + + d.userDisabled = false; + + do_check_false(d.userDisabled); + do_check_false(d.appDisabled); + do_check_true(d.isActive); + do_check_true(isThemeInAddonsList(profileDir, d.id)); + do_check_false(hasFlag(d.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_false(hasFlag(d.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_check_true(a.userDisabled); + do_check_false(a.appDisabled); + do_check_false(a.isActive); + do_check_false(isThemeInAddonsList(profileDir, a.id)); + do_check_false(hasFlag(a.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_true(hasFlag(a.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); + + a.userDisabled = false; + + do_check_true(d.userDisabled); + do_check_false(d.appDisabled); + do_check_true(d.isActive); + do_check_true(isThemeInAddonsList(profileDir, d.id)); + do_check_false(hasFlag(d.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_true(hasFlag(d.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_check_false(a.userDisabled); + do_check_false(a.appDisabled); + do_check_false(a.isActive); + do_check_false(isThemeInAddonsList(profileDir, a.id)); + do_check_false(hasFlag(a.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_false(hasFlag(a.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); + + do_execute_soon(check_test_2); + }); +} + +function check_test_2() { + restartManager(); + AddonManager.getAddonsByIDs(["default@tests.mozilla.org", + "alternate@tests.mozilla.org"], callback_soon(function([d, a]) { + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "alternate/1.0"); + + do_check_true(d.userDisabled); + do_check_false(d.appDisabled); + do_check_false(d.isActive); + do_check_false(isThemeInAddonsList(profileDir, d.id)); + do_check_false(hasFlag(d.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_true(hasFlag(d.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_check_false(a.userDisabled); + do_check_false(a.appDisabled); + do_check_true(a.isActive); + do_check_true(isThemeInAddonsList(profileDir, a.id)); + do_check_false(hasFlag(a.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_false(hasFlag(a.permissions, AddonManager.PERM_CAN_ENABLE)); + + d.userDisabled = false; + + do_check_false(d.userDisabled); + do_check_false(d.appDisabled); + do_check_false(d.isActive); + do_check_false(isThemeInAddonsList(profileDir, d.id)); + do_check_false(hasFlag(d.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_false(hasFlag(d.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_check_true(a.userDisabled); + do_check_false(a.appDisabled); + do_check_true(a.isActive); + do_check_true(isThemeInAddonsList(profileDir, a.id)); + do_check_false(hasFlag(a.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_true(hasFlag(a.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "alternate/1.0"); + + restartManager(); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); + + AddonManager.getAddonsByIDs(["default@tests.mozilla.org", + "alternate@tests.mozilla.org"], function([d, a]) { + do_check_neq(d, null); + do_check_false(d.userDisabled); + do_check_false(d.appDisabled); + do_check_true(d.isActive); + do_check_true(isThemeInAddonsList(profileDir, d.id)); + do_check_false(hasFlag(d.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_false(hasFlag(d.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_check_neq(a, null); + do_check_true(a.userDisabled); + do_check_false(a.appDisabled); + do_check_false(a.isActive); + do_check_false(isThemeInAddonsList(profileDir, a.id)); + do_check_false(hasFlag(a.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_true(hasFlag(a.permissions, AddonManager.PERM_CAN_ENABLE)); + + end_test(); + }); + })); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug564030.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug564030.js new file mode 100644 index 000000000..b5ac157c7 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug564030.js @@ -0,0 +1,63 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that upgrading an incompatible add-on to a compatible one forces an +// EM restart + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "1.9.2"); + + var dest = writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] + }, profileDir); + // Attempt to make this look like it was added some time in the past so + // the update makes the last modified time change. + setExtensionModifiedTime(dest, dest.lastModifiedTime - 5000); + + startupManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a) { + do_check_neq(a, null); + do_check_eq(a.version, "1.0"); + do_check_false(a.userDisabled); + do_check_true(a.appDisabled); + do_check_false(a.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a.id)); + + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "2.0", + name: "Test", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }] + }, profileDir); + + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a) { + do_check_neq(a, null); + do_check_eq(a.version, "2.0"); + do_check_false(a.userDisabled); + do_check_false(a.appDisabled); + do_check_true(a.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a.id)); + + do_execute_soon(do_test_finished); + }); + })); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug566626.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug566626.js new file mode 100644 index 000000000..641ff87c9 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug566626.js @@ -0,0 +1,112 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that multiple calls to the async API return fully formed +// add-ons + +var addon1 = { + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +var gAddon; + +// Sets up the profile by installing an add-on. +function run_test() { + do_test_pending(); + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + writeInstallRDFForExtension(addon1, profileDir); + + startupManager(); + + run_test_1(); +} + +// Verifies that multiple calls to get an add-on at various stages of execution +// return an add-on with a valid name. +function run_test_1() { + var count = 0; + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.name, "Test 1"); + + if (count == 0) + gAddon = a1; + else + do_check_eq(a1, gAddon); + count++; + if (count == 4) + run_test_2(); + }); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.name, "Test 1"); + + if (count == 0) + gAddon = a1; + else + do_check_eq(a1, gAddon); + count++; + if (count == 4) + run_test_2(); + }); + + do_execute_soon(function() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.name, "Test 1"); + + if (count == 0) + gAddon = a1; + else + do_check_eq(a1, gAddon); + count++; + if (count == 4) + run_test_2(); + }); + }); + + do_execute_soon(function() { + do_execute_soon(function() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.name, "Test 1"); + + if (count == 0) + gAddon = a1; + else + do_check_eq(a1, gAddon); + count++; + if (count == 4) + run_test_2(); + }); + }); + }); +} + +// Verifies that a subsequent call gets the same add-on from the cache +function run_test_2() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.name, "Test 1"); + + do_check_eq(a1, gAddon); + + do_execute_soon(do_test_finished); + }); + +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug567184.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug567184.js new file mode 100644 index 000000000..0e7863068 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug567184.js @@ -0,0 +1,53 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + startupManager(); + + run_test_1(); +} + +// Tests that installing doesn't require a restart +function run_test_1() { + prepare_test({ }, [ + "onNewInstall" + ]); + + AddonManager.getInstallForFile(do_get_addon("test_bug567184"), function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + + prepare_test({ + "bug567184@tests.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], check_test_1); + install.install(); + }); +} + +function check_test_1() { + AddonManager.getAllInstalls(function(installs) { + // There should be no active installs now since the install completed and + // doesn't require a restart. + do_check_eq(installs.length, 0); + + AddonManager.getAddonByID("bug567184@tests.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_true(b1.appDisabled); + do_check_false(b1.userDisabled); + do_check_false(b1.isActive); + + do_execute_soon(do_test_finished); + }); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug569138.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug569138.js new file mode 100644 index 000000000..4869fc117 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug569138.js @@ -0,0 +1,147 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that add-ons with invalid target application entries show +// up in the API but are correctly appDisabled + +// A working add-on +var addon1 = { + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Missing id +var addon2 = { + id: "addon2@tests.mozilla.org", + version: "1.0", + name: "Test 2", + targetApplications: [{ + minVersion: "1", + maxVersion: "2" + }] +}; + +// Missing minVersion +var addon3 = { + id: "addon3@tests.mozilla.org", + version: "1.0", + name: "Test 3", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + maxVersion: "1" + }] +}; + +// Missing maxVersion +var addon4 = { + id: "addon4@tests.mozilla.org", + version: "1.0", + name: "Test 4", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1" + }] +}; + +// Blank id +var addon5 = { + id: "addon5@tests.mozilla.org", + version: "1.0", + name: "Test 5", + targetApplications: [{ + id: "", + minVersion: "1", + maxVersion: "2" + }] +}; + +// Blank minVersion +var addon6 = { + id: "addon6@tests.mozilla.org", + version: "1.0", + name: "Test 6", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "", + maxVersion: "1" + }] +}; + +// Blank maxVersion +var addon7 = { + id: "addon7@tests.mozilla.org", + version: "1.0", + name: "Test 7", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "" + }] +}; + +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +// Set up the profile +function run_test() { + do_test_pending(); + + writeInstallRDFForExtension(addon1, profileDir); + writeInstallRDFForExtension(addon2, profileDir); + writeInstallRDFForExtension(addon3, profileDir); + writeInstallRDFForExtension(addon4, profileDir); + writeInstallRDFForExtension(addon5, profileDir); + writeInstallRDFForExtension(addon6, profileDir); + writeInstallRDFForExtension(addon7, profileDir); + + startupManager(); + + 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"], + function([a1, a2, a3, a4, a5, a6, a7]) { + do_check_neq(a1, null); + do_check_false(a1.appDisabled); + do_check_true(a1.isActive); + + do_check_neq(a2, null); + do_check_true(a2.appDisabled); + do_check_false(a2.isActive); + + do_check_neq(a3, null); + do_check_true(a3.appDisabled); + do_check_false(a3.isActive); + + do_check_neq(a4, null); + do_check_true(a4.appDisabled); + do_check_false(a4.isActive); + + do_check_neq(a5, null); + do_check_true(a5.appDisabled); + do_check_false(a5.isActive); + + do_check_neq(a6, null); + do_check_true(a6.appDisabled); + do_check_false(a6.isActive); + + do_check_neq(a6, null); + do_check_true(a6.appDisabled); + do_check_false(a6.isActive); + + do_execute_soon(do_test_finished); + + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug570173.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug570173.js new file mode 100644 index 000000000..70de3b426 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug570173.js @@ -0,0 +1,80 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that add-on update check failures are propogated correctly + +// The test extension uses an insecure update url. +Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); + +Components.utils.import("resource://testing-common/httpd.js"); +var testserver; +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + // Create and configure the HTTP server. + testserver = new HttpServer(); + testserver.registerDirectory("/data/", do_get_file("data")); + testserver.registerDirectory("/addons/", do_get_file("addons")); + testserver.start(-1); + gPort = testserver.identity.primaryPort; + + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_missing.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 1", + }, profileDir); + + startupManager(); + + do_test_pending(); + run_test_1(); +} + +function end_test() { + testserver.stop(do_test_finished); +} + +// Verify that an update check returns the correct errors. +function run_test_1() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "1.0"); + + let sawCompat = false; + let sawUpdate = false; + a1.findUpdates({ + onNoCompatibilityUpdateAvailable: function(addon) { + sawCompat = true; + }, + + onCompatibilityUpdateAvailable: function(addon) { + do_throw("Should not have seen a compatibility update"); + }, + + onNoUpdateAvailable: function(addon) { + sawUpdate = true; + }, + + onUpdateAvailable: function(addon, install) { + do_throw("Should not have seen an update"); + }, + + onUpdateFinished: function(addon, error) { + do_check_true(sawCompat); + do_check_true(sawUpdate); + do_check_eq(error, AddonManager.UPDATE_STATUS_DOWNLOAD_ERROR); + end_test(); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug576735.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug576735.js new file mode 100644 index 000000000..007e82706 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug576735.js @@ -0,0 +1,66 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that we recover gracefully from an extension directory disappearing +// when we were expecting to uninstall it. + +var addon1 = { + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +var addon2 = { + id: "addon2@tests.mozilla.org", + version: "2.0", + name: "Test 2", + targetApplications: [{ + id: "toolkit@mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "2"); + + writeInstallRDFForExtension(addon1, profileDir); + + startupManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { + a1.uninstall(); + + shutdownManager(); + + var dest = profileDir.clone(); + dest.append(do_get_expected_addon_name("addon1@tests.mozilla.org")); + dest.remove(true); + + writeInstallRDFForExtension(addon2, profileDir); + + startupManager(); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org"], + function([a1, a2]) { + // Addon1 should no longer be installed + do_check_eq(a1, null); + + // Addon2 should have been detected + do_check_neq(a2, null); + + do_execute_soon(do_test_finished); + }); + })); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug587088.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug587088.js new file mode 100644 index 000000000..01de80634 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug587088.js @@ -0,0 +1,174 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that trying to upgrade or uninstall an extension that has a file locked +// will roll back the upgrade or uninstall and retry at the next restart + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +function run_test() { + // This is only an issue on windows. + if (!("nsIWindowsRegKey" in AM_Ci)) + return; + + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + startupManager(); + run_test_1(); +} + +function check_addon(aAddon, aVersion) { + do_check_neq(aAddon, null); + do_check_eq(aAddon.version, aVersion); + do_check_true(aAddon.isActive); + do_check_true(isExtensionInAddonsList(profileDir, aAddon.id)); + + do_check_true(aAddon.hasResource("testfile")); + if (aVersion == "1.0") { + do_check_true(aAddon.hasResource("testfile1")); + do_check_false(aAddon.hasResource("testfile2")); + } + else { + do_check_false(aAddon.hasResource("testfile1")); + do_check_true(aAddon.hasResource("testfile2")); + } + + do_check_eq(aAddon.pendingOperations, AddonManager.PENDING_NONE); +} + +function check_addon_upgrading(aAddon) { + do_check_neq(aAddon, null); + do_check_eq(aAddon.version, "1.0"); + do_check_true(aAddon.isActive); + do_check_true(isExtensionInAddonsList(profileDir, aAddon.id)); + + do_check_true(aAddon.hasResource("testfile")); + do_check_true(aAddon.hasResource("testfile1")); + do_check_false(aAddon.hasResource("testfile2")); + + do_check_eq(aAddon.pendingOperations, AddonManager.PENDING_UPGRADE); + + do_check_eq(aAddon.pendingUpgrade.version, "2.0"); +} + +function check_addon_uninstalling(aAddon, aAfterRestart) { + do_check_neq(aAddon, null); + do_check_eq(aAddon.version, "1.0"); + + if (aAfterRestart) { + do_check_false(aAddon.isActive); + do_check_false(isExtensionInAddonsList(profileDir, aAddon.id)); + } + else { + do_check_true(aAddon.isActive); + do_check_true(isExtensionInAddonsList(profileDir, aAddon.id)); + } + + do_check_true(aAddon.hasResource("testfile")); + do_check_true(aAddon.hasResource("testfile1")); + do_check_false(aAddon.hasResource("testfile2")); + + do_check_eq(aAddon.pendingOperations, AddonManager.PENDING_UNINSTALL); +} + +function run_test_1() { + installAllFiles([do_get_addon("test_bug587088_1")], function() { + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + check_addon(a1, "1.0"); + + // Lock either install.rdf for unpacked add-ons or the xpi for packed add-ons. + let uri = a1.getResourceURI("install.rdf"); + if (uri.schemeIs("jar")) + uri = a1.getResourceURI(); + + let fstream = AM_Cc["@mozilla.org/network/file-input-stream;1"]. + createInstance(AM_Ci.nsIFileInputStream); + fstream.init(uri.QueryInterface(AM_Ci.nsIFileURL).file, -1, 0, 0); + + installAllFiles([do_get_addon("test_bug587088_2")], function() { + + check_addon_upgrading(a1); + + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { + check_addon_upgrading(a1); + + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { + check_addon_upgrading(a1); + + fstream.close(); + + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + check_addon(a1, "2.0"); + + a1.uninstall(); + do_execute_soon(run_test_2); + }); + })); + })); + }); + }); + }); +} + +// Test that a failed uninstall gets rolled back +function run_test_2() { + restartManager(); + + installAllFiles([do_get_addon("test_bug587088_1")], function() { + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { + check_addon(a1, "1.0"); + + // Lock either install.rdf for unpacked add-ons or the xpi for packed add-ons. + let uri = a1.getResourceURI("install.rdf"); + if (uri.schemeIs("jar")) + uri = a1.getResourceURI(); + + let fstream = AM_Cc["@mozilla.org/network/file-input-stream;1"]. + createInstance(AM_Ci.nsIFileInputStream); + fstream.init(uri.QueryInterface(AM_Ci.nsIFileURL).file, -1, 0, 0); + + a1.uninstall(); + + check_addon_uninstalling(a1); + + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { + check_addon_uninstalling(a1, true); + + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { + check_addon_uninstalling(a1, true); + + fstream.close(); + + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_eq(a1, null); + var dir = profileDir.clone(); + dir.append(do_get_expected_addon_name("addon1@tests.mozilla.org")); + do_check_false(dir.exists()); + do_check_false(isExtensionInAddonsList(profileDir, "addon1@tests.mozilla.org")); + + do_execute_soon(do_test_finished); + }); + })); + })); + })); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug594058.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug594058.js new file mode 100644 index 000000000..9bbda59a8 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug594058.js @@ -0,0 +1,97 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This tests is modifying a file in an unpacked extension +// causes cache invalidation. + +// Disables security checking our updates which haven't been signed +Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); +// Allow the mismatch UI to show +Services.prefs.setBoolPref("extensions.showMismatchUI", true); + +const Ci = Components.interfaces; +const extDir = gProfD.clone(); +extDir.append("extensions"); + +var gCachePurged = false; + +// Override the window watcher +var WindowWatcher = { + openWindow: function(parent, url, name, features, arguments) { + do_check_false(gCachePurged); + }, + + QueryInterface: function(iid) { + if (iid.equals(Ci.nsIWindowWatcher) + || iid.equals(Ci.nsISupports)) + return this; + + throw Components.results.NS_ERROR_NO_INTERFACE; + } +} + +var WindowWatcherFactory = { + createInstance: function createInstance(outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return WindowWatcher.QueryInterface(iid); + } +}; + +var registrar = Components.manager.QueryInterface(AM_Ci.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"), + "Fake Window Watcher", + "@mozilla.org/embedcomp/window-watcher;1", WindowWatcherFactory); + +/** + * Start the test by installing extensions. + */ +function run_test() { + do_test_pending(); + gCachePurged = false; + + let obs = AM_Cc["@mozilla.org/observer-service;1"]. + getService(AM_Ci.nsIObserverService); + obs.addObserver({ + observe: function(aSubject, aTopic, aData) { + gCachePurged = true; + } + }, "startupcache-invalidate", false); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); + + startupManager(); + // nsAppRunner takes care of clearing this when a new app is installed + do_check_false(gCachePurged); + + installAllFiles([do_get_addon("test_bug594058")], function() { + restartManager(); + do_check_true(gCachePurged); + gCachePurged = false; + + // Now, make it look like we've updated the file. First, start the EM + // so it records the bogus old time, then update the file and restart. + let extFile = extDir.clone(); + let pastTime = extFile.lastModifiedTime - 5000; + extFile.append("bug594058@tests.mozilla.org"); + setExtensionModifiedTime(extFile, pastTime); + let otherFile = extFile.clone(); + otherFile.append("directory"); + otherFile.lastModifiedTime = pastTime; + otherFile.append("file1"); + otherFile.lastModifiedTime = pastTime; + + restartManager(); + gCachePurged = false; + + otherFile.lastModifiedTime = pastTime + 5000; + restartManager(); + do_check_true(gCachePurged); + gCachePurged = false; + + restartManager(); + do_check_false(gCachePurged); + + do_test_finished(); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug595081.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug595081.js new file mode 100644 index 000000000..db53dc747 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug595081.js @@ -0,0 +1,27 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that the AddonManager objects cannot be tampered with + +function run_test() { + // Setup for test + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + startupManager(); + + // Verify that properties cannot be changed + let old = AddonManager.STATE_AVAILABLE; + AddonManager.STATE_AVAILABLE = 28; + do_check_eq(AddonManager.STATE_AVAILABLE, old); + + // Verify that functions cannot be replaced + AddonManager.isInstallEnabled = function() { + do_throw("Should not be able to replace a function"); + } + AddonManager.isInstallEnabled("application/x-xpinstall"); + + // Verify that properties cannot be added + AddonManager.foo = "bar"; + do_check_false("foo" in AddonManager); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug595573.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug595573.js new file mode 100644 index 000000000..7e2bf7d77 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug595573.js @@ -0,0 +1,40 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This tests if addons with UUID based ids install and stay installed + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + startupManager(); + run_test_1(); +} + +function run_test_1() { + installAllFiles([do_get_addon("test_bug595573")], function() { + restartManager(); + + AddonManager.getAddonByID("{2f69dacd-03df-4150-a9f1-e8a7b2748829}", function(a1) { + do_check_neq(a1, null); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); + + do_execute_soon(run_test_2); + }); + }); +} + +function run_test_2() { + restartManager(); + + AddonManager.getAddonByID("{2f69dacd-03df-4150-a9f1-e8a7b2748829}", function(a1) { + do_check_neq(a1, null); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); + + do_execute_soon(do_test_finished); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug596343.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug596343.js new file mode 100644 index 000000000..96e95c5ad --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug596343.js @@ -0,0 +1,86 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +const URI_EXTENSION_SELECT_DIALOG = "chrome://mozapps/content/extensions/selectAddons.xul"; +const URI_EXTENSION_UPDATE_DIALOG = "chrome://mozapps/content/extensions/update.xul"; +const PREF_EM_SHOW_MISMATCH_UI = "extensions.showMismatchUI"; +const PREF_SHOWN_SELECTION_UI = "extensions.shownSelectionUI"; + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +var gExpectedURL = null; + +// This will be called to show the any update dialog. +var WindowWatcher = { + openWindow: function(parent, url, name, features, arguments) { + do_check_eq(url, gExpectedURL); + gExpectedURL = null; + }, + + QueryInterface: function(iid) { + if (iid.equals(AM_Ci.nsIWindowWatcher) + || iid.equals(AM_Ci.nsISupports)) + return this; + + throw Components.results.NS_ERROR_NO_INTERFACE; + } +} + +var WindowWatcherFactory = { + createInstance: function createInstance(outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return WindowWatcher.QueryInterface(iid); + } +}; + +var registrar = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"), + "Fake Window Watcher", + "@mozilla.org/embedcomp/window-watcher;1", WindowWatcherFactory); + +// Tests that the selection UI is displayed when upgrading an existing profile +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); + + Services.prefs.setBoolPref(PREF_EM_SHOW_MISMATCH_UI, true); + + var dest = writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }], + name: "Test Addon 1", + }, profileDir); + + // For a new profile it should disable showing the selection UI in the future + // without showing the selection UI + gExpectedURL = URI_EXTENSION_SELECT_DIALOG; + startupManager(); + + do_check_true(Services.prefs.getBoolPref(PREF_SHOWN_SELECTION_UI)); + do_check_eq(gExpectedURL, URI_EXTENSION_SELECT_DIALOG); + + // Reset the 'already shown' pref so that we can test that the first upgrade of + // an existing profile shows the selection UI + Services.prefs.clearUserPref(PREF_SHOWN_SELECTION_UI); + + restartManager("2"); + + do_check_true(Services.prefs.getBoolPref(PREF_SHOWN_SELECTION_UI)); + do_check_eq(gExpectedURL, null); + + // Once we've seen the selection UI once, future upgrades will show the update dialog + // but only if this upgrade disabled an add-on + gExpectedURL = URI_EXTENSION_UPDATE_DIALOG; + + restartManager("3"); + + do_check_eq(gExpectedURL, null); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug596607.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug596607.js new file mode 100644 index 000000000..3e655dc87 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug596607.js @@ -0,0 +1,140 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that a reference to a non-existent extension in the registry doesn't +// break things +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + +// Enable loading extensions from the user and system scopes +Services.prefs.setIntPref("extensions.enabledScopes", + AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_USER + + AddonManager.SCOPE_SYSTEM); + +var addon1 = { + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +var addon2 = { + id: "addon2@tests.mozilla.org", + version: "2.0", + name: "Test 2", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }] +}; + +const addon1Dir = writeInstallRDFForExtension(addon1, gProfD, "addon1"); +const addon2Dir = writeInstallRDFForExtension(addon2, gProfD, "addon2"); +const addon3Dir = gProfD.clone(); +addon3Dir.append("addon3@tests.mozilla.org"); + +function run_test() { + // This test only works where there is a registry. + if (!("nsIWindowsRegKey" in AM_Ci)) + return; + + do_test_pending(); + + run_test_1(); +} + +// Tests whether starting a fresh profile with a bad entry works +function run_test_1() { + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon1@tests.mozilla.org", addon1Dir.path); + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon2@tests.mozilla.org", addon2Dir.path); + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon3@tests.mozilla.org", addon3Dir.path); + + startupManager(); + + 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_true(a1.isActive); + do_check_false(hasFlag(a1.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_eq(a1.scope, AddonManager.SCOPE_SYSTEM); + + do_check_neq(a2, null); + do_check_true(a2.isActive); + do_check_false(hasFlag(a2.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_eq(a2.scope, AddonManager.SCOPE_USER); + + do_check_eq(a3, null); + + do_execute_soon(run_test_2); + }); +} + +// Tests whether removing the bad entry has any effect +function run_test_2() { + shutdownManager(); + + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon3@tests.mozilla.org", addon3Dir.path); + + startupManager(false); + + 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_true(a1.isActive); + do_check_false(hasFlag(a1.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_eq(a1.scope, AddonManager.SCOPE_SYSTEM); + + do_check_neq(a2, null); + do_check_true(a2.isActive); + do_check_false(hasFlag(a2.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_eq(a2.scope, AddonManager.SCOPE_USER); + + do_check_eq(a3, null); + + do_execute_soon(run_test_3); + }); +} + +// Tests adding the bad entry to an existing profile has any effect +function run_test_3() { + shutdownManager(); + + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon3@tests.mozilla.org", null); + + startupManager(false); + + 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_true(a1.isActive); + do_check_false(hasFlag(a1.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_eq(a1.scope, AddonManager.SCOPE_SYSTEM); + + do_check_neq(a2, null); + do_check_true(a2.isActive); + do_check_false(hasFlag(a2.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_eq(a2.scope, AddonManager.SCOPE_USER); + + do_check_eq(a3, null); + + do_execute_soon(do_test_finished); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug616841.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug616841.js new file mode 100644 index 000000000..d0c973960 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug616841.js @@ -0,0 +1,26 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that string comparisons work correctly in callbacks + +function test_string_compare() { + do_check_true("C".localeCompare("D") < 0); + do_check_true("D".localeCompare("C") > 0); + do_check_true("\u010C".localeCompare("D") < 0); + do_check_true("D".localeCompare("\u010C") > 0); +} + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + startupManager(); + + do_test_pending(); + + test_string_compare(); + + AddonManager.getAddonByID("foo", function(aAddon) { + test_string_compare(); + do_execute_soon(do_test_finished); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug619730.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug619730.js new file mode 100644 index 000000000..761daf4eb --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug619730.js @@ -0,0 +1,64 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests whether +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; + +Cu.import("resource://testing-common/httpd.js"); + +var gTestserver = new HttpServer(); +gTestserver.start(-1); +gPort = gTestserver.identity.primaryPort; +mapFile("/data/test_bug619730.xml", gTestserver); + +function load_blocklist(file, aCallback) { + Services.obs.addObserver(function() { + Services.obs.removeObserver(arguments.callee, "blocklist-updated"); + + do_execute_soon(aCallback); + }, "blocklist-updated", false); + + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + + gPort + "/data/" + file); + var blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. + getService(Ci.nsITimerCallback); + blocklist.notify(null); +} + +var gSawGFX = false; +var gSawTest = false; + +// Performs the initial setup +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); + startupManager(); + + do_test_pending(); + + Services.obs.addObserver(function(aSubject, aTopic, aData) { + do_check_true(aSubject instanceof AM_Ci.nsIDOMElement); + do_check_eq(aSubject.getAttribute("testattr"), "GFX"); + do_check_eq(aSubject.childNodes.length, 2); + gSawGFX = true; + }, "blocklist-data-gfxItems", false); + + Services.obs.addObserver(function(aSubject, aTopic, aData) { + do_check_true(aSubject instanceof AM_Ci.nsIDOMElement); + do_check_eq(aSubject.getAttribute("testattr"), "FOO"); + do_check_eq(aSubject.childNodes.length, 3); + gSawTest = true; + }, "blocklist-data-testItems", false); + + Services.obs.addObserver(function(aSubject, aTopic, aData) { + do_check_true(gSawGFX); + do_check_true(gSawTest); + }, "blocklist-data-fooItems", false); + + // Need to wait for the blocklist to load; Bad Things happen if the test harness + // shuts down AddonManager before the blocklist service is done telling it about + // changes + load_blocklist("test_bug619730.xml", () => gTestserver.stop(do_test_finished)); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug620837.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug620837.js new file mode 100644 index 000000000..6bfbfcaf2 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug620837.js @@ -0,0 +1,145 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +Components.utils.import("resource://testing-common/httpd.js"); + +const PREF_BLOCKLIST_LASTUPDATETIME = "app.update.lastUpdateTime.blocklist-background-update-timer"; +const PREF_BLOCKLIST_PINGCOUNTTOTAL = "extensions.blocklist.pingCountTotal"; +const PREF_BLOCKLIST_PINGCOUNTVERSION = "extensions.blocklist.pingCountVersion"; + +const SECONDS_IN_DAY = 60 * 60 * 24; + +var gExpectedQueryString = null; +var gNextTest = null; +var gTestserver = null; + +function notify_blocklist() { + var blocklist = AM_Cc["@mozilla.org/extensions/blocklist;1"]. + getService(AM_Ci.nsITimerCallback); + blocklist.notify(null); +} + +function pathHandler(metadata, response) { + do_check_eq(metadata.queryString, gExpectedQueryString); + gNextTest(); +} + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); + + gTestserver = new HttpServer(); + gTestserver.registerPathHandler("/", pathHandler); + gTestserver.start(-1); + gPort = gTestserver.identity.primaryPort; + + Services.prefs.setCharPref("extensions.blocklist.url", + "http://localhost:" + gPort + + "/?%PING_COUNT%&%TOTAL_PING_COUNT%&%DAYS_SINCE_LAST_PING%"); + + do_test_pending(); + test1(); +} + +function getNowInSeconds() { + return Math.round(Date.now() / 1000); +} + +function test1() { + gNextTest = test2; + gExpectedQueryString = "1&1&new"; + notify_blocklist(); +} + +function test2() { + gNextTest = test3; + gExpectedQueryString = "invalid&invalid&invalid"; + notify_blocklist(); +} + +function test3() { + Services.prefs.setIntPref(PREF_BLOCKLIST_LASTUPDATETIME, + (getNowInSeconds() - SECONDS_IN_DAY)); + gNextTest = test4; + gExpectedQueryString = "2&2&1"; + notify_blocklist(); +} + +function test4() { + Services.prefs.setIntPref(PREF_BLOCKLIST_PINGCOUNTVERSION, -1); + Services.prefs.setIntPref(PREF_BLOCKLIST_LASTUPDATETIME, + (getNowInSeconds() - (SECONDS_IN_DAY * 2))); + gNextTest = test5; + gExpectedQueryString = "1&3&2"; + notify_blocklist(); +} + +function test5() { + Services.prefs.setIntPref(PREF_BLOCKLIST_LASTUPDATETIME, getNowInSeconds()); + gNextTest = test6; + gExpectedQueryString = "invalid&invalid&0"; + notify_blocklist(); +} + +function test6() { + Services.prefs.setIntPref(PREF_BLOCKLIST_LASTUPDATETIME, + (getNowInSeconds() - (SECONDS_IN_DAY * 3))); + gNextTest = test7; + gExpectedQueryString = "2&4&3"; + notify_blocklist(); +} + +function test7() { + Services.prefs.setIntPref(PREF_BLOCKLIST_PINGCOUNTVERSION, 2147483647); + Services.prefs.setIntPref(PREF_BLOCKLIST_LASTUPDATETIME, + (getNowInSeconds() - (SECONDS_IN_DAY * 4))); + gNextTest = test8; + gExpectedQueryString = "2147483647&5&4"; + notify_blocklist(); +} + +function test8() { + Services.prefs.setIntPref(PREF_BLOCKLIST_LASTUPDATETIME, + (getNowInSeconds() - (SECONDS_IN_DAY * 5))); + gNextTest = test9; + gExpectedQueryString = "1&6&5"; + notify_blocklist(); +} + +function test9() { + Services.prefs.setIntPref(PREF_BLOCKLIST_PINGCOUNTTOTAL, 2147483647); + Services.prefs.setIntPref(PREF_BLOCKLIST_LASTUPDATETIME, + (getNowInSeconds() - (SECONDS_IN_DAY * 6))); + gNextTest = test10; + gExpectedQueryString = "2&2147483647&6"; + notify_blocklist(); +} + +function test10() { + Services.prefs.setIntPref(PREF_BLOCKLIST_LASTUPDATETIME, + (getNowInSeconds() - (SECONDS_IN_DAY * 7))); + gNextTest = test11; + gExpectedQueryString = "3&1&7"; + notify_blocklist(); +} + +function test11() { + Services.prefs.setIntPref(PREF_BLOCKLIST_PINGCOUNTVERSION, -1); + Services.prefs.setIntPref(PREF_BLOCKLIST_LASTUPDATETIME, + (getNowInSeconds() - (SECONDS_IN_DAY * 8))); + gNextTest = test12; + gExpectedQueryString = "1&2&8"; + notify_blocklist(); +} + +function test12() { + Services.prefs.setIntPref(PREF_BLOCKLIST_LASTUPDATETIME, + (getNowInSeconds() - (SECONDS_IN_DAY * 9))); + gNextTest = finish; + gExpectedQueryString = "2&3&9"; + notify_blocklist(); +} + +function finish() { + gTestserver.stop(do_test_finished); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug655254.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug655254.js new file mode 100644 index 000000000..45274b734 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug655254.js @@ -0,0 +1,164 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that moving an extension in the filesystem without any other +// change still keeps updated compatibility information + +// The test extension uses an insecure update url. +Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); +// Enable loading extensions from the user and system scopes +Services.prefs.setIntPref("extensions.enabledScopes", + AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_USER); + +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "1.9.2"); + +Components.utils.import("resource://testing-common/httpd.js"); +var testserver = new HttpServer(); +testserver.start(-1); +gPort = testserver.identity.primaryPort; +mapFile("/data/test_bug655254.rdf", testserver); + +var userDir = gProfD.clone(); +userDir.append("extensions2"); +userDir.append(gAppInfo.ID); + +var dirProvider = { + getFile: function(aProp, aPersistent) { + aPersistent.value = false; + if (aProp == "XREUSysExt") + return userDir.parent; + return null; + }, + + QueryInterface: XPCOMUtils.generateQI([AM_Ci.nsIDirectoryServiceProvider, + AM_Ci.nsISupports]) +}; +Services.dirsvc.registerProvider(dirProvider); + +var addon1 = { + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + updateURL: "http://localhost:" + gPort + "/data/test_bug655254.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Set up the profile +function run_test() { + do_test_pending(); + run_test_1(); +} + +function end_test() { + testserver.stop(do_test_finished); +} + +function run_test_1() { + var time = Date.now(); + var dir = writeInstallRDFForExtension(addon1, userDir); + setExtensionModifiedTime(dir, time); + + manuallyInstall(do_get_addon("test_bug655254_2"), userDir, "addon2@tests.mozilla.org"); + + startupManager(); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org"], function([a1, a2]) { + do_check_neq(a1, null); + do_check_true(a1.appDisabled); + do_check_false(a1.isActive); + do_check_false(isExtensionInAddonsList(userDir, a1.id)); + + do_check_neq(a2, null); + do_check_false(a2.appDisabled); + do_check_true(a2.isActive); + do_check_false(isExtensionInAddonsList(userDir, a2.id)); + do_check_eq(Services.prefs.getIntPref("bootstraptest.active_version"), 1); + + a1.findUpdates({ + onUpdateFinished: function() { + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { + do_check_neq(a1, null); + do_check_false(a1.appDisabled); + do_check_true(a1.isActive); + do_check_true(isExtensionInAddonsList(userDir, a1.id)); + + shutdownManager(); + + do_check_eq(Services.prefs.getIntPref("bootstraptest.active_version"), 0); + + userDir.parent.moveTo(gProfD, "extensions3"); + userDir = gProfD.clone(); + userDir.append("extensions3"); + userDir.append(gAppInfo.ID); + do_check_true(userDir.exists()); + + startupManager(false); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org"], function([a1, a2]) { + do_check_neq(a1, null); + do_check_false(a1.appDisabled); + do_check_true(a1.isActive); + do_check_true(isExtensionInAddonsList(userDir, a1.id)); + + do_check_neq(a2, null); + do_check_false(a2.appDisabled); + do_check_true(a2.isActive); + do_check_false(isExtensionInAddonsList(userDir, a2.id)); + do_check_eq(Services.prefs.getIntPref("bootstraptest.active_version"), 1); + + do_execute_soon(run_test_2); + }); + })); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} + +//Set up the profile +function run_test_2() { + AddonManager.getAddonByID("addon2@tests.mozilla.org", callback_soon(function(a2) { + do_check_neq(a2, null); + do_check_false(a2.appDisabled); + do_check_true(a2.isActive); + do_check_false(isExtensionInAddonsList(userDir, a2.id)); + do_check_eq(Services.prefs.getIntPref("bootstraptest.active_version"), 1); + + a2.userDisabled = true; + do_check_eq(Services.prefs.getIntPref("bootstraptest.active_version"), 0); + + shutdownManager(); + + userDir.parent.moveTo(gProfD, "extensions4"); + userDir = gProfD.clone(); + userDir.append("extensions4"); + userDir.append(gAppInfo.ID); + do_check_true(userDir.exists()); + + startupManager(false); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org"], function([a1, a2]) { + do_check_neq(a1, null); + do_check_false(a1.appDisabled); + do_check_true(a1.isActive); + do_check_true(isExtensionInAddonsList(userDir, a1.id)); + + do_check_neq(a2, null); + do_check_true(a2.userDisabled); + do_check_false(a2.isActive); + do_check_false(isExtensionInAddonsList(userDir, a2.id)); + do_check_eq(Services.prefs.getIntPref("bootstraptest.active_version"), 0); + + end_test(); + }); + })); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug659772.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug659772.js new file mode 100644 index 000000000..c6e8ab4e2 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug659772.js @@ -0,0 +1,340 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that a pending upgrade during a schema update doesn't break things + +var addon1 = { + id: "addon1@tests.mozilla.org", + version: "2.0", + name: "Test 1", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +var addon2 = { + id: "addon2@tests.mozilla.org", + version: "2.0", + name: "Test 2", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }] +}; + +var addon3 = { + id: "addon3@tests.mozilla.org", + version: "2.0", + name: "Test 3", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +var addon4 = { + id: "addon4@tests.mozilla.org", + version: "2.0", + name: "Test 4", + 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", "1", "1.9.2"); + + run_test_1(); +} + +// Tests whether a schema migration without app version change works +function run_test_1() { + writeInstallRDFForExtension(addon1, profileDir); + writeInstallRDFForExtension(addon2, profileDir); + writeInstallRDFForExtension(addon3, profileDir); + writeInstallRDFForExtension(addon4, profileDir); + + 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_eq(a1.version, "2.0"); + do_check_false(a1.appDisabled); + do_check_false(a1.userDisabled); + do_check_true(a1.isActive); + do_check_true(isExtensionInAddonsList(profileDir, addon1.id)); + + do_check_neq(a2, null); + do_check_eq(a2.version, "2.0"); + do_check_false(a2.appDisabled); + do_check_false(a2.userDisabled); + do_check_true(a2.isActive); + do_check_true(isExtensionInAddonsList(profileDir, addon2.id)); + + do_check_neq(a3, null); + do_check_eq(a3.version, "2.0"); + do_check_false(a3.appDisabled); + do_check_false(a3.userDisabled); + do_check_true(a3.isActive); + do_check_true(isExtensionInAddonsList(profileDir, addon3.id)); + + do_check_neq(a4, null); + do_check_eq(a4.version, "2.0"); + do_check_true(a4.appDisabled); + do_check_false(a4.userDisabled); + do_check_false(a4.isActive); + do_check_false(isExtensionInAddonsList(profileDir, addon4.id)); + + // Prepare the add-on update, and a bootstrapped addon (bug 693714) + installAllFiles([ + do_get_addon("test_bug659772"), + do_get_addon("test_bootstrap1_1") + ], function() { + shutdownManager(); + + // Make it look like the next time the app is started it has a new DB schema + changeXPIDBVersion(1); + Services.prefs.setIntPref("extensions.databaseSchema", 1); + + let jsonfile = gProfD.clone(); + jsonfile.append("extensions"); + jsonfile.append("staged"); + jsonfile.append("addon3@tests.mozilla.org.json"); + do_check_true(jsonfile.exists()); + + // Remove an unnecessary property from the cached manifest + let fis = AM_Cc["@mozilla.org/network/file-input-stream;1"]. + createInstance(AM_Ci.nsIFileInputStream); + let json = AM_Cc["@mozilla.org/dom/json;1"]. + createInstance(AM_Ci.nsIJSON); + fis.init(jsonfile, -1, 0, 0); + let addonObj = json.decodeFromStream(fis, jsonfile.fileSize); + fis.close(); + delete addonObj.optionsType; + + let stream = AM_Cc["@mozilla.org/network/file-output-stream;1"]. + createInstance(AM_Ci.nsIFileOutputStream); + let converter = AM_Cc["@mozilla.org/intl/converter-output-stream;1"]. + createInstance(AM_Ci.nsIConverterOutputStream); + stream.init(jsonfile, FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | + FileUtils.MODE_TRUNCATE, FileUtils.PERMS_FILE, + 0); + converter.init(stream, "UTF-8", 0, 0x0000); + converter.writeString(JSON.stringify(addonObj)); + converter.close(); + stream.close(); + + Services.prefs.clearUserPref("bootstraptest.install_reason"); + Services.prefs.clearUserPref("bootstraptest.uninstall_reason"); + + startupManager(false); + + 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_eq(a1.version, "2.0"); + do_check_false(a1.appDisabled); + do_check_false(a1.userDisabled); + do_check_true(a1.isActive); + do_check_true(isExtensionInAddonsList(profileDir, addon1.id)); + + do_check_neq(a2, null); + do_check_eq(a2.version, "2.0"); + do_check_false(a2.appDisabled); + do_check_false(a2.userDisabled); + do_check_true(a2.isActive); + do_check_true(isExtensionInAddonsList(profileDir, addon2.id)); + + // Should stay enabled because we migrate the compat info from + // the previous version of the DB + do_check_neq(a3, null); + do_check_eq(a3.version, "2.0"); + todo_check_false(a3.appDisabled); // XXX unresolved issue + do_check_false(a3.userDisabled); + todo_check_true(a3.isActive); // XXX same + todo_check_true(isExtensionInAddonsList(profileDir, addon3.id)); // XXX same + + do_check_neq(a4, null); + do_check_eq(a4.version, "2.0"); + do_check_true(a4.appDisabled); + do_check_false(a4.userDisabled); + do_check_false(a4.isActive); + do_check_false(isExtensionInAddonsList(profileDir, addon4.id)); + + // Check that install and uninstall haven't been called on the bootstrapped addon + do_check_false(Services.prefs.prefHasUserValue("bootstraptest.install_reason")); + do_check_false(Services.prefs.prefHasUserValue("bootstraptest.uninstall_reason")); + + a1.uninstall(); + a2.uninstall(); + a3.uninstall(); + a4.uninstall(); + do_execute_soon(run_test_2); + }); + }); + }); +} + +// Tests whether a schema migration with app version change works +function run_test_2() { + restartManager(); + + shutdownManager(); + + writeInstallRDFForExtension(addon1, profileDir); + writeInstallRDFForExtension(addon2, profileDir); + writeInstallRDFForExtension(addon3, profileDir); + writeInstallRDFForExtension(addon4, profileDir); + + 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_eq(a1.version, "2.0"); + do_check_false(a1.appDisabled); + do_check_false(a1.userDisabled); + do_check_true(a1.isActive); + do_check_true(isExtensionInAddonsList(profileDir, addon1.id)); + + do_check_neq(a2, null); + do_check_eq(a2.version, "2.0"); + do_check_false(a2.appDisabled); + do_check_false(a2.userDisabled); + do_check_true(a2.isActive); + do_check_true(isExtensionInAddonsList(profileDir, addon2.id)); + + do_check_neq(a3, null); + do_check_eq(a3.version, "2.0"); + do_check_false(a3.appDisabled); + do_check_false(a3.userDisabled); + do_check_true(a3.isActive); + do_check_true(isExtensionInAddonsList(profileDir, addon3.id)); + + do_check_neq(a4, null); + do_check_eq(a4.version, "2.0"); + do_check_true(a4.appDisabled); + do_check_false(a4.userDisabled); + do_check_false(a4.isActive); + do_check_false(isExtensionInAddonsList(profileDir, addon4.id)); + + // Prepare the add-on update, and a bootstrapped addon (bug 693714) + installAllFiles([ + do_get_addon("test_bug659772"), + do_get_addon("test_bootstrap1_1") + ], function() { do_execute_soon(prepare_schema_migrate); }); + + function prepare_schema_migrate() { + shutdownManager(); + + // Make it look like the next time the app is started it has a new DB schema + changeXPIDBVersion(1); + Services.prefs.setIntPref("extensions.databaseSchema", 1); + + let jsonfile = gProfD.clone(); + jsonfile.append("extensions"); + jsonfile.append("staged"); + jsonfile.append("addon3@tests.mozilla.org.json"); + do_check_true(jsonfile.exists()); + + // Remove an unnecessary property from the cached manifest + let fis = AM_Cc["@mozilla.org/network/file-input-stream;1"]. + createInstance(AM_Ci.nsIFileInputStream); + let json = AM_Cc["@mozilla.org/dom/json;1"]. + createInstance(AM_Ci.nsIJSON); + fis.init(jsonfile, -1, 0, 0); + let addonObj = json.decodeFromStream(fis, jsonfile.fileSize); + fis.close(); + delete addonObj.optionsType; + + let stream = AM_Cc["@mozilla.org/network/file-output-stream;1"]. + createInstance(AM_Ci.nsIFileOutputStream); + let converter = AM_Cc["@mozilla.org/intl/converter-output-stream;1"]. + createInstance(AM_Ci.nsIConverterOutputStream); + stream.init(jsonfile, FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | + FileUtils.MODE_TRUNCATE, FileUtils.PERMS_FILE, + 0); + converter.init(stream, "UTF-8", 0, 0x0000); + converter.writeString(JSON.stringify(addonObj)); + converter.close(); + stream.close(); + + Services.prefs.clearUserPref("bootstraptest.install_reason"); + Services.prefs.clearUserPref("bootstraptest.uninstall_reason"); + + gAppInfo.version = "2"; + startupManager(true); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org"], + callback_soon(function([a1, a2, a3, a4]) { + do_check_neq(a1, null); + do_check_eq(a1.version, "2.0"); + do_check_true(a1.appDisabled); + do_check_false(a1.userDisabled); + do_check_false(a1.isActive); + do_check_false(isExtensionInAddonsList(profileDir, addon1.id)); + + do_check_neq(a2, null); + do_check_eq(a2.version, "2.0"); + do_check_false(a2.appDisabled); + do_check_false(a2.userDisabled); + do_check_true(a2.isActive); + do_check_true(isExtensionInAddonsList(profileDir, addon2.id)); + + // Should become appDisabled because we migrate the compat info from + // the previous version of the DB + do_check_neq(a3, null); + do_check_eq(a3.version, "2.0"); + todo_check_true(a3.appDisabled); + do_check_false(a3.userDisabled); + todo_check_false(a3.isActive); + todo_check_false(isExtensionInAddonsList(profileDir, addon3.id)); + + do_check_neq(a4, null); + do_check_eq(a4.version, "2.0"); + do_check_false(a4.appDisabled); + do_check_false(a4.userDisabled); + do_check_true(a4.isActive); + do_check_true(isExtensionInAddonsList(profileDir, addon4.id)); + + // Check that install and uninstall haven't been called on the bootstrapped addon + do_check_false(Services.prefs.prefHasUserValue("bootstraptest.install_reason")); + do_check_false(Services.prefs.prefHasUserValue("bootstraptest.uninstall_reason")); + + a1.uninstall(); + a2.uninstall(); + a3.uninstall(); + a4.uninstall(); + restartManager(); + + shutdownManager(); + + do_test_finished(); + })); + }; + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug675371.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug675371.js new file mode 100644 index 000000000..579335d8a --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug675371.js @@ -0,0 +1,91 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + startupManager(); + + prepare_test({ }, [ + "onNewInstall" + ]); + + AddonManager.getInstallForFile(do_get_addon("test_bug675371"), function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + + prepare_test({ + "bug675371@tests.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], callback_soon(check_test)); + install.install(); + }); +} + +function check_test() { + AddonManager.getAddonByID("bug675371@tests.mozilla.org", do_exception_wrap(function(addon) { + do_check_neq(addon, null); + do_check_true(addon.isActive); + + // Tests that chrome.manifest is registered when the addon is installed. + var target = { active: false }; + Services.scriptloader.loadSubScript("chrome://bug675371/content/test.js", target); + do_check_true(target.active); + + prepare_test({ + "bug675371@tests.mozilla.org": [ + ["onDisabling", false], + "onDisabled" + ] + }); + + // Tests that chrome.manifest is unregistered when the addon is disabled. + addon.userDisabled = true; + target.active = false; + try { + Services.scriptloader.loadSubScript("chrome://bug675371/content/test.js", target); + do_throw("Chrome file should not have been found"); + } catch (e) { + do_check_false(target.active); + } + + prepare_test({ + "bug675371@tests.mozilla.org": [ + ["onEnabling", false], + "onEnabled" + ] + }); + + // Tests that chrome.manifest is registered when the addon is enabled. + addon.userDisabled = false; + target.active = false; + Services.scriptloader.loadSubScript("chrome://bug675371/content/test.js", target); + do_check_true(target.active); + + prepare_test({ + "bug675371@tests.mozilla.org": [ + ["onUninstalling", false], + "onUninstalled" + ] + }); + + // Tests that chrome.manifest is unregistered when the addon is uninstalled. + addon.uninstall(); + target.active = false; + try { + Services.scriptloader.loadSubScript("chrome://bug675371/content/test.js", target); + do_throw("Chrome file should not have been found"); + } catch (e) { + do_check_false(target.active); + } + + do_execute_soon(do_test_finished); + })); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug740612.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug740612.js new file mode 100644 index 000000000..d17e7acde --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug740612.js @@ -0,0 +1,40 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that attempts to override the global values fails but doesn't +// destroy the world with it +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +function getActiveVersion() { + return Services.prefs.getIntPref("bootstraptest.active_version"); +} + +function getInstalledVersion() { + return Services.prefs.getIntPref("bootstraptest.installed_version"); +} + +function run_test() { + do_test_pending(); + + manuallyInstall(do_get_addon("test_bug740612_1"), profileDir, + "bug740612_1@tests.mozilla.org"); + manuallyInstall(do_get_addon("test_bug740612_2"), profileDir, + "bug740612_2@tests.mozilla.org"); + + startupManager(); + + AddonManager.getAddonsByIDs(["bug740612_1@tests.mozilla.org", + "bug740612_2@tests.mozilla.org"], + function([a1, a2]) { + do_check_neq(a1, null); + do_check_neq(a2, null); + do_check_eq(getInstalledVersion(), "1.0"); + do_check_eq(getActiveVersion(), "1.0"); + + do_execute_soon(do_test_finished); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug753900.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug753900.js new file mode 100644 index 000000000..206862339 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug753900.js @@ -0,0 +1,86 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that strange characters in an add-on version don't break the +// crash annotation. + +var addon1 = { + id: "addon1@tests.mozilla.org", + version: "1,0", + name: "Test 1", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +var addon2 = { + id: "addon2@tests.mozilla.org", + version: "1:0", + name: "Test 2", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +var addon3 = { + id: "addon3@tests.mozilla.org", + version: "1,0", + name: "Test 3", + bootstrap: true, + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +var addon4 = { + id: "addon4@tests.mozilla.org", + version: "1:0", + name: "Test 4", + bootstrap: true, + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +function run_test() { + do_test_pending(); + + writeInstallRDFForExtension(addon1, profileDir); + writeInstallRDFForExtension(addon2, profileDir); + writeInstallRDFForExtension(addon3, profileDir); + writeInstallRDFForExtension(addon4, profileDir); + + 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_in_crash_annotation(addon1.id, addon1.version); + do_check_neq(a2, null); + do_check_in_crash_annotation(addon2.id, addon2.version); + do_check_neq(a3, null); + do_check_in_crash_annotation(addon3.id, addon3.version); + do_check_neq(a4, null); + do_check_in_crash_annotation(addon4.id, addon4.version); + + do_execute_soon(do_test_finished); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug757663.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug757663.js new file mode 100644 index 000000000..648c7acc3 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug757663.js @@ -0,0 +1,112 @@ +/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// This test verifies that removing a listener during a callback for that type
+// of listener still results in all listeners being called.
+
+var addon1 = {
+ id: "addon1@tests.mozilla.org",
+ version: "2.0",
+ name: "Test 1",
+ bootstrap: "true",
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "1",
+ maxVersion: "1"
+ }]
+};
+
+var listener1 = {
+ sawEvent: false,
+ onDisabling: function() {
+ this.sawEvent = true;
+ AddonManager.removeAddonListener(this);
+ },
+ onNewInstall: function() {
+ this.sawEvent = true;
+ AddonManager.removeInstallListener(this);
+ }
+};
+var listener2 = {
+ sawEvent: false,
+ onDisabling: function() {
+ this.sawEvent = true;
+ },
+ onNewInstall: function() {
+ this.sawEvent = true;
+ }
+};
+var listener3 = {
+ sawEvent: false,
+ onDisabling: function() {
+ this.sawEvent = true;
+ },
+ onNewInstall: function() {
+ this.sawEvent = true;
+ }
+};
+
+const profileDir = gProfD.clone();
+profileDir.append("extensions");
+
+
+function run_test() {
+ do_test_pending();
+ createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
+
+ writeInstallRDFForExtension(addon1, profileDir);
+ startupManager();
+
+ run_test_1();
+}
+
+function run_test_1() {
+ AddonManager.addAddonListener(listener1);
+ AddonManager.addAddonListener(listener2);
+ AddonManager.addAddonListener(listener3);
+
+ AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org"], function([a1]) {
+ do_check_neq(a1, null);
+ do_check_false(a1.userDisabled);
+ do_check_true(a1.isActive);
+
+ a1.userDisabled = true;
+
+ do_check_true(listener1.sawEvent);
+ listener1.sawEvent = false;
+ do_check_true(listener2.sawEvent);
+ listener2.sawEvent = false;
+ do_check_true(listener3.sawEvent);
+ listener3.sawEvent = false;
+
+ AddonManager.removeAddonListener(listener1);
+ AddonManager.removeAddonListener(listener2);
+ AddonManager.removeAddonListener(listener3);
+
+ a1.uninstall();
+ run_test_2();
+ });
+}
+
+function run_test_2() {
+ AddonManager.addInstallListener(listener1);
+ AddonManager.addInstallListener(listener2);
+ AddonManager.addInstallListener(listener3);
+
+ AddonManager.getInstallForFile(do_get_addon("test_bug757663"), function(aInstall) {
+
+ do_check_true(listener1.sawEvent);
+ listener1.sawEvent = false;
+ do_check_true(listener2.sawEvent);
+ listener2.sawEvent = false;
+ do_check_true(listener3.sawEvent);
+ listener3.sawEvent = false;
+
+ AddonManager.removeInstallListener(listener1);
+ AddonManager.removeInstallListener(listener2);
+ AddonManager.removeInstallListener(listener3);
+
+ do_execute_soon(do_test_finished);
+ });
+}
diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug953156.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug953156.js new file mode 100644 index 000000000..a7acb9ad2 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug953156.js @@ -0,0 +1,51 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + startupManager(); + + prepare_test({ }, [ + "onNewInstall" + ]); + + AddonManager.getInstallForFile(do_get_addon("test_bug675371"), function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + + prepare_test({ + "bug675371@tests.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ] + }, [ + "onInstallStarted", + "onInstallEnded" + ], callback_soon(check_test)); + install.install(); + }); +} + +function check_test() { + AddonManager.getAddonByID("bug675371@tests.mozilla.org", do_exception_wrap(function(addon) { + do_check_neq(addon, null); + do_check_true(addon.isActive); + + // Tests that chrome.manifest is registered when the addon is installed. + var target = { active: false }; + Services.scriptloader.loadSubScript("chrome://bug675371/content/test.js", target); + do_check_true(target.active); + + shutdownManager(); + + // Tests that chrome.manifest remains registered at app shutdown. + target.active = false; + Services.scriptloader.loadSubScript("chrome://bug675371/content/test.js", target); + do_check_true(target.active); + + do_execute_soon(do_test_finished); + })); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_cacheflush.js b/toolkit/mozapps/extensions/test/xpcshell/test_cacheflush.js new file mode 100644 index 000000000..4e7da0ee7 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_cacheflush.js @@ -0,0 +1,124 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that flushing the zipreader cache happens when appropriate + +var gExpectedFile = null; +var gCacheFlushCount = 0; + +var CacheFlushObserver = { + observe: function(aSubject, aTopic, aData) { + if (aTopic != "flush-cache-entry") + return; + + do_check_true(gExpectedFile != null); + do_check_true(aSubject instanceof AM_Ci.nsIFile); + do_check_eq(aSubject.path, gExpectedFile.path); + gCacheFlushCount++; + } +}; + +function run_test() { + do_test_pending(); + Services.obs.addObserver(CacheFlushObserver, "flush-cache-entry", false); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "2"); + + startupManager(); + + run_test_1(); +} + +// Tests that the cache is flushed when cancelling a pending install +function run_test_1() { + AddonManager.getInstallForFile(do_get_addon("test_cacheflush1"), function(aInstall) { + completeAllInstalls([aInstall], function() { + // We should flush the staged XPI when cancelling the install + gExpectedFile = gProfD.clone(); + gExpectedFile.append("extensions"); + gExpectedFile.append("staged"); + gExpectedFile.append("addon1@tests.mozilla.org.xpi"); + aInstall.cancel(); + + do_check_eq(gCacheFlushCount, 1); + gExpectedFile = null; + gCacheFlushCount = 0; + + run_test_2(); + }); + }); +} + +// Tests that the cache is flushed when uninstalling an add-on +function run_test_2() { + installAllFiles([do_get_addon("test_cacheflush1")], function() { + // Installing will flush the staged XPI during startup + gExpectedFile = gProfD.clone(); + gExpectedFile.append("extensions"); + gExpectedFile.append("staged"); + gExpectedFile.append("addon1@tests.mozilla.org.xpi"); + restartManager(); + do_check_eq(gCacheFlushCount, 1); + gExpectedFile = null; + gCacheFlushCount = 0; + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + // We should flush the installed XPI when uninstalling + do_check_true(a1 != null); + a1.uninstall(); + do_check_eq(gCacheFlushCount, 0); + + gExpectedFile = gProfD.clone(); + gExpectedFile.append("extensions"); + gExpectedFile.append("addon1@tests.mozilla.org.xpi"); + restartManager(); + do_check_eq(gCacheFlushCount, 1); + gExpectedFile = null; + gCacheFlushCount = 0; + + do_execute_soon(run_test_3); + }); + }); +} + +// Tests that the cache is flushed when installing a restartless add-on +function run_test_3() { + AddonManager.getInstallForFile(do_get_addon("test_cacheflush2"), function(aInstall) { + aInstall.addListener({ + onInstallStarted: function(aInstall) { + // We should flush the staged XPI when completing the install + gExpectedFile = gProfD.clone(); + gExpectedFile.append("extensions"); + gExpectedFile.append("staged"); + gExpectedFile.append("addon2@tests.mozilla.org.xpi"); + }, + + onInstallEnded: function(aInstall) { + do_check_eq(gCacheFlushCount, 1); + gExpectedFile = null; + gCacheFlushCount = 0; + + do_execute_soon(run_test_4); + } + }); + + aInstall.install(); + }); +} + +// Tests that the cache is flushed when uninstalling a restartless add-on +function run_test_4() { + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + // We should flush the installed XPI when uninstalling + gExpectedFile = gProfD.clone(); + gExpectedFile.append("extensions"); + gExpectedFile.append("addon2@tests.mozilla.org.xpi"); + + a2.uninstall(); + do_check_eq(gCacheFlushCount, 2); + gExpectedFile = null; + gCacheFlushCount = 0; + + do_execute_soon(do_test_finished); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_checkCompatibility_themeOverride.js b/toolkit/mozapps/extensions/test/xpcshell/test_checkCompatibility_themeOverride.js new file mode 100644 index 000000000..c872d75c3 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_checkCompatibility_themeOverride.js @@ -0,0 +1,93 @@ +/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// This verifies that the (temporary)
+// extensions.checkCompatibility.temporaryThemeOverride_minAppVersion
+// preference works.
+
+var ADDONS = [{
+ id: "addon1@tests.mozilla.org",
+ type: 4,
+ internalName: "theme1/1.0",
+ version: "1.0",
+ name: "Test 1",
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "1.0",
+ maxVersion: "1.0"
+ }]
+}, {
+ id: "addon2@tests.mozilla.org",
+ type: 4,
+ internalName: "theme2/1.0",
+ version: "1.0",
+ name: "Test 2",
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "2.0",
+ maxVersion: "2.0"
+ }]
+}];
+
+const profileDir = gProfD.clone();
+profileDir.append("extensions");
+
+
+function run_test() {
+ do_test_pending();
+ createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3.0", "1");
+
+ for (let a of ADDONS) {
+ writeInstallRDFForExtension(a, profileDir);
+ }
+
+ startupManager();
+
+ run_test_1();
+}
+
+function run_test_1() {
+ AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
+ "addon2@tests.mozilla.org"],
+ function([a1, a2]) {
+
+ do_check_neq(a1, null);
+ do_check_false(a1.isActive);
+ do_check_false(a1.isCompatible);
+ do_check_true(a1.appDisabled);
+
+ do_check_neq(a2, null);
+ do_check_false(a2.isActive);
+ do_check_false(a2.isCompatible);
+ do_check_true(a1.appDisabled);
+
+ do_execute_soon(run_test_2);
+ });
+}
+
+function run_test_2() {
+ Services.prefs.setCharPref("extensions.checkCompatibility.temporaryThemeOverride_minAppVersion", "2.0");
+ if (isNightlyChannel())
+ Services.prefs.setBoolPref("extensions.checkCompatibility.nightly", false);
+ else
+ Services.prefs.setBoolPref("extensions.checkCompatibility.3.0", false);
+ restartManager();
+
+ AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
+ "addon2@tests.mozilla.org"],
+ function([a1, a2]) {
+
+ do_check_neq(a1, null);
+ do_check_false(a1.isActive);
+ do_check_false(a1.isCompatible);
+ do_check_true(a1.appDisabled);
+
+ do_check_neq(a2, null);
+ do_check_false(a2.isActive);
+ do_check_false(a2.isCompatible);
+ do_check_false(a2.appDisabled);
+
+ do_execute_soon(do_test_finished);
+ });
+}
diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_checkcompatibility.js b/toolkit/mozapps/extensions/test/xpcshell/test_checkcompatibility.js new file mode 100644 index 000000000..b9fc0b3ab --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_checkcompatibility.js @@ -0,0 +1,196 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that the extensions.checkCompatibility.* preferences work. + +var ADDONS = [{ + // Cannot be enabled as it has no target app info for the applciation + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + targetApplications: [{ + id: "unknown@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}, { + // Always appears incompatible but can be enabled if compatibility checking is + // disabled + id: "addon2@tests.mozilla.org", + version: "1.0", + name: "Test 2", + targetApplications: [{ + id: "toolkit@mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}, { + // Always appears incompatible but can be enabled if compatibility checking is + // disabled + id: "addon3@tests.mozilla.org", + version: "1.0", + name: "Test 3", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}, { // Always compatible and enabled + id: "addon4@tests.mozilla.org", + version: "1.0", + name: "Test 4", + targetApplications: [{ + id: "toolkit@mozilla.org", + minVersion: "1", + maxVersion: "2" + }] +}, { // Always compatible and enabled + id: "addon5@tests.mozilla.org", + version: "1.0", + name: "Test 5", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "3" + }] +}]; + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +var gIsNightly = false; + +function run_test() { + do_test_pending("checkcompatibility.js"); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2.2.3", "2"); + + ADDONS.forEach(function(a) { + writeInstallRDFForExtension(a, profileDir); + }); + + gIsNightly = isNightlyChannel(); + + startupManager(); + + run_test_1(); +} + +/** + * Checks that the add-ons are enabled as expected. + * @param overridden + * A boolean indicating that compatibility checking is overridden + * @param a1 + * The Addon for addon1@tests.mozilla.org + * @param a2 + * The Addon for addon2@tests.mozilla.org + * @param a3 + * The Addon for addon3@tests.mozilla.org + * @param a4 + * The Addon for addon4@tests.mozilla.org + * @param a5 + * The Addon for addon5@tests.mozilla.org + */ +function check_state(overridden, a1, a2, a3, a4, a5) { + do_check_neq(a1, null); + do_check_false(a1.isActive); + do_check_false(a1.isCompatible); + + do_check_neq(a2, null); + if (overridden) + do_check_true(a2.isActive); + else + do_check_false(a2.isActive); + do_check_false(a2.isCompatible); + + do_check_neq(a3, null); + if (overridden) + do_check_true(a3.isActive); + else + do_check_false(a3.isActive); + do_check_false(a3.isCompatible); + + do_check_neq(a4, null); + do_check_true(a4.isActive); + do_check_true(a4.isCompatible); + + do_check_neq(a5, null); + do_check_true(a5.isActive); + do_check_true(a5.isCompatible); +} + +// Tests that with compatibility checking enabled we see the incompatible +// add-ons disabled +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"], + function([a1, a2, a3, a4, a5]) { + check_state(false, a1, a2, a3, a4, a5); + + do_execute_soon(run_test_2); + }); +} + +// Tests that with compatibility checking disabled we see the incompatible +// add-ons enabled +function run_test_2() { + if (gIsNightly) + Services.prefs.setBoolPref("extensions.checkCompatibility.nightly", false); + else + Services.prefs.setBoolPref("extensions.checkCompatibility.2.2", false); + restartManager(); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org"], + function([a1, a2, a3, a4, a5]) { + check_state(true, a1, a2, a3, a4, a5); + + do_execute_soon(run_test_3); + }); +} + +// Tests that with compatibility checking disabled we see the incompatible +// add-ons enabled. +function run_test_3() { + if (!gIsNightly) + Services.prefs.setBoolPref("extensions.checkCompatibility.2.1a", false); + restartManager("2.1a4"); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org"], + function([a1, a2, a3, a4, a5]) { + check_state(true, a1, a2, a3, a4, a5); + + do_execute_soon(run_test_4); + }); +} + +// Tests that with compatibility checking enabled we see the incompatible +// add-ons disabled. +function run_test_4() { + if (gIsNightly) + Services.prefs.setBoolPref("extensions.checkCompatibility.nightly", true); + else + Services.prefs.setBoolPref("extensions.checkCompatibility.2.1a", true); + restartManager(); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org"], + function([a1, a2, a3, a4, a5]) { + check_state(false, a1, a2, a3, a4, a5); + + do_execute_soon(do_test_finished); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_childprocess.js b/toolkit/mozapps/extensions/test/xpcshell/test_childprocess.js new file mode 100644 index 000000000..a6c635eac --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_childprocess.js @@ -0,0 +1,21 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that the AddonManager refuses to load in child processes. + +function run_test() { + // Already loaded the module by head_addons.js. Need to unload this again, so + // that overriding the app-info and re-importing the module works. + Components.utils.unload("resource://gre/modules/AddonManager.jsm"); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + gAppInfo.processType = AM_Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT; + try { + Components.utils.import("resource://gre/modules/AddonManager.jsm"); + do_throw("AddonManager should have refused to load"); + } + catch (ex) { + do_print(ex.message); + do_check_true(!!ex.message); + } +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_compatoverrides.js b/toolkit/mozapps/extensions/test/xpcshell/test_compatoverrides.js new file mode 100644 index 000000000..ef60306db --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_compatoverrides.js @@ -0,0 +1,259 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Tests compatibility overrides, for when strict compatibility checking is +// disabled. See bug 693906. + + +const PREF_GETADDONS_CACHE_ENABLED = "extensions.getAddons.cache.enabled"; + +Components.utils.import("resource://testing-common/httpd.js"); +var gServer = new HttpServer(); +gServer.start(-1); +gPort = gServer.identity.primaryPort; + +const PORT = gPort; +const BASE_URL = "http://localhost:" + PORT; +const DEFAULT_URL = "about:blank"; +const REQ_URL = "/data.xml"; + +// register static file and mark it for interpolation +mapUrlToFile(REQ_URL, do_get_file("data/test_compatoverrides.xml"), gServer); + +Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false); +Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); +Services.prefs.setCharPref(PREF_GETADDONS_BYIDS_PERFORMANCE, + BASE_URL + REQ_URL); + + +// Not hosted, no overrides +var addon1 = { + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test addon 1", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Hosted, no overrides +var addon2 = { + id: "addon2@tests.mozilla.org", + version: "1.0", + name: "Test addon 2", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Hosted, matching override +var addon3 = { + id: "addon3@tests.mozilla.org", + version: "1.0", + name: "Test addon 3", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Hosted, matching override, wouldn't be compatible if strict checking is enabled +var addon4 = { + id: "addon4@tests.mozilla.org", + version: "1.0", + name: "Test addon 4", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0.1", + maxVersion: "0.2" + }] +}; + +// Hosted, app ID doesn't match in override +var addon5 = { + id: "addon5@tests.mozilla.org", + version: "1.0", + name: "Test addon 5", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Hosted, addon version range doesn't match in override +var addon6 = { + id: "addon6@tests.mozilla.org", + version: "1.0", + name: "Test addon 6", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Hosted, app version range doesn't match in override +var addon7 = { + id: "addon7@tests.mozilla.org", + version: "1.0", + name: "Test addon 7", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Hosted, multiple overrides +var addon8 = { + id: "addon8@tests.mozilla.org", + version: "1.0", + name: "Test addon 8", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Not hosted, matching override +var addon9 = { + id: "addon9@tests.mozilla.org", + version: "1.0", + name: "Test addon 9", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Not hosted, override is of unsupported type (compatible) +var addon10 = { + id: "addon10@tests.mozilla.org", + version: "1.0", + name: "Test addon 10", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "2"); + + writeInstallRDFForExtension(addon1, profileDir); + writeInstallRDFForExtension(addon2, profileDir); + writeInstallRDFForExtension(addon3, profileDir); + writeInstallRDFForExtension(addon4, profileDir); + writeInstallRDFForExtension(addon5, profileDir); + writeInstallRDFForExtension(addon6, profileDir); + writeInstallRDFForExtension(addon7, profileDir); + writeInstallRDFForExtension(addon8, profileDir); + writeInstallRDFForExtension(addon9, profileDir); + writeInstallRDFForExtension(addon10, profileDir); + + startupManager(); + + AddonManagerInternal.backgroundUpdateCheck().then(run_test_1); +} + +function end_test() { + gServer.stop(do_test_finished); +} + +function check_compat_status(aCallback) { + 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", + "addon8@tests.mozilla.org", + "addon9@tests.mozilla.org", + "addon10@tests.mozilla.org"], + function([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10]) { + + do_check_neq(a1, null); + do_check_eq(a1.compatibilityOverrides, null); + do_check_true(a1.isCompatible); + do_check_false(a1.appDisabled); + + do_check_neq(a2, null); + do_check_eq(a2.compatibilityOverrides, null); + do_check_true(a2.isCompatible); + do_check_false(a2.appDisabled); + + do_check_neq(a3, null); + do_check_neq(a3.compatibilityOverrides, null); + do_check_eq(a3.compatibilityOverrides.length, 1); + do_check_false(a3.isCompatible); + do_check_true(a3.appDisabled); + + do_check_neq(a4, null); + do_check_neq(a4.compatibilityOverrides, null); + do_check_eq(a4.compatibilityOverrides.length, 1); + do_check_false(a4.isCompatible); + do_check_true(a4.appDisabled); + + do_check_neq(a5, null); + do_check_eq(a5.compatibilityOverrides, null); + do_check_true(a5.isCompatible); + do_check_false(a5.appDisabled); + + do_check_neq(a6, null); + do_check_neq(a6.compatibilityOverrides, null); + do_check_eq(a6.compatibilityOverrides.length, 1); + do_check_true(a6.isCompatible); + do_check_false(a6.appDisabled); + + do_check_neq(a7, null); + do_check_neq(a7.compatibilityOverrides, null); + do_check_eq(a7.compatibilityOverrides.length, 1); + do_check_true(a7.isCompatible); + do_check_false(a7.appDisabled); + + do_check_neq(a8, null); + do_check_neq(a8.compatibilityOverrides, null); + do_check_eq(a8.compatibilityOverrides.length, 3); + do_check_false(a8.isCompatible); + do_check_true(a8.appDisabled); + + do_check_neq(a9, null); + do_check_neq(a9.compatibilityOverrides, null); + do_check_eq(a9.compatibilityOverrides.length, 1); + do_check_false(a9.isCompatible); + do_check_true(a9.appDisabled); + + do_check_neq(a10, null); + do_check_eq(a10.compatibilityOverrides, null); + do_check_true(a10.isCompatible); + do_check_false(a10.appDisabled); + + do_execute_soon(aCallback); + }); +} + +function run_test_1() { + do_print("Run test 1"); + check_compat_status(run_test_2); +} + +function run_test_2() { + do_print("Run test 2"); + restartManager(); + check_compat_status(end_test); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js b/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js new file mode 100644 index 000000000..4c8b3750d --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.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 + + +Components.utils.import("resource://testing-common/httpd.js"); +// Create and configure the HTTP server. +var testserver = new HttpServer(); +testserver.start(-1); +gPort = testserver.identity.primaryPort; + +// register files with server +testserver.registerDirectory("/addons/", do_get_file("addons")); +mapFile("/data/test_corrupt.rdf", 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, false); + +// 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 stay enabled +var addon3 = { + id: "addon3@tests.mozilla.org", + version: "1.0", + name: "Test 3", + updateURL: "http://localhost:" + gPort + "/data/test_corrupt.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Will get a compatibility update and be enabled +var addon4 = { + id: "addon4@tests.mozilla.org", + version: "1.0", + name: "Test 4", + updateURL: "http://localhost:" + gPort + "/data/test_corrupt.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Would stay incompatible with strict compat +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); + + // 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() { + do_execute_soon(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() { + 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"], + callback_soon(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_true(a5.isActive); + do_check_false(a5.userDisabled); + do_check_false(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); + + // Shutdown and replace the database with a corrupt file (a directory + // serves this purpose). On startup the add-ons manager won't rebuild + // because there is a file there still. + shutdownManager(); + gExtensionsJSON.remove(true); + gExtensionsJSON.create(AM_Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); + startupManager(false); + + // 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"], + callback_soon(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_false(a3.appDisabled); + do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE); + + // 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_true(a4.userDisabled); + do_check_false(a4.appDisabled); + do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a5, null); + do_check_true(a5.isActive); + do_check_false(a5.userDisabled); + do_check_false(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"], + callback_soon(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_true(a5.isActive); + do_check_false(a5.userDisabled); + do_check_false(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_corrupt_strictcompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_corrupt_strictcompat.js new file mode 100644 index 000000000..3ba6d213b --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_corrupt_strictcompat.js @@ -0,0 +1,402 @@ +/* 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 + + +Components.utils.import("resource://testing-common/httpd.js"); +// Create and configure the HTTP server. +var testserver = new HttpServer(); +testserver.start(-1); +gPort = testserver.identity.primaryPort; + +// register files with server +testserver.registerDirectory("/addons/", do_get_file("addons")); +mapFile("/data/test_corrupt.rdf", 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:" + gPort + "/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:" + gPort + "/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); + + // 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() { + do_execute_soon(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() { + 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"], + callback_soon(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); + + // Shutdown and replace the database with a corrupt file (a directory + // serves this purpose). On startup the add-ons manager won't rebuild + // because there is a file there still. + shutdownManager(); + gExtensionsJSON.remove(true); + gExtensionsJSON.create(AM_Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); + startupManager(false); + + // 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"], + callback_soon(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"], + callback_soon(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_corruptfile.js b/toolkit/mozapps/extensions/test/xpcshell/test_corruptfile.js new file mode 100644 index 000000000..92b375850 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_corruptfile.js @@ -0,0 +1,83 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that attempting to install a corrupt XPI file doesn't break the universe + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); + + startupManager(); + + if (TEST_UNPACKED) + run_test_unpacked(); + else + run_test_packed(); +} + +// When installing packed we won't detect corruption in the XPI until we attempt +// to load bootstrap.js so everything will look normal from the outside. +function run_test_packed() { + do_test_pending(); + + prepare_test({ + "corrupt@tests.mozilla.org": [ + ["onInstalling", false], + ["onInstalled", false] + ] + }, [ + "onNewInstall", + "onInstallStarted", + "onInstallEnded" + ]); + + installAllFiles([do_get_file("data/corruptfile.xpi")], function() { + ensure_test_completed(); + + AddonManager.getAddonByID("corrupt@tests.mozilla.org", function(addon) { + do_check_neq(addon, null); + + do_test_finished(); + }); + }); +} + +// When extracting the corruption will be detected and the add-on fails to +// install +function run_test_unpacked() { + do_test_pending(); + + prepare_test({ + "corrupt@tests.mozilla.org": [ + ["onInstalling", false], + "onOperationCancelled" + ] + }, [ + "onNewInstall", + "onInstallStarted", + "onInstallFailed" + ]); + + installAllFiles([do_get_file("data/corruptfile.xpi")], function() { + ensure_test_completed(); + + // Check the add-on directory isn't left over + var addonDir = profileDir.clone(); + addonDir.append("corrupt@tests.mozilla.org"); + pathShouldntExist(addonDir); + + // Check the staging directory isn't left over + var stageDir = profileDir.clone(); + stageDir.append("staged"); + pathShouldntExist(stageDir); + + AddonManager.getAddonByID("corrupt@tests.mozilla.org", function(addon) { + do_check_eq(addon, null); + + do_test_finished(); + }); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_dataDirectory.js b/toolkit/mozapps/extensions/test/xpcshell/test_dataDirectory.js new file mode 100644 index 000000000..99babc722 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_dataDirectory.js @@ -0,0 +1,50 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// Disables security checking our updates which haven't been signed +Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); + +var ADDON = { + id: "datadirectory1@tests.mozilla.org", + addon: "test_data_directory" +}; + +var expectedDir = gProfD.clone(); +expectedDir.append("extension-data"); +expectedDir.append(ADDON.id); + +function run_test() { + do_test_pending(); + do_check_false(expectedDir.exists()); + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "1.9"); + startupManager(); + + installAllFiles([do_get_addon(ADDON.addon)], function() { + restartManager(); + + AddonManager.getAddonByID(ADDON.id, function(item) { + item.getDataDirectory(promise_callback); + }); + }); +} + +function promise_callback() { + do_check_eq(arguments.length, 2); + var expectedDir = gProfD.clone(); + expectedDir.append("extension-data"); + expectedDir.append(ADDON.id); + + do_check_eq(arguments[0], expectedDir.path); + do_check_true(expectedDir.exists()); + do_check_true(expectedDir.isDirectory()); + + do_check_eq(arguments[1], null); + + // Cleanup. + expectedDir.parent.remove(true); + + do_test_finished(); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_default_providers_pref.js b/toolkit/mozapps/extensions/test/xpcshell/test_default_providers_pref.js new file mode 100644 index 000000000..1b61e033a --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_default_providers_pref.js @@ -0,0 +1,13 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Tests the extensions.defaultProviders.enabled pref which turns +// off the default XPIProvider and LightweightThemeManager. + +function run_test() { + Services.prefs.setBoolPref("extensions.defaultProviders.enabled", false); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + startupManager(); + do_check_false(AddonManager.isInstallEnabled("application/x-xpinstall")); + Services.prefs.clearUserPref("extensions.defaultProviders.enabled"); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_dictionary.js b/toolkit/mozapps/extensions/test/xpcshell/test_dictionary.js new file mode 100644 index 000000000..c24b5a1b0 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_dictionary.js @@ -0,0 +1,801 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that bootstrappable add-ons can be used without restarts. +Components.utils.import("resource://gre/modules/Services.jsm"); + +// Enable loading extensions from the user scopes +Services.prefs.setIntPref("extensions.enabledScopes", + AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_USER); + +// The test extension uses an insecure update url. +Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); + +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); +const userExtDir = gProfD.clone(); +userExtDir.append("extensions2"); +userExtDir.append(gAppInfo.ID); +registerDirectory("XREUSysExt", userExtDir.parent); + +Components.utils.import("resource://testing-common/httpd.js"); +// Create and configure the HTTP server. +var testserver = new HttpServer(); +testserver.start(-1); +gPort = testserver.identity.primaryPort; + +// register files with server +testserver.registerDirectory("/addons/", do_get_file("addons")); +mapFile("/data/test_dictionary.rdf", testserver); + +/** + * This object is both a factory and an mozISpellCheckingEngine implementation (so, it + * is de-facto a service). It's also an interface requestor that gives out + * itself when asked for mozISpellCheckingEngine. + */ +var HunspellEngine = { + dictionaryDirs: [], + listener: null, + + QueryInterface: function hunspell_qi(iid) { + if (iid.equals(Components.interfaces.nsISupports) || + iid.equals(Components.interfaces.nsIFactory) || + iid.equals(Components.interfaces.mozISpellCheckingEngine)) + return this; + throw Components.results.NS_ERROR_NO_INTERFACE; + }, + createInstance: function hunspell_ci(outer, iid) { + if (outer) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return this.QueryInterface(iid); + }, + lockFactory: function hunspell_lockf(lock) { + throw Components.results.NS_ERROR_NOT_IMPLEMENTED; + }, + + addDirectory: function hunspell_addDirectory(dir) { + this.dictionaryDirs.push(dir); + if (this.listener) + this.listener("addDirectory"); + }, + + removeDirectory: function hunspell_addDirectory(dir) { + this.dictionaryDirs.splice(this.dictionaryDirs.indexOf(dir), 1); + if (this.listener) + this.listener("removeDirectory"); + }, + + getInterface: function hunspell_gi(iid) { + if (iid.equals(Components.interfaces.mozISpellCheckingEngine)) + return this; + throw Components.results.NS_ERROR_NO_INTERFACE; + }, + + contractID: "@mozilla.org/spellchecker/engine;1", + classID: Components.ID("{6f3c63bc-a4fd-449b-9a58-a2d9bd972cce}"), + + activate: function hunspell_activate() { + this.origClassID = Components.manager.nsIComponentRegistrar + .contractIDToCID(this.contractID); + this.origFactory = Components.manager + .getClassObject(Components.classes[this.contractID], + Components.interfaces.nsIFactory); + + Components.manager.nsIComponentRegistrar + .unregisterFactory(this.origClassID, this.origFactory); + Components.manager.nsIComponentRegistrar.registerFactory(this.classID, + "Test hunspell", this.contractID, this); + }, + + deactivate: function hunspell_deactivate() { + Components.manager.nsIComponentRegistrar.unregisterFactory(this.classID, this); + Components.manager.nsIComponentRegistrar.registerFactory(this.origClassID, + "Hunspell", this.contractID, this.origFactory); + }, + + isDictionaryEnabled: function hunspell_isDictionaryEnabled(name) { + return this.dictionaryDirs.some(function(dir) { + var dic = dir.clone(); + dic.append(name); + return dic.exists(); + }); + } +}; + +function run_test() { + do_test_pending(); + + startupManager(); + + run_test_1(); +} + +// Tests that installing doesn't require a restart +function run_test_1() { + prepare_test({ }, [ + "onNewInstall" + ]); + + HunspellEngine.activate(); + + AddonManager.getInstallForFile(do_get_addon("test_dictionary"), function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + do_check_eq(install.type, "dictionary"); + do_check_eq(install.version, "1.0"); + do_check_eq(install.name, "Test Dictionary"); + do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); + do_check_true(install.addon.hasResource("install.rdf")); + do_check_false(install.addon.hasResource("bootstrap.js")); + do_check_eq(install.addon.operationsRequiringRestart & + AddonManager.OP_NEEDS_RESTART_INSTALL, 0); + do_check_not_in_crash_annotation("ab-CD@dictionaries.addons.mozilla.org", "1.0"); + + let addon = install.addon; + prepare_test({ + "ab-CD@dictionaries.addons.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], function() { + do_check_true(addon.hasResource("install.rdf")); + HunspellEngine.listener = function(aEvent) { + HunspellEngine.listener = null; + do_check_eq(aEvent, "addDirectory"); + do_execute_soon(check_test_1); + }; + }); + install.install(); + }); +} + +function check_test_1() { + AddonManager.getAllInstalls(function(installs) { + // There should be no active installs now since the install completed and + // doesn't require a restart. + do_check_eq(installs.length, 0); + + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_false(b1.appDisabled); + do_check_false(b1.userDisabled); + do_check_true(b1.isActive); + do_check_true(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); + do_check_true(b1.hasResource("install.rdf")); + do_check_false(b1.hasResource("bootstrap.js")); + do_check_in_crash_annotation("ab-CD@dictionaries.addons.mozilla.org", "1.0"); + + let dir = do_get_addon_root_uri(profileDir, "ab-CD@dictionaries.addons.mozilla.org"); + + AddonManager.getAddonsWithOperationsByTypes(null, function(list) { + do_check_eq(list.length, 0); + + run_test_2(); + }); + }); + }); +} + +// Tests that disabling doesn't require a restart +function run_test_2() { + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) { + prepare_test({ + "ab-CD@dictionaries.addons.mozilla.org": [ + ["onDisabling", false], + "onDisabled" + ] + }); + + do_check_eq(b1.operationsRequiringRestart & + AddonManager.OP_NEEDS_RESTART_DISABLE, 0); + b1.userDisabled = true; + ensure_test_completed(); + + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_false(b1.appDisabled); + do_check_true(b1.userDisabled); + do_check_false(b1.isActive); + do_check_false(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); + do_check_not_in_crash_annotation("ab-CD@dictionaries.addons.mozilla.org", "1.0"); + + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(newb1) { + do_check_neq(newb1, null); + do_check_eq(newb1.version, "1.0"); + do_check_false(newb1.appDisabled); + do_check_true(newb1.userDisabled); + do_check_false(newb1.isActive); + + do_execute_soon(run_test_3); + }); + }); +} + +// Test that restarting doesn't accidentally re-enable +function run_test_3() { + shutdownManager(); + do_check_false(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); + startupManager(false); + do_check_false(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); + do_check_not_in_crash_annotation("ab-CD@dictionaries.addons.mozilla.org", "1.0"); + + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_false(b1.appDisabled); + do_check_true(b1.userDisabled); + do_check_false(b1.isActive); + + run_test_4(); + }); +} + +// Tests that enabling doesn't require a restart +function run_test_4() { + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) { + prepare_test({ + "ab-CD@dictionaries.addons.mozilla.org": [ + ["onEnabling", false], + "onEnabled" + ] + }); + + do_check_eq(b1.operationsRequiringRestart & + AddonManager.OP_NEEDS_RESTART_ENABLE, 0); + b1.userDisabled = false; + ensure_test_completed(); + + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_false(b1.appDisabled); + do_check_false(b1.userDisabled); + do_check_true(b1.isActive); + do_check_true(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); + do_check_in_crash_annotation("ab-CD@dictionaries.addons.mozilla.org", "1.0"); + + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(newb1) { + do_check_neq(newb1, null); + do_check_eq(newb1.version, "1.0"); + do_check_false(newb1.appDisabled); + do_check_false(newb1.userDisabled); + do_check_true(newb1.isActive); + + do_execute_soon(run_test_5); + }); + }); +} + +// Tests that a restart shuts down and restarts the add-on +function run_test_5() { + shutdownManager(); + do_check_false(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); + do_check_not_in_crash_annotation("ab-CD@dictionaries.addons.mozilla.org", "1.0"); + startupManager(false); + do_check_true(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); + do_check_in_crash_annotation("ab-CD@dictionaries.addons.mozilla.org", "1.0"); + + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_false(b1.appDisabled); + do_check_false(b1.userDisabled); + do_check_true(b1.isActive); + do_check_false(isExtensionInAddonsList(profileDir, b1.id)); + + run_test_7(); + }); +} + +// Tests that uninstalling doesn't require a restart +function run_test_7() { + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) { + prepare_test({ + "ab-CD@dictionaries.addons.mozilla.org": [ + ["onUninstalling", false], + "onUninstalled" + ] + }); + + do_check_eq(b1.operationsRequiringRestart & + AddonManager.OP_NEEDS_RESTART_UNINSTALL, 0); + b1.uninstall(); + + check_test_7(); + }); +} + +function check_test_7() { + ensure_test_completed(); + do_check_false(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); + do_check_not_in_crash_annotation("ab-CD@dictionaries.addons.mozilla.org", "1.0"); + + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", + callback_soon(function(b1) { + do_check_eq(b1, null); + + restartManager(); + + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(newb1) { + do_check_eq(newb1, null); + + do_execute_soon(run_test_8); + }); + })); +} + +// Test that a bootstrapped extension dropped into the profile loads properly +// on startup and doesn't cause an EM restart +function run_test_8() { + shutdownManager(); + + let dir = profileDir.clone(); + dir.append("ab-CD@dictionaries.addons.mozilla.org"); + dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755); + let zip = AM_Cc["@mozilla.org/libjar/zip-reader;1"]. + createInstance(AM_Ci.nsIZipReader); + zip.open(do_get_addon("test_dictionary")); + dir.append("install.rdf"); + zip.extract("install.rdf", dir); + dir = dir.parent; + dir.append("dictionaries"); + dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755); + dir.append("ab-CD.dic"); + zip.extract("dictionaries/ab-CD.dic", dir); + zip.close(); + + startupManager(false); + + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_false(b1.appDisabled); + do_check_false(b1.userDisabled); + do_check_true(b1.isActive); + do_check_true(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); + do_check_in_crash_annotation("ab-CD@dictionaries.addons.mozilla.org", "1.0"); + + do_execute_soon(run_test_9); + }); +} + +// Test that items detected as removed during startup get removed properly +function run_test_9() { + shutdownManager(); + + let dir = profileDir.clone(); + dir.append("ab-CD@dictionaries.addons.mozilla.org"); + dir.remove(true); + startupManager(false); + + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) { + do_check_eq(b1, null); + do_check_not_in_crash_annotation("ab-CD@dictionaries.addons.mozilla.org", "1.0"); + + do_execute_soon(run_test_12); + }); +} + + +// Tests that bootstrapped extensions are correctly loaded even if the app is +// upgraded at the same time +function run_test_12() { + shutdownManager(); + + let dir = profileDir.clone(); + dir.append("ab-CD@dictionaries.addons.mozilla.org"); + dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755); + let zip = AM_Cc["@mozilla.org/libjar/zip-reader;1"]. + createInstance(AM_Ci.nsIZipReader); + zip.open(do_get_addon("test_dictionary")); + dir.append("install.rdf"); + zip.extract("install.rdf", dir); + dir = dir.parent; + dir.append("dictionaries"); + dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755); + dir.append("ab-CD.dic"); + zip.extract("dictionaries/ab-CD.dic", dir); + zip.close(); + + startupManager(true); + + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_false(b1.appDisabled); + do_check_false(b1.userDisabled); + do_check_true(b1.isActive); + do_check_true(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); + do_check_in_crash_annotation("ab-CD@dictionaries.addons.mozilla.org", "1.0"); + + b1.uninstall(); + do_execute_soon(run_test_16); + }); +} + + +// Tests that bootstrapped extensions don't get loaded when in safe mode +function run_test_16() { + restartManager(); + + installAllFiles([do_get_addon("test_dictionary")], function() { + // spin the event loop to let the addon finish starting + do_execute_soon(function check_installed_dictionary() { + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", + callback_soon(function(b1) { + // Should have installed and started + do_check_true(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); + + shutdownManager(); + + // Should have stopped + do_check_false(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); + + gAppInfo.inSafeMode = true; + startupManager(false); + + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", + callback_soon(function(b1) { + // Should still be stopped + do_check_false(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); + do_check_false(b1.isActive); + + shutdownManager(); + gAppInfo.inSafeMode = false; + startupManager(false); + + // Should have started + do_check_true(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); + + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) { + b1.uninstall(); + + do_execute_soon(run_test_17); + }); + })); + })); + }); + }); +} + +// Check that a bootstrapped extension in a non-profile location is loaded +function run_test_17() { + shutdownManager(); + + let dir = userExtDir.clone(); + dir.append("ab-CD@dictionaries.addons.mozilla.org"); + dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755); + let zip = AM_Cc["@mozilla.org/libjar/zip-reader;1"]. + createInstance(AM_Ci.nsIZipReader); + zip.open(do_get_addon("test_dictionary")); + dir.append("install.rdf"); + zip.extract("install.rdf", dir); + dir = dir.parent; + dir.append("dictionaries"); + dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755); + dir.append("ab-CD.dic"); + zip.extract("dictionaries/ab-CD.dic", dir); + zip.close(); + + startupManager(); + + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", + callback_soon(function(b1) { + // Should have installed and started + do_check_true(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_true(b1.isActive); + + // From run_test_21 + dir = userExtDir.clone(); + dir.append("ab-CD@dictionaries.addons.mozilla.org"); + dir.remove(true); + + restartManager(); + + run_test_23(); + })); +} + +// Tests that installing from a URL doesn't require a restart +function run_test_23() { + prepare_test({ }, [ + "onNewInstall" + ]); + + let url = "http://localhost:" + gPort + "/addons/test_dictionary.xpi"; + AddonManager.getInstallForURL(url, function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + + prepare_test({ }, [ + "onDownloadStarted", + "onDownloadEnded" + ], function() { + do_check_eq(install.type, "dictionary"); + do_check_eq(install.version, "1.0"); + do_check_eq(install.name, "Test Dictionary"); + do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); + do_check_true(install.addon.hasResource("install.rdf")); + do_check_false(install.addon.hasResource("bootstrap.js")); + do_check_eq(install.addon.operationsRequiringRestart & + AddonManager.OP_NEEDS_RESTART_INSTALL, 0); + do_check_not_in_crash_annotation("ab-CD@dictionaries.addons.mozilla.org", "1.0"); + + let addon = install.addon; + prepare_test({ + "ab-CD@dictionaries.addons.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], function() { + do_check_true(addon.hasResource("install.rdf")); + // spin to let the addon startup finish + do_execute_soon(check_test_23); + }); + }); + install.install(); + }, "application/x-xpinstall"); +} + +function check_test_23() { + AddonManager.getAllInstalls(function(installs) { + // There should be no active installs now since the install completed and + // doesn't require a restart. + do_check_eq(installs.length, 0); + + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_false(b1.appDisabled); + do_check_false(b1.userDisabled); + do_check_true(b1.isActive); + do_check_true(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); + do_check_true(b1.hasResource("install.rdf")); + do_check_false(b1.hasResource("bootstrap.js")); + do_check_in_crash_annotation("ab-CD@dictionaries.addons.mozilla.org", "1.0"); + + let dir = do_get_addon_root_uri(profileDir, "ab-CD@dictionaries.addons.mozilla.org"); + + AddonManager.getAddonsWithOperationsByTypes(null, callback_soon(function(list) { + do_check_eq(list.length, 0); + + restartManager(); + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) { + b1.uninstall(); + do_execute_soon(run_test_25); + }); + })); + }); + }); +} + +// Tests that updating from a bootstrappable add-on to a normal add-on calls +// the uninstall method +function run_test_25() { + restartManager(); + + HunspellEngine.listener = function(aEvent) { + HunspellEngine.listener = null; + do_check_eq(aEvent, "addDirectory"); + do_check_true(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); + + installAllFiles([do_get_addon("test_dictionary_2")], function test_25_installed2() { + // Needs a restart to complete this so the old version stays running + do_check_true(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); + + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", + callback_soon(function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_true(b1.isActive); + do_check_true(hasFlag(b1.pendingOperations, AddonManager.PENDING_UPGRADE)); + + restartManager(); + + do_check_false(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); + + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "2.0"); + do_check_true(b1.isActive); + do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE); + + do_execute_soon(run_test_26); + }); + })); + }); + }; + + installAllFiles([do_get_addon("test_dictionary")], function test_25_installed() { }); +} + +// Tests that updating from a normal add-on to a bootstrappable add-on calls +// the install method +function run_test_26() { + installAllFiles([do_get_addon("test_dictionary")], function test_26_install() { + // Needs a restart to complete this + do_check_false(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); + + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", + callback_soon(function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "2.0"); + do_check_true(b1.isActive); + do_check_true(hasFlag(b1.pendingOperations, AddonManager.PENDING_UPGRADE)); + + restartManager(); + + do_check_true(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); + + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_true(b1.isActive); + do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE); + + HunspellEngine.deactivate(); + b1.uninstall(); + do_execute_soon(run_test_27); + }); + })); + }); +} + +// Tests that an update check from a normal add-on to a bootstrappable add-on works +function run_test_27() { + restartManager(); + writeInstallRDFForExtension({ + id: "ab-CD@dictionaries.addons.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_dictionary.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Dictionary", + }, profileDir); + restartManager(); + + prepare_test({ + "ab-CD@dictionaries.addons.mozilla.org": [ + "onInstalling" + ] + }, [ + "onNewInstall", + "onDownloadStarted", + "onDownloadEnded", + "onInstallStarted", + "onInstallEnded" + ], callback_soon(check_test_27)); + + AddonManagerPrivate.backgroundUpdateCheck(); +} + +function check_test_27(install) { + do_check_eq(install.existingAddon.pendingUpgrade.install, install); + + restartManager(); + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "2.0"); + do_check_eq(b1.type, "dictionary"); + b1.uninstall(); + do_execute_soon(run_test_28); + }); +} + +// Tests that an update check from a bootstrappable add-on to a normal add-on works +function run_test_28() { + restartManager(); + + writeInstallRDFForExtension({ + id: "ef@dictionaries.addons.mozilla.org", + version: "1.0", + type: "64", + updateURL: "http://localhost:" + gPort + "/data/test_dictionary.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Dictionary ef", + }, profileDir); + restartManager(); + + prepare_test({ + "ef@dictionaries.addons.mozilla.org": [ + "onInstalling" + ] + }, [ + "onNewInstall", + "onDownloadStarted", + "onDownloadEnded", + "onInstallStarted", + "onInstallEnded" + ], callback_soon(check_test_28)); + + AddonManagerPrivate.backgroundUpdateCheck(); +} + +function check_test_28(install) { + do_check_eq(install.existingAddon.pendingUpgrade.install, install); + + restartManager(); + AddonManager.getAddonByID("ef@dictionaries.addons.mozilla.org", function(b2) { + do_check_neq(b2, null); + do_check_eq(b2.version, "2.0"); + do_check_eq(b2.type, "extension"); + b2.uninstall(); + do_execute_soon(run_test_29); + }); +} + +// Tests that an update check from a bootstrappable add-on to a bootstrappable add-on works +function run_test_29() { + restartManager(); + + writeInstallRDFForExtension({ + id: "gh@dictionaries.addons.mozilla.org", + version: "1.0", + type: "64", + updateURL: "http://localhost:" + gPort + "/data/test_dictionary.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Dictionary gh", + }, profileDir); + restartManager(); + + prepare_test({ + "gh@dictionaries.addons.mozilla.org": [ + ["onInstalling", false /* = no restart */], + ["onInstalled", false] + ] + }, [ + "onNewInstall", + "onDownloadStarted", + "onDownloadEnded", + "onInstallStarted", + "onInstallEnded" + ], check_test_29); + + AddonManagerPrivate.backgroundUpdateCheck(); +} + +function check_test_29(install) { + AddonManager.getAddonByID("gh@dictionaries.addons.mozilla.org", function(b2) { + do_check_neq(b2, null); + do_check_eq(b2.version, "2.0"); + do_check_eq(b2.type, "dictionary"); + + prepare_test({ + "gh@dictionaries.addons.mozilla.org": [ + ["onUninstalling", false], + ["onUninstalled", false], + ] + }, [ + ], callback_soon(finish_test_29)); + + b2.uninstall(); + }); +} + +function finish_test_29() { + testserver.stop(do_test_finished); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_disable.js b/toolkit/mozapps/extensions/test/xpcshell/test_disable.js new file mode 100644 index 000000000..867715863 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_disable.js @@ -0,0 +1,194 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +Components.utils.import("resource://gre/modules/NetUtil.jsm"); + +// This verifies that add-ons can be disabled and enabled. + +var addon1 = { + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + optionsURL: "chrome://foo/content/options.xul", + aboutURL: "chrome://foo/content/about.xul", + iconURL: "chrome://foo/content/icon.png", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +var gIconURL = null; + +// Sets up the profile by installing an add-on. +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + startupManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { + do_check_eq(a1, null); + do_check_not_in_crash_annotation(addon1.id, addon1.version); + + writeInstallRDFForExtension(addon1, profileDir, addon1.id, "icon.png"); + gIconURL = do_get_addon_root_uri(profileDir.clone(), addon1.id) + "icon.png"; + + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(newa1) { + do_check_neq(newa1, null); + do_check_true(newa1.isActive); + do_check_false(newa1.userDisabled); + do_check_eq(newa1.aboutURL, "chrome://foo/content/about.xul"); + do_check_eq(newa1.optionsURL, "chrome://foo/content/options.xul"); + do_check_eq(newa1.iconURL, "chrome://foo/content/icon.png"); + do_check_true(isExtensionInAddonsList(profileDir, newa1.id)); + do_check_true(hasFlag(newa1.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_false(hasFlag(newa1.permissions, AddonManager.PERM_CAN_ENABLE)); + do_check_eq(newa1.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_DISABLE | + AddonManager.OP_NEEDS_RESTART_UNINSTALL); + do_check_in_crash_annotation(addon1.id, addon1.version); + + run_test_1(); + }); + })); +} + +// Disabling an add-on should work +function run_test_1() { + prepare_test({ + "addon1@tests.mozilla.org": [ + "onDisabling" + ] + }); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1.operationsRequiringRestart & + AddonManager.OP_NEEDS_RESTART_DISABLE, 0); + a1.userDisabled = true; + do_check_eq(a1.aboutURL, "chrome://foo/content/about.xul"); + do_check_eq(a1.optionsURL, "chrome://foo/content/options.xul"); + do_check_eq(a1.iconURL, "chrome://foo/content/icon.png"); + do_check_false(hasFlag(a1.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_true(hasFlag(a1.permissions, AddonManager.PERM_CAN_ENABLE)); + do_check_eq(a1.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_DISABLE | + AddonManager.OP_NEEDS_RESTART_UNINSTALL); + do_check_in_crash_annotation(addon1.id, addon1.version); + + ensure_test_completed(); + + AddonManager.getAddonsWithOperationsByTypes(null, callback_soon(function(list) { + do_check_eq(list.length, 1); + do_check_eq(list[0].id, "addon1@tests.mozilla.org"); + + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(newa1) { + do_check_neq(newa1, null); + do_check_false(newa1.isActive); + do_check_true(newa1.userDisabled); + do_check_eq(newa1.aboutURL, null); + do_check_eq(newa1.optionsURL, null); + do_check_eq(newa1.iconURL, gIconURL); + do_check_false(isExtensionInAddonsList(profileDir, newa1.id)); + do_check_false(hasFlag(newa1.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_true(hasFlag(newa1.permissions, AddonManager.PERM_CAN_ENABLE)); + do_check_eq(newa1.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_ENABLE); + do_check_not_in_crash_annotation(addon1.id, addon1.version); + + run_test_2(); + }); + })); + }); +} + +// Enabling an add-on should work. +function run_test_2() { + prepare_test({ + "addon1@tests.mozilla.org": [ + "onEnabling" + ] + }); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + a1.userDisabled = false; + do_check_eq(a1.aboutURL, null); + do_check_eq(a1.optionsURL, null); + do_check_eq(a1.iconURL, gIconURL); + do_check_true(hasFlag(a1.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_false(hasFlag(a1.permissions, AddonManager.PERM_CAN_ENABLE)); + do_check_eq(a1.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_ENABLE); + + ensure_test_completed(); + + AddonManager.getAddonsWithOperationsByTypes(null, callback_soon(function(list) { + do_check_eq(list.length, 1); + do_check_eq(list[0].id, "addon1@tests.mozilla.org"); + + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(newa1) { + do_check_neq(newa1, null); + do_check_true(newa1.isActive); + do_check_false(newa1.userDisabled); + do_check_eq(newa1.aboutURL, "chrome://foo/content/about.xul"); + do_check_eq(newa1.optionsURL, "chrome://foo/content/options.xul"); + do_check_eq(newa1.iconURL, "chrome://foo/content/icon.png"); + do_check_true(isExtensionInAddonsList(profileDir, newa1.id)); + do_check_true(hasFlag(newa1.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_false(hasFlag(newa1.permissions, AddonManager.PERM_CAN_ENABLE)); + do_check_eq(newa1.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_DISABLE | + AddonManager.OP_NEEDS_RESTART_UNINSTALL); + do_check_in_crash_annotation(addon1.id, addon1.version); + + run_test_3(); + }); + })); + }); +} + +// Disabling then enabling without restart should fire onOperationCancelled. +function run_test_3() { + prepare_test({ + "addon1@tests.mozilla.org": [ + "onDisabling" + ] + }); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { + a1.userDisabled = true; + ensure_test_completed(); + prepare_test({ + "addon1@tests.mozilla.org": [ + "onOperationCancelled" + ] + }); + a1.userDisabled = false; + do_check_true(hasFlag(a1.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_false(hasFlag(a1.permissions, AddonManager.PERM_CAN_ENABLE)); + + ensure_test_completed(); + + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(newa1) { + do_check_neq(newa1, null); + do_check_true(newa1.isActive); + do_check_false(newa1.userDisabled); + do_check_eq(newa1.aboutURL, "chrome://foo/content/about.xul"); + do_check_eq(newa1.optionsURL, "chrome://foo/content/options.xul"); + do_check_eq(newa1.iconURL, "chrome://foo/content/icon.png"); + do_check_true(isExtensionInAddonsList(profileDir, newa1.id)); + do_check_true(hasFlag(newa1.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_false(hasFlag(newa1.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_execute_soon(do_test_finished); + }); + })); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_distribution.js b/toolkit/mozapps/extensions/test/xpcshell/test_distribution.js new file mode 100644 index 000000000..9f5bfacca --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_distribution.js @@ -0,0 +1,262 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that add-ons distributed with the application get installed +// correctly + +// Allow distributed add-ons to install +Services.prefs.setBoolPref("extensions.installDistroAddons", true); + +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); +const distroDir = gProfD.clone(); +distroDir.append("distribution"); +distroDir.append("extensions"); +registerDirectory("XREAppDist", distroDir.parent); + +var addon1_1 = { + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test version 1", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "5" + }] +}; + +var addon1_2 = { + id: "addon1@tests.mozilla.org", + version: "2.0", + name: "Test version 2", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "5" + }] +}; + +var addon1_3 = { + id: "addon1@tests.mozilla.org", + version: "3.0", + name: "Test version 3", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "5" + }] +}; + +function getActiveVersion() { + return Services.prefs.getIntPref("bootstraptest.active_version"); +} + +function getInstalledVersion() { + return Services.prefs.getIntPref("bootstraptest.installed_version"); +} + +function setOldModificationTime() { + // Make sure the installed extension has an old modification time so any + // changes will be detected + shutdownManager() + let extension = gProfD.clone(); + extension.append("extensions"); + if (Services.prefs.getBoolPref("extensions.alwaysUnpack")) + extension.append("addon1@tests.mozilla.org"); + else + extension.append("addon1@tests.mozilla.org.xpi"); + setExtensionModifiedTime(extension, Date.now - 10000); + startupManager(false); +} + +function run_test() { + do_test_pending(); + + run_test_1(); +} + +// Tests that on the first startup the add-on gets installed +function run_test_1() { + writeInstallRDFForExtension(addon1_1, distroDir); + + startupManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "1.0"); + do_check_true(a1.isActive); + do_check_eq(a1.scope, AddonManager.SCOPE_PROFILE); + do_check_false(a1.foreignInstall); + + do_execute_soon(run_test_2); + }); +} + +// Tests that starting with a newer version in the distribution dir doesn't +// install it yet +function run_test_2() { + setOldModificationTime(); + + writeInstallRDFForExtension(addon1_2, distroDir); + + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "1.0"); + do_check_true(a1.isActive); + do_check_eq(a1.scope, AddonManager.SCOPE_PROFILE); + + do_execute_soon(run_test_3); + }); +} + +// Test that an app upgrade installs the newer version +function run_test_3() { + restartManager("2"); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "2.0"); + do_check_true(a1.isActive); + do_check_eq(a1.scope, AddonManager.SCOPE_PROFILE); + do_check_false(a1.foreignInstall); + + do_execute_soon(run_test_4); + }); +} + +// Test that an app upgrade doesn't downgrade the extension +function run_test_4() { + setOldModificationTime(); + + writeInstallRDFForExtension(addon1_1, distroDir); + + restartManager("3"); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "2.0"); + do_check_true(a1.isActive); + do_check_eq(a1.scope, AddonManager.SCOPE_PROFILE); + + do_execute_soon(run_test_5); + }); +} + +// Tests that after uninstalling a restart doesn't re-install the extension +function run_test_5() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { + a1.uninstall(); + + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_eq(a1, null); + + do_execute_soon(run_test_6); + }); + })); +} + +// Tests that upgrading the application still doesn't re-install the uninstalled +// extension +function run_test_6() { + restartManager("4"); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_eq(a1, null); + + do_execute_soon(run_test_7); + }); +} + +// Tests that a pending install of a newer version of a distributed add-on +// at app change still gets applied +function run_test_7() { + Services.prefs.clearUserPref("extensions.installedDistroAddon.addon1@tests.mozilla.org"); + + installAllFiles([do_get_addon("test_distribution1_2")], function() { + restartManager(2); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "2.0"); + do_check_true(a1.isActive); + do_check_eq(a1.scope, AddonManager.SCOPE_PROFILE); + + a1.uninstall(); + do_execute_soon(run_test_8); + }); + }); +} + +// Tests that a pending install of a older version of a distributed add-on +// at app change gets replaced by the distributed version +function run_test_8() { + restartManager(); + + writeInstallRDFForExtension(addon1_3, distroDir); + + installAllFiles([do_get_addon("test_distribution1_2")], function() { + restartManager(3); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "3.0"); + do_check_true(a1.isActive); + do_check_eq(a1.scope, AddonManager.SCOPE_PROFILE); + + a1.uninstall(); + do_execute_soon(run_test_9); + }); + }); +} + +// Tests that bootstrapped add-ons distributed start up correctly, also that +// add-ons with multiple directories get copied fully +function run_test_9() { + restartManager(); + + // Copy the test add-on to the distro dir + let addon = do_get_file("data/test_distribution2_2"); + addon.copyTo(distroDir, "addon2@tests.mozilla.org"); + + restartManager("5"); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_neq(a2, null); + do_check_true(a2.isActive); + + do_check_eq(getInstalledVersion(), 2); + do_check_eq(getActiveVersion(), 2); + + do_check_true(a2.hasResource("bootstrap.js")); + do_check_true(a2.hasResource("subdir/dummy.txt")); + do_check_true(a2.hasResource("subdir/subdir2/dummy2.txt")); + + // Currently installs are unpacked if the source is a directory regardless + // of the install.rdf property or the global preference + + let addonDir = profileDir.clone(); + addonDir.append("addon2@tests.mozilla.org"); + do_check_true(addonDir.exists()); + do_check_true(addonDir.isDirectory()); + addonDir.append("subdir"); + do_check_true(addonDir.exists()); + do_check_true(addonDir.isDirectory()); + addonDir.append("subdir2"); + do_check_true(addonDir.exists()); + do_check_true(addonDir.isDirectory()); + addonDir.append("dummy2.txt"); + do_check_true(addonDir.exists()); + do_check_true(addonDir.isFile()); + + a2.uninstall(); + + do_execute_soon(do_test_finished); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_dss.js b/toolkit/mozapps/extensions/test/xpcshell/test_dss.js new file mode 100644 index 000000000..7b171212a --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_dss.js @@ -0,0 +1,824 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +Components.utils.import("resource://gre/modules/NetUtil.jsm"); + +// using a dynamic port in the addon metadata +Components.utils.import("resource://testing-common/httpd.js"); +let gServer = new HttpServer(); +gServer.start(-1); +gPort = gServer.identity.primaryPort; + +// This verifies that themes behave as expected + +const PREF_GENERAL_SKINS_SELECTEDSKIN = "general.skins.selectedSkin"; +const PREF_EXTENSIONS_DSS_ENABLED = "extensions.dss.enabled"; + +Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm"); + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +// Observer to ensure a "lightweight-theme-styling-update" notification is sent +// when expected +var gLWThemeChanged = false; +var LightweightThemeObserver = { + observe: function(aSubject, aTopic, aData) { + if (aTopic != "lightweight-theme-styling-update") + return; + + gLWThemeChanged = true; + } +}; + +AM_Cc["@mozilla.org/observer-service;1"] + .getService(Components.interfaces.nsIObserverService) + .addObserver(LightweightThemeObserver, "lightweight-theme-styling-update", false); + + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + Services.prefs.setCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN, "theme1/1.0"); + Services.prefs.setBoolPref(PREF_EXTENSIONS_DSS_ENABLED, true); + writeInstallRDFForExtension({ + id: "theme1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + type: 4, + internalName: "theme1/1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }] + }, profileDir); + + writeInstallRDFForExtension({ + id: "theme2@tests.mozilla.org", + version: "1.0", + name: "Test 1", + internalName: "theme2/1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }] + }, profileDir); + + // We need a default theme for some of these things to work but we have hidden + // the one in the application directory. + writeInstallRDFForExtension({ + id: "default@tests.mozilla.org", + version: "1.0", + name: "Default", + internalName: "classic/1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }] + }, profileDir); + + startupManager(); + // Make sure we only register once despite multiple calls + AddonManager.addInstallListener(InstallListener); + AddonManager.addAddonListener(AddonListener); + AddonManager.addInstallListener(InstallListener); + AddonManager.addAddonListener(AddonListener); + AddonManager.addInstallListener(InstallListener); + + AddonManager.getAddonsByIDs(["theme1@tests.mozilla.org", + "theme2@tests.mozilla.org"], function([t1, t2]) { + do_check_neq(t1, null); + do_check_false(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_true(t1.isActive); + do_check_eq(t1.screenshots, null); + do_check_true(isThemeInAddonsList(profileDir, t1.id)); + do_check_false(hasFlag(t1.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_false(hasFlag(t1.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_check_neq(t2, null); + do_check_true(t2.userDisabled); + do_check_false(t2.appDisabled); + do_check_false(t2.isActive); + do_check_eq(t2.screenshots, null); + do_check_true(isThemeInAddonsList(profileDir, t2.id)); + do_check_false(hasFlag(t2.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_true(hasFlag(t2.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_execute_soon(run_test_1); + }); +} + +function end_test() { + do_execute_soon(do_test_finished); +} + +// Checks enabling one theme disables the others +function run_test_1() { + prepare_test({ + "theme1@tests.mozilla.org": [ + ["onDisabling", false], + "onDisabled" + ], + "theme2@tests.mozilla.org": [ + ["onEnabling", false], + "onEnabled" + ] + }); + AddonManager.getAddonsByIDs(["theme1@tests.mozilla.org", + "theme2@tests.mozilla.org"], function([t1, t2]) { + t2.userDisabled = false; + + ensure_test_completed(); + do_check_false(hasFlag(t2.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_false(hasFlag(t2.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_check_true(t1.userDisabled); + do_check_false(hasFlag(t1.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_true(hasFlag(t1.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_execute_soon(check_test_1); + }); +} + +function check_test_1() { + restartManager(); + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "theme2/1.0"); + + AddonManager.getAddonsByIDs(["theme1@tests.mozilla.org", + "theme2@tests.mozilla.org"], function([t1, t2]) { + do_check_neq(t1, null); + do_check_true(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_false(t1.isActive); + do_check_true(isThemeInAddonsList(profileDir, t1.id)); + do_check_false(hasFlag(t1.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_true(hasFlag(t1.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_check_neq(t2, null); + do_check_false(t2.userDisabled); + do_check_false(t2.appDisabled); + do_check_true(t2.isActive); + do_check_true(isThemeInAddonsList(profileDir, t2.id)); + do_check_false(hasFlag(t2.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_false(hasFlag(t2.permissions, AddonManager.PERM_CAN_ENABLE)); + do_check_false(gLWThemeChanged); + + do_execute_soon(run_test_2); + }); +} + +// Removing the active theme should fall back to the default (not ideal in this +// case since we don't have the default theme installed) +function run_test_2() { + var dest = profileDir.clone(); + dest.append(do_get_expected_addon_name("theme2@tests.mozilla.org")); + dest.remove(true); + + restartManager(); + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); + + AddonManager.getAddonsByIDs(["theme1@tests.mozilla.org", + "theme2@tests.mozilla.org"], function([t1, t2]) { + do_check_neq(t1, null); + do_check_true(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_false(t1.isActive); + do_check_true(isThemeInAddonsList(profileDir, t1.id)); + do_check_false(hasFlag(t1.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_true(hasFlag(t1.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_check_eq(t2, null); + do_check_false(isThemeInAddonsList(profileDir, "theme2@tests.mozilla.org")); + do_check_false(gLWThemeChanged); + + do_execute_soon(run_test_3); + }); +} + +// Installing a lightweight theme should happen instantly and disable the default theme +function run_test_3() { + writeInstallRDFForExtension({ + id: "theme2@tests.mozilla.org", + version: "1.0", + name: "Test 1", + internalName: "theme2/1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }] + }, profileDir); + restartManager(); + + prepare_test({ + "1@personas.mozilla.org": [ + ["onInstalling", false], + "onInstalled", + ["onEnabling", false], + "onEnabled" + ], + "default@tests.mozilla.org": [ + ["onDisabling", false], + "onDisabled", + ] + }, [ + "onExternalInstall" + ]); + + LightweightThemeManager.currentTheme = { + id: "1", + version: "1", + name: "Test LW Theme", + description: "A test theme", + author: "Mozilla", + homepageURL: "http://localhost:" + gPort + "/data/index.html", + headerURL: "http://localhost:" + gPort + "/data/header.png", + footerURL: "http://localhost:" + gPort + "/data/footer.png", + previewURL: "http://localhost:" + gPort + "/data/preview.png", + iconURL: "http://localhost:" + gPort + "/data/icon.png" + }; + + ensure_test_completed(); + + AddonManager.getAddonByID("1@personas.mozilla.org", function(p1) { + do_check_neq(null, p1); + do_check_eq(p1.name, "Test LW Theme"); + do_check_eq(p1.version, "1"); + do_check_eq(p1.type, "theme"); + do_check_eq(p1.description, "A test theme"); + do_check_eq(p1.creator, "Mozilla"); + do_check_eq(p1.homepageURL, "http://localhost:" + gPort + "/data/index.html"); + do_check_eq(p1.iconURL, "http://localhost:" + gPort + "/data/icon.png"); + do_check_eq(p1.screenshots.length, 1); + do_check_eq(p1.screenshots[0], "http://localhost:" + gPort + "/data/preview.png"); + do_check_false(p1.appDisabled); + do_check_false(p1.userDisabled); + do_check_true(p1.isCompatible); + do_check_true(p1.providesUpdatesSecurely); + do_check_eq(p1.blocklistState, 0); + do_check_true(p1.isActive); + do_check_eq(p1.pendingOperations, 0); + do_check_eq(p1.permissions, AddonManager.PERM_CAN_UNINSTALL | AddonManager.PERM_CAN_DISABLE); + do_check_eq(p1.scope, AddonManager.SCOPE_PROFILE); + do_check_true("isCompatibleWith" in p1); + do_check_true("findUpdates" in p1); + + AddonManager.getAddonsByTypes(["theme"], function(addons) { + let seen = false; + addons.forEach(function(a) { + if (a.id == "1@personas.mozilla.org") { + seen = true; + } + else { + dump("Checking theme " + a.id + "\n"); + do_check_false(a.isActive); + do_check_true(a.userDisabled); + } + }); + do_check_true(seen); + + do_check_true(gLWThemeChanged); + gLWThemeChanged = false; + + do_execute_soon(run_test_4); + }); + }); +} + +// Installing a second lightweight theme should disable the first with no restart +function run_test_4() { + prepare_test({ + "1@personas.mozilla.org": [ + ["onDisabling", false], + "onDisabled", + ], + "2@personas.mozilla.org": [ + ["onInstalling", false], + "onInstalled", + ["onEnabling", false], + "onEnabled" + ] + }, [ + "onExternalInstall" + ]); + + LightweightThemeManager.currentTheme = { + id: "2", + version: "1", + name: "Test LW Theme", + description: "A second test theme", + author: "Mozilla", + homepageURL: "http://localhost:" + gPort + "/data/index.html", + headerURL: "http://localhost:" + gPort + "/data/header.png", + footerURL: "http://localhost:" + gPort + "/data/footer.png", + previewURL: "http://localhost:" + gPort + "/data/preview.png", + iconURL: "http://localhost:" + gPort + "/data/icon.png" + }; + + ensure_test_completed(); + + AddonManager.getAddonsByIDs(["1@personas.mozilla.org", + "2@personas.mozilla.org"], function([p1, p2]) { + do_check_neq(null, p2); + do_check_false(p2.appDisabled); + do_check_false(p2.userDisabled); + do_check_true(p2.isActive); + do_check_eq(p2.pendingOperations, 0); + do_check_eq(p2.permissions, AddonManager.PERM_CAN_UNINSTALL | AddonManager.PERM_CAN_DISABLE); + + do_check_neq(null, p1); + do_check_false(p1.appDisabled); + do_check_true(p1.userDisabled); + do_check_false(p1.isActive); + do_check_eq(p1.pendingOperations, 0); + do_check_eq(p1.permissions, AddonManager.PERM_CAN_UNINSTALL | AddonManager.PERM_CAN_ENABLE); + + AddonManager.getAddonsByTypes(["theme"], function(addons) { + let seen = false; + addons.forEach(function(a) { + if (a.id == "2@personas.mozilla.org") { + seen = true; + } + else { + dump("Checking theme " + a.id + "\n"); + do_check_false(a.isActive); + do_check_true(a.userDisabled); + } + }); + do_check_true(seen); + + do_check_true(gLWThemeChanged); + gLWThemeChanged = false; + + do_execute_soon(run_test_5); + }); + }); +} + +// Switching to a custom theme should disable the lightweight theme and require +// a restart. Cancelling that should also be possible. +function run_test_5() { + prepare_test({ + "2@personas.mozilla.org": [ + ["onDisabling", false], + "onDisabled" + ], + "theme2@tests.mozilla.org": [ + ["onEnabling", false], + "onEnabled" + ] + }); + + AddonManager.getAddonsByIDs(["2@personas.mozilla.org", + "theme2@tests.mozilla.org"], function([p2, t2]) { + t2.userDisabled = false; + + ensure_test_completed(); + + prepare_test({ + "2@personas.mozilla.org": [ + "onEnabling" + ], + "theme2@tests.mozilla.org": [ + ["onDisabling", false], + "onDisabled" + ] + }); + + p2.userDisabled = false; + + ensure_test_completed(); + + prepare_test({ + "2@personas.mozilla.org": [ + ["onOperationCancelled", true] + ], + "theme2@tests.mozilla.org": [ + ["onEnabling", false], + "onEnabled" + ] + }); + + t2.userDisabled = false; + + ensure_test_completed(); + + do_check_true(t2.isActive); + do_check_false(t2.userDisabled); + do_check_false(hasFlag(AddonManager.PENDING_ENABLE, t2.pendingOperations)); + do_check_false(p2.isActive); + do_check_true(p2.userDisabled); + do_check_false(hasFlag(AddonManager.PENDING_DISABLE, p2.pendingOperations)); + do_check_true(hasFlag(AddonManager.PERM_CAN_ENABLE, p2.permissions)); + do_check_true(gLWThemeChanged); + + do_execute_soon(check_test_5); + }); +} + +function check_test_5() { + restartManager(); + + AddonManager.getAddonsByIDs(["2@personas.mozilla.org", + "theme2@tests.mozilla.org"], function([p2, t2]) { + do_check_true(t2.isActive); + do_check_false(t2.userDisabled); + do_check_false(hasFlag(AddonManager.PENDING_ENABLE, t2.pendingOperations)); + do_check_false(p2.isActive); + do_check_true(p2.userDisabled); + do_check_false(hasFlag(AddonManager.PENDING_DISABLE, p2.pendingOperations)); + + do_check_true(gLWThemeChanged); + gLWThemeChanged = false; + + do_execute_soon(run_test_6); + }); +} + +// Switching from a custom theme to a lightweight theme should require a restart +function run_test_6() { + prepare_test({ + "2@personas.mozilla.org": [ + "onEnabling", + ], + "theme2@tests.mozilla.org": [ + ["onDisabling", false], + "onDisabled" + ] + }); + + AddonManager.getAddonsByIDs(["2@personas.mozilla.org", + "theme2@tests.mozilla.org"], function([p2, t2]) { + p2.userDisabled = false; + + ensure_test_completed(); + + prepare_test({ + "2@personas.mozilla.org": [ + "onOperationCancelled", + ], + "theme2@tests.mozilla.org": [ + ["onEnabling", false], + "onEnabled" + ] + }); + + t2.userDisabled = false; + + ensure_test_completed(); + + prepare_test({ + "2@personas.mozilla.org": [ + "onEnabling", + ], + "theme2@tests.mozilla.org": [ + ["onDisabling", false], + "onDisabled" + ] + }); + + p2.userDisabled = false; + + ensure_test_completed(); + + do_check_false(p2.isActive); + do_check_false(p2.userDisabled); + do_check_true(hasFlag(AddonManager.PENDING_ENABLE, p2.pendingOperations)); + do_check_false(t2.isActive); + do_check_true(t2.userDisabled); + do_check_false(hasFlag(AddonManager.PENDING_DISABLE, t2.pendingOperations)); + do_check_false(gLWThemeChanged); + + do_execute_soon(check_test_6); + }); +} + +function check_test_6() { + restartManager(); + + AddonManager.getAddonsByIDs(["2@personas.mozilla.org", + "theme2@tests.mozilla.org"], function([p2, t2]) { + do_check_true(p2.isActive); + do_check_false(p2.userDisabled); + do_check_false(hasFlag(AddonManager.PENDING_ENABLE, p2.pendingOperations)); + do_check_false(t2.isActive); + do_check_true(t2.userDisabled); + do_check_false(hasFlag(AddonManager.PENDING_DISABLE, t2.pendingOperations)); + + do_check_true(gLWThemeChanged); + gLWThemeChanged = false; + + do_execute_soon(run_test_7); + }); +} + +// Uninstalling a lightweight theme should not require a restart +function run_test_7() { + prepare_test({ + "1@personas.mozilla.org": [ + ["onUninstalling", false], + "onUninstalled" + ] + }); + + AddonManager.getAddonByID("1@personas.mozilla.org", function(p1) { + p1.uninstall(); + + ensure_test_completed(); + do_check_eq(LightweightThemeManager.usedThemes.length, 1); + do_check_false(gLWThemeChanged); + + do_execute_soon(run_test_8); + }); +} + +// Uninstalling a lightweight theme in use should not require a restart and it +// should reactivate the default theme +// Also, uninstalling a lightweight theme in use should send a +// "lightweight-theme-styling-update" notification through the observer service +function run_test_8() { + prepare_test({ + "2@personas.mozilla.org": [ + ["onUninstalling", false], + "onUninstalled" + ], + "default@tests.mozilla.org": [ + ["onEnabling", false], + "onEnabled" + ] + }); + + AddonManager.getAddonByID("2@personas.mozilla.org", function(p2) { + p2.uninstall(); + + ensure_test_completed(); + do_check_eq(LightweightThemeManager.usedThemes.length, 0); + + do_check_true(gLWThemeChanged); + gLWThemeChanged = false; + + do_execute_soon(run_test_9); + }); +} + +// Uninstalling a theme not in use should not require a restart +function run_test_9() { + AddonManager.getAddonByID("theme1@tests.mozilla.org", function(t1) { + prepare_test({ + "theme1@tests.mozilla.org": [ + ["onUninstalling", false], + "onUninstalled" + ] + }); + + t1.uninstall(); + + ensure_test_completed(); + + AddonManager.getAddonByID("theme1@tests.mozilla.org", function(newt1) { + do_check_eq(newt1, null); + do_check_false(gLWThemeChanged); + + do_execute_soon(run_test_10); + }); + }); +} + +// Uninstalling a custom theme in use should require a restart +function run_test_10() { + AddonManager.getAddonByID("theme2@tests.mozilla.org", callback_soon(function(oldt2) { + prepare_test({ + "theme2@tests.mozilla.org": [ + ["onEnabling", false], + "onEnabled" + ], + "default@tests.mozilla.org": [ + ["onDisabling", false], + "onDisabled" + ] + }); + + oldt2.userDisabled = false; + + ensure_test_completed(); + + restartManager(); + + AddonManager.getAddonsByIDs(["default@tests.mozilla.org", + "theme2@tests.mozilla.org"], + callback_soon(function([d, t2]) { + do_check_true(t2.isActive); + do_check_false(t2.userDisabled); + do_check_false(t2.appDisabled); + do_check_false(d.isActive); + do_check_true(d.userDisabled); + do_check_false(d.appDisabled); + + prepare_test({ + "theme2@tests.mozilla.org": [ + ["onUninstalling", false], + "onUninstalled" + ], + "default@tests.mozilla.org": [ + ["onEnabling", false], + "onEnabled" + ] + }); + + t2.uninstall(); + + ensure_test_completed(); + do_check_false(gLWThemeChanged); + + restartManager(); + + do_execute_soon(run_test_11); + })); + })); +} + +// Installing a custom theme not in use should not require a restart +function run_test_11() { + prepare_test({ }, [ + "onNewInstall" + ]); + + AddonManager.getInstallForFile(do_get_addon("test_theme"), function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + do_check_eq(install.type, "theme"); + do_check_eq(install.version, "1.0"); + do_check_eq(install.name, "Test Theme 1"); + do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); + + prepare_test({ + "theme1@tests.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], callback_soon(check_test_11)); + install.install(); + }); +} + +function check_test_11() { + restartManager(); + AddonManager.getAddonByID("theme1@tests.mozilla.org", function(t1) { + do_check_neq(t1, null); + var previewSpec = do_get_addon_root_uri(profileDir, "theme1@tests.mozilla.org") + "preview.png"; + do_check_eq(t1.screenshots.length, 1); + do_check_eq(t1.screenshots[0], previewSpec); + do_check_false(gLWThemeChanged); + + do_execute_soon(run_test_12); + }); +} + +// Updating a custom theme not in use should not require a restart +function run_test_12() { + prepare_test({ }, [ + "onNewInstall" + ]); + + AddonManager.getInstallForFile(do_get_addon("test_theme"), function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + do_check_eq(install.type, "theme"); + do_check_eq(install.version, "1.0"); + do_check_eq(install.name, "Test Theme 1"); + do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); + + prepare_test({ + "theme1@tests.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], check_test_12); + install.install(); + }); +} + +function check_test_12() { + AddonManager.getAddonByID("theme1@tests.mozilla.org", function(t1) { + do_check_neq(t1, null); + do_check_false(gLWThemeChanged); + + do_execute_soon(run_test_13); + }); +} + +// Updating a custom theme in use should require a restart +function run_test_13() { + AddonManager.getAddonByID("theme1@tests.mozilla.org", callback_soon(function(t1) { + prepare_test({ + "theme1@tests.mozilla.org": [ + ["onEnabling", false], + "onEnabled" + ], + "default@tests.mozilla.org": [ + ["onDisabling", false], + "onDisabled" + ] + }); + + t1.userDisabled = false; + ensure_test_completed(); + restartManager(); + + prepare_test({ }, [ + "onNewInstall" + ]); + + AddonManager.getInstallForFile(do_get_addon("test_theme"), function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + do_check_eq(install.type, "theme"); + do_check_eq(install.version, "1.0"); + do_check_eq(install.name, "Test Theme 1"); + do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); + + prepare_test({ + "theme1@tests.mozilla.org": [ + "onInstalling", + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], callback_soon(check_test_13)); + install.install(); + }); + })); +} + +function check_test_13() { + restartManager(); + + AddonManager.getAddonByID("theme1@tests.mozilla.org", function(t1) { + do_check_neq(t1, null); + do_check_true(t1.isActive); + do_check_false(gLWThemeChanged); + t1.uninstall(); + + do_execute_soon(run_test_14); + }); +} + +// Switching from a lightweight theme to the default theme should not require +// a restart +function run_test_14() { + restartManager(); + LightweightThemeManager.currentTheme = { + id: "1", + version: "1", + name: "Test LW Theme", + description: "A test theme", + author: "Mozilla", + homepageURL: "http://localhost:" + gPort + "/data/index.html", + headerURL: "http://localhost:" + gPort + "/data/header.png", + footerURL: "http://localhost:" + gPort + "/data/footer.png", + previewURL: "http://localhost:" + gPort + "/data/preview.png", + iconURL: "http://localhost:" + gPort + "/data/icon.png" + }; + + AddonManager.getAddonByID("default@tests.mozilla.org", function(d) { + do_check_true(d.userDisabled); + do_check_false(d.isActive); + + prepare_test({ + "1@personas.mozilla.org": [ + ["onDisabling", false], + "onDisabled" + ], + "default@tests.mozilla.org": [ + ["onEnabling", false], + "onEnabled" + ] + }); + + d.userDisabled = false; + ensure_test_completed(); + + do_check_false(d.userDisabled); + do_check_true(d.isActive); + + do_check_true(gLWThemeChanged); + gLWThemeChanged = false; + + end_test(); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_duplicateplugins.js b/toolkit/mozapps/extensions/test/xpcshell/test_duplicateplugins.js new file mode 100644 index 000000000..bad560306 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_duplicateplugins.js @@ -0,0 +1,185 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +const Ci = Components.interfaces; + +// This verifies that duplicate plugins are coalesced and maintain their ID +// across restarts. + +var PLUGINS = [{ + name: "Duplicate Plugin 1", + description: "A duplicate plugin", + version: "1", + blocklisted: false, + enabledState: Ci.nsIPluginTag.STATE_ENABLED, + get disabled() this.enabledState == Ci.nsIPluginTag.STATE_DISABLED, + filename: "/home/mozilla/.plugins/dupplugin1.so" +}, { + name: "Duplicate Plugin 1", + description: "A duplicate plugin", + version: "1", + blocklisted: false, + enabledState: Ci.nsIPluginTag.STATE_ENABLED, + get disabled() this.enabledState == Ci.nsIPluginTag.STATE_DISABLED, + filename: "", + filename: "/usr/lib/plugins/dupplugin1.so" +}, { + name: "Duplicate Plugin 2", + description: "Another duplicate plugin", + version: "1", + blocklisted: false, + enabledState: Ci.nsIPluginTag.STATE_ENABLED, + get disabled() this.enabledState == Ci.nsIPluginTag.STATE_DISABLED, + filename: "/home/mozilla/.plugins/dupplugin2.so" +}, { + name: "Duplicate Plugin 2", + description: "Another duplicate plugin", + version: "1", + blocklisted: false, + enabledState: Ci.nsIPluginTag.STATE_ENABLED, + get disabled() this.enabledState == Ci.nsIPluginTag.STATE_DISABLED, + filename: "", + filename: "/usr/lib/plugins/dupplugin2.so" +}, { + name: "Non-duplicate Plugin", // 3 + description: "Not a duplicate plugin", + version: "1", + blocklisted: false, + enabledState: Ci.nsIPluginTag.STATE_ENABLED, + get disabled() this.enabledState == Ci.nsIPluginTag.STATE_DISABLED, + filename: "/home/mozilla/.plugins/dupplugin3.so" +}, { + name: "Non-duplicate Plugin", // 4 + description: "Not a duplicate because the descriptions are different", + version: "1", + blocklisted: false, + enabledState: Ci.nsIPluginTag.STATE_ENABLED, + get disabled() this.enabledState == Ci.nsIPluginTag.STATE_DISABLED, + filename: "", + filename: "/usr/lib/plugins/dupplugin4.so" +}, { + name: "Another Non-duplicate Plugin", // 5 + description: "Not a duplicate plugin", + version: "1", + blocklisted: false, + enabledState: Ci.nsIPluginTag.STATE_ENABLED, + get disabled() this.enabledState == Ci.nsIPluginTag.STATE_DISABLED, + filename: "/home/mozilla/.plugins/dupplugin5.so" +}]; + +// A fake plugin host to return the plugins defined above +var PluginHost = { + getPluginTags: function(countRef) { + countRef.value = PLUGINS.length; + return PLUGINS; + }, + + QueryInterface: function(iid) { + if (iid.equals(Components.interfaces.nsIPluginHost) + || iid.equals(Components.interfaces.nsISupports)) + return this; + + throw Components.results.NS_ERROR_NO_INTERFACE; + } +} + +var PluginHostFactory = { + createInstance: function (outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return PluginHost.QueryInterface(iid); + } +}; + +var registrar = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{721c3e73-969e-474b-a6dc-059fd288c428}"), + "Fake Plugin Host", + "@mozilla.org/plugin/host;1", PluginHostFactory); + +var gPluginIDs = [null, null, null, null, null]; + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + Services.prefs.setBoolPref("media.gmp-provider.enabled", false); + + startupManager(); + + run_test_1(); +} + +function found_plugin(aNum, aId) { + if (gPluginIDs[aNum]) + do_throw("Found duplicate of plugin " + aNum); + gPluginIDs[aNum] = aId; +} + +// Test that the plugins were coalesced and all appear in the returned list +function run_test_1() { + AddonManager.getAddonsByTypes(["plugin"], function(aAddons) { + do_check_eq(aAddons.length, 5); + aAddons.forEach(function(aAddon) { + if (aAddon.name == "Duplicate Plugin 1") { + found_plugin(0, aAddon.id); + do_check_eq(aAddon.description, "A duplicate plugin"); + } + else if (aAddon.name == "Duplicate Plugin 2") { + found_plugin(1, aAddon.id); + do_check_eq(aAddon.description, "Another duplicate plugin"); + } + else if (aAddon.name == "Another Non-duplicate Plugin") { + found_plugin(5, aAddon.id); + do_check_eq(aAddon.description, "Not a duplicate plugin"); + } + else if (aAddon.name == "Non-duplicate Plugin") { + if (aAddon.description == "Not a duplicate plugin") + found_plugin(3, aAddon.id); + else if (aAddon.description == "Not a duplicate because the descriptions are different") + found_plugin(4, aAddon.id); + else + do_throw("Found unexpected plugin with description " + aAddon.description); + } + else { + do_throw("Found unexpected plugin " + aAddon.name); + } + }); + + run_test_2(); + }); +} + +// Test that disabling a coalesced plugin disables all its tags +function run_test_2() { + AddonManager.getAddonByID(gPluginIDs[0], function(p) { + do_check_false(p.userDisabled); + p.userDisabled = true; + do_check_true(PLUGINS[0].disabled); + do_check_true(PLUGINS[1].disabled); + + do_execute_soon(run_test_3); + }); +} + +// Test that IDs persist across restart +function run_test_3() { + restartManager(); + + AddonManager.getAddonByID(gPluginIDs[0], callback_soon(function(p) { + do_check_neq(p, null); + do_check_eq(p.name, "Duplicate Plugin 1"); + do_check_eq(p.description, "A duplicate plugin"); + + // Reorder the plugins and restart again + [PLUGINS[0], PLUGINS[1]] = [PLUGINS[1], PLUGINS[0]]; + restartManager(); + + AddonManager.getAddonByID(gPluginIDs[0], function(p) { + do_check_neq(p, null); + do_check_eq(p.name, "Duplicate Plugin 1"); + do_check_eq(p.description, "A duplicate plugin"); + + do_execute_soon(do_test_finished); + }); + })); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_error.js b/toolkit/mozapps/extensions/test/xpcshell/test_error.js new file mode 100644 index 000000000..2184399e2 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_error.js @@ -0,0 +1,90 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that various error conditions are handled correctly + +Components.utils.import("resource://gre/modules/Services.jsm"); + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + startupManager(); + + do_test_pending(); + run_test_1(); +} + +// Checks that a local file validates ok +function run_test_1() { + AddonManager.getInstallForFile(do_get_file("data/unsigned.xpi"), function(install) { + do_check_neq(install, null); + do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); + do_check_eq(install.error, 0); + + install.cancel(); + + run_test_2(); + }); +} + +// Checks that a corrupt file shows an error +function run_test_2() { + AddonManager.getInstallForFile(do_get_file("data/corrupt.xpi"), function(install) { + do_check_neq(install, null); + do_check_eq(install.state, AddonManager.STATE_DOWNLOAD_FAILED); + do_check_eq(install.error, AddonManager.ERROR_CORRUPT_FILE); + + run_test_3(); + }); +} + +// Checks that an empty file shows an error +function run_test_3() { + AddonManager.getInstallForFile(do_get_file("data/empty.xpi"), function(install) { + do_check_neq(install, null); + do_check_eq(install.state, AddonManager.STATE_DOWNLOAD_FAILED); + do_check_eq(install.error, AddonManager.ERROR_CORRUPT_FILE); + + run_test_4(); + }); +} + +// Checks that a file that doesn't match its hash shows an error +function run_test_4() { + let url = Services.io.newFileURI(do_get_file("data/unsigned.xpi")).spec; + AddonManager.getInstallForURL(url, function(install) { + do_check_neq(install, null); + do_check_eq(install.state, AddonManager.STATE_DOWNLOAD_FAILED); + do_check_eq(install.error, AddonManager.ERROR_INCORRECT_HASH); + + run_test_5(); + }, "application/x-xpinstall", "sha1:foo"); +} + +// Checks that a file that doesn't exist shows an error +function run_test_4() { + let file = do_get_file("data"); + file.append("missing.xpi"); + AddonManager.getInstallForFile(file, function(install) { + do_check_neq(install, null); + do_check_eq(install.state, AddonManager.STATE_DOWNLOAD_FAILED); + do_check_eq(install.error, AddonManager.ERROR_NETWORK_FAILURE); + + run_test_5(); + }); +} + +// Checks that an add-on with an illegal ID shows an error +function run_test_5() { + AddonManager.getInstallForFile(do_get_addon("test_bug567173"), function(install) { + do_check_neq(install, null); + do_check_eq(install.state, AddonManager.STATE_DOWNLOAD_FAILED); + do_check_eq(install.error, AddonManager.ERROR_CORRUPT_FILE); + + do_execute_soon(do_test_finished); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_experiment.js b/toolkit/mozapps/extensions/test/xpcshell/test_experiment.js new file mode 100644 index 000000000..25172749d --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_experiment.js @@ -0,0 +1,104 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +let scope = Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm"); +const XPIProvider = scope.XPIProvider; + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + startupManager(); + + run_next_test(); +} + +add_test(function test_experiment() { + AddonManager.getInstallForFile(do_get_addon("test_experiment1"), (install) => { + completeAllInstalls([install], () => { + AddonManager.getAddonByID("experiment1@tests.mozilla.org", (addon) => { + Assert.ok(addon, "Addon is found."); + + Assert.ok(addon.userDisabled, "Experiments are userDisabled by default."); + Assert.equal(addon.isActive, false, "Add-on is not active."); + Assert.equal(addon.updateURL, null, "No updateURL for experiments."); + Assert.equal(addon.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DISABLE, + "Background updates are disabled."); + Assert.equal(addon.permissions, AddonManager.PERM_CAN_UNINSTALL, + "Permissions are minimal."); + Assert.ok(!(addon.pendingOperations & AddonManager.PENDING_ENABLE), + "Should not be pending enable"); + Assert.ok(!(addon.pendingOperations & AddonManager.PENDING_DISABLE), + "Should not be pending disable"); + + // Setting applyBackgroundUpdates should not work. + addon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_ENABLE; + Assert.equal(addon.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DISABLE, + "Setting applyBackgroundUpdates shouldn't do anything."); + + let noCompatibleCalled = false; + let noUpdateCalled = false; + let finishedCalled = false; + + let listener = { + onNoCompatibilityUpdateAvailable: () => { noCompatibleCalled = true; }, + onNoUpdateAvailable: () => { noUpdateCalled = true; }, + onUpdateFinished: () => { finishedCalled = true; }, + }; + + addon.findUpdates(listener, "testing", null, null); + Assert.ok(noCompatibleCalled, "Listener called."); + Assert.ok(noUpdateCalled, "Listener called."); + Assert.ok(finishedCalled, "Listener called."); + + run_next_test(); + }); + }); + }); +}); + +// Changes to userDisabled should not be persisted to the database. +add_test(function test_userDisabledNotPersisted() { + AddonManager.getAddonByID("experiment1@tests.mozilla.org", (addon) => { + Assert.ok(addon, "Add-on is found."); + Assert.ok(addon.userDisabled, "Add-on is user disabled."); + + let listener = { + onEnabled: (addon2) => { + AddonManager.removeAddonListener(listener); + + Assert.equal(addon2.id, addon.id, "Changed add-on matches expected."); + Assert.equal(addon2.userDisabled, false, "Add-on is no longer user disabled."); + Assert.ok(addon2.isActive, "Add-on is active."); + + Assert.ok("experiment1@tests.mozilla.org" in XPIProvider.bootstrappedAddons, + "Experiment add-on listed in XPIProvider bootstrapped list."); + + AddonManager.getAddonByID("experiment1@tests.mozilla.org", (addon) => { + Assert.ok(addon, "Add-on retrieved."); + Assert.equal(addon.userDisabled, false, "Add-on is still enabled after API retrieve."); + Assert.ok(addon.isActive, "Add-on is still active."); + Assert.ok(!(addon.pendingOperations & AddonManager.PENDING_ENABLE), + "Should not be pending enable"); + Assert.ok(!(addon.pendingOperations & AddonManager.PENDING_DISABLE), + "Should not be pending disable"); + + // Now when we restart the manager the add-on should revert state. + restartManager(); + let persisted = JSON.parse(Services.prefs.getCharPref("extensions.bootstrappedAddons")); + Assert.ok(!("experiment1@tests.mozilla.org" in persisted), + "Experiment add-on not persisted to bootstrappedAddons."); + + AddonManager.getAddonByID("experiment1@tests.mozilla.org", (addon) => { + Assert.ok(addon, "Add-on retrieved."); + Assert.ok(addon.userDisabled, "Add-on is disabled after restart."); + Assert.equal(addon.isActive, false, "Add-on is not active after restart."); + + run_next_test(); + }); + }); + }, + }; + + AddonManager.addAddonListener(listener); + addon.userDisabled = false; + }); +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_filepointer.js b/toolkit/mozapps/extensions/test/xpcshell/test_filepointer.js new file mode 100644 index 000000000..cb661e495 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_filepointer.js @@ -0,0 +1,403 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that various operations with file pointers work and do not affect the +// source files + +var addon1 = { + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +var addon1_2 = { + id: "addon1@tests.mozilla.org", + version: "2.0", + name: "Test 1", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +var addon2 = { + id: "addon2@tests.mozilla.org", + version: "1.0", + name: "Test 2", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); +profileDir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755); + +const sourceDir = gProfD.clone(); +sourceDir.append("source"); + +Components.utils.import("resource://testing-common/httpd.js"); +var testserver; + +function writePointer(aId, aName) { + let file = profileDir.clone(); + file.append(aName ? aName : aId); + + let target = sourceDir.clone(); + target.append(do_get_expected_addon_name(aId)); + + var fos = AM_Cc["@mozilla.org/network/file-output-stream;1"]. + createInstance(AM_Ci.nsIFileOutputStream); + fos.init(file, + FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | FileUtils.MODE_TRUNCATE, + FileUtils.PERMS_FILE, 0); + fos.write(target.path, target.path.length); + fos.close(); +} + +function writeRelativePointer(aId, aName) { + let file = profileDir.clone(); + file.append(aName ? aName : aId); + + let absTarget = sourceDir.clone(); + absTarget.append(do_get_expected_addon_name(aId)); + + var relTarget = absTarget.getRelativeDescriptor(profileDir); + + var fos = AM_Cc["@mozilla.org/network/file-output-stream;1"]. + createInstance(AM_Ci.nsIFileOutputStream); + fos.init(file, + FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | FileUtils.MODE_TRUNCATE, + FileUtils.PERMS_FILE, 0); + fos.write(relTarget, relTarget.length); + fos.close(); +} + +function run_test() { + // pointer files only work with unpacked directories + if (Services.prefs.getBoolPref("extensions.alwaysUnpack") == false) + return; + + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); + + // Create and configure the HTTP server. + testserver = new HttpServer(); + testserver.registerDirectory("/data/", do_get_file("data")); + testserver.registerDirectory("/addons/", do_get_file("addons")); + testserver.start(-1); + gPort = testserver.identity.primaryPort; + + run_test_1(); +} + +function end_test() { + testserver.stop(do_test_finished); +} + +// Tests that installing a new add-on by pointer works +function run_test_1() { + writeInstallRDFForExtension(addon1, sourceDir); + writePointer(addon1.id); + + startupManager(); + + AddonManager.getAddonByID(addon1.id, function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "1.0"); + + let file = a1.getResourceURI().QueryInterface(AM_Ci.nsIFileURL).file; + do_check_eq(file.parent.path, sourceDir.path); + + let rootUri = do_get_addon_root_uri(sourceDir, addon1.id); + let uri = a1.getResourceURI("/"); + do_check_eq(uri.spec, rootUri); + uri = a1.getResourceURI("install.rdf"); + do_check_eq(uri.spec, rootUri + "install.rdf"); + + // Check that upgrade is disabled for addons installed by file-pointers. + do_check_eq(a1.permissions & AddonManager.PERM_CAN_UPGRADE, 0); + run_test_2(); + }); +} + +// Tests that installing the addon from some other source doesn't clobber +// the original sources +function run_test_2() { + prepare_test({}, [ + "onNewInstall", + ]); + + let url = "http://localhost:" + gPort + "/addons/test_filepointer.xpi"; + AddonManager.getInstallForURL(url, function(install) { + ensure_test_completed(); + + prepare_test({ + "addon1@tests.mozilla.org": [ + "onInstalling" + ] + }, [ + "onDownloadStarted", + "onDownloadEnded", + "onInstallStarted", + "onInstallEnded" + ], callback_soon(check_test_2)); + + install.install(); + }, "application/x-xpinstall"); +} + +function check_test_2() { + restartManager(); + + AddonManager.getAddonByID(addon1.id, function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "2.0"); + + let file = a1.getResourceURI().QueryInterface(AM_Ci.nsIFileURL).file; + do_check_eq(file.parent.path, profileDir.path); + + let rootUri = do_get_addon_root_uri(profileDir, addon1.id); + let uri = a1.getResourceURI("/"); + do_check_eq(uri.spec, rootUri); + uri = a1.getResourceURI("install.rdf"); + do_check_eq(uri.spec, rootUri + "install.rdf"); + + let source = sourceDir.clone(); + source.append(addon1.id); + do_check_true(source.exists()); + + a1.uninstall(); + + do_execute_soon(run_test_3); + }); +} + +// Tests that uninstalling doesn't clobber the original sources +function run_test_3() { + restartManager(); + + writePointer(addon1.id); + + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "1.0"); + + a1.uninstall(); + + restartManager(); + + let source = sourceDir.clone(); + source.append(addon1.id); + do_check_true(source.exists()); + + do_execute_soon(run_test_4); + })); +} + +// Tests that misnaming a pointer doesn't clobber the sources +function run_test_4() { + writePointer("addon2@tests.mozilla.org", addon1.id); + + restartManager(); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org"], function([a1, a2]) { + do_check_eq(a1, null); + do_check_eq(a2, null); + + let source = sourceDir.clone(); + source.append(addon1.id); + do_check_true(source.exists()); + + let pointer = profileDir.clone(); + pointer.append("addon2@tests.mozilla.org"); + do_check_false(pointer.exists()); + + do_execute_soon(run_test_5); + }); +} + +// Tests that changing the ID of an existing add-on doesn't clobber the sources +function run_test_5() { + var dest = writeInstallRDFForExtension(addon1, sourceDir); + // Make sure the modification time changes enough to be detected. + setExtensionModifiedTime(dest, dest.lastModifiedTime - 5000); + writePointer(addon1.id); + + restartManager(); + + AddonManager.getAddonByID(addon1.id, callback_soon(function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "1.0"); + + writeInstallRDFForExtension(addon2, sourceDir, addon1.id); + + restartManager(); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org"], function([a1, a2]) { + do_check_eq(a1, null); + do_check_eq(a2, null); + + let source = sourceDir.clone(); + source.append(addon1.id); + do_check_true(source.exists()); + + let pointer = profileDir.clone(); + pointer.append(addon1.id); + do_check_false(pointer.exists()); + + do_execute_soon(run_test_6); + }); + })); +} + +// Removing the pointer file should uninstall the add-on +function run_test_6() { + var dest = writeInstallRDFForExtension(addon1, sourceDir); + // Make sure the modification time changes enough to be detected in run_test_8. + setExtensionModifiedTime(dest, dest.lastModifiedTime - 5000); + writePointer(addon1.id); + + restartManager(); + + AddonManager.getAddonByID(addon1.id, callback_soon(function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "1.0"); + + let pointer = profileDir.clone(); + pointer.append(addon1.id); + pointer.remove(false); + + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_eq(a1, null); + + do_execute_soon(run_test_7); + }); + })); +} + +// Removing the pointer file and replacing it with a directory should work +function run_test_7() { + writePointer(addon1.id); + + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "1.0"); + + let pointer = profileDir.clone(); + pointer.append(addon1.id); + pointer.remove(false); + + writeInstallRDFForExtension(addon1_2, profileDir); + + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "2.0"); + + a1.uninstall(); + + do_execute_soon(run_test_8); + }); + })); +} + +// Changes to the source files should be detected +function run_test_8() { + restartManager(); + + writePointer(addon1.id); + + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "1.0"); + + writeInstallRDFForExtension(addon1_2, sourceDir); + + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "2.0"); + + a1.uninstall(); + + do_execute_soon(run_test_9); + }); + })); +} + +// Removing the add-on the pointer file points at should uninstall the add-on +function run_test_9() { + restartManager(); + + var dest = writeInstallRDFForExtension(addon1, sourceDir); + writePointer(addon1.id); + + restartManager(); + + AddonManager.getAddonByID(addon1.id, callback_soon(function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "1.0"); + + dest.remove(true); + + restartManager(); + + AddonManager.getAddonByID(addon1.id, function(a1) { + do_check_eq(a1, null); + + let pointer = profileDir.clone(); + pointer.append(addon1.id); + do_check_false(pointer.exists()); + + do_execute_soon(run_test_10); + }); + })); +} + +// Tests that installing a new add-on by pointer with a relative path works +function run_test_10() { + writeInstallRDFForExtension(addon1, sourceDir); + writeRelativePointer(addon1.id); + + restartManager(); + + AddonManager.getAddonByID(addon1.id, function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "1.0"); + + let file = a1.getResourceURI().QueryInterface(AM_Ci.nsIFileURL).file; + do_check_eq(file.parent.path, sourceDir.path); + + let rootUri = do_get_addon_root_uri(sourceDir, addon1.id); + let uri = a1.getResourceURI("/"); + do_check_eq(uri.spec, rootUri); + uri = a1.getResourceURI("install.rdf"); + do_check_eq(uri.spec, rootUri + "install.rdf"); + + // Check that upgrade is disabled for addons installed by file-pointers. + do_check_eq(a1.permissions & AddonManager.PERM_CAN_UPGRADE, 0); + end_test(); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_fuel.js b/toolkit/mozapps/extensions/test/xpcshell/test_fuel.js new file mode 100644 index 000000000..800933220 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_fuel.js @@ -0,0 +1,164 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// This just verifies that FUEL integrates to the add-ons manager + +var testdata = { + dummyid: "fuel-dummy-extension@mozilla.org", + dummyname: "Dummy Extension", + inspectorid: "addon1@tests.mozilla.org", + inspectorname: "Test Addon", + missing: "fuel.fuel-test-missing", + dummy: "fuel.fuel-test" +}; + +var Application = null + +function run_test() { + var cm = AM_Cc["@mozilla.org/categorymanager;1"]. + getService(AM_Ci.nsICategoryManager); + + try { + var contract = cm.getCategoryEntry("JavaScript-global-privileged-property", + "Application"); + Application = AM_Cc[contract].getService(AM_Ci.extIApplication); + } + catch (e) { + // This application does not include a FUEL variant. + return; + } + + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + const profileDir = gProfD.clone(); + profileDir.append("extensions"); + + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test Addon", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + }, profileDir); + + startupManager(); + + Application.getExtensions(function(extensions) { + // test to see if the extensions object is available + do_check_neq(extensions, null); + + // test to see if a non-existant extension exists + do_check_true(!extensions.has(testdata.dummyid)); + + // test to see if an extension exists + do_check_true(extensions.has(testdata.inspectorid)); + + var inspector = extensions.get(testdata.inspectorid); + do_check_eq(inspector.id, testdata.inspectorid); + do_check_eq(inspector.name, testdata.inspectorname); + do_check_eq(inspector.version, "1.0"); + do_check_true(inspector.firstRun, true); + do_check_true(inspector.enabled); + + // test to see if extension find works + do_check_eq(extensions.all.length, 1); + // STORAGE TESTING + // Make sure the we are given the same extension (cached) so things like .storage work right + inspector.storage.set("test", "simple check"); + do_check_true(inspector.storage.has("test")); + + var inspector2 = extensions.get(testdata.inspectorid); + do_check_eq(inspector2.id, testdata.inspectorid); + do_check_true(inspector.storage.has("test")); + do_check_eq(inspector2.storage.get("test", "cache"), inspector.storage.get("test", "original")); + + inspector.events.addListener("disable", onGenericEvent); + inspector.events.addListener("enable", onGenericEvent); + inspector.events.addListener("uninstall", onGenericEvent); + inspector.events.addListener("cancel", onGenericEvent); + + AddonManager.getAddonByID(testdata.inspectorid, function(a) { + a.userDisabled = true; + + do_check_eq(gLastEvent, "disable"); + + // enabling after a disable will only fire a 'cancel' event + // see - http://mxr.mozilla.org/seamonkey/source/toolkit/mozapps/extensions/src/nsExtensionManager.js.in#5216 + a.userDisabled = false; + do_check_eq(gLastEvent, "cancel"); + + a.uninstall(); + do_check_eq(gLastEvent, "uninstall"); + + a.cancelUninstall(); + do_check_eq(gLastEvent, "cancel"); + + // PREF TESTING + // Reset the install event preference, so that we can test it again later + //inspector.prefs.get("install-event-fired").reset(); + + // test the value of the preference root + do_check_eq(extensions.all[0].prefs.root, "extensions.addon1@tests.mozilla.org."); + + // test getting nonexistent values + var itemValue = inspector.prefs.getValue(testdata.missing, "default"); + do_check_eq(itemValue, "default"); + + do_check_eq(inspector.prefs.get(testdata.missing), null); + + // test setting and getting a value + inspector.prefs.setValue(testdata.dummy, "dummy"); + itemValue = inspector.prefs.getValue(testdata.dummy, "default"); + do_check_eq(itemValue, "dummy"); + + // test for overwriting an existing value + inspector.prefs.setValue(testdata.dummy, "smarty"); + itemValue = inspector.prefs.getValue(testdata.dummy, "default"); + do_check_eq(itemValue, "smarty"); + + // test setting and getting a value + inspector.prefs.get(testdata.dummy).value = "dummy2"; + itemValue = inspector.prefs.get(testdata.dummy).value; + do_check_eq(itemValue, "dummy2"); + + // test resetting a pref [since there is no default value, the pref should disappear] + inspector.prefs.get(testdata.dummy).reset(); + var itemValue = inspector.prefs.getValue(testdata.dummy, "default"); + do_check_eq(itemValue, "default"); + + // test to see if a non-existant property exists + do_check_true(!inspector.prefs.has(testdata.dummy)); + + inspector.prefs.events.addListener("change", onPrefChange); + inspector.prefs.setValue("fuel.fuel-test", "change event"); + }); + }); +} + +function onGenericEvent(event) { + gLastEvent = event.type; +} + +function onPrefChange(evt) { + Application.getExtensions(function(extensions) { + var inspector3 = extensions.get(testdata.inspectorid); + + do_check_eq(evt.data, testdata.dummy); + inspector3.prefs.events.removeListener("change", onPrefChange); + + inspector3.prefs.get("fuel.fuel-test").events.addListener("change", onPrefChange2); + inspector3.prefs.setValue("fuel.fuel-test", "change event2"); + }); +} + +function onPrefChange2(evt) { + do_check_eq(evt.data, testdata.dummy); + + do_execute_soon(do_test_finished); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_general.js b/toolkit/mozapps/extensions/test/xpcshell/test_general.js new file mode 100644 index 000000000..e69b13314 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_general.js @@ -0,0 +1,58 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This just verifies that the EM can actually startup and shutdown a few times +// without any errors + +// We have to look up how many add-ons are present since there will be plugins +// etc. detected +var gCount; + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + var count = 0; + startupManager(); + AddonManager.getAddonsByTypes(null, function(list) { + gCount = list.length; + + do_execute_soon(run_test_1); + }); +} + +function run_test_1() { + restartManager(); + + AddonManager.getAddonsByTypes(null, function(addons) { + do_check_eq(gCount, addons.length); + + AddonManager.getAddonsWithOperationsByTypes(null, function(pendingAddons) { + do_check_eq(0, pendingAddons.length); + + do_execute_soon(run_test_2); + }); + }); +} + +function run_test_2() { + shutdownManager(); + + startupManager(false); + + AddonManager.getAddonsByTypes(null, function(addons) { + do_check_eq(gCount, addons.length); + + do_execute_soon(run_test_3); + }); +} + +function run_test_3() { + restartManager(); + + AddonManager.getAddonsByTypes(null, callback_soon(function(addons) { + do_check_eq(gCount, addons.length); + do_test_finished(); + })); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_getresource.js b/toolkit/mozapps/extensions/test/xpcshell/test_getresource.js new file mode 100644 index 000000000..4dce15aec --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_getresource.js @@ -0,0 +1,94 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// install.rdf size, icon.png size, subfile.txt size +const ADDON_SIZE = 672 + 15 + 26; + +// This verifies the functionality of getResourceURI +// There are two cases - with a filename it returns an nsIFileURL to the filename +// and with no parameters, it returns an nsIFileURL to the root of the addon + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); + + startupManager(); + + AddonManager.getInstallForFile(do_get_addon("test_getresource"), function(aInstall) { + do_check_true(aInstall.addon.hasResource("install.rdf")); + do_check_eq(aInstall.addon.getResourceURI().spec, aInstall.sourceURI.spec); + + do_check_true(aInstall.addon.hasResource("icon.png")); + do_check_eq(aInstall.addon.getResourceURI("icon.png").spec, + "jar:" + aInstall.sourceURI.spec + "!/icon.png"); + + do_check_false(aInstall.addon.hasResource("missing.txt")); + + do_check_true(aInstall.addon.hasResource("subdir/subfile.txt")); + do_check_eq(aInstall.addon.getResourceURI("subdir/subfile.txt").spec, + "jar:" + aInstall.sourceURI.spec + "!/subdir/subfile.txt"); + + do_check_false(aInstall.addon.hasResource("subdir/missing.txt")); + + do_check_eq(aInstall.addon.size, ADDON_SIZE); + + completeAllInstalls([aInstall], function() { + restartManager(); + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + + let addonDir = gProfD.clone(); + addonDir.append("extensions"); + let rootUri = do_get_addon_root_uri(addonDir, "addon1@tests.mozilla.org"); + + let uri = a1.getResourceURI("/"); + do_check_eq(uri.spec, rootUri); + + let file = rootUri + "install.rdf"; + do_check_true(a1.hasResource("install.rdf")); + uri = a1.getResourceURI("install.rdf") + do_check_eq(uri.spec, file); + + file = rootUri + "icon.png"; + do_check_true(a1.hasResource("icon.png")); + uri = a1.getResourceURI("icon.png") + do_check_eq(uri.spec, file); + + do_check_false(a1.hasResource("missing.txt")); + + file = rootUri + "subdir/subfile.txt"; + do_check_true(a1.hasResource("subdir/subfile.txt")); + uri = a1.getResourceURI("subdir/subfile.txt") + do_check_eq(uri.spec, file); + + do_check_false(a1.hasResource("subdir/missing.txt")); + + do_check_eq(a1.size, ADDON_SIZE); + + a1.uninstall(); + + try { + // hasResource should never throw an exception. + do_check_false(a1.hasResource("icon.png")); + } catch (e) { + do_check_true(false); + } + + AddonManager.getInstallForFile(do_get_addon("test_getresource"), + callback_soon(function(aInstall) { + do_check_false(a1.hasResource("icon.png")); + do_check_true(aInstall.addon.hasResource("icon.png")); + + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(newa1) { + do_check_eq(newa1, null); + + do_execute_soon(do_test_finished); + }); + })); + }); + }); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Device.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Device.js new file mode 100644 index 000000000..5f781edf4 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Device.js @@ -0,0 +1,95 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test whether a machine which differs only on device ID, but otherwise +// exactly matches the blacklist entry, is not blocked. +// Uses test_gfxBlacklist.xml + +Components.utils.import("resource://testing-common/httpd.js"); + +var gTestserver = new HttpServer(); +gTestserver.start(-1); +gPort = gTestserver.identity.primaryPort; +mapFile("/data/test_gfxBlacklist.xml", gTestserver); + +function get_platform() { + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); + return xulRuntime.OS; +} + +function load_blocklist(file) { + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + + gPort + "/data/" + file); + var blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. + getService(Ci.nsITimerCallback); + blocklist.notify(null); +} + +// Performs the initial setup +function run_test() { + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } + + // We can't do anything if we can't spoof the stuff we need. + if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { + do_test_finished(); + return; + } + + gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug); + + // Set the vendor/device ID, etc, to match the test file. + switch (get_platform()) { + case "WINNT": + gfxInfo.spoofVendorID("0xabcd"); + gfxInfo.spoofDeviceID("0x9876"); + gfxInfo.spoofDriverVersion("8.52.322.2201"); + // Windows 7 + gfxInfo.spoofOSVersion(0x60001); + break; + case "Linux": + gfxInfo.spoofVendorID("0xabcd"); + gfxInfo.spoofDeviceID("0x9876"); + break; + case "Darwin": + gfxInfo.spoofVendorID("0xabcd"); + gfxInfo.spoofDeviceID("0x9876"); + gfxInfo.spoofOSVersion(0x1050); + break; + case "Android": + gfxInfo.spoofVendorID("abcd"); + gfxInfo.spoofDeviceID("aabb"); + gfxInfo.spoofDriverVersion("5"); + break; + } + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); + startupManager(); + + do_test_pending(); + + function checkBlacklist() + { + var status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT2D); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + + status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT3D_9_LAYERS); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + + gTestserver.stop(do_test_finished); + } + + Services.obs.addObserver(function(aSubject, aTopic, aData) { + // If we wait until after we go through the event loop, gfxInfo is sure to + // have processed the gfxItems event. + do_execute_soon(checkBlacklist); + }, "blocklist-data-gfxItems", false); + + load_blocklist("test_gfxBlacklist.xml"); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_DriverNew.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_DriverNew.js new file mode 100644 index 000000000..802fe11e2 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_DriverNew.js @@ -0,0 +1,94 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test whether a new-enough driver bypasses the blacklist, even if the rest of +// the attributes match the blacklist entry. +// Uses test_gfxBlacklist.xml + +Components.utils.import("resource://testing-common/httpd.js"); + +var gTestserver = new HttpServer(); +gTestserver.start(-1); +gPort = gTestserver.identity.primaryPort; +mapFile("/data/test_gfxBlacklist.xml", gTestserver); + +function get_platform() { + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); + return xulRuntime.OS; +} + +function load_blocklist(file) { + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + + gPort + "/data/" + file); + var blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. + getService(Ci.nsITimerCallback); + blocklist.notify(null); +} + +// Performs the initial setup +function run_test() { + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } + + // We can't do anything if we can't spoof the stuff we need. + if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { + do_test_finished(); + return; + } + + gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug); + + // Set the vendor/device ID, etc, to match the test file. + switch (get_platform()) { + case "WINNT": + gfxInfo.spoofVendorID("0xabcd"); + gfxInfo.spoofDeviceID("0x1234"); + gfxInfo.spoofDriverVersion("8.52.322.2202"); + // Windows 7 + gfxInfo.spoofOSVersion(0x60001); + break; + case "Linux": + // We don't support driver versions on Linux. + do_test_finished(); + return; + case "Darwin": + // We don't support driver versions on Darwin. + do_test_finished(); + return; + case "Android": + gfxInfo.spoofVendorID("abcd"); + gfxInfo.spoofDeviceID("wxyz"); + gfxInfo.spoofDriverVersion("6"); + break; + } + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); + startupManager(); + + do_test_pending(); + + function checkBlacklist() + { + var status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT2D); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + + status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT3D_9_LAYERS); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + + gTestserver.stop(do_test_finished); + } + + Services.obs.addObserver(function(aSubject, aTopic, aData) { + // If we wait until after we go through the event loop, gfxInfo is sure to + // have processed the gfxItems event. + do_execute_soon(checkBlacklist); + }, "blocklist-data-gfxItems", false); + + load_blocklist("test_gfxBlacklist.xml"); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverNew.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverNew.js new file mode 100644 index 000000000..08e87c38c --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverNew.js @@ -0,0 +1,95 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test whether a machine which is newer than the equal +// blacklist entry is allowed. +// Uses test_gfxBlacklist.xml + +Components.utils.import("resource://testing-common/httpd.js"); + +var gTestserver = new HttpServer(); +gTestserver.start(-1); +gPort = gTestserver.identity.primaryPort; +mapFile("/data/test_gfxBlacklist.xml", gTestserver); + +function get_platform() { + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); + return xulRuntime.OS; +} + +function load_blocklist(file) { + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + + gPort + "/data/" + file); + var blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. + getService(Ci.nsITimerCallback); + blocklist.notify(null); +} + +// Performs the initial setup +function run_test() { + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } + + // We can't do anything if we can't spoof the stuff we need. + if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { + do_test_finished(); + return; + } + + gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug); + + // Set the vendor/device ID, etc, to match the test file. + switch (get_platform()) { + case "WINNT": + gfxInfo.spoofVendorID("0xdcdc"); + gfxInfo.spoofDeviceID("0x1234"); + gfxInfo.spoofDriverVersion("8.52.322.1112"); + // Windows 7 + gfxInfo.spoofOSVersion(0x60001); + break; + case "Linux": + // We don't support driver versions on Linux. + do_test_finished(); + return; + case "Darwin": + // We don't support driver versions on Darwin. + do_test_finished(); + return; + case "Android": + gfxInfo.spoofVendorID("dcdc"); + gfxInfo.spoofDeviceID("uiop"); + gfxInfo.spoofDriverVersion("6"); + break; + } + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); + startupManager(); + + do_test_pending(); + + function checkBlacklist() + { + var status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT2D); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + + // Make sure unrelated features aren't affected + status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT3D_9_LAYERS); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + + gTestserver.stop(do_test_finished); + } + + Services.obs.addObserver(function(aSubject, aTopic, aData) { + // If we wait until after we go through the event loop, gfxInfo is sure to + // have processed the gfxItems event. + do_execute_soon(checkBlacklist); + }, "blocklist-data-gfxItems", false); + + load_blocklist("test_gfxBlacklist.xml"); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverOld.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverOld.js new file mode 100644 index 000000000..73253c89b --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverOld.js @@ -0,0 +1,95 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test whether a machine which is older than the equal +// blacklist entry is correctly allowed. +// Uses test_gfxBlacklist.xml + +Components.utils.import("resource://testing-common/httpd.js"); + +var gTestserver = new HttpServer(); +gTestserver.start(-1); +gPort = gTestserver.identity.primaryPort; +mapFile("/data/test_gfxBlacklist.xml", gTestserver); + +function get_platform() { + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); + return xulRuntime.OS; +} + +function load_blocklist(file) { + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + + gPort + "/data/" + file); + var blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. + getService(Ci.nsITimerCallback); + blocklist.notify(null); +} + +// Performs the initial setup +function run_test() { + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } + + // We can't do anything if we can't spoof the stuff we need. + if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { + do_test_finished(); + return; + } + + gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug); + + // Set the vendor/device ID, etc, to match the test file. + switch (get_platform()) { + case "WINNT": + gfxInfo.spoofVendorID("0xdcdc"); + gfxInfo.spoofDeviceID("0x1234"); + gfxInfo.spoofDriverVersion("8.52.322.1110"); + // Windows 7 + gfxInfo.spoofOSVersion(0x60001); + break; + case "Linux": + // We don't support driver versions on Linux. + do_test_finished(); + return; + case "Darwin": + // We don't support driver versions on Darwin. + do_test_finished(); + return; + case "Android": + gfxInfo.spoofVendorID("dcdc"); + gfxInfo.spoofDeviceID("uiop"); + gfxInfo.spoofDriverVersion("4"); + break; + } + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); + startupManager(); + + do_test_pending(); + + function checkBlacklist() + { + var status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT2D); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + + // Make sure unrelated features aren't affected + status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT3D_9_LAYERS); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + + gTestserver.stop(do_test_finished); + } + + Services.obs.addObserver(function(aSubject, aTopic, aData) { + // If we wait until after we go through the event loop, gfxInfo is sure to + // have processed the gfxItems event. + do_execute_soon(checkBlacklist); + }, "blocklist-data-gfxItems", false); + + load_blocklist("test_gfxBlacklist.xml"); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_OK.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_OK.js new file mode 100644 index 000000000..2dde268a3 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_OK.js @@ -0,0 +1,95 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test whether a machine which exactly matches the equal +// blacklist entry is successfully blocked. +// Uses test_gfxBlacklist.xml + +Components.utils.import("resource://testing-common/httpd.js"); + +var gTestserver = new HttpServer(); +gTestserver.start(-1); +gPort = gTestserver.identity.primaryPort; +mapFile("/data/test_gfxBlacklist.xml", gTestserver); + +function get_platform() { + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); + return xulRuntime.OS; +} + +function load_blocklist(file) { + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + + gPort + "/data/" + file); + var blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. + getService(Ci.nsITimerCallback); + blocklist.notify(null); +} + +// Performs the initial setup +function run_test() { + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } + + // We can't do anything if we can't spoof the stuff we need. + if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { + do_test_finished(); + return; + } + + gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug); + + // Set the vendor/device ID, etc, to match the test file. + switch (get_platform()) { + case "WINNT": + gfxInfo.spoofVendorID("0xdcdc"); + gfxInfo.spoofDeviceID("0x1234"); + gfxInfo.spoofDriverVersion("8.52.322.1111"); + // Windows 7 + gfxInfo.spoofOSVersion(0x60001); + break; + case "Linux": + // We don't support driver versions on Linux. + do_test_finished(); + return; + case "Darwin": + // We don't support driver versions on Darwin. + do_test_finished(); + return; + case "Android": + gfxInfo.spoofVendorID("dcdc"); + gfxInfo.spoofDeviceID("uiop"); + gfxInfo.spoofDriverVersion("5"); + break; + } + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); + startupManager(); + + do_test_pending(); + + function checkBlacklist() + { + var status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT2D); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_BLOCKED_DRIVER_VERSION); + + // Make sure unrelated features aren't affected + status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT3D_9_LAYERS); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + + gTestserver.stop(do_test_finished); + } + + Services.obs.addObserver(function(aSubject, aTopic, aData) { + // If we wait until after we go through the event loop, gfxInfo is sure to + // have processed the gfxItems event. + do_execute_soon(checkBlacklist); + }, "blocklist-data-gfxItems", false); + + load_blocklist("test_gfxBlacklist.xml"); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_DriverOld.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_DriverOld.js new file mode 100644 index 000000000..fd3145f5a --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_DriverOld.js @@ -0,0 +1,95 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test whether a machine which is lower than the greater-than-or-equal +// blacklist entry is allowed. +// Uses test_gfxBlacklist.xml + +Components.utils.import("resource://testing-common/httpd.js"); + +var gTestserver = new HttpServer(); +gTestserver.start(-1); +gPort = gTestserver.identity.primaryPort; +mapFile("/data/test_gfxBlacklist.xml", gTestserver); + +function get_platform() { + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); + return xulRuntime.OS; +} + +function load_blocklist(file) { + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + + gPort + "/data/" + file); + var blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. + getService(Ci.nsITimerCallback); + blocklist.notify(null); +} + +// Performs the initial setup +function run_test() { + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } + + // We can't do anything if we can't spoof the stuff we need. + if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { + do_test_finished(); + return; + } + + gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug); + + // Set the vendor/device ID, etc, to match the test file. + switch (get_platform()) { + case "WINNT": + gfxInfo.spoofVendorID("0xabab"); + gfxInfo.spoofDeviceID("0x1234"); + gfxInfo.spoofDriverVersion("8.52.322.2201"); + // Windows 7 + gfxInfo.spoofOSVersion(0x60001); + break; + case "Linux": + // We don't support driver versions on Linux. + do_test_finished(); + return; + case "Darwin": + // We don't support driver versions on Darwin. + do_test_finished(); + return; + case "Android": + gfxInfo.spoofVendorID("abab"); + gfxInfo.spoofDeviceID("ghjk"); + gfxInfo.spoofDriverVersion("6"); + break; + } + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); + startupManager(); + + do_test_pending(); + + function checkBlacklist() + { + var status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT2D); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + + // Make sure unrelated features aren't affected + status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT3D_9_LAYERS); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + + gTestserver.stop(do_test_finished); + } + + Services.obs.addObserver(function(aSubject, aTopic, aData) { + // If we wait until after we go through the event loop, gfxInfo is sure to + // have processed the gfxItems event. + do_execute_soon(checkBlacklist); + }, "blocklist-data-gfxItems", false); + + load_blocklist("test_gfxBlacklist.xml"); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_OK.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_OK.js new file mode 100644 index 000000000..0c2c65572 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_OK.js @@ -0,0 +1,95 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test whether a machine which exactly matches the greater-than-or-equal +// blacklist entry is successfully blocked. +// Uses test_gfxBlacklist.xml + +Components.utils.import("resource://testing-common/httpd.js"); + +var gTestserver = new HttpServer(); +gTestserver.start(-1); +gPort = gTestserver.identity.primaryPort; +mapFile("/data/test_gfxBlacklist.xml", gTestserver); + +function get_platform() { + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); + return xulRuntime.OS; +} + +function load_blocklist(file) { + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + + gPort + "/data/" + file); + var blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. + getService(Ci.nsITimerCallback); + blocklist.notify(null); +} + +// Performs the initial setup +function run_test() { + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } + + // We can't do anything if we can't spoof the stuff we need. + if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { + do_test_finished(); + return; + } + + gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug); + + // Set the vendor/device ID, etc, to match the test file. + switch (get_platform()) { + case "WINNT": + gfxInfo.spoofVendorID("0xabab"); + gfxInfo.spoofDeviceID("0x1234"); + gfxInfo.spoofDriverVersion("8.52.322.2202"); + // Windows 7 + gfxInfo.spoofOSVersion(0x60001); + break; + case "Linux": + // We don't support driver versions on Linux. + do_test_finished(); + return; + case "Darwin": + // We don't support driver versions on Darwin. + do_test_finished(); + return; + case "Android": + gfxInfo.spoofVendorID("abab"); + gfxInfo.spoofDeviceID("ghjk"); + gfxInfo.spoofDriverVersion("7"); + break; + } + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); + startupManager(); + + do_test_pending(); + + function checkBlacklist() + { + var status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT2D); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_BLOCKED_DRIVER_VERSION); + + // Make sure unrelated features aren't affected + status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT3D_9_LAYERS); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + + gTestserver.stop(do_test_finished); + } + + Services.obs.addObserver(function(aSubject, aTopic, aData) { + // If we wait until after we go through the event loop, gfxInfo is sure to + // have processed the gfxItems event. + do_execute_soon(checkBlacklist); + }, "blocklist-data-gfxItems", false); + + load_blocklist("test_gfxBlacklist.xml"); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_No_Comparison.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_No_Comparison.js new file mode 100644 index 000000000..61372cff8 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_No_Comparison.js @@ -0,0 +1,89 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test whether a machine which exactly matches the blacklist entry is +// successfully blocked. +// Uses test_gfxBlacklist.xml + +Components.utils.import("resource://testing-common/httpd.js"); + +var gTestserver = new HttpServer(); +gTestserver.start(-1); +gPort = gTestserver.identity.primaryPort; +mapFile("/data/test_gfxBlacklist.xml", gTestserver); + +function get_platform() { + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); + return xulRuntime.OS; +} + +function load_blocklist(file) { + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + + gPort + "/data/" + file); + var blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. + getService(Ci.nsITimerCallback); + blocklist.notify(null); +} + +// Performs the initial setup +function run_test() { + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } + + // We can't do anything if we can't spoof the stuff we need. + if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { + do_test_finished(); + return; + } + + gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug); + + gfxInfo.spoofVendorID("0xabcd"); + gfxInfo.spoofDeviceID("0x6666"); + + // Spoof the OS version so it matches the test file. + switch (get_platform()) { + case "WINNT": + // Windows 7 + gfxInfo.spoofOSVersion(0x60001); + break; + case "Linux": + break; + case "Darwin": + gfxInfo.spoofOSVersion(0x1050); + break; + case "Android": + break; + } + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); + startupManager(); + + do_test_pending(); + + function checkBlacklist() + { + var status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT2D); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_BLOCKED_DEVICE); + + // Make sure unrelated features aren't affected + status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT3D_9_LAYERS); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + + gTestserver.stop(do_test_finished); + } + + Services.obs.addObserver(function(aSubject, aTopic, aData) { + // If we wait until after we go through the event loop, gfxInfo is sure to + // have processed the gfxItems event. + do_execute_soon(checkBlacklist); + }, "blocklist-data-gfxItems", false); + + load_blocklist("test_gfxBlacklist.xml"); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OK.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OK.js new file mode 100644 index 000000000..dcd578dfb --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OK.js @@ -0,0 +1,96 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test whether a machine which exactly matches the blacklist entry is +// successfully blocked. +// Uses test_gfxBlacklist.xml + +Components.utils.import("resource://testing-common/httpd.js"); + +var gTestserver = new HttpServer(); +gTestserver.start(-1); +gPort = gTestserver.identity.primaryPort; +mapFile("/data/test_gfxBlacklist.xml", gTestserver); + +function get_platform() { + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); + return xulRuntime.OS; +} + +function load_blocklist(file) { + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + + gPort + "/data/" + file); + var blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. + getService(Ci.nsITimerCallback); + blocklist.notify(null); +} + +// Performs the initial setup +function run_test() { + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } + + // We can't do anything if we can't spoof the stuff we need. + if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { + do_test_finished(); + return; + } + + gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug); + + // Set the vendor/device ID, etc, to match the test file. + switch (get_platform()) { + case "WINNT": + gfxInfo.spoofVendorID("0xabcd"); + gfxInfo.spoofDeviceID("0x1234"); + gfxInfo.spoofDriverVersion("8.52.322.2201"); + // Windows 7 + gfxInfo.spoofOSVersion(0x60001); + break; + case "Linux": + gfxInfo.spoofVendorID("0xabcd"); + gfxInfo.spoofDeviceID("0x1234"); + break; + case "Darwin": + gfxInfo.spoofVendorID("0xabcd"); + gfxInfo.spoofDeviceID("0x1234"); + gfxInfo.spoofOSVersion(0x1050); + break; + case "Android": + gfxInfo.spoofVendorID("abcd"); + gfxInfo.spoofDeviceID("asdf"); + gfxInfo.spoofDriverVersion("5"); + break; + } + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); + startupManager(); + + do_test_pending(); + + function checkBlacklist() + { + var status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT2D); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_BLOCKED_DRIVER_VERSION); + + // Make sure unrelated features aren't affected + status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT3D_9_LAYERS); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + + gTestserver.stop(do_test_finished); + } + + Services.obs.addObserver(function(aSubject, aTopic, aData) { + // If we wait until after we go through the event loop, gfxInfo is sure to + // have processed the gfxItems event. + do_execute_soon(checkBlacklist); + }, "blocklist-data-gfxItems", false); + + load_blocklist("test_gfxBlacklist.xml"); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OS.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OS.js new file mode 100644 index 000000000..81edc9cd1 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OS.js @@ -0,0 +1,96 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test whether a machine which differs only on OS version, but otherwise +// exactly matches the blacklist entry, is not blocked. +// Uses test_gfxBlacklist.xml + +Components.utils.import("resource://testing-common/httpd.js"); + +var gTestserver = new HttpServer(); +gTestserver.start(-1); +gPort = gTestserver.identity.primaryPort; +mapFile("/data/test_gfxBlacklist.xml", gTestserver); + +function get_platform() { + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); + return xulRuntime.OS; +} + +function load_blocklist(file) { + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + + gPort + "/data/" + file); + var blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. + getService(Ci.nsITimerCallback); + blocklist.notify(null); +} + +// Performs the initial setup +function run_test() { + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } + + // We can't do anything if we can't spoof the stuff we need. + if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { + do_test_finished(); + return; + } + + gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug); + + // Set the vendor/device ID, etc, to match the test file. + switch (get_platform()) { + case "WINNT": + gfxInfo.spoofVendorID("0xabcd"); + gfxInfo.spoofDeviceID("0x1234"); + gfxInfo.spoofDriverVersion("8.52.322.2201"); + // Windows Vista + gfxInfo.spoofOSVersion(0x60000); + break; + case "Linux": + // We don't have any OS versions on Linux, just "Linux". + do_test_finished(); + return; + case "Darwin": + gfxInfo.spoofVendorID("0xabcd"); + gfxInfo.spoofDeviceID("0x1234"); + // Snow Leopard + gfxInfo.spoofOSVersion(0x1060); + break; + case "Android": + // On Android, the driver version is used as the OS version (because + // there's so many of them). + do_test_finished(); + return; + } + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); + startupManager(); + + do_test_pending(); + + function checkBlacklist() + { + var status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT2D); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + + status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT3D_9_LAYERS); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + + gTestserver.stop(do_test_finished); + } + + Services.obs.addObserver(function(aSubject, aTopic, aData) { + // If we wait until after we go through the event loop, gfxInfo is sure to + // have processed the gfxItems event. + do_execute_soon(checkBlacklist); + }, "blocklist-data-gfxItems", false); + + load_blocklist("test_gfxBlacklist.xml"); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_match.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_match.js new file mode 100644 index 000000000..3472c6d7e --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_match.js @@ -0,0 +1,96 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test whether new OS versions are matched properly. +// Uses test_gfxBlacklist_OS.xml + +Components.utils.import("resource://testing-common/httpd.js"); + +var gTestserver = new HttpServer(); +gTestserver.start(-1); +gPort = gTestserver.identity.primaryPort; + +function get_platform() { + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); + return xulRuntime.OS; +} + +function load_blocklist(file) { + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + + gPort + "/data/" + file); + var blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. + getService(Ci.nsITimerCallback); + blocklist.notify(null); +} + +// Performs the initial setup +function run_test() { + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } + + // We can't do anything if we can't spoof the stuff we need. + if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { + do_test_finished(); + return; + } + + gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug); + + // Set the vendor/device ID, etc, to match the test file. + gfxInfo.spoofDriverVersion("8.52.322.2201"); + gfxInfo.spoofVendorID("0xabcd"); + gfxInfo.spoofDeviceID("0x1234"); + + // Spoof the version of the OS appropriately to test the test file. + switch (get_platform()) { + case "WINNT": + // Windows 8 + gfxInfo.spoofOSVersion(0x60002); + break; + case "Linux": + // We don't have any OS versions on Linux, just "Linux". + do_test_finished(); + return; + case "Darwin": + // Mountain Lion + gfxInfo.spoofOSVersion(0x1080); + break; + case "Android": + // On Android, the driver version is used as the OS version (because + // there's so many of them). + do_test_finished(); + return; + } + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); + startupManager(); + + do_test_pending(); + + function checkBlacklist() + { + if (get_platform() == "WINNT") { + var status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT2D); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_BLOCKED_DRIVER_VERSION); + } else if (get_platform() == "Darwin") { + status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_OPENGL_LAYERS); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_BLOCKED_DRIVER_VERSION); + } + + gTestserver.stop(do_test_finished); + } + + Services.obs.addObserver(function(aSubject, aTopic, aData) { + // If we wait until after we go through the event loop, gfxInfo is sure to + // have processed the gfxItems event. + do_execute_soon(checkBlacklist); + }, "blocklist-data-gfxItems", false); + + load_blocklist("test_gfxBlacklist_OS.xml"); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_mismatch_DriverVersion.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_mismatch_DriverVersion.js new file mode 100644 index 000000000..fb25b9509 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_mismatch_DriverVersion.js @@ -0,0 +1,97 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test whether blocklists specifying new OSeswcorrectly don't block if driver +// versions are appropriately up-to-date. +// Uses test_gfxBlacklist_OS.xml + +Components.utils.import("resource://testing-common/httpd.js"); + +var gTestserver = new HttpServer(); +gTestserver.start(-1); +gPort = gTestserver.identity.primaryPort; + +function get_platform() { + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); + return xulRuntime.OS; +} + +function load_blocklist(file) { + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + + gPort + "/data/" + file); + var blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. + getService(Ci.nsITimerCallback); + blocklist.notify(null); +} + +// Performs the initial setup +function run_test() { + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } + + // We can't do anything if we can't spoof the stuff we need. + if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { + do_test_finished(); + return; + } + + gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug); + + // Set the vendor/device ID, etc, to match the test file. + gfxInfo.spoofDriverVersion("8.52.322.2202"); + gfxInfo.spoofVendorID("0xabcd"); + gfxInfo.spoofDeviceID("0x1234"); + + // Spoof the version of the OS appropriately to test the test file. + switch (get_platform()) { + case "WINNT": + // Windows 8 + gfxInfo.spoofOSVersion(0x60002); + break; + case "Linux": + // We don't have any OS versions on Linux, just "Linux". + do_test_finished(); + return; + case "Darwin": + // Mountain Lion + gfxInfo.spoofOSVersion(0x1080); + break; + case "Android": + // On Android, the driver version is used as the OS version (because + // there's so many of them). + do_test_finished(); + return; + } + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); + startupManager(); + + do_test_pending(); + + function checkBlacklist() + { + if (get_platform() == "WINNT") { + var status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT2D); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + } else if (get_platform() == "Darwin") { + status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_OPENGL_LAYERS); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + } + + gTestserver.stop(do_test_finished); + } + + Services.obs.addObserver(function(aSubject, aTopic, aData) { + // If we wait until after we go through the event loop, gfxInfo is sure to + // have processed the gfxItems event. + do_execute_soon(checkBlacklist); + }, "blocklist-data-gfxItems", false); + + load_blocklist("test_gfxBlacklist_OS.xml"); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_mismatch_OSVersion.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_mismatch_OSVersion.js new file mode 100644 index 000000000..4fb162262 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OSVersion_mismatch_OSVersion.js @@ -0,0 +1,97 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test whether old OS versions are not matched when the blacklist contains +// only new OS versions. +// Uses test_gfxBlacklist_OS.xml + +Components.utils.import("resource://testing-common/httpd.js"); + +var gTestserver = new HttpServer(); +gTestserver.start(-1); +gPort = gTestserver.identity.primaryPort; + +function get_platform() { + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); + return xulRuntime.OS; +} + +function load_blocklist(file) { + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + + gPort + "/data/" + file); + var blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. + getService(Ci.nsITimerCallback); + blocklist.notify(null); +} + +// Performs the initial setup +function run_test() { + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } + + // We can't do anything if we can't spoof the stuff we need. + if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { + do_test_finished(); + return; + } + + gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug); + + // Set the vendor/device ID, etc, to match the test file. + gfxInfo.spoofDriverVersion("8.52.322.2201"); + gfxInfo.spoofVendorID("0xabcd"); + gfxInfo.spoofDeviceID("0x1234"); + + // Spoof the version of the OS appropriately to test the test file. + switch (get_platform()) { + case "WINNT": + // Windows 7 + gfxInfo.spoofOSVersion(0x60001); + break; + case "Linux": + // We don't have any OS versions on Linux, just "Linux". + do_test_finished(); + return; + case "Darwin": + // Lion + gfxInfo.spoofOSVersion(0x1070); + break; + case "Android": + // On Android, the driver version is used as the OS version (because + // there's so many of them). + do_test_finished(); + return; + } + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); + startupManager(); + + do_test_pending(); + + function checkBlacklist() + { + if (get_platform() == "WINNT") { + var status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT2D); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + } else if (get_platform() == "Darwin") { + status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_OPENGL_LAYERS); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + } + + gTestserver.stop(do_test_finished); + } + + Services.obs.addObserver(function(aSubject, aTopic, aData) { + // If we wait until after we go through the event loop, gfxInfo is sure to + // have processed the gfxItems event. + do_execute_soon(checkBlacklist); + }, "blocklist-data-gfxItems", false); + + load_blocklist("test_gfxBlacklist_OS.xml"); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Vendor.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Vendor.js new file mode 100644 index 000000000..a5d1c71cf --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Vendor.js @@ -0,0 +1,95 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test whether a machine which differs only on vendor, but otherwise +// exactly matches the blacklist entry, is not blocked. +// Uses test_gfxBlacklist.xml + +Components.utils.import("resource://testing-common/httpd.js"); + +var gTestserver = new HttpServer(); +gTestserver.start(-1); +gPort = gTestserver.identity.primaryPort; +mapFile("/data/test_gfxBlacklist.xml", gTestserver); + +function get_platform() { + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); + return xulRuntime.OS; +} + +function load_blocklist(file) { + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + + gPort + "/data/" + file); + var blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. + getService(Ci.nsITimerCallback); + blocklist.notify(null); +} + +// Performs the initial setup +function run_test() { + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } + + // We can't do anything if we can't spoof the stuff we need. + if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { + do_test_finished(); + return; + } + + gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug); + + // Set the vendor/device ID, etc, to match the test file. + switch (get_platform()) { + case "WINNT": + gfxInfo.spoofVendorID("0xdcba"); + gfxInfo.spoofDeviceID("0x1234"); + gfxInfo.spoofDriverVersion("8.52.322.2201"); + // Windows 7 + gfxInfo.spoofOSVersion(0x60001); + break; + case "Linux": + gfxInfo.spoofVendorID("0xdcba"); + gfxInfo.spoofDeviceID("0x1234"); + break; + case "Darwin": + gfxInfo.spoofVendorID("0xdcba"); + gfxInfo.spoofDeviceID("0x1234"); + gfxInfo.spoofOSVersion(0x1050); + break; + case "Android": + gfxInfo.spoofVendorID("dcba"); + gfxInfo.spoofDeviceID("asdf"); + gfxInfo.spoofDriverVersion("5"); + break; + } + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); + startupManager(); + + do_test_pending(); + + function checkBlacklist() + { + var status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT2D); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + + status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT3D_9_LAYERS); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + + gTestserver.stop(do_test_finished); + } + + Services.obs.addObserver(function(aSubject, aTopic, aData) { + // If we wait until after we go through the event loop, gfxInfo is sure to + // have processed the gfxItems event. + do_execute_soon(checkBlacklist); + }, "blocklist-data-gfxItems", false); + + load_blocklist("test_gfxBlacklist.xml"); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_prefs.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_prefs.js new file mode 100644 index 000000000..bb0e55e2c --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_prefs.js @@ -0,0 +1,132 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test whether the blacklist succesfully adds and removes the prefs that store +// its decisions when the remote blacklist is changed. +// Uses test_gfxBlacklist.xml and test_gfxBlacklist2.xml + +Components.utils.import("resource://testing-common/httpd.js"); + +var gTestserver = new HttpServer(); +gTestserver.start(-1); +gPort = gTestserver.identity.primaryPort; +mapFile("/data/test_gfxBlacklist.xml", gTestserver); + +function get_platform() { + var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); + return xulRuntime.OS; +} + +function load_blocklist(file) { + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + + gPort + "/data/" + file); + var blocklist = Cc["@mozilla.org/extensions/blocklist;1"]. + getService(Ci.nsITimerCallback); + blocklist.notify(null); +} + +// Performs the initial setup +function run_test() { + try { + var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + } catch (e) { + do_test_finished(); + return; + } + + // We can't do anything if we can't spoof the stuff we need. + if (!(gfxInfo instanceof Ci.nsIGfxInfoDebug)) { + do_test_finished(); + return; + } + + gfxInfo.QueryInterface(Ci.nsIGfxInfoDebug); + + // Set the vendor/device ID, etc, to match the test file. + switch (get_platform()) { + case "WINNT": + gfxInfo.spoofVendorID("0xabcd"); + gfxInfo.spoofDeviceID("0x1234"); + gfxInfo.spoofDriverVersion("8.52.322.2201"); + // Windows 7 + gfxInfo.spoofOSVersion(0x60001); + break; + case "Linux": + gfxInfo.spoofVendorID("0xabcd"); + gfxInfo.spoofDeviceID("0x1234"); + break; + case "Darwin": + gfxInfo.spoofVendorID("0xabcd"); + gfxInfo.spoofDeviceID("0x1234"); + gfxInfo.spoofOSVersion(0x1050); + break; + case "Android": + gfxInfo.spoofVendorID("abcd"); + gfxInfo.spoofDeviceID("asdf"); + gfxInfo.spoofDriverVersion("5"); + break; + } + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); + startupManager(); + + do_test_pending(); + + function blacklistAdded(aSubject, aTopic, aData) + { + // If we wait until after we go through the event loop, gfxInfo is sure to + // have processed the gfxItems event. + do_execute_soon(ensureBlacklistSet); + } + function ensureBlacklistSet() + { + var status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT2D); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_BLOCKED_DRIVER_VERSION); + + // Make sure unrelated features aren't affected + status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT3D_9_LAYERS); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + + var prefs = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefBranch); + do_check_eq(prefs.getIntPref("gfx.blacklist.direct2d"), + Ci.nsIGfxInfo.FEATURE_BLOCKED_DRIVER_VERSION); + + Services.obs.removeObserver(blacklistAdded, "blocklist-data-gfxItems"); + Services.obs.addObserver(blacklistRemoved, "blocklist-data-gfxItems", false); + load_blocklist("test_gfxBlacklist2.xml"); + } + + function blacklistRemoved(aSubject, aTopic, aData) + { + // If we wait until after we go through the event loop, gfxInfo is sure to + // have processed the gfxItems event. + do_execute_soon(ensureBlacklistUnset); + } + function ensureBlacklistUnset() + { + var status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT2D); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + + // Make sure unrelated features aren't affected + status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT3D_9_LAYERS); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + + var prefs = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefBranch); + var exists = false; + try { + prefs.getIntPref("gfx.blacklist.direct2d"); + exists = true; + } catch(e) {} + + do_check_false(exists); + + gTestserver.stop(do_test_finished); + } + + Services.obs.addObserver(blacklistAdded, "blocklist-data-gfxItems", false); + load_blocklist("test_gfxBlacklist.xml"); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gmpProvider.js b/toolkit/mozapps/extensions/test/xpcshell/test_gmpProvider.js new file mode 100644 index 000000000..8de3ab4a2 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gmpProvider.js @@ -0,0 +1,332 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const {classes: Cc, interfaces: Ci, utils: Cu} = Components; +let GMPScope = Cu.import("resource://gre/modules/addons/GMPProvider.jsm"); + +XPCOMUtils.defineLazyGetter(this, "pluginsBundle", + () => Services.strings.createBundle("chrome://global/locale/plugins.properties")); + +let gMockAddons = new Map(); +let gMockEmeAddons = new Map(); + +for (let plugin of GMPScope.GMP_PLUGINS) { + let mockAddon = Object.freeze({ + id: plugin.id, + isValid: true, + isInstalled: false, + nameId: plugin.name, + descriptionId: plugin.description, + }); + gMockAddons.set(mockAddon.id, mockAddon); + if (mockAddon.id.indexOf("gmp-eme-") == 0) { + gMockEmeAddons.set(mockAddon.id, mockAddon); + } +} + +let gInstalledAddonId = ""; +let gPrefs = Services.prefs; +let gGetKey = GMPScope.GMPPrefs.getPrefKey; + +function MockGMPInstallManager() { +} + +MockGMPInstallManager.prototype = { + checkForAddons: () => Promise.resolve([...gMockAddons.values()]), + + installAddon: addon => { + gInstalledAddonId = addon.id; + return Promise.resolve(); + }, +}; + + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + startupManager(); + + gPrefs.setBoolPref(GMPScope.GMPPrefs.KEY_LOGGING_DUMP, true); + gPrefs.setIntPref(GMPScope.GMPPrefs.KEY_LOGGING_LEVEL, 0); + gPrefs.setBoolPref(GMPScope.GMPPrefs.KEY_EME_ENABLED, true); + for (let addon of gMockAddons.values()) { + gPrefs.setBoolPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCEVISIBLE, addon.id), + true); + } + GMPScope.GMPProvider.shutdown(); + GMPScope.GMPProvider.startup(); + + run_next_test(); +} + +add_task(function* test_notInstalled() { + for (let addon of gMockAddons.values()) { + gPrefs.setCharPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, addon.id), ""); + gPrefs.setBoolPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_ENABLED, addon.id), false); + } + + let addons = yield promiseAddonsByIDs([...gMockAddons.keys()]); + Assert.equal(addons.length, gMockAddons.size); + + for (let addon of addons) { + Assert.ok(!addon.isInstalled); + Assert.equal(addon.type, "plugin"); + Assert.equal(addon.version, ""); + + let mockAddon = gMockAddons.get(addon.id); + + Assert.notEqual(mockAddon, null); + let name = pluginsBundle.GetStringFromName(mockAddon.nameId); + Assert.equal(addon.name, name); + let description = pluginsBundle.GetStringFromName(mockAddon.descriptionId); + Assert.equal(addon.description, description); + + Assert.ok(!addon.isActive); + Assert.ok(!addon.appDisabled); + Assert.ok(addon.userDisabled); + + Assert.equal(addon.blocklistState, Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + Assert.equal(addon.size, 0); + Assert.equal(addon.scope, AddonManager.SCOPE_APPLICATION); + Assert.equal(addon.pendingOperations, AddonManager.PENDING_NONE); + Assert.equal(addon.operationsRequiringRestart, AddonManager.PENDING_NONE); + + Assert.equal(addon.permissions, AddonManager.PERM_CAN_UPGRADE | + AddonManager.PERM_CAN_ENABLE); + + Assert.equal(addon.updateDate, null); + + Assert.ok(addon.isCompatible); + Assert.ok(addon.isPlatformCompatible); + Assert.ok(addon.providesUpdatesSecurely); + Assert.ok(!addon.foreignInstall); + + let mimetypes = addon.pluginMimeTypes; + Assert.ok(mimetypes); + Assert.equal(mimetypes.length, 0); + let libraries = addon.pluginLibraries; + Assert.ok(libraries); + Assert.equal(libraries.length, 0); + Assert.equal(addon.pluginFullpath, ""); + } +}); + +add_task(function* test_installed() { + const TEST_DATE = new Date(2013, 0, 1, 12); + const TEST_VERSION = "1.2.3.4"; + const TEST_TIME_SEC = Math.round(TEST_DATE.getTime() / 1000); + + let addons = yield promiseAddonsByIDs([...gMockAddons.keys()]); + Assert.equal(addons.length, gMockAddons.size); + + for (let addon of addons) { + let mockAddon = gMockAddons.get(addon.id); + Assert.notEqual(mockAddon, null); + + let file = Services.dirsvc.get("ProfD", Ci.nsIFile); + file.append(addon.id); + file.append(TEST_VERSION); + gPrefs.setBoolPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_ENABLED, mockAddon.id), false); + gPrefs.setCharPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_LAST_UPDATE, mockAddon.id), + "" + TEST_TIME_SEC); + gPrefs.setCharPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, mockAddon.id), + TEST_VERSION); + + Assert.ok(addon.isInstalled); + Assert.equal(addon.type, "plugin"); + Assert.ok(!addon.isActive); + Assert.ok(!addon.appDisabled); + Assert.ok(addon.userDisabled); + + let name = pluginsBundle.GetStringFromName(mockAddon.nameId); + Assert.equal(addon.name, name); + Assert.equal(addon.version, TEST_VERSION); + + Assert.equal(addon.permissions, AddonManager.PERM_CAN_UPGRADE | + AddonManager.PERM_CAN_ENABLE); + + Assert.equal(addon.updateDate.getTime(), TEST_TIME_SEC * 1000); + + let mimetypes = addon.pluginMimeTypes; + Assert.ok(mimetypes); + Assert.equal(mimetypes.length, 0); + let libraries = addon.pluginLibraries; + Assert.ok(libraries); + Assert.equal(libraries.length, 1); + Assert.equal(libraries[0], TEST_VERSION); + let fullpath = addon.pluginFullpath; + Assert.equal(fullpath.length, 1); + Assert.equal(fullpath[0], file.path); + } +}); + +add_task(function* test_enable() { + let addons = yield promiseAddonsByIDs([...gMockAddons.keys()]); + Assert.equal(addons.length, gMockAddons.size); + + for (let addon of addons) { + gPrefs.setBoolPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_ENABLED, addon.id), true); + + Assert.ok(addon.isActive); + Assert.ok(!addon.appDisabled); + Assert.ok(!addon.userDisabled); + + Assert.equal(addon.permissions, AddonManager.PERM_CAN_UPGRADE | + AddonManager.PERM_CAN_DISABLE); + } +}); + +add_task(function* test_globalEmeDisabled() { + let addons = yield promiseAddonsByIDs([...gMockEmeAddons.keys()]); + Assert.equal(addons.length, gMockEmeAddons.size); + + gPrefs.setBoolPref(GMPScope.GMPPrefs.KEY_EME_ENABLED, false); + GMPScope.GMPProvider.shutdown(); + GMPScope.GMPProvider.startup(); + for (let addon of addons) { + Assert.ok(!addon.isActive); + Assert.ok(addon.appDisabled); + Assert.ok(!addon.userDisabled); + + Assert.equal(addon.permissions, 0); + } + gPrefs.setBoolPref(GMPScope.GMPPrefs.KEY_EME_ENABLED, true); + GMPScope.GMPProvider.shutdown(); + GMPScope.GMPProvider.startup(); +}); + +add_task(function* test_autoUpdatePrefPersistance() { + let addons = yield promiseAddonsByIDs([...gMockAddons.keys()]); + Assert.equal(addons.length, gMockAddons.size); + + for (let addon of addons) { + let autoupdateKey = gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_AUTOUPDATE, addon.id); + gPrefs.clearUserPref(autoupdateKey); + + addon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE; + Assert.ok(!gPrefs.getBoolPref(autoupdateKey)); + + addon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_ENABLE; + Assert.equal(addon.applyBackgroundUpdates, AddonManager.AUTOUPDATE_ENABLE); + Assert.ok(gPrefs.getBoolPref(autoupdateKey)); + + addon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DEFAULT; + Assert.ok(!gPrefs.prefHasUserValue(autoupdateKey)); + } +}); + +add_task(function* test_pluginRegistration() { + const TEST_VERSION = "1.2.3.4"; + + for (let addon of gMockAddons.values()) { + let file = Services.dirsvc.get("ProfD", Ci.nsIFile); + file.append(addon.id); + file.append(TEST_VERSION); + + let addedPaths = []; + let removedPaths = []; + let clearPaths = () => { addedPaths = []; removedPaths = []; } + + let MockGMPService = { + addPluginDirectory: path => addedPaths.push(path), + removePluginDirectory: path => removedPaths.push(path), + removeAndDeletePluginDirectory: path => removedPaths.push(path), + }; + + GMPScope.gmpService = MockGMPService; + gPrefs.setBoolPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_ENABLED, addon.id), true); + + // Check that the plugin gets registered after startup. + gPrefs.setCharPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, addon.id), + TEST_VERSION); + clearPaths(); + yield promiseRestartManager(); + Assert.notEqual(addedPaths.indexOf(file.path), -1); + Assert.deepEqual(removedPaths, []); + + // Check that clearing the version doesn't trigger registration. + clearPaths(); + gPrefs.clearUserPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, addon.id)); + Assert.deepEqual(addedPaths, []); + Assert.deepEqual(removedPaths, [file.path]); + + // Restarting with no version set should not trigger registration. + clearPaths(); + yield promiseRestartManager(); + Assert.equal(addedPaths.indexOf(file.path), -1); + Assert.equal(removedPaths.indexOf(file.path), -1); + + // Changing the pref mid-session should cause unregistration and registration. + gPrefs.setCharPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, addon.id), + TEST_VERSION); + clearPaths(); + const TEST_VERSION_2 = "5.6.7.8"; + let file2 = Services.dirsvc.get("ProfD", Ci.nsIFile); + file2.append(addon.id); + file2.append(TEST_VERSION_2); + gPrefs.setCharPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, addon.id), + TEST_VERSION_2); + Assert.deepEqual(addedPaths, [file2.path]); + Assert.deepEqual(removedPaths, [file.path]); + + // Disabling the plugin should cause unregistration. + gPrefs.setCharPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, addon.id), + TEST_VERSION); + clearPaths(); + gPrefs.setBoolPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_ENABLED, addon.id), false); + Assert.deepEqual(addedPaths, []); + Assert.deepEqual(removedPaths, [file.path]); + + // Restarting with the plugin disabled should not cause registration. + clearPaths(); + yield promiseRestartManager(); + Assert.equal(addedPaths.indexOf(file.path), -1); + Assert.equal(removedPaths.indexOf(file.path), -1); + + // Re-enabling the plugin should cause registration. + clearPaths(); + gPrefs.setBoolPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_ENABLED, addon.id), true); + Assert.deepEqual(addedPaths, [file.path]); + Assert.deepEqual(removedPaths, []); + GMPScope = Cu.import("resource://gre/modules/addons/GMPProvider.jsm"); + } +}); + +add_task(function* test_periodicUpdate() { + Object.defineProperty(GMPScope, "GMPInstallManager", { + value: MockGMPInstallManager, + writable: true, + enumerable: true, + configurable: true + }); + + let addons = yield promiseAddonsByIDs([...gMockAddons.keys()]); + Assert.equal(addons.length, gMockAddons.size); + + for (let addon of addons) { + gPrefs.clearUserPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_AUTOUPDATE, addon.id)); + + addon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE; + gPrefs.setIntPref(GMPScope.GMPPrefs.KEY_UPDATE_LAST_CHECK, 0); + let result = + yield addon.findUpdates({}, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); + Assert.strictEqual(result, false); + + addon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_ENABLE; + gPrefs.setIntPref(GMPScope.GMPPrefs.KEY_UPDATE_LAST_CHECK, Date.now() / 1000 - 60); + result = + yield addon.findUpdates({}, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); + Assert.strictEqual(result, false); + + gPrefs.setIntPref(GMPScope.GMPPrefs.KEY_UPDATE_LAST_CHECK, + Date.now() / 1000 - 2 * GMPScope.SEC_IN_A_DAY); + gInstalledAddonId = ""; + result = + yield addon.findUpdates({}, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); + Assert.strictEqual(result, true); + Assert.equal(gInstalledAddonId, addon.id); + } + + GMPScope = Cu.import("resource://gre/modules/addons/GMPProvider.jsm"); +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_hasbinarycomponents.js b/toolkit/mozapps/extensions/test/xpcshell/test_hasbinarycomponents.js new file mode 100644 index 000000000..598e06ed0 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_hasbinarycomponents.js @@ -0,0 +1,82 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests detection of binary components via parsing of chrome manifests. + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2"); + + startupManager(); + + installAllFiles([do_get_addon("test_chromemanifest_1"), + do_get_addon("test_chromemanifest_2"), + do_get_addon("test_chromemanifest_3"), + do_get_addon("test_chromemanifest_4"), + do_get_addon("test_chromemanifest_5")], + function() { + + restartManager(); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org"], + function([a1, a2, a3, a4, a5]) { + // addon1 has no binary components + do_check_neq(a1, null); + do_check_false(a1.userDisabled); + do_check_false(a1.hasBinaryComponents); + do_check_true(a1.isCompatible); + do_check_false(a1.appDisabled); + do_check_true(a1.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); + + // addon2 has a binary component, is compatible + do_check_neq(a2, null); + do_check_false(a2.userDisabled); + do_check_true(a2.hasBinaryComponents); + do_check_true(a2.isCompatible); + do_check_false(a2.appDisabled); + do_check_true(a2.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a2.id)); + + // addon3 has a binary component, is incompatible + do_check_neq(a3, null); + do_check_false(a3.userDisabled); + do_check_true(a2.hasBinaryComponents); + do_check_false(a3.isCompatible); + do_check_true(a3.appDisabled); + do_check_false(a3.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a3.id)); + + // addon4 has a binary component listed in a sub-manifest, is incompatible + do_check_neq(a4, null); + do_check_false(a4.userDisabled); + do_check_true(a2.hasBinaryComponents); + do_check_false(a4.isCompatible); + do_check_true(a4.appDisabled); + do_check_false(a4.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a4.id)); + + // addon5 has a binary component, but is set to not unpack + do_check_neq(a5, null); + do_check_false(a5.userDisabled); + if (TEST_UNPACKED) + do_check_true(a5.hasBinaryComponents); + else + do_check_false(a5.hasBinaryComponents); + do_check_true(a5.isCompatible); + do_check_false(a5.appDisabled); + do_check_true(a5.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a5.id)); + + do_execute_soon(do_test_finished); + }); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_install.js b/toolkit/mozapps/extensions/test/xpcshell/test_install.js new file mode 100644 index 000000000..16db604c5 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_install.js @@ -0,0 +1,1761 @@ +/* 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 +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; + +// 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; + +// install.rdf size, icon.png, icon64.png size +const ADDON1_SIZE = 705 + 16 + 16; + +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); +Cu.import("resource://testing-common/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, false); + +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 HttpServer(); + 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(-1); + gPort = testserver.identity.primaryPort; + + 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_neq(install.addon.syncGUID, null); + 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", + ], function() { + check_test_1(install.addon.syncGUID); + }); + install.install(); + }); + }); + }); + }); +} + +function check_test_1(installSyncGUID) { + ensure_test_completed(); + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(olda1) { + do_check_eq(olda1, null); + + AddonManager.getAddonsWithOperationsByTypes(null, callback_soon(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", callback_soon(function(a1) { + do_check_neq(a1, null); + do_check_neq(a1.syncGUID, null); + do_check_true(a1.syncGUID.length >= 9); + do_check_eq(a1.syncGUID, installSyncGUID); + 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_false(a1.foreignInstall); + + 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); + + do_execute_soon(run_test_2); + })); + }); + })); + }); +} + +// Tests that an install from a url downloads. +function run_test_2() { + let url = "http://localhost:" + gPort + "/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", callback_soon(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_neq(a2.syncGUID, 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:" + gPort + "/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:" + gPort + "/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, callback_soon(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:" + gPort + "/addons/test_install2_2.xpi"); + do_check_false(a2.foreignInstall); + + 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(); + do_execute_soon(run_test_6); + }); + }); + })); + }); +} + +// Tests that an install that requires a compatibility update works +function run_test_6() { + restartManager(); + + prepare_test({ }, [ + "onNewInstall" + ]); + + let url = "http://localhost:" + gPort + "/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", callback_soon(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_neq(a3.syncGUID, 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(); + do_execute_soon(run_test_8); + }); + }); + })); +} + +function run_test_8() { + restartManager(); + + 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", + ], callback_soon(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_neq(a3.syncGUID, 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(); + do_execute_soon(run_test_9); + }); +} + +// Test that after cancelling a download it is removed from the active installs +function run_test_9() { + restartManager(); + + prepare_test({ }, [ + "onNewInstall" + ]); + + let url = "http://localhost:" + gPort + "/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" + ], function() { + let file = install.file; + + // Allow the file removal to complete + do_execute_soon(function() { + AddonManager.getAllInstalls(function(activeInstalls) { + do_check_eq(activeInstalls.length, 0); + do_check_false(file.exists()); + + run_test_10(); + }); + }); + }); + + install.cancel(); +} + +// 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:" + gPort + "/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(callback_soon(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); + + do_execute_soon(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 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_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_true(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" + ], + "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" + ] + }, callback_soon(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(); + + do_execute_soon(run_test_12); + }); +} + +// Same as test 11 but for a remote XPI +function run_test_12() { + restartManager(); + + prepare_test({ }, [ + "onNewInstall", + ]); + + let url = "http://localhost:" + gPort + "/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" + ], + "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" + ] + }, callback_soon(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 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_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); + + // 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(); + + do_execute_soon(run_test_13); + }); +} + + +// Tests that cancelling an upgrade leaves the original add-on's pendingOperations +// correct +function run_test_13() { + restartManager(); + + installAllFiles([do_get_addon("test_install2_1")], function() { + restartManager(); + + prepare_test({ }, [ + "onNewInstall" + ]); + + let url = "http://localhost:" + gPort + "/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", callback_soon(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(); + + do_execute_soon(run_test_14); + }); + })); +} + +// Check that cancelling the install from onDownloadStarted actually cancels it +function run_test_14() { + restartManager(); + + prepare_test({ }, [ + "onNewInstall" + ]); + + let url = "http://localhost:" + gPort + "/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" + ], function() { + let file = install.file; + + 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_false(file.exists()); + + run_test_15(); + }); + }); + + // Wait for the channel to be ready to cancel + do_execute_soon(function() { + install.cancel(); + }); +} + +// Checks that cancelling the install from onDownloadEnded actually cancels it +function run_test_15() { + prepare_test({ }, [ + "onNewInstall" + ]); + + let url = "http://localhost:" + gPort + "/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:" + gPort + "/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() { + do_execute_soon(function install2_1_ended() { + restartManager(); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_true(a2.userDisabled); + do_check_false(a2.isActive); + + let url = "http://localhost:" + gPort + "/addons/test_install2_2.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ + onInstallEnded: function() { + do_execute_soon(function install2_2_ended() { + 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(); + do_execute_soon(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() { + restartManager(); + + let url = "http://localhost:" + gPort + "/addons/test_install2_1.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ + onInstallEnded: function() { + do_execute_soon(function install2_1_ended2() { + 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:" + gPort + "/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() { + do_execute_soon(function install2_2_ended2() { + restartManager(); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_true(a2.userDisabled); + do_check_false(a2.isActive); + + a2.uninstall(); + do_execute_soon(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() { + restartManager(); + + let url = "http://localhost:" + gPort + "/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() { + do_execute_soon(function install_2_1_ended3() { + restartManager(); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_true(a2.userDisabled); + do_check_false(a2.isActive); + + let url = "http://localhost:" + gPort + "/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() { + do_execute_soon(function install_2_2_ended3() { + restartManager(); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_false(a2.userDisabled); + do_check_true(a2.isActive); + + a2.uninstall(); + do_execute_soon(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() { + restartManager(); + + Services.prefs.setBoolPref("extensions.getAddons.cache.enabled", true); + Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, + "http://localhost:" + gPort + "/data/test_install.xml"); + + Services.prefs.setBoolPref("extensions.addon2@tests.mozilla.org.getAddons.cache.enabled", false); + + let url = "http://localhost:" + gPort + "/addons/test_install2_1.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ + onInstallEnded: function(aInstall, aAddon) { + do_execute_soon(function test18_1_install_ended() { + 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(); + do_execute_soon(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() { + restartManager(); + Services.prefs.setBoolPref("extensions.addon2@tests.mozilla.org.getAddons.cache.enabled", true); + + let url = "http://localhost:" + gPort + "/addons/test_install2_1.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ + onInstallEnded: function(aInstall, aAddon) { + do_execute_soon(function test19_install_ended() { + 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(); + do_execute_soon(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() { + restartManager(); + + let url = "http://localhost:" + gPort + "/addons/test_install2_1.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ + onInstallEnded: function(aInstall, aAddon) { + do_execute_soon(function test20_install_ended() { + 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(); + do_execute_soon(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() { + restartManager(); + Services.prefs.setBoolPref("extensions.getAddons.cache.enabled", false); + + 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:" + gPort + "/addons/test_install2_1.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.install(); + }, "application/x-xpinstall"); + }); + }); +} + +function check_test_21(aInstall) { + AddonManager.getAllInstalls(callback_soon(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:" + gPort + "/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:" + gPort + "/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:" + gPort + "/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:" + gPort + "/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:" + gPort + "/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:" + gPort + "/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); + + let file = aInstall.file; + aInstall.install(); + do_check_neq(file.path, aInstall.file.path); + do_check_false(file.exists()); +} + +function finish_test_27(aInstall) { + prepare_test({ + "addon3@tests.mozilla.org": [ + "onOperationCancelled" + ] + }, [ + "onInstallCancelled" + ]); + + aInstall.cancel(); + + ensure_test_completed(); + + run_test_28(); +} + +// Tests that an install that isn't strictly compatible and has +// binary components correctly has appDisabled set (see bug 702868). +function run_test_28() { + prepare_test({ }, [ + "onNewInstall" + ]); + + let url = "http://localhost:" + gPort + "/addons/test_install5.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 5"); + 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", + "onInstallStarted" + ], check_test_28); + install.install(); + }); + }, "application/x-xpinstall", null, "Real Test 5", null, "1.0"); +} + +function check_test_28(install) { + ensure_test_completed(); + do_check_eq(install.version, "1.0"); + do_check_eq(install.name, "Real Test 5"); + do_check_eq(install.state, AddonManager.STATE_INSTALLING); + do_check_eq(install.existingAddon, null); + do_check_false(install.addon.isCompatible); + do_check_true(install.addon.appDisabled); + + prepare_test({}, [ + "onInstallCancelled" + ], finish_test_28); + return false; +} + +function finish_test_28(install) { + prepare_test({}, [ + "onDownloadCancelled" + ], run_test_29); + + install.cancel(); +} + +// Tests that an install with a matching compatibility override has appDisabled +// set correctly. +function run_test_29() { + Services.prefs.setBoolPref("extensions.getAddons.cache.enabled", true); + + prepare_test({ }, [ + "onNewInstall" + ]); + + let url = "http://localhost:" + gPort + "/addons/test_install6.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, "Addon Test 6"); + 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_29); + install.install(); + }); + }, "application/x-xpinstall", null, "Addon Test 6", null, "1.0"); +} + +function check_test_29(install) { + //ensure_test_completed(); + do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); + do_check_neq(install.addon, null); + do_check_false(install.addon.isCompatible); + do_check_true(install.addon.appDisabled); + + prepare_test({}, [ + "onDownloadCancelled" + ], do_test_finished); + install.cancel(); + return false; +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_install_icons.js b/toolkit/mozapps/extensions/test/xpcshell/test_install_icons.js new file mode 100644 index 000000000..70f91c560 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_install_icons.js @@ -0,0 +1,61 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// use httpserver to find an available port +Components.utils.import("resource://testing-common/httpd.js"); +var gServer = new HttpServer(); +gServer.start(-1); +gPort = gServer.identity.primaryPort; + +var addon_url = "http://localhost:" + gPort + "/test.xpi"; +var icon32_url = "http://localhost:" + gPort + "/icon.png"; +var icon64_url = "http://localhost:" + gPort + "/icon64.png"; + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + startupManager(); + + test_1(); +} + +function test_1() { + AddonManager.getInstallForURL(addon_url, function(aInstall) { + do_check_eq(aInstall.iconURL, null); + do_check_neq(aInstall.icons, null); + do_check_eq(aInstall.icons[32], undefined); + do_check_eq(aInstall.icons[64], undefined); + test_2(); + }, "application/x-xpinstall", null, null, null, null, null); +} + +function test_2() { + AddonManager.getInstallForURL(addon_url, function(aInstall) { + do_check_eq(aInstall.iconURL, icon32_url); + do_check_neq(aInstall.icons, null); + do_check_eq(aInstall.icons[32], icon32_url); + do_check_eq(aInstall.icons[64], undefined); + test_3(); + }, "application/x-xpinstall", null, null, icon32_url, null, null); +} + +function test_3() { + AddonManager.getInstallForURL(addon_url, function(aInstall) { + do_check_eq(aInstall.iconURL, icon32_url); + do_check_neq(aInstall.icons, null); + do_check_eq(aInstall.icons[32], icon32_url); + do_check_eq(aInstall.icons[64], undefined); + test_4(); + }, "application/x-xpinstall", null, null, { "32": icon32_url }, null, null); +} + +function test_4() { + AddonManager.getInstallForURL(addon_url, function(aInstall) { + do_check_eq(aInstall.iconURL, icon32_url); + do_check_neq(aInstall.icons, null); + do_check_eq(aInstall.icons[32], icon32_url); + do_check_eq(aInstall.icons[64], icon64_url); + do_execute_soon(do_test_finished); + }, "application/x-xpinstall", null, null, { "32": icon32_url, "64": icon64_url }, null, null); +} 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 000000000..0c7003d59 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_install_strictcompat.js @@ -0,0 +1,1654 @@ +/* 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 +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; + +// 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; + +// install.rdf size, icon.png, icon64.png size +const ADDON1_SIZE = 705 + 16 + 16; + +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); +Cu.import("resource://testing-common/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 HttpServer(); + 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, callback_soon(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(); + do_execute_soon(function(){run_test_2(a1)}); + }); + }); + })); + }); +} + +// Tests that an install from a url downloads. +function run_test_2(aAddon) { + restartManager(); + do_check_not_in_crash_annotation(aAddon.id, aAddon.version); + + 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", callback_soon(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, callback_soon(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(); + do_execute_soon(run_test_6); + }); + }); + })); + }); +} + +// Tests that an install that requires a compatibility update works +function run_test_6() { + restartManager(); + + 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", callback_soon(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(); + do_execute_soon(run_test_8); + }); + }); + })); +} + +function run_test_8() { + restartManager(); + + 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", + ], callback_soon(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(); + do_execute_soon(run_test_9); + }); +} + +// Test that after cancelling a download it is removed from the active installs +function run_test_9() { + restartManager(); + + 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" + ], function() { + let file = install.file; + + // Allow the file removal to complete + do_execute_soon(function() { + AddonManager.getAllInstalls(function(activeInstalls) { + do_check_eq(activeInstalls.length, 0); + do_check_false(file.exists()); + + run_test_10(); + }); + }); + }); + + install.cancel(); +} + +// 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(callback_soon(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" + ] + }, callback_soon(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(); + + do_execute_soon(run_test_12); + }); +} + +// Same as test 11 but for a remote XPI +function run_test_12() { + restartManager(); + + 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" + ] + }, callback_soon(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(); + + do_execute_soon(run_test_13); + }); +} + + +// Tests that cancelling an upgrade leaves the original add-on's pendingOperations +// correct +function run_test_13() { + restartManager(); + + 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", callback_soon(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(); + + do_execute_soon(run_test_14); + }); + })); +} + +// Check that cancelling the install from onDownloadStarted actually cancels it +function run_test_14() { + restartManager(); + + 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" + ], function() { + let file = install.file; + + 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_false(file.exists()); + + run_test_15(); + }); + }); + + // Wait for the channel to be ready to cancel + do_execute_soon(function() { + install.cancel(); + }); +} + +// 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() { + do_execute_soon(function test16_install1() { + 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_execute_soon(function test16_install2() { + 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(); + do_execute_soon(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() { + restartManager(); + + let url = "http://localhost:4444/addons/test_install2_1.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ + onInstallEnded: function() { + do_execute_soon(function test17_install1() { + 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() { + do_execute_soon(function test17_install1() { + restartManager(); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_true(a2.userDisabled); + do_check_false(a2.isActive); + + a2.uninstall(); + do_execute_soon(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() { + 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() { + do_execute_soon(function test18_install1() { + 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() { + do_execute_soon(function test18_install2() { + restartManager(); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_false(a2.userDisabled); + do_check_true(a2.isActive); + + a2.uninstall(); + do_execute_soon(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() { + restartManager(); + + Services.prefs.setBoolPref("extensions.getAddons.cache.enabled", true); + Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, + "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_execute_soon(function test18_install() { + 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(); + do_execute_soon(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() { + restartManager(); + Services.prefs.setBoolPref("extensions.addon2@tests.mozilla.org.getAddons.cache.enabled", true); + + let url = "http://localhost:4444/addons/test_install2_1.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ + onInstallEnded: function(aInstall, aAddon) { + do_execute_soon(function test19_install() { + 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(); + do_execute_soon(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() { + restartManager(); + + let url = "http://localhost:4444/addons/test_install2_1.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ + onInstallEnded: function(aInstall, aAddon) { + do_execute_soon(function test20_install() { + 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(); + do_execute_soon(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() { + restartManager(); + Services.prefs.setBoolPref("extensions.getAddons.cache.enabled", false); + + 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(callback_soon(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); + + let file = aInstall.file; + aInstall.install(); + do_check_neq(file.path, aInstall.file.path); + do_check_false(file.exists()); +} + +function finish_test_27(aInstall) { + prepare_test({ + "addon3@tests.mozilla.org": [ + "onOperationCancelled" + ] + }, [ + "onInstallCancelled" + ]); + + aInstall.cancel(); + + ensure_test_completed(); + + end_test(); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_isDebuggable.js b/toolkit/mozapps/extensions/test/xpcshell/test_isDebuggable.js new file mode 100644 index 000000000..d4f8a482b --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_isDebuggable.js @@ -0,0 +1,36 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +var ADDONS = [ + "test_bootstrap2_1", // restartless addon + "test_bootstrap1_4", // old-school addon + "test_jetpack" // sdk addon +]; + +var IDS = [ + "bootstrap1@tests.mozilla.org", + "bootstrap2@tests.mozilla.org", + "jetpack@tests.mozilla.org" +]; + +function run_test() { + do_test_pending(); + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2"); + + startupManager(); + AddonManager.checkCompatibility = false; + + installAllFiles(ADDONS.map(do_get_addon), function () { + restartManager(); + + AddonManager.getAddonsByIDs(IDS, function([a1, a2, a3]) { + do_check_eq(a1.isDebuggable, false); + do_check_eq(a2.isDebuggable, true); + do_check_eq(a3.isDebuggable, true); + do_test_finished(); + }); + }, true); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_isReady.js b/toolkit/mozapps/extensions/test/xpcshell/test_isReady.js new file mode 100644 index 000000000..6222398a7 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_isReady.js @@ -0,0 +1,49 @@ +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + +function run_test() { + run_next_test(); +} + +add_task(function* () { + equal(AddonManager.isReady, false, "isReady should be false before startup"); + + let gotStartupEvent = false; + let gotShutdownEvent = false; + let listener = { + onStartup() { + gotStartupEvent = true; + }, + onShutdown() { + gotShutdownEvent = true; + }, + }; + AddonManager.addManagerListener(listener); + + do_print("Starting manager..."); + startupManager(); + equal(AddonManager.isReady, true, "isReady should be true after startup"); + equal(gotStartupEvent, true, "Should have seen onStartup event after startup"); + equal(gotShutdownEvent, false, "Should not have seen onShutdown event before shutdown"); + + gotStartupEvent = false; + gotShutdownEvent = false; + + do_print("Shutting down manager..."); + let shutdownPromise = promiseShutdownManager(); + equal(AddonManager.isReady, false, "isReady should be false when shutdown commences"); + yield shutdownPromise; + + equal(AddonManager.isReady, false, "isReady should be false after shutdown"); + equal(gotStartupEvent, false, "Should not have seen onStartup event after shutdown"); + equal(gotShutdownEvent, true, "Should have seen onShutdown event after shutdown"); + + AddonManager.addManagerListener(listener); + gotStartupEvent = false; + gotShutdownEvent = false; + + do_print("Starting manager again..."); + startupManager(); + equal(AddonManager.isReady, true, "isReady should be true after repeat startup"); + equal(gotStartupEvent, true, "Should have seen onStartup event after repeat startup"); + equal(gotShutdownEvent, false, "Should not have seen onShutdown event before shutdown, following repeat startup"); +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_langpack.js b/toolkit/mozapps/extensions/test/xpcshell/test_langpack.js new file mode 100644 index 000000000..a97a14d4d --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_langpack.js @@ -0,0 +1,339 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that language packs can be used without restarts. +Components.utils.import("resource://gre/modules/Services.jsm"); + +// Enable loading extensions from the user scopes +Services.prefs.setIntPref("extensions.enabledScopes", + AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_USER); +// Enable installing distribution add-ons +Services.prefs.setBoolPref("extensions.installDistroAddons", true); + +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); +const userExtDir = gProfD.clone(); +userExtDir.append("extensions2"); +userExtDir.append(gAppInfo.ID); +registerDirectory("XREUSysExt", userExtDir.parent); +const distroDir = gProfD.clone(); +distroDir.append("distribution"); +distroDir.append("extensions"); +registerDirectory("XREAppDist", distroDir.parent); + +var chrome = Components.classes["@mozilla.org/chrome/chrome-registry;1"] + .getService(Components.interfaces.nsIXULChromeRegistry); + +function do_unregister_manifest() { + let path = getFileForAddon(profileDir, "langpack-x-testing@tests.mozilla.org"); + Components.manager.removeBootstrappedManifestLocation(path); +} + +function do_check_locale_not_registered(provider) { + let didThrow = false; + try { + chrome.getSelectedLocale(provider); + } catch (e) { + didThrow = true; + } + do_check_true(didThrow); +} + +function run_test() { + do_test_pending(); + + startupManager(); + + run_test_1(); +} + +// Tests that installing doesn't require a restart +function run_test_1() { + do_check_locale_not_registered("test-langpack"); + + prepare_test({ }, [ + "onNewInstall" + ]); + + AddonManager.getInstallForFile(do_get_addon("test_langpack"), function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + do_check_eq(install.type, "locale"); + do_check_eq(install.version, "1.0"); + do_check_eq(install.name, "Language Pack x-testing"); + do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); + do_check_true(install.addon.hasResource("install.rdf")); + do_check_false(install.addon.hasResource("bootstrap.js")); + do_check_eq(install.addon.operationsRequiringRestart & + AddonManager.OP_NEEDS_RESTART_INSTALL, 0); + + let addon = install.addon; + prepare_test({ + "langpack-x-testing@tests.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], function() { + do_check_true(addon.hasResource("install.rdf")); + // spin to let the startup complete + do_execute_soon(check_test_1); + }); + install.install(); + }); +} + +function check_test_1() { + AddonManager.getAllInstalls(function(installs) { + // There should be no active installs now since the install completed and + // doesn't require a restart. + do_check_eq(installs.length, 0); + + AddonManager.getAddonByID("langpack-x-testing@tests.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_false(b1.appDisabled); + do_check_false(b1.userDisabled); + do_check_true(b1.isActive); + // check chrome reg that language pack is registered + do_check_eq(chrome.getSelectedLocale("test-langpack"), "x-testing"); + do_check_true(b1.hasResource("install.rdf")); + do_check_false(b1.hasResource("bootstrap.js")); + + let dir = do_get_addon_root_uri(profileDir, "langpack-x-testing@tests.mozilla.org"); + + AddonManager.getAddonsWithOperationsByTypes(null, function(list) { + do_check_eq(list.length, 0); + + run_test_2(); + }); + }); + }); +} + +// Tests that disabling doesn't require a restart +function run_test_2() { + AddonManager.getAddonByID("langpack-x-testing@tests.mozilla.org", function(b1) { + prepare_test({ + "langpack-x-testing@tests.mozilla.org": [ + ["onDisabling", false], + "onDisabled" + ] + }); + + do_check_eq(b1.operationsRequiringRestart & + AddonManager.OP_NEEDS_RESTART_DISABLE, 0); + b1.userDisabled = true; + ensure_test_completed(); + + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_false(b1.appDisabled); + do_check_true(b1.userDisabled); + do_check_false(b1.isActive); + // check chrome reg that language pack is not registered + do_check_locale_not_registered("test-langpack"); + + AddonManager.getAddonByID("langpack-x-testing@tests.mozilla.org", function(newb1) { + do_check_neq(newb1, null); + do_check_eq(newb1.version, "1.0"); + do_check_false(newb1.appDisabled); + do_check_true(newb1.userDisabled); + do_check_false(newb1.isActive); + + do_execute_soon(run_test_3); + }); + }); +} + +// Test that restarting doesn't accidentally re-enable +function run_test_3() { + shutdownManager(); + startupManager(false); + // check chrome reg that language pack is not registered + do_check_locale_not_registered("test-langpack"); + + AddonManager.getAddonByID("langpack-x-testing@tests.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_false(b1.appDisabled); + do_check_true(b1.userDisabled); + do_check_false(b1.isActive); + + run_test_4(); + }); +} + +// Tests that enabling doesn't require a restart +function run_test_4() { + AddonManager.getAddonByID("langpack-x-testing@tests.mozilla.org", function(b1) { + prepare_test({ + "langpack-x-testing@tests.mozilla.org": [ + ["onEnabling", false], + "onEnabled" + ] + }); + + do_check_eq(b1.operationsRequiringRestart & + AddonManager.OP_NEEDS_RESTART_ENABLE, 0); + b1.userDisabled = false; + ensure_test_completed(); + + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_false(b1.appDisabled); + do_check_false(b1.userDisabled); + do_check_true(b1.isActive); + // check chrome reg that language pack is registered + do_check_eq(chrome.getSelectedLocale("test-langpack"), "x-testing"); + + AddonManager.getAddonByID("langpack-x-testing@tests.mozilla.org", function(newb1) { + do_check_neq(newb1, null); + do_check_eq(newb1.version, "1.0"); + do_check_false(newb1.appDisabled); + do_check_false(newb1.userDisabled); + do_check_true(newb1.isActive); + + do_execute_soon(run_test_5); + }); + }); +} + +// Tests that a restart shuts down and restarts the add-on +function run_test_5() { + shutdownManager(); + do_unregister_manifest(); + // check chrome reg that language pack is not registered + do_check_locale_not_registered("test-langpack"); + startupManager(false); + // check chrome reg that language pack is registered + do_check_eq(chrome.getSelectedLocale("test-langpack"), "x-testing"); + + AddonManager.getAddonByID("langpack-x-testing@tests.mozilla.org", function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_false(b1.appDisabled); + do_check_false(b1.userDisabled); + do_check_true(b1.isActive); + do_check_false(isExtensionInAddonsList(profileDir, b1.id)); + + run_test_7(); + }); +} + +// Tests that uninstalling doesn't require a restart +function run_test_7() { + AddonManager.getAddonByID("langpack-x-testing@tests.mozilla.org", function(b1) { + prepare_test({ + "langpack-x-testing@tests.mozilla.org": [ + ["onUninstalling", false], + "onUninstalled" + ] + }); + + do_check_eq(b1.operationsRequiringRestart & + AddonManager.OP_NEEDS_RESTART_UNINSTALL, 0); + b1.uninstall(); + + check_test_7(); + }); +} + +function check_test_7() { + ensure_test_completed(); + // check chrome reg that language pack is not registered + do_check_locale_not_registered("test-langpack"); + + AddonManager.getAddonByID("langpack-x-testing@tests.mozilla.org", + callback_soon(function(b1) { + do_check_eq(b1, null); + + restartManager(); + + AddonManager.getAddonByID("langpack-x-testing@tests.mozilla.org", function(newb1) { + do_check_eq(newb1, null); + + do_execute_soon(run_test_8); + }); + })); +} + +// Tests that a locale detected in the profile starts working immediately +function run_test_8() { + shutdownManager(); + + manuallyInstall(do_get_addon("test_langpack"), profileDir, "langpack-x-testing@tests.mozilla.org"); + + startupManager(false); + + AddonManager.getAddonByID("langpack-x-testing@tests.mozilla.org", + callback_soon(function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_false(b1.appDisabled); + do_check_false(b1.userDisabled); + do_check_true(b1.isActive); + // check chrome reg that language pack is registered + do_check_eq(chrome.getSelectedLocale("test-langpack"), "x-testing"); + do_check_true(b1.hasResource("install.rdf")); + do_check_false(b1.hasResource("bootstrap.js")); + + shutdownManager(); + do_unregister_manifest(); + // check chrome reg that language pack is not registered + do_check_locale_not_registered("test-langpack"); + startupManager(false); + // check chrome reg that language pack is registered + do_check_eq(chrome.getSelectedLocale("test-langpack"), "x-testing"); + + AddonManager.getAddonByID("langpack-x-testing@tests.mozilla.org", function(b2) { + prepare_test({ + "langpack-x-testing@tests.mozilla.org": [ + ["onUninstalling", false], + "onUninstalled" + ] + }); + + b2.uninstall(); + ensure_test_completed(); + do_execute_soon(run_test_9); + }); + })); +} + +// Tests that a locale from distribution/extensions gets installed and starts +// working immediately +function run_test_9() { + shutdownManager(); + manuallyInstall(do_get_addon("test_langpack"), distroDir, "langpack-x-testing@tests.mozilla.org"); + gAppInfo.version = "2.0"; + startupManager(true); + + AddonManager.getAddonByID("langpack-x-testing@tests.mozilla.org", callback_soon(function(b1) { + do_check_neq(b1, null); + do_check_eq(b1.version, "1.0"); + do_check_false(b1.appDisabled); + do_check_false(b1.userDisabled); + do_check_true(b1.isActive); + // check chrome reg that language pack is registered + do_check_eq(chrome.getSelectedLocale("test-langpack"), "x-testing"); + do_check_true(b1.hasResource("install.rdf")); + do_check_false(b1.hasResource("bootstrap.js")); + + shutdownManager(); + do_unregister_manifest(); + // check chrome reg that language pack is not registered + do_check_locale_not_registered("test-langpack"); + startupManager(false); + // check chrome reg that language pack is registered + do_check_eq(chrome.getSelectedLocale("test-langpack"), "x-testing"); + + do_test_finished(); + })); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_locale.js b/toolkit/mozapps/extensions/test/xpcshell/test_locale.js new file mode 100644 index 000000000..b4c7311e5 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_locale.js @@ -0,0 +1,149 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that localized properties work as expected + +const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS"; +const PREF_SELECTED_LOCALE = "general.useragent.locale"; + + +function run_test() { + do_test_pending(); + + // Setup for 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"); + + startupManager(); + + run_test_1(); +} + +// Tests that the localized properties are visible before installation +function run_test_1() { + AddonManager.getInstallForFile(do_get_addon("test_locale"), function(install) { + do_check_eq(install.addon.name, "fr-FR Name"); + do_check_eq(install.addon.description, "fr-FR Description"); + + prepare_test({ + "addon1@tests.mozilla.org": [ + "onInstalling" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], callback_soon(run_test_2)); + install.install(); + }); +} + +// Tests that the localized properties are visible after installation +function run_test_2() { + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(addon) { + do_check_neq(addon, null); + + do_check_eq(addon.name, "fr-FR Name"); + do_check_eq(addon.description, "fr-FR Description"); + + addon.userDisabled = true; + do_execute_soon(run_test_3); + }); +} + +// Test that the localized properties are still there when disabled. +function run_test_3() { + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(addon) { + do_check_neq(addon, null); + do_check_eq(addon.name, "fr-FR Name"); + + do_execute_soon(run_test_4); + }); +} + +// Localised preference values should be ignored when the add-on is disabled +function run_test_4() { + Services.prefs.setCharPref("extensions.addon1@tests.mozilla.org.name", "Name from prefs"); + Services.prefs.setCharPref("extensions.addon1@tests.mozilla.org.contributor.1", "Contributor 1"); + Services.prefs.setCharPref("extensions.addon1@tests.mozilla.org.contributor.2", "Contributor 2"); + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(addon) { + do_check_neq(addon, null); + do_check_eq(addon.name, "fr-FR Name"); + let contributors = addon.contributors; + do_check_eq(contributors.length, 3); + do_check_eq(contributors[0], "Fr Contributor 1"); + do_check_eq(contributors[1], "Fr Contributor 2"); + do_check_eq(contributors[2], "Fr Contributor 3"); + + do_execute_soon(run_test_5); + }); +} + +// Test that changing locale works +function run_test_5() { + Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "de-DE"); + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(addon) { + do_check_neq(addon, null); + + do_check_eq(addon.name, "de-DE Name"); + do_check_eq(addon.description, null); + + do_execute_soon(run_test_6); + }); +} + +// Test that missing locales use the fallbacks +function run_test_6() { + Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "nl-NL"); + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(addon) { + do_check_neq(addon, null); + + do_check_eq(addon.name, "Fallback Name"); + do_check_eq(addon.description, "Fallback Description"); + + addon.userDisabled = false; + do_execute_soon(run_test_7); + })); +} + +// Test that the prefs will override the fallbacks +function run_test_7() { + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(addon) { + do_check_neq(addon, null); + + do_check_eq(addon.name, "Name from prefs"); + + do_execute_soon(run_test_8); + }); +} + +// Test that the prefs will override localized values from the manifest +function run_test_8() { + Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "fr-FR"); + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(addon) { + do_check_neq(addon, null); + + do_check_eq(addon.name, "Name from prefs"); + let contributors = addon.contributors; + do_check_eq(contributors.length, 2); + do_check_eq(contributors[0], "Contributor 1"); + do_check_eq(contributors[1], "Contributor 2"); + + do_execute_soon(do_test_finished); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_locked.js b/toolkit/mozapps/extensions/test/xpcshell/test_locked.js new file mode 100644 index 000000000..d16c1019d --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_locked.js @@ -0,0 +1,529 @@ +/* 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 + +Components.utils.import("resource://testing-common/httpd.js"); +Components.utils.import("resource://gre/modules/osfile.jsm"); + +var testserver = new HttpServer(); +testserver.start(-1); +gPort = testserver.identity.primaryPort; +mapFile("/data/test_corrupt.rdf", testserver); +testserver.registerDirectory("/addons/", do_get_file("addons")); + +// The test extension uses an insecure update url. +Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); +Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false); + +// 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 stay enabled +var addon3 = { + id: "addon3@tests.mozilla.org", + version: "1.0", + name: "Test 3", + updateURL: "http://localhost:" + gPort + "/data/test_corrupt.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Will get a compatibility update and be enabled +var addon4 = { + id: "addon4@tests.mozilla.org", + version: "1.0", + name: "Test 4", + updateURL: "http://localhost:" + gPort + "/data/test_corrupt.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Would stay incompatible with strict compat +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"); + +add_task(function* init() { + 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); + + // Startup the profile and setup the initial state + startupManager(); + + // New profile so new add-ons are ignored + check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []); + + let [a2, a3, a4, a7, t2] = + yield promiseAddonsByIDs(["addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon7@tests.mozilla.org", + "theme2@tests.mozilla.org"]); + let deferredUpdateFinished = Promise.defer(); + // 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() { + // Let the updates finish before restarting the manager + deferredUpdateFinished.resolve(); + } + }, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); + } + }, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); + + yield deferredUpdateFinished.promise; +}); + + +add_task(function* run_test_1() { + restartManager(); + let [a1, a2, a3, a4, a5, a6, a7, t1, t2] = + yield promiseAddonsByIDs(["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"]); + + 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_true(isExtensionInAddonsList(profileDir, a1.id)); + + 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_false(isExtensionInAddonsList(profileDir, a2.id)); + + 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_true(isExtensionInAddonsList(profileDir, a3.id)); + + 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_false(isExtensionInAddonsList(profileDir, a4.id)); + + do_check_neq(a5, null); + do_check_true(a5.isActive); + do_check_false(a5.userDisabled); + do_check_false(a5.appDisabled); + do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE); + do_check_true(isExtensionInAddonsList(profileDir, a5.id)); + + 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_false(isThemeInAddonsList(profileDir, t1.id)); + + 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); + do_check_true(isThemeInAddonsList(profileDir, t2.id)); + + // Open another handle on the JSON DB with as much Unix and Windows locking + // as we can to simulate some other process interfering with it + shutdownManager(); + do_print("Locking " + gExtensionsJSON.path); + let options = { + winShare: 0 + }; + if (OS.Constants.libc.O_EXLOCK) + options.unixFlags = OS.Constants.libc.O_EXLOCK; + + let file = yield OS.File.open(gExtensionsJSON.path, {read:true, write:true, existing:true}, options); + + let filePermissions = gExtensionsJSON.permissions; + if (!OS.Constants.Win) { + gExtensionsJSON.permissions = 0; + } + startupManager(false); + + // Shouldn't have seen any startup changes + check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []); + + // Accessing the add-ons should open and recover the database + [a1, a2, a3, a4, a5, a6, a7, t1, t2] = + yield promiseAddonsByIDs(["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"]); + + // 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); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); + + // 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); + do_check_false(isExtensionInAddonsList(profileDir, a2.id)); + + // 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_false(a3.appDisabled); + do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE); + do_check_true(isExtensionInAddonsList(profileDir, a3.id)); + + // 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_true(a4.userDisabled); + do_check_false(a4.appDisabled); + do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE); + do_check_false(isExtensionInAddonsList(profileDir, a4.id)); + + do_check_neq(a5, null); + do_check_true(a5.isActive); + do_check_false(a5.userDisabled); + do_check_false(a5.appDisabled); + do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE); + do_check_true(isExtensionInAddonsList(profileDir, a5.id)); + + 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); + do_check_false(isThemeInAddonsList(profileDir, t1.id)); + + // 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); + do_check_true(isThemeInAddonsList(profileDir, t2.id)); + + // 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(); + + // Shouldn't have seen any startup changes + check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []); + + [a1, a2, a3, a4, a5, a6, a7, t1, t2] = + yield promiseAddonsByIDs(["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"]); + + 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_true(isExtensionInAddonsList(profileDir, a1.id)); + + 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_false(isExtensionInAddonsList(profileDir, a2.id)); + + 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_true(isExtensionInAddonsList(profileDir, a3.id)); + + 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_false(isExtensionInAddonsList(profileDir, a4.id)); + + do_check_neq(a5, null); + do_check_true(a5.isActive); + do_check_false(a5.userDisabled); + do_check_false(a5.appDisabled); + do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE); + do_check_true(isExtensionInAddonsList(profileDir, a5.id)); + + 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_false(isThemeInAddonsList(profileDir, t1.id)); + + 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); + do_check_true(isThemeInAddonsList(profileDir, t2.id)); + + // After allowing access to the original DB things should go back to as + // they were previously + shutdownManager(); + do_print("Unlocking " + gExtensionsJSON.path); + yield file.close(); + gExtensionsJSON.permissions = filePermissions; + startupManager(); + + + // Shouldn't have seen any startup changes + check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []); + + [a1, a2, a3, a4, a5, a6, a7, t1, t2] = + yield promiseAddonsByIDs(["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"]); + + 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_true(isExtensionInAddonsList(profileDir, a1.id)); + + 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_false(isExtensionInAddonsList(profileDir, a2.id)); + + 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_true(isExtensionInAddonsList(profileDir, a3.id)); + + 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_false(isExtensionInAddonsList(profileDir, a4.id)); + + do_check_neq(a5, null); + do_check_true(a5.isActive); + do_check_false(a5.userDisabled); + do_check_false(a5.appDisabled); + do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE); + do_check_true(isExtensionInAddonsList(profileDir, a5.id)); + + 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_false(isThemeInAddonsList(profileDir, t1.id)); + + 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); + do_check_true(isThemeInAddonsList(profileDir, t2.id)); +}); + + +function run_test() { + run_next_test(); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_locked2.js b/toolkit/mozapps/extensions/test/xpcshell/test_locked2.js new file mode 100644 index 000000000..10b13c9f6 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_locked2.js @@ -0,0 +1,292 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Checks that we handle a locked database when there are extension changes +// in progress + +Components.utils.import("resource://gre/modules/osfile.jsm"); + +// Will be left alone +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 enabled +var addon2 = { + id: "addon2@tests.mozilla.org", + version: "1.0", + name: "Test 2", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "2", + maxVersion: "2" + }] +}; + +// Will be disabled +var addon3 = { + id: "addon3@tests.mozilla.org", + version: "1.0", + name: "Test 3", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "2", + maxVersion: "2" + }] +}; + +// Will be uninstalled +var addon4 = { + id: "addon4@tests.mozilla.org", + version: "1.0", + name: "Test 4", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "2", + maxVersion: "2" + }] +}; + + +// Will be updated +var addon5 = { + id: "addon5@tests.mozilla.org", + version: "1.0", + name: "Test 5", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "2", + maxVersion: "2" + }] +}; + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +add_task(function() { + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2"); + + writeInstallRDFForExtension(addon1, profileDir); + writeInstallRDFForExtension(addon2, profileDir); + writeInstallRDFForExtension(addon3, profileDir); + writeInstallRDFForExtension(addon4, profileDir); + writeInstallRDFForExtension(addon5, profileDir); + + // Make it look like add-on 5 was installed some time in the past so the update is + // detected + let path = getFileForAddon(profileDir, addon5.id).path; + yield promiseSetExtensionModifiedTime(path, Date.now() - (60000)); + + // Startup the profile and setup the initial state + startupManager(); + + check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_UNINSTALLED, []); + + let a1, a2, a3, a4, a5, a6; + + [a2] = yield promiseAddonsByIDs(["addon2@tests.mozilla.org"]); + a2.userDisabled = true; + + restartManager(); + + [a1, a2, a3, a4, a5] = + yield promiseAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org"]); + + a2.userDisabled = false; + a3.userDisabled = true; + a4.uninstall(); + + yield promiseInstallAllFiles([do_get_addon("test_locked2_5"), + do_get_addon("test_locked2_6")]); + 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_true(isExtensionInAddonsList(profileDir, a1.id)); + + do_check_neq(a2, null); + do_check_false(a2.isActive); + do_check_false(a2.userDisabled); + do_check_false(a2.appDisabled); + do_check_eq(a2.pendingOperations, AddonManager.PENDING_ENABLE); + do_check_false(isExtensionInAddonsList(profileDir, a2.id)); + + do_check_neq(a3, null); + do_check_true(a3.isActive); + do_check_true(a3.userDisabled); + do_check_false(a3.appDisabled); + do_check_eq(a3.pendingOperations, AddonManager.PENDING_DISABLE); + do_check_true(isExtensionInAddonsList(profileDir, a3.id)); + + do_check_neq(a4, null); + do_check_true(a4.isActive); + do_check_false(a4.userDisabled); + do_check_false(a4.appDisabled); + do_check_eq(a4.pendingOperations, AddonManager.PENDING_UNINSTALL); + do_check_true(isExtensionInAddonsList(profileDir, a4.id)); + + do_check_neq(a5, null); + do_check_eq(a5.version, "1.0"); + do_check_true(a5.isActive); + do_check_false(a5.userDisabled); + do_check_false(a5.appDisabled); + do_check_eq(a5.pendingOperations, AddonManager.PENDING_UPGRADE); + do_check_true(isExtensionInAddonsList(profileDir, a5.id)); + + // Open another handle on the JSON DB with as much Unix and Windows locking + // as we can to simulate some other process interfering with it + shutdownManager(); + do_print("Locking " + gExtensionsJSON.path); + let options = { + winShare: 0 + }; + if (OS.Constants.libc.O_EXLOCK) + options.unixFlags = OS.Constants.libc.O_EXLOCK; + + let file = yield OS.File.open(gExtensionsJSON.path, {read:true, write:true, existing:true}, options); + + let filePermissions = gExtensionsJSON.permissions; + if (!OS.Constants.Win) { + gExtensionsJSON.permissions = 0; + } + startupManager(false); + + check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_UNINSTALLED, []); + + [a1, a2, a3, a4, a5, a6] = + yield promiseAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org", + "addon6@tests.mozilla.org"]); + + 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_true(isExtensionInAddonsList(profileDir, a1.id)); + + do_check_neq(a2, null); + do_check_true(a2.isActive); + do_check_false(a2.userDisabled); + do_check_false(a2.appDisabled); + do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE); + do_check_true(isExtensionInAddonsList(profileDir, a2.id)); + + do_check_neq(a3, null); + do_check_false(a3.isActive); + do_check_true(a3.userDisabled); + do_check_false(a3.appDisabled); + do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE); + do_check_false(isExtensionInAddonsList(profileDir, a3.id)); + + do_check_eq(a4, null); + + do_check_neq(a5, null); + do_check_eq(a5.version, "2.0"); + do_check_true(a5.isActive); + do_check_false(a5.userDisabled); + do_check_false(a5.appDisabled); + do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE); + do_check_true(isExtensionInAddonsList(profileDir, a5.id)); + + 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_true(isExtensionInAddonsList(profileDir, a6.id)); + + // After allowing access to the original DB things should still be + // back how they were before the lock + shutdownManager(); + yield file.close(); + gExtensionsJSON.permissions = filePermissions; + startupManager(); + + // On Unix, we can save the DB even when the original file wasn't + // readable, so our changes were saved. On Windows, + // these things happened when we had no access to the database so + // they are seen as external changes when we get the database back + if (gXPISaveError) { + do_print("Previous XPI save failed"); + check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, + ["addon6@tests.mozilla.org"]); + check_startup_changes(AddonManager.STARTUP_CHANGE_UNINSTALLED, + ["addon4@tests.mozilla.org"]); + } + else { + do_print("Previous XPI save succeeded"); + check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_UNINSTALLED, []); + } + + [a1, a2, a3, a4, a5, a6] = + yield promiseAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org", + "addon6@tests.mozilla.org"]); + + 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_true(isExtensionInAddonsList(profileDir, a1.id)); + + do_check_neq(a2, null); + do_check_true(a2.isActive); + do_check_false(a2.userDisabled); + do_check_false(a2.appDisabled); + do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE); + do_check_true(isExtensionInAddonsList(profileDir, a2.id)); + + do_check_neq(a3, null); + do_check_false(a3.isActive); + do_check_true(a3.userDisabled); + do_check_false(a3.appDisabled); + do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE); + do_check_false(isExtensionInAddonsList(profileDir, a3.id)); + + do_check_eq(a4, null); + + do_check_neq(a5, null); + do_check_eq(a5.version, "2.0"); + do_check_true(a5.isActive); + do_check_false(a5.userDisabled); + do_check_false(a5.appDisabled); + do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE); + do_check_true(isExtensionInAddonsList(profileDir, a5.id)); + + 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_true(isExtensionInAddonsList(profileDir, a6.id)); +}); + +function run_test() { + run_next_test(); +} + 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 000000000..907c611dd --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_locked_strictcompat.js @@ -0,0 +1,551 @@ +/* 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 + +Components.utils.import("resource://testing-common/httpd.js"); +Components.utils.import("resource://gre/modules/osfile.jsm"); + +var testserver = new HttpServer(); +testserver.start(-1); +gPort = testserver.identity.primaryPort; +mapFile("/data/test_corrupt.rdf", testserver); +testserver.registerDirectory("/addons/", do_get_file("addons")); + +// 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:" + gPort + "/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:" + gPort + "/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"); + +add_task(function* init() { + 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); + + // Startup the profile and setup the initial state + startupManager(); + + // New profile so new add-ons are ignored + check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []); + + let a1, a2, a3, a4, a5, a6, a7, t1, t2; + + [a2, a3, a4, a7, t2] = + yield promiseAddonsByIDs(["addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon7@tests.mozilla.org", + "theme2@tests.mozilla.org"]); + + // Set up the initial state + let deferredUpdateFinished = Promise.defer(); + + a2.userDisabled = true; + a4.userDisabled = true; + a7.userDisabled = true; + t2.userDisabled = false; + a3.findUpdates({ + onUpdateFinished: function() { + a4.findUpdates({ + onUpdateFinished: function() { + deferredUpdateFinished.resolve(); + } + }, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); + } + }, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); + yield deferredUpdateFinished.promise; +}); + +add_task(function* run_test_1() { + let a1, a2, a3, a4, a5, a6, a7, t1, t2; + + restartManager(); + [a1, a2, a3, a4, a5, a6, a7, t1, t2] = + yield promiseAddonsByIDs(["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"]); + + 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_true(isExtensionInAddonsList(profileDir, a1.id)); + + 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_false(isExtensionInAddonsList(profileDir, a2.id)); + + 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_true(isExtensionInAddonsList(profileDir, a3.id)); + + 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_false(isExtensionInAddonsList(profileDir, a4.id)); + + 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_false(isExtensionInAddonsList(profileDir, a5.id)); + + 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_false(isThemeInAddonsList(profileDir, t1.id)); + + 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); + do_check_true(isThemeInAddonsList(profileDir, t2.id)); + + // Open another handle on the JSON DB with as much Unix and Windows locking + // as we can to simulate some other process interfering with it + shutdownManager(); + do_print("Locking " + gExtensionsJSON.path); + let options = { + winShare: 0 + }; + if (OS.Constants.libc.O_EXLOCK) + options.unixFlags = OS.Constants.libc.O_EXLOCK; + + let file = yield OS.File.open(gExtensionsJSON.path, {read:true, write:true, existing:true}, options); + + let filePermissions = gExtensionsJSON.permissions; + if (!OS.Constants.Win) { + gExtensionsJSON.permissions = 0; + } + startupManager(false); + + // Shouldn't have seen any startup changes + check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []); + + // Accessing the add-ons should open and recover the database + [a1, a2, a3, a4, a5, a6, a7, t1, t2] = + yield promiseAddonsByIDs(["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"]); + + // 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); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); + + // 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); + do_check_false(isExtensionInAddonsList(profileDir, a2.id)); + + // 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); + do_check_true(isExtensionInAddonsList(profileDir, a3.id)); + + // 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_false(isExtensionInAddonsList(profileDir, a4.id)); + + 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_false(isExtensionInAddonsList(profileDir, a5.id)); + + 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); + do_check_false(isThemeInAddonsList(profileDir, t1.id)); + + // 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); + do_check_true(isThemeInAddonsList(profileDir, t2.id)); + + // 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(); + + // Shouldn't have seen any startup changes + check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []); + + [a1, a2, a3, a4, a5, a6, a7, t1, t2] = + yield promiseAddonsByIDs(["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"]); + + 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_true(isExtensionInAddonsList(profileDir, a1.id)); + + 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_false(isExtensionInAddonsList(profileDir, a2.id)); + + 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_false(isExtensionInAddonsList(profileDir, a3.id)); + + 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_false(isExtensionInAddonsList(profileDir, a4.id)); + + 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_false(isExtensionInAddonsList(profileDir, a5.id)); + + 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_false(isThemeInAddonsList(profileDir, t1.id)); + + 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); + do_check_true(isThemeInAddonsList(profileDir, t2.id)); + + // After allowing access to the original DB things should go back to as + // back how they were before the lock + shutdownManager(); + do_print("Unlocking " + gExtensionsJSON.path); + yield file.close(); + gExtensionsJSON.permissions = filePermissions; + startupManager(false); + + // Shouldn't have seen any startup changes + check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []); + + [a1, a2, a3, a4, a5, a6, a7, t1, t2] = + yield promiseAddonsByIDs(["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"]); + + 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_true(isExtensionInAddonsList(profileDir, a1.id)); + + 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_false(isExtensionInAddonsList(profileDir, a2.id)); + + do_check_neq(a3, null); + do_check_false(a3.userDisabled); + // On Unix, we may be able to save our changes over the locked DB so we + // remember that this extension was changed to disabled. On Windows we + // couldn't replace the old DB so we read the older version of the DB + // where the extension is enabled + if (gXPISaveError) { + do_print("XPI save failed"); + do_check_true(a3.isActive); + do_check_false(a3.appDisabled); + do_check_true(isExtensionInAddonsList(profileDir, a3.id)); + } + else { + do_print("XPI save succeeded"); + do_check_false(a3.isActive); + do_check_true(a3.appDisabled); + do_check_false(isExtensionInAddonsList(profileDir, a3.id)); + } + do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a4, null); + do_check_false(a4.isActive); + // The reverse of the platform difference for a3 - Unix should + // stay the same as the last iteration because the save succeeded, + // Windows should still say userDisabled + if (OS.Constants.Win) { + do_check_true(a4.userDisabled); + do_check_false(a4.appDisabled); + } + else { + do_check_false(a4.userDisabled); + do_check_true(a4.appDisabled); + } + do_check_false(isExtensionInAddonsList(profileDir, a4.id)); + 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_false(isExtensionInAddonsList(profileDir, a5.id)); + + 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_false(isThemeInAddonsList(profileDir, t1.id)); + + 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); + do_check_true(isThemeInAddonsList(profileDir, t2.id)); +}); + +function run_test() { + run_next_test(); +} + diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_manifest.js b/toolkit/mozapps/extensions/test/xpcshell/test_manifest.js new file mode 100644 index 000000000..061a3a6b2 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_manifest.js @@ -0,0 +1,562 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This tests that all properties are read from the install manifests and that +// items are correctly enabled/disabled based on them (blocklist tests are +// elsewhere) + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + const profileDir = gProfD.clone(); + profileDir.append("extensions"); + + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + optionsURL: "chrome://test/content/options.xul", + aboutURL: "chrome://test/content/about.xul", + iconURL: "chrome://test/skin/icon.png", + icon64URL: "chrome://test/skin/icon64.png", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 1", + description: "Test Description", + creator: "Test Creator", + homepageURL: "http://www.example.com", + developer: [ + "Test Developer 1", + "Test Developer 2" + ], + translator: [ + "Test Translator 1", + "Test Translator 2" + ], + contributor: [ + "Test Contributor 1", + "Test Contributor 2" + ] + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon2@tests.mozilla.org", + version: "1.0", + updateURL: "https://www.foo.com", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 2" + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon3@tests.mozilla.org", + version: "1.0", + updateURL: "http://www.foo.com", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 3" + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon4@tests.mozilla.org", + version: "1.0", + updateURL: "http://www.foo.com", + updateKey: "foo", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 4" + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon5@tests.mozilla.org", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "*" + }], + name: "Test Addon 5" + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon6@tests.mozilla.org", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0", + maxVersion: "1" + }], + name: "Test Addon 6" + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon7@tests.mozilla.org", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0", + maxVersion: "0" + }], + name: "Test Addon 7" + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon8@tests.mozilla.org", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1.1", + maxVersion: "*" + }], + name: "Test Addon 8" + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon9@tests.mozilla.org", + version: "1.0", + targetApplications: [{ + id: "toolkit@mozilla.org", + minVersion: "1.9.2", + maxVersion: "1.9.*" + }], + name: "Test Addon 9" + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon10@tests.mozilla.org", + version: "1.0", + targetApplications: [{ + id: "toolkit@mozilla.org", + minVersion: "1.9.2.1", + maxVersion: "1.9.*" + }], + name: "Test Addon 10" + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon11@tests.mozilla.org", + version: "1.0", + targetApplications: [{ + id: "toolkit@mozilla.org", + minVersion: "1.9", + maxVersion: "1.9.2" + }], + name: "Test Addon 11" + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon12@tests.mozilla.org", + version: "1.0", + targetApplications: [{ + id: "toolkit@mozilla.org", + minVersion: "1.9", + maxVersion: "1.9.1.*" + }], + name: "Test Addon 12" + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon13@tests.mozilla.org", + version: "1.0", + targetApplications: [{ + id: "toolkit@mozilla.org", + minVersion: "1.9", + maxVersion: "1.9.*" + }, { + id: "xpcshell@tests.mozilla.org", + minVersion: "0", + maxVersion: "0.5" + }], + name: "Test Addon 13" + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon14@tests.mozilla.org", + version: "1.0", + targetApplications: [{ + id: "toolkit@mozilla.org", + minVersion: "1.9", + maxVersion: "1.9.1" + }, { + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 14" + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon15@tests.mozilla.org", + version: "1.0", + updateKey: "foo", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 15" + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon16@tests.mozilla.org", + version: "1.0", + updateKey: "foo", + updateURL: "https://www.foo.com", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 16" + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon17@tests.mozilla.org", + version: "1.0", + optionsURL: "chrome://test/content/options.xul", + optionsType: "2", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 17" + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon18@tests.mozilla.org", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 18" + }, profileDir, null, "options.xul"); + + writeInstallRDFForExtension({ + id: "addon19@tests.mozilla.org", + version: "1.0", + optionsType: "99", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 19" + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon20@tests.mozilla.org", + version: "1.0", + optionsType: "1", + optionsURL: "chrome://test/content/options.xul", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 20" + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon21@tests.mozilla.org", + version: "1.0", + optionsType: "3", + optionsURL: "chrome://test/content/options.xul", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 21" + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon22@tests.mozilla.org", + version: "1.0", + optionsType: "2", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 22" + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon23@tests.mozilla.org", + version: "1.0", + optionsType: "2", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 23" + }, profileDir, null, "options.xul"); + + writeInstallRDFForExtension({ + id: "addon24@tests.mozilla.org", + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 24" + }, profileDir, null, "options.xul"); + + writeInstallRDFForExtension({ + id: "addon25@tests.mozilla.org", + version: "1.0", + optionsType: "3", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 25" + }, profileDir); + + writeInstallRDFForExtension({ + id: "addon26@tests.mozilla.org", + version: "1.0", + optionsType: "4", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 26" + }, profileDir, null, "options.xul"); + + do_test_pending(); + startupManager(); + 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", + "addon8@tests.mozilla.org", + "addon9@tests.mozilla.org", + "addon10@tests.mozilla.org", + "addon11@tests.mozilla.org", + "addon12@tests.mozilla.org", + "addon13@tests.mozilla.org", + "addon14@tests.mozilla.org", + "addon15@tests.mozilla.org", + "addon16@tests.mozilla.org", + "addon17@tests.mozilla.org", + "addon18@tests.mozilla.org", + "addon19@tests.mozilla.org", + "addon20@tests.mozilla.org", + "addon21@tests.mozilla.org", + "addon22@tests.mozilla.org", + "addon23@tests.mozilla.org", + "addon24@tests.mozilla.org", + "addon25@tests.mozilla.org", + "addon26@tests.mozilla.org"], + function([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, + a21, a22, a23, a24, a25, a26]) { + + do_check_neq(a1, null); + do_check_eq(a1.id, "addon1@tests.mozilla.org"); + do_check_eq(a1.type, "extension"); + do_check_eq(a1.version, "1.0"); + do_check_eq(a1.optionsURL, "chrome://test/content/options.xul"); + do_check_eq(a1.optionsType, AddonManager.OPTIONS_TYPE_DIALOG); + do_check_eq(a1.aboutURL, "chrome://test/content/about.xul"); + do_check_eq(a1.iconURL, "chrome://test/skin/icon.png"); + do_check_eq(a1.icon64URL, "chrome://test/skin/icon64.png"); + do_check_eq(a1.icons[32], "chrome://test/skin/icon.png"); + do_check_eq(a1.icons[64], "chrome://test/skin/icon64.png"); + do_check_eq(a1.name, "Test Addon 1"); + do_check_eq(a1.description, "Test Description"); + do_check_eq(a1.creator, "Test Creator"); + do_check_eq(a1.homepageURL, "http://www.example.com"); + do_check_eq(a1.developers[0], "Test Developer 1"); + do_check_eq(a1.developers[1], "Test Developer 2"); + do_check_eq(a1.translators[0], "Test Translator 1"); + do_check_eq(a1.translators[1], "Test Translator 2"); + do_check_eq(a1.contributors[0], "Test Contributor 1"); + do_check_eq(a1.contributors[1], "Test Contributor 2"); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + do_check_false(a1.appDisabled); + do_check_true(a1.isCompatible); + do_check_true(a1.providesUpdatesSecurely); + do_check_eq(a1.blocklistState, AM_Ci.nsIBlocklistService.STATE_NOT_BLOCKED); + + do_check_neq(a2, null); + do_check_eq(a2.id, "addon2@tests.mozilla.org"); + do_check_true(a2.isActive); + do_check_false(a2.userDisabled); + do_check_false(a2.appDisabled); + do_check_true(a2.providesUpdatesSecurely); + + do_check_neq(a3, null); + do_check_eq(a3.id, "addon3@tests.mozilla.org"); + do_check_false(a3.isActive); + do_check_false(a3.userDisabled); + do_check_true(a3.appDisabled); + do_check_false(a3.providesUpdatesSecurely); + + do_check_neq(a4, null); + do_check_eq(a4.id, "addon4@tests.mozilla.org"); + do_check_true(a4.isActive); + do_check_false(a4.userDisabled); + do_check_false(a4.appDisabled); + do_check_true(a4.providesUpdatesSecurely); + + do_check_neq(a5, null); + do_check_true(a5.isActive); + do_check_false(a5.userDisabled); + do_check_false(a5.appDisabled); + do_check_true(a5.isCompatible); + + do_check_neq(a6, null); + do_check_true(a6.isActive); + do_check_false(a6.userDisabled); + do_check_false(a6.appDisabled); + do_check_true(a6.isCompatible); + + do_check_neq(a7, null); + do_check_false(a7.isActive); + do_check_false(a7.userDisabled); + do_check_true(a7.appDisabled); + do_check_false(a7.isCompatible); + + do_check_neq(a8, null); + do_check_false(a8.isActive); + do_check_false(a8.userDisabled); + do_check_true(a8.appDisabled); + do_check_false(a8.isCompatible); + + do_check_neq(a9, null); + do_check_true(a9.isActive); + do_check_false(a9.userDisabled); + do_check_false(a9.appDisabled); + do_check_true(a9.isCompatible); + + do_check_neq(a10, null); + do_check_false(a10.isActive); + do_check_false(a10.userDisabled); + do_check_true(a10.appDisabled); + do_check_false(a10.isCompatible); + + do_check_neq(a11, null); + do_check_true(a11.isActive); + do_check_false(a11.userDisabled); + do_check_false(a11.appDisabled); + do_check_true(a11.isCompatible); + + do_check_neq(a12, null); + do_check_false(a12.isActive); + do_check_false(a12.userDisabled); + do_check_true(a12.appDisabled); + do_check_false(a12.isCompatible); + + do_check_neq(a13, null); + do_check_false(a13.isActive); + do_check_false(a13.userDisabled); + do_check_true(a13.appDisabled); + do_check_false(a13.isCompatible); + + do_check_neq(a14, null); + do_check_true(a14.isActive); + do_check_false(a14.userDisabled); + do_check_false(a14.appDisabled); + do_check_true(a14.isCompatible); + + do_check_neq(a15, null); + do_check_true(a15.isActive); + do_check_false(a15.userDisabled); + do_check_false(a15.appDisabled); + do_check_true(a15.isCompatible); + do_check_true(a15.providesUpdatesSecurely); + + do_check_neq(a16, null); + do_check_true(a16.isActive); + do_check_false(a16.userDisabled); + do_check_false(a16.appDisabled); + do_check_true(a16.isCompatible); + do_check_true(a16.providesUpdatesSecurely); + + do_check_neq(a17, null); + do_check_true(a17.isActive); + do_check_false(a17.userDisabled); + do_check_false(a17.appDisabled); + do_check_true(a17.isCompatible); + do_check_eq(a17.optionsURL, "chrome://test/content/options.xul"); + do_check_eq(a17.optionsType, AddonManager.OPTIONS_TYPE_INLINE); + + do_check_neq(a18, null); + do_check_true(a18.isActive); + do_check_false(a18.userDisabled); + do_check_false(a18.appDisabled); + do_check_true(a18.isCompatible); + if (Services.prefs.getBoolPref("extensions.alwaysUnpack")) { + do_check_eq(a18.optionsURL, Services.io.newFileURI(profileDir).spec + + "addon18@tests.mozilla.org/options.xul"); + } else { + do_check_eq(a18.optionsURL, "jar:" + Services.io.newFileURI(profileDir).spec + + "addon18@tests.mozilla.org.xpi!/options.xul"); + } + do_check_eq(a18.optionsType, AddonManager.OPTIONS_TYPE_INLINE); + + do_check_eq(a19, null); + + do_check_neq(a20, null); + do_check_true(a20.isActive); + do_check_false(a20.userDisabled); + do_check_false(a20.appDisabled); + do_check_true(a20.isCompatible); + do_check_eq(a20.optionsURL, "chrome://test/content/options.xul"); + do_check_eq(a20.optionsType, AddonManager.OPTIONS_TYPE_DIALOG); + + do_check_neq(a21, null); + do_check_true(a21.isActive); + do_check_false(a21.userDisabled); + do_check_false(a21.appDisabled); + do_check_true(a21.isCompatible); + do_check_eq(a21.optionsURL, "chrome://test/content/options.xul"); + do_check_eq(a21.optionsType, AddonManager.OPTIONS_TYPE_TAB); + + do_check_neq(a22, null); + do_check_eq(a22.optionsType, null); + do_check_eq(a22.optionsURL, null); + + do_check_neq(a23, null); + do_check_eq(a23.optionsType, AddonManager.OPTIONS_TYPE_INLINE); + do_check_neq(a23.optionsURL, null); + + do_check_neq(a24, null); + do_check_eq(a24.optionsType, AddonManager.OPTIONS_TYPE_INLINE); + do_check_neq(a24.optionsURL, null); + + do_check_neq(a25, null); + do_check_eq(a25.optionsType, null); + do_check_eq(a25.optionsURL, null); + + do_check_neq(a26, null); + do_check_eq(a26.optionsType, AddonManager.OPTIONS_TYPE_INLINE_INFO); + do_check_neq(a26.optionsURL, null); + + do_execute_soon(do_test_finished); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_mapURIToAddonID.js b/toolkit/mozapps/extensions/test/xpcshell/test_mapURIToAddonID.js new file mode 100644 index 000000000..a6f9c8052 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_mapURIToAddonID.js @@ -0,0 +1,326 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that add-ons URIs can be mapped to add-on IDs +// +Components.utils.import("resource://gre/modules/Services.jsm"); + +// Enable loading extensions from the user scopes +Services.prefs.setIntPref("extensions.enabledScopes", + AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_USER); + +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); +const userExtDir = gProfD.clone(); +userExtDir.append("extensions2"); +userExtDir.append(gAppInfo.ID); +registerDirectory("XREUSysExt", userExtDir.parent); + +function TestProvider(result) { + this.result = result; +} +TestProvider.prototype = { + uri: Services.io.newURI("hellow://world", null, null), + id: "valid@id", + startup: function() {}, + shutdown: function() {}, + mapURIToAddonID: function(aURI) { + if (aURI.spec === this.uri.spec) { + return this.id; + } + throw Components.Exception("Not mapped", result); + } +}; + +function TestProviderNoMap() {} +TestProviderNoMap.prototype = { + startup: function() {}, + shutdown: function() {} +}; + +function check_mapping(uri, id) { + do_check_eq(AddonManager.mapURIToAddonID(uri), id); + let svc = Components.classes["@mozilla.org/addons/integration;1"]. + getService(Components.interfaces.amIAddonManager); + let val = {}; + do_check_true(svc.mapURIToAddonID(uri, val)); + do_check_eq(val.value, id); +} + +function resetPrefs() { + Services.prefs.setIntPref("bootstraptest.active_version", -1); +} + +function waitForPref(aPref, aCallback) { + function prefChanged() { + Services.prefs.removeObserver(aPref, prefChanged); + aCallback(); + } + Services.prefs.addObserver(aPref, prefChanged, false); +} + +function getActiveVersion() { + return Services.prefs.getIntPref("bootstraptest.active_version"); +} + +function run_test() { + do_test_pending(); + + resetPrefs(); + + run_test_early(); +} + +function run_test_early() { + startupManager(); + + installAllFiles([do_get_addon("test_chromemanifest_1")], function() { + restartManager(); + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(addon) { + let uri = addon.getResourceURI("."); + let id = addon.id; + check_mapping(uri, id); + + shutdownManager(); + + // Force an early call, to check that mappings will get correctly + // initialized when the manager actually starts up. + // See bug 957089 + + // First force-initialize the XPIProvider. + let s = Components.utils.import( + "resource://gre/modules/addons/XPIProvider.jsm", {}); + + // Make the early API call. + do_check_null(s.XPIProvider.mapURIToAddonID(uri)); + do_check_null(AddonManager.mapURIToAddonID(uri)); + + // Actually start up the manager. + startupManager(false); + + // Check that the mapping is there now. + check_mapping(uri, id); + do_check_eq(s.XPIProvider.mapURIToAddonID(uri), id); + + run_test_nomapping(); + }); + }); +} + +function run_test_nomapping() { + do_check_eq(AddonManager.mapURIToAddonID(TestProvider.prototype.uri), null); + try { + let svc = Components.classes["@mozilla.org/addons/integration;1"]. + getService(Components.interfaces.amIAddonManager); + let val = {}; + do_check_false(svc.mapURIToAddonID(TestProvider.prototype.uri, val)); + } + catch (ex) { + do_throw(ex); + } + + run_test_1(); +} + + +// Tests that add-on URIs are mappable after an install +function run_test_1() { + prepare_test({ }, [ + "onNewInstall" + ]); + + AddonManager.getInstallForFile(do_get_addon("test_bootstrap1_1"), function(install) { + ensure_test_completed(); + + let addon = install.addon; + prepare_test({ + "bootstrap1@tests.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], function() { + let uri = addon.getResourceURI("."); + check_mapping(uri, addon.id); + + waitForPref("bootstraptest.active_version", function() { + run_test_2(uri); + }); + }); + install.install(); + }); +} + +// Tests that add-on URIs are still mappable, even after the add-on gets +// disabled in-session. +function run_test_2(uri) { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + prepare_test({ + "bootstrap1@tests.mozilla.org": [ + ["onDisabling", false], + "onDisabled" + ] + }); + + b1.userDisabled = true; + ensure_test_completed(); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(newb1) { + do_check_true(newb1.userDisabled); + check_mapping(uri, newb1.id); + + do_execute_soon(() => run_test_3(uri)); + }); + }); +} + +// Tests that add-on URIs are mappable if the add-on was never started in a +// session +function run_test_3(uri) { + restartManager(); + + check_mapping(uri, "bootstrap1@tests.mozilla.org"); + + run_test_4(); +} + +// Tests that add-on URIs are mappable after a restart + reenable +function run_test_4() { + restartManager(); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + prepare_test({ + "bootstrap1@tests.mozilla.org": [ + ["onEnabling", false], + "onEnabled" + ] + }); + + b1.userDisabled = false; + ensure_test_completed(); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(newb1) { + let uri = newb1.getResourceURI("."); + check_mapping(uri, newb1.id); + + do_execute_soon(run_test_5); + }); + }); +} + +// Tests that add-on URIs are mappable after a restart +function run_test_5() { + restartManager(); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + let uri = b1.getResourceURI("."); + check_mapping(uri, b1.id); + + do_execute_soon(run_test_6); + }); +} + +// Tests that add-on URIs are mappable after being uninstalled +function run_test_6() { + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + prepare_test({ + "bootstrap1@tests.mozilla.org": [ + ["onUninstalling", false], + "onUninstalled" + ] + }); + + let uri = b1.getResourceURI("."); + b1.uninstall(); + ensure_test_completed(); + + check_mapping(uri, b1.id); + + restartManager(); + do_execute_soon(run_test_7); + }); +} + +// Tests that add-on URIs are mappable for add-ons detected at startup +function run_test_7() { + shutdownManager(); + + manuallyInstall(do_get_addon("test_bootstrap1_1"), profileDir, "bootstrap1@tests.mozilla.org"); + + startupManager(); + + AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) { + let uri = b1.getResourceURI("."); + check_mapping(uri, b1.id); + + do_execute_soon(run_test_invalidarg); + }); +} + +// Tests that the AddonManager will bail when mapURIToAddonID is called with an +// invalid argument +function run_test_invalidarg() { + restartManager(); + + let tests = [undefined, + null, + 1, + "string", + "chrome://global/content/", + function() {} + ]; + for (var test of tests) { + try { + AddonManager.mapURIToAddonID(test); + throw new Error("Shouldn't be able to map the URI in question"); + } + catch (ex if ex.result) { + do_check_eq(ex.result, Components.results.NS_ERROR_INVALID_ARG); + } + catch (ex) { + do_throw(ex); + } + } + + run_test_provider(); +} + +// Tests that custom providers are correctly handled +function run_test_provider() { + restartManager(); + + const provider = new TestProvider(Components.results.NS_ERROR_NOT_AVAILABLE); + AddonManagerPrivate.registerProvider(provider); + + check_mapping(provider.uri, provider.id); + + let u2 = provider.uri.clone(); + u2.path = "notmapped"; + do_check_eq(AddonManager.mapURIToAddonID(u2), null); + + AddonManagerPrivate.unregisterProvider(provider); + + run_test_provider_nomap(); +} + +// Tests that custom providers are correctly handled, even not implementing +// mapURIToAddonID +function run_test_provider_nomap() { + restartManager(); + + const provider = new TestProviderNoMap(); + AddonManagerPrivate.registerProvider(provider); + + do_check_eq(AddonManager.mapURIToAddonID(TestProvider.prototype.uri), null); + + AddonManagerPrivate.unregisterProvider(provider); + + do_test_finished(); +} + + diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_metadata_update.js b/toolkit/mozapps/extensions/test/xpcshell/test_metadata_update.js new file mode 100644 index 000000000..a87b3f45b --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_metadata_update.js @@ -0,0 +1,184 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/* + * Test whether we need to block start-up to check add-on compatibility, + * based on how long since the last succesful metadata ping. + * All tests depend on having one add-on installed in the profile + */ + + +const URI_EXTENSION_UPDATE_DIALOG = "chrome://mozapps/content/extensions/update.xul"; +const PREF_EM_SHOW_MISMATCH_UI = "extensions.showMismatchUI"; + +// Constants copied from AddonRepository.jsm +const PREF_METADATA_LASTUPDATE = "extensions.getAddons.cache.lastUpdate"; +const PREF_METADATA_UPDATETHRESHOLD_SEC = "extensions.getAddons.cache.updateThreshold"; +const DEFAULT_METADATA_UPDATETHRESHOLD_SEC = 172800; // two days + +// The test extension uses an insecure update url. +Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); +// None of this works without the add-on repository cache +Services.prefs.setBoolPref("extensions.getAddons.cache.enabled", true); + +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; +const Cr = Components.results; + +Cu.import("resource://testing-common/httpd.js"); +var testserver; + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +// This will be called to show the compatibility update dialog. +var WindowWatcher = { + expected: false, + arguments: null, + + openWindow: function(parent, url, name, features, args) { + do_check_true(Services.startup.interrupted); + do_check_eq(url, URI_EXTENSION_UPDATE_DIALOG); + do_check_true(this.expected); + this.expected = false; + }, + + QueryInterface: function(iid) { + if (iid.equals(Ci.nsIWindowWatcher) + || iid.equals(Ci.nsISupports)) + return this; + + throw Cr.NS_ERROR_NO_INTERFACE; + } +} + +var WindowWatcherFactory = { + createInstance: function createInstance(outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return WindowWatcher.QueryInterface(iid); + } +}; + +var registrar = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar); +registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"), + "Fake Window Watcher", + "@mozilla.org/embedcomp/window-watcher;1", WindowWatcherFactory); + +// Return Date.now() in seconds, rounded +function now() { + return Math.round(Date.now() / 1000); +} + +// First time with a new profile, so we don't have a cache.lastUpdate pref +add_task(function* checkFirstMetadata() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); + + Services.prefs.setBoolPref(PREF_EM_SHOW_MISMATCH_UI, true); + + // Create and configure the HTTP server. + testserver = new HttpServer(); + testserver.registerDirectory("/data/", do_get_file("data")); + testserver.registerDirectory("/addons/", do_get_file("addons")); + testserver.start(-1); + gPort = testserver.identity.primaryPort; + const BASE_URL = "http://localhost:" + gPort; + const GETADDONS_RESULTS = BASE_URL + "/data/test_AddonRepository_cache.xml"; + Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, GETADDONS_RESULTS); + + // Put an add-on in our profile so the metadata check will have something to do + var min1max2 = { + id: "min1max2@tests.mozilla.org", + version: "1.0", + name: "Test addon compatible with v1->v2", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }] + }; + writeInstallRDFForExtension(min1max2, profileDir); + + startupManager(); + + // Make sure that updating metadata for the first time sets the lastUpdate preference + yield AddonRepository.repopulateCache(); + do_print("Update done, getting last update"); + let lastUpdate = Services.prefs.getIntPref(PREF_METADATA_LASTUPDATE); + do_check_true(lastUpdate > 0); + + // Make sure updating metadata again updates the preference + let oldUpdate = lastUpdate - 2 * DEFAULT_METADATA_UPDATETHRESHOLD_SEC; + Services.prefs.setIntPref(PREF_METADATA_LASTUPDATE, oldUpdate); + yield AddonRepository.repopulateCache(); + do_check_neq(oldUpdate, Services.prefs.getIntPref(PREF_METADATA_LASTUPDATE)); +}); + +// First upgrade with no lastUpdate pref and no add-ons changing shows UI +add_task(function* upgrade_no_lastupdate() { + Services.prefs.clearUserPref(PREF_METADATA_LASTUPDATE); + + WindowWatcher.expected = true; + yield promiseRestartManager("2"); + do_check_false(WindowWatcher.expected); +}); + +// Upgrade with lastUpdate more than default threshold and no add-ons changing shows UI +add_task(function* upgrade_old_lastupdate() { + let oldEnough = now() - DEFAULT_METADATA_UPDATETHRESHOLD_SEC - 1000; + Services.prefs.setIntPref(PREF_METADATA_LASTUPDATE, oldEnough); + + WindowWatcher.expected = true; + // upgrade, downgrade, it has the same effect on the code path under test + yield promiseRestartManager("1"); + do_check_false(WindowWatcher.expected); +}); + +// Upgrade with lastUpdate less than default threshold and no add-ons changing doesn't show +add_task(function* upgrade_young_lastupdate() { + let notOldEnough = now() - DEFAULT_METADATA_UPDATETHRESHOLD_SEC + 1000; + Services.prefs.setIntPref(PREF_METADATA_LASTUPDATE, notOldEnough); + + WindowWatcher.expected = false; + yield promiseRestartManager("2"); + do_check_false(WindowWatcher.expected); +}); + +// Repeat more-than and less-than but with updateThreshold preference set +// Upgrade with lastUpdate more than pref threshold and no add-ons changing shows UI +const TEST_UPDATETHRESHOLD_SEC = 50000; +add_task(function* upgrade_old_pref_lastupdate() { + Services.prefs.setIntPref(PREF_METADATA_UPDATETHRESHOLD_SEC, TEST_UPDATETHRESHOLD_SEC); + + let oldEnough = now() - TEST_UPDATETHRESHOLD_SEC - 1000; + Services.prefs.setIntPref(PREF_METADATA_LASTUPDATE, oldEnough); + + WindowWatcher.expected = true; + yield promiseRestartManager("1"); + do_check_false(WindowWatcher.expected); +}); + +// Upgrade with lastUpdate less than pref threshold and no add-ons changing doesn't show +add_task(function* upgrade_young_pref_lastupdate() { + let notOldEnough = now() - TEST_UPDATETHRESHOLD_SEC + 1000; + Services.prefs.setIntPref(PREF_METADATA_LASTUPDATE, notOldEnough); + + WindowWatcher.expected = false; + yield promiseRestartManager("2"); + do_check_false(WindowWatcher.expected); +}); + + + +add_task(function* cleanup() { + return new Promise((resolve, reject) => { + testserver.stop(resolve); + }); +}); + +function run_test() { + run_next_test(); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_migrate1.js b/toolkit/mozapps/extensions/test/xpcshell/test_migrate1.js new file mode 100644 index 000000000..b3cae5283 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_migrate1.js @@ -0,0 +1,250 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Checks that we migrate data from the old rdf style database + +var addon1 = { + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +var addon2 = { + id: "addon2@tests.mozilla.org", + version: "2.0", + name: "Test 2", + targetApplications: [{ + id: "toolkit@mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +var addon3 = { + id: "addon3@tests.mozilla.org", + version: "2.0", + name: "Test 3", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +var addon4 = { + id: "addon4@tests.mozilla.org", + version: "2.0", + name: "Test 4", + targetApplications: [{ + id: "toolkit@mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +var addon5 = { + id: "addon5@tests.mozilla.org", + version: "2.0", + name: "Test 5", + targetApplications: [{ + id: "toolkit@mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +var theme1 = { + id: "theme1@tests.mozilla.org", + version: "1.0", + name: "Theme 1", + type: 4, + internalName: "theme1/1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }] +}; + +var theme2 = { + id: "theme2@tests.mozilla.org", + version: "1.0", + name: "Theme 2", + type: 4, + internalName: "theme2/1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + 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(theme1, profileDir); + writeInstallRDFForExtension(theme2, profileDir); + + let stagedXPIs = profileDir.clone(); + stagedXPIs.append("staged-xpis"); + stagedXPIs.append("addon6@tests.mozilla.org"); + stagedXPIs.create(AM_Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); + + let addon6 = do_get_addon("test_migrate6"); + addon6.copyTo(stagedXPIs, "tmp.xpi"); + stagedXPIs = stagedXPIs.parent; + + stagedXPIs.append("addon7@tests.mozilla.org"); + stagedXPIs.create(AM_Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); + + let addon7 = do_get_addon("test_migrate7"); + addon7.copyTo(stagedXPIs, "tmp.xpi"); + stagedXPIs = stagedXPIs.parent; + + stagedXPIs.append("addon8@tests.mozilla.org"); + stagedXPIs.create(AM_Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); + let addon8 = do_get_addon("test_migrate8"); + addon8.copyTo(stagedXPIs, "tmp.xpi"); + stagedXPIs = stagedXPIs.parent; + + let old = do_get_file("data/test_migrate.rdf"); + old.copyTo(gProfD, "extensions.rdf"); + + let oldCache = gProfD.clone(); + oldCache.append("extensions.cache"); + oldCache.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); + + // Theme state is determined by the selected theme pref + Services.prefs.setCharPref("general.skins.selectedSkin", "theme1/1.0"); + + Services.prefs.setCharPref("extensions.lastAppVersion", "1"); + + startupManager(); + check_startup_changes("installed", []); + check_startup_changes("updated", []); + check_startup_changes("uninstalled", []); + check_startup_changes("disabled", []); + check_startup_changes("enabled", []); + + do_check_false(oldCache.exists()); + + 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", + "addon8@tests.mozilla.org", + "theme1@tests.mozilla.org", + "theme2@tests.mozilla.org"], function([a1, a2, a3, + a4, a5, a6, + a7, a8, t1, + t2]) { + // addon1 was user and app enabled in the old extensions.rdf + do_check_neq(a1, null); + do_check_false(a1.userDisabled); + do_check_false(a1.appDisabled); + do_check_true(a1.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); + do_check_false(a1.hasBinaryComponents); + + // addon2 was user disabled and app enabled in the old extensions.rdf + do_check_neq(a2, null); + do_check_true(a2.userDisabled); + do_check_false(a2.appDisabled); + do_check_false(a2.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a2.id)); + do_check_false(a2.hasBinaryComponents); + + // addon3 was pending user disable and app disabled in the old extensions.rdf + do_check_neq(a3, null); + do_check_true(a3.userDisabled); + do_check_true(a3.appDisabled); + do_check_false(a3.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a3.id)); + do_check_false(a3.hasBinaryComponents); + + // addon4 was pending user enable and app disabled in the old extensions.rdf + do_check_neq(a4, null); + do_check_false(a4.userDisabled); + do_check_true(a4.appDisabled); + do_check_false(a4.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a4.id)); + do_check_false(a4.hasBinaryComponents); + + // addon5 was disabled and compatible but a new version has been installed + // since, it should still be disabled but should be incompatible + do_check_neq(a5, null); + do_check_true(a5.userDisabled); + do_check_true(a5.appDisabled); + do_check_false(a5.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a5.id)); + do_check_false(a5.hasBinaryComponents); + + // addon6 should be installed and compatible and packed unless unpacking is + // forced + do_check_neq(a6, null); + do_check_false(a6.userDisabled); + do_check_false(a6.appDisabled); + do_check_true(a6.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a6.id)); + if (Services.prefs.getBoolPref("extensions.alwaysUnpack")) + do_check_eq(a6.getResourceURI("install.rdf").scheme, "file"); + else + do_check_eq(a6.getResourceURI("install.rdf").scheme, "jar"); + do_check_false(a6.hasBinaryComponents); + + // addon7 should be installed and compatible and unpacked + do_check_neq(a7, null); + do_check_false(a7.userDisabled); + do_check_false(a7.appDisabled); + do_check_true(a7.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a7.id)); + do_check_eq(a7.getResourceURI("install.rdf").scheme, "file"); + do_check_false(a7.hasBinaryComponents); + + // addon8 should be installed and compatible and have binary components + do_check_neq(a8, null); + do_check_false(a8.userDisabled); + do_check_false(a8.appDisabled); + do_check_true(a8.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a8.id)); + do_check_true(a8.hasBinaryComponents); + + // Theme 1 was previously enabled + do_check_neq(t1, null); + do_check_false(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_true(t1.isActive); + do_check_true(isThemeInAddonsList(profileDir, t1.id)); + do_check_false(hasFlag(t1.permissions, AddonManager.PERM_CAN_ENABLE)); + + // Theme 2 was previously disabled + do_check_neq(t1, null); + do_check_true(t2.userDisabled); + do_check_false(t2.appDisabled); + do_check_false(t2.isActive); + do_check_false(isThemeInAddonsList(profileDir, t2.id)); + do_check_true(hasFlag(t2.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_check_false(stagedXPIs.exists()); + + do_execute_soon(do_test_finished); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_migrate2.js b/toolkit/mozapps/extensions/test/xpcshell/test_migrate2.js new file mode 100644 index 000000000..c213bace7 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_migrate2.js @@ -0,0 +1,259 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Checks that we migrate data from SQLITE databases +// Note that since the database doesn't contain the foreignInstall field we +// should just assume that no add-ons in the user profile were foreignInstalls + +// Enable loading extensions from the user and system scopes +Services.prefs.setIntPref("extensions.enabledScopes", + AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_USER + + AddonManager.SCOPE_SYSTEM); + +var addon1 = { + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +var addon2 = { + id: "addon2@tests.mozilla.org", + version: "2.0", + name: "Test 2", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +var addon3 = { + id: "addon3@tests.mozilla.org", + version: "2.0", + name: "Test 3", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +var addon4 = { + id: "addon4@tests.mozilla.org", + version: "2.0", + name: "Test 4", + strictCompatibility: true, + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +var addon5 = { + id: "addon5@tests.mozilla.org", + version: "2.0", + name: "Test 5", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0", + maxVersion: "0" + }] +}; + +var addon6 = { + id: "addon6@tests.mozilla.org", + version: "2.0", + name: "Test 6", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0", + maxVersion: "0" + }] +}; + +var addon7 = { + id: "addon7@tests.mozilla.org", + version: "2.0", + name: "Test 7", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +var addon8 = { + id: "addon8@tests.mozilla.org", + version: "2.0", + name: "Test 8", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); +const profileDir = gProfD.clone(); +profileDir.append("extensions"); +const globalDir = gProfD.clone(); +globalDir.append("extensions2"); +globalDir.append(gAppInfo.ID); +registerDirectory("XRESysSExtPD", globalDir.parent); +const userDir = gProfD.clone(); +userDir.append("extensions3"); +userDir.append(gAppInfo.ID); +registerDirectory("XREUSysExt", userDir.parent); + +function run_test() { + do_test_pending(); + + writeInstallRDFForExtension(addon1, profileDir); + writeInstallRDFForExtension(addon2, profileDir); + writeInstallRDFForExtension(addon3, profileDir); + writeInstallRDFForExtension(addon4, profileDir); + writeInstallRDFForExtension(addon5, profileDir); + writeInstallRDFForExtension(addon6, profileDir); + writeInstallRDFForExtension(addon7, globalDir); + writeInstallRDFForExtension(addon8, userDir); + + // Write out a minimal database + let dbfile = gProfD.clone(); + dbfile.append("extensions.sqlite"); + let db = AM_Cc["@mozilla.org/storage/service;1"]. + getService(AM_Ci.mozIStorageService). + openDatabase(dbfile); + db.createTable("addon", "internal_id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "id TEXT, location TEXT, version TEXT, active INTEGER, " + + "userDisabled INTEGER, installDate INTEGER"); + db.createTable("targetApplication", "addon_internal_id INTEGER, " + + "id TEXT, minVersion TEXT, maxVersion TEXT"); + let stmt = db.createStatement("INSERT INTO addon VALUES (NULL, :id, :location, " + + ":version, :active, :userDisabled, :installDate)"); + + let internal_ids = {}; + + [["addon1@tests.mozilla.org", "app-profile", "1.0", "1", "0", "0"], + ["addon2@tests.mozilla.org", "app-profile", "2.0", "0", "1", "0"], + ["addon3@tests.mozilla.org", "app-profile", "2.0", "1", "1", "0"], + ["addon4@tests.mozilla.org", "app-profile", "2.0", "0", "0", "0"], + ["addon5@tests.mozilla.org", "app-profile", "2.0", "1", "0", "0"], + ["addon6@tests.mozilla.org", "app-profile", "1.0", "0", "1", "0"], + ["addon7@tests.mozilla.org", "app-system-share", "1.0", "1", "0", "0"], + ["addon8@tests.mozilla.org", "app-system-user", "1.0", "1", "0", "0"]].forEach(function(a) { + stmt.params.id = a[0]; + stmt.params.location = a[1]; + stmt.params.version = a[2]; + stmt.params.active = a[3]; + stmt.params.userDisabled = a[4]; + stmt.params.installDate = a[5]; + stmt.execute(); + internal_ids[a[0]] = db.lastInsertRowID; + }); + stmt.finalize(); + + // Add updated target application into for addon5 + stmt = db.createStatement("INSERT INTO targetApplication VALUES " + + "(:internal_id, :id, :minVersion, :maxVersion)"); + stmt.params.internal_id = internal_ids["addon5@tests.mozilla.org"]; + stmt.params.id = "xpcshell@tests.mozilla.org"; + stmt.params.minVersion = "0"; + stmt.params.maxVersion = "1"; + stmt.execute(); + + // Add updated target application into for addon6 + stmt.params.internal_id = internal_ids["addon6@tests.mozilla.org"]; + stmt.params.id = "xpcshell@tests.mozilla.org"; + stmt.params.minVersion = "0"; + stmt.params.maxVersion = "1"; + stmt.execute(); + stmt.finalize(); + + db.schemaVersion = 10000; + Services.prefs.setIntPref("extensions.databaseSchema", 14); + db.close(); + + startupManager(); + check_startup_changes("installed", []); + check_startup_changes("updated", []); + check_startup_changes("uninstalled", []); + check_startup_changes("disabled", []); + check_startup_changes("enabled", []); + + 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", + "addon8@tests.mozilla.org"], + function([a1, a2, a3, a4, a5, a6, a7, a8]) { + // addon1 was enabled in the database + do_check_neq(a1, null); + do_check_false(a1.userDisabled); + do_check_false(a1.appDisabled); + do_check_true(a1.isActive); + do_check_false(a1.strictCompatibility); + do_check_false(a1.foreignInstall); + // addon2 was disabled in the database + do_check_neq(a2, null); + do_check_true(a2.userDisabled); + do_check_false(a2.appDisabled); + do_check_false(a2.isActive); + do_check_false(a2.strictCompatibility); + do_check_false(a2.foreignInstall); + // addon3 was pending-disable in the database + do_check_neq(a3, null); + do_check_true(a3.userDisabled); + do_check_false(a3.appDisabled); + do_check_false(a3.isActive); + do_check_false(a3.strictCompatibility); + do_check_false(a3.foreignInstall); + // addon4 was pending-enable in the database + do_check_neq(a4, null); + do_check_false(a4.userDisabled); + do_check_false(a4.appDisabled); + do_check_true(a4.isActive); + do_check_true(a4.strictCompatibility); + do_check_false(a4.foreignInstall); + // addon5 was enabled in the database but needed a compatibility update + do_check_neq(a5, null); + do_check_false(a5.userDisabled); + do_check_false(a5.appDisabled); + do_check_true(a5.isActive); + do_check_false(a5.strictCompatibility); + do_check_false(a5.foreignInstall); + // addon6 was disabled and compatible but a new version has been installed + // since, it should still be disabled but should be incompatible + do_check_neq(a6, null); + do_check_true(a6.userDisabled); + do_check_true(a6.appDisabled); + do_check_false(a6.isActive); + do_check_false(a6.strictCompatibility); + do_check_false(a6.foreignInstall); + // addon7 is in the global install location so should be a foreignInstall + do_check_neq(a7, null); + do_check_false(a7.userDisabled); + do_check_false(a7.appDisabled); + do_check_true(a7.isActive); + do_check_false(a7.strictCompatibility); + do_check_true(a7.foreignInstall); + // addon8 is in the user install location so should be a foreignInstall + do_check_neq(a8, null); + do_check_false(a8.userDisabled); + do_check_false(a8.appDisabled); + do_check_true(a8.isActive); + do_check_false(a8.strictCompatibility); + do_check_true(a8.foreignInstall); + + do_execute_soon(do_test_finished); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_migrate3.js b/toolkit/mozapps/extensions/test/xpcshell/test_migrate3.js new file mode 100644 index 000000000..f27d53c3f --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_migrate3.js @@ -0,0 +1,239 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Checks that we migrate data from the old extensions.rdf database. This +// matches test_migrate1.js however it runs with a lightweight theme selected +// so the themes should appear disabled. + +Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm"); + +var addon1 = { + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +var addon2 = { + id: "addon2@tests.mozilla.org", + version: "2.0", + name: "Test 2", + targetApplications: [{ + id: "toolkit@mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +var addon3 = { + id: "addon3@tests.mozilla.org", + version: "2.0", + name: "Test 3", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +var addon4 = { + id: "addon4@tests.mozilla.org", + version: "2.0", + name: "Test 4", + targetApplications: [{ + id: "toolkit@mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +var addon5 = { + id: "addon5@tests.mozilla.org", + version: "2.0", + name: "Test 5", + targetApplications: [{ + id: "toolkit@mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +var theme1 = { + id: "theme1@tests.mozilla.org", + version: "1.0", + name: "Theme 1", + type: 4, + internalName: "theme1/1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }] +}; + +var theme2 = { + id: "theme2@tests.mozilla.org", + version: "1.0", + name: "Theme 2", + type: 4, + internalName: "theme2/1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + 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(theme1, profileDir); + writeInstallRDFForExtension(theme2, profileDir); + + // Cannot use the LightweightThemeManager before AddonManager has been started + // so inject the correct prefs + Services.prefs.setCharPref("lightweightThemes.usedThemes", JSON.stringify([{ + id: "1", + version: "1", + name: "Test LW Theme", + description: "A test theme", + author: "Mozilla", + homepageURL: "http://localhost/data/index.html", + headerURL: "http://localhost/data/header.png", + footerURL: "http://localhost/data/footer.png", + previewURL: "http://localhost/data/preview.png", + iconURL: "http://localhost/data/icon.png" + }])); + Services.prefs.setBoolPref("lightweightThemes.isThemeSelected", true); + + let stagedXPIs = profileDir.clone(); + stagedXPIs.append("staged-xpis"); + stagedXPIs.append("addon6@tests.mozilla.org"); + stagedXPIs.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755); + + let addon6 = do_get_addon("test_migrate6"); + addon6.copyTo(stagedXPIs, "tmp.xpi"); + stagedXPIs = stagedXPIs.parent; + + stagedXPIs.append("addon7@tests.mozilla.org"); + stagedXPIs.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755); + + let addon7 = do_get_addon("test_migrate7"); + addon7.copyTo(stagedXPIs, "tmp.xpi"); + stagedXPIs = stagedXPIs.parent; + + let old = do_get_file("data/test_migrate.rdf"); + old.copyTo(gProfD, "extensions.rdf"); + + // Theme state is determined by the selected theme pref + Services.prefs.setCharPref("general.skins.selectedSkin", "theme1/1.0"); + + startupManager(); + check_startup_changes("installed", []); + check_startup_changes("updated", []); + check_startup_changes("uninstalled", []); + check_startup_changes("disabled", []); + check_startup_changes("enabled", []); + + 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]) { + // addon1 was user and app enabled in the old extensions.rdf + do_check_neq(a1, null); + do_check_false(a1.userDisabled); + do_check_false(a1.appDisabled); + do_check_true(a1.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); + + // addon2 was user disabled and app enabled in the old extensions.rdf + do_check_neq(a2, null); + do_check_true(a2.userDisabled); + do_check_false(a2.appDisabled); + do_check_false(a2.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a2.id)); + + // addon3 was pending user disable and app disabled in the old extensions.rdf + do_check_neq(a3, null); + do_check_true(a3.userDisabled); + do_check_true(a3.appDisabled); + do_check_false(a3.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a3.id)); + + // addon4 was pending user enable and app disabled in the old extensions.rdf + do_check_neq(a4, null); + do_check_false(a4.userDisabled); + do_check_true(a4.appDisabled); + do_check_false(a4.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a4.id)); + + // addon5 was disabled and compatible but a new version has been installed + // since, it should still be disabled but should be incompatible + do_check_neq(a5, null); + do_check_true(a5.userDisabled); + do_check_true(a5.appDisabled); + do_check_false(a5.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a5.id)); + + // addon6 should be installed and compatible and packed unless unpacking is + // forced + do_check_neq(a6, null); + do_check_false(a6.userDisabled); + do_check_false(a6.appDisabled); + do_check_true(a6.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a6.id)); + if (Services.prefs.getBoolPref("extensions.alwaysUnpack")) + do_check_eq(a6.getResourceURI("install.rdf").scheme, "file"); + else + do_check_eq(a6.getResourceURI("install.rdf").scheme, "jar"); + + // addon7 should be installed and compatible and unpacked + do_check_neq(a7, null); + do_check_false(a7.userDisabled); + do_check_false(a7.appDisabled); + do_check_true(a7.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a7.id)); + do_check_eq(a7.getResourceURI("install.rdf").scheme, "file"); + + // Theme 1 was previously disabled + do_check_neq(t1, null); + do_check_true(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_false(t1.isActive); + do_check_true(isThemeInAddonsList(profileDir, t1.id)); + do_check_true(hasFlag(t1.permissions, AddonManager.PERM_CAN_ENABLE)); + + // Theme 2 was previously disabled + do_check_neq(t1, null); + do_check_true(t2.userDisabled); + do_check_false(t2.appDisabled); + do_check_false(t2.isActive); + do_check_false(isThemeInAddonsList(profileDir, t2.id)); + do_check_true(hasFlag(t2.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_check_false(stagedXPIs.exists()); + + do_execute_soon(do_test_finished); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_migrate4.js b/toolkit/mozapps/extensions/test/xpcshell/test_migrate4.js new file mode 100644 index 000000000..b2903ead7 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_migrate4.js @@ -0,0 +1,307 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Checks that we migrate data from a previous version of the JSON database + +// The test extension uses an insecure update url. +Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); + +Components.utils.import("resource://testing-common/httpd.js"); +var testserver = new HttpServer(); +testserver.start(-1); +gPort = testserver.identity.primaryPort; +mapFile("/data/test_migrate4.rdf", testserver); +testserver.registerDirectory("/addons/", do_get_file("addons")); + +var addon1 = { + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }] +}; + +var addon2 = { + id: "addon2@tests.mozilla.org", + version: "2.0", + name: "Test 2", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }] +}; + +var addon3 = { + id: "addon3@tests.mozilla.org", + version: "2.0", + name: "Test 3", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }] +}; + +var addon4 = { + id: "addon4@tests.mozilla.org", + version: "2.0", + name: "Test 4", + strictCompatibility: true, + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }] +}; + +var addon5 = { + id: "addon5@tests.mozilla.org", + version: "2.0", + name: "Test 5", + updateURL: "http://localhost:" + gPort + "/data/test_migrate4.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0", + maxVersion: "1" + }] +}; + +var addon6 = { + id: "addon6@tests.mozilla.org", + version: "1.0", + name: "Test 6", + updateURL: "http://localhost:" + gPort + "/data/test_migrate4.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0", + maxVersion: "1" + }] +}; + +var defaultTheme = { + id: "default@tests.mozilla.org", + version: "1.0", + name: "Default", + internalName: "classic/1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }] +}; + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +let oldSyncGUIDs = {}; + +function prepare_profile() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + writeInstallRDFForExtension(addon1, profileDir); + writeInstallRDFForExtension(addon2, profileDir); + writeInstallRDFForExtension(addon3, profileDir); + writeInstallRDFForExtension(addon4, profileDir); + writeInstallRDFForExtension(addon5, profileDir); + writeInstallRDFForExtension(addon6, profileDir); + writeInstallRDFForExtension(defaultTheme, profileDir); + + startupManager(); + installAllFiles([do_get_addon("test_migrate8"), do_get_addon("test_migrate9")], + function() { + 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", + "addon9@tests.mozilla.org"], + function([a1, a2, a3, a4, a5, a6, a9]) { + a1.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DEFAULT; + a2.userDisabled = true; + a2.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE; + a3.applyBackgroundUpdates = AddonManager.AUTOUPDATE_ENABLE; + a4.userDisabled = true; + a6.userDisabled = true; + a9.userDisabled = false; + + for each (let addon in [a1, a2, a3, a4, a5, a6]) { + oldSyncGUIDs[addon.id] = addon.syncGUID; + } + + a6.findUpdates({ + onUpdateAvailable: function(aAddon, aInstall6) { + AddonManager.getInstallForURL("http://localhost:" + gPort + "/addons/test_migrate4_7.xpi", function(aInstall7) { + completeAllInstalls([aInstall6, aInstall7], function() { + 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"], + function([a1, a2, a3, a4, a5, a6]) { + a3.userDisabled = true; + a4.userDisabled = false; + + a5.findUpdates({ + onUpdateFinished: function() { + do_execute_soon(perform_migration); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); + }); + }, "application/x-xpinstall"); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); + }); +} + +function perform_migration() { + shutdownManager(); + + // Turn on disabling for all scopes + Services.prefs.setIntPref("extensions.autoDisableScopes", 15); + + changeXPIDBVersion(1); + Services.prefs.setIntPref("extensions.databaseSchema", 1); + + gAppInfo.version = "2" + startupManager(true); + test_results(); +} + +function test_results() { + check_startup_changes("installed", []); + check_startup_changes("updated", []); + check_startup_changes("uninstalled", []); + check_startup_changes("disabled", []); + check_startup_changes("enabled", []); + + 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", + "addon8@tests.mozilla.org", + "addon9@tests.mozilla.org"], + function([a1, a2, a3, a4, a5, a6, a7, a8, a9]) { + // addon1 was enabled + do_check_neq(a1, null); + do_check_eq(a1.syncGUID, oldSyncGUIDs[a1.id]); + do_check_false(a1.userDisabled); + do_check_false(a1.appDisabled); + do_check_true(a1.isActive); + do_check_eq(a1.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DEFAULT); + do_check_true(a1.foreignInstall); + do_check_false(a1.hasBinaryComponents); + do_check_false(a1.strictCompatibility); + + // addon2 was disabled + do_check_neq(a2, null); + do_check_eq(a2.syncGUID, oldSyncGUIDs[a2.id]); + do_check_true(a2.userDisabled); + do_check_false(a2.appDisabled); + do_check_false(a2.isActive); + do_check_eq(a2.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DISABLE); + do_check_true(a2.foreignInstall); + do_check_false(a2.hasBinaryComponents); + do_check_false(a2.strictCompatibility); + + // addon3 was pending-disable in the database + do_check_neq(a3, null); + do_check_eq(a3.syncGUID, oldSyncGUIDs[a3.id]); + do_check_true(a3.userDisabled); + do_check_false(a3.appDisabled); + do_check_false(a3.isActive); + do_check_eq(a3.applyBackgroundUpdates, AddonManager.AUTOUPDATE_ENABLE); + do_check_true(a3.foreignInstall); + do_check_false(a3.hasBinaryComponents); + do_check_false(a3.strictCompatibility); + + // addon4 was pending-enable in the database + do_check_neq(a4, null); + do_check_eq(a4.syncGUID, oldSyncGUIDs[a4.id]); + do_check_false(a4.userDisabled); + do_check_false(a4.appDisabled); + do_check_true(a4.isActive); + do_check_eq(a4.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DEFAULT); + do_check_true(a4.foreignInstall); + do_check_false(a4.hasBinaryComponents); + do_check_true(a4.strictCompatibility); + + // addon5 was enabled in the database but needed a compatibility update + do_check_neq(a5, null); + do_check_false(a5.userDisabled); + do_check_false(a5.appDisabled); + do_check_true(a5.isActive); + do_check_eq(a4.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DEFAULT); + do_check_true(a5.foreignInstall); + do_check_false(a5.hasBinaryComponents); + do_check_false(a5.strictCompatibility); + + // addon6 was disabled and compatible but a new version has been installed + do_check_neq(a6, null); + do_check_eq(a6.syncGUID, oldSyncGUIDs[a6.id]); + do_check_eq(a6.version, "2.0"); + do_check_true(a6.userDisabled); + do_check_false(a6.appDisabled); + do_check_false(a6.isActive); + do_check_eq(a6.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DEFAULT); + do_check_true(a6.foreignInstall); + do_check_eq(a6.sourceURI.spec, "http://localhost:" + gPort + "/addons/test_migrate4_6.xpi"); + do_check_eq(a6.releaseNotesURI.spec, "http://example.com/updateInfo.xhtml"); + do_check_false(a6.hasBinaryComponents); + do_check_false(a6.strictCompatibility); + + // addon7 was installed manually + do_check_neq(a7, null); + do_check_eq(a7.version, "1.0"); + do_check_false(a7.userDisabled); + do_check_false(a7.appDisabled); + do_check_true(a7.isActive); + do_check_eq(a7.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DEFAULT); + do_check_false(a7.foreignInstall); + do_check_eq(a7.sourceURI.spec, "http://localhost:" + gPort + "/addons/test_migrate4_7.xpi"); + do_check_eq(a7.releaseNotesURI, null); + do_check_false(a7.hasBinaryComponents); + do_check_false(a7.strictCompatibility); + + // addon8 was enabled and has binary components + do_check_neq(a8, null); + do_check_false(a8.userDisabled); + do_check_false(a8.appDisabled); + do_check_true(a8.isActive); + do_check_false(a8.foreignInstall); + do_check_true(a8.hasBinaryComponents); + do_check_false(a8.strictCompatibility); + + // addon9 is the active theme + do_check_neq(a9, null); + do_check_false(a9.userDisabled); + do_check_false(a9.appDisabled); + do_check_true(a9.isActive); + do_check_false(a9.foreignInstall); + do_check_false(a9.hasBinaryComponents); + do_check_true(a9.strictCompatibility); + + testserver.stop(do_test_finished); + }); +} + +function run_test() { + do_test_pending(); + + prepare_profile(); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_migrate5.js b/toolkit/mozapps/extensions/test/xpcshell/test_migrate5.js new file mode 100644 index 000000000..0109dcf92 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_migrate5.js @@ -0,0 +1,139 @@ +/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Checks that we fail to migrate but still start up ok when there is a SQLITE database
+// with no useful data in it.
+
+const PREF_GENERAL_SKINS_SELECTEDSKIN = "general.skins.selectedSkin";
+
+var addon1 = {
+ id: "addon1@tests.mozilla.org",
+ version: "1.0",
+ name: "Test 1",
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "1",
+ maxVersion: "1"
+ }]
+};
+
+var addon2 = {
+ id: "addon2@tests.mozilla.org",
+ version: "2.0",
+ name: "Test 5",
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "0",
+ maxVersion: "0"
+ }]
+};
+
+var defaultTheme = {
+ id: "default@tests.mozilla.org",
+ version: "2.0",
+ name: "Default theme",
+ internalName: "classic/1.0",
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "1",
+ maxVersion: "1"
+ }]
+};
+
+var theme1 = {
+ id: "theme1@tests.mozilla.org",
+ version: "2.0",
+ name: "Test theme",
+ internalName: "theme1/1.0",
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "1",
+ maxVersion: "1"
+ }]
+};
+
+const profileDir = gProfD.clone();
+profileDir.append("extensions");
+
+function run_test() {
+ do_test_pending();
+ createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
+
+ writeInstallRDFForExtension(addon1, profileDir);
+ writeInstallRDFForExtension(addon2, profileDir);
+ writeInstallRDFForExtension(defaultTheme, profileDir);
+ writeInstallRDFForExtension(theme1, profileDir);
+
+ Services.prefs.setCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN, "theme1/1.0");
+
+ // Write out a broken database (no userDisabled field)
+ let dbfile = gProfD.clone();
+ dbfile.append("extensions.sqlite");
+ let db = AM_Cc["@mozilla.org/storage/service;1"].
+ getService(AM_Ci.mozIStorageService).
+ openDatabase(dbfile);
+ db.createTable("addon", "internal_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
+ "id TEXT, location TEXT, version TEXT, active INTEGER, " +
+ "installDate INTEGER");
+ db.createTable("targetApplication", "addon_internal_id INTEGER, " +
+ "id TEXT, minVersion TEXT, maxVersion TEXT");
+ let stmt = db.createStatement("INSERT INTO addon VALUES (NULL, :id, :location, " +
+ ":version, :active, :installDate)");
+
+ let internal_ids = {};
+
+ [["addon1@tests.mozilla.org", "app-profile", "1.0", "1", "0"],
+ ["addon2@tests.mozilla.org", "app-profile", "2.0", "0", "0"],
+ ["default@tests.mozilla.org", "app-profile", "2.0", "1", "0"],
+ ["theme1@tests.mozilla.org", "app-profile", "2.0", "0", "0"]].forEach(function(a) {
+ stmt.params.id = a[0];
+ stmt.params.location = a[1];
+ stmt.params.version = a[2];
+ stmt.params.active = a[3];
+ stmt.params.installDate = a[4];
+ stmt.execute();
+ internal_ids[a[0]] = db.lastInsertRowID;
+ });
+ stmt.finalize();
+
+ db.schemaVersion = 100;
+ Services.prefs.setIntPref("extensions.databaseSchema", 100);
+ db.close();
+
+ startupManager();
+ check_startup_changes("installed", []);
+ check_startup_changes("updated", []);
+ check_startup_changes("uninstalled", []);
+ check_startup_changes("disabled", []);
+ check_startup_changes("enabled", []);
+
+ AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
+ "addon2@tests.mozilla.org",
+ "default@tests.mozilla.org",
+ "theme1@tests.mozilla.org"],
+ function([a1, a2, d, t1]) {
+ do_check_neq(a1, null);
+ do_check_false(a1.userDisabled);
+ do_check_false(a1.appDisabled);
+ do_check_true(a1.isActive);
+
+ do_check_neq(a2, null);
+ do_check_false(a2.userDisabled);
+ do_check_true(a2.appDisabled);
+ do_check_false(a2.isActive);
+
+ // Should have enabled the selected theme
+ do_check_neq(t1, null);
+ do_check_false(t1.userDisabled);
+ do_check_false(t1.appDisabled);
+ do_check_true(t1.isActive);
+
+ do_check_neq(d, null);
+ do_check_true(d.userDisabled);
+ do_check_false(d.appDisabled);
+ do_check_false(d.isActive);
+
+ do_execute_soon(do_test_finished);
+ });
+}
diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_migrateAddonRepository.js b/toolkit/mozapps/extensions/test/xpcshell/test_migrateAddonRepository.js new file mode 100644 index 000000000..ad8bd5bca --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_migrateAddonRepository.js @@ -0,0 +1,127 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +const EXPECTED_SCHEMA_VERSION = 4; +let dbfile; + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + // Write out a minimal database. + dbfile = gProfD.clone(); + dbfile.append("addons.sqlite"); + let db = AM_Cc["@mozilla.org/storage/service;1"]. + getService(AM_Ci.mozIStorageService). + openDatabase(dbfile); + + db.createTable("addon", + "internal_id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "id TEXT UNIQUE, " + + "type TEXT, " + + "name TEXT, " + + "version TEXT, " + + "creator TEXT, " + + "creatorURL TEXT, " + + "description TEXT, " + + "fullDescription TEXT, " + + "developerComments TEXT, " + + "eula TEXT, " + + "iconURL TEXT, " + + "homepageURL TEXT, " + + "supportURL TEXT, " + + "contributionURL TEXT, " + + "contributionAmount TEXT, " + + "averageRating INTEGER, " + + "reviewCount INTEGER, " + + "reviewURL TEXT, " + + "totalDownloads INTEGER, " + + "weeklyDownloads INTEGER, " + + "dailyUsers INTEGER, " + + "sourceURI TEXT, " + + "repositoryStatus INTEGER, " + + "size INTEGER, " + + "updateDate INTEGER"); + + db.createTable("developer", + "addon_internal_id INTEGER, " + + "num INTEGER, " + + "name TEXT, " + + "url TEXT, " + + "PRIMARY KEY (addon_internal_id, num)"); + + db.createTable("screenshot", + "addon_internal_id INTEGER, " + + "num INTEGER, " + + "url TEXT, " + + "thumbnailURL TEXT, " + + "caption TEXT, " + + "PRIMARY KEY (addon_internal_id, num)"); + + let stmt = db.createStatement("INSERT INTO addon (id) VALUES (:id)"); + stmt.params.id = "test1@tests.mozilla.org"; + stmt.execute(); + stmt.finalize(); + + stmt = db.createStatement("INSERT INTO screenshot VALUES " + + "(:addon_internal_id, :num, :url, :thumbnailURL, :caption)"); + + stmt.params.addon_internal_id = 1; + stmt.params.num = 0; + stmt.params.url = "http://localhost/full1-1.png"; + stmt.params.thumbnailURL = "http://localhost/thumbnail1-1.png"; + stmt.params.caption = "Caption 1 - 1"; + stmt.execute(); + stmt.finalize(); + + db.schemaVersion = 1; + db.close(); + + + Services.prefs.setBoolPref("extensions.getAddons.cache.enabled", true); + AddonRepository.getCachedAddonByID("test1@tests.mozilla.org", function (aAddon) { + do_check_neq(aAddon, null); + do_check_eq(aAddon.screenshots.length, 1); + do_check_true(aAddon.screenshots[0].width === null); + do_check_true(aAddon.screenshots[0].height === null); + do_check_true(aAddon.screenshots[0].thumbnailWidth === null); + do_check_true(aAddon.screenshots[0].thumbnailHeight === null); + do_check_eq(aAddon.iconURL, undefined); + do_check_eq(JSON.stringify(aAddon.icons), "{}"); + AddonRepository.shutdown().then( + function checkAfterRepoShutdown() { + // Check the DB schema has changed once AddonRepository has freed it. + db = AM_Cc["@mozilla.org/storage/service;1"]. + getService(AM_Ci.mozIStorageService). + openDatabase(dbfile); + do_check_eq(db.schemaVersion, EXPECTED_SCHEMA_VERSION); + do_check_true(db.indexExists("developer_idx")); + do_check_true(db.indexExists("screenshot_idx")); + do_check_true(db.indexExists("compatibility_override_idx")); + do_check_true(db.tableExists("compatibility_override")); + do_check_true(db.indexExists("icon_idx")); + do_check_true(db.tableExists("icon")); + + // Check the trigger is working + db.executeSimpleSQL("INSERT INTO addon (id, type, name) VALUES('test_addon', 'extension', 'Test Addon')"); + let internalID = db.lastInsertRowID; + db.executeSimpleSQL("INSERT INTO compatibility_override (addon_internal_id, num, type) VALUES('" + internalID + "', '1', 'incompatible')"); + + let stmt = db.createStatement("SELECT COUNT(*) AS count FROM compatibility_override"); + stmt.executeStep(); + do_check_eq(stmt.row.count, 1); + stmt.reset(); + + db.executeSimpleSQL("DELETE FROM addon"); + stmt.executeStep(); + do_check_eq(stmt.row.count, 0); + stmt.finalize(); + + db.close(); + do_test_finished(); + }, + do_report_unexpected_exception + ); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_migrate_max_version.js b/toolkit/mozapps/extensions/test/xpcshell/test_migrate_max_version.js new file mode 100644 index 000000000..133c3a199 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_migrate_max_version.js @@ -0,0 +1,103 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Checks that we don't migrate data from SQLITE if +// the "extensions.databaseSchema" preference shows we've +// already upgraded to JSON + +// Enable loading extensions from the user and system scopes +Services.prefs.setIntPref("extensions.enabledScopes", + AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_USER + + AddonManager.SCOPE_SYSTEM); + +var addon1 = { + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +function run_test() { + writeInstallRDFForExtension(addon1, profileDir); + + // Write out a minimal database + let dbfile = gProfD.clone(); + dbfile.append("extensions.sqlite"); + let db = AM_Cc["@mozilla.org/storage/service;1"]. + getService(AM_Ci.mozIStorageService). + openDatabase(dbfile); + db.createTable("addon", "internal_id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "id TEXT, location TEXT, version TEXT, active INTEGER, " + + "userDisabled INTEGER, installDate INTEGER"); + db.createTable("targetApplication", "addon_internal_id INTEGER, " + + "id TEXT, minVersion TEXT, maxVersion TEXT"); + let stmt = db.createStatement("INSERT INTO addon VALUES (NULL, :id, :location, " + + ":version, :active, :userDisabled, :installDate)"); + + let internal_ids = {}; + + let a = ["addon1@tests.mozilla.org", "app-profile", "1.0", "0", "1", "0"]; + stmt.params.id = a[0]; + stmt.params.location = a[1]; + stmt.params.version = a[2]; + stmt.params.active = a[3]; + stmt.params.userDisabled = a[4]; + stmt.params.installDate = a[5]; + stmt.execute(); + internal_ids[a[0]] = db.lastInsertRowID; + stmt.finalize(); + + db.schemaVersion = 14; + Services.prefs.setIntPref("extensions.databaseSchema", 14); + db.close(); + + startupManager(); + run_next_test(); +} + +add_test(function before_rebuild() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", + function check_before_rebuild (a1) { + // First check that it migrated OK once + // addon1 was disabled in the database + do_check_neq(a1, null); + do_check_true(a1.userDisabled); + do_check_false(a1.appDisabled); + do_check_false(a1.isActive); + do_check_false(a1.strictCompatibility); + do_check_false(a1.foreignInstall); + + run_next_test(); + }); +}); + +// now shut down, remove the JSON database, +// start up again, and make sure the data didn't migrate this time +add_test(function rebuild_again() { + shutdownManager(); + gExtensionsJSON.remove(true); + startupManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", + function check_after_rebuild(a1) { + // addon1 was rebuilt from extensions directory, + // so it appears enabled as a foreign install + do_check_neq(a1, null); + do_check_false(a1.userDisabled); + do_check_false(a1.appDisabled); + do_check_true(a1.isActive); + do_check_false(a1.strictCompatibility); + do_check_true(a1.foreignInstall); + + run_next_test(); + }); +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_multiprocessCompatible.js b/toolkit/mozapps/extensions/test/xpcshell/test_multiprocessCompatible.js new file mode 100644 index 000000000..ab5a976cc --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_multiprocessCompatible.js @@ -0,0 +1,118 @@ +Components.utils.import("resource://testing-common/httpd.js"); +var gServer; + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); + +function build_test(multiprocessCompatible, bootstrap, updateMultiprocessCompatible) { + return function* () { + dump("Running test" + + " multiprocessCompatible: " + multiprocessCompatible + + " bootstrap: " + bootstrap + + " updateMultiprocessCompatible: " + updateMultiprocessCompatible + + "\n"); + + let addonData = { + id: "addon@tests.mozilla.org", + name: "Test Add-on", + version: "1.0", + multiprocessCompatible, + bootstrap, + updateURL: "http://localhost:" + gPort + "/updaterdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] + } + + gServer.registerPathHandler("/updaterdf", function(request, response) { + let updateData = {}; + updateData[addonData.id] = [{ + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] + }]; + + if (updateMultiprocessCompatible !== undefined) { + updateData[addonData.id][0].multiprocessCompatible = updateMultiprocessCompatible; + } + + response.setStatusLine(request.httpVersion, 200, "OK"); + response.write(createUpdateRDF(updateData)); + }); + + let expectedMPC = updateMultiprocessCompatible === undefined ? + multiprocessCompatible : + updateMultiprocessCompatible; + + let xpifile = createTempXPIFile(addonData); + let install = yield new Promise(resolve => AddonManager.getInstallForFile(xpifile, resolve)); + do_check_eq(install.addon.multiprocessCompatible, multiprocessCompatible); + yield promiseCompleteAllInstalls([install]); + + if (!bootstrap) { + yield promiseRestartManager(); + do_check_true(isExtensionInAddonsList(profileDir, addonData.id)); + do_check_eq(isItemMarkedMPIncompatible(addonData.id), !multiprocessCompatible); + } + + let addon = yield promiseAddonByID(addonData.id); + do_check_neq(addon, null); + do_check_eq(addon.multiprocessCompatible, multiprocessCompatible); + + yield promiseFindAddonUpdates(addon); + + // Should have applied the compatibility change + do_check_eq(addon.multiprocessCompatible, expectedMPC); + yield promiseRestartManager(); + + addon = yield promiseAddonByID(addonData.id); + // Should have persisted the compatibility change + do_check_eq(addon.multiprocessCompatible, expectedMPC); + if (!bootstrap) { + do_check_true(isExtensionInAddonsList(profileDir, addonData.id)); + do_check_eq(isItemMarkedMPIncompatible(addonData.id), !multiprocessCompatible); + } + + addon.uninstall(); + yield promiseRestartManager(); + + gServer.registerPathHandler("/updaterdf", null); + } +} + +/* Builds a set of tests to run the same steps for every combination of: + * The add-on being restartless + * The initial add-on supporting multiprocess + * The update saying the add-on should or should not support multiprocess (or not say anything at all) + */ +for (let bootstrap of [false, true]) { + for (let multiprocessCompatible of [false, true]) { + for (let updateMultiprocessCompatible of [undefined, false, true]) { + add_task(build_test(multiprocessCompatible, bootstrap, updateMultiprocessCompatible)); + } + } +} + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); + startupManager(); + + // Create and configure the HTTP server. + gServer = new HttpServer(); + gServer.registerDirectory("/data/", gTmpD); + gServer.start(-1); + gPort = gServer.identity.primaryPort; + + run_next_test(); +} + +function end_test() { + gServer.stop(do_test_finished); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_no_addons.js b/toolkit/mozapps/extensions/test/xpcshell/test_no_addons.js new file mode 100644 index 000000000..ae75fbb43 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_no_addons.js @@ -0,0 +1,98 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test startup and restart when no add-ons are installed +// bug 944006 + +Components.utils.import("resource://gre/modules/Promise.jsm"); + +// Load XPI Provider to get schema version ID +let XPIScope = Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm"); +const DB_SCHEMA = XPIScope.DB_SCHEMA; + +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + +function run_test() { + // Kick off the task-based tests... + run_next_test(); +} + +// Test for a preference to either exist with a specified value, or not exist at all +function checkPending() { + try { + do_check_false(Services.prefs.getBoolPref("extensions.pendingOperations")); + } + catch (e) { + // OK + } +} + +function checkString(aPref, aValue) { + try { + do_check_eq(Services.prefs.getCharPref(aPref), aValue) + } + catch (e) { + //OK + } +} + +// Make sure all our extension state is empty/nonexistent +function check_empty_state() { + do_check_false(gExtensionsJSON.exists()); + do_check_false(gExtensionsINI.exists()); + + do_check_eq(Services.prefs.getIntPref("extensions.databaseSchema"), DB_SCHEMA); + + checkString("extensions.bootstrappedAddons", "{}"); + checkString("extensions.installCache", "[]"); + checkPending(); +} + +// After first run with no add-ons, we expect: +// no extensions.json is created +// no extensions.ini +// database schema version preference is set +// bootstrap add-ons preference is not found +// add-on directory state preference is an empty array +// no pending operations +add_task(function first_run() { + startupManager(); + check_empty_state(); + yield true; +}); + +// Now do something that causes a DB load, and re-check +function trigger_db_load() { + let addonDefer = Promise.defer(); + AddonManager.getAddonsByTypes(['extension'], addonDefer.resolve); + let addonList = yield addonDefer.promise; + + do_check_eq(addonList.length, 0); + check_empty_state(); + + yield true; +}; +add_task(trigger_db_load); + +// Now restart the manager and check again +add_task(function restart_and_recheck() { + restartManager(); + check_empty_state(); + yield true; +}); + +// and reload the DB again +add_task(trigger_db_load); + +// When we start up with no DB and an old database schema, we should update the +// schema number but not create a database +add_task(function upgrade_schema_version() { + shutdownManager(); + Services.prefs.setIntPref("extensions.databaseSchema", 1); + + startupManager(); + do_check_eq(Services.prefs.getIntPref("extensions.databaseSchema"), DB_SCHEMA); + check_empty_state(); +}); + diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_onPropertyChanged_appDisabled.js b/toolkit/mozapps/extensions/test/xpcshell/test_onPropertyChanged_appDisabled.js new file mode 100644 index 000000000..f9b7da073 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_onPropertyChanged_appDisabled.js @@ -0,0 +1,66 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0.1", + maxVersion: "0.2" + }] + }, profileDir); + + startupManager(); + + AddonManager.strictCompatibility = false; + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { + do_check_neq(aAddon, null); + aAddon.userDisabled = true; + do_execute_soon(run_test_1); + }); +} + +function run_test_1() { + restartManager(); + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { + do_check_neq(aAddon, null); + do_check_true(aAddon.userDisabled); + do_check_false(aAddon.isActive); + do_check_false(aAddon.appDisabled); + + prepare_test({ + "addon1@tests.mozilla.org": [ + ["onPropertyChanged", ["appDisabled"]] + ] + }, [], run_test_2); + + AddonManager.strictCompatibility = true; + }); +} + +function run_test_2() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { + do_check_neq(aAddon, null); + do_check_true(aAddon.userDisabled); + do_check_false(aAddon.isActive); + do_check_true(aAddon.appDisabled); + + prepare_test({ + "addon1@tests.mozilla.org": [ + ["onPropertyChanged", ["appDisabled"]] + ] + }, [], callback_soon(do_test_finished)); + + AddonManager.strictCompatibility = false; + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_overrideblocklist.js b/toolkit/mozapps/extensions/test/xpcshell/test_overrideblocklist.js new file mode 100644 index 000000000..8a6bedea1 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_overrideblocklist.js @@ -0,0 +1,200 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +const KEY_PROFILEDIR = "ProfD"; +const KEY_APPDIR = "XCurProcD"; +const FILE_BLOCKLIST = "blocklist.xml"; + +const PREF_BLOCKLIST_ENABLED = "extensions.blocklist.enabled"; + +const OLD = do_get_file("data/test_overrideblocklist/old.xml"); +const NEW = do_get_file("data/test_overrideblocklist/new.xml"); +const ANCIENT = do_get_file("data/test_overrideblocklist/ancient.xml"); +const OLD_TSTAMP = 1296046918000; +const NEW_TSTAMP = 1396046918000; + +const gAppDir = FileUtils.getFile(KEY_APPDIR, []); + +let oldAddon = { + id: "old@tests.mozilla.org", + version: 1 +} +let newAddon = { + id: "new@tests.mozilla.org", + version: 1 +} +let ancientAddon = { + id: "ancient@tests.mozilla.org", + version: 1 +} +let invalidAddon = { + id: "invalid@tests.mozilla.org", + version: 1 +} + +function incrementAppVersion() { + gAppInfo.version = "" + (parseInt(gAppInfo.version) + 1); +} + +function clearBlocklists() { + let blocklist = FileUtils.getFile(KEY_APPDIR, [FILE_BLOCKLIST]); + if (blocklist.exists()) + blocklist.remove(true); + + blocklist = FileUtils.getFile(KEY_PROFILEDIR, [FILE_BLOCKLIST]); + if (blocklist.exists()) + blocklist.remove(true); +} + +function reloadBlocklist() { + Services.prefs.setBoolPref(PREF_BLOCKLIST_ENABLED, false); + Services.prefs.setBoolPref(PREF_BLOCKLIST_ENABLED, true); +} + +function copyToApp(file) { + file.clone().copyTo(gAppDir, FILE_BLOCKLIST); +} + +function copyToProfile(file, tstamp) { + file = file.clone(); + file.copyTo(gProfD, FILE_BLOCKLIST); + file = gProfD.clone(); + file.append(FILE_BLOCKLIST); + file.lastModifiedTime = tstamp; +} + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); + + let appBlocklist = FileUtils.getFile(KEY_APPDIR, [FILE_BLOCKLIST]); + if (appBlocklist.exists()) { + try { + appBlocklist.moveTo(gAppDir, "blocklist.old"); + } + catch (e) { + todo(false, "Aborting test due to unmovable blocklist file: " + e); + return; + } + do_register_cleanup(function() { + clearBlocklists(); + appBlocklist.moveTo(gAppDir, FILE_BLOCKLIST); + }); + } + + run_next_test(); +} + +// On first run whataver is in the app dir should get copied to the profile +add_test(function test_copy() { + clearBlocklists(); + copyToApp(OLD); + + incrementAppVersion(); + startupManager(); + + reloadBlocklist(); + let blocklist = AM_Cc["@mozilla.org/extensions/blocklist;1"]. + getService(AM_Ci.nsIBlocklistService); + do_check_false(blocklist.isAddonBlocklisted(invalidAddon)); + do_check_false(blocklist.isAddonBlocklisted(ancientAddon)); + do_check_true(blocklist.isAddonBlocklisted(oldAddon)); + do_check_false(blocklist.isAddonBlocklisted(newAddon)); + + shutdownManager(); + + run_next_test(); +}); + +// An ancient blocklist should be ignored +add_test(function test_ancient() { + clearBlocklists(); + copyToApp(ANCIENT); + copyToProfile(OLD, OLD_TSTAMP); + + incrementAppVersion(); + startupManager(); + + reloadBlocklist(); + let blocklist = AM_Cc["@mozilla.org/extensions/blocklist;1"]. + getService(AM_Ci.nsIBlocklistService); + do_check_false(blocklist.isAddonBlocklisted(invalidAddon)); + do_check_false(blocklist.isAddonBlocklisted(ancientAddon)); + do_check_true(blocklist.isAddonBlocklisted(oldAddon)); + do_check_false(blocklist.isAddonBlocklisted(newAddon)); + + shutdownManager(); + + run_next_test(); +}); + +// A new blocklist should override an old blocklist +add_test(function test_override() { + clearBlocklists(); + copyToApp(NEW); + copyToProfile(OLD, OLD_TSTAMP); + + incrementAppVersion(); + startupManager(); + + reloadBlocklist(); + let blocklist = AM_Cc["@mozilla.org/extensions/blocklist;1"]. + getService(AM_Ci.nsIBlocklistService); + do_check_false(blocklist.isAddonBlocklisted(invalidAddon)); + do_check_false(blocklist.isAddonBlocklisted(ancientAddon)); + do_check_false(blocklist.isAddonBlocklisted(oldAddon)); + do_check_true(blocklist.isAddonBlocklisted(newAddon)); + + shutdownManager(); + + run_next_test(); +}); + +// An old blocklist shouldn't override a new blocklist +add_test(function test_retain() { + clearBlocklists(); + copyToApp(OLD); + copyToProfile(NEW, NEW_TSTAMP); + + incrementAppVersion(); + startupManager(); + + reloadBlocklist(); + let blocklist = AM_Cc["@mozilla.org/extensions/blocklist;1"]. + getService(AM_Ci.nsIBlocklistService); + do_check_false(blocklist.isAddonBlocklisted(invalidAddon)); + do_check_false(blocklist.isAddonBlocklisted(ancientAddon)); + do_check_false(blocklist.isAddonBlocklisted(oldAddon)); + do_check_true(blocklist.isAddonBlocklisted(newAddon)); + + shutdownManager(); + + run_next_test(); +}); + +// A missing blocklist in the profile should still load an app-shipped blocklist +add_test(function test_missing() { + clearBlocklists(); + copyToApp(OLD); + copyToProfile(NEW, NEW_TSTAMP); + + incrementAppVersion(); + startupManager(); + shutdownManager(); + + let blocklist = FileUtils.getFile(KEY_PROFILEDIR, [FILE_BLOCKLIST]); + blocklist.remove(true); + startupManager(false); + + reloadBlocklist(); + blocklist = AM_Cc["@mozilla.org/extensions/blocklist;1"]. + getService(AM_Ci.nsIBlocklistService); + do_check_false(blocklist.isAddonBlocklisted(invalidAddon)); + do_check_false(blocklist.isAddonBlocklisted(ancientAddon)); + do_check_true(blocklist.isAddonBlocklisted(oldAddon)); + do_check_false(blocklist.isAddonBlocklisted(newAddon)); + + shutdownManager(); + + run_next_test(); +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_permissions.js b/toolkit/mozapps/extensions/test/xpcshell/test_permissions.js new file mode 100644 index 000000000..11463768f --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_permissions.js @@ -0,0 +1,86 @@ +/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+Components.utils.import("resource://gre/modules/NetUtil.jsm");
+
+// Checks that permissions set in preferences are correctly imported but can
+// be removed by the user.
+
+const XPI_MIMETYPE = "application/x-xpinstall";
+
+function newPrincipal(uri) {
+ return Services.scriptSecurityManager.getNoAppCodebasePrincipal(NetUtil.newURI(uri));
+}
+
+function run_test() {
+ createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2");
+
+ Services.prefs.setCharPref("xpinstall.whitelist.add", "test1.com,test2.com");
+ Services.prefs.setCharPref("xpinstall.whitelist.add.36", "test3.com,www.test4.com");
+ Services.prefs.setCharPref("xpinstall.whitelist.add.test5", "test5.com");
+
+ Services.perms.add(NetUtil.newURI("https://www.test9.com"), "install",
+ AM_Ci.nsIPermissionManager.ALLOW_ACTION);
+
+ startupManager();
+
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("http://test1.com")));
+ do_check_true(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://test1.com")));
+ do_check_true(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://www.test2.com")));
+ do_check_true(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://test3.com")));
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://test4.com")));
+ do_check_true(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://www.test4.com")));
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("http://www.test5.com")));
+ do_check_true(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://www.test5.com")));
+
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("http://www.test6.com")));
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://www.test6.com")));
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://test7.com")));
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://www.test8.com")));
+
+ // This should remain unaffected
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("http://www.test9.com")));
+ do_check_true(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://www.test9.com")));
+
+ Services.perms.removeAll();
+
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://test1.com")));
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://www.test2.com")));
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://test3.com")));
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://www.test4.com")));
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://www.test5.com")));
+
+ // Upgrade the application and verify that the permissions are still not there
+ restartManager("2");
+
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://test1.com")));
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://www.test2.com")));
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://test3.com")));
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://www.test4.com")));
+ do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+ newPrincipal("https://www.test5.com")));
+}
diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_permissions_prefs.js b/toolkit/mozapps/extensions/test/xpcshell/test_permissions_prefs.js new file mode 100644 index 000000000..ae1373214 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_permissions_prefs.js @@ -0,0 +1,74 @@ +/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Tests that xpinstall.[whitelist|blacklist].add preferences are emptied when
+// converted into permissions.
+
+const PREF_XPI_WHITELIST_PERMISSIONS = "xpinstall.whitelist.add";
+const PREF_XPI_BLACKLIST_PERMISSIONS = "xpinstall.blacklist.add";
+
+function newPrincipal(uri) {
+ return Services.scriptSecurityManager.getNoAppCodebasePrincipal(NetUtil.newURI(uri));
+}
+
+function do_check_permission_prefs(preferences) {
+ // Check preferences were emptied
+ for (let pref of preferences) {
+ try {
+ do_check_eq(Services.prefs.getCharPref(pref), "");
+ }
+ catch (e) {
+ // Successfully emptied
+ }
+ }
+}
+
+function clear_imported_preferences_cache() {
+ let scope = Components.utils.import("resource://gre/modules/PermissionsUtils.jsm", {});
+ scope.gImportedPrefBranches.clear();
+}
+
+function run_test() {
+ createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9");
+
+ // Create own preferences to test
+ Services.prefs.setCharPref("xpinstall.whitelist.add.EMPTY", "");
+ Services.prefs.setCharPref("xpinstall.whitelist.add.TEST", "whitelist.example.com");
+ Services.prefs.setCharPref("xpinstall.blacklist.add.EMPTY", "");
+ Services.prefs.setCharPref("xpinstall.blacklist.add.TEST", "blacklist.example.com");
+
+ // Get list of preferences to check
+ var whitelistPreferences = Services.prefs.getChildList(PREF_XPI_WHITELIST_PERMISSIONS, {});
+ var blacklistPreferences = Services.prefs.getChildList(PREF_XPI_BLACKLIST_PERMISSIONS, {});
+ var preferences = whitelistPreferences.concat(blacklistPreferences);
+
+ startupManager();
+
+ // Permissions are imported lazily - act as thought we're checking an install,
+ // to trigger on-deman importing of the permissions.
+ AddonManager.isInstallAllowed("application/x-xpinstall", newPrincipal("http://example.com/file.xpi"));
+ do_check_permission_prefs(preferences);
+
+
+ // Import can also be triggerred by an observer notification by any other area
+ // of code, such as a permissions management UI.
+
+ // First, request to flush all permissions
+ clear_imported_preferences_cache();
+ Services.prefs.setCharPref("xpinstall.whitelist.add.TEST2", "whitelist2.example.com");
+ Services.obs.notifyObservers(null, "flush-pending-permissions", "install");
+ do_check_permission_prefs(preferences);
+
+ // Then, request to flush just install permissions
+ clear_imported_preferences_cache();
+ Services.prefs.setCharPref("xpinstall.whitelist.add.TEST3", "whitelist3.example.com");
+ Services.obs.notifyObservers(null, "flush-pending-permissions", "");
+ do_check_permission_prefs(preferences);
+
+ // And a request to flush some other permissions sholdn't flush install permissions
+ clear_imported_preferences_cache();
+ Services.prefs.setCharPref("xpinstall.whitelist.add.TEST4", "whitelist4.example.com");
+ Services.obs.notifyObservers(null, "flush-pending-permissions", "lolcats");
+ do_check_eq(Services.prefs.getCharPref("xpinstall.whitelist.add.TEST4"), "whitelist4.example.com");
+}
diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_pluginBlocklistCtp.js b/toolkit/mozapps/extensions/test/xpcshell/test_pluginBlocklistCtp.js new file mode 100644 index 000000000..8d7e944e2 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_pluginBlocklistCtp.js @@ -0,0 +1,181 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const nsIBLS = Components.interfaces.nsIBlocklistService; +Components.utils.import("resource://testing-common/httpd.js"); + +var gBlocklistService = null; +var gNotifier = null; +var gNextTest = null; +var gPluginHost = null; + +var gServer = new HttpServer(); +gServer.start(-1); +gPort = gServer.identity.primaryPort; +mapFile("/data/test_pluginBlocklistCtp.xml", gServer); +mapFile("/data/test_pluginBlocklistCtpUndo.xml", gServer); + +var PLUGINS = [{ + // severity=0, vulnerabilitystatus=0 -> outdated + name: "test_plugin_0", + version: "5", + disabled: false, + blocklisted: false +}, +{ + // severity=0, vulnerabilitystatus=1 -> update available + name: "test_plugin_1", + version: "5", + disabled: false, + blocklisted: false +}, +{ + // severity=0, vulnerabilitystatus=2 -> no update + name: "test_plugin_2", + version: "5", + disabled: false, + blocklisted: false +}, +{ + // no severity field -> severity=3 by default -> hardblock + name: "test_plugin_3", + version: "5", + disabled: false, + blocklisted: false +}, +{ + // severity=1, vulnerabilitystatus=2 -> softblock + name: "test_plugin_4", + version: "5", + disabled: false, + blocklisted: false +}, +{ + // not in the blocklist -> not blocked + name: "test_plugin_5", + version: "5", + disabled: false, + blocklisted: false +}]; + +function test_basic() { + var blocklist = Components.classes["@mozilla.org/extensions/blocklist;1"].getService(nsIBLS); + + do_check_true(blocklist.getPluginBlocklistState(PLUGINS[0], "1", "1.9") == nsIBLS.STATE_OUTDATED); + + do_check_true(blocklist.getPluginBlocklistState(PLUGINS[1], "1", "1.9") == nsIBLS.STATE_VULNERABLE_UPDATE_AVAILABLE); + + do_check_true(blocklist.getPluginBlocklistState(PLUGINS[2], "1", "1.9") == nsIBLS.STATE_VULNERABLE_NO_UPDATE); + + do_check_true(blocklist.getPluginBlocklistState(PLUGINS[3], "1", "1.9") == nsIBLS.STATE_BLOCKED); + + do_check_true(blocklist.getPluginBlocklistState(PLUGINS[4], "1", "1.9") == nsIBLS.STATE_SOFTBLOCKED); + + do_check_true(blocklist.getPluginBlocklistState(PLUGINS[5], "1", "1.9") == nsIBLS.STATE_NOT_BLOCKED); + + gNextTest = test_is_not_clicktoplay; + do_execute_soon(gNextTest); +} + +function get_test_plugin() { + var pluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost); + for (var plugin of pluginHost.getPluginTags()) { + if (plugin.name == "Test Plug-in") + return plugin; + } + do_check_true(false); + return null; +} + +// At this time, the blocklist does not have an entry for the test plugin, +// so it shouldn't be click-to-play. +function test_is_not_clicktoplay() { + var plugin = get_test_plugin(); + var blocklistState = gBlocklistService.getPluginBlocklistState(plugin, "1", "1.9"); + do_check_neq(blocklistState, Components.interfaces.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE); + do_check_neq(blocklistState, Components.interfaces.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE); + + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + gPort + "/data/test_pluginBlocklistCtpUndo.xml"); + gNextTest = test_is_clicktoplay; + gNotifier.notify(null); +} + +// Here, we've updated the blocklist to have a block for the test plugin, +// so it should be click-to-play. +function test_is_clicktoplay() { + var plugin = get_test_plugin(); + var blocklistState = gBlocklistService.getPluginBlocklistState(plugin, "1", "1.9"); + do_check_eq(blocklistState, Components.interfaces.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE); + + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + gPort + "/data/test_pluginBlocklistCtp.xml"); + gNextTest = test_is_not_clicktoplay2; + gNotifier.notify(null); +} + +// But now we've removed that entry from the blocklist (really we've gone back +// to the old one), so the plugin shouldn't be click-to-play any more. +function test_is_not_clicktoplay2() { + var plugin = get_test_plugin(); + var blocklistState = gBlocklistService.getPluginBlocklistState(plugin, "1", "1.9"); + do_check_neq(blocklistState, Components.interfaces.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE); + do_check_neq(blocklistState, Components.interfaces.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE); + + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + gPort + "/data/test_pluginBlocklistCtpUndo.xml"); + gNextTest = test_disable_blocklist; + gNotifier.notify(null); +} + +// Test that disabling the blocklist when a plugin is ctp-blocklisted will +// result in the plugin not being click-to-play. +function test_disable_blocklist() { + var plugin = get_test_plugin(); + var blocklistState = gBlocklistService.getPluginBlocklistState(plugin, "1", "1.9"); + do_check_eq(blocklistState, Components.interfaces.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE); + + gNextTest = null; + Services.prefs.setBoolPref("extensions.blocklist.enabled", false); + blocklistState = gBlocklistService.getPluginBlocklistState(plugin, "1", "1.9"); + do_check_neq(blocklistState, Components.interfaces.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE); + do_check_neq(blocklistState, Components.interfaces.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE); + + // it should still be possible to make a plugin click-to-play via the pref + // and setting that plugin's enabled state to click-to-play + Services.prefs.setBoolPref("plugins.click_to_play", true); + let previousEnabledState = plugin.enabledState; + plugin.enabledState = Components.interfaces.nsIPluginTag.STATE_CLICKTOPLAY; + do_check_eq(gPluginHost.getStateForType("application/x-test"), Components.interfaces.nsIPluginTag.STATE_CLICKTOPLAY); + // clean up plugin state + plugin.enabledState = previousEnabledState; + + gServer.stop(do_test_finished); +} + +// Observe "blocklist-updated" so we know when to advance to the next test +function observer() { + if (gNextTest) + do_execute_soon(gNextTest); +} + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); + + Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" + gPort + "/data/test_pluginBlocklistCtp.xml"); + startupManager(); + + gPluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost); + gBlocklistService = Components.classes["@mozilla.org/extensions/blocklist;1"].getService(Components.interfaces.nsIBlocklistService); + gNotifier = Components.classes["@mozilla.org/extensions/blocklist;1"].getService(Components.interfaces.nsITimerCallback); + Services.obs.addObserver(observer, "blocklist-updated", false); + + do_register_cleanup(function() { + Services.prefs.clearUserPref("extensions.blocklist.url"); + Services.prefs.clearUserPref("extensions.blocklist.enabled"); + Services.prefs.clearUserPref("plugins.click_to_play"); + Services.obs.removeObserver(observer, "blocklist-updated"); + }); + + gNextTest = test_basic; + do_test_pending(); + gNotifier.notify(null); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_pluginInfoURL.js b/toolkit/mozapps/extensions/test/xpcshell/test_pluginInfoURL.js new file mode 100644 index 000000000..e140f021a --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_pluginInfoURL.js @@ -0,0 +1,80 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +const Ci = Components.interfaces; +Components.utils.import("resource://gre/modules/Services.jsm"); + +/** + * MockPlugin mimics the behaviour of a plugin. + */ +function MockPlugin(name, version, enabledState) { + this.name = name; + this.version = version; + this.enabledState = enabledState; +} + +MockPlugin.prototype = { + get blocklisted() { + let bls = Services.blocklist; + return bls.getPluginBlocklistState(this) == bls.STATE_BLOCKED; + }, + + get disabled() { + return this.enabledState == Ci.nsIPluginTag.STATE_DISABLED; + } +}; + +// The mocked blocked plugin used to test the blocklist. +const PLUGINS = [ + new MockPlugin('test_with_infoURL', '5', Ci.nsIPluginTag.STATE_ENABLED), + new MockPlugin('test_with_altInfoURL', '5', Ci.nsIPluginTag.STATE_ENABLED), + new MockPlugin('test_no_infoURL', '5', Ci.nsIPluginTag.STATE_ENABLED) +]; + +/** + * The entry point of the unit tests, which is also responsible of + * copying the blocklist file to the profile folder. + */ +function run_test() { + copyBlocklistToProfile(do_get_file('data/pluginInfoURL_block.xml')); + + createAppInfo('xpcshell@tests.mozilla.org', 'XPCShell', '3', '8'); + startupManager(); + + run_next_test(); +} + +/** + * Test that the blocklist service correctly loads and returns the infoURL for + * a plugin that matches the first entry in the blocklist. + */ +add_task(function* test_infoURL() { + // The testInfoURL must match the value within the + // <infoURL> tag in pluginInfoURL_block.xml. + let testInfoURL = 'http://test.url.com/'; + + Assert.strictEqual(Services.blocklist.getPluginInfoURL(PLUGINS[0]), + testInfoURL, 'Should be the provided url when an infoURL tag is available'); +}); + +/** + * Test that the blocklist service correctly loads and returns the infoURL for + * a plugin that partially matches an earlier entry in the blocklist. + */ +add_task(function* test_altInfoURL() { + let altTestInfoURL = 'http://alt.test.url.com/'; + + Assert.strictEqual(Services.blocklist.getPluginInfoURL(PLUGINS[1]), + altTestInfoURL, 'Should be the alternative infoURL'); +}); + +/** + * Test that the blocklist service correctly returns null + * if the infoURL tag is missing in the blocklist.xml file. + */ +add_task(function* test_infoURL_missing() { + Assert.strictEqual(Services.blocklist.getPluginInfoURL(PLUGINS[2]), null, + 'Should be null when no infoURL tag is available.'); +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_pluginchange.js b/toolkit/mozapps/extensions/test/xpcshell/test_pluginchange.js new file mode 100644 index 000000000..d3e33dac3 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_pluginchange.js @@ -0,0 +1,292 @@ +/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+const LIST_UPDATED_TOPIC = "plugins-list-updated";
+
+// We need to use the same algorithm for generating IDs for plugins
+var { getIDHashForString } = Components.utils.import("resource://gre/modules/addons/PluginProvider.jsm");
+
+function PluginTag(name, description) {
+ this.name = name;
+ this.description = description;
+}
+
+PluginTag.prototype = {
+ name: null,
+ description: null,
+ version: "1.0",
+ filename: null,
+ fullpath: null,
+ disabled: false,
+ blocklisted: false,
+ clicktoplay: false,
+
+ mimeTypes: [],
+
+ getMimeTypes: function(count) {
+ count.value = this.mimeTypes.length;
+ return this.mimeTypes;
+ }
+};
+
+PLUGINS = [
+ // A standalone plugin
+ new PluginTag("Java", "A mock Java plugin"),
+
+ // A plugin made up of two plugin files
+ new PluginTag("Flash", "A mock Flash plugin"),
+ new PluginTag("Flash", "A mock Flash plugin")
+];
+
+gPluginHost = {
+ // nsIPluginHost
+ getPluginTags: function(count) {
+ count.value = PLUGINS.length;
+ return PLUGINS;
+ },
+
+ QueryInterface: XPCOMUtils.generateQI([AM_Ci.nsIPluginHost])
+};
+
+var PluginHostFactory = {
+ createInstance: function (outer, iid) {
+ if (outer != null)
+ throw Components.results.NS_ERROR_NO_AGGREGATION;
+ return gPluginHost.QueryInterface(iid);
+ }
+};
+
+var registrar = Components.manager.QueryInterface(AM_Ci.nsIComponentRegistrar);
+registrar.registerFactory(Components.ID("{aa6f9fef-cbe2-4d55-a2fa-dcf5482068b9}"), "PluginHost",
+ "@mozilla.org/plugin/host;1", PluginHostFactory);
+
+// This verifies that when the list of plugins changes the add-ons manager
+// correctly updates
+function run_test() {
+ do_test_pending();
+ createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
+
+ Services.prefs.setBoolPref("media.gmp-provider.enabled", false);
+
+ startupManager();
+ AddonManager.addAddonListener(AddonListener);
+ AddonManager.addInstallListener(InstallListener);
+
+ run_test_1();
+}
+
+function end_test() {
+ do_execute_soon(do_test_finished);
+}
+
+function sortAddons(addons) {
+ addons.sort(function(a, b) {
+ return a.name.localeCompare(b.name);
+ });
+}
+
+// Basic check that the mock object works
+function run_test_1() {
+ AddonManager.getAddonsByTypes(["plugin"], function(addons) {
+ sortAddons(addons);
+
+ do_check_eq(addons.length, 2);
+
+ do_check_eq(addons[0].name, "Flash");
+ do_check_false(addons[0].userDisabled);
+ do_check_eq(addons[1].name, "Java");
+ do_check_false(addons[1].userDisabled);
+
+ run_test_2();
+ });
+}
+
+// No change to the list should not trigger any events or changes in the API
+function run_test_2() {
+ // Reorder the list a bit
+ let tag = PLUGINS[0];
+ PLUGINS[0] = PLUGINS[2];
+ PLUGINS[2] = PLUGINS[1];
+ PLUGINS[1] = tag;
+
+ Services.obs.notifyObservers(null, LIST_UPDATED_TOPIC, null);
+
+ AddonManager.getAddonsByTypes(["plugin"], function(addons) {
+ sortAddons(addons);
+
+ do_check_eq(addons.length, 2);
+
+ do_check_eq(addons[0].name, "Flash");
+ do_check_false(addons[0].userDisabled);
+ do_check_eq(addons[1].name, "Java");
+ do_check_false(addons[1].userDisabled);
+
+ run_test_3();
+ });
+}
+
+// Tests that a newly detected plugin shows up in the API and sends out events
+function run_test_3() {
+ let tag = new PluginTag("Quicktime", "A mock Quicktime plugin");
+ PLUGINS.push(tag);
+ let id = getIDHashForString(tag.name + tag.description);
+
+ let test_params = {};
+ test_params[id] = [
+ ["onInstalling", false],
+ "onInstalled"
+ ];
+
+ prepare_test(test_params, [
+ "onExternalInstall"
+ ]);
+
+ Services.obs.notifyObservers(null, LIST_UPDATED_TOPIC, null);
+
+ ensure_test_completed();
+
+ AddonManager.getAddonsByTypes(["plugin"], function(addons) {
+ sortAddons(addons);
+
+ do_check_eq(addons.length, 3);
+
+ do_check_eq(addons[0].name, "Flash");
+ do_check_false(addons[0].userDisabled);
+ do_check_eq(addons[1].name, "Java");
+ do_check_false(addons[1].userDisabled);
+ do_check_eq(addons[2].name, "Quicktime");
+ do_check_false(addons[2].userDisabled);
+
+ run_test_4();
+ });
+}
+
+// Tests that a removed plugin disappears from in the API and sends out events
+function run_test_4() {
+ let tag = PLUGINS.splice(1, 1)[0];
+ let id = getIDHashForString(tag.name + tag.description);
+
+ let test_params = {};
+ test_params[id] = [
+ ["onUninstalling", false],
+ "onUninstalled"
+ ];
+
+ prepare_test(test_params);
+
+ Services.obs.notifyObservers(null, LIST_UPDATED_TOPIC, null);
+
+ ensure_test_completed();
+
+ AddonManager.getAddonsByTypes(["plugin"], function(addons) {
+ sortAddons(addons);
+
+ do_check_eq(addons.length, 2);
+
+ do_check_eq(addons[0].name, "Flash");
+ do_check_false(addons[0].userDisabled);
+ do_check_eq(addons[1].name, "Quicktime");
+ do_check_false(addons[1].userDisabled);
+
+ run_test_5();
+ });
+}
+
+// Removing part of the flash plugin should have no effect
+function run_test_5() {
+ PLUGINS.splice(0, 1);
+
+ Services.obs.notifyObservers(null, LIST_UPDATED_TOPIC, null);
+
+ ensure_test_completed();
+
+ AddonManager.getAddonsByTypes(["plugin"], function(addons) {
+ sortAddons(addons);
+
+ do_check_eq(addons.length, 2);
+
+ do_check_eq(addons[0].name, "Flash");
+ do_check_false(addons[0].userDisabled);
+ do_check_eq(addons[1].name, "Quicktime");
+ do_check_false(addons[1].userDisabled);
+
+ run_test_6();
+ });
+}
+
+// Replacing flash should be detected
+function run_test_6() {
+ let oldTag = PLUGINS.splice(0, 1)[0];
+ let newTag = new PluginTag("Flash 2", "A new crash-free Flash!");
+ newTag.disabled = true;
+ PLUGINS.push(newTag);
+
+ let test_params = {};
+ test_params[getIDHashForString(oldTag.name + oldTag.description)] = [
+ ["onUninstalling", false],
+ "onUninstalled"
+ ];
+ test_params[getIDHashForString(newTag.name + newTag.description)] = [
+ ["onInstalling", false],
+ "onInstalled"
+ ];
+
+ prepare_test(test_params, [
+ "onExternalInstall"
+ ]);
+
+ Services.obs.notifyObservers(null, LIST_UPDATED_TOPIC, null);
+
+ ensure_test_completed();
+
+ AddonManager.getAddonsByTypes(["plugin"], function(addons) {
+ sortAddons(addons);
+
+ do_check_eq(addons.length, 2);
+
+ do_check_eq(addons[0].name, "Flash 2");
+ do_check_true(addons[0].userDisabled);
+ do_check_eq(addons[1].name, "Quicktime");
+ do_check_false(addons[1].userDisabled);
+
+ run_test_7();
+ });
+}
+
+// If new tags are detected and the disabled state changes then we should send
+// out appropriate notifications
+function run_test_7() {
+ PLUGINS[0] = new PluginTag("Quicktime", "A mock Quicktime plugin");
+ PLUGINS[0].disabled = true;
+ PLUGINS[1] = new PluginTag("Flash 2", "A new crash-free Flash!");
+
+ let test_params = {};
+ test_params[getIDHashForString(PLUGINS[0].name + PLUGINS[0].description)] = [
+ ["onDisabling", false],
+ "onDisabled"
+ ];
+ test_params[getIDHashForString(PLUGINS[1].name + PLUGINS[1].description)] = [
+ ["onEnabling", false],
+ "onEnabled"
+ ];
+
+ prepare_test(test_params);
+
+ Services.obs.notifyObservers(null, LIST_UPDATED_TOPIC, null);
+
+ ensure_test_completed();
+
+ AddonManager.getAddonsByTypes(["plugin"], function(addons) {
+ sortAddons(addons);
+
+ do_check_eq(addons.length, 2);
+
+ do_check_eq(addons[0].name, "Flash 2");
+ do_check_false(addons[0].userDisabled);
+ do_check_eq(addons[1].name, "Quicktime");
+ do_check_true(addons[1].userDisabled);
+
+ end_test();
+ });
+}
diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_plugins.js b/toolkit/mozapps/extensions/test/xpcshell/test_plugins.js new file mode 100644 index 000000000..5541bc946 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_plugins.js @@ -0,0 +1,210 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that plugins exist and can be enabled and disabled. +var gID = null; + +function setTestPluginState(state) { + let tags = AM_Cc["@mozilla.org/plugin/host;1"].getService(AM_Ci.nsIPluginHost) + .getPluginTags(); + for (let tag of tags) { + if (tag.name == "Test Plug-in") { + tag.enabledState = state; + return; + } + } + throw Error("No plugin tag found for the test plugin"); +} + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + Services.prefs.setBoolPref("plugins.click_to_play", true); + + setTestPluginState(AM_Ci.nsIPluginTag.STATE_CLICKTOPLAY); + + startupManager(); + AddonManager.addAddonListener(AddonListener); + AddonManager.addInstallListener(InstallListener); + + run_test_1(); +} + +// Finds the test plugin library +function get_test_plugin() { + var pluginEnum = Services.dirsvc.get("APluginsDL", AM_Ci.nsISimpleEnumerator); + while (pluginEnum.hasMoreElements()) { + let dir = pluginEnum.getNext().QueryInterface(AM_Ci.nsILocalFile); + let plugin = dir.clone(); + // OSX plugin + plugin.append("Test.plugin"); + if (plugin.exists()) { + plugin.normalize(); + return plugin; + } + plugin = dir.clone(); + // *nix plugin + plugin.append("libnptest.so"); + if (plugin.exists()) { + plugin.normalize(); + return plugin; + } + // Windows plugin + plugin = dir.clone(); + plugin.append("nptest.dll"); + if (plugin.exists()) { + plugin.normalize(); + return plugin; + } + } + return null; +} + +function getFileSize(aFile) { + if (!aFile.isDirectory()) + return aFile.fileSize; + + let size = 0; + let entries = aFile.directoryEntries.QueryInterface(AM_Ci.nsIDirectoryEnumerator); + let entry; + while (entry = entries.nextFile) + size += getFileSize(entry); + entries.close(); + return size; +} + +function getPluginLastModifiedTime(aPluginFile) { + // On OS X we use the bundle contents last modified time as using + // the package directories modified date may be outdated. + // See bug 313700. + try { + let localFileMac = aPluginFile.QueryInterface(AM_Ci.nsILocalFileMac); + if (localFileMac) { + return localFileMac.bundleContentsLastModifiedTime; + } + } catch (e) { + } + + return aPluginFile.lastModifiedTime; +} + +// Tests that the test plugin exists +function run_test_1() { + var testPlugin = get_test_plugin(); + do_check_neq(testPlugin, null); + + AddonManager.getAddonsByTypes(["plugin"], function(addons) { + do_check_true(addons.length > 0); + + addons.forEach(function(p) { + if (p.name == "Test Plug-in") + gID = p.id; + }); + + do_check_neq(gID, null); + + AddonManager.getAddonByID(gID, function(p) { + do_check_neq(p, null); + do_check_eq(p.name, "Test Plug-in"); + do_check_eq(p.description, + "Plug-in for testing purposes.\u2122 " + + "(\u0939\u093f\u0928\u094d\u0926\u0940 " + + "\u4e2d\u6587 " + + "\u0627\u0644\u0639\u0631\u0628\u064a\u0629)"); + do_check_eq(p.creator, null); + do_check_eq(p.version, "1.0.0.0"); + do_check_eq(p.type, "plugin"); + do_check_eq(p.userDisabled, "askToActivate"); + do_check_false(p.appDisabled); + do_check_true(p.isActive); + do_check_true(p.isCompatible); + do_check_true(p.providesUpdatesSecurely); + do_check_eq(p.blocklistState, 0); + do_check_eq(p.permissions, AddonManager.PERM_CAN_DISABLE | AddonManager.PERM_CAN_ENABLE); + do_check_eq(p.pendingOperations, 0); + do_check_true(p.size > 0); + do_check_eq(p.size, getFileSize(testPlugin)); + do_check_true(p.updateDate > 0); + do_check_true("isCompatibleWith" in p); + do_check_true("findUpdates" in p); + + let lastModifiedTime = getPluginLastModifiedTime(testPlugin); + do_check_eq(p.updateDate.getTime(), lastModifiedTime); + do_check_eq(p.installDate.getTime(), lastModifiedTime); + + run_test_2(p); + }); + }); +} + +// Tests that disabling a plugin works +function run_test_2(p) { + let test = {}; + test[gID] = [ + ["onDisabling", false], + "onDisabled", + ["onPropertyChanged", ["userDisabled"]] + ]; + prepare_test(test); + + p.userDisabled = true; + + ensure_test_completed(); + + do_check_true(p.userDisabled); + do_check_false(p.appDisabled); + do_check_false(p.isActive); + + AddonManager.getAddonByID(gID, function(p) { + do_check_neq(p, null); + do_check_true(p.userDisabled); + do_check_false(p.appDisabled); + do_check_false(p.isActive); + do_check_eq(p.name, "Test Plug-in"); + + run_test_3(p); + }); +} + +// Tests that enabling a plugin works +function run_test_3(p) { + let test = {}; + test[gID] = [ + ["onEnabling", false], + "onEnabled" + ]; + prepare_test(test); + + p.userDisabled = false; + + ensure_test_completed(); + + do_check_false(p.userDisabled); + do_check_false(p.appDisabled); + do_check_true(p.isActive); + + AddonManager.getAddonByID(gID, function(p) { + do_check_neq(p, null); + do_check_false(p.userDisabled); + do_check_false(p.appDisabled); + do_check_true(p.isActive); + do_check_eq(p.name, "Test Plug-in"); + + do_execute_soon(run_test_4); + }); +} + +// Verify that after a restart the test plugin has the same ID +function run_test_4() { + restartManager(); + + AddonManager.getAddonByID(gID, function(p) { + do_check_neq(p, null); + do_check_eq(p.name, "Test Plug-in"); + + Services.prefs.clearUserPref("plugins.click_to_play"); + + do_execute_soon(do_test_finished); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_pref_properties.js b/toolkit/mozapps/extensions/test/xpcshell/test_pref_properties.js new file mode 100644 index 000000000..9abffaab0 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_pref_properties.js @@ -0,0 +1,206 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Tests the preference-related properties of AddonManager +// eg: AddonManager.checkCompatibility, AddonManager.updateEnabled, etc + +var gManagerEventsListener = { + seenEvents: [], + init: function() { + let events = ["onCompatibilityModeChanged", "onCheckUpdateSecurityChanged", + "onUpdateModeChanged"]; + events.forEach(function(aEvent) { + this[aEvent] = function() { + do_print("Saw event " + aEvent); + this.seenEvents.push(aEvent); + } + }, this); + AddonManager.addManagerListener(this); + // Try to add twice, to test that the second time silently fails. + AddonManager.addManagerListener(this); + }, + shutdown: function() { + AddonManager.removeManagerListener(this); + }, + expect: function(aEvents) { + this.expectedEvents = aEvents; + }, + checkExpected: function() { + do_print("Checking expected events..."); + while (this.expectedEvents.length > 0) { + let event = this.expectedEvents.pop(); + do_print("Looking for expected event " + event); + let matchingEvents = this.seenEvents.filter(function(aSeenEvent) { + return aSeenEvent == event; + }); + do_check_eq(matchingEvents.length, 1); + } + this.seenEvents = []; + } +} + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + Services.prefs.setBoolPref("extensions.update.enabled", true); + Services.prefs.setBoolPref("extensions.update.autoUpdateDefault", true); + Services.prefs.setBoolPref("extensions.strictCompatibility", true); + Services.prefs.setBoolPref("extensions.checkUpdatesecurity", true); + + startupManager(); + gManagerEventsListener.init(); + + + // AddonManager.updateEnabled + gManagerEventsListener.expect(["onUpdateModeChanged"]); + AddonManager.updateEnabled = false; + gManagerEventsListener.checkExpected(); + do_check_false(AddonManager.updateEnabled); + do_check_false(Services.prefs.getBoolPref("extensions.update.enabled")); + + gManagerEventsListener.expect([]); + AddonManager.updateEnabled = false; + gManagerEventsListener.checkExpected(); + do_check_false(AddonManager.updateEnabled); + do_check_false(Services.prefs.getBoolPref("extensions.update.enabled")); + + gManagerEventsListener.expect(["onUpdateModeChanged"]); + AddonManager.updateEnabled = true; + gManagerEventsListener.checkExpected(); + do_check_true(AddonManager.updateEnabled); + do_check_true(Services.prefs.getBoolPref("extensions.update.enabled")); + + gManagerEventsListener.expect([]); + AddonManager.updateEnabled = true; + gManagerEventsListener.checkExpected(); + do_check_true(AddonManager.updateEnabled); + do_check_true(Services.prefs.getBoolPref("extensions.update.enabled")); + + // AddonManager.autoUpdateDefault + gManagerEventsListener.expect(["onUpdateModeChanged"]); + AddonManager.autoUpdateDefault = false; + gManagerEventsListener.checkExpected(); + do_check_false(AddonManager.autoUpdateDefault); + do_check_false(Services.prefs.getBoolPref("extensions.update.autoUpdateDefault")); + + gManagerEventsListener.expect([]); + AddonManager.autoUpdateDefault = false; + gManagerEventsListener.checkExpected(); + do_check_false(AddonManager.autoUpdateDefault); + do_check_false(Services.prefs.getBoolPref("extensions.update.autoUpdateDefault")); + + gManagerEventsListener.expect(["onUpdateModeChanged"]); + AddonManager.autoUpdateDefault = true; + gManagerEventsListener.checkExpected(); + do_check_true(AddonManager.autoUpdateDefault); + do_check_true(Services.prefs.getBoolPref("extensions.update.autoUpdateDefault")); + + gManagerEventsListener.expect([]); + AddonManager.autoUpdateDefault = true; + gManagerEventsListener.checkExpected(); + do_check_true(AddonManager.autoUpdateDefault); + do_check_true(Services.prefs.getBoolPref("extensions.update.autoUpdateDefault")); + + // AddonManager.strictCompatibility + gManagerEventsListener.expect(["onCompatibilityModeChanged"]); + AddonManager.strictCompatibility = false; + gManagerEventsListener.checkExpected(); + do_check_false(AddonManager.strictCompatibility); + do_check_false(Services.prefs.getBoolPref("extensions.strictCompatibility")); + + gManagerEventsListener.expect([]); + AddonManager.strictCompatibility = false; + gManagerEventsListener.checkExpected(); + do_check_false(AddonManager.strictCompatibility); + do_check_false(Services.prefs.getBoolPref("extensions.strictCompatibility")); + + gManagerEventsListener.expect(["onCompatibilityModeChanged"]); + AddonManager.strictCompatibility = true; + gManagerEventsListener.checkExpected(); + do_check_true(AddonManager.strictCompatibility); + do_check_true(Services.prefs.getBoolPref("extensions.strictCompatibility")); + + gManagerEventsListener.expect([]); + AddonManager.strictCompatibility = true; + gManagerEventsListener.checkExpected(); + do_check_true(AddonManager.strictCompatibility); + do_check_true(Services.prefs.getBoolPref("extensions.strictCompatibility")); + + + // AddonManager.checkCompatibility + if (isNightlyChannel()) { + var version = "nightly"; + } else { + version = Services.appinfo.version.replace(/^([^\.]+\.[0-9]+[a-z]*).*/gi, "$1"); + } + const COMPATIBILITY_PREF = "extensions.checkCompatibility." + version; + + gManagerEventsListener.expect(["onCompatibilityModeChanged"]); + AddonManager.checkCompatibility = false; + gManagerEventsListener.checkExpected(); + do_check_false(AddonManager.checkCompatibility); + do_check_false(Services.prefs.getBoolPref(COMPATIBILITY_PREF)); + + gManagerEventsListener.expect([]); + AddonManager.checkCompatibility = false; + gManagerEventsListener.checkExpected(); + do_check_false(AddonManager.checkCompatibility); + do_check_false(Services.prefs.getBoolPref(COMPATIBILITY_PREF)); + + gManagerEventsListener.expect(["onCompatibilityModeChanged"]); + AddonManager.checkCompatibility = true; + gManagerEventsListener.checkExpected(); + do_check_true(AddonManager.checkCompatibility); + do_check_false(Services.prefs.prefHasUserValue(COMPATIBILITY_PREF)); + + gManagerEventsListener.expect([]); + AddonManager.checkCompatibility = true; + gManagerEventsListener.checkExpected(); + do_check_true(AddonManager.checkCompatibility); + do_check_false(Services.prefs.prefHasUserValue(COMPATIBILITY_PREF)); + + + // AddonManager.checkUpdateSecurity + gManagerEventsListener.expect(["onCheckUpdateSecurityChanged"]); + AddonManager.checkUpdateSecurity = false; + gManagerEventsListener.checkExpected(); + do_check_false(AddonManager.checkUpdateSecurity); + if (AddonManager.checkUpdateSecurityDefault) + do_check_false(Services.prefs.getBoolPref("extensions.checkUpdateSecurity")); + else + do_check_false(Services.prefs.prefHasUserValue("extensions.checkUpdateSecurity")); + + gManagerEventsListener.expect([]); + AddonManager.checkUpdateSecurity = false; + gManagerEventsListener.checkExpected(); + do_check_false(AddonManager.checkUpdateSecurity); + if (AddonManager.checkUpdateSecurityDefault) + do_check_false(Services.prefs.getBoolPref("extensions.checkUpdateSecurity")); + else + do_check_false(Services.prefs.prefHasUserValue("extensions.checkUpdateSecurity")); + + gManagerEventsListener.expect(["onCheckUpdateSecurityChanged"]); + AddonManager.checkUpdateSecurity = true; + gManagerEventsListener.checkExpected(); + do_check_true(AddonManager.checkUpdateSecurity); + if (!AddonManager.checkUpdateSecurityDefault) + do_check_true(Services.prefs.getBoolPref("extensions.checkUpdateSecurity")); + else + do_check_false(Services.prefs.prefHasUserValue("extensions.checkUpdateSecurity")); + + gManagerEventsListener.expect([]); + AddonManager.checkUpdateSecurity = true; + gManagerEventsListener.checkExpected(); + do_check_true(AddonManager.checkUpdateSecurity); + if (!AddonManager.checkUpdateSecurityDefault) + do_check_true(Services.prefs.getBoolPref("extensions.checkUpdateSecurity")); + else + do_check_false(Services.prefs.prefHasUserValue("extensions.checkUpdateSecurity")); + + gManagerEventsListener.shutdown(); + + // After removing the listener, ensure we get no further events. + gManagerEventsListener.expect([]); + AddonManager.updateEnabled = false; + gManagerEventsListener.checkExpected(); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_provider_markSafe.js b/toolkit/mozapps/extensions/test/xpcshell/test_provider_markSafe.js new file mode 100644 index 000000000..55d503f2c --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_provider_markSafe.js @@ -0,0 +1,47 @@ +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + +let startupOrder = []; + +function mockAddonProvider(name) { + let mockProvider = { + markSafe: false, + apiAccessed: false, + + startup() { + if (this.markSafe) + AddonManagerPrivate.markProviderSafe(this); + + let uri = Services.io.newURI("beard://long", null, null); + AddonManager.isInstallEnabled("made-up-mimetype"); + }, + supportsMimetype(mimetype) { + this.apiAccessed = true; + return false; + }, + + get name() name, + }; + + return mockProvider; +}; + +function run_test() { + run_next_test(); +} + +add_task(function* testMarkSafe() { + do_print("Starting with provider normally"); + let provider = mockAddonProvider("Mock1"); + AddonManagerPrivate.registerProvider(provider); + startupManager(); + ok(!provider.apiAccessed, "Provider API should not have been accessed"); + AddonManagerPrivate.unregisterProvider(provider); + yield promiseShutdownManager(); + + do_print("Starting with provider that marks itself safe"); + provider.apiAccessed = false; + provider.markSafe = true; + AddonManagerPrivate.registerProvider(provider); + startupManager(); + ok(provider.apiAccessed, "Provider API should have been accessed"); +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_provider_shutdown.js b/toolkit/mozapps/extensions/test/xpcshell/test_provider_shutdown.js new file mode 100644 index 000000000..f6de26241 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_provider_shutdown.js @@ -0,0 +1,97 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Verify that we report shutdown status for Addon Manager providers +// and AddonRepository correctly. + +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + +// Make a mock AddonRepository that just lets us hang shutdown. +// Needs two promises - one to let us know that AM has called shutdown, +// and one for us to let AM know that shutdown is done. +function mockAddonProvider(aName) { + let mockProvider = { + donePromise: null, + doneResolve: null, + doneReject: null, + shutdownPromise: null, + shutdownResolve: null, + + get name() aName, + + shutdown() { + this.shutdownResolve(); + return this.donePromise; + }, + }; + mockProvider.donePromise = new Promise((resolve, reject) => { + mockProvider.doneResolve = resolve; + mockProvider.doneReject = reject; + }); + mockProvider.shutdownPromise = new Promise((resolve, reject) => { + mockProvider.shutdownResolve = resolve; + }); + return mockProvider; +}; + +function run_test() { + run_next_test(); +} + +// Helper to find a particular shutdown blocker's status in the JSON blob +function findInStatus(aStatus, aName) { + for (let {name, state} of aStatus.state) { + if (name == aName) { + return state; + } + } + return null; +} + +/* + * Make sure we report correctly when an add-on provider or AddonRepository block shutdown + */ +add_task(function* blockRepoShutdown() { + // Reach into the AddonManager scope and inject our mock AddonRepository + let realAddonRepo = AMscope.AddonRepository; + // the mock provider behaves enough like AddonRepository for the purpose of this test + let mockRepo = mockAddonProvider("Mock repo"); + AMscope.AddonRepository = mockRepo; + + let mockProvider = mockAddonProvider("Mock provider"); + + startupManager(); + AddonManagerPrivate.registerProvider(mockProvider); + + // Start shutting the manager down + let managerDown = promiseShutdownManager(); + + // Wait for manager to call provider shutdown. + yield mockProvider.shutdownPromise; + // check AsyncShutdown state + let status = MockAsyncShutdown.status(); + equal(findInStatus(status[0], "Mock provider"), "(none)"); + equal(status[1].name, "AddonRepository: async shutdown"); + equal(status[1].state, "pending"); + // let the provider finish + mockProvider.doneResolve(); + + // Wait for manager to call repo shutdown and start waiting for it + yield mockRepo.shutdownPromise; + // Check the shutdown state + status = MockAsyncShutdown.status(); + equal(status[0].name, "AddonManager: Waiting for providers to shut down."); + equal(status[0].state, "Complete"); + equal(status[1].name, "AddonRepository: async shutdown"); + equal(status[1].state, "in progress"); + + // Now finish our shutdown, and wait for the manager to wrap up + mockRepo.doneResolve(); + yield managerDown; + + // Check the shutdown state again + status = MockAsyncShutdown.status(); + equal(status[0].name, "AddonRepository: async shutdown"); + equal(status[0].state, "done"); +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_provider_unsafe_access_shutdown.js b/toolkit/mozapps/extensions/test/xpcshell/test_provider_unsafe_access_shutdown.js new file mode 100644 index 000000000..df717f5a5 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_provider_unsafe_access_shutdown.js @@ -0,0 +1,61 @@ +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + +let shutdownOrder = []; + +function mockAddonProvider(name) { + let mockProvider = { + hasShutdown: false, + unsafeAccess: false, + + shutdownCallback: null, + + startup() { }, + shutdown() { + this.hasShutdown = true; + shutdownOrder.push(this.name); + if (this.shutdownCallback) + return this.shutdownCallback(); + }, + getAddonByID(id, callback) { + if (this.hasShutdown) { + unsafeAccess = true; + } + callback(null); + }, + + get name() name, + }; + + return mockProvider; +}; + +function run_test() { + run_next_test(); +} + +add_task(function* unsafeProviderShutdown() { + let firstProvider = mockAddonProvider("Mock1"); + AddonManagerPrivate.registerProvider(firstProvider); + let secondProvider = mockAddonProvider("Mock2"); + AddonManagerPrivate.registerProvider(secondProvider); + + startupManager(); + + let shutdownPromise = null; + yield new Promise(resolve => { + secondProvider.shutdownCallback = function() { + return new Promise(shutdownResolve => { + AddonManager.getAddonByID("does-not-exist", () => { + shutdownResolve(); + resolve(); + }); + }); + }; + + shutdownPromise = promiseShutdownManager(); + }); + yield shutdownPromise; + + equal(shutdownOrder.join(","), ["Mock1", "Mock2"].join(","), "Mock providers should have shutdown in expected order"); + ok(!firstProvider.unsafeAccess, "First registered mock provider should not have been accessed unsafely"); +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_provider_unsafe_access_startup.js b/toolkit/mozapps/extensions/test/xpcshell/test_provider_unsafe_access_startup.js new file mode 100644 index 000000000..867dc9673 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_provider_unsafe_access_startup.js @@ -0,0 +1,53 @@ +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + +let startupOrder = []; + +function mockAddonProvider(name) { + let mockProvider = { + hasStarted: false, + unsafeAccess: false, + + startupCallback: null, + + startup() { + this.hasStarted = true; + startupOrder.push(this.name); + if (this.startupCallback) + this.startupCallback(); + }, + getAddonByID(id, callback) { + if (!this.hasStarted) { + unsafeAccess = true; + } + callback(null); + }, + + get name() name, + }; + + return mockProvider; +}; + +function run_test() { + run_next_test(); +} + +add_task(function* unsafeProviderStartup() { + let secondProvider = null; + + yield new Promise(resolve => { + let firstProvider = mockAddonProvider("Mock1"); + firstProvider.startupCallback = function() { + AddonManager.getAddonByID("does-not-exist", resolve); + }; + AddonManagerPrivate.registerProvider(firstProvider); + + secondProvider = mockAddonProvider("Mock2"); + AddonManagerPrivate.registerProvider(secondProvider); + + startupManager(); + }); + + equal(startupOrder.join(","), ["Mock1", "Mock2"].join(","), "Mock providers should have hasStarted in expected order"); + ok(!secondProvider.unsafeAccess, "Second registered mock provider should not have been accessed unsafely"); +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_registry.js b/toolkit/mozapps/extensions/test/xpcshell/test_registry.js new file mode 100644 index 000000000..010250457 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_registry.js @@ -0,0 +1,151 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that extensions installed through the registry work as expected +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + +// Enable loading extensions from the user and system scopes +Services.prefs.setIntPref("extensions.enabledScopes", + AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_USER + + AddonManager.SCOPE_SYSTEM); + +var addon1 = { + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +var addon2 = { + id: "addon2@tests.mozilla.org", + version: "2.0", + name: "Test 2", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }] +}; + +const addon1Dir = writeInstallRDFForExtension(addon1, gProfD, "addon1"); +const addon2Dir = writeInstallRDFForExtension(addon2, gProfD, "addon2"); + +function run_test() { + // This test only works where there is a registry. + if (!("nsIWindowsRegKey" in AM_Ci)) + return; + + do_test_pending(); + + run_test_1(); +} + +// Tests whether basic registry install works +function run_test_1() { + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon1@tests.mozilla.org", addon1Dir.path); + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon2@tests.mozilla.org", addon2Dir.path); + + startupManager(); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org"], function([a1, a2]) { + do_check_neq(a1, null); + do_check_true(a1.isActive); + do_check_false(hasFlag(a1.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_eq(a1.scope, AddonManager.SCOPE_SYSTEM); + + do_check_neq(a2, null); + do_check_true(a2.isActive); + do_check_false(hasFlag(a2.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_eq(a2.scope, AddonManager.SCOPE_USER); + + do_execute_soon(run_test_2); + }); +} + +// Tests whether uninstalling from the registry works +function run_test_2() { + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon1@tests.mozilla.org", null); + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon2@tests.mozilla.org", null); + + restartManager(); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org"], function([a1, a2]) { + do_check_eq(a1, null); + do_check_eq(a2, null); + + do_execute_soon(run_test_3); + }); +} + +// Checks that the ID in the registry must match that in the install manifest +function run_test_3() { + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon1@tests.mozilla.org", addon2Dir.path); + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon2@tests.mozilla.org", addon1Dir.path); + + restartManager(); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org"], function([a1, a2]) { + do_check_eq(a1, null); + do_check_eq(a2, null); + + do_execute_soon(run_test_4); + }); +} + +// Tests whether an extension's ID can change without its directory changing +function run_test_4() { + // Restarting with bad items in the registry should not force an EM restart + restartManager(); + + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon1@tests.mozilla.org", null); + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon2@tests.mozilla.org", null); + + restartManager(); + + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon1@tests.mozilla.org", addon1Dir.path); + restartManager(); + + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon1@tests.mozilla.org", null); + MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + "SOFTWARE\\Mozilla\\XPCShell\\Extensions", + "addon2@tests.mozilla.org", addon1Dir.path); + writeInstallRDFForExtension(addon2, gProfD, "addon1"); + + restartManager(); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org"], function([a1, a2]) { + do_check_eq(a1, null); + do_check_neq(a2, null); + + do_execute_soon(do_test_finished); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_safemode.js b/toolkit/mozapps/extensions/test/xpcshell/test_safemode.js new file mode 100644 index 000000000..05647f807 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_safemode.js @@ -0,0 +1,115 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +Components.utils.import("resource://gre/modules/NetUtil.jsm"); + +// Tests that extensions behave correctly in safe mode + +var addon1 = { + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + optionsURL: "chrome://foo/content/options.xul", + aboutURL: "chrome://foo/content/about.xul", + iconURL: "chrome://foo/content/icon.png", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +var gIconURL = null; + +// Sets up the profile by installing an add-on. +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + gAppInfo.inSafeMode = true; + + startupManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { + do_check_eq(a1, null); + do_check_not_in_crash_annotation(addon1.id, addon1.version); + + writeInstallRDFForExtension(addon1, profileDir, addon1.id, "icon.png"); + gIconURL = do_get_addon_root_uri(profileDir.clone(), addon1.id) + "icon.png"; + + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(newa1) { + do_check_neq(newa1, null); + do_check_false(newa1.isActive); + do_check_false(newa1.userDisabled); + do_check_eq(newa1.aboutURL, null); + do_check_eq(newa1.optionsURL, null); + do_check_eq(newa1.iconURL, gIconURL); + do_check_true(isExtensionInAddonsList(profileDir, newa1.id)); + do_check_true(hasFlag(newa1.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_false(hasFlag(newa1.permissions, AddonManager.PERM_CAN_ENABLE)); + do_check_eq(newa1.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_NONE); + do_check_not_in_crash_annotation(addon1.id, addon1.version); + + run_test_1(); + }); + })); +} + +// Disabling an add-on should work +function run_test_1() { + prepare_test({ + "addon1@tests.mozilla.org": [ + ["onDisabling", false], + "onDisabled" + ] + }); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_false(hasFlag(a1.operationsRequiringRestart, + AddonManager.OP_NEEDS_RESTART_DISABLE)); + a1.userDisabled = true; + do_check_false(a1.isActive); + do_check_eq(a1.aboutURL, null); + do_check_eq(a1.optionsURL, null); + do_check_eq(a1.iconURL, gIconURL); + do_check_false(hasFlag(a1.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_true(hasFlag(a1.permissions, AddonManager.PERM_CAN_ENABLE)); + do_check_eq(a1.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_NONE); + do_check_not_in_crash_annotation(addon1.id, addon1.version); + + ensure_test_completed(); + + run_test_2(); + }); +} + +// Enabling an add-on should happen without restart but not become active. +function run_test_2() { + prepare_test({ + "addon1@tests.mozilla.org": [ + ["onEnabling", false], + "onEnabled" + ] + }); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + a1.userDisabled = false; + do_check_false(a1.isActive); + do_check_eq(a1.aboutURL, null); + do_check_eq(a1.optionsURL, null); + do_check_eq(a1.iconURL, gIconURL); + do_check_true(hasFlag(a1.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_false(hasFlag(a1.permissions, AddonManager.PERM_CAN_ENABLE)); + do_check_eq(a1.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_NONE); + do_check_not_in_crash_annotation(addon1.id, addon1.version); + + ensure_test_completed(); + + do_execute_soon(do_test_finished); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_shutdown.js b/toolkit/mozapps/extensions/test/xpcshell/test_shutdown.js new file mode 100644 index 000000000..a865824f0 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_shutdown.js @@ -0,0 +1,65 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Verify that API functions fail if the Add-ons Manager isn't initialised. + +const IGNORE = ["escapeAddonURI", "shouldAutoUpdate", "getStartupChanges", + "addTypeListener", "removeTypeListener", + "addAddonListener", "removeAddonListener", + "addInstallListener", "removeInstallListener", + "addManagerListener", "removeManagerListener", + "mapURIToAddonID", "shutdown"]; + +const IGNORE_PRIVATE = ["AddonAuthor", "AddonCompatibilityOverride", + "AddonScreenshot", "AddonType", "startup", "shutdown", + "registerProvider", "unregisterProvider", + "addStartupChange", "removeStartupChange", + "recordTimestamp", "recordSimpleMeasure", + "recordException", "getSimpleMeasures", "simpleTimer", + "setTelemetryDetails", "getTelemetryDetails", + "callNoUpdateListeners", "backgroundUpdateTimerHandler"]; + +function test_functions() { + for (let prop in AddonManager) { + if (IGNORE.indexOf(prop) != -1) + continue; + if (typeof AddonManager[prop] != "function") + continue; + + try { + do_print("AddonManager." + prop); + AddonManager[prop](); + do_throw(prop + " did not throw an exception"); + } + catch (e) { + if (e.result != Components.results.NS_ERROR_NOT_INITIALIZED) + do_throw(prop + " threw an unexpected exception: " + e); + } + } + + for (let prop in AddonManagerPrivate) { + if (typeof AddonManagerPrivate[prop] != "function") + continue; + if (IGNORE_PRIVATE.indexOf(prop) != -1) + continue; + + try { + do_print("AddonManagerPrivate." + prop); + AddonManagerPrivate[prop](); + do_throw(prop + " did not throw an exception"); + } + catch (e) { + if (e.result != Components.results.NS_ERROR_NOT_INITIALIZED) + do_throw(prop + " threw an unexpected exception: " + e); + } + } +} + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + test_functions(); + startupManager(); + shutdownManager(); + test_functions(); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_sourceURI.js b/toolkit/mozapps/extensions/test/xpcshell/test_sourceURI.js new file mode 100644 index 000000000..e78bb5074 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_sourceURI.js @@ -0,0 +1,66 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +Components.utils.import("resource://testing-common/httpd.js"); +var gServer = new HttpServer(); +gServer.start(-1); + +const PREF_GETADDONS_CACHE_ENABLED = "extensions.getAddons.cache.enabled"; + +const PORT = gServer.identity.primaryPort; +const BASE_URL = "http://localhost:" + PORT; +const DEFAULT_URL = "about:blank"; + +var addon = { + id: "addon@tests.mozilla.org", + version: "1.0", + name: "Test", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +function backgroundUpdate(aCallback) { + Services.obs.addObserver(function() { + Services.obs.removeObserver(arguments.callee, "addons-background-update-complete"); + aCallback(); + }, "addons-background-update-complete", false); + + AddonManagerPrivate.backgroundUpdateCheck(); +} + +function run_test() { + do_test_pending(); + + mapUrlToFile("/cache.xml", do_get_file("data/test_sourceURI.xml"), gServer); + Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, BASE_URL + "/cache.xml"); + Services.prefs.setCharPref(PREF_GETADDONS_BYIDS_PERFORMANCE, BASE_URL + "/cache.xml"); + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); + writeInstallRDFForExtension(addon, profileDir); + startupManager(); + + AddonManager.getAddonByID("addon@tests.mozilla.org", function(a) { + do_check_neq(a, null); + do_check_eq(a.sourceURI, null); + + backgroundUpdate(function() { + restartManager(); + + AddonManager.getAddonByID("addon@tests.mozilla.org", function(a) { + do_check_neq(a, null); + do_check_neq(a.sourceURI, null); + do_check_eq(a.sourceURI.spec, "http://www.example.com/testaddon.xpi"); + + do_test_finished(); + }); + }); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_startup.js b/toolkit/mozapps/extensions/test/xpcshell/test_startup.js new file mode 100644 index 000000000..181f8ee62 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_startup.js @@ -0,0 +1,917 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies startup detection of added/removed/changed items and install +// location priorities + +// Enable loading extensions from the user and system scopes +Services.prefs.setIntPref("extensions.enabledScopes", + AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_USER + + AddonManager.SCOPE_SYSTEM); + +var addon1 = { + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }, { // Repeated target application entries should be ignored + id: "xpcshell@tests.mozilla.org", + minVersion: "2", + maxVersion: "2" + }] +}; + +var addon2 = { + id: "addon2@tests.mozilla.org", + version: "2.0", + name: "Test 2", + targetApplications: [{ // Bad target application entries should be ignored + minVersion: "3", + maxVersion: "4" + }, { + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }] +}; + +var addon3 = { + id: "addon3@tests.mozilla.org", + version: "3.0", + name: "Test 3", + targetApplications: [{ + id: "toolkit@mozilla.org", + minVersion: "1.9.2", + maxVersion: "1.9.2.*" + }] +}; + +// Should be ignored because it has no ID +var addon4 = { + version: "4.0", + name: "Test 4", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Should be ignored because it has no version +var addon5 = { + id: "addon5@tests.mozilla.org", + name: "Test 5", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Should be ignored because it has an invalid type +var addon6 = { + id: "addon6@tests.mozilla.org", + version: "3.0", + name: "Test 6", + type: 5, + targetApplications: [{ + id: "toolkit@mozilla.org", + minVersion: "1.9.2", + maxVersion: "1.9.2.*" + }] +}; + +// Should be ignored because it has an invalid type +var addon7 = { + id: "addon7@tests.mozilla.org", + version: "3.0", + name: "Test 3", + type: "extension", + targetApplications: [{ + id: "toolkit@mozilla.org", + minVersion: "1.9.2", + maxVersion: "1.9.2.*" + }] +}; + +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + +const globalDir = gProfD.clone(); +globalDir.append("extensions2"); +globalDir.append(gAppInfo.ID); +registerDirectory("XRESysSExtPD", globalDir.parent); +const userDir = gProfD.clone(); +userDir.append("extensions3"); +userDir.append(gAppInfo.ID); +registerDirectory("XREUSysExt", userDir.parent); +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +var gCachePurged = false; + +// Set up the profile +function run_test() { + do_test_pending("test_startup main"); + + let obs = AM_Cc["@mozilla.org/observer-service;1"]. + getService(AM_Ci.nsIObserverService); + obs.addObserver({ + observe: function(aSubject, aTopic, aData) { + gCachePurged = true; + } + }, "startupcache-invalidate", false); + + startupManager(); + check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_CHANGED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_UNINSTALLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_DISABLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_ENABLED, []); + + do_check_false(gExtensionsJSON.exists()); + + do_check_false(gExtensionsINI.exists()); + + 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"], + function([a1, a2, a3, a4, a5, a6, a7]) { + + do_check_eq(a1, null); + do_check_not_in_crash_annotation(addon1.id, addon1.version); + do_check_eq(a2, null); + do_check_not_in_crash_annotation(addon2.id, addon2.version); + do_check_eq(a3, null); + do_check_not_in_crash_annotation(addon3.id, addon3.version); + do_check_eq(a4, null); + do_check_eq(a5, null); + + do_execute_soon(run_test_1); + }); +} + +function end_test() { + do_test_finished("test_startup main"); +} + +// Try to install all the items into the profile +function run_test_1() { + writeInstallRDFForExtension(addon1, profileDir); + var dest = writeInstallRDFForExtension(addon2, profileDir); + // Attempt to make this look like it was added some time in the past so + // the change in run_test_2 makes the last modified time change. + setExtensionModifiedTime(dest, dest.lastModifiedTime - 5000); + + writeInstallRDFForExtension(addon3, profileDir); + writeInstallRDFForExtension(addon4, profileDir, "addon4@tests.mozilla.org"); + writeInstallRDFForExtension(addon5, profileDir); + writeInstallRDFForExtension(addon6, profileDir); + writeInstallRDFForExtension(addon7, profileDir); + + gCachePurged = false; + restartManager(); + check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, ["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org"]); + check_startup_changes(AddonManager.STARTUP_CHANGE_CHANGED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_UNINSTALLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_DISABLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_ENABLED, []); + do_check_true(gCachePurged); + + do_print("Checking for " + gExtensionsINI.path); + do_check_true(gExtensionsINI.exists()); + + 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"], + function([a1, a2, a3, a4, a5, a6, a7]) { + + do_check_neq(a1, null); + do_check_eq(a1.id, "addon1@tests.mozilla.org"); + do_check_neq(a1.syncGUID, null); + do_check_true(a1.syncGUID.length >= 9); + do_check_eq(a1.version, "1.0"); + do_check_eq(a1.name, "Test 1"); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); + do_check_true(hasFlag(a1.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_true(hasFlag(a1.permissions, AddonManager.PERM_CAN_UPGRADE)); + do_check_in_crash_annotation(addon1.id, addon1.version); + do_check_eq(a1.scope, AddonManager.SCOPE_PROFILE); + do_check_eq(a1.sourceURI, null); + do_check_true(a1.foreignInstall); + + do_check_neq(a2, null); + do_check_eq(a2.id, "addon2@tests.mozilla.org"); + do_check_neq(a2.syncGUID, null); + do_check_true(a2.syncGUID.length >= 9); + do_check_eq(a2.version, "2.0"); + do_check_eq(a2.name, "Test 2"); + do_check_true(isExtensionInAddonsList(profileDir, a2.id)); + do_check_true(hasFlag(a2.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_true(hasFlag(a2.permissions, AddonManager.PERM_CAN_UPGRADE)); + do_check_in_crash_annotation(addon2.id, addon2.version); + do_check_eq(a2.scope, AddonManager.SCOPE_PROFILE); + do_check_eq(a2.sourceURI, null); + do_check_true(a2.foreignInstall); + + do_check_neq(a3, null); + do_check_eq(a3.id, "addon3@tests.mozilla.org"); + do_check_neq(a3.syncGUID, null); + do_check_true(a3.syncGUID.length >= 9); + do_check_eq(a3.version, "3.0"); + do_check_eq(a3.name, "Test 3"); + do_check_true(isExtensionInAddonsList(profileDir, a3.id)); + do_check_true(hasFlag(a3.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_true(hasFlag(a3.permissions, AddonManager.PERM_CAN_UPGRADE)); + do_check_in_crash_annotation(addon3.id, addon3.version); + do_check_eq(a3.scope, AddonManager.SCOPE_PROFILE); + do_check_eq(a3.sourceURI, null); + do_check_true(a3.foreignInstall); + + do_check_eq(a4, null); + do_check_false(isExtensionInAddonsList(profileDir, "addon4@tests.mozilla.org")); + dest = profileDir.clone(); + dest.append(do_get_expected_addon_name("addon4@tests.mozilla.org")); + do_check_false(dest.exists()); + + do_check_eq(a5, null); + do_check_false(isExtensionInAddonsList(profileDir, "addon5@tests.mozilla.org")); + dest = profileDir.clone(); + dest.append(do_get_expected_addon_name("addon5@tests.mozilla.org")); + do_check_false(dest.exists()); + + do_check_eq(a6, null); + do_check_false(isExtensionInAddonsList(profileDir, "addon6@tests.mozilla.org")); + dest = profileDir.clone(); + dest.append(do_get_expected_addon_name("addon6@tests.mozilla.org")); + do_check_false(dest.exists()); + + do_check_eq(a7, null); + do_check_false(isExtensionInAddonsList(profileDir, "addon7@tests.mozilla.org")); + dest = profileDir.clone(); + dest.append(do_get_expected_addon_name("addon7@tests.mozilla.org")); + do_check_false(dest.exists()); + + AddonManager.getAddonsByTypes(["extension"], function(extensionAddons) { + do_check_eq(extensionAddons.length, 3); + + do_execute_soon(run_test_2); + }); + }); +} + +// Test that modified items are detected and items in other install locations +// are ignored +function run_test_2() { + addon1.version = "1.1"; + writeInstallRDFForExtension(addon1, userDir); + addon2.version="2.1"; + writeInstallRDFForExtension(addon2, profileDir); + addon2.version="2.2"; + writeInstallRDFForExtension(addon2, globalDir); + addon2.version="2.3"; + writeInstallRDFForExtension(addon2, userDir); + var dest = profileDir.clone(); + dest.append(do_get_expected_addon_name("addon3@tests.mozilla.org")); + dest.remove(true); + + gCachePurged = false; + restartManager(); + check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_CHANGED, ["addon2@tests.mozilla.org"]); + check_startup_changes(AddonManager.STARTUP_CHANGE_UNINSTALLED, ["addon3@tests.mozilla.org"]); + check_startup_changes(AddonManager.STARTUP_CHANGE_DISABLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_ENABLED, []); + do_check_true(gCachePurged); + + do_check_true(gExtensionsINI.exists()); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org"], + function([a1, a2, a3, a4, a5]) { + + do_check_neq(a1, null); + do_check_eq(a1.id, "addon1@tests.mozilla.org"); + do_check_eq(a1.version, "1.0"); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); + do_check_false(isExtensionInAddonsList(userDir, a1.id)); + do_check_true(hasFlag(a1.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_true(hasFlag(a1.permissions, AddonManager.PERM_CAN_UPGRADE)); + do_check_in_crash_annotation(addon1.id, a1.version); + do_check_eq(a1.scope, AddonManager.SCOPE_PROFILE); + do_check_true(a1.foreignInstall); + + do_check_neq(a2, null); + do_check_eq(a2.id, "addon2@tests.mozilla.org"); + do_check_eq(a2.version, "2.1"); + do_check_true(isExtensionInAddonsList(profileDir, a2.id)); + do_check_false(isExtensionInAddonsList(userDir, a2.id)); + do_check_false(isExtensionInAddonsList(globalDir, a2.id)); + do_check_true(hasFlag(a2.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_true(hasFlag(a2.permissions, AddonManager.PERM_CAN_UPGRADE)); + do_check_in_crash_annotation(addon2.id, a2.version); + do_check_eq(a2.scope, AddonManager.SCOPE_PROFILE); + do_check_true(a2.foreignInstall); + + do_check_eq(a3, null); + do_check_false(isExtensionInAddonsList(profileDir, "addon3@tests.mozilla.org")); + do_check_not_in_crash_annotation(addon3.id, addon3.version); + + do_check_eq(a4, null); + do_check_false(isExtensionInAddonsList(profileDir, "addon4@tests.mozilla.org")); + + do_check_eq(a5, null); + do_check_false(isExtensionInAddonsList(profileDir, "addon5@tests.mozilla.org")); + + do_execute_soon(run_test_3); + }); +} + +// Check that removing items from the profile reveals their hidden versions. +function run_test_3() { + var dest = profileDir.clone(); + dest.append(do_get_expected_addon_name("addon1@tests.mozilla.org")); + dest.remove(true); + dest = profileDir.clone(); + dest.append(do_get_expected_addon_name("addon2@tests.mozilla.org")); + dest.remove(true); + writeInstallRDFForExtension(addon3, profileDir, "addon4@tests.mozilla.org"); + + gCachePurged = false; + restartManager(); + check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_CHANGED, ["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org"]); + check_startup_changes(AddonManager.STARTUP_CHANGE_UNINSTALLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_DISABLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_ENABLED, []); + do_check_true(gCachePurged); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org"], + function([a1, a2, a3, a4, a5]) { + + do_check_neq(a1, null); + do_check_eq(a1.id, "addon1@tests.mozilla.org"); + do_check_eq(a1.version, "1.1"); + do_check_false(isExtensionInAddonsList(profileDir, a1.id)); + do_check_true(isExtensionInAddonsList(userDir, a1.id)); + do_check_false(hasFlag(a1.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_false(hasFlag(a1.permissions, AddonManager.PERM_CAN_UPGRADE)); + do_check_in_crash_annotation(addon1.id, a1.version); + do_check_eq(a1.scope, AddonManager.SCOPE_USER); + + do_check_neq(a2, null); + do_check_eq(a2.id, "addon2@tests.mozilla.org"); + do_check_eq(a2.version, "2.3"); + do_check_false(isExtensionInAddonsList(profileDir, a2.id)); + do_check_true(isExtensionInAddonsList(userDir, a2.id)); + do_check_false(isExtensionInAddonsList(globalDir, a2.id)); + do_check_false(hasFlag(a2.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_false(hasFlag(a2.permissions, AddonManager.PERM_CAN_UPGRADE)); + do_check_in_crash_annotation(addon2.id, a2.version); + do_check_eq(a2.scope, AddonManager.SCOPE_USER); + + do_check_eq(a3, null); + do_check_false(isExtensionInAddonsList(profileDir, "addon3@tests.mozilla.org")); + + do_check_eq(a4, null); + do_check_false(isExtensionInAddonsList(profileDir, "addon4@tests.mozilla.org")); + + do_check_eq(a5, null); + do_check_false(isExtensionInAddonsList(profileDir, "addon5@tests.mozilla.org")); + + dest = profileDir.clone(); + dest.append(do_get_expected_addon_name("addon4@tests.mozilla.org")); + do_check_false(dest.exists()); + + do_execute_soon(run_test_4); + }); +} + +// Test that disabling an install location works +function run_test_4() { + Services.prefs.setIntPref("extensions.enabledScopes", AddonManager.SCOPE_SYSTEM); + + gCachePurged = false; + restartManager(); + check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_CHANGED, ["addon2@tests.mozilla.org"]); + check_startup_changes(AddonManager.STARTUP_CHANGE_UNINSTALLED, ["addon1@tests.mozilla.org"]); + check_startup_changes(AddonManager.STARTUP_CHANGE_DISABLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_ENABLED, []); + do_check_true(gCachePurged); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org"], + function([a1, a2, a3, a4, a5]) { + + do_check_eq(a1, null); + do_check_false(isExtensionInAddonsList(profileDir, "addon1@tests.mozilla.org")); + do_check_false(isExtensionInAddonsList(userDir, "addon1@tests.mozilla.org")); + + do_check_neq(a2, null); + do_check_eq(a2.id, "addon2@tests.mozilla.org"); + do_check_eq(a2.version, "2.2"); + do_check_false(isExtensionInAddonsList(profileDir, a2.id)); + do_check_false(isExtensionInAddonsList(userDir, a2.id)); + do_check_true(isExtensionInAddonsList(globalDir, a2.id)); + do_check_false(hasFlag(a2.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_false(hasFlag(a2.permissions, AddonManager.PERM_CAN_UPGRADE)); + do_check_in_crash_annotation(addon2.id, a2.version); + do_check_eq(a2.scope, AddonManager.SCOPE_SYSTEM); + + do_execute_soon(run_test_5); + }); +} + +// Switching disabled locations works +function run_test_5() { + Services.prefs.setIntPref("extensions.enabledScopes", AddonManager.SCOPE_USER); + + gCachePurged = false; + restartManager(); + check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, ["addon1@tests.mozilla.org"]); + check_startup_changes(AddonManager.STARTUP_CHANGE_CHANGED, ["addon2@tests.mozilla.org"]); + check_startup_changes(AddonManager.STARTUP_CHANGE_UNINSTALLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_DISABLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_ENABLED, []); + do_check_true(gCachePurged); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org"], + function([a1, a2, a3, a4, a5]) { + + do_check_neq(a1, null); + do_check_eq(a1.id, "addon1@tests.mozilla.org"); + do_check_eq(a1.version, "1.1"); + do_check_false(isExtensionInAddonsList(profileDir, a1.id)); + do_check_true(isExtensionInAddonsList(userDir, a1.id)); + do_check_false(hasFlag(a1.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_false(hasFlag(a1.permissions, AddonManager.PERM_CAN_UPGRADE)); + do_check_in_crash_annotation(addon1.id, a1.version); + do_check_eq(a1.scope, AddonManager.SCOPE_USER); + + do_check_neq(a2, null); + do_check_eq(a2.id, "addon2@tests.mozilla.org"); + do_check_eq(a2.version, "2.3"); + do_check_false(isExtensionInAddonsList(profileDir, a2.id)); + do_check_true(isExtensionInAddonsList(userDir, a2.id)); + do_check_false(isExtensionInAddonsList(globalDir, a2.id)); + do_check_false(hasFlag(a2.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_false(hasFlag(a2.permissions, AddonManager.PERM_CAN_UPGRADE)); + do_check_in_crash_annotation(addon2.id, a2.version); + do_check_eq(a2.scope, AddonManager.SCOPE_USER); + + do_execute_soon(run_test_6); + }); +} + +// Resetting the pref makes everything visible again +function run_test_6() { + Services.prefs.clearUserPref("extensions.enabledScopes"); + + gCachePurged = false; + restartManager(); + check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_CHANGED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_UNINSTALLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_DISABLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_ENABLED, []); + do_check_true(gCachePurged); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org"], + function([a1, a2, a3, a4, a5]) { + + do_check_neq(a1, null); + do_check_eq(a1.id, "addon1@tests.mozilla.org"); + do_check_eq(a1.version, "1.1"); + do_check_false(isExtensionInAddonsList(profileDir, a1.id)); + do_check_true(isExtensionInAddonsList(userDir, a1.id)); + do_check_false(hasFlag(a1.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_false(hasFlag(a1.permissions, AddonManager.PERM_CAN_UPGRADE)); + do_check_in_crash_annotation(addon1.id, a1.version); + do_check_eq(a1.scope, AddonManager.SCOPE_USER); + + do_check_neq(a2, null); + do_check_eq(a2.id, "addon2@tests.mozilla.org"); + do_check_eq(a2.version, "2.3"); + do_check_false(isExtensionInAddonsList(profileDir, a2.id)); + do_check_true(isExtensionInAddonsList(userDir, a2.id)); + do_check_false(isExtensionInAddonsList(globalDir, a2.id)); + do_check_false(hasFlag(a2.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_false(hasFlag(a2.permissions, AddonManager.PERM_CAN_UPGRADE)); + do_check_in_crash_annotation(addon2.id, a2.version); + do_check_eq(a2.scope, AddonManager.SCOPE_USER); + + do_execute_soon(run_test_7); + }); +} + +// Check that items in the profile hide the others again. +function run_test_7() { + addon1.version = "1.2"; + writeInstallRDFForExtension(addon1, profileDir); + var dest = userDir.clone(); + dest.append(do_get_expected_addon_name("addon2@tests.mozilla.org")); + dest.remove(true); + + gCachePurged = false; + restartManager(); + check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_CHANGED, ["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org"]); + check_startup_changes(AddonManager.STARTUP_CHANGE_UNINSTALLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_DISABLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_ENABLED, []); + do_check_true(gCachePurged); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org"], + function([a1, a2, a3, a4, a5]) { + + do_check_neq(a1, null); + do_check_eq(a1.id, "addon1@tests.mozilla.org"); + do_check_eq(a1.version, "1.2"); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); + do_check_false(isExtensionInAddonsList(userDir, a1.id)); + do_check_true(hasFlag(a1.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_true(hasFlag(a1.permissions, AddonManager.PERM_CAN_UPGRADE)); + do_check_in_crash_annotation(addon1.id, a1.version); + do_check_eq(a1.scope, AddonManager.SCOPE_PROFILE); + + do_check_neq(a2, null); + do_check_eq(a2.id, "addon2@tests.mozilla.org"); + do_check_eq(a2.version, "2.2"); + do_check_false(isExtensionInAddonsList(profileDir, a2.id)); + do_check_false(isExtensionInAddonsList(userDir, a2.id)); + do_check_true(isExtensionInAddonsList(globalDir, a2.id)); + do_check_false(hasFlag(a2.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_false(hasFlag(a2.permissions, AddonManager.PERM_CAN_UPGRADE)); + do_check_in_crash_annotation(addon2.id, a2.version); + do_check_eq(a2.scope, AddonManager.SCOPE_SYSTEM); + + do_check_eq(a3, null); + do_check_false(isExtensionInAddonsList(profileDir, "addon3@tests.mozilla.org")); + + do_check_eq(a4, null); + do_check_false(isExtensionInAddonsList(profileDir, "addon4@tests.mozilla.org")); + + do_check_eq(a5, null); + do_check_false(isExtensionInAddonsList(profileDir, "addon5@tests.mozilla.org")); + + do_execute_soon(run_test_8); + }); +} + +// Disabling all locations still leaves the profile working +function run_test_8() { + Services.prefs.setIntPref("extensions.enabledScopes", 0); + + gCachePurged = false; + restartManager(); + check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_CHANGED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_UNINSTALLED, ["addon2@tests.mozilla.org"]); + check_startup_changes(AddonManager.STARTUP_CHANGE_DISABLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_ENABLED, []); + do_check_true(gCachePurged); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org"], + function([a1, a2, a3, a4, a5]) { + + do_check_neq(a1, null); + do_check_eq(a1.id, "addon1@tests.mozilla.org"); + do_check_eq(a1.version, "1.2"); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); + do_check_false(isExtensionInAddonsList(userDir, a1.id)); + do_check_true(hasFlag(a1.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_true(hasFlag(a1.permissions, AddonManager.PERM_CAN_UPGRADE)); + do_check_in_crash_annotation(addon1.id, a1.version); + do_check_eq(a1.scope, AddonManager.SCOPE_PROFILE); + + do_check_eq(a2, null); + do_check_false(isExtensionInAddonsList(profileDir, "addon2@tests.mozilla.org")); + do_check_false(isExtensionInAddonsList(userDir, "addon2@tests.mozilla.org")); + do_check_false(isExtensionInAddonsList(globalDir, "addon2@tests.mozilla.org")); + + do_execute_soon(run_test_9); + }); +} + +// More hiding and revealing +function run_test_9() { + Services.prefs.clearUserPref("extensions.enabledScopes", 0); + + var dest = userDir.clone(); + dest.append(do_get_expected_addon_name("addon1@tests.mozilla.org")); + dest.remove(true); + dest = globalDir.clone(); + dest.append(do_get_expected_addon_name("addon2@tests.mozilla.org")); + dest.remove(true); + addon2.version = "2.4"; + writeInstallRDFForExtension(addon2, profileDir); + + gCachePurged = false; + restartManager(); + check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, ["addon2@tests.mozilla.org"]); + check_startup_changes(AddonManager.STARTUP_CHANGE_CHANGED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_UNINSTALLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_DISABLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_ENABLED, []); + do_check_true(gCachePurged); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org"], + function([a1, a2, a3, a4, a5]) { + + do_check_neq(a1, null); + do_check_eq(a1.id, "addon1@tests.mozilla.org"); + do_check_eq(a1.version, "1.2"); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); + do_check_false(isExtensionInAddonsList(userDir, a1.id)); + do_check_true(hasFlag(a1.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_true(hasFlag(a1.permissions, AddonManager.PERM_CAN_UPGRADE)); + do_check_eq(a1.scope, AddonManager.SCOPE_PROFILE); + + do_check_neq(a2, null); + do_check_eq(a2.id, "addon2@tests.mozilla.org"); + do_check_eq(a2.version, "2.4"); + do_check_true(isExtensionInAddonsList(profileDir, a2.id)); + do_check_false(isExtensionInAddonsList(userDir, a2.id)); + do_check_false(isExtensionInAddonsList(globalDir, a2.id)); + do_check_true(hasFlag(a2.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_true(hasFlag(a2.permissions, AddonManager.PERM_CAN_UPGRADE)); + do_check_eq(a2.scope, AddonManager.SCOPE_PROFILE); + + do_check_eq(a3, null); + do_check_false(isExtensionInAddonsList(profileDir, "addon3@tests.mozilla.org")); + + do_check_eq(a4, null); + do_check_false(isExtensionInAddonsList(profileDir, "addon4@tests.mozilla.org")); + + do_check_eq(a5, null); + do_check_false(isExtensionInAddonsList(profileDir, "addon5@tests.mozilla.org")); + + do_execute_soon(run_test_10); + }); +} + +// Checks that a removal from one location and an addition in another location +// for the same item is handled +function run_test_10() { + var dest = profileDir.clone(); + dest.append(do_get_expected_addon_name("addon1@tests.mozilla.org")); + dest.remove(true); + addon1.version = "1.3"; + writeInstallRDFForExtension(addon1, userDir); + + gCachePurged = false; + restartManager(); + check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_CHANGED, ["addon1@tests.mozilla.org"]); + check_startup_changes(AddonManager.STARTUP_CHANGE_UNINSTALLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_DISABLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_ENABLED, []); + do_check_true(gCachePurged); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org"], + function([a1, a2, a3, a4, a5]) { + + do_check_neq(a1, null); + do_check_eq(a1.id, "addon1@tests.mozilla.org"); + do_check_eq(a1.version, "1.3"); + do_check_false(isExtensionInAddonsList(profileDir, a1.id)); + do_check_true(isExtensionInAddonsList(userDir, a1.id)); + do_check_false(hasFlag(a1.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_false(hasFlag(a1.permissions, AddonManager.PERM_CAN_UPGRADE)); + do_check_eq(a1.scope, AddonManager.SCOPE_USER); + + do_check_neq(a2, null); + do_check_eq(a2.id, "addon2@tests.mozilla.org"); + do_check_eq(a2.version, "2.4"); + do_check_true(isExtensionInAddonsList(profileDir, a2.id)); + do_check_false(isExtensionInAddonsList(userDir, a2.id)); + do_check_false(isExtensionInAddonsList(globalDir, a2.id)); + do_check_true(hasFlag(a2.permissions, AddonManager.PERM_CAN_UNINSTALL)); + do_check_true(hasFlag(a2.permissions, AddonManager.PERM_CAN_UPGRADE)); + do_check_eq(a2.scope, AddonManager.SCOPE_PROFILE); + + do_check_eq(a3, null); + do_check_false(isExtensionInAddonsList(profileDir, "addon3@tests.mozilla.org")); + + do_check_eq(a4, null); + do_check_false(isExtensionInAddonsList(profileDir, "addon4@tests.mozilla.org")); + + do_check_eq(a5, null); + do_check_false(isExtensionInAddonsList(profileDir, "addon5@tests.mozilla.org")); + + do_execute_soon(run_test_11); + }); +} + +// This should remove any remaining items +function run_test_11() { + var dest = userDir.clone(); + dest.append(do_get_expected_addon_name("addon1@tests.mozilla.org")); + dest.remove(true); + dest = profileDir.clone(); + dest.append(do_get_expected_addon_name("addon2@tests.mozilla.org")); + dest.remove(true); + + gCachePurged = false; + restartManager(); + check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_CHANGED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_UNINSTALLED, ["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org"]); + check_startup_changes(AddonManager.STARTUP_CHANGE_DISABLED, []); + check_startup_changes(AddonManager.STARTUP_CHANGE_ENABLED, []); + do_check_true(gCachePurged); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@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_eq(a4, null); + do_check_eq(a5, null); + do_check_false(isExtensionInAddonsList(profileDir, "addon1@tests.mozilla.org")); + do_check_false(isExtensionInAddonsList(profileDir, "addon2@tests.mozilla.org")); + do_check_false(isExtensionInAddonsList(profileDir, "addon3@tests.mozilla.org")); + do_check_false(isExtensionInAddonsList(profileDir, "addon4@tests.mozilla.org")); + do_check_false(isExtensionInAddonsList(profileDir, "addon5@tests.mozilla.org")); + do_check_false(isExtensionInAddonsList(userDir, "addon1@tests.mozilla.org")); + do_check_false(isExtensionInAddonsList(userDir, "addon2@tests.mozilla.org")); + do_check_false(isExtensionInAddonsList(userDir, "addon3@tests.mozilla.org")); + do_check_false(isExtensionInAddonsList(userDir, "addon4@tests.mozilla.org")); + do_check_false(isExtensionInAddonsList(userDir, "addon5@tests.mozilla.org")); + do_check_false(isExtensionInAddonsList(globalDir, "addon1@tests.mozilla.org")); + do_check_false(isExtensionInAddonsList(globalDir, "addon2@tests.mozilla.org")); + do_check_false(isExtensionInAddonsList(globalDir, "addon3@tests.mozilla.org")); + do_check_false(isExtensionInAddonsList(globalDir, "addon4@tests.mozilla.org")); + do_check_false(isExtensionInAddonsList(globalDir, "addon5@tests.mozilla.org")); + do_check_not_in_crash_annotation(addon1.id, addon1.version); + do_check_not_in_crash_annotation(addon2.id, addon2.version); + + do_execute_soon(run_test_12); + }); +} + +// Test that auto-disabling for specific scopes works +function run_test_12() { + Services.prefs.setIntPref("extensions.autoDisableScopes", AddonManager.SCOPE_USER); + + writeInstallRDFForExtension(addon1, profileDir); + writeInstallRDFForExtension(addon2, userDir); + writeInstallRDFForExtension(addon3, globalDir); + + restartManager(); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org"], + callback_soon(function([a1, a2, a3, a4, a5]) { + do_check_neq(a1, null); + do_check_false(a1.userDisabled); + do_check_true(a1.isActive); + + do_check_neq(a2, null); + do_check_true(a2.userDisabled); + do_check_false(a2.isActive); + + do_check_neq(a3, null); + do_check_false(a3.userDisabled); + do_check_true(a3.isActive); + + var dest = profileDir.clone(); + dest.append(do_get_expected_addon_name("addon1@tests.mozilla.org")); + dest.remove(true); + dest = userDir.clone(); + dest.append(do_get_expected_addon_name("addon2@tests.mozilla.org")); + dest.remove(true); + dest = globalDir.clone(); + dest.append(do_get_expected_addon_name("addon3@tests.mozilla.org")); + dest.remove(true); + + restartManager(); + + Services.prefs.setIntPref("extensions.autoDisableScopes", AddonManager.SCOPE_SYSTEM); + + writeInstallRDFForExtension(addon1, profileDir); + writeInstallRDFForExtension(addon2, userDir); + writeInstallRDFForExtension(addon3, globalDir); + + restartManager(); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org"], + function([a1, a2, a3, a4, a5]) { + do_check_neq(a1, null); + do_check_false(a1.userDisabled); + do_check_true(a1.isActive); + + do_check_neq(a2, null); + do_check_false(a2.userDisabled); + do_check_true(a2.isActive); + + do_check_neq(a3, null); + do_check_true(a3.userDisabled); + do_check_false(a3.isActive); + + var dest = profileDir.clone(); + dest.append(do_get_expected_addon_name("addon1@tests.mozilla.org")); + dest.remove(true); + dest = userDir.clone(); + dest.append(do_get_expected_addon_name("addon2@tests.mozilla.org")); + dest.remove(true); + dest = globalDir.clone(); + dest.append(do_get_expected_addon_name("addon3@tests.mozilla.org")); + dest.remove(true); + + restartManager(); + + Services.prefs.setIntPref("extensions.autoDisableScopes", AddonManager.SCOPE_USER + AddonManager.SCOPE_SYSTEM); + + writeInstallRDFForExtension(addon1, profileDir); + writeInstallRDFForExtension(addon2, userDir); + writeInstallRDFForExtension(addon3, globalDir); + + restartManager(); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org"], + function([a1, a2, a3, a4, a5]) { + do_check_neq(a1, null); + do_check_false(a1.userDisabled); + do_check_true(a1.isActive); + + do_check_neq(a2, null); + do_check_true(a2.userDisabled); + do_check_false(a2.isActive); + + do_check_neq(a3, null); + do_check_true(a3.userDisabled); + do_check_false(a3.isActive); + + do_execute_soon(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 000000000..788e1ef79 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_strictcompatibility.js @@ -0,0 +1,203 @@ +/* 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, and the strictCompatibility option in
+// install.rdf
+
+
+// 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.7",
+ maxVersion: "0.8"
+ }]
+};
+
+// 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.8",
+ maxVersion: "0.9"
+ }]
+};
+
+// Opt-in to strict compatibility - always incompatible
+var addon4 = {
+ id: "addon4@tests.mozilla.org",
+ version: "1.0",
+ name: "Test 4",
+ strictCompatibility: true,
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "0.8",
+ maxVersion: "0.9"
+ }]
+};
+
+// Addon from the future - would be marked as compatibile-by-default,
+// but minVersion is higher than the app version
+var addon5 = {
+ id: "addon5@tests.mozilla.org",
+ version: "1.0",
+ name: "Test 5",
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "3",
+ maxVersion: "5"
+ }]
+};
+
+// Extremely old addon - maxVersion is less than the mimimum compat version
+// set in extensions.minCompatibleVersion
+var addon6 = {
+ id: "addon6@tests.mozilla.org",
+ version: "1.0",
+ name: "Test 6",
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "0.1",
+ maxVersion: "0.2"
+ }]
+};
+
+// Dictionary - incompatible in strict compatibility mode
+var addon7= {
+ id: "addon7@tests.mozilla.org",
+ version: "1.0",
+ name: "Test 7",
+ type: "64",
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "0.8",
+ maxVersion: "0.9"
+ }]
+};
+
+
+
+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",
+ "addon4@tests.mozilla.org",
+ "addon5@tests.mozilla.org",
+ "addon6@tests.mozilla.org",
+ "addon7@tests.mozilla.org"],
+ function([a1, a2, a3, a4, a5, a6, a7]) {
+ do_check_neq(a1, null);
+ do_check_eq(a1.isCompatible, aAddonCompat[0]);
+ do_check_eq(a1.appDisabled, !aAddonCompat[0]);
+ do_check_false(a1.strictCompatibility);
+
+ do_check_neq(a2, null);
+ do_check_eq(a2.isCompatible, aAddonCompat[1]);
+ do_check_eq(a2.appDisabled, !aAddonCompat[1]);
+ do_check_false(a2.strictCompatibility);
+
+ do_check_neq(a3, null);
+ do_check_eq(a3.isCompatible, aAddonCompat[2]);
+ do_check_eq(a3.appDisabled, !aAddonCompat[2]);
+ do_check_true(a3.strictCompatibility);
+
+ do_check_neq(a4, null);
+ do_check_eq(a4.isCompatible, aAddonCompat[3]);
+ do_check_eq(a4.appDisabled, !aAddonCompat[3]);
+ do_check_true(a4.strictCompatibility);
+
+ do_check_neq(a5, null);
+ do_check_eq(a5.isCompatible, aAddonCompat[4]);
+ do_check_eq(a5.appDisabled, !aAddonCompat[4]);
+ do_check_false(a5.strictCompatibility);
+
+ do_check_neq(a6, null);
+ do_check_eq(a6.isCompatible, aAddonCompat[5]);
+ do_check_eq(a6.appDisabled, !aAddonCompat[5]);
+ do_check_false(a6.strictCompatibility);
+
+ do_check_neq(a7, null);
+ do_check_eq(a7.isCompatible, aAddonCompat[6]);
+ do_check_eq(a7.appDisabled, !aAddonCompat[6]);
+ do_check_false(a7.strictCompatibility);
+
+ do_execute_soon(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);
+ writeInstallRDFForExtension(addon4, profileDir);
+ writeInstallRDFForExtension(addon5, profileDir);
+ writeInstallRDFForExtension(addon6, profileDir);
+ writeInstallRDFForExtension(addon7, profileDir);
+
+ Services.prefs.setCharPref(PREF_EM_MIN_COMPAT_APP_VERSION, "0.1");
+
+ startupManager();
+
+ // Should default to enabling strict compat.
+ do_check_compat_status(true, [true, false, false, false, false, false, false], run_test_1);
+}
+
+function run_test_1() {
+ do_print("Test 1");
+ Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false);
+ do_check_compat_status(false, [true, true, false, false, false, true, true], run_test_2);
+}
+
+function run_test_2() {
+ do_print("Test 2");
+ restartManager();
+ do_check_compat_status(false, [true, true, false, false, false, true, true], run_test_3);
+}
+
+function run_test_3() {
+ do_print("Test 3");
+ Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, true);
+ do_check_compat_status(true, [true, false, false, false, false, false, false], run_test_4);
+}
+
+function run_test_4() {
+ do_print("Test 4");
+ restartManager();
+ do_check_compat_status(true, [true, false, false, false, false, false, false], run_test_5);
+}
+
+function run_test_5() {
+ do_print("Test 5");
+ Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false);
+ Services.prefs.setCharPref(PREF_EM_MIN_COMPAT_APP_VERSION, "0.4");
+ do_check_compat_status(false, [true, true, false, false, false, false, true], do_test_finished);
+}
diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_syncGUID.js b/toolkit/mozapps/extensions/test/xpcshell/test_syncGUID.js new file mode 100644 index 000000000..f1d6e0914 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_syncGUID.js @@ -0,0 +1,154 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +Components.utils.import("resource://gre/modules/Services.jsm"); + +// restartManager() mucks with XPIProvider.jsm importing, so we hack around. +this.__defineGetter__("XPIProvider", function () { + let scope = {}; + return Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm", scope) + .XPIProvider; +}); + +const addonId = "addon1@tests.mozilla.org"; + +function run_test() { + Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); + startupManager(); + + run_next_test(); +} + +add_test(function test_getter_and_setter() { + // Our test add-on requires a restart. + let listener = { + onInstallEnded: function onInstallEnded() { + AddonManager.removeInstallListener(listener); + // never restart directly inside an onInstallEnded handler! + do_execute_soon(function getter_setter_install_ended() { + restartManager(); + + AddonManager.getAddonByID(addonId, function(addon) { + + do_check_neq(addon, null); + do_check_neq(addon.syncGUID, null); + do_check_true(addon.syncGUID.length >= 9); + + let oldGUID = addon.SyncGUID; + let newGUID = "foo"; + + addon.syncGUID = newGUID; + do_check_eq(newGUID, addon.syncGUID); + + // Verify change made it to DB. + AddonManager.getAddonByID(addonId, function(newAddon) { + do_check_neq(newAddon, null); + do_check_eq(newGUID, newAddon.syncGUID); + }); + + run_next_test(); + }); + }); + } + }; + + AddonManager.addInstallListener(listener); + + AddonManager.getInstallForFile(do_get_addon("test_install1"), + function(install) { + install.install(); + }); +}); + +add_test(function test_fetch_by_guid_unknown_guid() { + XPIProvider.getAddonBySyncGUID("XXXX", function(addon) { + do_check_eq(null, addon); + run_next_test(); + }); +}); + +// Ensure setting an extension to an existing syncGUID results in error. +add_test(function test_error_on_duplicate_syncguid_insert() { + const installNames = ["test_install1", "test_install2_1"]; + const installIDs = ["addon1@tests.mozilla.org", "addon2@tests.mozilla.org"]; + + let installCount = 0; + + let listener = { + onInstallEnded: function onInstallEnded() { + installCount++; + + if (installCount == installNames.length) { + AddonManager.removeInstallListener(listener); + do_execute_soon(function duplicate_syncguid_install_ended() { + restartManager(); + + AddonManager.getAddonsByIDs(installIDs, callback_soon(function(addons) { + let initialGUID = addons[1].syncGUID; + + try { + addons[1].syncGUID = addons[0].syncGUID; + do_throw("Should not get here."); + } + catch (e) { + do_check_true(e.message.startsWith("Addon sync GUID conflict")); + restartManager(); + + AddonManager.getAddonByID(installIDs[1], function(addon) { + do_check_eq(initialGUID, addon.syncGUID); + run_next_test(); + }); + } + })); + }); + } + } + }; + + AddonManager.addInstallListener(listener); + let getInstallCB = function(install) { install.install(); }; + + for each (let name in installNames) { + AddonManager.getInstallForFile(do_get_addon(name), getInstallCB); + } +}); + +add_test(function test_fetch_by_guid_known_guid() { + AddonManager.getAddonByID(addonId, function(addon) { + do_check_neq(null, addon); + do_check_neq(null, addon.syncGUID); + + let syncGUID = addon.syncGUID; + + XPIProvider.getAddonBySyncGUID(syncGUID, function(newAddon) { + do_check_neq(null, newAddon); + do_check_eq(syncGUID, newAddon.syncGUID); + + run_next_test(); + }); + }); +}); + +add_test(function test_addon_manager_get_by_sync_guid() { + AddonManager.getAddonByID(addonId, function(addon) { + do_check_neq(null, addon.syncGUID); + + let syncGUID = addon.syncGUID; + + AddonManager.getAddonBySyncGUID(syncGUID, function(newAddon) { + do_check_neq(null, newAddon); + do_check_eq(addon.id, newAddon.id); + do_check_eq(syncGUID, newAddon.syncGUID); + + AddonManager.getAddonBySyncGUID("DOES_NOT_EXIST", function(missing) { + do_check_eq(undefined, missing); + + run_next_test(); + }); + }); + }); +}); + diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_targetPlatforms.js b/toolkit/mozapps/extensions/test/xpcshell/test_targetPlatforms.js new file mode 100644 index 000000000..ef4f2aee5 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_targetPlatforms.js @@ -0,0 +1,146 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that the targetPlatform entries are checked when deciding +// if an add-on is incompatible. + +// No targetPlatforms so should be compatible +var addon1 = { + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Matches the OS +var addon2 = { + id: "addon2@tests.mozilla.org", + version: "1.0", + name: "Test 2", + targetPlatforms: [ + "XPCShell", + "WINNT_x86", + "XPCShell" + ], + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Matches the OS and ABI +var addon3 = { + id: "addon3@tests.mozilla.org", + version: "1.0", + name: "Test 3", + targetPlatforms: [ + "WINNT", + "XPCShell_noarch-spidermonkey" + ], + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Doesn't match +var addon4 = { + id: "addon4@tests.mozilla.org", + version: "1.0", + name: "Test 4", + targetPlatforms: [ + "WINNT_noarch-spidermonkey", + "Darwin", + "WINNT_noarch-spidermonkey" + ], + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Matches the OS but since a different entry specifies ABI this doesn't match. +var addon5 = { + id: "addon5@tests.mozilla.org", + version: "1.0", + name: "Test 5", + targetPlatforms: [ + "XPCShell", + "XPCShell_foo" + ], + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +// Set up the profile +function run_test() { + do_test_pending(); + + writeInstallRDFForExtension(addon1, profileDir); + writeInstallRDFForExtension(addon2, profileDir); + writeInstallRDFForExtension(addon3, profileDir); + writeInstallRDFForExtension(addon4, profileDir); + writeInstallRDFForExtension(addon5, profileDir); + + restartManager(); + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org", + "addon3@tests.mozilla.org", + "addon4@tests.mozilla.org", + "addon5@tests.mozilla.org"], + function([a1, a2, a3, a4, a5]) { + + do_check_neq(a1, null); + do_check_false(a1.appDisabled); + do_check_true(a1.isPlatformCompatible); + do_check_true(a1.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); + do_check_in_crash_annotation(addon1.id, addon1.version); + + do_check_neq(a2, null); + do_check_false(a2.appDisabled); + do_check_true(a2.isPlatformCompatible); + do_check_true(a2.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a2.id)); + do_check_in_crash_annotation(addon2.id, addon2.version); + + do_check_neq(a3, null); + do_check_false(a3.appDisabled); + do_check_true(a3.isPlatformCompatible); + do_check_true(a3.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a3.id)); + do_check_in_crash_annotation(addon3.id, addon3.version); + + do_check_neq(a4, null); + do_check_true(a4.appDisabled); + do_check_false(a4.isPlatformCompatible); + do_check_false(a4.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a4.id)); + do_check_not_in_crash_annotation(addon4.id, addon4.version); + + do_check_neq(a5, null); + do_check_true(a5.appDisabled); + do_check_false(a5.isPlatformCompatible); + do_check_false(a5.isActive); + do_check_false(isExtensionInAddonsList(profileDir, a5.id)); + do_check_not_in_crash_annotation(addon5.id, addon5.version); + + do_execute_soon(do_test_finished); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_theme.js b/toolkit/mozapps/extensions/test/xpcshell/test_theme.js new file mode 100644 index 000000000..f201c776d --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_theme.js @@ -0,0 +1,1092 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +Components.utils.import("resource://gre/modules/NetUtil.jsm"); + +// The maximum allowable time since install. If an add-on claims to have been +// installed longer ago than this the the test will fail. +const MAX_INSTALL_TIME = 10000; + +// This verifies that themes behave as expected + +const PREF_GENERAL_SKINS_SELECTEDSKIN = "general.skins.selectedSkin"; + +Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm"); + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +// Observer to ensure a "lightweight-theme-styling-update" notification is sent +// when expected +var gLWThemeChanged = false; +var LightweightThemeObserver = { + observe: function(aSubject, aTopic, aData) { + if (aTopic != "lightweight-theme-styling-update") + return; + + gLWThemeChanged = true; + } +}; + +AM_Cc["@mozilla.org/observer-service;1"] + .getService(Components.interfaces.nsIObserverService) + .addObserver(LightweightThemeObserver, "lightweight-theme-styling-update", false); + + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + Services.prefs.setCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN, "theme1/1.0"); + writeInstallRDFForExtension({ + id: "theme1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + type: 4, + skinnable: true, + internalName: "theme1/1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }] + }, profileDir); + + writeInstallRDFForExtension({ + id: "theme2@tests.mozilla.org", + version: "1.0", + name: "Test 1", + skinnable: false, + internalName: "theme2/1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }] + }, profileDir); + + // We need a default theme for some of these things to work but we have hidden + // the one in the application directory. + writeInstallRDFForExtension({ + id: "default@tests.mozilla.org", + version: "1.0", + name: "Default", + internalName: "classic/1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }] + }, profileDir); + + startupManager(); + // Make sure we only register once despite multiple calls + AddonManager.addInstallListener(InstallListener); + AddonManager.addAddonListener(AddonListener); + AddonManager.addInstallListener(InstallListener); + AddonManager.addAddonListener(AddonListener); + AddonManager.addInstallListener(InstallListener); + + AddonManager.getAddonsByIDs(["default@tests.mozilla.org", + "theme1@tests.mozilla.org", + "theme2@tests.mozilla.org"], + function([d, t1, t2]) { + do_check_neq(d, null); + do_check_false(d.skinnable); + do_check_false(d.foreignInstall); + + do_check_neq(t1, null); + do_check_false(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_true(t1.isActive); + do_check_true(t1.skinnable); + do_check_true(t1.foreignInstall); + do_check_eq(t1.screenshots, null); + do_check_true(isThemeInAddonsList(profileDir, t1.id)); + do_check_false(hasFlag(t1.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_false(hasFlag(t1.permissions, AddonManager.PERM_CAN_ENABLE)); + do_check_eq(t1.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_UNINSTALL | + AddonManager.OP_NEEDS_RESTART_DISABLE); + + do_check_neq(t2, null); + do_check_true(t2.userDisabled); + do_check_false(t2.appDisabled); + do_check_false(t2.isActive); + do_check_false(t2.skinnable); + do_check_true(t2.foreignInstall); + do_check_eq(t2.screenshots, null); + do_check_false(isThemeInAddonsList(profileDir, t2.id)); + do_check_false(hasFlag(t2.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_true(hasFlag(t2.permissions, AddonManager.PERM_CAN_ENABLE)); + do_check_eq(t2.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_ENABLE); + + do_execute_soon(run_test_1); + }); +} + +function end_test() { + do_execute_soon(do_test_finished); +} + +// Checks enabling one theme disables the others +function run_test_1() { + prepare_test({ + "theme1@tests.mozilla.org": [ + "onDisabling" + ], + "theme2@tests.mozilla.org": [ + "onEnabling" + ] + }); + AddonManager.getAddonsByIDs(["theme1@tests.mozilla.org", + "theme2@tests.mozilla.org"], function([t1, t2]) { + t2.userDisabled = false; + + ensure_test_completed(); + do_check_false(hasFlag(t2.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_false(hasFlag(t2.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_check_true(t1.userDisabled); + do_check_false(hasFlag(t1.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_true(hasFlag(t1.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_execute_soon(check_test_1); + }); +} + +function check_test_1() { + restartManager(); + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "theme2/1.0"); + + AddonManager.getAddonsByIDs(["theme1@tests.mozilla.org", + "theme2@tests.mozilla.org"], function([t1, t2]) { + do_check_neq(t1, null); + do_check_true(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_false(t1.isActive); + do_check_false(isThemeInAddonsList(profileDir, t1.id)); + do_check_false(hasFlag(t1.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_true(hasFlag(t1.permissions, AddonManager.PERM_CAN_ENABLE)); + do_check_eq(t1.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_ENABLE); + + do_check_neq(t2, null); + do_check_false(t2.userDisabled); + do_check_false(t2.appDisabled); + do_check_true(t2.isActive); + do_check_true(isThemeInAddonsList(profileDir, t2.id)); + do_check_false(hasFlag(t2.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_false(hasFlag(t2.permissions, AddonManager.PERM_CAN_ENABLE)); + do_check_eq(t2.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_UNINSTALL | + AddonManager.OP_NEEDS_RESTART_DISABLE); + do_check_false(gLWThemeChanged); + + do_execute_soon(run_test_2); + }); +} + +// Removing the active theme should fall back to the default (not ideal in this +// case since we don't have the default theme installed) +function run_test_2() { + var dest = profileDir.clone(); + dest.append(do_get_expected_addon_name("theme2@tests.mozilla.org")); + dest.remove(true); + + restartManager(); + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); + + AddonManager.getAddonsByIDs(["theme1@tests.mozilla.org", + "theme2@tests.mozilla.org"], function([t1, t2]) { + do_check_neq(t1, null); + do_check_true(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_false(t1.isActive); + do_check_false(isThemeInAddonsList(profileDir, t1.id)); + do_check_false(hasFlag(t1.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_true(hasFlag(t1.permissions, AddonManager.PERM_CAN_ENABLE)); + + do_check_eq(t2, null); + do_check_false(isThemeInAddonsList(profileDir, "theme2@tests.mozilla.org")); + do_check_false(gLWThemeChanged); + + do_execute_soon(run_test_3); + }); +} + +// Installing a lightweight theme should happen instantly and disable the default theme +function run_test_3() { + writeInstallRDFForExtension({ + id: "theme2@tests.mozilla.org", + version: "1.0", + name: "Test 1", + internalName: "theme2/1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "2" + }] + }, profileDir); + restartManager(); + + prepare_test({ + "1@personas.mozilla.org": [ + ["onInstalling", false], + "onInstalled", + ["onEnabling", false], + "onEnabled" + ], + "default@tests.mozilla.org": [ + ["onDisabling", false], + "onDisabled", + ] + }, [ + "onExternalInstall" + ]); + + LightweightThemeManager.currentTheme = { + id: "1", + version: "1", + name: "Test LW Theme", + description: "A test theme", + author: "Mozilla", + homepageURL: "http://localhost/data/index.html", + headerURL: "http://localhost/data/header.png", + footerURL: "http://localhost/data/footer.png", + previewURL: "http://localhost/data/preview.png", + iconURL: "http://localhost/data/icon.png" + }; + + ensure_test_completed(); + + AddonManager.getAddonByID("1@personas.mozilla.org", function(p1) { + do_check_neq(null, p1); + do_check_eq(p1.name, "Test LW Theme"); + do_check_eq(p1.version, "1"); + do_check_eq(p1.type, "theme"); + do_check_eq(p1.description, "A test theme"); + do_check_eq(p1.creator, "Mozilla"); + do_check_eq(p1.homepageURL, "http://localhost/data/index.html"); + do_check_eq(p1.iconURL, "http://localhost/data/icon.png"); + do_check_eq(p1.screenshots.length, 1); + do_check_eq(p1.screenshots[0], "http://localhost/data/preview.png"); + do_check_false(p1.appDisabled); + do_check_false(p1.userDisabled); + do_check_true(p1.isCompatible); + do_check_true(p1.providesUpdatesSecurely); + do_check_eq(p1.blocklistState, 0); + do_check_true(p1.isActive); + do_check_eq(p1.pendingOperations, 0); + do_check_eq(p1.permissions, AddonManager.PERM_CAN_UNINSTALL | AddonManager.PERM_CAN_DISABLE); + do_check_eq(p1.scope, AddonManager.SCOPE_PROFILE); + do_check_true("isCompatibleWith" in p1); + do_check_true("findUpdates" in p1); + do_check_eq(p1.installDate.getTime(), p1.updateDate.getTime()); + + // Should have been installed sometime in the last few seconds. + let difference = Date.now() - p1.installDate.getTime(); + if (difference > MAX_INSTALL_TIME) + do_throw("Add-on was installed " + difference + "ms ago"); + else if (difference < 0) + do_throw("Add-on was installed " + difference + "ms in the future"); + + AddonManager.getAddonsByTypes(["theme"], function(addons) { + let seen = false; + addons.forEach(function(a) { + if (a.id == "1@personas.mozilla.org") { + seen = true; + } + else { + dump("Checking theme " + a.id + "\n"); + do_check_false(a.isActive); + do_check_true(a.userDisabled); + } + }); + do_check_true(seen); + + do_check_true(gLWThemeChanged); + gLWThemeChanged = false; + + do_execute_soon(run_test_4); + }); + }); +} + +// Installing a second lightweight theme should disable the first with no restart +function run_test_4() { + prepare_test({ + "1@personas.mozilla.org": [ + ["onDisabling", false], + "onDisabled", + ], + "2@personas.mozilla.org": [ + ["onInstalling", false], + "onInstalled", + ["onEnabling", false], + "onEnabled" + ] + }, [ + "onExternalInstall" + ]); + + LightweightThemeManager.currentTheme = { + id: "2", + version: "1", + name: "Test LW Theme", + description: "A second test theme", + author: "Mozilla", + homepageURL: "http://localhost/data/index.html", + headerURL: "http://localhost/data/header.png", + footerURL: "http://localhost/data/footer.png", + previewURL: "http://localhost/data/preview.png", + iconURL: "http://localhost/data/icon.png" + }; + + ensure_test_completed(); + + AddonManager.getAddonsByIDs(["1@personas.mozilla.org", + "2@personas.mozilla.org"], function([p1, p2]) { + do_check_neq(null, p2); + do_check_false(p2.appDisabled); + do_check_false(p2.userDisabled); + do_check_true(p2.isActive); + do_check_eq(p2.pendingOperations, 0); + do_check_eq(p2.permissions, AddonManager.PERM_CAN_UNINSTALL | AddonManager.PERM_CAN_DISABLE); + do_check_eq(p2.installDate.getTime(), p2.updateDate.getTime()); + + // Should have been installed sometime in the last few seconds. + let difference = Date.now() - p2.installDate.getTime(); + if (difference > MAX_INSTALL_TIME) + do_throw("Add-on was installed " + difference + "ms ago"); + else if (difference < 0) + do_throw("Add-on was installed " + difference + "ms in the future"); + + do_check_neq(null, p1); + do_check_false(p1.appDisabled); + do_check_true(p1.userDisabled); + do_check_false(p1.isActive); + do_check_eq(p1.pendingOperations, 0); + do_check_eq(p1.permissions, AddonManager.PERM_CAN_UNINSTALL | AddonManager.PERM_CAN_ENABLE); + + AddonManager.getAddonsByTypes(["theme"], function(addons) { + let seen = false; + addons.forEach(function(a) { + if (a.id == "2@personas.mozilla.org") { + seen = true; + } + else { + dump("Checking theme " + a.id + "\n"); + do_check_false(a.isActive); + do_check_true(a.userDisabled); + } + }); + do_check_true(seen); + + do_check_true(gLWThemeChanged); + gLWThemeChanged = false; + + do_execute_soon(run_test_5); + }); + }); +} + +// Switching to a custom theme should disable the lightweight theme and require +// a restart. Cancelling that should also be possible. +function run_test_5() { + prepare_test({ + "2@personas.mozilla.org": [ + "onDisabling", + ], + "theme2@tests.mozilla.org": [ + "onEnabling" + ] + }); + + AddonManager.getAddonsByIDs(["2@personas.mozilla.org", + "theme2@tests.mozilla.org"], function([p2, t2]) { + t2.userDisabled = false; + + ensure_test_completed(); + + prepare_test({ + "2@personas.mozilla.org": [ + "onOperationCancelled", + ], + "theme2@tests.mozilla.org": [ + "onOperationCancelled" + ] + }); + + p2.userDisabled = false; + + ensure_test_completed(); + + prepare_test({ + "2@personas.mozilla.org": [ + "onDisabling", + ], + "theme2@tests.mozilla.org": [ + "onEnabling" + ] + }); + + t2.userDisabled = false; + + ensure_test_completed(); + + do_check_false(t2.isActive); + do_check_false(t2.userDisabled); + do_check_true(hasFlag(AddonManager.PENDING_ENABLE, t2.pendingOperations)); + do_check_true(p2.isActive); + do_check_true(p2.userDisabled); + do_check_true(hasFlag(AddonManager.PENDING_DISABLE, p2.pendingOperations)); + do_check_true(hasFlag(AddonManager.PERM_CAN_ENABLE, p2.permissions)); + do_check_false(gLWThemeChanged); + + do_execute_soon(check_test_5); + }); +} + +function check_test_5() { + restartManager(); + + AddonManager.getAddonsByIDs(["2@personas.mozilla.org", + "theme2@tests.mozilla.org"], function([p2, t2]) { + do_check_true(t2.isActive); + do_check_false(t2.userDisabled); + do_check_false(hasFlag(AddonManager.PENDING_ENABLE, t2.pendingOperations)); + do_check_false(p2.isActive); + do_check_true(p2.userDisabled); + do_check_false(hasFlag(AddonManager.PENDING_DISABLE, p2.pendingOperations)); + + do_check_true(gLWThemeChanged); + gLWThemeChanged = false; + + do_execute_soon(run_test_6); + }); +} + +// Switching from a custom theme to a lightweight theme should require a restart +function run_test_6() { + prepare_test({ + "2@personas.mozilla.org": [ + "onEnabling", + ], + "theme2@tests.mozilla.org": [ + "onDisabling" + ] + }); + + AddonManager.getAddonsByIDs(["2@personas.mozilla.org", + "theme2@tests.mozilla.org"], function([p2, t2]) { + p2.userDisabled = false; + + ensure_test_completed(); + + prepare_test({ + "2@personas.mozilla.org": [ + "onOperationCancelled", + ], + "theme2@tests.mozilla.org": [ + "onOperationCancelled" + ] + }); + + t2.userDisabled = false; + + ensure_test_completed(); + + prepare_test({ + "2@personas.mozilla.org": [ + "onEnabling", + ], + "theme2@tests.mozilla.org": [ + "onDisabling" + ] + }); + + p2.userDisabled = false; + + ensure_test_completed(); + + do_check_false(p2.isActive); + do_check_false(p2.userDisabled); + do_check_true(hasFlag(AddonManager.PENDING_ENABLE, p2.pendingOperations)); + do_check_true(t2.isActive); + do_check_true(t2.userDisabled); + do_check_true(hasFlag(AddonManager.PENDING_DISABLE, t2.pendingOperations)); + do_check_false(gLWThemeChanged); + + do_execute_soon(check_test_6); + }); +} + +function check_test_6() { + restartManager(); + + AddonManager.getAddonsByIDs(["2@personas.mozilla.org", + "theme2@tests.mozilla.org"], function([p2, t2]) { + do_check_true(p2.isActive); + do_check_false(p2.userDisabled); + do_check_false(hasFlag(AddonManager.PENDING_ENABLE, p2.pendingOperations)); + do_check_false(t2.isActive); + do_check_true(t2.userDisabled); + do_check_false(hasFlag(AddonManager.PENDING_DISABLE, t2.pendingOperations)); + + do_check_true(gLWThemeChanged); + gLWThemeChanged = false; + + do_execute_soon(run_test_7); + }); +} + +// Uninstalling a lightweight theme should not require a restart +function run_test_7() { + prepare_test({ + "1@personas.mozilla.org": [ + ["onUninstalling", false], + "onUninstalled" + ] + }); + + AddonManager.getAddonByID("1@personas.mozilla.org", function(p1) { + p1.uninstall(); + + ensure_test_completed(); + do_check_eq(LightweightThemeManager.usedThemes.length, 1); + do_check_false(gLWThemeChanged); + + do_execute_soon(run_test_8); + }); +} + +// Uninstalling a lightweight theme in use should not require a restart and it +// should reactivate the default theme +// Also, uninstalling a lightweight theme in use should send a +// "lightweight-theme-styling-update" notification through the observer service +function run_test_8() { + prepare_test({ + "2@personas.mozilla.org": [ + ["onUninstalling", false], + "onUninstalled" + ], + "default@tests.mozilla.org": [ + ["onEnabling", false], + "onEnabled" + ] + }); + + AddonManager.getAddonByID("2@personas.mozilla.org", function(p2) { + p2.uninstall(); + + ensure_test_completed(); + do_check_eq(LightweightThemeManager.usedThemes.length, 0); + + do_check_true(gLWThemeChanged); + gLWThemeChanged = false; + + do_execute_soon(run_test_9); + }); +} + +// Uninstalling a theme not in use should not require a restart +function run_test_9() { + AddonManager.getAddonByID("theme1@tests.mozilla.org", function(t1) { + prepare_test({ + "theme1@tests.mozilla.org": [ + ["onUninstalling", false], + "onUninstalled" + ] + }); + + t1.uninstall(); + + ensure_test_completed(); + + AddonManager.getAddonByID("theme1@tests.mozilla.org", function(newt1) { + do_check_eq(newt1, null); + do_check_false(gLWThemeChanged); + + do_execute_soon(run_test_10); + }); + }); +} + +// Uninstalling a custom theme in use should require a restart +function run_test_10() { + AddonManager.getAddonByID("theme2@tests.mozilla.org", callback_soon(function(oldt2) { + prepare_test({ + "theme2@tests.mozilla.org": [ + "onEnabling", + ], + "default@tests.mozilla.org": [ + "onDisabling" + ] + }); + + oldt2.userDisabled = false; + + ensure_test_completed(); + + restartManager(); + + AddonManager.getAddonsByIDs(["default@tests.mozilla.org", + "theme2@tests.mozilla.org"], function([d, t2]) { + do_check_true(t2.isActive); + do_check_false(t2.userDisabled); + do_check_false(t2.appDisabled); + do_check_false(d.isActive); + do_check_true(d.userDisabled); + do_check_false(d.appDisabled); + + prepare_test({ + "theme2@tests.mozilla.org": [ + "onUninstalling", + ], + "default@tests.mozilla.org": [ + "onEnabling" + ] + }); + + t2.uninstall(); + + ensure_test_completed(); + do_check_false(gLWThemeChanged); + + do_execute_soon(run_test_11); + }); + })); +} + +// Installing a custom theme not in use should not require a restart +function run_test_11() { + restartManager(); + + prepare_test({ }, [ + "onNewInstall" + ]); + + AddonManager.getInstallForFile(do_get_addon("test_theme"), function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + do_check_eq(install.type, "theme"); + do_check_eq(install.version, "1.0"); + do_check_eq(install.name, "Test Theme 1"); + do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); + do_check_true(install.addon.skinnable, true); + do_check_false(hasFlag(install.addon.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_INSTALL)); + + prepare_test({ + "theme1@tests.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], check_test_11); + install.install(); + }); +} + +function check_test_11() { + AddonManager.getAddonByID("theme1@tests.mozilla.org", function(t1) { + do_check_neq(t1, null); + var previewSpec = do_get_addon_root_uri(profileDir, "theme1@tests.mozilla.org") + "preview.png"; + do_check_eq(t1.screenshots.length, 1); + do_check_eq(t1.screenshots[0], previewSpec); + do_check_true(t1.skinnable); + do_check_false(gLWThemeChanged); + + do_execute_soon(run_test_12); + }); +} + +// Updating a custom theme not in use should not require a restart +function run_test_12() { + prepare_test({ }, [ + "onNewInstall" + ]); + + AddonManager.getInstallForFile(do_get_addon("test_theme"), function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + do_check_eq(install.type, "theme"); + do_check_eq(install.version, "1.0"); + do_check_eq(install.name, "Test Theme 1"); + do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); + do_check_false(hasFlag(install.addon.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_INSTALL)); + + prepare_test({ + "theme1@tests.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], check_test_12); + install.install(); + }); +} + +function check_test_12() { + AddonManager.getAddonByID("theme1@tests.mozilla.org", function(t1) { + do_check_neq(t1, null); + do_check_false(gLWThemeChanged); + + do_execute_soon(run_test_13); + }); +} + +// Updating a custom theme in use should require a restart +function run_test_13() { + AddonManager.getAddonByID("theme1@tests.mozilla.org", callback_soon(function(t1) { + prepare_test({ + "theme1@tests.mozilla.org": [ + "onEnabling", + ], + "default@tests.mozilla.org": [ + "onDisabling" + ] + }); + + t1.userDisabled = false; + ensure_test_completed(); + restartManager(); + + prepare_test({ }, [ + "onNewInstall" + ]); + + AddonManager.getInstallForFile(do_get_addon("test_theme"), function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + do_check_eq(install.type, "theme"); + do_check_eq(install.version, "1.0"); + do_check_eq(install.name, "Test Theme 1"); + do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); + do_check_true(hasFlag(install.addon.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_INSTALL)); + + prepare_test({ + "theme1@tests.mozilla.org": [ + "onInstalling", + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], callback_soon(check_test_13)); + install.install(); + }); + })); +} + +function check_test_13() { + restartManager(); + + AddonManager.getAddonByID("theme1@tests.mozilla.org", callback_soon(function(t1) { + do_check_neq(t1, null); + do_check_true(t1.isActive); + do_check_false(gLWThemeChanged); + t1.uninstall(); + restartManager(); + + do_execute_soon(run_test_14); + })); +} + +// Switching from a lightweight theme to the default theme should not require +// a restart +function run_test_14() { + LightweightThemeManager.currentTheme = { + id: "1", + version: "1", + name: "Test LW Theme", + description: "A test theme", + author: "Mozilla", + homepageURL: "http://localhost/data/index.html", + headerURL: "http://localhost/data/header.png", + footerURL: "http://localhost/data/footer.png", + previewURL: "http://localhost/data/preview.png", + iconURL: "http://localhost/data/icon.png" + }; + + AddonManager.getAddonByID("default@tests.mozilla.org", function(d) { + do_check_true(d.userDisabled); + do_check_false(d.isActive); + + prepare_test({ + "1@personas.mozilla.org": [ + ["onDisabling", false], + "onDisabled" + ], + "default@tests.mozilla.org": [ + ["onEnabling", false], + "onEnabled" + ] + }); + + d.userDisabled = false; + ensure_test_completed(); + + do_check_false(d.userDisabled); + do_check_true(d.isActive); + + do_check_true(gLWThemeChanged); + gLWThemeChanged = false; + + do_execute_soon(run_test_15); + }); +} + +// Upgrading the application with a custom theme in use should not disable it +function run_test_15() { + restartManager(); + + installAllFiles([do_get_addon("test_theme")], function() { + AddonManager.getAddonByID("theme1@tests.mozilla.org", callback_soon(function(t1) { + t1.userDisabled = false; + + restartManager(); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "theme1/1.0"); + AddonManager.getAddonsByIDs(["default@tests.mozilla.org", + "theme1@tests.mozilla.org"], + callback_soon(function([d, t1]) { + do_check_true(d.userDisabled); + do_check_false(d.appDisabled); + do_check_false(d.isActive); + + do_check_false(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_true(t1.isActive); + + restartManager("2"); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "theme1/1.0"); + AddonManager.getAddonsByIDs(["default@tests.mozilla.org", + "theme1@tests.mozilla.org"], function([d, t1]) { + do_check_true(d.userDisabled); + do_check_false(d.appDisabled); + do_check_false(d.isActive); + + do_check_false(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_true(t1.isActive); + + do_execute_soon(run_test_16); + }); + })); + })); + }); +} + +// Upgrading the application with a custom theme in use should disable it if it +// is no longer compatible +function run_test_16() { + restartManager("3"); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); + AddonManager.getAddonsByIDs(["default@tests.mozilla.org", + "theme1@tests.mozilla.org"], function([d, t1]) { + do_check_false(d.userDisabled); + do_check_false(d.appDisabled); + do_check_true(d.isActive); + + do_check_true(t1.userDisabled); + do_check_true(t1.appDisabled); + do_check_false(t1.isActive); + + do_execute_soon(run_test_17); + }); +} + +// Verifies that if the selected theme pref is changed by a different version +// of the application that we correctly reset it when it points to an +// incompatible theme +function run_test_17() { + restartManager("2"); + shutdownManager(); + + Services.prefs.setCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN, "theme1/1.0"); + + restartManager("3"); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); + AddonManager.getAddonsByIDs(["default@tests.mozilla.org", + "theme1@tests.mozilla.org"], function([d, t1]) { + do_check_false(d.userDisabled); + do_check_false(d.appDisabled); + do_check_true(d.isActive); + + do_check_true(t1.userDisabled); + do_check_true(t1.appDisabled); + do_check_false(t1.isActive); + + do_execute_soon(run_test_18); + }); +} + +// Disabling the active theme should switch back to the default theme +function run_test_18() { + restartManager(2); + + AddonManager.getAddonByID("theme1@tests.mozilla.org", callback_soon(function(t1) { + t1.userDisabled = false; + + restartManager(); + + AddonManager.getAddonsByIDs(["default@tests.mozilla.org", + "theme1@tests.mozilla.org"], + callback_soon(function([d, t1]) { + do_check_true(d.userDisabled); + do_check_false(d.appDisabled); + do_check_false(d.isActive); + + do_check_false(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_true(t1.isActive); + + prepare_test({ + "theme1@tests.mozilla.org": [ + "onDisabling", + ], + "default@tests.mozilla.org": [ + "onEnabling", + ] + }); + t1.userDisabled = true; + ensure_test_completed(); + + do_check_false(d.userDisabled); + do_check_false(d.appDisabled); + do_check_false(d.isActive); + + do_check_true(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_true(t1.isActive); + + restartManager(); + + AddonManager.getAddonsByIDs(["default@tests.mozilla.org", + "theme1@tests.mozilla.org"], function([d, t1]) { + do_check_false(d.userDisabled); + do_check_false(d.appDisabled); + do_check_true(d.isActive); + + do_check_true(t1.userDisabled); + do_check_false(t1.appDisabled); + do_check_false(t1.isActive); + + do_execute_soon(run_test_19); + }); + })); + })); +} + +// Disabling the active persona should switch back to the default theme +function run_test_19() { + AddonManager.getAddonsByIDs(["default@tests.mozilla.org", + "1@personas.mozilla.org"], function([d, p1]) { + p1.userDisabled = false; + + do_check_true(d.userDisabled); + do_check_false(d.appDisabled); + do_check_false(d.isActive); + + do_check_false(p1.userDisabled); + do_check_false(p1.appDisabled); + do_check_true(p1.isActive); + + prepare_test({ + "1@personas.mozilla.org": [ + ["onDisabling", false], + "onDisabled" + ], + "default@tests.mozilla.org": [ + ["onEnabling", false], + "onEnabled" + ] + }); + p1.userDisabled = true; + ensure_test_completed(); + + do_check_false(d.userDisabled); + do_check_false(d.appDisabled); + do_check_true(d.isActive); + + do_check_true(p1.userDisabled); + do_check_false(p1.appDisabled); + do_check_false(p1.isActive); + + do_execute_soon(run_test_20); + }); +} + +// Tests that you cannot disable the default theme +function run_test_20() { + AddonManager.getAddonByID("default@tests.mozilla.org", function(d) { + do_check_false(d.userDisabled); + do_check_false(d.appDisabled); + do_check_true(d.isActive); + + try { + d.userDisabled = true; + do_throw("Disabling the default theme should throw an exception"); + } + catch (e) { + } + + do_execute_soon(run_test_21); + }); +} + +// Tests that cached copies of a lightweight theme have the right permissions +// and pendingOperations during the onEnabling event +function run_test_21() { + AddonManager.getAddonByID("theme1@tests.mozilla.org", callback_soon(function(t1) { + // Switch to a custom theme so we can test pendingOperations properly. + + prepare_test({ + "theme1@tests.mozilla.org": [ + "onEnabling" + ], + "default@tests.mozilla.org": [ + "onDisabling" + ] + }); + + t1.userDisabled = false; + ensure_test_completed(); + + restartManager(); + + AddonManager.getAddonByID("1@personas.mozilla.org", function(p1) { + AddonManager.addAddonListener({ + onEnabling: function(aAddon) { + do_check_false(hasFlag(aAddon.permissions, AddonManager.PERM_CAN_ENABLE)); + do_check_true(hasFlag(aAddon.pendingOperations, AddonManager.PENDING_ENABLE)); + + do_check_eq(aAddon.permissions, p1.permissions); + do_check_eq(aAddon.pendingOperations, p1.pendingOperations); + } + }); + + prepare_test({ + "1@personas.mozilla.org": [ + "onEnabling" + ], + "theme1@tests.mozilla.org": [ + "onDisabling" + ] + }); + + p1.userDisabled = false; + ensure_test_completed(); + + end_test(); + }); + })); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_types.js b/toolkit/mozapps/extensions/test/xpcshell/test_types.js new file mode 100644 index 000000000..679f4808c --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_types.js @@ -0,0 +1,65 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that custom types can be defined and undefined + +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + +function run_test() { + startupManager(); + + do_check_false("test" in AddonManager.addonTypes); + let types = AddonManager.addonTypes; + + // The dumbest provider possible + var provider = { + }; + + var expectedAdd = "test"; + var expectedRemove = null; + + AddonManager.addTypeListener({ + onTypeAdded: function(aType) { + do_check_eq(aType.id, expectedAdd); + expectedAdd = null; + }, + + onTypeRemoved: function(aType) { + do_check_eq(aType.id, expectedRemove); + expectedRemove = null; + } + }); + + AddonManagerPrivate.registerProvider(provider, [{ + id: "test", + name: "Test", + uiPriority: 1 + }, { + id: "t$e%st", + name: "Test", + uiPriority: 1 + }]); + + do_check_eq(expectedAdd, null); + + do_check_true("test" in types); + do_check_eq(types["test"].name, "Test"); + do_check_false("t$e%st" in types); + + delete types["test"]; + do_check_true("test" in types); + + types["foo"] = "bar"; + do_check_false("foo" in types); + + expectedRemove = "test"; + + AddonManagerPrivate.unregisterProvider(provider); + + do_check_eq(expectedRemove, null); + + do_check_false("test" in AddonManager.addonTypes); + // The cached reference to addonTypes is live + do_check_false("test" in types); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_undothemeuninstall.js b/toolkit/mozapps/extensions/test/xpcshell/test_undothemeuninstall.js new file mode 100644 index 000000000..c804b3bd6 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_undothemeuninstall.js @@ -0,0 +1,421 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that forcing undo for uninstall works for themes +Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm"); + +const PREF_GENERAL_SKINS_SELECTEDSKIN = "general.skins.selectedSkin"; + +var defaultTheme = { + id: "default@tests.mozilla.org", + version: "1.0", + name: "Test 1", + internalName: "classic/1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +var theme1 = { + id: "theme1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + internalName: "theme1", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +function dummyLWTheme(id) { + return { + id: id || Math.random().toString(), + name: Math.random().toString(), + headerURL: "http://lwttest.invalid/a.png", + footerURL: "http://lwttest.invalid/b.png", + textcolor: Math.random().toString(), + accentcolor: Math.random().toString() + }; +} + +// Sets up the profile by installing an add-on. +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + startupManager(); + do_register_cleanup(promiseShutdownManager); + + run_next_test(); +} + +add_task(function* checkDefault() { + writeInstallRDFForExtension(defaultTheme, profileDir); + yield promiseRestartManager(); + + let d = yield promiseAddonByID("default@tests.mozilla.org"); + + do_check_neq(d, null); + do_check_true(d.isActive); + do_check_false(d.userDisabled); + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); +}); + +// Tests that uninstalling an enabled theme offers the option to undo +add_task(function* uninstallEnabledOffersUndo() { + writeInstallRDFForExtension(theme1, profileDir); + + yield promiseRestartManager(); + + let t1 = yield promiseAddonByID("theme1@tests.mozilla.org"); + + do_check_neq(t1, null); + do_check_true(t1.userDisabled); + + t1.userDisabled = false; + + yield promiseRestartManager(); + + let d = null; + [ t1, d ] = yield promiseAddonsByIDs(["theme1@tests.mozilla.org", + "default@tests.mozilla.org"]); + do_check_neq(d, null); + do_check_false(d.isActive); + do_check_true(d.userDisabled); + do_check_eq(d.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(t1, null); + do_check_true(t1.isActive); + do_check_false(t1.userDisabled); + do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "theme1"); + + prepare_test({ + "default@tests.mozilla.org": [ + "onEnabling" + ], + "theme1@tests.mozilla.org": [ + "onUninstalling" + ] + }); + t1.uninstall(true); + ensure_test_completed(); + + do_check_neq(d, null); + do_check_false(d.isActive); + do_check_false(d.userDisabled); + do_check_eq(d.pendingOperations, AddonManager.PENDING_ENABLE); + + do_check_true(t1.isActive); + do_check_false(t1.userDisabled); + do_check_true(hasFlag(t1.pendingOperations, AddonManager.PENDING_UNINSTALL)); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "theme1"); + + yield promiseRestartManager(); + + [ t1, d ] = yield promiseAddonsByIDs(["theme1@tests.mozilla.org", + "default@tests.mozilla.org"]); + do_check_neq(d, null); + do_check_true(d.isActive); + do_check_false(d.userDisabled); + do_check_eq(d.pendingOperations, AddonManager.PENDING_NONE); + + do_check_eq(t1, null); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); +}); + +//Tests that uninstalling an enabled theme can be undone +add_task(function* canUndoUninstallEnabled() { + writeInstallRDFForExtension(theme1, profileDir); + + yield promiseRestartManager(); + + let t1 = yield promiseAddonByID("theme1@tests.mozilla.org"); + + do_check_neq(t1, null); + do_check_true(t1.userDisabled); + + t1.userDisabled = false; + + yield promiseRestartManager(); + + let d = null; + [ t1, d ] = yield promiseAddonsByIDs(["theme1@tests.mozilla.org", + "default@tests.mozilla.org"]); + + do_check_neq(d, null); + do_check_false(d.isActive); + do_check_true(d.userDisabled); + do_check_eq(d.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(t1, null); + do_check_true(t1.isActive); + do_check_false(t1.userDisabled); + do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "theme1"); + + prepare_test({ + "default@tests.mozilla.org": [ + "onEnabling" + ], + "theme1@tests.mozilla.org": [ + "onUninstalling" + ] + }); + t1.uninstall(true); + ensure_test_completed(); + + do_check_neq(d, null); + do_check_false(d.isActive); + do_check_false(d.userDisabled); + do_check_eq(d.pendingOperations, AddonManager.PENDING_ENABLE); + + do_check_true(t1.isActive); + do_check_false(t1.userDisabled); + do_check_true(hasFlag(t1.pendingOperations, AddonManager.PENDING_UNINSTALL)); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "theme1"); + + prepare_test({ + "default@tests.mozilla.org": [ + "onOperationCancelled" + ], + "theme1@tests.mozilla.org": [ + "onOperationCancelled" + ] + }); + t1.cancelUninstall(); + ensure_test_completed(); + + do_check_neq(d, null); + do_check_false(d.isActive); + do_check_true(d.userDisabled); + do_check_eq(d.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(t1, null); + do_check_true(t1.isActive); + do_check_false(t1.userDisabled); + do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE); + + yield promiseRestartManager(); + + [ t1, d ] = yield promiseAddonsByIDs(["theme1@tests.mozilla.org", + "default@tests.mozilla.org"]); + + do_check_neq(d, null); + do_check_false(d.isActive); + do_check_true(d.userDisabled); + do_check_eq(d.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(t1, null); + do_check_true(t1.isActive); + do_check_false(t1.userDisabled); + do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "theme1"); + + t1.uninstall(); + yield promiseRestartManager(); +}); + +//Tests that uninstalling a disabled theme offers the option to undo +add_task(function* uninstallDisabledOffersUndo() { + writeInstallRDFForExtension(theme1, profileDir); + + yield promiseRestartManager(); + + let [ t1, d ] = yield promiseAddonsByIDs(["theme1@tests.mozilla.org", + "default@tests.mozilla.org"]); + + do_check_neq(d, null); + do_check_true(d.isActive); + do_check_false(d.userDisabled); + do_check_eq(d.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(t1, null); + do_check_false(t1.isActive); + do_check_true(t1.userDisabled); + do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); + + prepare_test({ + "theme1@tests.mozilla.org": [ + "onUninstalling" + ] + }); + t1.uninstall(true); + ensure_test_completed(); + + do_check_neq(d, null); + do_check_true(d.isActive); + do_check_false(d.userDisabled); + do_check_eq(d.pendingOperations, AddonManager.PENDING_NONE); + + do_check_false(t1.isActive); + do_check_true(t1.userDisabled); + do_check_true(hasFlag(t1.pendingOperations, AddonManager.PENDING_UNINSTALL)); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); + + yield promiseRestartManager(); + + [ t1, d ] = yield promiseAddonsByIDs(["theme1@tests.mozilla.org", + "default@tests.mozilla.org"]); + + do_check_neq(d, null); + do_check_true(d.isActive); + do_check_false(d.userDisabled); + do_check_eq(d.pendingOperations, AddonManager.PENDING_NONE); + + do_check_eq(t1, null); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); +}); + +//Tests that uninstalling a disabled theme can be undone +add_task(function* canUndoUninstallDisabled() { + writeInstallRDFForExtension(theme1, profileDir); + + yield promiseRestartManager(); + + let [ t1, d ] = yield promiseAddonsByIDs(["theme1@tests.mozilla.org", + "default@tests.mozilla.org"]); + + do_check_neq(d, null); + do_check_true(d.isActive); + do_check_false(d.userDisabled); + do_check_eq(d.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(t1, null); + do_check_false(t1.isActive); + do_check_true(t1.userDisabled); + do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); + + prepare_test({ + "theme1@tests.mozilla.org": [ + "onUninstalling" + ] + }); + t1.uninstall(true); + ensure_test_completed(); + + do_check_neq(d, null); + do_check_true(d.isActive); + do_check_false(d.userDisabled); + do_check_eq(d.pendingOperations, AddonManager.PENDING_NONE); + + do_check_false(t1.isActive); + do_check_true(t1.userDisabled); + do_check_true(hasFlag(t1.pendingOperations, AddonManager.PENDING_UNINSTALL)); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); + + prepare_test({ + "theme1@tests.mozilla.org": [ + "onOperationCancelled" + ] + }); + t1.cancelUninstall(); + ensure_test_completed(); + + do_check_neq(d, null); + do_check_true(d.isActive); + do_check_false(d.userDisabled); + do_check_eq(d.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(t1, null); + do_check_false(t1.isActive); + do_check_true(t1.userDisabled); + do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE); + + yield promiseRestartManager(); + + [ t1, d ] = yield promiseAddonsByIDs(["theme1@tests.mozilla.org", + "default@tests.mozilla.org"]); + + do_check_neq(d, null); + do_check_true(d.isActive); + do_check_false(d.userDisabled); + do_check_eq(d.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(t1, null); + do_check_false(t1.isActive); + do_check_true(t1.userDisabled); + do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); + + t1.uninstall(); + yield promiseRestartManager(); +}); + +//Tests that uninstalling an enabled lightweight theme offers the option to undo +add_task(function* uninstallLWTOffersUndo() { + // skipped since lightweight themes don't support undoable uninstall yet + return; + LightweightThemeManager.currentTheme = dummyLWTheme("theme1"); + + let [ t1, d ] = yield promiseAddonsByIDs(["theme1@personas.mozilla.org", + "default@tests.mozilla.org"]); + + do_check_neq(d, null); + do_check_false(d.isActive); + do_check_true(d.userDisabled); + do_check_eq(d.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(t1, null); + do_check_true(t1.isActive); + do_check_false(t1.userDisabled); + do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); + + prepare_test({ + "default@tests.mozilla.org": [ + "onEnabling" + ], + "theme1@personas.mozilla.org": [ + "onUninstalling" + ] + }); + t1.uninstall(true); + ensure_test_completed(); + + do_check_neq(d, null); + do_check_false(d.isActive); + do_check_false(d.userDisabled); + do_check_eq(d.pendingOperations, AddonManager.PENDING_ENABLE); + + do_check_true(t1.isActive); + do_check_false(t1.userDisabled); + do_check_true(hasFlag(t1.pendingOperations, AddonManager.PENDING_UNINSTALL)); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); + + yield promiseRestartManager(); + + [ t1, d ] = yield promiseAddonsByIDs(["theme1@personas.mozilla.org", + "default@tests.mozilla.org"]); + + do_check_neq(d, null); + do_check_true(d.isActive); + do_check_false(d.userDisabled); + do_check_eq(d.pendingOperations, AddonManager.PENDING_NONE); + + do_check_eq(t1, null); + + do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_undouninstall.js b/toolkit/mozapps/extensions/test/xpcshell/test_undouninstall.js new file mode 100644 index 000000000..a589361b6 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_undouninstall.js @@ -0,0 +1,792 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that forcing undo for uninstall works + +const APP_STARTUP = 1; +const APP_SHUTDOWN = 2; +const ADDON_ENABLE = 3; +const ADDON_DISABLE = 4; +const ADDON_INSTALL = 5; +const ADDON_UNINSTALL = 6; +const ADDON_UPGRADE = 7; +const ADDON_DOWNGRADE = 8; + +const ID = "undouninstall1@tests.mozilla.org"; +const INCOMPAT_ID = "incompatible@tests.mozilla.org"; + +var addon1 = { + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +BootstrapMonitor.init(); + +function getStartupReason(id) { + let info = BootstrapMonitor.started.get(id); + return info ? info.reason : undefined; +} + +function getShutdownReason(id) { + let info = BootstrapMonitor.stopped.get(id); + return info ? info.reason : undefined; +} + +function getInstallReason(id) { + let info = BootstrapMonitor.installed.get(id); + return info ? info.reason : undefined; +} + +function getUninstallReason(id) { + let info = BootstrapMonitor.uninstalled.get(id); + return info ? info.reason : undefined; +} + +function getStartupOldVersion(id) { + let info = BootstrapMonitor.started.get(id); + return info ? info.data.oldVersion : undefined; +} + +function getShutdownNewVersion(id) { + let info = BootstrapMonitor.stopped.get(id); + return info ? info.data.newVersion : undefined; +} + +function getInstallOldVersion(id) { + let info = BootstrapMonitor.installed.get(id); + return info ? info.data.oldVersion : undefined; +} + +function getUninstallNewVersion(id) { + let info = BootstrapMonitor.uninstalled.get(id); + return info ? info.data.newVersion : undefined; +} + +// Sets up the profile by installing an add-on. +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + startupManager(); + do_register_cleanup(promiseShutdownManager); + + run_next_test(); +} + +add_task(function* installAddon() { + let olda1 = yield promiseAddonByID("addon1@tests.mozilla.org"); + + do_check_eq(olda1, null); + + writeInstallRDFForExtension(addon1, profileDir); + yield promiseRestartManager(); + + let a1 = yield promiseAddonByID("addon1@tests.mozilla.org"); + + do_check_neq(a1, null); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); + do_check_eq(a1.pendingOperations, 0); + do_check_in_crash_annotation(addon1.id, addon1.version); +}); + +// Uninstalling an add-on should work. +add_task(function* uninstallAddon() { + prepare_test({ + "addon1@tests.mozilla.org": [ + "onUninstalling" + ] + }); + + let a1 = yield promiseAddonByID("addon1@tests.mozilla.org"); + + do_check_eq(a1.pendingOperations, 0); + do_check_neq(a1.operationsRequiringRestart & + AddonManager.OP_NEEDS_RESTART_UNINSTALL, 0); + a1.uninstall(true); + do_check_true(hasFlag(a1.pendingOperations, AddonManager.PENDING_UNINSTALL)); + do_check_in_crash_annotation(addon1.id, addon1.version); + + ensure_test_completed(); + + let list = yield promiseAddonsWithOperationsByTypes(null); + + do_check_eq(list.length, 1); + do_check_eq(list[0].id, "addon1@tests.mozilla.org"); + + yield promiseRestartManager(); + + a1 = yield promiseAddonByID("addon1@tests.mozilla.org"); + + do_check_eq(a1, null); + do_check_false(isExtensionInAddonsList(profileDir, "addon1@tests.mozilla.org")); + do_check_not_in_crash_annotation(addon1.id, addon1.version); + + var dest = profileDir.clone(); + dest.append(do_get_expected_addon_name("addon1@tests.mozilla.org")); + do_check_false(dest.exists()); + writeInstallRDFForExtension(addon1, profileDir); + yield promiseRestartManager(); +}); + +// Cancelling the uninstall should send onOperationCancelled +add_task(function* cancelUninstall() { + prepare_test({ + "addon1@tests.mozilla.org": [ + "onUninstalling" + ] + }); + + let a1 = yield promiseAddonByID("addon1@tests.mozilla.org"); + + do_check_neq(a1, null); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); + do_check_eq(a1.pendingOperations, 0); + a1.uninstall(true); + do_check_true(hasFlag(a1.pendingOperations, AddonManager.PENDING_UNINSTALL)); + + ensure_test_completed(); + + prepare_test({ + "addon1@tests.mozilla.org": [ + "onOperationCancelled" + ] + }); + a1.cancelUninstall(); + do_check_eq(a1.pendingOperations, 0); + + ensure_test_completed(); + yield promiseRestartManager(); + + a1 = yield promiseAddonByID("addon1@tests.mozilla.org"); + + do_check_neq(a1, null); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); +}); + +// Uninstalling an item pending disable should still require a restart +add_task(function* pendingDisableRequestRestart() { + let a1 = yield promiseAddonByID("addon1@tests.mozilla.org"); + + prepare_test({ + "addon1@tests.mozilla.org": [ + "onDisabling" + ] + }); + a1.userDisabled = true; + ensure_test_completed(); + + do_check_true(hasFlag(AddonManager.PENDING_DISABLE, a1.pendingOperations)); + do_check_true(a1.isActive); + + prepare_test({ + "addon1@tests.mozilla.org": [ + "onUninstalling" + ] + }); + a1.uninstall(true); + + ensure_test_completed(); + + a1 = yield promiseAddonByID("addon1@tests.mozilla.org"); + + do_check_neq(a1, null); + do_check_true(hasFlag(AddonManager.PENDING_UNINSTALL, a1.pendingOperations)); + + prepare_test({ + "addon1@tests.mozilla.org": [ + "onOperationCancelled" + ] + }); + a1.cancelUninstall(); + ensure_test_completed(); + do_check_true(hasFlag(AddonManager.PENDING_DISABLE, a1.pendingOperations)); + + yield promiseRestartManager(); +}); + +// Test that uninstalling an inactive item should still allow cancelling +add_task(function* uninstallInactiveIsCancellable() { + let a1 = yield promiseAddonByID("addon1@tests.mozilla.org"); + + do_check_neq(a1, null); + do_check_false(a1.isActive); + do_check_true(a1.userDisabled); + do_check_false(isExtensionInAddonsList(profileDir, a1.id)); + + prepare_test({ + "addon1@tests.mozilla.org": [ + "onUninstalling" + ] + }); + a1.uninstall(true); + ensure_test_completed(); + + a1 = yield promiseAddonByID("addon1@tests.mozilla.org"); + + do_check_neq(a1, null); + do_check_true(hasFlag(AddonManager.PENDING_UNINSTALL, a1.pendingOperations)); + + prepare_test({ + "addon1@tests.mozilla.org": [ + "onOperationCancelled" + ] + }); + a1.cancelUninstall(); + ensure_test_completed(); + + yield promiseRestartManager(); +}); + +//Test that an inactive item can be uninstalled +add_task(function* uninstallInactive() { + let a1 = yield promiseAddonByID("addon1@tests.mozilla.org"); + + do_check_neq(a1, null); + do_check_false(a1.isActive); + do_check_true(a1.userDisabled); + do_check_false(isExtensionInAddonsList(profileDir, a1.id)); + + prepare_test({ + "addon1@tests.mozilla.org": [ + [ "onUninstalling", false ], + "onUninstalled" + ] + }); + a1.uninstall(); + ensure_test_completed(); + + a1 = yield promiseAddonByID("addon1@tests.mozilla.org"); + do_check_eq(a1, null); +}); + +// Tests that an enabled restartless add-on can be uninstalled and goes away +// when the uninstall is committed +add_task(function* uninstallRestartless() { + prepare_test({ + "undouninstall1@tests.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ] + }, [ + "onNewInstall", + "onInstallStarted", + "onInstallEnded" + ]); + yield promiseInstallAllFiles([do_get_addon("test_undouninstall1")]); + ensure_test_completed(); + + let a1 = yield promiseAddonByID(ID); + + do_check_neq(a1, null); + BootstrapMonitor.checkAddonInstalled(ID, "1.0"); + BootstrapMonitor.checkAddonStarted(ID, "1.0"); + do_check_eq(getInstallReason(ID), ADDON_INSTALL); + do_check_eq(getStartupReason(ID), ADDON_INSTALL); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + + prepare_test({ + "undouninstall1@tests.mozilla.org": [ + "onUninstalling" + ] + }); + a1.uninstall(true); + ensure_test_completed(); + + a1 = yield promiseAddonByID(ID); + + do_check_neq(a1, null); + BootstrapMonitor.checkAddonInstalled(ID); + BootstrapMonitor.checkAddonNotStarted(ID); + do_check_eq(getShutdownReason(ID), ADDON_UNINSTALL); + do_check_true(hasFlag(AddonManager.PENDING_UNINSTALL, a1.pendingOperations)); + do_check_false(a1.isActive); + do_check_false(a1.userDisabled); + + // complete the uinstall + prepare_test({ + "undouninstall1@tests.mozilla.org": [ + "onUninstalled" + ] + }); + a1.uninstall(); + ensure_test_completed(); + + a1 = yield promiseAddonByID(ID); + + do_check_eq(a1, null); + BootstrapMonitor.checkAddonNotStarted(ID); +}); + +//Tests that an enabled restartless add-on can be uninstalled and then cancelled +add_task(function* cancelUninstallOfRestartless() { + prepare_test({ + "undouninstall1@tests.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ] + }, [ + "onNewInstall", + "onInstallStarted", + "onInstallEnded" + ]); + yield promiseInstallAllFiles([do_get_addon("test_undouninstall1")]); + ensure_test_completed(); + + a1 = yield promiseAddonByID(ID); + + do_check_neq(a1, null); + BootstrapMonitor.checkAddonInstalled(ID, "1.0"); + BootstrapMonitor.checkAddonStarted(ID, "1.0"); + do_check_eq(getInstallReason(ID), ADDON_INSTALL); + do_check_eq(getStartupReason(ID), ADDON_INSTALL); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + + prepare_test({ + "undouninstall1@tests.mozilla.org": [ + "onUninstalling" + ] + }); + a1.uninstall(true); + ensure_test_completed(); + + a1 = yield promiseAddonByID("undouninstall1@tests.mozilla.org"); + + do_check_neq(a1, null); + BootstrapMonitor.checkAddonInstalled(ID); + BootstrapMonitor.checkAddonNotStarted(ID); + do_check_eq(getShutdownReason(ID), ADDON_UNINSTALL); + do_check_true(hasFlag(AddonManager.PENDING_UNINSTALL, a1.pendingOperations)); + do_check_false(a1.isActive); + do_check_false(a1.userDisabled); + + prepare_test({ + "undouninstall1@tests.mozilla.org": [ + "onOperationCancelled" + ] + }); + a1.cancelUninstall(); + ensure_test_completed(); + + BootstrapMonitor.checkAddonInstalled(ID, "1.0"); + BootstrapMonitor.checkAddonStarted(ID, "1.0"); + do_check_eq(getStartupReason(ID), ADDON_INSTALL); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + + shutdownManager(); + + do_check_eq(getShutdownReason(ID), APP_SHUTDOWN); + do_check_eq(getShutdownNewVersion(ID), undefined); + + startupManager(false); + + a1 = yield promiseAddonByID("undouninstall1@tests.mozilla.org"); + + do_check_neq(a1, null); + BootstrapMonitor.checkAddonStarted(ID, "1.0"); + do_check_eq(getStartupReason(ID), APP_STARTUP); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + + a1.uninstall(); +}); + +// Tests that reinstalling an enabled restartless add-on waiting to be +// uninstalled aborts the uninstall and leaves the add-on enabled +add_task(function* reinstallAddonAwaitingUninstall() { + yield promiseInstallAllFiles([do_get_addon("test_undouninstall1")]); + + let a1 = yield promiseAddonByID("undouninstall1@tests.mozilla.org"); + + do_check_neq(a1, null); + BootstrapMonitor.checkAddonInstalled(ID, "1.0"); + BootstrapMonitor.checkAddonStarted(ID, "1.0"); + do_check_eq(getInstallReason(ID), ADDON_INSTALL); + do_check_eq(getStartupReason(ID), ADDON_INSTALL); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + + prepare_test({ + "undouninstall1@tests.mozilla.org": [ + "onUninstalling" + ] + }); + a1.uninstall(true); + ensure_test_completed(); + + a1 = yield promiseAddonByID("undouninstall1@tests.mozilla.org"); + + do_check_neq(a1, null); + BootstrapMonitor.checkAddonInstalled(ID); + BootstrapMonitor.checkAddonNotStarted(ID); + do_check_eq(getShutdownReason(ID), ADDON_UNINSTALL); + do_check_true(hasFlag(AddonManager.PENDING_UNINSTALL, a1.pendingOperations)); + do_check_false(a1.isActive); + do_check_false(a1.userDisabled); + + prepare_test({ + "undouninstall1@tests.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ] + }, [ + "onNewInstall", + "onInstallStarted", + "onInstallEnded" + ]); + + yield promiseInstallAllFiles([do_get_addon("test_undouninstall1")]); + + a1 = yield promiseAddonByID("undouninstall1@tests.mozilla.org"); + + ensure_test_completed(); + + BootstrapMonitor.checkAddonInstalled(ID, "1.0"); + BootstrapMonitor.checkAddonStarted(ID, "1.0"); + do_check_eq(getUninstallReason(ID), ADDON_DOWNGRADE); + do_check_eq(getInstallReason(ID), ADDON_DOWNGRADE); + do_check_eq(getStartupReason(ID), ADDON_DOWNGRADE); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + + shutdownManager(); + + do_check_eq(getShutdownReason(ID), APP_SHUTDOWN); + + startupManager(false); + + a1 = yield promiseAddonByID("undouninstall1@tests.mozilla.org"); + + do_check_neq(a1, null); + BootstrapMonitor.checkAddonStarted(ID, "1.0"); + do_check_eq(getStartupReason(ID), APP_STARTUP); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + + a1.uninstall(); +}); + +// Tests that a disabled restartless add-on can be uninstalled and goes away +// when the uninstall is committed +add_task(function* uninstallDisabledRestartless() { + yield promiseInstallAllFiles([do_get_addon("test_undouninstall1")]); + + let a1 = yield promiseAddonByID("undouninstall1@tests.mozilla.org"); + + do_check_neq(a1, null); + BootstrapMonitor.checkAddonInstalled(ID, "1.0"); + BootstrapMonitor.checkAddonStarted(ID, "1.0"); + do_check_eq(getInstallReason(ID), ADDON_INSTALL); + do_check_eq(getStartupReason(ID), ADDON_INSTALL); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + + a1.userDisabled = true; + BootstrapMonitor.checkAddonNotStarted(ID); + do_check_eq(getShutdownReason(ID), ADDON_DISABLE); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + do_check_false(a1.isActive); + do_check_true(a1.userDisabled); + + prepare_test({ + "undouninstall1@tests.mozilla.org": [ + "onUninstalling" + ] + }); + a1.uninstall(true); + ensure_test_completed(); + + a1 = yield promiseAddonByID("undouninstall1@tests.mozilla.org"); + + do_check_neq(a1, null); + BootstrapMonitor.checkAddonNotStarted(ID); + do_check_true(hasFlag(AddonManager.PENDING_UNINSTALL, a1.pendingOperations)); + do_check_false(a1.isActive); + do_check_true(a1.userDisabled); + + // commit the uninstall + prepare_test({ + "undouninstall1@tests.mozilla.org": [ + "onUninstalled" + ] + }); + a1.uninstall(); + ensure_test_completed(); + + a1 = yield promiseAddonByID("undouninstall1@tests.mozilla.org"); + + do_check_eq(a1, null); + BootstrapMonitor.checkAddonNotStarted(ID); + BootstrapMonitor.checkAddonNotInstalled(ID); + do_check_eq(getUninstallReason(ID), ADDON_UNINSTALL); +}); + +//Tests that a disabled restartless add-on can be uninstalled and then cancelled +add_task(function* cancelUninstallDisabledRestartless() { + prepare_test({ + "undouninstall1@tests.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ] + }, [ + "onNewInstall", + "onInstallStarted", + "onInstallEnded" + ]); + yield promiseInstallAllFiles([do_get_addon("test_undouninstall1")]); + ensure_test_completed(); + + let a1 = yield promiseAddonByID("undouninstall1@tests.mozilla.org"); + + do_check_neq(a1, null); + BootstrapMonitor.checkAddonInstalled(ID, "1.0"); + BootstrapMonitor.checkAddonStarted(ID, "1.0"); + do_check_eq(getInstallReason(ID), ADDON_INSTALL); + do_check_eq(getStartupReason(ID), ADDON_INSTALL); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + + prepare_test({ + "undouninstall1@tests.mozilla.org": [ + ["onDisabling", false], + "onDisabled" + ] + }); + a1.userDisabled = true; + ensure_test_completed(); + + BootstrapMonitor.checkAddonNotStarted(ID); + do_check_eq(getShutdownReason(ID), ADDON_DISABLE); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + do_check_false(a1.isActive); + do_check_true(a1.userDisabled); + + prepare_test({ + "undouninstall1@tests.mozilla.org": [ + "onUninstalling" + ] + }); + a1.uninstall(true); + ensure_test_completed(); + + a1 = yield promiseAddonByID("undouninstall1@tests.mozilla.org"); + + do_check_neq(a1, null); + BootstrapMonitor.checkAddonNotStarted(ID); + BootstrapMonitor.checkAddonInstalled(ID); + do_check_true(hasFlag(AddonManager.PENDING_UNINSTALL, a1.pendingOperations)); + do_check_false(a1.isActive); + do_check_true(a1.userDisabled); + + prepare_test({ + "undouninstall1@tests.mozilla.org": [ + "onOperationCancelled" + ] + }); + a1.cancelUninstall(); + ensure_test_completed(); + + BootstrapMonitor.checkAddonNotStarted(ID); + BootstrapMonitor.checkAddonInstalled(ID); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + do_check_false(a1.isActive); + do_check_true(a1.userDisabled); + + yield promiseRestartManager(); + + a1 = yield promiseAddonByID("undouninstall1@tests.mozilla.org"); + + do_check_neq(a1, null); + BootstrapMonitor.checkAddonNotStarted(ID); + BootstrapMonitor.checkAddonInstalled(ID); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + do_check_false(a1.isActive); + do_check_true(a1.userDisabled); + + a1.uninstall(); +}); + +//Tests that reinstalling a disabled restartless add-on waiting to be +//uninstalled aborts the uninstall and leaves the add-on disabled +add_task(function* reinstallDisabledAddonAwaitingUninstall() { + yield promiseInstallAllFiles([do_get_addon("test_undouninstall1")]); + + let a1 = yield promiseAddonByID("undouninstall1@tests.mozilla.org"); + + do_check_neq(a1, null); + BootstrapMonitor.checkAddonInstalled(ID, "1.0"); + BootstrapMonitor.checkAddonStarted(ID, "1.0"); + do_check_eq(getInstallReason(ID), ADDON_INSTALL); + do_check_eq(getStartupReason(ID), ADDON_INSTALL); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + + a1.userDisabled = true; + BootstrapMonitor.checkAddonNotStarted(ID); + do_check_eq(getShutdownReason(ID), ADDON_DISABLE); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + do_check_false(a1.isActive); + do_check_true(a1.userDisabled); + + prepare_test({ + "undouninstall1@tests.mozilla.org": [ + "onUninstalling" + ] + }); + a1.uninstall(true); + ensure_test_completed(); + + a1 = yield promiseAddonByID("undouninstall1@tests.mozilla.org"); + + do_check_neq(a1, null); + BootstrapMonitor.checkAddonNotStarted(ID); + do_check_true(hasFlag(AddonManager.PENDING_UNINSTALL, a1.pendingOperations)); + do_check_false(a1.isActive); + do_check_true(a1.userDisabled); + + prepare_test({ + "undouninstall1@tests.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ] + }, [ + "onNewInstall", + "onInstallStarted", + "onInstallEnded" + ]); + + yield promiseInstallAllFiles([do_get_addon("test_undouninstall1")]); + + a1 = yield promiseAddonByID("undouninstall1@tests.mozilla.org"); + + ensure_test_completed(); + + BootstrapMonitor.checkAddonInstalled(ID, "1.0"); + BootstrapMonitor.checkAddonNotStarted(ID, "1.0"); + do_check_eq(getUninstallReason(ID), ADDON_DOWNGRADE); + do_check_eq(getInstallReason(ID), ADDON_DOWNGRADE); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + do_check_false(a1.isActive); + do_check_true(a1.userDisabled); + + yield promiseRestartManager(); + + a1 = yield promiseAddonByID("undouninstall1@tests.mozilla.org"); + + do_check_neq(a1, null); + BootstrapMonitor.checkAddonNotStarted(ID, "1.0"); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + do_check_false(a1.isActive); + do_check_true(a1.userDisabled); + + a1.uninstall(); +}); + + +// Test that uninstalling a temporary addon can be canceled +add_task(function* cancelUninstallTemporary() { + yield AddonManager.installTemporaryAddon(do_get_addon("test_undouninstall1")); + + let a1 = yield promiseAddonByID("undouninstall1@tests.mozilla.org"); + do_check_neq(a1, null); + BootstrapMonitor.checkAddonInstalled(ID, "1.0"); + BootstrapMonitor.checkAddonStarted(ID, "1.0"); + do_check_eq(getInstallReason(ID), ADDON_INSTALL); + do_check_eq(getStartupReason(ID), ADDON_ENABLE); + do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + + prepare_test({ + "undouninstall1@tests.mozilla.org": [ + "onUninstalling" + ] + }); + a1.uninstall(true); + ensure_test_completed(); + + BootstrapMonitor.checkAddonNotStarted(ID, "1.0"); + do_check_true(hasFlag(AddonManager.PENDING_UNINSTALL, a1.pendingOperations)); + + prepare_test({ + "undouninstall1@tests.mozilla.org": [ + "onOperationCancelled" + ] + }); + a1.cancelUninstall(); + ensure_test_completed(); + + a1 = yield promiseAddonByID("undouninstall1@tests.mozilla.org"); + + do_check_neq(a1, null); + BootstrapMonitor.checkAddonStarted(ID, "1.0"); + do_check_eq(a1.pendingOperations, 0); + + yield promiseRestartManager(); +}); + +// Tests that cancelling the uninstall of an incompatible restartless addon +// does not start the addon +add_task(function* cancelUninstallIncompatibleRestartless() { + yield promiseInstallAllFiles([do_get_addon("test_undoincompatible")]); + + let a1 = yield promiseAddonByID(INCOMPAT_ID); + do_check_neq(a1, null); + BootstrapMonitor.checkAddonNotStarted(INCOMPAT_ID); + do_check_false(a1.isActive); + + prepare_test({ + "incompatible@tests.mozilla.org": [ + "onUninstalling" + ] + }); + a1.uninstall(true); + ensure_test_completed(); + + a1 = yield promiseAddonByID(INCOMPAT_ID); + do_check_neq(a1, null); + do_check_true(hasFlag(AddonManager.PENDING_UNINSTALL, a1.pendingOperations)); + do_check_false(a1.isActive); + + prepare_test({ + "incompatible@tests.mozilla.org": [ + "onOperationCancelled" + ] + }); + a1.cancelUninstall(); + ensure_test_completed(); + + a1 = yield promiseAddonByID(INCOMPAT_ID); + do_check_neq(a1, null); + BootstrapMonitor.checkAddonNotStarted(INCOMPAT_ID); + do_check_eq(a1.pendingOperations, 0); + do_check_false(a1.isActive); +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_uninstall.js b/toolkit/mozapps/extensions/test/xpcshell/test_uninstall.js new file mode 100644 index 000000000..6b12489f2 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_uninstall.js @@ -0,0 +1,216 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that add-ons can be uninstalled. + +var addon1 = { + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +// Sets up the profile by installing an add-on. +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + do_test_pending(); + startupManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(olda1) { + do_check_eq(olda1, null); + + writeInstallRDFForExtension(addon1, profileDir); + + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); + do_check_eq(a1.pendingOperations, 0); + do_check_in_crash_annotation(addon1.id, addon1.version); + + do_execute_soon(run_test_1); + }); + })); +} + +function end_test() { + do_execute_soon(do_test_finished); +} + +// Uninstalling an add-on should work. +function run_test_1() { + prepare_test({ + "addon1@tests.mozilla.org": [ + "onUninstalling" + ] + }); + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_eq(a1.pendingOperations, 0); + do_check_neq(a1.operationsRequiringRestart & + AddonManager.OP_NEEDS_RESTART_UNINSTALL, 0); + a1.uninstall(); + do_check_true(hasFlag(a1.pendingOperations, AddonManager.PENDING_UNINSTALL)); + do_check_in_crash_annotation(addon1.id, addon1.version); + + ensure_test_completed(); + + AddonManager.getAddonsWithOperationsByTypes(null, function(list) { + do_check_eq(list.length, 1); + do_check_eq(list[0].id, "addon1@tests.mozilla.org"); + + do_execute_soon(check_test_1); + }); + }); +} + +function check_test_1() { + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_eq(a1, null); + do_check_false(isExtensionInAddonsList(profileDir, "addon1@tests.mozilla.org")); + do_check_not_in_crash_annotation(addon1.id, addon1.version); + + var dest = profileDir.clone(); + dest.append(do_get_expected_addon_name("addon1@tests.mozilla.org")); + do_check_false(dest.exists()); + writeInstallRDFForExtension(addon1, profileDir); + do_execute_soon(run_test_2); + }); +} + +// Cancelling the uninstall should send onOperationCancelled +function run_test_2() { + restartManager(); + + prepare_test({ + "addon1@tests.mozilla.org": [ + "onUninstalling" + ] + }); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); + do_check_eq(a1.pendingOperations, 0); + a1.uninstall(); + do_check_true(hasFlag(a1.pendingOperations, AddonManager.PENDING_UNINSTALL)); + + ensure_test_completed(); + + prepare_test({ + "addon1@tests.mozilla.org": [ + "onOperationCancelled" + ] + }); + a1.cancelUninstall(); + do_check_eq(a1.pendingOperations, 0); + + ensure_test_completed(); + + do_execute_soon(check_test_2); + }); +} + +function check_test_2() { + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_true(a1.isActive); + do_check_false(a1.userDisabled); + do_check_true(isExtensionInAddonsList(profileDir, a1.id)); + + run_test_3(); + }); +} + +// Uninstalling an item pending disable should still require a restart +function run_test_3() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + prepare_test({ + "addon1@tests.mozilla.org": [ + "onDisabling" + ] + }); + a1.userDisabled = true; + ensure_test_completed(); + + do_check_true(hasFlag(AddonManager.PENDING_DISABLE, a1.pendingOperations)); + do_check_true(a1.isActive); + + prepare_test({ + "addon1@tests.mozilla.org": [ + "onUninstalling" + ] + }); + a1.uninstall(); + + check_test_3(); + }); +} + +function check_test_3() { + ensure_test_completed(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_true(hasFlag(AddonManager.PENDING_UNINSTALL, a1.pendingOperations)); + + prepare_test({ + "addon1@tests.mozilla.org": [ + "onOperationCancelled" + ] + }); + a1.cancelUninstall(); + ensure_test_completed(); + do_check_true(hasFlag(AddonManager.PENDING_DISABLE, a1.pendingOperations)); + + do_execute_soon(run_test_4); + }); +} + +// Test that uninstalling an inactive item should happen without a restart +function run_test_4() { + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_false(a1.isActive); + do_check_true(a1.userDisabled); + do_check_false(isExtensionInAddonsList(profileDir, a1.id)); + + prepare_test({ + "addon1@tests.mozilla.org": [ + ["onUninstalling", false], + "onUninstalled" + ] + }); + a1.uninstall(); + ensure_test_completed(); + + check_test_4(); + }); +} + +function check_test_4() { + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_eq(a1, null); + + end_test(); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_update.js b/toolkit/mozapps/extensions/test/xpcshell/test_update.js new file mode 100644 index 000000000..b7e32d59f --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_update.js @@ -0,0 +1,1310 @@ +/* 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"; +const PREF_GETADDONS_CACHE_ENABLED = "extensions.getAddons.cache.enabled"; + +// The test extension uses an insecure update url. +Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); +Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false); +// 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; + +Components.utils.import("resource://testing-common/httpd.js"); +var testserver = new HttpServer(); +testserver.start(-1); +gPort = testserver.identity.primaryPort; +mapFile("/data/test_update.rdf", testserver); +mapFile("/data/test_update.xml", testserver); +testserver.registerDirectory("/addons/", do_get_file("addons")); + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +let originalSyncGUID; + +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"); + + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/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:" + gPort + "/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:" + gPort + "/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() { + 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); + do_check_true(a1.foreignInstall); + do_check_neq(a1.syncGUID, null); + + originalSyncGUID = a1.syncGUID; + 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", callback_soon(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"); + do_check_true(a1.foreignInstall); + do_check_neq(a1.syncGUID, null); + do_check_eq(originalSyncGUID, a1.syncGUID); + + a1.uninstall(); + do_execute_soon(run_test_3); + }); + })); +} + + +// Check that an update check finds compatibility updates and applies them +function run_test_3() { + restartManager(); + + 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); + do_check_true(a2.isCompatibleWith("0")); + + a2.findUpdates({ + onCompatibilityUpdateAvailable: function(addon) { + do_check_true(a2.isCompatible); + do_check_false(a2.appDisabled); + do_check_true(a2.isActive); + }, + + onUpdateAvailable: function(addon, install) { + do_throw("Should not have seen an available update"); + }, + + onNoUpdateAvailable: function(addon) { + do_check_eq(addon, a2); + do_execute_soon(check_test_3); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} + +function check_test_3() { + restartManager(); + 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); + do_execute_soon(check_test_5); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED, "3.0"); + }); +} + +function check_test_5() { + restartManager(); + 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(); + do_execute_soon(run_test_6); + }); +} + +// Test that background update checks work +function run_test_6() { + restartManager(); + + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/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); + + AddonManagerInternal.backgroundUpdateCheck(); +} + +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", + ], callback_soon(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(); + do_execute_soon(run_test_7); + }); +} + +// Test that background update checks work for lightweight themes +function run_test_7() { + restartManager(); + + LightweightThemeManager.currentTheme = { + id: "1", + version: "1", + name: "Test LW Theme", + description: "A test theme", + author: "Mozilla", + homepageURL: "http://localhost:" + gPort + "/data/index.html", + headerURL: "http://localhost:" + gPort + "/data/header.png", + footerURL: "http://localhost:" + gPort + "/data/footer.png", + previewURL: "http://localhost:" + gPort + "/data/preview.png", + iconURL: "http://localhost:" + gPort + "/data/icon.png", + updateURL: "http://localhost:" + gPort + "/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:" + gPort + "/data/lwtheme.js"; + Services.prefs.setCharPref("lightweightThemes.usedThemes", JSON.stringify(themes)); + + testserver.registerPathHandler("/data/lwtheme.js", function(request, response) { + // Server will specify an expiry in one year. + let expiry = new Date(); + expiry.setFullYear(expiry.getFullYear() + 1); + response.setHeader("Expires", expiry.toUTCString(), false); + response.write(JSON.stringify({ + id: "1", + version: "2", + name: "Updated Theme", + description: "A test theme", + author: "Mozilla", + homepageURL: "http://localhost:" + gPort + "/data/index2.html", + headerURL: "http://localhost:" + gPort + "/data/header.png", + footerURL: "http://localhost:" + gPort + "/data/footer.png", + previewURL: "http://localhost:" + gPort + "/data/preview.png", + iconURL: "http://localhost:" + gPort + "/data/icon2.png", + updateURL: "http://localhost:" + gPort + "/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); + + AddonManagerInternal.backgroundUpdateCheck(); + }); +} + +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_7_cache(); + }); +} + +// Test that background update checks for lightweight themes do not use the cache +// The update body from test 7 shouldn't be used since the cache should be bypassed. +function run_test_7_cache() { + // 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:" + gPort + "/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: "3", + name: "Updated Theme v.3", + description: "A test theme v.3", + author: "John Smith", + homepageURL: "http://localhost:" + gPort + "/data/index3.html?v=3", + headerURL: "http://localhost:" + gPort + "/data/header.png?v=3", + footerURL: "http://localhost:" + gPort + "/data/footer.png?v=3", + previewURL: "http://localhost:" + gPort + "/data/preview.png?v=3", + iconURL: "http://localhost:" + gPort + "/data/icon2.png?v=3", + updateURL: "https://localhost:" + gPort + "/data/lwtheme.js?v=3" + })); + }); + + 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_true(p1.isActive); + do_check_eq(p1.installDate.getTime(), gInstallDate); + do_check_true(p1.installDate.getTime() < p1.updateDate.getTime()); + + prepare_test({ + "1@personas.mozilla.org": [ + ["onInstalling", false], + "onInstalled" + ] + }, [ + "onExternalInstall" + ], check_test_7_cache); + + AddonManagerInternal.backgroundUpdateCheck(); + }); +} + +function check_test_7_cache() { + AddonManager.getAddonByID("1@personas.mozilla.org", function(p1) { + let currentTheme = LightweightThemeManager.currentTheme; + do_check_neq(p1, null); + do_check_eq(p1.version, "3"); + do_check_eq(p1.name, "Updated Theme v.3"); + do_check_eq(p1.description, "A test theme v.3"); + do_print(JSON.stringify(p1)); + do_check_eq(p1.creator.name, "John Smith"); + do_check_eq(p1.homepageURL, "http://localhost:" + gPort + "/data/index3.html?v=3"); + do_check_eq(p1.screenshots[0].url, "http://localhost:" + gPort + "/data/preview.png?v=3"); + do_check_eq(p1.iconURL, "http://localhost:" + gPort + "/data/icon2.png?v=3"); + do_check_eq(currentTheme.headerURL, "http://localhost:" + gPort + "/data/header.png?v=3"); + do_check_eq(currentTheme.footerURL, "http://localhost:" + gPort + "/data/footer.png?v=3"); + do_check_eq(currentTheme.updateURL, "https://localhost:" + gPort + "/data/lwtheme.js?v=3"); + + do_check_eq(p1.installDate.getTime(), gInstallDate); + do_check_true(p1.installDate.getTime() < p1.updateDate.getTime()); + + do_execute_soon(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:" + gPort + "/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:" + gPort + "/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:" + gPort + "/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:" + gPort + "/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:" + gPort + "/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:" + gPort + "/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", callback_soon(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"); + 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) + do_execute_soon(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) + do_execute_soon(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:" + gPort + "/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_true(addon.isCompatible); + + do_execute_soon(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_true(a4.isActive); + do_check_true(a4.isCompatible); + + a4.uninstall(); + do_execute_soon(run_test_13); + }); +} + +// Tests that a 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, when +// strict compatibility checking is disabled. +function run_test_13() { + restartManager(); + + // Not initially compatible but the update check will make it compatible + writeInstallRDFForExtension({ + id: "addon7@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/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_true(a7.isActive); + do_check_true(a7.isCompatible); + do_check_false(a7.appDisabled); + do_check_true(a7.isCompatibleWith("0")); + + a7.findUpdates({ + sawUpdate: false, + onNoCompatibilityUpdateAvailable: function(addon) { + do_throw("Should 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); + do_execute_soon(check_test_13); + } + }, AddonManager.UPDATE_WHEN_NEW_APP_DETECTED, "3.0"); + }); +} + +function check_test_13() { + restartManager(); + 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(); + do_execute_soon(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() { + restartManager(); + + // 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:" + gPort + "/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:" + gPort + "/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"); + do_check_eq(aInstall.existingAddon.pendingUpgrade.install, aInstall); + + do_execute_soon(check_test_14); + }, + + onInstallFailed: function(aInstall) { + do_throw("Should not have seen onInstallFailed event"); + }, + + onInstallCancelled: function(aInstall) { + do_throw("Should not have seen onInstallCancelled event"); + }, + }); + + AddonManagerInternal.backgroundUpdateCheck(); + }); +} + +function check_test_14() { + 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(); + + do_execute_soon(run_test_15); + }); +} + +// Test that background update checks doesn't update an add-on that is +// pending uninstall +function run_test_15() { + restartManager(); + + // 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:" + gPort + "/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:" + gPort + "/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"); + do_execute_soon(check_test_15); + }, + + onInstallFailed: function(aInstall) { + do_throw("Should not have seen onInstallFailed event"); + }, + + onInstallCancelled: function(aInstall) { + do_throw("Should not have seen onInstallCancelled event"); + }, + }); + + AddonManagerInternal.backgroundUpdateCheck(); + }); +} + +function check_test_15() { + 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); + + do_execute_soon(run_test_16); + }); +} + +function run_test_16() { + restartManager(); + + restartManager(); + + let url = "http://localhost:" + gPort + "/addons/test_install2_1.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ + onInstallEnded: function() { + do_execute_soon(function install_2_1_ended() { + restartManager(); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a1) { + do_check_neq(a1.syncGUID, null); + let oldGUID = a1.syncGUID; + + let url = "http://localhost:" + gPort + "/addons/test_install2_2.xpi"; + AddonManager.getInstallForURL(url, function(aInstall) { + aInstall.addListener({ + onInstallEnded: function() { + do_execute_soon(function install_2_2_ended() { + restartManager(); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_neq(a2.syncGUID, null); + do_check_eq(oldGUID, a2.syncGUID); + + a2.uninstall(); + do_execute_soon(run_test_17); + }); + }); + } + }); + aInstall.install(); + }, "application/x-xpinstall"); + }); + }); + } + }); + aInstall.install(); + }, "application/x-xpinstall"); +} + +// Test that the update check correctly observes the +// extensions.strictCompatibility pref and compatibility overrides. +function run_test_17() { + restartManager(); + + writeInstallRDFForExtension({ + id: "addon9@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0.1", + maxVersion: "0.2" + }], + name: "Test Addon 9", + }, profileDir); + restartManager(); + + AddonManager.addInstallListener({ + onNewInstall: function(aInstall) { + if (aInstall.existingAddon.id != "addon9@tests.mozilla.org") + do_throw("Saw unexpected onNewInstall for " + aInstall.existingAddon.id); + do_check_eq(aInstall.version, "3.0"); + }, + onDownloadFailed: function(aInstall) { + AddonManager.getAddonByID("addon9@tests.mozilla.org", function(a9) { + a9.uninstall(); + do_execute_soon(run_test_18); + }); + } + }); + + Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, + "http://localhost:" + gPort + "/data/test_update.xml"); + Services.prefs.setCharPref(PREF_GETADDONS_BYIDS_PERFORMANCE, + "http://localhost:" + gPort + "/data/test_update.xml"); + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); + + AddonManagerInternal.backgroundUpdateCheck(); +} + +// Tests that compatibility updates are applied to addons when the updated +// compatibility data wouldn't match with strict compatibility enabled. +function run_test_18() { + restartManager(); + writeInstallRDFForExtension({ + id: "addon10@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0.1", + maxVersion: "0.2" + }], + name: "Test Addon 10", + }, profileDir); + restartManager(); + + AddonManager.getAddonByID("addon10@tests.mozilla.org", function(a10) { + do_check_neq(a10, null); + + a10.findUpdates({ + onNoCompatibilityUpdateAvailable: function() { + do_throw("Should have seen compatibility information"); + }, + + onUpdateAvailable: function() { + do_throw("Should not have seen an available update"); + }, + + onUpdateFinished: function() { + a10.uninstall(); + do_execute_soon(run_test_19); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} + +// Test that the update check correctly observes when an addon opts-in to +// strict compatibility checking. +function run_test_19() { + restartManager(); + writeInstallRDFForExtension({ + id: "addon11@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0.1", + maxVersion: "0.2" + }], + name: "Test Addon 11", + }, profileDir); + restartManager(); + + AddonManager.getAddonByID("addon11@tests.mozilla.org", function(a11) { + do_check_neq(a11, null); + + a11.findUpdates({ + onCompatibilityUpdateAvailable: function() { + do_throw("Should have not have seen compatibility information"); + }, + + onUpdateAvailable: function() { + do_throw("Should not have seen an available update"); + }, + + onUpdateFinished: function() { + a11.uninstall(); + do_execute_soon(run_test_20); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} + +// Test that the update succeeds when the update.rdf URN contains a type prefix +// different from the add-on type +function run_test_20() { + restartManager(); + writeInstallRDFForExtension({ + id: "addon12@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 12", + }, profileDir); + restartManager(); + + prepare_test({}, [ + "onNewInstall", + "onDownloadStarted", + "onDownloadEnded" + ], continue_test_20); + + AddonManagerPrivate.backgroundUpdateCheck(); +} + +function continue_test_20(install) { + do_check_neq(install.existingAddon, null); + do_check_eq(install.existingAddon.id, "addon12@tests.mozilla.org"); + + prepare_test({ + "addon12@tests.mozilla.org": [ + "onInstalling" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], callback_soon(check_test_20)); +} + +function check_test_20(install) { + do_check_eq(install.existingAddon.pendingUpgrade.install, install); + + restartManager(); + AddonManager.getAddonByID("addon12@tests.mozilla.org", function(a12) { + do_check_neq(a12, null); + do_check_eq(a12.version, "2.0"); + do_check_eq(a12.type, "extension"); + a12.uninstall(); + + do_execute_soon(() => { + restartManager(); + end_test(); + }); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_updateCancel.js b/toolkit/mozapps/extensions/test/xpcshell/test_updateCancel.js new file mode 100644 index 000000000..d513f4adf --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_updateCancel.js @@ -0,0 +1,142 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Test cancelling add-on update checks while in progress (bug 925389) + +Components.utils.import("resource://gre/modules/Promise.jsm"); + +// The test extension uses an insecure update url. +Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); +Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false); + +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + +// Set up an HTTP server to respond to update requests +Components.utils.import("resource://testing-common/httpd.js"); + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + + +function run_test() { + // Kick off the task-based tests... + run_next_test(); +} + +// Install one extension +// Start download of update check (but delay HTTP response) +// Cancel update check +// - ensure we get cancel notification +// complete HTTP response +// - ensure no callbacks after cancel +// - ensure update is gone + +// Create an addon update listener containing a promise +// that resolves when the update is cancelled +function makeCancelListener() { + let updated = Promise.defer(); + return { + onUpdateAvailable: function(addon, install) { + updated.reject("Should not have seen onUpdateAvailable notification"); + }, + + onUpdateFinished: function(aAddon, aError) { + do_print("onUpdateCheckFinished: " + aAddon.id + " " + aError); + updated.resolve(aError); + }, + promise: updated.promise + }; +} + +// Set up the HTTP server so that we can control when it responds +let httpReceived = Promise.defer(); +function dataHandler(aRequest, aResponse) { + asyncResponse = aResponse; + aResponse.processAsync(); + httpReceived.resolve([aRequest, aResponse]); +} +var testserver = new HttpServer(); +testserver.registerDirectory("/addons/", do_get_file("addons")); +testserver.registerPathHandler("/data/test_update.rdf", dataHandler); +testserver.start(-1); +gPort = testserver.identity.primaryPort; + +// Set up an add-on for update check +writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 1", +}, profileDir); + +add_task(function cancel_during_check() { + startupManager(); + + let a1 = yield promiseAddonByID("addon1@tests.mozilla.org"); + do_check_neq(a1, null); + + let listener = makeCancelListener(); + a1.findUpdates(listener, AddonManager.UPDATE_WHEN_USER_REQUESTED); + + // Wait for the http request to arrive + let [request, response] = yield httpReceived.promise; + + // cancelUpdate returns true if there is an update check in progress + do_check_true(a1.cancelUpdate()); + + let updateResult = yield listener.promise; + do_check_eq(AddonManager.UPDATE_STATUS_CANCELLED, updateResult); + + // Now complete the HTTP request + let file = do_get_cwd(); + file.append("data"); + file.append("test_update.rdf"); + let data = loadFile(file); + response.write(data); + response.finish(); + + // trying to cancel again should return false, i.e. nothing to cancel + do_check_false(a1.cancelUpdate()); + + yield true; +}); + +// Test that update check is cancelled if the XPI provider shuts down while +// the update check is in progress +add_task(function shutdown_during_check() { + // Reset our HTTP listener + httpReceived = Promise.defer(); + + let a1 = yield promiseAddonByID("addon1@tests.mozilla.org"); + do_check_neq(a1, null); + + let listener = makeCancelListener(); + a1.findUpdates(listener, AddonManager.UPDATE_WHEN_USER_REQUESTED); + + // Wait for the http request to arrive + let [request, response] = yield httpReceived.promise; + + shutdownManager(); + + let updateResult = yield listener.promise; + do_check_eq(AddonManager.UPDATE_STATUS_CANCELLED, updateResult); + + // Now complete the HTTP request + let file = do_get_cwd(); + file.append("data"); + file.append("test_update.rdf"); + let data = loadFile(file); + response.write(data); + response.finish(); + + // trying to cancel again should return false, i.e. nothing to cancel + do_check_false(a1.cancelUpdate()); + + yield testserver.stop(Promise.defer().resolve); +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_update_compatmode.js b/toolkit/mozapps/extensions/test/xpcshell/test_update_compatmode.js new file mode 100644 index 000000000..6043b1792 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_update_compatmode.js @@ -0,0 +1,184 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that add-on update check correctly fills in the +// %COMPATIBILITY_MODE% token in the update URL. + + +// The test extension uses an insecure update url. +Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); + +Components.utils.import("resource://testing-common/httpd.js"); +var testserver = new HttpServer(); +testserver.start(-1); +gPort = testserver.identity.primaryPort; +mapFile("/data/test_updatecompatmode_ignore.rdf", testserver); +mapFile("/data/test_updatecompatmode_normal.rdf", testserver); +mapFile("/data/test_updatecompatmode_strict.rdf", testserver); +testserver.registerDirectory("/addons/", do_get_file("addons")); + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +function run_test() { + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + writeInstallRDFForExtension({ + id: "compatmode-normal@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_updatecompatmode_%COMPATIBILITY_MODE%.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon - normal" + }, profileDir); + + writeInstallRDFForExtension({ + id: "compatmode-strict@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_updatecompatmode_%COMPATIBILITY_MODE%.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon - strict" + }, profileDir); + + writeInstallRDFForExtension({ + id: "compatmode-strict-optin@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_updatecompatmode_%COMPATIBILITY_MODE%.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon - strict opt-in", + strictCompatibility: true + }, profileDir); + + writeInstallRDFForExtension({ + id: "compatmode-ignore@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_updatecompatmode_%COMPATIBILITY_MODE%.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon - ignore", + }, profileDir); + + startupManager(); + run_test_1(); +} + +function end_test() { + testserver.stop(do_test_finished); +} + + +// Strict compatibility checking disabled. +function run_test_1() { + do_print("Testing with strict compatibility checking disabled"); + Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false); + AddonManager.getAddonByID("compatmode-normal@tests.mozilla.org", function(addon) { + do_check_neq(addon, null); + addon.findUpdates({ + onCompatibilityUpdateAvailable: function() { + do_throw("Should have not have seen compatibility information"); + }, + + onNoUpdateAvailable: function() { + do_throw("Should have seen an available update"); + }, + + onUpdateAvailable: function(addon, install) { + do_check_eq(install.version, "2.0") + }, + + onUpdateFinished: function() { + run_test_2(); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} + +// Strict compatibility checking enabled. +function run_test_2() { + do_print("Testing with strict compatibility checking enabled"); + Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, true); + AddonManager.getAddonByID("compatmode-strict@tests.mozilla.org", function(addon) { + do_check_neq(addon, null); + addon.findUpdates({ + onCompatibilityUpdateAvailable: function() { + do_throw("Should have not have seen compatibility information"); + }, + + onNoUpdateAvailable: function() { + do_throw("Should have seen an available update"); + }, + + onUpdateAvailable: function(addon, install) { + do_check_eq(install.version, "2.0") + }, + + onUpdateFinished: function() { + run_test_3(); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} + +// Strict compatibility checking opt-in. +function run_test_3() { + do_print("Testing with strict compatibility disabled, but addon opt-in"); + Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false); + AddonManager.getAddonByID("compatmode-strict-optin@tests.mozilla.org", function(addon) { + do_check_neq(addon, null); + addon.findUpdates({ + onCompatibilityUpdateAvailable: function() { + do_throw("Should have not have seen compatibility information"); + }, + + onUpdateAvailable: function(addon, install) { + do_throw("Should not have seen an available update"); + }, + + onUpdateFinished: function() { + run_test_4(); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} + +// Compatibility checking disabled. +function run_test_4() { + do_print("Testing with all compatibility checking disabled"); + AddonManager.checkCompatibility = false; + AddonManager.getAddonByID("compatmode-ignore@tests.mozilla.org", function(addon) { + do_check_neq(addon, null); + addon.findUpdates({ + onCompatibilityUpdateAvailable: function() { + do_throw("Should have not have seen compatibility information"); + }, + + onNoUpdateAvailable: function() { + do_throw("Should have seen an available update"); + }, + + onUpdateAvailable: function(addon, install) { + do_check_eq(install.version, "2.0") + }, + + onUpdateFinished: function() { + end_test(); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_update_ignorecompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_update_ignorecompat.js new file mode 100644 index 000000000..672594088 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_update_ignorecompat.js @@ -0,0 +1,98 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that add-on update checks work correctly when compatibility +// check is disabled. + +const PREF_GETADDONS_CACHE_ENABLED = "extensions.getAddons.cache.enabled"; + +// The test extension uses an insecure update url. +Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); + +Components.utils.import("resource://testing-common/httpd.js"); +var testserver = new HttpServer(); +testserver.start(-1); +gPort = testserver.identity.primaryPort; +mapFile("/data/test_update.rdf", testserver); +mapFile("/data/test_update.xml", testserver); +testserver.registerDirectory("/addons/", do_get_file("addons")); + +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + run_test_1(); +} + +// Test that the update check correctly observes the +// extensions.strictCompatibility pref and compatibility overrides. +function run_test_1() { + writeInstallRDFForExtension({ + id: "addon9@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0.1", + maxVersion: "0.2" + }], + name: "Test Addon 9", + }, profileDir); + restartManager(); + + AddonManager.addInstallListener({ + onNewInstall: function(aInstall) { + if (aInstall.existingAddon.id != "addon9@tests.mozilla.org") + do_throw("Saw unexpected onNewInstall for " + aInstall.existingAddon.id); + do_check_eq(aInstall.version, "4.0"); + }, + onDownloadFailed: function(aInstall) { + do_execute_soon(run_test_2); + } + }); + + Services.prefs.setCharPref(PREF_GETADDONS_BYIDS_PERFORMANCE, + "http://localhost:" + gPort + "/data/test_update.xml"); + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); + + AddonManagerInternal.backgroundUpdateCheck(); +} + +// Test that the update check correctly observes when an addon opts-in to +// strict compatibility checking. +function run_test_2() { + writeInstallRDFForExtension({ + id: "addon11@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0.1", + maxVersion: "0.2" + }], + name: "Test Addon 11", + }, profileDir); + restartManager(); + + AddonManager.getAddonByID("addon11@tests.mozilla.org", function(a11) { + do_check_neq(a11, null); + + a11.findUpdates({ + onCompatibilityUpdateAvailable: function() { + do_throw("Should have not have seen compatibility information"); + }, + + onNoUpdateAvailable: function() { + do_throw("Should have seen an available update"); + }, + + onUpdateFinished: function() { + end_test(); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} 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 000000000..0474535f1 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js @@ -0,0 +1,1085 @@ +/* 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"; +const PREF_GETADDONS_CACHE_ENABLED = "extensions.getAddons.cache.enabled"; + +// 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; + +Components.utils.import("resource://testing-common/httpd.js"); +var testserver = new HttpServer(); +testserver.start(-1); +gPort = testserver.identity.primaryPort; +mapFile("/data/test_update.rdf", testserver); +mapFile("/data/test_update.xml", testserver); +testserver.registerDirectory("/addons/", do_get_file("addons")); + +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); + + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/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:" + gPort + "/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:" + gPort + "/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", callback_soon(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(); + do_execute_soon(run_test_3); + }); + })); +} + + +// Check that an update check finds compatibility updates and applies them +function run_test_3() { + restartManager(); + + 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); + do_execute_soon(check_test_3); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} + +function check_test_3() { + restartManager(); + 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); + do_execute_soon(check_test_5); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED, "3.0"); + }); +} + +function check_test_5() { + restartManager(); + 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(); + do_execute_soon(run_test_6); + }); +} + +// Test that background update checks work +function run_test_6() { + restartManager(); + + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/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); + + AddonManagerInternal.backgroundUpdateCheck(); +} + +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", + ], callback_soon(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(); + do_execute_soon(run_test_7); + }); +} + +// Test that background update checks work for lightweight themes +function run_test_7() { + restartManager(); + + LightweightThemeManager.currentTheme = { + id: "1", + version: "1", + name: "Test LW Theme", + description: "A test theme", + author: "Mozilla", + homepageURL: "http://localhost:" + gPort + "/data/index.html", + headerURL: "http://localhost:" + gPort + "/data/header.png", + footerURL: "http://localhost:" + gPort + "/data/footer.png", + previewURL: "http://localhost:" + gPort + "/data/preview.png", + iconURL: "http://localhost:" + gPort + "/data/icon.png", + updateURL: "http://localhost:" + gPort + "/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:" + gPort + "/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:" + gPort + "/data/index2.html", + headerURL: "http://localhost:" + gPort + "/data/header.png", + footerURL: "http://localhost:" + gPort + "/data/footer.png", + previewURL: "http://localhost:" + gPort + "/data/preview.png", + iconURL: "http://localhost:" + gPort + "/data/icon2.png", + updateURL: "http://localhost:" + gPort + "/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); + + AddonManagerInternal.backgroundUpdateCheck(); + }); +} + +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(); + + do_execute_soon(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:" + gPort + "/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:" + gPort + "/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:" + gPort + "/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:" + gPort + "/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:" + gPort + "/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:" + gPort + "/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", callback_soon(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) + do_execute_soon(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) + do_execute_soon(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:" + gPort + "/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); + + do_execute_soon(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(); + do_execute_soon(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() { + restartManager(); + + // Not initially compatible but the update check will make it compatible + writeInstallRDFForExtension({ + id: "addon7@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/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); + do_execute_soon(check_test_13); + } + }, AddonManager.UPDATE_WHEN_NEW_APP_DETECTED, "3.0"); + }); +} + +function check_test_13() { + restartManager(); + 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(); + do_execute_soon(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() { + restartManager(); + + // 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:" + gPort + "/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:" + gPort + "/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"); + do_check_eq(aInstall.existingAddon.pendingUpgrade.install, aInstall); + do_execute_soon(check_test_14); + }, + + onInstallFailed: function(aInstall) { + do_throw("Should not have seen onInstallFailed event"); + }, + + onInstallCancelled: function(aInstall) { + do_throw("Should not have seen onInstallCancelled event"); + }, + }); + + AddonManagerInternal.backgroundUpdateCheck(); + }); +} + +function check_test_14() { + 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(); + + do_execute_soon(run_test_15); + }); +} + +// Test that background update checks doesn't update an add-on that is +// pending uninstall +function run_test_15() { + restartManager(); + + // 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:" + gPort + "/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:" + gPort + "/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"); + do_execute_soon(check_test_15); + }, + + onInstallFailed: function(aInstall) { + do_throw("Should not have seen onInstallFailed event"); + }, + + onInstallCancelled: function(aInstall) { + do_throw("Should not have seen onInstallCancelled event"); + }, + }); + + AddonManagerInternal.backgroundUpdateCheck(); + }); +} + +function check_test_15() { + 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); + + do_execute_soon(run_test_16); + }); +} + +// Test that the update check correctly observes the +// extensions.strictCompatibility pref and compatibility overrides. +function run_test_16() { + restartManager(); + + writeInstallRDFForExtension({ + id: "addon9@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0.1", + maxVersion: "0.2" + }], + name: "Test Addon 9", + }, profileDir); + restartManager(); + + AddonManager.addInstallListener({ + onNewInstall: function(aInstall) { + if (aInstall.existingAddon.id != "addon9@tests.mozilla.org") + do_throw("Saw unexpected onNewInstall for " + aInstall.existingAddon.id); + do_check_eq(aInstall.version, "2.0"); + }, + onDownloadFailed: function(aInstall) { + do_execute_soon(run_test_17); + } + }); + + Services.prefs.setCharPref(PREF_GETADDONS_BYIDS_PERFORMANCE, + "http://localhost:" + gPort + "/data/test_update.xml"); + Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); + + AddonManagerInternal.backgroundUpdateCheck(); +} + +// Test that the update check correctly observes when an addon opts-in to +// strict compatibility checking. +function run_test_17() { + + writeInstallRDFForExtension({ + id: "addon11@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0.1", + maxVersion: "0.2" + }], + name: "Test Addon 11", + }, profileDir); + restartManager(); + + AddonManager.getAddonByID("addon11@tests.mozilla.org", function(a11) { + do_check_neq(a11, null); + + a11.findUpdates({ + onCompatibilityUpdateAvailable: function() { + do_throw("Should have not have seen compatibility information"); + }, + + onUpdateAvailable: function() { + do_throw("Should not have seen an available update"); + }, + + onUpdateFinished: function() { + do_execute_soon(end_test); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_updatecheck.js b/toolkit/mozapps/extensions/test/xpcshell/test_updatecheck.js new file mode 100644 index 000000000..d2e15103b --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_updatecheck.js @@ -0,0 +1,312 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that AddonUpdateChecker works correctly + +Components.utils.import("resource://gre/modules/addons/AddonUpdateChecker.jsm"); + +Components.utils.import("resource://testing-common/httpd.js"); +var testserver; + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + // Create and configure the HTTP server. + testserver = new HttpServer(); + testserver.registerDirectory("/data/", do_get_file("data")); + testserver.start(4444); + + do_test_pending(); + run_test_1(); +} + +function end_test() { + testserver.stop(do_test_finished); +} + +// Test that a basic update check returns the expected available updates +function run_test_1() { + AddonUpdateChecker.checkForUpdates("updatecheck1@tests.mozilla.org", null, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + check_test_1(updates); + }, + + onUpdateCheckError: function(status) { + do_throw("Update check failed with status " + status); + } + }); +} + +function check_test_1(updates) { + do_check_eq(updates.length, 5); + let update = AddonUpdateChecker.getNewestCompatibleUpdate(updates); + do_check_neq(update, null); + do_check_eq(update.version, 3); + update = AddonUpdateChecker.getCompatibilityUpdate(updates, "2"); + do_check_neq(update, null); + do_check_eq(update.version, 2); + do_check_eq(update.targetApplications[0].minVersion, 1); + do_check_eq(update.targetApplications[0].maxVersion, 2); + + run_test_2(); +} + +/* + * Tests that the security checks are applied correctly + * + * Test signature updateHash updateLink expected + *-------------------------------------------------------- + * 2 absent absent http fail + * 3 broken absent http fail + * 4 correct absent http no update + * 5 correct sha1 http update + * 6 corrent absent https update + * 7 corrent sha1 https update + * 8 corrent md2 http no update + * 9 corrent md2 https update + */ + +let updateKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDK426erD/H3XtsjvaB5+PJqbhj" + + "Zc9EDI5OCJS8R3FIObJ9ZHJK1TXeaE7JWqt9WUmBWTEFvwS+FI9vWu8058N9CHhD" + + "NyeP6i4LuUYjTURnn7Yw/IgzyIJ2oKsYa32RuxAyteqAWqPT/J63wBixIeCxmysf" + + "awB/zH4KaPiY3vnrzQIDAQAB"; + +function run_test_2() { + AddonUpdateChecker.checkForUpdates("test_bug378216_5@tests.mozilla.org", + updateKey, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + do_throw("Expected the update check to fail"); + }, + + onUpdateCheckError: function(status) { + run_test_3(); + } + }); +} + +function run_test_3() { + AddonUpdateChecker.checkForUpdates("test_bug378216_7@tests.mozilla.org", + updateKey, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + do_throw("Expected the update check to fail"); + }, + + onUpdateCheckError: function(status) { + run_test_4(); + } + }); +} + +function run_test_4() { + AddonUpdateChecker.checkForUpdates("test_bug378216_8@tests.mozilla.org", + updateKey, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + do_check_eq(updates.length, 1); + do_check_false("updateURL" in updates[0]); + run_test_5(); + }, + + onUpdateCheckError: function(status) { + do_throw("Update check failed with status " + status); + } + }); +} + +function run_test_5() { + AddonUpdateChecker.checkForUpdates("test_bug378216_9@tests.mozilla.org", + updateKey, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + do_check_eq(updates.length, 1); + do_check_eq(updates[0].version, "2.0"); + do_check_true("updateURL" in updates[0]); + run_test_6(); + }, + + onUpdateCheckError: function(status) { + do_throw("Update check failed with status " + status); + } + }); +} + +function run_test_6() { + AddonUpdateChecker.checkForUpdates("test_bug378216_10@tests.mozilla.org", + updateKey, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + do_check_eq(updates.length, 1); + do_check_eq(updates[0].version, "2.0"); + do_check_true("updateURL" in updates[0]); + run_test_7(); + }, + + onUpdateCheckError: function(status) { + do_throw("Update check failed with status " + status); + } + }); +} + +function run_test_7() { + AddonUpdateChecker.checkForUpdates("test_bug378216_11@tests.mozilla.org", + updateKey, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + do_check_eq(updates.length, 1); + do_check_eq(updates[0].version, "2.0"); + do_check_true("updateURL" in updates[0]); + run_test_8(); + }, + + onUpdateCheckError: function(status) { + do_throw("Update check failed with status " + status); + } + }); +} + +function run_test_8() { + AddonUpdateChecker.checkForUpdates("test_bug378216_12@tests.mozilla.org", + updateKey, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + do_check_eq(updates.length, 1); + do_check_false("updateURL" in updates[0]); + run_test_9(); + }, + + onUpdateCheckError: function(status) { + do_throw("Update check failed with status " + status); + } + }); +} + +function run_test_9() { + AddonUpdateChecker.checkForUpdates("test_bug378216_13@tests.mozilla.org", + updateKey, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + do_check_eq(updates.length, 1); + do_check_eq(updates[0].version, "2.0"); + do_check_true("updateURL" in updates[0]); + run_test_10(); + }, + + onUpdateCheckError: function(status) { + do_throw("Update check failed with status " + status); + } + }); +} + +function run_test_10() { + AddonUpdateChecker.checkForUpdates("test_bug378216_14@tests.mozilla.org", + null, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + do_check_eq(updates.length, 0); + run_test_11(); + }, + + onUpdateCheckError: function(status) { + do_throw("Update check failed with status " + status); + } + }); +} + +function run_test_11() { + AddonUpdateChecker.checkForUpdates("test_bug378216_15@tests.mozilla.org", + null, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + do_throw("Update check should have failed"); + }, + + onUpdateCheckError: function(status) { + do_check_eq(status, AddonUpdateChecker.ERROR_PARSE_ERROR); + run_test_12(); + } + }); +} + +function run_test_12() { + AddonUpdateChecker.checkForUpdates("ignore-compat@tests.mozilla.org", + null, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + do_check_eq(updates.length, 3); + let update = AddonUpdateChecker.getNewestCompatibleUpdate(updates, + null, + null, + true); + do_check_neq(update, null); + do_check_eq(update.version, 2); + run_test_13(); + }, + + onUpdateCheckError: function(status) { + do_throw("Update check failed with status " + status); + } + }); +} + +function run_test_13() { + AddonUpdateChecker.checkForUpdates("compat-override@tests.mozilla.org", + null, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + do_check_eq(updates.length, 3); + let overrides = [{ + type: "incompatible", + minVersion: 1, + maxVersion: 2, + appID: "xpcshell@tests.mozilla.org", + appMinVersion: 0.1, + appMaxVersion: 0.2 + }, { + type: "incompatible", + minVersion: 2, + maxVersion: 2, + appID: "xpcshell@tests.mozilla.org", + appMinVersion: 1, + appMaxVersion: 2 + }]; + let update = AddonUpdateChecker.getNewestCompatibleUpdate(updates, + null, + null, + true, + false, + overrides); + do_check_neq(update, null); + do_check_eq(update.version, 1); + run_test_14(); + }, + + onUpdateCheckError: function(status) { + do_throw("Update check failed with status " + status); + } + }); +} + +function run_test_14() { + AddonUpdateChecker.checkForUpdates("compat-strict-optin@tests.mozilla.org", + null, + "http://localhost:4444/data/test_updatecheck.rdf", { + onUpdateCheckComplete: function(updates) { + do_check_eq(updates.length, 1); + let update = AddonUpdateChecker.getNewestCompatibleUpdate(updates, + null, + null, + true, + false); + do_check_eq(update, null); + end_test(); + }, + + onUpdateCheckError: function(status) { + do_throw("Update check failed with status " + status); + } + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_updateid.js b/toolkit/mozapps/extensions/test/xpcshell/test_updateid.js new file mode 100644 index 000000000..e8aea0301 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_updateid.js @@ -0,0 +1,422 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that updating an add-on to a new ID works + +// The test extension uses an insecure update url. +Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); + +Components.utils.import("resource://testing-common/httpd.js"); +var testserver; +const profileDir = gProfD.clone(); +profileDir.append("extensions"); + +function resetPrefs() { + Services.prefs.setIntPref("bootstraptest.active_version", -1); + Services.prefs.setIntPref("bootstraptest.installed_version", -1); + Services.prefs.setIntPref("bootstraptest.startup_reason", -1); + Services.prefs.setIntPref("bootstraptest.shutdown_reason", -1); + Services.prefs.setIntPref("bootstraptest.install_reason", -1); + Services.prefs.setIntPref("bootstraptest.uninstall_reason", -1); +} + +function getActiveVersion() { + return Services.prefs.getIntPref("bootstraptest.active_version"); +} + +function getInstalledVersion() { + return Services.prefs.getIntPref("bootstraptest.installed_version"); +} + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + + // Create and configure the HTTP server. + testserver = new HttpServer(); + testserver.registerDirectory("/data/", do_get_file("data")); + testserver.registerDirectory("/addons/", do_get_file("addons")); + testserver.start(4444); + + do_test_pending(); + run_test_1(); +} + +function end_test() { + testserver.stop(do_test_finished); +} + +function installUpdate(aInstall, aCallback) { + aInstall.addListener({ + onInstallEnded: function(aInstall) { + // give the startup time to run + do_execute_soon(function() { + aCallback(aInstall); + }); + } + }); + + aInstall.install(); +} + +// Verify that an update to an add-on with a new ID uninstalls the old add-on +function run_test_1() { + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:4444/data/test_updateid.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 1", + }, profileDir); + + startupManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "1.0"); + + a1.findUpdates({ + onUpdateAvailable: function(addon, install) { + 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, a1); + + installUpdate(install, check_test_1); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} + +function check_test_1(install) { + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { + // Existing add-on should have a pending upgrade + do_check_neq(a1.pendingUpgrade, null); + do_check_eq(a1.pendingUpgrade.id, "addon2@tests.mozilla.org"); + do_check_eq(a1.pendingUpgrade.install.existingAddon, a1); + do_check_neq(a1.syncGUID); + + let a1SyncGUID = a1.syncGUID; + + restartManager(); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org"], function([a1, a2]) { + // Should have uninstalled the old and installed the new + do_check_eq(a1, null); + do_check_neq(a2, null); + do_check_neq(a2.syncGUID, null); + + // The Sync GUID should change when the ID changes + do_check_neq(a1SyncGUID, a2.syncGUID); + + a2.uninstall(); + + do_execute_soon(run_test_2); + }); + })); +} + +// Test that when the new add-on already exists we just upgrade that +function run_test_2() { + restartManager(); + shutdownManager(); + + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:4444/data/test_updateid.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", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 2", + }, profileDir); + + startupManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "1.0"); + + a1.findUpdates({ + onUpdateAvailable: function(addon, install) { + installUpdate(install, check_test_2); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} + +function check_test_2(install) { + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org"], + callback_soon(function([a1, a2]) { + do_check_eq(a1.pendingUpgrade, null); + // Existing add-on should have a pending upgrade + do_check_neq(a2.pendingUpgrade, null); + do_check_eq(a2.pendingUpgrade.id, "addon2@tests.mozilla.org"); + do_check_eq(a2.pendingUpgrade.install.existingAddon, a2); + + restartManager(); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org"], function([a1, a2]) { + // Should have uninstalled the old and installed the new + do_check_neq(a1, null); + do_check_neq(a2, null); + + a1.uninstall(); + a2.uninstall(); + + do_execute_soon(run_test_3); + }); + })); +} + +// Test that we rollback correctly when removing the old add-on fails +function run_test_3() { + restartManager(); + shutdownManager(); + + // This test only works on Windows + if (!("nsIWindowsRegKey" in AM_Ci)) { + run_test_4(); + return; + } + + writeInstallRDFForExtension({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:4444/data/test_updateid.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 1", + }, profileDir); + + startupManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_eq(a1.version, "1.0"); + + a1.findUpdates({ + onUpdateAvailable: function(addon, install) { + installUpdate(install, check_test_3); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} + +function check_test_3(install) { + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { + // Existing add-on should have a pending upgrade + do_check_neq(a1.pendingUpgrade, null); + do_check_eq(a1.pendingUpgrade.id, "addon2@tests.mozilla.org"); + do_check_eq(a1.pendingUpgrade.install.existingAddon, a1); + + // Lock the old add-on open so it can't be uninstalled + var file = profileDir.clone(); + file.append("addon1@tests.mozilla.org"); + if (!file.exists()) + file.leafName += ".xpi"; + else + file.append("install.rdf"); + + var fstream = AM_Cc["@mozilla.org/network/file-output-stream;1"]. + createInstance(AM_Ci.nsIFileOutputStream); + fstream.init(file, FileUtils.MODE_APPEND | FileUtils.MODE_WRONLY, FileUtils.PERMS_FILE, 0); + + restartManager(); + + fstream.close(); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org"], + callback_soon(function([a1, a2]) { + // Should not have installed the new add-on but it should still be + // pending install + do_check_neq(a1, null); + do_check_eq(a2, null); + + restartManager(); + + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon2@tests.mozilla.org"], function([a1, a2]) { + // Should have installed the new add-on + do_check_eq(a1, null); + do_check_neq(a2, null); + + a2.uninstall(); + + do_execute_soon(run_test_4); + }); + })); + })); +} + +// Tests that upgrading to a bootstrapped add-on works but requires a restart +function run_test_4() { + restartManager(); + shutdownManager(); + + writeInstallRDFForExtension({ + id: "addon2@tests.mozilla.org", + version: "2.0", + updateURL: "http://localhost:4444/data/test_updateid.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 2", + }, profileDir); + + startupManager(); + + resetPrefs(); + + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { + do_check_neq(a2, null); + do_check_neq(a2.syncGUID, null); + do_check_eq(a2.version, "2.0"); + + a2.findUpdates({ + onUpdateAvailable: function(addon, install) { + installUpdate(install, check_test_4); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} + +function check_test_4() { + AddonManager.getAddonsByIDs(["addon2@tests.mozilla.org", + "addon3@tests.mozilla.org"], + callback_soon(function([a2, a3]) { + // Should still be pending install even though the new add-on is restartless + do_check_neq(a2, null); + do_check_eq(a3, null); + + do_check_neq(a2.pendingUpgrade, null); + do_check_eq(a2.pendingUpgrade.id, "addon3@tests.mozilla.org"); + + do_check_eq(getInstalledVersion(), -1); + do_check_eq(getActiveVersion(), -1); + + restartManager(); + + AddonManager.getAddonsByIDs(["addon2@tests.mozilla.org", + "addon3@tests.mozilla.org"], function([a2, a3]) { + // Should have updated + do_check_eq(a2, null); + do_check_neq(a3, null); + + do_check_eq(getInstalledVersion(), 3); + do_check_eq(getActiveVersion(), 3); + + do_execute_soon(run_test_5); + }); + })); +} + +// Tests that upgrading to another bootstrapped add-on works without a restart +function run_test_5() { + AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) { + do_check_neq(a3, null); + do_check_eq(a3.version, "3.0"); + + a3.findUpdates({ + onUpdateAvailable: function(addon, install) { + installUpdate(install, check_test_5); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} + +function check_test_5() { + AddonManager.getAddonsByIDs(["addon3@tests.mozilla.org", + "addon4@tests.mozilla.org"], + callback_soon(function([a3, a4]) { + // Should have updated + do_check_eq(a3, null); + do_check_neq(a4, null); + + do_check_eq(getInstalledVersion(), 4); + do_check_eq(getActiveVersion(), 4); + + restartManager(); + + AddonManager.getAddonsByIDs(["addon3@tests.mozilla.org", + "addon4@tests.mozilla.org"], function([a3, a4]) { + // Should still be gone + do_check_eq(a3, null); + do_check_neq(a4, null); + + do_check_eq(getInstalledVersion(), 4); + do_check_eq(getActiveVersion(), 4); + + run_test_6(); + }); + })); +} + +// Tests that upgrading to a non-bootstrapped add-on works but requires a restart +function run_test_6() { + AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) { + do_check_neq(a4, null); + do_check_eq(a4.version, "4.0"); + + a4.findUpdates({ + onUpdateAvailable: function(addon, install) { + installUpdate(install, check_test_6); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} + +function check_test_6() { + AddonManager.getAddonsByIDs(["addon4@tests.mozilla.org", + "addon2@tests.mozilla.org"], + callback_soon(function([a4, a2]) { + // Should still be pending install even though the old add-on is restartless + do_check_neq(a4, null); + do_check_eq(a2, null); + + do_check_neq(a4.pendingUpgrade, null); + do_check_eq(a4.pendingUpgrade.id, "addon2@tests.mozilla.org"); + + do_check_eq(getInstalledVersion(), 4); + do_check_eq(getActiveVersion(), 4); + + restartManager(); + + AddonManager.getAddonsByIDs(["addon4@tests.mozilla.org", + "addon2@tests.mozilla.org"], function([a4, a2]) { + // Should have updated + do_check_eq(a4, null); + do_check_neq(a2, null); + + do_check_eq(getInstalledVersion(), 0); + do_check_eq(getActiveVersion(), 0); + + end_test(); + }); + })); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_upgrade.js b/toolkit/mozapps/extensions/test/xpcshell/test_upgrade.js new file mode 100644 index 000000000..f79789b68 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_upgrade.js @@ -0,0 +1,206 @@ +/* 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 disabled. + +Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false); + +// 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.nsIFile); +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 compatible in the first version and incompatible 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 compatible 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(); + + 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); + } + do_execute_soon(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"); + + do_execute_soon(run_test_2); + }); +} + +// Test that upgrading the application doesn't disable 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_true(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"); + + do_execute_soon(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. + gExtensionsINI.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_true(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/test_upgrade_strictcompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_upgrade_strictcompat.js new file mode 100644 index 000000000..69383166e --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_upgrade_strictcompat.js @@ -0,0 +1,209 @@ +/* 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.nsIFile); +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_execute_soon(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"); + + do_execute_soon(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"); + + do_execute_soon(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. + gExtensionsINI.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-shared.ini b/toolkit/mozapps/extensions/test/xpcshell/xpcshell-shared.ini new file mode 100644 index 000000000..bab072e83 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell-shared.ini @@ -0,0 +1,281 @@ +# The file is shared between the two main xpcshell manifest files. +[DEFAULT] +skip-if = toolkit == 'android' || toolkit == 'gonk' + +[test_AddonRepository.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +[test_AddonRepository_cache.js] +# Bug 676992: test consistently hangs on Android +# Bug 1026805: frequent hangs on OSX 10.8 +skip-if = os == "android" || os == "mac" +run-sequentially = Uses hardcoded ports in xpi files. +[test_AddonRepository_compatmode.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +[test_LightweightThemeManager.js] +[test_backgroundupdate.js] +[test_bad_json.js] +[test_badschema.js] +[test_blocklistchange.js] +# Times out during parallel runs on desktop +requesttimeoutfactor = 2 +[test_blocklist_prefs.js] +[test_blocklist_metadata_filters.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +[test_blocklist_regexp.js] +skip-if = os == "android" +[test_bootstrap.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +[test_bootstrap_resource.js] +[test_bug299716.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +run-sequentially = Uses hardcoded ports in xpi files. +[test_bug299716_2.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +run-sequentially = Hardcoded port in install.rdf. +[test_bug324121.js] +# Bug 676992: test consistently hangs on Android +# Bug 1026805: frequent hangs on OSX 10.8 +skip-if = os == "android" || os == "mac" +run-sequentially = Uses hardcoded ports in xpi files. +[test_bug335238.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +run-sequentially = Uses hardcoded ports in xpi files. +[test_bug371495.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +[test_bug384052.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +[test_bug393285.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +[test_bug394300.js] +# Bug 676992: test consistently hangs on Android +# Bug 1026805: frequent hangs on OSX 10.8 +skip-if = os == "android" || os == "mac" +run-sequentially = Uses hardcoded ports in xpi files. +[test_bug397778.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +[test_bug406118.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +[test_bug424262.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +[test_bug425657.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +[test_bug430120.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +[test_bug449027.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +[test_bug455906.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +[test_bug465190.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +[test_bug468528.js] +# Bug 676992: test consistently hangs on Android +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" +[test_bug514327_1.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +[test_bug514327_2.js] +# Bug 676992: test consistently hangs on Android +skip-if = buildapp == "mulet" || os == "android" +[test_bug514327_3.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +[test_bug521905.js] +[test_bug526598.js] +[test_bug541420.js] +[test_bug542391.js] +run-sequentially = Uses hardcoded ports in xpi files. +[test_bug554133.js] +[test_bug559800.js] +[test_bug563256.js] +# Bug 676992: test consistently fails on Android +fail-if = os == "android" +[test_bug564030.js] +[test_bug566626.js] +[test_bug567184.js] +[test_bug569138.js] +[test_bug570173.js] +[test_bug576735.js] +[test_bug587088.js] +[test_bug594058.js] +[test_bug595081.js] +[test_bug595573.js] +[test_bug596343.js] +[test_bug596607.js] +[test_bug616841.js] +# Bug 676992: test consistently fails on Android +fail-if = os == "android" +[test_bug619730.js] +[test_bug620837.js] +[test_bug655254.js] +[test_bug659772.js] +[test_bug675371.js] +[test_bug740612.js] +[test_bug753900.js] +[test_bug757663.js] +[test_bug953156.js] +[test_checkcompatibility.js] +[test_checkCompatibility_themeOverride.js] +[test_childprocess.js] +[test_ChromeManifestParser.js] +[test_compatoverrides.js] +[test_corrupt.js] +[test_corrupt_strictcompat.js] +[test_corruptfile.js] +[test_dataDirectory.js] +[test_default_providers_pref.js] +[test_dictionary.js] +[test_langpack.js] +[test_disable.js] +[test_distribution.js] +[test_dss.js] +# Bug 676992: test consistently fails on Android +fail-if = os == "android" +[test_duplicateplugins.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +[test_error.js] +[test_experiment.js] +[test_filepointer.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +[test_fuel.js] +[test_general.js] +[test_getresource.js] +[test_gfxBlacklist_Device.js] +[test_gfxBlacklist_DriverNew.js] +[test_gfxBlacklist_Equal_DriverNew.js] +[test_gfxBlacklist_Equal_DriverOld.js] +[test_gfxBlacklist_Equal_OK.js] +[test_gfxBlacklist_GTE_DriverOld.js] +[test_gfxBlacklist_GTE_OK.js] +[test_gfxBlacklist_No_Comparison.js] +[test_gfxBlacklist_OK.js] +[test_gfxBlacklist_OS.js] +[test_gfxBlacklist_OSVersion_match.js] +[test_gfxBlacklist_OSVersion_mismatch_OSVersion.js] +[test_gfxBlacklist_OSVersion_mismatch_DriverVersion.js] +[test_gfxBlacklist_Vendor.js] +[test_gfxBlacklist_prefs.js] +[test_hasbinarycomponents.js] +[test_install.js] +[test_install_icons.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" +run-sequentially = Uses hardcoded ports in xpi files. +[test_isDebuggable.js] +[test_locale.js] +[test_locked.js] +[test_locked2.js] +[test_locked_strictcompat.js] +[test_manifest.js] +[test_mapURIToAddonID.js] +# Same as test_bootstrap.js +skip-if = os == "android" +[test_migrate1.js] +[test_migrate2.js] +[test_migrate3.js] +[test_migrate4.js] +# Times out during parallel runs on desktop +requesttimeoutfactor = 2 +[test_migrate5.js] +[test_migrateAddonRepository.js] +[test_migrate_max_version.js] +[test_multiprocessCompatible.js] +[test_no_addons.js] +[test_onPropertyChanged_appDisabled.js] +[test_permissions.js] +[test_permissions_prefs.js] +[test_plugins.js] +skip-if = buildapp == "mulet" +[test_pluginchange.js] +# PluginProvider.jsm is not shipped on Android +skip-if = os == "android" +[test_pluginBlocklistCtp.js] +# Bug 676992: test consistently fails on Android +fail-if = buildapp == "mulet" || os == "android" +[test_pref_properties.js] +[test_registry.js] +[test_safemode.js] +[test_startup.js] +# Bug 676992: test consistently fails on Android +fail-if = os == "android" +[test_syncGUID.js] +[test_strictcompatibility.js] +[test_targetPlatforms.js] +[test_theme.js] +# Bug 676992: test consistently fails on Android +fail-if = os == "android" +[test_types.js] +[test_undothemeuninstall.js] +[test_undouninstall.js] +[test_uninstall.js] +[test_update.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +[test_updateCancel.js] +[test_update_strictcompat.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +[test_update_ignorecompat.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" +run-sequentially = Uses hardcoded ports in xpi files. +[test_updateid.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +run-sequentially = Uses hardcoded ports in xpi files. +[test_update_compatmode.js] +[test_upgrade.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +run-sequentially = Uses global XCurProcD dir. +[test_upgrade_strictcompat.js] +# Bug 676992: test consistently hangs on Android +skip-if = os == "android" +run-sequentially = Uses global XCurProcD dir. +[test_overrideblocklist.js] +run-sequentially = Uses global XCurProcD dir. +[test_sourceURI.js] +[test_bootstrap_globals.js] diff --git a/toolkit/mozapps/extensions/test/xpcshell/xpcshell-unpack.ini b/toolkit/mozapps/extensions/test/xpcshell/xpcshell-unpack.ini new file mode 100644 index 000000000..51520f888 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell-unpack.ini @@ -0,0 +1,8 @@ + [DEFAULT] +head = head_addons.js head_unpack.js +tail = +firefox-appdir = browser +skip-if = toolkit == 'android' || toolkit == 'gonk' +dupe-manifest = + +[include:xpcshell-shared.ini] diff --git a/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini b/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini new file mode 100644 index 000000000..83ab77c74 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini @@ -0,0 +1,28 @@ +[DEFAULT] +skip-if = buildapp == 'mulet' || toolkit == 'android' || toolkit == 'gonk' +head = head_addons.js +tail = +firefox-appdir = browser +dupe-manifest = +support-files = + data/** + xpcshell-shared.ini + +[test_addon_path_service.js] +[test_asyncBlocklistLoad.js] +[test_cacheflush.js] +[test_DeferredSave.js] +[test_gmpProvider.js] +run-if = appname == "firefox" +[test_isReady.js] +[test_metadata_update.js] +[test_pluginInfoURL.js] +[test_provider_markSafe.js] +[test_provider_shutdown.js] +[test_provider_unsafe_access_shutdown.js] +[test_provider_unsafe_access_startup.js] +[test_shutdown.js] +[test_XPIcancel.js] +[test_XPIStates.js] + +[include:xpcshell-shared.ini] diff --git a/toolkit/mozapps/extensions/test/xpinstall/authRedirect.sjs b/toolkit/mozapps/extensions/test/xpinstall/authRedirect.sjs new file mode 100644 index 000000000..85d448e2b --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/authRedirect.sjs @@ -0,0 +1,21 @@ +// Simple script redirects to the query part of the uri if the browser +// authenticates with username "testuser" password "testpass" + +function handleRequest(request, response) { + if (request.hasHeader("Authorization")) { + if (request.getHeader("Authorization") == "Basic dGVzdHVzZXI6dGVzdHBhc3M=") { + response.setStatusLine(request.httpVersion, 302, "Found"); + response.setHeader("Location", request.queryString); + response.write("See " + request.queryString); + } + else { + response.setStatusLine(request.httpVersion, 403, "Forbidden"); + response.write("Invalid credentials"); + } + } + else { + response.setStatusLine(request.httpVersion, 401, "Authentication required"); + response.setHeader("WWW-Authenticate", "basic realm=\"XPInstall\"", false); + response.write("Unauthenticated request"); + } +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser.ini b/toolkit/mozapps/extensions/test/xpinstall/browser.ini new file mode 100644 index 000000000..d6392cdc8 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser.ini @@ -0,0 +1,103 @@ +[DEFAULT] +support-files = + authRedirect.sjs + bug540558.html + bug638292.html + bug645699.html + concurrent_installs.html + cookieRedirect.sjs + corrupt.xpi + empty.xpi + enabled.html + hashRedirect.sjs + head.js + incompatible.xpi + installchrome.html + installtrigger.html + installtrigger_frame.html + multipackage.xpi + navigate.html + redirect.sjs + restartless.xpi + signed-no-cn.xpi + signed-no-o.xpi + signed-tampered.xpi + signed-untrusted.xpi + signed.xpi + signed2.xpi + slowinstall.sjs + startsoftwareupdate.html + theme.xpi + triggerredirect.html + unsigned.xpi + +[browser_auth.js] +[browser_auth2.js] +[browser_auth3.js] +[browser_auth4.js] +[browser_badargs.js] +[browser_badargs2.js] +[browser_badhash.js] +[browser_badhashtype.js] +[browser_bug540558.js] +[browser_bug611242.js] +[browser_bug638292.js] +skip-if = e10s # Bug 1083269 +[browser_bug645699.js] +# [browser_bug672485.js] +# disabled due to a leak. See bug 682410. +[browser_cancel.js] +[browser_concurrent_installs.js] +[browser_cookies.js] +[browser_cookies2.js] +[browser_cookies3.js] +[browser_cookies4.js] +skip-if = true # Bug 1084646 +[browser_corrupt.js] +[browser_datauri.js] +[browser_empty.js] +[browser_enabled.js] +[browser_enabled2.js] +[browser_enabled3.js] +[browser_hash.js] +[browser_httphash.js] +[browser_httphash2.js] +[browser_httphash3.js] +[browser_httphash4.js] +[browser_httphash5.js] +[browser_httphash6.js] +[browser_installchrome.js] +[browser_localfile.js] +[browser_localfile2.js] +[browser_localfile3.js] +[browser_localfile4.js] +[browser_multipackage.js] +[browser_navigateaway.js] +[browser_navigateaway2.js] +[browser_navigateaway3.js] +[browser_navigateaway4.js] +[browser_offline.js] +[browser_relative.js] +[browser_signed_multiple.js] +[browser_signed_naming.js] +[browser_signed_tampered.js] +[browser_signed_trigger.js] +[browser_signed_untrusted.js] +[browser_signed_url.js] +[browser_softwareupdate.js] +[browser_switchtab.js] +[browser_trigger_redirect.js] +[browser_unsigned_trigger.js] +[browser_unsigned_trigger_iframe.js] +skip-if = buildapp == "mulet" +[browser_unsigned_trigger_xorigin.js] +skip-if = buildapp == "mulet" +[browser_unsigned_url.js] +[browser_whitelist.js] +[browser_whitelist2.js] +[browser_whitelist3.js] +[browser_whitelist4.js] +[browser_whitelist5.js] +[browser_whitelist6.js] +[browser_whitelist7.js] +skip-if = (os == 'win' || os == 'mac') && debug # bug 986458 - leaked 1 docshell until shutdown on chunked debug bc diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_auth.js b/toolkit/mozapps/extensions/test/xpinstall/browser_auth.js new file mode 100644 index 000000000..ee2913827 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_auth.js @@ -0,0 +1,43 @@ +// ---------------------------------------------------------------------------- +// Test whether an install succeeds when authentication is required +// This verifies bug 312473 +function test() { + Harness.authenticationCallback = get_auth_info; + Harness.downloadFailedCallback = download_failed; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "authRedirect.sjs?" + TESTROOT + "unsigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function get_auth_info() { + return [ "testuser", "testpass" ]; +} + +function download_failed(install) { + ok(false, "Install should not have failed"); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + var authMgr = Components.classes['@mozilla.org/network/http-auth-manager;1'] + .getService(Components.interfaces.nsIHttpAuthManager); + authMgr.clearAll(); + + Services.perms.remove("example.com", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_auth2.js b/toolkit/mozapps/extensions/test/xpinstall/browser_auth2.js new file mode 100644 index 000000000..d50ce941d --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_auth2.js @@ -0,0 +1,46 @@ +// ---------------------------------------------------------------------------- +// Test whether an install fails when authentication is required and bad +// credentials are given +// This verifies bug 312473 +function test() { + requestLongerTimeout(2); + Harness.authenticationCallback = get_auth_info; + Harness.downloadFailedCallback = download_failed; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "authRedirect.sjs?" + TESTROOT + "unsigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function get_auth_info() { + return [ "baduser", "badpass" ]; +} + +function download_failed(install) { + is(install.error, AddonManager.ERROR_NETWORK_FAILURE, "Install should have failed"); +} + +function install_ended(install, addon) { + ok(false, "Add-on should not have installed"); + install.cancel(); +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + var authMgr = Components.classes['@mozilla.org/network/http-auth-manager;1'] + .getService(Components.interfaces.nsIHttpAuthManager); + authMgr.clearAll(); + + Services.perms.remove("example.com", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_auth3.js b/toolkit/mozapps/extensions/test/xpinstall/browser_auth3.js new file mode 100644 index 000000000..f06e97fa3 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_auth3.js @@ -0,0 +1,54 @@ +// ---------------------------------------------------------------------------- +// Test whether an install fails when authentication is required and it is +// canceled +// This verifies bug 312473 + +/////////////////// +// +// Whitelisting this test. +// As part of bug 1077403, the leaking uncaught rejection should be fixed. +// +thisTestLeaksUncaughtRejectionsAndShouldBeFixed("TypeError: this.docShell is null"); + + +function test() { + Harness.authenticationCallback = get_auth_info; + Harness.downloadFailedCallback = download_failed; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "authRedirect.sjs?" + TESTROOT + "unsigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function get_auth_info() { + return null; +} + +function download_failed(install) { + is(install.error, AddonManager.ERROR_NETWORK_FAILURE, "Install should have failed"); +} + +function install_ended(install, addon) { + ok(false, "Add-on should not have installed"); + install.cancel(); +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + var authMgr = Components.classes['@mozilla.org/network/http-auth-manager;1'] + .getService(Components.interfaces.nsIHttpAuthManager); + authMgr.clearAll(); + + Services.perms.remove("example.com", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_auth4.js b/toolkit/mozapps/extensions/test/xpinstall/browser_auth4.js new file mode 100644 index 000000000..abbc161f7 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_auth4.js @@ -0,0 +1,53 @@ +/////////////////// +// +// Whitelisting this test. +// As part of bug 1077403, the leaking uncaught rejection should be fixed. +// +thisTestLeaksUncaughtRejectionsAndShouldBeFixed("TypeError: this.docShell is null"); + + +// ---------------------------------------------------------------------------- +// Test whether a request for auth for an XPI switches to the appropriate tab +var gNewTab; + +function test() { + Harness.authenticationCallback = get_auth_info; + Harness.downloadFailedCallback = download_failed; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "authRedirect.sjs?" + TESTROOT + "unsigned.xpi" + })); + gNewTab = gBrowser.addTab(); + gBrowser.getBrowserForTab(gNewTab).loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function get_auth_info() { + is(gBrowser.selectedTab, gNewTab, "Should have focused the tab loading the XPI"); + return [ "testuser", "testpass" ]; +} + +function download_failed(install) { + ok(false, "Install should not have failed"); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + var authMgr = Components.classes['@mozilla.org/network/http-auth-manager;1'] + .getService(Components.interfaces.nsIHttpAuthManager); + authMgr.clearAll(); + + Services.perms.remove("example.com", "install"); + + gBrowser.removeTab(gNewTab); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_badargs.js b/toolkit/mozapps/extensions/test/xpinstall/browser_badargs.js new file mode 100644 index 000000000..fb9c3d10c --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_badargs.js @@ -0,0 +1,37 @@ +// ---------------------------------------------------------------------------- +// Test whether passing a simple string to InstallTrigger.install throws an +// exception +function test() { + waitForExplicitFinish(); + + var triggers = encodeURIComponent(JSON.stringify(TESTROOT + "unsigned.xpi")); + gBrowser.selectedTab = gBrowser.addTab(); + + function loadListener() { + gBrowser.selectedBrowser.removeEventListener("load", loadListener, true); + gBrowser.contentWindow.addEventListener("InstallTriggered", page_loaded, false); + } + + gBrowser.selectedBrowser.addEventListener("load", loadListener, true); + + // In non-e10s the exception in the content page would trigger a test failure + if (!gMultiProcessBrowser) + expectUncaughtException(); + + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function page_loaded() { + gBrowser.contentWindow.removeEventListener("InstallTriggered", page_loaded, false); + var doc = gBrowser.contentDocument; + is(doc.getElementById("return").textContent, "exception", "installTrigger should have failed"); + + // In non-e10s the exception from the page is thrown after the event so we + // have to spin the event loop to make sure it arrives so expectUncaughtException + // sees it. + executeSoon(() => { + gBrowser.removeCurrentTab(); + finish(); + }); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_badargs2.js b/toolkit/mozapps/extensions/test/xpinstall/browser_badargs2.js new file mode 100644 index 000000000..25e1586c8 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_badargs2.js @@ -0,0 +1,41 @@ +// ---------------------------------------------------------------------------- +// Test whether passing an undefined url InstallTrigger.install throws an +// exception +function test() { + waitForExplicitFinish(); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: undefined + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + + function loadListener() { + gBrowser.selectedBrowser.removeEventListener("load", loadListener, true); + gBrowser.contentWindow.addEventListener("InstallTriggered", page_loaded, false); + } + + gBrowser.selectedBrowser.addEventListener("load", loadListener, true); + + // In non-e10s the exception in the content page would trigger a test failure + if (!gMultiProcessBrowser) + expectUncaughtException(); + + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function page_loaded() { + gBrowser.contentWindow.removeEventListener("InstallTriggered", page_loaded, false); + var doc = gBrowser.contentDocument; + is(doc.getElementById("return").textContent, "exception", "installTrigger should have failed"); + + // In non-e10s the exception from the page is thrown after the event so we + // have to spin the event loop to make sure it arrives so expectUncaughtException + // sees it. + executeSoon(() => { + gBrowser.removeCurrentTab(); + finish(); + }); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_badhash.js b/toolkit/mozapps/extensions/test/xpinstall/browser_badhash.js new file mode 100644 index 000000000..d7bcedd90 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_badhash.js @@ -0,0 +1,33 @@ +// ---------------------------------------------------------------------------- +// Test whether an install fails when an invalid hash is included +// This verifies bug 302284 +function test() { + Harness.downloadFailedCallback = download_failed; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: TESTROOT + "unsigned.xpi", + Hash: "sha1:643b08418599ddbd1ea8a511c90696578fb844b9", + toString: function() { return this.URL; } + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function download_failed(install) { + is(install.error, AddonManager.ERROR_INCORRECT_HASH, "Install should fail"); +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + Services.perms.remove("example.com", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_badhashtype.js b/toolkit/mozapps/extensions/test/xpinstall/browser_badhashtype.js new file mode 100644 index 000000000..105ab681e --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_badhashtype.js @@ -0,0 +1,33 @@ +// ---------------------------------------------------------------------------- +// Test whether an install fails when an unknown hash type is included +// This verifies bug 302284 +function test() { + Harness.downloadFailedCallback = download_failed; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: TESTROOT + "unsigned.xpi", + Hash: "foo:3d0dc22e1f394e159b08aaf5f0f97de4d5c65f4f", + toString: function() { return this.URL; } + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function download_failed(install) { + is(install.error, AddonManager.ERROR_INCORRECT_HASH, "Install should fail"); +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + Services.perms.remove("example.com", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_bug540558.js b/toolkit/mozapps/extensions/test/xpinstall/browser_bug540558.js new file mode 100644 index 000000000..6a425c61a --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_bug540558.js @@ -0,0 +1,25 @@ +// ---------------------------------------------------------------------------- +// Tests that calling InstallTrigger.installChrome works +function test() { + Harness.installEndedCallback = check_xpi_install; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "bug540558.html"); +} + +function check_xpi_install(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + Services.perms.remove("example.com", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_bug611242.js b/toolkit/mozapps/extensions/test/xpinstall/browser_bug611242.js new file mode 100644 index 000000000..08af331bd --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_bug611242.js @@ -0,0 +1,34 @@ +// ---------------------------------------------------------------------------- +// Test whether setting a new property in InstallTrigger then persists to other +// page loads +function loadURI(aUri, aCallback) { + gBrowser.selectedBrowser.addEventListener("load", function() { + if (gBrowser.selectedBrowser.currentURI.spec != aUri) + return; + + gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true); + + aCallback(); + }, true); + + gBrowser.loadURI(aUri); +} + +function test() { + waitForExplicitFinish(); + + gBrowser.selectedTab = gBrowser.addTab(); + + loadURI(TESTROOT + "enabled.html", function() { + window.content.wrappedJSObject.InstallTrigger.enabled.k = function() { }; + + loadURI(TESTROOT2 + "enabled.html", function() { + is(window.content.wrappedJSObject.InstallTrigger.enabled.k, undefined, "Property should not be defined"); + + gBrowser.removeTab(gBrowser.selectedTab); + + finish(); + }); + }); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_bug638292.js b/toolkit/mozapps/extensions/test/xpinstall/browser_bug638292.js new file mode 100644 index 000000000..d5d590a3f --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_bug638292.js @@ -0,0 +1,63 @@ +// ---------------------------------------------------------------------------- +// Test whether an InstallTrigger.enabled is working +function test() { + waitForExplicitFinish(); + + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.selectedBrowser.addEventListener("load", function() { + gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true); + waitForFocus(page_loaded, gBrowser.contentWindow); + }, true); + gBrowser.loadURI(TESTROOT + "bug638292.html"); +} + +function check_load(aCallback) { + gBrowser.addEventListener("load", function(aEvent) { + if (!gBrowser.browsers[2] || + aEvent.target != gBrowser.browsers[2].contentDocument) { + // SeaMonkey tabbrowser needs to deal with additional loads. + if (navigator.userAgent.match(/ SeaMonkey\//)) + info("Ignoring unrelated load on SeaMonkey. (Expected 2-3 times.)"); + else + ok(false, "Ignoring unrelated load on Firefox. (Should never happen!)"); + return; + } + + gBrowser.removeEventListener("load", arguments.callee, true); + + // Let the load handler complete + executeSoon(function() { + var doc = gBrowser.browsers[2].contentDocument; + is(doc.getElementById("enabled").textContent, "true", "installTrigger should have been enabled"); + + // Focus the old tab + gBrowser.selectedTab = gBrowser.tabs[1]; + waitForFocus(function() { + // Close the new tab + gBrowser.removeTab(gBrowser.tabs[2]); + aCallback(); + }, gBrowser.contentWindow); + }); + }, true); +} + +function page_loaded() { + var doc = gBrowser.contentDocument; + info("Clicking link 1"); + EventUtils.synthesizeMouseAtCenter(doc.getElementById("link1"), { }, gBrowser.contentWindow); + + check_load(function() { + info("Clicking link 2"); + EventUtils.synthesizeMouseAtCenter(doc.getElementById("link2"), { }, gBrowser.contentWindow); + + check_load(function() { + info("Clicking link 3"); + EventUtils.synthesizeMouseAtCenter(doc.getElementById("link3"), { button: 1 }, gBrowser.contentWindow); + + check_load(function() { + gBrowser.removeCurrentTab(); + finish(); + }); + }); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_bug645699.js b/toolkit/mozapps/extensions/test/xpinstall/browser_bug645699.js new file mode 100644 index 000000000..a5c188c03 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_bug645699.js @@ -0,0 +1,36 @@ +// ---------------------------------------------------------------------------- +// Tests installing an unsigned add-on through an InstallTrigger call in web +// content. This should be blocked by the whitelist check. +// This verifies bug 645699 +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installBlockedCallback = allow_blocked; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.org/"), "install", pm.ALLOW_ACTION); + + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "bug645699.html"); +} + +function allow_blocked(installInfo) { + is(installInfo.browser, gBrowser.selectedBrowser, "Install should have been triggered by the right browser"); + is(installInfo.originatingURI.spec, gBrowser.currentURI.spec, "Install should have been triggered by the right uri"); + return false; +} + +function confirm_install(window) { + ok(false, "Should not see the install dialog"); + return false; +} + +function finish_test(count) { + is(count, 0, "0 Add-ons should have been successfully installed"); + Services.perms.remove("addons.mozilla.org", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_bug672485.js b/toolkit/mozapps/extensions/test/xpinstall/browser_bug672485.js new file mode 100644 index 000000000..36e9c5b3c --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_bug672485.js @@ -0,0 +1,52 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +gWindowWatcher = null; + +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installCancelledCallback = cancelled_install; + Harness.installEndedCallback = complete_install; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + gWindowWatcher = Services.ww; + delete Services.ww; + is(Services.ww, undefined, "Services.ww should now be undefined"); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "unsigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function confirm_install(window) { + ok(false, "Should not see the install dialog"); + return false; +} + +function cancelled_install() { + ok(true, "Install should b cancelled"); +} + +function complete_install() { + ok(false, "Install should not have completed"); + return false; +} + +function finish_test(count) { + is(count, 0, "0 Add-ons should have been successfully installed"); + + gBrowser.removeCurrentTab(); + + Services.ww = gWindowWatcher; + + Services.perms.remove("example.com", "install"); + + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_cancel.js b/toolkit/mozapps/extensions/test/xpinstall/browser_cancel.js new file mode 100644 index 000000000..8fb6efcb8 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_cancel.js @@ -0,0 +1,62 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// ---------------------------------------------------------------------------- +// Tests that cancelling multiple installs doesn't fail +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Signed XPI": TESTROOT + "signed.xpi", + "Signed XPI 2": TESTROOT + "signed2.xpi", + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function get_item(items, url) { + for (let item of items) { + if (item.url == url) + return item; + } + ok(false, "Item for " + url + " was not listed"); + return null; +} + +function confirm_install(window) { + let items = window.document.getElementById("itemList").childNodes; + is(items.length, 2, "Should be 2 items listed in the confirmation dialog"); + let item = get_item(items, TESTROOT + "signed.xpi"); + if (item) { + is(item.name, "Signed XPI Test", "Should have seen the name from the trigger list"); + is(item.cert, "(Object Signer)", "Should have seen the signer"); + is(item.signed, "true", "Should have listed the item as signed"); + } + item = get_item(items, TESTROOT + "signed2.xpi"); + if (item) { + is(item.name, "Signed XPI Test", "Should have seen the name from the trigger list"); + is(item.cert, "(Object Signer)", "Should have seen the signer"); + is(item.signed, "true", "Should have listed the item as signed"); + } + return false; +} + +function install_ended(install, addon) { + ok(false, "Should not have seen installs complete"); +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been successfully installed"); + + Services.perms.remove("example.com", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_concurrent_installs.js b/toolkit/mozapps/extensions/test/xpinstall/browser_concurrent_installs.js new file mode 100644 index 000000000..3613e95b0 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_concurrent_installs.js @@ -0,0 +1,128 @@ +// Test that having two frames that request installs at the same time doesn't +// cause callback ID conflicts (discussed in bug 926712) + +let {Promise} = Cu.import("resource://gre/modules/Promise.jsm"); + +let gConcurrentTabs = []; +let gQueuedForInstall = []; +let gResults = []; + +function frame_script() { + addMessageListener("Test:StartInstall", () => { + content.document.getElementById("installnow").click() + }); + + addEventListener("load", () => { + sendAsyncMessage("Test:Loaded"); + + content.addEventListener("InstallComplete", (e) => { + sendAsyncMessage("Test:InstallComplete", e.detail); + }, true); + }, true); +} + +let gAddonAndWindowListener = { + onOpenWindow: function(win) { + var window = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow); + info("Window opened"); + + waitForFocus(function() { + info("Focused!"); + // Initially the accept button is disabled on a countdown timer + let button = window.document.documentElement.getButton("accept"); + button.disabled = false; + if (gQueuedForInstall.length > 0) { + // Start downloading the next add-on while we accept this dialog: + installNext(); + } + window.document.documentElement.acceptDialog(); + }, window); + }, + onCloseWindow: function(win) { }, + onInstallEnded: function(install) { + install.cancel(); + }, + QueryInterface: XPCOMUtils.generateQI([Ci.nsIWindowMediatorListener]) +}; + +function installNext() { + let tab = gQueuedForInstall.shift(); + tab.linkedBrowser.messageManager.sendAsyncMessage("Test:StartInstall"); +} + +function winForTab(t) { + return t.linkedBrowser.contentWindow; +} + +function createTab(url) { + let tab = gBrowser.addTab(url); + tab.linkedBrowser.messageManager.loadFrameScript("data:,(" + frame_script.toString() + ")();", true); + + tab.linkedBrowser.messageManager.addMessageListener("Test:InstallComplete", ({data}) => { + gResults.push(data); + if (gResults.length == 2) { + executeSoon(endThisTest); + } + }); + + return tab; +} + +function test() { + waitForExplicitFinish(); + + Services.prefs.setBoolPref(PREF_LOGGING_ENABLED, true); + Services.prefs.setBoolPref(PREF_INSTALL_REQUIRESECUREORIGIN, false); + Services.wm.addListener(gAddonAndWindowListener); + AddonManager.addInstallListener(gAddonAndWindowListener); + registerCleanupFunction(function() { + Services.wm.removeListener(gAddonAndWindowListener); + AddonManager.removeInstallListener(gAddonAndWindowListener); + Services.prefs.clearUserPref(PREF_LOGGING_ENABLED); + Services.prefs.clearUserPref(PREF_INSTALL_REQUIRESECUREORIGIN); + + Services.perms.remove("example.com", "install"); + Services.perms.remove("example.org", "install"); + + while (gConcurrentTabs.length) { + gBrowser.removeTab(gConcurrentTabs.shift()); + } + }); + + let pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + pm.add(makeURI("http://example.org/"), "install", pm.ALLOW_ACTION); + + gConcurrentTabs.push(createTab(TESTROOT + "concurrent_installs.html")); + gConcurrentTabs.push(createTab(TESTROOT2 + "concurrent_installs.html")); + + let promises = gConcurrentTabs.map((t) => { + return new Promise(resolve => { + t.linkedBrowser.messageManager.addMessageListener("Test:Loaded", resolve); + }); + }); + + Promise.all(promises).then(() => { + gQueuedForInstall = [...gConcurrentTabs]; + installNext(); + }); +} + +function endThisTest() { + is(gResults.length, 2, "Should have two urls"); + isnot(gResults[0].loc, gResults[1].loc, "Should not have results from the same page."); + isnot(gResults[0].xpi, gResults[1].xpi, "Should not have the same XPIs."); + for (let i = 0; i < 2; i++) { + let {loc, xpi} = gResults[i]; + if (loc.includes("example.org")) { + ok(xpi.includes("example.org"), "Should get .org XPI for .org loc"); + } else if (loc.includes("example.com")) { + ok(xpi.includes("example.com"), "Should get .com XPI for .com loc"); + } else { + ok(false, "Should never get anything that isn't from example.org or example.com"); + } + } + + finish(); +} + diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_cookies.js b/toolkit/mozapps/extensions/test/xpinstall/browser_cookies.js new file mode 100644 index 000000000..c0e7c11b5 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_cookies.js @@ -0,0 +1,30 @@ +// ---------------------------------------------------------------------------- +// Test that an install that requires cookies to be sent fails when no cookies +// are set +// This verifies bug 462739 +function test() { + Harness.downloadFailedCallback = download_failed; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Cookie check": TESTROOT + "cookieRedirect.sjs?" + TESTROOT + "unsigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function download_failed(install) { + is(install.error, AddonManager.ERROR_NETWORK_FAILURE, "Install should fail"); +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + Services.perms.remove("example.com", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_cookies2.js b/toolkit/mozapps/extensions/test/xpinstall/browser_cookies2.js new file mode 100644 index 000000000..02ea8ff21 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_cookies2.js @@ -0,0 +1,40 @@ +// ---------------------------------------------------------------------------- +// Test that an install that requires cookies to be sent succeeds when cookies +// are set +// This verifies bug 462739 +function test() { + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var cm = Components.classes["@mozilla.org/cookiemanager;1"] + .getService(Components.interfaces.nsICookieManager2); + cm.add("example.com", "/browser/" + RELATIVE_DIR, "xpinstall", "true", false, + false, true, (Date.now() / 1000) + 60); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Cookie check": TESTROOT + "cookieRedirect.sjs?" + TESTROOT + "unsigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + var cm = Components.classes["@mozilla.org/cookiemanager;1"] + .getService(Components.interfaces.nsICookieManager2); + cm.remove("example.com", "xpinstall", "/browser/" + RELATIVE_DIR, false); + + Services.perms.remove("example.com", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_cookies3.js b/toolkit/mozapps/extensions/test/xpinstall/browser_cookies3.js new file mode 100644 index 000000000..c23778dd0 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_cookies3.js @@ -0,0 +1,44 @@ +// ---------------------------------------------------------------------------- +// Test that an install that requires cookies to be sent succeeds when cookies +// are set and third party cookies are disabled. +// This verifies bug 462739 +function test() { + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var cm = Components.classes["@mozilla.org/cookiemanager;1"] + .getService(Components.interfaces.nsICookieManager2); + cm.add("example.com", "/browser/" + RELATIVE_DIR, "xpinstall", "true", false, + false, true, (Date.now() / 1000) + 60); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + Services.prefs.setIntPref("network.cookie.cookieBehavior", 1); + + var triggers = encodeURIComponent(JSON.stringify({ + "Cookie check": TESTROOT + "cookieRedirect.sjs?" + TESTROOT + "unsigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + var cm = Components.classes["@mozilla.org/cookiemanager;1"] + .getService(Components.interfaces.nsICookieManager2); + cm.remove("example.com", "xpinstall", "/browser/" + RELATIVE_DIR, false); + + Services.prefs.clearUserPref("network.cookie.cookieBehavior"); + + Services.perms.remove("example.com", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_cookies4.js b/toolkit/mozapps/extensions/test/xpinstall/browser_cookies4.js new file mode 100644 index 000000000..33347cdb7 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_cookies4.js @@ -0,0 +1,43 @@ +// ---------------------------------------------------------------------------- +// Test that an install that requires cookies to be sent fails when cookies +// are set and third party cookies are disabled and the request is to a third +// party. +// This verifies bug 462739 +function test() { + Harness.downloadFailedCallback = download_failed; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var cm = Components.classes["@mozilla.org/cookiemanager;1"] + .getService(Components.interfaces.nsICookieManager2); + cm.add("example.org", "/browser/" + RELATIVE_DIR, "xpinstall", "true", false, + false, true, (Date.now() / 1000) + 60); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + Services.prefs.setIntPref("network.cookie.cookieBehavior", 1); + + var triggers = encodeURIComponent(JSON.stringify({ + "Cookie check": TESTROOT2 + "cookieRedirect.sjs?" + TESTROOT + "unsigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function download_failed(install) { + is(install.error, AddonManager.ERROR_NETWORK_FAILURE, "Install should fail"); +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + var cm = Components.classes["@mozilla.org/cookiemanager;1"] + .getService(Components.interfaces.nsICookieManager2); + cm.remove("example.org", "xpinstall", "/browser/" + RELATIVE_DIR, false); + + Services.prefs.clearUserPref("network.cookie.cookieBehavior"); + Services.perms.remove("example.com", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_corrupt.js b/toolkit/mozapps/extensions/test/xpinstall/browser_corrupt.js new file mode 100644 index 000000000..8f0c3c66a --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_corrupt.js @@ -0,0 +1,32 @@ +// ---------------------------------------------------------------------------- +// Test whether an install fails when the xpi is corrupt. +function test() { + Harness.downloadFailedCallback = download_failed; + Harness.installsCompletedCallback = finish_test; + Harness.finalContentEvent = "InstallComplete"; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Corrupt XPI": TESTROOT + "corrupt.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function download_failed(install) { + is(install.error, AddonManager.ERROR_CORRUPT_FILE, "Install should fail"); +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + Services.perms.remove("example.com", "install"); + + var doc = gBrowser.contentDocument; + is(doc.getElementById("status").textContent, "-207", "Callback should have seen the failure"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_datauri.js b/toolkit/mozapps/extensions/test/xpinstall/browser_datauri.js new file mode 100644 index 000000000..917f2465d --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_datauri.js @@ -0,0 +1,36 @@ +// ---------------------------------------------------------------------------- +// Checks that a chained redirect through a data URI and javascript is blocked + +function setup_redirect(aSettings) { + var url = TESTROOT + "redirect.sjs?mode=setup"; + for (var name in aSettings) { + url += "&" + name + "=" + encodeURIComponent(aSettings[name]); + } + + var req = new XMLHttpRequest(); + req.open("GET", url, false); + req.send(null); +} + +function test() { + Harness.installOriginBlockedCallback = install_blocked; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + setup_redirect({ + "Location": "data:text/html,<script>window.location.href='" + TESTROOT + "unsigned.xpi'</script>" + }); + + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "redirect.sjs?mode=redirect"); +} + +function install_blocked(installInfo) { +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_empty.js b/toolkit/mozapps/extensions/test/xpinstall/browser_empty.js new file mode 100644 index 000000000..cbf9e48a7 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_empty.js @@ -0,0 +1,28 @@ +// ---------------------------------------------------------------------------- +// Test whether an install fails when there is no install script present. +function test() { + Harness.downloadFailedCallback = download_failed; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Empty XPI": TESTROOT + "empty.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function download_failed(install) { + is(install.error, AddonManager.ERROR_CORRUPT_FILE, "Install should fail"); +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + Services.perms.remove("example.com", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_enabled.js b/toolkit/mozapps/extensions/test/xpinstall/browser_enabled.js new file mode 100644 index 000000000..56118c4e1 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_enabled.js @@ -0,0 +1,24 @@ +// ---------------------------------------------------------------------------- +// Test whether an InstallTrigger.enabled is working +function test() { + waitForExplicitFinish(); + + gBrowser.selectedTab = gBrowser.addTab(); + + function loadListener() { + gBrowser.selectedBrowser.removeEventListener("load", loadListener, true); + gBrowser.contentWindow.addEventListener("PageLoaded", page_loaded, false); + } + + gBrowser.selectedBrowser.addEventListener("load", loadListener, true); + gBrowser.loadURI(TESTROOT + "enabled.html"); +} + +function page_loaded() { + gBrowser.contentWindow.removeEventListener("PageLoaded", page_loaded, false); + + var doc = gBrowser.contentDocument; + is(doc.getElementById("enabled").textContent, "true", "installTrigger should have been enabled"); + gBrowser.removeCurrentTab(); + finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_enabled2.js b/toolkit/mozapps/extensions/test/xpinstall/browser_enabled2.js new file mode 100644 index 000000000..290987bda --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_enabled2.js @@ -0,0 +1,27 @@ +// ---------------------------------------------------------------------------- +// Test whether an InstallTrigger.enabled is working +function test() { + waitForExplicitFinish(); + + Services.prefs.setBoolPref("xpinstall.enabled", false); + + gBrowser.selectedTab = gBrowser.addTab(); + + function loadListener() { + gBrowser.selectedBrowser.removeEventListener("load", loadListener, true); + gBrowser.contentWindow.addEventListener("PageLoaded", page_loaded, false); + } + + gBrowser.selectedBrowser.addEventListener("load", loadListener, true); + gBrowser.loadURI(TESTROOT + "enabled.html"); +} + +function page_loaded() { + gBrowser.contentWindow.removeEventListener("PageLoaded", page_loaded, false); + Services.prefs.clearUserPref("xpinstall.enabled"); + + var doc = gBrowser.contentDocument; + is(doc.getElementById("enabled").textContent, "false", "installTrigger should have not been enabled"); + gBrowser.removeCurrentTab(); + finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_enabled3.js b/toolkit/mozapps/extensions/test/xpinstall/browser_enabled3.js new file mode 100644 index 000000000..ea3eba530 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_enabled3.js @@ -0,0 +1,48 @@ +// ---------------------------------------------------------------------------- +// Test whether an InstallTrigger.install call fails when xpinstall is disabled +function test() { + Harness.installDisabledCallback = install_disabled; + Harness.installBlockedCallback = allow_blocked; + Harness.installConfirmCallback = confirm_install; + Harness.setup(); + + Services.prefs.setBoolPref("xpinstall.enabled", false); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "unsigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + + function loadListener() { + gBrowser.selectedBrowser.removeEventListener("load", loadListener, true); + gBrowser.contentWindow.addEventListener("InstallTriggered", page_loaded, false); + } + + gBrowser.selectedBrowser.addEventListener("load", loadListener, true); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function install_disabled(installInfo) { + ok(true, "Saw installation disabled"); +} + +function allow_blocked(installInfo) { + ok(false, "Should never see the blocked install notification"); + return false; +} + +function confirm_install(window) { + ok(false, "Should never see an install confirmation dialog"); + return false; +} + +function page_loaded() { + gBrowser.contentWindow.removeEventListener("InstallTriggered", page_loaded, false); + Services.prefs.clearUserPref("xpinstall.enabled"); + + var doc = gBrowser.contentDocument; + is(doc.getElementById("return").textContent, "false", "installTrigger should have not been enabled"); + gBrowser.removeCurrentTab(); + Harness.finish(); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_hash.js b/toolkit/mozapps/extensions/test/xpinstall/browser_hash.js new file mode 100644 index 000000000..0af71fcb0 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_hash.js @@ -0,0 +1,34 @@ +// ---------------------------------------------------------------------------- +// Test whether an install succeeds when a valid hash is included +// This verifies bug 302284 +function test() { + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: TESTROOT + "unsigned.xpi", + Hash: "sha1:3d0dc22e1f394e159b08aaf5f0f97de4d5c65f4f", + toString: function() { return this.URL; } + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove("example.com", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_hash2.js b/toolkit/mozapps/extensions/test/xpinstall/browser_hash2.js new file mode 100644 index 000000000..8d83e3cd3 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_hash2.js @@ -0,0 +1,34 @@ +// ---------------------------------------------------------------------------- +// Test whether an install succeeds using case-insensitive hashes +// This verifies bug 603021 +function test() { + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: TESTROOT + "unsigned.xpi", + Hash: "sha1:3D0DC22E1F394E159B08AAF5F0F97DE4D5C65F4F", + toString: function() { return this.URL; } + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove("example.com", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_httphash.js b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash.js new file mode 100644 index 000000000..b072db1f3 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash.js @@ -0,0 +1,39 @@ +// ---------------------------------------------------------------------------- +// Test whether an install succeeds when a valid hash is included in the HTTPS +// request +// This verifies bug 591070 +function test() { + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false); + + var url = "https://example.com/browser/" + RELATIVE_DIR + "hashRedirect.sjs"; + url += "?sha1:3d0dc22e1f394e159b08aaf5f0f97de4d5c65f4f|" + TESTROOT + "unsigned.xpi"; + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: url, + toString: function() { return this.URL; } + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove("example.com", "install"); + Services.prefs.clearUserPref(PREF_INSTALL_REQUIREBUILTINCERTS); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_httphash2.js b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash2.js new file mode 100644 index 000000000..93326af9f --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash2.js @@ -0,0 +1,39 @@ +// ---------------------------------------------------------------------------- +// Test whether an install fails when a invalid hash is included in the HTTPS +// request +// This verifies bug 591070 +function test() { + Harness.downloadFailedCallback = download_failed; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false); + + var url = "https://example.com/browser/" + RELATIVE_DIR + "hashRedirect.sjs"; + url += "?sha1:foobar|" + TESTROOT + "unsigned.xpi"; + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: url, + toString: function() { return this.URL; } + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function download_failed(install) { + is(install.error, AddonManager.ERROR_INCORRECT_HASH, "Download should fail"); +} + +function finish_test(count) { + is(count, 0, "0 Add-ons should have been successfully installed"); + + Services.perms.remove("example.com", "install"); + Services.prefs.clearUserPref(PREF_INSTALL_REQUIREBUILTINCERTS); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_httphash3.js b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash3.js new file mode 100644 index 000000000..76a6283fb --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash3.js @@ -0,0 +1,39 @@ +// ---------------------------------------------------------------------------- +// Tests that the HTTPS hash is ignored when InstallTrigger is passed a hash. +// This verifies bug 591070 +function test() { + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false); + + var url = "https://example.com/browser/" + RELATIVE_DIR + "hashRedirect.sjs"; + url += "?sha1:foobar|" + TESTROOT + "unsigned.xpi"; + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: url, + Hash: "sha1:3d0dc22e1f394e159b08aaf5f0f97de4d5c65f4f", + toString: function() { return this.URL; } + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove("example.com", "install"); + Services.prefs.clearUserPref(PREF_INSTALL_REQUIREBUILTINCERTS); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_httphash4.js b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash4.js new file mode 100644 index 000000000..97dc64d1f --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash4.js @@ -0,0 +1,36 @@ +// ---------------------------------------------------------------------------- +// Test that hashes are ignored in the headers of HTTP requests +// This verifies bug 591070 +function test() { + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var url = "http://example.com/browser/" + RELATIVE_DIR + "hashRedirect.sjs"; + url += "?sha1:foobar|" + TESTROOT + "unsigned.xpi"; + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: url, + toString: function() { return this.URL; } + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove("example.com", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_httphash5.js b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash5.js new file mode 100644 index 000000000..1237989f6 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash5.js @@ -0,0 +1,40 @@ +// ---------------------------------------------------------------------------- +// Test that only the first HTTPS hash is used +// This verifies bug 591070 +function test() { + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false); + + var url = "https://example.com/browser/" + RELATIVE_DIR + "hashRedirect.sjs"; + url += "?sha1:3d0dc22e1f394e159b08aaf5f0f97de4d5c65f4f|"; + url += "https://example.com/browser/" + RELATIVE_DIR + "hashRedirect.sjs"; + url += "?sha1:foobar|" + TESTROOT + "unsigned.xpi"; + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: url, + toString: function() { return this.URL; } + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove("example.com", "install"); + Services.prefs.clearUserPref(PREF_INSTALL_REQUIREBUILTINCERTS); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_httphash6.js b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash6.js new file mode 100644 index 000000000..9ab490235 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash6.js @@ -0,0 +1,83 @@ +// ---------------------------------------------------------------------------- +// Tests that a new hash is accepted when restarting a failed download +// This verifies bug 593535 +function setup_redirect(aSettings) { + var url = "https://example.com/browser/" + RELATIVE_DIR + "redirect.sjs?mode=setup"; + for (var name in aSettings) { + url += "&" + name + "=" + aSettings[name]; + } + + var req = new XMLHttpRequest(); + req.open("GET", url, false); + req.send(null); +} + +var gInstall = null; + +function test() { + Harness.downloadFailedCallback = download_failed; + Harness.installsCompletedCallback = finish_failed_download; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false); + + // Set up the redirect to give a bad hash + setup_redirect({ + "X-Target-Digest": "sha1:foo", + "Location": "http://example.com/browser/" + RELATIVE_DIR + "unsigned.xpi" + }); + + var url = "https://example.com/browser/" + RELATIVE_DIR + "redirect.sjs?mode=redirect"; + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: url, + toString: function() { return this.URL; } + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function download_failed(install) { + is(install.error, AddonManager.ERROR_INCORRECT_HASH, "Should have seen a hash failure"); + // Stash the failed download while the harness cleans itself up + gInstall = install; +} + +function finish_failed_download() { + // Setup to track the successful re-download + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + // Give it the right hash this time + setup_redirect({ + "X-Target-Digest": "sha1:3d0dc22e1f394e159b08aaf5f0f97de4d5c65f4f", + "Location": "http://example.com/browser/" + RELATIVE_DIR + "unsigned.xpi" + }); + + // The harness expects onNewInstall events for all installs that are about to start + Harness.onNewInstall(gInstall); + + // Restart the install as a regular webpage install so the harness tracks it + AddonManager.installAddonsFromWebpage("application/x-xpinstall", + gBrowser.selectedBrowser, + gBrowser.contentPrincipal, [gInstall]); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove("example.com", "install"); + Services.prefs.clearUserPref(PREF_INSTALL_REQUIREBUILTINCERTS); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_installchrome.js b/toolkit/mozapps/extensions/test/xpinstall/browser_installchrome.js new file mode 100644 index 000000000..c3be10ec9 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_installchrome.js @@ -0,0 +1,25 @@ +// ---------------------------------------------------------------------------- +// Tests that calling InstallTrigger.installChrome works +function test() { + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installchrome.html? " + encodeURIComponent(TESTROOT + "unsigned.xpi")); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + Services.perms.remove("example.com", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_localfile.js b/toolkit/mozapps/extensions/test/xpinstall/browser_localfile.js new file mode 100644 index 000000000..0e70e8177 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_localfile.js @@ -0,0 +1,34 @@ +// ---------------------------------------------------------------------------- +// Tests installing an local file works when loading the url +function test() { + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var cr = Components.classes["@mozilla.org/chrome/chrome-registry;1"] + .getService(Components.interfaces.nsIChromeRegistry); + + var chromeroot = extractChromeRoot(gTestPath); + try { + var xpipath = cr.convertChromeURL(makeURI(chromeroot + "unsigned.xpi")).spec; + } catch (ex) { + var xpipath = chromeroot + "unsigned.xpi"; //scenario where we are running from a .jar and already extracted + } + + gBrowser.selectedTab = gBrowser.addTab("about:blank"); + BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => { + gBrowser.loadURI(xpipath); + }); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_localfile2.js b/toolkit/mozapps/extensions/test/xpinstall/browser_localfile2.js new file mode 100644 index 000000000..253ed15b9 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_localfile2.js @@ -0,0 +1,49 @@ +// ---------------------------------------------------------------------------- +// Test whether an install fails if the url is a local file when requested from +// web content +function test() { + waitForExplicitFinish(); + + var cr = Components.classes["@mozilla.org/chrome/chrome-registry;1"] + .getService(Components.interfaces.nsIChromeRegistry); + + var chromeroot = getChromeRoot(gTestPath); + try { + var xpipath = cr.convertChromeURL(makeURI(chromeroot + "unsigned.xpi")).spec; + } catch (ex) { + var xpipath = chromeroot + "unsigned.xpi"; //scenario where we are running from a .jar and already extracted + } + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": xpipath + })); + gBrowser.selectedTab = gBrowser.addTab(); + + function loadListener() { + gBrowser.selectedBrowser.removeEventListener("load", loadListener, true); + gBrowser.contentWindow.addEventListener("InstallTriggered", page_loaded, false); + } + + gBrowser.selectedBrowser.addEventListener("load", loadListener, true); + + // In non-e10s the exception in the content page would trigger a test failure + if (!gMultiProcessBrowser) + expectUncaughtException(); + + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function page_loaded() { + gBrowser.contentWindow.removeEventListener("InstallTriggered", page_loaded, false); + var doc = gBrowser.contentDocument; + is(doc.getElementById("return").textContent, "exception", "installTrigger should have failed"); + + // In non-e10s the exception from the page is thrown after the event so we + // have to spin the event loop to make sure it arrives so expectUncaughtException + // sees it. + executeSoon(() => { + gBrowser.removeCurrentTab(); + finish(); + }); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_localfile3.js b/toolkit/mozapps/extensions/test/xpinstall/browser_localfile3.js new file mode 100644 index 000000000..f24f41cd6 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_localfile3.js @@ -0,0 +1,40 @@ +// ---------------------------------------------------------------------------- +// Tests installing an add-on from a local file with whitelisting disabled. +// This should be blocked by the whitelist check. +function test() { + Harness.installBlockedCallback = allow_blocked; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + // Disable direct request whitelisting, installing from file should be blocked. + Services.prefs.setBoolPref("xpinstall.whitelist.directRequest", false); + + var cr = Components.classes["@mozilla.org/chrome/chrome-registry;1"] + .getService(Components.interfaces.nsIChromeRegistry); + + var chromeroot = extractChromeRoot(gTestPath); + try { + var xpipath = cr.convertChromeURL(makeURI(chromeroot + "unsigned.xpi")).spec; + } catch (ex) { + var xpipath = chromeroot + "unsigned.xpi"; //scenario where we are running from a .jar and already extracted + } + + gBrowser.selectedTab = gBrowser.addTab("about:blank"); + BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => { + gBrowser.loadURI(xpipath); + }); +} + +function allow_blocked(installInfo) { + ok(true, "Seen blocked"); + return false; +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + + Services.prefs.clearUserPref("xpinstall.whitelist.directRequest"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_localfile4.js b/toolkit/mozapps/extensions/test/xpinstall/browser_localfile4.js new file mode 100644 index 000000000..2e8263f19 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_localfile4.js @@ -0,0 +1,40 @@ +// ---------------------------------------------------------------------------- +// Tests installing an add-on from a local file with whitelisting disabled. +// This should be blocked by the whitelist check. +function test() { + Harness.installBlockedCallback = allow_blocked; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + // Disable file request whitelisting, installing by file referrer should be blocked. + Services.prefs.setBoolPref("xpinstall.whitelist.fileRequest", false); + + var cr = Components.classes["@mozilla.org/chrome/chrome-registry;1"] + .getService(Components.interfaces.nsIChromeRegistry); + + var chromeroot = extractChromeRoot(gTestPath); + try { + var xpipath = cr.convertChromeURL(makeURI(chromeroot)).spec; + } catch (ex) { + var xpipath = chromeroot; //scenario where we are running from a .jar and already extracted + } + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "unsigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(xpipath + "installtrigger.html?" + triggers); +} + +function allow_blocked(installInfo) { + ok(true, "Seen blocked"); + return false; +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + + Services.prefs.clearUserPref("xpinstall.whitelist.fileRequest"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_multipackage.js b/toolkit/mozapps/extensions/test/xpinstall/browser_multipackage.js new file mode 100644 index 000000000..c5e00008c --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_multipackage.js @@ -0,0 +1,53 @@ +// ---------------------------------------------------------------------------- +// Tests installing an signed add-on by navigating directly to the url +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + gBrowser.selectedTab = gBrowser.addTab("about:blank"); + BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => { + gBrowser.loadURI(TESTROOT + "multipackage.xpi"); + }); +} + +function get_item(items, name) { + for (let item of items) { + if (item.name == name) + return item; + } + ok(false, "Item for " + name + " was not listed"); + return null; +} + +function confirm_install(window) { + let items = window.document.getElementById("itemList").childNodes; + is(items.length, 2, "Should be 2 items listed in the confirmation dialog"); + + let item = get_item(items, "XPI Test"); + if (item) { + is(item.signed, "false", "Should not have listed the item as signed"); + is(item.icon, "", "Should have listed no icon for the item"); + } + + item = get_item(items, "Signed XPI Test"); + if (item) { + is(item.cert, "(Object Signer)", "Should have seen the signer"); + is(item.signed, "true", "Should have listed the item as signed"); + is(item.icon, "", "Should have listed no icon for the item"); + } + + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 2, "2 Add-ons should have been successfully installed"); + gBrowser.removeCurrentTab(); + Harness.finish(); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway.js b/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway.js new file mode 100644 index 000000000..a2ba85d53 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway.js @@ -0,0 +1,36 @@ +// ---------------------------------------------------------------------------- +// Tests that navigating away from the initiating page during the install +// doesn't break the install. +// This verifies bug 473060 +function test() { + Harness.downloadProgressCallback = download_progress; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "unsigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function download_progress(addon, value, maxValue) { + gBrowser.loadURI(TESTROOT + "enabled.html"); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove("example.com", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway2.js b/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway2.js new file mode 100644 index 000000000..46d4ffe1e --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway2.js @@ -0,0 +1,34 @@ +// ---------------------------------------------------------------------------- +// Tests that closing the initiating page during the install cancels the install +// to avoid spoofing the user. +function test() { + Harness.downloadProgressCallback = download_progress; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "unsigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function download_progress(addon, value, maxValue) { + gBrowser.removeCurrentTab(); +} + +function install_ended(install, addon) { + ok(false, "Should not have seen installs complete"); +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been successfully installed"); + + Services.perms.remove("example.com", "install"); + + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway3.js b/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway3.js new file mode 100644 index 000000000..7f55a65fe --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway3.js @@ -0,0 +1,75 @@ +// ---------------------------------------------------------------------------- +// Tests that navigating to a new origin cancels ongoing installs. + +// Block the modal install UI from showing. +let InstallPrompt = { + confirm: function(aBrowser, aUri, aInstalls, aCount) { + }, + + QueryInterface: XPCOMUtils.generateQI([Ci.amIWebInstallPrompt]), + + classID: Components.ID("{405f3c55-241f-40df-97f1-a6e60e250ec5}"), + + factory: { + registrar: Components.manager.QueryInterface(Ci.nsIComponentRegistrar), + + register: function() { + this.registrar.registerFactory(InstallPrompt.classID, "InstallPrompt", + "@mozilla.org/addons/web-install-prompt;1", + this); + }, + + unregister: function() { + this.registrar.unregisterFactory(InstallPrompt.classID, this); + }, + + // nsIFactory + createInstance: function(aOuter, aIID) { + if (aOuter) { + throw Components.Exception("Class does not allow aggregation", + Components.results.NS_ERROR_NO_AGGREGATION); + } + return InstallPrompt.QueryInterface(aIID); + }, + + QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory]) + } +}; + +function test() { + InstallPrompt.factory.register(); + registerCleanupFunction(() => { + InstallPrompt.factory.unregister(); + }); + + Harness.downloadProgressCallback = download_progress; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "unsigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function download_progress(addon, value, maxValue) { + gBrowser.loadURI(TESTROOT2 + "enabled.html"); +} + +function install_ended(install, addon) { + ok(false, "Should not have seen installs complete"); +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been successfully installed"); + + Services.perms.remove("http://example.com", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway4.js b/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway4.js new file mode 100644 index 000000000..61fc7d3ac --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_navigateaway4.js @@ -0,0 +1,44 @@ +// ---------------------------------------------------------------------------- +// Tests that navigating to a new origin cancels ongoing installs and closes +// the install UI. +let sawUnload = null; + +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "unsigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function confirm_install(window) { + sawUnload = BrowserTestUtils.waitForEvent(window, "unload"); + + gBrowser.loadURI(TESTROOT2 + "enabled.html"); + + return Harness.leaveOpen; +} + +function install_ended(install, addon) { + ok(false, "Should not have seen installs complete"); +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been successfully installed"); + + Services.perms.remove("http://example.com", "install"); + + sawUnload.then(() => { + ok(true, "The install UI should have closed itself."); + gBrowser.removeCurrentTab(); + Harness.finish(); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_offline.js b/toolkit/mozapps/extensions/test/xpinstall/browser_offline.js new file mode 100644 index 000000000..28f3497d1 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_offline.js @@ -0,0 +1,61 @@ +let proxyPrefValue; + +// ---------------------------------------------------------------------------- +// Tests that going offline cancels an in progress download. +function test() { + Harness.downloadProgressCallback = download_progress; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "unsigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function download_progress(addon, value, maxValue) { + try { + // Tests always connect to localhost, and per bug 87717, localhost is now + // reachable in offline mode. To avoid this, disable any proxy. + proxyPrefValue = Services.prefs.getIntPref("network.proxy.type"); + Services.prefs.setIntPref("network.proxy.type", 0); + Services.io.manageOfflineStatus = false; + Services.io.offline = true; + } catch (ex) { + } +} + +function finish_test(count) { + function wait_for_online() { + info("Checking if the browser is still offline..."); + + let tab = gBrowser.selectedTab; + tab.linkedBrowser.addEventListener("DOMContentLoaded", function errorLoad() { + tab.linkedBrowser.removeEventListener("DOMContentLoaded", errorLoad, true); + let url = tab.linkedBrowser.contentDocument.documentURI; + info("loaded: " + url); + if (/^about:neterror\?e=netOffline/.test(url)) { + wait_for_online(); + } else { + gBrowser.removeCurrentTab(); + Harness.finish(); + } + }, true); + tab.linkedBrowser.loadURI("http://example.com/"); + } + + is(count, 0, "No add-ons should have been installed"); + try { + Services.prefs.setIntPref("network.proxy.type", proxyPrefValue); + Services.io.offline = false; + } catch (ex) { + } + + Services.perms.remove("example.com", "install"); + + wait_for_online(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_relative.js b/toolkit/mozapps/extensions/test/xpinstall/browser_relative.js new file mode 100644 index 000000000..dfd5a0898 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_relative.js @@ -0,0 +1,49 @@ +// ---------------------------------------------------------------------------- +// Tests that InstallTrigger deals with relative urls correctly. +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.finalContentEvent = "InstallComplete"; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: "unsigned.xpi", + IconURL: "icon.png", + toString: function() { return this.URL; } + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function confirm_install(window) { + var items = window.document.getElementById("itemList").childNodes; + is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); + is(items[0].name, "XPI Test", "Should have seen the name"); + is(items[0].url, TESTROOT + "unsigned.xpi", "Should have listed the correct url for the item"); + is(items[0].icon, TESTROOT + "icon.png", "Should have listed the correct icon for the item"); + is(items[0].signed, "false", "Should have listed the item as unsigned"); + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove("example.com", "install"); + + var doc = gBrowser.contentDocument; + is(doc.getElementById("return").textContent, "true", "installTrigger should have claimed success"); + is(doc.getElementById("status").textContent, "0", "Callback should have seen a success"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_multiple.js b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_multiple.js new file mode 100644 index 000000000..e6efe5468 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_multiple.js @@ -0,0 +1,72 @@ +// ---------------------------------------------------------------------------- +// Tests installing two signed add-ons in the same trigger works. +// This verifies bug 453545 +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Signed XPI": TESTROOT + "signed.xpi", + "Signed XPI 2": TESTROOT + "signed2.xpi", + "Signed XPI 3": TESTROOT + "signed-no-o.xpi", + "Signed XPI 4": TESTROOT + "signed-no-cn.xpi", + "Signed XPI 5": TESTROOT + "unsigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function get_item(items, url) { + for (let item of items) { + if (item.url == url) + return item; + } + ok(false, "Item for " + url + " was not listed"); + return null; +} + +function confirm_install(window) { + + var sbs = Components.classes["@mozilla.org/intl/stringbundle;1"]. + getService(Components.interfaces.nsIStringBundleService); + var bundle = sbs.createBundle("chrome://mozapps/locale/xpinstall/xpinstallConfirm.properties"); + + var expectedIntroString = bundle.formatStringFromName("itemWarnIntroMultiple", ["5"], 1); + + var introStringNode = window.document.getElementById("itemWarningIntro"); + is(introStringNode.textContent, expectedIntroString, "Should have the correct intro string"); + + var items = window.document.getElementById("itemList").childNodes; + is(items.length, 5, "Should be 5 items listed in the confirmation dialog"); + let item = get_item(items, TESTROOT + "signed.xpi"); + if (item) { + is(item.name, "Signed XPI Test", "Should have seen the name from the trigger list"); + is(item.cert, "(Object Signer)", "Should have seen the signer"); + is(item.signed, "true", "Should have listed the item as signed"); + } + item = get_item(items, TESTROOT + "signed2.xpi"); + if (item) { + is(item.name, "Signed XPI Test", "Should have seen the name from the trigger list"); + is(item.cert, "(Object Signer)", "Should have seen the signer"); + is(item.signed, "true", "Should have listed the item as signed"); + } + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 5, "5 Add-ons should have been successfully installed"); + + Services.perms.remove("example.com", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_naming.js b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_naming.js new file mode 100644 index 000000000..c57ddb200 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_naming.js @@ -0,0 +1,67 @@ +// ---------------------------------------------------------------------------- +// Tests that the correct signer is presented for combinations of O and CN present. +// The signed files have (when present) O=Mozilla Testing, CN=Object Signer +// This verifies bug 372980 +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Signed XPI (O and CN)": TESTROOT + "signed.xpi", + "Signed XPI (CN)": TESTROOT + "signed-no-o.xpi", + "Signed XPI (O)": TESTROOT + "signed-no-cn.xpi", + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function get_item(items, url) { + for (let item of items) { + if (item.url == url) + return item; + } + ok(false, "Item for " + url + " was not listed"); + return null; +} + +function confirm_install(window) { + let items = window.document.getElementById("itemList").childNodes; + is(items.length, 3, "Should be 3 items listed in the confirmation dialog"); + let item = get_item(items, TESTROOT + "signed.xpi"); + if (item) { + is(item.name, "Signed XPI Test", "Should have seen the name from the trigger list"); + is(item.cert, "(Object Signer)", "Should have seen the signer"); + is(item.signed, "true", "Should have listed the item as signed"); + } + item = get_item(items, TESTROOT + "signed-no-o.xpi"); + if (item) { + is(item.name, "Signed XPI Test (No Org)", "Should have seen the name from the trigger list"); + is(item.cert, "(Object Signer)", "Should have seen the signer"); + is(item.signed, "true", "Should have listed the item as signed"); + } + item = get_item(items, TESTROOT + "signed-no-cn.xpi"); + if (item) { + is(item.name, "Signed XPI Test (No Common Name)", "Should have seen the name from the trigger list"); + is(item.cert, "(Mozilla Testing)", "Should have seen the signer"); + is(item.signed, "true", "Should have listed the item as signed"); + } + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 3, "3 Add-ons should have been successfully installed"); + + Services.perms.remove("example.com", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_tampered.js b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_tampered.js new file mode 100644 index 000000000..a3dc454d9 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_tampered.js @@ -0,0 +1,33 @@ +// ---------------------------------------------------------------------------- +// Tests installing a signed add-on that has been tampered with after signing. +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.downloadFailedCallback = download_failed; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Tampered Signed XPI": TESTROOT + "signed-tampered.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function confirm_install(window) { + ok(false, "Should not offer to install"); +} + +function download_failed(install) { + is(install.error, AddonManager.ERROR_CORRUPT_FILE, "Install should fail"); +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + Services.perms.remove("example.com", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_trigger.js b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_trigger.js new file mode 100644 index 000000000..cefce2a4c --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_trigger.js @@ -0,0 +1,41 @@ +// ---------------------------------------------------------------------------- +// Tests installing an signed add-on through an InstallTrigger call in web +// content. +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Signed XPI": TESTROOT + "signed.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function confirm_install(window) { + var items = window.document.getElementById("itemList").childNodes; + is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); + is(items[0].name, "Signed XPI Test", "Should have seen the name from the trigger list"); + is(items[0].url, TESTROOT + "signed.xpi", "Should have listed the correct url for the item"); + is(items[0].cert, "(Object Signer)", "Should have seen the signer"); + is(items[0].signed, "true", "Should have listed the item as signed"); + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove("example.com", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_untrusted.js b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_untrusted.js new file mode 100644 index 000000000..afb34d8a3 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_untrusted.js @@ -0,0 +1,41 @@ +// ---------------------------------------------------------------------------- +// Tests installing an add-on signed by an untrusted certificate through an +// InstallTrigger call in web content. +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Untrusted Signed XPI": TESTROOT + "signed-untrusted.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function confirm_install(window) { + var items = window.document.getElementById("itemList").childNodes; + is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); + is(items[0].name, "Signed XPI Test", "Should have had the filename for the item name"); + is(items[0].url, TESTROOT + "signed-untrusted.xpi", "Should have listed the correct url for the item"); + is(items[0].icon, "", "Should have listed no icon for the item"); + is(items[0].signed, "false", "Should have listed the item as unsigned"); + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + Services.perms.remove("example.com", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_url.js b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_url.js new file mode 100644 index 000000000..33cda6e4c --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_url.js @@ -0,0 +1,34 @@ +// ---------------------------------------------------------------------------- +// Tests installing an signed add-on by navigating directly to the url +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + gBrowser.selectedTab = gBrowser.addTab("about:blank"); + BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => { + gBrowser.loadURI(TESTROOT + "signed.xpi"); + }); +} + +function confirm_install(window) { + let items = window.document.getElementById("itemList").childNodes; + is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); + is(items[0].name, "Signed XPI Test", "Should have had the name"); + is(items[0].url, TESTROOT + "signed.xpi", "Should have listed the correct url for the item"); + is(items[0].cert, "(Object Signer)", "Should have seen the signer"); + is(items[0].signed, "true", "Should have listed the item as signed"); + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + gBrowser.removeCurrentTab(); + Harness.finish(); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_softwareupdate.js b/toolkit/mozapps/extensions/test/xpinstall/browser_softwareupdate.js new file mode 100644 index 000000000..4c3dc768e --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_softwareupdate.js @@ -0,0 +1,25 @@ +// ---------------------------------------------------------------------------- +// Tests that calling InstallTrigger.startSoftwareUpdate works +function test() { + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "startsoftwareupdate.html? " + encodeURIComponent(TESTROOT + "unsigned.xpi")); +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + Services.perms.remove("example.com", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_switchtab.js b/toolkit/mozapps/extensions/test/xpinstall/browser_switchtab.js new file mode 100644 index 000000000..9672de9bd --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_switchtab.js @@ -0,0 +1,49 @@ +// ---------------------------------------------------------------------------- +// Tests installing an unsigned add-on through an InstallTrigger call in web +// content. +let expectedTab = null; + +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: TESTROOT + "unsigned.xpi", + IconURL: TESTROOT + "icon.png", + toString: function() { return this.URL; } + } + })); + expectedTab = gBrowser.addTab(); + expectedTab.linkedBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function confirm_install(window) { + var items = window.document.getElementById("itemList").childNodes; + is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); + is(items[0].name, "XPI Test", "Should have seen the name"); + is(items[0].url, TESTROOT + "unsigned.xpi", "Should have listed the correct url for the item"); + is(items[0].icon, TESTROOT + "icon.png", "Should have listed the correct icon for the item"); + is(items[0].signed, "false", "Should have listed the item as unsigned"); + + is(gBrowser.selectedTab, expectedTab, "Should have switched to the installing tab."); + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove("example.com", "install"); + + gBrowser.removeTab(expectedTab); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_trigger_redirect.js b/toolkit/mozapps/extensions/test/xpinstall/browser_trigger_redirect.js new file mode 100644 index 000000000..a5448b616 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_trigger_redirect.js @@ -0,0 +1,41 @@ +// ---------------------------------------------------------------------------- +// Tests that the InstallTrigger callback can redirect to a relative url. +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.finalContentEvent = "InstallComplete"; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "triggerredirect.html"); +} + +function confirm_install(window) { + var items = window.document.getElementById("itemList").childNodes; + is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); + is(items[0].name, "XPI Test", "Should have seen the name"); + is(items[0].url, TESTROOT + "unsigned.xpi", "Should have listed the correct url for the item"); + is(items[0].icon, TESTROOT + "icon.png", "Should have listed the correct icon for the item"); + is(items[0].signed, "false", "Should have listed the item as unsigned"); + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove("example.com", "install"); + + var doc = gBrowser.contentDocument; + is(gBrowser.currentURI.spec, TESTROOT + "triggerredirect.html#foo", "Should have redirected"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger.js b/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger.js new file mode 100644 index 000000000..ab0f238aa --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger.js @@ -0,0 +1,50 @@ +// ---------------------------------------------------------------------------- +// Tests installing an unsigned add-on through an InstallTrigger call in web +// content. +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.finalContentEvent = "InstallComplete"; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: TESTROOT + "unsigned.xpi", + IconURL: TESTROOT + "icon.png", + toString: function() { return this.URL; } + } + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function confirm_install(window) { + var items = window.document.getElementById("itemList").childNodes; + is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); + is(items[0].name, "XPI Test", "Should have seen the name"); + is(items[0].url, TESTROOT + "unsigned.xpi", "Should have listed the correct url for the item"); + is(items[0].icon, TESTROOT + "icon.png", "Should have listed the correct icon for the item"); + is(items[0].signed, "false", "Should have listed the item as unsigned"); + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove("example.com", "install"); + + var doc = gBrowser.contentDocument; + is(doc.getElementById("return").textContent, "true", "installTrigger should have claimed success"); + is(doc.getElementById("status").textContent, "0", "Callback should have seen a success"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_iframe.js b/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_iframe.js new file mode 100644 index 000000000..658bbfe1c --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_iframe.js @@ -0,0 +1,51 @@ +// ---------------------------------------------------------------------------- +// Test for bug 589598 - Ensure that installing through InstallTrigger +// works in an iframe in web content. + +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.finalContentEvent = "InstallComplete"; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var inner_url = encodeURIComponent(TESTROOT + "installtrigger.html?" + encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: TESTROOT + "unsigned.xpi", + IconURL: TESTROOT + "icon.png", + toString: function() { return this.URL; } + } + }))); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger_frame.html?" + inner_url); +} + +function confirm_install(window) { + var items = window.document.getElementById("itemList").childNodes; + is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); + is(items[0].name, "XPI Test", "Should have seen the name"); + is(items[0].url, TESTROOT + "unsigned.xpi", "Should have listed the correct url for the item"); + is(items[0].icon, TESTROOT + "icon.png", "Should have listed the correct icon for the item"); + is(items[0].signed, "false", "Should have listed the item as unsigned"); + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove("example.com", "install"); + + var doc = gBrowser.contentWindow.frames[0].document; // Document of iframe + is(doc.getElementById("return").textContent, "true", "installTrigger in iframe should have claimed success"); + is(doc.getElementById("status").textContent, "0", "Callback in iframe should have seen a success"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_xorigin.js b/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_xorigin.js new file mode 100644 index 000000000..07947a135 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_xorigin.js @@ -0,0 +1,38 @@ +// ---------------------------------------------------------------------------- +// Ensure that an inner frame from a different origin can't initiate an install + +let wasOriginBlocked = false; + +function test() { + Harness.installOriginBlockedCallback = install_blocked; + Harness.installsCompletedCallback = finish_test; + Harness.finalContentEvent = "InstallComplete"; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var inner_url = encodeURIComponent(TESTROOT + "installtrigger.html?" + encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: TESTROOT + "unsigned.xpi", + IconURL: TESTROOT + "icon.png", + toString: function() { return this.URL; } + } + }))); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT2 + "installtrigger_frame.html?" + inner_url); +} + +function install_blocked(installInfo) { + wasOriginBlocked = true; +} + +function finish_test(count) { + ok(wasOriginBlocked, "Should have been blocked due to the cross origin request."); + + is(count, 0, "No add-ons should have been installed"); + Services.perms.remove("http://example.com", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_url.js b/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_url.js new file mode 100644 index 000000000..e103dffd3 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_url.js @@ -0,0 +1,35 @@ +// ---------------------------------------------------------------------------- +// Tests installing an unsigned add-on by navigating directly to the url +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + gBrowser.selectedTab = gBrowser.addTab("about:blank"); + BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => { + gBrowser.loadURI(TESTROOT + "unsigned.xpi"); + }); +} + +function confirm_install(window) { + let items = window.document.getElementById("itemList").childNodes; + is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); + is(items[0].name, "XPI Test", "Should have had the filename for the item name"); + is(items[0].url, TESTROOT + "unsigned.xpi", "Should have listed the correct url for the item"); + is(items[0].icon, "", "Should have listed no icon for the item"); + is(items[0].signed, "false", "Should have listed the item as unsigned"); + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist.js b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist.js new file mode 100644 index 000000000..448ce3a5c --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist.js @@ -0,0 +1,46 @@ +// ---------------------------------------------------------------------------- +// Tests installing an unsigned add-on through an InstallTrigger call in web +// content. This should be blocked by the whitelist check. +// This verifies bug 252830 +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installBlockedCallback = allow_blocked; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT + "unsigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function allow_blocked(installInfo) { + is(installInfo.browser, gBrowser.selectedBrowser, "Install should have been triggered by the right browser"); + is(installInfo.originatingURI.spec, gBrowser.currentURI.spec, "Install should have been triggered by the right uri"); + return true; +} + +function confirm_install(window) { + var items = window.document.getElementById("itemList").childNodes; + is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); + is(items[0].name, "XPI Test", "Should have seen the name from the trigger list"); + is(items[0].url, TESTROOT + "unsigned.xpi", "Should have listed the correct url for the item"); + is(items[0].signed, "false", "Should have listed the item as unsigned"); + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + var doc = gBrowser.contentDocument; + is(doc.getElementById("return").textContent, "false", "installTrigger should seen a failure"); + gBrowser.removeCurrentTab(); + Harness.finish(); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist2.js b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist2.js new file mode 100644 index 000000000..168a31ef3 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist2.js @@ -0,0 +1,31 @@ +// ---------------------------------------------------------------------------- +// Tests installing an unsigned add-on through an InstallTrigger call in web +// content. This should be blocked by the whitelist check because the source +// is not whitelisted, even though the target is. +function test() { + Harness.installBlockedCallback = allow_blocked; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.org/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": TESTROOT2 + "unsigned.xpi" + })); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function allow_blocked(installInfo) { + is(installInfo.browser, gBrowser.selectedBrowser, "Install should have been triggered by the right browser"); + is(installInfo.originatingURI.spec, gBrowser.currentURI.spec, "Install should have been triggered by the right uri"); + return false; +} + +function finish_test() { + Services.perms.remove("example.org", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist3.js b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist3.js new file mode 100644 index 000000000..888e1bd5a --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist3.js @@ -0,0 +1,28 @@ +// ---------------------------------------------------------------------------- +// Tests installing an unsigned add-on through a navigation. Should not be +// blocked since the referer is whitelisted. +let URL = TESTROOT2 + "navigate.html?" + encodeURIComponent(TESTROOT + "unsigned.xpi"); + +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.org/"), "install", pm.ALLOW_ACTION); + + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(URL); +} + +function confirm_install(window) { + return false; +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + Services.perms.remove("example.org", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist4.js b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist4.js new file mode 100644 index 000000000..14a961742 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist4.js @@ -0,0 +1,30 @@ +// ---------------------------------------------------------------------------- +// Tests installing an unsigned add-on through a navigation. Should be +// blocked since the referer is not whitelisted even though the target is. +let URL = TESTROOT2 + "navigate.html?" + encodeURIComponent(TESTROOT + "unsigned.xpi"); + +function test() { + Harness.installBlockedCallback = allow_blocked; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(URL); +} + +function allow_blocked(installInfo) { + is(installInfo.browser, gBrowser.selectedBrowser, "Install should have been triggered by the right browser"); + is(installInfo.originatingURI.spec, URL, "Install should have been triggered by the right uri"); + return false; +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + Services.perms.remove("example.com", "install"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist5.js b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist5.js new file mode 100644 index 000000000..97448d803 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist5.js @@ -0,0 +1,25 @@ +// ---------------------------------------------------------------------------- +// Tests installing an unsigned add-on through a startSoftwareUpdate call in web +// content. This should be blocked by the whitelist check. +// This verifies bug 252830 +function test() { + Harness.installBlockedCallback = allow_blocked; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "startsoftwareupdate.html? " + encodeURIComponent(TESTROOT + "unsigned.xpi")); +} + +function allow_blocked(installInfo) { + is(installInfo.browser, gBrowser.selectedBrowser, "Install should have been triggered by the right browser"); + is(installInfo.originatingURI.spec, gBrowser.currentURI.spec, "Install should have been triggered by the right uri"); + return false; +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + gBrowser.removeCurrentTab(); + Harness.finish(); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist6.js b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist6.js new file mode 100644 index 000000000..f2f3641e4 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist6.js @@ -0,0 +1,25 @@ +// ---------------------------------------------------------------------------- +// Tests installing an unsigned add-on through an installChrome call in web +// content. This should be blocked by the whitelist check. +// This verifies bug 252830 +function test() { + Harness.installBlockedCallback = allow_blocked; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.loadURI(TESTROOT + "installchrome.html? " + encodeURIComponent(TESTROOT + "unsigned.xpi")); +} + +function allow_blocked(installInfo) { + is(installInfo.browser, gBrowser.selectedBrowser, "Install should have been triggered by the right browser"); + is(installInfo.originatingURI.spec, gBrowser.currentURI.spec, "Install should have been triggered by the right uri"); + return false; +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + gBrowser.removeCurrentTab(); + Harness.finish(); +} +// ---------------------------------------------------------------------------- diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist7.js b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist7.js new file mode 100644 index 000000000..b36617ab5 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist7.js @@ -0,0 +1,32 @@ +// ---------------------------------------------------------------------------- +// Tests installing an unsigned add-on through a direct install request from +// web content. This should be blocked by the whitelist check because we disable +// direct request whitelisting, even though the target URI is whitelisted. +function test() { + Harness.installBlockedCallback = allow_blocked; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + // Disable direct request whitelisting, installing should be blocked. + Services.prefs.setBoolPref("xpinstall.whitelist.directRequest", false); + + gBrowser.selectedTab = gBrowser.addTab("about:blank"); + BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => { + gBrowser.loadURI(TESTROOT + "unsigned.xpi"); + }); +} + +function allow_blocked(installInfo) { + ok(true, "Seen blocked"); + return false; +} + +function finish_test(count) { + is(count, 0, "No add-ons should have been installed"); + + Services.perms.remove("example.org", "install"); + Services.prefs.clearUserPref("xpinstall.whitelist.directRequest"); + + gBrowser.removeCurrentTab(); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/bug540558.html b/toolkit/mozapps/extensions/test/xpinstall/bug540558.html new file mode 100644 index 000000000..666a56437 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/bug540558.html @@ -0,0 +1,23 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html> + +<!-- This page tests that window.InstallTrigger.install works --> + +<head> +<title>InstallTrigger tests</title> +<script type="text/javascript"> +function startInstall() { + window.InstallTrigger.install({ + "Unsigned XPI": "unsigned.xpi" + }); +} +</script> +</head> +<body onload="startInstall()"> +<p>InstallTrigger tests</p> +<p id="return"></p> +<p id="status"></p> +</body> +</html> diff --git a/toolkit/mozapps/extensions/test/xpinstall/bug638292.html b/toolkit/mozapps/extensions/test/xpinstall/bug638292.html new file mode 100644 index 000000000..198207d4b --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/bug638292.html @@ -0,0 +1,17 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html> + +<!-- This page tests InstallTrigger is defined in a new window --> + +<head> +<title>InstallTrigger tests</title> +</head> +<body> +<p>InstallTrigger tests</p> +<p><a id="link1" target="_blank" href="enabled.html">Open window with target</a></p> +<p><a id="link2" onclick="window.open(this.href); return false" href="enabled.html">Open window with JS</a></p> +<p><a id="link3" href="enabled.html">Open window with middle-click</a></p> +</body> +</html> diff --git a/toolkit/mozapps/extensions/test/xpinstall/bug645699.html b/toolkit/mozapps/extensions/test/xpinstall/bug645699.html new file mode 100644 index 000000000..9a65720ae --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/bug645699.html @@ -0,0 +1,30 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html> + +<head> +<title>InstallTrigger tests</title> +<script type="text/javascript"> +function startInstall() { + var whiteUrl = "https://example.org/"; + + try { + Object.defineProperty(window, "location", { value : { href : whiteUrl } }); + throw new Error("Object.defineProperty(window, 'location', ...) should have thrown"); + } catch (exc) { + if (!(exc instanceof TypeError)) + throw exc; + } + Object.defineProperty(document, "documentURIObject", { spec : { href : whiteUrl } }); + + InstallTrigger.install({ + "Unsigned XPI": "http://example.com/browser/toolkit/mozapps/extensions/test/xpinstall/unsigned.xpi" + }); +} +</script> +</head> +<body onload="startInstall()"> +<p>InstallTrigger tests</p> +</body> +</html> diff --git a/toolkit/mozapps/extensions/test/xpinstall/concurrent_installs.html b/toolkit/mozapps/extensions/test/xpinstall/concurrent_installs.html new file mode 100644 index 000000000..192bbf2bc --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/concurrent_installs.html @@ -0,0 +1,39 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html> + +<head> + <meta charset="utf-8"> +<title>Concurrent InstallTrigger tests</title> +<script type="text/javascript"> +function installCallback(url, status) { + document.getElementById("status").textContent = status; + + dump("Sending InstallComplete\n"); + var event = new CustomEvent("InstallComplete", {detail: {loc: location.href, xpi: url}}); + window.dispatchEvent(event); +} + +function startInstall() { + var root = location.href.replace("concurrent_installs.html", ""); + var triggers = { + "Unsigned XPI": root + "unsigned.xpi" + }; + try { + document.getElementById("return").textContent = InstallTrigger.install(triggers, installCallback); + } + catch (e) { + document.getElementById("return").textContent = "exception"; + throw e; + } +} +</script> +</head> +<body> +<p>InstallTrigger tests</p> +<button id="installnow" onclick="startInstall()">Click to install</button> +<p id="return"></p> +<p id="status"></p> +</body> +</html> diff --git a/toolkit/mozapps/extensions/test/xpinstall/cookieRedirect.sjs b/toolkit/mozapps/extensions/test/xpinstall/cookieRedirect.sjs new file mode 100644 index 000000000..92bccd9ec --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/cookieRedirect.sjs @@ -0,0 +1,24 @@ +// Simple script redirects to the query part of the uri if the cookie "xpinstall" +// has the value "true", otherwise gives a 500 error. + +function handleRequest(request, response) +{ + let cookie = null; + if (request.hasHeader("Cookie")) { + let cookies = request.getHeader("Cookie").split(";"); + for (let i = 0; i < cookies.length; i++) { + if (cookies[i].substring(0, 10) == "xpinstall=") + cookie = cookies[i].substring(10); + } + } + + if (cookie == "true") { + response.setStatusLine(request.httpVersion, 302, "Found"); + response.setHeader("Location", request.queryString); + response.write("See " + request.queryString); + } + else { + response.setStatusLine(request.httpVersion, 500, "Internal Server Error"); + response.write("Invalid request"); + } +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/corrupt.xpi b/toolkit/mozapps/extensions/test/xpinstall/corrupt.xpi new file mode 100644 index 000000000..35d7bd5e5 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/corrupt.xpi @@ -0,0 +1 @@ +This is a corrupt zip file diff --git a/toolkit/mozapps/extensions/test/xpinstall/empty.xpi b/toolkit/mozapps/extensions/test/xpinstall/empty.xpi Binary files differnew file mode 100644 index 000000000..74ed2b817 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/empty.xpi diff --git a/toolkit/mozapps/extensions/test/xpinstall/enabled.html b/toolkit/mozapps/extensions/test/xpinstall/enabled.html new file mode 100644 index 000000000..ec8513edc --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/enabled.html @@ -0,0 +1,23 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html> + +<!-- This page will test if InstallTrigger seems to be enabled --> + +<head> +<title>InstallTrigger tests</title> +<script type="text/javascript"> +function init() { + document.getElementById("enabled").textContent = InstallTrigger.enabled() ? "true" : "false"; + dump("Sending PageLoaded\n"); + var event = new CustomEvent("PageLoaded"); + window.dispatchEvent(event); +} +</script> +</head> +<body onload="init()"> +<p>InstallTrigger tests</p> +<p id="enabled"></p> +</body> +</html> diff --git a/toolkit/mozapps/extensions/test/xpinstall/hashRedirect.sjs b/toolkit/mozapps/extensions/test/xpinstall/hashRedirect.sjs new file mode 100644 index 000000000..324a092a3 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/hashRedirect.sjs @@ -0,0 +1,15 @@ +// Simple script redirects takes the query part of te request and splits it on +// the | character. Anything before is included as the X-Target-Digest header +// the latter part is used as the url to redirect to + +function handleRequest(request, response) +{ + let pos = request.queryString.indexOf("|"); + let header = request.queryString.substring(0, pos); + let url = request.queryString.substring(pos + 1); + + response.setStatusLine(request.httpVersion, 302, "Found"); + response.setHeader("X-Target-Digest", header); + response.setHeader("Location", url); + response.write("See " + url); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/head.js b/toolkit/mozapps/extensions/test/xpinstall/head.js new file mode 100644 index 000000000..90db29924 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/head.js @@ -0,0 +1,424 @@ +const RELATIVE_DIR = "toolkit/mozapps/extensions/test/xpinstall/"; + +const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR; +const TESTROOT2 = "http://example.org/browser/" + RELATIVE_DIR; +const XPINSTALL_URL = "chrome://mozapps/content/xpinstall/xpinstallConfirm.xul"; +const PROMPT_URL = "chrome://global/content/commonDialog.xul"; +const ADDONS_URL = "chrome://mozapps/content/extensions/extensions.xul"; +const PREF_LOGGING_ENABLED = "extensions.logging.enabled"; +const PREF_INSTALL_REQUIREBUILTINCERTS = "extensions.install.requireBuiltInCerts"; +const PREF_INSTALL_REQUIRESECUREORIGIN = "extensions.install.requireSecureOrigin"; +const CHROME_NAME = "mochikit"; + +function getChromeRoot(path) { + if (path === undefined) { + return "chrome://" + CHROME_NAME + "/content/browser/" + RELATIVE_DIR + } + return getRootDirectory(path); +} + +function extractChromeRoot(path) { + var chromeRootPath = getChromeRoot(path); + var jar = getJar(chromeRootPath); + if (jar) { + var tmpdir = extractJarToTmp(jar); + return "file://" + tmpdir.path + "/"; + } + return chromeRootPath; +} + +/** + * This is a test harness designed to handle responding to UI during the process + * of installing an XPI. A test can set callbacks to hear about specific parts + * of the sequence. + * Before use setup must be called and finish must be called afterwards. + */ +var Harness = { + // If set then the callback is called when an install is attempted and + // software installation is disabled. + installDisabledCallback: null, + // If set then the callback is called when an install is attempted and + // then canceled. + installCancelledCallback: null, + // If set then the callback will be called when an install's origin is blocked. + installOriginBlockedCallback: null, + // If set then the callback will be called when an install is blocked by the + // whitelist. The callback should return true to continue with the install + // anyway. + installBlockedCallback: null, + // If set will be called in the event of authentication being needed to get + // the xpi. Should return a 2 element array of username and password, or + // null to not authenticate. + authenticationCallback: null, + // If set this will be called to allow checking the contents of the xpinstall + // confirmation dialog. The callback should return true to continue the install. + installConfirmCallback: null, + // If set will be called when downloading of an item has begun. + downloadStartedCallback: null, + // If set will be called during the download of an item. + downloadProgressCallback: null, + // If set will be called when an xpi fails to download. + downloadFailedCallback: null, + // If set will be called when an xpi download is cancelled. + downloadCancelledCallback: null, + // If set will be called when downloading of an item has ended. + downloadEndedCallback: null, + // If set will be called when installation by the extension manager of an xpi + // item starts + installStartedCallback: null, + // If set will be called when an xpi fails to install. + installFailedCallback: null, + // If set will be called when each xpi item to be installed completes + // installation. + installEndedCallback: null, + // If set will be called when all triggered items are installed or the install + // is canceled. + installsCompletedCallback: null, + // If set the harness will wait for this DOM event before calling + // installsCompletedCallback + finalContentEvent: null, + + waitingForEvent: false, + pendingCount: null, + installCount: null, + runningInstalls: null, + + waitingForFinish: false, + + // A unique value to return from the installConfirmCallback to indicate that + // the install UI shouldn't be closed automatically + leaveOpen: {}, + + // Setup and tear down functions + setup: function() { + if (!this.waitingForFinish) { + waitForExplicitFinish(); + this.waitingForFinish = true; + + Services.prefs.setBoolPref(PREF_INSTALL_REQUIRESECUREORIGIN, false); + + Services.prefs.setBoolPref(PREF_LOGGING_ENABLED, true); + Services.obs.addObserver(this, "addon-install-started", false); + Services.obs.addObserver(this, "addon-install-disabled", false); + Services.obs.addObserver(this, "addon-install-origin-blocked", false); + Services.obs.addObserver(this, "addon-install-blocked", false); + Services.obs.addObserver(this, "addon-install-failed", false); + Services.obs.addObserver(this, "addon-install-complete", false); + + AddonManager.addInstallListener(this); + + Services.wm.addListener(this); + + var self = this; + registerCleanupFunction(function() { + Services.prefs.clearUserPref(PREF_LOGGING_ENABLED); + Services.prefs.clearUserPref(PREF_INSTALL_REQUIRESECUREORIGIN); + Services.obs.removeObserver(self, "addon-install-started"); + Services.obs.removeObserver(self, "addon-install-disabled"); + Services.obs.removeObserver(self, "addon-install-origin-blocked"); + Services.obs.removeObserver(self, "addon-install-blocked"); + Services.obs.removeObserver(self, "addon-install-failed"); + Services.obs.removeObserver(self, "addon-install-complete"); + + AddonManager.removeInstallListener(self); + + Services.wm.removeListener(self); + + AddonManager.getAllInstalls(function(aInstalls) { + is(aInstalls.length, 0, "Should be no active installs at the end of the test"); + aInstalls.forEach(function(aInstall) { + info("Install for " + aInstall.sourceURI + " is in state " + aInstall.state); + aInstall.cancel(); + }); + }); + }); + } + + this.installCount = 0; + this.pendingCount = 0; + this.runningInstalls = []; + }, + + finish: function() { + finish(); + }, + + endTest: function() { + let callback = this.installsCompletedCallback; + let count = this.installCount; + + is(this.runningInstalls.length, 0, "Should be no running installs left"); + this.runningInstalls.forEach(function(aInstall) { + info("Install for " + aInstall.sourceURI + " is in state " + aInstall.state); + }); + + this.installOriginBlockedCallback = null; + this.installBlockedCallback = null; + this.authenticationCallback = null; + this.installConfirmCallback = null; + this.downloadStartedCallback = null; + this.downloadProgressCallback = null; + this.downloadCancelledCallback = null; + this.downloadFailedCallback = null; + this.downloadEndedCallback = null; + this.installStartedCallback = null; + this.installFailedCallback = null; + this.installEndedCallback = null; + this.installsCompletedCallback = null; + this.runningInstalls = null; + + if (callback) + callback(count); + }, + + // Window open handling + windowReady: function(window) { + if (window.document.location.href == XPINSTALL_URL) { + if (this.installBlockedCallback) + ok(false, "Should have been blocked by the whitelist"); + this.pendingCount = window.document.getElementById("itemList").childNodes.length; + + // If there is a confirm callback then its return status determines whether + // to install the items or not. If not the test is over. + let result = true; + if (this.installConfirmCallback) { + result = this.installConfirmCallback(window); + if (result === this.leaveOpen) + return; + } + + if (!result) { + window.document.documentElement.cancelDialog(); + } + else { + // Initially the accept button is disabled on a countdown timer + var button = window.document.documentElement.getButton("accept"); + button.disabled = false; + window.document.documentElement.acceptDialog(); + } + } + else if (window.document.location.href == PROMPT_URL) { + var promptType = window.args.promptType; + switch (promptType) { + case "alert": + case "alertCheck": + case "confirmCheck": + case "confirm": + case "confirmEx": + window.document.documentElement.acceptDialog(); + break; + case "promptUserAndPass": + // This is a login dialog, hopefully an authentication prompt + // for the xpi. + if (this.authenticationCallback) { + var auth = this.authenticationCallback(); + if (auth && auth.length == 2) { + window.document.getElementById("loginTextbox").value = auth[0]; + window.document.getElementById("password1Textbox").value = auth[1]; + window.document.documentElement.acceptDialog(); + } + else { + window.document.documentElement.cancelDialog(); + } + } + else { + window.document.documentElement.cancelDialog(); + } + break; + default: + ok(false, "prompt type " + promptType + " not handled in test."); + break; + } + } + }, + + // Install blocked handling + + installDisabled: function(installInfo) { + ok(!!this.installDisabledCallback, "Installation shouldn't have been disabled"); + if (this.installDisabledCallback) + this.installDisabledCallback(installInfo); + this.endTest(); + }, + + installCancelled: function(installInfo) { + if (this.expectingCancelled) + return; + + ok(!!this.installCancelledCallback, "Installation shouldn't have been cancelled"); + if (this.installCancelledCallback) + this.installCancelledCallback(installInfo); + this.endTest(); + }, + + installOriginBlocked: function(installInfo) { + ok(!!this.installOriginBlockedCallback, "Shouldn't have been blocked"); + if (this.installOriginBlockedCallback) + this.installOriginBlockedCallback(installInfo); + this.endTest(); + }, + + installBlocked: function(installInfo) { + ok(!!this.installBlockedCallback, "Shouldn't have been blocked by the whitelist"); + if (this.installBlockedCallback && this.installBlockedCallback(installInfo)) { + this.installBlockedCallback = null; + installInfo.install(); + } + else { + this.expectingCancelled = true; + installInfo.installs.forEach(function(install) { + install.cancel(); + }); + this.expectingCancelled = false; + this.endTest(); + } + }, + + // nsIWindowMediatorListener + + onWindowTitleChange: function(window, title) { + }, + + onOpenWindow: function(window) { + var domwindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIDOMWindow); + var self = this; + waitForFocus(function() { + self.windowReady(domwindow); + }, domwindow); + }, + + onCloseWindow: function(window) { + }, + + // Addon Install Listener + + onNewInstall: function(install) { + this.runningInstalls.push(install); + + if (this.finalContentEvent && !this.waitingForEvent) { + this.waitingForEvent = true; + info("Waiting for " + this.finalContentEvent); + let win = gBrowser.contentWindow; + let listener = () => { + info("Saw " + this.finalContentEvent); + win.removeEventListener(this.finalContentEvent, listener, false); + this.waitingForEvent = false; + if (this.pendingCount == 0) + this.endTest(); + } + win.addEventListener(this.finalContentEvent, listener, false); + } + }, + + onDownloadStarted: function(install) { + this.pendingCount++; + if (this.downloadStartedCallback) + this.downloadStartedCallback(install); + }, + + onDownloadProgress: function(install) { + if (this.downloadProgressCallback) + this.downloadProgressCallback(install); + }, + + onDownloadEnded: function(install) { + if (this.downloadEndedCallback) + this.downloadEndedCallback(install); + }, + + onDownloadCancelled: function(install) { + isnot(this.runningInstalls.indexOf(install), -1, + "Should only see cancelations for started installs"); + this.runningInstalls.splice(this.runningInstalls.indexOf(install), 1); + + if (this.downloadCancelledCallback) + this.downloadCancelledCallback(install); + this.checkTestEnded(); + }, + + onDownloadFailed: function(install) { + if (this.downloadFailedCallback) + this.downloadFailedCallback(install); + this.checkTestEnded(); + }, + + onInstallStarted: function(install) { + if (this.installStartedCallback) + this.installStartedCallback(install); + }, + + onInstallEnded: function(install, addon) { + if (this.installEndedCallback) + this.installEndedCallback(install, addon); + this.installCount++; + this.checkTestEnded(); + }, + + onInstallFailed: function(install) { + if (this.installFailedCallback) + this.installFailedCallback(install); + this.checkTestEnded(); + }, + + checkTestEnded: function() { + if (--this.pendingCount == 0 && !this.waitingForEvent) + this.endTest(); + }, + + // nsIObserver + + observe: function(subject, topic, data) { + var installInfo = subject.QueryInterface(Components.interfaces.amIWebInstallInfo); + switch (topic) { + case "addon-install-started": + is(this.runningInstalls.length, installInfo.installs.length, + "Should have seen the expected number of installs started"); + break; + case "addon-install-disabled": + this.installDisabled(installInfo); + break; + case "addon-install-cancelled": + this.installCancelled(installInfo); + break; + case "addon-install-origin-blocked": + this.installOriginBlocked(installInfo); + break; + case "addon-install-blocked": + this.installBlocked(installInfo); + break; + case "addon-install-failed": + installInfo.installs.forEach(function(aInstall) { + isnot(this.runningInstalls.indexOf(aInstall), -1, + "Should only see failures for started installs"); + + ok(aInstall.error != 0 || aInstall.addon.appDisabled, + "Failed installs should have an error or be appDisabled"); + + this.runningInstalls.splice(this.runningInstalls.indexOf(aInstall), 1); + }, this); + break; + case "addon-install-complete": + installInfo.installs.forEach(function(aInstall) { + isnot(this.runningInstalls.indexOf(aInstall), -1, + "Should only see completed events for started installs"); + + is(aInstall.error, 0, "Completed installs should have no error"); + ok(!aInstall.appDisabled, "Completed installs should not be appDisabled"); + + // Complete installs are either in the INSTALLED or CANCELLED state + // since the test may cancel installs the moment they complete. + ok(aInstall.state == AddonManager.STATE_INSTALLED || + aInstall.state == AddonManager.STATE_CANCELLED, + "Completed installs should be in the right state"); + + this.runningInstalls.splice(this.runningInstalls.indexOf(aInstall), 1); + }, this); + break; + } + }, + + QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, + Ci.nsIWindowMediatorListener, + Ci.nsISupports]) +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/incompatible.xpi b/toolkit/mozapps/extensions/test/xpinstall/incompatible.xpi Binary files differnew file mode 100644 index 000000000..cc40f43c9 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/incompatible.xpi diff --git a/toolkit/mozapps/extensions/test/xpinstall/installchrome.html b/toolkit/mozapps/extensions/test/xpinstall/installchrome.html new file mode 100644 index 000000000..71c072d3a --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/installchrome.html @@ -0,0 +1,21 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html> + +<!-- This page will accept a url as the uri query and pass it to InstallTrigger.installChrome --> + +<head> +<title>InstallTrigger tests</title> +<script type="text/javascript"> +function startInstall() { + InstallTrigger.installChrome(InstallTrigger.SKIN, + decodeURIComponent(document.location.search.substring(1)), + "test"); +} +</script> +</head> +<body onload="startInstall()"> +<p>InstallTrigger tests</p> +</body> +</html> diff --git a/toolkit/mozapps/extensions/test/xpinstall/installtrigger.html b/toolkit/mozapps/extensions/test/xpinstall/installtrigger.html new file mode 100644 index 000000000..cd7618cc5 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/installtrigger.html @@ -0,0 +1,43 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html> + +<!-- This page will accept some json as the uri query and pass it to InstallTrigger.install --> + +<head> +<title>InstallTrigger tests</title> +<script type="text/javascript"> +function installCallback(url, status) { + document.getElementById("status").textContent = status; + + dump("Sending InstallComplete\n"); + var event = new CustomEvent("InstallComplete"); + var target = window.parent ? window.parent : window; + target.dispatchEvent(event); +} + +function startInstall() { + var event = new CustomEvent("InstallTriggered"); + var text = decodeURIComponent(document.location.search.substring(1)); + var triggers = JSON.parse(text); + try { + document.getElementById("return").textContent = InstallTrigger.install(triggers, installCallback); + dump("Sending InstallTriggered\n"); + window.dispatchEvent(event); + } + catch (e) { + document.getElementById("return").textContent = "exception"; + dump("Sending InstallTriggered\n"); + window.dispatchEvent(event); + throw e; + } +} +</script> +</head> +<body onload="startInstall()"> +<p>InstallTrigger tests</p> +<p id="return"></p> +<p id="status"></p> +</body> +</html> diff --git a/toolkit/mozapps/extensions/test/xpinstall/installtrigger_frame.html b/toolkit/mozapps/extensions/test/xpinstall/installtrigger_frame.html new file mode 100644 index 000000000..2b302642e --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/installtrigger_frame.html @@ -0,0 +1,29 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html> + +<!-- This page will accept some url as the uri query and load it in + an inner iframe, which will run InstallTrigger.install --> + +<head> +<title>InstallTrigger frame tests</title> +<script type="text/javascript"> +function prepChild() { + // Pass our parameters over to the child + var child = window.frames[0]; + var url = decodeURIComponent(document.location.search.substr(1)); + child.location = url; +} +</script> +</head> +<body onload="prepChild()"> + +<iframe src="about:blank"> +</iframe> + +<p>InstallTrigger tests</p> +<p id="return"></p> +<p id="status"></p> +</body> +</html> diff --git a/toolkit/mozapps/extensions/test/xpinstall/multipackage.xpi b/toolkit/mozapps/extensions/test/xpinstall/multipackage.xpi Binary files differnew file mode 100644 index 000000000..11fbe1861 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/multipackage.xpi diff --git a/toolkit/mozapps/extensions/test/xpinstall/navigate.html b/toolkit/mozapps/extensions/test/xpinstall/navigate.html new file mode 100644 index 000000000..5a6903eb9 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/navigate.html @@ -0,0 +1,26 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html> + +<!-- This page will accept some url as the uri query and navigate to it by + clicking a link --> + +<head> +<title>Navigation tests</title> +<script type="text/javascript"> +function navigate() { + // Pass our parameters over to the child + var child = window.frames[0]; + var url = decodeURIComponent(document.location.search.substr(1)); + var link = document.getElementById("link"); + link.href = url; + link.click(); +} +</script> +</head> +<body onload="navigate()"> + +<p><a id="link">Test Link</a></p> +</body> +</html> diff --git a/toolkit/mozapps/extensions/test/xpinstall/redirect.sjs b/toolkit/mozapps/extensions/test/xpinstall/redirect.sjs new file mode 100644 index 000000000..d248bfbc7 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/redirect.sjs @@ -0,0 +1,45 @@ +// Script has two modes based on the query string. If the mode is "setup" then +// parameters from the query string configure the redirection. If the mode is +// "redirect" then a redirect is returned + +function handleRequest(request, response) +{ + let parts = request.queryString.split("&"); + let settings = {}; + + parts.forEach(function(aString) { + let [k, v] = aString.split("="); + settings[k] = decodeURIComponent(v); + }) + + if (settings.mode == "setup") { + delete settings.mode; + + // Object states must be an nsISupports + var state = { + settings: settings, + QueryInterface: function(aIid) { + if (aIid.equals(Components.interfaces.nsISupports)) + return settings; + throw Components.results.NS_ERROR_NO_INTERFACE; + } + } + state.wrappedJSObject = state; + + setObjectState("xpinstall-redirect-settings", state); + response.setStatusLine(request.httpVersion, 200, "Ok"); + response.setHeader("Content-Type", "text/plain"); + response.write("Setup complete"); + } + else if (settings.mode == "redirect") { + getObjectState("xpinstall-redirect-settings", function(aObject) { + settings = aObject.wrappedJSObject.settings; + }); + + response.setStatusLine(request.httpVersion, 302, "Found"); + for (var name in settings) { + response.setHeader(name, settings[name]); + } + response.write("Done"); + } +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/restartless.xpi b/toolkit/mozapps/extensions/test/xpinstall/restartless.xpi Binary files differnew file mode 100644 index 000000000..973bc00cb --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/restartless.xpi diff --git a/toolkit/mozapps/extensions/test/xpinstall/signed-no-cn.xpi b/toolkit/mozapps/extensions/test/xpinstall/signed-no-cn.xpi Binary files differnew file mode 100644 index 000000000..90d3a3ce6 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/signed-no-cn.xpi diff --git a/toolkit/mozapps/extensions/test/xpinstall/signed-no-o.xpi b/toolkit/mozapps/extensions/test/xpinstall/signed-no-o.xpi Binary files differnew file mode 100644 index 000000000..19b754038 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/signed-no-o.xpi diff --git a/toolkit/mozapps/extensions/test/xpinstall/signed-tampered.xpi b/toolkit/mozapps/extensions/test/xpinstall/signed-tampered.xpi Binary files differnew file mode 100644 index 000000000..8c951881e --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/signed-tampered.xpi diff --git a/toolkit/mozapps/extensions/test/xpinstall/signed-untrusted.xpi b/toolkit/mozapps/extensions/test/xpinstall/signed-untrusted.xpi Binary files differnew file mode 100644 index 000000000..09789d189 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/signed-untrusted.xpi diff --git a/toolkit/mozapps/extensions/test/xpinstall/signed.xpi b/toolkit/mozapps/extensions/test/xpinstall/signed.xpi Binary files differnew file mode 100644 index 000000000..bd7f78b7c --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/signed.xpi diff --git a/toolkit/mozapps/extensions/test/xpinstall/signed2.xpi b/toolkit/mozapps/extensions/test/xpinstall/signed2.xpi Binary files differnew file mode 100644 index 000000000..085efbbf7 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/signed2.xpi diff --git a/toolkit/mozapps/extensions/test/xpinstall/slowinstall.sjs b/toolkit/mozapps/extensions/test/xpinstall/slowinstall.sjs new file mode 100644 index 000000000..5f767a8f4 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/slowinstall.sjs @@ -0,0 +1,101 @@ +const { classes: Cc, interfaces: Ci, utils: Cu } = Components; + +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/osfile.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); + +const RELATIVE_PATH = "browser/toolkit/mozapps/extensions/test/xpinstall" +const NOTIFICATION_TOPIC = "slowinstall-complete"; + +/** + * Helper function to create a JS object representing the url parameters from + * the request's queryString. + * + * @param aQueryString + * The request's query string. + * @return A JS object representing the url parameters from the request's + * queryString. + */ +function parseQueryString(aQueryString) { + var paramArray = aQueryString.split("&"); + var regex = /^([^=]+)=(.*)$/; + var params = {}; + for (var i = 0, sz = paramArray.length; i < sz; i++) { + var match = regex.exec(paramArray[i]); + if (!match) + throw "Bad parameter in queryString! '" + paramArray[i] + "'"; + params[decodeURIComponent(match[1])] = decodeURIComponent(match[2]); + } + + return params; +} + +function handleRequest(aRequest, aResponse) { + let id = +getState("ID"); + setState("ID", "" + (id + 1)); + + function LOG(str) { + dump("slowinstall.sjs[" + id + "]: " + str + "\n"); + } + + aResponse.setStatusLine(aRequest.httpVersion, 200, "OK"); + + var params = { }; + if (aRequest.queryString) + params = parseQueryString(aRequest.queryString); + + if (params.file) { + let xpiFile = ""; + + function complete_download() { + LOG("Completing download"); + downloadPaused = false; + + try { + // Doesn't seem to be a sane way to read using OS.File and write to an + // nsIOutputStream so here we are. + let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); + file.initWithPath(xpiFile); + let stream = Cc["@mozilla.org/network/file-input-stream;1"]. + createInstance(Ci.nsIFileInputStream); + stream.init(file, -1, -1, stream.DEFER_OPEN + stream.CLOSE_ON_EOF); + + NetUtil.asyncCopy(stream, aResponse.bodyOutputStream, () => { + LOG("Download complete"); + aResponse.finish(); + }); + } + catch (e) { + LOG("Exception " + e); + } + } + + let waitForComplete = new Promise(resolve => { + function complete() { + Services.obs.removeObserver(complete, NOTIFICATION_TOPIC); + resolve(); + } + + Services.obs.addObserver(complete, NOTIFICATION_TOPIC, false); + }); + + aResponse.processAsync(); + + OS.File.getCurrentDirectory().then(dir => { + xpiFile = OS.Path.join(dir, ...RELATIVE_PATH.split("/"), params.file); + LOG("Starting slow download of " + xpiFile); + + OS.File.stat(xpiFile).then(info => { + aResponse.setHeader("Content-Type", "binary/octet-stream"); + aResponse.setHeader("Content-Length", info.size.toString()); + + LOG("Download paused"); + waitForComplete.then(complete_download); + }); + }); + } + else if (params.continue) { + dump("slowinstall.sjs: Received signal to complete all current downloads.\n"); + Services.obs.notifyObservers(null, NOTIFICATION_TOPIC, null); + } +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/startsoftwareupdate.html b/toolkit/mozapps/extensions/test/xpinstall/startsoftwareupdate.html new file mode 100644 index 000000000..4845a504a --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/startsoftwareupdate.html @@ -0,0 +1,19 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html> + +<!-- This page will accept a url as the uri query and pass it to InstallTrigger.startSoftwareUpdate --> + +<head> +<title>InstallTrigger tests</title> +<script type="text/javascript"> +function startInstall() { + InstallTrigger.startSoftwareUpdate(decodeURIComponent(document.location.search.substring(1))); +} +</script> +</head> +<body onload="startInstall()"> +<p>InstallTrigger tests</p> +</body> +</html> diff --git a/toolkit/mozapps/extensions/test/xpinstall/theme.xpi b/toolkit/mozapps/extensions/test/xpinstall/theme.xpi Binary files differnew file mode 100644 index 000000000..0c94a280b --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/theme.xpi diff --git a/toolkit/mozapps/extensions/test/xpinstall/triggerredirect.html b/toolkit/mozapps/extensions/test/xpinstall/triggerredirect.html new file mode 100644 index 000000000..49fda7dc8 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/triggerredirect.html @@ -0,0 +1,35 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html> + +<!-- This page will attempt an install and then try to load a new page in the tab --> + +<head> +<title>InstallTrigger tests</title> +<script type="text/javascript"> +function installCallback(url, status) { + document.location = "#foo"; + + dump("Sending InstallComplete\n"); + var event = new CustomEvent("InstallComplete"); + window.dispatchEvent(event); +} + +function startInstall() { + InstallTrigger.install({ + "Unsigned XPI": { + URL: "unsigned.xpi", + IconURL: "icon.png", + toString: function() { return this.URL; } + } + }, installCallback); +} +</script> +</head> +<body onload="startInstall()"> +<p>InstallTrigger tests</p> +<p id="return"></p> +<p id="status"></p> +</body> +</html> diff --git a/toolkit/mozapps/extensions/test/xpinstall/unsigned.xpi b/toolkit/mozapps/extensions/test/xpinstall/unsigned.xpi Binary files differnew file mode 100644 index 000000000..51b00475a --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/unsigned.xpi |