mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Merge latest green fx-team changeset and mozilla-central; a=merge
This commit is contained in:
commit
711fc57fe5
@ -19,7 +19,7 @@
|
|||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="19bf9795263e2ccc15d824a52ebf23c2670fa9b9"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e93780f9da8b34f370a4113abd4df9780d58e443"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2249037c79fda1d2eede2d085716577d5357e796"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2249037c79fda1d2eede2d085716577d5357e796"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
</project>
|
</project>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="19bf9795263e2ccc15d824a52ebf23c2670fa9b9"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="e93780f9da8b34f370a4113abd4df9780d58e443"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2249037c79fda1d2eede2d085716577d5357e796"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2249037c79fda1d2eede2d085716577d5357e796"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
|
||||||
@ -70,6 +70,7 @@
|
|||||||
<project name="platform/external/libnfc-nxp" path="external/libnfc-nxp" revision="8bf95c739da6c60a08b07297a1d7b996d51fd53b"/>
|
<project name="platform/external/libnfc-nxp" path="external/libnfc-nxp" revision="8bf95c739da6c60a08b07297a1d7b996d51fd53b"/>
|
||||||
<project name="platform/external/libnl-headers" path="external/libnl-headers" revision="7bd0b8345c96344746541e8f39375226bf580c41"/>
|
<project name="platform/external/libnl-headers" path="external/libnl-headers" revision="7bd0b8345c96344746541e8f39375226bf580c41"/>
|
||||||
<project name="platform/external/libogg" path="external/libogg" revision="6b0f05807a0e117bd774029a2b84e95ac1254353"/>
|
<project name="platform/external/libogg" path="external/libogg" revision="6b0f05807a0e117bd774029a2b84e95ac1254353"/>
|
||||||
|
<project name="platform/external/libpcap" path="external/libpcap" revision="7db9ecfdf0d68c5000dbbaf8d96b0ff11d98a7fd"/>
|
||||||
<project name="platform_external_libpng" path="external/libpng" remote="b2g" revision="5f020432161cfde3d66aa4879b1d216a1f093303"/>
|
<project name="platform_external_libpng" path="external/libpng" remote="b2g" revision="5f020432161cfde3d66aa4879b1d216a1f093303"/>
|
||||||
<project name="platform/external/libselinux" path="external/libselinux" revision="fafd3f40d5185ddb99a47fe951a60c8c5d9eece2"/>
|
<project name="platform/external/libselinux" path="external/libselinux" revision="fafd3f40d5185ddb99a47fe951a60c8c5d9eece2"/>
|
||||||
<project name="platform/external/libsepol" path="external/libsepol" revision="986b9a21757ebbd9c18a00a8b09d495b9681d6e1"/>
|
<project name="platform/external/libsepol" path="external/libsepol" revision="986b9a21757ebbd9c18a00a8b09d495b9681d6e1"/>
|
||||||
@ -92,6 +93,7 @@
|
|||||||
<project name="platform/external/strace" path="external/strace" revision="1714f1f9abf2237901b4c5d80955a3556d355c60"/>
|
<project name="platform/external/strace" path="external/strace" revision="1714f1f9abf2237901b4c5d80955a3556d355c60"/>
|
||||||
<project name="platform/external/svox" path="external/svox" revision="65c756ac5edc78493d8597b865362015c1a6b6e9"/>
|
<project name="platform/external/svox" path="external/svox" revision="65c756ac5edc78493d8597b865362015c1a6b6e9"/>
|
||||||
<project name="platform/external/tagsoup" path="external/tagsoup" revision="6fdb4dfecc14d4634479bb544b0badf1eb58df92"/>
|
<project name="platform/external/tagsoup" path="external/tagsoup" revision="6fdb4dfecc14d4634479bb544b0badf1eb58df92"/>
|
||||||
|
<project name="platform/external/tcpdump" path="external/tcpdump" revision="75a7b633f60026f8d371e18e9127015990656b12"/>
|
||||||
<project name="platform/external/tinyalsa" path="external/tinyalsa" revision="a6e1da53a63cc2b676ee75a97a5953531fafa27a"/>
|
<project name="platform/external/tinyalsa" path="external/tinyalsa" revision="a6e1da53a63cc2b676ee75a97a5953531fafa27a"/>
|
||||||
<project name="platform/external/tinyxml" path="external/tinyxml" revision="ed2c5fc8937f8225ec6fd94ebcabac65621a2dc8"/>
|
<project name="platform/external/tinyxml" path="external/tinyxml" revision="ed2c5fc8937f8225ec6fd94ebcabac65621a2dc8"/>
|
||||||
<project name="platform/external/tinyxml2" path="external/tinyxml2" revision="f5549cc02ee15888ecc31cf85b346578260975f9"/>
|
<project name="platform/external/tinyxml2" path="external/tinyxml2" revision="f5549cc02ee15888ecc31cf85b346578260975f9"/>
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
<project name="platform_build" path="build" remote="b2g" revision="999e945b85c578c503ad445c2285940f16aacdae">
|
<project name="platform_build" path="build" remote="b2g" revision="999e945b85c578c503ad445c2285940f16aacdae">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="19bf9795263e2ccc15d824a52ebf23c2670fa9b9"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="e93780f9da8b34f370a4113abd4df9780d58e443"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2249037c79fda1d2eede2d085716577d5357e796"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2249037c79fda1d2eede2d085716577d5357e796"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
@ -69,6 +69,7 @@
|
|||||||
<project name="platform/external/libnfc-nxp" path="external/libnfc-nxp" revision="06209143852be5967c67eb7675d80ea6250c6487"/>
|
<project name="platform/external/libnfc-nxp" path="external/libnfc-nxp" revision="06209143852be5967c67eb7675d80ea6250c6487"/>
|
||||||
<project name="platform/external/libnl-headers" path="external/libnl-headers" revision="35499a49e8475844a1ea4f7d17cef7c6ebb85051"/>
|
<project name="platform/external/libnl-headers" path="external/libnl-headers" revision="35499a49e8475844a1ea4f7d17cef7c6ebb85051"/>
|
||||||
<project name="platform/external/libogg" path="external/libogg" revision="b33f5501cc0ef62a776f1223ede90beacb54ffa3"/>
|
<project name="platform/external/libogg" path="external/libogg" revision="b33f5501cc0ef62a776f1223ede90beacb54ffa3"/>
|
||||||
|
<project name="platform/external/libpcap" path="external/libpcap" revision="b8abe0f4ea706357680930f86fdd6cd26bf30b31"/>
|
||||||
<project name="platform/external/libpng" path="external/libpng" revision="e79b02c09f131d26a4b95d025fe85f3e0bd87a55"/>
|
<project name="platform/external/libpng" path="external/libpng" revision="e79b02c09f131d26a4b95d025fe85f3e0bd87a55"/>
|
||||||
<project name="platform/external/libselinux" path="external/libselinux" revision="f2a93748f1974a76f1676f66049b3a29f1b4e532"/>
|
<project name="platform/external/libselinux" path="external/libselinux" revision="f2a93748f1974a76f1676f66049b3a29f1b4e532"/>
|
||||||
<project name="platform/external/libsepol" path="external/libsepol" revision="cf9b75ee1949969c6620fcbec854e67a305dbbc7"/>
|
<project name="platform/external/libsepol" path="external/libsepol" revision="cf9b75ee1949969c6620fcbec854e67a305dbbc7"/>
|
||||||
@ -91,6 +92,7 @@
|
|||||||
<project name="platform/external/strace" path="external/strace" revision="df60312a98c0cdb419d130a454bd5f3190ee6a16"/>
|
<project name="platform/external/strace" path="external/strace" revision="df60312a98c0cdb419d130a454bd5f3190ee6a16"/>
|
||||||
<project name="platform/external/svox" path="external/svox" revision="1cc8a28a4089b0a2041c4077e917e5964dd10e4d"/>
|
<project name="platform/external/svox" path="external/svox" revision="1cc8a28a4089b0a2041c4077e917e5964dd10e4d"/>
|
||||||
<project name="platform/external/tagsoup" path="external/tagsoup" revision="ab78ce1be9f67f787282796f8accc7d50a2fb051"/>
|
<project name="platform/external/tagsoup" path="external/tagsoup" revision="ab78ce1be9f67f787282796f8accc7d50a2fb051"/>
|
||||||
|
<project name="platform/external/tcpdump" path="external/tcpdump" revision="c76d00f367d39014256d478aa917f57f6424d455"/>
|
||||||
<project name="platform/external/tinyalsa" path="external/tinyalsa" revision="4b3f554e49d94a41276dddcc1a11fa0442c2044b"/>
|
<project name="platform/external/tinyalsa" path="external/tinyalsa" revision="4b3f554e49d94a41276dddcc1a11fa0442c2044b"/>
|
||||||
<project name="platform/external/tinycompress" path="external/tinycompress" revision="4ef0577bf643bc5ae8168015d2a0aa437d165564"/>
|
<project name="platform/external/tinycompress" path="external/tinycompress" revision="4ef0577bf643bc5ae8168015d2a0aa437d165564"/>
|
||||||
<project name="platform/external/tinyxml" path="external/tinyxml" revision="2a1ec6642c9f7672d9681ebb3f3a313fd07076ce"/>
|
<project name="platform/external/tinyxml" path="external/tinyxml" revision="2a1ec6642c9f7672d9681ebb3f3a313fd07076ce"/>
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="19bf9795263e2ccc15d824a52ebf23c2670fa9b9"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e93780f9da8b34f370a4113abd4df9780d58e443"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2249037c79fda1d2eede2d085716577d5357e796"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2249037c79fda1d2eede2d085716577d5357e796"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
</project>
|
</project>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="19bf9795263e2ccc15d824a52ebf23c2670fa9b9"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="e93780f9da8b34f370a4113abd4df9780d58e443"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2249037c79fda1d2eede2d085716577d5357e796"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2249037c79fda1d2eede2d085716577d5357e796"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
|
||||||
@ -68,6 +68,7 @@
|
|||||||
<project name="platform/external/libnfc-nxp" path="external/libnfc-nxp" revision="42f5b41d22bbbad1b16b9cd3aba0512a399f32a6"/>
|
<project name="platform/external/libnfc-nxp" path="external/libnfc-nxp" revision="42f5b41d22bbbad1b16b9cd3aba0512a399f32a6"/>
|
||||||
<project name="platform/external/libnl-headers" path="external/libnl-headers" revision="6ccf7349d61f73ac26a0675d735d903ab919c658"/>
|
<project name="platform/external/libnl-headers" path="external/libnl-headers" revision="6ccf7349d61f73ac26a0675d735d903ab919c658"/>
|
||||||
<project name="platform/external/libogg" path="external/libogg" revision="ec0b24fb1468abe37be4164a6feb16568e036bde"/>
|
<project name="platform/external/libogg" path="external/libogg" revision="ec0b24fb1468abe37be4164a6feb16568e036bde"/>
|
||||||
|
<project name="platform/external/libpcap" path="external/libpcap" revision="3a7bce5dda6a8db92c9248846d0255e68c3a5b2a"/>
|
||||||
<project name="platform/external/libpng" path="external/libpng" revision="8c58193420963d07311bb616b98a9d50a072696b"/>
|
<project name="platform/external/libpng" path="external/libpng" revision="8c58193420963d07311bb616b98a9d50a072696b"/>
|
||||||
<project name="platform/external/libselinux" path="external/libselinux" revision="f8bdc31c321543a22a7aa3fa8eb42f3d398811a2"/>
|
<project name="platform/external/libselinux" path="external/libselinux" revision="f8bdc31c321543a22a7aa3fa8eb42f3d398811a2"/>
|
||||||
<project name="platform/external/libsepol" path="external/libsepol" revision="b0e0162a246f2c051427154909c0ecd694cc4805"/>
|
<project name="platform/external/libsepol" path="external/libsepol" revision="b0e0162a246f2c051427154909c0ecd694cc4805"/>
|
||||||
@ -90,6 +91,7 @@
|
|||||||
<project name="platform/external/strace" path="external/strace" revision="1a4e05d53dec658a061acb9869cb1eb1342cd09d"/>
|
<project name="platform/external/strace" path="external/strace" revision="1a4e05d53dec658a061acb9869cb1eb1342cd09d"/>
|
||||||
<project name="platform/external/svox" path="external/svox" revision="843824a45e0839947049fdaf5c5be278ab0e09b1"/>
|
<project name="platform/external/svox" path="external/svox" revision="843824a45e0839947049fdaf5c5be278ab0e09b1"/>
|
||||||
<project name="platform/external/tagsoup" path="external/tagsoup" revision="68c2ec9e0acdb3214b7fb91dbab8c9fab8736817"/>
|
<project name="platform/external/tagsoup" path="external/tagsoup" revision="68c2ec9e0acdb3214b7fb91dbab8c9fab8736817"/>
|
||||||
|
<project name="platform/external/tcpdump" path="external/tcpdump" revision="b3aacfd59332c1a5dead9975e60c6fa8cf6e6bee"/>
|
||||||
<project name="platform/external/tinyalsa" path="external/tinyalsa" revision="42fc2d393c868d5db609e39551d64f1e60fefa0e"/>
|
<project name="platform/external/tinyalsa" path="external/tinyalsa" revision="42fc2d393c868d5db609e39551d64f1e60fefa0e"/>
|
||||||
<project name="platform/external/tinyxml" path="external/tinyxml" revision="494e448824844d866e805831d1d5f5acb654065c"/>
|
<project name="platform/external/tinyxml" path="external/tinyxml" revision="494e448824844d866e805831d1d5f5acb654065c"/>
|
||||||
<project name="platform/external/tinyxml2" path="external/tinyxml2" revision="c74b546f5af36968ffa56d7fd4529f4273b96f48"/>
|
<project name="platform/external/tinyxml2" path="external/tinyxml2" revision="c74b546f5af36968ffa56d7fd4529f4273b96f48"/>
|
||||||
@ -119,7 +121,7 @@
|
|||||||
<default remote="caf" revision="jb_3.2" sync-j="4"/>
|
<default remote="caf" revision="jb_3.2" sync-j="4"/>
|
||||||
<!-- Flame specific things -->
|
<!-- Flame specific things -->
|
||||||
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="e8a318f7690092e639ba88891606f4183e846d3f"/>
|
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="e8a318f7690092e639ba88891606f4183e846d3f"/>
|
||||||
<project name="device/qcom/common" path="device/qcom/common" revision="34ed8345250bb97262d70a052217a92e83444ede"/>
|
<project name="device/qcom/common" path="device/qcom/common" revision="878804e0becfe5635bb8ccbf2671333d546c6fb6"/>
|
||||||
<project name="device-flame" path="device/t2m/flame" remote="b2g" revision="d7e5ed0a081a39419932b8b9fdefc9b2d903850d"/>
|
<project name="device-flame" path="device/t2m/flame" remote="b2g" revision="d7e5ed0a081a39419932b8b9fdefc9b2d903850d"/>
|
||||||
<project name="codeaurora_kernel_msm" path="kernel" remote="b2g" revision="30d40a5636ff28a554f1d8e9d975bfd04c2463d3"/>
|
<project name="codeaurora_kernel_msm" path="kernel" remote="b2g" revision="30d40a5636ff28a554f1d8e9d975bfd04c2463d3"/>
|
||||||
<project name="kernel_lk" path="bootable/bootloader/lk" remote="b2g" revision="2b1d8b5b7a760230f4c94c02e733e3929f44253a"/>
|
<project name="kernel_lk" path="bootable/bootloader/lk" remote="b2g" revision="2b1d8b5b7a760230f4c94c02e733e3929f44253a"/>
|
||||||
@ -131,8 +133,8 @@
|
|||||||
<project name="platform_external_libnfc-nci" path="external/libnfc-nci" remote="t2m" revision="4186bdecb4dae911b39a8202252cc2310d91b0be"/>
|
<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/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="320b05a5761eb2a4816f7529c91ea49422979b55"/>
|
||||||
<project name="platform/frameworks/av" path="frameworks/av" revision="0f7829661cd7125de9dc2c90eca2fa1dbc68dfbf"/>
|
<project name="platform/frameworks/av" path="frameworks/av" revision="0f7829661cd7125de9dc2c90eca2fa1dbc68dfbf"/>
|
||||||
<project name="platform/frameworks/base" path="frameworks/base" revision="228d9f4189c42a11a65946420e836faa54073291"/>
|
<project name="platform/frameworks/base" path="frameworks/base" revision="051b29984ff0c23bc6bb31a36495dd1879d036d3"/>
|
||||||
<project name="platform/frameworks/native" path="frameworks/native" revision="be9db09a9889fa0dcf6539f39598c11fb2a3be44"/>
|
<project name="platform/frameworks/native" path="frameworks/native" revision="268d569074237b53617db8211400d4e3c947ae73"/>
|
||||||
<project name="platform/hardware/libhardware" path="hardware/libhardware" revision="484802559ed106bac4811bd01c024ca64f741e60"/>
|
<project name="platform/hardware/libhardware" path="hardware/libhardware" revision="484802559ed106bac4811bd01c024ca64f741e60"/>
|
||||||
<project name="platform/hardware/qcom/audio" path="hardware/qcom/audio" revision="de4ade568b273781416638fbbce13ff31b636ada"/>
|
<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/camera" path="hardware/qcom/camera" revision="5e110615212302c5d798a3c223dcee458817651c"/>
|
||||||
@ -142,7 +144,7 @@
|
|||||||
<project name="platform/hardware/qcom/wlan" path="hardware/qcom/wlan" revision="2208fa3537ace873b8f9ec2355055761c79dfd5f"/>
|
<project name="platform/hardware/qcom/wlan" path="hardware/qcom/wlan" revision="2208fa3537ace873b8f9ec2355055761c79dfd5f"/>
|
||||||
<project name="platform/hardware/ril" path="hardware/ril" revision="c4e2ac95907a5519a0e09f01a0d8e27fec101af0"/>
|
<project name="platform/hardware/ril" path="hardware/ril" revision="c4e2ac95907a5519a0e09f01a0d8e27fec101af0"/>
|
||||||
<project name="platform/system/bluetooth" path="system/bluetooth" revision="e1eb226fa3ad3874ea7b63c56a9dc7012d7ff3c2"/>
|
<project name="platform/system/bluetooth" path="system/bluetooth" revision="e1eb226fa3ad3874ea7b63c56a9dc7012d7ff3c2"/>
|
||||||
<project name="platform/system/core" path="system/core" revision="bbf7212289fc8311e43f9d11e10788e310d36a08"/>
|
<project name="platform/system/core" path="system/core" revision="b33c9a7b8eefbeaf480f0b8f9af2c6a8a35b0aee"/>
|
||||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="b6f025acd8ead1c3531e1ad62e70849161ed9340"/>
|
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="b6f025acd8ead1c3531e1ad62e70849161ed9340"/>
|
||||||
<project name="platform/system/qcom" path="system/qcom" revision="1cdab258b15258b7f9657da70e6f06ebd5a2fc25"/>
|
<project name="platform/system/qcom" path="system/qcom" revision="1cdab258b15258b7f9657da70e6f06ebd5a2fc25"/>
|
||||||
<project name="platform/vendor/qcom/msm8610" path="device/qcom/msm8610" revision="4ae5df252123591d5b941191790e7abed1bce5a4"/>
|
<project name="platform/vendor/qcom/msm8610" path="device/qcom/msm8610" revision="4ae5df252123591d5b941191790e7abed1bce5a4"/>
|
||||||
|
@ -4,6 +4,6 @@
|
|||||||
"remote": "",
|
"remote": "",
|
||||||
"branch": ""
|
"branch": ""
|
||||||
},
|
},
|
||||||
"revision": "0472c590f5c346190da0bfabe7818e0a9f18c2cb",
|
"revision": "f47342e0a4e802b69ec1da8b641f24ae35016d9d",
|
||||||
"repo_path": "/integration/gaia-central"
|
"repo_path": "/integration/gaia-central"
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="19bf9795263e2ccc15d824a52ebf23c2670fa9b9"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e93780f9da8b34f370a4113abd4df9780d58e443"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2249037c79fda1d2eede2d085716577d5357e796"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2249037c79fda1d2eede2d085716577d5357e796"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="19bf9795263e2ccc15d824a52ebf23c2670fa9b9"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e93780f9da8b34f370a4113abd4df9780d58e443"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2249037c79fda1d2eede2d085716577d5357e796"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2249037c79fda1d2eede2d085716577d5357e796"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
</project>
|
</project>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="19bf9795263e2ccc15d824a52ebf23c2670fa9b9"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="e93780f9da8b34f370a4113abd4df9780d58e443"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2249037c79fda1d2eede2d085716577d5357e796"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2249037c79fda1d2eede2d085716577d5357e796"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
|
||||||
@ -70,6 +70,7 @@
|
|||||||
<project name="platform/external/libnfc-nxp" path="external/libnfc-nxp" revision="8bf95c739da6c60a08b07297a1d7b996d51fd53b"/>
|
<project name="platform/external/libnfc-nxp" path="external/libnfc-nxp" revision="8bf95c739da6c60a08b07297a1d7b996d51fd53b"/>
|
||||||
<project name="platform/external/libnl-headers" path="external/libnl-headers" revision="7bd0b8345c96344746541e8f39375226bf580c41"/>
|
<project name="platform/external/libnl-headers" path="external/libnl-headers" revision="7bd0b8345c96344746541e8f39375226bf580c41"/>
|
||||||
<project name="platform/external/libogg" path="external/libogg" revision="6b0f05807a0e117bd774029a2b84e95ac1254353"/>
|
<project name="platform/external/libogg" path="external/libogg" revision="6b0f05807a0e117bd774029a2b84e95ac1254353"/>
|
||||||
|
<project name="platform/external/libpcap" path="external/libpcap" revision="7db9ecfdf0d68c5000dbbaf8d96b0ff11d98a7fd"/>
|
||||||
<project name="platform_external_libpng" path="external/libpng" remote="b2g" revision="5f020432161cfde3d66aa4879b1d216a1f093303"/>
|
<project name="platform_external_libpng" path="external/libpng" remote="b2g" revision="5f020432161cfde3d66aa4879b1d216a1f093303"/>
|
||||||
<project name="platform/external/libselinux" path="external/libselinux" revision="fafd3f40d5185ddb99a47fe951a60c8c5d9eece2"/>
|
<project name="platform/external/libselinux" path="external/libselinux" revision="fafd3f40d5185ddb99a47fe951a60c8c5d9eece2"/>
|
||||||
<project name="platform/external/libsepol" path="external/libsepol" revision="986b9a21757ebbd9c18a00a8b09d495b9681d6e1"/>
|
<project name="platform/external/libsepol" path="external/libsepol" revision="986b9a21757ebbd9c18a00a8b09d495b9681d6e1"/>
|
||||||
@ -92,6 +93,7 @@
|
|||||||
<project name="platform/external/strace" path="external/strace" revision="1714f1f9abf2237901b4c5d80955a3556d355c60"/>
|
<project name="platform/external/strace" path="external/strace" revision="1714f1f9abf2237901b4c5d80955a3556d355c60"/>
|
||||||
<project name="platform/external/svox" path="external/svox" revision="65c756ac5edc78493d8597b865362015c1a6b6e9"/>
|
<project name="platform/external/svox" path="external/svox" revision="65c756ac5edc78493d8597b865362015c1a6b6e9"/>
|
||||||
<project name="platform/external/tagsoup" path="external/tagsoup" revision="6fdb4dfecc14d4634479bb544b0badf1eb58df92"/>
|
<project name="platform/external/tagsoup" path="external/tagsoup" revision="6fdb4dfecc14d4634479bb544b0badf1eb58df92"/>
|
||||||
|
<project name="platform/external/tcpdump" path="external/tcpdump" revision="75a7b633f60026f8d371e18e9127015990656b12"/>
|
||||||
<project name="platform/external/tinyalsa" path="external/tinyalsa" revision="a6e1da53a63cc2b676ee75a97a5953531fafa27a"/>
|
<project name="platform/external/tinyalsa" path="external/tinyalsa" revision="a6e1da53a63cc2b676ee75a97a5953531fafa27a"/>
|
||||||
<project name="platform/external/tinyxml" path="external/tinyxml" revision="ed2c5fc8937f8225ec6fd94ebcabac65621a2dc8"/>
|
<project name="platform/external/tinyxml" path="external/tinyxml" revision="ed2c5fc8937f8225ec6fd94ebcabac65621a2dc8"/>
|
||||||
<project name="platform/external/tinyxml2" path="external/tinyxml2" revision="f5549cc02ee15888ecc31cf85b346578260975f9"/>
|
<project name="platform/external/tinyxml2" path="external/tinyxml2" revision="f5549cc02ee15888ecc31cf85b346578260975f9"/>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="19bf9795263e2ccc15d824a52ebf23c2670fa9b9"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e93780f9da8b34f370a4113abd4df9780d58e443"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2249037c79fda1d2eede2d085716577d5357e796"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2249037c79fda1d2eede2d085716577d5357e796"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
|
@ -48,8 +48,6 @@
|
|||||||
<menuitem value="ar" label="&font.langGroup.arabic;"/>
|
<menuitem value="ar" label="&font.langGroup.arabic;"/>
|
||||||
<menuitem value="x-armn" label="&font.langGroup.armenian;"/>
|
<menuitem value="x-armn" label="&font.langGroup.armenian;"/>
|
||||||
<menuitem value="x-beng" label="&font.langGroup.bengali;"/>
|
<menuitem value="x-beng" label="&font.langGroup.bengali;"/>
|
||||||
<menuitem value="x-baltic" label="&font.langGroup.baltic;"/>
|
|
||||||
<menuitem value="x-central-euro" label="&font.langGroup.latin2;"/>
|
|
||||||
<menuitem value="zh-CN" label="&font.langGroup.simpl-chinese;"/>
|
<menuitem value="zh-CN" label="&font.langGroup.simpl-chinese;"/>
|
||||||
<menuitem value="zh-HK" label="&font.langGroup.trad-chinese-hk;"/>
|
<menuitem value="zh-HK" label="&font.langGroup.trad-chinese-hk;"/>
|
||||||
<menuitem value="zh-TW" label="&font.langGroup.trad-chinese;"/>
|
<menuitem value="zh-TW" label="&font.langGroup.trad-chinese;"/>
|
||||||
@ -65,6 +63,7 @@
|
|||||||
<menuitem value="x-knda" label="&font.langGroup.kannada;"/>
|
<menuitem value="x-knda" label="&font.langGroup.kannada;"/>
|
||||||
<menuitem value="x-khmr" label="&font.langGroup.khmer;"/>
|
<menuitem value="x-khmr" label="&font.langGroup.khmer;"/>
|
||||||
<menuitem value="ko" label="&font.langGroup.korean;"/>
|
<menuitem value="ko" label="&font.langGroup.korean;"/>
|
||||||
|
<menuitem value="x-western" label="&font.langGroup.latin;"/>
|
||||||
<menuitem value="x-mlym" label="&font.langGroup.malayalam;"/>
|
<menuitem value="x-mlym" label="&font.langGroup.malayalam;"/>
|
||||||
<menuitem value="x-orya" label="&font.langGroup.oriya;"/>
|
<menuitem value="x-orya" label="&font.langGroup.oriya;"/>
|
||||||
<menuitem value="x-sinh" label="&font.langGroup.sinhala;"/>
|
<menuitem value="x-sinh" label="&font.langGroup.sinhala;"/>
|
||||||
@ -72,10 +71,8 @@
|
|||||||
<menuitem value="x-telu" label="&font.langGroup.telugu;"/>
|
<menuitem value="x-telu" label="&font.langGroup.telugu;"/>
|
||||||
<menuitem value="th" label="&font.langGroup.thai;"/>
|
<menuitem value="th" label="&font.langGroup.thai;"/>
|
||||||
<menuitem value="x-tibt" label="&font.langGroup.tibetan;"/>
|
<menuitem value="x-tibt" label="&font.langGroup.tibetan;"/>
|
||||||
<menuitem value="tr" label="&font.langGroup.turkish;"/>
|
|
||||||
<menuitem value="x-cans" label="&font.langGroup.canadian;"/>
|
<menuitem value="x-cans" label="&font.langGroup.canadian;"/>
|
||||||
<menuitem value="x-western" label="&font.langGroup.latin1;"/>
|
<menuitem value="x-unicode" label="&font.langGroup.other;"/>
|
||||||
<menuitem value="x-unicode" label="&font.langGroup.unicode;"/>
|
|
||||||
</menupopup>
|
</menupopup>
|
||||||
</menulist>
|
</menulist>
|
||||||
</caption>
|
</caption>
|
||||||
|
@ -21,18 +21,17 @@
|
|||||||
<!ENTITY monospace.label "Monospace:">
|
<!ENTITY monospace.label "Monospace:">
|
||||||
<!ENTITY monospace.accesskey "M">
|
<!ENTITY monospace.accesskey "M">
|
||||||
|
|
||||||
<!ENTITY font.langGroup.latin1 "Western">
|
<!-- LOCALIZATION NOTE (font.langGroup.latin) :
|
||||||
<!ENTITY font.langGroup.latin2 "Central European">
|
Translate "Latin" as the name of Latin (Roman) script, not as the name of the Latin language. -->
|
||||||
|
<!ENTITY font.langGroup.latin "Latin">
|
||||||
<!ENTITY font.langGroup.japanese "Japanese">
|
<!ENTITY font.langGroup.japanese "Japanese">
|
||||||
<!ENTITY font.langGroup.trad-chinese "Traditional Chinese (Taiwan)">
|
<!ENTITY font.langGroup.trad-chinese "Traditional Chinese (Taiwan)">
|
||||||
<!ENTITY font.langGroup.simpl-chinese "Simplified Chinese">
|
<!ENTITY font.langGroup.simpl-chinese "Simplified Chinese">
|
||||||
<!ENTITY font.langGroup.trad-chinese-hk "Traditional Chinese (Hong Kong)">
|
<!ENTITY font.langGroup.trad-chinese-hk "Traditional Chinese (Hong Kong)">
|
||||||
<!ENTITY font.langGroup.korean "Korean">
|
<!ENTITY font.langGroup.korean "Korean">
|
||||||
<!ENTITY font.langGroup.cyrillic "Cyrillic">
|
<!ENTITY font.langGroup.cyrillic "Cyrillic">
|
||||||
<!ENTITY font.langGroup.baltic "Baltic">
|
|
||||||
<!ENTITY font.langGroup.el "Greek">
|
<!ENTITY font.langGroup.el "Greek">
|
||||||
<!ENTITY font.langGroup.turkish "Turkish">
|
<!ENTITY font.langGroup.other "Other Writing Systems">
|
||||||
<!ENTITY font.langGroup.unicode "Other Languages">
|
|
||||||
<!ENTITY font.langGroup.thai "Thai">
|
<!ENTITY font.langGroup.thai "Thai">
|
||||||
<!ENTITY font.langGroup.hebrew "Hebrew">
|
<!ENTITY font.langGroup.hebrew "Hebrew">
|
||||||
<!ENTITY font.langGroup.arabic "Arabic">
|
<!ENTITY font.langGroup.arabic "Arabic">
|
||||||
|
23
configure.in
23
configure.in
@ -3843,6 +3843,7 @@ MOZ_PAY=
|
|||||||
MOZ_AUDIO_CHANNEL_MANAGER=
|
MOZ_AUDIO_CHANNEL_MANAGER=
|
||||||
NSS_NO_LIBPKIX=
|
NSS_NO_LIBPKIX=
|
||||||
MOZ_CONTENT_SANDBOX=
|
MOZ_CONTENT_SANDBOX=
|
||||||
|
MOZ_GMP_SANDBOX=
|
||||||
JSGC_USE_EXACT_ROOTING=1
|
JSGC_USE_EXACT_ROOTING=1
|
||||||
JSGC_GENERATIONAL=
|
JSGC_GENERATIONAL=
|
||||||
|
|
||||||
@ -6394,6 +6395,28 @@ fi
|
|||||||
|
|
||||||
AC_SUBST(MOZ_CONTENT_SANDBOX)
|
AC_SUBST(MOZ_CONTENT_SANDBOX)
|
||||||
|
|
||||||
|
dnl ========================================================
|
||||||
|
dnl = Gecko Media Plugin sandboxing
|
||||||
|
dnl ========================================================
|
||||||
|
case $OS_TARGET in
|
||||||
|
WINNT)
|
||||||
|
MOZ_GMP_SANDBOX=1
|
||||||
|
;;
|
||||||
|
Linux)
|
||||||
|
case $CPU_ARCH in
|
||||||
|
x86_64|x86)
|
||||||
|
MOZ_GMP_SANDBOX=1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if test -n "$MOZ_GMP_SANDBOX"; then
|
||||||
|
AC_DEFINE(MOZ_GMP_SANDBOX)
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_SUBST(MOZ_GMP_SANDBOX)
|
||||||
|
|
||||||
dnl ========================================================
|
dnl ========================================================
|
||||||
dnl =
|
dnl =
|
||||||
dnl = Module specific options
|
dnl = Module specific options
|
||||||
|
@ -2170,6 +2170,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
static bool IsContentInsertionPoint(const nsIContent* aContent);
|
static bool IsContentInsertionPoint(const nsIContent* aContent);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the children of the provided content are
|
||||||
|
* nodes that are distributed to Shadow DOM insertion points.
|
||||||
|
*/
|
||||||
|
static bool HasDistributedChildren(nsIContent* aContent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether a given header is forbidden for an XHR or fetch
|
* Returns whether a given header is forbidden for an XHR or fetch
|
||||||
* request.
|
* request.
|
||||||
|
@ -152,21 +152,23 @@ nsIContent::FindFirstNonChromeOnlyAccessContent() const
|
|||||||
nsIContent*
|
nsIContent*
|
||||||
nsIContent::GetFlattenedTreeParent() const
|
nsIContent::GetFlattenedTreeParent() const
|
||||||
{
|
{
|
||||||
nsIContent* parent = nullptr;
|
nsIContent* parent = GetParent();
|
||||||
|
|
||||||
|
if (nsContentUtils::HasDistributedChildren(parent)) {
|
||||||
|
// This node is distributed to insertion points, thus we
|
||||||
|
// need to consult the destination insertion points list to
|
||||||
|
// figure out where this node was inserted in the flattened tree.
|
||||||
|
// It may be the case that |parent| distributes its children
|
||||||
|
// but the child does not match any insertion points, thus
|
||||||
|
// the flattened tree parent is nullptr.
|
||||||
nsTArray<nsIContent*>* destInsertionPoints = GetExistingDestInsertionPoints();
|
nsTArray<nsIContent*>* destInsertionPoints = GetExistingDestInsertionPoints();
|
||||||
if (destInsertionPoints && !destInsertionPoints->IsEmpty()) {
|
parent = destInsertionPoints && !destInsertionPoints->IsEmpty() ?
|
||||||
// This node was distributed into an insertion point. The last node in
|
destInsertionPoints->LastElement()->GetParent() : nullptr;
|
||||||
// the list of destination insertion insertion points is where this node
|
|
||||||
// appears in the composed tree (see Shadow DOM spec).
|
|
||||||
nsIContent* lastInsertionPoint = destInsertionPoints->LastElement();
|
|
||||||
parent = lastInsertionPoint->GetParent();
|
|
||||||
} else if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
|
} else if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
|
||||||
parent = GetXBLInsertionParent();
|
nsIContent* insertionParent = GetXBLInsertionParent();
|
||||||
|
if (insertionParent) {
|
||||||
|
parent = insertionParent;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!parent) {
|
|
||||||
parent = GetParent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shadow roots never shows up in the flattened tree. Return the host
|
// Shadow roots never shows up in the flattened tree. Return the host
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
#include "mozilla/dom/HTMLMediaElement.h"
|
#include "mozilla/dom/HTMLMediaElement.h"
|
||||||
#include "mozilla/dom/HTMLTemplateElement.h"
|
#include "mozilla/dom/HTMLTemplateElement.h"
|
||||||
#include "mozilla/dom/HTMLContentElement.h"
|
#include "mozilla/dom/HTMLContentElement.h"
|
||||||
|
#include "mozilla/dom/HTMLShadowElement.h"
|
||||||
#include "mozilla/dom/ScriptSettings.h"
|
#include "mozilla/dom/ScriptSettings.h"
|
||||||
#include "mozilla/dom/TextDecoder.h"
|
#include "mozilla/dom/TextDecoder.h"
|
||||||
#include "mozilla/dom/TouchEvent.h"
|
#include "mozilla/dom/TouchEvent.h"
|
||||||
@ -6874,6 +6875,45 @@ nsContentUtils::IsContentInsertionPoint(const nsIContent* aContent)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
bool
|
||||||
|
nsContentUtils::HasDistributedChildren(nsIContent* aContent)
|
||||||
|
{
|
||||||
|
if (!aContent) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aContent->GetShadowRoot()) {
|
||||||
|
// Children of a shadow root host are distributed
|
||||||
|
// to content insertion points in the shadow root.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShadowRoot* shadow = ShadowRoot::FromNode(aContent);
|
||||||
|
if (shadow) {
|
||||||
|
// Children of a shadow root are distributed to
|
||||||
|
// the shadow insertion point of the younger shadow root.
|
||||||
|
return shadow->GetYoungerShadow();
|
||||||
|
}
|
||||||
|
|
||||||
|
HTMLShadowElement* shadowEl = HTMLShadowElement::FromContent(aContent);
|
||||||
|
if (shadowEl && shadowEl->IsInsertionPoint()) {
|
||||||
|
// Children of a shadow insertion points are distributed
|
||||||
|
// to the insertion points in the older shadow root.
|
||||||
|
return shadow->GetOlderShadow();
|
||||||
|
}
|
||||||
|
|
||||||
|
HTMLContentElement* contentEl = HTMLContentElement::FromContent(aContent);
|
||||||
|
if (contentEl && contentEl->IsInsertionPoint()) {
|
||||||
|
// Children of a content insertion point are distributed to the
|
||||||
|
// content insertion point if the content insertion point does
|
||||||
|
// not match any nodes (fallback content).
|
||||||
|
return contentEl->MatchedNodes().IsEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
bool
|
bool
|
||||||
nsContentUtils::IsForbiddenRequestHeader(const nsACString& aHeader)
|
nsContentUtils::IsForbiddenRequestHeader(const nsACString& aHeader)
|
||||||
|
@ -712,6 +712,7 @@ GK_ATOM(ondischargingtimechange, "ondischargingtimechange")
|
|||||||
GK_ATOM(ondisconnected, "ondisconnected")
|
GK_ATOM(ondisconnected, "ondisconnected")
|
||||||
GK_ATOM(ondisconnecting, "ondisconnecting")
|
GK_ATOM(ondisconnecting, "ondisconnecting")
|
||||||
GK_ATOM(ondiscoverystatechanged, "ondiscoverystatechanged")
|
GK_ATOM(ondiscoverystatechanged, "ondiscoverystatechanged")
|
||||||
|
GK_ATOM(ondisplaypasskeyreq, "ondisplaypasskeyreq")
|
||||||
GK_ATOM(ondownloading, "ondownloading")
|
GK_ATOM(ondownloading, "ondownloading")
|
||||||
GK_ATOM(onDOMActivate, "onDOMActivate")
|
GK_ATOM(onDOMActivate, "onDOMActivate")
|
||||||
GK_ATOM(onDOMAttrModified, "onDOMAttrModified")
|
GK_ATOM(onDOMAttrModified, "onDOMAttrModified")
|
||||||
@ -735,6 +736,7 @@ GK_ATOM(ondragover, "ondragover")
|
|||||||
GK_ATOM(ondragstart, "ondragstart")
|
GK_ATOM(ondragstart, "ondragstart")
|
||||||
GK_ATOM(ondrop, "ondrop")
|
GK_ATOM(ondrop, "ondrop")
|
||||||
GK_ATOM(onenabled, "onenabled")
|
GK_ATOM(onenabled, "onenabled")
|
||||||
|
GK_ATOM(onenterpincodereq, "onenterpincodereq")
|
||||||
GK_ATOM(onemergencycbmodechange, "onemergencycbmodechange")
|
GK_ATOM(onemergencycbmodechange, "onemergencycbmodechange")
|
||||||
GK_ATOM(onerror, "onerror")
|
GK_ATOM(onerror, "onerror")
|
||||||
GK_ATOM(onevicted, "onevicted")
|
GK_ATOM(onevicted, "onevicted")
|
||||||
@ -798,6 +800,8 @@ GK_ATOM(onpagehide, "onpagehide")
|
|||||||
GK_ATOM(onpageshow, "onpageshow")
|
GK_ATOM(onpageshow, "onpageshow")
|
||||||
GK_ATOM(onpaint, "onpaint")
|
GK_ATOM(onpaint, "onpaint")
|
||||||
GK_ATOM(onpairedstatuschanged, "onpairedstatuschanged")
|
GK_ATOM(onpairedstatuschanged, "onpairedstatuschanged")
|
||||||
|
GK_ATOM(onpairingconfirmationreq, "onpairingconfirmationreq")
|
||||||
|
GK_ATOM(onpairingconsentreq, "onpairingconsentreq")
|
||||||
GK_ATOM(onpaste, "onpaste")
|
GK_ATOM(onpaste, "onpaste")
|
||||||
GK_ATOM(onpendingchange, "onpendingchange")
|
GK_ATOM(onpendingchange, "onpendingchange")
|
||||||
GK_ATOM(onpopuphidden, "onpopuphidden")
|
GK_ATOM(onpopuphidden, "onpopuphidden")
|
||||||
@ -2024,7 +2028,6 @@ GK_ATOM(zh_tw, "zh-tw")
|
|||||||
GK_ATOM(x_cyrillic, "x-cyrillic")
|
GK_ATOM(x_cyrillic, "x-cyrillic")
|
||||||
GK_ATOM(he, "he")
|
GK_ATOM(he, "he")
|
||||||
GK_ATOM(ar, "ar")
|
GK_ATOM(ar, "ar")
|
||||||
GK_ATOM(x_baltic, "x-baltic")
|
|
||||||
GK_ATOM(x_devanagari, "x-devanagari")
|
GK_ATOM(x_devanagari, "x-devanagari")
|
||||||
GK_ATOM(x_tamil, "x-tamil")
|
GK_ATOM(x_tamil, "x-tamil")
|
||||||
GK_ATOM(x_armn, "x-armn")
|
GK_ATOM(x_armn, "x-armn")
|
||||||
@ -2044,7 +2047,6 @@ GK_ATOM(x_tibt, "x-tibt")
|
|||||||
|
|
||||||
// used in gfxGDIFontList.h
|
// used in gfxGDIFontList.h
|
||||||
GK_ATOM(ko_xxx, "ko-xxx")
|
GK_ATOM(ko_xxx, "ko-xxx")
|
||||||
GK_ATOM(x_central_euro, "x-central-euro")
|
|
||||||
GK_ATOM(x_symbol, "x-symbol")
|
GK_ATOM(x_symbol, "x-symbol")
|
||||||
|
|
||||||
// additional languages that have special case transformations
|
// additional languages that have special case transformations
|
||||||
|
@ -21,6 +21,8 @@ class HTMLContentElement MOZ_FINAL : public nsGenericHTMLElement
|
|||||||
public:
|
public:
|
||||||
HTMLContentElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
|
HTMLContentElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
|
||||||
|
|
||||||
|
NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLContentElement, content)
|
||||||
|
|
||||||
// nsISupports
|
// nsISupports
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
|
||||||
|
@ -17,6 +17,8 @@ class HTMLShadowElement MOZ_FINAL : public nsGenericHTMLElement,
|
|||||||
public:
|
public:
|
||||||
HTMLShadowElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
|
HTMLShadowElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
|
||||||
|
|
||||||
|
NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLShadowElement, shadow)
|
||||||
|
|
||||||
// nsISupports
|
// nsISupports
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
|
||||||
|
@ -105,6 +105,7 @@ MP4Reader::MP4Reader(AbstractMediaDecoder* aDecoder)
|
|||||||
, mVideo("MP4 video decoder data", Preferences::GetUint("media.mp4-video-decode-ahead", 2))
|
, mVideo("MP4 video decoder data", Preferences::GetUint("media.mp4-video-decode-ahead", 2))
|
||||||
, mLastReportedNumDecodedFrames(0)
|
, mLastReportedNumDecodedFrames(0)
|
||||||
, mLayersBackendType(layers::LayersBackend::LAYERS_NONE)
|
, mLayersBackendType(layers::LayersBackend::LAYERS_NONE)
|
||||||
|
, mTimeRangesMonitor("MP4Reader::TimeRanges")
|
||||||
, mDemuxerInitialized(false)
|
, mDemuxerInitialized(false)
|
||||||
, mIsEncrypted(false)
|
, mIsEncrypted(false)
|
||||||
{
|
{
|
||||||
@ -705,20 +706,30 @@ MP4Reader::Seek(int64_t aTime,
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
void
|
||||||
MP4Reader::GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime)
|
MP4Reader::NotifyDataArrived(const char* aBuffer, uint32_t aLength,
|
||||||
|
int64_t aOffset)
|
||||||
{
|
{
|
||||||
nsTArray<MediaByteRange> ranges;
|
nsTArray<MediaByteRange> ranges;
|
||||||
if (NS_FAILED(mDecoder->GetResource()->GetCachedRanges(ranges))) {
|
if (NS_FAILED(mDecoder->GetResource()->GetCachedRanges(ranges))) {
|
||||||
return NS_ERROR_FAILURE;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsTArray<Interval<Microseconds>> timeRanges;
|
nsTArray<Interval<Microseconds>> timeRanges;
|
||||||
mDemuxer->ConvertByteRangesToTime(ranges, &timeRanges);
|
mDemuxer->ConvertByteRangesToTime(ranges, &timeRanges);
|
||||||
|
|
||||||
for (size_t i = 0; i < timeRanges.Length(); i++) {
|
MonitorAutoLock mon(mTimeRangesMonitor);
|
||||||
aBuffered->Add((timeRanges[i].start - aStartTime) / 1000000.0,
|
mTimeRanges = timeRanges;
|
||||||
(timeRanges[i].end - aStartTime) / 1000000.0);
|
}
|
||||||
|
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
MP4Reader::GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime)
|
||||||
|
{
|
||||||
|
MonitorAutoLock mon(mTimeRangesMonitor);
|
||||||
|
for (size_t i = 0; i < mTimeRanges.Length(); i++) {
|
||||||
|
aBuffered->Add((mTimeRanges[i].start - aStartTime) / 1000000.0,
|
||||||
|
(mTimeRanges[i].end - aStartTime) / 1000000.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -53,6 +53,9 @@ public:
|
|||||||
|
|
||||||
virtual bool IsMediaSeekable() MOZ_OVERRIDE;
|
virtual bool IsMediaSeekable() MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength,
|
||||||
|
int64_t aOffset) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual nsresult GetBuffered(dom::TimeRanges* aBuffered,
|
virtual nsresult GetBuffered(dom::TimeRanges* aBuffered,
|
||||||
int64_t aStartTime) MOZ_OVERRIDE;
|
int64_t aStartTime) MOZ_OVERRIDE;
|
||||||
|
|
||||||
@ -165,6 +168,8 @@ private:
|
|||||||
layers::LayersBackend mLayersBackendType;
|
layers::LayersBackend mLayersBackendType;
|
||||||
|
|
||||||
nsTArray<nsTArray<uint8_t>> mInitDataEncountered;
|
nsTArray<nsTArray<uint8_t>> mInitDataEncountered;
|
||||||
|
Monitor mTimeRangesMonitor;
|
||||||
|
nsTArray<mp4_demuxer::Interval<Microseconds>> mTimeRanges;
|
||||||
|
|
||||||
// True if we've read the streams' metadata.
|
// True if we've read the streams' metadata.
|
||||||
bool mDemuxerInitialized;
|
bool mDemuxerInitialized;
|
||||||
|
@ -93,9 +93,6 @@ PlatformDecoderModule::CreateCDMWrapper(CDMProxy* aProxy,
|
|||||||
if (!pdm) {
|
if (!pdm) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
NS_WARNING("CDM that decodes not yet supported!");
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new EMEDecoderModule(aProxy,
|
return new EMEDecoderModule(aProxy,
|
||||||
|
319
content/media/fmp4/eme/EMEAACDecoder.cpp
Normal file
319
content/media/fmp4/eme/EMEAACDecoder.cpp
Normal file
@ -0,0 +1,319 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
#include "EMEAACDecoder.h"
|
||||||
|
#include "mp4_demuxer/DecoderData.h"
|
||||||
|
#include "mozilla/EMELog.h"
|
||||||
|
#include "gmp-audio-host.h"
|
||||||
|
#include "gmp-audio-decode.h"
|
||||||
|
#include "gmp-audio-samples.h"
|
||||||
|
#include "GMPAudioHost.h"
|
||||||
|
#include "GMPAudioDecoderProxy.h"
|
||||||
|
#include "mozilla/CDMProxy.h"
|
||||||
|
#include "nsServiceManagerUtils.h"
|
||||||
|
#include "prsystem.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
EMEAACDecoder::EMEAACDecoder(CDMProxy* aProxy,
|
||||||
|
const AudioDecoderConfig& aConfig,
|
||||||
|
MediaTaskQueue* aTaskQueue,
|
||||||
|
MediaDataDecoderCallback* aCallback)
|
||||||
|
: mAudioRate(0)
|
||||||
|
, mAudioBytesPerSample(0)
|
||||||
|
, mAudioChannels(0)
|
||||||
|
, mMustRecaptureAudioPosition(true)
|
||||||
|
, mAudioFrameSum(0)
|
||||||
|
, mAudioFrameOffset(0)
|
||||||
|
, mStreamOffset(0)
|
||||||
|
, mProxy(aProxy)
|
||||||
|
, mGMP(nullptr)
|
||||||
|
, mConfig(aConfig)
|
||||||
|
, mTaskQueue(aTaskQueue)
|
||||||
|
, mCallback(aCallback)
|
||||||
|
, mMonitor("EMEAACDecoder")
|
||||||
|
, mFlushComplete(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
EMEAACDecoder::~EMEAACDecoder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
EMEAACDecoder::Init()
|
||||||
|
{
|
||||||
|
// Note: this runs on the decode task queue.
|
||||||
|
|
||||||
|
MOZ_ASSERT((mConfig.bits_per_sample / 8) == 2); // Demuxer guarantees this.
|
||||||
|
|
||||||
|
mMPS = do_GetService("@mozilla.org/gecko-media-plugin-service;1");
|
||||||
|
MOZ_ASSERT(mMPS);
|
||||||
|
|
||||||
|
nsresult rv = mMPS->GetThread(getter_AddRefs(mGMPThread));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
nsRefPtr<InitTask> task(new InitTask(this));
|
||||||
|
rv = mGMPThread->Dispatch(task, NS_DISPATCH_SYNC);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
NS_ENSURE_SUCCESS(task->mResult, task->mResult);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
EMEAACDecoder::Input(MP4Sample* aSample)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue.
|
||||||
|
|
||||||
|
nsRefPtr<nsIRunnable> task(new DeliverSample(this, aSample));
|
||||||
|
nsresult rv = mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
EMEAACDecoder::Flush()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue.
|
||||||
|
|
||||||
|
{
|
||||||
|
MonitorAutoLock mon(mMonitor);
|
||||||
|
mFlushComplete = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRefPtr<nsIRunnable> task;
|
||||||
|
task = NS_NewRunnableMethod(this, &EMEAACDecoder::GmpFlush);
|
||||||
|
nsresult rv = mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
{
|
||||||
|
MonitorAutoLock mon(mMonitor);
|
||||||
|
while (!mFlushComplete) {
|
||||||
|
mon.Wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
EMEAACDecoder::Drain()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue.
|
||||||
|
|
||||||
|
nsRefPtr<nsIRunnable> task;
|
||||||
|
task = NS_NewRunnableMethod(this, &EMEAACDecoder::GmpDrain);
|
||||||
|
nsresult rv = mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
EMEAACDecoder::Shutdown()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue.
|
||||||
|
|
||||||
|
nsRefPtr<nsIRunnable> task;
|
||||||
|
task = NS_NewRunnableMethod(this, &EMEAACDecoder::GmpShutdown);
|
||||||
|
nsresult rv = mGMPThread->Dispatch(task, NS_DISPATCH_SYNC);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EMEAACDecoder::Decoded(const nsTArray<int16_t>& aPCM,
|
||||||
|
uint64_t aTimeStamp)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
|
||||||
|
size_t numFrames = aPCM.Length() / mAudioChannels;
|
||||||
|
nsAutoArrayPtr<AudioDataValue> audioData(new AudioDataValue[aPCM.Length()]);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < aPCM.Length(); ++i) {
|
||||||
|
audioData[i] = AudioSampleToFloat(aPCM[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mMustRecaptureAudioPosition) {
|
||||||
|
mAudioFrameSum = 0;
|
||||||
|
auto timestamp = UsecsToFrames(aTimeStamp, mAudioRate);
|
||||||
|
if (!timestamp.isValid()) {
|
||||||
|
NS_WARNING("Invalid timestamp");
|
||||||
|
mCallback->Error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mAudioFrameOffset = timestamp.value();
|
||||||
|
MOZ_ASSERT(mAudioFrameOffset >= 0);
|
||||||
|
mMustRecaptureAudioPosition = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto timestamp = FramesToUsecs(mAudioFrameOffset + mAudioFrameSum, mAudioRate);
|
||||||
|
if (!timestamp.isValid()) {
|
||||||
|
NS_WARNING("Invalid timestamp on audio samples");
|
||||||
|
mCallback->Error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mAudioFrameSum += numFrames;
|
||||||
|
|
||||||
|
auto duration = FramesToUsecs(numFrames, mAudioRate);
|
||||||
|
if (!duration.isValid()) {
|
||||||
|
NS_WARNING("Invalid duration on audio samples");
|
||||||
|
mCallback->Error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoPtr<AudioData> audio(new AudioData(mStreamOffset,
|
||||||
|
timestamp.value(),
|
||||||
|
duration.value(),
|
||||||
|
numFrames,
|
||||||
|
audioData.forget(),
|
||||||
|
mAudioChannels));
|
||||||
|
|
||||||
|
#ifdef LOG_SAMPLE_DECODE
|
||||||
|
LOG("Decoded audio sample! timestamp=%lld duration=%lld currentLength=%u",
|
||||||
|
timestamp, duration, currentLength);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mCallback->Output(audio.forget());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EMEAACDecoder::InputDataExhausted()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
mCallback->InputExhausted();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EMEAACDecoder::DrainComplete()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
mCallback->DrainComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EMEAACDecoder::ResetComplete()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
mMustRecaptureAudioPosition = true;
|
||||||
|
{
|
||||||
|
MonitorAutoLock mon(mMonitor);
|
||||||
|
mFlushComplete = true;
|
||||||
|
mon.NotifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EMEAACDecoder::Error(GMPErr aErr)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
mCallback->Error();
|
||||||
|
GmpShutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EMEAACDecoder::Terminated()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
GmpShutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
EMEAACDecoder::GmpInit()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
|
||||||
|
nsTArray<nsCString> tags;
|
||||||
|
tags.AppendElement(NS_LITERAL_CSTRING("aac"));
|
||||||
|
tags.AppendElement(NS_ConvertUTF16toUTF8(mProxy->KeySystem()));
|
||||||
|
nsresult rv = mMPS->GetGMPAudioDecoder(&tags,
|
||||||
|
mProxy->GetOrigin(),
|
||||||
|
&mGMP);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
MOZ_ASSERT(mGMP);
|
||||||
|
|
||||||
|
mAudioRate = mConfig.samples_per_second;
|
||||||
|
mAudioBytesPerSample = mConfig.bits_per_sample / 8;
|
||||||
|
mAudioChannels = mConfig.channel_count;
|
||||||
|
|
||||||
|
nsTArray<uint8_t> extraData;
|
||||||
|
extraData.AppendElements(&mConfig.audio_specific_config[0],
|
||||||
|
mConfig.audio_specific_config.length());
|
||||||
|
|
||||||
|
mGMP->InitDecode(kGMPAudioCodecAAC,
|
||||||
|
mAudioChannels,
|
||||||
|
mConfig.bits_per_sample,
|
||||||
|
mAudioRate,
|
||||||
|
extraData,
|
||||||
|
this);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
EMEAACDecoder::GmpInput(MP4Sample* aSample)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
nsAutoPtr<MP4Sample> sample(aSample);
|
||||||
|
if (!mGMP) {
|
||||||
|
mCallback->Error();
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sample->crypto.valid) {
|
||||||
|
CDMCaps::AutoLock caps(mProxy->Capabilites());
|
||||||
|
MOZ_ASSERT(caps.CanDecryptAndDecodeAudio());
|
||||||
|
const auto& keyid = sample->crypto.key;
|
||||||
|
if (!caps.IsKeyUsable(keyid)) {
|
||||||
|
// DeliverSample assumes responsibility for deleting aSample.
|
||||||
|
nsRefPtr<nsIRunnable> task(new DeliverSample(this, sample.forget()));
|
||||||
|
caps.CallWhenKeyUsable(keyid, task, mGMPThread);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gmp::GMPAudioSamplesImpl samples(sample);
|
||||||
|
mGMP->Decode(samples);
|
||||||
|
|
||||||
|
mStreamOffset = sample->byte_offset;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EMEAACDecoder::GmpFlush()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
if (!mGMP || NS_FAILED(mGMP->Reset())) {
|
||||||
|
// Abort the flush...
|
||||||
|
MonitorAutoLock mon(mMonitor);
|
||||||
|
mFlushComplete = true;
|
||||||
|
mon.NotifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EMEAACDecoder::GmpDrain()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
if (!mGMP || NS_FAILED(mGMP->Drain())) {
|
||||||
|
mCallback->DrainComplete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EMEAACDecoder::GmpShutdown()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
if (!mGMP) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mGMP->Close();
|
||||||
|
mGMP = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mozilla
|
115
content/media/fmp4/eme/EMEAACDecoder.h
Normal file
115
content/media/fmp4/eme/EMEAACDecoder.h
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
#ifndef EMEAACDecoder_h_
|
||||||
|
#define EMEAACDecoder_h_
|
||||||
|
|
||||||
|
#include "PlatformDecoderModule.h"
|
||||||
|
#include "mp4_demuxer/DecoderData.h"
|
||||||
|
#include "mozIGeckoMediaPluginService.h"
|
||||||
|
#include "nsServiceManagerUtils.h"
|
||||||
|
#include "GMPAudioHost.h"
|
||||||
|
#include "GMPAudioDecoderProxy.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
class EMEAACDecoder : public MediaDataDecoder
|
||||||
|
, public GMPAudioDecoderProxyCallback
|
||||||
|
{
|
||||||
|
typedef mp4_demuxer::MP4Sample MP4Sample;
|
||||||
|
typedef mp4_demuxer::AudioDecoderConfig AudioDecoderConfig;
|
||||||
|
public:
|
||||||
|
EMEAACDecoder(CDMProxy* aProxy,
|
||||||
|
const AudioDecoderConfig& aConfig,
|
||||||
|
MediaTaskQueue* aTaskQueue,
|
||||||
|
MediaDataDecoderCallback* aCallback);
|
||||||
|
|
||||||
|
~EMEAACDecoder();
|
||||||
|
|
||||||
|
// MediaDataDecoder implementation.
|
||||||
|
virtual nsresult Init() MOZ_OVERRIDE;
|
||||||
|
virtual nsresult Input(MP4Sample* aSample) MOZ_OVERRIDE;
|
||||||
|
virtual nsresult Flush() MOZ_OVERRIDE;
|
||||||
|
virtual nsresult Drain() MOZ_OVERRIDE;
|
||||||
|
virtual nsresult Shutdown() MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
// GMPAudioDecoderProxyCallback implementation.
|
||||||
|
virtual void Decoded(const nsTArray<int16_t>& aPCM,
|
||||||
|
uint64_t aTimeStamp) MOZ_OVERRIDE;
|
||||||
|
virtual void InputDataExhausted() MOZ_OVERRIDE;
|
||||||
|
virtual void DrainComplete() MOZ_OVERRIDE;
|
||||||
|
virtual void ResetComplete() MOZ_OVERRIDE;
|
||||||
|
virtual void Error(GMPErr aErr) MOZ_OVERRIDE;
|
||||||
|
virtual void Terminated() MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
class DeliverSample : public nsRunnable {
|
||||||
|
public:
|
||||||
|
DeliverSample(EMEAACDecoder* aDecoder,
|
||||||
|
mp4_demuxer::MP4Sample* aSample)
|
||||||
|
: mDecoder(aDecoder)
|
||||||
|
, mSample(aSample)
|
||||||
|
{}
|
||||||
|
|
||||||
|
NS_IMETHOD Run() {
|
||||||
|
mDecoder->GmpInput(mSample.forget());
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
nsRefPtr<EMEAACDecoder> mDecoder;
|
||||||
|
nsAutoPtr<mp4_demuxer::MP4Sample> mSample;
|
||||||
|
};
|
||||||
|
|
||||||
|
class InitTask : public nsRunnable {
|
||||||
|
public:
|
||||||
|
InitTask(EMEAACDecoder* aDecoder)
|
||||||
|
: mDecoder(aDecoder)
|
||||||
|
{}
|
||||||
|
NS_IMETHOD Run() {
|
||||||
|
mResult = mDecoder->GmpInit();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
nsresult mResult;
|
||||||
|
EMEAACDecoder* mDecoder;
|
||||||
|
};
|
||||||
|
|
||||||
|
nsresult GmpInit();
|
||||||
|
nsresult GmpInput(MP4Sample* aSample);
|
||||||
|
void GmpFlush();
|
||||||
|
void GmpDrain();
|
||||||
|
void GmpShutdown();
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
bool IsOnGMPThread() {
|
||||||
|
return NS_GetCurrentThread() == mGMPThread;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint32_t mAudioRate;
|
||||||
|
uint32_t mAudioBytesPerSample;
|
||||||
|
uint32_t mAudioChannels;
|
||||||
|
bool mMustRecaptureAudioPosition;
|
||||||
|
int64_t mAudioFrameSum;
|
||||||
|
int64_t mAudioFrameOffset;
|
||||||
|
int64_t mStreamOffset;
|
||||||
|
|
||||||
|
nsCOMPtr<mozIGeckoMediaPluginService> mMPS;
|
||||||
|
nsCOMPtr<nsIThread> mGMPThread;
|
||||||
|
nsRefPtr<CDMProxy> mProxy;
|
||||||
|
GMPAudioDecoderProxy* mGMP;
|
||||||
|
|
||||||
|
const mp4_demuxer::AudioDecoderConfig& mConfig;
|
||||||
|
nsRefPtr<MediaTaskQueue> mTaskQueue;
|
||||||
|
MediaDataDecoderCallback* mCallback;
|
||||||
|
|
||||||
|
Monitor mMonitor;
|
||||||
|
bool mFlushComplete;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif
|
@ -18,6 +18,8 @@
|
|||||||
#include "MediaTaskQueue.h"
|
#include "MediaTaskQueue.h"
|
||||||
#include "SharedThreadPool.h"
|
#include "SharedThreadPool.h"
|
||||||
#include "mozilla/EMELog.h"
|
#include "mozilla/EMELog.h"
|
||||||
|
#include "EMEH264Decoder.h"
|
||||||
|
#include "EMEAACDecoder.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
@ -199,8 +201,13 @@ EMEDecoderModule::CreateH264Decoder(const VideoDecoderConfig& aConfig,
|
|||||||
MediaDataDecoderCallback* aCallback)
|
MediaDataDecoderCallback* aCallback)
|
||||||
{
|
{
|
||||||
if (mCDMDecodesVideo) {
|
if (mCDMDecodesVideo) {
|
||||||
NS_WARNING("Support for CDM that decodes video not yet supported");
|
nsRefPtr<MediaDataDecoder> decoder(new EMEH264Decoder(mProxy,
|
||||||
return nullptr;
|
aConfig,
|
||||||
|
aLayersBackend,
|
||||||
|
aImageContainer,
|
||||||
|
aVideoTaskQueue,
|
||||||
|
aCallback));
|
||||||
|
return decoder.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
nsRefPtr<MediaDataDecoder> decoder(mPDM->CreateH264Decoder(aConfig,
|
nsRefPtr<MediaDataDecoder> decoder(mPDM->CreateH264Decoder(aConfig,
|
||||||
@ -225,8 +232,11 @@ EMEDecoderModule::CreateAACDecoder(const AudioDecoderConfig& aConfig,
|
|||||||
MediaDataDecoderCallback* aCallback)
|
MediaDataDecoderCallback* aCallback)
|
||||||
{
|
{
|
||||||
if (mCDMDecodesAudio) {
|
if (mCDMDecodesAudio) {
|
||||||
NS_WARNING("Support for CDM that decodes audio not yet supported");
|
nsRefPtr<MediaDataDecoder> decoder(new EMEAACDecoder(mProxy,
|
||||||
return nullptr;
|
aConfig,
|
||||||
|
aAudioTaskQueue,
|
||||||
|
aCallback));
|
||||||
|
return decoder.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
nsRefPtr<MediaDataDecoder> decoder(mPDM->CreateAACDecoder(aConfig,
|
nsRefPtr<MediaDataDecoder> decoder(mPDM->CreateAACDecoder(aConfig,
|
||||||
|
360
content/media/fmp4/eme/EMEH264Decoder.cpp
Normal file
360
content/media/fmp4/eme/EMEH264Decoder.cpp
Normal file
@ -0,0 +1,360 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
#include "EMEH264Decoder.h"
|
||||||
|
#include "gmp-video-host.h"
|
||||||
|
#include "gmp-video-decode.h"
|
||||||
|
#include "gmp-video-frame-i420.h"
|
||||||
|
#include "gmp-video-frame-encoded.h"
|
||||||
|
#include "GMPVideoEncodedFrameImpl.h"
|
||||||
|
#include "mp4_demuxer/AnnexB.h"
|
||||||
|
#include "mozilla/CDMProxy.h"
|
||||||
|
#include "nsServiceManagerUtils.h"
|
||||||
|
#include "prsystem.h"
|
||||||
|
#include "gfx2DGlue.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
EMEH264Decoder::EMEH264Decoder(CDMProxy* aProxy,
|
||||||
|
const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||||
|
layers::LayersBackend aLayersBackend,
|
||||||
|
layers::ImageContainer* aImageContainer,
|
||||||
|
MediaTaskQueue* aTaskQueue,
|
||||||
|
MediaDataDecoderCallback* aCallback)
|
||||||
|
: mProxy(aProxy)
|
||||||
|
, mGMP(nullptr)
|
||||||
|
, mHost(nullptr)
|
||||||
|
, mConfig(aConfig)
|
||||||
|
, mImageContainer(aImageContainer)
|
||||||
|
, mTaskQueue(aTaskQueue)
|
||||||
|
, mCallback(aCallback)
|
||||||
|
, mLastStreamOffset(0)
|
||||||
|
, mMonitor("EMEH264Decoder")
|
||||||
|
, mFlushComplete(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
EMEH264Decoder::~EMEH264Decoder() {
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
EMEH264Decoder::Init()
|
||||||
|
{
|
||||||
|
// Note: this runs on the decode task queue.
|
||||||
|
|
||||||
|
mMPS = do_GetService("@mozilla.org/gecko-media-plugin-service;1");
|
||||||
|
MOZ_ASSERT(mMPS);
|
||||||
|
|
||||||
|
nsresult rv = mMPS->GetThread(getter_AddRefs(mGMPThread));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
nsRefPtr<InitTask> task(new InitTask(this));
|
||||||
|
rv = mGMPThread->Dispatch(task, NS_DISPATCH_SYNC);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
NS_ENSURE_SUCCESS(task->mResult, task->mResult);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
EMEH264Decoder::Input(MP4Sample* aSample)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue.
|
||||||
|
|
||||||
|
nsRefPtr<nsIRunnable> task(new DeliverSample(this, aSample));
|
||||||
|
nsresult rv = mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
EMEH264Decoder::Flush()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue.
|
||||||
|
|
||||||
|
{
|
||||||
|
MonitorAutoLock mon(mMonitor);
|
||||||
|
mFlushComplete = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRefPtr<nsIRunnable> task;
|
||||||
|
task = NS_NewRunnableMethod(this, &EMEH264Decoder::GmpFlush);
|
||||||
|
nsresult rv = mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
{
|
||||||
|
MonitorAutoLock mon(mMonitor);
|
||||||
|
while (!mFlushComplete) {
|
||||||
|
mon.Wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
EMEH264Decoder::Drain()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue.
|
||||||
|
|
||||||
|
nsRefPtr<nsIRunnable> task;
|
||||||
|
task = NS_NewRunnableMethod(this, &EMEH264Decoder::GmpDrain);
|
||||||
|
nsresult rv = mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
EMEH264Decoder::Shutdown()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue.
|
||||||
|
|
||||||
|
nsRefPtr<nsIRunnable> task;
|
||||||
|
task = NS_NewRunnableMethod(this, &EMEH264Decoder::GmpShutdown);
|
||||||
|
nsresult rv = mGMPThread->Dispatch(task, NS_DISPATCH_SYNC);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EMEH264Decoder::Decoded(GMPVideoi420Frame* aDecodedFrame)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
|
||||||
|
VideoData::YCbCrBuffer b;
|
||||||
|
|
||||||
|
auto height = aDecodedFrame->Height();
|
||||||
|
auto width = aDecodedFrame->Width();
|
||||||
|
|
||||||
|
// Y (Y') plane
|
||||||
|
b.mPlanes[0].mData = aDecodedFrame->Buffer(kGMPYPlane);
|
||||||
|
b.mPlanes[0].mStride = aDecodedFrame->Stride(kGMPYPlane);
|
||||||
|
b.mPlanes[0].mHeight = height;
|
||||||
|
b.mPlanes[0].mWidth = width;
|
||||||
|
b.mPlanes[0].mOffset = 0;
|
||||||
|
b.mPlanes[0].mSkip = 0;
|
||||||
|
|
||||||
|
// U plane (Cb)
|
||||||
|
b.mPlanes[1].mData = aDecodedFrame->Buffer(kGMPUPlane);
|
||||||
|
b.mPlanes[1].mStride = aDecodedFrame->Stride(kGMPUPlane);
|
||||||
|
b.mPlanes[1].mHeight = height / 2;
|
||||||
|
b.mPlanes[1].mWidth = width / 2;
|
||||||
|
b.mPlanes[1].mOffset = 0;
|
||||||
|
b.mPlanes[1].mSkip = 0;
|
||||||
|
|
||||||
|
// V plane (Cr)
|
||||||
|
b.mPlanes[2].mData = aDecodedFrame->Buffer(kGMPVPlane);
|
||||||
|
b.mPlanes[2].mStride = aDecodedFrame->Stride(kGMPVPlane);
|
||||||
|
b.mPlanes[2].mHeight = height / 2;
|
||||||
|
b.mPlanes[2].mWidth = width / 2;
|
||||||
|
b.mPlanes[2].mOffset = 0;
|
||||||
|
b.mPlanes[2].mSkip = 0;
|
||||||
|
|
||||||
|
VideoData *v = VideoData::Create(mVideoInfo,
|
||||||
|
mImageContainer,
|
||||||
|
mLastStreamOffset,
|
||||||
|
aDecodedFrame->Timestamp(),
|
||||||
|
aDecodedFrame->Duration(),
|
||||||
|
b,
|
||||||
|
false,
|
||||||
|
-1,
|
||||||
|
ToIntRect(mPictureRegion));
|
||||||
|
aDecodedFrame->Destroy();
|
||||||
|
mCallback->Output(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EMEH264Decoder::ReceivedDecodedReferenceFrame(const uint64_t aPictureId)
|
||||||
|
{
|
||||||
|
// Ignore.
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EMEH264Decoder::ReceivedDecodedFrame(const uint64_t aPictureId)
|
||||||
|
{
|
||||||
|
// Ignore.
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EMEH264Decoder::InputDataExhausted()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
mCallback->InputExhausted();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EMEH264Decoder::DrainComplete()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
mCallback->DrainComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EMEH264Decoder::ResetComplete()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
{
|
||||||
|
MonitorAutoLock mon(mMonitor);
|
||||||
|
mFlushComplete = true;
|
||||||
|
mon.NotifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EMEH264Decoder::Error(GMPErr aErr)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
mCallback->Error();
|
||||||
|
GmpShutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EMEH264Decoder::Terminated()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
|
||||||
|
NS_WARNING("H.264 GMP decoder terminated.");
|
||||||
|
GmpShutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
EMEH264Decoder::GmpInit()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
|
||||||
|
nsTArray<nsCString> tags;
|
||||||
|
tags.AppendElement(NS_LITERAL_CSTRING("h264"));
|
||||||
|
tags.AppendElement(NS_ConvertUTF16toUTF8(mProxy->KeySystem()));
|
||||||
|
nsresult rv = mMPS->GetGMPVideoDecoder(&tags,
|
||||||
|
mProxy->GetOrigin(),
|
||||||
|
&mHost,
|
||||||
|
&mGMP);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
MOZ_ASSERT(mHost && mGMP);
|
||||||
|
|
||||||
|
GMPVideoCodec codec;
|
||||||
|
memset(&codec, 0, sizeof(codec));
|
||||||
|
|
||||||
|
codec.mGMPApiVersion = kGMPVersion33;
|
||||||
|
|
||||||
|
codec.mCodecType = kGMPVideoCodecH264;
|
||||||
|
codec.mWidth = mConfig.display_width;
|
||||||
|
codec.mHeight = mConfig.display_height;
|
||||||
|
|
||||||
|
nsTArray<uint8_t> codecSpecific;
|
||||||
|
codecSpecific.AppendElement(0); // mPacketizationMode.
|
||||||
|
codecSpecific.AppendElements(mConfig.extra_data.begin(),
|
||||||
|
mConfig.extra_data.length());
|
||||||
|
|
||||||
|
rv = mGMP->InitDecode(codec,
|
||||||
|
codecSpecific,
|
||||||
|
this,
|
||||||
|
PR_GetNumberOfProcessors());
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
mVideoInfo.mDisplay = nsIntSize(mConfig.display_width, mConfig.display_height);
|
||||||
|
mVideoInfo.mHasVideo = true;
|
||||||
|
mPictureRegion = nsIntRect(0, 0, mConfig.display_width, mConfig.display_height);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
EMEH264Decoder::GmpInput(MP4Sample* aSample)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
|
||||||
|
nsAutoPtr<MP4Sample> sample(aSample);
|
||||||
|
if (!mGMP) {
|
||||||
|
mCallback->Error();
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sample->crypto.valid) {
|
||||||
|
CDMCaps::AutoLock caps(mProxy->Capabilites());
|
||||||
|
MOZ_ASSERT(caps.CanDecryptAndDecodeVideo());
|
||||||
|
const auto& keyid = sample->crypto.key;
|
||||||
|
if (!caps.IsKeyUsable(keyid)) {
|
||||||
|
nsRefPtr<nsIRunnable> task(new DeliverSample(this, sample.forget()));
|
||||||
|
caps.CallWhenKeyUsable(keyid, task, mGMPThread);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mLastStreamOffset = sample->byte_offset;
|
||||||
|
|
||||||
|
GMPVideoFrame* ftmp = nullptr;
|
||||||
|
GMPErr err = mHost->CreateFrame(kGMPEncodedVideoFrame, &ftmp);
|
||||||
|
if (GMP_FAILED(err)) {
|
||||||
|
mCallback->Error();
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gmp::GMPVideoEncodedFrameImpl* frame = static_cast<gmp::GMPVideoEncodedFrameImpl*>(ftmp);
|
||||||
|
err = frame->CreateEmptyFrame(sample->size);
|
||||||
|
if (GMP_FAILED(err)) {
|
||||||
|
mCallback->Error();
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(frame->Buffer(), sample->data, frame->Size());
|
||||||
|
|
||||||
|
frame->SetEncodedWidth(mConfig.display_width);
|
||||||
|
frame->SetEncodedHeight(mConfig.display_height);
|
||||||
|
frame->SetTimeStamp(sample->composition_timestamp);
|
||||||
|
frame->SetCompleteFrame(true);
|
||||||
|
frame->SetDuration(sample->duration);
|
||||||
|
if (sample->crypto.valid) {
|
||||||
|
frame->InitCrypto(sample->crypto);
|
||||||
|
}
|
||||||
|
frame->SetFrameType(sample->is_sync_point ? kGMPKeyFrame : kGMPDeltaFrame);
|
||||||
|
frame->SetBufferType(GMP_BufferLength32);
|
||||||
|
|
||||||
|
nsTArray<uint8_t> info; // No codec specific per-frame info to pass.
|
||||||
|
nsresult rv = mGMP->Decode(frame, false, info, 0);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
mCallback->Error();
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EMEH264Decoder::GmpFlush()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
if (!mGMP || NS_FAILED(mGMP->Reset())) {
|
||||||
|
// Abort the flush...
|
||||||
|
MonitorAutoLock mon(mMonitor);
|
||||||
|
mFlushComplete = true;
|
||||||
|
mon.NotifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EMEH264Decoder::GmpDrain()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
if (!mGMP || NS_FAILED(mGMP->Drain())) {
|
||||||
|
mCallback->DrainComplete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EMEH264Decoder::GmpShutdown()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
if (!mGMP) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mGMP->Close();
|
||||||
|
mGMP = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mozilla
|
114
content/media/fmp4/eme/EMEH264Decoder.h
Normal file
114
content/media/fmp4/eme/EMEH264Decoder.h
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
#ifndef EMEH264Decoder_h_
|
||||||
|
#define EMEH264Decoder_h_
|
||||||
|
|
||||||
|
#include "PlatformDecoderModule.h"
|
||||||
|
#include "mp4_demuxer/DecoderData.h"
|
||||||
|
#include "ImageContainer.h"
|
||||||
|
#include "GMPVideoDecoderProxy.h"
|
||||||
|
#include "mozIGeckoMediaPluginService.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
class CDMProxy;
|
||||||
|
class MediaTaskQueue;
|
||||||
|
|
||||||
|
class EMEH264Decoder : public MediaDataDecoder
|
||||||
|
, public GMPVideoDecoderCallbackProxy
|
||||||
|
{
|
||||||
|
typedef mp4_demuxer::MP4Sample MP4Sample;
|
||||||
|
public:
|
||||||
|
EMEH264Decoder(CDMProxy* aProxy,
|
||||||
|
const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||||
|
layers::LayersBackend aLayersBackend,
|
||||||
|
layers::ImageContainer* aImageContainer,
|
||||||
|
MediaTaskQueue* aTaskQueue,
|
||||||
|
MediaDataDecoderCallback* aCallback);
|
||||||
|
~EMEH264Decoder();
|
||||||
|
|
||||||
|
// MediaDataDecoder
|
||||||
|
virtual nsresult Init() MOZ_OVERRIDE;
|
||||||
|
virtual nsresult Input(MP4Sample* aSample) MOZ_OVERRIDE;
|
||||||
|
virtual nsresult Flush() MOZ_OVERRIDE;
|
||||||
|
virtual nsresult Drain() MOZ_OVERRIDE;
|
||||||
|
virtual nsresult Shutdown() MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
// GMPVideoDecoderProxyCallback
|
||||||
|
virtual void Decoded(GMPVideoi420Frame* aDecodedFrame) MOZ_OVERRIDE;
|
||||||
|
virtual void ReceivedDecodedReferenceFrame(const uint64_t aPictureId) MOZ_OVERRIDE;
|
||||||
|
virtual void ReceivedDecodedFrame(const uint64_t aPictureId) MOZ_OVERRIDE;
|
||||||
|
virtual void InputDataExhausted() MOZ_OVERRIDE;
|
||||||
|
virtual void DrainComplete() MOZ_OVERRIDE;
|
||||||
|
virtual void ResetComplete() MOZ_OVERRIDE;
|
||||||
|
virtual void Error(GMPErr aErr) MOZ_OVERRIDE;
|
||||||
|
virtual void Terminated() MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
nsresult GmpInit();
|
||||||
|
nsresult GmpInput(MP4Sample* aSample);
|
||||||
|
void GmpFlush();
|
||||||
|
void GmpDrain();
|
||||||
|
void GmpShutdown();
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
bool IsOnGMPThread() {
|
||||||
|
return NS_GetCurrentThread() == mGMPThread;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class DeliverSample : public nsRunnable {
|
||||||
|
public:
|
||||||
|
DeliverSample(EMEH264Decoder* aDecoder,
|
||||||
|
mp4_demuxer::MP4Sample* aSample)
|
||||||
|
: mDecoder(aDecoder)
|
||||||
|
, mSample(aSample)
|
||||||
|
{}
|
||||||
|
|
||||||
|
NS_IMETHOD Run() {
|
||||||
|
mDecoder->GmpInput(mSample.forget());
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
nsRefPtr<EMEH264Decoder> mDecoder;
|
||||||
|
nsAutoPtr<mp4_demuxer::MP4Sample> mSample;
|
||||||
|
};
|
||||||
|
|
||||||
|
class InitTask : public nsRunnable {
|
||||||
|
public:
|
||||||
|
InitTask(EMEH264Decoder* aDecoder)
|
||||||
|
: mDecoder(aDecoder)
|
||||||
|
{}
|
||||||
|
NS_IMETHOD Run() {
|
||||||
|
mResult = mDecoder->GmpInit();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
nsresult mResult;
|
||||||
|
EMEH264Decoder* mDecoder;
|
||||||
|
};
|
||||||
|
|
||||||
|
nsCOMPtr<mozIGeckoMediaPluginService> mMPS;
|
||||||
|
nsCOMPtr<nsIThread> mGMPThread;
|
||||||
|
nsRefPtr<CDMProxy> mProxy;
|
||||||
|
GMPVideoDecoderProxy* mGMP;
|
||||||
|
GMPVideoHost* mHost;
|
||||||
|
|
||||||
|
VideoInfo mVideoInfo;
|
||||||
|
nsIntRect mPictureRegion;
|
||||||
|
const mp4_demuxer::VideoDecoderConfig& mConfig;
|
||||||
|
nsRefPtr<layers::ImageContainer> mImageContainer;
|
||||||
|
nsRefPtr<MediaTaskQueue> mTaskQueue;
|
||||||
|
MediaDataDecoderCallback* mCallback;
|
||||||
|
int64_t mLastStreamOffset;
|
||||||
|
Monitor mMonitor;
|
||||||
|
bool mFlushComplete;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // EMEH264Decoder_h_
|
@ -5,7 +5,9 @@
|
|||||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
EXPORTS += [
|
EXPORTS += [
|
||||||
|
'eme/EMEAACDecoder.h',
|
||||||
'eme/EMEDecoderModule.h',
|
'eme/EMEDecoderModule.h',
|
||||||
|
'eme/EMEH264Decoder.h',
|
||||||
'MP4Decoder.h',
|
'MP4Decoder.h',
|
||||||
'MP4Reader.h',
|
'MP4Reader.h',
|
||||||
'PlatformDecoderModule.h',
|
'PlatformDecoderModule.h',
|
||||||
@ -13,7 +15,9 @@ EXPORTS += [
|
|||||||
|
|
||||||
UNIFIED_SOURCES += [
|
UNIFIED_SOURCES += [
|
||||||
'BlankDecoderModule.cpp',
|
'BlankDecoderModule.cpp',
|
||||||
|
'eme/EMEAACDecoder.cpp',
|
||||||
'eme/EMEDecoderModule.cpp',
|
'eme/EMEDecoderModule.cpp',
|
||||||
|
'eme/EMEH264Decoder.cpp',
|
||||||
'PlatformDecoderModule.cpp',
|
'PlatformDecoderModule.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -58,6 +62,12 @@ if CONFIG['MOZ_APPLEMEDIA']:
|
|||||||
'-framework AudioToolbox',
|
'-framework AudioToolbox',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
include('/ipc/chromium/chromium-config.mozbuild')
|
||||||
|
|
||||||
|
LOCAL_INCLUDES += [
|
||||||
|
'../base',
|
||||||
|
]
|
||||||
|
|
||||||
FINAL_LIBRARY = 'xul'
|
FINAL_LIBRARY = 'xul'
|
||||||
|
|
||||||
FAIL_ON_WARNINGS = True
|
FAIL_ON_WARNINGS = True
|
||||||
|
@ -27,6 +27,8 @@ using mozilla::dom::CrashReporterChild;
|
|||||||
#if defined(XP_WIN)
|
#if defined(XP_WIN)
|
||||||
#define TARGET_SANDBOX_EXPORTS
|
#define TARGET_SANDBOX_EXPORTS
|
||||||
#include "mozilla/sandboxTarget.h"
|
#include "mozilla/sandboxTarget.h"
|
||||||
|
#elif defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
|
||||||
|
#include "mozilla/Sandbox.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
@ -99,6 +101,13 @@ GMPChild::LoadPluginLibrary(const std::string& aPluginPath)
|
|||||||
|
|
||||||
nsAutoCString nativePath;
|
nsAutoCString nativePath;
|
||||||
libFile->GetNativePath(nativePath);
|
libFile->GetNativePath(nativePath);
|
||||||
|
|
||||||
|
#if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
|
||||||
|
// Enable sandboxing here -- we know the plugin file's path, but
|
||||||
|
// this process's execution hasn't been affected by its content yet.
|
||||||
|
mozilla::SetMediaPluginSandbox(nativePath.get());
|
||||||
|
#endif
|
||||||
|
|
||||||
mLib = PR_LoadLibrary(nativePath.get());
|
mLib = PR_LoadLibrary(nativePath.get());
|
||||||
if (!mLib) {
|
if (!mLib) {
|
||||||
return false;
|
return false;
|
||||||
@ -110,7 +119,7 @@ GMPChild::LoadPluginLibrary(const std::string& aPluginPath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto platformAPI = new GMPPlatformAPI();
|
auto platformAPI = new GMPPlatformAPI();
|
||||||
InitPlatformAPI(*platformAPI);
|
InitPlatformAPI(*platformAPI, this);
|
||||||
|
|
||||||
if (initFunc(platformAPI) != GMPNoErr) {
|
if (initFunc(platformAPI) != GMPNoErr) {
|
||||||
return false;
|
return false;
|
||||||
@ -301,6 +310,33 @@ GMPChild::RecvPGMPDecryptorConstructor(PGMPDecryptorChild* aActor)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PGMPTimerChild*
|
||||||
|
GMPChild::AllocPGMPTimerChild()
|
||||||
|
{
|
||||||
|
return new GMPTimerChild(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
GMPChild::DeallocPGMPTimerChild(PGMPTimerChild* aActor)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mTimerChild == static_cast<GMPTimerChild*>(aActor));
|
||||||
|
mTimerChild = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
GMPTimerChild*
|
||||||
|
GMPChild::GetGMPTimers()
|
||||||
|
{
|
||||||
|
if (!mTimerChild) {
|
||||||
|
PGMPTimerChild* sc = SendPGMPTimerConstructor();
|
||||||
|
if (!sc) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
mTimerChild = static_cast<GMPTimerChild*>(sc);
|
||||||
|
}
|
||||||
|
return mTimerChild;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
GMPChild::RecvCrashPluginNow()
|
GMPChild::RecvCrashPluginNow()
|
||||||
{
|
{
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "mozilla/gmp/PGMPChild.h"
|
#include "mozilla/gmp/PGMPChild.h"
|
||||||
#include "GMPSharedMemManager.h"
|
#include "GMPSharedMemManager.h"
|
||||||
|
#include "GMPTimerChild.h"
|
||||||
#include "gmp-entrypoints.h"
|
#include "gmp-entrypoints.h"
|
||||||
#include "prlink.h"
|
#include "prlink.h"
|
||||||
|
|
||||||
@ -28,6 +29,9 @@ public:
|
|||||||
bool LoadPluginLibrary(const std::string& aPluginPath);
|
bool LoadPluginLibrary(const std::string& aPluginPath);
|
||||||
MessageLoop* GMPMessageLoop();
|
MessageLoop* GMPMessageLoop();
|
||||||
|
|
||||||
|
// Main thread only.
|
||||||
|
GMPTimerChild* GetGMPTimers();
|
||||||
|
|
||||||
// GMPSharedMem
|
// GMPSharedMem
|
||||||
virtual void CheckThread() MOZ_OVERRIDE;
|
virtual void CheckThread() MOZ_OVERRIDE;
|
||||||
|
|
||||||
@ -51,11 +55,16 @@ private:
|
|||||||
virtual bool DeallocPGMPAudioDecoderChild(PGMPAudioDecoderChild* aActor) MOZ_OVERRIDE;
|
virtual bool DeallocPGMPAudioDecoderChild(PGMPAudioDecoderChild* aActor) MOZ_OVERRIDE;
|
||||||
virtual bool RecvPGMPAudioDecoderConstructor(PGMPAudioDecoderChild* aActor) MOZ_OVERRIDE;
|
virtual bool RecvPGMPAudioDecoderConstructor(PGMPAudioDecoderChild* aActor) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual PGMPTimerChild* AllocPGMPTimerChild() MOZ_OVERRIDE;
|
||||||
|
virtual bool DeallocPGMPTimerChild(PGMPTimerChild* aActor) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual bool RecvCrashPluginNow() MOZ_OVERRIDE;
|
virtual bool RecvCrashPluginNow() MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
|
virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
|
||||||
virtual void ProcessingError(Result aWhat) MOZ_OVERRIDE;
|
virtual void ProcessingError(Result aWhat) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
nsRefPtr<GMPTimerChild> mTimerChild;
|
||||||
|
|
||||||
PRLibrary* mLib;
|
PRLibrary* mLib;
|
||||||
GMPGetAPIFunc mGetAPIFunc;
|
GMPGetAPIFunc mGetAPIFunc;
|
||||||
MessageLoop* mGMPMessageLoop;
|
MessageLoop* mGMPMessageLoop;
|
||||||
|
@ -149,8 +149,13 @@ GMPDecryptorChild::Decrypted(GMPBuffer* aBuffer, GMPErr aResult)
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
|
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
|
||||||
|
|
||||||
|
if (!aBuffer) {
|
||||||
|
NS_WARNING("GMPDecryptorCallback passed bull GMPBuffer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
auto buffer = static_cast<GMPBufferImpl*>(aBuffer);
|
auto buffer = static_cast<GMPBufferImpl*>(aBuffer);
|
||||||
SendDecrypted(buffer->mId, aResult, buffer->mData);
|
SendDecrypted(buffer->mId, aResult, buffer->mData);
|
||||||
|
delete buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -307,6 +312,8 @@ GMPDecryptorChild::RecvDecrypt(const uint32_t& aId,
|
|||||||
|
|
||||||
GMPEncryptedBufferDataImpl metadata(aMetadata);
|
GMPEncryptedBufferDataImpl metadata(aMetadata);
|
||||||
|
|
||||||
|
// Note: the GMPBufferImpl created here is deleted when the GMP passes
|
||||||
|
// it back in the Decrypted() callback above.
|
||||||
mSession->Decrypt(new GMPBufferImpl(aId, aBuffer), &metadata);
|
mSession->Decrypt(new GMPBufferImpl(aId, aBuffer), &metadata);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "mozIGeckoMediaPluginService.h"
|
#include "mozIGeckoMediaPluginService.h"
|
||||||
#include "mozilla/unused.h"
|
#include "mozilla/unused.h"
|
||||||
#include "nsIObserverService.h"
|
#include "nsIObserverService.h"
|
||||||
|
#include "GMPTimerParent.h"
|
||||||
#include "runnable_utils.h"
|
#include "runnable_utils.h"
|
||||||
|
|
||||||
#include "mozilla/dom/CrashReporterParent.h"
|
#include "mozilla/dom/CrashReporterParent.h"
|
||||||
@ -328,7 +329,6 @@ GMPParent::State() const
|
|||||||
return mState;
|
return mState;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
// Not changing to use mService since we'll be removing it
|
// Not changing to use mService since we'll be removing it
|
||||||
nsIThread*
|
nsIThread*
|
||||||
GMPParent::GMPThread()
|
GMPParent::GMPThread()
|
||||||
@ -350,7 +350,6 @@ GMPParent::GMPThread()
|
|||||||
|
|
||||||
return mGMPThread;
|
return mGMPThread;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
GMPParent::SupportsAPI(const nsCString& aAPI, const nsCString& aTag)
|
GMPParent::SupportsAPI(const nsCString& aAPI, const nsCString& aTag)
|
||||||
@ -618,6 +617,28 @@ GMPParent::DeallocPGMPAudioDecoderParent(PGMPAudioDecoderParent* aActor)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
GMPParent::RecvPGMPTimerConstructor(PGMPTimerParent* actor)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
PGMPTimerParent*
|
||||||
|
GMPParent::AllocPGMPTimerParent()
|
||||||
|
{
|
||||||
|
GMPTimerParent* p = new GMPTimerParent(GMPThread());
|
||||||
|
NS_ADDREF(p); // Released in DeallocPGMPTimerParent.
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
GMPParent::DeallocPGMPTimerParent(PGMPTimerParent* aActor)
|
||||||
|
{
|
||||||
|
GMPTimerParent* p = static_cast<GMPTimerParent*>(aActor);
|
||||||
|
NS_RELEASE(p);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
ParseNextRecord(nsILineInputStream* aLineInputStream,
|
ParseNextRecord(nsILineInputStream* aLineInputStream,
|
||||||
const nsCString& aPrefix,
|
const nsCString& aPrefix,
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "GMPDecryptorParent.h"
|
#include "GMPDecryptorParent.h"
|
||||||
#include "GMPVideoDecoderParent.h"
|
#include "GMPVideoDecoderParent.h"
|
||||||
#include "GMPVideoEncoderParent.h"
|
#include "GMPVideoEncoderParent.h"
|
||||||
|
#include "GMPTimerParent.h"
|
||||||
#include "mozilla/gmp/PGMPParent.h"
|
#include "mozilla/gmp/PGMPParent.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nscore.h"
|
#include "nscore.h"
|
||||||
@ -95,9 +96,7 @@ public:
|
|||||||
void AudioDecoderDestroyed(GMPAudioDecoderParent* aDecoder);
|
void AudioDecoderDestroyed(GMPAudioDecoderParent* aDecoder);
|
||||||
|
|
||||||
GMPState State() const;
|
GMPState State() const;
|
||||||
#ifdef DEBUG
|
|
||||||
nsIThread* GMPThread();
|
nsIThread* GMPThread();
|
||||||
#endif
|
|
||||||
|
|
||||||
// A GMP can either be a single instance shared across all origins (like
|
// A GMP can either be a single instance shared across all origins (like
|
||||||
// in the OpenH264 case), or we can require a new plugin instance for every
|
// in the OpenH264 case), or we can require a new plugin instance for every
|
||||||
@ -153,6 +152,10 @@ private:
|
|||||||
virtual PGMPAudioDecoderParent* AllocPGMPAudioDecoderParent() MOZ_OVERRIDE;
|
virtual PGMPAudioDecoderParent* AllocPGMPAudioDecoderParent() MOZ_OVERRIDE;
|
||||||
virtual bool DeallocPGMPAudioDecoderParent(PGMPAudioDecoderParent* aActor) MOZ_OVERRIDE;
|
virtual bool DeallocPGMPAudioDecoderParent(PGMPAudioDecoderParent* aActor) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual bool RecvPGMPTimerConstructor(PGMPTimerParent* actor) MOZ_OVERRIDE;
|
||||||
|
virtual PGMPTimerParent* AllocPGMPTimerParent() MOZ_OVERRIDE;
|
||||||
|
virtual bool DeallocPGMPTimerParent(PGMPTimerParent* aActor) MOZ_OVERRIDE;
|
||||||
|
|
||||||
GMPState mState;
|
GMPState mState;
|
||||||
nsCOMPtr<nsIFile> mDirectory; // plugin directory on disk
|
nsCOMPtr<nsIFile> mDirectory; // plugin directory on disk
|
||||||
nsString mName; // base name of plugin on disk, UTF-16 because used for paths
|
nsString mName; // base name of plugin on disk, UTF-16 because used for paths
|
||||||
@ -168,9 +171,7 @@ private:
|
|||||||
nsTArray<nsRefPtr<GMPVideoEncoderParent>> mVideoEncoders;
|
nsTArray<nsRefPtr<GMPVideoEncoderParent>> mVideoEncoders;
|
||||||
nsTArray<nsRefPtr<GMPDecryptorParent>> mDecryptors;
|
nsTArray<nsRefPtr<GMPDecryptorParent>> mDecryptors;
|
||||||
nsTArray<nsRefPtr<GMPAudioDecoderParent>> mAudioDecoders;
|
nsTArray<nsRefPtr<GMPAudioDecoderParent>> mAudioDecoders;
|
||||||
#ifdef DEBUG
|
|
||||||
nsCOMPtr<nsIThread> mGMPThread;
|
nsCOMPtr<nsIThread> mGMPThread;
|
||||||
#endif
|
|
||||||
// Origin the plugin is assigned to, or empty if the the plugin is not
|
// Origin the plugin is assigned to, or empty if the the plugin is not
|
||||||
// assigned to an origin.
|
// assigned to an origin.
|
||||||
nsAutoString mOrigin;
|
nsAutoString mOrigin;
|
||||||
|
@ -4,13 +4,17 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "GMPPlatform.h"
|
#include "GMPPlatform.h"
|
||||||
|
#include "GMPTimerChild.h"
|
||||||
#include "mozilla/Monitor.h"
|
#include "mozilla/Monitor.h"
|
||||||
#include "nsAutoPtr.h"
|
#include "nsAutoPtr.h"
|
||||||
|
#include "GMPChild.h"
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace gmp {
|
namespace gmp {
|
||||||
|
|
||||||
static MessageLoop* sMainLoop = nullptr;
|
static MessageLoop* sMainLoop = nullptr;
|
||||||
|
static GMPChild* sChild = nullptr;
|
||||||
|
|
||||||
// We just need a refcounted wrapper for GMPTask objects.
|
// We just need a refcounted wrapper for GMPTask objects.
|
||||||
class Runnable MOZ_FINAL
|
class Runnable MOZ_FINAL
|
||||||
@ -141,12 +145,30 @@ CreateMutex(GMPMutex** aMutex)
|
|||||||
return GMPNoErr;
|
return GMPNoErr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GMPErr
|
||||||
|
SetTimerOnMainThread(GMPTask* aTask, int64_t aTimeoutMS)
|
||||||
|
{
|
||||||
|
GMPTimerChild* timers = sChild->GetGMPTimers();
|
||||||
|
NS_ENSURE_TRUE(timers, GMPGenericErr);
|
||||||
|
return timers->SetTimer(aTask, aTimeoutMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
GMPErr
|
||||||
|
GetClock(GMPTimestamp* aOutTime)
|
||||||
|
{
|
||||||
|
*aOutTime = time(0) * 1000;
|
||||||
|
return GMPNoErr;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
InitPlatformAPI(GMPPlatformAPI& aPlatformAPI)
|
InitPlatformAPI(GMPPlatformAPI& aPlatformAPI, GMPChild* aChild)
|
||||||
{
|
{
|
||||||
if (!sMainLoop) {
|
if (!sMainLoop) {
|
||||||
sMainLoop = MessageLoop::current();
|
sMainLoop = MessageLoop::current();
|
||||||
}
|
}
|
||||||
|
if (!sChild) {
|
||||||
|
sChild = aChild;
|
||||||
|
}
|
||||||
|
|
||||||
aPlatformAPI.version = 0;
|
aPlatformAPI.version = 0;
|
||||||
aPlatformAPI.createthread = &CreateThread;
|
aPlatformAPI.createthread = &CreateThread;
|
||||||
@ -154,18 +176,20 @@ InitPlatformAPI(GMPPlatformAPI& aPlatformAPI)
|
|||||||
aPlatformAPI.syncrunonmainthread = &SyncRunOnMainThread;
|
aPlatformAPI.syncrunonmainthread = &SyncRunOnMainThread;
|
||||||
aPlatformAPI.createmutex = &CreateMutex;
|
aPlatformAPI.createmutex = &CreateMutex;
|
||||||
aPlatformAPI.createrecord = nullptr;
|
aPlatformAPI.createrecord = nullptr;
|
||||||
aPlatformAPI.settimer = nullptr;
|
aPlatformAPI.settimer = &SetTimerOnMainThread;
|
||||||
aPlatformAPI.getcurrenttime = nullptr;
|
aPlatformAPI.getcurrenttime = &GetClock;
|
||||||
}
|
}
|
||||||
|
|
||||||
GMPThreadImpl::GMPThreadImpl()
|
GMPThreadImpl::GMPThreadImpl()
|
||||||
: mMutex("GMPThreadImpl"),
|
: mMutex("GMPThreadImpl"),
|
||||||
mThread("GMPThread")
|
mThread("GMPThread")
|
||||||
{
|
{
|
||||||
|
MOZ_COUNT_CTOR(GMPThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
GMPThreadImpl::~GMPThreadImpl()
|
GMPThreadImpl::~GMPThreadImpl()
|
||||||
{
|
{
|
||||||
|
MOZ_COUNT_DTOR(GMPThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -188,20 +212,31 @@ GMPThreadImpl::Post(GMPTask* aTask)
|
|||||||
|
|
||||||
void
|
void
|
||||||
GMPThreadImpl::Join()
|
GMPThreadImpl::Join()
|
||||||
|
{
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(mMutex);
|
MutexAutoLock lock(mMutex);
|
||||||
if (mThread.IsRunning()) {
|
if (mThread.IsRunning()) {
|
||||||
mThread.Stop();
|
mThread.Stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
GMPMutexImpl::GMPMutexImpl()
|
GMPMutexImpl::GMPMutexImpl()
|
||||||
: mMutex("gmp-mutex")
|
: mMutex("gmp-mutex")
|
||||||
{
|
{
|
||||||
|
MOZ_COUNT_CTOR(GMPMutexImpl);
|
||||||
}
|
}
|
||||||
|
|
||||||
GMPMutexImpl::~GMPMutexImpl()
|
GMPMutexImpl::~GMPMutexImpl()
|
||||||
{
|
{
|
||||||
|
MOZ_COUNT_DTOR(GMPMutexImpl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GMPMutexImpl::Destroy()
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -15,7 +15,9 @@ namespace gmp {
|
|||||||
|
|
||||||
class GMPChild;
|
class GMPChild;
|
||||||
|
|
||||||
void InitPlatformAPI(GMPPlatformAPI& aPlatformAPI);
|
void InitPlatformAPI(GMPPlatformAPI& aPlatformAPI, GMPChild* aChild);
|
||||||
|
|
||||||
|
GMPErr RunOnMainThread(GMPTask* aTask);
|
||||||
|
|
||||||
class GMPThreadImpl : public GMPThread
|
class GMPThreadImpl : public GMPThread
|
||||||
{
|
{
|
||||||
@ -41,6 +43,7 @@ public:
|
|||||||
// GMPMutex
|
// GMPMutex
|
||||||
virtual void Acquire() MOZ_OVERRIDE;
|
virtual void Acquire() MOZ_OVERRIDE;
|
||||||
virtual void Release() MOZ_OVERRIDE;
|
virtual void Release() MOZ_OVERRIDE;
|
||||||
|
virtual void Destroy() MOZ_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Mutex mMutex;
|
Mutex mMutex;
|
||||||
|
67
content/media/gmp/GMPTimerChild.cpp
Normal file
67
content/media/gmp/GMPTimerChild.cpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
#include "GMPTimerChild.h"
|
||||||
|
#include "GMPPlatform.h"
|
||||||
|
#include "GMPChild.h"
|
||||||
|
|
||||||
|
#define MAX_NUM_TIMERS 1000
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace gmp {
|
||||||
|
|
||||||
|
GMPTimerChild::GMPTimerChild(GMPChild* aPlugin)
|
||||||
|
: mTimerCount(1)
|
||||||
|
, mPlugin(aPlugin)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
|
||||||
|
}
|
||||||
|
|
||||||
|
GMPTimerChild::~GMPTimerChild()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
|
||||||
|
}
|
||||||
|
|
||||||
|
GMPErr
|
||||||
|
GMPTimerChild::SetTimer(GMPTask* aTask, int64_t aTimeoutMS)
|
||||||
|
{
|
||||||
|
if (!aTask) {
|
||||||
|
NS_WARNING("Tried to set timer with null task!");
|
||||||
|
return GMPGenericErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mPlugin->GMPMessageLoop() != MessageLoop::current()) {
|
||||||
|
NS_WARNING("Tried to set GMP timer on non-main thread.");
|
||||||
|
return GMPGenericErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mTimers.Count() > MAX_NUM_TIMERS) {
|
||||||
|
return GMPQuotaExceededErr;
|
||||||
|
}
|
||||||
|
uint32_t timerId = mTimerCount;
|
||||||
|
mTimers.Put(timerId, aTask);
|
||||||
|
mTimerCount++;
|
||||||
|
|
||||||
|
if (!SendSetTimer(timerId, aTimeoutMS)) {
|
||||||
|
return GMPGenericErr;
|
||||||
|
}
|
||||||
|
return GMPNoErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
GMPTimerChild::RecvTimerExpired(const uint32_t& aTimerId)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
|
||||||
|
|
||||||
|
GMPTask* task = mTimers.Get(aTimerId);
|
||||||
|
mTimers.Remove(aTimerId);
|
||||||
|
if (task) {
|
||||||
|
RunOnMainThread(task);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace gmp
|
||||||
|
} // namespace mozilla
|
46
content/media/gmp/GMPTimerChild.h
Normal file
46
content/media/gmp/GMPTimerChild.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
#ifndef GMPTimerChild_h_
|
||||||
|
#define GMPTimerChild_h_
|
||||||
|
|
||||||
|
#include "mozilla/gmp/PGMPTimerChild.h"
|
||||||
|
#include "mozilla/Monitor.h"
|
||||||
|
#include "nsDataHashtable.h"
|
||||||
|
#include "nsHashKeys.h"
|
||||||
|
#include "gmp-errors.h"
|
||||||
|
#include "gmp-platform.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace gmp {
|
||||||
|
|
||||||
|
class GMPChild;
|
||||||
|
|
||||||
|
class GMPTimerChild : public PGMPTimerChild
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_INLINE_DECL_REFCOUNTING(GMPTimerChild)
|
||||||
|
|
||||||
|
GMPTimerChild(GMPChild* aPlugin);
|
||||||
|
|
||||||
|
GMPErr SetTimer(GMPTask* aTask, int64_t aTimeoutMS);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// GMPTimerChild
|
||||||
|
virtual bool RecvTimerExpired(const uint32_t& aTimerId) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
~GMPTimerChild();
|
||||||
|
|
||||||
|
nsDataHashtable<nsUint32HashKey, GMPTask*> mTimers;
|
||||||
|
uint32_t mTimerCount;
|
||||||
|
|
||||||
|
GMPChild* mPlugin;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace gmp
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // GMPTimerChild_h_
|
88
content/media/gmp/GMPTimerParent.cpp
Normal file
88
content/media/gmp/GMPTimerParent.cpp
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
#include "GMPTimerParent.h"
|
||||||
|
#include "nsComponentManagerUtils.h"
|
||||||
|
#include "mozilla/unused.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace gmp {
|
||||||
|
|
||||||
|
GMPTimerParent::GMPTimerParent(nsIThread* aGMPThread)
|
||||||
|
: mGMPThread(aGMPThread)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
GMPTimerParent::RecvSetTimer(const uint32_t& aTimerId,
|
||||||
|
const uint32_t& aTimeoutMs)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mGMPThread == NS_GetCurrentThread());
|
||||||
|
|
||||||
|
nsresult rv;
|
||||||
|
nsAutoPtr<Context> ctx(new Context());
|
||||||
|
ctx->mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
|
||||||
|
NS_ENSURE_SUCCESS(rv, true);
|
||||||
|
|
||||||
|
ctx->mId = aTimerId;
|
||||||
|
rv = ctx->mTimer->SetTarget(mGMPThread);
|
||||||
|
NS_ENSURE_SUCCESS(rv, true);
|
||||||
|
ctx->mParent = this;
|
||||||
|
|
||||||
|
rv = ctx->mTimer->InitWithFuncCallback(&GMPTimerParent::GMPTimerExpired,
|
||||||
|
ctx,
|
||||||
|
aTimeoutMs,
|
||||||
|
nsITimer::TYPE_ONE_SHOT);
|
||||||
|
NS_ENSURE_SUCCESS(rv, true);
|
||||||
|
|
||||||
|
mTimers.PutEntry(ctx.forget());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*static */
|
||||||
|
PLDHashOperator
|
||||||
|
GMPTimerParent::CancelTimers(nsPtrHashKey<Context>* aContext, void* aClosure)
|
||||||
|
{
|
||||||
|
auto context = aContext->GetKey();
|
||||||
|
context->mTimer->Cancel();
|
||||||
|
delete context;
|
||||||
|
return PL_DHASH_NEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GMPTimerParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mGMPThread == NS_GetCurrentThread());
|
||||||
|
mTimers.EnumerateEntries(GMPTimerParent::CancelTimers, nullptr);
|
||||||
|
mTimers.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
void
|
||||||
|
GMPTimerParent::GMPTimerExpired(nsITimer *aTimer, void *aClosure)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aClosure);
|
||||||
|
nsAutoPtr<Context> ctx(static_cast<Context*>(aClosure));
|
||||||
|
MOZ_ASSERT(ctx->mParent);
|
||||||
|
if (ctx->mParent) {
|
||||||
|
ctx->mParent->TimerExpired(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GMPTimerParent::TimerExpired(Context* aContext)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mGMPThread == NS_GetCurrentThread());
|
||||||
|
|
||||||
|
uint32_t id = aContext->mId;
|
||||||
|
mTimers.RemoveEntry(aContext);
|
||||||
|
if (id) {
|
||||||
|
unused << SendTimerExpired(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace gmp
|
||||||
|
} // namespace mozilla
|
61
content/media/gmp/GMPTimerParent.h
Normal file
61
content/media/gmp/GMPTimerParent.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
#ifndef GMPTimerParent_h_
|
||||||
|
#define GMPTimerParent_h_
|
||||||
|
|
||||||
|
#include "mozilla/gmp/PGMPTimerParent.h"
|
||||||
|
#include "nsITimer.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsClassHashtable.h"
|
||||||
|
#include "nsHashKeys.h"
|
||||||
|
#include "nsAutoPtr.h"
|
||||||
|
#include "mozilla/Monitor.h"
|
||||||
|
#include "nsIThread.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace gmp {
|
||||||
|
|
||||||
|
class GMPTimerParent : public PGMPTimerParent {
|
||||||
|
public:
|
||||||
|
NS_INLINE_DECL_REFCOUNTING(GMPTimerParent)
|
||||||
|
GMPTimerParent(nsIThread* aGMPThread);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool RecvSetTimer(const uint32_t& aTimerId,
|
||||||
|
const uint32_t& aTimeoutMs) MOZ_OVERRIDE;
|
||||||
|
virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
~GMPTimerParent() {}
|
||||||
|
|
||||||
|
static void GMPTimerExpired(nsITimer *aTimer, void *aClosure);
|
||||||
|
|
||||||
|
struct Context {
|
||||||
|
Context() {
|
||||||
|
MOZ_COUNT_CTOR(Context);
|
||||||
|
}
|
||||||
|
~Context() {
|
||||||
|
MOZ_COUNT_DTOR(Context);
|
||||||
|
}
|
||||||
|
nsCOMPtr<nsITimer> mTimer;
|
||||||
|
nsRefPtr<GMPTimerParent> mParent; // Note: live timers keep the GMPTimerParent alive.
|
||||||
|
uint32_t mId;
|
||||||
|
};
|
||||||
|
|
||||||
|
static PLDHashOperator
|
||||||
|
CancelTimers(nsPtrHashKey<Context>* aContext, void* aClosure);
|
||||||
|
|
||||||
|
void TimerExpired(Context* aContext);
|
||||||
|
|
||||||
|
nsTHashtable<nsPtrHashKey<Context>> mTimers;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIThread> mGMPThread;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace gmp
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // GMPTimerParent_h_
|
@ -8,6 +8,7 @@ include protocol PGMPVideoEncoder;
|
|||||||
include protocol PCrashReporter;
|
include protocol PCrashReporter;
|
||||||
include protocol PGMPDecryptor;
|
include protocol PGMPDecryptor;
|
||||||
include protocol PGMPAudioDecoder;
|
include protocol PGMPAudioDecoder;
|
||||||
|
include protocol PGMPTimer;
|
||||||
|
|
||||||
using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
|
using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
|
||||||
|
|
||||||
@ -21,9 +22,11 @@ intr protocol PGMP
|
|||||||
manages PGMPVideoDecoder;
|
manages PGMPVideoDecoder;
|
||||||
manages PGMPVideoEncoder;
|
manages PGMPVideoEncoder;
|
||||||
manages PCrashReporter;
|
manages PCrashReporter;
|
||||||
|
manages PGMPTimer;
|
||||||
|
|
||||||
parent:
|
parent:
|
||||||
async PCrashReporter(NativeThreadId tid);
|
async PCrashReporter(NativeThreadId tid);
|
||||||
|
async PGMPTimer();
|
||||||
|
|
||||||
child:
|
child:
|
||||||
async PGMPAudioDecoder();
|
async PGMPAudioDecoder();
|
||||||
|
22
content/media/gmp/PGMPTimer.ipdl
Normal file
22
content/media/gmp/PGMPTimer.ipdl
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
include protocol PGMP;
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace gmp {
|
||||||
|
|
||||||
|
async protocol PGMPTimer
|
||||||
|
{
|
||||||
|
manager PGMP;
|
||||||
|
child:
|
||||||
|
TimerExpired(uint32_t aTimerId);
|
||||||
|
parent:
|
||||||
|
SetTimer(uint32_t aTimerId, uint32_t aTimeoutMs);
|
||||||
|
__delete__();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace gmp
|
||||||
|
} // namespace mozilla
|
@ -257,6 +257,9 @@ public:
|
|||||||
// same GMPBuffer object and return it to Gecko by calling Decrypted(),
|
// same GMPBuffer object and return it to Gecko by calling Decrypted(),
|
||||||
// with the GMPNoErr successcode. If decryption fails, call Decrypted()
|
// with the GMPNoErr successcode. If decryption fails, call Decrypted()
|
||||||
// with a failure code, and an error event will fire on the media element.
|
// with a failure code, and an error event will fire on the media element.
|
||||||
|
// Note: When Decrypted() is called and aBuffer is passed back, aBuffer
|
||||||
|
// is deleted. Don't forget to call Decrypted(), as otherwise aBuffer's
|
||||||
|
// memory will leak!
|
||||||
virtual void Decrypt(GMPBuffer* aBuffer,
|
virtual void Decrypt(GMPBuffer* aBuffer,
|
||||||
GMPEncryptedBufferMetadata* aMetadata) = 0;
|
GMPEncryptedBufferMetadata* aMetadata) = 0;
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
|
|
||||||
class GMPTask {
|
class GMPTask {
|
||||||
public:
|
public:
|
||||||
virtual void Destroy() = 0;
|
virtual void Destroy() = 0; // Deletes object.
|
||||||
virtual ~GMPTask() {}
|
virtual ~GMPTask() {}
|
||||||
virtual void Run() = 0;
|
virtual void Run() = 0;
|
||||||
};
|
};
|
||||||
@ -50,7 +50,7 @@ class GMPThread {
|
|||||||
public:
|
public:
|
||||||
virtual ~GMPThread() {}
|
virtual ~GMPThread() {}
|
||||||
virtual void Post(GMPTask* aTask) = 0;
|
virtual void Post(GMPTask* aTask) = 0;
|
||||||
virtual void Join() = 0;
|
virtual void Join() = 0; // Deletes object after join completes.
|
||||||
};
|
};
|
||||||
|
|
||||||
class GMPMutex {
|
class GMPMutex {
|
||||||
@ -58,6 +58,7 @@ public:
|
|||||||
virtual ~GMPMutex() {}
|
virtual ~GMPMutex() {}
|
||||||
virtual void Acquire() = 0;
|
virtual void Acquire() = 0;
|
||||||
virtual void Release() = 0;
|
virtual void Release() = 0;
|
||||||
|
virtual void Destroy() = 0; // Deletes object.
|
||||||
};
|
};
|
||||||
|
|
||||||
// Time is defined as the number of milliseconds since the
|
// Time is defined as the number of milliseconds since the
|
||||||
@ -72,6 +73,8 @@ typedef GMPErr (*GMPCreateRecordPtr)(const char* aRecordName,
|
|||||||
uint32_t aRecordNameSize,
|
uint32_t aRecordNameSize,
|
||||||
GMPRecord** aOutRecord,
|
GMPRecord** aOutRecord,
|
||||||
GMPRecordClient* aClient);
|
GMPRecordClient* aClient);
|
||||||
|
|
||||||
|
// Call on main thread only.
|
||||||
typedef GMPErr (*GMPSetTimerOnMainThreadPtr)(GMPTask* aTask, int64_t aTimeoutMS);
|
typedef GMPErr (*GMPSetTimerOnMainThreadPtr)(GMPTask* aTask, int64_t aTimeoutMS);
|
||||||
typedef GMPErr (*GMPGetCurrentTimePtr)(GMPTimestamp* aOutTime);
|
typedef GMPErr (*GMPGetCurrentTimePtr)(GMPTimestamp* aOutTime);
|
||||||
|
|
||||||
|
@ -46,6 +46,8 @@ EXPORTS += [
|
|||||||
'GMPProcessParent.h',
|
'GMPProcessParent.h',
|
||||||
'GMPService.h',
|
'GMPService.h',
|
||||||
'GMPSharedMemManager.h',
|
'GMPSharedMemManager.h',
|
||||||
|
'GMPTimerChild.h',
|
||||||
|
'GMPTimerParent.h',
|
||||||
'GMPVideoDecoderChild.h',
|
'GMPVideoDecoderChild.h',
|
||||||
'GMPVideoDecoderParent.h',
|
'GMPVideoDecoderParent.h',
|
||||||
'GMPVideoDecoderProxy.h',
|
'GMPVideoDecoderProxy.h',
|
||||||
@ -72,6 +74,8 @@ UNIFIED_SOURCES += [
|
|||||||
'GMPProcessParent.cpp',
|
'GMPProcessParent.cpp',
|
||||||
'GMPService.cpp',
|
'GMPService.cpp',
|
||||||
'GMPSharedMemManager.cpp',
|
'GMPSharedMemManager.cpp',
|
||||||
|
'GMPTimerChild.cpp',
|
||||||
|
'GMPTimerParent.cpp',
|
||||||
'GMPVideoDecoderChild.cpp',
|
'GMPVideoDecoderChild.cpp',
|
||||||
'GMPVideoDecoderParent.cpp',
|
'GMPVideoDecoderParent.cpp',
|
||||||
'GMPVideoEncodedFrameImpl.cpp',
|
'GMPVideoEncodedFrameImpl.cpp',
|
||||||
@ -87,6 +91,7 @@ IPDL_SOURCES += [
|
|||||||
'PGMP.ipdl',
|
'PGMP.ipdl',
|
||||||
'PGMPAudioDecoder.ipdl',
|
'PGMPAudioDecoder.ipdl',
|
||||||
'PGMPDecryptor.ipdl',
|
'PGMPDecryptor.ipdl',
|
||||||
|
'PGMPTimer.ipdl',
|
||||||
'PGMPVideoDecoder.ipdl',
|
'PGMPVideoDecoder.ipdl',
|
||||||
'PGMPVideoEncoder.ipdl',
|
'PGMPVideoEncoder.ipdl',
|
||||||
]
|
]
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
#include "prlog.h"
|
#include "prlog.h"
|
||||||
#include "SubBufferDecoder.h"
|
#include "SubBufferDecoder.h"
|
||||||
|
#include "mozilla/Preferences.h"
|
||||||
|
|
||||||
struct JSContext;
|
struct JSContext;
|
||||||
class JSObject;
|
class JSObject;
|
||||||
@ -166,8 +167,19 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t chunk_size = BigEndian::readUint32(aData);
|
uint32_t chunk_size = BigEndian::readUint32(aData);
|
||||||
return chunk_size > 8 && aData[4] == 'f' && aData[5] == 't' &&
|
if (chunk_size < 8) {
|
||||||
aData[6] == 'y' && aData[7] == 'p';
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Preferences::GetBool("media.mediasource.allow_init_moov", false)) {
|
||||||
|
if (aData[4] == 'm' && aData[5] == 'o' && aData[6] == 'o' &&
|
||||||
|
aData[7] == 'v') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return aData[4] == 'f' && aData[5] == 't' && aData[6] == 'y' &&
|
||||||
|
aData[7] == 'p';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -48,9 +48,7 @@ function startTest() {
|
|||||||
|
|
||||||
function checkTrackRemoved() {
|
function checkTrackRemoved() {
|
||||||
if (isPlaying) {
|
if (isPlaying) {
|
||||||
is(audioOnremovetrack, 1, 'Calls of onremovetrack on audioTracks should be 1.');
|
|
||||||
is(element.audioTracks.length, 0, 'The length of audioTracks should be 0.');
|
is(element.audioTracks.length, 0, 'The length of audioTracks should be 0.');
|
||||||
is(videoOnremovetrack, 1, 'Calls of onremovetrack on videoTracks should be 1.');
|
|
||||||
is(element.videoTracks.length, 0, 'The length of videoTracks should be 0.');
|
is(element.videoTracks.length, 0, 'The length of videoTracks should be 0.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6162,6 +6162,35 @@ nsDocShell::ForceRefreshURIFromTimer(nsIURI * aURI,
|
|||||||
return ForceRefreshURI(aURI, aDelay, aMetaRefresh);
|
return ForceRefreshURI(aURI, aDelay, aMetaRefresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
nsDocShell::DoAppRedirectIfNeeded(nsIURI * aURI,
|
||||||
|
nsIDocShellLoadInfo * aLoadInfo,
|
||||||
|
bool aFirstParty)
|
||||||
|
{
|
||||||
|
uint32_t appId;
|
||||||
|
nsresult rv = GetAppId(&appId);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (appId != nsIScriptSecurityManager::NO_APP_ID &&
|
||||||
|
appId != nsIScriptSecurityManager::UNKNOWN_APP_ID) {
|
||||||
|
nsCOMPtr<nsIAppsService> appsService =
|
||||||
|
do_GetService(APPS_SERVICE_CONTRACTID);
|
||||||
|
NS_ASSERTION(appsService, "No AppsService available");
|
||||||
|
nsCOMPtr<nsIURI> redirect;
|
||||||
|
rv = appsService->GetRedirect(appId, aURI, getter_AddRefs(redirect));
|
||||||
|
if (NS_SUCCEEDED(rv) && redirect) {
|
||||||
|
rv = LoadURI(redirect, aLoadInfo, nsIWebNavigation::LOAD_FLAGS_NONE, aFirstParty);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsDocShell::ForceRefreshURI(nsIURI * aURI,
|
nsDocShell::ForceRefreshURI(nsIURI * aURI,
|
||||||
int32_t aDelay,
|
int32_t aDelay,
|
||||||
@ -6215,6 +6244,10 @@ nsDocShell::ForceRefreshURI(nsIURI * aURI,
|
|||||||
loadInfo->SetLoadType(nsIDocShellLoadInfo::loadRefresh);
|
loadInfo->SetLoadType(nsIDocShellLoadInfo::loadRefresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DoAppRedirectIfNeeded(aURI, loadInfo, true)) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* LoadURI(...) will cancel all refresh timers... This causes the
|
* LoadURI(...) will cancel all refresh timers... This causes the
|
||||||
* Timer and its refreshData instance to be released...
|
* Timer and its refreshData instance to be released...
|
||||||
@ -6848,29 +6881,10 @@ nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we have a redirect registered for this url.
|
if (DoAppRedirectIfNeeded(newURI, nullptr, false)) {
|
||||||
uint32_t appId;
|
|
||||||
nsresult rv = GetAppId(&appId);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (appId != nsIScriptSecurityManager::NO_APP_ID &&
|
|
||||||
appId != nsIScriptSecurityManager::UNKNOWN_APP_ID) {
|
|
||||||
nsCOMPtr<nsIAppsService> appsService =
|
|
||||||
do_GetService(APPS_SERVICE_CONTRACTID);
|
|
||||||
NS_ASSERTION(appsService, "No AppsService available");
|
|
||||||
nsCOMPtr<nsIURI> redirect;
|
|
||||||
rv = appsService->GetRedirect(appId, newURI, getter_AddRefs(redirect));
|
|
||||||
if (NS_SUCCEEDED(rv) && redirect) {
|
|
||||||
aNewChannel->Cancel(NS_BINDING_ABORTED);
|
|
||||||
rv = LoadURI(redirect, nullptr, 0, false);
|
|
||||||
if (NS_SUCCEEDED(rv)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Below a URI visit is saved (see AddURIVisit method doc).
|
// Below a URI visit is saved (see AddURIVisit method doc).
|
||||||
// The visit chain looks something like:
|
// The visit chain looks something like:
|
||||||
// ...
|
// ...
|
||||||
|
@ -640,6 +640,12 @@ protected:
|
|||||||
|
|
||||||
// Convenience method for getting our parent docshell. Can return null
|
// Convenience method for getting our parent docshell. Can return null
|
||||||
already_AddRefed<nsDocShell> GetParentDocshell();
|
already_AddRefed<nsDocShell> GetParentDocshell();
|
||||||
|
|
||||||
|
// Check if we have an app redirect registered for the URI and redirect if
|
||||||
|
// needed. Returns true if a redirect happened, false otherwise.
|
||||||
|
bool DoAppRedirectIfNeeded(nsIURI * aURI,
|
||||||
|
nsIDocShellLoadInfo * aLoadInfo,
|
||||||
|
bool aFirstParty);
|
||||||
protected:
|
protected:
|
||||||
nsresult GetCurScrollPos(int32_t scrollOrientation, int32_t * curPos);
|
nsresult GetCurScrollPos(int32_t scrollOrientation, int32_t * curPos);
|
||||||
nsresult SetCurScrollPosEx(int32_t curHorizontalPos, int32_t curVerticalPos);
|
nsresult SetCurScrollPosEx(int32_t curHorizontalPos, int32_t curVerticalPos);
|
||||||
|
@ -186,6 +186,11 @@ DOMInterfaces = {
|
|||||||
'nativeType': 'mozilla::dom::bluetooth::BluetoothPairingHandle',
|
'nativeType': 'mozilla::dom::bluetooth::BluetoothPairingHandle',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'BluetoothPairingListener': {
|
||||||
|
'nativeType':
|
||||||
|
'mozilla::dom::bluetooth::BluetoothPairingListener',
|
||||||
|
},
|
||||||
|
|
||||||
'CameraCapabilities': {
|
'CameraCapabilities': {
|
||||||
'nativeType': 'mozilla::dom::CameraCapabilities',
|
'nativeType': 'mozilla::dom::CameraCapabilities',
|
||||||
'headerFile': 'DOMCameraCapabilities.h'
|
'headerFile': 'DOMCameraCapabilities.h'
|
||||||
@ -353,6 +358,8 @@ DOMInterfaces = {
|
|||||||
'URL': 'documentURIFromJS'
|
'URL': 'documentURIFromJS'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
# Note: we still need the worker descriptor here because
|
||||||
|
# XMLHttpRequest.send() uses it.
|
||||||
{
|
{
|
||||||
'nativeType': 'JSObject',
|
'nativeType': 'JSObject',
|
||||||
'workers': True,
|
'workers': True,
|
||||||
@ -822,14 +829,10 @@ DOMInterfaces = {
|
|||||||
'nativeType': 'mozilla::dom::HTMLCanvasPrintState',
|
'nativeType': 'mozilla::dom::HTMLCanvasPrintState',
|
||||||
},
|
},
|
||||||
|
|
||||||
'MozChannel': [
|
'MozChannel': {
|
||||||
{
|
|
||||||
'nativeType': 'nsIChannel',
|
'nativeType': 'nsIChannel',
|
||||||
'notflattened': True
|
'notflattened': True
|
||||||
},
|
},
|
||||||
{
|
|
||||||
'workers': True,
|
|
||||||
}],
|
|
||||||
|
|
||||||
'MozCellBroadcast': {
|
'MozCellBroadcast': {
|
||||||
'nativeType': 'mozilla::dom::CellBroadcast',
|
'nativeType': 'mozilla::dom::CellBroadcast',
|
||||||
|
@ -78,9 +78,7 @@ def idlTypeNeedsCycleCollection(type):
|
|||||||
|
|
||||||
|
|
||||||
def wantsAddProperty(desc):
|
def wantsAddProperty(desc):
|
||||||
return (desc.concrete and
|
return (desc.concrete and desc.wrapperCache and not desc.isGlobal())
|
||||||
desc.wrapperCache and
|
|
||||||
not desc.interface.getExtendedAttribute("Global"))
|
|
||||||
|
|
||||||
|
|
||||||
# We'll want to insert the indent at the beginnings of lines, but we
|
# We'll want to insert the indent at the beginnings of lines, but we
|
||||||
@ -372,7 +370,7 @@ class CGDOMJSClass(CGThing):
|
|||||||
JS_NULL_CLASS_EXT,
|
JS_NULL_CLASS_EXT,
|
||||||
JS_NULL_OBJECT_OPS
|
JS_NULL_OBJECT_OPS
|
||||||
"""
|
"""
|
||||||
if self.descriptor.interface.getExtendedAttribute("Global"):
|
if self.descriptor.isGlobal():
|
||||||
classFlags += "JSCLASS_DOM_GLOBAL | JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(DOM_GLOBAL_SLOTS) | JSCLASS_IMPLEMENTS_BARRIERS"
|
classFlags += "JSCLASS_DOM_GLOBAL | JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(DOM_GLOBAL_SLOTS) | JSCLASS_IMPLEMENTS_BARRIERS"
|
||||||
traceHook = "JS_GlobalObjectTraceHook"
|
traceHook = "JS_GlobalObjectTraceHook"
|
||||||
reservedSlots = "JSCLASS_GLOBAL_APPLICATION_SLOTS"
|
reservedSlots = "JSCLASS_GLOBAL_APPLICATION_SLOTS"
|
||||||
@ -415,7 +413,7 @@ JS_NULL_OBJECT_OPS
|
|||||||
newResolveHook = "(JSResolveOp)" + NEWRESOLVE_HOOK_NAME
|
newResolveHook = "(JSResolveOp)" + NEWRESOLVE_HOOK_NAME
|
||||||
classFlags += " | JSCLASS_NEW_RESOLVE"
|
classFlags += " | JSCLASS_NEW_RESOLVE"
|
||||||
enumerateHook = ENUMERATE_HOOK_NAME
|
enumerateHook = ENUMERATE_HOOK_NAME
|
||||||
elif self.descriptor.interface.getExtendedAttribute("Global"):
|
elif self.descriptor.isGlobal():
|
||||||
newResolveHook = "(JSResolveOp) mozilla::dom::ResolveGlobal"
|
newResolveHook = "(JSResolveOp) mozilla::dom::ResolveGlobal"
|
||||||
classFlags += " | JSCLASS_NEW_RESOLVE"
|
classFlags += " | JSCLASS_NEW_RESOLVE"
|
||||||
enumerateHook = "mozilla::dom::EnumerateGlobal"
|
enumerateHook = "mozilla::dom::EnumerateGlobal"
|
||||||
@ -1521,7 +1519,7 @@ def finalizeHook(descriptor, hookName, freeOp):
|
|||||||
finalize += "ClearWrapper(self, self);\n"
|
finalize += "ClearWrapper(self, self);\n"
|
||||||
if descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
|
if descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
|
||||||
finalize += "self->mExpandoAndGeneration.expando = JS::UndefinedValue();\n"
|
finalize += "self->mExpandoAndGeneration.expando = JS::UndefinedValue();\n"
|
||||||
if descriptor.interface.getExtendedAttribute("Global"):
|
if descriptor.isGlobal():
|
||||||
finalize += "mozilla::dom::FinalizeGlobal(CastToJSFreeOp(%s), obj);\n" % freeOp
|
finalize += "mozilla::dom::FinalizeGlobal(CastToJSFreeOp(%s), obj);\n" % freeOp
|
||||||
finalize += ("AddForDeferredFinalization<%s, %s >(self);\n" %
|
finalize += ("AddForDeferredFinalization<%s, %s >(self);\n" %
|
||||||
(descriptor.nativeType, DeferredFinalizeSmartPtr(descriptor)))
|
(descriptor.nativeType, DeferredFinalizeSmartPtr(descriptor)))
|
||||||
@ -2034,6 +2032,11 @@ def methodLength(method):
|
|||||||
return min(overloadLength(arguments) for retType, arguments in signatures)
|
return min(overloadLength(arguments) for retType, arguments in signatures)
|
||||||
|
|
||||||
|
|
||||||
|
def isMaybeExposedIn(member, descriptor):
|
||||||
|
# All we can say for sure is that if this is a worker descriptor
|
||||||
|
# and member is only exposed in windows, then it's not exposed.
|
||||||
|
return not descriptor.workers or member.exposureSet != set(["Window"])
|
||||||
|
|
||||||
class MethodDefiner(PropertyDefiner):
|
class MethodDefiner(PropertyDefiner):
|
||||||
"""
|
"""
|
||||||
A class for defining methods on a prototype object.
|
A class for defining methods on a prototype object.
|
||||||
@ -2051,7 +2054,8 @@ class MethodDefiner(PropertyDefiner):
|
|||||||
methods = [m for m in descriptor.interface.members if
|
methods = [m for m in descriptor.interface.members if
|
||||||
m.isMethod() and m.isStatic() == static and
|
m.isMethod() and m.isStatic() == static and
|
||||||
MemberIsUnforgeable(m, descriptor) == unforgeable and
|
MemberIsUnforgeable(m, descriptor) == unforgeable and
|
||||||
not m.isIdentifierLess()]
|
not m.isIdentifierLess() and
|
||||||
|
isMaybeExposedIn(m, descriptor)]
|
||||||
else:
|
else:
|
||||||
methods = []
|
methods = []
|
||||||
self.chrome = []
|
self.chrome = []
|
||||||
@ -2265,7 +2269,8 @@ class AttrDefiner(PropertyDefiner):
|
|||||||
if descriptor.interface.hasInterfacePrototypeObject() or static:
|
if descriptor.interface.hasInterfacePrototypeObject() or static:
|
||||||
attributes = [m for m in descriptor.interface.members if
|
attributes = [m for m in descriptor.interface.members if
|
||||||
m.isAttr() and m.isStatic() == static and
|
m.isAttr() and m.isStatic() == static and
|
||||||
MemberIsUnforgeable(m, descriptor) == unforgeable]
|
MemberIsUnforgeable(m, descriptor) == unforgeable and
|
||||||
|
isMaybeExposedIn(m, descriptor)]
|
||||||
else:
|
else:
|
||||||
attributes = []
|
attributes = []
|
||||||
self.chrome = [m for m in attributes if isChromeOnly(m)]
|
self.chrome = [m for m in attributes if isChromeOnly(m)]
|
||||||
@ -2348,7 +2353,8 @@ class ConstDefiner(PropertyDefiner):
|
|||||||
def __init__(self, descriptor, name):
|
def __init__(self, descriptor, name):
|
||||||
PropertyDefiner.__init__(self, descriptor, name)
|
PropertyDefiner.__init__(self, descriptor, name)
|
||||||
self.name = name
|
self.name = name
|
||||||
constants = [m for m in descriptor.interface.members if m.isConst()]
|
constants = [m for m in descriptor.interface.members if m.isConst() and
|
||||||
|
isMaybeExposedIn(m, descriptor)]
|
||||||
self.chrome = [m for m in constants if isChromeOnly(m)]
|
self.chrome = [m for m in constants if isChromeOnly(m)]
|
||||||
self.regular = [m for m in constants if not isChromeOnly(m)]
|
self.regular = [m for m in constants if not isChromeOnly(m)]
|
||||||
|
|
||||||
@ -2599,7 +2605,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
|||||||
interfaceClass = "nullptr"
|
interfaceClass = "nullptr"
|
||||||
interfaceCache = "nullptr"
|
interfaceCache = "nullptr"
|
||||||
|
|
||||||
isGlobal = self.descriptor.interface.getExtendedAttribute("Global") is not None
|
isGlobal = self.descriptor.isGlobal() is not None
|
||||||
if not isGlobal and self.properties.hasNonChromeOnly():
|
if not isGlobal and self.properties.hasNonChromeOnly():
|
||||||
properties = "&sNativeProperties"
|
properties = "&sNativeProperties"
|
||||||
elif self.properties.hasNonChromeOnly():
|
elif self.properties.hasNonChromeOnly():
|
||||||
@ -7323,7 +7329,7 @@ class CGNewResolveHook(CGAbstractBindingMethod):
|
|||||||
"""))
|
"""))
|
||||||
|
|
||||||
def definition_body(self):
|
def definition_body(self):
|
||||||
if self.descriptor.interface.getExtendedAttribute("Global"):
|
if self.descriptor.isGlobal():
|
||||||
# Resolve standard classes
|
# Resolve standard classes
|
||||||
prefix = dedent("""
|
prefix = dedent("""
|
||||||
if (!ResolveGlobal(cx, obj, id, objp)) {
|
if (!ResolveGlobal(cx, obj, id, objp)) {
|
||||||
@ -7372,7 +7378,7 @@ class CGEnumerateHook(CGAbstractBindingMethod):
|
|||||||
"""))
|
"""))
|
||||||
|
|
||||||
def definition_body(self):
|
def definition_body(self):
|
||||||
if self.descriptor.interface.getExtendedAttribute("Global"):
|
if self.descriptor.isGlobal():
|
||||||
# Enumerate standard classes
|
# Enumerate standard classes
|
||||||
prefix = dedent("""
|
prefix = dedent("""
|
||||||
if (!EnumerateGlobal(cx, obj)) {
|
if (!EnumerateGlobal(cx, obj)) {
|
||||||
@ -10471,6 +10477,8 @@ class CGDescriptor(CGThing):
|
|||||||
for m in descriptor.interface.members:
|
for m in descriptor.interface.members:
|
||||||
if m.isMethod() and m.identifier.name == 'queryInterface':
|
if m.isMethod() and m.identifier.name == 'queryInterface':
|
||||||
continue
|
continue
|
||||||
|
if not isMaybeExposedIn(m, descriptor):
|
||||||
|
continue
|
||||||
if m.isMethod() and m == descriptor.operations['Jsonifier']:
|
if m.isMethod() and m == descriptor.operations['Jsonifier']:
|
||||||
hasJsonifier = True
|
hasJsonifier = True
|
||||||
hasMethod = descriptor.needsSpecialGenericOps()
|
hasMethod = descriptor.needsSpecialGenericOps()
|
||||||
@ -10626,9 +10634,7 @@ class CGDescriptor(CGThing):
|
|||||||
|
|
||||||
if ((descriptor.interface.hasInterfaceObject() or descriptor.interface.getNavigatorProperty()) and
|
if ((descriptor.interface.hasInterfaceObject() or descriptor.interface.getNavigatorProperty()) and
|
||||||
not descriptor.interface.isExternal() and
|
not descriptor.interface.isExternal() and
|
||||||
descriptor.isExposedConditionally() and
|
descriptor.isExposedConditionally()):
|
||||||
# Workers stuff is never conditional
|
|
||||||
not descriptor.workers):
|
|
||||||
cgThings.append(CGConstructorEnabled(descriptor))
|
cgThings.append(CGConstructorEnabled(descriptor))
|
||||||
|
|
||||||
if (descriptor.interface.hasMembersInSlots() and
|
if (descriptor.interface.hasMembersInSlots() and
|
||||||
@ -10666,7 +10672,7 @@ class CGDescriptor(CGThing):
|
|||||||
if descriptor.interface.hasMembersInSlots():
|
if descriptor.interface.hasMembersInSlots():
|
||||||
cgThings.append(CGUpdateMemberSlotsMethod(descriptor))
|
cgThings.append(CGUpdateMemberSlotsMethod(descriptor))
|
||||||
|
|
||||||
if descriptor.interface.getExtendedAttribute("Global"):
|
if descriptor.isGlobal():
|
||||||
assert descriptor.wrapperCache
|
assert descriptor.wrapperCache
|
||||||
cgThings.append(CGWrapGlobalMethod(descriptor, properties))
|
cgThings.append(CGWrapGlobalMethod(descriptor, properties))
|
||||||
elif descriptor.wrapperCache:
|
elif descriptor.wrapperCache:
|
||||||
@ -11325,6 +11331,48 @@ class CGDictionary(CGThing):
|
|||||||
return all(isTypeCopyConstructible(m.type) for m in dictionary.members)
|
return all(isTypeCopyConstructible(m.type) for m in dictionary.members)
|
||||||
|
|
||||||
|
|
||||||
|
class CGRegisterWorkerBindings(CGAbstractMethod):
|
||||||
|
def __init__(self, config):
|
||||||
|
CGAbstractMethod.__init__(self, None, 'RegisterWorkerBindings', 'bool',
|
||||||
|
[Argument('JSContext*', 'aCx'),
|
||||||
|
Argument('JS::Handle<JSObject*>', 'aObj')])
|
||||||
|
self.config = config
|
||||||
|
|
||||||
|
def definition_body(self):
|
||||||
|
# We have to be a bit careful: Some of the interfaces we want to expose
|
||||||
|
# in workers only have one descriptor, while others have both a worker
|
||||||
|
# and a non-worker descriptor. When both are present we want the worker
|
||||||
|
# descriptor, but otherwise we want whatever descriptor we've got.
|
||||||
|
descriptors = self.config.getDescriptors(hasInterfaceObject=True,
|
||||||
|
isExposedInAllWorkers=True,
|
||||||
|
register=True,
|
||||||
|
skipGen=False,
|
||||||
|
workers=True)
|
||||||
|
workerDescriptorIfaceNames = set(d.interface.identifier.name for
|
||||||
|
d in descriptors)
|
||||||
|
descriptors.extend(
|
||||||
|
filter(
|
||||||
|
lambda d: d.interface.identifier.name not in workerDescriptorIfaceNames,
|
||||||
|
self.config.getDescriptors(hasInterfaceObject=True,
|
||||||
|
isExposedInAllWorkers=True,
|
||||||
|
register=True,
|
||||||
|
skipGen=False,
|
||||||
|
workers=False)))
|
||||||
|
conditions = []
|
||||||
|
for desc in descriptors:
|
||||||
|
bindingNS = toBindingNamespace(desc.name)
|
||||||
|
condition = "!%s::GetConstructorObject(aCx, aObj)" % bindingNS
|
||||||
|
if desc.isExposedConditionally():
|
||||||
|
condition = (
|
||||||
|
"%s::ConstructorEnabled(aCx, aObj) && " % bindingNS
|
||||||
|
+ condition)
|
||||||
|
conditions.append(condition)
|
||||||
|
lines = [CGIfWrapper(CGGeneric("return false;\n"), condition) for
|
||||||
|
condition in conditions]
|
||||||
|
lines.append(CGGeneric("return true;\n"))
|
||||||
|
return CGList(lines, "\n").define()
|
||||||
|
|
||||||
|
|
||||||
class CGRegisterProtos(CGAbstractMethod):
|
class CGRegisterProtos(CGAbstractMethod):
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
CGAbstractMethod.__init__(self, None, 'Register', 'void',
|
CGAbstractMethod.__init__(self, None, 'Register', 'void',
|
||||||
@ -13716,6 +13764,33 @@ class GlobalGenRoots():
|
|||||||
# Done.
|
# Done.
|
||||||
return curr
|
return curr
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def RegisterWorkerBindings(config):
|
||||||
|
|
||||||
|
# TODO - Generate the methods we want
|
||||||
|
curr = CGRegisterWorkerBindings(config)
|
||||||
|
|
||||||
|
# Wrap all of that in our namespaces.
|
||||||
|
curr = CGNamespace.build(['mozilla', 'dom'],
|
||||||
|
CGWrapper(curr, post='\n'))
|
||||||
|
curr = CGWrapper(curr, post='\n')
|
||||||
|
|
||||||
|
# Add the includes
|
||||||
|
defineIncludes = [CGHeaders.getDeclarationFilename(desc.interface)
|
||||||
|
for desc in config.getDescriptors(hasInterfaceObject=True,
|
||||||
|
register=True,
|
||||||
|
isExposedInAllWorkers=True,
|
||||||
|
skipGen=False)]
|
||||||
|
|
||||||
|
curr = CGHeaders([], [], [], [], [], defineIncludes,
|
||||||
|
'RegisterWorkerBindings', curr)
|
||||||
|
|
||||||
|
# Add include guards.
|
||||||
|
curr = CGIncludeGuard('RegisterWorkerBindings', curr)
|
||||||
|
|
||||||
|
# Done.
|
||||||
|
return curr
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def UnionTypes(config):
|
def UnionTypes(config):
|
||||||
|
|
||||||
|
@ -138,6 +138,8 @@ class Configuration:
|
|||||||
getter = lambda x: x.interface.isJSImplemented()
|
getter = lambda x: x.interface.isJSImplemented()
|
||||||
elif key == 'isNavigatorProperty':
|
elif key == 'isNavigatorProperty':
|
||||||
getter = lambda x: x.interface.getNavigatorProperty() != None
|
getter = lambda x: x.interface.getNavigatorProperty() != None
|
||||||
|
elif key == 'isExposedInAllWorkers':
|
||||||
|
getter = lambda x: not x.interface.isExternal() and "Worker" in x.interface._exposureGlobalNames
|
||||||
else:
|
else:
|
||||||
# Have to watch out: just closing over "key" is not enough,
|
# Have to watch out: just closing over "key" is not enough,
|
||||||
# since we're about to mutate its value
|
# since we're about to mutate its value
|
||||||
@ -563,6 +565,14 @@ class Descriptor(DescriptorProvider):
|
|||||||
"""
|
"""
|
||||||
return self.hasXPConnectImpls or self.interface.isOnGlobalProtoChain()
|
return self.hasXPConnectImpls or self.interface.isOnGlobalProtoChain()
|
||||||
|
|
||||||
|
def isGlobal(self):
|
||||||
|
"""
|
||||||
|
Returns true if this is the primary interface for a global object
|
||||||
|
of some sort.
|
||||||
|
"""
|
||||||
|
return (self.interface.getExtendedAttribute("Global") or
|
||||||
|
self.interface.getExtendedAttribute("PrimaryGlobal"))
|
||||||
|
|
||||||
# Some utility methods
|
# Some utility methods
|
||||||
def getTypesFromDescriptor(descriptor):
|
def getTypesFromDescriptor(descriptor):
|
||||||
"""
|
"""
|
||||||
|
@ -131,6 +131,7 @@ class WebIDLCodegenManager(LoggingMixin):
|
|||||||
'GeneratedAtomList.h',
|
'GeneratedAtomList.h',
|
||||||
'PrototypeList.h',
|
'PrototypeList.h',
|
||||||
'RegisterBindings.h',
|
'RegisterBindings.h',
|
||||||
|
'RegisterWorkerBindings.h',
|
||||||
'UnionConversions.h',
|
'UnionConversions.h',
|
||||||
'UnionTypes.h',
|
'UnionTypes.h',
|
||||||
}
|
}
|
||||||
@ -138,6 +139,7 @@ class WebIDLCodegenManager(LoggingMixin):
|
|||||||
# Global parser derived definition files.
|
# Global parser derived definition files.
|
||||||
GLOBAL_DEFINE_FILES = {
|
GLOBAL_DEFINE_FILES = {
|
||||||
'RegisterBindings.cpp',
|
'RegisterBindings.cpp',
|
||||||
|
'RegisterWorkerBindings.cpp',
|
||||||
'UnionTypes.cpp',
|
'UnionTypes.cpp',
|
||||||
'PrototypeList.cpp',
|
'PrototypeList.cpp',
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import re
|
|||||||
import os
|
import os
|
||||||
import traceback
|
import traceback
|
||||||
import math
|
import math
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
# Machinery
|
# Machinery
|
||||||
|
|
||||||
@ -219,6 +220,12 @@ class IDLScope(IDLObject):
|
|||||||
self._name = None
|
self._name = None
|
||||||
|
|
||||||
self._dict = {}
|
self._dict = {}
|
||||||
|
self.globalNames = set()
|
||||||
|
# A mapping from global name to the set of global interfaces
|
||||||
|
# that have that global name.
|
||||||
|
self.globalNameMapping = defaultdict(set)
|
||||||
|
self.primaryGlobalAttr = None
|
||||||
|
self.primaryGlobalName = None
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.QName()
|
return self.QName()
|
||||||
@ -482,24 +489,85 @@ class IDLExternalInterface(IDLObjectWithIdentifier):
|
|||||||
def _getDependentObjects(self):
|
def _getDependentObjects(self):
|
||||||
return set()
|
return set()
|
||||||
|
|
||||||
|
class IDLPartialInterface(IDLObject):
|
||||||
|
def __init__(self, location, name, members, nonPartialInterface):
|
||||||
|
assert isinstance(name, IDLUnresolvedIdentifier)
|
||||||
|
|
||||||
|
IDLObject.__init__(self, location)
|
||||||
|
self.identifier = name
|
||||||
|
self.members = members
|
||||||
|
# propagatedExtendedAttrs are the ones that should get
|
||||||
|
# propagated to our non-partial interface.
|
||||||
|
self.propagatedExtendedAttrs = []
|
||||||
|
self._nonPartialInterface = nonPartialInterface
|
||||||
|
self._finished = False
|
||||||
|
nonPartialInterface.addPartialInterface(self)
|
||||||
|
|
||||||
|
def addExtendedAttributes(self, attrs):
|
||||||
|
for attr in attrs:
|
||||||
|
identifier = attr.identifier()
|
||||||
|
|
||||||
|
if identifier in ["Constructor", "NamedConstructor"]:
|
||||||
|
self.propagatedExtendedAttrs.append(attr)
|
||||||
|
elif identifier == "Exposed":
|
||||||
|
# This just gets propagated to all our members.
|
||||||
|
for member in self.members:
|
||||||
|
if len(member._exposureGlobalNames) != 0:
|
||||||
|
raise WebIDLError("[Exposed] specified on both a "
|
||||||
|
"partial interface member and on the "
|
||||||
|
"partial interface itself",
|
||||||
|
[member.location, attr.location])
|
||||||
|
member.addExtendedAttributes([attr])
|
||||||
|
else:
|
||||||
|
raise WebIDLError("Unknown extended attribute %s on partial "
|
||||||
|
"interface" % identifier,
|
||||||
|
[attr.location])
|
||||||
|
|
||||||
|
def finish(self, scope):
|
||||||
|
if self._finished:
|
||||||
|
return
|
||||||
|
self._finished = True
|
||||||
|
# Need to make sure our non-partial interface gets finished so it can
|
||||||
|
# report cases when we only have partial interfaces.
|
||||||
|
self._nonPartialInterface.finish(scope)
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def convertExposedAttrToGlobalNameSet(exposedAttr, targetSet):
|
||||||
|
assert len(targetSet) == 0
|
||||||
|
if exposedAttr.hasValue():
|
||||||
|
targetSet.add(exposedAttr.value())
|
||||||
|
else:
|
||||||
|
assert exposedAttr.hasArgs()
|
||||||
|
targetSet.update(exposedAttr.args())
|
||||||
|
|
||||||
|
def globalNameSetToExposureSet(globalScope, nameSet, exposureSet):
|
||||||
|
for name in nameSet:
|
||||||
|
exposureSet.update(globalScope.globalNameMapping[name])
|
||||||
|
|
||||||
class IDLInterface(IDLObjectWithScope):
|
class IDLInterface(IDLObjectWithScope):
|
||||||
def __init__(self, location, parentScope, name, parent, members,
|
def __init__(self, location, parentScope, name, parent, members,
|
||||||
isPartial):
|
isKnownNonPartial):
|
||||||
assert isinstance(parentScope, IDLScope)
|
assert isinstance(parentScope, IDLScope)
|
||||||
assert isinstance(name, IDLUnresolvedIdentifier)
|
assert isinstance(name, IDLUnresolvedIdentifier)
|
||||||
assert not isPartial or not parent
|
assert isKnownNonPartial or not parent
|
||||||
|
assert isKnownNonPartial or len(members) == 0
|
||||||
|
|
||||||
self.parent = None
|
self.parent = None
|
||||||
self._callback = False
|
self._callback = False
|
||||||
self._finished = False
|
self._finished = False
|
||||||
self.members = []
|
self.members = []
|
||||||
|
self._partialInterfaces = []
|
||||||
|
self._extendedAttrDict = {}
|
||||||
# namedConstructors needs deterministic ordering because bindings code
|
# namedConstructors needs deterministic ordering because bindings code
|
||||||
# outputs the constructs in the order that namedConstructors enumerates
|
# outputs the constructs in the order that namedConstructors enumerates
|
||||||
# them.
|
# them.
|
||||||
self.namedConstructors = list()
|
self.namedConstructors = list()
|
||||||
self.implementedInterfaces = set()
|
self.implementedInterfaces = set()
|
||||||
self._consequential = False
|
self._consequential = False
|
||||||
self._isPartial = True
|
self._isKnownNonPartial = False
|
||||||
# self.interfacesBasedOnSelf is the set of interfaces that inherit from
|
# self.interfacesBasedOnSelf is the set of interfaces that inherit from
|
||||||
# self or have self as a consequential interface, including self itself.
|
# self or have self as a consequential interface, including self itself.
|
||||||
# Used for distinguishability checking.
|
# Used for distinguishability checking.
|
||||||
@ -514,14 +582,16 @@ class IDLInterface(IDLObjectWithScope):
|
|||||||
self.totalMembersInSlots = 0
|
self.totalMembersInSlots = 0
|
||||||
# Tracking of the number of own own members we have in slots
|
# Tracking of the number of own own members we have in slots
|
||||||
self._ownMembersInSlots = 0
|
self._ownMembersInSlots = 0
|
||||||
|
# _exposureGlobalNames are the global names listed in our [Exposed]
|
||||||
|
# extended attribute. exposureSet is the exposure set as defined in the
|
||||||
|
# Web IDL spec: it contains interface names.
|
||||||
|
self._exposureGlobalNames = set()
|
||||||
|
self.exposureSet = set()
|
||||||
|
|
||||||
IDLObjectWithScope.__init__(self, location, parentScope, name)
|
IDLObjectWithScope.__init__(self, location, parentScope, name)
|
||||||
|
|
||||||
if not isPartial:
|
if isKnownNonPartial:
|
||||||
self.setNonPartial(location, parent, members)
|
self.setNonPartial(location, parent, members)
|
||||||
else:
|
|
||||||
# Just remember our members for now
|
|
||||||
self.members = members
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "Interface '%s'" % self.identifier.name
|
return "Interface '%s'" % self.identifier.name
|
||||||
@ -553,11 +623,42 @@ class IDLInterface(IDLObjectWithScope):
|
|||||||
|
|
||||||
self._finished = True
|
self._finished = True
|
||||||
|
|
||||||
if self._isPartial:
|
if not self._isKnownNonPartial:
|
||||||
raise WebIDLError("Interface %s does not have a non-partial "
|
raise WebIDLError("Interface %s does not have a non-partial "
|
||||||
"declaration" % self.identifier.name,
|
"declaration" % self.identifier.name,
|
||||||
[self.location])
|
[self.location])
|
||||||
|
|
||||||
|
# Verify that our [Exposed] value, if any, makes sense.
|
||||||
|
for globalName in self._exposureGlobalNames:
|
||||||
|
if globalName not in scope.globalNames:
|
||||||
|
raise WebIDLError("Unknown [Exposed] value %s" % globalName,
|
||||||
|
[self.location])
|
||||||
|
|
||||||
|
if len(self._exposureGlobalNames) == 0:
|
||||||
|
self._exposureGlobalNames.add(scope.primaryGlobalName)
|
||||||
|
|
||||||
|
globalNameSetToExposureSet(scope, self._exposureGlobalNames,
|
||||||
|
self.exposureSet)
|
||||||
|
|
||||||
|
# Now go ahead and merge in our partial interfaces.
|
||||||
|
for partial in self._partialInterfaces:
|
||||||
|
partial.finish(scope)
|
||||||
|
self.addExtendedAttributes(partial.propagatedExtendedAttrs)
|
||||||
|
self.members.extend(partial.members)
|
||||||
|
|
||||||
|
# Now that we've merged in our partial interfaces, set the
|
||||||
|
# _exposureGlobalNames on any members that don't have it set yet. Note
|
||||||
|
# that any partial interfaces that had [Exposed] set have already set up
|
||||||
|
# _exposureGlobalNames on all the members coming from them, so this is
|
||||||
|
# just implementing the "members default to interface that defined them"
|
||||||
|
# and "partial interfaces default to interface they're a partial for"
|
||||||
|
# rules from the spec.
|
||||||
|
for m in self.members:
|
||||||
|
# If m, or the partial interface m came from, had [Exposed]
|
||||||
|
# specified, it already has a nonempty exposure global names set.
|
||||||
|
if len(m._exposureGlobalNames) == 0:
|
||||||
|
m._exposureGlobalNames.update(self._exposureGlobalNames)
|
||||||
|
|
||||||
assert not self.parent or isinstance(self.parent, IDLIdentifierPlaceholder)
|
assert not self.parent or isinstance(self.parent, IDLIdentifierPlaceholder)
|
||||||
parent = self.parent.finish(scope) if self.parent else None
|
parent = self.parent.finish(scope) if self.parent else None
|
||||||
if parent and isinstance(parent, IDLExternalInterface):
|
if parent and isinstance(parent, IDLExternalInterface):
|
||||||
@ -595,8 +696,10 @@ class IDLInterface(IDLObjectWithScope):
|
|||||||
|
|
||||||
self.totalMembersInSlots = self.parent.totalMembersInSlots
|
self.totalMembersInSlots = self.parent.totalMembersInSlots
|
||||||
|
|
||||||
# Interfaces with [Global] must not have anything inherit from them
|
# Interfaces with [Global] or [PrimaryGlobal] must not
|
||||||
if self.parent.getExtendedAttribute("Global"):
|
# have anything inherit from them
|
||||||
|
if (self.parent.getExtendedAttribute("Global") or
|
||||||
|
self.parent.getExtendedAttribute("PrimaryGlobal")):
|
||||||
# Note: This is not a self.parent.isOnGlobalProtoChain() check
|
# Note: This is not a self.parent.isOnGlobalProtoChain() check
|
||||||
# because ancestors of a [Global] interface can have other
|
# because ancestors of a [Global] interface can have other
|
||||||
# descendants.
|
# descendants.
|
||||||
@ -604,6 +707,14 @@ class IDLInterface(IDLObjectWithScope):
|
|||||||
"inheriting from it",
|
"inheriting from it",
|
||||||
[self.location, self.parent.location])
|
[self.location, self.parent.location])
|
||||||
|
|
||||||
|
# Make sure that we're not exposed in places where our parent is not
|
||||||
|
if not self.exposureSet.issubset(self.parent.exposureSet):
|
||||||
|
raise WebIDLError("Interface %s is exposed in globals where its "
|
||||||
|
"parent interface %s is not exposed." %
|
||||||
|
(self.identifier.name,
|
||||||
|
self.parent.identifier.name),
|
||||||
|
[self.location, self.parent.location])
|
||||||
|
|
||||||
# Callbacks must not inherit from non-callbacks or inherit from
|
# Callbacks must not inherit from non-callbacks or inherit from
|
||||||
# anything that has consequential interfaces.
|
# anything that has consequential interfaces.
|
||||||
# XXXbz Can non-callbacks inherit from callbacks? Spec issue pending.
|
# XXXbz Can non-callbacks inherit from callbacks? Spec issue pending.
|
||||||
@ -649,6 +760,14 @@ class IDLInterface(IDLObjectWithScope):
|
|||||||
for member in self.members:
|
for member in self.members:
|
||||||
member.finish(scope)
|
member.finish(scope)
|
||||||
|
|
||||||
|
# Now that we've finished our members, which has updated their exposure
|
||||||
|
# sets, make sure they aren't exposed in places where we are not.
|
||||||
|
for member in self.members:
|
||||||
|
if not member.exposureSet.issubset(self.exposureSet):
|
||||||
|
raise WebIDLError("Interface member has larger exposure set "
|
||||||
|
"than the interface itself",
|
||||||
|
[member.location, self.location])
|
||||||
|
|
||||||
ctor = self.ctor()
|
ctor = self.ctor()
|
||||||
if ctor is not None:
|
if ctor is not None:
|
||||||
ctor.finish(scope)
|
ctor.finish(scope)
|
||||||
@ -669,6 +788,12 @@ class IDLInterface(IDLObjectWithScope):
|
|||||||
key=lambda x: x.identifier.name):
|
key=lambda x: x.identifier.name):
|
||||||
# Flag the interface as being someone's consequential interface
|
# Flag the interface as being someone's consequential interface
|
||||||
iface.setIsConsequentialInterfaceOf(self)
|
iface.setIsConsequentialInterfaceOf(self)
|
||||||
|
# Verify that we're not exposed somewhere where iface is not exposed
|
||||||
|
if not self.exposureSet.issubset(iface.exposureSet):
|
||||||
|
raise WebIDLError("Interface %s is exposed in globals where its "
|
||||||
|
"consequential interface %s is not exposed." %
|
||||||
|
(self.identifier.name, iface.identifier.name),
|
||||||
|
[self.location, iface.location])
|
||||||
additionalMembers = iface.originalMembers;
|
additionalMembers = iface.originalMembers;
|
||||||
for additionalMember in additionalMembers:
|
for additionalMember in additionalMembers:
|
||||||
for member in self.members:
|
for member in self.members:
|
||||||
@ -891,6 +1016,12 @@ class IDLInterface(IDLObjectWithScope):
|
|||||||
attr = fowardAttr
|
attr = fowardAttr
|
||||||
putForwards = attr.getExtendedAttribute("PutForwards")
|
putForwards = attr.getExtendedAttribute("PutForwards")
|
||||||
|
|
||||||
|
if (self.getExtendedAttribute("Pref") and
|
||||||
|
self._exposureGlobalNames != set([self.parentScope.primaryGlobalName])):
|
||||||
|
raise WebIDLError("[Pref] used on an member that is not %s-only" %
|
||||||
|
self.parentScope.primaryGlobalName,
|
||||||
|
[self.location])
|
||||||
|
|
||||||
|
|
||||||
def isInterface(self):
|
def isInterface(self):
|
||||||
return True
|
return True
|
||||||
@ -948,7 +1079,6 @@ class IDLInterface(IDLObjectWithScope):
|
|||||||
return not self.isCallback() and self.getUserData('hasConcreteDescendant', False)
|
return not self.isCallback() and self.getUserData('hasConcreteDescendant', False)
|
||||||
|
|
||||||
def addExtendedAttributes(self, attrs):
|
def addExtendedAttributes(self, attrs):
|
||||||
self._extendedAttrDict = {}
|
|
||||||
for attr in attrs:
|
for attr in attrs:
|
||||||
identifier = attr.identifier()
|
identifier = attr.identifier()
|
||||||
|
|
||||||
@ -1049,9 +1179,29 @@ class IDLInterface(IDLObjectWithScope):
|
|||||||
"an interface with inherited interfaces",
|
"an interface with inherited interfaces",
|
||||||
[attr.location, self.location])
|
[attr.location, self.location])
|
||||||
elif identifier == "Global":
|
elif identifier == "Global":
|
||||||
|
if attr.hasValue():
|
||||||
|
self.globalNames = [ attr.value() ]
|
||||||
|
elif attr.hasArgs():
|
||||||
|
self.globalNames = attr.args()
|
||||||
|
else:
|
||||||
|
self.globalNames = [ self.identifier.name ]
|
||||||
|
self.parentScope.globalNames.update(self.globalNames)
|
||||||
|
for globalName in self.globalNames:
|
||||||
|
self.parentScope.globalNameMapping[globalName].add(self.identifier.name)
|
||||||
|
self._isOnGlobalProtoChain = True
|
||||||
|
elif identifier == "PrimaryGlobal":
|
||||||
if not attr.noArguments():
|
if not attr.noArguments():
|
||||||
raise WebIDLError("[Global] must take no arguments",
|
raise WebIDLError("[PrimaryGlobal] must take no arguments",
|
||||||
[attr.location])
|
[attr.location])
|
||||||
|
if self.parentScope.primaryGlobalAttr is not None:
|
||||||
|
raise WebIDLError(
|
||||||
|
"[PrimaryGlobal] specified twice",
|
||||||
|
[attr.location,
|
||||||
|
self.parentScope.primaryGlobalAttr.location])
|
||||||
|
self.parentScope.primaryGlobalAttr = attr
|
||||||
|
self.parentScope.primaryGlobalName = self.identifier.name
|
||||||
|
self.parentScope.globalNames.add(self.identifier.name)
|
||||||
|
self.parentScope.globalNameMapping[self.identifier.name].add(self.identifier.name)
|
||||||
self._isOnGlobalProtoChain = True
|
self._isOnGlobalProtoChain = True
|
||||||
elif (identifier == "NeedNewResolve" or
|
elif (identifier == "NeedNewResolve" or
|
||||||
identifier == "OverrideBuiltins" or
|
identifier == "OverrideBuiltins" or
|
||||||
@ -1063,6 +1213,9 @@ class IDLInterface(IDLObjectWithScope):
|
|||||||
if not attr.noArguments():
|
if not attr.noArguments():
|
||||||
raise WebIDLError("[%s] must take no arguments" % identifier,
|
raise WebIDLError("[%s] must take no arguments" % identifier,
|
||||||
[attr.location])
|
[attr.location])
|
||||||
|
elif identifier == "Exposed":
|
||||||
|
convertExposedAttrToGlobalNameSet(attr,
|
||||||
|
self._exposureGlobalNames)
|
||||||
elif (identifier == "Pref" or
|
elif (identifier == "Pref" or
|
||||||
identifier == "JSImplementation" or
|
identifier == "JSImplementation" or
|
||||||
identifier == "HeaderFile" or
|
identifier == "HeaderFile" or
|
||||||
@ -1139,11 +1292,11 @@ class IDLInterface(IDLObjectWithScope):
|
|||||||
|
|
||||||
def setNonPartial(self, location, parent, members):
|
def setNonPartial(self, location, parent, members):
|
||||||
assert not parent or isinstance(parent, IDLIdentifierPlaceholder)
|
assert not parent or isinstance(parent, IDLIdentifierPlaceholder)
|
||||||
if not self._isPartial:
|
if self._isKnownNonPartial:
|
||||||
raise WebIDLError("Two non-partial definitions for the "
|
raise WebIDLError("Two non-partial definitions for the "
|
||||||
"same interface",
|
"same interface",
|
||||||
[location, self.location])
|
[location, self.location])
|
||||||
self._isPartial = False
|
self._isKnownNonPartial = True
|
||||||
# Now make it look like we were parsed at this new location, since
|
# Now make it look like we were parsed at this new location, since
|
||||||
# that's the place where the interface is "really" defined
|
# that's the place where the interface is "really" defined
|
||||||
self.location = location
|
self.location = location
|
||||||
@ -1152,6 +1305,10 @@ class IDLInterface(IDLObjectWithScope):
|
|||||||
# Put the new members at the beginning
|
# Put the new members at the beginning
|
||||||
self.members = members + self.members
|
self.members = members + self.members
|
||||||
|
|
||||||
|
def addPartialInterface(self, partial):
|
||||||
|
assert self.identifier.name == partial.identifier.name
|
||||||
|
self._partialInterfaces.append(partial)
|
||||||
|
|
||||||
def getJSImplementation(self):
|
def getJSImplementation(self):
|
||||||
classId = self.getExtendedAttribute("JSImplementation")
|
classId = self.getExtendedAttribute("JSImplementation")
|
||||||
if not classId:
|
if not classId:
|
||||||
@ -1535,6 +1692,9 @@ class IDLType(IDLObject):
|
|||||||
raise TypeError("Can't tell whether a generic type is or is not "
|
raise TypeError("Can't tell whether a generic type is or is not "
|
||||||
"distinguishable from other things")
|
"distinguishable from other things")
|
||||||
|
|
||||||
|
def isExposedInAllOf(self, exposureSet):
|
||||||
|
return True
|
||||||
|
|
||||||
class IDLUnresolvedType(IDLType):
|
class IDLUnresolvedType(IDLType):
|
||||||
"""
|
"""
|
||||||
Unresolved types are interface types
|
Unresolved types are interface types
|
||||||
@ -1842,6 +2002,9 @@ class IDLMozMapType(IDLType):
|
|||||||
return (other.isPrimitive() or other.isString() or other.isEnum() or
|
return (other.isPrimitive() or other.isString() or other.isEnum() or
|
||||||
other.isDate() or other.isNonCallbackInterface() or other.isSequence())
|
other.isDate() or other.isNonCallbackInterface() or other.isSequence())
|
||||||
|
|
||||||
|
def isExposedInAllOf(self, exposureSet):
|
||||||
|
return self.inner.unroll().isExposedInAllOf(exposureSet)
|
||||||
|
|
||||||
def _getDependentObjects(self):
|
def _getDependentObjects(self):
|
||||||
return self.inner._getDependentObjects()
|
return self.inner._getDependentObjects()
|
||||||
|
|
||||||
@ -1952,6 +2115,14 @@ class IDLUnionType(IDLType):
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def isExposedInAllOf(self, exposureSet):
|
||||||
|
# We could have different member types in different globals. Just make sure that each thing in exposureSet has one of our member types exposed in it.
|
||||||
|
for globalName in exposureSet:
|
||||||
|
if not any(t.unroll().isExposedInAllOf(set([globalName])) for t
|
||||||
|
in self.flatMemberTypes):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
def _getDependentObjects(self):
|
def _getDependentObjects(self):
|
||||||
return set(self.memberTypes)
|
return set(self.memberTypes)
|
||||||
|
|
||||||
@ -2291,6 +2462,20 @@ class IDLWrapperType(IDLType):
|
|||||||
assert other.isObject()
|
assert other.isObject()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def isExposedInAllOf(self, exposureSet):
|
||||||
|
if not self.isInterface():
|
||||||
|
return True
|
||||||
|
iface = self.inner
|
||||||
|
if iface.isExternal():
|
||||||
|
# Let's say true, though ideally we'd only do this when
|
||||||
|
# exposureSet contains the primary global's name.
|
||||||
|
return True
|
||||||
|
if (iface.identifier.name == "Promise" and
|
||||||
|
# Check the internal type
|
||||||
|
not self._promiseInnerType.unroll().isExposedInAllOf(exposureSet)):
|
||||||
|
return False
|
||||||
|
return iface.exposureSet.issuperset(exposureSet)
|
||||||
|
|
||||||
def _getDependentObjects(self):
|
def _getDependentObjects(self):
|
||||||
# NB: The codegen for an interface type depends on
|
# NB: The codegen for an interface type depends on
|
||||||
# a) That the identifier is in fact an interface (as opposed to
|
# a) That the identifier is in fact an interface (as opposed to
|
||||||
@ -2805,6 +2990,11 @@ class IDLInterfaceMember(IDLObjectWithIdentifier):
|
|||||||
IDLObjectWithIdentifier.__init__(self, location, None, identifier)
|
IDLObjectWithIdentifier.__init__(self, location, None, identifier)
|
||||||
self.tag = tag
|
self.tag = tag
|
||||||
self._extendedAttrDict = {}
|
self._extendedAttrDict = {}
|
||||||
|
# _exposureGlobalNames are the global names listed in our [Exposed]
|
||||||
|
# extended attribute. exposureSet is the exposure set as defined in the
|
||||||
|
# Web IDL spec: it contains interface names.
|
||||||
|
self._exposureGlobalNames = set()
|
||||||
|
self.exposureSet = set()
|
||||||
|
|
||||||
def isMethod(self):
|
def isMethod(self):
|
||||||
return self.tag == IDLInterfaceMember.Tags.Method
|
return self.tag == IDLInterfaceMember.Tags.Method
|
||||||
@ -2827,6 +3017,22 @@ class IDLInterfaceMember(IDLObjectWithIdentifier):
|
|||||||
def getExtendedAttribute(self, name):
|
def getExtendedAttribute(self, name):
|
||||||
return self._extendedAttrDict.get(name, None)
|
return self._extendedAttrDict.get(name, None)
|
||||||
|
|
||||||
|
def finish(self, scope):
|
||||||
|
for globalName in self._exposureGlobalNames:
|
||||||
|
if globalName not in scope.globalNames:
|
||||||
|
raise WebIDLError("Unknown [Exposed] value %s" % globalName,
|
||||||
|
[self.location])
|
||||||
|
globalNameSetToExposureSet(scope, self._exposureGlobalNames,
|
||||||
|
self.exposureSet)
|
||||||
|
self._scope = scope
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
if (self.getExtendedAttribute("Pref") and
|
||||||
|
self.exposureSet != set([self._scope.primaryGlobalName])):
|
||||||
|
raise WebIDLError("[Pref] used on an interface member that is not "
|
||||||
|
"%s-only" % self._scope.primaryGlobalName,
|
||||||
|
[self.location])
|
||||||
|
|
||||||
class IDLConst(IDLInterfaceMember):
|
class IDLConst(IDLInterfaceMember):
|
||||||
def __init__(self, location, identifier, type, value):
|
def __init__(self, location, identifier, type, value):
|
||||||
IDLInterfaceMember.__init__(self, location, identifier,
|
IDLInterfaceMember.__init__(self, location, identifier,
|
||||||
@ -2847,6 +3053,8 @@ class IDLConst(IDLInterfaceMember):
|
|||||||
return "'%s' const '%s'" % (self.type, self.identifier)
|
return "'%s' const '%s'" % (self.type, self.identifier)
|
||||||
|
|
||||||
def finish(self, scope):
|
def finish(self, scope):
|
||||||
|
IDLInterfaceMember.finish(self, scope)
|
||||||
|
|
||||||
if not self.type.isComplete():
|
if not self.type.isComplete():
|
||||||
type = self.type.complete(scope)
|
type = self.type.complete(scope)
|
||||||
if not type.isPrimitive() and not type.isString():
|
if not type.isPrimitive() and not type.isString():
|
||||||
@ -2865,7 +3073,23 @@ class IDLConst(IDLInterfaceMember):
|
|||||||
self.value = coercedValue
|
self.value = coercedValue
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
|
IDLInterfaceMember.validate(self)
|
||||||
|
|
||||||
|
def handleExtendedAttribute(self, attr):
|
||||||
|
identifier = attr.identifier()
|
||||||
|
if identifier == "Exposed":
|
||||||
|
convertExposedAttrToGlobalNameSet(attr, self._exposureGlobalNames)
|
||||||
|
elif (identifier == "Pref" or
|
||||||
|
identifier == "ChromeOnly" or
|
||||||
|
identifier == "Func" or
|
||||||
|
identifier == "AvailableIn" or
|
||||||
|
identifier == "CheckPermissions"):
|
||||||
|
# Known attributes that we don't need to do anything with here
|
||||||
pass
|
pass
|
||||||
|
else:
|
||||||
|
raise WebIDLError("Unknown extended attribute %s on constant" % identifier,
|
||||||
|
[attr.location])
|
||||||
|
IDLInterfaceMember.handleExtendedAttribute(self, attr)
|
||||||
|
|
||||||
def _getDependentObjects(self):
|
def _getDependentObjects(self):
|
||||||
return set([self.type, self.value])
|
return set([self.type, self.value])
|
||||||
@ -2903,6 +3127,8 @@ class IDLAttribute(IDLInterfaceMember):
|
|||||||
return "'%s' attribute '%s'" % (self.type, self.identifier)
|
return "'%s' attribute '%s'" % (self.type, self.identifier)
|
||||||
|
|
||||||
def finish(self, scope):
|
def finish(self, scope):
|
||||||
|
IDLInterfaceMember.finish(self, scope)
|
||||||
|
|
||||||
if not self.type.isComplete():
|
if not self.type.isComplete():
|
||||||
t = self.type.complete(scope)
|
t = self.type.complete(scope)
|
||||||
|
|
||||||
@ -2961,6 +3187,8 @@ class IDLAttribute(IDLInterfaceMember):
|
|||||||
[self.location])
|
[self.location])
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
|
IDLInterfaceMember.validate(self)
|
||||||
|
|
||||||
if ((self.getExtendedAttribute("Cached") or
|
if ((self.getExtendedAttribute("Cached") or
|
||||||
self.getExtendedAttribute("StoreInSlot")) and
|
self.getExtendedAttribute("StoreInSlot")) and
|
||||||
not self.getExtendedAttribute("Constant") and
|
not self.getExtendedAttribute("Constant") and
|
||||||
@ -2976,6 +3204,10 @@ class IDLAttribute(IDLInterfaceMember):
|
|||||||
"sequence-valued, dictionary-valued, and "
|
"sequence-valued, dictionary-valued, and "
|
||||||
"MozMap-valued attributes",
|
"MozMap-valued attributes",
|
||||||
[self.location])
|
[self.location])
|
||||||
|
if not self.type.unroll().isExposedInAllOf(self.exposureSet):
|
||||||
|
raise WebIDLError("Attribute returns a type that is not exposed "
|
||||||
|
"everywhere where the attribute is exposed",
|
||||||
|
[self.location])
|
||||||
|
|
||||||
def handleExtendedAttribute(self, attr):
|
def handleExtendedAttribute(self, attr):
|
||||||
identifier = attr.identifier()
|
identifier = attr.identifier()
|
||||||
@ -3078,6 +3310,8 @@ class IDLAttribute(IDLInterfaceMember):
|
|||||||
raise WebIDLError("[LenientThis] is not allowed in combination "
|
raise WebIDLError("[LenientThis] is not allowed in combination "
|
||||||
"with [%s]" % identifier,
|
"with [%s]" % identifier,
|
||||||
[attr.location, self.location])
|
[attr.location, self.location])
|
||||||
|
elif identifier == "Exposed":
|
||||||
|
convertExposedAttrToGlobalNameSet(attr, self._exposureGlobalNames)
|
||||||
elif (identifier == "Pref" or
|
elif (identifier == "Pref" or
|
||||||
identifier == "SetterThrows" or
|
identifier == "SetterThrows" or
|
||||||
identifier == "Pure" or
|
identifier == "Pure" or
|
||||||
@ -3494,6 +3728,8 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||||||
self._overloads]
|
self._overloads]
|
||||||
|
|
||||||
def finish(self, scope):
|
def finish(self, scope):
|
||||||
|
IDLInterfaceMember.finish(self, scope)
|
||||||
|
|
||||||
if self.getExtendedAttribute("FeatureDetectible"):
|
if self.getExtendedAttribute("FeatureDetectible"):
|
||||||
if not (self.getExtendedAttribute("Func") or
|
if not (self.getExtendedAttribute("Func") or
|
||||||
self.getExtendedAttribute("AvailableIn") or
|
self.getExtendedAttribute("AvailableIn") or
|
||||||
@ -3577,6 +3813,8 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||||||
if len(self.signaturesForArgCount(i)) != 0 ]
|
if len(self.signaturesForArgCount(i)) != 0 ]
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
|
IDLInterfaceMember.validate(self)
|
||||||
|
|
||||||
# Make sure our overloads are properly distinguishable and don't have
|
# Make sure our overloads are properly distinguishable and don't have
|
||||||
# different argument types before the distinguishing args.
|
# different argument types before the distinguishing args.
|
||||||
for argCount in self.allowedArgCounts:
|
for argCount in self.allowedArgCounts:
|
||||||
@ -3596,6 +3834,12 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||||||
distinguishingIndex),
|
distinguishingIndex),
|
||||||
[self.location, overload.location])
|
[self.location, overload.location])
|
||||||
|
|
||||||
|
for overload in self._overloads:
|
||||||
|
if not overload.returnType.unroll().isExposedInAllOf(self.exposureSet):
|
||||||
|
raise WebIDLError("Overload returns a type that is not exposed "
|
||||||
|
"everywhere where the method is exposed",
|
||||||
|
[overload.location])
|
||||||
|
|
||||||
def overloadsForArgCount(self, argc):
|
def overloadsForArgCount(self, argc):
|
||||||
return [overload for overload in self._overloads if
|
return [overload for overload in self._overloads if
|
||||||
len(overload.arguments) == argc or
|
len(overload.arguments) == argc or
|
||||||
@ -3674,6 +3918,8 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||||||
raise WebIDLError("[LenientFloat] used on an operation with no "
|
raise WebIDLError("[LenientFloat] used on an operation with no "
|
||||||
"restricted float type arguments",
|
"restricted float type arguments",
|
||||||
[attr.location, self.location])
|
[attr.location, self.location])
|
||||||
|
elif identifier == "Exposed":
|
||||||
|
convertExposedAttrToGlobalNameSet(attr, self._exposureGlobalNames)
|
||||||
elif (identifier == "Pure" or
|
elif (identifier == "Pure" or
|
||||||
identifier == "CrossOriginCallable" or
|
identifier == "CrossOriginCallable" or
|
||||||
identifier == "WebGLHandlesContextLoss" or
|
identifier == "WebGLHandlesContextLoss" or
|
||||||
@ -3920,6 +4166,45 @@ class Tokenizer(object):
|
|||||||
lextab='webidllex',
|
lextab='webidllex',
|
||||||
reflags=re.DOTALL)
|
reflags=re.DOTALL)
|
||||||
|
|
||||||
|
class SqueakyCleanLogger(object):
|
||||||
|
errorWhitelist = [
|
||||||
|
# Web IDL defines the WHITESPACE token, but doesn't actually
|
||||||
|
# use it ... so far.
|
||||||
|
"Token 'WHITESPACE' defined, but not used",
|
||||||
|
# And that means we have an unused token
|
||||||
|
"There is 1 unused token",
|
||||||
|
# Web IDL defines a OtherOrComma rule that's only used in
|
||||||
|
# ExtendedAttributeInner, which we don't use yet.
|
||||||
|
"Rule 'OtherOrComma' defined, but not used",
|
||||||
|
# And an unused rule
|
||||||
|
"There is 1 unused rule",
|
||||||
|
# And the OtherOrComma grammar symbol is unreachable.
|
||||||
|
"Symbol 'OtherOrComma' is unreachable",
|
||||||
|
# Which means the Other symbol is unreachable.
|
||||||
|
"Symbol 'Other' is unreachable",
|
||||||
|
]
|
||||||
|
def __init__(self):
|
||||||
|
self.errors = []
|
||||||
|
def debug(self, msg, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
info = debug
|
||||||
|
def warning(self, msg, *args, **kwargs):
|
||||||
|
if msg == "%s:%d: Rule '%s' defined, but not used":
|
||||||
|
# Munge things so we don't have to hardcode filenames and
|
||||||
|
# line numbers in our whitelist.
|
||||||
|
whitelistmsg = "Rule '%s' defined, but not used"
|
||||||
|
whitelistargs = args[2:]
|
||||||
|
else:
|
||||||
|
whitelistmsg = msg
|
||||||
|
whitelistargs = args
|
||||||
|
if (whitelistmsg % whitelistargs) not in SqueakyCleanLogger.errorWhitelist:
|
||||||
|
self.errors.append(msg % args)
|
||||||
|
error = warning
|
||||||
|
|
||||||
|
def reportGrammarErrors(self):
|
||||||
|
if self.errors:
|
||||||
|
raise WebIDLError("\n".join(self.errors), [])
|
||||||
|
|
||||||
class Parser(Tokenizer):
|
class Parser(Tokenizer):
|
||||||
def getLocation(self, p, i):
|
def getLocation(self, p, i):
|
||||||
return Location(self.lexer, p.lineno(i), p.lexpos(i), self._filename)
|
return Location(self.lexer, p.lineno(i), p.lexpos(i), self._filename)
|
||||||
@ -3995,10 +4280,11 @@ class Parser(Tokenizer):
|
|||||||
parent = p[3]
|
parent = p[3]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if self.globalScope()._lookupIdentifier(identifier):
|
existingObj = self.globalScope()._lookupIdentifier(identifier)
|
||||||
p[0] = self.globalScope()._lookupIdentifier(identifier)
|
if existingObj:
|
||||||
|
p[0] = existingObj
|
||||||
if not isinstance(p[0], IDLInterface):
|
if not isinstance(p[0], IDLInterface):
|
||||||
raise WebIDLError("Partial interface has the same name as "
|
raise WebIDLError("Interface has the same name as "
|
||||||
"non-interface object",
|
"non-interface object",
|
||||||
[location, p[0].location])
|
[location, p[0].location])
|
||||||
p[0].setNonPartial(location, parent, members)
|
p[0].setNonPartial(location, parent, members)
|
||||||
@ -4009,7 +4295,7 @@ class Parser(Tokenizer):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
p[0] = IDLInterface(location, self.globalScope(), identifier, parent,
|
p[0] = IDLInterface(location, self.globalScope(), identifier, parent,
|
||||||
members, isPartial=False)
|
members, isKnownNonPartial=True)
|
||||||
|
|
||||||
def p_InterfaceForwardDecl(self, p):
|
def p_InterfaceForwardDecl(self, p):
|
||||||
"""
|
"""
|
||||||
@ -4042,26 +4328,26 @@ class Parser(Tokenizer):
|
|||||||
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3])
|
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3])
|
||||||
members = p[5]
|
members = p[5]
|
||||||
|
|
||||||
|
nonPartialInterface = None
|
||||||
try:
|
try:
|
||||||
if self.globalScope()._lookupIdentifier(identifier):
|
nonPartialInterface = self.globalScope()._lookupIdentifier(identifier)
|
||||||
p[0] = self.globalScope()._lookupIdentifier(identifier)
|
if nonPartialInterface:
|
||||||
if not isinstance(p[0], IDLInterface):
|
if not isinstance(nonPartialInterface, IDLInterface):
|
||||||
raise WebIDLError("Partial interface has the same name as "
|
raise WebIDLError("Partial interface has the same name as "
|
||||||
"non-interface object",
|
"non-interface object",
|
||||||
[location, p[0].location])
|
[location, nonPartialInterface.location])
|
||||||
# Just throw our members into the existing IDLInterface. If we
|
|
||||||
# have extended attributes, those will get added to it
|
|
||||||
# automatically.
|
|
||||||
p[0].members.extend(members)
|
|
||||||
return
|
|
||||||
except Exception, ex:
|
except Exception, ex:
|
||||||
if isinstance(ex, WebIDLError):
|
if isinstance(ex, WebIDLError):
|
||||||
raise ex
|
raise ex
|
||||||
pass
|
pass
|
||||||
|
|
||||||
p[0] = IDLInterface(location, self.globalScope(), identifier, None,
|
if not nonPartialInterface:
|
||||||
members, isPartial=True)
|
nonPartialInterface = IDLInterface(location, self.globalScope(),
|
||||||
pass
|
identifier, None,
|
||||||
|
[], isKnownNonPartial=False)
|
||||||
|
partialInterface = IDLPartialInterface(location, identifier, members,
|
||||||
|
nonPartialInterface)
|
||||||
|
p[0] = partialInterface
|
||||||
|
|
||||||
def p_Inheritance(self, p):
|
def p_Inheritance(self, p):
|
||||||
"""
|
"""
|
||||||
@ -4726,6 +5012,7 @@ class Parser(Tokenizer):
|
|||||||
| ExtendedAttributeArgList
|
| ExtendedAttributeArgList
|
||||||
| ExtendedAttributeIdent
|
| ExtendedAttributeIdent
|
||||||
| ExtendedAttributeNamedArgList
|
| ExtendedAttributeNamedArgList
|
||||||
|
| ExtendedAttributeIdentList
|
||||||
"""
|
"""
|
||||||
p[0] = IDLExtendedAttribute(self.getLocation(p, 1), p[1])
|
p[0] = IDLExtendedAttribute(self.getLocation(p, 1), p[1])
|
||||||
|
|
||||||
@ -5200,6 +5487,34 @@ class Parser(Tokenizer):
|
|||||||
"""
|
"""
|
||||||
p[0] = (p[1], p[3], p[5])
|
p[0] = (p[1], p[3], p[5])
|
||||||
|
|
||||||
|
def p_ExtendedAttributeIdentList(self, p):
|
||||||
|
"""
|
||||||
|
ExtendedAttributeIdentList : IDENTIFIER EQUALS LPAREN IdentifierList RPAREN
|
||||||
|
"""
|
||||||
|
p[0] = (p[1], p[4])
|
||||||
|
|
||||||
|
def p_IdentifierList(self, p):
|
||||||
|
"""
|
||||||
|
IdentifierList : IDENTIFIER Identifiers
|
||||||
|
"""
|
||||||
|
idents = list(p[2])
|
||||||
|
idents.insert(0, p[1])
|
||||||
|
p[0] = idents
|
||||||
|
|
||||||
|
def p_IdentifiersList(self, p):
|
||||||
|
"""
|
||||||
|
Identifiers : COMMA IDENTIFIER Identifiers
|
||||||
|
"""
|
||||||
|
idents = list(p[3])
|
||||||
|
idents.insert(0, p[2])
|
||||||
|
p[0] = idents
|
||||||
|
|
||||||
|
def p_IdentifiersEmpty(self, p):
|
||||||
|
"""
|
||||||
|
Identifiers :
|
||||||
|
"""
|
||||||
|
p[0] = []
|
||||||
|
|
||||||
def p_error(self, p):
|
def p_error(self, p):
|
||||||
if not p:
|
if not p:
|
||||||
raise WebIDLError("Syntax Error at end of file. Possibly due to missing semicolon(;), braces(}) or both",
|
raise WebIDLError("Syntax Error at end of file. Possibly due to missing semicolon(;), braces(}) or both",
|
||||||
@ -5209,10 +5524,12 @@ class Parser(Tokenizer):
|
|||||||
|
|
||||||
def __init__(self, outputdir='', lexer=None):
|
def __init__(self, outputdir='', lexer=None):
|
||||||
Tokenizer.__init__(self, outputdir, lexer)
|
Tokenizer.__init__(self, outputdir, lexer)
|
||||||
|
|
||||||
|
logger = SqueakyCleanLogger()
|
||||||
self.parser = yacc.yacc(module=self,
|
self.parser = yacc.yacc(module=self,
|
||||||
outputdir=outputdir,
|
outputdir=outputdir,
|
||||||
tabmodule='webidlyacc',
|
tabmodule='webidlyacc',
|
||||||
errorlog=yacc.NullLogger()
|
errorlog=logger
|
||||||
# Pickling the grammar is a speedup in
|
# Pickling the grammar is a speedup in
|
||||||
# some cases (older Python?) but a
|
# some cases (older Python?) but a
|
||||||
# significant slowdown in others.
|
# significant slowdown in others.
|
||||||
@ -5220,7 +5537,13 @@ class Parser(Tokenizer):
|
|||||||
# becomes a speedup again.
|
# becomes a speedup again.
|
||||||
# , picklefile='WebIDLGrammar.pkl'
|
# , picklefile='WebIDLGrammar.pkl'
|
||||||
)
|
)
|
||||||
|
logger.reportGrammarErrors()
|
||||||
|
|
||||||
self._globalScope = IDLScope(BuiltinLocation("<Global Scope>"), None, None)
|
self._globalScope = IDLScope(BuiltinLocation("<Global Scope>"), None, None)
|
||||||
|
# To make our test harness work, pretend like we have a primary global already. Note that we _don't_ set _globalScope.primaryGlobalAttr, so we'll still be able to detect multiple PrimaryGlobal extended attributes.
|
||||||
|
self._globalScope.primaryGlobalName = "FakeTestPrimaryGlobal"
|
||||||
|
self._globalScope.globalNames.add("FakeTestPrimaryGlobal")
|
||||||
|
self._globalScope.globalNameMapping["FakeTestPrimaryGlobal"].add("FakeTestPrimaryGlobal")
|
||||||
self._installBuiltins(self._globalScope)
|
self._installBuiltins(self._globalScope)
|
||||||
self._productions = []
|
self._productions = []
|
||||||
|
|
||||||
|
222
dom/bindings/parser/tests/test_exposed_extended_attribute.py
Normal file
222
dom/bindings/parser/tests/test_exposed_extended_attribute.py
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
import WebIDL
|
||||||
|
|
||||||
|
def WebIDLTest(parser, harness):
|
||||||
|
parser.parse("""
|
||||||
|
[PrimaryGlobal] interface Foo {};
|
||||||
|
[Global=(Bar1,Bar2)] interface Bar {};
|
||||||
|
[Global=Baz2] interface Baz {};
|
||||||
|
|
||||||
|
[Exposed=(Foo,Bar1)]
|
||||||
|
interface Iface {
|
||||||
|
void method1();
|
||||||
|
|
||||||
|
[Exposed=Bar1]
|
||||||
|
readonly attribute any attr;
|
||||||
|
};
|
||||||
|
|
||||||
|
[Exposed=Foo]
|
||||||
|
partial interface Iface {
|
||||||
|
void method2();
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
|
||||||
|
harness.check(len(results), 5, "Should know about five things");
|
||||||
|
iface = results[3]
|
||||||
|
harness.ok(isinstance(iface, WebIDL.IDLInterface),
|
||||||
|
"Should have an interface here");
|
||||||
|
members = iface.members
|
||||||
|
harness.check(len(members), 3, "Should have three members")
|
||||||
|
|
||||||
|
harness.ok(members[0].exposureSet == set(["Foo", "Bar"]),
|
||||||
|
"method1 should have the right exposure set")
|
||||||
|
harness.ok(members[0]._exposureGlobalNames == set(["Foo", "Bar1"]),
|
||||||
|
"method1 should have the right exposure global names")
|
||||||
|
|
||||||
|
harness.ok(members[1].exposureSet == set(["Bar"]),
|
||||||
|
"attr should have the right exposure set")
|
||||||
|
harness.ok(members[1]._exposureGlobalNames == set(["Bar1"]),
|
||||||
|
"attr should have the right exposure global names")
|
||||||
|
|
||||||
|
harness.ok(members[2].exposureSet == set(["Foo"]),
|
||||||
|
"method2 should have the right exposure set")
|
||||||
|
harness.ok(members[2]._exposureGlobalNames == set(["Foo"]),
|
||||||
|
"method2 should have the right exposure global names")
|
||||||
|
|
||||||
|
harness.ok(iface.exposureSet == set(["Foo", "Bar"]),
|
||||||
|
"Iface should have the right exposure set")
|
||||||
|
harness.ok(iface._exposureGlobalNames == set(["Foo", "Bar1"]),
|
||||||
|
"Iface should have the right exposure global names")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
parser.parse("""
|
||||||
|
[PrimaryGlobal] interface Foo {};
|
||||||
|
[Global=(Bar1,Bar2)] interface Bar {};
|
||||||
|
[Global=Baz2] interface Baz {};
|
||||||
|
|
||||||
|
interface Iface2 {
|
||||||
|
void method3();
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
|
||||||
|
harness.check(len(results), 4, "Should know about four things");
|
||||||
|
iface = results[3]
|
||||||
|
harness.ok(isinstance(iface, WebIDL.IDLInterface),
|
||||||
|
"Should have an interface here");
|
||||||
|
members = iface.members
|
||||||
|
harness.check(len(members), 1, "Should have one member")
|
||||||
|
|
||||||
|
harness.ok(members[0].exposureSet == set(["Foo"]),
|
||||||
|
"method3 should have the right exposure set")
|
||||||
|
harness.ok(members[0]._exposureGlobalNames == set(["Foo"]),
|
||||||
|
"method3 should have the right exposure global names")
|
||||||
|
|
||||||
|
harness.ok(iface.exposureSet == set(["Foo"]),
|
||||||
|
"Iface2 should have the right exposure set")
|
||||||
|
harness.ok(iface._exposureGlobalNames == set(["Foo"]),
|
||||||
|
"Iface2 should have the right exposure global names")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
parser.parse("""
|
||||||
|
[PrimaryGlobal] interface Foo {};
|
||||||
|
[Global=(Bar1,Bar2)] interface Bar {};
|
||||||
|
[Global=Baz2] interface Baz {};
|
||||||
|
|
||||||
|
[Exposed=Foo]
|
||||||
|
interface Iface3 {
|
||||||
|
void method4();
|
||||||
|
};
|
||||||
|
|
||||||
|
[Exposed=(Foo,Bar1)]
|
||||||
|
interface Mixin {
|
||||||
|
void method5();
|
||||||
|
};
|
||||||
|
|
||||||
|
Iface3 implements Mixin;
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
harness.check(len(results), 6, "Should know about six things");
|
||||||
|
iface = results[3]
|
||||||
|
harness.ok(isinstance(iface, WebIDL.IDLInterface),
|
||||||
|
"Should have an interface here");
|
||||||
|
members = iface.members
|
||||||
|
harness.check(len(members), 2, "Should have two members")
|
||||||
|
|
||||||
|
harness.ok(members[0].exposureSet == set(["Foo"]),
|
||||||
|
"method4 should have the right exposure set")
|
||||||
|
harness.ok(members[0]._exposureGlobalNames == set(["Foo"]),
|
||||||
|
"method4 should have the right exposure global names")
|
||||||
|
|
||||||
|
harness.ok(members[1].exposureSet == set(["Foo", "Bar"]),
|
||||||
|
"method5 should have the right exposure set")
|
||||||
|
harness.ok(members[1]._exposureGlobalNames == set(["Foo", "Bar1"]),
|
||||||
|
"method5 should have the right exposure global names")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
[Exposed=Foo]
|
||||||
|
interface Bar {
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except Exception,x:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Should have thrown on invalid Exposed value on interface.")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface Bar {
|
||||||
|
[Exposed=Foo]
|
||||||
|
readonly attribute bool attr;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except Exception,x:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Should have thrown on invalid Exposed value on attribute.")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface Bar {
|
||||||
|
[Exposed=Foo]
|
||||||
|
void operation();
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except Exception,x:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Should have thrown on invalid Exposed value on operation.")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface Bar {
|
||||||
|
[Exposed=Foo]
|
||||||
|
const long constant = 5;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except Exception,x:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Should have thrown on invalid Exposed value on constant.")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
[Global] interface Foo {};
|
||||||
|
[Global] interface Bar {};
|
||||||
|
|
||||||
|
[Exposed=Foo]
|
||||||
|
interface Baz {
|
||||||
|
[Exposed=Bar]
|
||||||
|
void method();
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except Exception,x:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Should have thrown on member exposed where its interface is not.")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
[Global] interface Foo {};
|
||||||
|
[Global] interface Bar {};
|
||||||
|
|
||||||
|
[Exposed=Foo]
|
||||||
|
interface Baz {
|
||||||
|
void method();
|
||||||
|
};
|
||||||
|
|
||||||
|
[Exposed=Bar]
|
||||||
|
interface Mixin {};
|
||||||
|
|
||||||
|
Baz implements Mixin;
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except Exception,x:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Should have thrown on LHS of implements being exposed where RHS is not.")
|
@ -201,8 +201,8 @@ def WebIDLTest(parser, harness):
|
|||||||
};
|
};
|
||||||
""");
|
""");
|
||||||
results = parser.finish();
|
results = parser.finish();
|
||||||
harness.check(len(results), 1,
|
harness.check(len(results), 2,
|
||||||
"Should have one result with partial interface")
|
"Should have two results with partial interface")
|
||||||
iface = results[0]
|
iface = results[0]
|
||||||
harness.check(len(iface.members), 3,
|
harness.check(len(iface.members), 3,
|
||||||
"Should have three members with partial interface")
|
"Should have three members with partial interface")
|
||||||
@ -231,9 +231,9 @@ def WebIDLTest(parser, harness):
|
|||||||
};
|
};
|
||||||
""");
|
""");
|
||||||
results = parser.finish();
|
results = parser.finish();
|
||||||
harness.check(len(results), 1,
|
harness.check(len(results), 2,
|
||||||
"Should have one result with reversed partial interface")
|
"Should have two results with reversed partial interface")
|
||||||
iface = results[0]
|
iface = results[1]
|
||||||
harness.check(len(iface.members), 3,
|
harness.check(len(iface.members), 3,
|
||||||
"Should have three members with reversed partial interface")
|
"Should have three members with reversed partial interface")
|
||||||
harness.check(iface.members[0].identifier.name, "x",
|
harness.check(iface.members[0].identifier.name, "x",
|
||||||
|
@ -47,7 +47,7 @@ private:
|
|||||||
void (Obj::*mMethod)();
|
void (Obj::*mMethod)();
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Obj, typename Res, typename Arg1>
|
template <typename Obj, typename Res, typename Tin1, typename Arg1>
|
||||||
class BluetoothInterfaceRunnable1 : public nsRunnable
|
class BluetoothInterfaceRunnable1 : public nsRunnable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -70,11 +70,12 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
nsRefPtr<Obj> mObj;
|
nsRefPtr<Obj> mObj;
|
||||||
void (Obj::*mMethod)(Arg1);
|
Res (Obj::*mMethod)(Arg1);
|
||||||
Arg1 mArg1;
|
Tin1 mArg1;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Obj, typename Res,
|
template <typename Obj, typename Res,
|
||||||
|
typename Tin1, typename Tin2, typename Tin3,
|
||||||
typename Arg1, typename Arg2, typename Arg3>
|
typename Arg1, typename Arg2, typename Arg3>
|
||||||
class BluetoothInterfaceRunnable3 : public nsRunnable
|
class BluetoothInterfaceRunnable3 : public nsRunnable
|
||||||
{
|
{
|
||||||
@ -102,10 +103,10 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
nsRefPtr<Obj> mObj;
|
nsRefPtr<Obj> mObj;
|
||||||
void (Obj::*mMethod)(Arg1, Arg2, Arg3);
|
Res (Obj::*mMethod)(Arg1, Arg2, Arg3);
|
||||||
Arg1 mArg1;
|
Tin1 mArg1;
|
||||||
Arg2 mArg2;
|
Tin2 mArg2;
|
||||||
Arg3 mArg3;
|
Tin3 mArg3;
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -124,16 +125,18 @@ struct interface_traits<BluetoothSocketInterface>
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef
|
typedef
|
||||||
BluetoothInterfaceRunnable1<BluetoothSocketResultHandler, void, int>
|
BluetoothInterfaceRunnable1<BluetoothSocketResultHandler, void, int, int>
|
||||||
BluetoothSocketIntResultRunnable;
|
BluetoothSocketIntResultRunnable;
|
||||||
|
|
||||||
typedef
|
typedef
|
||||||
BluetoothInterfaceRunnable3<BluetoothSocketResultHandler,
|
BluetoothInterfaceRunnable3<BluetoothSocketResultHandler, void,
|
||||||
void, int, const nsAString_internal&, int>
|
int, const nsString, int,
|
||||||
|
int, const nsAString_internal&, int>
|
||||||
BluetoothSocketIntStringIntResultRunnable;
|
BluetoothSocketIntStringIntResultRunnable;
|
||||||
|
|
||||||
typedef
|
typedef
|
||||||
BluetoothInterfaceRunnable1<BluetoothSocketResultHandler, void, bt_status_t>
|
BluetoothInterfaceRunnable1<BluetoothSocketResultHandler, void,
|
||||||
|
bt_status_t, bt_status_t>
|
||||||
BluetoothSocketErrorRunnable;
|
BluetoothSocketErrorRunnable;
|
||||||
|
|
||||||
static nsresult
|
static nsresult
|
||||||
@ -581,7 +584,8 @@ typedef
|
|||||||
BluetoothHandsfreeResultRunnable;
|
BluetoothHandsfreeResultRunnable;
|
||||||
|
|
||||||
typedef
|
typedef
|
||||||
BluetoothInterfaceRunnable1<BluetoothHandsfreeResultHandler, void, bt_status_t>
|
BluetoothInterfaceRunnable1<BluetoothHandsfreeResultHandler, void,
|
||||||
|
bt_status_t, bt_status_t>
|
||||||
BluetoothHandsfreeErrorRunnable;
|
BluetoothHandsfreeErrorRunnable;
|
||||||
|
|
||||||
static nsresult
|
static nsresult
|
||||||
@ -852,7 +856,8 @@ typedef
|
|||||||
BluetoothA2dpResultRunnable;
|
BluetoothA2dpResultRunnable;
|
||||||
|
|
||||||
typedef
|
typedef
|
||||||
BluetoothInterfaceRunnable1<BluetoothA2dpResultHandler, void, bt_status_t>
|
BluetoothInterfaceRunnable1<BluetoothA2dpResultHandler, void,
|
||||||
|
bt_status_t, bt_status_t>
|
||||||
BluetoothA2dpErrorRunnable;
|
BluetoothA2dpErrorRunnable;
|
||||||
|
|
||||||
static nsresult
|
static nsresult
|
||||||
@ -956,7 +961,8 @@ typedef
|
|||||||
BluetoothAvrcpResultRunnable;
|
BluetoothAvrcpResultRunnable;
|
||||||
|
|
||||||
typedef
|
typedef
|
||||||
BluetoothInterfaceRunnable1<BluetoothAvrcpResultHandler, void, bt_status_t>
|
BluetoothInterfaceRunnable1<BluetoothAvrcpResultHandler, void,
|
||||||
|
bt_status_t, bt_status_t>
|
||||||
BluetoothAvrcpErrorRunnable;
|
BluetoothAvrcpErrorRunnable;
|
||||||
|
|
||||||
static nsresult
|
static nsresult
|
||||||
@ -1155,7 +1161,7 @@ typedef
|
|||||||
BluetoothResultRunnable;
|
BluetoothResultRunnable;
|
||||||
|
|
||||||
typedef
|
typedef
|
||||||
BluetoothInterfaceRunnable1<BluetoothResultHandler, void, int>
|
BluetoothInterfaceRunnable1<BluetoothResultHandler, void, int, int>
|
||||||
BluetoothErrorRunnable;
|
BluetoothErrorRunnable;
|
||||||
|
|
||||||
static nsresult
|
static nsresult
|
||||||
|
@ -811,10 +811,10 @@ BluetoothSocket::CloseDroidSocket()
|
|||||||
NotifyDisconnect();
|
NotifyDisconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConnectResultHandler MOZ_FINAL : public BluetoothSocketResultHandler
|
class ConnectSocketResultHandler MOZ_FINAL : public BluetoothSocketResultHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ConnectResultHandler(DroidSocketImpl* aImpl)
|
ConnectSocketResultHandler(DroidSocketImpl* aImpl)
|
||||||
: mImpl(aImpl)
|
: mImpl(aImpl)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mImpl);
|
MOZ_ASSERT(mImpl);
|
||||||
@ -861,7 +861,7 @@ BluetoothSocket::Connect(const nsAString& aDeviceAddress, int aChannel)
|
|||||||
aChannel,
|
aChannel,
|
||||||
(BTSOCK_FLAG_ENCRYPT * mEncrypt) |
|
(BTSOCK_FLAG_ENCRYPT * mEncrypt) |
|
||||||
(BTSOCK_FLAG_AUTH * mAuth),
|
(BTSOCK_FLAG_AUTH * mAuth),
|
||||||
new ConnectResultHandler(mImpl));
|
new ConnectSocketResultHandler(mImpl));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,27 +4,23 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
* 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/. */
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "base/basictypes.h"
|
#include "BluetoothReplyRunnable.h"
|
||||||
#include "nsDOMClassInfo.h"
|
#include "BluetoothService.h"
|
||||||
#include "nsTArrayHelpers.h"
|
#include "BluetoothUtils.h"
|
||||||
#include "DOMRequest.h"
|
#include "DOMRequest.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsTArrayHelpers.h"
|
||||||
|
|
||||||
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
|
|
||||||
#include "mozilla/dom/BluetoothAdapter2Binding.h"
|
#include "mozilla/dom/BluetoothAdapter2Binding.h"
|
||||||
#include "mozilla/dom/BluetoothAttributeEvent.h"
|
#include "mozilla/dom/BluetoothAttributeEvent.h"
|
||||||
#include "mozilla/dom/BluetoothStatusChangedEvent.h"
|
#include "mozilla/dom/BluetoothStatusChangedEvent.h"
|
||||||
#include "mozilla/dom/ContentChild.h"
|
#include "mozilla/dom/ContentChild.h"
|
||||||
#include "mozilla/dom/ScriptSettings.h"
|
|
||||||
#include "mozilla/LazyIdleThread.h"
|
|
||||||
|
|
||||||
#include "BluetoothAdapter.h"
|
#include "mozilla/dom/bluetooth/BluetoothAdapter.h"
|
||||||
#include "BluetoothClassOfDevice.h"
|
#include "mozilla/dom/bluetooth/BluetoothClassOfDevice.h"
|
||||||
#include "BluetoothDevice.h"
|
#include "mozilla/dom/bluetooth/BluetoothDevice.h"
|
||||||
#include "BluetoothDiscoveryHandle.h"
|
#include "mozilla/dom/bluetooth/BluetoothDiscoveryHandle.h"
|
||||||
#include "BluetoothReplyRunnable.h"
|
#include "mozilla/dom/bluetooth/BluetoothPairingListener.h"
|
||||||
#include "BluetoothService.h"
|
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
|
||||||
#include "BluetoothUtils.h"
|
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
@ -32,7 +28,8 @@ using namespace mozilla::dom;
|
|||||||
USING_BLUETOOTH_NAMESPACE
|
USING_BLUETOOTH_NAMESPACE
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(BluetoothAdapter, DOMEventTargetHelper,
|
NS_IMPL_CYCLE_COLLECTION_INHERITED(BluetoothAdapter, DOMEventTargetHelper,
|
||||||
mDevices, mDiscoveryHandleInUse)
|
mDevices, mDiscoveryHandleInUse,
|
||||||
|
mPairingReqs)
|
||||||
|
|
||||||
// QueryInterface implementation for BluetoothAdapter
|
// QueryInterface implementation for BluetoothAdapter
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothAdapter)
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothAdapter)
|
||||||
@ -220,6 +217,8 @@ BluetoothAdapter::BluetoothAdapter(nsPIDOMWindow* aWindow,
|
|||||||
MOZ_ASSERT(aWindow);
|
MOZ_ASSERT(aWindow);
|
||||||
MOZ_ASSERT(IsDOMBinding());
|
MOZ_ASSERT(IsDOMBinding());
|
||||||
|
|
||||||
|
mPairingReqs = BluetoothPairingListener::Create(aWindow);
|
||||||
|
|
||||||
const InfallibleTArray<BluetoothNamedValue>& values =
|
const InfallibleTArray<BluetoothNamedValue>& values =
|
||||||
aValue.get_ArrayOfBluetoothNamedValue();
|
aValue.get_ArrayOfBluetoothNamedValue();
|
||||||
for (uint32_t i = 0; i < values.Length(); ++i) {
|
for (uint32_t i = 0; i < values.Length(); ++i) {
|
||||||
@ -350,6 +349,8 @@ BluetoothAdapter::Notify(const BluetoothSignal& aData)
|
|||||||
if (mDiscoveryHandleInUse) {
|
if (mDiscoveryHandleInUse) {
|
||||||
HandleDeviceFound(v);
|
HandleDeviceFound(v);
|
||||||
}
|
}
|
||||||
|
} else if (aData.name().EqualsLiteral("PairingRequest")) {
|
||||||
|
HandlePairingRequest(v);
|
||||||
} else if (aData.name().EqualsLiteral(PAIRED_STATUS_CHANGED_ID) ||
|
} else if (aData.name().EqualsLiteral(PAIRED_STATUS_CHANGED_ID) ||
|
||||||
aData.name().EqualsLiteral(HFP_STATUS_CHANGED_ID) ||
|
aData.name().EqualsLiteral(HFP_STATUS_CHANGED_ID) ||
|
||||||
aData.name().EqualsLiteral(SCO_STATUS_CHANGED_ID) ||
|
aData.name().EqualsLiteral(SCO_STATUS_CHANGED_ID) ||
|
||||||
@ -427,7 +428,7 @@ BluetoothAdapter::StartDiscovery(ErrorResult& aRv)
|
|||||||
BT_API2_LOGR();
|
BT_API2_LOGR();
|
||||||
|
|
||||||
// Clear unpaired devices before start discovery
|
// Clear unpaired devices before start discovery
|
||||||
for (uint32_t i = mDevices.Length() - 1; i >= 0; i--) {
|
for (int32_t i = mDevices.Length() - 1; i >= 0; i--) {
|
||||||
if (!mDevices[i]->Paired()) {
|
if (!mDevices[i]->Paired()) {
|
||||||
mDevices.RemoveElementAt(i);
|
mDevices.RemoveElementAt(i);
|
||||||
}
|
}
|
||||||
@ -814,6 +815,45 @@ BluetoothAdapter::HandleDeviceFound(const BluetoothValue& aValue)
|
|||||||
mDiscoveryHandleInUse->DispatchDeviceEvent(discoveredDevice);
|
mDiscoveryHandleInUse->DispatchDeviceEvent(discoveredDevice);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BluetoothAdapter::HandlePairingRequest(const BluetoothValue& aValue)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mPairingReqs);
|
||||||
|
MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfBluetoothNamedValue);
|
||||||
|
|
||||||
|
const InfallibleTArray<BluetoothNamedValue>& arr =
|
||||||
|
aValue.get_ArrayOfBluetoothNamedValue();
|
||||||
|
|
||||||
|
MOZ_ASSERT(arr.Length() == 3 &&
|
||||||
|
arr[0].value().type() == BluetoothValue::TnsString && // address
|
||||||
|
arr[1].value().type() == BluetoothValue::TnsString && // passkey
|
||||||
|
arr[2].value().type() == BluetoothValue::TnsString); // type
|
||||||
|
|
||||||
|
nsString deviceAddress = arr[0].value().get_nsString();
|
||||||
|
nsString passkey = arr[1].value().get_nsString();
|
||||||
|
nsString type = arr[2].value().get_nsString();
|
||||||
|
|
||||||
|
// Create a temporary device with deviceAddress for searching
|
||||||
|
InfallibleTArray<BluetoothNamedValue> props;
|
||||||
|
BT_APPEND_NAMED_VALUE(props, "Address", deviceAddress);
|
||||||
|
nsRefPtr<BluetoothDevice> device =
|
||||||
|
BluetoothDevice::Create(GetOwner(), props);
|
||||||
|
|
||||||
|
// Find the remote device by address
|
||||||
|
size_t index = mDevices.IndexOf(device,
|
||||||
|
0, /* aStart */
|
||||||
|
BluetoothDeviceComparator());
|
||||||
|
|
||||||
|
if (index == mDevices.NoIndex) {
|
||||||
|
BT_WARNING("Cannot find the remote device with address %s",
|
||||||
|
NS_ConvertUTF16toUTF8(deviceAddress).get());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify application of pairing requests
|
||||||
|
mPairingReqs->DispatchPairingEvent(mDevices[index], passkey, type);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothAdapter::DispatchAttributeEvent(const nsTArray<nsString>& aTypes)
|
BluetoothAdapter::DispatchAttributeEvent(const nsTArray<nsString>& aTypes)
|
||||||
{
|
{
|
||||||
|
@ -28,6 +28,7 @@ class BluetoothDevice;
|
|||||||
class BluetoothDiscoveryHandle;
|
class BluetoothDiscoveryHandle;
|
||||||
class BluetoothSignal;
|
class BluetoothSignal;
|
||||||
class BluetoothNamedValue;
|
class BluetoothNamedValue;
|
||||||
|
class BluetoothPairingListener;
|
||||||
class BluetoothValue;
|
class BluetoothValue;
|
||||||
|
|
||||||
class BluetoothAdapter : public DOMEventTargetHelper
|
class BluetoothAdapter : public DOMEventTargetHelper
|
||||||
@ -76,6 +77,11 @@ public:
|
|||||||
return mDiscoverable;
|
return mDiscoverable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BluetoothPairingListener* PairingReqs() const
|
||||||
|
{
|
||||||
|
return mPairingReqs;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update this adapter's discovery handle in use (mDiscoveryHandleInUse).
|
* Update this adapter's discovery handle in use (mDiscoveryHandleInUse).
|
||||||
*
|
*
|
||||||
@ -169,6 +175,7 @@ private:
|
|||||||
void GetPairedDeviceProperties(const nsTArray<nsString>& aDeviceAddresses);
|
void GetPairedDeviceProperties(const nsTArray<nsString>& aDeviceAddresses);
|
||||||
|
|
||||||
void HandleDeviceFound(const BluetoothValue& aValue);
|
void HandleDeviceFound(const BluetoothValue& aValue);
|
||||||
|
void HandlePairingRequest(const BluetoothValue& aValue);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mDevices holds references of all created device objects.
|
* mDevices holds references of all created device objects.
|
||||||
@ -187,6 +194,7 @@ private:
|
|||||||
*/
|
*/
|
||||||
nsTArray<nsRefPtr<BluetoothDevice> > mDevices;
|
nsTArray<nsRefPtr<BluetoothDevice> > mDevices;
|
||||||
nsRefPtr<BluetoothDiscoveryHandle> mDiscoveryHandleInUse;
|
nsRefPtr<BluetoothDiscoveryHandle> mDiscoveryHandleInUse;
|
||||||
|
nsRefPtr<BluetoothPairingListener> mPairingReqs;
|
||||||
BluetoothAdapterState mState;
|
BluetoothAdapterState mState;
|
||||||
nsString mAddress;
|
nsString mAddress;
|
||||||
nsString mName;
|
nsString mName;
|
||||||
|
75
dom/bluetooth2/BluetoothPairingListener.cpp
Normal file
75
dom/bluetooth2/BluetoothPairingListener.cpp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
#include "mozilla/dom/bluetooth/BluetoothPairingListener.h"
|
||||||
|
#include "mozilla/dom/bluetooth/BluetoothPairingHandle.h"
|
||||||
|
#include "mozilla/dom/BluetoothPairingEvent.h"
|
||||||
|
#include "mozilla/dom/BluetoothPairingListenerBinding.h"
|
||||||
|
|
||||||
|
USING_BLUETOOTH_NAMESPACE
|
||||||
|
|
||||||
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BluetoothPairingListener)
|
||||||
|
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||||
|
|
||||||
|
NS_IMPL_ADDREF_INHERITED(BluetoothPairingListener, DOMEventTargetHelper)
|
||||||
|
NS_IMPL_RELEASE_INHERITED(BluetoothPairingListener, DOMEventTargetHelper)
|
||||||
|
|
||||||
|
BluetoothPairingListener::BluetoothPairingListener(nsPIDOMWindow* aWindow)
|
||||||
|
: DOMEventTargetHelper(aWindow)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aWindow);
|
||||||
|
MOZ_ASSERT(IsDOMBinding());
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<BluetoothPairingListener>
|
||||||
|
BluetoothPairingListener::Create(nsPIDOMWindow* aWindow)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
MOZ_ASSERT(aWindow);
|
||||||
|
|
||||||
|
nsRefPtr<BluetoothPairingListener> handle =
|
||||||
|
new BluetoothPairingListener(aWindow);
|
||||||
|
|
||||||
|
return handle.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
BluetoothPairingListener::~BluetoothPairingListener()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BluetoothPairingListener::DispatchPairingEvent(BluetoothDevice* aDevice,
|
||||||
|
const nsAString& aPasskey,
|
||||||
|
const nsAString& aType)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aDevice && !aType.IsEmpty());
|
||||||
|
|
||||||
|
nsString address;
|
||||||
|
aDevice->GetAddress(address);
|
||||||
|
|
||||||
|
nsRefPtr<BluetoothPairingHandle> handle =
|
||||||
|
BluetoothPairingHandle::Create(GetOwner(),
|
||||||
|
address,
|
||||||
|
aType,
|
||||||
|
aPasskey);
|
||||||
|
|
||||||
|
BluetoothPairingEventInit init;
|
||||||
|
init.mDevice = aDevice;
|
||||||
|
init.mHandle = handle;
|
||||||
|
|
||||||
|
nsRefPtr<BluetoothPairingEvent> event =
|
||||||
|
BluetoothPairingEvent::Constructor(this,
|
||||||
|
aType,
|
||||||
|
init);
|
||||||
|
|
||||||
|
DispatchTrustedEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSObject*
|
||||||
|
BluetoothPairingListener::WrapObject(JSContext* aCx)
|
||||||
|
{
|
||||||
|
return BluetoothPairingListenerBinding::Wrap(aCx, this);
|
||||||
|
}
|
49
dom/bluetooth2/BluetoothPairingListener.h
Normal file
49
dom/bluetooth2/BluetoothPairingListener.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_dom_bluetooth_bluetoothpairinglistener_h
|
||||||
|
#define mozilla_dom_bluetooth_bluetoothpairinglistener_h
|
||||||
|
|
||||||
|
#include "BluetoothCommon.h"
|
||||||
|
#include "mozilla/Attributes.h"
|
||||||
|
#include "mozilla/DOMEventTargetHelper.h"
|
||||||
|
|
||||||
|
BEGIN_BLUETOOTH_NAMESPACE
|
||||||
|
|
||||||
|
class BluetoothDevice;
|
||||||
|
|
||||||
|
class BluetoothPairingListener MOZ_FINAL : public DOMEventTargetHelper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
|
||||||
|
static already_AddRefed<BluetoothPairingListener>
|
||||||
|
Create(nsPIDOMWindow* aWindow);
|
||||||
|
|
||||||
|
void DispatchPairingEvent(BluetoothDevice* aDevice,
|
||||||
|
const nsAString& aPasskey,
|
||||||
|
const nsAString& aType);
|
||||||
|
|
||||||
|
nsPIDOMWindow* GetParentObject() const
|
||||||
|
{
|
||||||
|
return GetOwner();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
IMPL_EVENT_HANDLER(displaypasskeyreq);
|
||||||
|
IMPL_EVENT_HANDLER(enterpincodereq);
|
||||||
|
IMPL_EVENT_HANDLER(pairingconfirmationreq);
|
||||||
|
IMPL_EVENT_HANDLER(pairingconsentreq);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BluetoothPairingListener(nsPIDOMWindow* aWindow);
|
||||||
|
~BluetoothPairingListener();
|
||||||
|
};
|
||||||
|
|
||||||
|
END_BLUETOOTH_NAMESPACE
|
||||||
|
|
||||||
|
#endif // mozilla_dom_bluetooth_bluetoothpairinglistener_h
|
@ -344,20 +344,13 @@ BluetoothService::DistributeSignal(const BluetoothSignal& aSignal)
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
if (aSignal.path().EqualsLiteral(KEY_LOCAL_AGENT)) {
|
|
||||||
Notify(aSignal);
|
|
||||||
return;
|
|
||||||
} else if (aSignal.path().EqualsLiteral(KEY_REMOTE_AGENT)) {
|
|
||||||
Notify(aSignal);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BluetoothSignalObserverList* ol;
|
BluetoothSignalObserverList* ol;
|
||||||
if (!mBluetoothSignalObserverTable.Get(aSignal.path(), &ol)) {
|
if (!mBluetoothSignalObserverTable.Get(aSignal.path(), &ol)) {
|
||||||
BT_WARNING("No observer registered for path %s",
|
BT_WARNING("No observer registered for path %s",
|
||||||
NS_ConvertUTF16toUTF8(aSignal.path()).get());
|
NS_ConvertUTF16toUTF8(aSignal.path()).get());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(ol->Length());
|
MOZ_ASSERT(ol->Length());
|
||||||
ol->Broadcast(aSignal);
|
ol->Broadcast(aSignal);
|
||||||
}
|
}
|
||||||
@ -735,52 +728,3 @@ BluetoothService::FireAdapterStateChanged(bool aEnable)
|
|||||||
NS_LITERAL_STRING(KEY_ADAPTER), value);
|
NS_LITERAL_STRING(KEY_ADAPTER), value);
|
||||||
DistributeSignal(signal);
|
DistributeSignal(signal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
BluetoothService::Notify(const BluetoothSignal& aData)
|
|
||||||
{
|
|
||||||
nsString type = NS_LITERAL_STRING("bluetooth-pairing-request");
|
|
||||||
|
|
||||||
AutoSafeJSContext cx;
|
|
||||||
JS::Rooted<JSObject*> obj(cx, JS_NewObject(cx, nullptr, JS::NullPtr(),
|
|
||||||
JS::NullPtr()));
|
|
||||||
NS_ENSURE_TRUE_VOID(obj);
|
|
||||||
|
|
||||||
if (!SetJsObject(cx, aData.value(), obj)) {
|
|
||||||
BT_WARNING("Failed to set properties of system message!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BT_LOGD("[S] %s: %s", __FUNCTION__, NS_ConvertUTF16toUTF8(aData.name()).get());
|
|
||||||
|
|
||||||
if (aData.name().EqualsLiteral("RequestConfirmation")) {
|
|
||||||
MOZ_ASSERT(aData.value().get_ArrayOfBluetoothNamedValue().Length() == 4,
|
|
||||||
"RequestConfirmation: Wrong length of parameters");
|
|
||||||
} else if (aData.name().EqualsLiteral("RequestPinCode")) {
|
|
||||||
MOZ_ASSERT(aData.value().get_ArrayOfBluetoothNamedValue().Length() == 3,
|
|
||||||
"RequestPinCode: Wrong length of parameters");
|
|
||||||
} else if (aData.name().EqualsLiteral("RequestPasskey")) {
|
|
||||||
MOZ_ASSERT(aData.value().get_ArrayOfBluetoothNamedValue().Length() == 3,
|
|
||||||
"RequestPinCode: Wrong length of parameters");
|
|
||||||
} else if (aData.name().EqualsLiteral("Cancel")) {
|
|
||||||
MOZ_ASSERT(aData.value().get_ArrayOfBluetoothNamedValue().Length() == 0,
|
|
||||||
"Cancel: Wrong length of parameters");
|
|
||||||
type.AssignLiteral("bluetooth-cancel");
|
|
||||||
} else if (aData.name().EqualsLiteral(PAIRED_STATUS_CHANGED_ID)) {
|
|
||||||
MOZ_ASSERT(aData.value().get_ArrayOfBluetoothNamedValue().Length() == 1,
|
|
||||||
"pairedstatuschanged: Wrong length of parameters");
|
|
||||||
type.AssignLiteral("bluetooth-pairedstatuschanged");
|
|
||||||
} else {
|
|
||||||
BT_WARNING("Not handling service signal: %s",
|
|
||||||
NS_ConvertUTF16toUTF8(aData.name()).get());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsISystemMessagesInternal> systemMessenger =
|
|
||||||
do_GetService("@mozilla.org/system-message-internal;1");
|
|
||||||
NS_ENSURE_TRUE_VOID(systemMessenger);
|
|
||||||
|
|
||||||
JS::Rooted<JS::Value> value(cx, JS::ObjectValue(*obj));
|
|
||||||
systemMessenger->BroadcastMessage(type, value,
|
|
||||||
JS::UndefinedHandleValue);
|
|
||||||
}
|
|
||||||
|
@ -33,7 +33,6 @@ class BluetoothSignal;
|
|||||||
typedef mozilla::ObserverList<BluetoothSignal> BluetoothSignalObserverList;
|
typedef mozilla::ObserverList<BluetoothSignal> BluetoothSignalObserverList;
|
||||||
|
|
||||||
class BluetoothService : public nsIObserver
|
class BluetoothService : public nsIObserver
|
||||||
, public BluetoothSignalObserver
|
|
||||||
{
|
{
|
||||||
class ToggleBtTask;
|
class ToggleBtTask;
|
||||||
friend class ToggleBtTask;
|
friend class ToggleBtTask;
|
||||||
@ -97,13 +96,6 @@ public:
|
|||||||
void
|
void
|
||||||
DistributeSignal(const BluetoothSignal& aEvent);
|
DistributeSignal(const BluetoothSignal& aEvent);
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when get a Bluetooth Signal from BluetoothDBusService
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
Notify(const BluetoothSignal& aParam);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the BluetoothService singleton. Only to be called from main thread.
|
* Returns the BluetoothService singleton. Only to be called from main thread.
|
||||||
*
|
*
|
||||||
|
@ -632,23 +632,22 @@ PinRequestCallback(bt_bdaddr_t* aRemoteBdAddress,
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(!NS_IsMainThread());
|
MOZ_ASSERT(!NS_IsMainThread());
|
||||||
|
|
||||||
InfallibleTArray<BluetoothNamedValue> propertiesArray;
|
InfallibleTArray<BluetoothNamedValue> props;
|
||||||
nsAutoString remoteAddress;
|
nsAutoString deviceAddress;
|
||||||
BdAddressTypeToString(aRemoteBdAddress, remoteAddress);
|
BdAddressTypeToString(aRemoteBdAddress, deviceAddress);
|
||||||
|
|
||||||
BT_APPEND_NAMED_VALUE(propertiesArray, "address", remoteAddress);
|
BT_APPEND_NAMED_VALUE(props, "address", deviceAddress);
|
||||||
BT_APPEND_NAMED_VALUE(propertiesArray, "method",
|
BT_APPEND_NAMED_VALUE(props, "passkey", EmptyString());
|
||||||
NS_LITERAL_STRING("pincode"));
|
BT_APPEND_NAMED_VALUE(props, "type",
|
||||||
BT_APPEND_NAMED_VALUE(propertiesArray, "name",
|
NS_LITERAL_STRING(PAIRING_REQ_TYPE_ENTERPINCODE));
|
||||||
NS_ConvertUTF8toUTF16(
|
|
||||||
(const char*)aRemoteBdName->name));
|
|
||||||
|
|
||||||
BluetoothValue value = propertiesArray;
|
BluetoothSignal signal(NS_LITERAL_STRING("PairingRequest"),
|
||||||
BluetoothSignal signal(NS_LITERAL_STRING("RequestPinCode"),
|
NS_LITERAL_STRING(KEY_ADAPTER),
|
||||||
NS_LITERAL_STRING(KEY_LOCAL_AGENT), value);
|
BluetoothValue(props));
|
||||||
nsRefPtr<DistributeBluetoothSignalTask>
|
|
||||||
t = new DistributeBluetoothSignalTask(signal);
|
nsRefPtr<DistributeBluetoothSignalTask> task =
|
||||||
if (NS_FAILED(NS_DispatchToMainThread(t))) {
|
new DistributeBluetoothSignalTask(signal);
|
||||||
|
if (NS_FAILED(NS_DispatchToMainThread(task))) {
|
||||||
BT_WARNING("Failed to dispatch to main thread!");
|
BT_WARNING("Failed to dispatch to main thread!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -660,24 +659,49 @@ SspRequestCallback(bt_bdaddr_t* aRemoteBdAddress, bt_bdname_t* aRemoteBdName,
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(!NS_IsMainThread());
|
MOZ_ASSERT(!NS_IsMainThread());
|
||||||
|
|
||||||
InfallibleTArray<BluetoothNamedValue> propertiesArray;
|
InfallibleTArray<BluetoothNamedValue> props;
|
||||||
nsAutoString remoteAddress;
|
nsAutoString deviceAddress;
|
||||||
BdAddressTypeToString(aRemoteBdAddress, remoteAddress);
|
BdAddressTypeToString(aRemoteBdAddress, deviceAddress);
|
||||||
|
|
||||||
BT_APPEND_NAMED_VALUE(propertiesArray, "address", remoteAddress);
|
nsAutoString passkey;
|
||||||
BT_APPEND_NAMED_VALUE(propertiesArray, "method",
|
nsAutoString pairingType;
|
||||||
NS_LITERAL_STRING("confirmation"));
|
|
||||||
BT_APPEND_NAMED_VALUE(propertiesArray, "name",
|
|
||||||
NS_ConvertUTF8toUTF16(
|
|
||||||
(const char*)aRemoteBdName->name));
|
|
||||||
BT_APPEND_NAMED_VALUE(propertiesArray, "passkey", aPasskey);
|
|
||||||
|
|
||||||
BluetoothValue value = propertiesArray;
|
/**
|
||||||
BluetoothSignal signal(NS_LITERAL_STRING("RequestConfirmation"),
|
* Assign pairing request type and passkey based on the pairing variant.
|
||||||
NS_LITERAL_STRING(KEY_LOCAL_AGENT), value);
|
*
|
||||||
nsRefPtr<DistributeBluetoothSignalTask>
|
* passkey value based on pairing request type:
|
||||||
t = new DistributeBluetoothSignalTask(signal);
|
* 1) aPasskey: PAIRING_REQ_TYPE_CONFIRMATION and
|
||||||
if (NS_FAILED(NS_DispatchToMainThread(t))) {
|
* PAIRING_REQ_TYPE_DISPLAYPASSKEY
|
||||||
|
* 2) empty string: PAIRING_REQ_TYPE_CONSENT
|
||||||
|
*/
|
||||||
|
switch (aPairingVariant) {
|
||||||
|
case BT_SSP_VARIANT_PASSKEY_CONFIRMATION:
|
||||||
|
pairingType.AssignLiteral(PAIRING_REQ_TYPE_CONFIRMATION);
|
||||||
|
passkey.AppendInt(aPasskey);
|
||||||
|
break;
|
||||||
|
case BT_SSP_VARIANT_PASSKEY_NOTIFICATION:
|
||||||
|
pairingType.AssignLiteral(PAIRING_REQ_TYPE_DISPLAYPASSKEY);
|
||||||
|
passkey.AppendInt(aPasskey);
|
||||||
|
break;
|
||||||
|
case BT_SSP_VARIANT_CONSENT:
|
||||||
|
pairingType.AssignLiteral(PAIRING_REQ_TYPE_CONSENT);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BT_WARNING("Unhandled SSP Bonding Variant: %d", aPairingVariant);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BT_APPEND_NAMED_VALUE(props, "address", deviceAddress);
|
||||||
|
BT_APPEND_NAMED_VALUE(props, "passkey", passkey);
|
||||||
|
BT_APPEND_NAMED_VALUE(props, "type", pairingType);
|
||||||
|
|
||||||
|
BluetoothSignal signal(NS_LITERAL_STRING("PairingRequest"),
|
||||||
|
NS_LITERAL_STRING(KEY_ADAPTER),
|
||||||
|
BluetoothValue(props));
|
||||||
|
|
||||||
|
nsRefPtr<DistributeBluetoothSignalTask> task =
|
||||||
|
new DistributeBluetoothSignalTask(signal);
|
||||||
|
if (NS_FAILED(NS_DispatchToMainThread(task))) {
|
||||||
BT_WARNING("Failed to dispatch to main thread!");
|
BT_WARNING("Failed to dispatch to main thread!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ if CONFIG['MOZ_B2G_BT']:
|
|||||||
'BluetoothHidManager.cpp',
|
'BluetoothHidManager.cpp',
|
||||||
'BluetoothManager.cpp',
|
'BluetoothManager.cpp',
|
||||||
'BluetoothPairingHandle.cpp',
|
'BluetoothPairingHandle.cpp',
|
||||||
|
'BluetoothPairingListener.cpp',
|
||||||
'BluetoothProfileController.cpp',
|
'BluetoothProfileController.cpp',
|
||||||
'BluetoothReplyRunnable.cpp',
|
'BluetoothReplyRunnable.cpp',
|
||||||
'BluetoothService.cpp',
|
'BluetoothService.cpp',
|
||||||
@ -106,6 +107,7 @@ EXPORTS.mozilla.dom.bluetooth += [
|
|||||||
'BluetoothDiscoveryHandle.h',
|
'BluetoothDiscoveryHandle.h',
|
||||||
'BluetoothManager.h',
|
'BluetoothManager.h',
|
||||||
'BluetoothPairingHandle.h',
|
'BluetoothPairingHandle.h',
|
||||||
|
'BluetoothPairingListener.h',
|
||||||
]
|
]
|
||||||
|
|
||||||
IPDL_SOURCES += [
|
IPDL_SOURCES += [
|
||||||
|
@ -580,10 +580,6 @@ WebGLContext::CopyTexSubImage2D(GLenum target,
|
|||||||
if (yoffset + height > texHeight || yoffset + height < 0)
|
if (yoffset + height > texHeight || yoffset + height < 0)
|
||||||
return ErrorInvalidValue("copyTexSubImage2D: yoffset+height is too large");
|
return ErrorInvalidValue("copyTexSubImage2D: yoffset+height is too large");
|
||||||
|
|
||||||
GLenum webGLFormat = imageInfo.WebGLFormat();
|
|
||||||
if (IsGLDepthFormat(webGLFormat) || IsGLDepthStencilFormat(webGLFormat))
|
|
||||||
return ErrorInvalidOperation("copyTexSubImage2D: a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL isn't supported");
|
|
||||||
|
|
||||||
if (mBoundFramebuffer) {
|
if (mBoundFramebuffer) {
|
||||||
if (!mBoundFramebuffer->CheckAndInitializeAttachments())
|
if (!mBoundFramebuffer->CheckAndInitializeAttachments())
|
||||||
return ErrorInvalidFramebufferOperation("copyTexSubImage2D: incomplete framebuffer");
|
return ErrorInvalidFramebufferOperation("copyTexSubImage2D: incomplete framebuffer");
|
||||||
@ -597,6 +593,7 @@ WebGLContext::CopyTexSubImage2D(GLenum target,
|
|||||||
ClearBackbufferIfNeeded();
|
ClearBackbufferIfNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLenum webGLFormat = imageInfo.WebGLFormat();
|
||||||
bool texFormatRequiresAlpha = FormatHasAlpha(webGLFormat);
|
bool texFormatRequiresAlpha = FormatHasAlpha(webGLFormat);
|
||||||
bool fboFormatHasAlpha = mBoundFramebuffer ? mBoundFramebuffer->ColorAttachment(0).HasAlpha()
|
bool fboFormatHasAlpha = mBoundFramebuffer ? mBoundFramebuffer->ColorAttachment(0).HasAlpha()
|
||||||
: bool(gl->GetPixelFormat().alpha > 0);
|
: bool(gl->GetPixelFormat().alpha > 0);
|
||||||
|
@ -527,6 +527,31 @@ WebGLContext::ValidateTexImageFormat(GLenum format, WebGLTexImageFunc func)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* WEBGL_depth_texture added formats */
|
||||||
|
if (format == LOCAL_GL_DEPTH_COMPONENT ||
|
||||||
|
format == LOCAL_GL_DEPTH_STENCIL)
|
||||||
|
{
|
||||||
|
if (!IsExtensionEnabled(WebGLExtensionID::WEBGL_depth_texture)) {
|
||||||
|
ErrorInvalidEnum("%s: invalid format %s: need WEBGL_depth_texture enabled",
|
||||||
|
InfoFrom(func), EnumName(format));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If WEBGL_depth_texture is enabled, then it is not allowed to be used with the
|
||||||
|
// texSubImage, copyTexImage, or copyTexSubImage methods
|
||||||
|
if (func == WebGLTexImageFunc::TexSubImage ||
|
||||||
|
func == WebGLTexImageFunc::CopyTexImage ||
|
||||||
|
func == WebGLTexImageFunc::CopyTexSubImage)
|
||||||
|
{
|
||||||
|
ErrorInvalidOperation("%s: format %s is not supported", InfoFrom(func), EnumName(format));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Needs to be below the depth_texture check because an invalid operation
|
||||||
|
// error needs to be generated instead of invalid enum.
|
||||||
/* Only core formats are valid for CopyTex(Sub)?Image */
|
/* Only core formats are valid for CopyTex(Sub)?Image */
|
||||||
// TODO: Revisit this once color_buffer_(half_)?float lands
|
// TODO: Revisit this once color_buffer_(half_)?float lands
|
||||||
if (IsCopyFunc(func)) {
|
if (IsCopyFunc(func)) {
|
||||||
@ -534,17 +559,6 @@ WebGLContext::ValidateTexImageFormat(GLenum format, WebGLTexImageFunc func)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* WEBGL_depth_texture added formats */
|
|
||||||
if (format == LOCAL_GL_DEPTH_COMPONENT ||
|
|
||||||
format == LOCAL_GL_DEPTH_STENCIL)
|
|
||||||
{
|
|
||||||
bool validFormat = IsExtensionEnabled(WebGLExtensionID::WEBGL_depth_texture);
|
|
||||||
if (!validFormat)
|
|
||||||
ErrorInvalidEnum("%s: invalid format %s: need WEBGL_depth_texture enabled",
|
|
||||||
InfoFrom(func), WebGLContext::EnumName(format));
|
|
||||||
return validFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EXT_sRGB added formats */
|
/* EXT_sRGB added formats */
|
||||||
if (format == LOCAL_GL_SRGB ||
|
if (format == LOCAL_GL_SRGB ||
|
||||||
format == LOCAL_GL_SRGB_ALPHA)
|
format == LOCAL_GL_SRGB_ALPHA)
|
||||||
|
@ -14,29 +14,29 @@ HZ-GB-2312=zh-CN
|
|||||||
IBM866=x-cyrillic
|
IBM866=x-cyrillic
|
||||||
ISO-2022-JP=ja
|
ISO-2022-JP=ja
|
||||||
ISO-8859-3=x-western
|
ISO-8859-3=x-western
|
||||||
ISO-8859-4=x-baltic
|
ISO-8859-4=x-western
|
||||||
ISO-8859-5=x-cyrillic
|
ISO-8859-5=x-cyrillic
|
||||||
ISO-8859-6=ar
|
ISO-8859-6=ar
|
||||||
ISO-8859-7=el
|
ISO-8859-7=el
|
||||||
ISO-8859-8=he
|
ISO-8859-8=he
|
||||||
ISO-8859-8-I=he
|
ISO-8859-8-I=he
|
||||||
ISO-8859-10=x-western
|
ISO-8859-10=x-western
|
||||||
ISO-8859-13=x-baltic
|
ISO-8859-13=x-western
|
||||||
ISO-8859-14=x-western
|
ISO-8859-14=x-western
|
||||||
ISO-8859-15=x-western
|
ISO-8859-15=x-western
|
||||||
ISO-8859-16=x-central-euro
|
ISO-8859-16=x-western
|
||||||
ISO-8859-2=x-central-euro
|
ISO-8859-2=x-western
|
||||||
KOI8-R=x-cyrillic
|
KOI8-R=x-cyrillic
|
||||||
KOI8-U=x-cyrillic
|
KOI8-U=x-cyrillic
|
||||||
Shift_JIS=ja
|
Shift_JIS=ja
|
||||||
windows-1250=x-central-euro
|
windows-1250=x-western
|
||||||
windows-1251=x-cyrillic
|
windows-1251=x-cyrillic
|
||||||
windows-1252=x-western
|
windows-1252=x-western
|
||||||
windows-1253=el
|
windows-1253=el
|
||||||
windows-1254=tr
|
windows-1254=x-western
|
||||||
windows-1255=he
|
windows-1255=he
|
||||||
windows-1256=ar
|
windows-1256=ar
|
||||||
windows-1257=x-baltic
|
windows-1257=x-western
|
||||||
windows-1258=x-western
|
windows-1258=x-western
|
||||||
windows-874=th
|
windows-874=th
|
||||||
x-mac-cyrillic=x-cyrillic
|
x-mac-cyrillic=x-cyrillic
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "FMRadioService.h"
|
#include "FMRadioService.h"
|
||||||
#include "mozilla/Hal.h"
|
#include "mozilla/Hal.h"
|
||||||
|
#include "mozilla/ClearOnShutdown.h"
|
||||||
#include "nsIAudioManager.h"
|
#include "nsIAudioManager.h"
|
||||||
#include "AudioManager.h"
|
#include "AudioManager.h"
|
||||||
#include "nsDOMClassInfo.h"
|
#include "nsDOMClassInfo.h"
|
||||||
@ -832,6 +833,7 @@ FMRadioService::Singleton()
|
|||||||
|
|
||||||
if (!sFMRadioService) {
|
if (!sFMRadioService) {
|
||||||
sFMRadioService = new FMRadioService();
|
sFMRadioService = new FMRadioService();
|
||||||
|
ClearOnShutdown(&sFMRadioService);
|
||||||
}
|
}
|
||||||
|
|
||||||
return sFMRadioService;
|
return sFMRadioService;
|
||||||
|
@ -918,7 +918,7 @@ ContentChild::RecvSetProcessSandbox()
|
|||||||
// at some point; see bug 880808.
|
// at some point; see bug 880808.
|
||||||
#if defined(MOZ_CONTENT_SANDBOX)
|
#if defined(MOZ_CONTENT_SANDBOX)
|
||||||
#if defined(XP_LINUX)
|
#if defined(XP_LINUX)
|
||||||
SetCurrentProcessSandbox();
|
SetContentProcessSandbox();
|
||||||
#elif defined(XP_WIN)
|
#elif defined(XP_WIN)
|
||||||
mozilla::SandboxTarget::Instance()->StartSandbox();
|
mozilla::SandboxTarget::Instance()->StartSandbox();
|
||||||
#endif
|
#endif
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
[NoInterfaceObject]
|
[NoInterfaceObject, Exposed=(Window,Worker)]
|
||||||
interface AbstractWorker {
|
interface AbstractWorker {
|
||||||
attribute EventHandler onerror;
|
attribute EventHandler onerror;
|
||||||
};
|
};
|
||||||
|
@ -58,6 +58,9 @@ interface BluetoothAdapter : EventTarget {
|
|||||||
readonly attribute boolean discoverable;
|
readonly attribute boolean discoverable;
|
||||||
readonly attribute boolean discovering;
|
readonly attribute boolean discovering;
|
||||||
|
|
||||||
|
[AvailableIn=CertifiedApps]
|
||||||
|
readonly attribute BluetoothPairingListener pairingReqs;
|
||||||
|
|
||||||
// Fired when pairing process is completed
|
// Fired when pairing process is completed
|
||||||
attribute EventHandler onpairedstatuschanged;
|
attribute EventHandler onpairedstatuschanged;
|
||||||
|
|
||||||
|
13
dom/webidl/BluetoothPairingListener.webidl
Normal file
13
dom/webidl/BluetoothPairingListener.webidl
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
[AvailableIn=CertifiedApps, CheckPermissions="bluetooth"]
|
||||||
|
interface BluetoothPairingListener: EventTarget
|
||||||
|
{
|
||||||
|
attribute EventHandler ondisplaypasskeyreq;
|
||||||
|
attribute EventHandler onenterpincodereq;
|
||||||
|
attribute EventHandler onpairingconfirmationreq;
|
||||||
|
attribute EventHandler onpairingconsentreq;
|
||||||
|
};
|
@ -4,7 +4,8 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
[ChromeOnly]
|
[ChromeOnly,
|
||||||
|
Exposed=(Window,Worker)]
|
||||||
interface Console {
|
interface Console {
|
||||||
void log(any... data);
|
void log(any... data);
|
||||||
void info(any... data);
|
void info(any... data);
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
|
|
||||||
interface StackFrame;
|
interface StackFrame;
|
||||||
|
|
||||||
[NoInterfaceObject]
|
[NoInterfaceObject,
|
||||||
|
Exposed=(Window,Worker)]
|
||||||
interface ExceptionMembers
|
interface ExceptionMembers
|
||||||
{
|
{
|
||||||
// A custom message set by the thrower. LenientThis so it can be
|
// A custom message set by the thrower. LenientThis so it can be
|
||||||
@ -72,7 +73,8 @@ Exception implements ExceptionMembers;
|
|||||||
|
|
||||||
// XXXkhuey this is an 'exception', not an interface, but we don't have any
|
// XXXkhuey this is an 'exception', not an interface, but we don't have any
|
||||||
// parser or codegen mechanisms for dealing with exceptions.
|
// parser or codegen mechanisms for dealing with exceptions.
|
||||||
[ExceptionClass]
|
[ExceptionClass,
|
||||||
|
Exposed=(Window, Worker)]
|
||||||
interface DOMException {
|
interface DOMException {
|
||||||
const unsigned short INDEX_SIZE_ERR = 1;
|
const unsigned short INDEX_SIZE_ERR = 1;
|
||||||
const unsigned short DOMSTRING_SIZE_ERR = 2; // historical
|
const unsigned short DOMSTRING_SIZE_ERR = 2; // historical
|
||||||
|
@ -12,7 +12,8 @@ typedef (DOMString or unsigned long) DataStoreKey;
|
|||||||
// JS codes implemented by the DataStoreImpl WebIDL.
|
// JS codes implemented by the DataStoreImpl WebIDL.
|
||||||
|
|
||||||
[Func="Navigator::HasDataStoreSupport",
|
[Func="Navigator::HasDataStoreSupport",
|
||||||
ChromeConstructor]
|
ChromeConstructor,
|
||||||
|
Exposed=(Window,Worker)]
|
||||||
interface DataStore : EventTarget {
|
interface DataStore : EventTarget {
|
||||||
// Returns the label of the DataSource.
|
// Returns the label of the DataSource.
|
||||||
[GetterThrows]
|
[GetterThrows]
|
||||||
@ -65,8 +66,9 @@ partial interface DataStore {
|
|||||||
// which currently plays a role of C++ proxy directing to the
|
// which currently plays a role of C++ proxy directing to the
|
||||||
// JS codes implemented by the DataStoreCursorImpl WebIDL.
|
// JS codes implemented by the DataStoreCursorImpl WebIDL.
|
||||||
|
|
||||||
[Pref="dom.datastore.enabled",
|
[Func="Navigator::HasDataStoreSupport",
|
||||||
ChromeConstructor]
|
ChromeConstructor,
|
||||||
|
Exposed=(Window,Worker)]
|
||||||
interface DataStoreCursor {
|
interface DataStoreCursor {
|
||||||
// the DataStore
|
// the DataStore
|
||||||
[GetterThrows]
|
[GetterThrows]
|
||||||
|
@ -12,7 +12,8 @@
|
|||||||
* this document.
|
* this document.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
[Global, Func="mozilla::dom::workers::DedicatedWorkerGlobalScope::Visible"]
|
[Global=(Worker,DedicatedWorker),
|
||||||
|
Exposed=DedicatedWorker]
|
||||||
interface DedicatedWorkerGlobalScope : WorkerGlobalScope {
|
interface DedicatedWorkerGlobalScope : WorkerGlobalScope {
|
||||||
[Throws]
|
[Throws]
|
||||||
void postMessage(any message, optional sequence<any> transfer);
|
void postMessage(any message, optional sequence<any> transfer);
|
||||||
|
@ -10,7 +10,8 @@
|
|||||||
* liability, trademark and document use rules apply.
|
* liability, trademark and document use rules apply.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
[Constructor(DOMString type, optional EventInit eventInitDict)]
|
[Constructor(DOMString type, optional EventInit eventInitDict),
|
||||||
|
Exposed=(Window,Worker)]
|
||||||
interface Event {
|
interface Event {
|
||||||
[Pure]
|
[Pure]
|
||||||
readonly attribute DOMString type;
|
readonly attribute DOMString type;
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
* liability, trademark and document use rules apply.
|
* liability, trademark and document use rules apply.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
[Exposed=(Window,Worker)]
|
||||||
interface EventTarget {
|
interface EventTarget {
|
||||||
/* Passing null for wantsUntrusted means "default behavior", which
|
/* Passing null for wantsUntrusted means "default behavior", which
|
||||||
differs in content and chrome. In content that default boolean
|
differs in content and chrome. In content that default boolean
|
||||||
|
@ -12,7 +12,8 @@
|
|||||||
|
|
||||||
interface Blob;
|
interface Blob;
|
||||||
|
|
||||||
[Constructor]
|
[Constructor,
|
||||||
|
Exposed=Worker]
|
||||||
interface FileReaderSync {
|
interface FileReaderSync {
|
||||||
|
|
||||||
// Synchronously return strings
|
// Synchronously return strings
|
||||||
|
@ -19,7 +19,7 @@ enum HeadersGuardEnum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
[Constructor(optional HeadersInit init),
|
[Constructor(optional HeadersInit init),
|
||||||
// FIXME: Exposed=Window,Worker,
|
Exposed=(Window,Worker),
|
||||||
Func="mozilla::dom::Headers::PrefEnabled"]
|
Func="mozilla::dom::Headers::PrefEnabled"]
|
||||||
interface Headers {
|
interface Headers {
|
||||||
[Throws] void append(ByteString name, ByteString value);
|
[Throws] void append(ByteString name, ByteString value);
|
||||||
|
@ -11,7 +11,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
[Constructor(unsigned long sw, unsigned long sh),
|
[Constructor(unsigned long sw, unsigned long sh),
|
||||||
Constructor(Uint8ClampedArray data, unsigned long sw, optional unsigned long sh)]
|
Constructor(Uint8ClampedArray data, unsigned long sw, optional unsigned long sh),
|
||||||
|
Exposed=(Window,Worker)]
|
||||||
interface ImageData {
|
interface ImageData {
|
||||||
[Constant]
|
[Constant]
|
||||||
readonly attribute unsigned long width;
|
readonly attribute unsigned long width;
|
||||||
|
@ -10,7 +10,11 @@
|
|||||||
// While not explicitly restricted to ServiceWorkerGlobalScope, it probably
|
// While not explicitly restricted to ServiceWorkerGlobalScope, it probably
|
||||||
// should be. https://github.com/slightlyoff/ServiceWorker/issues/254
|
// should be. https://github.com/slightlyoff/ServiceWorker/issues/254
|
||||||
[Constructor(DOMString type, optional InstallEventInit eventInitDict),
|
[Constructor(DOMString type, optional InstallEventInit eventInitDict),
|
||||||
Func="mozilla::dom::workers::ServiceWorkerEventsVisible"]
|
Func="mozilla::dom::workers::ServiceWorkerEventsVisible",
|
||||||
|
// XXXbz I have no idea where this should be exposed. The spec makes
|
||||||
|
// no sense. But since it returns a ServiceWorker and that's only
|
||||||
|
// exposed in Window, let's say Window.
|
||||||
|
Exposed=Window]
|
||||||
interface InstallEvent : InstallPhaseEvent {
|
interface InstallEvent : InstallPhaseEvent {
|
||||||
// The currently active worker for this scope when this worker is asked to
|
// The currently active worker for this scope when this worker is asked to
|
||||||
// install itself.
|
// install itself.
|
||||||
|
@ -10,7 +10,8 @@
|
|||||||
// While not explicitly restricted to ServiceWorkerGlobalScope, it probably
|
// While not explicitly restricted to ServiceWorkerGlobalScope, it probably
|
||||||
// should be. https://github.com/slightlyoff/ServiceWorker/issues/254
|
// should be. https://github.com/slightlyoff/ServiceWorker/issues/254
|
||||||
[Constructor(DOMString type, optional EventInit eventInitDict),
|
[Constructor(DOMString type, optional EventInit eventInitDict),
|
||||||
Func="mozilla::dom::workers::ServiceWorkerEventsVisible"]
|
Func="mozilla::dom::workers::ServiceWorkerEventsVisible",
|
||||||
|
Exposed=(ServiceWorker,Window)]
|
||||||
interface InstallPhaseEvent : Event {
|
interface InstallPhaseEvent : Event {
|
||||||
// https://github.com/slightlyoff/ServiceWorker/issues/261
|
// https://github.com/slightlyoff/ServiceWorker/issues/261
|
||||||
void waitUntil(Promise<any> p);
|
void waitUntil(Promise<any> p);
|
||||||
|
@ -7,10 +7,14 @@
|
|||||||
interface nsISupports;
|
interface nsISupports;
|
||||||
interface IID;
|
interface IID;
|
||||||
|
|
||||||
[NoInterfaceObject]
|
[NoInterfaceObject,
|
||||||
|
// Need Exposed here, because this is a mixin onto things like Event
|
||||||
|
// that are exposed in workers.
|
||||||
|
Exposed=(Window,Worker)]
|
||||||
interface LegacyQueryInterface {
|
interface LegacyQueryInterface {
|
||||||
// Legacy QueryInterface, only exposed to chrome or XBL code on the
|
// Legacy QueryInterface, only exposed to chrome or XBL code on the
|
||||||
// main thread.
|
// main thread.
|
||||||
|
[Exposed=Window]
|
||||||
nsISupports queryInterface(IID iid);
|
nsISupports queryInterface(IID iid);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -9,7 +9,8 @@
|
|||||||
|
|
||||||
interface WindowProxy;
|
interface WindowProxy;
|
||||||
|
|
||||||
[Constructor(DOMString type, optional MessageEventInit eventInitDict)]
|
[Constructor(DOMString type, optional MessageEventInit eventInitDict),
|
||||||
|
Exposed=(Window,Worker)]
|
||||||
interface MessageEvent : Event {
|
interface MessageEvent : Event {
|
||||||
/**
|
/**
|
||||||
* Custom data associated with this event.
|
* Custom data associated with this event.
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
* http://www.whatwg.org/specs/web-apps/current-work/#channel-messaging
|
* http://www.whatwg.org/specs/web-apps/current-work/#channel-messaging
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
[Exposed=(Window,Worker)]
|
||||||
interface MessagePort : EventTarget {
|
interface MessagePort : EventTarget {
|
||||||
[Throws]
|
[Throws]
|
||||||
void postMessage(any message, optional sequence<Transferable> transferable);
|
void postMessage(any message, optional sequence<Transferable> transferable);
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
[NoInterfaceObject, ArrayClass]
|
[NoInterfaceObject, ArrayClass, Exposed=(Window,Worker)]
|
||||||
interface MessagePortList {
|
interface MessagePortList {
|
||||||
readonly attribute unsigned long length;
|
readonly attribute unsigned long length;
|
||||||
getter MessagePort? item(unsigned long index);
|
getter MessagePort? item(unsigned long index);
|
||||||
|
@ -30,7 +30,7 @@ Navigator implements NavigatorContentUtils;
|
|||||||
Navigator implements NavigatorStorageUtils;
|
Navigator implements NavigatorStorageUtils;
|
||||||
Navigator implements NavigatorFeatures;
|
Navigator implements NavigatorFeatures;
|
||||||
|
|
||||||
[NoInterfaceObject]
|
[NoInterfaceObject, Exposed=(Window,Worker)]
|
||||||
interface NavigatorID {
|
interface NavigatorID {
|
||||||
// WebKit/Blink/Trident/Presto support this (hardcoded "Mozilla").
|
// WebKit/Blink/Trident/Presto support this (hardcoded "Mozilla").
|
||||||
[Constant]
|
[Constant]
|
||||||
@ -53,10 +53,11 @@ interface NavigatorID {
|
|||||||
[NoInterfaceObject]
|
[NoInterfaceObject]
|
||||||
interface NavigatorLanguage {
|
interface NavigatorLanguage {
|
||||||
readonly attribute DOMString? language;
|
readonly attribute DOMString? language;
|
||||||
[Pure, Cached, Frozen] readonly attribute sequence<DOMString> languages;
|
[Pure, Cached, Frozen]
|
||||||
|
readonly attribute sequence<DOMString> languages;
|
||||||
};
|
};
|
||||||
|
|
||||||
[NoInterfaceObject]
|
[NoInterfaceObject, Exposed=(Window,Worker)]
|
||||||
interface NavigatorOnLine {
|
interface NavigatorOnLine {
|
||||||
readonly attribute boolean onLine;
|
readonly attribute boolean onLine;
|
||||||
};
|
};
|
||||||
@ -120,7 +121,8 @@ interface NavigatorBattery {
|
|||||||
Navigator implements NavigatorBattery;
|
Navigator implements NavigatorBattery;
|
||||||
|
|
||||||
// https://wiki.mozilla.org/WebAPI/DataStore
|
// https://wiki.mozilla.org/WebAPI/DataStore
|
||||||
[NoInterfaceObject]
|
[NoInterfaceObject,
|
||||||
|
Exposed=(Window,Worker)]
|
||||||
interface NavigatorDataStore {
|
interface NavigatorDataStore {
|
||||||
[Throws, NewObject, Func="Navigator::HasDataStoreSupport"]
|
[Throws, NewObject, Func="Navigator::HasDataStoreSupport"]
|
||||||
Promise<sequence<DataStore>> getDataStores(DOMString name,
|
Promise<sequence<DataStore>> getDataStores(DOMString name,
|
||||||
|
@ -16,7 +16,8 @@ callback PromiseInit = void (object resolve, object reject);
|
|||||||
callback AnyCallback = any (any value);
|
callback AnyCallback = any (any value);
|
||||||
|
|
||||||
// REMOVE THE RELEVANT ENTRY FROM test_interfaces.html WHEN THIS IS IMPLEMENTED IN JS.
|
// REMOVE THE RELEVANT ENTRY FROM test_interfaces.html WHEN THIS IS IMPLEMENTED IN JS.
|
||||||
[Constructor(PromiseInit init)]
|
[Constructor(PromiseInit init),
|
||||||
|
Exposed=(Window,Worker)]
|
||||||
// Need to escape "Promise" so it's treated as an identifier.
|
// Need to escape "Promise" so it's treated as an identifier.
|
||||||
interface _Promise {
|
interface _Promise {
|
||||||
// TODO bug 875289 - static Promise fulfill(any value);
|
// TODO bug 875289 - static Promise fulfill(any value);
|
||||||
|
@ -10,7 +10,10 @@
|
|||||||
|
|
||||||
// Still unclear what should be subclassed.
|
// Still unclear what should be subclassed.
|
||||||
// https://github.com/slightlyoff/ServiceWorker/issues/189
|
// https://github.com/slightlyoff/ServiceWorker/issues/189
|
||||||
[Pref="dom.serviceWorkers.enabled"]
|
[Pref="dom.serviceWorkers.enabled",
|
||||||
|
// XXXbz I have no idea where this should be exposed. The spec makes
|
||||||
|
// no sense. But since it's got a pref, let's say window.
|
||||||
|
Exposed=Window]
|
||||||
interface ServiceWorker : EventTarget {
|
interface ServiceWorker : EventTarget {
|
||||||
readonly attribute DOMString scope;
|
readonly attribute DOMString scope;
|
||||||
readonly attribute DOMString url;
|
readonly attribute DOMString url;
|
||||||
|
@ -37,15 +37,14 @@ interface ServiceWorkerContainer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Testing only.
|
// Testing only.
|
||||||
[ChromeOnly, Pref="dom.serviceWorkers.testing.enabled"]
|
|
||||||
partial interface ServiceWorkerContainer {
|
partial interface ServiceWorkerContainer {
|
||||||
[Throws]
|
[Throws,Pref="dom.serviceWorkers.testing.enabled"]
|
||||||
Promise<any> clearAllServiceWorkerData();
|
Promise<any> clearAllServiceWorkerData();
|
||||||
|
|
||||||
[Throws]
|
[Throws,Pref="dom.serviceWorkers.testing.enabled"]
|
||||||
DOMString getScopeForUrl(DOMString url);
|
DOMString getScopeForUrl(DOMString url);
|
||||||
|
|
||||||
[Throws]
|
[Throws,Pref="dom.serviceWorkers.testing.enabled"]
|
||||||
DOMString getControllingWorkerScriptURLForPath(DOMString path);
|
DOMString getControllingWorkerScriptURLForPath(DOMString path);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -10,10 +10,8 @@
|
|||||||
* this document.
|
* this document.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// The Pref controls exposure in general, the Func restricts it to inside the
|
[Global=(Worker,ServiceWorker),
|
||||||
// ServiceWorkerGlobalScope (itself).
|
Exposed=ServiceWorker]
|
||||||
[Global, Func="mozilla::dom::workers::ServiceWorkerGlobalScope::Visible",
|
|
||||||
Pref="dom.serviceWorkers.enabled"]
|
|
||||||
interface ServiceWorkerGlobalScope : WorkerGlobalScope {
|
interface ServiceWorkerGlobalScope : WorkerGlobalScope {
|
||||||
// FIXME(nsm): Bug 982725
|
// FIXME(nsm): Bug 982725
|
||||||
// readonly attribute CacheList caches;
|
// readonly attribute CacheList caches;
|
||||||
|
@ -12,7 +12,8 @@
|
|||||||
* this document.
|
* this document.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
[Global, Func="mozilla::dom::workers::SharedWorkerGlobalScope::Visible"]
|
[Global=(Worker,SharedWorker),
|
||||||
|
Exposed=SharedWorker]
|
||||||
interface SharedWorkerGlobalScope : WorkerGlobalScope {
|
interface SharedWorkerGlobalScope : WorkerGlobalScope {
|
||||||
readonly attribute DOMString name;
|
readonly attribute DOMString name;
|
||||||
attribute EventHandler onconnect;
|
attribute EventHandler onconnect;
|
||||||
|
@ -10,7 +10,8 @@
|
|||||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
[Constructor(optional DOMString label = "utf-8", optional TextDecoderOptions options)]
|
[Constructor(optional DOMString label = "utf-8", optional TextDecoderOptions options),
|
||||||
|
Exposed=(Window,Worker)]
|
||||||
interface TextDecoder {
|
interface TextDecoder {
|
||||||
[Constant]
|
[Constant]
|
||||||
readonly attribute DOMString encoding;
|
readonly attribute DOMString encoding;
|
||||||
|
@ -10,7 +10,8 @@
|
|||||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
[Constructor(optional DOMString utfLabel = "utf-8")]
|
[Constructor(optional DOMString utfLabel = "utf-8"),
|
||||||
|
Exposed=(Window,Worker)]
|
||||||
interface TextEncoder {
|
interface TextEncoder {
|
||||||
[Constant]
|
[Constant]
|
||||||
readonly attribute DOMString encoding;
|
readonly attribute DOMString encoding;
|
||||||
|
@ -14,7 +14,8 @@
|
|||||||
|
|
||||||
// [Constructor(DOMString url, optional (URL or DOMString) base = "about:blank")]
|
// [Constructor(DOMString url, optional (URL or DOMString) base = "about:blank")]
|
||||||
[Constructor(DOMString url, URL base),
|
[Constructor(DOMString url, URL base),
|
||||||
Constructor(DOMString url, optional DOMString base = "about:blank")]
|
Constructor(DOMString url, optional DOMString base = "about:blank"),
|
||||||
|
Exposed=(Window,Worker)]
|
||||||
interface URL {
|
interface URL {
|
||||||
};
|
};
|
||||||
URL implements URLUtils;
|
URL implements URLUtils;
|
||||||
|
@ -14,7 +14,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
[Constructor(optional DOMString init = ""),
|
[Constructor(optional DOMString init = ""),
|
||||||
Constructor(URLSearchParams init)]
|
Constructor(URLSearchParams init),
|
||||||
|
Exposed=(Window,Worker)]
|
||||||
interface URLSearchParams {
|
interface URLSearchParams {
|
||||||
void append(DOMString name, DOMString value);
|
void append(DOMString name, DOMString value);
|
||||||
void delete(DOMString name);
|
void delete(DOMString name);
|
||||||
|
@ -13,7 +13,8 @@
|
|||||||
* http://www.openwebfoundation.org/legal/the-owf-1-0-agreements/owfa-1-0.
|
* http://www.openwebfoundation.org/legal/the-owf-1-0-agreements/owfa-1-0.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
[NoInterfaceObject]
|
[NoInterfaceObject,
|
||||||
|
Exposed=(Window, Worker)]
|
||||||
interface URLUtilsNoSearchParams {
|
interface URLUtilsNoSearchParams {
|
||||||
// Bug 824857: no support for stringifier attributes yet.
|
// Bug 824857: no support for stringifier attributes yet.
|
||||||
// stringifier attribute DOMString href;
|
// stringifier attribute DOMString href;
|
||||||
@ -47,7 +48,8 @@ interface URLUtilsNoSearchParams {
|
|||||||
stringifier;
|
stringifier;
|
||||||
};
|
};
|
||||||
|
|
||||||
[NoInterfaceObject]
|
[NoInterfaceObject,
|
||||||
|
Exposed=(Window, Worker)]
|
||||||
interface URLUtils : URLUtilsNoSearchParams
|
interface URLUtils : URLUtilsNoSearchParams
|
||||||
{
|
{
|
||||||
attribute URLSearchParams searchParams;
|
attribute URLSearchParams searchParams;
|
||||||
|
@ -13,7 +13,8 @@
|
|||||||
* http://www.openwebfoundation.org/legal/the-owf-1-0-agreements/owfa-1-0.
|
* http://www.openwebfoundation.org/legal/the-owf-1-0-agreements/owfa-1-0.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
[NoInterfaceObject]
|
[NoInterfaceObject,
|
||||||
|
Exposed=(Window, Worker)]
|
||||||
interface URLUtilsReadOnly {
|
interface URLUtilsReadOnly {
|
||||||
stringifier;
|
stringifier;
|
||||||
readonly attribute DOMString href;
|
readonly attribute DOMString href;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user