зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to fx-team. a=merge
This commit is contained in:
Коммит
07a58022be
|
@ -15,15 +15,15 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="3ab0d9c70f0b2e1ededc679112c392303f037361">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="58734e8a48157f99d5b733412b600c2e04c954fe"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2650bae535e15eef5f299cc80d4fab460f78ada7"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f0e6d8bde961683b7862b4eb0bb04c49d9699f3c"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8374a0d66ca9228269e860089c1535fcda9f9c5f"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
|
||||
|
|
|
@ -19,13 +19,13 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="58734e8a48157f99d5b733412b600c2e04c954fe"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2650bae535e15eef5f299cc80d4fab460f78ada7"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="6fa7a4936414ceb4055fd27f7a30e76790f834fb"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f0e6d8bde961683b7862b4eb0bb04c49d9699f3c"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8374a0d66ca9228269e860089c1535fcda9f9c5f"/>
|
||||
<!-- Stock Android things -->
|
||||
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
|
||||
<project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="58734e8a48157f99d5b733412b600c2e04c954fe"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2650bae535e15eef5f299cc80d4fab460f78ada7"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f0e6d8bde961683b7862b4eb0bb04c49d9699f3c"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8374a0d66ca9228269e860089c1535fcda9f9c5f"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
<!-- Stock Android things -->
|
||||
|
|
|
@ -15,15 +15,15 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="3ab0d9c70f0b2e1ededc679112c392303f037361">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="58734e8a48157f99d5b733412b600c2e04c954fe"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2650bae535e15eef5f299cc80d4fab460f78ada7"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f0e6d8bde961683b7862b4eb0bb04c49d9699f3c"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8374a0d66ca9228269e860089c1535fcda9f9c5f"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>
|
||||
|
|
|
@ -19,13 +19,13 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="58734e8a48157f99d5b733412b600c2e04c954fe"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2650bae535e15eef5f299cc80d4fab460f78ada7"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="6fa7a4936414ceb4055fd27f7a30e76790f834fb"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f0e6d8bde961683b7862b4eb0bb04c49d9699f3c"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8374a0d66ca9228269e860089c1535fcda9f9c5f"/>
|
||||
<!-- Stock Android things -->
|
||||
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
|
||||
<project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
|
||||
|
|
|
@ -15,15 +15,15 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="3ab0d9c70f0b2e1ededc679112c392303f037361">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="58734e8a48157f99d5b733412b600c2e04c954fe"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2650bae535e15eef5f299cc80d4fab460f78ada7"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f0e6d8bde961683b7862b4eb0bb04c49d9699f3c"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8374a0d66ca9228269e860089c1535fcda9f9c5f"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
</project>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="58734e8a48157f99d5b733412b600c2e04c954fe"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2650bae535e15eef5f299cc80d4fab460f78ada7"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f0e6d8bde961683b7862b4eb0bb04c49d9699f3c"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8374a0d66ca9228269e860089c1535fcda9f9c5f"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
<!-- Stock Android things -->
|
||||
|
|
|
@ -4,6 +4,6 @@
|
|||
"remote": "",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "d937413f736efd995436c211649f930191429b66",
|
||||
"revision": "9e971d42c915f999f3e352fe43fca7ba0a5245b4",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -17,11 +17,11 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="58734e8a48157f99d5b733412b600c2e04c954fe"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2650bae535e15eef5f299cc80d4fab460f78ada7"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f0e6d8bde961683b7862b4eb0bb04c49d9699f3c"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8374a0d66ca9228269e860089c1535fcda9f9c5f"/>
|
||||
<!-- Stock Android things -->
|
||||
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
|
||||
<project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="58734e8a48157f99d5b733412b600c2e04c954fe"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2650bae535e15eef5f299cc80d4fab460f78ada7"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="58734e8a48157f99d5b733412b600c2e04c954fe"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2650bae535e15eef5f299cc80d4fab460f78ada7"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f0e6d8bde961683b7862b4eb0bb04c49d9699f3c"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8374a0d66ca9228269e860089c1535fcda9f9c5f"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
<!-- Stock Android things -->
|
||||
|
|
|
@ -17,12 +17,12 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="58734e8a48157f99d5b733412b600c2e04c954fe"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2650bae535e15eef5f299cc80d4fab460f78ada7"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f0e6d8bde961683b7862b4eb0bb04c49d9699f3c"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8374a0d66ca9228269e860089c1535fcda9f9c5f"/>
|
||||
<project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
|
||||
<!-- Stock Android things -->
|
||||
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
|
||||
|
|
|
@ -103,6 +103,12 @@ this.DOMApplicationRegistry = {
|
|||
this.cpmm.addMessageListener(aMsgName, this);
|
||||
}).bind(this));
|
||||
|
||||
this.resetList();
|
||||
|
||||
Services.obs.addObserver(this, "xpcom-shutdown", false);
|
||||
},
|
||||
|
||||
resetList: function() {
|
||||
this.cpmm.sendAsyncMessage("Webapps:RegisterForMessages", {
|
||||
messages: APPS_IPC_MSG_NAMES
|
||||
});
|
||||
|
@ -110,6 +116,7 @@ this.DOMApplicationRegistry = {
|
|||
// We need to prime the cache with the list of apps.
|
||||
let list = this.cpmm.sendSyncMessage("Webapps:GetList", { })[0];
|
||||
this.webapps = list.webapps;
|
||||
|
||||
// We need a fast mapping from localId -> app, so we add an index.
|
||||
// We also add the manifest to the app object.
|
||||
this.localIdIndex = { };
|
||||
|
@ -118,8 +125,6 @@ this.DOMApplicationRegistry = {
|
|||
this.localIdIndex[app.localId] = app;
|
||||
app.manifest = list.manifests[id];
|
||||
}
|
||||
|
||||
Services.obs.addObserver(this, "xpcom-shutdown", false);
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "mozilla/dom/DesktopNotification.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "nsGeolocation.h"
|
||||
#include "nsIClassOfService.h"
|
||||
#include "nsIHttpProtocolHandler.h"
|
||||
#include "nsIContentPolicy.h"
|
||||
#include "nsIContentSecurityPolicy.h"
|
||||
|
@ -1190,6 +1191,11 @@ Navigator::SendBeacon(const nsAString& aUrl,
|
|||
p->SetPriority(nsISupportsPriority::PRIORITY_LOWEST);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
|
||||
if (cos) {
|
||||
cos->AddClassFlags(nsIClassOfService::Background);
|
||||
}
|
||||
|
||||
nsRefPtr<nsCORSListenerProxy> cors = new nsCORSListenerProxy(new BeaconStreamListener(),
|
||||
principal,
|
||||
true);
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include "nsJSPrincipals.h"
|
||||
#include "nsContentPolicyUtils.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsIClassOfService.h"
|
||||
#include "nsITimedChannel.h"
|
||||
#include "nsIScriptElement.h"
|
||||
#include "nsIDOMHTMLScriptElement.h"
|
||||
|
@ -321,18 +321,17 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType,
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsIScriptElement *script = aRequest->mElement;
|
||||
nsCOMPtr<nsIHttpChannelInternal>
|
||||
internalHttpChannel(do_QueryInterface(channel));
|
||||
nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
|
||||
|
||||
if (internalHttpChannel) {
|
||||
if (cos) {
|
||||
if (aScriptFromHead &&
|
||||
!(script && (script->GetScriptAsync() || script->GetScriptDeferred()))) {
|
||||
// synchronous head scripts block lading of most other non js/css
|
||||
// content such as images
|
||||
internalHttpChannel->SetLoadAsBlocking(true);
|
||||
cos->AddClassFlags(nsIClassOfService::Leader);
|
||||
} else if (!(script && script->GetScriptDeferred())) {
|
||||
// other scripts are neither blocked nor prioritized unless marked deferred
|
||||
internalHttpChannel->SetLoadUnblocked(true);
|
||||
cos->AddClassFlags(nsIClassOfService::Unblocked);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
#include "nsIPermissionManager.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsIClassOfService.h"
|
||||
#include "nsCharSeparatedTokenizer.h"
|
||||
#include "nsFormData.h"
|
||||
#include "nsStreamListenerWrapper.h"
|
||||
|
@ -2403,10 +2404,8 @@ GetRequestBody(nsIDOMDocument* aDoc, nsIInputStream** aResult,
|
|||
aContentType.AssignLiteral("application/xml");
|
||||
nsCOMPtr<nsIDocument> doc(do_QueryInterface(aDoc));
|
||||
NS_ENSURE_STATE(doc);
|
||||
aCharset = doc->GetDocumentCharacterSet();
|
||||
aCharset.AssignLiteral("UTF-8");
|
||||
|
||||
// Serialize to a stream so that the encoding used will
|
||||
// match the document's.
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIDOMSerializer> serializer =
|
||||
do_CreateInstance(NS_XMLSERIALIZER_CONTRACTID, &rv);
|
||||
|
@ -2891,14 +2890,17 @@ nsXMLHttpRequest::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
|
|||
// the channel slow by default for pipeline purposes
|
||||
AddLoadFlags(mChannel, nsIRequest::INHIBIT_PIPELINE);
|
||||
|
||||
nsCOMPtr<nsIHttpChannelInternal>
|
||||
internalHttpChannel(do_QueryInterface(mChannel));
|
||||
if (internalHttpChannel) {
|
||||
nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(mChannel));
|
||||
if (cos) {
|
||||
// we never let XHR be blocked by head CSS/JS loads to avoid
|
||||
// potential deadlock where server generation of CSS/JS requires
|
||||
// an XHR signal.
|
||||
internalHttpChannel->SetLoadUnblocked(true);
|
||||
cos->AddClassFlags(nsIClassOfService::Unblocked);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHttpChannelInternal>
|
||||
internalHttpChannel(do_QueryInterface(mChannel));
|
||||
if (internalHttpChannel) {
|
||||
// Disable Necko-internal response timeouts.
|
||||
internalHttpChannel->SetResponseTimeoutEnabled(false);
|
||||
}
|
||||
|
|
|
@ -127,22 +127,22 @@ tests = [{ body: null,
|
|||
},
|
||||
{ body: testDoc1,
|
||||
resBody: "<!-- comment -->\n<out>hi</out>",
|
||||
resContentType: "application/xml; charset=windows-1252",
|
||||
resContentType: "application/xml; charset=UTF-8",
|
||||
},
|
||||
{ body: testDoc1,
|
||||
contentType: "foo/bar",
|
||||
resBody: "<!-- comment -->\n<out>hi</out>",
|
||||
resContentType: "foo/bar; charset=windows-1252",
|
||||
resContentType: "foo/bar; charset=UTF-8",
|
||||
},
|
||||
{ body: testDoc1,
|
||||
contentType: "foo/bar; charset=ascii; baz=bin",
|
||||
resBody: "<!-- comment -->\n<out>hi</out>",
|
||||
resContentType: "foo/bar; charset=windows-1252; baz=bin",
|
||||
resContentType: "foo/bar; charset=UTF-8; baz=bin",
|
||||
},
|
||||
{ body: testDoc1,
|
||||
contentType: "foo/bar; charset=wIndows-1252",
|
||||
resBody: "<!-- comment -->\n<out>hi</out>",
|
||||
resContentType: "foo/bar; charset=wIndows-1252",
|
||||
resContentType: "foo/bar; charset=UTF-8",
|
||||
},
|
||||
{ body: testDoc2,
|
||||
resBody: "<!-- doc 2 -->\n<res>text</res>",
|
||||
|
|
|
@ -903,6 +903,12 @@ nsGonkCameraControl::SetThumbnailSizeImpl(const Size& aSize)
|
|||
return SetAndPush(CAMERA_PARAM_THUMBNAILSIZE, size);
|
||||
}
|
||||
|
||||
android::sp<android::GonkCameraHardware>
|
||||
nsGonkCameraControl::GetCameraHw()
|
||||
{
|
||||
return mCameraHw;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGonkCameraControl::SetThumbnailSize(const Size& aSize)
|
||||
{
|
||||
|
|
|
@ -32,6 +32,7 @@ namespace android {
|
|||
class GonkCameraHardware;
|
||||
class MediaProfiles;
|
||||
class GonkRecorder;
|
||||
class GonkCameraSource;
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -154,6 +155,9 @@ protected:
|
|||
nsresult UpdateThumbnailSize();
|
||||
nsresult SetThumbnailSizeImpl(const Size& aSize);
|
||||
|
||||
friend class android::GonkCameraSource;
|
||||
android::sp<android::GonkCameraHardware> GetCameraHw();
|
||||
|
||||
int32_t RationalizeRotation(int32_t aRotation);
|
||||
|
||||
uint32_t mCameraId;
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "GonkCameraSource.h"
|
||||
#include "GonkCameraListener.h"
|
||||
#include "GonkCameraHwMgr.h"
|
||||
#include "ICameraControl.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
@ -157,6 +158,16 @@ GonkCameraSource *GonkCameraSource::Create(
|
|||
return source;
|
||||
}
|
||||
|
||||
GonkCameraSource *GonkCameraSource::Create(
|
||||
ICameraControl* aControl,
|
||||
Size videoSize,
|
||||
int32_t frameRate)
|
||||
{
|
||||
mozilla::nsGonkCameraControl* control =
|
||||
static_cast<mozilla::nsGonkCameraControl*>(aControl);
|
||||
return Create(control->GetCameraHw(), videoSize, frameRate, false);
|
||||
}
|
||||
|
||||
GonkCameraSource::GonkCameraSource(
|
||||
const sp<GonkCameraHardware>& aCameraHw,
|
||||
Size videoSize,
|
||||
|
@ -596,6 +607,10 @@ status_t GonkCameraSource::reset() {
|
|||
}
|
||||
releaseCamera();
|
||||
|
||||
if (mDirectBufferListener.get()) {
|
||||
mDirectBufferListener = nullptr;
|
||||
}
|
||||
|
||||
if (mCollectStats) {
|
||||
CS_LOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us",
|
||||
mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped,
|
||||
|
@ -652,6 +667,14 @@ void GonkCameraSource::signalBufferReturned(MediaBuffer *buffer) {
|
|||
CHECK(!"signalBufferReturned: bogus buffer");
|
||||
}
|
||||
|
||||
status_t GonkCameraSource::AddDirectBufferListener(DirectBufferListener* aListener) {
|
||||
if (mDirectBufferListener.get()) {
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
mDirectBufferListener = aListener;
|
||||
return OK;
|
||||
}
|
||||
|
||||
status_t GonkCameraSource::read(
|
||||
MediaBuffer **buffer, const ReadOptions *options) {
|
||||
CS_LOGV("read");
|
||||
|
@ -761,6 +784,15 @@ void GonkCameraSource::dataCallbackTimestamp(int64_t timestampUs,
|
|||
if(prevRateLimit != rateLimit) {
|
||||
mCameraHw->OnRateLimitPreview(rateLimit);
|
||||
}
|
||||
|
||||
if (mDirectBufferListener.get()) {
|
||||
MediaBuffer* mediaBuffer;
|
||||
if (read(&mediaBuffer) == OK) {
|
||||
mDirectBufferListener->BufferAvailable(mediaBuffer);
|
||||
// read() calls MediaBuffer->add_ref() so it needs to be released here.
|
||||
mediaBuffer->release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GonkCameraSource::isMetaDataStoredInVideoBuffers() const {
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
|
||||
#include "GonkCameraHwMgr.h"
|
||||
|
||||
namespace mozilla {
|
||||
class ICameraControl;
|
||||
}
|
||||
|
||||
namespace android {
|
||||
|
||||
class IMemory;
|
||||
|
@ -39,6 +43,10 @@ public:
|
|||
int32_t frameRate,
|
||||
bool storeMetaDataInVideoBuffers = false);
|
||||
|
||||
static GonkCameraSource *Create(mozilla::ICameraControl* aControl,
|
||||
Size videoSize,
|
||||
int32_t frameRate);
|
||||
|
||||
virtual ~GonkCameraSource();
|
||||
|
||||
virtual status_t start(MetaData *params = NULL);
|
||||
|
@ -75,6 +83,24 @@ public:
|
|||
|
||||
virtual void signalBufferReturned(MediaBuffer* buffer);
|
||||
|
||||
/**
|
||||
* It sends recording frames to listener directly in the same thread.
|
||||
* Because recording frame is critical resource and it should not be
|
||||
* propagated to other thread as much as possible or there could be frame
|
||||
* rate jitter due to camera HAL waiting for resource.
|
||||
*/
|
||||
class DirectBufferListener : public RefBase {
|
||||
public:
|
||||
DirectBufferListener() {};
|
||||
|
||||
virtual status_t BufferAvailable(MediaBuffer* aBuffer) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~DirectBufferListener() {}
|
||||
};
|
||||
|
||||
status_t AddDirectBufferListener(DirectBufferListener* aListener);
|
||||
|
||||
protected:
|
||||
|
||||
enum CameraFlags {
|
||||
|
@ -136,6 +162,7 @@ private:
|
|||
bool mCollectStats;
|
||||
bool mIsMetaDataStoredInVideoBuffers;
|
||||
sp<GonkCameraHardware> mCameraHw;
|
||||
sp<DirectBufferListener> mDirectBufferListener;
|
||||
|
||||
void releaseQueuedFrames();
|
||||
void releaseOneRecordingFrame(const sp<IMemory>& frame);
|
||||
|
|
|
@ -3244,10 +3244,7 @@ void HTMLMediaElement::UpdateReadyStateForData(MediaDecoderOwner::NextFrameStatu
|
|||
// autoplay elements for live streams will never play. Otherwise we
|
||||
// move to HAVE_ENOUGH_DATA if we can play through the entire media
|
||||
// without stopping to buffer.
|
||||
MediaDecoder::Statistics stats = mDecoder->GetStatistics();
|
||||
if (stats.mTotalBytes < 0 ? stats.mDownloadRateReliable
|
||||
: stats.mTotalBytes == stats.mDownloadPosition ||
|
||||
mDecoder->CanPlayThrough())
|
||||
if (mDecoder->CanPlayThrough())
|
||||
{
|
||||
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA);
|
||||
return;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsXPCOMCIDInternal.h"
|
||||
#include "ProfilerHelpers.h"
|
||||
#include "nsThread.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -176,6 +177,10 @@ private:
|
|||
~TransactionQueue()
|
||||
{ }
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
nsThread* mThread;
|
||||
#endif
|
||||
|
||||
NS_DECL_NSIRUNNABLE
|
||||
};
|
||||
|
||||
|
@ -789,6 +794,9 @@ TransactionQueue::TransactionQueue(TransactionThreadPool* aThreadPool,
|
|||
, mObjectStoreNames(aObjectStoreNames)
|
||||
, mMode(aMode)
|
||||
, mShouldFinish(false)
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
, mThread(nullptr)
|
||||
#endif
|
||||
{
|
||||
MOZ_ASSERT(aThreadPool);
|
||||
aThreadPool->AssertIsOnOwningThread();
|
||||
|
@ -814,6 +822,12 @@ TransactionThreadPool::TransactionQueue::Dispatch(nsIRunnable* aRunnable)
|
|||
|
||||
mQueue.AppendElement(aRunnable);
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
if (mThread) {
|
||||
mThread->SetWorking();
|
||||
}
|
||||
#endif
|
||||
|
||||
mMonitor.Notify();
|
||||
}
|
||||
|
||||
|
@ -849,6 +863,12 @@ TransactionThreadPool::TransactionQueue::Run()
|
|||
nsAutoTArray<nsCOMPtr<nsIRunnable>, 10> queue;
|
||||
nsRefPtr<FinishCallback> finishCallback;
|
||||
bool shouldFinish = false;
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
mThread = static_cast<nsThread*>(NS_GetCurrentThread());
|
||||
// Set ourself as working thread. We can reset later if we found
|
||||
// our queue is empty.
|
||||
mThread->SetWorking();
|
||||
#endif
|
||||
|
||||
do {
|
||||
NS_ASSERTION(queue.IsEmpty(), "Should have cleared this!");
|
||||
|
@ -856,6 +876,9 @@ TransactionThreadPool::TransactionQueue::Run()
|
|||
{
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
while (!mShouldFinish && mQueue.IsEmpty()) {
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
mThread->SetIdle();
|
||||
#endif
|
||||
if (NS_FAILED(mMonitor.Wait())) {
|
||||
NS_ERROR("Failed to wait!");
|
||||
}
|
||||
|
@ -888,6 +911,10 @@ TransactionThreadPool::TransactionQueue::Run()
|
|||
}
|
||||
} while (!shouldFinish);
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
mThread = nullptr;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
if (kDEBUGThreadSleepMS) {
|
||||
MOZ_ALWAYS_TRUE(
|
||||
|
|
|
@ -510,6 +510,12 @@ NS_IMPL_ISUPPORTS(BackgroundChildPrimer, nsIIPCBackgroundChildCreateCallback)
|
|||
|
||||
ContentChild* ContentChild::sSingleton;
|
||||
|
||||
static void
|
||||
PostForkPreload()
|
||||
{
|
||||
TabChild::PostForkPreload();
|
||||
}
|
||||
|
||||
// Performs initialization that is not fork-safe, i.e. that must be done after
|
||||
// forking from the Nuwa process.
|
||||
static void
|
||||
|
@ -520,6 +526,7 @@ InitOnContentProcessCreated()
|
|||
if (IsNuwaProcess()) {
|
||||
return;
|
||||
}
|
||||
PostForkPreload();
|
||||
#endif
|
||||
|
||||
// This will register cross-process observer.
|
||||
|
@ -1243,7 +1250,6 @@ ContentChild::RecvPBrowserConstructor(PBrowserChild* aActor,
|
|||
{
|
||||
// This runs after AllocPBrowserChild() returns and the IPC machinery for this
|
||||
// PBrowserChild has been set up.
|
||||
|
||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||
if (os) {
|
||||
nsITabChild* tc =
|
||||
|
@ -1991,8 +1997,11 @@ bool
|
|||
ContentChild::RecvFlushMemory(const nsString& reason)
|
||||
{
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
if (IsNuwaProcess()) {
|
||||
if (IsNuwaProcess() || ManagedPBrowserChild().Length() == 0) {
|
||||
// Don't flush memory in the nuwa process: the GC thread could be frozen.
|
||||
// If there's no PBrowser child, don't flush memory, either. GC writes
|
||||
// to copy-on-write pages and makes preallocated process take more memory
|
||||
// before it actually becomes an app.
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
@ -2080,12 +2089,28 @@ ContentChild::RecvAppInfo(const nsCString& version, const nsCString& buildID,
|
|||
// BrowserElementChild.js.
|
||||
if ((mIsForApp || mIsForBrowser)
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
&& !IsNuwaProcess()
|
||||
&& IsNuwaProcess()
|
||||
#endif
|
||||
) {
|
||||
PreloadSlowThings();
|
||||
#ifndef MOZ_NUWA_PROCESS
|
||||
PostForkPreload();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
// Some modules are initialized in preloading. We need to wait until the
|
||||
// tasks they dispatched to chrome process are done.
|
||||
if (IsNuwaProcess()) {
|
||||
SendNuwaWaitForFreeze();
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::RecvNuwaFreeze()
|
||||
{
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
if (IsNuwaProcess()) {
|
||||
ContentChild::GetSingleton()->RecvGarbageCollect();
|
||||
|
@ -2093,7 +2118,6 @@ ContentChild::RecvAppInfo(const nsCString& version, const nsCString& buildID,
|
|||
FROM_HERE, NewRunnableFunction(OnFinishNuwaPreparation));
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2344,6 +2368,36 @@ RunNuwaFork()
|
|||
DoNuwaFork();
|
||||
}
|
||||
}
|
||||
|
||||
class NuwaForkCaller: public nsRunnable
|
||||
{
|
||||
public:
|
||||
NS_IMETHODIMP
|
||||
Run() {
|
||||
// We want to ensure that the PBackground actor gets cloned in the Nuwa
|
||||
// process before we freeze. Also, we have to do this to avoid deadlock.
|
||||
// Protocols that are "opened" (e.g. PBackground, PCompositor) block the
|
||||
// main thread to wait for the IPC thread during the open operation.
|
||||
// NuwaSpawnWait() blocks the IPC thread to wait for the main thread when
|
||||
// the Nuwa process is forked. Unless we ensure that the two cannot happen
|
||||
// at the same time then we risk deadlock. Spinning the event loop here
|
||||
// guarantees the ordering is safe for PBackground.
|
||||
if (!BackgroundChild::GetForCurrentThread()) {
|
||||
// Dispatch ourself again.
|
||||
NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL);
|
||||
} else {
|
||||
MessageLoop* ioloop = XRE_GetIOMessageLoop();
|
||||
ioloop->PostTask(FROM_HERE, NewRunnableFunction(RunNuwaFork));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
virtual
|
||||
~NuwaForkCaller()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
bool
|
||||
|
@ -2355,22 +2409,9 @@ ContentChild::RecvNuwaFork()
|
|||
}
|
||||
sNuwaForking = true;
|
||||
|
||||
// We want to ensure that the PBackground actor gets cloned in the Nuwa
|
||||
// process before we freeze. Also, we have to do this to avoid deadlock.
|
||||
// Protocols that are "opened" (e.g. PBackground, PCompositor) block the
|
||||
// main thread to wait for the IPC thread during the open operation.
|
||||
// NuwaSpawnWait() blocks the IPC thread to wait for the main thread when
|
||||
// the Nuwa process is forked. Unless we ensure that the two cannot happen
|
||||
// at the same time then we risk deadlock. Spinning the event loop here
|
||||
// guarantees the ordering is safe for PBackground.
|
||||
while (!BackgroundChild::GetForCurrentThread()) {
|
||||
if (NS_WARN_IF(!NS_ProcessNextEvent())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
nsRefPtr<NuwaForkCaller> runnable = new NuwaForkCaller();
|
||||
NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL);
|
||||
|
||||
MessageLoop* ioloop = XRE_GetIOMessageLoop();
|
||||
ioloop->PostTask(FROM_HERE, NewRunnableFunction(RunNuwaFork));
|
||||
return true;
|
||||
#else
|
||||
return false; // Makes the underlying IPC channel abort.
|
||||
|
|
|
@ -350,6 +350,8 @@ public:
|
|||
|
||||
virtual bool RecvNotifyPhoneStateChange(const nsString& state) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool RecvNuwaFreeze() MOZ_OVERRIDE;
|
||||
|
||||
void AddIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS);
|
||||
void RemoveIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS);
|
||||
virtual bool RecvNotifyIdleObserver(const uint64_t& aObserver,
|
||||
|
|
|
@ -124,6 +124,7 @@
|
|||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsStyleSheetService.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsThreadManager.h"
|
||||
#include "nsToolkitCompsCID.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
#include "PreallocatedProcessManager.h"
|
||||
|
@ -1372,6 +1373,28 @@ StaticAutoPtr<LinkedList<SystemMessageHandledListener> >
|
|||
NS_IMPL_ISUPPORTS(SystemMessageHandledListener,
|
||||
nsITimerCallback)
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
class NuwaFreezeListener : public nsThreadManager::AllThreadsWereIdleListener
|
||||
{
|
||||
public:
|
||||
NuwaFreezeListener(ContentParent* parent)
|
||||
: mParent(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void OnAllThreadsWereIdle()
|
||||
{
|
||||
unused << mParent->SendNuwaFreeze();
|
||||
nsThreadManager::get()->RemoveAllThreadsWereIdleListener(this);
|
||||
}
|
||||
private:
|
||||
nsRefPtr<ContentParent> mParent;
|
||||
virtual ~NuwaFreezeListener()
|
||||
{
|
||||
}
|
||||
};
|
||||
#endif // MOZ_NUWA_PROCESS
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void
|
||||
|
@ -2062,6 +2085,8 @@ ContentParent::ContentParent(ContentParent* aTemplate,
|
|||
priority = PROCESS_PRIORITY_FOREGROUND;
|
||||
}
|
||||
|
||||
mSendPermissionUpdates = aTemplate->mSendPermissionUpdates;
|
||||
|
||||
InitInternal(priority,
|
||||
false, /* Setup Off-main thread compositing */
|
||||
false /* Send registered chrome */);
|
||||
|
@ -2219,7 +2244,7 @@ ContentParent::IsForApp()
|
|||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
bool
|
||||
ContentParent::IsNuwaProcess()
|
||||
ContentParent::IsNuwaProcess() const
|
||||
{
|
||||
return mIsNuwaProcess;
|
||||
}
|
||||
|
@ -2568,6 +2593,19 @@ ContentParent::RecvNuwaReady()
|
|||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvNuwaWaitForFreeze()
|
||||
{
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
nsRefPtr<NuwaFreezeListener> listener = new NuwaFreezeListener(this);
|
||||
nsThreadManager::get()->AddAllThreadsWereIdleListener(listener);
|
||||
return true;
|
||||
#else // MOZ_NUWA_PROCESS
|
||||
NS_ERROR("ContentParent::RecvNuwaWaitForFreeze() not implemented!");
|
||||
return false;
|
||||
#endif // MOZ_NUWA_PROCESS
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvAddNewProcess(const uint32_t& aPid,
|
||||
const InfallibleTArray<ProtocolFdMapping>& aFds)
|
||||
|
|
|
@ -206,7 +206,7 @@ public:
|
|||
return mIsForBrowser;
|
||||
}
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
bool IsNuwaProcess();
|
||||
bool IsNuwaProcess() const;
|
||||
#endif
|
||||
|
||||
GeckoChildProcessHost* Process() {
|
||||
|
@ -220,7 +220,11 @@ public:
|
|||
}
|
||||
|
||||
bool NeedsPermissionsUpdate() const {
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
return !IsNuwaProcess() && mSendPermissionUpdates;
|
||||
#else
|
||||
return mSendPermissionUpdates;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool NeedsDataStoreInfos() const {
|
||||
|
@ -680,6 +684,8 @@ private:
|
|||
|
||||
virtual bool RecvNuwaReady() MOZ_OVERRIDE;
|
||||
|
||||
virtual bool RecvNuwaWaitForFreeze() MOZ_OVERRIDE;
|
||||
|
||||
virtual bool RecvAddNewProcess(const uint32_t& aPid,
|
||||
const InfallibleTArray<ProtocolFdMapping>& aFds) MOZ_OVERRIDE;
|
||||
|
||||
|
|
|
@ -524,6 +524,7 @@ child:
|
|||
intr GetProfile()
|
||||
returns (nsCString aProfile);
|
||||
|
||||
NuwaFreeze();
|
||||
parent:
|
||||
/**
|
||||
* Tell the parent process a new accessible document has been created.
|
||||
|
@ -735,6 +736,9 @@ parent:
|
|||
async SystemMessageHandled();
|
||||
|
||||
NuwaReady();
|
||||
// Sent when nuwa finished its initialization process and is waiting for
|
||||
// parent's signal to make it freeze.
|
||||
NuwaWaitForFreeze();
|
||||
|
||||
sync AddNewProcess(uint32_t pid, ProtocolFdMapping[] aFds);
|
||||
|
||||
|
|
|
@ -834,6 +834,21 @@ TabChild::PreloadSlowThings()
|
|||
ClearOnShutdown(&sPreallocatedTab);
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
TabChild::PostForkPreload()
|
||||
{
|
||||
// Preallocated Tab can be null if we are forked directly from b2g. In such
|
||||
// case we don't need to preload anything, just return.
|
||||
if (!sPreallocatedTab) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Rebuild connections to parent.
|
||||
sPreallocatedTab->RecvLoadRemoteScript(
|
||||
NS_LITERAL_STRING("chrome://global/content/post-fork-preload.js"),
|
||||
true);
|
||||
}
|
||||
|
||||
/*static*/ already_AddRefed<TabChild>
|
||||
TabChild::Create(nsIContentChild* aManager,
|
||||
const TabId& aTabId,
|
||||
|
|
|
@ -268,6 +268,7 @@ public:
|
|||
* on the critical path.
|
||||
*/
|
||||
static void PreloadSlowThings();
|
||||
static void PostForkPreload();
|
||||
|
||||
/** Return a TabChild with the given attributes. */
|
||||
static already_AddRefed<TabChild>
|
||||
|
|
|
@ -9,3 +9,4 @@ toolkit.jar:
|
|||
content/global/BrowserElementChildPreload.js (../browser-element/BrowserElementChildPreload.js)
|
||||
* content/global/BrowserElementPanning.js (../browser-element/BrowserElementPanning.js)
|
||||
content/global/preload.js (preload.js)
|
||||
content/global/post-fork-preload.js (post-fork-preload.js)
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Preload some things, in an attempt to make app startup faster.
|
||||
//
|
||||
// This script is run when the preallocated process starts. It is injected as
|
||||
// a frame script.
|
||||
// If Nuwa process is enabled, this script will run in preallocated process
|
||||
// forked by Nuwa.
|
||||
|
||||
(function (global) {
|
||||
"use strict";
|
||||
|
||||
Components.utils.import("resource://gre/modules/AppsServiceChild.jsm");
|
||||
Components.classes["@mozilla.org/network/protocol-proxy-service;1"].
|
||||
getService(Ci["nsIProtocolProxyService"]);
|
||||
|
||||
DOMApplicationRegistry.resetList();
|
||||
})(this);
|
|
@ -6,6 +6,7 @@
|
|||
//
|
||||
// This script is run when the preallocated process starts. It is injected as
|
||||
// a frame script.
|
||||
// If nuwa is enabled, this script will run in Nuwa process before frozen.
|
||||
|
||||
const BrowserElementIsPreloaded = true;
|
||||
|
||||
|
@ -58,7 +59,6 @@ const BrowserElementIsPreloaded = true;
|
|||
Cc["@mozilla.org/network/idn-service;1"].getService(Ci["nsIIDNService"]);
|
||||
Cc["@mozilla.org/network/io-service;1"].getService(Ci["nsIIOService2"]);
|
||||
Cc["@mozilla.org/network/mime-hdrparam;1"].getService(Ci["nsIMIMEHeaderParam"]);
|
||||
Cc["@mozilla.org/network/protocol-proxy-service;1"].getService(Ci["nsIProtocolProxyService"]);
|
||||
Cc["@mozilla.org/network/socket-transport-service;1"].getService(Ci["nsISocketTransportService"]);
|
||||
Cc["@mozilla.org/network/stream-transport-service;1"].getService(Ci["nsIStreamTransportService"]);
|
||||
Cc["@mozilla.org/network/url-parser;1?auth=maybe"].getService(Ci["nsIURLParser"]);
|
||||
|
|
|
@ -77,7 +77,7 @@ function runTest()
|
|||
let timeout = setTimeout(function() {
|
||||
ok(false, "Nuwa process is not launched");
|
||||
testEnd();
|
||||
}, 60000);
|
||||
}, 240000);
|
||||
|
||||
function testEnd() {
|
||||
cpmm.removeMessageListener("TEST-ONLY:nuwa-ready", msgHandler);
|
||||
|
|
|
@ -78,7 +78,7 @@ function runTest()
|
|||
let timeout = setTimeout(function() {
|
||||
ok(false, "Nuwa process is not launched");
|
||||
testEnd();
|
||||
}, 90000);
|
||||
}, 240000);
|
||||
|
||||
function testEnd() {
|
||||
cpmm.removeMessageListener("TEST-ONLY:nuwa-ready", msgHandler);
|
||||
|
|
|
@ -1562,6 +1562,10 @@ void MediaDecoder::UnpinForSeek()
|
|||
bool MediaDecoder::CanPlayThrough()
|
||||
{
|
||||
Statistics stats = GetStatistics();
|
||||
if ((stats.mTotalBytes < 0 && stats.mDownloadRateReliable) ||
|
||||
(stats.mTotalBytes >= 0 && stats.mTotalBytes == stats.mDownloadPosition)) {
|
||||
return true;
|
||||
}
|
||||
if (!stats.mDownloadRateReliable || !stats.mPlaybackRateReliable) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1585,8 +1589,7 @@ bool MediaDecoder::CanPlayThrough()
|
|||
// required near the start of the media, when not much data is downloaded.
|
||||
int64_t readAheadMargin =
|
||||
static_cast<int64_t>(stats.mPlaybackRate * CAN_PLAY_THROUGH_MARGIN);
|
||||
return stats.mTotalBytes == stats.mDownloadPosition ||
|
||||
stats.mDownloadPosition > stats.mPlaybackPosition + readAheadMargin;
|
||||
return stats.mDownloadPosition > stats.mPlaybackPosition + readAheadMargin;
|
||||
}
|
||||
|
||||
#ifdef MOZ_EME
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "GonkCameraImage.h"
|
||||
#include "stagefright/MediaBuffer.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
GonkCameraImage::GonkCameraImage()
|
||||
: GrallocImage()
|
||||
, mMonitor("GonkCameraImage.Monitor")
|
||||
, mMediaBuffer(nullptr)
|
||||
, mThread(nullptr)
|
||||
{
|
||||
mFormat = ImageFormat::GONK_CAMERA_IMAGE;
|
||||
}
|
||||
|
||||
GonkCameraImage::~GonkCameraImage()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
// mMediaBuffer must be cleared before destructor.
|
||||
MOZ_ASSERT(mMediaBuffer == nullptr);
|
||||
}
|
||||
|
||||
nsresult
|
||||
GonkCameraImage::GetBuffer(android::MediaBuffer** aBuffer)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
|
||||
if (!mMediaBuffer) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(NS_GetCurrentThread() == mThread);
|
||||
|
||||
*aBuffer = mMediaBuffer;
|
||||
mMediaBuffer->add_ref();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
GonkCameraImage::HasMediaBuffer()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
return mMediaBuffer != nullptr;
|
||||
}
|
||||
|
||||
nsresult
|
||||
GonkCameraImage::SetBuffer(android::MediaBuffer* aBuffer)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
MOZ_ASSERT(!mMediaBuffer);
|
||||
|
||||
mMediaBuffer = aBuffer;
|
||||
mMediaBuffer->add_ref();
|
||||
mThread = NS_GetCurrentThread();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
GonkCameraImage::ClearBuffer()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
|
||||
if (mMediaBuffer) {
|
||||
MOZ_ASSERT(NS_GetCurrentThread() == mThread);
|
||||
mMediaBuffer->release();
|
||||
mMediaBuffer = nullptr;
|
||||
mThread = nullptr;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/* -*- Mode: C++; tab-width: 20; 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 GONKCAMERAIMAGE_H
|
||||
#define GONKCAMERAIMAGE_H
|
||||
|
||||
#include "mozilla/ReentrantMonitor.h"
|
||||
#include "ImageLayers.h"
|
||||
#include "ImageContainer.h"
|
||||
#include "GrallocImages.h"
|
||||
|
||||
namespace android {
|
||||
class MOZ_EXPORT MediaBuffer;
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* GonkCameraImage has two parts. One is preview image which will be saved in
|
||||
* GrallocImage, another kind is the MediaBuffer keeps in mMediaBuffer
|
||||
* which is from gonk camera recording callback. The data in MediaBuffer is Gonk
|
||||
* shared memory based on android binder (IMemory), the actual format in IMemory
|
||||
* is platform dependent.
|
||||
* This instance is created in MediaEngine when the preview image arrives.
|
||||
* The MediaBuffer is attached to the current created GonkCameraImage via SetBuffer().
|
||||
* After sending this image to MediaStreamGraph by AppendToTrack(), ClearBuffer()
|
||||
* must be called to clear MediaBuffer to avoid MediaBuffer be kept in MSG thread.
|
||||
* The reason to keep MediaBuffer be accessed from MSG thread is MediaBuffer is
|
||||
* limited resource and it could cause frame rate jitter if MediaBuffer stay too
|
||||
* long in other threads.
|
||||
* So there will be 3 threads to accessed this class. First is camera preview
|
||||
* thread which creates an instance of this class and initialize the preview
|
||||
* image in the base class GrallocImage. Second is the camera recording
|
||||
* thread which attaches MediaBuffer and sends this image to MediaStreamDirectListener.
|
||||
* Third is the MSG thread via NotifyPull, the image should have preview image
|
||||
* only in NotifyPull.
|
||||
*
|
||||
* Note: SetBuffer() and GetBuffer() should be called from the same thread. It
|
||||
* is forbidden to call GetBuffer() from other threads.
|
||||
*/
|
||||
class GonkCameraImage : public layers::GrallocImage
|
||||
{
|
||||
public:
|
||||
GonkCameraImage();
|
||||
|
||||
// The returned aBuffer has called aBuffer->add_ref() already, so it is caller's
|
||||
// duty to release aBuffer. It should be called from the same thread which
|
||||
// called SetBuffer().
|
||||
nsresult GetBuffer(android::MediaBuffer** aBuffer);
|
||||
|
||||
// Set MediaBuffer to image. It is caller's responsibility to call ClearBuffer()
|
||||
// after the MediaBuffer is sent via MediaStreamGraph.
|
||||
nsresult SetBuffer(android::MediaBuffer* aBuffer);
|
||||
|
||||
// It should be called from the same thread which called SetBuffer().
|
||||
nsresult ClearBuffer();
|
||||
|
||||
bool HasMediaBuffer();
|
||||
|
||||
protected:
|
||||
virtual ~GonkCameraImage();
|
||||
|
||||
// mMonitor protects mMediaBuffer and mThread.
|
||||
ReentrantMonitor mMonitor;
|
||||
android::MediaBuffer* mMediaBuffer;
|
||||
// Check if current thread is the same one which called SetBuffer().
|
||||
// It doesn't need to hold reference count.
|
||||
DebugOnly<nsIThread*> mThread;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* GONKCAMERAIMAGE_H */
|
|
@ -15,11 +15,13 @@
|
|||
|
||||
#include "libyuv.h"
|
||||
#include "mtransport/runnable_utils.h"
|
||||
#include "GonkCameraImage.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::gfx;
|
||||
using namespace android;
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
extern PRLogModuleInfo* GetMediaManagerLog();
|
||||
|
@ -30,6 +32,29 @@ extern PRLogModuleInfo* GetMediaManagerLog();
|
|||
#define LOGFRAME(msg)
|
||||
#endif
|
||||
|
||||
class MediaBufferListener : public GonkCameraSource::DirectBufferListener {
|
||||
public:
|
||||
MediaBufferListener(MediaEngineGonkVideoSource* aMediaEngine)
|
||||
: mMediaEngine(aMediaEngine)
|
||||
{
|
||||
}
|
||||
|
||||
status_t BufferAvailable(MediaBuffer* aBuffer)
|
||||
{
|
||||
nsresult rv = mMediaEngine->OnNewMediaBufferFrame(aBuffer);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return OK;
|
||||
}
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
~MediaBufferListener()
|
||||
{
|
||||
}
|
||||
|
||||
nsRefPtr<MediaEngineGonkVideoSource> mMediaEngine;
|
||||
};
|
||||
|
||||
#define WEBRTC_GONK_VIDEO_SOURCE_POOL_BUFFERS 10
|
||||
|
||||
// We are subclassed from CameraControlListener, which implements a
|
||||
|
@ -168,6 +193,46 @@ MediaEngineGonkVideoSource::Start(SourceMediaStream* aStream, TrackID aID)
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (NS_FAILED(InitDirectMediaBuffer())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaEngineGonkVideoSource::InitDirectMediaBuffer()
|
||||
{
|
||||
// Check available buffer resolution.
|
||||
nsTArray<ICameraControl::Size> videoSizes;
|
||||
mCameraControl->Get(CAMERA_PARAM_SUPPORTED_VIDEOSIZES, videoSizes);
|
||||
if (!videoSizes.Length()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// TODO: MediaEgnine should use supported recording frame sizes as the size
|
||||
// range in MediaTrackConstraintSet and find the best match.
|
||||
// Here we use the first one as the default size (largest supported size).
|
||||
android::Size videoSize;
|
||||
videoSize.width = videoSizes[0].width;
|
||||
videoSize.height = videoSizes[0].height;
|
||||
|
||||
LOG(("Intial size, width: %d, height: %d", videoSize.width, videoSize.height));
|
||||
mCameraSource = GonkCameraSource::Create(mCameraControl,
|
||||
videoSize,
|
||||
MediaEngine::DEFAULT_VIDEO_FPS);
|
||||
|
||||
status_t rv;
|
||||
rv = mCameraSource->AddDirectBufferListener(new MediaBufferListener(this));
|
||||
if (rv != OK) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
rv = mCameraSource->start(nullptr);
|
||||
if (rv != OK) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -353,6 +418,9 @@ void
|
|||
MediaEngineGonkVideoSource::StopImpl() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
mCameraSource->stop();
|
||||
mCameraSource = nullptr;
|
||||
|
||||
hal::UnregisterScreenConfigurationObserver(this);
|
||||
mCameraControl->Stop();
|
||||
}
|
||||
|
@ -589,17 +657,17 @@ MediaEngineGonkVideoSource::ConvertPixelFormatToFOURCC(int aFormat)
|
|||
void
|
||||
MediaEngineGonkVideoSource::RotateImage(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight) {
|
||||
layers::GrallocImage *nativeImage = static_cast<layers::GrallocImage*>(aImage);
|
||||
android::sp<android::GraphicBuffer> graphicBuffer = nativeImage->GetGraphicBuffer();
|
||||
android::sp<GraphicBuffer> graphicBuffer = nativeImage->GetGraphicBuffer();
|
||||
void *pMem = nullptr;
|
||||
// Bug 1109957 size will be wrong if width or height are odd
|
||||
uint32_t size = aWidth * aHeight * 3 / 2;
|
||||
MOZ_ASSERT(!(aWidth & 1) && !(aHeight & 1));
|
||||
|
||||
graphicBuffer->lock(android::GraphicBuffer::USAGE_SW_READ_MASK, &pMem);
|
||||
graphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_MASK, &pMem);
|
||||
|
||||
uint8_t* srcPtr = static_cast<uint8_t*>(pMem);
|
||||
// Create a video frame and append it to the track.
|
||||
ImageFormat format = ImageFormat::GRALLOC_PLANAR_YCBCR;
|
||||
ImageFormat format = ImageFormat::GONK_CAMERA_IMAGE;
|
||||
nsRefPtr<layers::Image> image = mImageContainer->CreateImage(format);
|
||||
|
||||
uint32_t dstWidth;
|
||||
|
@ -657,23 +725,8 @@ MediaEngineGonkVideoSource::RotateImage(layers::Image* aImage, uint32_t aWidth,
|
|||
data.mGraphicBuffer = textureClient;
|
||||
videoImage->SetData(data);
|
||||
|
||||
// implicitly releases last image
|
||||
// Implicitly releases last preview image.
|
||||
mImage = image.forget();
|
||||
|
||||
// Push the frame into the MSG with a minimal duration. This will likely
|
||||
// mean we'll still get NotifyPull calls which will then return the same
|
||||
// frame again with a longer duration. However, this means we won't
|
||||
// fail to get the frame in and drop frames.
|
||||
|
||||
// XXX The timestamp for the frame should be base on the Capture time,
|
||||
// not the MSG time, and MSG should never, ever block on a (realtime)
|
||||
// video frame (or even really for streaming - audio yes, video probably no).
|
||||
uint32_t len = mSources.Length();
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
if (mSources[i]) {
|
||||
AppendToTrack(mSources[i], mImage, mTrackID, 1); // shortest possible duration
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -702,4 +755,40 @@ MediaEngineGonkVideoSource::OnNewPreviewFrame(layers::Image* aImage, uint32_t aW
|
|||
return true; // return true because we're accepting the frame
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaEngineGonkVideoSource::OnNewMediaBufferFrame(MediaBuffer* aBuffer)
|
||||
{
|
||||
{
|
||||
ReentrantMonitorAutoEnter sync(mCallbackMonitor);
|
||||
if (mState == kStopped) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
MonitorAutoLock enter(mMonitor);
|
||||
if (mImage) {
|
||||
GonkCameraImage* cameraImage = static_cast<GonkCameraImage*>(mImage.get());
|
||||
|
||||
cameraImage->SetBuffer(aBuffer);
|
||||
|
||||
uint32_t len = mSources.Length();
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
if (mSources[i]) {
|
||||
// Duration is 1 here.
|
||||
// Ideally, it should be camera timestamp here and the MSG will have
|
||||
// enough sample duration without calling NotifyPull() anymore.
|
||||
// Unfortunately, clock in gonk camera looks like is a different one
|
||||
// comparing to MSG. As result, it causes time inaccurate. (frames be
|
||||
// queued in MSG longer and longer as time going by in device like Frame)
|
||||
AppendToTrack(mSources[i], cameraImage, mTrackID, 1);
|
||||
}
|
||||
}
|
||||
// Clear MediaBuffer immediately, it prevents MediaBuffer is kept in
|
||||
// MediaStreamGraph thread.
|
||||
cameraImage->ClearBuffer();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -16,6 +16,11 @@
|
|||
#include "mozilla/ReentrantMonitor.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/layers/TextureClientRecycleAllocator.h"
|
||||
#include "GonkCameraSource.h"
|
||||
|
||||
namespace android {
|
||||
class MOZ_EXPORT MediaBuffer;
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -91,6 +96,12 @@ public:
|
|||
// current screen orientation.
|
||||
nsresult UpdatePhotoOrientation();
|
||||
|
||||
// It adds aBuffer to current preview image and sends this image to MediaStreamDirectListener
|
||||
// via AppendToTrack(). Due to MediaBuffer is limited resource, it will clear
|
||||
// image's MediaBuffer by calling GonkCameraImage::ClearBuffer() before leaving
|
||||
// this function.
|
||||
nsresult OnNewMediaBufferFrame(android::MediaBuffer* aBuffer);
|
||||
|
||||
protected:
|
||||
~MediaEngineGonkVideoSource()
|
||||
{
|
||||
|
@ -101,12 +112,17 @@ protected:
|
|||
void Shutdown();
|
||||
void ChooseCapability(const VideoTrackConstraintsN& aConstraints,
|
||||
const MediaEnginePrefs& aPrefs);
|
||||
// Initialize the recording frame (MediaBuffer) callback and Gonk camera.
|
||||
// MediaBuffer will transfers to MediaStreamGraph via AppendToTrack.
|
||||
nsresult InitDirectMediaBuffer();
|
||||
|
||||
mozilla::ReentrantMonitor mCallbackMonitor; // Monitor for camera callback handling
|
||||
// This is only modified on MainThread (AllocImpl and DeallocImpl)
|
||||
nsRefPtr<ICameraControl> mCameraControl;
|
||||
nsCOMPtr<nsIDOMFile> mLastCapture;
|
||||
|
||||
android::sp<android::GonkCameraSource> mCameraSource;
|
||||
|
||||
// These are protected by mMonitor in parent class
|
||||
nsTArray<nsRefPtr<PhotoCallback>> mPhotoCallbacks;
|
||||
int mRotation;
|
||||
|
|
|
@ -36,8 +36,12 @@ if CONFIG['MOZ_WEBRTC']:
|
|||
]
|
||||
# Gonk camera source.
|
||||
if CONFIG['MOZ_B2G_CAMERA']:
|
||||
EXPORTS += ['MediaEngineGonkVideoSource.h']
|
||||
EXPORTS += [
|
||||
'GonkCameraImage.h',
|
||||
'MediaEngineGonkVideoSource.h',
|
||||
]
|
||||
UNIFIED_SOURCES += [
|
||||
'GonkCameraImage.cpp',
|
||||
'MediaEngineGonkVideoSource.cpp',
|
||||
]
|
||||
|
||||
|
|
|
@ -462,6 +462,17 @@ SettingsManager.prototype = {
|
|||
|
||||
cleanup: function() {
|
||||
Services.obs.removeObserver(this, "inner-window-destroyed");
|
||||
// At this point, the window is dying, so there's nothing left
|
||||
// that we could do with our lock. Go ahead and run finalize on
|
||||
// it to make sure changes are commited.
|
||||
for (let i = 0; i < this._locks.length; ++i) {
|
||||
if (DEBUG) debug("Lock alive at destroy, finalizing: " + this._locks[i]);
|
||||
// Due to bug 1105511 we should be able to send this without
|
||||
// cached principals. However, this is scary because any iframe
|
||||
// in the process could run this?
|
||||
cpmm.sendAsyncMessage("Settings:Finalize",
|
||||
{lockID: this._locks[i]});
|
||||
}
|
||||
cpmm.removeMessageListener("Settings:Change:Return:OK", this);
|
||||
mrm.unregisterStrongReporter(this);
|
||||
this.innerWindowID = null;
|
||||
|
|
|
@ -17,12 +17,15 @@ Cu.import("resource://gre/modules/PermissionsTable.jsm");
|
|||
|
||||
let DEBUG = false;
|
||||
let VERBOSE = false;
|
||||
let TRACK = false;
|
||||
|
||||
try {
|
||||
DEBUG =
|
||||
Services.prefs.getBoolPref("dom.mozSettings.SettingsRequestManager.debug.enabled");
|
||||
VERBOSE =
|
||||
Services.prefs.getBoolPref("dom.mozSettings.SettingsRequestManager.verbose.enabled");
|
||||
TRACK =
|
||||
Services.prefs.getBoolPref("dom.mozSettings.trackTasksUsage");
|
||||
} catch (ex) { }
|
||||
|
||||
let allowForceReadOnly = false;
|
||||
|
@ -207,7 +210,12 @@ let SettingsRequestManager = {
|
|||
// for message managers and check permissions on them before we send
|
||||
// settings notifications to child processes.
|
||||
observerPrincipalCache: new Map(),
|
||||
tasksConsumed: 0,
|
||||
totalProcessed: 0,
|
||||
tasksConsumed: {},
|
||||
totalSetProcessed: 0,
|
||||
tasksSetConsumed: {},
|
||||
totalGetProcessed: 0,
|
||||
tasksGetConsumed: {},
|
||||
|
||||
init: function() {
|
||||
if (VERBOSE) debug("init");
|
||||
|
@ -650,6 +658,13 @@ let SettingsRequestManager = {
|
|||
}
|
||||
let currentTask = lock.tasks.shift();
|
||||
let promises = [];
|
||||
if (TRACK) {
|
||||
if (this.tasksConsumed[aLockID] === undefined) {
|
||||
this.tasksConsumed[aLockID] = 0;
|
||||
this.tasksGetConsumed[aLockID] = 0;
|
||||
this.tasksSetConsumed[aLockID] = 0;
|
||||
}
|
||||
}
|
||||
while (currentTask) {
|
||||
if (VERBOSE) debug("Running Operation " + currentTask.operation);
|
||||
if (lock.finalizing) {
|
||||
|
@ -659,12 +674,23 @@ let SettingsRequestManager = {
|
|||
currentTask.defer.reject("Cannot call new task after finalizing");
|
||||
} else {
|
||||
let p;
|
||||
this.tasksConsumed++;
|
||||
this.totalProcessed++;
|
||||
if (TRACK) {
|
||||
this.tasksConsumed[aLockID]++;
|
||||
}
|
||||
switch (currentTask.operation) {
|
||||
case "get":
|
||||
this.totalGetProcessed++;
|
||||
if (TRACK) {
|
||||
this.tasksGetConsumed[aLockID]++;
|
||||
}
|
||||
p = this.taskGet(currentTask);
|
||||
break;
|
||||
case "set":
|
||||
this.totalSetProcessed++;
|
||||
if (TRACK) {
|
||||
this.tasksSetConsumed[aLockID]++;
|
||||
}
|
||||
p = this.taskSet(currentTask);
|
||||
break;
|
||||
case "clear":
|
||||
|
@ -753,23 +779,75 @@ let SettingsRequestManager = {
|
|||
continue;
|
||||
}
|
||||
|
||||
let path = "settings-locks/tasks/queue-length(id=" + lockId + ")";
|
||||
let path = "settings-locks/tasks/lock(id=" + lockId + ")/";
|
||||
|
||||
aCallback.callback("", path,
|
||||
aCallback.callback("", path + "alive",
|
||||
Ci.nsIMemoryReporter.KIND_OTHER,
|
||||
Ci.nsIMemoryReporter.UNITS_COUNT,
|
||||
length,
|
||||
"Tasks queue length for this lock",
|
||||
"Alive tasks for this lock",
|
||||
aData);
|
||||
}
|
||||
|
||||
aCallback.callback("",
|
||||
"settings-locks/tasks/processed",
|
||||
"settings-locks/tasks-total/processed",
|
||||
Ci.nsIMemoryReporter.KIND_OTHER,
|
||||
Ci.nsIMemoryReporter.UNITS_COUNT,
|
||||
this.tasksConsumed,
|
||||
"The number of tasks that were executed.",
|
||||
this.totalProcessed,
|
||||
"The total number of tasks that were executed.",
|
||||
aData);
|
||||
|
||||
aCallback.callback("",
|
||||
"settings-locks/tasks-total/set",
|
||||
Ci.nsIMemoryReporter.KIND_OTHER,
|
||||
Ci.nsIMemoryReporter.UNITS_COUNT,
|
||||
this.totalSetProcessed,
|
||||
"The total number of set tasks that were executed.",
|
||||
aData);
|
||||
|
||||
aCallback.callback("",
|
||||
"settings-locks/tasks-total/get",
|
||||
Ci.nsIMemoryReporter.KIND_OTHER,
|
||||
Ci.nsIMemoryReporter.UNITS_COUNT,
|
||||
this.totalGetProcessed,
|
||||
"The total number of get tasks that were executed.",
|
||||
aData);
|
||||
|
||||
// if TRACK is not enabled, then, no details are available
|
||||
if (!TRACK) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let lockId of Object.keys(this.tasksConsumed)) {
|
||||
let lock = this.lockInfo[lockId];
|
||||
let length = 0;
|
||||
if (lock) {
|
||||
length = lock.tasks.length;
|
||||
}
|
||||
|
||||
let path = "settings-locks/tasks/lock(id=" + lockId + ")/";
|
||||
|
||||
aCallback.callback("", path + "set",
|
||||
Ci.nsIMemoryReporter.KIND_OTHER,
|
||||
Ci.nsIMemoryReporter.UNITS_COUNT,
|
||||
this.tasksSetConsumed[lockId],
|
||||
"Set tasks for this lock.",
|
||||
aData);
|
||||
|
||||
aCallback.callback("", path + "get",
|
||||
Ci.nsIMemoryReporter.KIND_OTHER,
|
||||
Ci.nsIMemoryReporter.UNITS_COUNT,
|
||||
this.tasksGetConsumed[lockId],
|
||||
"Get tasks for this lock.",
|
||||
aData);
|
||||
|
||||
aCallback.callback("", path + "processed",
|
||||
Ci.nsIMemoryReporter.KIND_OTHER,
|
||||
Ci.nsIMemoryReporter.UNITS_COUNT,
|
||||
this.tasksConsumed[lockId],
|
||||
"Number of tasks that were executed.",
|
||||
aData);
|
||||
}
|
||||
},
|
||||
|
||||
sendSettingsChange: function(aKey, aValue, aIsServiceLock) {
|
||||
|
|
|
@ -32,8 +32,12 @@ XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
|
|||
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
|
||||
"@mozilla.org/childprocessmessagemanager;1",
|
||||
"nsIMessageSender");
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "mrm",
|
||||
"@mozilla.org/memory-reporter-manager;1",
|
||||
"nsIMemoryReporterManager");
|
||||
|
||||
const nsIClassInfo = Ci.nsIClassInfo;
|
||||
const nsIClassInfo = Ci.nsIClassInfo;
|
||||
const kXpcomShutdownObserverTopic = "xpcom-shutdown";
|
||||
|
||||
const SETTINGSSERVICELOCK_CONTRACTID = "@mozilla.org/settingsServiceLock;1";
|
||||
const SETTINGSSERVICELOCK_CID = Components.ID("{d7a395a0-e292-11e1-834e-1761d57f5f99}");
|
||||
|
@ -85,6 +89,7 @@ SettingsServiceLock.prototype = {
|
|||
|
||||
runOrFinalizeQueries: function() {
|
||||
if (!this._requests || Object.keys(this._requests).length == 0) {
|
||||
this._settingsService.unregisterLock(this._id);
|
||||
cpmm.sendAsyncMessage("Settings:Finalize", {lockID: this._id}, undefined, Services.scriptSecurityManager.getSystemPrincipal());
|
||||
} else {
|
||||
cpmm.sendAsyncMessage("Settings:Run", {lockID: this._id}, undefined, Services.scriptSecurityManager.getSystemPrincipal());
|
||||
|
@ -229,17 +234,81 @@ const SETTINGSSERVICE_CID = Components.ID("{f656f0c0-f776-11e1-a21f-08002
|
|||
function SettingsService()
|
||||
{
|
||||
if (VERBOSE) debug("settingsService Constructor");
|
||||
this._locks = [];
|
||||
this._createdLocks = 0;
|
||||
this._unregisteredLocks = 0;
|
||||
this.init();
|
||||
}
|
||||
|
||||
SettingsService.prototype = {
|
||||
|
||||
init: function() {
|
||||
Services.obs.addObserver(this, kXpcomShutdownObserverTopic, false);
|
||||
mrm.registerStrongReporter(this);
|
||||
},
|
||||
|
||||
uninit: function() {
|
||||
Services.obs.removeObserver(this, kXpcomShutdownObserverTopic);
|
||||
mrm.unregisterStrongReporter(this);
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (VERBOSE) debug("observe: " + aTopic);
|
||||
if (aTopic === kXpcomShutdownObserverTopic) {
|
||||
this.uninit();
|
||||
}
|
||||
},
|
||||
|
||||
createLock: function createLock(aCallback) {
|
||||
var lock = new SettingsServiceLock(this, aCallback);
|
||||
this.registerLock(lock._id);
|
||||
return lock;
|
||||
},
|
||||
|
||||
registerLock: function(aLockID) {
|
||||
this._locks.push(aLockID);
|
||||
this._createdLocks++;
|
||||
},
|
||||
|
||||
unregisterLock: function(aLockID) {
|
||||
let lock_index = this._locks.indexOf(aLockID);
|
||||
if (lock_index != -1) {
|
||||
if (VERBOSE) debug("Unregistering lock " + aLockID);
|
||||
this._locks.splice(lock_index, 1);
|
||||
this._unregisteredLocks++;
|
||||
}
|
||||
},
|
||||
|
||||
collectReports: function(aCallback, aData, aAnonymize) {
|
||||
aCallback.callback("",
|
||||
"settings-service-locks/alive",
|
||||
Ci.nsIMemoryReporter.KIND_OTHER,
|
||||
Ci.nsIMemoryReporter.UNITS_COUNT,
|
||||
this._locks.length,
|
||||
"The number of service locks that are currently alives.",
|
||||
aData);
|
||||
|
||||
aCallback.callback("",
|
||||
"settings-service-locks/created",
|
||||
Ci.nsIMemoryReporter.KIND_OTHER,
|
||||
Ci.nsIMemoryReporter.UNITS_COUNT,
|
||||
this._createdLocks,
|
||||
"The number of service locks that were created.",
|
||||
aData);
|
||||
|
||||
aCallback.callback("",
|
||||
"settings-service-locks/deleted",
|
||||
Ci.nsIMemoryReporter.KIND_OTHER,
|
||||
Ci.nsIMemoryReporter.UNITS_COUNT,
|
||||
this._unregisteredLocks,
|
||||
"The number of service locks that were deleted.",
|
||||
aData);
|
||||
},
|
||||
|
||||
classID : SETTINGSSERVICE_CID,
|
||||
QueryInterface : XPCOMUtils.generateQI([Ci.nsISettingsService])
|
||||
QueryInterface : XPCOMUtils.generateQI([Ci.nsISettingsService,
|
||||
Ci.nsIObserver,
|
||||
Ci.nsIMemoryReporter])
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SettingsService, SettingsServiceLock]);
|
||||
|
|
|
@ -65,6 +65,9 @@ public:
|
|||
NS_IMETHOD Run()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
NS_SetIgnoreStatusOfCurrentThread();
|
||||
#endif
|
||||
nsAutoString event;
|
||||
gWpaSupplicant->WaitForEvent(event, mInterface);
|
||||
if (!event.IsEmpty()) {
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
#include "nsProxyRelease.h"
|
||||
#include "nsSandboxFlags.h"
|
||||
#include "prthread.h"
|
||||
#include "nsThread.h"
|
||||
#include "xpcpublic.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
|
@ -4332,6 +4333,17 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
|
|||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
{
|
||||
nsThread *thr = static_cast<nsThread*>(NS_GetCurrentThread());
|
||||
ReentrantMonitorAutoEnter mon(thr->ThreadStatusMonitor());
|
||||
if (mControlQueue.IsEmpty() &&
|
||||
!(normalRunnablesPending = NS_HasPendingEvents(mThread))) {
|
||||
thr->SetIdle();
|
||||
}
|
||||
}
|
||||
#endif // MOZ_NUWA_PROCESS
|
||||
|
||||
while (mControlQueue.IsEmpty() &&
|
||||
!(normalRunnablesPending = NS_HasPendingEvents(mThread))) {
|
||||
WaitForWorkerEvents();
|
||||
|
|
|
@ -97,6 +97,11 @@ public:
|
|||
|
||||
virtual TextureClient* GetTextureClient(CompositableClient* aClient) MOZ_OVERRIDE;
|
||||
|
||||
virtual GrallocImage* AsGrallocImage() MOZ_OVERRIDE
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
virtual uint8_t* GetBuffer()
|
||||
{
|
||||
return static_cast<uint8_t*>(GetNativeBuffer());
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "YCbCrUtils.h" // for YCbCr conversions
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#include "GrallocImages.h"
|
||||
#include "GonkCameraImage.h"
|
||||
#endif
|
||||
#include "gfx2DGlue.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
|
@ -60,6 +61,10 @@ ImageFactory::CreateImage(ImageFormat aFormat,
|
|||
img = new OverlayImage();
|
||||
return img.forget();
|
||||
}
|
||||
if (aFormat == ImageFormat::GONK_CAMERA_IMAGE) {
|
||||
img = new GonkCameraImage();
|
||||
return img.forget();
|
||||
}
|
||||
#endif
|
||||
if (aFormat == ImageFormat::PLANAR_YCBCR) {
|
||||
img = new PlanarYCbCrImage(aRecycleBin);
|
||||
|
|
|
@ -105,6 +105,7 @@ class TextureClient;
|
|||
class CompositableClient;
|
||||
class CompositableForwarder;
|
||||
class SurfaceDescriptor;
|
||||
class GrallocImage;
|
||||
|
||||
struct ImageBackendData
|
||||
{
|
||||
|
@ -167,6 +168,11 @@ public:
|
|||
|
||||
virtual TemporaryRef<gfx::SourceSurface> GetAsSourceSurface() = 0;
|
||||
|
||||
virtual GrallocImage* AsGrallocImage()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
Image(void* aImplData, ImageFormat aFormat) :
|
||||
mImplData(aImplData),
|
||||
|
|
|
@ -25,6 +25,16 @@ MOZ_BEGIN_ENUM_CLASS(ImageFormat)
|
|||
*/
|
||||
GRALLOC_PLANAR_YCBCR,
|
||||
|
||||
/**
|
||||
* The GONK_CAMERA_IMAGE format creates a GonkCameraImage, which contains two
|
||||
* parts. One is GrallocImage image for preview image. Another one is
|
||||
* MediaBuffer from Gonk recording image. The preview image can be rendered in
|
||||
* a layer for display. And the MediaBuffer will be used in component like OMX
|
||||
* encoder. It is for GUM to support preview and recording image on Gonk
|
||||
* camera.
|
||||
*/
|
||||
GONK_CAMERA_IMAGE,
|
||||
|
||||
/**
|
||||
* The SHARED_RGB format creates a SharedRGBImage, which stores RGB data in
|
||||
* shared memory. Some Android hardware video decoders require this format.
|
||||
|
|
|
@ -373,6 +373,11 @@ CanvasClientSharedSurface::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
|
|||
newTex = TexClientFromReadback(surf, forwarder, flags, layersBackend);
|
||||
}
|
||||
MOZ_ASSERT(newTex);
|
||||
if (!newTex) {
|
||||
// May happen in a release build in case of memory pressure.
|
||||
gfxCriticalError() << "Failed to allocate a TextureClient for SharedSurface Canvas. size: " << aSize;
|
||||
return;
|
||||
}
|
||||
|
||||
// Add the new TexClient.
|
||||
MOZ_ALWAYS_TRUE( AddTextureClient(newTex) );
|
||||
|
|
|
@ -196,23 +196,30 @@ static void SetThreadPriority()
|
|||
hal::SetCurrentThreadPriority(hal::THREAD_PRIORITY_COMPOSITOR);
|
||||
}
|
||||
|
||||
CompositorVsyncObserver::CompositorVsyncObserver(CompositorParent* aCompositorParent)
|
||||
CompositorVsyncObserver::CompositorVsyncObserver(CompositorParent* aCompositorParent, nsIWidget* aWidget)
|
||||
: mNeedsComposite(false)
|
||||
, mIsObservingVsync(false)
|
||||
, mCompositorParent(aCompositorParent)
|
||||
, mCurrentCompositeTaskMonitor("CurrentCompositeTaskMonitor")
|
||||
, mCurrentCompositeTask(nullptr)
|
||||
{
|
||||
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aWidget != nullptr);
|
||||
mVsyncDispatcher = aWidget->GetVsyncDispatcher();
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
GeckoTouchDispatcher::SetCompositorVsyncObserver(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
CompositorVsyncObserver::~CompositorVsyncObserver()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
UnobserveVsync();
|
||||
mCompositorParent = nullptr;
|
||||
mNeedsComposite = false;
|
||||
MOZ_ASSERT(CompositorParent::IsInCompositorThread());
|
||||
MOZ_ASSERT(!mIsObservingVsync);
|
||||
// The VsyncDispatcher is cleaned up before this in the nsBaseWidget, which stops vsync listeners
|
||||
CancelCurrentCompositeTask();
|
||||
mCompositorParent = nullptr;
|
||||
mVsyncDispatcher = nullptr;
|
||||
mNeedsComposite = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -225,9 +232,14 @@ CompositorVsyncObserver::~CompositorVsyncObserver()
|
|||
void
|
||||
CompositorVsyncObserver::SetNeedsComposite(bool aNeedsComposite)
|
||||
{
|
||||
MOZ_ASSERT(CompositorParent::IsInCompositorThread());
|
||||
mNeedsComposite = aNeedsComposite;
|
||||
if (aNeedsComposite && !CompositorParent::IsInCompositorThread()) {
|
||||
CompositorParent::CompositorLoop()->PostTask(FROM_HERE,
|
||||
NewRunnableMethod(this,
|
||||
&CompositorVsyncObserver::SetNeedsComposite,
|
||||
aNeedsComposite));
|
||||
}
|
||||
|
||||
mNeedsComposite = aNeedsComposite;
|
||||
if (!mIsObservingVsync && mNeedsComposite) {
|
||||
ObserveVsync();
|
||||
}
|
||||
|
@ -273,10 +285,6 @@ CompositorVsyncObserver::Composite(TimeStamp aVsyncTimestamp)
|
|||
if (mNeedsComposite && mCompositorParent) {
|
||||
mNeedsComposite = false;
|
||||
mCompositorParent->CompositeCallback(aVsyncTimestamp);
|
||||
} else {
|
||||
// We're getting vsync notifications but we don't need to composite so
|
||||
// unregister the vsync.
|
||||
UnobserveVsync();
|
||||
}
|
||||
|
||||
DispatchTouchEvents(aVsyncTimestamp);
|
||||
|
@ -289,15 +297,11 @@ CompositorVsyncObserver::NeedsComposite()
|
|||
return mNeedsComposite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Since the vsync thread has its own locks before notifying us of vsync
|
||||
* we can't register/unregister from the vsync thread. Any other thread is fine
|
||||
*/
|
||||
void
|
||||
CompositorVsyncObserver::ObserveVsync()
|
||||
{
|
||||
MOZ_ASSERT(CompositorParent::IsInCompositorThread());
|
||||
VsyncDispatcher::GetInstance()->AddCompositorVsyncObserver(this);
|
||||
mVsyncDispatcher->SetCompositorVsyncObserver(this);
|
||||
mIsObservingVsync = true;
|
||||
}
|
||||
|
||||
|
@ -305,7 +309,7 @@ void
|
|||
CompositorVsyncObserver::UnobserveVsync()
|
||||
{
|
||||
MOZ_ASSERT(CompositorParent::IsInCompositorThread() || NS_IsMainThread());
|
||||
VsyncDispatcher::GetInstance()->RemoveCompositorVsyncObserver(this);
|
||||
mVsyncDispatcher->SetCompositorVsyncObserver(nullptr);
|
||||
mIsObservingVsync = false;
|
||||
}
|
||||
|
||||
|
@ -313,9 +317,7 @@ void
|
|||
CompositorVsyncObserver::DispatchTouchEvents(TimeStamp aVsyncTimestamp)
|
||||
{
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
if (gfxPrefs::TouchResampling()) {
|
||||
GeckoTouchDispatcher::NotifyVsync(aVsyncTimestamp);
|
||||
}
|
||||
GeckoTouchDispatcher::NotifyVsync(aVsyncTimestamp);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -385,7 +387,7 @@ CompositorParent::CompositorParent(nsIWidget* aWidget,
|
|||
}
|
||||
|
||||
if (gfxPrefs::VsyncAlignedCompositor()) {
|
||||
mCompositorVsyncObserver = new CompositorVsyncObserver(this);
|
||||
mCompositorVsyncObserver = new CompositorVsyncObserver(this, aWidget);
|
||||
}
|
||||
|
||||
gfxPlatform::GetPlatform()->ComputeTileSize();
|
||||
|
@ -428,7 +430,10 @@ CompositorParent::Destroy()
|
|||
mApzcTreeManager = nullptr;
|
||||
}
|
||||
sIndirectLayerTrees.erase(mRootLayerTreeID);
|
||||
mCompositorVsyncObserver = nullptr;
|
||||
if (mCompositorVsyncObserver) {
|
||||
mCompositorVsyncObserver->UnobserveVsync();
|
||||
mCompositorVsyncObserver = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -100,12 +100,12 @@ class CompositorVsyncObserver MOZ_FINAL : public VsyncObserver
|
|||
friend class CompositorParent;
|
||||
|
||||
public:
|
||||
explicit CompositorVsyncObserver(CompositorParent* aCompositorParent);
|
||||
explicit CompositorVsyncObserver(CompositorParent* aCompositorParent, nsIWidget* aWidget);
|
||||
virtual bool NotifyVsync(TimeStamp aVsyncTimestamp) MOZ_OVERRIDE;
|
||||
void SetNeedsComposite(bool aSchedule);
|
||||
bool NeedsComposite();
|
||||
void CancelCurrentCompositeTask();
|
||||
|
||||
|
||||
private:
|
||||
virtual ~CompositorVsyncObserver();
|
||||
|
||||
|
@ -118,6 +118,7 @@ private:
|
|||
bool mNeedsComposite;
|
||||
bool mIsObservingVsync;
|
||||
nsRefPtr<CompositorParent> mCompositorParent;
|
||||
nsRefPtr<VsyncDispatcher> mVsyncDispatcher;
|
||||
|
||||
mozilla::Monitor mCurrentCompositeTaskMonitor;
|
||||
CancelableTask* mCurrentCompositeTask;
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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 "VsyncSource.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/VsyncDispatcher.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
void
|
||||
VsyncSource::AddVsyncDispatcher(VsyncDispatcher* aVsyncDispatcher)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
GetGlobalDisplay().AddVsyncDispatcher(aVsyncDispatcher);
|
||||
}
|
||||
|
||||
void
|
||||
VsyncSource::RemoveVsyncDispatcher(VsyncDispatcher* aVsyncDispatcher)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
GetGlobalDisplay().RemoveVsyncDispatcher(aVsyncDispatcher);
|
||||
}
|
||||
|
||||
VsyncSource::Display&
|
||||
VsyncSource::FindDisplay(VsyncDispatcher* aVsyncDispatcher)
|
||||
{
|
||||
return GetGlobalDisplay();
|
||||
}
|
||||
|
||||
void
|
||||
VsyncSource::Display::NotifyVsync(TimeStamp aVsyncTimestamp)
|
||||
{
|
||||
// Called on the hardware vsync thread
|
||||
for (size_t i = 0; i < mVsyncDispatchers.Length(); i++) {
|
||||
mVsyncDispatchers[i]->NotifyVsync(aVsyncTimestamp);
|
||||
}
|
||||
}
|
||||
|
||||
VsyncSource::Display::Display()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
VsyncSource::Display::~Display()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mVsyncDispatchers.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
VsyncSource::Display::AddVsyncDispatcher(VsyncDispatcher* aVsyncDispatcher)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mVsyncDispatchers.AppendElement(aVsyncDispatcher);
|
||||
}
|
||||
|
||||
void
|
||||
VsyncSource::Display::RemoveVsyncDispatcher(VsyncDispatcher* aVsyncDispatcher)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mVsyncDispatchers.RemoveElement(aVsyncDispatcher);
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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/RefPtr.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
class VsyncDispatcher;
|
||||
|
||||
namespace gfx {
|
||||
|
||||
// Controls how and when to enable/disable vsync. Lives as long as the
|
||||
// gfxPlatform does on the parent process
|
||||
class VsyncSource
|
||||
{
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VsyncSource)
|
||||
public:
|
||||
// Controls vsync unique to each display and unique on each platform
|
||||
class Display {
|
||||
public:
|
||||
Display();
|
||||
virtual ~Display();
|
||||
void AddVsyncDispatcher(mozilla::VsyncDispatcher* aVsyncDispatcher);
|
||||
void RemoveVsyncDispatcher(mozilla::VsyncDispatcher* aVsyncDispatcher);
|
||||
// Notified when this display's vsync occurs, on the hardware vsync thread
|
||||
void NotifyVsync(mozilla::TimeStamp aVsyncTimestamp);
|
||||
|
||||
// These should all only be called on the main thread
|
||||
virtual void EnableVsync() = 0;
|
||||
virtual void DisableVsync() = 0;
|
||||
virtual bool IsVsyncEnabled() = 0;
|
||||
|
||||
private:
|
||||
nsTArray<nsRefPtr<mozilla::VsyncDispatcher>> mVsyncDispatchers;
|
||||
}; // end Display
|
||||
|
||||
void AddVsyncDispatcher(mozilla::VsyncDispatcher* aVsyncDispatcher);
|
||||
void RemoveVsyncDispatcher(mozilla::VsyncDispatcher* aVsyncDispatcher);
|
||||
|
||||
protected:
|
||||
virtual Display& GetGlobalDisplay() = 0; // Works across all displays
|
||||
virtual Display& FindDisplay(mozilla::VsyncDispatcher* aVsyncDispatcher);
|
||||
virtual ~VsyncSource() {}
|
||||
}; // VsyncSource
|
||||
} // gfx
|
||||
} // mozilla
|
|
@ -23,6 +23,7 @@
|
|||
#include "nsServiceManagerUtils.h"
|
||||
#include "gfxPrefs.h"
|
||||
#include "cairo.h"
|
||||
#include "VsyncSource.h"
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
#include "AndroidBridge.h"
|
||||
|
@ -30,6 +31,8 @@
|
|||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#include <cutils/properties.h>
|
||||
#include "mozilla/layers/CompositorParent.h"
|
||||
#include "HwcComposer2D.h"
|
||||
#endif
|
||||
|
||||
#include "ft2build.h"
|
||||
|
@ -420,3 +423,72 @@ bool gfxAndroidPlatform::HaveChoiceOfHWAndSWCanvas()
|
|||
#endif
|
||||
return gfxPlatform::HaveChoiceOfHWAndSWCanvas();
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
class GonkVsyncSource MOZ_FINAL : public VsyncSource
|
||||
{
|
||||
public:
|
||||
GonkVsyncSource()
|
||||
{
|
||||
}
|
||||
|
||||
virtual Display& GetGlobalDisplay() MOZ_OVERRIDE
|
||||
{
|
||||
return mGlobalDisplay;
|
||||
}
|
||||
|
||||
protected:
|
||||
class GonkDisplay MOZ_FINAL : public VsyncSource::Display
|
||||
{
|
||||
public:
|
||||
GonkDisplay() : mVsyncEnabled(false)
|
||||
{
|
||||
EnableVsync();
|
||||
}
|
||||
|
||||
~GonkDisplay()
|
||||
{
|
||||
DisableVsync();
|
||||
}
|
||||
|
||||
virtual void EnableVsync() MOZ_OVERRIDE
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mVsyncEnabled = HwcComposer2D::GetInstance()->EnableVsync(true);
|
||||
}
|
||||
|
||||
virtual void DisableVsync() MOZ_OVERRIDE
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mVsyncEnabled = HwcComposer2D::GetInstance()->EnableVsync(false);
|
||||
}
|
||||
|
||||
virtual bool IsVsyncEnabled() MOZ_OVERRIDE
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return mVsyncEnabled;
|
||||
}
|
||||
private:
|
||||
bool mVsyncEnabled;
|
||||
}; // GonkDisplay
|
||||
|
||||
private:
|
||||
virtual ~GonkVsyncSource()
|
||||
{
|
||||
}
|
||||
|
||||
GonkDisplay mGlobalDisplay;
|
||||
}; // GonkVsyncSource
|
||||
#endif
|
||||
|
||||
already_AddRefed<mozilla::gfx::VsyncSource>
|
||||
gfxAndroidPlatform::CreateHardwareVsyncSource()
|
||||
{
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
nsRefPtr<VsyncSource> vsyncSource = new GonkVsyncSource();
|
||||
return vsyncSource.forget();
|
||||
#else
|
||||
NS_WARNING("Hardware vsync not supported on android yet");
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -89,6 +89,8 @@ public:
|
|||
|
||||
virtual bool HaveChoiceOfHWAndSWCanvas() MOZ_OVERRIDE;
|
||||
virtual bool UseAcceleratedSkiaCanvas() MOZ_OVERRIDE;
|
||||
virtual already_AddRefed<mozilla::gfx::VsyncSource> CreateHardwareVsyncSource() MOZ_OVERRIDE;
|
||||
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
virtual bool IsInGonkEmulator() const { return mIsInGonkEmulator; }
|
||||
|
|
|
@ -104,6 +104,7 @@ class mozilla::gl::SkiaGLGlue : public GenericAtomicRefCounted {
|
|||
|
||||
#include "nsIGfxInfo.h"
|
||||
#include "nsIXULRuntime.h"
|
||||
#include "VsyncSource.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
@ -548,8 +549,8 @@ gfxPlatform::Init()
|
|||
|
||||
RegisterStrongMemoryReporter(new GfxMemoryImageReporter());
|
||||
|
||||
if (gfxPrefs::HardwareVsyncEnabled() && gfxPrefs::VsyncAlignedCompositor()) {
|
||||
gPlatform->InitHardwareVsync();
|
||||
if (XRE_IsParentProcess() && gfxPrefs::HardwareVsyncEnabled()) {
|
||||
gPlatform->mVsyncSource = gPlatform->CreateHardwareVsyncSource();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -597,6 +598,7 @@ gfxPlatform::Shutdown()
|
|||
|
||||
gPlatform->mMemoryPressureObserver = nullptr;
|
||||
gPlatform->mSkiaGlue = nullptr;
|
||||
gPlatform->mVsyncSource = nullptr;
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
|
|
|
@ -50,6 +50,7 @@ class SourceSurface;
|
|||
class DataSourceSurface;
|
||||
class ScaledFont;
|
||||
class DrawEventRecorder;
|
||||
class VsyncSource;
|
||||
|
||||
inline uint32_t
|
||||
BackendTypeBit(BackendType b)
|
||||
|
@ -583,6 +584,17 @@ public:
|
|||
static bool UsesOffMainThreadCompositing();
|
||||
|
||||
bool HasEnoughTotalSystemMemoryForSkiaGL();
|
||||
|
||||
/**
|
||||
* Get the hardware vsync source for each platform.
|
||||
* Should only exist and be valid on the parent process
|
||||
*/
|
||||
virtual mozilla::gfx::VsyncSource* GetHardwareVsync() {
|
||||
MOZ_ASSERT(mVsyncSource != nullptr);
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
return mVsyncSource;
|
||||
}
|
||||
|
||||
protected:
|
||||
gfxPlatform();
|
||||
virtual ~gfxPlatform();
|
||||
|
@ -593,7 +605,10 @@ protected:
|
|||
/**
|
||||
* Initialized hardware vsync based on each platform.
|
||||
*/
|
||||
virtual void InitHardwareVsync() {}
|
||||
virtual already_AddRefed<mozilla::gfx::VsyncSource> CreateHardwareVsyncSource() {
|
||||
NS_WARNING("Hardware vsync not supported on platform yet");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method, creates a draw target for a specific Azure backend.
|
||||
|
@ -659,6 +674,9 @@ protected:
|
|||
|
||||
uint32_t mTotalSystemMemory;
|
||||
|
||||
// Hardware vsync source. Only valid on parent process
|
||||
nsRefPtr<mozilla::gfx::VsyncSource> mVsyncSource;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Start up Thebes.
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include <CoreVideo/CoreVideo.h>
|
||||
|
||||
#include "nsCocoaFeatures.h"
|
||||
#include "mozilla/layers/CompositorParent.h"
|
||||
#include "VsyncSource.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gfx;
|
||||
|
@ -38,7 +40,7 @@ typedef uint32_t AutoActivationSetting;
|
|||
|
||||
// bug 567552 - disable auto-activation of fonts
|
||||
|
||||
static void
|
||||
static void
|
||||
DisableFontActivation()
|
||||
{
|
||||
// get the main bundle identifier
|
||||
|
@ -429,81 +431,98 @@ static CVReturn VsyncCallback(CVDisplayLinkRef aDisplayLink,
|
|||
CVOptionFlags* aFlagsOut,
|
||||
void* aDisplayLinkContext)
|
||||
{
|
||||
mozilla::VsyncSource* vsyncSource = (mozilla::VsyncSource*) aDisplayLinkContext;
|
||||
if (vsyncSource->IsVsyncEnabled()) {
|
||||
// Now refers to "Now" as in when this callback is called or when the current frame
|
||||
// is displayed. aOutputTime is when the next frame should be displayed.
|
||||
// Now is VERY VERY noisy, aOutputTime is in the future though.
|
||||
int64_t timestamp = aOutputTime->hostTime;
|
||||
mozilla::TimeStamp vsyncTime = mozilla::TimeStamp::FromSystemTime(timestamp);
|
||||
mozilla::VsyncDispatcher::GetInstance()->NotifyVsync(vsyncTime);
|
||||
return kCVReturnSuccess;
|
||||
} else {
|
||||
return kCVReturnDisplayLinkNotRunning;
|
||||
}
|
||||
VsyncSource::Display* display = (VsyncSource::Display*) aDisplayLinkContext;
|
||||
int64_t timestamp = aOutputTime->hostTime;
|
||||
mozilla::TimeStamp vsyncTime = mozilla::TimeStamp::FromSystemTime(timestamp);
|
||||
display->NotifyVsync(vsyncTime);
|
||||
return kCVReturnSuccess;
|
||||
}
|
||||
|
||||
class OSXVsyncSource MOZ_FINAL : public mozilla::VsyncSource
|
||||
class OSXVsyncSource MOZ_FINAL : public VsyncSource
|
||||
{
|
||||
public:
|
||||
OSXVsyncSource()
|
||||
{
|
||||
EnableVsync();
|
||||
}
|
||||
|
||||
virtual void EnableVsync() MOZ_OVERRIDE
|
||||
virtual Display& GetGlobalDisplay() MOZ_OVERRIDE
|
||||
{
|
||||
// Create a display link capable of being used with all active displays
|
||||
// TODO: See if we need to create an active DisplayLink for each monitor in multi-monitor
|
||||
// situations. According to the docs, it is compatible with all displays running on the computer
|
||||
// But if we have different monitors at different display rates, we may hit issues.
|
||||
if (CVDisplayLinkCreateWithActiveCGDisplays(&mDisplayLink) != kCVReturnSuccess) {
|
||||
NS_WARNING("Could not create a display link, returning");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the renderer output callback function
|
||||
if (CVDisplayLinkSetOutputCallback(mDisplayLink, &VsyncCallback, this) != kCVReturnSuccess) {
|
||||
NS_WARNING("Could not set displaylink output callback");
|
||||
return;
|
||||
}
|
||||
|
||||
// Activate the display link
|
||||
if (CVDisplayLinkStart(mDisplayLink) != kCVReturnSuccess) {
|
||||
NS_WARNING("Could not activate the display link");
|
||||
mDisplayLink = nullptr;
|
||||
}
|
||||
return mGlobalDisplay;
|
||||
}
|
||||
|
||||
virtual void DisableVsync() MOZ_OVERRIDE
|
||||
protected:
|
||||
class OSXDisplay MOZ_FINAL : public VsyncSource::Display
|
||||
{
|
||||
// Release the display link
|
||||
if (mDisplayLink) {
|
||||
CVDisplayLinkRelease(mDisplayLink);
|
||||
mDisplayLink = nullptr;
|
||||
public:
|
||||
OSXDisplay()
|
||||
{
|
||||
EnableVsync();
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool IsVsyncEnabled() MOZ_OVERRIDE
|
||||
{
|
||||
return mDisplayLink != nullptr;
|
||||
}
|
||||
~OSXDisplay()
|
||||
{
|
||||
DisableVsync();
|
||||
}
|
||||
|
||||
virtual void EnableVsync() MOZ_OVERRIDE
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Create a display link capable of being used with all active displays
|
||||
// TODO: See if we need to create an active DisplayLink for each monitor in multi-monitor
|
||||
// situations. According to the docs, it is compatible with all displays running on the computer
|
||||
// But if we have different monitors at different display rates, we may hit issues.
|
||||
if (CVDisplayLinkCreateWithActiveCGDisplays(&mDisplayLink) != kCVReturnSuccess) {
|
||||
NS_WARNING("Could not create a display link, returning");
|
||||
return;
|
||||
}
|
||||
|
||||
if (CVDisplayLinkSetOutputCallback(mDisplayLink, &VsyncCallback, this) != kCVReturnSuccess) {
|
||||
NS_WARNING("Could not set displaylink output callback");
|
||||
return;
|
||||
}
|
||||
|
||||
if (CVDisplayLinkStart(mDisplayLink) != kCVReturnSuccess) {
|
||||
NS_WARNING("Could not activate the display link");
|
||||
mDisplayLink = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void DisableVsync() MOZ_OVERRIDE
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Release the display link
|
||||
if (mDisplayLink) {
|
||||
CVDisplayLinkRelease(mDisplayLink);
|
||||
mDisplayLink = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool IsVsyncEnabled() MOZ_OVERRIDE
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return mDisplayLink != nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
// Manages the display link render thread
|
||||
CVDisplayLinkRef mDisplayLink;
|
||||
}; // OSXDisplay
|
||||
|
||||
private:
|
||||
virtual ~OSXVsyncSource()
|
||||
{
|
||||
DisableVsync();
|
||||
}
|
||||
|
||||
// Manages the display link render thread
|
||||
CVDisplayLinkRef mDisplayLink;
|
||||
OSXDisplay mGlobalDisplay;
|
||||
}; // OSXVsyncSource
|
||||
|
||||
void
|
||||
gfxPlatformMac::InitHardwareVsync()
|
||||
already_AddRefed<mozilla::gfx::VsyncSource>
|
||||
gfxPlatformMac::CreateHardwareVsyncSource()
|
||||
{
|
||||
nsRefPtr<VsyncSource> osxVsyncSource = new OSXVsyncSource();
|
||||
mozilla::VsyncDispatcher::GetInstance()->SetVsyncSource(osxVsyncSource);
|
||||
return osxVsyncSource.forget();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -9,7 +9,12 @@
|
|||
#include "nsTArrayForwardDeclare.h"
|
||||
#include "gfxPlatform.h"
|
||||
|
||||
namespace mozilla { namespace gfx { class DrawTarget; }}
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
class DrawTarget;
|
||||
class VsyncSource;
|
||||
} // gfx
|
||||
} // mozilla
|
||||
|
||||
class gfxPlatformMac : public gfxPlatform {
|
||||
public:
|
||||
|
@ -67,7 +72,7 @@ public:
|
|||
|
||||
virtual bool UseTiling() MOZ_OVERRIDE;
|
||||
virtual bool UseProgressivePaint() MOZ_OVERRIDE;
|
||||
virtual void InitHardwareVsync() MOZ_OVERRIDE;
|
||||
virtual already_AddRefed<mozilla::gfx::VsyncSource> CreateHardwareVsyncSource() MOZ_OVERRIDE;
|
||||
|
||||
// lower threshold on font anti-aliasing
|
||||
uint32_t GetAntiAliasingThreshold() { return mFontAntiAliasingThreshold; }
|
||||
|
|
|
@ -52,6 +52,7 @@ EXPORTS += [
|
|||
'gfxVR.h',
|
||||
'GraphicsFilter.h',
|
||||
'RoundedRect.h',
|
||||
'VsyncSource.h',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
|
||||
|
@ -246,6 +247,7 @@ UNIFIED_SOURCES += [
|
|||
'gfxUtils.cpp',
|
||||
'gfxVR.cpp',
|
||||
'nsUnicodeRange.cpp',
|
||||
'VsyncSource.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
||||
|
@ -269,6 +271,9 @@ LOCAL_INCLUDES += [
|
|||
'/dom/xml',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
LOCAL_INCLUDES += ['/widget/gonk']
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gtk3', 'gonk', 'qt'):
|
||||
DEFINES['MOZ_ENABLE_FREETYPE'] = True
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
gczeal(14);
|
||||
b = {};
|
||||
b.__proto__ = evalcx("lazy");
|
||||
(function m(b) {})(b.Intl.Collator(0))
|
||||
if (this.hasOwnProperty("Intl")) {
|
||||
gczeal(14);
|
||||
b = {};
|
||||
b.__proto__ = evalcx("lazy");
|
||||
(function m(b) {})(b.Intl.Collator(0))
|
||||
}
|
||||
|
|
|
@ -422,10 +422,7 @@ else:
|
|||
'perf/pm_stub.cpp'
|
||||
]
|
||||
|
||||
# Disable PGO for MSVC 2010 due to unpredictable performance, see
|
||||
# bug 1030706.
|
||||
if CONFIG['_MSC_VER'] != '1600':
|
||||
MSVC_ENABLE_PGO = True
|
||||
MSVC_ENABLE_PGO = True
|
||||
|
||||
HostSimplePrograms([
|
||||
'host_jskwgen',
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsContentPolicyUtils.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsIClassOfService.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsIStyleSheetLinkingElement.h"
|
||||
|
@ -1623,10 +1623,12 @@ Loader::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState)
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHttpChannelInternal>
|
||||
internalHttpChannel(do_QueryInterface(channel));
|
||||
if (internalHttpChannel)
|
||||
internalHttpChannel->SetLoadAsBlocking(!aLoadData->mWasAlternate);
|
||||
if (!aLoadData->mWasAlternate) {
|
||||
nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
|
||||
if (cos) {
|
||||
cos->AddClassFlags(nsIClassOfService::Leader);
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
|
||||
if (httpChannel) {
|
||||
|
|
|
@ -92,7 +92,7 @@ if CONFIG['OS_TARGET'] == 'Android':
|
|||
'%s/sources/android/cpufeatures/cpu-features.c' % CONFIG['ANDROID_NDK'],
|
||||
]
|
||||
|
||||
if not CONFIG['_MSC_VER']:
|
||||
if CONFIG['CLANG_CL'] or not CONFIG['_MSC_VER']:
|
||||
for f in SOURCES:
|
||||
if f.endswith('.c'):
|
||||
if 'sse2' in f:
|
||||
|
|
|
@ -1172,8 +1172,8 @@ void MediaPipelineTransmit::PipelineListener::ProcessVideoChunk(
|
|||
|
||||
ImageFormat format = img->GetFormat();
|
||||
#ifdef WEBRTC_GONK
|
||||
if (format == ImageFormat::GRALLOC_PLANAR_YCBCR) {
|
||||
layers::GrallocImage *nativeImage = static_cast<layers::GrallocImage*>(img);
|
||||
layers::GrallocImage* nativeImage = img->AsGrallocImage();
|
||||
if (nativeImage) {
|
||||
android::sp<android::GraphicBuffer> graphicBuffer = nativeImage->GetGraphicBuffer();
|
||||
int pixelFormat = graphicBuffer->getPixelFormat(); /* PixelFormat is an enum == int */
|
||||
mozilla::VideoType destFormat;
|
||||
|
|
|
@ -1284,6 +1284,7 @@ pref("network.http.spdy.enabled", true);
|
|||
pref("network.http.spdy.enabled.v3-1", true);
|
||||
pref("network.http.spdy.enabled.http2draft", true);
|
||||
pref("network.http.spdy.enabled.http2", true);
|
||||
pref("network.http.spdy.enabled.deps", true);
|
||||
pref("network.http.spdy.enforce-tls-profile", true);
|
||||
pref("network.http.spdy.chunk-size", 16000);
|
||||
pref("network.http.spdy.timeout", 180);
|
||||
|
|
|
@ -30,6 +30,7 @@ XPIDL_SOURCES += [
|
|||
'nsIChannel.idl',
|
||||
'nsIChannelEventSink.idl',
|
||||
'nsIChildChannel.idl',
|
||||
'nsIClassOfService.idl',
|
||||
'nsIContentSniffer.idl',
|
||||
'nsICryptoFIPSInfo.idl',
|
||||
'nsICryptoHash.idl',
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/* 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 "nsISupports.idl"
|
||||
|
||||
/**
|
||||
* nsIClassOfService.idl
|
||||
*
|
||||
* Used to express class dependencies and characteristics - complimentary to
|
||||
* nsISupportsPriority which is used to express weight
|
||||
*
|
||||
* Channels that implement this interface may make use of this
|
||||
* information in different ways.
|
||||
*
|
||||
* The default gecko HTTP/1 stack makes Followers wait for Leaders to
|
||||
* complete before dispatching followers. Other classes run in
|
||||
* parallel - neither being blocked nor blocking. All grouping is done
|
||||
* based on the Load Group - separate load groups proceed
|
||||
* independently.
|
||||
*
|
||||
* HTTP/2 does not use the load group, but prioritization is done per
|
||||
* HTTP/2 session. HTTP/2 dispatches all the requests as soon as
|
||||
* possible.
|
||||
* The various classes are assigned logical priority
|
||||
* dependency groups and then transactions of that class depend on the
|
||||
* group. In this model Followers block on Leaders and Speculative
|
||||
* depends on Background. See Http2Stream.cpp for weighting details.
|
||||
*
|
||||
*/
|
||||
|
||||
[scriptable, uuid(1ccb58ec-5e07-4cf9-a30d-ac5490d23b41)]
|
||||
interface nsIClassOfService : nsISupports
|
||||
{
|
||||
attribute unsigned long classFlags;
|
||||
|
||||
void clearClassFlags(in unsigned long flags);
|
||||
void addClassFlags(in unsigned long flags);
|
||||
|
||||
const unsigned long Leader = 1 << 0;
|
||||
const unsigned long Follower = 1 << 1;
|
||||
const unsigned long Speculative = 1 << 2;
|
||||
const unsigned long Background = 1 << 3;
|
||||
const unsigned long Unblocked = 1 << 4;
|
||||
};
|
|
@ -780,9 +780,10 @@ HttpConnInfo::SetHTTP2ProtocolVersion(uint8_t pv)
|
|||
{
|
||||
if (pv == SPDY_VERSION_31) {
|
||||
protocolVersion.AssignLiteral(MOZ_UTF16("spdy/3.1"));
|
||||
} else if (pv == NS_HTTP2_DRAFT_VERSION) {
|
||||
MOZ_ASSERT (pv == NS_HTTP2_DRAFT_VERSION);
|
||||
protocolVersion.Assign(NS_LITERAL_STRING(NS_HTTP2_DRAFT_TOKEN));
|
||||
} else if (pv == HTTP_VERSION_2_DRAFT_15) {
|
||||
protocolVersion.AssignLiteral(MOZ_UTF16("h2-14/15"));
|
||||
} else if (pv == HTTP_VERSION_2_DRAFT_LATEST) {
|
||||
protocolVersion.Assign(NS_LITERAL_STRING(HTTP2_DRAFT_LATEST_TOKEN));
|
||||
} else {
|
||||
MOZ_ASSERT (pv == HTTP_VERSION_2);
|
||||
protocolVersion.Assign(MOZ_UTF16("h2"));
|
||||
|
|
|
@ -699,6 +699,7 @@ nsSocketTransportService::Run()
|
|||
if (IsNuwaProcess()) {
|
||||
NuwaMarkCurrentThread(nullptr, nullptr);
|
||||
}
|
||||
NS_SetIgnoreStatusOfCurrentThread();
|
||||
#endif
|
||||
|
||||
SOCKET_LOG(("STS thread init\n"));
|
||||
|
|
|
@ -41,6 +41,7 @@ struct HttpChannelOpenArgs
|
|||
OptionalInputStreamParams uploadStream;
|
||||
bool uploadStreamHasHeaders;
|
||||
uint16_t priority;
|
||||
uint32_t classOfService;
|
||||
uint8_t redirectionLimit;
|
||||
bool allowPipelining;
|
||||
bool allowSTS;
|
||||
|
|
|
@ -42,7 +42,8 @@ ASpdySession::NewSpdySession(uint32_t version,
|
|||
// requests as a precondition
|
||||
MOZ_ASSERT(version == SPDY_VERSION_31 ||
|
||||
version == HTTP_VERSION_2 ||
|
||||
version == NS_HTTP2_DRAFT_VERSION,
|
||||
version == HTTP_VERSION_2_DRAFT_LATEST ||
|
||||
version == HTTP_VERSION_2_DRAFT_15,
|
||||
"Unsupported spdy version");
|
||||
|
||||
// Don't do a runtime check of IsSpdyV?Enabled() here because pref value
|
||||
|
@ -54,8 +55,9 @@ ASpdySession::NewSpdySession(uint32_t version,
|
|||
|
||||
if (version == SPDY_VERSION_31) {
|
||||
return new SpdySession31(aTransport);
|
||||
} else if (version == NS_HTTP2_DRAFT_VERSION || version == HTTP_VERSION_2) {
|
||||
return new Http2Session(aTransport);
|
||||
} else if (version == HTTP_VERSION_2_DRAFT_LATEST || version == HTTP_VERSION_2 ||
|
||||
version == HTTP_VERSION_2_DRAFT_15) {
|
||||
return new Http2Session(aTransport, version);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
@ -77,16 +79,16 @@ SpdyInformation::SpdyInformation()
|
|||
VersionString[1] = NS_LITERAL_CSTRING("h2");
|
||||
ALPNCallbacks[1] = Http2Session::ALPNCallback;
|
||||
|
||||
Version[2] = NS_HTTP2_DRAFT_VERSION;
|
||||
Version[2] = HTTP_VERSION_2_DRAFT_15; // 14 and 15 are aliased
|
||||
VersionString[2] = NS_LITERAL_CSTRING("h2-14");
|
||||
ALPNCallbacks[2] = Http2Session::ALPNCallback;
|
||||
|
||||
Version[3] = NS_HTTP2_DRAFT_VERSION;
|
||||
Version[3] = HTTP_VERSION_2_DRAFT_15; // 14 and 15 are aliased
|
||||
VersionString[3] = NS_LITERAL_CSTRING("h2-15");
|
||||
ALPNCallbacks[3] = Http2Session::ALPNCallback;
|
||||
|
||||
Version[4] = NS_HTTP2_DRAFT_VERSION;
|
||||
VersionString[4] = NS_LITERAL_CSTRING(NS_HTTP2_DRAFT_TOKEN);
|
||||
Version[4] = HTTP_VERSION_2_DRAFT_LATEST;
|
||||
VersionString[4] = NS_LITERAL_CSTRING(HTTP2_DRAFT_LATEST_TOKEN);
|
||||
ALPNCallbacks[4] = Http2Session::ALPNCallback;
|
||||
}
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ do { \
|
|||
return NS_ERROR_ILLEGAL_VALUE; \
|
||||
} while (0)
|
||||
|
||||
Http2Session::Http2Session(nsISocketTransport *aSocketTransport)
|
||||
Http2Session::Http2Session(nsISocketTransport *aSocketTransport, uint32_t version)
|
||||
: mSocketTransport(aSocketTransport)
|
||||
, mSegmentReader(nullptr)
|
||||
, mSegmentWriter(nullptr)
|
||||
|
@ -103,6 +103,8 @@ Http2Session::Http2Session(nsISocketTransport *aSocketTransport)
|
|||
, mPreviousUsed(false)
|
||||
, mWaitingForSettingsAck(false)
|
||||
, mGoAwayOnPush(false)
|
||||
, mUseH2Deps(false)
|
||||
, mVersion(version)
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
|
||||
|
@ -125,7 +127,7 @@ Http2Session::Http2Session(nsISocketTransport *aSocketTransport)
|
|||
|
||||
mPingThreshold = gHttpHandler->SpdyPingThreshold();
|
||||
|
||||
mNegotiatedToken.AssignLiteral(NS_HTTP2_DRAFT_TOKEN);
|
||||
mNegotiatedToken.AssignLiteral(HTTP2_DRAFT_LATEST_TOKEN);
|
||||
}
|
||||
|
||||
// Copy the 32 bit number into the destination, using network byte order
|
||||
|
@ -789,20 +791,26 @@ Http2Session::GenerateGoAway(uint32_t aStatusCode)
|
|||
FlushOutputQueue();
|
||||
}
|
||||
|
||||
// The Hello is comprised of 24 octets of magic, which are designed to
|
||||
// flush out silent but broken intermediaries, followed by a settings
|
||||
// frame which sets a small flow control window for pushes and a
|
||||
// window update frame which creates a large session flow control window
|
||||
// The Hello is comprised of
|
||||
// 1] 24 octets of magic, which are designed to
|
||||
// flush out silent but broken intermediaries
|
||||
// 2] a settings frame which sets a small flow control window for pushes
|
||||
// 3] a window update frame which creates a large session flow control window
|
||||
// 4] 5 priority frames for streams which will never be opened with headers
|
||||
// these streams (3, 5, 7, 9, b) build a dependency tree that all other
|
||||
// streams will be direct leaves of.
|
||||
void
|
||||
Http2Session::SendHello()
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
LOG3(("Http2Session::SendHello %p\n", this));
|
||||
|
||||
// sized for magic + 4 settings and a session window update to follow
|
||||
// 24 magic, 33 for settings (9 header + 4 settings @6), 13 for window update
|
||||
// sized for magic + 4 settings and a session window update and 5 priority frames
|
||||
// 24 magic, 33 for settings (9 header + 4 settings @6), 13 for window update,
|
||||
// 5 priority frames at 14 (9 + 5) each
|
||||
static const uint32_t maxSettings = 4;
|
||||
static const uint32_t maxDataLen = 24 + kFrameHeaderBytes + maxSettings * 6 + 13;
|
||||
static const uint32_t prioritySize = 5 * (kFrameHeaderBytes + 5);
|
||||
static const uint32_t maxDataLen = 24 + kFrameHeaderBytes + maxSettings * 6 + 13 + prioritySize;
|
||||
char *packet = EnsureOutputBuffer(maxDataLen);
|
||||
memcpy(packet, kMagicHello, 24);
|
||||
mOutputQueueUsed += 24;
|
||||
|
@ -855,25 +863,61 @@ Http2Session::SendHello()
|
|||
|
||||
// now bump the local session window from 64KB
|
||||
uint32_t sessionWindowBump = ASpdySession::kInitialRwin - kDefaultRwin;
|
||||
if (kDefaultRwin >= ASpdySession::kInitialRwin)
|
||||
goto sendHello_complete;
|
||||
if (kDefaultRwin < ASpdySession::kInitialRwin) {
|
||||
// send a window update for the session (Stream 0) for something large
|
||||
mLocalSessionWindow = ASpdySession::kInitialRwin;
|
||||
|
||||
// send a window update for the session (Stream 0) for something large
|
||||
mLocalSessionWindow = ASpdySession::kInitialRwin;
|
||||
packet = mOutputQueueBuffer.get() + mOutputQueueUsed;
|
||||
CreateFrameHeader(packet, 4, FRAME_TYPE_WINDOW_UPDATE, 0, 0);
|
||||
mOutputQueueUsed += kFrameHeaderBytes + 4;
|
||||
CopyAsNetwork32(packet + kFrameHeaderBytes, sessionWindowBump);
|
||||
|
||||
packet = mOutputQueueBuffer.get() + mOutputQueueUsed;
|
||||
CreateFrameHeader(packet, 4, FRAME_TYPE_WINDOW_UPDATE, 0, 0);
|
||||
mOutputQueueUsed += kFrameHeaderBytes + 4;
|
||||
CopyAsNetwork32(packet + kFrameHeaderBytes, sessionWindowBump);
|
||||
LOG3(("Session Window increase at start of session %p %u\n",
|
||||
this, sessionWindowBump));
|
||||
LogIO(this, nullptr, "Session Window Bump ", packet, kFrameHeaderBytes + 4);
|
||||
}
|
||||
|
||||
LOG3(("Session Window increase at start of session %p %u\n",
|
||||
this, sessionWindowBump));
|
||||
LogIO(this, nullptr, "Session Window Bump ", packet, kFrameHeaderBytes + 4);
|
||||
// draft-14 and draft-15 are the only versions we support that do not
|
||||
// allow our priority scheme. Blacklist them here - they are aliased
|
||||
// as draft-15
|
||||
if ((mVersion != HTTP_VERSION_2_DRAFT_15) &&
|
||||
gHttpHandler->UseH2Deps() && gHttpHandler->CriticalRequestPrioritization()) {
|
||||
mUseH2Deps = true;
|
||||
MOZ_ASSERT(mNextStreamID == kLeaderGroupID);
|
||||
CreatePriorityNode(kLeaderGroupID, 0, 200, "leader");
|
||||
mNextStreamID += 2;
|
||||
MOZ_ASSERT(mNextStreamID == kOtherGroupID);
|
||||
CreatePriorityNode(kOtherGroupID, 0, 100, "other");
|
||||
mNextStreamID += 2;
|
||||
MOZ_ASSERT(mNextStreamID == kBackgroundGroupID);
|
||||
CreatePriorityNode(kBackgroundGroupID, 0, 0, "background");
|
||||
mNextStreamID += 2;
|
||||
MOZ_ASSERT(mNextStreamID == kSpeculativeGroupID);
|
||||
CreatePriorityNode(kSpeculativeGroupID, kBackgroundGroupID, 0, "speculative");
|
||||
mNextStreamID += 2;
|
||||
MOZ_ASSERT(mNextStreamID == kFollowerGroupID);
|
||||
CreatePriorityNode(kFollowerGroupID, kLeaderGroupID, 0, "follower");
|
||||
mNextStreamID += 2;
|
||||
}
|
||||
|
||||
sendHello_complete:
|
||||
FlushOutputQueue();
|
||||
}
|
||||
|
||||
void
|
||||
Http2Session::CreatePriorityNode(uint32_t streamID, uint32_t dependsOn, uint8_t weight,
|
||||
const char *label)
|
||||
{
|
||||
char *packet = mOutputQueueBuffer.get() + mOutputQueueUsed;
|
||||
CreateFrameHeader(packet, 5, FRAME_TYPE_PRIORITY, 0, streamID);
|
||||
mOutputQueueUsed += kFrameHeaderBytes + 5;
|
||||
CopyAsNetwork32(packet + kFrameHeaderBytes, dependsOn); // depends on
|
||||
packet[kFrameHeaderBytes + 4] = weight; // weight
|
||||
|
||||
LOG3(("Http2Session %p generate Priority Frame 0x%X depends on 0x%X "
|
||||
"weight %d for %s class\n", this, streamID, dependsOn, weight, label));
|
||||
LogIO(this, nullptr, "Priority dep node", packet, kFrameHeaderBytes + 5);
|
||||
}
|
||||
|
||||
// perform a bunch of integrity checks on the stream.
|
||||
// returns true if passed, false (plus LOG and ABORT) if failed.
|
||||
bool
|
||||
|
@ -3322,7 +3366,7 @@ Http2Session::ConfirmTLSProfile()
|
|||
// Fallback to showing the draft version, just in case
|
||||
LOG3(("Http2Session::ConfirmTLSProfile %p could not get negotiated token. "
|
||||
"Falling back to draft token.", this));
|
||||
mNegotiatedToken.AssignLiteral(NS_HTTP2_DRAFT_TOKEN);
|
||||
mNegotiatedToken.AssignLiteral(HTTP2_DRAFT_LATEST_TOKEN);
|
||||
}
|
||||
|
||||
mTLSProfileConfirmed = true;
|
||||
|
|
|
@ -41,7 +41,7 @@ public:
|
|||
NS_DECL_NSAHTTPSEGMENTREADER
|
||||
NS_DECL_NSAHTTPSEGMENTWRITER
|
||||
|
||||
explicit Http2Session(nsISocketTransport *);
|
||||
Http2Session(nsISocketTransport *, uint32_t version);
|
||||
|
||||
bool AddStream(nsAHttpTransaction *, int32_t,
|
||||
bool, nsIInterfaceRequestor *);
|
||||
|
@ -161,6 +161,14 @@ public:
|
|||
const static uint8_t kFrameHeaderBytes = kFrameLengthBytes + kFrameFlagBytes +
|
||||
kFrameTypeBytes + kFrameStreamIDBytes;
|
||||
|
||||
enum {
|
||||
kLeaderGroupID = 0x3,
|
||||
kOtherGroupID = 0x5,
|
||||
kBackgroundGroupID = 0x7,
|
||||
kSpeculativeGroupID = 0x9,
|
||||
kFollowerGroupID = 0xB
|
||||
};
|
||||
|
||||
static nsresult RecvHeaders(Http2Session *);
|
||||
static nsresult RecvPriority(Http2Session *);
|
||||
static nsresult RecvRstStream(Http2Session *);
|
||||
|
@ -218,6 +226,8 @@ public:
|
|||
|
||||
void SendPing() MOZ_OVERRIDE;
|
||||
|
||||
bool UseH2Deps() { return mUseH2Deps; }
|
||||
|
||||
private:
|
||||
|
||||
// These internal states do not correspond to the states of the HTTP/2 specification
|
||||
|
@ -260,6 +270,7 @@ private:
|
|||
void ActivateStream(Http2Stream *);
|
||||
void ProcessPending();
|
||||
nsresult SetInputFrameDataStream(uint32_t);
|
||||
void CreatePriorityNode(uint32_t, uint32_t, uint8_t, const char *);
|
||||
bool VerifyStream(Http2Stream *, uint32_t);
|
||||
void SetNeedsCleanup();
|
||||
|
||||
|
@ -469,6 +480,9 @@ private:
|
|||
// For caching whether we negotiated "h2" or "h2-<draft>"
|
||||
nsCString mNegotiatedToken;
|
||||
|
||||
bool mUseH2Deps;
|
||||
uint32_t mVersion; // HTTP2_VERSION_ from nsHttp.h remove when draft support removed
|
||||
|
||||
private:
|
||||
/// connect tunnels
|
||||
void DispatchOnTunnel(nsAHttpTransaction *, nsIInterfaceRequestor *);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "nsHttp.h"
|
||||
#include "nsHttpHandler.h"
|
||||
#include "nsHttpRequestHead.h"
|
||||
#include "nsIClassOfService.h"
|
||||
#include "nsISocketTransport.h"
|
||||
#include "nsStandardURL.h"
|
||||
#include "prnetdb.h"
|
||||
|
@ -504,8 +505,11 @@ Http2Stream::ParseHttpRequestHeaders(const char *buf,
|
|||
mTxInlineFrameUsed, mTxInlineFrameSize);
|
||||
|
||||
mTxInlineFrameUsed += messageSize;
|
||||
LOG3(("%p Generating %d bytes of HEADERS for stream 0x%X with priority weight %u frames %u\n",
|
||||
this, mTxInlineFrameUsed, mStreamID, mPriorityWeight, numFrames));
|
||||
UpdatePriorityDependency();
|
||||
LOG3(("Http2Stream %p Generating %d bytes of HEADERS for stream 0x%X with "
|
||||
"priority weight %u dep 0x%X frames %u uri=%s\n",
|
||||
this, mTxInlineFrameUsed, mStreamID, mPriorityWeight,
|
||||
mPriorityDependency, numFrames, nsCString(head->RequestURI()).get()));
|
||||
|
||||
uint32_t outputOffset = 0;
|
||||
uint32_t compressedDataOffset = 0;
|
||||
|
@ -534,9 +538,7 @@ Http2Stream::ParseHttpRequestHeaders(const char *buf,
|
|||
outputOffset += Http2Session::kFrameHeaderBytes;
|
||||
|
||||
if (!idx) {
|
||||
// Priority - Dependency is 0, weight is our gecko-calculated weight,
|
||||
// non-exclusive dependency
|
||||
memset(mTxInlineFrame.get() + outputOffset, 0, 4);
|
||||
memcpy(mTxInlineFrame.get() + outputOffset, &mPriorityDependency, 4);
|
||||
memcpy(mTxInlineFrame.get() + outputOffset + 4, &mPriorityWeight, 1);
|
||||
outputOffset += 5;
|
||||
}
|
||||
|
@ -1063,18 +1065,67 @@ Http2Stream::SetPriority(uint32_t newPriority)
|
|||
mPriority = static_cast<uint32_t>(httpPriority);
|
||||
mPriorityWeight = (nsISupportsPriority::PRIORITY_LOWEST + 1) -
|
||||
(httpPriority - kNormalPriority);
|
||||
|
||||
mPriorityDependency = 0; // maybe adjusted later
|
||||
}
|
||||
|
||||
void
|
||||
Http2Stream::SetPriorityDependency(uint32_t newDependency, uint8_t newWeight,
|
||||
bool exclusive)
|
||||
{
|
||||
// XXX - we ignore this for now... why is the server sending priority frames?!
|
||||
// undefined what it means when the server sends a priority frame. ignore it.
|
||||
LOG3(("Http2Stream::SetPriorityDependency %p 0x%X received dependency=0x%X "
|
||||
"weight=%u exclusive=%d", this, mStreamID, newDependency, newWeight,
|
||||
exclusive));
|
||||
}
|
||||
|
||||
void
|
||||
Http2Stream::UpdatePriorityDependency()
|
||||
{
|
||||
if (!mSession->UseH2Deps()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsHttpTransaction *trans = mTransaction->QueryHttpTransaction();
|
||||
if (!trans) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we create 5 fake dependency streams per session,
|
||||
// these streams are never opened with HEADERS. our first opened stream is 0xd
|
||||
// 3 depends 0, weight 200, leader class (kLeaderGroupID)
|
||||
// 5 depends 0, weight 100, other (kOtherGroupID)
|
||||
// 7 depends 0, weight 0, background (kBackgroundGroupID)
|
||||
// 9 depends 7, weight 0, speculative (kSpeculativeGroupID)
|
||||
// b depends 3, weight 0, follower class (kFollowerGroupID)
|
||||
//
|
||||
// streams for leaders (html, js, css) depend on 3
|
||||
// streams for folowers (images) depend on b
|
||||
// default streams (xhr, async js) depend on 5
|
||||
// explicit bg streams (beacon, etc..) depend on 7
|
||||
// spculative bg streams depend on 9
|
||||
|
||||
uint32_t classFlags = trans->ClassOfService();
|
||||
|
||||
if (classFlags & nsIClassOfService::Leader) {
|
||||
mPriorityDependency = Http2Session::kLeaderGroupID;
|
||||
} else if (classFlags & nsIClassOfService::Follower) {
|
||||
mPriorityDependency = Http2Session::kFollowerGroupID;
|
||||
} else if (classFlags & nsIClassOfService::Speculative) {
|
||||
mPriorityDependency = Http2Session::kSpeculativeGroupID;
|
||||
} else if (classFlags & nsIClassOfService::Background) {
|
||||
mPriorityDependency = Http2Session::kBackgroundGroupID;
|
||||
} else if (classFlags & nsIClassOfService::Unblocked) {
|
||||
mPriorityDependency = Http2Session::kOtherGroupID;
|
||||
} else {
|
||||
mPriorityDependency = Http2Session::kFollowerGroupID; // unmarked followers
|
||||
}
|
||||
|
||||
LOG3(("Http2Stream::UpdatePriorityDependency %p "
|
||||
"classFlags %X depends on stream 0x%X\n",
|
||||
this, classFlags, mPriorityDependency));
|
||||
}
|
||||
|
||||
void
|
||||
Http2Stream::SetRecvdFin(bool aStatus)
|
||||
{
|
||||
|
|
|
@ -126,6 +126,7 @@ public:
|
|||
uint32_t Priority() { return mPriority; }
|
||||
void SetPriority(uint32_t);
|
||||
void SetPriorityDependency(uint32_t, uint8_t, bool);
|
||||
void UpdatePriorityDependency();
|
||||
|
||||
// A pull stream has an implicit sink, a pushed stream has a sink
|
||||
// once it is matched to a pull stream.
|
||||
|
@ -264,8 +265,9 @@ private:
|
|||
// close by setting this to the max value.
|
||||
int64_t mRequestBodyLenRemaining;
|
||||
|
||||
uint32_t mPriority;
|
||||
uint8_t mPriorityWeight;
|
||||
uint32_t mPriority; // geckoish weight
|
||||
uint8_t mPriorityWeight; // h2 weight
|
||||
uint8_t mPriorityDependency; // h2 stream id 3 - 0xb
|
||||
|
||||
// mClientReceiveWindow, mServerReceiveWindow, and mLocalUnacked are for flow control.
|
||||
// *window are signed because the race conditions in asynchronous SETTINGS
|
||||
|
|
|
@ -47,6 +47,7 @@ HttpBaseChannel::HttpBaseChannel()
|
|||
, mStatus(NS_OK)
|
||||
, mLoadFlags(LOAD_NORMAL)
|
||||
, mCaps(0)
|
||||
, mClassOfService(0)
|
||||
, mPriority(PRIORITY_NORMAL)
|
||||
, mRedirectionLimit(gHttpHandler->RedirectionLimit())
|
||||
, mApplyConversion(true)
|
||||
|
@ -66,8 +67,6 @@ HttpBaseChannel::HttpBaseChannel()
|
|||
, mTracingEnabled(true)
|
||||
, mTimingEnabled(false)
|
||||
, mAllowSpdy(true)
|
||||
, mLoadAsBlocking(false)
|
||||
, mLoadUnblocked(false)
|
||||
, mResponseTimeoutEnabled(true)
|
||||
, mAllRedirectsSameOrigin(true)
|
||||
, mAllRedirectsPassTimingAllowCheck(true)
|
||||
|
@ -1713,36 +1712,6 @@ HttpBaseChannel::SetAllowSpdy(bool aAllowSpdy)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpBaseChannel::GetLoadAsBlocking(bool *aLoadAsBlocking)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aLoadAsBlocking);
|
||||
*aLoadAsBlocking = mLoadAsBlocking;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpBaseChannel::SetLoadAsBlocking(bool aLoadAsBlocking)
|
||||
{
|
||||
mLoadAsBlocking = aLoadAsBlocking;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpBaseChannel::GetLoadUnblocked(bool *aLoadUnblocked)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aLoadUnblocked);
|
||||
*aLoadUnblocked = mLoadUnblocked;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpBaseChannel::SetLoadUnblocked(bool aLoadUnblocked)
|
||||
{
|
||||
mLoadUnblocked = aLoadUnblocked;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpBaseChannel::GetApiRedirectToURI(nsIURI ** aResult)
|
||||
{
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "nsIEffectiveTLDService.h"
|
||||
#include "nsIStringEnumerator.h"
|
||||
#include "nsISupportsPriority.h"
|
||||
#include "nsIClassOfService.h"
|
||||
#include "nsIApplicationCache.h"
|
||||
#include "nsIResumableChannel.h"
|
||||
#include "nsITraceableChannel.h"
|
||||
|
@ -65,6 +66,7 @@ class HttpBaseChannel : public nsHashPropertyBag
|
|||
, public nsIUploadChannel
|
||||
, public nsIUploadChannel2
|
||||
, public nsISupportsPriority
|
||||
, public nsIClassOfService
|
||||
, public nsIResumableChannel
|
||||
, public nsITraceableChannel
|
||||
, public PrivateBrowsingChannel<HttpBaseChannel>
|
||||
|
@ -176,10 +178,6 @@ public:
|
|||
NS_IMETHOD GetRemotePort(int32_t* port);
|
||||
NS_IMETHOD GetAllowSpdy(bool *aAllowSpdy);
|
||||
NS_IMETHOD SetAllowSpdy(bool aAllowSpdy);
|
||||
NS_IMETHOD GetLoadAsBlocking(bool *aLoadAsBlocking);
|
||||
NS_IMETHOD SetLoadAsBlocking(bool aLoadAsBlocking);
|
||||
NS_IMETHOD GetLoadUnblocked(bool *aLoadUnblocked);
|
||||
NS_IMETHOD SetLoadUnblocked(bool aLoadUnblocked);
|
||||
NS_IMETHOD GetApiRedirectToURI(nsIURI * *aApiRedirectToURI);
|
||||
NS_IMETHOD AddSecurityMessage(const nsAString &aMessageTag, const nsAString &aMessageCategory);
|
||||
NS_IMETHOD TakeAllSecurityMessages(nsCOMArray<nsISecurityConsoleMessage> &aMessages);
|
||||
|
@ -202,6 +200,9 @@ public:
|
|||
NS_IMETHOD GetPriority(int32_t *value);
|
||||
NS_IMETHOD AdjustPriority(int32_t delta);
|
||||
|
||||
// nsIClassOfService
|
||||
NS_IMETHOD GetClassFlags(uint32_t *outFlags) { *outFlags = mClassOfService; return NS_OK; }
|
||||
|
||||
// nsIResumableChannel
|
||||
NS_IMETHOD GetEntityID(nsACString& aEntityID);
|
||||
|
||||
|
@ -334,6 +335,7 @@ protected:
|
|||
nsresult mStatus;
|
||||
uint32_t mLoadFlags;
|
||||
uint32_t mCaps;
|
||||
uint32_t mClassOfService;
|
||||
int16_t mPriority;
|
||||
uint8_t mRedirectionLimit;
|
||||
|
||||
|
@ -356,8 +358,6 @@ protected:
|
|||
// True if timing collection is enabled
|
||||
uint32_t mTimingEnabled : 1;
|
||||
uint32_t mAllowSpdy : 1;
|
||||
uint32_t mLoadAsBlocking : 1;
|
||||
uint32_t mLoadUnblocked : 1;
|
||||
uint32_t mResponseTimeoutEnabled : 1;
|
||||
// A flag that should be false only if a cross-domain redirect occurred
|
||||
uint32_t mAllRedirectsSameOrigin : 1;
|
||||
|
|
|
@ -127,6 +127,7 @@ NS_INTERFACE_MAP_BEGIN(HttpChannelChild)
|
|||
NS_INTERFACE_MAP_ENTRY(nsICacheInfoChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIResumableChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIClassOfService)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIProxiedChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsITraceableChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheContainer)
|
||||
|
@ -1541,6 +1542,7 @@ HttpChannelChild::ContinueAsyncOpen()
|
|||
|
||||
openArgs.uploadStreamHasHeaders() = mUploadStreamHasHeaders;
|
||||
openArgs.priority() = mPriority;
|
||||
openArgs.classOfService() = mClassOfService;
|
||||
openArgs.redirectionLimit() = mRedirectionLimit;
|
||||
openArgs.allowPipelining() = mAllowPipelining;
|
||||
openArgs.allowSTS() = mAllowSTS;
|
||||
|
@ -1725,6 +1727,43 @@ HttpChannelChild::SetPriority(int32_t aPriority)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// HttpChannelChild::nsIClassOfService
|
||||
//-----------------------------------------------------------------------------
|
||||
NS_IMETHODIMP
|
||||
HttpChannelChild::SetClassFlags(uint32_t inFlags)
|
||||
{
|
||||
if (mClassOfService == inFlags) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mClassOfService = inFlags;
|
||||
if (RemoteChannelExists()) {
|
||||
SendSetClassOfService(mClassOfService);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpChannelChild::AddClassFlags(uint32_t inFlags)
|
||||
{
|
||||
mClassOfService |= inFlags;
|
||||
if (RemoteChannelExists()) {
|
||||
SendSetClassOfService(mClassOfService);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpChannelChild::ClearClassFlags(uint32_t inFlags)
|
||||
{
|
||||
mClassOfService &= ~inFlags;
|
||||
if (RemoteChannelExists()) {
|
||||
SendSetClassOfService(mClassOfService);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// HttpChannelChild::nsIProxiedChannel
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -87,6 +87,10 @@ public:
|
|||
NS_IMETHOD GetRemotePort(int32_t* port);
|
||||
// nsISupportsPriority
|
||||
NS_IMETHOD SetPriority(int32_t value);
|
||||
// nsIClassOfService
|
||||
NS_IMETHOD SetClassFlags(uint32_t inFlags);
|
||||
NS_IMETHOD AddClassFlags(uint32_t inFlags);
|
||||
NS_IMETHOD ClearClassFlags(uint32_t inFlags);
|
||||
// nsIResumableChannel
|
||||
NS_IMETHOD ResumeAt(uint64_t startPos, const nsACString& entityID);
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ HttpChannelParent::Init(const HttpChannelCreationArgs& aArgs)
|
|||
a.referrerPolicy(), a.apiRedirectTo(), a.topWindowURI(),
|
||||
a.loadFlags(), a.requestHeaders(),
|
||||
a.requestMethod(), a.uploadStream(),
|
||||
a.uploadStreamHasHeaders(), a.priority(),
|
||||
a.uploadStreamHasHeaders(), a.priority(), a.classOfService(),
|
||||
a.redirectionLimit(), a.allowPipelining(), a.allowSTS(),
|
||||
a.thirdPartyFlags(), a.resumeAt(), a.startPos(),
|
||||
a.entityID(), a.chooseApplicationCache(),
|
||||
|
@ -181,6 +181,7 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI,
|
|||
const OptionalInputStreamParams& uploadStream,
|
||||
const bool& uploadStreamHasHeaders,
|
||||
const uint16_t& priority,
|
||||
const uint32_t& classOfService,
|
||||
const uint8_t& redirectionLimit,
|
||||
const bool& allowPipelining,
|
||||
const bool& allowSTS,
|
||||
|
@ -315,8 +316,12 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI,
|
|||
mChannel->SetUploadStreamHasHeaders(uploadStreamHasHeaders);
|
||||
}
|
||||
|
||||
if (priority != nsISupportsPriority::PRIORITY_NORMAL)
|
||||
if (priority != nsISupportsPriority::PRIORITY_NORMAL) {
|
||||
mChannel->SetPriority(priority);
|
||||
}
|
||||
if (classOfService) {
|
||||
mChannel->SetClassFlags(classOfService);
|
||||
}
|
||||
mChannel->SetRedirectionLimit(redirectionLimit);
|
||||
mChannel->SetAllowPipelining(allowPipelining);
|
||||
mChannel->SetAllowSTS(allowSTS);
|
||||
|
@ -426,6 +431,15 @@ HttpChannelParent::RecvSetPriority(const uint16_t& priority)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
HttpChannelParent::RecvSetClassOfService(const uint32_t& cos)
|
||||
{
|
||||
if (mChannel) {
|
||||
mChannel->SetClassFlags(cos);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
HttpChannelParent::RecvSuspend()
|
||||
{
|
||||
|
|
|
@ -99,6 +99,7 @@ protected:
|
|||
const OptionalInputStreamParams& uploadStream,
|
||||
const bool& uploadStreamHasHeaders,
|
||||
const uint16_t& priority,
|
||||
const uint32_t& classOfService,
|
||||
const uint8_t& redirectionLimit,
|
||||
const bool& allowPipelining,
|
||||
const bool& allowSTS,
|
||||
|
@ -116,6 +117,7 @@ protected:
|
|||
const uint32_t& aContentPolicyType);
|
||||
|
||||
virtual bool RecvSetPriority(const uint16_t& priority) MOZ_OVERRIDE;
|
||||
virtual bool RecvSetClassOfService(const uint32_t& cos) MOZ_OVERRIDE;
|
||||
virtual bool RecvSetCacheTokenCachedCharset(const nsCString& charset) MOZ_OVERRIDE;
|
||||
virtual bool RecvSuspend() MOZ_OVERRIDE;
|
||||
virtual bool RecvResume() MOZ_OVERRIDE;
|
||||
|
|
|
@ -33,6 +33,7 @@ parent:
|
|||
// see PNecko.ipdl
|
||||
|
||||
SetPriority(uint16_t priority);
|
||||
SetClassOfService(uint32_t cos);
|
||||
|
||||
SetCacheTokenCachedCharset(nsCString charset);
|
||||
|
||||
|
|
|
@ -39,15 +39,16 @@ namespace net {
|
|||
// 27 was http/2-draft09, h2-10, and h2-11
|
||||
// 28 was http/2-draft12
|
||||
// 29 was http/2-draft13
|
||||
// 30 was also h2-14 and -15. They're effectively the same, -15 added an
|
||||
// 30 was also h2-14. They're effectively the same, -15 added an
|
||||
// error code. So, we advertise all, but our "default position" is -16.
|
||||
HTTP2_VERSION_DRAFT16 = 30
|
||||
HTTP_VERSION_2_DRAFT_15 = 30,
|
||||
HTTP_VERSION_2_DRAFT_16 = 31
|
||||
};
|
||||
|
||||
typedef uint8_t nsHttpVersion;
|
||||
|
||||
#define NS_HTTP2_DRAFT_VERSION HTTP2_VERSION_DRAFT16
|
||||
#define NS_HTTP2_DRAFT_TOKEN "h2-16"
|
||||
#define HTTP_VERSION_2_DRAFT_LATEST HTTP_VERSION_2_DRAFT_16
|
||||
#define HTTP2_DRAFT_LATEST_TOKEN "h2-16"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// http connection capabilities
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "nsISSLSocketControl.h"
|
||||
#include "sslt.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIClassOfService.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
|
@ -835,6 +836,7 @@ nsHttpChannel::SetupTransaction()
|
|||
return rv;
|
||||
}
|
||||
|
||||
mTransaction->SetClassOfService(mClassOfService);
|
||||
SetupTransactionLoadGroupInfo();
|
||||
|
||||
rv = nsInputStreamPump::Create(getter_AddRefs(mTransactionPump),
|
||||
|
@ -2784,10 +2786,8 @@ nsHttpChannel::OpenCacheEntry(bool isHttps)
|
|||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Don't consider mLoadUnblocked here, since it's not indication of a demand
|
||||
// to load prioritly. It's mostly used to load XHR requests, but those should
|
||||
// not be considered as influencing the page load performance.
|
||||
if (mLoadAsBlocking || (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI))
|
||||
if ((mClassOfService & nsIClassOfService::Leader) ||
|
||||
(mLoadFlags & LOAD_INITIAL_DOCUMENT_URI))
|
||||
cacheEntryOpenFlags |= nsICacheStorage::OPEN_PRIORITY;
|
||||
|
||||
// Only for backward compatibility with the old cache back end.
|
||||
|
@ -4594,6 +4594,7 @@ NS_INTERFACE_MAP_BEGIN(nsHttpChannel)
|
|||
NS_INTERFACE_MAP_ENTRY(nsIHttpChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsICacheInfoChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsICachingChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIClassOfService)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIUploadChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIUploadChannel2)
|
||||
NS_INTERFACE_MAP_ENTRY(nsICacheEntryOpenCallback)
|
||||
|
@ -4912,10 +4913,12 @@ nsHttpChannel::BeginConnect()
|
|||
mCaps &= ~(NS_HTTP_ALLOW_KEEPALIVE | NS_HTTP_ALLOW_PIPELINING);
|
||||
|
||||
if (gHttpHandler->CriticalRequestPrioritization()) {
|
||||
if (mLoadAsBlocking)
|
||||
if (mClassOfService & nsIClassOfService::Leader) {
|
||||
mCaps |= NS_HTTP_LOAD_AS_BLOCKING;
|
||||
if (mLoadUnblocked)
|
||||
}
|
||||
if (mClassOfService & nsIClassOfService::Unblocked) {
|
||||
mCaps |= NS_HTTP_LOAD_UNBLOCKED;
|
||||
}
|
||||
}
|
||||
|
||||
// Force-Reload should reset the persistent connection pool for this host
|
||||
|
@ -4983,6 +4986,30 @@ nsHttpChannel::SetPriority(int32_t value)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// HttpChannel::nsIClassOfService
|
||||
//-----------------------------------------------------------------------------
|
||||
NS_IMETHODIMP
|
||||
nsHttpChannel::SetClassFlags(uint32_t inFlags)
|
||||
{
|
||||
mClassOfService = inFlags;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpChannel::AddClassFlags(uint32_t inFlags)
|
||||
{
|
||||
mClassOfService |= inFlags;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpChannel::ClearClassFlags(uint32_t inFlags)
|
||||
{
|
||||
mClassOfService &= ~inFlags;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpChannel::nsIProtocolProxyCallback
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -121,6 +121,11 @@ public:
|
|||
NS_IMETHOD SetupFallbackChannel(const char *aFallbackKey);
|
||||
// nsISupportsPriority
|
||||
NS_IMETHOD SetPriority(int32_t value);
|
||||
// nsIClassOfService
|
||||
NS_IMETHOD SetClassFlags(uint32_t inFlags);
|
||||
NS_IMETHOD AddClassFlags(uint32_t inFlags);
|
||||
NS_IMETHOD ClearClassFlags(uint32_t inFlags);
|
||||
|
||||
// nsIResumableChannel
|
||||
NS_IMETHOD ResumeAt(uint64_t startPos, const nsACString& entityID);
|
||||
|
||||
|
|
|
@ -1753,8 +1753,7 @@ nsHttpConnectionMgr::TryDispatchTransaction(nsConnectionEntry *ent,
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// Mark the transaction and its load group as blocking right now to prevent
|
||||
// other transactions from being reordered in the queue due to slow syns.
|
||||
trans->DispatchedAsBlocking();
|
||||
|
|
|
@ -182,6 +182,7 @@ nsHttpHandler::nsHttpHandler()
|
|||
, mSpdyV31(true)
|
||||
, mHttp2DraftEnabled(true)
|
||||
, mHttp2Enabled(true)
|
||||
, mUseH2Deps(true)
|
||||
, mEnforceHttp2TlsProfile(true)
|
||||
, mCoalesceSpdy(true)
|
||||
, mSpdyPersistentSettings(false)
|
||||
|
@ -1194,6 +1195,12 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
|
|||
mHttp2Enabled = cVar;
|
||||
}
|
||||
|
||||
if (PREF_CHANGED(HTTP_PREF("spdy.enabled.deps"))) {
|
||||
rv = prefs->GetBoolPref(HTTP_PREF("spdy.enabled.deps"), &cVar);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
mUseH2Deps = cVar;
|
||||
}
|
||||
|
||||
if (PREF_CHANGED(HTTP_PREF("spdy.enforce-tls-profile"))) {
|
||||
rv = prefs->GetBoolPref(HTTP_PREF("spdy.enforce-tls-profile"), &cVar);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
|
|
|
@ -113,6 +113,7 @@ public:
|
|||
uint32_t ConnectTimeout() { return mConnectTimeout; }
|
||||
uint32_t ParallelSpeculativeConnectLimit() { return mParallelSpeculativeConnectLimit; }
|
||||
bool CriticalRequestPrioritization() { return mCriticalRequestPrioritization; }
|
||||
bool UseH2Deps() { return mUseH2Deps; }
|
||||
|
||||
uint32_t MaxConnectionsPerOrigin() { return mMaxPersistentConnectionsPerServer; }
|
||||
bool UseRequestTokenBucket() { return mRequestTokenBucketEnabled; }
|
||||
|
@ -470,6 +471,7 @@ private:
|
|||
uint32_t mSpdyV31 : 1;
|
||||
uint32_t mHttp2DraftEnabled : 1;
|
||||
uint32_t mHttp2Enabled : 1;
|
||||
uint32_t mUseH2Deps : 1;
|
||||
uint32_t mEnforceHttp2TlsProfile : 1;
|
||||
uint32_t mCoalesceSpdy : 1;
|
||||
uint32_t mSpdyPersistentSettings : 1;
|
||||
|
|
|
@ -136,6 +136,7 @@ nsHttpTransaction::nsHttpTransaction()
|
|||
, mCountRecv(0)
|
||||
, mCountSent(0)
|
||||
, mAppId(NECKO_NO_APP_ID)
|
||||
, mClassOfService(0)
|
||||
{
|
||||
LOG(("Creating nsHttpTransaction @%p\n", this));
|
||||
gHttpHandler->GetMaxPipelineObjectSize(&mMaxPipelineObjectSize);
|
||||
|
@ -1749,7 +1750,7 @@ nsHttpTransaction::CancelPipeline(uint32_t reason)
|
|||
}
|
||||
|
||||
// Called when the transaction marked for blocking is associated with a connection
|
||||
// (i.e. added to a spdy session, an idle http connection, or placed into
|
||||
// (i.e. added to a new h1 conn, an idle http connection, or placed into
|
||||
// a http pipeline). It is safe to call this multiple times with it only
|
||||
// having an effect once.
|
||||
void
|
||||
|
|
|
@ -405,6 +405,11 @@ private:
|
|||
mCountSent += sentBytes;
|
||||
SaveNetworkStats(false);
|
||||
}
|
||||
public:
|
||||
void SetClassOfService(uint32_t cos) { mClassOfService = cos; }
|
||||
uint32_t ClassOfService() { return mClassOfService; }
|
||||
private:
|
||||
uint32_t mClassOfService;
|
||||
};
|
||||
|
||||
}} // namespace mozilla::net
|
||||
|
|
|
@ -38,7 +38,7 @@ interface nsIHttpUpgradeListener : nsISupports
|
|||
* using any feature exposed by this interface, be aware that this interface
|
||||
* will change and you will be broken. You have been warned.
|
||||
*/
|
||||
[scriptable, uuid(62a8d6e2-3418-4c6f-9d90-88573838f6dd)]
|
||||
[scriptable, uuid(bbf9d5bb-8daf-4909-88bc-f3b2f6a886d0)]
|
||||
interface nsIHttpChannelInternal : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -194,22 +194,6 @@ interface nsIHttpChannelInternal : nsISupports
|
|||
*/
|
||||
attribute boolean allowSpdy;
|
||||
|
||||
/**
|
||||
* Set (e.g., by the docshell) to indicate whether or not the channel
|
||||
* corresponds to content that should be given a degree of network exclusivity
|
||||
* with respect to other members of its load group.
|
||||
* Examples are js from the HTML head and css which are latency
|
||||
* sensitive and should not compete with images for bandwidth. Default false.
|
||||
*/
|
||||
attribute boolean loadAsBlocking;
|
||||
|
||||
/**
|
||||
* If set, this channel will load in parallel with the rest of the load
|
||||
* group even if a blocking subset of the group would normally be given
|
||||
* exclusivity. Default false.
|
||||
*/
|
||||
attribute boolean loadUnblocked;
|
||||
|
||||
/**
|
||||
* This attribute en/disables the timeout for the first byte of an HTTP
|
||||
* response. Enabled by default.
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "nsIPrefBranch.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsICancelable.h"
|
||||
#include "nsIClassOfService.h"
|
||||
#include "nsIDNSRecord.h"
|
||||
#include "nsIDNSService.h"
|
||||
#include "nsIStreamConverterService.h"
|
||||
|
@ -2293,8 +2294,10 @@ WebSocketChannel::SetupRequest()
|
|||
// we never let websockets be blocked by head CSS/JS loads to avoid
|
||||
// potential deadlock where server generation of CSS/JS requires
|
||||
// an XHR signal.
|
||||
rv = mChannel->SetLoadUnblocked(true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(mChannel));
|
||||
if (cos) {
|
||||
cos->AddClassFlags(nsIClassOfService::Unblocked);
|
||||
}
|
||||
|
||||
// draft-ietf-hybi-thewebsocketprotocol-07 illustrates Upgrade: websocket
|
||||
// in lower case, so go with that. It is technically case insensitive.
|
||||
|
|
|
@ -203,6 +203,14 @@ function test_http2_basic() {
|
|||
chan.asyncOpen(listener, null);
|
||||
}
|
||||
|
||||
function test_http2_basic_unblocked_dep() {
|
||||
var chan = makeChan("https://localhost:6944/basic_unblocked_dep");
|
||||
var cos = chan.QueryInterface(Ci.nsIClassOfService);
|
||||
cos.addClassFlags(Ci.nsIClassOfService.Unblocked);
|
||||
var listener = new Http2CheckListener();
|
||||
chan.asyncOpen(listener, null);
|
||||
}
|
||||
|
||||
// make sure we don't use h2 when disallowed
|
||||
function test_http2_nospdy() {
|
||||
var chan = makeChan("https://localhost:6944/");
|
||||
|
@ -521,6 +529,7 @@ function test_complete() {
|
|||
// a stalled stream when a SETTINGS frame arrives
|
||||
var tests = [ test_http2_post_big
|
||||
, test_http2_basic
|
||||
, test_http2_basic_unblocked_dep
|
||||
, test_http2_nospdy
|
||||
, test_http2_push1
|
||||
, test_http2_push2
|
||||
|
|
|
@ -1021,6 +1021,7 @@ public final class AttributeName
|
|||
public static final AttributeName ONDRAGEND = new AttributeName(ALL_NO_NS, SAME_LOCAL("ondragend"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
|
||||
public static final AttributeName ONMOVEEND = new AttributeName(ALL_NO_NS, SAME_LOCAL("onmoveend"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
|
||||
public static final AttributeName ONINVALID = new AttributeName(ALL_NO_NS, SAME_LOCAL("oninvalid"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
|
||||
public static final AttributeName INTEGRITY = new AttributeName(ALL_NO_NS, SAME_LOCAL("integrity"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
|
||||
public static final AttributeName ONKEYDOWN = new AttributeName(ALL_NO_NS, SAME_LOCAL("onkeydown"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
|
||||
public static final AttributeName ONFOCUSIN = new AttributeName(ALL_NO_NS, SAME_LOCAL("onfocusin"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
|
||||
public static final AttributeName ONMOUSEUP = new AttributeName(ALL_NO_NS, SAME_LOCAL("onmouseup"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
|
||||
|
@ -1602,6 +1603,7 @@ public final class AttributeName
|
|||
ONDRAGEND,
|
||||
ONMOVEEND,
|
||||
ONINVALID,
|
||||
INTEGRITY,
|
||||
ONKEYDOWN,
|
||||
ONFOCUSIN,
|
||||
ONMOUSEUP,
|
||||
|
@ -2184,6 +2186,7 @@ public final class AttributeName
|
|||
313706996,
|
||||
313707317,
|
||||
313710350,
|
||||
313795700,
|
||||
314027746,
|
||||
314038181,
|
||||
314091299,
|
||||
|
|
|
@ -381,6 +381,7 @@ HTML5_ATOM(intercept, "intercept")
|
|||
HTML5_ATOM(ondragend, "ondragend")
|
||||
HTML5_ATOM(onmoveend, "onmoveend")
|
||||
HTML5_ATOM(oninvalid, "oninvalid")
|
||||
HTML5_ATOM(integrity, "integrity")
|
||||
HTML5_ATOM(onkeydown, "onkeydown")
|
||||
HTML5_ATOM(onfocusin, "onfocusin")
|
||||
HTML5_ATOM(onmouseup, "onmouseup")
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -396,6 +396,7 @@ class nsHtml5AttributeName
|
|||
static nsHtml5AttributeName* ATTR_ONDRAGEND;
|
||||
static nsHtml5AttributeName* ATTR_ONMOVEEND;
|
||||
static nsHtml5AttributeName* ATTR_ONINVALID;
|
||||
static nsHtml5AttributeName* ATTR_INTEGRITY;
|
||||
static nsHtml5AttributeName* ATTR_ONKEYDOWN;
|
||||
static nsHtml5AttributeName* ATTR_ONFOCUSIN;
|
||||
static nsHtml5AttributeName* ATTR_ONMOUSEUP;
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче