This commit is contained in:
Wes Kocher 2014-10-14 17:37:53 -07:00
Родитель b0ca48dd27 72c1b1df51
Коммит 047e5c3642
129 изменённых файлов: 2633 добавлений и 580 удалений

Просмотреть файл

@ -788,6 +788,9 @@ pref("dom.ipc.systemMessageCPULockTimeoutSec", 30);
// Ignore the "dialog=1" feature in window.open.
pref("dom.disable_window_open_dialog_feature", true);
// Enable before keyboard events and after keyboard events.
pref("dom.beforeAfterKeyboardEvent.enabled", true);
// Screen reader support
pref("accessibility.accessfu.activate", 2);
pref("accessibility.accessfu.quicknav_modes", "Link,Heading,FormElement,Landmark,ListItem");
@ -873,6 +876,8 @@ pref("general.useragent.updates.enabled", true);
pref("general.useragent.updates.url", "https://dynamicua.cdn.mozilla.net/0/%APP_ID%");
pref("general.useragent.updates.interval", 604800); // 1 week
pref("general.useragent.updates.retry", 86400); // 1 day
// Device ID can be composed of letter, numbers, hyphen ("-") and dot (".")
pref("general.useragent.device_id", "");
// Make <audio> and <video> talk to the AudioChannelService.
pref("media.useAudioChannelService", true);

Просмотреть файл

