--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,17 +14,17 @@
<!--original fetch url was git://github.com/apitrace/-->
<remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
<default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
<!-- Gonk specific things and forks -->
<project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
<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="98ca8c55dbe2f21a8661d0eaa87f34d316c3bc98"/>
+ <project name="gaia.git" path="gaia" remote="mozillaorg" revision="347d0517f0a77122c876d5f62c0942006a7a0bfe"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="ca283b9db2b151d465cfd2e19346cf58fe89e413"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="d5800c36b2d5822fc3fe1899b9280401de466e1e"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
@@ -97,12 +97,12 @@
<project name="platform/system/netd" path="system/netd" revision="3d298fde142bee3fc4f07f63f16f2d8ce42339c0"/>
<project name="platform/system/vold" path="system/vold" revision="919829940468066a32f403980b43f6ebfee5d314"/>
<!-- Emulator specific things -->
<project name="android-development" path="development" remote="b2g" revision="9abf0ab68376afae3e1c7beefa3e9cbee2fde202"/>
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="2fee3bbbfc236b883ef8507e27d88b17b203fe25"/>
<project name="platform/external/iproute2" path="external/iproute2" revision="c66c5716d5335e450f7a7b71ccc6a604fb2f41d2"/>
<project 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="d2685281e2e54ca14d1df304867aa82c37b27162"/>
<project 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="627f9b20fc518937b93747a7ff1ed4f5ed46e06f"/>
- <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="10977f28df27f79534f079c0a9852b21a5a0f6da"/>
+ <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="f19ba22ba6973804628781606bc072d18f3f79c2"/>
<project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="431afac2ebfdd9c1c8402b413ff5914ed448e961"/>
<project name="android-sdk" path="sdk" remote="b2g" revision="4f46930827957afbce500a4a920755a218bf3155"/>
</manifest>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,17 +12,17 @@
<!--original fetch url was https://git.mozilla.org/releases-->
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
<!-- B2G specific things. -->
<project name="platform_build" path="build" remote="b2g" revision="e6383e6e785cc3ea237e902beb1092f9aa88e29d">
<copyfile dest="Makefile" src="core/root.mk"/>
</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="98ca8c55dbe2f21a8661d0eaa87f34d316c3bc98"/>
+ <project name="gaia" path="gaia" remote="mozillaorg" revision="347d0517f0a77122c876d5f62c0942006a7a0bfe"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
<project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,17 +10,17 @@
<!--original fetch url was git://codeaurora.org/-->
<remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
<!--original fetch url was https://git.mozilla.org/releases-->
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
<!-- B2G specific things. -->
<project name="platform_build" path="build" remote="b2g" revision="65fba428f8d76336b33ddd9e15900357953600ba">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
- <project name="gaia" path="gaia" remote="mozillaorg" revision="98ca8c55dbe2f21a8661d0eaa87f34d316c3bc98"/>
+ <project name="gaia" path="gaia" remote="mozillaorg" revision="347d0517f0a77122c876d5f62c0942006a7a0bfe"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<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="3691614d0045f7968addce45d4140fb360c3ceaf"/>
<!-- Stock Android things -->
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,17 +14,17 @@
<!--original fetch url was git://github.com/apitrace/-->
<remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
<default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
<!-- Gonk specific things and forks -->
<project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
<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="98ca8c55dbe2f21a8661d0eaa87f34d316c3bc98"/>
+ <project name="gaia.git" path="gaia" remote="mozillaorg" revision="347d0517f0a77122c876d5f62c0942006a7a0bfe"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="ca283b9db2b151d465cfd2e19346cf58fe89e413"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="d5800c36b2d5822fc3fe1899b9280401de466e1e"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
@@ -97,12 +97,12 @@
<project name="platform/system/netd" path="system/netd" revision="3d298fde142bee3fc4f07f63f16f2d8ce42339c0"/>
<project name="platform/system/vold" path="system/vold" revision="919829940468066a32f403980b43f6ebfee5d314"/>
<!-- Emulator specific things -->
<project name="android-development" path="development" remote="b2g" revision="9abf0ab68376afae3e1c7beefa3e9cbee2fde202"/>
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="2fee3bbbfc236b883ef8507e27d88b17b203fe25"/>
<project name="platform/external/iproute2" path="external/iproute2" revision="c66c5716d5335e450f7a7b71ccc6a604fb2f41d2"/>
<project 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="d2685281e2e54ca14d1df304867aa82c37b27162"/>
<project 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="627f9b20fc518937b93747a7ff1ed4f5ed46e06f"/>
- <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="10977f28df27f79534f079c0a9852b21a5a0f6da"/>
+ <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="f19ba22ba6973804628781606bc072d18f3f79c2"/>
<project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="431afac2ebfdd9c1c8402b413ff5914ed448e961"/>
<project name="android-sdk" path="sdk" remote="b2g" revision="4f46930827957afbce500a4a920755a218bf3155"/>
</manifest>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -13,17 +13,17 @@
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
<!-- B2G specific things. -->
<project name="platform_build" path="build" remote="b2g" revision="e6383e6e785cc3ea237e902beb1092f9aa88e29d">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
- <project name="gaia" path="gaia" remote="mozillaorg" revision="98ca8c55dbe2f21a8661d0eaa87f34d316c3bc98"/>
+ <project name="gaia" path="gaia" remote="mozillaorg" revision="347d0517f0a77122c876d5f62c0942006a7a0bfe"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
<project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
@@ -124,24 +124,24 @@
<project name="platform/bootable/recovery" path="bootable/recovery" revision="f2914eacee9120680a41463708bb6ee8291749fc"/>
<project name="platform/external/bluetooth/bluedroid" path="external/bluetooth/bluedroid" revision="fa892235a9bd8983f8b591129fc1a9398f64e514"/>
<project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="f0689ac1914cdbc59e53bdc9edd9013dc157c299"/>
<project name="platform/external/bluetooth/glib" path="external/bluetooth/glib" revision="dd925f76e4f149c3d5571b80e12f7e24bbe89c59"/>
<project name="platform/external/dbus" path="external/dbus" revision="ea87119c843116340f5df1d94eaf8275e1055ae8"/>
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="494c177966fdc31183a5f7af82dc9130f523da4b"/>
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="320b05a5761eb2a4816f7529c91ea49422979b55"/>
<project name="platform/frameworks/av" path="frameworks/av" revision="1df6dac11d7370a2fffca8e31d65b80f537faec5"/>
- <project name="platform/frameworks/base" path="frameworks/base" revision="807d87d5ff66cb5e0664f6924f612fcdb5e2c453"/>
+ <project name="platform/frameworks/base" path="frameworks/base" revision="eed05deb23b612ef6b415a039c9e77483669b0c4"/>
<project name="platform/frameworks/native" path="frameworks/native" revision="33a2b51f78416536e1bfba0c0b7776db307f3a4f"/>
<project name="platform/hardware/libhardware" path="hardware/libhardware" revision="484802559ed106bac4811bd01c024ca64f741e60"/>
<project name="platform/hardware/qcom/audio" path="hardware/qcom/audio" revision="d30227d7ae5cbe8bac8775358b472f44504a20d2"/>
<project name="platform/hardware/qcom/camera" path="hardware/qcom/camera" revision="81afa7f775b7559da52f468150d1fe090c3fbdc5"/>
<project name="platform/hardware/qcom/display" path="hardware/qcom/display" revision="e38444b6ce12c7c25883272a439800376d5308eb"/>
<project name="platform/hardware/qcom/gps" path="hardware/qcom/gps" revision="13312a5577db9261cb0fcee9ccbc58cdb5e6bc55"/>
<project name="platform/hardware/qcom/media" path="hardware/qcom/media" revision="8a0d0b0d9889ef99c4c6317c810db4c09295f15a"/>
<project name="platform/hardware/qcom/wlan" path="hardware/qcom/wlan" revision="2208fa3537ace873b8f9ec2355055761c79dfd5f"/>
<project name="platform/hardware/ril" path="hardware/ril" revision="c4e2ac95907a5519a0e09f01a0d8e27fec101af0"/>
<project name="platform/system/bluetooth" path="system/bluetooth" revision="e1eb226fa3ad3874ea7b63c56a9dc7012d7ff3c2"/>
- <project name="platform/system/core" path="system/core" revision="e284280277c1312017a9450956a9676584441cdf"/>
+ <project name="platform/system/core" path="system/core" revision="81c9921fcf372228aab336ff7cf0076c66505af0"/>
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="f620016437dd2f050e044eccef5e70e3f689ccbe"/>
<project name="platform/system/qcom" path="system/qcom" revision="1cdab258b15258b7f9657da70e6f06ebd5a2fc25"/>
<project name="platform/vendor/qcom/msm8610" path="device/qcom/msm8610" revision="b3001d5f1686f89995b7bf70963cf69c8faebd83"/>
</manifest>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
{
"git": {
"git_revision": "",
"remote": "",
"branch": ""
},
- "revision": "7bf976de32cf817ed4529ac875755ac6f6895b89",
+ "revision": "787e0db2b536a3f1105c12819d48a8a584d5d4d6",
"repo_path": "/integration/gaia-central"
}
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,17 +12,17 @@
<!--original fetch url was git://github.com/apitrace/-->
<remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
<default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
<!-- Gonk specific things and forks -->
<project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
<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="98ca8c55dbe2f21a8661d0eaa87f34d316c3bc98"/>
+ <project name="gaia.git" path="gaia" remote="mozillaorg" revision="347d0517f0a77122c876d5f62c0942006a7a0bfe"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
<project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -10,17 +10,17 @@
<!--original fetch url was https://git.mozilla.org/releases-->
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
<default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
<!-- Gonk specific things and forks -->
<project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
<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="98ca8c55dbe2f21a8661d0eaa87f34d316c3bc98"/>
+ <project name="gaia.git" path="gaia" remote="mozillaorg" revision="347d0517f0a77122c876d5f62c0942006a7a0bfe"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
<project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/inari/sources.xml
+++ b/b2g/config/inari/sources.xml
@@ -14,17 +14,17 @@
<!--original fetch url was git://github.com/apitrace/-->
<remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
<default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
<!-- Gonk specific things and forks -->
<project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
<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="98ca8c55dbe2f21a8661d0eaa87f34d316c3bc98"/>
+ <project name="gaia.git" path="gaia" remote="mozillaorg" revision="347d0517f0a77122c876d5f62c0942006a7a0bfe"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
<project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
--- a/b2g/config/leo/sources.xml
+++ b/b2g/config/leo/sources.xml
@@ -12,17 +12,17 @@
<!--original fetch url was git://github.com/apitrace/-->
<remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
<default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
<!-- Gonk specific things and forks -->
<project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
<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="98ca8c55dbe2f21a8661d0eaa87f34d316c3bc98"/>
+ <project name="gaia.git" path="gaia" remote="mozillaorg" revision="347d0517f0a77122c876d5f62c0942006a7a0bfe"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>
<project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/b2g/config/mako/sources.xml
+++ b/b2g/config/mako/sources.xml
@@ -12,17 +12,17 @@
<!--original fetch url was https://git.mozilla.org/releases-->
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
<!-- B2G specific things. -->
<project name="platform_build" path="build" remote="b2g" revision="e6383e6e785cc3ea237e902beb1092f9aa88e29d">
<copyfile dest="Makefile" src="core/root.mk"/>
</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="98ca8c55dbe2f21a8661d0eaa87f34d316c3bc98"/>
+ <project name="gaia" path="gaia" remote="mozillaorg" revision="347d0517f0a77122c876d5f62c0942006a7a0bfe"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
<project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,17 +12,17 @@
<!--original fetch url was git://github.com/apitrace/-->
<remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
<default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
<!-- Gonk specific things and forks -->
<project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
<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="98ca8c55dbe2f21a8661d0eaa87f34d316c3bc98"/>
+ <project name="gaia.git" path="gaia" remote="mozillaorg" revision="347d0517f0a77122c876d5f62c0942006a7a0bfe"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>
<project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -114,18 +114,18 @@
oncommand="OpenBrowserWindow({remote: true});"/>
<command id="Tools:NonRemoteWindow"
oncommand="OpenBrowserWindow({remote: false});"/>
<command id="History:UndoCloseTab" oncommand="undoCloseTab();"/>
<command id="History:UndoCloseWindow" oncommand="undoCloseWindow();"/>
<command id="Social:SharePage" oncommand="SocialShare.sharePage();" disabled="true"/>
<command id="Social:ToggleSidebar" oncommand="SocialSidebar.toggleSidebar();" hidden="true"/>
<command id="Social:ToggleNotifications" oncommand="Social.toggleNotifications();" hidden="true"/>
- <command id="Social:FocusChat" oncommand="SocialChatBar.focus();" hidden="true" disabled="true"/>
<command id="Social:Addons" oncommand="BrowserOpenAddonsMgr('addons://list/service');"/>
+ <command id="Chat:Focus" oncommand="Cu.import('resource:///modules/Chat.jsm', {}).Chat.focus(window);"/>
</commandset>
<commandset id="placesCommands">
<command id="Browser:ShowAllBookmarks"
oncommand="PlacesCommandHook.showPlacesOrganizer('AllBookmarks');"/>
<command id="Browser:ShowAllHistory"
oncommand="PlacesCommandHook.showPlacesOrganizer('History');"/>
</commandset>
@@ -375,17 +375,25 @@
<key id="viewBookmarksSidebarKb" key="&bookmarksCmd.commandkey;" command="viewBookmarksSidebar" modifiers="accel"/>
#ifdef XP_WIN
# Cmd+I is conventially mapped to Info on MacOS X, thus it should not be
# overridden for other purposes there.
<key id="viewBookmarksSidebarWinKb" key="&bookmarksWinCmd.commandkey;" command="viewBookmarksSidebar" modifiers="accel"/>
#endif
<!--<key id="markPage" key="&markPageCmd.commandkey;" command="Social:TogglePageMark" modifiers="accel,shift"/>-->
- <key id="focusChatBar" key="&social.chatBar.commandkey;" command="Social:FocusChat" modifiers="accel,shift"/>
+ <key id="focusChatBar" key="&social.chatBar.commandkey;" command="Chat:Focus"
+#ifdef XP_MACOSX
+# Sadly the devtools uses shift-accel-c on non-mac and alt-accel-c everywhere else
+# So we just use the other
+ modifiers="accel,shift"
+#else
+ modifiers="accel,alt"
+#endif
+ />
<key id="key_stop" keycode="VK_ESCAPE" command="Browser:Stop"/>
#ifdef XP_MACOSX
<key id="key_stop_mac" modifiers="accel" key="&stopCmd.macCommandKey;" command="Browser:Stop"/>
#endif
<key id="key_gotoHistory"
--- a/browser/base/content/browser-social.js
+++ b/browser/base/content/browser-social.js
@@ -1,15 +1,14 @@
// 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/.
// the "exported" symbols
let SocialUI,
- SocialChatBar,
SocialFlyout,
SocialMarks,
SocialShare,
SocialSidebar,
SocialStatus;
(function() {
@@ -168,17 +167,16 @@ SocialUI = {
Components.utils.reportError(e + "\n" + e.stack);
throw e;
}
},
_providersChanged: function() {
SocialSidebar.clearProviderMenus();
SocialSidebar.update();
- SocialChatBar.update();
SocialShare.populateProviderMenu();
SocialStatus.populateToolbarPalette();
SocialMarks.populateToolbarPalette();
SocialShare.update();
},
// This handles "ActivateSocialFeature" events fired against content documents
// in this window.
@@ -292,55 +290,16 @@ SocialUI = {
updateState: function() {
if (!this.enabled)
return;
SocialMarks.update();
SocialShare.update();
}
}
-SocialChatBar = {
- get chatbar() {
- return document.getElementById("pinnedchats");
- },
- // Whether the chatbar is available for this window. Note that in full-screen
- // mode chats are available, but not shown.
- get isAvailable() {
- return SocialUI.enabled;
- },
- // Does this chatbar have any chats (whether minimized, collapsed or normal)
- get hasChats() {
- return !!this.chatbar.firstElementChild;
- },
- openChat: function(aProvider, aURL, aCallback, aMode) {
- this.update();
- if (!this.isAvailable)
- return false;
- this.chatbar.openChat(aProvider, aURL, aCallback, aMode);
- // We only want to focus the chat if it is as a result of user input.
- let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindowUtils);
- if (dwu.isHandlingUserInput)
- this.chatbar.focus();
- return true;
- },
- update: function() {
- let command = document.getElementById("Social:FocusChat");
- if (!this.isAvailable) {
- this.chatbar.hidden = command.hidden = true;
- } else {
- this.chatbar.hidden = command.hidden = false;
- }
- command.setAttribute("disabled", command.hidden ? "true" : "false");
- },
- focus: function SocialChatBar_focus() {
- this.chatbar.focus();
- }
-}
-
SocialFlyout = {
get panel() {
return document.getElementById("social-flyout-panel");
},
get iframe() {
if (!this.panel.firstChild)
this._createFrame();
--- a/browser/base/content/socialchat.xml
+++ b/browser/base/content/socialchat.xml
@@ -25,60 +25,53 @@
context="contentAreaContextMenu"
disableglobalhistory="true"
tooltip="aHTMLTooltip"
xbl:inherits="src,origin" type="content"/>
</content>
<implementation implements="nsIDOMEventListener">
<constructor><![CDATA[
- let Social = Components.utils.import("resource:///modules/Social.jsm", {}).Social;
this.content.__defineGetter__("popupnotificationanchor",
() => document.getAnonymousElementByAttribute(this, "anonid", "notification-icon"));
- Social.setErrorListener(this.content, function(aBrowser) {
- aBrowser.webNavigation.loadURI("about:socialerror?mode=compactInfo&origin=" +
- encodeURIComponent(aBrowser.getAttribute("origin")),
- null, null, null, null);
- });
+
if (!this.chatbar) {
document.getAnonymousElementByAttribute(this, "anonid", "minimize").hidden = true;
document.getAnonymousElementByAttribute(this, "anonid", "close").hidden = true;
}
let contentWindow = this.contentWindow;
+ // process this._callbacks, then set to null so the chatbox creator
+ // knows to make new callbacks immediately.
+ if (this._callbacks) {
+ for (let callback of this._callbacks) {
+ callback(this);
+ }
+ this._callbacks = null;
+ }
this.addEventListener("DOMContentLoaded", function DOMContentLoaded(event) {
if (event.target != this.contentDocument)
return;
this.removeEventListener("DOMContentLoaded", DOMContentLoaded, true);
this.isActive = !this.minimized;
- // process this._callbacks, then set to null so the chatbox creator
- // knows to make new callbacks immediately.
- if (this._callbacks) {
- for (let callback of this._callbacks) {
- if (callback)
- callback(contentWindow);
- }
- this._callbacks = null;
- }
-
- // content can send a socialChatActivity event to have the UI update.
- let chatActivity = function() {
- this.setAttribute("activity", true);
- if (this.chatbar)
- this.chatbar.updateTitlebar(this);
- }.bind(this);
- contentWindow.addEventListener("socialChatActivity", chatActivity);
- contentWindow.addEventListener("unload", function unload() {
- contentWindow.removeEventListener("unload", unload);
- contentWindow.removeEventListener("socialChatActivity", chatActivity);
- });
+ this._deferredChatLoaded.resolve(this);
}, true);
if (this.src)
this.setAttribute("src", this.src);
]]></constructor>
+ <field name="_deferredChatLoaded" readonly="true">
+ Promise.defer();
+ </field>
+
+ <property name="promiseChatLoaded">
+ <getter>
+ return this._deferredChatLoaded.promise;
+ </getter>
+ </property>
+
<field name="content" readonly="true">
document.getAnonymousElementByAttribute(this, "anonid", "content");
</field>
<property name="contentWindow">
<getter>
return this.content.contentWindow;
</getter>
@@ -128,40 +121,32 @@
this.content.docShell.isActive = !!val;
// let the chat frame know if it is being shown or hidden
let evt = this.contentDocument.createEvent("CustomEvent");
evt.initCustomEvent(val ? "socialFrameShow" : "socialFrameHide", true, true, {});
this.contentDocument.documentElement.dispatchEvent(evt);
</setter>
</property>
-
+
<method name="showNotifications">
<body><![CDATA[
PopupNotifications._reshowNotifications(this.content.popupnotificationanchor,
this.content);
]]></body>
</method>
<method name="swapDocShells">
<parameter name="aTarget"/>
<body><![CDATA[
aTarget.setAttribute('label', this.contentDocument.title);
aTarget.src = this.src;
aTarget.content.setAttribute("origin", this.content.getAttribute("origin"));
aTarget.content.popupnotificationanchor.className = this.content.popupnotificationanchor.className;
- this.content.socialErrorListener.remove();
- aTarget.content.socialErrorListener.remove();
this.content.swapDocShells(aTarget.content);
- Social.setErrorListener(this.content, function(aBrowser) {}); // 'this' will be destroyed soon.
- Social.setErrorListener(aTarget.content, function(aBrowser) {
- aBrowser.webNavigation.loadURI("about:socialerror?mode=compactInfo&origin=" +
- encodeURIComponent(aBrowser.getAttribute("origin")),
- null, null, null, null);
- });
]]></body>
</method>
<method name="onTitlebarClick">
<parameter name="aEvent"/>
<body><![CDATA[
if (!this.chatbar)
return;
@@ -181,41 +166,50 @@
this.chatbar.remove(this);
else
window.close();
]]></body>
</method>
<method name="swapWindows">
<body><![CDATA[
- let provider = Social._getProviderFromOrigin(this.content.getAttribute("origin"));
+ let deferred = Promise.defer();
+ let title = this.getAttribute("label");
if (this.chatbar) {
- this.chatbar.detachChatbox(this, { "centerscreen": "yes" }, win => {
- win.document.title = provider.name;
- });
+ this.chatbar.detachChatbox(this, { "centerscreen": "yes" }).then(
+ chatbox => {
+ chatbox.contentWindow.document.title = title;
+ deferred.resolve(chatbox);
+ }
+ );
} else {
// attach this chatbox to the topmost browser window
- let findChromeWindowForChats = Cu.import("resource://gre/modules/MozSocialAPI.jsm").findChromeWindowForChats;
- let win = findChromeWindowForChats();
- let chatbar = win.SocialChatBar.chatbar;
- chatbar.openChat(provider, "about:blank", win => {
- let cb = chatbar.selectedChat;
- this.swapDocShells(cb);
+ let Chat = Cu.import("resource:///modules/Chat.jsm").Chat;
+ let win = Chat.findChromeWindowForChats();
+ let chatbar = win.document.getElementById("pinnedchats");
+ let origin = this.content.getAttribute("origin");
+ let cb = chatbar.openChat(origin, title, "about:blank");
+ cb.promiseChatLoaded.then(
+ () => {
+ this.swapDocShells(cb);
- // chatboxForURL is a map of URL -> chatbox used to avoid opening
- // duplicate chat windows. Ensure reattached chat windows aren't
- // registered with about:blank as their URL, otherwise reattaching
- // more than one chat window isn't possible.
- chatbar.chatboxForURL.delete("about:blank");
- chatbar.chatboxForURL.set(this.src, Cu.getWeakReference(cb));
+ // chatboxForURL is a map of URL -> chatbox used to avoid opening
+ // duplicate chat windows. Ensure reattached chat windows aren't
+ // registered with about:blank as their URL, otherwise reattaching
+ // more than one chat window isn't possible.
+ chatbar.chatboxForURL.delete("about:blank");
+ chatbar.chatboxForURL.set(this.src, Cu.getWeakReference(cb));
- chatbar.focus();
- this.close();
- });
+ chatbar.focus();
+ this.close();
+ deferred.resolve(cb);
+ }
+ );
}
+ return deferred.promise;
]]></body>
</method>
<method name="toggle">
<body><![CDATA[
this.minimized = !this.minimized;
]]></body>
</method>
@@ -505,76 +499,70 @@
this._selectAnotherChat();
}
]]></body>
</method>
<method name="_remove">
<parameter name="aChatbox"/>
<body><![CDATA[
- aChatbox.content.socialErrorListener.remove();
this.removeChild(aChatbox);
// child might have been collapsed.
let menuitem = this.menuitemMap.get(aChatbox);
if (menuitem) {
this.menuitemMap.delete(aChatbox);
this.menupopup.removeChild(menuitem);
}
this.chatboxForURL.delete(aChatbox.src);
]]></body>
</method>
- <method name="removeAll">
- <body><![CDATA[
- this.selectedChat = null;
- while (this.firstElementChild) {
- this._remove(this.firstElementChild);
- }
- // and the nub/popup must also die.
- this.nub.collapsed = true;
- ]]></body>
- </method>
-
<method name="openChat">
- <parameter name="aProvider"/>
+ <parameter name="aOrigin"/>
+ <parameter name="aTitle"/>
<parameter name="aURL"/>
+ <parameter name="aMode"/>
<parameter name="aCallback"/>
- <parameter name="aMode"/>
<body><![CDATA[
let cb = this.chatboxForURL.get(aURL);
if (cb) {
cb = cb.get();
if (cb.parentNode) {
this.showChat(cb, aMode);
if (aCallback) {
if (cb._callbacks == null) {
- // DOMContentLoaded has already fired, so callback now.
- aCallback(cb.contentWindow);
+ // Chatbox has already been created, so callback now.
+ aCallback(cb);
} else {
- // DOMContentLoaded for this chat is yet to fire...
+ // Chatbox is yet to have bindings created...
cb._callbacks.push(aCallback);
}
}
- return;
+ return cb;
}
this.chatboxForURL.delete(aURL);
}
cb = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "chatbox");
- // _callbacks is a javascript property instead of a <field> as it
- // must exist before the (possibly delayed) bindings are created.
- cb._callbacks = [aCallback];
+ cb._callbacks = [];
+ if (aCallback) {
+ // _callbacks is a javascript property instead of a <field> as it
+ // must exist before the (possibly delayed) bindings are created.
+ cb._callbacks.push(aCallback);
+ }
// src also a javascript property; the src attribute is set in the ctor.
cb.src = aURL;
if (aMode == "minimized")
cb.setAttribute("minimized", "true");
- cb.setAttribute("origin", aProvider.origin);
+ cb.setAttribute("origin", aOrigin);
+ cb.setAttribute("label", aTitle);
this.insertBefore(cb, this.firstChild);
this.selectedChat = cb;
this.chatboxForURL.set(aURL, Cu.getWeakReference(cb));
this.resize();
+ return cb;
]]></body>
</method>
<method name="resize">
<body><![CDATA[
// Checks the current size against the collapsed state of children
// and collapses or expands as necessary such that as many as possible
// are shown.
@@ -643,40 +631,42 @@
<method name="_getDragTarget">
<parameter name="event"/>
<body><![CDATA[
return event.target.localName == "chatbox" ? event.target : null;
]]></body>
</method>
- <!-- Moves a chatbox to a new window. -->
+ <!-- Moves a chatbox to a new window. Returns a promise that is resolved
+ once the move to the other window is complete.
+ -->
<method name="detachChatbox">
<parameter name="aChatbox"/>
<parameter name="aOptions"/>
- <parameter name="aCallback"/>
<body><![CDATA[
+ let deferred = Promise.defer();
let options = "";
for (let name in aOptions)
options += "," + name + "=" + aOptions[name];
let otherWin = window.openDialog("chrome://browser/content/chatWindow.xul",
"_blank", "chrome,all,dialog=no" + options);
otherWin.addEventListener("load", function _chatLoad(event) {
if (event.target != otherWin.document)
return;
otherWin.removeEventListener("load", _chatLoad, true);
let otherChatbox = otherWin.document.getElementById("chatter");
aChatbox.swapDocShells(otherChatbox);
aChatbox.close();
- if (aCallback)
- aCallback(otherWin);
+ deferred.resolve(otherChatbox);
}, true);
+ return deferred.promise;
]]></body>
</method>
</implementation>
<handlers>
<handler event="popupshown"><![CDATA[
this.nub.removeAttribute("activity");
@@ -745,19 +735,20 @@
let winWidth = 400;
let winHeight = 420;
// ensure new window entirely within screen
let left = Math.min(Math.max(eX, sX.value),
sX.value + sWidth.value - winWidth);
let top = Math.min(Math.max(eY, sY.value),
sY.value + sHeight.value - winHeight);
- let provider = Social._getProviderFromOrigin(draggedChat.content.getAttribute("origin"));
- this.detachChatbox(draggedChat, { screenX: left, screenY: top }, win => {
- win.document.title = provider.name;
- });
-
+ let title = draggedChat.content.getAttribute("title");
+ this.detachChatbox(draggedChat, { screenX: left, screenY: top }).then(
+ chatbox => {
+ chatbox.contentWindow.document.title = title;
+ }
+ );
event.stopPropagation();
]]></handler>
</handlers>
</binding>
</bindings>
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/chat/browser.ini
@@ -0,0 +1,8 @@
+[DEFAULT]
+support-files =
+ head.js
+ chat.html
+
+[browser_chatwindow.js]
+[browser_focus.js]
+[browser_tearoff.js]
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/chat/browser_chatwindow.js
@@ -0,0 +1,135 @@
+/* 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/. */
+
+let chatbar = document.getElementById("pinnedchats");
+
+add_chat_task(function* testOpenCloseChat() {
+ let chatbox = yield promiseOpenChat("http://example.com");
+ Assert.strictEqual(chatbox, chatbar.selectedChat);
+ // we requested a "normal" chat, so shouldn't be minimized
+ Assert.ok(!chatbox.minimized, "chat is not minimized");
+ Assert.equal(chatbar.childNodes.length, 1, "should be 1 chat open");
+
+
+ // now request the same URL again - we should get the same chat.
+ let chatbox2 = yield promiseOpenChat("http://example.com");
+ Assert.strictEqual(chatbox2, chatbox, "got the same chat");
+ Assert.equal(numChatsInWindow(window), 1, "should be 1 chat open");
+
+ chatbox.toggle();
+ is(chatbox.minimized, true, "chat is now minimized");
+ // was no other chat to select, so selected becomes null.
+ is(chatbar.selectedChat, null);
+
+ // We check the content gets an unload event as we close it.
+ let promiseClosed = promiseOneEvent(chatbox.content, "unload", true);
+ chatbox.close();
+ yield promiseClosed;
+});
+
+// In this case we open a chat minimized, then request the same chat again
+// without specifying minimized. On that second call the chat should open,
+// selected, and no longer minimized.
+add_chat_task(function* testMinimized() {
+ let chatbox = yield promiseOpenChat("http://example.com", "minimized");
+ Assert.strictEqual(chatbox, chatbar.selectedChat);
+ Assert.ok(chatbox.minimized, "chat is minimized");
+ Assert.equal(numChatsInWindow(window), 1, "should be 1 chat open");
+ yield promiseOpenChat("http://example.com");
+ Assert.ok(!chatbox.minimized, false, "chat is no longer minimized");
+});
+
+// open enough chats to overflow the window, then check
+// if the menupopup is visible
+add_chat_task(function* testManyChats() {
+ Assert.ok(chatbar.menupopup.parentNode.collapsed, "popup nub collapsed at start");
+ // we should *never* find a test box that needs more than this to cause
+ // an overflow!
+ let maxToOpen = 20;
+ let numOpened = 0;
+ for (let i = 0; i < maxToOpen; i++) {
+ yield promiseOpenChat("http://example.com#" + i);
+ if (!chatbar.menupopup.parentNode.collapsed) {
+ info("the menu popup appeared");
+ return;
+ }
+ }
+ Assert.ok(false, "We didn't find a collapsed chat after " + maxToOpen + "chats!");
+});
+
+// Check that closeAll works as expected.
+add_chat_task(function* testOpenTwiceCallbacks() {
+ yield promiseOpenChat("http://example.com#1");
+ yield promiseOpenChat("http://example.com#2");
+ yield promiseOpenChat("http://test2.example.com");
+ Assert.equal(numChatsInWindow(window), 3, "should be 3 chats open");
+ Chat.closeAll("http://example.com");
+ Assert.equal(numChatsInWindow(window), 1, "should have closed 2 chats");
+ Chat.closeAll("http://test2.example.com");
+ Assert.equal(numChatsInWindow(window), 0, "should have closed last chat");
+});
+
+// Check that when we open the same chat twice, the callbacks are called back
+// twice.
+add_chat_task(function* testOpenTwiceCallbacks() {
+ yield promiseOpenChatCallback("http://example.com");
+ yield promiseOpenChatCallback("http://example.com");
+});
+
+// Bug 817782 - check chats work in new top-level windows.
+add_chat_task(function* testSecondTopLevelWindow() {
+ const chatUrl = "http://example.com";
+ let secondWindow = OpenBrowserWindow();
+ yield promiseOneEvent(secondWindow, "load");
+ yield promiseOpenChat(chatUrl);
+ // the chat was created - let's make sure it was created in the second window.
+ Assert.equal(numChatsInWindow(window), 0, "main window has no chats");
+ Assert.equal(numChatsInWindow(secondWindow), 1, "second window has 1 chat");
+ secondWindow.close();
+});
+
+// Test that chats are created in the correct window.
+add_chat_task(function* testChatWindowChooser() {
+ let chat = yield promiseOpenChat("http://example.com");
+ Assert.equal(numChatsInWindow(window), 1, "first window has the chat");
+ // create a second window - this will be the "most recent" and will
+ // therefore be the window that hosts the new chat (see bug 835111)
+ let secondWindow = OpenBrowserWindow();
+ yield promiseOneEvent(secondWindow, "load");
+ Assert.equal(numChatsInWindow(secondWindow), 0, "second window starts with no chats");
+ yield promiseOpenChat("http://example.com#2");
+ Assert.equal(numChatsInWindow(secondWindow), 1, "second window now has chats");
+ Assert.equal(numChatsInWindow(window), 1, "first window still has 1 chat");
+ chat.close();
+ Assert.equal(numChatsInWindow(window), 0, "first window now has no chats");
+ // now open another chat - it should still open in the second.
+ yield promiseOpenChat("http://example.com#3");
+ Assert.equal(numChatsInWindow(window), 0, "first window still has no chats");
+ Assert.equal(numChatsInWindow(secondWindow), 2, "second window has both chats");
+
+ // focus the first window, and open yet another chat - it
+ // should open in the first window.
+ window.focus();
+ yield promiseWaitForFocus();
+ chat = yield promiseOpenChat("http://example.com#4");
+ Assert.equal(numChatsInWindow(window), 1, "first window got new chat");
+ chat.close();
+ Assert.equal(numChatsInWindow(window), 0, "first window has no chats");
+
+ let privateWindow = OpenBrowserWindow({private: true});
+ yield promiseOneEvent(privateWindow, "load")
+
+ // open a last chat - the focused window can't accept
+ // chats (it's a private window), so the chat should open
+ // in the window that was selected before. This is known
+ // to be broken on Linux.
+ chat = yield promiseOpenChat("http://example.com#5");
+ let os = Services.appinfo.OS;
+ const BROKEN_WM_Z_ORDER = os != "WINNT" && os != "Darwin";
+ let fn = BROKEN_WM_Z_ORDER ? todo : ok;
+ fn(numChatsInWindow(window) == 1, "first window got the chat");
+ chat.close();
+ privateWindow.close();
+ secondWindow.close();
+});
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/chat/browser_focus.js
@@ -0,0 +1,226 @@
+/* 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/. */
+
+// Tests the focus functionality.
+
+const CHAT_URL = "https://example.com/browser/browser/base/content/test/chat/chat.html";
+
+// Is the currently opened tab focused?
+function isTabFocused() {
+ let tabb = gBrowser.getBrowserForTab(gBrowser.selectedTab);
+ return Services.focus.focusedWindow == tabb.contentWindow;
+}
+
+// Is the specified chat focused?
+function isChatFocused(chat) {
+ return chat.chatbar._isChatFocused(chat);
+}
+
+let chatbar = document.getElementById("pinnedchats");
+
+function* setUp() {
+ // Note that (probably) due to bug 604289, if a tab is focused but the
+ // focused element is null, our chat windows can "steal" focus. This is
+ // avoided if we explicitly focus an element in the tab.
+ // So we load a page with an <input> field and focus that before testing.
+ let html = '<input id="theinput"><button id="chat-opener"></button>';
+ let url = "data:text/html;charset=utf-8," + encodeURI(html);
+ let tab = gBrowser.selectedTab = gBrowser.addTab(url, {skipAnimation: true});
+ yield promiseOneEvent(tab.linkedBrowser, "load", true);
+ tab.linkedBrowser.contentDocument.getElementById("theinput").focus();
+ registerCleanupFunction(function() {
+ gBrowser.removeTab(tab);
+ });
+}
+
+// Test default focus - not user input.
+add_chat_task(function* testDefaultFocus() {
+ yield setUp();
+ let chat = yield promiseOpenChat("http://example.com");
+ // we used the default focus behaviour, which means that because this was
+ // not the direct result of user action the chat should not be focused.
+ Assert.equal(numChatsInWindow(window), 1, "should be 1 chat open");
+ Assert.ok(isTabFocused(), "the tab should remain focused.");
+ Assert.ok(!isChatFocused(chat), "the chat should not be focused.");
+});
+
+// Test default focus via user input.
+add_chat_task(function* testDefaultFocus() {
+ yield setUp();
+ let tab = gBrowser.selectedTab;
+ let deferred = Promise.defer();
+ let button = tab.linkedBrowser.contentDocument.getElementById("chat-opener");
+ button.addEventListener("click", function onclick() {
+ button.removeEventListener("click", onclick);
+ promiseOpenChat("http://example.com").then(
+ chat => deferred.resolve(chat)
+ );
+ })
+ // Note we must use synthesizeMouseAtCenter() rather than calling
+ // .click() directly as this causes nsIDOMWindowUtils.isHandlingUserInput
+ // to be true.
+ EventUtils.synthesizeMouseAtCenter(button, {}, button.ownerDocument.defaultView);
+ let chat = yield deferred.promise;
+
+ // we use the default focus behaviour but the chat was opened via user input,
+ // so the chat should be focused.
+ Assert.equal(numChatsInWindow(window), 1, "should be 1 chat open");
+ Assert.ok(!isTabFocused(), "the tab should have lost focus.");
+ Assert.ok(isChatFocused(chat), "the chat should have got focus.");
+});
+
+// We explicitly ask for the chat to be focused.
+add_chat_task(function* testExplicitFocus() {
+ yield setUp();
+ let chat = yield promiseOpenChat("http://example.com", undefined, true);
+ // we use the default focus behaviour, which means that because this was
+ // not the direct result of user action the chat should not be focused.
+ Assert.equal(numChatsInWindow(window), 1, "should be 1 chat open");
+ Assert.ok(!isTabFocused(), "the tab should have lost focus.");
+ Assert.ok(isChatFocused(chat), "the chat should have got focus.");
+});
+
+// Open a minimized chat via default focus behaviour - it will open and not
+// have focus. Then open the same chat without 'minimized' - it will be
+// restored but should still not have grabbed focus.
+add_chat_task(function* testNoFocusOnAutoRestore() {
+ yield setUp();
+ let chat = yield promiseOpenChat("http://example.com", "minimized");
+ Assert.ok(chat.minimized, "chat is minimized");
+ Assert.equal(numChatsInWindow(window), 1, "should be 1 chat open");
+ Assert.ok(isTabFocused(), "the tab should remain focused.");
+ Assert.ok(!isChatFocused(chat), "the chat should not be focused.");
+ yield promiseOpenChat("http://example.com");
+ Assert.ok(!chat.minimized, "chat should be restored");
+ Assert.ok(isTabFocused(), "the tab should remain focused.");
+ Assert.ok(!isChatFocused(chat), "the chat should not be focused.");
+});
+
+// Here we open a chat, which will not be focused. Then we minimize it and
+// restore it via a titlebar clock - it should get focus at that point.
+add_chat_task(function* testFocusOnExplicitRestore() {
+ yield setUp();
+ let chat = yield promiseOpenChat("http://example.com");
+ Assert.ok(!chat.minimized, "chat should have been opened restored");
+ Assert.ok(isTabFocused(), "the tab should remain focused.");
+ Assert.ok(!isChatFocused(chat), "the chat should not be focused.");
+ chat.minimized = true;
+ Assert.ok(isTabFocused(), "tab should still be focused");
+ Assert.ok(!isChatFocused(chat), "the chat should not be focused.");
+
+ let promise = promiseOneEvent(chat.contentWindow, "focus");
+ // pretend we clicked on the titlebar
+ chat.onTitlebarClick({button: 0});
+ yield promise; // wait for focus event.
+ Assert.ok(!chat.minimized, "chat should have been restored");
+ Assert.ok(isChatFocused(chat), "chat should be focused");
+ Assert.strictEqual(chat, chatbar.selectedChat, "chat is marked selected");
+});
+
+// Open 2 chats and give 1 focus. Minimize the focused one - the second
+// should get focus.
+add_chat_task(function* testMinimizeFocused() {
+ yield setUp();
+ let chat1 = yield promiseOpenChat("http://example.com#1");
+ let chat2 = yield promiseOpenChat("http://example.com#2");
+ Assert.equal(numChatsInWindow(window), 2, "2 chats open");
+ Assert.strictEqual(chatbar.selectedChat, chat2, "chat2 is selected");
+ let promise = promiseOneEvent(chat1.contentWindow, "focus");
+ chatbar.selectedChat = chat1;
+ chatbar.focus();
+ yield promise; // wait for chat1 to get focus.
+ Assert.strictEqual(chat1, chatbar.selectedChat, "chat1 is marked selected");
+ Assert.notStrictEqual(chat2, chatbar.selectedChat, "chat2 is not marked selected");
+ promise = promiseOneEvent(chat2.contentWindow, "focus");
+ chat1.minimized = true;
+ yield promise; // wait for chat2 to get focus.
+ Assert.notStrictEqual(chat1, chatbar.selectedChat, "chat1 is not marked selected");
+ Assert.strictEqual(chat2, chatbar.selectedChat, "chat2 is marked selected");
+});
+
+// Open 2 chats, select and focus the second. Pressing the TAB key should
+// cause focus to move between all elements in our chat window before moving
+// to the next chat window.
+add_chat_task(function* testTab() {
+ yield setUp();
+
+ function sendTabAndWaitForFocus(chat, eltid) {
+ let doc = chat.contentDocument;
+ EventUtils.sendKey("tab");
+ // ideally we would use the 'focus' event here, but that doesn't work
+ // as expected for the iframe - the iframe itself never gets the focus
+ // event (apparently the sub-document etc does.)
+ // So just poll for the correct element getting focus...
+ let deferred = Promise.defer();
+ let tries = 0;
+ let interval = setInterval(function() {
+ if (tries >= 30) {
+ clearInterval(interval);
+ deferred.reject("never got focus");
+ return;
+ }
+ tries ++;
+ let elt = eltid ? doc.getElementById(eltid) : doc.documentElement;
+ if (doc.activeElement == elt) {
+ clearInterval(interval);
+ deferred.resolve();
+ }
+ });
+ return deferred.promise;
+ }
+
+ let chat1 = yield promiseOpenChat(CHAT_URL + "#1");
+ let chat2 = yield promiseOpenChat(CHAT_URL + "#2");
+ chatbar.selectedChat = chat2;
+ let promise = promiseOneEvent(chat2.contentWindow, "focus");
+ chatbar.focus();
+ yield promise;
+
+ // Our chats have 3 focusable elements, so it takes 4 TABs to move
+ // to the new chat.
+ yield sendTabAndWaitForFocus(chat2, "input1");
+ Assert.equal(chat2.contentDocument.activeElement.getAttribute("id"), "input1",
+ "first input field has focus");
+ Assert.ok(isChatFocused(chat2), "new chat still focused after first tab");
+
+ yield sendTabAndWaitForFocus(chat2, "input2");
+ Assert.ok(isChatFocused(chat2), "new chat still focused after tab");
+ Assert.equal(chat2.contentDocument.activeElement.getAttribute("id"), "input2",
+ "second input field has focus");
+
+ yield sendTabAndWaitForFocus(chat2, "iframe");
+ Assert.ok(isChatFocused(chat2), "new chat still focused after tab");
+ Assert.equal(chat2.contentDocument.activeElement.getAttribute("id"), "iframe",
+ "iframe has focus");
+
+ // this tab now should move to the next chat, but focus the
+ // document element itself (hence the null eltid)
+ yield sendTabAndWaitForFocus(chat1, null);
+ Assert.ok(isChatFocused(chat1), "first chat is focused");
+});
+
+// Open a chat and focus an element other than the first. Move focus to some
+// other item (the tab itself in this case), then focus the chatbar - the
+// same element that was previously focused should still have focus.
+add_chat_task(function* testFocusedElement() {
+ yield setUp();
+
+ // open a chat with focus requested.
+ let chat = yield promiseOpenChat(CHAT_URL, undefined, true);
+
+ chat.contentDocument.getElementById("input2").focus();
+
+ // set focus to the tab.
+ let tabb = gBrowser.getBrowserForTab(gBrowser.selectedTab);
+ let promise = promiseOneEvent(tabb.contentWindow, "focus");
+ Services.focus.moveFocus(tabb.contentWindow, null, Services.focus.MOVEFOCUS_ROOT, 0);
+ yield promise;
+
+ promise = promiseOneEvent(chat.contentWindow, "focus");
+ chatbar.focus();
+ yield promise;
+
+ Assert.equal(chat.contentDocument.activeElement.getAttribute("id"), "input2",
+ "correct input field still has focus");
+});
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/chat/browser_tearoff.js
@@ -0,0 +1,128 @@
+/* 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/. */
+
+let chatbar = document.getElementById("pinnedchats");
+
+function promiseNewWindowLoaded() {
+ let deferred = Promise.defer();
+ Services.wm.addListener({
+ onWindowTitleChange: function() {},
+ onCloseWindow: function(xulwindow) {},
+ onOpenWindow: function(xulwindow) {
+ var domwindow = xulwindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIDOMWindow);
+ Services.wm.removeListener(this);
+ // wait for load to ensure the window is ready for us to test
+ domwindow.addEventListener("load", function _load(event) {
+ let doc = domwindow.document;
+ if (event.target != doc)
+ return;
+ domwindow.removeEventListener("load", _load);
+ deferred.resolve(domwindow);
+ });
+ },
+ });
+ return deferred.promise;
+}
+
+add_chat_task(function* testTearoffChat() {
+ let chatbox = yield promiseOpenChat("http://example.com");
+ Assert.equal(numChatsInWindow(window), 1, "should be 1 chat open");
+
+ let chatDoc = chatbox.contentDocument;
+ let chatTitle = chatDoc.title;
+
+ Assert.equal(chatbox.getAttribute("label"), chatTitle,
+ "the new chatbox should show the title of the chat window");
+
+ // mutate the chat document a bit before we tear it off.
+ let div = chatDoc.createElement("div");
+ div.setAttribute("id", "testdiv");
+ div.setAttribute("test", "1");
+ chatDoc.body.appendChild(div);
+
+ // chatbox is open, lets detach. The new chat window will be caught in
+ // the window watcher below
+ let promise = promiseNewWindowLoaded();
+
+ let swap = document.getAnonymousElementByAttribute(chatbox, "anonid", "swap");
+ swap.click();
+
+ // and wait for the new window.
+ let domwindow = yield promise;
+
+ Assert.equal(domwindow.document.documentElement.getAttribute("windowtype"), "Social:Chat", "Social:Chat window opened");
+ Assert.equal(numChatsInWindow(window), 0, "should be no chats in the chat bar");
+
+ // get the chatbox from the new window.
+ chatbox = domwindow.document.getElementById("chatter")
+ Assert.equal(chatbox.getAttribute("label"), chatTitle, "window should have same title as chat");
+
+ div = chatbox.contentDocument.getElementById("testdiv");
+ Assert.equal(div.getAttribute("test"), "1", "docshell should have been swapped");
+ div.setAttribute("test", "2");
+
+ // swap the window back to the chatbar
+ promise = promiseOneEvent(domwindow, "unload");
+ swap = domwindow.document.getAnonymousElementByAttribute(chatbox, "anonid", "swap");
+ swap.click();
+
+ yield promise;
+
+ Assert.equal(numChatsInWindow(window), 1, "chat should be docked back in the window");
+ chatbox = chatbar.selectedChat;
+ Assert.equal(chatbox.getAttribute("label"), chatTitle,
+ "the new chatbox should show the title of the chat window again");
+
+ div = chatbox.contentDocument.getElementById("testdiv");
+ Assert.equal(div.getAttribute("test"), "2", "docshell should have been swapped");
+});
+
+// Similar test but with 2 chats.
+add_chat_task(function* testReattachTwice() {
+ let chatbox1 = yield promiseOpenChat("http://example.com#1");
+ let chatbox2 = yield promiseOpenChat("http://example.com#2");
+ Assert.equal(numChatsInWindow(window), 2, "both chats should be docked in the window");
+
+ info("chatboxes are open, detach from window");
+ let promise = promiseNewWindowLoaded();
+ document.getAnonymousElementByAttribute(chatbox1, "anonid", "swap").click();
+ let domwindow1 = yield promise;
+ chatbox1 = domwindow1.document.getElementById("chatter");
+ Assert.equal(numChatsInWindow(window), 1, "only second chat should be docked in the window");
+
+ promise = promiseNewWindowLoaded();
+ document.getAnonymousElementByAttribute(chatbox2, "anonid", "swap").click();
+ let domwindow2 = yield promise;
+ chatbox2 = domwindow2.document.getElementById("chatter");
+ Assert.equal(numChatsInWindow(window), 0, "should be no docked chats");
+
+ promise = promiseOneEvent(domwindow2, "unload");
+ domwindow2.document.getAnonymousElementByAttribute(chatbox2, "anonid", "swap").click();
+ yield promise;
+ Assert.equal(numChatsInWindow(window), 1, "one chat should be docked back in the window");
+
+ promise = promiseOneEvent(domwindow1, "unload");
+ domwindow1.document.getAnonymousElementByAttribute(chatbox1, "anonid", "swap").click();
+ yield promise;
+ Assert.equal(numChatsInWindow(window), 2, "both chats should be docked back in the window");
+});
+
+// Check that Chat.closeAll() also closes detached windows.
+add_chat_task(function* testCloseAll() {
+ let chatbox1 = yield promiseOpenChat("http://example.com#1");
+ let chatbox2 = yield promiseOpenChat("http://example.com#2");
+
+ let promise = promiseNewWindowLoaded();
+ document.getAnonymousElementByAttribute(chatbox1, "anonid", "swap").click();
+ let domwindow = yield promise;
+ chatbox1 = domwindow.document.getElementById("chatter");
+
+ let promiseWindowUnload = promiseOneEvent(domwindow, "unload");
+
+ Assert.equal(numChatsInWindow(window), 1, "second chat should still be docked");
+ Chat.closeAll("http://example.com");
+ yield promiseWindowUnload;
+ Assert.equal(numChatsInWindow(window), 0, "should be no chats left");
+});
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/chat/chat.html
@@ -0,0 +1,14 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>test chat window</title>
+ </head>
+ <body>
+ <p>This is a test chat window.</p>
+ <!-- a couple of input fields to help with focus testing -->
+ <input id="input1"/>
+ <input id="input2"/>
+ <!-- an iframe here so this one page generates multiple load events -->
+ <iframe id="iframe" src="data:text/plain:this is an iframe"></iframe>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/chat/head.js
@@ -0,0 +1,74 @@
+/* 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/. */
+
+// Utility functions for Chat tests.
+
+let Chat = Cu.import("resource:///modules/Chat.jsm", {}).Chat;
+
+function promiseOpenChat(url, mode, focus) {
+ let uri = Services.io.newURI(url, null, null);
+ let origin = uri.prePath;
+ let title = origin;
+ let chatbox = Chat.open(null, origin, title, url, mode, focus);
+ return chatbox.promiseChatLoaded;
+}
+
+// Opens a chat, returns a promise resolved when the chat callback fired.
+function promiseOpenChatCallback(url, mode) {
+ let uri = Services.io.newURI(url, null, null);
+ let origin = uri.prePath;
+ let title = origin;
+ let deferred = Promise.defer();
+ let callback = deferred.resolve;
+ Chat.open(null, origin, title, url, mode, undefined, callback);
+ return deferred.promise;
+}
+
+// Opens a chat, returns the chat window's promise which fires when the chat
+// starts loading.
+function promiseOneEvent(target, eventName, capture) {
+ let deferred = Promise.defer();
+ target.addEventListener(eventName, function handler(event) {
+ target.removeEventListener(eventName, handler, capture);
+ deferred.resolve();
+ }, capture);
+ return deferred.promise;
+}
+
+// Return the number of chats in a browser window.
+function numChatsInWindow(win) {
+ let chatbar = win.document.getElementById("pinnedchats");
+ return chatbar.childElementCount;
+}
+
+function promiseWaitForFocus() {
+ let deferred = Promise.defer();
+ waitForFocus(deferred.resolve);
+ return deferred.promise;
+}
+
+// A simple way to clean up after each test.
+function add_chat_task(genFunction) {
+ add_task(function* () {
+ info("Starting chat test " + genFunction.name);
+ try {
+ yield genFunction();
+ } finally {
+ info("Finished chat test " + genFunction.name + " - cleaning up.");
+ // close all docked chats.
+ while (chatbar.childNodes.length) {
+ chatbar.childNodes[0].close();
+ }
+ // and non-docked chats.
+ let winEnum = Services.wm.getEnumerator("Social:Chat");
+ while (winEnum.hasMoreElements()) {
+ let win = winEnum.getNext();
+ if (win.closed) {
+ continue;
+ }
+ win.close();
+ }
+ }
+ });
+}
--- a/browser/base/content/test/social/browser.ini
+++ b/browser/base/content/test/social/browser.ini
@@ -21,17 +21,16 @@ support-files =
social_sidebar.html
social_sidebar_empty.html
social_window.html
social_worker.js
unchecked.jpg
[browser_addons.js]
[browser_blocklist.js]
-[browser_chat_tearoff.js]
[browser_defaults.js]
[browser_share.js]
[browser_social_activation.js]
[browser_social_chatwindow.js]
[browser_social_chatwindow_resize.js]
[browser_social_chatwindowfocus.js]
[browser_social_errorPage.js]
[browser_social_flyout.js]
deleted file mode 100644
--- a/browser/base/content/test/social/browser_chat_tearoff.js
+++ /dev/null
@@ -1,308 +0,0 @@
-/* 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/. */
-
-function test() {
- requestLongerTimeout(2); // only debug builds seem to need more time...
- waitForExplicitFinish();
-
- let manifest = { // normal provider
- name: "provider 1",
- origin: "https://example.com",
- sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
- workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
- iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png"
- };
-
- let postSubTest = function(cb) {
- let chats = document.getElementById("pinnedchats");
- ok(chats.children.length == 0, "no chatty children left behind");
- cb();
- };
- runSocialTestWithProvider(manifest, function (finishcb) {
- SocialSidebar.show();
- ok(SocialSidebar.provider, "sidebar provider exists");
- runSocialTests(tests, undefined, postSubTest, function() {
- finishcb();
- });
- });
-}
-
-var tests = {
- testTearoffChat: function(next) {
- let chats = document.getElementById("pinnedchats");
- let chatTitle;
- let port = SocialSidebar.provider.getWorkerPort();
- ok(port, "provider has a port");
- port.onmessage = function (e) {
- let topic = e.data.topic;
- switch (topic) {
- case "got-sidebar-message":
- port.postMessage({topic: "test-chatbox-open"});
- break;
- case "got-chatbox-visibility":
- // chatbox is open, lets detach. The new chat window will be caught in
- // the window watcher below
- let doc = chats.selectedChat.contentDocument;
- // This message is (sometimes!) received a second time
- // before we start our tests from the onCloseWindow
- // callback.
- if (doc.location == "about:blank")
- return;
- chatTitle = doc.title;
- ok(chats.selectedChat.getAttribute("label") == chatTitle,
- "the new chatbox should show the title of the chat window");
- let div = doc.createElement("div");
- div.setAttribute("id", "testdiv");
- div.setAttribute("test", "1");
- doc.body.appendChild(div);
- let swap = document.getAnonymousElementByAttribute(chats.selectedChat, "anonid", "swap");
- swap.click();
- port.close();
- break;
- case "got-chatbox-message":
- ok(true, "got chatbox message");
- ok(e.data.result == "ok", "got chatbox windowRef result: "+e.data.result);
- chats.selectedChat.toggle();
- break;
- }
- }
-
- Services.wm.addListener({
- onWindowTitleChange: function() {},
- onCloseWindow: function(xulwindow) {},
- onOpenWindow: function(xulwindow) {
- var domwindow = xulwindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
- .getInterface(Components.interfaces.nsIDOMWindow);
- Services.wm.removeListener(this);
- // wait for load to ensure the window is ready for us to test
- domwindow.addEventListener("load", function _load(event) {
- let doc = domwindow.document;
- if (event.target != doc)
- return;
-
- domwindow.removeEventListener("load", _load, false);
-
- domwindow.addEventListener("unload", function _close(event) {
- if (event.target != doc)
- return;
- domwindow.removeEventListener("unload", _close, false);
- info("window has been closed");
- waitForCondition(function() {
- return chats.selectedChat && chats.selectedChat.contentDocument &&
- chats.selectedChat.contentDocument.readyState == "complete";
- },function () {
- ok(chats.selectedChat, "should have a chatbox in our window again");
- ok(chats.selectedChat.getAttribute("label") == chatTitle,
- "the new chatbox should show the title of the chat window again");
- let testdiv = chats.selectedChat.contentDocument.getElementById("testdiv");
- is(testdiv.getAttribute("test"), "2", "docshell should have been swapped");
- chats.selectedChat.close();
- waitForCondition(function() {
- return chats.children.length == 0;
- },function () {
- next();
- });
- });
- }, false);
-
- is(doc.documentElement.getAttribute("windowtype"), "Social:Chat", "Social:Chat window opened");
- // window is loaded, but the docswap does not happen until after load,
- // and we have no event to wait on, so we'll wait for document state
- // to be ready
- let chatbox = doc.getElementById("chatter");
- waitForCondition(function() {
- return chats.selectedChat == null &&
- chatbox.contentDocument &&
- chatbox.contentDocument.readyState == "complete";
- },function() {
- ok(chatbox.getAttribute("label") == chatTitle,
- "detached window should show the title of the chat window");
- let testdiv = chatbox.contentDocument.getElementById("testdiv");
- is(testdiv.getAttribute("test"), "1", "docshell should have been swapped");
- testdiv.setAttribute("test", "2");
- // swap the window back to the chatbar
- let swap = doc.getAnonymousElementByAttribute(chatbox, "anonid", "swap");
- swap.click();
- }, domwindow);
- }, false);
- }
- });
-
- port.postMessage({topic: "test-init", data: { id: 1 }});
- },
-
- testCloseOnLogout: function(next) {
- let chats = document.getElementById("pinnedchats");
- const chatUrl = "https://example.com/browser/browser/base/content/test/social/social_chat.html";
- let port = SocialSidebar.provider.getWorkerPort();
- ok(port, "provider has a port");
- port.postMessage({topic: "test-init"});
- port.onmessage = function (e) {
- let topic = e.data.topic;
- switch (topic) {
- case "got-chatbox-visibility":
- // chatbox is open, lets detach. The new chat window will be caught in
- // the window watcher below
- let doc = chats.selectedChat.contentDocument;
- // This message is (sometimes!) received a second time
- // before we start our tests from the onCloseWindow
- // callback.
- if (doc.location == "about:blank")
- return;
- info("chatbox is open, detach from window");
- let swap = document.getAnonymousElementByAttribute(chats.selectedChat, "anonid", "swap");
- swap.click();
- break;
- }
- }
-
- Services.wm.addListener({
- onWindowTitleChange: function() {},
- onCloseWindow: function(xulwindow) {},
- onOpenWindow: function(xulwindow) {
- let domwindow = xulwindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
- .getInterface(Components.interfaces.nsIDOMWindow);
- Services.wm.removeListener(this);
- // wait for load to ensure the window is ready for us to test, make sure
- // we're not getting called for about:blank
- domwindow.addEventListener("load", function _load(event) {
- let doc = domwindow.document;
- if (event.target != doc)
- return;
- domwindow.removeEventListener("load", _load, false);
-
- domwindow.addEventListener("unload", function _close(event) {
- if (event.target != doc)
- return;
- domwindow.removeEventListener("unload", _close, false);
- ok(true, "window has been closed");
- next();
- }, false);
-
- is(doc.documentElement.getAttribute("windowtype"), "Social:Chat", "Social:Chat window opened");
- // window is loaded, but the docswap does not happen until after load,
- // and we have no event to wait on, so we'll wait for document state
- // to be ready
- let chatbox = doc.getElementById("chatter");
- waitForCondition(function() {
- return chats.children.length == 0 &&
- chatbox.contentDocument &&
- chatbox.contentDocument.readyState == "complete";
- },function() {
- // logout, we should get unload next
- port.postMessage({topic: "test-logout"});
- port.close();
- }, domwindow);
-
- }, false);
- }
- });
-
- port.postMessage({topic: "test-worker-chat", data: chatUrl});
- },
-
- testReattachTwice: function(next) {
- let chats = document.getElementById("pinnedchats");
- const chatUrl = "https://example.com/browser/browser/base/content/test/social/social_chat.html";
- let chatBoxCount = 0, reattachCount = 0;
- let port = SocialSidebar.provider.getWorkerPort();
- ok(port, "provider has a port");
- port.postMessage({topic: "test-init"});
- port.onmessage = function (e) {
- let topic = e.data.topic;
- switch (topic) {
- case "got-chatbox-visibility":
- // chatbox is open, lets detach. The new chat window will be caught in
- // the window watcher below
- let doc = chats.selectedChat.contentDocument;
- // This message is (sometimes!) received a second time
- // before we start our tests from the onCloseWindow
- // callback.
- if (doc.location == "about:blank")
- return;
- if (++chatBoxCount != 2) {
- // open the second chat window
- port.postMessage({topic: "test-worker-chat", data: chatUrl + "?id=2"});
- return;
- }
- info("chatbox is open, detach from window");
- let chat1 = chats.firstChild;
- let chat2 = chat1.nextSibling;
- document.getAnonymousElementByAttribute(chat1, "anonid", "swap").click();
- document.getAnonymousElementByAttribute(chat2, "anonid", "swap").click();
- break;
- }
- };
-
- let firstChatWindowDoc;
- Services.wm.addListener({
- onWindowTitleChange: function() {},
- onCloseWindow: function(xulwindow) {},
- onOpenWindow: function(xulwindow) {
- let listener = this;
- let domwindow = xulwindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
- .getInterface(Components.interfaces.nsIDOMWindow);
- // wait for load to ensure the window is ready for us to test, make sure
- // we're not getting called for about:blank
- domwindow.addEventListener("load", function _load(event) {
- let doc = domwindow.document;
- if (event.target != doc)
- return;
- domwindow.removeEventListener("load", _load, false);
-
- domwindow.addEventListener("unload", function _close(event) {
- if (event.target != doc)
- return;
- domwindow.removeEventListener("unload", _close, false);
- ok(true, "window has been closed");
- waitForCondition(function() {
- return chats.selectedChat && chats.selectedChat.contentDocument &&
- chats.selectedChat.contentDocument.readyState == "complete";
- }, function () {
- ++reattachCount;
- if (reattachCount == 1) {
- info("reattaching second chat window");
- let chatbox = firstChatWindowDoc.getElementById("chatter");
- firstChatWindowDoc.getAnonymousElementByAttribute(chatbox, "anonid", "swap").click();
- firstChatWindowDoc = null;
- }
- else if (reattachCount == 2) {
- is(chats.children.length, 2, "both chat windows should be reattached");
- chats.removeAll();
- waitForCondition(() => chats.children.length == 0, function () {
- info("no chat window left");
- is(chats.chatboxForURL.size, 0, "chatboxForURL map should be empty");
- next();
- });
- }
- }, "waited too long for the window to reattach");
- }, false);
-
- is(doc.documentElement.getAttribute("windowtype"), "Social:Chat", "Social:Chat window opened");
- if (!firstChatWindowDoc) {
- firstChatWindowDoc = doc;
- return;
- }
- Services.wm.removeListener(listener);
-
- // window is loaded, but the docswap does not happen until after load,
- // and we have no event to wait on, so we'll wait for document state
- // to be ready
- let chatbox = doc.getElementById("chatter");
- waitForCondition(function() {
- return chats.children.length == 0 &&
- chatbox.contentDocument &&
- chatbox.contentDocument.readyState == "complete";
- },function() {
- info("reattaching chat window");
- doc.getAnonymousElementByAttribute(chatbox, "anonid", "swap").click();
- }, "waited too long for the chat window to be detached");
-
- }, false);
- }
- });
-
- port.postMessage({topic: "test-worker-chat", data: chatUrl + "?id=1"});
- }
-};
--- a/browser/base/content/test/social/browser_social_chatwindow.js
+++ b/browser/base/content/test/social/browser_social_chatwindow.js
@@ -39,16 +39,20 @@ function openChat(provider, callback) {
}
}
let url = chatUrl + "?" + (chatId++);
port.postMessage({topic: "test-init"});
port.postMessage({topic: "test-worker-chat", data: url});
gURLsNotRemembered.push(url);
}
+function windowHasChats(win) {
+ return !!getChatBar().firstElementChild;
+}
+
function test() {
requestLongerTimeout(2); // only debug builds seem to need more time...
waitForExplicitFinish();
let oldwidth = window.outerWidth; // we futz with these, so we restore them
let oldleft = window.screenX;
window.moveTo(0, window.screenY)
let postSubTest = function(cb) {
@@ -102,95 +106,16 @@ var tests = {
ok(true, "got chatbox message");
ok(e.data.result == "ok", "got chatbox windowRef result: "+e.data.result);
chats.selectedChat.toggle();
break;
}
}
port.postMessage({topic: "test-init", data: { id: 1 }});
},
- testOpenMinimized: function(next) {
- // In this case the sidebar opens a chat (without specifying minimized).
- // We then minimize it and have the sidebar reopen the chat (again without
- // minimized). On that second call the chat should open and no longer
- // be minimized.
- let chats = document.getElementById("pinnedchats");
- let port = SocialSidebar.provider.getWorkerPort();
- let seen_opened = false;
- port.onmessage = function (e) {
- let topic = e.data.topic;
- switch (topic) {
- case "test-init-done":
- port.postMessage({topic: "test-chatbox-open"});
- break;
- case "chatbox-opened":
- is(e.data.result, "ok", "the sidebar says it got a chatbox");
- if (!seen_opened) {
- // first time we got the opened message, so minimize the chat then
- // re-request the same chat to be opened - we should get the
- // message again and the chat should be restored.
- ok(!chats.selectedChat.minimized, "chat not initially minimized")
- chats.selectedChat.minimized = true
- seen_opened = true;
- port.postMessage({topic: "test-chatbox-open"});
- } else {
- // This is the second time we've seen this message - there should
- // be exactly 1 chat open and it should no longer be minimized.
- let chats = document.getElementById("pinnedchats");
- ok(!chats.selectedChat.minimized, "chat no longer minimized")
- chats.selectedChat.close();
- is(chats.selectedChat, null, "should only have been one chat open");
- port.close();
- next();
- }
- }
- }
- port.postMessage({topic: "test-init", data: { id: 1 }});
- },
- testManyChats: function(next) {
- // open enough chats to overflow the window, then check
- // if the menupopup is visible
- let port = SocialSidebar.provider.getWorkerPort();
- let chats = document.getElementById("pinnedchats");
- ok(port, "provider has a port");
- ok(chats.menupopup.parentNode.collapsed, "popup nub collapsed at start");
- port.postMessage({topic: "test-init"});
- // we should *never* find a test box that needs more than this to cause
- // an overflow!
- let maxToOpen = 20;
- let numOpened = 0;
- let maybeOpenAnother = function() {
- if (numOpened++ >= maxToOpen) {
- ok(false, "We didn't find a collapsed chat after " + maxToOpen + "chats!");
- closeAllChats();
- next();
- }
- port.postMessage({topic: "test-chatbox-open", data: { id: numOpened }});
- }
- port.onmessage = function (e) {
- let topic = e.data.topic;
- switch (topic) {
- case "got-chatbox-message":
- if (!chats.menupopup.parentNode.collapsed) {
- maybeOpenAnother();
- break;
- }
- ok(true, "popup nub became visible");
- // close our chats now
- while (chats.selectedChat) {
- chats.selectedChat.close();
- }
- ok(!chats.selectedChat, "chats are all closed");
- port.close();
- next();
- break;
- }
- }
- maybeOpenAnother();
- },
testWorkerChatWindow: function(next) {
const chatUrl = SocialSidebar.provider.origin + "/browser/browser/base/content/test/social/social_chat.html";
let chats = document.getElementById("pinnedchats");
let port = SocialSidebar.provider.getWorkerPort();
ok(port, "provider has a port");
port.postMessage({topic: "test-init"});
port.onmessage = function (e) {
let topic = e.data.topic;
@@ -234,71 +159,20 @@ var tests = {
ok(!chat.parentNode, "chat is now closed");
port.close();
next();
break;
}
}
port.postMessage({topic: "test-init", data: { id: 1 }});
},
- testSameChatCallbacks: function(next) {
- let chats = document.getElementById("pinnedchats");
- let port = SocialSidebar.provider.getWorkerPort();
- let seen_opened = false;
- port.onmessage = function (e) {
- let topic = e.data.topic;
- switch (topic) {
- case "test-init-done":
- port.postMessage({topic: "test-chatbox-open"});
- break;
- case "chatbox-opened":
- is(e.data.result, "ok", "the sidebar says it got a chatbox");
- if (seen_opened) {
- // This is the second time we've seen this message - there should
- // be exactly 1 chat open.
- let chats = document.getElementById("pinnedchats");
- chats.selectedChat.close();
- is(chats.selectedChat, null, "should only have been one chat open");
- port.close();
- next();
- } else {
- // first time we got the opened message, so re-request the same
- // chat to be opened - we should get the message again.
- seen_opened = true;
- port.postMessage({topic: "test-chatbox-open"});
- }
- }
- }
- port.postMessage({topic: "test-init", data: { id: 1 }});
- },
-
- // check removeAll does the right thing
- testRemoveAll: function(next, mode) {
- let port = SocialSidebar.provider.getWorkerPort();
- port.postMessage({topic: "test-init"});
- get3ChatsForCollapsing(mode || "normal", function() {
- let chatbar = window.SocialChatBar.chatbar;
- chatbar.removeAll();
- // should be no evidence of any chats left.
- is(chatbar.childNodes.length, 0, "should be no chats left");
- checkPopup();
- is(chatbar.selectedChat, null, "nothing should be selected");
- is(chatbar.chatboxForURL.size, 0, "chatboxForURL map should be empty");
- port.close();
- next();
- });
- },
-
- testRemoveAllMinimized: function(next) {
- this.testRemoveAll(next, "minimized");
- },
// Check what happens when you close the only visible chat.
testCloseOnlyVisible: function(next) {
- let chatbar = window.SocialChatBar.chatbar;
+ let chatbar = getChatBar();
let chatWidth = undefined;
let num = 0;
is(chatbar.childNodes.length, 0, "chatbar starting empty");
is(chatbar.menupopup.childNodes.length, 0, "popup starting empty");
makeChat("normal", "first chat", function() {
// got the first one.
checkPopup();
@@ -326,81 +200,26 @@ var tests = {
});
});
},
testShowWhenCollapsed: function(next) {
let port = SocialSidebar.provider.getWorkerPort();
port.postMessage({topic: "test-init"});
get3ChatsForCollapsing("normal", function(first, second, third) {
- let chatbar = window.SocialChatBar.chatbar;
+ let chatbar = getChatBar();
chatbar.showChat(first);
ok(!first.collapsed, "first should no longer be collapsed");
ok(second.collapsed || third.collapsed, false, "one of the others should be collapsed");
closeAllChats();
port.close();
next();
});
},
- testActivity: function(next) {
- let port = SocialSidebar.provider.getWorkerPort();
- port.postMessage({topic: "test-init"});
- get3ChatsForCollapsing("normal", function(first, second, third) {
- let chatbar = window.SocialChatBar.chatbar;
- is(chatbar.selectedChat, third, "third chat should be selected");
- ok(!chatbar.selectedChat.hasAttribute("activity"), "third chat should have no activity");
- // send an activity message to the second.
- ok(!second.hasAttribute("activity"), "second chat should have no activity");
- let chat2 = second.content;
- let evt = chat2.contentDocument.createEvent("CustomEvent");
- evt.initCustomEvent("socialChatActivity", true, true, {});
- chat2.contentDocument.documentElement.dispatchEvent(evt);
- // second should have activity.
- ok(second.hasAttribute("activity"), "second chat should now have activity");
- // select the second - it should lose "activity"
- chatbar.selectedChat = second;
- ok(!second.hasAttribute("activity"), "second chat should no longer have activity");
- // Now try the first - it is collapsed, so the 'nub' also gets activity attr.
- ok(!first.hasAttribute("activity"), "first chat should have no activity");
- let chat1 = first.content;
- let evt = chat1.contentDocument.createEvent("CustomEvent");
- evt.initCustomEvent("socialChatActivity", true, true, {});
- chat1.contentDocument.documentElement.dispatchEvent(evt);
- ok(first.hasAttribute("activity"), "first chat should now have activity");
- ok(chatbar.nub.hasAttribute("activity"), "nub should also have activity");
- // first is collapsed, so use openChat to get it.
- chatbar.openChat(SocialSidebar.provider, first.getAttribute("src"));
- ok(!first.hasAttribute("activity"), "first chat should no longer have activity");
- // The nub should lose the activity flag here too
- todo(!chatbar.nub.hasAttribute("activity"), "Bug 806266 - nub should no longer have activity");
- // TODO: tests for bug 806266 should arrange to have 2 chats collapsed
- // then open them checking the nub is updated correctly.
- // Now we will go and change the embedded browser in the second chat and
- // ensure the activity magic still works (ie, check that the unload for
- // the browser didn't cause our event handlers to be removed.)
- ok(!second.hasAttribute("activity"), "second chat should have no activity");
- let subiframe = chat2.contentDocument.getElementById("iframe");
- subiframe.contentWindow.addEventListener("unload", function subunload() {
- subiframe.contentWindow.removeEventListener("unload", subunload);
- // ensure all other unload listeners have fired.
- executeSoon(function() {
- let evt = chat2.contentDocument.createEvent("CustomEvent");
- evt.initCustomEvent("socialChatActivity", true, true, {});
- chat2.contentDocument.documentElement.dispatchEvent(evt);
- ok(second.hasAttribute("activity"), "second chat still has activity after unloading sub-iframe");
- closeAllChats();
- port.close();
- next();
- })
- })
- subiframe.setAttribute("src", "data:text/plain:new location for iframe");
- });
- },
-
testOnlyOneCallback: function(next) {
let chats = document.getElementById("pinnedchats");
let port = SocialSidebar.provider.getWorkerPort();
let numOpened = 0;
port.onmessage = function (e) {
let topic = e.data.topic;
switch (topic) {
case "test-init-done":
@@ -408,121 +227,41 @@ var tests = {
break;
case "chatbox-opened":
numOpened += 1;
port.postMessage({topic: "ping"});
break;
case "pong":
executeSoon(function() {
is(numOpened, 1, "only got one open message");
- chats.removeAll();
+ chats.selectedChat.close();
port.close();
next();
});
}
}
port.postMessage({topic: "test-init", data: { id: 1 }});
},
- testSecondTopLevelWindow: function(next) {
- // Bug 817782 - check chats work in new top-level windows.
- const chatUrl = SocialSidebar.provider.origin + "/browser/browser/base/content/test/social/social_chat.html";
- let port = SocialSidebar.provider.getWorkerPort();
- let secondWindow;
- port.onmessage = function(e) {
- if (e.data.topic == "test-init-done") {
- secondWindow = OpenBrowserWindow();
- secondWindow.addEventListener("load", function loadListener() {
- secondWindow.removeEventListener("load", loadListener);
- port.postMessage({topic: "test-worker-chat", data: chatUrl});
- });
- } else if (e.data.topic == "got-chatbox-message") {
- // the chat was created - let's make sure it was created in the second window.
- is(secondWindow.SocialChatBar.chatbar.childElementCount, 1);
- secondWindow.close();
- next();
- }
- }
- port.postMessage({topic: "test-init"});
- },
-
- testChatWindowChooser: function(next) {
- // Tests that when a worker creates a chat, it is opened in the correct
- // window.
- // open a chat (it will open in the main window)
- ok(!window.SocialChatBar.hasChats, "first window should start with no chats");
- openChat(SocialSidebar.provider, function() {
- ok(window.SocialChatBar.hasChats, "first window has the chat");
- // create a second window - this will be the "most recent" and will
- // therefore be the window that hosts the new chat (see bug 835111)
- let secondWindow = OpenBrowserWindow();
- secondWindow.addEventListener("load", function loadListener() {
- secondWindow.removeEventListener("load", loadListener);
- ok(!secondWindow.SocialChatBar.hasChats, "second window has no chats");
- openChat(SocialSidebar.provider, function() {
- ok(secondWindow.SocialChatBar.hasChats, "second window now has chats");
- is(window.SocialChatBar.chatbar.childElementCount, 1, "first window still has 1 chat");
- window.SocialChatBar.chatbar.removeAll();
- // now open another chat - it should still open in the second.
- openChat(SocialSidebar.provider, function() {
- ok(!window.SocialChatBar.hasChats, "first window has no chats");
- ok(secondWindow.SocialChatBar.hasChats, "second window has a chat");
-
- // focus the first window, and open yet another chat - it
- // should open in the first window.
- waitForFocus(function() {
- openChat(SocialSidebar.provider, function() {
- ok(window.SocialChatBar.hasChats, "first window has chats");
- window.SocialChatBar.chatbar.removeAll();
- ok(!window.SocialChatBar.hasChats, "first window has no chats");
-
- let privateWindow = OpenBrowserWindow({private: true});
- privateWindow.addEventListener("load", function loadListener() {
- privateWindow.removeEventListener("load", loadListener);
-
- // open a last chat - the focused window can't accept
- // chats (it's a private window), so the chat should open
- // in the window that was selected before. This is known
- // to be broken on Linux.
- openChat(SocialSidebar.provider, function() {
- let os = Services.appinfo.OS;
- const BROKEN_WM_Z_ORDER = os != "WINNT" && os != "Darwin";
- let fn = BROKEN_WM_Z_ORDER ? todo : ok;
- fn(window.SocialChatBar.hasChats, "first window has a chat");
- window.SocialChatBar.chatbar.removeAll();
-
- privateWindow.close();
- secondWindow.close();
- next();
- });
- });
- });
- });
- window.focus();
- });
- });
- })
- });
- },
testMultipleProviderChat: function(next) {
// test incomming chats from all providers
openChat(Social.providers[0], function() {
openChat(Social.providers[1], function() {
openChat(Social.providers[2], function() {
let chats = document.getElementById("pinnedchats");
waitForCondition(function() chats.children.length == Social.providers.length,
function() {
ok(true, "one chat window per provider opened");
// test logout of a single provider
let provider = Social.providers[2];
let port = provider.getWorkerPort();
port.postMessage({topic: "test-logout"});
waitForCondition(function() chats.children.length == Social.providers.length - 1,
function() {
- chats.removeAll();
+ closeAllChats();
waitForCondition(function() chats.children.length == 0,
function() {
ok(!chats.selectedChat, "multiprovider chats are all closed");
port.close();
next();
},
"chat windows didn't close");
},
--- a/browser/base/content/test/social/browser_social_chatwindowfocus.js
+++ b/browser/base/content/test/social/browser_social_chatwindowfocus.js
@@ -4,17 +4,17 @@
// Is the currently opened tab focused?
function isTabFocused() {
let tabb = gBrowser.getBrowserForTab(gBrowser.selectedTab);
return Services.focus.focusedWindow == tabb.contentWindow;
}
function isChatFocused(chat) {
- return SocialChatBar.chatbar._isChatFocused(chat);
+ return getChatBar()._isChatFocused(chat);
}
function openChatViaUser() {
let sidebarDoc = document.getElementById("social-sidebar-browser").contentDocument;
let button = sidebarDoc.getElementById("chat-opener");
// Note we must use synthesizeMouseAtCenter() rather than calling
// .click() directly as this causes nsIDOMWindowUtils.isHandlingUserInput
// to be true.
@@ -27,30 +27,31 @@ function openChatViaSidebarMessage(port,
callback();
}
port.postMessage({topic: "test-chatbox-open", data: data});
}
function openChatViaWorkerMessage(port, data, callback) {
// sadly there is no message coming back to tell us when the chat has
// been opened, so we wait until one appears.
- let chatbar = SocialChatBar.chatbar;
+ let chatbar = getChatBar();
let numExpected = chatbar.childElementCount + 1;
port.postMessage({topic: "test-worker-chat", data: data});
waitForCondition(function() chatbar.childElementCount == numExpected,
function() {
// so the child has been added, but we don't know if it
// has been intialized - re-request it and the callback
// means it's done. Minimized, same as the worker.
- SocialChatBar.openChat(SocialSidebar.provider,
- data,
- function() {
- callback();
- },
- "minimized");
+ chatbar.openChat(SocialSidebar.provider.origin,
+ SocialSidebar.provider.name,
+ data,
+ "minimized",
+ function() {
+ callback();
+ });
},
"No new chat appeared");
}
let isSidebarLoaded = false;
function startTestAndWaitForSidebar(callback) {
@@ -104,17 +105,17 @@ function test() {
let preSubTest = function(cb) {
// XXX - when bug 604289 is fixed it should be possible to just do:
// tab.linkedBrowser.contentWindow.focus()
// but instead we must do:
tab.linkedBrowser.contentDocument.getElementById("theinput").focus();
waitForCondition(function() isTabFocused(), cb, "tab should have focus");
}
let postSubTest = function(cb) {
- window.SocialChatBar.chatbar.removeAll();
+ closeAllChats();
cb();
}
// and run the tests.
runSocialTestWithProvider(manifest, function (finishcb) {
SocialSidebar.show();
runSocialTests(tests, preSubTest, postSubTest, function () {
finishcb();
});
@@ -127,235 +128,46 @@ function test() {
}
var tests = {
// In this test the worker asks the sidebar to open a chat. As that means
// we aren't handling user-input we will not focus the chatbar.
// Then we do it again - should still not be focused.
// Then we perform a user-initiated request - it should get focus.
testNoFocusWhenViaWorker: function(next) {
+ let chatbar = getChatBar();
startTestAndWaitForSidebar(function(port) {
openChatViaSidebarMessage(port, {stealFocus: 1}, function() {
ok(true, "got chatbox message");
- is(SocialChatBar.chatbar.childElementCount, 1, "exactly 1 chat open");
+ is(chatbar.childElementCount, 1, "exactly 1 chat open");
ok(isTabFocused(), "tab should still be focused");
// re-request the same chat via a message.
openChatViaSidebarMessage(port, {stealFocus: 1}, function() {
- is(SocialChatBar.chatbar.childElementCount, 1, "still exactly 1 chat open");
+ is(chatbar.childElementCount, 1, "still exactly 1 chat open");
ok(isTabFocused(), "tab should still be focused");
// re-request the same chat via user event.
openChatViaUser();
- waitForCondition(function() isChatFocused(SocialChatBar.chatbar.selectedChat),
+ waitForCondition(function() isChatFocused(chatbar.selectedChat),
function() {
- is(SocialChatBar.chatbar.childElementCount, 1, "still exactly 1 chat open");
- is(SocialChatBar.chatbar.selectedChat, SocialChatBar.chatbar.firstElementChild, "chat should be selected");
+ is(chatbar.childElementCount, 1, "still exactly 1 chat open");
+ is(chatbar.selectedChat, chatbar.firstElementChild, "chat should be selected");
next();
}, "chat should be focused");
});
});
});
},
// In this test we arrange for the sidebar to open the chat via a simulated
// click. This should cause the new chat to be opened and focused.
testFocusWhenViaUser: function(next) {
startTestAndWaitForSidebar(function(port) {
+ let chatbar = getChatBar();
openChatViaUser();
- ok(SocialChatBar.chatbar.firstElementChild, "chat opened");
- waitForCondition(function() isChatFocused(SocialChatBar.chatbar.selectedChat),
+ ok(chatbar.firstElementChild, "chat opened");
+ waitForCondition(function() isChatFocused(chatbar.selectedChat),
function() {
- is(SocialChatBar.chatbar.selectedChat, SocialChatBar.chatbar.firstElementChild, "chat is selected");
+ is(chatbar.selectedChat, chatbar.firstElementChild, "chat is selected");
next();
}, "chat should be focused");
});
},
-
- // Open a chat via the worker - it will open and not have focus.
- // Then open the same chat via a sidebar message - it will be restored but
- // should still not have grabbed focus.
- testNoFocusOnAutoRestore: function(next) {
- const chatUrl = "https://example.com/browser/browser/base/content/test/social/social_chat.html?id=1";
- let chatbar = SocialChatBar.chatbar;
- startTestAndWaitForSidebar(function(port) {
- openChatViaWorkerMessage(port, chatUrl, function() {
- is(chatbar.childElementCount, 1, "exactly 1 chat open");
- // bug 865086 opening minimized still sets the window as selected
- todo(chatbar.selectedChat != chatbar.firstElementChild, "chat is not selected");
- ok(isTabFocused(), "tab should be focused");
- openChatViaSidebarMessage(port, {stealFocus: 1, id: 1}, function() {
- is(chatbar.childElementCount, 1, "still 1 chat open");
- ok(!chatbar.firstElementChild.minimized, "chat no longer minimized");
- // bug 865086 because we marked it selected on open, it still is
- todo(chatbar.selectedChat != chatbar.firstElementChild, "chat is not selected");
- ok(isTabFocused(), "tab should still be focused");
- next();
- });
- });
- });
- },
-
- // Here we open a chat, which will not be focused. Then we minimize it and
- // restore it via a titlebar clock - it should get focus at that point.
- testFocusOnExplicitRestore: function(next) {
- startTestAndWaitForSidebar(function(port) {
- openChatViaSidebarMessage(port, {stealFocus: 1}, function() {
- ok(true, "got chatbox message");
- ok(isTabFocused(), "tab should still be focused");
- let chatbox = SocialChatBar.chatbar.firstElementChild;
- ok(chatbox, "chat opened");
- chatbox.minimized = true;
- ok(isTabFocused(), "tab should still be focused");
- // pretend we clicked on the titlebar
- chatbox.onTitlebarClick({button: 0});
- waitForCondition(function() isChatFocused(SocialChatBar.chatbar.selectedChat),
- function() {
- ok(!chatbox.minimized, "chat should have been restored");
- ok(isChatFocused(chatbox), "chat should be focused");
- is(chatbox, SocialChatBar.chatbar.selectedChat, "chat is marked selected");
- next();
- }, "chat should have focus");
- });
- });
- },
-
- // Open 2 chats and give 1 focus. Minimize the focused one - the second
- // should get focus.
- testMinimizeFocused: function(next) {
- let chatbar = SocialChatBar.chatbar;
- startTestAndWaitForSidebar(function(port) {
- openChatViaSidebarMessage(port, {stealFocus: 1, id: 1}, function() {
- let chat1 = chatbar.firstElementChild;
- openChatViaSidebarMessage(port, {stealFocus: 1, id: 2}, function() {
- is(chatbar.childElementCount, 2, "exactly 2 chats open");
- let chat2 = chat1.nextElementSibling || chat1.previousElementSibling;
- chatbar.selectedChat = chat1;
- chatbar.focus();
- waitForCondition(function() isChatFocused(chat1),
- function() {
- is(chat1, SocialChatBar.chatbar.selectedChat, "chat1 is marked selected");
- isnot(chat2, SocialChatBar.chatbar.selectedChat, "chat2 is not marked selected");
- chat1.minimized = true;
- waitForCondition(function() isChatFocused(chat2),
- function() {
- // minimizing the chat with focus should give it to another.
- isnot(chat1, SocialChatBar.chatbar.selectedChat, "chat1 is not marked selected");
- is(chat2, SocialChatBar.chatbar.selectedChat, "chat2 is marked selected");
- next();
- }, "chat2 should have focus");
- }, "chat1 should have focus");
- });
- });
- });
- },
-
- // Open 2 chats, select (but not focus) one, then re-request it be
- // opened via a message. Focus should not move.
- testReopenNonFocused: function(next) {
- let chatbar = SocialChatBar.chatbar;
- startTestAndWaitForSidebar(function(port) {
- openChatViaSidebarMessage(port, {id: 1}, function() {
- let chat1 = chatbar.firstElementChild;
- openChatViaSidebarMessage(port, {id: 2}, function() {
- let chat2 = chat1.nextElementSibling || chat1.previousElementSibling;
- chatbar.selectedChat = chat2;
- // tab still has focus
- ok(isTabFocused(), "tab should still be focused");
- // re-request the first.
- openChatViaSidebarMessage(port, {id: 1}, function() {
- is(chatbar.selectedChat, chat1, "chat1 now selected");
- ok(isTabFocused(), "tab should still be focused");
- next();
- });
- });
- });
- });
- },
-
- // Open 2 chats, select and focus the second. Pressing the TAB key should
- // cause focus to move between all elements in our chat window before moving
- // to the next chat window.
- testTab: function(next) {
- function sendTabAndWaitForFocus(chat, eltid, callback) {
- // ideally we would use the 'focus' event here, but that doesn't work
- // as expected for the iframe - the iframe itself never gets the focus
- // event (apparently the sub-document etc does.)
- // So just poll for the correct element getting focus...
- let doc = chat.contentDocument;
- EventUtils.sendKey("tab");
- waitForCondition(function() {
- let elt = eltid ? doc.getElementById(eltid) : doc.documentElement;
- return doc.activeElement == elt;
- }, callback, "element " + eltid + " never got focus");
- }
-
- let chatbar = SocialChatBar.chatbar;
- startTestAndWaitForSidebar(function(port) {
- openChatViaSidebarMessage(port, {id: 1}, function() {
- let chat1 = chatbar.firstElementChild;
- openChatViaSidebarMessage(port, {id: 2}, function() {
- let chat2 = chat1.nextElementSibling || chat1.previousElementSibling;
- chatbar.selectedChat = chat2;
- chatbar.focus();
- waitForCondition(function() isChatFocused(chatbar.selectedChat),
- function() {
- // Our chats have 3 focusable elements, so it takes 4 TABs to move
- // to the new chat.
- sendTabAndWaitForFocus(chat2, "input1", function() {
- is(chat2.contentDocument.activeElement.getAttribute("id"), "input1",
- "first input field has focus");
- ok(isChatFocused(chat2), "new chat still focused after first tab");
- sendTabAndWaitForFocus(chat2, "input2", function() {
- ok(isChatFocused(chat2), "new chat still focused after tab");
- is(chat2.contentDocument.activeElement.getAttribute("id"), "input2",
- "second input field has focus");
- sendTabAndWaitForFocus(chat2, "iframe", function() {
- ok(isChatFocused(chat2), "new chat still focused after tab");
- is(chat2.contentDocument.activeElement.getAttribute("id"), "iframe",
- "iframe has focus");
- // this tab now should move to the next chat, but focus the
- // document element itself (hence the null eltid)
- sendTabAndWaitForFocus(chat1, null, function() {
- ok(isChatFocused(chat1), "first chat is focused");
- next();
- });
- });
- });
- });
- }, "chat should have focus");
- });
- });
- });
- },
-
- // Open a chat and focus an element other than the first. Move focus to some
- // other item (the tab itself in this case), then focus the chatbar - the
- // same element that was previously focused should still have focus.
- testFocusedElement: function(next) {
- let chatbar = SocialChatBar.chatbar;
- startTestAndWaitForSidebar(function(port) {
- openChatViaUser();
- let chat = chatbar.firstElementChild;
- // need to wait for the content to load before we can focus it.
- chat.addEventListener("DOMContentLoaded", function DOMContentLoaded() {
- chat.removeEventListener("DOMContentLoaded", DOMContentLoaded);
- chat.contentDocument.getElementById("input2").focus();
- waitForCondition(function() isChatFocused(chat),
- function() {
- is(chat.contentDocument.activeElement.getAttribute("id"), "input2",
- "correct input field has focus");
- // set focus to the tab.
- let tabb = gBrowser.getBrowserForTab(gBrowser.selectedTab);
- Services.focus.moveFocus(tabb.contentWindow, null, Services.focus.MOVEFOCUS_ROOT, 0);
- waitForCondition(function() isTabFocused(),
- function() {
- chatbar.focus();
- waitForCondition(function() isChatFocused(chat),
- function() {
- is(chat.contentDocument.activeElement.getAttribute("id"), "input2",
- "correct input field still has focus");
- next();
- }, "chat took focus");
- }, "tab has focus");
- }, "chat took focus");
- });
- });
- },
};
--- a/browser/base/content/test/social/browser_social_errorPage.js
+++ b/browser/base/content/test/social/browser_social_errorPage.js
@@ -4,16 +4,18 @@
function gc() {
Cu.forceGC();
let wu = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
wu.garbageCollect();
}
+let openChatWindow = Cu.import("resource://gre/modules/MozSocialAPI.jsm", {}).openChatWindow;
+
// Support for going on and offline.
// (via browser/base/content/test/browser_bookmark_titles.js)
let origProxyType = Services.prefs.getIntPref('network.proxy.type');
function goOffline() {
// Simulate a network outage with offline mode. (Localhost is still
// accessible in offline mode, so disable the test proxy as well.)
if (!Services.io.offline)
@@ -37,19 +39,20 @@ function openPanel(url, panelCallback, l
SocialFlyout.panel.firstChild.addEventListener("load", function panelLoad() {
SocialFlyout.panel.firstChild.removeEventListener("load", panelLoad, true);
loadCallback();
}, true);
}
function openChat(url, panelCallback, loadCallback) {
// open a chat window
- SocialChatBar.openChat(SocialSidebar.provider, url, panelCallback);
- SocialChatBar.chatbar.firstChild.addEventListener("DOMContentLoaded", function panelLoad() {
- SocialChatBar.chatbar.firstChild.removeEventListener("DOMContentLoaded", panelLoad, true);
+ let chatbar = getChatBar();
+ openChatWindow(null, SocialSidebar.provider, url, panelCallback);
+ chatbar.firstChild.addEventListener("DOMContentLoaded", function panelLoad() {
+ chatbar.firstChild.removeEventListener("DOMContentLoaded", panelLoad, true);
loadCallback();
}, true);
}
function onSidebarLoad(callback) {
let sbrowser = document.getElementById("social-sidebar-browser");
sbrowser.addEventListener("load", function load() {
sbrowser.removeEventListener("load", load, true);
@@ -149,30 +152,61 @@ var tests = {
);
});
}
);
},
testChatWindow: function(next) {
let panelCallbackCount = 0;
- // go offline and open a flyout.
+ // go offline and open a chat.
goOffline();
openChat(
"https://example.com/browser/browser/base/content/test/social/social_chat.html",
function() { // the panel api callback
panelCallbackCount++;
},
function() { // the "load" callback.
executeSoon(function() {
todo_is(panelCallbackCount, 0, "Bug 833207 - should be no callback when error page loads.");
- let chat = SocialChatBar.chatbar.selectedChat;
+ let chat = getChatBar().selectedChat;
waitForCondition(function() chat.contentDocument.location.href.indexOf("about:socialerror?")==0,
function() {
chat.close();
next();
},
"error page didn't appear");
});
}
);
+ },
+
+ testChatWindowAfterTearOff: function(next) {
+ // Ensure that the error listener survives the chat window being detached.
+ let url = "https://example.com/browser/browser/base/content/test/social/social_chat.html";
+ let panelCallbackCount = 0;
+ // open a chat while we are still online.
+ openChat(
+ url,
+ null,
+ function() { // the "load" callback.
+ executeSoon(function() {
+ let chat = getChatBar().selectedChat;
+ is(chat.contentDocument.location.href, url, "correct url loaded");
+ // toggle to a detached window.
+ chat.swapWindows().then(
+ chat => {
+ // now go offline and reload the chat - about:socialerror should be loaded.
+ goOffline();
+ chat.contentDocument.location.reload();
+ waitForCondition(function() chat.contentDocument.location.href.indexOf("about:socialerror?")==0,
+ function() {
+ chat.close();
+ next();
+ },
+ "error page didn't appear");
+ }
+ );
+ });
+ }
+ );
}
}
--- a/browser/base/content/test/social/head.js
+++ b/browser/base/content/test/social/head.js
@@ -232,18 +232,16 @@ function checkSocialUI(win) {
is(a, b, msg)
else
++numGoodTests;
}
function isbool(a, b, msg) {
_is(!!a, !!b, msg);
}
isbool(win.SocialSidebar.canShow, sidebarEnabled, "social sidebar active?");
- isbool(win.SocialChatBar.isAvailable, enabled, "chatbar available?");
- isbool(!win.SocialChatBar.chatbar.hidden, enabled, "chatbar visible?");
let contextMenus = [
{
type: "link",
id: "context-marklinkMenu",
label: "social.marklinkMenu.label"
},
{
@@ -274,18 +272,16 @@ function checkSocialUI(win) {
}
for (let m of menus)
_is(m.parentNode, parent, "menu has correct parent");
}
// and for good measure, check all the social commands.
isbool(!doc.getElementById("Social:ToggleSidebar").hidden, sidebarEnabled, "Social:ToggleSidebar visible?");
isbool(!doc.getElementById("Social:ToggleNotifications").hidden, enabled, "Social:ToggleNotifications visible?");
- isbool(!doc.getElementById("Social:FocusChat").hidden, enabled, "Social:FocusChat visible?");
- isbool(doc.getElementById("Social:FocusChat").getAttribute("disabled"), enabled ? "false" : "true", "Social:FocusChat disabled?");
// and report on overall success of failure of the various checks here.
is(numGoodTests, numTests, "The Social UI tests succeeded.")
}
function waitForNotification(topic, cb) {
function observer(subject, topic, data) {
Services.obs.removeObserver(observer, topic);
@@ -398,17 +394,17 @@ function loadIntoTab(tab, url, callback)
function get3ChatsForCollapsing(mode, cb) {
// We make one chat, then measure its size. We then resize the browser to
// ensure a second can be created fully visible but a third can not - then
// create the other 2. first will will be collapsed, second fully visible
// and the third also visible and the "selected" one.
// To make our life easier we don't go via the worker and ports so we get
// more control over creation *and* to make the code much simpler. We
// assume the worker/port stuff is individually tested above.
- let chatbar = window.SocialChatBar.chatbar;
+ let chatbar = getChatBar();
let chatWidth = undefined;
let num = 0;
is(chatbar.childNodes.length, 0, "chatbar starting empty");
is(chatbar.menupopup.childNodes.length, 0, "popup starting empty");
makeChat(mode, "first chat", function() {
// got the first one.
checkPopup();
@@ -442,33 +438,31 @@ function get3ChatsForCollapsing(mode, cb
});
}, mode);
}
function makeChat(mode, uniqueid, cb) {
info("making a chat window '" + uniqueid +"'");
let provider = SocialSidebar.provider;
const chatUrl = provider.origin + "/browser/browser/base/content/test/social/social_chat.html";
- let isOpened = window.SocialChatBar.openChat(provider, chatUrl + "?id=" + uniqueid, function(chat) {
+ // Note that we use promiseChatLoaded instead of the callback to ensure the
+ // content has started loading.
+ let chatbox = getChatBar().openChat(provider.origin, provider.name,
+ chatUrl + "?id=" + uniqueid, mode);
+ chatbox.promiseChatLoaded.then(
+ () => {
info("chat window has opened");
- // we can't callback immediately or we might close the chat during
- // this event which upsets the implementation - it is only 1/2 way through
- // handling the load event.
- chat.document.title = uniqueid;
- executeSoon(cb);
- }, mode);
- if (!isOpened) {
- ok(false, "unable to open chat window, no provider? more failures to come");
- executeSoon(cb);
- }
+ chatbox.contentDocument.title = uniqueid;
+ cb();
+ });
}
function checkPopup() {
// popup only showing if any collapsed popup children.
- let chatbar = window.SocialChatBar.chatbar;
+ let chatbar = getChatBar();
let numCollapsed = 0;
for (let chat of chatbar.childNodes) {
if (chat.collapsed) {
numCollapsed += 1;
// and it have a menuitem weakmap
is(chatbar.menuitemMap.get(chat).nodeName, "menuitem", "collapsed chat has a menu item");
} else {
ok(!chatbar.menuitemMap.has(chat), "open chat has no menu item");
@@ -477,17 +471,17 @@ function checkPopup() {
is(chatbar.menupopup.parentNode.collapsed, numCollapsed == 0, "popup matches child collapsed state");
is(chatbar.menupopup.childNodes.length, numCollapsed, "popup has correct count of children");
// todo - check each individual elt is what we expect?
}
// Resize the main window so the chat area's boxObject is |desired| wide.
// Does a callback passing |true| if the window is now big enough or false
// if we couldn't resize large enough to satisfy the test requirement.
function resizeWindowToChatAreaWidth(desired, cb, count = 0) {
- let current = window.SocialChatBar.chatbar.getBoundingClientRect().width;
+ let current = getChatBar().getBoundingClientRect().width;
let delta = desired - current;
info(count + ": resizing window so chat area is " + desired + " wide, currently it is "
+ current + ". Screen avail is " + window.screen.availWidth
+ ", current outer width is " + window.outerWidth);
// WTF? Sometimes we will get fractional values due to the - err - magic
// of DevPointsPerCSSPixel etc, so we allow a couple of pixels difference.
let widthDeltaCloseEnough = function(d) {
@@ -510,17 +504,17 @@ function resizeWindowToChatAreaWidth(des
info(count + ": skipping this as screen available width is less than necessary");
executeSoon(function() {
cb(false);
});
return;
}
function resize_handler(event) {
// we did resize - but did we get far enough to be able to continue?
- let newSize = window.SocialChatBar.chatbar.getBoundingClientRect().width;
+ let newSize = getChatBar().getBoundingClientRect().width;
let sizedOk = widthDeltaCloseEnough(newSize - desired);
if (!sizedOk)
return;
window.removeEventListener("resize", resize_handler, true);
info(count + ": resized window width is " + newSize);
executeSoon(function() {
cb(sizedOk);
});
@@ -558,20 +552,27 @@ function resizeAndCheckWidths(first, sec
let m = new MutationObserver(collapsedObserver);
m.observe(first, {attributes: true });
m.observe(second, {attributes: true });
m.observe(third, {attributes: true });
}
}, count);
}
+function getChatBar() {
+ return document.getElementById("pinnedchats");
+}
+
function getPopupWidth() {
- let popup = window.SocialChatBar.chatbar.menupopup;
+ let chatbar = getChatBar();
+ let popup = chatbar.menupopup;
ok(!popup.parentNode.collapsed, "asking for popup width when it is visible");
let cs = document.defaultView.getComputedStyle(popup.parentNode);
let margins = parseInt(cs.marginLeft) + parseInt(cs.marginRight);
return popup.parentNode.getBoundingClientRect().width + margins;
}
function closeAllChats() {
- let chatbar = window.SocialChatBar.chatbar;
- chatbar.removeAll();
+ let chatbar = getChatBar();
+ while (chatbar.selectedChat) {
+ chatbar.selectedChat.close();
+ }
}
--- a/browser/base/moz.build
+++ b/browser/base/moz.build
@@ -8,16 +8,17 @@ MOCHITEST_MANIFESTS += [
'content/test/general/mochitest.ini',
]
MOCHITEST_CHROME_MANIFESTS += [
'content/test/chrome/chrome.ini',
]
BROWSER_CHROME_MANIFESTS += [
+ 'content/test/chat/browser.ini',
'content/test/general/browser.ini',
'content/test/newtab/browser.ini',
'content/test/plugins/browser.ini',
'content/test/social/browser.ini',
]
DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION']
DEFINES['APP_LICENSE_BLOCK'] = '%s/content/overrides/app-license.html' % SRCDIR
--- a/browser/devtools/webaudioeditor/test/browser.ini
+++ b/browser/devtools/webaudioeditor/test/browser.ini
@@ -11,15 +11,15 @@ support-files =
[browser_audionode-actor-get-type.js]
[browser_audionode-actor-get-params.js]
[browser_audionode-actor-get-param-flags.js]
[browser_audionode-actor-is-source.js]
[browser_webaudio-actor-simple.js]
[browser_wa_first-run.js]
-[browser_wa_graph_mouseover.js]
+[browser_wa_graph_click.js]
[browser_wa_graph_render_01.js]
[browser_wa_graph_render_02.js]
[browser_wa_params_view_edit.js]
[browser_wa_params_view_events.js]
[browser_wa_params_view_mouseover.js]
--- a/browser/devtools/webaudioeditor/test/browser_audionode-actor-get-set-param.js
+++ b/browser/devtools/webaudioeditor/test/browser_audionode-actor-get-set-param.js
@@ -27,20 +27,16 @@ function spawnTest () {
ise(freq, 220, "AudioNode:setParam correctly sets a `number` AudioParam");
is(resSuccess, undefined, "AudioNode:setParam returns undefined for correctly set AudioParam");
resSuccess = yield oscNode.setParam("type", "square");
let type = yield oscNode.getParam("type");
ise(type, "square", "AudioNode:setParam correctly sets a `string` non-AudioParam");
is(resSuccess, undefined, "AudioNode:setParam returns undefined for correctly set AudioParam");
- resSuccess = yield oscNode.setParam("type", "\"triangle\"");
- type = yield oscNode.getParam("type");
- ise(type, "triangle", "AudioNode:setParam correctly removes quotes in `string` non-AudioParam");
-
try {
yield oscNode.setParam("frequency", "hello");
ok(false, "setParam with invalid types should throw");
} catch (e) {
ok(/is not a finite floating-point/.test(e.message), "AudioNode:setParam returns error with correct message when attempting an invalid assignment");
is(e.type, "TypeError", "AudioNode:setParam returns error with correct type when attempting an invalid assignment");
freq = yield oscNode.getParam("frequency");
ise(freq, 220, "AudioNode:setParam does not modify value when an error occurs");
new file mode 100644
--- /dev/null
+++ b/browser/devtools/webaudioeditor/test/browser_wa_graph_click.js
@@ -0,0 +1,58 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Tests that the ParamsList view opens the correct node when clicking
+ * on the node in the GraphView
+ */
+
+function spawnTest() {
+ let [target, debuggee, panel] = yield initWebAudioEditor(COMPLEX_CONTEXT_URL);
+ let panelWin = panel.panelWin;
+ let { gFront, $, $$, EVENTS, WebAudioParamView } = panelWin;
+ let gVars = WebAudioParamView._paramsView;
+
+ let started = once(gFront, "start-context");
+
+ reload(target);
+
+ let [_, nodes, _] = yield Promise.all([
+ getN(gFront, "create-node", 8),
+ getNSpread(panel.panelWin, EVENTS.UI_ADD_NODE_LIST, 8),
+ waitForGraphRendered(panel.panelWin, 8, 8)
+ ]);
+
+ let nodeIds = nodes.map(([e, id]) => id);
+
+ for (let i = 0; i < 8; i++) {
+ ok(!isExpanded(gVars, i), "no views expanded on default");
+ }
+
+ click(panel.panelWin, findGraphNode(panelWin, nodeIds[1]));
+ ok(isExpanded(gVars, 1), "params view expanded on click");
+
+ var allClosed = true;
+ for (let i = 0; i < 8; i++) {
+ if (i === 1) continue;
+ if (isExpanded(gVars, i))
+ allClosed = false;
+ }
+ ok(allClosed, "all other param views are still minimized");
+
+ click(panel.panelWin, findGraphNode(panelWin, nodeIds[2]));
+ ok(isExpanded(gVars, 2), "second params view expanded on click");
+
+ click(panel.panelWin, $("rect", findGraphNode(panelWin, nodeIds[3])));
+ ok(isExpanded(gVars, 3), "param view opens when clicking `<rect>`");
+
+ click(panel.panelWin, $("tspan", findGraphNode(panelWin, nodeIds[4])));
+ ok(isExpanded(gVars, 4), "param view opens when clicking `<tspan>`");
+
+ yield teardown(panel);
+ finish();
+}
+
+function isExpanded (view, index) {
+ let scope = view.getScopeAtIndex(index);
+ return scope.expanded;
+}
deleted file mode 100644
--- a/browser/devtools/webaudioeditor/test/browser_wa_graph_mouseover.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/**
- * Tests if the shader editor shows the appropriate UI when opened.
- */
-
-function spawnTest() {
- let [target, debuggee, panel] = yield initWebAudioEditor(COMPLEX_CONTEXT_URL);
- let { gFront, $, $$, EVENTS, WebAudioParamView } = panel.panelWin;
- let gVars = WebAudioParamView._paramsView;
-
- let started = once(gFront, "start-context");
-
- reload(target);
-
- yield Promise.all([
- getN(gFront, "create-node", 8),
- getNSpread(panel.panelWin, EVENTS.UI_ADD_NODE_LIST, 8),
- waitForGraphRendered(panel.panelWin, 8, 8)
- ]);
-
- let $items = $$(".variables-view-scope");
- let $graphNodes = $$(".nodes > g");
-
- for (let $item of $items) {
- mouseOver(panel.panelWin, $(".devtools-toolbar", $item));
- // Get actorID from id of variable scope
- let id = $item.id.match(/\(([^\)]*)\)/)[1];
-
- // Go over all graph nodes and check only the selected one is highlighted
- for (let $node of $graphNodes) {
- let shouldBeSelected = id === $node.getAttribute("data-id");
- ok($node.classList.contains("selected") === shouldBeSelected,
- "graph node correctly " + (shouldBeSelected ? "" : "not ") + "highlighted on param view mouseover");
- }
- }
-
- yield teardown(panel);
- finish();
-}
-
--- a/browser/devtools/webaudioeditor/test/browser_wa_params_view_edit.js
+++ b/browser/devtools/webaudioeditor/test/browser_wa_params_view_edit.js
@@ -14,29 +14,37 @@ function spawnTest() {
reload(target);
let [[dest, osc, gain], [[_, destID], [_, oscID], [_, gainID]]] = yield Promise.all([
get3(gFront, "create-node"),
get3Spread(panel.panelWin, EVENTS.UI_ADD_NODE_LIST)
]);
+ let setAndCheck = setAndCheckVariable(panel.panelWin, gVars);
checkVariableView(gVars, 1, {
"type": "\"sine\"",
"frequency": 440,
"detune": 0
- });
+ }, "default loaded string");
checkVariableView(gVars, 2, {
"gain": 0
- });
-
- yield modifyVariableView(panel.panelWin, gVars, 1, "type", "square");
+ }, "default loaded number");
- checkVariableView(gVars, 1, {
- "type": "\"square\""
- });
+ yield setAndCheck(1, "type", "\"square\"", "\"square\"", "sets string as string");
+
+ yield setAndCheck(2, "gain", 0.005, 0.005, "sets number as number");
yield teardown(panel);
finish();
}
+function setAndCheckVariable (panelWin, gVars) {
+ return Task.async(function (varNum, prop, value, expected, desc) {
+ yield modifyVariableView(panelWin, gVars, varNum, prop, value);
+ var props = {};
+ props[prop] = expected;
+ checkVariableView(gVars, varNum, props, desc);
+ });
+}
+
--- a/browser/devtools/webaudioeditor/test/head.js
+++ b/browser/devtools/webaudioeditor/test/head.js
@@ -206,25 +206,25 @@ function waitForGraphRendered (front, no
if (nodes === nodeCount && edges === edgeCount) {
front.off(eventName, onGraphRendered);
deferred.resolve();
}
});
return deferred.promise;
}
-function checkVariableView (view, index, hash) {
+function checkVariableView (view, index, hash, description = "") {
let scope = view.getScopeAtIndex(index);
let variables = Object.keys(hash);
variables.forEach(variable => {
let aVar = scope.get(variable);
is(aVar.target.querySelector(".name").getAttribute("value"), variable,
"Correct property name for " + variable);
is(aVar.target.querySelector(".value").getAttribute("value"), hash[variable],
- "Correct property value of " + hash[variable] + " for " + variable);
+ "Correct property value of " + hash[variable] + " for " + variable + " " + description);
});
}
function modifyVariableView (win, view, index, prop, value) {
let deferred = Promise.defer();
let scope = view.getScopeAtIndex(index);
let aVar = scope.get(prop);
scope.expand();
--- a/browser/devtools/webaudioeditor/webaudioeditor-view.js
+++ b/browser/devtools/webaudioeditor/webaudioeditor-view.js
@@ -35,25 +35,27 @@ const GENERIC_VARIABLES_VIEW_SETTINGS =
*/
let WebAudioGraphView = {
/**
* Initialization function, called when the tool is started.
*/
initialize: function() {
this._onGraphNodeClick = this._onGraphNodeClick.bind(this);
this.draw = debounce(this.draw.bind(this), GRAPH_DEBOUNCE_TIMER);
+ $('#graph-target').addEventListener('click', this._onGraphNodeClick, false);
},
/**
* Destruction function, called when the tool is closed.
*/
destroy: function() {
if (this._zoomBinding) {
this._zoomBinding.on("zoom", null);
}
+ $('#graph-target').removeEventListener('click', this._onGraphNodeClick, false);
},
/**
* Called when a page is reloaded and waiting for a "start-context" event
* and clears out old content
*/
resetUI: function () {
$("#reload-notice").hidden = true;
@@ -135,17 +137,17 @@ let WebAudioGraphView = {
let renderer = new dagreD3.Renderer();
// Post-render manipulation of the nodes
let oldDrawNodes = renderer.drawNodes();
renderer.drawNodes(function(graph, root) {
let svgNodes = oldDrawNodes(graph, root);
svgNodes.attr("class", (n) => {
let node = graph.node(n);
- return "type-" + node.label;
+ return "audionode type-" + node.label;
});
svgNodes.attr("data-id", (n) => {
let node = graph.node(n);
return node.id;
});
return svgNodes;
});
@@ -209,22 +211,26 @@ let WebAudioGraphView = {
/**
* Event handlers
*/
/**
* Fired when a node in the svg graph is clicked. Used to handle triggering the AudioNodePane.
*
- * @param Object AudioNodeView
- * The object stored in `AudioNodes` which contains render information, but most importantly,
- * the actorID under `id` property.
+ * @param Event e
+ * Click event.
*/
- _onGraphNodeClick: function (node) {
- WebAudioParamView.focusNode(node.id);
+ _onGraphNodeClick: function (e) {
+ let node = findGraphNodeParent(e.target);
+ // If node not found (clicking outside of an audio node in the graph),
+ // then ignore this event
+ if (!node)
+ return;
+ WebAudioParamView.focusNode(node.getAttribute('data-id'));
}
};
let WebAudioParamView = {
_paramsView: null,
/**
* Initialization function called when the tool starts up.
@@ -264,22 +270,31 @@ let WebAudioParamView = {
/**
* Executed when an audio param is changed in the UI.
*/
_onEval: Task.async(function* (variable, value) {
let ownerScope = variable.ownerView;
let node = getViewNodeById(ownerScope.actorID);
let propName = variable.name;
- let errorMessage = yield node.actor.setParam(propName, value);
+ let error;
+
+ // Cast value to proper type
+ try {
+ value = JSON.parse(value);
+ error = yield node.actor.setParam(propName, value);
+ }
+ catch (e) {
+ error = e;
+ }
// TODO figure out how to handle and display set param errors
// and enable `test/brorwser_wa_params_view_edit_error.js`
// Bug 994258
- if (!errorMessage) {
+ if (!error) {
ownerScope.get(propName).setGrip(value);
window.emit(EVENTS.UI_SET_PARAM, node.id, propName, value);
} else {
window.emit(EVENTS.UI_SET_PARAM_ERROR, node.id, propName, value);
}
}),
/**
@@ -356,8 +371,24 @@ let WebAudioParamView = {
/**
* Called when `DESTROY_NODE` is fired to remove the node from params view.
* TODO bug 994263, dependent on node GC events
*/
removeNode: Task.async(function* (viewNode) {
})
};
+
+/**
+ * Takes an element in an SVG graph and iterates over
+ * ancestors until it finds the graph node container. If not found,
+ * returns null.
+ */
+
+function findGraphNodeParent (el) {
+ while (!el.classList.contains("nodes")) {
+ if (el.classList.contains("audionode"))
+ return el;
+ else
+ el = el.parentNode;
+ }
+ return null;
+}
--- a/browser/devtools/webconsole/test/browser_webconsole_output_04.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_output_04.js
@@ -45,17 +45,17 @@ let inputTests = [
inspectable: true,
variablesViewLabel: "TypeError",
},
// 4
{
input: "testDOMException()",
output: 'DOMException [SyntaxError: "An invalid or illegal string was specified"',
- printOutput: '[Exception... "An invalid or illegal string was specified"',
+ printOutput: '[object XrayWrapper [object DOMException]]"',
inspectable: true,
variablesViewLabel: "SyntaxError",
},
// 5
{
input: "testCSSStyleDeclaration()",
output: 'CSS2Properties { color: "green", font-size: "2em" }',
--- a/browser/experiments/Experiments.jsm
+++ b/browser/experiments/Experiments.jsm
@@ -1160,17 +1160,21 @@ Experiments.Experiments.prototype = {
gPrefs.set(PREF_ACTIVE_EXPERIMENT, activeExperiment != null);
if (activeChanged) {
Services.obs.notifyObservers(null, EXPERIMENTS_CHANGED_TOPIC, null);
}
if ("@mozilla.org/toolkit/crash-reporter;1" in Cc && activeExperiment) {
- gCrashReporter.annotateCrashReport("ActiveExperiment", activeExperiment.id);
+ try {
+ gCrashReporter.annotateCrashReport("ActiveExperiment", activeExperiment.id);
+ } catch (e) {
+ // It's ok if crash reporting is disabled.
+ }
}
},
/*
* Schedule the soonest re-check of experiment applicability that is needed.
*/
_scheduleNextRun: function () {
this._checkForShutdown();
new file mode 100644
--- /dev/null
+++ b/browser/modules/Chat.jsm
@@ -0,0 +1,191 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+// A module for working with chat windows.
+
+this.EXPORTED_SYMBOLS = ["Chat"];
+
+const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
+ "resource://gre/modules/PrivateBrowsingUtils.jsm");
+
+// A couple of internal helper function.
+function isWindowChromeless(win) {
+ // XXX - stolen from browser-social.js, but there's no obvious place to
+ // put this so it can be shared.
+
+ // Is this a popup window that doesn't want chrome shown?
+ let docElem = win.document.documentElement;
+ // extrachrome is not restored during session restore, so we need
+ // to check for the toolbar as well.
+ let chromeless = docElem.getAttribute("chromehidden").contains("extrachrome") ||
+ docElem.getAttribute('chromehidden').contains("toolbar");
+ return chromeless;
+}
+
+function isWindowGoodForChats(win) {
+ return !win.closed &&
+ !!win.document.getElementById("pinnedchats") &&
+ !isWindowChromeless(win) &&
+ !PrivateBrowsingUtils.isWindowPrivate(win);
+}
+
+function getChromeWindow(contentWin) {
+ return contentWin.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIDocShellTreeItem)
+ .rootTreeItem
+ .QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindow);
+}
+
+/*
+ * The exported Chat object
+ */
+
+let Chat = {
+ /**
+ * Open a new chatbox.
+ *
+ * @param contentWindow [optional]
+ * The content window that requested this chat. May be null.
+ * @param origin
+ * The origin for the chat. This is primarily used as an identifier
+ * to help identify all chats from the same provider.
+ * @param title
+ * The title to be used if a new chat window is created.
+ * @param url
+ * The URL for the that. Should be under the origin. If an existing
+ * chatbox exists with the same URL, it will be reused and returned.
+ * @param mode [optional]
+ * May be undefined or 'minimized'
+ * @param focus [optional]
+ * Indicates if the chatbox should be focused. If undefined the chat
+ * will be focused if the window is currently handling user input (ie,
+ * if the chat is being opened as a direct result of user input)
+
+ * @return A chatbox binding. This binding has a number of promises which
+ * can be used to determine when the chatbox is being created and
+ * has loaded. Will return null if no chat can be created (Which
+ * should only happen in edge-cases)
+ */
+ open: function(contentWindow, origin, title, url, mode, focus, callback) {
+ let chromeWindow = this.findChromeWindowForChats(contentWindow);
+ if (!chromeWindow) {
+ Cu.reportError("Failed to open a chat window - no host window could be found.");
+ return null;
+ }
+
+ let chatbar = chromeWindow.document.getElementById("pinnedchats");
+ chatbar.hidden = false;
+ let chatbox = chatbar.openChat(origin, title, url, mode, callback);
+ // getAttention is ignored if the target window is already foreground, so
+ // we can call it unconditionally.
+ chromeWindow.getAttention();
+ // If focus is undefined we want automatic focus handling, and only focus
+ // if a direct result of user action.
+ if (focus === undefined) {
+ let dwu = chromeWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindowUtils);
+ focus = dwu.isHandlingUserInput;
+ }
+ if (focus) {
+ chatbar.focus();
+ }
+ return chatbox;
+ },
+
+ /**
+ * Close all chats from the specified origin.
+ *
+ * @param origin
+ * The origin from which all chats should be closed.
+ */
+ closeAll: function(origin) {
+ // close all attached chat windows
+ let winEnum = Services.wm.getEnumerator("navigator:browser");
+ while (winEnum.hasMoreElements()) {
+ let win = winEnum.getNext();
+ let chatbar = win.document.getElementById("pinnedchats");
+ if (!chatbar)
+ continue;
+ let chats = [c for (c of chatbar.children) if (c.content.getAttribute("origin") == origin)];
+ [c.close() for (c of chats)];
+ }
+
+ // close all standalone chat windows
+ winEnum = Services.wm.getEnumerator("Social:Chat");
+ while (winEnum.hasMoreElements()) {
+ let win = winEnum.getNext();
+ if (win.closed)
+ continue;
+ let chatOrigin = win.document.getElementById("chatter").content.getAttribute("origin");
+ if (origin == chatOrigin)
+ win.close();
+ }
+ },
+
+ /**
+ * Focus the chatbar associated with a window
+ *
+ * @param window
+ */
+ focus: function(win) {
+ let chatbar = win.document.getElementById("pinnedchats");
+ if (chatbar && !chatbar.hidden) {
+ chatbar.focus();
+ }
+
+ },
+
+ // This is exported as socialchat.xml needs to find a window when a chat
+ // is re-docked.
+ findChromeWindowForChats: function(preferredWindow) {
+ if (preferredWindow) {
+ preferredWindow = getChromeWindow(preferredWindow);
+ if (isWindowGoodForChats(preferredWindow)) {
+ return preferredWindow;
+ }
+ }
+ // no good - we just use the "most recent" browser window which can host
+ // chats (we used to try and "group" all chats in the same browser window,
+ // but that didn't work out so well - see bug 835111
+
+ // Try first the most recent window as getMostRecentWindow works
+ // even on platforms where getZOrderDOMWindowEnumerator is broken
+ // (ie. Linux). This will handle most cases, but won't work if the
+ // foreground window is a popup.
+
+ let mostRecent = Services.wm.getMostRecentWindow("navigator:browser");
+ if (isWindowGoodForChats(mostRecent))
+ return mostRecent;
+
+ let topMost, enumerator;
+ // *sigh* - getZOrderDOMWindowEnumerator is broken except on Mac and
+ // Windows. We use BROKEN_WM_Z_ORDER as that is what some other code uses
+ // and a few bugs recommend searching mxr for this symbol to identify the
+ // workarounds - we want this code to be hit in such searches.
+ let os = Services.appinfo.OS;
+ const BROKEN_WM_Z_ORDER = os != "WINNT" && os != "Darwin";
+ if (BROKEN_WM_Z_ORDER) {
+ // this is oldest to newest and no way to change the order.
+ enumerator = Services.wm.getEnumerator("navigator:browser");
+ } else {
+ // here we explicitly ask for bottom-to-top so we can use the same logic
+ // where BROKEN_WM_Z_ORDER is true.
+ enumerator = Services.wm.getZOrderDOMWindowEnumerator("navigator:browser", false);
+ }
+ while (enumerator.hasMoreElements()) {
+ let win = enumerator.getNext();
+ if (!win.closed && isWindowGoodForChats(win))
+ topMost = win;
+ }
+ return topMost;
+ },
+}
--- a/browser/modules/moz.build
+++ b/browser/modules/moz.build
@@ -4,16 +4,17 @@
# 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/.
TEST_DIRS += ['test']
EXTRA_JS_MODULES += [
'BrowserNewTabPreloader.jsm',
'BrowserUITelemetry.jsm',
+ 'Chat.jsm',
'ContentClick.jsm',
'ContentLinkHandler.jsm',
'ContentSearch.jsm',
'CustomizationTabPreloader.jsm',
'Feeds.jsm',
'NetworkPrioritizer.jsm',
'offlineAppCache.jsm',
'RemotePrompt.jsm',
--- a/build/mozconfig.cache
+++ b/build/mozconfig.cache
@@ -39,18 +39,19 @@ if test -z "$bucket"; then
else
mk_add_options "export SCCACHE_BUCKET=$bucket"
case "$master" in
*use1.mozilla.com*|*usw2.mozilla.com*)
mk_add_options "export SCCACHE_NAMESERVER=169.254.169.253"
;;
esac
ac_add_options "--with-compiler-wrapper=python2.7 $topsrcdir/sccache/sccache.py"
- mk_add_options MOZ_PREFLIGHT+=build/sccache.mk
- mk_add_options MOZ_POSTFLIGHT+=build/sccache.mk
+ mk_add_options MOZ_PREFLIGHT_ALL+=build/sccache.mk
+ mk_add_options MOZ_POSTFLIGHT_ALL+=build/sccache.mk
+ UPLOAD_EXTRA_FILES="sccache.log.gz"
case "$platform" in
win*)
# sccache supports a special flag to create depfiles.
export _DEPEND_CFLAGS='-deps$(MDDEPDIR)/$(@F).pp'
# Windows builds have a default wrapper that needs to be overridden
mk_add_options "export CC_WRAPPER="
mk_add_options "export CXX_WRAPPER="
# For now, sccache doesn't support separate PDBs so force debug info to be
--- a/build/sccache.mk
+++ b/build/sccache.mk
@@ -1,7 +1,18 @@
-preflight:
+# 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/.
+
+ifdef OBJDIR
+BASE_DIR = $(OBJDIR)
+else
+# OSX Universal builds only do upload in the first MOZ_BUILD_PROJECTS
+BASE_DIR = $(MOZ_OBJDIR)/$(firstword $(MOZ_BUILD_PROJECTS))
+endif
+
+preflight_all:
# Terminate any sccache server that might still be around
-python2.7 $(TOPSRCDIR)/sccache/sccache.py > /dev/null 2>&1
-postflight:
+postflight_all:
# Terminate sccache server. This prints sccache stats.
- -python2.7 $(TOPSRCDIR)/sccache/sccache.py
+ -python2.7 $(TOPSRCDIR)/sccache/sccache.py 2>&1 | gzip > $(BASE_DIR)/dist/sccache.log.gz
--- a/caps/idl/nsIScriptSecurityManager.idl
+++ b/caps/idl/nsIScriptSecurityManager.idl
@@ -6,17 +6,17 @@
#include "nsISupports.idl"
#include "nsIPrincipal.idl"
#include "nsIXPCSecurityManager.idl"
interface nsIURI;
interface nsIChannel;
interface nsIDocShell;
interface nsIDomainPolicy;
-[scriptable, uuid(4c087cc3-e0cc-4ec3-88df-8d68f3023b45)]
+[scriptable, uuid(2565769a-eaec-47a1-a076-605f5294d286)]
interface nsIScriptSecurityManager : nsIXPCSecurityManager
{
/**
* Check that the script currently running in context "cx" can load "uri".
*
* Will return error code NS_ERROR_DOM_BAD_URI if the load request
* should be denied.
*
@@ -94,22 +94,16 @@ interface nsIScriptSecurityManager : nsI
in unsigned long flags);
/**
* Return true if scripts may be executed in the scope of the given global.
*/
[noscript,notxpcom] boolean scriptAllowed(in JSObjectPtr aGlobal);
///////////////// Principals ///////////////////////
- /**
- * Return the principal of the innermost frame of the currently
- * executing script. Will return null if there is no script
- * currently executing.
- */
- [noscript] nsIPrincipal getSubjectPrincipal();
/**
* Return the all-powerful system principal.
*/
nsIPrincipal getSystemPrincipal();
/**
* Return a principal that has the same origin as aURI.
@@ -146,22 +140,16 @@ interface nsIScriptSecurityManager : nsI
/**
* Legacy name for getNoAppCodebasePrincipal.
*
* @deprecated use getNoAppCodebasePrincipal instead.
*/
[deprecated] nsIPrincipal getCodebasePrincipal(in nsIURI uri);
/**
- * Returns true if the principal of the currently running script is the
- * system principal, false otherwise.
- */
- [noscript] boolean subjectPrincipalIsSystem();
-
- /**
* Returns OK if aJSContext and target have the same "origin"
* (scheme, host, and port).
*/
[noscript] void checkSameOrigin(in JSContextPtr aJSContext,
in nsIURI aTargetURI);
/**
* Returns OK if aSourceURI and target have the same "origin"
@@ -188,24 +176,16 @@ interface nsIScriptSecurityManager : nsI
%{C++
bool IsSystemPrincipal(nsIPrincipal* aPrincipal) {
bool isSystem = false;
IsSystemPrincipal(aPrincipal, &isSystem);
return isSystem;
}
%}
- /**
- * Same as getSubjectPrincipal(), only faster. cx must *never* be
- * passed null, and it must be the context on the top of the
- * context stack. Does *not* reference count the returned
- * principal.
- */
- [noscript,notxpcom] nsIPrincipal getCxSubjectPrincipal(in JSContextPtr cx);
-
const unsigned long NO_APP_ID = 0;
const unsigned long UNKNOWN_APP_ID = 4294967295; // UINT32_MAX
const unsigned long SAFEBROWSING_APP_ID = 4294967294; // UINT32_MAX - 1
/**
* Returns the jar prefix for the app.
* appId can be NO_APP_ID or a valid app id. appId should not be
* UNKNOWN_APP_ID.
--- a/caps/include/nsScriptSecurityManager.h
+++ b/caps/include/nsScriptSecurityManager.h
@@ -35,28 +35,31 @@ class ClassInfoData;
{ 0xba, 0x18, 0x00, 0x60, 0xb0, 0xf1, 0x99, 0xa2 }}
class nsScriptSecurityManager : public nsIScriptSecurityManager,
public nsIChannelEventSink,
public nsIObserver
{
public:
static void Shutdown();
-
+
NS_DEFINE_STATIC_CID_ACCESSOR(NS_SCRIPTSECURITYMANAGER_CID)
-
+
NS_DECL_ISUPPORTS
NS_DECL_NSISCRIPTSECURITYMANAGER
NS_DECL_NSIXPCSECURITYMANAGER
NS_DECL_NSICHANNELEVENTSINK
NS_DECL_NSIOBSERVER
static nsScriptSecurityManager*
GetScriptSecurityManager();
+ // Invoked exactly once, by XPConnect.
+ static void InitStatics();
+
static nsSystemPrincipal*
SystemPrincipalSingletonConstructor();
JSContext* GetCurrentJSContext();
JSContext* GetSafeJSContext();
/**
@@ -113,36 +116,25 @@ private:
static bool
JSPrincipalsSubsume(JSPrincipals *first, JSPrincipals *second);
// Returns null if a principal cannot be found; generally callers
// should error out at that point.
static nsIPrincipal* doGetObjectPrincipal(JSObject* obj);
- // Returns null if a principal cannot be found. Note that rv can be NS_OK
- // when this happens -- this means that there was no JS running.
- nsIPrincipal*
- doGetSubjectPrincipal(nsresult* rv);
-
nsresult
GetCodebasePrincipalInternal(nsIURI* aURI, uint32_t aAppId,
bool aInMozBrowser,
nsIPrincipal** result);
nsresult
CreateCodebasePrincipal(nsIURI* aURI, uint32_t aAppId, bool aInMozBrowser,
nsIPrincipal** result);
- // Returns null if a principal cannot be found. Note that rv can be NS_OK
- // when this happens -- this means that there was no script for the
- // context. Callers MUST pass in a non-null rv here.
- nsIPrincipal*
- GetSubjectPrincipal(JSContext* cx, nsresult* rv);
-
nsresult
Init();
nsresult
InitPrefs();
inline void
ScriptSecurityPrefChanged();
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -76,21 +76,17 @@ static NS_DEFINE_CID(kZipReaderCID, NS_Z
nsIIOService *nsScriptSecurityManager::sIOService = nullptr;
nsIStringBundle *nsScriptSecurityManager::sStrBundle = nullptr;
JSRuntime *nsScriptSecurityManager::sRuntime = 0;
bool nsScriptSecurityManager::sStrictFileOriginPolicy = true;
bool
nsScriptSecurityManager::SubjectIsPrivileged()
{
- JSContext *cx = GetCurrentJSContext();
- if (cx && xpc::IsUniversalXPConnectEnabled(cx))
- return true;
- bool isSystem = false;
- return NS_SUCCEEDED(SubjectPrincipalIsSystem(&isSystem)) && isSystem;
+ return nsContentUtils::IsCallerChrome();
}
///////////////////////////
// Convenience Functions //
///////////////////////////
// Result of this function should not be freed.
static inline const char16_t *
IDToString(JSContext *cx, jsid id_)
@@ -313,30 +309,16 @@ nsScriptSecurityManager::GetChannelPrinc
NS_IMETHODIMP
nsScriptSecurityManager::IsSystemPrincipal(nsIPrincipal* aPrincipal,
bool* aIsSystem)
{
*aIsSystem = (aPrincipal == mSystemPrincipal);
return NS_OK;
}
-NS_IMETHODIMP_(nsIPrincipal *)
-nsScriptSecurityManager::GetCxSubjectPrincipal(JSContext *cx)
-{
- NS_ASSERTION(cx == GetCurrentJSContext(),
- "Uh, cx is not the current JS context!");
-
- nsresult rv = NS_ERROR_FAILURE;
- nsIPrincipal *principal = GetSubjectPrincipal(cx, &rv);
- if (NS_FAILED(rv))
- return nullptr;
-
- return principal;
-}
-
/////////////////////////////
// nsScriptSecurityManager //
/////////////////////////////
////////////////////////////////////
// Methods implementing ISupports //
////////////////////////////////////
NS_IMPL_ISUPPORTS(nsScriptSecurityManager,
@@ -349,36 +331,20 @@ NS_IMPL_ISUPPORTS(nsScriptSecurityManage
// Methods implementing nsIScriptSecurityManager //
///////////////////////////////////////////////////
///////////////// Security Checks /////////////////
bool
nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(JSContext *cx)
{
- // Get the security manager
- nsScriptSecurityManager *ssm =
- nsScriptSecurityManager::GetScriptSecurityManager();
-
- NS_ASSERTION(ssm, "Failed to get security manager service");
- if (!ssm)
- return false;
-
- nsresult rv;
- nsIPrincipal* subjectPrincipal = ssm->GetSubjectPrincipal(cx, &rv);
-
- NS_ASSERTION(NS_SUCCEEDED(rv), "CSP: Failed to get nsIPrincipal from js context");
- if (NS_FAILED(rv))
- return false; // Not just absence of principal, but failure.
-
- if (!subjectPrincipal)
- return true;
-
+ MOZ_ASSERT(cx == nsContentUtils::GetCurrentJSContext());
+ nsCOMPtr<nsIPrincipal> subjectPrincipal = nsContentUtils::GetSubjectPrincipal();
nsCOMPtr<nsIContentSecurityPolicy> csp;
- rv = subjectPrincipal->GetCsp(getter_AddRefs(csp));
+ nsresult rv = subjectPrincipal->GetCsp(getter_AddRefs(csp));
NS_ASSERTION(NS_SUCCEEDED(rv), "CSP: Failed to get CSP from principal.");
// don't do anything unless there's a CSP
if (!csp)
return true;
bool evalOK = true;
bool reportViolation = false;
@@ -419,37 +385,20 @@ nsScriptSecurityManager::JSPrincipalsSub
{
return nsJSPrincipals::get(first)->Subsumes(nsJSPrincipals::get(second));
}
NS_IMETHODIMP
nsScriptSecurityManager::CheckSameOrigin(JSContext* cx,
nsIURI* aTargetURI)
{
- nsresult rv;
-
- // Get a context if necessary
- if (!cx)
- {
- cx = GetCurrentJSContext();
- if (!cx)
- return NS_OK; // No JS context, so allow access
- }
+ MOZ_ASSERT_IF(cx, cx == nsContentUtils::GetCurrentJSContext());
// Get a principal from the context
- nsIPrincipal* sourcePrincipal = GetSubjectPrincipal(cx, &rv);
- if (NS_FAILED(rv))
- return rv;
-
- if (!sourcePrincipal)
- {
- NS_WARNING("CheckSameOrigin called on script w/o principals; should this happen?");
- return NS_OK;
- }
-
+ nsIPrincipal* sourcePrincipal = nsContentUtils::GetSubjectPrincipal();
if (sourcePrincipal == mSystemPrincipal)
{
// This is a system (chrome) script, so allow access
return NS_OK;
}
// Get the original URI from the source principal.
// This has the effect of ignoring any change to document.domain
@@ -515,27 +464,20 @@ nsScriptSecurityManager::AppAttributesEq
return ((firstAppId == secondAppId) &&
(aFirst->GetIsInBrowserElement() == aSecond->GetIsInBrowserElement()));
}
NS_IMETHODIMP
nsScriptSecurityManager::CheckLoadURIFromScript(JSContext *cx, nsIURI *aURI)
{
// Get principal of currently executing script.
- nsresult rv;
- nsIPrincipal* principal = GetSubjectPrincipal(cx, &rv);
- if (NS_FAILED(rv))
- return rv;
-
- // Native code can load all URIs.
- if (!principal)
- return NS_OK;
-
- rv = CheckLoadURIWithPrincipal(principal, aURI,
- nsIScriptSecurityManager::STANDARD);
+ MOZ_ASSERT(cx == nsContentUtils::GetCurrentJSContext());
+ nsIPrincipal* principal = nsContentUtils::GetSubjectPrincipal();
+ nsresult rv = CheckLoadURIWithPrincipal(principal, aURI,
+ nsIScriptSecurityManager::STANDARD);
if (NS_SUCCEEDED(rv)) {
// OK to load
return NS_OK;
}
// See if we're attempting to load a file: URI. If so, let a
// UniversalXPConnect capability trump the above check.
bool isFile = false;
@@ -934,72 +876,25 @@ nsScriptSecurityManager::ScriptAllowed(J
AutoJSContext cx;
JS::RootedObject global(cx, js::UncheckedUnwrap(aGlobal, /* stopAtOuter = */ false));
// Check the bits on the compartment private.
return xpc::Scriptability::Get(aGlobal).Allowed();
}
///////////////// Principals ///////////////////////
-NS_IMETHODIMP
-nsScriptSecurityManager::GetSubjectPrincipal(nsIPrincipal **aSubjectPrincipal)
-{
- nsresult rv;
- *aSubjectPrincipal = doGetSubjectPrincipal(&rv);
- if (NS_SUCCEEDED(rv))
- NS_IF_ADDREF(*aSubjectPrincipal);
- return rv;
-}
-
-nsIPrincipal*
-nsScriptSecurityManager::doGetSubjectPrincipal(nsresult* rv)
-{
- NS_PRECONDITION(rv, "Null out param");
- JSContext *cx = GetCurrentJSContext();
- if (!cx)
- {
- *rv = NS_OK;
- return nullptr;
- }
- return GetSubjectPrincipal(cx, rv);
-}
NS_IMETHODIMP
nsScriptSecurityManager::GetSystemPrincipal(nsIPrincipal **result)
{
NS_ADDREF(*result = mSystemPrincipal);
return NS_OK;
}
-NS_IMETHODIMP
-nsScriptSecurityManager::SubjectPrincipalIsSystem(bool* aIsSystem)
-{
- NS_ENSURE_ARG_POINTER(aIsSystem);
- *aIsSystem = false;
-
- if (!mSystemPrincipal)
- return NS_OK;
-
- nsCOMPtr<nsIPrincipal> subject;
- nsresult rv = GetSubjectPrincipal(getter_AddRefs(subject));
- if (NS_FAILED(rv))
- return rv;
-
- if(!subject)
- {
- // No subject principal means no JS is running;
- // this is the equivalent of system principal code
- *aIsSystem = true;
- return NS_OK;
- }
-
- return mSystemPrincipal->Equals(subject, aIsSystem);
-}
-
nsresult
nsScriptSecurityManager::CreateCodebasePrincipal(nsIURI* aURI, uint32_t aAppId,
bool aInMozBrowser,
nsIPrincipal **result)
{
// I _think_ it's safe to not create null principals here based on aURI.
// At least all the callers would do the right thing in those cases, as far
// as I can tell. --bz
@@ -1098,31 +993,16 @@ nsScriptSecurityManager::GetCodebasePrin
rv = CreateCodebasePrincipal(aURI, aAppId, aInMozBrowser,
getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, rv);
NS_IF_ADDREF(*result = principal);
return NS_OK;
}
-nsIPrincipal*
-nsScriptSecurityManager::GetSubjectPrincipal(JSContext *cx,
- nsresult* rv)
-{
- *rv = NS_OK;
- JSCompartment *compartment = js::GetContextCompartment(cx);
-
- // The context should always be in a compartment, either one it has entered
- // or the one associated with its global.
- MOZ_ASSERT(!!compartment);
-
- JSPrincipals *principals = JS_GetCompartmentPrincipals(compartment);
- return nsJSPrincipals::get(principals);
-}
-
// static
nsIPrincipal*
nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj)
{
JSCompartment *compartment = js::GetObjectCompartment(aObj);
JSPrincipals *principals = JS_GetCompartmentPrincipals(compartment);
return nsJSPrincipals::get(principals);
}
@@ -1153,42 +1033,36 @@ nsScriptSecurityManager::CanCreateWrappe
if (SubjectIsPrivileged())
{
return NS_OK;
}
//-- Access denied, report an error
NS_ConvertUTF8toUTF16 strName("CreateWrapperDenied");
nsAutoCString origin;
- nsresult rv2;
- nsIPrincipal* subjectPrincipal = doGetSubjectPrincipal(&rv2);
- if (NS_SUCCEEDED(rv2) && subjectPrincipal) {
- GetPrincipalDomainOrigin(subjectPrincipal, origin);
- }
+ nsIPrincipal* subjectPrincipal = nsContentUtils::GetSubjectPrincipal();
+ GetPrincipalDomainOrigin(subjectPrincipal, origin);
NS_ConvertUTF8toUTF16 originUnicode(origin);
NS_ConvertUTF8toUTF16 classInfoName(objClassInfo.GetName());
const char16_t* formatStrings[] = {
classInfoName.get(),
originUnicode.get()
};
uint32_t length = ArrayLength(formatStrings);
if (originUnicode.IsEmpty()) {
--length;
} else {
strName.AppendLiteral("ForOrigin");
}
nsXPIDLString errorMsg;
- // We need to keep our existing failure rv and not override it
- // with a likely success code from the following string bundle
- // call in order to throw the correct security exception later.
- rv2 = sStrBundle->FormatStringFromName(strName.get(),
- formatStrings,
- length,
- getter_Copies(errorMsg));
- NS_ENSURE_SUCCESS(rv2, rv2);
+ nsresult rv = sStrBundle->FormatStringFromName(strName.get(),
+ formatStrings,
+ length,
+ getter_Copies(errorMsg));
+ NS_ENSURE_SUCCESS(rv, rv);
SetPendingException(cx, errorMsg.get());
return NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED;
}
NS_IMETHODIMP
nsScriptSecurityManager::CanCreateInstance(JSContext *cx,
const nsCID &aCID)
@@ -1363,37 +1237,30 @@ nsScriptSecurityManager::Shutdown()
NS_IF_RELEASE(sIOService);
NS_IF_RELEASE(sStrBundle);
}
nsScriptSecurityManager *
nsScriptSecurityManager::GetScriptSecurityManager()
{
- if (!gScriptSecMan && nsXPConnect::XPConnect())
- {
- nsRefPtr<nsScriptSecurityManager> ssManager = new nsScriptSecurityManager();
+ return gScriptSecMan;
+}
- nsresult rv;
- rv = ssManager->Init();
- if (NS_FAILED(rv)) {
- return nullptr;
- }
-
- rv = nsXPConnect::XPConnect()->
- SetDefaultSecurityManager(ssManager);
- if (NS_FAILED(rv)) {
- NS_WARNING("Failed to install xpconnect security manager!");
- return nullptr;
- }
+/* static */ void
+nsScriptSecurityManager::InitStatics()
+{
+ nsRefPtr<nsScriptSecurityManager> ssManager = new nsScriptSecurityManager();
+ nsresult rv = ssManager->Init();
+ if (NS_FAILED(rv)) {
+ MOZ_CRASH();
+ }
- ClearOnShutdown(&gScriptSecMan);
- gScriptSecMan = ssManager;
- }
- return gScriptSecMan;
+ ClearOnShutdown(&gScriptSecMan);
+ gScriptSecMan = ssManager;
}
// Currently this nsGenericFactory constructor is used only from FastLoad
// (XPCOM object deserialization) code, when "creating" the system principal
// singleton.
nsSystemPrincipal *
nsScriptSecurityManager::SystemPrincipalSingletonConstructor()
{
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -1300,22 +1300,16 @@ endif
endif
ifneq ($(DIST_FILES),)
DIST_FILES_PATH := $(FINAL_TARGET)
DIST_FILES_FLAGS := $(XULAPP_DEFINES)
PP_TARGETS += DIST_FILES
endif
-ifneq ($(DIST_FILES_NO_PP),)
-_DIST_FILES := $(DIST_FILES_NO_PP)
-_DIST_DEST := $(FINAL_TARGET)
-INSTALL_TARGETS += _DIST
-endif
-
ifneq ($(XPI_PKGNAME),)
tools realchrome::
ifdef STRIP_XPI
ifndef MOZ_DEBUG
@echo 'Stripping $(XPI_PKGNAME) package directory...'
@echo $(FINAL_TARGET)
@cd $(FINAL_TARGET) && find . ! -type d \
! -name '*.js' \
--- a/config/system-headers
+++ b/config/system-headers
@@ -159,54 +159,79 @@ afxpriv.h
afxtempl.h
afxwin.h
algorithm
Aliases.h
all.h
alloca.h
alloc.h
alsa/asoundlib.h
+#ifdef ANDROID
+android/ashmem.h
android/log.h
+android/looper.h
+android/native_window.h
+android_audio/AudioSystem.h
+#endif
ansi_parms.h
a.out.h
app/Cursor.h
Appearance.h
AppFileInfo.h
AppKit.h
AppleEvents.h
Application.h
app/Message.h
app/MessageRunner.h
arpa/inet.h
arpa/nameser.h
+asm/page.h
asm/sigcontext.h
asm/signal.h
ASRegistry.h
assert.h
atk/atk.h
atlcom.h
atlconv.h
atlctl.cpp
atlctl.h
ATLCTL.H
atlhost.h
atlimpl.cpp
atlwin.cpp
ATSTypes.h
ATSUnicode.h
+#ifdef ANDROID
+AudioParameter.h
+AudioSystem.h
+AudioTrack.h
+avc_utils.h
+#endif
Balloons.h
base/pblock.h
base/PCR_Base.h
base/session.h
basetyps.h
be/app/Application.h
Beep.h
be/kernel/image.h
be/kernel/OS.h
bfd.h
+#ifdef ANDROID
+binder/Binder.h
+binder/BinderService.h
+binder/IBinder.h
+binder/IInterface.h
+binder/IMemory.h
+binder/IPCThreadState.h
+binder/IPermissionController.h
+binder/IServiceManager.h
+binder/Parcel.h
+binder/ProcessState.h
+#endif
Bitmap.h
bitset
blapi.h
bsd/libc.h
bsd/syscall.h
bstring.h
builtin.h
Button.h
@@ -278,16 +303,20 @@ direct/trace.h
direct/modules.h
direct/log.h
direct/system.h
direct/list.h
dfb_types.h
directfb_strings.h
directfb_keyboard.h
callconv.h
+#ifdef ANDROID
+camera/Camera.h
+camera/CameraParameters.h
+#endif
Carbon/Carbon.h
CarbonEvents.h
Carbon.h
cassert
c_asm.h
cctype
cderr.h
cerrno
@@ -303,16 +332,19 @@ CFString.h
CFURL.h
CGAffineTransform.h
CheckBox.h
climits
Clipboard.h
cmplrs/stsupport.h
Cocoa/Cocoa.h
CodeFragments.h
+#ifdef ANDROID
+ColorConverter.h
+#endif
comdef.h
commctrl.h
COMMCTRL.H
commdlg.h
compat.h
condapi.h
ConditionalMacros.h
config.h
@@ -335,16 +367,25 @@ cstddef
cstdio
cstdlib
cstring
ctime
ctype.h
curl/curl.h
curl/easy.h
curses.h
+#ifdef ANDROID
+cutils/android_reboot.h
+cutils/atomic.h
+cutils/compiler.h
+cutils/log.h
+cutils/native_handle.h
+cutils/properties.h
+cutils/sockets.h
+#endif
cxxabi.h
DateTimeUtils.h
dbus/dbus.h
dbus/dbus-glib.h
dbus/dbus-glib-lowlevel.h
ddeml.h
Debug.h
deque
@@ -361,16 +402,19 @@ dl.h
docobj.h
dos/dosextens.h
dos.h
Drag.h
DriverServices.h
DriverSynchronization.h
DropInPanel.h
dvidef.h
+#ifdef ANDROID
+EffectApi.h
+#endif
elf.h
endian.h
Entry.h
errno.h
Errors.h
Events.h
exdisp.h
ExDisp.h
@@ -391,16 +435,29 @@ FinderRegistry.h
FixMath.h
float.h
fnmatch.h
Folders.h
fontconfig/fontconfig.h
fontconfig/fcfreetype.h
Font.h
Fonts.h
+#ifdef ANDROID
+foundation/ABase.h
+foundation/ABitReader.h
+foundation/ABuffer.h
+foundation/ADebug.h
+foundation/AHandler.h
+foundation/AHandlerReflector.h
+foundation/ALooper.h
+foundation/AMessage.h
+foundation/AString.h
+foundation/base64.h
+foundation/hexdump.h
+#endif
fp.h
fpieee.h
frame/log.h
frame/req.h
freetype/freetype.h
freetype/ftcache.h
freetype/ftglyph.h
freetype/ftsynth.h
@@ -453,19 +510,51 @@ gssapi_generic.h
gssapi/gssapi_generic.h
gssapi/gssapi.h
gssapi.h
gtk/gtk.h
gtk/gtkx.h
gtk/gtkprinter.h
gtk/gtkprintjob.h
gtk/gtkprintunixdialog.h
+#ifdef ANDROID
+gui/GraphicBufferAlloc.h
+gui/IConsumerListener.h
+gui/IGraphicBufferAlloc.h
+gui/IGraphicBufferProducer.h
+gui/ISurfaceComposer.h
+gui/ISurfaceComposerClient.h
+gui/ISurfaceTexture.h
+gui/Surface.h
+gui/SurfaceComposerClient.h
+gui/SurfaceTextureClient.h
+hardware/audio.h
+hardware/gralloc.h
+hardware/hardware.h
+hardware/hwcomposer.h
+hardware/lights.h
+hardware/power.h
+hardware_legacy/power.h
+hardware_legacy/uevent.h
+hardware_legacy/vibrator.h
+#endif
HIToolbox/HIToolbox.h
hlink.h
+#ifdef ANDROID
+HTTPBase.h
+#endif
ia64/sys/inline.h
+#ifdef ANDROID
+IAudioFlingerClient.h
+IAudioFlinger.h
+IAudioRecord.h
+IAudioTrack.h
+IEffect.h
+IEffectClient.h
+#endif
Icons.h
iconv.h
ieeefp.h
ifaddrs.h
image.h
imagehlp.h
imm.h
initguid.h
@@ -555,16 +644,21 @@ libgnomevfs/gnome-vfs-mime.h
libgnomevfs/gnome-vfs-mime-handlers.h
libgnomevfs/gnome-vfs-mime-utils.h
libgnomevfs/gnome-vfs-ops.h
libgnomevfs/gnome-vfs-standard-callbacks.h
lib$routines.h
limits
limits.h
link.h
+#ifdef ANDROID
+linux/android_alarm.h
+linux/ashmem.h
+#endif
+linux/ioprio.h
linux/kernel.h
linux/limits.h
linux/rtc.h
linux/version.h
list
List.h
Lists.h
LListBox.h
@@ -641,16 +735,57 @@ mapidefs.h
mapiguid.h
mapi.h
mapitags.h
mapiutil.h
mapix.h
Math64.h
math.h
mbstring.h
+#ifdef ANDROID
+media/ICrypto.h
+media/IOMX.h
+media/MediaProfiles.h
+media/MediaRecorderBase.h
+media/openmax/OMX_Audio.h
+media/stagefright/AACWriter.h
+media/stagefright/AMRWriter.h
+media/stagefright/AudioSource.h
+media/stagefright/DataSource.h
+media/stagefright/foundation/ABase.h
+media/stagefright/foundation/ABitReader.h
+media/stagefright/foundation/ABuffer.h
+media/stagefright/foundation/ADebug.h
+media/stagefright/foundation/AHandler.h
+media/stagefright/foundation/AHandlerReflector.h
+media/stagefright/foundation/ALooper.h
+media/stagefright/foundation/AMessage.h
+media/stagefright/foundation/AString.h
+media/stagefright/foundation/base64.h
+media/stagefright/foundation/hexdump.h
+media/stagefright/MediaBuffer.h
+media/stagefright/MediaBufferGroup.h
+media/stagefright/MediaCodec.h
+media/stagefright/MediaDefs.h
+media/stagefright/MediaErrors.h
+media/stagefright/MediaExtractor.h
+media/stagefright/MediaSource.h
+media/stagefright/MediaWriter.h
+media/stagefright/MetaData.h
+media/stagefright/MPEG2TSWriter.h
+media/stagefright/MPEG4Writer.h
+media/stagefright/OMXClient.h
+media/stagefright/OMXCodec.h
+media/stagefright/openmax/OMX_Core.h
+media/stagefright/openmax/OMX_Index.h
+media/stagefright/openmax/OMX_IVCommon.h
+media/stagefright/openmax/OMX_Types.h
+media/stagefright/openmax/OMX_Video.h
+media/stagefright/Utils.h
+#endif
mem.h
memory
memory.h
Memory.h
MenuBar.h
Menu.h
Menus.h
Message.h
@@ -682,16 +817,20 @@ nl_types.h
NodeInfo.h
nsswitch.h
objbase.h
objidl.h
Objsafe.h
ojiapitests.h
ole2.h
oleidl.h
+#ifdef ANDROID
+OMX.h
+OMX_Component.h
+#endif
OpenGL/OpenGL.h
OpenTptInternet.h
OpenTransport.h
OS.h
osreldate.h
ostream
OSUtils.h
Packages.h
@@ -728,17 +867,20 @@ PP_DebugHeaders.cp
PP_KeyCodes.h
PP_Macros.h
PP_Messages.h
PP_Prefix.h
PP_Resources.h
PP_Types.h
Printing.h
Print/PMPrintingDialogExtensions.h
+#ifdef ANDROID
+private/android_filesystem_config.h
private/qucomextra_p.h
+#endif
Processes.h
process.h
Process.h
proto/dos.h
proto/exec.h
psap.h
Pt.h
pthread.h
@@ -778,16 +920,17 @@ secrng.h
security.h
secutil.h
semaphore.h
servprov.h
set
setjmp.h
SFNTLayoutTypes.h
SFNTTypes.h
+sha1.h
share.h
shellapi.h
shlguid.h
shlobj.h
sigcontext.h
signal.h
SimpleGameSound.h
SIOUX.h
@@ -795,16 +938,53 @@ size_t.h
sndio.h
someincludefile.h
Sound.h
soundcard.h
sqlite3.h
ssdef.h
sstream
stack
+#ifdef ANDROID
+stagefright/AACWriter.h
+stagefright/AMRWriter.h
+stagefright/AudioSource.h
+stagefright/DataSource.h
+stagefright/foundation/ABase.h
+stagefright/foundation/ABitReader.h
+stagefright/foundation/ABuffer.h
+stagefright/foundation/ADebug.h
+stagefright/foundation/AHandler.h
+stagefright/foundation/AHandlerReflector.h
+stagefright/foundation/ALooper.h
+stagefright/foundation/AMessage.h
+stagefright/foundation/AString.h
+stagefright/foundation/base64.h
+stagefright/foundation/hexdump.h
+stagefright/MediaBuffer.h
+stagefright/MediaBufferGroup.h
+stagefright/MediaCodec.h
+stagefright/MediaDefs.h
+stagefright/MediaErrors.h
+stagefright/MediaExtractor.h
+stagefright/MediaSource.h
+stagefright/MediaWriter.h
+stagefright/MetaData.h
+stagefright/MPEG2TSWriter.h
+stagefright/MPEG4Writer.h
+stagefright/OMXCodec.h
+stagefright/OMXClient.h
+stagefright/openmax/OMX_Component.h
+stagefright/openmax/OMX_Core.h
+stagefright/openmax/OMX_Index.h
+stagefright/openmax/OMX_IVCommon.h
+stagefright/openmax/OMX_Types.h
+stagefright/openmax/OMX_Video.h
+stagefright/Utils.h
+#endif
StandardFile.h
starlet.h
stat.h
statreg.cpp
statreg.h
stdarg.h
stdbool.h
stddef.h
@@ -823,40 +1003,46 @@ StringView.h
stropts.h
strstrea.h
structs.h
stsdef.h
SupportDefs.h
support/String.h
support/SupportDefs.h
support/TLS.h
+#ifdef ANDROID
+suspend/autosuspend.h
+#endif
svrcore.h
symconst.h
sym.h
synch.h
syncmgr.h
sys/atomic_op.h
sys/bitypes.h
sys/byteorder.h
syscall.h
sys/cdefs.h
sys/cfgodm.h
sys/elf.h
sys/endian.h
+sys/epoll.h
sys/errno.h
sys/fault.h
sys/fcntl.h
sys/file.h
sys/filio.h
sys/frame.h
sys/immu.h
+sys/inotify.h
sys/inttypes.h
sys/ioccom.h
sys/ioctl.h
sys/ipc.h
+sys/klog.h
sys/ldr.h
sys/link.h
sys/locking.h
syslog.h
sys/lwp.h
sys/machine.h
sys/mman.h
sys/mmu.h
@@ -905,16 +1091,22 @@ sys/ttycom.h
sys/types.h
sys/ucontext.h
sys/uio.h
sys/un.h
sys/unistd.h
sys/utsname.h
sys/vfs.h
sys/wait.h
+#ifdef ANDROID
+sysutils/NetlinkEvent.h
+system/audio.h
+system/graphics.h
+system/window.h
+#endif
tables.h
TArray.h
TArrayIterator.h
task.h
tchar.h
TCHAR.H
termios.h
TextCommon.h
@@ -947,16 +1139,25 @@ UDebugging.h
UDesktop.h
UDrawingState.h
UDrawingUtils.h
UEnvironment.h
UEventMgr.h
UException.h
UExtractFromAEDesc.h
UGWorld.h
+#ifdef ANDROID
+ui/ANativeObjectBase.h
+ui/egl/android_natives.h
+ui/Fence.h
+ui/FramebufferNativeWindow.h
+ui/GraphicBuffer.h
+ui/Rect.h
+ui/Region.h
+#endif
UKeyFilters.h
ulocks.h
ulserrno.h
UMemoryMgr.h
UModalDialogs.h
UNavServicesDialogs.h
UnicodeBlockObjects.h
UnicodeConverter.h
@@ -970,16 +1171,38 @@ unixlib.h
unknwn.h
UPrinting.h
UQuickTime.h
UReanimator.h
URegions.h
URegistrar.h
UResourceMgr.h
utility
+#ifdef ANDROID
+utils/BitSet.h
+utils/CallStack.h
+utils/Errors.h
+utils/FileMap.h
+utils/KeyedVector.h
+utils/List.h
+utils/Log.h
+utils/Looper.h
+utils/PropertyMap.h
+utils/RefBase.h
+utils/String16.h
+utils/String8.h
+utils/threads.h
+utils/TextOutput.h
+utils/Timers.h
+utils/Trace.h
+utils/TypeHelpers.h
+utils/Unicode.h
+utils/Vector.h
+utils/VectorImpl.h
+#endif
urlhist.h
urlmon.h
UScrap.h
UScreenPort.h
UTCUtils.h
UTETextAction.h
UTEViewTextAction.h
UTextEdit.h
--- a/configure.in
+++ b/configure.in
@@ -8978,16 +8978,18 @@ fi
if test -n "$JS_SHARED_LIBRARY"; then
MOZ_JS_LIBS="$MOZ_JS_SHARED_LIBS"
else
MOZ_JS_LIBS="$MOZ_JS_STATIC_LIBS"
AC_DEFINE(MOZ_STATIC_JS)
fi
AC_SUBST(JS_SHARED_LIBRARY)
+AC_SUBST(UPLOAD_EXTRA_FILES)
+
MOZ_CREATE_CONFIG_STATUS()
# No need to run subconfigures when building with LIBXUL_SDK_DIR
if test "$COMPILE_ENVIRONMENT" -a -z "$LIBXUL_SDK_DIR"; then
MOZ_SUBCONFIGURE_ICU()
MOZ_SUBCONFIGURE_FFI()
fi
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -2165,16 +2165,17 @@ private:
nsIAtom* aAtom, void* aData);
static void DestroyClassNameArray(void* aData);
static void* AllocClassMatchingInfo(nsINode* aRootNode,
const nsString* aClasses);
static nsIXPConnect *sXPConnect;
static nsIScriptSecurityManager *sSecurityManager;
+ static nsIPrincipal *sSystemPrincipal;
static nsIParserService *sParserService;
static nsNameSpaceManager *sNameSpaceManager;
static nsIIOService *sIOService;
static bool sImgLoaderInitialized;
--- a/content/base/src/DOMParser.cpp
+++ b/content/base/src/DOMParser.cpp
@@ -381,39 +381,20 @@ DOMParser::Constructor(const GlobalObjec
}
return domParser.forget();
}
/*static */already_AddRefed<DOMParser>
DOMParser::Constructor(const GlobalObject& aOwner,
ErrorResult& rv)
{
- nsCOMPtr<nsIPrincipal> prin;
- nsCOMPtr<nsIURI> documentURI;
- nsCOMPtr<nsIURI> baseURI;
- // No arguments; use the subject principal
- nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
- if (!secMan) {
- rv.Throw(NS_ERROR_UNEXPECTED);
- return nullptr;
- }
-
- rv = secMan->GetSubjectPrincipal(getter_AddRefs(prin));
- if (rv.Failed()) {
- return nullptr;
- }
-
- // We're called from JS; there better be a subject principal, really.
- if (!prin) {
- rv.Throw(NS_ERROR_UNEXPECTED);
- return nullptr;
- }
-
nsRefPtr<DOMParser> domParser = new DOMParser(aOwner.GetAsSupports());
- rv = domParser->InitInternal(aOwner.GetAsSupports(), prin, documentURI, baseURI);
+ rv = domParser->InitInternal(aOwner.GetAsSupports(),
+ nsContentUtils::GetSubjectPrincipal(),
+ nullptr, nullptr);
if (rv.Failed()) {
return nullptr;
}
return domParser.forget();
}
nsresult
DOMParser::InitInternal(nsISupports* aOwner, nsIPrincipal* prin,
@@ -459,34 +440,18 @@ DOMParser::Init(nsIPrincipal* aPrincipal
if (!cx) {
rv.Throw(NS_ERROR_UNEXPECTED);
return;
}
nsIScriptContext* scriptContext = GetScriptContextFromJSContext(cx);
nsCOMPtr<nsIPrincipal> principal = aPrincipal;
-
if (!principal && !aDocumentURI) {
- nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
- if (!secMan) {
- rv.Throw(NS_ERROR_UNEXPECTED);
- return;
- }
-
- rv = secMan->GetSubjectPrincipal(getter_AddRefs(principal));
- if (rv.Failed()) {
- return;
- }
-
- // We're called from JS; there better be a subject principal, really.
- if (!principal) {
- rv.Throw(NS_ERROR_UNEXPECTED);
- return;
- }
+ principal = nsContentUtils::GetSubjectPrincipal();
}
rv = Init(principal, aDocumentURI, aBaseURI,
scriptContext ? scriptContext->GetGlobalObject() : nullptr);
}
nsresult
DOMParser::SetUpDocument(DocumentFlavor aFlavor, nsIDOMDocument** aResult)
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -190,16 +190,17 @@ using namespace mozilla::dom;
using namespace mozilla::layers;
using namespace mozilla::widget;
using namespace mozilla;
const char kLoadAsData[] = "loadAsData";
nsIXPConnect *nsContentUtils::sXPConnect;
nsIScriptSecurityManager *nsContentUtils::sSecurityManager;
+nsIPrincipal *nsContentUtils::sSystemPrincipal;
nsIParserService *nsContentUtils::sParserService = nullptr;
nsNameSpaceManager *nsContentUtils::sNameSpaceManager;
nsIIOService *nsContentUtils::sIOService;
nsIConsoleService *nsContentUtils::sConsoleService;
nsDataHashtable<nsISupportsHashKey, EventNameMapping>* nsContentUtils::sAtomEventTable = nullptr;
nsDataHashtable<nsStringHashKey, EventNameMapping>* nsContentUtils::sStringEventTable = nullptr;
nsCOMArray<nsIAtom>* nsContentUtils::sUserDefinedEvents = nullptr;
nsIStringBundleService *nsContentUtils::sStringBundleService;
@@ -371,18 +372,18 @@ nsContentUtils::Init()
sXPConnect = nsXPConnect::XPConnect();
sSecurityManager = nsScriptSecurityManager::GetScriptSecurityManager();
if(!sSecurityManager)
return NS_ERROR_FAILURE;
NS_ADDREF(sSecurityManager);
- // Getting the first context can trigger GC, so do this non-lazily.
- sXPConnect->InitSafeJSContext();
+ sSecurityManager->GetSystemPrincipal(&sSystemPrincipal);
+ MOZ_ASSERT(sSystemPrincipal);
nsresult rv = CallGetService(NS_IOSERVICE_CONTRACTID, &sIOService);
if (NS_FAILED(rv)) {
// This makes life easier, but we can live without it.
sIOService = nullptr;
}
@@ -1429,16 +1430,17 @@ nsContentUtils::Shutdown()
uint32_t i;
for (i = 0; i < PropertiesFile_COUNT; ++i)
NS_IF_RELEASE(sStringBundles[i]);
NS_IF_RELEASE(sStringBundleService);
NS_IF_RELEASE(sConsoleService);
sXPConnect = nullptr;
NS_IF_RELEASE(sSecurityManager);
+ NS_IF_RELEASE(sSystemPrincipal);
NS_IF_RELEASE(sParserService);
NS_IF_RELEASE(sIOService);
NS_IF_RELEASE(sLineBreaker);
NS_IF_RELEASE(sWordBreaker);
NS_IF_RELEASE(sBidiKeyboard);
delete sAtomEventTable;
sAtomEventTable = nullptr;
@@ -1509,24 +1511,17 @@ nsContentUtils::CheckSameOrigin(const ns
}
nsresult
nsContentUtils::CheckSameOrigin(const nsINode* aTrustedNode,
const nsINode* unTrustedNode)
{
MOZ_ASSERT(aTrustedNode);
MOZ_ASSERT(unTrustedNode);
-
- bool isSystem = false;
- nsresult rv = sSecurityManager->SubjectPrincipalIsSystem(&isSystem);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (isSystem) {
- // we're running as system, grant access to the node.
-
+ if (IsCallerChrome()) {
return NS_OK;
}
/*
* Get hold of each node's principal
*/
nsIPrincipal* trustedPrincipal = aTrustedNode->NodePrincipal();
@@ -1573,55 +1568,29 @@ nsContentUtils::CanCallerAccess(nsIDOMNo
NS_ENSURE_TRUE(node, false);
return CanCallerAccess(node);
}
// static
bool
nsContentUtils::CanCallerAccess(nsINode* aNode)
{
- // XXXbz why not check the IsCapabilityEnabled thing up front, and not bother
- // with the system principal games? But really, there should be a simpler
- // API here, dammit.
- nsCOMPtr<nsIPrincipal> subjectPrincipal;
- nsresult rv = sSecurityManager->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
- NS_ENSURE_SUCCESS(rv, false);
-
- if (!subjectPrincipal) {
- // we're running as system, grant access to the node.
-
- return true;
- }
-
- return CanCallerAccess(subjectPrincipal, aNode->NodePrincipal());
+ return CanCallerAccess(GetSubjectPrincipal(), aNode->NodePrincipal());
}
// static
bool
nsContentUtils::CanCallerAccess(nsPIDOMWindow* aWindow)
{
- // XXXbz why not check the IsCapabilityEnabled thing up front, and not bother
- // with the system principal games? But really, there should be a simpler
- // API here, dammit.
- nsCOMPtr<nsIPrincipal> subjectPrincipal;
- nsresult rv = sSecurityManager->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
- NS_ENSURE_SUCCESS(rv, false);
-
- if (!subjectPrincipal) {
- // we're running as system, grant access to the node.
-
- return true;
- }
-
nsCOMPtr<nsIScriptObjectPrincipal> scriptObject =
do_QueryInterface(aWindow->IsOuterWindow() ?
aWindow->GetCurrentInnerWindow() : aWindow);
NS_ENSURE_TRUE(scriptObject, false);
- return CanCallerAccess(subjectPrincipal, scriptObject->GetPrincipal());
+ return CanCallerAccess(GetSubjectPrincipal(), scriptObject->GetPrincipal());
}
//static
bool
nsContentUtils::InProlog(nsINode *aNode)
{
NS_PRECONDITION(aNode, "missing node to nsContentUtils::InProlog");
@@ -1713,22 +1682,17 @@ nsContentUtils::GetDocumentFromContext()
return nullptr;
}
bool
nsContentUtils::IsCallerChrome()
{
MOZ_ASSERT(NS_IsMainThread());
- bool is_caller_chrome = false;
- nsresult rv = sSecurityManager->SubjectPrincipalIsSystem(&is_caller_chrome);
- if (NS_FAILED(rv)) {
- return false;
- }
- if (is_caller_chrome) {
+ if (GetSubjectPrincipal() == sSystemPrincipal) {
return true;
}
// If the check failed, look for UniversalXPConnect on the cx compartment.
return xpc::IsUniversalXPConnectEnabled(GetCurrentJSContext());
}
namespace mozilla {
@@ -2348,24 +2312,25 @@ nsContentUtils::GenerateStateKey(nsICont
return NS_OK;
}
// static
nsIPrincipal*
nsContentUtils::GetSubjectPrincipal()
{
- nsCOMPtr<nsIPrincipal> subject;
- sSecurityManager->GetSubjectPrincipal(getter_AddRefs(subject));
-
- // When the ssm says the subject is null, that means system principal.
- if (!subject)
- sSecurityManager->GetSystemPrincipal(getter_AddRefs(subject));
-
- return subject;
+ JSContext* cx = GetCurrentJSContext();
+ if (!cx) {
+ return GetSystemPrincipal();
+ }
+
+ JSCompartment* compartment = js::GetContextCompartment(cx);
+ MOZ_ASSERT(compartment);
+ JSPrincipals* principals = JS_GetCompartmentPrincipals(compartment);
+ return nsJSPrincipals::get(principals);
}
// static
nsIPrincipal*
nsContentUtils::GetObjectPrincipal(JSObject* aObj)
{
// This is duplicated from nsScriptSecurityManager. We don't call through there
// because the API unnecessarily requires a JSContext for historical reasons.
@@ -3136,21 +3101,17 @@ nsContentUtils::LogMessageToConsole(cons
}
bool
nsContentUtils::IsChromeDoc(nsIDocument *aDocument)
{
if (!aDocument) {
return false;
}
-
- nsCOMPtr<nsIPrincipal> systemPrincipal;
- sSecurityManager->GetSystemPrincipal(getter_AddRefs(systemPrincipal));
-
- return aDocument->NodePrincipal() == systemPrincipal;
+ return aDocument->NodePrincipal() == sSystemPrincipal;
}
bool
nsContentUtils::IsChildOfSameType(nsIDocument* aDoc)
{
nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(aDoc->GetDocShell());
nsCOMPtr<nsIDocShellTreeItem> sameTypeParent;
if (docShellAsItem) {
@@ -4346,20 +4307,17 @@ nsContentUtils::CheckSecurityBeforeLoad(
bool aAllowData,
uint32_t aContentPolicyType,
nsISupports* aContext,
const nsAFlatCString& aMimeGuess,
nsISupports* aExtra)
{
NS_PRECONDITION(aLoadingPrincipal, "Must have a loading principal here");
- bool isSystemPrin = false;
- if (NS_SUCCEEDED(sSecurityManager->IsSystemPrincipal(aLoadingPrincipal,
- &isSystemPrin)) &&
- isSystemPrin) {
+ if (aLoadingPrincipal == sSystemPrincipal) {
return NS_OK;
}
// XXXbz do we want to fast-path skin stylesheets loading XBL here somehow?
// CheckLoadURIWithPrincipal
nsresult rv = sSecurityManager->
CheckLoadURIWithPrincipal(aLoadingPrincipal, aURIToLoad, aCheckLoadFlags);
NS_ENSURE_SUCCESS(rv, rv);
@@ -4388,36 +4346,30 @@ nsContentUtils::CheckSecurityBeforeLoad(
}
return aLoadingPrincipal->CheckMayLoad(aURIToLoad, true, false);
}
bool
nsContentUtils::IsSystemPrincipal(nsIPrincipal* aPrincipal)
{
- bool isSystem;
- nsresult rv = sSecurityManager->IsSystemPrincipal(aPrincipal, &isSystem);
- return NS_SUCCEEDED(rv) && isSystem;
+ return aPrincipal == sSystemPrincipal;
}
bool
nsContentUtils::IsExpandedPrincipal(nsIPrincipal* aPrincipal)
{
nsCOMPtr<nsIExpandedPrincipal> ep = do_QueryInterface(aPrincipal);
return !!ep;
}
nsIPrincipal*
nsContentUtils::GetSystemPrincipal()
{
- nsCOMPtr<nsIPrincipal> sysPrin;
- DebugOnly<nsresult> rv =
- sSecurityManager->GetSystemPrincipal(getter_AddRefs(sysPrin));
- MOZ_ASSERT(NS_SUCCEEDED(rv) && sysPrin);
- return sysPrin;
+ return sSystemPrincipal;
}
bool
nsContentUtils::CombineResourcePrincipals(nsCOMPtr<nsIPrincipal>* aResourcePrincipal,
nsIPrincipal* aExtraPrincipal)
{
if (!aExtraPrincipal) {
return false;
@@ -4429,17 +4381,17 @@ nsContentUtils::CombineResourcePrincipal
if (*aResourcePrincipal == aExtraPrincipal) {
return false;
}
bool subsumes;
if (NS_SUCCEEDED((*aResourcePrincipal)->Subsumes(aExtraPrincipal, &subsumes)) &&
subsumes) {
return false;
}
- sSecurityManager->GetSystemPrincipal(getter_AddRefs(*aResourcePrincipal));
+ *aResourcePrincipal = sSystemPrincipal;
return true;
}
/* static */
void
nsContentUtils::TriggerLink(nsIContent *aContent, nsPresContext *aPresContext,
nsIURI *aLinkURI, const nsString &aTargetSpec,
bool aClick, bool aIsUserTriggered,
@@ -6101,30 +6053,20 @@ nsContentUtils::FindInternalContentViewe
return nullptr;
}
bool
nsContentUtils::GetContentSecurityPolicy(JSContext* aCx,
nsIContentSecurityPolicy** aCSP)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-
- // Get the security manager
- nsCOMPtr<nsIScriptSecurityManager> ssm = nsContentUtils::GetSecurityManager();
-
- if (!ssm) {
- NS_ERROR("Failed to get security manager service");
- return false;
- }
-
- nsCOMPtr<nsIPrincipal> subjectPrincipal = ssm->GetCxSubjectPrincipal(aCx);
- NS_ASSERTION(subjectPrincipal, "Failed to get subjectPrincipal");
+ MOZ_ASSERT(aCx == GetCurrentJSContext());
nsCOMPtr<nsIContentSecurityPolicy> csp;
- nsresult rv = subjectPrincipal->GetCsp(getter_AddRefs(csp));
+ nsresult rv = GetSubjectPrincipal()->GetCsp(getter_AddRefs(csp));
if (NS_FAILED(rv)) {
NS_ERROR("CSP: Failed to get CSP from principal.");
return false;
}
csp.forget(aCSP);
return true;
}
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -6330,33 +6330,23 @@ nsIDocument::LoadBindingDocument(const n
nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), aURI,
mCharacterSet.get(),
GetDocBaseURI());
if (rv.Failed()) {
return;
}
- // Figure out the right principal to use
- nsCOMPtr<nsIPrincipal> subject;
- nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
- if (secMan) {
- rv = secMan->GetSubjectPrincipal(getter_AddRefs(subject));
- if (rv.Failed()) {
- return;
- }
- }
-
- if (!subject) {
- // Fall back to our principal. Or should we fall back to the null
- // principal? The latter would just mean no binding loads....
- subject = NodePrincipal();
- }
-
- BindingManager()->LoadBindingDocument(this, uri, subject);
+ // Note - This computation of subjectPrincipal isn't necessarily sensical.
+ // It's just designed to preserve the old semantics during a mass-conversion
+ // patch.
+ nsCOMPtr<nsIPrincipal> subjectPrincipal =
+ nsContentUtils::GetCurrentJSContext() ? nsContentUtils::GetSubjectPrincipal()
+ : NodePrincipal();
+ BindingManager()->LoadBindingDocument(this, uri, subjectPrincipal);
}
NS_IMETHODIMP
nsDocument::GetBindingParent(nsIDOMNode* aNode, nsIDOMElement** aResult)
{
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
NS_ENSURE_ARG_POINTER(node);
--- a/content/base/test/chrome/test_bug391728.html
+++ b/content/base/test/chrome/test_bug391728.html
@@ -113,17 +113,17 @@ function load_frame(nextTest, file) {
frame.src = file + ".html?" + Math.random();
}
function next_text() {
PluginUtils.withTestPlugin(gNextTest);
}
function frame_loaded() {
- // We must delay to wait for the plugin sources to be loaded :(
+ SimpleTest.requestFlakyTimeout("We must delay to wait for the plugin sources to be loaded :(");
setTimeout(next_text, 500);
}
function test_style(expected) {
var frame = document.getElementById("testframe");
for (var i = 1; i <= PLUGIN_COUNT; i++) {
var tag = frame.contentDocument.getElementById("plugin" + i);
ok(tag, "Plugin " + i + " did not exist");
--- a/content/base/test/test_CrossSiteXHR_cache.html
+++ b/content/base/test/test_CrossSiteXHR_cache.html
@@ -12,16 +12,17 @@
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="application/javascript;version=1.7">
SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("This test needs to generate artificial pauses, hence it uses timeouts. There is no way around it, unfortunately. :(");
window.addEventListener("message", function(e) {
gen.send(e.data);
}, false);
gen = runTest();
function runTest() {
--- a/content/base/test/test_websocket.html
+++ b/content/base/test/test_websocket.html
@@ -174,17 +174,17 @@ function CreateTestWS(ws_location, ws_pr
function forcegc()
{
SpecialPowers.forceGC();
SpecialPowers.gc();
setTimeout(function()
{
SpecialPowers.gc();
- }, 1);
+ }, 0);
}
function doTest(number)
{
if (number > last_test) {
ranAllTests = true;
maybeFinished();
return;
@@ -1493,16 +1493,18 @@ function maybeFinished()
}
}
function testWebSocket ()
{
doTest(first_test);
}
+SimpleTest.requestFlakyTimeout("The web socket tests are really fragile, but avoiding timeouts might be hard, since it's testing stuff on the network. " +
+ "Expect all sorts of flakiness in this test...");
SimpleTest.waitForExplicitFinish();
</script>
</pre>
<div id="feedback">
</div>
--- a/content/canvas/test/webgl-conformance/test_webgl_conformance_test_suite.html
+++ b/content/canvas/test/webgl-conformance/test_webgl_conformance_test_suite.html
@@ -462,16 +462,17 @@ function start() {
},
OPTIONS);
// Make timeout delay much higher when running under valgrind.
testHarness.setTimeoutDelay(20000);
window.webglTestHarness = testHarness;
}
SimpleTest.requestLongerTimeout(requestLongerTimeoutLen);
+ SimpleTest.requestFlakyTimeout("We're embedding the WebGL test harness, which uses timeouts internally, so we have to abide. :(");
var statusElem = document.getElementById("status");
var statusTextNode = document.createTextNode('');
statusElem.appendChild(statusTextNode);
var expectedtofailElem = document.getElementById("expectedtofail");
var expectedtofailTextNode = document.createTextNode('');
expectedtofailElem.appendChild(expectedtofailTextNode);
--- a/content/html/content/src/HTMLOptionElement.cpp
+++ b/content/html/content/src/HTMLOptionElement.cpp
@@ -238,16 +238,35 @@ HTMLOptionElement::BeforeSetAttr(int32_t
mIsInSetDefaultSelected = inSetDefaultSelected;
// mIsSelected might have been changed by SetOptionsSelectedByIndex. Possibly
// more than once; make sure our mSelectedChanged state is set correctly.
mSelectedChanged = mIsSelected != defaultSelected;
return NS_OK;
}
+nsresult
+HTMLOptionElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+ const nsAttrValue* aValue, bool aNotify)
+{
+ if (aNameSpaceID == kNameSpaceID_None &&
+ aName == nsGkAtoms::value && Selected()) {
+ // Since this option is selected, changing value
+ // may have changed missing validity state of the
+ // Select element
+ HTMLSelectElement* select = GetSelect();
+ if (select) {
+ select->UpdateValueMissingValidityState();
+ }
+ }
+
+ return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
+ aValue, aNotify);
+}
+
NS_IMETHODIMP
HTMLOptionElement::GetText(nsAString& aText)
{
nsAutoString text;
nsIContent* child = nsINode::GetFirstChild();
while (child) {
if (child->NodeType() == nsIDOMNode::TEXT_NODE ||
--- a/content/html/content/src/HTMLOptionElement.h
+++ b/content/html/content/src/HTMLOptionElement.h
@@ -46,16 +46,18 @@ public:
bool DefaultSelected() const;
virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
int32_t aModType) const MOZ_OVERRIDE;
virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
const nsAttrValueOrString* aValue,
bool aNotify) MOZ_OVERRIDE;
+ virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+ const nsAttrValue* aValue, bool aNotify) MOZ_OVERRIDE;
void SetSelectedInternal(bool aValue, bool aNotify);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
bool aCompileEventHandlers) MOZ_OVERRIDE;
virtual void UnbindFromTree(bool aDeep = true,
bool aNullParent = true) MOZ_OVERRIDE;
--- a/content/html/content/src/HTMLSelectElement.h
+++ b/content/html/content/src/HTMLSelectElement.h
@@ -390,16 +390,17 @@ public:
{
return mOptions;
}
// nsIConstraintValidation
nsresult GetValidationMessage(nsAString& aValidationMessage,
ValidityStateType aType) MOZ_OVERRIDE;
+ void UpdateValueMissingValidityState();
/**
* Insert aElement before the node given by aBefore
*/
void Add(nsGenericHTMLElement& aElement, nsGenericHTMLElement* aBefore,
ErrorResult& aError);
void Add(nsGenericHTMLElement& aElement, int32_t aIndex, ErrorResult& aError)
{
// If item index is out of range, insert to last.
@@ -506,17 +507,16 @@ protected:
nsresult RemoveOptionsFromListRecurse(nsIContent* aOptions,
int32_t aRemoveIndex,
int32_t* aNumRemoved,
int32_t aDepth);
// nsIConstraintValidation
void UpdateBarredFromConstraintValidation();
bool IsValueMissing();
- void UpdateValueMissingValidityState();
/**
* Find out how deep this content is from the select (1=direct child)
* @param aContent the content to check
* @return the depth
*/
int32_t GetContentDepth(nsIContent* aContent);
/**
--- a/content/html/content/test/forms/mochitest.ini
+++ b/content/html/content/test/forms/mochitest.ini
@@ -69,16 +69,17 @@ skip-if = e10s
[test_output_element.html]
[test_pattern_attribute.html]
[test_progress_element.html]
[test_required_attribute.html]
skip-if = e10s
[test_restore_form_elements.html]
[test_save_restore_radio_groups.html]
[test_select_selectedOptions.html]
+[test_select_validation.html]
[test_set_range_text.html]
[test_step_attribute.html]
skip-if = e10s
[test_stepup_stepdown.html]
[test_submit_invalid_file.html]
[test_textarea_attributes_reflection.html]
[test_validation.html]
skip-if = buildapp == 'b2g' || e10s # b2g(374 total, bug 901848, no keygen support) b2g-debug(374 total, bug 901848, no keygen support) b2g-desktop(374 total, bug 901848, no keygen support)
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/forms/test_select_validation.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=942321
+-->
+<head>
+ <title>Test for Bug 942321</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=942321">Mozilla Bug 942321</a>
+<p id="display"></p>
+<form id="form" href="">
+ <select required id="testselect">
+ <option id="placeholder" value="" selected>placeholder</option>
+ <option value="test" id="actualvalue">test</option>
+ <select>
+ <input type="submit" />
+</form>
+<script class="testbody" type="text/javascript">
+/** Test for Bug 942321 **/
+var option = document.getElementById("actualvalue");
+option.selected = true;
+is(form.checkValidity(), true, "Select is required and should be valid");
+
+var placeholder = document.getElementById("placeholder");
+placeholder.selected = true;
+is(form.checkValidity(), false, "Select is required and should be invalid");
+
+placeholder.value = "not-invalid-anymore";
+is(form.checkValidity(), true, "Select is required and should be valid when option's value is changed by javascript");
+</script>
+</pre>
+</body>
+</html>
+
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -2844,37 +2844,20 @@ nsHTMLDocument::SetDesignMode(const nsAS
ErrorResult rv;
SetDesignMode(aDesignMode, rv);
return rv.ErrorCode();
}
void
nsHTMLDocument::SetDesignMode(const nsAString& aDesignMode, ErrorResult& rv)
{
- if (!nsContentUtils::IsCallerChrome()) {
- nsCOMPtr<nsIPrincipal> subject;
- nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
- rv = secMan->GetSubjectPrincipal(getter_AddRefs(subject));
- if (rv.Failed()) {
- return;
- }
- if (subject) {
- bool subsumes;
- rv = subject->Subsumes(NodePrincipal(), &subsumes);
- if (rv.Failed()) {
- return;
- }
-
- if (!subsumes) {
- rv.Throw(NS_ERROR_DOM_PROP_ACCESS_DENIED);
- return;
- }
- }
+ if (!nsContentUtils::GetSubjectPrincipal()->Subsumes(NodePrincipal())) {
+ rv.Throw(NS_ERROR_DOM_PROP_ACCESS_DENIED);
+ return;
}
-
bool editableMode = HasFlag(NODE_IS_EDITABLE);
if (aDesignMode.LowerCaseEqualsASCII(editableMode ? "off" : "on")) {
SetEditableFlag(!editableMode);
rv = EditingStateChanged();
}
}
--- a/content/media/MediaDecoderStateMachine.cpp
+++ b/content/media/MediaDecoderStateMachine.cpp
@@ -1444,17 +1444,17 @@ void MediaDecoderStateMachine::Seek(cons
int64_t seekTime = aTarget.mTime + mStartTime;
seekTime = std::min(seekTime, mEndTime);
seekTime = std::max(mStartTime, seekTime);
NS_ASSERTION(seekTime >= mStartTime && seekTime <= mEndTime,
"Can only seek in range [0,duration]");
mSeekTarget = SeekTarget(seekTime, aTarget.mType);
mBasePosition = seekTime - mStartTime;
- DECODER_LOG(PR_LOG_DEBUG, "Changed state to SEEKING (to %ld)", mSeekTarget.mTime);
+ DECODER_LOG(PR_LOG_DEBUG, "Changed state to SEEKING (to %lld)", mSeekTarget.mTime);
mState = DECODER_STATE_SEEKING;
if (mDecoder->GetDecodedStream()) {
mDecoder->RecreateDecodedStream(seekTime - mStartTime);
}
ScheduleStateMachine();
}
void MediaDecoderStateMachine::StopAudioThread()
--- a/content/media/omx/MediaOmxReader.h
+++ b/content/media/omx/MediaOmxReader.h
@@ -10,17 +10,17 @@
#include "MediaDecoderReader.h"
#include "nsRect.h"
#include "mozilla/dom/AudioChannelBinding.h"
#include <ui/GraphicBuffer.h>
#include <stagefright/MediaSource.h>
namespace android {
class OmxDecoder;
-class MediaExtractor;
+class MOZ_EXPORT MediaExtractor;
}
namespace mozilla {
namespace dom {
class TimeRanges;
}
--- a/content/media/omx/OMXCodecProxy.h
+++ b/content/media/omx/OMXCodecProxy.h
@@ -3,17 +3,17 @@
/* 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 OMX_CODEC_PROXY_DECODER_H_
#define OMX_CODEC_PROXY_DECODER_H_
#include <android/native_window.h>
-#include <IOMX.h>
+#include <media/IOMX.h>
#include <stagefright/MediaBuffer.h>
#include <stagefright/MediaSource.h>
#include <utils/threads.h>
#include "MediaResourceManagerClient.h"
namespace android {
--- a/content/media/plugins/MediaPluginReader.cpp
+++ b/content/media/plugins/MediaPluginReader.cpp
@@ -318,18 +318,18 @@ bool MediaPluginReader::DecodeAudioData(
source.mSize,
source.mAudioChannels));
}
nsresult MediaPluginReader::Seek(int64_t aTarget, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime)
{
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
- mVideoQueue.Erase();
- mAudioQueue.Erase();
+ mVideoQueue.Reset();
+ mAudioQueue.Reset();
mAudioSeekTimeUs = mVideoSeekTimeUs = aTarget;
return NS_OK;
}
MediaPluginReader::ImageBufferCallback::ImageBufferCallback(mozilla::layers::ImageContainer *aImageContainer) :
mImageContainer(aImageContainer)
--- a/content/media/raw/RawReader.cpp
+++ b/content/media/raw/RawReader.cpp
@@ -243,17 +243,17 @@ nsresult RawReader::Seek(int64_t aTime,
CheckedUint32 offset = CheckedUint32(mCurrentFrame) * mFrameSize;
offset += sizeof(RawVideoHeader);
NS_ENSURE_TRUE(offset.isValid(), NS_ERROR_FAILURE);
nsresult rv = resource->Seek(nsISeekableStream::NS_SEEK_SET, offset.value());
NS_ENSURE_SUCCESS(rv, rv);
- mVideoQueue.Erase();
+ mVideoQueue.Reset();
while(mVideoQueue.GetSize() == 0) {
bool keyframeSkip = false;
if (!DecodeVideoFrame(keyframeSkip, 0)) {
mCurrentFrame = frame;
return NS_ERROR_FAILURE;
}
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -1550,18 +1550,17 @@ nsDocShell::LoadURI(nsIURI * aURI,
return NS_ERROR_DOM_SECURITY_ERR;
}
owner = nullptr;
inheritOwner = true;
}
}
if (!owner && !inheritOwner && !ownerIsExplicit) {
// See if there's system or chrome JS code running
- inheritOwner = nsContentUtils::IsSystemPrincipal(
- nsContentUtils::GetSubjectPrincipal());
+ inheritOwner = nsContentUtils::IsCallerChrome();
}
if (aLoadFlags & LOAD_FLAGS_DISALLOW_INHERIT_OWNER) {
inheritOwner = false;
owner = do_CreateInstance("@mozilla.org/nullprincipal;1");
}
uint32_t flags = 0;
@@ -8640,67 +8639,53 @@ nsDocShell::CheckLoadingPermissions()
{
// This method checks whether the caller may load content into
// this docshell. Even though we've done our best to hide windows
// from code that doesn't have the right to access them, it's
// still possible for an evil site to open a window and access
// frames in the new window through window.frames[] (which is
// allAccess for historic reasons), so we still need to do this
// check on load.
- nsresult rv = NS_OK, sameOrigin = NS_OK;
+ nsresult rv = NS_OK;
if (!gValidateOrigin || !IsFrame()) {
// Origin validation was turned off, or we're not a frame.
// Permit all loads.
return rv;
}
- nsCOMPtr<nsIScriptSecurityManager> securityManager =
- do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // We're a frame. Check that the caller has write permission to
- // the parent before allowing it to load anything into this
- // docshell.
- nsCOMPtr<nsIPrincipal> subjPrincipal;
- rv = securityManager->GetSubjectPrincipal(getter_AddRefs(subjPrincipal));
- NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && subjPrincipal, rv);
+ // Note - The check for a current JSContext here isn't necessarily sensical.
+ // It's just designed to preserve the old semantics during a mass-conversion
+ // patch.
+ NS_ENSURE_TRUE(nsContentUtils::GetCurrentJSContext(), NS_OK);
// Check if the caller is from the same origin as this docshell,
// or any of its ancestors.
nsCOMPtr<nsIDocShellTreeItem> item(this);
do {
nsCOMPtr<nsIScriptGlobalObject> sgo(do_GetInterface(item));
nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(sgo));
nsIPrincipal *p;
if (!sop || !(p = sop->GetPrincipal())) {
return NS_ERROR_UNEXPECTED;
}
- // Compare origins
- bool subsumes;
- sameOrigin = subjPrincipal->Subsumes(p, &subsumes);
- if (NS_SUCCEEDED(sameOrigin)) {
- if (subsumes) {
- // Same origin, permit load
-
- return sameOrigin;
- }
-
- sameOrigin = NS_ERROR_DOM_PROP_ACCESS_DENIED;
+ if (nsContentUtils::GetSubjectPrincipal()->Subsumes(p)) {
+ // Same origin, permit load
+ return NS_OK;
}
nsCOMPtr<nsIDocShellTreeItem> tmp;
item->GetSameTypeParent(getter_AddRefs(tmp));
item.swap(tmp);
} while (item);
- return sameOrigin;
+ return NS_ERROR_DOM_PROP_ACCESS_DENIED;
}
//*****************************************************************************
// nsDocShell: Site Loading
//*****************************************************************************
namespace
{
--- a/dom/asmjscache/AsmJSCache.cpp
+++ b/dom/asmjscache/AsmJSCache.cpp
@@ -1624,18 +1624,17 @@ OpenEntryForRead(nsIPrincipal* aPrincipa
// The caller guarnatees a call to CloseEntryForRead (on success or
// failure) at which point the file will be closed.
file.Forget(reinterpret_cast<File**>(aFile));
return true;
}
void
-CloseEntryForRead(JS::Handle<JSObject*> global,
- size_t aSize,
+CloseEntryForRead(size_t aSize,
const uint8_t* aMemory,
intptr_t aFile)
{
File::AutoClose file(reinterpret_cast<File*>(aFile));
MOZ_ASSERT(aSize + sizeof(AsmJSCookieType) == file->FileSize());
MOZ_ASSERT(aMemory - sizeof(AsmJSCookieType) == file->MappedMemory());
}
@@ -1678,18 +1677,17 @@ OpenEntryForWrite(nsIPrincipal* aPrincip
// The caller guarnatees a call to CloseEntryForWrite (on success or
// failure) at which point the file will be closed
file.Forget(reinterpret_cast<File**>(aFile));
return true;
}
void
-CloseEntryForWrite(JS::Handle<JSObject*> global,
- size_t aSize,
+CloseEntryForWrite(size_t aSize,
uint8_t* aMemory,
intptr_t aFile)
{
File::AutoClose file(reinterpret_cast<File*>(aFile));
MOZ_ASSERT(aSize + sizeof(AsmJSCookieType) == file->FileSize());
MOZ_ASSERT(aMemory - sizeof(AsmJSCookieType) == file->MappedMemory());
--- a/dom/asmjscache/AsmJSCache.h
+++ b/dom/asmjscache/AsmJSCache.h
@@ -104,31 +104,29 @@ struct ReadParams
bool
OpenEntryForRead(nsIPrincipal* aPrincipal,
const jschar* aBegin,
const jschar* aLimit,
size_t* aSize,
const uint8_t** aMemory,
intptr_t *aHandle);
void
-CloseEntryForRead(JS::Handle<JSObject*> aGlobal,
- size_t aSize,
+CloseEntryForRead(size_t aSize,
const uint8_t* aMemory,
intptr_t aHandle);
bool
OpenEntryForWrite(nsIPrincipal* aPrincipal,
bool aInstalled,
const jschar* aBegin,
const jschar* aEnd,
size_t aSize,
uint8_t** aMemory,
intptr_t* aHandle);
void
-CloseEntryForWrite(JS::Handle<JSObject*> aGlobal,
- size_t aSize,
+CloseEntryForWrite(size_t aSize,
uint8_t* aMemory,
intptr_t aHandle);
bool
GetBuildId(JS::BuildIdCharVector* aBuildId);
// Called from QuotaManager.cpp:
--- a/dom/base/URL.cpp
+++ b/dom/base/URL.cpp
@@ -226,17 +226,17 @@ URL::SetHref(const nsAString& aHref, Err
nsCOMPtr<nsIURI> uri;
rv = ioService->NewURI(href, nullptr, nullptr, getter_AddRefs(uri));
if (NS_FAILED(rv)) {
nsAutoString label(aHref);
aRv.ThrowTypeError(MSG_INVALID_URL, &label);
return;
}
- aRv = mURI->SetSpec(href);
+ mURI = uri;
UpdateURLSearchParams();
}
void
URL::GetOrigin(nsString& aOrigin) const
{
nsContentUtils::GetUTFNonNullOrigin(mURI, aOrigin);
}
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -2009,19 +2009,16 @@ nsGlobalWindow::WouldReuseInnerWindow(ns
void
nsGlobalWindow::SetInitialPrincipalToSubject()
{
FORWARD_TO_OUTER_VOID(SetInitialPrincipalToSubject, ());
// First, grab the subject principal.
nsCOMPtr<nsIPrincipal> newWindowPrincipal = nsContentUtils::GetSubjectPrincipal();
- if (!newWindowPrincipal) {
- newWindowPrincipal = nsContentUtils::GetSystemPrincipal();
- }
// Now, if we're about to use the system principal or an nsExpandedPrincipal,
// make sure we're not using it for a content docshell.
if (nsContentUtils::IsSystemOrExpandedPrincipal(newWindowPrincipal) &&
GetDocShell()->ItemType() != nsIDocShellTreeItem::typeChrome) {
newWindowPrincipal = nullptr;
}
@@ -6050,63 +6047,52 @@ nsGlobalWindow::SetTextZoom(float aZoom)
void
nsGlobalWindow::MakeScriptDialogTitle(nsAString &aOutTitle)
{
aOutTitle.Truncate();
// Try to get a host from the running principal -- this will do the
// right thing for javascript: and data: documents.
- nsresult rv = NS_OK;
- NS_ASSERTION(nsContentUtils::GetSecurityManager(),
- "Global Window has no security manager!");
- if (nsContentUtils::GetSecurityManager()) {
- nsCOMPtr<nsIPrincipal> principal;
- rv = nsContentUtils::GetSecurityManager()->
- GetSubjectPrincipal(getter_AddRefs(principal));
-
- if (NS_SUCCEEDED(rv) && principal) {
- nsCOMPtr<nsIURI> uri;
- rv = principal->GetURI(getter_AddRefs(uri));
-
- if (NS_SUCCEEDED(rv) && uri) {
- // remove user:pass for privacy and spoof prevention
-
- nsCOMPtr<nsIURIFixup> fixup(do_GetService(NS_URIFIXUP_CONTRACTID));
- if (fixup) {
- nsCOMPtr<nsIURI> fixedURI;
- rv = fixup->CreateExposableURI(uri, getter_AddRefs(fixedURI));
- if (NS_SUCCEEDED(rv) && fixedURI) {
- nsAutoCString host;
- fixedURI->GetHost(host);
-
- if (!host.IsEmpty()) {
- // if this URI has a host we'll show it. For other
- // schemes (e.g. file:) we fall back to the localized
- // generic string
-
- nsAutoCString prepath;
- fixedURI->GetPrePath(prepath);
-
- NS_ConvertUTF8toUTF16 ucsPrePath(prepath);
- const char16_t *formatStrings[] = { ucsPrePath.get() };
- nsXPIDLString tempString;
- nsContentUtils::FormatLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
- "ScriptDlgHeading",
- formatStrings,
- tempString);
- aOutTitle = tempString;
- }
- }
+ nsCOMPtr<nsIPrincipal> principal = nsContentUtils::GetSubjectPrincipal();
+ nsCOMPtr<nsIURI> uri;
+ nsresult rv = principal->GetURI(getter_AddRefs(uri));
+ // Note - The check for the current JSContext here isn't necessarily sensical.
+ // It's just designed to preserve existing behavior during a mass-conversion
+ // patch.
+ if (NS_SUCCEEDED(rv) && uri && nsContentUtils::GetCurrentJSContext()) {
+ // remove user:pass for privacy and spoof prevention
+
+ nsCOMPtr<nsIURIFixup> fixup(do_GetService(NS_URIFIXUP_CONTRACTID));
+ if (fixup) {
+ nsCOMPtr<nsIURI> fixedURI;
+ rv = fixup->CreateExposableURI(uri, getter_AddRefs(fixedURI));
+ if (NS_SUCCEEDED(rv) && fixedURI) {
+ nsAutoCString host;
+ fixedURI->GetHost(host);
+
+ if (!host.IsEmpty()) {
+ // if this URI has a host we'll show it. For other
+ // schemes (e.g. file:) we fall back to the localized
+ // generic string
+
+ nsAutoCString prepath;
+ fixedURI->GetPrePath(prepath);
+
+ NS_ConvertUTF8toUTF16 ucsPrePath(prepath);
+ const char16_t *formatStrings[] = { ucsPrePath.get() };
+ nsXPIDLString tempString;
+ nsContentUtils::FormatLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
+ "ScriptDlgHeading",
+ formatStrings,
+ tempString);
+ aOutTitle = tempString;
}
}
}
- else { // failed to get subject principal
- NS_WARNING("No script principal? Who is calling alert/confirm/prompt?!");
- }
}
if (aOutTitle.IsEmpty()) {
// We didn't find a host so use the generic heading
nsXPIDLString tempString;
nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
"ScriptDlgGenericHeading",
tempString);
@@ -11688,53 +11674,40 @@ nsGlobalWindow::SetTimeoutOrInterval(nsI
// now...
realInterval = std::max(realInterval, uint32_t(DOMMinTimeoutValue()));
}
// Get principal of currently executing code, save for execution of timeout.
// If our principals subsume the subject principal then use the subject
// principal. Otherwise, use our principal to avoid running script in
// elevated principals.
-
- nsCOMPtr<nsIPrincipal> subjectPrincipal;
- nsresult rv;
- rv = nsContentUtils::GetSecurityManager()->
- GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
- if (NS_FAILED(rv)) {
- return NS_ERROR_FAILURE;
- }
-
- bool subsumes = false;
- nsCOMPtr<nsIPrincipal> ourPrincipal = GetPrincipal();
-
+ //
// Note the direction of this test: We don't allow setTimeouts running with
// chrome privileges on content windows, but we do allow setTimeouts running
// with content privileges on chrome windows (where they can't do very much,
// of course).
- rv = ourPrincipal->Subsumes(subjectPrincipal, &subsumes);
- if (NS_FAILED(rv)) {
- return NS_ERROR_FAILURE;
- }
-
- if (subsumes) {
+ nsCOMPtr<nsIPrincipal> subjectPrincipal = nsContentUtils::GetSubjectPrincipal();
+ nsCOMPtr<nsIPrincipal> ourPrincipal = GetPrincipal();
+ if (ourPrincipal->Subsumes(subjectPrincipal)) {
timeout->mPrincipal = subjectPrincipal;
} else {
timeout->mPrincipal = ourPrincipal;
}
++gTimeoutsRecentlySet;
TimeDuration delta = TimeDuration::FromMilliseconds(realInterval);
if (!IsFrozen() && !mTimeoutsSuspendDepth) {
// If we're not currently frozen, then we set timeout->mWhen to be the
// actual firing time of the timer (i.e., now + delta). We also actually
// create a timer and fire it off.
timeout->mWhen = TimeStamp::Now() + delta;
+ nsresult rv;
timeout->mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
if (NS_FAILED(rv)) {
return rv;
}
nsRefPtr<nsTimeout> copy = timeout;
rv = timeout->InitTimer(TimerCallback, realInterval);
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -2084,22 +2084,22 @@ nsJSContext::EndCycleCollectionCallback(
}
nsCString gcMsg;
if (aResults.mForcedGC) {
gcMsg.AssignLiteral(", forced a GC");
}
NS_NAMED_MULTILINE_LITERAL_STRING(kFmt,
- MOZ_UTF16("CC(T+%.1f) max pause: %lums, total time: %lums, suspected: %lu, visited: %lu RCed and %lu%s GCed, collected: %lu RCed and %lu GCed (%lu|%lu waiting for GC)%s\n")
+ MOZ_UTF16("CC(T+%.1f) max pause: %lums, total time: %lums, slices: %lu, suspected: %lu, visited: %lu RCed and %lu%s GCed, collected: %lu RCed and %lu GCed (%lu|%lu waiting for GC)%s\n")
MOZ_UTF16("ForgetSkippable %lu times before CC, min: %lu ms, max: %lu ms, avg: %lu ms, total: %lu ms, max sync: %lu ms, removed: %lu"));
nsString msg;
msg.Adopt(nsTextFormatter::smprintf(kFmt.get(), double(delta) / PR_USEC_PER_SEC,
gCCStats.mMaxSliceTime, gCCStats.mTotalSliceTime,
- gCCStats.mSuspected,
+ aResults.mNumSlices, gCCStats.mSuspected,
aResults.mVisitedRefCounted, aResults.mVisitedGCed, mergeMsg.get(),
aResults.mFreedRefCounted, aResults.mFreedGCed,
sCCollectedWaitingForGC, sLikelyShortLivingObjectsNeedingGC,
gcMsg.get(),
sForgetSkippableBeforeCC,
minForgetSkippableTime / PR_USEC_PER_MSEC,
sMaxForgetSkippableTime / PR_USEC_PER_MSEC,
(sTotalForgetSkippableTime / cleanups) /
--- a/dom/base/nsLocation.cpp
+++ b/dom/base/nsLocation.cpp
@@ -155,17 +155,17 @@ nsLocation::CheckURL(nsIURI* aURI, nsIDo
rv = principalURI->SchemeIs(NS_NULLPRINCIPAL_SCHEME,
&isNullPrincipalScheme);
if (NS_SUCCEEDED(rv) && !isNullPrincipalScheme) {
sourceURI = principalURI;
}
}
}
- owner = do_QueryInterface(ssm->GetCxSubjectPrincipal(cx));
+ owner = nsContentUtils::GetSubjectPrincipal();
}
// Create load info
nsCOMPtr<nsIDocShellLoadInfo> loadInfo;
docShell->CreateLoadInfo(getter_AddRefs(loadInfo));
NS_ENSURE_TRUE(loadInfo, NS_ERROR_FAILURE);
loadInfo->SetOwner(owner);
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -2323,16 +2323,18 @@ class CGCreateInterfaceObjectsMethod(CGA
CGAbstractMethod.__init__(self, descriptor, 'CreateInterfaceObjects', 'void', args)
self.properties = properties
def definition_body(self):
if len(self.descriptor.prototypeChain) == 1:
parentProtoType = "Rooted"
if self.descriptor.interface.getExtendedAttribute("ArrayClass"):
getParentProto = "aCx, JS_GetArrayPrototype(aCx, aGlobal)"
+ elif self.descriptor.interface.getExtendedAttribute("ExceptionClass"):
+ getParentProto = "aCx, JS_GetErrorPrototype(aCx)"
else:
getParentProto = "aCx, JS_GetObjectPrototype(aCx, aGlobal)"
else:
parentProtoName = self.descriptor.prototypeChain[-2]
parentDesc = self.descriptor.getDescriptor(parentProtoName)
if parentDesc.workers:
parentProtoName += '_workers'
getParentProto = ("%s::GetProtoObject(aCx, aGlobal)" %
--- a/dom/bindings/Exceptions.cpp
+++ b/dom/bindings/Exceptions.cpp
@@ -13,36 +13,16 @@
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/DOMException.h"
#include "nsServiceManagerUtils.h"
#include "nsThreadUtils.h"
#include "XPCWrapper.h"
#include "WorkerPrivate.h"
#include "nsContentUtils.h"
-namespace {
-
-// We can't use nsContentUtils::IsCallerChrome because it might not exist in
-// xpcshell.
-bool
-IsCallerChrome()
-{
- nsCOMPtr<nsIScriptSecurityManager> secMan;
- secMan = XPCWrapper::GetSecurityManager();
-
- if (!secMan) {
- return false;
- }
-
- bool isChrome;
- return NS_SUCCEEDED(secMan->SubjectPrincipalIsSystem(&isChrome)) && isChrome;
-}
-
-} // anonymous namespace
-
namespace mozilla {
namespace dom {
bool
ThrowExceptionObject(JSContext* aCx, nsIException* aException)
{
// See if we really have an Exception.
nsCOMPtr<Exception> exception = do_QueryInterface(aException);
@@ -75,17 +55,17 @@ ThrowExceptionObject(JSContext* aCx, Exc
{
JS::Rooted<JS::Value> thrown(aCx);
// If we stored the original thrown JS value in the exception
// (see XPCConvert::ConstructException) and we are in a web context
// (i.e., not chrome), rethrow the original value. This only applies to JS
// implemented components so we only need to check for this on the main
// thread.
- if (NS_IsMainThread() && !IsCallerChrome() &&
+ if (NS_IsMainThread() && !nsContentUtils::IsCallerChrome() &&
aException->StealJSVal(thrown.address())) {
if (!JS_WrapValue(aCx, &thrown)) {
return false;
}
JS_SetPendingException(aCx, thrown);
return true;
}
@@ -168,24 +148,18 @@ CreateException(JSContext* aCx, nsresult
already_AddRefed<nsIStackFrame>
GetCurrentJSStack()
{
// is there a current context available?
JSContext* cx = nullptr;
if (NS_IsMainThread()) {
- // Note, in xpcshell nsContentUtils is never initialized, but we still need
- // to report exceptions.
- if (nsContentUtils::XPConnect()) {
- cx = nsContentUtils::XPConnect()->GetCurrentJSContext();
- } else {
- nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID());
- cx = xpc->GetCurrentJSContext();
- }
+ MOZ_ASSERT(nsContentUtils::XPConnect());
+ cx = nsContentUtils::GetCurrentJSContext();
} else {
cx = workers::GetCurrentThreadJSContext();
}
if (!cx) {
return nullptr;
}
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -264,16 +264,24 @@ class IDLScope(IDLObject):
if (isinstance(originalObject, IDLExternalInterface) or
isinstance(newObject, IDLExternalInterface)):
raise WebIDLError(
"Name collision between "
"interface declarations for identifier '%s' at '%s' and '%s'"
% (identifier.name,
originalObject.location, newObject.location), [])
+ if (isinstance(originalObject, IDLDictionary) or
+ isinstance(newObject, IDLDictionary)):
+ raise WebIDLError(
+ "Name collision between dictionary declarations for "
+ "identifier '%s'.\n%s\n%s"
+ % (identifier.name,
+ originalObject.location, newObject.location), [])
+
# We do the merging of overloads here as opposed to in IDLInterface
# because we need to merge overloads of NamedConstructors and we need to
# detect conflicts in those across interfaces. See also the comment in
# IDLInterface.addExtendedAttributes for "NamedConstructor".
if originalObject.tag == IDLInterfaceMember.Tags.Method and \
newObject.tag == IDLInterfaceMember.Tags.Method:
return originalObject.addOverload(newObject)
@@ -908,17 +916,17 @@ class IDLInterface(IDLObjectWithScope):
if identifier == "ChromeConstructor" and not self.hasInterfaceObject():
raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible",
[self.location])
args = attr.args() if attr.hasArgs() else []
retType = IDLWrapperType(self.location, self)
-
+
if identifier == "Constructor" or identifier == "ChromeConstructor":
name = "constructor"
allowForbidden = True
else:
name = attr.value()
allowForbidden = False
methodIdentifier = IDLUnresolvedIdentifier(self.location, name,
@@ -963,16 +971,24 @@ class IDLInterface(IDLObjectWithScope):
elif (identifier == "ArrayClass"):
if not attr.noArguments():
raise WebIDLError("[ArrayClass] must take no arguments",
[attr.location])
if self.parent:
raise WebIDLError("[ArrayClass] must not be specified on "
"an interface with inherited interfaces",
[attr.location, self.location])
+ elif (identifier == "ExceptionClass"):
+ if not attr.noArguments():
+ raise WebIDLError("[ExceptionClass] must take no arguments",
+ [attr.location])
+ if self.parent:
+ raise WebIDLError("[ExceptionClass] must not be specified on "
+ "an interface with inherited interfaces",
+ [attr.location, self.location])
elif identifier == "Global":
if not attr.noArguments():
raise WebIDLError("[Global] must take no arguments",
[attr.location])
self._isOnGlobalProtoChain = True
elif (identifier == "NeedNewResolve" or
identifier == "OverrideBuiltins" or
identifier == "ChromeOnly"):
@@ -1439,17 +1455,17 @@ class IDLType(IDLObject):
return self
def isDistinguishableFrom(self, other):
raise TypeError("Can't tell whether a generic type is or is not "
"distinguishable from other things")
class IDLUnresolvedType(IDLType):
"""
- Unresolved types are interface types
+ Unresolved types are interface types
"""
def __init__(self, location, name):
IDLType.__init__(self, location, name)
def isComplete(self):
return False
@@ -3654,17 +3670,17 @@ class Parser(Tokenizer):
return Location(self.lexer, p.lineno(i), p.lexpos(i), self._filename)
def globalScope(self):
return self._globalScope
# The p_Foo functions here must match the WebIDL spec's grammar.
# It's acceptable to split things at '|' boundaries.
def p_Definitions(self, p):
- """
+ """
Definitions : ExtendedAttributeList Definition Definitions
"""
if p[2]:
p[0] = [p[2]]
p[2].addExtendedAttributes(p[1])
else:
assert not p[1]
p[0] = []
@@ -4582,17 +4598,17 @@ class Parser(Tokenizer):
"""
UnionMemberTypes : OR UnionMemberType UnionMemberTypes
"""
p[0] = [p[2]]
p[0].extend(p[3])
def p_UnionMemberTypesEmpty(self, p):
"""
- UnionMemberTypes :
+ UnionMemberTypes :
"""
p[0] = []
def p_NonAnyType(self, p):
"""
NonAnyType : PrimitiveOrStringType TypeSuffix
| ARRAYBUFFER TypeSuffix
| OBJECT TypeSuffix
--- a/dom/bluetooth/BluetoothProfileController.cpp
+++ b/dom/bluetooth/BluetoothProfileController.cpp
@@ -64,17 +64,16 @@ BluetoothProfileController::BluetoothPro
{
MOZ_ASSERT(!aDeviceAddress.IsEmpty());
MOZ_ASSERT(aRunnable);
MOZ_ASSERT(aCallback);
mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
MOZ_ASSERT(mTimer);
- mCheckProfileStatusCallback = new CheckProfileStatusCallback(this);
mProfiles.Clear();
/**
* If the service uuid is not specified, either connect multiple profiles
* based on Cod, or disconnect all connected profiles.
*/
if (!aServiceUuid) {
mTarget.cod = aCod;
@@ -220,18 +219,18 @@ BluetoothProfileController::StartSession
if (mProfiles.Length() < 1) {
BT_LOGR("No queued profile.");
EndSession();
return;
}
if (mTimer) {
- mTimer->InitWithCallback(mCheckProfileStatusCallback, CONNECTION_TIMEOUT_MS,
- nsITimer::TYPE_ONE_SHOT);
+ mTimer->InitWithCallback(new CheckProfileStatusCallback(this),
+ CONNECTION_TIMEOUT_MS, nsITimer::TYPE_ONE_SHOT);
}
BT_LOGR("%s", mConnect ? "connecting" : "disconnecting");
Next();
}
void
--- a/dom/bluetooth/BluetoothProfileController.h
+++ b/dom/bluetooth/BluetoothProfileController.h
@@ -134,14 +134,13 @@ private:
// Either CoD or BluetoothServiceClass is assigned.
union {
uint32_t cod;
BluetoothServiceClass service;
} mTarget;
nsCOMPtr<nsITimer> mTimer;
- nsCOMPtr<nsITimerCallback> mCheckProfileStatusCallback;
};
END_BLUETOOTH_NAMESPACE
#endif
--- a/dom/camera/GonkRecorder.h
+++ b/dom/camera/GonkRecorder.h
@@ -26,21 +26,21 @@
#include <system/audio.h>
#include "mozilla/RefPtr.h"
#include "GonkCameraHwMgr.h"
namespace android {
class GonkCameraSource;
-struct MediaSource;
-struct MediaWriter;
-class MetaData;
-struct AudioSource;
-class MediaProfiles;
+struct MOZ_EXPORT MediaSource;
+struct MOZ_EXPORT MediaWriter;
+class MOZ_EXPORT MetaData;
+struct MOZ_EXPORT AudioSource;
+class MOZ_EXPORT MediaProfiles;
class GonkCameraHardware;
struct GonkRecorder {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GonkRecorder)
GonkRecorder();
virtual status_t init();
--- a/dom/events/DataTransfer.cpp
+++ b/dom/events/DataTransfer.cpp
@@ -589,19 +589,17 @@ DataTransfer::MozGetDataAt(const nsAStri
// source of the drag is in a child frame of the caller. In that case,
// we only allow access to data of the same principal. During other events,
// only allow access to the data with the same principal.
nsIPrincipal* principal = nullptr;
if (mIsCrossDomainSubFrameDrop ||
(mEventType != NS_DRAGDROP_DROP && mEventType != NS_DRAGDROP_DRAGDROP &&
mEventType != NS_PASTE &&
!nsContentUtils::IsCallerChrome())) {
- nsresult rv = NS_OK;
- principal = GetCurrentPrincipal(&rv);
- NS_ENSURE_SUCCESS(rv, rv);
+ principal = nsContentUtils::GetSubjectPrincipal();
}
uint32_t count = item.Length();
for (uint32_t i = 0; i < count; i++) {
TransferItem& formatitem = item[i];
if (formatitem.mFormat.Equals(format)) {
bool subsumes;
if (formatitem.mPrincipal && principal &&
@@ -620,19 +618,19 @@ DataTransfer::MozGetDataAt(const nsAStri
nsIScriptContext* c = pt->GetContextForEventHandlers(&rv);
NS_ENSURE_TRUE(c && NS_SUCCEEDED(rv), NS_ERROR_DOM_SECURITY_ERR);
nsIGlobalObject* go = c->GetGlobalObject();
NS_ENSURE_TRUE(go, NS_ERROR_DOM_SECURITY_ERR);
nsCOMPtr<nsIScriptObjectPrincipal> sp = do_QueryInterface(go);
MOZ_ASSERT(sp, "This cannot fail on the main thread.");
nsIPrincipal* dataPrincipal = sp->GetPrincipal();
NS_ENSURE_TRUE(dataPrincipal, NS_ERROR_DOM_SECURITY_ERR);
- NS_ENSURE_TRUE(principal || (principal = GetCurrentPrincipal(&rv)),
- NS_ERROR_DOM_SECURITY_ERR);
- NS_ENSURE_SUCCESS(rv, rv);
+ if (!principal) {
+ principal = nsContentUtils::GetSubjectPrincipal();
+ }
bool equals = false;
NS_ENSURE_TRUE(NS_SUCCEEDED(principal->Equals(dataPrincipal, &equals)) && equals,
NS_ERROR_DOM_SECURITY_ERR);
}
}
*aData = formatitem.mData;
NS_IF_ADDREF(*aData);
return NS_OK;
@@ -692,21 +690,18 @@ DataTransfer::MozSetDataAt(const nsAStri
// don't allow non-chrome to add file data
// XXX perhaps this should also limit any non-string type as well
if ((aFormat.EqualsLiteral("application/x-moz-file-promise") ||
aFormat.EqualsLiteral("application/x-moz-file")) &&
!nsContentUtils::IsCallerChrome()) {
return NS_ERROR_DOM_SECURITY_ERR;
}
- nsresult rv = NS_OK;
- nsIPrincipal* principal = GetCurrentPrincipal(&rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return SetDataWithPrincipal(aFormat, aData, aIndex, principal);
+ return SetDataWithPrincipal(aFormat, aData, aIndex,
+ nsContentUtils::GetSubjectPrincipal());
}
void
DataTransfer::MozSetDataAt(JSContext* aCx, const nsAString& aFormat,
JS::Handle<JS::Value> aData,
uint32_t aIndex, ErrorResult& aRv)
{
nsCOMPtr<nsIVariant> data;
@@ -749,22 +744,17 @@ DataTransfer::MozClearDataAtHelper(const
MOZ_ASSERT(aIndex < mItems.Length());
MOZ_ASSERT(aIndex == 0 ||
(mEventType != NS_CUT && mEventType != NS_COPY &&
mEventType != NS_PASTE));
nsAutoString format;
GetRealFormat(aFormat, format);
- nsresult rv = NS_OK;
- nsIPrincipal* principal = GetCurrentPrincipal(&rv);
- if (NS_FAILED(rv)) {
- aRv = rv;
- return;
- }
+ nsIPrincipal* principal = nsContentUtils::GetSubjectPrincipal();
// if the format is empty, clear all formats
bool clearall = format.IsEmpty();
nsTArray<TransferItem>& item = mItems[aIndex];
// count backwards so that the count and index don't have to be adjusted
// after removing an element
for (int32_t i = item.Length() - 1; i >= 0; i--) {
@@ -1084,31 +1074,16 @@ DataTransfer::SetDataWithPrincipal(const
formatitem->mFormat = format;
formatitem->mPrincipal = aPrincipal;
formatitem->mData = aData;
return NS_OK;
}
-nsIPrincipal*
-DataTransfer::GetCurrentPrincipal(nsresult* rv)
-{
- nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
-
- nsCOMPtr<nsIPrincipal> currentPrincipal;
- *rv = ssm->GetSubjectPrincipal(getter_AddRefs(currentPrincipal));
- NS_ENSURE_SUCCESS(*rv, nullptr);
-
- if (!currentPrincipal)
- ssm->GetSystemPrincipal(getter_AddRefs(currentPrincipal));
-
- return currentPrincipal.get();
-}
-
void
DataTransfer::GetRealFormat(const nsAString& aInFormat, nsAString& aOutFormat)
{
// treat text/unicode as equivalent to text/plain
nsAutoString lowercaseFormat;
nsContentUtils::ASCIIToLower(aInFormat, lowercaseFormat);
if (lowercaseFormat.EqualsLiteral("text") || lowercaseFormat.EqualsLiteral("text/unicode"))
aOutFormat.AssignLiteral("text/plain");
--- a/dom/events/DataTransfer.h
+++ b/dom/events/DataTransfer.h
@@ -214,19 +214,16 @@ public:
return mDragImage;
}
nsresult Clone(nsISupports* aParent, uint32_t aEventType, bool aUserCancelled,
bool aIsCrossDomainSubFrameDrop, DataTransfer** aResult);
protected:
- // returns a weak reference to the current principal
- nsIPrincipal* GetCurrentPrincipal(nsresult* rv);
-
// converts some formats used for compatibility in aInFormat into aOutFormat.
// Text and text/unicode become text/plain, and URL becomes text/uri-list
void GetRealFormat(const nsAString& aInFormat, nsAString& aOutFormat);
// caches text and uri-list data formats that exist in the drag service or
// clipboard for retrieval later.
void CacheExternalData(const char* aFormat, uint32_t aIndex, nsIPrincipal* aPrincipal);
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -552,21 +552,16 @@ EventStateManager::PreHandleEvent(nsPres
// then fall through...
case WidgetMouseEvent::eRightButton:
case WidgetMouseEvent::eMiddleButton:
SetClickCount(aPresContext, mouseEvent, aStatus);
break;
}
break;
}
- case NS_POINTER_CANCEL:
- {
- GenerateMouseEnterExit(mouseEvent);
- break;
- }
case NS_MOUSE_EXIT:
// If the event is not a top-level window exit, then it's not
// really an exit --- we may have traversed widget boundaries but
// we're still in our toplevel window.
if (mouseEvent->exit != WidgetMouseEvent::eTopLevel) {
// Treat it as a synthetic move so we don't generate spurious
// "exit" or "move" events. Any necessary "out" or "over" events
// will be generated by GenerateMouseEnterExit
@@ -2859,17 +2854,23 @@ EventStateManager::PostHandleEvent(nsPre
fm->SetFocusedWindow(mDocument->GetWindow());
}
}
}
}
SetActiveManager(this, activeContent);
}
break;
- case NS_POINTER_CANCEL:
+ case NS_POINTER_CANCEL: {
+ if(WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent()) {
+ GenerateMouseEnterExit(mouseEvent);
+ }
+ // This break was commented specially
+ // break;
+ }
case NS_POINTER_UP: {
WidgetPointerEvent* pointerEvent = aEvent->AsPointerEvent();
// After UP/Cancel Touch pointers become invalid so we can remove relevant helper from Table
// Mouse/Pen pointers are valid all the time (not only between down/up)
if (pointerEvent->inputSource == nsIDOMMouseEvent::MOZ_SOURCE_TOUCH) {
mPointersEnterLeaveHelper.Remove(pointerEvent->pointerId);
}
if (pointerEvent->inputSource != nsIDOMMouseEvent::MOZ_SOURCE_MOUSE) {
--- a/dom/imptests/failures/html/dom/test_interfaces.html.json
+++ b/dom/imptests/failures/html/dom/test_interfaces.html.json
@@ -1,10 +1,9 @@
{
- "DOMException exception: existence and properties of exception interface prototype object": true,
"DOMException exception: existence and properties of exception interface prototype object's \"name\" property": true,
"CustomEvent interface: existence and properties of interface object": true,
"EventListener interface: existence and properties of interface prototype object": true,
"EventListener interface: existence and properties of interface prototype object's \"constructor\" property": true,
"EventListener interface: operation handleEvent(Event)": true,
"MutationObserver interface: operation observe(Node,MutationObserverInit)": true,
"Node interface: existence and properties of interface object": true,
"Document interface: existence and properties of interface object": true,
--- a/dom/indexedDB/test/extensions/Makefile.in
+++ b/dom/indexedDB/test/extensions/Makefile.in
@@ -1,20 +1,17 @@
# 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/.
DIST_FILES = \
+ bootstrap.js \
install.rdf \
$(NULL)
-DIST_FILES_NO_PP = \
- bootstrap.js \
- $(NULL)
-
TEST_EXTENSIONS_DIR = $(DEPTH)/_tests/testing/mochitest/extensions
GENERATED_DIRS = $(TEST_EXTENSIONS_DIR)
include $(topsrcdir)/config/rules.mk
libs::
@(cd $(DIST)/xpi-stage && tar $(TAR_CREATE_FLAGS) - $(XPI_NAME)) | (cd $(TEST_EXTENSIONS_DIR) && tar -xf -)
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -116,16 +116,17 @@ TabChildBase::TabChildBase()
, mTabChildGlobal(nullptr)
, mInnerSize(0, 0)
{
}
NS_IMPL_CYCLE_COLLECTING_ADDREF(TabChildBase)
NS_IMPL_CYCLE_COLLECTING_RELEASE(TabChildBase)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TabChildBase)
+ NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION(TabChildBase, mTabChildGlobal, mGlobal)
void
TabChildBase::InitializeRootMetrics()
{
// Calculate a really simple resolution that we probably won't
@@ -970,34 +971,33 @@ TabChild::NotifyTabContextUpdated()
if (IsBrowserElement()) {
docShell->SetIsBrowserInsideApp(BrowserOwnerAppId());
} else {
docShell->SetIsApp(OwnAppId());
}
}
}
-NS_INTERFACE_MAP_BEGIN(TabChild)
- NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebBrowserChrome)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TabChild)
NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome2)
NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow)
NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChromeFocus)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
NS_INTERFACE_MAP_ENTRY(nsIWindowProvider)
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
NS_INTERFACE_MAP_ENTRY(nsITabChild)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY(nsITooltipListener)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_ADDREF(TabChild)
-NS_IMPL_RELEASE(TabChild)
+NS_INTERFACE_MAP_END_INHERITING(TabChildBase)
+
+NS_IMPL_ADDREF_INHERITED(TabChild, TabChildBase);
+NS_IMPL_RELEASE_INHERITED(TabChild, TabChildBase);
NS_IMETHODIMP
TabChild::SetStatus(uint32_t aStatusType, const char16_t* aStatus)
{
return SetStatusWithContext(aStatusType,
aStatus ? static_cast<const nsString &>(nsDependentString(aStatus))
: EmptyString(),
nullptr);
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -215,30 +215,30 @@ protected:
float mOldViewportWidth;
bool mContentDocumentIsDisplayed;
nsRefPtr<TabChildGlobal> mTabChildGlobal;
ScreenIntSize mInnerSize;
mozilla::layers::FrameMetrics mLastRootMetrics;
mozilla::layout::ScrollingBehavior mScrolling;
};
-class TabChild : public PBrowserChild,
+class TabChild : public TabChildBase,
+ public PBrowserChild,
public nsIWebBrowserChrome2,
public nsIEmbeddingSiteWindow,
public nsIWebBrowserChromeFocus,
public nsIInterfaceRequestor,
public nsIWindowProvider,
public nsIDOMEventListener,
public nsIWebProgressListener,
public nsSupportsWeakReference,
public nsITabChild,
public nsIObserver,
public TabContext,
- public nsITooltipListener,
- public TabChildBase
+ public nsITooltipListener
{
typedef mozilla::dom::ClonedMessageData ClonedMessageData;
typedef mozilla::layout::RenderFrameChild RenderFrameChild;
typedef mozilla::layout::ScrollingBehavior ScrollingBehavior;
typedef mozilla::layers::ActiveElementManager ActiveElementManager;
public:
/**
@@ -251,17 +251,17 @@ public:
/** Return a TabChild with the given attributes. */
static already_AddRefed<TabChild>
Create(ContentChild* aManager, const TabContext& aContext, uint32_t aChromeFlags);
virtual ~TabChild();
bool IsRootContentDocument();
- NS_DECL_ISUPPORTS
+ NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIWEBBROWSERCHROME
NS_DECL_NSIWEBBROWSERCHROME2
NS_DECL_NSIEMBEDDINGSITEWINDOW
NS_DECL_NSIWEBBROWSERCHROMEFOCUS
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSIWINDOWPROVIDER
NS_DECL_NSIDOMEVENTLISTENER
NS_DECL_NSIWEBPROGRESSLISTENER
--- a/dom/nfc/tests/marionette/manifest.ini
+++ b/dom/nfc/tests/marionette/manifest.ini
@@ -1,9 +1,11 @@
[DEFAULT]
b2g=true
browser=false
qemu=true
[test_ndef.js]
[test_nfc_enabled.js]
[test_nfc_manager_tech_discovered.js]
+disabled = Bug 996426
[test_nfc_peer.js]
+disabled = Bug 996426
--- a/dom/nfc/tests/marionette/test_nfc_manager_tech_discovered.js
+++ b/dom/nfc/tests/marionette/test_nfc_manager_tech_discovered.js
@@ -13,29 +13,29 @@ function handleTechnologyDiscoveredRE0(m
log('Received \'nfc-manager-tech-discovered\'');
is(msg.type, 'techDiscovered', 'check for correct message type');
is(msg.techList[0], 'P2P', 'check for correct tech type');
toggleNFC(false, runNextTest);
}
function activateRE(re) {
let deferred = Promise.defer();
- let cmd = 'nfc ntf rf_intf_activated ' + re;
+ let cmd = 'nfc nci rf_intf_activated_ntf ' + re;
emulator.run(cmd, function(result) {
is(result.pop(), 'OK', 'check activation of RE' + re);
deferred.resolve();
});
return deferred.promise;
}
function notifyDiscoverRE(re, type) {
let deferred = Promise.defer();
- let cmd = 'nfc ntf rf_discover ' + re + ' ' + type;
+ let cmd = 'nfc nci rf_discover_ntf ' + re + ' ' + type;
emulator.run(cmd, function(result) {
is(result.pop(), 'OK', 'check discover of RE' + re);
deferred.resolve();
});
return deferred.promise;
}
--- a/dom/nfc/tests/marionette/test_nfc_peer.js
+++ b/dom/nfc/tests/marionette/test_nfc_peer.js
@@ -56,17 +56,17 @@ function handleTechnologyDiscoveredRE0Fo
nfc.onpeerready = null;
toggleNFC(false, runNextTest);
}
}
function activateRE(re) {
let deferred = Promise.defer();
- let cmd = "nfc ntf rf_intf_activated " + re;
+ let cmd = "nfc nci rf_intf_activated_ntf " + re;
emulator.run(cmd, function(result) {
is(result.pop(), "OK", "check activation of RE" + re);
deferred.resolve();
});
return deferred.promise;
}
--- a/dom/src/storage/DOMStorage.cpp
+++ b/dom/src/storage/DOMStorage.cpp
@@ -236,28 +236,22 @@ DOMStorage::CanUseStorage(DOMStorage* aS
aStorage->mIsSessionOnly = false;
}
if (!mozilla::Preferences::GetBool(kStorageEnabled)) {
return false;
}
// chrome can always use aStorage regardless of permission preferences
- if (nsContentUtils::IsCallerChrome()) {
+ nsCOMPtr<nsIPrincipal> subjectPrincipal =
+ nsContentUtils::GetSubjectPrincipal();
+ if (nsContentUtils::IsSystemPrincipal(subjectPrincipal)) {
return true;
}
- nsCOMPtr<nsIPrincipal> subjectPrincipal;
- nsresult rv = nsContentUtils::GetSecurityManager()->
- GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
- NS_ENSURE_SUCCESS(rv, false);
-
- // if subjectPrincipal were null we'd have returned after
- // IsCallerChrome().
-
nsCOMPtr<nsIPermissionManager> permissionManager =
services::GetPermissionManager();
if (!permissionManager) {
return false;
}
uint32_t perm;
permissionManager->TestPermissionFromPrincipal(subjectPrincipal,
--- a/dom/telephony/gonk/TelephonyProvider.js
+++ b/dom/telephony/gonk/TelephonyProvider.js
@@ -208,40 +208,28 @@ TelephonyProvider.prototype = {
this._activeCall.clientId === aCall.clientId &&
this._activeCall.callIndex === aCall.callIndex;
},
/**
* Track the active call and update the audio system as its state changes.
*/
_activeCall: null,
- _updateCallAudioState: function(aCall, aConferenceState) {
+ _updateActiveCall: function(aCall, aConferenceState) {
if (aConferenceState === nsITelephonyProvider.CALL_STATE_CONNECTED) {
this._activeCall = new ConferenceCall(aConferenceState);
- gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_IN_CALL;
- if (this.speakerEnabled) {
- gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION,
- nsIAudioManager.FORCE_SPEAKER);
- }
- if (DEBUG) {
- debug("Active call, put audio system into PHONE_STATE_IN_CALL: " +
- gAudioManager.phoneState);
- }
+ this._updateCallAudioState(aCall);
return;
}
if (aConferenceState === nsITelephonyProvider.CALL_STATE_UNKNOWN ||
aConferenceState === nsITelephonyProvider.CALL_STATE_HELD) {
if (this._activeCall instanceof ConferenceCall) {
this._activeCall = null;
- gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL;
- if (DEBUG) {
- debug("No active call, put audio system into PHONE_STATE_NORMAL: " +
- gAudioManager.phoneState);
- }
+ this._updateCallAudioState(aCall);
}
return;
}
if (!aCall) {
return;
}
@@ -253,60 +241,73 @@ TelephonyProvider.prototype = {
}
switch (aCall.state) {
case nsITelephonyProvider.CALL_STATE_DIALING: // Fall through...
case nsITelephonyProvider.CALL_STATE_ALERTING:
case nsITelephonyProvider.CALL_STATE_CONNECTED:
aCall.isActive = true;
this._activeCall = new SingleCall(aCall);
- gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_IN_CALL;
- if (this.speakerEnabled) {
- gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION,
- nsIAudioManager.FORCE_SPEAKER);
- }
- if (DEBUG) {
- debug("Active call, put audio system into PHONE_STATE_IN_CALL: " +
- gAudioManager.phoneState);
- }
+ this._updateCallAudioState(aCall);
break;
case nsITelephonyProvider.CALL_STATE_INCOMING:
aCall.isActive = false;
- if (!this._activeCall) {
- // We can change the phone state into RINGTONE only when there's
- // no active call.
- gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_RINGTONE;
- if (DEBUG) {
- debug("Incoming call, put audio system into PHONE_STATE_RINGTONE: " +
- gAudioManager.phoneState);
- }
- }
+ this._updateCallAudioState(aCall);
break;
case nsITelephonyProvider.CALL_STATE_HELD: // Fall through...
case nsITelephonyProvider.CALL_STATE_DISCONNECTED:
aCall.isActive = false;
if (this._matchActiveSingleCall(aCall)) {
// Previously active call is not active now.
this._activeCall = null;
- }
-
- if (!this._activeCall) {
- // No active call. Disable the audio.
- gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL;
- if (DEBUG) {
- debug("No active call, put audio system into PHONE_STATE_NORMAL: " +
- gAudioManager.phoneState);
- }
+ this._updateCallAudioState(aCall);
}
break;
}
},
+ _updateCallAudioState: function(aCall) {
+ // Ignore audio state setting if the call is a placeholder.
+ if (aCall && aCall.callIndex === OUTGOING_PLACEHOLDER_CALL_INDEX) {
+ return;
+ }
+
+ let active = (this._activeCall !== null);
+ let incoming = (aCall &&
+ aCall.state === nsITelephonyProvider.CALL_STATE_INCOMING);
+
+ if (active) {
+ gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_IN_CALL;
+ if (this.speakerEnabled) {
+ gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION,
+ nsIAudioManager.FORCE_SPEAKER);
+ }
+ if (DEBUG) {
+ debug("Active call, put audio system into PHONE_STATE_IN_CALL: " +
+ gAudioManager.phoneState);
+ }
+ } else if (incoming) {
+ // We can change the phone state into RINGTONE only when there's
+ // no active call.
+ gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_RINGTONE;
+ if (DEBUG) {
+ debug("Incoming call, put audio system into PHONE_STATE_RINGTONE: " +
+ gAudioManager.phoneState);
+ }
+ } else {
+ gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL;
+ if (DEBUG) {
+ debug("No active call, put audio system into PHONE_STATE_NORMAL: " +
+ gAudioManager.phoneState);
+ }
+ }
+ },
+
_convertRILCallState: function(aState) {
switch (aState) {
case RIL.CALL_STATE_UNKNOWN:
return nsITelephonyProvider.CALL_STATE_UNKNOWN;
case RIL.CALL_STATE_ACTIVE:
return nsITelephonyProvider.CALL_STATE_CONNECTED;
case RIL.CALL_STATE_HOLDING:
return nsITelephonyProvider.CALL_STATE_HELD;
@@ -742,17 +743,17 @@ TelephonyProvider.prototype = {
serviceId: aClientId,
emergency: aCall.isEmergency,
duration: duration,
direction: aCall.isOutgoing ? "outgoing" : "incoming"
};
gSystemMessenger.broadcastMessage("telephony-call-ended", data);
aCall.clientId = aClientId;
- this._updateCallAudioState(aCall, null);
+ this._updateActiveCall(aCall, null);
let manualConfStateChange = false;
let childId = this._currentCalls[aClientId][aCall.callIndex].childId;
if (childId) {
// Child cannot live without parent.
let childCall = this._currentCalls[aClientId][childId];
this.notifyCallDisconnected(aClientId, childCall);
} else {
@@ -822,17 +823,17 @@ TelephonyProvider.prototype = {
aCall.state = this._convertRILCallState(aCall.state);
}
if (aCall.state == nsITelephonyProvider.CALL_STATE_DIALING) {
gSystemMessenger.broadcastMessage("telephony-new-call", {});
}
aCall.clientId = aClientId;
- this._updateCallAudioState(aCall, null);
+ this._updateActiveCall(aCall, null);
let call = this._currentCalls[aClientId][aCall.callIndex];
if (call) {
call.state = aCall.state;
call.isConference = aCall.isConference;
call.isEmergency = aCall.isEmergency;
call.isActive = aCall.isActive;
call.isSwitchable = aCall.isSwitchable != null ?
@@ -886,17 +887,17 @@ TelephonyProvider.prototype = {
let notification = this._convertRILSuppSvcNotification(aNotification);
this._notifyAllListeners("supplementaryServiceNotification",
[aClientId, aCallIndex, notification]);
},
notifyConferenceCallStateChanged: function(aState) {
if (DEBUG) debug("handleConferenceCallStateChanged: " + aState);
aState = this._convertRILCallState(aState);
- this._updateCallAudioState(null, aState);
+ this._updateActiveCall(null, aState);
this._notifyAllListeners("conferenceCallStateChanged", [aState]);
},
/**
* nsIObserver interface.
*/
--- a/dom/tests/mochitest/chrome/test_cyclecollector.xul
+++ b/dom/tests/mochitest/chrome/test_cyclecollector.xul
@@ -13,33 +13,40 @@ https://bugzilla.mozilla.org/show_bug.cg
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id="
target="_blank">Mozilla Bug </a>
</body>
<!-- test code goes here -->
<script type="application/javascript">
<![CDATA[
/** Test for Bug **/
+ let Ci = Components.interfaces;
var obs = Components.classes["@mozilla.org/observer-service;1"]
- .getService(Components.interfaces.nsIObserverService);
+ .getService(Ci.nsIObserverService);
var didCall = false;
var observer = {
QueryInterface: function QueryInterface(aIID) {
- if (aIID.equals(Components.interfaces.nsIObserver) ||
- aIID.equals(Components.interfaces.nsISupports))
+ if (aIID.equals(Ci.nsIObserver) ||
+ aIID.equals(Ci.nsISupports))
return this;
throw Components.results.NS_NOINTERFACE;
},
observe: function(subject, topic, data) {
obs.removeObserver(observer, "cycle-collector-begin");
observer = null;
didCall = true;
}
};
+ // Make sure that we call the observer even if we're in the middle
+ // of an ICC when we add the observer. See bug 981033.
+ // XXX This will assert if we try to start an ICC during a IGC.
+ //SpecialPowers.finishCC();
+ //SpecialPowers.ccSlice(1);
+
obs.addObserver(observer, "cycle-collector-begin", false);
- window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
- .getInterface(Components.interfaces.nsIDOMWindowUtils).cycleCollect();
+
+ SpecialPowers.DOMWindowUtils.cycleCollect();
ok(didCall, "Observer should have been called!");
]]>
</script>
</window>
--- a/dom/webidl/DOMException.webidl
+++ b/dom/webidl/DOMException.webidl
@@ -13,21 +13,28 @@
// This is the WebIDL version of nsIException. This is mostly legacy stuff.
interface StackFrame;
[NoInterfaceObject]
interface ExceptionMembers
{
- // A custom message set by the thrower.
+ // A custom message set by the thrower. LenientThis so it can be
+ // gotten on the prototype, which Error.prototype.toString will do
+ // if someone tries to stringify DOMException.prototype.
+ [LenientThis]
readonly attribute DOMString message;
// The nsresult associated with this exception.
readonly attribute unsigned long result;
- // The name of the error code (ie, a string repr of |result|)
+ // The name of the error code (ie, a string repr of |result|).
+ // LenientThis so it can be gotten on the prototype, which
+ // Error.prototype.toString will do if someone tries to stringify
+ // DOMException.prototype.
+ [LenientThis]
readonly attribute DOMString name;
// Filename location. This is the location that caused the
// error, which may or may not be a source file location.
// For example, standard language errors would generally have
// the same location as their top stack entry. File
// parsers may put the location of the file they were parsing,
// etc.
@@ -44,29 +51,29 @@ interface ExceptionMembers
// this was only ever usefully available to chrome JS.
[ChromeOnly]
readonly attribute StackFrame? location;
// An inner exception that triggered this, if available.
readonly attribute nsISupports? inner;
// Arbitary data for the implementation.
readonly attribute nsISupports? data;
-
- // A generic formatter - make it suitable to print, etc.
- stringifier;
};
[NoInterfaceObject]
interface Exception {
+ // A generic formatter - make it suitable to print, etc.
+ stringifier;
};
Exception implements ExceptionMembers;
// XXXkhuey this is an 'exception', not an interface, but we don't have any
// parser or codegen mechanisms for dealing with exceptions.
+[ExceptionClass]
interface DOMException {
const unsigned short INDEX_SIZE_ERR = 1;
const unsigned short DOMSTRING_SIZE_ERR = 2; // historical
const unsigned short HIERARCHY_REQUEST_ERR = 3;
const unsigned short WRONG_DOCUMENT_ERR = 4;
const unsigned short INVALID_CHARACTER_ERR = 5;
const unsigned short NO_DATA_ALLOWED_ERR = 6; // historical
const unsigned short NO_MODIFICATION_ALLOWED_ERR = 7;
--- a/dom/webidl/MozWifiManager.webidl
+++ b/dom/webidl/MozWifiManager.webidl
@@ -242,16 +242,24 @@ interface MozWifiManager : EventTarget {
* string as value.
* request.result[USAGE] = [CA_NICKNAME1, CA_NICKNAME2, ...]
* USAGE string includes: "ServerCert".
* onerror: We have failed to list certificate.
*/
DOMRequest getImportedCerts();
/**
+ * Delete an imported certificate.
+ * @param certNickname Nickname of imported to be deleted.
+ * onsuccess: We have successfully deleted certificate.
+ * onerror: We have failed to delete certificate.
+ */
+ DOMRequest deleteCert(DOMString certNickname);
+
+ /**
* Returns whether or not wifi is currently enabled.
*/
readonly attribute boolean enabled;
/**
* Returns the MAC address of the wifi adapter.
*/
readonly attribute DOMString macAddress;
--- a/dom/wifi/DOMWifiManager.js
+++ b/dom/wifi/DOMWifiManager.js
@@ -91,16 +91,17 @@ DOMWifiManager.prototype = {
"WifiManager:associate:Return:OK", "WifiManager:associate:Return:NO",
"WifiManager:forget:Return:OK", "WifiManager:forget:Return:NO",
"WifiManager:wps:Return:OK", "WifiManager:wps:Return:NO",
"WifiManager:setPowerSavingMode:Return:OK", "WifiManager:setPowerSavingMode:Return:NO",
"WifiManager:setHttpProxy:Return:OK", "WifiManager:setHttpProxy:Return:NO",
"WifiManager:setStaticIpMode:Return:OK", "WifiManager:setStaticIpMode:Return:NO",
"WifiManager:importCert:Return:OK", "WifiManager:importCert:Return:NO",
"WifiManager:getImportedCerts:Return:OK", "WifiManager:getImportedCerts:Return:NO",
+ "WifiManager:deleteCert:Return:OK", "WifiManager:deleteCert:Return:NO",
"WifiManager:wifiDown", "WifiManager:wifiUp",
"WifiManager:onconnecting", "WifiManager:onassociate",
"WifiManager:onconnect", "WifiManager:ondisconnect",
"WifiManager:onwpstimeout", "WifiManager:onwpsfail",
"WifiManager:onwpsoverlap", "WifiManager:connectionInfoUpdate",
"WifiManager:onconnectingfailed"];
this.initDOMRequestHelper(aWindow, messages);
this._mm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsISyncMessageSender);
@@ -283,16 +284,24 @@ DOMWifiManager.prototype = {
case "WifiManager:getImportedCerts:Return:OK":
Services.DOMRequest.fireSuccess(request, this._convertWifiCertificateList(msg.data));
break;
case "WifiManager:getImportedCerts:Return:NO":
Services.DOMRequest.fireError(request, msg.data);
break;
+ case "WifiManager:deleteCert:Return:OK":
+ Services.DOMRequest.fireSuccess(request, msg.data);
+ break;
+
+ case "WifiManager:deleteCert:Return:NO":
+ Services.DOMRequest.fireError(request, msg.data);
+ break;
+
case "WifiManager:wifiDown":
this._enabled = false;
this._currentNetwork = null;
this._fireEnabledOrDisabled(false);
break;
case "WifiManager:wifiUp":
this._enabled = true;
@@ -447,16 +456,25 @@ DOMWifiManager.prototype = {
},
getImportedCerts: function nsIDOMWifiManager_getImportedCerts() {
var request = this.createRequest();
this._sendMessageForRequest("WifiManager:getImportedCerts", null, request);
return request;
},
+ deleteCert: function nsIDOMWifiManager_deleteCert(certNickname) {
+ var request = this.createRequest();
+ this._sendMessageForRequest("WifiManager:deleteCert",
+ {
+ certNickname: certNickname
+ }, request);
+ return request;
+ },
+
get enabled() {
return this._enabled;
},
get macAddress() {
return this._macAddress;
},
--- a/dom/wifi/WifiCertService.cpp
+++ b/dom/wifi/WifiCertService.cpp
@@ -158,16 +158,69 @@ private:
return NS_OK;
}
nsCOMPtr<nsIDOMBlob> mBlob;
nsString mPassword;
WifiCertServiceResultOptions mResult;
};
+class DeleteCertTask MOZ_FINAL: public CryptoTask
+{
+public:
+ DeleteCertTask(int32_t aId, const nsAString& aCertNickname)
+ {
+ MOZ_ASSERT(NS_IsMainThread());
+
+ mResult.mId = aId;
+ mResult.mStatus = 0;
+ mResult.mUsageFlag = 0;
+ mResult.mNickname = aCertNickname;
+ }
+
+private:
+ virtual void ReleaseNSSResources() {}
+
+ virtual nsresult CalculateResult() MOZ_OVERRIDE
+ {
+ MOZ_ASSERT(!NS_IsMainThread());
+
+ nsCString userNickname;
+ CopyUTF16toUTF8(mResult.mNickname, userNickname);
+
+ // Delete server certificate.
+ nsCString serverCertName("WIFI_SERVERCERT_", 16);
+ serverCertName += userNickname;
+
+ ScopedCERTCertificate cert(
+ CERT_FindCertByNickname(CERT_GetDefaultCertDB(), serverCertName.get())
+ );
+ if (!cert) {
+ return MapSECStatus(SECFailure);
+ }
+
+ SECStatus srv = SEC_DeletePermCertificate(cert);
+ if (srv != SECSuccess) {
+ return MapSECStatus(srv);
+ }
+
+ return NS_OK;
+ }
+
+ virtual void CallCallback(nsresult rv)
+ {
+ if (NS_FAILED(rv)) {
+ mResult.mStatus = -1;
+ }
+ gWifiCertService->DispatchResult(mResult);
+ }
+
+ WifiCertServiceResultOptions mResult;
+};
+
NS_IMPL_ISUPPORTS(WifiCertService, nsIWifiCertService)
NS_IMETHODIMP
WifiCertService::Start(nsIWifiEventListener* aListener)
{
MOZ_ASSERT(aListener);
nsresult rv = NS_NewThread(getter_AddRefs(mRequestThread));
@@ -244,16 +297,23 @@ WifiCertService::ImportCert(int32_t aId,
const nsAString& aCertPassword,
const nsAString& aCertNickname)
{
RefPtr<CryptoTask> task = new ImportCertTask(aId, aCertBlob, aCertPassword,
aCertNickname);
return task->Dispatch("WifiImportCert");
}
+NS_IMETHODIMP
+WifiCertService::DeleteCert(int32_t aId, const nsAString& aCertNickname)
+{
+ RefPtr<CryptoTask> task = new DeleteCertTask(aId, aCertNickname);
+ return task->Dispatch("WifiDeleteCert");
+}
+
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(WifiCertService,
WifiCertService::FactoryCreate)
NS_DEFINE_NAMED_CID(NS_WIFICERTSERVICE_CID);
static const mozilla::Module::CIDEntry kWifiCertServiceCIDs[] = {
{ &kNS_WIFICERTSERVICE_CID, false, nullptr, WifiCertServiceConstructor },
{ nullptr }
--- a/dom/wifi/WifiWorker.js
+++ b/dom/wifi/WifiWorker.js
@@ -1374,16 +1374,25 @@ var WifiManager = (function() {
if (callback) {
controlCallbacks[id] = callback;
}
wifiCertService.importCert(id, caInfo.certBlob, caInfo.certPassword,
caInfo.certNickname);
}
+ manager.deleteCert = function(caInfo, callback) {
+ var id = idgen++;
+ if (callback) {
+ controlCallbacks[id] = callback;
+ }
+
+ wifiCertService.deleteCert(id, caInfo.certNickname);
+ }
+
return manager;
})();
// Get unique key for a network, now the key is created by escape(SSID)+Security.
// So networks of same SSID but different security mode can be identified.
function getNetworkKey(network)
{
var ssid = "",
@@ -1642,16 +1651,17 @@ function WifiWorker() {
const messages = ["WifiManager:getNetworks", "WifiManager:getKnownNetworks",
"WifiManager:associate", "WifiManager:forget",
"WifiManager:wps", "WifiManager:getState",
"WifiManager:setPowerSavingMode",
"WifiManager:setHttpProxy",
"WifiManager:setStaticIpMode",
"WifiManager:importCert",
"WifiManager:getImportedCerts",
+ "WifiManager:deleteCert",
"child-process-shutdown"];
messages.forEach((function(msgName) {
this._mm.addMessageListener(msgName, this);
}).bind(this));
Services.obs.addObserver(this, kMozSettingsChangedObserverTopic, false);
@@ -2600,16 +2610,19 @@ WifiWorker.prototype = {
this.setStaticIpMode(msg);
break;
case "WifiManager:importCert":
this.importCert(msg);
break;
case "WifiManager:getImportedCerts":
this.getImportedCerts(msg);
break;
+ case "WifiManager:deleteCert":
+ this.deleteCert(msg);
+ break;
case "WifiManager:getState": {
let i;
if ((i = this._domManagers.indexOf(msg.manager)) === -1) {
this._domManagers.push(msg.manager);
}
let net = this.currentNetwork ? netToDOM(this.currentNetwork) : null;
return { network: net,
@@ -3152,16 +3165,25 @@ WifiWorker.prototype = {
continue;
}
importedCerts[UsageMapping[certNicknameInfo[1]]].push(certNicknameInfo[2]);
}
self._sendMessage(message, true, importedCerts, msg);
},
+ deleteCert: function deleteCert(msg) {
+ const message = "WifiManager:deleteCert:Return";
+ let self = this;
+
+ WifiManager.deleteCert(msg.data, function(data) {
+ self._sendMessage(message, data.status === 0, "Delete Cert failed", msg);
+ });
+ },
+
// This is a bit ugly, but works. In particular, this depends on the fact
// that RadioManager never actually tries to get the worker from us.
get worker() { throw "Not implemented"; },
shutdown: function() {
debug("shutting down ...");
this.queueRequest({command: "setWifiEnabled", value: false}, function(data) {
this.setWifiEnabled(false, this._setWifiEnabledCallback.bind(this));
--- a/dom/wifi/nsIWifiCertService.idl
+++ b/dom/wifi/nsIWifiCertService.idl
@@ -2,17 +2,17 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
interface nsIDOMBlob;
interface nsIWifiEventListener;
-[scriptable, uuid(49e8e04e-eb05-4c92-84a6-7af32310f0c3)]
+[scriptable, uuid(2712a791-f720-484d-8820-c4085629f657)]
interface nsIWifiCertService : nsISupports
{
const unsigned short WIFI_CERT_USAGE_FLAG_SERVER = 0x01;
const unsigned short WIFI_CERT_USAGE_FLAG_USER = 0x02;
void start(in nsIWifiEventListener listener);
void shutdown();
@@ -27,9 +27,20 @@ interface nsIWifiCertService : nsISuppor
* Password of certificate.
* @param certNickname
* User assigned nickname for imported certificate.
*/
void importCert(in long id,
in nsIDOMBlob certBlob,
in DOMString certPassword,
in DOMString certNickname);
+
+ /**
+ * Delete an imported certificate file
+ *
+ * @param id
+ * Request ID.
+ * @param certNickname
+ * Certificate nickname to delete.
+ */
+ void deleteCert(in long id,
+ in DOMString certNickname);
};
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -3712,16 +3712,17 @@ WorkerPrivate::Constructor(const GlobalO
nsresult
WorkerPrivate::GetLoadInfo(JSContext* aCx, nsPIDOMWindow* aWindow,
WorkerPrivate* aParent, const nsAString& aScriptURL,
bool aIsChromeWorker, LoadInfo* aLoadInfo)
{
using namespace mozilla::dom::workers::scriptloader;
MOZ_ASSERT(aCx);
+ MOZ_ASSERT_IF(NS_IsMainThread(), aCx == nsContentUtils::GetCurrentJSContext());
if (aWindow) {
AssertIsOnMainThread();
}
LoadInfo loadInfo;
nsresult rv;
@@ -3908,20 +3909,16 @@ WorkerPrivate::GetLoadInfo(JSContext* aC
}
}
loadInfo.mXHRParamsAllowed = true;
}
MOZ_ASSERT(loadInfo.mPrincipal);
MOZ_ASSERT(isChrome || !loadInfo.mDomain.IsEmpty());
- // XXXbent Use subject principal here instead of the one we already have?
- nsCOMPtr<nsIPrincipal> subjectPrincipal = ssm->GetCxSubjectPrincipal(aCx);
- MOZ_ASSERT(subjectPrincipal);
-
if (!nsContentUtils::GetContentSecurityPolicy(aCx,
getter_AddRefs(loadInfo.mCSP))) {
NS_WARNING("Failed to get CSP!");
return NS_ERROR_FAILURE;
}
if (loadInfo.mCSP) {
rv = loadInfo.mCSP->GetAllowsEval(&loadInfo.mReportCSPViolations,
--- a/dom/workers/test/extensions/bootstrap/Makefile.in
+++ b/dom/workers/test/extensions/bootstrap/Makefile.in
@@ -1,18 +1,15 @@
# 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/.
DIST_FILES = \
+ bootstrap.js \
install.rdf \
- $(NULL)
-
-DIST_FILES_NO_PP = \
- bootstrap.js \
worker.js \
$(NULL)
TEST_EXTENSIONS_DIR = $(DEPTH)/_tests/testing/mochitest/extensions
GENERATED_DIRS = $(TEST_EXTENSIONS_DIR)
include $(topsrcdir)/config/rules.mk
--- a/dom/workers/test/extensions/traditional/Makefile.in
+++ b/dom/workers/test/extensions/traditional/Makefile.in
@@ -1,17 +1,14 @@
# 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/.
DIST_FILES = \
install.rdf \
- $(NULL)
-
-DIST_FILES_NO_PP = \
worker.js \
$(NULL)
TEST_EXTENSIONS_DIR = $(DEPTH)/_tests/testing/mochitest/extensions
GENERATED_DIRS = $(TEST_EXTENSIONS_DIR)
include $(topsrcdir)/config/rules.mk
--- a/dom/xslt/xslt/txMozillaXSLTProcessor.cpp
+++ b/dom/xslt/xslt/txMozillaXSLTProcessor.cpp
@@ -1247,25 +1247,18 @@ txMozillaXSLTProcessor::ContentRemoved(n
{
mStylesheet = nullptr;
}
NS_IMETHODIMP
txMozillaXSLTProcessor::Initialize(nsISupports* aOwner, JSContext* cx,
JSObject* obj, const JS::CallArgs& args)
{
- nsCOMPtr<nsIPrincipal> prin;
- nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
- NS_ENSURE_TRUE(secMan, NS_ERROR_UNEXPECTED);
-
- nsresult rv = secMan->GetSubjectPrincipal(getter_AddRefs(prin));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(prin, NS_ERROR_UNEXPECTED);
-
- return Init(prin);
+ MOZ_ASSERT(nsContentUtils::GetCurrentJSContext());
+ return Init(nsContentUtils::GetSubjectPrincipal());
}
NS_IMETHODIMP
txMozillaXSLTProcessor::Init(nsIPrincipal* aPrincipal)
{
NS_ENSURE_ARG_POINTER(aPrincipal);
mPrincipal = aPrincipal;
--- a/embedding/components/commandhandler/src/nsCommandManager.cpp
+++ b/embedding/components/commandhandler/src/nsCommandManager.cpp
@@ -9,16 +9,17 @@
#include "nsIControllers.h"
#include "nsIObserver.h"
#include "nsIComponentManager.h"
#include "nsServiceManagerUtils.h"
#include "nsIScriptSecurityManager.h"
+#include "nsContentUtils.h"
#include "nsIDOMWindow.h"
#include "nsPIDOMWindow.h"
#include "nsPIWindowRoot.h"
#include "nsIFocusManager.h"
#include "nsCOMArray.h"
#include "nsCommandManager.h"
@@ -232,47 +233,26 @@ nsCommandManager::DoCommand(const char *
if (commandController && aCommandParams)
rv = commandController->DoCommandWithParams(aCommandName, aCommandParams);
else
rv = controller->DoCommand(aCommandName);
return rv;
}
nsresult
-nsCommandManager::IsCallerChrome(bool *is_caller_chrome)
-{
- *is_caller_chrome = false;
- nsresult rv = NS_OK;
- nsCOMPtr<nsIScriptSecurityManager> secMan =
- do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
- if (NS_FAILED(rv))
- return rv;
- if (!secMan)
- return NS_ERROR_FAILURE;
-
- rv = secMan->SubjectPrincipalIsSystem(is_caller_chrome);
- return rv;
-}
-
-nsresult
nsCommandManager::GetControllerForCommand(const char *aCommand,
nsIDOMWindow *aTargetWindow,
nsIController** outController)
{
nsresult rv = NS_ERROR_FAILURE;
*outController = nullptr;
// check if we're in content or chrome
// if we're not chrome we must have a target window or we bail
- bool isChrome = false;
- rv = IsCallerChrome(&isChrome);
- if (NS_FAILED(rv))
- return rv;
-
- if (!isChrome) {
+ if (!nsContentUtils::IsCallerChrome()) {
if (!aTargetWindow)
return rv;
// if a target window is specified, it must be the window we expect
if (aTargetWindow != mWindow)
return NS_ERROR_FAILURE;
}
--- a/embedding/components/commandhandler/src/nsCommandManager.h
+++ b/embedding/components/commandhandler/src/nsCommandManager.h
@@ -38,18 +38,16 @@ public:
NS_DECL_NSICOMMANDMANAGER
// nsPICommandUpdater
NS_DECL_NSPICOMMANDUPDATER
protected:
-
- nsresult IsCallerChrome(bool *aIsCallerChrome);
nsresult GetControllerForCommand(const char * aCommand,
nsIDOMWindow *aDirectedToThisWindow,
nsIController** outController);
protected:
nsClassHashtable<nsCharPtrHashKey, ObserverList> mObserversTable;
--- a/embedding/components/find/src/nsWebBrowserFind.cpp
+++ b/embedding/components/find/src/nsWebBrowserFind.cpp
@@ -34,16 +34,17 @@
#include "nsIObserverService.h"
#include "nsISupportsPrimitives.h"
#include "nsFind.h"
#include "nsError.h"
#include "nsFocusManager.h"
#include "mozilla/Services.h"
#include "mozilla/dom/Element.h"
#include "nsISimpleEnumerator.h"
+#include "nsContentUtils.h"
#if DEBUG
#include "nsIWebNavigation.h"
#include "nsXPIDLString.h"
#endif
//*****************************************************************************
// nsWebBrowserFind
@@ -655,31 +656,18 @@ nsresult nsWebBrowserFind::SearchInFrame
// Do security check, to ensure that the frame we're searching is
// acccessible from the frame where the Find is being run.
// get a uri for the window
nsCOMPtr<nsIDocument> theDoc = do_QueryInterface(domDoc);
if (!theDoc) return NS_ERROR_FAILURE;
- nsCOMPtr<nsIScriptSecurityManager> secMan =
- do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIPrincipal> subject;
- rv = secMan->GetSubjectPrincipal(getter_AddRefs(subject));
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (subject) {
- bool subsumes;
- rv = subject->Subsumes(theDoc->NodePrincipal(), &subsumes);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!subsumes) {
- return NS_ERROR_DOM_PROP_ACCESS_DENIED;
- }
+ if (!nsContentUtils::GetSubjectPrincipal()->Subsumes(theDoc->NodePrincipal())) {
+ return NS_ERROR_DOM_PROP_ACCESS_DENIED;
}
nsCOMPtr<nsIFind> find = do_CreateInstance(NS_FIND_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
(void) find->SetCaseSensitive(mMatchCase);
(void) find->SetFindBackwards(mFindBackwards);
--- a/embedding/components/windowwatcher/src/nsWindowWatcher.cpp
+++ b/embedding/components/windowwatcher/src/nsWindowWatcher.cpp
@@ -780,25 +780,24 @@ nsWindowWatcher::OpenWindowInternal(nsID
newDocShellItem->SetName(name);
} else {
newDocShellItem->SetName(EmptyString());
}
}
// Now we have to set the right opener principal on the new window. Note
// that we have to do this _before_ starting any URI loads, thanks to the
- // sync nature of javascript: loads. Since this is the only place where we
- // set said opener principal, we need to do it for all URIs, including
- // chrome ones. So to deal with the mess that is bug 79775, just press on in
- // a reasonable way even if GetSubjectPrincipal fails. In that case, just
- // use a null subjectPrincipal.
- nsCOMPtr<nsIPrincipal> subjectPrincipal;
- if (NS_FAILED(sm->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal)))) {
- subjectPrincipal = nullptr;
- }
+ // sync nature of javascript: loads.
+ //
+ // Note: The check for the current JSContext isn't necessarily sensical.
+ // It's just designed to preserve old semantics during a mass-conversion
+ // patch.
+ nsCOMPtr<nsIPrincipal> subjectPrincipal =
+ nsContentUtils::GetCurrentJSContext() ? nsContentUtils::GetSubjectPrincipal()
+ : nullptr;
if (windowIsNew) {
// Now set the opener principal on the new window. Note that we need to do
// this no matter whether we were opened from JS; if there is nothing on
// the JS stack, just use the principal of our parent window. In those
// cases we do _not_ set the parent window principal as the owner of the
// load--since we really don't know who the owner is, just leave it null.
nsCOMPtr<nsPIDOMWindow> newWindow = do_QueryInterface(*_retval);
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -298,16 +298,29 @@ GLContext::~GLContext() {
tip->SharedContextDestroyed(this);
tip->ReportOutstandingNames();
} else {
ReportOutstandingNames();
}
#endif
}
+/*static*/ void
+GLContext::StaticDebugCallback(GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ GLsizei length,
+ const GLchar* message,
+ const GLvoid* userParam)
+{
+ GLContext* gl = (GLContext*)userParam;
+ gl->DebugCallback(source, type, id, severity, length, message);
+}
+
bool
GLContext::InitWithPrefix(const char *prefix, bool trygl)
{
ScopedGfxFeatureReporter reporter("GL Context");
if (mInitialized) {
reporter.SetSuccessful();
return true;
@@ -1154,32 +1167,132 @@ GLContext::InitWithPrefix(const char *pr
DetermineCaps();
UpdatePixelFormat();
UpdateGLFormats(mCaps);
mTexGarbageBin = new TextureGarbageBin(this);
MOZ_ASSERT(IsCurrent());
+
+ if (DebugMode() && IsExtensionSupported(KHR_debug)) {
+ fEnable(LOCAL_GL_DEBUG_OUTPUT);
+ fDisable(LOCAL_GL_DEBUG_OUTPUT_SYNCHRONOUS);
+ fDebugMessageCallback(&StaticDebugCallback, (void*)this);
+ fDebugMessageControl(LOCAL_GL_DONT_CARE,
+ LOCAL_GL_DONT_CARE,
+ LOCAL_GL_DONT_CARE,
+ 0, nullptr,
+ true);
+ }
}
if (mInitialized)
reporter.SetSuccessful();
else {
// if initialization fails, ensure all symbols are zero, to avoid hard-to-understand bugs
mSymbols.Zero();
NS_WARNING("InitWithPrefix failed!");
}
mVersionString = nsPrintfCString("%u.%u.%u", mVersion / 100, (mVersion / 10) % 10, mVersion % 10);
return mInitialized;
}
void
+GLContext::DebugCallback(GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ GLsizei length,
+ const GLchar* message)
+{
+ nsAutoCString sourceStr;
+ switch (source) {
+ case LOCAL_GL_DEBUG_SOURCE_API:
+ sourceStr = NS_LITERAL_CSTRING("SOURCE_API");
+ break;
+ case LOCAL_GL_DEBUG_SOURCE_WINDOW_SYSTEM:
+ sourceStr = NS_LITERAL_CSTRING("SOURCE_WINDOW_SYSTEM");
+ break;
+ case LOCAL_GL_DEBUG_SOURCE_SHADER_COMPILER:
+ sourceStr = NS_LITERAL_CSTRING("SOURCE_SHADER_COMPILER");
+ break;
+ case LOCAL_GL_DEBUG_SOURCE_THIRD_PARTY:
+ sourceStr = NS_LITERAL_CSTRING("SOURCE_THIRD_PARTY");
+ break;
+ case LOCAL_GL_DEBUG_SOURCE_APPLICATION:
+ sourceStr = NS_LITERAL_CSTRING("SOURCE_APPLICATION");
+ break;
+ case LOCAL_GL_DEBUG_SOURCE_OTHER:
+ sourceStr = NS_LITERAL_CSTRING("SOURCE_OTHER");
+ break;
+ default:
+ sourceStr = nsPrintfCString("<source 0x%04x>", source);
+ break;
+ }
+
+ nsAutoCString typeStr;
+ switch (type) {
+ case LOCAL_GL_DEBUG_TYPE_ERROR:
+ typeStr = NS_LITERAL_CSTRING("TYPE_ERROR");
+ break;
+ case LOCAL_GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
+ typeStr = NS_LITERAL_CSTRING("TYPE_DEPRECATED_BEHAVIOR");
+ break;
+ case LOCAL_GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
+ typeStr = NS_LITERAL_CSTRING("TYPE_UNDEFINED_BEHAVIOR");
+ break;
+ case LOCAL_GL_DEBUG_TYPE_PORTABILITY:
+ typeStr = NS_LITERAL_CSTRING("TYPE_PORTABILITY");
+ break;
+ case LOCAL_GL_DEBUG_TYPE_PERFORMANCE:
+ typeStr = NS_LITERAL_CSTRING("TYPE_PERFORMANCE");
+ break;
+ case LOCAL_GL_DEBUG_TYPE_OTHER:
+ typeStr = NS_LITERAL_CSTRING("TYPE_OTHER");
+ break;
+ case LOCAL_GL_DEBUG_TYPE_MARKER:
+ typeStr = NS_LITERAL_CSTRING("TYPE_MARKER");
+ break;
+ default:
+ typeStr = nsPrintfCString("<type 0x%04x>", type);
+ break;
+ }
+
+ nsAutoCString sevStr;
+ switch (severity) {
+ case LOCAL_GL_DEBUG_SEVERITY_HIGH:
+ sevStr = NS_LITERAL_CSTRING("SEVERITY_HIGH");
+ break;
+ case LOCAL_GL_DEBUG_SEVERITY_MEDIUM:
+ sevStr = NS_LITERAL_CSTRING("SEVERITY_MEDIUM");
+ break;
+ case LOCAL_GL_DEBUG_SEVERITY_LOW:
+ sevStr = NS_LITERAL_CSTRING("SEVERITY_LOW");
+ break;
+ case LOCAL_GL_DEBUG_SEVERITY_NOTIFICATION:
+ sevStr = NS_LITERAL_CSTRING("SEVERITY_NOTIFICATION");
+ break;
+ default:
+ sevStr = nsPrintfCString("<severity 0x%04x>", severity);
+ break;
+ }
+
+ printf_stderr("[KHR_debug: 0x%x] ID %u: %s %s %s:\n %s",
+ (uintptr_t)this,
+ id,
+ sourceStr.BeginReading(),
+ typeStr.BeginReading(),
+ sevStr.BeginReading(),
+ message);
+}
+
+void
GLContext::InitExtensions()
{
MakeCurrent();
const char* extensions = (const char*)fGetString(LOCAL_GL_EXTENSIONS);
if (!extensions)
return;
#ifdef DEBUG
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -577,16 +577,30 @@ public:
#ifdef DEBUG
private:
GLenum mGLError;
#endif // DEBUG
+ static void GLAPIENTRY StaticDebugCallback(GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ GLsizei length,
+ const GLchar* message,
+ const GLvoid* userParam);
+ void DebugCallback(GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ GLsizei length,
+ const GLchar* message);
+
// -----------------------------------------------------------------------------
// MOZ_GL_DEBUG implementation
private:
#undef BEFORE_GL_CALL
#undef AFTER_GL_CALL
--- a/gfx/layers/FrameMetrics.h
+++ b/gfx/layers/FrameMetrics.h
@@ -200,16 +200,24 @@ public:
return mCompositionBounds.Size() / GetZoomToParent();
}
CSSRect CalculateCompositedRectInCssPixels() const
{
return mCompositionBounds / GetZoomToParent();
}
+ CSSSize CalculateBoundedCompositedSizeInCssPixels() const
+ {
+ CSSSize size = CalculateCompositedSizeInCssPixels();
+ size.width = std::min(size.width, mRootCompositionSize.width);
+ size.height = std::min(size.height, mRootCompositionSize.height);
+ return size;
+ }
+
void ScrollBy(const CSSPoint& aPoint)
{
mScrollOffset += aPoint;
}
void ZoomBy(float aFactor)
{
mZoom.scale *= aFactor;
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -1480,21 +1480,17 @@ RedistributeDisplayPortExcess(CSSSize& a
}
/* static */
const LayerMargin AsyncPanZoomController::CalculatePendingDisplayPort(
const FrameMetrics& aFrameMetrics,
const ScreenPoint& aVelocity,
double aEstimatedPaintDuration)
{
- CSSSize compositionBounds = aFrameMetrics.CalculateCompositedSizeInCssPixels();
- CSSSize compositionSize = aFrameMetrics.GetRootCompositionSize();
- compositionSize =
- CSSSize(std::min(compositionBounds.width, compositionSize.width),
- std::min(compositionBounds.height, compositionSize.height));
+ CSSSize compositionSize = aFrameMetrics.CalculateBoundedCompositedSizeInCssPixels();
CSSPoint velocity = aVelocity / aFrameMetrics.GetZoom();
CSSPoint scrollOffset = aFrameMetrics.GetScrollOffset();
CSSRect scrollableRect = aFrameMetrics.GetExpandedScrollableRect();
// Calculate the displayport size based on how fast we're moving along each axis.
CSSSize displayPortSize = CalculateDisplayPortSize(compositionSize, velocity);
if (gfxPrefs::APZEnlargeDisplayPortWhenClipped()) {
@@ -1590,20 +1586,17 @@ void AsyncPanZoomController::RequestCont
}
/*static*/ CSSRect
GetDisplayPortRect(const FrameMetrics& aFrameMetrics)
{
// This computation is based on what happens in CalculatePendingDisplayPort. If that
// changes then this might need to change too
CSSRect baseRect(aFrameMetrics.GetScrollOffset(),
- CSSSize(std::min(aFrameMetrics.CalculateCompositedSizeInCssPixels().width,
- aFrameMetrics.GetRootCompositionSize().width),
- std::min(aFrameMetrics.CalculateCompositedSizeInCssPixels().height,
- aFrameMetrics.GetRootCompositionSize().height)));
+ aFrameMetrics.CalculateBoundedCompositedSizeInCssPixels());
baseRect.Inflate(aFrameMetrics.GetDisplayPortMargins() / aFrameMetrics.LayersPixelsPerCSSPixel());
return baseRect;
}
void
AsyncPanZoomController::DispatchRepaintRequest(const FrameMetrics& aFrameMetrics) {
nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
if (controller) {
--- a/gfx/layers/client/TiledContentClient.cpp
+++ b/gfx/layers/client/TiledContentClient.cpp
@@ -236,17 +236,21 @@ SharedFrameMetricsHelper::FindFallbackCo
aZoom = contentMetrics->GetZoomToParent(); // TODO(botond): double-check this
return;
}
bool
SharedFrameMetricsHelper::AboutToCheckerboard(const FrameMetrics& aContentMetrics,
const FrameMetrics& aCompositorMetrics)
{
- return !aContentMetrics.mDisplayPort.Contains(aCompositorMetrics.CalculateCompositedRectInCssPixels() - aCompositorMetrics.GetScrollOffset());
+ CSSRect painted =
+ (aContentMetrics.mCriticalDisplayPort.IsEmpty() ? aContentMetrics.mDisplayPort : aContentMetrics.mCriticalDisplayPort)
+ + aContentMetrics.GetScrollOffset();
+ CSSRect showing = CSSRect(aCompositorMetrics.GetScrollOffset(), aCompositorMetrics.CalculateBoundedCompositedSizeInCssPixels());
+ return !painted.Contains(showing);
}
ClientTiledLayerBuffer::ClientTiledLayerBuffer(ClientTiledThebesLayer* aThebesLayer,
CompositableClient* aCompositableClient,
ClientLayerManager* aManager,
SharedFrameMetricsHelper* aHelper)
: mThebesLayer(aThebesLayer)
, mCompositableClient(aCompositableClient)
--- a/image/src/imgDecoderObserver.h
+++ b/image/src/imgDecoderObserver.h
@@ -28,21 +28,20 @@ struct nsIntRect;
* relied upon.
*
* Decode notifications may or may not be synchronous, depending on the
* situation. If imgIDecoder::FLAG_SYNC_DECODE is passed to a function that
* triggers a decode, all notifications that can be generated from the currently
* loaded data fire before the call returns. If FLAG_SYNC_DECODE is not passed,
* all, some, or none of the notifications may fire before the call returns.
*/
-class imgDecoderObserver : public mozilla::RefCounted<imgDecoderObserver>
+class imgDecoderObserver
{
public:
- MOZ_DECLARE_REFCOUNTED_TYPENAME(imgDecoderObserver)
- virtual ~imgDecoderObserver() = 0;
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(imgDecoderObserver);
/**
* Load notification.
*
* called at the same time that nsIRequestObserver::onStartRequest would be
* (used only for observers of imgIRequest objects, which are nsIRequests,
* not imgIDecoder objects)
*/
@@ -121,16 +120,19 @@ public:
* Called when we are asked to Draw an image that is not locked.
*/
virtual void OnUnlockedDraw() = 0;
/**
* Called when an image is realized to be in error state.
*/
virtual void OnError() = 0;
+
+protected:
+ virtual ~imgDecoderObserver() = 0;
};
// We must define a destructor because derived classes call our destructor from
// theirs. Pure virtual destructors only requires that child classes implement
// a virtual destructor, not that we can't have one too!
inline imgDecoderObserver::~imgDecoderObserver()
{}
--- a/image/src/imgStatusTracker.cpp
+++ b/image/src/imgStatusTracker.cpp
@@ -24,18 +24,16 @@ class imgStatusTrackerObserver : public
{
public:
imgStatusTrackerObserver(imgStatusTracker* aTracker)
: mTracker(aTracker->asWeakPtr())
{
MOZ_ASSERT(aTracker);
}
- virtual ~imgStatusTrackerObserver() {}
-
void SetTracker(imgStatusTracker* aTracker)
{
MOZ_ASSERT(aTracker);
mTracker = aTracker->asWeakPtr();
}
/** imgDecoderObserver methods **/
@@ -138,16 +136,19 @@ public:
virtual void OnError() MOZ_OVERRIDE
{
LOG_SCOPE(GetImgLog(), "imgStatusTrackerObserver::OnError");
nsRefPtr<imgStatusTracker> tracker = mTracker.get();
if (!tracker) { return; }
tracker->RecordError();
}
+protected:
+ virtual ~imgStatusTrackerObserver() {}
+
private:
WeakPtr<imgStatusTracker> mTracker;
};
// imgStatusTracker methods
imgStatusTracker::imgStatusTracker(Image* aImage)
: mImage(aImage),
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/bug1006205.js
@@ -0,0 +1,20 @@
+var lfcode = new Array();
+lfcode.push = loadFile;
+lfcode.push("\
+var g = newGlobal();\
+g.debuggeeGlobal = this;\
+g.eval(\"(\" + function () {\
+ dbg = new Debugger(debuggeeGlobal);\
+ } + \")();\");\
+");
+lfcode.push("gc();");
+lfcode.push("\
+var g = newGlobal();\
+g.debuggeeGlobal = this;\
+g.eval(\"(\" + function () {\
+ dbg = new Debugger(debuggeeGlobal);\
+} + \")();\");\
+");
+function loadFile(lfVarx) {
+function newFunc(x) { new Function(x)(); }; newFunc(lfVarx);
+}
--- a/js/src/jit-test/tests/debug/optimized-out-01.js
+++ b/js/src/jit-test/tests/debug/optimized-out-01.js
@@ -20,19 +20,20 @@ withJitOptions(Opts_Ion2NoParallelCompil
var frame = dbg.getNewestFrame();
assertEq(frame.implementation, "ion");
// x is unused and should be elided.
assertEq(frame.environment.getVariable("x").optimizedOut, true);
assertEq(frame.arguments[1].optimizedOut, true);
}
};
- g.eval("" + function f(d, x) { g(d, x); });
+ g.eval("" + function f(d, x) { "use strict"; g(d, x); });
g.eval("" + function g(d, x) {
+ "use strict";
for (var i = 0; i < 200; i++);
// Hack to prevent inlining.
function inner() { i = 42; };
toggle(d);
});
g.eval("(" + function test() {
for (i = 0; i < 5; i++)
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug1001382.js
@@ -0,0 +1,10 @@
+var i = 0;
+var expectedmatch = '';
+var expectedmatches = new Array();
+addThis();
+expectedmatch = null;
+addThis();
+function addThis() {
+ Array(-2147483648, -2147483648);
+ expectedmatches[i] = expectedmatch;
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug1005458.js
@@ -0,0 +1,5 @@
+(function(x) {
+ for (var y = 0; y < 1; y++) {
+ assertEq(Array.prototype.shift.call(arguments.callee.arguments), 0);
+ }
+})(0)
--- a/js/src/jit/AsmJSModule.cpp
+++ b/js/src/jit/AsmJSModule.cpp
@@ -162,20 +162,20 @@ InvokeFromAsmJS_ToInt32(JSContext *cx, i
int32_t
InvokeFromAsmJS_ToNumber(JSContext *cx, int32_t exitIndex, int32_t argc, Value *argv);
}
#if defined(JS_CODEGEN_ARM)
extern "C" {
-extern int64_t
+extern MOZ_EXPORT int64_t
__aeabi_idivmod(int, int);
-extern int64_t
+extern MOZ_EXPORT int64_t
__aeabi_uidivmod(int, int);
}
#endif
template <class F>
static inline void *
FuncCast(F *pf)
@@ -1241,17 +1241,17 @@ struct ScopedCacheEntryOpenedForWrite
intptr_t handle;
ScopedCacheEntryOpenedForWrite(ExclusiveContext *cx, size_t serializedSize)
: cx(cx), serializedSize(serializedSize), memory(nullptr), handle(-1)
{}
~ScopedCacheEntryOpenedForWrite() {
if (memory)
- cx->asmJSCacheOps().closeEntryForWrite(cx->global(), serializedSize, memory, handle);
+ cx->asmJSCacheOps().closeEntryForWrite(serializedSize, memory, handle);
}
};
bool
js::StoreAsmJSModuleInCache(AsmJSParser &parser,
const AsmJSModule &module,
ExclusiveContext *cx)
{
@@ -1298,17 +1298,17 @@ struct ScopedCacheEntryOpenedForRead
intptr_t handle;
ScopedCacheEntryOpenedForRead(ExclusiveContext *cx)
: cx(cx), serializedSize(0), memory(nullptr), handle(0)
{}
~ScopedCacheEntryOpenedForRead() {
if (memory)
- cx->asmJSCacheOps().closeEntryForRead(cx->global(), serializedSize, memory, handle);
+ cx->asmJSCacheOps().closeEntryForRead(serializedSize, memory, handle);
}
};
bool
js::LookupAsmJSModuleInCache(ExclusiveContext *cx,
AsmJSParser &parser,
ScopedJSDeletePtr<AsmJSModule> *moduleOut,
ScopedJSFreePtr<char> *compilationTimeReport)
--- a/js/src/jit/BaselineDebugModeOSR.cpp
+++ b/js/src/jit/BaselineDebugModeOSR.cpp
@@ -88,16 +88,20 @@ struct DebugModeOSREntry
bool needsRecompileInfo() const {
return (frameKind == ICEntry::Kind_CallVM ||
frameKind == ICEntry::Kind_DebugTrap ||
frameKind == ICEntry::Kind_DebugPrologue ||
frameKind == ICEntry::Kind_DebugEpilogue);
}
+ bool recompiled() const {
+ return oldBaselineScript != script->baselineScript();
+ }
+
BaselineDebugModeOSRInfo *takeRecompInfo() {
MOZ_ASSERT(recompInfo);
BaselineDebugModeOSRInfo *tmp = recompInfo;
recompInfo = nullptr;
return tmp;
}
bool allocateRecompileInfo(JSContext *cx) {
@@ -203,28 +207,27 @@ ICEntryKindToString(ICEntry::Kind kind)
}
}
static void
SpewPatchBaselineFrame(uint8_t *oldReturnAddress, uint8_t *newReturnAddress,
JSScript *script, ICEntry::Kind frameKind, jsbytecode *pc)
{
IonSpew(IonSpew_BaselineDebugModeOSR,
- "Patch return %#016llx -> %#016llx to BaselineJS (%s:%d) from %s at %s",
- uintptr_t(oldReturnAddress), uintptr_t(newReturnAddress),
- script->filename(), script->lineno(),
+ "Patch return %p -> %p on BaselineJS frame (%s:%d) from %s at %s",
+ oldReturnAddress, newReturnAddress, script->filename(), script->lineno(),
ICEntryKindToString(frameKind), js_CodeName[(JSOp)*pc]);
}
static void
SpewPatchStubFrame(ICStub *oldStub, ICStub *newStub)
{
IonSpew(IonSpew_BaselineDebugModeOSR,
- "Patch stub %#016llx -> %#016llx to BaselineStub (%s)",
- uintptr_t(oldStub), uintptr_t(newStub), ICStub::KindString(newStub->kind()));
+ "Patch stub %p -> %p on BaselineStub frame (%s)",
+ oldStub, newStub, ICStub::KindString(newStub->kind()));
}
static void
PatchBaselineFramesForDebugMode(JSContext *cx, const JitActivationIterator &activation,
DebugModeOSREntryVector &entries, size_t *start)
{
//
// Recompile Patching Overview
@@ -249,18 +252,25 @@ PatchBaselineFramesForDebugMode(JSContex
//
IonCommonFrameLayout *prev = nullptr;
size_t entryIndex = *start;
DebugOnly<bool> expectedDebugMode = cx->compartment()->debugMode();
for (JitFrameIterator iter(activation); !iter.done(); ++iter) {
DebugModeOSREntry &entry = entries[entryIndex];
+
switch (iter.type()) {
case JitFrame_BaselineJS: {
+ // If the script wasn't recompiled, there's nothing to patch.
+ if (!entry.recompiled()) {
+ entryIndex++;
+ break;
+ }
+
JSScript *script = entry.script;
uint32_t pcOffset = entry.pcOffset;
jsbytecode *pc = script->offsetToPC(pcOffset);
MOZ_ASSERT(script == iter.script());
MOZ_ASSERT(pcOffset < script->length());
MOZ_ASSERT(script->baselineScript()->debugMode() == expectedDebugMode);
@@ -346,16 +356,20 @@ PatchBaselineFramesForDebugMode(JSContex
prev->setReturnAddress(reinterpret_cast<uint8_t *>(handlerAddr));
iter.baselineFrame()->setDebugModeOSRInfo(recompInfo);
entryIndex++;
break;
}
case JitFrame_BaselineStub: {
+ // If the script wasn't recompiled, there's nothing to patch.
+ if (!entry.recompiled())
+ break;
+
IonBaselineStubFrameLayout *layout =
reinterpret_cast<IonBaselineStubFrameLayout *>(iter.fp());
MOZ_ASSERT(entry.script->baselineScript()->debugMode() == expectedDebugMode);
MOZ_ASSERT(layout->maybeStubPtr() == entry.oldStub);
// Patch baseline stub frames for case A above.
//
// We need to patch the stub frame to point to an ICStub belonging
@@ -534,17 +548,17 @@ static void
UndoRecompileBaselineScriptsForDebugMode(JSContext *cx,
const DebugModeOSREntryVector &entries)
{
// In case of failure, roll back the entire set of active scripts so that
// we don't have to patch return addresses on the stack.
for (size_t i = 0; i < entries.length(); i++) {
JSScript *script = entries[i].script;
BaselineScript *baselineScript = script->baselineScript();
- if (baselineScript != entries[i].oldBaselineScript) {
+ if (entries[i].recompiled()) {
script->setBaselineScript(cx, entries[i].oldBaselineScript);
BaselineScript::Destroy(cx->runtime()->defaultFreeOp(), baselineScript);
}
}
}
bool
jit::RecompileOnStackBaselineScriptsForDebugMode(JSContext *cx, JSCompartment *comp)
@@ -582,18 +596,20 @@ jit::RecompileOnStackBaselineScriptsForD
}
}
// If all recompiles succeeded, destroy the old baseline scripts and patch
// the live frames.
//
// After this point the function must be infallible.
- for (size_t i = 0; i < entries.length(); i++)
- BaselineScript::Destroy(cx->runtime()->defaultFreeOp(), entries[i].oldBaselineScript);
+ for (size_t i = 0; i < entries.length(); i++) {
+ if (entries[i].recompiled())
+ BaselineScript::Destroy(cx->runtime()->defaultFreeOp(), entries[i].oldBaselineScript);
+ }
size_t processed = 0;
for (JitActivationIterator iter(cx->runtime()); !iter.done(); ++iter) {
if (iter.activation()->compartment() == comp)
PatchBaselineFramesForDebugMode(cx, iter, entries, &processed);
}
MOZ_ASSERT(processed == entries.length());
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -1266,16 +1266,24 @@ ICTypeMonitor_Fallback::addMonitorStubFo
return true;
}
static bool
DoTypeMonitorFallback(JSContext *cx, BaselineFrame *frame, ICTypeMonitor_Fallback *stub,
HandleValue value, MutableHandleValue res)
{
+ // It's possible that we arrived here from bailing out of Ion, and that
+ // Ion proved that the value is dead and optimized out. In such cases, do
+ // nothing.
+ if (value.isMagic(JS_OPTIMIZED_OUT)) {
+ res.set(value);
+ return true;
+ }
+
RootedScript script(cx, frame->script());
jsbytecode *pc = stub->icEntry()->pc(script);
TypeFallbackICSpew(cx, stub, "TypeMonitor");
uint32_t argument;
if (stub->monitorsThis()) {
JS_ASSERT(pc == script->code());
types::TypeScript::SetThis(cx, script, value);
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -6829,16 +6829,17 @@ CodeGenerator::visitStoreFixedSlotT(LSto
bool
CodeGenerator::visitCallsiteCloneCache(LCallsiteCloneCache *ins)
{
const MCallsiteCloneCache *mir = ins->mir();
Register callee = ToRegister(ins->callee());
Register output = ToRegister(ins->output());
CallsiteCloneIC cache(callee, mir->block()->info().script(), mir->callPc(), output);
+ cache.setProfilerLeavePC(mir->profilerLeavePc());
return addCache(ins, allocateCache(cache));
}
typedef JSObject *(*CallsiteCloneICFn)(JSContext *, size_t, HandleObject);
const VMFunction CallsiteCloneIC::UpdateInfo =
FunctionInfo<CallsiteCloneICFn>(CallsiteCloneIC::update);
bool
@@ -6862,16 +6863,17 @@ bool
CodeGenerator::visitGetNameCache(LGetNameCache *ins)
{
RegisterSet liveRegs = ins->safepoint()->liveRegs();
Register scopeChain = ToRegister(ins->scopeObj());
TypedOrValueRegister output(GetValueOutput(ins));
bool isTypeOf = ins->mir()->accessKind() != MGetNameCache::NAME;
NameIC cache(liveRegs, isTypeOf, scopeChain, ins->mir()->name(), output);
+ cache.setProfilerLeavePC(ins->mir()->profilerLeavePc());
return addCache(ins, allocateCache(cache));
}
typedef bool (*NameICFn)(JSContext *, size_t, HandleObject, MutableHandleValue);
const VMFunction NameIC::UpdateInfo = FunctionInfo<NameICFn>(NameIC::update);
bool
CodeGenerator::visitNameIC(OutOfLineUpdateCache *ool, DataPtr<NameIC> &ic)
@@ -6888,94 +6890,103 @@ CodeGenerator::visitNameIC(OutOfLineUpda
masm.jump(ool->rejoin());
return true;
}
bool
CodeGenerator::addGetPropertyCache(LInstruction *ins, RegisterSet liveRegs, Register objReg,
PropertyName *name, TypedOrValueRegister output,
- bool monitoredResult)
+ bool monitoredResult, jsbytecode *profilerLeavePc)
{
switch (gen->info().executionMode()) {
case SequentialExecution: {
GetPropertyIC cache(liveRegs, objReg, name, output, monitoredResult);
+ cache.setProfilerLeavePC(profilerLeavePc);
return addCache(ins, allocateCache(cache));
}
case ParallelExecution: {
GetPropertyParIC cache(objReg, name, output);
+ cache.setProfilerLeavePC(profilerLeavePc);
return addCache(ins, allocateCache(cache));
}
default:
MOZ_ASSUME_UNREACHABLE("Bad execution mode");
}
}
bool
CodeGenerator::addSetPropertyCache(LInstruction *ins, RegisterSet liveRegs, Register objReg,
PropertyName *name, ConstantOrRegister value, bool strict,
- bool needsTypeBarrier)
+ bool needsTypeBarrier, jsbytecode *profilerLeavePc)
{
switch (gen->info().executionMode()) {
case SequentialExecution: {
SetPropertyIC cache(liveRegs, objReg, name, value, strict, needsTypeBarrier);
+ cache.setProfilerLeavePC(profilerLeavePc);
return addCache(ins, allocateCache(cache));
}
case ParallelExecution: {
SetPropertyParIC cache(objReg, name, value, strict, needsTypeBarrier);
+ cache.setProfilerLeavePC(profilerLeavePc);
return addCache(ins, allocateCache(cache));
}
default:
MOZ_ASSUME_UNREACHABLE("Bad execution mode");
}
}
bool
CodeGenerator::addSetElementCache(LInstruction *ins, Register obj, Register unboxIndex,
Register temp, FloatRegister tempFloat, ValueOperand index,
- ConstantOrRegister value, bool strict, bool guardHoles)
+ ConstantOrRegister value, bool strict, bool guardHoles,
+ jsbytecode *profilerLeavePc)
{
switch (gen->info().executionMode()) {
case SequentialExecution: {
SetElementIC cache(obj, unboxIndex, temp, tempFloat, index, value, strict,
guardHoles);
+ cache.setProfilerLeavePC(profilerLeavePc);
return addCache(ins, allocateCache(cache));
}
case ParallelExecution: {
SetElementParIC cache(obj, unboxIndex, temp, tempFloat, index, value, strict,
guardHoles);
+ cache.setProfilerLeavePC(profilerLeavePc);
return addCache(ins, allocateCache(cache));
}
default:
MOZ_ASSUME_UNREACHABLE("Bad execution mode");
}
}
bool
CodeGenerator::visitGetPropertyCacheV(LGetPropertyCacheV *ins)
{
RegisterSet liveRegs = ins->safepoint()->liveRegs();
Register objReg = ToRegister(ins->getOperand(0));
PropertyName *name = ins->mir()->name();
bool monitoredResult = ins->mir()->monitoredResult();
TypedOrValueRegister output = TypedOrValueRegister(GetValueOutput(ins));
- return addGetPropertyCache(ins, liveRegs, objReg, name, output, monitoredResult);
+ return addGetPropertyCache(ins, liveRegs, objReg, name, output, monitoredResult,
+ ins->mir()->profilerLeavePc());
}
bool
CodeGenerator::visitGetPropertyCacheT(LGetPropertyCacheT *ins)
{
RegisterSet liveRegs = ins->safepoint()->liveRegs();
Register objReg = ToRegister(ins->getOperand(0));
PropertyName *name = ins->mir()->name();
bool monitoredResult = ins->mir()->monitoredResult();
TypedOrValueRegister output(ins->mir()->type(), ToAnyRegister(ins->getDef(0)));
- return addGetPropertyCache(ins, liveRegs, objReg, name, output, monitoredResult);
+ return addGetPropertyCache(ins, liveRegs, objReg, name, output, monitoredResult,
+ ins->mir()->profilerLeavePc());
}
typedef bool (*GetPropertyICFn)(JSContext *, size_t, HandleObject, MutableHandleValue);
const VMFunction GetPropertyIC::UpdateInfo =
FunctionInfo<GetPropertyICFn>(GetPropertyIC::update);
bool
CodeGenerator::visitGetPropertyIC(OutOfLineUpdateCache *ool, DataPtr<GetPropertyIC> &ic)
@@ -7021,53 +7032,57 @@ CodeGenerator::visitGetPropertyParIC(Out
masm.jump(ool->rejoin());
return true;
}
bool
CodeGenerator::addGetElementCache(LInstruction *ins, Register obj, ConstantOrRegister index,
TypedOrValueRegister output, bool monitoredResult,
- bool allowDoubleResult)
+ bool allowDoubleResult, jsbytecode *profilerLeavePc)
{
switch (gen->info().executionMode()) {
case SequentialExecution: {
RegisterSet liveRegs = ins->safepoint()->liveRegs();
GetElementIC cache(liveRegs, obj, index, output, monitoredResult, allowDoubleResult);
+ cache.setProfilerLeavePC(profilerLeavePc);
return addCache(ins, allocateCache(cache));
}
case ParallelExecution: {
GetElementParIC cache(obj, index, output, monitoredResult, allowDoubleResult);
+ cache.setProfilerLeavePC(profilerLeavePc);
return addCache(ins, allocateCache(cache));
}
default:
MOZ_ASSUME_UNREACHABLE("No such execution mode");
}
}
bool
CodeGenerator::visitGetElementCacheV(LGetElementCacheV *ins)
{
Register obj = ToRegister(ins->object());
ConstantOrRegister index = TypedOrValueRegister(ToValue(ins, LGetElementCacheV::Index));
TypedOrValueRegister output = TypedOrValueRegister(GetValueOutput(ins));
const MGetElementCache *mir = ins->mir();
- return addGetElementCache(ins, obj, index, output, mir->monitoredResult(), mir->allowDoubleResult());
+ return addGetElementCache(ins, obj, index, output, mir->monitoredResult(),
+ mir->allowDoubleResult(), mir->profilerLeavePc());
}
bool
CodeGenerator::visitGetElementCacheT(LGetElementCacheT *ins)
{
Register obj = ToRegister(ins->object());
ConstantOrRegister index = TypedOrValueRegister(MIRType_Int32, ToAnyRegister(ins->index()));
TypedOrValueRegister output(ins->mir()->type(), ToAnyRegister(ins->output()));
const MGetElementCache *mir = ins->mir();
- return addGetElementCache(ins, obj, index, output, mir->monitoredResult(), mir->allowDoubleResult());
+ return addGetElementCache(ins, obj, index, output, mir->monitoredResult(),
+ mir->allowDoubleResult(), mir->profilerLeavePc());
}
typedef bool (*GetElementICFn)(JSContext *, size_t, HandleObject, HandleValue, MutableHandleValue);
const VMFunction GetElementIC::UpdateInfo =
FunctionInfo<GetElementICFn>(GetElementIC::update);
bool
CodeGenerator::visitGetElementIC(OutOfLineUpdateCache *ool, DataPtr<GetElementIC> &ic)
@@ -7093,17 +7108,18 @@ CodeGenerator::visitSetElementCacheV(LSe
Register obj = ToRegister(ins->object());
Register unboxIndex = ToTempUnboxRegister(ins->tempToUnboxIndex());
Register temp = ToRegister(ins->temp());
FloatRegister tempFloat = ToFloatRegister(ins->tempFloat());
ValueOperand index = ToValue(ins, LSetElementCacheV::Index);
ConstantOrRegister value = TypedOrValueRegister(ToValue(ins, LSetElementCacheV::Value));
return addSetElementCache(ins, obj, unboxIndex, temp, tempFloat, index, value,
- ins->mir()->strict(), ins->mir()->guardHoles());
+ ins->mir()->strict(), ins->mir()->guardHoles(),
+ ins->mir()->profilerLeavePc());
}
bool
CodeGenerator::visitSetElementCacheT(LSetElementCacheT *ins)
{
Register obj = ToRegister(ins->object());
Register unboxIndex = ToTempUnboxRegister(ins->tempToUnboxIndex());
Register temp = ToRegister(ins->temp());
@@ -7112,17 +7128,18 @@ CodeGenerator::visitSetElementCacheT(LSe
ConstantOrRegister value;
const LAllocation *tmp = ins->value();
if (tmp->isConstant())
value = *tmp->toConstant();
else
value = TypedOrValueRegister(ins->mir()->value()->type(), ToAnyRegister(tmp));
return addSetElementCache(ins, obj, unboxIndex, temp, tempFloat, index, value,
- ins->mir()->strict(), ins->mir()->guardHoles());
+ ins->mir()->strict(), ins->mir()->guardHoles(),
+ ins->mir()->profilerLeavePc());
}
typedef bool (*SetElementICFn)(JSContext *, size_t, HandleObject, HandleValue, HandleValue);
const VMFunction SetElementIC::UpdateInfo =
FunctionInfo<SetElementICFn>(SetElementIC::update);
bool
CodeGenerator::visitSetElementIC(OutOfLineUpdateCache *ool, DataPtr<SetElementIC> &ic)
@@ -7188,16 +7205,17 @@ CodeGenerator::visitGetElementParIC(OutO
}
bool
CodeGenerator::visitBindNameCache(LBindNameCache *ins)
{
Register scopeChain = ToRegister(ins->scopeChain());
Register output = ToRegister(ins->output());
BindNameIC cache(scopeChain, ins->mir()->name(), output);
+ cache.setProfilerLeavePC(ins->mir()->profilerLeavePc());
return addCache(ins, allocateCache(cache));
}
typedef JSObject *(*BindNameICFn)(JSContext *, size_t, HandleObject);
const VMFunction BindNameIC::UpdateInfo =
FunctionInfo<BindNameICFn>(BindNameIC::update);
@@ -7282,33 +7300,35 @@ CodeGenerator::visitCallDeleteElement(LC
bool
CodeGenerator::visitSetPropertyCacheV(LSetPropertyCacheV *ins)
{
RegisterSet liveRegs = ins->safepoint()->liveRegs();
Register objReg = ToRegister(ins->getOperand(0));
ConstantOrRegister value = TypedOrValueRegister(ToValue(ins, LSetPropertyCacheV::Value));
return addSetPropertyCache(ins, liveRegs, objReg, ins->mir()->name(), value,
- ins->mir()->strict(), ins->mir()->needsTypeBarrier());
+ ins->mir()->strict(), ins->mir()->needsTypeBarrier(),
+ ins->mir()->profilerLeavePc());
}
bool
CodeGenerator::visitSetPropertyCacheT(LSetPropertyCacheT *ins)
{
RegisterSet liveRegs = ins->safepoint()->liveRegs();
Register objReg = ToRegister(ins->getOperand(0));
ConstantOrRegister value;
if (ins->getOperand(1)->isConstant())
value = ConstantOrRegister(*ins->getOperand(1)->toConstant());
else
value = TypedOrValueRegister(ins->valueType(), ToAnyRegister(ins->getOperand(1)));
return addSetPropertyCache(ins, liveRegs, objReg, ins->mir()->name(), value,
- ins->mir()->strict(), ins->mir()->needsTypeBarrier());
+ ins->mir()->strict(), ins->mir()->needsTypeBarrier(),
+ ins->mir()->profilerLeavePc());
}
typedef bool (*SetPropertyICFn)(JSContext *, size_t, HandleObject, HandleValue);
const VMFunction SetPropertyIC::UpdateInfo =
FunctionInfo<SetPropertyICFn>(SetPropertyIC::update);
bool
CodeGenerator::visitSetPropertyIC(OutOfLineUpdateCache *ool, DataPtr<SetPropertyIC> &ic)
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -348,26 +348,26 @@ class CodeGenerator : public CodeGenerat
bool visitAssertRangeF(LAssertRangeF *ins);
bool visitAssertRangeV(LAssertRangeV *ins);
bool visitRecompileCheck(LRecompileCheck *ins);
private:
bool addGetPropertyCache(LInstruction *ins, RegisterSet liveRegs, Register objReg,
PropertyName *name, TypedOrValueRegister output,
- bool monitoredResult);
+ bool monitoredResult, jsbytecode *profilerLeavePc);
bool addGetElementCache(LInstruction *ins, Register obj, ConstantOrRegister index,
TypedOrValueRegister output, bool monitoredResult,
- bool allowDoubleResult);
+ bool allowDoubleResult, jsbytecode *profilerLeavePc);
bool addSetPropertyCache(LInstruction *ins, RegisterSet liveRegs, Register objReg,
PropertyName *name, ConstantOrRegister value, bool strict,
- bool needsTypeBarrier);
+ bool needsTypeBarrier, jsbytecode *profilerLeavePc);
bool addSetElementCache(LInstruction *ins, Register obj, Register unboxIndex, Register temp,
FloatRegister tempFloat, ValueOperand index, ConstantOrRegister value,
- bool strict, bool guardHoles);
+ bool strict, bool guardHoles, jsbytecode *profilerLeavePc);
bool checkForAbortPar(LInstruction *lir);
bool generateBranchV(const ValueOperand &value, Label *ifTrue, Label *ifFalse, FloatRegister fr);
bool emitAllocateGCThingPar(LInstruction *lir, Register objReg, Register cxReg,
Register tempReg1, Register tempReg2,
JSObject *templateObj);
--- a/js/src/jit/CompileInfo.h
+++ b/js/src/jit/CompileInfo.h
@@ -75,16 +75,25 @@ class InlineScriptTree {
InlineScriptTree *addCallee(TempAllocator *allocator, jsbytecode *callerPc,
JSScript *calleeScript);
InlineScriptTree *caller() const {
return caller_;
}
+ bool isOutermostCaller() const {
+ return caller_ == nullptr;
+ }
+ InlineScriptTree *outermostCaller() {
+ if (isOutermostCaller())
+ return this;
+ return caller_->outermostCaller();
+ }
+
jsbytecode *callerPc() const {
return callerPc_;
}
JSScript *script() const {
return script_;
}
@@ -387,16 +396,25 @@ class CompileInfo
bool executionModeIsAnalysis() const {
return executionMode_ == DefinitePropertiesAnalysis || executionMode_ == ArgumentsUsageAnalysis;
}
bool isParallelExecution() const {
return executionMode_ == ParallelExecution;
}
+ bool canOptimizeOutSlot(uint32_t i) const {
+ if (script()->strict())
+ return true;
+
+ // Function.arguments can be used to access all arguments in
+ // non-strict scripts, so we can't optimize out any arguments.
+ return !(firstArgSlot() <= i && i - firstArgSlot() < nargs());
+ }
+
private:
unsigned nimplicit_;
unsigned nargs_;
unsigned nfixedvars_;
unsigned nlocals_;
unsigned nstack_;
unsigned nslots_;
JSScript *script_;
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -138,26 +138,22 @@ jit::EliminateDeadResumePointOperands(MI
!mrp->instruction() ||
mrp->instruction() == *ins ||
mrp->instruction()->id() <= maxDefinition)
{
uses++;
continue;
}
- // Function.arguments can be used to access all arguments in
- // non-strict scripts, so we can't optimize out any arguments.
- CompileInfo &info = block->info();
- if (!info.script()->strict()) {
- uint32_t slot = uses->index();
- uint32_t firstArgSlot = info.firstArgSlot();
- if (firstArgSlot <= slot && slot - firstArgSlot < info.nargs()) {
- uses++;
- continue;
- }
+ // The operand is an uneliminable slot. This currently
+ // includes argument slots in non-strict scripts (due to being
+ // observable via Function.arguments).
+ if (!block->info().canOptimizeOutSlot(uses->index())) {
+ uses++;
+ continue;
}
// Store an optimized out magic value in place of all dead
// resume point operands. Making any such substitution can in
// general alter the interpreter's behavior, even though the
// code is dead, as the interpreter will still execute opcodes
// whose effects cannot be observed. If the magic value value
// were to flow to, say, a dead property access the
@@ -249,28 +245,21 @@ IsPhiObservable(MPhi *phi, Observability
// arguments object during bailout. If we've already created an arguments
// object (or got one via OSR), preserve that as well.
if (fun && info.hasArguments() &&
(slot == info.scopeChainSlot() || slot == info.argsObjSlot()))
{
return true;
}
- // If the Phi is one of the formal argument, and we are using an argument
- // object in the function. The phi might be observable after a bailout.
- // For inlined frames this is not needed, as they are captured in the inlineResumePoint.
- if (fun && info.hasArguments()) {
- uint32_t first = info.firstArgSlot();
- if (first <= slot && slot - first < info.nargs()) {
- // If arguments obj aliases formals, then the arg slots will never be used.
- if (info.argsObjAliasesFormals())
- return false;
- return true;
- }
- }
+ // The Phi is an uneliminable slot. Currently this includes argument slots
+ // in non-strict scripts (due to being observable via Function.arguments).
+ if (fun && !info.canOptimizeOutSlot(slot))
+ return true;
+
return false;
}
// Handles cases like:
// x is phi(a, x) --> a
// x is phi(a, a) --> a
static inline MDefinition *
IsPhiRedundant(MPhi *phi)
--- a/js/src/jit/IonCaches.cpp
+++ b/js/src/jit/IonCaches.cpp
@@ -27,16 +27,18 @@
#include "vm/Interpreter-inl.h"
#include "vm/Shape-inl.h"
using namespace js;
using namespace js::jit;
using mozilla::tl::FloorLog2;
+typedef Rooted<TypedArrayObject *> RootedTypedArrayObject;
+
void
CodeLocationJump::repoint(JitCode *code, MacroAssembler *masm)
{
JS_ASSERT(state_ == Relative);
size_t new_off = (size_t)raw_;
#ifdef JS_SMALL_BRANCH
size_t jumpTableEntryOffset = reinterpret_cast<size_t>(jumpTableEntry_);
#endif
@@ -1190,33 +1192,35 @@ GetPropertyIC::allowArrayLength(Context
if (!bcTypes->hasType(types::Type::Int32Type()))
return false;
}
return true;
}
bool
-GetPropertyIC::tryAttachNative(JSContext *cx, IonScript *ion, HandleObject obj,
- HandlePropertyName name, void *returnAddr, bool *emitted)
+GetPropertyIC::tryAttachNative(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, HandlePropertyName name,
+ void *returnAddr, bool *emitted)
{
JS_ASSERT(canAttachStub());
JS_ASSERT(!*emitted);
+ JS_ASSERT(outerScript->ionScript() == ion);
RootedShape shape(cx);
RootedObject holder(cx);
NativeGetPropCacheability type =
CanAttachNativeGetProp(cx, *this, obj, name, &holder, &shape);
if (type == CanAttachNone)
return true;
*emitted = true;
- MacroAssembler masm(cx, ion, script_, pc_);
+ MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
RepatchStubAppender attacher(*this);
const char *attachKind;
switch (type) {
case CanAttachReadSlot:
GenerateReadSlot(cx, ion, masm, attacher, obj, holder,
shape, object(), output());
@@ -1239,18 +1243,18 @@ GetPropertyIC::tryAttachNative(JSContext
break;
default:
MOZ_ASSUME_UNREACHABLE("Bad NativeGetPropCacheability");
}
return linkAndAttachStub(cx, masm, attacher, ion, attachKind);
}
bool
-GetPropertyIC::tryAttachTypedArrayLength(JSContext *cx, IonScript *ion, HandleObject obj,
- HandlePropertyName name, bool *emitted)
+GetPropertyIC::tryAttachTypedArrayLength(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, HandlePropertyName name, bool *emitted)
{
JS_ASSERT(canAttachStub());
JS_ASSERT(!*emitted);
if (!obj->is<TypedArrayObject>())
return true;
if (cx->names().length != name)
@@ -1265,17 +1269,17 @@ GetPropertyIC::tryAttachTypedArrayLength
return true;
}
if (idempotent())
return true;
*emitted = true;
- MacroAssembler masm(cx, ion);
+ MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
RepatchStubAppender attacher(*this);
GenerateTypedArrayLength(cx, masm, attacher, obj, object(), output());
JS_ASSERT(!hasTypedArrayLengthStub_);
hasTypedArrayLengthStub_ = true;
return linkAndAttachStub(cx, masm, attacher, ion, "typed array length");
}
@@ -1348,33 +1352,33 @@ EmitCallProxyGet(JSContext *cx, MacroAss
// masm.leaveExitFrame & pop locals
masm.adjustStack(IonOOLProxyExitFrameLayout::Size());
masm.icRestoreLive(liveRegs, aic);
return true;
}
bool
-GetPropertyIC::tryAttachDOMProxyShadowed(JSContext *cx, IonScript *ion,
+GetPropertyIC::tryAttachDOMProxyShadowed(JSContext *cx, HandleScript outerScript, IonScript *ion,
HandleObject obj, void *returnAddr,
bool *emitted)
{
JS_ASSERT(canAttachStub());
JS_ASSERT(!*emitted);
JS_ASSERT(IsCacheableDOMProxy(obj));
JS_ASSERT(monitoredResult());
JS_ASSERT(output().hasValue());
if (idempotent())
return true;
*emitted = true;
Label failures;
- MacroAssembler masm(cx, ion, script_, pc_);
+ MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
RepatchStubAppender attacher(*this);
// Guard on the shape of the object.
attacher.branchNextStubOrLabel(masm, Assembler::NotEqual,
Address(object(), JSObject::offsetOfShape()),
ImmGCPtr(obj->lastProperty()),
&failures);
@@ -1394,19 +1398,19 @@ GetPropertyIC::tryAttachDOMProxyShadowed
// Failure.
masm.bind(&failures);
attacher.jumpNextStub(masm);
return linkAndAttachStub(cx, masm, attacher, ion, "list base shadowed get");
}
bool
-GetPropertyIC::tryAttachDOMProxyUnshadowed(JSContext *cx, IonScript *ion, HandleObject obj,
- HandlePropertyName name, bool resetNeeded,
- void *returnAddr, bool *emitted)
+GetPropertyIC::tryAttachDOMProxyUnshadowed(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, HandlePropertyName name,
+ bool resetNeeded, void *returnAddr, bool *emitted)
{
JS_ASSERT(canAttachStub());
JS_ASSERT(!*emitted);
JS_ASSERT(IsCacheableDOMProxy(obj));
JS_ASSERT(monitoredResult());
JS_ASSERT(output().hasValue());
RootedObject checkObj(cx, obj->getTaggedProto().toObjectOrNull());
@@ -1433,17 +1437,17 @@ GetPropertyIC::tryAttachDOMProxyUnshadow
// (if there is one). The generation is a constant in the generated
// code and we will not have the same generation again for this
// object, so the generation check in the existing IC would always
// fail anyway.
reset();
}
Label failures;
- MacroAssembler masm(cx, ion, script_, pc_);
+ MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
RepatchStubAppender attacher(*this);
// Guard on the shape of the object.
attacher.branchNextStubOrLabel(masm, Assembler::NotEqual,
Address(object(), JSObject::offsetOfShape()),
ImmGCPtr(obj->lastProperty()),
&failures);
@@ -1494,19 +1498,19 @@ GetPropertyIC::tryAttachDOMProxyUnshadow
attacher.jumpRejoin(masm);
masm.bind(&failures);
attacher.jumpNextStub(masm);
return linkAndAttachStub(cx, masm, attacher, ion, "unshadowed proxy get");
}
bool
-GetPropertyIC::tryAttachProxy(JSContext *cx, IonScript *ion, HandleObject obj,
- HandlePropertyName name, void *returnAddr,
- bool *emitted)
+GetPropertyIC::tryAttachProxy(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, HandlePropertyName name,
+ void *returnAddr, bool *emitted)
{
JS_ASSERT(canAttachStub());
JS_ASSERT(!*emitted);
if (!obj->is<ProxyObject>())
return true;
// TI can't be sure about our properties, so make sure anything
@@ -1516,38 +1520,38 @@ GetPropertyIC::tryAttachProxy(JSContext
// Skim off DOM proxies.
if (IsCacheableDOMProxy(obj)) {
RootedId id(cx, NameToId(name));
DOMProxyShadowsResult shadows = GetDOMProxyShadowsCheck()(cx, obj, id);
if (shadows == ShadowCheckFailed)
return false;
if (shadows == Shadows)
- return tryAttachDOMProxyShadowed(cx, ion, obj, returnAddr, emitted);
-
- return tryAttachDOMProxyUnshadowed(cx, ion, obj, name, shadows == DoesntShadowUnique,
- returnAddr, emitted);
+ return tryAttachDOMProxyShadowed(cx, outerScript, ion, obj, returnAddr, emitted);
+
+ return tryAttachDOMProxyUnshadowed(cx, outerScript, ion, obj, name,
+ shadows == DoesntShadowUnique, returnAddr, emitted);
}
- return tryAttachGenericProxy(cx, ion, obj, name, returnAddr, emitted);
+ return tryAttachGenericProxy(cx, outerScript, ion, obj, name, returnAddr, emitted);
}
static void
GenerateProxyClassGuards(MacroAssembler &masm, Register object, Register scratchReg,
Label *failures)
{
masm.loadObjClass(object, scratchReg);
masm.branchTest32(Assembler::Zero,
Address(scratchReg, Class::offsetOfFlags()),
Imm32(JSCLASS_IS_PROXY), failures);
}
bool
-GetPropertyIC::tryAttachGenericProxy(JSContext *cx, IonScript *ion, HandleObject obj,
- HandlePropertyName name, void *returnAddr,
+GetPropertyIC::tryAttachGenericProxy(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, HandlePropertyName name, void *returnAddr,
bool *emitted)
{
JS_ASSERT(canAttachStub());
JS_ASSERT(!*emitted);
JS_ASSERT(obj->is<ProxyObject>());
JS_ASSERT(monitoredResult());
JS_ASSERT(output().hasValue());
@@ -1555,17 +1559,17 @@ GetPropertyIC::tryAttachGenericProxy(JSC
return true;
if (idempotent())
return true;
*emitted = true;
Label failures;
- MacroAssembler masm(cx, ion, script_, pc_);
+ MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
RepatchStubAppender attacher(*this);
Register scratchReg = output().valueReg().scratchReg();
GenerateProxyClassGuards(masm, object(), scratchReg, &failures);
// Ensure that the incoming object is not a DOM proxy, so that we can get to
// the specialized stubs
@@ -1585,18 +1589,18 @@ GetPropertyIC::tryAttachGenericProxy(JSC
JS_ASSERT(!hasGenericProxyStub_);
hasGenericProxyStub_ = true;
return linkAndAttachStub(cx, masm, attacher, ion, "Generic Proxy get");
}
bool
-GetPropertyIC::tryAttachArgumentsLength(JSContext *cx, IonScript *ion, HandleObject obj,
- HandlePropertyName name, bool *emitted)
+GetPropertyIC::tryAttachArgumentsLength(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, HandlePropertyName name, bool *emitted)
{
JS_ASSERT(canAttachStub());
JS_ASSERT(!*emitted);
if (name != cx->names().length)
return true;
if (!IsOptimizableArgumentsObjectForLength(obj))
return true;
@@ -1608,17 +1612,17 @@ GetPropertyIC::tryAttachArgumentsLength(
if (hasArgumentsLengthStub(obj->is<StrictArgumentsObject>()))
return true;
*emitted = true;
JS_ASSERT(!idempotent());
Label failures;
- MacroAssembler masm(cx, ion);
+ MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
RepatchStubAppender attacher(*this);
Register tmpReg;
if (output().hasValue()) {
tmpReg = output().valueReg().scratchReg();
} else {
JS_ASSERT(output().type() == MIRType_Int32);
tmpReg = output().typedReg().gpr();
@@ -1655,46 +1659,47 @@ GetPropertyIC::tryAttachArgumentsLength(
}
JS_ASSERT(!hasNormalArgumentsLengthStub_);
hasNormalArgumentsLengthStub_ = true;
return linkAndAttachStub(cx, masm, attacher, ion, "ArgsObj length (normal)");
}
bool
-GetPropertyIC::tryAttachStub(JSContext *cx, IonScript *ion, HandleObject obj,
- HandlePropertyName name, void *returnAddr, bool *emitted)
+GetPropertyIC::tryAttachStub(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, HandlePropertyName name,
+ void *returnAddr, bool *emitted)
{
JS_ASSERT(!*emitted);
if (!canAttachStub())
return true;
- if (!*emitted && !tryAttachArgumentsLength(cx, ion, obj, name, emitted))
+ if (!*emitted && !tryAttachArgumentsLength(cx, outerScript, ion, obj, name, emitted))
return false;
- if (!*emitted && !tryAttachProxy(cx, ion, obj, name, returnAddr, emitted))
+ if (!*emitted && !tryAttachProxy(cx, outerScript, ion, obj, name, returnAddr, emitted))
return false;
- if (!*emitted && !tryAttachNative(cx, ion, obj, name, returnAddr, emitted))
+ if (!*emitted && !tryAttachNative(cx, outerScript, ion, obj, name, returnAddr, emitted))
return false;
- if (!*emitted && !tryAttachTypedArrayLength(cx, ion, obj, name, emitted))
+ if (!*emitted && !tryAttachTypedArrayLength(cx, outerScript, ion, obj, name, emitted))
return false;
return true;
}
/* static */ bool
GetPropertyIC::update(JSContext *cx, size_t cacheIndex,
HandleObject obj, MutableHandleValue vp)
{
void *returnAddr;
- RootedScript topScript(cx, GetTopIonJSScript(cx, &returnAddr));
- IonScript *ion = topScript->ionScript();
+ RootedScript outerScript(cx, GetTopIonJSScript(cx, &returnAddr));
+ IonScript *ion = outerScript->ionScript();
GetPropertyIC &cache = ion->getCache(cacheIndex).toGetProperty();
RootedPropertyName name(cx, cache.name());
AutoFlushCache afc ("GetPropertyCache", cx->runtime()->jitRuntime());
// Override the return value if we are invalidated (bug 728188).
AutoDetectInvalidation adi(cx, vp.address(), ion);
@@ -1702,36 +1707,36 @@ GetPropertyIC::update(JSContext *cx, siz
// If the cache is idempotent, we will redo the op in the interpreter.
if (cache.idempotent())
adi.disable();
// For now, just stop generating new stubs once we hit the stub count
// limit. Once we can make calls from within generated stubs, a new call
// stub will be generated instead and the previous stubs unlinked.
bool emitted = false;
- if (!cache.tryAttachStub(cx, ion, obj, name, returnAddr, &emitted))
+ if (!cache.tryAttachStub(cx, outerScript, ion, obj, name, returnAddr, &emitted))
return false;
if (cache.idempotent() && !emitted) {
// Invalidate the cache if the property was not found, or was found on
// a non-native object. This ensures:
// 1) The property read has no observable side-effects.
// 2) There's no need to dynamically monitor the return type. This would
// be complicated since (due to GVN) there can be multiple pc's
// associated with a single idempotent cache.
IonSpew(IonSpew_InlineCaches, "Invalidating from idempotent cache %s:%d",
- topScript->filename(), topScript->lineno());
-
- topScript->setInvalidatedIdempotentCache();
+ outerScript->filename(), outerScript->lineno());
+
+ outerScript->setInvalidatedIdempotentCache();
// Do not re-invalidate if the lookup already caused invalidation.
- if (!topScript->hasIonScript())
+ if (!outerScript->hasIonScript())
return true;
- return Invalidate(cx, topScript);
+ return Invalidate(cx, outerScript);
}
RootedId id(cx, NameToId(name));
if (!JSObject::getGeneric(cx, obj, obj, id, vp))
return false;
if (!cache.idempotent()) {
RootedScript script(cx);
@@ -1809,40 +1814,40 @@ ParallelIonCache::destroy()
void
GetPropertyParIC::reset()
{
ParallelIonCache::reset();
hasTypedArrayLengthStub_ = false;
}
bool
-GetPropertyParIC::attachReadSlot(LockedJSContext &cx, IonScript *ion, JSObject *obj,
- JSObject *holder, Shape *shape)
+GetPropertyParIC::attachReadSlot(LockedJSContext &cx, IonScript *ion, HandleObject obj,
+ HandleObject holder, HandleShape shape)
{
// Ready to generate the read slot stub.
DispatchStubPrepender attacher(*this);
MacroAssembler masm(cx, ion);
GenerateReadSlot(cx, ion, masm, attacher, obj, holder, shape, object(), output());
return linkAndAttachStub(cx, masm, attacher, ion, "parallel reading");
}
bool
-GetPropertyParIC::attachArrayLength(LockedJSContext &cx, IonScript *ion, JSObject *obj)
+GetPropertyParIC::attachArrayLength(LockedJSContext &cx, IonScript *ion, HandleObject obj)
{
MacroAssembler masm(cx, ion);
DispatchStubPrepender attacher(*this);
if (!GenerateArrayLength(cx, masm, attacher, obj, object(), output()))
return false;
return linkAndAttachStub(cx, masm, attacher, ion, "parallel array length");
}
bool
-GetPropertyParIC::attachTypedArrayLength(LockedJSContext &cx, IonScript *ion, JSObject *obj)
+GetPropertyParIC::attachTypedArrayLength(LockedJSContext &cx, IonScript *ion, HandleObject obj)
{
MacroAssembler masm(cx, ion);
DispatchStubPrepender attacher(*this);
GenerateTypedArrayLength(cx, masm, attacher, obj, object(), output());
JS_ASSERT(!hasTypedArrayLengthStub_);
hasTypedArrayLengthStub_ = true;
return linkAndAttachStub(cx, masm, attacher, ion, "parallel typed array length");
@@ -2000,20 +2005,20 @@ GenerateSetSlot(JSContext *cx, MacroAsse
masm.pop(object);
}
masm.bind(&failures);
attacher.jumpNextStub(masm);
}
bool
-SetPropertyIC::attachSetSlot(JSContext *cx, IonScript *ion, HandleObject obj,
- HandleShape shape, bool checkTypeset)
+SetPropertyIC::attachSetSlot(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, HandleShape shape, bool checkTypeset)
{
- MacroAssembler masm(cx, ion);
+ MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
RepatchStubAppender attacher(*this);
GenerateSetSlot(cx, masm, attacher, obj, shape, object(), value(), needsTypeBarrier(),
checkTypeset);
return linkAndAttachStub(cx, masm, attacher, ion, "setting");
}
static bool
IsCacheableSetPropCallNative(HandleObject obj, HandleObject holder, HandleShape shape)
@@ -2119,21 +2124,22 @@ EmitCallProxySet(JSContext *cx, MacroAss
// masm.leaveExitFrame & pop locals
masm.adjustStack(IonOOLProxyExitFrameLayout::Size());
masm.icRestoreLive(liveRegs, aic);
return true;
}
bool
-SetPropertyIC::attachGenericProxy(JSContext *cx, IonScript *ion, void *returnAddr)
+SetPropertyIC::attachGenericProxy(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ void *returnAddr)
{
JS_ASSERT(!hasGenericProxyStub());
- MacroAssembler masm(cx, ion, script_, pc_);
+ MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
RepatchStubAppender attacher(*this);
Label failures;
{
Label proxyFailures;
Label proxySuccess;
RegisterSet regSet(RegisterSet::All());
@@ -2174,23 +2180,23 @@ SetPropertyIC::attachGenericProxy(JSCont
JS_ASSERT(!hasGenericProxyStub_);
hasGenericProxyStub_ = true;
return linkAndAttachStub(cx, masm, attacher, ion, "generic proxy set");
}
bool
-SetPropertyIC::attachDOMProxyShadowed(JSContext *cx, IonScript *ion, HandleObject obj,
- void *returnAddr)
+SetPropertyIC::attachDOMProxyShadowed(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, void *returnAddr)
{
JS_ASSERT(IsCacheableDOMProxy(obj));
Label failures;
- MacroAssembler masm(cx, ion, script_, pc_);
+ MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
RepatchStubAppender attacher(*this);
// Guard on the shape of the object.
masm.branchPtr(Assembler::NotEqual,
Address(object(), JSObject::offsetOfShape()),
ImmGCPtr(obj->lastProperty()), &failures);
// Make sure object is a DOMProxy
@@ -2401,23 +2407,23 @@ IsCacheableDOMProxyUnshadowedSetterCall(
return true;
}
*isSetter = true;
return true;
}
bool
-SetPropertyIC::attachDOMProxyUnshadowed(JSContext *cx, IonScript *ion, HandleObject obj,
- void *returnAddr)
+SetPropertyIC::attachDOMProxyUnshadowed(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, void *returnAddr)
{
JS_ASSERT(IsCacheableDOMProxy(obj));
Label failures;
- MacroAssembler masm(cx, ion, script_, pc_);
+ MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
RepatchStubAppender attacher(*this);
// Guard on the shape of the object.
masm.branchPtr(Assembler::NotEqual,
Address(object(), JSObject::offsetOfShape()),
ImmGCPtr(obj->lastProperty()), &failures);
// Make sure object is a DOMProxy
@@ -2456,23 +2462,23 @@ SetPropertyIC::attachDOMProxyUnshadowed(
// Failure.
masm.bind(&failures);
attacher.jumpNextStub(masm);
return linkAndAttachStub(cx, masm, attacher, ion, "DOM proxy unshadowed set");
}
bool
-SetPropertyIC::attachCallSetter(JSContext *cx, IonScript *ion,
+SetPropertyIC::attachCallSetter(JSContext *cx, HandleScript outerScript, IonScript *ion,
HandleObject obj, HandleObject holder, HandleShape shape,
void *returnAddr)
{
JS_ASSERT(obj->isNative());
- MacroAssembler masm(cx, ion, script_, pc_);
+ MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
RepatchStubAppender attacher(*this);
Label failure;
masm.branchPtr(Assembler::NotEqual,
Address(object(), JSObject::offsetOfShape()),
ImmGCPtr(obj->lastProperty()),
&failure);
@@ -2569,22 +2575,22 @@ GenerateAddSlot(JSContext *cx, MacroAsse
masm.bind(&failuresPopObject);
masm.pop(object);
masm.bind(&failures);
attacher.jumpNextStub(masm);
}
bool
-SetPropertyIC::attachAddSlot(JSContext *cx, IonScript *ion, JSObject *obj, HandleShape oldShape,
- bool checkTypeset)
+SetPropertyIC::attachAddSlot(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, HandleShape oldShape, bool checkTypeset)
{
JS_ASSERT_IF(!needsTypeBarrier(), !checkTypeset);
- MacroAssembler masm(cx, ion);
+ MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
RepatchStubAppender attacher(*this);
GenerateAddSlot(cx, masm, attacher, obj, oldShape, object(), value(), checkTypeset);
return linkAndAttachStub(cx, masm, attacher, ion, "adding");
}
static bool
CanInlineSetPropTypeCheck(JSObject *obj, jsid id, ConstantOrRegister val, bool *checkTypeset)
{
@@ -2765,31 +2771,31 @@ SetPropertyIC::update(JSContext *cx, siz
bool addedSetterStub = false;
if (inlinable) {
if (!addedSetterStub && obj->is<ProxyObject>()) {
if (IsCacheableDOMProxy(obj)) {
DOMProxyShadowsResult shadows = GetDOMProxyShadowsCheck()(cx, obj, id);
if (shadows == ShadowCheckFailed)
return false;
if (shadows == Shadows) {
- if (!cache.attachDOMProxyShadowed(cx, ion, obj, returnAddr))
+ if (!cache.attachDOMProxyShadowed(cx, script, ion, obj, returnAddr))
return false;
addedSetterStub = true;
} else {
JS_ASSERT(shadows == DoesntShadow || shadows == DoesntShadowUnique);
if (shadows == DoesntShadowUnique)
cache.reset();
- if (!cache.attachDOMProxyUnshadowed(cx, ion, obj, returnAddr))
+ if (!cache.attachDOMProxyUnshadowed(cx, script, ion, obj, returnAddr))
return false;
addedSetterStub = true;
}
}
if (!addedSetterStub && !cache.hasGenericProxyStub()) {
- if (!cache.attachGenericProxy(cx, ion, returnAddr))
+ if (!cache.attachGenericProxy(cx, script, ion, returnAddr))
return false;
addedSetterStub = true;
}
}
// Make sure the object de-lazifies its type. We do this here so that
// the parallel IC can share code that assumes that native objects all
// have a type object.
@@ -2798,23 +2804,23 @@ SetPropertyIC::update(JSContext *cx, siz
RootedShape shape(cx);
RootedObject holder(cx);
bool checkTypeset;
canCache = CanAttachNativeSetProp(obj, id, cache.value(), cache.needsTypeBarrier(),
&holder, &shape, &checkTypeset);
if (!addedSetterStub && canCache == CanAttachSetSlot) {
- if (!cache.attachSetSlot(cx, ion, obj, shape, checkTypeset))
+ if (!cache.attachSetSlot(cx, script, ion, obj, shape, checkTypeset))
return false;
addedSetterStub = true;
}
if (!addedSetterStub && canCache == CanAttachCallSetter) {
- if (!cache.attachCallSetter(cx, ion, obj, holder, shape, returnAddr))
+ if (!cache.attachCallSetter(cx, script, ion, obj, holder, shape, returnAddr))
return false;
addedSetterStub = true;
}
}
uint32_t oldSlots = obj->numDynamicSlots();
RootedShape oldShape(cx, obj->lastProperty());
@@ -2823,17 +2829,17 @@ SetPropertyIC::update(JSContext *cx, siz
return false;
// The property did not exist before, now we can try to inline the property add.
bool checkTypeset;
if (!addedSetterStub && canCache == MaybeCanAttachAddSlot &&
IsPropertyAddInlineable(obj, id, cache.value(), oldSlots, oldShape, cache.needsTypeBarrier(),
&checkTypeset))
{
- if (!cache.attachAddSlot(cx, ion, obj, oldShape, checkTypeset))
+ if (!cache.attachAddSlot(cx, script, ion, obj, oldShape, checkTypeset))
return false;
}
return true;
}
void
SetPropertyIC::reset()
@@ -2916,29 +2922,29 @@ SetPropertyParIC::update(ForkJoinContext
if (cache.canAttachStub() && !cache.attachAddSlot(ncx, ion, obj, oldShape, checkTypeset))
return cx->setPendingAbortFatal(ParallelBailoutFailedIC);
}
return true;
}
bool
-SetPropertyParIC::attachSetSlot(LockedJSContext &cx, IonScript *ion, JSObject *obj, Shape *shape,
- bool checkTypeset)
+SetPropertyParIC::attachSetSlot(LockedJSContext &cx, IonScript *ion, HandleObject obj,
+ HandleShape shape, bool checkTypeset)
{
MacroAssembler masm(cx, ion);
DispatchStubPrepender attacher(*this);
GenerateSetSlot(cx, masm, attacher, obj, shape, object(), value(), needsTypeBarrier(),
checkTypeset);
return linkAndAttachStub(cx, masm, attacher, ion, "parallel setting");
}
bool
-SetPropertyParIC::attachAddSlot(LockedJSContext &cx, IonScript *ion, JSObject *obj, Shape *oldShape,
- bool checkTypeset)
+SetPropertyParIC::attachAddSlot(LockedJSContext &cx, IonScript *ion, HandleObject obj,
+ HandleShape oldShape, bool checkTypeset)
{
JS_ASSERT_IF(!needsTypeBarrier(), !checkTypeset);
MacroAssembler masm(cx, ion);
DispatchStubPrepender attacher(*this);
GenerateAddSlot(cx, masm, attacher, obj, oldShape, object(), value(), checkTypeset);
return linkAndAttachStub(cx, masm, attacher, ion, "parallel adding");
}
@@ -2964,18 +2970,18 @@ EqualStringsHelper(JSString *str1, JSStr
const jschar *chars = str2->getChars(nullptr);
if (!chars)
return false;
return mozilla::PodEqual(str1->asAtom().chars(), chars, str1->length());
}
bool
-GetElementIC::attachGetProp(JSContext *cx, IonScript *ion, HandleObject obj,
- const Value &idval, HandlePropertyName name,
+GetElementIC::attachGetProp(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, const Value &idval, HandlePropertyName name,
void *returnAddr)
{
JS_ASSERT(index().reg().hasValue());
RootedObject holder(cx);
RootedShape shape(cx);
GetPropertyIC::NativeGetPropCacheability canCache =
@@ -2990,17 +2996,17 @@ GetElementIC::attachGetProp(JSContext *c
IonSpew(IonSpew_InlineCaches, "GETELEM uncacheable property");
return true;
}
JS_ASSERT(idval.isString());
JS_ASSERT(idval.toString()->length() == name->length());
Label failures;
- MacroAssembler masm(cx, ion);
+ MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
// Ensure the index is a string.
ValueOperand val = index().reg().valueReg();
masm.branchTestString(Assembler::NotEqual, val, &failures);
Register scratch = output().valueReg().scratchReg();
masm.unboxString(val, scratch);
@@ -3123,19 +3129,20 @@ GenerateDenseElement(JSContext *cx, Macr
masm.bind(&failures);
attacher.jumpNextStub(masm);
return true;
}
bool
-GetElementIC::attachDenseElement(JSContext *cx, IonScript *ion, JSObject *obj, const Value &idval)
+GetElementIC::attachDenseElement(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, const Value &idval)
{
- MacroAssembler masm(cx, ion);
+ MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
RepatchStubAppender attacher(*this);
if (!GenerateDenseElement(cx, masm, attacher, obj, idval, object(), index(), output()))
return false;
setHasDenseStub();
return linkAndAttachStub(cx, masm, attacher, ion, "dense array");
}
@@ -3174,17 +3181,17 @@ GetElementIC::canAttachTypedArrayElement
return output.hasValue();
}
return output.hasValue() || !output.typedReg().isFloat();
}
static void
GenerateGetTypedArrayElement(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &attacher,
- TypedArrayObject *tarr, const Value &idval, Register object,
+ HandleTypedArrayObject tarr, const Value &idval, Register object,
ConstantOrRegister index, TypedOrValueRegister output,
bool allowDoubleResult)
{
JS_ASSERT(GetElementIC::canAttachTypedArrayElement(tarr, idval, output));
Label failures;
// The array type is the object within the table of typed array classes.
@@ -3277,33 +3284,34 @@ GenerateGetTypedArrayElement(JSContext *
masm.bind(&popAndFail);
masm.pop(object);
masm.bind(&failures);
attacher.jumpNextStub(masm);
}
bool
-GetElementIC::attachTypedArrayElement(JSContext *cx, IonScript *ion, TypedArrayObject *tarr,
- const Value &idval)
+GetElementIC::attachTypedArrayElement(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleTypedArrayObject tarr, const Value &idval)
{
- MacroAssembler masm(cx, ion);
+ MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
RepatchStubAppender attacher(*this);
GenerateGetTypedArrayElement(cx, masm, attacher, tarr, idval, object(), index(), output(),
allowDoubleResult());
return linkAndAttachStub(cx, masm, attacher, ion, "typed array");
}
bool
-GetElementIC::attachArgumentsElement(JSContext *cx, IonScript *ion, JSObject *obj)
+GetElementIC::attachArgumentsElement(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj)
{
JS_ASSERT(obj->is<ArgumentsObject>());
Label failures;
- MacroAssembler masm(cx, ion);
+ MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
RepatchStubAppender attacher(*this);
Register tmpReg = output().scratchReg().gpr();
JS_ASSERT(tmpReg != InvalidReg);
const Class *clasp = obj->is<StrictArgumentsObject>() ? &StrictArgumentsObject::class_
: &NormalArgumentsObject::class_;
@@ -3401,17 +3409,18 @@ GetElementIC::attachArgumentsElement(JSC
return linkAndAttachStub(cx, masm, attacher, ion, "ArgsObj element (normal)");
}
bool
GetElementIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
HandleValue idval, MutableHandleValue res)
{
void *returnAddr;
- IonScript *ion = GetTopIonJSScript(cx, &returnAddr)->ionScript();
+ RootedScript outerScript(cx, GetTopIonJSScript(cx, &returnAddr));
+ IonScript *ion = outerScript->ionScript();
GetElementIC &cache = ion->getCache(cacheIndex).toGetElement();
RootedScript script(cx);
jsbytecode *pc;
cache.getScriptedLocation(&script, &pc);
// Override the return value when the script is invalidated (bug 728188).
AutoDetectInvalidation adi(cx, res.address(), ion);
@@ -3433,34 +3442,34 @@ GetElementIC::update(JSContext *cx, size
if (cache.canAttachStub()) {
if (IsOptimizableArgumentsObjectForGetElem(obj, idval) &&
!cache.hasArgumentsStub(obj->is<StrictArgumentsObject>()) &&
!cache.index().constant() &&
(cache.index().reg().hasValue() ||
cache.index().reg().type() == MIRType_Int32) &&
(cache.output().hasValue() || !cache.output().typedReg().isFloat()))
{
- if (!cache.attachArgumentsElement(cx, ion, obj))
+ if (!cache.attachArgumentsElement(cx, outerScript, ion, obj))
return false;
attachedStub = true;
}
if (!attachedStub && cache.monitoredResult() && canAttachGetProp(obj, idval, id)) {
RootedPropertyName name(cx, JSID_TO_ATOM(id)->asPropertyName());
- if (!cache.attachGetProp(cx, ion, obj, idval, name, returnAddr))
+ if (!cache.attachGetProp(cx, outerScript, ion, obj, idval, name, returnAddr))
return false;
attachedStub = true;
}
if (!attachedStub && !cache.hasDenseStub() && canAttachDenseElement(obj, idval)) {
- if (!cache.attachDenseElement(cx, ion, obj, idval))
+ if (!cache.attachDenseElement(cx, outerScript, ion, obj, idval))
return false;
attachedStub = true;
}
if (!attachedStub && canAttachTypedArrayElement(obj, idval, cache.output())) {
Rooted<TypedArrayObject*> tarr(cx, &obj->as<TypedArrayObject>());
- if (!cache.attachTypedArrayElement(cx, ion, tarr, idval))
+ if (!cache.attachTypedArrayElement(cx, outerScript, ion, tarr, idval))
return false;
attachedStub = true;
}
}
if (!GetObjectElementOperation(cx, JSOp(*pc), obj, /* wasObject = */true, idval, res))
return false;
@@ -3672,19 +3681,20 @@ GenerateSetDenseElement(JSContext *cx, M
masm.bind(&outOfBounds);
masm.bind(&failures);
attacher.jumpNextStub(masm);
return true;
}
bool
-SetElementIC::attachDenseElement(JSContext *cx, IonScript *ion, JSObject *obj, const Value &idval)
+SetElementIC::attachDenseElement(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, const Value &idval)
{
- MacroAssembler masm(cx, ion);
+ MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
RepatchStubAppender attacher(*this);
if (!GenerateSetDenseElement(cx, masm, attacher, obj, idval,
guardHoles(), object(), index(),
value(), tempToUnboxIndex(),
temp()))
{
return false;
}
@@ -3693,17 +3703,17 @@ SetElementIC::attachDenseElement(JSConte
const char *message = guardHoles() ?
"dense array (holes)" :
"dense array";
return linkAndAttachStub(cx, masm, attacher, ion, message);
}
static bool
GenerateSetTypedArrayElement(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &attacher,
- TypedArrayObject *tarr, Register object,
+ HandleTypedArrayObject tarr, Register object,
ValueOperand indexVal, ConstantOrRegister value,
Register tempUnbox, Register temp, FloatRegister tempFloat)
{
Label failures, done, popObjectAndFail;
// Guard on the shape.
Shape *shape = tarr->lastProperty();
if (!shape)
@@ -3775,47 +3785,49 @@ GenerateSetTypedArrayElement(JSContext *
}
masm.bind(&failures);
attacher.jumpNextStub(masm);
return true;
}
bool
-SetElementIC::attachTypedArrayElement(JSContext *cx, IonScript *ion, TypedArrayObject *tarr)
+SetElementIC::attachTypedArrayElement(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleTypedArrayObject tarr)
{
- MacroAssembler masm(cx, ion);
+ MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
RepatchStubAppender attacher(*this);
if (!GenerateSetTypedArrayElement(cx, masm, attacher, tarr,
object(), index(), value(),
tempToUnboxIndex(), temp(), tempFloat()))
{
return false;
}
return linkAndAttachStub(cx, masm, attacher, ion, "typed array");
}
bool
SetElementIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
HandleValue idval, HandleValue value)
{
- IonScript *ion = GetTopIonJSScript(cx)->ionScript();
+ RootedScript outerScript(cx, GetTopIonJSScript(cx));
+ IonScript *ion = outerScript->ionScript();
SetElementIC &cache = ion->getCache(cacheIndex).toSetElement();
bool attachedStub = false;
if (cache.canAttachStub()) {
if (!cache.hasDenseStub() && IsDenseElementSetInlineable(obj, idval)) {
- if (!cache.attachDenseElement(cx, ion, obj, idval))
+ if (!cache.attachDenseElement(cx, outerScript, ion, obj, idval))
return false;
attachedStub = true;
}
if (!attachedStub && IsTypedArrayElementSetInlineable(obj, idval, value)) {
- TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
- if (!cache.attachTypedArrayElement(cx, ion, tarr))
+ RootedTypedArrayObject tarr(cx, &obj->as<TypedArrayObject>());
+ if (!cache.attachTypedArrayElement(cx, outerScript, ion, tarr))
return false;
}
}
if (!SetObjectElement(cx, obj, idval, value, cache.strict()))
return false;
return true;
}
@@ -3823,17 +3835,17 @@ SetElementIC::update(JSContext *cx, size
void
SetElementIC::reset()
{
RepatchIonCache::reset();
hasDenseStub_ = false;
}
bool
-SetElementParIC::attachDenseElement(LockedJSContext &cx, IonScript *ion, JSObject *obj,
+SetElementParIC::attachDenseElement(LockedJSContext &cx, IonScript *ion, HandleObject obj,
const Value &idval)
{
MacroAssembler masm(cx, ion);
DispatchStubPrepender attacher(*this);
if (!GenerateSetDenseElement(cx, masm, attacher, obj, idval,
guardHoles(), object(), index(),
value(), tempToUnboxIndex(),
temp()))
@@ -3845,17 +3857,17 @@ SetElementParIC::attachDenseElement(Lock
"parallel dense array (holes)" :
"parallel dense array";
return linkAndAttachStub(cx, masm, attacher, ion, message);
}
bool
SetElementParIC::attachTypedArrayElement(LockedJSContext &cx, IonScript *ion,
- TypedArrayObject *tarr)
+ HandleTypedArrayObject tarr)
{
MacroAssembler masm(cx, ion);
DispatchStubPrepender attacher(*this);
if (!GenerateSetTypedArrayElement(cx, masm, attacher, tarr,
object(), index(), value(),
tempToUnboxIndex(), temp(), tempFloat()))
{
return false;
@@ -3887,60 +3899,60 @@ SetElementParIC::update(ForkJoinContext
bool attachedStub = false;
if (IsDenseElementSetInlineable(obj, idval)) {
if (!cache.attachDenseElement(ncx, ion, obj, idval))
return cx->setPendingAbortFatal(ParallelBailoutFailedIC);
attachedStub = true;
}
if (!attachedStub && IsTypedArrayElementSetInlineable(obj, idval, value)) {
- TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
+ RootedTypedArrayObject tarr(cx, &obj->as<TypedArrayObject>());
if (!cache.attachTypedArrayElement(ncx, ion, tarr))
return cx->setPendingAbortFatal(ParallelBailoutFailedIC);
}
}
}
return SetElementPar(cx, obj, idval, value, cache.strict());
}
bool
-GetElementParIC::attachReadSlot(LockedJSContext &cx, IonScript *ion, JSObject *obj,
- const Value &idval, PropertyName *name, JSObject *holder,
- Shape *shape)
+GetElementParIC::attachReadSlot(LockedJSContext &cx, IonScript *ion, HandleObject obj,
+ const Value &idval, HandlePropertyName name, HandleObject holder,
+ HandleShape shape)
{
MacroAssembler masm(cx, ion);
DispatchStubPrepender attacher(*this);
// Guard on the index value.
Label failures;
ValueOperand val = index().reg().valueReg();
masm.branchTestValue(Assembler::NotEqual, val, idval, &failures);
GenerateReadSlot(cx, ion, masm, attacher, obj, holder, shape, object(), output(),
&failures);
return linkAndAttachStub(cx, masm, attacher, ion, "parallel getelem reading");
}
bool
-GetElementParIC::attachDenseElement(LockedJSContext &cx, IonScript *ion, JSObject *obj,
+GetElementParIC::attachDenseElement(LockedJSContext &cx, IonScript *ion, HandleObject obj,
const Value &idval)
{
MacroAssembler masm(cx, ion);
DispatchStubPrepender attacher(*this);
if (!GenerateDenseElement(cx, masm, attacher, obj, idval, object(), index(), output()))
return false;
return linkAndAttachStub(cx, masm, attacher, ion, "parallel dense element");
}
bool
GetElementParIC::attachTypedArrayElement(LockedJSContext &cx, IonScript *ion,
- TypedArrayObject *tarr, const Value &idval)
+ HandleTypedArrayObject tarr, const Value &idval)
{
MacroAssembler masm(cx, ion);
DispatchStubPrepender attacher(*this);
GenerateGetTypedArrayElement(cx, masm, attacher, tarr, idval, object(), index(), output(),
allowDoubleResult());
return linkAndAttachStub(cx, masm, attacher, ion, "parallel typed array");
}
@@ -3999,32 +4011,34 @@ GetElementParIC::update(ForkJoinContext
{
if (!cache.attachDenseElement(ncx, ion, obj, idval))
return cx->setPendingAbortFatal(ParallelBailoutFailedIC);
attachedStub = true;
}
if (!attachedStub &&
GetElementIC::canAttachTypedArrayElement(obj, idval, cache.output()))
{
- if (!cache.attachTypedArrayElement(ncx, ion, &obj->as<TypedArrayObject>(), idval))
+ RootedTypedArrayObject tarr(cx, &obj->as<TypedArrayObject>());
+ if (!cache.attachTypedArrayElement(ncx, ion, tarr, idval))
return cx->setPendingAbortFatal(ParallelBailoutFailedIC);
attachedStub = true;
}
}
}
return true;
}
bool
-BindNameIC::attachGlobal(JSContext *cx, IonScript *ion, JSObject *scopeChain)
+BindNameIC::attachGlobal(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject scopeChain)
{
JS_ASSERT(scopeChain->is<GlobalObject>());
- MacroAssembler masm(cx, ion);
+ MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
RepatchStubAppender attacher(*this);
// Guard on the scope chain.
attacher.branchNextStub(masm, Assembler::NotEqual, scopeChainReg(),
ImmGCPtr(scopeChain));
masm.movePtr(ImmGCPtr(scopeChain), outputReg());
attacher.jumpRejoin(masm);
@@ -4085,21 +4099,22 @@ GenerateScopeChainGuards(MacroAssembler
// Load the next link.
tobj = &tobj->as<ScopeObject>().enclosingScope();
masm.extractObject(Address(outputReg, ScopeObject::offsetOfEnclosingScope()), outputReg);
}
}
bool
-BindNameIC::attachNonGlobal(JSContext *cx, IonScript *ion, JSObject *scopeChain, JSObject *holder)
+BindNameIC::attachNonGlobal(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject scopeChain, HandleObject holder)
{
JS_ASSERT(IsCacheableNonGlobalScope(scopeChain));
- MacroAssembler masm(cx, ion);
+ MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
RepatchStubAppender attacher(*this);
// Guard on the shape of the scope chain.
Label failures;
attacher.branchNextStubOrLabel(masm, Assembler::NotEqual,
Address(scopeChainReg(), JSObject::offsetOfShape()),
ImmGCPtr(scopeChain->lastProperty()),
holder != scopeChain ? &failures : nullptr);
@@ -4148,51 +4163,52 @@ IsCacheableScopeChain(JSObject *scopeCha
MOZ_ASSUME_UNREACHABLE("Invalid scope chain");
}
JSObject *
BindNameIC::update(JSContext *cx, size_t cacheIndex, HandleObject scopeChain)
{
AutoFlushCache afc ("BindNameCache", cx->runtime()->jitRuntime());
- IonScript *ion = GetTopIonJSScript(cx)->ionScript();
+ RootedScript outerScript(cx, GetTopIonJSScript(cx));
+ IonScript *ion = outerScript->ionScript();
BindNameIC &cache = ion->getCache(cacheIndex).toBindName();
HandlePropertyName name = cache.name();
RootedObject holder(cx);
if (scopeChain->is<GlobalObject>()) {
holder = scopeChain;
} else {
if (!LookupNameWithGlobalDefault(cx, name, scopeChain, &holder))
return nullptr;
}
// Stop generating new stubs once we hit the stub count limit, see
// GetPropertyCache.
if (cache.canAttachStub()) {
if (scopeChain->is<GlobalObject>()) {
- if (!cache.attachGlobal(cx, ion, scopeChain))
+ if (!cache.attachGlobal(cx, outerScript, ion, scopeChain))
return nullptr;
} else if (IsCacheableScopeChain(scopeChain, holder)) {
- if (!cache.attachNonGlobal(cx, ion, scopeChain, holder))
+ if (!cache.attachNonGlobal(cx, outerScript, ion, scopeChain, holder))
return nullptr;
} else {
IonSpew(IonSpew_InlineCaches, "BINDNAME uncacheable scope chain");
}
}
return holder;
}
bool
-NameIC::attachReadSlot(JSContext *cx, IonScript *ion, HandleObject scopeChain,
- HandleObject holderBase, HandleObject holder,
- HandleShape shape)
+NameIC::attachReadSlot(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject scopeChain, HandleObject holderBase,
+ HandleObject holder, HandleShape shape)
{
- MacroAssembler masm(cx, ion);
+ MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
Label failures;
RepatchStubAppender attacher(*this);
Register scratchReg = outputReg().valueReg().scratchReg();
// Don't guard the base of the proto chain the name was found on. It will be guarded
// by GenerateReadSlot().
masm.mov(scopeChainReg(), scratchReg);
@@ -4242,20 +4258,21 @@ IsCacheableNameReadSlot(JSContext *cx, H
obj2 = obj2->enclosingScope();
}
return obj == obj2;
}
bool
-NameIC::attachCallGetter(JSContext *cx, IonScript *ion, JSObject *obj, JSObject *holder,
- HandleShape shape, void *returnAddr)
+NameIC::attachCallGetter(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, HandleObject holder, HandleShape shape,
+ void *returnAddr)
{
- MacroAssembler masm(cx, ion, script_, pc_);
+ MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
RepatchStubAppender attacher(*this);
if (!GenerateCallGetter(cx, ion, masm, attacher, obj, name(), holder, shape, liveRegs_,
scopeChainReg(), outputReg(), returnAddr))
{
return false;
}
@@ -4278,37 +4295,38 @@ IsCacheableNameCallGetter(JSObject *scop
bool
NameIC::update(JSContext *cx, size_t cacheIndex, HandleObject scopeChain,
MutableHandleValue vp)
{
AutoFlushCache afc ("GetNameCache", cx->runtime()->jitRuntime());
void *returnAddr;
- IonScript *ion = GetTopIonJSScript(cx, &returnAddr)->ionScript();
+ RootedScript outerScript(cx, GetTopIonJSScript(cx, &returnAddr));
+ IonScript *ion = outerScript->ionScript();
NameIC &cache = ion->getCache(cacheIndex).toName();
RootedPropertyName name(cx, cache.name());
RootedScript script(cx);
jsbytecode *pc;
cache.getScriptedLocation(&script, &pc);
RootedObject obj(cx);
RootedObject holder(cx);
RootedShape shape(cx);
if (!LookupName(cx, name, scopeChain, &obj, &holder, &shape))
return false;
if (cache.canAttachStub()) {
if (IsCacheableNameReadSlot(cx, scopeChain, obj, holder, shape, pc, cache.outputReg())) {
- if (!cache.attachReadSlot(cx, ion, scopeChain, obj, holder, shape))
+ if (!cache.attachReadSlot(cx, outerScript, ion, scopeChain, obj, holder, shape))
return false;
} else if (IsCacheableNameCallGetter(scopeChain, obj, holder, shape)) {
- if (!cache.attachCallGetter(cx, ion, obj, holder, shape, returnAddr))
+ if (!cache.attachCallGetter(cx, outerScript, ion, obj, holder, shape, returnAddr))
return false;
}
}
if (cache.isTypeOf()) {
if (!FetchName<true>(cx, obj, holder, name, shape, vp))
return false;
} else {
@@ -4318,20 +4336,20 @@ NameIC::update(JSContext *cx, size_t cac
// Monitor changes to cache entry.
types::TypeScript::Monitor(cx, script, pc, vp);
return true;
}
bool
-CallsiteCloneIC::attach(JSContext *cx, IonScript *ion, HandleFunction original,
- HandleFunction clone)
+CallsiteCloneIC::attach(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleFunction original, HandleFunction clone)
{
- MacroAssembler masm(cx, ion);
+ MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
RepatchStubAppender attacher(*this);
// Guard against object identity on the original.
attacher.branchNextStub(masm, Assembler::NotEqual, calleeReg(), ImmGCPtr(original));
// Load the clone.
masm.movePtr(ImmGCPtr(clone), outputReg());
@@ -4346,22 +4364,23 @@ CallsiteCloneIC::update(JSContext *cx, s
AutoFlushCache afc ("CallsiteCloneCache", cx->runtime()->jitRuntime());
// Act as the identity for functions that are not clone-at-callsite, as we
// generate this cache as long as some callees are clone-at-callsite.
RootedFunction fun(cx, &callee->as<JSFunction>());
if (!fun->hasScript() || !fun->nonLazyScript()->shouldCloneAtCallsite())
return fun;
- IonScript *ion = GetTopIonJSScript(cx)->ionScript();
+ RootedScript outerScript(cx, GetTopIonJSScript(cx));
+ IonScript *ion = outerScript->ionScript();
CallsiteCloneIC &cache = ion->getCache(cacheIndex).toCallsiteClone();
RootedFunction clone(cx, CloneFunctionAtCallsite(cx, fun, cache.callScript(), cache.callPc()));
if (!clone)
return nullptr;
if (cache.canAttachStub()) {
- if (!cache.attach(cx, ion, fun, clone))
+ if (!cache.attach(cx, outerScript, ion, fun, clone))
return nullptr;
}
return clone;
}
--- a/js/src/jit/IonCaches.h
+++ b/js/src/jit/IonCaches.h
@@ -15,16 +15,18 @@
#include "jit/Registers.h"
#include "jit/shared/Assembler-shared.h"
namespace js {
class LockedJSContext;
class TypedArrayObject;
+typedef Handle<TypedArrayObject *> HandleTypedArrayObject;
+
namespace jit {
#define IONCACHE_KIND_LIST(_) \
_(GetProperty) \
_(SetProperty) \
_(GetElement) \
_(SetElement) \
_(BindName) \
@@ -163,16 +165,20 @@ class IonCache
size_t stubCount_ : 5;
CodeLocationLabel fallbackLabel_;
// Location of this operation, nullptr for idempotent caches.
JSScript *script_;
jsbytecode *pc_;
+ // Location to use when updating profiler pseudostack when leaving this
+ // IC code to enter a callee.
+ jsbytecode *profilerLeavePc_;
+
private:
static const size_t MAX_STUBS;
void incrementStubCount() {
// The IC should stop generating stubs before wrapping stubCount.
stubCount_++;
JS_ASSERT(stubCount_);
}
@@ -180,32 +186,38 @@ class IonCache
IonCache()
: pure_(false),
idempotent_(false),
disabled_(false),
stubCount_(0),
fallbackLabel_(),
script_(nullptr),
- pc_(nullptr)
+ pc_(nullptr),
+ profilerLeavePc_(nullptr)
{
}
virtual void disable();
inline bool isDisabled() const {
return disabled_;
}
// Set the initial 'out-of-line' jump state of the cache. The fallbackLabel is
// the location of the out-of-line update (slow) path. This location will
// be set to the exitJump of the last generated stub.
void setFallbackLabel(CodeOffsetLabel fallbackLabel) {
fallbackLabel_ = fallbackLabel;
}
+ void setProfilerLeavePC(jsbytecode *pc) {
+ JS_ASSERT(pc != nullptr);
+ profilerLeavePc_ = pc;
+ }
+
virtual void emitInitialJump(MacroAssembler &masm, AddCacheState &addState) = 0;
virtual void bindInitialJump(MacroAssembler &masm, AddCacheState &addState) = 0;
virtual void updateBaseAddress(JitCode *code, MacroAssembler &masm);
// Initialize the AddCacheState depending on the kind of cache, like
// setting a scratch register. Defaults to doing nothing.
virtual void initializeAddCacheState(LInstruction *ins, AddCacheState *addState);
@@ -609,34 +621,44 @@ class GetPropertyIC : public RepatchIonC
// Helpers for CanAttachNativeGetProp
typedef JSContext * Context;
bool allowArrayLength(Context cx, HandleObject obj) const;
bool allowGetters() const {
return monitoredResult() && !idempotent();
}
// Attach the proper stub, if possible
- bool tryAttachStub(JSContext *cx, IonScript *ion, HandleObject obj,
- HandlePropertyName name, void *returnAddr, bool *emitted);
- bool tryAttachProxy(JSContext *cx, IonScript *ion, HandleObject obj,
- HandlePropertyName name, void *returnAddr, bool *emitted);
- bool tryAttachGenericProxy(JSContext *cx, IonScript *ion, HandleObject obj,
- HandlePropertyName name, void *returnAddr, bool *emitted);
- bool tryAttachDOMProxyShadowed(JSContext *cx, IonScript *ion, HandleObject obj,
- void *returnAddr, bool *emitted);
- bool tryAttachDOMProxyUnshadowed(JSContext *cx, IonScript *ion, HandleObject obj,
- HandlePropertyName name, bool resetNeeded,
+ bool tryAttachStub(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, HandlePropertyName name,
+ void *returnAddr, bool *emitted);
+
+ bool tryAttachProxy(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, HandlePropertyName name,
+ void *returnAddr, bool *emitted);
+
+ bool tryAttachGenericProxy(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, HandlePropertyName name,
+ void *returnAddr, bool *emitted);
+
+ bool tryAttachDOMProxyShadowed(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, void *returnAddr, bool *emitted);
+
+ bool tryAttachDOMProxyUnshadowed(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, HandlePropertyName name, bool resetNeeded,
void *returnAddr, bool *emitted);
- bool tryAttachNative(JSContext *cx, IonScript *ion, HandleObject obj,
- HandlePropertyName name, void *returnAddr, bool *emitted);
- bool tryAttachTypedArrayLength(JSContext *cx, IonScript *ion, HandleObject obj,
- HandlePropertyName name, bool *emitted);
+
+ bool tryAttachNative(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, HandlePropertyName name,
+ void *returnAddr, bool *emitted);
- bool tryAttachArgumentsLength(JSContext *cx, IonScript *ion, HandleObject obj,
- HandlePropertyName name, bool *emitted);
+ bool tryAttachTypedArrayLength(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, HandlePropertyName name, bool *emitted);
+
+ bool tryAttachArgumentsLength(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, HandlePropertyName name, bool *emitted);
static bool update(JSContext *cx, size_t cacheIndex, HandleObject obj, MutableHandleValue vp);
};
class SetPropertyIC : public RepatchIonCache
{
protected:
// Registers live after the cache, excluding output registers. The initial
@@ -689,30 +711,36 @@ class SetPropertyIC : public RepatchIonC
enum NativeSetPropCacheability {
CanAttachNone,
CanAttachSetSlot,
MaybeCanAttachAddSlot,
CanAttachCallSetter
};
- bool attachSetSlot(JSContext *cx, IonScript *ion, HandleObject obj, HandleShape shape,
- bool checkTypeset);
- bool attachCallSetter(JSContext *cx, IonScript *ion, HandleObject obj,
- HandleObject holder, HandleShape shape, void *returnAddr);
- bool attachAddSlot(JSContext *cx, IonScript *ion, JSObject *obj, HandleShape oldShape,
- bool checkTypeset);
- bool attachGenericProxy(JSContext *cx, IonScript *ion, void *returnAddr);
- bool attachDOMProxyShadowed(JSContext *cx, IonScript *ion, HandleObject obj,
- void *returnAddr);
- bool attachDOMProxyUnshadowed(JSContext *cx, IonScript *ion, HandleObject obj,
- void *returnAddr);
+ bool attachSetSlot(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, HandleShape shape, bool checkTypeset);
+
+ bool attachCallSetter(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, HandleObject holder, HandleShape shape,
+ void *returnAddr);
+
+ bool attachAddSlot(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, HandleShape oldShape, bool checkTypeset);
- static bool
- update(JSContext *cx, size_t cacheIndex, HandleObject obj, HandleValue value);
+ bool attachGenericProxy(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ void *returnAddr);
+
+ bool attachDOMProxyShadowed(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, void *returnAddr);
+
+ bool attachDOMProxyUnshadowed(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, void *returnAddr);
+
+ static bool update(JSContext *cx, size_t cacheIndex, HandleObject obj, HandleValue value);
};
class GetElementIC : public RepatchIonCache
{
protected:
RegisterSet liveRegs_;
Register object_;
@@ -783,22 +811,28 @@ class GetElementIC : public RepatchIonCa
return monitoredResult();
}
static bool canAttachGetProp(JSObject *obj, const Value &idval, jsid id);
static bool canAttachDenseElement(JSObject *obj, const Value &idval);
static bool canAttachTypedArrayElement(JSObject *obj, const Value &idval,
TypedOrValueRegister output);
- bool attachGetProp(JSContext *cx, IonScript *ion, HandleObject obj, const Value &idval,
- HandlePropertyName name, void *returnAddr);
- bool attachDenseElement(JSContext *cx, IonScript *ion, JSObject *obj, const Value &idval);
- bool attachTypedArrayElement(JSContext *cx, IonScript *ion, TypedArrayObject *tarr,
- const Value &idval);
- bool attachArgumentsElement(JSContext *cx, IonScript *ion, JSObject *obj);
+ bool attachGetProp(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, const Value &idval, HandlePropertyName name,
+ void *returnAddr);
+
+ bool attachDenseElement(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, const Value &idval);
+
+ bool attachTypedArrayElement(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleTypedArrayObject tarr, const Value &idval);
+
+ bool attachArgumentsElement(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj);
static bool
update(JSContext *cx, size_t cacheIndex, HandleObject obj, HandleValue idval,
MutableHandleValue vp);
void incFailedUpdates() {
failedUpdates_++;
}
@@ -873,18 +907,21 @@ class SetElementIC : public RepatchIonCa
bool hasDenseStub() const {
return hasDenseStub_;
}
void setHasDenseStub() {
JS_ASSERT(!hasDenseStub());
hasDenseStub_ = true;
}
- bool attachDenseElement(JSContext *cx, IonScript *ion, JSObject *obj, const Value &idval);
- bool attachTypedArrayElement(JSContext *cx, IonScript *ion, TypedArrayObject *tarr);
+ bool attachDenseElement(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject obj, const Value &idval);
+
+ bool attachTypedArrayElement(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleTypedArrayObject tarr);
static bool
update(JSContext *cx, size_t cacheIndex, HandleObject obj, HandleValue idval,
HandleValue value);
};
class BindNameIC : public RepatchIonCache
{
@@ -908,18 +945,21 @@ class BindNameIC : public RepatchIonCach
}
HandlePropertyName name() const {
return HandlePropertyName::fromMarkedLocation(&name_);
}
Register outputReg() const {
return output_;
}
- bool attachGlobal(JSContext *cx, IonScript *ion, JSObject *scopeChain);
- bool attachNonGlobal(JSContext *cx, IonScript *ion, JSObject *scopeChain, JSObject *holder);
+ bool attachGlobal(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject scopeChain);
+
+ bool attachNonGlobal(JSContext *cx, HandleScript outerScript, IonScript *ion,
+ HandleObject scopeChain, HandleObject holder);
static JSObject *
update(JSContext *cx, size_t cacheIndex, HandleObject scopeChain);
};
class NameIC : public RepatchIonCache
{
protected:
@@ -954,20 +994,23 @@ class NameIC : public RepatchIonCache
}
TypedOrValueRegister outputReg() const {
return output_;
}
bool isTypeOf() const {
return typeOf_;
}