зеркало из https://github.com/mozilla/gecko-dev.git
Коммит
92f0e478fa
|
@ -15,7 +15,7 @@
|
||||||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9f36b711af7597a6a32471c3305cf1e2d6947d39"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="b387bcad9bf8389580a8ae133b071053cfc9c30f"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="41efd945c841175f733ef764fe5f6a85c592970b"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="94516f787d477dc307e4566f415e0d2f0794f6b9"/>
|
||||||
<!-- Stock Android things -->
|
<!-- Stock Android things -->
|
||||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
|
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
|
||||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
|
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
|
||||||
|
@ -122,7 +122,7 @@
|
||||||
<project name="platform/system/media" path="system/media" revision="c1332c21c608f4932a6d7e83450411cde53315ef"/>
|
<project name="platform/system/media" path="system/media" revision="c1332c21c608f4932a6d7e83450411cde53315ef"/>
|
||||||
<default remote="caf" revision="LNX.LA.3.5.2.1.1" sync-j="4"/>
|
<default remote="caf" revision="LNX.LA.3.5.2.1.1" sync-j="4"/>
|
||||||
<!-- Platform common things -->
|
<!-- Platform common things -->
|
||||||
<project name="device-shinano-common" path="device/sony/shinano-common" remote="b2g" revision="9934000e6d842b4c4d76fb56f52584e1a3819c9c"/>
|
<project name="device-shinano-common" path="device/sony/shinano-common" remote="b2g" revision="ac45522bb3a14aff9facd74e2cd03430e1e0793f"/>
|
||||||
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="1bb28abbc215f45220620af5cd60a8ac1be93722"/>
|
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="1bb28abbc215f45220620af5cd60a8ac1be93722"/>
|
||||||
<project name="device/qcom/common" path="device/qcom/common" revision="2501e5940ba69ece7654ff85611c76ae5bda299c"/>
|
<project name="device/qcom/common" path="device/qcom/common" revision="2501e5940ba69ece7654ff85611c76ae5bda299c"/>
|
||||||
<project name="codeaurora_kernel_msm" path="kernel" remote="b2g" revision="5ada05ac150f643ef19e87015df7e106b88effe7"/>
|
<project name="codeaurora_kernel_msm" path="kernel" remote="b2g" revision="5ada05ac150f643ef19e87015df7e106b88effe7"/>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9f36b711af7597a6a32471c3305cf1e2d6947d39"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="b387bcad9bf8389580a8ae133b071053cfc9c30f"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="41efd945c841175f733ef764fe5f6a85c592970b"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="94516f787d477dc307e4566f415e0d2f0794f6b9"/>
|
||||||
<!-- Stock Android things -->
|
<!-- Stock Android things -->
|
||||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
|
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
|
||||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
|
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="9f36b711af7597a6a32471c3305cf1e2d6947d39"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="b387bcad9bf8389580a8ae133b071053cfc9c30f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="87a2d8ab9248540910e56921654367b78a587095"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="87a2d8ab9248540910e56921654367b78a587095"/>
|
||||||
|
|
|
@ -17,10 +17,10 @@
|
||||||
</project>
|
</project>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9f36b711af7597a6a32471c3305cf1e2d6947d39"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="b387bcad9bf8389580a8ae133b071053cfc9c30f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="41efd945c841175f733ef764fe5f6a85c592970b"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="94516f787d477dc307e4566f415e0d2f0794f6b9"/>
|
||||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||||
<!-- Stock Android things -->
|
<!-- Stock Android things -->
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9f36b711af7597a6a32471c3305cf1e2d6947d39"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="b387bcad9bf8389580a8ae133b071053cfc9c30f"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="41efd945c841175f733ef764fe5f6a85c592970b"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="94516f787d477dc307e4566f415e0d2f0794f6b9"/>
|
||||||
<!-- Stock Android things -->
|
<!-- Stock Android things -->
|
||||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
|
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
|
||||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>
|
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
|
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9f36b711af7597a6a32471c3305cf1e2d6947d39"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="b387bcad9bf8389580a8ae133b071053cfc9c30f"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="41efd945c841175f733ef764fe5f6a85c592970b"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="94516f787d477dc307e4566f415e0d2f0794f6b9"/>
|
||||||
<!-- Stock Android things -->
|
<!-- Stock Android things -->
|
||||||
<project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
|
<project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
|
||||||
<project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>
|
<project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="9f36b711af7597a6a32471c3305cf1e2d6947d39"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="b387bcad9bf8389580a8ae133b071053cfc9c30f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="87a2d8ab9248540910e56921654367b78a587095"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="87a2d8ab9248540910e56921654367b78a587095"/>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9f36b711af7597a6a32471c3305cf1e2d6947d39"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="b387bcad9bf8389580a8ae133b071053cfc9c30f"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="41efd945c841175f733ef764fe5f6a85c592970b"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="94516f787d477dc307e4566f415e0d2f0794f6b9"/>
|
||||||
<!-- Stock Android things -->
|
<!-- Stock Android things -->
|
||||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
|
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
|
||||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
|
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
{
|
{
|
||||||
"git": {
|
"git": {
|
||||||
"git_revision": "9f36b711af7597a6a32471c3305cf1e2d6947d39",
|
"git_revision": "b387bcad9bf8389580a8ae133b071053cfc9c30f",
|
||||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||||
"branch": ""
|
"branch": ""
|
||||||
},
|
},
|
||||||
"revision": "8583025b84cda74c63e83bbbdfd7a4f33b917f20",
|
"revision": "7dbfef98a254a3d56b8d38e003c988f9d19771a4",
|
||||||
"repo_path": "integration/gaia-central"
|
"repo_path": "integration/gaia-central"
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,10 @@
|
||||||
</project>
|
</project>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9f36b711af7597a6a32471c3305cf1e2d6947d39"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="b387bcad9bf8389580a8ae133b071053cfc9c30f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="41efd945c841175f733ef764fe5f6a85c592970b"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="94516f787d477dc307e4566f415e0d2f0794f6b9"/>
|
||||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||||
<!-- Stock Android things -->
|
<!-- Stock Android things -->
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
|
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9f36b711af7597a6a32471c3305cf1e2d6947d39"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="b387bcad9bf8389580a8ae133b071053cfc9c30f"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="41efd945c841175f733ef764fe5f6a85c592970b"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="94516f787d477dc307e4566f415e0d2f0794f6b9"/>
|
||||||
<!-- Stock Android things -->
|
<!-- Stock Android things -->
|
||||||
<project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
|
<project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
|
||||||
<project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>
|
<project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>
|
||||||
|
|
|
@ -522,38 +522,38 @@ let LoopUI;
|
||||||
* has been fetched.
|
* has been fetched.
|
||||||
*/
|
*/
|
||||||
getFavicon: function(callback) {
|
getFavicon: function(callback) {
|
||||||
let favicon = gBrowser.getIcon(gBrowser.selectedTab);
|
let pageURI = gBrowser.selectedTab.linkedBrowser.currentURI.spec;
|
||||||
// If the tab image's url starts with http(s), fetch icon from favicon
|
// If the tab page’s url starts with http(s), fetch icon.
|
||||||
// service via the moz-anno protocol.
|
if (!/^https?:/.test(pageURI)) {
|
||||||
if (/^https?:/.test(favicon)) {
|
callback();
|
||||||
let faviconURI = makeURI(favicon);
|
|
||||||
favicon = this.favIconService.getFaviconLinkForIcon(faviconURI).spec;
|
|
||||||
}
|
|
||||||
if (!favicon) {
|
|
||||||
callback(new Error("No favicon found"));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
favicon = this.PlacesUtils.getImageURLForResolution(window, favicon);
|
|
||||||
|
|
||||||
// We XHR the favicon to get a File object, which we can pass to the FileReader
|
this.PlacesUtils.promiseFaviconLinkUrl(pageURI).then(uri => {
|
||||||
// object. The FileReader turns the File object into a data-uri.
|
uri = this.PlacesUtils.getImageURLForResolution(window, uri.spec);
|
||||||
let xhr = new XMLHttpRequest();
|
|
||||||
xhr.open("get", favicon, true);
|
|
||||||
xhr.responseType = "blob";
|
|
||||||
xhr.overrideMimeType("image/x-icon");
|
|
||||||
xhr.onload = () => {
|
|
||||||
if (xhr.status != 200) {
|
|
||||||
callback(new Error("Invalid status code received for favicon XHR: " + xhr.status));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let reader = new FileReader();
|
// We XHR the favicon to get a File object, which we can pass to the FileReader
|
||||||
reader.onload = () => callback(null, reader.result);
|
// object. The FileReader turns the File object into a data-uri.
|
||||||
reader.onerror = callback;
|
let xhr = new XMLHttpRequest();
|
||||||
reader.readAsDataURL(xhr.response);
|
xhr.open("get", uri, true);
|
||||||
};
|
xhr.responseType = "blob";
|
||||||
xhr.onerror = callback;
|
xhr.overrideMimeType("image/x-icon");
|
||||||
xhr.send();
|
xhr.onload = () => {
|
||||||
|
if (xhr.status != 200) {
|
||||||
|
callback(new Error("Invalid status code received for favicon XHR: " + xhr.status));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let reader = new FileReader();
|
||||||
|
reader.onload = reader.onload = () => callback(null, reader.result);
|
||||||
|
reader.onerror = callback;
|
||||||
|
reader.readAsDataURL(xhr.response);
|
||||||
|
};
|
||||||
|
xhr.onerror = callback;
|
||||||
|
xhr.send();
|
||||||
|
}).catch(err => {
|
||||||
|
callback(err || new Error("No favicon found"));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
@ -563,5 +563,3 @@ XPCOMUtils.defineLazyModuleGetter(LoopUI, "LoopRooms", "resource:///modules/loop
|
||||||
XPCOMUtils.defineLazyModuleGetter(LoopUI, "MozLoopService", "resource:///modules/loop/MozLoopService.jsm");
|
XPCOMUtils.defineLazyModuleGetter(LoopUI, "MozLoopService", "resource:///modules/loop/MozLoopService.jsm");
|
||||||
XPCOMUtils.defineLazyModuleGetter(LoopUI, "PanelFrame", "resource:///modules/PanelFrame.jsm");
|
XPCOMUtils.defineLazyModuleGetter(LoopUI, "PanelFrame", "resource:///modules/PanelFrame.jsm");
|
||||||
XPCOMUtils.defineLazyModuleGetter(LoopUI, "PlacesUtils", "resource://gre/modules/PlacesUtils.jsm");
|
XPCOMUtils.defineLazyModuleGetter(LoopUI, "PlacesUtils", "resource://gre/modules/PlacesUtils.jsm");
|
||||||
XPCOMUtils.defineLazyServiceGetter(LoopUI, "favIconService",
|
|
||||||
"@mozilla.org/browser/favicon-service;1", "nsIFaviconService");
|
|
||||||
|
|
|
@ -34,8 +34,8 @@
|
||||||
* along any dimension beyond the point at which an overflow event would
|
* along any dimension beyond the point at which an overflow event would
|
||||||
* occur". But none of -moz-{fit,max,min}-content do what we want here. So..
|
* occur". But none of -moz-{fit,max,min}-content do what we want here. So..
|
||||||
*/
|
*/
|
||||||
min-width: 320px;
|
min-width: 260px;
|
||||||
min-height: 280px;
|
min-height: 315px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#main-window[customize-entered] {
|
#main-window[customize-entered] {
|
||||||
|
@ -907,8 +907,32 @@ chatbox {
|
||||||
width: 260px; /* CHAT_WIDTH_OPEN in socialchat.xml */
|
width: 260px; /* CHAT_WIDTH_OPEN in socialchat.xml */
|
||||||
}
|
}
|
||||||
|
|
||||||
chatbox[large="true"] {
|
chatbox[customSize] {
|
||||||
width: 300px;
|
width: 300px; /* CHAT_WIDTH_OPEN_ALT in socialchat.xml */
|
||||||
|
}
|
||||||
|
|
||||||
|
#chat-window[customSize] {
|
||||||
|
min-width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
chatbox[customSize="loopChatEnabled"] {
|
||||||
|
/* 325px as defined per UX */
|
||||||
|
height: 325px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#chat-window[customSize="loopChatEnabled"] {
|
||||||
|
/* 325px + 30px top bar height. */
|
||||||
|
min-height: calc(325px + 30px);
|
||||||
|
}
|
||||||
|
|
||||||
|
chatbox[customSize="loopChatMessageAppended"] {
|
||||||
|
/* 445px as defined per UX */
|
||||||
|
height: 445px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#chat-window[customSize="loopChatMessageAppended"] {
|
||||||
|
/* 445px + 30px top bar height. */
|
||||||
|
min-height: calc(445px + 30px);
|
||||||
}
|
}
|
||||||
|
|
||||||
chatbox[minimized="true"] {
|
chatbox[minimized="true"] {
|
||||||
|
@ -922,6 +946,15 @@ chatbar {
|
||||||
max-height: 0;
|
max-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chatbar-innerbox {
|
||||||
|
margin: -285px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
chatbar[customSize] > .chatbar-innerbox {
|
||||||
|
/* 425px to make room for the maximum custom-size chatbox; currently 'loopChatMessageAppended'. */
|
||||||
|
margin-top: -425px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Apply crisp rendering for favicons at exactly 2dppx resolution */
|
/* Apply crisp rendering for favicons at exactly 2dppx resolution */
|
||||||
@media (resolution: 2dppx) {
|
@media (resolution: 2dppx) {
|
||||||
#social-sidebar-favico,
|
#social-sidebar-favico,
|
||||||
|
|
|
@ -160,8 +160,7 @@
|
||||||
<parameter name="aTarget"/>
|
<parameter name="aTarget"/>
|
||||||
<body><![CDATA[
|
<body><![CDATA[
|
||||||
aTarget.setAttribute("label", this.contentDocument.title);
|
aTarget.setAttribute("label", this.contentDocument.title);
|
||||||
if (this.getAttribute("dark") == "true")
|
|
||||||
aTarget.setAttribute("dark", "true");
|
|
||||||
aTarget.src = this.src;
|
aTarget.src = this.src;
|
||||||
aTarget.content.setAttribute("origin", this.content.getAttribute("origin"));
|
aTarget.content.setAttribute("origin", this.content.getAttribute("origin"));
|
||||||
aTarget.content.popupnotificationanchor.className = this.content.popupnotificationanchor.className;
|
aTarget.content.popupnotificationanchor.className = this.content.popupnotificationanchor.className;
|
||||||
|
@ -169,6 +168,16 @@
|
||||||
]]></body>
|
]]></body>
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
|
<method name="setDecorationAttributes">
|
||||||
|
<parameter name="aTarget"/>
|
||||||
|
<body><![CDATA[
|
||||||
|
for (let attr of ["dark", "customSize"]) {
|
||||||
|
if (this.hasAttribute(attr))
|
||||||
|
aTarget.setAttribute(attr, this.getAttribute(attr));
|
||||||
|
}
|
||||||
|
]]></body>
|
||||||
|
</method>
|
||||||
|
|
||||||
<method name="onTitlebarClick">
|
<method name="onTitlebarClick">
|
||||||
<parameter name="aEvent"/>
|
<parameter name="aEvent"/>
|
||||||
<body><![CDATA[
|
<body><![CDATA[
|
||||||
|
@ -211,6 +220,8 @@
|
||||||
let chatbar = win.document.getElementById("pinnedchats");
|
let chatbar = win.document.getElementById("pinnedchats");
|
||||||
let origin = this.content.getAttribute("origin");
|
let origin = this.content.getAttribute("origin");
|
||||||
let cb = chatbar.openChat(origin, title, "about:blank");
|
let cb = chatbar.openChat(origin, title, "about:blank");
|
||||||
|
this.setDecorationAttributes(cb);
|
||||||
|
|
||||||
cb.promiseChatLoaded.then(
|
cb.promiseChatLoaded.then(
|
||||||
() => {
|
() => {
|
||||||
this.swapDocShells(cb);
|
this.swapDocShells(cb);
|
||||||
|
@ -225,6 +236,12 @@
|
||||||
chatbar.chatboxForURL.delete("about:blank");
|
chatbar.chatboxForURL.delete("about:blank");
|
||||||
chatbar.chatboxForURL.set(this.src, Cu.getWeakReference(cb));
|
chatbar.chatboxForURL.set(this.src, Cu.getWeakReference(cb));
|
||||||
|
|
||||||
|
let attachEvent = new cb.contentWindow.CustomEvent("socialFrameAttached", {
|
||||||
|
bubbles: true,
|
||||||
|
cancelable: true,
|
||||||
|
});
|
||||||
|
cb.contentDocument.dispatchEvent(attachEvent);
|
||||||
|
|
||||||
deferred.resolve(cb);
|
deferred.resolve(cb);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -457,8 +474,10 @@
|
||||||
// These are from the CSS for the chatbox and must be kept in sync.
|
// These are from the CSS for the chatbox and must be kept in sync.
|
||||||
// We can't use calcTotalWidthOf due to the transitions...
|
// We can't use calcTotalWidthOf due to the transitions...
|
||||||
const CHAT_WIDTH_OPEN = 260;
|
const CHAT_WIDTH_OPEN = 260;
|
||||||
|
const CHAT_WIDTH_OPEN_ALT = 300;
|
||||||
const CHAT_WIDTH_MINIMIZED = 160;
|
const CHAT_WIDTH_MINIMIZED = 160;
|
||||||
let openWidth = aChatbox.hasAttribute("large") ? 300 : CHAT_WIDTH_OPEN;
|
let openWidth = aChatbox.hasAttribute("customSize") ?
|
||||||
|
CHAT_WIDTH_OPEN_ALT : CHAT_WIDTH_OPEN;
|
||||||
|
|
||||||
return aChatbox.minimized ? CHAT_WIDTH_MINIMIZED : openWidth;
|
return aChatbox.minimized ? CHAT_WIDTH_MINIMIZED : openWidth;
|
||||||
]]></body>
|
]]></body>
|
||||||
|
@ -684,18 +703,27 @@
|
||||||
if (event.target != otherWin.document)
|
if (event.target != otherWin.document)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (aChatbox.hasAttribute("customSize")) {
|
||||||
|
otherWin.document.getElementById("chat-window").
|
||||||
|
setAttribute("customSize", aChatbox.getAttribute("customSize"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let document = aChatbox.contentDocument;
|
||||||
let detachEvent = new aChatbox.contentWindow.CustomEvent("socialFrameDetached", {
|
let detachEvent = new aChatbox.contentWindow.CustomEvent("socialFrameDetached", {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
cancelable: true,
|
cancelable: true,
|
||||||
});
|
});
|
||||||
aChatbox.contentDocument.dispatchEvent(detachEvent);
|
|
||||||
|
|
||||||
otherWin.removeEventListener("load", _chatLoad, true);
|
otherWin.removeEventListener("load", _chatLoad, true);
|
||||||
let otherChatbox = otherWin.document.getElementById("chatter");
|
let otherChatbox = otherWin.document.getElementById("chatter");
|
||||||
|
aChatbox.setDecorationAttributes(otherChatbox);
|
||||||
aChatbox.swapDocShells(otherChatbox);
|
aChatbox.swapDocShells(otherChatbox);
|
||||||
aChatbox.close();
|
aChatbox.close();
|
||||||
chatbar.chatboxForURL.set(aChatbox.src, Cu.getWeakReference(otherChatbox));
|
chatbar.chatboxForURL.set(aChatbox.src, Cu.getWeakReference(otherChatbox));
|
||||||
|
|
||||||
|
// All processing is done, now we can fire the event.
|
||||||
|
document.dispatchEvent(detachEvent);
|
||||||
|
|
||||||
deferred.resolve(otherChatbox);
|
deferred.resolve(otherChatbox);
|
||||||
}, true);
|
}, true);
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
|
|
|
@ -269,10 +269,6 @@ html[dir="rtl"] .new-room-view > .context > .context-content > .context-preview
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.new-room-view > .context > .context-content > .context-preview[src=""] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.new-room-view > .context > .context-content > .context-description {
|
.new-room-view > .context > .context-content > .context-description {
|
||||||
flex: 0 1 auto;
|
flex: 0 1 auto;
|
||||||
display: block;
|
display: block;
|
||||||
|
|
|
@ -29,7 +29,7 @@ loop.conversationViews = (function(mozL10n) {
|
||||||
if (!contact.email || contact.email.length === 0) {
|
if (!contact.email || contact.email.length === 0) {
|
||||||
return { value: "" };
|
return { value: "" };
|
||||||
}
|
}
|
||||||
return contact.email.find(e => e.pref) || contact.email[0];
|
return contact.email.find(function find(e) { return e.pref; }) || contact.email[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
function _getContactDisplayName(contact) {
|
function _getContactDisplayName(contact) {
|
||||||
|
|
|
@ -29,7 +29,7 @@ loop.conversationViews = (function(mozL10n) {
|
||||||
if (!contact.email || contact.email.length === 0) {
|
if (!contact.email || contact.email.length === 0) {
|
||||||
return { value: "" };
|
return { value: "" };
|
||||||
}
|
}
|
||||||
return contact.email.find(e => e.pref) || contact.email[0];
|
return contact.email.find(function find(e) { return e.pref; }) || contact.email[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
function _getContactDisplayName(contact) {
|
function _getContactDisplayName(contact) {
|
||||||
|
|
|
@ -500,9 +500,8 @@ loop.panel = (function(_, mozL10n) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
React.createElement("div", {className: "room-entry-context-item"},
|
React.createElement("div", {className: "room-entry-context-item"},
|
||||||
React.createElement("a", {href: roomUrl.location, onClick: this.handleClick},
|
React.createElement("a", {href: roomUrl.location, title: roomUrl.description, onClick: this.handleClick},
|
||||||
React.createElement("img", {title: roomUrl.description,
|
React.createElement("img", {src: roomUrl.thumbnail || "loop/shared/img/icons-16x16.svg#globe"})
|
||||||
src: roomUrl.thumbnail})
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -766,6 +765,7 @@ loop.panel = (function(_, mozL10n) {
|
||||||
hide: !hostname ||
|
hide: !hostname ||
|
||||||
!this.props.mozLoop.getLoopPref("contextInConversations.enabled")
|
!this.props.mozLoop.getLoopPref("contextInConversations.enabled")
|
||||||
});
|
});
|
||||||
|
var thumbnail = this.state.previewImage || "loop/shared/img/icons-16x16.svg#globe";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
React.createElement("div", {className: "new-room-view"},
|
React.createElement("div", {className: "new-room-view"},
|
||||||
|
@ -773,7 +773,7 @@ loop.panel = (function(_, mozL10n) {
|
||||||
React.createElement(Checkbox, {label: mozL10n.get("context_inroom_label"),
|
React.createElement(Checkbox, {label: mozL10n.get("context_inroom_label"),
|
||||||
onChange: this.onCheckboxChange}),
|
onChange: this.onCheckboxChange}),
|
||||||
React.createElement("div", {className: "context-content"},
|
React.createElement("div", {className: "context-content"},
|
||||||
React.createElement("img", {className: "context-preview", src: this.state.previewImage}),
|
React.createElement("img", {className: "context-preview", src: thumbnail}),
|
||||||
React.createElement("span", {className: "context-description"},
|
React.createElement("span", {className: "context-description"},
|
||||||
this.state.description,
|
this.state.description,
|
||||||
React.createElement("span", {className: "context-url"}, hostname)
|
React.createElement("span", {className: "context-url"}, hostname)
|
||||||
|
|
|
@ -500,9 +500,8 @@ loop.panel = (function(_, mozL10n) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="room-entry-context-item">
|
<div className="room-entry-context-item">
|
||||||
<a href={roomUrl.location} onClick={this.handleClick}>
|
<a href={roomUrl.location} title={roomUrl.description} onClick={this.handleClick}>
|
||||||
<img title={roomUrl.description}
|
<img src={roomUrl.thumbnail || "loop/shared/img/icons-16x16.svg#globe"} />
|
||||||
src={roomUrl.thumbnail} />
|
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -766,6 +765,7 @@ loop.panel = (function(_, mozL10n) {
|
||||||
hide: !hostname ||
|
hide: !hostname ||
|
||||||
!this.props.mozLoop.getLoopPref("contextInConversations.enabled")
|
!this.props.mozLoop.getLoopPref("contextInConversations.enabled")
|
||||||
});
|
});
|
||||||
|
var thumbnail = this.state.previewImage || "loop/shared/img/icons-16x16.svg#globe";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="new-room-view">
|
<div className="new-room-view">
|
||||||
|
@ -773,7 +773,7 @@ loop.panel = (function(_, mozL10n) {
|
||||||
<Checkbox label={mozL10n.get("context_inroom_label")}
|
<Checkbox label={mozL10n.get("context_inroom_label")}
|
||||||
onChange={this.onCheckboxChange} />
|
onChange={this.onCheckboxChange} />
|
||||||
<div className="context-content">
|
<div className="context-content">
|
||||||
<img className="context-preview" src={this.state.previewImage}/>
|
<img className="context-preview" src={thumbnail} />
|
||||||
<span className="context-description">
|
<span className="context-description">
|
||||||
{this.state.description}
|
{this.state.description}
|
||||||
<span className="context-url">{hostname}</span>
|
<span className="context-url">{hostname}</span>
|
||||||
|
|
|
@ -480,7 +480,7 @@ loop.roomViews = (function(mozL10n) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var url = this._getURL();
|
var url = this._getURL();
|
||||||
var thumbnail = url && url.thumbnail || "";
|
var thumbnail = url && url.thumbnail || "loop/shared/img/icons-16x16.svg#globe";
|
||||||
var urlDescription = url && url.description || "";
|
var urlDescription = url && url.description || "";
|
||||||
var location = url && url.location || "";
|
var location = url && url.location || "";
|
||||||
var locationData = null;
|
var locationData = null;
|
||||||
|
@ -718,7 +718,6 @@ loop.roomViews = (function(mozL10n) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
React.createElement("div", {className: "room-conversation-wrapper"},
|
React.createElement("div", {className: "room-conversation-wrapper"},
|
||||||
React.createElement(sharedViews.TextChatView, {dispatcher: this.props.dispatcher}),
|
|
||||||
React.createElement(DesktopRoomInvitationView, {
|
React.createElement(DesktopRoomInvitationView, {
|
||||||
dispatcher: this.props.dispatcher,
|
dispatcher: this.props.dispatcher,
|
||||||
error: this.state.error,
|
error: this.state.error,
|
||||||
|
@ -761,7 +760,8 @@ loop.roomViews = (function(mozL10n) {
|
||||||
savingContext: this.state.savingContext,
|
savingContext: this.state.savingContext,
|
||||||
mozLoop: this.props.mozLoop,
|
mozLoop: this.props.mozLoop,
|
||||||
roomData: roomData,
|
roomData: roomData,
|
||||||
show: !shouldRenderInvitationOverlay && shouldRenderContextView})
|
show: !shouldRenderInvitationOverlay && shouldRenderContextView}),
|
||||||
|
React.createElement(sharedViews.TextChatView, {dispatcher: this.props.dispatcher})
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -480,7 +480,7 @@ loop.roomViews = (function(mozL10n) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var url = this._getURL();
|
var url = this._getURL();
|
||||||
var thumbnail = url && url.thumbnail || "";
|
var thumbnail = url && url.thumbnail || "loop/shared/img/icons-16x16.svg#globe";
|
||||||
var urlDescription = url && url.description || "";
|
var urlDescription = url && url.description || "";
|
||||||
var location = url && url.location || "";
|
var location = url && url.location || "";
|
||||||
var locationData = null;
|
var locationData = null;
|
||||||
|
@ -553,7 +553,7 @@ loop.roomViews = (function(mozL10n) {
|
||||||
<div className="room-context-label">{mozL10n.get("context_inroom_label")}</div>
|
<div className="room-context-label">{mozL10n.get("context_inroom_label")}</div>
|
||||||
<div className="room-context-content"
|
<div className="room-context-content"
|
||||||
onClick={this.handleContextClick}>
|
onClick={this.handleContextClick}>
|
||||||
<img className="room-context-thumbnail" src={thumbnail}/>
|
<img className="room-context-thumbnail" src={thumbnail} />
|
||||||
<div className="room-context-description"
|
<div className="room-context-description"
|
||||||
title={urlDescription}>
|
title={urlDescription}>
|
||||||
{this._truncate(urlDescription)}
|
{this._truncate(urlDescription)}
|
||||||
|
@ -718,7 +718,6 @@ loop.roomViews = (function(mozL10n) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="room-conversation-wrapper">
|
<div className="room-conversation-wrapper">
|
||||||
<sharedViews.TextChatView dispatcher={this.props.dispatcher} />
|
|
||||||
<DesktopRoomInvitationView
|
<DesktopRoomInvitationView
|
||||||
dispatcher={this.props.dispatcher}
|
dispatcher={this.props.dispatcher}
|
||||||
error={this.state.error}
|
error={this.state.error}
|
||||||
|
@ -762,6 +761,7 @@ loop.roomViews = (function(mozL10n) {
|
||||||
mozLoop={this.props.mozLoop}
|
mozLoop={this.props.mozLoop}
|
||||||
roomData={roomData}
|
roomData={roomData}
|
||||||
show={!shouldRenderInvitationOverlay && shouldRenderContextView} />
|
show={!shouldRenderInvitationOverlay && shouldRenderContextView} />
|
||||||
|
<sharedViews.TextChatView dispatcher={this.props.dispatcher} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -651,27 +651,6 @@ html, .fx-embedded, #main,
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The .fx-embbeded .text-chat-* styles are very temporarily whilst we work on
|
|
||||||
* text chat (bug 1108892 and dependencies).
|
|
||||||
*/
|
|
||||||
.fx-embedded .text-chat-view {
|
|
||||||
height: 60px;
|
|
||||||
color: white;
|
|
||||||
background-color: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fx-embedded .text-chat-entries {
|
|
||||||
/* XXX Should use flex, this is just for the initial implementation. */
|
|
||||||
height: calc(100% - 2em);
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fx-embedded .text-chat-box {
|
|
||||||
width: 100%;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We use 641px rather than 640, as min-width and max-width are inclusive */
|
/* We use 641px rather than 640, as min-width and max-width are inclusive */
|
||||||
@media screen and (min-width:641px) {
|
@media screen and (min-width:641px) {
|
||||||
.standalone .conversation-toolbar {
|
.standalone .conversation-toolbar {
|
||||||
|
@ -681,10 +660,6 @@ html, .fx-embedded, #main,
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fx-embedded .local-stream {
|
|
||||||
position: fixed;
|
|
||||||
}
|
|
||||||
|
|
||||||
.standalone .local-stream,
|
.standalone .local-stream,
|
||||||
.standalone .remote-inset-stream {
|
.standalone .remote-inset-stream {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -697,7 +672,7 @@ html, .fx-embedded, #main,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Nested video elements */
|
/* Nested video elements */
|
||||||
.conversation .media.nested {
|
.standalone .conversation .media.nested {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
@ -744,7 +719,7 @@ html, .fx-embedded, #main,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Nested video elements */
|
/* Nested video elements */
|
||||||
.conversation .media.nested {
|
.standalone .conversation .media.nested {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -969,10 +944,6 @@ body[platform="win"] .share-service-dropdown.overflow > .dropdown-menu-item {
|
||||||
flex: 0 1 auto;
|
flex: 0 1 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.room-context-thumbnail[src=""] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.room-context > .error-display-area.error {
|
.room-context > .error-display-area.error {
|
||||||
display: block;
|
display: block;
|
||||||
background-color: rgba(215,67,69,.8);
|
background-color: rgba(215,67,69,.8);
|
||||||
|
@ -1211,9 +1182,8 @@ html[dir="rtl"] .room-context-btn-edit {
|
||||||
|
|
||||||
.standalone-context-url > img {
|
.standalone-context-url > img {
|
||||||
margin: 1em auto;
|
margin: 1em auto;
|
||||||
max-width: 50%;
|
width: 16px;
|
||||||
/* allows 20% for the description wrapper plus the margins */
|
height: 16px;
|
||||||
max-height: calc(80% - 2em);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.standalone-context-url-description-wrapper {
|
.standalone-context-url-description-wrapper {
|
||||||
|
@ -1244,18 +1214,64 @@ html[dir="rtl"] .room-context-btn-edit {
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Text chat in rooms styles */
|
||||||
|
|
||||||
|
.fx-embedded .room-conversation-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fx-embedded .video-layout-wrapper {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-chat-view {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fx-embedded .text-chat-view {
|
||||||
|
flex: 1 0 auto;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fx-embedded .text-chat-entries {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
max-height: 120px;
|
||||||
|
min-height: 60px;
|
||||||
|
padding: .7em .5em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fx-embedded .text-chat-box {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
max-height: 40px;
|
||||||
|
min-height: 40px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.text-chat-entries {
|
.text-chat-entries {
|
||||||
margin: auto;
|
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
border: 1px solid red;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-chat-entry {
|
.text-chat-entry {
|
||||||
text-align: left;
|
text-align: end;
|
||||||
|
margin-bottom: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-chat-entry > span {
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: #0095dd;
|
||||||
|
border-radius: 10000px;
|
||||||
|
padding: .5em 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-chat-entry.received {
|
.text-chat-entry.received {
|
||||||
text-align: right;
|
text-align: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-chat-entry.received > span {
|
||||||
|
border-color: #d8d8d8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-chat-box {
|
.text-chat-box {
|
||||||
|
@ -1264,6 +1280,14 @@ html[dir="rtl"] .room-context-btn-edit {
|
||||||
|
|
||||||
.text-chat-box > form > input {
|
.text-chat-box > form > input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height: 40px;
|
||||||
|
padding: 0 .5em .5em;
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fx-embedded .text-chat-box > form > input {
|
||||||
|
border: 0;
|
||||||
|
border-top: 1px solid #999;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width:640px) {
|
@media screen and (max-width:640px) {
|
||||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
До Ширина: | Высота: | Размер: 13 KiB После Ширина: | Высота: | Размер: 73 KiB |
|
@ -255,6 +255,10 @@ loop.shared.mixins = (function() {
|
||||||
*/
|
*/
|
||||||
var DocumentVisibilityMixin = {
|
var DocumentVisibilityMixin = {
|
||||||
_onDocumentVisibilityChanged: function(event) {
|
_onDocumentVisibilityChanged: function(event) {
|
||||||
|
if (!this.isMounted()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var hidden = event.target.hidden;
|
var hidden = event.target.hidden;
|
||||||
if (hidden && typeof this.onDocumentHidden === "function") {
|
if (hidden && typeof this.onDocumentHidden === "function") {
|
||||||
this.onDocumentHidden();
|
this.onDocumentHidden();
|
||||||
|
@ -267,6 +271,9 @@ loop.shared.mixins = (function() {
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
rootObject.document.addEventListener(
|
rootObject.document.addEventListener(
|
||||||
"visibilitychange", this._onDocumentVisibilityChanged);
|
"visibilitychange", this._onDocumentVisibilityChanged);
|
||||||
|
// Assume that the consumer components is only mounted when the document
|
||||||
|
// has become visible.
|
||||||
|
this._onDocumentVisibilityChanged({ target: rootObject.document });
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUnmount: function() {
|
componentWillUnmount: function() {
|
||||||
|
|
|
@ -68,6 +68,27 @@ loop.store.TextChatStore = (function() {
|
||||||
*/
|
*/
|
||||||
dataChannelsAvailable: function() {
|
dataChannelsAvailable: function() {
|
||||||
this.setStoreState({ textChatEnabled: true });
|
this.setStoreState({ textChatEnabled: true });
|
||||||
|
window.dispatchEvent(new CustomEvent("LoopChatEnabled"));
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends a message to the store, which may be of type 'sent' or 'received'.
|
||||||
|
*
|
||||||
|
* @param {String} type
|
||||||
|
* @param {sharedActions.ReceivedTextChatMessage|sharedActions.SendTextChatMessage} actionData
|
||||||
|
*/
|
||||||
|
_appendTextChatMessage: function(type, actionData) {
|
||||||
|
// We create a new list to avoid updating the store's state directly,
|
||||||
|
// which confuses the views.
|
||||||
|
var message = {
|
||||||
|
type: type,
|
||||||
|
contentType: actionData.contentType,
|
||||||
|
message: actionData.message
|
||||||
|
};
|
||||||
|
var newList = this._storeState.messageList.concat(message);
|
||||||
|
this.setStoreState({ messageList: newList });
|
||||||
|
|
||||||
|
window.dispatchEvent(new CustomEvent("LoopChatMessageAppended"));
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -81,14 +102,8 @@ loop.store.TextChatStore = (function() {
|
||||||
if (actionData.contentType != CHAT_CONTENT_TYPES.TEXT) {
|
if (actionData.contentType != CHAT_CONTENT_TYPES.TEXT) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// We create a new list to avoid updating the store's state directly,
|
|
||||||
// which confuses the views.
|
this._appendTextChatMessage(CHAT_MESSAGE_TYPES.RECEIVED, actionData);
|
||||||
var newList = this._storeState.messageList.concat({
|
|
||||||
type: CHAT_MESSAGE_TYPES.RECEIVED,
|
|
||||||
contentType: actionData.contentType,
|
|
||||||
message: actionData.message
|
|
||||||
});
|
|
||||||
this.setStoreState({ messageList: newList });
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -97,15 +112,8 @@ loop.store.TextChatStore = (function() {
|
||||||
* @param {sharedActions.SendTextChatMessage} actionData
|
* @param {sharedActions.SendTextChatMessage} actionData
|
||||||
*/
|
*/
|
||||||
sendTextChatMessage: function(actionData) {
|
sendTextChatMessage: function(actionData) {
|
||||||
// We create a new list to avoid updating the store's state directly,
|
this._appendTextChatMessage(CHAT_MESSAGE_TYPES.SENT, actionData);
|
||||||
// which confuses the views.
|
|
||||||
var newList = this._storeState.messageList.concat({
|
|
||||||
type: CHAT_MESSAGE_TYPES.SENT,
|
|
||||||
contentType: actionData.contentType,
|
|
||||||
message: actionData.message
|
|
||||||
});
|
|
||||||
this._sdkDriver.sendTextChatMessage(actionData);
|
this._sdkDriver.sendTextChatMessage(actionData);
|
||||||
this.setStoreState({ messageList: newList });
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ loop.shared.views.TextChatView = (function(mozl10n) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
React.createElement("div", {className: classes},
|
React.createElement("div", {className: classes},
|
||||||
this.props.message
|
React.createElement("span", null, this.props.message)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,9 @@ loop.shared.views.TextChatView = (function(mozl10n) {
|
||||||
|
|
||||||
componentWillUpdate: function() {
|
componentWillUpdate: function() {
|
||||||
var node = this.getDOMNode();
|
var node = this.getDOMNode();
|
||||||
|
if (!node) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Scroll only if we're right at the bottom of the display.
|
// Scroll only if we're right at the bottom of the display.
|
||||||
this.shouldScroll = node.scrollHeight === node.scrollTop + node.clientHeight;
|
this.shouldScroll = node.scrollHeight === node.scrollTop + node.clientHeight;
|
||||||
},
|
},
|
||||||
|
@ -64,17 +67,23 @@ loop.shared.views.TextChatView = (function(mozl10n) {
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
|
if (!this.props.messageList.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
React.createElement("div", {className: "text-chat-entries"},
|
React.createElement("div", {className: "text-chat-entries"},
|
||||||
|
React.createElement("div", {className: "text-chat-scroller"},
|
||||||
this.props.messageList.map(function(entry, i) {
|
|
||||||
return (
|
this.props.messageList.map(function(entry, i) {
|
||||||
React.createElement(TextChatEntry, {key: i,
|
return (
|
||||||
message: entry.message,
|
React.createElement(TextChatEntry, {key: i,
|
||||||
type: entry.type})
|
message: entry.message,
|
||||||
);
|
type: entry.type})
|
||||||
}, this)
|
);
|
||||||
|
}, this)
|
||||||
|
|
||||||
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -134,12 +143,15 @@ loop.shared.views.TextChatView = (function(mozl10n) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var messageList = this.state.messageList;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
React.createElement("div", {className: "text-chat-view"},
|
React.createElement("div", {className: "text-chat-view"},
|
||||||
React.createElement(TextChatEntriesView, {messageList: this.state.messageList}),
|
React.createElement(TextChatEntriesView, {messageList: messageList}),
|
||||||
React.createElement("div", {className: "text-chat-box"},
|
React.createElement("div", {className: "text-chat-box"},
|
||||||
React.createElement("form", {onSubmit: this.handleFormSubmit},
|
React.createElement("form", {onSubmit: this.handleFormSubmit},
|
||||||
React.createElement("input", {type: "text",
|
React.createElement("input", {type: "text",
|
||||||
|
placeholder: messageList.length ? "" : mozl10n.get("chat_textbox_placeholder"),
|
||||||
onKeyDown: this.handleKeyDown,
|
onKeyDown: this.handleKeyDown,
|
||||||
valueLink: this.linkState("messageDetail")})
|
valueLink: this.linkState("messageDetail")})
|
||||||
)
|
)
|
||||||
|
|
|
@ -29,7 +29,7 @@ loop.shared.views.TextChatView = (function(mozl10n) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes}>
|
<div className={classes}>
|
||||||
{this.props.message}
|
<span>{this.props.message}</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,9 @@ loop.shared.views.TextChatView = (function(mozl10n) {
|
||||||
|
|
||||||
componentWillUpdate: function() {
|
componentWillUpdate: function() {
|
||||||
var node = this.getDOMNode();
|
var node = this.getDOMNode();
|
||||||
|
if (!node) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Scroll only if we're right at the bottom of the display.
|
// Scroll only if we're right at the bottom of the display.
|
||||||
this.shouldScroll = node.scrollHeight === node.scrollTop + node.clientHeight;
|
this.shouldScroll = node.scrollHeight === node.scrollTop + node.clientHeight;
|
||||||
},
|
},
|
||||||
|
@ -64,17 +67,23 @@ loop.shared.views.TextChatView = (function(mozl10n) {
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
|
if (!this.props.messageList.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="text-chat-entries">
|
<div className="text-chat-entries">
|
||||||
{
|
<div className="text-chat-scroller">
|
||||||
this.props.messageList.map(function(entry, i) {
|
{
|
||||||
return (
|
this.props.messageList.map(function(entry, i) {
|
||||||
<TextChatEntry key={i}
|
return (
|
||||||
message={entry.message}
|
<TextChatEntry key={i}
|
||||||
type={entry.type} />
|
message={entry.message}
|
||||||
);
|
type={entry.type} />
|
||||||
}, this)
|
);
|
||||||
}
|
}, this)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -134,12 +143,15 @@ loop.shared.views.TextChatView = (function(mozl10n) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var messageList = this.state.messageList;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="text-chat-view">
|
<div className="text-chat-view">
|
||||||
<TextChatEntriesView messageList={this.state.messageList} />
|
<TextChatEntriesView messageList={messageList} />
|
||||||
<div className="text-chat-box">
|
<div className="text-chat-box">
|
||||||
<form onSubmit={this.handleFormSubmit}>
|
<form onSubmit={this.handleFormSubmit}>
|
||||||
<input type="text"
|
<input type="text"
|
||||||
|
placeholder={messageList.length ? "" : mozl10n.get("chat_textbox_placeholder")}
|
||||||
onKeyDown={this.handleKeyDown}
|
onKeyDown={this.handleKeyDown}
|
||||||
valueLink={this.linkState("messageDetail")} />
|
valueLink={this.linkState("messageDetail")} />
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -853,27 +853,51 @@ let MozLoopServiceInternal = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
chatbox.setAttribute("dark", true);
|
|
||||||
chatbox.setAttribute("large", true);
|
|
||||||
|
|
||||||
chatbox.addEventListener("DOMContentLoaded", function loaded(event) {
|
chatbox.addEventListener("DOMContentLoaded", function loaded(event) {
|
||||||
if (event.target != chatbox.contentDocument) {
|
if (event.target != chatbox.contentDocument) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
chatbox.removeEventListener("DOMContentLoaded", loaded, true);
|
chatbox.removeEventListener("DOMContentLoaded", loaded, true);
|
||||||
|
|
||||||
|
let chatbar = chatbox.parentNode;
|
||||||
let window = chatbox.contentWindow;
|
let window = chatbox.contentWindow;
|
||||||
|
|
||||||
function socialFrameChanged(eventName) {
|
function socialFrameChanged(eventName) {
|
||||||
UITour.availableTargetsCache.clear();
|
UITour.availableTargetsCache.clear();
|
||||||
UITour.notify(eventName);
|
UITour.notify(eventName);
|
||||||
|
|
||||||
|
if (eventName == "Loop:ChatWindowDetached" || eventName == "Loop:ChatWindowAttached") {
|
||||||
|
// After detach, re-attach of the chatbox, refresh its reference so
|
||||||
|
// we can keep using it here.
|
||||||
|
let ref = chatbar.chatboxForURL.get(chatbox.src);
|
||||||
|
chatbox = ref && ref.get() || chatbox;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("socialFrameHide", socialFrameChanged.bind(null, "Loop:ChatWindowHidden"));
|
window.addEventListener("socialFrameHide", socialFrameChanged.bind(null, "Loop:ChatWindowHidden"));
|
||||||
window.addEventListener("socialFrameShow", socialFrameChanged.bind(null, "Loop:ChatWindowShown"));
|
window.addEventListener("socialFrameShow", socialFrameChanged.bind(null, "Loop:ChatWindowShown"));
|
||||||
window.addEventListener("socialFrameDetached", socialFrameChanged.bind(null, "Loop:ChatWindowDetached"));
|
window.addEventListener("socialFrameDetached", socialFrameChanged.bind(null, "Loop:ChatWindowDetached"));
|
||||||
|
window.addEventListener("socialFrameAttached", socialFrameChanged.bind(null, "Loop:ChatWindowAttached"));
|
||||||
window.addEventListener("unload", socialFrameChanged.bind(null, "Loop:ChatWindowClosed"));
|
window.addEventListener("unload", socialFrameChanged.bind(null, "Loop:ChatWindowClosed"));
|
||||||
|
|
||||||
|
const kSizeMap = {
|
||||||
|
LoopChatEnabled: "loopChatEnabled",
|
||||||
|
LoopChatMessageAppended: "loopChatMessageAppended"
|
||||||
|
};
|
||||||
|
|
||||||
|
function onChatEvent(event) {
|
||||||
|
// When the chat box or messages are shown, resize the panel or window
|
||||||
|
// to be slightly higher to accomodate them.
|
||||||
|
let customSize = kSizeMap[event.type];
|
||||||
|
if (customSize) {
|
||||||
|
chatbox.setAttribute("customSize", customSize);
|
||||||
|
chatbox.parentNode.setAttribute("customSize", customSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("LoopChatEnabled", onChatEvent);
|
||||||
|
window.addEventListener("LoopChatMessageAppended", onChatEvent);
|
||||||
|
|
||||||
injectLoopAPI(window);
|
injectLoopAPI(window);
|
||||||
|
|
||||||
let ourID = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
let ourID = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
@ -918,8 +942,16 @@ let MozLoopServiceInternal = {
|
||||||
}.bind(this), true);
|
}.bind(this), true);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!Chat.open(null, origin, "", url, undefined, undefined, callback)) {
|
let chatbox = Chat.open(null, origin, "", url, undefined, undefined, callback);
|
||||||
|
if (!chatbox) {
|
||||||
return null;
|
return null;
|
||||||
|
// It's common for unit tests to overload Chat.open.
|
||||||
|
} else if (chatbox.setAttribute) {
|
||||||
|
// Set properties that influence visual appeara nce of the chatbox right
|
||||||
|
// away to circumvent glitches.
|
||||||
|
chatbox.setAttribute("dark", true);
|
||||||
|
chatbox.setAttribute("customSize", "loopDefault");
|
||||||
|
chatbox.parentNode.setAttribute("customSize", "loopDefault");
|
||||||
}
|
}
|
||||||
return windowId;
|
return windowId;
|
||||||
},
|
},
|
||||||
|
|
|
@ -262,7 +262,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
React.createElement("div", {className: classes},
|
React.createElement("div", {className: classes},
|
||||||
React.createElement("img", {src: this.props.roomContextUrl.thumbnail}),
|
React.createElement("img", {src: this.props.roomContextUrl.thumbnail || "shared/img/icons-16x16.svg#globe"}),
|
||||||
React.createElement("div", {className: "standalone-context-url-description-wrapper"},
|
React.createElement("div", {className: "standalone-context-url-description-wrapper"},
|
||||||
this.props.roomContextUrl.description,
|
this.props.roomContextUrl.description,
|
||||||
React.createElement("br", null), React.createElement("a", {href: locationInfo.location,
|
React.createElement("br", null), React.createElement("a", {href: locationInfo.location,
|
||||||
|
|
|
@ -262,7 +262,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes}>
|
<div className={classes}>
|
||||||
<img src={this.props.roomContextUrl.thumbnail} />
|
<img src={this.props.roomContextUrl.thumbnail || "shared/img/icons-16x16.svg#globe"} />
|
||||||
<div className="standalone-context-url-description-wrapper">
|
<div className="standalone-context-url-description-wrapper">
|
||||||
{this.props.roomContextUrl.description}
|
{this.props.roomContextUrl.description}
|
||||||
<br /><a href={locationInfo.location}
|
<br /><a href={locationInfo.location}
|
||||||
|
|
|
@ -137,3 +137,7 @@ status_in_conversation=In conversation
|
||||||
status_conversation_ended=Conversation ended
|
status_conversation_ended=Conversation ended
|
||||||
status_error=Something went wrong
|
status_error=Something went wrong
|
||||||
support_link=Get Help
|
support_link=Get Help
|
||||||
|
|
||||||
|
# Text chat strings
|
||||||
|
|
||||||
|
chat_textbox_placeholder=Type here…
|
||||||
|
|
|
@ -850,6 +850,24 @@ describe("loop.panel", function() {
|
||||||
expect(contextContent).to.not.equal(null);
|
expect(contextContent).to.not.equal(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should show a default favicon when none is available", function() {
|
||||||
|
fakeMozLoop.getSelectedTabMetadata = function (callback) {
|
||||||
|
callback({
|
||||||
|
url: "https://www.example.com",
|
||||||
|
description: "fake description",
|
||||||
|
previews: [""]
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var view = createTestComponent();
|
||||||
|
|
||||||
|
// Simulate being visible
|
||||||
|
view.onDocumentVisible();
|
||||||
|
|
||||||
|
var previewImage = view.getDOMNode().querySelector(".context-preview");
|
||||||
|
expect(previewImage.src).to.match(/loop\/shared\/img\/icons-16x16.svg#globe$/);
|
||||||
|
});
|
||||||
|
|
||||||
it("should not show context information when a URL is unavailable", function() {
|
it("should not show context information when a URL is unavailable", function() {
|
||||||
fakeMozLoop.getSelectedTabMetadata = function (callback) {
|
fakeMozLoop.getSelectedTabMetadata = function (callback) {
|
||||||
callback({
|
callback({
|
||||||
|
|
|
@ -305,6 +305,19 @@ describe("loop.roomViews", function () {
|
||||||
expect(view.getDOMNode().querySelector(".room-context-url").textContent)
|
expect(view.getDOMNode().querySelector(".room-context-url").textContent)
|
||||||
.eql("hostname");
|
.eql("hostname");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should show a default favicon when none is available", function() {
|
||||||
|
fakeContextURL.thumbnail = null;
|
||||||
|
view = mountTestComponent({
|
||||||
|
showContext: true,
|
||||||
|
roomData: {
|
||||||
|
roomContextUrls: [fakeContextURL]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(view.getDOMNode().querySelector(".room-context-thumbnail").src)
|
||||||
|
.to.match(/loop\/shared\/img\/icons-16x16.svg#globe$/);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -28,10 +28,22 @@ add_task(function* test_mozLoop_getSelectedTabMetadata() {
|
||||||
metadata = yield promiseGetMetadata();
|
metadata = yield promiseGetMetadata();
|
||||||
|
|
||||||
Assert.strictEqual(metadata.url, null, "URL should be empty for about:home");
|
Assert.strictEqual(metadata.url, null, "URL should be empty for about:home");
|
||||||
Assert.ok(metadata.favicon.startsWith("data:image/x-icon;base64,"),
|
Assert.strictEqual(metadata.favicon, null, "Favicon should be empty for about:home");
|
||||||
"Favicon should be set for about:home");
|
|
||||||
Assert.ok(metadata.title, "Title should be set for about:home");
|
Assert.ok(metadata.title, "Title should be set for about:home");
|
||||||
Assert.deepEqual(metadata.previews, [], "No previews available for about:home");
|
Assert.deepEqual(metadata.previews, [], "No previews available for about:home");
|
||||||
|
|
||||||
gBrowser.removeTab(tab);
|
gBrowser.removeTab(tab);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
add_task(function* test_mozLoop_getSelectedTabMetadata_defaultIcon() {
|
||||||
|
let tab = gBrowser.selectedTab = gBrowser.addTab();
|
||||||
|
yield promiseTabLoadEvent(tab, "http://example.com/");
|
||||||
|
let metadata = yield promiseGetMetadata();
|
||||||
|
|
||||||
|
Assert.strictEqual(metadata.url, "http://example.com/", "URL should match");
|
||||||
|
Assert.strictEqual(metadata.favicon, null, "Favicon should be empty");
|
||||||
|
Assert.ok(metadata.title, "Title should be set");
|
||||||
|
Assert.deepEqual(metadata.previews, [], "No previews available");
|
||||||
|
|
||||||
|
gBrowser.removeTab(tab);
|
||||||
|
});
|
||||||
|
|
|
@ -177,7 +177,8 @@ describe("loop.shared.mixins", function() {
|
||||||
|
|
||||||
comp = TestUtils.renderIntoDocument(React.createElement(TestComp));
|
comp = TestUtils.renderIntoDocument(React.createElement(TestComp));
|
||||||
|
|
||||||
sinon.assert.calledOnce(onDocumentVisibleStub);
|
// Twice, because it's also called when the component was mounted.
|
||||||
|
sinon.assert.calledTwice(onDocumentVisibleStub);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should call onDocumentVisible when document visibility changes to hidden",
|
it("should call onDocumentVisible when document visibility changes to hidden",
|
||||||
|
|
|
@ -25,6 +25,11 @@ describe("loop.store.TextChatStore", function () {
|
||||||
store = new loop.store.TextChatStore(dispatcher, {
|
store = new loop.store.TextChatStore(dispatcher, {
|
||||||
sdkDriver: fakeSdkDriver
|
sdkDriver: fakeSdkDriver
|
||||||
});
|
});
|
||||||
|
|
||||||
|
sandbox.stub(window, "dispatchEvent");
|
||||||
|
sandbox.stub(window, "CustomEvent", function(name) {
|
||||||
|
this.name = name;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
|
@ -37,6 +42,14 @@ describe("loop.store.TextChatStore", function () {
|
||||||
|
|
||||||
expect(store.getStoreState("textChatEnabled")).eql(true);
|
expect(store.getStoreState("textChatEnabled")).eql(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should dispatch a LoopChatEnabled event", function() {
|
||||||
|
store.dataChannelsAvailable();
|
||||||
|
|
||||||
|
sinon.assert.calledOnce(window.dispatchEvent);
|
||||||
|
sinon.assert.calledWithExactly(window.dispatchEvent,
|
||||||
|
new CustomEvent("LoopChatEnabled"));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("#receivedTextChatMessage", function() {
|
describe("#receivedTextChatMessage", function() {
|
||||||
|
@ -63,6 +76,17 @@ describe("loop.store.TextChatStore", function () {
|
||||||
|
|
||||||
expect(store.getStoreState("messageList").length).eql(0);
|
expect(store.getStoreState("messageList").length).eql(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should dispatch a LoopChatMessageAppended event", function() {
|
||||||
|
store.receivedTextChatMessage({
|
||||||
|
contentType: CHAT_CONTENT_TYPES.TEXT,
|
||||||
|
message: "Hello!"
|
||||||
|
});
|
||||||
|
|
||||||
|
sinon.assert.calledOnce(window.dispatchEvent);
|
||||||
|
sinon.assert.calledWithExactly(window.dispatchEvent,
|
||||||
|
new CustomEvent("LoopChatMessageAppended"));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("#sendTextChatMessage", function() {
|
describe("#sendTextChatMessage", function() {
|
||||||
|
@ -92,5 +116,16 @@ describe("loop.store.TextChatStore", function () {
|
||||||
message: messageData.message
|
message: messageData.message
|
||||||
}]);
|
}]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should dipatch a LoopChatMessageAppended event", function() {
|
||||||
|
store.sendTextChatMessage({
|
||||||
|
contentType: CHAT_CONTENT_TYPES.TEXT,
|
||||||
|
message: "Hello!"
|
||||||
|
});
|
||||||
|
|
||||||
|
sinon.assert.calledOnce(window.dispatchEvent);
|
||||||
|
sinon.assert.calledWithExactly(window.dispatchEvent,
|
||||||
|
new CustomEvent("LoopChatMessageAppended"));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -80,5 +80,32 @@ describe("loop.shared.views.TextChatView", function () {
|
||||||
message: "Hello!"
|
message: "Hello!"
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should not render message entries when none are sent/ received yet", function() {
|
||||||
|
view = mountTestComponent();
|
||||||
|
|
||||||
|
expect(view.getDOMNode().querySelector(".text-chat-entries")).to.eql(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render message entries when message were sent/ received", function() {
|
||||||
|
view = mountTestComponent();
|
||||||
|
|
||||||
|
store.receivedTextChatMessage({
|
||||||
|
contentType: CHAT_CONTENT_TYPES.TEXT,
|
||||||
|
message: "Hello!"
|
||||||
|
});
|
||||||
|
store.sendTextChatMessage({
|
||||||
|
contentType: CHAT_CONTENT_TYPES.TEXT,
|
||||||
|
message: "Is it me you're looking for?"
|
||||||
|
});
|
||||||
|
|
||||||
|
var node = view.getDOMNode();
|
||||||
|
expect(node.querySelector(".text-chat-entries")).to.not.eql(null);
|
||||||
|
|
||||||
|
var entries = node.querySelectorAll(".text-chat-entry");
|
||||||
|
expect(entries.length).to.eql(2);
|
||||||
|
expect(entries[0].classList.contains("received")).to.eql(true);
|
||||||
|
expect(entries[1].classList.contains("received")).to.not.eql(true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -149,6 +149,20 @@ describe("loop.standaloneRoomViews", function() {
|
||||||
linkInfo: "Shared URL"
|
linkInfo: "Shared URL"
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should display the default favicon when no thumbnail is available", function() {
|
||||||
|
var view = mountTestComponent({
|
||||||
|
roomName: "Mike's room",
|
||||||
|
roomContextUrls: [{
|
||||||
|
description: "Mark's super page",
|
||||||
|
location: "http://invalid.com",
|
||||||
|
thumbnail: ""
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(view.getDOMNode().querySelector(".standalone-context-url > img").src)
|
||||||
|
.to.match(/shared\/img\/icons-16x16.svg#globe$/);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("StandaloneRoomHeader", function() {
|
describe("StandaloneRoomHeader", function() {
|
||||||
|
|
|
@ -148,10 +148,6 @@ body {
|
||||||
|
|
||||||
.svg-icon {
|
.svg-icon {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
margin-left: .5rem;
|
margin-left: .5rem;
|
||||||
background-repeat: no-repeat;
|
border: 0;
|
||||||
background-size: 16px 16px;
|
|
||||||
background-position: center;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -300,13 +300,12 @@
|
||||||
|
|
||||||
var SVGIcon = React.createClass({displayName: "SVGIcon",
|
var SVGIcon = React.createClass({displayName: "SVGIcon",
|
||||||
render: function() {
|
render: function() {
|
||||||
var sizeUnit = this.props.size.split("x")[0] + "px";
|
var sizeUnit = this.props.size.split("x");
|
||||||
return (
|
return (
|
||||||
React.createElement("span", {className: "svg-icon", style: {
|
React.createElement("img", {className: "svg-icon",
|
||||||
"backgroundImage": "url(../content/shared/img/icons-" + this.props.size +
|
src: "../content/shared/img/icons-" + this.props.size + ".svg#" + this.props.shapeId,
|
||||||
".svg#" + this.props.shapeId + ")",
|
width: sizeUnit[0],
|
||||||
"backgroundSize": sizeUnit + " " + sizeUnit
|
height: sizeUnit[1]})
|
||||||
}})
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -328,7 +327,7 @@
|
||||||
],
|
],
|
||||||
"16x16": ["add", "add-hover", "add-active", "audio", "audio-hover", "audio-active",
|
"16x16": ["add", "add-hover", "add-active", "audio", "audio-hover", "audio-active",
|
||||||
"block", "block-red", "block-hover", "block-active", "contacts", "contacts-hover",
|
"block", "block-red", "block-hover", "block-active", "contacts", "contacts-hover",
|
||||||
"contacts-active", "copy", "checkmark", "delete", "google", "google-hover",
|
"contacts-active", "copy", "checkmark", "delete", "globe", "google", "google-hover",
|
||||||
"google-active", "history", "history-hover", "history-active", "leave",
|
"google-active", "history", "history-hover", "history-active", "leave",
|
||||||
"precall", "precall-hover", "precall-active", "screen-white", "screenmute-white",
|
"precall", "precall-hover", "precall-active", "screen-white", "screenmute-white",
|
||||||
"settings", "settings-hover", "settings-active", "share-darkgrey", "tag",
|
"settings", "settings-hover", "settings-active", "share-darkgrey", "tag",
|
||||||
|
|
|
@ -300,13 +300,12 @@
|
||||||
|
|
||||||
var SVGIcon = React.createClass({
|
var SVGIcon = React.createClass({
|
||||||
render: function() {
|
render: function() {
|
||||||
var sizeUnit = this.props.size.split("x")[0] + "px";
|
var sizeUnit = this.props.size.split("x");
|
||||||
return (
|
return (
|
||||||
<span className="svg-icon" style={{
|
<img className="svg-icon"
|
||||||
"backgroundImage": "url(../content/shared/img/icons-" + this.props.size +
|
src={"../content/shared/img/icons-" + this.props.size + ".svg#" + this.props.shapeId}
|
||||||
".svg#" + this.props.shapeId + ")",
|
width={sizeUnit[0]}
|
||||||
"backgroundSize": sizeUnit + " " + sizeUnit
|
height={sizeUnit[1]} />
|
||||||
}} />
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -328,7 +327,7 @@
|
||||||
],
|
],
|
||||||
"16x16": ["add", "add-hover", "add-active", "audio", "audio-hover", "audio-active",
|
"16x16": ["add", "add-hover", "add-active", "audio", "audio-hover", "audio-active",
|
||||||
"block", "block-red", "block-hover", "block-active", "contacts", "contacts-hover",
|
"block", "block-red", "block-hover", "block-active", "contacts", "contacts-hover",
|
||||||
"contacts-active", "copy", "checkmark", "delete", "google", "google-hover",
|
"contacts-active", "copy", "checkmark", "delete", "globe", "google", "google-hover",
|
||||||
"google-active", "history", "history-hover", "history-active", "leave",
|
"google-active", "history", "history-hover", "history-active", "leave",
|
||||||
"precall", "precall-hover", "precall-active", "screen-white", "screenmute-white",
|
"precall", "precall-hover", "precall-active", "screen-white", "screenmute-white",
|
||||||
"settings", "settings-hover", "settings-active", "share-darkgrey", "tag",
|
"settings", "settings-hover", "settings-active", "share-darkgrey", "tag",
|
||||||
|
|
|
@ -193,6 +193,10 @@ let NetMonitorView = {
|
||||||
* @return string (e.g, "network-inspector-view" or "network-statistics-view")
|
* @return string (e.g, "network-inspector-view" or "network-statistics-view")
|
||||||
*/
|
*/
|
||||||
get currentFrontendMode() {
|
get currentFrontendMode() {
|
||||||
|
// The getter may be called from a timeout after the panel is destroyed.
|
||||||
|
if (!this._body.selectedPanel) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return this._body.selectedPanel.id;
|
return this._body.selectedPanel.id;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ support-files =
|
||||||
html_post-raw-test-page.html
|
html_post-raw-test-page.html
|
||||||
html_post-raw-with-headers-test-page.html
|
html_post-raw-with-headers-test-page.html
|
||||||
html_simple-test-page.html
|
html_simple-test-page.html
|
||||||
|
html_send-beacon.html
|
||||||
html_sorting-test-page.html
|
html_sorting-test-page.html
|
||||||
html_statistics-test-page.html
|
html_statistics-test-page.html
|
||||||
html_status-codes-test-page.html
|
html_status-codes-test-page.html
|
||||||
|
@ -99,6 +100,8 @@ skip-if = e10s # Bug 1091612
|
||||||
[browser_net_security-tab-deselect.js]
|
[browser_net_security-tab-deselect.js]
|
||||||
[browser_net_security-tab-visibility.js]
|
[browser_net_security-tab-visibility.js]
|
||||||
[browser_net_security-warnings.js]
|
[browser_net_security-warnings.js]
|
||||||
|
[browser_net_send-beacon.js]
|
||||||
|
[browser_net_send-beacon-other-tab.js]
|
||||||
[browser_net_simple-init.js]
|
[browser_net_simple-init.js]
|
||||||
[browser_net_simple-request-data.js]
|
[browser_net_simple-request-data.js]
|
||||||
[browser_net_simple-request-details.js]
|
[browser_net_simple-request-details.js]
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests if beacons from other tabs are properly ignored.
|
||||||
|
*/
|
||||||
|
|
||||||
|
let test = Task.async(function*() {
|
||||||
|
let [, debuggee, monitor] = yield initNetMonitor(SIMPLE_URL);
|
||||||
|
let { RequestsMenu } = monitor.panelWin.NetMonitorView;
|
||||||
|
RequestsMenu.lazyUpdate = false;
|
||||||
|
|
||||||
|
let tab = yield addTab(SEND_BEACON_URL);
|
||||||
|
let beaconDebuggee = tab.linkedBrowser.contentWindow.wrappedJSObject;
|
||||||
|
info("Beacon tab added successfully.");
|
||||||
|
|
||||||
|
is(RequestsMenu.itemCount, 0, "The requests menu should be empty.");
|
||||||
|
|
||||||
|
beaconDebuggee.performRequest();
|
||||||
|
debuggee.location.reload();
|
||||||
|
|
||||||
|
yield waitForNetworkEvents(monitor, 1);
|
||||||
|
is(RequestsMenu.itemCount, 1, "Only the reload should be recorded.");
|
||||||
|
let request = RequestsMenu.getItemAtIndex(0);
|
||||||
|
is(request.attachment.method, "GET", "The method is correct.");
|
||||||
|
is(request.attachment.status, "200", "The status is correct.");
|
||||||
|
|
||||||
|
yield teardown(monitor);
|
||||||
|
removeTab(tab);
|
||||||
|
finish();
|
||||||
|
});
|
|
@ -0,0 +1,27 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests if beacons are handled correctly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
let test = Task.async(function*() {
|
||||||
|
let [, debuggee, monitor] = yield initNetMonitor(SEND_BEACON_URL);
|
||||||
|
let { RequestsMenu } = monitor.panelWin.NetMonitorView;
|
||||||
|
|
||||||
|
RequestsMenu.lazyUpdate = false;
|
||||||
|
|
||||||
|
is(RequestsMenu.itemCount, 0, "The requests menu should be empty.");
|
||||||
|
|
||||||
|
debuggee.performRequest();
|
||||||
|
|
||||||
|
yield waitForNetworkEvents(monitor, 1);
|
||||||
|
is(RequestsMenu.itemCount, 1, "The beacon should be recorded.");
|
||||||
|
let request = RequestsMenu.getItemAtIndex(0);
|
||||||
|
is(request.attachment.method, "POST", "The method is correct.");
|
||||||
|
ok(request.attachment.url.endsWith("beacon_request"), "The URL is correct.");
|
||||||
|
is(request.attachment.status, "404", "The status is correct.");
|
||||||
|
|
||||||
|
yield teardown(monitor);
|
||||||
|
finish();
|
||||||
|
});
|
|
@ -40,6 +40,7 @@ const SINGLE_GET_URL = EXAMPLE_URL + "html_single-get-page.html";
|
||||||
const STATISTICS_URL = EXAMPLE_URL + "html_statistics-test-page.html";
|
const STATISTICS_URL = EXAMPLE_URL + "html_statistics-test-page.html";
|
||||||
const CURL_URL = EXAMPLE_URL + "html_copy-as-curl.html";
|
const CURL_URL = EXAMPLE_URL + "html_copy-as-curl.html";
|
||||||
const CURL_UTILS_URL = EXAMPLE_URL + "html_curl-utils.html";
|
const CURL_UTILS_URL = EXAMPLE_URL + "html_curl-utils.html";
|
||||||
|
const SEND_BEACON_URL = EXAMPLE_URL + "html_send-beacon.html";
|
||||||
|
|
||||||
const SIMPLE_SJS = EXAMPLE_URL + "sjs_simple-test-server.sjs";
|
const SIMPLE_SJS = EXAMPLE_URL + "sjs_simple-test-server.sjs";
|
||||||
const CONTENT_TYPE_SJS = EXAMPLE_URL + "sjs_content-type-test-server.sjs";
|
const CONTENT_TYPE_SJS = EXAMPLE_URL + "sjs_content-type-test-server.sjs";
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
<!-- Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||||
|
<!doctype html>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||||
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="Expires" content="0" />
|
||||||
|
<title>Network Monitor test page</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<p>Send beacon test</p>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
function performRequest() {
|
||||||
|
navigator.sendBeacon("beacon_request");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -116,6 +116,7 @@ support-files =
|
||||||
[browser_perf_recordings-io-02.js]
|
[browser_perf_recordings-io-02.js]
|
||||||
[browser_perf_recordings-io-03.js]
|
[browser_perf_recordings-io-03.js]
|
||||||
[browser_perf_recordings-io-04.js]
|
[browser_perf_recordings-io-04.js]
|
||||||
|
[browser_perf_recordings-io-05.js]
|
||||||
[browser_perf-range-changed-render.js]
|
[browser_perf-range-changed-render.js]
|
||||||
[browser_perf-recording-selected-01.js]
|
[browser_perf-recording-selected-01.js]
|
||||||
[browser_perf-recording-selected-02.js]
|
[browser_perf-recording-selected-02.js]
|
||||||
|
|
|
@ -29,7 +29,6 @@ let test = Task.async(function*() {
|
||||||
yield DetailsView.selectView("memory-calltree");
|
yield DetailsView.selectView("memory-calltree");
|
||||||
yield DetailsView.selectView("memory-flamegraph");
|
yield DetailsView.selectView("memory-flamegraph");
|
||||||
|
|
||||||
|
|
||||||
// Verify original recording.
|
// Verify original recording.
|
||||||
|
|
||||||
let originalData = PerformanceController.getCurrentRecording().getAllData();
|
let originalData = PerformanceController.getCurrentRecording().getAllData();
|
||||||
|
@ -81,25 +80,6 @@ let test = Task.async(function*() {
|
||||||
is(importedData.configuration.withMemory, originalData.configuration.withMemory,
|
is(importedData.configuration.withMemory, originalData.configuration.withMemory,
|
||||||
"The imported data is identical to the original data (9).");
|
"The imported data is identical to the original data (9).");
|
||||||
|
|
||||||
yield teardown(panel);
|
|
||||||
|
|
||||||
// Test that when importing and no graphs rendered yet,
|
|
||||||
// we do not get a getMappedSelection error
|
|
||||||
// bug 1160828
|
|
||||||
var { target, panel, toolbox } = yield initPerformance(SIMPLE_URL);
|
|
||||||
var { EVENTS, PerformanceController, DetailsView, DetailsSubview, OverviewView, WaterfallView } = panel.panelWin;
|
|
||||||
yield PerformanceController.clearRecordings();
|
|
||||||
|
|
||||||
rerendered = once(WaterfallView, EVENTS.WATERFALL_RENDERED);
|
|
||||||
imported = once(PerformanceController, EVENTS.RECORDING_IMPORTED);
|
|
||||||
yield PerformanceController.importRecording("", file);
|
|
||||||
|
|
||||||
yield imported;
|
|
||||||
ok(true, "The recording data appears to have been successfully imported.");
|
|
||||||
|
|
||||||
yield rerendered;
|
|
||||||
ok(true, "The imported data was re-rendered.");
|
|
||||||
|
|
||||||
yield teardown(panel);
|
yield teardown(panel);
|
||||||
finish();
|
finish();
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that when importing and no graphs rendered yet, we do not get a
|
||||||
|
* `getMappedSelection` error.
|
||||||
|
*/
|
||||||
|
|
||||||
|
let test = Task.async(function*() {
|
||||||
|
var { target, panel, toolbox } = yield initPerformance(SIMPLE_URL);
|
||||||
|
var { EVENTS, PerformanceController, WaterfallView } = panel.panelWin;
|
||||||
|
|
||||||
|
yield startRecording(panel);
|
||||||
|
yield stopRecording(panel);
|
||||||
|
|
||||||
|
// Save recording.
|
||||||
|
|
||||||
|
let file = FileUtils.getFile("TmpD", ["tmpprofile.json"]);
|
||||||
|
file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, parseInt("666", 8));
|
||||||
|
|
||||||
|
let exported = once(PerformanceController, EVENTS.RECORDING_EXPORTED);
|
||||||
|
yield PerformanceController.exportRecording("", PerformanceController.getCurrentRecording(), file);
|
||||||
|
|
||||||
|
yield exported;
|
||||||
|
ok(true, "The recording data appears to have been successfully saved.");
|
||||||
|
|
||||||
|
// Clear and re-import.
|
||||||
|
|
||||||
|
yield PerformanceController.clearRecordings();
|
||||||
|
|
||||||
|
let rendered = once(WaterfallView, EVENTS.WATERFALL_RENDERED);
|
||||||
|
let imported = once(PerformanceController, EVENTS.RECORDING_IMPORTED);
|
||||||
|
yield PerformanceController.importRecording("", file);
|
||||||
|
yield imported;
|
||||||
|
yield rendered;
|
||||||
|
|
||||||
|
ok(true, "No error was thrown.");
|
||||||
|
|
||||||
|
yield teardown(panel);
|
||||||
|
finish();
|
||||||
|
});
|
|
@ -65,10 +65,8 @@ function* spawnTest() {
|
||||||
is(afterResizeBarsCount, beforeResizeBarsCount,
|
is(afterResizeBarsCount, beforeResizeBarsCount,
|
||||||
"The same subset of the total markers remained visible.");
|
"The same subset of the total markers remained visible.");
|
||||||
|
|
||||||
// Temporarily disable the following assertion; intermittent failures.
|
is(Array.indexOf($$(".waterfall-tree-item"), $(".waterfall-tree-item:focus")), 2,
|
||||||
// Bug 1169352.
|
"The correct item is still focused in the tree.");
|
||||||
// is(Array.indexOf($$(".waterfall-tree-item"), $(".waterfall-tree-item:focus")), 2,
|
|
||||||
// "The correct item is still focused in the tree.");
|
|
||||||
ok(!$("#waterfall-details").hidden,
|
ok(!$("#waterfall-details").hidden,
|
||||||
"The waterfall sidebar is still visible.");
|
"The waterfall sidebar is still visible.");
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ skip-if = buildapp == 'mulet'
|
||||||
[browser_projecteditor_confirm_unsaved.js]
|
[browser_projecteditor_confirm_unsaved.js]
|
||||||
[browser_projecteditor_contextmenu_01.js]
|
[browser_projecteditor_contextmenu_01.js]
|
||||||
[browser_projecteditor_contextmenu_02.js]
|
[browser_projecteditor_contextmenu_02.js]
|
||||||
|
skip-if = true # Bug 1173950
|
||||||
[browser_projecteditor_delete_file.js]
|
[browser_projecteditor_delete_file.js]
|
||||||
skip-if = e10s # Frequent failures in e10s - Bug 1020027
|
skip-if = e10s # Frequent failures in e10s - Bug 1020027
|
||||||
[browser_projecteditor_rename_file.js]
|
[browser_projecteditor_rename_file.js]
|
||||||
|
@ -23,6 +24,7 @@ skip-if = buildapp == 'mulet'
|
||||||
[browser_projecteditor_init.js]
|
[browser_projecteditor_init.js]
|
||||||
[browser_projecteditor_menubar_01.js]
|
[browser_projecteditor_menubar_01.js]
|
||||||
[browser_projecteditor_menubar_02.js]
|
[browser_projecteditor_menubar_02.js]
|
||||||
|
skip-if = true # Bug 1173950
|
||||||
[browser_projecteditor_new_file.js]
|
[browser_projecteditor_new_file.js]
|
||||||
[browser_projecteditor_stores.js]
|
[browser_projecteditor_stores.js]
|
||||||
[browser_projecteditor_tree_selection_01.js]
|
[browser_projecteditor_tree_selection_01.js]
|
||||||
|
|
|
@ -63,10 +63,10 @@ share_email_subject5={{clientShortname2}} — Join the conversation
|
||||||
share_email_subject_context={{clientShortname2}} conversation: {{title}}
|
share_email_subject_context={{clientShortname2}} conversation: {{title}}
|
||||||
## LOCALIZATION NOTE (share_email_body4): In this item, don't translate the
|
## LOCALIZATION NOTE (share_email_body4): In this item, don't translate the
|
||||||
## part between {{..}} and leave the \n\n part alone
|
## part between {{..}} and leave the \n\n part alone
|
||||||
share_email_body5=Hello!\n\nJoin me for a video conversation on {{clientShortname2}}.\n\nIt's the easiest way to connect by video with anyone anywhere. With {{clientSuperShortname}}, you don't have to download or install anything. Just click or paste this link into your {{brandShortname}}, Opera, or Chrome browser to join the conversation:\n\n{{callUrl}}\n\nIf you'd like to learn more about {{clientSuperShortname}} and how you can start your own free video conversations, visit {{learnMoreUrl}}\n\nTalk to you soon!
|
share_email_body5=Hello!\n\nJoin me for a video conversation on {{clientShortname2}}.\n\nIt's the easiest way to connect by video with anyone anywhere. With {{clientSuperShortname}}, you don't have to download or install anything. Just click or paste this link into your {{brandShortname}}, Opera or Chrome browser to join the conversation:\n\n{{callUrl}}\n\nIf you'd like to learn more about {{clientSuperShortname}} and how you can start your own free video conversations, visit {{learnMoreUrl}}\n\nTalk to you soon!
|
||||||
## LOCALIZATION NOTE (share_email_body_context): In this item, don't translate
|
## LOCALIZATION NOTE (share_email_body_context): In this item, don't translate
|
||||||
## the part between {{..}} and leave the \n\n part alone.
|
## the part between {{..}} and leave the \n\n part alone.
|
||||||
share_email_body_context=Hello!\n\nJoin me for a video conversation on {{clientShortname2}} about:\n{{title}}.\n\nIt's the easiest way to connect by video with anyone anywhere. With {{clientSuperShortname}}, you don't have to download or install anything. Just click or paste this link into your {{brandShortname}}, Opera, or Chrome browser to join the conversation:\n\n{{callUrl}}\n\nIf you'd like to learn more about {{clientSuperShortname}} and how you can start your own free video conversations, visit {{learnMoreUrl}}\n\nTalk to you soon!
|
share_email_body_context=Hello!\n\nJoin me for a video conversation on {{clientShortname2}} about:\n{{title}}.\n\nIt's the easiest way to connect by video with anyone anywhere. With {{clientSuperShortname}}, you don't have to download or install anything. Just click or paste this link into your {{brandShortname}}, Opera or Chrome browser to join the conversation:\n\n{{callUrl}}\n\nIf you'd like to learn more about {{clientSuperShortname}} and how you can start your own free video conversations, visit {{learnMoreUrl}}\n\nTalk to you soon!
|
||||||
## LOCALIZATION NOTE (share_tweeet): In this item, don't translate the part
|
## LOCALIZATION NOTE (share_tweeet): In this item, don't translate the part
|
||||||
## between {{..}}. Please keep the text below 117 characters to make sure it fits
|
## between {{..}}. Please keep the text below 117 characters to make sure it fits
|
||||||
## in a tweet.
|
## in a tweet.
|
||||||
|
@ -354,3 +354,7 @@ context_show_tooltip=Show Context
|
||||||
context_save_label2=Save
|
context_save_label2=Save
|
||||||
context_link_modified=This link was modified.
|
context_link_modified=This link was modified.
|
||||||
context_learn_more_link_label=Learn more.
|
context_learn_more_link_label=Learn more.
|
||||||
|
|
||||||
|
# Text chat strings
|
||||||
|
|
||||||
|
chat_textbox_placeholder=Type here…
|
||||||
|
|
|
@ -195,7 +195,6 @@ chatbox[dark=true] > .chat-titlebar > hbox > .chat-title {
|
||||||
|
|
||||||
.chatbar-innerbox {
|
.chatbar-innerbox {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
margin: -285px 0 0;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1075,7 +1075,7 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
|
||||||
list-style-image: url(chrome://browser/skin/undoCloseTab.png);
|
list-style-image: url(chrome://browser/skin/undoCloseTab.png);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-resolution: 1.25dppx) {
|
@media (min-resolution: 1.1dppx) {
|
||||||
#alltabs_undoCloseTab {
|
#alltabs_undoCloseTab {
|
||||||
list-style-image: url(chrome://browser/skin/undoCloseTab@2x.png);
|
list-style-image: url(chrome://browser/skin/undoCloseTab@2x.png);
|
||||||
}
|
}
|
||||||
|
@ -1508,16 +1508,19 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
||||||
padding: 0 3px;
|
padding: 0 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (-moz-os-version: windows-xp),
|
@media not all and (-moz-os-version: windows-vista),
|
||||||
not all and (-moz-windows-default-theme) {
|
not all and (-moz-windows-default-theme) {
|
||||||
richlistitem[type~="action"][actiontype="switchtab"][selected="true"] > .ac-url-box > .ac-action-icon {
|
@media not all and (-moz-os-version: windows-win7),
|
||||||
-moz-image-region: rect(11px, 16px, 22px, 0);
|
not all and (-moz-windows-default-theme) {
|
||||||
}
|
richlistitem[type~="action"][actiontype="switchtab"][selected="true"] > .ac-url-box > .ac-action-icon {
|
||||||
|
-moz-image-region: rect(11px, 16px, 22px, 0);
|
||||||
|
}
|
||||||
|
|
||||||
.ac-comment[selected="true"],
|
.ac-comment[selected="true"],
|
||||||
.ac-url-text[selected="true"],
|
.ac-url-text[selected="true"],
|
||||||
.ac-action-text[selected="true"] {
|
.ac-action-text[selected="true"] {
|
||||||
color: inherit !important;
|
color: inherit !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1892,7 +1895,7 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
||||||
|
|
||||||
%include ../shared/tabs.inc.css
|
%include ../shared/tabs.inc.css
|
||||||
|
|
||||||
@media (min-resolution: 1.25dppx) {
|
@media (min-resolution: 1.1dppx) {
|
||||||
/* image preloading hack from shared/tabs.inc.css */
|
/* image preloading hack from shared/tabs.inc.css */
|
||||||
#tabbrowser-tabs::before {
|
#tabbrowser-tabs::before {
|
||||||
background-image:
|
background-image:
|
||||||
|
@ -1934,8 +1937,17 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#TabsToolbar[brighttext] .tab-close-button:not(:hover):not([visuallyselected="true"]) {
|
/* Invert the unhovered close tab icons on bright-text tabs */
|
||||||
-moz-image-region: rect(0, 64px, 16px, 48px) !important;
|
@media not all and (min-resolution: 1.1dppx) {
|
||||||
|
#TabsToolbar[brighttext] .tab-close-button:not(:hover):not([visuallyselected="true"]) {
|
||||||
|
-moz-image-region: rect(0, 64px, 16px, 48px) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-resolution: 1.1dppx) {
|
||||||
|
#TabsToolbar[brighttext] .tab-close-button:not(:hover):not([visuallyselected="true"]) {
|
||||||
|
-moz-image-region: rect(0, 128px, 32px, 96px) !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* tabbrowser-tab focus ring */
|
/* tabbrowser-tab focus ring */
|
||||||
|
|
|
@ -1642,13 +1642,15 @@ BluetoothGattManager::GetCharacteristicNotification(
|
||||||
aCharId,
|
aCharId,
|
||||||
new DiscoverResultHandler(client));
|
new DiscoverResultHandler(client));
|
||||||
} else { // all characteristics of this service are discovered
|
} else { // all characteristics of this service are discovered
|
||||||
// Notify BluetoothGattService to create characteristics then proceed
|
// Notify BluetoothGatt to make BluetoothGattService create characteristics
|
||||||
nsString path;
|
// then proceed
|
||||||
GeneratePathFromGattId(aServiceId.mId, path);
|
nsTArray<BluetoothNamedValue> values;
|
||||||
|
BT_APPEND_NAMED_VALUE(values, "serviceId", aServiceId);
|
||||||
|
BT_APPEND_NAMED_VALUE(values, "characteristics", client->mCharacteristics);
|
||||||
|
|
||||||
bs->DistributeSignal(NS_LITERAL_STRING("CharacteristicsDiscovered"),
|
bs->DistributeSignal(NS_LITERAL_STRING("CharacteristicsDiscovered"),
|
||||||
path,
|
client->mAppUuid,
|
||||||
BluetoothValue(client->mCharacteristics));
|
BluetoothValue(values));
|
||||||
|
|
||||||
ProceedDiscoverProcess(client, aServiceId);
|
ProceedDiscoverProcess(client, aServiceId);
|
||||||
}
|
}
|
||||||
|
@ -1686,13 +1688,16 @@ BluetoothGattManager::GetDescriptorNotification(
|
||||||
aDescriptorId,
|
aDescriptorId,
|
||||||
new DiscoverResultHandler(client));
|
new DiscoverResultHandler(client));
|
||||||
} else { // all descriptors of this characteristic are discovered
|
} else { // all descriptors of this characteristic are discovered
|
||||||
// Notify BluetoothGattCharacteristic to create descriptors then proceed
|
// Notify BluetoothGatt to make BluetoothGattCharacteristic create
|
||||||
nsString path;
|
// descriptors then proceed
|
||||||
GeneratePathFromGattId(aCharId, path);
|
nsTArray<BluetoothNamedValue> values;
|
||||||
|
BT_APPEND_NAMED_VALUE(values, "serviceId", aServiceId);
|
||||||
|
BT_APPEND_NAMED_VALUE(values, "characteristicId", aCharId);
|
||||||
|
BT_APPEND_NAMED_VALUE(values, "descriptors", client->mDescriptors);
|
||||||
|
|
||||||
bs->DistributeSignal(NS_LITERAL_STRING("DescriptorsDiscovered"),
|
bs->DistributeSignal(NS_LITERAL_STRING("DescriptorsDiscovered"),
|
||||||
path,
|
client->mAppUuid,
|
||||||
BluetoothValue(client->mDescriptors));
|
BluetoothValue(values));
|
||||||
client->mDescriptors.Clear();
|
client->mDescriptors.Clear();
|
||||||
|
|
||||||
ProceedDiscoverProcess(client, aServiceId);
|
ProceedDiscoverProcess(client, aServiceId);
|
||||||
|
@ -1729,13 +1734,16 @@ BluetoothGattManager::GetIncludedServiceNotification(
|
||||||
aIncludedServId,
|
aIncludedServId,
|
||||||
new DiscoverResultHandler(client));
|
new DiscoverResultHandler(client));
|
||||||
} else { // all included services of this service are discovered
|
} else { // all included services of this service are discovered
|
||||||
// Notify BluetoothGattService to create included services
|
// Notify BluetoothGatt to make BluetoothGattService create included
|
||||||
nsString path;
|
// services
|
||||||
GeneratePathFromGattId(aServiceId.mId, path);
|
nsTArray<BluetoothNamedValue> values;
|
||||||
|
BT_APPEND_NAMED_VALUE(values, "serviceId", aServiceId);
|
||||||
|
BT_APPEND_NAMED_VALUE(values, "includedServices",
|
||||||
|
client->mIncludedServices);
|
||||||
|
|
||||||
bs->DistributeSignal(NS_LITERAL_STRING("IncludedServicesDiscovered"),
|
bs->DistributeSignal(NS_LITERAL_STRING("IncludedServicesDiscovered"),
|
||||||
path,
|
client->mAppUuid,
|
||||||
BluetoothValue(client->mIncludedServices));
|
BluetoothValue(values));
|
||||||
client->mIncludedServices.Clear();
|
client->mIncludedServices.Clear();
|
||||||
|
|
||||||
// Start to discover characteristics of this service
|
// Start to discover characteristics of this service
|
||||||
|
|
|
@ -281,6 +281,77 @@ BluetoothGatt::HandleServicesDiscovered(const BluetoothValue& aValue)
|
||||||
BluetoothGattBinding::ClearCachedServicesValue(this);
|
BluetoothGattBinding::ClearCachedServicesValue(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BluetoothGatt::HandleIncludedServicesDiscovered(const BluetoothValue& aValue)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfBluetoothNamedValue);
|
||||||
|
|
||||||
|
const InfallibleTArray<BluetoothNamedValue>& values =
|
||||||
|
aValue.get_ArrayOfBluetoothNamedValue();
|
||||||
|
MOZ_ASSERT(values.Length() == 2); // ServiceId, IncludedServices
|
||||||
|
MOZ_ASSERT(values[0].name().EqualsLiteral("serviceId"));
|
||||||
|
MOZ_ASSERT(values[0].value().type() ==
|
||||||
|
BluetoothValue::TBluetoothGattServiceId);
|
||||||
|
MOZ_ASSERT(values[1].name().EqualsLiteral("includedServices"));
|
||||||
|
MOZ_ASSERT(values[1].value().type() ==
|
||||||
|
BluetoothValue::TArrayOfBluetoothGattServiceId);
|
||||||
|
|
||||||
|
size_t index = mServices.IndexOf(
|
||||||
|
values[0].value().get_BluetoothGattServiceId());
|
||||||
|
NS_ENSURE_TRUE_VOID(index != mServices.NoIndex);
|
||||||
|
|
||||||
|
nsRefPtr<BluetoothGattService> service = mServices.ElementAt(index);
|
||||||
|
service->AssignIncludedServices(
|
||||||
|
values[1].value().get_ArrayOfBluetoothGattServiceId());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BluetoothGatt::HandleCharacteristicsDiscovered(const BluetoothValue& aValue)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfBluetoothNamedValue);
|
||||||
|
|
||||||
|
const InfallibleTArray<BluetoothNamedValue>& values =
|
||||||
|
aValue.get_ArrayOfBluetoothNamedValue();
|
||||||
|
MOZ_ASSERT(values.Length() == 2); // ServiceId, Characteristics
|
||||||
|
MOZ_ASSERT(values[0].name().EqualsLiteral("serviceId"));
|
||||||
|
MOZ_ASSERT(values[0].value().type() == BluetoothValue::TBluetoothGattServiceId);
|
||||||
|
MOZ_ASSERT(values[1].name().EqualsLiteral("characteristics"));
|
||||||
|
MOZ_ASSERT(values[1].value().type() ==
|
||||||
|
BluetoothValue::TArrayOfBluetoothGattCharAttribute);
|
||||||
|
|
||||||
|
size_t index = mServices.IndexOf(
|
||||||
|
values[0].value().get_BluetoothGattServiceId());
|
||||||
|
NS_ENSURE_TRUE_VOID(index != mServices.NoIndex);
|
||||||
|
|
||||||
|
nsRefPtr<BluetoothGattService> service = mServices.ElementAt(index);
|
||||||
|
service->AssignCharacteristics(
|
||||||
|
values[1].value().get_ArrayOfBluetoothGattCharAttribute());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BluetoothGatt::HandleDescriptorsDiscovered(const BluetoothValue& aValue)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfBluetoothNamedValue);
|
||||||
|
|
||||||
|
const InfallibleTArray<BluetoothNamedValue>& values =
|
||||||
|
aValue.get_ArrayOfBluetoothNamedValue();
|
||||||
|
MOZ_ASSERT(values.Length() == 3); // ServiceId, CharacteristicId, Descriptors
|
||||||
|
MOZ_ASSERT(values[0].name().EqualsLiteral("serviceId"));
|
||||||
|
MOZ_ASSERT(values[0].value().type() == BluetoothValue::TBluetoothGattServiceId);
|
||||||
|
MOZ_ASSERT(values[1].name().EqualsLiteral("characteristicId"));
|
||||||
|
MOZ_ASSERT(values[1].value().type() == BluetoothValue::TBluetoothGattId);
|
||||||
|
MOZ_ASSERT(values[2].name().EqualsLiteral("descriptors"));
|
||||||
|
MOZ_ASSERT(values[2].value().type() == BluetoothValue::TArrayOfBluetoothGattId);
|
||||||
|
|
||||||
|
size_t index = mServices.IndexOf(
|
||||||
|
values[0].value().get_BluetoothGattServiceId());
|
||||||
|
NS_ENSURE_TRUE_VOID(index != mServices.NoIndex);
|
||||||
|
|
||||||
|
nsRefPtr<BluetoothGattService> service = mServices.ElementAt(index);
|
||||||
|
service->AssignDescriptors(values[1].value().get_BluetoothGattId(),
|
||||||
|
values[2].value().get_ArrayOfBluetoothGattId());
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothGatt::HandleCharacteristicChanged(const BluetoothValue& aValue)
|
BluetoothGatt::HandleCharacteristicChanged(const BluetoothValue& aValue)
|
||||||
{
|
{
|
||||||
|
@ -348,6 +419,12 @@ BluetoothGatt::Notify(const BluetoothSignal& aData)
|
||||||
}
|
}
|
||||||
|
|
||||||
mDiscoveringServices = false;
|
mDiscoveringServices = false;
|
||||||
|
} else if (aData.name().EqualsLiteral("IncludedServicesDiscovered")) {
|
||||||
|
HandleIncludedServicesDiscovered(v);
|
||||||
|
} else if (aData.name().EqualsLiteral("CharacteristicsDiscovered")) {
|
||||||
|
HandleCharacteristicsDiscovered(v);
|
||||||
|
} else if (aData.name().EqualsLiteral("DescriptorsDiscovered")) {
|
||||||
|
HandleDescriptorsDiscovered(v);
|
||||||
} else if (aData.name().EqualsLiteral(GATT_CHARACTERISTIC_CHANGED_ID)) {
|
} else if (aData.name().EqualsLiteral(GATT_CHARACTERISTIC_CHANGED_ID)) {
|
||||||
HandleCharacteristicChanged(v);
|
HandleCharacteristicChanged(v);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -96,6 +96,50 @@ private:
|
||||||
*/
|
*/
|
||||||
void HandleServicesDiscovered(const BluetoothValue& aValue);
|
void HandleServicesDiscovered(const BluetoothValue& aValue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add newly discovered GATT included services into mIncludedServices of
|
||||||
|
* BluetoothGattService and update the cache value of mIncludedServices.
|
||||||
|
*
|
||||||
|
* @param aValue [in] BluetoothValue which contains an array of
|
||||||
|
* BluetoothNamedValue. There are exact two elements in
|
||||||
|
* the array. The first element uses 'serviceId' as the
|
||||||
|
* name and uses BluetoothGattServiceId as the value. The
|
||||||
|
* second element uses 'includedServices' as the name and
|
||||||
|
* uses an array of BluetoothGattServiceId of all
|
||||||
|
* discovered included services as the value.
|
||||||
|
*/
|
||||||
|
void HandleIncludedServicesDiscovered(const BluetoothValue& aValue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add newly discovered GATT characteristics into mCharacteristics of
|
||||||
|
* BluetoothGattService and update the cache value of mCharacteristics.
|
||||||
|
*
|
||||||
|
* @param aValue [in] BluetoothValue which contains an array of
|
||||||
|
* BluetoothNamedValue. There are exact two elements in
|
||||||
|
* the array. The first element uses 'serviceId' as the
|
||||||
|
* name and uses BluetoothGattServiceId as the value. The
|
||||||
|
* second element uses 'characteristics' as the name and
|
||||||
|
* uses an array of BluetoothGattCharAttribute of all
|
||||||
|
* discovered characteristics as the value.
|
||||||
|
*/
|
||||||
|
void HandleCharacteristicsDiscovered(const BluetoothValue& aValue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add newly discovered GATT descriptors into mDescriptors of
|
||||||
|
* BluetoothGattCharacteristic and update the cache value of mDescriptors.
|
||||||
|
*
|
||||||
|
* @param aValue [in] BluetoothValue which contains an array of
|
||||||
|
* BluetoothNamedValue. There are exact three elements in
|
||||||
|
* the array. The first element uses 'serviceId' as the
|
||||||
|
* name and uses BluetoothGattServiceId as the value. The
|
||||||
|
* second element uses 'characteristicId' as the name and
|
||||||
|
* uses BluetoothGattId as the value. The third element
|
||||||
|
* uses 'descriptors' as the name and uses an array of
|
||||||
|
* BluetoothGattId of all discovered descriptors as the
|
||||||
|
* value.
|
||||||
|
*/
|
||||||
|
void HandleDescriptorsDiscovered(const BluetoothValue& aValue);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The value of a GATT characteristic has changed. In the mean time, the
|
* The value of a GATT characteristic has changed. In the mean time, the
|
||||||
* cached value of this GATT characteristic has already been updated. An
|
* cached value of this GATT characteristic has already been updated. An
|
||||||
|
|
|
@ -142,18 +142,13 @@ BluetoothGattCharacteristic::StopNotifications(ErrorResult& aRv)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothGattCharacteristic::HandleDescriptorsDiscovered(
|
BluetoothGattCharacteristic::AssignDescriptors(
|
||||||
const BluetoothValue& aValue)
|
const nsTArray<BluetoothGattId>& aDescriptorIds)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfBluetoothGattId);
|
|
||||||
|
|
||||||
const InfallibleTArray<BluetoothGattId>& descriptorIds =
|
|
||||||
aValue.get_ArrayOfBluetoothGattId();
|
|
||||||
|
|
||||||
mDescriptors.Clear();
|
mDescriptors.Clear();
|
||||||
for (uint32_t i = 0; i < descriptorIds.Length(); i++) {
|
for (uint32_t i = 0; i < aDescriptorIds.Length(); i++) {
|
||||||
mDescriptors.AppendElement(new BluetoothGattDescriptor(
|
mDescriptors.AppendElement(new BluetoothGattDescriptor(
|
||||||
GetParentObject(), this, descriptorIds[i]));
|
GetParentObject(), this, aDescriptorIds[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
BluetoothGattCharacteristicBinding::ClearCachedDescriptorsValue(this);
|
BluetoothGattCharacteristicBinding::ClearCachedDescriptorsValue(this);
|
||||||
|
@ -175,9 +170,7 @@ BluetoothGattCharacteristic::Notify(const BluetoothSignal& aData)
|
||||||
NS_ENSURE_TRUE_VOID(mSignalRegistered);
|
NS_ENSURE_TRUE_VOID(mSignalRegistered);
|
||||||
|
|
||||||
BluetoothValue v = aData.value();
|
BluetoothValue v = aData.value();
|
||||||
if (aData.name().EqualsLiteral("DescriptorsDiscovered")) {
|
if (aData.name().EqualsLiteral("CharacteristicValueUpdated")) {
|
||||||
HandleDescriptorsDiscovered(v);
|
|
||||||
} else if (aData.name().EqualsLiteral("CharacteristicValueUpdated")) {
|
|
||||||
HandleCharacteristicValueUpdated(v);
|
HandleCharacteristicValueUpdated(v);
|
||||||
} else {
|
} else {
|
||||||
BT_WARNING("Not handling GATT Characteristic signal: %s",
|
BT_WARNING("Not handling GATT Characteristic signal: %s",
|
||||||
|
|
|
@ -32,6 +32,7 @@ class BluetoothGattCharacteristic final : public nsISupports
|
||||||
, public nsWrapperCache
|
, public nsWrapperCache
|
||||||
, public BluetoothSignalObserver
|
, public BluetoothSignalObserver
|
||||||
{
|
{
|
||||||
|
friend class BluetoothGattService;
|
||||||
public:
|
public:
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(BluetoothGattCharacteristic)
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(BluetoothGattCharacteristic)
|
||||||
|
@ -106,10 +107,10 @@ private:
|
||||||
* Add newly discovered GATT descriptors into mDescriptors and update the
|
* Add newly discovered GATT descriptors into mDescriptors and update the
|
||||||
* cache value of mDescriptors.
|
* cache value of mDescriptors.
|
||||||
*
|
*
|
||||||
* @param aValue [in] BluetoothValue which contains an array of
|
* @param aDescriptorIds [in] An array of BluetoothGattId for each descriptor
|
||||||
* BluetoothGattId of all discovered descriptors.
|
* that belongs to this characteristic.
|
||||||
*/
|
*/
|
||||||
void HandleDescriptorsDiscovered(const BluetoothValue& aValue);
|
void AssignDescriptors(const nsTArray<BluetoothGattId>& aDescriptorIds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the value of this characteristic.
|
* Update the value of this characteristic.
|
||||||
|
|
|
@ -17,33 +17,10 @@ using namespace mozilla::dom;
|
||||||
|
|
||||||
USING_BLUETOOTH_NAMESPACE
|
USING_BLUETOOTH_NAMESPACE
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothGattService)
|
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(BluetoothGattService,
|
||||||
|
mOwner,
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BluetoothGattService)
|
mIncludedServices,
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
|
mCharacteristics)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIncludedServices)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCharacteristics)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unregister the bluetooth signal handler after unlinked.
|
|
||||||
*
|
|
||||||
* This is needed to avoid ending up with exposing a deleted object to JS or
|
|
||||||
* accessing deleted objects while receiving signals from parent process
|
|
||||||
* after unlinked. Please see Bug 1138267 for detail informations.
|
|
||||||
*/
|
|
||||||
nsString path;
|
|
||||||
GeneratePathFromGattId(tmp->mServiceId.mId, path);
|
|
||||||
UnregisterBluetoothSignalHandler(path, tmp);
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(BluetoothGattService)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIncludedServices)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCharacteristics)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(BluetoothGattService)
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(BluetoothGattService)
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(BluetoothGattService)
|
||||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(BluetoothGattService)
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(BluetoothGattService)
|
||||||
|
@ -63,72 +40,49 @@ BluetoothGattService::BluetoothGattService(
|
||||||
MOZ_ASSERT(!mAppUuid.IsEmpty());
|
MOZ_ASSERT(!mAppUuid.IsEmpty());
|
||||||
|
|
||||||
UuidToString(mServiceId.mId.mUuid, mUuidStr);
|
UuidToString(mServiceId.mId.mUuid, mUuidStr);
|
||||||
|
|
||||||
// Generate bluetooth signal path of this service to applications
|
|
||||||
nsString path;
|
|
||||||
GeneratePathFromGattId(mServiceId.mId, path);
|
|
||||||
RegisterBluetoothSignalHandler(path, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BluetoothGattService::~BluetoothGattService()
|
BluetoothGattService::~BluetoothGattService()
|
||||||
{
|
{
|
||||||
nsString path;
|
|
||||||
GeneratePathFromGattId(mServiceId.mId, path);
|
|
||||||
UnregisterBluetoothSignalHandler(path, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothGattService::HandleIncludedServicesDiscovered(
|
BluetoothGattService::AssignIncludedServices(
|
||||||
const BluetoothValue& aValue)
|
const nsTArray<BluetoothGattServiceId>& aServiceIds)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfBluetoothGattServiceId);
|
|
||||||
|
|
||||||
const InfallibleTArray<BluetoothGattServiceId>& includedServIds =
|
|
||||||
aValue.get_ArrayOfBluetoothGattServiceId();
|
|
||||||
|
|
||||||
mIncludedServices.Clear();
|
mIncludedServices.Clear();
|
||||||
for (uint32_t i = 0; i < includedServIds.Length(); i++) {
|
for (uint32_t i = 0; i < aServiceIds.Length(); i++) {
|
||||||
mIncludedServices.AppendElement(new BluetoothGattService(
|
mIncludedServices.AppendElement(new BluetoothGattService(
|
||||||
GetParentObject(), mAppUuid, includedServIds[i]));
|
GetParentObject(), mAppUuid, aServiceIds[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
BluetoothGattServiceBinding::ClearCachedIncludedServicesValue(this);
|
BluetoothGattServiceBinding::ClearCachedIncludedServicesValue(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothGattService::HandleCharacteristicsDiscovered(
|
BluetoothGattService::AssignCharacteristics(
|
||||||
const BluetoothValue& aValue)
|
const nsTArray<BluetoothGattCharAttribute>& aCharacteristics)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aValue.type() ==
|
|
||||||
BluetoothValue::TArrayOfBluetoothGattCharAttribute);
|
|
||||||
|
|
||||||
const InfallibleTArray<BluetoothGattCharAttribute>& characteristics =
|
|
||||||
aValue.get_ArrayOfBluetoothGattCharAttribute();
|
|
||||||
|
|
||||||
mCharacteristics.Clear();
|
mCharacteristics.Clear();
|
||||||
for (uint32_t i = 0; i < characteristics.Length(); i++) {
|
for (uint32_t i = 0; i < aCharacteristics.Length(); i++) {
|
||||||
mCharacteristics.AppendElement(new BluetoothGattCharacteristic(
|
mCharacteristics.AppendElement(new BluetoothGattCharacteristic(
|
||||||
GetParentObject(), this, characteristics[i]));
|
GetParentObject(), this, aCharacteristics[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
BluetoothGattServiceBinding::ClearCachedCharacteristicsValue(this);
|
BluetoothGattServiceBinding::ClearCachedCharacteristicsValue(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothGattService::Notify(const BluetoothSignal& aData)
|
BluetoothGattService::AssignDescriptors(
|
||||||
|
const BluetoothGattId& aCharacteristicId,
|
||||||
|
const nsTArray<BluetoothGattId>& aDescriptorIds)
|
||||||
{
|
{
|
||||||
BT_LOGD("[D] %s", NS_ConvertUTF16toUTF8(aData.name()).get());
|
size_t index = mCharacteristics.IndexOf(aCharacteristicId);
|
||||||
NS_ENSURE_TRUE_VOID(mSignalRegistered);
|
NS_ENSURE_TRUE_VOID(index != mCharacteristics.NoIndex);
|
||||||
|
|
||||||
BluetoothValue v = aData.value();
|
nsRefPtr<BluetoothGattCharacteristic> characteristic =
|
||||||
if (aData.name().EqualsLiteral("IncludedServicesDiscovered")) {
|
mCharacteristics.ElementAt(index);
|
||||||
HandleIncludedServicesDiscovered(v);
|
characteristic->AssignDescriptors(aDescriptorIds);
|
||||||
} else if (aData.name().EqualsLiteral("CharacteristicsDiscovered")) {
|
|
||||||
HandleCharacteristicsDiscovered(v);
|
|
||||||
} else {
|
|
||||||
BT_WARNING("Not handling GATT Service signal: %s",
|
|
||||||
NS_ConvertUTF16toUTF8(aData.name()).get());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JSObject*
|
JSObject*
|
||||||
|
|
|
@ -17,13 +17,14 @@
|
||||||
|
|
||||||
BEGIN_BLUETOOTH_NAMESPACE
|
BEGIN_BLUETOOTH_NAMESPACE
|
||||||
|
|
||||||
|
class BluetoothGatt;
|
||||||
class BluetoothSignal;
|
class BluetoothSignal;
|
||||||
class BluetoothValue;
|
class BluetoothValue;
|
||||||
|
|
||||||
class BluetoothGattService final : public nsISupports
|
class BluetoothGattService final : public nsISupports
|
||||||
, public nsWrapperCache
|
, public nsWrapperCache
|
||||||
, public BluetoothSignalObserver
|
|
||||||
{
|
{
|
||||||
|
friend class BluetoothGatt;
|
||||||
public:
|
public:
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(BluetoothGattService)
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(BluetoothGattService)
|
||||||
|
@ -71,8 +72,6 @@ public:
|
||||||
return mServiceId;
|
return mServiceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Notify(const BluetoothSignal& aData); // BluetoothSignalObserver
|
|
||||||
|
|
||||||
nsPIDOMWindow* GetParentObject() const
|
nsPIDOMWindow* GetParentObject() const
|
||||||
{
|
{
|
||||||
return mOwner;
|
return mOwner;
|
||||||
|
@ -92,20 +91,36 @@ private:
|
||||||
* Add newly discovered GATT included services into mIncludedServices and
|
* Add newly discovered GATT included services into mIncludedServices and
|
||||||
* update the cache value of mIncludedServices.
|
* update the cache value of mIncludedServices.
|
||||||
*
|
*
|
||||||
* @param aValue [in] BluetoothValue which contains an array of
|
* @param aServiceIds [in] An array of BluetoothGattServiceId for each
|
||||||
* BluetoothGattServiceId of all discovered included
|
* included service that belongs to this service.
|
||||||
* services.
|
|
||||||
*/
|
*/
|
||||||
void HandleIncludedServicesDiscovered(const BluetoothValue& aValue);
|
void AssignIncludedServices(
|
||||||
|
const nsTArray<BluetoothGattServiceId>& aServiceIds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add newly discovered GATT characteristics into mCharacteristics and
|
* Add newly discovered GATT characteristics into mCharacteristics and
|
||||||
* update the cache value of mCharacteristics.
|
* update the cache value of mCharacteristics.
|
||||||
*
|
*
|
||||||
* @param aValue [in] BluetoothValue which contains an array of
|
* @param aCharacteristics [in] An array of BluetoothGattCharAttribute for
|
||||||
* BluetoothGattId of all discovered characteristics.
|
* each characteristic that belongs to this
|
||||||
|
* service.
|
||||||
*/
|
*/
|
||||||
void HandleCharacteristicsDiscovered(const BluetoothValue& aValue);
|
void AssignCharacteristics(
|
||||||
|
const nsTArray<BluetoothGattCharAttribute>& aCharacteristics);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add newly discovered GATT descriptors into mDescriptors of
|
||||||
|
* BluetoothGattCharacteristic and update the cache value of mDescriptors.
|
||||||
|
*
|
||||||
|
* @param aCharacteristicId [in] BluetoothGattId of a characteristic that
|
||||||
|
* belongs to this service.
|
||||||
|
* @param aDescriptorIds [in] An array of BluetoothGattId for each descriptor
|
||||||
|
* that belongs to the characteristic referred by
|
||||||
|
* aCharacteristicId.
|
||||||
|
*/
|
||||||
|
void AssignDescriptors(
|
||||||
|
const BluetoothGattId& aCharacteristicId,
|
||||||
|
const nsTArray<BluetoothGattId>& aDescriptorIds);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Variables
|
* Variables
|
||||||
|
|
|
@ -94,6 +94,7 @@ this.Keyboard = {
|
||||||
Services.obs.addObserver(this, 'inprocess-browser-shown', false);
|
Services.obs.addObserver(this, 'inprocess-browser-shown', false);
|
||||||
Services.obs.addObserver(this, 'remote-browser-shown', false);
|
Services.obs.addObserver(this, 'remote-browser-shown', false);
|
||||||
Services.obs.addObserver(this, 'oop-frameloader-crashed', false);
|
Services.obs.addObserver(this, 'oop-frameloader-crashed', false);
|
||||||
|
Services.obs.addObserver(this, 'message-manager-close', false);
|
||||||
|
|
||||||
for (let name of this._messageNames) {
|
for (let name of this._messageNames) {
|
||||||
ppmm.addMessageListener('Keyboard:' + name, this);
|
ppmm.addMessageListener('Keyboard:' + name, this);
|
||||||
|
@ -107,10 +108,18 @@ this.Keyboard = {
|
||||||
},
|
},
|
||||||
|
|
||||||
observe: function keyboardObserve(subject, topic, data) {
|
observe: function keyboardObserve(subject, topic, data) {
|
||||||
let frameLoader = subject.QueryInterface(Ci.nsIFrameLoader);
|
let frameLoader = null;
|
||||||
let mm = frameLoader.messageManager;
|
let mm = null;
|
||||||
|
|
||||||
if (topic == 'oop-frameloader-crashed') {
|
if (topic == 'message-manager-close') {
|
||||||
|
mm = subject;
|
||||||
|
} else {
|
||||||
|
frameLoader = subject.QueryInterface(Ci.nsIFrameLoader);
|
||||||
|
mm = frameLoader.messageManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (topic == 'oop-frameloader-crashed' ||
|
||||||
|
topic == 'message-manager-close') {
|
||||||
if (this.formMM == mm) {
|
if (this.formMM == mm) {
|
||||||
// The application has been closed unexpectingly. Let's tell the
|
// The application has been closed unexpectingly. Let's tell the
|
||||||
// keyboard app that the focus has been lost.
|
// keyboard app that the focus has been lost.
|
||||||
|
@ -290,6 +299,8 @@ this.Keyboard = {
|
||||||
if (mm !== this.formMM) {
|
if (mm !== this.formMM) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.formMM = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,8 @@ const Cu = Components.utils;
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "AddonManager", "resource://gre/modules/AddonManager.jsm");
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
// Web Install Prompt service
|
// Web Install Prompt service
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
@ -27,7 +29,15 @@ WebInstallPrompt.prototype = {
|
||||||
let button = bundle.GetStringFromName("addonsConfirmInstall.install");
|
let button = bundle.GetStringFromName("addonsConfirmInstall.install");
|
||||||
|
|
||||||
aInstalls.forEach(function(install) {
|
aInstalls.forEach(function(install) {
|
||||||
let result = (prompt.confirmEx(aBrowser.contentWindow, title, install.name, flags, button, null, null, null, {value: false}) == 0);
|
let message;
|
||||||
|
if (install.addon.signedState <= AddonManager.SIGNEDSTATE_MISSING) {
|
||||||
|
title = bundle.GetStringFromName("addonsConfirmInstallUnsigned.title")
|
||||||
|
message = bundle.GetStringFromName("addonsConfirmInstallUnsigned.message") + "\n\n" + install.name;
|
||||||
|
} else {
|
||||||
|
message = install.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = (prompt.confirmEx(aBrowser.contentWindow, title, message, flags, button, null, null, null, {value: false}) == 0);
|
||||||
if (result)
|
if (result)
|
||||||
install.install();
|
install.install();
|
||||||
else
|
else
|
||||||
|
|
|
@ -5,6 +5,9 @@
|
||||||
addonsConfirmInstall.title=Installing Add-on
|
addonsConfirmInstall.title=Installing Add-on
|
||||||
addonsConfirmInstall.install=Install
|
addonsConfirmInstall.install=Install
|
||||||
|
|
||||||
|
addonsConfirmInstallUnsigned.title=Unverified add-on
|
||||||
|
addonsConfirmInstallUnsigned.message=This site would like to install an unverified add-on. Proceed at your own risk.
|
||||||
|
|
||||||
# Alerts
|
# Alerts
|
||||||
alertAddonsDownloading=Downloading add-on
|
alertAddonsDownloading=Downloading add-on
|
||||||
alertAddonsInstalledNoRestart.message=Installation complete
|
alertAddonsInstalledNoRestart.message=Installation complete
|
||||||
|
|
|
@ -13,7 +13,7 @@ task:
|
||||||
phone:
|
phone:
|
||||||
type: 'flame'
|
type: 'flame'
|
||||||
memory: '319'
|
memory: '319'
|
||||||
sims: '1'
|
sims: '2'
|
||||||
build: '{{{img_url}}}'
|
build: '{{{img_url}}}'
|
||||||
features:
|
features:
|
||||||
testdroidProxy: true
|
testdroidProxy: true
|
||||||
|
|
|
@ -15,7 +15,18 @@ loader.lazyImporter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm");
|
||||||
loader.lazyServiceGetter(this, "gActivityDistributor",
|
loader.lazyServiceGetter(this, "gActivityDistributor",
|
||||||
"@mozilla.org/network/http-activity-distributor;1",
|
"@mozilla.org/network/http-activity-distributor;1",
|
||||||
"nsIHttpActivityDistributor");
|
"nsIHttpActivityDistributor");
|
||||||
loader.lazyImporter(this, "gDevTools", "resource:///modules/devtools/gDevTools.jsm");
|
let _testing = false;
|
||||||
|
Object.defineProperty(this, "gTesting", {
|
||||||
|
get: function() {
|
||||||
|
try {
|
||||||
|
const { gDevTools } = require("resource:///modules/devtools/gDevTools.jsm");
|
||||||
|
_testing = gDevTools.testing;
|
||||||
|
} catch (e) {
|
||||||
|
// gDevTools is not present on B2G.
|
||||||
|
}
|
||||||
|
return _testing;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Network logging
|
// Network logging
|
||||||
|
@ -747,7 +758,7 @@ NetworkMonitor.prototype = {
|
||||||
// TODO: one particular test (browser_styleeditor_fetch-from-cache.js) needs
|
// TODO: one particular test (browser_styleeditor_fetch-from-cache.js) needs
|
||||||
// the gDevTools.testing check. We will move to a better way to serve its
|
// the gDevTools.testing check. We will move to a better way to serve its
|
||||||
// needs in bug 1167188, where this check should be removed.
|
// needs in bug 1167188, where this check should be removed.
|
||||||
if (!gDevTools.testing && aChannel.loadInfo &&
|
if (!gTesting && aChannel.loadInfo &&
|
||||||
aChannel.loadInfo.loadingDocument === null &&
|
aChannel.loadInfo.loadingDocument === null &&
|
||||||
aChannel.loadInfo.loadingPrincipal === Services.scriptSecurityManager.getSystemPrincipal()) {
|
aChannel.loadInfo.loadingPrincipal === Services.scriptSecurityManager.getSystemPrincipal()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -768,12 +779,6 @@ NetworkMonitor.prototype = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aChannel.loadInfo) {
|
|
||||||
if (aChannel.loadInfo.contentPolicyType == Ci.nsIContentPolicy.TYPE_BEACON) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.topFrame) {
|
if (this.topFrame) {
|
||||||
let topFrame = NetworkHelper.getTopFrameForRequest(aChannel);
|
let topFrame = NetworkHelper.getTopFrameForRequest(aChannel);
|
||||||
if (topFrame && topFrame === this.topFrame) {
|
if (topFrame && topFrame === this.topFrame) {
|
||||||
|
@ -788,6 +793,24 @@ NetworkMonitor.prototype = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The following check is necessary because beacon channels don't come
|
||||||
|
// associated with a load group. Bug 1160837 will hopefully introduce a
|
||||||
|
// platform fix that will render the following code entirely useless.
|
||||||
|
if (aChannel.loadInfo &&
|
||||||
|
aChannel.loadInfo.contentPolicyType == Ci.nsIContentPolicy.TYPE_BEACON) {
|
||||||
|
let nonE10sMatch = this.window &&
|
||||||
|
aChannel.loadInfo.loadingDocument === this.window.document;
|
||||||
|
let e10sMatch = this.topFrame &&
|
||||||
|
this.topFrame.contentPrincipal &&
|
||||||
|
this.topFrame.contentPrincipal.equals(aChannel.loadInfo.loadingPrincipal) &&
|
||||||
|
this.topFrame.contentPrincipal.URI.spec == aChannel.referrer.spec;
|
||||||
|
let b2gMatch = this.appId &&
|
||||||
|
aChannel.loadInfo.loadingPrincipal.appId === this.appId;
|
||||||
|
if (nonE10sMatch || e10sMatch || b2gMatch) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -106,28 +106,23 @@ treechildren.autocomplete-treebody::-moz-tree-cell-text(selected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
%ifdef XP_WIN
|
%ifdef XP_WIN
|
||||||
@media not all and (-moz-os-version: windows-xp) {
|
@media (-moz-os-version: windows-vista) and (-moz-windows-default-theme),
|
||||||
@media (-moz-windows-default-theme) {
|
(-moz-os-version: windows-win7) and (-moz-windows-default-theme) {
|
||||||
/*
|
.autocomplete-richlistitem[selected="true"] {
|
||||||
-moz-appearance: menuitem is almost right, but the hover effect is not
|
color: inherit;
|
||||||
transparent and is lighter than desired.
|
background-color: transparent;
|
||||||
*/
|
/* four gradients for the bevel highlights on each edge, one for blue background */
|
||||||
.autocomplete-richlistitem[selected="true"] {
|
background-image:
|
||||||
color: inherit;
|
linear-gradient(to bottom, rgba(255,255,255,0.9) 3px, transparent 3px),
|
||||||
background-color: transparent;
|
linear-gradient(to right, rgba(255,255,255,0.5) 3px, transparent 3px),
|
||||||
/* four gradients for the bevel highlights on each edge, one for blue background */
|
linear-gradient(to left, rgba(255,255,255,0.5) 3px, transparent 3px),
|
||||||
background-image:
|
linear-gradient(to top, rgba(255,255,255,0.4) 3px, transparent 3px),
|
||||||
linear-gradient(to bottom, rgba(255,255,255,0.9) 3px, transparent 3px),
|
linear-gradient(to bottom, rgba(163,196,247,0.3), rgba(122,180,246,0.3));
|
||||||
linear-gradient(to right, rgba(255,255,255,0.5) 3px, transparent 3px),
|
background-clip: content-box;
|
||||||
linear-gradient(to left, rgba(255,255,255,0.5) 3px, transparent 3px),
|
border-radius: 6px;
|
||||||
linear-gradient(to top, rgba(255,255,255,0.4) 3px, transparent 3px),
|
outline: 1px solid rgb(124,163,206);
|
||||||
linear-gradient(to bottom, rgba(163,196,247,0.3), rgba(122,180,246,0.3));
|
-moz-outline-radius: 3px;
|
||||||
background-clip: content-box;
|
outline-offset: -2px;
|
||||||
border-radius: 6px;
|
|
||||||
outline: 1px solid rgb(124,163,206);
|
|
||||||
-moz-outline-radius: 3px;
|
|
||||||
outline-offset: -2px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
%endif
|
%endif
|
||||||
|
|
Загрузка…
Ссылка в новой задаче