@ -324,6 +324,8 @@ var shell = {
chromeEventHandler.addEventListener('keydown', this, true);
chromeEventHandler.addEventListener('keypress', this, true);
chromeEventHandler.addEventListener('keyup', this, true);
chromeEventHandler.addEventListener('mozbrowserbeforekeydown', this, true);
chromeEventHandler.addEventListener('mozbrowserbeforekeyup', this, true);
window.addEventListener('MozApplicationManifest', this);
window.addEventListener('mozfullscreenchange', this);
@ -356,6 +358,8 @@ var shell = {
window.removeEventListener('keydown', this, true);
window.removeEventListener('keypress', this, true);
window.removeEventListener('keyup', this, true);
window.removeEventListener('mozbrowserbeforekeydown', this, true);
window.removeEventListener('mozbrowserbeforekeyup', this, true);
window.removeEventListener('MozApplicationManifest', this);
window.removeEventListener('mozfullscreenchange', this);
window.removeEventListener('sizemodechange', this);
@ -420,17 +424,14 @@ var shell = {
return;
}
// If we didn't return, then the key event represents a hardware key
// and we need to prevent it from propagating to Gaia
evt.stopImmediatePropagation();
evt.preventDefault(); // Prevent keypress events (when #501496 is fixed).
// If it is a key down or key up event, we send a chrome event to Gaia.
// If it is a keypress event we just ignore it.
switch (evt.type) {
case 'mozbrowserbeforekeydown':
case 'keydown':
type = type + '-press';
break;
case 'mozbrowserbeforekeyup':
case 'keyup':
type = type + '-release';
break;
@ -473,6 +474,8 @@ var shell = {
case 'keydown':
case 'keyup':
case 'keypress':
case 'mozbrowserbeforekeydown':
case 'mozbrowserbeforekeyup':
this.filterHardwareKeys(evt);
break;
case 'mozfullscreenchange':

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="de254419f3553f48187d003ee8e38034b429f069"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="5f1f0960ae9d22acf2a324ad37a48174d6df87f6"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
@ -23,7 +23,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>

Просмотреть файл

@ -19,13 +19,13 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="de254419f3553f48187d003ee8e38034b429f069"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="5f1f0960ae9d22acf2a324ad37a48174d6df87f6"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c058843242068d0df7c107e09da31b53d2e08fa6"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
<project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>

Просмотреть файл

@ -17,10 +17,10 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="de254419f3553f48187d003ee8e38034b429f069"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="5f1f0960ae9d22acf2a324ad37a48174d6df87f6"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
<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="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="de254419f3553f48187d003ee8e38034b429f069"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="5f1f0960ae9d22acf2a324ad37a48174d6df87f6"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
@ -23,7 +23,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>

Просмотреть файл

@ -19,13 +19,13 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="de254419f3553f48187d003ee8e38034b429f069"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="5f1f0960ae9d22acf2a324ad37a48174d6df87f6"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c058843242068d0df7c107e09da31b53d2e08fa6"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
<project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="de254419f3553f48187d003ee8e38034b429f069"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="5f1f0960ae9d22acf2a324ad37a48174d6df87f6"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
@ -23,7 +23,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
<!-- 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"/>
@ -133,7 +133,7 @@
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="1bb28abbc215f45220620af5cd60a8ac1be93722"/>
<project name="device/qcom/common" path="device/qcom/common" revision="54c32c2ddef066fbdf611d29e4b7c47e0363599e"/>
<project name="device-flame" path="device/t2m/flame" remote="b2g" revision="52c909e821d107d414f851e267dedcd7aae2cebf"/>
<project name="codeaurora_kernel_msm" path="kernel" remote="b2g" revision="1072f7d31dc0bf3a2adc64177b1104da9f4ce4b6"/>
<project name="codeaurora_kernel_msm" path="kernel" remote="b2g" revision="7731d63c809dbca4da408e1de0c1a044f0765e52"/>
<project name="kernel_lk" path="bootable/bootloader/lk" remote="b2g" revision="fda40423ffa573dc6cafd3780515010cb2a086be"/>
<project name="platform/external/bluetooth/bluedroid" path="external/bluetooth/bluedroid" revision="30b96dfca99cb384bf520a16b81f3aba56f09907"/>
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="5b71e40213f650459e95d35b6f14af7e88d8ab62"/>

Просмотреть файл

@ -17,10 +17,10 @@
</project>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="de254419f3553f48187d003ee8e38034b429f069"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="5f1f0960ae9d22acf2a324ad37a48174d6df87f6"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<!-- Stock Android things -->

Просмотреть файл

@ -4,6 +4,6 @@
"remote": "",
"branch": ""
},
"revision": "3e3eb020773e765f4cb7775356ae9c22896db875",
"revision": "b4f77d39d6d8eb153ede94f8a0d70247ccad74e8",
"repo_path": "/integration/gaia-central"
}

Просмотреть файл

@ -17,12 +17,12 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="de254419f3553f48187d003ee8e38034b429f069"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="5f1f0960ae9d22acf2a324ad37a48174d6df87f6"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
<project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>

Просмотреть файл

@ -15,7 +15,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="de254419f3553f48187d003ee8e38034b429f069"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="5f1f0960ae9d22acf2a324ad37a48174d6df87f6"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

Просмотреть файл

@ -17,10 +17,10 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="de254419f3553f48187d003ee8e38034b429f069"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="5f1f0960ae9d22acf2a324ad37a48174d6df87f6"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<!-- Stock Android things -->

Просмотреть файл

@ -17,12 +17,12 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="de254419f3553f48187d003ee8e38034b429f069"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="5f1f0960ae9d22acf2a324ad37a48174d6df87f6"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
<project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>

Просмотреть файл

@ -2361,8 +2361,8 @@ public:
virtual nsHTMLDocument* AsHTMLDocument() { return nullptr; }
virtual mozilla::dom::SVGDocument* AsSVGDocument() { return nullptr; }
// Each import tree has exactly one master document which is
// the root of the tree, and owns the browser context.
// The root document of the import tree. If this document is not an import
// this will return the document itself.
virtual nsIDocument* MasterDocument() = 0;
virtual void SetMasterDocument(nsIDocument* master) = 0;
virtual bool IsMasterDocument() = 0;

Просмотреть файл

@ -83,13 +83,9 @@ public:
, mDisconnected(false)
, mCloseEventWasClean(false)
, mCloseEventCode(nsIWebSocketChannel::CLOSE_ABNORMAL)
, mOutgoingBufferedAmount(0)
, mBinaryType(dom::BinaryType::Blob)
, mScriptLine(0)
, mInnerWindowID(0)
, mMutex("WebSocketImpl::mMutex")
, mWorkerPrivate(nullptr)
, mReadyState(WebSocket::CONNECTING)
{
if (!NS_IsMainThread()) {
mWorkerPrivate = GetCurrentThreadWorkerPrivate();
@ -104,51 +100,6 @@ public:
bool IsTargetThread() const;
uint16_t ReadyState()
{
MutexAutoLock lock(mMutex);
return mReadyState;
}
void SetReadyState(uint16_t aReadyState)
{
MutexAutoLock lock(mMutex);
mReadyState = aReadyState;
}
uint32_t BufferedAmount() const
{
AssertIsOnTargetThread();
return mOutgoingBufferedAmount;
}
dom::BinaryType BinaryType() const
{
AssertIsOnTargetThread();
return mBinaryType;
}
void SetBinaryType(dom::BinaryType aData)
{
AssertIsOnTargetThread();
mBinaryType = aData;
}
void GetUrl(nsAString& aURL) const
{
AssertIsOnTargetThread();
if (mEffectiveURL.IsEmpty()) {
aURL = mOriginalURL;
} else {
aURL = mEffectiveURL;
}
}
void Close(const Optional<uint16_t>& aCode,
const Optional<nsAString>& aReason,
ErrorResult& aRv);
void Init(JSContext* aCx,
nsIPrincipal* aPrincipal,
const nsAString& aURL,
@ -160,12 +111,6 @@ public:
void AsyncOpen(ErrorResult& aRv);
void Send(nsIInputStream* aMsgStream,
const nsACString& aMsgString,
uint32_t aMsgLength,
bool aIsBinary,
ErrorResult& aRv);
nsresult ParseURL(const nsAString& aURL);
nsresult InitializeConnection();
@ -212,9 +157,6 @@ public:
nsCOMPtr<nsIWebSocketChannel> mChannel;
// related to the WebSocket constructor steps
nsString mOriginalURL;
nsString mEffectiveURL; // after redirects
bool mSecure; // if true it is using SSL and the wss scheme,
// otherwise it is using the ws scheme with no SSL
@ -234,16 +176,10 @@ public:
nsCString mURI;
nsCString mRequestedProtocolList;
nsCString mEstablishedProtocol;
nsCString mEstablishedExtensions;
nsCOMPtr<nsIPrincipal> mPrincipal;
nsWeakPtr mOriginDocument;
uint32_t mOutgoingBufferedAmount;
dom::BinaryType mBinaryType;
// Web Socket owner information:
// - the script file name, UTF8 encoded.
// - source code line number where the Web Socket object was constructed.
@ -254,10 +190,6 @@ public:
uint32_t mScriptLine;
uint64_t mInnerWindowID;
// This mutex protects mReadyState that is the only variable that is used in
// different threads.
mozilla::Mutex mMutex;
WorkerPrivate* mWorkerPrivate;
nsAutoPtr<WorkerFeature> mWorkerFeature;
@ -269,9 +201,6 @@ private:
Disconnect();
}
}
// This value should not be used directly but use ReadyState() instead.
uint16_t mReadyState;
};
NS_IMPL_ISUPPORTS(WebSocketImpl,
@ -450,7 +379,7 @@ WebSocketImpl::CloseConnection(uint16_t aReasonCode,
{
AssertIsOnTargetThread();
uint16_t readyState = ReadyState();
uint16_t readyState = mWebSocket->ReadyState();
if (readyState == WebSocket::CLOSING ||
readyState == WebSocket::CLOSED) {
return NS_OK;
@ -458,7 +387,7 @@ WebSocketImpl::CloseConnection(uint16_t aReasonCode,
// The common case...
if (mChannel) {
SetReadyState(WebSocket::CLOSING);
mWebSocket->SetReadyState(WebSocket::CLOSING);
// The channel has to be closed on the main-thread.
@ -481,7 +410,7 @@ WebSocketImpl::CloseConnection(uint16_t aReasonCode,
mCloseEventCode = aReasonCode;
CopyUTF8toUTF16(aReasonString, mCloseEventReason);
SetReadyState(WebSocket::CLOSING);
mWebSocket->SetReadyState(WebSocket::CLOSING);
// Can be called from Cancel() or Init() codepaths, so need to dispatch
// onerror/onclose asynchronously
@ -503,7 +432,7 @@ WebSocketImpl::ConsoleError()
NS_ConvertUTF8toUTF16 specUTF16(mURI);
const char16_t* formatStrings[] = { specUTF16.get() };
if (ReadyState() < WebSocket::OPEN) {
if (mWebSocket->ReadyState() < WebSocket::OPEN) {
PrintErrorOnConsole("chrome://global/locale/appstrings.properties",
MOZ_UTF16("connectionFailure"),
formatStrings, ArrayLength(formatStrings));
@ -621,7 +550,7 @@ WebSocketImpl::DoOnMessageAvailable(const nsACString& aMsg, bool isBinary)
{
AssertIsOnTargetThread();
int16_t readyState = ReadyState();
int16_t readyState = mWebSocket->ReadyState();
if (readyState == WebSocket::CLOSED) {
NS_ERROR("Received message after CLOSED");
return NS_ERROR_UNEXPECTED;
@ -664,7 +593,7 @@ WebSocketImpl::OnStart(nsISupports* aContext)
{
AssertIsOnTargetThread();
int16_t readyState = ReadyState();
int16_t readyState = mWebSocket->ReadyState();
// This is the only function that sets OPEN, and should be called only once
MOZ_ASSERT(readyState != WebSocket::OPEN,
@ -683,13 +612,13 @@ WebSocketImpl::OnStart(nsISupports* aContext)
}
if (!mRequestedProtocolList.IsEmpty()) {
mChannel->GetProtocol(mEstablishedProtocol);
mChannel->GetProtocol(mWebSocket->mEstablishedProtocol);
}
mChannel->GetExtensions(mEstablishedExtensions);
mChannel->GetExtensions(mWebSocket->mEstablishedExtensions);
UpdateURI();
SetReadyState(WebSocket::OPEN);
mWebSocket->SetReadyState(WebSocket::OPEN);
// Call 'onopen'
rv = mWebSocket->CreateAndDispatchSimpleEvent(NS_LITERAL_STRING("open"));
@ -710,7 +639,7 @@ WebSocketImpl::OnStop(nsISupports* aContext, nsresult aStatusCode)
// We can be CONNECTING here if connection failed.
// We can be OPEN if we have encountered a fatal protocol error
// We can be CLOSING if close() was called and/or server initiated close.
MOZ_ASSERT(ReadyState() != WebSocket::CLOSED,
MOZ_ASSERT(mWebSocket->ReadyState() != WebSocket::CLOSED,
"Shouldn't already be CLOSED when OnStop called");
// called by network stack, not JS, so can dispatch JS events synchronously
@ -755,11 +684,11 @@ WebSocketImpl::OnAcknowledge(nsISupports *aContext, uint32_t aSize)
{
AssertIsOnTargetThread();
if (aSize > mOutgoingBufferedAmount) {
if (aSize > mWebSocket->mOutgoingBufferedAmount) {
return NS_ERROR_UNEXPECTED;
}
mOutgoingBufferedAmount -= aSize;
mWebSocket->mOutgoingBufferedAmount -= aSize;
return NS_OK;
}
@ -769,7 +698,7 @@ WebSocketImpl::OnServerClose(nsISupports *aContext, uint16_t aCode,
{
AssertIsOnTargetThread();
int16_t readyState = ReadyState();
int16_t readyState = mWebSocket->ReadyState();
MOZ_ASSERT(readyState != WebSocket::CONNECTING,
"Received server close before connected?");
@ -807,7 +736,7 @@ WebSocketImpl::GetInterface(const nsIID& aIID, void** aResult)
{
AssertIsOnMainThread();
if (ReadyState() == WebSocket::CLOSED) {
if (!mWebSocket || mWebSocket->ReadyState() == WebSocket::CLOSED) {
return NS_ERROR_FAILURE;
}
@ -841,6 +770,10 @@ WebSocket::WebSocket(nsPIDOMWindow* aOwnerWindow)
, mWorkerPrivate(nullptr)
, mKeepingAlive(false)
, mCheckMustKeepAlive(true)
, mOutgoingBufferedAmount(0)
, mBinaryType(dom::BinaryType::Blob)
, mMutex("WebSocketImpl::mMutex")
, mReadyState(CONNECTING)
{
mImpl = new WebSocketImpl(this);
mWorkerPrivate = mImpl->mWorkerPrivate;
@ -1490,7 +1423,7 @@ void
WebSocketImpl::DispatchConnectionCloseEvents()
{
AssertIsOnTargetThread();
SetReadyState(WebSocket::CLOSED);
mWebSocket->SetReadyState(WebSocket::CLOSED);
// Call 'onerror' if needed
if (mFailed) {
@ -1516,7 +1449,7 @@ nsresult
WebSocket::CreateAndDispatchSimpleEvent(const nsAString& aName)
{
MOZ_ASSERT(mImpl);
mImpl->AssertIsOnTargetThread();
AssertIsOnTargetThread();
nsresult rv = CheckInnerWindowCorrectness();
if (NS_FAILED(rv)) {
@ -1541,7 +1474,7 @@ WebSocket::CreateAndDispatchMessageEvent(const nsACString& aData,
bool aIsBinary)
{
MOZ_ASSERT(mImpl);
mImpl->AssertIsOnTargetThread();
AssertIsOnTargetThread();
AutoJSAPI jsapi;
@ -1565,7 +1498,7 @@ WebSocket::CreateAndDispatchMessageEvent(JSContext* aCx,
bool aIsBinary)
{
MOZ_ASSERT(mImpl);
mImpl->AssertIsOnTargetThread();
AssertIsOnTargetThread();
nsresult rv = CheckInnerWindowCorrectness();
if (NS_FAILED(rv)) {
@ -1575,11 +1508,11 @@ WebSocket::CreateAndDispatchMessageEvent(JSContext* aCx,
// Create appropriate JS object for message
JS::Rooted<JS::Value> jsData(aCx);
if (aIsBinary) {
if (mImpl->mBinaryType == dom::BinaryType::Blob) {
if (mBinaryType == dom::BinaryType::Blob) {
nsresult rv = nsContentUtils::CreateBlobBuffer(aCx, GetOwner(), aData,
&jsData);
NS_ENSURE_SUCCESS(rv, rv);
} else if (mImpl->mBinaryType == dom::BinaryType::Arraybuffer) {
} else if (mBinaryType == dom::BinaryType::Arraybuffer) {
JS::Rooted<JSObject*> arrayBuf(aCx);
nsresult rv = nsContentUtils::CreateArrayBuffer(aCx, aData,
arrayBuf.address());
@ -1625,7 +1558,7 @@ WebSocket::CreateAndDispatchCloseEvent(bool aWasClean,
const nsAString &aReason)
{
MOZ_ASSERT(mImpl);
mImpl->AssertIsOnTargetThread();
AssertIsOnTargetThread();
nsresult rv = CheckInnerWindowCorrectness();
if (NS_FAILED(rv)) {
@ -1767,7 +1700,7 @@ WebSocketImpl::ParseURL(const nsAString& aURL)
}
}
mOriginalURL = aURL;
mWebSocket->mOriginalURL = aURL;
rv = parsedURL->GetSpec(mURI);
MOZ_ASSERT(NS_SUCCEEDED(rv));
@ -1795,9 +1728,9 @@ WebSocket::UpdateMustKeepAlive()
bool shouldKeepAlive = false;
if (mListenerManager) {
switch (mImpl->ReadyState())
switch (ReadyState())
{
case WebSocket::CONNECTING:
case CONNECTING:
{
if (mListenerManager->HasListenersFor(nsGkAtoms::onopen) ||
mListenerManager->HasListenersFor(nsGkAtoms::onmessage) ||
@ -1808,19 +1741,19 @@ WebSocket::UpdateMustKeepAlive()
}
break;
case WebSocket::OPEN:
case WebSocket::CLOSING:
case OPEN:
case CLOSING:
{
if (mListenerManager->HasListenersFor(nsGkAtoms::onmessage) ||
mListenerManager->HasListenersFor(nsGkAtoms::onerror) ||
mListenerManager->HasListenersFor(nsGkAtoms::onclose) ||
mImpl->mOutgoingBufferedAmount != 0) {
mOutgoingBufferedAmount != 0) {
shouldKeepAlive = true;
}
}
break;
case WebSocket::CLOSED:
case CLOSED:
{
shouldKeepAlive = false;
}
@ -1940,7 +1873,7 @@ WebSocketImpl::UpdateURI()
channel = static_cast<BaseWebSocketChannel*>(mChannel.get());
MOZ_ASSERT(channel);
channel->GetEffectiveURL(mEffectiveURL);
channel->GetEffectiveURL(mWebSocket->mEffectiveURL);
mSecure = channel->IsEncrypted();
return NS_OK;
@ -1966,62 +1899,70 @@ WebSocket::EventListenerRemoved(nsIAtom* aType)
// webIDL: readonly attribute unsigned short readyState;
uint16_t
WebSocket::ReadyState() const
WebSocket::ReadyState()
{
MOZ_ASSERT(mImpl);
return mImpl->ReadyState();
MutexAutoLock lock(mMutex);
return mReadyState;
}
void
WebSocket::SetReadyState(uint16_t aReadyState)
{
MutexAutoLock lock(mMutex);
mReadyState = aReadyState;
}
// webIDL: readonly attribute unsigned long bufferedAmount;
uint32_t
WebSocket::BufferedAmount() const
{
MOZ_ASSERT(mImpl);
return mImpl->BufferedAmount();
AssertIsOnTargetThread();
return mOutgoingBufferedAmount;
}
// webIDL: attribute BinaryType binaryType;
dom::BinaryType
WebSocket::BinaryType() const
{
MOZ_ASSERT(mImpl);
return mImpl->BinaryType();
AssertIsOnTargetThread();
return mBinaryType;
}
// webIDL: attribute BinaryType binaryType;
void
WebSocket::SetBinaryType(dom::BinaryType aData)
{
MOZ_ASSERT(mImpl);
mImpl->SetBinaryType(aData);
AssertIsOnTargetThread();
mBinaryType = aData;
}
// webIDL: readonly attribute DOMString url
void
WebSocket::GetUrl(nsAString& aURL)
{
MOZ_ASSERT(mImpl);
mImpl->GetUrl(aURL);
AssertIsOnTargetThread();
if (mEffectiveURL.IsEmpty()) {
aURL = mOriginalURL;
} else {
aURL = mEffectiveURL;
}
}
// webIDL: readonly attribute DOMString extensions;
void
WebSocket::GetExtensions(nsAString& aExtensions)
{
MOZ_ASSERT(mImpl);
mImpl->AssertIsOnTargetThread();
CopyUTF8toUTF16(mImpl->mEstablishedExtensions, aExtensions);
AssertIsOnTargetThread();
CopyUTF8toUTF16(mEstablishedExtensions, aExtensions);
}
// webIDL: readonly attribute DOMString protocol;
void
WebSocket::GetProtocol(nsAString& aProtocol)
{
MOZ_ASSERT(mImpl);
mImpl->AssertIsOnTargetThread();
CopyUTF8toUTF16(mImpl->mEstablishedProtocol, aProtocol);
AssertIsOnTargetThread();
CopyUTF8toUTF16(mEstablishedProtocol, aProtocol);
}
// webIDL: void send(DOMString data);
@ -2029,16 +1970,17 @@ void
WebSocket::Send(const nsAString& aData,
ErrorResult& aRv)
{
MOZ_ASSERT(mImpl);
mImpl->AssertIsOnTargetThread();
AssertIsOnTargetThread();
NS_ConvertUTF16toUTF8 msgString(aData);
mImpl->Send(nullptr, msgString, msgString.Length(), false, aRv);
Send(nullptr, msgString, msgString.Length(), false, aRv);
}
void
WebSocket::Send(File& aData, ErrorResult& aRv)
{
AssertIsOnTargetThread();
nsCOMPtr<nsIInputStream> msgStream;
nsresult rv = aData.GetInternalStream(getter_AddRefs(msgStream));
if (NS_FAILED(rv)) {
@ -2058,15 +2000,14 @@ WebSocket::Send(File& aData, ErrorResult& aRv)
return;
}
mImpl->Send(msgStream, EmptyCString(), msgLength, true, aRv);
Send(msgStream, EmptyCString(), msgLength, true, aRv);
}
void
WebSocket::Send(const ArrayBuffer& aData,
ErrorResult& aRv)
{
MOZ_ASSERT(mImpl);
mImpl->AssertIsOnTargetThread();
AssertIsOnTargetThread();
aData.ComputeLengthAndData();
@ -2076,15 +2017,14 @@ WebSocket::Send(const ArrayBuffer& aData,
char* data = reinterpret_cast<char*>(aData.Data());
nsDependentCSubstring msgString(data, len);
mImpl->Send(nullptr, msgString, len, true, aRv);
Send(nullptr, msgString, len, true, aRv);
}
void
WebSocket::Send(const ArrayBufferView& aData,
ErrorResult& aRv)
{
MOZ_ASSERT(mImpl);
mImpl->AssertIsOnTargetThread();
AssertIsOnTargetThread();
aData.ComputeLengthAndData();
@ -2094,20 +2034,20 @@ WebSocket::Send(const ArrayBufferView& aData,
char* data = reinterpret_cast<char*>(aData.Data());
nsDependentCSubstring msgString(data, len);
mImpl->Send(nullptr, msgString, len, true, aRv);
Send(nullptr, msgString, len, true, aRv);
}
void
WebSocketImpl::Send(nsIInputStream* aMsgStream,
const nsACString& aMsgString,
uint32_t aMsgLength,
bool aIsBinary,
ErrorResult& aRv)
WebSocket::Send(nsIInputStream* aMsgStream,
const nsACString& aMsgString,
uint32_t aMsgLength,
bool aIsBinary,
ErrorResult& aRv)
{
AssertIsOnTargetThread();
int64_t readyState = ReadyState();
if (readyState == WebSocket::CONNECTING) {
if (readyState == CONNECTING) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
@ -2115,22 +2055,23 @@ WebSocketImpl::Send(nsIInputStream* aMsgStream,
// Always increment outgoing buffer len, even if closed
mOutgoingBufferedAmount += aMsgLength;
if (readyState == WebSocket::CLOSING ||
readyState == WebSocket::CLOSED) {
if (readyState == CLOSING ||
readyState == CLOSED) {
return;
}
MOZ_ASSERT(readyState == WebSocket::OPEN,
"Unknown state in WebSocket::Send");
// We must have mImpl when connected.
MOZ_ASSERT(mImpl);
MOZ_ASSERT(readyState == OPEN, "Unknown state in WebSocket::Send");
nsresult rv;
if (aMsgStream) {
rv = mChannel->SendBinaryStream(aMsgStream, aMsgLength);
rv = mImpl->mChannel->SendBinaryStream(aMsgStream, aMsgLength);
} else {
if (aIsBinary) {
rv = mChannel->SendBinaryMsg(aMsgString);
rv = mImpl->mChannel->SendBinaryMsg(aMsgString);
} else {
rv = mChannel->SendMsg(aMsgString);
rv = mImpl->mChannel->SendMsg(aMsgString);
}
}
@ -2139,7 +2080,7 @@ WebSocketImpl::Send(nsIInputStream* aMsgStream,
return;
}
mWebSocket->UpdateMustKeepAlive();
UpdateMustKeepAlive();
}
// webIDL: void close(optional unsigned short code, optional DOMString reason):
@ -2147,15 +2088,6 @@ void
WebSocket::Close(const Optional<uint16_t>& aCode,
const Optional<nsAString>& aReason,
ErrorResult& aRv)
{
MOZ_ASSERT(mImpl);
mImpl->Close(aCode, aReason, aRv);
}
void
WebSocketImpl::Close(const Optional<uint16_t>& aCode,
const Optional<nsAString>& aReason,
ErrorResult& aRv)
{
AssertIsOnTargetThread();
@ -2181,18 +2113,21 @@ WebSocketImpl::Close(const Optional<uint16_t>& aCode,
}
int64_t readyState = ReadyState();
if (readyState == WebSocket::CLOSING ||
readyState == WebSocket::CLOSED) {
if (readyState == CLOSING ||
readyState == CLOSED) {
return;
}
if (readyState == WebSocket::CONNECTING) {
FailConnection(closeCode, closeReason);
// If the webSocket is not closed we MUST have a mImpl.
MOZ_ASSERT(mImpl);
if (readyState == CONNECTING) {
mImpl->FailConnection(closeCode, closeReason);
return;
}
MOZ_ASSERT(readyState == WebSocket::OPEN);
CloseConnection(closeCode, closeReason);
MOZ_ASSERT(readyState == OPEN);
mImpl->CloseConnection(closeCode, closeReason);
}
//-----------------------------------------------------------------------------
@ -2206,7 +2141,7 @@ WebSocketImpl::Observe(nsISupports* aSubject,
{
AssertIsOnMainThread();
int64_t readyState = ReadyState();
int64_t readyState = mWebSocket->ReadyState();
if ((readyState == WebSocket::CLOSING) ||
(readyState == WebSocket::CLOSED)) {
return NS_OK;
@ -2235,7 +2170,7 @@ WebSocketImpl::GetName(nsACString& aName)
{
AssertIsOnMainThread();
CopyUTF16toUTF8(mOriginalURL, aName);
CopyUTF16toUTF8(mWebSocket->mOriginalURL, aName);
return NS_OK;
}
@ -2244,7 +2179,7 @@ WebSocketImpl::IsPending(bool* aValue)
{
AssertIsOnTargetThread();
int64_t readyState = ReadyState();
int64_t readyState = mWebSocket->ReadyState();
*aValue = (readyState != WebSocket::CLOSED);
return NS_OK;
}
@ -2323,7 +2258,7 @@ WebSocketImpl::CancelInternal()
{
AssertIsOnTargetThread();
int64_t readyState = ReadyState();
int64_t readyState = mWebSocket->ReadyState();
if (readyState == WebSocket::CLOSING || readyState == WebSocket::CLOSED) {
return NS_OK;
}
@ -2484,5 +2419,11 @@ WebSocketImpl::IsTargetThread() const
return NS_IsMainThread() == !mWorkerPrivate;
}
void
WebSocket::AssertIsOnTargetThread() const
{
MOZ_ASSERT(NS_IsMainThread() == !mWorkerPrivate);
}
} // dom namespace
} // mozilla namespace

Просмотреть файл

@ -23,6 +23,8 @@
#define DEFAULT_WS_SCHEME_PORT 80
#define DEFAULT_WSS_SCHEME_PORT 443
class nsIInputStream;
namespace mozilla {
namespace dom {
@ -88,7 +90,7 @@ public: // WebIDL interface:
void GetUrl(nsAString& aResult);
// webIDL: readonly attribute unsigned short readyState;
uint16_t ReadyState() const;
uint16_t ReadyState();
// webIDL: readonly attribute unsigned long bufferedAmount;
uint32_t BufferedAmount() const;
@ -134,6 +136,8 @@ private: // constructor && distructor
explicit WebSocket(nsPIDOMWindow* aOwnerWindow);
virtual ~WebSocket();
void SetReadyState(uint16_t aReadyState);
// These methods actually do the dispatch for various events.
nsresult CreateAndDispatchSimpleEvent(const nsAString& aName);
nsresult CreateAndDispatchMessageEvent(const nsACString& aData,
@ -157,16 +161,39 @@ private:
WebSocket(const WebSocket& x) MOZ_DELETE; // prevent bad usage
WebSocket& operator=(const WebSocket& x) MOZ_DELETE;
void Send(nsIInputStream* aMsgStream,
const nsACString& aMsgString,
uint32_t aMsgLength,
bool aIsBinary,
ErrorResult& aRv);
void AssertIsOnTargetThread() const;
// Raw pointer because this WebSocketImpl is created, managed and destroyed by
// WebSocket.
WebSocketImpl* mImpl;
// This is used just to check in which thread this object is used when mImpl
// is null.
workers::WorkerPrivate* mWorkerPrivate;
bool mKeepingAlive;
bool mCheckMustKeepAlive;
uint32_t mOutgoingBufferedAmount;
// related to the WebSocket constructor steps
nsString mOriginalURL;
nsString mEffectiveURL; // after redirects
nsCString mEstablishedExtensions;
nsCString mEstablishedProtocol;
dom::BinaryType mBinaryType;
// This mutex protects mReadyState that is the only variable that is used in
// different threads.
mozilla::Mutex mMutex;
// This value should not be used directly but use ReadyState() instead.
uint16_t mReadyState;
};
} //namespace dom

Просмотреть файл

@ -4703,10 +4703,6 @@ nsDocument::GetWindowInternal() const
if (win) {
// mScriptGlobalObject is always the inner window, let's get the outer.
win = win->GetOuterWindow();
} else if (mMasterDocument) {
// For script execution in the imported document we need the window of
// the master document.
win = mMasterDocument->GetWindow();
}
}

Просмотреть файл

@ -793,6 +793,10 @@ GK_ATOM(onmouseover, "onmouseover")
GK_ATOM(onMozMouseHittest, "onMozMouseHittest")
GK_ATOM(onmouseup, "onmouseup")
GK_ATOM(onMozAfterPaint, "onMozAfterPaint")
GK_ATOM(onmozbrowserafterkeydown, "onmozbrowserafterkeydown")
GK_ATOM(onmozbrowserafterkeyup, "onmozbrowserafterkeyup")
GK_ATOM(onmozbrowserbeforekeydown, "onmozbrowserbeforekeydown")
GK_ATOM(onmozbrowserbeforekeyup, "onmozbrowserbeforekeyup")
GK_ATOM(onmozfullscreenchange, "onmozfullscreenchange")
GK_ATOM(onmozfullscreenerror, "onmozfullscreenerror")
GK_ATOM(onmozpointerlockchange, "onmozpointerlockchange")

Просмотреть файл

@ -292,7 +292,8 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType,
nsCOMPtr<nsILoadGroup> loadGroup = mDocument->GetDocumentLoadGroup();
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(mDocument->GetWindow()));
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(mDocument->MasterDocument()->GetWindow()));
if (!window) {
return NS_ERROR_NULL_POINTER;
}

Просмотреть файл

@ -659,3 +659,5 @@ support-files = file_bug1011748_redirect.sjs file_bug1011748_OK.sjs
[test_element.matches.html]
[test_user_select.html]
skip-if = buildapp == 'mulet' || buildapp == 'b2g'
[test_bug1081686.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s

Просмотреть файл

@ -0,0 +1,70 @@
<!DOCTYPE HTML>
<html>
<!--
-->
<head>
<title>bug 1081686</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onload="testWebSocket()">
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
var ws;
function forcegc()
{
SpecialPowers.forceGC();
SpecialPowers.gc();
setTimeout(function()
{
SpecialPowers.gc();
}, 0);
}
function testWebSocket () {
ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket_hello");
ws.onopen = function(e) {
ws.send("data");
}
ws.onclose = function(e) {
forcegc();
setTimeout(function() {
is(ws.readyState, 3, 'WebSocket is closed');
is(ws.bufferedAmount, 0, 'WebSocket.bufferedAmount should be empty.');
is(ws.binaryType, 'blob', 'WebSocket.binaryType is blob');
ws.binaryType = 'arraybuffer';
is(ws.binaryType, 'arraybuffer', 'WebSocket.binaryType is arraybuffer');
is(ws.url, 'ws://mochi.test:8888/tests/content/base/test/file_websocket_hello', 'WebSocket.url is correct');
ws.close();
ws.send('foobar');
SimpleTest.finish();
}, 1000);
}
ws.onerror = function(e) {
ok(false, "onerror called!");
SimpleTest.finish();
}
ws.onmessage = function(e) {
is(e.data, "Hello world!", "Wrong data");
ws.close();
}
}
SimpleTest.waitForExplicitFinish();
</script>
</pre>
<div>
</div>
</body>
</html>

Просмотреть файл

@ -445,16 +445,18 @@ MediaEngineGonkVideoSource::OnTakePictureComplete(uint8_t* aData, uint32_t aLeng
uint8_t* aData,
uint32_t aLength,
const nsAString& aMimeType)
: mPhotoDataLength(aLength)
{
mCallbacks.SwapElements(aCallbacks);
mPhoto.AppendElements(aData, aLength);
mPhotoData = (uint8_t*) moz_malloc(aLength);
memcpy(mPhotoData, aData, mPhotoDataLength);
mMimeType = aMimeType;
}
NS_IMETHOD Run()
{
nsRefPtr<dom::File> blob =
dom::File::CreateMemoryFile(nullptr, mPhoto.Elements(), mPhoto.Length(), mMimeType);
dom::File::CreateMemoryFile(nullptr, mPhotoData, mPhotoDataLength, mMimeType);
uint32_t callbackCounts = mCallbacks.Length();
for (uint8_t i = 0; i < callbackCounts; i++) {
nsRefPtr<dom::File> tempBlob = blob;
@ -466,8 +468,9 @@ MediaEngineGonkVideoSource::OnTakePictureComplete(uint8_t* aData, uint32_t aLeng
}
nsTArray<nsRefPtr<PhotoCallback>> mCallbacks;
nsTArray<uint8_t> mPhoto;
uint8_t* mPhotoData;
nsString mMimeType;
uint32_t mPhotoDataLength;
};
// All elements in mPhotoCallbacks will be swapped in GenerateBlobRunnable

Просмотреть файл

@ -493,6 +493,12 @@ this.PermissionsTable = { geolocation: {
trusted: DENY_ACTION,
privileged: DENY_ACTION,
certified: ALLOW_ACTION
},
"before-after-keyboard-event": {
app: DENY_ACTION,
trusted: DENY_ACTION,
privileged: DENY_ACTION,
certified: ALLOW_ACTION
}
};

Просмотреть файл

@ -43,6 +43,11 @@ protected:
private:
DOMCursor() MOZ_DELETE;
// Calling Then() on DOMCursor is a mistake, since the DOMCursor object
// should not have a .then() method from JS' point of view.
already_AddRefed<mozilla::dom::Promise>
Then(JSContext* aCx, AnyCallback* aResolveCallback,
AnyCallback* aRejectCallback, ErrorResult& aRv) MOZ_DELETE;
nsCOMPtr<nsICursorContinueCallback> mCallback;
bool mFinished;

Просмотреть файл

@ -10,11 +10,16 @@
#include "nsThreadUtils.h"
#include "DOMCursor.h"
#include "nsIDOMEvent.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/ScriptSettings.h"
using mozilla::dom::AnyCallback;
using mozilla::dom::DOMError;
using mozilla::dom::DOMRequest;
using mozilla::dom::DOMRequestService;
using mozilla::dom::DOMCursor;
using mozilla::dom::Promise;
using mozilla::AutoSafeJSContext;
DOMRequest::DOMRequest(nsPIDOMWindow* aWindow)
@ -25,16 +30,24 @@ DOMRequest::DOMRequest(nsPIDOMWindow* aWindow)
{
}
DOMRequest::~DOMRequest()
{
mResult.setUndefined();
mozilla::DropJSObjects(this);
}
NS_IMPL_CYCLE_COLLECTION_CLASS(DOMRequest)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DOMRequest,
DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mError)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromise)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DOMRequest,
DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mError)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromise)
tmp->mResult = JSVAL_VOID;
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@ -107,6 +120,10 @@ DOMRequest::FireSuccess(JS::Handle<JS::Value> aResult)
mResult = aResult;
FireEvent(NS_LITERAL_STRING("success"), false, false);
if (mPromise) {
mPromise->MaybeResolve(mResult);
}
}
void
@ -120,6 +137,10 @@ DOMRequest::FireError(const nsAString& aError)
mError = new DOMError(GetOwner(), aError);
FireEvent(NS_LITERAL_STRING("error"), true, true);
if (mPromise) {
mPromise->MaybeRejectBrokenly(mError);
}
}
void
@ -133,6 +154,10 @@ DOMRequest::FireError(nsresult aError)
mError = new DOMError(GetOwner(), aError);
FireEvent(NS_LITERAL_STRING("error"), true, true);
if (mPromise) {
mPromise->MaybeRejectBrokenly(mError);
}
}
void
@ -147,6 +172,10 @@ DOMRequest::FireDetailedError(DOMError* aError)
mError = aError;
FireEvent(NS_LITERAL_STRING("error"), true, true);
if (mPromise) {
mPromise->MaybeRejectBrokenly(mError);
}
}
void
@ -175,6 +204,31 @@ DOMRequest::RootResultVal()
mozilla::HoldJSObjects(this);
}
already_AddRefed<Promise>
DOMRequest::Then(JSContext* aCx, AnyCallback* aResolveCallback,
AnyCallback* aRejectCallback, mozilla::ErrorResult& aRv)
{
if (!mPromise) {
mPromise = Promise::Create(DOMEventTargetHelper::GetParentObject(), aRv);
if (aRv.Failed()) {
return nullptr;
}
if (mDone) {
// Since we create mPromise lazily, it's possible that the DOMRequest object
// has already fired its success/error event. In that case we should
// manually resolve/reject mPromise here. mPromise will take care of
// calling the callbacks on |promise| as needed.
if (mError) {
mPromise->MaybeRejectBrokenly(mError);
} else {
mPromise->MaybeResolve(mResult);
}
}
}
return mPromise->Then(aCx, aResolveCallback, aRejectCallback, aRv);
}
NS_IMPL_ISUPPORTS(DOMRequestService, nsIDOMRequestService)
NS_IMETHODIMP
@ -253,7 +307,7 @@ public:
const JS::Value& aResult)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
AutoSafeJSContext cx;
mozilla::ThreadsafeAutoSafeJSContext cx;
nsRefPtr<FireSuccessAsyncTask> asyncTask = new FireSuccessAsyncTask(cx, aRequest, aResult);
if (NS_FAILED(NS_DispatchToMainThread(asyncTask))) {
NS_WARNING("Failed to dispatch to main thread!");

Просмотреть файл

@ -16,14 +16,21 @@
#include "nsCOMPtr.h"
namespace mozilla {
class ErrorResult;
namespace dom {
class AnyCallback;
class Promise;
class DOMRequest : public DOMEventTargetHelper,
public nsIDOMDOMRequest
{
protected:
JS::Heap<JS::Value> mResult;
nsRefPtr<DOMError> mError;
nsRefPtr<Promise> mPromise;
bool mDone;
public:
@ -67,6 +74,9 @@ public:
IMPL_EVENT_HANDLER(success)
IMPL_EVENT_HANDLER(error)
already_AddRefed<mozilla::dom::Promise>
Then(JSContext* aCx, AnyCallback* aResolveCallback,
AnyCallback* aRejectCallback, mozilla::ErrorResult& aRv);
void FireSuccess(JS::Handle<JS::Value> aResult);
void FireError(const nsAString& aError);
@ -76,11 +86,7 @@ public:
explicit DOMRequest(nsPIDOMWindow* aWindow);
protected:
virtual ~DOMRequest()
{
mResult = JSVAL_VOID;
mozilla::DropJSObjects(this);
}
virtual ~DOMRequest();
void FireEvent(const nsAString& aType, bool aBubble, bool aCancelable);

Просмотреть файл

@ -51,6 +51,7 @@ var tests = [
ok("readyState" in req, "cursor has readyState");
ok("done" in req, "cursor has finished");
ok("continue" in req, "cursor has continue");
ok(!("then" in req), "cursor should not have a then method");
is(req.readyState, "pending", "readyState is pending");
is(req.result, undefined, "result is undefined");

Просмотреть файл

@ -17,59 +17,212 @@
var reqserv = SpecialPowers.getDOMRequestService();
ok("createRequest" in reqserv, "appears to be a service");
// create a request
var req = reqserv.createRequest(window);
ok("result" in req, "request has result");
ok("error" in req, "request has error");
ok("onsuccess" in req, "request has onsuccess");
ok("onerror" in req, "request has onerror");
ok("readyState" in req, "request has readyState");
function testBasics() {
// create a request
var req = reqserv.createRequest(window);
ok("result" in req, "request has result");
ok("error" in req, "request has error");
ok("onsuccess" in req, "request has onsuccess");
ok("onerror" in req, "request has onerror");
ok("readyState" in req, "request has readyState");
ok("then" in req, "request has then");
is(req.readyState, "pending", "readyState is pending");
is(req.result, undefined, "result is undefined");
is(req.onsuccess, null, "onsuccess is null");
is(req.onerror, null, "onerror is null");
is(req.readyState, "pending", "readyState is pending");
is(req.result, undefined, "result is undefined");
is(req.onsuccess, null, "onsuccess is null");
is(req.onerror, null, "onerror is null");
// fire success
var ev = null;
req.onsuccess = function(e) {
ev = e;
runTest();
}
reqserv.fireSuccess(req, "my result");
ok(ev, "got success event");
is(ev.type, "success", "correct type during success");
is(ev.target, req, "correct target during success");
is(req.readyState, "done", "correct readyState after success");
is(req.error, null, "correct error after success");
is(req.result, "my result", "correct result after success");
// fire error
req = reqserv.createRequest(window);
ev = null;
req.onerror = function(e) {
ev = e;
function testSuccess() {
// fire success
var req = reqserv.createRequest(window);
var ev = null;
req.onsuccess = function(e) {
ev = e;
}
var result = null;
var promise = req.then(function(r) {
is(r, "my result", "correct result when resolving the promise");
result = r;
runTest();
}, function(e) {
ok(false, "promise should not be rejected");
runTest();
});
ok(promise instanceof Promise, "then() should return a Promise");
reqserv.fireSuccess(req, "my result");
ok(ev, "got success event");
is(ev.type, "success", "correct type during success");
is(ev.target, req, "correct target during success");
is(req.readyState, "done", "correct readyState after success");
is(req.error, null, "correct error after success");
is(req.result, "my result", "correct result after success");
is(result, null, "Promise should not be resolved synchronously");
}
reqserv.fireError(req, "OhMyError");
ok(ev, "got error event");
is(ev.type, "error", "correct type during error");
is(ev.target, req, "correct target during error");
is(req.readyState, "done", "correct readyState after error");
is(req.error.name, "OhMyError", "correct error after error");
is(req.result, undefined, "correct result after error");
// fire detailed error
req = reqserv.createRequest(window);
ev = null;
req.onerror = function(e) {
ev = e;
};
reqserv.fireDetailedError(req, new DOMError("detailedError"));
ok(ev, "got error event");
is(ev.type, "error", "correct type during error");
is(ev.target, req, "correct target during error");
is(req.readyState, "done", "correct readyState after error");
is(req.error.name, "detailedError", "correct error after error");
is(req.result, undefined, "correct result after error");
function testError() {
// fire error
var req = reqserv.createRequest(window);
var ev = null;
req.onerror = function(e) {
ev = e;
}
var error = null;
var promise = req.then(function(r) {
ok(false, "promise should not be resolved");
runTest();
}, function(e) {
ok(e instanceof DOMError, "got error rejection");
ok(e === req.error, "got correct error when rejecting the promise");
error = e;
runTest();
});
ok(promise instanceof Promise, "then() should return a Promise");
reqserv.fireError(req, "OhMyError");
ok(ev, "got error event");
is(ev.type, "error", "correct type during error");
is(ev.target, req, "correct target during error");
is(req.readyState, "done", "correct readyState after error");
is(req.error.name, "OhMyError", "correct error after error");
is(req.result, undefined, "correct result after error");
is(error, null, "Promise should not be rejected synchronously");
}
function testDetailedError() {
// fire detailed error
var req = reqserv.createRequest(window);
var ev = null;
req.onerror = function(e) {
ev = e;
};
var error = null;
var promise = req.then(function(r) {
ok(false, "promise should not be resolved");
runTest();
}, function(e) {
ok(e instanceof DOMError, "got error rejection");
ok(e === req.error, "got correct error when rejecting the promise");
error = e;
runTest();
});
ok(promise instanceof Promise, "then() should return a Promise");
reqserv.fireDetailedError(req, new DOMError("detailedError"));
ok(ev, "got error event");
is(ev.type, "error", "correct type during error");
is(ev.target, req, "correct target during error");
is(req.readyState, "done", "correct readyState after error");
is(req.error.name, "detailedError", "correct error after error");
is(req.result, undefined, "correct result after error");
is(error, null, "Promise should not be rejected synchronously");
}
function testThenAfterSuccess() {
// fire success
var req = reqserv.createRequest(window);
var ev = null;
req.onsuccess = function(e) {
ev = e;
}
reqserv.fireSuccess(req, "my result");
ok(ev, "got success event");
is(ev.type, "success", "correct type during success");
is(ev.target, req, "correct target during success");
is(req.readyState, "done", "correct readyState after success");
is(req.error, null, "correct error after success");
is(req.result, "my result", "correct result after success");
var result = null;
var promise = req.then(function(r) {
is(r, "my result", "correct result when resolving the promise");
result = r;
runTest();
}, function(e) {
ok(false, "promise should not be rejected");
runTest();
});
ok(promise instanceof Promise, "then() should return a Promise");
is(result, null, "Promise should not be resolved synchronously");
}
function testThenAfterError() {
// fire error
var req = reqserv.createRequest(window);
var ev = null;
req.onerror = function(e) {
ev = e;
}
reqserv.fireError(req, "OhMyError");
ok(ev, "got error event");
is(ev.type, "error", "correct type during error");
is(ev.target, req, "correct target during error");
is(req.readyState, "done", "correct readyState after error");
is(req.error.name, "OhMyError", "correct error after error");
is(req.result, undefined, "correct result after error");
var error = null;
var promise = req.then(function(r) {
ok(false, "promise should not be resolved");
runTest();
}, function(e) {
ok(e instanceof DOMError, "got error rejection");
ok(e === req.error, "got correct error when rejecting the promise");
error = e;
runTest();
});
ok(promise instanceof Promise, "then() should return a Promise");
is(error, null, "Promise should not be rejected synchronously");
}
function testDetailedError() {
// fire detailed error
var req = reqserv.createRequest(window);
var ev = null;
req.onerror = function(e) {
ev = e;
};
var error = null;
var promise = req.then(function(r) {
ok(false, "promise should not be resolved");
runTest();
}, function(e) {
ok(e instanceof DOMError, "got error rejection");
ok(e === req.error, "got correct error when rejecting the promise");
error = e;
runTest();
});
ok(promise instanceof Promise, "then() should return a Promise");
reqserv.fireDetailedError(req, new DOMError("detailedError"));
ok(ev, "got error event");
is(ev.type, "error", "correct type during error");
is(ev.target, req, "correct target during error");
is(req.readyState, "done", "correct readyState after error");
is(req.error.name, "detailedError", "correct error after error");
is(req.result, undefined, "correct result after error");
is(error, null, "Promise should not be rejected synchronously");
}
var tests = [
testBasics,
testSuccess,
testError,
testDetailedError,
testThenAfterSuccess,
testThenAfterError,
];
function runTest() {
if (!tests.length) {
SimpleTest.finish();
return;
}
var test = tests.shift();
test();
}
SimpleTest.waitForExplicitFinish();
runTest();
</script>
</pre>
</body>

Просмотреть файл

@ -352,6 +352,10 @@ DOMInterfaces = {
'headerFile': 'mozilla/dom/DOMRect.h',
},
'DOMRequest': {
'implicitJSContext': [ 'then' ],
},
'DOMSettableTokenList': {
'nativeType': 'nsDOMSettableTokenList',
},

Просмотреть файл

@ -236,6 +236,24 @@ ToJSValue(JSContext* aCx, JS::Handle<JS::Value> aArgument,
return MaybeWrapValue(aCx, aValue);
}
// Accept existing JS values on the Heap (which may not be same-compartment with us
inline bool
ToJSValue(JSContext* aCx, const JS::Heap<JS::Value>& aArgument,
JS::MutableHandle<JS::Value> aValue)
{
aValue.set(aArgument);
return MaybeWrapValue(aCx, aValue);
}
// Accept existing rooted JS values (which may not be same-compartment with us
inline bool
ToJSValue(JSContext* aCx, const JS::Rooted<JS::Value>& aArgument,
JS::MutableHandle<JS::Value> aValue)
{
aValue.set(aArgument);
return MaybeWrapValue(aCx, aValue);
}
// Accept nsresult, for use in rejections, and create an XPCOM
// exception object representing that nsresult.
bool

Просмотреть файл

@ -114,8 +114,8 @@
#undef free // apparently defined by some windows header, clashing with a free()
// method in SkTypes.h
#ifdef USE_SKIA
#include "SkiaGLGlue.h"
#ifdef USE_SKIA
#include "SurfaceTypes.h"
#endif

Просмотреть файл

@ -141,6 +141,13 @@ WebGL2Context::TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat
if (!ValidateTexStorage(target, levels, internalformat, width, height, 1, "texStorage2D"))
return;
GetAndFlushUnderlyingGLErrors();
gl->fTexStorage2D(target, levels, internalformat, width, height);
GLenum error = GetAndFlushUnderlyingGLErrors();
if (error) {
return GenerateWarning("texStorage2D generated error %s", ErrorName(error));
}
WebGLTexture* tex = activeBoundTextureForTarget(target);
tex->SetImmutable();
@ -157,8 +164,6 @@ WebGL2Context::TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat
w = std::max(1, w / 2);
h = std::max(1, h / 2);
}
gl->fTexStorage2D(target, levels, internalformat, width, height);
}
void
@ -175,6 +180,13 @@ WebGL2Context::TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat
if (!ValidateTexStorage(target, levels, internalformat, width, height, depth, "texStorage3D"))
return;
GetAndFlushUnderlyingGLErrors();
gl->fTexStorage3D(target, levels, internalformat, width, height, depth);
GLenum error = GetAndFlushUnderlyingGLErrors();
if (error) {
return GenerateWarning("texStorage3D generated error %s", ErrorName(error));
}
WebGLTexture* tex = activeBoundTextureForTarget(target);
tex->SetImmutable();
@ -190,8 +202,6 @@ WebGL2Context::TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat
h = std::max(1, h >> 1);
d = std::max(1, d >> 1);
}
gl->fTexStorage3D(target, levels, internalformat, width, height, depth);
}
void
@ -272,8 +282,19 @@ WebGL2Context::TexSubImage3D(GLenum rawTarget, GLint level,
if (dataLength < bytesNeeded)
return ErrorInvalidOperation("texSubImage2D: not enough data for operation (need %d, have %d)", bytesNeeded, dataLength);
if (imageInfo.HasUninitializedImageData())
tex->DoDeferredImageInitialization(texImageTarget, level);
if (imageInfo.HasUninitializedImageData()) {
bool coversWholeImage = xoffset == 0 &&
yoffset == 0 &&
zoffset == 0 &&
width == imageInfo.Width() &&
height == imageInfo.Height() &&
depth == imageInfo.Depth();
if (coversWholeImage) {
tex->SetImageDataStatus(texImageTarget, level, WebGLImageDataStatus::InitializedImageData);
} else {
tex->DoDeferredImageInitialization(texImageTarget, level);
}
}
GLenum driverType = LOCAL_GL_NONE;
GLenum driverInternalFormat = LOCAL_GL_NONE;

Просмотреть файл

@ -594,7 +594,15 @@ WebGLContext::CopyTexSubImage2D(GLenum rawTexImgTarget,
ClearBackbufferIfNeeded();
if (imageInfo.HasUninitializedImageData()) {
tex->DoDeferredImageInitialization(texImageTarget, level);
bool coversWholeImage = xoffset == 0 &&
yoffset == 0 &&
width == texWidth &&
height == texHeight;
if (coversWholeImage) {
tex->SetImageDataStatus(texImageTarget, level, WebGLImageDataStatus::InitializedImageData);
} else {
tex->DoDeferredImageInitialization(texImageTarget, level);
}
}
TexInternalFormat internalformat;
@ -3414,8 +3422,17 @@ WebGLContext::CompressedTexSubImage2D(GLenum rawTexImgTarget, GLint level, GLint
return;
}
if (levelInfo.HasUninitializedImageData())
tex->DoDeferredImageInitialization(texImageTarget, level);
if (levelInfo.HasUninitializedImageData()) {
bool coversWholeImage = xoffset == 0 &&
yoffset == 0 &&
width == levelInfo.Width() &&
height == levelInfo.Height();
if (coversWholeImage) {
tex->SetImageDataStatus(texImageTarget, level, WebGLImageDataStatus::InitializedImageData);
} else {
tex->DoDeferredImageInitialization(texImageTarget, level);
}
}
MakeContextCurrent();
gl->fCompressedTexSubImage2D(texImageTarget.get(), level, xoffset, yoffset, width, height, internalformat, byteLength, view.Data());
@ -3941,9 +3958,17 @@ WebGLContext::TexSubImage2D_base(TexImageTarget texImageTarget, GLint level,
if (byteLength < bytesNeeded)
return ErrorInvalidOperation("texSubImage2D: not enough data for operation (need %d, have %d)", bytesNeeded, byteLength);
if (imageInfo.HasUninitializedImageData())
tex->DoDeferredImageInitialization(texImageTarget, level);
if (imageInfo.HasUninitializedImageData()) {
bool coversWholeImage = xoffset == 0 &&
yoffset == 0 &&
width == imageInfo.Width() &&
height == imageInfo.Height();
if (coversWholeImage) {
tex->SetImageDataStatus(texImageTarget, level, WebGLImageDataStatus::InitializedImageData);
} else {
tex->DoDeferredImageInitialization(texImageTarget, level);
}
}
MakeContextCurrent();
size_t srcStride = srcStrideOrZero ? srcStrideOrZero : checked_alignedRowSize.value();

Просмотреть файл

@ -113,6 +113,7 @@ public:
size_t MemoryUsage() const;
TexInternalFormat EffectiveInternalFormat() const { return mEffectiveInternalFormat; }
GLsizei Depth() const { return mDepth; }
protected:
/*

Просмотреть файл

@ -129,6 +129,7 @@ LOCAL_INCLUDES += [
'/content/svg/content/src',
'/content/xul/content/src',
'/dom/base',
'/gfx/gl',
'/image/src',
'/js/xpconnect/src',
'/layout/generic',

Просмотреть файл

@ -0,0 +1,92 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/BeforeAfterKeyboardEvent.h"
#include "mozilla/TextEvents.h"
#include "prtime.h"
namespace mozilla {
namespace dom {
BeforeAfterKeyboardEvent::BeforeAfterKeyboardEvent(
EventTarget* aOwner,
nsPresContext* aPresContext,
InternalBeforeAfterKeyboardEvent* aEvent)
: KeyboardEvent(aOwner, aPresContext,
aEvent ? aEvent :
new InternalBeforeAfterKeyboardEvent(false, 0,
nullptr))
{
MOZ_ASSERT(mEvent->mClass == eBeforeAfterKeyboardEventClass,
"event type mismatch eBeforeAfterKeyboardEventClass");
if (!aEvent) {
mEventIsInternal = true;
mEvent->time = PR_Now();
}
}
// static
already_AddRefed<BeforeAfterKeyboardEvent>
BeforeAfterKeyboardEvent::Constructor(
EventTarget* aOwner,
const nsAString& aType,
const BeforeAfterKeyboardEventInit& aParam)
{
nsRefPtr<BeforeAfterKeyboardEvent> event =
new BeforeAfterKeyboardEvent(aOwner, nullptr, nullptr);
ErrorResult rv;
event->InitWithKeyboardEventInit(aOwner, aType, aParam, rv);
NS_WARN_IF(rv.Failed());
event->mEvent->AsBeforeAfterKeyboardEvent()->mEmbeddedCancelled =
aParam.mEmbeddedCancelled;
return event.forget();
}
// static
already_AddRefed<BeforeAfterKeyboardEvent>
BeforeAfterKeyboardEvent::Constructor(
const GlobalObject& aGlobal,
const nsAString& aType,
const BeforeAfterKeyboardEventInit& aParam,
ErrorResult& aRv)
{
nsCOMPtr<EventTarget> owner = do_QueryInterface(aGlobal.GetAsSupports());
return Constructor(owner, aType, aParam);
}
Nullable<bool>
BeforeAfterKeyboardEvent::GetEmbeddedCancelled()
{
nsAutoString type;
GetType(type);
if (type.EqualsLiteral("mozbrowserafterkeydown") ||
type.EqualsLiteral("mozbrowserafterkeyup")) {
return mEvent->AsBeforeAfterKeyboardEvent()->mEmbeddedCancelled;
}
return Nullable<bool>();
}
} // namespace dom
} // namespace mozilla
using namespace mozilla;
using namespace mozilla::dom;
nsresult
NS_NewDOMBeforeAfterKeyboardEvent(nsIDOMEvent** aInstancePtrResult,
EventTarget* aOwner,
nsPresContext* aPresContext,
InternalBeforeAfterKeyboardEvent* aEvent)
{
BeforeAfterKeyboardEvent* it =
new BeforeAfterKeyboardEvent(aOwner, aPresContext, aEvent);
NS_ADDREF(it);
*aInstancePtrResult = static_cast<Event*>(it);
return NS_OK;
}

Просмотреть файл

@ -0,0 +1,45 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_BeforeAfterKeyboardEvent_h_
#define mozilla_dom_BeforeAfterKeyboardEvent_h_
#include "mozilla/dom/KeyboardEvent.h"
#include "mozilla/dom/BeforeAfterKeyboardEventBinding.h"
namespace mozilla {
namespace dom {
class BeforeAfterKeyboardEvent : public KeyboardEvent
{
public:
BeforeAfterKeyboardEvent(EventTarget* aOwner,
nsPresContext* aPresContext,
InternalBeforeAfterKeyboardEvent* aEvent);
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE
{
return BeforeAfterKeyboardEventBinding::Wrap(aCx, this);
}
static already_AddRefed<BeforeAfterKeyboardEvent>
Constructor(const GlobalObject& aGlobal,
const nsAString& aType,
const BeforeAfterKeyboardEventInit& aParam,
ErrorResult& aRv);
static already_AddRefed<BeforeAfterKeyboardEvent>
Constructor(EventTarget* aOwner, const nsAString& aType,
const BeforeAfterKeyboardEventInit& aEventInitDict);
// This function returns a boolean value when event typs is either
// "mozbrowserafterkeydown" or "mozbrowserafterkeyup".
Nullable<bool> GetEmbeddedCancelled();
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_BeforeAfterKeyboardEvent_h_

Просмотреть файл

@ -701,6 +701,9 @@ EventDispatcher::CreateEvent(EventTarget* aOwner,
case eKeyboardEventClass:
return NS_NewDOMKeyboardEvent(aDOMEvent, aOwner, aPresContext,
aEvent->AsKeyboardEvent());
case eBeforeAfterKeyboardEventClass:
return NS_NewDOMBeforeAfterKeyboardEvent(aDOMEvent, aOwner, aPresContext,
aEvent->AsBeforeAfterKeyboardEvent());
case eCompositionEventClass:
return NS_NewDOMCompositionEvent(aDOMEvent, aOwner, aPresContext,
aEvent->AsCompositionEvent());

Просмотреть файл

@ -237,6 +237,22 @@ EVENT(keyup,
NS_KEY_UP,
EventNameType_HTMLXUL,
eKeyboardEventClass)
NON_IDL_EVENT(mozbrowserbeforekeydown,
NS_KEY_BEFORE_DOWN,
EventNameType_None,
eBeforeAfterKeyboardEventClass)
NON_IDL_EVENT(mozbrowserafterkeydown,
NS_KEY_AFTER_DOWN,
EventNameType_None,
eBeforeAfterKeyboardEventClass)
NON_IDL_EVENT(mozbrowserbeforekeyup,
NS_KEY_BEFORE_UP,
EventNameType_None,
eBeforeAfterKeyboardEventClass)
NON_IDL_EVENT(mozbrowserafterkeyup,
NS_KEY_AFTER_UP,
EventNameType_None,
eBeforeAfterKeyboardEventClass)
EVENT(loadeddata,
NS_LOADEDDATA,
EventNameType_HTML,

Просмотреть файл

@ -651,8 +651,12 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
}
}
// then fall through...
case NS_KEY_BEFORE_DOWN:
case NS_KEY_DOWN:
case NS_KEY_AFTER_DOWN:
case NS_KEY_BEFORE_UP:
case NS_KEY_UP:
case NS_KEY_AFTER_UP:
{
nsIContent* content = GetFocusedContent();
if (content)
@ -3159,7 +3163,9 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext,
GenerateDragDropEnterExit(presContext, aEvent->AsDragEvent());
break;
case NS_KEY_BEFORE_UP:
case NS_KEY_UP:
case NS_KEY_AFTER_UP:
break;
case NS_KEY_PRESS:

Просмотреть файл

@ -979,6 +979,16 @@ IMEStateManager::OnCompositionEventDiscarded(
nsRefPtr<TextComposition> composition =
sTextCompositions->GetCompositionFor(aCompositionEvent->widget);
if (!composition) {
// If the PresShell has been being destroyed during composition,
// a TextComposition instance for the composition was already removed from
// the array and destroyed in OnDestroyPresContext(). Therefore, we may
// fail to retrieve a TextComposition instance here.
PR_LOG(sISMLog, PR_LOG_ALWAYS,
("ISM: IMEStateManager::OnCompositionEventDiscarded(), "
"TextComposition instance for the widget has already gone"));
return;
}
composition->OnCompositionEventDiscarded(aCompositionEvent);
}

Просмотреть файл

@ -17,10 +17,8 @@ KeyboardEvent::KeyboardEvent(EventTarget* aOwner,
: UIEvent(aOwner, aPresContext,
aEvent ? aEvent : new WidgetKeyboardEvent(false, 0, nullptr))
, mInitializedByCtor(false)
, mInitialzedWhichValue(0)
, mInitializedWhichValue(0)
{
NS_ASSERTION(mEvent->mClass == eKeyboardEventClass, "event type mismatch");
if (aEvent) {
mEventIsInternal = false;
}
@ -257,8 +255,12 @@ KeyboardEvent::CharCode()
}
switch (mEvent->message) {
case NS_KEY_UP:
case NS_KEY_BEFORE_DOWN:
case NS_KEY_DOWN:
case NS_KEY_AFTER_DOWN:
case NS_KEY_BEFORE_UP:
case NS_KEY_UP:
case NS_KEY_AFTER_UP:
return 0;
case NS_KEY_PRESS:
return mEvent->AsKeyboardEvent()->charCode;
@ -282,10 +284,7 @@ KeyboardEvent::KeyCode()
return mEvent->AsKeyboardEvent()->keyCode;
}
switch (mEvent->message) {
case NS_KEY_UP:
case NS_KEY_PRESS:
case NS_KEY_DOWN:
if (mEvent->HasKeyEventMessage()) {
return mEvent->AsKeyboardEvent()->keyCode;
}
return 0;
@ -296,12 +295,16 @@ KeyboardEvent::Which()
{
// If this event is initialized with ctor, which can have independent value.
if (mInitializedByCtor) {
return mInitialzedWhichValue;
return mInitializedWhichValue;
}
switch (mEvent->message) {
case NS_KEY_UP:
case NS_KEY_BEFORE_DOWN:
case NS_KEY_DOWN:
case NS_KEY_AFTER_DOWN:
case NS_KEY_BEFORE_UP:
case NS_KEY_UP:
case NS_KEY_AFTER_UP:
return KeyCode();
case NS_KEY_PRESS:
//Special case for 4xp bug 62878. Try to make value of which
@ -343,26 +346,35 @@ KeyboardEvent::Constructor(const GlobalObject& aGlobal,
nsCOMPtr<EventTarget> target = do_QueryInterface(aGlobal.GetAsSupports());
nsRefPtr<KeyboardEvent> newEvent =
new KeyboardEvent(target, nullptr, nullptr);
bool trusted = newEvent->Init(target);
aRv = newEvent->InitKeyEvent(aType, aParam.mBubbles, aParam.mCancelable,
aParam.mView, aParam.mCtrlKey, aParam.mAltKey,
aParam.mShiftKey, aParam.mMetaKey,
aParam.mKeyCode, aParam.mCharCode);
newEvent->SetTrusted(trusted);
newEvent->mDetail = aParam.mDetail;
newEvent->mInitializedByCtor = true;
newEvent->mInitialzedWhichValue = aParam.mWhich;
newEvent->InitWithKeyboardEventInit(target, aType, aParam, aRv);
WidgetKeyboardEvent* internalEvent = newEvent->mEvent->AsKeyboardEvent();
return newEvent.forget();
}
void
KeyboardEvent::InitWithKeyboardEventInit(EventTarget* aOwner,
const nsAString& aType,
const KeyboardEventInit& aParam,
ErrorResult& aRv)
{
bool trusted = Init(aOwner);
aRv = InitKeyEvent(aType, aParam.mBubbles, aParam.mCancelable,
aParam.mView, aParam.mCtrlKey, aParam.mAltKey,
aParam.mShiftKey, aParam.mMetaKey,
aParam.mKeyCode, aParam.mCharCode);
SetTrusted(trusted);
mDetail = aParam.mDetail;
mInitializedByCtor = true;
mInitializedWhichValue = aParam.mWhich;
WidgetKeyboardEvent* internalEvent = mEvent->AsKeyboardEvent();
internalEvent->location = aParam.mLocation;
internalEvent->mIsRepeat = aParam.mRepeat;
internalEvent->mIsComposing = aParam.mIsComposing;
internalEvent->mKeyNameIndex = KEY_NAME_INDEX_USE_STRING;
internalEvent->mKeyValue = aParam.mKey;
internalEvent->mCodeNameIndex = CODE_NAME_INDEX_USE_STRING;
internalEvent->mKeyValue = aParam.mKey;
internalEvent->mCodeValue = aParam.mCode;
return newEvent.forget();
}
NS_IMETHODIMP

Просмотреть файл

@ -74,13 +74,19 @@ public:
protected:
~KeyboardEvent() {}
void InitWithKeyboardEventInit(EventTarget* aOwner,
const nsAString& aType,
const KeyboardEventInit& aParam,
ErrorResult& aRv);
private:
// True, if the instance is created with Constructor().
bool mInitializedByCtor;
// If the instance is created with Constructor(), which may have independent
// value. mInitializedWhichValue stores it. I.e., this is invalid when
// mInitializedByCtor is false.
uint32_t mInitialzedWhichValue;
uint32_t mInitializedWhichValue;
};
} // namespace dom

Просмотреть файл

@ -32,6 +32,7 @@ EXPORTS.mozilla += [
EXPORTS.mozilla.dom += [
'AnimationEvent.h',
'BeforeAfterKeyboardEvent.h',
'BeforeUnloadEvent.h',
'ClipboardEvent.h',
'CommandEvent.h',
@ -71,6 +72,7 @@ if CONFIG['MOZ_WEBSPEECH']:
UNIFIED_SOURCES += [
'AnimationEvent.cpp',
'AsyncEventDispatcher.cpp',
'BeforeAfterKeyboardEvent.cpp',
'BeforeUnloadEvent.cpp',
'ClipboardEvent.cpp',
'CommandEvent.cpp',

Просмотреть файл

@ -0,0 +1,20 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Embedded iframe</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body onload="getFocus();">
<p id="display"></p>
<div id="content" style="display: none"></div>
<input id="input" style="display: block;">
<pre id="test">
<script type="application/javascript">
function getFocus() {
input = document.getElementById("input");
input.focus();
}
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,200 @@
/*
* Constants and helper functions for testing BeforeAfterKeyboardEvent.
*/
const kUnknownEvent = 0x000;
const kKeyDownEvent = 0x001;
const kKeyUpEvent = 0x002;
const kBeforeEvent = 0x010;
const kAfterEvent = 0x020;
const kParent = 0x100;
const kChild = 0x200;
var gCurrentTest;
function frameScript()
{
function handler(e) {
var results = sendSyncMessage("forwardevent", { type: e.type });
if (results[0]) {
e.preventDefault();
}
}
addEventListener('keydown', handler);
addEventListener('keyup', handler);
addEventListener('mozbrowserbeforekeydown', handler);
addEventListener('mozbrowserbeforekeyup', handler);
addEventListener('mozbrowserafterkeydown', handler);
addEventListener('mozbrowserafterkeyup', handler);
}
function prepareTest(useRemote)
{
setupHandlers(window, embedderHandler);
var iframe = document.createElement("iframe");
iframe.id = "embedded";
iframe.src = "bug989198_embedded.html";
iframe.setAttribute("remote", useRemote ? "true" : "false");
SpecialPowers.wrap(iframe).mozbrowser = true;
iframe.addEventListener("mozbrowserloadend", function onloadend() {
iframe.removeEventListener("mozbrowserloadend", onloadend);
iframe.focus();
var mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
mm.addMessageListener("forwardevent", function(msg) {
return embeddedHandler(msg.json);
});
mm.loadFrameScript("data:,(" + frameScript.toString() + ")();", false);
runTests();
return;
});
document.body.appendChild(iframe);
}
function cleanupTest()
{
teardownHandlers(window, embedderHandler);
runTests();
}
function setupHandlers(element, handler)
{
element.addEventListener('keydown', handler);
element.addEventListener('keyup', handler);
element.addEventListener('mozbrowserbeforekeydown', handler);
element.addEventListener('mozbrowserbeforekeyup', handler);
element.addEventListener('mozbrowserafterkeydown', handler);
element.addEventListener('mozbrowserafterkeyup', handler);
}
function teardownHandlers(element, handler)
{
element.removeEventListener('keydown', handler);
element.removeEventListener('keyup', handler);
element.removeEventListener('mozbrowserbeforekeydown', handler);
element.removeEventListener('mozbrowserbeforekeyup', handler);
element.removeEventListener('mozbrowserafterkeydown', handler);
element.removeEventListener('mozbrowserafterkeyup', handler);
}
function convertNameToCode(name)
{
switch (name) {
case "mozbrowserbeforekeydown":
return kBeforeEvent | kKeyDownEvent;
case "mozbrowserafterkeydown":
return kAfterEvent | kKeyDownEvent;
case "mozbrowserbeforekeyup":
return kBeforeEvent | kKeyUpEvent;
case "mozbrowserafterkeyup":
return kAfterEvent | kKeyUpEvent;
case "keydown":
return kKeyDownEvent;
case "keyup":
return kKeyUpEvent;
default:
return kUnknownEvent;
}
}
function classifyEvents(test)
{
// Categorize resultEvents into KEYDOWN group and KEYUP group.
for (var i = 0; i < gCurrentTest.resultEvents.length ; i++) {
var code = test.resultEvents[i];
if ((code & 0xF) == 0x1) { // KEYDOWN
test.classifiedEvents[0].push(code);
} else if ((code & 0xF) == 0x2) { // KEYUP
test.classifiedEvents[1].push(code);
} else {
ok(false, "Invalid code for events");
}
}
}
function verifyResults(test)
{
for (var i = 0; i < gCurrentTest.expectedEvents.length; i++) {
is(test.classifiedEvents[i].length,
test.expectedEvents[i].length,
test.description + ": Wrong number of events");
for (var j = 0; j < gCurrentTest.classifiedEvents[i].length; j++) {
var item = test.classifiedEvents[i][j];
is(item, test.expectedEvents[i][j],
test.description + ": Wrong order of events");
}
}
}
function embeddedHandler(e)
{
return handler(e, kChild);
}
function embedderHandler(e)
{
// Verify value of attribute embeddedCancelled
handler(e, kParent, function checkEmbeddedCancelled(code){
switch (code) {
case kBeforeEvent | kKeyDownEvent:
case kBeforeEvent | kKeyUpEvent:
is(e.embeddedCancelled, null,
gCurrentTest.description + ': embeddedCancelled should be null');
break;
case kAfterEvent | kKeyDownEvent:
if ((gCurrentTest.doPreventDefaultAt & 0xFF) == kKeyDownEvent) {
is(e.embeddedCancelled, true,
gCurrentTest.description + ': embeddedCancelled should be true');
} else {
is(e.embeddedCancelled, false,
gCurrentTest.description + ': embeddedCancelled should be false');
}
break;
case kAfterEvent | kKeyUpEvent:
if ((gCurrentTest.doPreventDefaultAt & 0xFF) == kKeyUpEvent) {
is(e.embeddedCancelled, true,
gCurrentTest.description + ': embeddedCancelled should be true');
} else {
is(e.embeddedCancelled, false,
gCurrentTest.description + ': embeddedCancelled should be false');
}
break;
default:
break;
}
});
}
function handler(e, highBit, callback)
{
var code = convertNameToCode(e.type);
var newCode = highBit | code;
gCurrentTest.resultEvents.push(newCode);
if (callback) {
callback(code);
}
// Return and let frameScript to handle
if (highBit == kChild) {
return newCode == gCurrentTest.doPreventDefaultAt;
}
if (newCode == gCurrentTest.doPreventDefaultAt) {
e.preventDefault();
}
}
function runTests()
{
if (!tests.length) {
SimpleTest.finish();
return;
}
var test = tests.shift();
test();
}

Просмотреть файл

@ -166,3 +166,12 @@ skip-if = buildapp == 'mulet'
[test_onerror_handler_args.html]
[test_wheel_default_action.html]
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || e10s
[test_dom_before_after_keyboard_event.html]
support-files =
bug989198_embedded.html
bug989198_helper.js
[test_dom_before_after_keyboard_event_remote.html]
support-files =
bug989198_embedded.html
bug989198_helper.js
skip-if = buildapp == 'b2g' || e10s

Просмотреть файл

@ -34,6 +34,10 @@ const kEventConstructors = {
},
AudioProcessingEvent: { create: null, // Cannot create untrusted event from JS.
},
BeforeAfterKeyboardEvent: { create: function (aName, aProps) {
return new BeforeAfterKeyboardEvent(aName, aProps);
},
},
BeforeUnloadEvent: { create: function (aName, aProps) {
var e = document.createEvent("beforeunloadevent");
e.initEvent(aName, aProps.bubbles, aProps.cancelable);

Просмотреть файл

@ -0,0 +1,117 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Bug 989198</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/NativeKeyCodes.js"></script>
<script type="text/javascript" src="bug989198_helper.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body onload="runTests();">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=989198">Mozilla Bug 989198</a>
<p id="display"></p>
<pre id="test">
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
function testEventOrderAndAttr()
{
const mainDesc = 'Testing the order of the events';
const kTests = [
{
description: mainDesc,
expectedEvents: [ [ kParent | kBeforeEvent | kKeyDownEvent,
kChild | kKeyDownEvent,
kParent | kAfterEvent | kKeyDownEvent ],
[ kParent | kBeforeEvent | kKeyUpEvent,
kChild | kKeyUpEvent,
kParent | kAfterEvent | kKeyUpEvent ] ],
resultEvents: [],
classifiedEvents: [ [], [] ],
doPreventDefaultAt: kUnknownEvent
},
{
description: mainDesc + ', calling preventDefault() at "mozbrowserbeforekeydown" event',
expectedEvents: [ [ kParent | kBeforeEvent | kKeyDownEvent,
kParent | kAfterEvent | kKeyDownEvent ],
[ kParent | kBeforeEvent | kKeyUpEvent,
kChild | kKeyUpEvent,
kParent | kAfterEvent | kKeyUpEvent ] ],
resultEvents: [],
classifiedEvents: [ [], [] ],
doPreventDefaultAt: kParent | kBeforeEvent | kKeyDownEvent
},
{
description: mainDesc + ', calling preventDefault() at "mozbrowserbeforekeyup" event',
expectedEvents: [ [ kParent | kBeforeEvent | kKeyDownEvent,
kChild | kKeyDownEvent,
kParent | kAfterEvent | kKeyDownEvent ],
[ kParent | kBeforeEvent | kKeyUpEvent,
kParent | kAfterEvent | kKeyUpEvent ] ],
resultEvents: [],
classifiedEvents: [ [], [] ],
doPreventDefaultAt: kParent | kBeforeEvent | kKeyUpEvent
},
{
description: mainDesc + ', calling preventDefault() at "keydown" event',
expectedEvents: [ [ kParent | kBeforeEvent | kKeyDownEvent,
kChild | kKeyDownEvent,
kParent | kAfterEvent | kKeyDownEvent ],
[ kParent | kBeforeEvent | kKeyUpEvent,
kChild | kKeyUpEvent,
kParent | kAfterEvent | kKeyUpEvent ] ],
resultEvents: [],
classifiedEvents: [ [], [] ],
doPreventDefaultAt: kChild | kKeyDownEvent
},
{
description: mainDesc + ', calling preventDefault() at "keyup" event',
expectedEvents: [ [ kParent | kBeforeEvent | kKeyDownEvent,
kChild | kKeyDownEvent,
kParent | kAfterEvent | kKeyDownEvent ],
[ kParent | kBeforeEvent | kKeyUpEvent,
kChild | kKeyUpEvent,
kParent | kAfterEvent | kKeyUpEvent ] ],
resultEvents: [],
classifiedEvents: [ [], [] ],
doPreventDefaultAt: kChild | kKeyUpEvent
}
];
for (var k = 0; k < kTests.length; k++ ) {
gCurrentTest = kTests[k];
synthesizeKey('a', {}, document.getElementById("embedded").contentWindow);
classifyEvents(kTests[k]);
verifyResults(kTests[k]);
}
runTests();
}
var tests = [
function addPermissions() {
SpecialPowers.pushPermissions(
[{ type: "before-after-keyboard-event", allow: true, context: document },
{ type: "browser", allow: true, context: document }],
runTests);
},
function addPreferences() {
SpecialPowers.pushPrefEnv(
{ "set": [["dom.beforeAfterKeyboardEvent.enabled", true],
["dom.mozBrowserFramesEnabled", true],
["dom.ipc.tabs.disabled", false]] },
runTests);
},
// Tests for in-process iframe, i.e. <iframe mozbrowser>.
()=>prepareTest(false),
testEventOrderAndAttr,
cleanupTest,
];
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,142 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Bug 989198</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/NativeKeyCodes.js"></script>
<script type="text/javascript" src="bug989198_helper.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body onload="runTests();">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=989198">Mozilla Bug 989198</a>
<p id="display"></p>
<div id="content">
</div>
<pre id="test">
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
const mainDesc = 'Testing the order of the events (OOP)';
var testsForEventOrder = [
{
description: mainDesc,
expectedEvents: [ [ kParent | kBeforeEvent | kKeyDownEvent,
kParent | kKeyDownEvent,
kChild | kKeyDownEvent,
kParent | kAfterEvent | kKeyDownEvent ],
[ kParent | kBeforeEvent | kKeyUpEvent,
kParent | kKeyUpEvent,
kChild | kKeyUpEvent,
kParent | kAfterEvent | kKeyUpEvent ] ],
resultEvents: [],
classifiedEvents: [ [], [] ],
doPreventDefaultAt: kUnknownEvent
},
{
description: mainDesc + ', calling preventDefault() at "mozbrowserbeforekeydown" event',
expectedEvents: [ [ kParent | kBeforeEvent | kKeyDownEvent,
kParent | kAfterEvent | kKeyDownEvent ],
[ kParent | kBeforeEvent | kKeyUpEvent,
kParent | kKeyUpEvent,
kChild | kKeyUpEvent,
kParent | kAfterEvent | kKeyUpEvent ] ],
resultEvents: [],
classifiedEvents: [ [], [] ],
doPreventDefaultAt: kParent | kBeforeEvent | kKeyDownEvent
},
{
description: mainDesc + ', calling preventDefault() at "mozbrowserbeforekeyup" event',
expectedEvents: [ [ kParent | kBeforeEvent | kKeyDownEvent,
kParent | kKeyDownEvent,
kChild | kKeyDownEvent,
kParent | kAfterEvent | kKeyDownEvent ],
[ kParent | kBeforeEvent | kKeyUpEvent,
kParent | kAfterEvent | kKeyUpEvent ] ],
resultEvents: [],
classifiedEvents: [ [], [] ],
doPreventDefaultAt: kParent | kBeforeEvent | kKeyUpEvent
},
{
description: mainDesc + ', calling preventDefault() at "keydown" event',
expectedEvents: [ [ kParent | kBeforeEvent | kKeyDownEvent,
kParent | kKeyDownEvent,
kChild | kKeyDownEvent,
kParent | kAfterEvent | kKeyDownEvent ],
[ kParent | kBeforeEvent | kKeyUpEvent,
kParent | kKeyUpEvent,
kChild | kKeyUpEvent,
kParent | kAfterEvent | kKeyUpEvent ] ],
resultEvents: [],
classifiedEvents: [ [], [] ],
doPreventDefaultAt: kChild | kKeyDownEvent
},
{
description: mainDesc + ', calling preventDefault() at "keyup" event',
expectedEvents: [ [ kParent | kBeforeEvent | kKeyDownEvent,
kParent | kKeyDownEvent,
kChild | kKeyDownEvent,
kParent | kAfterEvent | kKeyDownEvent ],
[ kParent | kBeforeEvent | kKeyUpEvent,
kParent | kKeyUpEvent,
kChild | kKeyUpEvent,
kParent | kAfterEvent | kKeyUpEvent ] ],
resultEvents: [],
classifiedEvents: [ [], [] ],
doPreventDefaultAt: kChild | kKeyUpEvent
}
];
function testEventOrder()
{
if (!testsForEventOrder.length) {
runTests();
return;
}
gCurrentTest = testsForEventOrder.shift();
synthesizeKey('a', {}, document.getElementById("embedded").contentWindow);
// It take some time to propagate events to a remote iframe.
waitAndVerifyResult(0);
}
function waitAndVerifyResult(count) {
expectedEventLength = gCurrentTest.expectedEvents[0].length +
gCurrentTest.expectedEvents[1].length;
if (gCurrentTest.resultEvents.length >= expectedEventLength || count > 10) {
classifyEvents(gCurrentTest);
verifyResults(gCurrentTest);
testEventOrder();
}
else {
setTimeout(()=>waitAndVerifyResult(count + 1), 100);
}
}
var tests = [
function addPermissions() {
SpecialPowers.pushPermissions(
[{ type: "before-after-keyboard-event", allow: true, context: document },
{ type: "browser", allow: true, context: document }],
runTests);
},
function addPreferences() {
SpecialPowers.pushPrefEnv(
{ "set": [["dom.beforeAfterKeyboardEvent.enabled", true],
["dom.mozBrowserFramesEnabled", true],
["dom.ipc.tabs.disabled", false]] },
runTests);
},
// Tests for out-of-process iframe, i.el. <iframe mozbrowser remote>
()=>prepareTest(true),
testEventOrder,
cleanupTest
];
</script>
</body>
</html>

Просмотреть файл

@ -918,7 +918,9 @@ nsGeolocationService::UpdateAccuracy(bool aForceHigh)
if (XRE_GetProcessType() == GeckoProcessType_Content) {
ContentChild* cpc = ContentChild::GetSingleton();
cpc->SendSetGeolocationHigherAccuracy(highRequired);
if (cpc->IsAlive()) {
cpc->SendSetGeolocationHigherAccuracy(highRequired);
}
return;
}

Просмотреть файл

@ -272,6 +272,13 @@ NS_NewDOMKeyboardEvent(nsIDOMEvent** aInstancePtrResult,
mozilla::dom::EventTarget* aOwner,
nsPresContext* aPresContext,
mozilla::WidgetKeyboardEvent* aEvent);
nsresult
NS_NewDOMBeforeAfterKeyboardEvent(nsIDOMEvent** aInstancePtrResult,
mozilla::dom::EventTarget* aOwner,
nsPresContext* aPresContext,
mozilla::InternalBeforeAfterKeyboardEvent* aEvent);
nsresult
NS_NewDOMCompositionEvent(nsIDOMEvent** aInstancePtrResult,
mozilla::dom::EventTarget* aOwner,

Просмотреть файл

@ -515,12 +515,22 @@ InitOnContentProcessCreated()
mozilla::dom::time::InitializeDateCacheCleaner();
}
#if defined(MOZ_TASK_TRACER) && defined(MOZ_NUWA_PROCESS)
static void
ReinitTaskTracer(void* /*aUnused*/)
{
mozilla::tasktracer::InitTaskTracer(
mozilla::tasktracer::FORKED_AFTER_NUWA);
}
#endif
ContentChild::ContentChild()
: mID(uint64_t(-1))
#ifdef ANDROID
,mScreenSize(0, 0)
#endif
, mCanOverrideProcessName(true)
, mIsAlive(true)
{
// This process is a content process, so it's clearly running in
// multiprocess mode!
@ -594,6 +604,12 @@ ContentChild::Init(MessageLoop* aIOLoop,
SendGetProcessAttributes(&mID, &mIsForApp, &mIsForBrowser);
InitProcessAttributes();
#if defined(MOZ_TASK_TRACER) && defined (MOZ_NUWA_PROCESS)
if (IsNuwaProcess()) {
NuwaAddConstructor(ReinitTaskTracer, nullptr);
}
#endif
return true;
}
@ -653,6 +669,12 @@ ContentChild::GetProcessName(nsAString& aName)
aName.Assign(mProcessName);
}
bool
ContentChild::IsAlive()
{
return mIsAlive;
}
void
ContentChild::GetProcessName(nsACString& aName)
{
@ -1625,6 +1647,7 @@ ContentChild::ActorDestroy(ActorDestroyReason why)
svc->UnregisterListener(mConsoleListener);
mConsoleListener->mChild = nullptr;
}
mIsAlive = false;
XRE_ShutdownChildProcess();
}

Просмотреть файл

@ -87,10 +87,10 @@ public:
const AppInfo& GetAppInfo() {
return mAppInfo;
}
void SetProcessName(const nsAString& aName, bool aDontOverride = false);
void GetProcessName(nsAString& aName);
void GetProcessName(nsACString& aName);
bool IsAlive();
static void AppendProcessId(nsACString& aName);
ContentBridgeParent* GetLastBridge() {
@ -421,6 +421,7 @@ private:
bool mIsForApp;
bool mIsForBrowser;
bool mCanOverrideProcessName;
bool mIsAlive;
nsString mProcessName;
static ContentChild* sSingleton;

Просмотреть файл

@ -398,6 +398,8 @@ parent:
ReplyKeyEvent(WidgetKeyboardEvent event);
DispatchAfterKeyboardEvent(WidgetKeyboardEvent event);
sync RequestNativeKeyBindings(WidgetKeyboardEvent event)
returns (MaybeNativeKeyBinding bindings);

Просмотреть файл

@ -81,8 +81,8 @@
#include "ClientLayerManager.h"
#include "LayersLogging.h"
#include "nsIOService.h"
#include "nsColorPickerProxy.h"
#include "nsPresShell.h"
#define BROWSER_ELEMENT_CHILD_SCRIPT \
NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js")
@ -2362,6 +2362,10 @@ TabChild::RecvRealKeyEvent(const WidgetKeyboardEvent& event,
SendReplyKeyEvent(localEvent);
}
if (PresShell::BeforeAfterKeyboardEventEnabled()) {
SendDispatchAfterKeyboardEvent(localEvent);
}
return true;
}

Просмотреть файл

@ -52,6 +52,7 @@
#include "nsIWindowWatcher.h"
#include "nsPIDOMWindow.h"
#include "nsPIWindowWatcher.h"
#include "nsPresShell.h"
#include "nsPrintfCString.h"
#include "nsServiceManagerUtils.h"
#include "nsThreadUtils.h"
@ -1463,6 +1464,29 @@ TabParent::RecvReplyKeyEvent(const WidgetKeyboardEvent& event)
return true;
}
bool
TabParent::RecvDispatchAfterKeyboardEvent(const WidgetKeyboardEvent& aEvent)
{
NS_ENSURE_TRUE(mFrameElement, true);
WidgetKeyboardEvent localEvent(aEvent);
localEvent.widget = GetWidget();
nsIDocument* doc = mFrameElement->OwnerDoc();
nsCOMPtr<nsIPresShell> presShell = doc->GetShell();
NS_ENSURE_TRUE(presShell, true);
if (mFrameElement &&
PresShell::BeforeAfterKeyboardEventEnabled() &&
localEvent.message != NS_KEY_PRESS) {
nsCOMPtr<nsINode> node(do_QueryInterface(mFrameElement));
presShell->DispatchAfterKeyboardEvent(mFrameElement, localEvent,
aEvent.mFlags.mDefaultPrevented);
}
return true;
}
/**
* Try to answer query event using cached text.
*

Просмотреть файл

@ -122,6 +122,7 @@ public:
virtual bool RecvMoveFocus(const bool& aForward) MOZ_OVERRIDE;
virtual bool RecvEvent(const RemoteDOMEvent& aEvent) MOZ_OVERRIDE;
virtual bool RecvReplyKeyEvent(const WidgetKeyboardEvent& event);
virtual bool RecvDispatchAfterKeyboardEvent(const WidgetKeyboardEvent& event);
virtual bool RecvPRenderFrameConstructor(PRenderFrameParent* aActor,
ScrollingBehavior* aScrolling,
TextureFactoryIdentifier* aFactoryIdentifier,

Просмотреть файл

@ -36,13 +36,16 @@ const NFC_ENABLED = libcutils.property_get("ro.moz.nfc.enabled", "false") === "t
let DEBUG = NFC.DEBUG_CONTENT_HELPER;
let debug;
if (DEBUG) {
debug = function (s) {
dump("-*- NfcContentHelper: " + s + "\n");
};
} else {
debug = function (s) {};
}
function updateDebug() {
if (DEBUG) {
debug = function (s) {
dump("-*- NfcContentHelper: " + s + "\n");
};
} else {
debug = function (s) {};
}
};
updateDebug();
const NFCCONTENTHELPER_CID =
Components.ID("{4d72c120-da5f-11e1-9b23-0800200c9a66}");
@ -65,6 +68,8 @@ XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
function NfcContentHelper() {
this.initDOMRequestHelper(/* aWindow */ null, NFC_IPC_MSG_NAMES);
Services.obs.addObserver(this, NFC.TOPIC_MOZSETTINGS_CHANGED, false);
Services.obs.addObserver(this, "xpcom-shutdown", false);
this._requestMap = [];
@ -86,6 +91,17 @@ NfcContentHelper.prototype = {
_requestMap: null,
eventTarget: null,
init: function init(aWindow) {
if (aWindow && aWindow.navigator.mozSettings) {
let lock = aWindow.navigator.mozSettings.createLock();
var nfcDebug = lock.get(NFC.SETTING_NFC_DEBUG);
nfcDebug.onsuccess = function _nfcDebug() {
DEBUG = nfcDebug.result[NFC.SETTING_NFC_DEBUG];
updateDebug();
};
}
},
encodeNDEFRecords: function encodeNDEFRecords(records) {
let encodedRecords = [];
for (let i = 0; i < records.length; i++) {
@ -328,8 +344,16 @@ NfcContentHelper.prototype = {
observe: function observe(subject, topic, data) {
if (topic == "xpcom-shutdown") {
this.destroyDOMRequestHelper();
Services.obs.removeObserver(this, NFC.TOPIC_MOZSETTINGS_CHANGED);
Services.obs.removeObserver(this, "xpcom-shutdown");
cpmm = null;
} else if (topic == NFC.TOPIC_MOZSETTINGS_CHANGED) {
if ("wrappedJSObject" in subject) {
subject = subject.wrappedJSObject;
}
if (subject) {
this.handle(subject.key, subject.value);
}
}
},
@ -395,6 +419,15 @@ NfcContentHelper.prototype = {
}
},
handle: function handle(name, result) {
switch (name) {
case NFC.SETTING_NFC_DEBUG:
DEBUG = result;
updateDebug();
break;
}
},
handleReadNDEFResponse: function handleReadNDEFResponse(result) {
let requester = this._requestMap[result.requestId];
if (!requester) {

Просмотреть файл

@ -22,6 +22,10 @@ const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService",
"@mozilla.org/settingsService;1",
"nsISettingsService");
XPCOMUtils.defineLazyGetter(this, "NFC", function () {
let obj = {};
Cu.import("resource://gre/modules/nfc_consts.js", obj);
@ -35,13 +39,16 @@ const NFC_ENABLED = libcutils.property_get("ro.moz.nfc.enabled", "false") === "t
let DEBUG = NFC.DEBUG_NFC;
let debug;
if (DEBUG) {
debug = function (s) {
dump("-*- Nfc: " + s + "\n");
};
} else {
debug = function (s) {};
}
function updateDebug() {
if (DEBUG) {
debug = function (s) {
dump("-*- Nfc: " + s + "\n");
};
} else {
debug = function (s) {};
}
};
updateDebug();
const NFC_CONTRACTID = "@mozilla.org/nfc;1";
const NFC_CID =
@ -103,6 +110,10 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () {
init: function init(nfc) {
this.nfc = nfc;
let lock = gSettingsService.createLock();
lock.get(NFC.SETTING_NFC_DEBUG, this.nfc);
Services.obs.addObserver(this, NFC.TOPIC_MOZSETTINGS_CHANGED, false);
Services.obs.addObserver(this, NFC.TOPIC_XPCOM_SHUTDOWN, false);
this._registerMessageListeners();
},
@ -111,6 +122,7 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () {
this.nfc.shutdown();
this.nfc = null;
Services.obs.removeObserver(this, NFC.TOPIC_MOZSETTINGS_CHANGED);
Services.obs.removeObserver(this, NFC.TOPIC_XPCOM_SHUTDOWN);
this._unregisterMessageListeners();
},
@ -335,6 +347,14 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () {
observe: function observe(subject, topic, data) {
switch (topic) {
case NFC.TOPIC_MOZSETTINGS_CHANGED:
if ("wrappedJSObject" in subject) {
subject = subject.wrappedJSObject;
}
if (subject) {
this.nfc.handle(subject.key, subject.value);
}
break;
case NFC.TOPIC_XPCOM_SHUTDOWN:
this._shutdown();
break;
@ -649,6 +669,18 @@ Nfc.prototype = {
});
},
/**
* nsISettingsServiceCallback
*/
handle: function handle(name, result) {
switch (name) {
case NFC.SETTING_NFC_DEBUG:
DEBUG = result;
updateDebug();
break;
}
},
/**
* nsIObserver interface methods.
*/

Просмотреть файл

@ -105,8 +105,11 @@ this.NFC_POWER_LEVEL_DISABLED = 0;
this.NFC_POWER_LEVEL_LOW = 1;
this.NFC_POWER_LEVEL_ENABLED = 2;
this.TOPIC_MOZSETTINGS_CHANGED = "mozsettings-changed";
this.TOPIC_XPCOM_SHUTDOWN = "xpcom-shutdown";
this.SETTING_NFC_DEBUG = "nfc.debugging.enabled";
this.NFC_PEER_EVENT_READY = 0x01;
this.NFC_PEER_EVENT_LOST = 0x02;

Просмотреть файл

@ -27,12 +27,14 @@ interface nsINfcDOMEventTarget : nsISupports
void notifyPeerLost(in DOMString sessionToken);
};
[scriptable, uuid(d3f1bdc1-048f-44a8-abe2-bc386edce40b)]
[scriptable, uuid(cb9c934d-a7fa-422b-bcc1-4ac39741e6ec)]
interface nsINfcContentHelper : nsISupports
{
const long NFC_EVENT_PEER_READY = 0x01;
const long NFC_EVENT_PEER_LOST = 0x02;
void init(in nsIDOMWindow window);
boolean checkSessionToken(in DOMString sessionToken);
nsIDOMDOMRequest readNDEF(in nsIDOMWindow window, in DOMString sessionToken);

Просмотреть файл

@ -148,6 +148,9 @@ mozNfc.prototype = {
init: function init(aWindow) {
debug("mozNfc init called");
this._window = aWindow;
if (this._nfcContentHelper) {
this._nfcContentHelper.init(aWindow);
}
},
// Only apps which have nfc-manager permission can call the following interfaces

Просмотреть файл

@ -1316,17 +1316,8 @@ function sendMMI(aMmi) {
let deferred = Promise.defer();
telephony.dial(aMmi)
.then(request => {
ok(request instanceof DOMRequest,
"request is instanceof " + request.constructor);
request.addEventListener("success", function(event) {
deferred.resolve(request.result);
});
request.addEventListener("error", function(event) {
deferred.reject(request.error);
});
.then(result => {
deferred.resolve(result);
}, cause => {
deferred.reject(cause);
});

Просмотреть файл

@ -1,5 +1,4 @@
[DEFAULT]
skip-if = !debug || (buildapp == 'b2g') || (toolkit == 'android') #Bug 932350 - Frequent timeouts
support-files =
child_ip_address.html
file_crossdomainprops_inner.html
@ -10,6 +9,7 @@ support-files =
[test_crossdomainprops.html]
[test_innerWidthHeight_script.html]
skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'android' # Bug 1075071 - Permafail on Android/B2G/Mulet
[test_location.html]
[test_location_framed.html]
[test_location_getters.html]

Просмотреть файл

@ -1,5 +1,5 @@
[DEFAULT]
skip-if = !debug || (buildapp == 'b2g') || (toolkit == 'android') #android(bug 910229) #Bug 932350 - Frequent timeouts
skip-if = toolkit == 'gonk' || toolkit == 'android' # Bug 932350 - Frequent timeouts
support-files =
DOMTestCase.js
activity-home.css

Просмотреть файл

@ -1,5 +1,5 @@
[DEFAULT]
skip-if = !debug || (buildapp == 'b2g') || (toolkit == 'android') # android(bug 910229) #Bug 932350 - Frequent timeouts
skip-if = toolkit == 'gonk' || toolkit == 'android' # Bug 932350 - Frequent timeouts
support-files =
DOMTestCase.js
exclusions.js

Просмотреть файл

@ -1,5 +1,5 @@
[DEFAULT]
skip-if = !debug || (buildapp == 'b2g') || (toolkit == 'android') #android(bug 910229) #Bug 932350 - Frequent timeouts
skip-if = toolkit == 'gonk' || toolkit == 'android' # Bug 932350 - Frequent timeouts
support-files =
DOMTestCase.js
files/anchor.html

Просмотреть файл

@ -171,6 +171,10 @@ var interfaceNamesInGlobalScope =
"BarProp",
// IMPORTANT: Do not change this list without review from a DOM peer!
"BatteryManager",
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BeforeAfterKeyboardEvent", b2g: true,
pref: "dom.beforeAfterKeyboardEvent.enabled",
permission: ["embed-apps", "before-after-keyboard-event"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
"BeforeUnloadEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!
@ -180,18 +184,18 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
"BlobEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BluetoothAdapter", b2g: true, permission: "bluetooth"},
{name: "BluetoothAdapter", b2g: true, permission: ["bluetooth"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BluetoothDevice", b2g: true, permission: "bluetooth"},
{name: "BluetoothDevice", b2g: true, permission: ["bluetooth"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BluetoothDeviceEvent", b2g: true, permission: "bluetooth"},
{name: "BluetoothDeviceEvent", b2g: true, permission: ["bluetooth"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BluetoothDiscoveryStateChangedEvent", b2g: true,
permission: "bluetooth"},
permission: ["bluetooth"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BluetoothManager", b2g: true, permission: "bluetooth"},
{name: "BluetoothManager", b2g: true, permission: ["bluetooth"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BluetoothStatusChangedEvent", b2g: true, permission: "bluetooth"},
{name: "BluetoothStatusChangedEvent", b2g: true, permission: ["bluetooth"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BoxObject", xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
@ -751,7 +755,7 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
"MozSettingsEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozSettingsTransactionEvent", permission: "settings-api-read"},
{name: "MozSettingsTransactionEvent", permission: ["settings-api-read"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
"MozSmsEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!
@ -771,23 +775,23 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWakeLock", b2g: true, pref: "dom.wakelock.enabled"},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWifiCapabilities", b2g: true, permission: "wifi-manage"},
{name: "MozWifiCapabilities", b2g: true, permission: ["wifi-manage"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWifiConnectionInfoEvent", b2g: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWifiStationInfoEvent", b2g: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWifiManager", b2g: true, permission: "wifi-manage"},
{name: "MozWifiManager", b2g: true, permission: ["wifi-manage"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWifiNetwork", b2g: true, permission: "wifi-manage"},
{name: "MozWifiNetwork", b2g: true, permission: ["wifi-manage"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWifiStatusChangeEvent", b2g: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWifiP2pGroupOwner", b2g: true, permission: "wifi-manage"},
{name: "MozWifiP2pGroupOwner", b2g: true, permission: ["wifi-manage"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWifiP2pManager", b2g: true, permission: "wifi-manage"},
{name: "MozWifiP2pManager", b2g: true, permission: ["wifi-manage"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MozWifiP2pStatusChangeEvent", b2g: true, permission: "wifi-manage"},
{name: "MozWifiP2pStatusChangeEvent", b2g: true, permission: ["wifi-manage"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
"MutationEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!
@ -845,9 +849,9 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
"PeriodicWave",
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "PermissionSettings", b2g: true, permission: "permissions"},
{name: "PermissionSettings", b2g: true, permission: ["permissions"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "PhoneNumberService", permission: "phonenumberservice"},
{name: "PhoneNumberService", permission: ["phonenumberservice"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
"Plugin",
// IMPORTANT: Do not change this list without review from a DOM peer!
@ -1227,9 +1231,11 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
"TreeWalker",
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "UDPMessageEvent", pref: "dom.udpsocket.enabled", permission: "udp-socket"},
{name: "UDPMessageEvent", pref: "dom.udpsocket.enabled",
permission: ["udp-socket"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "UDPSocket", pref: "dom.udpsocket.enabled", permission: "udp-socket"},
{name: "UDPSocket", pref: "dom.udpsocket.enabled",
permission: ["udp-socket"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
"UIEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!
@ -1339,8 +1345,12 @@ function createInterfaceMap(isXBLScope) {
var isRelease = !version.contains("a");
var isDesktop = !/Mobile|Tablet/.test(navigator.userAgent);
var isB2G = !isDesktop && !navigator.userAgent.contains("Android");
var hasPermission = function (aPermission) {
return SpecialPowers.hasPermission(aPermission, window.document);
var hasPermission = function (aPermissions) {
var result = false;
for (var p of aPermissions) {
result = result || SpecialPowers.hasPermission(p, window.document);
}
return result;
};
var interfaceMap = {};

Просмотреть файл

@ -0,0 +1,24 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
[Constructor(DOMString typeArg,
optional BeforeAfterKeyboardEventInit eventInitDict),
CheckPermissions="embed-apps before-after-keyboard-event",
Pref="dom.beforeAfterKeyboardEvent.enabled"]
interface BeforeAfterKeyboardEvent : KeyboardEvent
{
// The valid value of embeddedCancelled is:
// - "mozbrowserbeforekeydown": null
// - "mozbrowserbeforekeyup": null
// - "mozbrowserafterkeydown": true/false
// - "mozbrowserafterkeyup": true/false
readonly attribute boolean? embeddedCancelled;
};
dictionary BeforeAfterKeyboardEventInit : KeyboardEventInit
{
boolean? embeddedCancelled = null;
};

Просмотреть файл

@ -3,8 +3,10 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
interface DOMCursor : DOMRequest {
interface DOMCursor : EventTarget {
readonly attribute boolean done;
[Throws]
void continue();
};
DOMCursor implements DOMRequestShared;

Просмотреть файл

@ -5,7 +5,8 @@
enum DOMRequestReadyState { "pending", "done" };
interface DOMRequest : EventTarget {
[NoInterfaceObject]
interface DOMRequestShared {
readonly attribute DOMRequestReadyState readyState;
readonly attribute any result;
@ -14,3 +15,13 @@ interface DOMRequest : EventTarget {
attribute EventHandler onsuccess;
attribute EventHandler onerror;
};
interface DOMRequest : EventTarget {
// The [TreatNonCallableAsNull] annotation is required since then() should do
// nothing instead of throwing errors when non-callable arguments are passed.
[NewObject, Throws]
Promise<any> then([TreatNonCallableAsNull] optional AnyCallback? fulfillCallback = null,
[TreatNonCallableAsNull] optional AnyCallback? rejectCallback = null);
};
DOMRequest implements DOMRequestShared;

Просмотреть файл

@ -49,6 +49,7 @@ WEBIDL_FILES = [
'AutocompleteInfo.webidl',
'BarProp.webidl',
'BatteryManager.webidl',
'BeforeAfterKeyboardEvent.webidl',
'BeforeUnloadEvent.webidl',
'BiquadFilterNode.webidl',
'Blob.webidl',

Просмотреть файл

@ -545,9 +545,8 @@ static const FeatureInfo sFeatureInfoArr[] = {
"transform_feedback2",
400, // OpenGL version
300, // OpenGL ES version
GLContext::Extension_None,
GLContext::ARB_transform_feedback2,
{
GLContext::ARB_transform_feedback2,
GLContext::NV_transform_feedback2,
GLContext::Extensions_End
}

Просмотреть файл

@ -652,7 +652,12 @@ AddressOf(AsmJSImmKind kind, ExclusiveContext *cx)
case AsmJSImm_ModD:
return RedirectCall(FuncCast(NumberMod), Args_Double_DoubleDouble);
case AsmJSImm_SinD:
#ifdef _WIN64
// Workaround a VS 2013 sin issue, see math_sin_uncached.
return RedirectCall(FuncCast<double (double)>(js::math_sin_uncached), Args_Double_Double);
#else
return RedirectCall(FuncCast<double (double)>(sin), Args_Double_Double);
#endif
case AsmJSImm_CosD:
return RedirectCall(FuncCast<double (double)>(cos), Args_Double_Double);
case AsmJSImm_TanD:

Просмотреть файл

@ -516,7 +516,7 @@ class StructTypeDescr : public ComplexTypeDescr
}
NativeObject &maybeForwardedFieldInfoObject(size_t slot) const {
return *MaybeForwarded(&fieldInfoObject(slot));
return MaybeForwarded(&getReservedSlot(slot).toObject())->as<NativeObject>();
}
};

Просмотреть файл

@ -472,6 +472,7 @@ class GCRuntime
template <AllowGC allowGC>
static void *refillFreeListFromAnyThread(ThreadSafeContext *cx, AllocKind thingKind);
static void *refillFreeListInGC(Zone *zone, AllocKind thingKind);
private:
// For ArenaLists::allocateFromArena()
@ -483,7 +484,6 @@ class GCRuntime
static void *refillFreeListFromMainThread(JSContext *cx, AllocKind thingKind);
static void *refillFreeListOffMainThread(ExclusiveContext *cx, AllocKind thingKind);
static void *refillFreeListPJS(ForkJoinContext *cx, AllocKind thingKind);
static void *refillFreeListInGC(Zone *zone, AllocKind thingKind);
/*
* Return the list of chunks that can be released outside the GC lock.

Просмотреть файл

@ -4008,6 +4008,7 @@ CodeGenerator::emitDebugResultChecks(LInstruction *ins)
default:
return true;
}
return true;
}
#endif
@ -7459,10 +7460,18 @@ CodeGenerator::link(JSContext *cx, types::CompilerConstraintList *constraints)
// Check to make sure we didn't have a mid-build invalidation. If so, we
// will trickle to jit::Compile() and return Method_Skipped.
uint32_t warmUpCount = script->getWarmUpCount();
types::RecompileInfo recompileInfo;
if (!types::FinishCompilation(cx, script, executionMode, constraints, &recompileInfo))
return true;
// IonMonkey could have inferred better type information during
// compilation. Since adding the new information to the actual type
// information can reset the usecount, increase it back to what it was
// before.
if (warmUpCount > script->getWarmUpCount())
script->incWarmUpCounter(warmUpCount - script->getWarmUpCount());
uint32_t scriptFrameSize = frameClass_ == FrameSizeClass::None()
? frameDepth_
: FrameSizeClass::FromDepth(frameDepth_).frameSize();
@ -9720,18 +9729,31 @@ CodeGenerator::visitAsmJSInterruptCheck(LAsmJSInterruptCheck *lir)
typedef bool (*RecompileFn)(JSContext *);
static const VMFunction RecompileFnInfo = FunctionInfo<RecompileFn>(Recompile);
typedef bool (*ForcedRecompileFn)(JSContext *);
static const VMFunction ForcedRecompileFnInfo = FunctionInfo<ForcedRecompileFn>(ForcedRecompile);
bool
CodeGenerator::visitRecompileCheck(LRecompileCheck *ins)
{
Label done;
Register tmp = ToRegister(ins->scratch());
OutOfLineCode *ool = oolCallVM(RecompileFnInfo, ins, (ArgList()), StoreRegisterTo(tmp));
OutOfLineCode *ool;
if (ins->mir()->forceRecompilation())
ool = oolCallVM(ForcedRecompileFnInfo, ins, (ArgList()), StoreRegisterTo(tmp));
else
ool = oolCallVM(RecompileFnInfo, ins, (ArgList()), StoreRegisterTo(tmp));
// Check if warm-up counter is high enough.
masm.movePtr(ImmPtr(ins->mir()->script()->addressOfWarmUpCounter()), tmp);
Address ptr(tmp, 0);
masm.add32(Imm32(1), tmp);
masm.branch32(Assembler::BelowOrEqual, ptr, Imm32(ins->mir()->recompileThreshold()), &done);
AbsoluteAddress warmUpCount = AbsoluteAddress(ins->mir()->script()->addressOfWarmUpCounter());
if (ins->mir()->increaseWarmUpCounter()) {
masm.load32(warmUpCount, tmp);
masm.add32(Imm32(1), tmp);
masm.store32(tmp, warmUpCount);
masm.branch32(Assembler::BelowOrEqual, tmp, Imm32(ins->mir()->recompileThreshold()), &done);
} else {
masm.branch32(Assembler::BelowOrEqual, warmUpCount, Imm32(ins->mir()->recompileThreshold()),
&done);
}
// Check if not yet recompiling.
CodeOffsetLabel label = masm.movWithPatch(ImmWord(uintptr_t(-1)), tmp);

Просмотреть файл

@ -2221,7 +2221,7 @@ GetOptimizationLevel(HandleScript script, jsbytecode *pc, ExecutionMode executio
static MethodStatus
Compile(JSContext *cx, HandleScript script, BaselineFrame *osrFrame, jsbytecode *osrPc,
bool constructing, ExecutionMode executionMode)
bool constructing, ExecutionMode executionMode, bool forceRecompile = false)
{
MOZ_ASSERT(jit::IsIonEnabled(cx));
MOZ_ASSERT(jit::IsBaselineEnabled(cx));
@ -2258,35 +2258,17 @@ Compile(JSContext *cx, HandleScript script, BaselineFrame *osrFrame, jsbytecode
if (!scriptIon->method())
return Method_CantCompile;
MethodStatus failedState = Method_Compiled;
// If we keep failing to enter the script due to an OSR pc mismatch,
// recompile with the right pc.
if (osrPc && script->ionScript()->osrPc() != osrPc) {
uint32_t count = script->ionScript()->incrOsrPcMismatchCounter();
if (count <= js_JitOptions.osrPcMismatchesBeforeRecompile)
return Method_Skipped;
failedState = Method_Skipped;
}
// Don't recompile/overwrite higher optimized code,
// with a lower optimization level.
if (optimizationLevel < scriptIon->optimizationLevel())
return failedState;
if (optimizationLevel == scriptIon->optimizationLevel() &&
(!osrPc || script->ionScript()->osrPc() == osrPc))
{
return failedState;
}
if (optimizationLevel <= scriptIon->optimizationLevel() && !forceRecompile)
return Method_Compiled;
// Don't start compiling if already compiling
if (scriptIon->isRecompiling())
return failedState;
return Method_Compiled;
if (osrPc)
script->ionScript()->resetOsrPcMismatchCounter();
scriptIon->resetOsrPcMismatchCounter();
recompile = true;
}
@ -2305,11 +2287,8 @@ Compile(JSContext *cx, HandleScript script, BaselineFrame *osrFrame, jsbytecode
}
// Compilation succeeded or we invalidated right away or an inlining/alloc abort
if (HasIonScript(script, executionMode)) {
if (osrPc && script->ionScript()->osrPc() != osrPc)
return Method_Skipped;
if (HasIonScript(script, executionMode))
return Method_Compiled;
}
return Method_Skipped;
}
@ -2347,6 +2326,16 @@ jit::CanEnterAtBranch(JSContext *cx, JSScript *script, BaselineFrame *osrFrame,
return Method_CantCompile;
}
// By default a recompilation doesn't happen on osr mismatch.
// Decide if we want to force a recompilation if this happens too much.
bool force = false;
if (script->hasIonScript() && pc != script->ionScript()->osrPc()) {
uint32_t count = script->ionScript()->incrOsrPcMismatchCounter();
if (count <= js_JitOptions.osrPcMismatchesBeforeRecompile)
return Method_Skipped;
force = true;
}
// Attempt compilation.
// - Returns Method_Compiled if the right ionscript is present
// (Meaning it was present or a sequantial compile finished)
@ -2354,13 +2343,20 @@ jit::CanEnterAtBranch(JSContext *cx, JSScript *script, BaselineFrame *osrFrame,
// (This means a background thread compilation with that pc could have started or not.)
RootedScript rscript(cx, script);
MethodStatus status = Compile(cx, rscript, osrFrame, pc, osrFrame->isConstructing(),
SequentialExecution);
SequentialExecution, force);
if (status != Method_Compiled) {
if (status == Method_CantCompile)
ForbidCompilation(cx, script);
return status;
}
// Return the compilation was skipped when the osr pc wasn't adjusted.
// This can happen when there was still an IonScript available and a
// background compilation started, but hasn't finished yet.
// Or when we didn't force a recompile.
if (pc != script->ionScript()->osrPc())
return Method_Skipped;
return Method_Compiled;
}
@ -2461,14 +2457,14 @@ jit::CompileFunctionForBaseline(JSContext *cx, HandleScript script, BaselineFram
MethodStatus
jit::Recompile(JSContext *cx, HandleScript script, BaselineFrame *osrFrame, jsbytecode *osrPc,
bool constructing)
bool constructing, bool force)
{
MOZ_ASSERT(script->hasIonScript());
if (script->ionScript()->isRecompiling())
return Method_Compiled;
MethodStatus status =
Compile(cx, script, osrFrame, osrPc, constructing, SequentialExecution);
Compile(cx, script, osrFrame, osrPc, constructing, SequentialExecution, force);
if (status != Method_Compiled) {
if (status == Method_CantCompile)
ForbidCompilation(cx, script);

Просмотреть файл

@ -93,7 +93,7 @@ MethodStatus CanEnterInParallel(JSContext *cx, HandleScript script);
MethodStatus
Recompile(JSContext *cx, HandleScript script, BaselineFrame *osrFrame, jsbytecode *osrPc,
bool constructing);
bool constructing, bool force);
enum IonExecStatus
{

Просмотреть файл

@ -4454,7 +4454,9 @@ IonBuilder::makeInliningDecision(JSFunction *target, CallInfo &callInfo)
!targetScript->baselineScript()->ionCompiledOrInlined() &&
info().executionMode() != DefinitePropertiesAnalysis)
{
return DontInline(targetScript, "Vetoed: callee is insufficiently hot.");
JitSpew(JitSpew_Inlining, "Cannot inline %s:%u: callee is insufficiently hot.",
targetScript->filename(), targetScript->lineno());
return InliningDecision_WarmUpCountTooLow;
}
}
@ -4489,6 +4491,7 @@ IonBuilder::selectInliningTargets(ObjectVector &targets, CallInfo &callInfo, Boo
case InliningDecision_Error:
return false;
case InliningDecision_DontInline:
case InliningDecision_WarmUpCountTooLow:
inlineable = false;
break;
case InliningDecision_Inline:
@ -4664,6 +4667,8 @@ IonBuilder::inlineCallsite(ObjectVector &targets, ObjectVector &originals,
return InliningStatus_Error;
case InliningDecision_DontInline:
return InliningStatus_NotInlined;
case InliningDecision_WarmUpCountTooLow:
return InliningStatus_WarmUpCountTooLow;
case InliningDecision_Inline:
break;
}
@ -5278,6 +5283,7 @@ IonBuilder::jsop_funcall(uint32_t argc)
case InliningDecision_Error:
return false;
case InliningDecision_DontInline:
case InliningDecision_WarmUpCountTooLow:
break;
case InliningDecision_Inline:
if (target->isInterpreted())
@ -5418,6 +5424,7 @@ IonBuilder::jsop_funapplyarguments(uint32_t argc)
case InliningDecision_Error:
return false;
case InliningDecision_DontInline:
case InliningDecision_WarmUpCountTooLow:
break;
case InliningDecision_Inline:
if (target->isInterpreted())
@ -5488,6 +5495,14 @@ IonBuilder::jsop_call(uint32_t argc, bool constructing)
if (targets.length() == 1)
target = &targets[0]->as<JSFunction>();
if (target && status == InliningStatus_WarmUpCountTooLow) {
MRecompileCheck *check =
MRecompileCheck::New(alloc(), target->nonLazyScript(),
optimizationInfo().inliningRecompileThreshold(),
MRecompileCheck::RecompileCheck_Inlining);
current->add(check);
}
return makeCall(target, callInfo, hasClones);
}
@ -6504,7 +6519,9 @@ IonBuilder::insertRecompileCheck()
OptimizationLevel nextLevel = js_IonOptimizations.nextLevel(curLevel);
const OptimizationInfo *info = js_IonOptimizations.get(nextLevel);
uint32_t warmUpThreshold = info->compilerWarmUpThreshold(topBuilder->script());
current->add(MRecompileCheck::New(alloc(), topBuilder->script(), warmUpThreshold));
MRecompileCheck *check = MRecompileCheck::New(alloc(), topBuilder->script(), warmUpThreshold,
MRecompileCheck::RecompileCheck_OptimizationLevel);
current->add(check);
}
JSObject *
@ -9425,6 +9442,7 @@ IonBuilder::getPropTryCommonGetter(bool *emitted, MDefinition *obj, PropertyName
switch (status) {
case InliningStatus_Error:
return false;
case InliningStatus_WarmUpCountTooLow:
case InliningStatus_NotInlined:
break;
case InliningStatus_Inlined:
@ -9441,6 +9459,7 @@ IonBuilder::getPropTryCommonGetter(bool *emitted, MDefinition *obj, PropertyName
case InliningDecision_Error:
return false;
case InliningDecision_DontInline:
case InliningDecision_WarmUpCountTooLow:
break;
case InliningDecision_Inline:
inlineable = true;
@ -9865,6 +9884,7 @@ IonBuilder::setPropTryCommonSetter(bool *emitted, MDefinition *obj,
case InliningDecision_Error:
return false;
case InliningDecision_DontInline:
case InliningDecision_WarmUpCountTooLow:
break;
case InliningDecision_Inline:
if (!inlineScriptedCall(callInfo, commonSetter))

Просмотреть файл

@ -666,6 +666,7 @@ class IonBuilder
{
InliningStatus_Error,
InliningStatus_NotInlined,
InliningStatus_WarmUpCountTooLow,
InliningStatus_Inlined
};
@ -673,7 +674,8 @@ class IonBuilder
{
InliningDecision_Error,
InliningDecision_Inline,
InliningDecision_DontInline
InliningDecision_DontInline,
InliningDecision_WarmUpCountTooLow
};
static InliningDecision DontInline(JSScript *targetScript, const char *reason);

Просмотреть файл

@ -42,6 +42,7 @@ OptimizationInfo::initNormalOptimizationInfo()
smallFunctionMaxInlineDepth_ = 10;
compilerWarmUpThreshold_ = 1000;
inliningWarmUpThresholdFactor_ = 0.125;
inliningRecompileThresholdFactor_ = 4;
}
void

Просмотреть файл

@ -108,6 +108,11 @@ class OptimizationInfo
// are inlined, as a fraction of compilerWarmUpThreshold.
double inliningWarmUpThresholdFactor_;
// How many invocations or loop iterations are needed before a function
// is hot enough to recompile the outerScript to inline that function,
// as a multiplication of inliningWarmUpThreshold.
uint32_t inliningRecompileThresholdFactor_;
OptimizationInfo()
{ }
@ -194,6 +199,10 @@ class OptimizationInfo
compilerWarmUpThreshold = js_JitOptions.forcedDefaultIonWarmUpThreshold;
return compilerWarmUpThreshold * inliningWarmUpThresholdFactor_;
}
uint32_t inliningRecompileThreshold() const {
return inliningWarmUpThreshold() * inliningRecompileThresholdFactor_;
}
};
class OptimizationInfos

Просмотреть файл

@ -11205,21 +11205,45 @@ class MHasClass
// outermost script (i.e. not the inlined script).
class MRecompileCheck : public MNullaryInstruction
{
public:
enum RecompileCheckType {
RecompileCheck_OptimizationLevel,
RecompileCheck_Inlining
};
private:
JSScript *script_;
uint32_t recompileThreshold_;
bool forceRecompilation_;
bool increaseWarmUpCounter_;
MRecompileCheck(JSScript *script, uint32_t recompileThreshold)
MRecompileCheck(JSScript *script, uint32_t recompileThreshold, RecompileCheckType type)
: script_(script),
recompileThreshold_(recompileThreshold)
{
switch (type) {
case RecompileCheck_OptimizationLevel:
forceRecompilation_ = false;
increaseWarmUpCounter_ = true;
break;
case RecompileCheck_Inlining:
forceRecompilation_ = true;
increaseWarmUpCounter_ = false;
break;
default:
MOZ_CRASH("Unexpected recompile check type");
}
setGuard();
}
public:
INSTRUCTION_HEADER(RecompileCheck);
static MRecompileCheck *New(TempAllocator &alloc, JSScript *script_, uint32_t recompileThreshold) {
return new(alloc) MRecompileCheck(script_, recompileThreshold);
static MRecompileCheck *New(TempAllocator &alloc, JSScript *script_, uint32_t recompileThreshold,
RecompileCheckType type)
{
return new(alloc) MRecompileCheck(script_, recompileThreshold, type);
}
JSScript *script() const {
@ -11230,6 +11254,14 @@ class MRecompileCheck : public MNullaryInstruction
return recompileThreshold_;
}
bool forceRecompilation() const {
return forceRecompilation_;
}
bool increaseWarmUpCounter() const {
return increaseWarmUpCounter_;
}
AliasSet getAliasSet() const {
return AliasSet::None();
}

Просмотреть файл

@ -1049,7 +1049,7 @@ StringReplace(JSContext *cx, HandleString string, HandleString pattern, HandleSt
}
bool
Recompile(JSContext *cx)
RecompileImpl(JSContext *cx, bool force)
{
MOZ_ASSERT(cx->currentlyRunningInJit());
JitActivationIterator activations(cx->runtime());
@ -1065,13 +1065,25 @@ Recompile(JSContext *cx)
if (!IsIonEnabled(cx))
return true;
MethodStatus status = Recompile(cx, script, nullptr, nullptr, isConstructing);
MethodStatus status = Recompile(cx, script, nullptr, nullptr, isConstructing, force);
if (status == Method_Error)
return false;
return true;
}
bool
ForcedRecompile(JSContext *cx)
{
return RecompileImpl(cx, /* force = */ true);
}
bool
Recompile(JSContext *cx)
{
return RecompileImpl(cx, /* force = */ false);
}
bool
SetDenseElement(JSContext *cx, HandleNativeObject obj, int32_t index, HandleValue value,
bool strict)

Просмотреть файл

@ -724,6 +724,7 @@ JSObject *CreateDerivedTypedObj(JSContext *cx, HandleObject descr,
bool ArraySpliceDense(JSContext *cx, HandleObject obj, uint32_t start, uint32_t deleteCount);
bool Recompile(JSContext *cx);
bool ForcedRecompile(JSContext *cx);
JSString *RegExpReplace(JSContext *cx, HandleString string, HandleObject regexp,
HandleString repl);
JSString *StringReplace(JSContext *cx, HandleString string, HandleString pattern,

Просмотреть файл

@ -2157,7 +2157,7 @@ RelocateCell(Zone *zone, TenuredCell *src, AllocKind thingKind, size_t thingSize
MOZ_ASSERT(zone == src->zone());
void *dstAlloc = zone->allocator.arenas.allocateFromFreeList(thingKind, thingSize);
if (!dstAlloc)
dstAlloc = js::gc::ArenaLists::refillFreeListInGC(zone, thingKind);
dstAlloc = GCRuntime::refillFreeListInGC(zone, thingKind);
if (!dstAlloc)
return false;
TenuredCell *dst = TenuredCell::fromPointer(dstAlloc);
@ -2572,14 +2572,22 @@ ArenaLists::backgroundFinalize(FreeOp *fop, ArenaHeader *listHead)
// Flatten |finalizedSorted| into a regular ArenaList.
ArenaList finalized = finalizedSorted.toArenaList();
AutoLockGC lock(fop->runtime());
MOZ_ASSERT(lists->backgroundFinalizeState[thingKind] == BFS_RUN);
// We must take the GC lock to be able to safely modify the ArenaList;
// however, this does not by itself make the changes visible to all threads,
// as not all threads take the GC lock to read the ArenaLists.
// That safety is provided by the ReleaseAcquire memory ordering of the
// background finalize state, which we explicitly set as the final step.
{
AutoLockGC lock(fop->runtime());
MOZ_ASSERT(lists->backgroundFinalizeState[thingKind] == BFS_RUN);
// Join |al| and |finalized| into a single list.
*al = finalized.insertListWithCursorAtEnd(*al);
// Join |al| and |finalized| into a single list.
*al = finalized.insertListWithCursorAtEnd(*al);
lists->arenaListsToSweep[thingKind] = nullptr;
}
lists->backgroundFinalizeState[thingKind] = BFS_DONE;
lists->arenaListsToSweep[thingKind] = nullptr;
}
void

Просмотреть файл

@ -78,6 +78,7 @@ class nsDisplayList;
class nsDisplayListBuilder;
class nsPIDOMWindow;
struct nsPoint;
class nsINode;
struct nsIntPoint;
struct nsIntRect;
struct nsRect;
@ -139,8 +140,8 @@ typedef struct CapturingContentInfo {
} CapturingContentInfo;
#define NS_IPRESSHELL_IID \
{ 0x42e9a352, 0x76f3, 0x4ba3, \
{ 0x94, 0x0b, 0x78, 0x9e, 0x58, 0x38, 0x73, 0x4f } }
{ 0xa0a4b515, 0x0b91, 0x4f13, \
{ 0xa0, 0x60, 0x4b, 0xfb, 0x35, 0x00, 0xdc, 0x00 } }
// debug VerifyReflow flags
#define VERIFY_REFLOW_ON 0x01
@ -855,6 +856,13 @@ public:
nsIDOMEvent* aEvent,
nsEventStatus* aStatus) = 0;
/**
* Dispatch AfterKeyboardEvent with specific target.
*/
virtual void DispatchAfterKeyboardEvent(nsINode* aTarget,
const mozilla::WidgetKeyboardEvent& aEvent,
bool aEmbeddedCancelled) = 0;
/**
* Gets the current target event frame from the PresShell
*/

Просмотреть файл

@ -42,6 +42,7 @@
#include "nsPresShell.h"
#include "nsPresContext.h"
#include "nsIContent.h"
#include "mozilla/dom/BeforeAfterKeyboardEvent.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/Event.h" // for Event::GetEventPopupControlState()
#include "mozilla/dom/ShadowRoot.h"
@ -72,6 +73,8 @@
#include "nsAutoPtr.h"
#include "nsReadableUtils.h"
#include "nsIPageSequenceFrame.h"
#include "nsIPermissionManager.h"
#include "nsIMozBrowserFrame.h"
#include "nsCaret.h"
#include "TouchCaret.h"
#include "SelectionCarets.h"
@ -81,6 +84,7 @@
#include "nsILayoutHistoryState.h"
#include "nsILineIterator.h" // for ScrollContentIntoView
#include "pldhash.h"
#include "mozilla/dom/BeforeAfterKeyboardEventBinding.h"
#include "mozilla/dom/Touch.h"
#include "mozilla/dom/PointerEventBinding.h"
#include "nsIObserverService.h"
@ -705,6 +709,7 @@ static uint32_t sNextPresShellId;
static bool sPointerEventEnabled = true;
static bool sTouchCaretEnabled = false;
static bool sSelectionCaretEnabled = false;
static bool sBeforeAfterKeyboardEventEnabled = false;
/* static */ bool
PresShell::TouchCaretPrefEnabled()
@ -728,6 +733,18 @@ PresShell::SelectionCaretPrefEnabled()
return sSelectionCaretEnabled;
}
/* static */ bool
PresShell::BeforeAfterKeyboardEventEnabled()
{
static bool sInitialized = false;
if (!sInitialized) {
Preferences::AddBoolVarCache(&sBeforeAfterKeyboardEventEnabled,
"dom.beforeAfterKeyboardEvent.enabled");
sInitialized = true;
}
return sBeforeAfterKeyboardEventEnabled;
}
PresShell::PresShell()
: mMouseLocation(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE)
{
@ -6862,6 +6879,236 @@ private:
nsCOMPtr<nsIContent> mContent;
};
static bool
CheckPermissionForBeforeAfterKeyboardEvent(Element* aElement)
{
// An element which is chrome-privileged should be able to handle before
// events and after events.
nsIPrincipal* principal = aElement->NodePrincipal();
if (nsContentUtils::IsSystemPrincipal(principal)) {
return true;
}
// An element which has "before-after-keyboard-event" permission should be
// able to handle before events and after events.
nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
uint32_t permission = nsIPermissionManager::DENY_ACTION;
if (permMgr) {
permMgr->TestPermissionFromPrincipal(principal, "before-after-keyboard-event", &permission);
if (permission == nsIPermissionManager::ALLOW_ACTION) {
return true;
}
// Check "embed-apps" permission for later use.
permission = nsIPermissionManager::DENY_ACTION;
permMgr->TestPermissionFromPrincipal(principal, "embed-apps", &permission);
}
// An element can handle before events and after events if the following
// conditions are met:
// 1) <iframe mozbrowser mozapp>
// 2) it has "embed-apps" permission.
nsCOMPtr<nsIMozBrowserFrame> browserFrame(do_QueryInterface(aElement));
if ((permission == nsIPermissionManager::ALLOW_ACTION) &&
browserFrame && browserFrame->GetReallyIsApp()) {
return true;
}
return false;
}
static void
BuildTargetChainForBeforeAfterKeyboardEvent(nsINode* aTarget,
nsTArray<nsCOMPtr<Element> >& aChain,
bool& aTargetIsIframe)
{
nsCOMPtr<nsIContent> content(do_QueryInterface(aTarget));
nsCOMPtr<nsPIDOMWindow> window;
Element* frameElement;
// Initialize frameElement.
if (content && content->IsHTML(nsGkAtoms::iframe)) {
aTargetIsIframe = true;
frameElement = aTarget->AsElement();
} else {
// If event target is not an iframe, dispatch keydown/keyup event to its
// window after dispatching before events to its ancestors.
aTargetIsIframe = false;
// And skip the event target and get its parent frame.
window = aTarget->OwnerDoc()->GetWindow();
if (window) {
frameElement = window->GetFrameElementInternal();
}
}
// Check permission for all ancestors and add them into the target chain.
while (frameElement) {
if (CheckPermissionForBeforeAfterKeyboardEvent(frameElement)) {
aChain.AppendElement(frameElement);
}
window = frameElement->OwnerDoc()->GetWindow();
frameElement = window ? window->GetFrameElementInternal() : nullptr;
}
}
void
PresShell::DispatchBeforeKeyboardEventInternal(const nsTArray<nsCOMPtr<Element> >& aChain,
const WidgetKeyboardEvent& aEvent,
size_t& aChainIndex,
bool& aDefaultPrevented)
{
size_t length = aChain.Length();
if (!CanDispatchEvent(&aEvent) || !length) {
return;
}
uint32_t message =
(aEvent.message == NS_KEY_DOWN) ? NS_KEY_BEFORE_DOWN : NS_KEY_BEFORE_UP;
nsCOMPtr<EventTarget> eventTarget;
// Dispatch before events from the outermost element.
for (int32_t i = length - 1; i >= 0; i--) {
eventTarget = do_QueryInterface(aChain[i]->OwnerDoc()->GetWindow());
if (!eventTarget || !CanDispatchEvent(&aEvent)) {
return;
}
aChainIndex = i;
InternalBeforeAfterKeyboardEvent beforeEvent(aEvent.mFlags.mIsTrusted,
message, aEvent.widget);
beforeEvent.AssignBeforeAfterKeyEventData(aEvent, false);
EventDispatcher::Dispatch(eventTarget, mPresContext, &beforeEvent);
if (beforeEvent.mFlags.mDefaultPrevented) {
aDefaultPrevented = true;
return;
}
}
}
void
PresShell::DispatchAfterKeyboardEventInternal(const nsTArray<nsCOMPtr<Element> >& aChain,
const WidgetKeyboardEvent& aEvent,
bool aEmbeddedCancelled,
size_t aStartOffset)
{
size_t length = aChain.Length();
if (!CanDispatchEvent(&aEvent) || !length) {
return;
}
uint32_t message =
(aEvent.message == NS_KEY_DOWN) ? NS_KEY_AFTER_DOWN : NS_KEY_AFTER_UP;
bool embeddedCancelled = aEmbeddedCancelled;
nsCOMPtr<EventTarget> eventTarget;
// Dispatch after events from the innermost element.
for (uint32_t i = aStartOffset; i < length; i++) {
eventTarget = do_QueryInterface(aChain[i]->OwnerDoc()->GetWindow());
if (!eventTarget || !CanDispatchEvent(&aEvent)) {
return;
}
InternalBeforeAfterKeyboardEvent afterEvent(aEvent.mFlags.mIsTrusted,
message, aEvent.widget);
afterEvent.AssignBeforeAfterKeyEventData(aEvent, false);
afterEvent.mEmbeddedCancelled.SetValue(embeddedCancelled);
EventDispatcher::Dispatch(eventTarget, mPresContext, &afterEvent);
embeddedCancelled = afterEvent.mFlags.mDefaultPrevented;
}
}
void
PresShell::DispatchAfterKeyboardEvent(nsINode* aTarget,
const WidgetKeyboardEvent& aEvent,
bool aEmbeddedCancelled)
{
MOZ_ASSERT(aTarget);
MOZ_ASSERT(BeforeAfterKeyboardEventEnabled());
if (NS_WARN_IF(aEvent.message != NS_KEY_DOWN &&
aEvent.message != NS_KEY_UP)) {
return;
}
// Build up a target chain. Each item in the chain will receive an after event.
nsAutoTArray<nsCOMPtr<Element>, 5> chain;
bool targetIsIframe = false;
BuildTargetChainForBeforeAfterKeyboardEvent(aTarget, chain, targetIsIframe);
DispatchAfterKeyboardEventInternal(chain, aEvent, aEmbeddedCancelled);
}
bool
PresShell::CanDispatchEvent(const WidgetGUIEvent* aEvent) const
{
bool rv =
mPresContext && !mHaveShutDown && nsContentUtils::IsSafeToRunScript();
if (aEvent) {
rv &= (aEvent && aEvent->widget && !aEvent->widget->Destroyed());
}
return rv;
}
void
PresShell::HandleKeyboardEvent(nsINode* aTarget,
WidgetKeyboardEvent& aEvent,
bool aEmbeddedCancelled,
nsEventStatus* aStatus,
EventDispatchingCallback* aEventCB)
{
if (aEvent.message == NS_KEY_PRESS ||
!BeforeAfterKeyboardEventEnabled()) {
EventDispatcher::Dispatch(aTarget, mPresContext,
&aEvent, nullptr, aStatus, aEventCB);
return;
}
MOZ_ASSERT(aTarget);
MOZ_ASSERT(aEvent.message == NS_KEY_DOWN || aEvent.message == NS_KEY_UP);
// Build up a target chain. Each item in the chain will receive a before event.
nsAutoTArray<nsCOMPtr<Element>, 5> chain;
bool targetIsIframe = false;
BuildTargetChainForBeforeAfterKeyboardEvent(aTarget, chain, targetIsIframe);
// Dispatch before events. If each item in the chain consumes the before
// event and doesn't prevent the default action, we will go further to
// dispatch the actual key event and after events in the reverse order.
// Otherwise, only items which has handled the before event will receive an
// after event.
size_t chainIndex;
bool defaultPrevented = false;
DispatchBeforeKeyboardEventInternal(chain, aEvent, chainIndex,
defaultPrevented);
// Dispatch after events to partial items.
if (defaultPrevented) {
DispatchAfterKeyboardEventInternal(chain, aEvent,
aEvent.mFlags.mDefaultPrevented, chainIndex);
// No need to forward the event to child process.
aEvent.mFlags.mNoCrossProcessBoundaryForwarding = true;
return;
}
// Event listeners may kill nsPresContext and nsPresShell.
if (!CanDispatchEvent()) {
return;
}
// Dispatch actual key event to event target.
EventDispatcher::Dispatch(aTarget, mPresContext,
&aEvent, nullptr, aStatus, aEventCB);
// Event listeners may kill nsPresContext and nsPresShell.
if (targetIsIframe || !CanDispatchEvent()) {
return;
}
// Dispatch after events to all items in the chain.
DispatchAfterKeyboardEventInternal(chain, aEvent,
aEvent.mFlags.mDefaultPrevented);
}
nsresult
PresShell::HandleEvent(nsIFrame* aFrame,
WidgetGUIEvent* aEvent,
@ -7866,6 +8113,9 @@ PresShell::HandleEventInternal(WidgetEvent* aEvent, nsEventStatus* aStatus)
IMEStateManager::DispatchCompositionEvent(eventTarget,
mPresContext, aEvent->AsCompositionEvent(), aStatus,
eventCBPtr);
} else if (aEvent->mClass == eKeyboardEventClass) {
HandleKeyboardEvent(eventTarget, *(aEvent->AsKeyboardEvent()),
false, aStatus, eventCBPtr);
} else {
EventDispatcher::Dispatch(eventTarget, mPresContext,
aEvent, nullptr, aStatus, eventCBPtr);

Просмотреть файл

@ -50,6 +50,7 @@ class nsAutoCauseReflowNotifier;
namespace mozilla {
class CSSStyleSheet;
class EventDispatchingCallback;
} // namespace mozilla
// 250ms. This is actually pref-controlled, but we use this value if we fail
@ -75,6 +76,9 @@ public:
// Selection caret preference
static bool SelectionCaretPrefEnabled();
// BeforeAfterKeyboardEvent preference
static bool BeforeAfterKeyboardEventEnabled();
void Init(nsIDocument* aDocument, nsPresContext* aPresContext,
nsViewManager* aViewManager, nsStyleSet* aStyleSet,
nsCompatibility aCompatMode);
@ -369,6 +373,10 @@ public:
virtual void RecordShadowStyleChange(mozilla::dom::ShadowRoot* aShadowRoot);
virtual void DispatchAfterKeyboardEvent(nsINode* aTarget,
const mozilla::WidgetKeyboardEvent& aEvent,
bool aEmbeddedCancelled) MOZ_OVERRIDE;
void SetNextPaintCompressed() { mNextPaintCompressed = true; }
protected:
@ -719,6 +727,24 @@ protected:
void EvictTouches();
// Methods for dispatching KeyboardEvent and BeforeAfterKeyboardEvent.
void HandleKeyboardEvent(nsINode* aTarget,
mozilla::WidgetKeyboardEvent& aEvent,
bool aEmbeddedCancelled,
nsEventStatus* aStatus,
mozilla::EventDispatchingCallback* aEventCB);
void DispatchBeforeKeyboardEventInternal(
const nsTArray<nsCOMPtr<mozilla::dom::Element> >& aChain,
const mozilla::WidgetKeyboardEvent& aEvent,
size_t& aChainIndex,
bool& aDefaultPrevented);
void DispatchAfterKeyboardEventInternal(
const nsTArray<nsCOMPtr<mozilla::dom::Element> >& aChain,
const mozilla::WidgetKeyboardEvent& aEvent,
bool aEmbeddedCancelled,
size_t aChainIndex = 0);
bool CanDispatchEvent(const mozilla::WidgetGUIEvent* aEvent = nullptr) const;
// A list of images that are visible or almost visible.
nsTHashtable< nsRefPtrHashKey<nsIImageLoadingContent> > mVisibleImages;

Просмотреть файл

@ -5183,8 +5183,6 @@ nsComputedDOMStyle::CreatePrimitiveValueForClipPath(
if (aStyleBasicShape &&
aStyleBasicShape->GetShapeType() == nsStyleBasicShape::Type::ePolygon) {
nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
// Shape function name and opening parenthesis.
nsAutoString shapeFunctionString;
AppendASCIItoUTF16(nsCSSKeywords::GetStringValue(eCSSKeyword_polygon),
@ -5209,12 +5207,11 @@ nsComputedDOMStyle::CreatePrimitiveValueForClipPath(
shapeFunctionString.Append(coordString);
}
shapeFunctionString.Append(')');
nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
val->SetString(shapeFunctionString);
valueList->AppendCSSValue(val);
}
nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
if (aSizingBox == NS_STYLE_CLIP_SHAPE_SIZING_NOBOX) {
return valueList;
}
@ -5224,6 +5221,7 @@ nsComputedDOMStyle::CreatePrimitiveValueForClipPath(
nsCSSProps::ValueToKeyword(aSizingBox,
nsCSSProps::kClipShapeSizingKTable),
boxString);
nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
val->SetString(boxString);
valueList->AppendCSSValue(val);

Просмотреть файл

@ -376,8 +376,9 @@ class ChromeCast implements GeckoMediaPlayer {
}
}
private class MirrorCallback implements ResultCallback<ApplicationConnectionResult> {
final EventCallback callback;
// See Bug 1055562, callback is set to null after it has been
// invoked so that it will not be called a second time.
EventCallback callback;
MirrorCallback(final EventCallback callback) {
this.callback = callback;
}
@ -385,6 +386,10 @@ class ChromeCast implements GeckoMediaPlayer {
@Override
public void onResult(ApplicationConnectionResult result) {
if (callback == null) {
Log.e(LOGTAG, "Attempting to invoke MirrorChannel callback more than once.");
return;
}
Status status = result.getStatus();
if (status.isSuccess()) {
ApplicationMetadata applicationMetadata = result.getApplicationMetadata();
@ -402,6 +407,7 @@ class ChromeCast implements GeckoMediaPlayer {
.getNamespace(),
mMirrorChannel);
callback.sendSuccess(null);
callback = null;
} catch (IOException e) {
Log.e(LOGTAG, "Exception while creating channel", e);
}
@ -409,6 +415,7 @@ class ChromeCast implements GeckoMediaPlayer {
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Casting:Mirror", route.getId()));
} else {
callback.sendError(status.toString());
callback = null;
}
}
}

Просмотреть файл

@ -4347,6 +4347,9 @@ pref("camera.control.low_memory_thresholdMB", 404);
// UDPSocket API
pref("dom.udpsocket.enabled", false);
// Disable before keyboard events and after keyboard events by default.
pref("dom.beforeAfterKeyboardEvent.enabled", false);
// Experiment: Get TTL from DNS records.
// Unset initially (0); Randomly chosen on first run; will remain unchanged
// unless adjusted by the user or experiment ends. Variants defined in

Просмотреть файл

@ -1489,7 +1489,6 @@ CacheIndex::UpdateEntryInIndex(CacheIndexEntry *aEntry, void* aClosure)
LOGSHA1(aEntry->Hash())));
MOZ_ASSERT(aEntry->IsFresh());
MOZ_ASSERT(aEntry->IsDirty());
CacheIndexEntry *entry = index->mIndex.GetEntry(*aEntry->Hash());

Просмотреть файл

@ -464,19 +464,24 @@ nsHostRecord::GetPriority(uint16_t aFlags)
return nsHostRecord::DNS_PRIORITY_LOW;
}
// Returns true if the entry can be removed, or false if it was marked to get
// refreshed.
// Returns true if the entry can be removed, or false if it should be left.
// Sets mResolveAgain true for entries being resolved right now.
bool
nsHostRecord::RemoveOrRefresh()
{
// This condition implies that the request has been passed to the OS
// resolver. The resultant DNS record should be considered stale and not
// trusted; set a flag to ensure it is called again.
if (resolving && !onQueue) {
mResolveAgain = true;
if (resolving) {
if (!onQueue) {
// The request has been passed to the OS resolver. The resultant DNS
// record should be considered stale and not trusted; set a flag to
// ensure it is called again.
mResolveAgain = true;
}
// if Onqueue is true, the host entry is already added to the cache
// but is still pending to get resolved: just leave it in hash.
return false;
}
return true; // can be removed now
// Already resolved; not in a pending state; remove from cache.
return true;
}
//----------------------------------------------------------------------------
@ -599,9 +604,9 @@ HostDB_PruneEntry(PLDHashTable *table,
void *arg)
{
nsHostDBEnt* ent = static_cast<nsHostDBEnt *>(hdr);
// Try to remove the record, or mark it for refresh
if (ent->rec->RemoveOrRefresh()) {
PR_REMOVE_LINK(ent->rec);
return PL_DHASH_REMOVE;
}
return PL_DHASH_NEXT;
@ -786,26 +791,24 @@ nsHostResolver::ClearPendingQueue(PRCList *aPendingQ)
void
nsHostResolver::FlushCache()
{
PRCList evictionQ;
PR_INIT_CLIST(&evictionQ);
MutexAutoLock lock(mLock);
mEvictionQSize = 0;
{
MutexAutoLock lock(mLock);
MoveCList(mEvictionQ, evictionQ);
mEvictionQSize = 0;
// Clear the evictionQ and remove all its corresponding entries from
// the cache first
if (!PR_CLIST_IS_EMPTY(&mEvictionQ)) {
PRCList *node = mEvictionQ.next;
while (node != &mEvictionQ) {
nsHostRecord *rec = static_cast<nsHostRecord *>(node);
node = node->next;
PR_REMOVE_AND_INIT_LINK(rec);
PL_DHashTableOperate(&mDB, (nsHostKey *) rec, PL_DHASH_REMOVE);
NS_RELEASE(rec);
}
}
// prune the hash from all hosts already resolved
PL_DHashTableEnumerate(&mDB, HostDB_PruneEntry, nullptr);
}
if (!PR_CLIST_IS_EMPTY(&evictionQ)) {
PRCList *node = evictionQ.next;
while (node != &evictionQ) {
nsHostRecord *rec = static_cast<nsHostRecord *>(node);
node = node->next;
NS_RELEASE(rec);
}
}
// Refresh the cache entries that are resolving RIGHT now, remove the rest.
PL_DHashTableEnumerate(&mDB, HostDB_PruneEntry, nullptr);
}
void
@ -1459,6 +1462,17 @@ nsHostResolver::OnLookupComplete(nsHostRecord* rec, nsresult status, AddrInfo* r
// release reference to rec owned by mEvictionQ
NS_RELEASE(head);
}
#if TTL_AVAILABLE
if (!rec->mGetTtl && sDnsVariant != DNS_EXP_VARIANT_CONTROL
&& !rec->resolving) {
LOG(("Issuing second async lookup for TTL for %s.", rec->host));
rec->flags =
(rec->flags & ~RES_PRIORITY_MEDIUM) | RES_PRIORITY_LOW;
DebugOnly<nsresult> rv = IssueLookup(rec);
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
"Could not issue second async lookup for TTL.");
}
#endif
}
}
@ -1475,21 +1489,6 @@ nsHostResolver::OnLookupComplete(nsHostRecord* rec, nsresult status, AddrInfo* r
}
}
#if TTL_AVAILABLE
{
MutexAutoLock lock(mLock);
if (!mShutdown && !rec->mGetTtl
&& sDnsVariant != DNS_EXP_VARIANT_CONTROL && !rec->resolving) {
LOG(("Issuing second async lookup for TTL for %s.", rec->host));
rec->flags =
(rec->flags & ~RES_PRIORITY_MEDIUM) | RES_PRIORITY_LOW;
DebugOnly<nsresult> rv = IssueLookup(rec);
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
"Could not issue second async lookup for TTL.");
}
}
#endif
NS_RELEASE(rec);
return LOOKUP_OK;

Просмотреть файл

@ -119,8 +119,8 @@ public:
};
static DnsPriority GetPriority(uint16_t aFlags);
bool RemoveOrRefresh(); // Returns whether the host record can be removed
// or needs to be refreshed
bool RemoveOrRefresh(); // Mark records currently being resolved as needed
// to resolve again.
private:
friend class nsHostResolver;

Просмотреть файл

@ -616,6 +616,7 @@ nsHttpHandler::BuildUserAgent()
mAppVersion.Length() +
mCompatFirefox.Length() +
mCompatDevice.Length() +
mDeviceModelId.Length() +
13);
// Application portion
@ -640,6 +641,10 @@ nsHttpHandler::BuildUserAgent()
mUserAgent += mOscpu;
mUserAgent.AppendLiteral("; ");
}
if (!mDeviceModelId.IsEmpty()) {
mUserAgent += mDeviceModelId;
mUserAgent.AppendLiteral("; ");
}
mUserAgent += mMisc;
mUserAgent += ')';
@ -703,6 +708,31 @@ nsHttpHandler::InitUserAgentComponents()
mCompatDevice.AssignLiteral("Mobile");
#endif
#if defined(MOZ_WIDGET_GONK)
// Device model identifier should be a simple token, which can be composed
// of letters, numbers, hyphen ("-") and dot (".").
// Any other characters means the identifier is invalid and ignored.
nsCString deviceId;
rv = Preferences::GetCString("general.useragent.device_id", &deviceId);
if (NS_SUCCEEDED(rv)) {
bool valid = true;
deviceId.Trim(" ", true, true);
for (int i = 0; i < deviceId.Length(); i++) {
char c = deviceId.CharAt(i);
if (!(isalnum(c) || c == '-' || c == '.')) {
valid = false;
break;
}
}
if (valid) {
mDeviceModelId = deviceId;
} else {
LOG(("nsHttpHandler: Ignore invalid device ID: [%s]\n",
deviceId.get()));
}
}
#endif
#ifndef MOZ_UA_OS_AGNOSTIC
// Gather OS/CPU.
#if defined(XP_WIN)

Просмотреть файл

@ -432,6 +432,7 @@ private:
nsCString mCompatFirefox;
bool mCompatFirefoxEnabled;
nsXPIDLCString mCompatDevice;
nsCString mDeviceModelId;
nsCString mUserAgent;
nsXPIDLCString mUserAgentOverride;

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше