diff options
Diffstat (limited to 'toolkit/mozapps/extensions/test/xpcshell')
263 files changed, 46370 insertions, 0 deletions
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] |