mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to fx-team. a=merge
This commit is contained in:
commit
57165df10b
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="d839242c2a4a6a445cbd8bc2443acbdf712a19fc"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="d4583df788d33119f1fc4c68dca40a986a9bf18b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="d839242c2a4a6a445cbd8bc2443acbdf712a19fc"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="d4583df788d33119f1fc4c68dca40a986a9bf18b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8b04b5aca4b0a894de40f4d53ae9750222d349a8"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="276ce45e78b09c4a4ee643646f691d22804754c1">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="d839242c2a4a6a445cbd8bc2443acbdf712a19fc"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="d4583df788d33119f1fc4c68dca40a986a9bf18b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="d839242c2a4a6a445cbd8bc2443acbdf712a19fc"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="d4583df788d33119f1fc4c68dca40a986a9bf18b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="d839242c2a4a6a445cbd8bc2443acbdf712a19fc"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="d4583df788d33119f1fc4c68dca40a986a9bf18b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8b04b5aca4b0a894de40f4d53ae9750222d349a8"/>
|
||||
@ -130,13 +130,13 @@
|
||||
<project name="platform/external/dbus" path="external/dbus" revision="ea87119c843116340f5df1d94eaf8275e1055ae8"/>
|
||||
<project name="platform_external_libnfc-nci" path="external/libnfc-nci" remote="t2m" revision="4186bdecb4dae911b39a8202252cc2310d91b0be"/>
|
||||
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="320b05a5761eb2a4816f7529c91ea49422979b55"/>
|
||||
<project name="platform/frameworks/av" path="frameworks/av" revision="5b934dc57dae25f286b0e7210dc6ff47f3244927"/>
|
||||
<project name="platform/frameworks/base" path="frameworks/base" revision="af3e4fbdc9369643a92015ea2657361f3b1b46fe"/>
|
||||
<project name="platform/frameworks/native" path="frameworks/native" revision="33a2b51f78416536e1bfba0c0b7776db307f3a4f"/>
|
||||
<project name="platform/frameworks/av" path="frameworks/av" revision="0f7829661cd7125de9dc2c90eca2fa1dbc68dfbf"/>
|
||||
<project name="platform/frameworks/base" path="frameworks/base" revision="228d9f4189c42a11a65946420e836faa54073291"/>
|
||||
<project name="platform/frameworks/native" path="frameworks/native" revision="be9db09a9889fa0dcf6539f39598c11fb2a3be44"/>
|
||||
<project name="platform/hardware/libhardware" path="hardware/libhardware" revision="484802559ed106bac4811bd01c024ca64f741e60"/>
|
||||
<project name="platform/hardware/qcom/audio" path="hardware/qcom/audio" revision="83f363a26069e9c188d2aaef5b9ef63e84ad1511"/>
|
||||
<project name="platform/hardware/qcom/audio" path="hardware/qcom/audio" revision="de4ade568b273781416638fbbce13ff31b636ada"/>
|
||||
<project name="platform/hardware/qcom/camera" path="hardware/qcom/camera" revision="5e110615212302c5d798a3c223dcee458817651c"/>
|
||||
<project name="platform/hardware/qcom/display" path="hardware/qcom/display" revision="280d29203b2aa30d713c5a6cc63d626e5a7df822"/>
|
||||
<project name="platform/hardware/qcom/display" path="hardware/qcom/display" revision="fa9ffd47948eb24466de227e48fe9c4a7c5e7711"/>
|
||||
<project name="platform/hardware/qcom/gps" path="hardware/qcom/gps" revision="5dc48bd46f9589653f8bf297be5d73676f2e2867"/>
|
||||
<project name="platform/hardware/qcom/media" path="hardware/qcom/media" revision="8a0d0b0d9889ef99c4c6317c810db4c09295f15a"/>
|
||||
<project name="platform/hardware/qcom/wlan" path="hardware/qcom/wlan" revision="2208fa3537ace873b8f9ec2355055761c79dfd5f"/>
|
||||
|
@ -4,6 +4,6 @@
|
||||
"remote": "",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "4af9ed6ff7ff454659aa3b443b466dc1527c607f",
|
||||
"revision": "f96a2a006cb9a1d304a171f642718f3c3a644dad",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="d839242c2a4a6a445cbd8bc2443acbdf712a19fc"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="d4583df788d33119f1fc4c68dca40a986a9bf18b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="d839242c2a4a6a445cbd8bc2443acbdf712a19fc"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="d4583df788d33119f1fc4c68dca40a986a9bf18b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="d839242c2a4a6a445cbd8bc2443acbdf712a19fc"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="d4583df788d33119f1fc4c68dca40a986a9bf18b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8b04b5aca4b0a894de40f4d53ae9750222d349a8"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="d839242c2a4a6a445cbd8bc2443acbdf712a19fc"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="d4583df788d33119f1fc4c68dca40a986a9bf18b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0"?>
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1405034316000">
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1405723700000">
|
||||
<emItems>
|
||||
<emItem blockID="i454" id="sqlmoz@facebook.com">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
@ -261,6 +261,10 @@
|
||||
<pref>browser.startup.homepage</pref>
|
||||
<pref>browser.search.defaultenginename</pref>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i7" id="{2224e955-00e9-4613-a844-ce69fccaae91}">
|
||||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i174" id="info@thebflix.com">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
@ -280,10 +284,11 @@
|
||||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i172" id="info@bflix.info">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
<emItem blockID="i670" id="/^({ad9a41d2-9a49-4fa6-a79e-71a0785364c8})|(ffxtlbr@mysearchdial\.com)$/">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
<prefs>
|
||||
<pref>browser.search.defaultenginename</pref>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i93" id="{68b8676b-99a5-46d1-b390-22411d8bcd61}">
|
||||
@ -781,6 +786,12 @@
|
||||
</versionRange>
|
||||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i668" id="/^(matchersite(pro(src)?)?\@matchersite(pro(src)?)?\.com)|((pro)?sitematcher(_src|pro|site|sitesrc)?\@(pro)?sitematcher(_src|pro|site|sitesrc)?\.com)$/">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i440" id="{2d069a16-fca1-4e81-81ea-5d5086dcbd0c}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
@ -906,8 +917,10 @@
|
||||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i7" id="{2224e955-00e9-4613-a844-ce69fccaae91}">
|
||||
<prefs>
|
||||
<emItem blockID="i172" id="info@bflix.info">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
</versionRange>
|
||||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i525" id="/^({65f9f6b7-2dae-46fc-bfaf-f88e4af1beca}|{9ed31f84-c8b3-4926-b950-dff74047ff79}|{0134af61-7a0c-4649-aeca-90d776060cb3}|{02edb56b-9b33-435b-b7df-b2843273a694}|{da51d4f6-3e7e-4ef8-b400-9198e0874606}|{b24577db-155e-4077-bb37-3fdd3c302bb5})$/">
|
||||
@ -1907,7 +1920,8 @@
|
||||
<versionRange minVersion="0.1" maxVersion="17.0.1" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</pluginItem>
|
||||
<infoURL>https://get.adobe.com/flashplayer/</infoURL>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p102">
|
||||
<match name="filename" exp="npmozax\.dll" /> <versionRange minVersion="0" maxVersion="*"></versionRange>
|
||||
</pluginItem>
|
||||
@ -1977,35 +1991,40 @@
|
||||
<versionRange minVersion="4.0" maxVersion="16.*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</pluginItem>
|
||||
<infoURL>https://get.adobe.com/flashplayer/</infoURL>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p176">
|
||||
<match name="filename" exp="(NPSWF32\.dll)|(Flash\ Player\.plugin)" /> <versionRange minVersion="10.3" maxVersion="10.3.183.18.999" severity="0" vulnerabilitystatus="1">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="19.0a1" maxVersion="*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</pluginItem>
|
||||
<infoURL>https://get.adobe.com/flashplayer/</infoURL>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p176">
|
||||
<match name="filename" exp="(NPSWF32\.dll)|(Flash\ Player\.plugin)" /> <versionRange minVersion="10.3" maxVersion="10.3.183.18.999" severity="0" vulnerabilitystatus="1">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="17.0.4" maxVersion="17.0.*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</pluginItem>
|
||||
<infoURL>https://get.adobe.com/flashplayer/</infoURL>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p178">
|
||||
<match name="filename" exp="(NPSWF[0-9_]*\.dll)|(Flash\ Player\.plugin)" /> <versionRange minVersion="11.0" maxVersion="11.7.700.169" severity="0" vulnerabilitystatus="1">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="19.0a1" maxVersion="*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</pluginItem>
|
||||
<infoURL>https://get.adobe.com/flashplayer/</infoURL>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p178">
|
||||
<match name="filename" exp="(NPSWF[0-9_]*\.dll)|(Flash\ Player\.plugin)" /> <versionRange minVersion="11.0" maxVersion="11.7.700.169" severity="0" vulnerabilitystatus="1">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="17.0.4" maxVersion="17.0.*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</pluginItem>
|
||||
<infoURL>https://get.adobe.com/flashplayer/</infoURL>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p180">
|
||||
<match name="filename" exp="JavaAppletPlugin\.plugin" /> <versionRange minVersion="Java 7 Update 0" maxVersion="Java 7 Update 11" severity="0" vulnerabilitystatus="1">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
@ -2101,28 +2120,32 @@
|
||||
<versionRange minVersion="18.0a1" maxVersion="*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</pluginItem>
|
||||
<infoURL>https://get.adobe.com/flashplayer/</infoURL>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p260">
|
||||
<match name="filename" exp="(NPSWF32\.dll)|(Flash\ Player\.plugin)" /> <versionRange minVersion="0" maxVersion="10.2.9999" severity="0" vulnerabilitystatus="1">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="17.0.4" maxVersion="17.0.*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</pluginItem>
|
||||
<infoURL>https://get.adobe.com/flashplayer/</infoURL>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p290">
|
||||
<match name="filename" exp="(NPSWF32\.dll)|(Flash\ Player\.plugin)" /> <versionRange minVersion="10.3.183.19" maxVersion="10.3.183.66" severity="0" vulnerabilitystatus="1">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="19.0a1" maxVersion="*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</pluginItem>
|
||||
<infoURL>https://get.adobe.com/flashplayer/</infoURL>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p290">
|
||||
<match name="filename" exp="(NPSWF32\.dll)|(Flash\ Player\.plugin)" /> <versionRange minVersion="10.3.183.19" maxVersion="10.3.183.66" severity="0" vulnerabilitystatus="1">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="17.0.4" maxVersion="17.0.*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</pluginItem>
|
||||
<infoURL>https://get.adobe.com/flashplayer/</infoURL>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p292">
|
||||
<match name="filename" exp="JavaAppletPlugin\.plugin" /> <versionRange minVersion="Java 7 Update 12" maxVersion="Java 7 Update 15" severity="0" vulnerabilitystatus="1">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
@ -2185,28 +2208,32 @@
|
||||
<versionRange minVersion="19.0a1" maxVersion="*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</pluginItem>
|
||||
<infoURL>https://get.adobe.com/flashplayer/</infoURL>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p330">
|
||||
<match name="description" exp="^Shockwave Flash (([1-9]\.[0-9]+)|(10\.([0-2]|(3 r(([0-9][0-9]?)|1(([0-7][0-9])|8[0-2]))))))( |$)" /> <match name="filename" exp="libflashplayer\.so" /> <versionRange severity="0" vulnerabilitystatus="1">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="17.0.4" maxVersion="17.0.*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</pluginItem>
|
||||
<infoURL>https://get.adobe.com/flashplayer/</infoURL>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p332">
|
||||
<match name="description" exp="^Shockwave Flash 11.(0|1) r[0-9]{1,3}$" /> <match name="filename" exp="libflashplayer\.so" /> <versionRange severity="0" vulnerabilitystatus="1">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="19.0a1" maxVersion="*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</pluginItem>
|
||||
<infoURL>https://get.adobe.com/flashplayer/</infoURL>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p332">
|
||||
<match name="description" exp="^Shockwave Flash 11.(0|1) r[0-9]{1,3}$" /> <match name="filename" exp="libflashplayer\.so" /> <versionRange severity="0" vulnerabilitystatus="1">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="17.0.4" maxVersion="17.0.*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</pluginItem>
|
||||
<infoURL>https://get.adobe.com/flashplayer/</infoURL>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p366">
|
||||
<match name="filename" exp="Scorch\.plugin" /> <versionRange minVersion="6.2.0" maxVersion="6.2.0" severity="1"></versionRange>
|
||||
</pluginItem>
|
||||
|
@ -139,6 +139,8 @@ pref("app.update.cert.maxErrors", 5);
|
||||
// when the |app.update.cert.checkAttributes| preference is set to false. Also,
|
||||
// the |app.update.url.override| preference should ONLY be used for testing.
|
||||
// IMPORTANT! metro.js should also be updated for updates to certs.X.issuerName
|
||||
// IMPORTANT! media.gmp-manager.certs.* prefs should also be updated if these
|
||||
// are updated.
|
||||
|
||||
// Non-release builds (Nightly, Aurora, etc.) have been switched over to aus4.mozilla.org.
|
||||
// This condition protects us against accidentally using it for release builds.
|
||||
@ -1590,6 +1592,45 @@ pref("ui.key.menuAccessKeyFocuses", true);
|
||||
// Encrypted media extensions.
|
||||
pref("media.eme.enabled", false);
|
||||
|
||||
// GMPInstallManager prefs
|
||||
|
||||
// Enables some extra logging (can reduce performance)
|
||||
pref("media.gmp-manager.log", false);
|
||||
|
||||
// User-settable override to media.gmp-manager.url for testing purposes.
|
||||
//pref("media.gmp-manager.url.override", "");
|
||||
|
||||
// Update service URL for GMP install/updates:
|
||||
pref("media.gmp-manager.url", "https://aus4.mozilla.org/update/3/GMP/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml");
|
||||
|
||||
// When |media.gmp-manager.cert.requireBuiltIn| is true or not specified the
|
||||
// final certificate and all certificates the connection is redirected to before
|
||||
// the final certificate for the url specified in the |media.gmp-manager.url|
|
||||
// preference must be built-in.
|
||||
pref("media.gmp-manager.cert.requireBuiltIn", true);
|
||||
|
||||
// The |media.gmp-manager.certs.| preference branch contains branches that are
|
||||
// sequentially numbered starting at 1 that contain attribute name / value
|
||||
// pairs for the certificate used by the server that hosts the update xml file
|
||||
// as specified in the |media.gmp-manager.url| preference. When these preferences are
|
||||
// present the following conditions apply for a successful update check:
|
||||
// 1. the uri scheme must be https
|
||||
// 2. the preference name must exist as an attribute name on the certificate and
|
||||
// the value for the name must be the same as the value for the attribute name
|
||||
// on the certificate.
|
||||
// If these conditions aren't met it will be treated the same as when there is
|
||||
// no update available. This validation will not be performed when the
|
||||
// |media.gmp-manager.url.override| user preference has been set for testing updates or
|
||||
// when the |media.gmp-manager.cert.checkAttributes| preference is set to false. Also,
|
||||
// the |media.gmp-manager.url.override| preference should ONLY be used for testing.
|
||||
// IMPORTANT! app.update.certs.* prefs should also be updated if these
|
||||
// are updated.
|
||||
pref("media.gmp-manager.cert.checkAttributes", true);
|
||||
pref("media.gmp-manager.certs.1.issuerName", "CN=DigiCert Secure Server CA,O=DigiCert Inc,C=US");
|
||||
pref("media.gmp-manager.certs.1.commonName", "aus4.mozilla.org");
|
||||
pref("media.gmp-manager.certs.2.issuerName", "CN=Thawte SSL CA,O=\"Thawte, Inc.\",C=US");
|
||||
pref("media.gmp-manager.certs.2.commonName", "aus4.mozilla.org");
|
||||
|
||||
// Delete HTTP cache v2 data of users that didn't opt-in manually
|
||||
pref("browser.cache.auto_delete_cache_version", 1);
|
||||
// Play with different values of the decay time and get telemetry,
|
||||
@ -1612,4 +1653,4 @@ pref("experiments.manifest.certs.1.issuerName", "CN=Cybertrust Public SureServer
|
||||
pref("experiments.supported", true);
|
||||
|
||||
// Enable the OpenH264 plugin support in the addon manager.
|
||||
pref("media.openh264.providerEnabled", true);
|
||||
pref("media.gmp-gmpopenh264.provider.enabled", true);
|
||||
|
@ -21,6 +21,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "CharsetMenu",
|
||||
"resource://gre/modules/CharsetMenu.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ShortcutUtils",
|
||||
"resource://gre/modules/ShortcutUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "GMPInstallManager",
|
||||
"resource://gre/modules/GMPInstallManager.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gDNSService",
|
||||
"@mozilla.org/network/dns-service;1",
|
||||
@ -1316,6 +1318,14 @@ var gBrowserInit = {
|
||||
WindowsPrefSync.init();
|
||||
}
|
||||
|
||||
// Delay this a minute because there's no rush
|
||||
setTimeout(() => {
|
||||
this.gmpInstallManager = new GMPInstallManager();
|
||||
// We don't really care about the results, if somenoe is interested they
|
||||
// can check the log.
|
||||
this.gmpInstallManager.simpleCheckAndInstall();
|
||||
}, 1000 * 60);
|
||||
|
||||
SessionStore.promiseInitialized.then(() => {
|
||||
// Bail out if the window has been closed in the meantime.
|
||||
if (window.closed) {
|
||||
@ -1465,6 +1475,9 @@ var gBrowserInit = {
|
||||
if (typeof WindowsPrefSync !== 'undefined') {
|
||||
WindowsPrefSync.uninit();
|
||||
}
|
||||
if (this.gmpInstallManager) {
|
||||
this.gmpInstallManager.uninit();
|
||||
}
|
||||
|
||||
BrowserOffline.uninit();
|
||||
OfflineApps.uninit();
|
||||
|
@ -47,9 +47,12 @@ GMPChild::Init(const std::string& aPluginPath,
|
||||
MessageLoop* aIOLoop,
|
||||
IPC::Channel* aChannel)
|
||||
{
|
||||
#ifdef GMP_CRASHREPORTER_READY
|
||||
// See bug 1041226
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
SendPCrashReporterConstructor(CrashReporter::CurrentThreadId());
|
||||
#endif
|
||||
#endif
|
||||
#if defined(XP_WIN)
|
||||
mozilla::SandboxTarget::Instance()->StartSandbox();
|
||||
#endif
|
||||
|
@ -248,17 +248,23 @@ ContactManager.prototype = {
|
||||
let permValue =
|
||||
Services.perms.testExactPermissionFromPrincipal(principal, type);
|
||||
if (permValue == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||
aAllowCallback();
|
||||
if (aAllowCallback) {
|
||||
aAllowCallback();
|
||||
}
|
||||
return;
|
||||
} else if (permValue == Ci.nsIPermissionManager.DENY_ACTION ||
|
||||
permValue == Ci.nsIPermissionManager.UNKNOWN_ACTION) {
|
||||
if (aCancelCallback) {
|
||||
aCancelCallback();
|
||||
}
|
||||
return;
|
||||
} else if (permValue == Ci.nsIPermissionManager.DENY_ACTION) {
|
||||
aCancelCallback();
|
||||
}
|
||||
|
||||
// Create an array with a single nsIContentPermissionType element.
|
||||
let type = {
|
||||
type: "contacts",
|
||||
access: access,
|
||||
options: null,
|
||||
options: [],
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionType])
|
||||
};
|
||||
let typeArray = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
|
||||
@ -269,8 +275,16 @@ ContactManager.prototype = {
|
||||
types: typeArray,
|
||||
principal: principal,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionRequest]),
|
||||
allow: aAllowCallback,
|
||||
cancel: aCancelCallback,
|
||||
allow: aAllowCallback ||
|
||||
function() {
|
||||
if (DEBUG)
|
||||
debug("Default allow contacts callback. " + access +"\n");
|
||||
},
|
||||
cancel: aCancelCallback ||
|
||||
function() {
|
||||
if (DEBUG)
|
||||
debug("Default cancel contacts callback. " + access +"\n");
|
||||
},
|
||||
window: this._window
|
||||
};
|
||||
|
||||
@ -425,7 +439,7 @@ ContactManager.prototype = {
|
||||
}.bind(this);
|
||||
|
||||
let cancelCallback = function() {
|
||||
Services.DOMRequest.fireError(request);
|
||||
Services.DOMRequest.fireError(request, "");
|
||||
};
|
||||
|
||||
this.askPermission("revision", request, allowCallback, cancelCallback);
|
||||
@ -442,7 +456,7 @@ ContactManager.prototype = {
|
||||
}.bind(this);
|
||||
|
||||
let cancelCallback = function() {
|
||||
Services.DOMRequest.fireError(request);
|
||||
Services.DOMRequest.fireError(request, "");
|
||||
};
|
||||
|
||||
this.askPermission("count", request, allowCallback, cancelCallback);
|
||||
|
@ -5,11 +5,14 @@ skip-if = e10s
|
||||
[test_contacts_basics.html]
|
||||
skip-if = (toolkit == 'gonk' && debug) #debug-only failure
|
||||
[test_contacts_basics2.html]
|
||||
skip-if = (toolkit == 'gonk' && debug) #debug-only failure
|
||||
[test_contacts_blobs.html]
|
||||
skip-if = (toolkit == 'gonk' && debug) #debug-only failure
|
||||
[test_contacts_events.html]
|
||||
[test_contacts_getall.html]
|
||||
skip-if = (toolkit == 'gonk' && debug) #debug-only failure
|
||||
[test_contacts_getall2.html]
|
||||
skip-if = (toolkit == 'gonk' && debug) #debug-only failure
|
||||
[test_contacts_international.html]
|
||||
[test_contacts_substringmatching.html]
|
||||
[test_contacts_substringmatchingVE.html]
|
||||
|
@ -1067,4 +1067,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
|
||||
|
||||
static const int32_t kUnknownId = -1;
|
||||
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1413940883162000);
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1414231808712000);
|
||||
|
@ -64,7 +64,7 @@ intercom.io: did not receive HSTS header
|
||||
iop.intuit.com: max-age too low: 86400
|
||||
irccloud.com: did not receive HSTS header
|
||||
jitsi.org: did not receive HSTS header
|
||||
jottit.com: did not receive HSTS header
|
||||
jottit.com: could not connect to host
|
||||
keymaster.lookout.com: did not receive HSTS header
|
||||
kiwiirc.com: max-age too low: 5256000
|
||||
ledgerscope.net: did not receive HSTS header
|
||||
@ -94,7 +94,7 @@ platform.lookout.com: could not connect to host
|
||||
play.google.com: did not receive HSTS header (error ignored - included regardless)
|
||||
prodpad.com: did not receive HSTS header
|
||||
profiles.google.com: did not receive HSTS header (error ignored - included regardless)
|
||||
rapidresearch.me: did not receive HSTS header
|
||||
rapidresearch.me: could not connect to host
|
||||
riseup.net: did not receive HSTS header
|
||||
sah3.net: could not connect to host
|
||||
saturngames.co.uk: did not receive HSTS header
|
||||
@ -103,10 +103,8 @@ security.google.com: did not receive HSTS header (error ignored - included regar
|
||||
semenkovich.com: did not receive HSTS header
|
||||
serverdensity.io: did not receive HSTS header
|
||||
shops.neonisi.com: could not connect to host
|
||||
silentcircle.com: did not receive HSTS header
|
||||
silentcircle.org: could not connect to host
|
||||
simon.butcher.name: max-age too low: 2629743
|
||||
simple.com: did not receive HSTS header
|
||||
sites.google.com: did not receive HSTS header (error ignored - included regardless)
|
||||
sol.io: could not connect to host
|
||||
souyar.de: could not connect to host
|
||||
@ -126,7 +124,6 @@ uprotect.it: could not connect to host
|
||||
wallet.google.com: did not receive HSTS header (error ignored - included regardless)
|
||||
webmail.mayfirst.org: did not receive HSTS header
|
||||
whonix.org: did not receive HSTS header
|
||||
www.airbnb.com: could not connect to host
|
||||
www.calyxinstitute.org: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 124" data: no]
|
||||
www.cueup.com: did not receive HSTS header
|
||||
www.developer.mydigipass.com: could not connect to host
|
||||
@ -136,7 +133,6 @@ www.gmail.com: did not receive HSTS header (error ignored - included regardless)
|
||||
www.googlemail.com: did not receive HSTS header (error ignored - included regardless)
|
||||
www.gov.uk: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 124" data: no]
|
||||
www.greplin.com: could not connect to host
|
||||
www.intercom.io: did not receive HSTS header
|
||||
www.jitsi.org: did not receive HSTS header
|
||||
www.lastpass.com: did not receive HSTS header
|
||||
www.ledgerscope.net: did not receive HSTS header
|
||||
|
@ -8,7 +8,7 @@
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
const PRTime gPreloadListExpirationTime = INT64_C(1416045990752000);
|
||||
const PRTime gPreloadListExpirationTime = INT64_C(1416651005379000);
|
||||
|
||||
class nsSTSPreload
|
||||
{
|
||||
@ -97,6 +97,7 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "feedbin.com", false },
|
||||
{ "fiken.no", true },
|
||||
{ "fj.simple.com", false },
|
||||
{ "flynn.io", true },
|
||||
{ "forum.linode.com", false },
|
||||
{ "forum.quantifiedself.com", true },
|
||||
{ "gernert-server.de", true },
|
||||
@ -122,6 +123,7 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "imouto.my", false },
|
||||
{ "inertianetworks.com", true },
|
||||
{ "itriskltd.com", true },
|
||||
{ "jackyyf.com", false },
|
||||
{ "keeperapp.com", true },
|
||||
{ "keepersecurity.com", true },
|
||||
{ "keyerror.com", true },
|
||||
@ -205,7 +207,9 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "securityheaders.com", true },
|
||||
{ "seifried.org", true },
|
||||
{ "shodan.io", true },
|
||||
{ "silentcircle.com", true },
|
||||
{ "simbolo.co.uk", false },
|
||||
{ "simple.com", false },
|
||||
{ "sites.google.com", true },
|
||||
{ "skydrive.live.com", false },
|
||||
{ "spreadsheets.google.com", true },
|
||||
@ -271,6 +275,7 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "www.gov.uk", false },
|
||||
{ "www.grc.com", false },
|
||||
{ "www.heliosnet.com", true },
|
||||
{ "www.intercom.io", false },
|
||||
{ "www.irccloud.com", false },
|
||||
{ "www.linode.com", false },
|
||||
{ "www.lookout.com", false },
|
||||
|
@ -40,6 +40,8 @@ user_pref("media.volume_scale", "0.01");
|
||||
user_pref("security.warn_viewing_mixed", false);
|
||||
user_pref("app.update.enabled", false);
|
||||
user_pref("app.update.staging.enabled", false);
|
||||
// Make sure GMPInstallManager won't hit the network.
|
||||
user_pref("media.gmp-manager.url", "https://%(server)s/dummy.xml");
|
||||
user_pref("browser.panorama.experienced_first_run", true); // Assume experienced
|
||||
user_pref("dom.w3c_touch_events.enabled", 1);
|
||||
user_pref("dom.undo_manager.enabled", true);
|
||||
|
953
toolkit/modules/GMPInstallManager.jsm
Normal file
953
toolkit/modules/GMPInstallManager.jsm
Normal file
@ -0,0 +1,953 @@
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = [];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu, manager: Cm} =
|
||||
Components;
|
||||
// Chunk size for the incremental downloader
|
||||
const DOWNLOAD_CHUNK_BYTES_SIZE = 300000;
|
||||
// Incremental downloader interval
|
||||
const DOWNLOAD_INTERVAL = 0;
|
||||
// 1 day default
|
||||
const DEFAULT_SECONDS_BETWEEN_CHECKS = 60 * 60 * 24;
|
||||
const OPEN_H264_ID = "gmp-gmpopenh264";
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/FileUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
Cu.import("resource://gre/modules/Preferences.jsm");
|
||||
Cu.import("resource://gre/modules/Log.jsm");
|
||||
Cu.import("resource://gre/modules/osfile.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/ctypes.jsm");
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["GMPInstallManager", "GMPExtractor", "GMPDownloader",
|
||||
"GMPAddon", "GMPPrefs"];
|
||||
|
||||
var gLocale = null;
|
||||
|
||||
// Shared code for suppressing bad cert dialogs
|
||||
XPCOMUtils.defineLazyGetter(this, "gCertUtils", function() {
|
||||
let temp = { };
|
||||
Cu.import("resource://gre/modules/CertUtils.jsm", temp);
|
||||
return temp;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "UpdateChannel",
|
||||
"resource://gre/modules/UpdateChannel.jsm");
|
||||
|
||||
// Used to determine if logging should be enabled
|
||||
XPCOMUtils.defineLazyGetter(this, "gLogEnabled", function() {
|
||||
return GMPPrefs.get(GMPPrefs.KEY_LOG_ENABLED);
|
||||
});
|
||||
|
||||
|
||||
function getScopedLogger(prefix) {
|
||||
let logger = Log.repository.getLogger(prefix);
|
||||
if (gLogEnabled) {
|
||||
logger.level = Log.Level.Debug;
|
||||
let appender = new Log.DumpAppender();
|
||||
logger.addAppender(appender);
|
||||
}
|
||||
return logger;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Manages preferences for GMP addons
|
||||
*/
|
||||
let GMPPrefs = {
|
||||
/**
|
||||
* Obtains the specified preference in relation to the specified addon
|
||||
* @param key The GMPPrefs key value to use
|
||||
* @param addon The addon to scope the preference to
|
||||
* @param defaultValue The default value if no preference exists
|
||||
* @return The obtained preference value, or the defaultVlaue if none exists
|
||||
*/
|
||||
get: function(key, addon, defaultValue) {
|
||||
if (key === GMPPrefs.KEY_APP_DISTRIBUTION ||
|
||||
key === GMPPrefs.KEY_APP_DISTRIBUTION_VERSION) {
|
||||
let prefValue = "default";
|
||||
try {
|
||||
prefValue = Services.prefs.getDefaultBranch(null).getCharPref(key);
|
||||
} catch (e) {
|
||||
// use default when pref not found
|
||||
}
|
||||
return prefValue;
|
||||
}
|
||||
|
||||
return Preferences.get(this._getPrefKey(key, addon), defaultValue);
|
||||
},
|
||||
/**
|
||||
* Sets the specified preference in relation to the specified addon
|
||||
* @param key The GMPPrefs key value to use
|
||||
* @param val The value to set
|
||||
* @param addon The addon to scope the preference to
|
||||
*/
|
||||
set: function(key, val, addon) {
|
||||
let log = getScopedLogger("GMPPrefs.set");
|
||||
log.info("Setting pref: " + this._getPrefKey(key, addon) +
|
||||
" to value: " + val);
|
||||
return Preferences.set(this._getPrefKey(key, addon), val);
|
||||
},
|
||||
_getPrefKey: function(key, addon) {
|
||||
return key.replace("{0}", addon || "");
|
||||
},
|
||||
|
||||
/**
|
||||
* List of keys which can be used in get and set
|
||||
*/
|
||||
KEY_LOG_ENABLED: "media.gmp-manager.log",
|
||||
KEY_ADDON_LAST_UPDATE: "media.{0}.lastUpdate",
|
||||
KEY_ADDON_PATH: "media.{0}.path",
|
||||
KEY_ADDON_VERSION: "media.{0}.version",
|
||||
KEY_URL: "media.gmp-manager.url",
|
||||
KEY_URL_OVERRIDE: "media.gmp-manager.url.override",
|
||||
KEY_CERT_CHECKATTRS: "media.gmp-manager.cert.checkAttributes",
|
||||
KEY_CERT_REQUIREBUILTIN: "media.gmp-manager.cert.requireBuiltIn",
|
||||
KEY_UPDATE_LAST_CHECK: "media.gmp-manager.lastCheck",
|
||||
KEY_UPDATE_SECONDS_BETWEEN_CHECKS: "media.gmp-manager.secondsBetweenChecks",
|
||||
KEY_APP_DISTRIBUTION: "distribution.id",
|
||||
KEY_APP_DISTRIBUTION_VERSION: "distribution.version",
|
||||
|
||||
CERTS_BRANCH: "media.gmp-manager.certs."
|
||||
};
|
||||
|
||||
// This is copied directly from nsUpdateService.js
|
||||
// It is used for calculating the URL string w/ var replacement.
|
||||
// TODO: refactor this out somewhere else
|
||||
XPCOMUtils.defineLazyGetter(this, "gOSVersion", function aus_gOSVersion() {
|
||||
let osVersion;
|
||||
let sysInfo = Cc["@mozilla.org/system-info;1"].
|
||||
getService(Ci.nsIPropertyBag2);
|
||||
try {
|
||||
osVersion = sysInfo.getProperty("name") + " " + sysInfo.getProperty("version");
|
||||
}
|
||||
catch (e) {
|
||||
LOG("gOSVersion - OS Version unknown: updates are not possible.");
|
||||
}
|
||||
|
||||
if (osVersion) {
|
||||
#ifdef XP_WIN
|
||||
const BYTE = ctypes.uint8_t;
|
||||
const WORD = ctypes.uint16_t;
|
||||
const DWORD = ctypes.uint32_t;
|
||||
const WCHAR = ctypes.jschar;
|
||||
const BOOL = ctypes.int;
|
||||
|
||||
// This structure is described at:
|
||||
// http://msdn.microsoft.com/en-us/library/ms724833%28v=vs.85%29.aspx
|
||||
const SZCSDVERSIONLENGTH = 128;
|
||||
const OSVERSIONINFOEXW = new ctypes.StructType('OSVERSIONINFOEXW',
|
||||
[
|
||||
{dwOSVersionInfoSize: DWORD},
|
||||
{dwMajorVersion: DWORD},
|
||||
{dwMinorVersion: DWORD},
|
||||
{dwBuildNumber: DWORD},
|
||||
{dwPlatformId: DWORD},
|
||||
{szCSDVersion: ctypes.ArrayType(WCHAR, SZCSDVERSIONLENGTH)},
|
||||
{wServicePackMajor: WORD},
|
||||
{wServicePackMinor: WORD},
|
||||
{wSuiteMask: WORD},
|
||||
{wProductType: BYTE},
|
||||
{wReserved: BYTE}
|
||||
]);
|
||||
|
||||
// This structure is described at:
|
||||
// http://msdn.microsoft.com/en-us/library/ms724958%28v=vs.85%29.aspx
|
||||
const SYSTEM_INFO = new ctypes.StructType('SYSTEM_INFO',
|
||||
[
|
||||
{wProcessorArchitecture: WORD},
|
||||
{wReserved: WORD},
|
||||
{dwPageSize: DWORD},
|
||||
{lpMinimumApplicationAddress: ctypes.voidptr_t},
|
||||
{lpMaximumApplicationAddress: ctypes.voidptr_t},
|
||||
{dwActiveProcessorMask: DWORD.ptr},
|
||||
{dwNumberOfProcessors: DWORD},
|
||||
{dwProcessorType: DWORD},
|
||||
{dwAllocationGranularity: DWORD},
|
||||
{wProcessorLevel: WORD},
|
||||
{wProcessorRevision: WORD}
|
||||
]);
|
||||
|
||||
let kernel32 = false;
|
||||
try {
|
||||
kernel32 = ctypes.open("Kernel32");
|
||||
} catch (e) {
|
||||
LOG("gOSVersion - Unable to open kernel32! " + e);
|
||||
osVersion += ".unknown (unknown)";
|
||||
}
|
||||
|
||||
if(kernel32) {
|
||||
try {
|
||||
// Get Service pack info
|
||||
try {
|
||||
let GetVersionEx = kernel32.declare("GetVersionExW",
|
||||
ctypes.default_abi,
|
||||
BOOL,
|
||||
OSVERSIONINFOEXW.ptr);
|
||||
let winVer = OSVERSIONINFOEXW();
|
||||
winVer.dwOSVersionInfoSize = OSVERSIONINFOEXW.size;
|
||||
|
||||
if(0 !== GetVersionEx(winVer.address())) {
|
||||
osVersion += "." + winVer.wServicePackMajor
|
||||
+ "." + winVer.wServicePackMinor;
|
||||
} else {
|
||||
LOG("gOSVersion - Unknown failure in GetVersionEX (returned 0)");
|
||||
osVersion += ".unknown";
|
||||
}
|
||||
} catch (e) {
|
||||
LOG("gOSVersion - error getting service pack information. Exception: " + e);
|
||||
osVersion += ".unknown";
|
||||
}
|
||||
|
||||
// Get processor architecture
|
||||
let arch = "unknown";
|
||||
try {
|
||||
let GetNativeSystemInfo = kernel32.declare("GetNativeSystemInfo",
|
||||
ctypes.default_abi,
|
||||
ctypes.void_t,
|
||||
SYSTEM_INFO.ptr);
|
||||
let sysInfo = SYSTEM_INFO();
|
||||
// Default to unknown
|
||||
sysInfo.wProcessorArchitecture = 0xffff;
|
||||
|
||||
GetNativeSystemInfo(sysInfo.address());
|
||||
switch(sysInfo.wProcessorArchitecture) {
|
||||
case 9:
|
||||
arch = "x64";
|
||||
break;
|
||||
case 6:
|
||||
arch = "IA64";
|
||||
break;
|
||||
case 0:
|
||||
arch = "x86";
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
LOG("gOSVersion - error getting processor architecture. Exception: " + e);
|
||||
} finally {
|
||||
osVersion += " (" + arch + ")";
|
||||
}
|
||||
} finally {
|
||||
kernel32.close();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
try {
|
||||
osVersion += " (" + sysInfo.getProperty("secondaryLibrary") + ")";
|
||||
}
|
||||
catch (e) {
|
||||
// Not all platforms have a secondary widget library, so an error is nothing to worry about.
|
||||
}
|
||||
osVersion = encodeURIComponent(osVersion);
|
||||
}
|
||||
return osVersion;
|
||||
});
|
||||
|
||||
// This is copied directly from nsUpdateService.js
|
||||
// It is used for calculating the URL string w/ var replacement.
|
||||
// TODO: refactor this out somewhere else
|
||||
XPCOMUtils.defineLazyGetter(this, "gABI", function aus_gABI() {
|
||||
let abi = null;
|
||||
try {
|
||||
abi = Services.appinfo.XPCOMABI;
|
||||
}
|
||||
catch (e) {
|
||||
LOG("gABI - XPCOM ABI unknown: updates are not possible.");
|
||||
}
|
||||
#ifdef XP_MACOSX
|
||||
// Mac universal build should report a different ABI than either macppc
|
||||
// or mactel.
|
||||
let macutils = Cc["@mozilla.org/xpcom/mac-utils;1"].
|
||||
getService(Ci.nsIMacUtils);
|
||||
|
||||
if (macutils.isUniversalBinary)
|
||||
abi += "-u-" + macutils.architecturesInBinary;
|
||||
#ifdef MOZ_SHARK
|
||||
// Disambiguate optimised and shark nightlies
|
||||
abi += "-shark"
|
||||
#endif
|
||||
#endif
|
||||
return abi;
|
||||
});
|
||||
|
||||
/**
|
||||
* Provides an easy API for downloading and installing GMP Addons
|
||||
*/
|
||||
function GMPInstallManager() {
|
||||
}
|
||||
/**
|
||||
* Temp file name used for downloading
|
||||
*/
|
||||
GMPInstallManager.prototype = {
|
||||
/**
|
||||
* Obtains a URL with replacement of vars
|
||||
*/
|
||||
_getURL: function() {
|
||||
let log = getScopedLogger("GMPInstallManager._getURL");
|
||||
// Use the override URL if it is specified. The override URL is just like
|
||||
// the normal URL but it does not check the cert.
|
||||
let url = GMPPrefs.get(GMPPrefs.KEY_URL_OVERRIDE);
|
||||
if (url) {
|
||||
log.info("Using override url: " + url);
|
||||
} else {
|
||||
url = GMPPrefs.get(GMPPrefs.KEY_URL);
|
||||
log.info("Using url: " + url);
|
||||
}
|
||||
|
||||
url =
|
||||
url.replace(/%PRODUCT%/g, Services.appinfo.name)
|
||||
.replace(/%VERSION%/g, Services.appinfo.version)
|
||||
.replace(/%BUILD_ID%/g, Services.appinfo.appBuildID)
|
||||
.replace(/%BUILD_TARGET%/g, Services.appinfo.OS + "_" + gABI)
|
||||
.replace(/%OS_VERSION%/g, gOSVersion);
|
||||
if (/%LOCALE%/.test(url)) {
|
||||
// TODO: Get the real local, does it actually matter for GMP plugins?
|
||||
url = url.replace(/%LOCALE%/g, "en-US");
|
||||
}
|
||||
url =
|
||||
url.replace(/%CHANNEL%/g, UpdateChannel.get())
|
||||
.replace(/%PLATFORM_VERSION%/g, Services.appinfo.platformVersion)
|
||||
.replace(/%DISTRIBUTION%/g,
|
||||
GMPPrefs.get(GMPPrefs.KEY_APP_DISTRIBUTION))
|
||||
.replace(/%DISTRIBUTION_VERSION%/g,
|
||||
GMPPrefs.get(GMPPrefs.KEY_APP_DISTRIBUTION_VERSION))
|
||||
.replace(/\+/g, "%2B");
|
||||
log.info("Using url (with replacement): " + url);
|
||||
return url;
|
||||
},
|
||||
/**
|
||||
* Performs an addon check.
|
||||
* @return a promise which will be resolved or rejected.
|
||||
* The promise is resolved with an array of GMPAddons
|
||||
* The promise is rejected with an object with properties:
|
||||
* target: The XHR request object
|
||||
* status: The HTTP status code
|
||||
* type: Sometimes specifies type of rejection
|
||||
*/
|
||||
checkForAddons: function() {
|
||||
let log = getScopedLogger("GMPInstallManager.checkForAddons");
|
||||
if (this._deferred) {
|
||||
log.error("checkForAddons already called");
|
||||
return Promise.reject({type: "alreadycalled"});
|
||||
}
|
||||
this._deferred = Promise.defer();
|
||||
let url = this._getURL();
|
||||
|
||||
this._request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
|
||||
createInstance(Ci.nsISupports);
|
||||
// This is here to let unit test code override XHR
|
||||
if (this._request.wrappedJSObject) {
|
||||
this._request = this._request.wrappedJSObject;
|
||||
}
|
||||
this._request.open("GET", url, true);
|
||||
let allowNonBuiltIn = !GMPPrefs.get(GMPPrefs.KEY_CERT_CHECKATTRS,
|
||||
undefined, true);
|
||||
this._request.channel.notificationCallbacks =
|
||||
new gCertUtils.BadCertHandler(allowNonBuiltIn);
|
||||
// Prevent the request from reading from the cache.
|
||||
this._request.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
|
||||
// Prevent the request from writing to the cache.
|
||||
this._request.channel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING;
|
||||
|
||||
this._request.overrideMimeType("text/xml");
|
||||
// The Cache-Control header is only interpreted by proxies and the
|
||||
// final destination. It does not help if a resource is already
|
||||
// cached locally.
|
||||
this._request.setRequestHeader("Cache-Control", "no-cache");
|
||||
// HTTP/1.0 servers might not implement Cache-Control and
|
||||
// might only implement Pragma: no-cache
|
||||
this._request.setRequestHeader("Pragma", "no-cache");
|
||||
|
||||
this._request.addEventListener("error", this.onErrorXML.bind(this) ,false);
|
||||
this._request.addEventListener("load", this.onLoadXML.bind(this), false);
|
||||
|
||||
log.info("sending request to: " + url);
|
||||
this._request.send(null);
|
||||
|
||||
return this._deferred.promise;
|
||||
},
|
||||
/**
|
||||
* Installs the specified addon and calls a callback when done.
|
||||
* @param gmpAddon The GMPAddon object to install
|
||||
* @return a promise which will be resolved or rejected
|
||||
* The promise will resolve with an array of paths that were extracted
|
||||
* The promise will reject with an error object:
|
||||
* target: The XHR request object
|
||||
* status: The HTTP status code
|
||||
* type: A string to represent the type of error
|
||||
* downloaderr, or verifyerr
|
||||
*/
|
||||
installAddon: function(gmpAddon) {
|
||||
if (this._deferred) {
|
||||
log.error("checkForAddons already called");
|
||||
return Promise.reject({type: "alreadycalled"});
|
||||
}
|
||||
this.gmpDownloader = new GMPDownloader(gmpAddon);
|
||||
return this.gmpDownloader.start();
|
||||
},
|
||||
_getTimeSinceLastCheck: function() {
|
||||
let now = Math.round(Date.now() / 1000);
|
||||
// Default to 0 here because `now - 0` will be returned later if that case
|
||||
// is hit. We want a large value so a check will occur.
|
||||
let lastCheck = GMPPrefs.get(GMPPrefs.KEY_UPDATE_LAST_CHECK,
|
||||
undefined, 0);
|
||||
// Handle clock jumps, return now since we want it to represent
|
||||
// a lot of time has passed since the last check.
|
||||
if (now < lastCheck) {
|
||||
return now;
|
||||
}
|
||||
return now - lastCheck;
|
||||
},
|
||||
_updateLastCheck: function() {
|
||||
let now = Math.round(Date.now() / 1000);
|
||||
GMPPrefs.set(GMPPrefs.KEY_UPDATE_LAST_CHECK, now);
|
||||
},
|
||||
/**
|
||||
* Wrapper for checkForAddons and installaddon.
|
||||
* Will only install if not already installed and will log the results.
|
||||
*/
|
||||
simpleCheckAndInstall: function() {
|
||||
let log = getScopedLogger("GMPInstallManager.simpleCheckAndInstall");
|
||||
let secondsBetweenChecks =
|
||||
GMPPrefs.get(GMPPrefs.KEY_UPDATE_SECONDS_BETWEEN_CHECKS, undefined,
|
||||
DEFAULT_SECONDS_BETWEEN_CHECKS)
|
||||
let secondsSinceLast = this._getTimeSinceLastCheck();
|
||||
log.info("Last check was: " + secondsSinceLast +
|
||||
" seconds ago, minimum seconds: " + secondsBetweenChecks);
|
||||
if (secondsBetweenChecks > secondsSinceLast) {
|
||||
log.info("Will not check for updates.");
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
let promise = this.checkForAddons();
|
||||
promise.then(gmpAddons => {
|
||||
this._updateLastCheck();
|
||||
log.info("Found " + gmpAddons.length + " addons advertised.");
|
||||
let addonsToInstall = gmpAddons.filter(gmpAddon => {
|
||||
log.info("Found addon: " + gmpAddon.toString());
|
||||
return gmpAddon.isValid && gmpAddon.isOpenH264 &&
|
||||
!gmpAddon.isInstalled
|
||||
});
|
||||
if (!addonsToInstall.length) {
|
||||
log.info("No new addons to install, returning");
|
||||
return;
|
||||
}
|
||||
addonsToInstall.forEach(gmpAddon => {
|
||||
promise = this.installAddon(gmpAddon);
|
||||
promise.then(extractedPaths => {
|
||||
// installed!
|
||||
log.info("Addon installed successfully: " + gmpAddon.toString());
|
||||
}, () => {
|
||||
if (!GMPPrefs.get(GMPPrefs.KEY_LOG_ENABLED)) {
|
||||
Cu.reportError(gmpAddon.toString() + " could not be installed. Enable " +
|
||||
GMPPrefs.KEY_LOG_ENABLED + " for details!");
|
||||
}
|
||||
log.error("Could not install addon: " + gmpAddon.toString());
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Makes sure everything is cleaned up
|
||||
*/
|
||||
uninit: function() {
|
||||
let log = getScopedLogger("GMPDownloader.uninit");
|
||||
if (this._request) {
|
||||
log.info("Aborting request");
|
||||
this._request.abort();
|
||||
}
|
||||
if (this._deferred) {
|
||||
log.info("Rejecting deferred");
|
||||
this._deferred.reject({type: "uninitialized"});
|
||||
}
|
||||
log.info("Done cleanup");
|
||||
},
|
||||
|
||||
/**
|
||||
* If set to true, specifies to leave the temporary downloaded zip file.
|
||||
* This is useful for tests.
|
||||
*/
|
||||
overrideLeaveDownloadedZip: false,
|
||||
|
||||
/**
|
||||
* The XMLHttpRequest succeeded and the document was loaded.
|
||||
* @param event The nsIDOMEvent for the load
|
||||
*/
|
||||
onLoadXML: function(event) {
|
||||
let log = getScopedLogger("GMPInstallManager.onLoadXML");
|
||||
log.info("request completed downloading document");
|
||||
|
||||
let certs = null;
|
||||
if (!Services.prefs.prefHasUserValue(GMPPrefs.KEY_URL_OVERRIDE) &&
|
||||
GMPPrefs.get(GMPPrefs.KEY_CERT_CHECKATTRS, undefined, true)) {
|
||||
certs = gCertUtils.readCertPrefs(GMPPrefs.CERTS_BRANCH);
|
||||
}
|
||||
|
||||
let allowNonBuiltIn = !GMPPrefs.get(GMPPrefs.KEY_CERT_REQUIREBUILTIN,
|
||||
undefined, true);
|
||||
log.info("allowNonBuiltIn: " + allowNonBuiltIn);
|
||||
gCertUtils.checkCert(this._request.channel, allowNonBuiltIn, certs);
|
||||
|
||||
this.parseResponseXML();
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the status code for the XMLHttpRequest
|
||||
*/
|
||||
_getChannelStatus: function(request) {
|
||||
let log = getScopedLogger("GMPInstallManager._getChannelStatus");
|
||||
let status = 0;
|
||||
try {
|
||||
status = request.status;
|
||||
log.info("request.status is: " + request.status);
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
|
||||
if (status == 0) {
|
||||
status = request.channel.QueryInterface(Ci.nsIRequest).status;
|
||||
}
|
||||
return status;
|
||||
},
|
||||
|
||||
/**
|
||||
* There was an error of some kind during the XMLHttpRequest
|
||||
* @param event The nsIDOMEvent for the error
|
||||
*/
|
||||
onErrorXML: function(event) {
|
||||
let log = getScopedLogger("GMPInstallManager.onErrorXML");
|
||||
let request = event.target;
|
||||
let status = this._getChannelStatus(request);
|
||||
let message = "request.status: " + status;
|
||||
log.warn(message);
|
||||
this._deferred.reject({
|
||||
target: request,
|
||||
status: status,
|
||||
message: message
|
||||
});
|
||||
delete this._deferred;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns an array of GMPAddon objects discovered by the update check.
|
||||
* Or returns an empty array if there were any problems with parsing.
|
||||
* If there's an error, it will be logged if logging is enabled.
|
||||
*/
|
||||
parseResponseXML: function() {
|
||||
try {
|
||||
let log = getScopedLogger("GMPInstallManager.parseResponseXML");
|
||||
let updatesElement = this._request.responseXML.documentElement;
|
||||
if (!updatesElement) {
|
||||
let message = "empty updates document";
|
||||
log.warn(message);
|
||||
this._deferred.reject({
|
||||
target: this._request,
|
||||
message: message
|
||||
});
|
||||
delete this._deferred;
|
||||
return;
|
||||
}
|
||||
|
||||
if (updatesElement.nodeName != "updates") {
|
||||
let message = "got node name: " + updatesElement.nodeName +
|
||||
", expected: updates";
|
||||
log.warn(message);
|
||||
this._deferred.reject({
|
||||
target: this._request,
|
||||
message: message
|
||||
});
|
||||
delete this._deferred;
|
||||
return;
|
||||
}
|
||||
|
||||
const ELEMENT_NODE = Ci.nsIDOMNode.ELEMENT_NODE;
|
||||
let gmpResults = [];
|
||||
for (let i = 0; i < updatesElement.childNodes.length; ++i) {
|
||||
let updatesChildElement = updatesElement.childNodes.item(i);
|
||||
if (updatesChildElement.nodeType != ELEMENT_NODE) {
|
||||
continue;
|
||||
}
|
||||
if (updatesChildElement.localName == "addons") {
|
||||
gmpResults = GMPAddon.parseGMPAddonsNode(updatesChildElement);
|
||||
}
|
||||
}
|
||||
this._deferred.resolve(gmpResults);
|
||||
delete this._deferred;
|
||||
} catch (e) {
|
||||
this._deferred.reject({
|
||||
target: this._request,
|
||||
message: e
|
||||
});
|
||||
delete this._deferred;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Used to construct a single GMP addon
|
||||
* GMPAddon objects are returns from GMPInstallManager.checkForAddons
|
||||
* GMPAddon objects can also be used in calls to GMPInstallManager.installAddon
|
||||
*
|
||||
* @param gmpAddon The AUS response XML's DOM element `addon`
|
||||
*/
|
||||
function GMPAddon(gmpAddon) {
|
||||
let log = getScopedLogger("GMPAddon.constructor");
|
||||
gmpAddon.QueryInterface(Ci.nsIDOMElement);
|
||||
["id", "URL", "hashFunction",
|
||||
"hashValue", "version", "size"].forEach(name => {
|
||||
if (gmpAddon.hasAttribute(name)) {
|
||||
this[name] = gmpAddon.getAttribute(name);
|
||||
}
|
||||
});
|
||||
this.size = Number(this.size) || undefined;
|
||||
log.info ("Created new addon: " + this.toString());
|
||||
}
|
||||
/**
|
||||
* Parses an XML GMP addons node from AUS into an array
|
||||
* @param addonsElement An nsIDOMElement compatible node with XML from AUS
|
||||
* @return An array of GMPAddon results
|
||||
*/
|
||||
GMPAddon.parseGMPAddonsNode = function(addonsElement) {
|
||||
let log = getScopedLogger("GMPAddon.parseGMPAddonsNode");
|
||||
let gmpResults = [];
|
||||
if (addonsElement.localName !== "addons") {
|
||||
return;
|
||||
}
|
||||
|
||||
addonsElement.QueryInterface(Ci.nsIDOMElement);
|
||||
let addonCount = addonsElement.childNodes.length;
|
||||
for (let i = 0; i < addonCount; ++i) {
|
||||
let addonElement = addonsElement.childNodes.item(i);
|
||||
if (addonElement.localName !== "addon") {
|
||||
continue;
|
||||
}
|
||||
addonElement.QueryInterface(Ci.nsIDOMElement);
|
||||
try {
|
||||
gmpResults.push(new GMPAddon(addonElement));
|
||||
} catch (e) {
|
||||
log.warn("invalid addon: " + e);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return gmpResults;
|
||||
};
|
||||
GMPAddon.prototype = {
|
||||
/**
|
||||
* Returns a string representation of the addon
|
||||
*/
|
||||
toString: function() {
|
||||
return this.id + " (" +
|
||||
"isValid: " + this.isValid +
|
||||
", isInstalled: " + this.isInstalled +
|
||||
", isOpenH264: " + this.isOpenH264 +
|
||||
", hashFunction: " + this.hashFunction+
|
||||
", hashValue: " + this.hashValue +
|
||||
(this.size !== undefined ? ", size: " + this.size : "" ) +
|
||||
")";
|
||||
},
|
||||
/**
|
||||
* If all the fields aren't specified don't consider this addon valid
|
||||
* @return true if the addon is parsed and valid
|
||||
*/
|
||||
get isValid() {
|
||||
return this.id && this.URL && this.version &&
|
||||
this.hashFunction && !!this.hashValue;
|
||||
},
|
||||
/**
|
||||
* Open H264 has special handling.
|
||||
* @return true if the plugin is the openh264 plugin
|
||||
*/
|
||||
get isOpenH264() {
|
||||
return this.id === OPEN_H264_ID;
|
||||
},
|
||||
get isInstalled() {
|
||||
return this.version &&
|
||||
GMPPrefs.get(GMPPrefs.KEY_ADDON_VERSION, this.id) === this.version;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Constructs a GMPExtractor object which is used to extract a GMP zip
|
||||
* into the specified location. (Which typically leties per platform)
|
||||
* @param zipPath The path on disk of the zip file to extract
|
||||
*/
|
||||
function GMPExtractor(zipPath, installToDirPath) {
|
||||
this.zipPath = zipPath;
|
||||
this.installToDirPath = installToDirPath;
|
||||
}
|
||||
GMPExtractor.prototype = {
|
||||
/**
|
||||
* Obtains a list of all the entries in a zipfile in the format of *.*.
|
||||
* This also includes files inside directories.
|
||||
*
|
||||
* @param zipReader the nsIZipReader to check
|
||||
* @return An array of string name entries which can be used
|
||||
* in nsIZipReader.extract
|
||||
*/
|
||||
_getZipEntries: function(zipReader) {
|
||||
let entries = [];
|
||||
let enumerator = zipReader.findEntries("*.*");
|
||||
while (enumerator.hasMore()) {
|
||||
entries.push(enumerator.getNext());
|
||||
}
|
||||
return entries;
|
||||
},
|
||||
/**
|
||||
* Installs the this.zipPath contents into the directory used to store GMP
|
||||
* addons for the current platform.
|
||||
*
|
||||
* @return a promise which will be resolved or rejected
|
||||
* See GMPInstallManager.installAddon for resolve/rejected info
|
||||
*/
|
||||
install: function() {
|
||||
try {
|
||||
let log = getScopedLogger("GMPExtractor.install");
|
||||
this._deferred = Promise.defer();
|
||||
log.info("Installing " + this.zipPath + "...");
|
||||
// Get the input zip file
|
||||
let zipFile = Cc["@mozilla.org/file/local;1"].
|
||||
createInstance(Ci.nsIFile);
|
||||
zipFile.initWithPath(this.zipPath);
|
||||
|
||||
// Initialize a zipReader and obtain the entries
|
||||
var zipReader = Cc["@mozilla.org/libjar/zip-reader;1"].
|
||||
createInstance(Ci.nsIZipReader);
|
||||
zipReader.open(zipFile)
|
||||
let entries = this._getZipEntries(zipReader);
|
||||
let extractedPaths = [];
|
||||
|
||||
// Extract each of the entries
|
||||
entries.forEach(entry => {
|
||||
// We don't need these types of files
|
||||
if (entry.contains("__MACOSX")) {
|
||||
return;
|
||||
}
|
||||
let outFile = Cc["@mozilla.org/file/local;1"].
|
||||
createInstance(Ci.nsILocalFile);
|
||||
outFile.initWithPath(this.installToDirPath);
|
||||
outFile.appendRelativePath(entry);
|
||||
|
||||
// Make sure the directory hierarchy exists
|
||||
if(!outFile.parent.exists()) {
|
||||
outFile.parent.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt("0755", 8));
|
||||
}
|
||||
zipReader.extract(entry, outFile);
|
||||
extractedPaths.push(outFile.path);
|
||||
log.info(entry + " was successfully extracted to: " +
|
||||
outFile.path);
|
||||
});
|
||||
zipReader.close();
|
||||
if (!GMPInstallManager.overrideLeaveDownloadedZip) {
|
||||
zipFile.remove(false);
|
||||
}
|
||||
|
||||
log.info(this.zipPath + " was installed successfully");
|
||||
this._deferred.resolve(extractedPaths);
|
||||
} catch (e) {
|
||||
if (zipReader) {
|
||||
zipReader.close();
|
||||
}
|
||||
this._deferred.reject({
|
||||
target: this,
|
||||
status: e,
|
||||
type: "exception"
|
||||
});
|
||||
}
|
||||
return this._deferred.promise;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an object which downloads and initiates an install of
|
||||
* the specified GMPAddon object.
|
||||
* @param gmpAddon The addon to install.
|
||||
*/
|
||||
function GMPDownloader(gmpAddon)
|
||||
{
|
||||
this._gmpAddon = gmpAddon;
|
||||
}
|
||||
/**
|
||||
* Computes the file hash of fileToHash with the specified hash function
|
||||
* @param hashFunctionName A hash function name such as sha512
|
||||
* @param fileToHash An nsIFile to hash
|
||||
* @return a promise which resolve to a digest in binary hex format
|
||||
*/
|
||||
GMPDownloader.computeHash = function(hashFunctionName, fileToHash) {
|
||||
let log = getScopedLogger("GMPDownloader.computeHash");
|
||||
let digest;
|
||||
let fileStream = Cc["@mozilla.org/network/file-input-stream;1"].
|
||||
createInstance(Ci.nsIFileInputStream);
|
||||
fileStream.init(fileToHash, FileUtils.MODE_RDONLY,
|
||||
FileUtils.PERMS_FILE, 0);
|
||||
try {
|
||||
let hash = Cc["@mozilla.org/security/hash;1"].
|
||||
createInstance(Ci.nsICryptoHash);
|
||||
let hashFunction =
|
||||
Ci.nsICryptoHash[hashFunctionName.toUpperCase()];
|
||||
if (!hashFunction) {
|
||||
log.error("could not get hash function");
|
||||
return Promise.reject();
|
||||
}
|
||||
hash.init(hashFunction);
|
||||
hash.updateFromStream(fileStream, -1);
|
||||
digest = binaryToHex(hash.finish(false));
|
||||
} catch (e) {
|
||||
log.warn("failed to compute hash: " + e);
|
||||
digest = "";
|
||||
}
|
||||
fileStream.close();
|
||||
return Promise.resolve(digest);
|
||||
},
|
||||
GMPDownloader.prototype = {
|
||||
/**
|
||||
* Starts the download process for an addon.
|
||||
* @return a promise which will be resolved or rejected
|
||||
* See GMPInstallManager.installAddon for resolve/rejected info
|
||||
*/
|
||||
start: function() {
|
||||
let log = getScopedLogger("GMPDownloader.start");
|
||||
this._deferred = Promise.defer();
|
||||
if (!this._gmpAddon.isValid) {
|
||||
log.info("gmpAddon is not valid, will not continue");
|
||||
return Promise.reject({
|
||||
target: this,
|
||||
status: status,
|
||||
type: "downloaderr"
|
||||
});
|
||||
}
|
||||
|
||||
let uri = Services.io.newURI(this._gmpAddon.URL, null, null);
|
||||
this._request = Cc["@mozilla.org/network/incremental-download;1"].
|
||||
createInstance(Ci.nsIIncrementalDownload);
|
||||
let gmpFile = FileUtils.getFile("TmpD", [this._gmpAddon.id + ".zip"]);
|
||||
if (gmpFile.exists()) {
|
||||
gmpFile.remove(false);
|
||||
}
|
||||
|
||||
log.info("downloading from " + uri.spec + " to " + gmpFile.path);
|
||||
this._request.init(uri, gmpFile, DOWNLOAD_CHUNK_BYTES_SIZE,
|
||||
DOWNLOAD_INTERVAL);
|
||||
this._request.start(this, null);
|
||||
return this._deferred.promise;
|
||||
},
|
||||
// For nsIRequestObserver
|
||||
onStartRequest: function(request, context) {
|
||||
},
|
||||
// For nsIRequestObserver
|
||||
// Called when the GMP addon zip file is downloaded
|
||||
onStopRequest: function(request, context, status) {
|
||||
let log = getScopedLogger("GMPDownloader.onStopRequest");
|
||||
log.info("onStopRequest called");
|
||||
if (!Components.isSuccessCode(status)) {
|
||||
log.info("status failed: " + status);
|
||||
this._deferred.reject({
|
||||
target: this,
|
||||
status: status,
|
||||
type: "downloaderr"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
let promise = this._verifyDownload();
|
||||
promise.then(() => {
|
||||
log.info("GMP file is ready to unzip");
|
||||
let destination = this._request.destination;
|
||||
|
||||
let zipPath = destination.path;
|
||||
let gmpAddon = this._gmpAddon;
|
||||
let installToDirPath = Cc["@mozilla.org/file/local;1"].
|
||||
createInstance(Ci.nsIFile);
|
||||
let path = OS.Path.join(OS.Constants.Path.profileDir, gmpAddon.id);
|
||||
installToDirPath.initWithPath(path);
|
||||
log.info("install to directory path: " + installToDirPath.path);
|
||||
let gmpInstaller = new GMPExtractor(zipPath, installToDirPath.path);
|
||||
let installPromise = gmpInstaller.install();
|
||||
installPromise.then(extractedPaths => {
|
||||
// Success, set the prefs
|
||||
let now = Math.round(Date.now() / 1000);
|
||||
GMPPrefs.set(GMPPrefs.KEY_ADDON_LAST_UPDATE, now, gmpAddon.id);
|
||||
// Setting the path pref signals installation completion to consumers,
|
||||
// so set the version and potential other information they use first.
|
||||
GMPPrefs.set(GMPPrefs.KEY_ADDON_VERSION, gmpAddon.version,
|
||||
gmpAddon.id);
|
||||
GMPPrefs.set(GMPPrefs.KEY_ADDON_PATH,
|
||||
installToDirPath.path, gmpAddon.id);
|
||||
this._deferred.resolve(extractedPaths);
|
||||
}, err => {
|
||||
this._deferred.reject(err);
|
||||
});
|
||||
}, err => {
|
||||
log.warn("verifyDownload check failed");
|
||||
this._deferred.reject({
|
||||
target: this,
|
||||
status: 200,
|
||||
type: "verifyerr"
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Verifies that the downloaded zip file's hash matches the GMPAddon hash.
|
||||
* @return a promise which resolves if the download verifies
|
||||
*/
|
||||
_verifyDownload: function() {
|
||||
let verifyDownloadDeferred = Promise.defer();
|
||||
let log = getScopedLogger("GMPDownloader._verifyDownload");
|
||||
log.info("_verifyDownload called");
|
||||
if (!this._request) {
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
let destination = this._request.destination;
|
||||
log.info("for path: " + destination.path);
|
||||
|
||||
// Ensure that the file size matches the expected file size.
|
||||
if (this._gmpAddon.size !== undefined &&
|
||||
destination.fileSize != this._gmpAddon.size) {
|
||||
log.warn("Downloader:_verifyDownload downloaded size " +
|
||||
destination.fileSize + " != expected size " +
|
||||
this._gmpAddon.size + ".");
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
let promise = GMPDownloader.computeHash(this._gmpAddon.hashFunction, destination);
|
||||
promise.then(digest => {
|
||||
let expectedDigest = this._gmpAddon.hashValue.toLowerCase();
|
||||
if (digest !== expectedDigest) {
|
||||
log.warn("hashes do not match! Got: `" +
|
||||
digest + "`, expected: `" + expectedDigest + "`");
|
||||
this._deferred.reject();
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("hashes match!");
|
||||
verifyDownloadDeferred.resolve();
|
||||
}, err => {
|
||||
verifyDownloadDeferred.reject();
|
||||
});
|
||||
return verifyDownloadDeferred.promise;
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIRequestObserver])
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert a string containing binary values to hex.
|
||||
*/
|
||||
function binaryToHex(input) {
|
||||
let result = "";
|
||||
for (let i = 0; i < input.length; ++i) {
|
||||
let hex = input.charCodeAt(i).toString(16);
|
||||
if (hex.length == 1)
|
||||
hex = "0" + hex;
|
||||
result += hex;
|
||||
}
|
||||
return result;
|
||||
}
|
@ -60,6 +60,7 @@ EXTRA_JS_MODULES += [
|
||||
|
||||
EXTRA_PP_JS_MODULES += [
|
||||
'CertUtils.jsm',
|
||||
'GMPInstallManager.jsm',
|
||||
'ResetProfile.jsm',
|
||||
'Services.jsm',
|
||||
'Troubleshoot.jsm',
|
||||
|
725
toolkit/modules/tests/xpcshell/test_GMPInstallManager.js
Normal file
725
toolkit/modules/tests/xpcshell/test_GMPInstallManager.js
Normal file
@ -0,0 +1,725 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu, manager: Cm} = Components;
|
||||
const URL_HOST = "http://localhost";
|
||||
|
||||
Cu.import("resource://gre/modules/GMPInstallManager.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/FileUtils.jsm");
|
||||
Cu.import("resource://testing-common/httpd.js");
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
Cu.import("resource://gre/modules/Preferences.jsm")
|
||||
|
||||
do_get_profile();
|
||||
|
||||
function run_test() {Cu.import("resource://gre/modules/Preferences.jsm")
|
||||
Preferences.set("media.gmp-manager.log", true);
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the helper used for preferences works correctly
|
||||
*/
|
||||
add_test(function test_prefs() {
|
||||
let addon1 = "addon1", addon2 = "addon2";
|
||||
|
||||
GMPPrefs.set(GMPPrefs.KEY_LOG_ENABLED, true);
|
||||
GMPPrefs.set(GMPPrefs.KEY_URL, "http://not-really-used");
|
||||
GMPPrefs.set(GMPPrefs.KEY_URL_OVERRIDE, "http://not-really-used-2");
|
||||
GMPPrefs.set(GMPPrefs.KEY_ADDON_LAST_UPDATE, "1", addon1);
|
||||
GMPPrefs.set(GMPPrefs.KEY_ADDON_PATH, "2", addon1);
|
||||
GMPPrefs.set(GMPPrefs.KEY_ADDON_VERSION, "3", addon1);
|
||||
GMPPrefs.set(GMPPrefs.KEY_ADDON_LAST_UPDATE, "4", addon2);
|
||||
GMPPrefs.set(GMPPrefs.KEY_ADDON_PATH, "5", addon2);
|
||||
GMPPrefs.set(GMPPrefs.KEY_ADDON_VERSION, "6", addon2);
|
||||
GMPPrefs.set(GMPPrefs.KEY_CERT_CHECKATTRS, true);
|
||||
|
||||
do_check_true(GMPPrefs.get(GMPPrefs.KEY_LOG_ENABLED));
|
||||
do_check_eq(GMPPrefs.get(GMPPrefs.KEY_URL), "http://not-really-used");
|
||||
do_check_eq(GMPPrefs.get(GMPPrefs.KEY_URL_OVERRIDE), "http://not-really-used-2");
|
||||
do_check_eq(GMPPrefs.get(GMPPrefs.KEY_ADDON_LAST_UPDATE, addon1), "1");
|
||||
do_check_eq(GMPPrefs.get(GMPPrefs.KEY_ADDON_PATH, addon1), "2");
|
||||
do_check_eq(GMPPrefs.get(GMPPrefs.KEY_ADDON_VERSION, addon1), "3");
|
||||
do_check_eq(GMPPrefs.get(GMPPrefs.KEY_ADDON_LAST_UPDATE, addon2), "4");
|
||||
do_check_eq(GMPPrefs.get(GMPPrefs.KEY_ADDON_PATH, addon2), "5");
|
||||
do_check_eq(GMPPrefs.get(GMPPrefs.KEY_ADDON_VERSION, addon2), "6");
|
||||
do_check_true(GMPPrefs.get(GMPPrefs.KEY_CERT_CHECKATTRS));
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that an uninit without a check works fine
|
||||
*/
|
||||
add_test(function test_checkForAddons_noResponse() {
|
||||
let installManager = new GMPInstallManager();
|
||||
installManager.uninit();
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that an uninit without an install works fine
|
||||
*/
|
||||
add_test(function test_checkForAddons_noResponse() {
|
||||
overrideXHR(200, "");
|
||||
let installManager = new GMPInstallManager();
|
||||
let promise = installManager.checkForAddons();
|
||||
promise.then(function(gmpAddons) {
|
||||
do_throw("no repsonse should reject");
|
||||
}, function(err) {
|
||||
installManager.uninit();
|
||||
});
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that no response returned rejects
|
||||
*/
|
||||
add_test(function test_checkForAddons_noResponse() {
|
||||
overrideXHR(200, "");
|
||||
let installManager = new GMPInstallManager();
|
||||
let promise = installManager.checkForAddons();
|
||||
promise.then(function(gmpAddons) {
|
||||
do_throw("no repsonse should reject");
|
||||
}, function(err) {
|
||||
do_check_true(!!err);
|
||||
installManager.uninit();
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that no addons element returned resolves with no addons
|
||||
*/
|
||||
add_task(function test_checkForAddons_noAddonsElement() {
|
||||
overrideXHR(200, "<updates></updates>");
|
||||
let installManager = new GMPInstallManager();
|
||||
let gmpAddons = yield installManager.checkForAddons();
|
||||
do_check_eq(gmpAddons.length, 0);
|
||||
installManager.uninit();
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that empty addons element returned resolves with no addons
|
||||
*/
|
||||
add_task(function test_checkForAddons_noAddonsElement() {
|
||||
overrideXHR(200, "<updates><addons/></updates>");
|
||||
let installManager = new GMPInstallManager();
|
||||
let gmpAddons = yield installManager.checkForAddons();
|
||||
do_check_eq(gmpAddons.length, 0);
|
||||
installManager.uninit();
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that a response with the wrong root element rejects
|
||||
*/
|
||||
add_test(function test_checkForAddons_wrongResponseXML() {
|
||||
overrideXHR(200, "<digits_of_pi>3.141592653589793....</digits_of_pi>");
|
||||
let installManager = new GMPInstallManager();
|
||||
let promise = installManager.checkForAddons();
|
||||
promise.then(function(err, gmpAddons) {
|
||||
do_throw("response with the wrong root element should reject");
|
||||
}, function(err) {
|
||||
do_check_true(!!err);
|
||||
installManager.uninit();
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Tests that a 404 error works as expected
|
||||
*/
|
||||
add_test(function test_checkForAddons_404Error() {
|
||||
overrideXHR(404, "");
|
||||
let installManager = new GMPInstallManager();
|
||||
let promise = installManager.checkForAddons();
|
||||
promise.then(function(gmpAddons) {
|
||||
do_throw("404 response should reject");
|
||||
}, function(err) {
|
||||
do_check_true(!!err);
|
||||
do_check_eq(err.status, 404);
|
||||
installManager.uninit();
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Tests that gettinga a funky non XML response works as expected
|
||||
*/
|
||||
add_test(function test_checkForAddons_notXML() {
|
||||
overrideXHR(200, "3.141592653589793....");
|
||||
let installManager = new GMPInstallManager();
|
||||
let promise = installManager.checkForAddons();
|
||||
promise.then(function(gmpAddons) {
|
||||
do_throw("non XML response should reject");
|
||||
}, function(err) {
|
||||
do_check_true(!!err);
|
||||
installManager.uninit();
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that getting a response with a single addon works as expected
|
||||
*/
|
||||
add_test(function test_checkForAddons_singleAddonNoUpdates() {
|
||||
let responseXML =
|
||||
"<?xml version=\"1.0\"?>" +
|
||||
"<updates>" +
|
||||
" <addons>" +
|
||||
" <addon id=\"gmp-gmpopenh264\"" +
|
||||
" URL=\"http://127.0.0.1:8011/gmp-gmpopenh264-1.1.zip\"" +
|
||||
" hashFunction=\"sha256\"" +
|
||||
" hashValue=\"1118b90d6f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee\"" +
|
||||
" version=\"1.1\"/>" +
|
||||
" </addons>" +
|
||||
"</updates>"
|
||||
overrideXHR(200, responseXML);
|
||||
let installManager = new GMPInstallManager();
|
||||
let promise = installManager.checkForAddons();
|
||||
promise.then(function(gmpAddons) {
|
||||
do_check_eq(gmpAddons.length, 1);
|
||||
let gmpAddon= gmpAddons[0];
|
||||
do_check_eq(gmpAddon.id, "gmp-gmpopenh264");
|
||||
do_check_eq(gmpAddon.URL, "http://127.0.0.1:8011/gmp-gmpopenh264-1.1.zip");
|
||||
do_check_eq(gmpAddon.hashFunction, "sha256");
|
||||
do_check_eq(gmpAddon.hashValue, "1118b90d6f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee");
|
||||
do_check_eq(gmpAddon.version, "1.1");
|
||||
do_check_eq(gmpAddon.size, undefined);
|
||||
do_check_true(gmpAddon.isValid);
|
||||
do_check_true(gmpAddon.isOpenH264);
|
||||
do_check_false(gmpAddon.isInstalled);
|
||||
installManager.uninit();
|
||||
run_next_test();
|
||||
}, function(err) {
|
||||
do_throw("1 addon found should not reject");
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that getting a response with a single addon with the optional size
|
||||
* attribute parses as expected.
|
||||
*/
|
||||
add_test(function test_checkForAddons_singleAddonNoUpdates() {
|
||||
let responseXML =
|
||||
"<?xml version=\"1.0\"?>" +
|
||||
"<updates>" +
|
||||
" <addons>" +
|
||||
" <addon id=\"openh264-plugin-no-at-symbol\"" +
|
||||
" URL=\"http://127.0.0.1:8011/gmp-gmpopenh264-1.1.zip\"" +
|
||||
" hashFunction=\"sha256\"" +
|
||||
" size=\"42\"" +
|
||||
" hashValue=\"1118b90d6f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee\"" +
|
||||
" version=\"1.1\"/>" +
|
||||
" </addons>" +
|
||||
"</updates>"
|
||||
overrideXHR(200, responseXML);
|
||||
let installManager = new GMPInstallManager();
|
||||
let promise = installManager.checkForAddons();
|
||||
promise.then(function(gmpAddons) {
|
||||
do_check_eq(gmpAddons.length, 1);
|
||||
let gmpAddon= gmpAddons[0];
|
||||
do_check_eq(gmpAddon.id, "openh264-plugin-no-at-symbol");
|
||||
do_check_eq(gmpAddon.URL, "http://127.0.0.1:8011/gmp-gmpopenh264-1.1.zip");
|
||||
do_check_eq(gmpAddon.hashFunction, "sha256");
|
||||
do_check_eq(gmpAddon.hashValue, "1118b90d6f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee");
|
||||
do_check_eq(gmpAddon.size, 42);
|
||||
do_check_eq(gmpAddon.version, "1.1");
|
||||
do_check_true(gmpAddon.isValid);
|
||||
do_check_false(gmpAddon.isOpenH264);
|
||||
do_check_false(gmpAddon.isInstalled);
|
||||
installManager.uninit();
|
||||
run_next_test();
|
||||
}, function(err) {
|
||||
do_throw("1 addon found should not reject");
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that checking for multiple addons work correctly.
|
||||
* Also tests that invalid addons work correctly.
|
||||
*/
|
||||
add_test(function test_checkForAddons_multipleAddonNoUpdatesSomeInvalid() {
|
||||
let responseXML =
|
||||
"<?xml version=\"1.0\"?>" +
|
||||
"<updates>" +
|
||||
" <addons>" +
|
||||
// valid openh264
|
||||
" <addon id=\"gmp-gmpopenh264\"" +
|
||||
" URL=\"http://127.0.0.1:8011/gmp-gmpopenh264-1.1.zip\"" +
|
||||
" hashFunction=\"sha256\"" +
|
||||
" hashValue=\"1118b90d6f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee\"" +
|
||||
" version=\"1.1\"/>" +
|
||||
// valid not openh264
|
||||
" <addon id=\"NOT-gmp-gmpopenh264\"" +
|
||||
" URL=\"http://127.0.0.1:8011/NOT-gmp-gmpopenh264-1.1.zip\"" +
|
||||
" hashFunction=\"sha512\"" +
|
||||
" hashValue=\"141592656f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee\"" +
|
||||
" version=\"9.1\"/>" +
|
||||
// noid
|
||||
" <addon notid=\"NOT-gmp-gmpopenh264\"" +
|
||||
" URL=\"http://127.0.0.1:8011/NOT-gmp-gmpopenh264-1.1.zip\"" +
|
||||
" hashFunction=\"sha512\"" +
|
||||
" hashValue=\"141592656f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee\"" +
|
||||
" version=\"9.1\"/>" +
|
||||
// no URL
|
||||
" <addon id=\"NOT-gmp-gmpopenh264\"" +
|
||||
" notURL=\"http://127.0.0.1:8011/NOT-gmp-gmpopenh264-1.1.zip\"" +
|
||||
" hashFunction=\"sha512\"" +
|
||||
" hashValue=\"141592656f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee\"" +
|
||||
" version=\"9.1\"/>" +
|
||||
// no hash function
|
||||
" <addon id=\"NOT-gmp-gmpopenh264\"" +
|
||||
" URL=\"http://127.0.0.1:8011/NOT-gmp-gmpopenh264-1.1.zip\"" +
|
||||
" nothashFunction=\"sha512\"" +
|
||||
" hashValue=\"141592656f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee\"" +
|
||||
" version=\"9.1\"/>" +
|
||||
// no hash function
|
||||
" <addon id=\"NOT-gmp-gmpopenh264\"" +
|
||||
" URL=\"http://127.0.0.1:8011/NOT-gmp-gmpopenh264-1.1.zip\"" +
|
||||
" hashFunction=\"sha512\"" +
|
||||
" nothashValue=\"141592656f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee\"" +
|
||||
" version=\"9.1\"/>" +
|
||||
// not version
|
||||
" <addon id=\"NOT-gmp-gmpopenh264\"" +
|
||||
" URL=\"http://127.0.0.1:8011/NOT-gmp-gmpopenh264-1.1.zip\"" +
|
||||
" hashFunction=\"sha512\"" +
|
||||
" hashValue=\"141592656f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee\"" +
|
||||
" notversion=\"9.1\"/>" +
|
||||
" </addons>" +
|
||||
"</updates>"
|
||||
overrideXHR(200, responseXML);
|
||||
let installManager = new GMPInstallManager();
|
||||
let promise = installManager.checkForAddons();
|
||||
promise.then(function(gmpAddons) {
|
||||
do_check_eq(gmpAddons.length, 7);
|
||||
let gmpAddon= gmpAddons[0];
|
||||
do_check_eq(gmpAddon.id, "gmp-gmpopenh264");
|
||||
do_check_eq(gmpAddon.URL, "http://127.0.0.1:8011/gmp-gmpopenh264-1.1.zip");
|
||||
do_check_eq(gmpAddon.hashFunction, "sha256");
|
||||
do_check_eq(gmpAddon.hashValue, "1118b90d6f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee");
|
||||
do_check_eq(gmpAddon.version, "1.1");
|
||||
do_check_true(gmpAddon.isValid);
|
||||
do_check_true(gmpAddon.isOpenH264);
|
||||
do_check_false(gmpAddon.isInstalled);
|
||||
|
||||
gmpAddon= gmpAddons[1];
|
||||
do_check_eq(gmpAddon.id, "NOT-gmp-gmpopenh264");
|
||||
do_check_eq(gmpAddon.URL, "http://127.0.0.1:8011/NOT-gmp-gmpopenh264-1.1.zip");
|
||||
do_check_eq(gmpAddon.hashFunction, "sha512");
|
||||
do_check_eq(gmpAddon.hashValue, "141592656f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee");
|
||||
do_check_eq(gmpAddon.version, "9.1");
|
||||
do_check_true(gmpAddon.isValid);
|
||||
do_check_false(gmpAddon.isOpenH264);
|
||||
do_check_false(gmpAddon.isInstalled);
|
||||
|
||||
for (let i = 2; i < gmpAddons.length; i++) {
|
||||
do_check_false(gmpAddons[i].isValid);
|
||||
do_check_false(gmpAddons[i].isInstalled);
|
||||
}
|
||||
installManager.uninit();
|
||||
run_next_test();
|
||||
}, function(err) {
|
||||
do_throw("multiple addons found should not reject");
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that checking for addons when there are also updates available
|
||||
* works as expected.
|
||||
*/
|
||||
add_test(function test_checkForAddons_updatesWithAddons() {
|
||||
let responseXML =
|
||||
"<?xml version=\"1.0\"?>" +
|
||||
" <updates>" +
|
||||
" <update type=\"minor\" displayVersion=\"33.0a1\" appVersion=\"33.0a1\" platformVersion=\"33.0a1\" buildID=\"20140628030201\">" +
|
||||
" <patch type=\"complete\" URL=\"http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/2014/06/2014-06-28-03-02-01-mozilla-central/firefox-33.0a1.en-US.mac.complete.mar\" hashFunction=\"sha512\" hashValue=\"f3f90d71dff03ae81def80e64bba3e4569da99c9e15269f731c2b167c4fc30b3aed9f5fee81c19614120230ca333e73a5e7def1b8e45d03135b2069c26736219\" size=\"85249896\"/>" +
|
||||
" </update>" +
|
||||
" <addons>" +
|
||||
" <addon id=\"gmp-gmpopenh264\"" +
|
||||
" URL=\"http://127.0.0.1:8011/gmp-gmpopenh264-1.1.zip\"" +
|
||||
" hashFunction=\"sha256\"" +
|
||||
" hashValue=\"1118b90d6f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee\"" +
|
||||
" version=\"1.1\"/>" +
|
||||
" </addons>" +
|
||||
"</updates>"
|
||||
overrideXHR(200, responseXML);
|
||||
let installManager = new GMPInstallManager();
|
||||
let promise = installManager.checkForAddons();
|
||||
promise.then(function(gmpAddons) {
|
||||
do_check_eq(gmpAddons.length, 1);
|
||||
let gmpAddon= gmpAddons[0];
|
||||
do_check_eq(gmpAddon.id, "gmp-gmpopenh264");
|
||||
do_check_eq(gmpAddon.URL, "http://127.0.0.1:8011/gmp-gmpopenh264-1.1.zip");
|
||||
do_check_eq(gmpAddon.hashFunction, "sha256");
|
||||
do_check_eq(gmpAddon.hashValue, "1118b90d6f645eefc2b99af17bae396636ace1e33d079c88de715177584e2aee");
|
||||
do_check_eq(gmpAddon.version, "1.1");
|
||||
do_check_true(gmpAddon.isValid);
|
||||
do_check_true(gmpAddon.isOpenH264);
|
||||
do_check_false(gmpAddon.isInstalled);
|
||||
installManager.uninit();
|
||||
run_next_test();
|
||||
}, function(err) {
|
||||
do_throw("updates with addons should not reject");
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that installing found addons works as expected
|
||||
*/
|
||||
function test_checkForAddons_installAddon(id, includeSize,wantInstallReject) {
|
||||
do_print("Running installAddon for includeSize: " + includeSize +
|
||||
" and wantInstallReject: " + wantInstallReject);
|
||||
let httpServer = new HttpServer();
|
||||
let dir = FileUtils.getDir("TmpD", [], true);
|
||||
httpServer.registerDirectory("/", dir);
|
||||
httpServer.start(-1);
|
||||
let testserverPort = httpServer.identity.primaryPort;
|
||||
let zipFileName = "test_" + id + "_GMP.zip";
|
||||
|
||||
let zipURL = URL_HOST + ":" + testserverPort + "/" + zipFileName;
|
||||
do_print("zipURL: " + zipURL);
|
||||
|
||||
let data = "e~=0.5772156649";
|
||||
let zipFile = createNewZipFile(zipFileName, data);
|
||||
let hashFunc = "sha256";
|
||||
let expectedDigest = yield GMPDownloader.computeHash(hashFunc, zipFile);
|
||||
|
||||
let fileSize = zipFile.size;
|
||||
if (wantInstallReject) {
|
||||
fileSize = 1;
|
||||
}
|
||||
|
||||
let responseXML =
|
||||
"<?xml version=\"1.0\"?>" +
|
||||
"<updates>" +
|
||||
" <addons>" +
|
||||
" <addon id=\"" + id + "-gmp-gmpopenh264\"" +
|
||||
" URL=\"" + zipURL + "\"" +
|
||||
" hashFunction=\"" + hashFunc + "\"" +
|
||||
" hashValue=\"" + expectedDigest + "\"" +
|
||||
(includeSize ? " size=\"" + fileSize + "\"" : "") +
|
||||
" version=\"1.1\"/>" +
|
||||
" </addons>" +
|
||||
"</updates>"
|
||||
|
||||
overrideXHR(200, responseXML);
|
||||
let installManager = new GMPInstallManager();
|
||||
let checkPromise = installManager.checkForAddons();
|
||||
checkPromise.then(function(gmpAddons) {
|
||||
do_check_eq(gmpAddons.length, 1);
|
||||
let gmpAddon = gmpAddons[0];
|
||||
do_check_false(gmpAddon.isInstalled);
|
||||
|
||||
GMPInstallManager.overrideLeaveDownloadedZip = true;
|
||||
let installPromise = installManager.installAddon(gmpAddon);
|
||||
installPromise.then(function(extractedPaths) {
|
||||
if (wantInstallReject) {
|
||||
do_throw("install update should reject");
|
||||
}
|
||||
do_check_eq(extractedPaths.length, 1);
|
||||
let extractedPath = extractedPaths[0];
|
||||
|
||||
do_print("Extracted path: " + extractedPath);
|
||||
|
||||
let extractedFile = Cc["@mozilla.org/file/local;1"].
|
||||
createInstance(Ci.nsIFile);
|
||||
extractedFile.initWithPath(extractedPath);
|
||||
do_check_true(extractedFile.exists());
|
||||
let readData = readStringFromFile(extractedFile);
|
||||
do_check_eq(readData, data);
|
||||
|
||||
// Check that the downloaded zip mathces the offered zip exactly
|
||||
let downloadedGMPFile = FileUtils.getFile("TmpD",
|
||||
[gmpAddon.id + ".zip"]);
|
||||
do_check_true(downloadedGMPFile.exists());
|
||||
let downloadedBytes = getBinaryFileData(downloadedGMPFile);
|
||||
let sourceBytes = getBinaryFileData(zipFile);
|
||||
do_check_true(compareBinaryData(downloadedBytes, sourceBytes));
|
||||
|
||||
// Make sure the prefs are set correctly
|
||||
do_check_true(!!GMPPrefs.get(GMPPrefs.KEY_ADDON_LAST_UPDATE,
|
||||
gmpAddon.id, ""));
|
||||
do_check_eq(GMPPrefs.get(GMPPrefs.KEY_ADDON_PATH, gmpAddon.id, ""),
|
||||
extractedFile.parent.path);
|
||||
do_check_eq(GMPPrefs.get(GMPPrefs.KEY_ADDON_VERSION, gmpAddon.id, ""),
|
||||
"1.1");
|
||||
// Make sure it reports as being installed
|
||||
do_check_true(gmpAddon.isInstalled);
|
||||
|
||||
// Cleanup
|
||||
extractedFile.parent.remove(true);
|
||||
zipFile.remove(false);
|
||||
httpServer.stop(function() {});
|
||||
do_print("Removing downloaded GMP file: " + downloadedGMPFile.path);
|
||||
downloadedGMPFile.remove(false);
|
||||
installManager.uninit();
|
||||
}, function(err) {
|
||||
zipFile.remove(false);
|
||||
let downloadedGMPFile = FileUtils.getFile("TmpD",
|
||||
[gmpAddon.id + ".zip"]);
|
||||
do_print("Removing from err downloaded GMP file: " +
|
||||
downloadedGMPFile.path);
|
||||
downloadedGMPFile.remove(false);
|
||||
if (!wantInstallReject) {
|
||||
do_throw("install update should not reject");
|
||||
}
|
||||
});
|
||||
}, function(err) {
|
||||
do_throw("checking updates to install them should not reject");
|
||||
});
|
||||
}
|
||||
|
||||
add_task(test_checkForAddons_installAddon.bind(null, "1", true, false));
|
||||
add_task(test_checkForAddons_installAddon.bind(null, "2", false, false));
|
||||
add_task(test_checkForAddons_installAddon.bind(null, "3", true, true));
|
||||
|
||||
/**
|
||||
* Tests that installing addons when there is no server works as expected
|
||||
*/
|
||||
add_test(function test_installAddon_noServer() {
|
||||
let dir = FileUtils.getDir("TmpD", [], true);
|
||||
let zipFileName = "test_GMP.zip";
|
||||
let zipURL = URL_HOST + ":0/" + zipFileName;
|
||||
|
||||
let data = "e~=0.5772156649";
|
||||
let zipFile = createNewZipFile(zipFileName, data);
|
||||
|
||||
let responseXML =
|
||||
"<?xml version=\"1.0\"?>" +
|
||||
"<updates>" +
|
||||
" <addons>" +
|
||||
" <addon id=\"gmp-gmpopenh264\"" +
|
||||
" URL=\"" + zipURL + "\"" +
|
||||
" hashFunction=\"sha256\"" +
|
||||
" hashValue=\"11221cbda000347b054028b527a60e578f919cb10f322ef8077d3491c6fcb474\"" +
|
||||
" version=\"1.1\"/>" +
|
||||
" </addons>" +
|
||||
"</updates>"
|
||||
|
||||
overrideXHR(200, responseXML);
|
||||
let installManager = new GMPInstallManager();
|
||||
let checkPromise = installManager.checkForAddons();
|
||||
checkPromise.then(function(gmpAddons) {
|
||||
do_check_eq(gmpAddons.length, 1);
|
||||
let gmpAddon= gmpAddons[0];
|
||||
|
||||
GMPInstallManager.overrideLeaveDownloadedZip = true;
|
||||
let installPromise = installManager.installAddon(gmpAddon);
|
||||
installPromise.then(function(extractedPaths) {
|
||||
do_throw("No server for install should reject");
|
||||
}, function(err) {
|
||||
do_check_true(!!err);
|
||||
installManager.uninit();
|
||||
run_next_test();
|
||||
});
|
||||
}, function(err) {
|
||||
do_throw("check should not reject for installn o server");
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns the read stream into a string
|
||||
*/
|
||||
function readStringFromInputStream(inputStream) {
|
||||
let sis = Cc["@mozilla.org/scriptableinputstream;1"].
|
||||
createInstance(Ci.nsIScriptableInputStream);
|
||||
sis.init(inputStream);
|
||||
let text = sis.read(sis.available());
|
||||
sis.close();
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a string of text from a file.
|
||||
* This function only works with ASCII text.
|
||||
*/
|
||||
function readStringFromFile(file) {
|
||||
if (!file.exists()) {
|
||||
do_print("readStringFromFile - file doesn't exist: " + file.path);
|
||||
return null;
|
||||
}
|
||||
let fis = Cc["@mozilla.org/network/file-input-stream;1"].
|
||||
createInstance(Ci.nsIFileInputStream);
|
||||
fis.init(file, FileUtils.MODE_RDONLY, FileUtils.PERMS_FILE, 0);
|
||||
return readStringFromInputStream(fis);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bare bones XMLHttpRequest implementation for testing onprogress, onerror,
|
||||
* and onload nsIDomEventListener handleEvent.
|
||||
*/
|
||||
function makeHandler(aVal) {
|
||||
if (typeof aVal == "function")
|
||||
return { handleEvent: aVal };
|
||||
return aVal;
|
||||
}
|
||||
/**
|
||||
* Constructs a mock xhr which is used for testing different aspects
|
||||
* of responses.
|
||||
*/
|
||||
function xhr(inputStatus, inputResponse) {
|
||||
this.inputStatus = inputStatus;
|
||||
this.inputResponse = inputResponse;
|
||||
}
|
||||
xhr.prototype = {
|
||||
overrideMimeType: function(aMimetype) { },
|
||||
setRequestHeader: function(aHeader, aValue) { },
|
||||
status: null,
|
||||
channel: { set notificationCallbacks(aVal) { } },
|
||||
_url: null,
|
||||
_method: null,
|
||||
open: function(aMethod, aUrl) {
|
||||
this.channel.originalURI = Services.io.newURI(aUrl, null, null);
|
||||
this._method = aMethod; this._url = aUrl;
|
||||
},
|
||||
abort: function() {
|
||||
},
|
||||
responseXML: null,
|
||||
responseText: null,
|
||||
send: function(aBody) {
|
||||
let self = this;
|
||||
do_execute_soon(function() {
|
||||
self.status = self.inputStatus;
|
||||
self.responseText = self.inputResponse;
|
||||
try {
|
||||
let parser = Cc["@mozilla.org/xmlextras/domparser;1"].
|
||||
createInstance(Ci.nsIDOMParser);
|
||||
self.responseXML = parser.parseFromString(self.inputResponse,
|
||||
"application/xml");
|
||||
} catch (e) {
|
||||
self.responseXML = null;
|
||||
}
|
||||
let e = { target: self };
|
||||
if (self.inputStatus === 200) {
|
||||
self.onload(e);
|
||||
} else {
|
||||
self.onerror(e);
|
||||
}
|
||||
});
|
||||
},
|
||||
_onprogress: null,
|
||||
set onprogress(aValue) { this._onprogress = makeHandler(aValue); },
|
||||
get onprogress() { return this._onprogress; },
|
||||
_onerror: null,
|
||||
set onerror(aValue) { this._onerror = makeHandler(aValue); },
|
||||
get onerror() { return this._onerror; },
|
||||
_onload: null,
|
||||
set onload(aValue) { this._onload = makeHandler(aValue); },
|
||||
get onload() { return this._onload; },
|
||||
addEventListener: function(aEvent, aValue, aCapturing) {
|
||||
eval("this._on" + aEvent + " = aValue");
|
||||
},
|
||||
flags: Ci.nsIClassInfo.SINGLETON,
|
||||
implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT,
|
||||
getHelperForLanguage: function(aLanguage) null,
|
||||
getInterfaces: function(aCount) {
|
||||
let interfaces = [Ci.nsISupports];
|
||||
aCount.value = interfaces.length;
|
||||
return interfaces;
|
||||
},
|
||||
classDescription: "XMLHttpRequest",
|
||||
contractID: "@mozilla.org/xmlextras/xmlhttprequest;1",
|
||||
classID: Components.ID("{c9b37f43-4278-4304-a5e0-600991ab08cb}"),
|
||||
createInstance: function(aOuter, aIID) {
|
||||
if (aOuter == null)
|
||||
return this.QueryInterface(aIID);
|
||||
throw Cr.NS_ERROR_NO_AGGREGATION;
|
||||
},
|
||||
QueryInterface: function(aIID) {
|
||||
if (aIID.equals(Ci.nsIClassInfo) ||
|
||||
aIID.equals(Ci.nsISupports))
|
||||
return this;
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
get wrappedJSObject() { return this; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper used to overrideXHR requests (no matter to what URL) with the
|
||||
* specified status and response.
|
||||
* @param status The status you want to get back when an XHR request is made
|
||||
* @param response The response you want to get back when an XHR request is made
|
||||
*/
|
||||
function overrideXHR(status, response) {
|
||||
let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
if (overrideXHR.myxhr) {
|
||||
registrar.unregisterFactory(overrideXHR.myxhr.classID, overrideXHR.myxhr);
|
||||
}
|
||||
overrideXHR.myxhr = new xhr(status, response);
|
||||
registrar.registerFactory(overrideXHR.myxhr.classID,
|
||||
overrideXHR.myxhr.classDescription,
|
||||
overrideXHR.myxhr.contractID,
|
||||
overrideXHR.myxhr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares binary data of 2 arrays and returns true if they are the same
|
||||
*
|
||||
* @param arr1 The first array to compare
|
||||
* @param arr2 The second array to compare
|
||||
*/
|
||||
function compareBinaryData(arr1, arr2) {
|
||||
do_check_eq(arr1.length, arr2.length);
|
||||
for (let i = 0; i < arr1.length; i++) {
|
||||
if (arr1[i] != arr2[i]) {
|
||||
do_print("Data differs at index " + i +
|
||||
", arr1: " + arr1[i] + ", arr2: " + arr2[i]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a file's data and returns it
|
||||
*
|
||||
* @param file The file to read the data from
|
||||
* @return array of bytes for the data in the file.
|
||||
*/
|
||||
function getBinaryFileData(file) {
|
||||
let fileStream = Cc["@mozilla.org/network/file-input-stream;1"].
|
||||
createInstance(Ci.nsIFileInputStream);
|
||||
// Open as RD_ONLY with default permissions.
|
||||
fileStream.init(file, FileUtils.MODE_RDONLY, FileUtils.PERMS_FILE, 0);
|
||||
|
||||
// Check the returned size versus the expected size.
|
||||
let stream = Cc["@mozilla.org/binaryinputstream;1"].
|
||||
createInstance(Ci.nsIBinaryInputStream);
|
||||
stream.setInputStream(fileStream);
|
||||
let bytes = stream.readByteArray(stream.available());
|
||||
fileStream.close();
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new zip file containing a file with the specified data
|
||||
* @param zipName The name of the zip file
|
||||
* @param data The data to go inside the zip for the filename entry1.info
|
||||
*/
|
||||
function createNewZipFile(zipName, data) {
|
||||
// Create a zip file which will be used for extracting
|
||||
let stream = Cc["@mozilla.org/io/string-input-stream;1"].
|
||||
createInstance(Ci.nsIStringInputStream);
|
||||
stream.setData(data, data.length);
|
||||
let zipWriter = Cc["@mozilla.org/zipwriter;1"].
|
||||
createInstance(Components.interfaces.nsIZipWriter);
|
||||
let zipFile = FileUtils.getFile("TmpD", [zipName]);
|
||||
if (zipFile.exists()) {
|
||||
zipFile.remove(false);
|
||||
}
|
||||
// From prio.h
|
||||
const PR_RDWR = 0x04;
|
||||
const PR_CREATE_FILE = 0x08;
|
||||
const PR_TRUNCATE = 0x20;
|
||||
zipWriter.open(zipFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
|
||||
zipWriter.addEntryStream("entry1.info", Date.now(),
|
||||
Ci.nsIZipWriter.COMPRESSION_BEST, stream, false);
|
||||
zipWriter.close();
|
||||
stream.close();
|
||||
do_print("zip file created on disk at: " + zipFile.path);
|
||||
return zipFile;
|
||||
}
|
@ -13,6 +13,7 @@ support-files =
|
||||
[test_dict.js]
|
||||
[test_DirectoryLinksProvider.js]
|
||||
[test_FileUtils.js]
|
||||
[test_GMPInstallManager.js]
|
||||
[test_Http.js]
|
||||
[test_Log.js]
|
||||
[test_NewTabUtils.js]
|
||||
|
@ -3088,7 +3088,7 @@ var gDetailView = {
|
||||
errorLink.value = gStrings.ext.GetStringFromName("details.notification.vulnerableNoUpdate.link");
|
||||
errorLink.href = this._addon.blocklistURL;
|
||||
errorLink.hidden = false;
|
||||
} else if (this._addon.id == "openh264-plugin@cisco.com" && !this._addon.isInstalled) {
|
||||
} else if (this._addon.id == "gmp-gmpopenh264" && !this._addon.isInstalled) {
|
||||
this.node.setAttribute("notification", "warning");
|
||||
let warning = document.getElementById("detail-warning");
|
||||
warning.textContent = gStrings.ext.GetStringFromName("details.notification.openH264Pending");
|
||||
|
@ -1294,7 +1294,7 @@
|
||||
this._errorLink.value = gStrings.ext.GetStringFromName("notification.vulnerableNoUpdate.link");
|
||||
this._errorLink.href = this.mAddon.blocklistURL;
|
||||
this._errorLink.hidden = false;
|
||||
} else if (this.mAddon.id == "openh264-plugin@cisco.com" && !this.mAddon.isInstalled) {
|
||||
} else if (this.mAddon.id == "gmp-gmpopenh264" && !this.mAddon.isInstalled) {
|
||||
this.setAttribute("notification", "warning");
|
||||
this._warning.textContent = gStrings.ext.GetStringFromName("notification.openH264Pending");
|
||||
} else {
|
||||
|
@ -15,18 +15,22 @@ Cu.import("resource://gre/modules/AddonManager.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Preferences.jsm");
|
||||
Cu.import("resource://gre/modules/osfile.jsm");
|
||||
Cu.import("resource://gre/modules/Log.jsm");
|
||||
|
||||
const URI_EXTENSION_STRINGS = "chrome://mozapps/locale/extensions/extensions.properties";
|
||||
const STRING_TYPE_NAME = "type.%ID%.name";
|
||||
|
||||
const OPENH264_PLUGIN_ID = "openh264-plugin@cisco.com";
|
||||
const OPENH264_PREF_BRANCH = "media.openh264.";
|
||||
const OPENH264_PLUGIN_ID = "gmp-gmpopenh264";
|
||||
const OPENH264_PREF_BRANCH = "media." + OPENH264_PLUGIN_ID + ".";
|
||||
const OPENH264_PREF_ENABLED = "enabled";
|
||||
const OPENH264_PREF_PATH = "path";
|
||||
const OPENH264_PREF_VERSION = "version";
|
||||
const OPENH264_PREF_LASTUPDATE = "lastUpdate";
|
||||
const OPENH264_PREF_AUTOUPDATE = "autoupdate";
|
||||
const OPENH264_PREF_PROVIDERENABLED = "providerEnabled";
|
||||
const OPENH264_PREF_PROVIDERENABLED = "provider.enabled";
|
||||
const OPENH264_PREF_LOGGING = "provider.logging";
|
||||
const OPENH264_PREF_LOGGING_LEVEL = OPENH264_PREF_LOGGING + ".level"; // media.gmp-gmpopenh264.provider.logging.level
|
||||
const OPENH264_PREF_LOGGING_DUMP = OPENH264_PREF_LOGGING + ".dump"; // media.gmp-gmpopenh264.provider.logging.dump
|
||||
const OPENH264_HOMEPAGE_URL = "http://www.openh264.org/";
|
||||
const OPENH264_OPTIONS_URL = "chrome://mozapps/content/extensions/openH264Prefs.xul";
|
||||
|
||||
@ -37,6 +41,30 @@ XPCOMUtils.defineLazyGetter(this, "prefs",
|
||||
XPCOMUtils.defineLazyGetter(this, "gmpService",
|
||||
() => Cc["@mozilla.org/gecko-media-plugin-service;1"].getService(Ci.mozIGeckoMediaPluginService));
|
||||
|
||||
let gLogger;
|
||||
let gLogDumping = false;
|
||||
let gLogAppenderDump = null;
|
||||
|
||||
function configureLogging() {
|
||||
if (!gLogger) {
|
||||
gLogger = Log.repository.getLogger("Toolkit.OpenH264Provider");
|
||||
gLogger.addAppender(new Log.ConsoleAppender(new Log.BasicFormatter()));
|
||||
}
|
||||
gLogger.level = prefs.get(OPENH264_PREF_LOGGING_LEVEL, Log.Level.Warn);
|
||||
|
||||
let logDumping = prefs.get(OPENH264_PREF_LOGGING_DUMP, false);
|
||||
if (logDumping != gLogDumping) {
|
||||
if (logDumping) {
|
||||
gLogAppenderDump = new Log.DumpAppender(new Log.BasicFormatter());
|
||||
gLogger.addAppender(gLogAppenderDump);
|
||||
} else {
|
||||
gLogger.removeAppender(gLogAppenderDump);
|
||||
gLogAppenderDump = null;
|
||||
}
|
||||
gLogDumping = logDumping;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The OpenH264Wrapper provides the info for the OpenH264 GMP plugin to public callers through the API.
|
||||
*/
|
||||
@ -63,7 +91,7 @@ let OpenH264Wrapper = Object.freeze({
|
||||
get isActive() { return !this.userDisabled; },
|
||||
get appDisabled() { return false; },
|
||||
|
||||
get userDisabled() { return !prefs.get(OPENH264_PREF_ENABLED, false); },
|
||||
get userDisabled() { return !prefs.get(OPENH264_PREF_ENABLED, true); },
|
||||
set userDisabled(aVal) { prefs.set(OPENH264_PREF_ENABLED, aVal === false); },
|
||||
|
||||
get blocklistState() { return Ci.nsIBlocklistService.STATE_NOT_BLOCKED; },
|
||||
@ -85,7 +113,7 @@ let OpenH264Wrapper = Object.freeze({
|
||||
get updateDate() {
|
||||
let time = Number(prefs.get(OPENH264_PREF_LASTUPDATE, null));
|
||||
if (time !== NaN && this.isInstalled) {
|
||||
return new Date(time)
|
||||
return new Date(time * 1000)
|
||||
}
|
||||
return null;
|
||||
},
|
||||
@ -158,20 +186,30 @@ let OpenH264Wrapper = Object.freeze({
|
||||
|
||||
let OpenH264Provider = {
|
||||
startup: function() {
|
||||
configureLogging();
|
||||
this._log = Log.repository.getLogger("Toolkit.OpenH264Provider");
|
||||
this.gmpPath = prefs.get(OPENH264_PREF_PATH, null);
|
||||
let enabled = prefs.get(OPENH264_PREF_ENABLED, true);
|
||||
this._log.trace("startup() - enabled=" + enabled + ", gmpPath="+this.gmpPath);
|
||||
|
||||
|
||||
Services.obs.addObserver(this, AddonManager.OPTIONS_NOTIFICATION_DISPLAYED, false);
|
||||
prefs.observe(OPENH264_PREF_ENABLED, this.onPrefEnabledChanged, this);
|
||||
prefs.observe(OPENH264_PREF_PATH, this.onPrefPathChanged, this);
|
||||
prefs.observe(OPENH264_PREF_LOGGING, configureLogging);
|
||||
|
||||
this.gmpPath = prefs.get(OPENH264_PREF_PATH, null);
|
||||
if (this.gmpPath) {
|
||||
if (this.gmpPath && enabled) {
|
||||
this._log.info("startup() - adding gmp directory " + this.gmpPath);
|
||||
gmpService.addPluginDirectory(this.gmpPath);
|
||||
}
|
||||
},
|
||||
|
||||
shutdown: function() {
|
||||
this._log.trace("shutdown()");
|
||||
Services.obs.removeObserver(this, AddonManager.OPTIONS_NOTIFICATION_DISPLAYED);
|
||||
prefs.ignore(OPENH264_PREF_ENABLED, this.onPrefEnabledChanged, this);
|
||||
prefs.ignore(OPENH264_PREF_PATH, this.onPrefPathChanged, this);
|
||||
prefs.ignore(OPENH264_PREF_LOGGING, configureLogging);
|
||||
},
|
||||
|
||||
onPrefEnabledChanged: function() {
|
||||
@ -180,6 +218,15 @@ let OpenH264Provider = {
|
||||
AddonManagerPrivate.callAddonListeners(wrapper.isActive ?
|
||||
"onEnabling" : "onDisabling",
|
||||
wrapper, false);
|
||||
if (this.gmpPath) {
|
||||
if (wrapper.isActive) {
|
||||
this._log.info("onPrefEnabledChanged() - adding gmp directory " + this.gmpPath);
|
||||
gmpService.addPluginDirectory(this.gmpPath);
|
||||
} else {
|
||||
this._log.info("onPrefEnabledChanged() - removing gmp directory " + this.gmpPath);
|
||||
gmpService.removePluginDirectory(this.gmpPath);
|
||||
}
|
||||
}
|
||||
AddonManagerPrivate.callAddonListeners(wrapper.isActive ?
|
||||
"onEnabled" : "onDisabled",
|
||||
wrapper);
|
||||
@ -190,13 +237,15 @@ let OpenH264Provider = {
|
||||
|
||||
AddonManagerPrivate.callAddonListeners("onUninstalling", wrapper, false);
|
||||
if (this.gmpPath) {
|
||||
this._log.info("onPrefPathChanged() - removing gmp directory " + this.gmpPath);
|
||||
gmpService.removePluginDirectory(this.gmpPath);
|
||||
}
|
||||
AddonManagerPrivate.callAddonListeners("onUninstalled", wrapper);
|
||||
|
||||
AddonManagerPrivate.callInstallListeners("onExternalInstall", null, wrapper, null, false);
|
||||
this.gmpPath = prefs.get(OPENH264_PREF_PATH, null);
|
||||
if (this.gmpPath) {
|
||||
if (this.gmpPath && wrapper.isActive) {
|
||||
this._log.info("onPrefPathChanged() - adding gmp directory " + this.gmpPath);
|
||||
gmpService.addPluginDirectory(this.gmpPath);
|
||||
}
|
||||
AddonManagerPrivate.callAddonListeners("onInstalled", wrapper);
|
||||
|
@ -4,13 +4,16 @@
|
||||
|
||||
let {AddonTestUtils} = Components.utils.import("resource://testing-common/AddonManagerTesting.jsm", {});
|
||||
|
||||
const OPENH264_PLUGIN_ID = "openh264-plugin@cisco.com";
|
||||
const OPENH264_PREF_BRANCH = "media.openh264.";
|
||||
const OPENH264_PLUGIN_ID = "gmp-gmpopenh264";
|
||||
const OPENH264_PREF_BRANCH = "media." + OPENH264_PLUGIN_ID + ".";
|
||||
const OPENH264_PREF_ENABLED = OPENH264_PREF_BRANCH + "enabled";
|
||||
const OPENH264_PREF_PATH = OPENH264_PREF_BRANCH + "path";
|
||||
const OPENH264_PREF_VERSION = OPENH264_PREF_BRANCH + "version";
|
||||
const OPENH264_PREF_LASTUPDATE = OPENH264_PREF_BRANCH + "lastUpdate";
|
||||
const OPENH264_PREF_AUTOUPDATE = OPENH264_PREF_BRANCH + "autoupdate";
|
||||
const PREF_LOGGING = OPENH264_PREF_BRANCH + "provider.logging";
|
||||
const PREF_LOGGING_LEVEL = PREF_LOGGING + ".level";
|
||||
const PREF_LOGGING_DUMP = PREF_LOGGING + ".dump";
|
||||
|
||||
const TEST_DATE = new Date(2013, 0, 1, 12);
|
||||
|
||||
@ -56,6 +59,9 @@ function openDetailsView(aId) {
|
||||
}
|
||||
|
||||
add_task(function* initializeState() {
|
||||
Services.prefs.setBoolPref(PREF_LOGGING_DUMP, true);
|
||||
Services.prefs.setIntPref(PREF_LOGGING_LEVEL, 0);
|
||||
|
||||
gManagerWindow = yield open_manager();
|
||||
gCategoryUtilities = new CategoryUtilities(gManagerWindow);
|
||||
|
||||
@ -67,6 +73,8 @@ add_task(function* initializeState() {
|
||||
Services.prefs.clearUserPref(OPENH264_PREF_VERSION);
|
||||
Services.prefs.clearUserPref(OPENH264_PREF_LASTUPDATE);
|
||||
Services.prefs.clearUserPref(OPENH264_PREF_AUTOUPDATE);
|
||||
Services.prefs.clearUserPref(PREF_LOGGING_DUMP);
|
||||
Services.prefs.clearUserPref(PREF_LOGGING_LEVEL);
|
||||
});
|
||||
|
||||
let chrome = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIXULChromeRegistry);
|
||||
|
@ -102,7 +102,7 @@ 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.openh264.providerEnabled", false);
|
||||
Services.prefs.setBoolPref("media.gmp-gmpopenh264.provider.enabled", false);
|
||||
|
||||
startupManager();
|
||||
|
||||
|
@ -5,13 +5,16 @@
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
const OPENH264_PLUGIN_ID = "openh264-plugin@cisco.com";
|
||||
const OPENH264_PREF_BRANCH = "media.openh264.";
|
||||
const OPENH264_PLUGIN_ID = "gmp-gmpopenh264";
|
||||
const OPENH264_PREF_BRANCH = "media." + OPENH264_PLUGIN_ID + ".";
|
||||
const OPENH264_PREF_ENABLED = OPENH264_PREF_BRANCH + "enabled";
|
||||
const OPENH264_PREF_PATH = OPENH264_PREF_BRANCH + "path";
|
||||
const OPENH264_PREF_VERSION = OPENH264_PREF_BRANCH + "version";
|
||||
const OPENH264_PREF_LASTUPDATE = OPENH264_PREF_BRANCH + "lastUpdate";
|
||||
const OPENH264_PREF_AUTOUPDATE = OPENH264_PREF_BRANCH + "autoupdate";
|
||||
const PREF_LOGGING = OPENH264_PREF_BRANCH + "provider.logging";
|
||||
const PREF_LOGGING_LEVEL = PREF_LOGGING + ".level";
|
||||
const PREF_LOGGING_DUMP = PREF_LOGGING + ".dump";
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "pluginsBundle",
|
||||
() => Services.strings.createBundle("chrome://global/locale/plugins.properties"));
|
||||
@ -27,6 +30,8 @@ function run_test() {
|
||||
add_task(function* test_notInstalled() {
|
||||
Services.prefs.setCharPref(OPENH264_PREF_PATH, "");
|
||||
Services.prefs.setBoolPref(OPENH264_PREF_ENABLED, false);
|
||||
Services.prefs.setBoolPref(PREF_LOGGING_DUMP, true);
|
||||
Services.prefs.setIntPref(PREF_LOGGING_LEVEL, 0);
|
||||
|
||||
let addons = yield promiseAddonsByIDs([OPENH264_PLUGIN_ID]);
|
||||
Assert.equal(addons.length, 1);
|
||||
@ -73,13 +78,14 @@ add_task(function* test_notInstalled() {
|
||||
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 file = Services.dirsvc.get("ProfD", Ci.nsIFile);
|
||||
file.append("openh264");
|
||||
file.append("testDir");
|
||||
|
||||
Services.prefs.setBoolPref(OPENH264_PREF_ENABLED, false);
|
||||
Services.prefs.setCharPref(OPENH264_PREF_LASTUPDATE, "" + TEST_DATE.getTime());
|
||||
Services.prefs.setCharPref(OPENH264_PREF_LASTUPDATE, "" + TEST_TIME_SEC);
|
||||
Services.prefs.setCharPref(OPENH264_PREF_VERSION, TEST_VERSION);
|
||||
Services.prefs.setCharPref(OPENH264_PREF_PATH, file.path);
|
||||
|
||||
@ -100,7 +106,7 @@ add_task(function* test_installed() {
|
||||
Assert.equal(addon.permissions, AddonManager.PERM_CAN_UPGRADE |
|
||||
AddonManager.PERM_CAN_ENABLE);
|
||||
|
||||
Assert.equal(addon.updateDate.getTime(), TEST_DATE.getTime());
|
||||
Assert.equal(addon.updateDate.getTime(), TEST_TIME_SEC * 1000);
|
||||
|
||||
let mimetypes = addon.pluginMimeTypes;
|
||||
Assert.ok(mimetypes);
|
||||
@ -163,6 +169,7 @@ add_task(function* test_pluginRegistration() {
|
||||
|
||||
let OpenH264Scope = Cu.import("resource://gre/modules/addons/OpenH264Provider.jsm");
|
||||
OpenH264Scope.gmpService = MockGMPService;
|
||||
Services.prefs.setBoolPref(OPENH264_PREF_ENABLED, true);
|
||||
|
||||
// Check that the OpenH264 plugin gets registered after startup.
|
||||
Services.prefs.setCharPref(OPENH264_PREF_PATH, file.path);
|
||||
@ -191,4 +198,23 @@ add_task(function* test_pluginRegistration() {
|
||||
Services.prefs.setCharPref(OPENH264_PREF_PATH, file2.path);
|
||||
Assert.equal(addedPath, file2.path);
|
||||
Assert.equal(removedPath, file.path);
|
||||
|
||||
// Disabling OpenH264 should cause unregistration.
|
||||
Services.prefs.setCharPref(OPENH264_PREF_PATH, file.path);
|
||||
clearPaths();
|
||||
Services.prefs.setBoolPref(OPENH264_PREF_ENABLED, false);
|
||||
Assert.equal(addedPath, null);
|
||||
Assert.equal(removedPath, file.path);
|
||||
|
||||
// Restarting with OpenH264 disabled should not cause registration.
|
||||
clearPaths();
|
||||
yield promiseRestartManager();
|
||||
Assert.equal(addedPath, null);
|
||||
Assert.equal(removedPath, null);
|
||||
|
||||
// Re-enabling OpenH264 should cause registration.
|
||||
clearPaths();
|
||||
Services.prefs.setBoolPref(OPENH264_PREF_ENABLED, true);
|
||||
Assert.equal(addedPath, file.path);
|
||||
Assert.equal(removedPath, null);
|
||||
});
|
||||
|
@ -67,7 +67,7 @@ function run_test() {
|
||||
do_test_pending();
|
||||
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
|
||||
|
||||
Services.prefs.setBoolPref("media.openh264.providerEnabled", false);
|
||||
Services.prefs.setBoolPref("media.gmp-gmpopenh264.provider.enabled", false);
|
||||
|
||||
startupManager();
|
||||
AddonManager.addAddonListener(AddonListener);
|
||||
|
Loading…
Reference in New Issue
Block a user