зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to fx-team, a=merge
This commit is contained in:
Коммит
f9926c89e5
|
@ -63,6 +63,18 @@ function ConsoleMessage(aMsg, aLevel) {
|
|||
}
|
||||
}
|
||||
|
||||
function toggleUnrestrictedDevtools(unrestricted) {
|
||||
Services.prefs.setBoolPref("devtools.debugger.forbid-certified-apps",
|
||||
!unrestricted);
|
||||
Services.prefs.setBoolPref("dom.apps.developer_mode", unrestricted);
|
||||
// TODO: Remove once bug 1125916 is fixed.
|
||||
Services.prefs.setBoolPref("network.disable.ipc.security", unrestricted);
|
||||
Services.prefs.setBoolPref("dom.webcomponents.enabled", unrestricted);
|
||||
let lock = settings.createLock();
|
||||
lock.set("developer.menu.enabled", unrestricted, null);
|
||||
lock.set("devtools.unrestricted", unrestricted, null);
|
||||
}
|
||||
|
||||
ConsoleMessage.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIConsoleMessage]),
|
||||
toString: function() { return this.msg; }
|
||||
|
@ -99,17 +111,17 @@ ProcessGlobal.prototype = {
|
|||
lines.forEach((line) => {
|
||||
log(line);
|
||||
let params = line.split(" ");
|
||||
if (params[0] == "wipe") {
|
||||
this.wipeDir(params[1]);
|
||||
} else if (params[0] == "root") {
|
||||
log("unrestrict devtools");
|
||||
Services.prefs.setBoolPref("devtools.debugger.forbid-certified-apps", false);
|
||||
Services.prefs.setBoolPref("dom.apps.developer_mode", true);
|
||||
// TODO: Remove once bug 1125916 is fixed.
|
||||
Services.prefs.setBoolPref("network.disable.ipc.security", true);
|
||||
Services.prefs.setBoolPref("dom.webcomponents.enabled", true);
|
||||
let lock = settings.createLock();
|
||||
lock.set("developer.menu.enabled", true, null);
|
||||
switch (params[0]) {
|
||||
case "root":
|
||||
log("unrestrict devtools");
|
||||
toggleUnrestrictedDevtools(true);
|
||||
break;
|
||||
case "wipe":
|
||||
this.wipeDir(params[1]);
|
||||
case "normal":
|
||||
log("restrict devtools");
|
||||
toggleUnrestrictedDevtools(false);
|
||||
break;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6d477a7884273886605049b20f60af5c1583a150"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -23,7 +23,7 @@
|
|||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<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="4a697ec692aa762eb8cdb7812f5a051c5870020f"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="15a220c3e411f9606e4059e4c9fd0c57a4290c13"/>
|
||||
<!-- 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"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6d477a7884273886605049b20f60af5c1583a150"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -23,7 +23,7 @@
|
|||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<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="4a697ec692aa762eb8cdb7812f5a051c5870020f"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="15a220c3e411f9606e4059e4c9fd0c57a4290c13"/>
|
||||
<!-- 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,11 +19,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="6d477a7884273886605049b20f60af5c1583a150"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="22664edc4c73e5fe8f5095ff1d5549db78a2bc10"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="218a5637399d023f4326e12c8a486dad95403b6c"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="aac9cc4bb94cf720baf8f7ee419b4d76ac86b1ac"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="10b3daf0093db94c64e78a72ac43a93b68976087"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
|
||||
<!-- Stock Android things -->
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6d477a7884273886605049b20f60af5c1583a150"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="4a697ec692aa762eb8cdb7812f5a051c5870020f"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="15a220c3e411f9606e4059e4c9fd0c57a4290c13"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
<!-- Stock Android things -->
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6d477a7884273886605049b20f60af5c1583a150"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -23,7 +23,7 @@
|
|||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<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="4a697ec692aa762eb8cdb7812f5a051c5870020f"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="15a220c3e411f9606e4059e4c9fd0c57a4290c13"/>
|
||||
<!-- 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"/>
|
||||
|
@ -129,10 +129,10 @@
|
|||
<!-- Emulator specific things -->
|
||||
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="72ffdf71c68a96309212eb13d63560d66db14c9e"/>
|
||||
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="f390788a00706c06e5248edfd8d27b365387e84a"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="d2f58dbee70cba71bd3fad8cdd0fee620d10cf92"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c4d9746e5f1a3a2e6cb53d59d5d721e9888cd2e1"/>
|
||||
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="f37bd545063039e30a92f2550ae78c0e6e4e2d08"/>
|
||||
<project name="platform_external_wpa_supplicant_8" path="external/wpa_supplicant_8" remote="b2g" revision="0c6a6547cd1fd302fa2b0f6e375654df36bf0ec4"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="42f61f665e7a9857da8cd14b455e15bae98e6b44"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="de4bfffbbc2aabe5b5eca485e459da75e49097e2"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="d82e00fb6380b4f6cea7a96213913ee9eb441239"/>
|
||||
<project name="platform/development" path="development" revision="5968ff4e13e0d696ad8d972281fc27ae5a12829b"/>
|
||||
<project name="android-sdk" path="sdk" remote="b2g" revision="0951179277915335251c5e11d242e4e1a8c2236f"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6d477a7884273886605049b20f60af5c1583a150"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -23,7 +23,7 @@
|
|||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<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="4a697ec692aa762eb8cdb7812f5a051c5870020f"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="15a220c3e411f9606e4059e4c9fd0c57a4290c13"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
|
||||
<project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>
|
||||
|
|
|
@ -19,11 +19,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="6d477a7884273886605049b20f60af5c1583a150"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="22664edc4c73e5fe8f5095ff1d5549db78a2bc10"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="218a5637399d023f4326e12c8a486dad95403b6c"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="aac9cc4bb94cf720baf8f7ee419b4d76ac86b1ac"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="10b3daf0093db94c64e78a72ac43a93b68976087"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
|
||||
<!-- Stock Android things -->
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6d477a7884273886605049b20f60af5c1583a150"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -23,7 +23,7 @@
|
|||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<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="4a697ec692aa762eb8cdb7812f5a051c5870020f"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="15a220c3e411f9606e4059e4c9fd0c57a4290c13"/>
|
||||
<!-- 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"/>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"git": {
|
||||
"git_revision": "6d477a7884273886605049b20f60af5c1583a150",
|
||||
"git_revision": "9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "c7beef2b034d2308a85e8c866395c78245bc554f",
|
||||
"revision": "d5e509fd9697316bcbc267413a30478dcd4dbca9",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6d477a7884273886605049b20f60af5c1583a150"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="4a697ec692aa762eb8cdb7812f5a051c5870020f"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="15a220c3e411f9606e4059e4c9fd0c57a4290c13"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
<!-- Stock Android things -->
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6d477a7884273886605049b20f60af5c1583a150"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -23,7 +23,7 @@
|
|||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<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="4a697ec692aa762eb8cdb7812f5a051c5870020f"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="15a220c3e411f9606e4059e4c9fd0c57a4290c13"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
|
||||
<project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>
|
||||
|
|
|
@ -76,14 +76,14 @@ BasePrincipal::GetOriginNoSuffix(nsACString& aOrigin)
|
|||
bool
|
||||
BasePrincipal::Subsumes(nsIPrincipal* aOther, DocumentDomainConsideration aConsideration)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(aOther, "The caller is performing a nonsensical security check!");
|
||||
MOZ_ASSERT(aOther);
|
||||
return SubsumesInternal(aOther, aConsideration);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BasePrincipal::Equals(nsIPrincipal *aOther, bool *aResult)
|
||||
{
|
||||
|
||||
NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG);
|
||||
*aResult = Subsumes(aOther, DontConsiderDocumentDomain) &&
|
||||
Cast(aOther)->Subsumes(this, DontConsiderDocumentDomain);
|
||||
return NS_OK;
|
||||
|
@ -92,6 +92,7 @@ BasePrincipal::Equals(nsIPrincipal *aOther, bool *aResult)
|
|||
NS_IMETHODIMP
|
||||
BasePrincipal::EqualsConsideringDomain(nsIPrincipal *aOther, bool *aResult)
|
||||
{
|
||||
NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG);
|
||||
*aResult = Subsumes(aOther, ConsiderDocumentDomain) &&
|
||||
Cast(aOther)->Subsumes(this, ConsiderDocumentDomain);
|
||||
return NS_OK;
|
||||
|
@ -100,6 +101,7 @@ BasePrincipal::EqualsConsideringDomain(nsIPrincipal *aOther, bool *aResult)
|
|||
NS_IMETHODIMP
|
||||
BasePrincipal::Subsumes(nsIPrincipal *aOther, bool *aResult)
|
||||
{
|
||||
NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG);
|
||||
*aResult = Subsumes(aOther, DontConsiderDocumentDomain);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -107,6 +109,7 @@ BasePrincipal::Subsumes(nsIPrincipal *aOther, bool *aResult)
|
|||
NS_IMETHODIMP
|
||||
BasePrincipal::SubsumesConsideringDomain(nsIPrincipal *aOther, bool *aResult)
|
||||
{
|
||||
NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG);
|
||||
*aResult = Subsumes(aOther, ConsiderDocumentDomain);
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -175,9 +175,6 @@ function runTest() {
|
|||
runApp(app, continueTest);
|
||||
yield undefined;
|
||||
|
||||
SpecialPowers.popPermissions(continueTest);
|
||||
yield undefined;
|
||||
|
||||
// Uninstall the app to cleanup after ourself.
|
||||
navigator.mozApps.mgmt.onuninstall = function(event) {
|
||||
var app = event.application;
|
||||
|
|
|
@ -36,6 +36,10 @@
|
|||
#include "nsIWebNavigation.h"
|
||||
#include "nsIXPConnect.h"
|
||||
|
||||
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||
#include "nsIProfiler.h"
|
||||
#endif
|
||||
|
||||
// The maximum allowed number of concurrent timers per page.
|
||||
#define MAX_PAGE_TIMERS 10000
|
||||
|
||||
|
@ -860,6 +864,23 @@ Console::TimeStamp(JSContext* aCx, const JS::Handle<JS::Value> aData)
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||
if (aData.isString() && NS_IsMainThread()) {
|
||||
if (!mProfiler) {
|
||||
mProfiler = do_GetService("@mozilla.org/tools/profiler;1");
|
||||
}
|
||||
if (mProfiler) {
|
||||
bool active = false;
|
||||
if (NS_SUCCEEDED(mProfiler->IsActive(&active)) && active) {
|
||||
nsAutoJSString stringValue;
|
||||
if (stringValue.init(aCx, aData)) {
|
||||
mProfiler->AddMarker(NS_ConvertUTF16toUTF8(stringValue).get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Method(aCx, MethodTimeStamp, NS_LITERAL_STRING("timeStamp"), data);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "nsPIDOMWindow.h"
|
||||
|
||||
class nsIConsoleAPIStorage;
|
||||
class nsIProfiler;
|
||||
class nsIXPConnectJSObjectHolder;
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -203,6 +204,9 @@ private:
|
|||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
nsCOMPtr<nsIConsoleAPIStorage> mStorage;
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> mSandbox;
|
||||
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||
nsCOMPtr<nsIProfiler> mProfiler;
|
||||
#endif
|
||||
|
||||
nsDataHashtable<nsStringHashKey, DOMHighResTimeStamp> mTimerRegistry;
|
||||
nsDataHashtable<nsStringHashKey, uint32_t> mCounterRegistry;
|
||||
|
|
|
@ -113,6 +113,7 @@ NS_CP_ContentTypeName(uint32_t contentType)
|
|||
CASE_RETURN( TYPE_BEACON );
|
||||
CASE_RETURN( TYPE_FETCH );
|
||||
CASE_RETURN( TYPE_IMAGESET );
|
||||
CASE_RETURN( TYPE_WEB_MANIFEST );
|
||||
default:
|
||||
return "<Unknown Type>";
|
||||
}
|
||||
|
|
|
@ -1660,7 +1660,7 @@ nsContentUtils::ParseLegacyFontSize(const nsAString& aValue)
|
|||
++iter;
|
||||
}
|
||||
|
||||
if (*iter < char16_t('0') || *iter > char16_t('9')) {
|
||||
if (iter == end || *iter < char16_t('0') || *iter > char16_t('9')) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -123,7 +123,8 @@ nsDataDocumentContentPolicy::ShouldLoad(uint32_t aContentType,
|
|||
aContentType == nsIContentPolicy::TYPE_SUBDOCUMENT ||
|
||||
aContentType == nsIContentPolicy::TYPE_SCRIPT ||
|
||||
aContentType == nsIContentPolicy::TYPE_XSLT ||
|
||||
aContentType == nsIContentPolicy::TYPE_FETCH) {
|
||||
aContentType == nsIContentPolicy::TYPE_FETCH ||
|
||||
aContentType == nsIContentPolicy::TYPE_WEB_MANIFEST) {
|
||||
*aDecision = nsIContentPolicy::REJECT_TYPE;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ interface nsIPrincipal;
|
|||
* by launching a dialog to prompt the user for something).
|
||||
*/
|
||||
|
||||
[scriptable,uuid(447a2300-ab3c-11e4-bcd8-0800200c9a66)]
|
||||
[scriptable,uuid(cb978019-0c5b-4067-abb6-c914461208c1)]
|
||||
interface nsIContentPolicy : nsIContentPolicyBase
|
||||
{
|
||||
/**
|
||||
|
|
|
@ -24,7 +24,7 @@ typedef unsigned long nsContentPolicyType;
|
|||
* by launching a dialog to prompt the user for something).
|
||||
*/
|
||||
|
||||
[scriptable,uuid(21bb54b0-ab3c-11e4-bcd8-0800200c9a66)]
|
||||
[scriptable,uuid(4f2655e8-6365-4583-8510-732bff2186c5)]
|
||||
interface nsIContentPolicyBase : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -172,6 +172,11 @@ interface nsIContentPolicyBase : nsISupports
|
|||
*/
|
||||
const nsContentPolicyType TYPE_IMAGESET = 21;
|
||||
|
||||
/**
|
||||
* Indicates a web manifest.
|
||||
*/
|
||||
const nsContentPolicyType TYPE_WEB_MANIFEST = 22;
|
||||
|
||||
/* When adding new content types, please update nsContentBlocker,
|
||||
* NS_CP_ContentTypeName, nsCSPContext, all nsIContentPolicy
|
||||
* implementations, and other things that are not listed here that are
|
||||
|
|
|
@ -28,7 +28,7 @@ interface nsIDOMElement;
|
|||
* by launching a dialog to prompt the user for something).
|
||||
*/
|
||||
|
||||
[scriptable,uuid(83d93c70-ab46-11e4-bcd8-0800200c9a66)]
|
||||
[scriptable,uuid(704b4b8e-2287-498a-9c0a-d1bde547a2d4)]
|
||||
interface nsISimpleContentPolicy : nsIContentPolicyBase
|
||||
{
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
[DEFAULT]
|
||||
skip-if = e10s # Bug 1170385 - csp-on-violate-policy message not sent in browser tests with e10s
|
||||
[browser_test_web_manifest.js]
|
||||
[browser_test_web_manifest_mixed_content.js]
|
|
@ -0,0 +1,265 @@
|
|||
/*
|
||||
* Description of the tests:
|
||||
* These tests check for conformance to the CSP spec as they relate to Web Manifests.
|
||||
*
|
||||
* In particular, the tests check that default-src and manifest-src directives are
|
||||
* are respected by the ManifestObtainer.
|
||||
*/
|
||||
/*globals Components*/
|
||||
'use strict';
|
||||
requestLongerTimeout(10); // e10s tests take time.
|
||||
const {
|
||||
ManifestObtainer
|
||||
} = Components.utils.import('resource://gre/modules/WebManifest.jsm', {});
|
||||
const path = '/tests/dom/base/test/csp/';
|
||||
const testFile = `file=${path}file_CSP_web_manifest.html`;
|
||||
const remoteFile = `file=${path}file_CSP_web_manifest_remote.html`;
|
||||
const httpsManifest = `file=${path}file_CSP_web_manifest_https.html`;
|
||||
const mixedContent = `file=${path}file_CSP_web_manifest_mixed_content.html`;
|
||||
const server = 'file_csp_testserver.sjs';
|
||||
const defaultURL = `http://example.org${path}${server}`;
|
||||
const remoteURL = `http://mochi.test:8888`;
|
||||
const secureURL = `https://example.com${path}${server}`;
|
||||
const tests = [
|
||||
// CSP block everything, so trying to load a manifest
|
||||
// will result in a policy violation.
|
||||
{
|
||||
expected: `default-src 'none' blocks fetching manifest.`,
|
||||
get tabURL() {
|
||||
let queryParts = [
|
||||
`csp=default-src 'none'`,
|
||||
testFile
|
||||
];
|
||||
return `${defaultURL}?${queryParts.join('&')}`;
|
||||
},
|
||||
run(topic) {
|
||||
is(topic, 'csp-on-violate-policy', this.expected);
|
||||
}
|
||||
},
|
||||
// CSP allows fetching only from mochi.test:8888,
|
||||
// so trying to load a manifest from same origin
|
||||
// triggers a CSP violation.
|
||||
{
|
||||
expected: `default-src mochi.test:8888 blocks manifest fetching.`,
|
||||
get tabURL() {
|
||||
let queryParts = [
|
||||
`csp=default-src mochi.test:8888`,
|
||||
testFile
|
||||
];
|
||||
return `${defaultURL}?${queryParts.join('&')}`;
|
||||
},
|
||||
run(topic) {
|
||||
is(topic, 'csp-on-violate-policy', this.expected);
|
||||
}
|
||||
},
|
||||
// CSP restricts fetching to 'self', so allowing the manifest
|
||||
// to load. The name of the manifest is then checked.
|
||||
{
|
||||
expected: `CSP default-src 'self' allows fetch of manifest.`,
|
||||
get tabURL() {
|
||||
let queryParts = [
|
||||
`csp=default-src 'self'`,
|
||||
testFile
|
||||
];
|
||||
return `${defaultURL}?${queryParts.join('&')}`;
|
||||
},
|
||||
run(manifest) {
|
||||
is(manifest.name, 'loaded', this.expected);
|
||||
}
|
||||
},
|
||||
// CSP only allows fetching from mochi.test:8888 and remoteFile
|
||||
// requests a manifest from that origin, so manifest should load.
|
||||
{
|
||||
expected: 'CSP default-src mochi.test:8888 allows fetching manifest.',
|
||||
get tabURL() {
|
||||
let queryParts = [
|
||||
`csp=default-src http://mochi.test:8888`,
|
||||
remoteFile
|
||||
];
|
||||
return `${defaultURL}?${queryParts.join('&')}`;
|
||||
},
|
||||
run(manifest) {
|
||||
is(manifest.name, 'loaded', this.expected);
|
||||
}
|
||||
},
|
||||
// default-src blocks everything, so any attempt to
|
||||
// fetch a manifest from another origin will trigger a
|
||||
// policy violation.
|
||||
{
|
||||
expected: `default-src 'none' blocks mochi.test:8888`,
|
||||
get tabURL() {
|
||||
let queryParts = [
|
||||
`csp=default-src 'none'`,
|
||||
remoteFile
|
||||
];
|
||||
return `${defaultURL}?${queryParts.join('&')}`;
|
||||
},
|
||||
run(topic) {
|
||||
is(topic, 'csp-on-violate-policy', this.expected);
|
||||
}
|
||||
},
|
||||
// CSP allows fetching from self, so manifest should load.
|
||||
{
|
||||
expected: `CSP manifest-src allows self`,
|
||||
get tabURL() {
|
||||
let queryParts = [
|
||||
`manifest-src 'self'`,
|
||||
testFile
|
||||
];
|
||||
return `${defaultURL}?${queryParts.join('&')}`;
|
||||
},
|
||||
run(manifest) {
|
||||
is(manifest.name, 'loaded', this.expected);
|
||||
}
|
||||
},
|
||||
// CSP allows fetching from example.org, so manifest should load.
|
||||
{
|
||||
expected: `CSP manifest-src allows http://example.org`,
|
||||
get tabURL() {
|
||||
let queryParts = [
|
||||
`manifest-src http://example.org`,
|
||||
testFile
|
||||
];
|
||||
return `${defaultURL}?${queryParts.join('&')}`;
|
||||
},
|
||||
run(manifest) {
|
||||
is(manifest.name, 'loaded', this.expected);
|
||||
}
|
||||
},
|
||||
// Check interaction with default-src and another origin,
|
||||
// CSP allows fetching from example.org, so manifest should load.
|
||||
{
|
||||
expected: `CSP manifest-src overrides default-src of elsewhere.com`,
|
||||
get tabURL() {
|
||||
let queryParts = [
|
||||
`default-src: http://elsewhere.com; manifest-src http://example.org`,
|
||||
testFile
|
||||
];
|
||||
return `${defaultURL}?${queryParts.join('&')}`;
|
||||
},
|
||||
run(manifest) {
|
||||
is(manifest.name, 'loaded', this.expected);
|
||||
}
|
||||
},
|
||||
// Check interaction with default-src none,
|
||||
// CSP allows fetching manifest from example.org, so manifest should load.
|
||||
{
|
||||
expected: `CSP manifest-src overrides default-src`,
|
||||
get tabURL() {
|
||||
let queryParts = [
|
||||
`default-src: 'none'; manifest-src 'self'`,
|
||||
testFile
|
||||
];
|
||||
return `${defaultURL}?${queryParts.join('&')}`;
|
||||
},
|
||||
run(manifest) {
|
||||
is(manifest.name, 'loaded', this.expected);
|
||||
}
|
||||
},
|
||||
// CSP allows fetching from mochi.test:8888, which has a
|
||||
// CORS header set to '*'. So the manifest should load.
|
||||
{
|
||||
expected: `CSP manifest-src allows mochi.test:8888`,
|
||||
get tabURL() {
|
||||
let queryParts = [
|
||||
`csp=default-src *; manifest-src http://mochi.test:8888`,
|
||||
remoteFile
|
||||
];
|
||||
return `${defaultURL}?${queryParts.join('&')}`;
|
||||
},
|
||||
run(manifest) {
|
||||
is(manifest.name, 'loaded', this.expected);
|
||||
}
|
||||
},
|
||||
// CSP restricts fetching to mochi.test:8888, but the test
|
||||
// file is at example.org. Hence, a policy violation is
|
||||
// triggered.
|
||||
{
|
||||
expected: `CSP blocks manifest fetching from example.org.`,
|
||||
get tabURL() {
|
||||
let queryParts = [
|
||||
`csp=manifest-src mochi.test:8888`,
|
||||
testFile
|
||||
];
|
||||
return `${defaultURL}?${queryParts.join('&')}`;
|
||||
},
|
||||
run(topic) {
|
||||
is(topic, 'csp-on-violate-policy', this.expected);
|
||||
}
|
||||
},
|
||||
// CSP is set to only allow manifest to be loaded from same origin,
|
||||
// but the remote file attempts to load from a different origin. Thus
|
||||
// this causes a CSP violation.
|
||||
{
|
||||
expected: `CSP manifest-src 'self' blocks cross-origin fetch.`,
|
||||
get tabURL() {
|
||||
let queryParts = [
|
||||
`csp=manifest-src 'self'`,
|
||||
remoteFile
|
||||
];
|
||||
return `${defaultURL}?${queryParts.join('&')}`;
|
||||
},
|
||||
run(topic) {
|
||||
is(topic, 'csp-on-violate-policy', this.expected);
|
||||
}
|
||||
}
|
||||
];
|
||||
//jscs:disable
|
||||
add_task(function* () {
|
||||
//jscs:enable
|
||||
for (let test of tests) {
|
||||
let tabOptions = {
|
||||
gBrowser: gBrowser,
|
||||
url: test.tabURL,
|
||||
};
|
||||
yield BrowserTestUtils.withNewTab(
|
||||
tabOptions,
|
||||
browser => testObtainingManifest(browser, test)
|
||||
);
|
||||
}
|
||||
|
||||
function* testObtainingManifest(aBrowser, aTest) {
|
||||
const observer = (/blocks/.test(aTest.expected)) ? new NetworkObserver(aTest) : null;
|
||||
const obtainer = new ManifestObtainer();
|
||||
let manifest;
|
||||
// Expect an exception (from promise rejection) if there a content policy
|
||||
// that is violated.
|
||||
try {
|
||||
manifest = yield obtainer.obtainManifest(aBrowser);
|
||||
} catch (e) {
|
||||
const msg = `Expected promise rejection obtaining.`;
|
||||
ok(/blocked the loading of a resource/.test(e.message), msg);
|
||||
if (observer) {
|
||||
yield observer.finished;
|
||||
}
|
||||
return;
|
||||
}
|
||||
// otherwise, we test manifest's content.
|
||||
if (manifest) {
|
||||
aTest.run(manifest);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Helper object used to observe policy violations. It waits 10 seconds
|
||||
// for a response, and then times out causing its associated test to fail.
|
||||
function NetworkObserver(test) {
|
||||
let finishedTest;
|
||||
let success = false;
|
||||
this.finished = new Promise((resolver) => {
|
||||
finishedTest = resolver;
|
||||
})
|
||||
this.observe = function observer(subject, topic) {
|
||||
SpecialPowers.removeObserver(this, 'csp-on-violate-policy');
|
||||
test.run(topic);
|
||||
finishedTest();
|
||||
success = true;
|
||||
};
|
||||
SpecialPowers.addObserver(this, 'csp-on-violate-policy', false);
|
||||
setTimeout(() => {
|
||||
if (!success) {
|
||||
test.run('This test timed out.');
|
||||
finishedTest();
|
||||
}
|
||||
}, 1000);
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Description of the test:
|
||||
* Check that mixed content blocker works prevents fetches of
|
||||
* mixed content manifests.
|
||||
*/
|
||||
'use strict';
|
||||
const {
|
||||
ManifestObtainer
|
||||
} = Components.utils.import('resource://gre/modules/WebManifest.jsm', {});
|
||||
const path = '/tests/dom/base/test/csp/';
|
||||
const mixedContent = `file=${path}file_CSP_web_manifest_mixed_content.html`;
|
||||
const server = 'file_csp_testserver.sjs';
|
||||
const secureURL = `https://example.com${path}${server}`;
|
||||
const tests = [
|
||||
// Trying to load mixed content in file_CSP_web_manifest_mixed_content.html
|
||||
// needs to result in an error.
|
||||
{
|
||||
expected: `Mixed Content Blocker prevents fetching manifest.`,
|
||||
get tabURL() {
|
||||
let queryParts = [
|
||||
mixedContent
|
||||
];
|
||||
return `${secureURL}?${queryParts.join('&')}`;
|
||||
},
|
||||
run(error) {
|
||||
// Check reason for error.
|
||||
const check = /blocked the loading of a resource/.test(error.message);
|
||||
ok(check, this.expected);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
//jscs:disable
|
||||
add_task(function*() {
|
||||
//jscs:enable
|
||||
for (let test of tests) {
|
||||
let tabOptions = {
|
||||
gBrowser: gBrowser,
|
||||
url: test.tabURL,
|
||||
};
|
||||
yield BrowserTestUtils.withNewTab(
|
||||
tabOptions,
|
||||
browser => testObtainingManifest(browser, test)
|
||||
);
|
||||
}
|
||||
|
||||
function* testObtainingManifest(aBrowser, aTest) {
|
||||
const obtainer = new ManifestObtainer();
|
||||
try {
|
||||
yield obtainer.obtainManifest(aBrowser);
|
||||
} catch (e) {
|
||||
aTest.run(e)
|
||||
}
|
||||
}
|
||||
});
|
|
@ -0,0 +1,6 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<head>
|
||||
<link rel="manifest" href="file_CSP_web_manifest.json">
|
||||
</head>
|
||||
<h1>Support Page for Web Manifest Tests</h1>
|
|
@ -0,0 +1 @@
|
|||
{"name": "loaded"}
|
|
@ -0,0 +1 @@
|
|||
Access-Control-Allow-Origin: http://example.org
|
|
@ -0,0 +1,4 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<link rel="manifest" href="https://example.com:443/tests/dom/base/test/csp/file_CSP_web_manifest_https.json">
|
||||
<h1>Support Page for Web Manifest Tests</h1>
|
|
@ -0,0 +1 @@
|
|||
{"name": "loaded"}
|
|
@ -0,0 +1,9 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<head>
|
||||
<link
|
||||
rel="manifest"
|
||||
href="http://example.org/tests/dom/base/test/csp/file_csp_testserver.sjs?file=/test/dom/base/test/csp/file_CSP_web_manifest.json&cors=*">
|
||||
</head>
|
||||
<h1>Support Page for Web Manifest Tests</h1>
|
||||
<p>Used to try to load a resource over an insecure connection to trigger mixed content blocking.</p>
|
|
@ -0,0 +1,8 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<link rel="manifest"
|
||||
crossorigin
|
||||
href="//mochi.test:8888/tests/dom/base/test/csp/file_csp_testserver.sjs?file=/tests/dom/base/test/csp/file_CSP_web_manifest.json&cors=*">
|
||||
|
||||
<h1>Support Page for Web Manifest Tests</h1>
|
||||
<p>Loads a manifest from mochi.test:8888 with CORS set to "*".</p>
|
|
@ -22,6 +22,7 @@ function loadHTMLFromFile(path) {
|
|||
return testHTML;
|
||||
}
|
||||
|
||||
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
var query = {};
|
||||
|
@ -30,16 +31,23 @@ function handleRequest(request, response)
|
|||
query[name] = unescape(value);
|
||||
});
|
||||
|
||||
var csp = unescape(query['csp']);
|
||||
var csp = (query['csp']) ? unescape(query['csp']) : "";
|
||||
var file = unescape(query['file']);
|
||||
var cors = unescape(query['cors']);
|
||||
|
||||
// avoid confusing cache behaviors
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
|
||||
// Deliver the CSP policy encoded in the URI
|
||||
response.setHeader("Content-Security-Policy", csp, false);
|
||||
|
||||
if(csp){
|
||||
response.setHeader("Content-Security-Policy", csp, false);
|
||||
}
|
||||
// Deliver the CORS header in the URI
|
||||
if(cors){
|
||||
response.setHeader("Access-Control-Allow-Origin", cors, false);
|
||||
}
|
||||
// Send HTML to test allowed/blocked behaviors
|
||||
response.setHeader("Content-Type", "text/html", false);
|
||||
|
||||
response.write(loadHTMLFromFile(file));
|
||||
}
|
||||
|
|
|
@ -43,6 +43,13 @@ support-files =
|
|||
file_CSP_main.html
|
||||
file_CSP_main.html^headers^
|
||||
file_CSP_main.js
|
||||
file_CSP_web_manifest.html
|
||||
file_CSP_web_manifest_remote.html
|
||||
file_CSP_web_manifest_https.html
|
||||
file_CSP_web_manifest.json
|
||||
file_CSP_web_manifest.json^headers^
|
||||
file_CSP_web_manifest_https.json
|
||||
file_CSP_web_manifest_mixed_content.html
|
||||
file_bug836922_npolicies.html
|
||||
file_bug836922_npolicies.html^headers^
|
||||
file_bug836922_npolicies_ro_violation.sjs
|
||||
|
|
|
@ -37,4 +37,7 @@ MOCHITEST_CHROME_MANIFESTS += [
|
|||
'csp/chrome.ini',
|
||||
]
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ['browser.ini']
|
||||
BROWSER_CHROME_MANIFESTS += [
|
||||
'browser.ini',
|
||||
'csp/browser.ini',
|
||||
]
|
||||
|
|
|
@ -812,7 +812,7 @@ MaybeWrapStringValue(JSContext* cx, JS::MutableHandle<JS::Value> rval)
|
|||
{
|
||||
MOZ_ASSERT(rval.isString());
|
||||
JSString* str = rval.toString();
|
||||
if (JS::GetTenuredGCThingZone(str) != js::GetContextZone(cx)) {
|
||||
if (JS::GetStringZone(str) != js::GetContextZone(cx)) {
|
||||
return JS_WrapValue(cx, rval);
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -13301,6 +13301,9 @@ class CGBindingImplClass(CGClass):
|
|||
|
||||
wrapArgs = [Argument('JSContext*', 'aCx'),
|
||||
Argument('JS::Handle<JSObject*>', 'aGivenProto')]
|
||||
if not descriptor.wrapperCache:
|
||||
wrapArgs.append(Argument('JS::MutableHandle<JSObject*>',
|
||||
'aReflector'))
|
||||
self.methodDecls.insert(0,
|
||||
ClassMethod(wrapMethodName, "JSObject*",
|
||||
wrapArgs, virtual=descriptor.wrapperCache,
|
||||
|
@ -13418,18 +13421,26 @@ class CGExampleClass(CGBindingImplClass):
|
|||
|
||||
""")
|
||||
|
||||
if self.descriptor.wrapperCache:
|
||||
reflectorArg = ""
|
||||
reflectorPassArg = ""
|
||||
else:
|
||||
reflectorArg = ", JS::MutableHandle<JSObject*> aReflector"
|
||||
reflectorPassArg = ", aReflector"
|
||||
classImpl = ccImpl + ctordtor + "\n" + dedent("""
|
||||
JSObject*
|
||||
${nativeType}::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
${nativeType}::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto${reflectorArg})
|
||||
{
|
||||
return ${ifaceName}Binding::Wrap(aCx, this, aGivenProto);
|
||||
return ${ifaceName}Binding::Wrap(aCx, this, aGivenProto${reflectorPassArg});
|
||||
}
|
||||
|
||||
""")
|
||||
return string.Template(classImpl).substitute(
|
||||
ifaceName=self.descriptor.name,
|
||||
nativeType=self.nativeLeafName(self.descriptor),
|
||||
parentType=self.nativeLeafName(self.parentDesc) if self.parentIface else "")
|
||||
parentType=self.nativeLeafName(self.parentDesc) if self.parentIface else "",
|
||||
reflectorArg=reflectorArg,
|
||||
reflectorPassArg=reflectorPassArg)
|
||||
|
||||
@staticmethod
|
||||
def nativeLeafName(descriptor):
|
||||
|
|
|
@ -522,8 +522,7 @@ public:
|
|||
gattManager->UnregisterClient(mClient->mClientIf, result);
|
||||
}
|
||||
|
||||
DispatchReplyError(mClient->mStartLeScanRunnable,
|
||||
BluetoothValue(mClient->mAppUuid));
|
||||
DispatchReplyError(mClient->mStartLeScanRunnable, aStatus);
|
||||
mClient->mStartLeScanRunnable = nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -74,8 +74,11 @@ public:
|
|||
SOCKET_IS_CONNECTED
|
||||
};
|
||||
|
||||
DroidSocketImpl(MessageLoop* aIOLoop, BluetoothSocket* aConsumer)
|
||||
DroidSocketImpl(nsIThread* aConsumerThread,
|
||||
MessageLoop* aIOLoop,
|
||||
BluetoothSocket* aConsumer)
|
||||
: ipc::UnixFdWatcher(aIOLoop)
|
||||
, DataSocketIO(aConsumerThread)
|
||||
, mConsumer(aConsumer)
|
||||
, mShuttingDownOnIOThread(false)
|
||||
, mConnectionStatus(SOCKET_IS_DISCONNECTED)
|
||||
|
@ -83,7 +86,7 @@ public:
|
|||
|
||||
~DroidSocketImpl()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(IsConsumerThread());
|
||||
}
|
||||
|
||||
void Send(UnixSocketIOBuffer* aBuffer)
|
||||
|
@ -120,8 +123,8 @@ public:
|
|||
|
||||
/**
|
||||
* Consumer pointer. Non-thread safe RefPtr, so should only be manipulated
|
||||
* directly from main thread. All non-main-thread accesses should happen with
|
||||
* mImpl as container.
|
||||
* directly from consumer thread. All non-consumer-thread accesses should
|
||||
* happen with mImpl as container.
|
||||
*/
|
||||
RefPtr<BluetoothSocket> mConsumer;
|
||||
|
||||
|
@ -140,9 +143,10 @@ public:
|
|||
return GetDataSocket();
|
||||
}
|
||||
|
||||
bool IsShutdownOnMainThread() const override
|
||||
bool IsShutdownOnConsumerThread() const override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(IsConsumerThread());
|
||||
|
||||
return mConsumer == nullptr;
|
||||
}
|
||||
|
||||
|
@ -151,16 +155,17 @@ public:
|
|||
return mShuttingDownOnIOThread;
|
||||
}
|
||||
|
||||
void ShutdownOnMainThread() override
|
||||
void ShutdownOnConsumerThread() override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdownOnMainThread());
|
||||
MOZ_ASSERT(IsConsumerThread());
|
||||
MOZ_ASSERT(!IsShutdownOnConsumerThread());
|
||||
|
||||
mConsumer = nullptr;
|
||||
}
|
||||
|
||||
void ShutdownOnIOThread() override
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsConsumerThread());
|
||||
MOZ_ASSERT(!mShuttingDownOnIOThread);
|
||||
|
||||
Close(); // will also remove fd from I/O loop
|
||||
|
@ -214,7 +219,7 @@ public:
|
|||
|
||||
void Run() override
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(!GetIO()->IsConsumerThread());
|
||||
MOZ_ASSERT(!IsCanceled());
|
||||
|
||||
GetIO()->Connect(mFd);
|
||||
|
@ -234,7 +239,7 @@ public:
|
|||
|
||||
void Run() override
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(!GetIO()->IsConsumerThread());
|
||||
|
||||
if (!IsCanceled()) {
|
||||
GetIO()->Listen(mFd);
|
||||
|
@ -254,7 +259,7 @@ class SocketConnectClientFdTask final
|
|||
|
||||
void Run() override
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(!GetIO()->IsConsumerThread());
|
||||
|
||||
GetIO()->ConnectClientFd();
|
||||
}
|
||||
|
@ -314,8 +319,9 @@ DroidSocketImpl::Accept(int aFd)
|
|||
SetFd(aFd);
|
||||
mConnectionStatus = SOCKET_IS_CONNECTED;
|
||||
|
||||
NS_DispatchToMainThread(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS));
|
||||
GetConsumerThread()->Dispatch(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
AddWatchers(READ_WATCHER, true);
|
||||
if (HasPendingData()) {
|
||||
|
@ -338,7 +344,7 @@ DroidSocketImpl::OnFileCanReadWithoutBlocking(int aFd)
|
|||
void
|
||||
DroidSocketImpl::OnSocketCanReceiveWithoutBlocking(int aFd)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsConsumerThread());
|
||||
MOZ_ASSERT(!mShuttingDownOnIOThread);
|
||||
|
||||
ssize_t res = ReceiveData(aFd);
|
||||
|
@ -361,7 +367,7 @@ public:
|
|||
|
||||
void Run() override
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(!GetIO()->IsConsumerThread());
|
||||
MOZ_ASSERT(!IsCanceled());
|
||||
|
||||
GetIO()->Accept(mFd);
|
||||
|
@ -383,11 +389,11 @@ public:
|
|||
void Accept(int aFd, const nsAString& aBdAddress,
|
||||
int aConnectionStatus) override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mImpl->IsConsumerThread());
|
||||
|
||||
mozilla::ScopedClose fd(aFd); // Close received socket fd on error
|
||||
|
||||
if (mImpl->IsShutdownOnMainThread()) {
|
||||
if (mImpl->IsShutdownOnConsumerThread()) {
|
||||
BT_LOGD("mConsumer is null, aborting receive!");
|
||||
return;
|
||||
}
|
||||
|
@ -398,16 +404,16 @@ public:
|
|||
}
|
||||
|
||||
mImpl->mConsumer->SetAddress(aBdAddress);
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
|
||||
new AcceptTask(mImpl, fd.forget()));
|
||||
mImpl->GetIOLoop()->PostTask(FROM_HERE,
|
||||
new AcceptTask(mImpl, fd.forget()));
|
||||
}
|
||||
|
||||
void OnError(BluetoothStatus aStatus) override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mImpl->IsConsumerThread());
|
||||
BT_LOGR("BluetoothSocketInterface::Accept failed: %d", (int)aStatus);
|
||||
|
||||
if (!mImpl->IsShutdownOnMainThread()) {
|
||||
if (!mImpl->IsShutdownOnConsumerThread()) {
|
||||
// Instead of NotifyError(), call NotifyDisconnect() to trigger
|
||||
// BluetoothOppManager::OnSocketDisconnect() as
|
||||
// DroidSocketImpl::OnFileCanReadWithoutBlocking() in Firefox OS 2.0 in
|
||||
|
@ -430,7 +436,7 @@ public:
|
|||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(GetIO()->IsConsumerThread());
|
||||
MOZ_ASSERT(sBluetoothSocketInterface);
|
||||
|
||||
BluetoothSocketResultHandler* res = new AcceptResultHandler(GetIO());
|
||||
|
@ -448,7 +454,7 @@ private:
|
|||
void
|
||||
DroidSocketImpl::OnSocketCanAcceptWithoutBlocking(int aFd)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsConsumerThread());
|
||||
MOZ_ASSERT(!mShuttingDownOnIOThread);
|
||||
|
||||
/* When a listening socket is ready for receiving data,
|
||||
|
@ -456,8 +462,8 @@ DroidSocketImpl::OnSocketCanAcceptWithoutBlocking(int aFd)
|
|||
*/
|
||||
|
||||
RemoveWatchers(READ_WATCHER);
|
||||
nsRefPtr<AcceptRunnable> t = new AcceptRunnable(this, aFd);
|
||||
NS_DispatchToMainThread(t);
|
||||
GetConsumerThread()->Dispatch(new AcceptRunnable(this, aFd),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -475,7 +481,7 @@ DroidSocketImpl::OnFileCanWriteWithoutBlocking(int aFd)
|
|||
void
|
||||
DroidSocketImpl::OnSocketCanSendWithoutBlocking(int aFd)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsConsumerThread());
|
||||
MOZ_ASSERT(!mShuttingDownOnIOThread);
|
||||
MOZ_ASSERT(aFd >= 0);
|
||||
|
||||
|
@ -492,7 +498,7 @@ DroidSocketImpl::OnSocketCanSendWithoutBlocking(int aFd)
|
|||
void
|
||||
DroidSocketImpl::OnSocketCanConnectWithoutBlocking(int aFd)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsConsumerThread());
|
||||
MOZ_ASSERT(!mShuttingDownOnIOThread);
|
||||
|
||||
/* We follow Posix behaviour here: Connect operations are
|
||||
|
@ -501,8 +507,9 @@ DroidSocketImpl::OnSocketCanConnectWithoutBlocking(int aFd)
|
|||
|
||||
mConnectionStatus = SOCKET_IS_CONNECTED;
|
||||
|
||||
NS_DispatchToMainThread(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS));
|
||||
GetConsumerThread()->Dispatch(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
AddWatchers(READ_WATCHER, true);
|
||||
if (HasPendingData()) {
|
||||
|
@ -528,7 +535,7 @@ DroidSocketImpl::QueryReceiveBuffer(
|
|||
|
||||
/**
|
||||
* |ReceiveRunnable| transfers data received on the I/O thread
|
||||
* to an instance of |BluetoothSocket| on the main thread.
|
||||
* to an instance of |BluetoothSocket| on the consumer thread.
|
||||
*/
|
||||
class DroidSocketImpl::ReceiveRunnable final
|
||||
: public SocketIORunnable<DroidSocketImpl>
|
||||
|
@ -541,11 +548,11 @@ public:
|
|||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
DroidSocketImpl* io = SocketIORunnable<DroidSocketImpl>::GetIO();
|
||||
|
||||
if (NS_WARN_IF(io->IsShutdownOnMainThread())) {
|
||||
MOZ_ASSERT(io->IsConsumerThread());
|
||||
|
||||
if (NS_WARN_IF(io->IsShutdownOnConsumerThread())) {
|
||||
// Since we've already explicitly closed and the close
|
||||
// happened before this, this isn't really an error.
|
||||
return NS_OK;
|
||||
|
@ -566,7 +573,8 @@ private:
|
|||
void
|
||||
DroidSocketImpl::ConsumeBuffer()
|
||||
{
|
||||
NS_DispatchToMainThread(new ReceiveRunnable(this, mBuffer.forget()));
|
||||
GetConsumerThread()->Dispatch(new ReceiveRunnable(this, mBuffer.forget()),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -602,9 +610,9 @@ public:
|
|||
void Connect(int aFd, const nsAString& aBdAddress,
|
||||
int aConnectionStatus) override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mImpl->IsConsumerThread());
|
||||
|
||||
if (mImpl->IsShutdownOnMainThread()) {
|
||||
if (mImpl->IsShutdownOnConsumerThread()) {
|
||||
BT_LOGD("mConsumer is null, aborting send!");
|
||||
return;
|
||||
}
|
||||
|
@ -615,16 +623,16 @@ public:
|
|||
}
|
||||
|
||||
mImpl->mConsumer->SetAddress(aBdAddress);
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
|
||||
new SocketConnectTask(mImpl, aFd));
|
||||
mImpl->GetIOLoop()->PostTask(FROM_HERE,
|
||||
new SocketConnectTask(mImpl, aFd));
|
||||
}
|
||||
|
||||
void OnError(BluetoothStatus aStatus) override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mImpl->IsConsumerThread());
|
||||
BT_WARNING("Connect failed: %d", (int)aStatus);
|
||||
|
||||
if (!mImpl->IsShutdownOnMainThread()) {
|
||||
if (!mImpl->IsShutdownOnConsumerThread()) {
|
||||
// Instead of NotifyError(), call NotifyDisconnect() to trigger
|
||||
// BluetoothOppManager::OnSocketDisconnect() as
|
||||
// DroidSocketImpl::OnFileCanReadWithoutBlocking() in Firefox OS 2.0 in
|
||||
|
@ -642,14 +650,15 @@ BluetoothSocket::Connect(const nsAString& aDeviceAddress,
|
|||
const BluetoothUuid& aServiceUuid,
|
||||
BluetoothSocketType aType,
|
||||
int aChannel,
|
||||
bool aAuth, bool aEncrypt)
|
||||
bool aAuth, bool aEncrypt,
|
||||
nsIThread* aConsumerThread,
|
||||
MessageLoop* aIOLoop)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mImpl);
|
||||
|
||||
SetConnectionStatus(SOCKET_CONNECTING);
|
||||
|
||||
mImpl = new DroidSocketImpl(XRE_GetIOMessageLoop(), this);
|
||||
mImpl = new DroidSocketImpl(aConsumerThread, aIOLoop, this);
|
||||
|
||||
BluetoothSocketResultHandler* res = new ConnectSocketResultHandler(mImpl);
|
||||
SetCurrentResultHandler(res);
|
||||
|
@ -662,6 +671,23 @@ BluetoothSocket::Connect(const nsAString& aDeviceAddress,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothSocket::Connect(const nsAString& aDeviceAddress,
|
||||
const BluetoothUuid& aServiceUuid,
|
||||
BluetoothSocketType aType,
|
||||
int aChannel,
|
||||
bool aAuth, bool aEncrypt)
|
||||
{
|
||||
nsIThread* consumerThread = nullptr;
|
||||
nsresult rv = NS_GetCurrentThread(&consumerThread);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return Connect(aDeviceAddress, aServiceUuid, aType, aChannel, aAuth,
|
||||
aEncrypt, consumerThread, XRE_GetIOMessageLoop());
|
||||
}
|
||||
|
||||
class ListenResultHandler final : public BluetoothSocketResultHandler
|
||||
{
|
||||
public:
|
||||
|
@ -673,15 +699,14 @@ public:
|
|||
|
||||
void Listen(int aFd) override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mImpl->IsConsumerThread());
|
||||
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
|
||||
new SocketListenTask(mImpl, aFd));
|
||||
mImpl->GetIOLoop()->PostTask(FROM_HERE, new SocketListenTask(mImpl, aFd));
|
||||
}
|
||||
|
||||
void OnError(BluetoothStatus aStatus) override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mImpl->IsConsumerThread());
|
||||
|
||||
BT_WARNING("Listen failed: %d", (int)aStatus);
|
||||
}
|
||||
|
@ -695,14 +720,15 @@ BluetoothSocket::Listen(const nsAString& aServiceName,
|
|||
const BluetoothUuid& aServiceUuid,
|
||||
BluetoothSocketType aType,
|
||||
int aChannel,
|
||||
bool aAuth, bool aEncrypt)
|
||||
bool aAuth, bool aEncrypt,
|
||||
nsIThread* aConsumerThread,
|
||||
MessageLoop* aIOLoop)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mImpl);
|
||||
|
||||
SetConnectionStatus(SOCKET_LISTENING);
|
||||
|
||||
mImpl = new DroidSocketImpl(XRE_GetIOMessageLoop(), this);
|
||||
mImpl = new DroidSocketImpl(aConsumerThread, aIOLoop, this);
|
||||
|
||||
BluetoothSocketResultHandler* res = new ListenResultHandler(mImpl);
|
||||
SetCurrentResultHandler(res);
|
||||
|
@ -715,10 +741,26 @@ BluetoothSocket::Listen(const nsAString& aServiceName,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothSocket::Listen(const nsAString& aServiceName,
|
||||
const BluetoothUuid& aServiceUuid,
|
||||
BluetoothSocketType aType,
|
||||
int aChannel,
|
||||
bool aAuth, bool aEncrypt)
|
||||
{
|
||||
nsIThread* consumerThread = nullptr;
|
||||
nsresult rv = NS_GetCurrentThread(&consumerThread);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return Listen(aServiceName, aServiceUuid, aType, aChannel, aAuth, aEncrypt,
|
||||
consumerThread, XRE_GetIOMessageLoop());
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothSocket::ReceiveSocketData(nsAutoPtr<UnixSocketBuffer>& aBuffer)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mObserver);
|
||||
|
||||
mObserver->ReceiveSocketData(this, aBuffer);
|
||||
|
@ -729,11 +771,11 @@ BluetoothSocket::ReceiveSocketData(nsAutoPtr<UnixSocketBuffer>& aBuffer)
|
|||
void
|
||||
BluetoothSocket::SendSocketData(UnixSocketIOBuffer* aBuffer)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mImpl);
|
||||
MOZ_ASSERT(!mImpl->IsShutdownOnMainThread());
|
||||
MOZ_ASSERT(mImpl->IsConsumerThread());
|
||||
MOZ_ASSERT(!mImpl->IsShutdownOnConsumerThread());
|
||||
|
||||
XRE_GetIOMessageLoop()->PostTask(
|
||||
mImpl->GetIOLoop()->PostTask(
|
||||
FROM_HERE,
|
||||
new SocketIOSendTask<DroidSocketImpl, UnixSocketIOBuffer>(mImpl, aBuffer));
|
||||
}
|
||||
|
@ -743,12 +785,14 @@ BluetoothSocket::SendSocketData(UnixSocketIOBuffer* aBuffer)
|
|||
void
|
||||
BluetoothSocket::Close()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(sBluetoothSocketInterface);
|
||||
|
||||
if (!mImpl) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mImpl->IsConsumerThread());
|
||||
|
||||
// Stop any watching |SocketMessageWatcher|
|
||||
if (mCurrentRes) {
|
||||
sBluetoothSocketInterface->Close(mCurrentRes);
|
||||
|
@ -757,10 +801,8 @@ BluetoothSocket::Close()
|
|||
// From this point on, we consider mImpl as being deleted.
|
||||
// We sever the relationship here so any future calls to listen or connect
|
||||
// will create a new implementation.
|
||||
mImpl->ShutdownOnMainThread();
|
||||
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mImpl));
|
||||
|
||||
mImpl->ShutdownOnConsumerThread();
|
||||
mImpl->GetIOLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mImpl));
|
||||
mImpl = nullptr;
|
||||
|
||||
NotifyDisconnect();
|
||||
|
@ -769,7 +811,6 @@ BluetoothSocket::Close()
|
|||
void
|
||||
BluetoothSocket::OnConnectSuccess()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mObserver);
|
||||
|
||||
SetCurrentResultHandler(nullptr);
|
||||
|
@ -779,7 +820,6 @@ BluetoothSocket::OnConnectSuccess()
|
|||
void
|
||||
BluetoothSocket::OnConnectError()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mObserver);
|
||||
|
||||
SetCurrentResultHandler(nullptr);
|
||||
|
@ -789,7 +829,6 @@ BluetoothSocket::OnConnectError()
|
|||
void
|
||||
BluetoothSocket::OnDisconnect()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mObserver);
|
||||
mObserver->OnSocketDisconnect(this);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
#include "BluetoothCommon.h"
|
||||
#include "mozilla/ipc/DataSocket.h"
|
||||
|
||||
class MessageLoop;
|
||||
class nsIThread;
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothSocketObserver;
|
||||
|
@ -21,12 +24,28 @@ class BluetoothSocket final : public mozilla::ipc::DataSocket
|
|||
public:
|
||||
BluetoothSocket(BluetoothSocketObserver* aObserver);
|
||||
|
||||
nsresult Connect(const nsAString& aDeviceAddress,
|
||||
const BluetoothUuid& aServiceUuid,
|
||||
BluetoothSocketType aType,
|
||||
int aChannel,
|
||||
bool aAuth, bool aEncrypt,
|
||||
nsIThread* aConsumerThread,
|
||||
MessageLoop* aIOLoop);
|
||||
|
||||
nsresult Connect(const nsAString& aDeviceAddress,
|
||||
const BluetoothUuid& aServiceUuid,
|
||||
BluetoothSocketType aType,
|
||||
int aChannel,
|
||||
bool aAuth, bool aEncrypt);
|
||||
|
||||
nsresult Listen(const nsAString& aServiceName,
|
||||
const BluetoothUuid& aServiceUuid,
|
||||
BluetoothSocketType aType,
|
||||
int aChannel,
|
||||
bool aAuth, bool aEncrypt,
|
||||
nsIThread* aConsumerThread,
|
||||
MessageLoop* aIOLoop);
|
||||
|
||||
nsresult Listen(const nsAString& aServiceName,
|
||||
const BluetoothUuid& aServiceUuid,
|
||||
BluetoothSocketType aType,
|
||||
|
@ -35,7 +54,7 @@ public:
|
|||
|
||||
/**
|
||||
* Method to be called whenever data is received. This is only called on the
|
||||
* main thread.
|
||||
* consumer thread.
|
||||
*
|
||||
* @param aBuffer Data received from the socket.
|
||||
*/
|
||||
|
|
|
@ -28,7 +28,8 @@ class BluetoothSocket::BluetoothSocketIO final
|
|||
, public DataSocketIO
|
||||
{
|
||||
public:
|
||||
BluetoothSocketIO(MessageLoop* mIOLoop,
|
||||
BluetoothSocketIO(nsIThread* aConsumerThread,
|
||||
MessageLoop* aIOLoop,
|
||||
BluetoothSocket* aConsumer,
|
||||
UnixSocketConnector* aConnector);
|
||||
~BluetoothSocketIO();
|
||||
|
@ -82,10 +83,10 @@ public:
|
|||
|
||||
SocketBase* GetSocketBase() override;
|
||||
|
||||
bool IsShutdownOnMainThread() const override;
|
||||
bool IsShutdownOnConsumerThread() const override;
|
||||
bool IsShutdownOnIOThread() const override;
|
||||
|
||||
void ShutdownOnMainThread() override;
|
||||
void ShutdownOnConsumerThread() override;
|
||||
void ShutdownOnIOThread() override;
|
||||
|
||||
private:
|
||||
|
@ -95,8 +96,8 @@ private:
|
|||
|
||||
/**
|
||||
* Consumer pointer. Non-thread safe RefPtr, so should only be manipulated
|
||||
* directly from main thread. All non-main-thread accesses should happen with
|
||||
* mIO as container.
|
||||
* directly from consumer thread. All non-consumer-thread accesses should
|
||||
* happen with mIO as container.
|
||||
*/
|
||||
RefPtr<BluetoothSocket> mConsumer;
|
||||
|
||||
|
@ -121,7 +122,8 @@ private:
|
|||
struct sockaddr_storage mAddress;
|
||||
|
||||
/**
|
||||
* Task member for delayed connect task. Should only be access on main thread.
|
||||
* Task member for delayed connect task. Should only be access on consumer
|
||||
* thread.
|
||||
*/
|
||||
CancelableTask* mDelayedConnectTask;
|
||||
|
||||
|
@ -132,10 +134,12 @@ private:
|
|||
};
|
||||
|
||||
BluetoothSocket::BluetoothSocketIO::BluetoothSocketIO(
|
||||
MessageLoop* mIOLoop,
|
||||
nsIThread* aConsumerThread,
|
||||
MessageLoop* aIOLoop,
|
||||
BluetoothSocket* aConsumer,
|
||||
UnixSocketConnector* aConnector)
|
||||
: UnixSocketWatcher(mIOLoop)
|
||||
: UnixSocketWatcher(aIOLoop)
|
||||
, DataSocketIO(aConsumerThread)
|
||||
, mConsumer(aConsumer)
|
||||
, mConnector(aConnector)
|
||||
, mShuttingDownOnIOThread(false)
|
||||
|
@ -148,8 +152,8 @@ BluetoothSocket::BluetoothSocketIO::BluetoothSocketIO(
|
|||
|
||||
BluetoothSocket::BluetoothSocketIO::~BluetoothSocketIO()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(IsShutdownOnMainThread());
|
||||
MOZ_ASSERT(IsConsumerThread());
|
||||
MOZ_ASSERT(IsShutdownOnConsumerThread());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -188,7 +192,7 @@ BluetoothSocket::BluetoothSocketIO::GetDataSocket()
|
|||
void
|
||||
BluetoothSocket::BluetoothSocketIO::SetDelayedConnectTask(CancelableTask* aTask)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(IsConsumerThread());
|
||||
|
||||
mDelayedConnectTask = aTask;
|
||||
}
|
||||
|
@ -196,7 +200,7 @@ BluetoothSocket::BluetoothSocketIO::SetDelayedConnectTask(CancelableTask* aTask)
|
|||
void
|
||||
BluetoothSocket::BluetoothSocketIO::ClearDelayedConnectTask()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(IsConsumerThread());
|
||||
|
||||
mDelayedConnectTask = nullptr;
|
||||
}
|
||||
|
@ -204,7 +208,7 @@ BluetoothSocket::BluetoothSocketIO::ClearDelayedConnectTask()
|
|||
void
|
||||
BluetoothSocket::BluetoothSocketIO::CancelDelayedConnectTask()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(IsConsumerThread());
|
||||
|
||||
if (!mDelayedConnectTask) {
|
||||
return;
|
||||
|
@ -277,8 +281,9 @@ BluetoothSocket::BluetoothSocketIO::OnConnected()
|
|||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED);
|
||||
|
||||
NS_DispatchToMainThread(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS));
|
||||
GetConsumerThread()->Dispatch(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
AddWatchers(READ_WATCHER, true);
|
||||
if (HasPendingData()) {
|
||||
|
@ -326,8 +331,9 @@ BluetoothSocket::BluetoothSocketIO::OnSocketCanAcceptWithoutBlocking()
|
|||
Close();
|
||||
SetSocket(fd, SOCKET_IS_CONNECTED);
|
||||
|
||||
NS_DispatchToMainThread(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS));
|
||||
GetConsumerThread()->Dispatch(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
AddWatchers(READ_WATCHER, true);
|
||||
if (HasPendingData()) {
|
||||
|
@ -375,9 +381,10 @@ BluetoothSocket::BluetoothSocketIO::FireSocketError()
|
|||
// Clean up watchers, statuses, fds
|
||||
Close();
|
||||
|
||||
// Tell the main thread we've errored
|
||||
NS_DispatchToMainThread(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR));
|
||||
// Tell the consumer thread we've errored
|
||||
GetConsumerThread()->Dispatch(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
}
|
||||
|
||||
|
@ -399,7 +406,7 @@ BluetoothSocket::BluetoothSocketIO::QueryReceiveBuffer(
|
|||
|
||||
/**
|
||||
* |ReceiveRunnable| transfers data received on the I/O thread
|
||||
* to an instance of |BluetoothSocket| on the main thread.
|
||||
* to an instance of |BluetoothSocket| on the consumer thread.
|
||||
*/
|
||||
class BluetoothSocket::BluetoothSocketIO::ReceiveRunnable final
|
||||
: public SocketIORunnable<BluetoothSocketIO>
|
||||
|
@ -412,11 +419,11 @@ public:
|
|||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
BluetoothSocketIO* io = SocketIORunnable<BluetoothSocketIO>::GetIO();
|
||||
|
||||
if (NS_WARN_IF(io->IsShutdownOnMainThread())) {
|
||||
MOZ_ASSERT(io->IsConsumerThread());
|
||||
|
||||
if (NS_WARN_IF(io->IsShutdownOnConsumerThread())) {
|
||||
// Since we've already explicitly closed and the close
|
||||
// happened before this, this isn't really an error.
|
||||
return NS_OK;
|
||||
|
@ -437,7 +444,8 @@ private:
|
|||
void
|
||||
BluetoothSocket::BluetoothSocketIO::ConsumeBuffer()
|
||||
{
|
||||
NS_DispatchToMainThread(new ReceiveRunnable(this, mBuffer.forget()));
|
||||
GetConsumerThread()->Dispatch(new ReceiveRunnable(this, mBuffer.forget()),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -455,18 +463,18 @@ BluetoothSocket::BluetoothSocketIO::GetSocketBase()
|
|||
}
|
||||
|
||||
bool
|
||||
BluetoothSocket::BluetoothSocketIO::IsShutdownOnMainThread() const
|
||||
BluetoothSocket::BluetoothSocketIO::IsShutdownOnConsumerThread() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(IsConsumerThread());
|
||||
|
||||
return mConsumer == nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothSocket::BluetoothSocketIO::ShutdownOnMainThread()
|
||||
BluetoothSocket::BluetoothSocketIO::ShutdownOnConsumerThread()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdownOnMainThread());
|
||||
MOZ_ASSERT(IsConsumerThread());
|
||||
MOZ_ASSERT(!IsShutdownOnConsumerThread());
|
||||
|
||||
mConsumer = nullptr;
|
||||
}
|
||||
|
@ -480,7 +488,7 @@ BluetoothSocket::BluetoothSocketIO::IsShutdownOnIOThread() const
|
|||
void
|
||||
BluetoothSocket::BluetoothSocketIO::ShutdownOnIOThread()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsConsumerThread());
|
||||
MOZ_ASSERT(!mShuttingDownOnIOThread);
|
||||
|
||||
Close(); // will also remove fd from I/O loop
|
||||
|
@ -502,7 +510,7 @@ public:
|
|||
|
||||
void Run() override
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(!GetIO()->IsConsumerThread());
|
||||
|
||||
if (!IsCanceled()) {
|
||||
GetIO()->Listen();
|
||||
|
@ -520,7 +528,7 @@ public:
|
|||
|
||||
void Run() override
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(!GetIO()->IsConsumerThread());
|
||||
MOZ_ASSERT(!IsCanceled());
|
||||
|
||||
GetIO()->Connect();
|
||||
|
@ -537,19 +545,19 @@ public:
|
|||
|
||||
void Run() override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(GetIO()->IsConsumerThread());
|
||||
|
||||
if (IsCanceled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
BluetoothSocketIO* io = GetIO();
|
||||
if (io->IsShutdownOnMainThread()) {
|
||||
if (io->IsShutdownOnConsumerThread()) {
|
||||
return;
|
||||
}
|
||||
|
||||
io->ClearDelayedConnectTask();
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new ConnectTask(io));
|
||||
io->GetIOLoop()->PostTask(FROM_HERE, new ConnectTask(io));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -576,7 +584,6 @@ BluetoothSocket::Connect(const nsAString& aDeviceAddress,
|
|||
int aChannel,
|
||||
bool aAuth, bool aEncrypt)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!aDeviceAddress.IsEmpty());
|
||||
|
||||
nsAutoPtr<BluetoothUnixSocketConnector> connector(
|
||||
|
@ -603,8 +610,6 @@ BluetoothSocket::Listen(const nsAString& aServiceName,
|
|||
int aChannel,
|
||||
bool aAuth, bool aEncrypt)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsAutoPtr<BluetoothUnixSocketConnector> connector(
|
||||
new BluetoothUnixSocketConnector(NS_LITERAL_CSTRING(BLUETOOTH_ADDRESS_NONE),
|
||||
aType, aChannel, aAuth, aEncrypt));
|
||||
|
@ -625,7 +630,6 @@ BluetoothSocket::Listen(const nsAString& aServiceName,
|
|||
void
|
||||
BluetoothSocket::ReceiveSocketData(nsAutoPtr<UnixSocketBuffer>& aBuffer)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mObserver);
|
||||
|
||||
mObserver->ReceiveSocketData(this, aBuffer);
|
||||
|
@ -645,39 +649,68 @@ BluetoothSocket::SendSocketData(const nsACString& aStr)
|
|||
|
||||
nsresult
|
||||
BluetoothSocket::Connect(BluetoothUnixSocketConnector* aConnector,
|
||||
int aDelayMs)
|
||||
int aDelayMs,
|
||||
nsIThread* aConsumerThread, MessageLoop* aIOLoop)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aConnector);
|
||||
MOZ_ASSERT(aConsumerThread);
|
||||
MOZ_ASSERT(aIOLoop);
|
||||
MOZ_ASSERT(!mIO);
|
||||
|
||||
MessageLoop* ioLoop = XRE_GetIOMessageLoop();
|
||||
mIO = new BluetoothSocketIO(ioLoop, this, aConnector);
|
||||
mIO = new BluetoothSocketIO(aConsumerThread, aIOLoop, this, aConnector);
|
||||
SetConnectionStatus(SOCKET_CONNECTING);
|
||||
|
||||
if (aDelayMs > 0) {
|
||||
DelayedConnectTask* connectTask = new DelayedConnectTask(mIO);
|
||||
mIO->SetDelayedConnectTask(connectTask);
|
||||
MessageLoop::current()->PostDelayedTask(FROM_HERE, connectTask, aDelayMs);
|
||||
} else {
|
||||
ioLoop->PostTask(FROM_HERE, new ConnectTask(mIO));
|
||||
aIOLoop->PostTask(FROM_HERE, new ConnectTask(mIO));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothSocket::Connect(BluetoothUnixSocketConnector* aConnector,
|
||||
int aDelayMs)
|
||||
{
|
||||
nsIThread* consumerThread = nullptr;
|
||||
nsresult rv = NS_GetCurrentThread(&consumerThread);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return Connect(aConnector, aDelayMs, consumerThread, XRE_GetIOMessageLoop());
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothSocket::Listen(BluetoothUnixSocketConnector* aConnector,
|
||||
nsIThread* aConsumerThread, MessageLoop* aIOLoop)
|
||||
{
|
||||
MOZ_ASSERT(aConnector);
|
||||
MOZ_ASSERT(aConsumerThread);
|
||||
MOZ_ASSERT(aIOLoop);
|
||||
MOZ_ASSERT(!mIO);
|
||||
|
||||
mIO = new BluetoothSocketIO(aConsumerThread, aIOLoop, this, aConnector);
|
||||
SetConnectionStatus(SOCKET_LISTENING);
|
||||
|
||||
aIOLoop->PostTask(FROM_HERE, new ListenTask(mIO));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothSocket::Listen(BluetoothUnixSocketConnector* aConnector)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aConnector);
|
||||
MOZ_ASSERT(!mIO);
|
||||
nsIThread* consumerThread = nullptr;
|
||||
nsresult rv = NS_GetCurrentThread(&consumerThread);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
MessageLoop* ioLoop = XRE_GetIOMessageLoop();
|
||||
|
||||
mIO = new BluetoothSocketIO(ioLoop, this, aConnector);
|
||||
SetConnectionStatus(SOCKET_LISTENING);
|
||||
ioLoop->PostTask(FROM_HERE, new ListenTask(mIO));
|
||||
|
||||
return NS_OK;
|
||||
return Listen(aConnector, consumerThread, XRE_GetIOMessageLoop());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -696,11 +729,11 @@ BluetoothSocket::GetAddress(nsAString& aAddrStr)
|
|||
void
|
||||
BluetoothSocket::SendSocketData(UnixSocketIOBuffer* aBuffer)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mIO);
|
||||
MOZ_ASSERT(!mIO->IsShutdownOnMainThread());
|
||||
MOZ_ASSERT(mIO->IsConsumerThread());
|
||||
MOZ_ASSERT(!mIO->IsShutdownOnConsumerThread());
|
||||
|
||||
XRE_GetIOMessageLoop()->PostTask(
|
||||
mIO->GetIOLoop()->PostTask(
|
||||
FROM_HERE,
|
||||
new SocketIOSendTask<BluetoothSocketIO, UnixSocketIOBuffer>(mIO, aBuffer));
|
||||
}
|
||||
|
@ -710,20 +743,19 @@ BluetoothSocket::SendSocketData(UnixSocketIOBuffer* aBuffer)
|
|||
void
|
||||
BluetoothSocket::Close()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!mIO) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mIO->IsConsumerThread());
|
||||
|
||||
mIO->CancelDelayedConnectTask();
|
||||
|
||||
// From this point on, we consider mIO as being deleted.
|
||||
// We sever the relationship here so any future calls to listen or connect
|
||||
// will create a new implementation.
|
||||
mIO->ShutdownOnMainThread();
|
||||
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO));
|
||||
|
||||
mIO->ShutdownOnConsumerThread();
|
||||
mIO->GetIOLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO));
|
||||
mIO = nullptr;
|
||||
|
||||
NotifyDisconnect();
|
||||
|
@ -732,7 +764,6 @@ BluetoothSocket::Close()
|
|||
void
|
||||
BluetoothSocket::OnConnectSuccess()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mObserver);
|
||||
mObserver->OnSocketConnectSuccess(this);
|
||||
}
|
||||
|
@ -740,7 +771,6 @@ BluetoothSocket::OnConnectSuccess()
|
|||
void
|
||||
BluetoothSocket::OnConnectError()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mObserver);
|
||||
mObserver->OnSocketConnectError(this);
|
||||
}
|
||||
|
@ -748,7 +778,6 @@ BluetoothSocket::OnConnectError()
|
|||
void
|
||||
BluetoothSocket::OnDisconnect()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mObserver);
|
||||
mObserver->OnSocketDisconnect(this);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#include "nsString.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
class MessageLoop;
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothSocketObserver;
|
||||
|
@ -41,7 +43,7 @@ public:
|
|||
|
||||
/**
|
||||
* Method to be called whenever data is received. This is only called on the
|
||||
* main thread.
|
||||
* consumer thread.
|
||||
*
|
||||
* @param aBuffer Data received from the socket.
|
||||
*/
|
||||
|
@ -58,6 +60,19 @@ public:
|
|||
*/
|
||||
bool SendSocketData(const nsACString& aMessage);
|
||||
|
||||
/**
|
||||
* Starts a task on the socket that will try to connect to a socket in a
|
||||
* non-blocking manner.
|
||||
*
|
||||
* @param aConnector Connector object for socket type specific functions
|
||||
* @param aDelayMs Time delay in milli-seconds.
|
||||
* @param aConsumerThread The socket's consumer thread.
|
||||
* @param aIOLoop The socket's I/O thread.
|
||||
* @return NS_OK on success, or an XPCOM error code otherwise.
|
||||
*/
|
||||
nsresult Connect(BluetoothUnixSocketConnector* aConnector, int aDelayMs,
|
||||
nsIThread* aConsumerThread, MessageLoop* aIOLoop);
|
||||
|
||||
/**
|
||||
* Starts a task on the socket that will try to connect to a socket in a
|
||||
* non-blocking manner.
|
||||
|
@ -69,6 +84,18 @@ public:
|
|||
nsresult Connect(BluetoothUnixSocketConnector* aConnector,
|
||||
int aDelayMs = 0);
|
||||
|
||||
/**
|
||||
* Starts a task on the socket that will try to accept a new connection in a
|
||||
* non-blocking manner.
|
||||
*
|
||||
* @param aConnector Connector object for socket type specific functions
|
||||
* @param aConsumerThread The socket's consumer thread.
|
||||
* @param aIOLoop The socket's I/O thread.
|
||||
* @return NS_OK on success, or an XPCOM error code otherwise.
|
||||
*/
|
||||
nsresult Listen(BluetoothUnixSocketConnector* aConnector,
|
||||
nsIThread* aConsumerThread, MessageLoop* aIOLoop);
|
||||
|
||||
/**
|
||||
* Starts a task on the socket that will try to accept a new connection in a
|
||||
* non-blocking manner.
|
||||
|
|
|
@ -168,6 +168,9 @@ InternalRequest::SetContentPolicyType(nsContentPolicyType aContentPolicyType)
|
|||
case nsIContentPolicy::TYPE_IMAGESET:
|
||||
mContext = RequestContext::Imageset;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_WEB_MANIFEST:
|
||||
mContext = RequestContext::Manifest;
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(false, "Unhandled nsContentPolicyType value");
|
||||
mContext = RequestContext::Internal;
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace dom {
|
|||
* import | Not supported by Gecko
|
||||
* internal | TYPE_DOCUMENT, TYPE_XBL, TYPE_OTHER
|
||||
* location |
|
||||
* manifest |
|
||||
* manifest | TYPE_WEB_MANIFEST
|
||||
* object | TYPE_OBJECT
|
||||
* ping | TYPE_PING
|
||||
* plugin | TYPE_OBJECT_SUBREQUEST
|
||||
|
|
|
@ -20,7 +20,7 @@ interface nsIURI;
|
|||
|
||||
typedef unsigned short CSPDirective;
|
||||
|
||||
[scriptable, uuid(459fe61a-203e-4460-9ced-352a9bd3aa71)]
|
||||
[scriptable, uuid(059b94e3-45c2-4794-ac2a-5b66a66b5967)]
|
||||
interface nsIContentSecurityPolicy : nsISerializable
|
||||
{
|
||||
/**
|
||||
|
@ -48,6 +48,7 @@ interface nsIContentSecurityPolicy : nsISerializable
|
|||
const unsigned short BASE_URI_DIRECTIVE = 13;
|
||||
const unsigned short FORM_ACTION_DIRECTIVE = 14;
|
||||
const unsigned short REFERRER_DIRECTIVE = 15;
|
||||
const unsigned short WEB_MANIFEST_SRC_DIRECTIVE = 16;
|
||||
|
||||
/**
|
||||
* Accessor method for a read-only string version of the policy at a given
|
||||
|
|
|
@ -14,27 +14,33 @@
|
|||
/*globals content, sendAsyncMessage, addMessageListener, Components*/
|
||||
'use strict';
|
||||
const {
|
||||
utils: Cu
|
||||
utils: Cu,
|
||||
classes: Cc,
|
||||
interfaces: Ci
|
||||
} = Components;
|
||||
const {
|
||||
ManifestProcessor
|
||||
} = Cu.import('resource://gre/modules/WebManifest.jsm', {});
|
||||
const {
|
||||
Task: {
|
||||
spawn, async
|
||||
}
|
||||
} = Components.utils.import('resource://gre/modules/Task.jsm', {});
|
||||
|
||||
addMessageListener('DOM:ManifestObtainer:Obtain', (aMsg) => {
|
||||
fetchManifest()
|
||||
.then(
|
||||
manifest => sendAsyncMessage('DOM:ManifestObtainer:Obtain', {
|
||||
success: true,
|
||||
result: manifest,
|
||||
msgId: aMsg.data.msgId
|
||||
}),
|
||||
error => sendAsyncMessage('DOM:ManifestObtainer:Obtain', {
|
||||
success: false,
|
||||
result: cloneError(error),
|
||||
msgId: aMsg.data.msgId
|
||||
})
|
||||
);
|
||||
});
|
||||
addMessageListener('DOM:ManifestObtainer:Obtain', async(function* (aMsg) {
|
||||
const response = {
|
||||
msgId: aMsg.data.msgId,
|
||||
success: true,
|
||||
result: undefined
|
||||
};
|
||||
try {
|
||||
response.result = yield fetchManifest();
|
||||
} catch (err) {
|
||||
response.success = false;
|
||||
response.result = cloneError(err);
|
||||
}
|
||||
sendAsyncMessage('DOM:ManifestObtainer:Obtain', response);
|
||||
}));
|
||||
|
||||
function cloneError(aError) {
|
||||
const clone = {
|
||||
|
@ -49,19 +55,23 @@ function cloneError(aError) {
|
|||
}
|
||||
|
||||
function fetchManifest() {
|
||||
const manifestQuery = 'link[rel~="manifest"]';
|
||||
return new Promise((resolve, reject) => {
|
||||
return spawn(function* () {
|
||||
if (!content || content.top !== content) {
|
||||
let msg = 'Content window must be a top-level browsing context.';
|
||||
return reject(new Error(msg));
|
||||
throw new Error(msg);
|
||||
}
|
||||
const elem = content.document.querySelector(manifestQuery);
|
||||
const elem = content.document.querySelector('link[rel~="manifest"]');
|
||||
if (!elem || !elem.getAttribute('href')) {
|
||||
let msg = 'No manifest to fetch.';
|
||||
return reject(new Error(msg));
|
||||
throw new Error(msg);
|
||||
}
|
||||
// Will throw on "about:blank" and possibly other invalid URIs.
|
||||
// Throws on malformed URLs
|
||||
const manifestURL = new content.URL(elem.href, elem.baseURI);
|
||||
if (!canLoadManifest(elem)) {
|
||||
let msg = `Content Security Policy: The page's settings blocked the `;
|
||||
msg += `loading of a resource at ${elem.href}`;
|
||||
throw new Error(msg);
|
||||
}
|
||||
const reqInit = {
|
||||
mode: 'cors'
|
||||
};
|
||||
|
@ -70,34 +80,43 @@ function fetchManifest() {
|
|||
}
|
||||
const req = new content.Request(manifestURL, reqInit);
|
||||
req.setContext('manifest');
|
||||
content
|
||||
.fetch(req)
|
||||
.then(resp => processResponse(resp, content))
|
||||
.then(resolve)
|
||||
.catch(reject);
|
||||
const response = yield content.fetch(req);
|
||||
const manifest = yield processResponse(response, content);
|
||||
return manifest;
|
||||
});
|
||||
}
|
||||
|
||||
function canLoadManifest(aElem) {
|
||||
const contentPolicy = Cc['@mozilla.org/layout/content-policy;1']
|
||||
.getService(Ci.nsIContentPolicy);
|
||||
const mimeType = aElem.type || 'application/manifest+json';
|
||||
const elemURI = BrowserUtils.makeURI(
|
||||
aElem.href, aElem.ownerDocument.characterSet
|
||||
);
|
||||
const shouldLoad = contentPolicy.shouldLoad(
|
||||
Ci.nsIContentPolicy.TYPE_WEB_MANIFEST, elemURI,
|
||||
aElem.ownerDocument.documentURIObject,
|
||||
aElem, mimeType, null
|
||||
);
|
||||
return shouldLoad === Ci.nsIContentPolicy.ACCEPT;
|
||||
}
|
||||
|
||||
function processResponse(aResp, aContentWindow) {
|
||||
const manifestURL = aResp.url;
|
||||
return new Promise((resolve, reject) => {
|
||||
return spawn(function* () {
|
||||
const badStatus = aResp.status < 200 || aResp.status >= 300;
|
||||
if (aResp.type === 'error' || badStatus) {
|
||||
let msg =
|
||||
`Fetch error: ${aResp.status} - ${aResp.statusText} at ${aResp.url}`;
|
||||
return reject(new Error(msg));
|
||||
throw new Error(msg);
|
||||
}
|
||||
aResp
|
||||
.text()
|
||||
.then((text) => {
|
||||
const args = {
|
||||
jsonText: text,
|
||||
manifestURL: manifestURL,
|
||||
docURL: aContentWindow.location.href
|
||||
};
|
||||
const processor = new ManifestProcessor();
|
||||
const manifest = processor.process(args);
|
||||
resolve(Cu.cloneInto(manifest, content));
|
||||
}, reject);
|
||||
const text = yield aResp.text();
|
||||
const args = {
|
||||
jsonText: text,
|
||||
manifestURL: aResp.url,
|
||||
docURL: aContentWindow.location.href
|
||||
};
|
||||
const processor = new ManifestProcessor();
|
||||
const manifest = processor.process(args);
|
||||
return Cu.cloneInto(manifest, content);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -74,7 +74,14 @@ ManifestObtainer.prototype = {
|
|||
});
|
||||
|
||||
function toError(aErrorClone) {
|
||||
const error = new Error();
|
||||
let error;
|
||||
switch (aErrorClone.name) {
|
||||
case 'TypeError':
|
||||
error = new TypeError();
|
||||
break;
|
||||
default:
|
||||
error = new Error();
|
||||
}
|
||||
Object.getOwnPropertyNames(aErrorClone)
|
||||
.forEach(name => error[name] = aErrorClone[name]);
|
||||
return error;
|
||||
|
|
|
@ -109,6 +109,51 @@ const tests = [
|
|||
href='${remoteURL}?${body}&${CORS}'>`;
|
||||
return link;
|
||||
}
|
||||
},{
|
||||
expected: 'Trying to load from about:whatever is a TypeError.',
|
||||
get tabURL() {
|
||||
let query = [
|
||||
`body=<h1>${this.expected}</h1>`,
|
||||
'Content-Type=text/html; charset=utf-8',
|
||||
];
|
||||
const URL = `${defaultURL}?${query.join('&')}`;
|
||||
return URL;
|
||||
},
|
||||
run(err) {
|
||||
Assert.strictEqual(err.name, 'TypeError', this.expected);
|
||||
},
|
||||
testData: `<link rel="manifest" href='about:whatever'>`
|
||||
},
|
||||
{
|
||||
expected: 'Trying to load from file://whatever is a TypeError.',
|
||||
get tabURL() {
|
||||
let query = [
|
||||
`body=<h1>${this.expected}</h1>`,
|
||||
'Content-Type=text/html; charset=utf-8',
|
||||
];
|
||||
const URL = `${defaultURL}?${query.join('&')}`;
|
||||
return URL;
|
||||
},
|
||||
run(err) {
|
||||
Assert.strictEqual(err.name, 'TypeError', this.expected);
|
||||
},
|
||||
testData: `<link rel="manifest" href='file://manifest'>`
|
||||
},
|
||||
//URL parsing tests
|
||||
{
|
||||
expected: 'Trying to load invalid URL is a TypeError.',
|
||||
get tabURL() {
|
||||
let query = [
|
||||
`body=<h1>${this.expected}</h1>`,
|
||||
'Content-Type=text/html; charset=utf-8',
|
||||
];
|
||||
const URL = `${defaultURL}?${query.join('&')}`;
|
||||
return URL;
|
||||
},
|
||||
run(err) {
|
||||
Assert.strictEqual(err.name, 'TypeError', this.expected);
|
||||
},
|
||||
testData: `<link rel="manifest" href='http://[12.1212.21.21.12.21.12]'>`
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
@ -272,16 +272,18 @@ private:
|
|||
* so that it may be called on the main thread. The error callback is also
|
||||
* passed so it can be released correctly.
|
||||
*/
|
||||
class DeviceSuccessCallbackRunnable: public nsRunnable
|
||||
class DeviceSuccessCallbackRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
DeviceSuccessCallbackRunnable(
|
||||
uint64_t aWindowID,
|
||||
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback>& aOnSuccess,
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aOnFailure,
|
||||
nsTArray<nsRefPtr<MediaDevice>>* aDevices)
|
||||
nsTArray<nsRefPtr<MediaDevice>>* aDevices,
|
||||
bool aIsGum)
|
||||
: mDevices(aDevices)
|
||||
, mWindowID(aWindowID)
|
||||
, mIsGum(aIsGum)
|
||||
, mManager(MediaManager::GetInstance())
|
||||
{
|
||||
mOnSuccess.swap(aOnSuccess);
|
||||
|
@ -358,38 +360,43 @@ public:
|
|||
do_CreateInstance("@mozilla.org/variant;1");
|
||||
|
||||
size_t len = mDevices->Length();
|
||||
if (len == 0) {
|
||||
// XXX
|
||||
// We should in the future return an empty array, and dynamically add
|
||||
// devices to the dropdowns if things are hotplugged while the
|
||||
// requester is up.
|
||||
nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(mWindowID);
|
||||
if (window) {
|
||||
nsRefPtr<MediaStreamError> error = new MediaStreamError(window,
|
||||
NS_LITERAL_STRING("NotFoundError"));
|
||||
mOnFailure->OnError(error);
|
||||
|
||||
if (!len) {
|
||||
if (mIsGum) { // gUM fails on 0 devices whereas enumerateDevices doesn't.
|
||||
// XXX
|
||||
// We should in the future return an empty array, and dynamically add
|
||||
// devices to the dropdowns if things are hotplugged while the
|
||||
// requester is up.
|
||||
nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(mWindowID);
|
||||
if (window) {
|
||||
nsRefPtr<MediaStreamError> error = new MediaStreamError(window,
|
||||
NS_LITERAL_STRING("NotFoundError"));
|
||||
mOnFailure->OnError(error);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsTArray<nsIMediaDevice*> tmp(len);
|
||||
for (auto& device : *mDevices) {
|
||||
if (!mOriginKey.IsEmpty()) {
|
||||
nsString id;
|
||||
device->GetId(id);
|
||||
AnonymizeId(id, mOriginKey);
|
||||
device->SetId(id);
|
||||
devices->SetAsEmptyArray(); // SetAsArray() fails on zero length arrays.
|
||||
} else {
|
||||
nsTArray<nsIMediaDevice*> tmp(len);
|
||||
for (auto& device : *mDevices) {
|
||||
if (!mOriginKey.IsEmpty()) {
|
||||
nsString id;
|
||||
device->GetId(id);
|
||||
AnonymizeId(id, mOriginKey);
|
||||
device->SetId(id);
|
||||
}
|
||||
tmp.AppendElement(device);
|
||||
}
|
||||
nsresult rv = devices->SetAsArray(nsIDataType::VTYPE_INTERFACE,
|
||||
&NS_GET_IID(nsIMediaDevice),
|
||||
mDevices->Length(),
|
||||
const_cast<void*>(
|
||||
static_cast<const void*>(tmp.Elements())
|
||||
));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
tmp.AppendElement(device);
|
||||
}
|
||||
|
||||
devices->SetAsArray(nsIDataType::VTYPE_INTERFACE,
|
||||
&NS_GET_IID(nsIMediaDevice),
|
||||
mDevices->Length(),
|
||||
const_cast<void*>(
|
||||
static_cast<const void*>(tmp.Elements())
|
||||
));
|
||||
|
||||
mOnSuccess->OnSuccess(devices);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -400,6 +407,7 @@ private:
|
|||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
|
||||
nsAutoPtr<nsTArray<nsRefPtr<MediaDevice>>> mDevices;
|
||||
uint64_t mWindowID;
|
||||
bool mIsGum;
|
||||
nsRefPtr<MediaManager> mManager;
|
||||
};
|
||||
|
||||
|
@ -1512,7 +1520,7 @@ public:
|
|||
}
|
||||
nsRefPtr<DeviceSuccessCallbackRunnable> runnable =
|
||||
new DeviceSuccessCallbackRunnable(mWindowId, mOnSuccess, mOnFailure,
|
||||
result.forget());
|
||||
result.forget(), mPrivileged);
|
||||
if (mPrivileged) {
|
||||
NS_DispatchToMainThread(runnable);
|
||||
} else {
|
||||
|
|
|
@ -403,12 +403,14 @@ GMPChild::RecvStartPlugin()
|
|||
mGMPLoader = GMPProcessChild::GetGMPLoader();
|
||||
if (!mGMPLoader) {
|
||||
NS_WARNING("Failed to get GMPLoader");
|
||||
delete platformAPI;
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(MOZ_GMP_SANDBOX) && defined(XP_MACOSX)
|
||||
if (!SetMacSandboxInfo()) {
|
||||
NS_WARNING("Failed to set Mac GMP sandbox info");
|
||||
delete platformAPI;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
@ -419,6 +421,7 @@ GMPChild::RecvStartPlugin()
|
|||
mNodeId.size(),
|
||||
platformAPI)) {
|
||||
NS_WARNING("Failed to load GMP");
|
||||
delete platformAPI;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -224,10 +224,14 @@ void GStreamerReader::ElementAddedCb(GstBin *aPlayBin,
|
|||
GstElement *aElement,
|
||||
gpointer aUserData)
|
||||
{
|
||||
const gchar *name =
|
||||
gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(gst_element_get_factory(aElement)));
|
||||
GstElementFactory *factory = gst_element_get_factory(aElement);
|
||||
|
||||
if (!strcmp(name, "uridecodebin")) {
|
||||
if (!factory)
|
||||
return;
|
||||
|
||||
const gchar *name = gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(factory));
|
||||
|
||||
if (name && !strcmp(name, "uridecodebin")) {
|
||||
g_signal_connect(G_OBJECT(aElement), "autoplug-sort",
|
||||
G_CALLBACK(GStreamerReader::ElementFilterCb), aUserData);
|
||||
}
|
||||
|
|
|
@ -60,6 +60,9 @@ const kCHILD_PROCESS_MESSAGES = ["Push:Register", "Push:Unregister",
|
|||
|
||||
const kWS_MAX_WENTDOWN = 2;
|
||||
|
||||
// 1 minute is the least allowed ping interval
|
||||
const kWS_MIN_PING_INTERVAL = 60000;
|
||||
|
||||
// This is a singleton
|
||||
this.PushDB = function PushDB() {
|
||||
debug("PushDB()");
|
||||
|
@ -803,7 +806,11 @@ this.PushService = {
|
|||
this._wsWentDownCounter = 0;
|
||||
this._recalculatePing = true;
|
||||
this._lastGoodPingInterval = Math.floor(lastTriedPingInterval / 2);
|
||||
nextPingInterval = this._lastGoodPingInterval;
|
||||
if (this._lastGoodPingInterval < kWS_MIN_PING_INTERVAL) {
|
||||
nextPingInterval = kWS_MIN_PING_INTERVAL;
|
||||
} else {
|
||||
nextPingInterval = this._lastGoodPingInterval;
|
||||
}
|
||||
prefs.set('pingInterval', nextPingInterval);
|
||||
this._save(ns, nextPingInterval);
|
||||
return;
|
||||
|
|
|
@ -149,6 +149,9 @@ CSP_ContentTypeToDirective(nsContentPolicyType aType)
|
|||
case nsIContentPolicy::TYPE_MEDIA:
|
||||
return nsIContentSecurityPolicy::MEDIA_SRC_DIRECTIVE;
|
||||
|
||||
case nsIContentPolicy::TYPE_WEB_MANIFEST:
|
||||
return nsIContentSecurityPolicy::WEB_MANIFEST_SRC_DIRECTIVE;
|
||||
|
||||
case nsIContentPolicy::TYPE_SUBDOCUMENT:
|
||||
return nsIContentSecurityPolicy::FRAME_SRC_DIRECTIVE;
|
||||
|
||||
|
@ -836,6 +839,10 @@ nsCSPDirective::toDomCSPStruct(mozilla::dom::CSP& outCSP) const
|
|||
outCSP.mFrame_ancestors.Value() = srcs;
|
||||
return;
|
||||
|
||||
case nsIContentSecurityPolicy::WEB_MANIFEST_SRC_DIRECTIVE:
|
||||
outCSP.mManifest_src.Construct();
|
||||
outCSP.mManifest_src.Value() = srcs;
|
||||
return;
|
||||
// not supporting REFLECTED_XSS_DIRECTIVE
|
||||
|
||||
case nsIContentSecurityPolicy::BASE_URI_DIRECTIVE:
|
||||
|
|
|
@ -64,8 +64,11 @@ void CSP_LogMessage(const nsAString& aMessage,
|
|||
|
||||
// these strings map to the CSPDirectives in nsIContentSecurityPolicy
|
||||
// NOTE: When implementing a new directive, you will need to add it here but also
|
||||
// add a corresponding entry to the constants in nsIContentSecurityPolicy.idl and
|
||||
// also create an entry for the new directive in nsCSPDirective::toDomCSPStruct().
|
||||
// add a corresponding entry to the constants in nsIContentSecurityPolicy.idl
|
||||
// and also create an entry for the new directive in
|
||||
// nsCSPDirective::toDomCSPStruct() and add it to CSPDictionaries.webidl.
|
||||
// Order of elements below important! Make sure it matches the order as in
|
||||
// nsIContentSecurityPolicy.idl
|
||||
static const char* CSPStrDirectives[] = {
|
||||
"-error-", // NO_DIRECTIVE
|
||||
"default-src", // DEFAULT_SRC_DIRECTIVE
|
||||
|
@ -82,7 +85,8 @@ static const char* CSPStrDirectives[] = {
|
|||
"reflected-xss", // REFLECTED_XSS_DIRECTIVE
|
||||
"base-uri", // BASE_URI_DIRECTIVE
|
||||
"form-action", // FORM_ACTION_DIRECTIVE
|
||||
"referrer" // REFERRER_DIRECTIVE
|
||||
"referrer", // REFERRER_DIRECTIVE
|
||||
"manifest-src" // MANIFEST_SRC_DIRECTIVE
|
||||
};
|
||||
|
||||
inline const char* CSP_CSPDirectiveToString(CSPDirective aDir)
|
||||
|
|
|
@ -439,6 +439,7 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
|
|||
case TYPE_SCRIPT:
|
||||
case TYPE_STYLESHEET:
|
||||
case TYPE_SUBDOCUMENT:
|
||||
case TYPE_WEB_MANIFEST:
|
||||
case TYPE_XBL:
|
||||
case TYPE_XMLHTTPREQUEST:
|
||||
case TYPE_XSLT:
|
||||
|
|
|
@ -24,6 +24,7 @@ dictionary CSP {
|
|||
sequence<DOMString> base-uri;
|
||||
sequence<DOMString> form-action;
|
||||
sequence<DOMString> referrer;
|
||||
sequence<DOMString> manifest-src;
|
||||
};
|
||||
|
||||
dictionary CSPPolicies {
|
||||
|
|
|
@ -66,6 +66,9 @@ partial interface Selection {
|
|||
[ChromeOnly,Throws]
|
||||
attribute boolean interlinePosition;
|
||||
|
||||
[Throws]
|
||||
attribute short? caretBidiLevel;
|
||||
|
||||
[ChromeOnly,Throws]
|
||||
DOMString toStringWithFormat(DOMString formatType, unsigned long flags, long wrapColumn);
|
||||
[ChromeOnly,Throws]
|
||||
|
|
|
@ -1049,21 +1049,22 @@ ServiceWorkerManager::Register(nsIDOMWindow* aWindow,
|
|||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
// XXXnsm Don't allow chrome callers for now, we don't support chrome
|
||||
// ServiceWorkers.
|
||||
MOZ_ASSERT(!nsContentUtils::IsCallerChrome());
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aWindow);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> outerWindow = window->GetOuterWindow();
|
||||
bool serviceWorkersTestingEnabled =
|
||||
outerWindow->GetServiceWorkersTestingEnabled();
|
||||
MOZ_ASSERT(window);
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
|
||||
if (!doc) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Don't allow service workers to register when the *document* is chrome for
|
||||
// now.
|
||||
MOZ_ASSERT(!nsContentUtils::IsSystemPrincipal(doc->NodePrincipal()));
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> outerWindow = window->GetOuterWindow();
|
||||
bool serviceWorkersTestingEnabled =
|
||||
outerWindow->GetServiceWorkersTestingEnabled();
|
||||
|
||||
nsCOMPtr<nsIURI> documentURI = doc->GetBaseURI();
|
||||
|
||||
bool authenticatedOrigin = false;
|
||||
|
@ -1474,15 +1475,18 @@ ServiceWorkerManager::GetRegistrations(nsIDOMWindow* aWindow,
|
|||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aWindow);
|
||||
|
||||
// XXXnsm Don't allow chrome callers for now, we don't support chrome
|
||||
// ServiceWorkers.
|
||||
MOZ_ASSERT(!nsContentUtils::IsCallerChrome());
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aWindow);
|
||||
if (!window) {
|
||||
MOZ_ASSERT(window);
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
|
||||
if (!doc) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Don't allow service workers to register when the *document* is chrome for
|
||||
// now.
|
||||
MOZ_ASSERT(!nsContentUtils::IsSystemPrincipal(doc->NodePrincipal()));
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> sgo = do_QueryInterface(window);
|
||||
ErrorResult result;
|
||||
nsRefPtr<Promise> promise = Promise::Create(sgo, result);
|
||||
|
@ -1575,15 +1579,18 @@ ServiceWorkerManager::GetRegistration(nsIDOMWindow* aWindow,
|
|||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aWindow);
|
||||
|
||||
// XXXnsm Don't allow chrome callers for now, we don't support chrome
|
||||
// ServiceWorkers.
|
||||
MOZ_ASSERT(!nsContentUtils::IsCallerChrome());
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aWindow);
|
||||
if (!window) {
|
||||
MOZ_ASSERT(window);
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
|
||||
if (!doc) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Don't allow service workers to register when the *document* is chrome for
|
||||
// now.
|
||||
MOZ_ASSERT(!nsContentUtils::IsSystemPrincipal(doc->NodePrincipal()));
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> sgo = do_QueryInterface(window);
|
||||
ErrorResult result;
|
||||
nsRefPtr<Promise> promise = Promise::Create(sgo, result);
|
||||
|
@ -1784,15 +1791,18 @@ ServiceWorkerManager::GetReadyPromise(nsIDOMWindow* aWindow,
|
|||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aWindow);
|
||||
|
||||
// XXXnsm Don't allow chrome callers for now, we don't support chrome
|
||||
// ServiceWorkers.
|
||||
MOZ_ASSERT(!nsContentUtils::IsCallerChrome());
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aWindow);
|
||||
if (!window) {
|
||||
MOZ_ASSERT(window);
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
|
||||
if (!doc) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Don't allow service workers to register when the *document* is chrome for
|
||||
// now.
|
||||
MOZ_ASSERT(!nsContentUtils::IsSystemPrincipal(doc->NodePrincipal()));
|
||||
|
||||
MOZ_ASSERT(!mPendingReadyPromises.Contains(window));
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> sgo = do_QueryInterface(window);
|
||||
|
|
|
@ -614,11 +614,13 @@ nsHTMLEditRules::WillDoAction(Selection* aSelection,
|
|||
switch (info->action) {
|
||||
case EditAction::insertText:
|
||||
case EditAction::insertIMEText:
|
||||
UndefineCaretBidiLevel(aSelection);
|
||||
return WillInsertText(info->action, aSelection, aCancel, aHandled,
|
||||
info->inString, info->outString, info->maxLength);
|
||||
case EditAction::loadHTML:
|
||||
return WillLoadHTML(aSelection, aCancel);
|
||||
case EditAction::insertBreak:
|
||||
UndefineCaretBidiLevel(aSelection);
|
||||
return WillInsertBreak(aSelection, aCancel, aHandled);
|
||||
case EditAction::deleteSelection:
|
||||
return WillDeleteSelection(aSelection, info->collapsedAction,
|
||||
|
|
|
@ -252,9 +252,11 @@ nsTextEditRules::WillDoAction(Selection* aSelection,
|
|||
|
||||
switch (info->action) {
|
||||
case EditAction::insertBreak:
|
||||
UndefineCaretBidiLevel(aSelection);
|
||||
return WillInsertBreak(aSelection, aCancel, aHandled, info->maxLength);
|
||||
case EditAction::insertText:
|
||||
case EditAction::insertIMEText:
|
||||
UndefineCaretBidiLevel(aSelection);
|
||||
return WillInsertText(info->action, aSelection, aCancel, aHandled,
|
||||
info->inString, info->outString, info->maxLength);
|
||||
case EditAction::deleteSelection:
|
||||
|
|
|
@ -193,6 +193,8 @@ protected:
|
|||
nsresult CreateMozBR(nsIDOMNode* inParent, int32_t inOffset,
|
||||
nsIDOMNode** outBRNode = nullptr);
|
||||
|
||||
void UndefineCaretBidiLevel(Selection* aSelection);
|
||||
|
||||
nsresult CheckBidiLevelForDeletion(mozilla::dom::Selection* aSelection,
|
||||
nsIDOMNode *aSelNode,
|
||||
int32_t aSelOffset,
|
||||
|
|
|
@ -80,3 +80,19 @@ nsTextEditRules::CheckBidiLevelForDeletion(Selection* aSelection,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsTextEditRules::UndefineCaretBidiLevel(Selection* aSelection)
|
||||
{
|
||||
/**
|
||||
* After inserting text the caret Bidi level must be set to the level of the
|
||||
* inserted text.This is difficult, because we cannot know what the level is
|
||||
* until after the Bidi algorithm is applied to the whole paragraph.
|
||||
*
|
||||
* So we set the caret Bidi level to UNDEFINED here, and the caret code will
|
||||
* set it correctly later
|
||||
*/
|
||||
nsRefPtr<nsFrameSelection> frameSelection = aSelection->GetFrameSelection();
|
||||
if (frameSelection) {
|
||||
frameSelection->UndefineCaretBidiLevel();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,11 @@ static const char *kTypeString[] = {"other",
|
|||
"media",
|
||||
"websocket",
|
||||
"csp_report",
|
||||
"xslt"};
|
||||
"xslt",
|
||||
"beacon",
|
||||
"fetch",
|
||||
"imageset",
|
||||
"manifest"};
|
||||
|
||||
#define NUMBER_OF_TYPES MOZ_ARRAY_LENGTH(kTypeString)
|
||||
uint8_t nsContentBlocker::mBehaviorPref[NUMBER_OF_TYPES];
|
||||
|
|
|
@ -549,8 +549,8 @@ FilterNodeD2D1::Create(ID2D1DeviceContext *aDC, FilterType aType)
|
|||
|
||||
hr = aDC->CreateEffect(GetCLDIDForFilterType(aType), byRef(effect));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
gfxWarning() << "Failed to create effect for FilterType: " << hexa(hr);
|
||||
if (FAILED(hr) || !effect) {
|
||||
gfxCriticalErrorOnce() << "Failed to create effect for FilterType: " << hexa(hr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -227,6 +227,81 @@ Rect Matrix4x4::ProjectRectBounds(const Rect& aRect, const Rect &aClip) const
|
|||
return Rect(min_x, min_y, max_x - min_x, max_y - min_y);
|
||||
}
|
||||
|
||||
size_t
|
||||
Matrix4x4::TransformAndClipRect(const Rect& aRect, const Rect& aClip,
|
||||
Point* aVerts) const
|
||||
{
|
||||
// Initialize a double-buffered array of points in homogenous space with
|
||||
// the input rectangle, aRect.
|
||||
Point4D points[2][kTransformAndClipRectMaxVerts];
|
||||
Point4D* dstPoint = points[0];
|
||||
*dstPoint++ = *this * Point4D(aRect.x, aRect.y, 0, 1);
|
||||
*dstPoint++ = *this * Point4D(aRect.XMost(), aRect.y, 0, 1);
|
||||
*dstPoint++ = *this * Point4D(aRect.XMost(), aRect.YMost(), 0, 1);
|
||||
*dstPoint++ = *this * Point4D(aRect.x, aRect.YMost(), 0, 1);
|
||||
|
||||
// View frustum clipping planes are described as normals originating from
|
||||
// the 0,0,0,0 origin.
|
||||
Point4D planeNormals[4];
|
||||
planeNormals[0] = Point4D(1.0, 0.0, 0.0, -aClip.x);
|
||||
planeNormals[1] = Point4D(-1.0, 0.0, 0.0, aClip.XMost());
|
||||
planeNormals[2] = Point4D(0.0, 1.0, 0.0, -aClip.y);
|
||||
planeNormals[3] = Point4D(0.0, -1.0, 0.0, aClip.YMost());
|
||||
|
||||
// Iterate through each clipping plane and clip the polygon.
|
||||
// In each pass, we double buffer, alternating between points[0] and
|
||||
// points[1].
|
||||
for (int plane=0; plane < 4; plane++) {
|
||||
planeNormals[plane].Normalize();
|
||||
|
||||
Point4D* srcPoint = points[plane & 1];
|
||||
Point4D* srcPointEnd = dstPoint;
|
||||
dstPoint = points[~plane & 1];
|
||||
|
||||
Point4D* prevPoint = srcPointEnd - 1;
|
||||
float prevDot = planeNormals[plane].DotProduct(*prevPoint);
|
||||
while (srcPoint < srcPointEnd) {
|
||||
float nextDot = planeNormals[plane].DotProduct(*srcPoint);
|
||||
|
||||
if ((nextDot >= 0.0) != (prevDot >= 0.0)) {
|
||||
// An intersection with the clipping plane has been detected.
|
||||
// Interpolate to find the intersecting point and emit it.
|
||||
float t = -prevDot / (nextDot - prevDot);
|
||||
*dstPoint++ = *srcPoint * t + *prevPoint * (1.0 - t);
|
||||
}
|
||||
|
||||
if (nextDot >= 0.0) {
|
||||
// Emit any source points that are on the positive side of the
|
||||
// clipping plane.
|
||||
*dstPoint++ = *srcPoint;
|
||||
}
|
||||
|
||||
prevPoint = srcPoint++;
|
||||
prevDot = nextDot;
|
||||
}
|
||||
}
|
||||
|
||||
size_t dstPointCount = 0;
|
||||
size_t srcPointCount = dstPoint - points[0];
|
||||
for (Point4D* srcPoint = points[0]; srcPoint < points[0] + srcPointCount; srcPoint++) {
|
||||
|
||||
Point p;
|
||||
if (srcPoint->w == 0.0) {
|
||||
// If a point lies on the intersection of the clipping planes at
|
||||
// (0,0,0,0), we must avoid a division by zero w component.
|
||||
p = Point(0.0, 0.0);
|
||||
} else {
|
||||
p = srcPoint->As2DPoint();
|
||||
}
|
||||
// Emit only unique points
|
||||
if (dstPointCount == 0 || p != aVerts[dstPointCount - 1]) {
|
||||
aVerts[dstPointCount++] = p;
|
||||
}
|
||||
}
|
||||
|
||||
return dstPointCount;
|
||||
}
|
||||
|
||||
bool
|
||||
Matrix4x4::Invert()
|
||||
{
|
||||
|
|
|
@ -499,6 +499,19 @@ public:
|
|||
|
||||
Rect ProjectRectBounds(const Rect& aRect, const Rect &aClip) const;
|
||||
|
||||
/**
|
||||
* TransformAndClipRect projects a rectangle and clips against view frustum
|
||||
* clipping planes in homogenous space so that its projected vertices are
|
||||
* constrained within the 2d rectangle passed in aClip.
|
||||
* The resulting vertices are populated in aVerts. aVerts must be
|
||||
* pre-allocated to hold at least kTransformAndClipRectMaxVerts Points.
|
||||
* The vertex count is returned by TransformAndClipRect. It is possible to
|
||||
* emit fewer that 3 vertices, indicating that aRect will not be visible
|
||||
* within aClip.
|
||||
*/
|
||||
size_t TransformAndClipRect(const Rect& aRect, const Rect& aClip, Point* aVerts) const;
|
||||
static const size_t kTransformAndClipRectMaxVerts = 32;
|
||||
|
||||
static Matrix4x4 From2D(const Matrix &aMatrix) {
|
||||
Matrix4x4 matrix;
|
||||
matrix._11 = aMatrix._11;
|
||||
|
|
|
@ -297,10 +297,24 @@ public:
|
|||
* drawn is specified by aEffectChain. aRect is the quad to draw, in user space.
|
||||
* aTransform transforms from user space to screen space. If texture coords are
|
||||
* required, these will be in the primary effect in the effect chain.
|
||||
* aVisibleRect is used to determine which edges should be antialiased,
|
||||
* without applying the effect to the inner edges of a tiled layer.
|
||||
*/
|
||||
virtual void DrawQuad(const gfx::Rect& aRect, const gfx::Rect& aClipRect,
|
||||
const EffectChain& aEffectChain,
|
||||
gfx::Float aOpacity, const gfx::Matrix4x4 &aTransform) = 0;
|
||||
gfx::Float aOpacity, const gfx::Matrix4x4& aTransform,
|
||||
const gfx::Rect& aVisibleRect) = 0;
|
||||
|
||||
/**
|
||||
* Overload of DrawQuad, with aVisibleRect defaulted to the value of aRect.
|
||||
* Use this when you are drawing a single quad that is not part of a tiled
|
||||
* layer.
|
||||
*/
|
||||
void DrawQuad(const gfx::Rect& aRect, const gfx::Rect& aClipRect,
|
||||
const EffectChain& aEffectChain,
|
||||
gfx::Float aOpacity, const gfx::Matrix4x4& aTransform) {
|
||||
DrawQuad(aRect, aClipRect, aEffectChain, aOpacity, aTransform, aRect);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear aRect on current render target.
|
||||
|
|
|
@ -178,37 +178,141 @@ private:
|
|||
nsCOMPtr<nsIServerSocket> mServerSocket;
|
||||
};
|
||||
|
||||
// Static class to create and destory LayerScopeWebSocketManager object
|
||||
class WebSocketHelper
|
||||
class DrawSession {
|
||||
public:
|
||||
DrawSession()
|
||||
: mOffsetX(0.0)
|
||||
, mOffsetY(0.0)
|
||||
, mRects(0)
|
||||
{ }
|
||||
|
||||
float mOffsetX;
|
||||
float mOffsetY;
|
||||
gfx::Matrix4x4 mMVMatrix;
|
||||
size_t mRects;
|
||||
gfx::Rect mLayerRects[4];
|
||||
};
|
||||
|
||||
class ContentMonitor {
|
||||
public:
|
||||
using THArray = nsTArray<const TextureHost *>;
|
||||
|
||||
// Notify the content of a TextureHost was changed.
|
||||
void SetChangedHost(const TextureHost* host) {
|
||||
if (THArray::NoIndex == mChangedHosts.IndexOf(host)) {
|
||||
mChangedHosts.AppendElement(host);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear changed flag of a host.
|
||||
void ClearChangedHost(const TextureHost* host) {
|
||||
if (THArray::NoIndex != mChangedHosts.IndexOf(host)) {
|
||||
mChangedHosts.RemoveElement(host);
|
||||
}
|
||||
}
|
||||
|
||||
// Return true iff host is a new one or the content of it had been changed.
|
||||
bool IsChangedOrNew(const TextureHost* host) {
|
||||
if (THArray::NoIndex == mSeenHosts.IndexOf(host)) {
|
||||
mSeenHosts.AppendElement(host);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (decltype(mChangedHosts)::NoIndex != mChangedHosts.IndexOf(host)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Empty() {
|
||||
mSeenHosts.SetLength(0);
|
||||
mChangedHosts.SetLength(0);
|
||||
}
|
||||
private:
|
||||
THArray mSeenHosts;
|
||||
THArray mChangedHosts;
|
||||
};
|
||||
|
||||
// Hold all singleton objects used by LayerScope
|
||||
class LayerScopeManager
|
||||
{
|
||||
public:
|
||||
static void CreateServerSocket()
|
||||
void CreateServerSocket()
|
||||
{
|
||||
// Create Web Server Socket (which has to be on the main thread)
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
|
||||
if (!sWebSocketManager) {
|
||||
sWebSocketManager = new LayerScopeWebSocketManager();
|
||||
// WebSocketManager must be created on the main thread.
|
||||
if (NS_IsMainThread()) {
|
||||
mWebSocketManager = mozilla::MakeUnique<LayerScopeWebSocketManager>();
|
||||
} else {
|
||||
// Dispatch creation to main thread, and make sure we
|
||||
// dispatch this only once after booting
|
||||
static bool dispatched = false;
|
||||
if (dispatched) {
|
||||
return;
|
||||
}
|
||||
|
||||
DebugOnly<nsresult> rv =
|
||||
NS_DispatchToMainThread(new CreateServerSocketRunnable(this));
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv),
|
||||
"Failed to dispatch WebSocket Creation to main thread");
|
||||
dispatched = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void DestroyServerSocket()
|
||||
void DestroyServerSocket()
|
||||
{
|
||||
// Destroy Web Server Socket
|
||||
if (sWebSocketManager) {
|
||||
sWebSocketManager->RemoveAllConnections();
|
||||
if (mWebSocketManager) {
|
||||
mWebSocketManager->RemoveAllConnections();
|
||||
}
|
||||
}
|
||||
|
||||
static LayerScopeWebSocketManager* GetSocketManager()
|
||||
LayerScopeWebSocketManager* GetSocketManager()
|
||||
{
|
||||
return sWebSocketManager;
|
||||
return mWebSocketManager.get();
|
||||
}
|
||||
|
||||
ContentMonitor* GetContentMonitor()
|
||||
{
|
||||
if (!mContentMonitor.get()) {
|
||||
mContentMonitor = mozilla::MakeUnique<ContentMonitor>();
|
||||
}
|
||||
|
||||
return mContentMonitor.get();
|
||||
}
|
||||
|
||||
void NewDrawSession() {
|
||||
mSession = mozilla::MakeUnique<DrawSession>();
|
||||
}
|
||||
|
||||
DrawSession& CurrentSession() {
|
||||
return *mSession;
|
||||
}
|
||||
|
||||
private:
|
||||
static StaticAutoPtr<LayerScopeWebSocketManager> sWebSocketManager;
|
||||
friend class CreateServerSocketRunnable;
|
||||
class CreateServerSocketRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
explicit CreateServerSocketRunnable(LayerScopeManager *aLayerScopeManager)
|
||||
: mLayerScopeManager(aLayerScopeManager)
|
||||
{
|
||||
}
|
||||
NS_IMETHOD Run() {
|
||||
mLayerScopeManager->mWebSocketManager =
|
||||
mozilla::MakeUnique<LayerScopeWebSocketManager>();
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
LayerScopeManager* mLayerScopeManager;
|
||||
};
|
||||
|
||||
mozilla::UniquePtr<LayerScopeWebSocketManager> mWebSocketManager;
|
||||
mozilla::UniquePtr<DrawSession> mSession;
|
||||
mozilla::UniquePtr<ContentMonitor> mContentMonitor;
|
||||
};
|
||||
|
||||
StaticAutoPtr<LayerScopeWebSocketManager> WebSocketHelper::sWebSocketManager;
|
||||
LayerScopeManager gLayerScopeManager;
|
||||
|
||||
/*
|
||||
* DebugGLData is the base class of
|
||||
|
@ -230,13 +334,13 @@ public:
|
|||
|
||||
protected:
|
||||
static bool WriteToStream(Packet& aPacket) {
|
||||
if (!WebSocketHelper::GetSocketManager())
|
||||
if (!gLayerScopeManager.GetSocketManager())
|
||||
return true;
|
||||
|
||||
uint32_t size = aPacket.ByteSize();
|
||||
auto data = MakeUnique<uint8_t[]>(size);
|
||||
aPacket.SerializeToArray(data.get(), size);
|
||||
return WebSocketHelper::GetSocketManager()->WriteAll(data.get(), size);
|
||||
return gLayerScopeManager.GetSocketManager()->WriteAll(data.get(), size);
|
||||
}
|
||||
|
||||
Packet::DataType mDataType;
|
||||
|
@ -290,7 +394,7 @@ public:
|
|||
return WriteToStream(mPacket);
|
||||
}
|
||||
|
||||
bool TryPack() {
|
||||
bool TryPack(bool packData) {
|
||||
android::sp<android::GraphicBuffer> buffer = mState.mSurface;
|
||||
MOZ_ASSERT(buffer.get());
|
||||
|
||||
|
@ -300,16 +404,9 @@ public:
|
|||
tp->set_name(mName);
|
||||
tp->set_target(mTarget);
|
||||
|
||||
int format = buffer->getPixelFormat();
|
||||
if (HAL_PIXEL_FORMAT_RGBA_8888 != format &&
|
||||
HAL_PIXEL_FORMAT_RGBX_8888 != format) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t* grallocData;
|
||||
if (BAD_VALUE == buffer->lock(GRALLOC_USAGE_SW_READ_OFTEN |
|
||||
GRALLOC_USAGE_SW_WRITE_NEVER,
|
||||
reinterpret_cast<void**>(&grallocData))) {
|
||||
int pFormat = buffer->getPixelFormat();
|
||||
if (HAL_PIXEL_FORMAT_RGBA_8888 != pFormat &&
|
||||
HAL_PIXEL_FORMAT_RGBX_8888 != pFormat) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -317,29 +414,44 @@ public:
|
|||
int32_t height = buffer->getHeight();
|
||||
int32_t width = buffer->getWidth();
|
||||
int32_t sourceSize = stride * height;
|
||||
bool ret = false;
|
||||
if (sourceSize <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sourceSize > 0) {
|
||||
auto compressedData = MakeUnique<char[]>(LZ4::maxCompressedSize(sourceSize));
|
||||
uint32_t dFormat = mState.FormatRBSwapped() ?
|
||||
LOCAL_GL_BGRA : LOCAL_GL_RGBA;
|
||||
tp->set_dataformat(dFormat);
|
||||
tp->set_dataformat((1 << 16 | tp->dataformat()));
|
||||
tp->set_width(width);
|
||||
tp->set_height(height);
|
||||
tp->set_stride(stride);
|
||||
|
||||
if (packData) {
|
||||
uint8_t* grallocData = nullptr;
|
||||
if (BAD_VALUE == buffer->lock(GRALLOC_USAGE_SW_READ_OFTEN |
|
||||
GRALLOC_USAGE_SW_WRITE_NEVER,
|
||||
reinterpret_cast<void**>(&grallocData)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Do not return before buffer->unlock();
|
||||
auto compressedData =
|
||||
MakeUnique<char[]>(LZ4::maxCompressedSize(sourceSize));
|
||||
int compressedSize = LZ4::compress((char*)grallocData,
|
||||
sourceSize,
|
||||
compressedData.get());
|
||||
|
||||
if (compressedSize > 0) {
|
||||
uint32_t format = mState.FormatRBSwapped() ?
|
||||
LOCAL_GL_BGRA : LOCAL_GL_RGBA;
|
||||
tp->set_dataformat(format);
|
||||
tp->set_dataformat((1 << 16 | tp->dataformat()));
|
||||
tp->set_width(width);
|
||||
tp->set_height(height);
|
||||
tp->set_stride(stride);
|
||||
tp->set_data(compressedData.get(), compressedSize);
|
||||
ret = true;
|
||||
}
|
||||
} else {
|
||||
buffer->unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer->unlock();
|
||||
}
|
||||
|
||||
buffer->unlock();
|
||||
return ret;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -576,11 +688,12 @@ public:
|
|||
NS_IMETHODIMP OnSocketAccepted(nsIServerSocket *aServ,
|
||||
nsISocketTransport *aTransport) override
|
||||
{
|
||||
if (!WebSocketHelper::GetSocketManager())
|
||||
if (!gLayerScopeManager.GetSocketManager())
|
||||
return NS_OK;
|
||||
|
||||
printf_stderr("*** LayerScope: Accepted connection\n");
|
||||
WebSocketHelper::GetSocketManager()->AddConnection(aTransport);
|
||||
gLayerScopeManager.GetSocketManager()->AddConnection(aTransport);
|
||||
gLayerScopeManager.GetContentMonitor()->Empty();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -619,8 +732,6 @@ public:
|
|||
delete d;
|
||||
}
|
||||
|
||||
/* nsIRunnable impl; send the data */
|
||||
|
||||
NS_IMETHODIMP Run() override {
|
||||
DebugGLData *d;
|
||||
nsresult rv = NS_OK;
|
||||
|
@ -636,7 +747,7 @@ public:
|
|||
Cleanup();
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
WebSocketHelper::DestroyServerSocket();
|
||||
gLayerScopeManager.DestroyServerSocket();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -649,15 +760,6 @@ protected:
|
|||
NS_IMPL_ISUPPORTS(DebugDataSender, nsIRunnable);
|
||||
|
||||
|
||||
class CreateServerSocketRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
NS_IMETHOD Run() {
|
||||
WebSocketHelper::CreateServerSocket();
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* LayerScope SendXXX Structure
|
||||
* 1. SendLayer
|
||||
|
@ -799,7 +901,7 @@ SenderHelper::SendColor(void* aLayerRef,
|
|||
int aWidth,
|
||||
int aHeight)
|
||||
{
|
||||
WebSocketHelper::GetSocketManager()->AppendDebugData(
|
||||
gLayerScopeManager.GetSocketManager()->AppendDebugData(
|
||||
new DebugGLColorData(aLayerRef, aColor, aWidth, aHeight));
|
||||
}
|
||||
|
||||
|
@ -848,7 +950,7 @@ SenderHelper::SendTextureSource(GLContext* aGLContext,
|
|||
aGLContext->ReadTexImageHelper()->ReadTexImage(0, textureTarget,
|
||||
size,
|
||||
shaderConfig, aFlipY);
|
||||
WebSocketHelper::GetSocketManager()->AppendDebugData(
|
||||
gLayerScopeManager.GetSocketManager()->AppendDebugData(
|
||||
new DebugGLTextureData(aGLContext, aLayerRef, textureTarget,
|
||||
aTexID, img));
|
||||
|
||||
|
@ -869,13 +971,19 @@ SenderHelper::SendGraphicBuffer(void* aLayerRef,
|
|||
mozilla::UniquePtr<DebugGLGraphicBuffer> package =
|
||||
MakeUnique<DebugGLGraphicBuffer>(aLayerRef, target, aTexID, aEffect->mState);
|
||||
|
||||
if (!package->TryPack()) {
|
||||
// The texure content in this TexureHost is not altered,
|
||||
// we don't need to send it again.
|
||||
bool changed = gLayerScopeManager.GetContentMonitor()->IsChangedOrNew(
|
||||
aEffect->mState.mTexture);
|
||||
if (!package->TryPack(changed)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Transfer ownership to SocketManager.
|
||||
WebSocketHelper::GetSocketManager()->AppendDebugData(package.release());
|
||||
gLayerScopeManager.GetSocketManager()->AppendDebugData(package.release());
|
||||
sTextureIdList.push_back(aTexID);
|
||||
|
||||
gLayerScopeManager.GetContentMonitor()->ClearChangedHost(aEffect->mState.mTexture);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
@ -897,9 +1005,10 @@ SenderHelper::SendTexturedEffect(GLContext* aGLContext,
|
|||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
if (SendGraphicBuffer(aLayerRef, source, texID, aEffect)) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
// Fallback texture sending path.
|
||||
// Render to texture and read pixels back.
|
||||
SendTextureSource(aGLContext, aLayerRef, source, texID, false);
|
||||
}
|
||||
|
@ -976,6 +1085,16 @@ SenderHelper::SendEffectChain(GLContext* aGLContext,
|
|||
// TODO:
|
||||
}
|
||||
|
||||
void
|
||||
LayerScope::ContentChanged(TextureHost *host)
|
||||
{
|
||||
if (!CheckSendable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
gLayerScopeManager.GetContentMonitor()->SetChangedHost(host);
|
||||
}
|
||||
|
||||
// ----------------------------------------------
|
||||
// LayerScopeWebSocketHandler implementation
|
||||
// ----------------------------------------------
|
||||
|
@ -1383,7 +1502,7 @@ LayerScopeWebSocketHandler::HandleDataFrame(uint8_t *aData,
|
|||
void
|
||||
LayerScopeWebSocketHandler::CloseConnection()
|
||||
{
|
||||
WebSocketHelper::GetSocketManager()->CleanDebugData();
|
||||
gLayerScopeManager.GetSocketManager()->CleanDebugData();
|
||||
if (mInputStream) {
|
||||
mInputStream->AsyncWait(nullptr, 0, 0, nullptr);
|
||||
mInputStream = nullptr;
|
||||
|
@ -1453,56 +1572,9 @@ LayerScope::Init()
|
|||
return;
|
||||
}
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
WebSocketHelper::CreateServerSocket();
|
||||
} else {
|
||||
// Dispatch creation to main thread, and make sure we
|
||||
// dispatch this only once after booting
|
||||
static bool dispatched = false;
|
||||
if (dispatched) {
|
||||
return;
|
||||
}
|
||||
DebugOnly<nsresult> rv = NS_DispatchToMainThread(new CreateServerSocketRunnable());
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed to dispatch WebSocket Creation to main thread");
|
||||
dispatched = true;
|
||||
}
|
||||
gLayerScopeManager.CreateServerSocket();
|
||||
}
|
||||
|
||||
class DrawSession {
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(DrawSession)
|
||||
|
||||
DrawSession()
|
||||
: mOffsetX(0.0),
|
||||
mOffsetY(0.0),
|
||||
mRects(0)
|
||||
{ }
|
||||
|
||||
float mOffsetX;
|
||||
float mOffsetY;
|
||||
gfx::Matrix4x4 mMVMatrix;
|
||||
size_t mRects;
|
||||
gfx::Rect mLayerRects[4];
|
||||
private:
|
||||
~DrawSession() {}
|
||||
};
|
||||
|
||||
class DrawSessionHolder {
|
||||
public:
|
||||
static void setSession(DrawSession *aSession) {
|
||||
mSession = aSession;
|
||||
}
|
||||
|
||||
static DrawSession& current() {
|
||||
return *mSession;
|
||||
}
|
||||
|
||||
private:
|
||||
static nsRefPtr<DrawSession> mSession;
|
||||
};
|
||||
|
||||
nsRefPtr<DrawSession> DrawSessionHolder::mSession;
|
||||
|
||||
void
|
||||
LayerScope::DrawBegin()
|
||||
{
|
||||
|
@ -1510,7 +1582,7 @@ LayerScope::DrawBegin()
|
|||
return;
|
||||
}
|
||||
|
||||
DrawSessionHolder::setSession(new DrawSession());
|
||||
gLayerScopeManager.NewDrawSession();
|
||||
}
|
||||
|
||||
void LayerScope::SetRenderOffset(float aX, float aY)
|
||||
|
@ -1519,8 +1591,8 @@ void LayerScope::SetRenderOffset(float aX, float aY)
|
|||
return;
|
||||
}
|
||||
|
||||
DrawSessionHolder::current().mOffsetX = aX;
|
||||
DrawSessionHolder::current().mOffsetY = aY;
|
||||
gLayerScopeManager.CurrentSession().mOffsetX = aX;
|
||||
gLayerScopeManager.CurrentSession().mOffsetY = aY;
|
||||
}
|
||||
|
||||
void LayerScope::SetLayerTransform(const gfx::Matrix4x4& aMatrix)
|
||||
|
@ -1529,7 +1601,7 @@ void LayerScope::SetLayerTransform(const gfx::Matrix4x4& aMatrix)
|
|||
return;
|
||||
}
|
||||
|
||||
DrawSessionHolder::current().mMVMatrix = aMatrix;
|
||||
gLayerScopeManager.CurrentSession().mMVMatrix = aMatrix;
|
||||
}
|
||||
|
||||
void LayerScope::SetLayerRects(size_t aRects, const gfx::Rect* aLayerRects)
|
||||
|
@ -1541,10 +1613,10 @@ void LayerScope::SetLayerRects(size_t aRects, const gfx::Rect* aLayerRects)
|
|||
MOZ_ASSERT(aRects > 0 && aRects <= 4);
|
||||
MOZ_ASSERT(aLayerRects);
|
||||
|
||||
DrawSessionHolder::current().mRects = aRects;
|
||||
gLayerScopeManager.CurrentSession().mRects = aRects;
|
||||
|
||||
for (size_t i = 0; i < aRects; i++){
|
||||
DrawSessionHolder::current().mLayerRects[i] = aLayerRects[i];
|
||||
gLayerScopeManager.CurrentSession().mLayerRects[i] = aLayerRects[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1561,8 +1633,8 @@ LayerScope::DrawEnd(gl::GLContext* aGLContext,
|
|||
|
||||
// 1. Send parameters of draw call, such as uniforms and attributes of
|
||||
// vertex adnd fragment shader.
|
||||
DrawSession& draws = DrawSessionHolder::current();
|
||||
WebSocketHelper::GetSocketManager()->AppendDebugData(
|
||||
DrawSession& draws = gLayerScopeManager.CurrentSession();
|
||||
gLayerScopeManager.GetSocketManager()->AppendDebugData(
|
||||
new DebugGLDrawData(draws.mOffsetX, draws.mOffsetY,
|
||||
draws.mMVMatrix, draws.mRects,
|
||||
draws.mLayerRects,
|
||||
|
@ -1591,7 +1663,7 @@ LayerScope::SendLayerDump(UniquePtr<Packet> aPacket)
|
|||
if (!CheckSendable() || !SenderHelper::GetLayersTreeSendable()) {
|
||||
return;
|
||||
}
|
||||
WebSocketHelper::GetSocketManager()->AppendDebugData(
|
||||
gLayerScopeManager.GetSocketManager()->AppendDebugData(
|
||||
new DebugGLLayersData(Move(aPacket)));
|
||||
}
|
||||
|
||||
|
@ -1604,11 +1676,11 @@ LayerScope::CheckSendable()
|
|||
if (!gfxPrefs::LayerScopeEnabled()) {
|
||||
return false;
|
||||
}
|
||||
if (!WebSocketHelper::GetSocketManager()) {
|
||||
if (!gLayerScopeManager.GetSocketManager()) {
|
||||
Init();
|
||||
return false;
|
||||
}
|
||||
if (!WebSocketHelper::GetSocketManager()->IsConnected()) {
|
||||
if (!gLayerScopeManager.GetSocketManager()->IsConnected()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -1618,7 +1690,7 @@ void
|
|||
LayerScope::CleanLayer()
|
||||
{
|
||||
if (CheckSendable()) {
|
||||
WebSocketHelper::GetSocketManager()->CleanDebugData();
|
||||
gLayerScopeManager.GetSocketManager()->CleanDebugData();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1626,7 +1698,7 @@ void
|
|||
LayerScope::SetHWComposed()
|
||||
{
|
||||
if (CheckSendable()) {
|
||||
WebSocketHelper::GetSocketManager()->AppendDebugData(
|
||||
gLayerScopeManager.GetSocketManager()->AppendDebugData(
|
||||
new DebugGLMetaData(Packet::META, true));
|
||||
}
|
||||
}
|
||||
|
@ -1655,7 +1727,7 @@ LayerScopeAutoFrame::BeginFrame(int64_t aFrameStamp)
|
|||
return;
|
||||
}
|
||||
|
||||
WebSocketHelper::GetSocketManager()->AppendDebugData(
|
||||
gLayerScopeManager.GetSocketManager()->AppendDebugData(
|
||||
new DebugGLFrameStatusData(Packet::FRAMESTART, aFrameStamp));
|
||||
}
|
||||
|
||||
|
@ -1666,9 +1738,9 @@ LayerScopeAutoFrame::EndFrame()
|
|||
return;
|
||||
}
|
||||
|
||||
WebSocketHelper::GetSocketManager()->AppendDebugData(
|
||||
gLayerScopeManager.GetSocketManager()->AppendDebugData(
|
||||
new DebugGLFrameStatusData(Packet::FRAMEEND));
|
||||
WebSocketHelper::GetSocketManager()->DispatchDebugData();
|
||||
gLayerScopeManager.GetSocketManager()->DispatchDebugData();
|
||||
}
|
||||
|
||||
} /* layers */
|
||||
|
|
|
@ -40,6 +40,7 @@ public:
|
|||
static void CleanLayer();
|
||||
static void SetHWComposed();
|
||||
|
||||
static void ContentChanged(TextureHost *host);
|
||||
private:
|
||||
static void Init();
|
||||
};
|
||||
|
|
|
@ -297,7 +297,7 @@ DIBTextureHost::DIBTextureHost(TextureFlags aFlags,
|
|||
}
|
||||
|
||||
void
|
||||
DIBTextureHost::Updated(const nsIntRegion* aRegion)
|
||||
DIBTextureHost::UpdatedInternal(const nsIntRegion* aRegion)
|
||||
{
|
||||
if (!mCompositor) {
|
||||
// This can happen if we send textures to a compositable that isn't yet
|
||||
|
@ -331,7 +331,7 @@ TextureHostFileMapping::~TextureHostFileMapping()
|
|||
}
|
||||
|
||||
void
|
||||
TextureHostFileMapping::Updated(const nsIntRegion* aRegion)
|
||||
TextureHostFileMapping::UpdatedInternal(const nsIntRegion* aRegion)
|
||||
{
|
||||
if (!mCompositor) {
|
||||
// This can happen if we send textures to a compositable that isn't yet
|
||||
|
|
|
@ -155,14 +155,14 @@ public:
|
|||
DIBTextureHost(TextureFlags aFlags,
|
||||
const SurfaceDescriptorDIB& aDescriptor);
|
||||
|
||||
virtual void Updated(const nsIntRegion* aRegion = nullptr) override;
|
||||
|
||||
virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() override
|
||||
{
|
||||
return nullptr; // TODO: cf bug 872568
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void UpdatedInternal(const nsIntRegion* aRegion = nullptr) override;
|
||||
|
||||
nsRefPtr<gfxWindowsSurface> mSurface;
|
||||
};
|
||||
|
||||
|
@ -173,8 +173,6 @@ public:
|
|||
const SurfaceDescriptorFileMapping& aDescriptor);
|
||||
~TextureHostFileMapping();
|
||||
|
||||
virtual void Updated(const nsIntRegion* aRegion = nullptr) override;
|
||||
|
||||
virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() override
|
||||
{
|
||||
MOZ_CRASH(); // Not implemented! It would be tricky to keep track of the
|
||||
|
@ -183,6 +181,8 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
virtual void UpdatedInternal(const nsIntRegion* aRegion = nullptr) override;
|
||||
|
||||
HANDLE mFileMapping;
|
||||
};
|
||||
|
||||
|
|
|
@ -541,7 +541,7 @@ TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& newValidRegion,
|
|||
#ifdef DEBUG
|
||||
int currTileX = floor_div(x - newBufferOrigin.x, scaledTileSize.width);
|
||||
int currTileY = floor_div(y - newBufferOrigin.y, scaledTileSize.height);
|
||||
int index = currTileX * mRetainedHeight + currTileY;
|
||||
int index = TileIndex(currTileX, currTileY);
|
||||
// If allocating a tile failed we can run into this assertion.
|
||||
// Rendering is going to be glitchy but we don't want to crash.
|
||||
NS_ASSERTION(!newValidRegion.Intersects(tileRect) ||
|
||||
|
@ -556,7 +556,7 @@ TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& newValidRegion,
|
|||
|
||||
int tileX = floor_div(x - newBufferOrigin.x, scaledTileSize.width);
|
||||
int tileY = floor_div(y - newBufferOrigin.y, scaledTileSize.height);
|
||||
int index = tileX * mRetainedHeight + tileY;
|
||||
int index = TileIndex(tileX, tileY);
|
||||
MOZ_ASSERT(index >= 0 &&
|
||||
static_cast<unsigned>(index) < newRetainedTiles.Length(),
|
||||
"index out of range");
|
||||
|
|
|
@ -323,7 +323,8 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect,
|
|||
const gfx::Rect& aClipRect,
|
||||
const EffectChain &aEffectChain,
|
||||
gfx::Float aOpacity,
|
||||
const gfx::Matrix4x4 &aTransform)
|
||||
const gfx::Matrix4x4& aTransform,
|
||||
const gfx::Rect& aVisibleRect)
|
||||
{
|
||||
RefPtr<DrawTarget> buffer = mRenderTarget->mDrawTarget;
|
||||
|
||||
|
|
|
@ -84,7 +84,8 @@ public:
|
|||
const gfx::Rect& aClipRect,
|
||||
const EffectChain &aEffectChain,
|
||||
gfx::Float aOpacity,
|
||||
const gfx::Matrix4x4 &aTransform) override;
|
||||
const gfx::Matrix4x4& aTransform,
|
||||
const gfx::Rect& aVisibleRect) override;
|
||||
|
||||
virtual void ClearRect(const gfx::Rect& aRect) override;
|
||||
|
||||
|
|
|
@ -128,6 +128,7 @@ CompositableClient::CompositableClient(CompositableForwarder* aForwarder,
|
|||
: mCompositableChild(nullptr)
|
||||
, mForwarder(aForwarder)
|
||||
, mTextureFlags(aTextureFlags)
|
||||
, mDestroyed(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(CompositableClient);
|
||||
}
|
||||
|
@ -169,6 +170,8 @@ CompositableClient::Connect()
|
|||
void
|
||||
CompositableClient::Destroy()
|
||||
{
|
||||
mDestroyed = true;
|
||||
|
||||
if (!mCompositableChild) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -149,6 +149,8 @@ public:
|
|||
|
||||
void Destroy();
|
||||
|
||||
bool IsDestroyed() { return mDestroyed; }
|
||||
|
||||
PCompositableChild* GetIPDLActor() const;
|
||||
|
||||
// should only be called by a CompositableForwarder
|
||||
|
@ -232,6 +234,7 @@ protected:
|
|||
// Some layers may want to enforce some flags to all their textures
|
||||
// (like disallowing tiling)
|
||||
TextureFlags mTextureFlags;
|
||||
bool mDestroyed;
|
||||
RefPtr<TextureClientRecycleAllocator> mTextureClientRecycler;
|
||||
|
||||
friend class CompositableChild;
|
||||
|
|
|
@ -540,6 +540,7 @@ protected:
|
|||
{
|
||||
MOZ_COUNT_DTOR(TiledContentClient);
|
||||
|
||||
mDestroyed = true;
|
||||
mTiledBuffer.Release();
|
||||
mLowPrecisionTiledBuffer.Release();
|
||||
}
|
||||
|
|
|
@ -353,6 +353,13 @@ TextureHost::PrintInfo(std::stringstream& aStream, const char* aPrefix)
|
|||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
TextureHost::Updated(const nsIntRegion* aRegion)
|
||||
{
|
||||
LayerScope::ContentChanged(this);
|
||||
UpdatedInternal(aRegion);
|
||||
}
|
||||
|
||||
TextureSource::TextureSource()
|
||||
: mCompositableCount(0)
|
||||
{
|
||||
|
@ -401,7 +408,7 @@ BufferTextureHost::~BufferTextureHost()
|
|||
{}
|
||||
|
||||
void
|
||||
BufferTextureHost::Updated(const nsIntRegion* aRegion)
|
||||
BufferTextureHost::UpdatedInternal(const nsIntRegion* aRegion)
|
||||
{
|
||||
++mUpdateSerial;
|
||||
// If the last frame wasn't uploaded yet, and we -don't- have a partial update,
|
||||
|
|
|
@ -388,7 +388,7 @@ public:
|
|||
* @param aRegion The region that has been changed, if nil, it means that the
|
||||
* entire surface should be updated.
|
||||
*/
|
||||
virtual void Updated(const nsIntRegion* aRegion = nullptr) {}
|
||||
void Updated(const nsIntRegion* aRegion = nullptr);
|
||||
|
||||
/**
|
||||
* Sets this TextureHost's compositor.
|
||||
|
@ -538,6 +538,8 @@ protected:
|
|||
|
||||
void RecycleTexture(TextureFlags aFlags);
|
||||
|
||||
virtual void UpdatedInternal(const nsIntRegion *Region) {}
|
||||
|
||||
PTextureParent* mActor;
|
||||
TextureFlags mFlags;
|
||||
int mCompositableCount;
|
||||
|
@ -570,8 +572,6 @@ public:
|
|||
|
||||
virtual size_t GetBufferSize() = 0;
|
||||
|
||||
virtual void Updated(const nsIntRegion* aRegion = nullptr) override;
|
||||
|
||||
virtual bool Lock() override;
|
||||
|
||||
virtual void Unlock() override;
|
||||
|
@ -603,6 +603,8 @@ protected:
|
|||
|
||||
void InitSize();
|
||||
|
||||
virtual void UpdatedInternal(const nsIntRegion* aRegion = nullptr) override;
|
||||
|
||||
RefPtr<Compositor> mCompositor;
|
||||
RefPtr<DataTextureSource> mFirstSource;
|
||||
nsIntRegion mMaybeUpdatedRegion;
|
||||
|
|
|
@ -213,8 +213,8 @@ TiledLayerBufferComposite::UseTiles(const SurfaceDescriptorTiles& aTiles,
|
|||
|
||||
if (tile.mTextureHost && !tile.mTextureHost->HasInternalBuffer()) {
|
||||
MOZ_ASSERT(tile.mSharedLock);
|
||||
int tileX = i % oldRetainedWidth + oldFirstTileX;
|
||||
int tileY = i / oldRetainedWidth + oldFirstTileY;
|
||||
int tileX = i / oldRetainedHeight + oldFirstTileX;
|
||||
int tileY = i % oldRetainedHeight + oldFirstTileY;
|
||||
|
||||
if (tileX >= newFirstTileX && tileY >= newFirstTileY &&
|
||||
tileX < (newFirstTileX + newRetainedWidth) &&
|
||||
|
@ -237,8 +237,8 @@ TiledLayerBufferComposite::UseTiles(const SurfaceDescriptorTiles& aTiles,
|
|||
// they should be with the new retained with and height rather than the
|
||||
// old one.
|
||||
for (size_t i = 0; i < tileDescriptors.Length(); i++) {
|
||||
int tileX = i % newRetainedWidth + newFirstTileX;
|
||||
int tileY = i / newRetainedWidth + newFirstTileY;
|
||||
int tileX = i / newRetainedHeight + newFirstTileX;
|
||||
int tileY = i % newRetainedHeight + newFirstTileY;
|
||||
|
||||
// First, get the already existing tiles to the right place in the array,
|
||||
// and use placeholders where there was no tiles.
|
||||
|
@ -247,8 +247,8 @@ TiledLayerBufferComposite::UseTiles(const SurfaceDescriptorTiles& aTiles,
|
|||
tileY >= (oldFirstTileY + oldRetainedHeight)) {
|
||||
mRetainedTiles[i] = GetPlaceholderTile();
|
||||
} else {
|
||||
mRetainedTiles[i] = oldTiles[(tileY - oldFirstTileY) * oldRetainedWidth +
|
||||
(tileX - oldFirstTileX)];
|
||||
mRetainedTiles[i] = oldTiles[(tileX - oldFirstTileX) * oldRetainedHeight +
|
||||
(tileY - oldFirstTileY)];
|
||||
// If we hit this assertion it means we probably mixed something up in the
|
||||
// logic that tries to reuse tiles on the compositor side. It is most likely
|
||||
// benign, but we are missing some fast paths so let's try to make it not happen.
|
||||
|
@ -334,8 +334,8 @@ TiledLayerBufferComposite::UseTiles(const SurfaceDescriptorTiles& aTiles,
|
|||
}
|
||||
}
|
||||
|
||||
tile.x = i % newRetainedWidth + newFirstTileX;
|
||||
tile.y = i / newRetainedWidth + newFirstTileY;
|
||||
tile.x = i / newRetainedHeight + newFirstTileX;
|
||||
tile.y = i % newRetainedHeight + newFirstTileY;
|
||||
}
|
||||
|
||||
mFirstTileX = newFirstTileX;
|
||||
|
@ -435,7 +435,8 @@ TiledContentHost::RenderTile(TileHost& aTile,
|
|||
const gfx::Rect& aClipRect,
|
||||
const nsIntRegion& aScreenRegion,
|
||||
const IntPoint& aTextureOffset,
|
||||
const nsIntSize& aTextureBounds)
|
||||
const nsIntSize& aTextureBounds,
|
||||
const gfx::Rect& aVisibleRect)
|
||||
{
|
||||
if (aTile.IsPlaceholderTile()) {
|
||||
// This shouldn't ever happen, but let's fail semi-gracefully. No need
|
||||
|
@ -490,7 +491,7 @@ TiledContentHost::RenderTile(TileHost& aTile,
|
|||
textureRect.y / aTextureBounds.height,
|
||||
textureRect.width / aTextureBounds.width,
|
||||
textureRect.height / aTextureBounds.height);
|
||||
mCompositor->DrawQuad(graphicsRect, aClipRect, aEffectChain, aOpacity, aTransform);
|
||||
mCompositor->DrawQuad(graphicsRect, aClipRect, aEffectChain, aOpacity, aTransform, aVisibleRect);
|
||||
}
|
||||
DiagnosticFlags flags = DiagnosticFlags::CONTENT | DiagnosticFlags::TILE;
|
||||
if (aTile.mTextureHostOnWhite) {
|
||||
|
@ -582,7 +583,9 @@ TiledContentHost::RenderLayerBuffer(TiledLayerBufferComposite& aLayerBuffer,
|
|||
gfx::IntSize tileSize = aLayerBuffer.GetTileSize();
|
||||
RenderTile(tileTexture, aBackgroundColor, aEffectChain, aOpacity, aTransform,
|
||||
aFilter, aClipRect, tileDrawRegion, tileOffset,
|
||||
nsIntSize(tileSize.width, tileSize.height));
|
||||
nsIntSize(tileSize.width, tileSize.height),
|
||||
gfx::Rect(visibleRect.x, visibleRect.y,
|
||||
visibleRect.width, visibleRect.height));
|
||||
if (tileTexture.mTextureHostOnWhite) {
|
||||
componentAlphaDiagnostic = DiagnosticFlags::COMPONENT_ALPHA;
|
||||
}
|
||||
|
|
|
@ -283,7 +283,8 @@ private:
|
|||
const gfx::Rect& aClipRect,
|
||||
const nsIntRegion& aScreenRegion,
|
||||
const gfx::IntPoint& aTextureOffset,
|
||||
const gfx::IntSize& aTextureBounds);
|
||||
const gfx::IntSize& aTextureBounds,
|
||||
const gfx::Rect& aVisibleRect);
|
||||
|
||||
void EnsureTileStore() {}
|
||||
|
||||
|
|
|
@ -741,7 +741,8 @@ CompositorD3D11::DrawQuad(const gfx::Rect& aRect,
|
|||
const gfx::Rect& aClipRect,
|
||||
const EffectChain& aEffectChain,
|
||||
gfx::Float aOpacity,
|
||||
const gfx::Matrix4x4& aTransform)
|
||||
const gfx::Matrix4x4& aTransform,
|
||||
const gfx::Rect& aVisibleRect)
|
||||
{
|
||||
if (mCurrentClip.IsEmpty()) {
|
||||
return;
|
||||
|
@ -1023,7 +1024,7 @@ CompositorD3D11::BeginFrame(const nsIntRegion& aInvalidRegion,
|
|||
|
||||
// Failed to create a render target or the view.
|
||||
if (!mDefaultRT || !mDefaultRT->mRTView ||
|
||||
mSize.width == 0 || mSize.height == 0) {
|
||||
mSize.width <= 0 || mSize.height <= 0) {
|
||||
*aRenderBoundsOut = Rect();
|
||||
return;
|
||||
}
|
||||
|
@ -1092,6 +1093,10 @@ CompositorD3D11::EndFrame()
|
|||
|
||||
nsIntSize oldSize = mSize;
|
||||
EnsureSize();
|
||||
if (mSize.width <= 0 || mSize.height <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
UINT presentInterval = 0;
|
||||
|
||||
if (gfxWindowsPlatform::GetPlatform()->IsWARP()) {
|
||||
|
@ -1180,6 +1185,7 @@ CompositorD3D11::VerifyBufferSize()
|
|||
|
||||
hr = mSwapChain->GetDesc(&swapDesc);
|
||||
if (Failed(hr)) {
|
||||
gfxCriticalError() << "Failed to get the description " << hexa(hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1210,12 +1216,20 @@ void
|
|||
CompositorD3D11::UpdateRenderTarget()
|
||||
{
|
||||
EnsureSize();
|
||||
VerifyBufferSize();
|
||||
if (!VerifyBufferSize()) {
|
||||
gfxCriticalError(gfxCriticalError::DefaultOptions(false)) << "Failed VerifyBufferSize in UpdateRenderTarget";
|
||||
return;
|
||||
}
|
||||
|
||||
if (mDefaultRT) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mSize.width <= 0 || mSize.height <= 0) {
|
||||
gfxCriticalError(gfxCriticalError::DefaultOptions(false)) << "Invalid size in UpdateRenderTarget " << mSize;
|
||||
return;
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
nsRefPtr<ID3D11Texture2D> backBuf;
|
||||
|
|
|
@ -94,7 +94,8 @@ public:
|
|||
const gfx::Rect &aClipRect,
|
||||
const EffectChain &aEffectChain,
|
||||
gfx::Float aOpacity,
|
||||
const gfx::Matrix4x4 &aTransform) override;
|
||||
const gfx::Matrix4x4& aTransform,
|
||||
const gfx::Rect& aVisibleRect) override;
|
||||
|
||||
/* Helper for when the primary effect is VR_DISTORTION */
|
||||
void DrawVRDistortion(const gfx::Rect &aRect,
|
||||
|
|
|
@ -241,7 +241,8 @@ CompositorD3D9::DrawQuad(const gfx::Rect &aRect,
|
|||
const gfx::Rect &aClipRect,
|
||||
const EffectChain &aEffectChain,
|
||||
gfx::Float aOpacity,
|
||||
const gfx::Matrix4x4 &aTransform)
|
||||
const gfx::Matrix4x4& aTransform,
|
||||
const gfx::Rect& aVisibleRect)
|
||||
{
|
||||
if (!mDeviceManager) {
|
||||
return;
|
||||
|
|
|
@ -57,7 +57,8 @@ public:
|
|||
const gfx::Rect &aClipRect,
|
||||
const EffectChain &aEffectChain,
|
||||
gfx::Float aOpacity,
|
||||
const gfx::Matrix4x4 &aTransform) override;
|
||||
const gfx::Matrix4x4& aTransform,
|
||||
const gfx::Rect& aVisibleRect) override;
|
||||
|
||||
virtual void BeginFrame(const nsIntRegion& aInvalidRegion,
|
||||
const gfx::Rect *aClipRectIn,
|
||||
|
|
|
@ -914,7 +914,7 @@ DataTextureSourceD3D9::UpdateFromTexture(IDirect3DTexture9* aTexture,
|
|||
}
|
||||
|
||||
void
|
||||
TextureHostD3D9::Updated(const nsIntRegion* aRegion)
|
||||
TextureHostD3D9::UpdatedInternal(const nsIntRegion* aRegion)
|
||||
{
|
||||
MOZ_ASSERT(mTexture);
|
||||
if (!mTexture) {
|
||||
|
|
|
@ -308,8 +308,6 @@ public:
|
|||
|
||||
virtual void Unlock() override;
|
||||
|
||||
virtual void Updated(const nsIntRegion* aRegion) override;
|
||||
|
||||
virtual gfx::IntSize GetSize() const override { return mSize; }
|
||||
|
||||
virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() override
|
||||
|
@ -323,6 +321,8 @@ protected:
|
|||
TextureHostD3D9(TextureFlags aFlags);
|
||||
IDirect3DDevice9* GetDevice();
|
||||
|
||||
virtual void UpdatedInternal(const nsIntRegion* aRegion) override;
|
||||
|
||||
RefPtr<DataTextureSourceD3D9> mTextureSource;
|
||||
RefPtr<IDirect3DTexture9> mTexture;
|
||||
RefPtr<CompositorD3D9> mCompositor;
|
||||
|
|
|
@ -428,7 +428,7 @@ ShadowLayerForwarder::RemoveTextureFromCompositableAsync(AsyncTransactionTracker
|
|||
CompositableClient* aCompositable,
|
||||
TextureClient* aTexture)
|
||||
{
|
||||
if (mTxn->Opened()) {
|
||||
if (mTxn->Opened() && !aCompositable->IsDestroyed()) {
|
||||
mTxn->AddEdit(OpRemoveTextureAsync(CompositableClient::GetTrackersHolderId(aCompositable->GetIPDLActor()),
|
||||
aAsyncTransactionTracker->GetId(),
|
||||
nullptr, aCompositable->GetIPDLActor(),
|
||||
|
|
|
@ -47,7 +47,7 @@ EXPORTS += [
|
|||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
SOURCES += [
|
||||
'D3D11ShareHandleImage.cpp',
|
||||
'D3D11ShareHandleImage.cpp',
|
||||
]
|
||||
UNIFIED_SOURCES += [
|
||||
'D3D9SurfaceImage.cpp',
|
||||
|
|
|
@ -87,7 +87,7 @@ CompositorOGL::CompositorOGL(nsIWidget *aWidget, int aSurfaceWidth,
|
|||
, mUseExternalSurfaceSize(aUseExternalSurfaceSize)
|
||||
, mFrameInProgress(false)
|
||||
, mDestroyed(false)
|
||||
, mHeight(0)
|
||||
, mViewportSize(0, 0)
|
||||
, mCurrentProgram(nullptr)
|
||||
{
|
||||
MOZ_COUNT_CTOR(CompositorOGL);
|
||||
|
@ -441,7 +441,7 @@ CompositorOGL::PrepareViewport(const gfx::IntSize& aSize)
|
|||
// Set the viewport correctly.
|
||||
mGLContext->fViewport(0, 0, aSize.width, aSize.height);
|
||||
|
||||
mHeight = aSize.height;
|
||||
mViewportSize = aSize;
|
||||
|
||||
// We flip the view matrix around so that everything is right-side up; we're
|
||||
// drawing directly into the window's back buffer, so this keeps things
|
||||
|
@ -575,7 +575,7 @@ void
|
|||
CompositorOGL::ClearRect(const gfx::Rect& aRect)
|
||||
{
|
||||
// Map aRect to OGL coordinates, origin:bottom-left
|
||||
GLint y = mHeight - (aRect.y + aRect.height);
|
||||
GLint y = mViewportSize.height - (aRect.y + aRect.height);
|
||||
|
||||
ScopedGLState scopedScissorTestState(mGLContext, LOCAL_GL_SCISSOR_TEST, true);
|
||||
ScopedScissorRect autoScissorRect(mGLContext, aRect.x, y, aRect.width, aRect.height);
|
||||
|
@ -770,7 +770,8 @@ ShaderConfigOGL
|
|||
CompositorOGL::GetShaderConfigFor(Effect *aEffect,
|
||||
MaskType aMask,
|
||||
gfx::CompositionOp aOp,
|
||||
bool aColorMatrix) const
|
||||
bool aColorMatrix,
|
||||
bool aDEAAEnabled) const
|
||||
{
|
||||
ShaderConfigOGL config;
|
||||
|
||||
|
@ -821,6 +822,7 @@ CompositorOGL::GetShaderConfigFor(Effect *aEffect,
|
|||
config.SetColorMatrix(aColorMatrix);
|
||||
config.SetMask2D(aMask == MaskType::Mask2d);
|
||||
config.SetMask3D(aMask == MaskType::Mask3d);
|
||||
config.SetDEAA(aDEAAEnabled);
|
||||
return config;
|
||||
}
|
||||
|
||||
|
@ -902,12 +904,41 @@ static bool SetBlendMode(GLContext* aGL, gfx::CompositionOp aBlendMode, bool aIs
|
|||
return true;
|
||||
}
|
||||
|
||||
gfx::Point3D
|
||||
CompositorOGL::GetLineCoefficients(const gfx::Point& aPoint1,
|
||||
const gfx::Point& aPoint2)
|
||||
{
|
||||
// Return standard coefficients for a line between aPoint1 and aPoint2
|
||||
// for standard line equation:
|
||||
//
|
||||
// Ax + By + C = 0
|
||||
//
|
||||
// A = (p1.y – p2.y)
|
||||
// B = (p2.x – p1.x)
|
||||
// C = (p1.x * p2.y) – (p2.x * p1.y)
|
||||
|
||||
gfx::Point3D coeffecients;
|
||||
coeffecients.x = aPoint1.y - aPoint2.y;
|
||||
coeffecients.y = aPoint2.x - aPoint1.x;
|
||||
coeffecients.z = aPoint1.x * aPoint2.y - aPoint2.x * aPoint1.y;
|
||||
|
||||
coeffecients *= 1.0f / sqrtf(coeffecients.x * coeffecients.x +
|
||||
coeffecients.y * coeffecients.y);
|
||||
|
||||
// Offset outwards by 0.5 pixel as the edge is considered to be 1 pixel
|
||||
// wide and included within the interior of the polygon
|
||||
coeffecients.z += 0.5f;
|
||||
|
||||
return coeffecients;
|
||||
}
|
||||
|
||||
void
|
||||
CompositorOGL::DrawQuad(const Rect& aRect,
|
||||
const Rect& aClipRect,
|
||||
const EffectChain &aEffectChain,
|
||||
Float aOpacity,
|
||||
const gfx::Matrix4x4 &aTransform)
|
||||
const gfx::Matrix4x4& aTransform,
|
||||
const gfx::Rect& aVisibleRect)
|
||||
{
|
||||
PROFILER_LABEL("CompositorOGL", "DrawQuad",
|
||||
js::ProfileEntry::Category::GRAPHICS);
|
||||
|
@ -1000,8 +1031,15 @@ CompositorOGL::DrawQuad(const Rect& aRect,
|
|||
blendMode = blendEffect->mBlendMode;
|
||||
}
|
||||
|
||||
// Only apply DEAA to quads that have been transformed such that aliasing
|
||||
// could be visible
|
||||
bool bEnableAA = gfxPrefs::LayersDEAAEnabled() &&
|
||||
!aTransform.Is2DIntegerTranslation();
|
||||
|
||||
bool colorMatrix = aEffectChain.mSecondaryEffects[EffectTypes::COLOR_MATRIX];
|
||||
ShaderConfigOGL config = GetShaderConfigFor(aEffectChain.mPrimaryEffect, maskType, blendMode, colorMatrix);
|
||||
ShaderConfigOGL config = GetShaderConfigFor(aEffectChain.mPrimaryEffect,
|
||||
maskType, blendMode, colorMatrix,
|
||||
bEnableAA);
|
||||
config.SetOpacity(aOpacity != 1.f);
|
||||
ShaderProgramOGL *program = GetShaderProgramFor(config);
|
||||
ActivateProgram(program);
|
||||
|
@ -1028,6 +1066,74 @@ CompositorOGL::DrawQuad(const Rect& aRect,
|
|||
program->SetTexCoordMultiplier(source->GetSize().width, source->GetSize().height);
|
||||
}
|
||||
|
||||
// XXX kip - These calculations could be performed once per layer rather than
|
||||
// for every tile. This might belong in Compositor.cpp once DEAA
|
||||
// is implemented for DirectX.
|
||||
if (bEnableAA) {
|
||||
// Calculate the transformed vertices of aVisibleRect in screen space
|
||||
// pixels, mirroring the calculations in the vertex shader
|
||||
Matrix4x4 flatTransform = aTransform;
|
||||
flatTransform.PostTranslate(-offset.x, -offset.y, 0.0f);
|
||||
flatTransform *= mProjMatrix;
|
||||
|
||||
Rect viewportClip = Rect(-1.0f, -1.0f, 2.0f, 2.0f);
|
||||
size_t edgeCount = 0;
|
||||
Point3D coefficients[4];
|
||||
|
||||
Point points[Matrix4x4::kTransformAndClipRectMaxVerts];
|
||||
size_t pointCount = flatTransform.TransformAndClipRect(aVisibleRect, viewportClip, points);
|
||||
for (size_t i = 0; i < pointCount; i++) {
|
||||
points[i] = Point((points[i].x * 0.5f + 0.5f) * mViewportSize.width,
|
||||
(points[i].y * 0.5f + 0.5f) * mViewportSize.height);
|
||||
}
|
||||
if (pointCount > 2) {
|
||||
// Use shoelace formula on a triangle in the clipped quad to determine if
|
||||
// winding order is reversed. Iterate through the triangles until one is
|
||||
// found with a non-zero area.
|
||||
float winding = 0.0f;
|
||||
size_t wp = 0;
|
||||
while (winding == 0.0f && wp < pointCount) {
|
||||
int wp1 = (wp + 1) % pointCount;
|
||||
int wp2 = (wp + 2) % pointCount;
|
||||
winding = (points[wp1].x - points[wp].x) * (points[wp1].y + points[wp].y) +
|
||||
(points[wp2].x - points[wp1].x) * (points[wp2].y + points[wp1].y) +
|
||||
(points[wp].x - points[wp2].x) * (points[wp].y + points[wp2].y);
|
||||
wp++;
|
||||
}
|
||||
bool frontFacing = winding >= 0.0f;
|
||||
|
||||
// Calculate the line coefficients used by the DEAA shader to determine the
|
||||
// sub-pixel coverage of the edge pixels
|
||||
for (size_t i=0; i<pointCount; i++) {
|
||||
const Point& p1 = points[i];
|
||||
const Point& p2 = points[(i + 1) % pointCount];
|
||||
// Create a DEAA edge for any non-straight lines, to a maximum of 4
|
||||
if (p1.x != p2.x && p1.y != p2.y && edgeCount < 4) {
|
||||
if (frontFacing) {
|
||||
coefficients[edgeCount++] = GetLineCoefficients(p2, p1);
|
||||
} else {
|
||||
coefficients[edgeCount++] = GetLineCoefficients(p1, p2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The coefficients that are not needed must not cull any fragments.
|
||||
// We fill these unused coefficients with a clipping plane that has no
|
||||
// effect.
|
||||
for (size_t i = edgeCount; i < 4; i++) {
|
||||
coefficients[i] = Point3D(0.0f, 1.0f, mViewportSize.height);
|
||||
}
|
||||
|
||||
// Set uniforms required by DEAA shader
|
||||
Matrix4x4 transformInverted = aTransform;
|
||||
transformInverted.Invert();
|
||||
program->SetLayerTransformInverse(transformInverted);
|
||||
program->SetDEAAEdges(coefficients);
|
||||
program->SetVisibleCenter(aVisibleRect.Center());
|
||||
program->SetViewportSize(mViewportSize);
|
||||
}
|
||||
|
||||
bool didSetBlendMode = false;
|
||||
|
||||
switch (aEffectChain.mPrimaryEffect->mType) {
|
||||
|
@ -1126,9 +1232,7 @@ CompositorOGL::DrawQuad(const Rect& aRect,
|
|||
program->SetTextureUnit(0);
|
||||
|
||||
if (maskType != MaskType::MaskNone) {
|
||||
sourceMask->BindTexture(LOCAL_GL_TEXTURE1, gfx::Filter::LINEAR);
|
||||
program->SetMaskTextureUnit(1);
|
||||
program->SetMaskLayerTransform(maskQuadTransform);
|
||||
BindMaskForProgram(program, sourceMask, LOCAL_GL_TEXTURE1, maskQuadTransform);
|
||||
}
|
||||
|
||||
if (config.mFeatures & ENABLE_TEXTURE_RECT) {
|
||||
|
|
|
@ -229,7 +229,8 @@ public:
|
|||
const gfx::Rect& aClipRect,
|
||||
const EffectChain &aEffectChain,
|
||||
gfx::Float aOpacity,
|
||||
const gfx::Matrix4x4 &aTransform) override;
|
||||
const gfx::Matrix4x4& aTransform,
|
||||
const gfx::Rect& aVisibleRect) override;
|
||||
|
||||
virtual void EndFrame() override;
|
||||
virtual void SetDispAcquireFence(Layer* aLayer) override;
|
||||
|
@ -335,7 +336,7 @@ private:
|
|||
gfx::Matrix4x4 mProjMatrix;
|
||||
|
||||
/** The size of the surface we are rendering to */
|
||||
nsIntSize mSurfaceSize;
|
||||
gfx::IntSize mSurfaceSize;
|
||||
|
||||
ScreenPoint mRenderOffset;
|
||||
|
||||
|
@ -387,7 +388,8 @@ private:
|
|||
ShaderConfigOGL GetShaderConfigFor(Effect *aEffect,
|
||||
MaskType aMask = MaskType::MaskNone,
|
||||
gfx::CompositionOp aOp = gfx::CompositionOp::OP_OVER,
|
||||
bool aColorMatrix = false) const;
|
||||
bool aColorMatrix = false,
|
||||
bool aDEAAEnabled = false) const;
|
||||
ShaderProgramOGL* GetShaderProgramFor(const ShaderConfigOGL &aConfig);
|
||||
|
||||
/**
|
||||
|
@ -418,7 +420,8 @@ private:
|
|||
const gfx::Rect& aRect,
|
||||
const gfx::Rect& aTexCoordRect,
|
||||
TextureSource *aTexture);
|
||||
|
||||
gfx::Point3D GetLineCoefficients(const gfx::Point& aPoint1,
|
||||
const gfx::Point& aPoint2);
|
||||
void ActivateProgram(ShaderProgramOGL *aProg);
|
||||
void CleanupResources();
|
||||
|
||||
|
@ -437,7 +440,7 @@ private:
|
|||
* y-axis pointing downwards, for good reason as Web pages are typically
|
||||
* scrolled downwards. So, some flipping has to take place; FlippedY does it.
|
||||
*/
|
||||
GLint FlipY(GLint y) const { return mHeight - y; }
|
||||
GLint FlipY(GLint y) const { return mViewportSize.height - y; }
|
||||
|
||||
RefPtr<CompositorTexturePoolOGL> mTexturePool;
|
||||
|
||||
|
@ -446,10 +449,10 @@ private:
|
|||
bool mDestroyed;
|
||||
|
||||
/**
|
||||
* Height of the OpenGL context's primary framebuffer in pixels. Used by
|
||||
* FlipY for the y-flipping calculation.
|
||||
* Size of the OpenGL context's primary framebuffer in pixels. Used by
|
||||
* FlipY for the y-flipping calculation and by the DEAA shader.
|
||||
*/
|
||||
GLint mHeight;
|
||||
gfx::IntSize mViewportSize;
|
||||
|
||||
FenceHandle mReleaseFenceHandle;
|
||||
ShaderProgramOGL *mCurrentProgram;
|
||||
|
|
|
@ -24,8 +24,6 @@ public:
|
|||
|
||||
virtual ~GrallocTextureHostOGL();
|
||||
|
||||
virtual void Updated(const nsIntRegion* aRegion) override {}
|
||||
|
||||
virtual bool Lock() override;
|
||||
|
||||
virtual void Unlock() override;
|
||||
|
|
|
@ -30,6 +30,7 @@ AddUniforms(ProgramProfileOGL& aProfile)
|
|||
// This needs to be kept in sync with the KnownUniformName enum
|
||||
static const char *sKnownUniformNames[] = {
|
||||
"uLayerTransform",
|
||||
"uLayerTransformInverse",
|
||||
"uMaskTransform",
|
||||
"uLayerRects",
|
||||
"uMatrixProj",
|
||||
|
@ -53,6 +54,9 @@ AddUniforms(ProgramProfileOGL& aProfile)
|
|||
"uBlurOffset",
|
||||
"uBlurAlpha",
|
||||
"uBlurGaussianKernel",
|
||||
"uSSEdges",
|
||||
"uViewportSize",
|
||||
"uVisibleCenter",
|
||||
nullptr
|
||||
};
|
||||
|
||||
|
@ -142,6 +146,12 @@ ShaderConfigOGL::SetPremultiply(bool aEnabled)
|
|||
SetFeature(ENABLE_PREMULTIPLY, aEnabled);
|
||||
}
|
||||
|
||||
void
|
||||
ShaderConfigOGL::SetDEAA(bool aEnabled)
|
||||
{
|
||||
SetFeature(ENABLE_DEAA, aEnabled);
|
||||
}
|
||||
|
||||
/* static */ ProgramProfileOGL
|
||||
ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig)
|
||||
{
|
||||
|
@ -153,8 +163,13 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig)
|
|||
vs << "uniform mat4 uMatrixProj;" << endl;
|
||||
vs << "uniform vec4 uLayerRects[4];" << endl;
|
||||
vs << "uniform mat4 uLayerTransform;" << endl;
|
||||
vs << "uniform vec4 uRenderTargetOffset;" << endl;
|
||||
|
||||
if (aConfig.mFeatures & ENABLE_DEAA) {
|
||||
vs << "uniform mat4 uLayerTransformInverse;" << endl;
|
||||
vs << "uniform vec3 uSSEdges[4];" << endl;
|
||||
vs << "uniform vec2 uVisibleCenter;" << endl;
|
||||
vs << "uniform vec2 uViewportSize;" << endl;
|
||||
}
|
||||
vs << "uniform vec2 uRenderTargetOffset;" << endl;
|
||||
vs << "attribute vec4 aCoord;" << endl;
|
||||
|
||||
if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) {
|
||||
|
@ -174,27 +189,78 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig)
|
|||
vs << " vec4 layerRect = uLayerRects[vertexID];" << endl;
|
||||
vs << " vec4 finalPosition = vec4(aCoord.xy * layerRect.zw + layerRect.xy, 0.0, 1.0);" << endl;
|
||||
vs << " finalPosition = uLayerTransform * finalPosition;" << endl;
|
||||
vs << " finalPosition.xyz /= finalPosition.w;" << endl;
|
||||
|
||||
if (aConfig.mFeatures & ENABLE_MASK_3D) {
|
||||
vs << " vMaskCoord.xy = (uMaskTransform * vec4(finalPosition.xyz, 1.0)).xy;" << endl;
|
||||
// correct for perspective correct interpolation, see comment in D3D10 shader
|
||||
vs << " vMaskCoord.z = 1.0;" << endl;
|
||||
vs << " vMaskCoord *= finalPosition.w;" << endl;
|
||||
} else if (aConfig.mFeatures & ENABLE_MASK_2D) {
|
||||
vs << " vMaskCoord.xy = (uMaskTransform * finalPosition).xy;" << endl;
|
||||
}
|
||||
if (aConfig.mFeatures & ENABLE_DEAA) {
|
||||
// XXX kip - The DEAA shader could be made simpler if we switch to
|
||||
// using dynamic vertex buffers instead of sending everything
|
||||
// in through uniforms. This would enable passing information
|
||||
// about how to dilate each vertex explicitly and eliminate the
|
||||
// need to extrapolate this with the sub-pixel coverage
|
||||
// calculation in the vertex shader.
|
||||
|
||||
vs << " finalPosition = finalPosition - uRenderTargetOffset;" << endl;
|
||||
vs << " finalPosition.xyz *= finalPosition.w;" << endl;
|
||||
vs << " finalPosition = uMatrixProj * finalPosition;" << endl;
|
||||
// Calculate the screen space position of this vertex, in screen pixels
|
||||
vs << " vec4 ssPos = finalPosition;" << endl;
|
||||
vs << " ssPos.xy -= uRenderTargetOffset * finalPosition.w;" << endl;
|
||||
vs << " ssPos = uMatrixProj * ssPos;" << endl;
|
||||
vs << " ssPos.xy = ((ssPos.xy/ssPos.w)*0.5+0.5)*uViewportSize;" << endl;
|
||||
|
||||
if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) {
|
||||
if (aConfig.mFeatures & ENABLE_MASK_2D ||
|
||||
aConfig.mFeatures & ENABLE_MASK_3D ||
|
||||
!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) {
|
||||
vs << " vec4 coordAdjusted;" << endl;
|
||||
vs << " coordAdjusted.xy = aCoord.xy;" << endl;
|
||||
}
|
||||
|
||||
// It is necessary to dilate edges away from uVisibleCenter to ensure that
|
||||
// fragments with less than 50% sub-pixel coverage will be shaded.
|
||||
// This offset is applied when the sub-pixel coverage of the vertex is
|
||||
// less than 100%. Expanding by 0.5 pixels in screen space is sufficient
|
||||
// to include these pixels.
|
||||
vs << " if (dot(uSSEdges[0], vec3(ssPos.xy, 1.0)) < 1.5 ||" << endl;
|
||||
vs << " dot(uSSEdges[1], vec3(ssPos.xy, 1.0)) < 1.5 ||" << endl;
|
||||
vs << " dot(uSSEdges[2], vec3(ssPos.xy, 1.0)) < 1.5 ||" << endl;
|
||||
vs << " dot(uSSEdges[3], vec3(ssPos.xy, 1.0)) < 1.5) {" << endl;
|
||||
// If the shader reaches this branch, then this vertex is on the edge of
|
||||
// the layer's visible rect and should be dilated away from the center of
|
||||
// the visible rect. We don't want to hit this for inner facing
|
||||
// edges between tiles, as the pixels may be covered twice without clipping
|
||||
// against uSSEdges. If all edges were dilated, it would result in
|
||||
// artifacts visible within semi-transparent layers with multiple tiles.
|
||||
vs << " vec4 visibleCenter = uLayerTransform * vec4(uVisibleCenter, 0.0, 1.0);" << endl;
|
||||
vs << " vec2 dilateDir = finalPosition.xy / finalPosition.w - visibleCenter.xy / visibleCenter.w;" << endl;
|
||||
vs << " vec2 offset = sign(dilateDir) * 0.5;" << endl;
|
||||
vs << " finalPosition.xy += offset * finalPosition.w;" << endl;
|
||||
if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) {
|
||||
// We must adjust the texture coordinates to compensate for the dilation
|
||||
vs << " coordAdjusted = uLayerTransformInverse * finalPosition;" << endl;
|
||||
vs << " coordAdjusted /= coordAdjusted.w;" << endl;
|
||||
vs << " coordAdjusted.xy -= layerRect.xy;" << endl;
|
||||
vs << " coordAdjusted.xy /= layerRect.zw;" << endl;
|
||||
}
|
||||
vs << " }" << endl;
|
||||
|
||||
if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) {
|
||||
vs << " vec4 textureRect = uTextureRects[vertexID];" << endl;
|
||||
vs << " vec2 texCoord = coordAdjusted.xy * textureRect.zw + textureRect.xy;" << endl;
|
||||
vs << " vTexCoord = (uTextureTransform * vec4(texCoord, 0.0, 1.0)).xy;" << endl;
|
||||
}
|
||||
|
||||
} else if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) {
|
||||
vs << " vec4 textureRect = uTextureRects[vertexID];" << endl;
|
||||
vs << " vec2 texCoord = aCoord.xy * textureRect.zw + textureRect.xy;" << endl;
|
||||
vs << " vTexCoord = (uTextureTransform * vec4(texCoord, 0.0, 1.0)).xy;" << endl;
|
||||
}
|
||||
|
||||
if (aConfig.mFeatures & ENABLE_MASK_2D ||
|
||||
aConfig.mFeatures & ENABLE_MASK_3D) {
|
||||
vs << " vMaskCoord.xy = (uMaskTransform * (finalPosition / finalPosition.w)).xy;" << endl;
|
||||
if (aConfig.mFeatures & ENABLE_MASK_3D) {
|
||||
// correct for perspective correct interpolation, see comment in D3D10 shader
|
||||
vs << " vMaskCoord.z = 1.0;" << endl;
|
||||
vs << " vMaskCoord *= finalPosition.w;" << endl;
|
||||
}
|
||||
}
|
||||
vs << " finalPosition.xy -= uRenderTargetOffset * finalPosition.w;" << endl;
|
||||
vs << " finalPosition = uMatrixProj * finalPosition;" << endl;
|
||||
vs << " gl_Position = finalPosition;" << endl;
|
||||
vs << "}" << endl;
|
||||
|
||||
|
@ -261,6 +327,10 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig)
|
|||
fs << "uniform sampler2D uMaskTexture;" << endl;
|
||||
}
|
||||
|
||||
if (aConfig.mFeatures & ENABLE_DEAA) {
|
||||
fs << "uniform vec3 uSSEdges[4];" << endl;
|
||||
}
|
||||
|
||||
if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) {
|
||||
fs << "vec4 sample(vec2 coord) {" << endl;
|
||||
fs << " vec4 color;" << endl;
|
||||
|
@ -353,6 +423,16 @@ For [0,1] instead of [0,255], and to 5 places:
|
|||
fs << " color.rgb *= color.a;" << endl;
|
||||
}
|
||||
}
|
||||
if (aConfig.mFeatures & ENABLE_DEAA) {
|
||||
// Calculate the sub-pixel coverage of the pixel and modulate its opacity
|
||||
// by that amount to perform DEAA.
|
||||
fs << " vec3 ssPos = vec3(gl_FragCoord.xy, 1.0);" << endl;
|
||||
fs << " float deaaCoverage = clamp(dot(uSSEdges[0], ssPos), 0.0, 1.0);" << endl;
|
||||
fs << " deaaCoverage *= clamp(dot(uSSEdges[1], ssPos), 0.0, 1.0);" << endl;
|
||||
fs << " deaaCoverage *= clamp(dot(uSSEdges[2], ssPos), 0.0, 1.0);" << endl;
|
||||
fs << " deaaCoverage *= clamp(dot(uSSEdges[3], ssPos), 0.0, 1.0);" << endl;
|
||||
fs << " color *= deaaCoverage;" << endl;
|
||||
}
|
||||
if (aConfig.mFeatures & ENABLE_MASK_3D) {
|
||||
fs << " vec2 maskCoords = vMaskCoord.xy / vMaskCoord.z;" << endl;
|
||||
fs << " COLOR_PRECISION float mask = texture2D(uMaskTexture, maskCoords).r;" << endl;
|
||||
|
|
|
@ -40,7 +40,8 @@ enum ShaderFeatures {
|
|||
ENABLE_COLOR_MATRIX=0x200,
|
||||
ENABLE_MASK_2D=0x400,
|
||||
ENABLE_MASK_3D=0x800,
|
||||
ENABLE_PREMULTIPLY=0x1000
|
||||
ENABLE_PREMULTIPLY=0x1000,
|
||||
ENABLE_DEAA=0x2000
|
||||
};
|
||||
|
||||
class KnownUniform {
|
||||
|
@ -50,6 +51,7 @@ public:
|
|||
NotAKnownUniform = -1,
|
||||
|
||||
LayerTransform = 0,
|
||||
LayerTransformInverse,
|
||||
MaskTransform,
|
||||
LayerRects,
|
||||
MatrixProj,
|
||||
|
@ -73,6 +75,9 @@ public:
|
|||
BlurOffset,
|
||||
BlurAlpha,
|
||||
BlurGaussianKernel,
|
||||
SSEdges,
|
||||
ViewportSize,
|
||||
VisibleCenter,
|
||||
|
||||
KnownUniformCount
|
||||
};
|
||||
|
@ -163,6 +168,30 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool UpdateArrayUniform(int cnt, const gfx::Point3D* points) {
|
||||
if (mLocation == -1) return false;
|
||||
if (cnt > 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float fp[12];
|
||||
float *d = fp;
|
||||
for(int i=0; i < cnt; i++) {
|
||||
// Note: Do not want to make assumptions about .x, .y, .z member packing.
|
||||
// If gfx::Point3D is updated to make this guarantee, SIMD optimizations
|
||||
// may be possible
|
||||
*d++ = points[i].x;
|
||||
*d++ = points[i].y;
|
||||
*d++ = points[i].z;
|
||||
}
|
||||
|
||||
if (memcmp(mValue.f16v, fp, sizeof(float) * cnt * 3) != 0) {
|
||||
memcpy(mValue.f16v, fp, sizeof(float) * cnt * 3);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
KnownUniformName mName;
|
||||
const char *mNameString;
|
||||
int32_t mLocation;
|
||||
|
@ -192,6 +221,7 @@ public:
|
|||
void SetMask2D(bool aEnabled);
|
||||
void SetMask3D(bool aEnabled);
|
||||
void SetPremultiply(bool aEnabled);
|
||||
void SetDEAA(bool aEnabled);
|
||||
|
||||
bool operator< (const ShaderConfigOGL& other) const {
|
||||
return mFeatures < other.mFeatures;
|
||||
|
@ -303,10 +333,28 @@ public:
|
|||
SetMatrixUniform(KnownUniform::LayerTransform, aMatrix);
|
||||
}
|
||||
|
||||
void SetLayerTransformInverse(const gfx::Matrix4x4& aMatrix) {
|
||||
SetMatrixUniform(KnownUniform::LayerTransformInverse, aMatrix);
|
||||
}
|
||||
|
||||
void SetMaskLayerTransform(const gfx::Matrix4x4& aMatrix) {
|
||||
SetMatrixUniform(KnownUniform::MaskTransform, aMatrix);
|
||||
}
|
||||
|
||||
void SetDEAAEdges(const gfx::Point3D* aEdges) {
|
||||
SetArrayUniform(KnownUniform::SSEdges, 4, aEdges);
|
||||
}
|
||||
|
||||
void SetViewportSize(const gfx::IntSize& aSize) {
|
||||
float vals[2] = { (float)aSize.width, (float)aSize.height };
|
||||
SetUniform(KnownUniform::ViewportSize, 2, vals);
|
||||
}
|
||||
|
||||
void SetVisibleCenter(const gfx::Point& aVisibleCenter) {
|
||||
float vals[2] = { aVisibleCenter.x, aVisibleCenter.y };
|
||||
SetUniform(KnownUniform::VisibleCenter, 2, vals);
|
||||
}
|
||||
|
||||
void SetLayerRects(const gfx::Rect* aRects) {
|
||||
float vals[16] = { aRects[0].x, aRects[0].y, aRects[0].width, aRects[0].height,
|
||||
aRects[1].x, aRects[1].y, aRects[1].width, aRects[1].height,
|
||||
|
@ -333,13 +381,13 @@ public:
|
|||
}
|
||||
|
||||
void SetRenderOffset(const nsIntPoint& aOffset) {
|
||||
float vals[4] = { float(aOffset.x), float(aOffset.y), 0.0f, 0.0f };
|
||||
SetUniform(KnownUniform::RenderTargetOffset, 4, vals);
|
||||
float vals[4] = { float(aOffset.x), float(aOffset.y) };
|
||||
SetUniform(KnownUniform::RenderTargetOffset, 2, vals);
|
||||
}
|
||||
|
||||
void SetRenderOffset(float aX, float aY) {
|
||||
float vals[4] = { aX, aY, 0.0f, 0.0f };
|
||||
SetUniform(KnownUniform::RenderTargetOffset, 4, vals);
|
||||
float vals[2] = { aX, aY };
|
||||
SetUniform(KnownUniform::RenderTargetOffset, 2, vals);
|
||||
}
|
||||
|
||||
void SetLayerOpacity(float aOpacity) {
|
||||
|
@ -497,6 +545,17 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
void SetArrayUniform(KnownUniform::KnownUniformName aKnownUniform, int aLength, const gfx::Point3D *aPointValues)
|
||||
{
|
||||
ASSERT_THIS_PROGRAM;
|
||||
NS_ASSERTION(aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount, "Invalid known uniform");
|
||||
|
||||
KnownUniform& ku(mProfile.mUniforms[aKnownUniform]);
|
||||
if (ku.UpdateArrayUniform(aLength, aPointValues)) {
|
||||
mGL->fUniform3fv(ku.mLocation, aLength, ku.mValue.f16v);
|
||||
}
|
||||
}
|
||||
|
||||
void SetUniform(KnownUniform::KnownUniformName aKnownUniform, GLint aIntValue) {
|
||||
ASSERT_THIS_PROGRAM;
|
||||
NS_ASSERTION(aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount, "Invalid known uniform");
|
||||
|
|
|
@ -102,64 +102,82 @@ namespace FilterWrappers {
|
|||
Unpremultiply(DrawTarget* aDT, FilterNode* aInput)
|
||||
{
|
||||
RefPtr<FilterNode> filter = aDT->CreateFilter(FilterType::UNPREMULTIPLY);
|
||||
filter->SetInput(IN_UNPREMULTIPLY_IN, aInput);
|
||||
return filter.forget();
|
||||
if (filter) {
|
||||
filter->SetInput(IN_UNPREMULTIPLY_IN, aInput);
|
||||
return filter.forget();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static TemporaryRef<FilterNode>
|
||||
Premultiply(DrawTarget* aDT, FilterNode* aInput)
|
||||
{
|
||||
RefPtr<FilterNode> filter = aDT->CreateFilter(FilterType::PREMULTIPLY);
|
||||
filter->SetInput(IN_PREMULTIPLY_IN, aInput);
|
||||
return filter.forget();
|
||||
if (filter) {
|
||||
filter->SetInput(IN_PREMULTIPLY_IN, aInput);
|
||||
return filter.forget();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static TemporaryRef<FilterNode>
|
||||
LinearRGBToSRGB(DrawTarget* aDT, FilterNode* aInput)
|
||||
{
|
||||
RefPtr<FilterNode> transfer = aDT->CreateFilter(FilterType::DISCRETE_TRANSFER);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_DISABLE_R, false);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_TABLE_R, glinearRGBTosRGBMap, 256);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_DISABLE_G, false);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_TABLE_G, glinearRGBTosRGBMap, 256);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_DISABLE_B, false);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_TABLE_B, glinearRGBTosRGBMap, 256);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_DISABLE_A, true);
|
||||
transfer->SetInput(IN_DISCRETE_TRANSFER_IN, aInput);
|
||||
return transfer.forget();
|
||||
if (transfer) {
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_DISABLE_R, false);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_TABLE_R, glinearRGBTosRGBMap, 256);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_DISABLE_G, false);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_TABLE_G, glinearRGBTosRGBMap, 256);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_DISABLE_B, false);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_TABLE_B, glinearRGBTosRGBMap, 256);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_DISABLE_A, true);
|
||||
transfer->SetInput(IN_DISCRETE_TRANSFER_IN, aInput);
|
||||
return transfer.forget();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static TemporaryRef<FilterNode>
|
||||
SRGBToLinearRGB(DrawTarget* aDT, FilterNode* aInput)
|
||||
{
|
||||
RefPtr<FilterNode> transfer = aDT->CreateFilter(FilterType::DISCRETE_TRANSFER);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_DISABLE_R, false);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_TABLE_R, gsRGBToLinearRGBMap, 256);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_DISABLE_G, false);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_TABLE_G, gsRGBToLinearRGBMap, 256);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_DISABLE_B, false);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_TABLE_B, gsRGBToLinearRGBMap, 256);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_DISABLE_A, true);
|
||||
transfer->SetInput(IN_DISCRETE_TRANSFER_IN, aInput);
|
||||
return transfer.forget();
|
||||
if (transfer) {
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_DISABLE_R, false);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_TABLE_R, gsRGBToLinearRGBMap, 256);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_DISABLE_G, false);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_TABLE_G, gsRGBToLinearRGBMap, 256);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_DISABLE_B, false);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_TABLE_B, gsRGBToLinearRGBMap, 256);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_DISABLE_A, true);
|
||||
transfer->SetInput(IN_DISCRETE_TRANSFER_IN, aInput);
|
||||
return transfer.forget();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static TemporaryRef<FilterNode>
|
||||
Crop(DrawTarget* aDT, FilterNode* aInputFilter, const IntRect& aRect)
|
||||
{
|
||||
RefPtr<FilterNode> filter = aDT->CreateFilter(FilterType::CROP);
|
||||
filter->SetAttribute(ATT_CROP_RECT, Rect(aRect));
|
||||
filter->SetInput(IN_CROP_IN, aInputFilter);
|
||||
return filter.forget();
|
||||
if (filter) {
|
||||
filter->SetAttribute(ATT_CROP_RECT, Rect(aRect));
|
||||
filter->SetInput(IN_CROP_IN, aInputFilter);
|
||||
return filter.forget();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static TemporaryRef<FilterNode>
|
||||
Offset(DrawTarget* aDT, FilterNode* aInputFilter, const IntPoint& aOffset)
|
||||
{
|
||||
RefPtr<FilterNode> filter = aDT->CreateFilter(FilterType::TRANSFORM);
|
||||
filter->SetAttribute(ATT_TRANSFORM_MATRIX, Matrix::Translation(aOffset.x, aOffset.y));
|
||||
filter->SetInput(IN_TRANSFORM_IN, aInputFilter);
|
||||
return filter.forget();
|
||||
if (filter) {
|
||||
filter->SetAttribute(ATT_TRANSFORM_MATRIX, Matrix::Translation(aOffset.x, aOffset.y));
|
||||
filter->SetInput(IN_TRANSFORM_IN, aInputFilter);
|
||||
return filter.forget();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static TemporaryRef<FilterNode>
|
||||
|
@ -169,27 +187,36 @@ namespace FilterWrappers {
|
|||
float stdY = float(std::min(aStdDeviation.height, kMaxStdDeviation));
|
||||
if (stdX == stdY) {
|
||||
RefPtr<FilterNode> filter = aDT->CreateFilter(FilterType::GAUSSIAN_BLUR);
|
||||
filter->SetAttribute(ATT_GAUSSIAN_BLUR_STD_DEVIATION, stdX);
|
||||
filter->SetInput(IN_GAUSSIAN_BLUR_IN, aInputFilter);
|
||||
return filter.forget();
|
||||
if (filter) {
|
||||
filter->SetAttribute(ATT_GAUSSIAN_BLUR_STD_DEVIATION, stdX);
|
||||
filter->SetInput(IN_GAUSSIAN_BLUR_IN, aInputFilter);
|
||||
return filter.forget();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
RefPtr<FilterNode> filterH = aDT->CreateFilter(FilterType::DIRECTIONAL_BLUR);
|
||||
RefPtr<FilterNode> filterV = aDT->CreateFilter(FilterType::DIRECTIONAL_BLUR);
|
||||
filterH->SetAttribute(ATT_DIRECTIONAL_BLUR_DIRECTION, (uint32_t)BLUR_DIRECTION_X);
|
||||
filterH->SetAttribute(ATT_DIRECTIONAL_BLUR_STD_DEVIATION, stdX);
|
||||
filterV->SetAttribute(ATT_DIRECTIONAL_BLUR_DIRECTION, (uint32_t)BLUR_DIRECTION_Y);
|
||||
filterV->SetAttribute(ATT_DIRECTIONAL_BLUR_STD_DEVIATION, stdY);
|
||||
filterH->SetInput(IN_DIRECTIONAL_BLUR_IN, aInputFilter);
|
||||
filterV->SetInput(IN_DIRECTIONAL_BLUR_IN, filterH);
|
||||
return filterV.forget();
|
||||
if (filterH && filterV) {
|
||||
filterH->SetAttribute(ATT_DIRECTIONAL_BLUR_DIRECTION, (uint32_t)BLUR_DIRECTION_X);
|
||||
filterH->SetAttribute(ATT_DIRECTIONAL_BLUR_STD_DEVIATION, stdX);
|
||||
filterV->SetAttribute(ATT_DIRECTIONAL_BLUR_DIRECTION, (uint32_t)BLUR_DIRECTION_Y);
|
||||
filterV->SetAttribute(ATT_DIRECTIONAL_BLUR_STD_DEVIATION, stdY);
|
||||
filterH->SetInput(IN_DIRECTIONAL_BLUR_IN, aInputFilter);
|
||||
filterV->SetInput(IN_DIRECTIONAL_BLUR_IN, filterH);
|
||||
return filterV.forget();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static TemporaryRef<FilterNode>
|
||||
Clear(DrawTarget* aDT)
|
||||
{
|
||||
RefPtr<FilterNode> filter = aDT->CreateFilter(FilterType::FLOOD);
|
||||
filter->SetAttribute(ATT_FLOOD_COLOR, Color(0,0,0,0));
|
||||
return filter.forget();
|
||||
if (filter) {
|
||||
filter->SetAttribute(ATT_FLOOD_COLOR, Color(0, 0, 0, 0));
|
||||
return filter.forget();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static TemporaryRef<FilterNode>
|
||||
|
@ -197,10 +224,13 @@ namespace FilterWrappers {
|
|||
const IntPoint& aSurfacePosition)
|
||||
{
|
||||
RefPtr<FilterNode> filter = aDT->CreateFilter(FilterType::TRANSFORM);
|
||||
filter->SetAttribute(ATT_TRANSFORM_MATRIX,
|
||||
Matrix::Translation(aSurfacePosition.x, aSurfacePosition.y));
|
||||
filter->SetInput(IN_TRANSFORM_IN, aSurface);
|
||||
return filter.forget();
|
||||
if (filter) {
|
||||
filter->SetAttribute(ATT_TRANSFORM_MATRIX,
|
||||
Matrix::Translation(aSurfacePosition.x, aSurfacePosition.y));
|
||||
filter->SetInput(IN_TRANSFORM_IN, aSurface);
|
||||
return filter.forget();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static TemporaryRef<FilterNode>
|
||||
|
@ -208,15 +238,18 @@ namespace FilterWrappers {
|
|||
{
|
||||
float zero = 0.0f;
|
||||
RefPtr<FilterNode> transfer = aDT->CreateFilter(FilterType::DISCRETE_TRANSFER);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_DISABLE_R, false);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_TABLE_R, &zero, 1);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_DISABLE_G, false);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_TABLE_G, &zero, 1);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_DISABLE_B, false);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_TABLE_B, &zero, 1);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_DISABLE_A, true);
|
||||
transfer->SetInput(IN_DISCRETE_TRANSFER_IN, aInput);
|
||||
return transfer.forget();
|
||||
if (transfer) {
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_DISABLE_R, false);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_TABLE_R, &zero, 1);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_DISABLE_G, false);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_TABLE_G, &zero, 1);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_DISABLE_B, false);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_TABLE_B, &zero, 1);
|
||||
transfer->SetAttribute(ATT_DISCRETE_TRANSFER_DISABLE_A, true);
|
||||
transfer->SetInput(IN_DISCRETE_TRANSFER_IN, aInput);
|
||||
return transfer.forget();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -535,6 +568,9 @@ ConvertComponentTransferFunctionToFilter(const AttributeMap& aFunctionAttributes
|
|||
|
||||
if (!aTableTransfer) {
|
||||
aTableTransfer = aDT->CreateFilter(FilterType::TABLE_TRANSFER);
|
||||
if (!aTableTransfer) {
|
||||
return;
|
||||
}
|
||||
DisableAllTransfers(aTableTransfer);
|
||||
}
|
||||
filter = aTableTransfer;
|
||||
|
@ -558,6 +594,9 @@ ConvertComponentTransferFunctionToFilter(const AttributeMap& aFunctionAttributes
|
|||
|
||||
if (!aDiscreteTransfer) {
|
||||
aDiscreteTransfer = aDT->CreateFilter(FilterType::DISCRETE_TRANSFER);
|
||||
if (!aDiscreteTransfer) {
|
||||
return;
|
||||
}
|
||||
DisableAllTransfers(aDiscreteTransfer);
|
||||
}
|
||||
filter = aDiscreteTransfer;
|
||||
|
@ -589,6 +628,9 @@ ConvertComponentTransferFunctionToFilter(const AttributeMap& aFunctionAttributes
|
|||
};
|
||||
if (!aLinearTransfer) {
|
||||
aLinearTransfer = aDT->CreateFilter(FilterType::LINEAR_TRANSFER);
|
||||
if (!aLinearTransfer) {
|
||||
return;
|
||||
}
|
||||
DisableAllTransfers(aLinearTransfer);
|
||||
}
|
||||
filter = aLinearTransfer;
|
||||
|
@ -622,6 +664,9 @@ ConvertComponentTransferFunctionToFilter(const AttributeMap& aFunctionAttributes
|
|||
};
|
||||
if (!aGammaTransfer) {
|
||||
aGammaTransfer = aDT->CreateFilter(FilterType::GAMMA_TRANSFER);
|
||||
if (!aGammaTransfer) {
|
||||
return;
|
||||
}
|
||||
DisableAllTransfers(aGammaTransfer);
|
||||
}
|
||||
filter = aGammaTransfer;
|
||||
|
@ -672,10 +717,16 @@ FilterNodeFromPrimitiveDescription(const FilterPrimitiveDescription& aDescriptio
|
|||
}
|
||||
if (mode == SVG_FEBLEND_MODE_NORMAL) {
|
||||
filter = aDT->CreateFilter(FilterType::COMPOSITE);
|
||||
if (!filter) {
|
||||
return nullptr;
|
||||
}
|
||||
filter->SetInput(IN_COMPOSITE_IN_START, aSources[1]);
|
||||
filter->SetInput(IN_COMPOSITE_IN_START + 1, aSources[0]);
|
||||
} else {
|
||||
filter = aDT->CreateFilter(FilterType::BLEND);
|
||||
if (!filter) {
|
||||
return nullptr;
|
||||
}
|
||||
static const uint8_t blendModes[SVG_FEBLEND_MODE_LUMINOSITY + 1] = {
|
||||
0,
|
||||
0,
|
||||
|
@ -717,6 +768,9 @@ FilterNodeFromPrimitiveDescription(const FilterPrimitiveDescription& aDescriptio
|
|||
colorMatrix[3], colorMatrix[8], colorMatrix[13], colorMatrix[18],
|
||||
colorMatrix[4], colorMatrix[9], colorMatrix[14], colorMatrix[19]);
|
||||
RefPtr<FilterNode> filter = aDT->CreateFilter(FilterType::COLOR_MATRIX);
|
||||
if (!filter) {
|
||||
return nullptr;
|
||||
}
|
||||
filter->SetAttribute(ATT_COLOR_MATRIX_MATRIX, matrix);
|
||||
filter->SetAttribute(ATT_COLOR_MATRIX_ALPHA_MODE, (uint32_t)ALPHA_MODE_STRAIGHT);
|
||||
filter->SetInput(IN_COLOR_MATRIX_IN, aSources[0]);
|
||||
|
@ -744,6 +798,9 @@ FilterNodeFromPrimitiveDescription(const FilterPrimitiveDescription& aDescriptio
|
|||
MORPHOLOGY_OPERATOR_ERODE : MORPHOLOGY_OPERATOR_DILATE;
|
||||
|
||||
RefPtr<FilterNode> filter = aDT->CreateFilter(FilterType::MORPHOLOGY);
|
||||
if (!filter) {
|
||||
return nullptr;
|
||||
}
|
||||
filter->SetAttribute(ATT_MORPHOLOGY_RADII, IntSize(rx, ry));
|
||||
filter->SetAttribute(ATT_MORPHOLOGY_OPERATOR, (uint32_t)op);
|
||||
filter->SetInput(IN_MORPHOLOGY_IN, aSources[0]);
|
||||
|
@ -754,6 +811,9 @@ FilterNodeFromPrimitiveDescription(const FilterPrimitiveDescription& aDescriptio
|
|||
{
|
||||
Color color = atts.GetColor(eFloodColor);
|
||||
RefPtr<FilterNode> filter = aDT->CreateFilter(FilterType::FLOOD);
|
||||
if (!filter) {
|
||||
return nullptr;
|
||||
}
|
||||
filter->SetAttribute(ATT_FLOOD_COLOR, color);
|
||||
return filter.forget();
|
||||
}
|
||||
|
@ -761,6 +821,9 @@ FilterNodeFromPrimitiveDescription(const FilterPrimitiveDescription& aDescriptio
|
|||
case PrimitiveType::Tile:
|
||||
{
|
||||
RefPtr<FilterNode> filter = aDT->CreateFilter(FilterType::TILE);
|
||||
if (!filter) {
|
||||
return nullptr;
|
||||
}
|
||||
filter->SetAttribute(ATT_TILE_SOURCE_RECT, aSourceRegions[0]);
|
||||
filter->SetInput(IN_TILE_IN, aSources[0]);
|
||||
return filter.forget();
|
||||
|
@ -797,6 +860,9 @@ FilterNodeFromPrimitiveDescription(const FilterPrimitiveDescription& aDescriptio
|
|||
case PrimitiveType::ConvolveMatrix:
|
||||
{
|
||||
RefPtr<FilterNode> filter = aDT->CreateFilter(FilterType::CONVOLVE_MATRIX);
|
||||
if (!filter) {
|
||||
return nullptr;
|
||||
}
|
||||
filter->SetAttribute(ATT_CONVOLVE_MATRIX_KERNEL_SIZE, atts.GetIntSize(eConvolveMatrixKernelSize));
|
||||
const nsTArray<float>& matrix = atts.GetFloats(eConvolveMatrixKernelMatrix);
|
||||
filter->SetAttribute(ATT_CONVOLVE_MATRIX_KERNEL_MATRIX,
|
||||
|
@ -834,6 +900,9 @@ FilterNodeFromPrimitiveDescription(const FilterPrimitiveDescription& aDescriptio
|
|||
case PrimitiveType::DisplacementMap:
|
||||
{
|
||||
RefPtr<FilterNode> filter = aDT->CreateFilter(FilterType::DISPLACEMENT_MAP);
|
||||
if (!filter) {
|
||||
return nullptr;
|
||||
}
|
||||
filter->SetAttribute(ATT_DISPLACEMENT_MAP_SCALE,
|
||||
atts.GetFloat(eDisplacementMapScale));
|
||||
static const uint8_t channel[SVG_CHANNEL_A+1] = {
|
||||
|
@ -855,6 +924,9 @@ FilterNodeFromPrimitiveDescription(const FilterPrimitiveDescription& aDescriptio
|
|||
case PrimitiveType::Turbulence:
|
||||
{
|
||||
RefPtr<FilterNode> filter = aDT->CreateFilter(FilterType::TURBULENCE);
|
||||
if (!filter) {
|
||||
return nullptr;
|
||||
}
|
||||
filter->SetAttribute(ATT_TURBULENCE_BASE_FREQUENCY,
|
||||
atts.GetSize(eTurbulenceBaseFrequency));
|
||||
filter->SetAttribute(ATT_TURBULENCE_NUM_OCTAVES,
|
||||
|
@ -881,6 +953,9 @@ FilterNodeFromPrimitiveDescription(const FilterPrimitiveDescription& aDescriptio
|
|||
uint32_t op = atts.GetUint(eCompositeOperator);
|
||||
if (op == SVG_FECOMPOSITE_OPERATOR_ARITHMETIC) {
|
||||
filter = aDT->CreateFilter(FilterType::ARITHMETIC_COMBINE);
|
||||
if (!filter) {
|
||||
return nullptr;
|
||||
}
|
||||
const nsTArray<float>& coefficients = atts.GetFloats(eCompositeCoefficients);
|
||||
filter->SetAttribute(ATT_ARITHMETIC_COMBINE_COEFFICIENTS,
|
||||
coefficients.Elements(), coefficients.Length());
|
||||
|
@ -888,6 +963,9 @@ FilterNodeFromPrimitiveDescription(const FilterPrimitiveDescription& aDescriptio
|
|||
filter->SetInput(IN_ARITHMETIC_COMBINE_IN2, aSources[1]);
|
||||
} else {
|
||||
filter = aDT->CreateFilter(FilterType::COMPOSITE);
|
||||
if (!filter) {
|
||||
return nullptr;
|
||||
}
|
||||
static const uint8_t operators[SVG_FECOMPOSITE_OPERATOR_ARITHMETIC] = {
|
||||
COMPOSITE_OPERATOR_OVER, // SVG_FECOMPOSITE_OPERATOR_UNKNOWN
|
||||
COMPOSITE_OPERATOR_OVER, // SVG_FECOMPOSITE_OPERATOR_OVER
|
||||
|
@ -913,6 +991,9 @@ FilterNodeFromPrimitiveDescription(const FilterPrimitiveDescription& aDescriptio
|
|||
return filter.forget();
|
||||
}
|
||||
RefPtr<FilterNode> filter = aDT->CreateFilter(FilterType::COMPOSITE);
|
||||
if (!filter) {
|
||||
return nullptr;
|
||||
}
|
||||
filter->SetAttribute(ATT_COMPOSITE_OPERATOR, (uint32_t)COMPOSITE_OPERATOR_OVER);
|
||||
for (size_t i = 0; i < aSources.Length(); i++) {
|
||||
filter->SetInput(IN_COMPOSITE_IN_START + i, aSources[i]);
|
||||
|
@ -934,6 +1015,9 @@ FilterNodeFromPrimitiveDescription(const FilterPrimitiveDescription& aDescriptio
|
|||
RefPtr<FilterNode> offsetBlur = FilterWrappers::Offset(aDT, blur,
|
||||
atts.GetIntPoint(eDropShadowOffset));
|
||||
RefPtr<FilterNode> flood = aDT->CreateFilter(FilterType::FLOOD);
|
||||
if (!flood) {
|
||||
return nullptr;
|
||||
}
|
||||
Color color = atts.GetColor(eDropShadowColor);
|
||||
if (aDescription.InputColorSpace(0) == ColorSpace::LinearRGB) {
|
||||
color = Color(gsRGBToLinearRGBMap[uint8_t(color.r * 255)],
|
||||
|
@ -944,11 +1028,17 @@ FilterNodeFromPrimitiveDescription(const FilterPrimitiveDescription& aDescriptio
|
|||
flood->SetAttribute(ATT_FLOOD_COLOR, color);
|
||||
|
||||
RefPtr<FilterNode> composite = aDT->CreateFilter(FilterType::COMPOSITE);
|
||||
if (!composite) {
|
||||
return nullptr;
|
||||
}
|
||||
composite->SetAttribute(ATT_COMPOSITE_OPERATOR, (uint32_t)COMPOSITE_OPERATOR_IN);
|
||||
composite->SetInput(IN_COMPOSITE_IN_START, offsetBlur);
|
||||
composite->SetInput(IN_COMPOSITE_IN_START + 1, flood);
|
||||
|
||||
RefPtr<FilterNode> filter = aDT->CreateFilter(FilterType::COMPOSITE);
|
||||
if (!filter) {
|
||||
return nullptr;
|
||||
}
|
||||
filter->SetAttribute(ATT_COMPOSITE_OPERATOR, (uint32_t)COMPOSITE_OPERATOR_OVER);
|
||||
filter->SetInput(IN_COMPOSITE_IN_START, composite);
|
||||
filter->SetInput(IN_COMPOSITE_IN_START + 1, aSources[0]);
|
||||
|
@ -981,6 +1071,9 @@ FilterNodeFromPrimitiveDescription(const FilterPrimitiveDescription& aDescriptio
|
|||
};
|
||||
RefPtr<FilterNode> filter =
|
||||
aDT->CreateFilter(filterType[isSpecular][lightType]);
|
||||
if (!filter) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
filter->SetAttribute(ATT_LIGHTING_COLOR,
|
||||
atts.GetColor(eLightingColor));
|
||||
|
@ -1040,6 +1133,9 @@ FilterNodeFromPrimitiveDescription(const FilterPrimitiveDescription& aDescriptio
|
|||
aInputImages[atts.GetUint(eImageInputIndex)];
|
||||
|
||||
RefPtr<FilterNode> transform = aDT->CreateFilter(FilterType::TRANSFORM);
|
||||
if (!transform) {
|
||||
return nullptr;
|
||||
}
|
||||
transform->SetInput(IN_TRANSFORM_IN, inputImage);
|
||||
transform->SetAttribute(ATT_TRANSFORM_MATRIX, TM);
|
||||
transform->SetAttribute(ATT_TRANSFORM_FILTER, atts.GetUint(eImageFilter));
|
||||
|
@ -1250,7 +1346,10 @@ FilterSupport::RenderFilterDescription(DrawTarget* aDT,
|
|||
FilterNodeGraphFromDescription(aDT, aFilter, aRenderRect,
|
||||
aSourceGraphic, aSourceGraphicRect, aFillPaint, aFillPaintRect,
|
||||
aStrokePaint, aStrokePaintRect, aAdditionalImages);
|
||||
|
||||
if (!resultFilter) {
|
||||
gfxWarning() << "Filter is NULL.";
|
||||
return;
|
||||
}
|
||||
aDT->DrawFilter(resultFilter, aRenderRect, aDestPoint, aOptions);
|
||||
}
|
||||
|
||||
|
|
|
@ -1145,7 +1145,10 @@ gfxFcPlatformFontList::GetFontList(nsIAtom *aLangGroup,
|
|||
gfxFontFamily*
|
||||
gfxFcPlatformFontList::GetDefaultFont(const gfxFontStyle* aStyle)
|
||||
{
|
||||
return FindGenericFamily(NS_LITERAL_STRING("serif"), nsGkAtoms::x_western);
|
||||
// Get the default font by using a fake name to retrieve the first
|
||||
// scalable font that fontconfig suggests for the given language.
|
||||
return FindGenericFamily(NS_LITERAL_STRING("-moz-default"),
|
||||
aStyle->language);
|
||||
}
|
||||
|
||||
gfxFontEntry*
|
||||
|
|
|
@ -293,6 +293,7 @@ private:
|
|||
DECL_GFX_PREF(Live, "layers.composer2d.enabled", Composer2DCompositionEnabled, bool, false);
|
||||
DECL_GFX_PREF(Once, "layers.d3d11.disable-warp", LayersD3D11DisableWARP, bool, false);
|
||||
DECL_GFX_PREF(Once, "layers.d3d11.force-warp", LayersD3D11ForceWARP, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.deaa.enabled", LayersDEAAEnabled, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.draw-bigimage-borders", DrawBigImageBorders, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.draw-borders", DrawLayerBorders, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.draw-tile-borders", DrawTileBorders, bool, false);
|
||||
|
|
|
@ -71,7 +71,7 @@ if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_TARGET'] in ('Linux', 'Android'):
|
|||
# from the function using it which breaks the build. Work around that by
|
||||
# forcing there to be only one partition.
|
||||
if '-flto' in CONFIG['OS_CXXFLAGS'] and not CONFIG['CLANG_CXX']:
|
||||
LDFLAGS += ['--param lto-partitions=1']
|
||||
LDFLAGS += ['--param lto-partitions=1']
|
||||
|
||||
if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_TARGET'] == 'Darwin':
|
||||
USE_LIBS += [
|
||||
|
|
|
@ -206,8 +206,9 @@ class BluetoothDaemonConnectionIO final
|
|||
, public ConnectionOrientedSocketIO
|
||||
{
|
||||
public:
|
||||
BluetoothDaemonConnectionIO(MessageLoop* aIOLoop, int aFd,
|
||||
ConnectionStatus aConnectionStatus,
|
||||
BluetoothDaemonConnectionIO(nsIThread* aConsumerThread,
|
||||
MessageLoop* aIOLoop,
|
||||
int aFd, ConnectionStatus aConnectionStatus,
|
||||
BluetoothDaemonConnection* aConnection,
|
||||
BluetoothDaemonPDUConsumer* aConsumer);
|
||||
|
||||
|
@ -241,10 +242,10 @@ public:
|
|||
|
||||
SocketBase* GetSocketBase() override;
|
||||
|
||||
bool IsShutdownOnMainThread() const override;
|
||||
bool IsShutdownOnConsumerThread() const override;
|
||||
bool IsShutdownOnIOThread() const override;
|
||||
|
||||
void ShutdownOnMainThread() override;
|
||||
void ShutdownOnConsumerThread() override;
|
||||
void ShutdownOnIOThread() override;
|
||||
|
||||
private:
|
||||
|
@ -255,14 +256,17 @@ private:
|
|||
};
|
||||
|
||||
BluetoothDaemonConnectionIO::BluetoothDaemonConnectionIO(
|
||||
MessageLoop* aIOLoop, int aFd,
|
||||
nsIThread* aConsumerThread,
|
||||
MessageLoop* aIOLoop,
|
||||
int aFd,
|
||||
ConnectionStatus aConnectionStatus,
|
||||
BluetoothDaemonConnection* aConnection,
|
||||
BluetoothDaemonPDUConsumer* aConsumer)
|
||||
: UnixSocketWatcher(aIOLoop, aFd, aConnectionStatus)
|
||||
, mConnection(aConnection)
|
||||
, mConsumer(aConsumer)
|
||||
, mShuttingDownOnIOThread(false)
|
||||
: UnixSocketWatcher(aIOLoop, aFd, aConnectionStatus)
|
||||
, ConnectionOrientedSocketIO(aConsumerThread)
|
||||
, mConnection(aConnection)
|
||||
, mConsumer(aConsumer)
|
||||
, mShuttingDownOnIOThread(false)
|
||||
{
|
||||
MOZ_ASSERT(mConnection);
|
||||
MOZ_ASSERT(mConsumer);
|
||||
|
@ -308,8 +312,9 @@ BluetoothDaemonConnectionIO::OnConnected()
|
|||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED);
|
||||
|
||||
NS_DispatchToMainThread(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS));
|
||||
GetConsumerThread()->Dispatch(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
AddWatchers(READ_WATCHER, true);
|
||||
if (HasPendingData()) {
|
||||
|
@ -327,9 +332,10 @@ BluetoothDaemonConnectionIO::OnError(const char* aFunction, int aErrno)
|
|||
// Clean up watchers, status, fd
|
||||
Close();
|
||||
|
||||
// Tell the main thread we've errored
|
||||
NS_DispatchToMainThread(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR));
|
||||
// Tell the consumer thread we've errored
|
||||
GetConsumerThread()->Dispatch(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
// |ConnectionOrientedSocketIO|
|
||||
|
@ -397,9 +403,9 @@ BluetoothDaemonConnectionIO::GetSocketBase()
|
|||
}
|
||||
|
||||
bool
|
||||
BluetoothDaemonConnectionIO::IsShutdownOnMainThread() const
|
||||
BluetoothDaemonConnectionIO::IsShutdownOnConsumerThread() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(IsConsumerThread());
|
||||
|
||||
return mConnection == nullptr;
|
||||
}
|
||||
|
@ -411,10 +417,10 @@ BluetoothDaemonConnectionIO::IsShutdownOnIOThread() const
|
|||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonConnectionIO::ShutdownOnMainThread()
|
||||
BluetoothDaemonConnectionIO::ShutdownOnConsumerThread()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdownOnMainThread());
|
||||
MOZ_ASSERT(IsConsumerThread());
|
||||
MOZ_ASSERT(!IsShutdownOnConsumerThread());
|
||||
|
||||
mConnection = nullptr;
|
||||
}
|
||||
|
@ -422,7 +428,7 @@ BluetoothDaemonConnectionIO::ShutdownOnMainThread()
|
|||
void
|
||||
BluetoothDaemonConnectionIO::ShutdownOnIOThread()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsConsumerThread());
|
||||
MOZ_ASSERT(!mShuttingDownOnIOThread);
|
||||
|
||||
Close(); // will also remove fd from I/O loop
|
||||
|
@ -437,10 +443,10 @@ BluetoothDaemonConnection::BluetoothDaemonConnection(
|
|||
BluetoothDaemonPDUConsumer* aPDUConsumer,
|
||||
BluetoothDaemonConnectionConsumer* aConsumer,
|
||||
int aIndex)
|
||||
: mPDUConsumer(aPDUConsumer)
|
||||
: mIO(nullptr)
|
||||
, mPDUConsumer(aPDUConsumer)
|
||||
, mConsumer(aConsumer)
|
||||
, mIndex(aIndex)
|
||||
, mIO(nullptr)
|
||||
{
|
||||
MOZ_ASSERT(mConsumer);
|
||||
}
|
||||
|
@ -452,9 +458,10 @@ BluetoothDaemonConnection::~BluetoothDaemonConnection()
|
|||
|
||||
nsresult
|
||||
BluetoothDaemonConnection::PrepareAccept(UnixSocketConnector* aConnector,
|
||||
nsIThread* aConsumerThread,
|
||||
MessageLoop* aIOLoop,
|
||||
ConnectionOrientedSocketIO*& aIO)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mIO);
|
||||
|
||||
// |BluetoothDaemonConnection| now owns the connector, but doesn't
|
||||
|
@ -465,7 +472,7 @@ BluetoothDaemonConnection::PrepareAccept(UnixSocketConnector* aConnector,
|
|||
SetConnectionStatus(SOCKET_CONNECTING);
|
||||
|
||||
mIO = new BluetoothDaemonConnectionIO(
|
||||
XRE_GetIOMessageLoop(), -1, UnixSocketWatcher::SOCKET_IS_CONNECTING,
|
||||
aConsumerThread, aIOLoop, -1, UnixSocketWatcher::SOCKET_IS_CONNECTING,
|
||||
this, mPDUConsumer);
|
||||
aIO = mIO;
|
||||
|
||||
|
@ -477,10 +484,10 @@ BluetoothDaemonConnection::PrepareAccept(UnixSocketConnector* aConnector,
|
|||
void
|
||||
BluetoothDaemonConnection::SendSocketData(UnixSocketIOBuffer* aBuffer)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mIO);
|
||||
MOZ_ASSERT(mIO->IsConsumerThread());
|
||||
|
||||
XRE_GetIOMessageLoop()->PostTask(
|
||||
mIO->GetIOLoop()->PostTask(
|
||||
FROM_HERE,
|
||||
new SocketIOSendTask<BluetoothDaemonConnectionIO,
|
||||
UnixSocketIOBuffer>(mIO, aBuffer));
|
||||
|
@ -491,15 +498,15 @@ BluetoothDaemonConnection::SendSocketData(UnixSocketIOBuffer* aBuffer)
|
|||
void
|
||||
BluetoothDaemonConnection::Close()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!mIO) {
|
||||
CHROMIUM_LOG("Bluetooth daemon already disconnected!");
|
||||
return;
|
||||
}
|
||||
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO));
|
||||
MOZ_ASSERT(mIO->IsConsumerThread());
|
||||
|
||||
mIO->ShutdownOnConsumerThread();
|
||||
mIO->GetIOLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO));
|
||||
mIO = nullptr;
|
||||
|
||||
NotifyDisconnect();
|
||||
|
@ -508,24 +515,18 @@ BluetoothDaemonConnection::Close()
|
|||
void
|
||||
BluetoothDaemonConnection::OnConnectSuccess()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
mConsumer->OnConnectSuccess(mIndex);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonConnection::OnConnectError()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
mConsumer->OnConnectError(mIndex);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonConnection::OnDisconnect()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
mConsumer->OnDisconnect(mIndex);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include "mozilla/ipc/ConnectionOrientedSocket.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
class MessageLoop;
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
|
@ -92,7 +94,7 @@ private:
|
|||
/*
|
||||
* |BluetoothDaemonPDUConsumer| processes incoming PDUs from the Bluetooth
|
||||
* daemon. Please note that its method |Handle| runs on a different than the
|
||||
* main thread.
|
||||
* consumer thread.
|
||||
*/
|
||||
class BluetoothDaemonPDUConsumer
|
||||
{
|
||||
|
@ -123,6 +125,8 @@ public:
|
|||
//
|
||||
|
||||
nsresult PrepareAccept(UnixSocketConnector* aConnector,
|
||||
nsIThread* aConsumerThread,
|
||||
MessageLoop* aIOLoop,
|
||||
ConnectionOrientedSocketIO*& aIO) override;
|
||||
|
||||
// Methods for |DataSocket|
|
||||
|
@ -139,10 +143,10 @@ public:
|
|||
void OnDisconnect() override;
|
||||
|
||||
private:
|
||||
BluetoothDaemonConnectionIO* mIO;
|
||||
BluetoothDaemonPDUConsumer* mPDUConsumer;
|
||||
BluetoothDaemonConnectionConsumer* mConsumer;
|
||||
int mIndex;
|
||||
BluetoothDaemonConnectionIO* mIO;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче